twoapple-reboot/src/video/laz_engine.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];
}
}
}
}