215 lines
5.8 KiB
D
215 lines
5.8 KiB
D
/+
|
|
+ video/laz_engine.d
|
|
+
|
|
+ Copyright: 2007 Gerald Stocker
|
|
+
|
|
+ This file is part of Twoapple.
|
|
+
|
|
+ Twoapple is free software; you can redistribute it and/or modify
|
|
+ it under the terms of the GNU General Public License as published by
|
|
+ the Free Software Foundation; either version 2 of the License, or
|
|
+ (at your option) any later version.
|
|
+
|
|
+ Twoapple is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ GNU General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU General Public License
|
|
+ along with Twoapple; if not, write to the Free Software
|
|
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+/
|
|
|
|
import video.base;
|
|
|
|
private:
|
|
|
|
template Tuple(E...) { alias E Tuple; }
|
|
|
|
enum Color
|
|
{
|
|
Black,
|
|
Red,
|
|
Brown,
|
|
Orange,
|
|
DarkGreen,
|
|
DarkGray,
|
|
Green,
|
|
Yellow,
|
|
DarkBlue,
|
|
Purple,
|
|
LightGray,
|
|
Pink,
|
|
MediumBlue,
|
|
LightBlue,
|
|
Aqua,
|
|
White
|
|
}
|
|
|
|
public:
|
|
|
|
class LazEngine : Screen
|
|
{
|
|
ushort data_[562 * 192];
|
|
|
|
ushort[1][3] monoPalettes = [
|
|
[0x03E0], // green
|
|
[0xFAA3], // amber
|
|
[0xFFFF] // white
|
|
];
|
|
ushort* monoPalette;
|
|
|
|
mixin("static final ushort[32][8] colorPalettes = "
|
|
~ import("palette_5_6_5"));
|
|
ushort* colorPalette;
|
|
|
|
mixin("static final uint[32][4][3] schemes = "
|
|
~ import("laz_scheme"));
|
|
uint[32]* scheme;
|
|
|
|
mixin("static final uint[32][2][2] sharp_table = "
|
|
~ import("laz_sharp"));
|
|
|
|
this()
|
|
{
|
|
width = 562;
|
|
height = 192;
|
|
data = data_.ptr;
|
|
monoPalette = monoPalettes[0].ptr;
|
|
colorPalette = colorPalettes[0].ptr;
|
|
scheme = schemes[0].ptr;
|
|
isColor = true;
|
|
}
|
|
|
|
void monochrome(ubyte* bitmap, int scanLine, int scanStart, int scanEnd,
|
|
ushort color_5_6_5)
|
|
{
|
|
uint dataPtr = (scanLine * width) + scanStart * 14;
|
|
uint bitmapPtr = 0;
|
|
uint bits, bitPos;
|
|
for (int scan = scanStart; scan <= scanEnd; ++scan)
|
|
{
|
|
foreach(mapByte; Tuple!(0, 1))
|
|
{
|
|
bits = bitmap[bitmapPtr++];
|
|
bitPos = 0b01000000;
|
|
foreach (mapBit; Tuple!(0, 1, 2, 3, 4, 5, 6))
|
|
{
|
|
if (bits & bitPos)
|
|
data[dataPtr++] = color_5_6_5;
|
|
else
|
|
data[dataPtr++] = 0;
|
|
bitPos >>= 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void draw(bool col80, bool colorBurst, ubyte* bitmap, int scanLine,
|
|
int scanStart, int scanEnd)
|
|
{
|
|
if (!isColor || !colorBurst)
|
|
{
|
|
monochrome(((scanStart == 0) ? bitmap : bitmap + 1),
|
|
scanLine, scanStart, scanEnd,
|
|
(isColor ? colorPalette[15] : monoPalette[0]));
|
|
}
|
|
else
|
|
{
|
|
polychrome(col80, bitmap, scanLine, scanStart, scanEnd);
|
|
}
|
|
}
|
|
|
|
void polychrome(bool col80, ubyte* bitmap, int scanLine, int scanStart,
|
|
int scanEnd)
|
|
{
|
|
uint colStart = scanStart * 14;
|
|
uint colEnd = scanEnd * 14 + 13;
|
|
uint colCorrection = (col80 ? 0 : 3);
|
|
bool finishCols;
|
|
|
|
uint bitmapPtr = 0;
|
|
uint dataPtr = (scanLine * width) + colStart;
|
|
|
|
uint colorIndex, paletteIndex;
|
|
uint prevBit, nextBit;
|
|
uint nextBitTest = 0b00010000;
|
|
uint nextBitShift = 4;
|
|
|
|
ubyte bits = bitmap[bitmapPtr];
|
|
|
|
if (scanStart == 0)
|
|
{
|
|
colorIndex = (bits >> 5) & 0b11;
|
|
}
|
|
else
|
|
{
|
|
colorIndex = (bits << 2) & 0b11111;
|
|
bits = bitmap[++bitmapPtr];
|
|
colorIndex |= (bits >> 5 & 0b11);
|
|
}
|
|
nextBit = (bits & nextBitTest) >> nextBitShift;
|
|
|
|
if (colEnd > 556)
|
|
{
|
|
finishCols = true;
|
|
colEnd = 556;
|
|
}
|
|
colEnd += colCorrection;
|
|
|
|
for (uint col = colStart + colCorrection; col <= colEnd; ++col)
|
|
{
|
|
nextBitTest >>= 1;
|
|
--nextBitShift;
|
|
if (nextBitTest == 0)
|
|
{
|
|
nextBitTest = 0b01000000;
|
|
nextBitShift = 6;
|
|
bits = bitmap[++bitmapPtr];
|
|
}
|
|
prevBit = colorIndex >> 4;
|
|
colorIndex = ((colorIndex << 1) | nextBit) & 0b11111;
|
|
nextBit = (bits & nextBitTest) >> nextBitShift;
|
|
paletteIndex = scheme[col & 0b11][colorIndex];
|
|
if (paletteIndex > 0x80)
|
|
{
|
|
switch (sharp_table[prevBit][nextBit][colorIndex])
|
|
{
|
|
case 0:
|
|
paletteIndex = Color.Black;
|
|
case 15:
|
|
paletteIndex = Color.White;
|
|
case 99:
|
|
paletteIndex &= 0x7F;
|
|
}
|
|
}
|
|
data[dataPtr++] = colorPalette[paletteIndex];
|
|
}
|
|
|
|
if (finishCols)
|
|
{
|
|
for (uint col = 557 + colCorrection; col <= 561 + colCorrection;
|
|
++col)
|
|
{
|
|
prevBit = colorIndex >> 4;
|
|
colorIndex = (colorIndex << 1) & 0b11111;
|
|
paletteIndex = scheme[col & 0b11][colorIndex];
|
|
if (paletteIndex > 0x80)
|
|
{
|
|
switch (sharp_table[prevBit][nextBit][colorIndex])
|
|
{
|
|
case 0:
|
|
paletteIndex = Color.Black;
|
|
case 15:
|
|
paletteIndex = Color.White;
|
|
case 99:
|
|
paletteIndex &= 0x7F;
|
|
}
|
|
}
|
|
data[dataPtr++] = colorPalette[paletteIndex];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|