Prepare for new BG processors
This commit is contained in:
parent
bcd80d291b
commit
67bcb6d508
259
core/vip.c
259
core/vip.c
|
@ -54,6 +54,32 @@ static const uint8_t BRIGHT8[] = {
|
|||
|
||||
|
||||
|
||||
/*********************************** Types ***********************************/
|
||||
|
||||
/* World attribtues per eye */
|
||||
typedef struct {
|
||||
int32_t bp; /* BG source parallax */
|
||||
int32_t left, right; /* Window bounds */
|
||||
int32_t wx; /* World horizontal position */
|
||||
} EyeAttribs;
|
||||
|
||||
/* Parsed world attributes */
|
||||
typedef struct {
|
||||
int32_t base; /* Base BG map index */
|
||||
uint8_t *bg; /* Background template */
|
||||
int32_t bgm; /* World type */
|
||||
int32_t bgw, bgh; /* Background dimension masks */
|
||||
int32_t bottom, top; /* Window bounds */
|
||||
int32_t gx, gp, gy; /* World screen position */
|
||||
int32_t mx, mp, my; /* Background scroll */
|
||||
int32_t over; /* Overplane flag */
|
||||
uint32_t params; /* Line parameters address */
|
||||
int32_t scx, scy; /* Background dimensions */
|
||||
int32_t w, h; /* Window size */
|
||||
} WorldAttribs;
|
||||
|
||||
|
||||
|
||||
/***************************** Module Functions ******************************/
|
||||
|
||||
/* Retrieve a pointer to character data in host memory */
|
||||
|
@ -597,6 +623,88 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
|
|||
|
||||
/****************************** Pixel Processor ******************************/
|
||||
|
||||
/* Parse eye attributes and test window bounds */
|
||||
static int vipParseEye(WorldAttribs *wttr, EyeAttribs *ettr, int eye) {
|
||||
|
||||
/* Validate the world isn't right of frame */
|
||||
ettr->wx = wttr->gx - (eye == 0 ? wttr->gp : -wttr->gp);
|
||||
if (ettr->wx > 383)
|
||||
return 1;
|
||||
ettr->left = ettr->wx < 0 ? 0 : ettr->wx;
|
||||
|
||||
/* Validate the world isn't left of frame */
|
||||
ettr->right = ettr->wx + wttr->w - 1;
|
||||
if (ettr->right < 0)
|
||||
return 1;
|
||||
if (ettr->right > 383)
|
||||
ettr->right = 383;
|
||||
|
||||
/* BG source parallax */
|
||||
if (wttr->bgm != 2)
|
||||
ettr->bp = eye == 0 ? -wttr->mp : wttr->mp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse world attributes and test window bounds */
|
||||
static int vipParseWorld(VB*sim,uint8_t*world,uint16_t bits,WorldAttribs*attr){
|
||||
int32_t z; /* Scratch */
|
||||
|
||||
/* Validate the world isn't below the frame */
|
||||
attr->gy = busReadBuffer(world + 6, VB_S16);
|
||||
if (attr->gy > 223)
|
||||
return 1;
|
||||
|
||||
/* Validate the world isn't above the frame, and height is positive */
|
||||
attr->bgm = bits >> 12 & 3;
|
||||
attr->h = busReadBuffer(world + 16, VB_S16) + 1;
|
||||
z = attr->bgm == 2 ? 0 : 8;
|
||||
if (attr->h < z)
|
||||
attr->h = z;
|
||||
if (attr->h == 0)
|
||||
return 1;
|
||||
attr->bottom = attr->gy + attr->h - 1;
|
||||
attr->top = (int32_t) sim->vip.xp.sbcount << 3;
|
||||
if (attr->bottom < attr->top)
|
||||
return 1;
|
||||
if (attr->bottom > 223)
|
||||
attr->bottom = 223;
|
||||
if (attr->top < attr->gy)
|
||||
attr->top = attr->gy;
|
||||
|
||||
/* Validate width is positive */
|
||||
attr->w = SignExtend(busReadBuffer(world + 14, VB_U16),
|
||||
attr->bgm == 2 ? 10 : 13) + 1;
|
||||
if (attr->w < 1)
|
||||
return 1;
|
||||
|
||||
/* Parse attributes */
|
||||
attr->bg = (uint8_t *) BG_TEMPLATES[bits >> 8 & 15];
|
||||
attr->gx = SignExtend(busReadBuffer(world + 2, VB_U16), 10);
|
||||
attr->gp = SignExtend(busReadBuffer(world + 4, VB_U16), 10);
|
||||
attr->over = bits >> 7 & 1;
|
||||
attr->scx = bits >> 10 & 3;
|
||||
attr->scy = bits >> 8 & 3;
|
||||
attr->bgw = (1 << attr->scx) - 1;
|
||||
attr->bgh = (1 << attr->scy) - 1;
|
||||
z = attr->scx + attr->scy;
|
||||
attr->base = bits & 15 & ~((1 << (z < 3 ? z : 3)) - 1);
|
||||
if (attr->bgm != 2) {
|
||||
attr->mx = SignExtend(busReadBuffer(world + 8, VB_U16), 13);
|
||||
attr->mp = SignExtend(busReadBuffer(world + 10, VB_U16), 15);
|
||||
attr->my = SignExtend(busReadBuffer(world + 12, VB_U16), 13);
|
||||
}
|
||||
if (attr->bgm != 0) {
|
||||
attr->params =
|
||||
0x20000 +
|
||||
(attr->top - attr->gy) * (attr->bgm == 1 ? 4 : 16) +
|
||||
((uint32_t) busReadBuffer(world + 18, VB_U16) << 1)
|
||||
;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Draw an object group into shadow memory */
|
||||
static void vipDrawObjects(VB *sim, int group) {
|
||||
uint8_t *dest; /* Pointer to object position in shadow memory */
|
||||
|
@ -687,124 +795,56 @@ static void vipDrawObjects(VB *sim, int group) {
|
|||
}
|
||||
|
||||
/* Draw a background world into shadow memory */
|
||||
static void vipDrawWorld(VB *sim, uint8_t *world, uint16_t attr) {
|
||||
uint8_t *bg; /* Background arrangement */
|
||||
static void vipDrawWorld(VB *sim, uint8_t *world, uint16_t bits) {
|
||||
uint16_t bgAttr; /* BG map cell attributes */
|
||||
int32_t bgh; /* Height of background in BG maps, minus 1 */
|
||||
int32_t bgw; /* Width of background in BG maps, minus 1 */
|
||||
int32_t bottom; /* Window bottom edge position */
|
||||
int32_t bp; /* Eye BG map source parallax */
|
||||
int32_t bx; /* BG horizontal map source position */
|
||||
int32_t by; /* BG vertical map source position */
|
||||
int32_t bx; /* BG source X */
|
||||
int32_t by; /* BG source Y */
|
||||
uint8_t *cell; /* Pointer to BG map cell in host memory */
|
||||
uint8_t *chr; /* Pointer to character data in host memory */
|
||||
int32_t cx; /* BG cell/character horizontal pixel source position */
|
||||
int32_t cy; /* BG cell/character vertical pixel source position */
|
||||
int32_t cx; /* BG cell/character source X */
|
||||
int32_t cy; /* BG cell/character source Y */
|
||||
uint8_t *dest; /* Pointer to output in shadow memory */
|
||||
int32_t left; /* Window left edge position */
|
||||
EyeAttribs ettr; /* Eye attributes */
|
||||
uint32_t param; /* Current line parameter address */
|
||||
int8_t pixel; /* Character pixel value */
|
||||
int32_t right; /* Window right edge position */
|
||||
int32_t top; /* Window top edge position */
|
||||
int32_t wx; /* Eye horizontal position */
|
||||
int32_t i, x, y; /* Iterators */
|
||||
|
||||
/* World attributes */
|
||||
int32_t base; /* BG map base index */
|
||||
int bgm; /* BG mode */
|
||||
WorldAttribs wttr; /* Common attributes */
|
||||
int32_t dx; /* Affine per-pixel X delta */
|
||||
int32_t dy; /* Affine per-pixel Y delta */
|
||||
int16_t gp; /* Window stereo parallax */
|
||||
int16_t gx; /* Window base horizontal position */
|
||||
int16_t gy; /* Window vertical position */
|
||||
int16_t h; /* Window height */
|
||||
int32_t mp; /* BG source parallax */
|
||||
int32_t mx; /* BG source X */
|
||||
int32_t my; /* BG source Y */
|
||||
int16_t hofst; /* H-bias shift */
|
||||
int32_t mp; /* BG map source stereo parallax */
|
||||
int32_t mx = 0; /* BG map horizontal source */
|
||||
int32_t my = 0; /* BG map vertical source */
|
||||
int32_t scx; /* Background width shift amount */
|
||||
int32_t scy; /* Background height shift amount */
|
||||
uint8_t *over; /* Pointer to overplane "cell" in host memory */
|
||||
uint32_t params = 0; /* Base address of line parameters */
|
||||
int16_t w; /* Window width */
|
||||
|
||||
/* Validate the world isn't below the frame */
|
||||
gy = busReadBuffer(world + 6, VB_S16);
|
||||
if (gy > 223)
|
||||
return;
|
||||
|
||||
/* Validate the world isn't above the frame, and height is positive */
|
||||
bgm = attr >> 12 & 3;
|
||||
y = bgm == 2 ? 0 : 8;
|
||||
h = busReadBuffer(world + 16, VB_S16) + 1;
|
||||
if (h < y)
|
||||
h = y;
|
||||
if (h == 0)
|
||||
return;
|
||||
bottom = gy + h - 1;
|
||||
top = (int32_t) sim->vip.xp.sbcount << 3;
|
||||
if (bottom < top)
|
||||
return;
|
||||
if (bottom > 223)
|
||||
bottom = 223;
|
||||
if (top < gy)
|
||||
top = gy;
|
||||
|
||||
/* Validate width is positive */
|
||||
w = SignExtend(busReadBuffer(world + 14, VB_U16), bgm == 2 ? 10 : 13) + 1;
|
||||
if (w < 1)
|
||||
return;
|
||||
/* Working variables */
|
||||
ettr.bp = wttr.mp = wttr.mx = wttr.my = wttr.params = 0;
|
||||
|
||||
/* Parse attributes */
|
||||
bg = (uint8_t *) BG_TEMPLATES[attr >> 8 & 15];
|
||||
gx = SignExtend(busReadBuffer(world + 2, VB_U16), 10);
|
||||
gp = SignExtend(busReadBuffer(world + 4, VB_U16), 10);
|
||||
over = (attr & 0x0080) ? world + 20 : NULL;
|
||||
scx = attr >> 10 & 3;
|
||||
scy = attr >> 8 & 3;
|
||||
bgw = (1 << scx) - 1;
|
||||
bgh = (1 << scy) - 1;
|
||||
base = attr & 15 & ~((1 << (scx + scy < 3 ? scx + scy : 3)) - 1);
|
||||
if (bgm != 2) {
|
||||
mx = SignExtend(busReadBuffer(world + 8, VB_U16), 13);
|
||||
mp = SignExtend(busReadBuffer(world + 10, VB_U16), 15);
|
||||
my = SignExtend(busReadBuffer(world + 12, VB_U16), 13);
|
||||
}
|
||||
if (bgm != 0) {
|
||||
params = 0x20000 + (top - gy) * (bgm == 1 ? 4 : 16) +
|
||||
((uint32_t) busReadBuffer(world + 18, VB_U16) << 1);
|
||||
}
|
||||
else hofst = 0;
|
||||
if (vipParseWorld(sim, world, bits, &wttr))
|
||||
return; /* Window not in frame */
|
||||
|
||||
/* Draw the world */
|
||||
for (i = 0; i < 2; i++) {
|
||||
|
||||
/* Validate world is enabled */
|
||||
if ((attr & (int32_t) 0x8000 >> i) == 0) /* LON, RON */
|
||||
/* World is not visible */
|
||||
if ((bits & (int32_t) 0x8000 >> i) == 0) /* LON, RON */
|
||||
continue;
|
||||
|
||||
/* Validate the world isn't right of frame */
|
||||
wx = gx - (i == 0 ? gp : -gp);
|
||||
if (wx > 383)
|
||||
return;
|
||||
left = wx < 0 ? 0 : wx;
|
||||
|
||||
/* Validate the world isn't left of frame */
|
||||
right = wx + w - 1;
|
||||
if (right < 0)
|
||||
return;
|
||||
if (right > 383)
|
||||
right = 383;
|
||||
|
||||
/* BG source parallax */
|
||||
if (bgm != 2)
|
||||
bp = i == 0 ? -mp : mp;
|
||||
/* Process attributes */
|
||||
if (vipParseEye(&wttr, &ettr, i))
|
||||
continue;
|
||||
|
||||
/* Draw all rows */
|
||||
for (y = top, param = params; y <= bottom; y++) {
|
||||
for (y = wttr.top, param = wttr.params; y <= wttr.bottom; y++) {
|
||||
|
||||
/* Parse line parameters */
|
||||
switch (bgm) {
|
||||
hofst = 0;
|
||||
mp = wttr.mp;
|
||||
mx = wttr.mx;
|
||||
my = wttr.my;
|
||||
switch (wttr.bgm) {
|
||||
case 1: /* H-bias */
|
||||
hofst = SignExtend(vipParam(param | i << 1), 13);
|
||||
param += 4;
|
||||
|
@ -813,22 +853,22 @@ static void vipDrawWorld(VB *sim, uint8_t *world, uint16_t attr) {
|
|||
dx = (int32_t) (int16_t) vipParam(param|6) << 7;
|
||||
dy = (int32_t) (int16_t) vipParam(param|8) << 7;
|
||||
mp = (int32_t) (int16_t) vipParam(param|2);
|
||||
mp = left - wx - ((mp < 0) ^ i ? mp : 0);
|
||||
mp = ettr.left - ettr.wx - ((mp < 0) ^ i ? mp : 0);
|
||||
mx = ((int32_t) (int16_t) vipParam(param ) << 13) + dx*mp;
|
||||
my = ((int32_t) (int16_t) vipParam(param|4) << 13) + dy*mp;
|
||||
param += 16;
|
||||
}
|
||||
|
||||
/* Select output in shadow memory */
|
||||
dest = &sim->vip.shadow[i][left * 224 + y];
|
||||
dest = &sim->vip.shadow[i][ettr.left * 224 + y];
|
||||
|
||||
/* Draw all columns */
|
||||
for (x = left; x <= right; x++, dest += 224) {
|
||||
for (x = ettr.left; x <= ettr.right; x++, dest += 224) {
|
||||
|
||||
/* Locate the pixel in the background */
|
||||
if (bgm != 2) { /* Normal, H-bias */
|
||||
cx = x - wx + mx + bp + hofst;
|
||||
cy = y - gy + my;
|
||||
if (wttr.bgm != 2) { /* Normal, H-bias */
|
||||
cx = x - ettr.wx + mx + ettr.bp + hofst;
|
||||
cy = y - wttr.gy + my;
|
||||
} else { /* Affine */
|
||||
cx = (int16_t) (mx >> 16);
|
||||
cy = (int16_t) (my >> 16);
|
||||
|
@ -842,22 +882,23 @@ static void vipDrawWorld(VB *sim, uint8_t *world, uint16_t attr) {
|
|||
cell = NULL;
|
||||
|
||||
/* BG map is out of bounds */
|
||||
if (bx < 0 || bx > bgw || by < 0 || by > bgh) {
|
||||
if (over == NULL) {
|
||||
bx &= bgw;
|
||||
by &= bgh;
|
||||
}
|
||||
else {
|
||||
cell = over;
|
||||
if (
|
||||
bx < 0 || bx > wttr.bgw ||
|
||||
by < 0 || by > wttr.bgh
|
||||
) {
|
||||
if (wttr.over)
|
||||
continue; /* TODO: Research overplane */
|
||||
}
|
||||
bx &= wttr.bgw;
|
||||
by &= wttr.bgh;
|
||||
}
|
||||
|
||||
/* Locate the cell in the BG map */
|
||||
if (cell == NULL) {
|
||||
cell = &sim->vip.ram[
|
||||
0x20000 |
|
||||
(base + bg[by << scx | bx]) << 13 |
|
||||
0x20000 | ((
|
||||
wttr.base +
|
||||
wttr.bg[by << wttr.scx | bx]
|
||||
) << 13) |
|
||||
(cy << 4 & 0x1F80) |
|
||||
(cx >> 2 & 0x007E)
|
||||
];
|
||||
|
|
Loading…
Reference in New Issue