mirror of https://github.com/bsnes-emu/bsnes.git
170 lines
3.8 KiB
C++
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];
|
|
}
|