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 ******************************/
|
/***************************** Module Functions ******************************/
|
||||||
|
|
||||||
/* Retrieve a pointer to character data in host memory */
|
/* Retrieve a pointer to character data in host memory */
|
||||||
|
@ -597,6 +623,88 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
|
||||||
|
|
||||||
/****************************** Pixel Processor ******************************/
|
/****************************** 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 */
|
/* Draw an object group into shadow memory */
|
||||||
static void vipDrawObjects(VB *sim, int group) {
|
static void vipDrawObjects(VB *sim, int group) {
|
||||||
uint8_t *dest; /* Pointer to object position in shadow memory */
|
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 */
|
/* Draw a background world into shadow memory */
|
||||||
static void vipDrawWorld(VB *sim, uint8_t *world, uint16_t attr) {
|
static void vipDrawWorld(VB *sim, uint8_t *world, uint16_t bits) {
|
||||||
uint8_t *bg; /* Background arrangement */
|
|
||||||
uint16_t bgAttr; /* BG map cell attributes */
|
uint16_t bgAttr; /* BG map cell attributes */
|
||||||
int32_t bgh; /* Height of background in BG maps, minus 1 */
|
int32_t bx; /* BG source X */
|
||||||
int32_t bgw; /* Width of background in BG maps, minus 1 */
|
int32_t by; /* BG source Y */
|
||||||
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 */
|
|
||||||
uint8_t *cell; /* Pointer to BG map cell in host memory */
|
uint8_t *cell; /* Pointer to BG map cell in host memory */
|
||||||
uint8_t *chr; /* Pointer to character data 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 cx; /* BG cell/character source X */
|
||||||
int32_t cy; /* BG cell/character vertical pixel source position */
|
int32_t cy; /* BG cell/character source Y */
|
||||||
uint8_t *dest; /* Pointer to output in shadow memory */
|
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 */
|
uint32_t param; /* Current line parameter address */
|
||||||
int8_t pixel; /* Character pixel value */
|
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 */
|
int32_t i, x, y; /* Iterators */
|
||||||
|
|
||||||
/* World attributes */
|
/* World attributes */
|
||||||
int32_t base; /* BG map base index */
|
WorldAttribs wttr; /* Common attributes */
|
||||||
int bgm; /* BG mode */
|
|
||||||
int32_t dx; /* Affine per-pixel X delta */
|
int32_t dx; /* Affine per-pixel X delta */
|
||||||
int32_t dy; /* Affine per-pixel Y delta */
|
int32_t dy; /* Affine per-pixel Y delta */
|
||||||
int16_t gp; /* Window stereo parallax */
|
int32_t mp; /* BG source parallax */
|
||||||
int16_t gx; /* Window base horizontal position */
|
int32_t mx; /* BG source X */
|
||||||
int16_t gy; /* Window vertical position */
|
int32_t my; /* BG source Y */
|
||||||
int16_t h; /* Window height */
|
|
||||||
int16_t hofst; /* H-bias shift */
|
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 */
|
/* Working variables */
|
||||||
gy = busReadBuffer(world + 6, VB_S16);
|
ettr.bp = wttr.mp = wttr.mx = wttr.my = wttr.params = 0;
|
||||||
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;
|
|
||||||
|
|
||||||
/* Parse attributes */
|
/* Parse attributes */
|
||||||
bg = (uint8_t *) BG_TEMPLATES[attr >> 8 & 15];
|
if (vipParseWorld(sim, world, bits, &wttr))
|
||||||
gx = SignExtend(busReadBuffer(world + 2, VB_U16), 10);
|
return; /* Window not in frame */
|
||||||
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;
|
|
||||||
|
|
||||||
/* Draw the world */
|
/* Draw the world */
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
|
|
||||||
/* Validate world is enabled */
|
/* World is not visible */
|
||||||
if ((attr & (int32_t) 0x8000 >> i) == 0) /* LON, RON */
|
if ((bits & (int32_t) 0x8000 >> i) == 0) /* LON, RON */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Validate the world isn't right of frame */
|
/* Process attributes */
|
||||||
wx = gx - (i == 0 ? gp : -gp);
|
if (vipParseEye(&wttr, &ettr, i))
|
||||||
if (wx > 383)
|
continue;
|
||||||
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;
|
|
||||||
|
|
||||||
/* Draw all rows */
|
/* 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 */
|
/* Parse line parameters */
|
||||||
switch (bgm) {
|
hofst = 0;
|
||||||
|
mp = wttr.mp;
|
||||||
|
mx = wttr.mx;
|
||||||
|
my = wttr.my;
|
||||||
|
switch (wttr.bgm) {
|
||||||
case 1: /* H-bias */
|
case 1: /* H-bias */
|
||||||
hofst = SignExtend(vipParam(param | i << 1), 13);
|
hofst = SignExtend(vipParam(param | i << 1), 13);
|
||||||
param += 4;
|
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;
|
dx = (int32_t) (int16_t) vipParam(param|6) << 7;
|
||||||
dy = (int32_t) (int16_t) vipParam(param|8) << 7;
|
dy = (int32_t) (int16_t) vipParam(param|8) << 7;
|
||||||
mp = (int32_t) (int16_t) vipParam(param|2);
|
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;
|
mx = ((int32_t) (int16_t) vipParam(param ) << 13) + dx*mp;
|
||||||
my = ((int32_t) (int16_t) vipParam(param|4) << 13) + dy*mp;
|
my = ((int32_t) (int16_t) vipParam(param|4) << 13) + dy*mp;
|
||||||
param += 16;
|
param += 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Select output in shadow memory */
|
/* 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 */
|
/* 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 */
|
/* Locate the pixel in the background */
|
||||||
if (bgm != 2) { /* Normal, H-bias */
|
if (wttr.bgm != 2) { /* Normal, H-bias */
|
||||||
cx = x - wx + mx + bp + hofst;
|
cx = x - ettr.wx + mx + ettr.bp + hofst;
|
||||||
cy = y - gy + my;
|
cy = y - wttr.gy + my;
|
||||||
} else { /* Affine */
|
} else { /* Affine */
|
||||||
cx = (int16_t) (mx >> 16);
|
cx = (int16_t) (mx >> 16);
|
||||||
cy = (int16_t) (my >> 16);
|
cy = (int16_t) (my >> 16);
|
||||||
|
@ -842,22 +882,23 @@ static void vipDrawWorld(VB *sim, uint8_t *world, uint16_t attr) {
|
||||||
cell = NULL;
|
cell = NULL;
|
||||||
|
|
||||||
/* BG map is out of bounds */
|
/* BG map is out of bounds */
|
||||||
if (bx < 0 || bx > bgw || by < 0 || by > bgh) {
|
if (
|
||||||
if (over == NULL) {
|
bx < 0 || bx > wttr.bgw ||
|
||||||
bx &= bgw;
|
by < 0 || by > wttr.bgh
|
||||||
by &= bgh;
|
) {
|
||||||
}
|
if (wttr.over)
|
||||||
else {
|
|
||||||
cell = over;
|
|
||||||
continue; /* TODO: Research overplane */
|
continue; /* TODO: Research overplane */
|
||||||
}
|
bx &= wttr.bgw;
|
||||||
|
by &= wttr.bgh;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Locate the cell in the BG map */
|
/* Locate the cell in the BG map */
|
||||||
if (cell == NULL) {
|
if (cell == NULL) {
|
||||||
cell = &sim->vip.ram[
|
cell = &sim->vip.ram[
|
||||||
0x20000 |
|
0x20000 | ((
|
||||||
(base + bg[by << scx | bx]) << 13 |
|
wttr.base +
|
||||||
|
wttr.bg[by << wttr.scx | bx]
|
||||||
|
) << 13) |
|
||||||
(cy << 4 & 0x1F80) |
|
(cy << 4 & 0x1F80) |
|
||||||
(cx >> 2 & 0x007E)
|
(cx >> 2 & 0x007E)
|
||||||
];
|
];
|
||||||
|
|
Loading…
Reference in New Issue