auto PPU::portRead(uint16 addr) -> uint8 { //DISP_CTRL if(addr == 0x0000) return ( r.screenOneEnable << 0 | r.screenTwoEnable << 1 | r.spriteEnable << 2 | r.spriteWindowEnable << 3 | r.screenTwoWindowInvert << 4 | r.screenTwoWindowEnable << 5 ); //BACK_COLOR if(addr == 0x0001) return ( r.backColor.bits(0, !system.color() ? 2 : 7) ); //LINE_CUR if(addr == 0x0002) return s.vclk; //LINE_CMP if(addr == 0x0003) return r.lineCompare; //SPR_BASE if(addr == 0x0004) return ( r.spriteBase.bits(0, 4 + system.depth()) ); //SPR_FIRST if(addr == 0x0005) return r.spriteFirst; //SPR_COUNT if(addr == 0x0006) return r.spriteCount; //MAP_BASE if(addr == 0x0007) return ( r.screenOneMapBase.bits(0, 2 + system.depth()) << 0 | r.screenTwoMapBase.bits(0, 2 + system.depth()) << 4 ); //SCR2_WIN_X0 if(addr == 0x0008) return r.screenTwoWindowX0; //SCR2_WIN_Y0 if(addr == 0x0009) return r.screenTwoWindowY0; //SCR2_WIN_X1 if(addr == 0x000a) return r.screenTwoWindowX1; //SCR2_WIN_Y1 if(addr == 0x000b) return r.screenTwoWindowY1; //SPR_WIN_X0 if(addr == 0x000c) return r.spriteWindowX0; //SPR_WIN_Y0 if(addr == 0x000d) return r.spriteWindowY0; //SPR_WIN_X1 if(addr == 0x000e) return r.spriteWindowX1; //SPR_WIN_Y1 if(addr == 0x000f) return r.spriteWindowY1; //SCR1_X if(addr == 0x0010) return r.scrollOneX; //SCR1_Y if(addr == 0x0011) return r.scrollOneY; //SCR2_X if(addr == 0x0012) return r.scrollTwoX; //SCR2_Y if(addr == 0x0013) return r.scrollTwoY; //LCD_CTRL if(addr == 0x0014) return ( r.lcdEnable << 0 | r.lcdContrast << 1 | r.lcdUnknown << 2 ); //LCD_ICON if(addr == 0x0015) return ( r.iconSleep << 0 | r.iconVertical << 1 | r.iconHorizontal << 2 | r.iconAux1 << 3 | r.iconAux2 << 4 | r.iconAux3 << 5 ); //LCD_VTOTAL if(addr == 0x0016) return r.vtotal; //LCD_VBLANK if(addr == 0x0017) return r.vblank; //PALMONO_POOL if(addr >= 0x001c && addr <= 0x001f) return ( r.pool[addr.bits(0,1) * 2 + 0] << 0 | r.pool[addr.bits(0,1) * 2 + 1] << 4 ); //PALMONO if(addr >= 0x0020 && addr <= 0x003f) return ( r.palette[addr.bits(1,4)].color[addr.bit(0) * 2 + 0] << 0 | r.palette[addr.bits(1,4)].color[addr.bit(0) * 2 + 1] << 4 ); //TMR_CTRL if(addr == 0x00a2) return ( r.htimerEnable << 0 | r.htimerRepeat << 1 | r.vtimerEnable << 2 | r.vtimerRepeat << 3 ); //HTMR_FREQ if(addr == 0x00a4) return r.htimerFrequency.byte(0); if(addr == 0x00a5) return r.htimerFrequency.byte(1); //VTMR_FREQ if(addr == 0x00a6) return r.vtimerFrequency.byte(0); if(addr == 0x00a7) return r.vtimerFrequency.byte(1); //HTMR_CTR if(addr == 0x00a8) return r.htimerCounter.byte(0); if(addr == 0x00a9) return r.htimerCounter.byte(1); //VTMR_CTR if(addr == 0x00aa) return r.vtimerCounter.byte(0); if(addr == 0x00ab) return r.vtimerCounter.byte(1); return 0x00; } auto PPU::portWrite(uint16 addr, uint8 data) -> void { //DISP_CTRL if(addr == 0x0000) { r.screenOneEnable = data.bit(0); r.screenTwoEnable = data.bit(1); r.spriteEnable = data.bit(2); r.spriteWindowEnable = data.bit(3); r.screenTwoWindowInvert = data.bit(4); r.screenTwoWindowEnable = data.bit(5); } //BACK_COLOR if(addr == 0x0001) r.backColor = data; //LINE_CMP if(addr == 0x0003) r.lineCompare = data; //SPR_BASE if(addr == 0x0004) r.spriteBase = data.bits(0,5); //SPR_FIRST if(addr == 0x0005) r.spriteFirst = data.bits(6,0); //SPR_COUNT if(addr == 0x0006) r.spriteCount = data; //MAP_BASE if(addr == 0x0007) { r.screenOneMapBase = data.bits(0,3); r.screenTwoMapBase = data.bits(4,7); } //SCR2_WIN_X0 if(addr == 0x0008) r.screenTwoWindowX0 = data; //SCR2_WIN_Y0 if(addr == 0x0009) r.screenTwoWindowY0 = data; //SCR2_WIN_X1 if(addr == 0x000a) r.screenTwoWindowX1 = data; //SCR2_WIN_Y1 if(addr == 0x000b) r.screenTwoWindowY1 = data; //SPR_WIN_X0 if(addr == 0x000c) r.spriteWindowX0 = data; //SPR_WIN_Y0 if(addr == 0x000d) r.spriteWindowY0 = data; //SPR_WIN_X1 if(addr == 0x000e) r.spriteWindowX1 = data; //SPR_WIN_Y1 if(addr == 0x000f) r.spriteWindowY1 = data; //SCR1_X if(addr == 0x0010) r.scrollOneX = data; //SCR1_Y if(addr == 0x0011) r.scrollOneY = data; //SCR2_X if(addr == 0x0012) r.scrollTwoX = data; //SCR2_Y if(addr == 0x0013) r.scrollTwoY = data; //LCD_CTRL if(addr == 0x0014) { r.lcdEnable = data.bit (0); r.lcdContrast = data.bit (1); r.lcdUnknown = data.bits(2,7); if(system.model() == Model::WonderSwanColor) { r.lcdUnknown &= 0b111100; } if(system.model() == Model::SwanCrystal) { r.lcdContrast = 0; r.lcdUnknown = 0; } } //LCD_ICON if(addr == 0x0015) { r.iconSleep = data.bit(0); r.iconVertical = data.bit(1); r.iconHorizontal = data.bit(2); r.iconAux1 = data.bit(3); r.iconAux2 = data.bit(4); r.iconAux3 = data.bit(5); } //LCD_VTOTAL if(addr == 0x0016) r.vtotal = data; //LCD_VBLANK if(addr == 0x0017) r.vblank = data; //PALMONO_POOL if(addr >= 0x001c && addr <= 0x001f) { r.pool[addr.bits(0,1) * 2 + 0] = data.bits(0,3); r.pool[addr.bits(0,1) * 2 + 1] = data.bits(4,7); } //PALMONO if(addr >= 0x0020 && addr <= 0x003f) { r.palette[addr.bits(1,4)].color[addr.bit(0) * 2 + 0] = data.bits(0,2); r.palette[addr.bits(1,4)].color[addr.bit(0) * 2 + 1] = data.bits(4,6); } //TMR_CTRL if(addr == 0x00a2) { r.htimerEnable = data.bit(0); r.htimerRepeat = data.bit(1); r.vtimerEnable = data.bit(2); r.vtimerRepeat = data.bit(3); if(r.htimerEnable) r.htimerCounter = 0; if(r.vtimerEnable) r.vtimerCounter = 0; } //HTMR_FREQ if(addr == 0x00a4) r.htimerFrequency.byte(0) = data; if(addr == 0x00a5) r.htimerFrequency.byte(1) = data; if(addr == 0x00a4 || addr == 0x00a5) { r.htimerEnable = true; r.htimerRepeat = true; r.htimerCounter = 0; } //VTMR_FREQ if(addr == 0x00a6) r.vtimerFrequency.byte(0) = data; if(addr == 0x00a7) r.vtimerFrequency.byte(1) = data; if(addr == 0x00a6 || addr == 0x00a7) { r.vtimerEnable = true; r.vtimerRepeat = true; r.vtimerCounter = 0; } }