Establish display processing

This commit is contained in:
2024-10-16 16:15:39 -05:00
parent c91eb0785f
commit 448658430c
4 changed files with 305 additions and 96 deletions
+244 -59
View File
@@ -3,13 +3,68 @@
/********************************** Macros ***********************************/
/* Compute how many clocks are in some number of milliseconds */
#define vipClocksMs(x) x * 20000
/***************************** 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;
}
/* Raise an interrupt request */
static void vipThrow(VB *sim, uint16_t cause) {
if (!(sim->vip.intenb & cause))
return;
sim->vip.intpnd |= 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 */
int y, z; /* Iterators */
/* Select source and destination addresses in host memory */
uint8_t *dest = &sim->vip.frames
[sim->vip.dp.buffer][eye][sim->vip.dp.column];
uint8_t *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)
@@ -21,7 +76,7 @@ static void vipWritePalette(uint8_t *entries, int32_t mask, int32_t value) {
/* Read a typed value from an I/O register */
static int32_t vipReadIO(VB *sim, uint32_t address, int type) {
int mask; /* Byte access mask */
int32_t mask; /* Byte access mask */
int32_t value; /* Return value */
/* Adjustments by type */
@@ -53,16 +108,16 @@ static int32_t vipReadIO(VB *sim, uint32_t address, int type) {
case 0x5F820>>1: /* DPSTTS */
value =
(int32_t) sim->vip.dpctrl.lock << 10 |
(int32_t) sim->vip.dpctrl.synce << 9 |
(int32_t) sim->vip.dpctrl.re << 8 |
(int32_t) sim->vip.dpctrl.fclk << 7 |
(int32_t) sim->vip.dpctrl.scanrdy << 6 |
(int32_t) sim->vip.dpctrl.r1bsy << 5 |
(int32_t) sim->vip.dpctrl.l1bsy << 4 |
(int32_t) sim->vip.dpctrl.r0bsy << 3 |
(int32_t) sim->vip.dpctrl.l0bsy << 2 |
(int32_t) sim->vip.dpctrl.disp << 1
(int32_t) sim->vip.dp.lock << 10 |
(int32_t) sim->vip.dp.synce << 9 |
(int32_t) sim->vip.dp.re << 8 |
(int32_t) sim->vip.dp.fclk << 7 |
(int32_t) sim->vip.dp.scanrdy << 6 |
(int32_t) sim->vip.dp.r1bsy << 5 |
(int32_t) sim->vip.dp.l1bsy << 4 |
(int32_t) sim->vip.dp.r0bsy << 3 |
(int32_t) sim->vip.dp.l0bsy << 2 |
(int32_t) sim->vip.dp.disp << 1
;
break;
@@ -89,12 +144,12 @@ static int32_t vipReadIO(VB *sim, uint32_t address, int type) {
case 0x5F840>>1: /* XPSTTS */
value =
(int32_t) sim->vip.xpctrl.sbout << 15 |
(int32_t) sim->vip.xpctrl.sbcount << 8 |
(int32_t) sim->vip.xpctrl.overtime << 4 |
(int32_t) sim->vip.xpctrl.f1bsy << 3 |
(int32_t) sim->vip.xpctrl.f0bsy << 2 |
(int32_t) sim->vip.xpctrl.xpen << 1
(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 |
(int32_t) sim->vip.xp.f0bsy << 2 |
(int32_t) sim->vip.xp.xpen << 1
;
break;
@@ -158,7 +213,7 @@ static int32_t vipReadIO(VB *sim, uint32_t address, int type) {
/* Write a typed value to an I/O register */
static void vipWriteIO(
VB *sim, uint32_t address, int type, int32_t value, int debug) {
int mask; /* Byte access mask */
int32_t mask; /* Byte access mask */
/* Adjustments by type */
switch (type) {
@@ -202,12 +257,12 @@ static void vipWriteIO(
case 0x5F822>>1: /* DPCTRL */
if ((mask & 0xFF00) == 0) {
sim->vip.dpctrl.lock = value >> 10 & 1;
sim->vip.dpctrl.synce = value >> 9 & 1;
sim->vip.dpctrl.re = value >> 8 & 1;
sim->vip.dp.lock = value >> 10 & 1;
sim->vip.dp.synce = value >> 9 & 1;
sim->vip.dp.re = value >> 8 & 1;
}
if ((mask & 0x00FF) == 0) {
sim->vip.dpctrl.disp = value >> 1 & 1;
sim->vip.dp.disp = value >> 1 & 1;
/* if (value & 1) {} TODO: DPRST */
}
break;
@@ -238,9 +293,9 @@ static void vipWriteIO(
case 0x5F842>>1: /* XPCTRL */
if ((mask & 0xFF00) == 0)
sim->vip.xpctrl.sbcmp = value >> 8 & 31;
sim->vip.xp.sbcmp = value >> 8 & 31;
if ((mask & 0x00FF) == 0) {
sim->vip.xpctrl.xpen = value >> 1 & 1;
sim->vip.xp.xpen = value >> 1 & 1;
/* if (value & 1) TODO: XPRST */
}
break;
@@ -292,13 +347,138 @@ static void vipWriteIO(
/***************************** Callback Handlers *****************************/
/* Prepare to handle an exception */
#ifndef VB_DIRECT_FRAME
#define VB_ON_FRAME sim->onFrame
#else
extern int VB_DIRECT_FRAME(VB *);
#define VB_ON_FRAME VB_DIRECT_FRAME
#endif
static int vipOnFrame(VB *sim) {
return sim->onFrame != NULL && VB_ON_FRAME(sim);
}
#undef VB_ON_FRAME
/***************************** Library Functions *****************************/
/* Display processor */
static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
/* Process all clocks */
while (clocks != 0) {
/* The next event is after the time remaining */
if (sim->vip.dp.clocks > clocks) {
sim->vip.dp.clocks -= clocks;
return 0;
}
/* Advance forward the component's number of clocks */
clocks -= sim->vip.dp.clocks;
sim->vip.dp.clocks = 0;
/* Processing by operation phase */
switch (sim->vip.dp.step) {
case 0: /* 0ms - FCLK rising edge */
sim->vip.dp.clocks = vipClocksMs(3);
sim->vip.dp.fclk = 1;
sim->vip.dp.step = 1;
vipThrow(sim, 0x0010); /* FRAMESTART */
/* TODO: Initiate drawing, throw GAMESTART */
/* ELSE: Set OVERTIME, throw TIMEERR */
break;
/* 0ms-3ms - Idle */
case 1: /* 3ms - L*BSY rising edge */
if (sim->vip.dp.buffer == 0)
sim->vip.dp.l0bsy = 1;
else sim->vip.dp.l1bsy = 1;
sim->vip.dp.column = 0;
sim->vip.dp.cta = 0x3DC00 | (uint32_t)sim->vip.cta.cta_l<<1;
sim->vip.dp.step = 2;
vipComputeBrightness(sim);
/* Fallthrough */
case 2: /* 3ms-8ms - Display left frame buffer */
if ((sim->vip.dp.column & 3) == 0)
vipComputeBrightness(sim);
vipTransferColumn(sim, 0);
sim->vip.dp.clocks =
260 + (0xA94 >> sim->vip.dp.column % 12 & 1);
sim->vip.dp.column++;
if ((sim->vip.dp.column & 3) == 0)
sim->vip.dp.cta -= 2;
if (sim->vip.dp.column == 384)
sim->vip.dp.step = 3;
break;
case 3: /* 8ms - L*BSY falling edge */
if (sim->vip.dp.buffer == 0)
sim->vip.dp.l0bsy = 0;
else sim->vip.dp.l1bsy = 0;
sim->vip.dp.clocks = vipClocksMs(2);
sim->vip.dp.step = 4;
vipThrow(sim, 0x0002); /* LFBEND */
break;
/* 8ms-10ms - Idle */
case 4: /* 10ms - FCLK falling edge */
sim->vip.dp.clocks = vipClocksMs(3);
sim->vip.dp.fclk = 0;
sim->vip.dp.step = 5;
break;
/* 10ms-13ms - Idle */
case 5: /* 13ms - R*BSY rising edge */
if (sim->vip.dp.buffer == 0)
sim->vip.dp.r0bsy = 1;
else sim->vip.dp.r1bsy = 1;
sim->vip.dp.column = 0;
sim->vip.dp.cta = 0x3DE00 | (uint32_t)sim->vip.cta.cta_r<<1;
sim->vip.dp.step = 6;
/* Fallthrough */
case 6: /* 13ms-18ms - Display right frame buffer */
vipTransferColumn(sim, 1);
sim->vip.dp.clocks =
260 + (0xA94 >> sim->vip.dp.column % 12 & 1);
sim->vip.dp.column++;
if (sim->vip.dp.column == 384)
sim->vip.dp.step = 7;
break;
case 7: /* 18ms - R*BSY falling edge */
if (sim->vip.dp.buffer == 0)
sim->vip.dp.r0bsy = 0;
else sim->vip.dp.r1bsy = 0;
sim->vip.dp.clocks = vipClocksMs(2);
sim->vip.dp.step = 0;
vipThrow(sim, 0x0004); /* RFBEND */
if (vipOnFrame(sim))
return 1;
break;
/* 18ms-20ms - Idle */
}
}
return 0;
}
/* Process component */
static int vipEmulate(VB *sim, uint32_t clocks) {
(void) sim;
(void) clocks;
return 0;
int brk = vipEmulateDisplay(sim, clocks);
/*vipEmulateDrawing(sim, clocks);*/
return brk;
}
/* Read a typed value from the VIP bus */
@@ -307,10 +487,9 @@ static void vipRead(VB *sim, uint32_t address, int type, int32_t *value) {
/* Working variables */
address &= 0x0007FFFF;
/* VRAM */
if (address < 0x40000) {
*value = busReadBuffer(&sim->vip.vram[address], type);
}
/* RAM */
if (address < 0x40000)
*value = busReadBuffer(&sim->vip.ram[address], type);
/* Unmapped */
else if (address < 0x5E000)
@@ -327,7 +506,7 @@ static void vipRead(VB *sim, uint32_t address, int type, int32_t *value) {
/* Mirrors of character memory */
else {
address = 0x06000 | (address << 2 & 0x18000) | (address & 0x01FFF);
*value = busReadBuffer(&sim->vip.vram[address], type);
*value = busReadBuffer(&sim->vip.ram[address], type);
}
}
@@ -337,31 +516,33 @@ static void vipReset(VB *sim) {
int x, y; /* Iterators */
/* Normal */
sim->vip.dpctrl.disp = 0;
sim->vip.dpctrl.re = 0;
sim->vip.dpctrl.synce = 0;
sim->vip.intenb = 0x0000;
sim->vip.xpctrl.xpen = 0;
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) */
sim->vip.bkcol = 0;
sim->vip.cta.cta_l = 0;
sim->vip.cta.cta_r = 0;
sim->vip.frmcyc = 0;
sim->vip.intpnd = 0x0000;
sim->vip.dpctrl.fclk = 0;
sim->vip.dpctrl.l0bsy = 0;
sim->vip.dpctrl.l1bsy = 0;
sim->vip.dpctrl.lock = 0;
sim->vip.dpctrl.r0bsy = 0;
sim->vip.dpctrl.r1bsy = 0;
sim->vip.dpctrl.scanrdy = 0;
sim->vip.xpctrl.f0bsy = 0;
sim->vip.xpctrl.f1bsy = 0;
sim->vip.xpctrl.overtime = 0;
sim->vip.xpctrl.sbcmp = 0;
sim->vip.xpctrl.sbcount = 0;
sim->vip.xpctrl.sbout = 0;
for (x = 0; x < 0x80000; 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;
@@ -371,24 +552,28 @@ static void vipReset(VB *sim) {
}
}
/* Other */
sim->vip.dp.brt[0] = 0;
sim->vip.dp.clocks = 0;
sim->vip.dp.step = 0;
}
/* Determine how many clocks are guaranteed to process */
static uint32_t vipUntil(VB *sim, uint32_t clocks) {
(void) sim;
/* Don't allow clocks to exceed interrupt conditions, even if disabled */
return clocks;
}
/* Write a typed value to the VIP bus */
static void vipWrite(VB*sim,uint32_t address,int type,int32_t value,int debug){
(void) debug;
/* Working variables */
address &= 0x0007FFFF;
/* VRAM */
/* RAM */
if (address < 0x40000)
busWriteBuffer(&sim->vip.vram[address], type, value);
busWriteBuffer(&sim->vip.ram[address], type, value);
/* Unmapped */
else if (address < 0x5E000)
@@ -405,7 +590,7 @@ static void vipWrite(VB*sim,uint32_t address,int type,int32_t value,int debug){
/* Mirrors of character memory */
else {
address = 0x06000 | (address << 2 & 0x18000) | (address & 0x01FFF);
busWriteBuffer(&sim->vip.vram[address], type, value);
busWriteBuffer(&sim->vip.ram[address], type, value);
}
}