Establish drawing procedure

This commit is contained in:
Guy Perfect 2024-10-16 20:14:38 -05:00
parent 7a8cf8952a
commit 3c2c9bb938
3 changed files with 190 additions and 99 deletions

View File

@ -126,13 +126,20 @@ struct VB {
/* Pixel processor */ /* Pixel processor */
struct { struct {
/* Hardware state */
uint8_t f0bsy; /* Drawing into frame buffer 0 */ uint8_t f0bsy; /* Drawing into frame buffer 0 */
uint8_t f1bsy; /* Drawing into frame buffer 1 */ uint8_t f1bsy; /* Drawing into frame buffer 1 */
uint8_t overtime; /* Drawing extends into display interval */ uint8_t overtime; /* Drawing extends into display interval */
uint8_t sbcmp; /* Vertical output position compare */ uint8_t sbcmp; /* Vertical output position compare */
uint8_t sbcount; /* Current vertical output position */ uint8_t sbcount; /* Current vertical output position */
uint8_t sbout; /* Drawing specified vertical output position */ uint32_t sbout; /* Drawing specified vertical output position */
uint8_t xpen; /* Drawing enabled */ uint8_t xpen; /* Drawing enabled */
/* Simulation state */
uint32_t clocks; /* Master clocks to wait */
int frame; /* FRMCYC counter */
int step; /* Processing phase */
uint32_t until; /* Clocks until interrupt condition */
} xp; } xp;
/* Control state */ /* Control state */
@ -146,7 +153,7 @@ struct VB {
uint16_t spt[4]; /* Object control */ uint16_t spt[4]; /* Object control */
/* Output frame buffers [buffer index][0=left, 1=right][pixel index] */ /* Output frame buffers [buffer index][0=left, 1=right][pixel index] */
uint8_t frames[2][2][384 * 224]; uint8_t frames[2][2][384*224];
/* Other state */ /* Other state */
uint8_t ram[0x40000]; /* Video memory */ uint8_t ram[0x40000]; /* Video memory */

View File

@ -12,23 +12,6 @@
/***************************** Module Functions ******************************/ /***************************** Module Functions ******************************/
/* Precompute brightness values for image output */
static void vipComputeBrightness(VB *sim) {
int32_t brt[4]; /* Working output */
int32_t repeat; /* Multiplier from column table */
int x; /* Iterator */
/* Compute brightness from hardware state */
repeat = (int32_t) sim->vip.ram[sim->vip.dp.cta + 1] + 1;
brt[1] = repeat * sim->vip.brtRest[0];
brt[2] = repeat * sim->vip.brtRest[1];
brt[3] = repeat * sim->vip.brtRest[2] + brt[2] + brt[1];
/* Scale brightness values to 0..255 */
for (x = 1; x < 4; x++)
sim->vip.dp.brt[x] = ((brt[x] > 127 ? 127 : brt[x]) * 510 + 127) / 254;
}
/* Read a palette */ /* Read a palette */
static int32_t vipReadPalette(uint8_t *entries) { static int32_t vipReadPalette(uint8_t *entries) {
return entries[3] << 6 | entries[2] << 4 | entries[1] << 2; return entries[3] << 6 | entries[2] << 4 | entries[1] << 2;
@ -42,42 +25,6 @@ static void vipThrow(VB *sim, uint16_t cause) {
sim->cpu.irq |= 0x0010; sim->cpu.irq |= 0x0010;
} }
/* Transfer one column of frame buffer pixels to output */
static void vipTransferColumn(VB *sim, int32_t eye) {
int32_t bits; /* Pixel bits from frame buffer */
uint8_t *dest; /* Host frame image output */
uint8_t *src; /* Simulation frame buffer input */
int y, z; /* Iterators */
/* Select destination address in host memory */
dest = &sim->vip.frames
[sim->vip.dp.buffer][eye][sim->vip.dp.column];
/* Output is disabled */
if ((sim->vip.dp.disp & sim->vip.dp.synce) == 0) {
for (z = 0; z < 0x15000; z += 4) {
busWriteBuffer(dest, VB_S32, 0);
dest += 4;
}
return;
}
/* Select source address in host memory */
src = &sim->vip.ram[
eye << 16 |
sim->vip.dp.buffer << 15 |
sim->vip.dp.column << 6
];
/* Transfer all rows as words */
for (y = 0; y < 224; y += 4) {
bits = busReadBuffer(src, VB_S32);
for (z = 0; z < 1536; z += 384, bits >>= 2)
dest[z] = sim->vip.dp.brt[bits & 3];
}
}
/* Write a palette */ /* Write a palette */
static void vipWritePalette(uint8_t *entries, int32_t mask, int32_t value) { static void vipWritePalette(uint8_t *entries, int32_t mask, int32_t value) {
if (mask & 0x00FF) if (mask & 0x00FF)
@ -157,7 +104,7 @@ static int32_t vipReadIO(VB *sim, uint32_t address, int type) {
case 0x5F840>>1: /* XPSTTS */ case 0x5F840>>1: /* XPSTTS */
value = value =
(int32_t) sim->vip.xp.sbout << 15 | (int32_t) !!sim->vip.xp.sbout << 15 |
(int32_t) sim->vip.xp.sbcount << 8 | (int32_t) sim->vip.xp.sbcount << 8 |
(int32_t) sim->vip.xp.overtime << 4 | (int32_t) sim->vip.xp.overtime << 4 |
(int32_t) sim->vip.xp.f1bsy << 3 | (int32_t) sim->vip.xp.f1bsy << 3 |
@ -378,6 +325,59 @@ static int vipOnFrame(VB *sim) {
/***************************** Display Processor *****************************/ /***************************** Display Processor *****************************/
/* Precompute brightness values for image output */
static void vipComputeBrightness(VB *sim) {
int32_t brt[4]; /* Working output */
int32_t repeat; /* Multiplier from column table */
int x; /* Iterator */
/* Compute brightness from hardware state */
repeat = (int32_t) sim->vip.ram[sim->vip.dp.cta + 1] + 1;
brt[1] = repeat * sim->vip.brtRest[0];
brt[2] = repeat * sim->vip.brtRest[1];
brt[3] = repeat * sim->vip.brtRest[2] + brt[2] + brt[1];
/* Scale brightness values to 0..255 */
for (x = 1; x < 4; x++)
sim->vip.dp.brt[x] = ((brt[x] > 127 ? 127 : brt[x]) * 510 + 127) / 254;
}
/* Transfer one column of frame buffer pixels to output */
static void vipTransferColumn(VB *sim, int32_t eye) {
int32_t bits; /* Pixel bits from frame buffer */
uint8_t *dest; /* Host frame image output */
uint8_t *src; /* Simulation frame buffer input */
int y, z; /* Iterators */
/* Select destination address in host memory */
dest = &sim->vip.frames
[sim->vip.dp.buffer][eye][sim->vip.dp.column];
/* Output is disabled */
if ((sim->vip.dp.disp & sim->vip.dp.synce) == 0) {
for (z = 0; z < 0x15000; z += 4) {
busWriteBuffer(dest, VB_S32, 0);
dest += 4;
}
return;
}
/* Select source address in host memory */
src = &sim->vip.ram[
eye << 16 |
sim->vip.dp.buffer << 15 |
sim->vip.dp.column << 6
];
/* Transfer all rows as words */
for (y = 0; y < 224; y += 16, src += 4) {
bits = busReadBuffer(src, VB_S32);
for (z = 0; z < 16; bits >>= 2, z++, dest += 384)
*dest = sim->vip.dp.brt[bits & 3];
}
}
/* Process sub-component */ /* Process sub-component */
static int vipEmulateDisplay(VB *sim, uint32_t clocks) { static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
@ -405,8 +405,26 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
sim->vip.dp.step = 1; sim->vip.dp.step = 1;
sim->vip.dp.until = vipClocksMs(8); sim->vip.dp.until = vipClocksMs(8);
vipThrow(sim, 0x0010); /* FRAMESTART */ vipThrow(sim, 0x0010); /* FRAMESTART */
/* TODO: Initiate drawing, throw GAMESTART */
/* ELSE: Set OVERTIME, throw TIMEERR */ /* Game frame */
if (sim->vip.xp.frame >= sim->vip.frmcyc) {
sim->vip.xp.frame = 0;
/* Initiate drawing procedure */
if (sim->vip.xp.step == 0) {
sim->vip.xp.overtime = 0;
sim->vip.xp.step = 1;
vipThrow(sim, 0x0008); /* GAMESTART */
}
/* Drawing procedure has run into overtime */
else {
sim->vip.xp.overtime = 1;
vipThrow(sim, 0x8000); /* TIMEERR */
}
} else sim->vip.xp.frame++;
break; break;
/* 0ms-3ms - Idle */ /* 0ms-3ms - Idle */
@ -500,10 +518,55 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
/****************************** Pixel Processor ******************************/ /****************************** Pixel Processor ******************************/
/* Draw every world into a group of 8 rows of pixels */
static void vipDrawWorlds(VB *sim) {
(void) sim;
}
/* Process sub-component */ /* Process sub-component */
static void vipEmulateDrawing(VB *sim, uint32_t clocks) { static void vipEmulateDrawing(VB *sim, uint32_t clocks) {
(void) sim;
(void) clocks; /* Process all clocks */
for (;;) {
/* The next event is after the time remaining */
if (sim->vip.xp.clocks > clocks) {
sim->vip.xp.clocks -= clocks;
sim->vip.xp.until -= clocks;
return;
}
/* Advance forward the component's number of clocks */
clocks -= sim->vip.xp.clocks;
sim->vip.xp.until -= sim->vip.xp.clocks;
sim->vip.xp.clocks = 0;
/* Processing by operation phase */
switch (sim->vip.xp.step) {
case 1: /* Initialize */
sim->vip.xp.sbcount = 0;
/* Fallthrough */
case 2: /* Transition to a new row of halfwords */
sim->vip.xp.sbout = 2240; /* 112us */
sim->vip.xp.step = 3;
if (sim->vip.xp.sbcount == sim->vip.xp.sbcmp)
vipThrow(sim, 0x2000); /* SBHIT */
break;
case 3: /* Draw halfwords */
vipDrawWorlds(sim);
sim->vip.xp.until = 2000; /* 100us */
break;
case 4: /* Finalize */
sim->vip.xp.step = 0;
vipThrow(sim, 0x4000); /* XPEND */
}
}
} }
@ -512,8 +575,18 @@ static void vipEmulateDrawing(VB *sim, uint32_t clocks) {
/* Process component */ /* Process component */
static int vipEmulate(VB *sim, uint32_t clocks) { static int vipEmulate(VB *sim, uint32_t clocks) {
/* Process sub-components */
int brk = vipEmulateDisplay(sim, clocks); int brk = vipEmulateDisplay(sim, clocks);
vipEmulateDrawing(sim, clocks); vipEmulateDrawing(sim, clocks);
/* Process SBOUT */
if (sim->vip.xp.sbout != 0) {
if (sim->vip.xp.sbout <= clocks) {
sim->vip.xp.sbout = 0;
} else sim->vip.xp.sbout -= clocks;
}
return brk; return brk;
} }
@ -552,33 +625,20 @@ static void vipReset(VB *sim) {
int x, y; /* Iterators */ int x, y; /* Iterators */
/* Normal */ /* Normal */
sim->vip.intenb = 0x0000;
sim->vip.dp.disp = 0; sim->vip.dp.disp = 0;
sim->vip.dp.re = 0; sim->vip.dp.re = 0;
sim->vip.dp.synce = 0; sim->vip.dp.synce = 0;
sim->vip.intenb = 0x0000;
sim->vip.xp.xpen = 0; sim->vip.xp.xpen = 0;
/* Extra (the hardware does not do this) */ /* Extra (the hardware does not do this) */
for (x = 0; x < 0x80000; x++)
sim->vip.ram[x] = 0;
sim->vip.bkcol = 0; sim->vip.bkcol = 0;
sim->vip.cta.cta_l = 0xFA; sim->vip.cta.cta_l = 0xFA;
sim->vip.cta.cta_r = 0xFA; sim->vip.cta.cta_r = 0xFA;
sim->vip.frmcyc = 0; sim->vip.frmcyc = 0;
sim->vip.intpnd = 0x0000; sim->vip.intpnd = 0x0000;
sim->vip.dp.fclk = 0; for (x = 0; x < 0x40000; x++)
sim->vip.dp.l0bsy = 0; sim->vip.ram[x] = 0;
sim->vip.dp.l1bsy = 0;
sim->vip.dp.lock = 0;
sim->vip.dp.r0bsy = 0;
sim->vip.dp.r1bsy = 0;
sim->vip.dp.scanrdy = 0;
sim->vip.xp.f0bsy = 0;
sim->vip.xp.f1bsy = 0;
sim->vip.xp.overtime = 0;
sim->vip.xp.sbcmp = 0;
sim->vip.xp.sbcount = 0;
sim->vip.xp.sbout = 0;
for (x = 0; x < 4; x++) { for (x = 0; x < 4; x++) {
sim->vip.brtRest[x] = 0; sim->vip.brtRest[x] = 0;
sim->vip.spt [x] = 0; sim->vip.spt [x] = 0;
@ -588,10 +648,34 @@ static void vipReset(VB *sim) {
} }
} }
/* Other */ /* Display processor extra (the hardware does not do this) */
sim->vip.dp.fclk = 0;
sim->vip.dp.l0bsy = 0;
sim->vip.dp.l1bsy = 0;
sim->vip.dp.lock = 0;
sim->vip.dp.r0bsy = 0;
sim->vip.dp.r1bsy = 0;
sim->vip.dp.scanrdy = 0;
/* Pixel processor extra (the hardware does not do this) */
sim->vip.xp.f0bsy = 0;
sim->vip.xp.f1bsy = 0;
sim->vip.xp.overtime = 0;
sim->vip.xp.sbcmp = 0;
sim->vip.xp.sbcount = 0;
sim->vip.xp.sbout = 0;
/* Display processor other */
sim->vip.dp.brt[0] = 0; sim->vip.dp.brt[0] = 0;
sim->vip.dp.buffer = 0; /* TODO: Hardware might actually do this */
sim->vip.dp.clocks = 0; sim->vip.dp.clocks = 0;
sim->vip.dp.step = 0; sim->vip.dp.step = 0;
sim->vip.dp.until = 0;
/* Pixel processor other */
sim->vip.xp.clocks = 0;
sim->vip.xp.step = 0;
sim->vip.xp.until = 0;
} }
/* Determine how many clocks are guaranteed to process */ /* Determine how many clocks are guaranteed to process */

View File

@ -27,8 +27,8 @@ core:
-Werror -std=c90 -Wall -Wextra -Wpedantic \ -Werror -std=c90 -Wall -Wextra -Wpedantic \
-D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC \ -D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC \
-D VB_DIRECT_EXCEPTION=textException -D VB_DIRECT_EXECUTE=textExecute \ -D VB_DIRECT_EXCEPTION=textException -D VB_DIRECT_EXECUTE=textExecute \
-D VB_DIRECT_FETCH=testFetch -D VB_DIRECT_READ=testRead \ -D VB_DIRECT_FETCH=testFetch -D VB_DIRECT_FRAME=testFrame \
-D VB_DIRECT_WRITE=testWrite -D VB_DIRECT_WRITE=testWrite -D VB_DIRECT_READ=testRead
# Clang generic # Clang generic
@emcc core/vb.c -I core -c -o /dev/null \ @emcc core/vb.c -I core -c -o /dev/null \
-Werror -std=c90 -Wall -Wextra -Wpedantic -Werror -std=c90 -Wall -Wextra -Wpedantic
@ -37,8 +37,8 @@ core:
-Werror -std=c90 -Wall -Wextra -Wpedantic \ -Werror -std=c90 -Wall -Wextra -Wpedantic \
-D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC \ -D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC \
-D VB_DIRECT_EXCEPTION=textException -D VB_DIRECT_EXECUTE=textExecute \ -D VB_DIRECT_EXCEPTION=textException -D VB_DIRECT_EXECUTE=textExecute \
-D VB_DIRECT_FETCH=testFetch -D VB_DIRECT_READ=testRead \ -D VB_DIRECT_FETCH=testFetch -D VB_DIRECT_FRAME=testFrame \
-D VB_DIRECT_WRITE=testWrite -D VB_DIRECT_WRITE=testWrite -D VB_DIRECT_READ=testRead
.PHONY: wasm .PHONY: wasm
wasm: wasm: