mirror of https://github.com/bsnes-emu/bsnes.git
276 lines
9.0 KiB
C++
276 lines
9.0 KiB
C++
auto PPU::readIO(uint32 addr) -> uint8 {
|
|
auto bgcnt = [&]() -> Registers::Background::Control& { return regs.bg[addr.bits(1,2)].control; };
|
|
auto wf = [&]() -> Registers::WindowFlags& {
|
|
static uint id[] = {In0, In1, Out, Obj};
|
|
return regs.windowflags[id[addr.bits(0,1)]];
|
|
};
|
|
|
|
switch(addr) {
|
|
|
|
//DISPCNT
|
|
case 0x0400'0000: return (
|
|
regs.control.bgmode << 0
|
|
| regs.control.cgbmode << 3
|
|
| regs.control.frame << 4
|
|
| regs.control.hblank << 5
|
|
| regs.control.objmapping << 6
|
|
| regs.control.forceblank << 7
|
|
);
|
|
case 0x0400'0001: return (
|
|
regs.control.enable[BG0] << 0
|
|
| regs.control.enable[BG1] << 1
|
|
| regs.control.enable[BG2] << 2
|
|
| regs.control.enable[BG3] << 3
|
|
| regs.control.enable[OBJ] << 4
|
|
| regs.control.enablewindow[In0] << 5
|
|
| regs.control.enablewindow[In1] << 6
|
|
| regs.control.enablewindow[Obj] << 7
|
|
);
|
|
|
|
//GRSWP
|
|
case 0x0400'0002: return regs.greenswap;
|
|
case 0x0400'0003: return 0;
|
|
|
|
//DISPSTAT
|
|
case 0x0400'0004: return (
|
|
regs.status.vblank << 0
|
|
| regs.status.hblank << 1
|
|
| regs.status.vcoincidence << 2
|
|
| regs.status.irqvblank << 3
|
|
| regs.status.irqhblank << 4
|
|
| regs.status.irqvcoincidence << 5
|
|
);
|
|
case 0x0400'0005: return (
|
|
regs.status.vcompare
|
|
);
|
|
|
|
//VCOUNT
|
|
case 0x0400'0006: return regs.vcounter.byte(0);
|
|
case 0x0400'0007: return regs.vcounter.byte(1);
|
|
|
|
//BG0CNT, BG1CNT, BG2CNT, BG3CNT
|
|
case 0x0400'0008: case 0x0400'000a: case 0x0400'000c: case 0x0400'000e: return (
|
|
bgcnt().priority << 0
|
|
| bgcnt().characterbaseblock << 2
|
|
| bgcnt().unused << 4
|
|
| bgcnt().mosaic << 6
|
|
| bgcnt().colormode << 7
|
|
);
|
|
case 0x0400'0009: case 0x0400'000b: case 0x0400'000d: case 0x0400'000f: return (
|
|
bgcnt().screenbaseblock << 0
|
|
| bgcnt().affinewrap << 5
|
|
| bgcnt().screensize << 6
|
|
);
|
|
|
|
//WININ, WINOUT
|
|
case 0x0400'0048: case 0x0400'0049: case 0x0400'004a: case 0x0400'004b: return (
|
|
wf().enable[BG0] << 0
|
|
| wf().enable[BG1] << 1
|
|
| wf().enable[BG2] << 2
|
|
| wf().enable[BG3] << 3
|
|
| wf().enable[OBJ] << 4
|
|
| wf().enable[SFX] << 4
|
|
);
|
|
|
|
//BLTCNT
|
|
case 0x0400'0050: return (
|
|
regs.blend.control.above[BG0] << 0
|
|
| regs.blend.control.above[BG1] << 1
|
|
| regs.blend.control.above[BG2] << 2
|
|
| regs.blend.control.above[BG3] << 3
|
|
| regs.blend.control.above[OBJ] << 4
|
|
| regs.blend.control.above[SFX] << 5
|
|
| regs.blend.control.mode << 6
|
|
);
|
|
case 0x0400'0051: return (
|
|
regs.blend.control.below[BG0] << 0
|
|
| regs.blend.control.below[BG1] << 1
|
|
| regs.blend.control.below[BG2] << 2
|
|
| regs.blend.control.below[BG3] << 3
|
|
| regs.blend.control.below[OBJ] << 4
|
|
| regs.blend.control.below[SFX] << 5
|
|
);
|
|
|
|
//BLDALPHA
|
|
case 0x0400'0052: return regs.blend.eva;
|
|
case 0x0400'0053: return regs.blend.evb;
|
|
|
|
//BLDY is write-only
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
auto PPU::writeIO(uint32 addr, uint8 data) -> void {
|
|
auto bgcnt = [&]() -> Registers::Background::Control& { return regs.bg[addr.bits(1,2)].control; };
|
|
auto bgofs = [&]() -> Registers::Background& { return regs.bg[addr.bits(2,3)]; };
|
|
auto bg = [&]() -> Registers::Background& { return regs.bg[addr.bits(4,5)]; };
|
|
auto wf = [&]() -> Registers::WindowFlags& {
|
|
static uint id[] = {In0, In1, Out, Obj};
|
|
return regs.windowflags[id[addr.bits(0,1)]];
|
|
};
|
|
|
|
switch(addr) {
|
|
|
|
//DISPCNT
|
|
case 0x0400'0000:
|
|
regs.control.bgmode = data.bits(0,2);
|
|
regs.control.cgbmode = data.bit (3);
|
|
regs.control.frame = data.bit (4);
|
|
regs.control.hblank = data.bit (5);
|
|
regs.control.objmapping = data.bit (6);
|
|
regs.control.forceblank = data.bit (7);
|
|
return;
|
|
case 0x0400'0001:
|
|
regs.control.enable[BG0] = data.bit(0);
|
|
regs.control.enable[BG1] = data.bit(1);
|
|
regs.control.enable[BG2] = data.bit(2);
|
|
regs.control.enable[BG3] = data.bit(3);
|
|
regs.control.enable[OBJ] = data.bit(4);
|
|
regs.control.enablewindow[In0] = data.bit(5);
|
|
regs.control.enablewindow[In1] = data.bit(6);
|
|
regs.control.enablewindow[Obj] = data.bit(7);
|
|
return;
|
|
|
|
//GRSWP
|
|
case 0x0400'0002:
|
|
regs.greenswap = data.bit(0);
|
|
return;
|
|
case 0x0400'0003: return;
|
|
|
|
//DISPSTAT
|
|
case 0x0400'0004:
|
|
regs.status.irqvblank = data.bit(3);
|
|
regs.status.irqhblank = data.bit(4);
|
|
regs.status.irqvcoincidence = data.bit(5);
|
|
return;
|
|
case 0x0400'0005:
|
|
regs.status.vcompare = data;
|
|
return;
|
|
|
|
//BG0CNT, BG1CNT, BG2CNT, BG3CNT
|
|
case 0x0400'0008: case 0x0400'000a: case 0x0400'000c: case 0x0400'000e:
|
|
bgcnt().priority = data.bits(0,1);
|
|
bgcnt().characterbaseblock = data.bits(2,3);
|
|
bgcnt().unused = data.bits(4,5);
|
|
bgcnt().mosaic = data.bit (6);
|
|
bgcnt().colormode = data.bit (7);
|
|
return;
|
|
case 0x0400'0009: case 0x0400'000b: case 0x0400'000d: case 0x0400'000f:
|
|
if(addr.bits(1,2) <= 1) data.bit(5) = 0; //clear affine wrap for BG0, BG1
|
|
bgcnt().screenbaseblock = data.bits(0,4);
|
|
bgcnt().affinewrap = data.bit (5);
|
|
bgcnt().screensize = data.bits(6,7);
|
|
return;
|
|
|
|
//BG0HOFS, BG1HOFS, BG2BOFS, BG3HOFS
|
|
case 0x0400'0010: case 0x0400'0014: case 0x0400'0018: case 0x0400'001c:
|
|
bgofs().hoffset.bits(0,7) = data;
|
|
return;
|
|
case 0x0400'0011: case 0x0400'0015: case 0x0400'0019: case 0x0400'001d:
|
|
bgofs().hoffset.bit(8) = data.bit(0);
|
|
return;
|
|
|
|
//BG0VOFS, BG1VOFS, BG2VOFS, BG3VOFS
|
|
case 0x0400'0012: case 0x0400'0016: case 0x0400'001a: case 0x0400'001e:
|
|
bgofs().voffset.bits(0,7) = data;
|
|
return;
|
|
case 0x0400'0013: case 0x0400'0017: case 0x0400'001b: case 0x0400'001f:
|
|
bgofs().voffset.bit(8) = data.bit(0);
|
|
return;
|
|
|
|
//BG2PA, BG3PA
|
|
case 0x0400'0020: case 0x0400'0030: bg().pa.byte(0) = data; return;
|
|
case 0x0400'0021: case 0x0400'0031: bg().pa.byte(1) = data; return;
|
|
|
|
//BG2PB, BG3PB
|
|
case 0x0400'0022: case 0x0400'0032: bg().pb.byte(0) = data; return;
|
|
case 0x0400'0023: case 0x0400'0033: bg().pb.byte(1) = data; return;
|
|
|
|
//BG2PC, BG3PC
|
|
case 0x0400'0024: case 0x0400'0034: bg().pc.byte(0) = data; return;
|
|
case 0x0400'0025: case 0x0400'0035: bg().pc.byte(1) = data; return;
|
|
|
|
//BG2PD, BG3PD
|
|
case 0x0400'0026: case 0x0400'0036: bg().pd.byte(0) = data; return;
|
|
case 0x0400'0027: case 0x0400'0037: bg().pd.byte(1) = data; return;
|
|
|
|
//BG2X_L, BG2X_H, BG3X_L, BG3X_H
|
|
case 0x0400'0028: case 0x0400'0038: bg().x.bits( 0, 7) = data.bits(0,7); bg().lx = bg().x; return;
|
|
case 0x0400'0029: case 0x0400'0039: bg().x.bits( 8,15) = data.bits(0,7); bg().lx = bg().x; return;
|
|
case 0x0400'002a: case 0x0400'003a: bg().x.bits(16,23) = data.bits(0,7); bg().lx = bg().x; return;
|
|
case 0x0400'002b: case 0x0400'003b: bg().x.bits(24,27) = data.bits(0,3); bg().lx = bg().x; return;
|
|
|
|
//BG2Y_L, BG2Y_H, BG3Y_L, BG3Y_H
|
|
case 0x0400'002c: case 0x0400'003c: bg().y.bits( 0, 7) = data.bits(0,7); bg().ly = bg().y; return;
|
|
case 0x0400'002d: case 0x0400'003d: bg().y.bits( 8,15) = data.bits(0,7); bg().ly = bg().y; return;
|
|
case 0x0400'002e: case 0x0400'003e: bg().y.bits(16,23) = data.bits(0,7); bg().ly = bg().y; return;
|
|
case 0x0400'002f: case 0x0400'003f: bg().y.bits(24,27) = data.bits(0,3); bg().ly = bg().y; return;
|
|
|
|
//WIN0H
|
|
case 0x0400'0040: regs.window[0].x2 = data; return;
|
|
case 0x0400'0041: regs.window[0].x1 = data; return;
|
|
|
|
//WIN1H
|
|
case 0x0400'0042: regs.window[1].x2 = data; return;
|
|
case 0x0400'0043: regs.window[1].x1 = data; return;
|
|
|
|
//WIN0V
|
|
case 0x0400'0044: regs.window[0].y2 = data; return;
|
|
case 0x0400'0045: regs.window[0].y1 = data; return;
|
|
|
|
//WIN1V
|
|
case 0x0400'0046: regs.window[1].y2 = data; return;
|
|
case 0x0400'0047: regs.window[1].y1 = data; return;
|
|
|
|
//WININ, WINOUT
|
|
case 0x0400'0048: case 0x0400'0049: case 0x0400'004a: case 0x0400'004b:
|
|
wf().enable[BG0] = data.bit(0);
|
|
wf().enable[BG1] = data.bit(1);
|
|
wf().enable[BG2] = data.bit(2);
|
|
wf().enable[BG3] = data.bit(3);
|
|
wf().enable[OBJ] = data.bit(4);
|
|
wf().enable[SFX] = data.bit(5);
|
|
return;
|
|
|
|
//MOSAIC
|
|
case 0x0400'004c:
|
|
regs.mosaic.bghsize = data.bits(0,3);
|
|
regs.mosaic.bgvsize = data.bits(4,7);
|
|
return;
|
|
case 0x0400'004d:
|
|
regs.mosaic.objhsize = data.bits(0,3);
|
|
regs.mosaic.objvsize = data.bits(4,7);
|
|
return;
|
|
|
|
//BLDCNT
|
|
case 0x0400'0050:
|
|
regs.blend.control.above[BG0] = data.bit (0);
|
|
regs.blend.control.above[BG1] = data.bit (1);
|
|
regs.blend.control.above[BG2] = data.bit (2);
|
|
regs.blend.control.above[BG3] = data.bit (3);
|
|
regs.blend.control.above[OBJ] = data.bit (4);
|
|
regs.blend.control.above[SFX] = data.bit (5);
|
|
regs.blend.control.mode = data.bits(6,7);
|
|
return;
|
|
case 0x0400'0051:
|
|
regs.blend.control.below[BG0] = data.bit(0);
|
|
regs.blend.control.below[BG1] = data.bit(1);
|
|
regs.blend.control.below[BG2] = data.bit(2);
|
|
regs.blend.control.below[BG3] = data.bit(3);
|
|
regs.blend.control.below[OBJ] = data.bit(4);
|
|
regs.blend.control.below[SFX] = data.bit(5);
|
|
return;
|
|
|
|
//BLDALPHA
|
|
case 0x0400'0052: regs.blend.eva = data.bits(0,4); return;
|
|
case 0x0400'0053: regs.blend.evb = data.bits(0,4); return;
|
|
|
|
//BLDY
|
|
case 0x0400'0054: regs.blend.evy = data.bits(0,4); return;
|
|
case 0x0400'0055: return;
|
|
|
|
}
|
|
}
|