bsnes/gba/ppu/memory.cpp

170 lines
3.8 KiB
C++

uint32 PPU::vram_read(uint32 addr, uint32 size) {
addr &= (addr & 0x10000) ? 0x17fff : 0x0ffff;
switch(size) {
case Word:
addr &= ~3;
return vram[addr + 0] << 0 | vram[addr + 1] << 8 | vram[addr + 2] << 16 | vram[addr + 3] << 24;
case Half:
addr &= ~1;
return vram[addr + 0] << 0 | vram[addr + 1] << 8;
case Byte:
return vram[addr];
}
}
void PPU::vram_write(uint32 addr, uint32 size, uint32 word) {
addr &= (addr & 0x10000) ? 0x17fff : 0x0ffff;
switch(size) {
case Word:
addr &= ~3;
vram[addr + 0] = word >> 0;
vram[addr + 1] = word >> 8;
vram[addr + 2] = word >> 16;
vram[addr + 3] = word >> 24;
break;
case Half:
addr &= ~1;
vram[addr + 0] = word >> 0;
vram[addr + 1] = word >> 8;
break;
case Byte:
addr &= ~1;
vram[addr + 0] = word;
vram[addr + 1] = word;
break;
}
}
uint32 PPU::pram_read(uint32 addr, uint32 size) {
if(size == Word) return pram_read(addr & ~2, Half) << 0 | pram_read(addr | 2, Half) << 16;
if(size == Byte) return pram_read(addr, Half) >> ((addr & 1) * 8);
return pram[addr >> 1 & 511];
}
void PPU::pram_write(uint32 addr, uint32 size, uint32 word) {
if(size == Word) {
pram_write(addr & ~2, Half, word >> 0);
pram_write(addr | 2, Half, word >> 16);
return;
}
if(size == Byte) {
return pram_write(addr, Half, word << 8 | word << 0);
}
pram[addr >> 1 & 511] = word & 0x7fff;
}
uint32 PPU::oam_read(uint32 addr, uint32 size) {
if(size == Word) return oam_read(addr & ~2, Half) << 0 | oam_read(addr | 2, Half) << 16;
if(size == Byte) return oam_read(addr, Half) >> ((addr & 1) * 8);
auto& obj = object[addr >> 3 & 127];
auto& par = objectparam[addr >> 5 & 31];
switch(addr & 6) {
case 0: return (
(obj.y << 0)
| (obj.affine << 8)
| (obj.affinesize << 9)
| (obj.mode << 10)
| (obj.mosaic << 12)
| (obj.colors << 13)
| (obj.shape << 14)
);
case 2: return (
(obj.x << 0)
| (obj.affineparam << 9)
| (obj.hflip << 12)
| (obj.vflip << 13)
| (obj.size << 14)
);
case 4: return (
(obj.character << 0)
| (obj.priority << 10)
| (obj.palette << 12)
);
case 6:
switch(addr >> 3 & 3) {
case 0: return par.pa;
case 1: return par.pb;
case 2: return par.pc;
case 3: return par.pd;
}
}
}
void PPU::oam_write(uint32 addr, uint32 size, uint32 word) {
if(size == Word) {
oam_write(addr & ~2, Half, word >> 0);
oam_write(addr | 2, Half, word >> 16);
return;
}
if(size == Byte) {
return oam_write(addr, Half, word << 8 | word << 0);
}
auto& obj = object[addr >> 3 & 127];
auto& par = objectparam[addr >> 5 & 31];
switch(addr & 6) {
case 0:
obj.y = word >> 0;
obj.affine = word >> 8;
obj.affinesize = word >> 9;
obj.mode = word >> 10;
obj.mosaic = word >> 12;
obj.colors = word >> 13;
obj.shape = word >> 14;
break;
case 2:
obj.x = word >> 0;
obj.affineparam = word >> 9;
obj.hflip = word >> 12;
obj.vflip = word >> 13;
obj.size = word >> 14;
break;
case 4:
obj.character = word >> 0;
obj.priority = word >> 10;
obj.palette = word >> 12;
break;
case 6:
switch(addr >> 3 & 3) {
case 0: par.pa = word; break;
case 1: par.pb = word; break;
case 2: par.pc = word; break;
case 3: par.pd = word; break;
}
}
static unsigned widths[] = {
8, 16, 32, 64,
16, 32, 32, 64,
8, 8, 16, 32,
8, 8, 8, 8, //invalid modes
};
static unsigned heights[] = {
8, 16, 32, 64,
8, 8, 16, 32,
16, 32, 32, 64,
8, 8, 8, 8, //invalid modes
};
obj.width = widths [obj.shape * 4 + obj.size];
obj.height = heights[obj.shape * 4 + obj.size];
}