diff --git a/bsnes-bppu.exe b/bsnes-bppu.exe deleted file mode 100644 index c0277ec0..00000000 Binary files a/bsnes-bppu.exe and /dev/null differ diff --git a/bsnes-sppu.exe b/bsnes-sppu.exe deleted file mode 100644 index 842b2651..00000000 Binary files a/bsnes-sppu.exe and /dev/null differ diff --git a/src/snes/Makefile b/src/snes/Makefile index 44ce3bb9..b8d19e9d 100644 --- a/src/snes/Makefile +++ b/src/snes/Makefile @@ -1,4 +1,4 @@ -snes_core = sMemory sCPU sSMP sDSP bPPU +snes_core = sMemory sCPU sSMP sDSP sPPU snes_objects := libco snes_objects += snes-system diff --git a/src/snes/cpu/scpu/mmio/mmio.cpp b/src/snes/cpu/scpu/mmio/mmio.cpp index fe779bb2..4f85fe0a 100644 --- a/src/snes/cpu/scpu/mmio/mmio.cpp +++ b/src/snes/cpu/scpu/mmio/mmio.cpp @@ -75,6 +75,7 @@ void sCPU::mmio_w4200(uint8 data) { //WRIO void sCPU::mmio_w4201(uint8 data) { + scheduler.sync_cpuppu(); if((status.pio & 0x80) && !(data & 0x80)) { ppu.latch_counters(); } diff --git a/src/snes/ppu/sppu/background/background.cpp b/src/snes/ppu/sppu/background/background.cpp new file mode 100644 index 00000000..3df4d83f --- /dev/null +++ b/src/snes/ppu/sppu/background/background.cpp @@ -0,0 +1,174 @@ +#ifdef SPPU_CPP + +void sPPU::Background::run() { + output.main.valid = false; + output.sub.valid = false; + if(regs.mode == Mode::Inactive) return; + if(regs.main_enabled == false && regs.sub_enabled == false) return; + + if(self.hcounter() < 88) return; + if(self.hcounter() >= 1112) return; + if(self.hcounter() & 2) return; + + unsigned x = (self.hcounter() - 88) >> 2; + unsigned y = regs.mosaic_y; + + unsigned color_depth = (regs.mode == Mode::BPP2 ? 0 : regs.mode == Mode::BPP4 ? 1 : 2); + unsigned palette_offset = (self.regs.bgmode == 0 ? (id << 5) : 0); + unsigned palette_size = 2 << color_depth; + unsigned tile_mask = 0x0fff >> color_depth; + unsigned tiledata_index = regs.tiledata_addr >> (4 + color_depth); + + bool hires = (self.regs.bgmode == 5 || self.regs.bgmode == 6); + unsigned width = (!hires ? 256 : 512); + + unsigned tile_height = (regs.tile_size == TileSize::Size8x8 ? 3 : 4); + unsigned tile_width = (!hires ? tile_height : 4); + + unsigned mask_x = (tile_height == 3 ? width : (width << 1)); + unsigned mask_y = mask_x; + if(regs.screen_size & 1) mask_x <<= 1; + if(regs.screen_size & 2) mask_y <<= 1; + mask_x--; + mask_y--; + + unsigned screen_y = (regs.screen_size & 2 ? (32 << 5) : 0); + unsigned screen_x = (regs.screen_size & 1 ? (32 << 5) : 0); + if(regs.screen_size == 3) screen_y <<= 1; + + unsigned hscroll = regs.hoffset; + unsigned vscroll = regs.voffset; + if(hires) { + hscroll <<= 1; + } + + unsigned hoffset = hscroll + mosaic_table[regs.mosaic][x]; + unsigned voffset = vscroll + y; + + hoffset &= mask_x; + voffset &= mask_y; + + unsigned tile_number; { + unsigned tx = hoffset >> tile_width; + unsigned ty = voffset >> tile_height; + + uint16 pos = ((ty & 0x1f) << 5) + (tx & 0x1f); + if(ty & 0x20) pos += screen_y; + if(tx & 0x20) pos += screen_x; + + uint16 addr = regs.screen_addr + (pos << 1); + tile_number = memory::vram[addr + 0] + (memory::vram[addr + 1] << 8); + } + + bool mirror_y = tile_number & 0x8000; + bool mirror_x = tile_number & 0x4000; + unsigned priority = (tile_number & 0x2000 ? regs.priority1 : regs.priority0); + unsigned palette_number = (tile_number >> 10) & 7; + unsigned palette_index = palette_offset + (palette_number << palette_size); + + if(tile_width == 4 && (bool)(hoffset & 8) != mirror_x) tile_number += 1; + if(tile_height == 4 && (bool)(voffset & 8) != mirror_y) tile_number += 16; + tile_number &= 0x03ff; + tile_number += tiledata_index; + tile_number &= tile_mask; + + if(mirror_y) voffset ^= 7; + if(mirror_x) hoffset ^= 7; + + unsigned color = get_color(hoffset, voffset, tile_number); + if(color == 0) return; + + unsigned palette_addr = (palette_index + color) << 1; + unsigned output_color = memory::cgram[palette_addr + 0] + (memory::cgram[palette_addr + 1] << 8); + + if(regs.main_enabled) { + output.main.valid = true; + output.main.color = output_color; + output.main.priority = priority; + } + + if(regs.sub_enabled) { + output.sub.valid = true; + output.sub.color = output_color; + output.sub.priority = priority; + } +} + +unsigned sPPU::Background::get_color(unsigned x, unsigned y, uint16 offset) { + unsigned mask = 0x80 >> (x & 7); + + switch(regs.mode) { + case Background::Mode::BPP2: { + offset = (offset * 16) + ((y & 7) * 2); + + unsigned d0 = memory::vram[offset + 0]; + unsigned d1 = memory::vram[offset + 1]; + + return (((bool)(d0 & mask)) << 0) + + (((bool)(d1 & mask)) << 1); + } + + case Background::Mode::BPP4: { + offset = (offset * 32) + ((y & 7) * 2); + + unsigned d0 = memory::vram[offset + 0]; + unsigned d1 = memory::vram[offset + 1]; + unsigned d2 = memory::vram[offset + 16]; + unsigned d3 = memory::vram[offset + 17]; + + return (((bool)(d0 & mask)) << 0) + + (((bool)(d1 & mask)) << 1) + + (((bool)(d2 & mask)) << 2) + + (((bool)(d3 & mask)) << 3); + } + + case Background::Mode::BPP8: { + offset = (offset * 64) + ((y & 7) * 2); + + unsigned d0 = memory::vram[offset + 0]; + unsigned d1 = memory::vram[offset + 1]; + unsigned d2 = memory::vram[offset + 16]; + unsigned d3 = memory::vram[offset + 17]; + unsigned d4 = memory::vram[offset + 32]; + unsigned d5 = memory::vram[offset + 33]; + unsigned d6 = memory::vram[offset + 48]; + unsigned d7 = memory::vram[offset + 49]; + + return (((bool)(d0 & mask)) << 0) + + (((bool)(d1 & mask)) << 1) + + (((bool)(d2 & mask)) << 2) + + (((bool)(d3 & mask)) << 3) + + (((bool)(d4 & mask)) << 4) + + (((bool)(d5 & mask)) << 5) + + (((bool)(d6 & mask)) << 6) + + (((bool)(d7 & mask)) << 7); + } + }; +} + +sPPU::Background::Background(sPPU &self, unsigned id) : self(self), id(id) { + //generate mosaic table + for(unsigned m = 0; m < 16; m++) { + for(unsigned x = 0; x < 4096; x++) { + mosaic_table[m][x] = (x / (m + 1)) * (m + 1); + } + } + + regs.tiledata_addr = 0x0000; + regs.screen_addr = 0x0000; + regs.screen_size = ScreenSize::Size32x32; + regs.mosaic = 0; + regs.mosaic_y = 0; + regs.tile_size = TileSize::Size8x8; + + regs.mode = Mode::BPP2; + regs.priority0 = 0; + regs.priority1 = 0; + + regs.main_enabled = false; + regs.sub_enabled = false; +} + +uint16 sPPU::Background::mosaic_table[16][4096]; + +#endif diff --git a/src/snes/ppu/sppu/background/background.hpp b/src/snes/ppu/sppu/background/background.hpp new file mode 100644 index 00000000..49cc20f6 --- /dev/null +++ b/src/snes/ppu/sppu/background/background.hpp @@ -0,0 +1,45 @@ +class Background { +public: + sPPU &self; + struct ID { enum { BG1, BG2, BG3, BG4 }; }; + unsigned id; + + struct Mode { enum { BPP2, BPP4, BPP8, Mode7, Inactive }; }; + struct ScreenSize { enum { Size32x32, Size32x64, Size64x32, Size64x64 }; }; + struct TileSize { enum { Size8x8, Size16x16 }; }; + + struct { + unsigned tiledata_addr; + unsigned screen_addr; + unsigned screen_size; + unsigned mosaic; + unsigned mosaic_y; + bool tile_size; + + unsigned mode; + unsigned priority0; + unsigned priority1; + + bool main_enabled; + bool sub_enabled; + + unsigned hoffset; + unsigned voffset; + } regs; + + struct { + struct { + bool valid; + uint16 color; + unsigned priority; + } main, sub; + } output; + + void run(); + unsigned get_color(unsigned x, unsigned y, uint16 offset); + + Background(sPPU &self, unsigned id); + +private: + static uint16 mosaic_table[16][4096]; +}; diff --git a/src/snes/ppu/sppu/mmio/mmio.cpp b/src/snes/ppu/sppu/mmio/mmio.cpp index 5d28e22c..6e2df25d 100644 --- a/src/snes/ppu/sppu/mmio/mmio.cpp +++ b/src/snes/ppu/sppu/mmio/mmio.cpp @@ -1,8 +1,8 @@ #ifdef SPPU_CPP void sPPU::latch_counters() { - regs.hcounter = cpu.hdot(); - regs.vcounter = cpu.vcounter(); + regs.hcounter = hdot(); + regs.vcounter = vcounter(); regs.counters_latched = true; } @@ -96,52 +96,179 @@ void sPPU::mmio_w2104(uint8 data) { regs.oam_firstsprite = (regs.oam_priority == false ? 0 : (regs.oam_addr >> 2) & 127); } +//BGMODE void sPPU::mmio_w2105(uint8 data) { + bg4.regs.tile_size = (data & 0x80); + bg3.regs.tile_size = (data & 0x40); + bg2.regs.tile_size = (data & 0x20); + bg1.regs.tile_size = (data & 0x10); + regs.bg3_priority = (data & 0x08); + regs.bgmode = (data & 0x07); + + switch(regs.bgmode) { + case 0: { + bg1.regs.mode = Background::Mode::BPP2; bg1.regs.priority0 = 8; bg1.regs.priority1 = 11; + bg2.regs.mode = Background::Mode::BPP2; bg2.regs.priority0 = 7; bg2.regs.priority1 = 10; + bg3.regs.mode = Background::Mode::BPP2; bg3.regs.priority0 = 2; bg3.regs.priority1 = 5; + bg4.regs.mode = Background::Mode::BPP2; bg4.regs.priority0 = 1; bg4.regs.priority1 = 4; + } break; + + case 1: { + bg1.regs.mode = Background::Mode::BPP4; + bg2.regs.mode = Background::Mode::BPP4; + bg3.regs.mode = Background::Mode::BPP2; + bg4.regs.mode = Background::Mode::Inactive; + if(regs.bg3_priority) { + bg1.regs.priority0 = 5; bg1.regs.priority1 = 8; + bg2.regs.priority0 = 4; bg2.regs.priority1 = 7; + bg3.regs.priority0 = 1; bg3.regs.priority1 = 10; + } else { + bg1.regs.priority0 = 6; bg1.regs.priority1 = 9; + bg2.regs.priority0 = 5; bg2.regs.priority1 = 8; + bg3.regs.priority0 = 1; bg3.regs.priority1 = 3; + } + } break; + + case 2: { + bg1.regs.mode = Background::Mode::BPP4; + bg2.regs.mode = Background::Mode::BPP4; + bg3.regs.mode = Background::Mode::Inactive; + bg4.regs.mode = Background::Mode::Inactive; + bg1.regs.priority0 = 3; bg1.regs.priority1 = 7; + bg2.regs.priority0 = 1; bg2.regs.priority1 = 5; + } break; + + case 3: { + bg1.regs.mode = Background::Mode::BPP8; + bg2.regs.mode = Background::Mode::BPP4; + bg3.regs.mode = Background::Mode::Inactive; + bg4.regs.mode = Background::Mode::Inactive; + bg1.regs.priority0 = 3; bg1.regs.priority1 = 7; + bg2.regs.priority0 = 1; bg2.regs.priority1 = 5; + } break; + + case 4: { + bg1.regs.mode = Background::Mode::BPP8; + bg2.regs.mode = Background::Mode::BPP2; + bg3.regs.mode = Background::Mode::Inactive; + bg4.regs.mode = Background::Mode::Inactive; + bg1.regs.priority0 = 3; bg1.regs.priority1 = 7; + bg2.regs.priority0 = 1; bg2.regs.priority1 = 5; + } break; + + case 5: { + bg1.regs.mode = Background::Mode::BPP4; + bg2.regs.mode = Background::Mode::BPP2; + bg3.regs.mode = Background::Mode::Inactive; + bg4.regs.mode = Background::Mode::Inactive; + bg1.regs.priority0 = 3; bg1.regs.priority1 = 7; + bg2.regs.priority0 = 1; bg2.regs.priority1 = 5; + } break; + + case 6: { + bg1.regs.mode = Background::Mode::BPP4; + bg2.regs.mode = Background::Mode::Inactive; + bg3.regs.mode = Background::Mode::Inactive; + bg4.regs.mode = Background::Mode::Inactive; + bg1.regs.priority0 = 2; bg1.regs.priority1 = 5; + } break; + + case 7: { + } break; + } } +//MOSAIC void sPPU::mmio_w2106(uint8 data) { + regs.mosaic_size = (data >> 4) & 15; + bg4.regs.mosaic = (data & 0x08 ? regs.mosaic_size : 0); + bg3.regs.mosaic = (data & 0x04 ? regs.mosaic_size : 0); + bg2.regs.mosaic = (data & 0x02 ? regs.mosaic_size : 0); + bg1.regs.mosaic = (data & 0x01 ? regs.mosaic_size : 0); } +//BG1SC void sPPU::mmio_w2107(uint8 data) { + bg1.regs.screen_addr = (data & 0x7c) << 9; + bg1.regs.screen_size = data & 3; } +//BG2SC void sPPU::mmio_w2108(uint8 data) { + bg2.regs.screen_addr = (data & 0x7c) << 9; + bg2.regs.screen_size = data & 3; } +//BG3SC void sPPU::mmio_w2109(uint8 data) { + bg3.regs.screen_addr = (data & 0x7c) << 9; + bg3.regs.screen_size = data & 3; } +//BG4SC void sPPU::mmio_w210a(uint8 data) { + bg4.regs.screen_addr = (data & 0x7c) << 9; + bg4.regs.screen_size = data & 3; } +//BG12NBA void sPPU::mmio_w210b(uint8 data) { + bg1.regs.tiledata_addr = (data & 0x07) << 13; + bg2.regs.tiledata_addr = (data & 0x70) << 9; } +//BG34NBA void sPPU::mmio_w210c(uint8 data) { + bg3.regs.tiledata_addr = (data & 0x07) << 13; + bg4.regs.tiledata_addr = (data & 0x70) << 9; } +//BG1HOFS void sPPU::mmio_w210d(uint8 data) { + bg1.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg1.regs.hoffset >> 8) & 7); + regs.bgofs_latchdata = data; } +//BG1VOFS void sPPU::mmio_w210e(uint8 data) { + bg1.regs.voffset = (data << 8) | regs.bgofs_latchdata; + regs.bgofs_latchdata = data; } +//BG2HOFS void sPPU::mmio_w210f(uint8 data) { + bg2.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg2.regs.hoffset >> 8) & 7); + regs.bgofs_latchdata = data; } +//BG2VOFS void sPPU::mmio_w2110(uint8 data) { + bg2.regs.voffset = (data << 8) | regs.bgofs_latchdata; + regs.bgofs_latchdata = data; } +//BG3HOFS void sPPU::mmio_w2111(uint8 data) { + bg3.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg3.regs.hoffset >> 8) & 7); + regs.bgofs_latchdata = data; } +//BG3VOFS void sPPU::mmio_w2112(uint8 data) { + bg3.regs.voffset = (data << 8) | regs.bgofs_latchdata; + regs.bgofs_latchdata = data; } +//BG4HOFS void sPPU::mmio_w2113(uint8 data) { + bg4.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg4.regs.hoffset >> 8) & 7); + regs.bgofs_latchdata = data; } +//BG4VOFS void sPPU::mmio_w2114(uint8 data) { + bg4.regs.voffset = (data << 8) | regs.bgofs_latchdata; + regs.bgofs_latchdata = data; } //VMAIN @@ -270,10 +397,20 @@ void sPPU::mmio_w212a(uint8 data) { void sPPU::mmio_w212b(uint8 data) { } +//TM void sPPU::mmio_w212c(uint8 data) { + bg4.regs.main_enabled = data & 0x08; + bg3.regs.main_enabled = data & 0x04; + bg2.regs.main_enabled = data & 0x02; + bg1.regs.main_enabled = data & 0x01; } +//TS void sPPU::mmio_w212d(uint8 data) { + bg4.regs.sub_enabled = data & 0x08; + bg3.regs.sub_enabled = data & 0x04; + bg2.regs.sub_enabled = data & 0x02; + bg1.regs.sub_enabled = data & 0x01; } void sPPU::mmio_w212e(uint8 data) { @@ -405,7 +542,7 @@ uint8 sPPU::mmio_r213f() { regs.latch_vcounter = 0; regs.ppu2_mdr &= 0x20; - regs.ppu2_mdr |= cpu.field() << 7; + regs.ppu2_mdr |= field() << 7; if((cpu.pio() & 0x80) == 0) { regs.ppu2_mdr |= 0x40; } else if(regs.counters_latched) { @@ -421,9 +558,11 @@ void sPPU::mmio_reset() { regs.ppu1_mdr = 0xff; regs.ppu2_mdr = 0xff; + regs.mosaic_countdown = 0; regs.vram_readbuffer = 0x0000; regs.oam_latchdata = 0x00; regs.cgram_latchdata = 0x00; + regs.bgofs_latchdata = 0x00; regs.m7_latchdata = 0x00; regs.counters_latched = false; regs.latch_hcounter = 0; @@ -440,6 +579,13 @@ void sPPU::mmio_reset() { regs.oam_priority = false; regs.oam_firstsprite = 0; + //$2105 BGMODE + regs.bg3_priority = false; + regs.bgmode = 0; + + //$2106 MOSAIC + regs.mosaic_size = 0; + //$2115 VMAIN regs.vram_incmode = 1; regs.vram_mapping = 0; diff --git a/src/snes/ppu/sppu/mmio/mmio.hpp b/src/snes/ppu/sppu/mmio/mmio.hpp index 478f77d4..2dc1ab37 100644 --- a/src/snes/ppu/sppu/mmio/mmio.hpp +++ b/src/snes/ppu/sppu/mmio/mmio.hpp @@ -2,9 +2,11 @@ struct { uint8 ppu1_mdr; uint8 ppu2_mdr; + unsigned mosaic_countdown; uint16 vram_readbuffer; uint8 oam_latchdata; uint8 cgram_latchdata; + uint8 bgofs_latchdata; uint8 m7_latchdata; bool counters_latched; bool latch_hcounter; @@ -21,6 +23,13 @@ struct { bool oam_priority; uint8 oam_firstsprite; + //$2105 BGMODE + bool bg3_priority; + uint8 bgmode; + + //$2106 MOSAIC + uint8 mosaic_size; + //$2115 VMAIN bool vram_incmode; uint8 vram_mapping; diff --git a/src/snes/ppu/sppu/screen/screen.cpp b/src/snes/ppu/sppu/screen/screen.cpp new file mode 100644 index 00000000..fda1dcc9 --- /dev/null +++ b/src/snes/ppu/sppu/screen/screen.cpp @@ -0,0 +1,54 @@ +#ifdef SPPU_CPP + +void sPPU::Screen::scanline() { + output = self.output + self.vcounter() * 1024; +} + +void sPPU::Screen::run() { + unsigned priority = 0; + uint16 color; + + if(self.bg1.output.main.valid) { + priority = self.bg1.output.main.priority; + color = self.bg1.output.main.color; + } + if(self.bg2.output.main.valid && self.bg2.output.main.priority > priority) { + priority = self.bg2.output.main.priority; + color = self.bg2.output.main.color; + } + if(self.bg3.output.main.valid && self.bg3.output.main.priority > priority) { + priority = self.bg3.output.main.priority; + color = self.bg3.output.main.color; + } + if(self.bg4.output.main.valid && self.bg4.output.main.priority > priority) { + priority = self.bg4.output.main.priority; + color = self.bg4.output.main.color; + } + if(priority == 0) { + color = (memory::cgram[1] << 8) + (memory::cgram[0] << 0); + } + + color = light_table[self.regs.display_brightness][color]; + if(self.regs.display_disabled) color = 0; + *output++ = color; + *output++ = color; +} + +sPPU::Screen::Screen(sPPU &self) : self(self) { + //generate light table + for(unsigned l = 0; l < 16; l++) { + for(unsigned r = 0; r < 32; r++) { + for(unsigned g = 0; g < 32; g++) { + for(unsigned b = 0; b < 32; b++) { + double luma = (double)l / 15.0; + unsigned ar = (luma * r + 0.5); + unsigned ag = (luma * g + 0.5); + unsigned ab = (luma * b + 0.5); + light_table[l][(b << 10) + (g << 5) + r] = (ab << 10) + (ag << 5) + ar; + } + } + } + } +} + +#endif diff --git a/src/snes/ppu/sppu/screen/screen.hpp b/src/snes/ppu/sppu/screen/screen.hpp new file mode 100644 index 00000000..4ac44dc4 --- /dev/null +++ b/src/snes/ppu/sppu/screen/screen.hpp @@ -0,0 +1,13 @@ +class Screen { +public: + sPPU &self; + uint16 *output; + + void scanline(); + void run(); + + Screen(sPPU &self); + +private: + uint16 light_table[16][32768]; +}; diff --git a/src/snes/ppu/sppu/sppu.cpp b/src/snes/ppu/sppu/sppu.cpp index 4c770f97..52024b22 100644 --- a/src/snes/ppu/sppu/sppu.cpp +++ b/src/snes/ppu/sppu/sppu.cpp @@ -3,7 +3,9 @@ #define SPPU_CPP namespace SNES { +#include "background/background.cpp" #include "mmio/mmio.cpp" +#include "screen/screen.cpp" #if !defined(DEBUGGER) sPPU ppu; @@ -17,14 +19,29 @@ void sPPU::enter() { add_clocks(88); + //mosaic + if(vcounter() == 1) { + bg1.regs.mosaic_y = 1; + bg2.regs.mosaic_y = 1; + bg3.regs.mosaic_y = 1; + bg4.regs.mosaic_y = 1; + } else { + if(!bg1.regs.mosaic || !regs.mosaic_countdown) bg1.regs.mosaic_y = vcounter(); + if(!bg2.regs.mosaic || !regs.mosaic_countdown) bg2.regs.mosaic_y = vcounter(); + if(!bg3.regs.mosaic || !regs.mosaic_countdown) bg3.regs.mosaic_y = vcounter(); + if(!bg4.regs.mosaic || !regs.mosaic_countdown) bg4.regs.mosaic_y = vcounter(); + if(!regs.mosaic_countdown) regs.mosaic_countdown = regs.mosaic_size + 1; + regs.mosaic_countdown--; + } + if(vcounter() >= 1 && vcounter() <= 224) { - uint16_t *buffer = output + vcounter() * 1024; + screen.scanline(); for(unsigned n = 0; n < 256; n++) { - uint16 color = (memory::cgram[1] << 8) + (memory::cgram[0] << 0); - color = light_table[regs.display_brightness][color]; - if(regs.display_disabled) color = 0; - *buffer++ = color; - *buffer++ = color; + bg1.run(); + bg2.run(); + bg3.run(); + bg4.run(); + screen.run(); add_clocks(4); } } else { @@ -36,20 +53,12 @@ void sPPU::enter() { } void sPPU::add_clocks(unsigned clocks) { - #if 0 - //asynchronous execution - tick(clocks); - scheduler.addclocks_ppu(clocks); - scheduler.sync_ppucpu(); - #else - //synchronous execution clocks >>= 1; while(clocks--) { tick(2); scheduler.addclocks_ppu(2); scheduler.sync_ppucpu(); } - #endif } void sPPU::power() { @@ -74,21 +83,12 @@ void sPPU::frame() { system.frame(); } -sPPU::sPPU() { - //generate light table for INIDISP::d3-d0 - for(unsigned l = 0; l < 16; l++) { - for(unsigned r = 0; r < 32; r++) { - for(unsigned g = 0; g < 32; g++) { - for(unsigned b = 0; b < 32; b++) { - double luma = (double)l / 15.0; - unsigned ar = (luma * r + 0.5); - unsigned ag = (luma * g + 0.5); - unsigned ab = (luma * b + 0.5); - light_table[l][(b << 10) + (g << 5) + r] = (ab << 10) + (ag << 5) + ar; - } - } - } - } +sPPU::sPPU() : +bg1(*this, Background::ID::BG1), +bg2(*this, Background::ID::BG2), +bg3(*this, Background::ID::BG3), +bg4(*this, Background::ID::BG4), +screen(*this) { } } diff --git a/src/snes/ppu/sppu/sppu.hpp b/src/snes/ppu/sppu/sppu.hpp index ce3aa596..4aa9c288 100644 --- a/src/snes/ppu/sppu/sppu.hpp +++ b/src/snes/ppu/sppu/sppu.hpp @@ -1,6 +1,14 @@ class sPPU : public PPU { public: + #include "background/background.hpp" #include "mmio/mmio.hpp" + #include "screen/screen.hpp" + + Background bg1; + Background bg2; + Background bg3; + Background bg4; + Screen screen; void enter(); void add_clocks(unsigned); @@ -12,9 +20,6 @@ public: void frame(); sPPU(); - -private: - uint16 light_table[16][32768]; }; #if !defined(DEBUGGER) diff --git a/src/snes/snes.hpp b/src/snes/snes.hpp index 9a29c227..acb04b47 100644 --- a/src/snes/snes.hpp +++ b/src/snes/snes.hpp @@ -1,4 +1,4 @@ -static const char bsnesVersion[] = "063.07"; +static const char bsnesVersion[] = "063.08"; static const char bsnesTitle[] = "bsnes"; static const unsigned bsnesSerializerVersion = 9; @@ -6,7 +6,7 @@ static const unsigned bsnesSerializerVersion = 9; #define CORE_SCPU #define CORE_SSMP #define CORE_SDSP -#define CORE_BPPU +#define CORE_SPPU //S-DSP can be encapsulated into a state machine using #define magic //this avoids ~2.048m co_switch() calls per second (~5% speedup)