Establish drawing procedure
This commit is contained in:
parent
7a8cf8952a
commit
3c2c9bb938
39
core/vb.c
39
core/vb.c
|
@ -126,13 +126,20 @@ struct VB {
|
|||
|
||||
/* Pixel processor */
|
||||
struct {
|
||||
uint8_t f0bsy; /* Drawing into frame buffer 0 */
|
||||
uint8_t f1bsy; /* Drawing into frame buffer 1 */
|
||||
uint8_t overtime; /* Drawing extends into display interval */
|
||||
uint8_t sbcmp; /* Vertical output position compare */
|
||||
uint8_t sbcount; /* Current vertical output position */
|
||||
uint8_t sbout; /* Drawing specified vertical output position */
|
||||
uint8_t xpen; /* Drawing enabled */
|
||||
/* Hardware state */
|
||||
uint8_t f0bsy; /* Drawing into frame buffer 0 */
|
||||
uint8_t f1bsy; /* Drawing into frame buffer 1 */
|
||||
uint8_t overtime; /* Drawing extends into display interval */
|
||||
uint8_t sbcmp; /* Vertical output position compare */
|
||||
uint8_t sbcount; /* Current vertical output position */
|
||||
uint32_t sbout; /* Drawing specified vertical output position */
|
||||
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;
|
||||
|
||||
/* Control state */
|
||||
|
@ -146,10 +153,10 @@ struct VB {
|
|||
uint16_t spt[4]; /* Object control */
|
||||
|
||||
/* 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 */
|
||||
uint8_t ram[0x40000]; /* Video memory */
|
||||
uint8_t ram[0x40000]; /* Video memory */
|
||||
} vip;
|
||||
|
||||
/* Other state */
|
||||
|
@ -352,13 +359,13 @@ VBAPI vbOnWrite vbGetWriteCallback(VB *sim) {
|
|||
|
||||
/* Initialize a simulation instance */
|
||||
VBAPI VB* vbInit(VB *sim) {
|
||||
sim->cart.ram = NULL;
|
||||
sim->cart.rom = NULL;
|
||||
sim->onExecute = NULL;
|
||||
sim->onFetch = NULL;
|
||||
sim->onFrame = NULL;
|
||||
sim->onRead = NULL;
|
||||
sim->onWrite = NULL;
|
||||
sim->cart.ram = NULL;
|
||||
sim->cart.rom = NULL;
|
||||
sim->onExecute = NULL;
|
||||
sim->onFetch = NULL;
|
||||
sim->onFrame = NULL;
|
||||
sim->onRead = NULL;
|
||||
sim->onWrite = NULL;
|
||||
vbReset(sim);
|
||||
return sim;
|
||||
}
|
||||
|
|
242
core/vip.c
242
core/vip.c
|
@ -12,23 +12,6 @@
|
|||
|
||||
/***************************** 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 */
|
||||
static int32_t vipReadPalette(uint8_t *entries) {
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
static void vipWritePalette(uint8_t *entries, int32_t mask, int32_t value) {
|
||||
if (mask & 0x00FF)
|
||||
|
@ -157,7 +104,7 @@ static int32_t vipReadIO(VB *sim, uint32_t address, int type) {
|
|||
|
||||
case 0x5F840>>1: /* XPSTTS */
|
||||
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.overtime << 4 |
|
||||
(int32_t) sim->vip.xp.f1bsy << 3 |
|
||||
|
@ -378,6 +325,59 @@ static int vipOnFrame(VB *sim) {
|
|||
|
||||
/***************************** 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 */
|
||||
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.until = vipClocksMs(8);
|
||||
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;
|
||||
|
||||
/* 0ms-3ms - Idle */
|
||||
|
@ -500,10 +518,55 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
|
|||
|
||||
/****************************** Pixel Processor ******************************/
|
||||
|
||||
/* Draw every world into a group of 8 rows of pixels */
|
||||
static void vipDrawWorlds(VB *sim) {
|
||||
(void) sim;
|
||||
}
|
||||
|
||||
/* Process sub-component */
|
||||
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 */
|
||||
static int vipEmulate(VB *sim, uint32_t clocks) {
|
||||
|
||||
/* Process sub-components */
|
||||
int brk = vipEmulateDisplay(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;
|
||||
}
|
||||
|
||||
|
@ -552,33 +625,20 @@ static void vipReset(VB *sim) {
|
|||
int x, y; /* Iterators */
|
||||
|
||||
/* Normal */
|
||||
sim->vip.intenb = 0x0000;
|
||||
sim->vip.dp.disp = 0;
|
||||
sim->vip.dp.re = 0;
|
||||
sim->vip.dp.synce = 0;
|
||||
sim->vip.intenb = 0x0000;
|
||||
sim->vip.xp.xpen = 0;
|
||||
|
||||
/* Extra (the hardware does not do this) */
|
||||
for (x = 0; x < 0x80000; x++)
|
||||
sim->vip.bkcol = 0;
|
||||
sim->vip.cta.cta_l = 0xFA;
|
||||
sim->vip.cta.cta_r = 0xFA;
|
||||
sim->vip.frmcyc = 0;
|
||||
sim->vip.intpnd = 0x0000;
|
||||
for (x = 0; x < 0x40000; x++)
|
||||
sim->vip.ram[x] = 0;
|
||||
sim->vip.bkcol = 0;
|
||||
sim->vip.cta.cta_l = 0xFA;
|
||||
sim->vip.cta.cta_r = 0xFA;
|
||||
sim->vip.frmcyc = 0;
|
||||
sim->vip.intpnd = 0x0000;
|
||||
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;
|
||||
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++) {
|
||||
sim->vip.brtRest[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.buffer = 0; /* TODO: Hardware might actually do this */
|
||||
sim->vip.dp.clocks = 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 */
|
||||
|
|
8
makefile
8
makefile
|
@ -27,8 +27,8 @@ core:
|
|||
-Werror -std=c90 -Wall -Wextra -Wpedantic \
|
||||
-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_FETCH=testFetch -D VB_DIRECT_READ=testRead \
|
||||
-D VB_DIRECT_WRITE=testWrite
|
||||
-D VB_DIRECT_FETCH=testFetch -D VB_DIRECT_FRAME=testFrame \
|
||||
-D VB_DIRECT_WRITE=testWrite -D VB_DIRECT_READ=testRead
|
||||
# Clang generic
|
||||
@emcc core/vb.c -I core -c -o /dev/null \
|
||||
-Werror -std=c90 -Wall -Wextra -Wpedantic
|
||||
|
@ -37,8 +37,8 @@ core:
|
|||
-Werror -std=c90 -Wall -Wextra -Wpedantic \
|
||||
-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_FETCH=testFetch -D VB_DIRECT_READ=testRead \
|
||||
-D VB_DIRECT_WRITE=testWrite
|
||||
-D VB_DIRECT_FETCH=testFetch -D VB_DIRECT_FRAME=testFrame \
|
||||
-D VB_DIRECT_WRITE=testWrite -D VB_DIRECT_READ=testRead
|
||||
|
||||
.PHONY: wasm
|
||||
wasm:
|
||||
|
|
Loading…
Reference in New Issue