893 lines
21 KiB
C++
893 lines
21 KiB
C++
//
|
|
// Object Processor
|
|
//
|
|
// Original source by David Raingeard (Cal2)
|
|
// GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
|
|
// Extensive cleanups/fixes/rewrites by James Hammons
|
|
// (C) 2010 Underground Software
|
|
//
|
|
// JLH = James Hammons <jlhamm@acm.org>
|
|
//
|
|
// Who When What
|
|
// --- ---------- -----------------------------------------------------------
|
|
// JLH 01/16/2010 Created this log ;-)
|
|
//
|
|
|
|
#include "op.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "gpu.h"
|
|
#include "jaguar.h"
|
|
#include "m68000/m68kinterface.h"
|
|
#include "memory.h"
|
|
#include "tom.h"
|
|
|
|
#define BLEND_Y(dst, src) op_blend_y[(((uint16_t)dst<<8)) | ((uint16_t)(src))]
|
|
#define BLEND_CR(dst, src) op_blend_cr[(((uint16_t)dst)<<8) | ((uint16_t)(src))]
|
|
|
|
#define OBJECT_TYPE_BITMAP 0 // 000
|
|
#define OBJECT_TYPE_SCALE 1 // 001
|
|
#define OBJECT_TYPE_GPU 2 // 010
|
|
#define OBJECT_TYPE_BRANCH 3 // 011
|
|
#define OBJECT_TYPE_STOP 4 // 100
|
|
|
|
#define CONDITION_EQUAL 0 // VC == YPOS
|
|
#define CONDITION_LESS_THAN 1 // VC < YPOS
|
|
#define CONDITION_GREATER_THAN 2 // VC > YPOS
|
|
#define CONDITION_OP_FLAG_SET 3
|
|
#define CONDITION_SECOND_HALF_LINE 4
|
|
|
|
static void OPProcessFixedBitmap(uint64_t p0, uint64_t p1);
|
|
static void OPProcessScaledBitmap(uint64_t p0, uint64_t p1, uint64_t p2);
|
|
|
|
// Local global variables
|
|
|
|
// Blend tables (64K each)
|
|
static uint8_t op_blend_y[0x10000];
|
|
static uint8_t op_blend_cr[0x10000];
|
|
|
|
static uint32_t op_pointer;
|
|
|
|
static const int32_t phraseWidthToPixels[8] = { 64, 32, 16, 8, 4, 2, 0, 0 };
|
|
|
|
//
|
|
// Object Processor initialization
|
|
//
|
|
void OPInit(void)
|
|
{
|
|
for(int i=0; i<256*256; i++)
|
|
{
|
|
int y = (i >> 8) & 0xFF;
|
|
int dy = (int8_t)i;
|
|
int c1 = (i >> 8) & 0x0F;
|
|
int dc1 = (int8_t)(i << 4) >> 4;
|
|
int c2 = (i >> 12) & 0x0F;
|
|
int dc2 = (int8_t)(i & 0xF0) >> 4;
|
|
|
|
y += dy;
|
|
|
|
if (y < 0)
|
|
y = 0;
|
|
else if (y > 0xFF)
|
|
y = 0xFF;
|
|
|
|
op_blend_y[i] = y;
|
|
|
|
c1 += dc1;
|
|
|
|
if (c1 < 0)
|
|
c1 = 0;
|
|
else if (c1 > 0x0F)
|
|
c1 = 0x0F;
|
|
|
|
c2 += dc2;
|
|
|
|
if (c2 < 0)
|
|
c2 = 0;
|
|
else if (c2 > 0x0F)
|
|
c2 = 0x0F;
|
|
|
|
op_blend_cr[i] = (c2 << 4) | c1;
|
|
}
|
|
|
|
OPReset();
|
|
}
|
|
|
|
//
|
|
// Object Processor reset
|
|
//
|
|
void OPReset(void)
|
|
{
|
|
}
|
|
|
|
static uint32_t OPGetListPointer(void)
|
|
{
|
|
return GET16(tomRam8, 0x20) | (GET16(tomRam8, 0x22) << 16);
|
|
}
|
|
|
|
static uint32_t OPGetStatusRegister(void)
|
|
{
|
|
return GET16(tomRam8, 0x26);
|
|
}
|
|
|
|
static void OPSetCurrentObject(uint64_t object)
|
|
{
|
|
tomRam8[0x17] = object & 0xFF; object >>= 8;
|
|
tomRam8[0x16] = object & 0xFF; object >>= 8;
|
|
tomRam8[0x15] = object & 0xFF; object >>= 8;
|
|
tomRam8[0x14] = object & 0xFF; object >>= 8;
|
|
|
|
tomRam8[0x13] = object & 0xFF; object >>= 8;
|
|
tomRam8[0x12] = object & 0xFF; object >>= 8;
|
|
tomRam8[0x11] = object & 0xFF; object >>= 8;
|
|
tomRam8[0x10] = object & 0xFF;
|
|
}
|
|
|
|
static uint64_t OPLoadPhrase(uint32_t offset)
|
|
{
|
|
offset &= ~0x07;
|
|
return ((uint64_t)JaguarReadLong(offset, OP) << 32) | (uint64_t)JaguarReadLong(offset+4, OP);
|
|
}
|
|
|
|
static void OPStorePhrase(uint32_t offset, uint64_t p)
|
|
{
|
|
offset &= ~0x07;
|
|
JaguarWriteLong(offset, p >> 32, OP);
|
|
JaguarWriteLong(offset + 4, p & 0xFFFFFFFF, OP);
|
|
}
|
|
|
|
//
|
|
// Object Processor main routine
|
|
//
|
|
void OPProcessList(int halfline)
|
|
{
|
|
halfline &= 0x7FF;
|
|
|
|
op_pointer = OPGetListPointer();
|
|
|
|
uint32_t opCyclesToRun = 30000;
|
|
|
|
while (op_pointer)
|
|
{
|
|
uint64_t p0 = OPLoadPhrase(op_pointer);
|
|
op_pointer += 8;
|
|
|
|
switch ((uint8_t)p0 & 0x07)
|
|
{
|
|
case OBJECT_TYPE_BITMAP:
|
|
{
|
|
uint16_t ypos = (p0 >> 3) & 0x7FF;
|
|
uint32_t height = (p0 & 0xFFC000) >> 14;
|
|
uint32_t oldOPP = op_pointer - 8;
|
|
|
|
if (halfline >= ypos && height > 0)
|
|
{
|
|
uint64_t p1 = OPLoadPhrase(oldOPP | 0x08);
|
|
OPProcessFixedBitmap(p0, p1);
|
|
|
|
height--;
|
|
|
|
uint64_t data = (p0 & 0xFFFFF80000000000LL) >> 40;
|
|
uint64_t dwidth = (p1 & 0xFFC0000) >> 15;
|
|
data += dwidth;
|
|
|
|
p0 &= ~0xFFFFF80000FFC000LL;
|
|
p0 |= (uint64_t)height << 14;
|
|
p0 |= data << 40;
|
|
OPStorePhrase(oldOPP, p0);
|
|
}
|
|
|
|
op_pointer = (p0 & 0x000007FFFF000000LL) >> 21;
|
|
|
|
if (op_pointer > 0x1FFFFF && op_pointer < 0x800000)
|
|
op_pointer &= 0xFF1FFFFF;
|
|
|
|
break;
|
|
}
|
|
case OBJECT_TYPE_SCALE:
|
|
{
|
|
uint16_t ypos = (p0 >> 3) & 0x7FF;
|
|
uint32_t height = (p0 & 0xFFC000) >> 14;
|
|
uint32_t oldOPP = op_pointer - 8;
|
|
|
|
if (halfline >= ypos && height > 0)
|
|
{
|
|
uint64_t p1 = OPLoadPhrase(oldOPP | 0x08);
|
|
uint64_t p2 = OPLoadPhrase(oldOPP | 0x10);
|
|
OPProcessScaledBitmap(p0, p1, p2);
|
|
|
|
uint16_t remainder = (p2 >> 16) & 0xFF;
|
|
uint8_t vscale = p2 >> 8;
|
|
|
|
if (vscale == 0)
|
|
vscale = 0x20;
|
|
|
|
if (remainder < 0x20)
|
|
{
|
|
uint64_t data = (p0 & 0xFFFFF80000000000LL) >> 40;
|
|
uint64_t dwidth = (p1 & 0xFFC0000) >> 15;
|
|
|
|
while (remainder < 0x20)
|
|
{
|
|
remainder += vscale;
|
|
|
|
if (height)
|
|
height--;
|
|
|
|
data += dwidth;
|
|
}
|
|
|
|
p0 &= ~0xFFFFF80000FFC000LL;
|
|
p0 |= (uint64_t)height << 14;
|
|
p0 |= data << 40;
|
|
OPStorePhrase(oldOPP, p0);
|
|
}
|
|
|
|
remainder -= 0x20;
|
|
|
|
p2 &= ~0x0000000000FF0000LL;
|
|
p2 |= (uint64_t)remainder << 16;
|
|
OPStorePhrase(oldOPP + 16, p2);
|
|
}
|
|
|
|
op_pointer = (p0 & 0x000007FFFF000000LL) >> 21;
|
|
|
|
if (op_pointer > 0x1FFFFF && op_pointer < 0x800000)
|
|
op_pointer &= 0xFF1FFFFF;
|
|
|
|
break;
|
|
}
|
|
case OBJECT_TYPE_GPU:
|
|
{
|
|
OPSetCurrentObject(p0);
|
|
GPUSetIRQLine(3, ASSERT_LINE);
|
|
break;
|
|
}
|
|
case OBJECT_TYPE_BRANCH:
|
|
{
|
|
uint16_t ypos = (p0 >> 3) & 0x7FF;
|
|
uint8_t cc = (p0 >> 14) & 0x07;
|
|
uint32_t link = (p0 >> 21) & 0x3FFFF8;
|
|
|
|
switch (cc)
|
|
{
|
|
case CONDITION_EQUAL:
|
|
if (halfline == ypos || ypos == 0x7FF)
|
|
op_pointer = link;
|
|
break;
|
|
case CONDITION_LESS_THAN:
|
|
if (halfline < ypos)
|
|
op_pointer = link;
|
|
break;
|
|
case CONDITION_GREATER_THAN:
|
|
if (halfline > ypos)
|
|
op_pointer = link;
|
|
break;
|
|
case CONDITION_OP_FLAG_SET:
|
|
if (OPGetStatusRegister() & 0x01)
|
|
op_pointer = link;
|
|
break;
|
|
case CONDITION_SECOND_HALF_LINE:
|
|
if (TOMGetHC() & 0x0400)
|
|
op_pointer = link;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case OBJECT_TYPE_STOP:
|
|
{
|
|
OPSetCurrentObject(p0);
|
|
|
|
if ((p0 & 0x08) && TOMIRQEnabled(IRQ_OPFLAG))
|
|
{
|
|
TOMSetPendingObjectInt();
|
|
m68k_set_irq(2);
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
opCyclesToRun--;
|
|
|
|
if (!opCyclesToRun)
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Store fixed size bitmap in line buffer
|
|
//
|
|
static void OPProcessFixedBitmap(uint64_t p0, uint64_t p1)
|
|
{
|
|
uint8_t depth = (p1 >> 12) & 0x07;
|
|
int32_t xpos = ((int16_t)((p1 << 4) & 0xFFFF)) >> 4;
|
|
uint32_t iwidth = (p1 >> 28) & 0x3FF;
|
|
uint32_t data = (p0 >> 40) & 0xFFFFF8;
|
|
uint32_t firstPix = (p1 >> 49) & 0x3F;
|
|
firstPix &= 0x3E;
|
|
|
|
uint8_t flags = (p1 >> 45) & 0x07;
|
|
bool flagREFLECT = (flags & OPFLAG_REFLECT ? true : false),
|
|
flagRMW = (flags & OPFLAG_RMW ? true : false),
|
|
flagTRANS = (flags & OPFLAG_TRANS ? true : false);
|
|
|
|
uint8_t index = (p1 >> 37) & 0xFE;
|
|
uint32_t pitch = (p1 >> 15) & 0x07;
|
|
pitch <<= 3;
|
|
|
|
uint8_t * paletteRAM = &tomRam8[0x400];
|
|
uint16_t * paletteRAM16 = (uint16_t *)paletteRAM;
|
|
|
|
if (iwidth == 0)
|
|
iwidth = 1;
|
|
|
|
if (iwidth == 0)
|
|
return;
|
|
|
|
int32_t startPos = xpos, endPos = xpos +
|
|
(!flagREFLECT ? (phraseWidthToPixels[depth] * iwidth) - 1
|
|
: -((phraseWidthToPixels[depth] * iwidth) + 1));
|
|
uint32_t clippedWidth = 0, phraseClippedWidth = 0, dataClippedWidth = 0;
|
|
bool in24BPPMode = (((GET16(tomRam8, 0x0028) >> 1) & 0x03) == 1 ? true : false);
|
|
|
|
int32_t limit = 720;
|
|
int32_t lbufWidth = 719;
|
|
|
|
if ((!flagREFLECT && (endPos < 0 || startPos > lbufWidth))
|
|
|| (flagREFLECT && (startPos < 0 || endPos > lbufWidth)))
|
|
return;
|
|
|
|
if (startPos < 0)
|
|
clippedWidth = 0 - startPos,
|
|
dataClippedWidth = phraseClippedWidth = clippedWidth / phraseWidthToPixels[depth],
|
|
startPos = 0 - (clippedWidth % phraseWidthToPixels[depth]);
|
|
|
|
if (endPos < 0)
|
|
clippedWidth = 0 - endPos,
|
|
phraseClippedWidth = clippedWidth / phraseWidthToPixels[depth];
|
|
|
|
if (endPos > lbufWidth)
|
|
clippedWidth = endPos - lbufWidth,
|
|
phraseClippedWidth = clippedWidth / phraseWidthToPixels[depth];
|
|
|
|
if (startPos > lbufWidth)
|
|
clippedWidth = startPos - lbufWidth,
|
|
dataClippedWidth = phraseClippedWidth = clippedWidth / phraseWidthToPixels[depth],
|
|
startPos = lbufWidth + (clippedWidth % phraseWidthToPixels[depth]);
|
|
|
|
iwidth -= phraseClippedWidth;
|
|
|
|
data += dataClippedWidth * pitch;
|
|
|
|
uint32_t lbufAddress = 0x1800 + (startPos * 2);
|
|
uint8_t * currentLineBuffer = &tomRam8[lbufAddress];
|
|
|
|
if (depth == 0)
|
|
{
|
|
int32_t lbufDelta = ((int8_t)((flags << 7) & 0xFF) >> 5) | 0x02;
|
|
|
|
uint64_t pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
pixels <<= firstPix;
|
|
int i = firstPix;
|
|
|
|
while (iwidth--)
|
|
{
|
|
while (i++ < 64)
|
|
{
|
|
uint8_t bit = pixels >> 63;
|
|
if (flagTRANS && bit == 0)
|
|
;
|
|
else
|
|
{
|
|
if (!flagRMW)
|
|
*(uint16_t *)currentLineBuffer = paletteRAM16[index | bit];
|
|
else
|
|
*currentLineBuffer =
|
|
BLEND_CR(*currentLineBuffer, paletteRAM[(index | bit) << 1]),
|
|
*(currentLineBuffer + 1) =
|
|
BLEND_Y(*(currentLineBuffer + 1), paletteRAM[((index | bit) << 1) + 1]);
|
|
}
|
|
|
|
currentLineBuffer += lbufDelta;
|
|
pixels <<= 1;
|
|
}
|
|
|
|
i = 0;
|
|
data += pitch;
|
|
pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
}
|
|
}
|
|
else if (depth == 1)
|
|
{
|
|
index &= 0xFC;
|
|
int32_t lbufDelta = ((int8_t)((flags << 7) & 0xFF) >> 5) | 0x02;
|
|
|
|
while (iwidth--)
|
|
{
|
|
uint64_t pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
data += pitch;
|
|
|
|
for(int i=0; i<32; i++)
|
|
{
|
|
uint8_t bits = pixels >> 62;
|
|
if (flagTRANS && bits == 0)
|
|
;
|
|
else
|
|
{
|
|
if (!flagRMW)
|
|
*(uint16_t *)currentLineBuffer = paletteRAM16[index | bits];
|
|
else
|
|
*currentLineBuffer =
|
|
BLEND_CR(*currentLineBuffer, paletteRAM[(index | bits) << 1]),
|
|
*(currentLineBuffer + 1) =
|
|
BLEND_Y(*(currentLineBuffer + 1), paletteRAM[((index | bits) << 1) + 1]);
|
|
}
|
|
|
|
currentLineBuffer += lbufDelta;
|
|
pixels <<= 2;
|
|
}
|
|
}
|
|
}
|
|
else if (depth == 2)
|
|
{
|
|
index &= 0xF0;
|
|
int32_t lbufDelta = ((int8_t)((flags << 7) & 0xFF) >> 5) | 0x02;
|
|
|
|
while (iwidth--)
|
|
{
|
|
uint64_t pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
data += pitch;
|
|
|
|
for(int i=0; i<16; i++)
|
|
{
|
|
uint8_t bits = pixels >> 60;
|
|
if (flagTRANS && bits == 0)
|
|
;
|
|
else
|
|
{
|
|
if (!flagRMW)
|
|
*(uint16_t *)currentLineBuffer = paletteRAM16[index | bits];
|
|
else
|
|
*currentLineBuffer =
|
|
BLEND_CR(*currentLineBuffer, paletteRAM[(index | bits) << 1]),
|
|
*(currentLineBuffer + 1) =
|
|
BLEND_Y(*(currentLineBuffer + 1), paletteRAM[((index | bits) << 1) + 1]);
|
|
}
|
|
|
|
currentLineBuffer += lbufDelta;
|
|
pixels <<= 4;
|
|
}
|
|
}
|
|
}
|
|
else if (depth == 3)
|
|
{
|
|
int32_t lbufDelta = ((int8_t)((flags << 7) & 0xFF) >> 5) | 0x02;
|
|
|
|
uint64_t pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
firstPix &= 0x30;
|
|
pixels <<= firstPix;
|
|
int i = firstPix >> 3;
|
|
|
|
while (iwidth--)
|
|
{
|
|
while (i++ < 8)
|
|
{
|
|
uint8_t bits = pixels >> 56;
|
|
if (flagTRANS && bits == 0)
|
|
;
|
|
else
|
|
{
|
|
if (!flagRMW)
|
|
*(uint16_t *)currentLineBuffer = paletteRAM16[bits];
|
|
else
|
|
*currentLineBuffer =
|
|
BLEND_CR(*currentLineBuffer, paletteRAM[bits << 1]),
|
|
*(currentLineBuffer + 1) =
|
|
BLEND_Y(*(currentLineBuffer + 1), paletteRAM[(bits << 1) + 1]);
|
|
}
|
|
|
|
currentLineBuffer += lbufDelta;
|
|
pixels <<= 8;
|
|
}
|
|
i = 0;
|
|
|
|
data += pitch;
|
|
pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
}
|
|
}
|
|
else if (depth == 4)
|
|
{
|
|
int32_t lbufDelta = ((int8_t)((flags << 7) & 0xFF) >> 5) | 0x02;
|
|
|
|
while (iwidth--)
|
|
{
|
|
uint64_t pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
data += pitch;
|
|
|
|
for(int i=0; i<4; i++)
|
|
{
|
|
uint8_t bitsHi = pixels >> 56, bitsLo = pixels >> 48;
|
|
|
|
if (flagTRANS && ((bitsLo | bitsHi) == 0))
|
|
;
|
|
else
|
|
{
|
|
if (!flagRMW)
|
|
*currentLineBuffer = bitsHi,
|
|
*(currentLineBuffer + 1) = bitsLo;
|
|
else
|
|
*currentLineBuffer =
|
|
BLEND_CR(*currentLineBuffer, bitsHi),
|
|
*(currentLineBuffer + 1) =
|
|
BLEND_Y(*(currentLineBuffer + 1), bitsLo);
|
|
}
|
|
|
|
currentLineBuffer += lbufDelta;
|
|
pixels <<= 16;
|
|
}
|
|
}
|
|
}
|
|
else if (depth == 5)
|
|
{
|
|
int32_t lbufDelta = ((int8_t)((flags << 7) & 0xFF) >> 4) | 0x04;
|
|
|
|
while (iwidth--)
|
|
{
|
|
uint64_t pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
data += pitch;
|
|
|
|
for(int i=0; i<2; i++)
|
|
{
|
|
uint8_t bits3 = pixels >> 56, bits2 = pixels >> 48,
|
|
bits1 = pixels >> 40, bits0 = pixels >> 32;
|
|
|
|
if (flagTRANS && (bits3 | bits2 | bits1 | bits0) == 0)
|
|
;
|
|
else
|
|
*currentLineBuffer = bits3,
|
|
*(currentLineBuffer + 1) = bits2,
|
|
*(currentLineBuffer + 2) = bits1,
|
|
*(currentLineBuffer + 3) = bits0;
|
|
|
|
currentLineBuffer += lbufDelta;
|
|
pixels <<= 32;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Store scaled bitmap in line buffer
|
|
//
|
|
static void OPProcessScaledBitmap(uint64_t p0, uint64_t p1, uint64_t p2)
|
|
{
|
|
uint8_t depth = (p1 >> 12) & 0x07;
|
|
int32_t xpos = ((int16_t)((p1 << 4) & 0xFFFF)) >> 4;
|
|
uint32_t iwidth = (p1 >> 28) & 0x3FF;
|
|
uint32_t data = (p0 >> 40) & 0xFFFFF8;
|
|
|
|
uint32_t firstPix = (p1 >> 49) & 0x3F;
|
|
|
|
uint8_t flags = (p1 >> 45) & 0x07;
|
|
bool flagREFLECT = (flags & OPFLAG_REFLECT ? true : false),
|
|
flagRMW = (flags & OPFLAG_RMW ? true : false),
|
|
flagTRANS = (flags & OPFLAG_TRANS ? true : false);
|
|
uint8_t index = (p1 >> 37) & 0xFE;
|
|
uint32_t pitch = (p1 >> 15) & 0x07;
|
|
|
|
uint8_t * paletteRAM = &tomRam8[0x400];
|
|
uint16_t * paletteRAM16 = (uint16_t *)paletteRAM;
|
|
|
|
uint16_t hscale = p2 & 0xFF;
|
|
uint16_t horizontalRemainder = hscale;
|
|
int32_t scaledWidthInPixels = (iwidth * phraseWidthToPixels[depth] * hscale) >> 5;
|
|
uint32_t scaledPhrasePixels = (phraseWidthToPixels[depth] * hscale) >> 5;
|
|
|
|
if (iwidth == 0 || hscale == 0)
|
|
return;
|
|
|
|
int32_t startPos = xpos, endPos = xpos +
|
|
(!flagREFLECT ? scaledWidthInPixels - 1 : -(scaledWidthInPixels + 1));
|
|
uint32_t clippedWidth = 0, phraseClippedWidth = 0, dataClippedWidth = 0;
|
|
bool in24BPPMode = (((GET16(tomRam8, 0x0028) >> 1) & 0x03) == 1 ? true : false);
|
|
|
|
int32_t limit = 720;
|
|
int32_t lbufWidth = 719;
|
|
|
|
if ((!flagREFLECT && (endPos < 0 || startPos > lbufWidth))
|
|
|| (flagREFLECT && (startPos < 0 || endPos > lbufWidth)))
|
|
return;
|
|
|
|
uint32_t scaledPhrasePixelsUS = phraseWidthToPixels[depth] * hscale;
|
|
|
|
if (startPos < 0)
|
|
clippedWidth = (0 - startPos) << 5,
|
|
dataClippedWidth = phraseClippedWidth = (clippedWidth / scaledPhrasePixelsUS) >> 5,
|
|
startPos += (dataClippedWidth * scaledPhrasePixelsUS) >> 5;
|
|
|
|
if (endPos < 0)
|
|
clippedWidth = 0 - endPos,
|
|
phraseClippedWidth = clippedWidth / scaledPhrasePixels;
|
|
|
|
if (endPos > lbufWidth)
|
|
clippedWidth = endPos - lbufWidth,
|
|
phraseClippedWidth = clippedWidth / scaledPhrasePixels;
|
|
|
|
if (startPos > lbufWidth)
|
|
clippedWidth = startPos - lbufWidth,
|
|
dataClippedWidth = phraseClippedWidth = clippedWidth / scaledPhrasePixels,
|
|
startPos = lbufWidth + (clippedWidth % scaledPhrasePixels);
|
|
|
|
iwidth -= phraseClippedWidth;
|
|
|
|
data += dataClippedWidth * (pitch << 3);
|
|
|
|
uint32_t lbufAddress = 0x1800 + startPos * 2;
|
|
uint8_t * currentLineBuffer = &tomRam8[lbufAddress];
|
|
|
|
if (depth == 0)
|
|
{
|
|
int32_t lbufDelta = ((int8_t)((flags << 7) & 0xFF) >> 5) | 0x02;
|
|
|
|
int pixCount = 0;
|
|
uint64_t pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
|
|
while ((int32_t)iwidth > 0)
|
|
{
|
|
uint8_t bits = pixels >> 63;
|
|
|
|
if (flagTRANS && bits == 0)
|
|
;
|
|
else
|
|
{
|
|
if (!flagRMW)
|
|
*(uint16_t *)currentLineBuffer = paletteRAM16[index | bits];
|
|
else
|
|
*currentLineBuffer =
|
|
BLEND_CR(*currentLineBuffer, paletteRAM[(index | bits) << 1]),
|
|
*(currentLineBuffer + 1) =
|
|
BLEND_Y(*(currentLineBuffer + 1), paletteRAM[((index | bits) << 1) + 1]);
|
|
}
|
|
|
|
currentLineBuffer += lbufDelta;
|
|
|
|
while (horizontalRemainder < 0x20)
|
|
{
|
|
horizontalRemainder += hscale;
|
|
pixCount++;
|
|
pixels <<= 1;
|
|
}
|
|
horizontalRemainder -= 0x20;
|
|
|
|
if (pixCount > 63)
|
|
{
|
|
int phrasesToSkip = pixCount / 64, pixelShift = pixCount % 64;
|
|
|
|
data += (pitch << 3) * phrasesToSkip;
|
|
pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
pixels <<= 1 * pixelShift;
|
|
iwidth -= phrasesToSkip;
|
|
pixCount = pixelShift;
|
|
}
|
|
}
|
|
}
|
|
else if (depth == 1)
|
|
{
|
|
index &= 0xFC;
|
|
int32_t lbufDelta = ((int8_t)((flags << 7) & 0xFF) >> 5) | 0x02;
|
|
|
|
int pixCount = 0;
|
|
uint64_t pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
|
|
while ((int32_t)iwidth > 0)
|
|
{
|
|
uint8_t bits = pixels >> 62;
|
|
|
|
if (flagTRANS && bits == 0)
|
|
;
|
|
else
|
|
{
|
|
if (!flagRMW)
|
|
*(uint16_t *)currentLineBuffer = paletteRAM16[index | bits];
|
|
else
|
|
*currentLineBuffer =
|
|
BLEND_CR(*currentLineBuffer, paletteRAM[(index | bits) << 1]),
|
|
*(currentLineBuffer + 1) =
|
|
BLEND_Y(*(currentLineBuffer + 1), paletteRAM[((index | bits) << 1) + 1]);
|
|
}
|
|
|
|
currentLineBuffer += lbufDelta;
|
|
|
|
while (horizontalRemainder < 0x20)
|
|
{
|
|
horizontalRemainder += hscale;
|
|
pixCount++;
|
|
pixels <<= 2;
|
|
}
|
|
horizontalRemainder -= 0x20;
|
|
|
|
if (pixCount > 31)
|
|
{
|
|
int phrasesToSkip = pixCount / 32, pixelShift = pixCount % 32;
|
|
|
|
data += (pitch << 3) * phrasesToSkip;
|
|
pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
pixels <<= 2 * pixelShift;
|
|
iwidth -= phrasesToSkip;
|
|
pixCount = pixelShift;
|
|
}
|
|
}
|
|
}
|
|
else if (depth == 2)
|
|
{
|
|
index &= 0xF0;
|
|
int32_t lbufDelta = ((int8_t)((flags << 7) & 0xFF) >> 5) | 0x02;
|
|
|
|
int pixCount = 0;
|
|
uint64_t pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
|
|
while ((int32_t)iwidth > 0)
|
|
{
|
|
uint8_t bits = pixels >> 60;
|
|
|
|
if (flagTRANS && bits == 0)
|
|
;
|
|
else
|
|
{
|
|
if (!flagRMW)
|
|
*(uint16_t *)currentLineBuffer = paletteRAM16[index | bits];
|
|
else
|
|
*currentLineBuffer =
|
|
BLEND_CR(*currentLineBuffer, paletteRAM[(index | bits) << 1]),
|
|
*(currentLineBuffer + 1) =
|
|
BLEND_Y(*(currentLineBuffer + 1), paletteRAM[((index | bits) << 1) + 1]);
|
|
}
|
|
|
|
currentLineBuffer += lbufDelta;
|
|
|
|
while (horizontalRemainder < 0x20)
|
|
{
|
|
horizontalRemainder += hscale;
|
|
pixCount++;
|
|
pixels <<= 4;
|
|
}
|
|
horizontalRemainder -= 0x20;
|
|
|
|
if (pixCount > 15)
|
|
{
|
|
int phrasesToSkip = pixCount / 16, pixelShift = pixCount % 16;
|
|
|
|
data += (pitch << 3) * phrasesToSkip;
|
|
pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
pixels <<= 4 * pixelShift;
|
|
iwidth -= phrasesToSkip;
|
|
pixCount = pixelShift;
|
|
}
|
|
}
|
|
}
|
|
else if (depth == 3)
|
|
{
|
|
int32_t lbufDelta = ((int8_t)((flags << 7) & 0xFF) >> 5) | 0x02;
|
|
|
|
int pixCount = 0;
|
|
uint64_t pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
|
|
while ((int32_t)iwidth > 0)
|
|
{
|
|
uint8_t bits = pixels >> 56;
|
|
|
|
if (flagTRANS && bits == 0)
|
|
;
|
|
else
|
|
{
|
|
if (!flagRMW)
|
|
*(uint16_t *)currentLineBuffer = paletteRAM16[bits];
|
|
else
|
|
*currentLineBuffer =
|
|
BLEND_CR(*currentLineBuffer, paletteRAM[bits << 1]),
|
|
*(currentLineBuffer + 1) =
|
|
BLEND_Y(*(currentLineBuffer + 1), paletteRAM[(bits << 1) + 1]);
|
|
}
|
|
|
|
currentLineBuffer += lbufDelta;
|
|
|
|
while (horizontalRemainder < 0x20)
|
|
{
|
|
horizontalRemainder += hscale;
|
|
pixCount++;
|
|
pixels <<= 8;
|
|
}
|
|
horizontalRemainder -= 0x20;
|
|
|
|
if (pixCount > 7)
|
|
{
|
|
int phrasesToSkip = pixCount / 8, pixelShift = pixCount % 8;
|
|
|
|
data += (pitch << 3) * phrasesToSkip;
|
|
pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
pixels <<= 8 * pixelShift;
|
|
iwidth -= phrasesToSkip;
|
|
pixCount = pixelShift;
|
|
}
|
|
}
|
|
}
|
|
else if (depth == 4)
|
|
{
|
|
int32_t lbufDelta = ((int8_t)((flags << 7) & 0xFF) >> 5) | 0x02;
|
|
|
|
int pixCount = 0;
|
|
uint64_t pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
|
|
while ((int32_t)iwidth > 0)
|
|
{
|
|
uint8_t bitsHi = pixels >> 56, bitsLo = pixels >> 48;
|
|
|
|
if (flagTRANS && ((bitsLo | bitsHi) == 0))
|
|
;
|
|
else
|
|
{
|
|
if (!flagRMW)
|
|
*currentLineBuffer = bitsHi,
|
|
*(currentLineBuffer + 1) = bitsLo;
|
|
else
|
|
*currentLineBuffer =
|
|
BLEND_CR(*currentLineBuffer, bitsHi),
|
|
*(currentLineBuffer + 1) =
|
|
BLEND_Y(*(currentLineBuffer + 1), bitsLo);
|
|
}
|
|
|
|
currentLineBuffer += lbufDelta;
|
|
|
|
while (horizontalRemainder < 0x20)
|
|
{
|
|
horizontalRemainder += hscale;
|
|
pixCount++;
|
|
pixels <<= 16;
|
|
}
|
|
horizontalRemainder -= 0x20;
|
|
|
|
if (pixCount > 3)
|
|
{
|
|
int phrasesToSkip = pixCount / 4, pixelShift = pixCount % 4;
|
|
|
|
data += (pitch << 3) * phrasesToSkip;
|
|
pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
pixels <<= 16 * pixelShift;
|
|
|
|
iwidth -= phrasesToSkip;
|
|
|
|
pixCount = pixelShift;
|
|
}
|
|
}
|
|
}
|
|
else if (depth == 5)
|
|
{
|
|
int32_t lbufDelta = ((int8_t)((flags << 7) & 0xFF) >> 4) | 0x04;
|
|
|
|
while (iwidth--)
|
|
{
|
|
uint64_t pixels = ((uint64_t)JaguarReadLong(data, OP) << 32) | JaguarReadLong(data + 4, OP);
|
|
data += pitch << 3;
|
|
|
|
for(int i=0; i<2; i++)
|
|
{
|
|
uint8_t bits3 = pixels >> 56, bits2 = pixels >> 48,
|
|
bits1 = pixels >> 40, bits0 = pixels >> 32;
|
|
|
|
if (flagTRANS && (bits3 | bits2 | bits1 | bits0) == 0)
|
|
;
|
|
else
|
|
*currentLineBuffer = bits3,
|
|
*(currentLineBuffer + 1) = bits2,
|
|
*(currentLineBuffer + 2) = bits1,
|
|
*(currentLineBuffer + 3) = bits0;
|
|
|
|
currentLineBuffer += lbufDelta;
|
|
pixels <<= 32;
|
|
}
|
|
}
|
|
}
|
|
}
|