/* This file is included into vb.c and cannot be compiled on its own. */ #ifdef VBAPI /***************************** Module Functions ******************************/ /* Read a palette */ static int32_t vipReadPalette(uint8_t *entries) { return entries[3] << 6 | entries[2] << 4 | entries[1] << 2; } /* Write a palette */ static void vipWritePalette(uint8_t *entries, int32_t mask, int32_t value) { if (mask & 0x00FF) return; entries[3] = value >> 6 & 3; entries[2] = value >> 4 & 3; entries[1] = value >> 2 & 3; } /* 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 value; /* Return value */ /* Adjustments by type */ switch (type) { case VB_S32: /* Word */ return vipReadIO(sim, address, VB_U16) | (uint32_t) vipReadIO(sim, address + 2, VB_U16) << 16; case VB_S8: /* Byte */ case VB_U8: mask = 0x00FF << ((address & 1) << 3); break; case VB_S16: /* Halfword */ case VB_U16: mask = 0xFFFF; } /* Access by register */ switch (address >> 1) { case 0x5F800>>1: /* INTPND */ value = sim->vip.intpnd; break; case 0x5F802>>1: /* INTENB */ value = sim->vip.intenb; break; 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 ; break; case 0x5F824>>1: /* BRTA */ value = sim->vip.brtRest[0]; break; case 0x5F826>>1: /* BRTB */ value = sim->vip.brtRest[1]; break; case 0x5F828>>1: /* BRTC */ value = sim->vip.brtRest[2]; break; case 0x5F82A>>1: /* REST */ value = sim->vip.brtRest[3]; break; case 0x5F82E>>1: /* FRMCYC */ value = sim->vip.frmcyc; break; case 0x5F830>>1: /* CTA */ value = (int32_t) sim->vip.cta.cta_r << 8 | sim->vip.cta.cta_l; break; 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 ; break; case 0x5F844>>1: /* VER */ value = 2; break; case 0x5F848>>1: /* SPT0 */ value = sim->vip.spt[0]; break; case 0x5F84A>>1: /* SPT1 */ value = sim->vip.spt[1]; break; case 0x5F84C>>1: /* SPT2 */ value = sim->vip.spt[2]; break; case 0x5F84E>>1: /* SPT3 */ value = sim->vip.spt[3]; break; case 0x5F860>>1: /* GPLT0 */ value = vipReadPalette(sim->vip.gplt[0]); break; case 0x5F862>>1: /* GPLT1 */ value = vipReadPalette(sim->vip.gplt[1]); break; case 0x5F864>>1: /* GPLT2 */ value = vipReadPalette(sim->vip.gplt[2]); break; case 0x5F866>>1: /* GPLT3 */ value = vipReadPalette(sim->vip.gplt[3]); break; case 0x5F868>>1: /* JPLT0 */ value = vipReadPalette(sim->vip.jplt[0]); break; case 0x5F86A>>1: /* JPLT1 */ value = vipReadPalette(sim->vip.jplt[1]); break; case 0x5F86C>>1: /* JPLT2 */ value = vipReadPalette(sim->vip.jplt[2]); break; case 0x5F86E>>1: /* JPLT3 */ value = vipReadPalette(sim->vip.jplt[3]); break; case 0x5F870>>1: /* BKCOL */ value = sim->vip.bkcol; break; /* Unmapped */ default: value = 0; } /* Select byte bits as necessary */ return mask == 0x00FF ? value & 0x00FF : mask == 0xFF00 ? value >> 8 : value; } /* 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 */ /* Adjustments by type */ switch (type) { case VB_S32: /* Word */ vipWriteIO(sim, address , VB_U16, value , debug); vipWriteIO(sim, address + 2, VB_U16, value >> 16, debug); return; case VB_S8: /* Byte */ case VB_U8: /* Select which half of the register to access */ if (debug) { mask = (address & 1) << 3; value = (value & 0x00FF) << mask; mask = 0xFF00 >> mask; break; } /* Convert to a halfword access */ if ((address & 1) != 0) value = (value & 0x00FF) << 8; /* Fallthrough */ default: /* Halfword */ mask = 0x0000; } /* Access by register */ switch (address >> 1) { case 0x5F802>>1: /* INTENB */ sim->vip.intenb = (sim->vip.intenb & mask) | (value & 0xE01F); break; case 0x5F804>>1: /* INTCLR */ sim->vip.intpnd &= ~value; if (sim->vip.intpnd == 0) sim->cpu.irq &= ~0x0010; break; 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; } if ((mask & 0x00FF) == 0) { sim->vip.dpctrl.disp = value >> 1 & 1; /* if (value & 1) {} TODO: DPRST */ } break; case 0x5F824>>1: /* BRTA */ sim->vip.brtRest[0] = (sim->vip.brtRest[0] & mask) | value; break; case 0x5F826>>1: /* BRTB */ sim->vip.brtRest[1] = (sim->vip.brtRest[1] & mask) | value; break; case 0x5F828>>1: /* BRTC */ sim->vip.brtRest[2] = (sim->vip.brtRest[2] & mask) | value; break; case 0x5F82A>>1: /* REST */ sim->vip.brtRest[3] = (sim->vip.brtRest[3] & mask) | value; break; case 0x5F82E>>1: /* FRMCYC */ sim->vip.frmcyc = (sim->vip.frmcyc & mask) | (value & 15); break; case 0x5F830>>1: /* CTA */ if ((mask & 0xFF00) == 0) sim->vip.cta.cta_r = value >> 8; if ((mask & 0x00FF) == 0) sim->vip.cta.cta_l = value; break; case 0x5F842>>1: /* XPCTRL */ if ((mask & 0xFF00) == 0) sim->vip.xpctrl.sbcmp = value >> 8 & 31; if ((mask & 0x00FF) == 0) { sim->vip.xpctrl.xpen = value >> 1 & 1; /* if (value & 1) TODO: XPRST */ } break; case 0x5F848>>1: /* SPT0 */ sim->vip.spt[0] = (sim->vip.spt[0]&mask) | (value&0x03FF&~mask); break; case 0x5F84A>>1: /* SPT1 */ sim->vip.spt[1] = (sim->vip.spt[1]&mask) | (value&0x03FF&~mask); break; case 0x5F84C>>1: /* SPT2 */ sim->vip.spt[2] = (sim->vip.spt[2]&mask) | (value&0x03FF&~mask); break; case 0x5F84E>>1: /* SPT3 */ sim->vip.spt[3] = (sim->vip.spt[3]&mask) | (value&0x03FF&~mask); break; case 0x5F860>>1: /* GPLT0 */ vipWritePalette(sim->vip.gplt[0], mask, value); break; case 0x5F862>>1: /* GPLT1 */ vipWritePalette(sim->vip.gplt[1], mask, value); break; case 0x5F864>>1: /* GPLT2 */ vipWritePalette(sim->vip.gplt[2], mask, value); break; case 0x5F866>>1: /* GPLT3 */ vipWritePalette(sim->vip.gplt[3], mask, value); break; case 0x5F868>>1: /* JPLT0 */ vipWritePalette(sim->vip.jplt[0], mask, value); break; case 0x5F86A>>1: /* JPLT1 */ vipWritePalette(sim->vip.jplt[1], mask, value); break; case 0x5F86C>>1: /* JPLT2 */ vipWritePalette(sim->vip.jplt[2], mask, value); break; case 0x5F86E>>1: /* JPLT3 */ vipWritePalette(sim->vip.jplt[3], mask, value); break; case 0x5F870>>1: /* BKCOL */ sim->vip.bkcol = (sim->vip.bkcol & mask) | (value & 3 * ~mask); break; } } /***************************** Library Functions *****************************/ /* Process component */ static int vipEmulate(VB *sim, uint32_t clocks) { (void) sim; (void) clocks; return 0; } /* Read a typed value from the VIP bus */ 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); } /* Unmapped */ else if (address < 0x5E000) *value = 0; /* I/O register */ else if (address < 0x60000) *value = vipReadIO(sim, address, type); /* Unmapped */ if (address < 0x78000) *value = 0; /* Mirrors of character memory */ else { address = 0x06000 | (address << 2 & 0x18000) | (address & 0x01FFF); *value = busReadBuffer(&sim->vip.vram[address], type); } } /* Simulate a hardware reset */ 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; /* 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 < 4; x++) { sim->vip.brtRest[x] = 0; sim->vip.spt [x] = 0; for (y = 0; y < 4; y++) { sim->vip.gplt[x][y] = 0; sim->vip.jplt[x][y] = 0; } } } /* Determine how many clocks are guaranteed to process */ static uint32_t vipUntil(VB *sim, uint32_t clocks) { (void) sim; 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 */ if (address < 0x40000) busWriteBuffer(&sim->vip.vram[address], type, value); /* Unmapped */ else if (address < 0x5E000) ; /* I/O register */ else if (address < 0x60000) vipWriteIO(sim, address, type, value, debug); /* Unmapped */ else if (address < 0x78000) ; /* Mirrors of character memory */ else { address = 0x06000 | (address << 2 & 0x18000) | (address & 0x01FFF); busWriteBuffer(&sim->vip.vram[address], type, value); } } #endif /* VBAPI */