bsnes/higan/gba/ppu/mmio.cpp

208 lines
5.8 KiB
C++

auto PPU::read(uint32 addr) -> uint8 {
switch(addr) {
//DISPCNT
case 0x04000000: return regs.control >> 0;
case 0x04000001: return regs.control >> 8;
//GRSWP
case 0x04000002: return regs.greenswap;
case 0x04000003: return 0u;
//DISPSTAT
case 0x04000004: return regs.status >> 0;
case 0x04000005: return regs.status >> 8;
//VCOUNT
case 0x04000006: return regs.vcounter >> 0;
case 0x04000007: return regs.vcounter >> 8;
//BG0CNT,BG1CNT,BG2CNT,BG3CNT
case 0x04000008: case 0x04000009:
case 0x0400000a: case 0x0400000b:
case 0x0400000c: case 0x0400000d:
case 0x0400000e: case 0x0400000f: {
auto& bg = regs.bg[(addr >> 1) & 3];
unsigned shift = (addr & 1) * 8;
return bg.control >> shift;
}
//WININ
case 0x04000048: return regs.windowflags[In0];
case 0x04000049: return regs.windowflags[In1];
case 0x0400004a: return regs.windowflags[Out];
case 0x0400004b: return regs.windowflags[Obj];
//BLTCNT
case 0x04000050: return regs.blend.control >> 0;
case 0x04000051: return regs.blend.control >> 8;
//BLDALPHA
case 0x04000052: return regs.blend.eva;
case 0x04000053: return regs.blend.evb;
//BLDY is write-only
}
return 0u;
}
auto PPU::write(uint32 addr, uint8 byte) -> void {
switch(addr) {
//DISPCNT
case 0x04000000: regs.control = (regs.control & 0xff00) | (byte << 0); return;
case 0x04000001: regs.control = (regs.control & 0x00ff) | (byte << 8); return;
//GRSWP
case 0x04000002: regs.greenswap = byte >> 0; return;
case 0x04000003: return;
//DISPSTAT
case 0x04000004:
regs.status.irqvblank = byte >> 3;
regs.status.irqhblank = byte >> 4;
regs.status.irqvcoincidence = byte >> 5;
return;
case 0x04000005:
regs.status.vcompare = byte;
return;
//BG0CNT,BG1CNT,BG2CNT,BG3CNT
case 0x04000008: case 0x04000009:
case 0x0400000a: case 0x0400000b:
case 0x0400000c: case 0x0400000d:
case 0x0400000e: case 0x0400000f: {
auto& bg = regs.bg[(addr >> 1) & 3];
unsigned shift = (addr & 1) * 8;
if(addr == 0x04000009 || addr == 0x0400000b) byte &= 0xdf; //clear affine wrap for BG0,1
bg.control = (bg.control & ~(255 << shift)) | (byte << shift);
return;
}
//BG0HOFS,BG1HOFS,BG2BOFS,BG3HOFS
case 0x04000010: case 0x04000011:
case 0x04000014: case 0x04000015:
case 0x04000018: case 0x04000019:
case 0x0400001c: case 0x0400001d: {
auto& bg = regs.bg[(addr >> 2) & 3];
unsigned shift = (addr & 1) * 8;
bg.hoffset = (bg.hoffset & ~(255 << shift)) | (byte << shift);
return;
}
//BG0VOFS,BG1VOFS,BG2VOFS,BG3VOFS
case 0x04000012: case 0x04000013:
case 0x04000016: case 0x04000017:
case 0x0400001a: case 0x0400001b:
case 0x0400001e: case 0x0400001f: {
auto& bg = regs.bg[(addr >> 2) & 3];
unsigned shift = (addr & 1) * 8;
bg.voffset = (bg.voffset & ~(255 << shift)) | (byte << shift);
return;
}
//BG2PA,BG3PA
case 0x04000020: case 0x04000021:
case 0x04000030: case 0x04000031: {
auto& bg = regs.bg[(addr >> 4) & 3];
unsigned shift = (addr & 1) * 8;
bg.pa = (bg.pa & ~(255 << shift)) | (byte << shift);
return;
}
//BG2PB,BG3PB
case 0x04000022: case 0x04000023:
case 0x04000032: case 0x04000033: {
auto& bg = regs.bg[(addr >> 4) & 3];
unsigned shift = (addr & 1) * 8;
bg.pb = (bg.pb & ~(255 << shift)) | (byte << shift);
return;
}
//BG2PC,BG3PC
case 0x04000024: case 0x04000025:
case 0x04000034: case 0x04000035: {
auto& bg = regs.bg[(addr >> 4) & 3];
unsigned shift = (addr & 1) * 8;
bg.pc = (bg.pc & ~(255 << shift)) | (byte << shift);
return;
}
//BG2PD,BG3PD
case 0x04000026: case 0x04000027:
case 0x04000036: case 0x04000037: {
auto& bg = regs.bg[(addr >> 4) & 3];
unsigned shift = (addr & 1) * 8;
bg.pd = (bg.pd & ~(255 << shift)) | (byte << shift);
return;
}
//BG2X_L,BG2X_H,BG3X_L,BG3X_H
case 0x04000028: case 0x04000029: case 0x0400002a: case 0x0400002b:
case 0x04000038: case 0x04000039: case 0x0400003a: case 0x0400003b: {
auto& bg = regs.bg[(addr >> 4) & 3];
unsigned shift = (addr & 3) * 8;
bg.lx = bg.x = (bg.x & ~(255 << shift)) | (byte << shift);
return;
}
//BG2Y_L,BG2Y_H,BG3Y_L,BG3Y_H
case 0x0400002c: case 0x0400002d: case 0x0400002e: case 0x0400002f:
case 0x0400003c: case 0x0400003d: case 0x0400003e: case 0x0400003f: {
auto& bg = regs.bg[(addr >> 4) & 3];
unsigned shift = (addr & 3) * 8;
bg.ly = bg.y = (bg.y & ~(255 << shift)) | (byte << shift);
return;
}
//WIN0H
case 0x04000040: regs.window[0].x2 = byte; return;
case 0x04000041: regs.window[0].x1 = byte; return;
//WIN1H
case 0x04000042: regs.window[1].x2 = byte; return;
case 0x04000043: regs.window[1].x1 = byte; return;
//WIN0V
case 0x04000044: regs.window[0].y2 = byte; return;
case 0x04000045: regs.window[0].y1 = byte; return;
//WIN1V
case 0x04000046: regs.window[1].y2 = byte; return;
case 0x04000047: regs.window[1].y1 = byte; return;
//WININ
case 0x04000048: regs.windowflags[In0] = byte; return;
case 0x04000049: regs.windowflags[In1] = byte; return;
//WINOUT
case 0x0400004a: regs.windowflags[Out] = byte; return;
case 0x0400004b: regs.windowflags[Obj] = byte; return;
//MOSAIC
case 0x0400004c:
regs.mosaic.bghsize = byte >> 0;
regs.mosaic.bgvsize = byte >> 4;
return;
case 0x0400004d:
regs.mosaic.objhsize = byte >> 0;
regs.mosaic.objvsize = byte >> 4;
return;
//BLDCNT
case 0x04000050: regs.blend.control = (regs.blend.control & 0xff00) | (byte << 0); return;
case 0x04000051: regs.blend.control = (regs.blend.control & 0x00ff) | (byte << 8); return;
//BLDALPHA
case 0x04000052: regs.blend.eva = byte & 0x1f; return;
case 0x04000053: regs.blend.evb = byte & 0x1f; return;
//BLDY
case 0x04000054: regs.blend.evy = byte & 0x1f; return;
case 0x04000055: return;
}
}