From 23238a848f7d2671851e3a8b591f7b3bd0d6598a Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Tue, 8 Apr 2025 15:34:44 +1000 Subject: [PATCH] Remove (old) BSNES' unmanaged source and the binary --- .github/workflows/waterbox-cores.yml | 1 - Assets/dll/libsnes.wbx.zst | Bin 346254 -> 0 bytes waterbox/libsnes/0.87 | 0 waterbox/libsnes/Makefile | 63 - waterbox/libsnes/bsnes/base/base.cpp | 12 - waterbox/libsnes/bsnes/base/base.hpp | 169 -- waterbox/libsnes/bsnes/gameboy/apu/apu.cpp | 106 -- waterbox/libsnes/bsnes/gameboy/apu/apu.hpp | 26 - .../bsnes/gameboy/apu/master/master.cpp | 99 - .../bsnes/gameboy/apu/master/master.hpp | 23 - .../libsnes/bsnes/gameboy/apu/noise/noise.cpp | 89 - .../libsnes/bsnes/gameboy/apu/noise/noise.hpp | 26 - .../bsnes/gameboy/apu/square1/square1.cpp | 134 -- .../bsnes/gameboy/apu/square1/square1.hpp | 35 - .../bsnes/gameboy/apu/square2/square2.cpp | 91 - .../bsnes/gameboy/apu/square2/square2.hpp | 26 - .../libsnes/bsnes/gameboy/apu/wave/wave.cpp | 83 - .../libsnes/bsnes/gameboy/apu/wave/wave.hpp | 21 - .../bsnes/gameboy/cartridge/cartridge.cpp | 154 -- .../bsnes/gameboy/cartridge/cartridge.hpp | 65 - .../bsnes/gameboy/cartridge/huc1/huc1.cpp | 54 - .../bsnes/gameboy/cartridge/huc1/huc1.hpp | 10 - .../bsnes/gameboy/cartridge/huc3/huc3.cpp | 53 - .../bsnes/gameboy/cartridge/huc3/huc3.hpp | 9 - .../bsnes/gameboy/cartridge/mbc0/mbc0.cpp | 25 - .../bsnes/gameboy/cartridge/mbc0/mbc0.hpp | 5 - .../bsnes/gameboy/cartridge/mbc1/mbc1.cpp | 70 - .../bsnes/gameboy/cartridge/mbc1/mbc1.hpp | 10 - .../bsnes/gameboy/cartridge/mbc2/mbc2.cpp | 42 - .../bsnes/gameboy/cartridge/mbc2/mbc2.hpp | 8 - .../bsnes/gameboy/cartridge/mbc3/mbc3.cpp | 120 -- .../bsnes/gameboy/cartridge/mbc3/mbc3.hpp | 24 - .../bsnes/gameboy/cartridge/mbc5/mbc5.cpp | 53 - .../bsnes/gameboy/cartridge/mbc5/mbc5.hpp | 9 - .../bsnes/gameboy/cartridge/mmm01/mmm01.cpp | 65 - .../bsnes/gameboy/cartridge/mmm01/mmm01.hpp | 12 - .../libsnes/bsnes/gameboy/cpu/core/core.cpp | 689 ------- .../libsnes/bsnes/gameboy/cpu/core/core.hpp | 146 -- .../bsnes/gameboy/cpu/core/disassembler.cpp | 560 ------ .../bsnes/gameboy/cpu/core/registers.hpp | 101 -- .../libsnes/bsnes/gameboy/cpu/core/table.cpp | 519 ------ waterbox/libsnes/bsnes/gameboy/cpu/cpu.cpp | 226 --- waterbox/libsnes/bsnes/gameboy/cpu/cpu.hpp | 106 -- .../libsnes/bsnes/gameboy/cpu/mmio/mmio.cpp | 278 --- .../libsnes/bsnes/gameboy/cpu/mmio/mmio.hpp | 4 - .../bsnes/gameboy/cpu/timing/opcode.cpp | 28 - .../bsnes/gameboy/cpu/timing/timing.cpp | 96 - .../bsnes/gameboy/cpu/timing/timing.hpp | 13 - waterbox/libsnes/bsnes/gameboy/gameboy.hpp | 47 - .../bsnes/gameboy/interface/interface.cpp | 27 - .../bsnes/gameboy/interface/interface.hpp | 15 - waterbox/libsnes/bsnes/gameboy/lcd/cgb.cpp | 185 -- waterbox/libsnes/bsnes/gameboy/lcd/dmg.cpp | 145 -- waterbox/libsnes/bsnes/gameboy/lcd/lcd.cpp | 157 -- waterbox/libsnes/bsnes/gameboy/lcd/lcd.hpp | 93 - .../libsnes/bsnes/gameboy/lcd/mmio/mmio.cpp | 203 --- .../libsnes/bsnes/gameboy/lcd/mmio/mmio.hpp | 3 - .../libsnes/bsnes/gameboy/memory/memory.cpp | 57 - .../libsnes/bsnes/gameboy/memory/memory.hpp | 32 - .../bsnes/gameboy/scheduler/scheduler.cpp | 35 - .../bsnes/gameboy/scheduler/scheduler.hpp | 17 - .../bsnes/gameboy/system/bootrom-cgb.cpp | 135 -- .../bsnes/gameboy/system/bootrom-dmg.cpp | 23 - .../bsnes/gameboy/system/bootrom-sgb.cpp | 23 - .../libsnes/bsnes/gameboy/system/system.cpp | 55 - .../libsnes/bsnes/gameboy/system/system.hpp | 38 - .../libsnes/bsnes/gameboy/video/video.cpp | 82 - .../libsnes/bsnes/gameboy/video/video.hpp | 17 - waterbox/libsnes/bsnes/nall/algorithm.hpp | 17 - waterbox/libsnes/bsnes/nall/any.hpp | 72 - waterbox/libsnes/bsnes/nall/array.hpp | 289 --- waterbox/libsnes/bsnes/nall/atoi.hpp | 101 -- waterbox/libsnes/bsnes/nall/base64.hpp | 90 - waterbox/libsnes/bsnes/nall/bit.hpp | 69 - waterbox/libsnes/bsnes/nall/bmp.hpp | 101 -- waterbox/libsnes/bsnes/nall/bps/delta.hpp | 214 --- waterbox/libsnes/bsnes/nall/bps/linear.hpp | 152 -- waterbox/libsnes/bsnes/nall/bps/metadata.hpp | 121 -- waterbox/libsnes/bsnes/nall/bps/patch.hpp | 219 --- waterbox/libsnes/bsnes/nall/compositor.hpp | 152 -- waterbox/libsnes/bsnes/nall/config.hpp | 126 -- waterbox/libsnes/bsnes/nall/crc32.hpp | 66 - waterbox/libsnes/bsnes/nall/directory.hpp | 153 -- waterbox/libsnes/bsnes/nall/dl.hpp | 115 -- waterbox/libsnes/bsnes/nall/dsp.hpp | 13 - waterbox/libsnes/bsnes/nall/dsp/buffer.hpp | 51 - waterbox/libsnes/bsnes/nall/dsp/core.hpp | 168 -- .../bsnes/nall/dsp/resample/average.hpp | 72 - .../bsnes/nall/dsp/resample/cosine.hpp | 45 - .../libsnes/bsnes/nall/dsp/resample/cubic.hpp | 50 - .../bsnes/nall/dsp/resample/hermite.hpp | 62 - .../bsnes/nall/dsp/resample/lib/sinc.hpp | 602 ------- .../bsnes/nall/dsp/resample/linear.hpp | 43 - .../bsnes/nall/dsp/resample/nearest.hpp | 43 - .../libsnes/bsnes/nall/dsp/resample/sinc.hpp | 54 - waterbox/libsnes/bsnes/nall/dsp/settings.hpp | 50 - waterbox/libsnes/bsnes/nall/endian.hpp | 42 - waterbox/libsnes/bsnes/nall/file.hpp | 291 --- waterbox/libsnes/bsnes/nall/filemap.hpp | 213 --- waterbox/libsnes/bsnes/nall/function.hpp | 60 - .../libsnes/bsnes/nall/gameboy/cartridge.hpp | 127 -- waterbox/libsnes/bsnes/nall/gzip.hpp | 87 - waterbox/libsnes/bsnes/nall/http.hpp | 176 -- waterbox/libsnes/bsnes/nall/image.hpp | 465 ----- waterbox/libsnes/bsnes/nall/inflate.hpp | 358 ---- waterbox/libsnes/bsnes/nall/input.hpp | 386 ---- waterbox/libsnes/bsnes/nall/interpolation.hpp | 59 - waterbox/libsnes/bsnes/nall/intrinsics.hpp | 63 - waterbox/libsnes/bsnes/nall/ips.hpp | 110 -- waterbox/libsnes/bsnes/nall/lzss.hpp | 165 -- waterbox/libsnes/bsnes/nall/map.hpp | 116 -- waterbox/libsnes/bsnes/nall/moduloarray.hpp | 36 - waterbox/libsnes/bsnes/nall/mosaic.hpp | 10 - .../libsnes/bsnes/nall/mosaic/bitstream.hpp | 55 - .../libsnes/bsnes/nall/mosaic/context.hpp | 224 --- waterbox/libsnes/bsnes/nall/mosaic/parser.hpp | 126 -- waterbox/libsnes/bsnes/nall/platform.hpp | 155 -- waterbox/libsnes/bsnes/nall/png.hpp | 339 ---- waterbox/libsnes/bsnes/nall/priorityqueue.hpp | 100 -- waterbox/libsnes/bsnes/nall/property.hpp | 97 - waterbox/libsnes/bsnes/nall/public_cast.hpp | 32 - waterbox/libsnes/bsnes/nall/random.hpp | 28 - .../libsnes/bsnes/nall/reference_array.hpp | 142 -- waterbox/libsnes/bsnes/nall/serial.hpp | 85 - waterbox/libsnes/bsnes/nall/serializer.hpp | 167 -- waterbox/libsnes/bsnes/nall/sha256.hpp | 145 -- .../libsnes/bsnes/nall/snes/cartridge.hpp | 886 --------- waterbox/libsnes/bsnes/nall/snes/cpu.hpp | 458 ----- waterbox/libsnes/bsnes/nall/snes/smp.hpp | 639 ------- waterbox/libsnes/bsnes/nall/snes/usart.hpp | 70 - waterbox/libsnes/bsnes/nall/sort.hpp | 77 - waterbox/libsnes/bsnes/nall/stdint.hpp | 42 - waterbox/libsnes/bsnes/nall/stream.hpp | 26 - waterbox/libsnes/bsnes/nall/stream/auto.hpp | 24 - waterbox/libsnes/bsnes/nall/stream/file.hpp | 31 - waterbox/libsnes/bsnes/nall/stream/gzip.hpp | 28 - waterbox/libsnes/bsnes/nall/stream/http.hpp | 43 - waterbox/libsnes/bsnes/nall/stream/memory.hpp | 40 - waterbox/libsnes/bsnes/nall/stream/mmap.hpp | 36 - waterbox/libsnes/bsnes/nall/stream/stream.hpp | 90 - waterbox/libsnes/bsnes/nall/stream/zip.hpp | 30 - waterbox/libsnes/bsnes/nall/string.hpp | 51 - waterbox/libsnes/bsnes/nall/string/base.hpp | 200 --- waterbox/libsnes/bsnes/nall/string/bml.hpp | 151 -- waterbox/libsnes/bsnes/nall/string/bsv.hpp | 76 - waterbox/libsnes/bsnes/nall/string/cast.hpp | 189 -- .../libsnes/bsnes/nall/string/compare.hpp | 69 - .../libsnes/bsnes/nall/string/convert.hpp | 64 - waterbox/libsnes/bsnes/nall/string/core.hpp | 163 -- .../libsnes/bsnes/nall/string/cstring.hpp | 21 - .../libsnes/bsnes/nall/string/filename.hpp | 62 - .../bsnes/nall/string/math-fixed-point.hpp | 166 -- .../bsnes/nall/string/math-floating-point.hpp | 157 -- .../libsnes/bsnes/nall/string/platform.hpp | 39 - .../libsnes/bsnes/nall/string/replace.hpp | 51 - waterbox/libsnes/bsnes/nall/string/split.hpp | 36 - waterbox/libsnes/bsnes/nall/string/strm.hpp | 45 - waterbox/libsnes/bsnes/nall/string/strpos.hpp | 33 - waterbox/libsnes/bsnes/nall/string/trim.hpp | 38 - waterbox/libsnes/bsnes/nall/string/utf8.hpp | 43 - .../libsnes/bsnes/nall/string/utility.hpp | 285 --- .../libsnes/bsnes/nall/string/variadic.hpp | 11 - .../libsnes/bsnes/nall/string/wildcard.hpp | 78 - .../libsnes/bsnes/nall/string/wrapper.hpp | 42 - .../libsnes/bsnes/nall/string/xml-legacy.hpp | 265 --- waterbox/libsnes/bsnes/nall/string/xml.hpp | 250 --- waterbox/libsnes/bsnes/nall/type_traits.hpp | 33 - waterbox/libsnes/bsnes/nall/ups.hpp | 223 --- waterbox/libsnes/bsnes/nall/utility.hpp | 32 - waterbox/libsnes/bsnes/nall/varint.hpp | 192 -- waterbox/libsnes/bsnes/nall/vector.hpp | 459 ----- .../libsnes/bsnes/nall/windows/detour.hpp | 192 -- .../libsnes/bsnes/nall/windows/launcher.hpp | 94 - waterbox/libsnes/bsnes/nall/windows/utf8.hpp | 86 - waterbox/libsnes/bsnes/nall/xorg/guard.hpp | 29 - waterbox/libsnes/bsnes/nall/xorg/xorg.hpp | 12 - waterbox/libsnes/bsnes/nall/zip.hpp | 124 -- waterbox/libsnes/bsnes/snes/alt/cpu/cpu.cpp | 189 -- waterbox/libsnes/bsnes/snes/alt/cpu/cpu.hpp | 160 -- waterbox/libsnes/bsnes/snes/alt/cpu/dma.cpp | 205 --- .../libsnes/bsnes/snes/alt/cpu/memory.cpp | 49 - waterbox/libsnes/bsnes/snes/alt/cpu/mmio.cpp | 308 ---- .../libsnes/bsnes/snes/alt/cpu/timing.cpp | 123 -- .../libsnes/bsnes/snes/alt/dsp/SPC_DSP.cpp | 1032 ----------- waterbox/libsnes/bsnes/snes/alt/dsp/SPC_DSP.h | 304 ---- .../bsnes/snes/alt/dsp/blargg_common.h | 186 -- .../bsnes/snes/alt/dsp/blargg_config.h | 24 - .../bsnes/snes/alt/dsp/blargg_endian.h | 185 -- .../bsnes/snes/alt/dsp/blargg_source.h | 100 -- waterbox/libsnes/bsnes/snes/alt/dsp/dsp.cpp | 65 - waterbox/libsnes/bsnes/snes/alt/dsp/dsp.hpp | 26 - .../alt/ppu-compatibility/memory/memory.cpp | 157 -- .../alt/ppu-compatibility/memory/memory.hpp | 10 - .../snes/alt/ppu-compatibility/mmio/mmio.cpp | 671 ------- .../snes/alt/ppu-compatibility/mmio/mmio.hpp | 202 --- .../bsnes/snes/alt/ppu-compatibility/ppu.cpp | 453 ----- .../bsnes/snes/alt/ppu-compatibility/ppu.hpp | 77 - .../alt/ppu-compatibility/render/addsub.cpp | 25 - .../snes/alt/ppu-compatibility/render/bg.cpp | 209 --- .../alt/ppu-compatibility/render/cache.cpp | 149 -- .../alt/ppu-compatibility/render/line.cpp | 118 -- .../alt/ppu-compatibility/render/mode7.cpp | 143 -- .../snes/alt/ppu-compatibility/render/oam.cpp | 237 --- .../alt/ppu-compatibility/render/render.cpp | 129 -- .../alt/ppu-compatibility/render/render.hpp | 99 - .../alt/ppu-compatibility/render/windows.cpp | 70 - .../ppu-performance/background/background.cpp | 184 -- .../ppu-performance/background/background.hpp | 65 - .../alt/ppu-performance/background/mode7.cpp | 105 -- .../snes/alt/ppu-performance/cache/cache.cpp | 134 -- .../snes/alt/ppu-performance/cache/cache.hpp | 17 - .../snes/alt/ppu-performance/mmio/mmio.cpp | 891 --------- .../snes/alt/ppu-performance/mmio/mmio.hpp | 95 - .../bsnes/snes/alt/ppu-performance/ppu.cpp | 160 -- .../bsnes/snes/alt/ppu-performance/ppu.hpp | 69 - .../alt/ppu-performance/screen/screen.cpp | 155 -- .../alt/ppu-performance/screen/screen.hpp | 43 - .../alt/ppu-performance/sprite/sprite.cpp | 190 -- .../alt/ppu-performance/sprite/sprite.hpp | 70 - .../alt/ppu-performance/window/window.cpp | 98 - .../alt/ppu-performance/window/window.hpp | 35 - .../libsnes/bsnes/snes/alt/smp/algorithms.cpp | 122 -- waterbox/libsnes/bsnes/snes/alt/smp/core.cpp | 107 -- .../libsnes/bsnes/snes/alt/smp/core/cc.sh | 1 - .../bsnes/snes/alt/smp/core/generate.cpp | 154 -- .../libsnes/bsnes/snes/alt/smp/core/op_misc.b | 163 -- .../bsnes/snes/alt/smp/core/op_misc.cpp | 346 ---- .../libsnes/bsnes/snes/alt/smp/core/op_mov.b | 217 --- .../bsnes/snes/alt/smp/core/op_mov.cpp | 389 ---- .../libsnes/bsnes/snes/alt/smp/core/op_pc.b | 179 -- .../libsnes/bsnes/snes/alt/smp/core/op_pc.cpp | 603 ------- .../libsnes/bsnes/snes/alt/smp/core/op_read.b | 205 --- .../bsnes/snes/alt/smp/core/op_read.cpp | 744 -------- .../libsnes/bsnes/snes/alt/smp/core/op_rmw.b | 74 - .../bsnes/snes/alt/smp/core/op_rmw.cpp | 262 --- .../bsnes/snes/alt/smp/core/opcycle_misc.cpp | 696 ------- .../bsnes/snes/alt/smp/core/opcycle_mov.cpp | 806 --------- .../bsnes/snes/alt/smp/core/opcycle_pc.cpp | 1347 -------------- .../bsnes/snes/alt/smp/core/opcycle_read.cpp | 1599 ----------------- .../bsnes/snes/alt/smp/core/opcycle_rmw.cpp | 550 ------ .../bsnes/snes/alt/smp/disassembler.cpp | 304 ---- .../libsnes/bsnes/snes/alt/smp/iplrom.cpp | 44 - .../libsnes/bsnes/snes/alt/smp/memory.cpp | 130 -- waterbox/libsnes/bsnes/snes/alt/smp/smp.cpp | 101 -- waterbox/libsnes/bsnes/snes/alt/smp/smp.hpp | 117 -- .../libsnes/bsnes/snes/alt/smp/timing.cpp | 26 - .../bsnes/snes/cartridge/cartridge.cpp | 95 - .../bsnes/snes/cartridge/cartridge.hpp | 119 -- .../libsnes/bsnes/snes/cartridge/markup.cpp | 596 ------ .../libsnes/bsnes/snes/chip/armdsp/armdsp.cpp | 187 -- .../libsnes/bsnes/snes/chip/armdsp/armdsp.hpp | 66 - .../bsnes/snes/chip/armdsp/disassembler.cpp | 246 --- .../libsnes/bsnes/snes/chip/armdsp/memory.cpp | 86 - .../bsnes/snes/chip/armdsp/opcodes.cpp | 404 ----- .../bsnes/snes/chip/armdsp/registers.hpp | 123 -- waterbox/libsnes/bsnes/snes/chip/bsx/bsx.cpp | 8 - waterbox/libsnes/bsnes/snes/chip/bsx/bsx.hpp | 3 - .../snes/chip/bsx/cartridge/cartridge.cpp | 152 -- .../snes/chip/bsx/cartridge/cartridge.hpp | 34 - .../bsnes/snes/chip/bsx/flash/flash.cpp | 127 -- .../bsnes/snes/chip/bsx/flash/flash.hpp | 27 - .../snes/chip/bsx/satellaview/satellaview.cpp | 142 -- .../snes/chip/bsx/satellaview/satellaview.hpp | 26 - waterbox/libsnes/bsnes/snes/chip/chip.hpp | 31 - .../bsnes/snes/chip/hitachidsp/hitachidsp.cpp | 81 - .../bsnes/snes/chip/hitachidsp/hitachidsp.hpp | 48 - .../bsnes/snes/chip/hitachidsp/memory.cpp | 138 -- .../bsnes/snes/chip/hitachidsp/opcodes.cpp | 356 ---- .../bsnes/snes/chip/hitachidsp/registers.cpp | 78 - .../bsnes/snes/chip/hitachidsp/registers.hpp | 31 - .../libsnes/bsnes/snes/chip/icd2/icd2.cpp | 82 - .../libsnes/bsnes/snes/chip/icd2/icd2.hpp | 24 - .../snes/chip/icd2/interface/interface.cpp | 118 -- .../snes/chip/icd2/interface/interface.hpp | 25 - .../bsnes/snes/chip/icd2/mmio/mmio.cpp | 96 - .../bsnes/snes/chip/icd2/mmio/mmio.hpp | 19 - .../libsnes/bsnes/snes/chip/link/link.cpp | 59 - .../libsnes/bsnes/snes/chip/link/link.hpp | 24 - .../libsnes/bsnes/snes/chip/msu1/msu1.cpp | 136 -- .../libsnes/bsnes/snes/chip/msu1/msu1.hpp | 41 - .../bsnes/snes/chip/necdsp/disassembler.cpp | 196 -- .../libsnes/bsnes/snes/chip/necdsp/memory.cpp | 74 - .../libsnes/bsnes/snes/chip/necdsp/necdsp.cpp | 307 ---- .../libsnes/bsnes/snes/chip/necdsp/necdsp.hpp | 49 - .../bsnes/snes/chip/necdsp/registers.hpp | 51 - waterbox/libsnes/bsnes/snes/chip/nss/nss.cpp | 39 - waterbox/libsnes/bsnes/snes/chip/nss/nss.hpp | 17 - .../libsnes/bsnes/snes/chip/obc1/obc1.cpp | 78 - .../libsnes/bsnes/snes/chip/obc1/obc1.hpp | 23 - .../libsnes/bsnes/snes/chip/sa1/bus/bus.cpp | 34 - .../libsnes/bsnes/snes/chip/sa1/bus/bus.hpp | 14 - .../libsnes/bsnes/snes/chip/sa1/dma/dma.cpp | 139 -- .../libsnes/bsnes/snes/chip/sa1/dma/dma.hpp | 11 - .../bsnes/snes/chip/sa1/memory/memory.cpp | 267 --- .../bsnes/snes/chip/sa1/memory/memory.hpp | 19 - .../libsnes/bsnes/snes/chip/sa1/mmio/mmio.cpp | 554 ------ .../libsnes/bsnes/snes/chip/sa1/mmio/mmio.hpp | 255 --- waterbox/libsnes/bsnes/snes/chip/sa1/sa1.cpp | 330 ---- waterbox/libsnes/bsnes/snes/chip/sa1/sa1.hpp | 36 - .../libsnes/bsnes/snes/chip/sdd1/decomp.cpp | 287 --- .../libsnes/bsnes/snes/chip/sdd1/decomp.hpp | 82 - .../libsnes/bsnes/snes/chip/sdd1/sdd1.cpp | 151 -- .../libsnes/bsnes/snes/chip/sdd1/sdd1.hpp | 35 - .../bsnes/snes/chip/spc7110/decomp.cpp | 500 ------ .../bsnes/snes/chip/spc7110/decomp.hpp | 43 - .../bsnes/snes/chip/spc7110/spc7110.cpp | 704 -------- .../bsnes/snes/chip/spc7110/spc7110.hpp | 132 -- .../libsnes/bsnes/snes/chip/srtc/srtc.cpp | 241 --- .../libsnes/bsnes/snes/chip/srtc/srtc.hpp | 28 - .../snes/chip/sufamiturbo/sufamiturbo.cpp | 38 - .../snes/chip/sufamiturbo/sufamiturbo.hpp | 14 - .../bsnes/snes/chip/superfx/bus/bus.cpp | 38 - .../bsnes/snes/chip/superfx/bus/bus.hpp | 11 - .../bsnes/snes/chip/superfx/core/core.cpp | 107 -- .../bsnes/snes/chip/superfx/core/core.hpp | 92 - .../snes/chip/superfx/core/opcode_table.cpp | 270 --- .../bsnes/snes/chip/superfx/core/opcodes.cpp | 661 ------- .../snes/chip/superfx/core/registers.hpp | 176 -- .../bsnes/snes/chip/superfx/disasm/disasm.cpp | 279 --- .../bsnes/snes/chip/superfx/disasm/disasm.hpp | 5 - .../bsnes/snes/chip/superfx/memory/memory.cpp | 114 -- .../bsnes/snes/chip/superfx/memory/memory.hpp | 14 - .../bsnes/snes/chip/superfx/mmio/mmio.cpp | 118 -- .../bsnes/snes/chip/superfx/mmio/mmio.hpp | 2 - .../bsnes/snes/chip/superfx/superfx.cpp | 81 - .../bsnes/snes/chip/superfx/superfx.hpp | 23 - .../bsnes/snes/chip/superfx/timing/timing.cpp | 97 - .../bsnes/snes/chip/superfx/timing/timing.hpp | 19 - waterbox/libsnes/bsnes/snes/config/config.cpp | 26 - waterbox/libsnes/bsnes/snes/config/config.hpp | 35 - .../bsnes/snes/controller/controller.cpp | 54 - .../bsnes/snes/controller/controller.hpp | 36 - .../bsnes/snes/controller/gamepad/gamepad.cpp | 21 - .../bsnes/snes/controller/gamepad/gamepad.hpp | 8 - .../snes/controller/justifier/justifier.cpp | 126 -- .../snes/controller/justifier/justifier.hpp | 17 - .../bsnes/snes/controller/mouse/mouse.cpp | 76 - .../bsnes/snes/controller/mouse/mouse.hpp | 10 - .../snes/controller/multitap/multitap.cpp | 49 - .../snes/controller/multitap/multitap.hpp | 11 - .../snes/controller/superscope/superscope.cpp | 121 -- .../snes/controller/superscope/superscope.hpp | 22 - .../bsnes/snes/controller/usart/usart.cpp | 103 -- .../bsnes/snes/controller/usart/usart.hpp | 28 - .../bsnes/snes/cpu/core/algorithms.cpp | 331 ---- waterbox/libsnes/bsnes/snes/cpu/core/core.cpp | 88 - waterbox/libsnes/bsnes/snes/cpu/core/core.hpp | 216 --- .../cpu/core/disassembler/disassembler.cpp | 448 ----- .../cpu/core/disassembler/disassembler.hpp | 29 - .../libsnes/bsnes/snes/cpu/core/memory.hpp | 89 - .../bsnes/snes/cpu/core/opcode_misc.cpp | 338 ---- .../libsnes/bsnes/snes/cpu/core/opcode_pc.cpp | 181 -- .../bsnes/snes/cpu/core/opcode_read.cpp | 279 --- .../bsnes/snes/cpu/core/opcode_rmw.cpp | 169 -- .../bsnes/snes/cpu/core/opcode_write.cpp | 199 -- .../libsnes/bsnes/snes/cpu/core/registers.hpp | 83 - .../libsnes/bsnes/snes/cpu/core/table.cpp | 312 ---- waterbox/libsnes/bsnes/snes/cpu/cpu.cpp | 179 -- waterbox/libsnes/bsnes/snes/cpu/cpu.hpp | 150 -- waterbox/libsnes/bsnes/snes/cpu/dma/dma.cpp | 290 --- waterbox/libsnes/bsnes/snes/cpu/dma/dma.hpp | 79 - .../libsnes/bsnes/snes/cpu/memory/memory.cpp | 46 - .../libsnes/bsnes/snes/cpu/memory/memory.hpp | 4 - waterbox/libsnes/bsnes/snes/cpu/mmio/mmio.cpp | 523 ------ waterbox/libsnes/bsnes/snes/cpu/mmio/mmio.hpp | 71 - .../libsnes/bsnes/snes/cpu/timing/irq.cpp | 106 -- .../libsnes/bsnes/snes/cpu/timing/joypad.cpp | 33 - .../libsnes/bsnes/snes/cpu/timing/timing.cpp | 205 --- .../libsnes/bsnes/snes/cpu/timing/timing.hpp | 24 - waterbox/libsnes/bsnes/snes/dsp/brr.cpp | 62 - waterbox/libsnes/bsnes/snes/dsp/counter.cpp | 52 - waterbox/libsnes/bsnes/snes/dsp/dsp.cpp | 307 ---- waterbox/libsnes/bsnes/snes/dsp/dsp.hpp | 171 -- waterbox/libsnes/bsnes/snes/dsp/echo.cpp | 135 -- waterbox/libsnes/bsnes/snes/dsp/envelope.cpp | 62 - waterbox/libsnes/bsnes/snes/dsp/gaussian.cpp | 54 - waterbox/libsnes/bsnes/snes/dsp/misc.cpp | 35 - waterbox/libsnes/bsnes/snes/dsp/voice.cpp | 174 -- .../bsnes/snes/interface/interface.cpp | 45 - .../bsnes/snes/interface/interface.hpp | 38 - .../bsnes/snes/memory/memory-inline.hpp | 68 - waterbox/libsnes/bsnes/snes/memory/memory.cpp | 78 - waterbox/libsnes/bsnes/snes/memory/memory.hpp | 80 - .../bsnes/snes/ppu/background/background.cpp | 277 --- .../bsnes/snes/ppu/background/background.hpp | 77 - .../bsnes/snes/ppu/background/mode7.cpp | 110 -- .../bsnes/snes/ppu/counter/counter-inline.hpp | 85 - .../bsnes/snes/ppu/counter/counter.hpp | 48 - waterbox/libsnes/bsnes/snes/ppu/mmio/mmio.cpp | 894 --------- waterbox/libsnes/bsnes/snes/ppu/mmio/mmio.hpp | 165 -- waterbox/libsnes/bsnes/snes/ppu/ppu.cpp | 173 -- waterbox/libsnes/bsnes/snes/ppu/ppu.hpp | 73 - .../libsnes/bsnes/snes/ppu/screen/screen.cpp | 210 --- .../libsnes/bsnes/snes/ppu/screen/screen.hpp | 35 - .../libsnes/bsnes/snes/ppu/sprite/list.cpp | 58 - .../libsnes/bsnes/snes/ppu/sprite/sprite.cpp | 223 --- .../libsnes/bsnes/snes/ppu/sprite/sprite.hpp | 81 - .../libsnes/bsnes/snes/ppu/window/window.cpp | 169 -- .../libsnes/bsnes/snes/ppu/window/window.hpp | 87 - .../libsnes/bsnes/snes/profile-accuracy.hpp | 8 - .../bsnes/snes/profile-compatibility.hpp | 8 - .../bsnes/snes/profile-performance.hpp | 12 - waterbox/libsnes/bsnes/snes/random/random.cpp | 14 - waterbox/libsnes/bsnes/snes/random/random.hpp | 10 - .../bsnes/snes/scheduler/scheduler.cpp | 32 - .../bsnes/snes/scheduler/scheduler.hpp | 19 - .../bsnes/snes/smp/core/algorithms.cpp | 138 -- waterbox/libsnes/bsnes/snes/smp/core/core.cpp | 271 --- waterbox/libsnes/bsnes/snes/smp/core/core.hpp | 95 - .../bsnes/snes/smp/core/disassembler.cpp | 311 ---- .../libsnes/bsnes/snes/smp/core/memory.hpp | 28 - .../libsnes/bsnes/snes/smp/core/opcodes.cpp | 559 ------ .../libsnes/bsnes/snes/smp/core/registers.hpp | 51 - waterbox/libsnes/bsnes/snes/smp/iplrom.cpp | 44 - .../libsnes/bsnes/snes/smp/memory/memory.cpp | 203 --- .../libsnes/bsnes/snes/smp/memory/memory.hpp | 9 - waterbox/libsnes/bsnes/snes/smp/smp.cpp | 139 -- waterbox/libsnes/bsnes/snes/smp/smp.hpp | 61 - .../libsnes/bsnes/snes/smp/timing/timing.cpp | 62 - .../libsnes/bsnes/snes/smp/timing/timing.hpp | 21 - waterbox/libsnes/bsnes/snes/snes.hpp | 64 - waterbox/libsnes/bsnes/snes/system/audio.cpp | 69 - waterbox/libsnes/bsnes/snes/system/audio.hpp | 20 - waterbox/libsnes/bsnes/snes/system/input.cpp | 39 - waterbox/libsnes/bsnes/snes/system/input.hpp | 39 - waterbox/libsnes/bsnes/snes/system/system.cpp | 264 --- waterbox/libsnes/bsnes/snes/system/system.hpp | 45 - waterbox/libsnes/bsnes/snes/system/video.cpp | 103 -- waterbox/libsnes/bsnes/snes/system/video.hpp | 19 - .../libsnes/bsnes/target-libsnes/libsnes.cpp | 701 -------- .../libsnes/bsnes/target-libsnes/libsnes.hpp | 263 --- .../bsnes/target-libsnes/libsnes_pwrap.cpp | 700 -------- waterbox/libsnes/libco_debugging/build.sh | 2 - waterbox/libsnes/libco_debugging/libco.h | 34 - .../libco_debugging/libco_win32threads.c | 138 -- waterbox/libsnes/libco_debugging/makefile | 2 - ...01-Don-t-use-time-in-emulating-chips.patch | 84 - ...ve-controller-state-when-savestating.patch | 346 ---- ...ontend-to-control-random-number-seed.patch | 53 - .../0004-Fix-mouse-polling.patch | 60 - waterbox/make-all-cores.sh | 1 - waterbox/readme.txt | 1 - 442 files changed, 62765 deletions(-) delete mode 100644 Assets/dll/libsnes.wbx.zst delete mode 100644 waterbox/libsnes/0.87 delete mode 100644 waterbox/libsnes/Makefile delete mode 100644 waterbox/libsnes/bsnes/base/base.cpp delete mode 100644 waterbox/libsnes/bsnes/base/base.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/apu/apu.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/apu/apu.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/apu/master/master.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/apu/master/master.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/apu/noise/noise.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/apu/noise/noise.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/apu/square1/square1.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/apu/square1/square1.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/apu/square2/square2.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/apu/square2/square2.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/apu/wave/wave.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/apu/wave/wave.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/cartridge.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/cartridge.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/huc1/huc1.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/huc1/huc1.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/huc3/huc3.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/huc3/huc3.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/mbc0/mbc0.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/mbc0/mbc0.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/mbc1/mbc1.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/mbc1/mbc1.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/mbc2/mbc2.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/mbc2/mbc2.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/mbc3/mbc3.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/mbc3/mbc3.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/mbc5/mbc5.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/mbc5/mbc5.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/mmm01/mmm01.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cartridge/mmm01/mmm01.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cpu/core/core.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cpu/core/core.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cpu/core/disassembler.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cpu/core/registers.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cpu/core/table.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cpu/cpu.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cpu/cpu.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cpu/mmio/mmio.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cpu/mmio/mmio.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cpu/timing/opcode.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cpu/timing/timing.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/cpu/timing/timing.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/gameboy.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/interface/interface.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/interface/interface.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/lcd/cgb.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/lcd/dmg.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/lcd/lcd.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/lcd/lcd.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/lcd/mmio/mmio.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/lcd/mmio/mmio.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/memory/memory.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/memory/memory.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/scheduler/scheduler.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/scheduler/scheduler.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/system/bootrom-cgb.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/system/bootrom-dmg.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/system/bootrom-sgb.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/system/system.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/system/system.hpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/video/video.cpp delete mode 100644 waterbox/libsnes/bsnes/gameboy/video/video.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/algorithm.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/any.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/array.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/atoi.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/base64.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/bit.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/bmp.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/bps/delta.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/bps/linear.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/bps/metadata.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/bps/patch.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/compositor.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/config.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/crc32.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/directory.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/dl.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/dsp.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/dsp/buffer.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/dsp/core.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/dsp/resample/average.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/dsp/resample/cosine.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/dsp/resample/cubic.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/dsp/resample/hermite.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/dsp/resample/lib/sinc.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/dsp/resample/linear.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/dsp/resample/nearest.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/dsp/resample/sinc.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/dsp/settings.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/endian.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/file.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/filemap.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/function.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/gameboy/cartridge.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/gzip.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/http.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/image.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/inflate.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/input.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/interpolation.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/intrinsics.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/ips.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/lzss.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/map.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/moduloarray.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/mosaic.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/mosaic/bitstream.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/mosaic/context.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/mosaic/parser.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/platform.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/png.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/priorityqueue.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/property.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/public_cast.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/random.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/reference_array.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/serial.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/serializer.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/sha256.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/snes/cartridge.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/snes/cpu.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/snes/smp.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/snes/usart.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/sort.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/stdint.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/stream.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/stream/auto.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/stream/file.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/stream/gzip.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/stream/http.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/stream/memory.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/stream/mmap.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/stream/stream.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/stream/zip.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/base.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/bml.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/bsv.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/cast.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/compare.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/convert.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/core.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/cstring.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/filename.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/math-fixed-point.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/math-floating-point.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/platform.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/replace.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/split.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/strm.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/strpos.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/trim.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/utf8.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/utility.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/variadic.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/wildcard.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/wrapper.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/xml-legacy.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/string/xml.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/type_traits.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/ups.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/utility.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/varint.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/vector.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/windows/detour.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/windows/launcher.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/windows/utf8.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/xorg/guard.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/xorg/xorg.hpp delete mode 100644 waterbox/libsnes/bsnes/nall/zip.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/cpu/cpu.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/cpu/cpu.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/cpu/dma.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/cpu/memory.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/cpu/mmio.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/cpu/timing.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/dsp/SPC_DSP.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/dsp/SPC_DSP.h delete mode 100644 waterbox/libsnes/bsnes/snes/alt/dsp/blargg_common.h delete mode 100644 waterbox/libsnes/bsnes/snes/alt/dsp/blargg_config.h delete mode 100644 waterbox/libsnes/bsnes/snes/alt/dsp/blargg_endian.h delete mode 100644 waterbox/libsnes/bsnes/snes/alt/dsp/blargg_source.h delete mode 100644 waterbox/libsnes/bsnes/snes/alt/dsp/dsp.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/dsp/dsp.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/memory/memory.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/memory/memory.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/mmio/mmio.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/mmio/mmio.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/ppu.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/ppu.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/addsub.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/bg.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/cache.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/line.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/mode7.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/oam.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/render.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/render.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/windows.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-performance/background/background.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-performance/background/background.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-performance/background/mode7.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-performance/cache/cache.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-performance/cache/cache.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-performance/mmio/mmio.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-performance/mmio/mmio.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-performance/ppu.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-performance/ppu.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-performance/screen/screen.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-performance/screen/screen.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-performance/sprite/sprite.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-performance/sprite/sprite.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-performance/window/window.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/ppu-performance/window/window.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/algorithms.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core/cc.sh delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core/generate.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core/op_misc.b delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core/op_misc.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core/op_mov.b delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core/op_mov.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core/op_pc.b delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core/op_pc.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core/op_read.b delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core/op_read.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core/op_rmw.b delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core/op_rmw.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_misc.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_mov.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_pc.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_read.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_rmw.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/disassembler.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/iplrom.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/memory.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/smp.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/smp.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/alt/smp/timing.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cartridge/cartridge.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cartridge/cartridge.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/cartridge/markup.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/armdsp/armdsp.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/armdsp/armdsp.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/armdsp/disassembler.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/armdsp/memory.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/armdsp/opcodes.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/armdsp/registers.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/bsx/bsx.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/bsx/bsx.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/bsx/cartridge/cartridge.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/bsx/cartridge/cartridge.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/bsx/flash/flash.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/bsx/flash/flash.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/bsx/satellaview/satellaview.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/bsx/satellaview/satellaview.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/chip.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/hitachidsp/hitachidsp.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/hitachidsp/hitachidsp.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/hitachidsp/memory.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/hitachidsp/opcodes.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/hitachidsp/registers.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/hitachidsp/registers.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/icd2/icd2.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/icd2/icd2.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/icd2/interface/interface.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/icd2/interface/interface.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/icd2/mmio/mmio.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/icd2/mmio/mmio.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/link/link.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/link/link.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/msu1/msu1.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/msu1/msu1.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/necdsp/disassembler.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/necdsp/memory.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/necdsp/necdsp.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/necdsp/necdsp.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/necdsp/registers.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/nss/nss.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/nss/nss.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/obc1/obc1.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/obc1/obc1.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/sa1/bus/bus.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/sa1/bus/bus.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/sa1/dma/dma.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/sa1/dma/dma.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/sa1/memory/memory.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/sa1/memory/memory.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/sa1/mmio/mmio.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/sa1/mmio/mmio.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/sa1/sa1.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/sa1/sa1.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/sdd1/decomp.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/sdd1/decomp.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/sdd1/sdd1.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/sdd1/sdd1.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/spc7110/decomp.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/spc7110/decomp.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/spc7110/spc7110.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/spc7110/spc7110.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/srtc/srtc.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/srtc/srtc.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/sufamiturbo/sufamiturbo.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/sufamiturbo/sufamiturbo.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/superfx/bus/bus.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/superfx/bus/bus.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/superfx/core/core.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/superfx/core/core.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/superfx/core/opcode_table.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/superfx/core/opcodes.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/superfx/core/registers.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/superfx/disasm/disasm.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/superfx/disasm/disasm.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/superfx/memory/memory.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/superfx/memory/memory.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/superfx/mmio/mmio.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/superfx/mmio/mmio.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/superfx/superfx.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/superfx/superfx.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/superfx/timing/timing.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/chip/superfx/timing/timing.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/config/config.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/config/config.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/controller/controller.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/controller/controller.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/controller/gamepad/gamepad.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/controller/gamepad/gamepad.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/controller/justifier/justifier.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/controller/justifier/justifier.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/controller/mouse/mouse.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/controller/mouse/mouse.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/controller/multitap/multitap.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/controller/multitap/multitap.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/controller/superscope/superscope.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/controller/superscope/superscope.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/controller/usart/usart.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/controller/usart/usart.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/core/algorithms.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/core/core.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/core/core.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/core/disassembler/disassembler.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/core/disassembler/disassembler.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/core/memory.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/core/opcode_misc.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/core/opcode_pc.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/core/opcode_read.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/core/opcode_rmw.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/core/opcode_write.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/core/registers.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/core/table.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/cpu.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/cpu.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/dma/dma.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/dma/dma.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/memory/memory.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/memory/memory.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/mmio/mmio.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/mmio/mmio.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/timing/irq.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/timing/joypad.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/timing/timing.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/cpu/timing/timing.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/dsp/brr.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/dsp/counter.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/dsp/dsp.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/dsp/dsp.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/dsp/echo.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/dsp/envelope.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/dsp/gaussian.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/dsp/misc.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/dsp/voice.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/interface/interface.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/interface/interface.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/memory/memory-inline.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/memory/memory.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/memory/memory.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/ppu/background/background.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/ppu/background/background.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/ppu/background/mode7.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/ppu/counter/counter-inline.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/ppu/counter/counter.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/ppu/mmio/mmio.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/ppu/mmio/mmio.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/ppu/ppu.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/ppu/ppu.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/ppu/screen/screen.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/ppu/screen/screen.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/ppu/sprite/list.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/ppu/sprite/sprite.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/ppu/sprite/sprite.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/ppu/window/window.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/ppu/window/window.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/profile-accuracy.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/profile-compatibility.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/profile-performance.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/random/random.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/random/random.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/scheduler/scheduler.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/scheduler/scheduler.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/smp/core/algorithms.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/smp/core/core.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/smp/core/core.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/smp/core/disassembler.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/smp/core/memory.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/smp/core/opcodes.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/smp/core/registers.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/smp/iplrom.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/smp/memory/memory.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/smp/memory/memory.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/smp/smp.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/smp/smp.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/smp/timing/timing.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/smp/timing/timing.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/snes.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/system/audio.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/system/audio.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/system/input.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/system/input.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/system/system.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/system/system.hpp delete mode 100644 waterbox/libsnes/bsnes/snes/system/video.cpp delete mode 100644 waterbox/libsnes/bsnes/snes/system/video.hpp delete mode 100644 waterbox/libsnes/bsnes/target-libsnes/libsnes.cpp delete mode 100644 waterbox/libsnes/bsnes/target-libsnes/libsnes.hpp delete mode 100644 waterbox/libsnes/bsnes/target-libsnes/libsnes_pwrap.cpp delete mode 100644 waterbox/libsnes/libco_debugging/build.sh delete mode 100644 waterbox/libsnes/libco_debugging/libco.h delete mode 100644 waterbox/libsnes/libco_debugging/libco_win32threads.c delete mode 100644 waterbox/libsnes/libco_debugging/makefile delete mode 100644 waterbox/libsnes/lsnes_patches/0001-Don-t-use-time-in-emulating-chips.patch delete mode 100644 waterbox/libsnes/lsnes_patches/0002-Save-controller-state-when-savestating.patch delete mode 100644 waterbox/libsnes/lsnes_patches/0003-Allow-frontend-to-control-random-number-seed.patch delete mode 100644 waterbox/libsnes/lsnes_patches/0004-Fix-mouse-polling.patch diff --git a/.github/workflows/waterbox-cores.yml b/.github/workflows/waterbox-cores.yml index 56e2d26964..70aea9f2ce 100644 --- a/.github/workflows/waterbox-cores.yml +++ b/.github/workflows/waterbox-cores.yml @@ -65,7 +65,6 @@ jobs: Assets/dll/faust.wbx.zst Assets/dll/gpgx.wbx.zst Assets/dll/hyper.wbx.zst - Assets/dll/libsnes.wbx.zst Assets/dll/melonDS.wbx.zst Assets/dll/ngp.wbx.zst Assets/dll/pcfx.wbx.zst diff --git a/Assets/dll/libsnes.wbx.zst b/Assets/dll/libsnes.wbx.zst deleted file mode 100644 index 41a956ebb5924cc399863fad8424cc1fbbfcceaf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 346254 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

*og5Log7IdhHB8px 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 z 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

~J`w5{mO)Fd`W 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 diff --git a/waterbox/libsnes/0.87 b/waterbox/libsnes/0.87 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/waterbox/libsnes/Makefile b/waterbox/libsnes/Makefile deleted file mode 100644 index 4a0dba8405..0000000000 --- a/waterbox/libsnes/Makefile +++ /dev/null @@ -1,63 +0,0 @@ -NEED_LIBCO := 1 - -#-DPROFILE_PERFORMANCE -CXXFLAGS := -DHOOKS -DBIZHAWK -DPROFILE_COMPATIBILITY -DGAMEBOY \ - -D_GNU_SOURCE \ - -Werror=int-to-pointer-cast \ - -I../libco -I./bsnes \ - -Wno-parentheses -Wno-sign-compare -Wno-unused-variable -Wno-unused-function \ - -Wno-switch -Wno-switch-bool -Wno-reorder -Wno-return-type -Wno-bool-operation \ - -Wno-mismatched-tags -Wno-delete-non-virtual-dtor \ - -fno-threadsafe-statics \ - -std=gnu++17 - -TARGET = libsnes.wbx - -SRCS_PERF = \ - $(ROOT_DIR)/bsnes/snes/alt/cpu/cpu.cpp \ - $(ROOT_DIR)/bsnes/snes/alt/ppu-performance/ppu.cpp \ - $(ROOT_DIR)/bsnes/snes/alt/smp/smp.cpp -SRCS_COMPAT = \ - $(ROOT_DIR)/bsnes/snes/alt/ppu-compatibility/ppu.cpp \ - $(ROOT_DIR)/bsnes/snes/cpu/cpu.cpp \ - $(ROOT_DIR)/bsnes/snes/smp/smp.cpp -SRCS_ALL = \ - $(ROOT_DIR)/bsnes/base/base.cpp \ - $(ROOT_DIR)/bsnes/gameboy/apu/apu.cpp \ - $(ROOT_DIR)/bsnes/gameboy/cartridge/cartridge.cpp \ - $(ROOT_DIR)/bsnes/gameboy/cpu/cpu.cpp \ - $(ROOT_DIR)/bsnes/snes/alt/dsp/dsp.cpp \ - $(ROOT_DIR)/bsnes/gameboy/interface/interface.cpp \ - $(ROOT_DIR)/bsnes/gameboy/lcd/lcd.cpp \ - $(ROOT_DIR)/bsnes/gameboy/memory/memory.cpp \ - $(ROOT_DIR)/bsnes/gameboy/scheduler/scheduler.cpp \ - $(ROOT_DIR)/bsnes/gameboy/system/system.cpp \ - $(ROOT_DIR)/bsnes/gameboy/video/video.cpp \ - $(ROOT_DIR)/bsnes/snes/cartridge/cartridge.cpp \ - $(ROOT_DIR)/bsnes/snes/chip/armdsp/armdsp.cpp \ - $(ROOT_DIR)/bsnes/snes/chip/bsx/bsx.cpp \ - $(ROOT_DIR)/bsnes/snes/chip/hitachidsp/hitachidsp.cpp \ - $(ROOT_DIR)/bsnes/snes/chip/icd2/icd2.cpp \ - $(ROOT_DIR)/bsnes/snes/chip/link/link.cpp \ - $(ROOT_DIR)/bsnes/snes/chip/msu1/msu1.cpp \ - $(ROOT_DIR)/bsnes/snes/chip/necdsp/necdsp.cpp \ - $(ROOT_DIR)/bsnes/snes/chip/nss/nss.cpp \ - $(ROOT_DIR)/bsnes/snes/chip/obc1/obc1.cpp \ - $(ROOT_DIR)/bsnes/snes/chip/sa1/sa1.cpp \ - $(ROOT_DIR)/bsnes/snes/chip/sdd1/sdd1.cpp \ - $(ROOT_DIR)/bsnes/snes/chip/spc7110/spc7110.cpp \ - $(ROOT_DIR)/bsnes/snes/chip/srtc/srtc.cpp \ - $(ROOT_DIR)/bsnes/snes/chip/sufamiturbo/sufamiturbo.cpp \ - $(ROOT_DIR)/bsnes/snes/chip/superfx/superfx.cpp \ - $(ROOT_DIR)/bsnes/snes/config/config.cpp \ - $(ROOT_DIR)/bsnes/snes/controller/controller.cpp \ - $(ROOT_DIR)/bsnes/snes/cpu/core/core.cpp \ - $(ROOT_DIR)/bsnes/snes/interface/interface.cpp \ - $(ROOT_DIR)/bsnes/snes/memory/memory.cpp \ - $(ROOT_DIR)/bsnes/snes/smp/core/core.cpp \ - $(ROOT_DIR)/bsnes/snes/system/system.cpp \ - $(ROOT_DIR)/bsnes/target-libsnes/libsnes.cpp \ - $(ROOT_DIR)/bsnes/target-libsnes/libsnes_pwrap.cpp -SRCS = $(SRCS_ALL) $(SRCS_COMPAT) - -include ../common.mak diff --git a/waterbox/libsnes/bsnes/base/base.cpp b/waterbox/libsnes/bsnes/base/base.cpp deleted file mode 100644 index ccb246012c..0000000000 --- a/waterbox/libsnes/bsnes/base/base.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "base.hpp" - -#include "snes/snes.hpp" - -CDLInfo cdlInfo; - -void CDLInfo::dorom(uint32_t addr) -{ - blocks[eCDLog_AddrType_CARTROM_DB][addr] = SNES::cpu.regs.db; - blocks[eCDLog_AddrType_CARTROM_D][addr*2+0] = SNES::cpu.regs.d; - blocks[eCDLog_AddrType_CARTROM_D][addr*2+1] = SNES::cpu.regs.d>>8; -} diff --git a/waterbox/libsnes/bsnes/base/base.hpp b/waterbox/libsnes/bsnes/base/base.hpp deleted file mode 100644 index b02db8abef..0000000000 --- a/waterbox/libsnes/bsnes/base/base.hpp +++ /dev/null @@ -1,169 +0,0 @@ -#ifndef BASE_HPP -#define BASE_HPP - -const char Version[] = "087"; - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -using namespace nall; - -//debugging function hook: -//no overhead (and no debugger invocation) if not compiled with -DDEBUGGER -//wraps testing of function to allow invocation without a defined callback -template struct hook; -template struct hook { - function callback; - - R operator()(P... p) const { - #if defined(DEBUGGER) || defined(HOOKS) - if(callback) return callback(std::forward

(p)...); - #endif - return R(); - } - - hook() {} - hook(const hook &hook) { callback = hook.callback; } - hook(void *function) { callback = function; } - hook(R (*function)(P...)) { callback = function; } - template hook(R (C::*function)(P...), C *object) { callback = { function, object }; } - template hook(R (C::*function)(P...) const, C *object) { callback = { function, object }; } - template hook(const L& function) { callback = function; } - - hook& operator=(const hook& hook) { callback = hook.callback; return *this; } -}; - -#if defined(DEBUGGER) - #define privileged public -#else - #define privileged private -#endif - -enum eCDLog_AddrType -{ - eCDLog_AddrType_CARTROM, eCDLog_AddrType_CARTROM_DB, eCDLog_AddrType_CARTROM_D, eCDLog_AddrType_CARTRAM, eCDLog_AddrType_WRAM, eCDLog_AddrType_APURAM, - eCDLog_AddrType_SGB_CARTROM, eCDLog_AddrType_SGB_CARTRAM, eCDLog_AddrType_SGB_WRAM, eCDLog_AddrType_SGB_HRAM, - eCDLog_AddrType_NUM -}; - -enum eCDLog_Flags -{ - eCDLog_Flags_None = 0x00, - eCDLog_Flags_ExecFirst = 0x01, - eCDLog_Flags_ExecOperand = 0x02, - eCDLog_Flags_CPUData = 0x04, - eCDLog_Flags_DMAData = 0x08, - eCDLog_Flags_CPUXFlag = 0x10, //these values are picky, don't change them - eCDLog_Flags_CPUMFlag = 0x20, //these values are picky, don't change them - eCDLog_Flags_BRR = 0x80 -}; - -struct CDLInfo -{ - eCDLog_Flags currFlags; - uint8_t* blocks[16]; //[0]==nullptr -> disabled - uint32_t blockSizes[16]; - void set(eCDLog_AddrType addrType, uint32_t addr) - { - if(!blocks[0]) return; - if(addr >= blockSizes[addrType]) - return; - blocks[addrType][addr] |= currFlags; - if(addrType == eCDLog_AddrType_CARTROM) - { - dorom(addr); - } - } - void dorom(uint32_t addr); -}; - -extern CDLInfo cdlInfo; -inline bool wantCDL() { return cdlInfo.blocks[0] != nullptr; } - -typedef int1_t int1; -typedef int2_t int2; -typedef int3_t int3; -typedef int4_t int4; -typedef int5_t int5; -typedef int6_t int6; -typedef int7_t int7; -typedef int8_t int8; -typedef int9_t int9; -typedef int10_t int10; -typedef int11_t int11; -typedef int12_t int12; -typedef int13_t int13; -typedef int14_t int14; -typedef int15_t int15; -typedef int16_t int16; -typedef int17_t int17; -typedef int18_t int18; -typedef int19_t int19; -typedef int20_t int20; -typedef int21_t int21; -typedef int22_t int22; -typedef int23_t int23; -typedef int24_t int24; -typedef int25_t int25; -typedef int26_t int26; -typedef int27_t int27; -typedef int28_t int28; -typedef int29_t int29; -typedef int30_t int30; -typedef int31_t int31; -typedef int32_t int32; -typedef int64_t int64; - -typedef uint1_t uint1; -typedef uint2_t uint2; -typedef uint3_t uint3; -typedef uint4_t uint4; -typedef uint5_t uint5; -typedef uint6_t uint6; -typedef uint7_t uint7; -typedef uint8_t uint8; -typedef uint9_t uint9; -typedef uint10_t uint10; -typedef uint11_t uint11; -typedef uint12_t uint12; -typedef uint13_t uint13; -typedef uint14_t uint14; -typedef uint15_t uint15; -typedef uint16_t uint16; -typedef uint17_t uint17; -typedef uint18_t uint18; -typedef uint19_t uint19; -typedef uint20_t uint20; -typedef uint21_t uint21; -typedef uint22_t uint22; -typedef uint23_t uint23; -typedef uint24_t uint24; -typedef uint25_t uint25; -typedef uint26_t uint26; -typedef uint27_t uint27; -typedef uint28_t uint28; -typedef uint29_t uint29; -typedef uint30_t uint30; -typedef uint31_t uint31; -typedef uint32_t uint32; -typedef uint_t<33> uint33; -typedef uint64_t uint64; - -typedef varuint_t varuint; - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/apu/apu.cpp b/waterbox/libsnes/bsnes/gameboy/apu/apu.cpp deleted file mode 100644 index 25cd2bc393..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/apu/apu.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include - -#define APU_CPP -namespace GameBoy { - -#include "square1/square1.cpp" -#include "square2/square2.cpp" -#include "wave/wave.cpp" -#include "noise/noise.cpp" -#include "master/master.cpp" -APU apu; - -void APU::Main() { - apu.main(); -} - -void APU::main() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - if(sequencer_base == 0) { //512hz - if(sequencer_step == 0 || sequencer_step == 2 || sequencer_step == 4 || sequencer_step == 6) { //256hz - square1.clock_length(); - square2.clock_length(); - wave.clock_length(); - noise.clock_length(); - } - if(sequencer_step == 2 || sequencer_step == 6) { //128hz - square1.clock_sweep(); - } - if(sequencer_step == 7) { //64hz - square1.clock_envelope(); - square2.clock_envelope(); - noise.clock_envelope(); - } - sequencer_step++; - } - sequencer_base++; - - square1.run(); - square2.run(); - wave.run(); - noise.run(); - master.run(); - - interface->audioSample(master.center, master.left, master.right); - - clock += 1 * cpu.frequency; - if(clock >= 0) co_switch(scheduler.active_thread = cpu.thread); - } -} - -void APU::power() { - create(Main, 4 * 1024 * 1024); - for(unsigned n = 0xff10; n <= 0xff3f; n++) bus.mmio[n] = this; - - for(auto &n : mmio_data) n = 0x00; - sequencer_base = 0; - sequencer_step = 0; - - square1.power(); - square2.power(); - wave.power(); - noise.power(); - master.power(); -} - -uint8 APU::mmio_read(uint16 addr) { - static const uint8 table[48] = { - 0x80, 0x3f, 0x00, 0xff, 0xbf, //square1 - 0xff, 0x3f, 0x00, 0xff, 0xbf, //square2 - 0x7f, 0xff, 0x9f, 0xff, 0xbf, //wave - 0xff, 0xff, 0x00, 0x00, 0xbf, //noise - 0x00, 0x00, 0x70, //master - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, //unmapped - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //wave pattern - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //wave pattern - }; - - if(addr == 0xff26) { - uint8 data = master.enable << 7; - if(square1.enable) data |= 0x01; - if(square2.enable) data |= 0x02; - if( wave.enable) data |= 0x04; - if( noise.enable) data |= 0x08; - return data | table[addr - 0xff10]; - } - - if(addr >= 0xff10 && addr <= 0xff3f) return mmio_data[addr - 0xff10] | table[addr - 0xff10]; - return 0xff; -} - -void APU::mmio_write(uint16 addr, uint8 data) { - if(addr >= 0xff10 && addr <= 0xff3f) mmio_data[addr - 0xff10] = data; - - if(addr >= 0xff10 && addr <= 0xff14) return square1.write (addr - 0xff10, data); - if(addr >= 0xff15 && addr <= 0xff19) return square2.write (addr - 0xff15, data); - if(addr >= 0xff1a && addr <= 0xff1e) return wave.write (addr - 0xff1a, data); - if(addr >= 0xff1f && addr <= 0xff23) return noise.write (addr - 0xff1f, data); - if(addr >= 0xff24 && addr <= 0xff26) return master.write (addr - 0xff24, data); - if(addr >= 0xff30 && addr <= 0xff3f) return wave.write_pattern(addr - 0xff30, data); -} - -} diff --git a/waterbox/libsnes/bsnes/gameboy/apu/apu.hpp b/waterbox/libsnes/bsnes/gameboy/apu/apu.hpp deleted file mode 100644 index b33f6cf6f2..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/apu/apu.hpp +++ /dev/null @@ -1,26 +0,0 @@ -struct APU : Processor, MMIO { - #include "square1/square1.hpp" - #include "square2/square2.hpp" - #include "wave/wave.hpp" - #include "noise/noise.hpp" - #include "master/master.hpp" - - uint8 mmio_data[48]; - uint13 sequencer_base; - uint3 sequencer_step; - - Square1 square1; - Square2 square2; - Wave wave; - Noise noise; - Master master; - - static void Main(); - void main(); - void power(); - - uint8 mmio_read(uint16 addr); - void mmio_write(uint16 addr, uint8 data); -}; - -extern APU apu; diff --git a/waterbox/libsnes/bsnes/gameboy/apu/master/master.cpp b/waterbox/libsnes/bsnes/gameboy/apu/master/master.cpp deleted file mode 100644 index 40414a59ec..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/apu/master/master.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#ifdef APU_CPP - -void APU::Master::run() { - if(enable == false) { - center = 0; - left = 0; - right = 0; - return; - } - - signed sample = 0; - sample += apu.square1.output; - sample += apu.square2.output; - sample += apu.wave.output; - sample += apu.noise.output; - center = (sample * 512) - 16384; - - sample = 0; - if(channel1_left_enable) sample += apu.square1.output; - if(channel2_left_enable) sample += apu.square2.output; - if(channel3_left_enable) sample += apu.wave.output; - if(channel4_left_enable) sample += apu.noise.output; - left = (sample * 512) - 16384; - - switch(left_volume) { - case 0: left >>= 3; break; // 12.5% - case 1: left >>= 2; break; // 25.0% - case 2: left = (left >> 2) + (left >> 3); break; // 37.5% - case 3: left >>= 1; break; // 50.0% - case 4: left = (left >> 1) + (left >> 3); break; // 62.5% - case 5: left -= (left >> 2); break; // 75.0% - case 6: left -= (left >> 3); break; // 87.5% - //case 7: break; //100.0% - } - - sample = 0; - if(channel1_right_enable) sample += apu.square1.output; - if(channel2_right_enable) sample += apu.square2.output; - if(channel3_right_enable) sample += apu.wave.output; - if(channel4_right_enable) sample += apu.noise.output; - right = (sample * 512) - 16384; - - switch(right_volume) { - case 0: right >>= 3; break; // 12.5% - case 1: right >>= 2; break; // 25.0% - case 2: right = (right >> 2) + (right >> 3); break; // 37.5% - case 3: right >>= 1; break; // 50.0% - case 4: right = (right >> 1) + (right >> 3); break; // 62.5% - case 5: right -= (right >> 2); break; // 75.0% - case 6: right -= (right >> 3); break; // 87.5% - //case 7: break; //100.0% - } -} - -void APU::Master::write(unsigned r, uint8 data) { - if(r == 0) { //$ff24 NR50 - left_in_enable = data & 0x80; - left_volume = (data >> 4) & 7; - right_in_enable = data & 0x08; - right_volume = (data >> 0) & 7; - } - - if(r == 1) { //$ff25 NR51 - channel4_left_enable = data & 0x80; - channel3_left_enable = data & 0x40; - channel2_left_enable = data & 0x20; - channel1_left_enable = data & 0x10; - channel4_right_enable = data & 0x08; - channel3_right_enable = data & 0x04; - channel2_right_enable = data & 0x02; - channel1_right_enable = data & 0x01; - } - - if(r == 2) { //$ff26 NR52 - enable = data & 0x80; - } -} - -void APU::Master::power() { - left_in_enable = 0; - left_volume = 0; - right_in_enable = 0; - right_volume = 0; - channel4_left_enable = 0; - channel3_left_enable = 0; - channel2_left_enable = 0; - channel1_left_enable = 0; - channel4_right_enable = 0; - channel3_right_enable = 0; - channel2_right_enable = 0; - channel1_right_enable = 0; - enable = 0; - - center = 0; - left = 0; - right = 0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/apu/master/master.hpp b/waterbox/libsnes/bsnes/gameboy/apu/master/master.hpp deleted file mode 100644 index da0212ee85..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/apu/master/master.hpp +++ /dev/null @@ -1,23 +0,0 @@ -struct Master { - bool left_in_enable; - uint3 left_volume; - bool right_in_enable; - uint3 right_volume; - bool channel4_left_enable; - bool channel3_left_enable; - bool channel2_left_enable; - bool channel1_left_enable; - bool channel4_right_enable; - bool channel3_right_enable; - bool channel2_right_enable; - bool channel1_right_enable; - bool enable; - - int16 center; - int16 left; - int16 right; - - void run(); - void write(unsigned r, uint8 data); - void power(); -}; diff --git a/waterbox/libsnes/bsnes/gameboy/apu/noise/noise.cpp b/waterbox/libsnes/bsnes/gameboy/apu/noise/noise.cpp deleted file mode 100644 index e97546bf19..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/apu/noise/noise.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#ifdef APU_CPP - -bool APU::Noise::dac_enable() { - return (envelope_volume || envelope_direction); -} - -void APU::Noise::run() { - if(period && --period == 0) { - period = divisor << frequency; - if(frequency < 14) { - bool bit = (lfsr ^ (lfsr >> 1)) & 1; - lfsr = (lfsr >> 1) ^ (bit << (narrow_lfsr ? 6 : 14)); - } - } - - uint4 sample = (lfsr & 1) ? (uint4)0 : volume; - if(enable == false) sample = 0; - - output = sample; -} - -void APU::Noise::clock_length() { - if(counter && length) { - if(--length == 0) enable = false; - } -} - -void APU::Noise::clock_envelope() { - if(enable && envelope_frequency && --envelope_period == 0) { - envelope_period = envelope_frequency; - if(envelope_direction == 0 && volume > 0) volume--; - if(envelope_direction == 1 && volume < 15) volume++; - } -} - -void APU::Noise::write(unsigned r, uint8 data) { - if(r == 1) { //$ff20 NR41 - length = 64 - (data & 0x3f); - } - - if(r == 2) { //$ff21 NR42 - envelope_volume = data >> 4; - envelope_direction = data & 0x08; - envelope_frequency = data & 0x07; - if(dac_enable() == false) enable = false; - } - - if(r == 3) { //$ff22 NR43 - frequency = data >> 4; - narrow_lfsr = data & 0x08; - divisor = (data & 0x07) << 4; - if(divisor == 0) divisor = 8; - period = divisor << frequency; - } - - if(r == 4) { //$ff34 NR44 - bool initialize = data & 0x80; - counter = data & 0x40; - - if(initialize) { - enable = dac_enable(); - lfsr = ~0U; - envelope_period = envelope_frequency; - volume = envelope_volume; - if(length == 0) length = 64; - } - } -} - -void APU::Noise::power() { - enable = 0; - - envelope_volume = 0; - envelope_direction = 0; - envelope_frequency = 0; - frequency = 0; - narrow_lfsr = 0; - divisor = 0; - counter = 0; - - output = 0; - length = 0; - envelope_period = 0; - volume = 0; - period = 0; - lfsr = 0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/apu/noise/noise.hpp b/waterbox/libsnes/bsnes/gameboy/apu/noise/noise.hpp deleted file mode 100644 index 822de6a80c..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/apu/noise/noise.hpp +++ /dev/null @@ -1,26 +0,0 @@ -struct Noise { - bool enable; - - uint4 envelope_volume; - bool envelope_direction; - uint3 envelope_frequency; - uint4 frequency; - bool narrow_lfsr; - unsigned divisor; - bool counter; - - int16 output; - unsigned length; - uint3 envelope_period; - uint4 volume; - unsigned period; - uint15 lfsr; - - bool dac_enable(); - - void run(); - void clock_length(); - void clock_envelope(); - void write(unsigned r, uint8 data); - void power(); -}; diff --git a/waterbox/libsnes/bsnes/gameboy/apu/square1/square1.cpp b/waterbox/libsnes/bsnes/gameboy/apu/square1/square1.cpp deleted file mode 100644 index 2b05b9c4a7..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/apu/square1/square1.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#ifdef APU_CPP - -bool APU::Square1::dac_enable() { - return (envelope_volume || envelope_direction); -} - -void APU::Square1::run() { - if(period && --period == 0) { - period = 4 * (2048 - frequency); - phase++; - switch(duty) { - case 0: duty_output = (phase == 6); break; //______-_ - case 1: duty_output = (phase >= 6); break; //______-- - case 2: duty_output = (phase >= 4); break; //____---- - case 3: duty_output = (phase <= 5); break; //------__ - } - } - - uint4 sample = (duty_output ? volume : (uint4)0); - if(enable == false) sample = 0; - - output = sample; -} - -void APU::Square1::sweep(bool update) { - if(sweep_enable == false) return; - - sweep_negate = sweep_direction; - unsigned delta = frequency_shadow >> sweep_shift; - signed freq = frequency_shadow + (sweep_negate ? -delta : delta); - - if(freq > 2047) { - enable = false; - } else if(sweep_shift && update) { - frequency_shadow = freq; - frequency = freq & 2047; - period = 4 * (2048 - frequency); - } -} - -void APU::Square1::clock_length() { - if(counter && length) { - if(--length == 0) enable = false; - } -} - -void APU::Square1::clock_sweep() { - if(enable && sweep_frequency && --sweep_period == 0) { - sweep_period = sweep_frequency; - sweep(1); - sweep(0); - } -} - -void APU::Square1::clock_envelope() { - if(enable && envelope_frequency && --envelope_period == 0) { - envelope_period = envelope_frequency; - if(envelope_direction == 0 && volume > 0) volume--; - if(envelope_direction == 1 && volume < 15) volume++; - } -} - -void APU::Square1::write(unsigned r, uint8 data) { - if(r == 0) { //$ff10 NR10 - if(sweep_negate && sweep_direction && !(data & 0x08)) enable = false; - sweep_frequency = (data >> 4) & 7; - sweep_direction = data & 0x08; - sweep_shift = data & 0x07; - } - - if(r == 1) { //$ff11 NR11 - duty = data >> 6; - length = 64 - (data & 0x3f); - } - - if(r == 2) { //$ff12 NR12 - envelope_volume = data >> 4; - envelope_direction = data & 0x08; - envelope_frequency = data & 0x07; - if(dac_enable() == false) enable = false; - } - - if(r == 3) { //$ff13 NR13 - frequency = (frequency & 0x0700) | data; - } - - if(r == 4) { //$ff14 NR14 - bool initialize = data & 0x80; - counter = data & 0x40; - frequency = ((data & 7) << 8) | (frequency & 0x00ff); - - if(initialize) { - enable = dac_enable(); - envelope_period = envelope_frequency; - volume = envelope_volume; - frequency_shadow = frequency; - sweep_period = sweep_frequency; - sweep_enable = sweep_period || sweep_shift; - sweep_negate = false; - if(sweep_shift) sweep(0); - if(length == 0) length = 64; - } - } - - period = 4 * (2048 - frequency); -} - -void APU::Square1::power() { - enable = 0; - - sweep_frequency = 0; - sweep_direction = 0; - sweep_shift = 0; - sweep_negate = 0; - duty = 0; - length = 0; - envelope_volume = 0; - envelope_direction = 0; - envelope_frequency = 0; - frequency = 0; - counter = 0; - - output = 0; - duty_output = 0; - phase = 0; - period = 0; - envelope_period = 0; - sweep_period = 0; - frequency_shadow = 0; - sweep_enable = 0; - volume = 0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/apu/square1/square1.hpp b/waterbox/libsnes/bsnes/gameboy/apu/square1/square1.hpp deleted file mode 100644 index 07d1ab0ac9..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/apu/square1/square1.hpp +++ /dev/null @@ -1,35 +0,0 @@ -struct Square1 { - bool enable; - - uint3 sweep_frequency; - bool sweep_direction; - uint3 sweep_shift; - bool sweep_negate; - uint2 duty; - unsigned length; - uint4 envelope_volume; - bool envelope_direction; - uint3 envelope_frequency; - uint11 frequency; - bool counter; - - int16 output; - bool duty_output; - uint3 phase; - unsigned period; - uint3 envelope_period; - uint3 sweep_period; - signed frequency_shadow; - bool sweep_enable; - uint4 volume; - - bool dac_enable(); - - void run(); - void sweep(bool update); - void clock_length(); - void clock_sweep(); - void clock_envelope(); - void write(unsigned r, uint8 data); - void power(); -}; diff --git a/waterbox/libsnes/bsnes/gameboy/apu/square2/square2.cpp b/waterbox/libsnes/bsnes/gameboy/apu/square2/square2.cpp deleted file mode 100644 index 18713c51fb..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/apu/square2/square2.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#ifdef APU_CPP - -bool APU::Square2::dac_enable() { - return (envelope_volume || envelope_direction); -} - -void APU::Square2::run() { - if(period && --period == 0) { - period = 4 * (2048 - frequency); - phase++; - switch(duty) { - case 0: duty_output = (phase == 6); break; //______-_ - case 1: duty_output = (phase >= 6); break; //______-- - case 2: duty_output = (phase >= 4); break; //____---- - case 3: duty_output = (phase <= 5); break; //------__ - } - } - - uint4 sample = (duty_output ? volume : (uint4)0); - if(enable == false) sample = 0; - - output = sample; -} - -void APU::Square2::clock_length() { - if(counter && length) { - if(--length == 0) enable = false; - } -} - -void APU::Square2::clock_envelope() { - if(enable && envelope_frequency && --envelope_period == 0) { - envelope_period = envelope_frequency; - if(envelope_direction == 0 && volume > 0) volume--; - if(envelope_direction == 1 && volume < 15) volume++; - } -} - -void APU::Square2::write(unsigned r, uint8 data) { - if(r == 1) { //$ff16 NR21 - duty = data >> 6; - length = 64 - (data & 0x3f); - } - - if(r == 2) { //$ff17 NR22 - envelope_volume = data >> 4; - envelope_direction = data & 0x08; - envelope_frequency = data & 0x07; - if(dac_enable() == false) enable = false; - } - - if(r == 3) { //$ff18 NR23 - frequency = (frequency & 0x0700) | data; - } - - if(r == 4) { //$ff19 NR24 - bool initialize = data & 0x80; - counter = data & 0x40; - frequency = ((data & 7) << 8) | (frequency & 0x00ff); - - if(initialize) { - enable = dac_enable(); - envelope_period = envelope_frequency; - volume = envelope_volume; - if(length == 0) length = 64; - } - } - - period = 4 * (2048 - frequency); -} - -void APU::Square2::power() { - enable = 0; - - duty = 0; - length = 0; - envelope_volume = 0; - envelope_direction = 0; - envelope_frequency = 0; - frequency = 0; - counter = 0; - - output = 0; - duty_output = 0; - phase = 0; - period = 0; - envelope_period = 0; - volume = 0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/apu/square2/square2.hpp b/waterbox/libsnes/bsnes/gameboy/apu/square2/square2.hpp deleted file mode 100644 index 4d0d2b730c..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/apu/square2/square2.hpp +++ /dev/null @@ -1,26 +0,0 @@ -struct Square2 { - bool enable; - - uint2 duty; - unsigned length; - uint4 envelope_volume; - bool envelope_direction; - uint3 envelope_frequency; - uint11 frequency; - bool counter; - - int16 output; - bool duty_output; - uint3 phase; - unsigned period; - uint3 envelope_period; - uint4 volume; - - bool dac_enable(); - - void run(); - void clock_length(); - void clock_envelope(); - void write(unsigned r, uint8 data); - void power(); -}; diff --git a/waterbox/libsnes/bsnes/gameboy/apu/wave/wave.cpp b/waterbox/libsnes/bsnes/gameboy/apu/wave/wave.cpp deleted file mode 100644 index 5ab9cb1c03..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/apu/wave/wave.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#ifdef APU_CPP - -void APU::Wave::run() { - if(period && --period == 0) { - period = 2 * (2048 - frequency); - pattern_sample = pattern[++pattern_offset]; - } - - uint4 sample = pattern_sample >> volume_shift; - if(enable == false) sample = 0; - - output = sample; -} - -void APU::Wave::clock_length() { - if(counter && length) { - if(--length == 0) enable = false; - } -} - -void APU::Wave::write(unsigned r, uint8 data) { - if(r == 0) { //$ff1a NR30 - dac_enable = data & 0x80; - if(dac_enable == false) enable = false; - } - - if(r == 1) { //$ff1b NR31 - length = 256 - data; - } - - if(r == 2) { //$ff1c NR32 - switch((data >> 5) & 3) { - case 0: volume_shift = 4; break; // 0% - case 1: volume_shift = 0; break; //100% - case 2: volume_shift = 1; break; // 50% - case 3: volume_shift = 2; break; // 25% - } - } - - if(r == 3) { //$ff1d NR33 - frequency = (frequency & 0x0700) | data; - } - - if(r == 4) { //$ff1e NR34 - bool initialize = data & 0x80; - counter = data & 0x40; - frequency = ((data & 7) << 8) | (frequency & 0x00ff); - - if(initialize) { - enable = dac_enable; - pattern_offset = 0; - if(length == 0) length = 256; - } - } - - period = 2 * (2048 - frequency); -} - -void APU::Wave::write_pattern(unsigned p, uint8 data) { - p <<= 1; - pattern[p + 0] = (data >> 4) & 15; - pattern[p + 1] = (data >> 0) & 15; -} - -void APU::Wave::power() { - enable = 0; - - dac_enable = 0; - volume_shift = 0; - frequency = 0; - counter = 0; - - random_lfsr r; - for(auto &n : pattern) n = r() & 15; - - output = 0; - length = 0; - period = 0; - pattern_offset = 0; - pattern_sample = 0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/apu/wave/wave.hpp b/waterbox/libsnes/bsnes/gameboy/apu/wave/wave.hpp deleted file mode 100644 index cc70043b74..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/apu/wave/wave.hpp +++ /dev/null @@ -1,21 +0,0 @@ -struct Wave { - bool enable; - - bool dac_enable; - unsigned volume_shift; - uint11 frequency; - bool counter; - uint8 pattern[32]; - - int16 output; - unsigned length; - unsigned period; - uint5 pattern_offset; - uint4 pattern_sample; - - void run(); - void clock_length(); - void write(unsigned r, uint8 data); - void write_pattern(unsigned p, uint8 data); - void power(); -}; diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/cartridge.cpp b/waterbox/libsnes/bsnes/gameboy/cartridge/cartridge.cpp deleted file mode 100644 index e613e8b84a..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/cartridge.cpp +++ /dev/null @@ -1,154 +0,0 @@ -#include - -#include - -#define CARTRIDGE_CPP -namespace GameBoy { - -#include "mbc0/mbc0.cpp" -#include "mbc1/mbc1.cpp" -#include "mbc2/mbc2.cpp" -#include "mbc3/mbc3.cpp" -#include "mbc5/mbc5.cpp" -#include "mmm01/mmm01.cpp" -#include "huc1/huc1.cpp" -#include "huc3/huc3.cpp" -Cartridge cartridge; - -void Cartridge::load(System::Revision revision, const string &markup, const uint8_t *data, unsigned size) { - if(size == 0) size = 32768; - romdata = allocate(romsize = size, 0xff); - if(data) memcpy(romdata, data, size); - - info.mapper = Mapper::Unknown; - info.ram = false; - info.battery = false; - info.rtc = false; - info.rumble = false; - - info.romsize = 0; - info.ramsize = 0; - - XML::Document document(markup); - - auto &mapperid = document["cartridge"]["mapper"].data; - if(mapperid == "none" ) info.mapper = Mapper::MBC0; - if(mapperid == "MBC1" ) info.mapper = Mapper::MBC1; - if(mapperid == "MBC2" ) info.mapper = Mapper::MBC2; - if(mapperid == "MBC3" ) info.mapper = Mapper::MBC3; - if(mapperid == "MBC5" ) info.mapper = Mapper::MBC5; - if(mapperid == "MMM01") info.mapper = Mapper::MMM01; - if(mapperid == "HuC1" ) info.mapper = Mapper::HuC1; - if(mapperid == "HuC3" ) info.mapper = Mapper::HuC3; - - info.rtc = document["cartridge"]["rtc"].data == "true"; - info.rumble = document["cartridge"]["rumble"].data == "true"; - - info.romsize = numeral(document["cartridge"]["rom"]["size"].data); - info.ramsize = numeral(document["cartridge"]["ram"]["size"].data); - info.battery = document["cartridge"]["ram"]["battery"].data == "true"; - - switch(info.mapper) { default: - case Mapper::MBC0: mapper = &mbc0; break; - case Mapper::MBC1: mapper = &mbc1; break; - case Mapper::MBC2: mapper = &mbc2; break; - case Mapper::MBC3: mapper = &mbc3; break; - case Mapper::MBC5: mapper = &mbc5; break; - case Mapper::MMM01: mapper = &mmm01; break; - case Mapper::HuC1: mapper = &huc1; break; - case Mapper::HuC3: mapper = &huc3; break; - } - - ramdata = (uint8_t*)interface->allocSharedMemory("SGB_CARTRAM",ramsize = info.ramsize, 0xff); - system.load(revision); - - loaded = true; - sha256 = nall::sha256(romdata, romsize); -} - -void Cartridge::unload() { - if(loaded == false) return; - - if(romdata) { delete[] romdata; romdata = 0; } - if(ramdata) { interface->freeSharedMemory(ramdata); } - loaded = false; -} - -uint8 Cartridge::rom_read(unsigned addr) { - if(addr >= romsize) addr %= romsize; - cdlInfo.set(eCDLog_AddrType_SGB_CARTROM, addr); - return romdata[addr]; -} - -void Cartridge::rom_write(unsigned addr, uint8 data) { - if(addr >= romsize) addr %= romsize; - romdata[addr] = data; -} - -uint8 Cartridge::ram_read(unsigned addr) { - if(ramsize == 0) return 0x00; - if(addr >= ramsize) addr %= ramsize; - cdlInfo.set(eCDLog_AddrType_SGB_CARTRAM, addr); - return ramdata[addr]; -} - -void Cartridge::ram_write(unsigned addr, uint8 data) { - if(ramsize == 0) return; - if(addr >= ramsize) addr %= ramsize; - ramdata[addr] = data; -} - -uint8 Cartridge::mmio_read(uint16 addr) { - if(addr == 0xff50) return 0x00; - - if(bootrom_enable) { - const uint8 *data = nullptr; - switch(system.revision()) { default: - case System::Revision::GameBoy: data = System::BootROM::dmg; break; - case System::Revision::SuperGameBoy: data = System::BootROM::sgb; break; - case System::Revision::GameBoyColor: data = System::BootROM::cgb; break; - } - if(addr >= 0x0000 && addr <= 0x00ff) return data[addr]; - if(addr >= 0x0200 && addr <= 0x08ff && system.cgb()) return data[addr - 256]; - } - - return mapper->mmio_read(addr); -} - -void Cartridge::mmio_write(uint16 addr, uint8 data) { - if(bootrom_enable && addr == 0xff50) { - bootrom_enable = false; - return; - } - - mapper->mmio_write(addr, data); -} - -void Cartridge::power() { - bootrom_enable = true; - - mbc0.power(); - mbc1.power(); - mbc2.power(); - mbc3.power(); - mbc5.power(); - mmm01.power(); - huc1.power(); - huc3.power(); - - for(unsigned n = 0x0000; n <= 0x7fff; n++) bus.mmio[n] = this; - for(unsigned n = 0xa000; n <= 0xbfff; n++) bus.mmio[n] = this; - bus.mmio[0xff50] = this; -} - -Cartridge::Cartridge() { - loaded = false; - romdata = 0; - ramdata = 0; -} - -Cartridge::~Cartridge() { - unload(); -} - -} diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/cartridge.hpp b/waterbox/libsnes/bsnes/gameboy/cartridge/cartridge.hpp deleted file mode 100644 index 568ae8307c..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/cartridge.hpp +++ /dev/null @@ -1,65 +0,0 @@ -struct Cartridge : MMIO, property { - #include "mbc0/mbc0.hpp" - #include "mbc1/mbc1.hpp" - #include "mbc2/mbc2.hpp" - #include "mbc3/mbc3.hpp" - #include "mbc5/mbc5.hpp" - #include "mmm01/mmm01.hpp" - #include "huc1/huc1.hpp" - #include "huc3/huc3.hpp" - - enum Mapper : unsigned { - MBC0, - MBC1, - MBC2, - MBC3, - MBC5, - MMM01, - HuC1, - HuC3, - Unknown, - }; - - struct Information { - string xml; - - Mapper mapper; - bool ram; - bool battery; - bool rtc; - bool rumble; - - unsigned romsize; - unsigned ramsize; - } info; - - readonly loaded; - readonly sha256; - - uint8_t *romdata; - unsigned romsize; - - uint8_t *ramdata; - unsigned ramsize; - - MMIO *mapper; - bool bootrom_enable; - - void load(System::Revision revision, const string &markup, const uint8_t *data, unsigned size); - void unload(); - - uint8 rom_read(unsigned addr); - void rom_write(unsigned addr, uint8 data); - uint8 ram_read(unsigned addr); - void ram_write(unsigned addr, uint8 data); - - uint8 mmio_read(uint16 addr); - void mmio_write(uint16 addr, uint8 data); - - void power(); - - Cartridge(); - ~Cartridge(); -}; - -extern Cartridge cartridge; diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/huc1/huc1.cpp b/waterbox/libsnes/bsnes/gameboy/cartridge/huc1/huc1.cpp deleted file mode 100644 index b8fb11013e..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/huc1/huc1.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#ifdef CARTRIDGE_CPP - -uint8 Cartridge::HuC1::mmio_read(uint16 addr) { - if((addr & 0xc000) == 0x0000) { //$0000-3fff - return cartridge.rom_read(addr); - } - - if((addr & 0xc000) == 0x4000) { //$4000-7fff - return cartridge.rom_read((rom_select << 14) | (addr & 0x3fff)); - } - - if((addr & 0xe000) == 0xa000) { //$a000-bfff - return cartridge.ram_read((ram_select << 13) | (addr & 0x1fff)); - } - - return 0x00; -} - -void Cartridge::HuC1::mmio_write(uint16 addr, uint8 data) { - if((addr & 0xe000) == 0x0000) { //$0000-1fff - ram_writable = (data & 0x0f) == 0x0a; - return; - } - - if((addr & 0xe000) == 0x2000) { //$2000-3fff - rom_select = data; - if(rom_select == 0) rom_select = 1; - return; - } - - if((addr & 0xe000) == 0x4000) { //$4000-5fff - ram_select = data; - return; - } - - if((addr & 0xe000) == 0x6000) { //$6000-7fff - model = data & 0x01; - return; - } - - if((addr & 0xe000) == 0xa000) { //$a000-bfff - if(ram_writable == false) return; - return cartridge.ram_write((ram_select << 13) | (addr & 0x1fff), data); - } -} - -void Cartridge::HuC1::power() { - ram_writable = false; - rom_select = 0x01; - ram_select = 0x00; - model = 0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/huc1/huc1.hpp b/waterbox/libsnes/bsnes/gameboy/cartridge/huc1/huc1.hpp deleted file mode 100644 index f0f60d8f30..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/huc1/huc1.hpp +++ /dev/null @@ -1,10 +0,0 @@ -struct HuC1 : MMIO { - bool ram_writable; //$0000-1fff - uint8 rom_select; //$2000-3fff - uint8 ram_select; //$4000-5fff - bool model; //$6000-7fff - - uint8 mmio_read(uint16 addr); - void mmio_write(uint16 addr, uint8 data); - void power(); -} huc1; diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/huc3/huc3.cpp b/waterbox/libsnes/bsnes/gameboy/cartridge/huc3/huc3.cpp deleted file mode 100644 index c2bdcda4c8..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/huc3/huc3.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#ifdef CARTRIDGE_CPP - -uint8 Cartridge::HuC3::mmio_read(uint16 addr) { - if((addr & 0xc000) == 0x0000) { //$0000-3fff - return cartridge.rom_read(addr); - } - - if((addr & 0xc000) == 0x4000) { //$4000-7fff - return cartridge.rom_read((rom_select << 14) | (addr & 0x3fff)); - } - - if((addr & 0xe000) == 0xa000) { //$a000-bfff - if(ram_enable) return cartridge.ram_read((ram_select << 13) | (addr & 0x1fff)); - return 0x00; - } - - return 0x00; -} - -void Cartridge::HuC3::mmio_write(uint16 addr, uint8 data) { - if((addr & 0xe000) == 0x0000) { //$0000-1fff - ram_enable = (data & 0x0f) == 0x0a; - return; - } - - if((addr & 0xe000) == 0x2000) { //$2000-3fff - rom_select = data; - return; - } - - if((addr & 0xe000) == 0x4000) { //$4000-5fff - ram_select = data; - return; - } - - if((addr & 0xe000) == 0x6000) { //$6000-7fff - //unknown purpose - return; - } - - if((addr & 0xe000) == 0xa000) { //$a000-bfff - if(ram_enable) cartridge.ram_write((ram_select << 13) | (addr & 0x1fff), data); - return; - } -} - -void Cartridge::HuC3::power() { - ram_enable = false; - rom_select = 0x01; - ram_select = 0x00; -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/huc3/huc3.hpp b/waterbox/libsnes/bsnes/gameboy/cartridge/huc3/huc3.hpp deleted file mode 100644 index 61d4aa61f9..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/huc3/huc3.hpp +++ /dev/null @@ -1,9 +0,0 @@ -struct HuC3 : MMIO { - bool ram_enable; //$0000-1fff - uint8 rom_select; //$2000-3fff - uint8 ram_select; //$4000-5fff - - uint8 mmio_read(uint16 addr); - void mmio_write(uint16 addr, uint8 data); - void power(); -} huc3; diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc0/mbc0.cpp b/waterbox/libsnes/bsnes/gameboy/cartridge/mbc0/mbc0.cpp deleted file mode 100644 index 2312f572f6..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc0/mbc0.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifdef CARTRIDGE_CPP - -uint8 Cartridge::MBC0::mmio_read(uint16 addr) { - if((addr & 0x8000) == 0x0000) { //$0000-7fff - return cartridge.rom_read(addr); - } - - if((addr & 0xe000) == 0xa000) { //$a000-bfff - return cartridge.ram_read(addr & 0x1fff); - } - - return 0x00; -} - -void Cartridge::MBC0::mmio_write(uint16 addr, uint8 data) { - if((addr & 0xe000) == 0xa000) { //$a000-bfff - cartridge.ram_write(addr & 0x1fff, data); - return; - } -} - -void Cartridge::MBC0::power() { -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc0/mbc0.hpp b/waterbox/libsnes/bsnes/gameboy/cartridge/mbc0/mbc0.hpp deleted file mode 100644 index da7390eae8..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc0/mbc0.hpp +++ /dev/null @@ -1,5 +0,0 @@ -struct MBC0 : MMIO { - uint8 mmio_read(uint16 addr); - void mmio_write(uint16 addr, uint8 data); - void power(); -} mbc0; diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc1/mbc1.cpp b/waterbox/libsnes/bsnes/gameboy/cartridge/mbc1/mbc1.cpp deleted file mode 100644 index 7e15c13537..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc1/mbc1.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#ifdef CARTRIDGE_CPP - -uint8 Cartridge::MBC1::mmio_read(uint16 addr) { - if((addr & 0xc000) == 0x0000) { //$0000-3fff - return cartridge.rom_read(addr); - } - - if((addr & 0xc000) == 0x4000) { //$4000-7fff - if(mode_select == 0) { - return cartridge.rom_read((ram_select << 19) | (rom_select << 14) | (addr & 0x3fff)); - } else { - return cartridge.rom_read((rom_select << 14) | (addr & 0x3fff)); - } - } - - if((addr & 0xe000) == 0xa000) { //$a000-bfff - if(ram_enable) { - if(mode_select == 0) { - return cartridge.ram_read(addr & 0x1fff); - } else { - return cartridge.ram_read((ram_select << 13) | (addr & 0x1fff)); - } - } - return 0x00; - } - - return 0x00; -} - -void Cartridge::MBC1::mmio_write(uint16 addr, uint8 data) { - if((addr & 0xe000) == 0x0000) { //$0000-1fff - ram_enable = (data & 0x0f) == 0x0a; - return; - } - - if((addr & 0xe000) == 0x2000) { //$2000-3fff - rom_select = (data & 0x1f) + ((data & 0x1f) == 0); - return; - } - - if((addr & 0xe000) == 0x4000) { //$4000-5fff - ram_select = data & 0x03; - return; - } - - if((addr & 0xe000) == 0x6000) { //$6000-7fff - mode_select = data & 0x01; - return; - } - - if((addr & 0xe000) == 0xa000) { //$a000-bfff - if(ram_enable) { - if(mode_select == 0) { - cartridge.ram_write(addr & 0x1fff, data); - } else { - cartridge.ram_write((ram_select << 13) | (addr & 0x1fff), data); - } - } - return; - } -} - -void Cartridge::MBC1::power() { - ram_enable = false; - rom_select = 0x01; - ram_select = 0x00; - mode_select = 0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc1/mbc1.hpp b/waterbox/libsnes/bsnes/gameboy/cartridge/mbc1/mbc1.hpp deleted file mode 100644 index 19f8b75be6..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc1/mbc1.hpp +++ /dev/null @@ -1,10 +0,0 @@ -struct MBC1 : MMIO { - bool ram_enable; //$0000-1fff - uint8 rom_select; //$2000-3fff - uint8 ram_select; //$4000-5fff - bool mode_select; //$6000-7fff - - uint8 mmio_read(uint16 addr); - void mmio_write(uint16 addr, uint8 data); - void power(); -} mbc1; diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc2/mbc2.cpp b/waterbox/libsnes/bsnes/gameboy/cartridge/mbc2/mbc2.cpp deleted file mode 100644 index 0e0825f802..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc2/mbc2.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifdef CARTRIDGE_CPP - -uint8 Cartridge::MBC2::mmio_read(uint16 addr) { - if((addr & 0xc000) == 0x0000) { //$0000-3fff - return cartridge.rom_read(addr); - } - - if((addr & 0xc000) == 0x4000) { //$4000-7fff - return cartridge.rom_read((rom_select << 14) | (addr & 0x3fff)); - } - - if((addr & 0xee00) == 0xa000) { //$a000-a1ff - if(ram_enable) return cartridge.ram_read(addr & 0x1ff); - return 0x00; - } - - return 0x00; -} - -void Cartridge::MBC2::mmio_write(uint16 addr, uint8 data) { - if((addr & 0xe000) == 0x0000) { //$0000-1fff - if(!(addr & 0x0100)) ram_enable = (data & 0x0f) == 0x0a; - return; - } - - if((addr & 0xe000) == 0x2000) { //$2000-3fff - if( (addr & 0x0100)) rom_select = (data & 0x0f) + ((data & 0x0f) == 0); - return; - } - - if((addr & 0xee00) == 0xa000) { //$a000-a1ff - if(ram_enable) cartridge.ram_write(addr & 0x1ff, data & 0x0f); - return; - } -} - -void Cartridge::MBC2::power() { - ram_enable = false; - rom_select = 0x01; -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc2/mbc2.hpp b/waterbox/libsnes/bsnes/gameboy/cartridge/mbc2/mbc2.hpp deleted file mode 100644 index c22a652ab2..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc2/mbc2.hpp +++ /dev/null @@ -1,8 +0,0 @@ -struct MBC2 : MMIO { - bool ram_enable; //$0000-1fff - uint8 rom_select; //$2000-3fff - - uint8 mmio_read(uint16 addr); - void mmio_write(uint16 addr, uint8 data); - void power(); -} mbc2; diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc3/mbc3.cpp b/waterbox/libsnes/bsnes/gameboy/cartridge/mbc3/mbc3.cpp deleted file mode 100644 index 595ac1d9b5..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc3/mbc3.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#ifdef CARTRIDGE_CPP - -void Cartridge::MBC3::second() { - if(rtc_halt == false) { - if(++rtc_second >= 60) { - rtc_second = 0; - if(++rtc_minute >= 60) { - rtc_minute = 0; - if(++rtc_hour >= 24) { - rtc_hour = 0; - if(++rtc_day >= 512) { - rtc_day = 0; - rtc_day_carry = true; - } - } - } - } - } -} - -uint8 Cartridge::MBC3::mmio_read(uint16 addr) { - if((addr & 0xc000) == 0x0000) { //$0000-3fff - return cartridge.rom_read(addr); - } - - if((addr & 0xc000) == 0x4000) { //$4000-7fff - return cartridge.rom_read((rom_select << 14) | (addr & 0x3fff)); - } - - if((addr & 0xe000) == 0xa000) { //$a000-bfff - if(ram_enable) { - if(ram_select >= 0x00 && ram_select <= 0x03) { - return cartridge.ram_read((ram_select << 13) | (addr & 0x1fff)); - } - if(ram_select == 0x08) return rtc_latch_second; - if(ram_select == 0x09) return rtc_latch_minute; - if(ram_select == 0x0a) return rtc_latch_hour; - if(ram_select == 0x0b) return rtc_latch_day; - if(ram_select == 0x0c) return (rtc_latch_day_carry << 7) | (rtc_latch_day >> 8); - } - return 0x00; - } - - return 0x00; -} - -void Cartridge::MBC3::mmio_write(uint16 addr, uint8 data) { - if((addr & 0xe000) == 0x0000) { //$0000-1fff - ram_enable = (data & 0x0f) == 0x0a; - return; - } - - if((addr & 0xe000) == 0x2000) { //$2000-3fff - rom_select = (data & 0x7f) + ((data & 0x7f) == 0); - return; - } - - if((addr & 0xe000) == 0x4000) { //$4000-5fff - ram_select = data; - return; - } - - if((addr & 0xe000) == 0x6000) { //$6000-7fff - if(rtc_latch == 0 && data == 1) { - rtc_latch_second = rtc_second; - rtc_latch_minute = rtc_minute; - rtc_latch_hour = rtc_hour; - rtc_latch_day = rtc_day; - rtc_latch_day_carry = rtc_day_carry; - } - rtc_latch = data; - return; - } - - if((addr & 0xe000) == 0xa000) { //$a000-bfff - if(ram_enable) { - if(ram_select >= 0x00 && ram_select <= 0x03) { - cartridge.ram_write((ram_select << 13) | (addr & 0x1fff), data); - } else if(ram_select == 0x08) { - if(data >= 60) data = 0; - rtc_second = data; - } else if(ram_select == 0x09) { - if(data >= 60) data = 0; - rtc_minute = data; - } else if(ram_select == 0x0a) { - if(data >= 24) data = 0; - rtc_hour = data; - } else if(ram_select == 0x0b) { - rtc_day = (rtc_day & 0x0100) | data; - } else if(ram_select == 0x0c) { - rtc_day = ((data & 1) << 8) | (rtc_day & 0xff); - rtc_halt = data & 0x40; - rtc_day_carry = data & 0x80; - } - } - return; - } -} - -void Cartridge::MBC3::power() { - ram_enable = false; - rom_select = 0x01; - ram_select = 0x00; - rtc_latch = 0; - - rtc_halt = true; - rtc_second = 0; - rtc_minute = 0; - rtc_hour = 0; - rtc_day = 0; - rtc_day_carry = false; - - rtc_latch_second = 0; - rtc_latch_minute = 0; - rtc_latch_hour = 0; - rtc_latch_day = 0; - rtc_latch_day_carry = false; -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc3/mbc3.hpp b/waterbox/libsnes/bsnes/gameboy/cartridge/mbc3/mbc3.hpp deleted file mode 100644 index fbd7775d87..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc3/mbc3.hpp +++ /dev/null @@ -1,24 +0,0 @@ -struct MBC3 : MMIO { - bool ram_enable; //$0000-1fff - uint8 rom_select; //$2000-3fff - uint8 ram_select; //$4000-5fff - bool rtc_latch; //$6000-7fff - - bool rtc_halt; - unsigned rtc_second; - unsigned rtc_minute; - unsigned rtc_hour; - unsigned rtc_day; - bool rtc_day_carry; - - unsigned rtc_latch_second; - unsigned rtc_latch_minute; - unsigned rtc_latch_hour; - unsigned rtc_latch_day; - unsigned rtc_latch_day_carry; - - void second(); - uint8 mmio_read(uint16 addr); - void mmio_write(uint16 addr, uint8 data); - void power(); -} mbc3; diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc5/mbc5.cpp b/waterbox/libsnes/bsnes/gameboy/cartridge/mbc5/mbc5.cpp deleted file mode 100644 index 52f3223b18..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc5/mbc5.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#ifdef CARTRIDGE_CPP - -uint8 Cartridge::MBC5::mmio_read(uint16 addr) { - if((addr & 0xc000) == 0x0000) { //$0000-3fff - return cartridge.rom_read(addr); - } - - if((addr & 0xc000) == 0x4000) { //$4000-7fff - return cartridge.rom_read((rom_select << 14) | (addr & 0x3fff)); - } - - if((addr & 0xe000) == 0xa000) { //$a000-bfff - if(ram_enable) return cartridge.ram_read((ram_select << 13) | (addr & 0x1fff)); - return 0x00; - } - - return 0x00; -} - -void Cartridge::MBC5::mmio_write(uint16 addr, uint8 data) { - if((addr & 0xe000) == 0x0000) { //$0000-1fff - ram_enable = (data & 0x0f) == 0x0a; - return; - } - - if((addr & 0xf000) == 0x2000) { //$2000-2fff - rom_select = (rom_select & 0x0100) | data; - return; - } - - if((addr & 0xf000) == 0x3000) { //$3000-3fff - rom_select = ((data & 1) << 8) | (rom_select & 0x00ff); - return; - } - - if((addr & 0xe000) == 0x4000) { //$4000-5fff - ram_select = data & 0x0f; - return; - } - - if((addr & 0xe000) == 0xa000) { //$a000-bfff - if(ram_enable) cartridge.ram_write((ram_select << 13) | (addr & 0x1fff), data); - return; - } -} - -void Cartridge::MBC5::power() { - ram_enable = false; - rom_select = 0x001; - ram_select = 0x00; -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc5/mbc5.hpp b/waterbox/libsnes/bsnes/gameboy/cartridge/mbc5/mbc5.hpp deleted file mode 100644 index 0ec3abb0e3..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/mbc5/mbc5.hpp +++ /dev/null @@ -1,9 +0,0 @@ -struct MBC5 : MMIO { - bool ram_enable; //$0000-1fff - uint16 rom_select; //$2000-2fff + $3000-3fff - uint8 ram_select; //$4000-5fff - - uint8 mmio_read(uint16 addr); - void mmio_write(uint16 addr, uint8 data); - void power(); -} mbc5; diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/mmm01/mmm01.cpp b/waterbox/libsnes/bsnes/gameboy/cartridge/mmm01/mmm01.cpp deleted file mode 100644 index b690b8cf26..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/mmm01/mmm01.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#ifdef CARTRIDGE_CPP - -uint8 Cartridge::MMM01::mmio_read(uint16 addr) { - if((addr & 0x8000) == 0x0000) { //$0000-7fff - if(rom_mode == 0) return cartridge.rom_read(addr); - } - - if((addr & 0xc000) == 0x0000) { //$0000-3fff - return cartridge.rom_read(0x8000 + (rom_base << 14) + (addr & 0x3fff)); - } - - if((addr & 0xc000) == 0x4000) { //$4000-7fff - return cartridge.rom_read(0x8000 + (rom_base << 14) + (rom_select << 14) + (addr & 0x3fff)); - } - - if((addr & 0xe000) == 0xa000) { //$a000-bfff - if(ram_enable) return cartridge.ram_read((ram_select << 13) + (addr & 0x1fff)); - return 0x00; - } - - return 0x00; -} - -void Cartridge::MMM01::mmio_write(uint16 addr, uint8 data) { - if((addr & 0xe000) == 0x0000) { //$0000-1fff - if(rom_mode == 0) { - rom_mode = 1; - } else { - ram_enable = (data & 0x0f) == 0x0a; - } - } - - if((addr & 0xe000) == 0x2000) { //$2000-3fff - if(rom_mode == 0) { - rom_base = data & 0x3f; - } else { - rom_select = data; - } - } - - if((addr & 0xe000) == 0x4000) { //$4000-5fff - if(rom_mode == 1) { - ram_select = data; - } - } - - if((addr & 0xe000) == 0x6000) { //$6000-7fff - //unknown purpose - } - - if((addr & 0xe000) == 0xa000) { //$a000-bfff - if(ram_enable) cartridge.ram_write((ram_select << 13) + (addr & 0x1fff), data); - } -} - -void Cartridge::MMM01::power() { - rom_mode = 0; - rom_base = 0; - - ram_enable = false; - rom_select = 0x01; - ram_select = 0x00; -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/cartridge/mmm01/mmm01.hpp b/waterbox/libsnes/bsnes/gameboy/cartridge/mmm01/mmm01.hpp deleted file mode 100644 index 3474b06229..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cartridge/mmm01/mmm01.hpp +++ /dev/null @@ -1,12 +0,0 @@ -struct MMM01 : MMIO { - bool rom_mode; - uint8 rom_base; - - bool ram_enable; - uint8 rom_select; - uint8 ram_select; - - uint8 mmio_read(uint16 addr); - void mmio_write(uint16 addr, uint8 data); - void power(); -} mmm01; diff --git a/waterbox/libsnes/bsnes/gameboy/cpu/core/core.cpp b/waterbox/libsnes/bsnes/gameboy/cpu/core/core.cpp deleted file mode 100644 index 0926fa1ce7..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cpu/core/core.cpp +++ /dev/null @@ -1,689 +0,0 @@ -#ifdef CPU_CPP - -#include "table.cpp" -#include "disassembler.cpp" - -uint8 CPU::op_fetch() { - cdlInfo.currFlags = eCDLog_Flags_ExecOperand; - uint8 opcode = op_read(r[PC]++); - cdlInfo.currFlags = eCDLog_Flags_CPUData; - return opcode; -} - -void CPU::op_xx() { -} - -void CPU::op_cb() { - uint8 opcode = op_fetch(); - (this->*opcode_table_cb[opcode])(); -} - -//8-bit load commands - -template void CPU::op_ld_r_r() { - r[x] = r[y]; -} - -template void CPU::op_ld_r_n() { - r[x] = op_fetch(); -} - -template void CPU::op_ld_r_hl() { - r[x] = op_read(r[HL]); -} - -template void CPU::op_ld_hl_r() { - op_write(r[HL], r[x]); -} - -void CPU::op_ld_hl_n() { - op_write(r[HL], op_fetch()); -} - -template void CPU::op_ld_a_rr() { - r[A] = op_read(r[x]); -} - -void CPU::op_ld_a_nn() { - uint8 lo = op_fetch(); - uint8 hi = op_fetch(); - r[A] = op_read((hi << 8) | (lo << 0)); -} - -template void CPU::op_ld_rr_a() { - op_write(r[x], r[A]); -} - -void CPU::op_ld_nn_a() { - uint8 lo = op_fetch(); - uint8 hi = op_fetch(); - op_write((hi << 8) | (lo << 0), r[A]); -} - -void CPU::op_ld_a_ffn() { - r[A] = op_read(0xff00 + op_fetch()); -} - -void CPU::op_ld_ffn_a() { - op_write(0xff00 + op_fetch(), r[A]); -} - -void CPU::op_ld_a_ffc() { - r[A] = op_read(0xff00 + r[C]); -} - -void CPU::op_ld_ffc_a() { - op_write(0xff00 + r[C], r[A]); -} - -void CPU::op_ldi_hl_a() { - op_write(r[HL], r[A]); - r[HL]++; -} - -void CPU::op_ldi_a_hl() { - r[A] = op_read(r[HL]); - r[HL]++; -} - -void CPU::op_ldd_hl_a() { - op_write(r[HL], r[A]); - r[HL]--; -} - -void CPU::op_ldd_a_hl() { - r[A] = op_read(r[HL]); - r[HL]--; -} - -//16-bit load commands - -template void CPU::op_ld_rr_nn() { - r[x] = op_fetch() << 0; - r[x] |= op_fetch() << 8; -} - -void CPU::op_ld_nn_sp() { - uint16 addr = op_fetch() << 0; - addr |= op_fetch() << 8; - op_write(addr + 0, r[SP] >> 0); - op_write(addr + 1, r[SP] >> 8); -} - -void CPU::op_ld_sp_hl() { - r[SP] = r[HL]; - op_io(); -} - -template void CPU::op_push_rr() { - op_write(--r[SP], r[x] >> 8); - op_write(--r[SP], r[x] >> 0); - op_io(); -} - -template void CPU::op_pop_rr() { - r[x] = op_read(r[SP]++) << 0; - r[x] |= op_read(r[SP]++) << 8; -} - -//8-bit arithmetic commands - -void CPU::opi_add_a(uint8 x) { - uint16 rh = r[A] + x; - uint16 rl = (r[A] & 0x0f) + (x & 0x0f); - r[A] = rh; - r.f.z = (uint8)rh == 0; - r.f.n = 0; - r.f.h = rl > 0x0f; - r.f.c = rh > 0xff; -} - -template void CPU::op_add_a_r() { opi_add_a(r[x]); } -void CPU::op_add_a_n() { opi_add_a(op_fetch()); } -void CPU::op_add_a_hl() { opi_add_a(op_read(r[HL])); } - -void CPU::opi_adc_a(uint8 x) { - uint16 rh = r[A] + x + r.f.c; - uint16 rl = (r[A] & 0x0f) + (x & 0x0f) + r.f.c; - r[A] = rh; - r.f.z = (uint8)rh == 0; - r.f.n = 0; - r.f.h = rl > 0x0f; - r.f.c = rh > 0xff; -} - -template void CPU::op_adc_a_r() { opi_adc_a(r[x]); } -void CPU::op_adc_a_n() { opi_adc_a(op_fetch()); } -void CPU::op_adc_a_hl() { opi_adc_a(op_read(r[HL])); } - -void CPU::opi_sub_a(uint8 x) { - uint16 rh = r[A] - x; - uint16 rl = (r[A] & 0x0f) - (x & 0x0f); - r[A] = rh; - r.f.z = (uint8)rh == 0; - r.f.n = 1; - r.f.h = rl > 0x0f; - r.f.c = rh > 0xff; -} - -template void CPU::op_sub_a_r() { opi_sub_a(r[x]); } -void CPU::op_sub_a_n() { opi_sub_a(op_fetch()); } -void CPU::op_sub_a_hl() { opi_sub_a(op_read(r[HL])); } - -void CPU::opi_sbc_a(uint8 x) { - uint16 rh = r[A] - x - r.f.c; - uint16 rl = (r[A] & 0x0f) - (x & 0x0f) - r.f.c; - r[A] = rh; - r.f.z = (uint8)rh == 0; - r.f.n = 1; - r.f.h = rl > 0x0f; - r.f.c = rh > 0xff; -} - -template void CPU::op_sbc_a_r() { opi_sbc_a(r[x]); } -void CPU::op_sbc_a_n() { opi_sbc_a(op_fetch()); } -void CPU::op_sbc_a_hl() { opi_sbc_a(op_read(r[HL])); } - -void CPU::opi_and_a(uint8 x) { - r[A] &= x; - r.f.z = r[A] == 0; - r.f.n = 0; - r.f.h = 1; - r.f.c = 0; -} - -template void CPU::op_and_a_r() { opi_and_a(r[x]); } -void CPU::op_and_a_n() { opi_and_a(op_fetch()); } -void CPU::op_and_a_hl() { opi_and_a(op_read(r[HL])); } - -void CPU::opi_xor_a(uint8 x) { - r[A] ^= x; - r.f.z = r[A] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = 0; -} - -template void CPU::op_xor_a_r() { opi_xor_a(r[x]); } -void CPU::op_xor_a_n() { opi_xor_a(op_fetch()); } -void CPU::op_xor_a_hl() { opi_xor_a(op_read(r[HL])); } - -void CPU::opi_or_a(uint8 x) { - r[A] |= x; - r.f.z = r[A] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = 0; -} - -template void CPU::op_or_a_r() { opi_or_a(r[x]); } -void CPU::op_or_a_n() { opi_or_a(op_fetch()); } -void CPU::op_or_a_hl() { opi_or_a(op_read(r[HL])); } - -void CPU::opi_cp_a(uint8 x) { - uint16 rh = r[A] - x; - uint16 rl = (r[A] & 0x0f) - (x & 0x0f); - r.f.z = (uint8)rh == 0; - r.f.n = 1; - r.f.h = rl > 0x0f; - r.f.c = rh > 0xff; -} - -template void CPU::op_cp_a_r() { opi_cp_a(r[x]); } -void CPU::op_cp_a_n() { opi_cp_a(op_fetch()); } -void CPU::op_cp_a_hl() { opi_cp_a(op_read(r[HL])); } - -template void CPU::op_inc_r() { - r[x]++; - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = (r[x] & 0x0f) == 0x00; -} - -void CPU::op_inc_hl() { - uint8 n = op_read(r[HL]); - op_write(r[HL], ++n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = (n & 0x0f) == 0x00; -} - -template void CPU::op_dec_r() { - r[x]--; - r.f.z = r[x] == 0; - r.f.n = 1; - r.f.h = (r[x] & 0x0f) == 0x0f; -} - -void CPU::op_dec_hl() { - uint8 n = op_read(r[HL]); - op_write(r[HL], --n); - r.f.z = n == 0; - r.f.n = 1; - r.f.h = (n & 0x0f) == 0x0f; -} - -void CPU::op_daa() { - uint16 a = r[A]; - if(r.f.n == 0) { - if(r.f.h || (a & 0x0f) > 0x09) a += 0x06; - if(r.f.c || (a ) > 0x9f) a += 0x60; - } else { - if(r.f.h) { - a -= 0x06; - if(r.f.c == 0) a &= 0xff; - } - if(r.f.c) a -= 0x60; - } - r[A] = a; - r.f.z = r[A] == 0; - r.f.h = 0; - r.f.c |= a & 0x100; -} - -void CPU::op_cpl() { - r[A] ^= 0xff; - r.f.n = 1; - r.f.h = 1; -} - -//16-bit arithmetic commands - -template void CPU::op_add_hl_rr() { - op_io(); - uint32 rb = (r[HL] + r[x]); - uint32 rn = (r[HL] & 0xfff) + (r[x] & 0xfff); - r[HL] = rb; - r.f.n = 0; - r.f.h = rn > 0x0fff; - r.f.c = rb > 0xffff; -} - -template void CPU::op_inc_rr() { - op_io(); - r[x]++; -} - -template void CPU::op_dec_rr() { - op_io(); - r[x]--; -} - -void CPU::op_add_sp_n() { - op_io(); - op_io(); - signed n = (int8)op_fetch(); - r.f.z = 0; - r.f.n = 0; - r.f.h = ((r[SP] & 0x0f) + (n & 0x0f)) > 0x0f; - r.f.c = ((r[SP] & 0xff) + (n & 0xff)) > 0xff; - r[SP] += n; -} - -void CPU::op_ld_hl_sp_n() { - op_io(); - signed n = (int8)op_fetch(); - r.f.z = 0; - r.f.n = 0; - r.f.h = ((r[SP] & 0x0f) + (n & 0x0f)) > 0x0f; - r.f.c = ((r[SP] & 0xff) + (n & 0xff)) > 0xff; - r[HL] = r[SP] + n; -} - -//rotate/shift commands - -void CPU::op_rlca() { - r[A] = (r[A] << 1) | (r[A] >> 7); - r.f.z = 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = r[A] & 0x01; -} - -void CPU::op_rla() { - bool c = r[A] & 0x80; - r[A] = (r[A] << 1) | (r.f.c << 0); - r.f.z = 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -void CPU::op_rrca() { - r[A] = (r[A] >> 1) | (r[A] << 7); - r.f.z = 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = r[A] & 0x80; -} - -void CPU::op_rra() { - bool c = r[A] & 0x01; - r[A] = (r[A] >> 1) | (r.f.c << 7); - r.f.z = 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -template void CPU::op_rlc_r() { - r[x] = (r[x] << 1) | (r[x] >> 7); - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = r[x] & 0x01; -} - -void CPU::op_rlc_hl() { - uint8 n = op_read(r[HL]); - n = (n << 1) | (n >> 7); - op_write(r[HL], n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = n & 0x01; -} - -template void CPU::op_rl_r() { - bool c = r[x] & 0x80; - r[x] = (r[x] << 1) | (r.f.c << 0); - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -void CPU::op_rl_hl() { - uint8 n = op_read(r[HL]); - bool c = n & 0x80; - n = (n << 1) | (r.f.c << 0); - op_write(r[HL], n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -template void CPU::op_rrc_r() { - r[x] = (r[x] >> 1) | (r[x] << 7); - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = r[x] & 0x80; -} - -void CPU::op_rrc_hl() { - uint8 n = op_read(r[HL]); - n = (n >> 1) | (n << 7); - op_write(r[HL], n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = n & 0x80; -} - -template void CPU::op_rr_r() { - bool c = r[x] & 0x01; - r[x] = (r[x] >> 1) | (r.f.c << 7); - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -void CPU::op_rr_hl() { - uint8 n = op_read(r[HL]); - bool c = n & 0x01; - n = (n >> 1) | (r.f.c << 7); - op_write(r[HL], n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -template void CPU::op_sla_r() { - bool c = r[x] & 0x80; - r[x] <<= 1; - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -void CPU::op_sla_hl() { - uint8 n = op_read(r[HL]); - bool c = n & 0x80; - n <<= 1; - op_write(r[HL], n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -template void CPU::op_swap_r() { - r[x] = (r[x] << 4) | (r[x] >> 4); - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = 0; -} - -void CPU::op_swap_hl() { - uint8 n = op_read(r[HL]); - n = (n << 4) | (n >> 4); - op_write(r[HL], n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = 0; -} - -template void CPU::op_sra_r() { - bool c = r[x] & 0x01; - r[x] = (int8)r[x] >> 1; - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -void CPU::op_sra_hl() { - uint8 n = op_read(r[HL]); - bool c = n & 0x01; - n = (int8)n >> 1; - op_write(r[HL], n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -template void CPU::op_srl_r() { - bool c = r[x] & 0x01; - r[x] >>= 1; - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -void CPU::op_srl_hl() { - uint8 n = op_read(r[HL]); - bool c = n & 0x01; - n >>= 1; - op_write(r[HL], n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -//single-bit commands - -template void CPU::op_bit_n_r() { - r.f.z = (r[x] & (1 << b)) == 0; - r.f.n = 0; - r.f.h = 1; -} - -template void CPU::op_bit_n_hl() { - uint8 n = op_read(r[HL]); - r.f.z = (n & (1 << b)) == 0; - r.f.n = 0; - r.f.h = 1; -} - -template void CPU::op_set_n_r() { - r[x] |= 1 << b; -} - -template void CPU::op_set_n_hl() { - uint8 n = op_read(r[HL]); - n |= 1 << b; - op_write(r[HL], n); -} - -template void CPU::op_res_n_r() { - r[x] &= ~(1 << b); -} - -template void CPU::op_res_n_hl() { - uint8 n = op_read(r[HL]); - n &= ~(1 << b); - op_write(r[HL], n); -} - -//control commands - -void CPU::op_ccf() { - r.f.n = 0; - r.f.h = 0; - r.f.c = !r.f.c; -} - -void CPU::op_scf() { - r.f.n = 0; - r.f.h = 0; - r.f.c = 1; -} - -void CPU::op_nop() { -} - -void CPU::op_halt() { - status.halt = true; - while(status.halt == true) op_io(); -} - -void CPU::op_stop() { - if(status.speed_switch) { - status.speed_switch = 0; - status.speed_double ^= 1; - frequency = 4 * 1024 * 1024; - if(status.speed_double) frequency *= 2; - return; - } - status.stop = true; - while(status.stop == true) op_io(); -} - -void CPU::op_di() { - status.ime = 0; -} - -void CPU::op_ei() { - status.ei = true; -//status.ime = 1; -} - -//jump commands - -void CPU::op_jp_nn() { - uint8 lo = op_fetch(); - uint8 hi = op_fetch(); - r[PC] = (hi << 8) | (lo << 0); - op_io(); -} - -void CPU::op_jp_hl() { - r[PC] = r[HL]; -} - -template void CPU::op_jp_f_nn() { - uint8 lo = op_fetch(); - uint8 hi = op_fetch(); - if(r.f[x] == y) { - r[PC] = (hi << 8) | (lo << 0); - op_io(); - } -} - -void CPU::op_jr_n() { - int8 n = op_fetch(); - r[PC] += n; - op_io(); -} - -template void CPU::op_jr_f_n() { - int8 n = op_fetch(); - if(r.f[x] == y) { - r[PC] += n; - op_io(); - } -} - -void CPU::op_call_nn() { - uint8 lo = op_fetch(); - uint8 hi = op_fetch(); - op_write(--r[SP], r[PC] >> 8); - op_write(--r[SP], r[PC] >> 0); - r[PC] = (hi << 8) | (lo << 0); - op_io(); -} - -template void CPU::op_call_f_nn() { - uint8 lo = op_fetch(); - uint8 hi = op_fetch(); - if(r.f[x] == y) { - op_write(--r[SP], r[PC] >> 8); - op_write(--r[SP], r[PC] >> 0); - r[PC] = (hi << 8) | (lo << 0); - op_io(); - } -} - -void CPU::op_ret() { - uint8 lo = op_read(r[SP]++); - uint8 hi = op_read(r[SP]++); - r[PC] = (hi << 8) | (lo << 0); - op_io(); -} - -template void CPU::op_ret_f() { - op_io(); - if(r.f[x] == y) { - uint8 lo = op_read(r[SP]++); - uint8 hi = op_read(r[SP]++); - r[PC] = (hi << 8) | (lo << 0); - op_io(); - } -} - -void CPU::op_reti() { - uint8 lo = op_read(r[SP]++); - uint8 hi = op_read(r[SP]++); - r[PC] = (hi << 8) | (lo << 0); - op_io(); - status.ime = 1; -} - -template void CPU::op_rst_n() { - op_write(--r[SP], r[PC] >> 8); - op_write(--r[SP], r[PC] >> 0); - r[PC] = n; - op_io(); -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/cpu/core/core.hpp b/waterbox/libsnes/bsnes/gameboy/cpu/core/core.hpp deleted file mode 100644 index f239f2ff04..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cpu/core/core.hpp +++ /dev/null @@ -1,146 +0,0 @@ -#include "registers.hpp" -void (CPU::*opcode_table[256])(); -void (CPU::*opcode_table_cb[256])(); -void initialize_opcode_table(); - -void op_xx(); -void op_cb(); -uint8 op_fetch(); - -//8-bit load commands -template void op_ld_r_r(); -template void op_ld_r_n(); -template void op_ld_r_hl(); -template void op_ld_hl_r(); -void op_ld_hl_n(); -template void op_ld_a_rr(); -void op_ld_a_nn(); -template void op_ld_rr_a(); -void op_ld_nn_a(); -void op_ld_a_ffn(); -void op_ld_ffn_a(); -void op_ld_a_ffc(); -void op_ld_ffc_a(); -void op_ldi_hl_a(); -void op_ldi_a_hl(); -void op_ldd_hl_a(); -void op_ldd_a_hl(); - -//16-bit load commands -template void op_ld_rr_nn(); -void op_ld_nn_sp(); -void op_ld_sp_hl(); -template void op_push_rr(); -template void op_pop_rr(); - -//8-bit arithmetic commands -void opi_add_a(uint8 x); -template void op_add_a_r(); -void op_add_a_n(); -void op_add_a_hl(); - -void opi_adc_a(uint8 x); -template void op_adc_a_r(); -void op_adc_a_n(); -void op_adc_a_hl(); - -void opi_sub_a(uint8 x); -template void op_sub_a_r(); -void op_sub_a_n(); -void op_sub_a_hl(); - -void opi_sbc_a(uint8 x); -template void op_sbc_a_r(); -void op_sbc_a_n(); -void op_sbc_a_hl(); - -void opi_and_a(uint8 x); -template void op_and_a_r(); -void op_and_a_n(); -void op_and_a_hl(); - -void opi_xor_a(uint8 x); -template void op_xor_a_r(); -void op_xor_a_n(); -void op_xor_a_hl(); - -void opi_or_a(uint8 x); -template void op_or_a_r(); -void op_or_a_n(); -void op_or_a_hl(); - -void opi_cp_a(uint8 x); -template void op_cp_a_r(); -void op_cp_a_n(); -void op_cp_a_hl(); - -template void op_inc_r(); -void op_inc_hl(); -template void op_dec_r(); -void op_dec_hl(); -void op_daa(); -void op_cpl(); - -//16-bit arithmetic commands -template void op_add_hl_rr(); -template void op_inc_rr(); -template void op_dec_rr(); -void op_add_sp_n(); -void op_ld_hl_sp_n(); - -//rotate/shift commands -void op_rlca(); -void op_rla(); -void op_rrca(); -void op_rra(); -template void op_rlc_r(); -void op_rlc_hl(); -template void op_rl_r(); -void op_rl_hl(); -template void op_rrc_r(); -void op_rrc_hl(); -template void op_rr_r(); -void op_rr_hl(); -template void op_sla_r(); -void op_sla_hl(); -template void op_swap_r(); -void op_swap_hl(); -template void op_sra_r(); -void op_sra_hl(); -template void op_srl_r(); -void op_srl_hl(); - -//single-bit commands -template void op_bit_n_r(); -template void op_bit_n_hl(); -template void op_set_n_r(); -template void op_set_n_hl(); -template void op_res_n_r(); -template void op_res_n_hl(); - -//control commands -void op_ccf(); -void op_scf(); -void op_nop(); -void op_halt(); -void op_stop(); -void op_di(); -void op_ei(); - -//jump commands -void op_jp_nn(); -void op_jp_hl(); -template void op_jp_f_nn(); -void op_jr_n(); -template void op_jr_f_n(); -void op_call_nn(); -template void op_call_f_nn(); -void op_ret(); -template void op_ret_f(); -void op_reti(); -template void op_rst_n(); - -//disassembler.cpp -string disassemble(uint16 pc); -string disassemble_opcode(uint16 pc); -string disassemble_opcode_cb(uint16 pc); diff --git a/waterbox/libsnes/bsnes/gameboy/cpu/core/disassembler.cpp b/waterbox/libsnes/bsnes/gameboy/cpu/core/disassembler.cpp deleted file mode 100644 index 77a1c53aae..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cpu/core/disassembler.cpp +++ /dev/null @@ -1,560 +0,0 @@ -#ifdef CPU_CPP - -string CPU::disassemble(uint16 pc) { - char output[80]; - memset(output, ' ', sizeof output); - output[79] = 0; - - string opcode = disassemble_opcode(pc); - string registers = { - " AF:", hex<4>(r[AF]), - " BC:", hex<4>(r[BC]), - " DE:", hex<4>(r[DE]), - " HL:", hex<4>(r[HL]), - " SP:", hex<4>(r[SP]) - }; - - memcpy(output + 0, hex<4>(pc), 4); - memcpy(output + 6, opcode, opcode.length()); - memcpy(output + 23, registers, registers.length()); - output[63] = 0; - return output; -} - -string CPU::disassemble_opcode(uint16 pc) { - uint8 opcode = bus.read(pc); - uint8 p0 = bus.read(pc + 1); - uint8 p1 = bus.read(pc + 2); - uint8 p2 = bus.read(pc + 3); - - switch(opcode) { - case 0x00: return { "nop" }; - case 0x01: return { "ld bc,$", hex<2>(p1), hex<2>(p0) }; - case 0x02: return { "ld (bc),a" }; - case 0x03: return { "inc bc" }; - case 0x04: return { "inc b" }; - case 0x05: return { "dec b" }; - case 0x06: return { "ld b,$", hex<2>(p0) }; - case 0x07: return { "rlc a" }; - case 0x08: return { "ld ($", hex<2>(p1), hex<2>(p0), "),sp" }; - case 0x09: return { "add hl,bc" }; - case 0x0a: return { "ld a,(bc)" }; - case 0x0b: return { "dec bc" }; - case 0x0c: return { "inc c" }; - case 0x0d: return { "dec c" }; - case 0x0e: return { "ld c,$", hex<2>(p0) }; - case 0x0f: return { "rrc a" }; - case 0x10: return { "stop" }; - case 0x11: return { "ld de,$", hex<2>(p1), hex<2>(p0) }; - case 0x12: return { "ld (de),a" }; - case 0x13: return { "inc de" }; - case 0x14: return { "inc d" }; - case 0x15: return { "dec d" }; - case 0x16: return { "ld d,$", hex<2>(p0) }; - case 0x17: return { "rl a" }; - case 0x18: return { "jr $", hex<4>(r[PC] + 2 + (int8)p0) }; - case 0x19: return { "add hl,de" }; - case 0x1a: return { "ld a,(de)" }; - case 0x1b: return { "dec de" }; - case 0x1c: return { "inc e" }; - case 0x1d: return { "dec e" }; - case 0x1e: return { "ld e,$", hex<2>(p0) }; - case 0x1f: return { "rr a" }; - case 0x20: return { "jr nz,$", hex<4>(r[PC] + 2 + (int8)p0) }; - case 0x21: return { "ld hl,$", hex<2>(p1), hex<2>(p0) }; - case 0x22: return { "ldi (hl),a" }; - case 0x23: return { "inc hl" }; - case 0x24: return { "inc h" }; - case 0x25: return { "dec h" }; - case 0x26: return { "ld h,$", hex<2>(p0) }; - case 0x27: return { "daa" }; - case 0x28: return { "jr z,$", hex<4>(r[PC] + 2 + (int8)p0) }; - case 0x29: return { "add hl,hl" }; - case 0x2a: return { "ldi a,(hl)" }; - case 0x2b: return { "dec hl" }; - case 0x2c: return { "inc l" }; - case 0x2d: return { "dec l" }; - case 0x2e: return { "ld l,$", hex<2>(p0) }; - case 0x2f: return { "cpl" }; - case 0x30: return { "jr nc,$", hex<4>(r[PC] + 2 + (int8)p0) }; - case 0x31: return { "ld sp,$", hex<2>(p1), hex<2>(p0) }; - case 0x32: return { "ldd (hl),a" }; - case 0x33: return { "inc sp" }; - case 0x34: return { "inc (hl)" }; - case 0x35: return { "dec (hl)" }; - case 0x36: return { "ld (hl),$", hex<2>(p0) }; - case 0x37: return { "scf" }; - case 0x38: return { "jr c,$", hex<4>(r[PC] + 2 + (int8)p0) }; - case 0x39: return { "add hl,sp" }; - case 0x3a: return { "ldd a,(hl)" }; - case 0x3b: return { "dec sp" }; - case 0x3c: return { "inc a" }; - case 0x3d: return { "dec a" }; - case 0x3e: return { "ld a,$", hex<2>(p0) }; - case 0x3f: return { "ccf" }; - case 0x40: return { "ld b,b" }; - case 0x41: return { "ld b,c" }; - case 0x42: return { "ld b,d" }; - case 0x43: return { "ld b,e" }; - case 0x44: return { "ld b,h" }; - case 0x45: return { "ld b,l" }; - case 0x46: return { "ld b,(hl)" }; - case 0x47: return { "ld b,a" }; - case 0x48: return { "ld c,b" }; - case 0x49: return { "ld c,c" }; - case 0x4a: return { "ld c,d" }; - case 0x4b: return { "ld c,e" }; - case 0x4c: return { "ld c,h" }; - case 0x4d: return { "ld c,l" }; - case 0x4e: return { "ld c,(hl)" }; - case 0x4f: return { "ld c,a" }; - case 0x50: return { "ld d,b" }; - case 0x51: return { "ld d,c" }; - case 0x52: return { "ld d,d" }; - case 0x53: return { "ld d,e" }; - case 0x54: return { "ld d,h" }; - case 0x55: return { "ld d,l" }; - case 0x56: return { "ld d,(hl)" }; - case 0x57: return { "ld d,a" }; - case 0x58: return { "ld e,b" }; - case 0x59: return { "ld e,c" }; - case 0x5a: return { "ld e,d" }; - case 0x5b: return { "ld e,e" }; - case 0x5c: return { "ld e,h" }; - case 0x5d: return { "ld e,l" }; - case 0x5e: return { "ld e,(hl)" }; - case 0x5f: return { "ld e,a" }; - case 0x60: return { "ld h,b" }; - case 0x61: return { "ld h,c" }; - case 0x62: return { "ld h,d" }; - case 0x63: return { "ld h,e" }; - case 0x64: return { "ld h,h" }; - case 0x65: return { "ld h,l" }; - case 0x66: return { "ld h,(hl)" }; - case 0x67: return { "ld h,a" }; - case 0x68: return { "ld l,b" }; - case 0x69: return { "ld l,c" }; - case 0x6a: return { "ld l,d" }; - case 0x6b: return { "ld l,e" }; - case 0x6c: return { "ld l,h" }; - case 0x6d: return { "ld l,l" }; - case 0x6e: return { "ld l,(hl)" }; - case 0x6f: return { "ld l,a" }; - case 0x70: return { "ld (hl),b" }; - case 0x71: return { "ld (hl),c" }; - case 0x72: return { "ld (hl),d" }; - case 0x73: return { "ld (hl),e" }; - case 0x74: return { "ld (hl),h" }; - case 0x75: return { "ld (hl),l" }; - case 0x76: return { "halt" }; - case 0x77: return { "ld (hl),a" }; - case 0x78: return { "ld a,b" }; - case 0x79: return { "ld a,c" }; - case 0x7a: return { "ld a,d" }; - case 0x7b: return { "ld a,e" }; - case 0x7c: return { "ld a,h" }; - case 0x7d: return { "ld a,l" }; - case 0x7e: return { "ld a,(hl)" }; - case 0x7f: return { "ld a,a" }; - case 0x80: return { "add a,b" }; - case 0x81: return { "add a,c" }; - case 0x82: return { "add a,d" }; - case 0x83: return { "add a,e" }; - case 0x84: return { "add a,h" }; - case 0x85: return { "add a,l" }; - case 0x86: return { "add a,(hl)" }; - case 0x87: return { "add a,a" }; - case 0x88: return { "adc a,b" }; - case 0x89: return { "adc a,c" }; - case 0x8a: return { "adc a,d" }; - case 0x8b: return { "adc a,e" }; - case 0x8c: return { "adc a,h" }; - case 0x8d: return { "adc a,l" }; - case 0x8e: return { "adc a,(hl)" }; - case 0x8f: return { "adc a,a" }; - case 0x90: return { "sub a,b" }; - case 0x91: return { "sub a,c" }; - case 0x92: return { "sub a,d" }; - case 0x93: return { "sub a,e" }; - case 0x94: return { "sub a,h" }; - case 0x95: return { "sub a,l" }; - case 0x96: return { "sub a,(hl)" }; - case 0x97: return { "sub a,a" }; - case 0x98: return { "sbc a,b" }; - case 0x99: return { "sbc a,c" }; - case 0x9a: return { "sbc a,d" }; - case 0x9b: return { "sbc a,e" }; - case 0x9c: return { "sbc a,h" }; - case 0x9d: return { "sbc a,l" }; - case 0x9e: return { "sbc a,(hl)" }; - case 0x9f: return { "sbc a,a" }; - case 0xa0: return { "and a,b" }; - case 0xa1: return { "and a,c" }; - case 0xa2: return { "and a,d" }; - case 0xa3: return { "and a,e" }; - case 0xa4: return { "and a,h" }; - case 0xa5: return { "and a,l" }; - case 0xa6: return { "and a,(hl)" }; - case 0xa7: return { "and a,a" }; - case 0xa8: return { "xor a,b" }; - case 0xa9: return { "xor a,c" }; - case 0xaa: return { "xor a,d" }; - case 0xab: return { "xor a,e" }; - case 0xac: return { "xor a,h" }; - case 0xad: return { "xor a,l" }; - case 0xae: return { "xor a,(hl)" }; - case 0xaf: return { "xor a,a" }; - case 0xb0: return { "or a,b" }; - case 0xb1: return { "or a,c" }; - case 0xb2: return { "or a,d" }; - case 0xb3: return { "or a,e" }; - case 0xb4: return { "or a,h" }; - case 0xb5: return { "or a,l" }; - case 0xb6: return { "or a,(hl)" }; - case 0xb7: return { "or a,a" }; - case 0xb8: return { "cp a,b" }; - case 0xb9: return { "cp a,c" }; - case 0xba: return { "cp a,d" }; - case 0xbb: return { "cp a,e" }; - case 0xbc: return { "cp a,h" }; - case 0xbd: return { "cp a,l" }; - case 0xbe: return { "cp a,(hl)" }; - case 0xbf: return { "cp a,a" }; - case 0xc0: return { "ret nz" }; - case 0xc1: return { "pop bc" }; - case 0xc2: return { "jp nz,$", hex<2>(p1), hex<2>(p0) }; - case 0xc3: return { "jp $", hex<2>(p1), hex<2>(p0) }; - case 0xc4: return { "call nz,$", hex<2>(p1), hex<2>(p0) }; - case 0xc5: return { "push bc" }; - case 0xc6: return { "add a,$", hex<2>(p0) }; - case 0xc7: return { "rst $0000" }; - case 0xc8: return { "ret z" }; - case 0xc9: return { "ret" }; - case 0xca: return { "jp z,$", hex<2>(p1), hex<2>(p0) }; - case 0xcb: return disassemble_opcode_cb(pc + 1); - case 0xcc: return { "call z,$", hex<2>(p1), hex<2>(p0) }; - case 0xcd: return { "call $", hex<2>(p1), hex<2>(p0) }; - case 0xce: return { "adc a,$", hex<2>(p0) }; - case 0xcf: return { "rst $0008" }; - case 0xd0: return { "ret nc" }; - case 0xd1: return { "pop de" }; - case 0xd2: return { "jp nc,$", hex<2>(p1), hex<2>(p0) }; - case 0xd3: return { "xx" }; - case 0xd4: return { "call nc,$", hex<2>(p1), hex<2>(p0) }; - case 0xd5: return { "push de" }; - case 0xd6: return { "sub a,$", hex<2>(p0) }; - case 0xd7: return { "rst $0010" }; - case 0xd8: return { "ret c" }; - case 0xd9: return { "reti" }; - case 0xda: return { "jp c,$", hex<2>(p1), hex<2>(p0) }; - case 0xdb: return { "xx" }; - case 0xdc: return { "call c,$", hex<2>(p1), hex<2>(p0) }; - case 0xdd: return { "xx" }; - case 0xde: return { "sbc a,$", hex<2>(p0) }; - case 0xdf: return { "rst $0018" }; - case 0xe0: return { "ld ($ff", hex<2>(p0), "),a" }; - case 0xe1: return { "pop hl" }; - case 0xe2: return { "ld ($ff00+c),a" }; - case 0xe3: return { "xx" }; - case 0xe4: return { "xx" }; - case 0xe5: return { "push hl" }; - case 0xe6: return { "and a,$", hex<2>(p0) }; - case 0xe7: return { "rst $0020" }; - case 0xe8: return { "add sp,$", hex<4>((int8)p0) }; - case 0xe9: return { "jp hl" }; - case 0xea: return { "ld ($", hex<2>(p1), hex<2>(p0), "),a" }; - case 0xeb: return { "xx" }; - case 0xec: return { "xx" }; - case 0xed: return { "xx" }; - case 0xee: return { "xor a,$", hex<2>(p0) }; - case 0xef: return { "rst $0028" }; - case 0xf0: return { "ld a,($ff", hex<2>(p0), ")" }; - case 0xf1: return { "pop af" }; - case 0xf2: return { "ld a,($ff00+c)" }; - case 0xf3: return { "di" }; - case 0xf4: return { "xx" }; - case 0xf5: return { "push af" }; - case 0xf6: return { "or a,$", hex<2>(p0) }; - case 0xf7: return { "rst $0030" }; - case 0xf8: return { "ld hl,sp+$", hex<4>((int8)p0) }; - case 0xf9: return { "ld sp,hl" }; - case 0xfa: return { "ld a,($", hex<2>(p1), hex<2>(p0), ")" }; - case 0xfb: return { "ei" }; - case 0xfc: return { "xx" }; - case 0xfd: return { "xx" }; - case 0xfe: return { "cp a,$", hex<2>(p0) }; - case 0xff: return { "rst $0038" }; - } - - return ""; -} - -string CPU::disassemble_opcode_cb(uint16 pc) { - uint8 opcode = bus.read(pc); - uint8 p0 = bus.read(pc + 1); - uint8 p1 = bus.read(pc + 2); - uint8 p2 = bus.read(pc + 3); - - switch(opcode) { - case 0x00: return { "rlc b" }; - case 0x01: return { "rlc c" }; - case 0x02: return { "rlc d" }; - case 0x03: return { "rlc e" }; - case 0x04: return { "rlc h" }; - case 0x05: return { "rlc l" }; - case 0x06: return { "rlc (hl)" }; - case 0x07: return { "rlc a" }; - case 0x08: return { "rrc b" }; - case 0x09: return { "rrc c" }; - case 0x0a: return { "rrc d" }; - case 0x0b: return { "rrc e" }; - case 0x0c: return { "rrc h" }; - case 0x0d: return { "rrc l" }; - case 0x0e: return { "rrc (hl)" }; - case 0x0f: return { "rrc a" }; - case 0x10: return { "rl b" }; - case 0x11: return { "rl c" }; - case 0x12: return { "rl d" }; - case 0x13: return { "rl e" }; - case 0x14: return { "rl h" }; - case 0x15: return { "rl l" }; - case 0x16: return { "rl (hl)" }; - case 0x17: return { "rl a" }; - case 0x18: return { "rr b" }; - case 0x19: return { "rr c" }; - case 0x1a: return { "rr d" }; - case 0x1b: return { "rr e" }; - case 0x1c: return { "rr h" }; - case 0x1d: return { "rr l" }; - case 0x1e: return { "rr (hl)" }; - case 0x1f: return { "rr a" }; - case 0x20: return { "sla b" }; - case 0x21: return { "sla c" }; - case 0x22: return { "sla d" }; - case 0x23: return { "sla e" }; - case 0x24: return { "sla h" }; - case 0x25: return { "sla l" }; - case 0x26: return { "sla (hl)" }; - case 0x27: return { "sla a" }; - case 0x28: return { "sra b" }; - case 0x29: return { "sra c" }; - case 0x2a: return { "sra d" }; - case 0x2b: return { "sra e" }; - case 0x2c: return { "sra h" }; - case 0x2d: return { "sra l" }; - case 0x2e: return { "sra (hl)" }; - case 0x2f: return { "sra a" }; - case 0x30: return { "swap b" }; - case 0x31: return { "swap c" }; - case 0x32: return { "swap d" }; - case 0x33: return { "swap e" }; - case 0x34: return { "swap h" }; - case 0x35: return { "swap l" }; - case 0x36: return { "swap (hl)" }; - case 0x37: return { "swap a" }; - case 0x38: return { "srl b" }; - case 0x39: return { "srl c" }; - case 0x3a: return { "srl d" }; - case 0x3b: return { "srl e" }; - case 0x3c: return { "srl h" }; - case 0x3d: return { "srl l" }; - case 0x3e: return { "srl (hl)" }; - case 0x3f: return { "srl a" }; - case 0x40: return { "bit 0,b" }; - case 0x41: return { "bit 0,c" }; - case 0x42: return { "bit 0,d" }; - case 0x43: return { "bit 0,e" }; - case 0x44: return { "bit 0,h" }; - case 0x45: return { "bit 0,l" }; - case 0x46: return { "bit 0,(hl)" }; - case 0x47: return { "bit 0,a" }; - case 0x48: return { "bit 1,b" }; - case 0x49: return { "bit 1,c" }; - case 0x4a: return { "bit 1,d" }; - case 0x4b: return { "bit 1,e" }; - case 0x4c: return { "bit 1,h" }; - case 0x4d: return { "bit 1,l" }; - case 0x4e: return { "bit 1,(hl)" }; - case 0x4f: return { "bit 1,a" }; - case 0x50: return { "bit 2,b" }; - case 0x51: return { "bit 2,c" }; - case 0x52: return { "bit 2,d" }; - case 0x53: return { "bit 2,e" }; - case 0x54: return { "bit 2,h" }; - case 0x55: return { "bit 2,l" }; - case 0x56: return { "bit 2,(hl)" }; - case 0x57: return { "bit 2,a" }; - case 0x58: return { "bit 3,b" }; - case 0x59: return { "bit 3,c" }; - case 0x5a: return { "bit 3,d" }; - case 0x5b: return { "bit 3,e" }; - case 0x5c: return { "bit 3,h" }; - case 0x5d: return { "bit 3,l" }; - case 0x5e: return { "bit 3,(hl)" }; - case 0x5f: return { "bit 3,a" }; - case 0x60: return { "bit 4,b" }; - case 0x61: return { "bit 4,c" }; - case 0x62: return { "bit 4,d" }; - case 0x63: return { "bit 4,e" }; - case 0x64: return { "bit 4,h" }; - case 0x65: return { "bit 4,l" }; - case 0x66: return { "bit 4,(hl)" }; - case 0x67: return { "bit 4,a" }; - case 0x68: return { "bit 5,b" }; - case 0x69: return { "bit 5,c" }; - case 0x6a: return { "bit 5,d" }; - case 0x6b: return { "bit 5,e" }; - case 0x6c: return { "bit 5,h" }; - case 0x6d: return { "bit 5,l" }; - case 0x6e: return { "bit 5,(hl)" }; - case 0x6f: return { "bit 5,a" }; - case 0x70: return { "bit 6,b" }; - case 0x71: return { "bit 6,c" }; - case 0x72: return { "bit 6,d" }; - case 0x73: return { "bit 6,e" }; - case 0x74: return { "bit 6,h" }; - case 0x75: return { "bit 6,l" }; - case 0x76: return { "bit 6,(hl)" }; - case 0x77: return { "bit 6,a" }; - case 0x78: return { "bit 7,b" }; - case 0x79: return { "bit 7,c" }; - case 0x7a: return { "bit 7,d" }; - case 0x7b: return { "bit 7,e" }; - case 0x7c: return { "bit 7,h" }; - case 0x7d: return { "bit 7,l" }; - case 0x7e: return { "bit 7,(hl)" }; - case 0x7f: return { "bit 7,a" }; - case 0x80: return { "res 0,b" }; - case 0x81: return { "res 0,c" }; - case 0x82: return { "res 0,d" }; - case 0x83: return { "res 0,e" }; - case 0x84: return { "res 0,h" }; - case 0x85: return { "res 0,l" }; - case 0x86: return { "res 0,(hl)" }; - case 0x87: return { "res 0,a" }; - case 0x88: return { "res 1,b" }; - case 0x89: return { "res 1,c" }; - case 0x8a: return { "res 1,d" }; - case 0x8b: return { "res 1,e" }; - case 0x8c: return { "res 1,h" }; - case 0x8d: return { "res 1,l" }; - case 0x8e: return { "res 1,(hl)" }; - case 0x8f: return { "res 1,a" }; - case 0x90: return { "res 2,b" }; - case 0x91: return { "res 2,c" }; - case 0x92: return { "res 2,d" }; - case 0x93: return { "res 2,e" }; - case 0x94: return { "res 2,h" }; - case 0x95: return { "res 2,l" }; - case 0x96: return { "res 2,(hl)" }; - case 0x97: return { "res 2,a" }; - case 0x98: return { "res 3,b" }; - case 0x99: return { "res 3,c" }; - case 0x9a: return { "res 3,d" }; - case 0x9b: return { "res 3,e" }; - case 0x9c: return { "res 3,h" }; - case 0x9d: return { "res 3,l" }; - case 0x9e: return { "res 3,(hl)" }; - case 0x9f: return { "res 3,a" }; - case 0xa0: return { "res 4,b" }; - case 0xa1: return { "res 4,c" }; - case 0xa2: return { "res 4,d" }; - case 0xa3: return { "res 4,e" }; - case 0xa4: return { "res 4,h" }; - case 0xa5: return { "res 4,l" }; - case 0xa6: return { "res 4,(hl)" }; - case 0xa7: return { "res 4,a" }; - case 0xa8: return { "res 5,b" }; - case 0xa9: return { "res 5,c" }; - case 0xaa: return { "res 5,d" }; - case 0xab: return { "res 5,e" }; - case 0xac: return { "res 5,h" }; - case 0xad: return { "res 5,l" }; - case 0xae: return { "res 5,(hl)" }; - case 0xaf: return { "res 5,a" }; - case 0xb0: return { "res 6,b" }; - case 0xb1: return { "res 6,c" }; - case 0xb2: return { "res 6,d" }; - case 0xb3: return { "res 6,e" }; - case 0xb4: return { "res 6,h" }; - case 0xb5: return { "res 6,l" }; - case 0xb6: return { "res 6,(hl)" }; - case 0xb7: return { "res 6,a" }; - case 0xb8: return { "res 7,b" }; - case 0xb9: return { "res 7,c" }; - case 0xba: return { "res 7,d" }; - case 0xbb: return { "res 7,e" }; - case 0xbc: return { "res 7,h" }; - case 0xbd: return { "res 7,l" }; - case 0xbe: return { "res 7,(hl)" }; - case 0xbf: return { "res 7,a" }; - case 0xc0: return { "set 0,b" }; - case 0xc1: return { "set 0,c" }; - case 0xc2: return { "set 0,d" }; - case 0xc3: return { "set 0,e" }; - case 0xc4: return { "set 0,h" }; - case 0xc5: return { "set 0,l" }; - case 0xc6: return { "set 0,(hl)" }; - case 0xc7: return { "set 0,a" }; - case 0xc8: return { "set 1,b" }; - case 0xc9: return { "set 1,c" }; - case 0xca: return { "set 1,d" }; - case 0xcb: return { "set 1,e" }; - case 0xcc: return { "set 1,h" }; - case 0xcd: return { "set 1,l" }; - case 0xce: return { "set 1,(hl)" }; - case 0xcf: return { "set 1,a" }; - case 0xd0: return { "set 2,b" }; - case 0xd1: return { "set 2,c" }; - case 0xd2: return { "set 2,d" }; - case 0xd3: return { "set 2,e" }; - case 0xd4: return { "set 2,h" }; - case 0xd5: return { "set 2,l" }; - case 0xd6: return { "set 2,(hl)" }; - case 0xd7: return { "set 2,a" }; - case 0xd8: return { "set 3,b" }; - case 0xd9: return { "set 3,c" }; - case 0xda: return { "set 3,d" }; - case 0xdb: return { "set 3,e" }; - case 0xdc: return { "set 3,h" }; - case 0xdd: return { "set 3,l" }; - case 0xde: return { "set 3,(hl)" }; - case 0xdf: return { "set 3,a" }; - case 0xe0: return { "set 4,b" }; - case 0xe1: return { "set 4,c" }; - case 0xe2: return { "set 4,d" }; - case 0xe3: return { "set 4,e" }; - case 0xe4: return { "set 4,h" }; - case 0xe5: return { "set 4,l" }; - case 0xe6: return { "set 4,(hl)" }; - case 0xe7: return { "set 4,a" }; - case 0xe8: return { "set 5,b" }; - case 0xe9: return { "set 5,c" }; - case 0xea: return { "set 5,d" }; - case 0xeb: return { "set 5,e" }; - case 0xec: return { "set 5,h" }; - case 0xed: return { "set 5,l" }; - case 0xee: return { "set 5,(hl)" }; - case 0xef: return { "set 5,a" }; - case 0xf0: return { "set 6,b" }; - case 0xf1: return { "set 6,c" }; - case 0xf2: return { "set 6,d" }; - case 0xf3: return { "set 6,e" }; - case 0xf4: return { "set 6,h" }; - case 0xf5: return { "set 6,l" }; - case 0xf6: return { "set 6,(hl)" }; - case 0xf7: return { "set 6,a" }; - case 0xf8: return { "set 7,b" }; - case 0xf9: return { "set 7,c" }; - case 0xfa: return { "set 7,d" }; - case 0xfb: return { "set 7,e" }; - case 0xfc: return { "set 7,h" }; - case 0xfd: return { "set 7,l" }; - case 0xfe: return { "set 7,(hl)" }; - case 0xff: return { "set 7,a" }; - } - - return ""; -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/cpu/core/registers.hpp b/waterbox/libsnes/bsnes/gameboy/cpu/core/registers.hpp deleted file mode 100644 index fbbcbd809f..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cpu/core/registers.hpp +++ /dev/null @@ -1,101 +0,0 @@ -enum { - A, F, AF, - B, C, BC, - D, E, DE, - H, L, HL, - SP, PC, -}; - -enum { - ZF, NF, HF, CF, -}; - -//register base class -//the idea here is to have all registers derive from a single base class. -//this allows construction of opcodes that can take any register as input or output, -//despite the fact that behind-the-scenes, special handling is done for eg: F, AF, HL, etc. -//registers can also be chained together: eg af = 0x0000 writes both a and f. -struct Register { - virtual operator unsigned() const = 0; - virtual unsigned operator=(unsigned x) = 0; - Register& operator=(const Register &x) { operator=((unsigned)x); return *this; } - - unsigned operator++(int) { unsigned r = *this; operator=(*this + 1); return r; } - unsigned operator--(int) { unsigned r = *this; operator=(*this - 1); return r; } - unsigned operator++() { return operator=(*this + 1); } - unsigned operator--() { return operator=(*this - 1); } - - unsigned operator |=(unsigned x) { return operator=(*this | x); } - unsigned operator ^=(unsigned x) { return operator=(*this ^ x); } - unsigned operator &=(unsigned x) { return operator=(*this & x); } - - unsigned operator<<=(unsigned x) { return operator=(*this << x); } - unsigned operator>>=(unsigned x) { return operator=(*this >> x); } - - unsigned operator +=(unsigned x) { return operator=(*this + x); } - unsigned operator -=(unsigned x) { return operator=(*this - x); } - unsigned operator *=(unsigned x) { return operator=(*this * x); } - unsigned operator /=(unsigned x) { return operator=(*this / x); } - unsigned operator %=(unsigned x) { return operator=(*this % x); } -}; - -struct Register8 : Register { - uint8 data; - operator unsigned() const { return data; } - unsigned operator=(unsigned x) { return data = x; } -}; - -struct RegisterF : Register { - bool z, n, h, c; - operator unsigned() const { return (z << 7) | (n << 6) | (h << 5) | (c << 4); } - unsigned operator=(unsigned x) { z = x & 0x80; n = x & 0x40; h = x & 0x20; c = x & 0x10; return *this; } - bool& operator[](unsigned r) { - static bool* table[] = { &z, &n, &h, &c }; - return *table[r]; - } -}; - -struct Register16 : Register { - uint16 data; - operator unsigned() const { return data; } - unsigned operator=(unsigned x) { return data = x; } -}; - -struct RegisterAF : Register { - Register8 &hi; - RegisterF &lo; - operator unsigned() const { return (hi << 8) | (lo << 0); } - unsigned operator=(unsigned x) { hi = x >> 8; lo = x >> 0; return *this; } - RegisterAF(Register8 &hi, RegisterF &lo) : hi(hi), lo(lo) {} -}; - -struct RegisterW : Register { - Register8 &hi, &lo; - operator unsigned() const { return (hi << 8) | (lo << 0); } - unsigned operator=(unsigned x) { hi = x >> 8; lo = x >> 0; return *this; } - RegisterW(Register8 &hi, Register8 &lo) : hi(hi), lo(lo) {} -}; - -struct Registers { - Register8 a; - RegisterF f; - RegisterAF af; - Register8 b; - Register8 c; - RegisterW bc; - Register8 d; - Register8 e; - RegisterW de; - Register8 h; - Register8 l; - RegisterW hl; - Register16 sp; - Register16 pc; - - Register& operator[](unsigned r) { - static Register* table[] = { &a, &f, &af, &b, &c, &bc, &d, &e, &de, &h, &l, &hl, &sp, &pc }; - return *table[r]; - } - - Registers() : af(a, f), bc(b, c), de(d, e), hl(h, l) {} -} r; diff --git a/waterbox/libsnes/bsnes/gameboy/cpu/core/table.cpp b/waterbox/libsnes/bsnes/gameboy/cpu/core/table.cpp deleted file mode 100644 index fa2f1112df..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cpu/core/table.cpp +++ /dev/null @@ -1,519 +0,0 @@ -#ifdef CPU_CPP - -void CPU::initialize_opcode_table() { - opcode_table[0x00] = &CPU::op_nop; - opcode_table[0x01] = &CPU::op_ld_rr_nn; - opcode_table[0x02] = &CPU::op_ld_rr_a; - opcode_table[0x03] = &CPU::op_inc_rr; - opcode_table[0x04] = &CPU::op_inc_r; - opcode_table[0x05] = &CPU::op_dec_r; - opcode_table[0x06] = &CPU::op_ld_r_n; - opcode_table[0x07] = &CPU::op_rlca; - opcode_table[0x08] = &CPU::op_ld_nn_sp; - opcode_table[0x09] = &CPU::op_add_hl_rr; - opcode_table[0x0a] = &CPU::op_ld_a_rr; - opcode_table[0x0b] = &CPU::op_dec_rr; - opcode_table[0x0c] = &CPU::op_inc_r; - opcode_table[0x0d] = &CPU::op_dec_r; - opcode_table[0x0e] = &CPU::op_ld_r_n; - opcode_table[0x0f] = &CPU::op_rrca; - opcode_table[0x10] = &CPU::op_stop; - opcode_table[0x11] = &CPU::op_ld_rr_nn; - opcode_table[0x12] = &CPU::op_ld_rr_a; - opcode_table[0x13] = &CPU::op_inc_rr; - opcode_table[0x14] = &CPU::op_inc_r; - opcode_table[0x15] = &CPU::op_dec_r; - opcode_table[0x16] = &CPU::op_ld_r_n; - opcode_table[0x17] = &CPU::op_rla; - opcode_table[0x18] = &CPU::op_jr_n; - opcode_table[0x19] = &CPU::op_add_hl_rr; - opcode_table[0x1a] = &CPU::op_ld_a_rr; - opcode_table[0x1b] = &CPU::op_dec_rr; - opcode_table[0x1c] = &CPU::op_inc_r; - opcode_table[0x1d] = &CPU::op_dec_r; - opcode_table[0x1e] = &CPU::op_ld_r_n; - opcode_table[0x1f] = &CPU::op_rra; - opcode_table[0x20] = &CPU::op_jr_f_n; - opcode_table[0x21] = &CPU::op_ld_rr_nn; - opcode_table[0x22] = &CPU::op_ldi_hl_a; - opcode_table[0x23] = &CPU::op_inc_rr; - opcode_table[0x24] = &CPU::op_inc_r; - opcode_table[0x25] = &CPU::op_dec_r; - opcode_table[0x26] = &CPU::op_ld_r_n; - opcode_table[0x27] = &CPU::op_daa; - opcode_table[0x28] = &CPU::op_jr_f_n; - opcode_table[0x29] = &CPU::op_add_hl_rr; - opcode_table[0x2a] = &CPU::op_ldi_a_hl; - opcode_table[0x2b] = &CPU::op_dec_rr; - opcode_table[0x2c] = &CPU::op_inc_r; - opcode_table[0x2d] = &CPU::op_dec_r; - opcode_table[0x2e] = &CPU::op_ld_r_n; - opcode_table[0x2f] = &CPU::op_cpl; - opcode_table[0x30] = &CPU::op_jr_f_n; - opcode_table[0x31] = &CPU::op_ld_rr_nn; - opcode_table[0x32] = &CPU::op_ldd_hl_a; - opcode_table[0x33] = &CPU::op_inc_rr; - opcode_table[0x34] = &CPU::op_inc_hl; - opcode_table[0x35] = &CPU::op_dec_hl; - opcode_table[0x36] = &CPU::op_ld_hl_n; - opcode_table[0x37] = &CPU::op_scf; - opcode_table[0x38] = &CPU::op_jr_f_n; - opcode_table[0x39] = &CPU::op_add_hl_rr; - opcode_table[0x3a] = &CPU::op_ldd_a_hl; - opcode_table[0x3b] = &CPU::op_dec_rr; - opcode_table[0x3c] = &CPU::op_inc_r; - opcode_table[0x3d] = &CPU::op_dec_r; - opcode_table[0x3e] = &CPU::op_ld_r_n; - opcode_table[0x3f] = &CPU::op_ccf; - opcode_table[0x40] = &CPU::op_ld_r_r; - opcode_table[0x41] = &CPU::op_ld_r_r; - opcode_table[0x42] = &CPU::op_ld_r_r; - opcode_table[0x43] = &CPU::op_ld_r_r; - opcode_table[0x44] = &CPU::op_ld_r_r; - opcode_table[0x45] = &CPU::op_ld_r_r; - opcode_table[0x46] = &CPU::op_ld_r_hl; - opcode_table[0x47] = &CPU::op_ld_r_r; - opcode_table[0x48] = &CPU::op_ld_r_r; - opcode_table[0x49] = &CPU::op_ld_r_r; - opcode_table[0x4a] = &CPU::op_ld_r_r; - opcode_table[0x4b] = &CPU::op_ld_r_r; - opcode_table[0x4c] = &CPU::op_ld_r_r; - opcode_table[0x4d] = &CPU::op_ld_r_r; - opcode_table[0x4e] = &CPU::op_ld_r_hl; - opcode_table[0x4f] = &CPU::op_ld_r_r; - opcode_table[0x50] = &CPU::op_ld_r_r; - opcode_table[0x51] = &CPU::op_ld_r_r; - opcode_table[0x52] = &CPU::op_ld_r_r; - opcode_table[0x53] = &CPU::op_ld_r_r; - opcode_table[0x54] = &CPU::op_ld_r_r; - opcode_table[0x55] = &CPU::op_ld_r_r; - opcode_table[0x56] = &CPU::op_ld_r_hl; - opcode_table[0x57] = &CPU::op_ld_r_r; - opcode_table[0x58] = &CPU::op_ld_r_r; - opcode_table[0x59] = &CPU::op_ld_r_r; - opcode_table[0x5a] = &CPU::op_ld_r_r; - opcode_table[0x5b] = &CPU::op_ld_r_r; - opcode_table[0x5c] = &CPU::op_ld_r_r; - opcode_table[0x5d] = &CPU::op_ld_r_r; - opcode_table[0x5e] = &CPU::op_ld_r_hl; - opcode_table[0x5f] = &CPU::op_ld_r_r; - opcode_table[0x60] = &CPU::op_ld_r_r; - opcode_table[0x61] = &CPU::op_ld_r_r; - opcode_table[0x62] = &CPU::op_ld_r_r; - opcode_table[0x63] = &CPU::op_ld_r_r; - opcode_table[0x64] = &CPU::op_ld_r_r; - opcode_table[0x65] = &CPU::op_ld_r_r; - opcode_table[0x66] = &CPU::op_ld_r_hl; - opcode_table[0x67] = &CPU::op_ld_r_r; - opcode_table[0x68] = &CPU::op_ld_r_r; - opcode_table[0x69] = &CPU::op_ld_r_r; - opcode_table[0x6a] = &CPU::op_ld_r_r; - opcode_table[0x6b] = &CPU::op_ld_r_r; - opcode_table[0x6c] = &CPU::op_ld_r_r; - opcode_table[0x6d] = &CPU::op_ld_r_r; - opcode_table[0x6e] = &CPU::op_ld_r_hl; - opcode_table[0x6f] = &CPU::op_ld_r_r; - opcode_table[0x70] = &CPU::op_ld_hl_r; - opcode_table[0x71] = &CPU::op_ld_hl_r; - opcode_table[0x72] = &CPU::op_ld_hl_r; - opcode_table[0x73] = &CPU::op_ld_hl_r; - opcode_table[0x74] = &CPU::op_ld_hl_r; - opcode_table[0x75] = &CPU::op_ld_hl_r; - opcode_table[0x76] = &CPU::op_halt; - opcode_table[0x77] = &CPU::op_ld_hl_r; - opcode_table[0x78] = &CPU::op_ld_r_r; - opcode_table[0x79] = &CPU::op_ld_r_r; - opcode_table[0x7a] = &CPU::op_ld_r_r; - opcode_table[0x7b] = &CPU::op_ld_r_r; - opcode_table[0x7c] = &CPU::op_ld_r_r; - opcode_table[0x7d] = &CPU::op_ld_r_r; - opcode_table[0x7e] = &CPU::op_ld_r_hl; - opcode_table[0x7f] = &CPU::op_ld_r_r; - opcode_table[0x80] = &CPU::op_add_a_r; - opcode_table[0x81] = &CPU::op_add_a_r; - opcode_table[0x82] = &CPU::op_add_a_r; - opcode_table[0x83] = &CPU::op_add_a_r; - opcode_table[0x84] = &CPU::op_add_a_r; - opcode_table[0x85] = &CPU::op_add_a_r; - opcode_table[0x86] = &CPU::op_add_a_hl; - opcode_table[0x87] = &CPU::op_add_a_r; - opcode_table[0x88] = &CPU::op_adc_a_r; - opcode_table[0x89] = &CPU::op_adc_a_r; - opcode_table[0x8a] = &CPU::op_adc_a_r; - opcode_table[0x8b] = &CPU::op_adc_a_r; - opcode_table[0x8c] = &CPU::op_adc_a_r; - opcode_table[0x8d] = &CPU::op_adc_a_r; - opcode_table[0x8e] = &CPU::op_adc_a_hl; - opcode_table[0x8f] = &CPU::op_adc_a_r; - opcode_table[0x90] = &CPU::op_sub_a_r; - opcode_table[0x91] = &CPU::op_sub_a_r; - opcode_table[0x92] = &CPU::op_sub_a_r; - opcode_table[0x93] = &CPU::op_sub_a_r; - opcode_table[0x94] = &CPU::op_sub_a_r; - opcode_table[0x95] = &CPU::op_sub_a_r; - opcode_table[0x96] = &CPU::op_sub_a_hl; - opcode_table[0x97] = &CPU::op_sub_a_r; - opcode_table[0x98] = &CPU::op_sbc_a_r; - opcode_table[0x99] = &CPU::op_sbc_a_r; - opcode_table[0x9a] = &CPU::op_sbc_a_r; - opcode_table[0x9b] = &CPU::op_sbc_a_r; - opcode_table[0x9c] = &CPU::op_sbc_a_r; - opcode_table[0x9d] = &CPU::op_sbc_a_r; - opcode_table[0x9e] = &CPU::op_sbc_a_hl; - opcode_table[0x9f] = &CPU::op_sbc_a_r; - opcode_table[0xa0] = &CPU::op_and_a_r; - opcode_table[0xa1] = &CPU::op_and_a_r; - opcode_table[0xa2] = &CPU::op_and_a_r; - opcode_table[0xa3] = &CPU::op_and_a_r; - opcode_table[0xa4] = &CPU::op_and_a_r; - opcode_table[0xa5] = &CPU::op_and_a_r; - opcode_table[0xa6] = &CPU::op_and_a_hl; - opcode_table[0xa7] = &CPU::op_and_a_r; - opcode_table[0xa8] = &CPU::op_xor_a_r; - opcode_table[0xa9] = &CPU::op_xor_a_r; - opcode_table[0xaa] = &CPU::op_xor_a_r; - opcode_table[0xab] = &CPU::op_xor_a_r; - opcode_table[0xac] = &CPU::op_xor_a_r; - opcode_table[0xad] = &CPU::op_xor_a_r; - opcode_table[0xae] = &CPU::op_xor_a_hl; - opcode_table[0xaf] = &CPU::op_xor_a_r; - opcode_table[0xb0] = &CPU::op_or_a_r; - opcode_table[0xb1] = &CPU::op_or_a_r; - opcode_table[0xb2] = &CPU::op_or_a_r; - opcode_table[0xb3] = &CPU::op_or_a_r; - opcode_table[0xb4] = &CPU::op_or_a_r; - opcode_table[0xb5] = &CPU::op_or_a_r; - opcode_table[0xb6] = &CPU::op_or_a_hl; - opcode_table[0xb7] = &CPU::op_or_a_r; - opcode_table[0xb8] = &CPU::op_cp_a_r; - opcode_table[0xb9] = &CPU::op_cp_a_r; - opcode_table[0xba] = &CPU::op_cp_a_r; - opcode_table[0xbb] = &CPU::op_cp_a_r; - opcode_table[0xbc] = &CPU::op_cp_a_r; - opcode_table[0xbd] = &CPU::op_cp_a_r; - opcode_table[0xbe] = &CPU::op_cp_a_hl; - opcode_table[0xbf] = &CPU::op_cp_a_r; - opcode_table[0xc0] = &CPU::op_ret_f; - opcode_table[0xc1] = &CPU::op_pop_rr; - opcode_table[0xc2] = &CPU::op_jp_f_nn; - opcode_table[0xc3] = &CPU::op_jp_nn; - opcode_table[0xc4] = &CPU::op_call_f_nn; - opcode_table[0xc5] = &CPU::op_push_rr; - opcode_table[0xc6] = &CPU::op_add_a_n; - opcode_table[0xc7] = &CPU::op_rst_n<0x00>; - opcode_table[0xc8] = &CPU::op_ret_f; - opcode_table[0xc9] = &CPU::op_ret; - opcode_table[0xca] = &CPU::op_jp_f_nn; - opcode_table[0xcb] = &CPU::op_cb; - opcode_table[0xcc] = &CPU::op_call_f_nn; - opcode_table[0xcd] = &CPU::op_call_nn; - opcode_table[0xce] = &CPU::op_adc_a_n; - opcode_table[0xcf] = &CPU::op_rst_n<0x08>; - opcode_table[0xd0] = &CPU::op_ret_f; - opcode_table[0xd1] = &CPU::op_pop_rr; - opcode_table[0xd2] = &CPU::op_jp_f_nn; - opcode_table[0xd3] = &CPU::op_xx; - opcode_table[0xd4] = &CPU::op_call_f_nn; - opcode_table[0xd5] = &CPU::op_push_rr; - opcode_table[0xd6] = &CPU::op_sub_a_n; - opcode_table[0xd7] = &CPU::op_rst_n<0x10>; - opcode_table[0xd8] = &CPU::op_ret_f; - opcode_table[0xd9] = &CPU::op_reti; - opcode_table[0xda] = &CPU::op_jp_f_nn; - opcode_table[0xdb] = &CPU::op_xx; - opcode_table[0xdc] = &CPU::op_call_f_nn; - opcode_table[0xdd] = &CPU::op_xx; - opcode_table[0xde] = &CPU::op_sbc_a_n; - opcode_table[0xdf] = &CPU::op_rst_n<0x18>; - opcode_table[0xe0] = &CPU::op_ld_ffn_a; - opcode_table[0xe1] = &CPU::op_pop_rr; - opcode_table[0xe2] = &CPU::op_ld_ffc_a; - opcode_table[0xe3] = &CPU::op_xx; - opcode_table[0xe4] = &CPU::op_xx; - opcode_table[0xe5] = &CPU::op_push_rr; - opcode_table[0xe6] = &CPU::op_and_a_n; - opcode_table[0xe7] = &CPU::op_rst_n<0x20>; - opcode_table[0xe8] = &CPU::op_add_sp_n; - opcode_table[0xe9] = &CPU::op_jp_hl; - opcode_table[0xea] = &CPU::op_ld_nn_a; - opcode_table[0xeb] = &CPU::op_xx; - opcode_table[0xec] = &CPU::op_xx; - opcode_table[0xed] = &CPU::op_xx; - opcode_table[0xee] = &CPU::op_xor_a_n; - opcode_table[0xef] = &CPU::op_rst_n<0x28>; - opcode_table[0xf0] = &CPU::op_ld_a_ffn; - opcode_table[0xf1] = &CPU::op_pop_rr; - opcode_table[0xf2] = &CPU::op_ld_a_ffc; - opcode_table[0xf3] = &CPU::op_di; - opcode_table[0xf4] = &CPU::op_xx; - opcode_table[0xf5] = &CPU::op_push_rr; - opcode_table[0xf6] = &CPU::op_or_a_n; - opcode_table[0xf7] = &CPU::op_rst_n<0x30>; - opcode_table[0xf8] = &CPU::op_ld_hl_sp_n; - opcode_table[0xf9] = &CPU::op_ld_sp_hl; - opcode_table[0xfa] = &CPU::op_ld_a_nn; - opcode_table[0xfb] = &CPU::op_ei; - opcode_table[0xfc] = &CPU::op_xx; - opcode_table[0xfd] = &CPU::op_xx; - opcode_table[0xfe] = &CPU::op_cp_a_n; - opcode_table[0xff] = &CPU::op_rst_n<0x38>; - - opcode_table_cb[0x00] = &CPU::op_rlc_r; - opcode_table_cb[0x01] = &CPU::op_rlc_r; - opcode_table_cb[0x02] = &CPU::op_rlc_r; - opcode_table_cb[0x03] = &CPU::op_rlc_r; - opcode_table_cb[0x04] = &CPU::op_rlc_r; - opcode_table_cb[0x05] = &CPU::op_rlc_r; - opcode_table_cb[0x06] = &CPU::op_rlc_hl; - opcode_table_cb[0x07] = &CPU::op_rlc_r; - opcode_table_cb[0x08] = &CPU::op_rrc_r; - opcode_table_cb[0x09] = &CPU::op_rrc_r; - opcode_table_cb[0x0a] = &CPU::op_rrc_r; - opcode_table_cb[0x0b] = &CPU::op_rrc_r; - opcode_table_cb[0x0c] = &CPU::op_rrc_r; - opcode_table_cb[0x0d] = &CPU::op_rrc_r; - opcode_table_cb[0x0e] = &CPU::op_rrc_hl; - opcode_table_cb[0x0f] = &CPU::op_rrc_r; - opcode_table_cb[0x10] = &CPU::op_rl_r; - opcode_table_cb[0x11] = &CPU::op_rl_r; - opcode_table_cb[0x12] = &CPU::op_rl_r; - opcode_table_cb[0x13] = &CPU::op_rl_r; - opcode_table_cb[0x14] = &CPU::op_rl_r; - opcode_table_cb[0x15] = &CPU::op_rl_r; - opcode_table_cb[0x16] = &CPU::op_rl_hl; - opcode_table_cb[0x17] = &CPU::op_rl_r; - opcode_table_cb[0x18] = &CPU::op_rr_r; - opcode_table_cb[0x19] = &CPU::op_rr_r; - opcode_table_cb[0x1a] = &CPU::op_rr_r; - opcode_table_cb[0x1b] = &CPU::op_rr_r; - opcode_table_cb[0x1c] = &CPU::op_rr_r; - opcode_table_cb[0x1d] = &CPU::op_rr_r; - opcode_table_cb[0x1e] = &CPU::op_rr_hl; - opcode_table_cb[0x1f] = &CPU::op_rr_r; - opcode_table_cb[0x20] = &CPU::op_sla_r; - opcode_table_cb[0x21] = &CPU::op_sla_r; - opcode_table_cb[0x22] = &CPU::op_sla_r; - opcode_table_cb[0x23] = &CPU::op_sla_r; - opcode_table_cb[0x24] = &CPU::op_sla_r; - opcode_table_cb[0x25] = &CPU::op_sla_r; - opcode_table_cb[0x26] = &CPU::op_sla_hl; - opcode_table_cb[0x27] = &CPU::op_sla_r; - opcode_table_cb[0x28] = &CPU::op_sra_r; - opcode_table_cb[0x29] = &CPU::op_sra_r; - opcode_table_cb[0x2a] = &CPU::op_sra_r; - opcode_table_cb[0x2b] = &CPU::op_sra_r; - opcode_table_cb[0x2c] = &CPU::op_sra_r; - opcode_table_cb[0x2d] = &CPU::op_sra_r; - opcode_table_cb[0x2e] = &CPU::op_sra_hl; - opcode_table_cb[0x2f] = &CPU::op_sra_r; - opcode_table_cb[0x30] = &CPU::op_swap_r; - opcode_table_cb[0x31] = &CPU::op_swap_r; - opcode_table_cb[0x32] = &CPU::op_swap_r; - opcode_table_cb[0x33] = &CPU::op_swap_r; - opcode_table_cb[0x34] = &CPU::op_swap_r; - opcode_table_cb[0x35] = &CPU::op_swap_r; - opcode_table_cb[0x36] = &CPU::op_swap_hl; - opcode_table_cb[0x37] = &CPU::op_swap_r; - opcode_table_cb[0x38] = &CPU::op_srl_r; - opcode_table_cb[0x39] = &CPU::op_srl_r; - opcode_table_cb[0x3a] = &CPU::op_srl_r; - opcode_table_cb[0x3b] = &CPU::op_srl_r; - opcode_table_cb[0x3c] = &CPU::op_srl_r; - opcode_table_cb[0x3d] = &CPU::op_srl_r; - opcode_table_cb[0x3e] = &CPU::op_srl_hl; - opcode_table_cb[0x3f] = &CPU::op_srl_r; - opcode_table_cb[0x40] = &CPU::op_bit_n_r<0, B>; - opcode_table_cb[0x41] = &CPU::op_bit_n_r<0, C>; - opcode_table_cb[0x42] = &CPU::op_bit_n_r<0, D>; - opcode_table_cb[0x43] = &CPU::op_bit_n_r<0, E>; - opcode_table_cb[0x44] = &CPU::op_bit_n_r<0, H>; - opcode_table_cb[0x45] = &CPU::op_bit_n_r<0, L>; - opcode_table_cb[0x46] = &CPU::op_bit_n_hl<0>; - opcode_table_cb[0x47] = &CPU::op_bit_n_r<0, A>; - opcode_table_cb[0x48] = &CPU::op_bit_n_r<1, B>; - opcode_table_cb[0x49] = &CPU::op_bit_n_r<1, C>; - opcode_table_cb[0x4a] = &CPU::op_bit_n_r<1, D>; - opcode_table_cb[0x4b] = &CPU::op_bit_n_r<1, E>; - opcode_table_cb[0x4c] = &CPU::op_bit_n_r<1, H>; - opcode_table_cb[0x4d] = &CPU::op_bit_n_r<1, L>; - opcode_table_cb[0x4e] = &CPU::op_bit_n_hl<1>; - opcode_table_cb[0x4f] = &CPU::op_bit_n_r<1, A>; - opcode_table_cb[0x50] = &CPU::op_bit_n_r<2, B>; - opcode_table_cb[0x51] = &CPU::op_bit_n_r<2, C>; - opcode_table_cb[0x52] = &CPU::op_bit_n_r<2, D>; - opcode_table_cb[0x53] = &CPU::op_bit_n_r<2, E>; - opcode_table_cb[0x54] = &CPU::op_bit_n_r<2, H>; - opcode_table_cb[0x55] = &CPU::op_bit_n_r<2, L>; - opcode_table_cb[0x56] = &CPU::op_bit_n_hl<2>; - opcode_table_cb[0x57] = &CPU::op_bit_n_r<2, A>; - opcode_table_cb[0x58] = &CPU::op_bit_n_r<3, B>; - opcode_table_cb[0x59] = &CPU::op_bit_n_r<3, C>; - opcode_table_cb[0x5a] = &CPU::op_bit_n_r<3, D>; - opcode_table_cb[0x5b] = &CPU::op_bit_n_r<3, E>; - opcode_table_cb[0x5c] = &CPU::op_bit_n_r<3, H>; - opcode_table_cb[0x5d] = &CPU::op_bit_n_r<3, L>; - opcode_table_cb[0x5e] = &CPU::op_bit_n_hl<3>; - opcode_table_cb[0x5f] = &CPU::op_bit_n_r<3, A>; - opcode_table_cb[0x60] = &CPU::op_bit_n_r<4, B>; - opcode_table_cb[0x61] = &CPU::op_bit_n_r<4, C>; - opcode_table_cb[0x62] = &CPU::op_bit_n_r<4, D>; - opcode_table_cb[0x63] = &CPU::op_bit_n_r<4, E>; - opcode_table_cb[0x64] = &CPU::op_bit_n_r<4, H>; - opcode_table_cb[0x65] = &CPU::op_bit_n_r<4, L>; - opcode_table_cb[0x66] = &CPU::op_bit_n_hl<4>; - opcode_table_cb[0x67] = &CPU::op_bit_n_r<4, A>; - opcode_table_cb[0x68] = &CPU::op_bit_n_r<5, B>; - opcode_table_cb[0x69] = &CPU::op_bit_n_r<5, C>; - opcode_table_cb[0x6a] = &CPU::op_bit_n_r<5, D>; - opcode_table_cb[0x6b] = &CPU::op_bit_n_r<5, E>; - opcode_table_cb[0x6c] = &CPU::op_bit_n_r<5, H>; - opcode_table_cb[0x6d] = &CPU::op_bit_n_r<5, L>; - opcode_table_cb[0x6e] = &CPU::op_bit_n_hl<5>; - opcode_table_cb[0x6f] = &CPU::op_bit_n_r<5, A>; - opcode_table_cb[0x70] = &CPU::op_bit_n_r<6, B>; - opcode_table_cb[0x71] = &CPU::op_bit_n_r<6, C>; - opcode_table_cb[0x72] = &CPU::op_bit_n_r<6, D>; - opcode_table_cb[0x73] = &CPU::op_bit_n_r<6, E>; - opcode_table_cb[0x74] = &CPU::op_bit_n_r<6, H>; - opcode_table_cb[0x75] = &CPU::op_bit_n_r<6, L>; - opcode_table_cb[0x76] = &CPU::op_bit_n_hl<6>; - opcode_table_cb[0x77] = &CPU::op_bit_n_r<6, A>; - opcode_table_cb[0x78] = &CPU::op_bit_n_r<7, B>; - opcode_table_cb[0x79] = &CPU::op_bit_n_r<7, C>; - opcode_table_cb[0x7a] = &CPU::op_bit_n_r<7, D>; - opcode_table_cb[0x7b] = &CPU::op_bit_n_r<7, E>; - opcode_table_cb[0x7c] = &CPU::op_bit_n_r<7, H>; - opcode_table_cb[0x7d] = &CPU::op_bit_n_r<7, L>; - opcode_table_cb[0x7e] = &CPU::op_bit_n_hl<7>; - opcode_table_cb[0x7f] = &CPU::op_bit_n_r<7, A>; - opcode_table_cb[0x80] = &CPU::op_res_n_r<0, B>; - opcode_table_cb[0x81] = &CPU::op_res_n_r<0, C>; - opcode_table_cb[0x82] = &CPU::op_res_n_r<0, D>; - opcode_table_cb[0x83] = &CPU::op_res_n_r<0, E>; - opcode_table_cb[0x84] = &CPU::op_res_n_r<0, H>; - opcode_table_cb[0x85] = &CPU::op_res_n_r<0, L>; - opcode_table_cb[0x86] = &CPU::op_res_n_hl<0>; - opcode_table_cb[0x87] = &CPU::op_res_n_r<0, A>; - opcode_table_cb[0x88] = &CPU::op_res_n_r<1, B>; - opcode_table_cb[0x89] = &CPU::op_res_n_r<1, C>; - opcode_table_cb[0x8a] = &CPU::op_res_n_r<1, D>; - opcode_table_cb[0x8b] = &CPU::op_res_n_r<1, E>; - opcode_table_cb[0x8c] = &CPU::op_res_n_r<1, H>; - opcode_table_cb[0x8d] = &CPU::op_res_n_r<1, L>; - opcode_table_cb[0x8e] = &CPU::op_res_n_hl<1>; - opcode_table_cb[0x8f] = &CPU::op_res_n_r<1, A>; - opcode_table_cb[0x90] = &CPU::op_res_n_r<2, B>; - opcode_table_cb[0x91] = &CPU::op_res_n_r<2, C>; - opcode_table_cb[0x92] = &CPU::op_res_n_r<2, D>; - opcode_table_cb[0x93] = &CPU::op_res_n_r<2, E>; - opcode_table_cb[0x94] = &CPU::op_res_n_r<2, H>; - opcode_table_cb[0x95] = &CPU::op_res_n_r<2, L>; - opcode_table_cb[0x96] = &CPU::op_res_n_hl<2>; - opcode_table_cb[0x97] = &CPU::op_res_n_r<2, A>; - opcode_table_cb[0x98] = &CPU::op_res_n_r<3, B>; - opcode_table_cb[0x99] = &CPU::op_res_n_r<3, C>; - opcode_table_cb[0x9a] = &CPU::op_res_n_r<3, D>; - opcode_table_cb[0x9b] = &CPU::op_res_n_r<3, E>; - opcode_table_cb[0x9c] = &CPU::op_res_n_r<3, H>; - opcode_table_cb[0x9d] = &CPU::op_res_n_r<3, L>; - opcode_table_cb[0x9e] = &CPU::op_res_n_hl<3>; - opcode_table_cb[0x9f] = &CPU::op_res_n_r<3, A>; - opcode_table_cb[0xa0] = &CPU::op_res_n_r<4, B>; - opcode_table_cb[0xa1] = &CPU::op_res_n_r<4, C>; - opcode_table_cb[0xa2] = &CPU::op_res_n_r<4, D>; - opcode_table_cb[0xa3] = &CPU::op_res_n_r<4, E>; - opcode_table_cb[0xa4] = &CPU::op_res_n_r<4, H>; - opcode_table_cb[0xa5] = &CPU::op_res_n_r<4, L>; - opcode_table_cb[0xa6] = &CPU::op_res_n_hl<4>; - opcode_table_cb[0xa7] = &CPU::op_res_n_r<4, A>; - opcode_table_cb[0xa8] = &CPU::op_res_n_r<5, B>; - opcode_table_cb[0xa9] = &CPU::op_res_n_r<5, C>; - opcode_table_cb[0xaa] = &CPU::op_res_n_r<5, D>; - opcode_table_cb[0xab] = &CPU::op_res_n_r<5, E>; - opcode_table_cb[0xac] = &CPU::op_res_n_r<5, H>; - opcode_table_cb[0xad] = &CPU::op_res_n_r<5, L>; - opcode_table_cb[0xae] = &CPU::op_res_n_hl<5>; - opcode_table_cb[0xaf] = &CPU::op_res_n_r<5, A>; - opcode_table_cb[0xb0] = &CPU::op_res_n_r<6, B>; - opcode_table_cb[0xb1] = &CPU::op_res_n_r<6, C>; - opcode_table_cb[0xb2] = &CPU::op_res_n_r<6, D>; - opcode_table_cb[0xb3] = &CPU::op_res_n_r<6, E>; - opcode_table_cb[0xb4] = &CPU::op_res_n_r<6, H>; - opcode_table_cb[0xb5] = &CPU::op_res_n_r<6, L>; - opcode_table_cb[0xb6] = &CPU::op_res_n_hl<6>; - opcode_table_cb[0xb7] = &CPU::op_res_n_r<6, A>; - opcode_table_cb[0xb8] = &CPU::op_res_n_r<7, B>; - opcode_table_cb[0xb9] = &CPU::op_res_n_r<7, C>; - opcode_table_cb[0xba] = &CPU::op_res_n_r<7, D>; - opcode_table_cb[0xbb] = &CPU::op_res_n_r<7, E>; - opcode_table_cb[0xbc] = &CPU::op_res_n_r<7, H>; - opcode_table_cb[0xbd] = &CPU::op_res_n_r<7, L>; - opcode_table_cb[0xbe] = &CPU::op_res_n_hl<7>; - opcode_table_cb[0xbf] = &CPU::op_res_n_r<7, A>; - opcode_table_cb[0xc0] = &CPU::op_set_n_r<0, B>; - opcode_table_cb[0xc1] = &CPU::op_set_n_r<0, C>; - opcode_table_cb[0xc2] = &CPU::op_set_n_r<0, D>; - opcode_table_cb[0xc3] = &CPU::op_set_n_r<0, E>; - opcode_table_cb[0xc4] = &CPU::op_set_n_r<0, H>; - opcode_table_cb[0xc5] = &CPU::op_set_n_r<0, L>; - opcode_table_cb[0xc6] = &CPU::op_set_n_hl<0>; - opcode_table_cb[0xc7] = &CPU::op_set_n_r<0, A>; - opcode_table_cb[0xc8] = &CPU::op_set_n_r<1, B>; - opcode_table_cb[0xc9] = &CPU::op_set_n_r<1, C>; - opcode_table_cb[0xca] = &CPU::op_set_n_r<1, D>; - opcode_table_cb[0xcb] = &CPU::op_set_n_r<1, E>; - opcode_table_cb[0xcc] = &CPU::op_set_n_r<1, H>; - opcode_table_cb[0xcd] = &CPU::op_set_n_r<1, L>; - opcode_table_cb[0xce] = &CPU::op_set_n_hl<1>; - opcode_table_cb[0xcf] = &CPU::op_set_n_r<1, A>; - opcode_table_cb[0xd0] = &CPU::op_set_n_r<2, B>; - opcode_table_cb[0xd1] = &CPU::op_set_n_r<2, C>; - opcode_table_cb[0xd2] = &CPU::op_set_n_r<2, D>; - opcode_table_cb[0xd3] = &CPU::op_set_n_r<2, E>; - opcode_table_cb[0xd4] = &CPU::op_set_n_r<2, H>; - opcode_table_cb[0xd5] = &CPU::op_set_n_r<2, L>; - opcode_table_cb[0xd6] = &CPU::op_set_n_hl<2>; - opcode_table_cb[0xd7] = &CPU::op_set_n_r<2, A>; - opcode_table_cb[0xd8] = &CPU::op_set_n_r<3, B>; - opcode_table_cb[0xd9] = &CPU::op_set_n_r<3, C>; - opcode_table_cb[0xda] = &CPU::op_set_n_r<3, D>; - opcode_table_cb[0xdb] = &CPU::op_set_n_r<3, E>; - opcode_table_cb[0xdc] = &CPU::op_set_n_r<3, H>; - opcode_table_cb[0xdd] = &CPU::op_set_n_r<3, L>; - opcode_table_cb[0xde] = &CPU::op_set_n_hl<3>; - opcode_table_cb[0xdf] = &CPU::op_set_n_r<3, A>; - opcode_table_cb[0xe0] = &CPU::op_set_n_r<4, B>; - opcode_table_cb[0xe1] = &CPU::op_set_n_r<4, C>; - opcode_table_cb[0xe2] = &CPU::op_set_n_r<4, D>; - opcode_table_cb[0xe3] = &CPU::op_set_n_r<4, E>; - opcode_table_cb[0xe4] = &CPU::op_set_n_r<4, H>; - opcode_table_cb[0xe5] = &CPU::op_set_n_r<4, L>; - opcode_table_cb[0xe6] = &CPU::op_set_n_hl<4>; - opcode_table_cb[0xe7] = &CPU::op_set_n_r<4, A>; - opcode_table_cb[0xe8] = &CPU::op_set_n_r<5, B>; - opcode_table_cb[0xe9] = &CPU::op_set_n_r<5, C>; - opcode_table_cb[0xea] = &CPU::op_set_n_r<5, D>; - opcode_table_cb[0xeb] = &CPU::op_set_n_r<5, E>; - opcode_table_cb[0xec] = &CPU::op_set_n_r<5, H>; - opcode_table_cb[0xed] = &CPU::op_set_n_r<5, L>; - opcode_table_cb[0xee] = &CPU::op_set_n_hl<5>; - opcode_table_cb[0xef] = &CPU::op_set_n_r<5, A>; - opcode_table_cb[0xf0] = &CPU::op_set_n_r<6, B>; - opcode_table_cb[0xf1] = &CPU::op_set_n_r<6, C>; - opcode_table_cb[0xf2] = &CPU::op_set_n_r<6, D>; - opcode_table_cb[0xf3] = &CPU::op_set_n_r<6, E>; - opcode_table_cb[0xf4] = &CPU::op_set_n_r<6, H>; - opcode_table_cb[0xf5] = &CPU::op_set_n_r<6, L>; - opcode_table_cb[0xf6] = &CPU::op_set_n_hl<6>; - opcode_table_cb[0xf7] = &CPU::op_set_n_r<6, A>; - opcode_table_cb[0xf8] = &CPU::op_set_n_r<7, B>; - opcode_table_cb[0xf9] = &CPU::op_set_n_r<7, C>; - opcode_table_cb[0xfa] = &CPU::op_set_n_r<7, D>; - opcode_table_cb[0xfb] = &CPU::op_set_n_r<7, E>; - opcode_table_cb[0xfc] = &CPU::op_set_n_r<7, H>; - opcode_table_cb[0xfd] = &CPU::op_set_n_r<7, L>; - opcode_table_cb[0xfe] = &CPU::op_set_n_hl<7>; - opcode_table_cb[0xff] = &CPU::op_set_n_r<7, A>; -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/cpu/cpu.cpp b/waterbox/libsnes/bsnes/gameboy/cpu/cpu.cpp deleted file mode 100644 index 4b7e95b071..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cpu/cpu.cpp +++ /dev/null @@ -1,226 +0,0 @@ -#include - -#include - -#define CPU_CPP -namespace GameBoy { - -#include "core/core.cpp" -#include "mmio/mmio.cpp" -#include "timing/timing.cpp" -CPU cpu; - -void CPU::Main() { - cpu.main(); -} - -void CPU::main() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::CPU) { - scheduler.sync = Scheduler::SynchronizeMode::All; - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - if(SNES::interface()->wanttrace & TRACE_GB_MASK) - { - auto disasm = disassemble(r[PC]); - SNES::interface()->cpuTrace(TRACE_GB, (const char*)disasm); - } - //if(trace) print(disassemble(r[PC]), "\n"); - interrupt_test(); - cdlInfo.currFlags = eCDLog_Flags_ExecFirst; - uint8 opcode = op_read(r[PC]++); - cdlInfo.currFlags = eCDLog_Flags_CPUData; - (this->*opcode_table[opcode])(); - } -} - -void CPU::interrupt_raise(CPU::Interrupt id) { - if(id == Interrupt::Vblank) { - status.interrupt_request_vblank = 1; - if(status.interrupt_enable_vblank) status.halt = false; - } - - if(id == Interrupt::Stat) { - status.interrupt_request_stat = 1; - if(status.interrupt_enable_stat) status.halt = false; - } - - if(id == Interrupt::Timer) { - status.interrupt_request_timer = 1; - if(status.interrupt_enable_timer) status.halt = false; - } - - if(id == Interrupt::Serial) { - status.interrupt_request_serial = 1; - if(status.interrupt_enable_serial) status.halt = false; - } - - if(id == Interrupt::Joypad) { - status.interrupt_request_joypad = 1; - if(status.interrupt_enable_joypad) status.halt = status.stop = false; - } -} - -void CPU::interrupt_test() { - if(status.ime) { - if(status.interrupt_request_vblank && status.interrupt_enable_vblank) { - status.interrupt_request_vblank = 0; - return interrupt_exec(0x0040); - } - - if(status.interrupt_request_stat && status.interrupt_enable_stat) { - status.interrupt_request_stat = 0; - return interrupt_exec(0x0048); - } - - if(status.interrupt_request_timer && status.interrupt_enable_timer) { - status.interrupt_request_timer = 0; - return interrupt_exec(0x0050); - } - - if(status.interrupt_request_serial && status.interrupt_enable_serial) { - status.interrupt_request_serial = 0; - return interrupt_exec(0x0058); - } - - if(status.interrupt_request_joypad && status.interrupt_enable_joypad) { - status.interrupt_request_joypad = 0; - return interrupt_exec(0x0060); - } - } -} - -void CPU::interrupt_exec(uint16 pc) { - status.ime = 0; - op_write(--r[SP], r[PC] >> 8); - op_write(--r[SP], r[PC] >> 0); - r[PC] = pc; - op_io(); - op_io(); - op_io(); -} - -void CPU::power() { - create(Main, 4 * 1024 * 1024); - - for(unsigned n = 0xc000; n <= 0xdfff; n++) bus.mmio[n] = this; //WRAM - for(unsigned n = 0xe000; n <= 0xfdff; n++) bus.mmio[n] = this; //WRAM (mirror) - for(unsigned n = 0xff80; n <= 0xfffe; n++) bus.mmio[n] = this; //HRAM - - bus.mmio[0xff00] = this; //JOYP - bus.mmio[0xff01] = this; //SB - bus.mmio[0xff02] = this; //SC - bus.mmio[0xff04] = this; //DIV - bus.mmio[0xff05] = this; //TIMA - bus.mmio[0xff06] = this; //TMA - bus.mmio[0xff07] = this; //TAC - bus.mmio[0xff0f] = this; //IF - bus.mmio[0xff46] = this; //DMA - bus.mmio[0xffff] = this; //IE - - if(system.cgb()) { - bus.mmio[0xff4d] = this; //KEY1 - bus.mmio[0xff51] = this; //HDMA1 - bus.mmio[0xff52] = this; //HDMA2 - bus.mmio[0xff53] = this; //HDMA3 - bus.mmio[0xff54] = this; //HDMA4 - bus.mmio[0xff55] = this; //HDMA5 - bus.mmio[0xff56] = this; //RP - bus.mmio[0xff6c] = this; //??? - bus.mmio[0xff70] = this; //SVBK - bus.mmio[0xff72] = this; //??? - bus.mmio[0xff73] = this; //??? - bus.mmio[0xff74] = this; //??? - bus.mmio[0xff75] = this; //??? - bus.mmio[0xff76] = this; //??? - bus.mmio[0xff77] = this; //??? - } - - for(unsigned n = 0; n < 32768; n++) wram[n] = 0x00; - for(unsigned n = 0; n < 8192; n++) hram[n] = 0x00; - - r[PC] = 0x0000; - r[SP] = 0x0000; - r[AF] = 0x0000; - r[BC] = 0x0000; - r[DE] = 0x0000; - r[HL] = 0x0000; - - status.clock = 0; - status.halt = false; - status.stop = false; - status.ei = false; - status.ime = 0; - - status.p15 = 0; - status.p14 = 0; - status.joyp = 0; - status.mlt_req = 0; - - status.serial_data = 0; - status.serial_bits = 0; - - status.serial_transfer = 0; - status.serial_clock = 0; - - status.div = 0; - - status.tima = 0; - - status.tma = 0; - - status.timer_enable = 0; - status.timer_clock = 0; - - status.interrupt_request_joypad = 0; - status.interrupt_request_serial = 0; - status.interrupt_request_timer = 0; - status.interrupt_request_stat = 0; - status.interrupt_request_vblank = 0; - - status.speed_double = 0; - status.speed_switch = 0; - - status.dma_source = 0; - status.dma_target = 0; - - status.dma_mode = 0; - status.dma_length = 0; - - status.ff6c = 0; - status.ff72 = 0; - status.ff73 = 0; - status.ff74 = 0; - status.ff75 = 0; - - status.wram_bank = 1; - - status.interrupt_enable_joypad = 0; - status.interrupt_enable_serial = 0; - status.interrupt_enable_timer = 0; - status.interrupt_enable_stat = 0; - status.interrupt_enable_vblank = 0; -} - -CPU::CPU() - : trace(false) - , wram(nullptr) - , hram(nullptr) -{ - initialize_opcode_table(); -} - -CPU::~CPU() -{ - SNES::interface()->freeSharedMemory(wram); - SNES::interface()->freeSharedMemory(hram); -} - -void CPU::initialize() -{ - wram = (uint8*)SNES::interface()->allocSharedMemory("SGB_WRAM", 32768); - hram = (uint8*)SNES::interface()->allocSharedMemory("SGB_HRAM", 8192); -} - -} //namespace GameBoy diff --git a/waterbox/libsnes/bsnes/gameboy/cpu/cpu.hpp b/waterbox/libsnes/bsnes/gameboy/cpu/cpu.hpp deleted file mode 100644 index c16ac493f9..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cpu/cpu.hpp +++ /dev/null @@ -1,106 +0,0 @@ -struct CPU : Processor, MMIO { - #include "core/core.hpp" - #include "mmio/mmio.hpp" - #include "timing/timing.hpp" - - bool trace; - - enum class Interrupt : unsigned { - Vblank, - Stat, - Timer, - Serial, - Joypad, - }; - - struct Status { - unsigned clock; - bool halt; - bool stop; - bool ei; - bool ime; - - //$ff00 JOYP - bool p15; - bool p14; - uint8 joyp; - uint8 mlt_req; - - //$ff01 SB - uint8 serial_data; - unsigned serial_bits; - - //$ff02 SC - bool serial_transfer; - bool serial_clock; - - //$ff04 DIV - uint8 div; - - //$ff05 TIMA - uint8 tima; - - //$ff06 TMA - uint8 tma; - - //$ff07 TAC - bool timer_enable; - unsigned timer_clock; - - //$ff0f IF - bool interrupt_request_joypad; - bool interrupt_request_serial; - bool interrupt_request_timer; - bool interrupt_request_stat; - bool interrupt_request_vblank; - - //$ff4d KEY1 - bool speed_double; - bool speed_switch; - - //$ff51,$ff52 HDMA1,HDMA2 - uint16 dma_source; - - //$ff53,$ff54 HDMA3,HDMA4 - uint16 dma_target; - - //$ff55 HDMA5 - bool dma_mode; - uint16 dma_length; - - //$ff6c ??? - uint8 ff6c; - - //$ff70 SVBK - uint3 wram_bank; - - //$ff72-$ff75 ??? - uint8 ff72; - uint8 ff73; - uint8 ff74; - uint8 ff75; - - //$ffff IE - bool interrupt_enable_joypad; - bool interrupt_enable_serial; - bool interrupt_enable_timer; - bool interrupt_enable_stat; - bool interrupt_enable_vblank; - } status; - - uint8* wram; //[32768]; //GB=8192, GBC=32768 - uint8* hram; //[128]; - - static void Main(); - void main(); - void interrupt_raise(Interrupt id); - void interrupt_test(); - void interrupt_exec(uint16 pc); - void power(); - - void initialize(); - CPU(); - ~CPU(); -}; - -extern CPU cpu; diff --git a/waterbox/libsnes/bsnes/gameboy/cpu/mmio/mmio.cpp b/waterbox/libsnes/bsnes/gameboy/cpu/mmio/mmio.cpp deleted file mode 100644 index d66c9164aa..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cpu/mmio/mmio.cpp +++ /dev/null @@ -1,278 +0,0 @@ -#ifdef CPU_CPP - -unsigned CPU::wram_addr(uint16 addr) const { - addr &= 0x1fff; - if(addr < 0x1000) return addr; - auto bank = status.wram_bank + (status.wram_bank == 0); - return (bank * 0x1000) + (addr & 0x0fff); -} - -void CPU::mmio_joyp_poll() { - unsigned button = 0, dpad = 0; - - button |= interface->inputPoll((unsigned)Input::Start) << 3; - button |= interface->inputPoll((unsigned)Input::Select) << 2; - button |= interface->inputPoll((unsigned)Input::B) << 1; - button |= interface->inputPoll((unsigned)Input::A) << 0; - - dpad |= interface->inputPoll((unsigned)Input::Down) << 3; - dpad |= interface->inputPoll((unsigned)Input::Up) << 2; - dpad |= interface->inputPoll((unsigned)Input::Left) << 1; - dpad |= interface->inputPoll((unsigned)Input::Right) << 0; - - status.joyp = 0x0f; - if(status.p15 == 1 && status.p14 == 1) status.joyp -= status.mlt_req; - if(status.p15 == 0) status.joyp &= button ^ 0x0f; - if(status.p14 == 0) status.joyp &= dpad ^ 0x0f; - if(status.joyp != 0x0f) interrupt_raise(Interrupt::Joypad); -} - -uint8 CPU::mmio_read(uint16 addr) { - if(addr >= 0xc000 && addr <= 0xfdff) { - unsigned mapped_addr = wram_addr(addr); - cdlInfo.set(eCDLog_AddrType_SGB_WRAM, mapped_addr); - return wram[mapped_addr]; - } - if(addr >= 0xff80 && addr <= 0xfffe) { - cdlInfo.set(eCDLog_AddrType_SGB_HRAM, addr & 0x7f); - return hram[addr & 0x7f]; - } - - if(addr == 0xff00) { //JOYP - return (status.p15 << 5) - | (status.p14 << 4) - | (status.joyp << 0); - } - - if(addr == 0xff01) { //SB - return 0xff; - } - - if(addr == 0xff02) { //SC - return (status.serial_transfer << 7) - | (status.serial_clock << 0); - } - - if(addr == 0xff04) { //DIV - return status.div; - } - - if(addr == 0xff05) { //TIMA - return status.tima; - } - - if(addr == 0xff06) { //TMA - return status.tma; - } - - if(addr == 0xff07) { //TAC - return (status.timer_enable << 2) - | (status.timer_clock << 0); - } - - if(addr == 0xff0f) { //IF - return (status.interrupt_request_joypad << 4) - | (status.interrupt_request_serial << 3) - | (status.interrupt_request_timer << 2) - | (status.interrupt_request_stat << 1) - | (status.interrupt_request_vblank << 0); - } - - if(addr == 0xff4d) { //KEY1 - return (status.speed_double << 7); - } - - if(addr == 0xff55) { //HDMA5 - return (status.dma_length / 16) - 1; - } - - if(addr == 0xff56) { //RP - return 0x02; - } - - if(addr == 0xff6c) { //??? - return 0xfe | status.ff6c; - } - - if(addr == 0xff70) { //SVBK - return status.wram_bank; - } - - if(addr == 0xff72) { //??? - return status.ff72; - } - - if(addr == 0xff73) { //??? - return status.ff73; - } - - if(addr == 0xff74) { //??? - return status.ff74; - } - - if(addr == 0xff75) { //??? - return 0x8f | status.ff75; - } - - if(addr == 0xff76) { //??? - return 0x00; - } - - if(addr == 0xff77) { //??? - return 0x00; - } - - if(addr == 0xffff) { //IE - return (status.interrupt_enable_joypad << 4) - | (status.interrupt_enable_serial << 3) - | (status.interrupt_enable_timer << 2) - | (status.interrupt_enable_stat << 1) - | (status.interrupt_enable_vblank << 0); - } - - return 0x00; -} - -void CPU::mmio_write(uint16 addr, uint8 data) { - if(addr >= 0xc000 && addr <= 0xfdff) { wram[wram_addr(addr)] = data; return; } - if(addr >= 0xff80 && addr <= 0xfffe) { hram[addr & 0x7f] = data; return; } - - if(addr == 0xff00) { //JOYP - status.p15 = data & 0x20; - status.p14 = data & 0x10; - interface->joypWrite(status.p15, status.p14); - mmio_joyp_poll(); - return; - } - - if(addr == 0xff01) { //SB - status.serial_data = data; - return; - } - - if(addr == 0xff02) { //SC - status.serial_transfer = data & 0x80; - status.serial_clock = data & 0x01; - if(status.serial_transfer) status.serial_bits = 8; - return; - } - - if(addr == 0xff04) { //DIV - status.div = 0; - return; - } - - if(addr == 0xff05) { //TIMA - status.tima = data; - return; - } - - if(addr == 0xff06) { //TMA - status.tma = data; - return; - } - - if(addr == 0xff07) { //TAC - status.timer_enable = data & 0x04; - status.timer_clock = data & 0x03; - return; - } - - if(addr == 0xff0f) { //IF - status.interrupt_request_joypad = data & 0x10; - status.interrupt_request_serial = data & 0x08; - status.interrupt_request_timer = data & 0x04; - status.interrupt_request_stat = data & 0x02; - status.interrupt_request_vblank = data & 0x01; - return; - } - - if(addr == 0xff46) { //DMA - for(unsigned n = 0x00; n <= 0x9f; n++) { - bus.write(0xfe00 + n, bus.read((data << 8) + n)); - add_clocks(4); - } - return; - } - - if(addr == 0xff4d) { //KEY1 - status.speed_switch = data & 0x01; - return; - } - - if(addr == 0xff51) { //HDMA1 - status.dma_source = (status.dma_source & 0x00ff) | (data << 8); - return; - } - - if(addr == 0xff52) { //HDMA2 - status.dma_source = (status.dma_source & 0xff00) | (data << 0); - return; - } - - if(addr == 0xff53) { //HDMA3 - status.dma_target = (status.dma_target & 0x00ff) | (data << 8); - return; - } - - if(addr == 0xff54) { //HDMA4 - status.dma_target = (status.dma_target & 0xff00) | (data << 0); - return; - } - - if(addr == 0xff55) { //HDMA5 - status.dma_mode = data & 0x80; - status.dma_length = ((data & 0x7f) + 1) * 16; - - if(status.dma_mode == 0) do { - bus.write(status.dma_target++, bus.read(status.dma_source++)); - add_clocks(4 << status.speed_double); - } while(--status.dma_length); - return; - } - - if(addr == 0xff56) { //RP - return; - } - - if(addr == 0xff6c) { //??? - status.ff6c = data & 0x01; - return; - } - - if(addr == 0xff72) { //??? - status.ff72 = data; - return; - } - - if(addr == 0xff73) { //??? - status.ff73 = data; - return; - } - - if(addr == 0xff74) { //??? - status.ff74 = data; - return; - } - - if(addr == 0xff75) { //??? - status.ff75 = data & 0x70; - return; - } - - if(addr == 0xff70) { //SVBK - status.wram_bank = data & 0x07; - return; - } - - if(addr == 0xffff) { //IE - status.interrupt_enable_joypad = data & 0x10; - status.interrupt_enable_serial = data & 0x08; - status.interrupt_enable_timer = data & 0x04; - status.interrupt_enable_stat = data & 0x02; - status.interrupt_enable_vblank = data & 0x01; - return; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/cpu/mmio/mmio.hpp b/waterbox/libsnes/bsnes/gameboy/cpu/mmio/mmio.hpp deleted file mode 100644 index 14408995f5..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cpu/mmio/mmio.hpp +++ /dev/null @@ -1,4 +0,0 @@ -unsigned wram_addr(uint16 addr) const; -void mmio_joyp_poll(); -uint8 mmio_read(uint16 addr); -void mmio_write(uint16 addr, uint8 data); diff --git a/waterbox/libsnes/bsnes/gameboy/cpu/timing/opcode.cpp b/waterbox/libsnes/bsnes/gameboy/cpu/timing/opcode.cpp deleted file mode 100644 index 5774670b4b..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cpu/timing/opcode.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifdef CPU_CPP - -void CPU::op_io() { - cycle_edge(); - add_clocks(4); -} - -uint8 CPU::op_read(uint16 addr) { - cycle_edge(); - uint8 r = bus.read(addr); - add_clocks(4); - return r; -} - -void CPU::op_write(uint16 addr, uint8 data) { - cycle_edge(); - bus.write(addr, data); - add_clocks(4); -} - -void CPU::cycle_edge() { - if(status.ei) { - status.ei = false; - status.ime = 1; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/cpu/timing/timing.cpp b/waterbox/libsnes/bsnes/gameboy/cpu/timing/timing.cpp deleted file mode 100644 index 2fcec3d1e4..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cpu/timing/timing.cpp +++ /dev/null @@ -1,96 +0,0 @@ -//70224 clocks/frame -// 456 clocks/scanline -// 154 scanlines/frame - -#ifdef CPU_CPP - -#include "opcode.cpp" - -void CPU::add_clocks(unsigned clocks) { - system.clocks_executed += clocks; - - auto flags = cdlInfo.currFlags; - - if(system.sgb()) scheduler.exit(Scheduler::ExitReason::StepEvent); - cdlInfo.currFlags = flags; - - status.clock += clocks; - if(status.clock >= 4 * 1024 * 1024) { - status.clock -= 4 * 1024 * 1024; - cartridge.mbc3.second(); - } - - //4MHz / N(hz) - 1 = mask - if((status.clock & 15) == 0) timer_262144hz(); - if((status.clock & 63) == 0) timer_65536hz(); - if((status.clock & 255) == 0) timer_16384hz(); - if((status.clock & 511) == 0) timer_8192hz(); - if((status.clock & 1023) == 0) timer_4096hz(); - - lcd.clock -= clocks * lcd.frequency; - if(lcd.clock <= 0) co_switch(scheduler.active_thread = lcd.thread); - cdlInfo.currFlags = flags; - - apu.clock -= clocks * apu.frequency; - if(apu.clock <= 0) co_switch(scheduler.active_thread = apu.thread); - cdlInfo.currFlags = flags; -} - -void CPU::timer_262144hz() { - if(status.timer_enable && status.timer_clock == 1) { - if(++status.tima == 0) { - status.tima = status.tma; - interrupt_raise(Interrupt::Timer); - } - } -} - -void CPU::timer_65536hz() { - if(status.timer_enable && status.timer_clock == 2) { - if(++status.tima == 0) { - status.tima = status.tma; - interrupt_raise(Interrupt::Timer); - } - } -} - -void CPU::timer_16384hz() { - if(status.timer_enable && status.timer_clock == 3) { - if(++status.tima == 0) { - status.tima = status.tma; - interrupt_raise(Interrupt::Timer); - } - } - - status.div++; -} - -void CPU::timer_8192hz() { - if(status.serial_transfer && status.serial_clock) { - if(--status.serial_bits == 0) { - status.serial_transfer = 0; - interrupt_raise(Interrupt::Serial); - } - } -} - -void CPU::timer_4096hz() { - if(status.timer_enable && status.timer_clock == 0) { - if(++status.tima == 0) { - status.tima = status.tma; - interrupt_raise(Interrupt::Timer); - } - } -} - -void CPU::hblank() { - if(status.dma_mode == 1 && status.dma_length) { - for(unsigned n = 0; n < 16; n++) { - bus.write(status.dma_target++, bus.read(status.dma_source++)); - add_clocks(4); - } - status.dma_length -= 16; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/cpu/timing/timing.hpp b/waterbox/libsnes/bsnes/gameboy/cpu/timing/timing.hpp deleted file mode 100644 index 6c16c47e3f..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/cpu/timing/timing.hpp +++ /dev/null @@ -1,13 +0,0 @@ -void add_clocks(unsigned clocks); -void timer_262144hz(); -void timer_65536hz(); -void timer_16384hz(); -void timer_8192hz(); -void timer_4096hz(); -void hblank(); - -//opcode.cpp -void op_io(); -uint8 op_read(uint16 addr); -void op_write(uint16 addr, uint8 data); -void cycle_edge(); diff --git a/waterbox/libsnes/bsnes/gameboy/gameboy.hpp b/waterbox/libsnes/bsnes/gameboy/gameboy.hpp deleted file mode 100644 index e7f93281aa..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/gameboy.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef GAMEBOY_HPP -#define GAMEBOY_HPP - -#include - -/* - bgameboy - Game Boy, Super Game Boy, and Game Boy Color emulator - author: byuu - license: GPLv3 - project started: 2010-12-27 -*/ - -#include -#include - -namespace GameBoy { - struct Processor { - cothread_t thread; - unsigned frequency; - int64 clock; - - inline void create(void (*entrypoint)(), unsigned frequency) { - if(thread) co_delete(thread); - thread = co_create(65536 * sizeof(void*), entrypoint); - this->frequency = frequency; - clock = 0; - } - - inline Processor() : thread(nullptr) { - } - - inline ~Processor() { - if(thread) co_delete(thread); - } - }; - - #include - #include - #include - #include - #include - #include - #include - #include -}; - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/interface/interface.cpp b/waterbox/libsnes/bsnes/gameboy/interface/interface.cpp deleted file mode 100644 index 0a6d5f2a2d..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/interface/interface.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include - -namespace GameBoy { - -Interface *interface = nullptr; - -void Interface::lcdScanline() { -} - -void Interface::joypWrite(bool p15, bool p14) { -} - -void Interface::videoRefresh(const uint16_t *data) { -} - -void Interface::audioSample(int16_t center, int16_t left, int16_t right) { -} - -bool Interface::inputPoll(unsigned id) { - return false; -} - -void Interface::message(const string &text) { - print(text, "\n"); -} - -} diff --git a/waterbox/libsnes/bsnes/gameboy/interface/interface.hpp b/waterbox/libsnes/bsnes/gameboy/interface/interface.hpp deleted file mode 100644 index 80a0a9ab69..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/interface/interface.hpp +++ /dev/null @@ -1,15 +0,0 @@ -struct Interface { - virtual void lcdScanline(); - virtual void joypWrite(bool p15, bool p14); - - virtual void videoRefresh(const uint16_t *data); - virtual void audioSample(int16_t center, int16_t left, int16_t right); - virtual bool inputPoll(unsigned id); - - virtual void message(const string &text); - - virtual void* allocSharedMemory(const char* memtype, size_t amt, int initialByte = -1) = 0; - virtual void freeSharedMemory(void* ptr) = 0; -}; - -extern Interface *interface; diff --git a/waterbox/libsnes/bsnes/gameboy/lcd/cgb.cpp b/waterbox/libsnes/bsnes/gameboy/lcd/cgb.cpp deleted file mode 100644 index 31892ca343..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/lcd/cgb.cpp +++ /dev/null @@ -1,185 +0,0 @@ -#ifdef LCD_CPP - -void LCD::cgb_render() { - for(unsigned n = 0; n < 160; n++) { - line[n] = 0x7fff; - origin[n] = Origin::None; - } - - if(status.display_enable) { - cgb_render_bg(); - if(status.window_display_enable) cgb_render_window(); - if(status.ob_enable) cgb_render_ob(); - } - - uint16 *output = screen + status.ly * 160; - for(unsigned n = 0; n < 160; n++) output[n] = line[n]; - interface->lcdScanline(); -} - -//Attributes: -//0x80: 0 = OAM priority, 1 = BG priority -//0x40: vertical flip -//0x20: horizontal flip -//0x08: VRAM bank# -//0x07: palette# -void LCD::cgb_read_tile(bool select, unsigned x, unsigned y, unsigned &tile, unsigned &attr, unsigned &data) { - unsigned tmaddr = 0x1800 + (select << 10); - tmaddr += (((y >> 3) << 5) + (x >> 3)) & 0x03ff; - - tile = vram[0x0000 + tmaddr]; - attr = vram[0x2000 + tmaddr]; - - unsigned tdaddr = attr & 0x08 ? 0x2000 : 0x0000; - if(status.bg_tiledata_select == 0) { - tdaddr += 0x1000 + ((int8)tile << 4); - } else { - tdaddr += 0x0000 + (tile << 4); - } - - y &= 7; - if(attr & 0x40) y ^= 7; - tdaddr += y << 1; - - data = vram[tdaddr++] << 0; - data |= vram[tdaddr++] << 8; - if(attr & 0x20) data = hflip(data); -} - -void LCD::cgb_render_bg() { - unsigned iy = (status.ly + status.scy) & 255; - unsigned ix = status.scx, tx = ix & 7; - - unsigned tile, attr, data; - cgb_read_tile(status.bg_tilemap_select, ix, iy, tile, attr, data); - - for(unsigned ox = 0; ox < 160; ox++) { - unsigned index = ((data & (0x0080 >> tx)) ? 1 : 0) - | ((data & (0x8000 >> tx)) ? 2 : 0); - unsigned palette_index = ((attr & 0x07) << 3) + (index << 1); - unsigned palette = 0; - palette |= bgpd[palette_index++] << 0; - palette |= bgpd[palette_index++] << 8; - palette &= 0x7fff; - - line[ox] = palette; - origin[ox] = (attr & 0x80 ? Origin::BGP : Origin::BG); - - ix = (ix + 1) & 255; - tx = (tx + 1) & 7; - if(tx == 0) cgb_read_tile(status.bg_tilemap_select, ix, iy, tile, attr, data); - } -} - -void LCD::cgb_render_window() { - if(status.ly - status.wy >= 144u) return; - if(status.wx >= 167u) return; - unsigned iy = status.wyc++; - unsigned ix = (7 - status.wx) & 255, tx = ix & 7; - - unsigned tile, attr, data; - cgb_read_tile(status.window_tilemap_select, ix, iy, tile, attr, data); - - for(unsigned ox = 0; ox < 160; ox++) { - unsigned index = ((data & (0x0080 >> tx)) ? 1 : 0) - | ((data & (0x8000 >> tx)) ? 2 : 0); - unsigned palette_index = ((attr & 0x07) << 3) + (index << 1); - unsigned palette = 0; - palette |= bgpd[palette_index++] << 0; - palette |= bgpd[palette_index++] << 8; - palette &= 0x7fff; - - if(ox - (status.wx - 7) < 160u) { - line[ox] = palette; - origin[ox] = (attr & 0x80 ? Origin::BGP : Origin::BG); - } - - ix = (ix + 1) & 255; - tx = (tx + 1) & 7; - if(tx == 0) cgb_read_tile(status.window_tilemap_select, ix, iy, tile, attr, data); - } -} - -//Attributes: -//0x80: 0 = OBJ above BG, 1 = BG above OBJ -//0x40: vertical flip -//0x20: horizontal flip -//0x08: VRAM bank# -//0x07: palette# -void LCD::cgb_render_ob() { - const unsigned Height = (status.ob_size == 0 ? 8 : 16); - unsigned sprite[10], sprites = 0; - - //find first ten sprites on this scanline - for(unsigned s = 0; s < 40; s++) { - unsigned sy = oam[(s << 2) + 0] - 16; - unsigned sx = oam[(s << 2) + 1] - 8; - - sy = status.ly - sy; - if(sy >= Height) continue; - - sprite[sprites++] = s; - if(sprites == 10) break; - } - - //sort by X-coordinate, when equal, lower address comes first - for(unsigned x = 0; x < sprites; x++) { - for(unsigned y = x + 1; y < sprites; y++) { - signed sx = oam[(sprite[x] << 2) + 1] - 8; - signed sy = oam[(sprite[y] << 2) + 1] - 8; - if(sy < sx) { - sprite[x] ^= sprite[y]; - sprite[y] ^= sprite[x]; - sprite[x] ^= sprite[y]; - } - } - } - - //render backwards, so that first sprite has highest priority - for(signed s = sprites - 1; s >= 0; s--) { - unsigned n = sprite[s] << 2; - unsigned sy = oam[n + 0] - 16; - unsigned sx = oam[n + 1] - 8; - unsigned tile = oam[n + 2] & ~status.ob_size; - unsigned attr = oam[n + 3]; - - sy = status.ly - sy; - if(sy >= Height) continue; - if(attr & 0x40) sy ^= (Height - 1); - - unsigned tdaddr = (attr & 0x08 ? 0x2000 : 0x0000) + (tile << 4) + (sy << 1), data = 0; - data |= vram[tdaddr++] << 0; - data |= vram[tdaddr++] << 8; - if(attr & 0x20) data = hflip(data); - - for(unsigned tx = 0; tx < 8; tx++) { - unsigned index = ((data & (0x0080 >> tx)) ? 1 : 0) - | ((data & (0x8000 >> tx)) ? 2 : 0); - if(index == 0) continue; - - unsigned palette_index = ((attr & 0x07) << 3) + (index << 1); - unsigned palette = 0; - palette |= obpd[palette_index++] << 0; - palette |= obpd[palette_index++] << 8; - palette &= 0x7fff; - - unsigned ox = sx + tx; - - if(ox < 160) { - //When LCDC.D0 (BG enable) is off, OB is always rendered above BG+Window - if(status.bg_enable) { - if(origin[ox] == Origin::BGP) continue; - if(attr & 0x80) { - if(origin[ox] == Origin::BG || origin[ox] == Origin::BGP) { - if(line[ox] > 0) continue; - } - } - } - line[ox] = palette; - origin[ox] = Origin::OB; - } - } - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/lcd/dmg.cpp b/waterbox/libsnes/bsnes/gameboy/lcd/dmg.cpp deleted file mode 100644 index dae518af4d..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/lcd/dmg.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#ifdef LCD_CPP - -void LCD::dmg_render() { - for(unsigned n = 0; n < 160; n++) { - line[n] = 0x00; - origin[n] = Origin::None; - } - - if(status.display_enable) { - if(status.bg_enable) dmg_render_bg(); - if(status.window_display_enable) dmg_render_window(); - if(status.ob_enable) dmg_render_ob(); - } - - uint16 *output = screen + status.ly * 160; - for(unsigned n = 0; n < 160; n++) output[n] = line[n]; - interface->lcdScanline(); -} - -uint16 LCD::dmg_read_tile(bool select, unsigned x, unsigned y) { - unsigned tmaddr = 0x1800 + (select << 10), tdaddr; - tmaddr += (((y >> 3) << 5) + (x >> 3)) & 0x03ff; - if(status.bg_tiledata_select == 0) { - tdaddr = 0x1000 + ((int8)vram[tmaddr] << 4); - } else { - tdaddr = 0x0000 + (vram[tmaddr] << 4); - } - tdaddr += (y & 7) << 1; - return (vram[tdaddr + 0] << 0) | (vram[tdaddr + 1] << 8); -} - -void LCD::dmg_render_bg() { - unsigned iy = (status.ly + status.scy) & 255; - unsigned ix = status.scx, tx = ix & 7; - unsigned data = dmg_read_tile(status.bg_tilemap_select, ix, iy); - - for(unsigned ox = 0; ox < 160; ox++) { - uint8 palette = ((data & (0x0080 >> tx)) ? 1 : 0) - | ((data & (0x8000 >> tx)) ? 2 : 0); - - line[ox] = bgp[palette]; - origin[ox] = Origin::BG; - - ix = (ix + 1) & 255; - tx = (tx + 1) & 7; - - if(tx == 0) data = dmg_read_tile(status.bg_tilemap_select, ix, iy); - } -} - -void LCD::dmg_render_window() { - if(status.ly - status.wy >= 144u) return; - if(status.wx >= 167u) return; - unsigned iy = status.wyc++; - unsigned ix = (7 - status.wx) & 255, tx = ix & 7; - unsigned data = dmg_read_tile(status.window_tilemap_select, ix, iy); - - for(unsigned ox = 0; ox < 160; ox++) { - uint8 palette = ((data & (0x0080 >> tx)) ? 1 : 0) - | ((data & (0x8000 >> tx)) ? 2 : 0); - if(ox - (status.wx - 7) < 160u) { - line[ox] = bgp[palette]; - origin[ox] = Origin::BG; - } - - ix = (ix + 1) & 255; - tx = (tx + 1) & 7; - - if(tx == 0) data = dmg_read_tile(status.window_tilemap_select, ix, iy); - } -} - -//Attributes: -//0x80: 0 = OBJ above BG, 1 = BG above OBJ -//0x40: vertical flip -//0x20: horizontal flip -//0x10: palette# -void LCD::dmg_render_ob() { - const unsigned Height = (status.ob_size == 0 ? 8 : 16); - unsigned sprite[10], sprites = 0; - - //find first ten sprites on this scanline - for(unsigned s = 0; s < 40; s++) { - unsigned sy = oam[(s << 2) + 0] - 16; - unsigned sx = oam[(s << 2) + 1] - 8; - - sy = status.ly - sy; - if(sy >= Height) continue; - - sprite[sprites++] = s; - if(sprites == 10) break; - } - - //sort by X-coordinate, when equal, lower address comes first - for(unsigned x = 0; x < sprites; x++) { - for(unsigned y = x + 1; y < sprites; y++) { - signed sx = oam[(sprite[x] << 2) + 1] - 8; - signed sy = oam[(sprite[y] << 2) + 1] - 8; - if(sy < sx) { - sprite[x] ^= sprite[y]; - sprite[y] ^= sprite[x]; - sprite[x] ^= sprite[y]; - } - } - } - - //render backwards, so that first sprite has highest priority - for(signed s = sprites - 1; s >= 0; s--) { - unsigned n = sprite[s] << 2; - unsigned sy = oam[n + 0] - 16; - unsigned sx = oam[n + 1] - 8; - unsigned tile = oam[n + 2] & ~status.ob_size; - unsigned attr = oam[n + 3]; - - sy = status.ly - sy; - if(sy >= Height) continue; - if(attr & 0x40) sy ^= (Height - 1); - - unsigned tdaddr = (tile << 4) + (sy << 1), data = 0; - data |= vram[tdaddr++] << 0; - data |= vram[tdaddr++] << 8; - if(attr & 0x20) data = hflip(data); - - for(unsigned tx = 0; tx < 8; tx++) { - uint8 palette = ((data & (0x0080 >> tx)) ? 1 : 0) - | ((data & (0x8000 >> tx)) ? 2 : 0); - if(palette == 0) continue; - - palette = obp[(bool)(attr & 0x10)][palette]; - unsigned ox = sx + tx; - - if(ox < 160) { - if(attr & 0x80) { - if(origin[ox] == Origin::BG) { - if(line[ox] > 0) continue; - } - } - line[ox] = palette; - origin[ox] = Origin::OB; - } - } - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/lcd/lcd.cpp b/waterbox/libsnes/bsnes/gameboy/lcd/lcd.cpp deleted file mode 100644 index 595c46e2e8..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/lcd/lcd.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include - -//LY = 0-153 -//Raster = 0-143 -//Vblank = 144-153 - -//LX = 0-455 - -#define LCD_CPP -namespace GameBoy { - -#include "dmg.cpp" -#include "cgb.cpp" -#include "mmio/mmio.cpp" -LCD lcd; - -void LCD::Main() { - lcd.main(); -} - -void LCD::main() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - add_clocks(4); - status.lx += 4; - if(status.lx >= 456) scanline(); - - if(status.display_enable && status.lx == 0) { - if(status.interrupt_oam) cpu.interrupt_raise(CPU::Interrupt::Stat); - } - - if(status.display_enable && status.lx == 252) { - if(status.interrupt_hblank) cpu.interrupt_raise(CPU::Interrupt::Stat); - cpu.hblank(); - } - } -} - -void LCD::add_clocks(unsigned clocks) { - clock += clocks * cpu.frequency; - if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) { - co_switch(scheduler.active_thread = cpu.thread); - } -} - -void LCD::scanline() { - status.lx -= 456; - if(++status.ly == 154) frame(); - - if(status.display_enable && status.interrupt_lyc == true) { - if(status.ly == status.lyc) cpu.interrupt_raise(CPU::Interrupt::Stat); - } - - if(status.ly < 144) { - system.cgb() == false ? dmg_render() : cgb_render(); - } - - if(status.display_enable && status.ly == 144) { - cpu.interrupt_raise(CPU::Interrupt::Vblank); - if(status.interrupt_vblank) cpu.interrupt_raise(CPU::Interrupt::Stat); - } -} - -void LCD::frame() { - interface->videoRefresh(screen); - cpu.mmio_joyp_poll(); - - status.ly = 0; - status.wyc = 0; - scheduler.exit(Scheduler::ExitReason::FrameEvent); -} - -unsigned LCD::hflip(unsigned data) const { - return ((data & 0x8080) >> 7) | ((data & 0x4040) >> 5) - | ((data & 0x2020) >> 3) | ((data & 0x1010) >> 1) - | ((data & 0x0808) << 1) | ((data & 0x0404) << 3) - | ((data & 0x0202) << 5) | ((data & 0x0101) << 7); -} - -void LCD::power() { - create(Main, 4 * 1024 * 1024); - - for(unsigned n = 0x8000; n <= 0x9fff; n++) bus.mmio[n] = this; //VRAM - for(unsigned n = 0xfe00; n <= 0xfe9f; n++) bus.mmio[n] = this; //OAM - - bus.mmio[0xff40] = this; //LCDC - bus.mmio[0xff41] = this; //STAT - bus.mmio[0xff42] = this; //SCY - bus.mmio[0xff43] = this; //SCX - bus.mmio[0xff44] = this; //LY - bus.mmio[0xff45] = this; //LYC - bus.mmio[0xff47] = this; //BGP - bus.mmio[0xff48] = this; //OBP0 - bus.mmio[0xff49] = this; //OBP1 - bus.mmio[0xff4a] = this; //WY - bus.mmio[0xff4b] = this; //WX - - if(system.cgb()) { - bus.mmio[0xff4f] = this; //VBK - bus.mmio[0xff68] = this; //BGPI - bus.mmio[0xff69] = this; //BGPD - bus.mmio[0xff6a] = this; //OBPI - bus.mmio[0xff6b] = this; //OBPD - } - - for(auto &n : screen) n = 0x0000; - for(auto &n : line) n = 0x0000; - for(auto &n : origin) n = Origin::None; - - for(auto &n : vram) n = 0x00; - for(auto &n : oam) n = 0x00; - for(auto &n : bgp) n = 0x00; - for(auto &n : obp[0]) n = 0x00; - for(auto &n : obp[1]) n = 0x00; - for(auto &n : bgpd) n = 0x0000; - for(auto &n : obpd) n = 0x0000; - - status.lx = 0; - status.wyc = 0; - - status.display_enable = 0; - status.window_tilemap_select = 0; - status.window_display_enable = 0; - status.bg_tiledata_select = 0; - status.bg_tilemap_select = 0; - status.ob_size = 0; - status.ob_enable = 0; - status.bg_enable = 0; - - status.interrupt_lyc = 0; - status.interrupt_oam = 0; - status.interrupt_vblank = 0; - status.interrupt_hblank = 0; - - status.scy = 0; - status.scx = 0; - status.ly = 0; - status.lyc = 0; - status.wy = 0; - status.wx = 0; - - status.vram_bank = 0; - - status.bgpi_increment = 0; - status.bgpi = 0; - - status.obpi_increment = 0; - status.obpi = 0; -} - -LCD::LCD() { -} - -} diff --git a/waterbox/libsnes/bsnes/gameboy/lcd/lcd.hpp b/waterbox/libsnes/bsnes/gameboy/lcd/lcd.hpp deleted file mode 100644 index 4adec719cf..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/lcd/lcd.hpp +++ /dev/null @@ -1,93 +0,0 @@ -struct LCD : Processor, MMIO { - #include "mmio/mmio.hpp" - - struct Status { - unsigned lx; - unsigned wyc; - - //$ff40 LCDC - bool display_enable; - bool window_tilemap_select; - bool window_display_enable; - bool bg_tiledata_select; - bool bg_tilemap_select; - bool ob_size; - bool ob_enable; - bool bg_enable; - - //$ff41 STAT - bool interrupt_lyc; - bool interrupt_oam; - bool interrupt_vblank; - bool interrupt_hblank; - - //$ff42 SCY - uint8 scy; - - //$ff43 SCX - uint8 scx; - - //$ff44 LY - uint8 ly; - - //$ff45 LYC - uint8 lyc; - - //$ff4a WY - uint8 wy; - - //$ff4b WX - uint8 wx; - - //$ff4f VBK - bool vram_bank; - - //$ff68 BGPI - bool bgpi_increment; - uint6 bgpi; - - //$ff6a OBPI - bool obpi_increment; - uint8 obpi; - } status; - - uint16 screen[160 * 144]; - uint16 line[160]; - struct Origin { enum : unsigned { None, BG, BGP, OB }; }; - uint8 origin[160]; - - uint8 vram[16384]; //GB = 8192, GBC = 16384 - uint8 oam[160]; - uint8 bgp[4]; - uint8 obp[2][4]; - uint8 bgpd[64]; - uint8 obpd[64]; - - static void Main(); - void main(); - void add_clocks(unsigned clocks); - void scanline(); - void frame(); - - unsigned hflip(unsigned data) const; - - //dmg.cpp - void dmg_render(); - uint16 dmg_read_tile(bool select, unsigned x, unsigned y); - void dmg_render_bg(); - void dmg_render_window(); - void dmg_render_ob(); - - //cgb.cpp - void cgb_render(); - void cgb_read_tile(bool select, unsigned x, unsigned y, unsigned &tile, unsigned &attr, unsigned &data); - void cgb_render_bg(); - void cgb_render_window(); - void cgb_render_ob(); - - void power(); - - LCD(); -}; - -extern LCD lcd; diff --git a/waterbox/libsnes/bsnes/gameboy/lcd/mmio/mmio.cpp b/waterbox/libsnes/bsnes/gameboy/lcd/mmio/mmio.cpp deleted file mode 100644 index 5b20fe70ac..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/lcd/mmio/mmio.cpp +++ /dev/null @@ -1,203 +0,0 @@ -#ifdef LCD_CPP - -unsigned LCD::vram_addr(uint16 addr) const { - return (status.vram_bank * 0x2000) + (addr & 0x1fff); -} - -uint8 LCD::mmio_read(uint16 addr) { - if(addr >= 0x8000 && addr <= 0x9fff) return vram[vram_addr(addr)]; - if(addr >= 0xfe00 && addr <= 0xfe9f) return oam[addr & 0xff]; - - if(addr == 0xff40) { //LCDC - return (status.display_enable << 7) - | (status.window_tilemap_select << 6) - | (status.window_display_enable << 5) - | (status.bg_tiledata_select << 4) - | (status.bg_tilemap_select << 3) - | (status.ob_size << 2) - | (status.ob_enable << 1) - | (status.bg_enable << 0); - } - - if(addr == 0xff41) { //STAT - unsigned mode; - if(status.ly >= 144) mode = 1; //Vblank - else if(status.lx < 80) mode = 2; //OAM - else if(status.lx < 252) mode = 3; //LCD - else mode = 0; //Hblank - - return (status.interrupt_lyc << 6) - | (status.interrupt_oam << 5) - | (status.interrupt_vblank << 4) - | (status.interrupt_hblank << 3) - | ((status.ly == status.lyc) << 2) - | (mode << 0); - } - - if(addr == 0xff42) { //SCY - return status.scy; - } - - if(addr == 0xff43) { //SCX - return status.scx; - } - - if(addr == 0xff44) { //LY - return status.ly; - } - - if(addr == 0xff45) { //LYC - return status.lyc; - } - - if(addr == 0xff47) { //BGP - return (bgp[3] << 6) - | (bgp[2] << 4) - | (bgp[1] << 2) - | (bgp[0] << 0); - } - - if(addr == 0xff48) { //OBP0 - return (obp[0][3] << 6) - | (obp[0][2] << 4) - | (obp[0][1] << 2) - | (obp[0][0] << 0); - } - - if(addr == 0xff49) { //OBP1 - return (obp[1][3] << 6) - | (obp[1][2] << 4) - | (obp[1][1] << 2) - | (obp[1][0] << 0); - } - - if(addr == 0xff4a) { //WY - return status.wy; - } - - if(addr == 0xff4b) { //WX - return status.wx; - } - - if(addr == 0xff69) { //BGPD - return bgpd[status.bgpi]; - } - - if(addr == 0xff6b) { //OBPD - return obpd[status.obpi]; - } - - return 0x00; -} - -void LCD::mmio_write(uint16 addr, uint8 data) { - if(addr >= 0x8000 && addr <= 0x9fff) { vram[vram_addr(addr)] = data; return; } - if(addr >= 0xfe00 && addr <= 0xfe9f) { oam[addr & 0xff] = data; return; } - - if(addr == 0xff40) { //LCDC - if(status.display_enable == false && (data & 0x80)) { - status.lx = 0; //unverified behavior; fixes Super Mario Land 2 - Tree Zone - } - - status.display_enable = data & 0x80; - status.window_tilemap_select = data & 0x40; - status.window_display_enable = data & 0x20; - status.bg_tiledata_select = data & 0x10; - status.bg_tilemap_select = data & 0x08; - status.ob_size = data & 0x04; - status.ob_enable = data & 0x02; - status.bg_enable = data & 0x01; - return; - } - - if(addr == 0xff41) { //STAT - status.interrupt_lyc = data & 0x40; - status.interrupt_oam = data & 0x20; - status.interrupt_vblank = data & 0x10; - status.interrupt_hblank = data & 0x08; - return; - } - - if(addr == 0xff42) { //SCY - status.scy = data; - return; - } - - if(addr == 0xff43) { //SCX - status.scx = data; - return; - } - - if(addr == 0xff44) { //LY - status.ly = 0; - return; - } - - if(addr == 0xff45) { //LYC - status.lyc = data; - return; - } - - if(addr == 0xff47) { //BGP - bgp[3] = (data >> 6) & 3; - bgp[2] = (data >> 4) & 3; - bgp[1] = (data >> 2) & 3; - bgp[0] = (data >> 0) & 3; - return; - } - - if(addr == 0xff48) { //OBP0 - obp[0][3] = (data >> 6) & 3; - obp[0][2] = (data >> 4) & 3; - obp[0][1] = (data >> 2) & 3; - obp[0][0] = (data >> 0) & 3; - return; - } - - if(addr == 0xff49) { //OBP1 - obp[1][3] = (data >> 6) & 3; - obp[1][2] = (data >> 4) & 3; - obp[1][1] = (data >> 2) & 3; - obp[1][0] = (data >> 0) & 3; - return; - } - - if(addr == 0xff4a) { //WY - status.wy = data; - return; - } - - if(addr == 0xff4b) { //WX - status.wx = data; - return; - } - - if(addr == 0xff4f) { //VBK - status.vram_bank = data & 1; - return; - } - - if(addr == 0xff68) { //BGPI - status.bgpi_increment = data & 0x80; - status.bgpi = data & 0x3f; - return; - } - - if(addr == 0xff69) { //BGPD - bgpd[status.bgpi] = data; - if(status.bgpi_increment) status.bgpi++; - return; - } - - if(addr == 0xff6a) { //OBPI - status.obpi_increment = data & 0x80; - status.obpi = data & 0x3f; - } - - if(addr == 0xff6b) { //OBPD - obpd[status.obpi] = data; - if(status.obpi_increment) status.obpi++; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/lcd/mmio/mmio.hpp b/waterbox/libsnes/bsnes/gameboy/lcd/mmio/mmio.hpp deleted file mode 100644 index d02d75597b..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/lcd/mmio/mmio.hpp +++ /dev/null @@ -1,3 +0,0 @@ -unsigned vram_addr(uint16 addr) const; -uint8 mmio_read(uint16 addr); -void mmio_write(uint16 addr, uint8 data); diff --git a/waterbox/libsnes/bsnes/gameboy/memory/memory.cpp b/waterbox/libsnes/bsnes/gameboy/memory/memory.cpp deleted file mode 100644 index bb3bb3f970..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/memory/memory.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include - -#define MEMORY_CPP -namespace GameBoy { - -Unmapped unmapped; -Bus bus; - -uint8_t& Memory::operator[](unsigned addr) { - return data[addr]; -} - -void Memory::allocate(unsigned size_) { - free(); - size = size_; - data = new uint8_t[size](); -} - -void Memory::copy(const uint8_t *data_, unsigned size_) { - free(); - size = size_; - data = new uint8_t[size]; - memcpy(data, data_, size); -} - -void Memory::free() { - if(data) { - delete[] data; - data = 0; - } -} - -Memory::Memory() { - data = 0; - size = 0; -} - -Memory::~Memory() { - free(); -} - -// - -uint8 Bus::read(uint16 addr) { - uint8 data = mmio[addr]->mmio_read(addr); - return data; -} - -void Bus::write(uint16 addr, uint8 data) { - mmio[addr]->mmio_write(addr, data); -} - -void Bus::power() { - for(unsigned n = 0x0000; n <= 0xffff; n++) mmio[n] = &unmapped; -} - -} diff --git a/waterbox/libsnes/bsnes/gameboy/memory/memory.hpp b/waterbox/libsnes/bsnes/gameboy/memory/memory.hpp deleted file mode 100644 index 3dfb8df96b..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/memory/memory.hpp +++ /dev/null @@ -1,32 +0,0 @@ -struct Memory { - uint8_t *data; - unsigned size; - - uint8_t& operator[](unsigned addr); - void allocate(unsigned size); - void copy(const uint8_t *data, unsigned size); - void free(); - Memory(); - ~Memory(); -}; - -struct MMIO { - virtual uint8 mmio_read(uint16 addr) = 0; - virtual void mmio_write(uint16 addr, uint8 data) = 0; -}; - -struct Unmapped : MMIO { - uint8 mmio_read(uint16) { return 0x00; } - void mmio_write(uint16, uint8) {} -}; - -struct Bus { - MMIO *mmio[65536]; - uint8 read(uint16 addr); - void write(uint16 addr, uint8 data); - - void power(); -}; - -extern Unmapped unmapped; -extern Bus bus; diff --git a/waterbox/libsnes/bsnes/gameboy/scheduler/scheduler.cpp b/waterbox/libsnes/bsnes/gameboy/scheduler/scheduler.cpp deleted file mode 100644 index 14bd733142..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/scheduler/scheduler.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include - -#define SCHEDULER_CPP -namespace GameBoy { - -Scheduler scheduler; - -void Scheduler::enter() { - host_thread = co_active(); - co_switch(active_thread); -} - -void Scheduler::exit(ExitReason reason) { - exit_reason = reason; - active_thread = co_active(); - co_switch(host_thread); -} - -void Scheduler::swapto(Processor &p) { - active_thread = p.thread; - co_switch(active_thread); -} - -void Scheduler::init() { - host_thread = co_active(); - active_thread = cpu.thread; -} - -Scheduler::Scheduler() { - exit_reason = ExitReason::UnknownEvent; - host_thread = 0; - active_thread = 0; -} - -} diff --git a/waterbox/libsnes/bsnes/gameboy/scheduler/scheduler.hpp b/waterbox/libsnes/bsnes/gameboy/scheduler/scheduler.hpp deleted file mode 100644 index ccdb78ecfb..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/scheduler/scheduler.hpp +++ /dev/null @@ -1,17 +0,0 @@ -struct Scheduler : property { - enum class SynchronizeMode : unsigned { None, CPU, All } sync; - enum class ExitReason : unsigned { UnknownEvent, StepEvent, FrameEvent, SynchronizeEvent }; - readonly exit_reason; - - cothread_t host_thread; - cothread_t active_thread; - - void enter(); - void exit(ExitReason); - void swapto(Processor&); - - void init(); - Scheduler(); -}; - -extern Scheduler scheduler; diff --git a/waterbox/libsnes/bsnes/gameboy/system/bootrom-cgb.cpp b/waterbox/libsnes/bsnes/gameboy/system/bootrom-cgb.cpp deleted file mode 100644 index 290c0176e5..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/system/bootrom-cgb.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#ifdef SYSTEM_CPP - -//from FastCgbBoot (cgb_boot.rom.gz) -const uint8_t System::BootROM::cgb[2048] = { -0x01,0x00,0x00,0x11,0x08,0x00,0x21,0x7C,0x00,0x31,0xFE,0xFF,0x3E,0x39,0xE0,0xFA, -0x3E,0x01,0xE0,0xFB,0x3E,0x2E,0xE0,0xFC,0x3E,0x00,0xE0,0xFD,0x3E,0x00,0xE0,0x42, -0xE0,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x80,0xE0,0x26,0x3E, -0x00,0xE0,0x25,0x3E,0x77,0xE0,0x24,0x3E,0x80,0xE0,0x11,0x3E,0x13,0xE0,0x12,0x3E, -0x80,0xE0,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x3E,0x91,0xE0,0x40,0xF0,0x44,0xFE,0x90,0x20,0xFA,0xCD,0x00,0x02,0xF0,0x44,0xFE, -0x00,0x20,0xFA,0x3C,0xFE,0x10,0x20,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x3E,0xF3,0xE0,0x25,0x3E,0xF3,0xE0,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x3E,0x00,0xE0,0x70,0xAF,0x3E,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x50, -0xFA,0x43,0x01,0xEE,0x3F,0xE6,0xC4,0xCB,0x7F,0x28,0x05,0xD6,0x04,0xE0,0x4C,0xC9, -0x3E,0x80,0xE0,0x6A,0x3E,0xFF,0xE0,0x6B,0x3E,0x7F,0xE0,0x6B,0x3E,0x1F,0xE0,0x6B, -0x3E,0x42,0xE0,0x6B,0x3E,0xF2,0xE0,0x6B,0x3E,0x1C,0xE0,0x6B,0x3E,0x00,0xE0,0x6B, -0x3E,0x00,0xE0,0x6B,0x3E,0xFF,0xE0,0x6B,0x3E,0x7F,0xE0,0x6B,0x3E,0x1F,0xE0,0x6B, -0x3E,0x42,0xE0,0x6B,0x3E,0xF2,0xE0,0x6B,0x3E,0x1C,0xE0,0x6B,0x3E,0x00,0xE0,0x6B, -0x3E,0x00,0xE0,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x80,0xE0,0x68, -0x3E,0xFF,0xE0,0x69,0x3E,0x7F,0xE0,0x69,0x3E,0xEF,0xE0,0x69,0x3E,0x1B,0xE0,0x69, -0x3E,0x80,0xE0,0x69,0x3E,0x61,0xE0,0x69,0x3E,0x00,0xE0,0x69,0x3E,0x00,0xE0,0x69, -0xC6,0x04,0xE0,0x4C,0xC9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -}; - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/system/bootrom-dmg.cpp b/waterbox/libsnes/bsnes/gameboy/system/bootrom-dmg.cpp deleted file mode 100644 index 75c4b9e824..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/system/bootrom-dmg.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#ifdef SYSTEM_CPP - -//from FastDmgBoot (dmg_boot.rom.gz) -const uint8_t System::BootROM::dmg[256] = { -0x01,0x13,0x00,0x11,0xD8,0x00,0x21,0x4D,0x01,0x31,0xFE,0xFF,0x3E,0x39,0xE0,0xFA, -0x3E,0x01,0xE0,0xFB,0x3E,0x2E,0xE0,0xFC,0x3E,0x00,0xE0,0xFD,0x3E,0x00,0xE0,0x42, -0xE0,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x80,0xE0,0x26,0x3E, -0x00,0xE0,0x25,0x3E,0x77,0xE0,0x24,0x3E,0x80,0xE0,0x11,0x3E,0x13,0xE0,0x12,0x3E, -0x80,0xE0,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x3E,0x91,0xE0,0x40,0xF0,0x44,0xFE,0x98,0x20,0xFA,0xF0,0x44,0xFE,0x00,0x20,0xFA, -0x3C,0xFE,0x10,0x20,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x3E,0xF3,0xE0,0x25,0x3E,0xF3,0xE0,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x28,0x83,0x7C,0xE0,0x50, -}; - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/system/bootrom-sgb.cpp b/waterbox/libsnes/bsnes/gameboy/system/bootrom-sgb.cpp deleted file mode 100644 index 28844849c2..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/system/bootrom-sgb.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#ifdef SYSTEM_CPP - -//from https://github.com/LIJI32/SameBoy/tree/v0.14.3/BootROMs -const uint8_t System::BootROM::sgb[256] = { -0x31,0xFE,0xFF,0x21,0x00,0x80,0x22,0xCB,0x6C,0x28,0xFB,0x3E,0x80,0xE0,0x26,0xE0, -0x11,0x3E,0xF3,0xE0,0x12,0xE0,0x25,0x3E,0x77,0xE0,0x24,0x3E,0x00,0xE0,0x47,0x11, -0x04,0x01,0x21,0x10,0x80,0x1A,0x47,0xCD,0xC9,0x00,0xCD,0xC9,0x00,0x13,0x7B,0xEE, -0x34,0x20,0xF2,0x11,0xEA,0x00,0x0E,0x08,0x1A,0x13,0x22,0x23,0x0D,0x20,0xF9,0x3E, -0x19,0xEA,0x10,0x99,0x21,0x2F,0x99,0x0E,0x0C,0x3D,0x28,0x08,0x32,0x0D,0x20,0xF9, -0x2E,0x0F,0x18,0xF5,0x3E,0x91,0xE0,0x40,0x3E,0xF1,0xE0,0x80,0x21,0x04,0x01,0xAF, -0x4F,0xAF,0xE2,0x3E,0x30,0xE2,0xF0,0x80,0xCD,0xB7,0x00,0xE5,0x06,0x0E,0x16,0x00, -0xCD,0xAD,0x00,0x82,0x57,0x05,0x20,0xF8,0xCD,0xB7,0x00,0xE1,0x06,0x0E,0xCD,0xAD, -0x00,0xCD,0xB7,0x00,0x05,0x20,0xF7,0x3E,0x20,0xE2,0x3E,0x30,0xE2,0xF0,0x80,0xC6, -0x02,0xE0,0x80,0x3E,0x58,0xBD,0x20,0xC9,0x0E,0x13,0x3E,0xC1,0xE2,0x0C,0x3E,0x07, -0xE2,0x3E,0xFC,0xE0,0x47,0x3E,0x01,0x21,0x60,0xC0,0xC3,0xFE,0x00,0x3E,0x4F,0xBD, -0x38,0x02,0x2A,0xC9,0x23,0xAF,0xC9,0x5F,0x16,0x08,0x3E,0x10,0xCB,0x1B,0x38,0x01, -0x87,0xE2,0x3E,0x30,0xE2,0x15,0xC8,0x18,0xF1,0x3E,0x04,0x0E,0x00,0xCB,0x20,0xF5, -0xCB,0x11,0xF1,0xCB,0x11,0x3D,0x20,0xF5,0x79,0x22,0x23,0x22,0x23,0xC9,0xE5,0x21, -0x0F,0xFF,0xCB,0x86,0xCB,0x46,0x28,0xFC,0xE1,0xC9,0x3C,0x42,0xB9,0xA5,0xB9,0xA5, -0x42,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x50, -}; - -#endif diff --git a/waterbox/libsnes/bsnes/gameboy/system/system.cpp b/waterbox/libsnes/bsnes/gameboy/system/system.cpp deleted file mode 100644 index 37727b5778..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/system/system.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include - -#define SYSTEM_CPP -namespace GameBoy { - -#include "bootrom-dmg.cpp" -#include "bootrom-sgb.cpp" -#include "bootrom-cgb.cpp" -System system; - -void System::run() { - scheduler.sync = Scheduler::SynchronizeMode::None; - - scheduler.enter(); - if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) { - } -} - -void System::runtosave() { - scheduler.sync = Scheduler::SynchronizeMode::CPU; - runthreadtosave(); - - scheduler.active_thread = lcd.thread; - runthreadtosave(); -} - -void System::runthreadtosave() { - while(true) { - scheduler.enter(); - if(scheduler.exit_reason() == Scheduler::ExitReason::SynchronizeEvent) break; - if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) { - } - } -} - -void System::init() { - assert(interface != 0); -} - -void System::load(Revision revision) { - this->revision = revision; -} - -void System::power() { - bus.power(); - cartridge.power(); - cpu.power(); - apu.power(); - lcd.power(); - scheduler.init(); - - clocks_executed = 0; -} - -} diff --git a/waterbox/libsnes/bsnes/gameboy/system/system.hpp b/waterbox/libsnes/bsnes/gameboy/system/system.hpp deleted file mode 100644 index a3be91e8e0..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/system/system.hpp +++ /dev/null @@ -1,38 +0,0 @@ -class Interface; - -enum class Input : unsigned { - Up, Down, Left, Right, B, A, Select, Start, -}; - -struct System : property { - enum class Revision : unsigned { - GameBoy, - SuperGameBoy, - GameBoyColor, - }; - readonly revision; - inline bool dmg() const { return (Revision)revision == Revision::GameBoy; } - inline bool sgb() const { return (Revision)revision == Revision::SuperGameBoy; } - inline bool cgb() const { return (Revision)revision == Revision::GameBoyColor; } - - struct BootROM { - static const uint8 dmg[ 256]; - static const uint8 sgb[ 256]; - static const uint8 cgb[2048]; - } bootROM; - - void run(); - void runtosave(); - void runthreadtosave(); - - void init(); - void load(Revision); - void power(); - - unsigned clocks_executed; - -}; - -#include - -extern System system; diff --git a/waterbox/libsnes/bsnes/gameboy/video/video.cpp b/waterbox/libsnes/bsnes/gameboy/video/video.cpp deleted file mode 100644 index 3cbcd249a6..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/video/video.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include - -#define VIDEO_CPP -namespace GameBoy { - -Video video; - -unsigned Video::palette_dmg(unsigned color) const { - unsigned R = monochrome[color][0] * 1023.0; - unsigned G = monochrome[color][1] * 1023.0; - unsigned B = monochrome[color][2] * 1023.0; - - return (R << 20) + (G << 10) + (B << 0); -} - -unsigned Video::palette_sgb(unsigned color) const { - unsigned R = (3 - color) * 341; - unsigned G = (3 - color) * 341; - unsigned B = (3 - color) * 341; - - return (R << 20) + (G << 10) + (B << 0); -} - -unsigned Video::palette_cgb(unsigned color) const { - unsigned r = (color >> 0) & 31; - unsigned g = (color >> 5) & 31; - unsigned b = (color >> 10) & 31; - - unsigned R = (r * 26 + g * 4 + b * 2); - unsigned G = ( g * 24 + b * 8); - unsigned B = (r * 6 + g * 4 + b * 22); - - R = min(960, R); - G = min(960, G); - B = min(960, B); - - return (R << 20) + (G << 10) + (B << 0); -} - -void Video::generate(Format format) { - if(system.dmg()) for(unsigned n = 0; n < 4; n++) palette[n] = palette_dmg(n); - if(system.sgb()) for(unsigned n = 0; n < 4; n++) palette[n] = palette_sgb(n); - if(system.cgb()) for(unsigned n = 0; n < (1 << 15); n++) palette[n] = palette_cgb(n); - - if(format == Format::RGB24) { - for(unsigned n = 0; n < (1 << 15); n++) { - unsigned color = palette[n]; - palette[n] = ((color >> 6) & 0xff0000) + ((color >> 4) & 0x00ff00) + ((color >> 2) & 0x0000ff); - } - } - - if(format == Format::RGB16) { - for(unsigned n = 0; n < (1 << 15); n++) { - unsigned color = palette[n]; - palette[n] = ((color >> 14) & 0xf800) + ((color >> 9) & 0x07e0) + ((color >> 5) & 0x001f); - } - } - - if(format == Format::RGB15) { - for(unsigned n = 0; n < (1 << 15); n++) { - unsigned color = palette[n]; - palette[n] = ((color >> 15) & 0x7c00) + ((color >> 10) & 0x03e0) + ((color >> 5) & 0x001f); - } - } -} - -Video::Video() { - palette = new unsigned[1 << 15]; -} - -Video::~Video() { - delete[] palette; -} - -const double Video::monochrome[4][3] = { - { 0.605, 0.734, 0.059 }, - { 0.543, 0.672, 0.059 }, - { 0.188, 0.383, 0.188 }, - { 0.059, 0.219, 0.059 }, -}; - -} diff --git a/waterbox/libsnes/bsnes/gameboy/video/video.hpp b/waterbox/libsnes/bsnes/gameboy/video/video.hpp deleted file mode 100644 index 131b2868c2..0000000000 --- a/waterbox/libsnes/bsnes/gameboy/video/video.hpp +++ /dev/null @@ -1,17 +0,0 @@ -struct Video { - enum class Format : unsigned { RGB30, RGB24, RGB16, RGB15 }; - unsigned *palette; - - unsigned palette_dmg(unsigned color) const; - unsigned palette_sgb(unsigned color) const; - unsigned palette_cgb(unsigned color) const; - - void generate(Format format); - Video(); - ~Video(); - -private: - static const double monochrome[4][3]; -}; - -extern Video video; diff --git a/waterbox/libsnes/bsnes/nall/algorithm.hpp b/waterbox/libsnes/bsnes/nall/algorithm.hpp deleted file mode 100644 index 037f0bb7bb..0000000000 --- a/waterbox/libsnes/bsnes/nall/algorithm.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef NALL_ALGORITHM_HPP -#define NALL_ALGORITHM_HPP - -#undef min -#undef max - -namespace nall { - template T min(const T &t, const U &u) { - return t < u ? t : u; - } - - template T max(const T &t, const U &u) { - return t > u ? t : u; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/any.hpp b/waterbox/libsnes/bsnes/nall/any.hpp deleted file mode 100644 index fc577957f7..0000000000 --- a/waterbox/libsnes/bsnes/nall/any.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef NALL_ANY_HPP -#define NALL_ANY_HPP - -#include -#include - -namespace nall { - struct any { - bool empty() const { return container; } - const std::type_info& type() const { return container ? container->type() : typeid(void); } - - template any& operator=(const T& value_) { - typedef typename type_if< - std::is_array::value, - typename std::remove_extent::type>::type*, - T - >::type auto_t; - - if(type() == typeid(auto_t)) { - static_cast*>(container)->value = (auto_t)value_; - } else { - if(container) delete container; - container = new holder((auto_t)value_); - } - - return *this; - } - - any() : container(0) {} - template any(const T& value_) : container(0) { operator=(value_); } - - private: - struct placeholder { - virtual const std::type_info& type() const = 0; - } *container; - - template struct holder : placeholder { - T value; - const std::type_info& type() const { return typeid(T); } - holder(const T& value_) : value(value_) {} - }; - - template friend T any_cast(any&); - template friend T any_cast(const any&); - template friend T* any_cast(any*); - template friend const T* any_cast(const any*); - }; - - template T any_cast(any &value) { - typedef typename std::remove_reference::type nonref; - if(value.type() != typeid(nonref)) throw; - return static_cast*>(value.container)->value; - } - - template T any_cast(const any &value) { - typedef const typename std::remove_reference::type nonref; - if(value.type() != typeid(nonref)) throw; - return static_cast*>(value.container)->value; - } - - template T* any_cast(any *value) { - if(!value || value->type() != typeid(T)) return 0; - return &static_cast*>(value->container)->value; - } - - template const T* any_cast(const any *value) { - if(!value || value->type() != typeid(T)) return 0; - return &static_cast*>(value->container)->value; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/array.hpp b/waterbox/libsnes/bsnes/nall/array.hpp deleted file mode 100644 index 5fb5dff402..0000000000 --- a/waterbox/libsnes/bsnes/nall/array.hpp +++ /dev/null @@ -1,289 +0,0 @@ -#ifndef NALL_ARRAY_HPP -#define NALL_ARRAY_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - -template struct array; - -//non-reference array -//=================== - -template struct array::value>::type> { - struct exception_out_of_bounds{}; - -protected: - T *pool; - unsigned poolsize, objectsize; - -public: - unsigned size() const { return objectsize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) free(pool); - pool = nullptr; - poolsize = 0; - objectsize = 0; - } - - void reserve(unsigned newsize) { - if(newsize == poolsize) return; - - pool = (T*)realloc(pool, newsize * sizeof(T)); - poolsize = newsize; - objectsize = min(objectsize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(bit::round(newsize)); //round reserve size up to power of 2 - objectsize = newsize; - } - - T* get(unsigned minsize = 0) { - if(minsize > objectsize) resize(minsize); - return pool; - } - - void append(const T data) { - operator()(objectsize) = data; - } - - void append(const T data[], unsigned length) { - for(unsigned n = 0; n < length; n++) operator()(objectsize) = data[n]; - } - - void remove() { - if(size() > 0) resize(size() - 1); //remove last element only - } - - void remove(unsigned index, unsigned count = 1) { - for(unsigned i = index; count + i < objectsize; i++) { - pool[i] = pool[count + i]; - } - if(count + index >= objectsize) resize(index); //every element >= index was removed - else resize(objectsize - count); - } - - void sort() { - nall::sort(pool, objectsize); - } - - template void sort(const Comparator &lessthan) { - nall::sort(pool, objectsize, lessthan); - } - - optional find(const T data) { - for(unsigned n = 0; n < size(); n++) if(pool[n] == data) return { true, n }; - return { false, 0u }; - } - - void clear() { - memset(pool, 0, objectsize * sizeof(T)); - } - - array() : pool(nullptr), poolsize(0), objectsize(0) { - } - - array(std::initializer_list list) : pool(nullptr), poolsize(0), objectsize(0) { - for(auto &data : list) append(data); - } - - ~array() { - reset(); - } - - //copy - array& operator=(const array &source) { - if(pool) free(pool); - objectsize = source.objectsize; - poolsize = source.poolsize; - pool = (T*)malloc(sizeof(T) * poolsize); //allocate entire pool size, - memcpy(pool, source.pool, sizeof(T) * objectsize); //... but only copy used pool objects - return *this; - } - - array(const array &source) : pool(nullptr), poolsize(0), objectsize(0) { - operator=(source); - } - - //move - array& operator=(array &&source) { - if(pool) free(pool); - pool = source.pool; - poolsize = source.poolsize; - objectsize = source.objectsize; - source.pool = nullptr; - source.reset(); - return *this; - } - - array(array &&source) : pool(nullptr), poolsize(0), objectsize(0) { - operator=(std::move(source)); - } - - //access - inline T& operator[](unsigned position) { - if(position >= objectsize) throw exception_out_of_bounds(); - return pool[position]; - } - - inline const T& operator[](unsigned position) const { - if(position >= objectsize) throw exception_out_of_bounds(); - return pool[position]; - } - - inline T& operator()(unsigned position) { - if(position >= objectsize) resize(position + 1); - return pool[position]; - } - - inline const T& operator()(unsigned position, const T& data) { - if(position >= objectsize) return data; - return pool[position]; - } - - //iteration - T* begin() { return &pool[0]; } - T* end() { return &pool[objectsize]; } - const T* begin() const { return &pool[0]; } - const T* end() const { return &pool[objectsize]; } -}; - -//reference array -//=============== - -template struct array::value>::type> { - struct exception_out_of_bounds{}; - -protected: - typedef typename std::remove_reference::type T; - T **pool; - unsigned poolsize, objectsize; - -public: - unsigned size() const { return objectsize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) free(pool); - pool = nullptr; - poolsize = 0; - objectsize = 0; - } - - void reserve(unsigned newsize) { - if(newsize == poolsize) return; - - pool = (T**)realloc(pool, sizeof(T*) * newsize); - poolsize = newsize; - objectsize = min(objectsize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(bit::round(newsize)); - objectsize = newsize; - } - - template - bool append(T& data, Args&&... args) { - bool result = append(data); - append(std::forward(args)...); - return result; - } - - bool append(T& data) { - if(find(data)) return false; - unsigned offset = objectsize++; - if(offset >= poolsize) resize(offset + 1); - pool[offset] = &data; - return true; - } - - bool remove(T& data) { - if(auto position = find(data)) { - for(signed i = position(); i < objectsize - 1; i++) pool[i] = pool[i + 1]; - resize(objectsize - 1); - return true; - } - return false; - } - - optional find(const T& data) { - for(unsigned n = 0; n < objectsize; n++) if(pool[n] == &data) return { true, n }; - return { false, 0u }; - } - - template array(Args&&... args) : pool(nullptr), poolsize(0), objectsize(0) { - construct(std::forward(args)...); - } - - ~array() { - reset(); - } - - array& operator=(const array &source) { - if(pool) free(pool); - objectsize = source.objectsize; - poolsize = source.poolsize; - pool = (T**)malloc(sizeof(T*) * poolsize); - memcpy(pool, source.pool, sizeof(T*) * objectsize); - return *this; - } - - array& operator=(const array &&source) { - if(pool) free(pool); - pool = source.pool; - poolsize = source.poolsize; - objectsize = source.objectsize; - source.pool = nullptr; - source.reset(); - return *this; - } - - T& operator[](unsigned position) const { - if(position >= objectsize) throw exception_out_of_bounds(); - return *pool[position]; - } - - //iteration - struct iterator { - bool operator!=(const iterator &source) const { return position != source.position; } - T& operator*() { return source.operator[](position); } - iterator& operator++() { position++; return *this; } - iterator(const array &source, unsigned position) : source(source), position(position) {} - private: - const array &source; - unsigned position; - }; - - iterator begin() { return iterator(*this, 0); } - iterator end() { return iterator(*this, objectsize); } - const iterator begin() const { return iterator(*this, 0); } - const iterator end() const { return iterator(*this, objectsize); } - -private: - void construct() { - } - - void construct(const array& source) { operator=(source); } - void construct(const array&& source) { operator=(std::move(source)); } - - template void construct(T& data, Args&&... args) { - append(data); - construct(std::forward(args)...); - } -}; - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/atoi.hpp b/waterbox/libsnes/bsnes/nall/atoi.hpp deleted file mode 100644 index ac58b8ab89..0000000000 --- a/waterbox/libsnes/bsnes/nall/atoi.hpp +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef NALL_ATOI_HPP -#define NALL_ATOI_HPP - -namespace nall { - -//note: this header is intended to form the base for user-defined literals; -//once they are supported by GCC. eg: -//unsigned operator "" b(const char *s) { return binary(s); } -//-> signed data = 1001b; -//(0b1001 is nicer, but is not part of the C++ standard) - -constexpr inline uintmax_t binary_(const char *s, uintmax_t sum = 0) { - return ( - *s == '0' || *s == '1' ? binary_(s + 1, (sum << 1) | *s - '0') : - sum - ); -} - -constexpr inline uintmax_t octal_(const char *s, uintmax_t sum = 0) { - return ( - *s >= '0' && *s <= '7' ? octal_(s + 1, (sum << 3) | *s - '0') : - sum - ); -} - -constexpr inline uintmax_t decimal_(const char *s, uintmax_t sum = 0) { - return ( - *s >= '0' && *s <= '9' ? decimal_(s + 1, (sum * 10) + *s - '0') : - sum - ); -} - -constexpr inline uintmax_t hex_(const char *s, uintmax_t sum = 0) { - return ( - *s >= 'A' && *s <= 'F' ? hex_(s + 1, (sum << 4) | *s - 'A' + 10) : - *s >= 'a' && *s <= 'f' ? hex_(s + 1, (sum << 4) | *s - 'a' + 10) : - *s >= '0' && *s <= '9' ? hex_(s + 1, (sum << 4) | *s - '0') : - sum - ); -} - -// - -constexpr inline uintmax_t binary(const char *s) { - return ( - *s == '0' && *(s + 1) == 'B' ? binary_(s + 2) : - *s == '0' && *(s + 1) == 'b' ? binary_(s + 2) : - *s == '%' ? binary_(s + 1) : - binary_(s) - ); -} - -constexpr inline uintmax_t octal(const char *s) { - return ( - octal_(s) - ); -} - -constexpr inline intmax_t integer(const char *s) { - return ( - *s == '+' ? +decimal_(s + 1) : - *s == '-' ? -decimal_(s + 1) : - decimal_(s) - ); -} - -constexpr inline uintmax_t decimal(const char *s) { - return ( - decimal_(s) - ); -} - -constexpr inline uintmax_t hex(const char *s) { - return ( - *s == '0' && *(s + 1) == 'X' ? hex_(s + 2) : - *s == '0' && *(s + 1) == 'x' ? hex_(s + 2) : - *s == '$' ? hex_(s + 1) : - hex_(s) - ); -} - -constexpr inline intmax_t numeral(const char *s) { - return ( - *s == '0' && *(s + 1) == 'X' ? hex_(s + 2) : - *s == '0' && *(s + 1) == 'x' ? hex_(s + 2) : - *s == '0' && *(s + 1) == 'B' ? binary_(s + 2) : - *s == '0' && *(s + 1) == 'b' ? binary_(s + 2) : - *s == '0' ? octal_(s + 1) : - *s == '+' ? +decimal_(s + 1) : - *s == '-' ? -decimal_(s + 1) : - decimal_(s) - ); -} - -inline double fp(const char *s) { - return atof(s); -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/base64.hpp b/waterbox/libsnes/bsnes/nall/base64.hpp deleted file mode 100644 index a0afd8b1cf..0000000000 --- a/waterbox/libsnes/bsnes/nall/base64.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef NALL_BASE64_HPP -#define NALL_BASE64_HPP - -#include -#include - -namespace nall { - struct base64 { - static bool encode(char *&output, const uint8_t* input, unsigned inlength) { - output = new char[inlength * 8 / 6 + 6](); - - unsigned i = 0, o = 0; - while(i < inlength) { - switch(i % 3) { - case 0: { - output[o++] = enc(input[i] >> 2); - output[o] = enc((input[i] & 3) << 4); - } break; - - case 1: { - uint8_t prev = dec(output[o]); - output[o++] = enc(prev + (input[i] >> 4)); - output[o] = enc((input[i] & 15) << 2); - } break; - - case 2: { - uint8_t prev = dec(output[o]); - output[o++] = enc(prev + (input[i] >> 6)); - output[o++] = enc(input[i] & 63); - } break; - } - - i++; - } - - return true; - } - - static bool decode(uint8_t *&output, unsigned &outlength, const char *input) { - unsigned inlength = strlen(input), infix = 0; - output = new uint8_t[inlength](); - - unsigned i = 0, o = 0; - while(i < inlength) { - uint8_t x = dec(input[i]); - - switch(i++ & 3) { - case 0: { - output[o] = x << 2; - } break; - - case 1: { - output[o++] |= x >> 4; - output[o] = (x & 15) << 4; - } break; - - case 2: { - output[o++] |= x >> 2; - output[o] = (x & 3) << 6; - } break; - - case 3: { - output[o++] |= x; - } break; - } - } - - outlength = o; - return true; - } - - private: - static char enc(uint8_t n) { - //base64 for URL encodings - static char lookup_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - return lookup_table[n & 63]; - } - - static uint8_t dec(char n) { - if(n >= 'A' && n <= 'Z') return n - 'A'; - if(n >= 'a' && n <= 'z') return n - 'a' + 26; - if(n >= '0' && n <= '9') return n - '0' + 52; - if(n == '-') return 62; - if(n == '_') return 63; - return 0; - } - }; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/bit.hpp b/waterbox/libsnes/bsnes/nall/bit.hpp deleted file mode 100644 index 9815c89f82..0000000000 --- a/waterbox/libsnes/bsnes/nall/bit.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef NALL_BIT_HPP -#define NALL_BIT_HPP - -namespace nall { - template - constexpr inline uintmax_t uclamp(const uintmax_t x) { - enum : uintmax_t { b = 1ull << (bits - 1), y = b * 2 - 1 }; - return y + ((x - y) & -(x < y)); //min(x, y); - } - - template - constexpr inline uintmax_t uclip(const uintmax_t x) { - //zero 17-jun-2015 - revised to use more standard constexpr behaviour - //enum : uintmax_t { b = 1ull << (bits - 1), m = b * 2 - 1 }; - //return (x & m); //test - return (x & ((uintmax_t)(((uintmax_t)(1ull << (bits - 1))) * 2 - 1))); - } - - template - constexpr inline intmax_t sclamp(const intmax_t x) { - //zero 17-jun-2015 - revised to use more standard constexpr behaviour - //enum : intmax_t { b = 1ull << (bits - 1), m = b - 1 }; - //(intmax_t)(1ull << (bits - 1)) //b - //(((intmax_t)(1ull << (bits - 1))) - 1) //m - //return (x > m) ? m : (x < -b) ? -b : x; - return (x > (((intmax_t)(1ull << (bits - 1))) - 1)) ? (((intmax_t)(1ull << (bits - 1))) - 1) : (x < -((intmax_t)(1ull << (bits - 1)))) ? -((intmax_t)(1ull << (bits - 1))) : x; //test - } - - template - constexpr inline intmax_t sclip(const intmax_t x) { - //zero 17-jun-2015 - revised to use more standard constexpr behaviour - //enum : uintmax_t { b = 1ull << (bits - 1), m = b * 2 - 1 }; //test - return ((x & ((uintmax_t)(((uintmax_t)(1ull << (bits - 1))) * 2 - 1))) ^ ((uintmax_t)(1ull << (bits - 1)))) - ((uintmax_t)(1ull << (bits - 1))); - } - - namespace bit { - //lowest(0b1110) == 0b0010 - constexpr inline uintmax_t lowest(const uintmax_t x) { - return x & -x; - } - - //clear_lowest(0b1110) == 0b1100 - constexpr inline uintmax_t clear_lowest(const uintmax_t x) { - return x & (x - 1); - } - - //set_lowest(0b0101) == 0b0111 - constexpr inline uintmax_t set_lowest(const uintmax_t x) { - return x | (x + 1); - } - - //count number of bits set in a byte - inline unsigned count(uintmax_t x) { - unsigned count = 0; - do count += x & 1; while(x >>= 1); - return count; - } - - //round up to next highest single bit: - //round(15) == 16, round(16) == 16, round(17) == 32 - inline uintmax_t round(uintmax_t x) { - if((x & (x - 1)) == 0) return x; - while(x & (x - 1)) x &= x - 1; - return x << 1; - } - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/bmp.hpp b/waterbox/libsnes/bsnes/nall/bmp.hpp deleted file mode 100644 index 33cdf4dcfb..0000000000 --- a/waterbox/libsnes/bsnes/nall/bmp.hpp +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef NALL_BMP_HPP -#define NALL_BMP_HPP - -#include - -//BMP reader / writer -//author: byuu -//note: only 24-bit RGB and 32-bit ARGB uncompressed images supported - -namespace nall { - -struct bmp { - inline static bool read(const string &filename, uint32_t *&data, unsigned &width, unsigned &height); - inline static bool write(const string &filename, const uint32_t *data, unsigned width, unsigned height, unsigned pitch, bool alpha = false); -}; - -bool bmp::read(const string &filename, uint32_t *&data, unsigned &width, unsigned &height) { - file fp; - if(fp.open(filename, file::mode::read) == false) return false; - if(fp.size() < 0x36) return false; - - if(fp.readm(2) != 0x424d) return false; - fp.seek(0x000a); - unsigned offset = fp.readl(4); - unsigned dibsize = fp.readl(4); - if(dibsize != 40) return false; - signed headerWidth = fp.readl(4); - if(headerWidth < 0) return false; - signed headerHeight = fp.readl(4); - fp.readl(2); - unsigned bitsPerPixel = fp.readl(2); - if(bitsPerPixel != 24 && bitsPerPixel != 32) return false; - unsigned compression = fp.readl(4); - if(compression != 0) return false; - fp.seek(offset); - - bool noFlip = headerHeight < 0; - width = headerWidth, height = abs(headerHeight); - data = new uint32_t[width * height]; - - unsigned bytesPerPixel = bitsPerPixel / 8; - unsigned alignedWidth = width * bytesPerPixel; - unsigned paddingLength = 0; - while(alignedWidth % 4) alignedWidth++, paddingLength++; - - for(unsigned y = 0; y < height; y++) { - uint32_t *p = noFlip ? data + y * width : data + (height - 1 - y) * width; - for(unsigned x = 0; x < width; x++, p++) { - *p = fp.readl(bytesPerPixel); - if(bytesPerPixel == 3) *p |= 255 << 24; - } - if(paddingLength) fp.readl(paddingLength); - } - - fp.close(); - return true; -} - -bool bmp::write(const string &filename, const uint32_t *data, unsigned width, unsigned height, unsigned pitch, bool alpha) { - file fp; - if(fp.open(filename, file::mode::write) == false) return false; - - unsigned bitsPerPixel = alpha ? 32 : 24; - unsigned bytesPerPixel = bitsPerPixel / 8; - unsigned alignedWidth = width * bytesPerPixel; - unsigned paddingLength = 0; - unsigned imageSize = alignedWidth * height; - unsigned fileSize = 0x36 + imageSize; - while(alignedWidth % 4) alignedWidth++, paddingLength++; - - fp.writem(0x424d, 2); //signature - fp.writel(fileSize, 4); //file size - fp.writel(0, 2); //reserved - fp.writel(0, 2); //reserved - fp.writel(0x36, 4); //offset - - fp.writel(40, 4); //DIB size - fp.writel(width, 4); //width - fp.writel(-height, 4); //height - fp.writel(1, 2); //color planes - fp.writel(bitsPerPixel, 2); //bits per pixel - fp.writel(0, 4); //compression method (BI_RGB) - fp.writel(imageSize, 4); //image data size - fp.writel(3780, 4); //horizontal resolution - fp.writel(3780, 4); //vertical resolution - fp.writel(0, 4); //palette size - fp.writel(0, 4); //important color count - - for(unsigned y = 0; y < height; y++) { - const uint32_t *p = (const uint32_t*)((const uint8_t*)data + y * pitch); - for(unsigned x = 0; x < width; x++) fp.writel(*p++, bytesPerPixel); - if(paddingLength) fp.writel(0, paddingLength); - } - - fp.close(); - return true; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/bps/delta.hpp b/waterbox/libsnes/bsnes/nall/bps/delta.hpp deleted file mode 100644 index 6cee56a302..0000000000 --- a/waterbox/libsnes/bsnes/nall/bps/delta.hpp +++ /dev/null @@ -1,214 +0,0 @@ -#ifndef NALL_BPS_DELTA_HPP -#define NALL_BPS_DELTA_HPP - -#include -#include -#include -#include -#include - -namespace nall { - -struct bpsdelta { - inline void source(const uint8_t *data, unsigned size); - inline void target(const uint8_t *data, unsigned size); - - inline bool source(const string &filename); - inline bool target(const string &filename); - inline bool create(const string &filename, const string &metadata = ""); - -protected: - enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy }; - enum : unsigned { Granularity = 1 }; - - struct Node { - unsigned offset; - Node *next; - inline Node() : offset(0), next(nullptr) {} - inline ~Node() { if(next) delete next; } - }; - - filemap sourceFile; - const uint8_t *sourceData; - unsigned sourceSize; - - filemap targetFile; - const uint8_t *targetData; - unsigned targetSize; -}; - -void bpsdelta::source(const uint8_t *data, unsigned size) { - sourceData = data; - sourceSize = size; -} - -void bpsdelta::target(const uint8_t *data, unsigned size) { - targetData = data; - targetSize = size; -} - -bool bpsdelta::source(const string &filename) { - if(sourceFile.open(filename, filemap::mode::read) == false) return false; - source(sourceFile.data(), sourceFile.size()); - return true; -} - -bool bpsdelta::target(const string &filename) { - if(targetFile.open(filename, filemap::mode::read) == false) return false; - target(targetFile.data(), targetFile.size()); - return true; -} - -bool bpsdelta::create(const string &filename, const string &metadata) { - file modifyFile; - if(modifyFile.open(filename, file::mode::write) == false) return false; - - uint32_t sourceChecksum = ~0, modifyChecksum = ~0; - unsigned sourceRelativeOffset = 0, targetRelativeOffset = 0, outputOffset = 0; - - auto write = [&](uint8_t data) { - modifyFile.write(data); - modifyChecksum = crc32_adjust(modifyChecksum, data); - }; - - auto encode = [&](uint64_t data) { - while(true) { - uint64_t x = data & 0x7f; - data >>= 7; - if(data == 0) { - write(0x80 | x); - break; - } - write(x); - data--; - } - }; - - write('B'); - write('P'); - write('S'); - write('1'); - - encode(sourceSize); - encode(targetSize); - - unsigned markupSize = metadata.length(); - encode(markupSize); - for(unsigned n = 0; n < markupSize; n++) write(metadata[n]); - - Node *sourceTree[65536], *targetTree[65536]; - for(unsigned n = 0; n < 65536; n++) sourceTree[n] = 0, targetTree[n] = 0; - - //source tree creation - for(unsigned offset = 0; offset < sourceSize; offset++) { - uint16_t symbol = sourceData[offset + 0]; - sourceChecksum = crc32_adjust(sourceChecksum, symbol); - if(offset < sourceSize - 1) symbol |= sourceData[offset + 1] << 8; - Node *node = new Node; - node->offset = offset; - node->next = sourceTree[symbol]; - sourceTree[symbol] = node; - } - - unsigned targetReadLength = 0; - - auto targetReadFlush = [&]() { - if(targetReadLength) { - encode(TargetRead | ((targetReadLength - 1) << 2)); - unsigned offset = outputOffset - targetReadLength; - while(targetReadLength) write(targetData[offset++]), targetReadLength--; - } - }; - - while(outputOffset < targetSize) { - unsigned maxLength = 0, maxOffset = 0, mode = TargetRead; - - uint16_t symbol = targetData[outputOffset + 0]; - if(outputOffset < targetSize - 1) symbol |= targetData[outputOffset + 1] << 8; - - { //source read - unsigned length = 0, offset = outputOffset; - while(offset < sourceSize && offset < targetSize && sourceData[offset] == targetData[offset]) { - length++; - offset++; - } - if(length > maxLength) maxLength = length, mode = SourceRead; - } - - { //source copy - Node *node = sourceTree[symbol]; - while(node) { - unsigned length = 0, x = node->offset, y = outputOffset; - while(x < sourceSize && y < targetSize && sourceData[x++] == targetData[y++]) length++; - if(length > maxLength) maxLength = length, maxOffset = node->offset, mode = SourceCopy; - node = node->next; - } - } - - { //target copy - Node *node = targetTree[symbol]; - while(node) { - unsigned length = 0, x = node->offset, y = outputOffset; - while(y < targetSize && targetData[x++] == targetData[y++]) length++; - if(length > maxLength) maxLength = length, maxOffset = node->offset, mode = TargetCopy; - node = node->next; - } - - //target tree append - node = new Node; - node->offset = outputOffset; - node->next = targetTree[symbol]; - targetTree[symbol] = node; - } - - { //target read - if(maxLength < 4) { - maxLength = min((unsigned)Granularity, targetSize - outputOffset); - mode = TargetRead; - } - } - - if(mode != TargetRead) targetReadFlush(); - - switch(mode) { - case SourceRead: - encode(SourceRead | ((maxLength - 1) << 2)); - break; - case TargetRead: - //delay write to group sequential TargetRead commands into one - targetReadLength += maxLength; - break; - case SourceCopy: - case TargetCopy: - encode(mode | ((maxLength - 1) << 2)); - signed relativeOffset; - if(mode == SourceCopy) { - relativeOffset = maxOffset - sourceRelativeOffset; - sourceRelativeOffset = maxOffset + maxLength; - } else { - relativeOffset = maxOffset - targetRelativeOffset; - targetRelativeOffset = maxOffset + maxLength; - } - encode((relativeOffset < 0) | (abs(relativeOffset) << 1)); - break; - } - - outputOffset += maxLength; - } - - targetReadFlush(); - - sourceChecksum = ~sourceChecksum; - for(unsigned n = 0; n < 32; n += 8) write(sourceChecksum >> n); - uint32_t targetChecksum = crc32_calculate(targetData, targetSize); - for(unsigned n = 0; n < 32; n += 8) write(targetChecksum >> n); - uint32_t outputChecksum = ~modifyChecksum; - for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n); - - modifyFile.close(); - return true; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/bps/linear.hpp b/waterbox/libsnes/bsnes/nall/bps/linear.hpp deleted file mode 100644 index df8402838f..0000000000 --- a/waterbox/libsnes/bsnes/nall/bps/linear.hpp +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef NALL_BPS_LINEAR_HPP -#define NALL_BPS_LINEAR_HPP - -#include -#include -#include -#include -#include - -namespace nall { - -struct bpslinear { - inline void source(const uint8_t *data, unsigned size); - inline void target(const uint8_t *data, unsigned size); - - inline bool source(const string &filename); - inline bool target(const string &filename); - inline bool create(const string &filename, const string &metadata = ""); - -protected: - enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy }; - enum : unsigned { Granularity = 1 }; - - filemap sourceFile; - const uint8_t *sourceData; - unsigned sourceSize; - - filemap targetFile; - const uint8_t *targetData; - unsigned targetSize; -}; - -void bpslinear::source(const uint8_t *data, unsigned size) { - sourceData = data; - sourceSize = size; -} - -void bpslinear::target(const uint8_t *data, unsigned size) { - targetData = data; - targetSize = size; -} - -bool bpslinear::source(const string &filename) { - if(sourceFile.open(filename, filemap::mode::read) == false) return false; - source(sourceFile.data(), sourceFile.size()); - return true; -} - -bool bpslinear::target(const string &filename) { - if(targetFile.open(filename, filemap::mode::read) == false) return false; - target(targetFile.data(), targetFile.size()); - return true; -} - -bool bpslinear::create(const string &filename, const string &metadata) { - file modifyFile; - if(modifyFile.open(filename, file::mode::write) == false) return false; - - uint32_t modifyChecksum = ~0; - unsigned targetRelativeOffset = 0, outputOffset = 0; - - auto write = [&](uint8_t data) { - modifyFile.write(data); - modifyChecksum = crc32_adjust(modifyChecksum, data); - }; - - auto encode = [&](uint64_t data) { - while(true) { - uint64_t x = data & 0x7f; - data >>= 7; - if(data == 0) { - write(0x80 | x); - break; - } - write(x); - data--; - } - }; - - unsigned targetReadLength = 0; - - auto targetReadFlush = [&]() { - if(targetReadLength) { - encode(TargetRead | ((targetReadLength - 1) << 2)); - unsigned offset = outputOffset - targetReadLength; - while(targetReadLength) write(targetData[offset++]), targetReadLength--; - } - }; - - write('B'); - write('P'); - write('S'); - write('1'); - - encode(sourceSize); - encode(targetSize); - - unsigned markupSize = metadata.length(); - encode(markupSize); - for(unsigned n = 0; n < markupSize; n++) write(metadata[n]); - - while(outputOffset < targetSize) { - unsigned sourceLength = 0; - for(unsigned n = 0; outputOffset + n < min(sourceSize, targetSize); n++) { - if(sourceData[outputOffset + n] != targetData[outputOffset + n]) break; - sourceLength++; - } - - unsigned rleLength = 0; - for(unsigned n = 1; outputOffset + n < targetSize; n++) { - if(targetData[outputOffset] != targetData[outputOffset + n]) break; - rleLength++; - } - - if(rleLength >= 4) { - //write byte to repeat - targetReadLength++; - outputOffset++; - targetReadFlush(); - - //copy starting from repetition byte - encode(TargetCopy | ((rleLength - 1) << 2)); - unsigned relativeOffset = (outputOffset - 1) - targetRelativeOffset; - encode(relativeOffset << 1); - outputOffset += rleLength; - targetRelativeOffset = outputOffset - 1; - } else if(sourceLength >= 4) { - targetReadFlush(); - encode(SourceRead | ((sourceLength - 1) << 2)); - outputOffset += sourceLength; - } else { - targetReadLength += Granularity; - outputOffset += Granularity; - } - } - - targetReadFlush(); - - uint32_t sourceChecksum = crc32_calculate(sourceData, sourceSize); - for(unsigned n = 0; n < 32; n += 8) write(sourceChecksum >> n); - uint32_t targetChecksum = crc32_calculate(targetData, targetSize); - for(unsigned n = 0; n < 32; n += 8) write(targetChecksum >> n); - uint32_t outputChecksum = ~modifyChecksum; - for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n); - - modifyFile.close(); - return true; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/bps/metadata.hpp b/waterbox/libsnes/bsnes/nall/bps/metadata.hpp deleted file mode 100644 index 46759e6fe1..0000000000 --- a/waterbox/libsnes/bsnes/nall/bps/metadata.hpp +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef NALL_BPS_METADATA_HPP -#define NALL_BPS_METADATA_HPP - -#include -#include -#include -#include -#include - -namespace nall { - -struct bpsmetadata { - inline bool load(const string &filename); - inline bool save(const string &filename, const string &metadata); - inline string metadata() const; - -protected: - file sourceFile; - string metadataString; -}; - -bool bpsmetadata::load(const string &filename) { - if(sourceFile.open(filename, file::mode::read) == false) return false; - - auto read = [&]() -> uint8_t { - return sourceFile.read(); - }; - - auto decode = [&]() -> uint64_t { - uint64_t data = 0, shift = 1; - while(true) { - uint8_t x = read(); - data += (x & 0x7f) * shift; - if(x & 0x80) break; - shift <<= 7; - data += shift; - } - return data; - }; - - if(read() != 'B') return false; - if(read() != 'P') return false; - if(read() != 'S') return false; - if(read() != '1') return false; - decode(); - decode(); - unsigned metadataSize = decode(); - char data[metadataSize + 1]; - for(unsigned n = 0; n < metadataSize; n++) data[n] = read(); - data[metadataSize] = 0; - metadataString = (const char*)data; - - return true; -} - -bool bpsmetadata::save(const string &filename, const string &metadata) { - file targetFile; - if(targetFile.open(filename, file::mode::write) == false) return false; - if(sourceFile.open() == false) return false; - sourceFile.seek(0); - - auto read = [&]() -> uint8_t { - return sourceFile.read(); - }; - - auto decode = [&]() -> uint64_t { - uint64_t data = 0, shift = 1; - while(true) { - uint8_t x = read(); - data += (x & 0x7f) * shift; - if(x & 0x80) break; - shift <<= 7; - data += shift; - } - return data; - }; - - uint32_t checksum = ~0; - - auto write = [&](uint8_t data) { - targetFile.write(data); - checksum = crc32_adjust(checksum, data); - }; - - auto encode = [&](uint64_t data) { - while(true) { - uint64_t x = data & 0x7f; - data >>= 7; - if(data == 0) { - write(0x80 | x); - break; - } - write(x); - data--; - } - }; - - for(unsigned n = 0; n < 4; n++) write(read()); - encode(decode()); - encode(decode()); - unsigned sourceLength = decode(); - unsigned targetLength = metadata.length(); - encode(targetLength); - sourceFile.seek(sourceLength, file::index::relative); - for(unsigned n = 0; n < targetLength; n++) write(metadata[n]); - unsigned length = sourceFile.size() - sourceFile.offset() - 4; - for(unsigned n = 0; n < length; n++) write(read()); - uint32_t outputChecksum = ~checksum; - for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n); - - targetFile.close(); - return true; -} - -string bpsmetadata::metadata() const { - return metadataString; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/bps/patch.hpp b/waterbox/libsnes/bsnes/nall/bps/patch.hpp deleted file mode 100644 index 85c4dcaefe..0000000000 --- a/waterbox/libsnes/bsnes/nall/bps/patch.hpp +++ /dev/null @@ -1,219 +0,0 @@ -#ifndef NALL_BPS_PATCH_HPP -#define NALL_BPS_PATCH_HPP - -#include -#include -#include -#include -#include - -namespace nall { - -struct bpspatch { - inline bool modify(const uint8_t *data, unsigned size); - inline void source(const uint8_t *data, unsigned size); - inline void target(uint8_t *data, unsigned size); - - inline bool modify(const string &filename); - inline bool source(const string &filename); - inline bool target(const string &filename); - - inline string metadata() const; - inline unsigned size() const; - - enum result : unsigned { - unknown, - success, - patch_too_small, - patch_invalid_header, - source_too_small, - target_too_small, - source_checksum_invalid, - target_checksum_invalid, - patch_checksum_invalid, - }; - - inline result apply(); - -protected: - enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy }; - - filemap modifyFile; - const uint8_t *modifyData; - unsigned modifySize; - - filemap sourceFile; - const uint8_t *sourceData; - unsigned sourceSize; - - filemap targetFile; - uint8_t *targetData; - unsigned targetSize; - - unsigned modifySourceSize; - unsigned modifyTargetSize; - unsigned modifyMarkupSize; - string metadataString; -}; - -bool bpspatch::modify(const uint8_t *data, unsigned size) { - if(size < 19) return false; - modifyData = data; - modifySize = size; - - unsigned offset = 4; - auto decode = [&]() -> uint64_t { - uint64_t data = 0, shift = 1; - while(true) { - uint8_t x = modifyData[offset++]; - data += (x & 0x7f) * shift; - if(x & 0x80) break; - shift <<= 7; - data += shift; - } - return data; - }; - - modifySourceSize = decode(); - modifyTargetSize = decode(); - modifyMarkupSize = decode(); - - char buffer[modifyMarkupSize + 1]; - for(unsigned n = 0; n < modifyMarkupSize; n++) buffer[n] = modifyData[offset++]; - buffer[modifyMarkupSize] = 0; - metadataString = (const char*)buffer; - - return true; -} - -void bpspatch::source(const uint8_t *data, unsigned size) { - sourceData = data; - sourceSize = size; -} - -void bpspatch::target(uint8_t *data, unsigned size) { - targetData = data; - targetSize = size; -} - -bool bpspatch::modify(const string &filename) { - if(modifyFile.open(filename, filemap::mode::read) == false) return false; - return modify(modifyFile.data(), modifyFile.size()); -} - -bool bpspatch::source(const string &filename) { - if(sourceFile.open(filename, filemap::mode::read) == false) return false; - source(sourceFile.data(), sourceFile.size()); - return true; -} - -bool bpspatch::target(const string &filename) { - file fp; - if(fp.open(filename, file::mode::write) == false) return false; - fp.truncate(modifyTargetSize); - fp.close(); - - if(targetFile.open(filename, filemap::mode::readwrite) == false) return false; - target(targetFile.data(), targetFile.size()); - return true; -} - -string bpspatch::metadata() const { - return metadataString; -} - -unsigned bpspatch::size() const { - return modifyTargetSize; -} - -bpspatch::result bpspatch::apply() { - if(modifySize < 19) return result::patch_too_small; - - uint32_t modifyChecksum = ~0, targetChecksum = ~0; - unsigned modifyOffset = 0, sourceRelativeOffset = 0, targetRelativeOffset = 0, outputOffset = 0; - - auto read = [&]() -> uint8_t { - uint8_t data = modifyData[modifyOffset++]; - modifyChecksum = crc32_adjust(modifyChecksum, data); - return data; - }; - - auto decode = [&]() -> uint64_t { - uint64_t data = 0, shift = 1; - while(true) { - uint8_t x = read(); - data += (x & 0x7f) * shift; - if(x & 0x80) break; - shift <<= 7; - data += shift; - } - return data; - }; - - auto write = [&](uint8_t data) { - targetData[outputOffset++] = data; - targetChecksum = crc32_adjust(targetChecksum, data); - }; - - if(read() != 'B') return result::patch_invalid_header; - if(read() != 'P') return result::patch_invalid_header; - if(read() != 'S') return result::patch_invalid_header; - if(read() != '1') return result::patch_invalid_header; - - modifySourceSize = decode(); - modifyTargetSize = decode(); - modifyMarkupSize = decode(); - for(unsigned n = 0; n < modifyMarkupSize; n++) read(); - - if(modifySourceSize > sourceSize) return result::source_too_small; - if(modifyTargetSize > targetSize) return result::target_too_small; - - while(modifyOffset < modifySize - 12) { - unsigned length = decode(); - unsigned mode = length & 3; - length = (length >> 2) + 1; - - switch(mode) { - case SourceRead: - while(length--) write(sourceData[outputOffset]); - break; - case TargetRead: - while(length--) write(read()); - break; - case SourceCopy: - case TargetCopy: - signed offset = decode(); - bool negative = offset & 1; - offset >>= 1; - if(negative) offset = -offset; - - if(mode == SourceCopy) { - sourceRelativeOffset += offset; - while(length--) write(sourceData[sourceRelativeOffset++]); - } else { - targetRelativeOffset += offset; - while(length--) write(targetData[targetRelativeOffset++]); - } - break; - } - } - - uint32_t modifySourceChecksum = 0, modifyTargetChecksum = 0, modifyModifyChecksum = 0; - for(unsigned n = 0; n < 32; n += 8) modifySourceChecksum |= read() << n; - for(unsigned n = 0; n < 32; n += 8) modifyTargetChecksum |= read() << n; - uint32_t checksum = ~modifyChecksum; - for(unsigned n = 0; n < 32; n += 8) modifyModifyChecksum |= read() << n; - - uint32_t sourceChecksum = crc32_calculate(sourceData, modifySourceSize); - targetChecksum = ~targetChecksum; - - if(sourceChecksum != modifySourceChecksum) return result::source_checksum_invalid; - if(targetChecksum != modifyTargetChecksum) return result::target_checksum_invalid; - if(checksum != modifyModifyChecksum) return result::patch_checksum_invalid; - - return result::success; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/compositor.hpp b/waterbox/libsnes/bsnes/nall/compositor.hpp deleted file mode 100644 index 6b9245f63b..0000000000 --- a/waterbox/libsnes/bsnes/nall/compositor.hpp +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef NALL_COMPOSITOR_HPP -#define NALL_COMPOSITOR_HPP - -#include - -namespace nall { - -struct compositor { - inline static bool enabled(); - inline static bool enable(bool status); - - #if defined(PLATFORM_X) - enum class Compositor : unsigned { Unknown, Metacity, Xfwm4 }; - inline static Compositor detect(); - - inline static bool enabled_metacity(); - inline static bool enable_metacity(bool status); - - inline static bool enabled_xfwm4(); - inline static bool enable_xfwm4(bool status); - #endif -}; - -#if defined(PLATFORM_X) - -//Metacity - -bool compositor::enabled_metacity() { - FILE *fp = popen("gconftool-2 --get /apps/metacity/general/compositing_manager", "r"); - if(fp == 0) return false; - - char buffer[512]; - if(fgets(buffer, sizeof buffer, fp) == 0) return false; - - if(!memcmp(buffer, "true", 4)) return true; - return false; -} - -bool compositor::enable_metacity(bool status) { - FILE *fp; - if(status) { - fp = popen("gconftool-2 --set --type bool /apps/metacity/general/compositing_manager true", "r"); - } else { - fp = popen("gconftool-2 --set --type bool /apps/metacity/general/compositing_manager false", "r"); - } - if(fp == 0) return false; - pclose(fp); - return true; -} - -//Xfwm4 - -bool compositor::enabled_xfwm4() { - FILE *fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing'", "r"); - if(fp == 0) return false; - - char buffer[512]; - if(fgets(buffer, sizeof buffer, fp) == 0) return false; - - if(!memcmp(buffer, "true", 4)) return true; - return false; -} - -bool compositor::enable_xfwm4(bool status) { - FILE *fp; - if(status) { - fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'true'", "r"); - } else { - fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'false'", "r"); - } - if(fp == 0) return false; - pclose(fp); - return true; -} - -//General - -compositor::Compositor compositor::detect() { - Compositor result = Compositor::Unknown; - - FILE *fp; - char buffer[512]; - - fp = popen("pidof metacity", "r"); - if(fp && fgets(buffer, sizeof buffer, fp)) result = Compositor::Metacity; - pclose(fp); - - fp = popen("pidof xfwm4", "r"); - if(fp && fgets(buffer, sizeof buffer, fp)) result = Compositor::Xfwm4; - pclose(fp); - - return result; -} - -bool compositor::enabled() { - switch(detect()) { - case Compositor::Metacity: return enabled_metacity(); - case Compositor::Xfwm4: return enabled_xfwm4(); - default: return false; - } -} - -bool compositor::enable(bool status) { - switch(detect()) { - case Compositor::Metacity: return enable_metacity(status); - case Compositor::Xfwm4: return enable_xfwm4(status); - default: return false; - } -} - -#elif defined(PLATFORM_WINDOWS) - -bool compositor::enabled() { - HMODULE module = GetModuleHandleW(L"dwmapi"); - if(module == 0) module = LoadLibraryW(L"dwmapi"); - if(module == 0) return false; - - auto pDwmIsCompositionEnabled = (HRESULT (WINAPI*)(BOOL*))GetProcAddress(module, "DwmIsCompositionEnabled"); - if(pDwmIsCompositionEnabled == 0) return false; - - BOOL result; - if(pDwmIsCompositionEnabled(&result) != S_OK) return false; - return result; -} - -bool compositor::enable(bool status) { - HMODULE module = GetModuleHandleW(L"dwmapi"); - if(module == 0) module = LoadLibraryW(L"dwmapi"); - if(module == 0) return false; - - auto pDwmEnableComposition = (HRESULT (WINAPI*)(UINT))GetProcAddress(module, "DwmEnableComposition"); - if(pDwmEnableComposition == 0) return false; - - if(pDwmEnableComposition(status) != S_OK) return false; - return true; -} - -#else - -bool compositor::enabled() { - return false; -} - -bool compositor::enable(bool) { - return false; -} - -#endif - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/config.hpp b/waterbox/libsnes/bsnes/nall/config.hpp deleted file mode 100644 index 94be7dc125..0000000000 --- a/waterbox/libsnes/bsnes/nall/config.hpp +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef NALL_CONFIG_HPP -#define NALL_CONFIG_HPP - -#include -#include -#include - -namespace nall { - namespace configuration_traits { - template struct is_boolean { enum { value = false }; }; - template<> struct is_boolean { enum { value = true }; }; - - template struct is_signed { enum { value = false }; }; - template<> struct is_signed { enum { value = true }; }; - - template struct is_unsigned { enum { value = false }; }; - template<> struct is_unsigned { enum { value = true }; }; - - template struct is_double { enum { value = false }; }; - template<> struct is_double { enum { value = true }; }; - - template struct is_string { enum { value = false }; }; - template<> struct is_string { enum { value = true }; }; - } - - class configuration { - public: - enum type_t { boolean_t, signed_t, unsigned_t, double_t, string_t, unknown_t }; - struct item_t { - uintptr_t data; - string name; - string desc; - type_t type; - - inline string get() const { - switch(type) { - case boolean_t: return { *(bool*)data }; - case signed_t: return { *(signed*)data }; - case unsigned_t: return { *(unsigned*)data }; - case double_t: return { *(double*)data }; - case string_t: return { "\"", *(string*)data, "\"" }; - } - return "???"; - } - - inline void set(string s) { - switch(type) { - case boolean_t: *(bool*)data = (s == "true"); break; - case signed_t: *(signed*)data = integer(s); break; - case unsigned_t: *(unsigned*)data = decimal(s); break; - case double_t: *(double*)data = fp(s); break; - case string_t: s.trim("\""); *(string*)data = s; break; - } - } - }; - vector list; - - template - inline void append(T &data, const char *name, const char *desc = "") { - item_t item = { (uintptr_t)&data, name, desc }; - if(configuration_traits::is_boolean::value) item.type = boolean_t; - else if(configuration_traits::is_signed::value) item.type = signed_t; - else if(configuration_traits::is_unsigned::value) item.type = unsigned_t; - else if(configuration_traits::is_double::value) item.type = double_t; - else if(configuration_traits::is_string::value) item.type = string_t; - else item.type = unknown_t; - list.append(item); - } - - //deprecated - template - inline void attach(T &data, const char *name, const char *desc = "") { - append(data, name, desc); - } - - inline virtual bool load(const string &filename) { - string data; - if(data.readfile(filename) == true) { - data.replace("\r", ""); - lstring line; - line.split("\n", data); - - for(unsigned i = 0; i < line.size(); i++) { - if(auto position = qstrpos(line[i], "#")) line[i][position()] = 0; - if(!qstrpos(line[i], " = ")) continue; - - lstring part; - part.qsplit(" = ", line[i]); - part[0].trim(); - part[1].trim(); - - for(unsigned n = 0; n < list.size(); n++) { - if(part[0] == list[n].name) { - list[n].set(part[1]); - break; - } - } - } - - return true; - } else { - return false; - } - } - - inline virtual bool save(const string &filename) const { - file fp; - if(fp.open(filename, file::mode::write)) { - for(unsigned i = 0; i < list.size(); i++) { - string output; - output.append(list[i].name, " = ", list[i].get()); - if(list[i].desc != "") output.append(" # ", list[i].desc); - output.append("\r\n"); - fp.print(output); - } - - fp.close(); - return true; - } else { - return false; - } - } - }; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/crc32.hpp b/waterbox/libsnes/bsnes/nall/crc32.hpp deleted file mode 100644 index ad36fbf697..0000000000 --- a/waterbox/libsnes/bsnes/nall/crc32.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef NALL_CRC32_HPP -#define NALL_CRC32_HPP - -#include - -namespace nall { - const uint32_t crc32_table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d - }; - - inline uint32_t crc32_adjust(uint32_t crc32, uint8_t input) { - return ((crc32 >> 8) & 0x00ffffff) ^ crc32_table[(crc32 ^ input) & 0xff]; - } - - inline uint32_t crc32_calculate(const uint8_t *data, unsigned length) { - uint32_t crc32 = ~0; - for(unsigned i = 0; i < length; i++) { - crc32 = crc32_adjust(crc32, data[i]); - } - return ~crc32; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/directory.hpp b/waterbox/libsnes/bsnes/nall/directory.hpp deleted file mode 100644 index ff43980396..0000000000 --- a/waterbox/libsnes/bsnes/nall/directory.hpp +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef NALL_DIRECTORY_HPP -#define NALL_DIRECTORY_HPP - -#include -#include -#include -#include - -#if defined(PLATFORM_WINDOWS) - #include -#else - #include - #include - #include -#endif - -namespace nall { - -struct directory { - static bool exists(const string &pathname); - static lstring folders(const string &pathname, const string &pattern = "*"); - static lstring files(const string &pathname, const string &pattern = "*"); - static lstring contents(const string &pathname, const string &pattern = "*"); -}; - -#if defined(PLATFORM_WINDOWS) - inline bool directory::exists(const string &pathname) { - DWORD result = GetFileAttributes(utf16_t(pathname)); - if(result == INVALID_FILE_ATTRIBUTES) return false; - return (result & FILE_ATTRIBUTE_DIRECTORY); - } - - inline lstring directory::folders(const string &pathname, const string &pattern) { - lstring list; - string path = pathname; - path.transform("/", "\\"); - if(!strend(path, "\\")) path.append("\\"); - path.append("*"); - HANDLE handle; - WIN32_FIND_DATA data; - handle = FindFirstFile(utf16_t(path), &data); - if(handle != INVALID_HANDLE_VALUE) { - if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { - if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - string name = (const char*)utf8_t(data.cFileName); - if(wildcard(name, pattern)) list.append(name); - } - } - while(FindNextFile(handle, &data) != false) { - if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { - if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - string name = (const char*)utf8_t(data.cFileName); - if(wildcard(name, pattern)) list.append(name); - } - } - } - FindClose(handle); - } - if(list.size() > 0) list.sort(); - for(auto &name : list) name.append("/"); //must append after sorting - return list; - } - - inline lstring directory::files(const string &pathname, const string &pattern) { - lstring list; - string path = pathname; - path.transform("/", "\\"); - if(!strend(path, "\\")) path.append("\\"); - path.append("*"); - HANDLE handle; - WIN32_FIND_DATA data; - handle = FindFirstFile(utf16_t(path), &data); - if(handle != INVALID_HANDLE_VALUE) { - if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { - string name = (const char*)utf8_t(data.cFileName); - if(wildcard(name, pattern)) list.append(name); - } - while(FindNextFile(handle, &data) != false) { - if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { - string name = (const char*)utf8_t(data.cFileName); - if(wildcard(name, pattern)) list.append(name); - } - } - FindClose(handle); - } - if(list.size() > 0) list.sort(); - return list; - } - - inline lstring directory::contents(const string &pathname, const string &pattern) { - lstring folders = directory::folders(pathname); //pattern search of contents() should only filter files - lstring files = directory::files(pathname, pattern); - for(auto &file : files) folders.append(file); - return folders; - } -#else - inline bool directory::exists(const string &pathname) { - DIR *dp = opendir(pathname); - if(!dp) return false; - closedir(dp); - return true; - } - - inline lstring directory::folders(const string &pathname, const string &pattern) { - lstring list; - DIR *dp; - struct dirent *ep; - dp = opendir(pathname); - if(dp) { - while(ep = readdir(dp)) { - if(!strcmp(ep->d_name, ".")) continue; - if(!strcmp(ep->d_name, "..")) continue; - if(ep->d_type & DT_DIR) { - if(wildcard(ep->d_name, pattern)) list.append(ep->d_name); - } - } - closedir(dp); - } - if(list.size() > 0) list.sort(); - for(auto &name : list) name.append("/"); //must append after sorting - return list; - } - - inline lstring directory::files(const string &pathname, const string &pattern) { - lstring list; - DIR *dp; - struct dirent *ep; - dp = opendir(pathname); - if(dp) { - while(ep = readdir(dp)) { - if(!strcmp(ep->d_name, ".")) continue; - if(!strcmp(ep->d_name, "..")) continue; - if((ep->d_type & DT_DIR) == 0) { - if(wildcard(ep->d_name, pattern)) list.append(ep->d_name); - } - } - closedir(dp); - } - if(list.size() > 0) list.sort(); - return list; - } - - inline lstring directory::contents(const string &pathname, const string &pattern) { - lstring folders = directory::folders(pathname); //pattern search of contents() should only filter files - lstring files = directory::files(pathname, pattern); - for(auto &file : files) folders.append(file); - return folders; - } -#endif - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/dl.hpp b/waterbox/libsnes/bsnes/nall/dl.hpp deleted file mode 100644 index 3bd7d4d2b8..0000000000 --- a/waterbox/libsnes/bsnes/nall/dl.hpp +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef NALL_DL_HPP -#define NALL_DL_HPP - -//dynamic linking support - -#include -#include -#include -#include - -#if defined(PLATFORM_X) || defined(PLATFORM_OSX) - #include -#elif defined(PLATFORM_WINDOWS) - #include - #include -#endif - -namespace nall { - struct library { - bool opened() const { return handle; } - bool open(const char*, const char* = ""); - bool open_absolute(const char*); - void* sym(const char*); - void close(); - - library() : handle(0) {} - ~library() { close(); } - - library& operator=(const library&) = delete; - library(const library&) = delete; - - private: - uintptr_t handle; - }; - - #if defined(PLATFORM_X) - inline bool library::open(const char *name, const char *path) { - if(handle) close(); - handle = (uintptr_t)dlopen(string(path, *path && !strend(path, "/") ? "/" : "", "lib", name, ".so"), RTLD_LAZY); - if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".so"), RTLD_LAZY); - return handle; - } - - inline bool library::open_absolute(const char *name) { - if(handle) close(); - handle = (uintptr_t)dlopen(name, RTLD_LAZY); - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return 0; - return dlsym((void*)handle, name); - } - - inline void library::close() { - if(!handle) return; - dlclose((void*)handle); - handle = 0; - } - #elif defined(PLATFORM_OSX) - inline bool library::open(const char *name, const char *path) { - if(handle) close(); - handle = (uintptr_t)dlopen(string(path, *path && !strend(path, "/") ? "/" : "", "lib", name, ".dylib"), RTLD_LAZY); - if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".dylib"), RTLD_LAZY); - return handle; - } - - inline bool library::open_absolute(const char *name) { - if(handle) close(); - handle = (uintptr_t)dlopen(name, RTLD_LAZY); - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return 0; - return dlsym((void*)handle, name); - } - - inline void library::close() { - if(!handle) return; - dlclose((void*)handle); - handle = 0; - } - #elif defined(PLATFORM_WINDOWS) - inline bool library::open(const char *name, const char *path) { - if(handle) close(); - string filepath(path, *path && !strend(path, "/") && !strend(path, "\\") ? "\\" : "", name, ".dll"); - handle = (uintptr_t)LoadLibraryW(utf16_t(filepath)); - return handle; - } - - inline bool library::open_absolute(const char *name) { - if(handle) close(); - handle = (uintptr_t)LoadLibraryW(utf16_t(name)); - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return 0; - return (void*)GetProcAddress((HMODULE)handle, name); - } - - inline void library::close() { - if(!handle) return; - FreeLibrary((HMODULE)handle); - handle = 0; - } - #else - inline bool library::open(const char*, const char*) { return false; } - inline void* library::sym(const char*) { return 0; } - inline void library::close() {} - #endif -}; - -#endif diff --git a/waterbox/libsnes/bsnes/nall/dsp.hpp b/waterbox/libsnes/bsnes/nall/dsp.hpp deleted file mode 100644 index a2400ec74e..0000000000 --- a/waterbox/libsnes/bsnes/nall/dsp.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef NALL_DSP_HPP -#define NALL_DSP_HPP - -#include -#ifdef __SSE__ - #include -#endif - -#define NALL_DSP_INTERNAL_HPP -#include -#undef NALL_DSP_INTERNAL_HPP - -#endif diff --git a/waterbox/libsnes/bsnes/nall/dsp/buffer.hpp b/waterbox/libsnes/bsnes/nall/dsp/buffer.hpp deleted file mode 100644 index 58632d2f83..0000000000 --- a/waterbox/libsnes/bsnes/nall/dsp/buffer.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -struct Buffer { - double **sample; - uint16_t rdoffset; - uint16_t wroffset; - unsigned channels; - - void setChannels(unsigned channels) { - for(unsigned c = 0; c < this->channels; c++) { - if(sample[c]) abort(); - } - if(sample) abort(); - - this->channels = channels; - if(channels == 0) return; - - sample = (double**)alloc_invisible(channels * sizeof(*sample)); - for(unsigned c = 0; c < channels; c++) { - sample[c] = (double*)alloc_invisible(65536 * sizeof(**sample)); - } - } - - inline double& read(unsigned channel, signed offset = 0) { - return sample[channel][(uint16_t)(rdoffset + offset)]; - } - - inline double& write(unsigned channel, signed offset = 0) { - return sample[channel][(uint16_t)(wroffset + offset)]; - } - - inline void clear() { - for(unsigned c = 0; c < channels; c++) { - for(unsigned n = 0; n < 65536; n++) { - sample[c][n] = 0; - } - } - rdoffset = 0; - wroffset = 0; - } - - Buffer() { - channels = 0; - } - - ~Buffer() { - setChannels(0); - } -}; - -#endif diff --git a/waterbox/libsnes/bsnes/nall/dsp/core.hpp b/waterbox/libsnes/bsnes/nall/dsp/core.hpp deleted file mode 100644 index a7683db6e1..0000000000 --- a/waterbox/libsnes/bsnes/nall/dsp/core.hpp +++ /dev/null @@ -1,168 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -#include -#include -#include - -namespace nall { - -//precision: can be float, double or long double -#define real float - -struct DSP; - -struct Resampler { - DSP &dsp; - real frequency; - - virtual void setFrequency() = 0; - virtual void clear() = 0; - virtual void sample() = 0; - Resampler(DSP &dsp) : dsp(dsp) {} -}; - -struct DSP { - enum class ResampleEngine : unsigned { - Nearest, - Linear, - Cosine, - Cubic, - Hermite, - Average, - Sinc, - }; - - inline void setChannels(unsigned channels); - inline void setPrecision(unsigned precision); - inline void setFrequency(real frequency); //inputFrequency - inline void setVolume(real volume); - inline void setBalance(real balance); - - inline void setResampler(ResampleEngine resamplingEngine); - inline void setResamplerFrequency(real frequency); //outputFrequency - - inline void sample(signed channel[]); - inline bool pending(); - inline void read(signed channel[]); - - inline void clear(); - inline DSP(); - inline ~DSP(); - -protected: - friend class ResampleNearest; - friend class ResampleLinear; - friend class ResampleCosine; - friend class ResampleCubic; - friend class ResampleAverage; - friend class ResampleHermite; - friend class ResampleSinc; - - struct Settings { - unsigned channels; - unsigned precision; - real frequency; - real volume; - real balance; - - //internal - real intensity; - real intensityInverse; - } settings; - - Resampler *resampler; - inline void write(real channel[]); - - #include "buffer.hpp" - Buffer buffer; - Buffer output; - - inline void adjustVolume(); - inline void adjustBalance(); - inline signed clamp(const unsigned bits, const signed x); -}; - -#include "resample/nearest.hpp" -#include "resample/linear.hpp" -#include "resample/cosine.hpp" -#include "resample/cubic.hpp" -#include "resample/hermite.hpp" -#include "resample/average.hpp" -#include "resample/sinc.hpp" -#include "settings.hpp" - -void DSP::sample(signed channel[]) { - for(unsigned c = 0; c < settings.channels; c++) { - buffer.write(c) = (real)channel[c] * settings.intensityInverse; - } - buffer.wroffset++; - resampler->sample(); -} - -bool DSP::pending() { - return output.rdoffset != output.wroffset; -} - -void DSP::read(signed channel[]) { - adjustVolume(); - adjustBalance(); - - for(unsigned c = 0; c < settings.channels; c++) { - channel[c] = clamp(settings.precision, output.read(c) * settings.intensity); - } - output.rdoffset++; -} - -void DSP::write(real channel[]) { - for(unsigned c = 0; c < settings.channels; c++) { - output.write(c) = channel[c]; - } - output.wroffset++; -} - -void DSP::adjustVolume() { - for(unsigned c = 0; c < settings.channels; c++) { - output.read(c) *= settings.volume; - } -} - -void DSP::adjustBalance() { - if(settings.channels != 2) return; //TODO: support > 2 channels - if(settings.balance < 0.0) output.read(1) *= 1.0 + settings.balance; - if(settings.balance > 0.0) output.read(0) *= 1.0 - settings.balance; -} - -signed DSP::clamp(const unsigned bits, const signed x) { - const signed b = 1U << (bits - 1); - const signed m = (1U << (bits - 1)) - 1; - return (x > m) ? m : (x < -b) ? -b : x; -} - -void DSP::clear() { - buffer.clear(); - output.clear(); - resampler->clear(); -} - -DSP::DSP() { - setResampler(ResampleEngine::Hermite); - setResamplerFrequency(44100.0); - - setChannels(2); - setPrecision(16); - setFrequency(44100.0); - setVolume(1.0); - setBalance(0.0); - - clear(); -} - -DSP::~DSP() { - if(resampler) delete resampler; -} - -#undef real - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/dsp/resample/average.hpp b/waterbox/libsnes/bsnes/nall/dsp/resample/average.hpp deleted file mode 100644 index f584e3731f..0000000000 --- a/waterbox/libsnes/bsnes/nall/dsp/resample/average.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -struct ResampleAverage : Resampler { - inline void setFrequency(); - inline void clear(); - inline void sample(); - inline void sampleLinear(); - ResampleAverage(DSP &dsp) : Resampler(dsp) {} - - real fraction; - real step; -}; - -void ResampleAverage::setFrequency() { - fraction = 0.0; - step = dsp.settings.frequency / frequency; -} - -void ResampleAverage::clear() { - fraction = 0.0; -} - -void ResampleAverage::sample() { - //can only average if input frequency >= output frequency - if(step < 1.0) return sampleLinear(); - - fraction += 1.0; - - real scalar = 1.0; - if(fraction > step) scalar = 1.0 - (fraction - step); - - for(unsigned c = 0; c < dsp.settings.channels; c++) { - dsp.output.write(c) += dsp.buffer.read(c) * scalar; - } - - if(fraction >= step) { - for(unsigned c = 0; c < dsp.settings.channels; c++) { - dsp.output.write(c) /= step; - } - dsp.output.wroffset++; - - fraction -= step; - for(unsigned c = 0; c < dsp.settings.channels; c++) { - dsp.output.write(c) = dsp.buffer.read(c) * fraction; - } - } - - dsp.buffer.rdoffset++; -} - -void ResampleAverage::sampleLinear() { - while(fraction <= 1.0) { - std::vector channel(dsp.settings.channels); - - for(unsigned n = 0; n < dsp.settings.channels; n++) { - real a = dsp.buffer.read(n, -1); - real b = dsp.buffer.read(n, -0); - - real mu = fraction; - - channel[n] = a * (1.0 - mu) + b * mu; - } - - dsp.write(channel.data()); - fraction += step; - } - - dsp.buffer.rdoffset++; - fraction -= 1.0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/dsp/resample/cosine.hpp b/waterbox/libsnes/bsnes/nall/dsp/resample/cosine.hpp deleted file mode 100644 index 6120a734b3..0000000000 --- a/waterbox/libsnes/bsnes/nall/dsp/resample/cosine.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -struct ResampleCosine : Resampler { - inline void setFrequency(); - inline void clear(); - inline void sample(); - ResampleCosine(DSP &dsp) : Resampler(dsp) {} - - real fraction; - real step; -}; - -void ResampleCosine::setFrequency() { - fraction = 0.0; - step = dsp.settings.frequency / frequency; -} - -void ResampleCosine::clear() { - fraction = 0.0; -} - -void ResampleCosine::sample() { - while(fraction <= 1.0) { - std::vector channel(dsp.settings.channels); - - - for(unsigned n = 0; n < dsp.settings.channels; n++) { - real a = dsp.buffer.read(n, -1); - real b = dsp.buffer.read(n, -0); - - real mu = fraction; - mu = (1.0 - cos(mu * 3.14159265)) / 2.0; - - channel[n] = a * (1.0 - mu) + b * mu; - } - - dsp.write(channel.data()); - fraction += step; - } - - dsp.buffer.rdoffset++; - fraction -= 1.0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/dsp/resample/cubic.hpp b/waterbox/libsnes/bsnes/nall/dsp/resample/cubic.hpp deleted file mode 100644 index f7f077961c..0000000000 --- a/waterbox/libsnes/bsnes/nall/dsp/resample/cubic.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -struct ResampleCubic : Resampler { - inline void setFrequency(); - inline void clear(); - inline void sample(); - ResampleCubic(DSP &dsp) : Resampler(dsp) {} - - real fraction; - real step; -}; - -void ResampleCubic::setFrequency() { - fraction = 0.0; - step = dsp.settings.frequency / frequency; -} - -void ResampleCubic::clear() { - fraction = 0.0; -} - -void ResampleCubic::sample() { - while(fraction <= 1.0) { - std::vector channel(dsp.settings.channels); - - for(unsigned n = 0; n < dsp.settings.channels; n++) { - real a = dsp.buffer.read(n, -3); - real b = dsp.buffer.read(n, -2); - real c = dsp.buffer.read(n, -1); - real d = dsp.buffer.read(n, -0); - - real mu = fraction; - - real A = d - c - a + b; - real B = a - b - A; - real C = c - a; - real D = b; - - channel[n] = A * (mu * 3) + B * (mu * 2) + C * mu + D; - } - - dsp.write(channel.data()); - fraction += step; - } - - dsp.buffer.rdoffset++; - fraction -= 1.0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/dsp/resample/hermite.hpp b/waterbox/libsnes/bsnes/nall/dsp/resample/hermite.hpp deleted file mode 100644 index 04c57b85c9..0000000000 --- a/waterbox/libsnes/bsnes/nall/dsp/resample/hermite.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -struct ResampleHermite : Resampler { - inline void setFrequency(); - inline void clear(); - inline void sample(); - ResampleHermite(DSP &dsp) : Resampler(dsp) {} - - real fraction; - real step; -}; - -void ResampleHermite::setFrequency() { - fraction = 0.0; - step = dsp.settings.frequency / frequency; -} - -void ResampleHermite::clear() { - fraction = 0.0; -} - -void ResampleHermite::sample() { - while(fraction <= 1.0) { - std::vector channel(dsp.settings.channels); - - for(unsigned n = 0; n < dsp.settings.channels; n++) { - real a = dsp.buffer.read(n, -3); - real b = dsp.buffer.read(n, -2); - real c = dsp.buffer.read(n, -1); - real d = dsp.buffer.read(n, -0); - - const real tension = 0.0; //-1 = low, 0 = normal, +1 = high - const real bias = 0.0; //-1 = left, 0 = even, +1 = right - - real mu1, mu2, mu3, m0, m1, a0, a1, a2, a3; - - mu1 = fraction; - mu2 = mu1 * mu1; - mu3 = mu2 * mu1; - - m0 = (b - a) * (1.0 + bias) * (1.0 - tension) / 2.0; - m0 += (c - b) * (1.0 - bias) * (1.0 - tension) / 2.0; - m1 = (c - b) * (1.0 + bias) * (1.0 - tension) / 2.0; - m1 += (d - c) * (1.0 - bias) * (1.0 - tension) / 2.0; - - a0 = +2 * mu3 - 3 * mu2 + 1; - a1 = mu3 - 2 * mu2 + mu1; - a2 = mu3 - mu2; - a3 = -2 * mu3 + 3 * mu2; - - channel[n] = (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c); - } - - dsp.write(channel.data()); - fraction += step; - } - - dsp.buffer.rdoffset++; - fraction -= 1.0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/dsp/resample/lib/sinc.hpp b/waterbox/libsnes/bsnes/nall/dsp/resample/lib/sinc.hpp deleted file mode 100644 index 449ccee10c..0000000000 --- a/waterbox/libsnes/bsnes/nall/dsp/resample/lib/sinc.hpp +++ /dev/null @@ -1,602 +0,0 @@ -// If these types are changed to anything other than "float", you should comment out the SSE detection directives below -// so that the SSE code is not used. - -typedef float resample_coeff_t; // note: sizeof(resample_coeff_t) must be == to a power of 2, and not larger than 16 -typedef float resample_samp_t; - -#include -#include - -// ...but don't comment this single RESAMPLE_SSEREGPARM define out when disabling SSE. -#define RESAMPLE_SSEREGPARM - -#if defined(__SSE__) - #define SINCRESAMPLE_USE_SSE 1 - #ifndef __x86_64__ - #undef RESAMPLE_SSEREGPARM - #define RESAMPLE_SSEREGPARM __attribute__((sseregparm)) - #endif -#else - // TODO: altivec here -#endif - -namespace ResampleUtility -{ - inline void kaiser_window(double* io, int count, double beta); - inline void gen_sinc(double* out, int size, double cutoff, double kaiser); - inline void gen_sinc_os(double* out, int size, double cutoff, double kaiser); - inline void normalize(double* io, int size, double gain = 1.0); - - inline void* make_aligned(void* ptr, unsigned boundary); // boundary must be a power of 2 -} - -class SincResampleHR -{ - private: - - inline void Init(unsigned ratio_arg, double desired_bandwidth, double beta, double d); - - inline void write(resample_samp_t sample) RESAMPLE_SSEREGPARM; - inline resample_samp_t read(void) RESAMPLE_SSEREGPARM; - inline bool output_avail(void); - - private: - - inline resample_samp_t mac(const resample_samp_t *wave, const resample_coeff_t *coeff, unsigned count); - - unsigned ratio; - unsigned num_convolutions; - - resample_coeff_t *coeffs; - std::vector coeffs_mem; - - // second half of ringbuffer should be copy of first half. - resample_samp_t *rb; - std::vector rb_mem; - - signed rb_readpos; - signed rb_writepos; - signed rb_in; - signed rb_eff_size; - - friend class SincResample; -}; - -class SincResample -{ - public: - - enum - { - QUALITY_LOW = 0, - QUALITY_MEDIUM = 2, - QUALITY_HIGH = 4 - }; - - inline SincResample(double input_rate, double output_rate, double desired_bandwidth, unsigned quality = QUALITY_HIGH); - - inline void write(resample_samp_t sample) RESAMPLE_SSEREGPARM; - inline resample_samp_t read(void) RESAMPLE_SSEREGPARM; - inline bool output_avail(void); - - private: - - inline void Init(double input_rate, double output_rate, double desired_bandwidth, double beta, double d, unsigned pn_nume, unsigned phases_min); - - inline resample_samp_t mac(const resample_samp_t *wave, const resample_coeff_t *coeffs_a, const resample_coeff_t *coeffs_b, const double ffract, unsigned count) RESAMPLE_SSEREGPARM; - - unsigned num_convolutions; - unsigned num_phases; - - unsigned step_int; - double step_fract; - - double input_pos_fract; - - - std::vector coeffs; // Pointers into coeff_mem. - std::vector coeff_mem; - - - std::vector rb; // second half should be copy of first half. - signed rb_readpos; - signed rb_writepos; - signed rb_in; - - bool hr_used; - SincResampleHR hr; -}; - - -// -// Code: -// -//#include "resample.hpp" - -#if 0 -namespace bit -{ - inline unsigned round(unsigned x) { - if((x & (x - 1)) == 0) return x; - while(x & (x - 1)) x &= x - 1; - return x << 1; - } -} -#endif - -void SincResampleHR::Init(unsigned ratio_arg, double desired_bandwidth, double beta, double d) -{ - const unsigned align_boundary = 16; - std::vector coeffs_tmp; - double cutoff; // 1.0 = f/2 - - ratio = ratio_arg; - - //num_convolutions = ((unsigned)ceil(d / ((1.0 - desired_bandwidth) / ratio)) + 1) &~ 1; // round up to be even - num_convolutions = ((unsigned)ceil(d / ((1.0 - desired_bandwidth) / ratio)) | 1); - - cutoff = (1.0 / ratio) - (d / num_convolutions); - -//printf("%d %d %.20f\n", ratio, num_convolutions, cutoff); - assert(num_convolutions > ratio); - - - // Generate windowed sinc of POWER - coeffs_tmp.resize(num_convolutions); - //ResampleUtility::gen_sinc(&coeffs_tmp[0], num_convolutions, cutoff, beta); - ResampleUtility::gen_sinc_os(&coeffs_tmp[0], num_convolutions, cutoff, beta); - ResampleUtility::normalize(&coeffs_tmp[0], num_convolutions); - - // Copy from coeffs_tmp to coeffs~ - // We multiply many coefficients at a time in the mac loop, so make sure the last few that don't really - // exist are allocated, zero'd mem. - - coeffs_mem.resize(((num_convolutions + 7) &~ 7) * sizeof(resample_coeff_t) + (align_boundary - 1)); - coeffs = (resample_coeff_t *)ResampleUtility::make_aligned(&coeffs_mem[0], align_boundary); - - - for(unsigned i = 0; i < num_convolutions; i++) - coeffs[i] = coeffs_tmp[i]; - - rb_eff_size = nall::bit::round(num_convolutions * 2) >> 1; - rb_readpos = 0; - rb_writepos = 0; - rb_in = 0; - - rb_mem.resize(rb_eff_size * 2 * sizeof(resample_samp_t) + (align_boundary - 1)); - rb = (resample_samp_t *)ResampleUtility::make_aligned(&rb_mem[0], align_boundary); -} - - -inline bool SincResampleHR::output_avail(void) -{ - return(rb_in >= (signed)num_convolutions); -} - -inline void SincResampleHR::write(resample_samp_t sample) -{ - assert(!output_avail()); - - rb[rb_writepos] = sample; - rb[rb_writepos + rb_eff_size] = sample; - rb_writepos = (rb_writepos + 1) & (rb_eff_size - 1); - rb_in++; -} - -resample_samp_t SincResampleHR::mac(const resample_samp_t *wave, const resample_coeff_t *coeff, unsigned count) -{ -#if SINCRESAMPLE_USE_SSE - __m128 accum_veca[2] = { _mm_set1_ps(0), _mm_set1_ps(0) }; - - resample_samp_t accum; - - for(unsigned c = 0; c < count; c += 8) - { - for(unsigned i = 0; i < 2; i++) - { - __m128 co[2]; - __m128 w[2]; - - co[i] = _mm_load_ps(&coeff[c + i * 4]); - w[i] = _mm_load_ps(&wave[c + i * 4]); - - w[i] = _mm_mul_ps(w[i], co[i]); - - accum_veca[i] = _mm_add_ps(w[i], accum_veca[i]); - } - } - - __m128 accum_vec = _mm_add_ps(accum_veca[0], accum_veca[1]); //_mm_add_ps(_mm_add_ps(accum_veca[0], accum_veca[1]), _mm_add_ps(accum_veca[2], accum_veca[3])); - - accum_vec = _mm_add_ps(accum_vec, _mm_shuffle_ps(accum_vec, accum_vec, (3 << 0) | (2 << 2) | (1 << 4) | (0 << 6))); - accum_vec = _mm_add_ps(accum_vec, _mm_shuffle_ps(accum_vec, accum_vec, (1 << 0) | (0 << 2) | (1 << 4) | (0 << 6))); - - _mm_store_ss(&accum, accum_vec); - - return accum; -#else - resample_samp_t accum[4] = { 0, 0, 0, 0 }; - - for(unsigned c = 0; c < count; c+= 4) - { - accum[0] += wave[c + 0] * coeff[c + 0]; - accum[1] += wave[c + 1] * coeff[c + 1]; - accum[2] += wave[c + 2] * coeff[c + 2]; - accum[3] += wave[c + 3] * coeff[c + 3]; - } - - return (accum[0] + accum[1]) + (accum[2] + accum[3]); // don't mess with parentheses(assuming compiler doesn't already, which it may... - -#endif -} - - -resample_samp_t SincResampleHR::read(void) -{ - assert(output_avail()); - resample_samp_t ret; - - ret = mac(&rb[rb_readpos], &coeffs[0], num_convolutions); - - rb_readpos = (rb_readpos + ratio) & (rb_eff_size - 1); - rb_in -= ratio; - - return ret; -} - - -SincResample::SincResample(double input_rate, double output_rate, double desired_bandwidth, unsigned quality) -{ - const struct - { - double beta; - double d; - unsigned pn_nume; - unsigned phases_min; - } qtab[5] = - { - { 5.658, 3.62, 4096, 4 }, - { 6.764, 4.32, 8192, 4 }, - { 7.865, 5.0, 16384, 8 }, - { 8.960, 5.7, 32768, 16 }, - { 10.056, 6.4, 65536, 32 } - }; - - // Sanity checks - assert(ceil(input_rate) > 0); - assert(ceil(output_rate) > 0); - assert(ceil(input_rate / output_rate) <= 1024); - assert(ceil(output_rate / input_rate) <= 1024); - - // The simplistic number-of-phases calculation code doesn't work well enough for when desired_bandwidth is close to 1.0 and when - // upsampling. - assert(desired_bandwidth >= 0.25 && desired_bandwidth < 0.96); - assert(quality >= 0 && quality <= 4); - - hr_used = false; - -#if 1 - // Round down to the nearest multiple of 4(so wave buffer remains aligned) - // It also adjusts the effective intermediate sampling rate up slightly, so that the upper frequencies below f/2 - // aren't overly attenuated so much. In the future, we might want to do an FFT or something to choose the intermediate rate more accurately - // to virtually eliminate over-attenuation. - unsigned ioratio_rd = (unsigned)floor(input_rate / (output_rate * (1.0 + (1.0 - desired_bandwidth) / 2) )) & ~3; - - if(ioratio_rd >= 8) - { - hr.Init(ioratio_rd, desired_bandwidth, qtab[quality].beta, qtab[quality].d); //10.056, 6.4); - hr_used = true; - - input_rate /= ioratio_rd; - } -#endif - - Init(input_rate, output_rate, desired_bandwidth, qtab[quality].beta, qtab[quality].d, qtab[quality].pn_nume, qtab[quality].phases_min); -} - -void SincResample::Init(double input_rate, double output_rate, double desired_bandwidth, double beta, double d, unsigned pn_nume, unsigned phases_min) -{ - const unsigned max_mult_atatime = 8; // multiply "granularity". must be power of 2. - const unsigned max_mult_minus1 = (max_mult_atatime - 1); - const unsigned conv_alignment_bytes = 16; // must be power of 2 - const double input_to_output_ratio = input_rate / output_rate; - const double output_to_input_ratio = output_rate / input_rate; - double cutoff; // 1.0 = input_rate / 2 - std::vector coeff_init_buffer; - - // Round up num_convolutions to be even. - if(output_rate > input_rate) - num_convolutions = ((unsigned)ceil(d / (1.0 - desired_bandwidth)) + 1) & ~1; - else - num_convolutions = ((unsigned)ceil(d / (output_to_input_ratio * (1.0 - desired_bandwidth))) + 1) & ~1; - - if(output_rate > input_rate) // Upsampling - cutoff = desired_bandwidth; - else // Downsampling - cutoff = output_to_input_ratio * desired_bandwidth; - - // Round up to be even. - num_phases = (std::max(pn_nume / num_convolutions, phases_min) + 1) &~1; - - // Adjust cutoff to account for the multiple phases. - cutoff = cutoff / num_phases; - - assert((num_convolutions & 1) == 0); - assert((num_phases & 1) == 0); - -// fprintf(stderr, "num_convolutions=%u, num_phases=%u, total expected coeff byte size=%lu\n", num_convolutions, num_phases, -// (long)((num_phases + 2) * ((num_convolutions + max_mult_minus1) & ~max_mult_minus1) * sizeof(float) + conv_alignment_bytes)); - - coeff_init_buffer.resize(num_phases * num_convolutions); - - coeffs.resize(num_phases + 1 + 1); - - coeff_mem.resize((num_phases + 1 + 1) * ((num_convolutions + max_mult_minus1) &~ max_mult_minus1) * sizeof(resample_coeff_t) + conv_alignment_bytes); - - // Assign aligned pointers into coeff_mem - { - resample_coeff_t *base_ptr = (resample_coeff_t *)ResampleUtility::make_aligned(&coeff_mem[0], conv_alignment_bytes); - - for(unsigned phase = 0; phase < (num_phases + 1 + 1); phase++) - { - coeffs[phase] = base_ptr + (((num_convolutions + max_mult_minus1) & ~max_mult_minus1) * phase); - } - } - - ResampleUtility::gen_sinc(&coeff_init_buffer[0], num_phases * num_convolutions, cutoff, beta); - ResampleUtility::normalize(&coeff_init_buffer[0], num_phases * num_convolutions, num_phases); - - // Reorder coefficients to allow for more efficient convolution. - for(int phase = -1; phase < ((int)num_phases + 1); phase++) - { - for(int conv = 0; conv < (int)num_convolutions; conv++) - { - double coeff; - - if(phase == -1 && conv == 0) - coeff = 0; - else if(phase == (int)num_phases && conv == ((int)num_convolutions - 1)) - coeff = 0; - else - coeff = coeff_init_buffer[conv * num_phases + phase]; - - coeffs[phase + 1][conv] = coeff; - } - } - - // Free a bit of mem - coeff_init_buffer.resize(0); - - step_int = floor(input_to_output_ratio); - step_fract = input_to_output_ratio - step_int; - - input_pos_fract = 0; - - // Do NOT use rb.size() later in the code, since it'll include the padding. - // We should only need one "max_mult_minus1" here, not two, since it won't matter if it over-reads(due to doing "max_mult_atatime" multiplications at a time - // rather than just 1, in which case this over-read wouldn't happen), from the first half into the duplicated half, - // since those corresponding coefficients will be zero anyway; this is just to handle the case of reading off the end of the duplicated half to - // prevent illegal memory accesses. - rb.resize(num_convolutions * 2 + max_mult_minus1); - - rb_readpos = 0; - rb_writepos = 0; - rb_in = 0; -} - -resample_samp_t SincResample::mac(const resample_samp_t *wave, const resample_coeff_t *coeffs_a, const resample_coeff_t *coeffs_b, const double ffract, unsigned count) -{ - resample_samp_t accum = 0; -#if SINCRESAMPLE_USE_SSE - __m128 accum_vec_a[2] = { _mm_set1_ps(0), _mm_set1_ps(0) }; - __m128 accum_vec_b[2] = { _mm_set1_ps(0), _mm_set1_ps(0) }; - - for(unsigned c = 0; c < count; c += 8) //8) //4) - { - __m128 coeff_a[2]; - __m128 coeff_b[2]; - __m128 w[2]; - __m128 result_a[2], result_b[2]; - - for(unsigned i = 0; i < 2; i++) - { - coeff_a[i] = _mm_load_ps(&coeffs_a[c + (i * 4)]); - coeff_b[i] = _mm_load_ps(&coeffs_b[c + (i * 4)]); - w[i] = _mm_loadu_ps(&wave[c + (i * 4)]); - - result_a[i] = _mm_mul_ps(coeff_a[i], w[i]); - result_b[i] = _mm_mul_ps(coeff_b[i], w[i]); - - accum_vec_a[i] = _mm_add_ps(result_a[i], accum_vec_a[i]); - accum_vec_b[i] = _mm_add_ps(result_b[i], accum_vec_b[i]); - } - } - - __m128 accum_vec, av_a, av_b; - __m128 mult_a_vec = _mm_set1_ps(1.0 - ffract); - __m128 mult_b_vec = _mm_set1_ps(ffract); - - av_a = _mm_mul_ps(mult_a_vec, /*accum_vec_a[0]);*/ _mm_add_ps(accum_vec_a[0], accum_vec_a[1])); - av_b = _mm_mul_ps(mult_b_vec, /*accum_vec_b[0]);*/ _mm_add_ps(accum_vec_b[0], accum_vec_b[1])); - - accum_vec = _mm_add_ps(av_a, av_b); - - accum_vec = _mm_add_ps(accum_vec, _mm_shuffle_ps(accum_vec, accum_vec, (3 << 0) | (2 << 2) | (1 << 4) | (0 << 6))); - accum_vec = _mm_add_ps(accum_vec, _mm_shuffle_ps(accum_vec, accum_vec, (1 << 0) | (0 << 2) | (1 << 4) | (0 << 6))); - - _mm_store_ss(&accum, accum_vec); -#else - resample_coeff_t mult_a = 1.0 - ffract; - resample_coeff_t mult_b = ffract; - - for(unsigned c = 0; c < count; c += 4) - { - accum += wave[c + 0] * (coeffs_a[c + 0] * mult_a + coeffs_b[c + 0] * mult_b); - accum += wave[c + 1] * (coeffs_a[c + 1] * mult_a + coeffs_b[c + 1] * mult_b); - accum += wave[c + 2] * (coeffs_a[c + 2] * mult_a + coeffs_b[c + 2] * mult_b); - accum += wave[c + 3] * (coeffs_a[c + 3] * mult_a + coeffs_b[c + 3] * mult_b); - } -#endif - - return accum; -} - -inline bool SincResample::output_avail(void) -{ - return(rb_in >= (int)num_convolutions); -} - -resample_samp_t SincResample::read(void) -{ - assert(output_avail()); - double phase = input_pos_fract * num_phases - 0.5; - signed phase_int = (signed)floor(phase); - double phase_fract = phase - phase_int; - unsigned phase_a = num_phases - 1 - phase_int; - unsigned phase_b = phase_a - 1; - resample_samp_t ret; - - ret = mac(&rb[rb_readpos], &coeffs[phase_a + 1][0], &coeffs[phase_b + 1][0], phase_fract, num_convolutions); - - unsigned int_increment = step_int; - - input_pos_fract += step_fract; - int_increment += floor(input_pos_fract); - input_pos_fract -= floor(input_pos_fract); - - rb_readpos = (rb_readpos + int_increment) % num_convolutions; - rb_in -= int_increment; - - return ret; -} - -inline void SincResample::write(resample_samp_t sample) -{ - assert(!output_avail()); - - if(hr_used) - { - hr.write(sample); - - if(hr.output_avail()) - { - sample = hr.read(); - } - else - { - return; - } - } - - rb[rb_writepos + 0 * num_convolutions] = sample; - rb[rb_writepos + 1 * num_convolutions] = sample; - rb_writepos = (rb_writepos + 1) % num_convolutions; - rb_in++; -} - -void ResampleUtility::kaiser_window( double* io, int count, double beta) -{ - int const accuracy = 24; //16; //12; - - double* end = io + count; - - double beta2 = beta * beta * (double) -0.25; - double to_fract = beta2 / ((double) count * count); - double i = 0; - double rescale = 0; // Doesn't need an initializer, to shut up gcc - - for ( ; io < end; ++io, i += 1 ) - { - double x = i * i * to_fract - beta2; - double u = x; - double k = x + 1; - - double n = 2; - do - { - u *= x / (n * n); - n += 1; - k += u; - } - while ( k <= u * (1 << accuracy) ); - - if ( !i ) - rescale = 1 / k; // otherwise values get large - - *io *= k * rescale; - } -} - -void ResampleUtility::gen_sinc(double* out, int size, double cutoff, double kaiser) -{ - assert( size % 2 == 0 ); // size must be even - - int const half_size = size / 2; - double* const mid = &out [half_size]; - - // Generate right half of sinc - for ( int i = 0; i < half_size; i++ ) - { - double angle = (i * 2 + 1) * (M_PI / 2); - mid [i] = sin( angle * cutoff ) / angle; - } - - kaiser_window( mid, half_size, kaiser ); - - // Mirror for left half - for ( int i = 0; i < half_size; i++ ) - out [i] = mid [half_size - 1 - i]; -} - -void ResampleUtility::gen_sinc_os(double* out, int size, double cutoff, double kaiser) -{ - assert( size % 2 == 1); // size must be odd - - for(int i = 0; i < size; i++) - { - if(i == (size / 2)) - out[i] = 2 * M_PI * (cutoff / 2); //0.078478; //1.0; //sin(2 * M_PI * (cutoff / 2) * (i - size / 2)) / (i - (size / 2)); - else - out[i] = sin(2 * M_PI * (cutoff / 2) * (i - size / 2)) / (i - (size / 2)); - -// out[i] *= 0.3635819 - 0.4891775 * cos(2 * M_PI * i / (size - 1)) + 0.1365995 * cos(4 * M_PI * i / (size - 1)) - 0.0106411 * cos(6 * M_PI * i / (size - 1)); -//0.42 - 0.5 * cos(2 * M_PI * i / (size - 1)) + 0.08 * cos(4 * M_PI * i / (size - 1)); - -// printf("%d %f\n", i, out[i]); - } - - kaiser_window(&out[size / 2], size / 2 + 1, kaiser); - - // Mirror for left half - for ( int i = 0; i < size / 2; i++ ) - out [i] = out [size - 1 - i]; - -} - -void ResampleUtility::normalize(double* io, int size, double gain) -{ - double sum = 0; - for ( int i = 0; i < size; i++ ) - sum += io [i]; - - double scale = gain / sum; - for ( int i = 0; i < size; i++ ) - io [i] *= scale; -} - -void* ResampleUtility::make_aligned(void* ptr, unsigned boundary) -{ - unsigned char* null_ptr = (unsigned char *)NULL; - unsigned char* uc_ptr = (unsigned char *)ptr; - - uc_ptr += (boundary - ((uc_ptr - null_ptr) & (boundary - 1))) & (boundary - 1); - - //while((uc_ptr - null_ptr) & (boundary - 1)) - // uc_ptr++; - - //printf("%16llx %16llx\n", (unsigned long long)ptr, (unsigned long long)uc_ptr); - - assert((uc_ptr - (unsigned char *)ptr) < boundary && (uc_ptr >= (unsigned char *)ptr)); - - return uc_ptr; -} diff --git a/waterbox/libsnes/bsnes/nall/dsp/resample/linear.hpp b/waterbox/libsnes/bsnes/nall/dsp/resample/linear.hpp deleted file mode 100644 index 34e06ae440..0000000000 --- a/waterbox/libsnes/bsnes/nall/dsp/resample/linear.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -struct ResampleLinear : Resampler { - inline void setFrequency(); - inline void clear(); - inline void sample(); - ResampleLinear(DSP &dsp) : Resampler(dsp) {} - - real fraction; - real step; -}; - -void ResampleLinear::setFrequency() { - fraction = 0.0; - step = dsp.settings.frequency / frequency; -} - -void ResampleLinear::clear() { - fraction = 0.0; -} - -void ResampleLinear::sample() { - while(fraction <= 1.0) { - std::vector channel(dsp.settings.channels); - - for(unsigned n = 0; n < dsp.settings.channels; n++) { - real a = dsp.buffer.read(n, -1); - real b = dsp.buffer.read(n, -0); - - real mu = fraction; - - channel[n] = a * (1.0 - mu) + b * mu; - } - - dsp.write(channel.data()); - fraction += step; - } - - dsp.buffer.rdoffset++; - fraction -= 1.0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/dsp/resample/nearest.hpp b/waterbox/libsnes/bsnes/nall/dsp/resample/nearest.hpp deleted file mode 100644 index 73df9f7d91..0000000000 --- a/waterbox/libsnes/bsnes/nall/dsp/resample/nearest.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -struct ResampleNearest : Resampler { - inline void setFrequency(); - inline void clear(); - inline void sample(); - ResampleNearest(DSP &dsp) : Resampler(dsp) {} - - real fraction; - real step; -}; - -void ResampleNearest::setFrequency() { - fraction = 0.0; - step = dsp.settings.frequency / frequency; -} - -void ResampleNearest::clear() { - fraction = 0.0; -} - -void ResampleNearest::sample() { - while(fraction <= 1.0) { - std::vector channel(dsp.settings.channels); - - for(unsigned n = 0; n < dsp.settings.channels; n++) { - real a = dsp.buffer.read(n, -1); - real b = dsp.buffer.read(n, -0); - - real mu = fraction; - - channel[n] = mu < 0.5 ? a : b; - } - - dsp.write(channel.data()); - fraction += step; - } - - dsp.buffer.rdoffset++; - fraction -= 1.0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/dsp/resample/sinc.hpp b/waterbox/libsnes/bsnes/nall/dsp/resample/sinc.hpp deleted file mode 100644 index a77a1eeb82..0000000000 --- a/waterbox/libsnes/bsnes/nall/dsp/resample/sinc.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -#include "lib/sinc.hpp" - -struct ResampleSinc : Resampler { - inline void setFrequency(); - inline void clear(); - inline void sample(); - inline ResampleSinc(DSP &dsp); - -private: - inline void remakeSinc(); - SincResample *sinc_resampler[8]; -}; - -void ResampleSinc::setFrequency() { - remakeSinc(); -} - -void ResampleSinc::clear() { - remakeSinc(); -} - -void ResampleSinc::sample() { - for(unsigned c = 0; c < dsp.settings.channels; c++) { - sinc_resampler[c]->write(dsp.buffer.read(c)); - } - - if(sinc_resampler[0]->output_avail()) { - do { - for(unsigned c = 0; c < dsp.settings.channels; c++) { - dsp.output.write(c) = sinc_resampler[c]->read(); - } - dsp.output.wroffset++; - } while(sinc_resampler[0]->output_avail()); - } - - dsp.buffer.rdoffset++; -} - -ResampleSinc::ResampleSinc(DSP &dsp) : Resampler(dsp) { - for(unsigned n = 0; n < 8; n++) sinc_resampler[n] = 0; -} - -void ResampleSinc::remakeSinc() { - assert(dsp.settings.channels < 8); - - for(unsigned c = 0; c < dsp.settings.channels; c++) { - if(sinc_resampler[c]) delete sinc_resampler[c]; - sinc_resampler[c] = new SincResample(dsp.settings.frequency, frequency, 0.85, SincResample::QUALITY_HIGH); - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/dsp/settings.hpp b/waterbox/libsnes/bsnes/nall/dsp/settings.hpp deleted file mode 100644 index 3a8f24c621..0000000000 --- a/waterbox/libsnes/bsnes/nall/dsp/settings.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -void DSP::setChannels(unsigned channels) { - assert(channels > 0); - buffer.setChannels(channels); - output.setChannels(channels); - settings.channels = channels; -} - -void DSP::setPrecision(unsigned precision) { - settings.precision = precision; - settings.intensity = 1 << (settings.precision - 1); - settings.intensityInverse = 1.0 / settings.intensity; -} - -void DSP::setFrequency(real frequency) { - settings.frequency = frequency; - resampler->setFrequency(); -} - -void DSP::setVolume(real volume) { - settings.volume = volume; -} - -void DSP::setBalance(real balance) { - settings.balance = balance; -} - -void DSP::setResampler(ResampleEngine engine) { - if(resampler) delete resampler; - - switch(engine) { - case ResampleEngine::Nearest: resampler = new ResampleNearest(*this); return; - case ResampleEngine::Linear: resampler = new ResampleLinear (*this); return; - case ResampleEngine::Cosine: resampler = new ResampleCosine (*this); return; - case ResampleEngine::Cubic: resampler = new ResampleCubic (*this); return; - case ResampleEngine::Hermite: resampler = new ResampleHermite(*this); return; - case ResampleEngine::Average: resampler = new ResampleAverage(*this); return; - case ResampleEngine::Sinc: resampler = new ResampleSinc (*this); return; - } - - throw; -} - -void DSP::setResamplerFrequency(real frequency) { - resampler->frequency = frequency; - resampler->setFrequency(); -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/endian.hpp b/waterbox/libsnes/bsnes/nall/endian.hpp deleted file mode 100644 index 1f834b5b9c..0000000000 --- a/waterbox/libsnes/bsnes/nall/endian.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef NALL_ENDIAN_HPP -#define NALL_ENDIAN_HPP - -#include - -#if defined(ENDIAN_LSB) - //little-endian: uint8_t[] { 0x01, 0x02, 0x03, 0x04 } == 0x04030201 - #define order_lsb2(a,b) a,b - #define order_lsb3(a,b,c) a,b,c - #define order_lsb4(a,b,c,d) a,b,c,d - #define order_lsb5(a,b,c,d,e) a,b,c,d,e - #define order_lsb6(a,b,c,d,e,f) a,b,c,d,e,f - #define order_lsb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g - #define order_lsb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h - #define order_msb2(a,b) b,a - #define order_msb3(a,b,c) c,b,a - #define order_msb4(a,b,c,d) d,c,b,a - #define order_msb5(a,b,c,d,e) e,d,c,b,a - #define order_msb6(a,b,c,d,e,f) f,e,d,c,b,a - #define order_msb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a - #define order_msb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a -#elif defined(ENDIAN_MSB) - //big-endian: uint8_t[] { 0x01, 0x02, 0x03, 0x04 } == 0x01020304 - #define order_lsb2(a,b) b,a - #define order_lsb3(a,b,c) c,b,a - #define order_lsb4(a,b,c,d) d,c,b,a - #define order_lsb5(a,b,c,d,e) e,d,c,b,a - #define order_lsb6(a,b,c,d,e,f) f,e,d,c,b,a - #define order_lsb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a - #define order_lsb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a - #define order_msb2(a,b) a,b - #define order_msb3(a,b,c) a,b,c - #define order_msb4(a,b,c,d) a,b,c,d - #define order_msb5(a,b,c,d,e) a,b,c,d,e - #define order_msb6(a,b,c,d,e,f) a,b,c,d,e,f - #define order_msb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g - #define order_msb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h -#else - #error "Unknown endian. Please specify in nall/intrinsics.hpp" -#endif - -#endif diff --git a/waterbox/libsnes/bsnes/nall/file.hpp b/waterbox/libsnes/bsnes/nall/file.hpp deleted file mode 100644 index 910f284c14..0000000000 --- a/waterbox/libsnes/bsnes/nall/file.hpp +++ /dev/null @@ -1,291 +0,0 @@ -#ifndef NALL_FILE_HPP -#define NALL_FILE_HPP - -#include -#include -#include -#include -#include - -namespace nall { - inline FILE* fopen_utf8(const string &utf8_filename, const char *mode) { - #if !defined(_WIN32) - return fopen(utf8_filename, mode); - #else - return _wfopen(utf16_t(utf8_filename), utf16_t(mode)); - #endif - } - - class file { - public: - enum class mode : unsigned { read, write, readwrite, writeread }; - enum class index : unsigned { absolute, relative }; - enum class time : unsigned { create, modify, access }; - - static bool read(const string &filename, uint8_t *&data, unsigned &size) { - data = 0; - file fp; - if(fp.open(filename, mode::read) == false) return false; - size = fp.size(); - data = new uint8_t[size]; - fp.read(data, size); - fp.close(); - return true; - } - - static bool read(const string &filename, const uint8_t *&data, unsigned &size) { - return file::read(filename, (uint8_t*&)data, size); - } - - static bool write(const string &filename, const uint8_t *data, unsigned size) { - file fp; - if(fp.open(filename, mode::write) == false) return false; - fp.write(data, size); - fp.close(); - return true; - } - - uint8_t read() { - if(!fp) return 0xff; //file not open - if(file_mode == mode::write) return 0xff; //reads not permitted - if(file_offset >= file_size) return 0xff; //cannot read past end of file - buffer_sync(); - return buffer[(file_offset++) & buffer_mask]; - } - - uintmax_t readl(unsigned length = 1) { - uintmax_t data = 0; - for(int i = 0; i < length; i++) { - data |= (uintmax_t)read() << (i << 3); - } - return data; - } - - uintmax_t readm(unsigned length = 1) { - uintmax_t data = 0; - while(length--) { - data <<= 8; - data |= read(); - } - return data; - } - - void read(uint8_t *buffer, unsigned length) { - while(length--) *buffer++ = read(); - } - - void write(uint8_t data) { - if(!fp) return; //file not open - if(file_mode == mode::read) return; //writes not permitted - buffer_sync(); - buffer[(file_offset++) & buffer_mask] = data; - buffer_dirty = true; - if(file_offset > file_size) file_size = file_offset; - } - - void writel(uintmax_t data, unsigned length = 1) { - while(length--) { - write(data); - data >>= 8; - } - } - - void writem(uintmax_t data, unsigned length = 1) { - for(int i = length - 1; i >= 0; i--) { - write(data >> (i << 3)); - } - } - - void write(const uint8_t *buffer, unsigned length) { - while(length--) write(*buffer++); - } - - template void print(Args... args) { - string data(args...); - const char *p = data; - while(*p) write(*p++); - } - - void flush() { - buffer_flush(); - fflush(fp); - } - - void seek(int offset, index index_ = index::absolute) { - if(!fp) return; //file not open - buffer_flush(); - - uintmax_t req_offset = file_offset; - switch(index_) { - case index::absolute: req_offset = offset; break; - case index::relative: req_offset += offset; break; - } - - if(req_offset < 0) req_offset = 0; //cannot seek before start of file - if(req_offset > file_size) { - if(file_mode == mode::read) { //cannot seek past end of file - req_offset = file_size; - } else { //pad file to requested location - file_offset = file_size; - while(file_size < req_offset) write(0x00); - } - } - - file_offset = req_offset; - } - - int offset() const { - if(!fp) return -1; //file not open - return file_offset; - } - - int size() const { - if(!fp) return -1; //file not open - return file_size; - } - - bool truncate(unsigned size) { - if(!fp) return false; //file not open - #if !defined(_WIN32) - return ftruncate(fileno(fp), size) == 0; - #else - return _chsize(fileno(fp), size) == 0; - #endif - } - - bool end() { - if(!fp) return true; //file not open - return file_offset >= file_size; - } - - static bool exists(const string &filename) { - #if !defined(_WIN32) - struct stat64 data; - return stat64(filename, &data) == 0; - #else - struct __stat64 data; - return _wstat64(utf16_t(filename), &data) == 0; - #endif - } - - static uintmax_t size(const string &filename) { - #if !defined(_WIN32) - struct stat64 data; - stat64(filename, &data); - #else - struct __stat64 data; - _wstat64(utf16_t(filename), &data); - #endif - - //not readily possible in msvc; not needed in bizhawk - #ifdef BIZHAWK - return data.st_size; - #else - return S_ISREG(data.st_mode) ? data.st_size : 0u; //TEST - #endif - } - - static time_t timestamp(const string &filename, file::time mode = file::time::create) { - #if !defined(_WIN32) - struct stat64 data; - stat64(filename, &data); - #else - struct __stat64 data; - _wstat64(utf16_t(filename), &data); - #endif - switch(mode) { default: - case file::time::create: return data.st_ctime; - case file::time::modify: return data.st_mtime; - case file::time::access: return data.st_atime; - } - } - - bool open() const { - return fp; - } - - bool open(const string &filename, mode mode_) { - if(fp) return false; - - switch(file_mode = mode_) { - #if !defined(_WIN32) - case mode::read: fp = fopen(filename, "rb" ); break; - case mode::write: fp = fopen(filename, "wb+"); break; //need read permission for buffering - case mode::readwrite: fp = fopen(filename, "rb+"); break; - case mode::writeread: fp = fopen(filename, "wb+"); break; - #else - case mode::read: fp = _wfopen(utf16_t(filename), L"rb" ); break; - case mode::write: fp = _wfopen(utf16_t(filename), L"wb+"); break; - case mode::readwrite: fp = _wfopen(utf16_t(filename), L"rb+"); break; - case mode::writeread: fp = _wfopen(utf16_t(filename), L"wb+"); break; - #endif - } - if(!fp) return false; - buffer_offset = -1; //invalidate buffer - file_offset = 0; - fseek(fp, 0, SEEK_END); - file_size = ftell(fp); - fseek(fp, 0, SEEK_SET); - return true; - } - - void close() { - if(!fp) return; - buffer_flush(); - fclose(fp); - fp = 0; - } - - file() { - memset(buffer, 0, sizeof buffer); - buffer_offset = -1; - buffer_dirty = false; - fp = 0; - file_offset = 0; - file_size = 0; - file_mode = mode::read; - } - - ~file() { - close(); - } - - file& operator=(const file&) = delete; - file(const file&) = delete; - - private: - enum { buffer_size = 1 << 12, buffer_mask = buffer_size - 1 }; - char buffer[buffer_size]; - int buffer_offset; - bool buffer_dirty; - FILE *fp; - unsigned file_offset; - unsigned file_size; - mode file_mode; - - void buffer_sync() { - if(!fp) return; //file not open - if(buffer_offset != (file_offset & ~buffer_mask)) { - buffer_flush(); - buffer_offset = file_offset & ~buffer_mask; - fseek(fp, buffer_offset, SEEK_SET); - unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask); - if(length) unsigned unused = fread(buffer, 1, length, fp); - } - } - - void buffer_flush() { - if(!fp) return; //file not open - if(file_mode == mode::read) return; //buffer cannot be written to - if(buffer_offset < 0) return; //buffer unused - if(buffer_dirty == false) return; //buffer unmodified since read - fseek(fp, buffer_offset, SEEK_SET); - unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask); - if(length) unsigned unused = fwrite(buffer, 1, length, fp); - buffer_offset = -1; //invalidate buffer - buffer_dirty = false; - } - }; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/filemap.hpp b/waterbox/libsnes/bsnes/nall/filemap.hpp deleted file mode 100644 index f57d933c76..0000000000 --- a/waterbox/libsnes/bsnes/nall/filemap.hpp +++ /dev/null @@ -1,213 +0,0 @@ -#ifndef NALL_FILEMAP_HPP -#define NALL_FILEMAP_HPP - -#include -#include -#include - -#include -#include -#if defined(_WIN32) - #include -#else - #include - #include - #include - #include - #include -#endif - -namespace nall { - class filemap { - public: - enum class mode : unsigned { read, write, readwrite, writeread }; - - bool open() const { return p_open(); } - bool open(const char *filename, mode mode_) { return p_open(filename, mode_); } - void close() { return p_close(); } - unsigned size() const { return p_size; } - uint8_t* data() { return p_handle; } - const uint8_t* data() const { return p_handle; } - filemap() : p_size(0), p_handle(0) { p_ctor(); } - filemap(const char *filename, mode mode_) : p_size(0), p_handle(0) { p_ctor(); p_open(filename, mode_); } - ~filemap() { p_dtor(); } - - private: - unsigned p_size; - uint8_t *p_handle; - - #if defined(_WIN32) - //============= - //MapViewOfFile - //============= - - HANDLE p_filehandle, p_maphandle; - - bool p_open() const { - return p_handle; - } - - bool p_open(const char *filename, mode mode_) { - if(file::exists(filename) && file::size(filename) == 0) { - p_handle = 0; - p_size = 0; - return true; - } - - int desired_access, creation_disposition, flprotect, map_access; - - switch(mode_) { - default: return false; - case mode::read: - desired_access = GENERIC_READ; - creation_disposition = OPEN_EXISTING; - flprotect = PAGE_READONLY; - map_access = FILE_MAP_READ; - break; - case mode::write: - //write access requires read access - desired_access = GENERIC_WRITE; - creation_disposition = CREATE_ALWAYS; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - case mode::readwrite: - desired_access = GENERIC_READ | GENERIC_WRITE; - creation_disposition = OPEN_EXISTING; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - case mode::writeread: - desired_access = GENERIC_READ | GENERIC_WRITE; - creation_disposition = CREATE_NEW; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - } - - p_filehandle = CreateFileW(utf16_t(filename), desired_access, FILE_SHARE_READ, NULL, - creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL); - if(p_filehandle == INVALID_HANDLE_VALUE) return false; - - p_size = GetFileSize(p_filehandle, NULL); - - p_maphandle = CreateFileMapping(p_filehandle, NULL, flprotect, 0, p_size, NULL); - if(p_maphandle == INVALID_HANDLE_VALUE) { - CloseHandle(p_filehandle); - p_filehandle = INVALID_HANDLE_VALUE; - return false; - } - - p_handle = (uint8_t*)MapViewOfFile(p_maphandle, map_access, 0, 0, p_size); - return p_handle; - } - - void p_close() { - if(p_handle) { - UnmapViewOfFile(p_handle); - p_handle = 0; - } - - if(p_maphandle != INVALID_HANDLE_VALUE) { - CloseHandle(p_maphandle); - p_maphandle = INVALID_HANDLE_VALUE; - } - - if(p_filehandle != INVALID_HANDLE_VALUE) { - CloseHandle(p_filehandle); - p_filehandle = INVALID_HANDLE_VALUE; - } - } - - void p_ctor() { - p_filehandle = INVALID_HANDLE_VALUE; - p_maphandle = INVALID_HANDLE_VALUE; - } - - void p_dtor() { - close(); - } - - #else - //==== - //mmap - //==== - - int p_fd; - - bool p_open() const { - return p_handle; - } - - bool p_open(const char *filename, mode mode_) { - if(file::exists(filename) && file::size(filename) == 0) { - p_handle = 0; - p_size = 0; - return true; - } - - int open_flags, mmap_flags; - - switch(mode_) { - default: return false; - case mode::read: - open_flags = O_RDONLY; - mmap_flags = PROT_READ; - break; - case mode::write: - open_flags = O_RDWR | O_CREAT; //mmap() requires read access - mmap_flags = PROT_WRITE; - break; - case mode::readwrite: - open_flags = O_RDWR; - mmap_flags = PROT_READ | PROT_WRITE; - break; - case mode::writeread: - open_flags = O_RDWR | O_CREAT; - mmap_flags = PROT_READ | PROT_WRITE; - break; - } - - p_fd = ::open(filename, open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - if(p_fd < 0) return false; - - struct stat p_stat; - fstat(p_fd, &p_stat); - p_size = p_stat.st_size; - - p_handle = (uint8_t*)mmap(0, p_size, mmap_flags, MAP_SHARED, p_fd, 0); - if(p_handle == MAP_FAILED) { - p_handle = 0; - ::close(p_fd); - p_fd = -1; - return false; - } - - return p_handle; - } - - void p_close() { - if(p_handle) { - munmap(p_handle, p_size); - p_handle = 0; - } - - if(p_fd >= 0) { - ::close(p_fd); - p_fd = -1; - } - } - - void p_ctor() { - p_fd = -1; - } - - void p_dtor() { - p_close(); - } - - #endif - }; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/function.hpp b/waterbox/libsnes/bsnes/nall/function.hpp deleted file mode 100644 index ca574b8c17..0000000000 --- a/waterbox/libsnes/bsnes/nall/function.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef NALL_FUNCTION_HPP -#define NALL_FUNCTION_HPP - -namespace nall { - template class function; - - template class function { - struct container { - virtual R operator()(P... p) const = 0; - virtual container* copy() const = 0; - virtual ~container() {} - } *callback; - - struct global : container { - R (*function)(P...); - R operator()(P... p) const { return function(std::forward

(p)...); } - container* copy() const { return new global(function); } - global(R (*function)(P...)) : function(function) {} - }; - - template struct member : container { - R (C::*function)(P...); - C *object; - R operator()(P... p) const { return (object->*function)(std::forward

(p)...); } - container* copy() const { return new member(function, object); } - member(R (C::*function)(P...), C *object) : function(function), object(object) {} - }; - - template struct lambda : container { - mutable L object; - R operator()(P... p) const { return object(std::forward

(p)...); } - container* copy() const { return new lambda(object); } - lambda(const L& object) : object(object) {} - }; - - public: - operator bool() const { return callback; } - R operator()(P... p) const { return (*callback)(std::forward

(p)...); } - void reset() { if(callback) { delete callback; callback = nullptr; } } - - function& operator=(const function &source) { - if(this != &source) { - if(callback) { delete callback; callback = nullptr; } - if(source.callback) callback = source.callback->copy(); - } - return *this; - } - - function(const function &source) : callback(nullptr) { operator=(source); } - function() : callback(nullptr) {} - function(void *function) : callback(nullptr) { if(function) callback = new global((R (*)(P...))function); } - function(R (*function)(P...)) { callback = new global(function); } - template function(R (C::*function)(P...), C *object) { callback = new member(function, object); } - template function(R (C::*function)(P...) const, C *object) { callback = new member((R (C::*)(P...))function, object); } - template function(const L& object) { callback = new lambda(object); } - ~function() { if(callback) delete callback; } - }; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/gameboy/cartridge.hpp b/waterbox/libsnes/bsnes/nall/gameboy/cartridge.hpp deleted file mode 100644 index 2952502870..0000000000 --- a/waterbox/libsnes/bsnes/nall/gameboy/cartridge.hpp +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef NALL_GAMEBOY_CARTRIDGE_HPP -#define NALL_GAMEBOY_CARTRIDGE_HPP - -namespace nall { - -class GameBoyCartridge { -public: - string markup; - inline GameBoyCartridge(uint8_t *data, unsigned size); - -//private: - struct Information { - string mapper; - bool ram; - bool battery; - bool rtc; - bool rumble; - - unsigned romsize; - unsigned ramsize; - } info; -}; - -GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) { - markup = ""; - if(romsize < 0x4000) return; - - info.mapper = "unknown"; - info.ram = false; - info.battery = false; - info.rtc = false; - info.rumble = false; - - info.romsize = 0; - info.ramsize = 0; - - unsigned base = romsize - 0x8000; - if(romdata[base + 0x0104] == 0xce && romdata[base + 0x0105] == 0xed - && romdata[base + 0x0106] == 0x66 && romdata[base + 0x0107] == 0x66 - && romdata[base + 0x0108] == 0xcc && romdata[base + 0x0109] == 0x0d - && romdata[base + 0x0147] >= 0x0b && romdata[base + 0x0147] <= 0x0d - ) { - //MMM01 stores header at bottom of image - //flip this around for consistency with all other mappers - uint8_t header[0x8000]; - memcpy(header, romdata + base, 0x8000); - memmove(romdata + 0x8000, romdata, romsize - 0x8000); - memcpy(romdata, header, 0x8000); - } - - switch(romdata[0x0147]) { - case 0x00: info.mapper = "none"; break; - case 0x01: info.mapper = "MBC1"; break; - case 0x02: info.mapper = "MBC1"; info.ram = true; break; - case 0x03: info.mapper = "MBC1"; info.ram = true; info.battery = true; break; - case 0x05: info.mapper = "MBC2"; info.ram = true; break; - case 0x06: info.mapper = "MBC2"; info.ram = true; info.battery = true; break; - case 0x08: info.mapper = "none"; info.ram = true; break; - case 0x09: info.mapper = "MBC0"; info.ram = true; info.battery = true; break; - case 0x0b: info.mapper = "MMM01"; break; - case 0x0c: info.mapper = "MMM01"; info.ram = true; break; - case 0x0d: info.mapper = "MMM01"; info.ram = true; info.battery = true; break; - case 0x0f: info.mapper = "MBC3"; info.rtc = true; info.battery = true; break; - case 0x10: info.mapper = "MBC3"; info.rtc = true; info.ram = true; info.battery = true; break; - case 0x11: info.mapper = "MBC3"; break; - case 0x12: info.mapper = "MBC3"; info.ram = true; break; - case 0x13: info.mapper = "MBC3"; info.ram = true; info.battery = true; break; - case 0x19: info.mapper = "MBC5"; break; - case 0x1a: info.mapper = "MBC5"; info.ram = true; break; - case 0x1b: info.mapper = "MBC5"; info.ram = true; info.battery = true; break; - case 0x1c: info.mapper = "MBC5"; info.rumble = true; break; - case 0x1d: info.mapper = "MBC5"; info.rumble = true; info.ram = true; break; - case 0x1e: info.mapper = "MBC5"; info.rumble = true; info.ram = true; info.battery = true; break; - case 0xfc: break; //Pocket Camera - case 0xfd: break; //Bandai TAMA5 - case 0xfe: info.mapper = "HuC3"; break; - case 0xff: info.mapper = "HuC1"; info.ram = true; info.battery = true; break; - } - - switch(romdata[0x0148]) { default: - case 0x00: info.romsize = 2 * 16 * 1024; break; - case 0x01: info.romsize = 4 * 16 * 1024; break; - case 0x02: info.romsize = 8 * 16 * 1024; break; - case 0x03: info.romsize = 16 * 16 * 1024; break; - case 0x04: info.romsize = 32 * 16 * 1024; break; - case 0x05: info.romsize = 64 * 16 * 1024; break; - case 0x06: info.romsize = 128 * 16 * 1024; break; - case 0x07: info.romsize = 256 * 16 * 1024; break; - case 0x52: info.romsize = 72 * 16 * 1024; break; - case 0x53: info.romsize = 80 * 16 * 1024; break; - case 0x54: info.romsize = 96 * 16 * 1024; break; - } - - switch(romdata[0x0149]) { default: - case 0x00: info.ramsize = 0 * 1024; break; - case 0x01: info.ramsize = 2 * 1024; break; - case 0x02: info.ramsize = 8 * 1024; break; - case 0x03: info.ramsize = 32 * 1024; break; - } - - if(info.mapper == "MBC2") info.ramsize = 512; //512 x 4-bit - - markup.append( - "\n", - "\n", - " \n"); - if(info.ramsize > 0) markup.append( - " \n"); - markup.append( - "\n"); - -/* - markup.append("cartridge mapper=", info.mapper); - if(info.rtc) markup.append(" rtc"); - if(info.rumble) markup.append(" rumble"); - markup.append("\n"); - - markup.append("\t" "rom size=", hex(romsize), "\n"); //TODO: trust/check info.romsize? - - if(info.ramsize > 0) - markup.append("\t" "ram size=", hex(info.ramsize), info.battery ? " non-volatile\n" : "\n"); -*/ -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/gzip.hpp b/waterbox/libsnes/bsnes/nall/gzip.hpp deleted file mode 100644 index fa0aaad161..0000000000 --- a/waterbox/libsnes/bsnes/nall/gzip.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef NALL_GZIP_HPP -#define NALL_GZIP_HPP - -#include -#include - -namespace nall { - -struct gzip { - string filename; - uint8_t *data; - unsigned size; - - inline bool decompress(const string &filename); - inline bool decompress(const uint8_t *data, unsigned size); - - inline gzip(); - inline ~gzip(); -}; - -bool gzip::decompress(const string &filename) { - uint8_t *data; - unsigned size; - if(file::read(filename, data, size) == false) return false; - bool result = decompress(data, size); - delete[] data; - return result; -} - -bool gzip::decompress(const uint8_t *data, unsigned size) { - if(size < 18) return false; - if(data[0] != 0x1f) return false; - if(data[1] != 0x8b) return false; - unsigned cm = data[2]; - unsigned flg = data[3]; - unsigned mtime = data[4]; - mtime |= data[5] << 8; - mtime |= data[6] << 16; - mtime |= data[7] << 24; - unsigned xfl = data[8]; - unsigned os = data[9]; - unsigned p = 10; - unsigned isize = data[size - 4]; - isize |= data[size - 3] << 8; - isize |= data[size - 2] << 16; - isize |= data[size - 1] << 24; - filename = ""; - - if(flg & 0x04) { //FEXTRA - unsigned xlen = data[p + 0]; - xlen |= data[p + 1] << 8; - p += 2 + xlen; - } - - if(flg & 0x08) { //FNAME - char buffer[PATH_MAX]; - for(unsigned n = 0; n < PATH_MAX; n++, p++) { - buffer[n] = data[p]; - if(data[p] == 0) break; - } - if(data[p++]) return false; - filename = buffer; - } - - if(flg & 0x10) { //FCOMMENT - while(data[p++]); - } - - if(flg & 0x02) { //FHCRC - p += 2; - } - - this->size = isize; - this->data = new uint8_t[this->size]; - return inflate(this->data, this->size, data + p, size - p - 8); -} - -gzip::gzip() : data(nullptr) { -} - -gzip::~gzip() { - if(data) delete[] data; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/http.hpp b/waterbox/libsnes/bsnes/nall/http.hpp deleted file mode 100644 index 55190e820f..0000000000 --- a/waterbox/libsnes/bsnes/nall/http.hpp +++ /dev/null @@ -1,176 +0,0 @@ -#ifndef NALL_HTTP_HPP -#define NALL_HTTP_HPP - -#if !defined(_WIN32) - #include - #include - #include - #include -#else - #include - #include - #include -#endif - -#include -#include - -namespace nall { - -struct http { - string hostname; - addrinfo *serverinfo; - int serversocket; - string header; - - inline void download(const string &path, uint8_t *&data, unsigned &size) { - data = 0; - size = 0; - - send({ - "GET ", path, " HTTP/1.1\r\n" - "Host: ", hostname, "\r\n" - "Connection: close\r\n" - "\r\n" - }); - - header = downloadHeader(); - downloadContent(data, size); - } - - inline bool connect(string host, unsigned port) { - hostname = host; - - addrinfo hints; - memset(&hints, 0, sizeof(addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; - - int status = getaddrinfo(hostname, string(port), &hints, &serverinfo); - if(status != 0) return false; - - serversocket = socket(serverinfo->ai_family, serverinfo->ai_socktype, serverinfo->ai_protocol); - if(serversocket == -1) return false; - - int result = ::connect(serversocket, serverinfo->ai_addr, serverinfo->ai_addrlen); - if(result == -1) return false; - - return true; - } - - inline bool send(const string &data) { - return send((const uint8_t*)(const char*)data, data.length()); - } - - inline bool send(const uint8_t *data, unsigned size) { - while(size) { - int length = ::send(serversocket, (const char*)data, size, 0); - if(length == -1) return false; - data += length; - size -= length; - } - return true; - } - - inline string downloadHeader() { - string output; - do { - char buffer[2]; - int length = recv(serversocket, buffer, 1, 0); - if(length <= 0) return output; - buffer[1] = 0; - output.append(buffer); - } while(output.endswith("\r\n\r\n") == false); - return output; - } - - inline string downloadChunkLength() { - string output; - do { - char buffer[2]; - int length = recv(serversocket, buffer, 1, 0); - if(length <= 0) return output; - buffer[1] = 0; - output.append(buffer); - } while(output.endswith("\r\n") == false); - return output; - } - - inline void downloadContent(uint8_t *&data, unsigned &size) { - unsigned capacity = 0; - - if(header.iposition("\r\nTransfer-Encoding: chunked\r\n")) { - while(true) { - unsigned length = hex(downloadChunkLength()); - if(length == 0) break; - capacity += length; - data = (uint8_t*)realloc(data, capacity); - - char buffer[length]; - while(length) { - int packetlength = recv(serversocket, buffer, length, 0); - if(packetlength <= 0) break; - memcpy(data + size, buffer, packetlength); - size += packetlength; - length -= packetlength; - } - } - } else if(auto position = header.iposition("\r\nContent-Length: ")) { - unsigned length = decimal((const char*)header + position() + 18); - while(length) { - char buffer[256]; - int packetlength = recv(serversocket, buffer, min(256, length), 0); - if(packetlength <= 0) break; - capacity += packetlength; - data = (uint8_t*)realloc(data, capacity); - memcpy(data + size, buffer, packetlength); - size += packetlength; - length -= packetlength; - } - } else { - while(true) { - char buffer[256]; - int packetlength = recv(serversocket, buffer, 256, 0); - if(packetlength <= 0) break; - capacity += packetlength; - data = (uint8_t*)realloc(data, capacity); - memcpy(data + size, buffer, packetlength); - size += packetlength; - } - } - - data = (uint8_t*)realloc(data, capacity + 1); - data[capacity] = 0; - } - - inline void disconnect() { - close(serversocket); - freeaddrinfo(serverinfo); - serverinfo = 0; - serversocket = -1; - } - - #ifdef _WIN32 - inline int close(int sock) { - return closesocket(sock); - } - - inline http() { - int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if(sock == INVALID_SOCKET && WSAGetLastError() == WSANOTINITIALISED) { - WSADATA wsaData; - if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { - WSACleanup(); - return; - } - } else { - close(sock); - } - } - #endif -}; - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/image.hpp b/waterbox/libsnes/bsnes/nall/image.hpp deleted file mode 100644 index 986aabc319..0000000000 --- a/waterbox/libsnes/bsnes/nall/image.hpp +++ /dev/null @@ -1,465 +0,0 @@ -#ifndef NALL_IMAGE_HPP -#define NALL_IMAGE_HPP - -#include -#include -#include -#include -#include -#include - -namespace nall { - -struct image { - uint8_t *data; - unsigned width; - unsigned height; - unsigned pitch; - - bool endian; //0 = little, 1 = big - unsigned depth; - unsigned stride; - - struct Channel { - uint64_t mask; - unsigned depth; - unsigned shift; - } alpha, red, green, blue; - - typedef double (*interpolation)(double, double, double, double, double); - static inline unsigned bitDepth(uint64_t color); - static inline unsigned bitShift(uint64_t color); - static inline uint64_t normalize(uint64_t color, unsigned sourceDepth, unsigned targetDepth); - - inline image& operator=(const image &source); - inline image& operator=(image &&source); - inline image(const image &source); - inline image(image &&source); - inline image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask); - inline image(); - inline ~image(); - - inline uint64_t read(const uint8_t *data) const; - inline void write(uint8_t *data, uint64_t value) const; - - inline void free(); - inline void allocate(unsigned width, unsigned height); - inline void clear(uint64_t color); - inline bool load(const string &filename); -//inline bool loadBMP(const uint8_t *data, unsigned size); - inline bool loadPNG(const uint8_t *data, unsigned size); - inline void scale(unsigned width, unsigned height, interpolation op); - inline void transform(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask); - inline void alphaBlend(uint64_t alphaColor); - -protected: - inline uint64_t interpolate(double mu, const uint64_t *s, interpolation op); - inline void scaleX(unsigned width, interpolation op); - inline void scaleY(unsigned height, interpolation op); - inline bool loadBMP(const string &filename); - inline bool loadPNG(const string &filename); -}; - -//static - -unsigned image::bitDepth(uint64_t color) { - unsigned depth = 0; - if(color) while((color & 1) == 0) color >>= 1; - while((color & 1) == 1) { color >>= 1; depth++; } - return depth; -} - -unsigned image::bitShift(uint64_t color) { - unsigned shift = 0; - if(color) while((color & 1) == 0) { color >>= 1; shift++; } - return shift; -} - -uint64_t image::normalize(uint64_t color, unsigned sourceDepth, unsigned targetDepth) { - while(sourceDepth < targetDepth) { - color = (color << sourceDepth) | color; - sourceDepth += sourceDepth; - } - if(targetDepth < sourceDepth) color >>= (sourceDepth - targetDepth); - return color; -} - -//public - -image& image::operator=(const image &source) { - free(); - - width = source.width; - height = source.height; - pitch = source.pitch; - - endian = source.endian; - stride = source.stride; - - alpha = source.alpha; - red = source.red; - green = source.green; - blue = source.blue; - - data = new uint8_t[width * height * stride]; - memcpy(data, source.data, width * height * stride); - return *this; -} - -image& image::operator=(image &&source) { - width = source.width; - height = source.height; - pitch = source.pitch; - - endian = source.endian; - stride = source.stride; - - alpha = source.alpha; - red = source.red; - green = source.green; - blue = source.blue; - - data = source.data; - source.data = nullptr; - return *this; -} - -image::image(const image &source) : data(nullptr) { - operator=(source); -} - -image::image(image &&source) : data(nullptr) { - operator=(std::forward(source)); -} - -image::image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask) : data(nullptr) { - width = 0, height = 0, pitch = 0; - - this->endian = endian; - this->depth = depth; - this->stride = (depth / 8) + ((depth & 7) > 0); - - alpha.mask = alphaMask, red.mask = redMask, green.mask = greenMask, blue.mask = blueMask; - alpha.depth = bitDepth(alpha.mask), alpha.shift = bitShift(alpha.mask); - red.depth = bitDepth(red.mask), red.shift = bitShift(red.mask); - green.depth = bitDepth(green.mask), green.shift = bitShift(green.mask); - blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask); -} - -image::image() : data(nullptr) { - width = 0, height = 0, pitch = 0; - - this->endian = 0; - this->depth = 32; - this->stride = 4; - - alpha.mask = 255u << 24, red.mask = 255u << 16, green.mask = 255u << 8, blue.mask = 255u << 0; - alpha.depth = bitDepth(alpha.mask), alpha.shift = bitShift(alpha.mask); - red.depth = bitDepth(red.mask), red.shift = bitShift(red.mask); - green.depth = bitDepth(green.mask), green.shift = bitShift(green.mask); - blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask); -} - -image::~image() { - free(); -} - -uint64_t image::read(const uint8_t *data) const { - uint64_t result = 0; - if(endian == 0) { - for(signed n = stride - 1; n >= 0; n--) result = (result << 8) | data[n]; - } else { - for(signed n = 0; n < stride; n++) result = (result << 8) | data[n]; - } - return result; -} - -void image::write(uint8_t *data, uint64_t value) const { - if(endian == 0) { - for(signed n = 0; n < stride; n++) { data[n] = value; value >>= 8; } - } else { - for(signed n = stride - 1; n >= 0; n--) { data[n] = value; value >>= 8; } - } -} - -void image::free() { - if(data) delete[] data; - data = nullptr; -} - -void image::allocate(unsigned width, unsigned height) { - if(data != nullptr && this->width == width && this->height == height) return; - free(); - data = new uint8_t[width * height * stride](); - pitch = width * stride; - this->width = width; - this->height = height; -} - -void image::clear(uint64_t color) { - uint8_t *dp = data; - for(unsigned n = 0; n < width * height; n++) { - write(dp, color); - dp += stride; - } -} - -bool image::load(const string &filename) { - if(loadBMP(filename) == true) return true; - if(loadPNG(filename) == true) return true; - return false; -} - -void image::scale(unsigned outputWidth, unsigned outputHeight, interpolation op) { - if(width != outputWidth) scaleX(outputWidth, op); - if(height != outputHeight) scaleY(outputHeight, op); -} - -void image::transform(bool outputEndian, unsigned outputDepth, uint64_t outputAlphaMask, uint64_t outputRedMask, uint64_t outputGreenMask, uint64_t outputBlueMask) { - image output(outputEndian, outputDepth, outputAlphaMask, outputRedMask, outputGreenMask, outputBlueMask); - output.allocate(width, height); - - #pragma omp parallel for - for(unsigned y = 0; y < height; y++) { - uint8_t *dp = output.data + output.pitch * y; - uint8_t *sp = data + pitch * y; - for(unsigned x = 0; x < width; x++) { - uint64_t color = read(sp); - sp += stride; - - uint64_t a = (color & alpha.mask) >> alpha.shift; - uint64_t r = (color & red.mask) >> red.shift; - uint64_t g = (color & green.mask) >> green.shift; - uint64_t b = (color & blue.mask) >> blue.shift; - - a = normalize(a, alpha.depth, output.alpha.depth); - r = normalize(r, red.depth, output.red.depth); - g = normalize(g, green.depth, output.green.depth); - b = normalize(b, blue.depth, output.blue.depth); - - output.write(dp, (a << output.alpha.shift) | (r << output.red.shift) | (g << output.green.shift) | (b << output.blue.shift)); - dp += output.stride; - } - } - - operator=(std::move(output)); -} - -void image::alphaBlend(uint64_t alphaColor) { - uint64_t alphaR = (alphaColor & red.mask) >> red.shift; - uint64_t alphaG = (alphaColor & green.mask) >> green.shift; - uint64_t alphaB = (alphaColor & blue.mask) >> blue.shift; - - #pragma omp parallel for - for(unsigned y = 0; y < height; y++) { - uint8_t *dp = data + pitch * y; - for(unsigned x = 0; x < width; x++) { - uint64_t color = read(dp); - - uint64_t colorA = (color & alpha.mask) >> alpha.shift; - uint64_t colorR = (color & red.mask) >> red.shift; - uint64_t colorG = (color & green.mask) >> green.shift; - uint64_t colorB = (color & blue.mask) >> blue.shift; - double alphaScale = (double)colorA / (double)((1 << alpha.depth) - 1); - - colorA = (1 << alpha.depth) - 1; - colorR = (colorR * alphaScale) + (alphaR * (1.0 - alphaScale)); - colorG = (colorG * alphaScale) + (alphaG * (1.0 - alphaScale)); - colorB = (colorB * alphaScale) + (alphaB * (1.0 - alphaScale)); - - write(dp, (colorA << alpha.shift) | (colorR << red.shift) | (colorG << green.shift) | (colorB << blue.shift)); - dp += stride; - } - } -} - -//protected - -uint64_t image::interpolate(double mu, const uint64_t *s, double (*op)(double, double, double, double, double)) { - uint64_t aa = (s[0] & alpha.mask) >> alpha.shift, ar = (s[0] & red.mask) >> red.shift, - ag = (s[0] & green.mask) >> green.shift, ab = (s[0] & blue.mask) >> blue.shift; - uint64_t ba = (s[1] & alpha.mask) >> alpha.shift, br = (s[1] & red.mask) >> red.shift, - bg = (s[1] & green.mask) >> green.shift, bb = (s[1] & blue.mask) >> blue.shift; - uint64_t ca = (s[2] & alpha.mask) >> alpha.shift, cr = (s[2] & red.mask) >> red.shift, - cg = (s[2] & green.mask) >> green.shift, cb = (s[2] & blue.mask) >> blue.shift; - uint64_t da = (s[3] & alpha.mask) >> alpha.shift, dr = (s[3] & red.mask) >> red.shift, - dg = (s[3] & green.mask) >> green.shift, db = (s[3] & blue.mask) >> blue.shift; - - int64_t A = op(mu, aa, ba, ca, da); - int64_t R = op(mu, ar, br, cr, dr); - int64_t G = op(mu, ag, bg, cg, dg); - int64_t B = op(mu, ab, bb, cb, db); - - A = max(0, min(A, (1 << alpha.depth) - 1)); - R = max(0, min(R, (1 << red.depth) - 1)); - G = max(0, min(G, (1 << green.depth) - 1)); - B = max(0, min(B, (1 << blue.depth) - 1)); - - return (A << alpha.shift) | (R << red.shift) | (G << green.shift) | (B << blue.shift); -} - -void image::scaleX(unsigned outputWidth, interpolation op) { - uint8_t *outputData = new uint8_t[outputWidth * height * stride]; - unsigned outputPitch = outputWidth * stride; - double step = (double)width / (double)outputWidth; - const uint8_t *terminal = data + pitch * height; - - #pragma omp parallel for - for(unsigned y = 0; y < height; y++) { - uint8_t *dp = outputData + outputPitch * y; - uint8_t *sp = data + pitch * y; - - double fraction = 0.0; - uint64_t s[4] = { sp < terminal ? read(sp) : 0 }; //B,C (0,1) = center of kernel { 0, 0, 1, 2 } - s[1] = s[0]; - s[2] = sp + stride < terminal ? read(sp += stride) : s[1]; - s[3] = sp + stride < terminal ? read(sp += stride) : s[2]; - - for(unsigned x = 0; x < width; x++) { - while(fraction <= 1.0) { - if(dp >= outputData + outputPitch * height) break; - write(dp, interpolate(fraction, (const uint64_t*)&s, op)); - dp += stride; - fraction += step; - } - - s[0] = s[1]; s[1] = s[2]; s[2] = s[3]; - if(sp + stride < terminal) s[3] = read(sp += stride); - fraction -= 1.0; - } - } - - free(); - data = outputData; - width = outputWidth; - pitch = width * stride; -} - -void image::scaleY(unsigned outputHeight, interpolation op) { - uint8_t *outputData = new uint8_t[width * outputHeight * stride]; - double step = (double)height / (double)outputHeight; - const uint8_t *terminal = data + pitch * height; - - #pragma omp parallel for - for(unsigned x = 0; x < width; x++) { - uint8_t *dp = outputData + stride * x; - uint8_t *sp = data + stride * x; - - double fraction = 0.0; - uint64_t s[4] = { sp < terminal ? read(sp) : 0 }; - s[1] = s[0]; - s[2] = sp + pitch < terminal ? read(sp += pitch) : s[1]; - s[3] = sp + pitch < terminal ? read(sp += pitch) : s[2]; - - for(unsigned y = 0; y < height; y++) { - while(fraction <= 1.0) { - if(dp >= outputData + pitch * outputHeight) break; - write(dp, interpolate(fraction, (const uint64_t*)&s, op)); - dp += pitch; - fraction += step; - } - - s[0] = s[1]; s[1] = s[2]; s[2] = s[3]; - if(sp + pitch < terminal) s[3] = read(sp += pitch); - fraction -= 1.0; - } - } - - free(); - data = outputData; - height = outputHeight; -} - -bool image::loadBMP(const string &filename) { - uint32_t *outputData; - unsigned outputWidth, outputHeight; - if(bmp::read(filename, outputData, outputWidth, outputHeight) == false) return false; - - allocate(outputWidth, outputHeight); - const uint32_t *sp = outputData; - uint8_t *dp = data; - - for(unsigned y = 0; y < outputHeight; y++) { - for(unsigned x = 0; x < outputWidth; x++) { - uint32_t color = *sp++; - uint64_t a = normalize((uint8_t)(color >> 24), 8, alpha.depth); - uint64_t r = normalize((uint8_t)(color >> 16), 8, red.depth); - uint64_t g = normalize((uint8_t)(color >> 8), 8, green.depth); - uint64_t b = normalize((uint8_t)(color >> 0), 8, blue.depth); - write(dp, (a << alpha.shift) | (r << red.shift) | (g << green.shift) | (b << blue.shift)); - dp += stride; - } - } - - delete[] outputData; - return true; -} - -bool image::loadPNG(const uint8_t *pngData, unsigned pngSize) { - png source; - if(source.decode(pngData, pngSize) == false) return false; - - allocate(source.info.width, source.info.height); - const uint8_t *sp = source.data; - uint8_t *dp = data; - - auto decode = [&]() -> uint64_t { - uint64_t p, r, g, b, a; - - switch(source.info.colorType) { - case 0: //L - r = g = b = source.readbits(sp); - a = (1 << source.info.bitDepth) - 1; - break; - case 2: //R,G,B - r = source.readbits(sp); - g = source.readbits(sp); - b = source.readbits(sp); - a = (1 << source.info.bitDepth) - 1; - break; - case 3: //P - p = source.readbits(sp); - r = source.info.palette[p][0]; - g = source.info.palette[p][1]; - b = source.info.palette[p][2]; - a = (1 << source.info.bitDepth) - 1; - break; - case 4: //L,A - r = g = b = source.readbits(sp); - a = source.readbits(sp); - break; - case 6: //R,G,B,A - r = source.readbits(sp); - g = source.readbits(sp); - b = source.readbits(sp); - a = source.readbits(sp); - break; - } - - a = normalize(a, source.info.bitDepth, alpha.depth); - r = normalize(r, source.info.bitDepth, red.depth); - g = normalize(g, source.info.bitDepth, green.depth); - b = normalize(b, source.info.bitDepth, blue.depth); - - return (a << alpha.shift) | (r << red.shift) | (g << green.shift) | (b << blue.shift); - }; - - for(unsigned y = 0; y < height; y++) { - for(unsigned x = 0; x < width; x++) { - write(dp, decode()); - dp += stride; - } - } - - return true; -} - -bool image::loadPNG(const string &filename) { - filemap map; - if(map.open(filename, filemap::mode::read) == false) return false; - return loadPNG(map.data(), map.size()); -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/inflate.hpp b/waterbox/libsnes/bsnes/nall/inflate.hpp deleted file mode 100644 index cbbf6d2985..0000000000 --- a/waterbox/libsnes/bsnes/nall/inflate.hpp +++ /dev/null @@ -1,358 +0,0 @@ -#ifndef NALL_INFLATE_HPP -#define NALL_INFLATE_HPP - -#include - -namespace nall { - -namespace puff { - inline int puff( - unsigned char *dest, unsigned long *destlen, - unsigned char *source, unsigned long *sourcelen - ); -} - -inline bool inflate( - uint8_t *target, unsigned targetLength, - const uint8_t *source, unsigned sourceLength -) { - unsigned long tl = targetLength, sl = sourceLength; - int result = puff::puff((unsigned char*)target, &tl, (unsigned char*)source, &sl); - return result == 0; -} - -namespace puff { - -//zlib/contrib/puff.c -//version 2.1* -//author: Mark Adler -//license: zlib -//ported by: byuu - -//* I have corrected a bug in fixed(), where it was accessing uninitialized -// memory: calling construct() with lencode prior to initializing lencode.count - -enum { - MAXBITS = 15, - MAXLCODES = 286, - MAXDCODES = 30, - FIXLCODES = 288, - MAXCODES = MAXLCODES + MAXDCODES, -}; - -struct state { - unsigned char *out; - unsigned long outlen; - unsigned long outcnt; - - unsigned char *in; - unsigned long inlen; - unsigned long incnt; - int bitbuf; - int bitcnt; - - jmp_buf env; -}; - -struct huffman { - short *count; - short *symbol; -}; - -inline int bits(state *s, int need) { - long val; - - val = s->bitbuf; - while(s->bitcnt < need) { - if(s->incnt == s->inlen) longjmp(s->env, 1); - val |= (long)(s->in[s->incnt++]) << s->bitcnt; - s->bitcnt += 8; - } - - s->bitbuf = (int)(val >> need); - s->bitcnt -= need; - - return (int)(val & ((1L << need) - 1)); -} - -inline int stored(state *s) { - unsigned len; - - s->bitbuf = 0; - s->bitcnt = 0; - - if(s->incnt + 4 > s->inlen) return 2; - len = s->in[s->incnt++]; - len |= s->in[s->incnt++] << 8; - if(s->in[s->incnt++] != (~len & 0xff) || - s->in[s->incnt++] != ((~len >> 8) & 0xff) - ) return 2; - - if(s->incnt + len > s->inlen) return 2; - if(s->out != 0) { - if(s->outcnt + len > s->outlen) return 1; - while(len--) s->out[s->outcnt++] = s->in[s->incnt++]; - } else { - s->outcnt += len; - s->incnt += len; - } - - return 0; -} - -inline int decode(state *s, huffman *h) { - int len, code, first, count, index, bitbuf, left; - short *next; - - bitbuf = s->bitbuf; - left = s->bitcnt; - code = first = index = 0; - len = 1; - next = h->count + 1; - while(true) { - while(left--) { - code |= bitbuf & 1; - bitbuf >>= 1; - count = *next++; - if(code - count < first) { - s->bitbuf = bitbuf; - s->bitcnt = (s->bitcnt - len) & 7; - return h->symbol[index + (code - first)]; - } - index += count; - first += count; - first <<= 1; - code <<= 1; - len++; - } - left = (MAXBITS + 1) - len; - if(left == 0) break; - if(s->incnt == s->inlen) longjmp(s->env, 1); - bitbuf = s->in[s->incnt++]; - if(left > 8) left = 8; - } - - return -10; -} - -inline int construct(huffman *h, short *length, int n) { - int symbol, len, left; - short offs[MAXBITS + 1]; - - for(len = 0; len <= MAXBITS; len++) h->count[len] = 0; - for(symbol = 0; symbol < n; symbol++) h->count[length[symbol]]++; - if(h->count[0] == n) return 0; - - left = 1; - for(len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= h->count[len]; - if(left < 0) return left; - } - - offs[1] = 0; - for(len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + h->count[len]; - - for(symbol = 0; symbol < n; symbol++) { - if(length[symbol] != 0) h->symbol[offs[length[symbol]]++] = symbol; - } - - return left; -} - -inline int codes(state *s, huffman *lencode, huffman *distcode) { - int symbol, len; - unsigned dist; - static const short lens[29] = { - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 - }; - static const short lext[29] = { - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 - }; - static const short dists[30] = { - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577 - }; - static const short dext[30] = { - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13 - }; - - do { - symbol = decode(s, lencode); - if(symbol < 0) return symbol; - if(symbol < 256) { - if(s->out != 0) { - if(s->outcnt == s->outlen) return 1; - s->out[s->outcnt] = symbol; - } - s->outcnt++; - } else if(symbol > 256) { - symbol -= 257; - if(symbol >= 29) return -10; - len = lens[symbol] + bits(s, lext[symbol]); - - symbol = decode(s, distcode); - if(symbol < 0) return symbol; - dist = dists[symbol] + bits(s, dext[symbol]); - #ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOO_FAR - if(dist > s->outcnt) return -11; - #endif - - if(s->out != 0) { - if(s->outcnt + len > s->outlen) return 1; - while(len--) { - s->out[s->outcnt] = - #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOO_FAR - dist > s->outcnt ? 0 : - #endif - s->out[s->outcnt - dist]; - s->outcnt++; - } - } else { - s->outcnt += len; - } - } - } while(symbol != 256); - - return 0; -} - -inline int fixed(state *s) { - static int virgin = 1; - static short lencnt[MAXBITS + 1], lensym[FIXLCODES]; - static short distcnt[MAXBITS + 1], distsym[MAXDCODES]; - static huffman lencode, distcode; - - if(virgin) { - int symbol = 0; - short lengths[FIXLCODES]; - - lencode.count = lencnt; - lencode.symbol = lensym; - distcode.count = distcnt; - distcode.symbol = distsym; - - for(; symbol < 144; symbol++) lengths[symbol] = 8; - for(; symbol < 256; symbol++) lengths[symbol] = 9; - for(; symbol < 280; symbol++) lengths[symbol] = 7; - for(; symbol < FIXLCODES; symbol++) lengths[symbol] = 8; - construct(&lencode, lengths, FIXLCODES); - - for(symbol = 0; symbol < MAXDCODES; symbol++) lengths[symbol] = 5; - construct(&distcode, lengths, MAXDCODES); - - virgin = 0; - } - - return codes(s, &lencode, &distcode); -} - -inline int dynamic(state *s) { - int nlen, ndist, ncode, index, err; - short lengths[MAXCODES]; - short lencnt[MAXBITS + 1], lensym[MAXLCODES]; - short distcnt[MAXBITS + 1], distsym[MAXDCODES]; - huffman lencode, distcode; - static const short order[19] = { - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 - }; - - lencode.count = lencnt; - lencode.symbol = lensym; - distcode.count = distcnt; - distcode.symbol = distsym; - - nlen = bits(s, 5) + 257; - ndist = bits(s, 5) + 1; - ncode = bits(s, 4) + 4; - if(nlen > MAXLCODES || ndist > MAXDCODES) return -3; - - for(index = 0; index < ncode; index++) lengths[order[index]] = bits(s, 3); - for(; index < 19; index++) lengths[order[index]] = 0; - - err = construct(&lencode, lengths, 19); - if(err != 0) return -4; - - index = 0; - while(index < nlen + ndist) { - int symbol, len; - - symbol = decode(s, &lencode); - if(symbol < 16) { - lengths[index++] = symbol; - } else { - len = 0; - if(symbol == 16) { - if(index == 0) return -5; - len = lengths[index - 1]; - symbol = 3 + bits(s, 2); - } else if(symbol == 17) { - symbol = 3 + bits(s, 3); - } else { - symbol = 11 + bits(s, 7); - } - if(index + symbol > nlen + ndist) return -6; - while(symbol--) lengths[index++] = len; - } - } - - if(lengths[256] == 0) return -9; - - err = construct(&lencode, lengths, nlen); - if(err < 0 || (err > 0 && nlen - lencode.count[0] != 1)) return -7; - - err = construct(&distcode, lengths + nlen, ndist); - if(err < 0 || (err > 0 && ndist - distcode.count[0] != 1)) return -8; - - return codes(s, &lencode, &distcode); -} - -inline int puff( - unsigned char *dest, unsigned long *destlen, - unsigned char *source, unsigned long *sourcelen -) { - state s; - int last, type, err; - - s.out = dest; - s.outlen = *destlen; - s.outcnt = 0; - - s.in = source; - s.inlen = *sourcelen; - s.incnt = 0; - s.bitbuf = 0; - s.bitcnt = 0; - - if(setjmp(s.env) != 0) { - err = 2; - } else { - do { - last = bits(&s, 1); - type = bits(&s, 2); - err = type == 0 ? stored(&s) - : type == 1 ? fixed(&s) - : type == 2 ? dynamic(&s) - : -1; - if(err != 0) break; - } while(!last); - } - - if(err <= 0) { - *destlen = s.outcnt; - *sourcelen = s.incnt; - } - - return err; -} - -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/input.hpp b/waterbox/libsnes/bsnes/nall/input.hpp deleted file mode 100644 index cd76539330..0000000000 --- a/waterbox/libsnes/bsnes/nall/input.hpp +++ /dev/null @@ -1,386 +0,0 @@ -#ifndef NALL_INPUT_HPP -#define NALL_INPUT_HPP - -#include -#include -#include - -#include -#include - -namespace nall { - -struct Keyboard; -Keyboard& keyboard(unsigned = 0); - -static const char KeyboardScancodeName[][64] = { - "Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", - "PrintScreen", "ScrollLock", "Pause", "Tilde", - "Num1", "Num2", "Num3", "Num4", "Num5", "Num6", "Num7", "Num8", "Num9", "Num0", - "Dash", "Equal", "Backspace", - "Insert", "Delete", "Home", "End", "PageUp", "PageDown", - "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", - "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", - "LeftBracket", "RightBracket", "Backslash", "Semicolon", "Apostrophe", "Comma", "Period", "Slash", - "Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", "Keypad6", "Keypad7", "Keypad8", "Keypad9", "Keypad0", - "Point", "Enter", "Add", "Subtract", "Multiply", "Divide", - "NumLock", "CapsLock", - "Up", "Down", "Left", "Right", - "Tab", "Return", "Spacebar", "Menu", - "Shift", "Control", "Alt", "Super", -}; - -struct Keyboard { - const unsigned ID; - enum { Base = 1 }; - enum { Count = 8, Size = 128 }; - - enum Scancode { - Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, - PrintScreen, ScrollLock, Pause, Tilde, - Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9, Num0, - Dash, Equal, Backspace, - Insert, Delete, Home, End, PageUp, PageDown, - A, B, C, D, E, F, G, H, I, J, K, L, M, - N, O, P, Q, R, S, T, U, V, W, X, Y, Z, - LeftBracket, RightBracket, Backslash, Semicolon, Apostrophe, Comma, Period, Slash, - Keypad1, Keypad2, Keypad3, Keypad4, Keypad5, Keypad6, Keypad7, Keypad8, Keypad9, Keypad0, - Point, Enter, Add, Subtract, Multiply, Divide, - NumLock, CapsLock, - Up, Down, Left, Right, - Tab, Return, Spacebar, Menu, - Shift, Control, Alt, Super, - Limit, - }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed keyDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isKey(scancode)) return scancode - keyboard(i).key(Escape); - } - return -1; - } - - static signed modifierDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isModifier(scancode)) return scancode - keyboard(i).key(Shift); - } - return -1; - } - - static bool isAnyKey(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isKey(scancode)) return true; - } - return false; - } - - static bool isAnyModifier(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isModifier(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "KB")) return 0; - s.ltrim("KB"); - unsigned id = decimal(s); - auto pos = strpos(s, "::"); - if(!pos) return 0; - s = substr(s, pos() + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == KeyboardScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - break; - } - } - return { "KB", ID, "::", KeyboardScancodeName[index] }; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t key(unsigned id) const { return Base + Size * ID + id; } - bool isKey(unsigned id) const { return id >= key(Escape) && id <= key(Menu); } - bool isModifier(unsigned id) const { return id >= key(Shift) && id <= key(Super); } - bool belongsTo(uint16_t scancode) const { return isKey(scancode) || isModifier(scancode); } - - Keyboard(unsigned ID_) : ID(ID_) {} -}; - -inline Keyboard& keyboard(unsigned id) { - static Keyboard kb0(0), kb1(1), kb2(2), kb3(3), kb4(4), kb5(5), kb6(6), kb7(7); - switch(id) { default: - case 0: return kb0; case 1: return kb1; case 2: return kb2; case 3: return kb3; - case 4: return kb4; case 5: return kb5; case 6: return kb6; case 7: return kb7; - } -} - -static const char MouseScancodeName[][64] = { - "Xaxis", "Yaxis", "Zaxis", - "Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7", -}; - -struct Mouse; -Mouse& mouse(unsigned = 0); - -struct Mouse { - const unsigned ID; - enum { Base = Keyboard::Base + Keyboard::Size * Keyboard::Count }; - enum { Count = 8, Size = 16 }; - enum { Axes = 3, Buttons = 8 }; - - enum Scancode { - Xaxis, Yaxis, Zaxis, - Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7, - Limit, - }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed axisDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isAxis(scancode)) return scancode - mouse(i).axis(0); - } - return -1; - } - - static signed buttonDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isButton(scancode)) return scancode - mouse(i).button(0); - } - return -1; - } - - static bool isAnyAxis(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isAxis(scancode)) return true; - } - return false; - } - - static bool isAnyButton(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isButton(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "MS")) return 0; - s.ltrim("MS"); - unsigned id = decimal(s); - auto pos = strpos(s, "::"); - if(!pos) return 0; - s = substr(s, pos() + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == MouseScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - break; - } - } - return { "MS", ID, "::", MouseScancodeName[index] }; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t axis(unsigned id) const { return Base + Size * ID + Xaxis + id; } - uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; } - bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(2); } - bool isButton(unsigned id) const { return id >= button(0) && id <= button(7); } - bool belongsTo(uint16_t scancode) const { return isAxis(scancode) || isButton(scancode); } - - Mouse(unsigned ID_) : ID(ID_) {} -}; - -inline Mouse& mouse(unsigned id) { - static Mouse ms0(0), ms1(1), ms2(2), ms3(3), ms4(4), ms5(5), ms6(6), ms7(7); - switch(id) { default: - case 0: return ms0; case 1: return ms1; case 2: return ms2; case 3: return ms3; - case 4: return ms4; case 5: return ms5; case 6: return ms6; case 7: return ms7; - } -} - -static const char JoypadScancodeName[][64] = { - "Hat0", "Hat1", "Hat2", "Hat3", "Hat4", "Hat5", "Hat6", "Hat7", - "Axis0", "Axis1", "Axis2", "Axis3", "Axis4", "Axis5", "Axis6", "Axis7", - "Axis8", "Axis9", "Axis10", "Axis11", "Axis12", "Axis13", "Axis14", "Axis15", - "Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7", - "Button8", "Button9", "Button10", "Button11", "Button12", "Button13", "Button14", "Button15", - "Button16", "Button17", "Button18", "Button19", "Button20", "Button21", "Button22", "Button23", - "Button24", "Button25", "Button26", "Button27", "Button28", "Button29", "Button30", "Button31", -}; - -struct Joypad; -Joypad& joypad(unsigned = 0); - -struct Joypad { - const unsigned ID; - enum { Base = Mouse::Base + Mouse::Size * Mouse::Count }; - enum { Count = 8, Size = 64 }; - enum { Hats = 8, Axes = 16, Buttons = 32 }; - - enum Scancode { - Hat0, Hat1, Hat2, Hat3, Hat4, Hat5, Hat6, Hat7, - Axis0, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7, - Axis8, Axis9, Axis10, Axis11, Axis12, Axis13, Axis14, Axis15, - Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7, - Button8, Button9, Button10, Button11, Button12, Button13, Button14, Button15, - Button16, Button17, Button18, Button19, Button20, Button21, Button22, Button23, - Button24, Button25, Button26, Button27, Button28, Button29, Button30, Button31, - Limit, - }; - - enum Hat { HatCenter = 0, HatUp = 1, HatRight = 2, HatDown = 4, HatLeft = 8 }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed hatDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isHat(scancode)) return scancode - joypad(i).hat(0); - } - return -1; - } - - static signed axisDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isAxis(scancode)) return scancode - joypad(i).axis(0); - } - return -1; - } - - static signed buttonDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isButton(scancode)) return scancode - joypad(i).button(0); - } - return -1; - } - - static bool isAnyHat(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isHat(scancode)) return true; - } - return false; - } - - static bool isAnyAxis(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isAxis(scancode)) return true; - } - return false; - } - - static bool isAnyButton(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isButton(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "JP")) return 0; - s.ltrim("JP"); - unsigned id = decimal(s); - auto pos = strpos(s, "::"); - if(!pos) return 0; - s = substr(s, pos() + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == JoypadScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - } - } - return { "JP", ID, "::", JoypadScancodeName[index] }; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t hat(unsigned id) const { return Base + Size * ID + Hat0 + id; } - uint16_t axis(unsigned id) const { return Base + Size * ID + Axis0 + id; } - uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; } - bool isHat(unsigned id) const { return id >= hat(0) && id <= hat(7); } - bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(15); } - bool isButton(unsigned id) const { return id >= button(0) && id <= button(31); } - bool belongsTo(uint16_t scancode) const { return isHat(scancode) || isAxis(scancode) || isButton(scancode); } - - Joypad(unsigned ID_) : ID(ID_) {} -}; - -inline Joypad& joypad(unsigned id) { - static Joypad jp0(0), jp1(1), jp2(2), jp3(3), jp4(4), jp5(5), jp6(6), jp7(7); - switch(id) { default: - case 0: return jp0; case 1: return jp1; case 2: return jp2; case 3: return jp3; - case 4: return jp4; case 5: return jp5; case 6: return jp6; case 7: return jp7; - } -} - -struct Scancode { - enum { None = 0, Limit = Joypad::Base + Joypad::Size * Joypad::Count }; - - static uint16_t decode(const char *name) { - uint16_t code; - code = Keyboard::decode(name); - if(code) return code; - code = Mouse::decode(name); - if(code) return code; - code = Joypad::decode(name); - if(code) return code; - return None; - } - - static string encode(uint16_t code) { - for(unsigned i = 0; i < Keyboard::Count; i++) { - if(keyboard(i).belongsTo(code)) return keyboard(i).encode(code); - } - for(unsigned i = 0; i < Mouse::Count; i++) { - if(mouse(i).belongsTo(code)) return mouse(i).encode(code); - } - for(unsigned i = 0; i < Joypad::Count; i++) { - if(joypad(i).belongsTo(code)) return joypad(i).encode(code); - } - return "None"; - } -}; - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/interpolation.hpp b/waterbox/libsnes/bsnes/nall/interpolation.hpp deleted file mode 100644 index afc7108b9f..0000000000 --- a/waterbox/libsnes/bsnes/nall/interpolation.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef NALL_INTERPOLATION_HPP -#define NALL_INTERPOLATION_HPP - -namespace nall { - -struct Interpolation { - static inline double Nearest(double mu, double a, double b, double c, double d) { - return (mu <= 0.5 ? b : c); - } - - static inline double Sublinear(double mu, double a, double b, double c, double d) { - mu = ((mu - 0.5) * 2.0) + 0.5; - if(mu < 0) mu = 0; - if(mu > 1) mu = 1; - return b * (1.0 - mu) + c * mu; - } - - static inline double Linear(double mu, double a, double b, double c, double d) { - return b * (1.0 - mu) + c * mu; - } - - static inline double Cosine(double mu, double a, double b, double c, double d) { - mu = (1.0 - cos(mu * 3.14159265)) / 2.0; - return b * (1.0 - mu) + c * mu; - } - - static inline double Cubic(double mu, double a, double b, double c, double d) { - double A = d - c - a + b; - double B = a - b - A; - double C = c - a; - double D = b; - return A * (mu * mu * mu) + B * (mu * mu) + C * mu + D; - } - - static inline double Hermite(double mu1, double a, double b, double c, double d) { - const double tension = 0.0; //-1 = low, 0 = normal, +1 = high - const double bias = 0.0; //-1 = left, 0 = even, +1 = right - double mu2, mu3, m0, m1, a0, a1, a2, a3; - - mu2 = mu1 * mu1; - mu3 = mu2 * mu1; - - m0 = (b - a) * (1.0 + bias) * (1.0 - tension) / 2.0; - m0 += (c - b) * (1.0 - bias) * (1.0 - tension) / 2.0; - m1 = (c - b) * (1.0 + bias) * (1.0 - tension) / 2.0; - m1 += (d - c) * (1.0 - bias) * (1.0 - tension) / 2.0; - - a0 = +2 * mu3 - 3 * mu2 + 1; - a1 = mu3 - 2 * mu2 + mu1; - a2 = mu3 - mu2; - a3 = -2 * mu3 + 3 * mu2; - - return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c); - } -}; - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/intrinsics.hpp b/waterbox/libsnes/bsnes/nall/intrinsics.hpp deleted file mode 100644 index 413ef59383..0000000000 --- a/waterbox/libsnes/bsnes/nall/intrinsics.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef NALL_INTRINSICS_HPP -#define NALL_INTRINSICS_HPP - -struct Intrinsics { - enum class Compiler : unsigned { GCC, VisualC, Unknown }; - enum class Platform : unsigned { X, OSX, Windows, Unknown }; - enum class Endian : unsigned { LSB, MSB, Unknown }; - - static inline Compiler compiler(); - static inline Platform platform(); - static inline Endian endian(); -}; - -/* Compiler detection */ - -#if defined(__GNUC__) - #define COMPILER_GCC - Intrinsics::Compiler Intrinsics::compiler() { return Intrinsics::Compiler::GCC; } -#elif defined(_MSC_VER) - #define COMPILER_VISUALC - Intrinsics::Compiler Intrinsics::compiler() { return Intrinsics::Compiler::VisualC; } -#else - #warning "unable to detect compiler" - #define COMPILER_UNKNOWN - Intrinsics::Compiler Intrinsics::compiler() { return Intrinsics::Compiler::Unknown; } -#endif - -/* Platform detection */ - -#if defined(linux) || defined(__sun__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) - #define PLATFORM_X - Intrinsics::Platform Intrinsics::platform() { return Intrinsics::Platform::X; } -#elif defined(__APPLE__) - #define PLATFORM_OSX - Intrinsics::Platform Intrinsics::platform() { return Intrinsics::Platform::OSX; } -#elif defined(_WIN32) - #define PLATFORM_WINDOWS - #define PLATFORM_WIN - Intrinsics::Platform Intrinsics::platform() { return Intrinsics::Platform::Windows; } -#else - #warning "unable to detect platform" - #define PLATFORM_UNKNOWN - Intrinsics::Platform Intrinsics::platform() { return Intrinsics::Platform::Unknown; } -#endif - -/* Endian detection */ - -#if defined(__i386__) || defined(__amd64__) || defined(_M_IX86) || defined(_M_AMD64) - #define ENDIAN_LSB - #define ARCH_LSB - Intrinsics::Endian Intrinsics::endian() { return Intrinsics::Endian::LSB; } -#elif defined(__powerpc__) || defined(_M_PPC) || defined(__BIG_ENDIAN__) - #define ENDIAN_MSB - #define ARCH_MSB - Intrinsics::Endian Intrinsics::endian() { return Intrinsics::Endian::MSB; } -#else - #warning "unable to detect endian" - #define ENDIAN_UNKNOWN - #define ARCH_UNKNOWN - Intrinsics::Endian Intrinsics::endian() { return Intrinsics::Endian::Unknown; } -#endif - -#endif diff --git a/waterbox/libsnes/bsnes/nall/ips.hpp b/waterbox/libsnes/bsnes/nall/ips.hpp deleted file mode 100644 index 3071d03829..0000000000 --- a/waterbox/libsnes/bsnes/nall/ips.hpp +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef NALL_IPS_HPP -#define NALL_IPS_HPP - -#include -#include -#include - -namespace nall { - -struct ips { - inline bool apply(); - inline void source(const uint8_t *data, unsigned size); - inline void modify(const uint8_t *data, unsigned size); - inline bool source(const string &filename); - inline bool modify(const string &filename); - inline ips(); - inline ~ips(); - - uint8_t *data; - unsigned size; - const uint8_t *sourceData; - unsigned sourceSize; - const uint8_t *modifyData; - unsigned modifySize; -}; - -bool ips::apply() { - if(modifySize < 8) return false; - if(modifyData[0] != 'P') return false; - if(modifyData[1] != 'A') return false; - if(modifyData[2] != 'T') return false; - if(modifyData[3] != 'C') return false; - if(modifyData[4] != 'H') return false; - - if(data) delete[] data; - data = new uint8_t[16 * 1024 * 1024 + 65536](); //maximum size of IPS patch + single-tag padding - size = sourceSize; - memcpy(data, sourceData, sourceSize); - unsigned offset = 5; - - while(true) { - unsigned address, length; - - if(offset > modifySize - 3) break; - address = modifyData[offset++] << 16; - address |= modifyData[offset++] << 8; - address |= modifyData[offset++] << 0; - - if(address == 0x454f46) { //EOF - if(offset == modifySize) return true; - if(offset == modifySize - 3) { - size = modifyData[offset++] << 16; - size |= modifyData[offset++] << 8; - size |= modifyData[offset++] << 0; - return true; - } - } - - if(offset > modifySize - 2) break; - length = modifyData[offset++] << 8; - length |= modifyData[offset++] << 0; - - if(length) { //Copy - if(offset > modifySize - length) break; - while(length--) data[address++] = modifyData[offset++]; - } else { //RLE - if(offset > modifySize - 3) break; - length = modifyData[offset++] << 8; - length |= modifyData[offset++] << 0; - if(length == 0) break; //illegal - while(length--) data[address++] = modifyData[offset]; - offset++; - } - - size = max(size, address); - } - - delete[] data; - data = nullptr; - return false; -} - -void ips::source(const uint8_t *data, unsigned size) { - sourceData = data, sourceSize = size; -} - -void ips::modify(const uint8_t *data, unsigned size) { - modifyData = data, modifySize = size; -} - -bool ips::source(const string &filename) { - return file::read(filename, sourceData, sourceSize); -} - -bool ips::modify(const string &filename) { - return file::read(filename, modifyData, modifySize); -} - -ips::ips() : data(nullptr), sourceData(nullptr), modifyData(nullptr) { -} - -ips::~ips() { - if(data) delete[] data; - if(sourceData) delete[] sourceData; - if(modifyData) delete[] modifyData; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/lzss.hpp b/waterbox/libsnes/bsnes/nall/lzss.hpp deleted file mode 100644 index fb3e0ba63c..0000000000 --- a/waterbox/libsnes/bsnes/nall/lzss.hpp +++ /dev/null @@ -1,165 +0,0 @@ -#ifndef NALL_LZSS_HPP -#define NALL_LZSS_HPP - -#include -#include -#include -#include - -namespace nall { - -//19:5 pulldown -//8:1 marker: d7-d0 -//length: { 4 - 35 }, offset: { 1 - 0x80000 } -//4-byte file size header -//little-endian encoding -struct lzss { - inline void source(const uint8_t *data, unsigned size); - inline bool source(const string &filename); - inline unsigned size() const; - inline bool compress(const string &filename); - inline bool decompress(uint8_t *targetData, unsigned targetSize); - inline bool decompress(const string &filename); - -protected: - struct Node { - unsigned offset; - Node *next; - inline Node() : offset(0), next(nullptr) {} - inline ~Node() { if(next) delete next; } - } *tree[65536]; - - filemap sourceFile; - const uint8_t *sourceData; - unsigned sourceSize; - -public: - inline lzss() : sourceData(nullptr), sourceSize(0) {} -}; - -void lzss::source(const uint8_t *data, unsigned size) { - sourceData = data; - sourceSize = size; -} - -bool lzss::source(const string &filename) { - if(sourceFile.open(filename, filemap::mode::read) == false) return false; - sourceData = sourceFile.data(); - sourceSize = sourceFile.size(); - return true; -} - -unsigned lzss::size() const { - unsigned size = 0; - if(sourceSize < 4) return size; - for(unsigned n = 0; n < 32; n += 8) size |= sourceData[n >> 3] << n; - return size; -} - -bool lzss::compress(const string &filename) { - file targetFile; - if(targetFile.open(filename, file::mode::write) == false) return false; - - for(unsigned n = 0; n < 32; n += 8) targetFile.write(sourceSize >> n); - for(unsigned n = 0; n < 65536; n++) tree[n] = 0; - - uint8_t buffer[25]; - unsigned sourceOffset = 0; - - while(sourceOffset < sourceSize) { - uint8_t mask = 0x00; - unsigned bufferOffset = 1; - - for(unsigned iteration = 0; iteration < 8; iteration++) { - if(sourceOffset >= sourceSize) break; - - uint16_t symbol = sourceData[sourceOffset + 0]; - if(sourceOffset < sourceSize - 1) symbol |= sourceData[sourceOffset + 1] << 8; - Node *node = tree[symbol]; - unsigned maxLength = 0, maxOffset = 0; - - while(node) { - if(node->offset < sourceOffset - 0x80000) { - //out-of-range: all subsequent nodes will also be, so free up their memory - if(node->next) { delete node->next; node->next = 0; } - break; - } - - unsigned length = 0, x = sourceOffset, y = node->offset; - while(length < 35 && x < sourceSize && sourceData[x++] == sourceData[y++]) length++; - if(length > maxLength) maxLength = length, maxOffset = node->offset; - if(length == 35) break; - - node = node->next; - } - - //attach current symbol to top of tree for subsequent searches - node = new Node; - node->offset = sourceOffset; - node->next = tree[symbol]; - tree[symbol] = node; - - if(maxLength < 4) { - buffer[bufferOffset++] = sourceData[sourceOffset++]; - } else { - unsigned output = ((maxLength - 4) << 19) | (sourceOffset - 1 - maxOffset); - for(unsigned n = 0; n < 24; n += 8) buffer[bufferOffset++] = output >> n; - mask |= 0x80 >> iteration; - sourceOffset += maxLength; - } - } - - buffer[0] = mask; - targetFile.write(buffer, bufferOffset); - } - - sourceFile.close(); - targetFile.close(); - return true; -} - -bool lzss::decompress(uint8_t *targetData, unsigned targetSize) { - if(targetSize < size()) return false; - - unsigned sourceOffset = 4, targetOffset = 0; - while(sourceOffset < sourceSize) { - uint8_t mask = sourceData[sourceOffset++]; - - for(unsigned iteration = 0; iteration < 8; iteration++) { - if(sourceOffset >= sourceSize) break; - - if((mask & (0x80 >> iteration)) == 0) { - targetData[targetOffset++] = sourceData[sourceOffset++]; - } else { - unsigned code = 0; - for(unsigned n = 0; n < 24; n += 8) code |= sourceData[sourceOffset++] << n; - unsigned length = (code >> 19) + 4; - unsigned offset = targetOffset - 1 - (code & 0x7ffff); - while(length--) targetData[targetOffset++] = targetData[offset++]; - } - } - } -} - -bool lzss::decompress(const string &filename) { - if(sourceSize < 4) return false; - unsigned targetSize = size(); - - file fp; - if(fp.open(filename, file::mode::write) == false) return false; - fp.truncate(targetSize); - fp.close(); - - filemap targetFile; - if(targetFile.open(filename, filemap::mode::readwrite) == false) return false; - uint8_t *targetData = targetFile.data(); - - bool result = decompress(targetData, targetSize); - sourceFile.close(); - targetFile.close(); - return result; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/map.hpp b/waterbox/libsnes/bsnes/nall/map.hpp deleted file mode 100644 index 84709781a5..0000000000 --- a/waterbox/libsnes/bsnes/nall/map.hpp +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef NALL_MAP_HPP -#define NALL_MAP_HPP - -#include - -namespace nall { - -template -struct map { - struct pair { - LHS name; - RHS data; - }; - - inline void reset() { - list.reset(); - } - - inline unsigned size() const { - return list.size(); - } - - //O(log n) find - inline optional find(const LHS &name) const { - signed first = 0, last = size() - 1; - while(first <= last) { - signed middle = (first + last) / 2; - if(name < list[middle].name) last = middle - 1; //search lower half - else if(list[middle].name < name) first = middle + 1; //search upper half - else return { true, middle }; //match found - } - return { false, 0u }; - } - - //O(n) insert + O(log n) find - inline RHS& insert(const LHS &name, const RHS &data) { - if(auto position = find(name)) { - list[position()].data = data; - return list[position()].data; - } - signed offset = size(); - for(unsigned n = 0; n < size(); n++) { - if(name < list[n].name) { offset = n; break; } - } - list.insert(offset, { name, data }); - return list[offset].data; - } - - //O(log n) find - inline void modify(const LHS &name, const RHS &data) { - if(auto position = find(name)) list[position()].data = data; - } - - //O(n) remove + O(log n) find - inline void remove(const LHS &name) { - if(auto position = find(name)) list.remove(position()); - } - - //O(log n) find - inline RHS& operator[](const LHS &name) { - if(auto position = find(name)) return list[position()].data; - throw; - } - - inline const RHS& operator[](const LHS &name) const { - if(auto position = find(name)) return list[position()].data; - throw; - } - - inline RHS& operator()(const LHS &name) { - return insert(name, RHS()); - } - - inline const RHS& operator()(const LHS &name, const RHS &data) const { - if(auto position = find(name)) return list[position()].data; - return data; - } - - inline pair* begin() { return list.begin(); } - inline pair* end() { return list.end(); } - inline const pair* begin() const { return list.begin(); } - inline const pair* end() const { return list.end(); } - -protected: - vector list; -}; - -template -struct bidirectional_map { - const map &lhs; - const map &rhs; - - inline void reset() { - llist.reset(); - rlist.reset(); - } - - inline unsigned size() const { - return llist.size(); - } - - inline void insert(const LHS &ldata, const RHS &rdata) { - llist.insert(ldata, rdata); - rlist.insert(rdata, ldata); - } - - inline bidirectional_map() : lhs(llist), rhs(rlist) {} - -protected: - map llist; - map rlist; -}; - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/moduloarray.hpp b/waterbox/libsnes/bsnes/nall/moduloarray.hpp deleted file mode 100644 index f6b28ab8b4..0000000000 --- a/waterbox/libsnes/bsnes/nall/moduloarray.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef NALL_MODULO_HPP -#define NALL_MODULO_HPP - -#include - -namespace nall { - template class modulo_array { - public: - inline T operator[](int index) const { - return buffer[size + index]; - } - - inline T read(int index) const { - return buffer[size + index]; - } - - inline void write(unsigned index, const T value) { - buffer[index] = - buffer[index + size] = - buffer[index + size + size] = value; - } - - modulo_array() { - buffer = new T[size * 3](); - } - - ~modulo_array() { - delete[] buffer; - } - - private: - T *buffer; - }; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/mosaic.hpp b/waterbox/libsnes/bsnes/nall/mosaic.hpp deleted file mode 100644 index 16fd0bfd3d..0000000000 --- a/waterbox/libsnes/bsnes/nall/mosaic.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef NALL_MOSAIC_HPP -#define NALL_MOSAIC_HPP - -#define NALL_MOSAIC_INTERNAL_HPP -#include -#include -#include -#undef NALL_MOSAIC_INTERNAL_HPP - -#endif diff --git a/waterbox/libsnes/bsnes/nall/mosaic/bitstream.hpp b/waterbox/libsnes/bsnes/nall/mosaic/bitstream.hpp deleted file mode 100644 index e2cb3bc548..0000000000 --- a/waterbox/libsnes/bsnes/nall/mosaic/bitstream.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#ifdef NALL_MOSAIC_INTERNAL_HPP - -namespace nall { -namespace mosaic { - -struct bitstream { - filemap fp; - uint8_t *data; - unsigned size; - bool readonly; - bool endian; - - inline bool read(uint64_t addr) const { - if(data == nullptr || (addr >> 3) >= size) return 0; - unsigned mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7)); - return data[addr >> 3] & mask; - } - - inline void write(uint64_t addr, bool value) { - if(data == nullptr || readonly == true || (addr >> 3) >= size) return; - unsigned mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7)); - if(value == 0) data[addr >> 3] &= ~mask; - if(value == 1) data[addr >> 3] |= mask; - } - - inline bool open(const string &filename) { - readonly = false; - if(fp.open(filename, filemap::mode::readwrite) == false) { - readonly = true; - if(fp.open(filename, filemap::mode::read) == false) { - return false; - } - } - data = fp.data(); - size = fp.size(); - return true; - } - - inline void close() { - fp.close(); - data = nullptr; - } - - inline bitstream() : data(nullptr), endian(1) { - } - - inline ~bitstream() { - close(); - } -}; - -} -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/mosaic/context.hpp b/waterbox/libsnes/bsnes/nall/mosaic/context.hpp deleted file mode 100644 index 2d8c71cacf..0000000000 --- a/waterbox/libsnes/bsnes/nall/mosaic/context.hpp +++ /dev/null @@ -1,224 +0,0 @@ -#ifdef NALL_MOSAIC_INTERNAL_HPP - -namespace nall { -namespace mosaic { - -struct context { - unsigned offset; - unsigned width; - unsigned height; - unsigned count; - - bool endian; //0 = lsb, 1 = msb - bool order; //0 = linear, 1 = planar - unsigned depth; //1 - 24bpp - - unsigned blockWidth; - unsigned blockHeight; - unsigned blockStride; - unsigned blockOffset; - array block; - - unsigned tileWidth; - unsigned tileHeight; - unsigned tileStride; - unsigned tileOffset; - array tile; - - unsigned mosaicWidth; - unsigned mosaicHeight; - unsigned mosaicStride; - unsigned mosaicOffset; - array mosaic; - - unsigned paddingWidth; - unsigned paddingHeight; - unsigned paddingColor; - array palette; - - inline unsigned objectWidth() const { return blockWidth * tileWidth * mosaicWidth + paddingWidth; } - inline unsigned objectHeight() const { return blockHeight * tileHeight * mosaicHeight + paddingHeight; } - inline unsigned objectSize() const { - unsigned size = blockStride * tileWidth * tileHeight * mosaicWidth * mosaicHeight - + blockOffset * tileHeight * mosaicWidth * mosaicHeight - + tileStride * mosaicWidth * mosaicHeight - + tileOffset * mosaicHeight; - return max(1u, size); - } - - inline unsigned eval(const string &expression) { - intmax_t result; - if(fixedpoint::eval(expression, result) == false) return 0u; - return result; - } - - inline void eval(array &buffer, const string &expression_) { - string expression = expression_; - bool function = false; - for(auto &c : expression) { - if(c == '(') function = true; - if(c == ')') function = false; - if(c == ',' && function == true) c = ';'; - } - - lstring list = expression.split(","); - for(auto &item : list) { - item.trim(); - if(item.wildcard("f(?*) ?*")) { - item.ltrim<1>("f("); - lstring part = item.split<1>(") "); - lstring args = part[0].split<3>(";"); - for(auto &item : args) item.trim(); - - unsigned length = eval(args(0, "0")); - unsigned offset = eval(args(1, "0")); - unsigned stride = eval(args(2, "0")); - if(args.size() < 2) offset = buffer.size(); - if(args.size() < 3) stride = 1; - - for(unsigned n = 0; n < length; n++) { - string fn = part[1]; - fn.replace("n", decimal(n)); - fn.replace("o", decimal(offset)); - fn.replace("p", decimal(buffer.size())); - buffer.resize(offset + 1); - buffer[offset] = eval(fn); - offset += stride; - } - } else if(item.wildcard("base64*")) { - unsigned offset = 0; - item.ltrim<1>("base64"); - if(item.wildcard("(?*) *")) { - item.ltrim<1>("("); - lstring part = item.split<1>(") "); - offset = eval(part[0]); - item = part(1, ""); - } - item.trim(); - for(auto &c : item) { - if(c >= 'A' && c <= 'Z') buffer.append(offset + c - 'A' + 0); - if(c >= 'a' && c <= 'z') buffer.append(offset + c - 'a' + 26); - if(c >= '0' && c <= '9') buffer.append(offset + c - '0' + 52); - if(c == '-') buffer.append(offset + 62); - if(c == '_') buffer.append(offset + 63); - } - } else if(item.wildcard("file *")) { - item.ltrim<1>("file "); - item.trim(); - //... - } else if(item.empty() == false) { - buffer.append(eval(item)); - } - } - } - - inline void parse(const string &data) { - reset(); - - lstring lines = data.split("\n"); - for(auto &line : lines) { - lstring part = line.split<1>(":"); - if(part.size() != 2) continue; - part[0].trim(); - part[1].trim(); - - if(part[0] == "offset") offset = eval(part[1]); - if(part[0] == "width") width = eval(part[1]); - if(part[0] == "height") height = eval(part[1]); - if(part[0] == "count") count = eval(part[1]); - - if(part[0] == "endian") endian = eval(part[1]); - if(part[0] == "order") order = eval(part[1]); - if(part[0] == "depth") depth = eval(part[1]); - - if(part[0] == "blockWidth") blockWidth = eval(part[1]); - if(part[0] == "blockHeight") blockHeight = eval(part[1]); - if(part[0] == "blockStride") blockStride = eval(part[1]); - if(part[0] == "blockOffset") blockOffset = eval(part[1]); - if(part[0] == "block") eval(block, part[1]); - - if(part[0] == "tileWidth") tileWidth = eval(part[1]); - if(part[0] == "tileHeight") tileHeight = eval(part[1]); - if(part[0] == "tileStride") tileStride = eval(part[1]); - if(part[0] == "tileOffset") tileOffset = eval(part[1]); - if(part[0] == "tile") eval(tile, part[1]); - - if(part[0] == "mosaicWidth") mosaicWidth = eval(part[1]); - if(part[0] == "mosaicHeight") mosaicHeight = eval(part[1]); - if(part[0] == "mosaicStride") mosaicStride = eval(part[1]); - if(part[0] == "mosaicOffset") mosaicOffset = eval(part[1]); - if(part[0] == "mosaic") eval(mosaic, part[1]); - - if(part[0] == "paddingWidth") paddingWidth = eval(part[1]); - if(part[0] == "paddingHeight") paddingHeight = eval(part[1]); - if(part[0] == "paddingColor") paddingColor = eval(part[1]); - if(part[0] == "palette") eval(palette, part[1]); - } - - sanitize(); - } - - inline bool load(const string &filename) { - string filedata; - if(filedata.readfile(filename) == false) return false; - parse(filedata); - return true; - } - - inline void sanitize() { - if(depth < 1) depth = 1; - if(depth > 24) depth = 24; - - if(blockWidth < 1) blockWidth = 1; - if(blockHeight < 1) blockHeight = 1; - - if(tileWidth < 1) tileWidth = 1; - if(tileHeight < 1) tileHeight = 1; - - if(mosaicWidth < 1) mosaicWidth = 1; - if(mosaicHeight < 1) mosaicHeight = 1; - } - - inline void reset() { - offset = 0; - width = 0; - height = 0; - count = 0; - - endian = 1; - order = 0; - depth = 1; - - blockWidth = 1; - blockHeight = 1; - blockStride = 0; - blockOffset = 0; - block.reset(); - - tileWidth = 1; - tileHeight = 1; - tileStride = 0; - tileOffset = 0; - tile.reset(); - - mosaicWidth = 1; - mosaicHeight = 1; - mosaicStride = 0; - mosaicOffset = 0; - mosaic.reset(); - - paddingWidth = 0; - paddingHeight = 0; - paddingColor = 0x000000; - palette.reset(); - } - - inline context() { - reset(); - } -}; - -} -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/mosaic/parser.hpp b/waterbox/libsnes/bsnes/nall/mosaic/parser.hpp deleted file mode 100644 index b2c0b8ef32..0000000000 --- a/waterbox/libsnes/bsnes/nall/mosaic/parser.hpp +++ /dev/null @@ -1,126 +0,0 @@ -#ifdef NALL_MOSAIC_INTERNAL_HPP - -namespace nall { -namespace mosaic { - -struct parser { - image canvas; - - //export from bitstream to canvas - inline void load(bitstream &stream, uint64_t offset, context &ctx, unsigned width, unsigned height) { - canvas.allocate(width, height); - canvas.clear(ctx.paddingColor); - parse(1, stream, offset, ctx, width, height); - } - - //import from canvas to bitstream - inline bool save(bitstream &stream, uint64_t offset, context &ctx) { - if(stream.readonly) return false; - parse(0, stream, offset, ctx, canvas.width, canvas.height); - return true; - } - - inline parser() : canvas(0, 32, 0u, 255u << 16, 255u << 8, 255u << 0) { - } - -private: - inline uint32_t read(unsigned x, unsigned y) const { - unsigned addr = y * canvas.width + x; - if(addr >= canvas.width * canvas.height) return 0u; - uint32_t *buffer = (uint32_t*)canvas.data; - return buffer[addr]; - } - - inline void write(unsigned x, unsigned y, uint32_t data) { - unsigned addr = y * canvas.width + x; - if(addr >= canvas.width * canvas.height) return; - uint32_t *buffer = (uint32_t*)canvas.data; - buffer[addr] = data; - } - - inline void parse(bool load, bitstream &stream, uint64_t offset, context &ctx, unsigned width, unsigned height) { - stream.endian = ctx.endian; - unsigned canvasWidth = width / (ctx.mosaicWidth * ctx.tileWidth * ctx.blockWidth + ctx.paddingWidth); - unsigned canvasHeight = height / (ctx.mosaicHeight * ctx.tileHeight * ctx.blockHeight + ctx.paddingHeight); - unsigned bitsPerBlock = ctx.depth * ctx.blockWidth * ctx.blockHeight; - - unsigned objectOffset = 0; - for(unsigned objectY = 0; objectY < canvasHeight; objectY++) { - for(unsigned objectX = 0; objectX < canvasWidth; objectX++) { - if(objectOffset >= ctx.count && ctx.count > 0) break; - unsigned objectIX = objectX * ctx.objectWidth(); - unsigned objectIY = objectY * ctx.objectHeight(); - objectOffset++; - - unsigned mosaicOffset = 0; - for(unsigned mosaicY = 0; mosaicY < ctx.mosaicHeight; mosaicY++) { - for(unsigned mosaicX = 0; mosaicX < ctx.mosaicWidth; mosaicX++) { - unsigned mosaicData = ctx.mosaic(mosaicOffset, mosaicOffset); - unsigned mosaicIX = (mosaicData % ctx.mosaicWidth) * (ctx.tileWidth * ctx.blockWidth); - unsigned mosaicIY = (mosaicData / ctx.mosaicWidth) * (ctx.tileHeight * ctx.blockHeight); - mosaicOffset++; - - unsigned tileOffset = 0; - for(unsigned tileY = 0; tileY < ctx.tileHeight; tileY++) { - for(unsigned tileX = 0; tileX < ctx.tileWidth; tileX++) { - unsigned tileData = ctx.tile(tileOffset, tileOffset); - unsigned tileIX = (tileData % ctx.tileWidth) * ctx.blockWidth; - unsigned tileIY = (tileData / ctx.tileWidth) * ctx.blockHeight; - tileOffset++; - - unsigned blockOffset = 0; - for(unsigned blockY = 0; blockY < ctx.blockHeight; blockY++) { - for(unsigned blockX = 0; blockX < ctx.blockWidth; blockX++) { - if(load) { - unsigned palette = 0; - for(unsigned n = 0; n < ctx.depth; n++) { - unsigned index = blockOffset++; - if(ctx.order == 1) index = (index % ctx.depth) * ctx.blockWidth * ctx.blockHeight + (index / ctx.depth); - palette |= stream.read(offset + ctx.block(index, index)) << n; - } - - write( - objectIX + mosaicIX + tileIX + blockX, - objectIY + mosaicIY + tileIY + blockY, - ctx.palette(palette, palette) - ); - } else /* save */ { - uint32_t palette = read( - objectIX + mosaicIX + tileIX + blockX, - objectIY + mosaicIY + tileIY + blockY - ); - - for(unsigned n = 0; n < ctx.depth; n++) { - unsigned index = blockOffset++; - if(ctx.order == 1) index = (index % ctx.depth) * ctx.blockWidth * ctx.blockHeight + (index / ctx.depth); - stream.write(offset + ctx.block(index, index), palette & 1); - palette >>= 1; - } - } - } //blockX - } //blockY - - offset += ctx.blockStride; - } //tileX - - offset += ctx.blockOffset; - } //tileY - - offset += ctx.tileStride; - } //mosaicX - - offset += ctx.tileOffset; - } //mosaicY - - offset += ctx.mosaicStride; - } //objectX - - offset += ctx.mosaicOffset; - } //objectY - } -}; - -} -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/platform.hpp b/waterbox/libsnes/bsnes/nall/platform.hpp deleted file mode 100644 index 3bbffd9ab9..0000000000 --- a/waterbox/libsnes/bsnes/nall/platform.hpp +++ /dev/null @@ -1,155 +0,0 @@ -#ifndef NALL_PLATFORM_HPP -#define NALL_PLATFORM_HPP - -#if defined(_WIN32) - //minimum version needed for _wstat64, etc - #undef __MSVCRT_VERSION__ - #define __MSVCRT_VERSION__ 0x0601 - #include -#endif - -#ifdef _MSC_VER -#define _USE_MATH_DEFINES 1 -#endif - -//========================= -//standard platform headers -//========================= - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#if defined(_WIN32) - #include - #include - //#include //bizhawk chokes? - #include - #undef interface - #define dllexport __declspec(dllexport) - //bad things happen without these here -#else - #include - #include - #define dllexport -#endif - -//================== -//warning supression -//================== - -//Visual C++ -#if defined(_MSC_VER) - //disable libc "deprecation" warnings - #pragma warning(disable:4996) -#endif - -//================ -//POSIX compliance -//================ - -#if defined(_MSC_VER) - #define PATH_MAX _MAX_PATH - #define va_copy(dest, src) ((dest) = (src)) -#endif - -#if defined(_WIN32) - #define getcwd _getcwd - #define ftruncate _chsize - #define mkdir(n, m) _wmkdir(nall::utf16_t(n)) - #define putenv _putenv - #define rmdir _rmdir - #define vsnprintf _vsnprintf - inline void usleep(unsigned milliseconds) { Sleep(milliseconds / 1000); } -#endif - -//================ -//inline expansion -//================ - -#if defined(__GNUC__) - #define noinline __attribute__((noinline)) - #define inline inline - #define alwaysinline inline __attribute__((always_inline)) -#elif defined(_MSC_VER) - #define noinline __declspec(noinline) - #define inline inline - #define alwaysinline inline __forceinline -#else - #define noinline - #define inline inline - #define alwaysinline inline -#endif - -//========================= -//file system functionality -//========================= - -#if defined(_WIN32) - inline char* realpath(const char *filename, char *resolvedname) { - wchar_t fn[_MAX_PATH] = L""; - _wfullpath(fn, nall::utf16_t(filename), _MAX_PATH); - strcpy(resolvedname, nall::utf8_t(fn)); - for(unsigned n = 0; resolvedname[n]; n++) if(resolvedname[n] == '\\') resolvedname[n] = '/'; - return resolvedname; - } - - inline char* userpath(char *path) { - //TODO BIZHAWK - return nullptr; - //wchar_t fp[_MAX_PATH] = L""; - //SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, fp); - //strcpy(path, nall::utf8_t(fp)); - //for(unsigned n = 0; path[n]; n++) if(path[n] == '\\') path[n] = '/'; - //unsigned length = strlen(path); - //if(path[length] != '/') strcpy(path + length, "/"); - //return path; - } - - inline char* getcwd(char *path) { - //TODO BIZHAWK - return nullptr; - //wchar_t fp[_MAX_PATH] = L""; - //_wgetcwd(fp, _MAX_PATH); - //strcpy(path, nall::utf8_t(fp)); - //for(unsigned n = 0; path[n]; n++) if(path[n] == '\\') path[n] = '/'; - //unsigned length = strlen(path); - //if(path[length] != '/') strcpy(path + length, "/"); - //return path; - } -#else - //realpath() already exists - - inline char* userpath(char *path) { - *path = 0; - struct passwd *userinfo = getpwuid(getuid()); - if(userinfo) strcpy(path, userinfo->pw_dir); - unsigned length = strlen(path); - if(path[length] != '/') strcpy(path + length, "/"); - return path; - } - - inline char *getcwd(char *path) { - auto unused = getcwd(path, PATH_MAX); - unsigned length = strlen(path); - if(path[length] != '/') strcpy(path + length, "/"); - return path; - } -#endif - -#endif - diff --git a/waterbox/libsnes/bsnes/nall/png.hpp b/waterbox/libsnes/bsnes/nall/png.hpp deleted file mode 100644 index 4b474724e4..0000000000 --- a/waterbox/libsnes/bsnes/nall/png.hpp +++ /dev/null @@ -1,339 +0,0 @@ -#ifndef NALL_PNG_HPP -#define NALL_PNG_HPP - -//PNG image decoder -//author: byuu - -#include -#include - -namespace nall { - -struct png { - //colorType: - //0 = L - //2 = R,G,B - //3 = P - //4 = L,A - //6 = R,G,B,A - struct Info { - unsigned width; - unsigned height; - unsigned bitDepth; - unsigned colorType; - unsigned compressionMethod; - unsigned filterType; - unsigned interlaceMethod; - - unsigned bytesPerPixel; - unsigned pitch; - - uint8_t palette[256][3]; - } info; - - uint8_t *data; - unsigned size; - - inline bool decode(const string &filename); - inline bool decode(const uint8_t *sourceData, unsigned sourceSize); - inline unsigned readbits(const uint8_t *&data); - unsigned bitpos; - - inline png(); - inline ~png(); - -protected: - enum class FourCC : unsigned { - IHDR = 0x49484452, - PLTE = 0x504c5445, - IDAT = 0x49444154, - IEND = 0x49454e44, - }; - - inline unsigned interlace(unsigned pass, unsigned index); - inline unsigned inflateSize(); - inline bool deinterlace(const uint8_t *&inputData, unsigned pass); - inline bool filter(uint8_t *outputData, const uint8_t *inputData, unsigned width, unsigned height); - inline unsigned read(const uint8_t *data, unsigned length); -}; - -bool png::decode(const string &filename) { - uint8_t *data; - unsigned size; - if(file::read(filename, data, size) == false) return false; - bool result = decode(data, size); - delete[] data; - return result; -} - -bool png::decode(const uint8_t *sourceData, unsigned sourceSize) { - if(sourceSize < 8) return false; - if(read(sourceData + 0, 4) != 0x89504e47) return false; - if(read(sourceData + 4, 4) != 0x0d0a1a0a) return false; - - uint8_t *compressedData = 0; - unsigned compressedSize = 0; - - unsigned offset = 8; - while(offset < sourceSize) { - unsigned length = read(sourceData + offset + 0, 4); - unsigned fourCC = read(sourceData + offset + 4, 4); - unsigned checksum = read(sourceData + offset + 8 + length, 4); - - if(fourCC == (unsigned)FourCC::IHDR) { - info.width = read(sourceData + offset + 8, 4); - info.height = read(sourceData + offset + 12, 4); - info.bitDepth = read(sourceData + offset + 16, 1); - info.colorType = read(sourceData + offset + 17, 1); - info.compressionMethod = read(sourceData + offset + 18, 1); - info.filterType = read(sourceData + offset + 19, 1); - info.interlaceMethod = read(sourceData + offset + 20, 1); - - if(info.bitDepth == 0 || info.bitDepth > 16) return false; - if(info.bitDepth & (info.bitDepth - 1)) return false; //not a power of two - if(info.compressionMethod != 0) return false; - if(info.filterType != 0) return false; - if(info.interlaceMethod != 0 && info.interlaceMethod != 1) return false; - - switch(info.colorType) { - case 0: info.bytesPerPixel = info.bitDepth * 1; break; //L - case 2: info.bytesPerPixel = info.bitDepth * 3; break; //R,G,B - case 3: info.bytesPerPixel = info.bitDepth * 1; break; //P - case 4: info.bytesPerPixel = info.bitDepth * 2; break; //L,A - case 6: info.bytesPerPixel = info.bitDepth * 4; break; //R,G,B,A - default: return false; - } - - if(info.colorType == 2 || info.colorType == 4 || info.colorType == 6) - if(info.bitDepth != 8 && info.bitDepth != 16) return false; - if(info.colorType == 3 && info.bitDepth == 16) return false; - - info.bytesPerPixel = (info.bytesPerPixel + 7) / 8; - info.pitch = (int)info.width * info.bytesPerPixel; - } - - if(fourCC == (unsigned)FourCC::PLTE) { - if(length % 3) return false; - for(unsigned n = 0, p = offset + 8; n < length / 3; n++) { - info.palette[n][0] = sourceData[p++]; - info.palette[n][1] = sourceData[p++]; - info.palette[n][2] = sourceData[p++]; - } - } - - if(fourCC == (unsigned)FourCC::IDAT) { - compressedData = (uint8_t*)realloc(compressedData, compressedSize + length); - memcpy(compressedData + compressedSize, sourceData + offset + 8, length); - compressedSize += length; - } - - if(fourCC == (unsigned)FourCC::IEND) { - break; - } - - offset += 4 + 4 + length + 4; - } - - unsigned interlacedSize = inflateSize(); - uint8_t *interlacedData = new uint8_t[interlacedSize]; - - bool result = inflate(interlacedData, interlacedSize, compressedData + 2, compressedSize - 6); - delete[] compressedData; - - if(result == false) { - delete[] interlacedData; - return false; - } - - size = info.width * info.height * info.bytesPerPixel; - data = new uint8_t[size]; - - if(info.interlaceMethod == 0) { - if(filter(data, interlacedData, info.width, info.height) == false) { - delete[] interlacedData; - delete[] data; - data = 0; - return false; - } - } else { - const uint8_t *passData = interlacedData; - for(unsigned pass = 0; pass < 7; pass++) { - if(deinterlace(passData, pass) == false) { - delete[] interlacedData; - delete[] data; - data = 0; - return false; - } - } - } - - delete[] interlacedData; - return true; -} - -unsigned png::interlace(unsigned pass, unsigned index) { - static const unsigned data[7][4] = { - //x-distance, y-distance, x-origin, y-origin - { 8, 8, 0, 0 }, - { 8, 8, 4, 0 }, - { 4, 8, 0, 4 }, - { 4, 4, 2, 0 }, - { 2, 4, 0, 2 }, - { 2, 2, 1, 0 }, - { 1, 2, 0, 1 }, - }; - return data[pass][index]; -} - -unsigned png::inflateSize() { - if(info.interlaceMethod == 0) { - return info.width * info.height * info.bytesPerPixel + info.height; - } - - unsigned size = 0; - for(unsigned pass = 0; pass < 7; pass++) { - unsigned xd = interlace(pass, 0), yd = interlace(pass, 1); - unsigned xo = interlace(pass, 2), yo = interlace(pass, 3); - unsigned width = (info.width + (xd - xo - 1)) / xd; - unsigned height = (info.height + (yd - yo - 1)) / yd; - if(width == 0 || height == 0) continue; - size += width * height * info.bytesPerPixel + height; - } - return size; -} - -bool png::deinterlace(const uint8_t *&inputData, unsigned pass) { - unsigned xd = interlace(pass, 0), yd = interlace(pass, 1); - unsigned xo = interlace(pass, 2), yo = interlace(pass, 3); - unsigned width = (info.width + (xd - xo - 1)) / xd; - unsigned height = (info.height + (yd - yo - 1)) / yd; - if(width == 0 || height == 0) return true; - - unsigned outputSize = width * height * info.bytesPerPixel; - uint8_t *outputData = new uint8_t[outputSize]; - bool result = filter(outputData, inputData, width, height); - - const uint8_t *rd = outputData; - for(unsigned y = yo; y < info.height; y += yd) { - uint8_t *wr = data + y * info.pitch; - for(unsigned x = xo; x < info.width; x += xd) { - for(unsigned b = 0; b < info.bytesPerPixel; b++) { - wr[x * info.bytesPerPixel + b] = *rd++; - } - } - } - - inputData += outputSize + height; - delete[] outputData; - return result; -} - -bool png::filter(uint8_t *outputData, const uint8_t *inputData, unsigned width, unsigned height) { - uint8_t *wr = outputData; - const uint8_t *rd = inputData; - int bpp = info.bytesPerPixel, pitch = width * bpp; - for(int y = 0; y < height; y++) { - uint8_t filter = *rd++; - - switch(filter) { - case 0x00: //None - for(int x = 0; x < pitch; x++) { - wr[x] = rd[x]; - } - break; - - case 0x01: //Subtract - for(int x = 0; x < pitch; x++) { - wr[x] = rd[x] + (x - bpp < 0 ? 0 : wr[x - bpp]); - } - break; - - case 0x02: //Above - for(int x = 0; x < pitch; x++) { - wr[x] = rd[x] + (y - 1 < 0 ? 0 : wr[x - pitch]); - } - break; - - case 0x03: //Average - for(int x = 0; x < pitch; x++) { - short a = x - bpp < 0 ? 0 : wr[x - bpp]; - short b = y - 1 < 0 ? 0 : wr[x - pitch]; - - wr[x] = rd[x] + (uint8_t)((a + b) / 2); - } - break; - - case 0x04: //Paeth - for(int x = 0; x < pitch; x++) { - short a = x - bpp < 0 ? 0 : wr[x - bpp]; - short b = y - 1 < 0 ? 0 : wr[x - pitch]; - short c = x - bpp < 0 || y - 1 < 0 ? 0 : wr[x - pitch - bpp]; - - short p = a + b - c; - short pa = p > a ? p - a : a - p; - short pb = p > b ? p - b : b - p; - short pc = p > c ? p - c : c - p; - - uint8_t paeth = (uint8_t)((pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c); - - wr[x] = rd[x] + paeth; - } - break; - - default: //Invalid - return false; - } - - rd += pitch; - wr += pitch; - } - - return true; -} - -unsigned png::read(const uint8_t *data, unsigned length) { - unsigned result = 0; - while(length--) result = (result << 8) | (*data++); - return result; -} - -unsigned png::readbits(const uint8_t *&data) { - unsigned result = 0; - switch(info.bitDepth) { - case 1: - result = (*data >> bitpos) & 1; - bitpos++; - if(bitpos == 8) { data++; bitpos = 0; } - break; - case 2: - result = (*data >> bitpos) & 3; - bitpos += 2; - if(bitpos == 8) { data++; bitpos = 0; } - break; - case 4: - result = (*data >> bitpos) & 15; - bitpos += 4; - if(bitpos == 8) { data++; bitpos = 0; } - break; - case 8: - result = *data++; - break; - case 16: - result = (data[0] << 8) | (data[1] << 0); - data += 2; - break; - } - return result; -} - -png::png() : data(nullptr) { - bitpos = 0; -} - -png::~png() { - if(data) delete[] data; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/priorityqueue.hpp b/waterbox/libsnes/bsnes/nall/priorityqueue.hpp deleted file mode 100644 index 390fcff586..0000000000 --- a/waterbox/libsnes/bsnes/nall/priorityqueue.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef NALL_PRIORITYQUEUE_HPP -#define NALL_PRIORITYQUEUE_HPP - -#include -#include -#include -#include - -namespace nall { - template void priority_queue_nocallback(type_t) {} - - //priority queue implementation using binary min-heap array; - //does not require normalize() function. - //O(1) find (tick) - //O(log n) append (enqueue) - //O(log n) remove (dequeue) - template class priority_queue { - public: - inline void tick(unsigned ticks) { - basecounter += ticks; - while(heapsize && gte(basecounter, heap[0].counter)) callback(dequeue()); - } - - //counter is relative to current time (eg enqueue(64, ...) fires in 64 ticks); - //counter cannot exceed std::numeric_limits::max() >> 1. - void enqueue(unsigned counter, type_t event) { - unsigned child = heapsize++; - counter += basecounter; - - while(child) { - unsigned parent = (child - 1) >> 1; - if(gte(counter, heap[parent].counter)) break; - - heap[child].counter = heap[parent].counter; - heap[child].event = heap[parent].event; - child = parent; - } - - heap[child].counter = counter; - heap[child].event = event; - } - - type_t dequeue() { - type_t event(heap[0].event); - unsigned parent = 0; - unsigned counter = heap[--heapsize].counter; - - while(true) { - unsigned child = (parent << 1) + 1; - if(child >= heapsize) break; - if(child + 1 < heapsize && gte(heap[child].counter, heap[child + 1].counter)) child++; - if(gte(heap[child].counter, counter)) break; - - heap[parent].counter = heap[child].counter; - heap[parent].event = heap[child].event; - parent = child; - } - - heap[parent].counter = counter; - heap[parent].event = heap[heapsize].event; - return event; - } - - void reset() { - basecounter = 0; - heapsize = 0; - } - - priority_queue(unsigned size, function callback_ = &priority_queue_nocallback) - : callback(callback_) { - heap = new heap_t[size]; - heapcapacity = size; - reset(); - } - - ~priority_queue() { - delete[] heap; - } - - priority_queue& operator=(const priority_queue&) = delete; - priority_queue(const priority_queue&) = delete; - - private: - function callback; - unsigned basecounter; - unsigned heapsize; - unsigned heapcapacity; - struct heap_t { - unsigned counter; - type_t event; - } *heap; - - //return true if x is greater than or equal to y - inline bool gte(unsigned x, unsigned y) { - return x - y < (std::numeric_limits::max() >> 1); - } - }; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/property.hpp b/waterbox/libsnes/bsnes/nall/property.hpp deleted file mode 100644 index 4796d1ef86..0000000000 --- a/waterbox/libsnes/bsnes/nall/property.hpp +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef NALL_PROPERTY_HPP -#define NALL_PROPERTY_HPP - -//nall::property implements ownership semantics into container classes -//example: property::readonly implies that only owner has full -//access to type; and all other code has readonly access. -// -//this code relies on extended friend semantics from C++0x to work, as it -//declares a friend class via a template paramter. it also exploits a bug in -//G++ 4.x to work even in C++98 mode. -// -//if compiling elsewhere, simply remove the friend class and private semantics - -//property can be used either of two ways: -//struct foo { -// property::readonly x; -// property::readwrite y; -//}; -//-or- -//struct foo : property { -// readonly x; -// readwrite y; -//}; - -//return types are const T& (byref) instead of T (byval) to avoid major speed -//penalties for objects with expensive copy constructors - -//operator-> provides access to underlying object type: -//readonly foo; -//foo->bar(); -//... will call Object::bar(); - -//operator='s reference is constant so as to avoid leaking a reference handle -//that could bypass access restrictions - -//both constant and non-constant operators are provided, though it may be -//necessary to cast first, for instance: -//struct foo : property { readonly bar; } object; -//int main() { int value = const_cast(object); } - -//writeonly is useful for objects that have non-const reads, but const writes. -//however, to avoid leaking handles, the interface is very restricted. the only -//way to write is via operator=, which requires conversion via eg copy -//constructor. example: -//struct foo { -// foo(bool value) { ... } -//}; -//writeonly bar; -//bar = true; - -#if defined(_MSC_VER) || defined(__clang__) -#define DUMB(X) -#else -#define DUMB(X) X -#endif - -namespace nall { - template struct property { - template struct traits { typedef T type; }; - - template struct readonly { - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - DUMB(private:) - T* operator->() { return &value; } - operator T&() { return value; } - const T& operator=(const T& value_) { return value = value_; } - T value; - DUMB(friend class traits::type); - }; - - template struct writeonly { - void operator=(const T& value_) { value = value_; } - DUMB(private:) - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - T* operator->() { return &value; } - operator T&() { return value; } - T value; - DUMB(friend class traits::type); - }; - - template struct readwrite { - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - T* operator->() { return &value; } - operator T&() { return value; } - const T& operator=(const T& value_) { return value = value_; } - T value; - }; - }; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/public_cast.hpp b/waterbox/libsnes/bsnes/nall/public_cast.hpp deleted file mode 100644 index 331800e1ff..0000000000 --- a/waterbox/libsnes/bsnes/nall/public_cast.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef NALL_PUBLIC_CAST_HPP -#define NALL_PUBLIC_CAST_HPP - -//this is a proof-of-concept-*only* C++ access-privilege elevation exploit. -//this code is 100% legal C++, per C++98 section 14.7.2 paragraph 8: -//"access checking rules do not apply to names in explicit instantiations." -//usage example: - -//struct N { typedef void (Class::*)(); }; -//template class public_cast; -//(class.*public_cast::value); - -//Class::Reference may be public, protected or private -//Class::Reference may be a function, object or variable - -namespace nall { - template struct public_cast; - - template struct public_cast { - static typename T::type value; - }; - - template typename T::type public_cast::value; - - template struct public_cast { - static typename T::type value; - }; - - template typename T::type public_cast::value = public_cast::value = P; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/random.hpp b/waterbox/libsnes/bsnes/nall/random.hpp deleted file mode 100644 index 409c456103..0000000000 --- a/waterbox/libsnes/bsnes/nall/random.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef NALL_RANDOM_HPP -#define NALL_RANDOM_HPP - -namespace nall { - //pseudo-random number generator - inline unsigned prng() { - static unsigned n = 0; - return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320); - } - - struct random_lfsr { - inline void seed(unsigned seed__) { - seed_ = seed__; - } - - inline unsigned operator()() { - return seed_ = (seed_ >> 1) ^ (((seed_ & 1) - 1) & 0xedb88320); - } - - random_lfsr() : seed_(0) { - } - - private: - unsigned seed_; - }; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/reference_array.hpp b/waterbox/libsnes/bsnes/nall/reference_array.hpp deleted file mode 100644 index 7c915090ff..0000000000 --- a/waterbox/libsnes/bsnes/nall/reference_array.hpp +++ /dev/null @@ -1,142 +0,0 @@ -#ifndef NALL_REFERENCE_ARRAY_HPP -#define NALL_REFERENCE_ARRAY_HPP - -#include -#include -#include - -namespace nall { - template struct reference_array { - struct exception_out_of_bounds{}; - - protected: - typedef typename std::remove_reference::type type_t; - type_t **pool; - unsigned poolsize, buffersize; - - public: - unsigned size() const { return buffersize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) free(pool); - pool = nullptr; - poolsize = 0; - buffersize = 0; - } - - void reserve(unsigned newsize) { - if(newsize == poolsize) return; - - pool = (type_t**)realloc(pool, sizeof(type_t*) * newsize); - poolsize = newsize; - buffersize = min(buffersize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(bit::round(newsize)); - buffersize = newsize; - } - - template - bool append(type_t& data, Args&&... args) { - bool result = append(data); - append(std::forward(args)...); - return result; - } - - bool append(type_t& data) { - for(unsigned index = 0; index < buffersize; index++) { - if(pool[index] == &data) return false; - } - - unsigned index = buffersize++; - if(index >= poolsize) resize(index + 1); - pool[index] = &data; - return true; - } - - bool remove(type_t& data) { - for(unsigned index = 0; index < buffersize; index++) { - if(pool[index] == &data) { - for(unsigned i = index; i < buffersize - 1; i++) pool[i] = pool[i + 1]; - resize(buffersize - 1); - return true; - } - } - return false; - } - - template reference_array(Args&... args) : pool(nullptr), poolsize(0), buffersize(0) { - construct(args...); - } - - ~reference_array() { - reset(); - } - - reference_array& operator=(const reference_array &source) { - if(pool) free(pool); - buffersize = source.buffersize; - poolsize = source.poolsize; - pool = (type_t**)malloc(sizeof(type_t*) * poolsize); - memcpy(pool, source.pool, sizeof(type_t*) * buffersize); - return *this; - } - - reference_array& operator=(const reference_array &&source) { - if(pool) free(pool); - pool = source.pool; - poolsize = source.poolsize; - buffersize = source.buffersize; - source.pool = nullptr; - source.reset(); - return *this; - } - - inline type_t& operator[](unsigned index) { - if(index >= buffersize) throw exception_out_of_bounds(); - return *pool[index]; - } - - inline type_t& operator[](unsigned index) const { - if(index >= buffersize) throw exception_out_of_bounds(); - return *pool[index]; - } - - //iteration - struct iterator { - bool operator!=(const iterator &source) const { return index != source.index; } - type_t& operator*() { return array.operator[](index); } - iterator& operator++() { index++; return *this; } - iterator(const reference_array &array, unsigned index) : array(array), index(index) {} - private: - const reference_array &array; - unsigned index; - }; - - iterator begin() { return iterator(*this, 0); } - iterator end() { return iterator(*this, buffersize); } - const iterator begin() const { return iterator(*this, 0); } - const iterator end() const { return iterator(*this, buffersize); } - - private: - void construct() { - } - - void construct(const reference_array &source) { - operator=(source); - } - - void construct(const reference_array &&source) { - operator=(std::move(source)); - } - - template void construct(T data, Args&... args) { - append(data); - construct(args...); - } - }; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/serial.hpp b/waterbox/libsnes/bsnes/nall/serial.hpp deleted file mode 100644 index 9ac8451a26..0000000000 --- a/waterbox/libsnes/bsnes/nall/serial.hpp +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef NALL_SERIAL_HPP -#define NALL_SERIAL_HPP - -#include -#include -#include -#include - -#include - -namespace nall { - class serial { - public: - //-1 on error, otherwise return bytes read - int read(uint8_t *data, unsigned length) { - if(port_open == false) return -1; - return ::read(port, (void*)data, length); - } - - //-1 on error, otherwise return bytes written - int write(const uint8_t *data, unsigned length) { - if(port_open == false) return -1; - return ::write(port, (void*)data, length); - } - - bool open(const char *portname, unsigned rate, bool flowcontrol) { - close(); - - port = ::open(portname, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); - if(port == -1) return false; - - if(ioctl(port, TIOCEXCL) == -1) { close(); return false; } - if(fcntl(port, F_SETFL, 0) == -1) { close(); return false; } - if(tcgetattr(port, &original_attr) == -1) { close(); return false; } - - termios attr = original_attr; - cfmakeraw(&attr); - cfsetspeed(&attr, rate); - - attr.c_lflag &=~ (ECHO | ECHONL | ISIG | ICANON | IEXTEN); - attr.c_iflag &=~ (BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY); - attr.c_iflag |= (IGNBRK | IGNPAR); - attr.c_oflag &=~ (OPOST); - attr.c_cflag &=~ (CSIZE | CSTOPB | PARENB | CLOCAL); - attr.c_cflag |= (CS8 | CREAD); - if(flowcontrol == false) { - attr.c_cflag &= ~CRTSCTS; - } else { - attr.c_cflag |= CRTSCTS; - } - attr.c_cc[VTIME] = attr.c_cc[VMIN] = 0; - - if(tcsetattr(port, TCSANOW, &attr) == -1) { close(); return false; } - return port_open = true; - } - - void close() { - if(port != -1) { - tcdrain(port); - if(port_open == true) { - tcsetattr(port, TCSANOW, &original_attr); - port_open = false; - } - ::close(port); - port = -1; - } - } - - serial() { - port = -1; - port_open = false; - } - - ~serial() { - close(); - } - - private: - int port; - bool port_open; - termios original_attr; - }; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/serializer.hpp b/waterbox/libsnes/bsnes/nall/serializer.hpp deleted file mode 100644 index 729e99e0dd..0000000000 --- a/waterbox/libsnes/bsnes/nall/serializer.hpp +++ /dev/null @@ -1,167 +0,0 @@ -#ifndef NALL_SERIALIZER_HPP -#define NALL_SERIALIZER_HPP - -#include -#include -#include -#include - -namespace nall { - //serializer: a class designed to save and restore the state of classes. - // - //benefits: - //- data() will be portable in size (it is not necessary to specify type sizes.) - //- data() will be portable in endianness (always stored internally as little-endian.) - //- one serialize function can both save and restore class states. - // - //caveats: - //- only plain-old-data can be stored. complex classes must provide serialize(serializer&); - //- floating-point usage is not portable across platforms - - class serializer { - public: - enum mode_t { Load, Save, Size }; - - mode_t mode() const { - return imode; - } - - const uint8_t* data() const { - return idata; - } - - unsigned size() const { - return isize; - } - - unsigned capacity() const { - return icapacity; - } - - template void floatingpoint(T &value) { - enum { size = sizeof(T) }; - //this is rather dangerous, and not cross-platform safe; - //but there is no standardized way to export FP-values - uint8_t *p = (uint8_t*)&value; - if(imode == Save) { - for(unsigned n = 0; n < size; n++) idata[isize++] = p[n]; - } else if(imode == Load) { - for(unsigned n = 0; n < size; n++) p[n] = idata[isize++]; - } else { - isize += size; - } - } - - template void integer(T &value) { - enum { size = std::is_same::value ? 1 : sizeof(T) }; - if(imode == Save) { - for(unsigned n = 0; n < size; n++) idata[isize++] = (uintmax_t)value >> (n << 3); - } else if(imode == Load) { - value = 0; - for(unsigned n = 0; n < size; n++) value |= (uintmax_t)idata[isize++] << (n << 3); - } else if(imode == Size) { - isize += size; - } - } - - template void integer(const T &value) { - enum { size = std::is_same::value ? 1 : sizeof(T) }; - if(imode == Save) { - for(unsigned n = 0; n < size; n++) idata[isize++] = (uintmax_t)value >> (n << 3); - } else if(imode == Load) { - } else if(imode == Size) { - isize += size; - } - } - - template void array(T *array, int size) { - for(unsigned n = 0; n < size; n++) integer(array[n]); - } - - template void array(T &array) { - enum { size = sizeof(T) / sizeof(typename std::remove_extent::type) }; - for(unsigned n = 0; n < size; n++) integer(array[n]); - } - - template void array(const T &array) { - enum { size = sizeof(T) / sizeof(typename std::remove_extent::type) }; - for(unsigned n = 0; n < size; n++) integer(array[n]); - } - - template void array(T array, unsigned size) { - for(unsigned n = 0; n < size; n++) integer(array[n]); - } - - //copy - serializer& operator=(const serializer &s) { - if(idata) delete[] idata; - - imode = s.imode; - idata = new uint8_t[s.icapacity]; - isize = s.isize; - icapacity = s.icapacity; - - memcpy(idata, s.idata, s.icapacity); - return *this; - } - - serializer(const serializer &s) : idata(0) { - operator=(s); - } - - //move - serializer& operator=(serializer &&s) { - if(idata) delete[] idata; - - imode = s.imode; - idata = s.idata; - isize = s.isize; - icapacity = s.icapacity; - - s.idata = 0; - return *this; - } - - serializer(serializer &&s) - : idata(nullptr) //zero 16-jun-2015 - was a bug not to have this. operator= chokes on uninitialized idata otherwise - { - operator=(std::move(s)); - } - - //construction - serializer() { - imode = Size; - idata = 0; - isize = 0; - icapacity = 0; - } - - serializer(unsigned capacity) { - imode = Save; - idata = new uint8_t[capacity](); - isize = 0; - icapacity = capacity; - } - - serializer(const uint8_t *data, unsigned capacity) { - imode = Load; - idata = new uint8_t[capacity]; - isize = 0; - icapacity = capacity; - memcpy(idata, data, capacity); - } - - ~serializer() { - if(idata) delete[] idata; - } - - private: - mode_t imode; - uint8_t *idata; - unsigned isize; - unsigned icapacity; - }; - -}; - -#endif diff --git a/waterbox/libsnes/bsnes/nall/sha256.hpp b/waterbox/libsnes/bsnes/nall/sha256.hpp deleted file mode 100644 index c63367a7a9..0000000000 --- a/waterbox/libsnes/bsnes/nall/sha256.hpp +++ /dev/null @@ -1,145 +0,0 @@ -#ifndef NALL_SHA256_HPP -#define NALL_SHA256_HPP - -//author: vladitx - -#include - -namespace nall { - #define PTR(t, a) ((t*)(a)) - - #define SWAP32(x) ((uint32_t)( \ - (((uint32_t)(x) & 0x000000ff) << 24) | \ - (((uint32_t)(x) & 0x0000ff00) << 8) | \ - (((uint32_t)(x) & 0x00ff0000) >> 8) | \ - (((uint32_t)(x) & 0xff000000) >> 24) \ - )) - - #define ST32(a, d) *PTR(uint32_t, a) = (d) - #define ST32BE(a, d) ST32(a, SWAP32(d)) - - #define LD32(a) *PTR(uint32_t, a) - #define LD32BE(a) SWAP32(LD32(a)) - - #define LSL32(x, n) ((uint32_t)(x) << (n)) - #define LSR32(x, n) ((uint32_t)(x) >> (n)) - #define ROR32(x, n) (LSR32(x, n) | LSL32(x, 32 - (n))) - - //first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19 - static const uint32_t T_H[8] = { - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, - }; - - //first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311 - static const uint32_t T_K[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, - }; - - struct sha256_ctx { - uint8_t in[64]; - unsigned inlen; - - uint32_t w[64]; - uint32_t h[8]; - uint64_t len; - }; - - inline void sha256_init(sha256_ctx *p) { - memset(p, 0, sizeof(sha256_ctx)); - memcpy(p->h, T_H, sizeof(T_H)); - } - - static void sha256_block(sha256_ctx *p) { - unsigned i; - uint32_t s0, s1; - uint32_t a, b, c, d, e, f, g, h; - uint32_t t1, t2, maj, ch; - - for(i = 0; i < 16; i++) p->w[i] = LD32BE(p->in + i * 4); - - for(i = 16; i < 64; i++) { - s0 = ROR32(p->w[i - 15], 7) ^ ROR32(p->w[i - 15], 18) ^ LSR32(p->w[i - 15], 3); - s1 = ROR32(p->w[i - 2], 17) ^ ROR32(p->w[i - 2], 19) ^ LSR32(p->w[i - 2], 10); - p->w[i] = p->w[i - 16] + s0 + p->w[i - 7] + s1; - } - - a = p->h[0]; b = p->h[1]; c = p->h[2]; d = p->h[3]; - e = p->h[4]; f = p->h[5]; g = p->h[6]; h = p->h[7]; - - for(i = 0; i < 64; i++) { - s0 = ROR32(a, 2) ^ ROR32(a, 13) ^ ROR32(a, 22); - maj = (a & b) ^ (a & c) ^ (b & c); - t2 = s0 + maj; - s1 = ROR32(e, 6) ^ ROR32(e, 11) ^ ROR32(e, 25); - ch = (e & f) ^ (~e & g); - t1 = h + s1 + ch + T_K[i] + p->w[i]; - - h = g; g = f; f = e; e = d + t1; - d = c; c = b; b = a; a = t1 + t2; - } - - p->h[0] += a; p->h[1] += b; p->h[2] += c; p->h[3] += d; - p->h[4] += e; p->h[5] += f; p->h[6] += g; p->h[7] += h; - - //next block - p->inlen = 0; - } - - inline void sha256_chunk(sha256_ctx *p, const uint8_t *s, unsigned len) { - unsigned l; - p->len += len; - - while(len) { - l = 64 - p->inlen; - l = (len < l) ? len : l; - - memcpy(p->in + p->inlen, s, l); - s += l; - p->inlen += l; - len -= l; - - if(p->inlen == 64) sha256_block(p); - } - } - - inline void sha256_final(sha256_ctx *p) { - uint64_t len; - p->in[p->inlen++] = 0x80; - - if(p->inlen > 56) { - memset(p->in + p->inlen, 0, 64 - p->inlen); - sha256_block(p); - } - - memset(p->in + p->inlen, 0, 56 - p->inlen); - - len = p->len << 3; - ST32BE(p->in + 56, len >> 32); - ST32BE(p->in + 60, len); - sha256_block(p); - } - - inline void sha256_hash(sha256_ctx *p, uint8_t *s) { - uint32_t *t = (uint32_t*)s; - for(unsigned i = 0; i < 8; i++) ST32BE(t++, p->h[i]); - } - - #undef PTR - #undef SWAP32 - #undef ST32 - #undef ST32BE - #undef LD32 - #undef LD32BE - #undef LSL32 - #undef LSR32 - #undef ROR32 -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/snes/cartridge.hpp b/waterbox/libsnes/bsnes/nall/snes/cartridge.hpp deleted file mode 100644 index 5596f69b5c..0000000000 --- a/waterbox/libsnes/bsnes/nall/snes/cartridge.hpp +++ /dev/null @@ -1,886 +0,0 @@ -#ifndef NALL_SNES_CARTRIDGE_HPP -#define NALL_SNES_CARTRIDGE_HPP - -namespace nall { - -class SnesCartridge { -public: - string markup; - inline SnesCartridge(const uint8_t *data, unsigned size); - -//private: - inline void read_header(const uint8_t *data, unsigned size); - inline unsigned find_header(const uint8_t *data, unsigned size); - inline unsigned score_header(const uint8_t *data, unsigned size, unsigned addr); - inline unsigned gameboy_ram_size(const uint8_t *data, unsigned size); - inline bool gameboy_has_rtc(const uint8_t *data, unsigned size); - - enum HeaderField { - CartName = 0x00, - Mapper = 0x15, - RomType = 0x16, - RomSize = 0x17, - RamSize = 0x18, - CartRegion = 0x19, - Company = 0x1a, - Version = 0x1b, - Complement = 0x1c, //inverse checksum - Checksum = 0x1e, - ResetVector = 0x3c, - }; - - enum Mode { - ModeNormal, - ModeBsxSlotted, - ModeBsx, - ModeSufamiTurbo, - ModeSuperGameBoy, - }; - - enum Type { - TypeNormal, - TypeBsxSlotted, - TypeBsxBios, - TypeBsx, - TypeSufamiTurboBios, - TypeSufamiTurbo, - TypeSuperGameBoy1Bios, - TypeSuperGameBoy2Bios, - TypeGameBoy, - TypeUnknown, - }; - - enum Region { - NTSC, - PAL, - }; - - enum MemoryMapper { - LoROM, - HiROM, - ExLoROM, - ExHiROM, - SuperFXROM, - SA1ROM, - SPC7110ROM, - BSCLoROM, - BSCHiROM, - BSXROM, - STROM, - }; - - enum DSP1MemoryMapper { - DSP1Unmapped, - DSP1LoROM1MB, - DSP1LoROM2MB, - DSP1HiROM, - }; - - bool loaded; //is a base cartridge inserted? - unsigned crc32; //crc32 of all cartridges (base+slot(s)) - unsigned rom_size; - unsigned ram_size; - - Mode mode; - Type type; - Region region; - MemoryMapper mapper; - DSP1MemoryMapper dsp1_mapper; - - bool has_bsx_slot; - bool has_superfx; - bool has_sa1; - bool has_srtc; - bool has_sdd1; - bool has_spc7110; - bool has_spc7110rtc; - bool has_cx4; - bool has_dsp1; - bool has_dsp2; - bool has_dsp3; - bool has_dsp4; - bool has_obc1; - bool has_st010; - bool has_st011; - bool has_st018; -}; - -SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) { - read_header(data, size); - - string xml; - markup = "\n"; - - if(type == TypeBsx) { - markup.append("\n"); - return; - } - - if(type == TypeSufamiTurbo) { - markup.append("\n"); - return; - } - - if(type == TypeGameBoy) { - markup.append(" 0) { - markup.append(" \n"); - } - markup.append("\n"); - return; - } - - const char *range = (rom_size > 0x200000) || (ram_size > 32 * 1024) ? "0000-7fff" : "0000-ffff"; - markup.append("\n"); - - if(type == TypeSuperGameBoy1Bios || type == TypeSuperGameBoy2Bios) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - - else if(has_cx4) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - - else if(has_spc7110) { - markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - if(has_spc7110rtc) markup.append( - " \n" - " \n" - " \n" - " \n" - ); - markup.append( - " \n" - ); - } - - else if(mapper == LoROM) { - markup.append( - " \n" - " \n" - " \n" - " \n" - ); - if(ram_size > 0) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - } - - else if(mapper == HiROM) { - markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - if(ram_size > 0) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - ); - } - - else if(mapper == ExLoROM) { - markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - ); - if(ram_size > 0) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - ); - } - - else if(mapper == ExHiROM) { - markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - if(ram_size > 0) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - ); - } - - else if(mapper == SuperFXROM) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - - else if(mapper == SA1ROM) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - - else if(mapper == BSCLoROM) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - - else if(mapper == BSCHiROM) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - - else if(mapper == BSXROM) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - - else if(mapper == STROM) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - - if(has_srtc) markup.append( - " \n" - " \n" - " \n" - " \n" - ); - - if(has_sdd1) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - - if(has_obc1) markup.append( - " \n" - " \n" - " \n" - " \n" - ); - - if(has_dsp1) { - //91e87d11e1c30d172556bed2211cce2efa94ba595f58c5d264809ef4d363a97b dsp1.rom - markup.append(" \n"); - if(dsp1_mapper == DSP1LoROM1MB) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - if(dsp1_mapper == DSP1LoROM2MB) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - if(dsp1_mapper == DSP1HiROM) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - markup.append(" \n"); - } - - if(has_dsp2) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - - if(has_dsp3) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - - if(has_dsp4) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - - if(has_st010) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - - if(has_st011) markup.append( - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ); - - if(has_st018) markup.append( - " \n" - " \n" - " \n" - " \n" - ); - - markup.append("\n"); -} - -void SnesCartridge::read_header(const uint8_t *data, unsigned size) { - type = TypeUnknown; - mapper = LoROM; - dsp1_mapper = DSP1Unmapped; - region = NTSC; - rom_size = size; - ram_size = 0; - - has_bsx_slot = false; - has_superfx = false; - has_sa1 = false; - has_srtc = false; - has_sdd1 = false; - has_spc7110 = false; - has_spc7110rtc = false; - has_cx4 = false; - has_dsp1 = false; - has_dsp2 = false; - has_dsp3 = false; - has_dsp4 = false; - has_obc1 = false; - has_st010 = false; - has_st011 = false; - has_st018 = false; - - //===================== - //detect Game Boy carts - //===================== - - if(size >= 0x0140) { - if(data[0x0104] == 0xce && data[0x0105] == 0xed && data[0x0106] == 0x66 && data[0x0107] == 0x66 - && data[0x0108] == 0xcc && data[0x0109] == 0x0d && data[0x010a] == 0x00 && data[0x010b] == 0x0b) { - type = TypeGameBoy; - return; - } - } - - if(size < 32768) { - type = TypeUnknown; - return; - } - - const unsigned index = find_header(data, size); - const uint8_t mapperid = data[index + Mapper]; - const uint8_t rom_type = data[index + RomType]; - const uint8_t rom_size = data[index + RomSize]; - const uint8_t company = data[index + Company]; - const uint8_t regionid = data[index + CartRegion] & 0x7f; - - ram_size = 1024 << (data[index + RamSize] & 7); - if(ram_size == 1024) ram_size = 0; //no RAM present - - //0, 1, 13 = NTSC; 2 - 12 = PAL - region = (regionid <= 1 || regionid >= 13) ? NTSC : PAL; - - //======================= - //detect BS-X flash carts - //======================= - - if(data[index + 0x13] == 0x00 || data[index + 0x13] == 0xff) { - if(data[index + 0x14] == 0x00) { - const uint8_t n15 = data[index + 0x15]; - if(n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc) { - if(data[index + 0x1a] == 0x33 || data[index + 0x1a] == 0xff) { - type = TypeBsx; - mapper = BSXROM; - region = NTSC; //BS-X only released in Japan - return; - } - } - } - } - - //========================= - //detect Sufami Turbo carts - //========================= - - if(!memcmp(data, "BANDAI SFC-ADX", 14)) { - if(!memcmp(data + 16, "SFC-ADX BACKUP", 14)) { - type = TypeSufamiTurboBios; - } else { - type = TypeSufamiTurbo; - } - mapper = STROM; - region = NTSC; //Sufami Turbo only released in Japan - return; //RAM size handled outside this routine - } - - //========================== - //detect Super Game Boy BIOS - //========================== - - if(!memcmp(data + index, "Super GAMEBOY2", 14)) { - type = TypeSuperGameBoy2Bios; - return; - } - - if(!memcmp(data + index, "Super GAMEBOY", 13)) { - type = TypeSuperGameBoy1Bios; - return; - } - - //===================== - //detect standard carts - //===================== - - //detect presence of BS-X flash cartridge connector (reads extended header information) - if(data[index - 14] == 'Z') { - if(data[index - 11] == 'J') { - uint8_t n13 = data[index - 13]; - if((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) { - if(company == 0x33 || (data[index - 10] == 0x00 && data[index - 4] == 0x00)) { - has_bsx_slot = true; - } - } - } - } - - if(has_bsx_slot) { - if(!memcmp(data + index, "Satellaview BS-X ", 21)) { - //BS-X base cart - type = TypeBsxBios; - mapper = BSXROM; - region = NTSC; //BS-X only released in Japan - return; //RAM size handled internally by load_cart_bsx() -> BSXCart class - } else { - type = TypeBsxSlotted; - mapper = (index == 0x7fc0 ? BSCLoROM : BSCHiROM); - region = NTSC; //BS-X slotted cartridges only released in Japan - } - } else { - //standard cart - type = TypeNormal; - - if(index == 0x7fc0 && size >= 0x401000) { - mapper = ExLoROM; - } else if(index == 0x7fc0 && mapperid == 0x32) { - mapper = ExLoROM; - } else if(index == 0x7fc0) { - mapper = LoROM; - } else if(index == 0xffc0) { - mapper = HiROM; - } else { //index == 0x40ffc0 - mapper = ExHiROM; - } - } - - if(mapperid == 0x20 && (rom_type == 0x13 || rom_type == 0x14 || rom_type == 0x15 || rom_type == 0x1a)) { - has_superfx = true; - mapper = SuperFXROM; - ram_size = 1024 << (data[index - 3] & 7); - if(ram_size == 1024) ram_size = 0; - } - - if(mapperid == 0x23 && (rom_type == 0x32 || rom_type == 0x34 || rom_type == 0x35)) { - has_sa1 = true; - mapper = SA1ROM; - } - - if(mapperid == 0x35 && rom_type == 0x55) { - has_srtc = true; - } - - if(mapperid == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) { - has_sdd1 = true; - } - - if(mapperid == 0x3a && (rom_type == 0xf5 || rom_type == 0xf9)) { - has_spc7110 = true; - has_spc7110rtc = (rom_type == 0xf9); - mapper = SPC7110ROM; - } - - if(mapperid == 0x20 && rom_type == 0xf3) { - has_cx4 = true; - } - - if((mapperid == 0x20 || mapperid == 0x21) && rom_type == 0x03) { - has_dsp1 = true; - } - - if(mapperid == 0x30 && rom_type == 0x05 && company != 0xb2) { - has_dsp1 = true; - } - - if(mapperid == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) { - has_dsp1 = true; - } - - if(has_dsp1 == true) { - if((mapperid & 0x2f) == 0x20 && size <= 0x100000) { - dsp1_mapper = DSP1LoROM1MB; - } else if((mapperid & 0x2f) == 0x20) { - dsp1_mapper = DSP1LoROM2MB; - } else if((mapperid & 0x2f) == 0x21) { - dsp1_mapper = DSP1HiROM; - } - } - - if(mapperid == 0x20 && rom_type == 0x05) { - has_dsp2 = true; - } - - if(mapperid == 0x30 && rom_type == 0x05 && company == 0xb2) { - has_dsp3 = true; - } - - if(mapperid == 0x30 && rom_type == 0x03) { - has_dsp4 = true; - } - - if(mapperid == 0x30 && rom_type == 0x25) { - has_obc1 = true; - } - - if(mapperid == 0x30 && rom_type == 0xf6 && rom_size >= 10) { - has_st010 = true; - } - - if(mapperid == 0x30 && rom_type == 0xf6 && rom_size < 10) { - has_st011 = true; - } - - if(mapperid == 0x30 && rom_type == 0xf5) { - has_st018 = true; - } -} - -unsigned SnesCartridge::find_header(const uint8_t *data, unsigned size) { - unsigned score_lo = score_header(data, size, 0x007fc0); - unsigned score_hi = score_header(data, size, 0x00ffc0); - unsigned score_ex = score_header(data, size, 0x40ffc0); - if(score_ex) score_ex += 4; //favor ExHiROM on images > 32mbits - - if(score_lo >= score_hi && score_lo >= score_ex) { - return 0x007fc0; - } else if(score_hi >= score_ex) { - return 0x00ffc0; - } else { - return 0x40ffc0; - } -} - -unsigned SnesCartridge::score_header(const uint8_t *data, unsigned size, unsigned addr) { - if(size < addr + 64) return 0; //image too small to contain header at this location? - int score = 0; - - uint16_t resetvector = data[addr + ResetVector] | (data[addr + ResetVector + 1] << 8); - uint16_t checksum = data[addr + Checksum ] | (data[addr + Checksum + 1] << 8); - uint16_t complement = data[addr + Complement ] | (data[addr + Complement + 1] << 8); - - uint8_t resetop = data[(addr & ~0x7fff) | (resetvector & 0x7fff)]; //first opcode executed upon reset - uint8_t mapper = data[addr + Mapper] & ~0x10; //mask off irrelevent FastROM-capable bit - - //$00:[000-7fff] contains uninitialized RAM and MMIO. - //reset vector must point to ROM at $00:[8000-ffff] to be considered valid. - if(resetvector < 0x8000) return 0; - - //some images duplicate the header in multiple locations, and others have completely - //invalid header information that cannot be relied upon. - //below code will analyze the first opcode executed at the specified reset vector to - //determine the probability that this is the correct header. - - //most likely opcodes - if(resetop == 0x78 //sei - || resetop == 0x18 //clc (clc; xce) - || resetop == 0x38 //sec (sec; xce) - || resetop == 0x9c //stz $nnnn (stz $4200) - || resetop == 0x4c //jmp $nnnn - || resetop == 0x5c //jml $nnnnnn - ) score += 8; - - //plausible opcodes - if(resetop == 0xc2 //rep #$nn - || resetop == 0xe2 //sep #$nn - || resetop == 0xad //lda $nnnn - || resetop == 0xae //ldx $nnnn - || resetop == 0xac //ldy $nnnn - || resetop == 0xaf //lda $nnnnnn - || resetop == 0xa9 //lda #$nn - || resetop == 0xa2 //ldx #$nn - || resetop == 0xa0 //ldy #$nn - || resetop == 0x20 //jsr $nnnn - || resetop == 0x22 //jsl $nnnnnn - ) score += 4; - - //implausible opcodes - if(resetop == 0x40 //rti - || resetop == 0x60 //rts - || resetop == 0x6b //rtl - || resetop == 0xcd //cmp $nnnn - || resetop == 0xec //cpx $nnnn - || resetop == 0xcc //cpy $nnnn - ) score -= 4; - - //least likely opcodes - if(resetop == 0x00 //brk #$nn - || resetop == 0x02 //cop #$nn - || resetop == 0xdb //stp - || resetop == 0x42 //wdm - || resetop == 0xff //sbc $nnnnnn,x - ) score -= 8; - - //at times, both the header and reset vector's first opcode will match ... - //fallback and rely on info validity in these cases to determine more likely header. - - //a valid checksum is the biggest indicator of a valid header. - if((checksum + complement) == 0xffff && (checksum != 0) && (complement != 0)) score += 4; - - if(addr == 0x007fc0 && mapper == 0x20) score += 2; //0x20 is usually LoROM - if(addr == 0x00ffc0 && mapper == 0x21) score += 2; //0x21 is usually HiROM - if(addr == 0x007fc0 && mapper == 0x22) score += 2; //0x22 is usually ExLoROM - if(addr == 0x40ffc0 && mapper == 0x25) score += 2; //0x25 is usually ExHiROM - - if(data[addr + Company] == 0x33) score += 2; //0x33 indicates extended header - if(data[addr + RomType] < 0x08) score++; - if(data[addr + RomSize] < 0x10) score++; - if(data[addr + RamSize] < 0x08) score++; - if(data[addr + CartRegion] < 14) score++; - - if(score < 0) score = 0; - return score; -} - -unsigned SnesCartridge::gameboy_ram_size(const uint8_t *data, unsigned size) { - if(size < 512) return 0; - switch(data[0x0149]) { - case 0x00: return 0 * 1024; - case 0x01: return 8 * 1024; - case 0x02: return 8 * 1024; - case 0x03: return 32 * 1024; - case 0x04: return 128 * 1024; - case 0x05: return 128 * 1024; - default: return 128 * 1024; - } -} - -bool SnesCartridge::gameboy_has_rtc(const uint8_t *data, unsigned size) { - if(size < 512) return false; - if(data[0x0147] == 0x0f ||data[0x0147] == 0x10) return true; - return false; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/snes/cpu.hpp b/waterbox/libsnes/bsnes/nall/snes/cpu.hpp deleted file mode 100644 index 28f5ddb58e..0000000000 --- a/waterbox/libsnes/bsnes/nall/snes/cpu.hpp +++ /dev/null @@ -1,458 +0,0 @@ -#ifndef NALL_SNES_CPU_HPP -#define NALL_SNES_CPU_HPP - -namespace nall { - -struct SNESCPU { - enum : unsigned { - Implied, // - Constant, //#$00 - AccumConstant, //#$00 - IndexConstant, //#$00 - Direct, //$00 - DirectX, //$00,x - DirectY, //$00,y - IDirect, //($00) - IDirectX, //($00,x) - IDirectY, //($00),y - ILDirect, //[$00] - ILDirectY, //[$00],y - Address, //$0000 - AddressX, //$0000,x - AddressY, //$0000,y - IAddressX, //($0000,x) - ILAddress, //[$0000] - PAddress, //PBR:$0000 - PIAddress, //PBR:($0000) - Long, //$000000 - LongX, //$000000,x - Stack, //$00,s - IStackY, //($00,s),y - BlockMove, //$00,$00 - RelativeShort, //+/- $00 - RelativeLong, //+/- $0000 - }; - - struct OpcodeInfo { - char name[4]; - unsigned mode; - }; - - static const OpcodeInfo opcodeInfo[256]; - - static unsigned getOpcodeLength(bool accum, bool index, uint8_t opcode); - static string disassemble(unsigned pc, bool accum, bool index, uint8_t opcode, uint8_t pl, uint8_t ph, uint8_t pb); -}; - -const SNESCPU::OpcodeInfo SNESCPU::opcodeInfo[256] = { - //0x00 - 0x0f - { "brk", Constant }, - { "ora", IDirectX }, - { "cop", Constant }, - { "ora", Stack }, - - { "tsb", Direct }, - { "ora", Direct }, - { "asl", Direct }, - { "ora", ILDirect }, - - { "php", Implied }, - { "ora", AccumConstant }, - { "asl", Implied }, - { "phd", Implied }, - - { "tsb", Address }, - { "ora", Address }, - { "asl", Address }, - { "ora", Long }, - - //0x10 - 0x1f - { "bpl", RelativeShort }, - { "ora", IDirectY }, - { "ora", IDirect }, - { "ora", IStackY }, - - { "trb", Direct }, - { "ora", DirectX }, - { "asl", DirectX }, - { "ora", ILDirectY }, - - { "clc", Implied }, - { "ora", AddressY }, - { "inc", Implied }, - { "tcs", Implied }, - - { "trb", Address }, - { "ora", AddressX }, - { "asl", AddressX }, - { "ora", LongX }, - - //0x20 - 0x2f - { "jsr", Address }, - { "and", IDirectX }, - { "jsl", Long }, - { "and", Stack }, - - { "bit", Direct }, - { "and", Direct }, - { "rol", Direct }, - { "and", ILDirect }, - - { "plp", Implied }, - { "and", AccumConstant }, - { "rol", Implied }, - { "pld", Implied }, - - { "bit", Address }, - { "and", Address }, - { "rol", Address }, - { "and", Long }, - - //0x30 - 0x3f - { "bmi", RelativeShort }, - { "and", IDirectY }, - { "and", IDirect }, - { "and", IStackY }, - - { "bit", DirectX }, - { "and", DirectX }, - { "rol", DirectX }, - { "and", ILDirectY }, - - { "sec", Implied }, - { "and", AddressY }, - { "dec", Implied }, - { "tsc", Implied }, - - { "bit", AddressX }, - { "and", AddressX }, - { "rol", AddressX }, - { "and", LongX }, - - //0x40 - 0x4f - { "rti", Implied }, - { "eor", IDirectX }, - { "wdm", Constant }, - { "eor", Stack }, - - { "mvp", BlockMove }, - { "eor", Direct }, - { "lsr", Direct }, - { "eor", ILDirect }, - - { "pha", Implied }, - { "eor", AccumConstant }, - { "lsr", Implied }, - { "phk", Implied }, - - { "jmp", PAddress }, - { "eor", Address }, - { "lsr", Address }, - { "eor", Long }, - - //0x50 - 0x5f - { "bvc", RelativeShort }, - { "eor", IDirectY }, - { "eor", IDirect }, - { "eor", IStackY }, - - { "mvn", BlockMove }, - { "eor", DirectX }, - { "lsr", DirectX }, - { "eor", ILDirectY }, - - { "cli", Implied }, - { "eor", AddressY }, - { "phy", Implied }, - { "tcd", Implied }, - - { "jml", Long }, - { "eor", AddressX }, - { "lsr", AddressX }, - { "eor", LongX }, - - //0x60 - 0x6f - { "rts", Implied }, - { "adc", IDirectX }, - { "per", Address }, - { "adc", Stack }, - - { "stz", Direct }, - { "adc", Direct }, - { "ror", Direct }, - { "adc", ILDirect }, - - { "pla", Implied }, - { "adc", AccumConstant }, - { "ror", Implied }, - { "rtl", Implied }, - - { "jmp", PIAddress }, - { "adc", Address }, - { "ror", Address }, - { "adc", Long }, - - //0x70 - 0x7f - { "bvs", RelativeShort }, - { "adc", IDirectY }, - { "adc", IDirect }, - { "adc", IStackY }, - - { "stz", DirectX }, - { "adc", DirectX }, - { "ror", DirectX }, - { "adc", ILDirectY }, - - { "sei", Implied }, - { "adc", AddressY }, - { "ply", Implied }, - { "tdc", Implied }, - - { "jmp", IAddressX }, - { "adc", AddressX }, - { "ror", AddressX }, - { "adc", LongX }, - - //0x80 - 0x8f - { "bra", RelativeShort }, - { "sta", IDirectX }, - { "brl", RelativeLong }, - { "sta", Stack }, - - { "sty", Direct }, - { "sta", Direct }, - { "stx", Direct }, - { "sta", ILDirect }, - - { "dey", Implied }, - { "bit", AccumConstant }, - { "txa", Implied }, - { "phb", Implied }, - - { "sty", Address }, - { "sta", Address }, - { "stx", Address }, - { "sta", Long }, - - //0x90 - 0x9f - { "bcc", RelativeShort }, - { "sta", IDirectY }, - { "sta", IDirect }, - { "sta", IStackY }, - - { "sty", DirectX }, - { "sta", DirectX }, - { "stx", DirectY }, - { "sta", ILDirectY }, - - { "tya", Implied }, - { "sta", AddressY }, - { "txs", Implied }, - { "txy", Implied }, - - { "stz", Address }, - { "sta", AddressX }, - { "stz", AddressX }, - { "sta", LongX }, - - //0xa0 - 0xaf - { "ldy", IndexConstant }, - { "lda", IDirectX }, - { "ldx", IndexConstant }, - { "lda", Stack }, - - { "ldy", Direct }, - { "lda", Direct }, - { "ldx", Direct }, - { "lda", ILDirect }, - - { "tay", Implied }, - { "lda", AccumConstant }, - { "tax", Implied }, - { "plb", Implied }, - - { "ldy", Address }, - { "lda", Address }, - { "ldx", Address }, - { "lda", Long }, - - //0xb0 - 0xbf - { "bcs", RelativeShort }, - { "lda", IDirectY }, - { "lda", IDirect }, - { "lda", IStackY }, - - { "ldy", DirectX }, - { "lda", DirectX }, - { "ldx", DirectY }, - { "lda", ILDirectY }, - - { "clv", Implied }, - { "lda", AddressY }, - { "tsx", Implied }, - { "tyx", Implied }, - - { "ldy", AddressX }, - { "lda", AddressX }, - { "ldx", AddressY }, - { "lda", LongX }, - - //0xc0 - 0xcf - { "cpy", IndexConstant }, - { "cmp", IDirectX }, - { "rep", Constant }, - { "cmp", Stack }, - - { "cpy", Direct }, - { "cmp", Direct }, - { "dec", Direct }, - { "cmp", ILDirect }, - - { "iny", Implied }, - { "cmp", AccumConstant }, - { "dex", Implied }, - { "wai", Implied }, - - { "cpy", Address }, - { "cmp", Address }, - { "dec", Address }, - { "cmp", Long }, - - //0xd0 - 0xdf - { "bne", RelativeShort }, - { "cmp", IDirectY }, - { "cmp", IDirect }, - { "cmp", IStackY }, - - { "pei", IDirect }, - { "cmp", DirectX }, - { "dec", DirectX }, - { "cmp", ILDirectY }, - - { "cld", Implied }, - { "cmp", AddressY }, - { "phx", Implied }, - { "stp", Implied }, - - { "jmp", ILAddress }, - { "cmp", AddressX }, - { "dec", AddressX }, - { "cmp", LongX }, - - //0xe0 - 0xef - { "cpx", IndexConstant }, - { "sbc", IDirectX }, - { "sep", Constant }, - { "sbc", Stack }, - - { "cpx", Direct }, - { "sbc", Direct }, - { "inc", Direct }, - { "sbc", ILDirect }, - - { "inx", Implied }, - { "sbc", AccumConstant }, - { "nop", Implied }, - { "xba", Implied }, - - { "cpx", Address }, - { "sbc", Address }, - { "inc", Address }, - { "sbc", Long }, - - //0xf0 - 0xff - { "beq", RelativeShort }, - { "sbc", IDirectY }, - { "sbc", IDirect }, - { "sbc", IStackY }, - - { "pea", Address }, - { "sbc", DirectX }, - { "inc", DirectX }, - { "sbc", ILDirectY }, - - { "sed", Implied }, - { "sbc", AddressY }, - { "plx", Implied }, - { "xce", Implied }, - - { "jsr", IAddressX }, - { "sbc", AddressX }, - { "inc", AddressX }, - { "sbc", LongX }, -}; - -inline unsigned SNESCPU::getOpcodeLength(bool accum, bool index, uint8_t opcode) { - switch(opcodeInfo[opcode].mode) { default: - case Implied: return 1; - case Constant: return 2; - case AccumConstant: return 3 - accum; - case IndexConstant: return 3 - index; - case Direct: return 2; - case DirectX: return 2; - case DirectY: return 2; - case IDirect: return 2; - case IDirectX: return 2; - case IDirectY: return 2; - case ILDirect: return 2; - case ILDirectY: return 2; - case Address: return 3; - case AddressX: return 3; - case AddressY: return 3; - case IAddressX: return 3; - case ILAddress: return 3; - case PAddress: return 3; - case PIAddress: return 3; - case Long: return 4; - case LongX: return 4; - case Stack: return 2; - case IStackY: return 2; - case BlockMove: return 3; - case RelativeShort: return 2; - case RelativeLong: return 3; - } -} - -inline string SNESCPU::disassemble(unsigned pc, bool accum, bool index, uint8_t opcode, uint8_t pl, uint8_t ph, uint8_t pb) { - string name = opcodeInfo[opcode].name; - unsigned mode = opcodeInfo[opcode].mode; - - if(mode == Implied) return name; - if(mode == Constant) return { name, " #$", hex<2>(pl) }; - if(mode == AccumConstant) return { name, " #$", accum ? "" : hex<2>(ph), hex<2>(pl) }; - if(mode == IndexConstant) return { name, " #$", index ? "" : hex<2>(ph), hex<2>(pl) }; - if(mode == Direct) return { name, " $", hex<2>(pl) }; - if(mode == DirectX) return { name, " $", hex<2>(pl), ",x" }; - if(mode == DirectY) return { name, " $", hex<2>(pl), ",y" }; - if(mode == IDirect) return { name, " ($", hex<2>(pl), ")" }; - if(mode == IDirectX) return { name, " ($", hex<2>(pl), ",x)" }; - if(mode == IDirectY) return { name, " ($", hex<2>(pl), "),y" }; - if(mode == ILDirect) return { name, " [$", hex<2>(pl), "]" }; - if(mode == ILDirectY) return { name, " [$", hex<2>(pl), "],y" }; - if(mode == Address) return { name, " $", hex<2>(ph), hex<2>(pl) }; - if(mode == AddressX) return { name, " $", hex<2>(ph), hex<2>(pl), ",x" }; - if(mode == AddressY) return { name, " $", hex<2>(ph), hex<2>(pl), ",y" }; - if(mode == IAddressX) return { name, " ($", hex<2>(ph), hex<2>(pl), ",x)" }; - if(mode == ILAddress) return { name, " [$", hex<2>(ph), hex<2>(pl), "]" }; - if(mode == PAddress) return { name, " $", hex<2>(ph), hex<2>(pl) }; - if(mode == PIAddress) return { name, " ($", hex<2>(ph), hex<2>(pl), ")" }; - if(mode == Long) return { name, " $", hex<2>(pb), hex<2>(ph), hex<2>(pl) }; - if(mode == LongX) return { name, " $", hex<2>(pb), hex<2>(ph), hex<2>(pl), ",x" }; - if(mode == Stack) return { name, " $", hex<2>(pl), ",s" }; - if(mode == IStackY) return { name, " ($", hex<2>(pl), ",s),y" }; - if(mode == BlockMove) return { name, " $", hex<2>(ph), ",$", hex<2>(pl) }; - if(mode == RelativeShort) { - unsigned addr = (pc + 2) + (int8_t)(pl << 0); - return { name, " $", hex<4>(addr) }; - } - if(mode == RelativeLong) { - unsigned addr = (pc + 3) + (int16_t)((ph << 8) + (pl << 0)); - return { name, " $", hex<4>(addr) }; - } - - return ""; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/snes/smp.hpp b/waterbox/libsnes/bsnes/nall/snes/smp.hpp deleted file mode 100644 index 7a1ac47b64..0000000000 --- a/waterbox/libsnes/bsnes/nall/snes/smp.hpp +++ /dev/null @@ -1,639 +0,0 @@ -#ifndef NALL_SNES_SMP_HPP -#define NALL_SNES_SMP_HPP - -namespace nall { - -struct SNESSMP { - enum : unsigned { - Implied, // - TVector, //0 - Direct, //$00 - DirectRelative, //$00,+/-$00 - ADirect, //a,$00 - AAbsolute, //a,$0000 - AIX, //a,(x) - AIDirectX, //a,($00+x) - AConstant, //a,#$00 - DirectDirect, //$00,$00 - CAbsoluteBit, //c,$0000:0 - Absolute, //$0000 - P, //p - AbsoluteA, //$0000,a - Relative, //+/-$00 - ADirectX, //a,$00+x - AAbsoluteX, //a,$0000+x - AAbsoluteY, //a,$0000+y - AIDirectY, //a,($00)+y - DirectConstant, //$00,#$00 - IXIY, //(x),(y) - DirectX, //$00+x - A, //a - X, //x - XAbsolute, //x,$0000 - IAbsoluteX, //($0000+x) - CNAbsoluteBit, //c,!$0000:0 - XDirect, //x,$00 - PVector, //$ff00 - YaDirect, //ya,$00 - XA, //x,a - YAbsolute, //y,$0000 - Y, //y - AX, //a,x - YDirect, //y,$00 - YConstant, //y,#$00 - XSp, //x,sp - YaX, //ya,x - IXPA, //(x)+,a - SpX, //sp,x - AIXP, //a,(x)+ - DirectA, //$00,a - IXA, //(x),a - IDirectXA, //($00+x),a - XConstant, //x,#$00 - AbsoluteX, //$0000,x - AbsoluteBitC, //$0000:0,c - DirectY, //$00,y - AbsoluteY, //$0000,y - Ya, //ya - DirectXA, //$00+x,a - AbsoluteXA, //$0000+x,a - AbsoluteYA, //$0000+y,a - IDirectYA, //($00)+y,a - DirectYX, //$00+y,x - DirectYa, //$00,ya - DirectXY, //$00+x,y - AY, //a,y - DirectXRelative, //$00+x,+/-$00 - XDirectY, //x,$00+y - YDirectX, //y,$00+x - YA, //y,a - YRelative, //y,+/-$00 - }; - - struct OpcodeInfo { - char name[6]; - unsigned mode; - }; - - static const OpcodeInfo opcodeInfo[256]; - - static unsigned getOpcodeLength(uint8_t opcode); - static string disassemble(uint16_t pc, uint8_t opcode, uint8_t pl, uint8_t ph); - static string disassemble(uint16_t pc, bool p, uint8_t opcode, uint8_t pl, uint8_t ph); -}; - -const SNESSMP::OpcodeInfo SNESSMP::opcodeInfo[256] = { - //0x00 - 0x0f - { "nop ", Implied }, - { "tcall", TVector }, - { "set0 ", Direct }, - { "bbs0 ", DirectRelative }, - - { "or ", ADirect }, - { "or ", AAbsolute }, - { "or ", AIX }, - { "or ", AIDirectX }, - - { "or ", AConstant }, - { "or ", DirectDirect }, - { "or1 ", CAbsoluteBit }, - { "asl ", Direct }, - - { "asl ", Absolute }, - { "push ", P }, - { "tset ", AbsoluteA }, - { "brk ", Implied }, - - //0x10 - 0x1f - { "bpl ", Relative }, - { "tcall", TVector }, - { "clr0 ", Direct }, - { "bbc0 ", DirectRelative }, - - { "or ", ADirectX }, - { "or ", AAbsoluteX }, - { "or ", AAbsoluteY }, - { "or ", AIDirectY }, - - { "or ", DirectConstant }, - { "or ", IXIY }, - { "decw ", Direct }, - { "asl ", DirectX }, - - { "asl ", A }, - { "dec ", X }, - { "cmp ", XAbsolute }, - { "jmp ", IAbsoluteX }, - - //0x20 - 0x2f - { "clrp ", Implied }, - { "tcall", TVector }, - { "set1 ", Direct }, - { "bbs1 ", DirectRelative }, - - { "and ", ADirect }, - { "and ", AAbsolute }, - { "and ", AIX }, - { "and ", AIDirectX }, - - { "and ", AConstant }, - { "and ", DirectDirect }, - { "or1 ", CNAbsoluteBit }, - { "rol ", Direct }, - - { "rol ", Absolute }, - { "push ", A }, - { "cbne ", DirectRelative }, - { "bra ", Relative }, - - //0x30 - 0x3f - { "bmi ", Relative }, - { "tcall", TVector }, - { "clr1 ", Direct }, - { "bbc1 ", DirectRelative }, - - { "and ", ADirectX }, - { "and ", AAbsoluteX }, - { "and ", AAbsoluteY }, - { "and ", AIDirectY }, - - { "and ", DirectConstant }, - { "and ", IXIY }, - { "incw ", Direct }, - { "rol ", DirectX }, - - { "rol ", A }, - { "inc ", X }, - { "cmp ", XDirect }, - { "call ", Absolute }, - - //0x40 - 0x4f - { "setp ", Implied }, - { "tcall", TVector }, - { "set2 ", Direct }, - { "bbs2 ", DirectRelative }, - - { "eor ", ADirect }, - { "eor ", AAbsolute }, - { "eor ", AIX }, - { "eor ", AIDirectX }, - - { "eor ", AConstant }, - { "eor ", DirectDirect }, - { "and1 ", CAbsoluteBit }, - { "lsr ", Direct }, - - { "lsr ", Absolute }, - { "push ", X }, - { "tclr ", AbsoluteA }, - { "pcall", PVector }, - - //0x50 - 0x5f - { "bvc ", Relative }, - { "tcall", TVector }, - { "clr2 ", Direct }, - { "bbc2 ", DirectRelative }, - - { "eor ", ADirectX }, - { "eor ", AAbsoluteX }, - { "eor ", AAbsoluteY }, - { "eor ", AIDirectY }, - - { "eor ", DirectConstant }, - { "eor ", IXIY }, - { "cmpw ", YaDirect }, - { "lsr ", DirectX }, - - { "lsr ", A }, - { "mov ", XA }, - { "cmp ", YAbsolute }, - { "jmp ", Absolute }, - - //0x60 - 0x6f - { "clrc ", Implied }, - { "tcall", TVector }, - { "set3 ", Direct }, - { "bbs3 ", DirectRelative }, - - { "cmp ", ADirect }, - { "cmp ", AAbsolute }, - { "cmp ", AIX }, - { "cmp ", AIDirectX }, - - { "cmp ", AConstant }, - { "cmp ", DirectDirect }, - { "and1 ", CNAbsoluteBit }, - { "ror ", Direct }, - - { "ror ", Absolute }, - { "push ", Y }, - { "dbnz ", DirectRelative }, - { "ret ", Implied }, - - //0x70 - 0x7f - { "bvs ", Relative }, - { "tcall", TVector }, - { "clr3 ", Direct }, - { "bbc3 ", DirectRelative }, - - { "cmp ", ADirectX }, - { "cmp ", AAbsoluteX }, - { "cmp ", AAbsoluteY }, - { "cmp ", AIDirectY }, - - { "cmp ", DirectConstant }, - { "cmp ", IXIY }, - { "addw ", YaDirect }, - { "ror ", DirectX }, - - { "ror ", A }, - { "mov ", AX }, - { "cmp ", YDirect }, - { "reti ", Implied }, - - //0x80 - 0x8f - { "setc ", Implied }, - { "tcall", TVector }, - { "set4 ", Direct }, - { "bbs4 ", DirectRelative }, - - { "adc ", ADirect }, - { "adc ", AAbsolute }, - { "adc ", AIX }, - { "adc ", AIDirectX }, - - { "adc ", AConstant }, - { "adc ", DirectDirect }, - { "eor1 ", CAbsoluteBit }, - { "dec ", Direct }, - - { "dec ", Absolute }, - { "mov ", YConstant }, - { "pop ", P }, - { "mov ", DirectConstant }, - - //0x90 - 0x9f - { "bcc ", Relative }, - { "tcall", TVector }, - { "clr4 ", Direct }, - { "bbc4 ", DirectRelative }, - - { "adc ", ADirectX }, - { "adc ", AAbsoluteX }, - { "adc ", AAbsoluteY }, - { "adc ", AIDirectY }, - - { "adc ", DirectRelative }, - { "adc ", IXIY }, - { "subw ", YaDirect }, - { "dec ", DirectX }, - - { "dec ", A }, - { "mov ", XSp }, - { "div ", YaX }, - { "xcn ", A }, - - //0xa0 - 0xaf - { "ei ", Implied }, - { "tcall", TVector }, - { "set5 ", Direct }, - { "bbs5 ", DirectRelative }, - - { "sbc ", ADirect }, - { "sbc ", AAbsolute }, - { "sbc ", AIX }, - { "sbc ", AIDirectX }, - - { "sbc ", AConstant }, - { "sbc ", DirectDirect }, - { "mov1 ", CAbsoluteBit }, - { "inc ", Direct }, - - { "inc ", Absolute }, - { "cmp ", YConstant }, - { "pop ", A }, - { "mov ", IXPA }, - - //0xb0 - 0xbf - { "bcs ", Relative }, - { "tcall", TVector }, - { "clr5 ", Direct }, - { "bbc5 ", DirectRelative }, - - { "sbc ", ADirectX }, - { "sbc ", AAbsoluteX }, - { "sbc ", AAbsoluteY }, - { "sbc ", AIDirectY }, - - { "sbc ", DirectConstant }, - { "sbc ", IXIY }, - { "movw ", YaDirect }, - { "inc ", DirectX }, - - { "inc ", A }, - { "mov ", SpX }, - { "das ", A }, - { "mov ", AIXP }, - - //0xc0 - 0xcf - { "di ", Implied }, - { "tcall", TVector }, - { "set6 ", Direct }, - { "bbs6 ", DirectRelative }, - - { "mov ", DirectA }, - { "mov ", AbsoluteA }, - { "mov ", IXA }, - { "mov ", IDirectXA }, - - { "cmp ", XConstant }, - { "mov ", AbsoluteX }, - { "mov1 ", AbsoluteBitC }, - { "mov ", DirectY }, - - { "mov ", AbsoluteY }, - { "mov ", XConstant }, - { "pop ", X }, - { "mul ", Ya }, - - //0xd0 - 0xdf - { "bne ", Relative }, - { "tcall", TVector }, - { "clr6 ", Relative }, - { "bbc6 ", DirectRelative }, - - { "mov ", DirectXA }, - { "mov ", AbsoluteXA }, - { "mov ", AbsoluteYA }, - { "mov ", IDirectYA }, - - { "mov ", DirectX }, - { "mov ", DirectYX }, - { "movw ", DirectYa }, - { "mov ", DirectXY }, - - { "dec ", Y }, - { "mov ", AY }, - { "cbne ", DirectXRelative }, - { "daa ", A }, - - //0xe0 - 0xef - { "clrv ", Implied }, - { "tcall", TVector }, - { "set7 ", Direct }, - { "bbs7 ", DirectRelative }, - - { "mov ", ADirect }, - { "mov ", AAbsolute }, - { "mov ", AIX }, - { "mov ", AIDirectX }, - - { "mov ", AConstant }, - { "mov ", XAbsolute }, - { "not1 ", CAbsoluteBit }, - { "mov ", YDirect }, - - { "mov ", YAbsolute }, - { "notc ", Implied }, - { "pop ", Y }, - { "sleep", Implied }, - - //0xf0 - 0xff - { "beq ", Relative }, - { "tcall", TVector }, - { "clr7 ", Direct }, - { "bbc7 ", DirectRelative }, - - { "mov ", ADirectX }, - { "mov ", AAbsoluteX }, - { "mov ", AAbsoluteY }, - { "mov ", AIDirectY }, - - { "mov ", XDirect }, - { "mov ", XDirectY }, - { "mov ", DirectDirect }, - { "mov ", YDirectX }, - - { "inc ", Y }, - { "mov ", YA }, - { "dbz ", YRelative }, - { "stop ", Implied }, -}; - -inline unsigned SNESSMP::getOpcodeLength(uint8_t opcode) { - switch(opcodeInfo[opcode].mode) { default: - case Implied: return 1; // - case TVector: return 1; //0 - case Direct: return 2; //$00 - case DirectRelative: return 3; //$00,+/-$00 - case ADirect: return 2; //a,$00 - case AAbsolute: return 3; //a,$0000 - case AIX: return 1; //a,(x) - case AIDirectX: return 2; //a,($00+x) - case AConstant: return 2; //a,#$00 - case DirectDirect: return 3; //$00,$00 - case CAbsoluteBit: return 3; //c,$0000:0 - case Absolute: return 3; //$0000 - case P: return 1; //p - case AbsoluteA: return 3; //$0000,a - case Relative: return 2; //+/-$00 - case ADirectX: return 2; //a,$00+x - case AAbsoluteX: return 3; //a,$0000+x - case AAbsoluteY: return 3; //a,$0000+y - case AIDirectY: return 2; //a,($00)+y - case DirectConstant: return 3; //$00,#$00 - case IXIY: return 1; //(x),(y) - case DirectX: return 2; //$00+x - case A: return 1; //a - case X: return 1; //x - case XAbsolute: return 3; //x,$0000 - case IAbsoluteX: return 3; //($0000+x) - case CNAbsoluteBit: return 3; //c,!$0000:0 - case XDirect: return 2; //x,$00 - case PVector: return 2; //$ff00 - case YaDirect: return 2; //ya,$00 - case XA: return 1; //x,a - case YAbsolute: return 3; //y,$0000 - case Y: return 1; //y - case AX: return 1; //a,x - case YDirect: return 2; //y,$00 - case YConstant: return 2; //y,#$00 - case XSp: return 1; //x,sp - case YaX: return 1; //ya,x - case IXPA: return 1; //(x)+,a - case SpX: return 1; //sp,x - case AIXP: return 1; //a,(x)+ - case DirectA: return 2; //$00,a - case IXA: return 1; //(x),a - case IDirectXA: return 2; //($00+x),a - case XConstant: return 2; //x,#$00 - case AbsoluteX: return 3; //$0000,x - case AbsoluteBitC: return 3; //$0000:0,c - case DirectY: return 2; //$00,y - case AbsoluteY: return 3; //$0000,y - case Ya: return 1; //ya - case DirectXA: return 2; //$00+x,a - case AbsoluteXA: return 3; //$0000+x,a - case AbsoluteYA: return 3; //$0000+y,a - case IDirectYA: return 2; //($00)+y,a - case DirectYX: return 2; //$00+y,x - case DirectYa: return 2; //$00,ya - case DirectXY: return 2; //$00+x,y - case AY: return 1; //a,y - case DirectXRelative: return 3; //$00+x,+/-$00 - case XDirectY: return 2; //x,$00+y - case YDirectX: return 2; //y,$00+x - case YA: return 1; //y,a - case YRelative: return 2; //y,+/-$00 - } -} - -inline string SNESSMP::disassemble(uint16_t pc, uint8_t opcode, uint8_t pl, uint8_t ph) { - string name = opcodeInfo[opcode].name; - unsigned mode = opcodeInfo[opcode].mode; - unsigned pa = (ph << 8) + pl; - - if(mode == Implied) return name; - if(mode == TVector) return { name, " ", opcode >> 4 }; - if(mode == Direct) return { name, " $", hex<2>(pl) }; - if(mode == DirectRelative) return { name, " $", hex<2>(pl), ",$", hex<4>(pc + 3 + (int8_t)ph) }; - if(mode == ADirect) return { name, " a,$", hex<2>(pl) }; - if(mode == AAbsolute) return { name, " a,$", hex<4>(pa) }; - if(mode == AIX) return { name, "a,(x)" }; - if(mode == AIDirectX) return { name, " a,($", hex<2>(pl), "+x)" }; - if(mode == AConstant) return { name, " a,#$", hex<2>(pl) }; - if(mode == DirectDirect) return { name, " $", hex<2>(ph), ",$", hex<2>(pl) }; - if(mode == CAbsoluteBit) return { name, " c,$", hex<4>(pa & 0x1fff), ":", pa >> 13 }; - if(mode == Absolute) return { name, " $", hex<4>(pa) }; - if(mode == P) return { name, " p" }; - if(mode == AbsoluteA) return { name, " $", hex<4>(pa), ",a" }; - if(mode == Relative) return { name, " $", hex<4>(pc + 2 + (int8_t)pl) }; - if(mode == ADirectX) return { name, " a,$", hex<2>(pl), "+x" }; - if(mode == AAbsoluteX) return { name, " a,$", hex<4>(pa), "+x" }; - if(mode == AAbsoluteY) return { name, " a,$", hex<4>(pa), "+y" }; - if(mode == AIDirectY) return { name, " a,($", hex<2>(pl), ")+y" }; - if(mode == DirectConstant) return { name, " $", hex<2>(ph), ",#$", hex<2>(pl) }; - if(mode == IXIY) return { name, " (x),(y)" }; - if(mode == DirectX) return { name, " $", hex<2>(pl), "+x" }; - if(mode == A) return { name, " a" }; - if(mode == X) return { name, " x" }; - if(mode == XAbsolute) return { name, " x,$", hex<4>(pa) }; - if(mode == IAbsoluteX) return { name, " ($", hex<4>(pa), "+x)" }; - if(mode == CNAbsoluteBit) return { name, " c,!$", hex<4>(pa & 0x1fff), ":", pa >> 13 }; - if(mode == XDirect) return { name, " x,$", hex<2>(pl) }; - if(mode == PVector) return { name, " $ff", hex<2>(pl) }; - if(mode == YaDirect) return { name, " ya,$", hex<2>(pl) }; - if(mode == XA) return { name, " x,a" }; - if(mode == YAbsolute) return { name, " y,$", hex<4>(pa) }; - if(mode == Y) return { name, " y" }; - if(mode == AX) return { name, " a,x" }; - if(mode == YDirect) return { name, " y,$", hex<2>(pl) }; - if(mode == YConstant) return { name, " y,#$", hex<2>(pl) }; - if(mode == XSp) return { name, " x,sp" }; - if(mode == YaX) return { name, " ya,x" }; - if(mode == IXPA) return { name, " (x)+,a" }; - if(mode == SpX) return { name, " sp,x" }; - if(mode == AIXP) return { name, " a,(x)+" }; - if(mode == DirectA) return { name, " $", hex<2>(pl), ",a" }; - if(mode == IXA) return { name, " (x),a" }; - if(mode == IDirectXA) return { name, " ($", hex<2>(pl), "+x),a" }; - if(mode == XConstant) return { name, " x,#$", hex<2>(pl) }; - if(mode == AbsoluteX) return { name, " $", hex<4>(pa), ",x" }; - if(mode == AbsoluteBitC) return { name, " $", hex<4>(pa & 0x1fff), ":", pa >> 13, ",c" }; - if(mode == DirectY) return { name, " $", hex<2>(pl), ",y" }; - if(mode == AbsoluteY) return { name, " $", hex<4>(pa), ",y" }; - if(mode == Ya) return { name, " ya" }; - if(mode == DirectXA) return { name, " $", hex<2>(pl), "+x,a" }; - if(mode == AbsoluteXA) return { name, " $", hex<4>(pa), "+x,a" }; - if(mode == AbsoluteYA) return { name, " $", hex<4>(pa), "+y,a" }; - if(mode == IDirectYA) return { name, " ($", hex<2>(pl), ")+y,a" }; - if(mode == DirectYX) return { name, " $", hex<2>(pl), "+y,x" }; - if(mode == DirectYa) return { name, " $", hex<2>(pl), ",ya" }; - if(mode == DirectXY) return { name, " $", hex<2>(pl), "+x,y" }; - if(mode == AY) return { name, " a,y" }; - if(mode == DirectXRelative) return { name, " $", hex<2>(pl), ",$", hex<4>(pc + 3 + (int8_t)ph) }; - if(mode == XDirectY) return { name, " x,$", hex<2>(pl), "+y" }; - if(mode == YDirectX) return { name, " y,$", hex<2>(pl), "+x" }; - if(mode == YA) return { name, " y,a" }; - if(mode == YRelative) return { name, " y,$", hex<4>(pc + 2 + (int8_t)pl) }; - - return ""; -} - -inline string SNESSMP::disassemble(uint16_t pc, bool p, uint8_t opcode, uint8_t pl, uint8_t ph) { - string name = opcodeInfo[opcode].name; - unsigned mode = opcodeInfo[opcode].mode; - unsigned pdl = (p << 8) + pl; - unsigned pdh = (p << 8) + ph; - unsigned pa = (ph << 8) + pl; - - if(mode == Implied) return name; - if(mode == TVector) return { name, " ", opcode >> 4 }; - if(mode == Direct) return { name, " $", hex<3>(pdl) }; - if(mode == DirectRelative) return { name, " $", hex<3>(pdl), ",$", hex<4>(pc + 3 + (int8_t)ph) }; - if(mode == ADirect) return { name, " a,$", hex<3>(pdl) }; - if(mode == AAbsolute) return { name, " a,$", hex<4>(pa) }; - if(mode == AIX) return { name, "a,(x)" }; - if(mode == AIDirectX) return { name, " a,($", hex<3>(pdl), "+x)" }; - if(mode == AConstant) return { name, " a,#$", hex<2>(pl) }; - if(mode == DirectDirect) return { name, " $", hex<3>(pdh), ",$", hex<3>(pdl) }; - if(mode == CAbsoluteBit) return { name, " c,$", hex<4>(pa & 0x1fff), ":", pa >> 13 }; - if(mode == Absolute) return { name, " $", hex<4>(pa) }; - if(mode == P) return { name, " p" }; - if(mode == AbsoluteA) return { name, " $", hex<4>(pa), ",a" }; - if(mode == Relative) return { name, " $", hex<4>(pc + 2 + (int8_t)pl) }; - if(mode == ADirectX) return { name, " a,$", hex<3>(pdl), "+x" }; - if(mode == AAbsoluteX) return { name, " a,$", hex<4>(pa), "+x" }; - if(mode == AAbsoluteY) return { name, " a,$", hex<4>(pa), "+y" }; - if(mode == AIDirectY) return { name, " a,($", hex<3>(pdl), ")+y" }; - if(mode == DirectConstant) return { name, " $", hex<3>(pdh), ",#$", hex<2>(pl) }; - if(mode == IXIY) return { name, " (x),(y)" }; - if(mode == DirectX) return { name, " $", hex<3>(pdl), "+x" }; - if(mode == A) return { name, " a" }; - if(mode == X) return { name, " x" }; - if(mode == XAbsolute) return { name, " x,$", hex<4>(pa) }; - if(mode == IAbsoluteX) return { name, " ($", hex<4>(pa), "+x)" }; - if(mode == CNAbsoluteBit) return { name, " c,!$", hex<4>(pa & 0x1fff), ":", pa >> 13 }; - if(mode == XDirect) return { name, " x,$", hex<3>(pdl) }; - if(mode == PVector) return { name, " $ff", hex<2>(pl) }; - if(mode == YaDirect) return { name, " ya,$", hex<3>(pdl) }; - if(mode == XA) return { name, " x,a" }; - if(mode == YAbsolute) return { name, " y,$", hex<4>(pa) }; - if(mode == Y) return { name, " y" }; - if(mode == AX) return { name, " a,x" }; - if(mode == YDirect) return { name, " y,$", hex<3>(pdl) }; - if(mode == YConstant) return { name, " y,#$", hex<2>(pl) }; - if(mode == XSp) return { name, " x,sp" }; - if(mode == YaX) return { name, " ya,x" }; - if(mode == IXPA) return { name, " (x)+,a" }; - if(mode == SpX) return { name, " sp,x" }; - if(mode == AIXP) return { name, " a,(x)+" }; - if(mode == DirectA) return { name, " $", hex<3>(pdl), ",a" }; - if(mode == IXA) return { name, " (x),a" }; - if(mode == IDirectXA) return { name, " ($", hex<3>(pdl), "+x),a" }; - if(mode == XConstant) return { name, " x,#$", hex<2>(pl) }; - if(mode == AbsoluteX) return { name, " $", hex<4>(pa), ",x" }; - if(mode == AbsoluteBitC) return { name, " $", hex<4>(pa & 0x1fff), ":", pa >> 13, ",c" }; - if(mode == DirectY) return { name, " $", hex<3>(pdl), ",y" }; - if(mode == AbsoluteY) return { name, " $", hex<4>(pa), ",y" }; - if(mode == Ya) return { name, " ya" }; - if(mode == DirectXA) return { name, " $", hex<3>(pdl), "+x,a" }; - if(mode == AbsoluteXA) return { name, " $", hex<4>(pa), "+x,a" }; - if(mode == AbsoluteYA) return { name, " $", hex<4>(pa), "+y,a" }; - if(mode == IDirectYA) return { name, " ($", hex<3>(pdl), ")+y,a" }; - if(mode == DirectYX) return { name, " $", hex<3>(pdl), "+y,x" }; - if(mode == DirectYa) return { name, " $", hex<3>(pdl), ",ya" }; - if(mode == DirectXY) return { name, " $", hex<3>(pdl), "+x,y" }; - if(mode == AY) return { name, " a,y" }; - if(mode == DirectXRelative) return { name, " $", hex<3>(pdl), ",$", hex<4>(pc + 3 + (int8_t)ph) }; - if(mode == XDirectY) return { name, " x,$", hex<3>(pdl), "+y" }; - if(mode == YDirectX) return { name, " y,$", hex<3>(pdl), "+x" }; - if(mode == YA) return { name, " y,a" }; - if(mode == YRelative) return { name, " y,$", hex<4>(pc + 2 + (int8_t)pl) }; - - return ""; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/snes/usart.hpp b/waterbox/libsnes/bsnes/nall/snes/usart.hpp deleted file mode 100644 index e0d9a2246a..0000000000 --- a/waterbox/libsnes/bsnes/nall/snes/usart.hpp +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef NALL_SNES_USART_HPP -#define NALL_SNES_USART_HPP - -#include -#include -#include -#include - -#define usartproc dllexport - -static nall::function usart_usleep; -static nall::function usart_read; -static nall::function usart_write; - -extern "C" usartproc void usart_init( - nall::function usleep, - nall::function read, - nall::function write -) { - usart_usleep = usleep; - usart_read = read; - usart_write = write; -} - -extern "C" usartproc void usart_main(); - -// - -static nall::serial usart; -static bool usart_is_virtual = true; - -static bool usart_virtual() { - return usart_is_virtual; -} - -// - -static void usarthw_usleep(unsigned milliseconds) { - usleep(milliseconds); -} - -static uint8_t usarthw_read() { - while(true) { - uint8_t buffer[1]; - signed length = usart.read((uint8_t*)&buffer, 1); - if(length > 0) return buffer[0]; - } -} - -static void usarthw_write(uint8_t data) { - uint8_t buffer[1] = { data }; - usart.write((uint8_t*)&buffer, 1); -} - -int main(int argc, char **argv) { - bool result = false; - if(argc == 1) result = usart.open("/dev/ttyACM0", 57600, true); - if(argc == 2) result = usart.open(argv[1], 57600, true); - if(result == false) { - printf("error: unable to open USART hardware device\n"); - return 0; - } - usart_is_virtual = false; - usart_init(usarthw_usleep, usarthw_read, usarthw_write); - usart_main(); - usart.close(); - return 0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/sort.hpp b/waterbox/libsnes/bsnes/nall/sort.hpp deleted file mode 100644 index 36d91865d3..0000000000 --- a/waterbox/libsnes/bsnes/nall/sort.hpp +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef NALL_SORT_HPP -#define NALL_SORT_HPP - -#include -#include - -//class: merge sort -//average: O(n log n) -//worst: O(n log n) -//memory: O(n) -//stack: O(log n) -//stable?: yes - -//note: merge sort was chosen over quick sort, because: -//* it is a stable sort -//* it lacks O(n^2) worst-case overhead - -#define NALL_SORT_INSERTION -//#define NALL_SORT_SELECTION - -namespace nall { - template - void sort(T list[], unsigned size, const Comparator &lessthan) { - if(size <= 1) return; //nothing to sort - - //use insertion sort to quickly sort smaller blocks - if(size < 64) { - #if defined(NALL_SORT_INSERTION) - for(signed i = 1, j; i < size; i++) { - T copy = std::move(list[i]); - for(j = i - 1; j >= 0; j--) { - if(lessthan(list[j], copy)) break; - list[j + 1] = std::move(list[j]); - } - list[j + 1] = std::move(copy); - } - #elif defined(NALL_SORT_SELECTION) - for(unsigned i = 0; i < size; i++) { - unsigned min = i; - for(unsigned j = i + 1; j < size; j++) { - if(lessthan(list[j], list[min])) min = j; - } - if(min != i) std::swap(list[i], list[min]); - } - #endif - return; - } - - //split list in half and recursively sort both - unsigned middle = size / 2; - sort(list, middle, lessthan); - sort(list + middle, size - middle, lessthan); - - //left and right are sorted here; perform merge sort - T *buffer = new T[size]; - unsigned offset = 0, left = 0, right = middle; - while(left < middle && right < size) { - if(lessthan(list[left], list[right])) { - buffer[offset++] = std::move(list[left++]); - } else { - buffer[offset++] = std::move(list[right++]); - } - } - while(left < middle) buffer[offset++] = std::move(list[left++]); - while(right < size) buffer[offset++] = std::move(list[right++]); - - for(unsigned i = 0; i < size; i++) list[i] = std::move(buffer[i]); - delete[] buffer; - } - - template - void sort(T list[], unsigned size) { - return sort(list, size, [](const T &l, const T &r) { return l < r; }); - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/stdint.hpp b/waterbox/libsnes/bsnes/nall/stdint.hpp deleted file mode 100644 index c63f59121d..0000000000 --- a/waterbox/libsnes/bsnes/nall/stdint.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef NALL_STDINT_HPP -#define NALL_STDINT_HPP - -#if defined(_MSC_VER) - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef signed long long int64_t; - typedef int64_t intmax_t; - #if defined(_WIN64) - typedef int64_t intptr_t; - #else - typedef int32_t intptr_t; - #endif - - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; - typedef unsigned long long uint64_t; - typedef uint64_t uintmax_t; - #if defined(_WIN64) - typedef uint64_t uintptr_t; - #else - typedef uint32_t uintptr_t; - #endif -#else - #include -#endif - -namespace nall { - static_assert(sizeof(int8_t) == 1, "int8_t is not of the correct size" ); - static_assert(sizeof(int16_t) == 2, "int16_t is not of the correct size"); - static_assert(sizeof(int32_t) == 4, "int32_t is not of the correct size"); - static_assert(sizeof(int64_t) == 8, "int64_t is not of the correct size"); - - static_assert(sizeof(uint8_t) == 1, "int8_t is not of the correct size" ); - static_assert(sizeof(uint16_t) == 2, "int16_t is not of the correct size"); - static_assert(sizeof(uint32_t) == 4, "int32_t is not of the correct size"); - static_assert(sizeof(uint64_t) == 8, "int64_t is not of the correct size"); -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/stream.hpp b/waterbox/libsnes/bsnes/nall/stream.hpp deleted file mode 100644 index 586ccda729..0000000000 --- a/waterbox/libsnes/bsnes/nall/stream.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef NALL_STREAM_HPP -#define NALL_STREAM_HPP - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define NALL_STREAM_INTERNAL_HPP -#include -#include -#include -#include -#include -#include -#include -#include -#undef NALL_STREAM_INTERNAL_HPP - -#endif diff --git a/waterbox/libsnes/bsnes/nall/stream/auto.hpp b/waterbox/libsnes/bsnes/nall/stream/auto.hpp deleted file mode 100644 index 148c7fd467..0000000000 --- a/waterbox/libsnes/bsnes/nall/stream/auto.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifdef NALL_STREAM_INTERNAL_HPP - -namespace nall { - -#define autostream(...) (*makestream(__VA_ARGS__)) - -inline std::unique_ptr makestream(const string &path) { - if(path.ibeginswith("http://")) return std::unique_ptr(new httpstream(path, 80)); - if(path.iendswith(".gz")) return std::unique_ptr(new gzipstream(filestream{path})); - if(path.iendswith(".zip")) return std::unique_ptr(new zipstream(filestream{path})); - return std::unique_ptr(new mmapstream(path)); -} - -inline std::unique_ptr makestream(uint8_t *data, unsigned size) { - return std::unique_ptr(new memorystream(data, size)); -} - -inline std::unique_ptr makestream(const uint8_t *data, unsigned size) { - return std::unique_ptr(new memorystream(data, size)); -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/stream/file.hpp b/waterbox/libsnes/bsnes/nall/stream/file.hpp deleted file mode 100644 index 55521f07ac..0000000000 --- a/waterbox/libsnes/bsnes/nall/stream/file.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#ifdef NALL_STREAM_INTERNAL_HPP - -namespace nall { - -struct filestream : stream { - inline bool seekable() const { return true; } - inline bool readable() const { return true; } - inline bool writable() const { return pwritable; } - inline bool randomaccess() const { return false; } - - inline unsigned size() const { return pfile.size(); } - inline unsigned offset() const { return pfile.offset(); } - inline void seek(unsigned offset) const { pfile.seek(offset); } - - inline uint8_t read() const { return pfile.read(); } - inline void write(uint8_t data) const { pfile.write(data); } - - inline filestream(const string &filename) { - pfile.open(filename, file::mode::readwrite); - pwritable = pfile.open(); - if(!pwritable) pfile.open(filename, file::mode::read); - } - -private: - mutable file pfile; - bool pwritable; -}; - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/stream/gzip.hpp b/waterbox/libsnes/bsnes/nall/stream/gzip.hpp deleted file mode 100644 index 37bd977871..0000000000 --- a/waterbox/libsnes/bsnes/nall/stream/gzip.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifdef NALL_STREAM_INTERNAL_HPP - -namespace nall { - -struct gzipstream : memorystream { - inline gzipstream(const stream &stream) { - unsigned size = stream.size(); - uint8_t *data = new uint8_t[size]; - stream.read(data, size); - - gzip archive; - bool result = archive.decompress(data, size); - delete[] data; - if(result == false) return; - - psize = archive.size; - pdata = new uint8_t[psize]; - memcpy(pdata, archive.data, psize); - } - - inline ~gzipstream() { - if(pdata) delete[] pdata; - } -}; - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/stream/http.hpp b/waterbox/libsnes/bsnes/nall/stream/http.hpp deleted file mode 100644 index b853d51cce..0000000000 --- a/waterbox/libsnes/bsnes/nall/stream/http.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifdef NALL_STREAM_INTERNAL_HPP - -namespace nall { - -struct httpstream : stream { - inline bool seekable() const { return true; } - inline bool readable() const { return true; } - inline bool writable() const { return true; } - inline bool randomaccess() const { return true; } - - inline unsigned size() const { return psize; } - inline unsigned offset() const { return poffset; } - inline void seek(unsigned offset) const { poffset = offset; } - - inline uint8_t read() const { return pdata[poffset++]; } - inline void write(uint8_t data) const { pdata[poffset++] = data; } - - inline uint8_t read(unsigned offset) const { return pdata[offset]; } - inline void write(unsigned offset, uint8_t data) const { pdata[offset] = data; } - - inline httpstream(const string &url, unsigned port) : pdata(nullptr), psize(0), poffset(0) { - string uri = url; - uri.ltrim<1>("http://"); - lstring part = uri.split<1>("/"); - part[1] = { "/", part[1] }; - - http connection; - if(connection.connect(part[0], port) == false) return; - connection.download(part[1], pdata, psize); - } - - inline ~httpstream() { - if(pdata) delete[] pdata; - } - -private: - mutable uint8_t *pdata; - mutable unsigned psize, poffset; -}; - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/stream/memory.hpp b/waterbox/libsnes/bsnes/nall/stream/memory.hpp deleted file mode 100644 index 80bbb240c3..0000000000 --- a/waterbox/libsnes/bsnes/nall/stream/memory.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifdef NALL_STREAM_INTERNAL_HPP - -namespace nall { - -struct memorystream : stream { - inline bool seekable() const { return true; } - inline bool readable() const { return true; } - inline bool writable() const { return pwritable; } - inline bool randomaccess() const { return true; } - - inline unsigned size() const { return psize; } - inline unsigned offset() const { return poffset; } - inline void seek(unsigned offset) const { poffset = offset; } - - inline uint8_t read() const { return pdata[poffset++]; } - inline void write(uint8_t data) const { pdata[poffset++] = data; } - - inline uint8_t read(unsigned offset) const { return pdata[offset]; } - inline void write(unsigned offset, uint8_t data) const { pdata[offset] = data; } - - inline memorystream() : pdata(nullptr), psize(0), poffset(0), pwritable(true) {} - - inline memorystream(uint8_t *data, unsigned size) { - pdata = data, psize = size, poffset = 0; - pwritable = true; - } - - inline memorystream(const uint8_t *data, unsigned size) { - pdata = (uint8_t*)data, psize = size, poffset = 0; - pwritable = false; - } - -protected: - mutable uint8_t *pdata; - mutable unsigned psize, poffset, pwritable; -}; - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/stream/mmap.hpp b/waterbox/libsnes/bsnes/nall/stream/mmap.hpp deleted file mode 100644 index a172ccf1fc..0000000000 --- a/waterbox/libsnes/bsnes/nall/stream/mmap.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#ifdef NALL_STREAM_INTERNAL_HPP - -namespace nall { - -struct mmapstream : stream { - inline bool seekable() const { return true; } - inline bool readable() const { return true; } - inline bool writable() const { return pwritable; } - inline bool randomaccess() const { return false; } - - inline unsigned size() const { return pmmap.size(); } - inline unsigned offset() const { return poffset; } - inline void seek(unsigned offset) const { poffset = offset; } - - inline uint8_t read() const { return pdata[poffset++]; } - inline void write(uint8_t data) const { pdata[poffset++] = data; } - - inline uint8_t read(unsigned offset) const { return pdata[offset]; } - inline void write(unsigned offset, uint8_t data) const { pdata[offset] = data; } - - inline mmapstream(const string &filename) { - pmmap.open(filename, filemap::mode::readwrite); - pwritable = pmmap.open(); - if(!pwritable) pmmap.open(filename, filemap::mode::read); - pdata = pmmap.data(), poffset = 0; - } - -private: - mutable filemap pmmap; - mutable uint8_t *pdata; - mutable unsigned pwritable, poffset; -}; - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/stream/stream.hpp b/waterbox/libsnes/bsnes/nall/stream/stream.hpp deleted file mode 100644 index 3fdee984c7..0000000000 --- a/waterbox/libsnes/bsnes/nall/stream/stream.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef NALL_STREAM_STREAM_HPP -#define NALL_STREAM_STREAM_HPP - -namespace nall { - -struct stream { - virtual bool seekable() const = 0; - virtual bool readable() const = 0; - virtual bool writable() const = 0; - virtual bool randomaccess() const = 0; - - virtual unsigned size() const = 0; - virtual unsigned offset() const = 0; - virtual void seek(unsigned offset) const = 0; - - virtual uint8_t read() const = 0; - virtual void write(uint8_t data) const = 0; - - inline virtual uint8_t read(unsigned) const { return 0; } - inline virtual void write(unsigned, uint8_t) const {} - - inline bool end() const { - return offset() >= size(); - } - - inline void copy(uint8_t *&data, unsigned &length) const { - seek(0); - length = size(); - data = new uint8_t[length]; - for(unsigned n = 0; n < length; n++) data[n] = read(); - } - - inline uintmax_t readl(unsigned length = 1) const { - uintmax_t data = 0, shift = 0; - while(length--) { data |= read() << shift; shift += 8; } - return data; - } - - inline uintmax_t readm(unsigned length = 1) const { - uintmax_t data = 0; - while(length--) data = (data << 8) | read(); - return data; - } - - inline void read(uint8_t *data, unsigned length) const { - while(length--) *data++ = read(); - } - - inline void writel(uintmax_t data, unsigned length = 1) const { - while(length--) { - write(data); - data >>= 8; - } - } - - inline void writem(uintmax_t data, unsigned length = 1) const { - uintmax_t shift = 8 * length; - while(length--) { - shift -= 8; - write(data >> shift); - } - } - - inline void write(const uint8_t *data, unsigned length) const { - while(length--) write(*data++); - } - - struct byte { - inline operator uint8_t() const { return s.read(offset); } - inline byte& operator=(uint8_t data) { s.write(offset, data); } - inline byte(const stream &s, unsigned offset) : s(s), offset(offset) {} - - private: - const stream &s; - const unsigned offset; - }; - - inline byte operator[](unsigned offset) const { - return byte(*this, offset); - } - - inline stream() {} - inline virtual ~stream() {} - stream(const stream&) = delete; - stream& operator=(const stream&) = delete; -}; - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/stream/zip.hpp b/waterbox/libsnes/bsnes/nall/stream/zip.hpp deleted file mode 100644 index dc1d82bc93..0000000000 --- a/waterbox/libsnes/bsnes/nall/stream/zip.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifdef NALL_STREAM_INTERNAL_HPP - -namespace nall { - -struct zipstream : memorystream { - inline zipstream(const stream &stream, const string &filter = "*") { - unsigned size = stream.size(); - uint8_t *data = new uint8_t[size]; - stream.read(data, size); - - zip archive; - if(archive.open(data, size) == false) return; - delete[] data; - - for(auto &file : archive.file) { - if(file.name.wildcard(filter)) { - archive.extract(file, pdata, psize); - return; - } - } - } - - inline ~zipstream() { - if(pdata) delete[] pdata; - } -}; - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string.hpp b/waterbox/libsnes/bsnes/nall/string.hpp deleted file mode 100644 index c29574552b..0000000000 --- a/waterbox/libsnes/bsnes/nall/string.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef NALL_STRING_HPP -#define NALL_STRING_HPP - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define NALL_STRING_INTERNAL_HPP -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#undef NALL_STRING_INTERNAL_HPP - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/base.hpp b/waterbox/libsnes/bsnes/nall/string/base.hpp deleted file mode 100644 index 2e0d4296ba..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/base.hpp +++ /dev/null @@ -1,200 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - struct cstring; - struct string; - struct lstring; - template inline const char* to_string(T); - - struct cstring { - inline operator const char*() const; - inline unsigned length() const; - inline bool operator==(const char*) const; - inline bool operator!=(const char*) const; - inline optional position(const char *key) const; - inline optional iposition(const char *key) const; - inline cstring& operator=(const char *data); - inline cstring(const char *data); - inline cstring(); - - protected: - const char *data; - }; - - struct string { - inline void reserve(unsigned); - inline bool empty() const; - - template inline string& assign(Args&&... args); - template inline string& append(Args&&... args); - - inline bool readfile(const string&); - - template inline string& replace(const char*, const char*); - template inline string& ireplace(const char*, const char*); - template inline string& qreplace(const char*, const char*); - template inline string& iqreplace(const char*, const char*); - - inline unsigned length() const; - inline unsigned capacity() const; - - template inline lstring split(const char*) const; - template inline lstring isplit(const char*) const; - template inline lstring qsplit(const char*) const; - template inline lstring iqsplit(const char*) const; - - inline bool equals(const char*) const; - inline bool iequals(const char*) const; - - inline bool wildcard(const char*) const; - inline bool iwildcard(const char*) const; - - inline bool beginswith(const char*) const; - inline bool ibeginswith(const char*) const; - inline bool endswith(const char*) const; - inline bool iendswith(const char*) const; - - inline string& lower(); - inline string& upper(); - inline string& qlower(); - inline string& qupper(); - inline string& transform(const char *before, const char *after); - - template inline string& ltrim(const char *key = " "); - template inline string& rtrim(const char *key = " "); - template inline string& trim(const char *key = " ", const char *rkey = 0); - - inline optional position(const char *key) const; - inline optional iposition(const char *key) const; - inline optional qposition(const char *key) const; - inline optional iqposition(const char *key) const; - - inline operator const char*() const; - inline char* operator()(); - inline char& operator[](int); - - inline bool operator==(const char*) const; - inline bool operator!=(const char*) const; - inline bool operator< (const char*) const; - inline bool operator<=(const char*) const; - inline bool operator> (const char*) const; - inline bool operator>=(const char*) const; - - inline string& operator=(const string&); - inline string& operator=(string&&); - - template inline string(Args&&... args); - inline string(const string&); - inline string(string&&); - inline ~string(); - - inline char* begin() { return &data[0]; } - inline char* end() { return &data[length()]; } - inline const char* begin() const { return &data[0]; } - inline const char* end() const { return &data[length()]; } - - //internal functions - inline string& assign_(const char*); - inline string& append_(const char*); - - protected: - char *data; - unsigned size; - - template inline string& ureplace(const char*, const char*); - - #if defined(QSTRING_H) - public: - inline operator QString() const; - #endif - }; - - struct lstring : vector { - inline optional find(const char*) const; - template inline lstring& split(const char*, const char*); - template inline lstring& isplit(const char*, const char*); - template inline lstring& qsplit(const char*, const char*); - template inline lstring& iqsplit(const char*, const char*); - - inline bool operator==(const lstring&) const; - inline bool operator!=(const lstring&) const; - - inline lstring(); - inline lstring(std::initializer_list); - - protected: - template inline lstring& usplit(const char*, const char*); - }; - - //compare.hpp - inline char chrlower(char c); - inline char chrupper(char c); - inline int istrcmp(const char *str1, const char *str2); - inline bool strbegin(const char *str, const char *key); - inline bool istrbegin(const char *str, const char *key); - inline bool strend(const char *str, const char *key); - inline bool istrend(const char *str, const char *key); - - //convert.hpp - inline char* strlower(char *str); - inline char* strupper(char *str); - inline char* qstrlower(char *str); - inline char* qstrupper(char *str); - inline char* strtr(char *dest, const char *before, const char *after); - - //math.hpp - inline bool strint(const char *str, int &result); - inline bool strmath(const char *str, int &result); - - //platform.hpp - inline string realpath(const char *name); - inline string userpath(); - inline string currentpath(); - - //strm.hpp - inline unsigned strmcpy(char *target, const char *source, unsigned length); - inline unsigned strmcat(char *target, const char *source, unsigned length); - inline bool strccpy(char *target, const char *source, unsigned length); - inline bool strccat(char *target, const char *source, unsigned length); - inline void strpcpy(char *&target, const char *source, unsigned &length); - - //strpos.hpp - inline optional strpos(const char *str, const char *key); - inline optional istrpos(const char *str, const char *key); - inline optional qstrpos(const char *str, const char *key); - inline optional iqstrpos(const char *str, const char *key); - template inline optional ustrpos(const char *str, const char *key); - - //trim.hpp - template inline char* ltrim(char *str, const char *key = " "); - template inline char* rtrim(char *str, const char *key = " "); - template inline char* trim(char *str, const char *key = " ", const char *rkey = 0); - - //utility.hpp - template alwaysinline bool chrequal(char x, char y); - template alwaysinline bool quoteskip(T *&p); - template alwaysinline bool quotecopy(char *&t, T *&p); - inline string substr(const char *src, unsigned start = 0, unsigned length = ~0u); - inline string sha256(const uint8_t *data, unsigned size); - - inline char* integer(char *result, intmax_t value); - inline char* decimal(char *result, uintmax_t value); - - template inline string integer(intmax_t value); - template inline string linteger(intmax_t value); - template inline string decimal(uintmax_t value); - template inline string ldecimal(uintmax_t value); - template inline string hex(uintmax_t value); - template inline string binary(uintmax_t value); - inline unsigned fp(char *str, long double value); - inline string fp(long double value); - - //variadic.hpp - template inline void print(Args&&... args); - - //wildcard.hpp - inline bool wildcard(const char *str, const char *pattern); - inline bool iwildcard(const char *str, const char *pattern); -}; - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/bml.hpp b/waterbox/libsnes/bsnes/nall/string/bml.hpp deleted file mode 100644 index d2fa60e392..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/bml.hpp +++ /dev/null @@ -1,151 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -//BML v1.0 parser -//revision 0.05 - -namespace nall { -namespace BML { - -inline static string indent(const char *s, unsigned depth) { - array output; - do { - for(unsigned n = 0; n < depth; n++) output.append('\t'); - do output.append(*s); while(*s && *s++ != '\n'); - } while(*s); - return output.get(); -} - -struct Node { - cstring name; - cstring value; - -private: - vector children; - - inline bool valid(char p) const { //A-Za-z0-9-. - return p - 'A' < 26u | p - 'a' < 26u | p - '0' < 10u | p - '-' < 2u; - } - - inline unsigned parseDepth(char *&p) { - while(*p == '\n' || *p == '#') { - while(*p != '\n') *p++ = 0; - *p++ = 0; //'\n' - } - unsigned depth = 0; - while(p[depth] == '\t') depth++; - return depth; - } - - inline void parseName(char *&p) { - if(valid(*p) == false) throw "Missing node name"; - name = p; - while(valid(*p)) p++; - } - - inline void parseValue(char *&p) { - char terminal = *p == ':' ? '\n' : ' '; //':' or '=' - *p++ = 0; - value = p; - while(*p && *p != terminal && *p != '\n') p++; - } - - inline void parseBlock(char *&p, unsigned depth) { - value = p; - char *w = p; - while(parseDepth(p) > depth) { - p += depth + 1; - while(*p && *p != '\n') *w++ = *p++; - if(*p && *p != '\n') throw "Multi-line value missing line feed"; - *w++ = *p; - } - *(w - 1) = 0; //'\n' - } - - inline void parseLine(char *&p) { - unsigned depth = parseDepth(p); - while(*p == '\t') p++; - - parseName(p); - bool multiLine = *p == '~'; - if(multiLine) *p++ = 0; - else if(*p == ':' || *p == '=') parseValue(p); - if(*p && *p != ' ' && *p != '\n') throw "Invalid character encountered"; - - while(*p == ' ') { - *p++ = 0; - Node node; - node.parseName(p); - if(*p == ':' || *p == '=') node.parseValue(p); - if(*p && *p != ' ' && *p != '\n') throw "Invalid character after node"; - if(*p == '\n') *p++ = 0; - children.append(node); - } - - if(multiLine) return parseBlock(p, depth); - - while(parseDepth(p) > depth) { - Node node; - node.parseLine(p); - children.append(node); - } - } - - inline void parse(char *&p) { - while(*p) { - Node node; - node.parseLine(p); - children.append(node); - } - } - -public: - inline Node& operator[](const char *name) { - for(auto &node : children) { - if(node.name == name) return node; - } - static Node node; - node.name = nullptr; - return node; - } - - inline bool exists() const { return name; } - unsigned size() const { return children.size(); } - Node* begin() { return children.begin(); } - Node* end() { return children.end(); } - const Node* begin() const { return children.begin(); } - const Node* end() const { return children.end(); } - inline Node() : name(""), value("") {} - friend class Document; -}; - -struct Document : Node { - cstring error; - - inline bool load(const char *document) { - if(document == nullptr) return false; - this->document = strdup(document); - char *p = this->document; - try { - this->error = nullptr; - parse(p); - } catch(const char *error) { - this->error = error; - free(this->document); - this->document = nullptr; - children.reset(); - return false; - } - return true; - } - - inline Document(const char *document = "") : document(nullptr), error(nullptr) { if(*document) load(document); } - inline ~Document() { if(document) free(document); } - -private: - char *document; -}; - -} -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/bsv.hpp b/waterbox/libsnes/bsnes/nall/string/bsv.hpp deleted file mode 100644 index d9415d53dd..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/bsv.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -//BSV v1.0 parser -//revision 0.02 - -namespace nall { - -struct BSV { - static inline string decode(const char *input) { - string output; - unsigned offset = 0; - while(*input) { - //illegal characters - if(*input == '}' ) return ""; - if(*input == '\r') return ""; - if(*input == '\n') return ""; - - //normal characters - if(*input != '{') { output[offset++] = *input++; continue; } - - //entities - if(strbegin(input, "{lf}")) { output[offset++] = '\n'; input += 4; continue; } - if(strbegin(input, "{lb}")) { output[offset++] = '{'; input += 4; continue; } - if(strbegin(input, "{rb}")) { output[offset++] = '}'; input += 4; continue; } - - //illegal entities - return ""; - } - output[offset] = 0; - return output; - } - - static inline string encode(const char *input) { - string output; - unsigned offset = 0; - while(*input) { - //illegal characters - if(*input == '\r') return ""; - - if(*input == '\n') { - output[offset++] = '{'; - output[offset++] = 'l'; - output[offset++] = 'f'; - output[offset++] = '}'; - input++; - continue; - } - - if(*input == '{') { - output[offset++] = '{'; - output[offset++] = 'l'; - output[offset++] = 'b'; - output[offset++] = '}'; - input++; - continue; - } - - if(*input == '}') { - output[offset++] = '{'; - output[offset++] = 'r'; - output[offset++] = 'b'; - output[offset++] = '}'; - input++; - continue; - } - - output[offset++] = *input++; - } - output[offset] = 0; - return output; - } -}; - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/cast.hpp b/waterbox/libsnes/bsnes/nall/string/cast.hpp deleted file mode 100644 index c7874515c6..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/cast.hpp +++ /dev/null @@ -1,189 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -//convert any (supported) type to a const char* without constructing a new nall::string -//this is used inside istring(...) to build nall::string values -template struct stringify; - -// base types - -template<> struct stringify { - bool value; - operator const char*() const { return value ? "true" : "false"; } - stringify(bool value) : value(value) {} -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(char value) { integer(data, value); } -}; - -// signed integers - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(signed char value) { integer(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(signed short value) { integer(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(signed int value) { integer(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(signed long value) { integer(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(signed long long value) { integer(data, value); } -}; - -template struct stringify> { - char data[256]; - operator const char*() const { return data; } - stringify(int_t value) { integer(data, value); } -}; - -// unsigned integers - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(unsigned char value) { decimal(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(unsigned short value) { decimal(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(unsigned int value) { decimal(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(unsigned long value) { decimal(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(unsigned long long value) { decimal(data, value); } -}; - -template struct stringify> { - char data[256]; - operator const char*() const { return data; } - stringify(uint_t value) { decimal(data, value); } -}; - -// floating-point - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(float value) { fp(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(double value) { fp(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(long double value) { fp(data, value); } -}; - -// strings - -template<> struct stringify { - const char *value; - operator const char*() const { return value; } - stringify(char *value) : value(value) {} -}; - -template<> struct stringify { - const char *value; - operator const char*() const { return value; } - stringify(const char *value) : value(value) {} -}; - -template<> struct stringify { - //zero 17-jun-2015 - this is a bug. dangling reference can and will go out of scope - //const string &value; - string value; - operator const char*() const { return value; } - stringify(const string &value) : value(value) {} -}; - -template<> struct stringify { - //zero 17-jun-2015 - this is a bug. dangling reference can and will go out of scope - //const string &value; - string value; - operator const char*() const { return value; } - stringify(const string &value) : value(value) {} -}; - -template<> struct stringify { - const char *value; - operator const char*() const { return value; } - stringify(const cstring &value) : value(value) {} -}; - -template<> struct stringify { - const char *value; - operator const char*() const { return value; } - stringify(const cstring &value) : value(value) {} -}; - -#if defined(QSTRING_H) - -template<> struct stringify { - const QString &value; - operator const char*() const { return value.toUtf8().constData(); } - stringify(const QString &value) : value(value) {} -}; - -template<> struct stringify { - const QString &value; - operator const char*() const { return value.toUtf8().constData(); } - stringify(const QString &value) : value(value) {} -}; - -string::operator QString() const { - return QString::fromUtf8(*this); -} - -#endif - -// - -template stringify make_string(T value) { - return stringify(std::forward(value)); -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/compare.hpp b/waterbox/libsnes/bsnes/nall/string/compare.hpp deleted file mode 100644 index 941c8e6769..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/compare.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -char chrlower(char c) { - return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; -} - -char chrupper(char c) { - return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c; -} - -int istrcmp(const char *str1, const char *str2) { - while(*str1) { - if(chrlower(*str1) != chrlower(*str2)) break; - str1++, str2++; - } - return (int)chrlower(*str1) - (int)chrlower(*str2); -} - -bool strbegin(const char *str, const char *key) { - int i, ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - return (!memcmp(str, key, ksl)); -} - -bool istrbegin(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - for(int i = 0; i < ksl; i++) { - if(str[i] >= 'A' && str[i] <= 'Z') { - if(str[i] != key[i] && str[i]+0x20 != key[i])return false; - } else if(str[i] >= 'a' && str[i] <= 'z') { - if(str[i] != key[i] && str[i]-0x20 != key[i])return false; - } else { - if(str[i] != key[i])return false; - } - } - return true; -} - -bool strend(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - return (!memcmp(str + ssl - ksl, key, ksl)); -} - -bool istrend(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - for(int i = ssl - ksl, z = 0; i < ssl; i++, z++) { - if(str[i] >= 'A' && str[i] <= 'Z') { - if(str[i] != key[z] && str[i]+0x20 != key[z])return false; - } else if(str[i] >= 'a' && str[i] <= 'z') { - if(str[i] != key[z] && str[i]-0x20 != key[z])return false; - } else { - if(str[i] != key[z])return false; - } - } - return true; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/convert.hpp b/waterbox/libsnes/bsnes/nall/string/convert.hpp deleted file mode 100644 index f5a2a7808d..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/convert.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -char* strlower(char *str) { - if(!str) return 0; - int i = 0; - while(str[i]) { - str[i] = chrlower(str[i]); - i++; - } - return str; -} - -char* strupper(char *str) { - if(!str) return 0; - int i = 0; - while(str[i]) { - str[i] = chrupper(str[i]); - i++; - } - return str; -} - -char* qstrlower(char *s) { - if(!s) return 0; - bool quoted = false; - while(*s) { - if(*s == '\"' || *s == '\'') quoted ^= 1; - if(quoted == false && *s >= 'A' && *s <= 'Z') *s += 0x20; - s++; - } -} - -char* qstrupper(char *s) { - if(!s) return 0; - bool quoted = false; - while(*s) { - if(*s == '\"' || *s == '\'') quoted ^= 1; - if(quoted == false && *s >= 'a' && *s <= 'z') *s -= 0x20; - s++; - } -} - -char* strtr(char *dest, const char *before, const char *after) { - if(!dest || !before || !after) return dest; - int sl = strlen(dest), bsl = strlen(before), asl = strlen(after); - - if(bsl != asl || bsl == 0) return dest; //patterns must be the same length for 1:1 replace - for(unsigned i = 0; i < sl; i++) { - for(unsigned l = 0; l < bsl; l++) { - if(dest[i] == before[l]) { - dest[i] = after[l]; - break; - } - } - } - - return dest; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/core.hpp b/waterbox/libsnes/bsnes/nall/string/core.hpp deleted file mode 100644 index e5281b82bf..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/core.hpp +++ /dev/null @@ -1,163 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -static void istring(string &output) { -} - -template -static void istring(string &output, const T &value, Args&&... args) { - output.append_(make_string(value)); - istring(output, std::forward(args)...); -} - -void string::reserve(unsigned size_) { - if(size_ > size) { - size = size_; - data = (char*)realloc(data, size + 1); - data[size] = 0; - } -} - -bool string::empty() const { - return !*data; -} - -template string& string::assign(Args&&... args) { - *data = 0; - istring(*this, std::forward(args)...); - return *this; -} - -template string& string::append(Args&&... args) { - istring(*this, std::forward(args)...); - return *this; -} - -string& string::assign_(const char *s) { - unsigned length = strlen(s); - reserve(length); - strcpy(data, s); - return *this; -} - -string& string::append_(const char *s) { - unsigned length = strlen(data) + strlen(s); - reserve(length); - strcat(data, s); - return *this; -} - -string::operator const char*() const { - return data; -} - -char* string::operator()() { - return data; -} - -char& string::operator[](int index) { - reserve(index); - return data[index]; -} - -bool string::operator==(const char *str) const { return strcmp(data, str) == 0; } -bool string::operator!=(const char *str) const { return strcmp(data, str) != 0; } -bool string::operator< (const char *str) const { return strcmp(data, str) < 0; } -bool string::operator<=(const char *str) const { return strcmp(data, str) <= 0; } -bool string::operator> (const char *str) const { return strcmp(data, str) > 0; } -bool string::operator>=(const char *str) const { return strcmp(data, str) >= 0; } - -string& string::operator=(const string &value) { - if(&value == this) return *this; - assign(value); - return *this; -} - -string& string::operator=(string &&source) { - if(&source == this) return *this; - if(data) free(data); - size = source.size; - data = source.data; - source.data = nullptr; - source.size = 0; - return *this; -} - -template string::string(Args&&... args) { - size = 64; - data = (char*)malloc(size + 1); - *data = 0; - istring(*this, std::forward(args)...); -} - -string::string(const string &value) { - if(&value == this) return; - size = strlen(value); - data = strdup(value); -} - -string::string(string &&source) { - if(&source == this) return; - size = source.size; - data = source.data; - source.data = nullptr; -} - -string::~string() { - if(data) free(data); -} - -bool string::readfile(const string &filename) { - assign(""); - - #if !defined(_WIN32) - FILE *fp = fopen(filename, "rb"); - #else - FILE *fp = _wfopen(utf16_t(filename), L"rb"); - #endif - if(!fp) return false; - - fseek(fp, 0, SEEK_END); - unsigned size = ftell(fp); - rewind(fp); - char *fdata = new char[size + 1]; - unsigned unused = fread(fdata, 1, size, fp); - fclose(fp); - fdata[size] = 0; - assign(fdata); - delete[] fdata; - - return true; -} - -optional lstring::find(const char *key) const { - for(unsigned i = 0; i < size(); i++) { - if(operator[](i) == key) return { true, i }; - } - return { false, 0 }; -} - -bool lstring::operator==(const lstring &source) const { - if(this == &source) return true; - if(size() != source.size()) return false; - for(unsigned n = 0; n < size(); n++) { - if(operator[](n) != source[n]) return false; - } - return true; -} - -bool lstring::operator!=(const lstring &source) const { - return !operator==(source); -} - -inline lstring::lstring() { -} - -inline lstring::lstring(std::initializer_list list) { - for(auto &data : list) append(data); -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/cstring.hpp b/waterbox/libsnes/bsnes/nall/string/cstring.hpp deleted file mode 100644 index 13b508ff0a..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/cstring.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -//const string: -//bind a const char* pointer to an object that has various testing functionality; -//yet lacks the memory allocation and modification functionality of the string class - -namespace nall { - -cstring::operator const char*() const { return data; } -unsigned cstring::length() const { return strlen(data); } -bool cstring::operator==(const char *s) const { return !strcmp(data, s); } -bool cstring::operator!=(const char *s) const { return strcmp(data, s); } -optional cstring::position (const char *key) const { return strpos(data, key); } -optional cstring::iposition(const char *key) const { return istrpos(data, key); } -cstring& cstring::operator=(const char *data) { this->data = data; return *this; } -cstring::cstring(const char *data) : data(data) {} -cstring::cstring() : data("") {} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/filename.hpp b/waterbox/libsnes/bsnes/nall/string/filename.hpp deleted file mode 100644 index 6dea67fc99..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/filename.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -// "foo/bar.c" -> "foo/" -// "foo/" -> "foo/" -// "bar.c" -> "./" -inline string dir(char const *name) { - string result = name; - for(signed i = strlen(result); i >= 0; i--) { - if(result[i] == '/' || result[i] == '\\') { - result[i + 1] = 0; - break; - } - if(i == 0) result = "./"; - } - return result; -} - -// "foo/bar.c" -> "bar.c" -inline string notdir(char const *name) { - for(signed i = strlen(name); i >= 0; i--) { - if(name[i] == '/' || name[i] == '\\') { - name += i + 1; - break; - } - } - string result = name; - return result; -} - -// "foo/bar.c" -> "foo/bar" -inline string basename(char const *name) { - string result = name; - for(signed i = strlen(result); i >= 0; i--) { - if(result[i] == '/' || result[i] == '\\') { - //file has no extension - break; - } - if(result[i] == '.') { - result[i] = 0; - break; - } - } - return result; -} - -// "foo/bar.c" -> "c" -inline string extension(char const *name) { - for(signed i = strlen(name); i >= 0; i--) { - if(name[i] == '.') { - name += i + 1; - break; - } - } - string result = name; - return result; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/math-fixed-point.hpp b/waterbox/libsnes/bsnes/nall/string/math-fixed-point.hpp deleted file mode 100644 index a61b23f317..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/math-fixed-point.hpp +++ /dev/null @@ -1,166 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace fixedpoint { - -static nall::function eval_fallback; - -static intmax_t eval_integer(const char *& s) { - if(!*s) throw "unrecognized integer"; - intmax_t value = 0, x = *s, y = *(s + 1); - - //hexadecimal - if(x == '0' && (y == 'X' || y == 'x')) { - s += 2; - while(true) { - if(*s >= '0' && *s <= '9') { value = value * 16 + (*s++ - '0'); continue; } - if(*s >= 'A' && *s <= 'F') { value = value * 16 + (*s++ - 'A' + 10); continue; } - if(*s >= 'a' && *s <= 'f') { value = value * 16 + (*s++ - 'a' + 10); continue; } - return value; - } - } - - //binary - if(x == '0' && (y == 'B' || y == 'b')) { - s += 2; - while(true) { - if(*s == '0' || *s == '1') { value = value * 2 + (*s++ - '0'); continue; } - return value; - } - } - - //octal (or decimal '0') - if(x == '0') { - s += 1; - while(true) { - if(*s >= '0' && *s <= '7') { value = value * 8 + (*s++ - '0'); continue; } - return value; - } - } - - //decimal - if(x >= '0' && x <= '9') { - while(true) { - if(*s >= '0' && *s <= '9') { value = value * 10 + (*s++ - '0'); continue; } - return value; - } - } - - //char - if(x == '\'' && y != '\'') { - s += 1; - while(true) { - value = value * 256 + *s++; - if(*s == '\'') { s += 1; return value; } - if(!*s) throw "mismatched char"; - } - } - - throw "unrecognized integer"; -} - -static intmax_t eval(const char *&s, int depth = 0) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace - if(!*s) throw "unrecognized token"; - intmax_t value = 0, x = *s, y = *(s + 1); - - if(*s == '(') { - value = eval(++s, 1); - if(*s++ != ')') throw "mismatched group"; - } - - else if(x == '!') value = !eval(++s, 13); - else if(x == '~') value = ~eval(++s, 13); - else if(x == '+') value = +eval(++s, 13); - else if(x == '-') value = -eval(++s, 13); - - else if((x >= '0' && x <= '9') || x == '\'') value = eval_integer(s); - - else if(eval_fallback) value = eval_fallback(s); //optional user-defined syntax parsing - - else throw "unrecognized token"; - - while(true) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace - if(!*s) break; - x = *s, y = *(s + 1); - - if(depth >= 13) break; - if(x == '*') { value *= eval(++s, 13); continue; } - if(x == '/') { intmax_t result = eval(++s, 13); if(result == 0) throw "division by zero"; value /= result; continue; } - if(x == '%') { intmax_t result = eval(++s, 13); if(result == 0) throw "division by zero"; value %= result; continue; } - - if(depth >= 12) break; - if(x == '+') { value += eval(++s, 12); continue; } - if(x == '-') { value -= eval(++s, 12); continue; } - - if(depth >= 11) break; - if(x == '<' && y == '<') { value <<= eval(++++s, 11); continue; } - if(x == '>' && y == '>') { value >>= eval(++++s, 11); continue; } - - if(depth >= 10) break; - if(x == '<' && y == '=') { value = value <= eval(++++s, 10); continue; } - if(x == '>' && y == '=') { value = value >= eval(++++s, 10); continue; } - if(x == '<') { value = value < eval(++s, 10); continue; } - if(x == '>') { value = value > eval(++s, 10); continue; } - - if(depth >= 9) break; - if(x == '=' && y == '=') { value = value == eval(++++s, 9); continue; } - if(x == '!' && y == '=') { value = value != eval(++++s, 9); continue; } - - if(depth >= 8) break; - if(x == '&' && y != '&') { value = value & eval(++s, 8); continue; } - - if(depth >= 7) break; - if(x == '^' && y != '^') { value = value ^ eval(++s, 7); continue; } - - if(depth >= 6) break; - if(x == '|' && y != '|') { value = value | eval(++s, 6); continue; } - - if(depth >= 5) break; - if(x == '&' && y == '&') { value = eval(++++s, 5) && value; continue; } - - if(depth >= 4) break; - if(x == '^' && y == '^') { value = (!eval(++++s, 4) != !value); continue; } - - if(depth >= 3) break; - if(x == '|' && y == '|') { value = eval(++++s, 3) || value; continue; } - - if(x == '?') { - intmax_t lhs = eval(++s, 2); - if(*s != ':') throw "mismatched ternary"; - intmax_t rhs = eval(++s, 2); - value = value ? lhs : rhs; - continue; - } - if(depth >= 2) break; - - if(depth > 0 && x == ')') break; - - throw "unrecognized token"; - } - - return value; -} - -static bool eval(const char *s, intmax_t &result) { - try { - result = eval(s); - return true; - } catch(const char*) { - result = 0; - return false; - } -} - -static intmax_t parse(const char *s) { - try { - intmax_t result = eval(s); - return result; - } catch(const char *) { - return 0; - } -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/math-floating-point.hpp b/waterbox/libsnes/bsnes/nall/string/math-floating-point.hpp deleted file mode 100644 index 43a2f0f42e..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/math-floating-point.hpp +++ /dev/null @@ -1,157 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace floatingpoint { - -static nall::function eval_fallback; - -static double eval_integer(const char *&s) { - if(!*s) throw "unrecognized integer"; - intmax_t value = 0, radix = 0, x = *s, y = *(s + 1); - - //hexadecimal - if(x == '0' && (y == 'X' || y == 'x')) { - s += 2; - while(true) { - if(*s >= '0' && *s <= '9') { value = value * 16 + (*s++ - '0'); continue; } - if(*s >= 'A' && *s <= 'F') { value = value * 16 + (*s++ - 'A' + 10); continue; } - if(*s >= 'a' && *s <= 'f') { value = value * 16 + (*s++ - 'a' + 10); continue; } - return value; - } - } - - //binary - if(x == '0' && (y == 'B' || y == 'b')) { - s += 2; - while(true) { - if(*s == '0' || *s == '1') { value = value * 2 + (*s++ - '0'); continue; } - return value; - } - } - - //octal (or decimal '0') - if(x == '0' && y != '.') { - s += 1; - while(true) { - if(*s >= '0' && *s <= '7') { value = value * 8 + (*s++ - '0'); continue; } - return value; - } - } - - //decimal - if(x >= '0' && x <= '9') { - while(true) { - if(*s >= '0' && *s <= '9') { value = value * 10 + (*s++ - '0'); continue; } - if(*s == '.') { s++; break; } - return value; - } - //floating-point - while(true) { - if(*s >= '0' && *s <= '9') { radix = radix * 10 + (*s++ - '0'); continue; } - return atof(nall::string{ nall::decimal(value), ".", nall::decimal(radix) }); - } - } - - //char - if(x == '\'' && y != '\'') { - s += 1; - while(true) { - value = value * 256 + *s++; - if(*s == '\'') { s += 1; return value; } - if(!*s) throw "mismatched char"; - } - } - - throw "unrecognized integer"; -} - -static double eval(const char *&s, int depth = 0) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace - if(!*s) throw "unrecognized token"; - double value = 0, x = *s, y = *(s + 1); - - if(*s == '(') { - value = eval(++s, 1); - if(*s++ != ')') throw "mismatched group"; - } - - else if(x == '!') value = !eval(++s, 9); - else if(x == '+') value = +eval(++s, 9); - else if(x == '-') value = -eval(++s, 9); - - else if((x >= '0' && x <= '9') || x == '\'') value = eval_integer(s); - - else if(eval_fallback) value = eval_fallback(s); //optional user-defined syntax parsing - - else throw "unrecognized token"; - - while(true) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace - if(!*s) break; - x = *s, y = *(s + 1); - - if(depth >= 9) break; - if(x == '*') { value *= eval(++s, 9); continue; } - if(x == '/') { double result = eval(++s, 9); if(result == 0.0) throw "division by zero"; value /= result; continue; } - - if(depth >= 8) break; - if(x == '+') { value += eval(++s, 8); continue; } - if(x == '-') { value -= eval(++s, 8); continue; } - - if(depth >= 7) break; - if(x == '<' && y == '=') { value = value <= eval(++++s, 7); continue; } - if(x == '>' && y == '=') { value = value >= eval(++++s, 7); continue; } - if(x == '<') { value = value < eval(++s, 7); continue; } - if(x == '>') { value = value > eval(++s, 7); continue; } - - if(depth >= 6) break; - if(x == '=' && y == '=') { value = value == eval(++++s, 6); continue; } - if(x == '!' && y == '=') { value = value != eval(++++s, 6); continue; } - - if(depth >= 5) break; - if(x == '&' && y == '&') { value = eval(++++s, 5) && value; continue; } - - if(depth >= 4) break; - if(x == '^' && y == '^') { value = (!eval(++++s, 4) != !value); continue; } - - if(depth >= 3) break; - if(x == '|' && y == '|') { value = eval(++++s, 3) || value; continue; } - - if(x == '?') { - double lhs = eval(++s, 2); - if(*s != ':') throw "mismatched ternary"; - double rhs = eval(++s, 2); - value = value ? lhs : rhs; - continue; - } - if(depth >= 2) break; - - if(depth > 0 && x == ')') break; - - throw "unrecognized token"; - } - - return value; -} - -static bool eval(const char *s, double &result) { - try { - result = eval(s); - return true; - } catch(const char*e) { - result = 0; - return false; - } -} - -static double parse(const char *s) { - try { - double result = eval(s); - return result; - } catch(const char *) { - return 0; - } -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/platform.hpp b/waterbox/libsnes/bsnes/nall/string/platform.hpp deleted file mode 100644 index 83a5fbae99..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/platform.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -string currentpath() { - char path[PATH_MAX]; - if(::getcwd(path)) { - string result(path); - result.transform("\\", "/"); - if(result.endswith("/") == false) result.append("/"); - return result; - } - return "./"; -} - -string userpath() { - char path[PATH_MAX]; - if(::userpath(path)) { - string result(path); - result.transform("\\", "/"); - if(result.endswith("/") == false) result.append("/"); - return result; - } - return currentpath(); -} - -string realpath(const char *name) { - char path[PATH_MAX]; - if(::realpath(name, path)) { - string result(path); - result.transform("\\", "/"); - return result; - } - return userpath(); -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/replace.hpp b/waterbox/libsnes/bsnes/nall/string/replace.hpp deleted file mode 100644 index 2bd1412feb..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/replace.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -template -string& string::ureplace(const char *key, const char *token) { - if(!key || !*key) return *this; - enum : unsigned { limit = Limit ? Limit : ~0u }; - - const char *p = data; - unsigned counter = 0, keyLength = 0; - - while(*p) { - if(quoteskip(p)) continue; - for(unsigned n = 0;; n++) { - if(key[n] == 0) { counter++; p += n; keyLength = n; break; } - if(!chrequal(key[n], p[n])) { p++; break; } - } - } - if(counter == 0) return *this; - if(Limit) counter = min(counter, Limit); - - char *t = data, *base; - unsigned tokenLength = strlen(token); - if(tokenLength > keyLength) { - t = base = strdup(data); - reserve((unsigned)(p - data) + ((tokenLength - keyLength) * counter)); - } - char *o = data; - - while(*t && counter) { - if(quotecopy(o, t)) continue; - for(unsigned n = 0;; n++) { - if(key[n] == 0) { counter--; memcpy(o, token, tokenLength); t += keyLength; o += tokenLength; break; } - if(!chrequal(key[n], t[n])) { *o++ = *t++; break; } - } - } - do *o++ = *t; while(*t++); - if(tokenLength > keyLength) free(base); - - return *this; -} - -template string &string::replace(const char *key, const char *token) { return ureplace(key, token); } -template string &string::ireplace(const char *key, const char *token) { return ureplace(key, token); } -template string &string::qreplace(const char *key, const char *token) { return ureplace(key, token); } -template string &string::iqreplace(const char *key, const char *token) { return ureplace(key, token); } - -}; - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/split.hpp b/waterbox/libsnes/bsnes/nall/string/split.hpp deleted file mode 100644 index bb12a91b60..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/split.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -template lstring& lstring::usplit(const char *key, const char *base) { - reset(); - if(!key || !*key) return *this; - - const char *p = base; - - while(*p) { - if(Limit) if(size() >= Limit) break; - if(quoteskip(p)) continue; - for(unsigned n = 0;; n++) { - if(key[n] == 0) { - append(substr(base, 0, p - base)); - p += n; - base = p; - break; - } - if(!chrequal(key[n], p[n])) { p++; break; } - } - } - - append(base); - return *this; -} - -template lstring& lstring::split(const char *key, const char *src) { return usplit(key, src); } -template lstring& lstring::isplit(const char *key, const char *src) { return usplit(key, src); } -template lstring& lstring::qsplit(const char *key, const char *src) { return usplit(key, src); } -template lstring& lstring::iqsplit(const char *key, const char *src) { return usplit(key, src); } - -}; - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/strm.hpp b/waterbox/libsnes/bsnes/nall/string/strm.hpp deleted file mode 100644 index 21d05652c3..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/strm.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -// -//strmcpy, strmcat created by byuu -// - -//return = strlen(target) -unsigned strmcpy(char *target, const char *source, unsigned length) { - const char *origin = target; - if(length) { - while(*source && --length) *target++ = *source++; - *target = 0; - } - return target - origin; -} - -//return = strlen(target) -unsigned strmcat(char *target, const char *source, unsigned length) { - const char *origin = target; - while(*target && length) target++, length--; - return (target - origin) + strmcpy(target, source, length); -} - -//return = true when all of source was copied -bool strccpy(char *target, const char *source, unsigned length) { - return !source[strmcpy(target, source, length)]; -} - -//return = true when all of source was copied -bool strccat(char *target, const char *source, unsigned length) { - while(*target && length) target++, length--; - return !source[strmcpy(target, source, length)]; -} - -//return = reserved for future use -void strpcpy(char *&target, const char *source, unsigned &length) { - unsigned offset = strmcpy(target, source, length); - target += offset, length -= offset; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/strpos.hpp b/waterbox/libsnes/bsnes/nall/string/strpos.hpp deleted file mode 100644 index fe563a6ccf..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/strpos.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -//usage example: -//if(auto position = strpos(str, key)) print(position(), "\n"); -//prints position of key within str; but only if it is found - -namespace nall { - -template -optional ustrpos(const char *str, const char *key) { - const char *base = str; - - while(*str) { - if(quoteskip(str)) continue; - for(unsigned n = 0;; n++) { - if(key[n] == 0) return { true, (unsigned)(str - base) }; - if(str[n] == 0) return { false, 0 }; - if(!chrequal(str[n], key[n])) break; - } - str++; - } - - return { false, 0 }; -} - -optional strpos(const char *str, const char *key) { return ustrpos(str, key); } -optional istrpos(const char *str, const char *key) { return ustrpos(str, key); } -optional qstrpos(const char *str, const char *key) { return ustrpos(str, key); } -optional iqstrpos(const char *str, const char *key) { return ustrpos(str, key); } - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/trim.hpp b/waterbox/libsnes/bsnes/nall/string/trim.hpp deleted file mode 100644 index ba049d71d3..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/trim.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -//limit defaults to zero, which will underflow on first compare; equivalent to no limit -template char* ltrim(char *str, const char *key) { - unsigned limit = Limit; - if(!key || !*key) return str; - while(strbegin(str, key)) { - char *dest = str, *src = str + strlen(key); - while(true) { - *dest = *src++; - if(!*dest) break; - dest++; - } - if(--limit == 0) break; - } - return str; -} - -template char* rtrim(char *str, const char *key) { - unsigned limit = Limit; - if(!key || !*key) return str; - while(strend(str, key)) { - str[strlen(str) - strlen(key)] = 0; - if(--limit == 0) break; - } - return str; -} - -template char* trim(char *str, const char *key, const char *rkey) { - if(rkey) return ltrim(rtrim(str, rkey), key); - return ltrim(rtrim(str, key), key); -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/utf8.hpp b/waterbox/libsnes/bsnes/nall/string/utf8.hpp deleted file mode 100644 index 77397bf2b3..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/utf8.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -struct UTF8 { - unsigned size; //size of encoded codepoint - uint64_t data; //encoded codepoint - unsigned codepoint; //decoded codepoint -}; - -inline UTF8 utf8_read(const char *s) { - UTF8 utf8; - - if((*s & 0xfe) == 0xfc) utf8.size = 6; - else if((*s & 0xfc) == 0xf8) utf8.size = 5; - else if((*s & 0xf8) == 0xf0) utf8.size = 4; - else if((*s & 0xf0) == 0xe0) utf8.size = 3; - else if((*s & 0xe0) == 0xc0) utf8.size = 2; - else utf8.size = 1; - - utf8.data = 0; - for(unsigned n = 0; n < utf8.size; n++) { - utf8.data = (utf8.data << 8) | (uint8_t)s[n]; - } - - static uint8_t mask[] = { 0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; - utf8.codepoint = s[0] & mask[utf8.size]; - for(unsigned n = 1; n < utf8.size; n++) { - utf8.codepoint = (utf8.codepoint << 6) | (s[n] & 0x3f); - } - - return utf8; -} - -inline void utf8_write(char *s, const UTF8 &utf8) { - for(signed n = utf8.size - 1, shift = 0; n >= 0; n--, shift += 8) { - s[n] = utf8.data >> shift; - } -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/utility.hpp b/waterbox/libsnes/bsnes/nall/string/utility.hpp deleted file mode 100644 index 945728ba23..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/utility.hpp +++ /dev/null @@ -1,285 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -#include - -namespace nall { - -template -bool chrequal(char x, char y) { - if(Insensitive) return chrlower(x) == chrlower(y); - return x == y; -} - -template -bool quoteskip(T *&p) { - if(Quoted == false) return false; - if(*p != '\'' && *p != '\"') return false; - - while(*p == '\'' || *p == '\"') { - char x = *p++; - while(*p && *p++ != x); - } - return true; -} - -template -bool quotecopy(char *&t, T *&p) { - if(Quoted == false) return false; - if(*p != '\'' && *p != '\"') return false; - - while(*p == '\'' || *p == '\"') { - char x = *p++; - *t++ = x; - while(*p && *p != x) *t++ = *p++; - *t++ = *p++; - } - return true; -} - -string substr(const char *src, unsigned start, unsigned length) { - string dest; - if(length == ~0u) { - //copy entire string - dest.reserve(strlen(src + start) + 1); - strcpy(dest(), src + start); - } else { - //copy partial string - dest.reserve(length + 1); - strmcpy(dest(), src + start, length + 1); - } - return dest; -} - -string sha256(const uint8_t *data, unsigned size) { - sha256_ctx sha; - uint8_t hash[32]; - sha256_init(&sha); - sha256_chunk(&sha, data, size); - sha256_final(&sha); - sha256_hash(&sha, hash); - string result; - for(auto &byte : hash) result.append(hex<2>(byte)); - return result; -} - -/* cast.hpp arithmetic -> string */ - -char* integer(char *result, intmax_t value) { - bool negative = value < 0; - if(negative) value = -value; - - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - buffer[size++] = negative ? '-' : '+'; - - for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) result[x] = buffer[y]; - result[size] = 0; - return result; -} - -char* decimal(char *result, uintmax_t value) { - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - - for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) result[x] = buffer[y]; - result[size] = 0; - return result; -} - -/* general-purpose arithmetic -> string */ - -template string integer(intmax_t value) { - bool negative = value < 0; - if(negative) value = -value; - - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - buffer[size++] = negative ? '-' : '+'; - buffer[size] = 0; - - unsigned length = (length_ == 0 ? size : length_); - char result[length + 1]; - memset(result, padding, length); - result[length] = 0; - - for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -template string linteger(intmax_t value) { - bool negative = value < 0; - if(negative) value = -value; - - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - buffer[size++] = negative ? '-' : '+'; - buffer[size] = 0; - - unsigned length = (length_ == 0 ? size : length_); - char result[length + 1]; - memset(result, padding, length); - result[length] = 0; - - for(signed x = 0, y = size - 1; x < length && y >= 0; x++, y--) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -template string decimal(uintmax_t value) { - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - buffer[size] = 0; - - unsigned length = (length_ == 0 ? size : length_); - std::vector result(length + 1); - memset(result.data(), padding, length); - result[length] = 0; - - for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { - result[x] = buffer[y]; - } - - return (const char*)result.data(); -} - -template string ldecimal(uintmax_t value) { - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - buffer[size] = 0; - - unsigned length = (length_ == 0 ? size : length_); - char result[length + 1]; - memset(result, padding, length); - result[length] = 0; - - for(signed x = 0, y = size - 1; x < length && y >= 0; x++, y--) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -template string hex(uintmax_t value) { - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value & 15; - buffer[size++] = n < 10 ? '0' + n : 'a' + n - 10; - value >>= 4; - } while(value); - - unsigned length = (length_ == 0 ? size : length_); - std::vector result(length + 1); - memset(result.data(), padding, length); - result[length] = 0; - - for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { - result[x] = buffer[y]; - } - - return (const char*)result.data(); -} - -template string binary(uintmax_t value) { - char buffer[256]; - unsigned size = 0; - - do { - unsigned n = value & 1; - buffer[size++] = '0' + n; - value >>= 1; - } while(value); - - unsigned length = (length_ == 0 ? size : length_); - char result[length + 1]; - memset(result, padding, length); - result[length] = 0; - - for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -//using sprintf is certainly not the most ideal method to convert -//a double to a string ... but attempting to parse a double by -//hand, digit-by-digit, results in subtle rounding errors. -unsigned fp(char *str, long double value) { - char buffer[256]; - #ifdef _WIN32 - //Windows C-runtime does not support long double via sprintf() - sprintf(buffer, "%f", (double)value); - #else - sprintf(buffer, "%Lf", value); - #endif - - //remove excess 0's in fraction (2.500000 -> 2.5) - for(char *p = buffer; *p; p++) { - if(*p == '.') { - char *p = buffer + strlen(buffer) - 1; - while(*p == '0') { - if(*(p - 1) != '.') *p = 0; //... but not for eg 1.0 -> 1. - p--; - } - break; - } - } - - unsigned length = strlen(buffer); - if(str) strcpy(str, buffer); - return length + 1; -} - -string fp(long double value) { - string temp; - temp.reserve(fp(0, value)); - fp(temp(), value); - return temp; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/variadic.hpp b/waterbox/libsnes/bsnes/nall/string/variadic.hpp deleted file mode 100644 index c43bfe86f7..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/variadic.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -template inline void print(Args&&... args) { - printf("%s", (const char*)string(std::forward(args)...)); -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/wildcard.hpp b/waterbox/libsnes/bsnes/nall/string/wildcard.hpp deleted file mode 100644 index 9d2359d50c..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/wildcard.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -bool wildcard(const char *s, const char *p) { - const char *cp = 0, *mp = 0; - while(*s && *p != '*') { - if(*p != '?' && *s != *p) return false; - p++, s++; - } - while(*s) { - if(*p == '*') { - if(!*++p) return true; - mp = p, cp = s + 1; - } else if(*p == '?' || *p == *s) { - p++, s++; - } else { - p = mp, s = cp++; - } - } - while(*p == '*') p++; - return !*p; -} - -bool iwildcard(const char *s, const char *p) { - const char *cp = 0, *mp = 0; - while(*s && *p != '*') { - if(*p != '?' && chrlower(*s) != chrlower(*p)) return false; - p++, s++; - } - while(*s) { - if(*p == '*') { - if(!*++p) return true; - mp = p, cp = s + 1; - } else if(*p == '?' || chrlower(*p) == chrlower(*s)) { - p++, s++; - } else { - p = mp, s = cp++; - } - } - while(*p == '*') p++; - return !*p; -} - -inline bool tokenize(const char *s, const char *p) { - while(*s) { - if(*p == '*') { - while(*s) if(tokenize(s++, p + 1)) return true; - return !*++p; - } - if(*s++ != *p++) return false; - } - while(*p == '*') p++; - return !*p; -} - -inline bool tokenize(lstring &list, const char *s, const char *p) { - while(*s) { - if(*p == '*') { - const char *b = s; - while(*s) { - if(tokenize(list, s++, p + 1)) { - list.prepend(substr(b, 0, --s - b)); - return true; - } - } - list.prepend(b); - return !*++p; - } - if(*s++ != *p++) return false; - } - while(*p == '*') { list.prepend(s); p++; } - return !*p; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/wrapper.hpp b/waterbox/libsnes/bsnes/nall/string/wrapper.hpp deleted file mode 100644 index 9845e0b7ef..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/wrapper.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -unsigned string::length() const { return strlen(data); } -unsigned string::capacity() const { return size; } - -template lstring string::split(const char *key) const { lstring result; result.split(key, data); return result; } -template lstring string::isplit(const char *key) const { lstring result; result.isplit(key, data); return result; } -template lstring string::qsplit(const char *key) const { lstring result; result.qsplit(key, data); return result; } -template lstring string::iqsplit(const char *key) const { lstring result; result.iqsplit(key, data); return result; } - -bool string::equals(const char *str) const { return !strcmp(data, str); } -bool string::iequals(const char *str) const { return !istrcmp(data, str); } - -bool string::wildcard(const char *str) const { return nall::wildcard(data, str); } -bool string::iwildcard(const char *str) const { return nall::iwildcard(data, str); } - -bool string::beginswith(const char *str) const { return strbegin(data, str); } -bool string::ibeginswith(const char *str) const { return istrbegin(data, str); } - -bool string::endswith(const char *str) const { return strend(data, str); } -bool string::iendswith(const char *str) const { return istrend(data, str); } - -string& string::lower() { nall::strlower(data); return *this; } -string& string::upper() { nall::strupper(data); return *this; } -string& string::qlower() { nall::qstrlower(data); return *this; } -string& string::qupper() { nall::qstrupper(data); return *this; } -string& string::transform(const char *before, const char *after) { nall::strtr(data, before, after); return *this; } - -template string& string::ltrim(const char *key) { nall::ltrim(data, key); return *this; } -template string& string::rtrim(const char *key) { nall::rtrim(data, key); return *this; } -template string& string::trim(const char *key, const char *rkey) { nall::trim (data, key, rkey); return *this; } - -optional string::position(const char *key) const { return strpos(data, key); } -optional string::iposition(const char *key) const { return istrpos(data, key); } -optional string::qposition(const char *key) const { return qstrpos(data, key); } -optional string::iqposition(const char *key) const { return iqstrpos(data, key); } - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/xml-legacy.hpp b/waterbox/libsnes/bsnes/nall/string/xml-legacy.hpp deleted file mode 100644 index 069639b00d..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/xml-legacy.hpp +++ /dev/null @@ -1,265 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -//XML v1.0 subset parser -//revision 0.05 - -namespace nall { - -struct xml_attribute { - string name; - string content; - virtual string parse() const; -}; - -struct xml_element : xml_attribute { - string parse() const; - linear_vector attribute; - linear_vector element; - -protected: - void parse_doctype(const char *&data); - bool parse_head(string data); - bool parse_body(const char *&data); - friend xml_element xml_parse(const char *data); -}; - -inline string xml_attribute::parse() const { - string data; - unsigned offset = 0; - - const char *source = content; - while(*source) { - if(*source == '&') { - if(strbegin(source, "<")) { data[offset++] = '<'; source += 4; continue; } - if(strbegin(source, ">")) { data[offset++] = '>'; source += 4; continue; } - if(strbegin(source, "&")) { data[offset++] = '&'; source += 5; continue; } - if(strbegin(source, "'")) { data[offset++] = '\''; source += 6; continue; } - if(strbegin(source, """)) { data[offset++] = '"'; source += 6; continue; } - } - - //reject illegal characters - if(*source == '&') return ""; - if(*source == '<') return ""; - if(*source == '>') return ""; - - data[offset++] = *source++; - } - - data[offset] = 0; - return data; -} - -inline string xml_element::parse() const { - string data; - unsigned offset = 0; - - const char *source = content; - while(*source) { - if(*source == '&') { - if(strbegin(source, "<")) { data[offset++] = '<'; source += 4; continue; } - if(strbegin(source, ">")) { data[offset++] = '>'; source += 4; continue; } - if(strbegin(source, "&")) { data[offset++] = '&'; source += 5; continue; } - if(strbegin(source, "'")) { data[offset++] = '\''; source += 6; continue; } - if(strbegin(source, """)) { data[offset++] = '"'; source += 6; continue; } - } - - if(strbegin(source, "")) { - source += pos() + 3; - continue; - } else { - return ""; - } - } - - if(strbegin(source, "")) { - if(pos() - 9 > 0) { - string cdata = substr(source, 9, pos() - 9); - data.append(cdata); - offset += strlen(cdata); - } - source += 9 + offset + 3; - continue; - } else { - return ""; - } - } - - //reject illegal characters - if(*source == '&') return ""; - if(*source == '<') return ""; - if(*source == '>') return ""; - - data[offset++] = *source++; - } - - data[offset] = 0; - return data; -} - -inline void xml_element::parse_doctype(const char *&data) { - name = "!DOCTYPE"; - const char *content_begin = data; - - signed counter = 0; - while(*data) { - char value = *data++; - if(value == '<') counter++; - if(value == '>') counter--; - if(counter < 0) { - content = substr(content_begin, 0, data - content_begin - 1); - return; - } - } - throw "..."; -} - -inline bool xml_element::parse_head(string data) { - data.qreplace("\t", " "); - data.qreplace("\r", " "); - data.qreplace("\n", " "); - while(qstrpos(data, " ")) data.qreplace(" ", " "); - data.qreplace(" =", "="); - data.qreplace("= ", "="); - data.rtrim(); - - lstring part; - part.qsplit(" ", data); - - name = part[0]; - if(name == "") throw "..."; - - for(unsigned i = 1; i < part.size(); i++) { - lstring side; - side.qsplit("=", part[i]); - if(side.size() != 2) throw "..."; - - xml_attribute attr; - attr.name = side[0]; - attr.content = side[1]; - if(strbegin(attr.content, "\"") && strend(attr.content, "\"")) attr.content.trim<1>("\""); - else if(strbegin(attr.content, "'") && strend(attr.content, "'")) attr.content.trim<1>("'"); - else throw "..."; - attribute.append(attr); - } -} - -inline bool xml_element::parse_body(const char *&data) { - while(true) { - if(!*data) return false; - if(*data++ != '<') continue; - if(*data == '/') return false; - - if(strbegin(data, "!DOCTYPE") == true) { - parse_doctype(data); - return true; - } - - if(strbegin(data, "!--")) { - if(auto offset = strpos(data, "-->")) { - data += offset() + 3; - continue; - } else { - throw "..."; - } - } - - if(strbegin(data, "![CDATA[")) { - if(auto offset = strpos(data, "]]>")) { - data += offset() + 3; - continue; - } else { - throw "..."; - } - } - - auto offset = strpos(data, ">"); - if(!offset) throw "..."; - - string tag = substr(data, 0, offset()); - data += offset() + 1; - const char *content_begin = data; - - bool self_terminating = false; - - if(strend(tag, "?") == true) { - self_terminating = true; - tag.rtrim<1>("?"); - } else if(strend(tag, "/") == true) { - self_terminating = true; - tag.rtrim<1>("/"); - } - - parse_head(tag); - if(self_terminating) return true; - - while(*data) { - unsigned index = element.size(); - xml_element node; - if(node.parse_body(data) == false) { - if(*data == '/') { - signed length = data - content_begin - 1; - if(length > 0) content = substr(content_begin, 0, length); - - data++; - auto offset = strpos(data, ">"); - if(!offset) throw "..."; - - tag = substr(data, 0, offset()); - data += offset() + 1; - - tag.replace("\t", " "); - tag.replace("\r", " "); - tag.replace("\n", " "); - while(strpos(tag, " ")) tag.replace(" ", " "); - tag.rtrim(); - - if(name != tag) throw "..."; - return true; - } - } else { - element.append(node); - } - } - } -} - -//ensure there is only one root element -inline bool xml_validate(xml_element &document) { - unsigned root_counter = 0; - - for(unsigned i = 0; i < document.element.size(); i++) { - string &name = document.element[i].name; - if(strbegin(name, "?")) continue; - if(strbegin(name, "!")) continue; - if(++root_counter > 1) return false; - } - - return true; -} - -inline xml_element xml_parse(const char *data) { - xml_element self; - - try { - while(*data) { - xml_element node; - if(node.parse_body(data) == false) { - break; - } else { - self.element.append(node); - } - } - - if(xml_validate(self) == false) throw "..."; - return self; - } catch(const char*) { - xml_element empty; - return empty; - } -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/string/xml.hpp b/waterbox/libsnes/bsnes/nall/string/xml.hpp deleted file mode 100644 index e08a354f5c..0000000000 --- a/waterbox/libsnes/bsnes/nall/string/xml.hpp +++ /dev/null @@ -1,250 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -//XML v1.0 subset parser -//revision 0.01 - -namespace nall { -namespace XML { - -struct Node { - string name; - string data; - bool attribute; - array children; - - inline bool exists() const { - return !name.empty(); - } - - inline bool isName(char c) const { - if(c >= 'A' && c <= 'Z') return true; - if(c >= 'a' && c <= 'z') return true; - if(c >= '0' && c <= '9') return true; - if(c == '.' || c == '_') return true; - if(c == '?') return true; - return false; - } - - inline bool isWhitespace(char c) const { - if(c == ' ' || c == '\t') return true; - if(c == '\r' || c == '\n') return true; - return false; - } - - //copy part of string from source document into target string; decode markup while copying - inline void copy(string &target, const char *source, unsigned length) { - target.reserve(length + 1); - - #if defined(NALL_XML_LITERAL) - memcpy(target(), source, length); - target[length] = 0; - return; - #endif - - char *output = target(); - while(length) { - if(*source == '&') { - if(!memcmp(source, "<", 4)) { *output++ = '<'; source += 4; length -= 4; continue; } - if(!memcmp(source, ">", 4)) { *output++ = '>'; source += 4; length -= 4; continue; } - if(!memcmp(source, "&", 5)) { *output++ = '&'; source += 5; length -= 5; continue; } - if(!memcmp(source, "'", 6)) { *output++ = '\''; source += 6; length -= 6; continue; } - if(!memcmp(source, """, 6)) { *output++ = '\"'; source += 6; length -= 6; continue; } - } - - if(attribute == false && source[0] == '<' && source[1] == '!') { - //comment - if(!memcmp(source, "", 3)) source++, length--; - source += 3, length -= 3; - continue; - } - - //CDATA - if(!memcmp(source, "", 3)) *output++ = *source++, length--; - source += 3, length -= 3; - continue; - } - } - - *output++ = *source++, length--; - } - *output = 0; - } - - inline bool parseExpression(const char *&p) { - if(*(p + 1) != '!') return false; - - //comment - if(!memcmp(p, "", 3)) p++; - if(!*p) throw "unclosed comment"; - p += 3; - return true; - } - - //CDATA - if(!memcmp(p, "", 3)) p++; - if(!*p) throw "unclosed CDATA"; - p += 3; - return true; - } - - //DOCTYPE - if(!memcmp(p, "') counter--; - } while(counter); - return true; - } - - return false; - } - - //returns true if tag closes itself (); false if not () - inline bool parseHead(const char *&p) { - //parse name - const char *nameStart = ++p; //skip '<' - while(isName(*p)) p++; - const char *nameEnd = p; - copy(name, nameStart, nameEnd - nameStart); - if(name.empty()) throw "missing element name"; - - //parse attributes - while(*p) { - while(isWhitespace(*p)) p++; - if(!*p) throw "unclosed attribute"; - if(*p == '?' || *p == '/' || *p == '>') break; - - //parse attribute name - Node *attribute = new Node; - children.append(attribute); - attribute->attribute = true; - - const char *nameStart = p; - while(isName(*p)) p++; - const char *nameEnd = p; - copy(attribute->name, nameStart, nameEnd - nameStart); - if(attribute->name.empty()) throw "missing attribute name"; - - //parse attribute data - if(*p++ != '=') throw "missing attribute value"; - char terminal = *p++; - if(terminal != '\'' && terminal != '\"') throw "attribute value not quoted"; - const char *dataStart = p; - while(*p && *p != terminal) p++; - if(!*p) throw "missing attribute data terminal"; - const char *dataEnd = p++; //skip closing terminal - - copy(attribute->data, dataStart, dataEnd - dataStart); - } - - //parse closure - if(*p == '?' && *(p + 1) == '>') { p += 2; return true; } - if(*p == '/' && *(p + 1) == '>') { p += 2; return true; } - if(*p == '>') { p += 1; return false; } - throw "invalid element tag"; - } - - //parse element and all of its child elements - inline void parseElement(const char *&p) { - Node *node = new Node; - children.append(node); - if(node->parseHead(p) == true) return; - node->parse(p); - } - - //return true if matches this node's name - inline bool parseClosureElement(const char *&p) { - if(p[0] != '<' || p[1] != '/') return false; - p += 2; - const char *nameStart = p; - while(*p && *p != '>') p++; - if(*p != '>') throw "unclosed closure element"; - const char *nameEnd = p++; - if(memcmp(name, nameStart, nameEnd - nameStart)) throw "closure element name mismatch"; - return true; - } - - //parse contents of an element - inline void parse(const char *&p) { - const char *dataStart = p, *dataEnd = p; - - while(*p) { - while(*p && *p != '<') p++; - if(!*p) break; - dataEnd = p; - if(parseClosureElement(p) == true) break; - if(parseExpression(p) == true) continue; - parseElement(p); - } - - copy(data, dataStart, dataEnd - dataStart); - } - - inline void reset() { - for(auto &child : children) delete child; - children.reset(); - } - - struct iterator { - inline bool operator!=(const iterator &source) const { return index != source.index; } - inline Node& operator*() { return *node.children[index]; } - inline iterator& operator++() { index++; return *this; } - inline iterator(const Node &node, unsigned index) : node(node), index(index) {} - private: - const Node &node; - unsigned index; - }; - - inline iterator begin() { return iterator(*this, 0); } - inline iterator end() { return iterator(*this, children.size()); } - inline const iterator begin() const { return iterator(*this, 0); } - inline const iterator end() const { return iterator(*this, children.size()); } - - inline Node& operator[](const char *name) { - for(auto &node : *this) { - if(node.name == name) return node; - } - static Node node; - return node; - } - - inline Node() : attribute(false) {} - inline ~Node() { reset(); } - - Node(const Node&) = delete; - Node& operator=(const Node&) = delete; -}; - -struct Document : Node { - string error; - - inline bool load(const char *document) { - if(document == nullptr) return false; - reset(); - try { - parse(document); - } catch(const char *error) { - reset(); - this->error = error; - return false; - } - return true; - } - - inline Document() {} - inline Document(const char *document) { load(document); } -}; - -} -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/type_traits.hpp b/waterbox/libsnes/bsnes/nall/type_traits.hpp deleted file mode 100644 index 1be3bf79ca..0000000000 --- a/waterbox/libsnes/bsnes/nall/type_traits.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef NALL_STATIC_HPP -#define NALL_STATIC_HPP - -#include - -namespace nall { - -template class has_default_constructor { - template class receive_size{}; - template static signed sfinae(receive_size*); - template static char sfinae(...); - -public: - enum : bool { value = sizeof(sfinae(0)) == sizeof(signed) }; -}; - -template struct enable_if { typedef T type; }; -template struct enable_if {}; - -template struct type_if { typedef T type; }; -template struct type_if { typedef F type; }; - -template struct static_and { enum { value = false }; }; -template<> struct static_and { enum { value = true }; }; - -template struct static_or { enum { value = false }; }; -template<> struct static_or { enum { value = true }; }; -template<> struct static_or { enum { value = true }; }; -template<> struct static_or { enum { value = true }; }; - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/ups.hpp b/waterbox/libsnes/bsnes/nall/ups.hpp deleted file mode 100644 index ffcdb2d7e5..0000000000 --- a/waterbox/libsnes/bsnes/nall/ups.hpp +++ /dev/null @@ -1,223 +0,0 @@ -#ifndef NALL_UPS_HPP -#define NALL_UPS_HPP - -#include -#include -#include -#include - -namespace nall { - -struct ups { - enum class result : unsigned { - unknown, - success, - patch_unwritable, - patch_invalid, - source_invalid, - target_invalid, - target_too_small, - patch_checksum_invalid, - source_checksum_invalid, - target_checksum_invalid, - }; - - function progress; - - result create( - const uint8_t *sourcedata, unsigned sourcelength, - const uint8_t *targetdata, unsigned targetlength, - const char *patchfilename - ) { - source_data = (uint8_t*)sourcedata, target_data = (uint8_t*)targetdata; - source_length = sourcelength, target_length = targetlength; - source_offset = target_offset = 0; - source_checksum = target_checksum = patch_checksum = ~0; - - if(patch_file.open(patchfilename, file::mode::write) == false) return result::patch_unwritable; - - patch_write('U'); - patch_write('P'); - patch_write('S'); - patch_write('1'); - encode(source_length); - encode(target_length); - - unsigned output_length = source_length > target_length ? source_length : target_length; - unsigned relative = 0; - for(unsigned offset = 0; offset < output_length;) { - uint8_t x = source_read(); - uint8_t y = target_read(); - - if(x == y) { - offset++; - continue; - } - - encode(offset++ - relative); - patch_write(x ^ y); - - while(true) { - if(offset >= output_length) { - patch_write(0x00); - break; - } - - x = source_read(); - y = target_read(); - offset++; - patch_write(x ^ y); - if(x == y) break; - } - - relative = offset; - } - - source_checksum = ~source_checksum; - target_checksum = ~target_checksum; - for(unsigned i = 0; i < 4; i++) patch_write(source_checksum >> (i * 8)); - for(unsigned i = 0; i < 4; i++) patch_write(target_checksum >> (i * 8)); - uint32_t patch_result_checksum = ~patch_checksum; - for(unsigned i = 0; i < 4; i++) patch_write(patch_result_checksum >> (i * 8)); - - patch_file.close(); - return result::success; - } - - result apply( - const uint8_t *patchdata, unsigned patchlength, - const uint8_t *sourcedata, unsigned sourcelength, - uint8_t *targetdata, unsigned &targetlength - ) { - patch_data = (uint8_t*)patchdata, source_data = (uint8_t*)sourcedata, target_data = targetdata; - patch_length = patchlength, source_length = sourcelength, target_length = targetlength; - patch_offset = source_offset = target_offset = 0; - patch_checksum = source_checksum = target_checksum = ~0; - - if(patch_length < 18) return result::patch_invalid; - if(patch_read() != 'U') return result::patch_invalid; - if(patch_read() != 'P') return result::patch_invalid; - if(patch_read() != 'S') return result::patch_invalid; - if(patch_read() != '1') return result::patch_invalid; - - unsigned source_read_length = decode(); - unsigned target_read_length = decode(); - - if(source_length != source_read_length && source_length != target_read_length) return result::source_invalid; - targetlength = (source_length == source_read_length ? target_read_length : source_read_length); - if(target_length < targetlength) return result::target_too_small; - target_length = targetlength; - - while(patch_offset < patch_length - 12) { - unsigned length = decode(); - while(length--) target_write(source_read()); - while(true) { - uint8_t patch_xor = patch_read(); - target_write(patch_xor ^ source_read()); - if(patch_xor == 0) break; - } - } - while(source_offset < source_length) target_write(source_read()); - while(target_offset < target_length) target_write(source_read()); - - uint32_t patch_read_checksum = 0, source_read_checksum = 0, target_read_checksum = 0; - for(unsigned i = 0; i < 4; i++) source_read_checksum |= patch_read() << (i * 8); - for(unsigned i = 0; i < 4; i++) target_read_checksum |= patch_read() << (i * 8); - uint32_t patch_result_checksum = ~patch_checksum; - source_checksum = ~source_checksum; - target_checksum = ~target_checksum; - for(unsigned i = 0; i < 4; i++) patch_read_checksum |= patch_read() << (i * 8); - - if(patch_result_checksum != patch_read_checksum) return result::patch_invalid; - if(source_checksum == source_read_checksum && source_length == source_read_length) { - if(target_checksum == target_read_checksum && target_length == target_read_length) return result::success; - return result::target_invalid; - } else if(source_checksum == target_read_checksum && source_length == target_read_length) { - if(target_checksum == source_read_checksum && target_length == source_read_length) return result::success; - return result::target_invalid; - } else { - return result::source_invalid; - } - } - -private: - uint8_t *patch_data, *source_data, *target_data; - unsigned patch_length, source_length, target_length; - unsigned patch_offset, source_offset, target_offset; - unsigned patch_checksum, source_checksum, target_checksum; - file patch_file; - - uint8_t patch_read() { - if(patch_offset < patch_length) { - uint8_t n = patch_data[patch_offset++]; - patch_checksum = crc32_adjust(patch_checksum, n); - return n; - } - return 0x00; - } - - uint8_t source_read() { - if(source_offset < source_length) { - uint8_t n = source_data[source_offset++]; - source_checksum = crc32_adjust(source_checksum, n); - return n; - } - return 0x00; - } - - uint8_t target_read() { - uint8_t result = 0x00; - if(target_offset < target_length) { - result = target_data[target_offset]; - target_checksum = crc32_adjust(target_checksum, result); - } - if(((target_offset++ & 255) == 0) && progress) { - progress(target_offset, source_length > target_length ? source_length : target_length); - } - return result; - } - - void patch_write(uint8_t n) { - patch_file.write(n); - patch_checksum = crc32_adjust(patch_checksum, n); - } - - void target_write(uint8_t n) { - if(target_offset < target_length) { - target_data[target_offset] = n; - target_checksum = crc32_adjust(target_checksum, n); - } - if(((target_offset++ & 255) == 0) && progress) { - progress(target_offset, source_length > target_length ? source_length : target_length); - } - } - - void encode(uint64_t offset) { - while(true) { - uint64_t x = offset & 0x7f; - offset >>= 7; - if(offset == 0) { - patch_write(0x80 | x); - break; - } - patch_write(x); - offset--; - } - } - - uint64_t decode() { - uint64_t offset = 0, shift = 1; - while(true) { - uint8_t x = patch_read(); - offset += (x & 0x7f) * shift; - if(x & 0x80) break; - shift <<= 7; - offset += shift; - } - return offset; - } -}; - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/utility.hpp b/waterbox/libsnes/bsnes/nall/utility.hpp deleted file mode 100644 index b3c1e5aab9..0000000000 --- a/waterbox/libsnes/bsnes/nall/utility.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef NALL_UTILITY_HPP -#define NALL_UTILITY_HPP - -#include -#include - -namespace nall { - template struct base_from_member { - T value; - base_from_member(T value_) : value(value_) {} - }; - - template class optional { - public: - bool valid; - T value; - public: - inline operator bool() const { return valid; } - inline const T& operator()() const { if(!valid) throw; return value; } - inline optional& operator=(const optional &source) { valid = source.valid; value = source.value; return *this; } - inline optional() : valid(false) {} - inline optional(bool valid, const T &value) : valid(valid), value(value) {} - }; - - template inline T* allocate(unsigned size, const T &value) { - T *array = new T[size]; - for(unsigned i = 0; i < size; i++) array[i] = value; - return array; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/varint.hpp b/waterbox/libsnes/bsnes/nall/varint.hpp deleted file mode 100644 index 439d3c6b0a..0000000000 --- a/waterbox/libsnes/bsnes/nall/varint.hpp +++ /dev/null @@ -1,192 +0,0 @@ -#ifndef NALL_VARINT_HPP -#define NALL_VARINT_HPP - -#include -#include - -namespace nall { - template class uint_t { - private: - typedef typename type_if::type type_t; - type_t data; - - public: - inline operator type_t() const { return data; } - inline type_t operator ++(int) { type_t r = data; data = uclip(data + 1); return r; } - inline type_t operator --(int) { type_t r = data; data = uclip(data - 1); return r; } - inline type_t operator ++() { return data = uclip(data + 1); } - inline type_t operator --() { return data = uclip(data - 1); } - inline type_t operator =(const type_t i) { return data = uclip(i); } - inline type_t operator |=(const type_t i) { return data = uclip(data | i); } - inline type_t operator ^=(const type_t i) { return data = uclip(data ^ i); } - inline type_t operator &=(const type_t i) { return data = uclip(data & i); } - inline type_t operator<<=(const type_t i) { return data = uclip(data << i); } - inline type_t operator>>=(const type_t i) { return data = uclip(data >> i); } - inline type_t operator +=(const type_t i) { return data = uclip(data + i); } - inline type_t operator -=(const type_t i) { return data = uclip(data - i); } - inline type_t operator *=(const type_t i) { return data = uclip(data * i); } - inline type_t operator /=(const type_t i) { return data = uclip(data / i); } - inline type_t operator %=(const type_t i) { return data = uclip(data % i); } - - inline uint_t() : data(0) {} - inline uint_t(const type_t i) : data(uclip(i)) {} - - template inline type_t operator=(const uint_t &i) { return data = uclip((type_t)i); } - template inline uint_t(const uint_t &i) : data(uclip(i)) {} - }; - - template class int_t { - private: - typedef typename type_if::type type_t; - type_t data; - - public: - inline operator type_t() const { return data; } - inline type_t operator ++(int) { type_t r = data; data = sclip(data + 1); return r; } - inline type_t operator --(int) { type_t r = data; data = sclip(data - 1); return r; } - inline type_t operator ++() { return data = sclip(data + 1); } - inline type_t operator --() { return data = sclip(data - 1); } - inline type_t operator =(const type_t i) { return data = sclip(i); } - inline type_t operator |=(const type_t i) { return data = sclip(data | i); } - inline type_t operator ^=(const type_t i) { return data = sclip(data ^ i); } - inline type_t operator &=(const type_t i) { return data = sclip(data & i); } - inline type_t operator<<=(const type_t i) { return data = sclip(data << i); } - inline type_t operator>>=(const type_t i) { return data = sclip(data >> i); } - inline type_t operator +=(const type_t i) { return data = sclip(data + i); } - inline type_t operator -=(const type_t i) { return data = sclip(data - i); } - inline type_t operator *=(const type_t i) { return data = sclip(data * i); } - inline type_t operator /=(const type_t i) { return data = sclip(data / i); } - inline type_t operator %=(const type_t i) { return data = sclip(data % i); } - - inline int_t() : data(0) {} - inline int_t(const type_t i) : data(sclip(i)) {} - - template inline type_t operator=(const int_t &i) { return data = sclip((type_t)i); } - template inline int_t(const int_t &i) : data(sclip(i)) {} - }; - - class varuint_t { - private: - unsigned data; - unsigned mask; - - public: - inline operator unsigned() const { return data; } - inline unsigned operator ++(int) { unsigned r = data; data = (data + 1) & mask; return r; } - inline unsigned operator --(int) { unsigned r = data; data = (data - 1) & mask; return r; } - inline unsigned operator ++() { return data = (data + 1) & mask; } - inline unsigned operator --() { return data = (data - 1) & mask; } - inline unsigned operator =(const unsigned i) { return data = (i) & mask; } - inline unsigned operator |=(const unsigned i) { return data = (data | i) & mask; } - inline unsigned operator ^=(const unsigned i) { return data = (data ^ i) & mask; } - inline unsigned operator &=(const unsigned i) { return data = (data & i) & mask; } - inline unsigned operator<<=(const unsigned i) { return data = (data << i) & mask; } - inline unsigned operator>>=(const unsigned i) { return data = (data >> i) & mask; } - inline unsigned operator +=(const unsigned i) { return data = (data + i) & mask; } - inline unsigned operator -=(const unsigned i) { return data = (data - i) & mask; } - inline unsigned operator *=(const unsigned i) { return data = (data * i) & mask; } - inline unsigned operator /=(const unsigned i) { return data = (data / i) & mask; } - inline unsigned operator %=(const unsigned i) { return data = (data % i) & mask; } - - inline void bits(unsigned bits) { mask = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1); data &= mask; } - inline varuint_t() : data(0), mask(~0U) {} - inline varuint_t(const unsigned i) : data(i), mask(~0U) {} - }; - - class varuintmax_t { - private: - uintmax_t data; - uintmax_t mask; - - public: - inline operator uintmax_t() const { return data; } - inline uintmax_t operator ++(int) { uintmax_t r = data; data = (data + 1) & mask; return r; } - inline uintmax_t operator --(int) { uintmax_t r = data; data = (data - 1) & mask; return r; } - inline uintmax_t operator ++() { return data = (data + 1) & mask; } - inline uintmax_t operator --() { return data = (data - 1) & mask; } - inline uintmax_t operator =(const uintmax_t i) { return data = (i) & mask; } - inline uintmax_t operator |=(const uintmax_t i) { return data = (data | i) & mask; } - inline uintmax_t operator ^=(const uintmax_t i) { return data = (data ^ i) & mask; } - inline uintmax_t operator &=(const uintmax_t i) { return data = (data & i) & mask; } - inline uintmax_t operator<<=(const uintmax_t i) { return data = (data << i) & mask; } - inline uintmax_t operator>>=(const uintmax_t i) { return data = (data >> i) & mask; } - inline uintmax_t operator +=(const uintmax_t i) { return data = (data + i) & mask; } - inline uintmax_t operator -=(const uintmax_t i) { return data = (data - i) & mask; } - inline uintmax_t operator *=(const uintmax_t i) { return data = (data * i) & mask; } - inline uintmax_t operator /=(const uintmax_t i) { return data = (data / i) & mask; } - inline uintmax_t operator %=(const uintmax_t i) { return data = (data % i) & mask; } - - inline void bits(unsigned bits) { mask = (1ULL << (bits - 1)) + ((1ULL << (bits - 1)) - 1); data &= mask; } - inline varuintmax_t() : data(0), mask(~0ULL) {} - inline varuintmax_t(const uintmax_t i) : data(i), mask(~0ULL) {} - }; -} - -//typedefs - typedef nall::uint_t< 1> uint1_t; - typedef nall::uint_t< 2> uint2_t; - typedef nall::uint_t< 3> uint3_t; - typedef nall::uint_t< 4> uint4_t; - typedef nall::uint_t< 5> uint5_t; - typedef nall::uint_t< 6> uint6_t; - typedef nall::uint_t< 7> uint7_t; -//typedef nall::uint_t< 8> uint8_t; - typedef nall::uint_t< 9> uint9_t; - typedef nall::uint_t<10> uint10_t; - typedef nall::uint_t<11> uint11_t; - typedef nall::uint_t<12> uint12_t; - typedef nall::uint_t<13> uint13_t; - typedef nall::uint_t<14> uint14_t; - typedef nall::uint_t<15> uint15_t; -//typedef nall::uint_t<16> uint16_t; - typedef nall::uint_t<17> uint17_t; - typedef nall::uint_t<18> uint18_t; - typedef nall::uint_t<19> uint19_t; - typedef nall::uint_t<20> uint20_t; - typedef nall::uint_t<21> uint21_t; - typedef nall::uint_t<22> uint22_t; - typedef nall::uint_t<23> uint23_t; - typedef nall::uint_t<24> uint24_t; - typedef nall::uint_t<25> uint25_t; - typedef nall::uint_t<26> uint26_t; - typedef nall::uint_t<27> uint27_t; - typedef nall::uint_t<28> uint28_t; - typedef nall::uint_t<29> uint29_t; - typedef nall::uint_t<30> uint30_t; - typedef nall::uint_t<31> uint31_t; -//typedef nall::uint_t<32> uint32_t; - - typedef nall::int_t< 1> int1_t; - typedef nall::int_t< 2> int2_t; - typedef nall::int_t< 3> int3_t; - typedef nall::int_t< 4> int4_t; - typedef nall::int_t< 5> int5_t; - typedef nall::int_t< 6> int6_t; - typedef nall::int_t< 7> int7_t; -//typedef nall::int_t< 8> int8_t; - typedef nall::int_t< 9> int9_t; - typedef nall::int_t<10> int10_t; - typedef nall::int_t<11> int11_t; - typedef nall::int_t<12> int12_t; - typedef nall::int_t<13> int13_t; - typedef nall::int_t<14> int14_t; - typedef nall::int_t<15> int15_t; -//typedef nall::int_t<16> int16_t; - typedef nall::int_t<17> int17_t; - typedef nall::int_t<18> int18_t; - typedef nall::int_t<19> int19_t; - typedef nall::int_t<20> int20_t; - typedef nall::int_t<21> int21_t; - typedef nall::int_t<22> int22_t; - typedef nall::int_t<23> int23_t; - typedef nall::int_t<24> int24_t; - typedef nall::int_t<25> int25_t; - typedef nall::int_t<26> int26_t; - typedef nall::int_t<27> int27_t; - typedef nall::int_t<28> int28_t; - typedef nall::int_t<29> int29_t; - typedef nall::int_t<30> int30_t; - typedef nall::int_t<31> int31_t; -//typedef nall::int_t<32> int32_t; - -#endif diff --git a/waterbox/libsnes/bsnes/nall/vector.hpp b/waterbox/libsnes/bsnes/nall/vector.hpp deleted file mode 100644 index efa522a827..0000000000 --- a/waterbox/libsnes/bsnes/nall/vector.hpp +++ /dev/null @@ -1,459 +0,0 @@ -#ifndef NALL_VECTOR_HPP -#define NALL_VECTOR_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - template struct vector { - struct exception_out_of_bounds{}; - - protected: - T *pool; - unsigned poolsize; - unsigned objectsize; - - public: - unsigned size() const { return objectsize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) { - for(unsigned n = 0; n < objectsize; n++) pool[n].~T(); - free(pool); - } - pool = nullptr; - poolsize = 0; - objectsize = 0; - } - - void reserve(unsigned size) { - size = bit::round(size); //amortize growth - T *copy = (T*)calloc(size, sizeof(T)); - for(unsigned n = 0; n < min(size, objectsize); n++) new(copy + n) T(pool[n]); - for(unsigned n = 0; n < objectsize; n++) pool[n].~T(); - free(pool); - pool = copy; - poolsize = size; - objectsize = min(size, objectsize); - } - - template - void append(const T& data, Args&&... args) { - append(data); - append(std::forward(args)...); - } - - void append(const T& data) { - if(objectsize + 1 > poolsize) reserve(objectsize + 1); - new(pool + objectsize++) T(data); - } - - void insert(unsigned position, const T& data) { - append(data); - for(signed n = size() - 1; n > position; n--) pool[n] = pool[n - 1]; - pool[position] = data; - } - - void prepend(const T& data) { - insert(0, data); - } - - void remove(unsigned index = ~0u, unsigned count = 1) { - if(index == ~0) index = objectsize ? objectsize - 1 : 0; - for(unsigned n = index; count + n < objectsize; n++) pool[n] = pool[count + n]; - objectsize = (count + index >= objectsize) ? index : objectsize - count; - } - - T take(unsigned index = ~0u) { - if(index == ~0) index = objectsize ? objectsize - 1 : 0; - if(index >= objectsize) throw exception_out_of_bounds(); - T item = pool[index]; - remove(index); - return item; - } - - void sort() { - nall::sort(pool, objectsize); - } - - template void sort(const Comparator &lessthan) { - nall::sort(pool, objectsize, lessthan); - } - - optional find(const T& data) { - for(unsigned n = 0; n < size(); n++) if(pool[n] == data) return { true, n }; - return { false, 0u }; - } - - T& first() { - if(objectsize == 0) throw exception_out_of_bounds(); - return pool[0]; - } - - T& last() { - if(objectsize == 0) throw exception_out_of_bounds(); - return pool[objectsize - 1]; - } - - //access - inline T& operator[](unsigned position) { - if(position >= objectsize) throw exception_out_of_bounds(); - return pool[position]; - } - - inline const T& operator[](unsigned position) const { - if(position >= objectsize) throw exception_out_of_bounds(); - return pool[position]; - } - - inline T& operator()(unsigned position) { - if(position >= poolsize) reserve(position + 1); - while(position >= objectsize) append(T()); - return pool[position]; - } - - inline const T& operator()(unsigned position, const T& data) const { - if(position >= objectsize) return data; - return pool[position]; - } - - //iteration - T* begin() { return &pool[0]; } - T* end() { return &pool[objectsize]; } - const T* begin() const { return &pool[0]; } - const T* end() const { return &pool[objectsize]; } - - //copy - inline vector& operator=(const vector &source) { - reset(); - reserve(source.capacity()); - for(auto &data : source) append(data); - return *this; - } - - vector(const vector &source) : pool(nullptr), poolsize(0), objectsize(0) { - operator=(source); - } - - //move - inline vector& operator=(vector &&source) { - reset(); - pool = source.pool, poolsize = source.poolsize, objectsize = source.objectsize; - source.pool = nullptr, source.poolsize = 0, source.objectsize = 0; - return *this; - } - - vector(vector &&source) : pool(nullptr), poolsize(0), objectsize(0) { - operator=(std::move(source)); - } - - //construction - vector() : pool(nullptr), poolsize(0), objectsize(0) { - } - - vector(std::initializer_list list) : pool(nullptr), poolsize(0), objectsize(0) { - for(auto &data : list) append(data); - } - - ~vector() { - reset(); - } - }; - - //linear_vector - //memory: O(capacity * 2) - // - //linear_vector uses placement new + manual destructor calls to create a - //contiguous block of memory for all objects. accessing individual elements - //is fast, though resizing the array incurs significant overhead. - //reserve() overhead is reduced from quadratic time to amortized constant time - //by resizing twice as much as requested. - // - //if objects hold memory address references to themselves (introspection), a - //valid copy constructor will be needed to keep pointers valid. - - #define NALL_DEPRECATED - #if defined(NALL_DEPRECATED) - template struct linear_vector { - protected: - T *pool; - unsigned poolsize, objectsize; - - public: - unsigned size() const { return objectsize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) { - for(unsigned i = 0; i < objectsize; i++) pool[i].~T(); - free(pool); - } - pool = nullptr; - poolsize = 0; - objectsize = 0; - } - - void reserve(unsigned newsize) { - newsize = bit::round(newsize); //round to nearest power of two (for amortized growth) - - T *poolcopy = (T*)calloc(newsize, sizeof(T)); - for(unsigned i = 0; i < min(objectsize, newsize); i++) new(poolcopy + i) T(pool[i]); - for(unsigned i = 0; i < objectsize; i++) pool[i].~T(); - free(pool); - pool = poolcopy; - poolsize = newsize; - objectsize = min(objectsize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(newsize); - - if(newsize < objectsize) { - //vector is shrinking; destroy excess objects - for(unsigned i = newsize; i < objectsize; i++) pool[i].~T(); - } else if(newsize > objectsize) { - //vector is expanding; allocate new objects - for(unsigned i = objectsize; i < newsize; i++) new(pool + i) T; - } - - objectsize = newsize; - } - - void append(const T data) { - if(objectsize + 1 > poolsize) reserve(objectsize + 1); - new(pool + objectsize++) T(data); - } - - template void insert(unsigned index, const U list) { - linear_vector merged; - for(unsigned i = 0; i < index; i++) merged.append(pool[i]); - for(auto &item : list) merged.append(item); - for(unsigned i = index; i < objectsize; i++) merged.append(pool[i]); - operator=(merged); - } - - void insert(unsigned index, const T item) { - insert(index, linear_vector{ item }); - } - - void remove(unsigned index, unsigned count = 1) { - for(unsigned i = index; count + i < objectsize; i++) { - pool[i] = pool[count + i]; - } - if(count + index >= objectsize) resize(index); //every element >= index was removed - else resize(objectsize - count); - } - - linear_vector() : pool(nullptr), poolsize(0), objectsize(0) { - } - - linear_vector(std::initializer_list list) : pool(nullptr), poolsize(0), objectsize(0) { - for(const T *p = list.begin(); p != list.end(); ++p) append(*p); - } - - ~linear_vector() { - reset(); - } - - //copy - inline linear_vector& operator=(const linear_vector &source) { - reset(); - reserve(source.capacity()); - resize(source.size()); - for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i); - return *this; - } - - linear_vector(const linear_vector &source) : pool(nullptr), poolsize(0), objectsize(0) { - operator=(source); - } - - //move - inline linear_vector& operator=(linear_vector &&source) { - reset(); - pool = source.pool; - poolsize = source.poolsize; - objectsize = source.objectsize; - source.pool = nullptr; - source.reset(); - return *this; - } - - linear_vector(linear_vector &&source) : pool(nullptr), poolsize(0), objectsize(0) { - operator=(std::move(source)); - } - - //index - inline T& operator[](unsigned index) { - if(index >= objectsize) resize(index + 1); - return pool[index]; - } - - inline const T& operator[](unsigned index) const { - if(index >= objectsize) throw "vector[] out of bounds"; - return pool[index]; - } - - //iteration - T* begin() { return &pool[0]; } - T* end() { return &pool[objectsize]; } - const T* begin() const { return &pool[0]; } - const T* end() const { return &pool[objectsize]; } - }; - - //pointer_vector - //memory: O(1) - // - //pointer_vector keeps an array of pointers to each vector object. this adds - //significant overhead to individual accesses, but allows for optimal memory - //utilization. - // - //by guaranteeing that the base memory address of each objects never changes, - //this avoids the need for an object to have a valid copy constructor. - - template struct pointer_vector { - protected: - T **pool; - unsigned poolsize, objectsize; - - public: - unsigned size() const { return objectsize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) { - for(unsigned i = 0; i < objectsize; i++) { if(pool[i]) delete pool[i]; } - free(pool); - } - pool = nullptr; - poolsize = 0; - objectsize = 0; - } - - void reserve(unsigned newsize) { - newsize = bit::round(newsize); //round to nearest power of two (for amortized growth) - - for(unsigned i = newsize; i < objectsize; i++) { - if(pool[i]) { delete pool[i]; pool[i] = 0; } - } - - pool = (T**)realloc(pool, newsize * sizeof(T*)); - for(unsigned i = poolsize; i < newsize; i++) pool[i] = 0; - poolsize = newsize; - objectsize = min(objectsize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(newsize); - - for(unsigned i = newsize; i < objectsize; i++) { - if(pool[i]) { delete pool[i]; pool[i] = 0; } - } - - objectsize = newsize; - } - - void append(const T data) { - if(objectsize + 1 > poolsize) reserve(objectsize + 1); - pool[objectsize++] = new T(data); - } - - template void insert(unsigned index, const U list) { - pointer_vector merged; - for(unsigned i = 0; i < index; i++) merged.append(*pool[i]); - for(auto &item : list) merged.append(item); - for(unsigned i = index; i < objectsize; i++) merged.append(*pool[i]); - operator=(merged); - } - - void insert(unsigned index, const T item) { - insert(index, pointer_vector{ item }); - } - - void remove(unsigned index, unsigned count = 1) { - for(unsigned i = index; count + i < objectsize; i++) { - *pool[i] = *pool[count + i]; - } - if(count + index >= objectsize) resize(index); //every element >= index was removed - else resize(objectsize - count); - } - - pointer_vector() : pool(nullptr), poolsize(0), objectsize(0) { - } - - pointer_vector(std::initializer_list list) : pool(nullptr), poolsize(0), objectsize(0) { - for(const T *p = list.begin(); p != list.end(); ++p) append(*p); - } - - ~pointer_vector() { - reset(); - } - - //copy - inline pointer_vector& operator=(const pointer_vector &source) { - reset(); - reserve(source.capacity()); - resize(source.size()); - for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i); - return *this; - } - - pointer_vector(const pointer_vector &source) : pool(nullptr), poolsize(0), objectsize(0) { - operator=(source); - } - - //move - inline pointer_vector& operator=(pointer_vector &&source) { - reset(); - pool = source.pool; - poolsize = source.poolsize; - objectsize = source.objectsize; - source.pool = nullptr; - source.reset(); - return *this; - } - - pointer_vector(pointer_vector &&source) : pool(nullptr), poolsize(0), objectsize(0) { - operator=(std::move(source)); - } - - //index - inline T& operator[](unsigned index) { - if(index >= objectsize) resize(index + 1); - if(!pool[index]) pool[index] = new T; - return *pool[index]; - } - - inline const T& operator[](unsigned index) const { - if(index >= objectsize || !pool[index]) throw "vector[] out of bounds"; - return *pool[index]; - } - - //iteration - struct iterator { - bool operator!=(const iterator &source) const { return index != source.index; } - T& operator*() { return vector.operator[](index); } - iterator& operator++() { index++; return *this; } - iterator(const pointer_vector &vector, unsigned index) : vector(vector), index(index) {} - private: - const pointer_vector &vector; - unsigned index; - }; - - iterator begin() { return iterator(*this, 0); } - iterator end() { return iterator(*this, objectsize); } - const iterator begin() const { return iterator(*this, 0); } - const iterator end() const { return iterator(*this, objectsize); } - }; - #endif -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/windows/detour.hpp b/waterbox/libsnes/bsnes/nall/windows/detour.hpp deleted file mode 100644 index e270f31802..0000000000 --- a/waterbox/libsnes/bsnes/nall/windows/detour.hpp +++ /dev/null @@ -1,192 +0,0 @@ -#ifndef NALL_WINDOWS_DETOUR_HPP -#define NALL_WINDOWS_DETOUR_HPP - -#include -#include -#include -#include -#include - -namespace nall { - -#define Copy 0 -#define RelNear 1 - -struct detour { - static bool insert(const string &moduleName, const string &functionName, void *&source, void *target); - static bool remove(const string &moduleName, const string &functionName, void *&source); - -protected: - static unsigned length(const uint8_t *function); - static unsigned mirror(uint8_t *target, const uint8_t *source); - - struct opcode { - uint16_t prefix; - unsigned length; - unsigned mode; - uint16_t modify; - }; - static opcode opcodes[]; -}; - -//TODO: -//* fs:, gs: should force another opcode copy -//* conditional branches within +5-byte range should fail -detour::opcode detour::opcodes[] = { - { 0x50, 1 }, //push eax - { 0x51, 1 }, //push ecx - { 0x52, 1 }, //push edx - { 0x53, 1 }, //push ebx - { 0x54, 1 }, //push esp - { 0x55, 1 }, //push ebp - { 0x56, 1 }, //push esi - { 0x57, 1 }, //push edi - { 0x58, 1 }, //pop eax - { 0x59, 1 }, //pop ecx - { 0x5a, 1 }, //pop edx - { 0x5b, 1 }, //pop ebx - { 0x5c, 1 }, //pop esp - { 0x5d, 1 }, //pop ebp - { 0x5e, 1 }, //pop esi - { 0x5f, 1 }, //pop edi - { 0x64, 1 }, //fs: - { 0x65, 1 }, //gs: - { 0x68, 5 }, //push dword - { 0x6a, 2 }, //push byte - { 0x74, 2, RelNear, 0x0f84 }, //je near -> je far - { 0x75, 2, RelNear, 0x0f85 }, //jne near -> jne far - { 0x89, 2 }, //mov reg,reg - { 0x8b, 2 }, //mov reg,reg - { 0x90, 1 }, //nop - { 0xa1, 5 }, //mov eax,[dword] - { 0xeb, 2, RelNear, 0xe9 }, //jmp near -> jmp far -}; - -bool detour::insert(const string &moduleName, const string &functionName, void *&source, void *target) { - HMODULE module = GetModuleHandleW(utf16_t(moduleName)); - if(!module) return false; - - uint8_t *sourceData = (uint8_t*)GetProcAddress(module, functionName); - if(!sourceData) return false; - - unsigned sourceLength = detour::length(sourceData); - if(sourceLength < 5) { - //unable to clone enough bytes to insert hook - #if 1 - string output = { "detour::insert(", moduleName, "::", functionName, ") failed: " }; - for(unsigned n = 0; n < 16; n++) output.append(hex<2>(sourceData[n]), " "); - output.rtrim<1>(" "); - MessageBoxA(0, output, "nall::detour", MB_OK); - #endif - return false; - } - - uint8_t *mirrorData = new uint8_t[512](); - detour::mirror(mirrorData, sourceData); - - DWORD privileges; - VirtualProtect((void*)mirrorData, 512, PAGE_EXECUTE_READWRITE, &privileges); - VirtualProtect((void*)sourceData, 256, PAGE_EXECUTE_READWRITE, &privileges); - uintmax_t address = (uintmax_t)target - ((uintmax_t)sourceData + 5); - sourceData[0] = 0xe9; //jmp target - sourceData[1] = address >> 0; - sourceData[2] = address >> 8; - sourceData[3] = address >> 16; - sourceData[4] = address >> 24; - VirtualProtect((void*)sourceData, 256, privileges, &privileges); - - source = (void*)mirrorData; - return true; -} - -bool detour::remove(const string &moduleName, const string &functionName, void *&source) { - HMODULE module = GetModuleHandleW(utf16_t(moduleName)); - if(!module) return false; - - uint8_t *sourceData = (uint8_t*)GetProcAddress(module, functionName); - if(!sourceData) return false; - - uint8_t *mirrorData = (uint8_t*)source; - if(mirrorData == sourceData) return false; //hook was never installed - - unsigned length = detour::length(256 + mirrorData); - if(length < 5) return false; - - DWORD privileges; - VirtualProtect((void*)sourceData, 256, PAGE_EXECUTE_READWRITE, &privileges); - for(unsigned n = 0; n < length; n++) sourceData[n] = mirrorData[256 + n]; - VirtualProtect((void*)sourceData, 256, privileges, &privileges); - - source = (void*)sourceData; - delete[] mirrorData; - return true; -} - -unsigned detour::length(const uint8_t *function) { - unsigned length = 0; - while(length < 5) { - detour::opcode *opcode = 0; - foreach(op, detour::opcodes) { - if(function[length] == op.prefix) { - opcode = &op; - break; - } - } - if(opcode == 0) break; - length += opcode->length; - } - return length; -} - -unsigned detour::mirror(uint8_t *target, const uint8_t *source) { - const uint8_t *entryPoint = source; - for(unsigned n = 0; n < 256; n++) target[256 + n] = source[n]; - - unsigned size = detour::length(source); - while(size) { - detour::opcode *opcode = 0; - foreach(op, detour::opcodes) { - if(*source == op.prefix) { - opcode = &op; - break; - } - } - - switch(opcode->mode) { - case Copy: - for(unsigned n = 0; n < opcode->length; n++) *target++ = *source++; - break; - case RelNear: { - source++; - uintmax_t sourceAddress = (uintmax_t)source + 1 + (int8_t)*source; - *target++ = opcode->modify; - if(opcode->modify >> 8) *target++ = opcode->modify >> 8; - uintmax_t targetAddress = (uintmax_t)target + 4; - uintmax_t address = sourceAddress - targetAddress; - *target++ = address >> 0; - *target++ = address >> 8; - *target++ = address >> 16; - *target++ = address >> 24; - source += 2; - } break; - } - - size -= opcode->length; - } - - uintmax_t address = (entryPoint + detour::length(entryPoint)) - (target + 5); - *target++ = 0xe9; //jmp entryPoint - *target++ = address >> 0; - *target++ = address >> 8; - *target++ = address >> 16; - *target++ = address >> 24; - - return source - entryPoint; -} - -#undef Implied -#undef RelNear - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/windows/launcher.hpp b/waterbox/libsnes/bsnes/nall/windows/launcher.hpp deleted file mode 100644 index 914683ec39..0000000000 --- a/waterbox/libsnes/bsnes/nall/windows/launcher.hpp +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef NALL_WINDOWS_LAUNCHER_HPP -#define NALL_WINDOWS_LAUNCHER_HPP - -namespace nall { - -//launch a new process and inject specified DLL into it - -bool launch(const char *applicationName, const char *libraryName, uint32_t entryPoint) { - //if a launcher does not send at least one message, a wait cursor will appear - PostThreadMessage(GetCurrentThreadId(), WM_USER, 0, 0); - MSG msg; - GetMessage(&msg, 0, 0, 0); - - STARTUPINFOW si; - PROCESS_INFORMATION pi; - - memset(&si, 0, sizeof(STARTUPINFOW)); - BOOL result = CreateProcessW( - utf16_t(applicationName), GetCommandLineW(), NULL, NULL, TRUE, - DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS, //do not break if application creates its own processes - NULL, NULL, &si, &pi - ); - if(result == false) return false; - - uint8_t entryData[1024], entryHook[1024] = { - 0x68, 0x00, 0x00, 0x00, 0x00, //push libraryName - 0xb8, 0x00, 0x00, 0x00, 0x00, //mov eax,LoadLibraryW - 0xff, 0xd0, //call eax - 0xcd, 0x03, //int 3 - }; - - entryHook[1] = (uint8_t)((entryPoint + 14) >> 0); - entryHook[2] = (uint8_t)((entryPoint + 14) >> 8); - entryHook[3] = (uint8_t)((entryPoint + 14) >> 16); - entryHook[4] = (uint8_t)((entryPoint + 14) >> 24); - - uint32_t pLoadLibraryW = (uint32_t)GetProcAddress(GetModuleHandleW(L"kernel32"), "LoadLibraryW"); - entryHook[6] = pLoadLibraryW >> 0; - entryHook[7] = pLoadLibraryW >> 8; - entryHook[8] = pLoadLibraryW >> 16; - entryHook[9] = pLoadLibraryW >> 24; - - utf16_t buffer = utf16_t(libraryName); - memcpy(entryHook + 14, buffer, 2 * wcslen(buffer) + 2); - - while(true) { - DEBUG_EVENT event; - WaitForDebugEvent(&event, INFINITE); - - if(event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break; - - if(event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) { - if(event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { - if(event.u.Exception.ExceptionRecord.ExceptionAddress == (void*)(entryPoint + 14 - 1)) { - HANDLE hProcess = OpenProcess(0, FALSE, event.dwProcessId); - HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, event.dwThreadId); - - CONTEXT context; - context.ContextFlags = CONTEXT_FULL; - GetThreadContext(hThread, &context); - - WriteProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryData, sizeof entryData, NULL); - context.Eip = entryPoint; - SetThreadContext(hThread, &context); - - CloseHandle(hThread); - CloseHandle(hProcess); - } - - ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); - continue; - } - - ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_EXCEPTION_NOT_HANDLED); - continue; - } - - if(event.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) { - ReadProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryData, sizeof entryData, NULL); - WriteProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryHook, sizeof entryHook, NULL); - - ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); - continue; - } - - ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); - } - - return true; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/nall/windows/utf8.hpp b/waterbox/libsnes/bsnes/nall/windows/utf8.hpp deleted file mode 100644 index f5597b857d..0000000000 --- a/waterbox/libsnes/bsnes/nall/windows/utf8.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef NALL_UTF8_HPP -#define NALL_UTF8_HPP - -//UTF-8 <> UTF-16 conversion -//used only for Win32; Linux, etc use UTF-8 internally - -#if defined(_WIN32) - -#undef UNICODE -#undef _WIN32_WINNT -#undef NOMINMAX -#define UNICODE -#define _WIN32_WINNT 0x0501 -#define NOMINMAX -#include -#undef interface - -namespace nall { - //UTF-8 to UTF-16 - class utf16_t { - public: - operator wchar_t*() { - return buffer; - } - - operator const wchar_t*() const { - return buffer; - } - - utf16_t(const char *s = "") { - if(!s) s = ""; - unsigned length = MultiByteToWideChar(CP_UTF8, 0, s, -1, 0, 0); - buffer = new wchar_t[length + 1](); - MultiByteToWideChar(CP_UTF8, 0, s, -1, buffer, length); - } - - ~utf16_t() { - delete[] buffer; - } - - private: - wchar_t *buffer; - }; - - //UTF-16 to UTF-8 - class utf8_t { - public: - operator char*() { - return buffer; - } - - operator const char*() const { - return buffer; - } - - utf8_t(const wchar_t *s = L"") { - if(!s) s = L""; - unsigned length = WideCharToMultiByte(CP_UTF8, 0, s, -1, 0, 0, (const char*)0, (BOOL*)0); - buffer = new char[length + 1](); - WideCharToMultiByte(CP_UTF8, 0, s, -1, buffer, length, (const char*)0, (BOOL*)0); - } - - ~utf8_t() { - delete[] buffer; - } - - utf8_t(const utf8_t&) = delete; - utf8_t& operator=(const utf8_t&) = delete; - - private: - char *buffer; - }; - - inline void utf8_args(int &argc, char **&argv) { - wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc); - argv = new char*[argc]; - for(unsigned i = 0; i < argc; i++) { - argv[i] = new char[_MAX_PATH]; - strcpy(argv[i], nall::utf8_t(wargv[i])); - } - } -} - -#endif //if defined(_WIN32) - -#endif diff --git a/waterbox/libsnes/bsnes/nall/xorg/guard.hpp b/waterbox/libsnes/bsnes/nall/xorg/guard.hpp deleted file mode 100644 index a128268344..0000000000 --- a/waterbox/libsnes/bsnes/nall/xorg/guard.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef NALL_XORG_GUARD_HPP -#define NALL_XORG_GUARD_HPP - -#define None -#undef XlibNone -#define XlibNone 0L -#define Button1 XlibButton1 -#define Button2 XlibButton2 -#define Button3 XlibButton3 -#define Button4 XlibButton4 -#define Button5 XlibButton5 -#define Display XlibDisplay -#define Screen XlibScreen -#define Window XlibWindow - -#else -#undef NALL_XORG_GUARD_HPP - -#undef None -#undef Button1 -#undef Button2 -#undef Button3 -#undef Button4 -#undef Button5 -#undef Display -#undef Screen -#undef Window - -#endif diff --git a/waterbox/libsnes/bsnes/nall/xorg/xorg.hpp b/waterbox/libsnes/bsnes/nall/xorg/xorg.hpp deleted file mode 100644 index bcf48b4638..0000000000 --- a/waterbox/libsnes/bsnes/nall/xorg/xorg.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef NALL_XORG_XORG_HPP -#define NALL_XORG_XORG_HPP - -#include -#include -#include -#include -#include -#include -#include - -#endif diff --git a/waterbox/libsnes/bsnes/nall/zip.hpp b/waterbox/libsnes/bsnes/nall/zip.hpp deleted file mode 100644 index a224afe4db..0000000000 --- a/waterbox/libsnes/bsnes/nall/zip.hpp +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef NALL_UNZIP_HPP -#define NALL_UNZIP_HPP - -#include -#include -#include -#include - -namespace nall { - -struct zip { - struct File { - string name; - const uint8_t *data; - unsigned size; - unsigned csize; - unsigned cmode; //0 = uncompressed, 8 = deflate - unsigned crc32; - }; - - inline bool open(const string &filename) { - close(); - if(fm.open(filename, filemap::mode::read) == false) return false; - if(open(fm.data(), fm.size()) == false) { - fm.close(); - return false; - } - return true; - } - - inline bool open(const uint8_t *data, unsigned size) { - if(size < 22) return false; - - filedata = data; - filesize = size; - - file.reset(); - - const uint8_t *footer = data + size - 22; - const uint8_t *directory = data + read(footer + 16, 4); - - while(true) { - unsigned signature = read(directory + 0, 4); - if(signature != 0x02014b50) break; - - File file; - file.cmode = read(directory + 10, 2); - file.crc32 = read(directory + 16, 4); - file.csize = read(directory + 20, 4); - file.size = read(directory + 24, 4); - - unsigned namelength = read(directory + 28, 2); - unsigned extralength = read(directory + 30, 2); - unsigned commentlength = read(directory + 32, 2); - - char *filename = new char[namelength + 1]; - memcpy(filename, directory + 46, namelength); - filename[namelength] = 0; - file.name = filename; - delete[] filename; - - unsigned offset = read(directory + 42, 4); - unsigned offsetNL = read(data + offset + 26, 2); - unsigned offsetEL = read(data + offset + 28, 2); - file.data = data + offset + 30 + offsetNL + offsetEL; - - directory += 46 + namelength + extralength + commentlength; - - this->file.append(file); - } - - return true; - } - - inline bool extract(File &file, uint8_t *&data, unsigned &size) { - data = 0, size = 0; - - if(file.cmode == 0) { - size = file.size; - data = new uint8_t[size]; - memcpy(data, file.data, size); - return true; - } - - if(file.cmode == 8) { - size = file.size; - data = new uint8_t[size]; - if(inflate(data, size, file.data, file.csize) == false) { - delete[] data; - size = 0; - return false; - } - return true; - } - - return false; - } - - inline void close() { - if(fm.open()) fm.close(); - } - - ~zip() { - close(); - } - -protected: - filemap fm; - const uint8_t *filedata; - unsigned filesize; - - unsigned read(const uint8_t *data, unsigned size) { - unsigned result = 0, shift = 0; - while(size--) { result |= *data++ << shift; shift += 8; } - return result; - } - -public: - vector file; -}; - -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/cpu/cpu.cpp b/waterbox/libsnes/bsnes/snes/alt/cpu/cpu.cpp deleted file mode 100644 index 585de807ee..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/cpu/cpu.cpp +++ /dev/null @@ -1,189 +0,0 @@ -#include - -#define CPU_CPP -namespace SNES { - -CPU cpu; - -#include "dma.cpp" -#include "memory.cpp" -#include "mmio.cpp" -#include "timing.cpp" - -void CPU::step(unsigned clocks) { - smp.clock -= clocks * (uint64)smp.frequency; - ppu.clock -= clocks; - for(unsigned i = 0; i < coprocessors.size(); i++) { - Processor &chip = *coprocessors[i]; - chip.clock -= clocks * (uint64)chip.frequency; - } - input.port1->clock -= clocks * (uint64)input.port1->frequency; - input.port2->clock -= clocks * (uint64)input.port2->frequency; - synchronize_controllers(); -} - -void CPU::synchronize_smp() { - if(SMP::Threaded == true) { - if(smp.clock < 0) co_switch(smp.thread); - } else { - while(smp.clock < 0) smp.enter(); - } -} - -void CPU::synchronize_ppu() { - if(PPU::Threaded == true) { - if(ppu.clock < 0) co_switch(ppu.thread); - } else { - while(ppu.clock < 0) ppu.enter(); - } -} - -void CPU::synchronize_coprocessors() { - for(unsigned i = 0; i < coprocessors.size(); i++) { - Processor &chip = *coprocessors[i]; - if(chip.clock < 0) co_switch(chip.thread); - } -} - -void CPU::synchronize_controllers() { - if(input.port1->clock < 0) co_switch(input.port1->thread); - if(input.port2->clock < 0) co_switch(input.port2->thread); -} - -void CPU::Enter() { cpu.enter(); } - -void CPU::enter() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::CPU) { - scheduler.sync = Scheduler::SynchronizeMode::All; - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - if(status.nmi_pending) { - status.nmi_pending = false; - regs.vector = (regs.e == false ? 0xffea : 0xfffa); - op_irq(); - } - - if(status.irq_pending) { - status.irq_pending = false; - regs.vector = (regs.e == false ? 0xffee : 0xfffe); - op_irq(); - } - - op_step(); - } -} - -alwaysinline void CPU::op_step() { - (this->*opcode_table[op_readpcfirst()])(); -} - -void CPU::enable() { - function read = { &CPU::mmio_read, (CPU*)&cpu }; - function write = { &CPU::mmio_write, (CPU*)&cpu }; - - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, read, write); - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, read, write); - - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, read, write); - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, read, write); - - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, read, write); - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, read, write); - - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, read, write); - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, read, write); - - read = [](unsigned addr) { cdlInfo.set(eCDLog_AddrType_WRAM, addr); return cpu.wram[addr]; }; - write = [](unsigned addr, uint8 data) { cpu.wram[addr] = data; }; - - bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, read, write, 0x000000, 0x002000); - bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, read, write, 0x000000, 0x002000); - bus.map(Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff, read, write); -} - -void CPU::power() { - regs.a = 0x0000; - regs.x = 0x0000; - regs.y = 0x0000; - regs.s = 0x01ff; - - reset(); -} - -void CPU::reset() { - create(Enter, system.cpu_frequency(), 16384); - coprocessors.reset(); - PPUcounter::reset(); - - regs.pc = 0x000000; - regs.x.h = 0x00; - regs.y.h = 0x00; - regs.s.h = 0x01; - regs.d = 0x0000; - regs.db = 0x00; - regs.p = 0x34; - regs.e = 1; - regs.mdr = 0x00; - regs.wai = false; - update_table(); - - regs.pc.l = bus.read(0xfffc); - regs.pc.h = bus.read(0xfffd); - regs.pc.b = 0x00; - - status.nmi_valid = false; - status.nmi_line = false; - status.nmi_transition = false; - status.nmi_pending = false; - - status.irq_valid = false; - status.irq_line = false; - status.irq_transition = false; - status.irq_pending = false; - - status.irq_lock = false; - status.hdma_pending = false; - - status.wram_addr = 0x000000; - - status.joypad_strobe_latch = 0; - - status.nmi_enabled = false; - status.virq_enabled = false; - status.hirq_enabled = false; - status.auto_joypad_poll_enabled = false; - - status.pio = 0xff; - - status.htime = 0x0000; - status.vtime = 0x0000; - - status.rom_speed = 8; - - status.joy1l = status.joy1h = 0x00; - status.joy2l = status.joy2h = 0x00; - status.joy3l = status.joy3h = 0x00; - status.joy4l = status.joy4h = 0x00; - - dma_reset(); -} - -CPU::CPU() - : queue(512, { &CPU::queue_event, this }) - , wram(nullptr) -{ - PPUcounter::scanline = { &CPU::scanline, this }; -} - -CPU::~CPU() { - interface()->freeSharedMemory(wram); -} - -void CPU::initialize() -{ - wram = (uint8*)interface()->allocSharedMemory("WRAM", 128 * 1024); -} - -} diff --git a/waterbox/libsnes/bsnes/snes/alt/cpu/cpu.hpp b/waterbox/libsnes/bsnes/snes/alt/cpu/cpu.hpp deleted file mode 100644 index 890765ee7b..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/cpu/cpu.hpp +++ /dev/null @@ -1,160 +0,0 @@ -class CPU : public Processor, public CPUcore, public PPUcounter { -public: - uint8* wram; //[128 * 1024]; - - enum : bool { Threaded = true }; - array coprocessors; - alwaysinline void step(unsigned clocks); - alwaysinline void synchronize_smp(); - void synchronize_ppu(); - void synchronize_coprocessors(); - void synchronize_controllers(); - - uint8 pio(); - bool joylatch(); - bool interrupt_pending(); - uint8 port_read(uint8 port); - void port_write(uint8 port, uint8 data); - uint8 mmio_read(unsigned addr); - void mmio_write(unsigned addr, uint8 data); - - void op_io(); - uint8 op_read(unsigned addr, eCDLog_Flags = eCDLog_Flags_CPUData); - void op_write(unsigned addr, uint8 data); - - void enter(); - void enable(); - void power(); - void reset(); - - CPU(); - ~CPU(); - void initialize(); - -private: - //cpu - static void Enter(); - void op_step(); - - //timing - struct QueueEvent { - enum : unsigned { - DramRefresh, - HdmaRun, - }; - }; - nall::priority_queue queue; - void queue_event(unsigned id); - void last_cycle(); - void add_clocks(unsigned clocks); - void scanline(); - void run_auto_joypad_poll(); - - //memory - unsigned speed(unsigned addr) const; - - //dma - bool dma_transfer_valid(uint8 bbus, unsigned abus); - bool dma_addr_valid(unsigned abus); - uint8 dma_read(unsigned abus); - void dma_write(bool valid, unsigned addr, uint8 data); - void dma_transfer(bool direction, uint8 bbus, unsigned abus); - uint8 dma_bbus(unsigned i, unsigned index); - unsigned dma_addr(unsigned i); - unsigned hdma_addr(unsigned i); - unsigned hdma_iaddr(unsigned i); - void dma_run(); - bool hdma_active_after(unsigned i); - void hdma_update(unsigned i); - void hdma_run(); - void hdma_init(); - void dma_reset(); - - //registers - uint8 port_data[4]; - - struct Channel { - bool dma_enabled; - bool hdma_enabled; - - bool direction; - bool indirect; - bool unused; - bool reverse_transfer; - bool fixed_transfer; - uint8 transfer_mode; - - uint8 dest_addr; - uint16 source_addr; - uint8 source_bank; - - union { - uint16 transfer_size; - uint16 indirect_addr; - }; - - uint8 indirect_bank; - uint16 hdma_addr; - uint8 line_counter; - uint8 unknown; - - bool hdma_completed; - bool hdma_do_transfer; - } channel[8]; - - struct Status { - bool nmi_valid; - bool nmi_line; - bool nmi_transition; - bool nmi_pending; - - bool irq_valid; - bool irq_line; - bool irq_transition; - bool irq_pending; - - bool irq_lock; - bool hdma_pending; - - unsigned wram_addr; - - bool joypad_strobe_latch; - - bool nmi_enabled; - bool virq_enabled; - bool hirq_enabled; - bool auto_joypad_poll_enabled; - - uint8 pio; - - uint8 wrmpya; - uint8 wrmpyb; - uint16 wrdiva; - uint8 wrdivb; - - uint16 htime; - uint16 vtime; - - unsigned rom_speed; - - uint16 rddiv; - uint16 rdmpy; - - uint8 joy1l, joy1h; - uint8 joy2l, joy2h; - uint8 joy3l, joy3h; - uint8 joy4l, joy4h; - } status; - -public: - struct Debugger { - hook op_exec; - hook op_read; - hook op_write; - hook op_nmi; - hook op_irq; - } debugger; - -}; - -extern CPU cpu; diff --git a/waterbox/libsnes/bsnes/snes/alt/cpu/dma.cpp b/waterbox/libsnes/bsnes/snes/alt/cpu/dma.cpp deleted file mode 100644 index bdf8c9a790..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/cpu/dma.cpp +++ /dev/null @@ -1,205 +0,0 @@ -#ifdef CPU_CPP - -bool CPU::dma_transfer_valid(uint8 bbus, unsigned abus) { - //transfers from WRAM to WRAM are invalid; chip only has one address bus - if(bbus == 0x80 && ((abus & 0xfe0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) return false; - return true; -} - -bool CPU::dma_addr_valid(unsigned abus) { - //A-bus access to B-bus or S-CPU registers are invalid - if((abus & 0x40ff00) == 0x2100) return false; //$[00-3f|80-bf]:[2100-21ff] - if((abus & 0x40fe00) == 0x4000) return false; //$[00-3f|80-bf]:[4000-41ff] - if((abus & 0x40ffe0) == 0x4200) return false; //$[00-3f|80-bf]:[4200-421f] - if((abus & 0x40ff80) == 0x4300) return false; //$[00-3f|80-bf]:[4300-437f] - return true; -} - -uint8 CPU::dma_read(unsigned abus) { - if(dma_addr_valid(abus) == false) return 0x00; - cdlInfo.currFlags = eCDLog_Flags_DMAData; - return bus.read(abus); -} - -void CPU::dma_write(bool valid, unsigned addr, uint8 data) { - if(valid) bus.write(addr, data); -} - -void CPU::dma_transfer(bool direction, uint8 bbus, unsigned abus) { - if(direction == 0) { - uint8 data = dma_read(abus); - add_clocks(8); - dma_write(dma_transfer_valid(bbus, abus), 0x2100 | bbus, data); - } else { - uint8 data = dma_transfer_valid(bbus, abus) ? bus.read(0x2100 | bbus) : 0x00; - add_clocks(8); - dma_write(dma_addr_valid(abus), abus, data); - } -} - -uint8 CPU::dma_bbus(unsigned i, unsigned index) { - switch(channel[i].transfer_mode) { default: - case 0: return (channel[i].dest_addr); //0 - case 1: return (channel[i].dest_addr + (index & 1)); //0,1 - case 2: return (channel[i].dest_addr); //0,0 - case 3: return (channel[i].dest_addr + ((index >> 1) & 1)); //0,0,1,1 - case 4: return (channel[i].dest_addr + (index & 3)); //0,1,2,3 - case 5: return (channel[i].dest_addr + (index & 1)); //0,1,0,1 - case 6: return (channel[i].dest_addr); //0,0 [2] - case 7: return (channel[i].dest_addr + ((index >> 1) & 1)); //0,0,1,1 [3] - } -} - -unsigned CPU::dma_addr(unsigned i) { - unsigned result = (channel[i].source_bank << 16) | (channel[i].source_addr); - - if(channel[i].fixed_transfer == false) { - if(channel[i].reverse_transfer == false) { - channel[i].source_addr++; - } else { - channel[i].source_addr--; - } - } - - return result; -} - -unsigned CPU::hdma_addr(unsigned i) { - return (channel[i].source_bank << 16) | (channel[i].hdma_addr++); -} - -unsigned CPU::hdma_iaddr(unsigned i) { - return (channel[i].indirect_bank << 16) | (channel[i].indirect_addr++); -} - -void CPU::dma_run() { - add_clocks(16); - - for(unsigned i = 0; i < 8; i++) { - if(channel[i].dma_enabled == false) continue; - add_clocks(8); - - unsigned index = 0; - do { - dma_transfer(channel[i].direction, dma_bbus(i, index++), dma_addr(i)); - } while(channel[i].dma_enabled && --channel[i].transfer_size); - - channel[i].dma_enabled = false; - } - - status.irq_lock = true; -} - -bool CPU::hdma_active_after(unsigned i) { - for(unsigned n = i + 1; i < 8; i++) { - if(channel[i].hdma_enabled && !channel[i].hdma_completed) return true; - } - return false; -} - -void CPU::hdma_update(unsigned i) { - if((channel[i].line_counter & 0x7f) == 0) { - channel[i].line_counter = dma_read(hdma_addr(i)); - channel[i].hdma_completed = (channel[i].line_counter == 0); - channel[i].hdma_do_transfer = !channel[i].hdma_completed; - add_clocks(8); - - if(channel[i].indirect) { - channel[i].indirect_addr = dma_read(hdma_addr(i)) << 8; - add_clocks(8); - - //emulating this glitch causes a slight slowdown; only enable if needed - //if(!channel[i].hdma_completed || hdma_active_after(i)) { - channel[i].indirect_addr >>= 8; - channel[i].indirect_addr |= dma_read(hdma_addr(i)) << 8; - add_clocks(8); - //} - } - } -} - -void CPU::hdma_run() { - unsigned channels = 0; - for(unsigned i = 0; i < 8; i++) { - if(channel[i].hdma_enabled) channels++; - } - if(channels == 0) return; - - add_clocks(16); - for(unsigned i = 0; i < 8; i++) { - if(channel[i].hdma_enabled == false || channel[i].hdma_completed == true) continue; - channel[i].dma_enabled = false; - - if(channel[i].hdma_do_transfer) { - static const unsigned transfer_length[] = { 1, 2, 2, 4, 4, 4, 2, 4 }; - unsigned length = transfer_length[channel[i].transfer_mode]; - for(unsigned index = 0; index < length; index++) { - unsigned addr = channel[i].indirect == false ? hdma_addr(i) : hdma_iaddr(i); - dma_transfer(channel[i].direction, dma_bbus(i, index), addr); - } - } - } - - for(unsigned i = 0; i < 8; i++) { - if(channel[i].hdma_enabled == false || channel[i].hdma_completed == true) continue; - - channel[i].line_counter--; - channel[i].hdma_do_transfer = channel[i].line_counter & 0x80; - hdma_update(i); - } - - status.irq_lock = true; -} - -void CPU::hdma_init() { - unsigned channels = 0; - for(unsigned i = 0; i < 8; i++) { - channel[i].hdma_completed = false; - channel[i].hdma_do_transfer = false; - if(channel[i].hdma_enabled) channels++; - } - if(channels == 0) return; - - add_clocks(16); - for(unsigned i = 0; i < 8; i++) { - if(!channel[i].hdma_enabled) continue; - channel[i].dma_enabled = false; - - channel[i].hdma_addr = channel[i].source_addr; - channel[i].line_counter = 0; - hdma_update(i); - } - - status.irq_lock = true; -} - -void CPU::dma_reset() { - for(unsigned i = 0; i < 8; i++) { - channel[i].dma_enabled = false; - channel[i].hdma_enabled = false; - - channel[i].direction = 1; - channel[i].indirect = true; - channel[i].unused = true; - channel[i].reverse_transfer = true; - channel[i].fixed_transfer = true; - channel[i].transfer_mode = 0x07; - - channel[i].dest_addr = 0xff; - channel[i].source_addr = 0xffff; - channel[i].source_bank = 0xff; - - channel[i].transfer_size = 0xffff; - channel[i].indirect_addr = 0xffff; - - channel[i].indirect_bank = 0xff; - channel[i].hdma_addr = 0xff; - channel[i].line_counter = 0xff; - channel[i].unknown = 0xff; - - channel[i].hdma_completed = false; - channel[i].hdma_do_transfer = false; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/cpu/memory.cpp b/waterbox/libsnes/bsnes/snes/alt/cpu/memory.cpp deleted file mode 100644 index 2e1a4a11a1..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/cpu/memory.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#ifdef CPU_CPP - -uint8 CPU::pio() { - return status.pio; -} - -bool CPU::joylatch() { - return status.joypad_strobe_latch; -} - -bool CPU::interrupt_pending() { - return false; -} - -uint8 CPU::port_read(uint8 port) { - return port_data[port & 3]; -} - -void CPU::port_write(uint8 port, uint8 data) { - port_data[port & 3] = data; -} - -void CPU::op_io() { - add_clocks(6); -} - -uint8 CPU::op_read(unsigned addr, eCDLog_Flags flags) { - cdlInfo.currFlags = flags; - regs.mdr = bus.read(addr); - add_clocks(speed(addr)); - return regs.mdr; -} - -void CPU::op_write(unsigned addr, uint8 data) { - add_clocks(speed(addr)); - bus.write(addr, regs.mdr = data); -} - -unsigned CPU::speed(unsigned addr) const { - if(addr & 0x408000) { - if(addr & 0x800000) return status.rom_speed; - return 8; - } - if((addr + 0x6000) & 0x4000) return 8; - if((addr - 0x4000) & 0x7e00) return 6; - return 12; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/cpu/mmio.cpp b/waterbox/libsnes/bsnes/snes/alt/cpu/mmio.cpp deleted file mode 100644 index 16f6e84353..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/cpu/mmio.cpp +++ /dev/null @@ -1,308 +0,0 @@ -#ifdef CPU_CPP - -uint8 CPU::mmio_read(unsigned addr) { - if((addr & 0xffc0) == 0x2140) { - synchronize_smp(); - return smp.port_read(addr & 3); - } - - switch(addr & 0xffff) { - case 0x2180: { - uint8 result = bus.read(0x7e0000 | status.wram_addr); - status.wram_addr = (status.wram_addr + 1) & 0x01ffff; - return result; - } - - case 0x4016: { - uint8 result = regs.mdr & 0xfc; - result |= input.port1->data() & 3; - return result; - } - - case 0x4017: { - uint8 result = (regs.mdr & 0xe0) | 0x1c; - result |= input.port2->data() & 3; - if (!status.auto_joypad_poll_enabled) interface()->inputNotify(0x4017); - return result; - } - - case 0x4210: { - uint8 result = (regs.mdr & 0x70); - result |= status.nmi_line << 7; - result |= 0x02; //CPU revision - status.nmi_line = false; - return result; - } - - case 0x4211: { - uint8 result = (regs.mdr & 0x7f); - result |= status.irq_line << 7; - status.irq_line = false; - return result; - } - - case 0x4212: { - uint8 result = (regs.mdr & 0x3e); - unsigned vbstart = ppu.overscan() == false ? 225 : 240; - - if(vcounter() >= vbstart && vcounter() <= vbstart + 2) result |= 0x01; - if(hcounter() <= 2 || hcounter() >= 1096) result |= 0x40; - if(vcounter() >= vbstart) result |= 0x80; - - return result; - } - - case 0x4213: - // interface()->inputNotify(0x4213); // if there are lag counter issues with super scope, uncomment this - return status.pio; - - case 0x4214: return status.rddiv >> 0; - case 0x4215: return status.rddiv >> 8; - case 0x4216: return status.rdmpy >> 0; - case 0x4217: return status.rdmpy >> 8; - - case 0x4218: interface()->inputNotify(0x4218); return status.joy1l; - case 0x4219: interface()->inputNotify(0x4219); return status.joy1h; - case 0x421a: interface()->inputNotify(0x421a); return status.joy2l; - case 0x421b: interface()->inputNotify(0x421b); return status.joy2h; - case 0x421c: interface()->inputNotify(0x421c); return status.joy3l; - case 0x421d: interface()->inputNotify(0x421d); return status.joy3h; - case 0x421e: interface()->inputNotify(0x421e); return status.joy4l; - case 0x421f: interface()->inputNotify(0x421f); return status.joy4h; - } - - if((addr & 0xff80) == 0x4300) { - unsigned i = (addr >> 4) & 7; - switch(addr & 0xff8f) { - case 0x4300: { - return (channel[i].direction << 7) - | (channel[i].indirect << 6) - | (channel[i].unused << 5) - | (channel[i].reverse_transfer << 4) - | (channel[i].fixed_transfer << 3) - | (channel[i].transfer_mode << 0); - } - - case 0x4301: return channel[i].dest_addr; - case 0x4302: return channel[i].source_addr >> 0; - case 0x4303: return channel[i].source_addr >> 8; - case 0x4304: return channel[i].source_bank; - case 0x4305: return channel[i].transfer_size >> 0; - case 0x4306: return channel[i].transfer_size >> 8; - case 0x4307: return channel[i].indirect_bank; - case 0x4308: return channel[i].hdma_addr >> 0; - case 0x4309: return channel[i].hdma_addr >> 8; - case 0x430a: return channel[i].line_counter; - case 0x430b: case 0x430f: return channel[i].unknown; - } - } - - return regs.mdr; -} - -void CPU::mmio_write(unsigned addr, uint8 data) { - if((addr & 0xffc0) == 0x2140) { - synchronize_smp(); - port_write(addr & 3, data); - return; - } - - switch(addr & 0xffff) { - case 0x2180: { - bus.write(0x7e0000 | status.wram_addr, data); - status.wram_addr = (status.wram_addr + 1) & 0x01ffff; - return; - } - - case 0x2181: { - status.wram_addr = (status.wram_addr & 0x01ff00) | (data << 0); - return; - } - - case 0x2182: { - status.wram_addr = (status.wram_addr & 0x0100ff) | (data << 8); - return; - } - - case 0x2183: { - status.wram_addr = (status.wram_addr & 0x00ffff) | ((data & 1) << 16); - return; - } - - case 0x4016: { - input.port1->latch(data & 1); - input.port2->latch(data & 1); - interface()->inputNotify(data & 1); // latch notify - if (!status.auto_joypad_poll_enabled) { interface()->inputNotify(0x4016); } - return; - } - - case 0x4200: { - bool nmi_enabled = status.nmi_enabled; - bool virq_enabled = status.virq_enabled; - bool hirq_enabled = status.hirq_enabled; - - status.nmi_enabled = data & 0x80; - status.virq_enabled = data & 0x20; - status.hirq_enabled = data & 0x10; - status.auto_joypad_poll_enabled = data & 0x01; - - if(!nmi_enabled && status.nmi_enabled && status.nmi_line) { - status.nmi_transition = true; - } - - if(status.virq_enabled && !status.hirq_enabled && status.irq_line) { - status.irq_transition = true; - } - - if(!status.virq_enabled && !status.hirq_enabled) { - status.irq_line = false; - status.irq_transition = false; - } - - status.irq_lock = true; - return; - } - - case 0x4201: { - if((status.pio & 0x80) && !(data & 0x80)) ppu.latch_counters(); - status.pio = data; - } - - case 0x4202: { - status.wrmpya = data; - return; - } - - case 0x4203: { - status.wrmpyb = data; - status.rdmpy = status.wrmpya * status.wrmpyb; - return; - } - - case 0x4204: { - status.wrdiva = (status.wrdiva & 0xff00) | (data << 0); - return; - } - - case 0x4205: { - status.wrdiva = (data << 8) | (status.wrdiva & 0x00ff); - return; - } - - case 0x4206: { - status.wrdivb = data; - status.rddiv = status.wrdivb ? status.wrdiva / status.wrdivb : 0xffff; - status.rdmpy = status.wrdivb ? status.wrdiva % status.wrdivb : status.wrdiva; - return; - } - - case 0x4207: { - status.htime = (status.htime & 0x0100) | (data << 0); - return; - } - - case 0x4208: { - status.htime = ((data & 1) << 8) | (status.htime & 0x00ff); - return; - } - - case 0x4209: { - status.vtime = (status.vtime & 0x0100) | (data << 0); - return; - } - - case 0x420a: { - status.vtime = ((data & 1) << 8) | (status.vtime & 0x00ff); - return; - } - - case 0x420b: { - for(unsigned i = 0; i < 8; i++) channel[i].dma_enabled = data & (1 << i); - if(data) dma_run(); - return; - } - - case 0x420c: { - for(unsigned i = 0; i < 8; i++) channel[i].hdma_enabled = data & (1 << i); - return; - } - - case 0x420d: { - status.rom_speed = data & 1 ? 6 : 8; - return; - } - } - - if((addr & 0xff80) == 0x4300) { - unsigned i = (addr >> 4) & 7; - switch(addr & 0xff8f) { - case 0x4300: { - channel[i].direction = data & 0x80; - channel[i].indirect = data & 0x40; - channel[i].unused = data & 0x20; - channel[i].reverse_transfer = data & 0x10; - channel[i].fixed_transfer = data & 0x08; - channel[i].transfer_mode = data & 0x07; - return; - } - - case 0x4301: { - channel[i].dest_addr = data; - return; - } - - case 0x4302: { - channel[i].source_addr = (channel[i].source_addr & 0xff00) | (data << 0); - return; - } - - case 0x4303: { - channel[i].source_addr = (data << 8) | (channel[i].source_addr & 0x00ff); - return; - } - - case 0x4304: { - channel[i].source_bank = data; - return; - } - - case 0x4305: { - channel[i].transfer_size = (channel[i].transfer_size & 0xff00) | (data << 0); - return; - } - - case 0x4306: { - channel[i].transfer_size = (data << 8) | (channel[i].transfer_size & 0x00ff); - return; - } - - case 0x4307: { - channel[i].indirect_bank = data; - return; - } - - case 0x4308: { - channel[i].hdma_addr = (channel[i].hdma_addr & 0xff00) | (data << 0); - return; - } - - case 0x4309: { - channel[i].hdma_addr = (data << 8) | (channel[i].hdma_addr & 0x00ff); - return; - } - - case 0x430a: { - channel[i].line_counter = data; - return; - } - - case 0x430b: case 0x430f: { - channel[i].unknown = data; - return; - } - } - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/cpu/timing.cpp b/waterbox/libsnes/bsnes/snes/alt/cpu/timing.cpp deleted file mode 100644 index 13027e8bf6..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/cpu/timing.cpp +++ /dev/null @@ -1,123 +0,0 @@ -#ifdef CPU_CPP - -void CPU::queue_event(unsigned id) { - switch(id) { - case QueueEvent::DramRefresh: return add_clocks(40); - case QueueEvent::HdmaRun: return hdma_run(); - } -} - -void CPU::last_cycle() { - if(status.irq_lock) { - status.irq_lock = false; - return; - } - - if(status.nmi_transition) { - regs.wai = false; - status.nmi_transition = false; - status.nmi_pending = true; - } - - if(status.irq_transition || regs.irq) { - regs.wai = false; - status.irq_transition = false; - status.irq_pending = !regs.p.i; - } -} - -void CPU::add_clocks(unsigned clocks) { - if(status.hirq_enabled) { - if(status.virq_enabled) { - unsigned cpu_time = vcounter() * 1364 + hcounter(); - unsigned irq_time = status.vtime * 1364 + status.htime * 4; - unsigned framelines = (system.region() == System::Region::NTSC ? 262 : 312) + field(); - if(cpu_time > irq_time) irq_time += framelines * 1364; - bool irq_valid = status.irq_valid; - status.irq_valid = cpu_time <= irq_time && cpu_time + clocks > irq_time; - if(!irq_valid && status.irq_valid) status.irq_line = true; - } else { - unsigned irq_time = status.htime * 4; - if(hcounter() > irq_time) irq_time += 1364; - bool irq_valid = status.irq_valid; - status.irq_valid = hcounter() <= irq_time && hcounter() + clocks > irq_time; - if(!irq_valid && status.irq_valid) status.irq_line = true; - } - if(status.irq_line) status.irq_transition = true; - } else if(status.virq_enabled) { - bool irq_valid = status.irq_valid; - status.irq_valid = vcounter() == status.vtime; - if(!irq_valid && status.irq_valid) status.irq_line = true; - if(status.irq_line) status.irq_transition = true; - } else { - status.irq_valid = false; - } - - tick(clocks); - queue.tick(clocks); - step(clocks); -} - -void CPU::scanline() { - synchronize_smp(); - synchronize_ppu(); - synchronize_coprocessors(); - system.scanline(); - - if(vcounter() == 0) hdma_init(); - - queue.enqueue(534, QueueEvent::DramRefresh); - - if(vcounter() <= (ppu.overscan() == false ? 224 : 239)) { - queue.enqueue(1104 + 8, QueueEvent::HdmaRun); - } - - bool nmi_valid = status.nmi_valid; - status.nmi_valid = vcounter() >= (ppu.overscan() == false ? 225 : 240); - if(!nmi_valid && status.nmi_valid) { - status.nmi_line = true; - if(status.nmi_enabled) status.nmi_transition = true; - } else if(nmi_valid && !status.nmi_valid) { - status.nmi_line = false; - } - - if(status.auto_joypad_poll_enabled && vcounter() == (ppu.overscan() == false ? 227 : 242)) { - run_auto_joypad_poll(); - } -} - -void CPU::run_auto_joypad_poll() { - - input.port1->latch(1); - input.port2->latch(1); - input.port1->latch(0); - input.port2->latch(0); - interface()->inputNotify(1); - interface()->inputNotify(0); - - - uint16 joy1 = 0, joy2 = 0, joy3 = 0, joy4 = 0; - for(unsigned i = 0; i < 16; i++) { - uint8 port0 = input.port1->data(); - uint8 port1 = input.port2->data(); - - joy1 |= (port0 & 1) ? (0x8000 >> i) : 0; - joy2 |= (port1 & 1) ? (0x8000 >> i) : 0; - joy3 |= (port0 & 2) ? (0x8000 >> i) : 0; - joy4 |= (port1 & 2) ? (0x8000 >> i) : 0; - } - - status.joy1l = joy1; - status.joy1h = joy1 >> 8; - - status.joy2l = joy2; - status.joy2h = joy2 >> 8; - - status.joy3l = joy3; - status.joy3h = joy3 >> 8; - - status.joy4l = joy4; - status.joy4h = joy4 >> 8; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/dsp/SPC_DSP.cpp b/waterbox/libsnes/bsnes/snes/alt/dsp/SPC_DSP.cpp deleted file mode 100644 index 12752a8431..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/dsp/SPC_DSP.cpp +++ /dev/null @@ -1,1032 +0,0 @@ -// snes_spc 0.9.0. http://www.slack.net/~ant/ - -#include "SPC_DSP.h" - -#include "blargg_endian.h" -#include - -/* Copyright (C) 2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -#ifdef BLARGG_ENABLE_OPTIMIZER - #include BLARGG_ENABLE_OPTIMIZER -#endif - -#if INT_MAX < 0x7FFFFFFF - #error "Requires that int type have at least 32 bits" -#endif - -// TODO: add to blargg_endian.h -#define GET_LE16SA( addr ) ((BOOST::int16_t) GET_LE16( addr )) -#define GET_LE16A( addr ) GET_LE16( addr ) -#define SET_LE16A( addr, data ) SET_LE16( addr, data ) - -static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] = -{ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - -// 0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80, -// 0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF, -// 0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A, -// 0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF, -// 0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67, -// 0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x9C,0x4E,0x7B,0xFF, -// 0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F, -// 0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF -}; - -// if ( io < -32768 ) io = -32768; -// if ( io > 32767 ) io = 32767; -#define CLAMP16( io )\ -{\ - if ( (int16_t) io != io )\ - io = (io >> 31) ^ 0x7FFF;\ -} - -// Access global DSP register -#define REG(n) m.regs [r_##n] - -// Access voice DSP register -#define VREG(r,n) r [v_##n] - -#define WRITE_SAMPLES( l, r, out ) \ -{\ - out [0] = l;\ - out [1] = r;\ - out += 2;\ - if ( out >= m.out_end )\ - {\ - check( out == m.out_end );\ - check( m.out_end != &m.extra [extra_size] || \ - (m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\ - out = m.extra;\ - m.out_end = &m.extra [extra_size];\ - }\ -}\ - -void SPC_DSP::set_output( sample_t* out, int size ) -{ - require( (size & 1) == 0 ); // must be even - if ( !out ) - { - out = m.extra; - size = extra_size; - } - m.out_begin = out; - m.out = out; - m.out_end = out + size; -} - -// Volume registers and efb are signed! Easy to forget int8_t cast. -// Prefixes are to avoid accidental use of locals with same names. - -// Gaussian interpolation - -static short const gauss [512] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, - 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, - 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, - 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17, - 18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 24, 24, 25, 26, 27, 27, - 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 36, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 58, 59, 60, 61, 62, 64, 65, 66, 67, 69, 70, 71, 73, 74, 76, 77, - 78, 80, 81, 83, 84, 86, 87, 89, 90, 92, 94, 95, 97, 99, 100, 102, - 104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132, - 134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168, - 171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210, - 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257, - 260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311, - 314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370, - 374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434, - 439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504, - 508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577, - 582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654, - 659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732, - 737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811, - 816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889, - 894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965, - 969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036, -1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102, -1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160, -1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210, -1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251, -1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280, -1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298, -1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305, -}; - -inline int SPC_DSP::interpolate( voice_t const* v ) -{ - // Make pointers into gaussian based on fractional position between samples - int offset = v->interp_pos >> 4 & 0xFF; - short const* fwd = gauss + 255 - offset; - short const* rev = gauss + offset; // mirror left half of gaussian - - int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; - int out; - out = (fwd [ 0] * in [0]) >> 11; - out += (fwd [256] * in [1]) >> 11; - out += (rev [256] * in [2]) >> 11; - out = (int16_t) out; - out += (rev [ 0] * in [3]) >> 11; - - CLAMP16( out ); - out &= ~1; - return out; -} - - -//// Counters - -int const simple_counter_range = 2048 * 5 * 3; // 30720 - -static unsigned const counter_rates [32] = -{ - simple_counter_range + 1, // never fires - 2048, 1536, - 1280, 1024, 768, - 640, 512, 384, - 320, 256, 192, - 160, 128, 96, - 80, 64, 48, - 40, 32, 24, - 20, 16, 12, - 10, 8, 6, - 5, 4, 3, - 2, - 1 -}; - -static unsigned const counter_offsets [32] = -{ - 1, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 0, - 0 -}; - -inline void SPC_DSP::init_counter() -{ - m.counter = 0; -} - -inline void SPC_DSP::run_counters() -{ - if ( --m.counter < 0 ) - m.counter = simple_counter_range - 1; -} - -inline unsigned SPC_DSP::read_counter( int rate ) -{ - return ((unsigned) m.counter + counter_offsets [rate]) % counter_rates [rate]; -} - - -//// Envelope - -inline void SPC_DSP::run_envelope( voice_t* const v ) -{ - int env = v->env; - if ( v->env_mode == env_release ) // 60% - { - if ( (env -= 0x8) < 0 ) - env = 0; - v->env = env; - } - else - { - int rate; - int env_data = VREG(v->regs,adsr1); - if ( m.t_adsr0 & 0x80 ) // 99% ADSR - { - if ( v->env_mode >= env_decay ) // 99% - { - env--; - env -= env >> 8; - rate = env_data & 0x1F; - if ( v->env_mode == env_decay ) // 1% - rate = (m.t_adsr0 >> 3 & 0x0E) + 0x10; - } - else // env_attack - { - rate = (m.t_adsr0 & 0x0F) * 2 + 1; - env += rate < 31 ? 0x20 : 0x400; - } - } - else // GAIN - { - int mode; - env_data = VREG(v->regs,gain); - mode = env_data >> 5; - if ( mode < 4 ) // direct - { - env = env_data * 0x10; - rate = 31; - } - else - { - rate = env_data & 0x1F; - if ( mode == 4 ) // 4: linear decrease - { - env -= 0x20; - } - else if ( mode < 6 ) // 5: exponential decrease - { - env--; - env -= env >> 8; - } - else // 6,7: linear increase - { - env += 0x20; - if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 ) - env += 0x8 - 0x20; // 7: two-slope linear increase - } - } - } - - // Sustain level - if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay ) - v->env_mode = env_sustain; - - v->hidden_env = env; - - // unsigned cast because linear decrease going negative also triggers this - if ( (unsigned) env > 0x7FF ) - { - env = (env < 0 ? 0 : 0x7FF); - if ( v->env_mode == env_attack ) - v->env_mode = env_decay; - } - - if ( !read_counter( rate ) ) - v->env = env; // nothing else is controlled by the counter - } -} - - -//// BRR Decoding - -inline void SPC_DSP::decode_brr( voice_t* v ) -{ - // Arrange the four input nybbles in 0xABCD order for easy decoding - int nybbles = m.t_brr_byte * 0x100 + m.ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF]; - - int const header = m.t_brr_header; - - // Write to next four samples in circular buffer - int* pos = &v->buf [v->buf_pos]; - int* end; - if ( (v->buf_pos += 4) >= brr_buf_size ) - v->buf_pos = 0; - - // Decode four samples - for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 ) - { - // Extract nybble and sign-extend - int s = (int16_t) nybbles >> 12; - - // Shift sample based on header - int const shift = header >> 4; - s = (s << shift) >> 1; - if ( shift >= 0xD ) // handle invalid range - s = (s >> 25) << 11; // same as: s = (s < 0 ? -0x800 : 0) - - // Apply IIR filter (8 is the most commonly used) - int const filter = header & 0x0C; - int const p1 = pos [brr_buf_size - 1]; - int const p2 = pos [brr_buf_size - 2] >> 1; - if ( filter >= 8 ) - { - s += p1; - s -= p2; - if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875 - { - s += p2 >> 4; - s += (p1 * -3) >> 6; - } - else // s += p1 * 0.8984375 - p2 * 0.40625 - { - s += (p1 * -13) >> 7; - s += (p2 * 3) >> 4; - } - } - else if ( filter ) // s += p1 * 0.46875 - { - s += p1 >> 1; - s += (-p1) >> 5; - } - - // Adjust and write sample - CLAMP16( s ); - s = (int16_t) (s * 2); - pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around - } -} - - -//// Misc - -#define MISC_CLOCK( n ) inline void SPC_DSP::misc_##n() - -MISC_CLOCK( 27 ) -{ - m.t_pmon = REG(pmon) & 0xFE; // voice 0 doesn't support PMON -} -MISC_CLOCK( 28 ) -{ - m.t_non = REG(non); - m.t_eon = REG(eon); - m.t_dir = REG(dir); -} -MISC_CLOCK( 29 ) -{ - if ( (m.every_other_sample ^= 1) != 0 ) - m.new_kon &= ~m.kon; // clears KON 63 clocks after it was last read -} -MISC_CLOCK( 30 ) -{ - if ( m.every_other_sample ) - { - m.kon = m.new_kon; - m.t_koff = REG(koff) | m.mute_mask; - } - - run_counters(); - - // Noise - if ( !read_counter( REG(flg) & 0x1F ) ) - { - int feedback = (m.noise << 13) ^ (m.noise << 14); - m.noise = (feedback & 0x4000) ^ (m.noise >> 1); - } -} - - -//// Voices - -#define VOICE_CLOCK( n ) void SPC_DSP::voice_##n( voice_t* const v ) - -inline VOICE_CLOCK( V1 ) -{ - m.t_dir_addr = m.t_dir * 0x100 + m.t_srcn * 4; - m.t_srcn = VREG(v->regs,srcn); -} -inline VOICE_CLOCK( V2 ) -{ - // Read sample pointer (ignored if not needed) - uint8_t const* entry = &m.ram [m.t_dir_addr]; - if ( !v->kon_delay ) - entry += 2; - m.t_brr_next_addr = GET_LE16A( entry ); - - m.t_adsr0 = VREG(v->regs,adsr0); - - // Read pitch, spread over two clocks - m.t_pitch = VREG(v->regs,pitchl); -} -inline VOICE_CLOCK( V3a ) -{ - m.t_pitch += (VREG(v->regs,pitchh) & 0x3F) << 8; -} -inline VOICE_CLOCK( V3b ) -{ - // Read BRR header and byte - m.t_brr_byte = m.ram [(v->brr_addr + v->brr_offset) & 0xFFFF]; - m.t_brr_header = m.ram [v->brr_addr]; // brr_addr doesn't need masking -} -VOICE_CLOCK( V3c ) -{ - // Pitch modulation using previous voice's output - if ( m.t_pmon & v->vbit ) - m.t_pitch += ((m.t_output >> 5) * m.t_pitch) >> 10; - - if ( v->kon_delay ) - { - // Get ready to start BRR decoding on next sample - if ( v->kon_delay == 5 ) - { - v->brr_addr = m.t_brr_next_addr; - v->brr_offset = 1; - v->buf_pos = 0; - m.t_brr_header = 0; // header is ignored on this sample - m.kon_check = true; - } - - // Envelope is never run during KON - v->env = 0; - v->hidden_env = 0; - - // Disable BRR decoding until last three samples - v->interp_pos = 0; - if ( --v->kon_delay & 3 ) - v->interp_pos = 0x4000; - - // Pitch is never added during KON - m.t_pitch = 0; - } - - // Gaussian interpolation - { - int output = interpolate( v ); - - // Noise - if ( m.t_non & v->vbit ) - output = (int16_t) (m.noise * 2); - - // Apply envelope - m.t_output = (output * v->env) >> 11 & ~1; - v->t_envx_out = (uint8_t) (v->env >> 4); - } - - // Immediate silence due to end of sample or soft reset - if ( REG(flg) & 0x80 || (m.t_brr_header & 3) == 1 ) - { - v->env_mode = env_release; - v->env = 0; - } - - if ( m.every_other_sample ) - { - // KOFF - if ( m.t_koff & v->vbit ) - v->env_mode = env_release; - - // KON - if ( m.kon & v->vbit ) - { - v->kon_delay = 5; - v->env_mode = env_attack; - } - } - - // Run envelope for next sample - if ( !v->kon_delay ) - run_envelope( v ); -} -inline void SPC_DSP::voice_output( voice_t const* v, int ch ) -{ - // Apply left/right volume - int amp = (m.t_output * (int8_t) VREG(v->regs,voll + ch)) >> 7; - - // Add to output total - m.t_main_out [ch] += amp; - CLAMP16( m.t_main_out [ch] ); - - // Optionally add to echo total - if ( m.t_eon & v->vbit ) - { - m.t_echo_out [ch] += amp; - CLAMP16( m.t_echo_out [ch] ); - } -} -VOICE_CLOCK( V4 ) -{ - // Decode BRR - m.t_looped = 0; - if ( v->interp_pos >= 0x4000 ) - { - decode_brr( v ); - - if ( (v->brr_offset += 2) >= brr_block_size ) - { - // Start decoding next BRR block - assert( v->brr_offset == brr_block_size ); - v->brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF; - if ( m.t_brr_header & 1 ) - { - v->brr_addr = m.t_brr_next_addr; - m.t_looped = v->vbit; - } - v->brr_offset = 1; - - //assume we're going to access the whole block - cdlInfo.currFlags = eCDLog_Flags_BRR; - for(int i=0;i<9;i++) - cdlInfo.set(eCDLog_AddrType_APURAM, (v->brr_addr+i) & 0xFFFF); - } - } - - // Apply pitch - v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch; - - // Keep from getting too far ahead (when using pitch modulation) - if ( v->interp_pos > 0x7FFF ) - v->interp_pos = 0x7FFF; - - // Output left - voice_output( v, 0 ); -} -inline VOICE_CLOCK( V5 ) -{ - // Output right - voice_output( v, 1 ); - - // ENDX, OUTX, and ENVX won't update if you wrote to them 1-2 clocks earlier - int endx_buf = REG(endx) | m.t_looped; - - // Clear bit in ENDX if KON just began - if ( v->kon_delay == 5 ) - endx_buf &= ~v->vbit; - m.endx_buf = (uint8_t) endx_buf; -} -inline VOICE_CLOCK( V6 ) -{ - (void) v; // avoid compiler warning about unused v - m.outx_buf = (uint8_t) (m.t_output >> 8); -} -inline VOICE_CLOCK( V7 ) -{ - // Update ENDX - REG(endx) = m.endx_buf; - - m.envx_buf = v->t_envx_out; -} -inline VOICE_CLOCK( V8 ) -{ - // Update OUTX - VREG(v->regs,outx) = m.outx_buf; -} -inline VOICE_CLOCK( V9 ) -{ - // Update ENVX - VREG(v->regs,envx) = m.envx_buf; -} - -// Most voices do all these in one clock, so make a handy composite -inline VOICE_CLOCK( V3 ) -{ - voice_V3a( v ); - voice_V3b( v ); - voice_V3c( v ); -} - -// Common combinations of voice steps on different voices. This greatly reduces -// code size and allows everything to be inlined in these functions. -VOICE_CLOCK(V7_V4_V1) { voice_V7(v); voice_V1(v+3); voice_V4(v+1); } -VOICE_CLOCK(V8_V5_V2) { voice_V8(v); voice_V5(v+1); voice_V2(v+2); } -VOICE_CLOCK(V9_V6_V3) { voice_V9(v); voice_V6(v+1); voice_V3(v+2); } - - -//// Echo - -// Current echo buffer pointer for left/right channel -#define ECHO_PTR( ch ) (&m.ram [m.t_echo_ptr + ch * 2]) - -// Sample in echo history buffer, where 0 is the oldest -#define ECHO_FIR( i ) (m.echo_hist_pos [i]) - -// Calculate FIR point for left/right channel -#define CALC_FIR( i, ch ) ((ECHO_FIR( i + 1 ) [ch] * (int8_t) REG(fir + i * 0x10)) >> 6) - -#define ECHO_CLOCK( n ) inline void SPC_DSP::echo_##n() - -inline void SPC_DSP::echo_read( int ch ) -{ - int s = GET_LE16SA( ECHO_PTR( ch ) ); - // second copy simplifies wrap-around handling - ECHO_FIR( 0 ) [ch] = ECHO_FIR( 8 ) [ch] = s >> 1; -} - -ECHO_CLOCK( 22 ) -{ - // History - if ( ++m.echo_hist_pos >= &m.echo_hist [echo_hist_size] ) - m.echo_hist_pos = m.echo_hist; - - m.t_echo_ptr = (m.t_esa * 0x100 + m.echo_offset) & 0xFFFF; - echo_read( 0 ); - - // FIR (using l and r temporaries below helps compiler optimize) - int l = CALC_FIR( 0, 0 ); - int r = CALC_FIR( 0, 1 ); - - m.t_echo_in [0] = l; - m.t_echo_in [1] = r; -} -ECHO_CLOCK( 23 ) -{ - int l = CALC_FIR( 1, 0 ) + CALC_FIR( 2, 0 ); - int r = CALC_FIR( 1, 1 ) + CALC_FIR( 2, 1 ); - - m.t_echo_in [0] += l; - m.t_echo_in [1] += r; - - echo_read( 1 ); -} -ECHO_CLOCK( 24 ) -{ - int l = CALC_FIR( 3, 0 ) + CALC_FIR( 4, 0 ) + CALC_FIR( 5, 0 ); - int r = CALC_FIR( 3, 1 ) + CALC_FIR( 4, 1 ) + CALC_FIR( 5, 1 ); - - m.t_echo_in [0] += l; - m.t_echo_in [1] += r; -} -ECHO_CLOCK( 25 ) -{ - int l = m.t_echo_in [0] + CALC_FIR( 6, 0 ); - int r = m.t_echo_in [1] + CALC_FIR( 6, 1 ); - - l = (int16_t) l; - r = (int16_t) r; - - l += (int16_t) CALC_FIR( 7, 0 ); - r += (int16_t) CALC_FIR( 7, 1 ); - - CLAMP16( l ); - CLAMP16( r ); - - m.t_echo_in [0] = l & ~1; - m.t_echo_in [1] = r & ~1; -} -inline int SPC_DSP::echo_output( int ch ) -{ - int out = (int16_t) ((m.t_main_out [ch] * (int8_t) REG(mvoll + ch * 0x10)) >> 7) + - (int16_t) ((m.t_echo_in [ch] * (int8_t) REG(evoll + ch * 0x10)) >> 7); - CLAMP16( out ); - return out; -} -ECHO_CLOCK( 26 ) -{ - // Left output volumes - // (save sample for next clock so we can output both together) - m.t_main_out [0] = echo_output( 0 ); - - // Echo feedback - int l = m.t_echo_out [0] + (int16_t) ((m.t_echo_in [0] * (int8_t) REG(efb)) >> 7); - int r = m.t_echo_out [1] + (int16_t) ((m.t_echo_in [1] * (int8_t) REG(efb)) >> 7); - - CLAMP16( l ); - CLAMP16( r ); - - m.t_echo_out [0] = l & ~1; - m.t_echo_out [1] = r & ~1; -} -ECHO_CLOCK( 27 ) -{ - // Output - int l = m.t_main_out [0]; - int r = echo_output( 1 ); - m.t_main_out [0] = 0; - m.t_main_out [1] = 0; - - // TODO: global muting isn't this simple (turns DAC on and off - // or something, causing small ~37-sample pulse when first muted) - if ( REG(flg) & 0x40 ) - { - l = 0; - r = 0; - } - - // Output sample to DAC - #ifdef SPC_DSP_OUT_HOOK - SPC_DSP_OUT_HOOK( l, r ); - #else - sample_t* out = m.out; - WRITE_SAMPLES( l, r, out ); - m.out = out; - #endif -} -ECHO_CLOCK( 28 ) -{ - m.t_echo_enabled = REG(flg); -} -inline void SPC_DSP::echo_write( int ch ) -{ - if ( !(m.t_echo_enabled & 0x20) ) - SET_LE16A( ECHO_PTR( ch ), m.t_echo_out [ch] ); - m.t_echo_out [ch] = 0; -} -ECHO_CLOCK( 29 ) -{ - m.t_esa = REG(esa); - - if ( !m.echo_offset ) - m.echo_length = (REG(edl) & 0x0F) * 0x800; - - m.echo_offset += 4; - if ( m.echo_offset >= m.echo_length ) - m.echo_offset = 0; - - // Write left echo - echo_write( 0 ); - - m.t_echo_enabled = REG(flg); -} -ECHO_CLOCK( 30 ) -{ - // Write right echo - echo_write( 1 ); -} - - -//// Timing - -// Execute clock for a particular voice -#define V( clock, voice ) voice_##clock( &m.voices [voice] ); - -/* The most common sequence of clocks uses composite operations -for efficiency. For example, the following are equivalent to the -individual steps on the right: - -V(V7_V4_V1,2) -> V(V7,2) V(V4,3) V(V1,5) -V(V8_V5_V2,2) -> V(V8,2) V(V5,3) V(V2,4) -V(V9_V6_V3,2) -> V(V9,2) V(V6,3) V(V3,4) */ - -// Voice 0 1 2 3 4 5 6 7 -#define GEN_DSP_TIMING \ -PHASE( 0) V(V5,0)V(V2,1)\ -PHASE( 1) V(V6,0)V(V3,1)\ -PHASE( 2) V(V7_V4_V1,0)\ -PHASE( 3) V(V8_V5_V2,0)\ -PHASE( 4) V(V9_V6_V3,0)\ -PHASE( 5) V(V7_V4_V1,1)\ -PHASE( 6) V(V8_V5_V2,1)\ -PHASE( 7) V(V9_V6_V3,1)\ -PHASE( 8) V(V7_V4_V1,2)\ -PHASE( 9) V(V8_V5_V2,2)\ -PHASE(10) V(V9_V6_V3,2)\ -PHASE(11) V(V7_V4_V1,3)\ -PHASE(12) V(V8_V5_V2,3)\ -PHASE(13) V(V9_V6_V3,3)\ -PHASE(14) V(V7_V4_V1,4)\ -PHASE(15) V(V8_V5_V2,4)\ -PHASE(16) V(V9_V6_V3,4)\ -PHASE(17) V(V1,0) V(V7,5)V(V4,6)\ -PHASE(18) V(V8_V5_V2,5)\ -PHASE(19) V(V9_V6_V3,5)\ -PHASE(20) V(V1,1) V(V7,6)V(V4,7)\ -PHASE(21) V(V8,6)V(V5,7) V(V2,0) /* t_brr_next_addr order dependency */\ -PHASE(22) V(V3a,0) V(V9,6)V(V6,7) echo_22();\ -PHASE(23) V(V7,7) echo_23();\ -PHASE(24) V(V8,7) echo_24();\ -PHASE(25) V(V3b,0) V(V9,7) echo_25();\ -PHASE(26) echo_26();\ -PHASE(27) misc_27(); echo_27();\ -PHASE(28) misc_28(); echo_28();\ -PHASE(29) misc_29(); echo_29();\ -PHASE(30) misc_30();V(V3c,0) echo_30();\ -PHASE(31) V(V4,0) V(V1,2)\ - -#if !SPC_DSP_CUSTOM_RUN - -void SPC_DSP::run( int clocks_remain ) -{ - require( clocks_remain > 0 ); - - int const phase = m.phase; - m.phase = (phase + clocks_remain) & 31; - switch ( phase ) - { - loop: - - #define PHASE( n ) if ( n && !--clocks_remain ) break; case n: - GEN_DSP_TIMING - #undef PHASE - - if ( --clocks_remain ) - goto loop; - } -} - -#endif - - -//// Setup - -void SPC_DSP::init( void* ram_64k ) -{ - m.ram = (uint8_t*) ram_64k; - mute_voices( 0 ); - disable_surround( false ); - set_output( 0, 0 ); - reset(); - - #ifndef NDEBUG - // be sure this sign-extends - assert( (int16_t) 0x8000 == -0x8000 ); - - // be sure right shift preserves sign - assert( (-1 >> 1) == -1 ); - - // check clamp macro - int i; - i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF ); - i = -0x8001; CLAMP16( i ); assert( i == -0x8000 ); - - blargg_verify_byte_order(); - #endif -} - -void SPC_DSP::soft_reset_common() -{ - require( m.ram ); // init() must have been called already - - m.noise = 0x4000; - m.echo_hist_pos = m.echo_hist; - m.every_other_sample = 1; - m.echo_offset = 0; - m.phase = 0; - - init_counter(); -} - -void SPC_DSP::soft_reset() -{ - REG(flg) = 0xE0; - soft_reset_common(); -} - -void SPC_DSP::load( uint8_t const regs [register_count] ) -{ - memcpy( m.regs, regs, sizeof m.regs ); - memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count ); - - // Internal state - for ( int i = voice_count; --i >= 0; ) - { - voice_t* v = &m.voices [i]; - v->brr_offset = 1; - v->vbit = 1 << i; - v->regs = &m.regs [i * 0x10]; - } - m.new_kon = REG(kon); - m.t_dir = REG(dir); - m.t_esa = REG(esa); - - soft_reset_common(); -} - -void SPC_DSP::reset() { load( initial_regs ); } - - -//// State save/load - -#if !SPC_NO_COPY_STATE_FUNCS - -void SPC_State_Copier::copy( void* state, size_t size ) -{ - func( buf, state, size ); -} - -int SPC_State_Copier::copy_int( int state, int size ) -{ - BOOST::uint8_t s [2]; - SET_LE16( s, state ); - func( buf, &s, size ); - return GET_LE16( s ); -} - -void SPC_State_Copier::skip( int count ) -{ - if ( count > 0 ) - { - char temp [64]; - memset( temp, 0, sizeof temp ); - do - { - int n = sizeof temp; - if ( n > count ) - n = count; - count -= n; - func( buf, temp, n ); - } - while ( count ); - } -} - -void SPC_State_Copier::extra() -{ - int n = 0; - SPC_State_Copier& copier = *this; - SPC_COPY( uint8_t, n ); - skip( n ); -} - -void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) -{ - SPC_State_Copier copier( io, copy ); - - // DSP registers - copier.copy( m.regs, register_count ); - - // Internal state - - // Voices - int i; - for ( i = 0; i < voice_count; i++ ) - { - voice_t* v = &m.voices [i]; - - // BRR buffer - int i; - for ( i = 0; i < brr_buf_size; i++ ) - { - int s = v->buf [i]; - SPC_COPY( int16_t, s ); - v->buf [i] = v->buf [i + brr_buf_size] = s; - } - - SPC_COPY( uint16_t, v->interp_pos ); - SPC_COPY( uint16_t, v->brr_addr ); - SPC_COPY( uint16_t, v->env ); - SPC_COPY( int16_t, v->hidden_env ); - SPC_COPY( uint8_t, v->buf_pos ); - SPC_COPY( uint8_t, v->brr_offset ); - SPC_COPY( uint8_t, v->kon_delay ); - { - int m = v->env_mode; - SPC_COPY( uint8_t, m ); - v->env_mode = (enum env_mode_t) m; - } - SPC_COPY( uint8_t, v->t_envx_out ); - - copier.extra(); - } - - // Echo history - for ( i = 0; i < echo_hist_size; i++ ) - { - int j; - for ( j = 0; j < 2; j++ ) - { - int s = m.echo_hist_pos [i] [j]; - SPC_COPY( int16_t, s ); - m.echo_hist [i] [j] = s; // write back at offset 0 - } - } - m.echo_hist_pos = m.echo_hist; - memcpy( &m.echo_hist [echo_hist_size], m.echo_hist, echo_hist_size * sizeof m.echo_hist [0] ); - - // Misc - SPC_COPY( uint8_t, m.every_other_sample ); - SPC_COPY( uint8_t, m.kon ); - - SPC_COPY( uint16_t, m.noise ); - SPC_COPY( uint16_t, m.counter ); - SPC_COPY( uint16_t, m.echo_offset ); - SPC_COPY( uint16_t, m.echo_length ); - SPC_COPY( uint8_t, m.phase ); - - SPC_COPY( uint8_t, m.new_kon ); - SPC_COPY( uint8_t, m.endx_buf ); - SPC_COPY( uint8_t, m.envx_buf ); - SPC_COPY( uint8_t, m.outx_buf ); - - SPC_COPY( uint8_t, m.t_pmon ); - SPC_COPY( uint8_t, m.t_non ); - SPC_COPY( uint8_t, m.t_eon ); - SPC_COPY( uint8_t, m.t_dir ); - SPC_COPY( uint8_t, m.t_koff ); - - SPC_COPY( uint16_t, m.t_brr_next_addr ); - SPC_COPY( uint8_t, m.t_adsr0 ); - SPC_COPY( uint8_t, m.t_brr_header ); - SPC_COPY( uint8_t, m.t_brr_byte ); - SPC_COPY( uint8_t, m.t_srcn ); - SPC_COPY( uint8_t, m.t_esa ); - SPC_COPY( uint8_t, m.t_echo_enabled ); - - SPC_COPY( int16_t, m.t_main_out [0] ); - SPC_COPY( int16_t, m.t_main_out [1] ); - SPC_COPY( int16_t, m.t_echo_out [0] ); - SPC_COPY( int16_t, m.t_echo_out [1] ); - SPC_COPY( int16_t, m.t_echo_in [0] ); - SPC_COPY( int16_t, m.t_echo_in [1] ); - - SPC_COPY( uint16_t, m.t_dir_addr ); - SPC_COPY( uint16_t, m.t_pitch ); - SPC_COPY( int16_t, m.t_output ); - SPC_COPY( uint16_t, m.t_echo_ptr ); - SPC_COPY( uint8_t, m.t_looped ); - - copier.extra(); -} -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/dsp/SPC_DSP.h b/waterbox/libsnes/bsnes/snes/alt/dsp/SPC_DSP.h deleted file mode 100644 index 4522ace915..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/dsp/SPC_DSP.h +++ /dev/null @@ -1,304 +0,0 @@ -// Highly accurate SNES SPC-700 DSP emulator - -// snes_spc 0.9.0 -#ifndef SPC_DSP_H -#define SPC_DSP_H - -#include "blargg_common.h" - -extern "C" { typedef void (*dsp_copy_func_t)( unsigned char** io, void* state, size_t ); } - -class SPC_DSP { -public: - typedef BOOST::uint8_t uint8_t; - -// Setup - - // Initializes DSP and has it use the 64K RAM provided - void init( void* ram_64k ); - - // Sets destination for output samples. If out is NULL or out_size is 0, - // doesn't generate any. - typedef short sample_t; - void set_output( sample_t* out, int out_size ); - - // Number of samples written to output since it was last set, always - // a multiple of 2. Undefined if more samples were generated than - // output buffer could hold. - int sample_count() const; - -// Emulation - - // Resets DSP to power-on state - void reset(); - - // Emulates pressing reset switch on SNES - void soft_reset(); - - // Reads/writes DSP registers. For accuracy, you must first call run() - // to catch the DSP up to present. - int read ( int addr ) const; - void write( int addr, int data ); - - // Runs DSP for specified number of clocks (~1024000 per second). Every 32 clocks - // a pair of samples is be generated. - void run( int clock_count ); - -// Sound control - - // Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events). - // Reduces emulation accuracy. - enum { voice_count = 8 }; - void mute_voices( int mask ); - -// State - - // Resets DSP and uses supplied values to initialize registers - enum { register_count = 128 }; - void load( uint8_t const regs [register_count] ); - - // Saves/loads exact emulator state - enum { state_size = 640 }; // maximum space needed when saving - typedef dsp_copy_func_t copy_func_t; - void copy_state( unsigned char** io, copy_func_t ); - - // Returns non-zero if new key-on events occurred since last call - bool check_kon(); - -// DSP register addresses - - // Global registers - enum { - r_mvoll = 0x0C, r_mvolr = 0x1C, - r_evoll = 0x2C, r_evolr = 0x3C, - r_kon = 0x4C, r_koff = 0x5C, - r_flg = 0x6C, r_endx = 0x7C, - r_efb = 0x0D, r_pmon = 0x2D, - r_non = 0x3D, r_eon = 0x4D, - r_dir = 0x5D, r_esa = 0x6D, - r_edl = 0x7D, - r_fir = 0x0F // 8 coefficients at 0x0F, 0x1F ... 0x7F - }; - - // Voice registers - enum { - v_voll = 0x00, v_volr = 0x01, - v_pitchl = 0x02, v_pitchh = 0x03, - v_srcn = 0x04, v_adsr0 = 0x05, - v_adsr1 = 0x06, v_gain = 0x07, - v_envx = 0x08, v_outx = 0x09 - }; - -public: - enum { extra_size = 16 }; - sample_t* extra() { return m.extra; } - sample_t const* out_pos() const { return m.out; } - void disable_surround( bool ) { } // not supported -public: - BLARGG_DISABLE_NOTHROW - - typedef BOOST::int8_t int8_t; - typedef BOOST::int16_t int16_t; - - enum { echo_hist_size = 8 }; - - enum env_mode_t { env_release, env_attack, env_decay, env_sustain }; - enum { brr_buf_size = 12 }; - struct voice_t - { - int buf [brr_buf_size*2];// decoded samples (twice the size to simplify wrap handling) - int buf_pos; // place in buffer where next samples will be decoded - int interp_pos; // relative fractional position in sample (0x1000 = 1.0) - int brr_addr; // address of current BRR block - int brr_offset; // current decoding offset in BRR block - uint8_t* regs; // pointer to voice's DSP registers - int vbit; // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc. - int kon_delay; // KON delay/current setup phase - env_mode_t env_mode; - int env; // current envelope level - int hidden_env; // used by GAIN mode 7, very obscure quirk - uint8_t t_envx_out; - }; -private: - enum { brr_block_size = 9 }; - - struct state_t - { - uint8_t regs [register_count]; - - // Echo history keeps most recent 8 samples (twice the size to simplify wrap handling) - int echo_hist [echo_hist_size * 2] [2]; - int (*echo_hist_pos) [2]; // &echo_hist [0 to 7] - - int every_other_sample; // toggles every sample - int kon; // KON value when last checked - int noise; - int counter; - int echo_offset; // offset from ESA in echo buffer - int echo_length; // number of bytes that echo_offset will stop at - int phase; // next clock cycle to run (0-31) - bool kon_check; // set when a new KON occurs - - // Hidden registers also written to when main register is written to - int new_kon; - uint8_t endx_buf; - uint8_t envx_buf; - uint8_t outx_buf; - - // Temporary state between clocks - - // read once per sample - int t_pmon; - int t_non; - int t_eon; - int t_dir; - int t_koff; - - // read a few clocks ahead then used - int t_brr_next_addr; - int t_adsr0; - int t_brr_header; - int t_brr_byte; - int t_srcn; - int t_esa; - int t_echo_enabled; - - // internal state that is recalculated every sample - int t_dir_addr; - int t_pitch; - int t_output; - int t_looped; - int t_echo_ptr; - - // left/right sums - int t_main_out [2]; - int t_echo_out [2]; - int t_echo_in [2]; - - voice_t voices [voice_count]; - - // non-emulation state - uint8_t* ram; // 64K shared RAM between DSP and SMP - int mute_mask; - sample_t* out; - sample_t* out_end; - sample_t* out_begin; - sample_t extra [extra_size]; - }; - state_t m; - - void init_counter(); - void run_counters(); - unsigned read_counter( int rate ); - - int interpolate( voice_t const* v ); - void run_envelope( voice_t* const v ); - void decode_brr( voice_t* v ); - - void misc_27(); - void misc_28(); - void misc_29(); - void misc_30(); - - void voice_output( voice_t const* v, int ch ); - void voice_V1( voice_t* const ); - void voice_V2( voice_t* const ); - void voice_V3( voice_t* const ); - void voice_V3a( voice_t* const ); - void voice_V3b( voice_t* const ); - void voice_V3c( voice_t* const ); - void voice_V4( voice_t* const ); - void voice_V5( voice_t* const ); - void voice_V6( voice_t* const ); - void voice_V7( voice_t* const ); - void voice_V8( voice_t* const ); - void voice_V9( voice_t* const ); - void voice_V7_V4_V1( voice_t* const ); - void voice_V8_V5_V2( voice_t* const ); - void voice_V9_V6_V3( voice_t* const ); - - void echo_read( int ch ); - int echo_output( int ch ); - void echo_write( int ch ); - void echo_22(); - void echo_23(); - void echo_24(); - void echo_25(); - void echo_26(); - void echo_27(); - void echo_28(); - void echo_29(); - void echo_30(); - - void soft_reset_common(); -}; - -#include - -inline int SPC_DSP::sample_count() const { return m.out - m.out_begin; } - -inline int SPC_DSP::read( int addr ) const -{ - assert( (unsigned) addr < register_count ); - return m.regs [addr]; -} - -inline void SPC_DSP::write( int addr, int data ) -{ - assert( (unsigned) addr < register_count ); - - m.regs [addr] = (uint8_t) data; - switch ( addr & 0x0F ) - { - case v_envx: - m.envx_buf = (uint8_t) data; - break; - - case v_outx: - m.outx_buf = (uint8_t) data; - break; - - case 0x0C: - if ( addr == r_kon ) - m.new_kon = (uint8_t) data; - - if ( addr == r_endx ) // always cleared, regardless of data written - { - m.endx_buf = 0; - m.regs [r_endx] = 0; - } - break; - } -} - -inline void SPC_DSP::mute_voices( int mask ) { m.mute_mask = mask; } - -inline bool SPC_DSP::check_kon() -{ - bool old = m.kon_check; - m.kon_check = 0; - return old; -} - -#if !SPC_NO_COPY_STATE_FUNCS - -class SPC_State_Copier { - SPC_DSP::copy_func_t func; - unsigned char** buf; -public: - SPC_State_Copier( unsigned char** p, SPC_DSP::copy_func_t f ) { func = f; buf = p; } - void copy( void* state, size_t size ); - int copy_int( int state, int size ); - void skip( int count ); - void extra(); -}; - -#define SPC_COPY( type, state )\ -{\ - state = (BOOST::type) copier.copy_int( state, sizeof (BOOST::type) );\ - assert( (BOOST::type) state == state );\ -} - -#endif - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/dsp/blargg_common.h b/waterbox/libsnes/bsnes/snes/alt/dsp/blargg_common.h deleted file mode 100644 index 75edff3914..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/dsp/blargg_common.h +++ /dev/null @@ -1,186 +0,0 @@ -// Sets up common environment for Shay Green's libraries. -// To change configuration options, modify blargg_config.h, not this file. - -// snes_spc 0.9.0 -#ifndef BLARGG_COMMON_H -#define BLARGG_COMMON_H - -#include -#include -#include -#include - -#undef BLARGG_COMMON_H -// allow blargg_config.h to #include blargg_common.h -#include "blargg_config.h" -#ifndef BLARGG_COMMON_H -#define BLARGG_COMMON_H - -// BLARGG_RESTRICT: equivalent to restrict, where supported -#if defined (__GNUC__) || _MSC_VER >= 1100 - #define BLARGG_RESTRICT __restrict -#else - #define BLARGG_RESTRICT -#endif - -// STATIC_CAST(T,expr): Used in place of static_cast (expr) -#ifndef STATIC_CAST - #define STATIC_CAST(T,expr) ((T) (expr)) -#endif - -// blargg_err_t (0 on success, otherwise error string) -#ifndef blargg_err_t - typedef const char* blargg_err_t; -#endif - -// blargg_vector - very lightweight vector of POD types (no constructor/destructor) -template -class blargg_vector { - T* begin_; - size_t size_; -public: - blargg_vector() : begin_( 0 ), size_( 0 ) { } - ~blargg_vector() { free( begin_ ); } - size_t size() const { return size_; } - T* begin() const { return begin_; } - T* end() const { return begin_ + size_; } - blargg_err_t resize( size_t n ) - { - // TODO: blargg_common.cpp to hold this as an outline function, ugh - void* p = realloc( begin_, n * sizeof (T) ); - if ( p ) - begin_ = (T*) p; - else if ( n > size_ ) // realloc failure only a problem if expanding - return "Out of memory"; - size_ = n; - return 0; - } - void clear() { void* p = begin_; begin_ = 0; size_ = 0; free( p ); } - T& operator [] ( size_t n ) const - { - assert( n <= size_ ); // <= to allow past-the-end value - return begin_ [n]; - } -}; - -#ifndef BLARGG_DISABLE_NOTHROW - // throw spec mandatory in ISO C++ if operator new can return NULL - #if __cplusplus >= 199711 || defined (__GNUC__) - #define BLARGG_THROWS( spec ) throw spec - #else - #define BLARGG_THROWS( spec ) - #endif - #define BLARGG_DISABLE_NOTHROW \ - void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\ - void operator delete ( void* p ) { free( p ); } - #define BLARGG_NEW new -#else - #include - #define BLARGG_NEW new (std::nothrow) -#endif - -// BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant) -#define BLARGG_4CHAR( a, b, c, d ) \ - ((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF)) - -// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0. -#ifndef BOOST_STATIC_ASSERT - #ifdef _MSC_VER - // MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified - #define BOOST_STATIC_ASSERT( expr ) \ - void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] ) - #else - // Some other compilers fail when declaring same function multiple times in class, - // so differentiate them by line - #define BOOST_STATIC_ASSERT( expr ) \ - void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] ) - #endif -#endif - -// BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compiler. If 1, -// compiler is assumed to support bool. If undefined, availability is determined. -#ifndef BLARGG_COMPILER_HAS_BOOL - #if defined (__MWERKS__) - #if !__option(bool) - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif - #elif defined (_MSC_VER) - #if _MSC_VER < 1100 - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif - #elif defined (__GNUC__) - // supports bool - #elif __cplusplus < 199711 - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif -#endif -#if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL - // If you get errors here, modify your blargg_config.h file - typedef int bool; - const bool true = 1; - const bool false = 0; -#endif - -// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough - -#if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF - typedef long blargg_long; -#else - typedef int blargg_long; -#endif - -#if UINT_MAX < 0xFFFFFFFF || ULONG_MAX == 0xFFFFFFFF - typedef unsigned long blargg_ulong; -#else - typedef unsigned blargg_ulong; -#endif - -// BOOST::int8_t etc. - -// HAVE_STDINT_H: If defined, use for int8_t etc. -#if defined (HAVE_STDINT_H) - #include - #define BOOST - -// HAVE_INTTYPES_H: If defined, use for int8_t etc. -#elif defined (HAVE_INTTYPES_H) - #include - #define BOOST - -#else - struct BOOST - { - #if UCHAR_MAX == 0xFF && SCHAR_MAX == 0x7F - typedef signed char int8_t; - typedef unsigned char uint8_t; - #else - // No suitable 8-bit type available - typedef struct see_blargg_common_h int8_t; - typedef struct see_blargg_common_h uint8_t; - #endif - - #if USHRT_MAX == 0xFFFF - typedef short int16_t; - typedef unsigned short uint16_t; - #else - // No suitable 16-bit type available - typedef struct see_blargg_common_h int16_t; - typedef struct see_blargg_common_h uint16_t; - #endif - - #if ULONG_MAX == 0xFFFFFFFF - typedef long int32_t; - typedef unsigned long uint32_t; - #elif UINT_MAX == 0xFFFFFFFF - typedef int int32_t; - typedef unsigned int uint32_t; - #else - // No suitable 32-bit type available - typedef struct see_blargg_common_h int32_t; - typedef struct see_blargg_common_h uint32_t; - #endif - }; -#endif - -#endif -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/dsp/blargg_config.h b/waterbox/libsnes/bsnes/snes/alt/dsp/blargg_config.h deleted file mode 100644 index d85d2663bf..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/dsp/blargg_config.h +++ /dev/null @@ -1,24 +0,0 @@ -// snes_spc 0.9.0 user configuration file. Don't replace when updating library. - -// snes_spc 0.9.0 -#ifndef BLARGG_CONFIG_H -#define BLARGG_CONFIG_H - -// Uncomment to disable debugging checks -#define NDEBUG 1 - -// Uncomment to enable platform-specific (and possibly non-portable) optimizations -//#define BLARGG_NONPORTABLE 1 - -// Uncomment if automatic byte-order determination doesn't work -//#define BLARGG_BIG_ENDIAN 1 - -// Uncomment if you get errors in the bool section of blargg_common.h -//#define BLARGG_COMPILER_HAS_BOOL 1 - -// Use standard config.h if present -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/dsp/blargg_endian.h b/waterbox/libsnes/bsnes/snes/alt/dsp/blargg_endian.h deleted file mode 100644 index f2daca6416..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/dsp/blargg_endian.h +++ /dev/null @@ -1,185 +0,0 @@ -// CPU Byte Order Utilities - -// snes_spc 0.9.0 -#ifndef BLARGG_ENDIAN -#define BLARGG_ENDIAN - -#include "blargg_common.h" - -// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16) -#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ - defined (__x86_64__) || defined (__ia64__) || defined (__i386__) - #define BLARGG_CPU_X86 1 - #define BLARGG_CPU_CISC 1 -#endif - -#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc) - #define BLARGG_CPU_POWERPC 1 - #define BLARGG_CPU_RISC 1 -#endif - -// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only -// one may be #defined to 1. Only needed if something actually depends on byte order. -#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN) -#ifdef __GLIBC__ - // GCC handles this for us - #include - #if __BYTE_ORDER == __LITTLE_ENDIAN - #define BLARGG_LITTLE_ENDIAN 1 - #elif __BYTE_ORDER == __BIG_ENDIAN - #define BLARGG_BIG_ENDIAN 1 - #endif -#else - -#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \ - (defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234) - #define BLARGG_LITTLE_ENDIAN 1 -#endif - -#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \ - defined (__sparc__) || BLARGG_CPU_POWERPC || \ - (defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321) - #define BLARGG_BIG_ENDIAN 1 -#elif !defined (__mips__) - // No endian specified; assume little-endian, since it's most common - #define BLARGG_LITTLE_ENDIAN 1 -#endif -#endif -#endif - -#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN - #undef BLARGG_LITTLE_ENDIAN - #undef BLARGG_BIG_ENDIAN -#endif - -inline void blargg_verify_byte_order() -{ - #ifndef NDEBUG - #if BLARGG_BIG_ENDIAN - volatile int i = 1; - assert( *(volatile char*) &i == 0 ); - #elif BLARGG_LITTLE_ENDIAN - volatile int i = 1; - assert( *(volatile char*) &i != 0 ); - #endif - #endif -} - -inline unsigned get_le16( void const* p ) -{ - return (unsigned) ((unsigned char const*) p) [1] << 8 | - (unsigned) ((unsigned char const*) p) [0]; -} - -inline unsigned get_be16( void const* p ) -{ - return (unsigned) ((unsigned char const*) p) [0] << 8 | - (unsigned) ((unsigned char const*) p) [1]; -} - -inline blargg_ulong get_le32( void const* p ) -{ - return (blargg_ulong) ((unsigned char const*) p) [3] << 24 | - (blargg_ulong) ((unsigned char const*) p) [2] << 16 | - (blargg_ulong) ((unsigned char const*) p) [1] << 8 | - (blargg_ulong) ((unsigned char const*) p) [0]; -} - -inline blargg_ulong get_be32( void const* p ) -{ - return (blargg_ulong) ((unsigned char const*) p) [0] << 24 | - (blargg_ulong) ((unsigned char const*) p) [1] << 16 | - (blargg_ulong) ((unsigned char const*) p) [2] << 8 | - (blargg_ulong) ((unsigned char const*) p) [3]; -} - -inline void set_le16( void* p, unsigned n ) -{ - ((unsigned char*) p) [1] = (unsigned char) (n >> 8); - ((unsigned char*) p) [0] = (unsigned char) n; -} - -inline void set_be16( void* p, unsigned n ) -{ - ((unsigned char*) p) [0] = (unsigned char) (n >> 8); - ((unsigned char*) p) [1] = (unsigned char) n; -} - -inline void set_le32( void* p, blargg_ulong n ) -{ - ((unsigned char*) p) [0] = (unsigned char) n; - ((unsigned char*) p) [1] = (unsigned char) (n >> 8); - ((unsigned char*) p) [2] = (unsigned char) (n >> 16); - ((unsigned char*) p) [3] = (unsigned char) (n >> 24); -} - -inline void set_be32( void* p, blargg_ulong n ) -{ - ((unsigned char*) p) [3] = (unsigned char) n; - ((unsigned char*) p) [2] = (unsigned char) (n >> 8); - ((unsigned char*) p) [1] = (unsigned char) (n >> 16); - ((unsigned char*) p) [0] = (unsigned char) (n >> 24); -} - -#if BLARGG_NONPORTABLE - // Optimized implementation if byte order is known - #if BLARGG_LITTLE_ENDIAN - #define GET_LE16( addr ) (*(BOOST::uint16_t*) (addr)) - #define GET_LE32( addr ) (*(BOOST::uint32_t*) (addr)) - #define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) - #define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) - #elif BLARGG_BIG_ENDIAN - #define GET_BE16( addr ) (*(BOOST::uint16_t*) (addr)) - #define GET_BE32( addr ) (*(BOOST::uint32_t*) (addr)) - #define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) - #define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) - - #if BLARGG_CPU_POWERPC - // PowerPC has special byte-reversed instructions - #if defined (__MWERKS__) - #define GET_LE16( addr ) (__lhbrx( addr, 0 )) - #define GET_LE32( addr ) (__lwbrx( addr, 0 )) - #define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 )) - #define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 )) - #elif defined (__GNUC__) - #define GET_LE16( addr ) ({unsigned ppc_lhbrx_; asm( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr), "0" (ppc_lhbrx_) ); ppc_lhbrx_;}) - #define GET_LE32( addr ) ({unsigned ppc_lwbrx_; asm( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr), "0" (ppc_lwbrx_) ); ppc_lwbrx_;}) - #define SET_LE16( addr, in ) ({asm( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) );}) - #define SET_LE32( addr, in ) ({asm( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) );}) - #endif - #endif - #endif -#endif - -#ifndef GET_LE16 - #define GET_LE16( addr ) get_le16( addr ) - #define SET_LE16( addr, data ) set_le16( addr, data ) -#endif - -#ifndef GET_LE32 - #define GET_LE32( addr ) get_le32( addr ) - #define SET_LE32( addr, data ) set_le32( addr, data ) -#endif - -#ifndef GET_BE16 - #define GET_BE16( addr ) get_be16( addr ) - #define SET_BE16( addr, data ) set_be16( addr, data ) -#endif - -#ifndef GET_BE32 - #define GET_BE32( addr ) get_be32( addr ) - #define SET_BE32( addr, data ) set_be32( addr, data ) -#endif - -// auto-selecting versions - -inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); } -inline void set_le( BOOST::uint32_t* p, blargg_ulong n ) { SET_LE32( p, n ); } -inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); } -inline void set_be( BOOST::uint32_t* p, blargg_ulong n ) { SET_BE32( p, n ); } -inline unsigned get_le( BOOST::uint16_t* p ) { return GET_LE16( p ); } -inline blargg_ulong get_le( BOOST::uint32_t* p ) { return GET_LE32( p ); } -inline unsigned get_be( BOOST::uint16_t* p ) { return GET_BE16( p ); } -inline blargg_ulong get_be( BOOST::uint32_t* p ) { return GET_BE32( p ); } - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/dsp/blargg_source.h b/waterbox/libsnes/bsnes/snes/alt/dsp/blargg_source.h deleted file mode 100644 index 5e45c4fb42..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/dsp/blargg_source.h +++ /dev/null @@ -1,100 +0,0 @@ -/* Included at the beginning of library source files, after all other #include lines. -Sets up helpful macros and services used in my source code. They don't need -module an annoying module prefix on their names since they are defined after -all other #include lines. */ - -// snes_spc 0.9.0 -#ifndef BLARGG_SOURCE_H -#define BLARGG_SOURCE_H - -// If debugging is enabled, abort program if expr is false. Meant for checking -// internal state and consistency. A failed assertion indicates a bug in the module. -// void assert( bool expr ); -#include - -// If debugging is enabled and expr is false, abort program. Meant for checking -// caller-supplied parameters and operations that are outside the control of the -// module. A failed requirement indicates a bug outside the module. -// void require( bool expr ); -#undef require -#define require( expr ) assert( expr ) - -// Like printf() except output goes to debug log file. Might be defined to do -// nothing (not even evaluate its arguments). -// void dprintf( const char* format, ... ); -static inline void blargg_dprintf_( const char*, ... ) { } -#undef dprintf -#define dprintf (1) ? (void) 0 : blargg_dprintf_ - -// If enabled, evaluate expr and if false, make debug log entry with source file -// and line. Meant for finding situations that should be examined further, but that -// don't indicate a problem. In all cases, execution continues normally. -#undef check -#define check( expr ) ((void) 0) - -// If expr yields error string, return it from current function, otherwise continue. -#undef RETURN_ERR -#define RETURN_ERR( expr ) do { \ - blargg_err_t blargg_return_err_ = (expr); \ - if ( blargg_return_err_ ) return blargg_return_err_; \ - } while ( 0 ) - -// If ptr is 0, return out of memory error string. -#undef CHECK_ALLOC -#define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 ) - -// Avoid any macros which evaluate their arguments multiple times -#undef min -#undef max - -#define DEF_MIN_MAX( type ) \ - static inline type min( type x, type y ) { if ( x < y ) return x; return y; }\ - static inline type max( type x, type y ) { if ( y < x ) return x; return y; } - -DEF_MIN_MAX( int ) -DEF_MIN_MAX( unsigned ) -DEF_MIN_MAX( long ) -DEF_MIN_MAX( unsigned long ) -DEF_MIN_MAX( float ) -DEF_MIN_MAX( double ) - -#undef DEF_MIN_MAX - -/* -// using const references generates crappy code, and I am currenly only using these -// for built-in types, so they take arguments by value - -// TODO: remove -inline int min( int x, int y ) -template -inline T min( T x, T y ) -{ - if ( x < y ) - return x; - return y; -} - -template -inline T max( T x, T y ) -{ - if ( x < y ) - return y; - return x; -} -*/ - -// TODO: good idea? bad idea? -#undef byte -#define byte byte_ -typedef unsigned char byte; - -// deprecated -#define BLARGG_CHECK_ALLOC CHECK_ALLOC -#define BLARGG_RETURN_ERR RETURN_ERR - -// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf and check -#ifdef BLARGG_SOURCE_BEGIN - #include BLARGG_SOURCE_BEGIN -#endif - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/dsp/dsp.cpp b/waterbox/libsnes/bsnes/snes/alt/dsp/dsp.cpp deleted file mode 100644 index c6c6c64de5..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/dsp/dsp.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include - -#define DSP_CPP -namespace SNES { - -DSP dsp; - -#include "SPC_DSP.cpp" - -void DSP::step(unsigned clocks) { - clock += clocks; -} - -void DSP::synchronize_smp() { - if(SMP::Threaded == true) { - if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(smp.thread); - } else { - while(clock >= 0) smp.enter(); - } -} - -void DSP::enter() { - spc_dsp.run(1); - step(24); - - signed count = spc_dsp.sample_count(); - if(count > 0) { - for(unsigned n = 0; n < count; n += 2) audio.sample(samplebuffer[n + 0], samplebuffer[n + 1]); - spc_dsp.set_output(samplebuffer, 8192); - } -} - -uint8 DSP::read(uint8 addr) { - return spc_dsp.read(addr); -} - -void DSP::write(uint8 addr, uint8 data) { - spc_dsp.write(addr, data); -} - -void DSP::power() { - spc_dsp.init(smp.apuram); - spc_dsp.reset(); - spc_dsp.set_output(samplebuffer, 8192); -} - -void DSP::reset() { - spc_dsp.soft_reset(); - spc_dsp.set_output(samplebuffer, 8192); -} - -void DSP::channel_enable(unsigned channel, bool enable) { - channel_enabled[channel & 7] = enable; - unsigned mask = 0; - for(unsigned i = 0; i < 8; i++) { - if(channel_enabled[i] == false) mask |= 1 << i; - } - spc_dsp.mute_voices(mask); -} - -DSP::DSP() { - for(unsigned i = 0; i < 8; i++) channel_enabled[i] = true; -} - -} diff --git a/waterbox/libsnes/bsnes/snes/alt/dsp/dsp.hpp b/waterbox/libsnes/bsnes/snes/alt/dsp/dsp.hpp deleted file mode 100644 index 79c4e4c42c..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/dsp/dsp.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "SPC_DSP.h" - -class DSP : public Processor { -public: - enum : bool { Threaded = false }; - alwaysinline void step(unsigned clocks); - alwaysinline void synchronize_smp(); - - uint8 read(uint8 addr); - void write(uint8 addr, uint8 data); - - void enter(); - void power(); - void reset(); - - void channel_enable(unsigned channel, bool enable); - - DSP(); - -private: - SPC_DSP spc_dsp; - int16 samplebuffer[8192]; - bool channel_enabled[8]; -}; - -extern DSP dsp; diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/memory/memory.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/memory/memory.cpp deleted file mode 100644 index 3f120d84f0..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/memory/memory.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#ifdef PPU_CPP - -void PPU::latch_counters() { - regs.hcounter = cpu.hdot(); - regs.vcounter = cpu.vcounter(); - regs.counters_latched = true; -} - -uint16 PPU::get_vram_address() { - uint16 addr = regs.vram_addr; - switch(regs.vram_mapping) { - case 0: break; //direct mapping - case 1: addr = (addr & 0xff00) | ((addr & 0x001f) << 3) | ((addr >> 5) & 7); break; - case 2: addr = (addr & 0xfe00) | ((addr & 0x003f) << 3) | ((addr >> 6) & 7); break; - case 3: addr = (addr & 0xfc00) | ((addr & 0x007f) << 3) | ((addr >> 7) & 7); break; - } - return (addr << 1); -} - -//NOTE: all VRAM writes during active display are invalid. Unlike OAM and CGRAM, they will -//not be written anywhere at all. The below address ranges for where writes are invalid have -//been validated on hardware, as has the edge case where the S-CPU MDR can be written if the -//write occurs during the very last clock cycle of vblank. - -uint8 PPU::vram_mmio_read(uint16 addr) { - uint8 data; - - if(regs.display_disabled == true) { - data = vram[addr]; - } else { - uint16 v = cpu.vcounter(); - uint16 h = cpu.hcounter(); - uint16 ls = ((system.region() == System::Region::NTSC ? 525 : 625) >> 1) - 1; - if(interlace() && !cpu.field()) ls++; - - if(v == ls && h == 1362) { - data = 0x00; - } else if(v < (!overscan() ? 224 : 239)) { - data = 0x00; - } else if(v == (!overscan() ? 224 : 239)) { - if(h == 1362) { - data = vram[addr]; - } else { - data = 0x00; - } - } else { - data = vram[addr]; - } - } - - return data; -} - -void PPU::vram_mmio_write(uint16 addr, uint8 data) { - if(regs.display_disabled == true) { - vram[addr] = data; - } else { - uint16 v = cpu.vcounter(); - uint16 h = cpu.hcounter(); - if(v == 0) { - if(h <= 4) { - vram[addr] = data; - } else if(h == 6) { - vram[addr] = cpu.regs.mdr; - } else { - //no write - } - } else if(v < (!overscan() ? 225 : 240)) { - //no write - } else if(v == (!overscan() ? 225 : 240)) { - if(h <= 4) { - //no write - } else { - vram[addr] = data; - } - } else { - vram[addr] = data; - } - } -} - -uint8 PPU::oam_mmio_read(uint16 addr) { - addr &= 0x03ff; - if(addr & 0x0200) addr &= 0x021f; - uint8 data; - - if(regs.display_disabled == true) { - data = oam[addr]; - } else { - if(cpu.vcounter() < (!overscan() ? 225 : 240)) { - data = oam[regs.ioamaddr]; - } else { - data = oam[addr]; - } - } - - return data; -} - -void PPU::oam_mmio_write(uint16 addr, uint8 data) { - addr &= 0x03ff; - if(addr & 0x0200) addr &= 0x021f; - - sprite_list_valid = false; - - if(regs.display_disabled == true) { - oam[addr] = data; - update_sprite_list(addr, data); - } else { - if(cpu.vcounter() < (!overscan() ? 225 : 240)) { - oam[regs.ioamaddr] = data; - update_sprite_list(regs.ioamaddr, data); - } else { - oam[addr] = data; - update_sprite_list(addr, data); - } - } -} - -uint8 PPU::cgram_mmio_read(uint16 addr) { - addr &= 0x01ff; - uint8 data; - - if(1 || regs.display_disabled == true) { - data = cgram[addr]; - } else { - uint16 v = cpu.vcounter(); - uint16 h = cpu.hcounter(); - if(v < (!overscan() ? 225 : 240) && h >= 128 && h < 1096) { - data = cgram[regs.icgramaddr] & 0x7f; - } else { - data = cgram[addr]; - } - } - - if(addr & 1) data &= 0x7f; - return data; -} - -void PPU::cgram_mmio_write(uint16 addr, uint8 data) { - addr &= 0x01ff; - if(addr & 1) data &= 0x7f; - - if(1 || regs.display_disabled == true) { - cgram[addr] = data; - } else { - uint16 v = cpu.vcounter(); - uint16 h = cpu.hcounter(); - if(v < (!overscan() ? 225 : 240) && h >= 128 && h < 1096) { - cgram[regs.icgramaddr] = data & 0x7f; - } else { - cgram[addr] = data; - } - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/memory/memory.hpp b/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/memory/memory.hpp deleted file mode 100644 index 3af9a56ec2..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/memory/memory.hpp +++ /dev/null @@ -1,10 +0,0 @@ -uint16 get_vram_address(); - -uint8 vram_mmio_read(uint16 addr); -void vram_mmio_write(uint16 addr, uint8 data); - -uint8 oam_mmio_read(uint16 addr); -void oam_mmio_write(uint16 addr, uint8 data); - -uint8 cgram_mmio_read(uint16 addr); -void cgram_mmio_write(uint16 addr, uint8 data); diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/mmio/mmio.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/mmio/mmio.cpp deleted file mode 100644 index aedb67c173..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/mmio/mmio.cpp +++ /dev/null @@ -1,671 +0,0 @@ -#ifdef PPU_CPP - -//INIDISP -void PPU::mmio_w2100(uint8 value) { - if(regs.display_disabled == true && cpu.vcounter() == (!overscan() ? 225 : 240)) { - regs.oam_addr = regs.oam_baseaddr << 1; - regs.oam_firstsprite = (regs.oam_priority == false) ? 0 : (regs.oam_addr >> 2) & 127; - } - - regs.display_disabled = !!(value & 0x80); - regs.display_brightness = value & 15; -} - -//OBSEL -void PPU::mmio_w2101(uint8 value) { - regs.oam_basesize = (value >> 5) & 7; - regs.oam_nameselect = (value >> 3) & 3; - regs.oam_tdaddr = (value & 3) << 14; -} - -//OAMADDL -void PPU::mmio_w2102(uint8 data) { - regs.oam_baseaddr = (regs.oam_baseaddr & ~0xff) | (data << 0); - regs.oam_baseaddr &= 0x01ff; - regs.oam_addr = regs.oam_baseaddr << 1; - regs.oam_firstsprite = (regs.oam_priority == false) ? 0 : (regs.oam_addr >> 2) & 127; -} - -//OAMADDH -void PPU::mmio_w2103(uint8 data) { - regs.oam_priority = !!(data & 0x80); - regs.oam_baseaddr = (regs.oam_baseaddr & 0xff) | (data << 8); - regs.oam_baseaddr &= 0x01ff; - regs.oam_addr = regs.oam_baseaddr << 1; - regs.oam_firstsprite = (regs.oam_priority == false) ? 0 : (regs.oam_addr >> 2) & 127; -} - -//OAMDATA -void PPU::mmio_w2104(uint8 data) { - if((regs.oam_addr & 1) == 0) regs.oam_latchdata = data; - - if(regs.oam_addr & 0x0200) { - oam_mmio_write(regs.oam_addr, data); - } else if((regs.oam_addr & 1) == 1) { - oam_mmio_write((regs.oam_addr & ~1) + 0, regs.oam_latchdata); - oam_mmio_write((regs.oam_addr & ~1) + 1, data); - } - - regs.oam_addr++; - regs.oam_addr &= 0x03ff; - regs.oam_firstsprite = (regs.oam_priority == false) ? 0 : (regs.oam_addr >> 2) & 127; -} - -//BGMODE -void PPU::mmio_w2105(uint8 value) { - regs.bg_tilesize[BG4] = !!(value & 0x80); - regs.bg_tilesize[BG3] = !!(value & 0x40); - regs.bg_tilesize[BG2] = !!(value & 0x20); - regs.bg_tilesize[BG1] = !!(value & 0x10); - regs.bg3_priority = !!(value & 0x08); - regs.bg_mode = (value & 7); -} - -//MOSAIC -void PPU::mmio_w2106(uint8 value) { - regs.mosaic_size = (value >> 4) & 15; - regs.mosaic_enabled[BG4] = !!(value & 0x08); - regs.mosaic_enabled[BG3] = !!(value & 0x04); - regs.mosaic_enabled[BG2] = !!(value & 0x02); - regs.mosaic_enabled[BG1] = !!(value & 0x01); -} - -//BG1SC -void PPU::mmio_w2107(uint8 value) { - regs.bg_scaddr[BG1] = (value & 0x7c) << 9; - regs.bg_scsize[BG1] = value & 3; -} - -//BG2SC -void PPU::mmio_w2108(uint8 value) { - regs.bg_scaddr[BG2] = (value & 0x7c) << 9; - regs.bg_scsize[BG2] = value & 3; -} - -//BG3SC -void PPU::mmio_w2109(uint8 value) { - regs.bg_scaddr[BG3] = (value & 0x7c) << 9; - regs.bg_scsize[BG3] = value & 3; -} - -//BG4SC -void PPU::mmio_w210a(uint8 value) { - regs.bg_scaddr[BG4] = (value & 0x7c) << 9; - regs.bg_scsize[BG4] = value & 3; -} - -//BG12NBA -void PPU::mmio_w210b(uint8 value) { - regs.bg_tdaddr[BG1] = (value & 0x07) << 13; - regs.bg_tdaddr[BG2] = (value & 0x70) << 9; -} - -//BG34NBA -void PPU::mmio_w210c(uint8 value) { - regs.bg_tdaddr[BG3] = (value & 0x07) << 13; - regs.bg_tdaddr[BG4] = (value & 0x70) << 9; -} - -//BG1HOFS -void PPU::mmio_w210d(uint8 value) { - regs.m7_hofs = (value << 8) | regs.m7_latch; - regs.m7_latch = value; - - regs.bg_hofs[BG1] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG1] >> 8) & 7); - regs.bg_ofslatch = value; -} - -//BG1VOFS -void PPU::mmio_w210e(uint8 value) { - regs.m7_vofs = (value << 8) | regs.m7_latch; - regs.m7_latch = value; - - regs.bg_vofs[BG1] = (value << 8) | (regs.bg_ofslatch); - regs.bg_ofslatch = value; -} - -//BG2HOFS -void PPU::mmio_w210f(uint8 value) { - regs.bg_hofs[BG2] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG2] >> 8) & 7); - regs.bg_ofslatch = value; -} - -//BG2VOFS -void PPU::mmio_w2110(uint8 value) { - regs.bg_vofs[BG2] = (value << 8) | (regs.bg_ofslatch); - regs.bg_ofslatch = value; -} - -//BG3HOFS -void PPU::mmio_w2111(uint8 value) { - regs.bg_hofs[BG3] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG3] >> 8) & 7); - regs.bg_ofslatch = value; -} - -//BG3VOFS -void PPU::mmio_w2112(uint8 value) { - regs.bg_vofs[BG3] = (value << 8) | (regs.bg_ofslatch); - regs.bg_ofslatch = value; -} - -//BG4HOFS -void PPU::mmio_w2113(uint8 value) { - regs.bg_hofs[BG4] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG4] >> 8) & 7); - regs.bg_ofslatch = value; -} - -//BG4VOFS -void PPU::mmio_w2114(uint8 value) { - regs.bg_vofs[BG4] = (value << 8) | (regs.bg_ofslatch); - regs.bg_ofslatch = value; -} - -//VMAIN -void PPU::mmio_w2115(uint8 value) { - regs.vram_incmode = !!(value & 0x80); - regs.vram_mapping = (value >> 2) & 3; - switch(value & 3) { - case 0: regs.vram_incsize = 1; break; - case 1: regs.vram_incsize = 32; break; - case 2: regs.vram_incsize = 128; break; - case 3: regs.vram_incsize = 128; break; - } -} - -//VMADDL -void PPU::mmio_w2116(uint8 value) { - regs.vram_addr = (regs.vram_addr & 0xff00) | value; - uint16 addr = get_vram_address(); - regs.vram_readbuffer = vram_mmio_read(addr + 0); - regs.vram_readbuffer |= vram_mmio_read(addr + 1) << 8; -} - -//VMADDH -void PPU::mmio_w2117(uint8 value) { - regs.vram_addr = (value << 8) | (regs.vram_addr & 0x00ff); - uint16 addr = get_vram_address(); - regs.vram_readbuffer = vram_mmio_read(addr + 0); - regs.vram_readbuffer |= vram_mmio_read(addr + 1) << 8; -} - -//VMDATAL -void PPU::mmio_w2118(uint8 value) { -uint16 addr = get_vram_address(); - vram_mmio_write(addr, value); - bg_tiledata_state[TILE_2BIT][(addr >> 4)] = 1; - bg_tiledata_state[TILE_4BIT][(addr >> 5)] = 1; - bg_tiledata_state[TILE_8BIT][(addr >> 6)] = 1; - - if(regs.vram_incmode == 0) { - regs.vram_addr += regs.vram_incsize; - } -} - -//VMDATAH -void PPU::mmio_w2119(uint8 value) { -uint16 addr = get_vram_address() + 1; - vram_mmio_write(addr, value); - bg_tiledata_state[TILE_2BIT][(addr >> 4)] = 1; - bg_tiledata_state[TILE_4BIT][(addr >> 5)] = 1; - bg_tiledata_state[TILE_8BIT][(addr >> 6)] = 1; - - if(regs.vram_incmode == 1) { - regs.vram_addr += regs.vram_incsize; - } -} - -//M7SEL -void PPU::mmio_w211a(uint8 value) { - regs.mode7_repeat = (value >> 6) & 3; - regs.mode7_vflip = !!(value & 0x02); - regs.mode7_hflip = !!(value & 0x01); -} - -//M7A -void PPU::mmio_w211b(uint8 value) { - regs.m7a = (value << 8) | regs.m7_latch; - regs.m7_latch = value; -} - -//M7B -void PPU::mmio_w211c(uint8 value) { - regs.m7b = (value << 8) | regs.m7_latch; - regs.m7_latch = value; -} - -//M7C -void PPU::mmio_w211d(uint8 value) { - regs.m7c = (value << 8) | regs.m7_latch; - regs.m7_latch = value; -} - -//M7D -void PPU::mmio_w211e(uint8 value) { - regs.m7d = (value << 8) | regs.m7_latch; - regs.m7_latch = value; -} - -//M7X -void PPU::mmio_w211f(uint8 value) { - regs.m7x = (value << 8) | regs.m7_latch; - regs.m7_latch = value; -} - -//M7Y -void PPU::mmio_w2120(uint8 value) { - regs.m7y = (value << 8) | regs.m7_latch; - regs.m7_latch = value; -} - -//CGADD -void PPU::mmio_w2121(uint8 value) { - regs.cgram_addr = value << 1; -} - -//CGDATA -//note: CGRAM palette data format is 15-bits -//(0,bbbbb,ggggg,rrrrr). Highest bit is ignored, -//as evidenced by $213b CGRAM data reads. -// -//anomie indicates writes to CGDATA work the same -//as writes to OAMDATA's low table. need to verify -//this on hardware. -void PPU::mmio_w2122(uint8 value) { - if(!(regs.cgram_addr & 1)) { - regs.cgram_latchdata = value; - } else { - cgram_mmio_write((regs.cgram_addr & 0x01fe), regs.cgram_latchdata); - cgram_mmio_write((regs.cgram_addr & 0x01fe) + 1, value & 0x7f); - } - regs.cgram_addr++; - regs.cgram_addr &= 0x01ff; -} - -//W12SEL -void PPU::mmio_w2123(uint8 value) { - regs.window2_enabled[BG2] = !!(value & 0x80); - regs.window2_invert [BG2] = !!(value & 0x40); - regs.window1_enabled[BG2] = !!(value & 0x20); - regs.window1_invert [BG2] = !!(value & 0x10); - regs.window2_enabled[BG1] = !!(value & 0x08); - regs.window2_invert [BG1] = !!(value & 0x04); - regs.window1_enabled[BG1] = !!(value & 0x02); - regs.window1_invert [BG1] = !!(value & 0x01); -} - -//W34SEL -void PPU::mmio_w2124(uint8 value) { - regs.window2_enabled[BG4] = !!(value & 0x80); - regs.window2_invert [BG4] = !!(value & 0x40); - regs.window1_enabled[BG4] = !!(value & 0x20); - regs.window1_invert [BG4] = !!(value & 0x10); - regs.window2_enabled[BG3] = !!(value & 0x08); - regs.window2_invert [BG3] = !!(value & 0x04); - regs.window1_enabled[BG3] = !!(value & 0x02); - regs.window1_invert [BG3] = !!(value & 0x01); -} - -//WOBJSEL -void PPU::mmio_w2125(uint8 value) { - regs.window2_enabled[COL] = !!(value & 0x80); - regs.window2_invert [COL] = !!(value & 0x40); - regs.window1_enabled[COL] = !!(value & 0x20); - regs.window1_invert [COL] = !!(value & 0x10); - regs.window2_enabled[OAM] = !!(value & 0x08); - regs.window2_invert [OAM] = !!(value & 0x04); - regs.window1_enabled[OAM] = !!(value & 0x02); - regs.window1_invert [OAM] = !!(value & 0x01); -} - -//WH0 -void PPU::mmio_w2126(uint8 value) { - regs.window1_left = value; -} - -//WH1 -void PPU::mmio_w2127(uint8 value) { - regs.window1_right = value; -} - -//WH2 -void PPU::mmio_w2128(uint8 value) { - regs.window2_left = value; -} - -//WH3 -void PPU::mmio_w2129(uint8 value) { - regs.window2_right = value; -} - -//WBGLOG -void PPU::mmio_w212a(uint8 value) { - regs.window_mask[BG4] = (value >> 6) & 3; - regs.window_mask[BG3] = (value >> 4) & 3; - regs.window_mask[BG2] = (value >> 2) & 3; - regs.window_mask[BG1] = (value ) & 3; -} - -//WOBJLOG -void PPU::mmio_w212b(uint8 value) { - regs.window_mask[COL] = (value >> 2) & 3; - regs.window_mask[OAM] = (value ) & 3; -} - -//TM -void PPU::mmio_w212c(uint8 value) { - regs.bg_enabled[OAM] = !!(value & 0x10); - regs.bg_enabled[BG4] = !!(value & 0x08); - regs.bg_enabled[BG3] = !!(value & 0x04); - regs.bg_enabled[BG2] = !!(value & 0x02); - regs.bg_enabled[BG1] = !!(value & 0x01); -} - -//TS -void PPU::mmio_w212d(uint8 value) { - regs.bgsub_enabled[OAM] = !!(value & 0x10); - regs.bgsub_enabled[BG4] = !!(value & 0x08); - regs.bgsub_enabled[BG3] = !!(value & 0x04); - regs.bgsub_enabled[BG2] = !!(value & 0x02); - regs.bgsub_enabled[BG1] = !!(value & 0x01); -} - -//TMW -void PPU::mmio_w212e(uint8 value) { - regs.window_enabled[OAM] = !!(value & 0x10); - regs.window_enabled[BG4] = !!(value & 0x08); - regs.window_enabled[BG3] = !!(value & 0x04); - regs.window_enabled[BG2] = !!(value & 0x02); - regs.window_enabled[BG1] = !!(value & 0x01); -} - -//TSW -void PPU::mmio_w212f(uint8 value) { - regs.sub_window_enabled[OAM] = !!(value & 0x10); - regs.sub_window_enabled[BG4] = !!(value & 0x08); - regs.sub_window_enabled[BG3] = !!(value & 0x04); - regs.sub_window_enabled[BG2] = !!(value & 0x02); - regs.sub_window_enabled[BG1] = !!(value & 0x01); -} - -//CGWSEL -void PPU::mmio_w2130(uint8 value) { - regs.color_mask = (value >> 6) & 3; - regs.colorsub_mask = (value >> 4) & 3; - regs.addsub_mode = !!(value & 0x02); - regs.direct_color = !!(value & 0x01); -} - -//CGADDSUB -void PPU::mmio_w2131(uint8 value) { - regs.color_mode = !!(value & 0x80); - regs.color_halve = !!(value & 0x40); - regs.color_enabled[BACK] = !!(value & 0x20); - regs.color_enabled[OAM] = !!(value & 0x10); - regs.color_enabled[BG4] = !!(value & 0x08); - regs.color_enabled[BG3] = !!(value & 0x04); - regs.color_enabled[BG2] = !!(value & 0x02); - regs.color_enabled[BG1] = !!(value & 0x01); -} - -//COLDATA -void PPU::mmio_w2132(uint8 value) { - if(value & 0x80) regs.color_b = value & 0x1f; - if(value & 0x40) regs.color_g = value & 0x1f; - if(value & 0x20) regs.color_r = value & 0x1f; - - regs.color_rgb = (regs.color_r) - | (regs.color_g << 5) - | (regs.color_b << 10); -} - -//SETINI -void PPU::mmio_w2133(uint8 value) { - regs.mode7_extbg = !!(value & 0x40); - regs.pseudo_hires = !!(value & 0x08); - regs.overscan = !!(value & 0x04); - regs.oam_interlace = !!(value & 0x02); - regs.interlace = !!(value & 0x01); - - display.overscan = regs.overscan; - sprite_list_valid = false; -} - -//MPYL -uint8 PPU::mmio_r2134() { -uint32 r; - r = ((int16)regs.m7a * (int8)(regs.m7b >> 8)); - regs.ppu1_mdr = r; - return regs.ppu1_mdr; -} - -//MPYM -uint8 PPU::mmio_r2135() { -uint32 r; - r = ((int16)regs.m7a * (int8)(regs.m7b >> 8)); - regs.ppu1_mdr = r >> 8; - return regs.ppu1_mdr; -} - -//MPYH -uint8 PPU::mmio_r2136() { -uint32 r; - r = ((int16)regs.m7a * (int8)(regs.m7b >> 8)); - regs.ppu1_mdr = r >> 16; - return regs.ppu1_mdr; -} - -//SLHV -uint8 PPU::mmio_r2137() { - if(cpu.pio() & 0x80) { - latch_counters(); - } - return cpu.regs.mdr; -} - -//OAMDATAREAD -uint8 PPU::mmio_r2138() { - regs.ppu1_mdr = oam_mmio_read(regs.oam_addr); - - regs.oam_addr++; - regs.oam_addr &= 0x03ff; - regs.oam_firstsprite = (regs.oam_priority == false) ? 0 : (regs.oam_addr >> 2) & 127; - - return regs.ppu1_mdr; -} - -//VMDATALREAD -uint8 PPU::mmio_r2139() { -uint16 addr = get_vram_address(); - regs.ppu1_mdr = regs.vram_readbuffer; - if(regs.vram_incmode == 0) { - addr &= 0xfffe; - regs.vram_readbuffer = vram_mmio_read(addr + 0); - regs.vram_readbuffer |= vram_mmio_read(addr + 1) << 8; - regs.vram_addr += regs.vram_incsize; - } - return regs.ppu1_mdr; -} - -//VMDATAHREAD -uint8 PPU::mmio_r213a() { -uint16 addr = get_vram_address() + 1; - regs.ppu1_mdr = regs.vram_readbuffer >> 8; - if(regs.vram_incmode == 1) { - addr &= 0xfffe; - regs.vram_readbuffer = vram_mmio_read(addr + 0); - regs.vram_readbuffer |= vram_mmio_read(addr + 1) << 8; - regs.vram_addr += regs.vram_incsize; - } - return regs.ppu1_mdr; -} - -//CGDATAREAD -//note: CGRAM palette data is 15-bits (0,bbbbb,ggggg,rrrrr) -//therefore, the high byte read from each color does not -//update bit 7 of the PPU2 MDR. -uint8 PPU::mmio_r213b() { - if(!(regs.cgram_addr & 1)) { - regs.ppu2_mdr = cgram_mmio_read(regs.cgram_addr) & 0xff; - } else { - regs.ppu2_mdr &= 0x80; - regs.ppu2_mdr |= cgram_mmio_read(regs.cgram_addr) & 0x7f; - } - regs.cgram_addr++; - regs.cgram_addr &= 0x01ff; - return regs.ppu2_mdr; -} - -//OPHCT -uint8 PPU::mmio_r213c() { - if(!regs.latch_hcounter) { - regs.ppu2_mdr = regs.hcounter & 0xff; - } else { - regs.ppu2_mdr &= 0xfe; - regs.ppu2_mdr |= (regs.hcounter >> 8) & 1; - } - regs.latch_hcounter ^= 1; - return regs.ppu2_mdr; -} - -//OPVCT -uint8 PPU::mmio_r213d() { - if(!regs.latch_vcounter) { - regs.ppu2_mdr = regs.vcounter & 0xff; - } else { - regs.ppu2_mdr &= 0xfe; - regs.ppu2_mdr |= (regs.vcounter >> 8) & 1; - } - regs.latch_vcounter ^= 1; - return regs.ppu2_mdr; -} - -//STAT77 -uint8 PPU::mmio_r213e() { -uint8 r = 0x00; - r |= (regs.time_over) ? 0x80 : 0x00; - r |= (regs.range_over) ? 0x40 : 0x00; - r |= (regs.ppu1_mdr & 0x10); - r |= (ppu1_version & 0x0f); - regs.ppu1_mdr = r; - return regs.ppu1_mdr; -} - -//STAT78 -uint8 PPU::mmio_r213f() { -uint8 r = 0x00; - regs.latch_hcounter = 0; - regs.latch_vcounter = 0; - - r |= cpu.field() << 7; - if(!(cpu.pio() & 0x80)) { - r |= 0x40; - } else if(regs.counters_latched == true) { - r |= 0x40; - regs.counters_latched = false; - } - r |= (regs.ppu2_mdr & 0x20); - r |= (region << 4); //0 = NTSC, 1 = PAL - r |= (ppu2_version & 0x0f); - regs.ppu2_mdr = r; - return regs.ppu2_mdr; -} - -uint8 PPU::mmio_read(unsigned addr) { - cpu.synchronize_ppu(); - - switch(addr & 0xffff) { - case 0x2104: - case 0x2105: - case 0x2106: - case 0x2108: - case 0x2109: - case 0x210a: - case 0x2114: - case 0x2115: - case 0x2116: - case 0x2118: - case 0x2119: - case 0x211a: - case 0x2124: - case 0x2125: - case 0x2126: - case 0x2128: - case 0x2129: - case 0x212a: return regs.ppu1_mdr; - case 0x2134: return mmio_r2134(); //MPYL - case 0x2135: return mmio_r2135(); //MPYM - case 0x2136: return mmio_r2136(); //MPYH - case 0x2137: return mmio_r2137(); //SLHV - case 0x2138: return mmio_r2138(); //OAMDATAREAD - case 0x2139: return mmio_r2139(); //VMDATALREAD - case 0x213a: return mmio_r213a(); //VMDATAHREAD - case 0x213b: return mmio_r213b(); //CGDATAREAD - case 0x213c: return mmio_r213c(); //OPHCT - case 0x213d: return mmio_r213d(); //OPVCT - case 0x213e: return mmio_r213e(); //STAT77 - case 0x213f: return mmio_r213f(); //STAT78 - } - - return cpu.regs.mdr; -} - -void PPU::mmio_write(unsigned addr, uint8 data) { - cpu.synchronize_ppu(); - - switch(addr & 0xffff) { - case 0x2100: return mmio_w2100(data); //INIDISP - case 0x2101: return mmio_w2101(data); //OBSEL - case 0x2102: return mmio_w2102(data); //OAMADDL - case 0x2103: return mmio_w2103(data); //OAMADDH - case 0x2104: return mmio_w2104(data); //OAMDATA - case 0x2105: return mmio_w2105(data); //BGMODE - case 0x2106: return mmio_w2106(data); //MOSAIC - case 0x2107: return mmio_w2107(data); //BG1SC - case 0x2108: return mmio_w2108(data); //BG2SC - case 0x2109: return mmio_w2109(data); //BG3SC - case 0x210a: return mmio_w210a(data); //BG4SC - case 0x210b: return mmio_w210b(data); //BG12NBA - case 0x210c: return mmio_w210c(data); //BG34NBA - case 0x210d: return mmio_w210d(data); //BG1HOFS - case 0x210e: return mmio_w210e(data); //BG1VOFS - case 0x210f: return mmio_w210f(data); //BG2HOFS - case 0x2110: return mmio_w2110(data); //BG2VOFS - case 0x2111: return mmio_w2111(data); //BG3HOFS - case 0x2112: return mmio_w2112(data); //BG3VOFS - case 0x2113: return mmio_w2113(data); //BG4HOFS - case 0x2114: return mmio_w2114(data); //BG4VOFS - case 0x2115: return mmio_w2115(data); //VMAIN - case 0x2116: return mmio_w2116(data); //VMADDL - case 0x2117: return mmio_w2117(data); //VMADDH - case 0x2118: return mmio_w2118(data); //VMDATAL - case 0x2119: return mmio_w2119(data); //VMDATAH - case 0x211a: return mmio_w211a(data); //M7SEL - case 0x211b: return mmio_w211b(data); //M7A - case 0x211c: return mmio_w211c(data); //M7B - case 0x211d: return mmio_w211d(data); //M7C - case 0x211e: return mmio_w211e(data); //M7D - case 0x211f: return mmio_w211f(data); //M7X - case 0x2120: return mmio_w2120(data); //M7Y - case 0x2121: return mmio_w2121(data); //CGADD - case 0x2122: return mmio_w2122(data); //CGDATA - case 0x2123: return mmio_w2123(data); //W12SEL - case 0x2124: return mmio_w2124(data); //W34SEL - case 0x2125: return mmio_w2125(data); //WOBJSEL - case 0x2126: return mmio_w2126(data); //WH0 - case 0x2127: return mmio_w2127(data); //WH1 - case 0x2128: return mmio_w2128(data); //WH2 - case 0x2129: return mmio_w2129(data); //WH3 - case 0x212a: return mmio_w212a(data); //WBGLOG - case 0x212b: return mmio_w212b(data); //WOBJLOG - case 0x212c: return mmio_w212c(data); //TM - case 0x212d: return mmio_w212d(data); //TS - case 0x212e: return mmio_w212e(data); //TMW - case 0x212f: return mmio_w212f(data); //TSW - case 0x2130: return mmio_w2130(data); //CGWSEL - case 0x2131: return mmio_w2131(data); //CGADDSUB - case 0x2132: return mmio_w2132(data); //COLDATA - case 0x2133: return mmio_w2133(data); //SETINI - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/mmio/mmio.hpp b/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/mmio/mmio.hpp deleted file mode 100644 index aeb1c3a6a2..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/mmio/mmio.hpp +++ /dev/null @@ -1,202 +0,0 @@ -struct { - //open bus support - uint8 ppu1_mdr, ppu2_mdr; - - //bg line counters - uint16 bg_y[4]; - - //internal state - uint16 ioamaddr; - uint16 icgramaddr; - - //$2100 - bool display_disabled; - uint8 display_brightness; - - //$2101 - uint8 oam_basesize; - uint8 oam_nameselect; - uint16 oam_tdaddr; - - //$2102-$2103 - uint16 oam_baseaddr; - uint16 oam_addr; - bool oam_priority; - uint8 oam_firstsprite; - - //$2104 - uint8 oam_latchdata; - - //$2105 - bool bg_tilesize[4]; - bool bg3_priority; - uint8 bg_mode; - - //$2106 - uint8 mosaic_size; - bool mosaic_enabled[4]; - uint16 mosaic_countdown; - - //$2107-$210a - uint16 bg_scaddr[4]; - uint8 bg_scsize[4]; - - //$210b-$210c - uint16 bg_tdaddr[4]; - - //$210d-$2114 - uint8 bg_ofslatch; - uint16 m7_hofs, m7_vofs; - uint16 bg_hofs[4]; - uint16 bg_vofs[4]; - - //$2115 - bool vram_incmode; - uint8 vram_mapping; - uint8 vram_incsize; - - //$2116-$2117 - uint16 vram_addr; - - //$211a - uint8 mode7_repeat; - bool mode7_vflip; - bool mode7_hflip; - - //$211b-$2120 - uint8 m7_latch; - uint16 m7a, m7b, m7c, m7d, m7x, m7y; - - //$2121 - uint16 cgram_addr; - - //$2122 - uint8 cgram_latchdata; - - //$2123-$2125 - bool window1_enabled[6]; - bool window1_invert [6]; - bool window2_enabled[6]; - bool window2_invert [6]; - - //$2126-$2129 - uint8 window1_left, window1_right; - uint8 window2_left, window2_right; - - //$212a-$212b - uint8 window_mask[6]; - - //$212c-$212d - bool bg_enabled[5], bgsub_enabled[5]; - - //$212e-$212f - bool window_enabled[5], sub_window_enabled[5]; - - //$2130 - uint8 color_mask, colorsub_mask; - bool addsub_mode; - bool direct_color; - - //$2131 - bool color_mode, color_halve; - bool color_enabled[6]; - - //$2132 - uint8 color_r, color_g, color_b; - uint16 color_rgb; - - //$2133 - //overscan and interlace are checked once per frame to - //determine if entire frame should be interlaced/non-interlace - //and overscan adjusted. therefore, the variables act sort of - //like a buffer, but they do still affect internal rendering - bool mode7_extbg; - bool pseudo_hires; - bool overscan; - uint16 scanlines; - bool oam_interlace; - bool interlace; - - //$2137 - uint16 hcounter, vcounter; - bool latch_hcounter, latch_vcounter; - bool counters_latched; - - //$2139-$213a - uint16 vram_readbuffer; - - //$213e - bool time_over, range_over; - uint16 oam_itemcount, oam_tilecount; -} regs; - -void mmio_w2100(uint8 value); //INIDISP -void mmio_w2101(uint8 value); //OBSEL -void mmio_w2102(uint8 value); //OAMADDL -void mmio_w2103(uint8 value); //OAMADDH -void mmio_w2104(uint8 value); //OAMDATA -void mmio_w2105(uint8 value); //BGMODE -void mmio_w2106(uint8 value); //MOSAIC -void mmio_w2107(uint8 value); //BG1SC -void mmio_w2108(uint8 value); //BG2SC -void mmio_w2109(uint8 value); //BG3SC -void mmio_w210a(uint8 value); //BG4SC -void mmio_w210b(uint8 value); //BG12NBA -void mmio_w210c(uint8 value); //BG34NBA -void mmio_w210d(uint8 value); //BG1HOFS -void mmio_w210e(uint8 value); //BG1VOFS -void mmio_w210f(uint8 value); //BG2HOFS -void mmio_w2110(uint8 value); //BG2VOFS -void mmio_w2111(uint8 value); //BG3HOFS -void mmio_w2112(uint8 value); //BG3VOFS -void mmio_w2113(uint8 value); //BG4HOFS -void mmio_w2114(uint8 value); //BG4VOFS -void mmio_w2115(uint8 value); //VMAIN -void mmio_w2116(uint8 value); //VMADDL -void mmio_w2117(uint8 value); //VMADDH -void mmio_w2118(uint8 value); //VMDATAL -void mmio_w2119(uint8 value); //VMDATAH -void mmio_w211a(uint8 value); //M7SEL -void mmio_w211b(uint8 value); //M7A -void mmio_w211c(uint8 value); //M7B -void mmio_w211d(uint8 value); //M7C -void mmio_w211e(uint8 value); //M7D -void mmio_w211f(uint8 value); //M7X -void mmio_w2120(uint8 value); //M7Y -void mmio_w2121(uint8 value); //CGADD -void mmio_w2122(uint8 value); //CGDATA -void mmio_w2123(uint8 value); //W12SEL -void mmio_w2124(uint8 value); //W34SEL -void mmio_w2125(uint8 value); //WOBJSEL -void mmio_w2126(uint8 value); //WH0 -void mmio_w2127(uint8 value); //WH1 -void mmio_w2128(uint8 value); //WH2 -void mmio_w2129(uint8 value); //WH3 -void mmio_w212a(uint8 value); //WBGLOG -void mmio_w212b(uint8 value); //WOBJLOG -void mmio_w212c(uint8 value); //TM -void mmio_w212d(uint8 value); //TS -void mmio_w212e(uint8 value); //TMW -void mmio_w212f(uint8 value); //TSW -void mmio_w2130(uint8 value); //CGWSEL -void mmio_w2131(uint8 value); //CGADDSUB -void mmio_w2132(uint8 value); //COLDATA -void mmio_w2133(uint8 value); //SETINI - -uint8 mmio_r2134(); //MPYL -uint8 mmio_r2135(); //MPYM -uint8 mmio_r2136(); //MPYH -uint8 mmio_r2137(); //SLHV -uint8 mmio_r2138(); //OAMDATAREAD -uint8 mmio_r2139(); //VMDATALREAD -uint8 mmio_r213a(); //VMDATAHREAD -uint8 mmio_r213b(); //CGDATAREAD -uint8 mmio_r213c(); //OPHCT -uint8 mmio_r213d(); //OPVCT -uint8 mmio_r213e(); //STAT77 -uint8 mmio_r213f(); //STAT78 - -uint8 mmio_read(unsigned addr); -void mmio_write(unsigned addr, uint8 data); - -void latch_counters(); diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/ppu.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/ppu.cpp deleted file mode 100644 index 46b21a9d54..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/ppu.cpp +++ /dev/null @@ -1,453 +0,0 @@ -#include - -#define PPU_CPP -namespace SNES { - -PPU ppu; - -#include "memory/memory.cpp" -#include "mmio/mmio.cpp" -#include "render/render.cpp" - -void PPU::step(unsigned clocks) { - clock += clocks; -} - -void PPU::synchronize_cpu() { - if(CPU::Threaded == true) { - if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); - } else { - while(clock >= 0) cpu.enter(); - } -} - -void PPU::Enter() { ppu.enter(); } - -void PPU::enter() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - //H = 0 (initialize) - scanline(); - add_clocks(10); - - //H = 10 (cache mode7 registers + OAM address reset) - cache.m7_hofs = regs.m7_hofs; - cache.m7_vofs = regs.m7_vofs; - cache.m7a = regs.m7a; - cache.m7b = regs.m7b; - cache.m7c = regs.m7c; - cache.m7d = regs.m7d; - cache.m7x = regs.m7x; - cache.m7y = regs.m7y; - if(vcounter() == (!overscan() ? 225 : 240)) { - if(regs.display_disabled == false) { - regs.oam_addr = regs.oam_baseaddr << 1; - regs.oam_firstsprite = (regs.oam_priority == false) ? 0 : (regs.oam_addr >> 2) & 127; - } - } - add_clocks(502); - - //H = 512 (render) - render_scanline(); - add_clocks(640); - - //H = 1152 (cache OBSEL) - if(cache.oam_basesize != regs.oam_basesize) { - cache.oam_basesize = regs.oam_basesize; - sprite_list_valid = false; - } - cache.oam_nameselect = regs.oam_nameselect; - cache.oam_tdaddr = regs.oam_tdaddr; - add_clocks(lineclocks() - 1152); //seek to start of next scanline - - } -} - -void PPU::add_clocks(unsigned clocks) { - tick(clocks); - step(clocks); - synchronize_cpu(); -} - -void PPU::scanline() { - line = vcounter(); - - if(line == 0) { - frame(); - - //RTO flag reset - regs.time_over = false; - regs.range_over = false; - } - - interface()->scanlineStart(line); - - if(line == 1) { - //mosaic reset - for(int bg = BG1; bg <= BG4; bg++) regs.bg_y[bg] = 1; - regs.mosaic_countdown = regs.mosaic_size + 1; - regs.mosaic_countdown--; - } else { - for(int bg = BG1; bg <= BG4; bg++) { - if(!regs.mosaic_enabled[bg] || !regs.mosaic_countdown) regs.bg_y[bg] = line; - } - if(!regs.mosaic_countdown) regs.mosaic_countdown = regs.mosaic_size + 1; - regs.mosaic_countdown--; - } -} - -void PPU::render_scanline() { - if(line >= 1 && line < (!overscan() ? 225 : 240)) { - if(framecounter) return; - render_line_oam_rto(); - render_line(); - } -} - -void PPU::frame() { - system.frame(); - - if(field() == 0) { - display.interlace = regs.interlace; - regs.scanlines = (regs.overscan == false) ? 224 : 239; - } - - framecounter = (frameskip == 0 ? 0 : (framecounter + 1) % frameskip); -} - -void PPU::enable() { - function read = { &PPU::mmio_read, (PPU*)&ppu }; - function write = { &PPU::mmio_write, (PPU*)&ppu }; - - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, read, write); - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, read, write); -} - -void PPU::power() { - ppu1_version = config.ppu1.version; - ppu2_version = config.ppu2.version; - - for(int i=0;i<128*1024;i++) vram[i] = 0; - for(int i=0;i<544;i++) oam[i] = 0; - for(int i=0;i<512;i++) cgram[i] = 0; - flush_tiledata_cache(); - - region = (system.region() == System::Region::NTSC ? 0 : 1); //0 = NTSC, 1 = PAL - - regs.ioamaddr = 0x0000; - regs.icgramaddr = 0x01ff; - - //$2100 - regs.display_disabled = true; - regs.display_brightness = 15; - - //$2101 - regs.oam_basesize = 0; - regs.oam_nameselect = 0; - regs.oam_tdaddr = 0x0000; - - cache.oam_basesize = 0; - cache.oam_nameselect = 0; - cache.oam_tdaddr = 0x0000; - - //$2102-$2103 - regs.oam_baseaddr = 0x0000; - regs.oam_addr = 0x0000; - regs.oam_priority = false; - regs.oam_firstsprite = 0; - - //$2104 - regs.oam_latchdata = 0x00; - - //$2105 - regs.bg_tilesize[BG1] = 0; - regs.bg_tilesize[BG2] = 0; - regs.bg_tilesize[BG3] = 0; - regs.bg_tilesize[BG4] = 0; - regs.bg3_priority = 0; - regs.bg_mode = 0; - - //$2106 - regs.mosaic_size = 0; - regs.mosaic_enabled[BG1] = false; - regs.mosaic_enabled[BG2] = false; - regs.mosaic_enabled[BG3] = false; - regs.mosaic_enabled[BG4] = false; - regs.mosaic_countdown = 0; - - //$2107-$210a - regs.bg_scaddr[BG1] = 0x0000; - regs.bg_scaddr[BG2] = 0x0000; - regs.bg_scaddr[BG3] = 0x0000; - regs.bg_scaddr[BG4] = 0x0000; - regs.bg_scsize[BG1] = SC_32x32; - regs.bg_scsize[BG2] = SC_32x32; - regs.bg_scsize[BG3] = SC_32x32; - regs.bg_scsize[BG4] = SC_32x32; - - //$210b-$210c - regs.bg_tdaddr[BG1] = 0x0000; - regs.bg_tdaddr[BG2] = 0x0000; - regs.bg_tdaddr[BG3] = 0x0000; - regs.bg_tdaddr[BG4] = 0x0000; - - //$210d-$2114 - regs.bg_ofslatch = 0x00; - regs.m7_hofs = regs.m7_vofs = 0x0000; - regs.bg_hofs[BG1] = regs.bg_vofs[BG1] = 0x0000; - regs.bg_hofs[BG2] = regs.bg_vofs[BG2] = 0x0000; - regs.bg_hofs[BG3] = regs.bg_vofs[BG3] = 0x0000; - regs.bg_hofs[BG4] = regs.bg_vofs[BG4] = 0x0000; - - //$2115 - regs.vram_incmode = 1; - regs.vram_mapping = 0; - regs.vram_incsize = 1; - - //$2116-$2117 - regs.vram_addr = 0x0000; - - //$211a - regs.mode7_repeat = 0; - regs.mode7_vflip = false; - regs.mode7_hflip = false; - - //$211b-$2120 - regs.m7_latch = 0x00; - regs.m7a = 0x0000; - regs.m7b = 0x0000; - regs.m7c = 0x0000; - regs.m7d = 0x0000; - regs.m7x = 0x0000; - regs.m7y = 0x0000; - - //$2121 - regs.cgram_addr = 0x0000; - - //$2122 - regs.cgram_latchdata = 0x00; - - //$2123-$2125 - regs.window1_enabled[BG1] = false; - regs.window1_enabled[BG2] = false; - regs.window1_enabled[BG3] = false; - regs.window1_enabled[BG4] = false; - regs.window1_enabled[OAM] = false; - regs.window1_enabled[COL] = false; - - regs.window1_invert [BG1] = false; - regs.window1_invert [BG2] = false; - regs.window1_invert [BG3] = false; - regs.window1_invert [BG4] = false; - regs.window1_invert [OAM] = false; - regs.window1_invert [COL] = false; - - regs.window2_enabled[BG1] = false; - regs.window2_enabled[BG2] = false; - regs.window2_enabled[BG3] = false; - regs.window2_enabled[BG4] = false; - regs.window2_enabled[OAM] = false; - regs.window2_enabled[COL] = false; - - regs.window2_invert [BG1] = false; - regs.window2_invert [BG2] = false; - regs.window2_invert [BG3] = false; - regs.window2_invert [BG4] = false; - regs.window2_invert [OAM] = false; - regs.window2_invert [COL] = false; - - //$2126-$2129 - regs.window1_left = 0x00; - regs.window1_right = 0x00; - regs.window2_left = 0x00; - regs.window2_right = 0x00; - - //$212a-$212b - regs.window_mask[BG1] = 0; - regs.window_mask[BG2] = 0; - regs.window_mask[BG3] = 0; - regs.window_mask[BG4] = 0; - regs.window_mask[OAM] = 0; - regs.window_mask[COL] = 0; - - //$212c-$212d - regs.bg_enabled[BG1] = false; - regs.bg_enabled[BG2] = false; - regs.bg_enabled[BG3] = false; - regs.bg_enabled[BG4] = false; - regs.bg_enabled[OAM] = false; - regs.bgsub_enabled[BG1] = false; - regs.bgsub_enabled[BG2] = false; - regs.bgsub_enabled[BG3] = false; - regs.bgsub_enabled[BG4] = false; - regs.bgsub_enabled[OAM] = false; - - //$212e-$212f - regs.window_enabled[BG1] = false; - regs.window_enabled[BG2] = false; - regs.window_enabled[BG3] = false; - regs.window_enabled[BG4] = false; - regs.window_enabled[OAM] = false; - regs.sub_window_enabled[BG1] = false; - regs.sub_window_enabled[BG2] = false; - regs.sub_window_enabled[BG3] = false; - regs.sub_window_enabled[BG4] = false; - regs.sub_window_enabled[OAM] = false; - - //$2130 - regs.color_mask = 0; - regs.colorsub_mask = 0; - regs.addsub_mode = false; - regs.direct_color = false; - - //$2131 - regs.color_mode = 0; - regs.color_halve = false; - regs.color_enabled[BACK] = false; - regs.color_enabled[OAM] = false; - regs.color_enabled[BG4] = false; - regs.color_enabled[BG3] = false; - regs.color_enabled[BG2] = false; - regs.color_enabled[BG1] = false; - - //$2132 - regs.color_r = 0x00; - regs.color_g = 0x00; - regs.color_b = 0x00; - regs.color_rgb = 0x0000; - - //$2133 - regs.mode7_extbg = false; - regs.pseudo_hires = false; - regs.overscan = false; - regs.scanlines = 224; - regs.oam_interlace = false; - regs.interlace = false; - - //$2137 - regs.hcounter = 0; - regs.vcounter = 0; - regs.latch_hcounter = 0; - regs.latch_vcounter = 0; - regs.counters_latched = false; - - //$2139-$213a - regs.vram_readbuffer = 0x0000; - - //$213e - regs.time_over = false; - regs.range_over = false; - - reset(); -} - -void PPU::reset() { - create(Enter, system.cpu_frequency(), 32768); - PPUcounter::reset(); - memset(surface, 0, 512 * 512 * sizeof(uint32)); - - //zero 01-dec-2012 - gotta reset these sometime, somewhere - memset(oam_itemlist, 0, sizeof(oam_itemlist)); - memset(oam_tilelist, 0, sizeof(oam_tilelist)); - memset(oam_line_pal, 0, sizeof(oam_line_pal)); - memset(oam_line_pri, 0, sizeof(oam_line_pri)); - active_sprite = sprite_list_valid = 0; - memset(bg_info, 0, sizeof(bg_info)); - memset(window, 0, sizeof(window)); - memset(pixel_cache, 0, sizeof(pixel_cache)); - regs.oam_tilecount = regs.oam_itemcount = 0; - - frame(); - - //$2100 - regs.display_disabled = true; - - display.interlace = false; - display.overscan = false; - regs.scanlines = 224; - - memset(sprite_list, 0, sizeof(sprite_list)); - sprite_list_valid = false; - - //open bus support - regs.ppu1_mdr = 0xff; - regs.ppu2_mdr = 0xff; - - //bg line counters - regs.bg_y[0] = 0; - regs.bg_y[1] = 0; - regs.bg_y[2] = 0; - regs.bg_y[3] = 0; -} - -void PPU::layer_enable(unsigned layer, unsigned priority, bool enable) { - switch(layer * 4 + priority) { - case 0: layer_enabled[BG1][0] = enable; break; - case 1: layer_enabled[BG1][1] = enable; break; - case 4: layer_enabled[BG2][0] = enable; break; - case 5: layer_enabled[BG2][1] = enable; break; - case 8: layer_enabled[BG3][0] = enable; break; - case 9: layer_enabled[BG3][1] = enable; break; - case 12: layer_enabled[BG4][0] = enable; break; - case 13: layer_enabled[BG4][1] = enable; break; - case 16: layer_enabled[OAM][0] = enable; break; - case 17: layer_enabled[OAM][1] = enable; break; - case 18: layer_enabled[OAM][2] = enable; break; - case 19: layer_enabled[OAM][3] = enable; break; - } -} - -void PPU::set_frameskip(unsigned frameskip_) { - frameskip = frameskip_; - framecounter = 0; -} - -PPU::PPU() - : vram(nullptr) - , oam(nullptr) - , cgram(nullptr) -{ - -} - -void PPU::initialize() -{ - vram = (uint8*)interface()->allocSharedMemory("VRAM",128 * 1024); - oam = (uint8*)interface()->allocSharedMemory("OAM",544); - cgram = (uint8*)interface()->allocSharedMemory("CGRAM",512); - - surface = (uint32_t*)alloc_invisible(512 * 512 * sizeof(uint32_t)); - output = surface + 16 * 512; - - alloc_tiledata_cache(); - - for(unsigned l = 0; l < 16; l++) { - for(unsigned i = 0; i < 4096; i++) { - mosaic_table[l][i] = (i / (l + 1)) * (l + 1); - } - } - - layer_enabled[BG1][0] = true; - layer_enabled[BG1][1] = true; - layer_enabled[BG2][0] = true; - layer_enabled[BG2][1] = true; - layer_enabled[BG3][0] = true; - layer_enabled[BG3][1] = true; - layer_enabled[BG4][0] = true; - layer_enabled[BG4][1] = true; - layer_enabled[OAM][0] = true; - layer_enabled[OAM][1] = true; - layer_enabled[OAM][2] = true; - layer_enabled[OAM][3] = true; - frameskip = 0; - framecounter = 0; -} - -PPU::~PPU() { - abort(); -} - -} diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/ppu.hpp b/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/ppu.hpp deleted file mode 100644 index 2df53c1e8e..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/ppu.hpp +++ /dev/null @@ -1,77 +0,0 @@ -class PPU : public Processor, public PPUcounter { -public: - uint8* vram; //[128 * 1024] - uint8* oam; //[544] - uint8* cgram; //[512] - - enum : bool { Threaded = true }; - alwaysinline void step(unsigned clocks); - alwaysinline void synchronize_cpu(); - - #include "memory/memory.hpp" - #include "mmio/mmio.hpp" - #include "render/render.hpp" - - uint32 *surface; - uint32 *output; - - uint8 ppu1_version; - uint8 ppu2_version; - - static void Enter(); - void add_clocks(unsigned clocks); - - uint8 region; - unsigned line; - - enum { NTSC = 0, PAL = 1 }; - enum { BG1 = 0, BG2 = 1, BG3 = 2, BG4 = 3, OAM = 4, BACK = 5, COL = 5 }; - enum { SC_32x32 = 0, SC_64x32 = 1, SC_32x64 = 2, SC_64x64 = 3 }; - - struct { - bool interlace; - bool overscan; - } display; - - struct { - //$2101 - uint8 oam_basesize; - uint8 oam_nameselect; - uint16 oam_tdaddr; - - //$210d-$210e - uint16 m7_hofs, m7_vofs; - - //$211b-$2120 - uint16 m7a, m7b, m7c, m7d, m7x, m7y; - } cache; - - alwaysinline bool interlace() const { return display.interlace; } - alwaysinline bool overscan() const { return display.overscan; } - alwaysinline bool hires() const { return (regs.pseudo_hires || regs.bg_mode == 5 || regs.bg_mode == 6); } - - uint16 mosaic_table[16][4096]; - void render_line(); - - void update_oam_status(); - //required functions - void scanline(); - void render_scanline(); - void frame(); - void enter(); - void enable(); - void power(); - void reset(); - - bool layer_enabled[5][4]; - void layer_enable(unsigned layer, unsigned priority, bool enable); - unsigned frameskip; - unsigned framecounter; - void set_frameskip(unsigned frameskip); - - void initialize(); - PPU(); - ~PPU(); -}; - -extern PPU ppu; diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/addsub.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/addsub.cpp deleted file mode 100644 index fc88bad31f..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/addsub.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifdef PPU_CPP - -//color addition / subtraction -//thanks go to blargg for the optimized algorithms -inline uint16 PPU::addsub(uint32 x, uint32 y, bool halve) { - if(!regs.color_mode) { - if(!halve) { - unsigned sum = x + y; - unsigned carry = (sum - ((x ^ y) & 0x0421)) & 0x8420; - return (sum - carry) | (carry - (carry >> 5)); - } else { - return (x + y - ((x ^ y) & 0x0421)) >> 1; - } - } else { - unsigned diff = x - y + 0x8420; - unsigned borrow = (diff - ((x ^ y) & 0x8420)) & 0x8420; - if(!halve) { - return (diff - borrow) & (borrow - (borrow >> 5)); - } else { - return (((diff - borrow) & (borrow - (borrow >> 5))) & 0x7bde) >> 1; - } - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/bg.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/bg.cpp deleted file mode 100644 index 6793d74759..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/bg.cpp +++ /dev/null @@ -1,209 +0,0 @@ -#ifdef PPU_CPP - -//called once at the start of every rendered scanline -void PPU::update_bg_info() { - const unsigned hires = (regs.bg_mode == 5 || regs.bg_mode == 6); - const unsigned width = (!hires ? 256 : 512); - - for(unsigned bg = 0; bg < 4; bg++) { - bg_info[bg].th = (regs.bg_tilesize[bg] ? 4 : 3); - bg_info[bg].tw = (hires ? 4 : bg_info[bg].th); - - bg_info[bg].mx = (bg_info[bg].th == 4 ? (width << 1) : width); - bg_info[bg].my = bg_info[bg].mx; - if(regs.bg_scsize[bg] & 0x01) bg_info[bg].mx <<= 1; - if(regs.bg_scsize[bg] & 0x02) bg_info[bg].my <<= 1; - bg_info[bg].mx--; - bg_info[bg].my--; - - bg_info[bg].scy = (regs.bg_scsize[bg] & 0x02) ? (32 << 5) : 0; - bg_info[bg].scx = (regs.bg_scsize[bg] & 0x01) ? (32 << 5) : 0; - if(regs.bg_scsize[bg] == 3) bg_info[bg].scy <<= 1; - } -} - -template -uint16 PPU::bg_get_tile(uint16 x, uint16 y) { - x = (x & bg_info[bg].mx) >> bg_info[bg].tw; - y = (y & bg_info[bg].my) >> bg_info[bg].th; - - uint16 pos = ((y & 0x1f) << 5) + (x & 0x1f); - if(y & 0x20) pos += bg_info[bg].scy; - if(x & 0x20) pos += bg_info[bg].scx; - - const uint16 addr = regs.bg_scaddr[bg] + (pos << 1); - return vram[addr] + (vram[addr + 1] << 8); -} - -#define setpixel_main(x) \ - if(pixel_cache[x].pri_main < tile_pri) { \ - pixel_cache[x].pri_main = tile_pri; \ - pixel_cache[x].bg_main = bg; \ - pixel_cache[x].src_main = col; \ - pixel_cache[x].ce_main = false; \ - } - -#define setpixel_sub(x) \ - if(pixel_cache[x].pri_sub < tile_pri) { \ - pixel_cache[x].pri_sub = tile_pri; \ - pixel_cache[x].bg_sub = bg; \ - pixel_cache[x].src_sub = col; \ - pixel_cache[x].ce_sub = false; \ - } - -template -void PPU::render_line_bg(uint8 pri0_pos, uint8 pri1_pos) { - if(layer_enabled[bg][0] == false) pri0_pos = 0; - if(layer_enabled[bg][1] == false) pri1_pos = 0; - if(pri0_pos + pri1_pos == 0) return; - - if(regs.bg_enabled[bg] == false && regs.bgsub_enabled[bg] == false) return; - - const bool bg_enabled = regs.bg_enabled[bg]; - const bool bgsub_enabled = regs.bgsub_enabled[bg]; - - const uint16 opt_valid_bit = (bg == BG1) ? 0x2000 : (bg == BG2) ? 0x4000 : 0x0000; - const uint8 bgpal_index = (mode == 0 ? (bg << 5) : 0); - - const uint8 pal_size = 2 << color_depth; //<<2 (*4), <<4 (*16), <<8 (*256) - const uint16 tile_mask = 0x0fff >> color_depth; //0x0fff, 0x07ff, 0x03ff - //4 + color_depth = >>(4-6) -- / {16, 32, 64 } bytes/tile - //index is a tile number count to add to base tile number - const unsigned tiledata_index = regs.bg_tdaddr[bg] >> (4 + color_depth); - - const uint8 *bg_td = bg_tiledata[color_depth]; - const uint8 *bg_td_state = bg_tiledata_state[color_depth]; - - const uint8 tile_width = bg_info[bg].tw; - const uint8 tile_height = bg_info[bg].th; - const uint16 mask_x = bg_info[bg].mx; //screen width mask - const uint16 mask_y = bg_info[bg].my; //screen height mask - - uint16 y = regs.bg_y[bg]; - uint16 hscroll = regs.bg_hofs[bg]; - uint16 vscroll = regs.bg_vofs[bg]; - - const unsigned hires = (mode == 5 || mode == 6); - const unsigned width = (!hires ? 256 : 512); - - if(hires) { - hscroll <<= 1; - if(regs.interlace) y = (y << 1) + field(); - } - - uint16 hval, vval; - uint16 tile_pri, tile_num; - uint8 pal_index, pal_num; - uint16 hoffset, voffset, opt_x, col; - bool mirror_x, mirror_y; - - const uint8 *tile_ptr; - const uint16 *mtable = mosaic_table[regs.mosaic_enabled[bg] ? regs.mosaic_size : 0]; - const bool is_opt_mode = (mode == 2 || mode == 4 || mode == 6); - const bool is_direct_color_mode = (regs.direct_color == true && bg == BG1 && (mode == 3 || mode == 4)); - - build_window_tables(bg); - const uint8 *wt_main = window[bg].main; - const uint8 *wt_sub = window[bg].sub; - - uint16 prev_x = 0xffff, prev_y = 0xffff, prev_optx = 0xffff; - for(uint16 x = 0; x < width; x++) { - hoffset = mtable[x] + hscroll; - voffset = y + vscroll; - - if(is_opt_mode) { - opt_x = (x + (hscroll & 7)); - - //tile 0 is unaffected by OPT mode... - if(opt_x >= 8) { - //cache tile data in hval, vval if possible - if((opt_x >> 3) != (prev_optx >> 3)) { - prev_optx = opt_x; - - hval = bg_get_tile((opt_x - 8) + (regs.bg_hofs[BG3] & ~7), regs.bg_vofs[BG3]); - if(mode != 4) { - vval = bg_get_tile((opt_x - 8) + (regs.bg_hofs[BG3] & ~7), regs.bg_vofs[BG3] + 8); - } - } - - if(mode == 4) { - if(hval & opt_valid_bit) { - if(!(hval & 0x8000)) { - hoffset = opt_x + (hval & ~7); - } else { - voffset = y + hval; - } - } - } else { - if(hval & opt_valid_bit) { - hoffset = opt_x + (hval & ~7); - } - if(vval & opt_valid_bit) { - voffset = y + vval; - } - } - } - } - - hoffset &= mask_x; - voffset &= mask_y; - - if((hoffset >> 3) != prev_x || (voffset >> 3) != prev_y) { - prev_x = (hoffset >> 3); - prev_y = (voffset >> 3); - - tile_num = bg_get_tile(hoffset, voffset); //format = vhopppcc cccccccc - mirror_y = (tile_num & 0x8000); - mirror_x = (tile_num & 0x4000); - tile_pri = (tile_num & 0x2000) ? pri1_pos : pri0_pos; - pal_num = ((tile_num >> 10) & 7); - pal_index = bgpal_index + (pal_num << pal_size); - - if(tile_width == 4) { //16x16 horizontal tile mirroring - if((bool)(hoffset & 8) != mirror_x) tile_num++; - } - - if(tile_height == 4) { //16x16 vertical tile mirroring - if((bool)(voffset & 8) != mirror_y) tile_num += 16; - } - - tile_num &= 0x03ff; - tile_num += tiledata_index; - tile_num &= tile_mask; - - if(bg_td_state[tile_num] == 1) { - render_bg_tile(tile_num); - } - - if(mirror_y) voffset ^= 7; //invert y tile pos - tile_ptr = bg_td + (tile_num * 64) + ((voffset & 7) * 8); - } - - if(mirror_x) hoffset ^= 7; //invert x tile pos - col = *(tile_ptr + (hoffset & 7)); - if(col) { - if(is_direct_color_mode) { - col = get_direct_color(pal_num, col); - } else { - col = get_palette(col + pal_index); - } - - if(!hires) { - if(bg_enabled == true && !wt_main[x]) { setpixel_main(x); } - if(bgsub_enabled == true && !wt_sub[x]) { setpixel_sub(x); } - } else { - int hx = x >> 1; - if(x & 1) { - if(bg_enabled == true && !wt_main[hx]) { setpixel_main(hx); } - } else { - if(bgsub_enabled == true && !wt_sub[hx]) { setpixel_sub(hx); } - } - } - } - } -} - -#undef setpixel_main -#undef setpixel_sub - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/cache.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/cache.cpp deleted file mode 100644 index 551af9104c..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/cache.cpp +++ /dev/null @@ -1,149 +0,0 @@ -#ifdef PPU_CPP - -#define render_bg_tile_line_2bpp(mask) \ - col = !!(d0 & mask) << 0; \ - col += !!(d1 & mask) << 1; \ - *dest++ = col - -#define render_bg_tile_line_4bpp(mask) \ - col = !!(d0 & mask) << 0; \ - col += !!(d1 & mask) << 1; \ - col += !!(d2 & mask) << 2; \ - col += !!(d3 & mask) << 3; \ - *dest++ = col - -#define render_bg_tile_line_8bpp(mask) \ - col = !!(d0 & mask) << 0; \ - col += !!(d1 & mask) << 1; \ - col += !!(d2 & mask) << 2; \ - col += !!(d3 & mask) << 3; \ - col += !!(d4 & mask) << 4; \ - col += !!(d5 & mask) << 5; \ - col += !!(d6 & mask) << 6; \ - col += !!(d7 & mask) << 7; \ - *dest++ = col - -template -void PPU::render_bg_tile(uint16 tile_num) { - uint8 col, d0, d1, d2, d3, d4, d5, d6, d7; - - if(color_depth == COLORDEPTH_4) { - uint8 *dest = (uint8*)bg_tiledata[TILE_2BIT] + tile_num * 64; - unsigned pos = tile_num * 16; - unsigned y = 8; - while(y--) { - d0 = vram[pos ]; - d1 = vram[pos + 1]; - render_bg_tile_line_2bpp(0x80); - render_bg_tile_line_2bpp(0x40); - render_bg_tile_line_2bpp(0x20); - render_bg_tile_line_2bpp(0x10); - render_bg_tile_line_2bpp(0x08); - render_bg_tile_line_2bpp(0x04); - render_bg_tile_line_2bpp(0x02); - render_bg_tile_line_2bpp(0x01); - pos += 2; - } - bg_tiledata_state[TILE_2BIT][tile_num] = 0; - } - - if(color_depth == COLORDEPTH_16) { - uint8 *dest = (uint8*)bg_tiledata[TILE_4BIT] + tile_num * 64; - unsigned pos = tile_num * 32; - unsigned y = 8; - while(y--) { - d0 = vram[pos ]; - d1 = vram[pos + 1]; - d2 = vram[pos + 16]; - d3 = vram[pos + 17]; - render_bg_tile_line_4bpp(0x80); - render_bg_tile_line_4bpp(0x40); - render_bg_tile_line_4bpp(0x20); - render_bg_tile_line_4bpp(0x10); - render_bg_tile_line_4bpp(0x08); - render_bg_tile_line_4bpp(0x04); - render_bg_tile_line_4bpp(0x02); - render_bg_tile_line_4bpp(0x01); - pos += 2; - } - bg_tiledata_state[TILE_4BIT][tile_num] = 0; - } - - if(color_depth == COLORDEPTH_256) { - uint8 *dest = (uint8*)bg_tiledata[TILE_8BIT] + tile_num * 64; - unsigned pos = tile_num * 64; - unsigned y = 8; - while(y--) { - d0 = vram[pos ]; - d1 = vram[pos + 1]; - d2 = vram[pos + 16]; - d3 = vram[pos + 17]; - d4 = vram[pos + 32]; - d5 = vram[pos + 33]; - d6 = vram[pos + 48]; - d7 = vram[pos + 49]; - render_bg_tile_line_8bpp(0x80); - render_bg_tile_line_8bpp(0x40); - render_bg_tile_line_8bpp(0x20); - render_bg_tile_line_8bpp(0x10); - render_bg_tile_line_8bpp(0x08); - render_bg_tile_line_8bpp(0x04); - render_bg_tile_line_8bpp(0x02); - render_bg_tile_line_8bpp(0x01); - pos += 2; - } - bg_tiledata_state[TILE_8BIT][tile_num] = 0; - } -} - -#undef render_bg_tile_line_2bpp -#undef render_bg_tile_line_4bpp -#undef render_bg_tile_line_8bpp - -void PPU::flush_pixel_cache() { - - uint16 main; - - int backdropColor = interface()->getBackdropColor(); - if(backdropColor == -1) - main = get_palette(0); - else main = backdropColor; - - uint16 sub = (regs.pseudo_hires || regs.bg_mode == 5 || regs.bg_mode == 6) - ? main - : regs.color_rgb; - - unsigned i = 255; - do { - pixel_cache[i].src_main = main; - pixel_cache[i].src_sub = sub; - pixel_cache[i].bg_main = BACK; - pixel_cache[i].bg_sub = BACK; - pixel_cache[i].ce_main = false; - pixel_cache[i].ce_sub = false; - pixel_cache[i].pri_main = 0; - pixel_cache[i].pri_sub = 0; - } while(i--); -} - -void PPU::alloc_tiledata_cache() { - bg_tiledata[TILE_2BIT] = (uint8_t*)alloc_invisible(262144); - bg_tiledata[TILE_4BIT] = (uint8_t*)alloc_invisible(131072); - bg_tiledata[TILE_8BIT] = (uint8_t*)alloc_invisible( 65536); - bg_tiledata_state[TILE_2BIT] = (uint8_t*)alloc_invisible( 4096); - bg_tiledata_state[TILE_4BIT] = (uint8_t*)alloc_invisible( 2048); - bg_tiledata_state[TILE_8BIT] = (uint8_t*)alloc_invisible( 1024); -} - -//marks all tiledata cache entries as dirty -void PPU::flush_tiledata_cache() { - for(unsigned i = 0; i < 4096; i++) bg_tiledata_state[TILE_2BIT][i] = 1; - for(unsigned i = 0; i < 2048; i++) bg_tiledata_state[TILE_4BIT][i] = 1; - for(unsigned i = 0; i < 1024; i++) bg_tiledata_state[TILE_8BIT][i] = 1; -} - -void PPU::free_tiledata_cache() { - abort(); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/line.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/line.cpp deleted file mode 100644 index c7e870fe36..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/line.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#ifdef PPU_CPP - -inline uint16 PPU::get_palette(uint8 index) { - const unsigned addr = index << 1; - return cgram[addr] + (cgram[addr + 1] << 8); -} - -//p = 00000bgr -//t = BBGGGRRR -//r = 0BBb00GGGg0RRRr0 -inline uint16 PPU::get_direct_color(uint8 p, uint8 t) { - return ((t & 7) << 2) | ((p & 1) << 1) | - (((t >> 3) & 7) << 7) | (((p >> 1) & 1) << 6) | - ((t >> 6) << 13) | ((p >> 2) << 12); -} - -inline uint16 PPU::get_pixel_normal(uint32 x) { - pixel_t &p = pixel_cache[x]; - uint16 src_main, src_sub; - uint8 bg_sub; - src_main = p.src_main; - - if(!regs.addsub_mode) { - bg_sub = BACK; - src_sub = regs.color_rgb; - } else { - bg_sub = p.bg_sub; - src_sub = p.src_sub; - } - - if(!window[COL].main[x]) { - if(!window[COL].sub[x]) { - return 0x0000; - } - src_main = 0x0000; - } - - if(!p.ce_main && regs.color_enabled[p.bg_main] && window[COL].sub[x]) { - bool halve = false; - if(regs.color_halve && window[COL].main[x]) { - if(regs.addsub_mode && bg_sub == BACK); - else { - halve = true; - } - } - return addsub(src_main, src_sub, halve); - } - - return src_main; -} - -inline uint16 PPU::get_pixel_swap(uint32 x) { - pixel_t &p = pixel_cache[x]; - uint16 src_main, src_sub; - uint8 bg_sub; - src_main = p.src_sub; - - if(!regs.addsub_mode) { - bg_sub = BACK; - src_sub = regs.color_rgb; - } else { - bg_sub = p.bg_main; - src_sub = p.src_main; - } - - if(!window[COL].main[x]) { - if(!window[COL].sub[x]) { - return 0x0000; - } - src_main = 0x0000; - } - - if(!p.ce_sub && regs.color_enabled[p.bg_sub] && window[COL].sub[x]) { - bool halve = false; - if(regs.color_halve && window[COL].main[x]) { - if(regs.addsub_mode && bg_sub == BACK); - else { - halve = true; - } - } - return addsub(src_main, src_sub, halve); - } - - return src_main; -} - -inline void PPU::render_line_output() { - uint32 *ptr = (uint32*)output + (line * 1024) + ((interlace() && field()) ? 512 : 0); - uint32 curr, prev; - - if(!regs.pseudo_hires && regs.bg_mode != 5 && regs.bg_mode != 6) { - for(unsigned x = 0; x < 256; x++) { - curr = (regs.display_brightness << 15) | get_pixel_normal(x); - *ptr++ = curr; - } - } else { - for(unsigned x = 0, prev = 0; x < 256; x++) { - //blending is disabled below, as this should be done via video filtering - //blending code is left for reference purposes - - curr = (regs.display_brightness << 15) | get_pixel_swap(x); - *ptr++ = curr; //(prev + curr - ((prev ^ curr) & 0x0421)) >> 1; - //prev = curr; - - curr = (regs.display_brightness << 15) | get_pixel_normal(x); - *ptr++ = curr; //(prev + curr - ((prev ^ curr) & 0x0421)) >> 1; - //prev = curr; - } - } -} - -inline void PPU::render_line_clear() { - uint32 *ptr = (uint32*)output + (line * 1024) + ((interlace() && field()) ? 512 : 0); - unsigned width = (!regs.pseudo_hires && regs.bg_mode != 5 && regs.bg_mode != 6) ? 256 : 512; - memset(ptr, 0, width * 2 * sizeof(uint32)); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/mode7.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/mode7.cpp deleted file mode 100644 index 747bafef9d..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/mode7.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#ifdef PPU_CPP - -//bsnes mode7 renderer -// -//base algorithm written by anomie -//bsnes implementation written by byuu -// -//supports mode 7 + extbg + rotate + zoom + direct color + scrolling + m7sel + windowing + mosaic -//interlace and pseudo-hires support are automatic via main rendering routine - -//13-bit sign extend -//--s---vvvvvvvvvv -> ssssssvvvvvvvvvv -#define CLIP(x) ( ((x) & 0x2000) ? ( (x) | ~0x03ff) : ((x) & 0x03ff) ) - -template -void PPU::render_line_mode7(uint8 pri0_pos, uint8 pri1_pos) { - if(layer_enabled[bg][0] == false) pri0_pos = 0; - if(layer_enabled[bg][1] == false) pri1_pos = 0; - if(pri0_pos + pri1_pos == 0) return; - - if(regs.bg_enabled[bg] == false && regs.bgsub_enabled[bg] == false) return; - - int32 px, py; - int32 tx, ty, tile, palette; - - int32 a = sclip<16>(cache.m7a); - int32 b = sclip<16>(cache.m7b); - int32 c = sclip<16>(cache.m7c); - int32 d = sclip<16>(cache.m7d); - - int32 cx = sclip<13>(cache.m7x); - int32 cy = sclip<13>(cache.m7y); - int32 hofs = sclip<13>(cache.m7_hofs); - int32 vofs = sclip<13>(cache.m7_vofs); - - int _pri, _x; - bool _bg_enabled = regs.bg_enabled[bg]; - bool _bgsub_enabled = regs.bgsub_enabled[bg]; - - build_window_tables(bg); - uint8 *wt_main = window[bg].main; - uint8 *wt_sub = window[bg].sub; - - int32 y = (regs.mode7_vflip == false ? line : 255 - line); - - uint16 *mtable_x, *mtable_y; - if(bg == BG1) { - mtable_x = (uint16*)mosaic_table[(regs.mosaic_enabled[BG1] == true) ? regs.mosaic_size : 0]; - mtable_y = (uint16*)mosaic_table[(regs.mosaic_enabled[BG1] == true) ? regs.mosaic_size : 0]; - } else { //bg == BG2 - //Mode7 EXTBG BG2 uses BG1 mosaic enable to control vertical mosaic, - //and BG2 mosaic enable to control horizontal mosaic... - mtable_x = (uint16*)mosaic_table[(regs.mosaic_enabled[BG2] == true) ? regs.mosaic_size : 0]; - mtable_y = (uint16*)mosaic_table[(regs.mosaic_enabled[BG1] == true) ? regs.mosaic_size : 0]; - } - - int32 psx = ((a * CLIP(hofs - cx)) & ~63) + ((b * CLIP(vofs - cy)) & ~63) + ((b * mtable_y[y]) & ~63) + (cx << 8); - int32 psy = ((c * CLIP(hofs - cx)) & ~63) + ((d * CLIP(vofs - cy)) & ~63) + ((d * mtable_y[y]) & ~63) + (cy << 8); - for(int32 x = 0; x < 256; x++) { - px = psx + (a * mtable_x[x]); - py = psy + (c * mtable_x[x]); - - //mask floating-point bits (low 8 bits) - px >>= 8; - py >>= 8; - - switch(regs.mode7_repeat) { - case 0: //screen repetition outside of screen area - case 1: { //same as case 0 - px &= 1023; - py &= 1023; - tx = ((px >> 3) & 127); - ty = ((py >> 3) & 127); - tile = vram[(ty * 128 + tx) << 1]; - palette = vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1]; - } break; - case 2: { //palette color 0 outside of screen area - if((px | py) & ~1023) { - palette = 0; - } else { - px &= 1023; - py &= 1023; - tx = ((px >> 3) & 127); - ty = ((py >> 3) & 127); - tile = vram[(ty * 128 + tx) << 1]; - palette = vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1]; - } - } break; - case 3: { //character 0 repetition outside of screen area - if((px | py) & ~1023) { - tile = 0; - } else { - px &= 1023; - py &= 1023; - tx = ((px >> 3) & 127); - ty = ((py >> 3) & 127); - tile = vram[(ty * 128 + tx) << 1]; - } - palette = vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1]; - } break; - } - - if(bg == BG1) { - _pri = pri0_pos; - } else { - _pri = (palette >> 7) ? pri1_pos : pri0_pos; - palette &= 0x7f; - } - - if(!palette) continue; - - _x = (regs.mode7_hflip == false) ? (x) : (255 - x); - - uint32 col; - if(regs.direct_color == true && bg == BG1) { - //direct color mode does not apply to bg2, as it is only 128 colors... - col = get_direct_color(0, palette); - } else { - col = get_palette(palette); - } - - if(regs.bg_enabled[bg] == true && !wt_main[_x]) { - if(pixel_cache[_x].pri_main < _pri) { - pixel_cache[_x].pri_main = _pri; - pixel_cache[_x].bg_main = bg; - pixel_cache[_x].src_main = col; - pixel_cache[_x].ce_main = false; - } - } - if(regs.bgsub_enabled[bg] == true && !wt_sub[_x]) { - if(pixel_cache[_x].pri_sub < _pri) { - pixel_cache[_x].pri_sub = _pri; - pixel_cache[_x].bg_sub = bg; - pixel_cache[_x].src_sub = col; - pixel_cache[_x].ce_sub = false; - } - } - } -} - -#undef CLIP - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/oam.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/oam.cpp deleted file mode 100644 index 42544a0238..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/oam.cpp +++ /dev/null @@ -1,237 +0,0 @@ -#ifdef PPU_CPP - -void PPU::update_sprite_list(unsigned addr, uint8 data) { - if(addr < 0x0200) { - unsigned i = addr >> 2; - switch(addr & 3) { - case 0: sprite_list[i].x = (sprite_list[i].x & 0x0100) | data; break; - case 1: sprite_list[i].y = (data + 1) & 0xff; break; - case 2: sprite_list[i].character = data; break; - case 3: sprite_list[i].vflip = data & 0x80; - sprite_list[i].hflip = data & 0x40; - sprite_list[i].priority = (data >> 4) & 3; - sprite_list[i].palette = (data >> 1) & 7; - sprite_list[i].use_nameselect = data & 0x01; - } - } else { - unsigned i = (addr & 0x1f) << 2; - sprite_list[i + 0].x = ((data & 0x01) << 8) | (sprite_list[i + 0].x & 0xff); - sprite_list[i + 0].size = data & 0x02; - sprite_list[i + 1].x = ((data & 0x04) << 6) | (sprite_list[i + 1].x & 0xff); - sprite_list[i + 1].size = data & 0x08; - sprite_list[i + 2].x = ((data & 0x10) << 4) | (sprite_list[i + 2].x & 0xff); - sprite_list[i + 2].size = data & 0x20; - sprite_list[i + 3].x = ((data & 0x40) << 2) | (sprite_list[i + 3].x & 0xff); - sprite_list[i + 3].size = data & 0x80; - } -} - -void PPU::build_sprite_list() { - if(sprite_list_valid == true) return; - sprite_list_valid = true; - - for(unsigned i = 0; i < 128; i++) { - const bool size = sprite_list[i].size; - - switch(cache.oam_basesize) { - case 0: sprite_list[i].width = (!size) ? 8 : 16; - sprite_list[i].height = (!size) ? 8 : 16; - break; - case 1: sprite_list[i].width = (!size) ? 8 : 32; - sprite_list[i].height = (!size) ? 8 : 32; - break; - case 2: sprite_list[i].width = (!size) ? 8 : 64; - sprite_list[i].height = (!size) ? 8 : 64; - break; - case 3: sprite_list[i].width = (!size) ? 16 : 32; - sprite_list[i].height = (!size) ? 16 : 32; - break; - case 4: sprite_list[i].width = (!size) ? 16 : 64; - sprite_list[i].height = (!size) ? 16 : 64; - break; - case 5: sprite_list[i].width = (!size) ? 32 : 64; - sprite_list[i].height = (!size) ? 32 : 64; - break; - case 6: sprite_list[i].width = (!size) ? 16 : 32; - sprite_list[i].height = (!size) ? 32 : 64; - if(regs.oam_interlace && !size) sprite_list[i].height = 16; - //32x64 height is not affected by oam_interlace setting - break; - case 7: sprite_list[i].width = (!size) ? 16 : 32; - sprite_list[i].height = (!size) ? 32 : 32; - if(regs.oam_interlace && !size) sprite_list[i].height = 16; - break; - } - } -} - -bool PPU::is_sprite_on_scanline() { - //if sprite is entirely offscreen and doesn't wrap around to the left side of the screen, - //then it is not counted. this *should* be 256, and not 255, even though dot 256 is offscreen. - sprite_item *spr = &sprite_list[active_sprite]; - if(spr->x > 256 && (spr->x + spr->width - 1) < 512) return false; - - int spr_height = (regs.oam_interlace == false) ? (spr->height) : (spr->height >> 1); - if(line >= spr->y && line < (spr->y + spr_height)) return true; - if((spr->y + spr_height) >= 256 && line < ((spr->y + spr_height) & 255)) return true; - return false; -} - -void PPU::load_oam_tiles() { - sprite_item *spr = &sprite_list[active_sprite]; - uint16 tile_width = spr->width >> 3; - int x = spr->x; - int y = (line - spr->y) & 0xff; - if(regs.oam_interlace == true) { - y <<= 1; - } - - if(spr->vflip == true) { - if(spr->width == spr->height) { - y = (spr->height - 1) - y; - } else { - y = (y < spr->width) ? ((spr->width - 1) - y) : (spr->width + ((spr->width - 1) - (y - spr->width))); - } - } - - if(regs.oam_interlace == true) { - y = (spr->vflip == false) ? (y + field()) : (y - field()); - } - - x &= 511; - y &= 255; - - uint16 tdaddr = cache.oam_tdaddr; - uint16 chrx = (spr->character ) & 15; - uint16 chry = (spr->character >> 4) & 15; - if(spr->use_nameselect == true) { - tdaddr += (256 * 32) + (cache.oam_nameselect << 13); - } - chry += (y >> 3); - chry &= 15; - chry <<= 4; - - for(unsigned tx = 0; tx < tile_width; tx++) { - unsigned sx = (x + (tx << 3)) & 511; - //ignore sprites that are offscreen, x==256 is a special case that loads all tiles in OBJ - if(x != 256 && sx >= 256 && (sx + 7) < 512) continue; - - if(regs.oam_tilecount++ >= 34) break; - unsigned n = regs.oam_tilecount - 1; - oam_tilelist[n].x = sx; - oam_tilelist[n].y = y; - oam_tilelist[n].pri = spr->priority; - oam_tilelist[n].pal = 128 + (spr->palette << 4); - oam_tilelist[n].hflip = spr->hflip; - - unsigned mx = (spr->hflip == false) ? tx : ((tile_width - 1) - tx); - unsigned pos = tdaddr + ((chry + ((chrx + mx) & 15)) << 5); - oam_tilelist[n].tile = (pos >> 5) & 0x07ff; - } -} - -void PPU::render_oam_tile(int tile_num) { - oam_tileitem *t = &oam_tilelist[tile_num]; - uint8 *oam_td = (uint8*)bg_tiledata[COLORDEPTH_16]; - uint8 *oam_td_state = (uint8*)bg_tiledata_state[COLORDEPTH_16]; - - if(oam_td_state[t->tile] == 1) { - render_bg_tile(t->tile); - } - - unsigned sx = t->x; - uint8 *tile_ptr = (uint8*)oam_td + (t->tile << 6) + ((t->y & 7) << 3); - for(unsigned x = 0; x < 8; x++) { - sx &= 511; - if(sx < 256) { - unsigned col = *(tile_ptr + ((t->hflip == false) ? x : (7 - x))); - if(col) { - col += t->pal; - oam_line_pal[sx] = col; - oam_line_pri[sx] = t->pri; - } - } - sx++; - } -} - -void PPU::render_line_oam_rto() { - build_sprite_list(); - - regs.oam_itemcount = 0; - regs.oam_tilecount = 0; - memset(oam_line_pri, OAM_PRI_NONE, 256); - memset(oam_itemlist, 0xff, 32); - for(int s = 0; s < 34; s++) oam_tilelist[s].tile = 0xffff; - - for(int s = 0; s < 128; s++) { - active_sprite = (s + regs.oam_firstsprite) & 127; - if(is_sprite_on_scanline() == false) continue; - if(regs.oam_itemcount++ >= 32) break; - oam_itemlist[regs.oam_itemcount - 1] = (s + regs.oam_firstsprite) & 127; - } - - if(regs.oam_itemcount > 0 && oam_itemlist[regs.oam_itemcount - 1] != 0xff) { - regs.ioamaddr = 0x0200 + (oam_itemlist[regs.oam_itemcount - 1] >> 2); - } - - for(int s = 31; s >= 0; s--) { - if(oam_itemlist[s] == 0xff) continue; - active_sprite = oam_itemlist[s]; - load_oam_tiles(); - } - - regs.time_over |= (regs.oam_tilecount > 34); - regs.range_over |= (regs.oam_itemcount > 32); -} - -#define setpixel_main(x) \ - if(pixel_cache[x].pri_main < pri) { \ - pixel_cache[x].pri_main = pri; \ - pixel_cache[x].bg_main = OAM; \ - pixel_cache[x].src_main = get_palette(oam_line_pal[x]); \ - pixel_cache[x].ce_main = (oam_line_pal[x] < 192); \ - } -#define setpixel_sub(x) \ - if(pixel_cache[x].pri_sub < pri) { \ - pixel_cache[x].pri_sub = pri; \ - pixel_cache[x].bg_sub = OAM; \ - pixel_cache[x].src_sub = get_palette(oam_line_pal[x]); \ - pixel_cache[x].ce_sub = (oam_line_pal[x] < 192); \ - } - -void PPU::render_line_oam(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 pri3_pos) { - if(layer_enabled[OAM][0] == false) pri0_pos = 0; - if(layer_enabled[OAM][1] == false) pri1_pos = 0; - if(layer_enabled[OAM][2] == false) pri2_pos = 0; - if(layer_enabled[OAM][3] == false) pri3_pos = 0; - if(pri0_pos + pri1_pos + pri2_pos + pri3_pos == 0) return; - - if(regs.bg_enabled[OAM] == false && regs.bgsub_enabled[OAM] == false) return; - - for(unsigned s = 0; s < 34; s++) { - if(oam_tilelist[s].tile == 0xffff) continue; - render_oam_tile(s); - } - - bool bg_enabled = regs.bg_enabled[OAM]; - bool bgsub_enabled = regs.bgsub_enabled[OAM]; - - build_window_tables(OAM); - uint8 *wt_main = window[OAM].main; - uint8 *wt_sub = window[OAM].sub; - - unsigned pri_tbl[4] = { pri0_pos, pri1_pos, pri2_pos, pri3_pos }; - for(int x = 0; x < 256; x++) { - if(oam_line_pri[x] == OAM_PRI_NONE) continue; - - unsigned pri = pri_tbl[oam_line_pri[x]]; - if(bg_enabled == true && !wt_main[x]) { setpixel_main(x); } - if(bgsub_enabled == true && !wt_sub[x]) { setpixel_sub(x); } - } -} - -#undef setpixel_main -#undef setpixel_sub - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/render.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/render.cpp deleted file mode 100644 index c185fa0a1e..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/render.cpp +++ /dev/null @@ -1,129 +0,0 @@ -#ifdef PPU_CPP - -#include "cache.cpp" -#include "windows.cpp" -#include "bg.cpp" -#include "oam.cpp" -#include "mode7.cpp" -#include "addsub.cpp" -#include "line.cpp" - -//Mode 0: -> -// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 -// BG4B, BG3B, OAM0, BG4A, BG3A, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3 -void PPU::render_line_mode0() { - render_line_bg<0, BG1, COLORDEPTH_4>(8, 11); - render_line_bg<0, BG2, COLORDEPTH_4>(7, 10); - render_line_bg<0, BG3, COLORDEPTH_4>(2, 5); - render_line_bg<0, BG4, COLORDEPTH_4>(1, 4); - render_line_oam(3, 6, 9, 12); -} - -//Mode 1 (pri=1): -> -// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -// BG3B, OAM0, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3, BG3A -// -//Mode 1 (pri=0): -> -// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -// BG3B, OAM0, BG3A, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3 -void PPU::render_line_mode1() { - if(regs.bg3_priority) { - render_line_bg<1, BG1, COLORDEPTH_16>(5, 8); - render_line_bg<1, BG2, COLORDEPTH_16>(4, 7); - render_line_bg<1, BG3, COLORDEPTH_4 >(1, 10); - render_line_oam(2, 3, 6, 9); - } else { - render_line_bg<1, BG1, COLORDEPTH_16>(6, 9); - render_line_bg<1, BG2, COLORDEPTH_16>(5, 8); - render_line_bg<1, BG3, COLORDEPTH_4 >(1, 3); - render_line_oam(2, 4, 7, 10); - } -} - -//Mode 2: -> -// 1, 2, 3, 4, 5, 6, 7, 8 -// BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3 -void PPU::render_line_mode2() { - render_line_bg<2, BG1, COLORDEPTH_16>(3, 7); - render_line_bg<2, BG2, COLORDEPTH_16>(1, 5); - render_line_oam(2, 4, 6, 8); -} - -//Mode 3: -> -// 1, 2, 3, 4, 5, 6, 7, 8 -// BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3 -void PPU::render_line_mode3() { - render_line_bg<3, BG1, COLORDEPTH_256>(3, 7); - render_line_bg<3, BG2, COLORDEPTH_16 >(1, 5); - render_line_oam(2, 4, 6, 8); -} - -//Mode 4: -> -// 1, 2, 3, 4, 5, 6, 7, 8 -// BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3 -void PPU::render_line_mode4() { - render_line_bg<4, BG1, COLORDEPTH_256>(3, 7); - render_line_bg<4, BG2, COLORDEPTH_4 >(1, 5); - render_line_oam(2, 4, 6, 8); -} - -//Mode 5: -> -// 1, 2, 3, 4, 5, 6, 7, 8 -// BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3 -void PPU::render_line_mode5() { - render_line_bg<5, BG1, COLORDEPTH_16>(3, 7); - render_line_bg<5, BG2, COLORDEPTH_4 >(1, 5); - render_line_oam(2, 4, 6, 8); -} - -//Mode 6: -> -// 1, 2, 3, 4, 5, 6 -// OAM0, BG1B, OAM1, OAM2, BG1A, OAM3 -void PPU::render_line_mode6() { - render_line_bg<6, BG1, COLORDEPTH_16>(2, 5); - render_line_oam(1, 3, 4, 6); -} - -//Mode7: -> -// 1, 2, 3, 4, 5 -// OAM0, BG1n, OAM1, OAM2, OAM3 - -//Mode 7 EXTBG: -> -// 1, 2, 3, 4, 5, 6, 7 -// BG2B, OAM0, BG1n, OAM1, BG2A, OAM2, OAM3 -void PPU::render_line_mode7() { - if(regs.mode7_extbg == false) { - render_line_mode7(2, 2); - render_line_oam(1, 3, 4, 5); - } else { - render_line_mode7(3, 3); - render_line_mode7(1, 5); - render_line_oam(2, 4, 6, 7); - } -} - -void PPU::render_line() { - if(regs.display_disabled == true) { - render_line_clear(); - return; - } - - flush_pixel_cache(); - build_window_tables(COL); - update_bg_info(); - - switch(regs.bg_mode) { - case 0: render_line_mode0(); break; - case 1: render_line_mode1(); break; - case 2: render_line_mode2(); break; - case 3: render_line_mode3(); break; - case 4: render_line_mode4(); break; - case 5: render_line_mode5(); break; - case 6: render_line_mode6(); break; - case 7: render_line_mode7(); break; - } - - render_line_output(); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/render.hpp b/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/render.hpp deleted file mode 100644 index 91438009bb..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/render.hpp +++ /dev/null @@ -1,99 +0,0 @@ -//render.cpp -inline void render_line_mode0(); -inline void render_line_mode1(); -inline void render_line_mode2(); -inline void render_line_mode3(); -inline void render_line_mode4(); -inline void render_line_mode5(); -inline void render_line_mode6(); -inline void render_line_mode7(); - -//cache.cpp -enum { COLORDEPTH_4 = 0, COLORDEPTH_16 = 1, COLORDEPTH_256 = 2 }; -enum { TILE_2BIT = 0, TILE_4BIT = 1, TILE_8BIT = 2 }; - -struct pixel_t { - //bgr555 color data for main/subscreen pixels: 0x0000 = transparent / use palette color # 0 - //needs to be bgr555 instead of palette index for direct color mode ($2130 bit 0) to work - uint16 src_main, src_sub; - //indicates source of palette # for main/subscreen (BG1-4, OAM, or back) - uint8 bg_main, bg_sub; - //color_exemption -- true when bg == OAM && palette index >= 192, disables color add/sub effects - uint8 ce_main, ce_sub; - //priority level of src_n. to set src_n, - //the priority of the pixel must be >pri_n - uint8 pri_main, pri_sub; -} pixel_cache[256]; - -uint8 *bg_tiledata[3]; -uint8 *bg_tiledata_state[3]; //0 = valid, 1 = dirty - -template void render_bg_tile(uint16 tile_num); -inline void flush_pixel_cache(); -void alloc_tiledata_cache(); -void flush_tiledata_cache(); -void free_tiledata_cache(); - -//windows.cpp -struct window_t { - uint8 main[256], sub[256]; -} window[6]; - -void build_window_table(uint8 bg, bool mainscreen); -void build_window_tables(uint8 bg); - -//bg.cpp -struct { - uint16 tw, th; //tile width, height - uint16 mx, my; //screen mask x, y - uint16 scx, scy; //sc index offsets -} bg_info[4]; -void update_bg_info(); - -template uint16 bg_get_tile(uint16 x, uint16 y); -template void render_line_bg(uint8 pri0_pos, uint8 pri1_pos); - -//oam.cpp -struct sprite_item { - uint8 width, height; - uint16 x, y; - uint8 character; - bool use_nameselect; - bool vflip, hflip; - uint8 palette; - uint8 priority; - bool size; -} sprite_list[128]; -bool sprite_list_valid; -unsigned active_sprite; - -uint8 oam_itemlist[32]; -struct oam_tileitem { - uint16 x, y, pri, pal, tile; - bool hflip; -} oam_tilelist[34]; - -enum { OAM_PRI_NONE = 4 }; -uint8 oam_line_pal[256], oam_line_pri[256]; - -void update_sprite_list(unsigned addr, uint8 data); -void build_sprite_list(); -bool is_sprite_on_scanline(); -void load_oam_tiles(); -void render_oam_tile(int tile_num); -void render_line_oam_rto(); -void render_line_oam(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 pri3_pos); - -//mode7.cpp -template void render_line_mode7(uint8 pri0_pos, uint8 pri1_pos); - -//addsub.cpp -inline uint16 addsub(uint32 x, uint32 y, bool halve); - -//line.cpp -inline uint16 get_palette(uint8 index); -inline uint16 get_direct_color(uint8 p, uint8 t); -inline uint16 get_pixel_normal(uint32 x); -inline uint16 get_pixel_swap(uint32 x); -void render_line_output(); -void render_line_clear(); diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/windows.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/windows.cpp deleted file mode 100644 index d8b4fd1af6..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-compatibility/render/windows.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#ifdef PPU_CPP - -//screen: 0 = main, 1 = sub -void PPU::build_window_table(uint8 bg, bool screen) { - bool set = 1, clr = 0; - uint8 *table = (screen == 0 ? window[bg].main : window[bg].sub); - - if(bg != COL) { - if(screen == 0 && regs.window_enabled[bg] == false) { - memset(table, 0, 256); - return; - } - if(screen == 1 && regs.sub_window_enabled[bg] == false) { - memset(table, 0, 256); - return; - } - } else { - switch(screen == 0 ? regs.color_mask : regs.colorsub_mask) { - case 0: memset(table, 1, 256); return; //always - case 3: memset(table, 0, 256); return; //never - case 1: set = 1, clr = 0; break; //inside window only - case 2: set = 0, clr = 1; break; //outside window only - } - } - - const uint16 window1_left = regs.window1_left; - const uint16 window1_right = regs.window1_right; - const uint16 window2_left = regs.window2_left; - const uint16 window2_right = regs.window2_right; - - if(regs.window1_enabled[bg] == false && regs.window2_enabled[bg] == false) { - memset(table, clr, 256); - return; - } - - if(regs.window1_enabled[bg] == true && regs.window2_enabled[bg] == false) { - if(regs.window1_invert[bg] == true) set ^= clr ^= set ^= clr; - for(unsigned x = 0; x < 256; x++) { - table[x] = (x >= window1_left && x <= window1_right) ? set : clr; - } - return; - } - - if(regs.window1_enabled[bg] == false && regs.window2_enabled[bg] == true) { - if(regs.window2_invert[bg] == true) set ^= clr ^= set ^= clr; - for(unsigned x = 0; x < 256; x++) { - table[x] = (x >= window2_left && x <= window2_right) ? set : clr; - } - return; - } - - for(unsigned x = 0; x < 256; x++) { - bool w1_mask = (x >= window1_left && x <= window1_right) ^ regs.window1_invert[bg]; - bool w2_mask = (x >= window2_left && x <= window2_right) ^ regs.window2_invert[bg]; - - switch(regs.window_mask[bg]) { - case 0: table[x] = (w1_mask | w2_mask) == 1 ? set : clr; break; //or - case 1: table[x] = (w1_mask & w2_mask) == 1 ? set : clr; break; //and - case 2: table[x] = (w1_mask ^ w2_mask) == 1 ? set : clr; break; //xor - case 3: table[x] = (w1_mask ^ w2_mask) == 0 ? set : clr; break; //xnor - } - } -} - -void PPU::build_window_tables(uint8 bg) { - build_window_table(bg, 0); - build_window_table(bg, 1); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/background/background.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-performance/background/background.cpp deleted file mode 100644 index 29c70aaf00..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/background/background.cpp +++ /dev/null @@ -1,184 +0,0 @@ -#ifdef PPU_CPP - -#include "mode7.cpp" - -unsigned PPU::Background::get_tile(unsigned hoffset, unsigned voffset) { - unsigned tile_x = (hoffset & mask_x) >> tile_width; - unsigned tile_y = (voffset & mask_y) >> tile_height; - - unsigned tile_pos = ((tile_y & 0x1f) << 5) + (tile_x & 0x1f); - if(tile_y & 0x20) tile_pos += scy; - if(tile_x & 0x20) tile_pos += scx; - - const uint16 tiledata_addr = regs.screen_addr + (tile_pos << 1); - return (ppu.vram[tiledata_addr + 0] << 0) + (ppu.vram[tiledata_addr + 1] << 8); -} - -void PPU::Background::offset_per_tile(unsigned x, unsigned y, unsigned &hoffset, unsigned &voffset) { - unsigned opt_x = (x + (hscroll & 7)), hval, vval; - if(opt_x >= 8) { - hval = self.bg3.get_tile((opt_x - 8) + (self.bg3.regs.hoffset & ~7), self.bg3.regs.voffset + 0); - if(self.regs.bgmode != 4) - vval = self.bg3.get_tile((opt_x - 8) + (self.bg3.regs.hoffset & ~7), self.bg3.regs.voffset + 8); - - if(self.regs.bgmode == 4) { - if(hval & opt_valid_bit) { - if(!(hval & 0x8000)) { - hoffset = opt_x + (hval & ~7); - } else { - voffset = y + hval; - } - } - } else { - if(hval & opt_valid_bit) { - hoffset = opt_x + (hval & ~7); - } - if(vval & opt_valid_bit) { - voffset = y + vval; - } - } - } -} - -void PPU::Background::scanline() { - if(self.vcounter() == 1) { - mosaic_vcounter = regs.mosaic + 1; - mosaic_voffset = 1; - } else if(--mosaic_vcounter == 0) { - mosaic_vcounter = regs.mosaic + 1; - mosaic_voffset += regs.mosaic + 1; - } - if(self.regs.display_disable) return; - - hires = (self.regs.bgmode == 5 || self.regs.bgmode == 6); - width = !hires ? 256 : 512; - - tile_height = regs.tile_size ? 4 : 3; - tile_width = hires ? 4 : tile_height; - - mask_x = (tile_height == 4 ? width << 1 : width); - mask_y = mask_x; - if(regs.screen_size & 1) mask_x <<= 1; - if(regs.screen_size & 2) mask_y <<= 1; - mask_x--; - mask_y--; - - scx = (regs.screen_size & 1 ? 32 << 5 : 0); - scy = (regs.screen_size & 2 ? 32 << 5 : 0); - if(regs.screen_size == 3) scy <<= 1; -} - -void PPU::Background::render() { - if(regs.mode == Mode::Inactive) return; - if(regs.main_enable == false && regs.sub_enable == false) return; - - if(regs.main_enable) window.render(0); - if(regs.sub_enable) window.render(1); - if(regs.mode == Mode::Mode7) return render_mode7(); - - unsigned priority0 = (priority0_enable ? regs.priority0 : 0); - unsigned priority1 = (priority1_enable ? regs.priority1 : 0); - if(priority0 + priority1 == 0) return; - - unsigned mosaic_hcounter = 1; - unsigned mosaic_palette = 0; - unsigned mosaic_priority = 0; - unsigned mosaic_color = 0; - - const unsigned bgpal_index = (self.regs.bgmode == 0 ? id << 5 : 0); - const unsigned pal_size = 2 << regs.mode; - const unsigned tile_mask = 0x0fff >> regs.mode; - const unsigned tiledata_index = regs.tiledata_addr >> (4 + regs.mode); - - hscroll = regs.hoffset; - vscroll = regs.voffset; - - unsigned y = (regs.mosaic == 0 ? self.vcounter() : mosaic_voffset); - if(hires) { - hscroll <<= 1; - if(self.regs.interlace) y = (y << 1) + self.field(); - } - - unsigned tile_pri, tile_num; - unsigned pal_index, pal_num; - unsigned hoffset, voffset, col; - bool mirror_x, mirror_y; - - const bool is_opt_mode = (self.regs.bgmode == 2 || self.regs.bgmode == 4 || self.regs.bgmode == 6); - const bool is_direct_color_mode = (self.screen.regs.direct_color == true && id == ID::BG1 && (self.regs.bgmode == 3 || self.regs.bgmode == 4)); - - signed x = 0 - (hscroll & 7); - while(x < width) { - hoffset = x + hscroll; - voffset = y + vscroll; - if(is_opt_mode) offset_per_tile(x, y, hoffset, voffset); - hoffset &= mask_x; - voffset &= mask_y; - - tile_num = get_tile(hoffset, voffset); - mirror_y = tile_num & 0x8000; - mirror_x = tile_num & 0x4000; - tile_pri = tile_num & 0x2000 ? priority1 : priority0; - pal_num = (tile_num >> 10) & 7; - pal_index = (bgpal_index + (pal_num << pal_size)) & 0xff; - - if(tile_width == 4 && (bool)(hoffset & 8) != mirror_x) tile_num += 1; - if(tile_height == 4 && (bool)(voffset & 8) != mirror_y) tile_num += 16; - tile_num = ((tile_num & 0x03ff) + tiledata_index) & tile_mask; - - if(mirror_y) voffset ^= 7; - unsigned mirror_xmask = !mirror_x ? 0 : 7; - - uint8 *tiledata = self.cache.tile(regs.mode, tile_num); - tiledata += ((voffset & 7) * 8); - - for(unsigned n = 0; n < 8; n++, x++) { - if(x & width) continue; - if(--mosaic_hcounter == 0) { - mosaic_hcounter = regs.mosaic + 1; - mosaic_palette = tiledata[n ^ mirror_xmask]; - mosaic_priority = tile_pri; - if(is_direct_color_mode) { - mosaic_color = self.screen.get_direct_color(pal_num, mosaic_palette); - } else { - mosaic_color = self.screen.get_palette(pal_index + mosaic_palette); - } - } - if(mosaic_palette == 0) continue; - - if(hires == false) { - if(regs.main_enable && !window.main[x]) self.screen.output.plot_main(x, mosaic_color, mosaic_priority, id); - if(regs.sub_enable && !window.sub[x]) self.screen.output.plot_sub(x, mosaic_color, mosaic_priority, id); - } else { - signed half_x = x >> 1; - if(x & 1) { - if(regs.main_enable && !window.main[half_x]) self.screen.output.plot_main(half_x, mosaic_color, mosaic_priority, id); - } else { - if(regs.sub_enable && !window.sub[half_x]) self.screen.output.plot_sub(half_x, mosaic_color, mosaic_priority, id); - } - } - } - } -} - -PPU::Background::Background(PPU &self, unsigned id) : self(self), id(id) { - priority0_enable = true; - priority1_enable = true; - - opt_valid_bit = (id == ID::BG1 ? 0x2000 : id == ID::BG2 ? 0x4000 : 0x0000); - - mosaic_table = new uint16*[16]; - for(unsigned m = 0; m < 16; m++) { - mosaic_table[m] = new uint16[4096]; - for(unsigned x = 0; x < 4096; x++) { - mosaic_table[m][x] = (x / (m + 1)) * (m + 1); - } - } -} - -PPU::Background::~Background() { - for(unsigned m = 0; m < 16; m++) delete[] mosaic_table[m]; - delete[] mosaic_table; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/background/background.hpp b/waterbox/libsnes/bsnes/snes/alt/ppu-performance/background/background.hpp deleted file mode 100644 index c2bd08d77e..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/background/background.hpp +++ /dev/null @@ -1,65 +0,0 @@ -class Background { - struct ID { enum { BG1, BG2, BG3, BG4 }; }; - struct Mode { enum { BPP2, BPP4, BPP8, Mode7, Inactive }; }; - struct ScreenSize { enum { Size32x32, Size32x64, Size64x32, Size64x64 }; }; - struct TileSize { enum { Size8x8, Size16x16 }; }; - - bool priority0_enable; - bool priority1_enable; - - struct Regs { - unsigned mode; - unsigned priority0; - unsigned priority1; - - bool tile_size; - unsigned mosaic; - - unsigned screen_addr; - unsigned screen_size; - unsigned tiledata_addr; - - unsigned hoffset; - unsigned voffset; - - bool main_enable; - bool sub_enable; - } regs; - - uint16 **mosaic_table; - - const unsigned id; - unsigned opt_valid_bit; - - bool hires; - signed width; - - unsigned tile_width; - unsigned tile_height; - - unsigned mask_x; - unsigned mask_y; - - unsigned scx; - unsigned scy; - - unsigned hscroll; - unsigned vscroll; - - unsigned mosaic_vcounter; - unsigned mosaic_voffset; - - LayerWindow window; - - alwaysinline unsigned get_tile(unsigned hoffset, unsigned voffset); - void offset_per_tile(unsigned x, unsigned y, unsigned &hoffset, unsigned &voffset); - void scanline(); - void render(); - void render_mode7(); - - Background(PPU &self, unsigned id); - ~Background(); - - PPU &self; - friend class PPU; -}; diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/background/mode7.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-performance/background/mode7.cpp deleted file mode 100644 index ef2b388c10..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/background/mode7.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#ifdef PPU_CPP - -#define Clip(x) (((x) & 0x2000) ? ((x) | ~0x03ff) : ((x) & 0x03ff)) - -void PPU::Background::render_mode7() { - signed px, py; - signed tx, ty, tile, palette; - - signed a = sclip<16>(self.regs.m7a); - signed b = sclip<16>(self.regs.m7b); - signed c = sclip<16>(self.regs.m7c); - signed d = sclip<16>(self.regs.m7d); - - signed cx = sclip<13>(self.regs.m7x); - signed cy = sclip<13>(self.regs.m7y); - signed hofs = sclip<13>(self.regs.mode7_hoffset); - signed vofs = sclip<13>(self.regs.mode7_voffset); - - signed y = (self.regs.mode7_vflip == false ? self.vcounter() : 255 - self.vcounter()); - - uint16 *mosaic_x, *mosaic_y; - if(id == ID::BG1) { - mosaic_x = mosaic_table[self.bg1.regs.mosaic]; - mosaic_y = mosaic_table[self.bg1.regs.mosaic]; - } else { - mosaic_x = mosaic_table[self.bg2.regs.mosaic]; - mosaic_y = mosaic_table[self.bg1.regs.mosaic]; - } - - unsigned priority0 = (priority0_enable ? regs.priority0 : 0); - unsigned priority1 = (priority1_enable ? regs.priority1 : 0); - if(priority0 + priority1 == 0) return; - - signed psx = ((a * Clip(hofs - cx)) & ~63) + ((b * Clip(vofs - cy)) & ~63) + ((b * mosaic_y[y]) & ~63) + (cx << 8); - signed psy = ((c * Clip(hofs - cx)) & ~63) + ((d * Clip(vofs - cy)) & ~63) + ((d * mosaic_y[y]) & ~63) + (cy << 8); - for(signed x = 0; x < 256; x++) { - px = (psx + (a * mosaic_x[x])) >> 8; - py = (psy + (c * mosaic_x[x])) >> 8; - - switch(self.regs.mode7_repeat) { - case 0: case 1: { - px &= 1023; - py &= 1023; - tx = ((px >> 3) & 127); - ty = ((py >> 3) & 127); - tile = ppu.vram[(ty * 128 + tx) << 1]; - palette = ppu.vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1]; - break; - } - - case 2: { - if((px | py) & ~1023) { - palette = 0; - } else { - px &= 1023; - py &= 1023; - tx = ((px >> 3) & 127); - ty = ((py >> 3) & 127); - tile = ppu.vram[(ty * 128 + tx) << 1]; - palette = ppu.vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1]; - } - break; - } - - case 3: { - if((px | py) & ~1023) { - tile = 0; - } else { - px &= 1023; - py &= 1023; - tx = ((px >> 3) & 127); - ty = ((py >> 3) & 127); - tile = ppu.vram[(ty * 128 + tx) << 1]; - } - palette = ppu.vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1]; - break; - } - } - - unsigned priority; - if(id == ID::BG1) { - priority = priority0; - } else { - priority = (palette & 0x80 ? priority1 : priority0); - palette &= 0x7f; - } - - if(palette == 0) continue; - unsigned plot_x = (self.regs.mode7_hflip == false ? x : 255 - x); - - unsigned color; - if(self.screen.regs.direct_color && id == ID::BG1) { - color = self.screen.get_direct_color(0, palette); - } else { - color = self.screen.get_palette(palette); - } - - if(regs.main_enable && !window.main[plot_x]) self.screen.output.plot_main(plot_x, color, priority, id); - if(regs.sub_enable && !window.sub[plot_x]) self.screen.output.plot_sub(plot_x, color, priority, id); - } -} - -#undef Clip - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/cache/cache.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-performance/cache/cache.cpp deleted file mode 100644 index c0942b2f8f..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/cache/cache.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#ifdef PPU_CPP - -uint8* PPU::Cache::tile_2bpp(unsigned tile) { - if(tilevalid[0][tile] == 0) { - tilevalid[0][tile] = 1; - uint8 *output = (uint8*)tiledata[0] + (tile << 6); - unsigned offset = tile << 4; - unsigned y = 8; - unsigned color, d0, d1; - while(y--) { - d0 = ppu.vram[offset + 0]; - d1 = ppu.vram[offset + 1]; - #define render_line(mask) \ - color = !!(d0 & mask) << 0; \ - color |= !!(d1 & mask) << 1; \ - *output++ = color - render_line(0x80); - render_line(0x40); - render_line(0x20); - render_line(0x10); - render_line(0x08); - render_line(0x04); - render_line(0x02); - render_line(0x01); - #undef render_line - offset += 2; - } - } - return tiledata[0] + (tile << 6); -} - -uint8* PPU::Cache::tile_4bpp(unsigned tile) { - if(tilevalid[1][tile] == 0) { - tilevalid[1][tile] = 1; - uint8 *output = (uint8*)tiledata[1] + (tile << 6); - unsigned offset = tile << 5; - unsigned y = 8; - unsigned color, d0, d1, d2, d3; - while(y--) { - d0 = ppu.vram[offset + 0]; - d1 = ppu.vram[offset + 1]; - d2 = ppu.vram[offset + 16]; - d3 = ppu.vram[offset + 17]; - #define render_line(mask) \ - color = !!(d0 & mask) << 0; \ - color |= !!(d1 & mask) << 1; \ - color |= !!(d2 & mask) << 2; \ - color |= !!(d3 & mask) << 3; \ - *output++ = color - render_line(0x80); - render_line(0x40); - render_line(0x20); - render_line(0x10); - render_line(0x08); - render_line(0x04); - render_line(0x02); - render_line(0x01); - #undef render_line - offset += 2; - } - } - return tiledata[1] + (tile << 6); -} - -uint8* PPU::Cache::tile_8bpp(unsigned tile) { - if(tilevalid[2][tile] == 0) { - tilevalid[2][tile] = 1; - uint8 *output = (uint8*)tiledata[2] + (tile << 6); - unsigned offset = tile << 6; - unsigned y = 8; - unsigned color, d0, d1, d2, d3, d4, d5, d6, d7; - while(y--) { - d0 = ppu.vram[offset + 0]; - d1 = ppu.vram[offset + 1]; - d2 = ppu.vram[offset + 16]; - d3 = ppu.vram[offset + 17]; - d4 = ppu.vram[offset + 32]; - d5 = ppu.vram[offset + 33]; - d6 = ppu.vram[offset + 48]; - d7 = ppu.vram[offset + 49]; - #define render_line(mask) \ - color = !!(d0 & mask) << 0; \ - color |= !!(d1 & mask) << 1; \ - color |= !!(d2 & mask) << 2; \ - color |= !!(d3 & mask) << 3; \ - color |= !!(d4 & mask) << 4; \ - color |= !!(d5 & mask) << 5; \ - color |= !!(d6 & mask) << 6; \ - color |= !!(d7 & mask) << 7; \ - *output++ = color - render_line(0x80); - render_line(0x40); - render_line(0x20); - render_line(0x10); - render_line(0x08); - render_line(0x04); - render_line(0x02); - render_line(0x01); - #undef render_line - offset += 2; - } - } - return tiledata[2] + (tile << 6); -} - -uint8* PPU::Cache::tile(unsigned bpp, unsigned tile) { - switch(bpp) { - case 0: return tile_2bpp(tile); - case 1: return tile_4bpp(tile); - case 2: return tile_8bpp(tile); - } -} - -PPU::Cache::Cache(PPU &self) : self(self) { - tiledata[0] = (uint8*)alloc_invisible(262144); - tiledata[1] = (uint8*)alloc_invisible(131072); - tiledata[2] = (uint8*)alloc_invisible(65536); - tilevalid[0] = (uint8*)alloc_invisible(4096); - tilevalid[1] = (uint8*)alloc_invisible(2048); - tilevalid[2] = (uint8*)alloc_invisible(1024); -} - -PPU::Cache::invalidate() { - memset(tilevalid[0], 0, 4096); - memset(tilevalid[1], 0, 2048); - memset(tilevalid[2], 0, 1024); -} - -PPU::Cache::~Cache() -{ - abort(); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/cache/cache.hpp b/waterbox/libsnes/bsnes/snes/alt/ppu-performance/cache/cache.hpp deleted file mode 100644 index ec4b2a543e..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/cache/cache.hpp +++ /dev/null @@ -1,17 +0,0 @@ -class Cache { -public: - uint8 *tiledata[3]; - uint8 *tilevalid[3]; - - uint8* tile_2bpp(unsigned tile); - uint8* tile_4bpp(unsigned tile); - uint8* tile_8bpp(unsigned tile); - uint8* tile(unsigned bpp, unsigned tile); - void invalidate(); - - Cache(PPU &self); - ~Cache(); - - PPU &self; - friend class PPU; -}; diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/mmio/mmio.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-performance/mmio/mmio.cpp deleted file mode 100644 index 8941627489..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/mmio/mmio.cpp +++ /dev/null @@ -1,891 +0,0 @@ -#ifdef PPU_CPP - -void PPU::latch_counters() { - regs.hcounter = cpu.hdot(); - regs.vcounter = cpu.vcounter(); - regs.counters_latched = true; -} - -bool PPU::interlace() const { return display.interlace; } -bool PPU::overscan() const { return display.overscan; } -bool PPU::hires() const { return regs.pseudo_hires || regs.bgmode == 5 || regs.bgmode == 6; } - -uint16 PPU::get_vram_addr() { - uint16 addr = regs.vram_addr; - switch(regs.vram_mapping) { - case 0: break; - case 1: addr = (addr & 0xff00) | ((addr & 0x001f) << 3) | ((addr >> 5) & 7); break; - case 2: addr = (addr & 0xfe00) | ((addr & 0x003f) << 3) | ((addr >> 6) & 7); break; - case 3: addr = (addr & 0xfc00) | ((addr & 0x007f) << 3) | ((addr >> 7) & 7); break; - } - return (addr << 1); -} - -uint8 PPU::vram_read(unsigned addr) { - if(regs.display_disable) return vram[addr]; - if(cpu.vcounter() >= display.height) return vram[addr]; - return 0x00; -} - -void PPU::vram_write(unsigned addr, uint8 data) { - if(regs.display_disable || cpu.vcounter() >= display.height) { - vram[addr] = data; - cache.tilevalid[0][addr >> 4] = false; - cache.tilevalid[1][addr >> 5] = false; - cache.tilevalid[2][addr >> 6] = false; - return; - } -} - -uint8 PPU::oam_read(unsigned addr) { - if(addr & 0x0200) addr &= 0x021f; - if(regs.display_disable) return oam[addr]; - if(cpu.vcounter() >= display.height) return oam[addr]; - return oam[0x0218]; -} - -void PPU::oam_write(unsigned addr, uint8 data) { - if(addr & 0x0200) addr &= 0x021f; - if(!regs.display_disable && cpu.vcounter() < display.height) addr = 0x0218; - oam[addr] = data; - sprite.update_list(addr, data); -} - -uint8 PPU::cgram_read(unsigned addr) { - return cgram[addr]; -} - -void PPU::cgram_write(unsigned addr, uint8 data) { - cgram[addr] = data; -} - -void PPU::mmio_update_video_mode() { - 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; - sprite.regs.priority0 = 3; sprite.regs.priority1 = 6; sprite.regs.priority2 = 9; sprite.regs.priority3 = 12; - } 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; - sprite.regs.priority0 = 2; sprite.regs.priority1 = 3; sprite.regs.priority2 = 6; sprite.regs.priority3 = 9; - } 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; - sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 7; sprite.regs.priority3 = 10; - } - } 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; - sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8; - } 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; - sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8; - } 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; - sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8; - } 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; - sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8; - } 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; - sprite.regs.priority0 = 1; sprite.regs.priority1 = 3; sprite.regs.priority2 = 4; sprite.regs.priority3 = 6; - } break; - - case 7: { - if(regs.mode7_extbg == false) { - bg1.regs.mode = Background::Mode::Mode7; - 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 = 2; - sprite.regs.priority0 = 1; sprite.regs.priority1 = 3; sprite.regs.priority2 = 4; sprite.regs.priority3 = 5; - } else { - bg1.regs.mode = Background::Mode::Mode7; - bg2.regs.mode = Background::Mode::Mode7; - bg3.regs.mode = Background::Mode::Inactive; - bg4.regs.mode = Background::Mode::Inactive; - bg1.regs.priority0 = 3; bg1.regs.priority1 = 3; - bg2.regs.priority0 = 1; bg2.regs.priority1 = 5; - sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 7; - } - } break; - } -} - -uint8 PPU::mmio_read(unsigned addr) { - cpu.synchronize_ppu(); - - switch(addr & 0xffff) { - case 0x2104: case 0x2105: case 0x2106: case 0x2108: case 0x2109: case 0x210a: - case 0x2114: case 0x2115: case 0x2116: case 0x2118: case 0x2119: case 0x211a: - case 0x2124: case 0x2125: case 0x2126: case 0x2128: case 0x2129: case 0x212a: { - return regs.ppu1_mdr; - } - - case 0x2134: { //MPYL - unsigned result = ((int16)regs.m7a * (int8)(regs.m7b >> 8)); - regs.ppu1_mdr = result >> 0; - return regs.ppu1_mdr; - } - - case 0x2135: { //MPYM - unsigned result = ((int16)regs.m7a * (int8)(regs.m7b >> 8)); - regs.ppu1_mdr = result >> 8; - return regs.ppu1_mdr; - } - - case 0x2136: { //MPYH - unsigned result = ((int16)regs.m7a * (int8)(regs.m7b >> 8)); - regs.ppu1_mdr = result >> 16; - return regs.ppu1_mdr; - } - - case 0x2137: { //SLHV - if(cpu.pio() & 0x80) latch_counters(); - return cpu.regs.mdr; - } - - case 0x2138: { //OAMDATAREAD - regs.ppu1_mdr = oam_read(regs.oam_addr); - regs.oam_addr = (regs.oam_addr + 1) & 0x03ff; - sprite.set_first(); - return regs.ppu1_mdr; - } - - case 0x2139: { //VMDATALREAD - regs.ppu1_mdr = regs.vram_readbuffer >> 0; - if(regs.vram_incmode == 0) { - uint16 addr = get_vram_addr(); - regs.vram_readbuffer = vram_read(addr + 0) << 0; - regs.vram_readbuffer |= vram_read(addr + 1) << 8; - regs.vram_addr += regs.vram_incsize; - } - return regs.ppu1_mdr; - } - - case 0x213a: { //VMDATAHREAD - regs.ppu1_mdr = regs.vram_readbuffer >> 8; - if(regs.vram_incmode == 1) { - uint16 addr = get_vram_addr(); - regs.vram_readbuffer = vram_read(addr + 0) << 0; - regs.vram_readbuffer |= vram_read(addr + 1) << 8; - regs.vram_addr += regs.vram_incsize; - } - return regs.ppu1_mdr; - } - - case 0x213b: { //CGDATAREAD - if((regs.cgram_addr & 1) == 0) { - regs.ppu2_mdr = cgram_read(regs.cgram_addr); - } else { - regs.ppu2_mdr = (regs.ppu2_mdr & 0x80) | (cgram_read(regs.cgram_addr) & 0x7f); - } - regs.cgram_addr = (regs.cgram_addr + 1) & 0x01ff; - return regs.ppu2_mdr; - } - - case 0x213c: { //OPHCT - if(regs.latch_hcounter == 0) { - regs.ppu2_mdr = regs.hcounter & 0xff; - } else { - regs.ppu2_mdr = (regs.ppu2_mdr & 0xfe) | (regs.hcounter >> 8); - } - regs.latch_hcounter ^= 1; - return regs.ppu2_mdr; - } - - case 0x213d: { //OPVCT - if(regs.latch_vcounter == 0) { - regs.ppu2_mdr = regs.vcounter & 0xff; - } else { - regs.ppu2_mdr = (regs.ppu2_mdr & 0xfe) | (regs.vcounter >> 8); - } - regs.latch_vcounter ^= 1; - return regs.ppu2_mdr; - } - - case 0x213e: { //STAT77 - regs.ppu1_mdr &= 0x10; - regs.ppu1_mdr |= sprite.regs.time_over << 7; - regs.ppu1_mdr |= sprite.regs.range_over << 6; - regs.ppu1_mdr |= 0x01; //version - return regs.ppu1_mdr; - } - - case 0x213f: { //STAT78 - regs.latch_hcounter = 0; - regs.latch_vcounter = 0; - - regs.ppu2_mdr &= 0x20; - regs.ppu2_mdr |= cpu.field() << 7; - if((cpu.pio() & 0x80) == 0) { - regs.ppu2_mdr |= 0x40; - } else if(regs.counters_latched) { - regs.ppu2_mdr |= 0x40; - regs.counters_latched = false; - } - regs.ppu2_mdr |= (system.region() == System::Region::NTSC ? 0 : 1) << 4; - regs.ppu2_mdr |= 0x03; //version - return regs.ppu2_mdr; - } - } - - return cpu.regs.mdr; -} - -void PPU::mmio_write(unsigned addr, uint8 data) { - cpu.synchronize_ppu(); - - switch(addr & 0xffff) { - case 0x2100: { //INIDISP - if(regs.display_disable && cpu.vcounter() == display.height) sprite.address_reset(); - regs.display_disable = data & 0x80; - regs.display_brightness = data & 0x0f; - return; - } - - case 0x2101: { //OBSEL - sprite.regs.base_size = (data >> 5) & 7; - sprite.regs.nameselect = (data >> 3) & 3; - sprite.regs.tiledata_addr = (data & 3) << 14; - sprite.list_valid = false; - return; - } - - case 0x2102: { //OAMADDL - regs.oam_baseaddr = (regs.oam_baseaddr & 0x0100) | (data << 0); - sprite.address_reset(); - return; - } - - case 0x2103: { //OAMADDH - regs.oam_priority = data & 0x80; - regs.oam_baseaddr = ((data & 1) << 8) | (regs.oam_baseaddr & 0x00ff); - sprite.address_reset(); - return; - } - - case 0x2104: { //OAMDATA - if((regs.oam_addr & 1) == 0) regs.oam_latchdata = data; - if(regs.oam_addr & 0x0200) { - oam_write(regs.oam_addr, data); - } else if((regs.oam_addr & 1) == 1) { - oam_write((regs.oam_addr & ~1) + 0, regs.oam_latchdata); - oam_write((regs.oam_addr & ~1) + 1, data); - } - regs.oam_addr = (regs.oam_addr + 1) & 0x03ff; - sprite.set_first(); - return; - } - - case 0x2105: { //BGMODE - 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; - mmio_update_video_mode(); - return; - } - - case 0x2106: { //MOSAIC - unsigned mosaic_size = (data >> 4) & 15; - bg4.regs.mosaic = (data & 0x08 ? mosaic_size : 0); - bg3.regs.mosaic = (data & 0x04 ? mosaic_size : 0); - bg2.regs.mosaic = (data & 0x02 ? mosaic_size : 0); - bg1.regs.mosaic = (data & 0x01 ? mosaic_size : 0); - return; - } - - case 0x2107: { //BG1SC - bg1.regs.screen_addr = (data & 0x7c) << 9; - bg1.regs.screen_size = data & 3; - return; - } - - case 0x2108: { //BG2SC - bg2.regs.screen_addr = (data & 0x7c) << 9; - bg2.regs.screen_size = data & 3; - return; - } - - case 0x2109: { //BG3SC - bg3.regs.screen_addr = (data & 0x7c) << 9; - bg3.regs.screen_size = data & 3; - return; - } - - case 0x210a: { //BG4SC - bg4.regs.screen_addr = (data & 0x7c) << 9; - bg4.regs.screen_size = data & 3; - return; - } - - case 0x210b: { //BG12NBA - bg1.regs.tiledata_addr = (data & 0x07) << 13; - bg2.regs.tiledata_addr = (data & 0x70) << 9; - return; - } - - case 0x210c: { //BG34NBA - bg3.regs.tiledata_addr = (data & 0x07) << 13; - bg4.regs.tiledata_addr = (data & 0x70) << 9; - return; - } - - case 0x210d: { //BG1HOFS - regs.mode7_hoffset = (data << 8) | regs.mode7_latchdata; - regs.mode7_latchdata = data; - - bg1.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg1.regs.hoffset >> 8) & 7); - regs.bgofs_latchdata = data; - return; - } - - case 0x210e: { //BG1VOFS - regs.mode7_voffset = (data << 8) | regs.mode7_latchdata; - regs.mode7_latchdata = data; - - bg1.regs.voffset = (data << 8) | regs.bgofs_latchdata; - regs.bgofs_latchdata = data; - return; - } - - case 0x210f: { //BG2HOFS - bg2.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg2.regs.hoffset >> 8) & 7); - regs.bgofs_latchdata = data; - return; - } - - case 0x2110: { //BG2VOFS - bg2.regs.voffset = (data << 8) | regs.bgofs_latchdata; - regs.bgofs_latchdata = data; - return; - } - - case 0x2111: { //BG3HOFS - bg3.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg3.regs.hoffset >> 8) & 7); - regs.bgofs_latchdata = data; - return; - } - - case 0x2112: { //BG3VOFS - bg3.regs.voffset = (data << 8) | regs.bgofs_latchdata; - regs.bgofs_latchdata = data; - return; - } - - case 0x2113: { //BG4HOFS - bg4.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg4.regs.hoffset >> 8) & 7); - regs.bgofs_latchdata = data; - return; - } - - case 0x2114: { //BG4VOFS - bg4.regs.voffset = (data << 8) | regs.bgofs_latchdata; - regs.bgofs_latchdata = data; - return; - } - - case 0x2115: { //VMAIN - regs.vram_incmode = data & 0x80; - regs.vram_mapping = (data >> 2) & 3; - switch(data & 3) { - case 0: regs.vram_incsize = 1; break; - case 1: regs.vram_incsize = 32; break; - case 2: regs.vram_incsize = 128; break; - case 3: regs.vram_incsize = 128; break; - } - return; - } - - case 0x2116: { //VMADDL - regs.vram_addr = (regs.vram_addr & 0xff00) | (data << 0); - uint16 addr = get_vram_addr(); - regs.vram_readbuffer = vram_read(addr + 0) << 0; - regs.vram_readbuffer |= vram_read(addr + 1) << 8; - return; - } - - case 0x2117: { //VMADDH - regs.vram_addr = (data << 8) | (regs.vram_addr & 0x00ff); - uint16 addr = get_vram_addr(); - regs.vram_readbuffer = vram_read(addr + 0) << 0; - regs.vram_readbuffer |= vram_read(addr + 1) << 8; - return; - } - - case 0x2118: { //VMDATAL - vram_write(get_vram_addr() + 0, data); - if(regs.vram_incmode == 0) regs.vram_addr += regs.vram_incsize; - return; - } - - case 0x2119: { //VMDATAH - vram_write(get_vram_addr() + 1, data); - if(regs.vram_incmode == 1) regs.vram_addr += regs.vram_incsize; - return; - } - - case 0x211a: { //M7SEL - regs.mode7_repeat = (data >> 6) & 3; - regs.mode7_vflip = data & 0x02; - regs.mode7_hflip = data & 0x01; - return; - } - - case 0x211b: { //M7A - regs.m7a = (data << 8) | regs.mode7_latchdata; - regs.mode7_latchdata = data; - return; - } - - case 0x211c: { //M7B - regs.m7b = (data << 8) | regs.mode7_latchdata; - regs.mode7_latchdata = data; - return; - } - - case 0x211d: { //M7C - regs.m7c = (data << 8) | regs.mode7_latchdata; - regs.mode7_latchdata = data; - return; - } - - case 0x211e: { //M7D - regs.m7d = (data << 8) | regs.mode7_latchdata; - regs.mode7_latchdata = data; - return; - } - - case 0x211f: { //M7X - regs.m7x = (data << 8) | regs.mode7_latchdata; - regs.mode7_latchdata = data; - return; - } - - case 0x2120: { //M7Y - regs.m7y = (data << 8) | regs.mode7_latchdata; - regs.mode7_latchdata = data; - return; - } - - case 0x2121: { //CGADD - regs.cgram_addr = data << 1; - return; - } - - case 0x2122: { //CGDATA - if((regs.cgram_addr & 1) == 0) { - regs.cgram_latchdata = data; - } else { - cgram_write((regs.cgram_addr & ~1) + 0, regs.cgram_latchdata); - cgram_write((regs.cgram_addr & ~1) + 1, data & 0x7f); - } - regs.cgram_addr = (regs.cgram_addr + 1) & 0x01ff; - return; - } - - case 0x2123: { //W12SEL - bg2.window.two_enable = data & 0x80; - bg2.window.two_invert = data & 0x40; - bg2.window.one_enable = data & 0x20; - bg2.window.one_invert = data & 0x10; - bg1.window.two_enable = data & 0x08; - bg1.window.two_invert = data & 0x04; - bg1.window.one_enable = data & 0x02; - bg1.window.one_invert = data & 0x01; - return; - } - - case 0x2124: { //W34SEL - bg4.window.two_enable = data & 0x80; - bg4.window.two_invert = data & 0x40; - bg4.window.one_enable = data & 0x20; - bg4.window.one_invert = data & 0x10; - bg3.window.two_enable = data & 0x08; - bg3.window.two_invert = data & 0x04; - bg3.window.one_enable = data & 0x02; - bg3.window.one_invert = data & 0x01; - return; - } - - case 0x2125: { //WOBJSEL - screen.window.two_enable = data & 0x80; - screen.window.two_invert = data & 0x40; - screen.window.one_enable = data & 0x20; - screen.window.one_invert = data & 0x10; - sprite.window.two_enable = data & 0x08; - sprite.window.two_invert = data & 0x04; - sprite.window.one_enable = data & 0x02; - sprite.window.one_invert = data & 0x01; - return; - } - - case 0x2126: { //WH0 - regs.window_one_left = data; - return; - } - - case 0x2127: { //WH1 - regs.window_one_right = data; - return; - } - - case 0x2128: { //WH2 - regs.window_two_left = data; - return; - } - - case 0x2129: { //WH3 - regs.window_two_right = data; - return; - } - - case 0x212a: { //WBGLOG - bg4.window.mask = (data >> 6) & 3; - bg3.window.mask = (data >> 4) & 3; - bg2.window.mask = (data >> 2) & 3; - bg1.window.mask = (data >> 0) & 3; - return; - } - - case 0x212b: { //WOBJLOG - screen.window.mask = (data >> 2) & 3; - sprite.window.mask = (data >> 0) & 3; - return; - } - - case 0x212c: { //TM - sprite.regs.main_enable = data & 0x10; - bg4.regs.main_enable = data & 0x08; - bg3.regs.main_enable = data & 0x04; - bg2.regs.main_enable = data & 0x02; - bg1.regs.main_enable = data & 0x01; - return; - } - - case 0x212d: { //TS - sprite.regs.sub_enable = data & 0x10; - bg4.regs.sub_enable = data & 0x08; - bg3.regs.sub_enable = data & 0x04; - bg2.regs.sub_enable = data & 0x02; - bg1.regs.sub_enable = data & 0x01; - return; - } - - case 0x212e: { //TMW - sprite.window.main_enable = data & 0x10; - bg4.window.main_enable = data & 0x08; - bg3.window.main_enable = data & 0x04; - bg2.window.main_enable = data & 0x02; - bg1.window.main_enable = data & 0x01; - return; - } - - case 0x212f: { //TSW - sprite.window.sub_enable = data & 0x10; - bg4.window.sub_enable = data & 0x08; - bg3.window.sub_enable = data & 0x04; - bg2.window.sub_enable = data & 0x02; - bg1.window.sub_enable = data & 0x01; - return; - } - - case 0x2130: { //CGWSEL - screen.window.main_mask = (data >> 6) & 3; - screen.window.sub_mask = (data >> 4) & 3; - screen.regs.addsub_mode = data & 0x02; - screen.regs.direct_color = data & 0x01; - return; - } - - case 0x2131: { //CGADDSUB - screen.regs.color_mode = data & 0x80; - screen.regs.color_halve = data & 0x40; - screen.regs.color_enable[6] = data & 0x20; - screen.regs.color_enable[5] = data & 0x10; - screen.regs.color_enable[4] = data & 0x10; - screen.regs.color_enable[3] = data & 0x08; - screen.regs.color_enable[2] = data & 0x04; - screen.regs.color_enable[1] = data & 0x02; - screen.regs.color_enable[0] = data & 0x01; - return; - } - - case 0x2132: { //COLDATA - if(data & 0x80) screen.regs.color_b = data & 0x1f; - if(data & 0x40) screen.regs.color_g = data & 0x1f; - if(data & 0x20) screen.regs.color_r = data & 0x1f; - screen.regs.color = (screen.regs.color_b << 10) | (screen.regs.color_g << 5) | (screen.regs.color_r << 0); - return; - } - - case 0x2133: { //SETINI - regs.mode7_extbg = data & 0x40; - regs.pseudo_hires = data & 0x08; - regs.overscan = data & 0x04; - sprite.regs.interlace = data & 0x02; - regs.interlace = data & 0x01; - mmio_update_video_mode(); - sprite.list_valid = false; - return; - } - } -} - -void PPU::mmio_reset() { - //internal - regs.ppu1_mdr = 0; - regs.ppu2_mdr = 0; - - regs.vram_readbuffer = 0; - regs.oam_latchdata = 0; - regs.cgram_latchdata = 0; - regs.bgofs_latchdata = 0; - regs.mode7_latchdata = 0; - - regs.counters_latched = 0; - regs.latch_hcounter = 0; - regs.latch_vcounter = 0; - - sprite.regs.first_sprite = 0; - sprite.list_valid = false; - - //$2100 - regs.display_disable = true; - regs.display_brightness = 0; - - //$2101 - sprite.regs.base_size = 0; - sprite.regs.nameselect = 0; - sprite.regs.tiledata_addr = 0; - - //$2102-$2103 - regs.oam_baseaddr = 0; - regs.oam_addr = 0; - regs.oam_priority = 0; - - //$2105 - bg4.regs.tile_size = 0; - bg3.regs.tile_size = 0; - bg2.regs.tile_size = 0; - bg1.regs.tile_size = 0; - regs.bg3_priority = 0; - regs.bgmode = 0; - - //$2106 - bg4.regs.mosaic = 0; - bg3.regs.mosaic = 0; - bg2.regs.mosaic = 0; - bg1.regs.mosaic = 0; - - //$2107-$210a - bg1.regs.screen_addr = 0; - bg1.regs.screen_size = 0; - bg2.regs.screen_addr = 0; - bg2.regs.screen_size = 0; - bg3.regs.screen_addr = 0; - bg3.regs.screen_size = 0; - bg4.regs.screen_addr = 0; - bg4.regs.screen_size = 0; - - //$210b-$210c - bg1.regs.tiledata_addr = 0; - bg2.regs.tiledata_addr = 0; - bg3.regs.tiledata_addr = 0; - bg4.regs.tiledata_addr = 0; - - //$210d-$2114 - regs.mode7_hoffset = 0; - regs.mode7_voffset = 0; - bg1.regs.hoffset = 0; - bg1.regs.voffset = 0; - bg2.regs.hoffset = 0; - bg2.regs.voffset = 0; - bg3.regs.hoffset = 0; - bg3.regs.voffset = 0; - bg4.regs.hoffset = 0; - bg4.regs.voffset = 0; - - //$2115 - regs.vram_incmode = 0; - regs.vram_mapping = 0; - regs.vram_incsize = 1; - - //$2116-$2117 - regs.vram_addr = 0; - - //$211a - regs.mode7_repeat = 0; - regs.mode7_vflip = 0; - regs.mode7_hflip = 0; - - //$211b-$2120 - regs.m7a = 0; - regs.m7b = 0; - regs.m7c = 0; - regs.m7d = 0; - regs.m7x = 0; - regs.m7y = 0; - - //$2121 - regs.cgram_addr = 0; - - //$2123-$2125 - bg1.window.one_enable = 0; - bg1.window.one_invert = 0; - bg1.window.two_enable = 0; - bg1.window.two_invert = 0; - - bg2.window.one_enable = 0; - bg2.window.one_invert = 0; - bg2.window.two_enable = 0; - bg2.window.two_invert = 0; - - bg3.window.one_enable = 0; - bg3.window.one_invert = 0; - bg3.window.two_enable = 0; - bg3.window.two_invert = 0; - - bg4.window.one_enable = 0; - bg4.window.one_invert = 0; - bg4.window.two_enable = 0; - bg4.window.two_invert = 0; - - sprite.window.one_enable = 0; - sprite.window.one_invert = 0; - sprite.window.two_enable = 0; - sprite.window.two_invert = 0; - - screen.window.one_enable = 0; - screen.window.one_invert = 0; - screen.window.two_enable = 0; - screen.window.two_invert = 0; - - //$2126-$2129 - regs.window_one_left = 0; - regs.window_one_right = 0; - regs.window_two_left = 0; - regs.window_two_right = 0; - - //$212a-$212b - bg1.window.mask = 0; - bg2.window.mask = 0; - bg3.window.mask = 0; - bg4.window.mask = 0; - sprite.window.mask = 0; - screen.window.mask = 0; - - //$212c - bg1.regs.main_enable = 0; - bg2.regs.main_enable = 0; - bg3.regs.main_enable = 0; - bg4.regs.main_enable = 0; - sprite.regs.main_enable = 0; - - //$212d - bg1.regs.sub_enable = 0; - bg2.regs.sub_enable = 0; - bg3.regs.sub_enable = 0; - bg4.regs.sub_enable = 0; - sprite.regs.sub_enable = 0; - - //$212e - bg1.window.main_enable = 0; - bg2.window.main_enable = 0; - bg3.window.main_enable = 0; - bg4.window.main_enable = 0; - sprite.window.main_enable = 0; - - //$212f - bg1.window.sub_enable = 0; - bg2.window.sub_enable = 0; - bg3.window.sub_enable = 0; - bg4.window.sub_enable = 0; - sprite.window.sub_enable = 0; - - //$2130 - screen.window.main_mask = 0; - screen.window.sub_mask = 0; - screen.regs.addsub_mode = 0; - screen.regs.direct_color = 0; - - //$2131 - screen.regs.color_mode = 0; - screen.regs.color_halve = 0; - screen.regs.color_enable[6] = 0; - screen.regs.color_enable[5] = 0; - screen.regs.color_enable[4] = 0; - screen.regs.color_enable[3] = 0; - screen.regs.color_enable[2] = 0; - screen.regs.color_enable[1] = 0; - screen.regs.color_enable[0] = 0; - - //$2132 - screen.regs.color_b = 0; - screen.regs.color_g = 0; - screen.regs.color_r = 0; - screen.regs.color = 0; - - //$2133 - regs.mode7_extbg = 0; - regs.pseudo_hires = 0; - regs.overscan = 0; - sprite.regs.interlace = 0; - regs.interlace = 0; - - //$213e - sprite.regs.time_over = 0; - sprite.regs.range_over = 0; - - mmio_update_video_mode(); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/mmio/mmio.hpp b/waterbox/libsnes/bsnes/snes/alt/ppu-performance/mmio/mmio.hpp deleted file mode 100644 index 36b5af4da5..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/mmio/mmio.hpp +++ /dev/null @@ -1,95 +0,0 @@ -public: - uint8 mmio_read(unsigned addr); - void mmio_write(unsigned addr, uint8 data); - -private: - -struct Regs { - //internal - uint8 ppu1_mdr; - uint8 ppu2_mdr; - - uint16 vram_readbuffer; - uint8 oam_latchdata; - uint8 cgram_latchdata; - uint8 bgofs_latchdata; - uint8 mode7_latchdata; - - bool counters_latched; - bool latch_hcounter; - bool latch_vcounter; - - //$2100 - bool display_disable; - unsigned display_brightness; - - //$2102-$2103 - uint16 oam_baseaddr; - uint16 oam_addr; - bool oam_priority; - - //$2105 - bool bg3_priority; - unsigned bgmode; - - //$210d - uint16 mode7_hoffset; - - //$210e - uint16 mode7_voffset; - - //$2115 - bool vram_incmode; - unsigned vram_mapping; - unsigned vram_incsize; - - //$2116-$2117 - uint16 vram_addr; - - //$211a - unsigned mode7_repeat; - bool mode7_vflip; - bool mode7_hflip; - - //$211b-$2120 - uint16 m7a; - uint16 m7b; - uint16 m7c; - uint16 m7d; - uint16 m7x; - uint16 m7y; - - //$2121 - uint16 cgram_addr; - - //$2126-$212a - unsigned window_one_left; - unsigned window_one_right; - unsigned window_two_left; - unsigned window_two_right; - - //$2133 - bool mode7_extbg; - bool pseudo_hires; - bool overscan; - bool interlace; - - //$213c - uint16 hcounter; - - //$213d - uint16 vcounter; -} regs; - -uint16 get_vram_addr(); -uint8 vram_read(unsigned addr); -void vram_write(unsigned addr, uint8 data); - -uint8 oam_read(unsigned addr); -void oam_write(unsigned addr, uint8 data); - -uint8 cgram_read(unsigned addr); -void cgram_write(unsigned addr, uint8 data); - -void mmio_update_video_mode(); -void mmio_reset(); diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/ppu.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-performance/ppu.cpp deleted file mode 100644 index a286e0b0dc..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/ppu.cpp +++ /dev/null @@ -1,160 +0,0 @@ -#include - -#define PPU_CPP -namespace SNES { - -PPU ppu; - -#include "mmio/mmio.cpp" -#include "window/window.cpp" -#include "cache/cache.cpp" -#include "background/background.cpp" -#include "sprite/sprite.cpp" -#include "screen/screen.cpp" - -void PPU::step(unsigned clocks) { - clock += clocks; -} - -void PPU::synchronize_cpu() { - if(CPU::Threaded == true) { - if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); - } else { - while(clock >= 0) cpu.enter(); - } -} - -void PPU::Enter() { ppu.enter(); } - -void PPU::enter() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - scanline(); - if(vcounter() < display.height && vcounter()) { - add_clocks(512); - render_scanline(); - add_clocks(lineclocks() - 512); - } else { - add_clocks(lineclocks()); - } - } -} - -void PPU::add_clocks(unsigned clocks) { - tick(clocks); - step(clocks); - synchronize_cpu(); -} - -void PPU::render_scanline() { - if(display.framecounter) return; //skip this frame? - bg1.scanline(); - bg2.scanline(); - bg3.scanline(); - bg4.scanline(); - if(regs.display_disable) return screen.render_black(); - screen.scanline(); - bg1.render(); - bg2.render(); - bg3.render(); - bg4.render(); - sprite.render(); - screen.render(); -} - -void PPU::scanline() { - display.width = !hires() ? 256 : 512; - display.height = !overscan() ? 225 : 240; - if(vcounter() == 0) frame(); - if(vcounter() == display.height && regs.display_disable == false) sprite.address_reset(); -} - -void PPU::frame() { - sprite.frame(); - system.frame(); - display.interlace = regs.interlace; - display.overscan = regs.overscan; - display.framecounter = display.frameskip == 0 ? 0 : (display.framecounter + 1) % display.frameskip; -} - -void PPU::enable() { - function read = { &PPU::mmio_read, (PPU*)&ppu }; - function write = { &PPU::mmio_write, (PPU*)&ppu }; - - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, read, write); - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, read, write); -} - -void PPU::power() { - for(int i=0;i<128*1024;i++) vram[i] = 0; - for(int i=0;i<544;i++) oam[i] = 0; - for(int i=0;i<512;i++) cgram[i] = 0; - reset(); -} - -void PPU::reset() { - create(Enter, system.cpu_frequency()); - PPUcounter::reset(); - memset(surface, 0, 512 * 512 * sizeof(uint32)); - mmio_reset(); - display.interlace = false; - display.overscan = false; -} - -void PPU::layer_enable(unsigned layer, unsigned priority, bool enable) { - switch(layer * 4 + priority) { - case 0: bg1.priority0_enable = enable; break; - case 1: bg1.priority1_enable = enable; break; - case 4: bg2.priority0_enable = enable; break; - case 5: bg2.priority1_enable = enable; break; - case 8: bg3.priority0_enable = enable; break; - case 9: bg3.priority1_enable = enable; break; - case 12: bg4.priority0_enable = enable; break; - case 13: bg4.priority1_enable = enable; break; - case 16: sprite.priority0_enable = enable; break; - case 17: sprite.priority1_enable = enable; break; - case 18: sprite.priority2_enable = enable; break; - case 19: sprite.priority3_enable = enable; break; - } -} - -void PPU::set_frameskip(unsigned frameskip) { - display.frameskip = frameskip; - display.framecounter = 0; -} - -PPU::PPU() : -cache(*this), -bg1(*this, Background::ID::BG1), -bg2(*this, Background::ID::BG2), -bg3(*this, Background::ID::BG3), -bg4(*this, Background::ID::BG4), -sprite(*this), -screen(*this), -vram(nullptr), -oam(nullptr), -cgram(nullptr) -{ - surface = (uint32_t*)alloc_invisible(512 * 512 * sizeof(uint32_t)); - output = surface + 16 * 512; - display.width = 256; - display.height = 224; - display.frameskip = 0; - display.framecounter = 0; -} - -PPU::~PPU() { - abort(); -} - -void PPU::initialize() -{ - vram = (uint8*)interface()->allocSharedMemory("VRAM",128 * 1024); - oam = (uint8*)interface()->allocSharedMemory("OAM",544); - cgram = (uint8*)interface()->allocSharedMemory("CGRAM",512); -} - -} diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/ppu.hpp b/waterbox/libsnes/bsnes/snes/alt/ppu-performance/ppu.hpp deleted file mode 100644 index a71eab44e4..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/ppu.hpp +++ /dev/null @@ -1,69 +0,0 @@ -class PPU : public Processor, public PPUcounter { -public: - uint8 *vram; //[64 * 1024]; - uint8 *oam; //[544]; - uint8 *cgram; //[512]; - - enum : bool { Threaded = true }; - alwaysinline void step(unsigned clocks); - alwaysinline void synchronize_cpu(); - - void latch_counters(); - bool interlace() const; - bool overscan() const; - bool hires() const; - - void enter(); - void enable(); - void power(); - void reset(); - void scanline(); - void frame(); - - void layer_enable(unsigned layer, unsigned priority, bool enable); - void set_frameskip(unsigned frameskip); - - PPU(); - ~PPU(); - void initialize(); - -private: - uint32 *surface; - uint32 *output; - - #include "mmio/mmio.hpp" - #include "window/window.hpp" - #include "cache/cache.hpp" - #include "background/background.hpp" - #include "sprite/sprite.hpp" - #include "screen/screen.hpp" - - Cache cache; - Background bg1; - Background bg2; - Background bg3; - Background bg4; - Sprite sprite; - Screen screen; - - struct Display { - bool interlace; - bool overscan; - unsigned width; - unsigned height; - unsigned frameskip; - unsigned framecounter; - } display; - - static void Enter(); - void add_clocks(unsigned clocks); - void render_scanline(); - - friend class PPU::Cache; - friend class PPU::Background; - friend class PPU::Sprite; - friend class PPU::Screen; - friend class Video; -}; - -extern PPU ppu; diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/screen/screen.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-performance/screen/screen.cpp deleted file mode 100644 index 7939f243c5..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/screen/screen.cpp +++ /dev/null @@ -1,155 +0,0 @@ -#ifdef PPU_CPP - -unsigned PPU::Screen::get_palette(unsigned color) { - #if defined(ARCH_LSB) - return ((uint16*)ppu.cgram)[color]; - #else - color <<= 1; - return (ppu.cgram[color + 0] << 0) + (ppu.cgram[color + 1] << 8); - #endif -} - -unsigned PPU::Screen::get_direct_color(unsigned p, unsigned t) { - return ((t & 7) << 2) | ((p & 1) << 1) | - (((t >> 3) & 7) << 7) | (((p >> 1) & 1) << 6) | - ((t >> 6) << 13) | ((p >> 2) << 12); -} - -uint16 PPU::Screen::addsub(unsigned x, unsigned y, bool halve) { - if(!regs.color_mode) { - if(!halve) { - unsigned sum = x + y; - unsigned carry = (sum - ((x ^ y) & 0x0421)) & 0x8420; - return (sum - carry) | (carry - (carry >> 5)); - } else { - return (x + y - ((x ^ y) & 0x0421)) >> 1; - } - } else { - unsigned diff = x - y + 0x8420; - unsigned borrow = (diff - ((x ^ y) & 0x8420)) & 0x8420; - if(!halve) { - return (diff - borrow) & (borrow - (borrow >> 5)); - } else { - return (((diff - borrow) & (borrow - (borrow >> 5))) & 0x7bde) >> 1; - } - } -} - -void PPU::Screen::scanline() { - unsigned main_color = get_palette(0); - unsigned sub_color = (self.regs.pseudo_hires == false && self.regs.bgmode != 5 && self.regs.bgmode != 6) - ? regs.color : main_color; - - for(unsigned x = 0; x < 256; x++) { - output.main[x].color = main_color; - output.main[x].priority = 0; - output.main[x].source = 6; - - output.sub[x].color = sub_color; - output.sub[x].priority = 0; - output.sub[x].source = 6; - } - - window.render(0); - window.render(1); -} - -void PPU::Screen::render_black() { - uint32 *data = self.output + self.vcounter() * 1024; - if(self.interlace() && self.field()) data += 512; - memset(data, 0, self.display.width << 2); -} - -uint16 PPU::Screen::get_pixel_main(unsigned x) { - auto main = output.main[x]; - auto sub = output.sub[x]; - - if(!regs.addsub_mode) { - sub.source = 6; - sub.color = regs.color; - } - - if(!window.main[x]) { - if(!window.sub[x]) { - return 0x0000; - } - main.color = 0x0000; - } - - if(main.source != 5 && regs.color_enable[main.source] && window.sub[x]) { - bool halve = false; - if(regs.color_halve && window.main[x]) { - if(!regs.addsub_mode || sub.source != 6) halve = true; - } - return addsub(main.color, sub.color, halve); - } - - return main.color; -} - -uint16 PPU::Screen::get_pixel_sub(unsigned x) { - auto main = output.sub[x]; - auto sub = output.main[x]; - - if(!regs.addsub_mode) { - sub.source = 6; - sub.color = regs.color; - } - - if(!window.main[x]) { - if(!window.sub[x]) { - return 0x0000; - } - main.color = 0x0000; - } - - if(main.source != 5 && regs.color_enable[main.source] && window.sub[x]) { - bool halve = false; - if(regs.color_halve && window.main[x]) { - if(!regs.addsub_mode || sub.source != 6) halve = true; - } - return addsub(main.color, sub.color, halve); - } - - return main.color; -} - -void PPU::Screen::render() { - uint32 *data = self.output + self.vcounter() * 1024; - if(self.interlace() && self.field()) data += 512; - - if(!self.regs.pseudo_hires && self.regs.bgmode != 5 && self.regs.bgmode != 6) { - for(unsigned i = 0; i < 256; i++) { - data[i] = (self.regs.display_brightness << 15) | get_pixel_main(i); - } - } else { - for(unsigned i = 0; i < 256; i++) { - *data++ = (self.regs.display_brightness << 15) | get_pixel_sub(i); - *data++ = (self.regs.display_brightness << 15) | get_pixel_main(i); - } - } -} - -PPU::Screen::Screen(PPU &self) : self(self) { -} - -PPU::Screen::~Screen() { -} - -void PPU::Screen::Output::plot_main(unsigned x, unsigned color, unsigned priority, unsigned source) { - if(priority > main[x].priority) { - main[x].color = color; - main[x].priority = priority; - main[x].source = source; - } -} - -void PPU::Screen::Output::plot_sub(unsigned x, unsigned color, unsigned priority, unsigned source) { - if(priority > sub[x].priority) { - sub[x].color = color; - sub[x].priority = priority; - sub[x].source = source; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/screen/screen.hpp b/waterbox/libsnes/bsnes/snes/alt/ppu-performance/screen/screen.hpp deleted file mode 100644 index dec3214e2e..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/screen/screen.hpp +++ /dev/null @@ -1,43 +0,0 @@ -class Screen { - struct Regs { - bool addsub_mode; - bool direct_color; - - bool color_mode; - bool color_halve; - bool color_enable[7]; - - unsigned color_b; - unsigned color_g; - unsigned color_r; - unsigned color; - } regs; - - struct Output { - struct Pixel { - unsigned color; - unsigned priority; - unsigned source; - } main[256], sub[256]; - - alwaysinline void plot_main(unsigned x, unsigned color, unsigned priority, unsigned source); - alwaysinline void plot_sub(unsigned x, unsigned color, unsigned priority, unsigned source); - } output; - - ColorWindow window; - - alwaysinline unsigned get_palette(unsigned color); - unsigned get_direct_color(unsigned palette, unsigned tile); - alwaysinline uint16 addsub(unsigned x, unsigned y, bool halve); - void scanline(); - void render_black(); - alwaysinline uint16 get_pixel_main(unsigned x); - alwaysinline uint16 get_pixel_sub(unsigned x); - void render(); - - Screen(PPU &self); - ~Screen(); - - PPU &self; - friend class PPU; -}; diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/sprite/sprite.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-performance/sprite/sprite.cpp deleted file mode 100644 index 222739cd23..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/sprite/sprite.cpp +++ /dev/null @@ -1,190 +0,0 @@ -#ifdef PPU_CPP - -void PPU::Sprite::frame() { - regs.time_over = false; - regs.range_over = false; -} - -void PPU::Sprite::update_list(unsigned addr, uint8 data) { - if(addr < 0x0200) { - unsigned i = addr >> 2; - switch(addr & 3) { - case 0: list[i].x = (list[i].x & 0x0100) | data; break; - case 1: list[i].y = (data + 1) & 0xff; break; - case 2: list[i].character = data; break; - case 3: list[i].vflip = data & 0x80; - list[i].hflip = data & 0x40; - list[i].priority = (data >> 4) & 3; - list[i].palette = (data >> 1) & 7; - list[i].use_nameselect = data & 0x01; - break; - } - } else { - unsigned i = (addr & 0x1f) << 2; - list[i + 0].x = ((data & 0x01) << 8) | (list[i + 0].x & 0xff); - list[i + 0].size = data & 0x02; - list[i + 1].x = ((data & 0x04) << 6) | (list[i + 1].x & 0xff); - list[i + 1].size = data & 0x08; - list[i + 2].x = ((data & 0x10) << 4) | (list[i + 2].x & 0xff); - list[i + 2].size = data & 0x20; - list[i + 3].x = ((data & 0x40) << 2) | (list[i + 3].x & 0xff); - list[i + 3].size = data & 0x80; - list_valid = false; - } -} - -void PPU::Sprite::address_reset() { - self.regs.oam_addr = self.regs.oam_baseaddr << 1; - set_first(); -} - -void PPU::Sprite::set_first() { - regs.first_sprite = (self.regs.oam_priority == false ? 0 : (self.regs.oam_addr >> 2) & 127); -} - -bool PPU::Sprite::on_scanline(unsigned sprite) { - auto &s = list[sprite]; - if(s.x > 256 && (s.x + s.width - 1) < 512) return false; - signed height = (regs.interlace == false ? s.height : s.height >> 1); - if(self.vcounter() >= s.y && self.vcounter() < (s.y + height)) return true; - if((s.y + height) >= 256 && self.vcounter() < ((s.y + height) & 255)) return true; - return false; -} - -void PPU::Sprite::render() { - if(list_valid == false) { - list_valid = true; - for(unsigned i = 0; i < 128; i++) { - if(list[i].size == 0) { - static unsigned width[] = { 8, 8, 8, 16, 16, 32, 16, 16 }; - static unsigned height[] = { 8, 8, 8, 16, 16, 32, 32, 32 }; - list[i].width = width[regs.base_size]; - list[i].height = height[regs.base_size]; - } else { - static unsigned width[] = { 16, 32, 64, 32, 64, 64, 32, 32 }; - static unsigned height[] = { 16, 32, 64, 32, 64, 64, 64, 32 }; - list[i].width = width[regs.base_size]; - list[i].height = height[regs.base_size]; - if(regs.interlace && regs.base_size >= 6) list[i].height = 16; - } - } - } - - unsigned itemcount = 0; - unsigned tilecount = 0; - memset(output.priority, 0xff, 256); - memset(itemlist, 0xff, 32); - for(unsigned i = 0; i < 34; i++) tilelist[i].tile = 0xffff; - - for(unsigned i = 0; i < 128; i++) { - unsigned s = (regs.first_sprite + i) & 127; - if(on_scanline(s) == false) continue; - if(itemcount++ >= 32) break; - itemlist[itemcount - 1] = s; - } - - for(signed i = 31; i >= 0; i--) { - if(itemlist[i] == 0xff) continue; - auto &s = list[itemlist[i]]; - unsigned tile_width = s.width >> 3; - signed x = s.x; - signed y = (self.vcounter() - s.y) & 0xff; - if(regs.interlace) y <<= 1; - - if(s.vflip) { - if(s.width == s.height) { - y = (s.height - 1) - y; - } else { - y = (y < s.width) ? ((s.width - 1) - y) : (s.width + ((s.width - 1) - (y - s.width))); - } - } - - if(regs.interlace) { - y = (s.vflip == false) ? (y + self.field()) : (y - self.field()); - } - - x &= 511; - y &= 255; - - uint16 tdaddr = regs.tiledata_addr; - uint16 chrx = (s.character >> 0) & 15; - uint16 chry = (s.character >> 4) & 15; - if(s.use_nameselect) { - tdaddr += (256 * 32) + (regs.nameselect << 13); - } - chry += (y >> 3); - chry &= 15; - chry <<= 4; - - for(unsigned tx = 0; tx < tile_width; tx++) { - unsigned sx = (x + (tx << 3)) & 511; - if(x != 256 && sx >= 256 && (sx + 7) < 512) continue; - if(tilecount++ >= 34) break; - - unsigned n = tilecount - 1; - tilelist[n].x = sx; - tilelist[n].y = y; - tilelist[n].priority = s.priority; - tilelist[n].palette = 128 + (s.palette << 4); - tilelist[n].hflip = s.hflip; - - unsigned mx = (s.hflip == false) ? tx : ((tile_width - 1) - tx); - unsigned pos = tdaddr + ((chry + ((chrx + mx) & 15)) << 5); - tilelist[n].tile = (pos >> 5) & 0x07ff; - } - } - - regs.time_over |= (tilecount > 34); - regs.range_over |= (itemcount > 32); - - if(regs.main_enable == false && regs.sub_enable == false) return; - - for(unsigned i = 0; i < 34; i++) { - if(tilelist[i].tile == 0xffff) continue; - - auto &t = tilelist[i]; - uint8 *tiledata = self.cache.tile_4bpp(t.tile); - tiledata += (t.y & 7) << 3; - unsigned sx = t.x; - for(unsigned x = 0; x < 8; x++) { - sx &= 511; - if(sx < 256) { - unsigned color = *(tiledata + (t.hflip == false ? x : 7 - x)); - if(color) { - color += t.palette; - output.palette[sx] = color; - output.priority[sx] = t.priority; - } - } - sx++; - } - } - - if(regs.main_enable) window.render(0); - if(regs.sub_enable) window.render(1); - - unsigned priority0 = (priority0_enable ? regs.priority0 : 0); - unsigned priority1 = (priority1_enable ? regs.priority1 : 0); - unsigned priority2 = (priority2_enable ? regs.priority2 : 0); - unsigned priority3 = (priority3_enable ? regs.priority3 : 0); - if(priority0 + priority1 + priority2 + priority3 == 0) return; - const unsigned priority_table[] = { priority0, priority1, priority2, priority3 }; - - for(unsigned x = 0; x < 256; x++) { - if(output.priority[x] == 0xff) continue; - unsigned priority = priority_table[output.priority[x]]; - unsigned palette = output.palette[x]; - unsigned color = self.screen.get_palette(output.palette[x]); - if(regs.main_enable && !window.main[x]) self.screen.output.plot_main(x, color, priority, 4 + (palette < 192)); - if(regs.sub_enable && !window.sub[x]) self.screen.output.plot_sub(x, color, priority, 4 + (palette < 192)); - } -} - -PPU::Sprite::Sprite(PPU &self) : self(self) { - priority0_enable = true; - priority1_enable = true; - priority2_enable = true; - priority3_enable = true; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/sprite/sprite.hpp b/waterbox/libsnes/bsnes/snes/alt/ppu-performance/sprite/sprite.hpp deleted file mode 100644 index 062f116549..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/sprite/sprite.hpp +++ /dev/null @@ -1,70 +0,0 @@ -class Sprite { - bool priority0_enable; - bool priority1_enable; - bool priority2_enable; - bool priority3_enable; - - struct Regs { - unsigned priority0; - unsigned priority1; - unsigned priority2; - unsigned priority3; - - unsigned base_size; - unsigned nameselect; - unsigned tiledata_addr; - unsigned first_sprite; - - bool main_enable; - bool sub_enable; - - bool interlace; - - bool time_over; - bool range_over; - } regs; - - struct List { - unsigned width; - unsigned height; - unsigned x; - unsigned y; - unsigned character; - bool use_nameselect; - bool vflip; - bool hflip; - unsigned palette; - unsigned priority; - bool size; - } list[128]; - bool list_valid; - - uint8 itemlist[32]; - struct TileList { - unsigned x; - unsigned y; - unsigned priority; - unsigned palette; - unsigned tile; - bool hflip; - } tilelist[34]; - - struct Output { - uint8 palette[256]; - uint8 priority[256]; - } output; - - LayerWindow window; - - void frame(); - void update_list(unsigned addr, uint8 data); - void address_reset(); - void set_first(); - alwaysinline bool on_scanline(unsigned sprite); - void render(); - - Sprite(PPU &self); - - PPU &self; - friend class PPU; -}; diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/window/window.cpp b/waterbox/libsnes/bsnes/snes/alt/ppu-performance/window/window.cpp deleted file mode 100644 index 216ee7b1f1..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/window/window.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#ifdef PPU_CPP - -void PPU::LayerWindow::render(bool screen) { - uint8 *output; - if(screen == 0) { - output = main; - if(main_enable == false) { - memset(output, 0, 256); - return; - } - } else { - output = sub; - if(sub_enable == false) { - memset(output, 0, 256); - return; - } - } - - if(one_enable == false && two_enable == false) { - memset(output, 0, 256); - return; - } - - if(one_enable == true && two_enable == false) { - bool set = 1 ^ one_invert, clr = !set; - for(unsigned x = 0; x < 256; x++) { - output[x] = (x >= ppu.regs.window_one_left && x <= ppu.regs.window_one_right) ? set : clr; - } - return; - } - - if(one_enable == false && two_enable == true) { - bool set = 1 ^ two_invert, clr = !set; - for(unsigned x = 0; x < 256; x++) { - output[x] = (x >= ppu.regs.window_two_left && x <= ppu.regs.window_two_right) ? set : clr; - } - return; - } - - for(unsigned x = 0; x < 256; x++) { - bool one_mask = (x >= ppu.regs.window_one_left && x <= ppu.regs.window_one_right) ^ one_invert; - bool two_mask = (x >= ppu.regs.window_two_left && x <= ppu.regs.window_two_right) ^ two_invert; - switch(mask) { - case 0: output[x] = one_mask | two_mask == 1; break; - case 1: output[x] = one_mask & two_mask == 1; break; - case 2: output[x] = one_mask ^ two_mask == 1; break; - case 3: output[x] = one_mask ^ two_mask == 0; break; - } - } -} - -// - -void PPU::ColorWindow::render(bool screen) { - uint8 *output = (screen == 0 ? main : sub); - bool set = 1, clr = 0; - - switch(screen == 0 ? main_mask : sub_mask) { - case 0: memset(output, 1, 256); return; //always - case 1: set = 1, clr = 0; break; //inside window only - case 2: set = 0, clr = 1; break; //outside window only - case 3: memset(output, 0, 256); return; //never - } - - if(one_enable == false && two_enable == false) { - memset(output, clr, 256); - return; - } - - if(one_enable == true && two_enable == false) { - if(one_invert) { set ^= 1; clr ^= 1; } - for(unsigned x = 0; x < 256; x++) { - output[x] = (x >= ppu.regs.window_one_left && x <= ppu.regs.window_one_right) ? set : clr; - } - return; - } - - if(one_enable == false && two_enable == true) { - if(two_invert) { set ^= 1; clr ^= 1; } - for(unsigned x = 0; x < 256; x++) { - output[x] = (x >= ppu.regs.window_two_left && x <= ppu.regs.window_two_right) ? set : clr; - } - return; - } - - for(unsigned x = 0; x < 256; x++) { - bool one_mask = (x >= ppu.regs.window_one_left && x <= ppu.regs.window_one_right) ^ one_invert; - bool two_mask = (x >= ppu.regs.window_two_left && x <= ppu.regs.window_two_right) ^ two_invert; - switch(mask) { - case 0: output[x] = one_mask | two_mask == 1 ? set : clr; break; - case 1: output[x] = one_mask & two_mask == 1 ? set : clr; break; - case 2: output[x] = one_mask ^ two_mask == 1 ? set : clr; break; - case 3: output[x] = one_mask ^ two_mask == 0 ? set : clr; break; - } - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/window/window.hpp b/waterbox/libsnes/bsnes/snes/alt/ppu-performance/window/window.hpp deleted file mode 100644 index 96957b0073..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/ppu-performance/window/window.hpp +++ /dev/null @@ -1,35 +0,0 @@ -class LayerWindow { -public: - bool one_enable; - bool one_invert; - bool two_enable; - bool two_invert; - - unsigned mask; - - bool main_enable; - bool sub_enable; - - uint8 main[256]; - uint8 sub[256]; - - void render(bool screen); -}; - -class ColorWindow { -public: - bool one_enable; - bool one_invert; - bool two_enable; - bool two_invert; - - unsigned mask; - - unsigned main_mask; - unsigned sub_mask; - - uint8 main[256]; - uint8 sub[256]; - - void render(bool screen); -}; diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/algorithms.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/algorithms.cpp deleted file mode 100644 index a55369fbab..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/algorithms.cpp +++ /dev/null @@ -1,122 +0,0 @@ -uint8 SMP::op_adc(uint8 x, uint8 y) { - int r = x + y + regs.p.c; - regs.p.n = r & 0x80; - regs.p.v = ~(x ^ y) & (x ^ r) & 0x80; - regs.p.h = (x ^ y ^ r) & 0x10; - regs.p.z = (uint8)r == 0; - regs.p.c = r > 0xff; - return r; -} - -uint16 SMP::op_addw(uint16 x, uint16 y) { - uint16 r; - regs.p.c = 0; - r = op_adc(x, y); - r |= op_adc(x >> 8, y >> 8) << 8; - regs.p.z = r == 0; - return r; -} - -uint8 SMP::op_and(uint8 x, uint8 y) { - x &= y; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMP::op_cmp(uint8 x, uint8 y) { - int r = x - y; - regs.p.n = r & 0x80; - regs.p.z = (uint8)r == 0; - regs.p.c = r >= 0; - return x; -} - -uint16 SMP::op_cmpw(uint16 x, uint16 y) { - int r = x - y; - regs.p.n = r & 0x8000; - regs.p.z = (uint16)r == 0; - regs.p.c = r >= 0; - return x; -} - -uint8 SMP::op_eor(uint8 x, uint8 y) { - x ^= y; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMP::op_or(uint8 x, uint8 y) { - x |= y; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMP::op_sbc(uint8 x, uint8 y) { - int r = x - y - !regs.p.c; - regs.p.n = r & 0x80; - regs.p.v = (x ^ y) & (x ^ r) & 0x80; - regs.p.h = !((x ^ y ^ r) & 0x10); - regs.p.z = (uint8)r == 0; - regs.p.c = r >= 0; - return r; -} - -uint16 SMP::op_subw(uint16 x, uint16 y) { - uint16 r; - regs.p.c = 1; - r = op_sbc(x, y); - r |= op_sbc(x >> 8, y >> 8) << 8; - regs.p.z = r == 0; - return r; -} - -uint8 SMP::op_inc(uint8 x) { - x++; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMP::op_dec(uint8 x) { - x--; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMP::op_asl(uint8 x) { - regs.p.c = x & 0x80; - x <<= 1; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMP::op_lsr(uint8 x) { - regs.p.c = x & 0x01; - x >>= 1; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMP::op_rol(uint8 x) { - unsigned carry = (unsigned)regs.p.c; - regs.p.c = x & 0x80; - x = (x << 1) | carry; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMP::op_ror(uint8 x) { - unsigned carry = (unsigned)regs.p.c << 7; - regs.p.c = x & 0x01; - x = carry | (x >> 1); - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/core.cpp deleted file mode 100644 index 6a79e71d8e..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core.cpp +++ /dev/null @@ -1,107 +0,0 @@ -void SMP::tick() { - timer0.tick(); - timer1.tick(); - timer2.tick(); - - clock += cycle_step_cpu; - dsp.clock -= 24; - synchronize_dsp(); -} - -void SMP::op_io() { - #if defined(CYCLE_ACCURATE) - tick(); - #endif -} - -uint8 SMP::op_read(uint16 addr, eCDLog_Flags flags) { - #if defined(CYCLE_ACCURATE) - tick(); - #endif - if((addr & 0xfff0) == 0x00f0) return mmio_read(addr); - if(addr >= 0xffc0 && status.iplrom_enable) return iplrom[addr & 0x3f]; - cdlInfo.currFlags = flags; - cdlInfo.set(eCDLog_AddrType_APURAM, addr); - return apuram[addr]; -} - -void SMP::op_write(uint16 addr, uint8 data) { - #if defined(CYCLE_ACCURATE) - tick(); - #endif - if((addr & 0xfff0) == 0x00f0) mmio_write(addr, data); - apuram[addr] = data; //all writes go to RAM, even MMIO writes -} - -void SMP::op_step() { - #define op_readpcfirst() op_read(regs.pc++,eCDLog_Flags_ExecFirst) - #define op_readpc() op_read(regs.pc++,eCDLog_Flags_ExecOperand) - #define op_readdp(addr) op_read((regs.p.p << 8) + addr,eCDLog_Flags_CPUData) - #define op_writedp(addr, data) op_write((regs.p.p << 8) + addr, data) - #define op_readaddr(addr) op_read(addr,eCDLog_Flags_CPUData) - #define op_writeaddr(addr, data) op_write(addr, data) - #define op_readstack() op_read(0x0100 | ++regs.sp,eCDLog_Flags_CPUData) - #define op_writestack(data) op_write(0x0100 | regs.sp--, data) - - #if defined(CYCLE_ACCURATE) - - if(opcode_cycle == 0) { - opcode_number = op_readpcfirst(); - opcode_cycle++; - } else switch(opcode_number) { - #include "core/opcycle_misc.cpp" - #include "core/opcycle_mov.cpp" - #include "core/opcycle_pc.cpp" - #include "core/opcycle_read.cpp" - #include "core/opcycle_rmw.cpp" - } - - #else - - unsigned opcode = op_readpcfirst(); - switch(opcode) { - #include "core/op_misc.cpp" - #include "core/op_mov.cpp" - #include "core/op_pc.cpp" - #include "core/op_read.cpp" - #include "core/op_rmw.cpp" - } - - //TODO: untaken branches should consume less cycles - - timer0.tick(cycle_count_table[opcode]); - timer1.tick(cycle_count_table[opcode]); - timer2.tick(cycle_count_table[opcode]); - - clock += cycle_table_cpu[opcode]; - dsp.clock -= cycle_table_dsp[opcode]; - synchronize_dsp(); - - #endif -} - -const unsigned SMP::cycle_count_table[256] = { - #define c 12 -//0 1 2 3 4 5 6 7 8 9 A B C D E F - 2,8,4,7, 3,4,3,6, 2,6,5,4, 5,4,6,8, //0 - 4,8,4,7, 4,5,5,6, 5,5,6,5, 2,2,4,6, //1 - 2,8,4,7, 3,4,3,6, 2,6,5,4, 5,4,7,4, //2 - 4,8,4,7, 4,5,5,6, 5,5,6,5, 2,2,3,8, //3 - - 2,8,4,7, 3,4,3,6, 2,6,4,4, 5,4,6,6, //4 - 4,8,4,7, 4,5,5,6, 5,5,4,5, 2,2,4,3, //5 - 2,8,4,7, 3,4,3,6, 2,6,4,4, 5,4,7,5, //6 - 4,8,4,7, 4,5,5,6, 5,5,5,5, 2,2,3,6, //7 - - 2,8,4,7, 3,4,3,6, 2,6,5,4, 5,2,4,5, //8 - 4,8,4,7, 4,5,5,6, 5,5,5,5, 2,2,c,5, //9 - 3,8,4,7, 3,4,3,6, 2,6,4,4, 5,2,4,4, //A - 4,8,4,7, 4,5,5,6, 5,5,5,5, 2,2,3,4, //B - - 3,8,4,7, 4,5,4,7, 2,5,6,4, 5,2,4,9, //C - 4,8,4,7, 5,6,6,7, 4,5,5,5, 2,2,8,3, //D - 2,8,4,7, 3,4,3,6, 2,4,5,3, 4,3,4,1, //E - 4,8,4,7, 4,5,5,6, 3,4,5,4, 2,2,6,1, //F - - #undef c -}; diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core/cc.sh b/waterbox/libsnes/bsnes/snes/alt/smp/core/cc.sh deleted file mode 100644 index 937b7139b9..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core/cc.sh +++ /dev/null @@ -1 +0,0 @@ -g++-4.5 -std=gnu++0x -I../../../.. -o generate generate.cpp diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core/generate.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/core/generate.cpp deleted file mode 100644 index 77ab3ed289..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core/generate.cpp +++ /dev/null @@ -1,154 +0,0 @@ -#include -#include -#include -using namespace nall; - -static bool cycle_accurate; - -struct opcode_t { - string name; - lstring args; - unsigned opcode; -}; - -void generate(const char *sourceFilename, const char *targetFilename) { - file fp; - fp.open(targetFilename, file::mode::write); - - string filedata; - filedata.readfile(sourceFilename); - filedata.replace("\r", ""); - - lstring block; - block.split("\n\n", filedata); - - foreach(data, block) { - lstring lines; - lines.split("\n", data); - - linear_vector array; - - unsigned sourceStart = 0; - foreach(line, lines, currentLine) { - line.transform("()", "``"); - lstring part; - part.split("`", line); - lstring arguments; - arguments.split(", ", part[1]); - - opcode_t opcode; - opcode.name = part[0]; - opcode.args = arguments; - opcode.opcode = hex(arguments[0]); - array.append(opcode); - - line.rtrim<1>(","); - if(line.endswith(" {")) { - line.rtrim<1>("{ "); - sourceStart = currentLine + 1; - break; - } - } - - if(cycle_accurate == false) { - foreach(opcode, array) { - fp.print("case 0x", hex<2>(opcode.opcode), ": {\n"); - - for(unsigned n = sourceStart; n < lines.size(); n++) { - if(lines[n] == "}") break; - - string output; - - if(lines[n].beginswith(" ")) { - output = lines[n]; - } else { - lstring part; - part.split<1>(":", lines[n]); - output = { " ", part[1] }; - } - - output.replace("$1", opcode.args[1]); - output.replace("$2", opcode.args[2]); - output.replace("$3", opcode.args[3]); - output.replace("$4", opcode.args[4]); - output.replace("$5", opcode.args[5]); - output.replace("$6", opcode.args[6]); - output.replace("$7", opcode.args[7]); - output.replace("$8", opcode.args[8]); - output.replace("end;", "break;"); - - fp.print(output, "\n"); - } - - fp.print(" break;\n"); - fp.print("}\n\n"); - } - } else { - foreach(opcode, array) { - fp.print("case 0x", hex<2>(opcode.opcode), ": {\n"); - fp.print(" switch(opcode_cycle++) {\n"); - - for(unsigned n = sourceStart; n < lines.size(); n++) { - if(lines[n] == "}") break; - - bool nextLineEndsCycle = false; - if(lines[n + 1] == "}") nextLineEndsCycle = true; - if(lines[n + 1].beginswith(" ") == false) nextLineEndsCycle = true; - - string output; - - if(lines[n].beginswith(" ")) { - output = { " ", lines[n] }; - } else { - lstring part; - part.split<1>(":", lines[n]); - fp.print(" case ", (unsigned)decimal(part[0]), ":\n"); - output = { " ", part[1] }; - } - - output.replace("$1", opcode.args[1]); - output.replace("$2", opcode.args[2]); - output.replace("$3", opcode.args[3]); - output.replace("$4", opcode.args[4]); - output.replace("$5", opcode.args[5]); - output.replace("$6", opcode.args[6]); - output.replace("$7", opcode.args[7]); - output.replace("$8", opcode.args[8]); - output.replace("end;", "{ opcode_cycle = 0; break; }"); - - fp.print(output, "\n"); - if(nextLineEndsCycle) { - if(lines[n + 1].beginswith("}")) { - fp.print(" opcode_cycle = 0;\n"); - } - fp.print(" break;\n"); - } - } - - fp.print(" }\n"); - fp.print(" break;\n"); - fp.print("}\n\n"); - } - } - } - - fp.close(); -} - -int main() { - cycle_accurate = false; - generate("op_misc.b", "op_misc.cpp"); - generate("op_mov.b", "op_mov.cpp" ); - generate("op_pc.b", "op_pc.cpp" ); - generate("op_read.b", "op_read.cpp"); - generate("op_rmw.b", "op_rmw.cpp" ); - - cycle_accurate = true; - generate("op_misc.b", "opcycle_misc.cpp"); - generate("op_mov.b", "opcycle_mov.cpp" ); - generate("op_pc.b", "opcycle_pc.cpp" ); - generate("op_read.b", "opcycle_read.cpp"); - generate("op_rmw.b", "opcycle_rmw.cpp" ); - - return 0; -} diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_misc.b b/waterbox/libsnes/bsnes/snes/alt/smp/core/op_misc.b deleted file mode 100644 index d38086fdd2..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_misc.b +++ /dev/null @@ -1,163 +0,0 @@ -nop(0x00) { -1:op_io(); -} - -sleep(0xef), -stop(0xff) { -1:op_io(); -2:op_io(); - regs.pc--; -} - -xcn(0x9f) { -1:op_io(); -2:op_io(); -3:op_io(); -4:op_io(); - regs.a = (regs.a >> 4) | (regs.a << 4); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -daa(0xdf) { -1:op_io(); -2:op_io(); - if(regs.p.c || (regs.a) > 0x99) { - regs.a += 0x60; - regs.p.c = 1; - } - if(regs.p.h || (regs.a & 15) > 0x09) { - regs.a += 0x06; - } - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -das(0xbe) { -1:op_io(); -2:op_io(); - if(!regs.p.c || (regs.a) > 0x99) { - regs.a -= 0x60; - regs.p.c = 0; - } - if(!regs.p.h || (regs.a & 15) > 0x09) { - regs.a -= 0x06; - } - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -clrc(0x60, regs.p.c = 0), -clrp(0x20, regs.p.p = 0), -setc(0x80, regs.p.c = 1), -setp(0x40, regs.p.p = 1) { -1:op_io(); - $1; -} - -clrv(0xe0) { -1:op_io(); - regs.p.v = 0; - regs.p.h = 0; -} - -notc(0xed) { -1:op_io(); -2:op_io(); - regs.p.c = !regs.p.c; -} - -ei(0xa0, 1), -di(0xc0, 0) { -1:op_io(); -2:op_io(); - regs.p.i = $1; -} - -set0_dp(0x02, rd |= 0x01), -clr0_dp(0x12, rd &= ~0x01), -set1_dp(0x22, rd |= 0x02), -clr1_dp(0x32, rd &= ~0x02), -set2_dp(0x42, rd |= 0x04), -clr2_dp(0x52, rd &= ~0x04), -set3_dp(0x62, rd |= 0x08), -clr3_dp(0x72, rd &= ~0x08), -set4_dp(0x82, rd |= 0x10), -clr4_dp(0x92, rd &= ~0x10), -set5_dp(0xa2, rd |= 0x20), -clr5_dp(0xb2, rd &= ~0x20), -set6_dp(0xc2, rd |= 0x40), -clr6_dp(0xd2, rd &= ~0x40), -set7_dp(0xe2, rd |= 0x80), -clr7_dp(0xf2, rd &= ~0x80) { -1:dp = op_readpc(); -2:rd = op_readdp(dp); -3:$1; - op_writedp(dp, rd); -} - -push_a(0x2d, a), -push_x(0x4d, x), -push_y(0x6d, y), -push_p(0x0d, p) { -1:op_io(); -2:op_io(); -3:op_writestack(regs.$1); -} - -pop_a(0xae, a), -pop_x(0xce, x), -pop_y(0xee, y), -pop_p(0x8e, p) { -1:op_io(); -2:op_io(); -3:regs.$1 = op_readstack(); -} - -mul_ya(0xcf) { -1:op_io(); -2:op_io(); -3:op_io(); -4:op_io(); -5:op_io(); -6:op_io(); -7:op_io(); -8:op_io(); - ya = regs.y * regs.a; - regs.a = ya; - regs.y = ya >> 8; - //result is set based on y (high-byte) only - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); -} - -div_ya_x(0x9e) { -1:op_io(); -2:op_io(); -3:op_io(); -4:op_io(); -5:op_io(); -6:op_io(); -7:op_io(); -8:op_io(); -9:op_io(); -10:op_io(); -11:op_io(); - ya = regs.ya; - //overflow set if quotient >= 256 - regs.p.v = !!(regs.y >= regs.x); - regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); - if(regs.y < (regs.x << 1)) { - //if quotient is <= 511 (will fit into 9-bit result) - regs.a = ya / regs.x; - regs.y = ya % regs.x; - } else { - //otherwise, the quotient won't fit into regs.p.v + regs.a - //this emulates the odd behavior of the S-SMP in this case - regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); - regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); - } - //result is set based on a (quotient) only - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); -} diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_misc.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/core/op_misc.cpp deleted file mode 100644 index 9a6a062de7..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_misc.cpp +++ /dev/null @@ -1,346 +0,0 @@ -case 0x00: { - op_io(); - break; -} - -case 0xef: { - op_io(); - op_io(); - regs.pc--; - break; -} - -case 0xff: { - op_io(); - op_io(); - regs.pc--; - break; -} - -case 0x9f: { - op_io(); - op_io(); - op_io(); - op_io(); - regs.a = (regs.a >> 4) | (regs.a << 4); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - break; -} - -case 0xdf: { - op_io(); - op_io(); - if(regs.p.c || (regs.a) > 0x99) { - regs.a += 0x60; - regs.p.c = 1; - } - if(regs.p.h || (regs.a & 15) > 0x09) { - regs.a += 0x06; - } - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - break; -} - -case 0xbe: { - op_io(); - op_io(); - if(!regs.p.c || (regs.a) > 0x99) { - regs.a -= 0x60; - regs.p.c = 0; - } - if(!regs.p.h || (regs.a & 15) > 0x09) { - regs.a -= 0x06; - } - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - break; -} - -case 0x60: { - op_io(); - regs.p.c = 0; - break; -} - -case 0x20: { - op_io(); - regs.p.p = 0; - break; -} - -case 0x80: { - op_io(); - regs.p.c = 1; - break; -} - -case 0x40: { - op_io(); - regs.p.p = 1; - break; -} - -case 0xe0: { - op_io(); - regs.p.v = 0; - regs.p.h = 0; - break; -} - -case 0xed: { - op_io(); - op_io(); - regs.p.c = !regs.p.c; - break; -} - -case 0xa0: { - op_io(); - op_io(); - regs.p.i = 1; - break; -} - -case 0xc0: { - op_io(); - op_io(); - regs.p.i = 0; - break; -} - -case 0x02: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x01; - op_writedp(dp, rd); - break; -} - -case 0x12: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x01; - op_writedp(dp, rd); - break; -} - -case 0x22: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x02; - op_writedp(dp, rd); - break; -} - -case 0x32: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x02; - op_writedp(dp, rd); - break; -} - -case 0x42: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x04; - op_writedp(dp, rd); - break; -} - -case 0x52: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x04; - op_writedp(dp, rd); - break; -} - -case 0x62: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x08; - op_writedp(dp, rd); - break; -} - -case 0x72: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x08; - op_writedp(dp, rd); - break; -} - -case 0x82: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x10; - op_writedp(dp, rd); - break; -} - -case 0x92: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x10; - op_writedp(dp, rd); - break; -} - -case 0xa2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x20; - op_writedp(dp, rd); - break; -} - -case 0xb2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x20; - op_writedp(dp, rd); - break; -} - -case 0xc2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x40; - op_writedp(dp, rd); - break; -} - -case 0xd2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x40; - op_writedp(dp, rd); - break; -} - -case 0xe2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x80; - op_writedp(dp, rd); - break; -} - -case 0xf2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x80; - op_writedp(dp, rd); - break; -} - -case 0x2d: { - op_io(); - op_io(); - op_writestack(regs.a); - break; -} - -case 0x4d: { - op_io(); - op_io(); - op_writestack(regs.x); - break; -} - -case 0x6d: { - op_io(); - op_io(); - op_writestack(regs.y); - break; -} - -case 0x0d: { - op_io(); - op_io(); - op_writestack(regs.p); - break; -} - -case 0xae: { - op_io(); - op_io(); - regs.a = op_readstack(); - break; -} - -case 0xce: { - op_io(); - op_io(); - regs.x = op_readstack(); - break; -} - -case 0xee: { - op_io(); - op_io(); - regs.y = op_readstack(); - break; -} - -case 0x8e: { - op_io(); - op_io(); - regs.p = op_readstack(); - break; -} - -case 0xcf: { - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - ya = regs.y * regs.a; - regs.a = ya; - regs.y = ya >> 8; - //result is set based on y (high-byte) only - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - break; -} - -case 0x9e: { - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - ya = regs.ya; - //overflow set if quotient >= 256 - regs.p.v = !!(regs.y >= regs.x); - regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); - if(regs.y < (regs.x << 1)) { - //if quotient is <= 511 (will fit into 9-bit result) - regs.a = ya / regs.x; - regs.y = ya % regs.x; - } else { - //otherwise, the quotient won't fit into regs.p.v + regs.a - //this emulates the odd behavior of the S-SMP in this case - regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); - regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); - } - //result is set based on a (quotient) only - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - break; -} - diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_mov.b b/waterbox/libsnes/bsnes/snes/alt/smp/core/op_mov.b deleted file mode 100644 index 37b1116b09..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_mov.b +++ /dev/null @@ -1,217 +0,0 @@ -mov_a_x(0x7d, a, x), -mov_a_y(0xdd, a, y), -mov_x_a(0x5d, x, a), -mov_y_a(0xfd, y, a), -mov_x_sp(0x9d, x, sp) { -1:op_io(); - regs.$1 = regs.$2; - regs.p.n = !!(regs.$1 & 0x80); - regs.p.z = (regs.$1 == 0); -} - -mov_sp_x(0xbd, sp, x) { -1:op_io(); - regs.$1 = regs.$2; -} - -mov_a_const(0xe8, a), -mov_x_const(0xcd, x), -mov_y_const(0x8d, y) { -1:regs.$1 = op_readpc(); - regs.p.n = !!(regs.$1 & 0x80); - regs.p.z = (regs.$1 == 0); -} - -mov_a_ix(0xe6) { -1:op_io(); -2:regs.a = op_readdp(regs.x); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -mov_a_ixinc(0xbf) { -1:op_io(); -2:regs.a = op_readdp(regs.x++); -3:op_io(); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -mov_a_dp(0xe4, a), -mov_x_dp(0xf8, x), -mov_y_dp(0xeb, y) { -1:sp = op_readpc(); -2:regs.$1 = op_readdp(sp); - regs.p.n = !!(regs.$1 & 0x80); - regs.p.z = (regs.$1 == 0); -} - -mov_a_dpx(0xf4, a, x), -mov_x_dpy(0xf9, x, y), -mov_y_dpx(0xfb, y, x) { -1:sp = op_readpc(); -2:op_io(); -3:regs.$1 = op_readdp(sp + regs.$2); - regs.p.n = !!(regs.$1 & 0x80); - regs.p.z = (regs.$1 == 0); -} - -mov_a_addr(0xe5, a), -mov_x_addr(0xe9, x), -mov_y_addr(0xec, y) { -1:sp = op_readpc(); -2:sp |= op_readpc() << 8; -3:regs.$1 = op_readaddr(sp); - regs.p.n = !!(regs.$1 & 0x80); - regs.p.z = (regs.$1 == 0); -} - -mov_a_addrx(0xf5, x), -mov_a_addry(0xf6, y) { -1:sp = op_readpc(); -2:sp |= op_readpc() << 8; -3:op_io(); -4:regs.a = op_readaddr(sp + regs.$1); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -mov_a_idpx(0xe7) { -1:dp = op_readpc() + regs.x; -2:op_io(); -3:sp = op_readdp(dp); -4:sp |= op_readdp(dp + 1) << 8; -5:regs.a = op_readaddr(sp); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -mov_a_idpy(0xf7) { -1:dp = op_readpc(); -2:op_io(); -3:sp = op_readdp(dp); -4:sp |= op_readdp(dp + 1) << 8; -5:regs.a = op_readaddr(sp + regs.y); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -mov_dp_dp(0xfa) { -1:sp = op_readpc(); -2:rd = op_readdp(sp); -3:dp = op_readpc(); -4:op_writedp(dp, rd); -} - -mov_dp_const(0x8f) { -1:rd = op_readpc(); -2:dp = op_readpc(); -3:op_readdp(dp); -4:op_writedp(dp, rd); -} - -mov_ix_a(0xc6) { -1:op_io(); -2:op_readdp(regs.x); -3:op_writedp(regs.x, regs.a); -} - -mov_ixinc_a(0xaf) { -1:op_io(); -2:op_io(); -3:op_writedp(regs.x++, regs.a); -} - -mov_dp_a(0xc4, a), -mov_dp_x(0xd8, x), -mov_dp_y(0xcb, y) { -1:dp = op_readpc(); -2:op_readdp(dp); -3:op_writedp(dp, regs.$1); -} - -mov_dpx_a(0xd4, x, a), -mov_dpy_x(0xd9, y, x), -mov_dpx_y(0xdb, x, y) { -1:dp = op_readpc(); -2:op_io(); - dp += regs.$1; -3:op_readdp(dp); -4:op_writedp(dp, regs.$2); -} - -mov_addr_a(0xc5, a), -mov_addr_x(0xc9, x), -mov_addr_y(0xcc, y) { -1:dp = op_readpc(); -2:dp |= op_readpc() << 8; -3:op_readaddr(dp); -4:op_writeaddr(dp, regs.$1); -} - -mov_addrx_a(0xd5, x), -mov_addry_a(0xd6, y) { -1:dp = op_readpc(); -2:dp |= op_readpc() << 8; -3:op_io(); - dp += regs.$1; -4:op_readaddr(dp); -5:op_writeaddr(dp, regs.a); -} - -mov_idpx_a(0xc7) { -1:sp = op_readpc(); -2:op_io(); - sp += regs.x; -3:dp = op_readdp(sp); -4:dp |= op_readdp(sp + 1) << 8; -5:op_readaddr(dp); -6:op_writeaddr(dp, regs.a); -} - -mov_idpy_a(0xd7) { -1:sp = op_readpc(); -2:dp = op_readdp(sp); -3:dp |= op_readdp(sp + 1) << 8; -4:op_io(); - dp += regs.y; -5:op_readaddr(dp); -6:op_writeaddr(dp, regs.a); -} - -movw_ya_dp(0xba) { -1:sp = op_readpc(); -2:regs.a = op_readdp(sp); -3:op_io(); -4:regs.y = op_readdp(sp + 1); - regs.p.n = !!(regs.ya & 0x8000); - regs.p.z = (regs.ya == 0); -} - -movw_dp_ya(0xda) { -1:dp = op_readpc(); -2:op_readdp(dp); -3:op_writedp(dp, regs.a); -4:op_writedp(dp + 1, regs.y); -} - -mov1_c_bit(0xaa) { -1:sp = op_readpc(); -2:sp |= op_readpc() << 8; -3:bit = sp >> 13; - sp &= 0x1fff; - rd = op_readaddr(sp); - regs.p.c = !!(rd & (1 << bit)); -} - -mov1_bit_c(0xca) { -1:dp = op_readpc(); -2:dp |= op_readpc() << 8; -3:bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - if(regs.p.c)rd |= (1 << bit); - else rd &= ~(1 << bit); -4:op_io(); -5:op_writeaddr(dp, rd); -} diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_mov.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/core/op_mov.cpp deleted file mode 100644 index f307942357..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_mov.cpp +++ /dev/null @@ -1,389 +0,0 @@ -case 0x7d: { - op_io(); - regs.a = regs.x; - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - break; -} - -case 0xdd: { - op_io(); - regs.a = regs.y; - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - break; -} - -case 0x5d: { - op_io(); - regs.x = regs.a; - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - break; -} - -case 0xfd: { - op_io(); - regs.y = regs.a; - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - break; -} - -case 0x9d: { - op_io(); - regs.x = regs.sp; - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - break; -} - -case 0xbd: { - op_io(); - regs.sp = regs.x; - break; -} - -case 0xe8: { - regs.a = op_readpc(); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - break; -} - -case 0xcd: { - regs.x = op_readpc(); - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - break; -} - -case 0x8d: { - regs.y = op_readpc(); - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - break; -} - -case 0xe6: { - op_io(); - regs.a = op_readdp(regs.x); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - break; -} - -case 0xbf: { - op_io(); - regs.a = op_readdp(regs.x++); - op_io(); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - break; -} - -case 0xe4: { - sp = op_readpc(); - regs.a = op_readdp(sp); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - break; -} - -case 0xf8: { - sp = op_readpc(); - regs.x = op_readdp(sp); - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - break; -} - -case 0xeb: { - sp = op_readpc(); - regs.y = op_readdp(sp); - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - break; -} - -case 0xf4: { - sp = op_readpc(); - op_io(); - regs.a = op_readdp(sp + regs.x); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - break; -} - -case 0xf9: { - sp = op_readpc(); - op_io(); - regs.x = op_readdp(sp + regs.y); - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - break; -} - -case 0xfb: { - sp = op_readpc(); - op_io(); - regs.y = op_readdp(sp + regs.x); - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - break; -} - -case 0xe5: { - sp = op_readpc(); - sp |= op_readpc() << 8; - regs.a = op_readaddr(sp); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - break; -} - -case 0xe9: { - sp = op_readpc(); - sp |= op_readpc() << 8; - regs.x = op_readaddr(sp); - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - break; -} - -case 0xec: { - sp = op_readpc(); - sp |= op_readpc() << 8; - regs.y = op_readaddr(sp); - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - break; -} - -case 0xf5: { - sp = op_readpc(); - sp |= op_readpc() << 8; - op_io(); - regs.a = op_readaddr(sp + regs.x); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - break; -} - -case 0xf6: { - sp = op_readpc(); - sp |= op_readpc() << 8; - op_io(); - regs.a = op_readaddr(sp + regs.y); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - break; -} - -case 0xe7: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - regs.a = op_readaddr(sp); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - break; -} - -case 0xf7: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - regs.a = op_readaddr(sp + regs.y); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - break; -} - -case 0xfa: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - op_writedp(dp, rd); - break; -} - -case 0x8f: { - rd = op_readpc(); - dp = op_readpc(); - op_readdp(dp); - op_writedp(dp, rd); - break; -} - -case 0xc6: { - op_io(); - op_readdp(regs.x); - op_writedp(regs.x, regs.a); - break; -} - -case 0xaf: { - op_io(); - op_io(); - op_writedp(regs.x++, regs.a); - break; -} - -case 0xc4: { - dp = op_readpc(); - op_readdp(dp); - op_writedp(dp, regs.a); - break; -} - -case 0xd8: { - dp = op_readpc(); - op_readdp(dp); - op_writedp(dp, regs.x); - break; -} - -case 0xcb: { - dp = op_readpc(); - op_readdp(dp); - op_writedp(dp, regs.y); - break; -} - -case 0xd4: { - dp = op_readpc(); - op_io(); - dp += regs.x; - op_readdp(dp); - op_writedp(dp, regs.a); - break; -} - -case 0xd9: { - dp = op_readpc(); - op_io(); - dp += regs.y; - op_readdp(dp); - op_writedp(dp, regs.x); - break; -} - -case 0xdb: { - dp = op_readpc(); - op_io(); - dp += regs.x; - op_readdp(dp); - op_writedp(dp, regs.y); - break; -} - -case 0xc5: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_readaddr(dp); - op_writeaddr(dp, regs.a); - break; -} - -case 0xc9: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_readaddr(dp); - op_writeaddr(dp, regs.x); - break; -} - -case 0xcc: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_readaddr(dp); - op_writeaddr(dp, regs.y); - break; -} - -case 0xd5: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - dp += regs.x; - op_readaddr(dp); - op_writeaddr(dp, regs.a); - break; -} - -case 0xd6: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - dp += regs.y; - op_readaddr(dp); - op_writeaddr(dp, regs.a); - break; -} - -case 0xc7: { - sp = op_readpc(); - op_io(); - sp += regs.x; - dp = op_readdp(sp); - dp |= op_readdp(sp + 1) << 8; - op_readaddr(dp); - op_writeaddr(dp, regs.a); - break; -} - -case 0xd7: { - sp = op_readpc(); - dp = op_readdp(sp); - dp |= op_readdp(sp + 1) << 8; - op_io(); - dp += regs.y; - op_readaddr(dp); - op_writeaddr(dp, regs.a); - break; -} - -case 0xba: { - sp = op_readpc(); - regs.a = op_readdp(sp); - op_io(); - regs.y = op_readdp(sp + 1); - regs.p.n = !!(regs.ya & 0x8000); - regs.p.z = (regs.ya == 0); - break; -} - -case 0xda: { - dp = op_readpc(); - op_readdp(dp); - op_writedp(dp, regs.a); - op_writedp(dp + 1, regs.y); - break; -} - -case 0xaa: { - sp = op_readpc(); - sp |= op_readpc() << 8; - bit = sp >> 13; - sp &= 0x1fff; - rd = op_readaddr(sp); - regs.p.c = !!(rd & (1 << bit)); - break; -} - -case 0xca: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - if(regs.p.c)rd |= (1 << bit); - else rd &= ~(1 << bit); - op_io(); - op_writeaddr(dp, rd); - break; -} - diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_pc.b b/waterbox/libsnes/bsnes/snes/alt/smp/core/op_pc.b deleted file mode 100644 index 4339377d84..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_pc.b +++ /dev/null @@ -1,179 +0,0 @@ -bra(0x2f, 0), -beq(0xf0, !regs.p.z), -bne(0xd0, regs.p.z), -bcs(0xb0, !regs.p.c), -bcc(0x90, regs.p.c), -bvs(0x70, !regs.p.v), -bvc(0x50, regs.p.v), -bmi(0x30, !regs.p.n), -bpl(0x10, regs.p.n) { -1:rd = op_readpc(); - if($1)end; -2:op_io(); -3:op_io(); - regs.pc += (int8)rd; -} - -bbs0(0x03, 0x01, !=), -bbc0(0x13, 0x01, ==), -bbs1(0x23, 0x02, !=), -bbc1(0x33, 0x02, ==), -bbs2(0x43, 0x04, !=), -bbc2(0x53, 0x04, ==), -bbs3(0x63, 0x08, !=), -bbc3(0x73, 0x08, ==), -bbs4(0x83, 0x10, !=), -bbc4(0x93, 0x10, ==), -bbs5(0xa3, 0x20, !=), -bbc5(0xb3, 0x20, ==), -bbs6(0xc3, 0x40, !=), -bbc6(0xd3, 0x40, ==), -bbs7(0xe3, 0x80, !=), -bbc7(0xf3, 0x80, ==) { -1:dp = op_readpc(); -2:sp = op_readdp(dp); -3:rd = op_readpc(); -4:op_io(); - if((sp & $1) $2 $1)end; -5:op_io(); -6:op_io(); - regs.pc += (int8)rd; -} - -cbne_dp(0x2e) { -1:dp = op_readpc(); -2:sp = op_readdp(dp); -3:rd = op_readpc(); -4:op_io(); - if(regs.a == sp)end; -5:op_io(); -6:op_io(); - regs.pc += (int8)rd; -} - -cbne_dpx(0xde) { -1:dp = op_readpc(); -2:op_io(); -3:sp = op_readdp(dp + regs.x); -4:rd = op_readpc(); -5:op_io(); - if(regs.a == sp)end; -6:op_io(); -7:op_io(); - regs.pc += (int8)rd; -} - -dbnz_dp(0x6e) { -1:dp = op_readpc(); -2:wr = op_readdp(dp); -3:op_writedp(dp, --wr); -4:rd = op_readpc(); - if(wr == 0x00)end; -5:op_io(); -6:op_io(); - regs.pc += (int8)rd; -} - -dbnz_y(0xfe) { -1:rd = op_readpc(); -2:op_io(); - regs.y--; -3:op_io(); - if(regs.y == 0x00)end; -4:op_io(); -5:op_io(); - regs.pc += (int8)rd; -} - -jmp_addr(0x5f) { -1:rd = op_readpc(); -2:rd |= op_readpc() << 8; - regs.pc = rd; -} - -jmp_iaddrx(0x1f) { -1:dp = op_readpc(); -2:dp |= op_readpc() << 8; -3:op_io(); - dp += regs.x; -4:rd = op_readaddr(dp); -5:rd |= op_readaddr(dp + 1) << 8; - regs.pc = rd; -} - -call(0x3f) { -1:rd = op_readpc(); -2:rd |= op_readpc() << 8; -3:op_io(); -4:op_io(); -5:op_io(); -6:op_writestack(regs.pc >> 8); -7:op_writestack(regs.pc); - regs.pc = rd; -} - -pcall(0x4f) { -1:rd = op_readpc(); -2:op_io(); -3:op_io(); -4:op_writestack(regs.pc >> 8); -5:op_writestack(regs.pc); - regs.pc = 0xff00 | rd; -} - -tcall_0(0x01, 0), -tcall_1(0x11, 1), -tcall_2(0x21, 2), -tcall_3(0x31, 3), -tcall_4(0x41, 4), -tcall_5(0x51, 5), -tcall_6(0x61, 6), -tcall_7(0x71, 7), -tcall_8(0x81, 8), -tcall_9(0x91, 9), -tcall_10(0xa1, 10), -tcall_11(0xb1, 11), -tcall_12(0xc1, 12), -tcall_13(0xd1, 13), -tcall_14(0xe1, 14), -tcall_15(0xf1, 15) { -1:dp = 0xffde - ($1 << 1); - rd = op_readaddr(dp); -2:rd |= op_readaddr(dp + 1) << 8; -3:op_io(); -4:op_io(); -5:op_io(); -6:op_writestack(regs.pc >> 8); -7:op_writestack(regs.pc); - regs.pc = rd; -} - -brk(0x0f) { -1:rd = op_readaddr(0xffde); -2:rd |= op_readaddr(0xffdf) << 8; -3:op_io(); -4:op_io(); -5:op_writestack(regs.pc >> 8); -6:op_writestack(regs.pc); -7:op_writestack(regs.p); - regs.pc = rd; - regs.p.b = 1; - regs.p.i = 0; -} - -ret(0x6f) { -1:rd = op_readstack(); -2:rd |= op_readstack() << 8; -3:op_io(); -4:op_io(); - regs.pc = rd; -} - -reti(0x7f) { -1:regs.p = op_readstack(); -2:rd = op_readstack(); -3:rd |= op_readstack() << 8; -4:op_io(); -5:op_io(); - regs.pc = rd; -} diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_pc.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/core/op_pc.cpp deleted file mode 100644 index 763a033eaa..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_pc.cpp +++ /dev/null @@ -1,603 +0,0 @@ -case 0x2f: { - rd = op_readpc(); - if(0)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0xf0: { - rd = op_readpc(); - if(!regs.p.z)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0xd0: { - rd = op_readpc(); - if(regs.p.z)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0xb0: { - rd = op_readpc(); - if(!regs.p.c)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x90: { - rd = op_readpc(); - if(regs.p.c)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x70: { - rd = op_readpc(); - if(!regs.p.v)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x50: { - rd = op_readpc(); - if(regs.p.v)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x30: { - rd = op_readpc(); - if(!regs.p.n)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x10: { - rd = op_readpc(); - if(regs.p.n)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x03: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x01) != 0x01)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x13: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x01) == 0x01)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x23: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x02) != 0x02)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x33: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x02) == 0x02)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x43: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x04) != 0x04)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x53: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x04) == 0x04)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x63: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x08) != 0x08)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x73: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x08) == 0x08)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x83: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x10) != 0x10)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x93: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x10) == 0x10)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0xa3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x20) != 0x20)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0xb3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x20) == 0x20)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0xc3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x40) != 0x40)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0xd3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x40) == 0x40)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0xe3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x80) != 0x80)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0xf3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x80) == 0x80)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x2e: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if(regs.a == sp)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0xde: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp + regs.x); - rd = op_readpc(); - op_io(); - if(regs.a == sp)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x6e: { - dp = op_readpc(); - wr = op_readdp(dp); - op_writedp(dp, --wr); - rd = op_readpc(); - if(wr == 0x00)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0xfe: { - rd = op_readpc(); - op_io(); - regs.y--; - op_io(); - if(regs.y == 0x00)break; - op_io(); - op_io(); - regs.pc += (int8)rd; - break; -} - -case 0x5f: { - rd = op_readpc(); - rd |= op_readpc() << 8; - regs.pc = rd; - break; -} - -case 0x1f: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - dp += regs.x; - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - regs.pc = rd; - break; -} - -case 0x3f: { - rd = op_readpc(); - rd |= op_readpc() << 8; - op_io(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; - break; -} - -case 0x4f: { - rd = op_readpc(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = 0xff00 | rd; - break; -} - -case 0x01: { - dp = 0xffde - (0 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; - break; -} - -case 0x11: { - dp = 0xffde - (1 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; - break; -} - -case 0x21: { - dp = 0xffde - (2 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; - break; -} - -case 0x31: { - dp = 0xffde - (3 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; - break; -} - -case 0x41: { - dp = 0xffde - (4 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; - break; -} - -case 0x51: { - dp = 0xffde - (5 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; - break; -} - -case 0x61: { - dp = 0xffde - (6 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; - break; -} - -case 0x71: { - dp = 0xffde - (7 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; - break; -} - -case 0x81: { - dp = 0xffde - (8 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; - break; -} - -case 0x91: { - dp = 0xffde - (9 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; - break; -} - -case 0xa1: { - dp = 0xffde - (10 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; - break; -} - -case 0xb1: { - dp = 0xffde - (11 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; - break; -} - -case 0xc1: { - dp = 0xffde - (12 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; - break; -} - -case 0xd1: { - dp = 0xffde - (13 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; - break; -} - -case 0xe1: { - dp = 0xffde - (14 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; - break; -} - -case 0xf1: { - dp = 0xffde - (15 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(); - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; - break; -} - -case 0x0f: { - rd = op_readaddr(0xffde); - rd |= op_readaddr(0xffdf) << 8; - op_io(); - op_io(); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - op_writestack(regs.p); - regs.pc = rd; - regs.p.b = 1; - regs.p.i = 0; - break; -} - -case 0x6f: { - rd = op_readstack(); - rd |= op_readstack() << 8; - op_io(); - op_io(); - regs.pc = rd; - break; -} - -case 0x7f: { - regs.p = op_readstack(); - rd = op_readstack(); - rd |= op_readstack() << 8; - op_io(); - op_io(); - regs.pc = rd; - break; -} - diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_read.b b/waterbox/libsnes/bsnes/snes/alt/smp/core/op_read.b deleted file mode 100644 index d46e1d2f3f..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_read.b +++ /dev/null @@ -1,205 +0,0 @@ -adc_a_const(0x88, adc, a), -and_a_const(0x28, and, a), -cmp_a_const(0x68, cmp, a), -cmp_x_const(0xc8, cmp, x), -cmp_y_const(0xad, cmp, y), -eor_a_const(0x48, eor, a), -or_a_const(0x08, or, a), -sbc_a_const(0xa8, sbc, a) { -1:rd = op_readpc(); - regs.$2 = op_$1(regs.$2, rd); -} - -adc_a_ix(0x86, adc), -and_a_ix(0x26, and), -cmp_a_ix(0x66, cmp), -eor_a_ix(0x46, eor), -or_a_ix(0x06, or), -sbc_a_ix(0xa6, sbc) { -1:op_io(); -2:rd = op_readdp(regs.x); - regs.a = op_$1(regs.a, rd); -} - -adc_a_dp(0x84, adc, a), -and_a_dp(0x24, and, a), -cmp_a_dp(0x64, cmp, a), -cmp_x_dp(0x3e, cmp, x), -cmp_y_dp(0x7e, cmp, y), -eor_a_dp(0x44, eor, a), -or_a_dp(0x04, or, a), -sbc_a_dp(0xa4, sbc, a) { -1:dp = op_readpc(); -2:rd = op_readdp(dp); - regs.$2 = op_$1(regs.$2, rd); -} - -adc_a_dpx(0x94, adc), -and_a_dpx(0x34, and), -cmp_a_dpx(0x74, cmp), -eor_a_dpx(0x54, eor), -or_a_dpx(0x14, or), -sbc_a_dpx(0xb4, sbc) { -1:dp = op_readpc(); -2:op_io(); -3:rd = op_readdp(dp + regs.x); - regs.a = op_$1(regs.a, rd); -} - -adc_a_addr(0x85, adc, a), -and_a_addr(0x25, and, a), -cmp_a_addr(0x65, cmp, a), -cmp_x_addr(0x1e, cmp, x), -cmp_y_addr(0x5e, cmp, y), -eor_a_addr(0x45, eor, a), -or_a_addr(0x05, or, a), -sbc_a_addr(0xa5, sbc, a) { -1:dp = op_readpc(); -2:dp |= op_readpc() << 8; -3:rd = op_readaddr(dp); - regs.$2 = op_$1(regs.$2, rd); -} - -adc_a_addrx(0x95, adc, x), -adc_a_addry(0x96, adc, y), -and_a_addrx(0x35, and, x), -and_a_addry(0x36, and, y), -cmp_a_addrx(0x75, cmp, x), -cmp_a_addry(0x76, cmp, y), -eor_a_addrx(0x55, eor, x), -eor_a_addry(0x56, eor, y), -or_a_addrx(0x15, or, x), -or_a_addry(0x16, or, y), -sbc_a_addrx(0xb5, sbc, x), -sbc_a_addry(0xb6, sbc, y) { -1:dp = op_readpc(); -2:dp |= op_readpc() << 8; -3:op_io(); -4:rd = op_readaddr(dp + regs.$2); - regs.a = op_$1(regs.a, rd); -} - -adc_a_idpx(0x87, adc), -and_a_idpx(0x27, and), -cmp_a_idpx(0x67, cmp), -eor_a_idpx(0x47, eor), -or_a_idpx(0x07, or), -sbc_a_idpx(0xa7, sbc) { -1:dp = op_readpc() + regs.x; -2:op_io(); -3:sp = op_readdp(dp); -4:sp |= op_readdp(dp + 1) << 8; -5:rd = op_readaddr(sp); - regs.a = op_$1(regs.a, rd); -} - -adc_a_idpy(0x97, adc), -and_a_idpy(0x37, and), -cmp_a_idpy(0x77, cmp), -eor_a_idpy(0x57, eor), -or_a_idpy(0x17, or), -sbc_a_idpy(0xb7, sbc) { -1:dp = op_readpc(); -2:op_io(); -3:sp = op_readdp(dp); -4:sp |= op_readdp(dp + 1) << 8; -5:rd = op_readaddr(sp + regs.y); - regs.a = op_$1(regs.a, rd); -} - -adc_ix_iy(0x99, adc, 1), -and_ix_iy(0x39, and, 1), -cmp_ix_iy(0x79, cmp, 0), -eor_ix_iy(0x59, eor, 1), -or_ix_iy(0x19, or, 1), -sbc_ix_iy(0xb9, sbc, 1) { -1:op_io(); -2:rd = op_readdp(regs.y); -3:wr = op_readdp(regs.x); - wr = op_$1(wr, rd); -4:($2) ? op_writedp(regs.x, wr) : op_io(); -} - -adc_dp_dp(0x89, adc, 1), -and_dp_dp(0x29, and, 1), -cmp_dp_dp(0x69, cmp, 0), -eor_dp_dp(0x49, eor, 1), -or_dp_dp(0x09, or, 1), -sbc_dp_dp(0xa9, sbc, 1) { -1:sp = op_readpc(); -2:rd = op_readdp(sp); -3:dp = op_readpc(); -4:wr = op_readdp(dp); -5:wr = op_$1(wr, rd); - ($2) ? op_writedp(dp, wr) : op_io(); -} - -adc_dp_const(0x98, adc, 1), -and_dp_const(0x38, and, 1), -cmp_dp_const(0x78, cmp, 0), -eor_dp_const(0x58, eor, 1), -or_dp_const(0x18, or, 1), -sbc_dp_const(0xb8, sbc, 1) { -1:rd = op_readpc(); -2:dp = op_readpc(); -3:wr = op_readdp(dp); -4:wr = op_$1(wr, rd); - ($2) ? op_writedp(dp, wr) : op_io(); -} - -addw_ya_dp(0x7a, addw), -subw_ya_dp(0x9a, subw) { -1:dp = op_readpc(); -2:rd = op_readdp(dp); -3:op_io(); -4:rd |= op_readdp(dp + 1) << 8; - regs.ya = op_$1(regs.ya, rd); -} - -cmpw_ya_dp(0x5a) { -1:dp = op_readpc(); -2:rd = op_readdp(dp); -3:rd |= op_readdp(dp + 1) << 8; - op_cmpw(regs.ya, rd); -} - -and1_bit(0x4a, !!), -and1_notbit(0x6a, !) { -1:dp = op_readpc(); -2:dp |= op_readpc() << 8; -3:bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - regs.p.c = regs.p.c & $1(rd & (1 << bit)); -} - -eor1_bit(0x8a) { -1:dp = op_readpc(); -2:dp |= op_readpc() << 8; -3:bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); -4:op_io(); - regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); -} - -not1_bit(0xea) { -1:dp = op_readpc(); -2:dp |= op_readpc() << 8; -3:bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - rd ^= (1 << bit); -4:op_writeaddr(dp, rd); -} - -or1_bit(0x0a, !!), -or1_notbit(0x2a, !) { -1:dp = op_readpc(); -2:dp |= op_readpc() << 8; -3:bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); -4:op_io(); - regs.p.c = regs.p.c | $1(rd & (1 << bit)); -} diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_read.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/core/op_read.cpp deleted file mode 100644 index 2a16a3c8de..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_read.cpp +++ /dev/null @@ -1,744 +0,0 @@ -case 0x88: { - rd = op_readpc(); - regs.a = op_adc(regs.a, rd); - break; -} - -case 0x28: { - rd = op_readpc(); - regs.a = op_and(regs.a, rd); - break; -} - -case 0x68: { - rd = op_readpc(); - regs.a = op_cmp(regs.a, rd); - break; -} - -case 0xc8: { - rd = op_readpc(); - regs.x = op_cmp(regs.x, rd); - break; -} - -case 0xad: { - rd = op_readpc(); - regs.y = op_cmp(regs.y, rd); - break; -} - -case 0x48: { - rd = op_readpc(); - regs.a = op_eor(regs.a, rd); - break; -} - -case 0x08: { - rd = op_readpc(); - regs.a = op_or(regs.a, rd); - break; -} - -case 0xa8: { - rd = op_readpc(); - regs.a = op_sbc(regs.a, rd); - break; -} - -case 0x86: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_adc(regs.a, rd); - break; -} - -case 0x26: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_and(regs.a, rd); - break; -} - -case 0x66: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_cmp(regs.a, rd); - break; -} - -case 0x46: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_eor(regs.a, rd); - break; -} - -case 0x06: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_or(regs.a, rd); - break; -} - -case 0xa6: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_sbc(regs.a, rd); - break; -} - -case 0x84: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_adc(regs.a, rd); - break; -} - -case 0x24: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_and(regs.a, rd); - break; -} - -case 0x64: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_cmp(regs.a, rd); - break; -} - -case 0x3e: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.x = op_cmp(regs.x, rd); - break; -} - -case 0x7e: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.y = op_cmp(regs.y, rd); - break; -} - -case 0x44: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_eor(regs.a, rd); - break; -} - -case 0x04: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_or(regs.a, rd); - break; -} - -case 0xa4: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_sbc(regs.a, rd); - break; -} - -case 0x94: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_adc(regs.a, rd); - break; -} - -case 0x34: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_and(regs.a, rd); - break; -} - -case 0x74: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_cmp(regs.a, rd); - break; -} - -case 0x54: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_eor(regs.a, rd); - break; -} - -case 0x14: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_or(regs.a, rd); - break; -} - -case 0xb4: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_sbc(regs.a, rd); - break; -} - -case 0x85: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_adc(regs.a, rd); - break; -} - -case 0x25: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_and(regs.a, rd); - break; -} - -case 0x65: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_cmp(regs.a, rd); - break; -} - -case 0x1e: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.x = op_cmp(regs.x, rd); - break; -} - -case 0x5e: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.y = op_cmp(regs.y, rd); - break; -} - -case 0x45: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_eor(regs.a, rd); - break; -} - -case 0x05: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_or(regs.a, rd); - break; -} - -case 0xa5: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_sbc(regs.a, rd); - break; -} - -case 0x95: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_adc(regs.a, rd); - break; -} - -case 0x96: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_adc(regs.a, rd); - break; -} - -case 0x35: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_and(regs.a, rd); - break; -} - -case 0x36: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_and(regs.a, rd); - break; -} - -case 0x75: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_cmp(regs.a, rd); - break; -} - -case 0x76: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_cmp(regs.a, rd); - break; -} - -case 0x55: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_eor(regs.a, rd); - break; -} - -case 0x56: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_eor(regs.a, rd); - break; -} - -case 0x15: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_or(regs.a, rd); - break; -} - -case 0x16: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_or(regs.a, rd); - break; -} - -case 0xb5: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_sbc(regs.a, rd); - break; -} - -case 0xb6: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_sbc(regs.a, rd); - break; -} - -case 0x87: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_adc(regs.a, rd); - break; -} - -case 0x27: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_and(regs.a, rd); - break; -} - -case 0x67: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_cmp(regs.a, rd); - break; -} - -case 0x47: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_eor(regs.a, rd); - break; -} - -case 0x07: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_or(regs.a, rd); - break; -} - -case 0xa7: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_sbc(regs.a, rd); - break; -} - -case 0x97: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_adc(regs.a, rd); - break; -} - -case 0x37: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_and(regs.a, rd); - break; -} - -case 0x77: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_cmp(regs.a, rd); - break; -} - -case 0x57: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_eor(regs.a, rd); - break; -} - -case 0x17: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_or(regs.a, rd); - break; -} - -case 0xb7: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_sbc(regs.a, rd); - break; -} - -case 0x99: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_adc(wr, rd); - (1) ? op_writedp(regs.x, wr) : op_io(); - break; -} - -case 0x39: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_and(wr, rd); - (1) ? op_writedp(regs.x, wr) : op_io(); - break; -} - -case 0x79: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_cmp(wr, rd); - (0) ? op_writedp(regs.x, wr) : op_io(); - break; -} - -case 0x59: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_eor(wr, rd); - (1) ? op_writedp(regs.x, wr) : op_io(); - break; -} - -case 0x19: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_or(wr, rd); - (1) ? op_writedp(regs.x, wr) : op_io(); - break; -} - -case 0xb9: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_sbc(wr, rd); - (1) ? op_writedp(regs.x, wr) : op_io(); - break; -} - -case 0x89: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_adc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - break; -} - -case 0x29: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_and(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - break; -} - -case 0x69: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_cmp(wr, rd); - (0) ? op_writedp(dp, wr) : op_io(); - break; -} - -case 0x49: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_eor(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - break; -} - -case 0x09: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_or(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - break; -} - -case 0xa9: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_sbc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - break; -} - -case 0x98: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_adc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - break; -} - -case 0x38: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_and(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - break; -} - -case 0x78: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_cmp(wr, rd); - (0) ? op_writedp(dp, wr) : op_io(); - break; -} - -case 0x58: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_eor(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - break; -} - -case 0x18: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_or(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - break; -} - -case 0xb8: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_sbc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - break; -} - -case 0x7a: { - dp = op_readpc(); - rd = op_readdp(dp); - op_io(); - rd |= op_readdp(dp + 1) << 8; - regs.ya = op_addw(regs.ya, rd); - break; -} - -case 0x9a: { - dp = op_readpc(); - rd = op_readdp(dp); - op_io(); - rd |= op_readdp(dp + 1) << 8; - regs.ya = op_subw(regs.ya, rd); - break; -} - -case 0x5a: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= op_readdp(dp + 1) << 8; - op_cmpw(regs.ya, rd); - break; -} - -case 0x4a: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - regs.p.c = regs.p.c & !!(rd & (1 << bit)); - break; -} - -case 0x6a: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - regs.p.c = regs.p.c & !(rd & (1 << bit)); - break; -} - -case 0x8a: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - op_io(); - regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); - break; -} - -case 0xea: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - rd ^= (1 << bit); - op_writeaddr(dp, rd); - break; -} - -case 0x0a: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - op_io(); - regs.p.c = regs.p.c | !!(rd & (1 << bit)); - break; -} - -case 0x2a: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - op_io(); - regs.p.c = regs.p.c | !(rd & (1 << bit)); - break; -} - diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_rmw.b b/waterbox/libsnes/bsnes/snes/alt/smp/core/op_rmw.b deleted file mode 100644 index 327082a139..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_rmw.b +++ /dev/null @@ -1,74 +0,0 @@ -inc_a(0xbc, inc, a), -inc_x(0x3d, inc, x), -inc_y(0xfc, inc, y), -dec_a(0x9c, dec, a), -dec_x(0x1d, dec, x), -dec_y(0xdc, dec, y), -asl_a(0x1c, asl, a), -lsr_a(0x5c, lsr, a), -rol_a(0x3c, rol, a), -ror_a(0x7c, ror, a) { -1:op_io(); - regs.$2 = op_$1(regs.$2); -} - -inc_dp(0xab, inc), -dec_dp(0x8b, dec), -asl_dp(0x0b, asl), -lsr_dp(0x4b, lsr), -rol_dp(0x2b, rol), -ror_dp(0x6b, ror) { -1:dp = op_readpc(); -2:rd = op_readdp(dp); -3:rd = op_$1(rd); - op_writedp(dp, rd); -} - -inc_dpx(0xbb, inc), -dec_dpx(0x9b, dec), -asl_dpx(0x1b, asl), -lsr_dpx(0x5b, lsr), -rol_dpx(0x3b, rol), -ror_dpx(0x7b, ror) { -1:dp = op_readpc(); -2:op_io(); -3:rd = op_readdp(dp + regs.x); -4:rd = op_$1(rd); - op_writedp(dp + regs.x, rd); -} - -inc_addr(0xac, inc), -dec_addr(0x8c, dec), -asl_addr(0x0c, asl), -lsr_addr(0x4c, lsr), -rol_addr(0x2c, rol), -ror_addr(0x6c, ror) { -1:dp = op_readpc(); -2:dp |= op_readpc() << 8; -3:rd = op_readaddr(dp); -4:rd = op_$1(rd); - op_writeaddr(dp, rd); -} - -tset_addr_a(0x0e, |), -tclr_addr_a(0x4e, &~) { -1:dp = op_readpc(); -2:dp |= op_readpc() << 8; -3:rd = op_readaddr(dp); - regs.p.n = !!((regs.a - rd) & 0x80); - regs.p.z = ((regs.a - rd) == 0); -4:op_readaddr(dp); -5:op_writeaddr(dp, rd $1 regs.a); -} - -incw_dp(0x3a, ++), -decw_dp(0x1a, --) { -1:dp = op_readpc(); -2:rd = op_readdp(dp); - rd$1; -3:op_writedp(dp++, rd); -4:rd += op_readdp(dp) << 8; -5:op_writedp(dp, rd >> 8); - regs.p.n = !!(rd & 0x8000); - regs.p.z = (rd == 0); -} diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_rmw.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/core/op_rmw.cpp deleted file mode 100644 index f89ecacff6..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core/op_rmw.cpp +++ /dev/null @@ -1,262 +0,0 @@ -case 0xbc: { - op_io(); - regs.a = op_inc(regs.a); - break; -} - -case 0x3d: { - op_io(); - regs.x = op_inc(regs.x); - break; -} - -case 0xfc: { - op_io(); - regs.y = op_inc(regs.y); - break; -} - -case 0x9c: { - op_io(); - regs.a = op_dec(regs.a); - break; -} - -case 0x1d: { - op_io(); - regs.x = op_dec(regs.x); - break; -} - -case 0xdc: { - op_io(); - regs.y = op_dec(regs.y); - break; -} - -case 0x1c: { - op_io(); - regs.a = op_asl(regs.a); - break; -} - -case 0x5c: { - op_io(); - regs.a = op_lsr(regs.a); - break; -} - -case 0x3c: { - op_io(); - regs.a = op_rol(regs.a); - break; -} - -case 0x7c: { - op_io(); - regs.a = op_ror(regs.a); - break; -} - -case 0xab: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_inc(rd); - op_writedp(dp, rd); - break; -} - -case 0x8b: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_dec(rd); - op_writedp(dp, rd); - break; -} - -case 0x0b: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_asl(rd); - op_writedp(dp, rd); - break; -} - -case 0x4b: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_lsr(rd); - op_writedp(dp, rd); - break; -} - -case 0x2b: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_rol(rd); - op_writedp(dp, rd); - break; -} - -case 0x6b: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_ror(rd); - op_writedp(dp, rd); - break; -} - -case 0xbb: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_inc(rd); - op_writedp(dp + regs.x, rd); - break; -} - -case 0x9b: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_dec(rd); - op_writedp(dp + regs.x, rd); - break; -} - -case 0x1b: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_asl(rd); - op_writedp(dp + regs.x, rd); - break; -} - -case 0x5b: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_lsr(rd); - op_writedp(dp + regs.x, rd); - break; -} - -case 0x3b: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_rol(rd); - op_writedp(dp + regs.x, rd); - break; -} - -case 0x7b: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_ror(rd); - op_writedp(dp + regs.x, rd); - break; -} - -case 0xac: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_inc(rd); - op_writeaddr(dp, rd); - break; -} - -case 0x8c: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_dec(rd); - op_writeaddr(dp, rd); - break; -} - -case 0x0c: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_asl(rd); - op_writeaddr(dp, rd); - break; -} - -case 0x4c: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_lsr(rd); - op_writeaddr(dp, rd); - break; -} - -case 0x2c: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_rol(rd); - op_writeaddr(dp, rd); - break; -} - -case 0x6c: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_ror(rd); - op_writeaddr(dp, rd); - break; -} - -case 0x0e: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.p.n = !!((regs.a - rd) & 0x80); - regs.p.z = ((regs.a - rd) == 0); - op_readaddr(dp); - op_writeaddr(dp, rd | regs.a); - break; -} - -case 0x4e: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.p.n = !!((regs.a - rd) & 0x80); - regs.p.z = ((regs.a - rd) == 0); - op_readaddr(dp); - op_writeaddr(dp, rd &~ regs.a); - break; -} - -case 0x3a: { - dp = op_readpc(); - rd = op_readdp(dp); - rd++; - op_writedp(dp++, rd); - rd += op_readdp(dp) << 8; - op_writedp(dp, rd >> 8); - regs.p.n = !!(rd & 0x8000); - regs.p.z = (rd == 0); - break; -} - -case 0x1a: { - dp = op_readpc(); - rd = op_readdp(dp); - rd--; - op_writedp(dp++, rd); - rd += op_readdp(dp) << 8; - op_writedp(dp, rd >> 8); - regs.p.n = !!(rd & 0x8000); - regs.p.z = (rd == 0); - break; -} - diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_misc.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_misc.cpp deleted file mode 100644 index 963f9fc21c..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_misc.cpp +++ /dev/null @@ -1,696 +0,0 @@ -case 0x00: { - switch(opcode_cycle++) { - case 1: - op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0xef: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - regs.pc--; - opcode_cycle = 0; - break; - } - break; -} - -case 0xff: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - regs.pc--; - opcode_cycle = 0; - break; - } - break; -} - -case 0x9f: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_io(); - break; - case 4: - op_io(); - regs.a = (regs.a >> 4) | (regs.a << 4); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xdf: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - if(regs.p.c || (regs.a) > 0x99) { - regs.a += 0x60; - regs.p.c = 1; - } - if(regs.p.h || (regs.a & 15) > 0x09) { - regs.a += 0x06; - } - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xbe: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - if(!regs.p.c || (regs.a) > 0x99) { - regs.a -= 0x60; - regs.p.c = 0; - } - if(!regs.p.h || (regs.a & 15) > 0x09) { - regs.a -= 0x06; - } - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0x60: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.p.c = 0; - opcode_cycle = 0; - break; - } - break; -} - -case 0x20: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.p.p = 0; - opcode_cycle = 0; - break; - } - break; -} - -case 0x80: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.p.c = 1; - opcode_cycle = 0; - break; - } - break; -} - -case 0x40: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.p.p = 1; - opcode_cycle = 0; - break; - } - break; -} - -case 0xe0: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.p.v = 0; - regs.p.h = 0; - opcode_cycle = 0; - break; - } - break; -} - -case 0xed: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - regs.p.c = !regs.p.c; - opcode_cycle = 0; - break; - } - break; -} - -case 0xa0: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - regs.p.i = 1; - opcode_cycle = 0; - break; - } - break; -} - -case 0xc0: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - regs.p.i = 0; - opcode_cycle = 0; - break; - } - break; -} - -case 0x02: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x01; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x12: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x01; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x22: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x02; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x32: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x02; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x42: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x04; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x52: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x04; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x62: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x08; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x72: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x08; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x82: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x10; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x92: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x10; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xa2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x20; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xb2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x20; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xc2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x40; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xd2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x40; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xe2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x80; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xf2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x80; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x2d: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_writestack(regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0x4d: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_writestack(regs.x); - opcode_cycle = 0; - break; - } - break; -} - -case 0x6d: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_writestack(regs.y); - opcode_cycle = 0; - break; - } - break; -} - -case 0x0d: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_writestack(regs.p); - opcode_cycle = 0; - break; - } - break; -} - -case 0xae: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - regs.a = op_readstack(); - opcode_cycle = 0; - break; - } - break; -} - -case 0xce: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - regs.x = op_readstack(); - opcode_cycle = 0; - break; - } - break; -} - -case 0xee: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - regs.y = op_readstack(); - opcode_cycle = 0; - break; - } - break; -} - -case 0x8e: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - regs.p = op_readstack(); - opcode_cycle = 0; - break; - } - break; -} - -case 0xcf: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_io(); - break; - case 7: - op_io(); - break; - case 8: - op_io(); - ya = regs.y * regs.a; - regs.a = ya; - regs.y = ya >> 8; - //result is set based on y (high-byte) only - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0x9e: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_io(); - break; - case 7: - op_io(); - break; - case 8: - op_io(); - break; - case 9: - op_io(); - break; - case 10: - op_io(); - break; - case 11: - op_io(); - ya = regs.ya; - //overflow set if quotient >= 256 - regs.p.v = !!(regs.y >= regs.x); - regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); - if(regs.y < (regs.x << 1)) { - //if quotient is <= 511 (will fit into 9-bit result) - regs.a = ya / regs.x; - regs.y = ya % regs.x; - } else { - //otherwise, the quotient won't fit into regs.p.v + regs.a - //this emulates the odd behavior of the S-SMP in this case - regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); - regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); - } - //result is set based on a (quotient) only - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } - break; -} - diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_mov.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_mov.cpp deleted file mode 100644 index 635c7ca587..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_mov.cpp +++ /dev/null @@ -1,806 +0,0 @@ -case 0x7d: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = regs.x; - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xdd: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = regs.y; - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0x5d: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.x = regs.a; - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xfd: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.y = regs.a; - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0x9d: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.x = regs.sp; - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xbd: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.sp = regs.x; - opcode_cycle = 0; - break; - } - break; -} - -case 0xe8: { - switch(opcode_cycle++) { - case 1: - regs.a = op_readpc(); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xcd: { - switch(opcode_cycle++) { - case 1: - regs.x = op_readpc(); - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0x8d: { - switch(opcode_cycle++) { - case 1: - regs.y = op_readpc(); - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xe6: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - regs.a = op_readdp(regs.x); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xbf: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - regs.a = op_readdp(regs.x++); - break; - case 3: - op_io(); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xe4: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - regs.a = op_readdp(sp); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xf8: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - regs.x = op_readdp(sp); - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xeb: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - regs.y = op_readdp(sp); - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xf4: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - regs.a = op_readdp(sp + regs.x); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xf9: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - regs.x = op_readdp(sp + regs.y); - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xfb: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - regs.y = op_readdp(sp + regs.x); - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xe5: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - sp |= op_readpc() << 8; - break; - case 3: - regs.a = op_readaddr(sp); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xe9: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - sp |= op_readpc() << 8; - break; - case 3: - regs.x = op_readaddr(sp); - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xec: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - sp |= op_readpc() << 8; - break; - case 3: - regs.y = op_readaddr(sp); - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xf5: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - sp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - regs.a = op_readaddr(sp + regs.x); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xf6: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - sp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - regs.a = op_readaddr(sp + regs.y); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xe7: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - regs.a = op_readaddr(sp); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xf7: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - regs.a = op_readaddr(sp + regs.y); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xfa: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x8f: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - op_readdp(dp); - break; - case 4: - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xc6: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_readdp(regs.x); - break; - case 3: - op_writedp(regs.x, regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0xaf: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_writedp(regs.x++, regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0xc4: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_readdp(dp); - break; - case 3: - op_writedp(dp, regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0xd8: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_readdp(dp); - break; - case 3: - op_writedp(dp, regs.x); - opcode_cycle = 0; - break; - } - break; -} - -case 0xcb: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_readdp(dp); - break; - case 3: - op_writedp(dp, regs.y); - opcode_cycle = 0; - break; - } - break; -} - -case 0xd4: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - dp += regs.x; - break; - case 3: - op_readdp(dp); - break; - case 4: - op_writedp(dp, regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0xd9: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - dp += regs.y; - break; - case 3: - op_readdp(dp); - break; - case 4: - op_writedp(dp, regs.x); - opcode_cycle = 0; - break; - } - break; -} - -case 0xdb: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - dp += regs.x; - break; - case 3: - op_readdp(dp); - break; - case 4: - op_writedp(dp, regs.y); - opcode_cycle = 0; - break; - } - break; -} - -case 0xc5: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_readaddr(dp); - break; - case 4: - op_writeaddr(dp, regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0xc9: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_readaddr(dp); - break; - case 4: - op_writeaddr(dp, regs.x); - opcode_cycle = 0; - break; - } - break; -} - -case 0xcc: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_readaddr(dp); - break; - case 4: - op_writeaddr(dp, regs.y); - opcode_cycle = 0; - break; - } - break; -} - -case 0xd5: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - dp += regs.x; - break; - case 4: - op_readaddr(dp); - break; - case 5: - op_writeaddr(dp, regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0xd6: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - dp += regs.y; - break; - case 4: - op_readaddr(dp); - break; - case 5: - op_writeaddr(dp, regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0xc7: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - op_io(); - sp += regs.x; - break; - case 3: - dp = op_readdp(sp); - break; - case 4: - dp |= op_readdp(sp + 1) << 8; - break; - case 5: - op_readaddr(dp); - break; - case 6: - op_writeaddr(dp, regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0xd7: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - dp = op_readdp(sp); - break; - case 3: - dp |= op_readdp(sp + 1) << 8; - break; - case 4: - op_io(); - dp += regs.y; - break; - case 5: - op_readaddr(dp); - break; - case 6: - op_writeaddr(dp, regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0xba: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - regs.a = op_readdp(sp); - break; - case 3: - op_io(); - break; - case 4: - regs.y = op_readdp(sp + 1); - regs.p.n = !!(regs.ya & 0x8000); - regs.p.z = (regs.ya == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0xda: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_readdp(dp); - break; - case 3: - op_writedp(dp, regs.a); - break; - case 4: - op_writedp(dp + 1, regs.y); - opcode_cycle = 0; - break; - } - break; -} - -case 0xaa: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - sp |= op_readpc() << 8; - break; - case 3: - bit = sp >> 13; - sp &= 0x1fff; - rd = op_readaddr(sp); - regs.p.c = !!(rd & (1 << bit)); - opcode_cycle = 0; - break; - } - break; -} - -case 0xca: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - if(regs.p.c)rd |= (1 << bit); - else rd &= ~(1 << bit); - break; - case 4: - op_io(); - break; - case 5: - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_pc.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_pc.cpp deleted file mode 100644 index 1cdda64724..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_pc.cpp +++ /dev/null @@ -1,1347 +0,0 @@ -case 0x2f: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(0){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0xf0: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(!regs.p.z){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0xd0: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(regs.p.z){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0xb0: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(!regs.p.c){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x90: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(regs.p.c){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x70: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(!regs.p.v){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x50: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(regs.p.v){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x30: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(!regs.p.n){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x10: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(regs.p.n){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x03: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x01) != 0x01){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x13: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x01) == 0x01){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x23: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x02) != 0x02){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x33: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x02) == 0x02){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x43: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x04) != 0x04){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x53: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x04) == 0x04){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x63: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x08) != 0x08){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x73: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x08) == 0x08){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x83: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x10) != 0x10){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x93: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x10) == 0x10){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0xa3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x20) != 0x20){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0xb3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x20) == 0x20){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0xc3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x40) != 0x40){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0xd3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x40) == 0x40){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0xe3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x80) != 0x80){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0xf3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x80) == 0x80){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x2e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if(regs.a == sp){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0xde: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp + regs.x); - break; - case 4: - rd = op_readpc(); - break; - case 5: - op_io(); - if(regs.a == sp){ opcode_cycle = 0; break; } - break; - case 6: - op_io(); - break; - case 7: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x6e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - wr = op_readdp(dp); - break; - case 3: - op_writedp(dp, --wr); - break; - case 4: - rd = op_readpc(); - if(wr == 0x00){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0xfe: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - op_io(); - regs.y--; - break; - case 3: - op_io(); - if(regs.y == 0x00){ opcode_cycle = 0; break; } - break; - case 4: - op_io(); - break; - case 5: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x5f: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - rd |= op_readpc() << 8; - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x1f: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - dp += regs.x; - break; - case 4: - rd = op_readaddr(dp); - break; - case 5: - rd |= op_readaddr(dp + 1) << 8; - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x3f: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - rd |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x4f: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - op_io(); - break; - case 4: - op_writestack(regs.pc >> 8); - break; - case 5: - op_writestack(regs.pc); - regs.pc = 0xff00 | rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x01: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (0 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x11: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (1 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x21: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (2 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x31: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (3 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x41: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (4 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x51: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (5 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x61: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (6 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x71: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (7 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x81: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (8 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x91: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (9 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0xa1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (10 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0xb1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (11 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0xc1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (12 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0xd1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (13 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0xe1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (14 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0xf1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (15 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x0f: { - switch(opcode_cycle++) { - case 1: - rd = op_readaddr(0xffde); - break; - case 2: - rd |= op_readaddr(0xffdf) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_writestack(regs.pc >> 8); - break; - case 6: - op_writestack(regs.pc); - break; - case 7: - op_writestack(regs.p); - regs.pc = rd; - regs.p.b = 1; - regs.p.i = 0; - opcode_cycle = 0; - break; - } - break; -} - -case 0x6f: { - switch(opcode_cycle++) { - case 1: - rd = op_readstack(); - break; - case 2: - rd |= op_readstack() << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - -case 0x7f: { - switch(opcode_cycle++) { - case 1: - regs.p = op_readstack(); - break; - case 2: - rd = op_readstack(); - break; - case 3: - rd |= op_readstack() << 8; - break; - case 4: - op_io(); - break; - case 5: - op_io(); - regs.pc = rd; - opcode_cycle = 0; - break; - } - break; -} - diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_read.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_read.cpp deleted file mode 100644 index 6c19f3a94c..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_read.cpp +++ /dev/null @@ -1,1599 +0,0 @@ -case 0x88: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x28: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x68: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xc8: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.x = op_cmp(regs.x, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xad: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.y = op_cmp(regs.y, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x48: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x08: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xa8: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x86: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x26: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x66: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x46: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x06: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xa6: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x84: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x24: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x64: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x3e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.x = op_cmp(regs.x, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x7e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.y = op_cmp(regs.y, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x44: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x04: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xa4: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x94: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x34: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x74: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x54: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x14: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xb4: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x85: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x25: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x65: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x1e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.x = op_cmp(regs.x, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x5e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.y = op_cmp(regs.y, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x45: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x05: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xa5: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x95: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x96: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x35: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x36: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x75: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x76: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x55: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x56: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x15: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x16: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xb5: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xb6: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x87: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x27: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x67: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x47: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x07: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xa7: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x97: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x37: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x77: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x57: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x17: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xb7: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x99: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_adc(wr, rd); - break; - case 4: - (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0x39: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_and(wr, rd); - break; - case 4: - (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0x79: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_cmp(wr, rd); - break; - case 4: - (0) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0x59: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_eor(wr, rd); - break; - case 4: - (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0x19: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_or(wr, rd); - break; - case 4: - (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0xb9: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_sbc(wr, rd); - break; - case 4: - (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0x89: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_adc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0x29: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_and(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0x69: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_cmp(wr, rd); - (0) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0x49: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_eor(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0x09: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_or(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0xa9: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_sbc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0x98: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_adc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0x38: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_and(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0x78: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_cmp(wr, rd); - (0) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0x58: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_eor(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0x18: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_or(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0xb8: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_sbc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } - break; -} - -case 0x7a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - op_io(); - break; - case 4: - rd |= op_readdp(dp + 1) << 8; - regs.ya = op_addw(regs.ya, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x9a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - op_io(); - break; - case 4: - rd |= op_readdp(dp + 1) << 8; - regs.ya = op_subw(regs.ya, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x5a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= op_readdp(dp + 1) << 8; - op_cmpw(regs.ya, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x4a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - regs.p.c = regs.p.c & !!(rd & (1 << bit)); - opcode_cycle = 0; - break; - } - break; -} - -case 0x6a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - regs.p.c = regs.p.c & !(rd & (1 << bit)); - opcode_cycle = 0; - break; - } - break; -} - -case 0x8a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - break; - case 4: - op_io(); - regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); - opcode_cycle = 0; - break; - } - break; -} - -case 0xea: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - rd ^= (1 << bit); - break; - case 4: - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x0a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - break; - case 4: - op_io(); - regs.p.c = regs.p.c | !!(rd & (1 << bit)); - opcode_cycle = 0; - break; - } - break; -} - -case 0x2a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - break; - case 4: - op_io(); - regs.p.c = regs.p.c | !(rd & (1 << bit)); - opcode_cycle = 0; - break; - } - break; -} - diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_rmw.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_rmw.cpp deleted file mode 100644 index eca62f0230..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/core/opcycle_rmw.cpp +++ /dev/null @@ -1,550 +0,0 @@ -case 0xbc: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_inc(regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0x3d: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.x = op_inc(regs.x); - opcode_cycle = 0; - break; - } - break; -} - -case 0xfc: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.y = op_inc(regs.y); - opcode_cycle = 0; - break; - } - break; -} - -case 0x9c: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_dec(regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0x1d: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.x = op_dec(regs.x); - opcode_cycle = 0; - break; - } - break; -} - -case 0xdc: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.y = op_dec(regs.y); - opcode_cycle = 0; - break; - } - break; -} - -case 0x1c: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_asl(regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0x5c: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_lsr(regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0x3c: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_rol(regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0x7c: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_ror(regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0xab: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_inc(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x8b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_dec(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x0b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_asl(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x4b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_lsr(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x2b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_rol(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x6b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_ror(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xbb: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_inc(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x9b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_dec(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x1b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_asl(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x5b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_lsr(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x3b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_rol(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x7b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_ror(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0xac: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_inc(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x8c: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_dec(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x0c: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_asl(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x4c: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_lsr(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x2c: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_rol(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x6c: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_ror(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } - break; -} - -case 0x0e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.p.n = !!((regs.a - rd) & 0x80); - regs.p.z = ((regs.a - rd) == 0); - break; - case 4: - op_readaddr(dp); - break; - case 5: - op_writeaddr(dp, rd | regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0x4e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.p.n = !!((regs.a - rd) & 0x80); - regs.p.z = ((regs.a - rd) == 0); - break; - case 4: - op_readaddr(dp); - break; - case 5: - op_writeaddr(dp, rd &~ regs.a); - opcode_cycle = 0; - break; - } - break; -} - -case 0x3a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - rd++; - break; - case 3: - op_writedp(dp++, rd); - break; - case 4: - rd += op_readdp(dp) << 8; - break; - case 5: - op_writedp(dp, rd >> 8); - regs.p.n = !!(rd & 0x8000); - regs.p.z = (rd == 0); - opcode_cycle = 0; - break; - } - break; -} - -case 0x1a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - rd--; - break; - case 3: - op_writedp(dp++, rd); - break; - case 4: - rd += op_readdp(dp) << 8; - break; - case 5: - op_writedp(dp, rd >> 8); - regs.p.n = !!(rd & 0x8000); - regs.p.z = (rd == 0); - opcode_cycle = 0; - break; - } - break; -} - diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/disassembler.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/disassembler.cpp deleted file mode 100644 index fb76ae922d..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/disassembler.cpp +++ /dev/null @@ -1,304 +0,0 @@ -uint8 SMP::disassemble_read(uint16 addr) { - if(addr >= 0xffc0) return smp.iplrom[addr & 0x3f]; - return smp.apuram[addr]; -} - -uint16 SMP::relb(int8 offset, int op_len) { - uint16 pc = regs.pc + op_len; - return pc + offset; -} - -void SMP::disassemble_opcode(char *output, uint16 addr) { - char *s, t[512]; - uint8 op, op0, op1; - uint16 opw, opdp0, opdp1; - s = output; - - sprintf(s, "..%.4x ", addr); - - op = disassemble_read(addr + 0); - op0 = disassemble_read(addr + 1); - op1 = disassemble_read(addr + 2); - opw = (op0) | (op1 << 8); - opdp0 = ((unsigned)regs.p.p << 8) + op0; - opdp1 = ((unsigned)regs.p.p << 8) + op1; - - strcpy(t, " "); - - switch(op) { - case 0x00: sprintf(t, "nop"); break; - case 0x01: sprintf(t, "tcall 0"); break; - case 0x02: sprintf(t, "set0 $%.3x", opdp0); break; - case 0x03: sprintf(t, "bbs0 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0x04: sprintf(t, "or a,$%.3x", opdp0); break; - case 0x05: sprintf(t, "or a,$%.4x", opw); break; - case 0x06: sprintf(t, "or a,(x)"); break; - case 0x07: sprintf(t, "or a,($%.3x+x)", opdp0); break; - case 0x08: sprintf(t, "or a,#$%.2x", op0); break; - case 0x09: sprintf(t, "or $%.3x,$%.3x", opdp1, opdp0); break; - case 0x0a: sprintf(t, "or1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break; - case 0x0b: sprintf(t, "asl $%.3x", opdp0); break; - case 0x0c: sprintf(t, "asl $%.4x", opw); break; - case 0x0d: sprintf(t, "push p"); break; - case 0x0e: sprintf(t, "tset $%.4x,a", opw); break; - case 0x0f: sprintf(t, "brk"); break; - case 0x10: sprintf(t, "bpl $%.4x", relb(op0, 2)); break; - case 0x11: sprintf(t, "tcall 1"); break; - case 0x12: sprintf(t, "clr0 $%.3x", opdp0); break; - case 0x13: sprintf(t, "bbc0 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0x14: sprintf(t, "or a,$%.3x+x", opdp0); break; - case 0x15: sprintf(t, "or a,$%.4x+x", opw); break; - case 0x16: sprintf(t, "or a,$%.4x+y", opw); break; - case 0x17: sprintf(t, "or a,($%.3x)+y", opdp0); break; - case 0x18: sprintf(t, "or $%.3x,#$%.2x", opdp1, op0); break; - case 0x19: sprintf(t, "or (x),(y)"); break; - case 0x1a: sprintf(t, "decw $%.3x", opdp0); break; - case 0x1b: sprintf(t, "asl $%.3x+x", opdp0); break; - case 0x1c: sprintf(t, "asl a"); break; - case 0x1d: sprintf(t, "dec x"); break; - case 0x1e: sprintf(t, "cmp x,$%.4x", opw); break; - case 0x1f: sprintf(t, "jmp ($%.4x+x)", opw); break; - case 0x20: sprintf(t, "clrp"); break; - case 0x21: sprintf(t, "tcall 2"); break; - case 0x22: sprintf(t, "set1 $%.3x", opdp0); break; - case 0x23: sprintf(t, "bbs1 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0x24: sprintf(t, "and a,$%.3x", opdp0); break; - case 0x25: sprintf(t, "and a,$%.4x", opw); break; - case 0x26: sprintf(t, "and a,(x)"); break; - case 0x27: sprintf(t, "and a,($%.3x+x)", opdp0); break; - case 0x28: sprintf(t, "and a,#$%.2x", op0); break; - case 0x29: sprintf(t, "and $%.3x,$%.3x", opdp1, opdp0); break; - case 0x2a: sprintf(t, "or1 c,!$%.4x:%d", opw & 0x1fff, opw >> 13); break; - case 0x2b: sprintf(t, "rol $%.3x", opdp0); break; - case 0x2c: sprintf(t, "rol $%.4x", opw); break; - case 0x2d: sprintf(t, "push a"); break; - case 0x2e: sprintf(t, "cbne $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0x2f: sprintf(t, "bra $%.4x", relb(op0, 2)); break; - case 0x30: sprintf(t, "bmi $%.4x", relb(op0, 2)); break; - case 0x31: sprintf(t, "tcall 3"); break; - case 0x32: sprintf(t, "clr1 $%.3x", opdp0); break; - case 0x33: sprintf(t, "bbc1 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0x34: sprintf(t, "and a,$%.3x+x", opdp0); break; - case 0x35: sprintf(t, "and a,$%.4x+x", opw); break; - case 0x36: sprintf(t, "and a,$%.4x+y", opw); break; - case 0x37: sprintf(t, "and a,($%.3x)+y", opdp0); break; - case 0x38: sprintf(t, "and $%.3x,#$%.2x", opdp1, op0); break; - case 0x39: sprintf(t, "and (x),(y)"); break; - case 0x3a: sprintf(t, "incw $%.3x", opdp0); break; - case 0x3b: sprintf(t, "rol $%.3x+x", opdp0); break; - case 0x3c: sprintf(t, "rol a"); break; - case 0x3d: sprintf(t, "inc x"); break; - case 0x3e: sprintf(t, "cmp x,$%.3x", opdp0); break; - case 0x3f: sprintf(t, "call $%.4x", opw); break; - case 0x40: sprintf(t, "setp"); break; - case 0x41: sprintf(t, "tcall 4"); break; - case 0x42: sprintf(t, "set2 $%.3x", opdp0); break; - case 0x43: sprintf(t, "bbs2 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0x44: sprintf(t, "eor a,$%.3x", opdp0); break; - case 0x45: sprintf(t, "eor a,$%.4x", opw); break; - case 0x46: sprintf(t, "eor a,(x)"); break; - case 0x47: sprintf(t, "eor a,($%.3x+x)", opdp0); break; - case 0x48: sprintf(t, "eor a,#$%.2x", op0); break; - case 0x49: sprintf(t, "eor $%.3x,$%.3x", opdp1, opdp0); break; - case 0x4a: sprintf(t, "and1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break; - case 0x4b: sprintf(t, "lsr $%.3x", opdp0); break; - case 0x4c: sprintf(t, "lsr $%.4x", opw); break; - case 0x4d: sprintf(t, "push x"); break; - case 0x4e: sprintf(t, "tclr $%.4x,a", opw); break; - case 0x4f: sprintf(t, "pcall $ff%.2x", op0); break; - case 0x50: sprintf(t, "bvc $%.4x", relb(op0, 2)); break; - case 0x51: sprintf(t, "tcall 5"); break; - case 0x52: sprintf(t, "clr2 $%.3x", opdp0); break; - case 0x53: sprintf(t, "bbc2 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0x54: sprintf(t, "eor a,$%.3x+x", opdp0); break; - case 0x55: sprintf(t, "eor a,$%.4x+x", opw); break; - case 0x56: sprintf(t, "eor a,$%.4x+y", opw); break; - case 0x57: sprintf(t, "eor a,($%.3x)+y", opdp0); break; - case 0x58: sprintf(t, "eor $%.3x,#$%.2x", opdp1, op0); break; - case 0x59: sprintf(t, "eor (x),(y)"); break; - case 0x5a: sprintf(t, "cmpw ya,$%.3x", opdp0); break; - case 0x5b: sprintf(t, "lsr $%.3x+x", opdp0); break; - case 0x5c: sprintf(t, "lsr a"); break; - case 0x5d: sprintf(t, "mov x,a"); break; - case 0x5e: sprintf(t, "cmp y,$%.4x", opw); break; - case 0x5f: sprintf(t, "jmp $%.4x", opw); break; - case 0x60: sprintf(t, "clrc"); break; - case 0x61: sprintf(t, "tcall 6"); break; - case 0x62: sprintf(t, "set3 $%.3x", opdp0); break; - case 0x63: sprintf(t, "bbs3 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0x64: sprintf(t, "cmp a,$%.3x", opdp0); break; - case 0x65: sprintf(t, "cmp a,$%.4x", opw); break; - case 0x66: sprintf(t, "cmp a,(x)"); break; - case 0x67: sprintf(t, "cmp a,($%.3x+x)", opdp0); break; - case 0x68: sprintf(t, "cmp a,#$%.2x", op0); break; - case 0x69: sprintf(t, "cmp $%.3x,$%.3x", opdp1, opdp0); break; - case 0x6a: sprintf(t, "and1 c,!$%.4x:%d", opw & 0x1fff, opw >> 13); break; - case 0x6b: sprintf(t, "ror $%.3x", opdp0); break; - case 0x6c: sprintf(t, "ror $%.4x", opw); break; - case 0x6d: sprintf(t, "push y"); break; - case 0x6e: sprintf(t, "dbnz $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0x6f: sprintf(t, "ret"); break; - case 0x70: sprintf(t, "bvs $%.4x", relb(op0, 2)); break; - case 0x71: sprintf(t, "tcall 7"); break; - case 0x72: sprintf(t, "clr3 $%.3x", opdp0); break; - case 0x73: sprintf(t, "bbc3 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0x74: sprintf(t, "cmp a,$%.3x+x", opdp0); break; - case 0x75: sprintf(t, "cmp a,$%.4x+x", opw); break; - case 0x76: sprintf(t, "cmp a,$%.4x+y", opw); break; - case 0x77: sprintf(t, "cmp a,($%.3x)+y", opdp0); break; - case 0x78: sprintf(t, "cmp $%.3x,#$%.2x", opdp1, op0); break; - case 0x79: sprintf(t, "cmp (x),(y)"); break; - case 0x7a: sprintf(t, "addw ya,$%.3x", opdp0); break; - case 0x7b: sprintf(t, "ror $%.3x+x", opdp0); break; - case 0x7c: sprintf(t, "ror a"); break; - case 0x7d: sprintf(t, "mov a,x"); break; - case 0x7e: sprintf(t, "cmp y,$%.3x", opdp0); break; - case 0x7f: sprintf(t, "reti"); break; - case 0x80: sprintf(t, "setc"); break; - case 0x81: sprintf(t, "tcall 8"); break; - case 0x82: sprintf(t, "set4 $%.3x", opdp0); break; - case 0x83: sprintf(t, "bbs4 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0x84: sprintf(t, "adc a,$%.3x", opdp0); break; - case 0x85: sprintf(t, "adc a,$%.4x", opw); break; - case 0x86: sprintf(t, "adc a,(x)"); break; - case 0x87: sprintf(t, "adc a,($%.3x+x)", opdp0); break; - case 0x88: sprintf(t, "adc a,#$%.2x", op0); break; - case 0x89: sprintf(t, "adc $%.3x,$%.3x", opdp1, opdp0); break; - case 0x8a: sprintf(t, "eor1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break; - case 0x8b: sprintf(t, "dec $%.3x", opdp0); break; - case 0x8c: sprintf(t, "dec $%.4x", opw); break; - case 0x8d: sprintf(t, "mov y,#$%.2x", op0); break; - case 0x8e: sprintf(t, "pop p"); break; - case 0x8f: sprintf(t, "mov $%.3x,#$%.2x", opdp1, op0); break; - case 0x90: sprintf(t, "bcc $%.4x", relb(op0, 2)); break; - case 0x91: sprintf(t, "tcall 9"); break; - case 0x92: sprintf(t, "clr4 $%.3x", opdp0); break; - case 0x93: sprintf(t, "bbc4 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0x94: sprintf(t, "adc a,$%.3x+x", opdp0); break; - case 0x95: sprintf(t, "adc a,$%.4x+x", opw); break; - case 0x96: sprintf(t, "adc a,$%.4x+y", opw); break; - case 0x97: sprintf(t, "adc a,($%.3x)+y", opdp0); break; - case 0x98: sprintf(t, "adc $%.3x,#$%.2x", opdp1, op0); break; - case 0x99: sprintf(t, "adc (x),(y)"); break; - case 0x9a: sprintf(t, "subw ya,$%.3x", opdp0); break; - case 0x9b: sprintf(t, "dec $%.3x+x", opdp0); break; - case 0x9c: sprintf(t, "dec a"); break; - case 0x9d: sprintf(t, "mov x,sp"); break; - case 0x9e: sprintf(t, "div ya,x"); break; - case 0x9f: sprintf(t, "xcn a"); break; - case 0xa0: sprintf(t, "ei"); break; - case 0xa1: sprintf(t, "tcall 10"); break; - case 0xa2: sprintf(t, "set5 $%.3x", opdp0); break; - case 0xa3: sprintf(t, "bbs5 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0xa4: sprintf(t, "sbc a,$%.3x", opdp0); break; - case 0xa5: sprintf(t, "sbc a,$%.4x", opw); break; - case 0xa6: sprintf(t, "sbc a,(x)"); break; - case 0xa7: sprintf(t, "sbc a,($%.3x+x)", opdp0); break; - case 0xa8: sprintf(t, "sbc a,#$%.2x", op0); break; - case 0xa9: sprintf(t, "sbc $%.3x,$%.3x", opdp1, opdp0); break; - case 0xaa: sprintf(t, "mov1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break; - case 0xab: sprintf(t, "inc $%.3x", opdp0); break; - case 0xac: sprintf(t, "inc $%.4x", opw); break; - case 0xad: sprintf(t, "cmp y,#$%.2x", op0); break; - case 0xae: sprintf(t, "pop a"); break; - case 0xaf: sprintf(t, "mov (x)+,a"); break; - case 0xb0: sprintf(t, "bcs $%.4x", relb(op0, 2)); break; - case 0xb1: sprintf(t, "tcall 11"); break; - case 0xb2: sprintf(t, "clr5 $%.3x", opdp0); break; - case 0xb3: sprintf(t, "bbc5 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0xb4: sprintf(t, "sbc a,$%.3x+x", opdp0); break; - case 0xb5: sprintf(t, "sbc a,$%.4x+x", opw); break; - case 0xb6: sprintf(t, "sbc a,$%.4x+y", opw); break; - case 0xb7: sprintf(t, "sbc a,($%.3x)+y", opdp0); break; - case 0xb8: sprintf(t, "sbc $%.3x,#$%.2x", opdp1, op0); break; - case 0xb9: sprintf(t, "sbc (x),(y)"); break; - case 0xba: sprintf(t, "movw ya,$%.3x", opdp0); break; - case 0xbb: sprintf(t, "inc $%.3x+x", opdp0); break; - case 0xbc: sprintf(t, "inc a"); break; - case 0xbd: sprintf(t, "mov sp,x"); break; - case 0xbe: sprintf(t, "das a"); break; - case 0xbf: sprintf(t, "mov a,(x)+"); break; - case 0xc0: sprintf(t, "di"); break; - case 0xc1: sprintf(t, "tcall 12"); break; - case 0xc2: sprintf(t, "set6 $%.3x", opdp0); break; - case 0xc3: sprintf(t, "bbs6 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0xc4: sprintf(t, "mov $%.3x,a", opdp0); break; - case 0xc5: sprintf(t, "mov $%.4x,a", opw); break; - case 0xc6: sprintf(t, "mov (x),a"); break; - case 0xc7: sprintf(t, "mov ($%.3x+x),a", opdp0); break; - case 0xc8: sprintf(t, "cmp x,#$%.2x", op0); break; - case 0xc9: sprintf(t, "mov $%.4x,x", opw); break; - case 0xca: sprintf(t, "mov1 $%.4x:%d,c", opw & 0x1fff, opw >> 13); break; - case 0xcb: sprintf(t, "mov $%.3x,y", opdp0); break; - case 0xcc: sprintf(t, "mov $%.4x,y", opw); break; - case 0xcd: sprintf(t, "mov x,#$%.2x", op0); break; - case 0xce: sprintf(t, "pop x"); break; - case 0xcf: sprintf(t, "mul ya"); break; - case 0xd0: sprintf(t, "bne $%.4x", relb(op0, 2)); break; - case 0xd1: sprintf(t, "tcall 13"); break; - case 0xd2: sprintf(t, "clr6 $%.3x", opdp0); break; - case 0xd3: sprintf(t, "bbc6 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0xd4: sprintf(t, "mov $%.3x+x,a", opdp0); break; - case 0xd5: sprintf(t, "mov $%.4x+x,a", opw); break; - case 0xd6: sprintf(t, "mov $%.4x+y,a", opw); break; - case 0xd7: sprintf(t, "mov ($%.3x)+y,a", opdp0); break; - case 0xd8: sprintf(t, "mov $%.3x,x", opdp0); break; - case 0xd9: sprintf(t, "mov $%.3x+y,x", opdp0); break; - case 0xda: sprintf(t, "movw $%.3x,ya", opdp0); break; - case 0xdb: sprintf(t, "mov $%.3x+x,y", opdp0); break; - case 0xdc: sprintf(t, "dec y"); break; - case 0xdd: sprintf(t, "mov a,y"); break; - case 0xde: sprintf(t, "cbne $%.3x+x,$%.4x", opdp0, relb(op1, 3)); break; - case 0xdf: sprintf(t, "daa a"); break; - case 0xe0: sprintf(t, "clrv"); break; - case 0xe1: sprintf(t, "tcall 14"); break; - case 0xe2: sprintf(t, "set7 $%.3x", opdp0); break; - case 0xe3: sprintf(t, "bbs7 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0xe4: sprintf(t, "mov a,$%.3x", opdp0); break; - case 0xe5: sprintf(t, "mov a,$%.4x", opw); break; - case 0xe6: sprintf(t, "mov a,(x)"); break; - case 0xe7: sprintf(t, "mov a,($%.3x+x)", opdp0); break; - case 0xe8: sprintf(t, "mov a,#$%.2x", op0); break; - case 0xe9: sprintf(t, "mov x,$%.4x", opw); break; - case 0xea: sprintf(t, "not1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break; - case 0xeb: sprintf(t, "mov y,$%.3x", opdp0); break; - case 0xec: sprintf(t, "mov y,$%.4x", opw); break; - case 0xed: sprintf(t, "notc"); break; - case 0xee: sprintf(t, "pop y"); break; - case 0xef: sprintf(t, "sleep"); break; - case 0xf0: sprintf(t, "beq $%.4x", relb(op0, 2)); break; - case 0xf1: sprintf(t, "tcall 15"); break; - case 0xf2: sprintf(t, "clr7 $%.3x", opdp0); break; - case 0xf3: sprintf(t, "bbc7 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; - case 0xf4: sprintf(t, "mov a,$%.3x+x", opdp0); break; - case 0xf5: sprintf(t, "mov a,$%.4x+x", opw); break; - case 0xf6: sprintf(t, "mov a,$%.4x+y", opw); break; - case 0xf7: sprintf(t, "mov a,($%.3x)+y", opdp0); break; - case 0xf8: sprintf(t, "mov x,$%.3x", opdp0); break; - case 0xf9: sprintf(t, "mov x,$%.3x+y", opdp0); break; - case 0xfa: sprintf(t, "mov $%.3x,$%.3x", opdp1, opdp0); break; - case 0xfb: sprintf(t, "mov y,$%.3x+x", opdp0); break; - case 0xfc: sprintf(t, "inc y"); break; - case 0xfd: sprintf(t, "mov y,a"); break; - case 0xfe: sprintf(t, "dbnz y,$%.4x", relb(op0, 2)); break; - case 0xff: sprintf(t, "stop"); break; - } - - t[strlen(t)] = ' '; - strcat(s, t); - - sprintf(t, "A:%.2x X:%.2x Y:%.2x SP:01%.2x YA:%.4x ", - regs.a, regs.x, regs.y, regs.sp, (uint16)regs.ya); - strcat(s, t); - - sprintf(t, "%c%c%c%c%c%c%c%c", - regs.p.n ? 'N' : 'n', - regs.p.v ? 'V' : 'v', - regs.p.p ? 'P' : 'p', - regs.p.b ? 'B' : 'b', - regs.p.h ? 'H' : 'h', - regs.p.i ? 'I' : 'i', - regs.p.z ? 'Z' : 'z', - regs.p.c ? 'C' : 'c'); - strcat(s, t); -} diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/iplrom.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/iplrom.cpp deleted file mode 100644 index a2ade89d94..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/iplrom.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#ifdef SMP_CPP - -//this is the IPLROM for the S-SMP coprocessor. -//the S-SMP does not allow writing to the IPLROM. -//all writes are instead mapped to the extended -//RAM region, accessible when $f1.d7 is clear. - -const uint8 SMP::iplrom[64] = { -/*ffc0*/ 0xcd, 0xef, //mov x,#$ef -/*ffc2*/ 0xbd, //mov sp,x -/*ffc3*/ 0xe8, 0x00, //mov a,#$00 -/*ffc5*/ 0xc6, //mov (x),a -/*ffc6*/ 0x1d, //dec x -/*ffc7*/ 0xd0, 0xfc, //bne $ffc5 -/*ffc9*/ 0x8f, 0xaa, 0xf4, //mov $f4,#$aa -/*ffcc*/ 0x8f, 0xbb, 0xf5, //mov $f5,#$bb -/*ffcf*/ 0x78, 0xcc, 0xf4, //cmp $f4,#$cc -/*ffd2*/ 0xd0, 0xfb, //bne $ffcf -/*ffd4*/ 0x2f, 0x19, //bra $ffef -/*ffd6*/ 0xeb, 0xf4, //mov y,$f4 -/*ffd8*/ 0xd0, 0xfc, //bne $ffd6 -/*ffda*/ 0x7e, 0xf4, //cmp y,$f4 -/*ffdc*/ 0xd0, 0x0b, //bne $ffe9 -/*ffde*/ 0xe4, 0xf5, //mov a,$f5 -/*ffe0*/ 0xcb, 0xf4, //mov $f4,y -/*ffe2*/ 0xd7, 0x00, //mov ($00)+y,a -/*ffe4*/ 0xfc, //inc y -/*ffe5*/ 0xd0, 0xf3, //bne $ffda -/*ffe7*/ 0xab, 0x01, //inc $01 -/*ffe9*/ 0x10, 0xef, //bpl $ffda -/*ffeb*/ 0x7e, 0xf4, //cmp y,$f4 -/*ffed*/ 0x10, 0xeb, //bpl $ffda -/*ffef*/ 0xba, 0xf6, //movw ya,$f6 -/*fff1*/ 0xda, 0x00, //movw $00,ya -/*fff3*/ 0xba, 0xf4, //movw ya,$f4 -/*fff5*/ 0xc4, 0xf4, //mov $f4,a -/*fff7*/ 0xdd, //mov a,y -/*fff8*/ 0x5d, //mov x,a -/*fff9*/ 0xd0, 0xdb, //bne $ffd6 -/*fffb*/ 0x1f, 0x00, 0x00, //jmp ($0000+x) -/*fffe*/ 0xc0, 0xff //reset vector location ($ffc0) -}; - -#endif diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/memory.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/memory.cpp deleted file mode 100644 index aecba7209f..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/memory.cpp +++ /dev/null @@ -1,130 +0,0 @@ -unsigned SMP::port_read(unsigned addr) { - return apuram[0xf4 + (addr & 3)]; -} - -void SMP::port_write(unsigned addr, unsigned data) { - apuram[0xf4 + (addr & 3)] = data; -} - -unsigned SMP::mmio_read(unsigned addr) { - switch(addr) { - - case 0xf2: - return status.dsp_addr; - - case 0xf3: - return dsp.read(status.dsp_addr & 0x7f); - - case 0xf4: - case 0xf5: - case 0xf6: - case 0xf7: - synchronize_cpu(); - return cpu.port_read(addr); - - case 0xf8: - return status.ram00f8; - - case 0xf9: - return status.ram00f9; - - case 0xfd: { - unsigned result = timer0.stage3_ticks & 15; - timer0.stage3_ticks = 0; - return result; - } - - case 0xfe: { - unsigned result = timer1.stage3_ticks & 15; - timer1.stage3_ticks = 0; - return result; - } - - case 0xff: { - unsigned result = timer2.stage3_ticks & 15; - timer2.stage3_ticks = 0; - return result; - } - - } - - return 0x00; -} - -void SMP::mmio_write(unsigned addr, unsigned data) { - switch(addr) { - - case 0xf1: - status.iplrom_enable = data & 0x80; - - if(data & 0x30) { - synchronize_cpu(); - if(data & 0x20) { - cpu.port_write(3, 0x00); - cpu.port_write(2, 0x00); - } - if(data & 0x10) { - cpu.port_write(1, 0x00); - cpu.port_write(0, 0x00); - } - } - - if(timer2.enable == false && (data & 0x04)) { - timer2.stage2_ticks = 0; - timer2.stage3_ticks = 0; - } - timer2.enable = data & 0x04; - - if(timer1.enable == false && (data & 0x02)) { - timer1.stage2_ticks = 0; - timer1.stage3_ticks = 0; - } - timer1.enable = data & 0x02; - - if(timer0.enable == false && (data & 0x01)) { - timer0.stage2_ticks = 0; - timer0.stage3_ticks = 0; - } - timer0.enable = data & 0x01; - - break; - - case 0xf2: - status.dsp_addr = data; - break; - - case 0xf3: - if(status.dsp_addr & 0x80) break; - dsp.write(status.dsp_addr, data); - break; - - case 0xf4: - case 0xf5: - case 0xf6: - case 0xf7: - synchronize_cpu(); - port_write(addr, data); - break; - - case 0xf8: - status.ram00f8 = data; - break; - - case 0xf9: - status.ram00f9 = data; - break; - - case 0xfa: - timer0.target = data; - break; - - case 0xfb: - timer1.target = data; - break; - - case 0xfc: - timer2.target = data; - break; - - } -} diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/smp.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/smp.cpp deleted file mode 100644 index 9002683342..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/smp.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#define CYCLE_ACCURATE - -#include - -#define SMP_CPP -namespace SNES { - -SMP smp; - -#include "algorithms.cpp" -#include "core.cpp" -#include "iplrom.cpp" -#include "memory.cpp" -#include "timing.cpp" - -void SMP::synchronize_cpu() { - if(CPU::Threaded == true) { - //if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); - } else { - while(clock >= 0) cpu.enter(); - } -} - -void SMP::synchronize_dsp() { - if(DSP::Threaded == true) { - //if(dsp.clock < 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(dsp.thread); - } else { - while(dsp.clock < 0) dsp.enter(); - } -} - -void SMP::enter() { - while(clock < 0) op_step(); -} - -void SMP::power() { - Processor::frequency = system.apu_frequency(); - Processor::clock = 0; - - timer0.target = 0; - timer1.target = 0; - timer2.target = 0; - - for(unsigned n = 0; n < 256; n++) { - cycle_table_dsp[n] = (cycle_count_table[n] * 24); - cycle_table_cpu[n] = (cycle_count_table[n] * 24) * cpu.frequency; - } - - cycle_step_cpu = 24 * cpu.frequency; - - reset(); -} - -void SMP::reset() { - for(unsigned n = 0x0000; n <= 0xffff; n++) apuram[n] = 0x00; - - opcode_number = 0; - opcode_cycle = 0; - - regs.pc = 0xffc0; - regs.sp = 0xef; - regs.a = 0x00; - regs.x = 0x00; - regs.y = 0x00; - regs.p = 0x02; - - //$00f1 - status.iplrom_enable = true; - - //$00f2 - status.dsp_addr = 0x00; - - //$00f8,$00f9 - status.ram00f8 = 0x00; - status.ram00f9 = 0x00; - - //timers - timer0.enable = timer1.enable = timer2.enable = false; - timer0.stage1_ticks = timer1.stage1_ticks = timer2.stage1_ticks = 0; - timer0.stage2_ticks = timer1.stage2_ticks = timer2.stage2_ticks = 0; - timer0.stage3_ticks = timer1.stage3_ticks = timer2.stage3_ticks = 0; -} - -SMP::SMP() : - apuram(nullptr) -{ - -} - -SMP::~SMP() { - interface()->freeSharedMemory(apuram); -} - -void SMP::initialize() -{ - apuram = (uint8*)interface()->allocSharedMemory("APURAM", 64 * 1024); -} - - - -} diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/smp.hpp b/waterbox/libsnes/bsnes/snes/alt/smp/smp.hpp deleted file mode 100644 index 77d8ca33b0..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/smp.hpp +++ /dev/null @@ -1,117 +0,0 @@ -class SMP : public Processor { -public: - static const uint8 iplrom[64]; - uint8 *apuram; - - enum : bool { Threaded = false }; - alwaysinline void synchronize_cpu(); - alwaysinline void synchronize_dsp(); - - unsigned port_read(unsigned port); - void port_write(unsigned port, unsigned data); - - unsigned mmio_read(unsigned addr); - void mmio_write(unsigned addr, unsigned data); - - void enter(); - void power(); - void reset(); - - SMP(); - ~SMP(); - void initialize(); - - void disassemble_opcode(char *output, uint16 addr); - -//private: - struct Flags { - bool n, v, p, b, h, i, z, c; - - alwaysinline operator unsigned() const { - return (n << 7) | (v << 6) | (p << 5) | (b << 4) - | (h << 3) | (i << 2) | (z << 1) | (c << 0); - }; - - alwaysinline unsigned operator=(unsigned data) { - n = data & 0x80; v = data & 0x40; p = data & 0x20; b = data & 0x10; - h = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01; - return data; - } - - alwaysinline unsigned operator|=(unsigned data) { return operator=(operator unsigned() | data); } - alwaysinline unsigned operator^=(unsigned data) { return operator=(operator unsigned() ^ data); } - alwaysinline unsigned operator&=(unsigned data) { return operator=(operator unsigned() & data); } - }; - - unsigned opcode_number; - unsigned opcode_cycle; - - struct Regs { - uint16 pc; - uint8 sp; - union { - uint16 ya; - struct { uint8 order_lsb2(a, y); }; - }; - uint8 x; - Flags p; - } regs; - - uint16 rd, wr, dp, sp, ya, bit; - - struct Status { - //$00f1 - bool iplrom_enable; - - //$00f2 - unsigned dsp_addr; - - //$00f8,$00f9 - unsigned ram00f8; - unsigned ram00f9; - } status; - - template - struct Timer { - bool enable; - uint8 target; - uint8 stage1_ticks; - uint8 stage2_ticks; - uint8 stage3_ticks; - - void tick(); - void tick(unsigned clocks); - }; - - Timer<128> timer0; - Timer<128> timer1; - Timer< 16> timer2; - - void tick(); - alwaysinline void op_io(); - alwaysinline uint8 op_read(uint16 addr, eCDLog_Flags flags); - alwaysinline void op_write(uint16 addr, uint8 data); - alwaysinline void op_step(); - static const unsigned cycle_count_table[256]; - uint64 cycle_table_cpu[256]; - unsigned cycle_table_dsp[256]; - uint64 cycle_step_cpu; - - uint8 op_adc (uint8 x, uint8 y); - uint16 op_addw(uint16 x, uint16 y); - uint8 op_and (uint8 x, uint8 y); - uint8 op_cmp (uint8 x, uint8 y); - uint16 op_cmpw(uint16 x, uint16 y); - uint8 op_eor (uint8 x, uint8 y); - uint8 op_inc (uint8 x); - uint8 op_dec (uint8 x); - uint8 op_or (uint8 x, uint8 y); - uint8 op_sbc (uint8 x, uint8 y); - uint16 op_subw(uint16 x, uint16 y); - uint8 op_asl (uint8 x); - uint8 op_lsr (uint8 x); - uint8 op_rol (uint8 x); - uint8 op_ror (uint8 x); -}; - -extern SMP smp; diff --git a/waterbox/libsnes/bsnes/snes/alt/smp/timing.cpp b/waterbox/libsnes/bsnes/snes/alt/smp/timing.cpp deleted file mode 100644 index d278f6f4fc..0000000000 --- a/waterbox/libsnes/bsnes/snes/alt/smp/timing.cpp +++ /dev/null @@ -1,26 +0,0 @@ -template -void SMP::Timer::tick() { - if(++stage1_ticks < cycle_frequency) return; - - stage1_ticks = 0; - if(enable == false) return; - - if(++stage2_ticks != target) return; - - stage2_ticks = 0; - stage3_ticks = (stage3_ticks + 1) & 15; -} - -template -void SMP::Timer::tick(unsigned clocks) { - stage1_ticks += clocks; - if(stage1_ticks < cycle_frequency) return; - - stage1_ticks -= cycle_frequency; - if(enable == false) return; - - if(++stage2_ticks != target) return; - - stage2_ticks = 0; - stage3_ticks = (stage3_ticks + 1) & 15; -} diff --git a/waterbox/libsnes/bsnes/snes/cartridge/cartridge.cpp b/waterbox/libsnes/bsnes/snes/cartridge/cartridge.cpp deleted file mode 100644 index 6827beae54..0000000000 --- a/waterbox/libsnes/bsnes/snes/cartridge/cartridge.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include - -#include -#include - -#define CARTRIDGE_CPP -namespace SNES { - -#include "markup.cpp" - -Cartridge cartridge; - -void Cartridge::load(Mode cartridge_mode, const char *markup) { - mode = cartridge_mode; - region = Region::NTSC; - ram_size = 0; - - has_bsx_slot = false; - has_nss_dip = false; - has_superfx = false; - has_sa1 = false; - has_necdsp = false; - has_hitachidsp = false; - has_armdsp = false; - has_srtc = false; - has_sdd1 = false; - has_spc7110 = false; - has_spc7110rtc = false; - has_obc1 = false; - has_msu1 = false; - has_link = false; - - nvram.reset(); - - parse_markup(markup); -//print(markup, "\n\n"); - - if(ram_size > 0) { - uint8* buf = (uint8*)interface()->allocSharedMemory("CARTRIDGE_RAM",ram_size,0xff); - ram.map(buf, ram_size); - nvram.append({ "program.ram", ram.data(), ram.size() }); - } - - rom.write_protect(true); - ram.write_protect(false); - - crc32 = crc32_calculate(rom.data(), rom.size()); - - switch((Mode)mode) { - case Mode::Normal: - case Mode::BsxSlotted: - sha256 = nall::sha256(rom.data(), rom.size()); - break; - case Mode::Bsx: - sha256 = nall::sha256(bsxflash.memory.data(), bsxflash.memory.size()); - break; - case Mode::SufamiTurbo: - sha256 = nall::sha256(sufamiturbo.slotA.rom.data(), sufamiturbo.slotA.rom.size()); - break; - case Mode::SuperGameBoy: - #if defined(GAMEBOY) - sha256 = GameBoy::cartridge.sha256(); - #else - throw "Game Boy support not present"; - #endif - break; - } - - system.load(); - loaded = true; -} - -void Cartridge::unload() { - if(loaded == false) return; - - system.unload(); - rom.reset(); - ram.reset(); - - loaded = false; -} - -Cartridge::Cartridge() - : rom("CARTRIDGE_ROM") - , ram("CARTRIDGE_RAM") -{ - loaded = false; - unload(); -} - -Cartridge::~Cartridge() { - unload(); -} - -} diff --git a/waterbox/libsnes/bsnes/snes/cartridge/cartridge.hpp b/waterbox/libsnes/bsnes/snes/cartridge/cartridge.hpp deleted file mode 100644 index d4099227d3..0000000000 --- a/waterbox/libsnes/bsnes/snes/cartridge/cartridge.hpp +++ /dev/null @@ -1,119 +0,0 @@ -struct Cartridge : property { - enum class Mode : unsigned { - Normal, - BsxSlotted, - Bsx, - SufamiTurbo, - SuperGameBoy, - }; - - enum class Region : unsigned { - NTSC, - PAL, - }; - - enum class Slot : unsigned { - Base, - Bsx, - SufamiTurbo, - SufamiTurboA, - SufamiTurboB, - GameBoy, - }; - - MappedRAM rom; - MappedRAM ram; - - readonly loaded; - readonly crc32; - readonly sha256; - - readonly mode; - readonly region; - readonly ram_size; - - readonly has_bsx_slot; - readonly has_nss_dip; - readonly has_superfx; - readonly has_sa1; - readonly has_necdsp; - readonly has_hitachidsp; - readonly has_armdsp; - readonly has_srtc; - readonly has_sdd1; - readonly has_spc7110; - readonly has_spc7110rtc; - readonly has_obc1; - readonly has_msu1; - readonly has_link; - - struct NonVolatileRAM { - const string id; - uint8_t *data; - unsigned size; - Slot slot; - NonVolatileRAM() : id(""), data(0), size(0), slot(Slot::Base) {} - NonVolatileRAM(const string id, uint8_t *data, unsigned size, Slot slot = Slot::Base) - : id(id), data(data), size(size), slot(slot) {} - }; - linear_vector nvram; - - struct Mapping { - function read; - function write; - Bus::MapMode mode; - unsigned banklo; - unsigned bankhi; - unsigned addrlo; - unsigned addrhi; - unsigned offset; - unsigned size; - - Mapping(); - Mapping(const function&, const function&); - Mapping(Memory&); - }; - linear_vector mapping; - - struct Information { - struct NSS { - lstring setting; - lstring option[16]; - } nss; - } information; - - void load(Mode, const char*); - void unload(); - - Cartridge(); - ~Cartridge(); - -private: - void parse_markup(const char*); - void parse_markup_map(Mapping&, XML::Node&); - - void parse_markup_rom(XML::Node&); - void parse_markup_ram(XML::Node&); - void parse_markup_nss(XML::Node&); - void parse_markup_icd2(XML::Node&); - void parse_markup_superfx(XML::Node&); - void parse_markup_sa1(XML::Node&); - void parse_markup_necdsp(XML::Node&); - void parse_markup_hitachidsp(XML::Node&); - void parse_markup_armdsp(XML::Node&); - void parse_markup_bsx(XML::Node&); - void parse_markup_sufamiturbo(XML::Node&); - void parse_markup_srtc(XML::Node&); - void parse_markup_sdd1(XML::Node&); - void parse_markup_spc7110(XML::Node&); - void parse_markup_obc1(XML::Node&); - void parse_markup_msu1(XML::Node&); - void parse_markup_link(XML::Node&); - - inline uint8 rom_read(unsigned addr); - inline void rom_write(unsigned addr, uint8 n); - inline uint8 ram_read(unsigned addr); - inline void ram_write(unsigned addr, uint8 n); -}; - -extern Cartridge cartridge; diff --git a/waterbox/libsnes/bsnes/snes/cartridge/markup.cpp b/waterbox/libsnes/bsnes/snes/cartridge/markup.cpp deleted file mode 100644 index e4cde6a3fa..0000000000 --- a/waterbox/libsnes/bsnes/snes/cartridge/markup.cpp +++ /dev/null @@ -1,596 +0,0 @@ -#ifdef CARTRIDGE_CPP - -void Cartridge::parse_markup(const char *markup) { - mapping.reset(); - information.nss.setting.reset(); - - XML::Document document(markup); - auto &cartridge = document["cartridge"]; - region = cartridge["region"].data != "PAL" ? Region::NTSC : Region::PAL; - - parse_markup_rom(cartridge["rom"]); - parse_markup_ram(cartridge["ram"]); - parse_markup_nss(cartridge["nss"]); - parse_markup_icd2(cartridge["icd2"]); - parse_markup_sa1(cartridge["sa1"]); - parse_markup_superfx(cartridge["superfx"]); - parse_markup_necdsp(cartridge["necdsp"]); - parse_markup_hitachidsp(cartridge["hitachidsp"]); - parse_markup_armdsp(cartridge["armdsp"]); - parse_markup_bsx(cartridge["bsx"]); - parse_markup_sufamiturbo(cartridge["sufamiturbo"]); - parse_markup_srtc(cartridge["srtc"]); - parse_markup_sdd1(cartridge["sdd1"]); - parse_markup_spc7110(cartridge["spc7110"]); - parse_markup_obc1(cartridge["obc1"]); - parse_markup_msu1(cartridge["msu1"]); - parse_markup_link(cartridge["link"]); -} - -// - -void Cartridge::parse_markup_map(Mapping &m, XML::Node &map) { - m.offset = numeral(map["offset"].data); - m.size = numeral(map["size"].data); - - string data = map["mode"].data; - if(data == "direct") m.mode = Bus::MapMode::Direct; - if(data == "linear") m.mode = Bus::MapMode::Linear; - if(data == "shadow") m.mode = Bus::MapMode::Shadow; - - lstring part; - part.split(":", map["address"].data); - if(part.size() != 2) return; - - lstring subpart; - subpart.split("-", part[0]); - if(subpart.size() == 1) { - m.banklo = hex(subpart[0]); - m.bankhi = m.banklo; - } else if(subpart.size() == 2) { - m.banklo = hex(subpart[0]); - m.bankhi = hex(subpart[1]); - } - - subpart.split("-", part[1]); - if(subpart.size() == 1) { - m.addrlo = hex(subpart[0]); - m.addrhi = m.addrlo; - } else if(subpart.size() == 2) { - m.addrlo = hex(subpart[0]); - m.addrhi = hex(subpart[1]); - } -} - -uint8 Cartridge::rom_read(unsigned addr) -{ - cdlInfo.set(eCDLog_AddrType_CARTROM, addr); - return rom.read(addr); -} -void Cartridge::rom_write(unsigned addr, uint8 n) -{ - rom.write(addr,n); -} - -uint8 Cartridge::ram_read(unsigned addr) -{ - cdlInfo.set(eCDLog_AddrType_CARTRAM, addr); - return ram.read(addr); -} -void Cartridge::ram_write(unsigned addr, uint8 n) -{ - ram.write(addr, n); -} - -void Cartridge::parse_markup_rom(XML::Node &root) { - if(root.exists() == false) return; - for(auto &node : root) { - if(node.name != "map") continue; - Mapping m({&Cartridge::rom_read, this}, {&Cartridge::rom_write, this}); - parse_markup_map(m, node); - if(m.size == 0) m.size = rom.size(); - mapping.append(m); - } -} - -void Cartridge::parse_markup_ram(XML::Node &root) { - if(root.exists() == false) return; - ram_size = numeral(root["size"].data); - for(auto &node : root) { - Mapping m({ &Cartridge::ram_read, this }, { &Cartridge::ram_write, this }); - parse_markup_map(m, node); - if(m.size == 0) m.size = ram_size; - mapping.append(m); - } -} - -void Cartridge::parse_markup_nss(XML::Node &root) { - if(root.exists() == false) return; - has_nss_dip = true; - for(auto &node : root) { - if(node.name != "setting") continue; - unsigned number = information.nss.setting.size(); - if(number >= 16) break; //more than 16 DIP switches is not physically possible - - information.nss.option[number].reset(); - information.nss.setting.append(node["name"].data); - for(auto &leaf : node) { - if(leaf.name != "option") continue; - string name = leaf["name"].data; - unsigned value = numeral(leaf["value"].data); - information.nss.option[number].append({ hex<4>(value), ":", name }); - } - } -} - -void Cartridge::parse_markup_icd2(XML::Node &root) { - #if defined(GAMEBOY) - if(root.exists() == false) return; - if(mode.value != Mode::SuperGameBoy) return; - - icd2.revision = max(1, numeral(root["revision"].data)); - - for(auto &node : root) { - if(node.name != "map") continue; - Mapping m({ &ICD2::read, &icd2 }, { &ICD2::write, &icd2 }); - parse_markup_map(m, node); - mapping.append(m); - } - #endif -} - -void Cartridge::parse_markup_superfx(XML::Node &root) { - if(root.exists() == false) return; - has_superfx = true; - - for(auto &node : root) { - if(node.name == "rom") { - for(auto &leaf : node) { - if(leaf.name != "map") continue; - Mapping m(superfx.rom); - parse_markup_map(m, leaf); - mapping.append(m); - } - } - if(node.name == "ram") { - for(auto &leaf : node) { - if(leaf.name == "size") { - ram_size = numeral(leaf.data); - continue; - } - if(leaf.name != "map") continue; - Mapping m(superfx.ram); - parse_markup_map(m, leaf); - if(m.size == 0) m.size = ram_size; - mapping.append(m); - } - } - if(node.name == "mmio") { - for(auto &leaf : node) { - if(leaf.name != "map") continue; - Mapping m({ &SuperFX::mmio_read, &superfx }, { &SuperFX::mmio_write, &superfx }); - parse_markup_map(m, leaf); - mapping.append(m); - } - } - } -} - -void Cartridge::parse_markup_sa1(XML::Node &root) { - if(root.exists() == false) return; - has_sa1 = true; - - auto &mcurom = root["mcu"]["rom"]; - auto &mcuram = root["mcu"]["ram"]; - auto &iram = root["iram"]; - auto &bwram = root["bwram"]; - auto &mmio = root["mmio"]; - - for(auto &node : mcurom) { - if(node.name != "map") continue; - Mapping m({ &SA1::mmc_read, &sa1 }, { &SA1::mmc_write, &sa1 }); - parse_markup_map(m, node); - mapping.append(m); - } - - for(auto &node : mcuram) { - if(node.name != "map") continue; - Mapping m({ &SA1::mmc_cpu_read, &sa1 }, { &SA1::mmc_cpu_write, &sa1 }); - parse_markup_map(m, node); - mapping.append(m); - } - - for(auto &node : iram) { - if(node.name != "map") continue; - Mapping m(sa1.cpuiram); - parse_markup_map(m, node); - if(m.size == 0) m.size = 2048; - mapping.append(m); - } - - ram_size = numeral(bwram["size"].data); - for(auto &node : bwram) { - if(node.name != "map") continue; - Mapping m(sa1.cpubwram); - parse_markup_map(m, node); - if(m.size == 0) m.size = ram_size; - mapping.append(m); - } - - for(auto &node : mmio) { - if(node.name != "map") continue; - Mapping m({ &SA1::mmio_read, &sa1 }, { &SA1::mmio_write, &sa1 }); - parse_markup_map(m, node); - mapping.append(m); - } -} - -void Cartridge::parse_markup_necdsp(XML::Node &root) { - if(root.exists() == false) return; - has_necdsp = true; - - for(unsigned n = 0; n < 16384; n++) necdsp.programROM[n] = 0x000000; - for(unsigned n = 0; n < 2048; n++) necdsp.dataROM[n] = 0x0000; - - necdsp.frequency = numeral(root["frequency"].data); - if(necdsp.frequency == 0) necdsp.frequency = 8000000; - necdsp.revision - = root["model"].data == "uPD7725" ? NECDSP::Revision::uPD7725 - : root["model"].data == "uPD96050" ? NECDSP::Revision::uPD96050 - : NECDSP::Revision::uPD7725; - string firmware = root["firmware"].data; - string sha256 = root["sha256"].data; - - string path = interface()->path(Slot::Base, firmware); - unsigned promsize = (necdsp.revision == NECDSP::Revision::uPD7725 ? 2048 : 16384); - unsigned dromsize = (necdsp.revision == NECDSP::Revision::uPD7725 ? 1024 : 2048); - unsigned filesize = promsize * 3 + dromsize * 2; - - file fp; - if(fp.open(path, file::mode::read) == false) { - interface()->message({ "Warning: NEC DSP firmware ", firmware, " is missing." }); - } else if(fp.size() != filesize) { - interface()->message({ "Warning: NEC DSP firmware ", firmware, " is of the wrong file size." }); - fp.close(); - } else { - for(unsigned n = 0; n < promsize; n++) necdsp.programROM[n] = fp.readl(3); - for(unsigned n = 0; n < dromsize; n++) necdsp.dataROM[n] = fp.readl(2); - - if(!sha256.empty()) { - //XML file specified SHA256 sum for program. Verify file matches the hash. - fp.seek(0); - std::vector data(filesize); - fp.read(data.data(), filesize); - - if(sha256 != nall::sha256(data.data(), filesize)) { - interface()->message({ "Warning: NEC DSP firmware ", firmware, " SHA256 sum is incorrect." }); - } - } - - fp.close(); - } - - for(auto &node : root) { - if(node.name == "dr") { - for(auto &leaf : node) { - Mapping m({ &NECDSP::dr_read, &necdsp }, { &NECDSP::dr_write, &necdsp }); - parse_markup_map(m, leaf); - mapping.append(m); - } - } - if(node.name == "sr") { - for(auto &leaf : node) { - Mapping m({ &NECDSP::sr_read, &necdsp }, { &NECDSP::sr_write, &necdsp }); - parse_markup_map(m, leaf); - mapping.append(m); - } - } - if(node.name == "dp") { - for(auto &leaf : node) { - Mapping m({ &NECDSP::dp_read, &necdsp }, { &NECDSP::dp_write, &necdsp }); - parse_markup_map(m, leaf); - mapping.append(m); - } - } - } -} - -void Cartridge::parse_markup_hitachidsp(XML::Node &root) { - if(root.exists() == false) return; - has_hitachidsp = true; - - for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = 0x000000; - - hitachidsp.frequency = numeral(root["frequency"].data); - if(hitachidsp.frequency == 0) hitachidsp.frequency = 20000000; - string firmware = root["firmware"].data; - string sha256 = root["sha256"].data; - - string path = interface()->path(Slot::Base, firmware); - file fp; - if(fp.open(path, file::mode::read) == false) { - interface()->message({ "Warning: Hitachi DSP firmware ", firmware, " is missing." }); - } else if(fp.size() != 1024 * 3) { - interface()->message({ "Warning: Hitachi DSP firmware ", firmware, " is of the wrong file size." }); - fp.close(); - } else { - for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = fp.readl(3); - - if(!sha256.empty()) { - //XML file specified SHA256 sum for program. Verify file matches the hash. - fp.seek(0); - uint8 data[3072]; - fp.read(data, 3072); - - if(sha256 != nall::sha256(data, 3072)) { - interface()->message({ "Warning: Hitachi DSP firmware ", firmware, " SHA256 sum is incorrect." }); - } - } - - fp.close(); - } - - for(auto &node : root) { - if(node.name == "rom") { - for(auto &leaf : node) { - if(leaf.name != "map") continue; - Mapping m({ &HitachiDSP::rom_read, &hitachidsp }, { &HitachiDSP::rom_write, &hitachidsp }); - parse_markup_map(m, leaf); - mapping.append(m); - } - } - if(node.name == "mmio") { - for(auto &leaf : node) { - Mapping m({ &HitachiDSP::dsp_read, &hitachidsp }, { &HitachiDSP::dsp_write, &hitachidsp }); - parse_markup_map(m, leaf); - mapping.append(m); - } - } - } -} - -void Cartridge::parse_markup_armdsp(XML::Node &root) { - if(root.exists() == false) return; - has_armdsp = true; - - string firmware = root["firmware"].data; - string sha256 = root["sha256"].data; - - string path = interface()->path(Slot::Base, firmware); - file fp; - if(fp.open(path, file::mode::read) == false) { - interface()->message({ "Warning: ARM DSP firmware ", firmware, " is missing." }); - } else if(fp.size() != 160 * 1024) { - interface()->message({ "Warning: ARM DSP firmware ", firmware, " is of the wrong file size." }); - fp.close(); - } else { - fp.read(armdsp.firmware, fp.size()); - - if(!sha256.empty()) { - if(sha256 != nall::sha256(armdsp.firmware, fp.size())) { - interface()->message({ "Warning: ARM DSP firmware ", firmware, " SHA256 sum is incorrect." }); - } - } - - fp.close(); - } - - for(auto &node : root) { - if(node.name != "map") continue; - Mapping m({ &ArmDSP::mmio_read, &armdsp }, { &ArmDSP::mmio_write, &armdsp }); - parse_markup_map(m, node); - mapping.append(m); - } -} - -void Cartridge::parse_markup_bsx(XML::Node &root) { - if(root.exists() == false) return; - if(mode.value != Mode::BsxSlotted && mode.value != Mode::Bsx) return; - has_bsx_slot = true; - - for(auto &node : root["slot"]) { - if(node.name != "map") continue; - Mapping m(bsxflash.memory); - parse_markup_map(m, node); - mapping.append(m); - } - - for(auto &node : root["mmio"]) { - if(node.name != "map") continue; - Mapping m({ &BSXCartridge::mmio_read, &bsxcartridge }, { &BSXCartridge::mmio_write, &bsxcartridge }); - parse_markup_map(m, node); - mapping.append(m); - } - - for(auto &node : root["mcu"]) { - if(node.name != "map") continue; - Mapping m({ &BSXCartridge::mcu_read, &bsxcartridge }, { &BSXCartridge::mcu_write, &bsxcartridge }); - parse_markup_map(m, node); - mapping.append(m); - } -} - -void Cartridge::parse_markup_sufamiturbo(XML::Node &root) { - if(root.exists() == false) return; - if(mode.value != Mode::SufamiTurbo) return; - - for(auto &slot : root) { - if(slot.name != "slot") continue; - bool slotid = slot["id"].data == "A" ? 0 : slot["id"].data == "B" ? 1 : 0; - for(auto &node : slot) { - if(node.name == "rom") { - for(auto &leaf : node) { - if(leaf.name != "map") continue; - Memory &memory = slotid == 0 ? sufamiturbo.slotA.rom : sufamiturbo.slotB.rom; - Mapping m(memory); - parse_markup_map(m, leaf); - if(m.size == 0) m.size = memory.size(); - if(m.size) mapping.append(m); - } - } - if(node.name == "ram") { - unsigned ram_size = numeral(node["size"].data); - for(auto &leaf : node) { - if(leaf.name != "map") continue; - Memory &memory = slotid == 0 ? sufamiturbo.slotA.ram : sufamiturbo.slotB.ram; - Mapping m(memory); - parse_markup_map(m, leaf); - if(m.size == 0) m.size = ram_size; - if(m.size) mapping.append(m); - } - } - } - } -} - -void Cartridge::parse_markup_srtc(XML::Node &root) { - if(root.exists() == false) return; - has_srtc = true; - - for(auto &node : root) { - if(node.name != "map") continue; - Mapping m({ &SRTC::read, &srtc }, { &SRTC::write, &srtc }); - parse_markup_map(m, node); - mapping.append(m); - } -} - -void Cartridge::parse_markup_sdd1(XML::Node &root) { - if(root.exists() == false) return; - has_sdd1 = true; - - for(auto &node : root["mmio"]) { - if(node.name != "map") continue; - Mapping m({ &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 }); - parse_markup_map(m, node); - mapping.append(m); - } - - for(auto &node : root["mcu"]) { - if(node.name != "map") continue; - Mapping m({ &SDD1::mcu_read, &sdd1 }, { &SDD1::mcu_write, &sdd1 }); - parse_markup_map(m, node); - mapping.append(m); - } -} - -void Cartridge::parse_markup_spc7110(XML::Node &root) { - if(root.exists() == false) return; - has_spc7110 = true; - has_spc7110rtc = root["rtc"].exists(); - - auto &ram = root["ram"]; - auto &mmio = root["mmio"]; - auto &mcu = root["mcu"]; - auto &dcu = root["dcu"]; - auto &rtc = root["rtc"]; - - ram_size = numeral(ram["size"].data); - for(auto &node : ram) { - if(node.name != "map") continue; - Mapping m({ &SPC7110::ram_read, &spc7110 }, { &SPC7110::ram_write, &spc7110 }); - parse_markup_map(m, node); - mapping.append(m); - } - - for(auto &node : mmio) { - if(node.name != "map") continue; - Mapping m({ &SPC7110::mmio_read, &spc7110 }, { &SPC7110::mmio_write, &spc7110 }); - parse_markup_map(m, node); - mapping.append(m); - } - - spc7110.data_rom_offset = numeral(mcu["offset"].data); - if(spc7110.data_rom_offset == 0) spc7110.data_rom_offset = 0x100000; - for(auto &node : mcu) { - if(node.name != "map") continue; - Mapping m({ &SPC7110::mcu_read, &spc7110 }, { &SPC7110::mcu_write, &spc7110 }); - parse_markup_map(m, node); - mapping.append(m); - } - - for(auto &node : dcu) { - if(node.name != "map") continue; - Mapping m({ &SPC7110::dcu_read, &spc7110 }, { &SPC7110::dcu_write, &spc7110 }); - parse_markup_map(m, node); - mapping.append(m); - } - - for(auto &node : rtc) { - if(node.name != "map") continue; - Mapping m({ &SPC7110::mmio_read, &spc7110 }, { &SPC7110::mmio_write, &spc7110 }); - parse_markup_map(m, node); - mapping.append(m); - } -} - -void Cartridge::parse_markup_obc1(XML::Node &root) { - if(root.exists() == false) return; - has_obc1 = true; - - for(auto &node : root) { - if(node.name != "map") continue; - Mapping m({ &OBC1::read, &obc1 }, { &OBC1::write, &obc1 }); - parse_markup_map(m, node); - mapping.append(m); - } -} - -void Cartridge::parse_markup_msu1(XML::Node &root) { - if(root.exists() == false) { - has_msu1 = file::exists(interface()->path(Cartridge::Slot::Base, "msu1.rom")); - if(has_msu1) { - Mapping m({ &MSU1::mmio_read, &msu1 }, { &MSU1::mmio_write, &msu1 }); - m.banklo = 0x00, m.bankhi = 0x3f, m.addrlo = 0x2000, m.addrhi = 0x2007; - mapping.append(m); - m.banklo = 0x80, m.bankhi = 0xbf, m.addrlo = 0x2000, m.addrhi = 0x2007; - mapping.append(m); - } - return; - } - - has_msu1 = true; - - for(auto &node : root) { - if(node.name != "map") continue; - Mapping m({ &MSU1::mmio_read, &msu1 }, { &MSU1::mmio_write, &msu1 }); - parse_markup_map(m, node); - mapping.append(m); - } -} - -void Cartridge::parse_markup_link(XML::Node &root) { - if(root.exists() == false) return; - has_link = true; - - link.frequency = max(1, numeral(root["frequency"].data)); - link.program = root["program"].data; - - for(auto &node : root) { - if(node.name != "map") continue; - Mapping m({ &Link::read, &link }, { &Link::write, &link }); - parse_markup_map(m, node); - mapping.append(m); - } -} - -Cartridge::Mapping::Mapping() { - mode = Bus::MapMode::Direct; - banklo = bankhi = addrlo = addrhi = offset = size = 0; -} - -Cartridge::Mapping::Mapping(Memory &memory) { - read = { &Memory::read, &memory }; - write = { &Memory::write, &memory }; - mode = Bus::MapMode::Direct; - banklo = bankhi = addrlo = addrhi = offset = size = 0; -} - -Cartridge::Mapping::Mapping(const function &read_, const function &write_) { - read = read_; - write = write_; - mode = Bus::MapMode::Direct; - banklo = bankhi = addrlo = addrhi = offset = size = 0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/armdsp/armdsp.cpp b/waterbox/libsnes/bsnes/snes/chip/armdsp/armdsp.cpp deleted file mode 100644 index 344829ca2f..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/armdsp/armdsp.cpp +++ /dev/null @@ -1,187 +0,0 @@ -#include - -#define ARMDSP_CPP -namespace SNES { - -//zero 01-sep-2014 - dont clobber these when reconstructing! -uint8 *ArmDSP::firmware; -uint8 *ArmDSP::programROM; -uint8 *ArmDSP::dataROM; - -static bool trace = 0; - -#include "opcodes.cpp" -#include "memory.cpp" -#include "disassembler.cpp" -ArmDSP armdsp; - -void ArmDSP::Enter() { armdsp.enter(); } - -void ArmDSP::enter() { - //reset hold delay - while(bridge.reset) { - tick(); - continue; - } - - //reset sequence delay - if(bridge.ready == false) { - tick(65536); - bridge.ready = true; - } - - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - if(exception) { - print("* ARM unknown instruction\n"); - print("\n", disassemble_registers()); - print("\n", disassemble_opcode(pipeline.instruction.address), "\n"); - while(true) tick(frequency); - } - - if(pipeline.reload) { - pipeline.reload = false; - pipeline.prefetch.address = r[15]; - pipeline.prefetch.opcode = bus_readword(r[15]); - r[15].step(); - } - - pipeline.instruction = pipeline.prefetch; - pipeline.prefetch.address = r[15]; - pipeline.prefetch.opcode = bus_readword(r[15]); - r[15].step(); - - //todo: bus_readword() calls tick(); so we need to prefetch this as well - //pipeline.mdr.address = r[15]; - //pipeline.mdr.opcode = bus_readword(r[15]); - - //if(pipeline.instruction.address == 0x00000208) trace = 1; - if(trace) { - print("\n", disassemble_registers(), "\n"); - print(disassemble_opcode(pipeline.instruction.address), "\n"); - usleep(200000); - } - //trace = 0; - - instruction = pipeline.instruction.opcode; - if(!condition()) continue; - if((instruction & 0x0fc000f0) == 0x00000090) { op_multiply(); continue; } - if((instruction & 0x0fb000f0) == 0x01000000) { op_move_to_register_from_status_register(); continue; } - if((instruction & 0x0fb000f0) == 0x01200000) { op_move_to_status_register_from_register(); continue; } - if((instruction & 0x0e000010) == 0x00000000) { op_data_immediate_shift(); continue; } - if((instruction & 0x0e000090) == 0x00000010) { op_data_register_shift(); continue; } - if((instruction & 0x0e000000) == 0x02000000) { op_data_immediate(); continue; } - if((instruction & 0x0e000000) == 0x04000000) { op_move_immediate_offset(); continue; } - if((instruction & 0x0e000010) == 0x06000000) { op_move_register_offset(); continue; } - if((instruction & 0x0e000000) == 0x08000000) { op_move_multiple(); continue; } - if((instruction & 0x0e000000) == 0x0a000000) { op_branch(); continue; } - - exception = true; - } -} - -void ArmDSP::tick(unsigned clocks) { - if(bridge.timer && --bridge.timer == 0) bridge.busy = false; - - step(clocks); - synchronize_cpu(); -} - -//MMIO: $00-3f|80-bf:3800-38ff -//3800-3807 mirrored throughout -//a0 ignored - -uint8 ArmDSP::mmio_read(unsigned addr) { - cpu.synchronize_coprocessors(); - - uint8 data = 0x00; - addr &= 0xff06; - - if(addr == 0x3800) { - if(bridge.armtocpu.ready) { - bridge.armtocpu.ready = false; - data = bridge.armtocpu.data; - } - } - - if(addr == 0x3802) { - bridge.timer = 0; - bridge.busy = false; - } - - if(addr == 0x3804) { - data = bridge.status(); - } - - return data; -} - -void ArmDSP::mmio_write(unsigned addr, uint8 data) { - cpu.synchronize_coprocessors(); - - addr &= 0xff06; - - if(addr == 0x3802) { - bridge.cputoarm.ready = true; - bridge.cputoarm.data = data; - } - - if(addr == 0x3804) { - data &= 1; - if(!bridge.reset && data) arm_reset(); - bridge.reset = data; - } -} - -void ArmDSP::init() { -} - -void ArmDSP::load() { -} - -void ArmDSP::unload() { -} - -void ArmDSP::power() { - for(unsigned n = 0; n < 16 * 1024; n++) programRAM[n] = random(0x00); -} - -void ArmDSP::reset() { - bridge.reset = false; - arm_reset(); -} - -void ArmDSP::arm_reset() { - create(ArmDSP::Enter, 21477272, 8192); - - bridge.ready = false; - bridge.timer = 0; - bridge.timerlatch = 0; - bridge.busy = false; - bridge.cputoarm.ready = false; - bridge.armtocpu.ready = false; - - for(auto &rd : r) rd = 0; - shiftercarry = 0; - exception = 0; - pipeline.reload = true; - r[15].write = [&] { pipeline.reload = true; }; -} - -ArmDSP::ArmDSP() { - firmware = new uint8[160 * 1024](); - programRAM = new uint8[16 * 1024](); - - programROM = &firmware[0]; - dataROM = &firmware[128 * 1024]; -} - -ArmDSP::~ArmDSP() { - delete[] firmware; - delete[] programRAM; -} - -} diff --git a/waterbox/libsnes/bsnes/snes/chip/armdsp/armdsp.hpp b/waterbox/libsnes/bsnes/snes/chip/armdsp/armdsp.hpp deleted file mode 100644 index 968fa139d8..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/armdsp/armdsp.hpp +++ /dev/null @@ -1,66 +0,0 @@ -//ARMv3 (ARM6) - -struct ArmDSP : public Coprocessor { - - //zero 01-sep-2014 - dont clobber these when reconstructing! - static uint8 *firmware; - static uint8 *programROM; - static uint8 *dataROM; - - uint8 *programRAM; - - #include "registers.hpp" - - static void Enter(); - void enter(); - void tick(unsigned clocks = 1); - - void init(); - void load(); - void unload(); - void power(); - void reset(); - void arm_reset(); - - ArmDSP(); - ~ArmDSP(); - - uint8 mmio_read(unsigned addr); - void mmio_write(unsigned addr, uint8 data); - - //opcodes.cpp - bool condition(); - void opcode(uint32 data); - void lsl(bool &c, uint32 &rm, uint32 rs); - void lsr(bool &c, uint32 &rm, uint32 rs); - void asr(bool &c, uint32 &rm, uint32 rs); - void ror(bool &c, uint32 &rm, uint32 rs); - void rrx(bool &c, uint32 &rm); - - void op_multiply(); - void op_move_to_status_register_from_register(); - void op_move_to_register_from_status_register(); - void op_data_immediate_shift(); - void op_data_register_shift(); - void op_data_immediate(); - void op_move_immediate_offset(); - void op_move_register_offset(); - void op_move_multiple(); - void op_branch(); - - //memory.cpp - uint8 bus_read(uint32 addr); - void bus_write(uint32 addr, uint8 data); - - uint32 bus_readbyte(uint32 addr); - void bus_writebyte(uint32 addr, uint32 data); - - uint32 bus_readword(uint32 addr); - void bus_writeword(uint32 addr, uint32 data); - - //disassembler.cpp - string disassemble_opcode(uint32 pc); - string disassemble_registers(); -}; - -extern ArmDSP armdsp; diff --git a/waterbox/libsnes/bsnes/snes/chip/armdsp/disassembler.cpp b/waterbox/libsnes/bsnes/snes/chip/armdsp/disassembler.cpp deleted file mode 100644 index ae6fc6438c..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/armdsp/disassembler.cpp +++ /dev/null @@ -1,246 +0,0 @@ -#ifdef ARMDSP_CPP - -string ArmDSP::disassemble_opcode(uint32 pc) { - static string conditions[] = { "eq", "ne", "cs", "cc", "mi" ,"pl", "vs", "vc", "hi", "ls", "ge", "lt", "gt", "le", "" /*al*/, "nv" }; - static string opcodes[] = { "and", "eor", "sub", "rsb", "add", "adc", "sbc", "rsc", "tst", "teq", "cmp", "cmn", "orr", "mov", "bic", "mvn" }; - static string registers[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }; - static string indices[] = { "da", "ia", "db", "ib" }; - - static auto is_move = [](uint4 opcode) { return opcode == 13 || opcode == 15; }; - static auto is_comp = [](uint4 opcode) { return opcode >= 8 && opcode <= 11; }; - static auto is_math = [](uint4 opcode) { return opcode < 8 || opcode == 12 || opcode == 14; }; - - string output{hex<8>(pc), " "}; - - uint32 instruction = bus_readword(pc); - output.append(hex<8>(instruction), " "); - - //multiply - //(mul,mla){condition}{s} rd,rm,rs,rn - if((instruction & 0x0fc000f0) == 0x00000090) { - uint4 condition = instruction >> 28; - uint1 accumulate = instruction >> 21; - uint1 save = instruction >> 20; - uint4 rd = instruction >> 16; - uint4 rn = instruction >> 12; - uint4 rs = instruction >> 8; - uint4 rm = instruction >> 0; - - output.append(accumulate ? "mla" : "mul", condition[conditions], save ? "s " : " "); - output.append(registers[rd], ",", registers[rm], ",", registers[rs]); - if(accumulate) output.append(",", registers[rn]); - - return output; - } - - //move to register from status register - //mrs{condition} rd,(c,s)psr - if((instruction & 0x0fb000f0) == 0x01000000) { - uint4 condition = instruction >> 28; - uint1 psr = instruction >> 22; - uint4 rd = instruction >> 12; - - output.append("mrs", condition[conditions], " "); - output.append(registers[rd], ",", psr ? "spsr" : "cpsr"); - - return output; - } - - //move to status register from register - //msr{condition} (c,s)psr:{fields},rm - if((instruction & 0x0fb000f0) == 0x01200000) { - uint4 condition = instruction >> 28; - uint1 psr = instruction >> 22; - uint4 field = instruction >> 16; - - output.append("msr", conditions[condition], " "); - output.append(psr ? "spsr:" : "cpsr:", - field & 1 ? "c" : "", - field & 2 ? "x" : "", - field & 4 ? "s" : "", - field & 8 ? "f" : "", - ",", registers[(uint4)instruction]); - - return output; - } - - //data immediate shift - //{opcode}{condition}{s} rd,rm {shift} #immediate - //{opcode}{condition} rn,rm {shift} #immediate - //{opcode}{condition}{s} rd,rn,rm {shift} #immediate - if((instruction & 0x0e000010) == 0x00000000) { - uint4 condition = instruction >> 28; - uint4 opcode = instruction >> 21; - uint1 save = instruction >> 20; - uint4 rn = instruction >> 16; - uint4 rd = instruction >> 12; - uint5 shift = instruction >> 7; - uint2 op = instruction >> 5; - uint4 rm = instruction; - - output.append(opcodes[opcode], conditions[condition]); - if(is_move(opcode)) output.append(save ? "s " : " ", registers[rd]); - if(is_comp(opcode)) output.append(" ", registers[rn]); - if(is_math(opcode)) output.append(save ? "s " : " ", registers[rd], ",", registers[rn]); - output.append(",", registers[rm]); - if(op == 0 && shift != 0) output.append(" lsl #", shift); - if(op == 1) output.append(" lsr #", shift == 0 ? 32u : (unsigned)shift); - if(op == 2) output.append(" asr #", shift == 0 ? 32u : (unsigned)shift); - if(op == 3 && shift != 0) output.append(" ror #", shift); - if(op == 3 && shift == 0) output.append(" rrx"); - - return output; - } - - //data register shift - //{opcode}{condition}{s} rd,rm {shift} rs - //{opcode}{condition} rn,rm {shift} rs - //{opcode}{condition}{s} rd,rn,rm {shift} rs - if((instruction & 0x0e000090) == 0x00000010) { - uint4 condition = instruction >> 28; - uint4 opcode = instruction >> 21; - uint1 save = instruction >> 20; - uint4 rn = instruction >> 16; - uint4 rd = instruction >> 12; - uint4 rs = instruction >> 8; - uint2 mode = instruction >> 5; - uint4 rm = instruction; - - output.append(opcodes[opcode], conditions[condition]); - if(is_move(opcode)) output.append(save ? "s " : " ", registers[rd], ","); - if(is_comp(opcode)) output.append(registers[rn], ","); - if(is_math(opcode)) output.append(save ? "s " : " ", registers[rd], ",", registers[rn], ","); - output.append(registers[rm]); - if(mode == 0) output.append(" lsl "); - if(mode == 1) output.append(" lsr "); - if(mode == 2) output.append(" asr "); - if(mode == 3) output.append(" ror "); - output.append(registers[rs]); - - return output; - } - - //data immediate - //{opcode}{condition}{s} rd,#immediate - //{opcode}{condition} rn,#immediate - //{opcode}{condition}{s} rd,rn,#immediate - if((instruction & 0x0e000000) == 0x02000000) { - uint4 condition = instruction >> 28; - uint4 opcode = instruction >> 21; - uint1 save = instruction >> 20; - uint4 rn = instruction >> 16; - uint4 rd = instruction >> 12; - uint4 rotate = instruction >> 8; - uint8 immediate = instruction; - - uint32 shifter = (immediate >> (rotate << 1)) | (immediate << (32 - (rotate << 1))); - output.append(opcodes[opcode], conditions[condition]); - if(is_move(opcode)) output.append(save ? "s " : " ", registers[rd]); - if(is_comp(opcode)) output.append(" ", registers[rn]); - if(is_math(opcode)) output.append(save ? "s " : " ", registers[rd], ",", registers[rn]); - output.append(",#0x", hex<8>(shifter)); - - return output; - } - - //move immediate offset - //(ldr,str){condition}{b} rd,[rn{,+/-offset}]{!} - //(ldr,str){condition}{b} rd,[rn]{,+/-offset} - if((instruction & 0x0e000000) == 0x04000000) { - uint4 condition = instruction >> 28; - uint1 p = instruction >> 24; - uint1 u = instruction >> 23; - uint1 b = instruction >> 22; - uint1 w = instruction >> 21; - uint1 load = instruction >> 20; - uint4 rn = instruction >> 16; - uint4 rd = instruction >> 12; - uint12 immediate = instruction; - - output.append(load ? "ldr" : "str", conditions[condition], b ? "b " : " "); - output.append(registers[rd], ",[", registers[rn]); - if(p == 0) output.append("]"); - if(immediate) output.append(",", u ? "+" : "-", "0x", hex<3>(immediate)); - if(p == 1) output.append("]"); - if(p == 1 && w == 1) output.append("!"); - - if(rn == 15) output.append(" =0x", hex<8>(bus_readword(pc + 8 + (u ? +immediate : -immediate)))); - - return output; - } - - //move register offset - //(ldr)(str){condition}{b} rd,[rn,rm {mode} #immediate]{!} - //(ldr)(str){condition}{b} rd,[rn],rm {mode} #immediate - if((instruction & 0x0e000010) == 0x06000000) { - uint4 condition = instruction >> 28; - uint1 p = instruction >> 24; - uint1 u = instruction >> 23; - uint1 b = instruction >> 22; - uint1 w = instruction >> 21; - uint1 load = instruction >> 20; - uint4 rn = instruction >> 16; - uint4 rd = instruction >> 12; - uint5 shift = instruction >> 7; - uint2 mode = instruction >> 5; - uint4 rm = instruction; - - output.append(load ? "ldr" : "str", conditions[condition], b ? "b " : " "); - output.append(registers[rd], ",[", registers[rn]); - if(p == 0) output.append("]"); - output.append(",", u ? "+" : "-", registers[rm]); - if(mode == 0 && shift != 0) output.append(" lsl #", shift); - if(mode == 1) output.append(" lsr #", shift == 0 ? 32u : (unsigned)shift); - if(mode == 2) output.append(" asr #", shift == 0 ? 32u : (unsigned)shift); - if(mode == 3 && shift != 0) output.append(" ror #", shift); - if(mode == 3 && shift == 0) output.append(" rrx"); - if(p == 1) output.append("]"); - if(p == 1 && w == 1) output.append("!"); - - return output; - } - - //move multiple - //(ldm,stm){condition}{mode} rn{!},{r...} - if((instruction & 0x0e000000) == 0x08000000) { - uint4 condition = instruction >> 28; - uint4 rn = instruction >> 16; - - output.append(instruction & 0x00100000 ? "ldm" : "stm", conditions[condition], indices[(uint2)(instruction >> 23)]); - output.append(" ", registers[rn], instruction & 0x00200000 ? "!" : "", ",{"); - for(unsigned n = 0; n < 16; n++) if(instruction & (1 << n)) output.append(registers[n], ","); - output.rtrim<1>(","); - output.append("}"); - - return output; - } - - //branch - //b{l}{condition} address - if((instruction & 0x0e000000) == 0x0a000000) { - uint4 condition = instruction >> 28; - uint1 l = instruction >> 24; - - output.append("b", l ? "l" : "", conditions[condition]); - output.append(" 0x", hex<8>(pc + 8 + (int24)instruction * 4)); - - return output; - } - - output.append("???"); - return output; -} - -string ArmDSP::disassemble_registers() { - return { - "r0:", hex<8>(r[ 0]), " r1:", hex<8>(r[ 1]), " r2:", hex<8>(r[ 2]), " r3:", hex<8>(r[ 3]), - " r4:", hex<8>(r[ 4]), " r5:", hex<8>(r[ 5]), " r6:", hex<8>(r[ 6]), " r7:", hex<8>(r[ 7]), " ", - "cpsr:", cpsr.n ? "N" : "n", cpsr.z ? "Z" : "z", cpsr.c ? "C" : "c", cpsr.v ? "V" : "v", "\n", - "r8:", hex<8>(r[ 8]), " r9:", hex<8>(r[ 9]), " r10:", hex<8>(r[10]), " r11:", hex<8>(r[11]), - " r12:", hex<8>(r[12]), " r13:", hex<8>(r[13]), " r14:", hex<8>(r[14]), " r15:", hex<8>(r[15]), " ", - "spsr:", spsr.n ? "N" : "n", spsr.z ? "Z" : "z", spsr.c ? "C" : "c", spsr.v ? "V" : "v" - - }; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/armdsp/memory.cpp b/waterbox/libsnes/bsnes/snes/chip/armdsp/memory.cpp deleted file mode 100644 index cf2a0fcab6..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/armdsp/memory.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#ifdef ARMDSP_CPP - -uint8 ArmDSP::bus_read(uint32 addr) { - switch(addr & 0xe0000000) { - case 0x00000000: return programROM[addr & 0x0001ffff]; - case 0x20000000: return pipeline.mdr.opcode >> ((addr & 3) << 3); - case 0x40000000: break; //MMIO - case 0x60000000: return 0x40404001 >> ((addr & 3) << 3); - case 0x80000000: return pipeline.mdr.opcode >> ((addr & 3) << 3); - case 0xa0000000: return dataROM[addr & 0x00007fff]; - case 0xc0000000: return pipeline.mdr.opcode >> ((addr & 3) << 3); - case 0xe0000000: return programRAM[addr & 0x00003fff]; - } - - addr &= 0xe000003f; - - if(addr == 0x40000010) { - if(bridge.cputoarm.ready) { - bridge.cputoarm.ready = false; - return bridge.cputoarm.data; - } - } - - if(addr == 0x40000020) { - return bridge.status(); - } - - return 0x00; -} - -void ArmDSP::bus_write(uint32 addr, uint8 data) { - switch(addr & 0xe0000000) { - case 0x40000000: break; //MMIO - case 0xe0000000: programRAM[addr & 0x00003fff] = data; return; - default: return; - } - - addr &= 0xe000003f; - - if(addr == 0x40000000) { - bridge.armtocpu.ready = true; - bridge.armtocpu.data = data; - return; - } - - if(addr == 0x40000020) bridge.timerlatch = (bridge.timerlatch & 0xffff00) | (data << 0); - if(addr == 0x40000024) bridge.timerlatch = (bridge.timerlatch & 0xff00ff) | (data << 8); - if(addr == 0x40000028) bridge.timerlatch = (bridge.timerlatch & 0x00ffff) | (data << 16); - - if(addr == 0x40000028) { - bridge.timer = bridge.timerlatch; - bridge.busy = !bridge.timer; - } -} - -uint32 ArmDSP::bus_readbyte(uint32 addr) { - tick(); - return bus_read(addr); -} - -void ArmDSP::bus_writebyte(uint32 addr, uint32 data) { - tick(); - return bus_write(addr, data); -} - -uint32 ArmDSP::bus_readword(uint32 addr) { - tick(); - addr &= ~3; - return ( - (bus_read(addr + 0) << 0) - | (bus_read(addr + 1) << 8) - | (bus_read(addr + 2) << 16) - | (bus_read(addr + 3) << 24) - ); -} - -void ArmDSP::bus_writeword(uint32 addr, uint32 data) { - tick(); - addr &= ~3; - bus_write(addr + 0, data >> 0); - bus_write(addr + 1, data >> 8); - bus_write(addr + 2, data >> 16); - bus_write(addr + 3, data >> 24); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/armdsp/opcodes.cpp b/waterbox/libsnes/bsnes/snes/chip/armdsp/opcodes.cpp deleted file mode 100644 index 007a8842b9..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/armdsp/opcodes.cpp +++ /dev/null @@ -1,404 +0,0 @@ -#ifdef ARMDSP_CPP - -bool ArmDSP::condition() { - uint4 condition = instruction >> 28; - switch(condition) { - case 0: return cpsr.z == 1; //EQ (equal) - case 1: return cpsr.z == 0; //NE (not equal) - case 2: return cpsr.c == 1; //CS (carry set) - case 3: return cpsr.c == 0; //CC (carry clear) - case 4: return cpsr.n == 1; //MI (negative) - case 5: return cpsr.n == 0; //PL (positive) - case 6: return cpsr.v == 1; //VS (overflow) - case 7: return cpsr.v == 0; //VC (no overflow) - case 8: return cpsr.c == 1 && cpsr.z == 0; //HI (unsigned higher) - case 9: return cpsr.c == 0 || cpsr.z == 1; //LS (unsigned lower or same) - case 10: return cpsr.n == cpsr.v; //GE (signed greater than or equal) - case 11: return cpsr.n != cpsr.v; //LT (signed less than) - case 12: return cpsr.z == 0 && cpsr.n == cpsr.v; //GT (signed greater than) - case 13: return cpsr.z == 1 || cpsr.n != cpsr.v; //LE (signed less than or equal) - case 14: return true; //AL (always) - case 15: return false; //NV (never) - } -} - -//rd = target -//rn = source -//rm = modifier -//ri = original target -//ro = modified target -void ArmDSP::opcode(uint32 rm) { - uint4 opcode = instruction >> 21; - uint1 save = instruction >> 20; - uint4 n = instruction >> 16; - uint4 d = instruction >> 12; - - uint32 rn = r[n]; - - //comparison opcodes always update flags (debug test) - //this can be removed later: s=0 opcode=8-11 is invalid - if(opcode >= 8 && opcode <= 11) assert(save == 1); - - auto test = [&](uint32 result) { - if(save) { - cpsr.n = result >> 31; - cpsr.z = result == 0; - cpsr.c = shiftercarry; - } - return result; - }; - - auto math = [&](uint32 source, uint32 modify, bool carry) { - uint32 result = source + modify + carry; - if(save) { - uint32 overflow = ~(source ^ modify) & (source ^ result); - cpsr.n = result >> 31; - cpsr.z = result == 0; - cpsr.c = (1u << 31) & (overflow ^ source ^ modify ^ result); - cpsr.v = (1u << 31) & (overflow); - } - return result; - }; - - switch(opcode) { - case 0: r[d] = test(rn & rm); break; //AND - case 1: r[d] = test(rn ^ rm); break; //EOR - case 2: r[d] = math(rn, ~rm, 1); break; //SUB - case 3: r[d] = math(rm, ~rn, 1); break; //RSB - case 4: r[d] = math(rn, rm, 0); break; //ADD - case 5: r[d] = math(rn, rm, cpsr.c); break; //ADC - case 6: r[d] = math(rn, ~rm, cpsr.c); break; //SBC - case 7: r[d] = math(rm, ~rn, cpsr.c); break; //RSC - case 8: test(rn & rm); break; //TST - case 9: test(rn ^ rm); break; //TEQ - case 10: math(rn, ~rm, 1); break; //CMP - case 11: math(rn, rm, 0); break; //CMN - case 12: r[d] = test(rn | rm); break; //ORR - case 13: r[d] = test(rm); break; //MOV - case 14: r[d] = test(rn &~rm); break; //BIC - case 15: r[d] = test(~rm); break; //MVN - } -} - -//logical shift left -void ArmDSP::lsl(bool &c, uint32 &rm, uint32 rs) { - while(rs--) { - c = rm >> 31; - rm <<= 1; - } -} - -//logical shift right -void ArmDSP::lsr(bool &c, uint32 &rm, uint32 rs) { - while(rs--) { - c = rm & 1; - rm >>= 1; - } -} - -//arithmetic shift right -void ArmDSP::asr(bool &c, uint32 &rm, uint32 rs) { - while(rs--) { - c = rm & 1; - rm = (int32)rm >> 1; - } -} - -//rotate right -void ArmDSP::ror(bool &c, uint32 &rm, uint32 rs) { - while(rs--) { - c = rm & 1; - rm = (rm << 31) | (rm >> 1); - } -} - -//rotate right with extend -void ArmDSP::rrx(bool &c, uint32 &rm) { - bool carry = c; - c = rm & 1; - rm = (carry << 31) | (rm >> 1); -} - -//(mul,mla){condition}{s} rd,rm,rs,rn -//cccc 0000 00as dddd nnnn ssss 1001 mmmm -//c = condition -//a = accumulate -//s = save flags -//d = rd -//n = rn -//s = rs -//n = rm -void ArmDSP::op_multiply() { - uint1 accumulate = instruction >> 21; - uint1 save = instruction >> 20; - uint4 d = instruction >> 16; - uint4 n = instruction >> 12; - uint4 s = instruction >> 8; - uint4 m = instruction >> 0; - - //Booth's algorithm: two bit steps - uint32 temp = r[s]; - while(temp) { - temp >>= 2; - tick(); - } - r[d] = r[m] * r[s]; - - if(accumulate) { - tick(); - r[d] += r[n]; - } - - if(save) { - cpsr.n = r[d] >> 31; - cpsr.z = r[d] == 0; - cpsr.c = 0; //undefined - } -} - -//mrs{condition} rd,(c,s)psr -//cccc 0001 0r00 ++++ dddd ---- 0000 ---- -//c = condition -//r = SPSR (0 = CPSR) -//d = rd -void ArmDSP::op_move_to_register_from_status_register() { - uint1 source = instruction >> 22; - uint4 d = instruction >> 12; - - r[d] = source ? spsr : cpsr; -} - -//msr{condition} (c,s)psr:{fields},rm -//cccc 0001 0r10 ffff ++++ ---- 0000 mmmm -//c = condition -//r = SPSR (0 = CPSR) -//f = field mask -//m = rm -void ArmDSP::op_move_to_status_register_from_register() { - uint1 source = instruction >> 22; - uint4 field = instruction >> 16; - uint4 m = instruction; - - PSR &psr = source ? spsr : cpsr; - if(field & 1) psr.setc(r[m]); - if(field & 2) psr.setx(r[m]); - if(field & 4) psr.sets(r[m]); - if(field & 8) psr.setf(r[m]); -} - -//{opcode}{condition}{s} rd,rm {shift} #immediate -//{opcode}{condition} rn,rm {shift} #immediate -//{opcode}{condition}{s} rd,rn,rm {shift} #immediate -//cccc 000o ooos nnnn dddd llll lss0 mmmm -//c = condition -//o = opcode -//s = save flags -//n = rn -//d = rd -//l = shift immmediate -//s = shift -//m = rm -void ArmDSP::op_data_immediate_shift() { - uint1 save = instruction >> 20; - uint5 shift = instruction >> 7; - uint2 mode = instruction >> 5; - uint4 m = instruction; - - uint32 rs = shift; - uint32 rm = r[m]; - bool c = cpsr.c; - - if(mode == 0) lsl(c, rm, rs); - if(mode == 1) lsr(c, rm, rs ? rs : 32); - if(mode == 2) asr(c, rm, rs ? rs : 32); - if(mode == 3) rs ? ror(c, rm, rs) : rrx(c, rm); - - shiftercarry = c; - opcode(rm); -} - -//{opcode}{condition}{s} rd,rm {shift} rs -//{opcode}{condition} rn,rm {shift} rs -//{opcode}{condition}{s} rd,rn,rm {shift} rs -//cccc 000o ooos nnnn dddd ssss 0ss1 mmmm -//c = condition -//o = opcode -//s = save flags -//n = rn -//d = rd -//s = rs -//s = shift -//m = rm -void ArmDSP::op_data_register_shift() { - uint1 save = instruction >> 20; - uint4 s = instruction >> 8; - uint2 mode = instruction >> 5; - uint4 m = instruction >> 0; - - uint8 rs = r[s]; - uint32 rm = r[m]; - bool c = cpsr.c; - - if(mode == 0) lsl(c, rm, rs < 33 ? rs : 33); - if(mode == 1) lsr(c, rm, rs < 33 ? rs : 33); - if(mode == 2) asr(c, rm, rs < 32 ? rs : 32); - if(mode == 3 && rs) ror(c, rm, rs & 31 == 0 ? 32 : rs & 31); - - shiftercarry = c; - opcode(rm); -} - -//{opcode}{condition}{s} rd,#immediate -//{opcode}{condition} rn,#immediate -//{opcode}{condition}{s} rd,rn,#immediate -//cccc 001o ooos nnnn dddd llll iiii iiii -//c = condition -//o = opcode -//s = save flags -//n = rn -//d = rd -//l = shift immediate -//i = immediate -void ArmDSP::op_data_immediate() { - uint1 save = instruction >> 20; - uint4 shift = instruction >> 8; - uint8 immediate = instruction; - - uint32 rs = shift << 1; - uint32 rm = (immediate >> rs) | (immediate << (32 - rs)); - if(rs) shiftercarry = immediate >> 31; - - opcode(rm); -} - -//(ldr,str){condition}{b} rd,[rn{,+/-offset}]{!} -//(ldr,str){condition}{b} rd,[rn]{,+/-offset} -//cccc 010p ubwl nnnn dddd iiii iiii iiii -//c = condition -//p = pre (0 = post-indexed addressing) -//u = up (add/sub offset to base) -//b = byte (1 = 32-bit) -//w = writeback -//l = load (0 = save) -//n = rn -//d = rd -//i = immediate -void ArmDSP::op_move_immediate_offset() { - uint1 p = instruction >> 24; - uint1 u = instruction >> 23; - uint1 b = instruction >> 22; - uint1 w = instruction >> 21; - uint1 l = instruction >> 20; - uint4 n = instruction >> 16; - uint4 d = instruction >> 12; - uint12 rm = instruction; - - uint32 rn = r[n]; - auto &rd = r[d]; - - if(p == 1) rn = u ? rn + rm : rn - rm; - if(l) rd = b ? bus_readbyte(rn) : bus_readword(rn); - else b ? bus_writebyte(rn, rd) : bus_writeword(rn, rd); - if(p == 0) rn = u ? rn + rm : rn - rm; - - if(p == 0 || w == 1) r[n] = rn; -} - -//(ldr)(str){condition}{b} rd,[rn,rm {mode} #immediate]{!} -//(ldr)(str){condition}{b} rd,[rn],rm {mode} #immediate -//cccc 011p ubwl nnnn dddd llll lss0 mmmm -//c = condition -//p = pre (0 = post-indexed addressing) -//u = up -//b = byte (1 = 32-bit) -//w = writeback -//l = load (0 = save) -//n = rn -//d = rd -//l = shift immediate -//s = shift mode -//m = rm -void ArmDSP::op_move_register_offset() { - uint1 p = instruction >> 24; - uint1 u = instruction >> 23; - uint1 b = instruction >> 22; - uint1 w = instruction >> 21; - uint1 l = instruction >> 20; - uint4 n = instruction >> 16; - uint4 d = instruction >> 12; - uint5 immediate = instruction >> 7; - uint2 mode = instruction >> 5; - uint4 m = instruction; - - uint32 rn = r[n]; - auto &rd = r[d]; - uint32 rs = immediate; - uint32 rm = r[m]; - bool c = cpsr.c; - - if(mode == 0) lsl(c, rm, rs); - if(mode == 1) lsr(c, rm, rs ? rs : 32); - if(mode == 2) asr(c, rm, rs ? rs : 32); - if(mode == 3) rs ? ror(c, rm, rs) : rrx(c, rm); - - if(p == 1) rn = u ? rn + rm : rn - rm; - if(l) rd = b ? bus_readbyte(rn) : bus_readword(rn); - else b ? bus_writebyte(rn, rd) : bus_writeword(rn, rd); - if(p == 0) rn = u ? rn + rm : rn - rm; - - if(p == 0 || w == 1) r[n] = rn; -} - -//(ldm,stm){condition}{mode} rn{!},{r...} -//cccc 100p uswl nnnn llll llll llll llll -//c = condition -//p = pre (0 = post-indexed addressing) -//u = up (add/sub offset to base) -//s = ??? -//w = writeback -//l = load (0 = save) -//n = rn -//l = register list -void ArmDSP::op_move_multiple() { - uint1 p = instruction >> 24; - uint1 u = instruction >> 23; - uint1 s = instruction >> 22; - uint1 w = instruction >> 21; - uint1 l = instruction >> 20; - uint4 n = instruction >> 16; - uint16 list = instruction; - - uint32 rn = r[n]; - if(p == 0 && u == 1) rn = rn + 0; //IA - if(p == 1 && u == 1) rn = rn + 4; //IB - if(p == 1 && u == 0) rn = rn - bit::count(list) * 4 + 0; //DB - if(p == 0 && u == 0) rn = rn - bit::count(list) * 4 + 4; //DA - - for(unsigned n = 0; n < 16; n++) { - if(list & (1 << n)) { - if(l) r[n] = bus_readword(rn); - else bus_writeword(rn, r[n]); - rn += 4; - } - } - - if(w) { - if(u == 1) r[n] = r[n] + bit::count(list) * 4; //IA, IB - if(u == 0) r[n] = r[n] - bit::count(list) * 4; //DA, DB - } -} - -//b{l}{condition} address -//cccc 101l dddd dddd dddd dddd dddd dddd -//c = condition -//l = link -//d = displacement (24-bit signed) -void ArmDSP::op_branch() { - uint1 l = instruction >> 24; - int24 displacement = instruction; - - if(l) r[14] = r[15] - 4; - r[15] += displacement * 4; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/armdsp/registers.hpp b/waterbox/libsnes/bsnes/snes/chip/armdsp/registers.hpp deleted file mode 100644 index f7e4e30b6e..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/armdsp/registers.hpp +++ /dev/null @@ -1,123 +0,0 @@ -//Exceptions: -//00000000 = reset -//00000004 = undefined instruction -//00000008 = software interrupt -//0000000c = prefetch abort -//00000010 = data abort -//00000018 = IRQ (interrupt) -//0000001c = FIQ (fast interrupt) - -struct Bridge { - struct Buffer { - bool ready; - uint8 data; - }; - Buffer cputoarm; - Buffer armtocpu; - uint32 timer; - uint32 timerlatch; - bool reset; - bool ready; - bool busy; - - uint8 status() const { - return (ready << 7) | (cputoarm.ready << 3) | (busy << 2) | (armtocpu.ready << 0); - } -} bridge; - -struct PSR { - bool n; - bool z; - bool c; - bool v; - bool i; - bool f; - uint5 m; - - uint32 getf() const { - return (n << 31) | (z << 30) | (c << 29) | (v << 28); - } - - uint32 gets() const { - return 0u; - } - - uint32 getx() const { - return 0u; - } - - uint32 getc() const { - return (i << 7) | (f << 6) | (m << 0); - } - - void setf(uint32 data) { - n = data & 0x80000000; - z = data & 0x40000000; - c = data & 0x20000000; - v = data & 0x10000000; - } - - void sets(uint32 data) { - } - - void setx(uint32 data) { - } - - void setc(uint32 data) { - i = data & 0x00000080; - f = data & 0x00000040; - m = data & 0x0000001f; - } - - operator uint32() const { - return getf() | gets() | getx() | getc(); - } - - PSR& operator=(uint32 data) { - setf(data), sets(data), setx(data), setc(data); - return *this; - } -} cpsr, spsr; - -//r13 = SP (stack pointer) -//r14 = LR (link register) -//r15 = PC (program counter) -struct Register { - uint32 data; - function write; - - operator unsigned() const { - return data; - } - - Register& operator=(uint32 n) { - data = n; - if(write) write(); - return *this; - } - - Register& operator+=(uint32 n) { return operator=(data + n); } - Register& operator-=(uint32 n) { return operator=(data - n); } - Register& operator&=(uint32 n) { return operator=(data & n); } - Register& operator|=(uint32 n) { return operator=(data | n); } - Register& operator^=(uint32 n) { return operator=(data ^ n); } - - void step() { - data += 4; - } -} r[16]; - -bool shiftercarry; -uint32 instruction; -bool exception; - -struct Pipeline { - bool reload; - struct Instruction { - uint32 opcode; - uint32 address; - }; - Instruction instruction; - Instruction prefetch; - Instruction mdr; -} pipeline; diff --git a/waterbox/libsnes/bsnes/snes/chip/bsx/bsx.cpp b/waterbox/libsnes/bsnes/snes/chip/bsx/bsx.cpp deleted file mode 100644 index 450c0423af..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/bsx/bsx.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include - -#define BSX_CPP -namespace SNES { - #include "satellaview/satellaview.cpp" - #include "cartridge/cartridge.cpp" - #include "flash/flash.cpp" -} diff --git a/waterbox/libsnes/bsnes/snes/chip/bsx/bsx.hpp b/waterbox/libsnes/bsnes/snes/chip/bsx/bsx.hpp deleted file mode 100644 index 5f3895bd1b..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/bsx/bsx.hpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "satellaview/satellaview.hpp" -#include "cartridge/cartridge.hpp" -#include "flash/flash.hpp" diff --git a/waterbox/libsnes/bsnes/snes/chip/bsx/cartridge/cartridge.cpp b/waterbox/libsnes/bsnes/snes/chip/bsx/cartridge/cartridge.cpp deleted file mode 100644 index 9fbc2c84f2..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/bsx/cartridge/cartridge.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#ifdef BSX_CPP - -BSXCartridge bsxcartridge; - -BSXCartridge::BSXCartridge() - : sram("BSX_RAM") - , psram("BSX_PRAM") -{ -} - -void BSXCartridge::init() { -} - -void BSXCartridge::load() { - sram.map(allocate(32 * 1024, 0xff), 32 * 1024); - sram.write_protect(false); - cartridge.nvram.append({ "bsx.ram", sram.data(), sram.size() }); - - psram.map(allocate(512 * 1024, 0xff), 512 * 1024); - psram.write_protect(false); - cartridge.nvram.append({ "bsx.psram", psram.data(), psram.size() }); -} - -void BSXCartridge::unload() { -} - -void BSXCartridge::power() { -} - -void BSXCartridge::reset() { - for(unsigned i = 0; i < 16; i++) r[i] = 0x00; - r[0x07] = 0x80; - r[0x08] = 0x80; - mmio_commit(); -} - -uint8 BSXCartridge::memory_access(bool write, Memory &memory, unsigned addr, uint8 data) { - if(write == 0) return memory_read(memory, addr); - memory_write(memory, addr, data); -} - -uint8 BSXCartridge::memory_read(Memory &memory, unsigned addr) { - addr = bus.mirror(addr, memory.size()); - return memory.read(addr); -} - -void BSXCartridge::memory_write(Memory &memory, unsigned addr, uint8 data) { - addr = bus.mirror(addr, memory.size()); - return memory.write(addr, data); -} - -//mcu_access() allows mcu_read() and mcu_write() to share decoding logic -uint8 BSXCartridge::mcu_access(bool write, unsigned addr, uint8 data) { - if((addr & 0xe08000) == 0x008000) { //$00-1f:8000-ffff - if(r07 == 1) { - addr = ((addr & 0x1f0000) >> 1) | (addr & 0x7fff); - return memory_access(write, cartridge.rom, addr, data); - } - } - - if((addr & 0xe08000) == 0x808000) { //$80-9f:8000-ffff - if(r08 == 1) { - addr = ((addr & 0x1f0000) >> 1) | (addr & 0x7fff); - return memory_access(write, cartridge.rom, addr, data); - } - } - - if((addr & 0xe0e000) == 0x206000) { //$20-3f:6000-7fff - return memory_access(write, psram, addr, data); - } - - if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff - if(r05 == 0) return memory_access(write, psram, addr & 0x0fffff, data); - } - - if((addr & 0xf00000) == 0x500000) { //$50-5f:0000-ffff - if(r06 == 0) return memory_access(write, psram, addr & 0x0fffff, data); - } - - if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff - if(r03 == 1) return memory_access(write, psram, addr & 0x0fffff, data); - } - - if((addr & 0xf80000) == 0x700000) { //$70-77:0000-ffff - return memory_access(write, psram, addr & 0x07ffff, data); - } - - if(((addr & 0x408000) == 0x008000) //$00-3f|80-bf:8000-ffff - || ((addr & 0x400000) == 0x400000) //$40-7f|c0-ff:0000-ffff - ) { - if(r02 == 0) addr = ((addr & 0x7f0000) >> 1) | (addr & 0x7fff); - Memory &memory = (r01 == 0 ? (Memory&)bsxflash : (Memory&)psram); - return memory_access(write, memory, addr & 0x7fffff, data); - } - - return cpu.regs.mdr; -} - -uint8 BSXCartridge::mcu_read(unsigned addr) { - return mcu_access(0, addr); -} - -void BSXCartridge::mcu_write(unsigned addr, uint8 data) { - mcu_access(1, addr, data); -} - -uint8 BSXCartridge::mmio_read(unsigned addr) { - if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000 - uint8 n = (addr >> 16) & 15; - return r[n]; - } - - if((addr & 0xf8f000) == 0x105000) { //$10-17:5000-5fff - return memory_read(sram, ((addr >> 16) & 7) * 0x1000 + (addr & 0xfff)); - } - - return 0x00; -} - -void BSXCartridge::mmio_write(unsigned addr, uint8 data) { - if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000 - uint8 n = (addr >> 16) & 15; - r[n] = data; - if(n == 0x0e && data & 0x80) mmio_commit(); - return; - } - - if((addr & 0xf8f000) == 0x105000) { //$10-17:5000-5fff - return memory_write(sram, ((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data); - } -} - -void BSXCartridge::mmio_commit() { - r00 = r[0x00] & 0x80; - r01 = r[0x01] & 0x80; - r02 = r[0x02] & 0x80; - r03 = r[0x03] & 0x80; - r04 = r[0x04] & 0x80; - r05 = r[0x05] & 0x80; - r06 = r[0x06] & 0x80; - r07 = r[0x07] & 0x80; - r08 = r[0x08] & 0x80; - r09 = r[0x09] & 0x80; - r0a = r[0x0a] & 0x80; - r0b = r[0x0b] & 0x80; - r0c = r[0x0c] & 0x80; - r0d = r[0x0d] & 0x80; - r0e = r[0x0e] & 0x80; - r0f = r[0x0f] & 0x80; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/bsx/cartridge/cartridge.hpp b/waterbox/libsnes/bsnes/snes/chip/bsx/cartridge/cartridge.hpp deleted file mode 100644 index 7fb6cd71ed..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/bsx/cartridge/cartridge.hpp +++ /dev/null @@ -1,34 +0,0 @@ -class BSXCartridge { -public: - MappedRAM sram; - MappedRAM psram; - - void init(); - void load(); - void unload(); - void power(); - void reset(); - - uint8 memory_access(bool write, Memory &memory, unsigned addr, uint8 data); - uint8 memory_read(Memory &memory, unsigned addr); - void memory_write(Memory &memory, unsigned addr, uint8 data); - - uint8 mcu_access(bool write, unsigned addr, uint8 data = 0x00); - uint8 mcu_read(unsigned addr); - void mcu_write(unsigned addr, uint8 data); - - uint8 mmio_read(unsigned addr); - void mmio_write(unsigned addr, uint8 data); - void mmio_commit(); - - BSXCartridge(); - -private: - uint8 r[16]; - bool r00, r01, r02, r03; - bool r04, r05, r06, r07; - bool r08, r09, r0a, r0b; - bool r0c, r0d, r0e, r0f; -}; - -extern BSXCartridge bsxcartridge; diff --git a/waterbox/libsnes/bsnes/snes/chip/bsx/flash/flash.cpp b/waterbox/libsnes/bsnes/snes/chip/bsx/flash/flash.cpp deleted file mode 100644 index 17b525b63a..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/bsx/flash/flash.cpp +++ /dev/null @@ -1,127 +0,0 @@ -#ifdef BSX_CPP - -BSXFlash bsxflash; - -void BSXFlash::init() { -} - -void BSXFlash::load() { - if(memory.size() == 0) { - memory.map(allocate(1024 * 1024, 0xff), 1024 * 1024); - } -} - -void BSXFlash::unload() { - memory.reset(); -} - -void BSXFlash::power() { -} - -void BSXFlash::reset() { - regs.command = 0; - regs.write_old = 0x00; - regs.write_new = 0x00; - - regs.flash_enable = false; - regs.read_enable = false; - regs.write_enable = false; - memory.write_protect(!regs.write_enable); -} - -unsigned BSXFlash::size() const { - return memory.size(); -} - -uint8 BSXFlash::read(unsigned addr) { - if(addr == 0x0002) { - if(regs.flash_enable) return 0x80; - } - - if(addr == 0x5555) { - if(regs.flash_enable) return 0x80; - } - - if(regs.read_enable && addr >= 0xff00 && addr <= 0xff13) { - //read flash cartridge vendor information - switch(addr - 0xff00) { - case 0x00: return 0x4d; - case 0x01: return 0x00; - case 0x02: return 0x50; - case 0x03: return 0x00; - case 0x04: return 0x00; - case 0x05: return 0x00; - case 0x06: return 0x2a; //0x2a = 8mbit, 0x2b = 16mbit (not known to exist, though BIOS recognizes ID) - case 0x07: return 0x00; - default: return 0x00; - } - } - - return memory.read(addr); -} - -void BSXFlash::write(unsigned addr, uint8 data) { - //there exist both read-only and read-write BS-X flash cartridges ... - //unfortunately, the vendor info is not stored inside memory dumps - //of BS-X flashcarts, so it is impossible to determine whether a - //given flashcart is writeable. - //however, it has been observed that LoROM-mapped BS-X carts always - //use read-write flashcarts, and HiROM-mapped BS-X carts always use - //read-only flashcarts. - //below is an unfortunately necessary workaround to this problem. - //if(cartridge.mapper() == Cartridge::BSCHiROM) return; - - if((addr & 0xff0000) == 0) { - regs.write_old = regs.write_new; - regs.write_new = data; - - if(regs.write_enable && regs.write_old == regs.write_new) { - return memory.write(addr, data); - } - } else { - if(regs.write_enable) { - return memory.write(addr, data); - } - } - - if(addr == 0x0000) { - regs.command <<= 8; - regs.command |= data; - - if((regs.command & 0xffff) == 0x38d0) { - regs.flash_enable = true; - regs.read_enable = true; - } - } - - if(addr == 0x2aaa) { - regs.command <<= 8; - regs.command |= data; - } - - if(addr == 0x5555) { - regs.command <<= 8; - regs.command |= data; - - if((regs.command & 0xffffff) == 0xaa5570) { - regs.write_enable = false; - } - - if((regs.command & 0xffffff) == 0xaa55a0) { - regs.write_old = 0x00; - regs.write_new = 0x00; - regs.flash_enable = true; - regs.write_enable = true; - } - - if((regs.command & 0xffffff) == 0xaa55f0) { - regs.flash_enable = false; - regs.read_enable = false; - regs.write_enable = false; - } - - memory.write_protect(!regs.write_enable); - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/bsx/flash/flash.hpp b/waterbox/libsnes/bsnes/snes/chip/bsx/flash/flash.hpp deleted file mode 100644 index 353bef1970..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/bsx/flash/flash.hpp +++ /dev/null @@ -1,27 +0,0 @@ -class BSXFlash : public Memory { -public: - MappedRAM memory; - - void init(); - void load(); - void unload(); - void power(); - void reset(); - - unsigned size() const; - uint8 read(unsigned addr); - void write(unsigned addr, uint8 data); - -private: - struct { - unsigned command; - uint8 write_old; - uint8 write_new; - - bool flash_enable; - bool read_enable; - bool write_enable; - } regs; -}; - -extern BSXFlash bsxflash; diff --git a/waterbox/libsnes/bsnes/snes/chip/bsx/satellaview/satellaview.cpp b/waterbox/libsnes/bsnes/snes/chip/bsx/satellaview/satellaview.cpp deleted file mode 100644 index c52c10aa17..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/bsx/satellaview/satellaview.cpp +++ /dev/null @@ -1,142 +0,0 @@ -#ifdef BSX_CPP - -BSXSatellaview bsxsatellaview; - -void BSXSatellaview::init() { -} - -void BSXSatellaview::load() { - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2188, 0x219f, { &BSXSatellaview::mmio_read, &bsxsatellaview }, { &BSXSatellaview::mmio_write, &bsxsatellaview }); - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2188, 0x219f, { &BSXSatellaview::mmio_read, &bsxsatellaview }, { &BSXSatellaview::mmio_write, &bsxsatellaview }); -} - -void BSXSatellaview::unload() { -} - -void BSXSatellaview::power() { -} - -void BSXSatellaview::reset() { - memset(®s, 0x00, sizeof regs); -} - -uint8 BSXSatellaview::mmio_read(unsigned addr) { - addr &= 0xffff; - - switch(addr) { - case 0x2188: return regs.r2188; - case 0x2189: return regs.r2189; - case 0x218a: return regs.r218a; - case 0x218c: return regs.r218c; - case 0x218e: return regs.r218e; - case 0x218f: return regs.r218f; - case 0x2190: return regs.r2190; - - case 0x2192: { - unsigned counter = regs.r2192_counter++; - if(regs.r2192_counter >= 18) regs.r2192_counter = 0; - - if(counter == 0) { - time_t rawtime; - rawtime = SNES::interface()->currentTime(); - tm *t = localtime(&rawtime); - - regs.r2192_hour = t->tm_hour; - regs.r2192_minute = t->tm_min; - regs.r2192_second = t->tm_sec; - } - - switch(counter) { - case 0: return 0x00; //??? - case 1: return 0x00; //??? - case 2: return 0x00; //??? - case 3: return 0x00; //??? - case 4: return 0x00; //??? - case 5: return 0x01; - case 6: return 0x01; - case 7: return 0x00; - case 8: return 0x00; - case 9: return 0x00; - case 10: return regs.r2192_second; - case 11: return regs.r2192_minute; - case 12: return regs.r2192_hour; - case 13: return 0x00; //??? - case 14: return 0x00; //??? - case 15: return 0x00; //??? - case 16: return 0x00; //??? - case 17: return 0x00; //??? - } - } break; - - case 0x2193: return regs.r2193 & ~0x0c; - case 0x2194: return regs.r2194; - case 0x2196: return regs.r2196; - case 0x2197: return regs.r2197; - case 0x2199: return regs.r2199; - } - - return cpu.regs.mdr; -} - -void BSXSatellaview::mmio_write(unsigned addr, uint8 data) { - addr &= 0xffff; - - switch(addr) { - case 0x2188: { - regs.r2188 = data; - } break; - - case 0x2189: { - regs.r2189 = data; - } break; - - case 0x218a: { - regs.r218a = data; - } break; - - case 0x218b: { - regs.r218b = data; - } break; - - case 0x218c: { - regs.r218c = data; - } break; - - case 0x218e: { - regs.r218e = data; - } break; - - case 0x218f: { - regs.r218e >>= 1; - regs.r218e = regs.r218f - regs.r218e; - regs.r218f >>= 1; - } break; - - case 0x2191: { - regs.r2191 = data; - regs.r2192_counter = 0; - } break; - - case 0x2192: { - regs.r2190 = 0x80; - } break; - - case 0x2193: { - regs.r2193 = data; - } break; - - case 0x2194: { - regs.r2194 = data; - } break; - - case 0x2197: { - regs.r2197 = data; - } break; - - case 0x2199: { - regs.r2199 = data; - } break; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/bsx/satellaview/satellaview.hpp b/waterbox/libsnes/bsnes/snes/chip/bsx/satellaview/satellaview.hpp deleted file mode 100644 index 0f99acbd5c..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/bsx/satellaview/satellaview.hpp +++ /dev/null @@ -1,26 +0,0 @@ -class BSXSatellaview { -public: - void init(); - void load(); - void unload(); - void power(); - void reset(); - - uint8 mmio_read(unsigned addr); - void mmio_write(unsigned addr, uint8 data); - -private: - struct { - uint8 r2188, r2189, r218a, r218b; - uint8 r218c, r218d, r218e, r218f; - uint8 r2190, r2191, r2192, r2193; - uint8 r2194, r2195, r2196, r2197; - uint8 r2198, r2199, r219a, r219b; - uint8 r219c, r219d, r219e, r219f; - - uint8 r2192_counter; - uint8 r2192_hour, r2192_minute, r2192_second; - } regs; -}; - -extern BSXSatellaview bsxsatellaview; diff --git a/waterbox/libsnes/bsnes/snes/chip/chip.hpp b/waterbox/libsnes/bsnes/snes/chip/chip.hpp deleted file mode 100644 index fe13a0a4ec..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/chip.hpp +++ /dev/null @@ -1,31 +0,0 @@ -struct Coprocessor : Processor { - alwaysinline void step(unsigned clocks); - alwaysinline void synchronize_cpu(); -}; - -#if defined(GAMEBOY) - #include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void Coprocessor::step(unsigned clocks) { - clock += clocks * (uint64)cpu.frequency; -} - -void Coprocessor::synchronize_cpu() { - if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); -} diff --git a/waterbox/libsnes/bsnes/snes/chip/hitachidsp/hitachidsp.cpp b/waterbox/libsnes/bsnes/snes/chip/hitachidsp/hitachidsp.cpp deleted file mode 100644 index 235d08f1a6..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/hitachidsp/hitachidsp.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include - -#define HITACHIDSP_CPP -namespace SNES { - -#include "memory.cpp" -#include "opcodes.cpp" -#include "registers.cpp" -HitachiDSP hitachidsp; - -//zero 01-sep-2014 - dont clobber these when reconstructing! -unsigned HitachiDSP::frequency; -uint24 HitachiDSP::dataROM[1024]; - -void HitachiDSP::Enter() { hitachidsp.enter(); } - -void HitachiDSP::enter() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - switch(state) { - case State::Idle: - step(1); - break; - case State::DMA: - for(unsigned n = 0; n < regs.dma_length; n++) { - bus.write(regs.dma_target + n, bus.read(regs.dma_source + n)); - step(2); - } - state = State::Idle; - break; - case State::Execute: - unsigned offset = regs.program_offset + regs.pc * 2; - opcode = bus_read(offset + 0) << 0; - opcode |= bus_read(offset + 1) << 8; - regs.pc = (regs.pc & 0xffff00) | ((regs.pc + 1) & 0x0000ff); - exec(); - step(1); - break; - } - - synchronize_cpu(); - } -} - -void HitachiDSP::init() { -} - -void HitachiDSP::load() { -} - -void HitachiDSP::unload() { -} - -void HitachiDSP::power() { -} - -void HitachiDSP::reset() { - create(HitachiDSP::Enter, frequency, 8192); - state = State::Idle; - - regs.n = 0; - regs.z = 0; - regs.c = 0; - - regs.dma_source = 0x000000; - regs.dma_length = 0x0000; - regs.dma_target = 0x000000; - regs.r1f48 = 0x00; - regs.program_offset = 0x000000; - regs.r1f4c = 0x00; - regs.page_number = 0x0000; - regs.program_counter = 0x00; - regs.r1f50 = 0x33; - regs.r1f51 = 0x00; - regs.r1f52 = 0x01; -} - -} diff --git a/waterbox/libsnes/bsnes/snes/chip/hitachidsp/hitachidsp.hpp b/waterbox/libsnes/bsnes/snes/chip/hitachidsp/hitachidsp.hpp deleted file mode 100644 index 4aae361ad3..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/hitachidsp/hitachidsp.hpp +++ /dev/null @@ -1,48 +0,0 @@ -//Hitachi HG51B169 - -class HitachiDSP : public Coprocessor { -public: - - //zero 01-sep-2014 - dont clobber these when reconstructing! - static unsigned frequency; - static uint24 dataROM[1024]; - - uint8 dataRAM[3072]; - uint24 stack[8]; - uint16 opcode; - enum class State : unsigned { Idle, DMA, Execute } state; - #include "registers.hpp" - - static void Enter(); - void enter(); - - void init(); - void load(); - void unload(); - void power(); - void reset(); - - //memory.cpp - uint8 bus_read(unsigned addr); - void bus_write(unsigned addr, uint8 data); - - uint8 rom_read(unsigned addr); - void rom_write(unsigned addr, uint8 data); - - uint8 dsp_read(unsigned addr); - void dsp_write(unsigned addr, uint8 data); - - //opcodes.cpp - void push(); - void pull(); - unsigned sa(); - unsigned ri(); - unsigned np(); - void exec(); - - //registers.cpp - unsigned reg_read(unsigned n) const; - void reg_write(unsigned n, unsigned data); -}; - -extern HitachiDSP hitachidsp; diff --git a/waterbox/libsnes/bsnes/snes/chip/hitachidsp/memory.cpp b/waterbox/libsnes/bsnes/snes/chip/hitachidsp/memory.cpp deleted file mode 100644 index fca7ec8729..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/hitachidsp/memory.cpp +++ /dev/null @@ -1,138 +0,0 @@ -#ifdef HITACHIDSP_CPP - -uint8 HitachiDSP::bus_read(unsigned addr) { - if((addr & 0x408000) == 0x008000) return bus.read(addr); - return 0x00; -} - -void HitachiDSP::bus_write(unsigned addr, uint8 data) { - if((addr & 0x40e000) == 0x006000) return bus.write(addr, data); -} - -uint8 HitachiDSP::rom_read(unsigned addr) { - if(co_active() == cpu.thread) { - if(state == State::Idle) - { - cdlInfo.set(eCDLog_AddrType_CARTROM, addr); - return cartridge.rom.read(addr); - } - if((addr & 0x40ffe0) == 0x00ffe0) return regs.vector[addr & 0x1f]; - return cpu.regs.mdr; - } - if(co_active() == hitachidsp.thread) { - cdlInfo.set(eCDLog_AddrType_CARTROM, addr); - return cartridge.rom.read(addr); - } - return cpu.regs.mdr; -} - -void HitachiDSP::rom_write(unsigned addr, uint8 data) { -} - -uint8 HitachiDSP::dsp_read(unsigned addr) { - addr &= 0x1fff; - - //Data RAM - if((addr >= 0x0000 && addr <= 0x0bff) || (addr >= 0x1000 && addr <= 0x1bff)) { - return dataRAM[addr & 0x0fff]; - } - - //MMIO - switch(addr) { - case 0x1f40: return regs.dma_source >> 0; - case 0x1f41: return regs.dma_source >> 8; - case 0x1f42: return regs.dma_source >> 16; - case 0x1f43: return regs.dma_length >> 0; - case 0x1f44: return regs.dma_length >> 8; - case 0x1f45: return regs.dma_target >> 0; - case 0x1f46: return regs.dma_target >> 8; - case 0x1f47: return regs.dma_target >> 16; - case 0x1f48: return regs.r1f48; - case 0x1f49: return regs.program_offset >> 0; - case 0x1f4a: return regs.program_offset >> 8; - case 0x1f4b: return regs.program_offset >> 16; - case 0x1f4c: return regs.r1f4c; - case 0x1f4d: return regs.page_number >> 0; - case 0x1f4e: return regs.page_number >> 8; - case 0x1f4f: return regs.program_counter; - case 0x1f50: return regs.r1f50; - case 0x1f51: return regs.r1f51; - case 0x1f52: return regs.r1f52; - case 0x1f53: case 0x1f54: case 0x1f55: case 0x1f56: - case 0x1f57: case 0x1f58: case 0x1f59: case 0x1f5a: - case 0x1f5b: case 0x1f5c: case 0x1f5d: case 0x1f5e: - case 0x1f5f: return ((state != State::Idle) << 6) | ((state == State::Idle) << 1); - } - - //Vector - if(addr >= 0x1f60 && addr <= 0x1f7f) { - return regs.vector[addr & 0x1f]; - } - - //GPRs - if((addr >= 0x1f80 && addr <= 0x1faf) || (addr >= 0x1fc0 && addr <= 0x1fef)) { - unsigned index = (addr & 0x3f) / 3; //0..15 - unsigned shift = ((addr & 0x3f) % 3) * 8; //0, 8, 16 - return regs.gpr[index] >> shift; - } - - return 0x00; -} - -void HitachiDSP::dsp_write(unsigned addr, uint8 data) { - addr &= 0x1fff; - - //Data RAM - if((addr >= 0x0000 && addr <= 0x0bff) || (addr >= 0x1000 && addr <= 0x1bff)) { - dataRAM[addr & 0x0fff] = data; - return; - } - - //MMIO - switch(addr) { - case 0x1f40: regs.dma_source = (regs.dma_source & 0xffff00) | (data << 0); return; - case 0x1f41: regs.dma_source = (regs.dma_source & 0xff00ff) | (data << 8); return; - case 0x1f42: regs.dma_source = (regs.dma_source & 0x00ffff) | (data << 16); return; - case 0x1f43: regs.dma_length = (regs.dma_length & 0xff00) | (data << 0); return; - case 0x1f44: regs.dma_length = (regs.dma_length & 0x00ff) | (data << 8); return; - case 0x1f45: regs.dma_target = (regs.dma_target & 0xffff00) | (data << 0); return; - case 0x1f46: regs.dma_target = (regs.dma_target & 0xff00ff) | (data << 8); return; - case 0x1f47: regs.dma_target = (regs.dma_target & 0x00ffff) | (data << 16); - if(state == State::Idle) state = State::DMA; - return; - case 0x1f48: regs.r1f48 = data & 0x01; return; - case 0x1f49: regs.program_offset = (regs.program_offset & 0xffff00) | (data << 0); return; - case 0x1f4a: regs.program_offset = (regs.program_offset & 0xff00ff) | (data << 8); return; - case 0x1f4b: regs.program_offset = (regs.program_offset & 0x00ffff) | (data << 16); return; - case 0x1f4c: regs.r1f4c = data & 0x03; return; - case 0x1f4d: regs.page_number = (regs.page_number & 0x7f00) | ((data & 0xff) << 0); return; - case 0x1f4e: regs.page_number = (regs.page_number & 0x00ff) | ((data & 0x7f) << 8); return; - case 0x1f4f: regs.program_counter = data; - if(state == State::Idle) { - regs.pc = regs.page_number * 256 + regs.program_counter; - state = State::Execute; - } - return; - case 0x1f50: regs.r1f50 = data & 0x77; return; - case 0x1f51: regs.r1f51 = data & 0x01; return; - case 0x1f52: regs.r1f52 = data & 0x01; return; - } - - //Vector - if(addr >= 0x1f60 && addr <= 0x1f7f) { - regs.vector[addr & 0x1f] = data; - return; - } - - //GPRs - if((addr >= 0x1f80 && addr <= 0x1faf) || (addr >= 0x1fc0 && addr <= 0x1fef)) { - unsigned index = (addr & 0x3f) / 3; - switch((addr & 0x3f) % 3) { - case 0: regs.gpr[index] = (regs.gpr[index] & 0xffff00) | (data << 0); return; - case 1: regs.gpr[index] = (regs.gpr[index] & 0xff00ff) | (data << 8); return; - case 2: regs.gpr[index] = (regs.gpr[index] & 0x00ffff) | (data << 16); return; - } - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/hitachidsp/opcodes.cpp b/waterbox/libsnes/bsnes/snes/chip/hitachidsp/opcodes.cpp deleted file mode 100644 index 6fc9d2d73d..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/hitachidsp/opcodes.cpp +++ /dev/null @@ -1,356 +0,0 @@ -#ifdef HITACHIDSP_CPP - -void HitachiDSP::push() { - stack[7] = stack[6]; - stack[6] = stack[5]; - stack[5] = stack[4]; - stack[4] = stack[3]; - stack[3] = stack[2]; - stack[2] = stack[1]; - stack[1] = stack[0]; - stack[0] = regs.pc; -} - -void HitachiDSP::pull() { - regs.pc = stack[0]; - stack[0] = stack[1]; - stack[1] = stack[2]; - stack[2] = stack[3]; - stack[3] = stack[4]; - stack[4] = stack[5]; - stack[5] = stack[6]; - stack[6] = stack[7]; - stack[7] = 0x0000; -} - -//Shift-A: math opcodes can shift A register prior to ALU operation -unsigned HitachiDSP::sa() { - switch(opcode & 0x0300) { default: - case 0x0000: return regs.a << 0; - case 0x0100: return regs.a << 1; - case 0x0200: return regs.a << 8; - case 0x0300: return regs.a << 16; - } -} - -//Register-or-Immediate: most opcodes can load from a register or immediate -unsigned HitachiDSP::ri() { - if(opcode & 0x0400) return opcode & 0xff; - return reg_read(opcode & 0xff); -} - -//New-PC: determine jump target address; opcode.d9 = long jump flag (1 = yes) -unsigned HitachiDSP::np() { - if(opcode & 0x0200) return (regs.p << 8) | (opcode & 0xff); - return (regs.pc & 0xffff00) | (opcode & 0xff); -} - -void HitachiDSP::exec() { - if((opcode & 0xffff) == 0x0000) { - //0000 0000 0000 0000 - //nop - } - - else if((opcode & 0xdd00) == 0x0800) { - //00.0 10.0 .... .... - //jump i - if(opcode & 0x2000) push(); - regs.pc = np(); - } - - else if((opcode & 0xdd00) == 0x0c00) { - //00.0 11.0 .... .... - //jumpeq i - if(regs.z) { - if(opcode & 0x2000) push(); - regs.pc = np(); - } - } - - else if((opcode & 0xdd00) == 0x1000) { - //00.1 00.0 .... .... - //jumpge i - if(regs.c) { - if(opcode & 0x2000) push(); - regs.pc = np(); - } - } - - else if((opcode & 0xdd00) == 0x1400) { - //00.1 01.0 .... .... - //jumpmi i - if(regs.n) { - if(opcode & 0x2000) push(); - regs.pc = np(); - } - } - - else if((opcode & 0xffff) == 0x1c00) { - //0001 1100 0000 0000 - //loop? - } - - else if((opcode & 0xfffe) == 0x2500) { - //0010 0101 0000 000. - //skiplt/skipge - if(regs.c == (opcode & 1)) regs.pc++; - } - - else if((opcode & 0xfffe) == 0x2600) { - //0010 0110 0000 000. - //skipne/skipeq - if(regs.z == (opcode & 1)) regs.pc++; - } - - else if((opcode & 0xfffe) == 0x2700) { - //0010 0111 0000 000. - //skipmi/skippl - if(regs.n == (opcode & 1)) regs.pc++; - } - - else if((opcode & 0xffff) == 0x3c00) { - //0011 1100 0000 0000 - //ret - pull(); - } - - else if((opcode & 0xffff) == 0x4000) { - //0100 0000 0000 0000 - //rdbus - regs.busdata = bus_read(regs.busaddr++); - } - - else if((opcode & 0xf800) == 0x4800) { - //0100 1... .... .... - //cmpr a<= 0; - } - - else if((opcode & 0xf800) == 0x5000) { - //0101 0... .... .... - //cmp a<= 0; - } - - else if((opcode & 0xfb00) == 0x5900) { - //0101 1.01 .... .... - //sxb - regs.a = (int8)ri(); - } - - else if((opcode & 0xfb00) == 0x5a00) { - //0101 1.10 .... .... - //sxw - regs.a = (int16)ri(); - } - - else if((opcode & 0xfb00) == 0x6000) { - //0110 0.00 .... .... - //ld a,ri - regs.a = ri(); - } - - else if((opcode & 0xfb00) == 0x6100) { - //0110 0.01 .... .... - //ld ?,ri - } - - else if((opcode & 0xfb00) == 0x6300) { - //0110 0.11 .... .... - //ld p,ri - regs.p = ri(); - } - - else if((opcode & 0xfb00) == 0x6800) { - //0110 1.00 .... .... - //rdraml - uint24 target = ri() + (opcode & 0x0400 ? regs.ramaddr : (uint24)0); - if(target < 0xc00) regs.ramdata = (regs.ramdata & 0xffff00) | (dataRAM[target] << 0); - } - - else if((opcode & 0xfb00) == 0x6900) { - //0110 1.01 .... .... - //rdramh - uint24 target = ri() + (opcode & 0x0400 ? regs.ramaddr : (uint24)0); - if(target < 0xc00) regs.ramdata = (regs.ramdata & 0xff00ff) | (dataRAM[target] << 8); - } - - else if((opcode & 0xfb00) == 0x6a00) { - //0110 1.10 .... .... - //rdramb - uint24 target = ri() + (opcode & 0x0400 ? regs.ramaddr : (uint24)0); - if(target < 0xc00) regs.ramdata = (regs.ramdata & 0x00ffff) | (dataRAM[target] << 16); - } - - else if((opcode & 0xffff) == 0x7000) { - //0111 0000 0000 0000 - //rdrom - regs.romdata = dataROM[regs.a & 0x3ff]; - } - - else if((opcode & 0xff00) == 0x7c00) { - //0111 1100 .... .... - //ld pl,i - regs.p = (regs.p & 0xff00) | ((opcode & 0xff) << 0); - } - - else if((opcode & 0xff00) == 0x7d00) { - //0111 1101 .... .... - //ld ph,i - regs.p = (regs.p & 0x00ff) | ((opcode & 0xff) << 8); - } - - else if((opcode & 0xf800) == 0x8000) { - //1000 0... .... .... - //add a< 0xffffff; - } - - else if((opcode & 0xf800) == 0x8800) { - //1000 1... .... .... - //subr a<= 0; - } - - else if((opcode & 0xf800) == 0x9000) { - //1001 0... .... .... - //sub a<= 0; - } - - else if((opcode & 0xfb00) == 0x9800) { - //1001 1.00 .... .... - //mul a,ri - int64 x = (int24)regs.a; - int64 y = (int24)ri(); - x *= y; - regs.accl = x >> 0ull; - regs.acch = x >> 24ull; - regs.n = regs.acch & 0x800000; - regs.z = x == 0; - } - - else if((opcode & 0xf800) == 0xa800) { - //1010 1... .... .... - //xor a<> ri(); - regs.n = regs.a & 0x800000; - regs.z = regs.a == 0; - } - - else if((opcode & 0xfb00) == 0xc800) { - //1100 1.00 .... .... - //asr a,ri - regs.a = (int24)regs.a >> ri(); - regs.n = regs.a & 0x800000; - regs.z = regs.a == 0; - } - - else if((opcode & 0xfb00) == 0xd000) { - //1101 0.00 .... .... - //ror a,ri - uint24 length = ri(); - regs.a = (regs.a >> length) | (regs.a << (24 - length)); - regs.n = regs.a & 0x800000; - regs.z = regs.a == 0; - } - - else if((opcode & 0xfb00) == 0xd800) { - //1101 1.00 .... .... - //shl a,ri - regs.a = regs.a << ri(); - regs.n = regs.a & 0x800000; - regs.z = regs.a == 0; - } - - else if((opcode & 0xff00) == 0xe000) { - //1110 0000 .... .... - //st r,a - reg_write(opcode & 0xff, regs.a); - } - - else if((opcode & 0xfb00) == 0xe800) { - //1110 1.00 .... .... - //wrraml - uint24 target = ri() + (opcode & 0x0400 ? regs.ramaddr : (uint24)0); - if(target < 0xc00) dataRAM[target] = regs.ramdata >> 0; - } - - else if((opcode & 0xfb00) == 0xe900) { - //1110 1.01 .... .... - //wrramh - uint24 target = ri() + (opcode & 0x0400 ? regs.ramaddr : (uint24)0); - if(target < 0xc00) dataRAM[target] = regs.ramdata >> 8; - } - - else if((opcode & 0xfb00) == 0xea00) { - //1110 1.10 .... .... - //wrramb - uint24 target = ri() + (opcode & 0x0400 ? regs.ramaddr : (uint24)0); - if(target < 0xc00) dataRAM[target] = regs.ramdata >> 16; - } - - else if((opcode & 0xff00) == 0xf000) { - //1111 0000 .... .... - //swap a,r - uint24 source = reg_read(opcode & 0xff); - uint24 target = regs.a; - regs.a = source; - reg_write(opcode & 0xff, target); - } - - else if((opcode & 0xffff) == 0xfc00) { - //1111 1100 0000 0000 - //halt - state = State::Idle; - } - - else { - print("Hitachi DSP: invalid opcode @ ", hex<4>(regs.pc - 1), " = ", hex<4>(opcode), "\n"); - state = State::Idle; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/hitachidsp/registers.cpp b/waterbox/libsnes/bsnes/snes/chip/hitachidsp/registers.cpp deleted file mode 100644 index 396bdf3e66..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/hitachidsp/registers.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#ifdef HITACHIDSP_CPP - -unsigned HitachiDSP::reg_read(unsigned n) const { - switch(n) { - case 0x00: return regs.a; - case 0x01: return regs.acch; - case 0x02: return regs.accl; - case 0x03: return regs.busdata; - case 0x08: return regs.romdata; - case 0x0c: return regs.ramdata; - case 0x13: return regs.busaddr; - case 0x1c: return regs.ramaddr; - case 0x50: return 0x000000; - case 0x51: return 0xffffff; - case 0x52: return 0x00ff00; - case 0x53: return 0xff0000; - case 0x54: return 0x00ffff; - case 0x55: return 0xffff00; - case 0x56: return 0x800000; - case 0x57: return 0x7fffff; - case 0x58: return 0x008000; - case 0x59: return 0x007fff; - case 0x5a: return 0xff7fff; - case 0x5b: return 0xffff7f; - case 0x5c: return 0x010000; - case 0x5d: return 0xfeffff; - case 0x5e: return 0x000100; - case 0x5f: return 0x00feff; - case 0x60: return regs.gpr[ 0]; - case 0x61: return regs.gpr[ 1]; - case 0x62: return regs.gpr[ 2]; - case 0x63: return regs.gpr[ 3]; - case 0x64: return regs.gpr[ 4]; - case 0x65: return regs.gpr[ 5]; - case 0x66: return regs.gpr[ 6]; - case 0x67: return regs.gpr[ 7]; - case 0x68: return regs.gpr[ 8]; - case 0x69: return regs.gpr[ 9]; - case 0x6a: return regs.gpr[10]; - case 0x6b: return regs.gpr[11]; - case 0x6c: return regs.gpr[12]; - case 0x6d: return regs.gpr[13]; - case 0x6e: return regs.gpr[14]; - case 0x6f: return regs.gpr[15]; - } - return 0x000000; -} - -void HitachiDSP::reg_write(unsigned n, unsigned data) { - switch(n) { - case 0x00: regs.a = data; return; - case 0x01: regs.acch = data; return; - case 0x02: regs.accl = data; return; - case 0x03: regs.busdata = data; return; - case 0x08: regs.romdata = data; return; - case 0x0c: regs.ramdata = data; return; - case 0x13: regs.busaddr = data; return; - case 0x1c: regs.ramaddr = data; return; - case 0x60: regs.gpr[ 0] = data; return; - case 0x61: regs.gpr[ 1] = data; return; - case 0x62: regs.gpr[ 2] = data; return; - case 0x63: regs.gpr[ 3] = data; return; - case 0x64: regs.gpr[ 4] = data; return; - case 0x65: regs.gpr[ 5] = data; return; - case 0x66: regs.gpr[ 6] = data; return; - case 0x67: regs.gpr[ 7] = data; return; - case 0x68: regs.gpr[ 8] = data; return; - case 0x69: regs.gpr[ 9] = data; return; - case 0x6a: regs.gpr[10] = data; return; - case 0x6b: regs.gpr[11] = data; return; - case 0x6c: regs.gpr[12] = data; return; - case 0x6d: regs.gpr[13] = data; return; - case 0x6e: regs.gpr[14] = data; return; - case 0x6f: regs.gpr[15] = data; return; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/hitachidsp/registers.hpp b/waterbox/libsnes/bsnes/snes/chip/hitachidsp/registers.hpp deleted file mode 100644 index 73d2370f8c..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/hitachidsp/registers.hpp +++ /dev/null @@ -1,31 +0,0 @@ -struct Registers { - uint24 pc; - uint16 p; - bool n; - bool z; - bool c; - - uint24 a; - uint24 acch; - uint24 accl; - uint24 busdata; - uint24 romdata; - uint24 ramdata; - uint24 busaddr; - uint24 ramaddr; - uint24 gpr[16]; - - //MMIO - uint24 dma_source; //$1f40-$1f42 - uint24 dma_length; //$1f43-$1f44 - uint24 dma_target; //$1f45-$1f47 - uint8 r1f48; //$1f48 - uint24 program_offset; //$1f49-$1f4b - uint8 r1f4c; //$1f4c - uint16 page_number; //$1f4d-$1f4e - uint8 program_counter; //$1f4f - uint8 r1f50; //$1f50 - uint8 r1f51; //$1f51 - uint8 r1f52; //$1f52 - uint8 vector[32]; //$1f60-$1f7f -} regs; diff --git a/waterbox/libsnes/bsnes/snes/chip/icd2/icd2.cpp b/waterbox/libsnes/bsnes/snes/chip/icd2/icd2.cpp deleted file mode 100644 index bd2828e5dd..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/icd2/icd2.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#if defined(GAMEBOY) - -#include - -#define ICD2_CPP -namespace SNES { - -#include "interface/interface.cpp" -#include "mmio/mmio.cpp" -ICD2 icd2; - -void ICD2::Enter() { icd2.enter(); } - -void ICD2::enter() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - GameBoy::system.runtosave(); - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - if(r6003 & 0x80) { - GameBoy::system.run(); - step(GameBoy::system.clocks_executed); - GameBoy::system.clocks_executed = 0; - } else { //DMG halted - audio.coprocessor_sample(0x0000, 0x0000); - step(1); - } - synchronize_cpu(); - } -} - -void ICD2::init() { -} - -void ICD2::load() { -} - -void ICD2::unload() { -} - -void ICD2::power() { - audio.coprocessor_enable(true); - audio.coprocessor_frequency(4 * 1024 * 1024); -} - -void ICD2::reset() { - create(ICD2::Enter, cpu.frequency / 5, 16384); - - r6000_ly = 0x00; - r6000_row = 0x00; - r6003 = 0x00; - r6004 = 0xff; - r6005 = 0xff; - r6006 = 0xff; - r6007 = 0xff; - for(unsigned n = 0; n < 16; n++) r7000[n] = 0x00; - r7800 = 0x0000; - mlt_req = 0; - - for(auto &n : lcd.buffer) n = 0; - for(auto &n : lcd.output) n = 0; - lcd.row = 0; - - packetsize = 0; - joyp_id = 3; - joyp15lock = 0; - joyp14lock = 0; - pulselock = true; - - GameBoy::system.init(); - GameBoy::system.power(); -} - -ICD2::ICD2() -{ - GameBoy::interface = this; -} - -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/icd2/icd2.hpp b/waterbox/libsnes/bsnes/snes/chip/icd2/icd2.hpp deleted file mode 100644 index 5c741a1e25..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/icd2/icd2.hpp +++ /dev/null @@ -1,24 +0,0 @@ -class ICD2 : public GameBoy::Interface, public Coprocessor { -public: - unsigned revision; - - static void Enter(); - void enter(); - - void init(); - void load(); - void unload(); - void power(); - void reset(); - - uint8 read(unsigned addr); - void write(unsigned addr, uint8 data); - - ICD2(); - -private: - #include "interface/interface.hpp" - #include "mmio/mmio.hpp" -}; - -extern ICD2 icd2; diff --git a/waterbox/libsnes/bsnes/snes/chip/icd2/interface/interface.cpp b/waterbox/libsnes/bsnes/snes/chip/icd2/interface/interface.cpp deleted file mode 100644 index 8f2a16f42b..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/icd2/interface/interface.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#ifdef ICD2_CPP - -//called on rendered lines 0-143 (not on Vblank lines 144-153) -void ICD2::lcdScanline() { - if((GameBoy::lcd.status.ly & 7) == 0) { - lcd.row = (lcd.row + 1) & 3; - } - - unsigned offset = (lcd.row * 160 * 8) + ((GameBoy::lcd.status.ly & 7) * 160); - memcpy(lcd.buffer + offset, GameBoy::lcd.screen + GameBoy::lcd.status.ly * 160, 160 * sizeof(uint16)); -} - -void ICD2::joypWrite(bool p15, bool p14) { - //joypad handling - if(p15 == 1 && p14 == 1) { - if(joyp15lock == 0 && joyp14lock == 0) { - joyp15lock = 1; - joyp14lock = 1; - joyp_id = (joyp_id + 1) & 3; - } - } - - if(p15 == 0 && p14 == 1) joyp15lock = 0; - if(p15 == 1 && p14 == 0) joyp14lock = 0; - - //packet handling - if(p15 == 0 && p14 == 0) { //pulse - pulselock = false; - packetoffset = 0; - bitoffset = 0; - strobelock = true; - packetlock = false; - return; - } - - if(pulselock) return; - - if(p15 == 1 && p14 == 1) { - strobelock = false; - return; - } - - if(strobelock) { - if(p15 == 1 || p14 == 1) { //malformed packet - packetlock = false; - pulselock = true; - bitoffset = 0; - packetoffset = 0; - } else { - return; - } - } - - //p15:1, p14:0 = 0 - //p15:0, p14:1 = 1 - bool bit = (p15 == 0); - strobelock = true; - - if(packetlock) { - if(p15 == 1 && p14 == 0) { - if((joyp_packet[0] >> 3) == 0x11) { - mlt_req = joyp_packet[1] & 3; - if(mlt_req == 2) mlt_req = 3; - joyp_id = 0; - } - - if(packetsize < 64) packet[packetsize++] = joyp_packet; - packetlock = false; - pulselock = true; - } - return; - } - - bitdata = (bit << 7) | (bitdata >> 1); - if(++bitoffset < 8) return; - - bitoffset = 0; - joyp_packet[packetoffset] = bitdata; - if(++packetoffset < 16) return; - packetlock = true; -} - -void ICD2::videoRefresh(const uint16_t *data) { -} - -void ICD2::audioSample(int16_t center, int16_t left, int16_t right) { - audio.coprocessor_sample(left, right); -} - -bool ICD2::inputPoll(unsigned id) { - GameBoy::cpu.status.mlt_req = joyp_id & mlt_req; - - unsigned data = 0x00; - switch(joyp_id & mlt_req) { - case 0: data = ~r6004; break; - case 1: data = ~r6005; break; - case 2: data = ~r6006; break; - case 3: data = ~r6007; break; - } - - switch((GameBoy::Input)id) { - case GameBoy::Input::Start: return data & 0x80; - case GameBoy::Input::Select: return data & 0x40; - case GameBoy::Input::B: return data & 0x20; - case GameBoy::Input::A: return data & 0x10; - case GameBoy::Input::Down: return data & 0x08; - case GameBoy::Input::Up: return data & 0x04; - case GameBoy::Input::Left: return data & 0x02; - case GameBoy::Input::Right: return data & 0x01; - } - - return 0; -} - -void* ICD2::allocSharedMemory(const char* memtype, size_t amt, int initialByte) { return SNES::interface()->allocSharedMemory(memtype, amt, initialByte); } -void ICD2::freeSharedMemory(void* ptr) { SNES::interface()->freeSharedMemory(ptr); } - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/icd2/interface/interface.hpp b/waterbox/libsnes/bsnes/snes/chip/icd2/interface/interface.hpp deleted file mode 100644 index c6202492c8..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/icd2/interface/interface.hpp +++ /dev/null @@ -1,25 +0,0 @@ -void lcdScanline(); -void joypWrite(bool p15, bool p14); -void videoRefresh(const uint16_t *data); -void audioSample(int16_t center, int16_t left, int16_t right); -bool inputPoll(unsigned id); - -void* allocSharedMemory(const char* memtype, size_t amt, int initialByte = -1); -void freeSharedMemory(void* ptr); - -struct Packet { - uint8 data[16]; - uint8& operator[](unsigned addr) { return data[addr & 15]; } -}; -Packet packet[64]; -unsigned packetsize; - -unsigned joyp_id; -bool joyp15lock; -bool joyp14lock; -bool pulselock; -bool strobelock; -bool packetlock; -Packet joyp_packet; -uint8 packetoffset; -uint8 bitdata, bitoffset; diff --git a/waterbox/libsnes/bsnes/snes/chip/icd2/mmio/mmio.cpp b/waterbox/libsnes/bsnes/snes/chip/icd2/mmio/mmio.cpp deleted file mode 100644 index 0835c0274b..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/icd2/mmio/mmio.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#ifdef ICD2_CPP - -//convert linear pixel data { 0x00, 0x55, 0xaa, 0xff } to 2bpp planar tiledata -void ICD2::render(const uint16 *source) { - memset(lcd.output, 0x00, 320 * sizeof(uint16)); - - for(unsigned y = 0; y < 8; y++) { - for(unsigned x = 0; x < 160; x++) { - unsigned pixel = *source++; - unsigned addr = y * 2 + (x / 8 * 16); - lcd.output[addr + 0] |= ((pixel & 1) >> 0) << (7 - (x & 7)); - lcd.output[addr + 1] |= ((pixel & 2) >> 1) << (7 - (x & 7)); - } - } -} - -uint8 ICD2::read(unsigned addr) { - addr &= 0xffff; - - //LY counter - if(addr == 0x6000) { - r6000_ly = GameBoy::lcd.status.ly; - r6000_row = lcd.row; - return r6000_ly; - } - - //command ready port - if(addr == 0x6002) { - bool data = packetsize > 0; - if(data) { - for(unsigned i = 0; i < 16; i++) r7000[i] = packet[0][i]; - packetsize--; - for(unsigned i = 0; i < packetsize; i++) packet[i] = packet[i + 1]; - } - return data; - } - - //ICD2 revision - if(addr == 0x600f) { - return 0x21; - } - - //command port - if((addr & 0xfff0) == 0x7000) { - return r7000[addr & 15]; - } - - //VRAM port - if(addr == 0x7800) { - uint8 data = lcd.output[r7800]; - r7800 = (r7800 + 1) % 320; - return data; - } - - return 0x00; -} - -void ICD2::write(unsigned addr, uint8 data) { - addr &= 0xffff; - - //VRAM port - if(addr == 0x6001) { - r6001 = data; - r7800 = 0; - - unsigned offset = (r6000_row - (4 - (r6001 - (r6000_ly & 3)))) & 3; - render(lcd.buffer + offset * 160 * 8); - - return; - } - - //control port - //d7: 0 = halt, 1 = reset - //d5,d4: 0 = 1-player, 1 = 2-player, 2 = 4-player, 3 = ??? - //d1,d0: 0 = frequency divider (clock rate adjust) - if(addr == 0x6003) { - if((r6003 & 0x80) == 0x00 && (data & 0x80) == 0x80) { - reset(); - } - switch(data & 3) { - case 0: frequency = cpu.frequency / 4; break; //fast (glitchy, even on real hardware) - case 1: frequency = cpu.frequency / 5; break; //normal - case 2: frequency = cpu.frequency / 7; break; //slow - case 3: frequency = cpu.frequency / 9; break; //very slow - } - r6003 = data; - return; - } - - if(addr == 0x6004) { r6004 = data; return; } //joypad 1 - if(addr == 0x6005) { r6005 = data; return; } //joypad 2 - if(addr == 0x6006) { r6006 = data; return; } //joypad 3 - if(addr == 0x6007) { r6007 = data; return; } //joypad 4 -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/icd2/mmio/mmio.hpp b/waterbox/libsnes/bsnes/snes/chip/icd2/mmio/mmio.hpp deleted file mode 100644 index fdd029def7..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/icd2/mmio/mmio.hpp +++ /dev/null @@ -1,19 +0,0 @@ -void render(const uint16 *source); - -uint8 r6000_ly; //SGB BIOS' cache of LY -uint8 r6000_row; //SGB BIOS' cache of ROW -uint8 r6001; //VRAM conversion -uint8 r6003; //control port -uint8 r6004; //joypad 1 -uint8 r6005; //joypad 2 -uint8 r6006; //joypad 3 -uint8 r6007; //joypad 4 -uint8 r7000[16]; //JOYP packet data -unsigned r7800; //VRAM offset -uint8 mlt_req; //number of active joypads - -struct LCD { - uint16 buffer[4 * 160 * 8]; //four tile rows of linear video data - uint16 output[320]; //one tile row of 2bpp video data - unsigned row; //active ICD2 rendering tile row -} lcd; diff --git a/waterbox/libsnes/bsnes/snes/chip/link/link.cpp b/waterbox/libsnes/bsnes/snes/chip/link/link.cpp deleted file mode 100644 index da50e519c1..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/link/link.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include - -#define LINK_HPP -namespace SNES { - -Link link; - -void Link::Enter() { link.enter(); } - -void Link::enter() { - while(true) { - cpu.synchronize_coprocessors(); - unsigned clocks = 1; - if(link_run) clocks = link_run(); - step(clocks); - synchronize_cpu(); - } -} - -void Link::init() { -} - -void Link::load() { - if(opened()) close(); - string basename = interface()->path(Cartridge::Slot::Base, ""); - string name = program != "" ? program : notdir(basename); - string path = dir(basename); - if(open(name, path)) { - link_power = sym("link_power"); - link_reset = sym("link_reset"); - link_run = sym("link_run" ); - link_read = sym("link_read" ); - link_write = sym("link_write"); - } -} - -void Link::unload() { - if(opened()) close(); -} - -void Link::power() { - if(link_power) link_power(); -} - -void Link::reset() { - if(link_reset) link_reset(); - create(Link::Enter, frequency, 8192); -} - -uint8 Link::read(unsigned addr) { - if(link_read) return link_read(addr); - return cpu.regs.mdr; -} - -void Link::write(unsigned addr, uint8 data) { - if(link_write) return link_write(addr, data); -} - -} diff --git a/waterbox/libsnes/bsnes/snes/chip/link/link.hpp b/waterbox/libsnes/bsnes/snes/chip/link/link.hpp deleted file mode 100644 index 1898fa029b..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/link/link.hpp +++ /dev/null @@ -1,24 +0,0 @@ -class Link : public Coprocessor, public library { -public: - string program; - - static void Enter(); - void enter(); - void init(); - void load(); - void unload(); - void power(); - void reset(); - - uint8 read(unsigned addr); - void write(unsigned addr, uint8 data); - -private: - function link_power; - function link_reset; - function link_run; - function link_read; - function link_write; -}; - -extern Link link; diff --git a/waterbox/libsnes/bsnes/snes/chip/msu1/msu1.cpp b/waterbox/libsnes/bsnes/snes/chip/msu1/msu1.cpp deleted file mode 100644 index bf44fddb12..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/msu1/msu1.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include - -#define MSU1_CPP -namespace SNES { - -MSU1 msu1; - -void MSU1::Enter() { msu1.enter(); } - -void MSU1::enter() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - int16 left = 0, right = 0; - - if(mmio.audio_play) { - if(audiofile.open()) { - if(audiofile.end()) { - if(!mmio.audio_repeat) { - mmio.audio_play = false; - audiofile.seek(mmio.audio_offset = 8); - } else { - audiofile.seek(mmio.audio_offset = mmio.audio_loop_offset); - } - } else { - mmio.audio_offset += 4; - left = audiofile.readl(2); - right = audiofile.readl(2); - } - } else { - mmio.audio_play = false; - } - } - - signed lchannel = (double)left * (double)mmio.audio_volume / 255.0; - signed rchannel = (double)right * (double)mmio.audio_volume / 255.0; - left = sclamp<16>(lchannel); - right = sclamp<16>(rchannel); - - audio.coprocessor_sample(left, right); - step(1); - synchronize_cpu(); - } -} - -void MSU1::init() { -} - -void MSU1::load() { - if(datafile.open()) datafile.close(); - datafile.open(interface()->path(Cartridge::Slot::Base, "msu1.rom"), file::mode::read); -} - -void MSU1::unload() { - if(datafile.open()) datafile.close(); -} - -void MSU1::power() { - audio.coprocessor_enable(true); - audio.coprocessor_frequency(44100.0); -} - -void MSU1::reset() { - create(MSU1::Enter, 44100, 16384); - - mmio.data_offset = 0; - mmio.audio_offset = 0; - mmio.audio_track = 0; - mmio.audio_volume = 255; - mmio.data_busy = true; - mmio.audio_busy = true; - mmio.audio_repeat = false; - mmio.audio_play = false; -} - -uint8 MSU1::mmio_read(unsigned addr) { - switch(addr & 7) { - case 0: - return (mmio.data_busy << 7) - | (mmio.audio_busy << 6) - | (mmio.audio_repeat << 5) - | (mmio.audio_play << 4) - | (Revision << 0); - case 1: - if(mmio.data_busy) return 0x00; - mmio.data_offset++; - if(datafile.open()) return datafile.read(); - return 0x00; - case 2: return 'S'; - case 3: return '-'; - case 4: return 'M'; - case 5: return 'S'; - case 6: return 'U'; - case 7: return '0' + Revision; - } - throw; -} - -void MSU1::mmio_write(unsigned addr, uint8 data) { - switch(addr & 7) { - case 0: mmio.data_offset = (mmio.data_offset & 0xffffff00) | (data << 0); break; - case 1: mmio.data_offset = (mmio.data_offset & 0xffff00ff) | (data << 8); break; - case 2: mmio.data_offset = (mmio.data_offset & 0xff00ffff) | (data << 16); break; - case 3: mmio.data_offset = (mmio.data_offset & 0x00ffffff) | (data << 24); - if(datafile.open()) datafile.seek(mmio.data_offset); - mmio.data_busy = false; - break; - case 4: mmio.audio_track = (mmio.audio_track & 0xff00) | (data << 0); - case 5: mmio.audio_track = (mmio.audio_track & 0x00ff) | (data << 8); - if(audiofile.open()) audiofile.close(); - if(audiofile.open(interface()->path(Cartridge::Slot::Base, { "track-", (unsigned)mmio.audio_track, ".pcm" }), file::mode::read)) { - uint32 header = audiofile.readm(4); - if(header != 0x4d535531) { //verify 'MSU1' header - audiofile.close(); - } else { - mmio.audio_offset = 8; - mmio.audio_loop_offset = 8 + audiofile.readl(4) * 4; - } - } - mmio.audio_busy = false; - mmio.audio_repeat = false; - mmio.audio_play = false; - break; - case 6: - mmio.audio_volume = data; - break; - case 7: - mmio.audio_repeat = data & 2; - mmio.audio_play = data & 1; - break; - } -} - -} diff --git a/waterbox/libsnes/bsnes/snes/chip/msu1/msu1.hpp b/waterbox/libsnes/bsnes/snes/chip/msu1/msu1.hpp deleted file mode 100644 index a109c339af..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/msu1/msu1.hpp +++ /dev/null @@ -1,41 +0,0 @@ -class MSU1 : public Coprocessor { -public: - static void Enter(); - void enter(); - void init(); - void load(); - void unload(); - void power(); - void reset(); - - uint8 mmio_read(unsigned addr); - void mmio_write(unsigned addr, uint8 data); - -private: - file datafile; - file audiofile; - - enum Flag { - DataBusy = 0x80, - AudioBusy = 0x40, - AudioRepeating = 0x20, - AudioPlaying = 0x10, - Revision = 0x01, - }; - - struct MMIO { - uint32 data_offset; - uint32 audio_offset; - uint32 audio_loop_offset; - - uint16 audio_track; - uint8 audio_volume; - - bool data_busy; - bool audio_busy; - bool audio_repeat; - bool audio_play; - } mmio; -}; - -extern MSU1 msu1; diff --git a/waterbox/libsnes/bsnes/snes/chip/necdsp/disassembler.cpp b/waterbox/libsnes/bsnes/snes/chip/necdsp/disassembler.cpp deleted file mode 100644 index 23a5bb9596..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/necdsp/disassembler.cpp +++ /dev/null @@ -1,196 +0,0 @@ -#ifdef NECDSP_CPP - -string NECDSP::disassemble(uint14 ip) { - string output = { hex<4>(ip), " " }; - uint24 opcode = programROM[ip]; - uint2 type = opcode >> 22; - - if(type == 0 || type == 1) { //OP,RT - uint2 pselect = opcode >> 20; - uint4 alu = opcode >> 16; - uint1 asl = opcode >> 15; - uint2 dpl = opcode >> 13; - uint4 dphm = opcode >> 9; - uint1 rpdcr = opcode >> 8; - uint4 src = opcode >> 4; - uint4 dst = opcode >> 0; - - switch(alu) { - case 0: output.append("nop "); break; - case 1: output.append("or "); break; - case 2: output.append("and "); break; - case 3: output.append("xor "); break; - case 4: output.append("sub "); break; - case 5: output.append("add "); break; - case 6: output.append("sbb "); break; - case 7: output.append("adc "); break; - case 8: output.append("dec "); break; - case 9: output.append("inc "); break; - case 10: output.append("cmp "); break; - case 11: output.append("shr1 "); break; - case 12: output.append("shl1 "); break; - case 13: output.append("shl2 "); break; - case 14: output.append("shl4 "); break; - case 15: output.append("xchg "); break; - } - - if(alu < 8) { - switch(pselect) { - case 0: output.append("ram,"); break; - case 1: output.append("idb,"); break; - case 2: output.append("m," ); break; - case 3: output.append("n," ); break; - } - } - - switch(asl) { - case 0: output.append("a"); break; - case 1: output.append("b"); break; - } - - output.append("\n mov "); - - switch(src) { - case 0: output.append("trb," ); break; - case 1: output.append("a," ); break; - case 2: output.append("b," ); break; - case 3: output.append("tr," ); break; - case 4: output.append("dp," ); break; - case 5: output.append("rp," ); break; - case 6: output.append("ro," ); break; - case 7: output.append("sgn," ); break; - case 8: output.append("dr," ); break; - case 9: output.append("drnf,"); break; - case 10: output.append("sr," ); break; - case 11: output.append("sim," ); break; - case 12: output.append("sil," ); break; - case 13: output.append("k," ); break; - case 14: output.append("l," ); break; - case 15: output.append("mem," ); break; - } - - switch(dst) { - case 0: output.append("non"); break; - case 1: output.append("a" ); break; - case 2: output.append("b" ); break; - case 3: output.append("tr" ); break; - case 4: output.append("dp" ); break; - case 5: output.append("rp" ); break; - case 6: output.append("dr" ); break; - case 7: output.append("sr" ); break; - case 8: output.append("sol"); break; - case 9: output.append("som"); break; - case 10: output.append("k" ); break; - case 11: output.append("klr"); break; - case 12: output.append("klm"); break; - case 13: output.append("l" ); break; - case 14: output.append("trb"); break; - case 15: output.append("mem"); break; - } - - if(dpl) { - switch(dpl) { - case 0: output.append("\n dpnop"); break; - case 1: output.append("\n dpinc"); break; - case 2: output.append("\n dpdec"); break; - case 3: output.append("\n dpclr"); break; - } - } - - if(dphm) { - output.append("\n m", hex<1>(dphm)); - } - - if(rpdcr == 1) { - output.append("\n rpdec"); - } - - if(type == 1) { - output.append("\n ret"); - } - } - - if(type == 2) { //JP - uint9 brch = opcode >> 13; - uint11 na = opcode >> 2; - uint8 bank = opcode >> 0; - - uint14 jp = (regs.pc & 0x2000) | (bank << 11) | (na << 0); - - switch(brch) { - case 0x000: output.append("jmpso "); jp = 0; break; - case 0x080: output.append("jnca "); break; - case 0x082: output.append("jca "); break; - case 0x084: output.append("jncb "); break; - case 0x086: output.append("jcb "); break; - case 0x088: output.append("jnza "); break; - case 0x08a: output.append("jza "); break; - case 0x08c: output.append("jnzb "); break; - case 0x08e: output.append("jzb "); break; - case 0x090: output.append("jnova0 "); break; - case 0x092: output.append("jova0 "); break; - case 0x094: output.append("jnovb0 "); break; - case 0x096: output.append("jovb0 "); break; - case 0x098: output.append("jnova1 "); break; - case 0x09a: output.append("jova1 "); break; - case 0x09c: output.append("jnovb1 "); break; - case 0x09e: output.append("jovb1 "); break; - case 0x0a0: output.append("jnsa0 "); break; - case 0x0a2: output.append("jsa0 "); break; - case 0x0a4: output.append("jnsb0 "); break; - case 0x0a6: output.append("jsb0 "); break; - case 0x0a8: output.append("jnsa1 "); break; - case 0x0aa: output.append("jsa1 "); break; - case 0x0ac: output.append("jnsb1 "); break; - case 0x0ae: output.append("jsb1 "); break; - case 0x0b0: output.append("jdpl0 "); break; - case 0x0b1: output.append("jdpln0 "); break; - case 0x0b2: output.append("jdplf "); break; - case 0x0b3: output.append("jdplnf "); break; - case 0x0b4: output.append("jnsiak "); break; - case 0x0b6: output.append("jsiak "); break; - case 0x0b8: output.append("jnsoak "); break; - case 0x0ba: output.append("jsoak "); break; - case 0x0bc: output.append("jnrqm "); break; - case 0x0be: output.append("jrqm "); break; - case 0x100: output.append("ljmp "); jp &= ~0x2000; break; - case 0x101: output.append("hjmp "); jp |= 0x2000; break; - case 0x140: output.append("lcall "); jp &= ~0x2000; break; - case 0x141: output.append("hcall "); jp |= 0x2000; break; - default: output.append("?????? "); break; - } - - output.append("$", hex<4>(jp)); - } - - if(type == 3) { //LD - output.append("ld "); - uint16 id = opcode >> 6; - uint4 dst = opcode >> 0; - - output.append("$", hex<4>(id), ","); - - switch(dst) { - case 0: output.append("non"); break; - case 1: output.append("a" ); break; - case 2: output.append("b" ); break; - case 3: output.append("tr" ); break; - case 4: output.append("dp" ); break; - case 5: output.append("rp" ); break; - case 6: output.append("dr" ); break; - case 7: output.append("sr" ); break; - case 8: output.append("sol"); break; - case 9: output.append("som"); break; - case 10: output.append("k" ); break; - case 11: output.append("klr"); break; - case 12: output.append("klm"); break; - case 13: output.append("l" ); break; - case 14: output.append("trb"); break; - case 15: output.append("mem"); break; - } - } - - return output; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/necdsp/memory.cpp b/waterbox/libsnes/bsnes/snes/chip/necdsp/memory.cpp deleted file mode 100644 index 0b11d594cb..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/necdsp/memory.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#ifdef NECDSP_CPP - -uint8 NECDSP::sr_read(unsigned) { - cpu.synchronize_coprocessors(); - return regs.sr >> 8; -} - -void NECDSP::sr_write(unsigned, uint8 data) { - cpu.synchronize_coprocessors(); -} - -uint8 NECDSP::dr_read(unsigned) { - cpu.synchronize_coprocessors(); - if(regs.sr.drc == 0) { - //16-bit - if(regs.sr.drs == 0) { - regs.sr.drs = 1; - return regs.dr >> 0; - } else { - regs.sr.rqm = 0; - regs.sr.drs = 0; - return regs.dr >> 8; - } - } else { - //8-bit - regs.sr.rqm = 0; - return regs.dr >> 0; - } -} - -void NECDSP::dr_write(unsigned, uint8 data) { - cpu.synchronize_coprocessors(); - if(regs.sr.drc == 0) { - //16-bit - if(regs.sr.drs == 0) { - regs.sr.drs = 1; - regs.dr = (regs.dr & 0xff00) | (data << 0); - } else { - regs.sr.rqm = 0; - regs.sr.drs = 0; - regs.dr = (data << 8) | (regs.dr & 0x00ff); - } - } else { - //8-bit - regs.sr.rqm = 0; - regs.dr = (regs.dr & 0xff00) | (data << 0); - } -} - -uint8 NECDSP::dp_read(unsigned addr) { - cpu.synchronize_coprocessors(); - bool hi = addr & 1; - addr = (addr >> 1) & 2047; - - if(hi == false) { - return dataRAM[addr] >> 0; - } else { - return dataRAM[addr] >> 8; - } -} - -void NECDSP::dp_write(unsigned addr, uint8 data) { - cpu.synchronize_coprocessors(); - bool hi = addr & 1; - addr = (addr >> 1) & 2047; - - if(hi == false) { - dataRAM[addr] = (dataRAM[addr] & 0xff00) | (data << 0); - } else { - dataRAM[addr] = (dataRAM[addr] & 0x00ff) | (data << 8); - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/necdsp/necdsp.cpp b/waterbox/libsnes/bsnes/snes/chip/necdsp/necdsp.cpp deleted file mode 100644 index 37b49e4106..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/necdsp/necdsp.cpp +++ /dev/null @@ -1,307 +0,0 @@ -#include - -#define NECDSP_CPP -namespace SNES { - -#include "memory.cpp" -#include "disassembler.cpp" -NECDSP necdsp; - -//zero 01-sep-2014 - dont clobber these when reconstructing! -unsigned NECDSP::frequency; -uint24 NECDSP::programROM[16384]; -uint16 NECDSP::dataROM[2048]; -unsigned NECDSP::programROMSize; -unsigned NECDSP::dataROMSize; - -void NECDSP::Enter() { necdsp.enter(); } - -void NECDSP::enter() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - uint24 opcode = programROM[regs.pc++]; - switch(opcode >> 22) { - case 0: exec_op(opcode); break; - case 1: exec_rt(opcode); break; - case 2: exec_jp(opcode); break; - case 3: exec_ld(opcode); break; - } - - int32 result = (int32)regs.k * regs.l; //sign + 30-bit result - regs.m = result >> 15; //store sign + top 15-bits - regs.n = result << 1; //store low 15-bits + zero - - step(1); - synchronize_cpu(); - } -} - -void NECDSP::exec_op(uint24 opcode) { - uint2 pselect = opcode >> 20; //P select - uint4 alu = opcode >> 16; //ALU operation mode - uint1 asl = opcode >> 15; //accumulator select - uint2 dpl = opcode >> 13; //DP low modify - uint4 dphm = opcode >> 9; //DP high XOR modify - uint1 rpdcr = opcode >> 8; //RP decrement - uint4 src = opcode >> 4; //move source - uint4 dst = opcode >> 0; //move destination - - uint16 idb; - switch(src) { - case 0: idb = regs.trb; break; - case 1: idb = regs.a; break; - case 2: idb = regs.b; break; - case 3: idb = regs.tr; break; - case 4: idb = regs.dp; break; - case 5: idb = regs.rp; break; - case 6: idb = dataROM[regs.rp]; break; - case 7: idb = 0x8000 - regs.flaga.s1; break; - case 8: idb = regs.dr; regs.sr.rqm = 1; break; - case 9: idb = regs.dr; break; - case 10: idb = regs.sr; break; - case 11: idb = regs.si; break; //MSB - case 12: idb = regs.si; break; //LSB - case 13: idb = regs.k; break; - case 14: idb = regs.l; break; - case 15: idb = dataRAM[regs.dp]; break; - } - - if(alu) { - uint16 p, q, r; - Flag flag; - bool c; - - switch(pselect) { - case 0: p = dataRAM[regs.dp]; break; - case 1: p = idb; break; - case 2: p = regs.m; break; - case 3: p = regs.n; break; - } - - switch(asl) { - case 0: q = regs.a; flag = regs.flaga; c = regs.flagb.c; break; - case 1: q = regs.b; flag = regs.flagb; c = regs.flaga.c; break; - } - - switch(alu) { - case 1: r = q | p; break; //OR - case 2: r = q & p; break; //AND - case 3: r = q ^ p; break; //XOR - case 4: r = q - p; break; //SUB - case 5: r = q + p; break; //ADD - case 6: r = q - p - c; break; //SBB - case 7: r = q + p + c; break; //ADC - case 8: r = q - 1; p = 1; break; //DEC - case 9: r = q + 1; p = 1; break; //INC - case 10: r = ~q; break; //CMP - case 11: r = (q >> 1) | (q & 0x8000); break; //SHR1 (ASR) - case 12: r = (q << 1) | c; break; //SHL1 (ROL) - case 13: r = (q << 2) | 3; break; //SHL2 - case 14: r = (q << 4) | 15; break; //SHL4 - case 15: r = (q << 8) | (q >> 8); break; //XCHG - } - - flag.s0 = (r & 0x8000); - flag.z = (r == 0); - - switch(alu) { - case 1: case 2: case 3: case 10: case 13: case 14: case 15: { - flag.c = 0; - flag.ov0 = 0; - flag.ov1 = 0; - break; - } - case 4: case 5: case 6: case 7: case 8: case 9: { - if(alu & 1) { - //addition - flag.ov0 = (q ^ r) & ~(q ^ p) & 0x8000; - flag.c = (r < q); - } else { - //subtraction - flag.ov0 = (q ^ r) & (q ^ p) & 0x8000; - flag.c = (r > q); - } - if(flag.ov0) { - flag.s1 = flag.ov1 ^ !(r & 0x8000); - flag.ov1 = !flag.ov1; - } - break; - } - case 11: { - flag.c = q & 1; - flag.ov0 = 0; - flag.ov1 = 0; - break; - } - case 12: { - flag.c = q >> 15; - flag.ov0 = 0; - flag.ov1 = 0; - break; - } - } - - switch(asl) { - case 0: regs.a = r; regs.flaga = flag; break; - case 1: regs.b = r; regs.flagb = flag; break; - } - } - - exec_ld((idb << 6) + dst); - - switch(dpl) { - case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC - case 2: regs.dp = (regs.dp & 0xf0) + ((regs.dp - 1) & 0x0f); break; //DPDEC - case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR - } - - regs.dp ^= dphm << 4; - - if(rpdcr) regs.rp--; -} - -void NECDSP::exec_rt(uint24 opcode) { - exec_op(opcode); - regs.pc = regs.stack[--regs.sp]; -} - -void NECDSP::exec_jp(uint24 opcode) { - uint9 brch = opcode >> 13; //branch - uint11 na = opcode >> 2; //next address - uint2 bank = opcode >> 0; //bank address - - uint14 jp = (regs.pc & 0x2000) | (bank << 11) | (na << 0); - - switch(brch) { - case 0x000: regs.pc = regs.so; return; //JMPSO - - case 0x080: if(regs.flaga.c == 0) regs.pc = jp; return; //JNCA - case 0x082: if(regs.flaga.c == 1) regs.pc = jp; return; //JCA - case 0x084: if(regs.flagb.c == 0) regs.pc = jp; return; //JNCB - case 0x086: if(regs.flagb.c == 1) regs.pc = jp; return; //JCB - - case 0x088: if(regs.flaga.z == 0) regs.pc = jp; return; //JNZA - case 0x08a: if(regs.flaga.z == 1) regs.pc = jp; return; //JZA - case 0x08c: if(regs.flagb.z == 0) regs.pc = jp; return; //JNZB - case 0x08e: if(regs.flagb.z == 1) regs.pc = jp; return; //JZB - - case 0x090: if(regs.flaga.ov0 == 0) regs.pc = jp; return; //JNOVA0 - case 0x092: if(regs.flaga.ov0 == 1) regs.pc = jp; return; //JOVA0 - case 0x094: if(regs.flagb.ov0 == 0) regs.pc = jp; return; //JNOVB0 - case 0x096: if(regs.flagb.ov0 == 1) regs.pc = jp; return; //JOVB0 - - case 0x098: if(regs.flaga.ov1 == 0) regs.pc = jp; return; //JNOVA1 - case 0x09a: if(regs.flaga.ov1 == 1) regs.pc = jp; return; //JOVA1 - case 0x09c: if(regs.flagb.ov1 == 0) regs.pc = jp; return; //JNOVB1 - case 0x09e: if(regs.flagb.ov1 == 1) regs.pc = jp; return; //JOVB1 - - case 0x0a0: if(regs.flaga.s0 == 0) regs.pc = jp; return; //JNSA0 - case 0x0a2: if(regs.flaga.s0 == 1) regs.pc = jp; return; //JSA0 - case 0x0a4: if(regs.flagb.s0 == 0) regs.pc = jp; return; //JNSB0 - case 0x0a6: if(regs.flagb.s0 == 1) regs.pc = jp; return; //JSB0 - - case 0x0a8: if(regs.flaga.s1 == 0) regs.pc = jp; return; //JNSA1 - case 0x0aa: if(regs.flaga.s1 == 1) regs.pc = jp; return; //JSA1 - case 0x0ac: if(regs.flagb.s1 == 0) regs.pc = jp; return; //JNSB1 - case 0x0ae: if(regs.flagb.s1 == 1) regs.pc = jp; return; //JSB1 - - case 0x0b0: if((regs.dp & 0x0f) == 0x00) regs.pc = jp; return; //JDPL0 - case 0x0b1: if((regs.dp & 0x0f) != 0x00) regs.pc = jp; return; //JDPLN0 - case 0x0b2: if((regs.dp & 0x0f) == 0x0f) regs.pc = jp; return; //JDPLF - case 0x0b3: if((regs.dp & 0x0f) != 0x0f) regs.pc = jp; return; //JDPLNF - - case 0x0bc: if(regs.sr.rqm == 0) regs.pc = jp; return; //JNRQM - case 0x0be: if(regs.sr.rqm == 1) regs.pc = jp; return; //JRQM - - case 0x100: regs.pc = jp & ~0x2000; return; //LJMP - case 0x101: regs.pc = jp | 0x2000; return; //HJMP - - case 0x140: regs.stack[regs.sp++] = regs.pc; regs.pc = jp & ~0x2000; return; //LCALL - case 0x141: regs.stack[regs.sp++] = regs.pc; regs.pc = jp | 0x2000; return; //HCALL - } -} - -void NECDSP::exec_ld(uint24 opcode) { - uint16 id = opcode >> 6; //immediate data - uint4 dst = opcode >> 0; //destination - - switch(dst) { - case 0: break; - case 1: regs.a = id; break; - case 2: regs.b = id; break; - case 3: regs.tr = id; break; - case 4: regs.dp = id; break; - case 5: regs.rp = id; break; - case 6: regs.dr = id; regs.sr.rqm = 1; break; - case 7: regs.sr = (regs.sr & 0x907c) | (id & ~0x907c); break; - case 8: regs.so = id; break; //LSB - case 9: regs.so = id; break; //MSB - case 10: regs.k = id; break; - case 11: regs.k = id; regs.l = dataROM[regs.rp]; break; - case 12: regs.l = id; regs.k = dataRAM[regs.dp | 0x40]; break; - case 13: regs.l = id; break; - case 14: regs.trb = id; break; - case 15: dataRAM[regs.dp] = id; break; - } -} - -void NECDSP::init() { -} - -void NECDSP::load() { - if(revision == Revision::uPD96050) { - cartridge.nvram.append({ "upd96050.ram", (uint8_t*)dataRAM, 4096 }); - } -} - -void NECDSP::unload() { -} - -void NECDSP::power() { - if(revision == Revision::uPD7725) { - regs.pc.bits(11); - regs.rp.bits(10); - regs.dp.bits( 8); - } - - if(revision == Revision::uPD96050) { - regs.pc.bits(14); - regs.rp.bits(11); - regs.dp.bits(11); - } -} - -void NECDSP::reset() { - create(NECDSP::Enter, frequency, 8192); - - for(unsigned n = 0; n < 16; n++) regs.stack[n] = 0x0000; - regs.pc = 0x0000; - regs.rp = 0x0000; - regs.dp = 0x0000; - regs.sp = 0x0; - regs.k = 0x0000; - regs.l = 0x0000; - regs.m = 0x0000; - regs.n = 0x0000; - regs.a = 0x0000; - regs.b = 0x0000; - regs.flaga = 0x00; - regs.flagb = 0x00; - regs.tr = 0x0000; - regs.trb = 0x0000; - regs.sr = 0x0000; - regs.dr = 0x0000; - regs.si = 0x0000; - regs.so = 0x0000; -} - -NECDSP::NECDSP() { -} - -NECDSP::~NECDSP() { -} - -} diff --git a/waterbox/libsnes/bsnes/snes/chip/necdsp/necdsp.hpp b/waterbox/libsnes/bsnes/snes/chip/necdsp/necdsp.hpp deleted file mode 100644 index 318734f987..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/necdsp/necdsp.hpp +++ /dev/null @@ -1,49 +0,0 @@ -//NEC uPD7725 -//NEC uPD96050 - -class NECDSP : public Coprocessor { -public: - enum class Revision : unsigned { uPD7725, uPD96050 } revision; - - #include "registers.hpp" - - //zero 01-sep-2014 - dont clobber these when reconstructing! - static unsigned frequency; - static uint24 programROM[16384]; - static uint16 dataROM[2048]; - static unsigned programROMSize; - static unsigned dataROMSize; - - unsigned dataRAMSize; - uint16 dataRAM[2048]; - - static void Enter(); - void enter(); - - void exec_op(uint24 opcode); - void exec_rt(uint24 opcode); - void exec_jp(uint24 opcode); - void exec_ld(uint24 opcode); - - string disassemble(uint14 ip); - - uint8 sr_read(unsigned); - void sr_write(unsigned, uint8 data); - - uint8 dr_read(unsigned); - void dr_write(unsigned, uint8 data); - - uint8 dp_read(unsigned addr); - void dp_write(unsigned addr, uint8 data); - - void init(); - void load(); - void unload(); - void power(); - void reset(); - - NECDSP(); - ~NECDSP(); -}; - -extern NECDSP necdsp; diff --git a/waterbox/libsnes/bsnes/snes/chip/necdsp/registers.hpp b/waterbox/libsnes/bsnes/snes/chip/necdsp/registers.hpp deleted file mode 100644 index ff5de61f4a..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/necdsp/registers.hpp +++ /dev/null @@ -1,51 +0,0 @@ -struct Flag { - bool s1, s0, c, z, ov1, ov0; - - inline operator unsigned() const { - return (s1 << 5) + (s0 << 4) + (c << 3) + (z << 2) + (ov1 << 1) + (ov0 << 0); - } - - inline unsigned operator=(unsigned d) { - s1 = d & 0x20; s0 = d & 0x10; c = d & 0x08; z = d & 0x04; ov1 = d & 0x02; ov0 = d & 0x01; - return d; - } -}; - -struct Status { - bool rqm, usf1, usf0, drs, dma, drc, soc, sic, ei, p1, p0; - - inline operator unsigned() const { - return (rqm << 15) + (usf1 << 14) + (usf0 << 13) + (drs << 12) - + (dma << 11) + (drc << 10) + (soc << 9) + (sic << 8) - + (ei << 7) + (p1 << 1) + (p0 << 0); - } - - inline unsigned operator=(unsigned d) { - rqm = d & 0x8000; usf1 = d & 0x4000; usf0 = d & 0x2000; drs = d & 0x1000; - dma = d & 0x0800; drc = d & 0x0400; soc = d & 0x0200; sic = d & 0x0100; - ei = d & 0x0080; p1 = d & 0x0002; p0 = d & 0x0001; - return d; - } -}; - -struct Regs { - uint16 stack[16]; //LIFO - varuint pc; //program counter - varuint rp; //ROM pointer - varuint dp; //data pointer - uint4 sp; //stack pointer - int16 k; - int16 l; - int16 m; - int16 n; - int16 a; //accumulator - int16 b; //accumulator - Flag flaga; - Flag flagb; - uint16 tr; //temporary register - uint16 trb; //temporary register - Status sr; //status register - uint16 dr; //data register - uint16 si; - uint16 so; -} regs; diff --git a/waterbox/libsnes/bsnes/snes/chip/nss/nss.cpp b/waterbox/libsnes/bsnes/snes/chip/nss/nss.cpp deleted file mode 100644 index 964973d04e..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/nss/nss.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include - -#define NSS_CPP -namespace SNES { - -NSS nss; - -void NSS::init() { -} - -void NSS::load() { - dip = 0x0000; - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4100, 0x4101, { &NSS::read, this }, { &NSS::write, this }); - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4100, 0x4101, { &NSS::read, this }, { &NSS::write, this }); -} - -void NSS::unload() { -} - -void NSS::power() { -} - -void NSS::reset() { -} - -void NSS::set_dip(uint16 dip) { - this->dip = dip; -} - -uint8 NSS::read(unsigned addr) { - if((addr & 0x40ffff) == 0x004100) return dip >> 0; - if((addr & 0x40ffff) == 0x004101) return dip >> 8; - return cpu.regs.mdr; -} - -void NSS::write(unsigned addr, uint8 data) { -} - -} diff --git a/waterbox/libsnes/bsnes/snes/chip/nss/nss.hpp b/waterbox/libsnes/bsnes/snes/chip/nss/nss.hpp deleted file mode 100644 index 3cab46da54..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/nss/nss.hpp +++ /dev/null @@ -1,17 +0,0 @@ -class NSS { -public: - void init(); - void load(); - void unload(); - void power(); - void reset(); - - void set_dip(uint16 dip); - uint8 read(unsigned addr); - void write(unsigned addr, uint8 data); - -private: - uint16 dip; -}; - -extern NSS nss; diff --git a/waterbox/libsnes/bsnes/snes/chip/obc1/obc1.cpp b/waterbox/libsnes/bsnes/snes/chip/obc1/obc1.cpp deleted file mode 100644 index 0d25410fac..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/obc1/obc1.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#define OBC1_CPP -namespace SNES { - -OBC1 obc1; - -void OBC1::init() { -} - -void OBC1::load() { -} - -void OBC1::unload() { -} - -void OBC1::power() { -} - -void OBC1::reset() { - status.baseptr = (ram_read(0x1ff5) & 1) ? 0x1800 : 0x1c00; - status.address = (ram_read(0x1ff6) & 0x7f); - status.shift = (ram_read(0x1ff6) & 3) << 1; -} - -uint8 OBC1::read(unsigned addr) { - addr &= 0x1fff; - - switch(addr) { - case 0x1ff0: return ram_read(status.baseptr + (status.address << 2) + 0); - case 0x1ff1: return ram_read(status.baseptr + (status.address << 2) + 1); - case 0x1ff2: return ram_read(status.baseptr + (status.address << 2) + 2); - case 0x1ff3: return ram_read(status.baseptr + (status.address << 2) + 3); - case 0x1ff4: return ram_read(status.baseptr + (status.address >> 2) + 0x200); - } - - return ram_read(addr); -} - -void OBC1::write(unsigned addr, uint8 data) { - addr &= 0x1fff; - - switch(addr) { - case 0x1ff0: ram_write(status.baseptr + (status.address << 2) + 0, data); return; - case 0x1ff1: ram_write(status.baseptr + (status.address << 2) + 1, data); return; - case 0x1ff2: ram_write(status.baseptr + (status.address << 2) + 2, data); return; - case 0x1ff3: ram_write(status.baseptr + (status.address << 2) + 3, data); return; - case 0x1ff4: { - uint8 temp = ram_read(status.baseptr + (status.address >> 2) + 0x200); - temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift); - ram_write(status.baseptr + (status.address >> 2) + 0x200, temp); - } return; - case 0x1ff5: - status.baseptr = (data & 1) ? 0x1800 : 0x1c00; - ram_write(addr, data); - return; - case 0x1ff6: - status.address = (data & 0x7f); - status.shift = (data & 3) << 1; - ram_write(addr, data); - return; - case 0x1ff7: - ram_write(addr, data); - return; - } - - return ram_write(addr, data); -} - -uint8 OBC1::ram_read(unsigned addr) { - return cartridge.ram.read(addr & 0x1fff); -} - -void OBC1::ram_write(unsigned addr, uint8 data) { - cartridge.ram.write(addr & 0x1fff, data); -} - -} diff --git a/waterbox/libsnes/bsnes/snes/chip/obc1/obc1.hpp b/waterbox/libsnes/bsnes/snes/chip/obc1/obc1.hpp deleted file mode 100644 index 2209b2a64d..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/obc1/obc1.hpp +++ /dev/null @@ -1,23 +0,0 @@ -class OBC1 { -public: - void init(); - void load(); - void unload(); - void power(); - void reset(); - - uint8 read(unsigned addr); - void write(unsigned addr, uint8 data); - -private: - uint8 ram_read(unsigned addr); - void ram_write(unsigned addr, uint8 data); - - struct { - uint16 address; - uint16 baseptr; - uint16 shift; - } status; -}; - -extern OBC1 obc1; diff --git a/waterbox/libsnes/bsnes/snes/chip/sa1/bus/bus.cpp b/waterbox/libsnes/bsnes/snes/chip/sa1/bus/bus.cpp deleted file mode 100644 index a632551a42..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/sa1/bus/bus.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifdef SA1_CPP - -//ROM / RAM access from the S-CPU - -unsigned SA1::CPUIRAM::size() const { - return sa1.iram.size(); -} - -uint8 SA1::CPUIRAM::read(unsigned addr) { - cpu.synchronize_coprocessors(); - return sa1.iram.read(addr); -} - -void SA1::CPUIRAM::write(unsigned addr, uint8 data) { - cpu.synchronize_coprocessors(); - sa1.iram.write(addr, data); -} - -unsigned SA1::CPUBWRAM::size() const { - return cartridge.ram.size(); -} - -uint8 SA1::CPUBWRAM::read(unsigned addr) { - cpu.synchronize_coprocessors(); - if(dma) return sa1.dma_cc1_read(addr); - return cartridge.ram.read(addr); -} - -void SA1::CPUBWRAM::write(unsigned addr, uint8 data) { - cpu.synchronize_coprocessors(); - cartridge.ram.write(addr, data); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/sa1/bus/bus.hpp b/waterbox/libsnes/bsnes/snes/chip/sa1/bus/bus.hpp deleted file mode 100644 index e3b42b9729..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/sa1/bus/bus.hpp +++ /dev/null @@ -1,14 +0,0 @@ -StaticRAM iram; - -struct CPUIRAM : Memory { - unsigned size() const; - alwaysinline uint8 read(unsigned); - alwaysinline void write(unsigned, uint8); -} cpuiram; - -struct CPUBWRAM : Memory { - unsigned size() const; - alwaysinline uint8 read(unsigned); - alwaysinline void write(unsigned, uint8); - bool dma; -} cpubwram; diff --git a/waterbox/libsnes/bsnes/snes/chip/sa1/dma/dma.cpp b/waterbox/libsnes/bsnes/snes/chip/sa1/dma/dma.cpp deleted file mode 100644 index 7114886561..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/sa1/dma/dma.cpp +++ /dev/null @@ -1,139 +0,0 @@ -#ifdef SA1_CPP - -//==================== -//direct data transfer -//==================== - -void SA1::dma_normal() { - while(mmio.dtc--) { - uint8 data = regs.mdr; - uint32 dsa = mmio.dsa++; - uint32 dda = mmio.dda++; - - //source and destination cannot be the same - if(mmio.sd == DMA::SourceBWRAM && mmio.dd == DMA::DestBWRAM) continue; - if(mmio.sd == DMA::SourceIRAM && mmio.dd == DMA::DestIRAM ) continue; - - switch(mmio.sd) { - case DMA::SourceROM: { - if((dsa & 0x408000) == 0x008000 || (dsa & 0xc00000) == 0xc00000) { - data = bus_read(dsa); - } - } break; - - case DMA::SourceBWRAM: { - if((dsa & 0x40e000) == 0x006000 || (dsa & 0xf00000) == 0x400000) { - data = bus_read(dsa); - } - } break; - - case DMA::SourceIRAM: { - data = iram.read(dsa & 0x07ff); - } break; - } - - switch(mmio.dd) { - case DMA::DestBWRAM: { - if((dda & 0x40e000) == 0x006000 || (dda & 0xf00000) == 0x400000) { - bus_write(dda, data); - } - } break; - - case DMA::DestIRAM: { - iram.write(dda & 0x07ff, data); - } break; - } - } - - mmio.dma_irqfl = true; - if(mmio.dma_irqen) mmio.dma_irqcl = 0; -} - -//((byte & 6) << 3) + (byte & 1) explanation: -//transforms a byte index (0-7) into a planar index: -//result[] = { 0, 1, 16, 17, 32, 33, 48, 49 }; -//works for 2bpp, 4bpp and 8bpp modes - -//=========================== -//type-1 character conversion -//=========================== - -void SA1::dma_cc1() { - cpubwram.dma = true; - mmio.chdma_irqfl = true; - if(mmio.chdma_irqen) { - mmio.chdma_irqcl = 0; - cpu.regs.irq = 1; - } -} - -uint8 SA1::dma_cc1_read(unsigned addr) { - //16 bytes/char (2bpp); 32 bytes/char (4bpp); 64 bytes/char (8bpp) - unsigned charmask = (1 << (6 - mmio.dmacb)) - 1; - - if((addr & charmask) == 0) { - //buffer next character to I-RAM - unsigned bpp = 2 << (2 - mmio.dmacb); - unsigned bpl = (8 << mmio.dmasize) >> mmio.dmacb; - unsigned bwmask = cartridge.ram.size() - 1; - unsigned tile = ((addr - mmio.dsa) & bwmask) >> (6 - mmio.dmacb); - unsigned ty = (tile >> mmio.dmasize); - unsigned tx = tile & ((1 << mmio.dmasize) - 1); - unsigned bwaddr = mmio.dsa + ty * 8 * bpl + tx * bpp; - - for(unsigned y = 0; y < 8; y++) { - uint64 data = 0; - for(unsigned byte = 0; byte < bpp; byte++) { - data |= (uint64)cartridge.ram.read((bwaddr + byte) & bwmask) << (byte << 3); - } - bwaddr += bpl; - - uint8 out[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - for(unsigned x = 0; x < 8; x++) { - out[0] |= (data & 1) << (7 - x); data >>= 1; - out[1] |= (data & 1) << (7 - x); data >>= 1; - if(mmio.dmacb == 2) continue; - out[2] |= (data & 1) << (7 - x); data >>= 1; - out[3] |= (data & 1) << (7 - x); data >>= 1; - if(mmio.dmacb == 1) continue; - out[4] |= (data & 1) << (7 - x); data >>= 1; - out[5] |= (data & 1) << (7 - x); data >>= 1; - out[6] |= (data & 1) << (7 - x); data >>= 1; - out[7] |= (data & 1) << (7 - x); data >>= 1; - } - - for(unsigned byte = 0; byte < bpp; byte++) { - unsigned p = mmio.dda + (y << 1) + ((byte & 6) << 3) + (byte & 1); - iram.write(p & 0x07ff, out[byte]); - } - } - } - - return iram.read((mmio.dda + (addr & charmask)) & 0x07ff); -} - -//=========================== -//type-2 character conversion -//=========================== - -void SA1::dma_cc2() { - //select register file index (0-7 or 8-15) - const uint8 *brf = &mmio.brf[(dma.line & 1) << 3]; - unsigned bpp = 2 << (2 - mmio.dmacb); - unsigned addr = mmio.dda & 0x07ff; - addr &= ~((1 << (7 - mmio.dmacb)) - 1); - addr += (dma.line & 8) * bpp; - addr += (dma.line & 7) * 2; - - for(unsigned byte = 0; byte < bpp; byte++) { - uint8 output = 0; - for(unsigned bit = 0; bit < 8; bit++) { - output |= ((brf[bit] >> byte) & 1) << (7 - bit); - } - iram.write(addr + ((byte & 6) << 3) + (byte & 1), output); - } - - dma.line = (dma.line + 1) & 15; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/sa1/dma/dma.hpp b/waterbox/libsnes/bsnes/snes/chip/sa1/dma/dma.hpp deleted file mode 100644 index 4d3cff7f93..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/sa1/dma/dma.hpp +++ /dev/null @@ -1,11 +0,0 @@ -struct DMA { - enum CDEN { DmaNormal = 0, DmaCharConversion = 1 }; - enum SD { SourceROM = 0, SourceBWRAM = 1, SourceIRAM = 2 }; - enum DD { DestIRAM = 0, DestBWRAM = 1 }; - unsigned line; -} dma; - -void dma_normal(); -void dma_cc1(); -uint8 dma_cc1_read(unsigned addr); -void dma_cc2(); diff --git a/waterbox/libsnes/bsnes/snes/chip/sa1/memory/memory.cpp b/waterbox/libsnes/bsnes/snes/chip/sa1/memory/memory.cpp deleted file mode 100644 index 45a9d54c3d..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/sa1/memory/memory.cpp +++ /dev/null @@ -1,267 +0,0 @@ -#ifdef SA1_CPP - -uint8 SA1::bus_read(unsigned addr) { - if((addr & 0x40fe00) == 0x002200) { //$00-3f|80-bf:2200-23ff - return mmio_read(addr); - } - - if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff - return mmc_read(addr); - } - - if((addr & 0xc00000) == 0xc00000) { //$c0-ff:0000-ffff - return mmc_read(addr); - } - - if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff - return mmc_sa1_read(addr); - } - - if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff - synchronize_cpu(); - return iram.read(addr & 2047); - } - - if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff - synchronize_cpu(); - return iram.read(addr & 2047); - } - - if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff - synchronize_cpu(); - return cartridge.ram.read(addr & (cartridge.ram.size() - 1)); - } - - if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff - synchronize_cpu(); - return bitmap_read(addr & 0x0fffff); - } -} - -void SA1::bus_write(unsigned addr, uint8 data) { - if((addr & 0x40fe00) == 0x002200) { //$00-3f|80-bf:2200-23ff - return mmio_write(addr, data); - } - - if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff - return mmc_sa1_write(addr, data); - } - - if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff - synchronize_cpu(); - return iram.write(addr & 2047, data); - } - - if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff - synchronize_cpu(); - return iram.write(addr & 2047, data); - } - - if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff - synchronize_cpu(); - return cartridge.ram.write(addr & (cartridge.ram.size() - 1), data); - } - - if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff - synchronize_cpu(); - return bitmap_write(addr & 0x0fffff, data); - } -} - -//$230c (VDPL), $230d (VDPH) use this bus to read variable-length data. -//this is used both to keep VBR-reads from accessing MMIO registers, and -//to avoid syncing the S-CPU and SA-1*; as both chips are able to access -//these ports. -uint8 SA1::vbr_read(unsigned addr) { - if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff - return mmc_read(addr); - } - - if((addr & 0xc00000) == 0xc00000) { //$c0-ff:0000-ffff - return mmc_read(addr); - } - - if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff - return cartridge.ram.read(addr & (cartridge.ram.size() - 1)); - } - - if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff - return cartridge.ram.read(addr & (cartridge.ram.size() - 1)); - } - - if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff - return iram.read(addr & 2047); - } - - if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff - return iram.read(addr & 0x2047); - } -} - -//ROM, I-RAM and MMIO registers are accessed at ~10.74MHz (2 clock ticks) -//BW-RAM is accessed at ~5.37MHz (4 clock ticks) -//tick() == 2 clock ticks -//note: bus conflict delays are not emulated at this time - -void SA1::op_io() { - tick(); -} - -uint8 SA1::op_read(unsigned addr, eCDLog_Flags flags) { - (void)flags; //this was needed for inheritance purposes, as SA-1 is derived from the main CPU class - tick(); - if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick(); - return bus_read(addr); -} - -void SA1::op_write(unsigned addr, uint8 data) { - tick(); - if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick(); - bus_write(addr, data); -} - -uint8 SA1::mmc_read(unsigned addr) { - if((addr & 0xffffe0) == 0x00ffe0) { - if(addr == 0xffea && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 0; - if(addr == 0xffeb && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 8; - if(addr == 0xffee && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 0; - if(addr == 0xffef && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 8; - } - - static auto read = [](unsigned addr) { - auto myaddr = bus.mirror(addr, cartridge.rom.size()); - cdlInfo.set(eCDLog_AddrType_CARTROM, myaddr); - return cartridge.rom.read(myaddr); - }; - - if((addr & 0xe08000) == 0x008000) { //$00-1f:8000-ffff - addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff); - if(mmio.cbmode == 0) return read(0x000000 | addr); - return read((mmio.cb << 20) | addr); - } - - if((addr & 0xe08000) == 0x208000) { //$20-3f:8000-ffff - addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff); - if(mmio.dbmode == 0) return read(0x100000 | addr); - return read((mmio.db << 20) | addr); - } - - if((addr & 0xe08000) == 0x808000) { //$80-9f:8000-ffff - addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff); - if(mmio.ebmode == 0) return read(0x200000 | addr); - return read((mmio.eb << 20) | addr); - } - - if((addr & 0xe08000) == 0xa08000) { //$a0-bf:8000-ffff - addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff); - if(mmio.fbmode == 0) return read(0x300000 | addr); - return read((mmio.fb << 20) | addr); - } - - if((addr & 0xf00000) == 0xc00000) { //$c0-cf:0000-ffff - return read((mmio.cb << 20) | (addr & 0x0fffff)); - } - - if((addr & 0xf00000) == 0xd00000) { //$d0-df:0000-ffff - return read((mmio.db << 20) | (addr & 0x0fffff)); - } - - if((addr & 0xf00000) == 0xe00000) { //$e0-ef:0000-ffff - return read((mmio.eb << 20) | (addr & 0x0fffff)); - } - - if((addr & 0xf00000) == 0xf00000) { //$f0-ff:0000-ffff - return read((mmio.fb << 20) | (addr & 0x0fffff)); - } - - return 0x00; -} - -void SA1::mmc_write(unsigned addr, uint8 data) { -} - -uint8 SA1::mmc_cpu_read(unsigned addr) { - cpu.synchronize_coprocessors(); - addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size()); - return cpubwram.read(addr); -} - -void SA1::mmc_cpu_write(unsigned addr, uint8 data) { - cpu.synchronize_coprocessors(); - addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size()); - cpubwram.write(addr, data); -} - -uint8 SA1::mmc_sa1_read(unsigned addr) { - synchronize_cpu(); - if(mmio.sw46 == 0) { - //$40-43:0000-ffff x 32 projection - addr = bus.mirror((mmio.cbm & 0x1f) * 0x2000 + (addr & 0x1fff), cartridge.ram.size()); - return cartridge.ram.read(addr); - } else { - //$60-6f:0000-ffff x 128 projection - addr = bus.mirror(mmio.cbm * 0x2000 + (addr & 0x1fff), 0x100000); - return bitmap_read(addr); - } -} - -void SA1::mmc_sa1_write(unsigned addr, uint8 data) { - synchronize_cpu(); - if(mmio.sw46 == 0) { - //$40-43:0000-ffff x 32 projection - addr = bus.mirror((mmio.cbm & 0x1f) * 0x2000 + (addr & 0x1fff), cartridge.ram.size()); - cartridge.ram.write(addr, data); - } else { - //$60-6f:0000-ffff x 128 projection - addr = bus.mirror(mmio.cbm * 0x2000 + (addr & 0x1fff), 0x100000); - bitmap_write(addr, data); - } -} - -uint8 SA1::bitmap_read(unsigned addr) { - if(mmio.bbf == 0) { - //4bpp - unsigned shift = addr & 1; - addr = (addr >> 1) & (cartridge.ram.size() - 1); - switch(shift) { default: - case 0: return (cartridge.ram.read(addr) >> 0) & 15; - case 1: return (cartridge.ram.read(addr) >> 4) & 15; - } - } else { - //2bpp - unsigned shift = addr & 3; - addr = (addr >> 2) & (cartridge.ram.size() - 1); - switch(shift) { default: - case 0: return (cartridge.ram.read(addr) >> 0) & 3; - case 1: return (cartridge.ram.read(addr) >> 2) & 3; - case 2: return (cartridge.ram.read(addr) >> 4) & 3; - case 3: return (cartridge.ram.read(addr) >> 6) & 3; - } - } -} - -void SA1::bitmap_write(unsigned addr, uint8 data) { - if(mmio.bbf == 0) { - //4bpp - unsigned shift = addr & 1; - addr = (addr >> 1) & (cartridge.ram.size() - 1); - switch(shift) { default: - case 0: data = (cartridge.ram.read(addr) & 0xf0) | ((data & 15) << 0); break; - case 1: data = (cartridge.ram.read(addr) & 0x0f) | ((data & 15) << 4); break; - } - } else { - //2bpp - unsigned shift = addr & 3; - addr = (addr >> 2) & (cartridge.ram.size() - 1); - switch(shift) { default: - case 0: data = (cartridge.ram.read(addr) & 0xfc) | ((data & 3) << 0); break; - case 1: data = (cartridge.ram.read(addr) & 0xf3) | ((data & 3) << 2); break; - case 2: data = (cartridge.ram.read(addr) & 0xcf) | ((data & 3) << 4); break; - case 3: data = (cartridge.ram.read(addr) & 0x3f) | ((data & 3) << 6); break; - } - } - - cartridge.ram.write(addr, data); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/sa1/memory/memory.hpp b/waterbox/libsnes/bsnes/snes/chip/sa1/memory/memory.hpp deleted file mode 100644 index 6e627057c0..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/sa1/memory/memory.hpp +++ /dev/null @@ -1,19 +0,0 @@ -uint8 bus_read(unsigned addr); -void bus_write(unsigned addr, uint8 data); -uint8 vbr_read(unsigned addr); - -alwaysinline void op_io(); -alwaysinline uint8 op_read(unsigned addr, eCDLog_Flags = eCDLog_Flags_CPUData); -alwaysinline void op_write(unsigned addr, uint8 data); - -uint8 mmc_read(unsigned addr); -void mmc_write(unsigned addr, uint8 data); - -uint8 mmc_cpu_read(unsigned addr); -void mmc_cpu_write(unsigned addr, uint8 data); - -uint8 mmc_sa1_read(unsigned addr); -void mmc_sa1_write(unsigned addr, uint8 data); - -uint8 bitmap_read(unsigned addr); -void bitmap_write(unsigned addr, uint8 data); diff --git a/waterbox/libsnes/bsnes/snes/chip/sa1/mmio/mmio.cpp b/waterbox/libsnes/bsnes/snes/chip/sa1/mmio/mmio.cpp deleted file mode 100644 index c4a894b0a9..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/sa1/mmio/mmio.cpp +++ /dev/null @@ -1,554 +0,0 @@ -#ifdef SA1_CPP - -//(CCNT) SA-1 control -void SA1::mmio_w2200(uint8 data) { - if(mmio.sa1_resb && !(data & 0x80)) { - //reset SA-1 CPU - regs.pc.w = mmio.crv; - regs.pc.b = 0x00; - } - - mmio.sa1_irq = (data & 0x80); - mmio.sa1_rdyb = (data & 0x40); - mmio.sa1_resb = (data & 0x20); - mmio.sa1_nmi = (data & 0x10); - mmio.smeg = (data & 0x0f); - - if(mmio.sa1_irq) { - mmio.sa1_irqfl = true; - if(mmio.sa1_irqen) mmio.sa1_irqcl = 0; - } - - if(mmio.sa1_nmi) { - mmio.sa1_nmifl = true; - if(mmio.sa1_nmien) mmio.sa1_nmicl = 0; - } -} - -//(SIE) S-CPU interrupt enable -void SA1::mmio_w2201(uint8 data) { - if(!mmio.cpu_irqen && (data & 0x80)) { - if(mmio.cpu_irqfl) { - mmio.cpu_irqcl = 0; - cpu.regs.irq = 1; - } - } - - if(!mmio.chdma_irqen && (data & 0x20)) { - if(mmio.chdma_irqfl) { - mmio.chdma_irqcl = 0; - cpu.regs.irq = 1; - } - } - - mmio.cpu_irqen = (data & 0x80); - mmio.chdma_irqen = (data & 0x20); -} - -//(SIC) S-CPU interrupt clear -void SA1::mmio_w2202(uint8 data) { - mmio.cpu_irqcl = (data & 0x80); - mmio.chdma_irqcl = (data & 0x20); - - if(mmio.cpu_irqcl ) mmio.cpu_irqfl = false; - if(mmio.chdma_irqcl) mmio.chdma_irqfl = false; - - if(!mmio.cpu_irqfl && !mmio.chdma_irqfl) cpu.regs.irq = 0; -} - -//(CRV) SA-1 reset vector -void SA1::mmio_w2203(uint8 data) { mmio.crv = (mmio.crv & 0xff00) | data; } -void SA1::mmio_w2204(uint8 data) { mmio.crv = (data << 8) | (mmio.crv & 0xff); } - -//(CNV) SA-1 NMI vector -void SA1::mmio_w2205(uint8 data) { mmio.cnv = (mmio.cnv & 0xff00) | data; } -void SA1::mmio_w2206(uint8 data) { mmio.cnv = (data << 8) | (mmio.cnv & 0xff); } - -//(CIV) SA-1 IRQ vector -void SA1::mmio_w2207(uint8 data) { mmio.civ = (mmio.civ & 0xff00) | data; } -void SA1::mmio_w2208(uint8 data) { mmio.civ = (data << 8) | (mmio.civ & 0xff); } - -//(SCNT) S-CPU control -void SA1::mmio_w2209(uint8 data) { - mmio.cpu_irq = (data & 0x80); - mmio.cpu_ivsw = (data & 0x40); - mmio.cpu_nvsw = (data & 0x10); - mmio.cmeg = (data & 0x0f); - - if(mmio.cpu_irq) { - mmio.cpu_irqfl = true; - if(mmio.cpu_irqen) { - mmio.cpu_irqcl = 0; - cpu.regs.irq = 1; - } - } -} - -//(CIE) SA-1 interrupt enable -void SA1::mmio_w220a(uint8 data) { - if(!mmio.sa1_irqen && (data & 0x80) && mmio.sa1_irqfl ) mmio.sa1_irqcl = 0; - if(!mmio.timer_irqen && (data & 0x40) && mmio.timer_irqfl) mmio.timer_irqcl = 0; - if(!mmio.dma_irqen && (data & 0x20) && mmio.dma_irqfl ) mmio.dma_irqcl = 0; - if(!mmio.sa1_nmien && (data & 0x10) && mmio.sa1_nmifl ) mmio.sa1_nmicl = 0; - - mmio.sa1_irqen = (data & 0x80); - mmio.timer_irqen = (data & 0x40); - mmio.dma_irqen = (data & 0x20); - mmio.sa1_nmien = (data & 0x10); -} - -//(CIC) SA-1 interrupt clear -void SA1::mmio_w220b(uint8 data) { - mmio.sa1_irqcl = (data & 0x80); - mmio.timer_irqcl = (data & 0x40); - mmio.dma_irqcl = (data & 0x20); - mmio.sa1_nmicl = (data & 0x10); - - if(mmio.sa1_irqcl) mmio.sa1_irqfl = false; - if(mmio.timer_irqcl) mmio.timer_irqfl = false; - if(mmio.dma_irqcl) mmio.dma_irqfl = false; - if(mmio.sa1_nmicl) mmio.sa1_nmifl = false; -} - -//(SNV) S-CPU NMI vector -void SA1::mmio_w220c(uint8 data) { mmio.snv = (mmio.snv & 0xff00) | data; } -void SA1::mmio_w220d(uint8 data) { mmio.snv = (data << 8) | (mmio.snv & 0xff); } - -//(SIV) S-CPU IRQ vector -void SA1::mmio_w220e(uint8 data) { mmio.siv = (mmio.siv & 0xff00) | data; } -void SA1::mmio_w220f(uint8 data) { mmio.siv = (data << 8) | (mmio.siv & 0xff); } - -//(TMC) H/V timer control -void SA1::mmio_w2210(uint8 data) { - mmio.hvselb = (data & 0x80); - mmio.ven = (data & 0x02); - mmio.hen = (data & 0x01); -} - -//(CTR) SA-1 timer restart -void SA1::mmio_w2211(uint8 data) { - status.vcounter = 0; - status.hcounter = 0; -} - -//(HCNT) H-count -void SA1::mmio_w2212(uint8 data) { mmio.hcnt = (mmio.hcnt & 0xff00) | (data << 0); } -void SA1::mmio_w2213(uint8 data) { mmio.hcnt = (mmio.hcnt & 0x00ff) | (data << 8); } - -//(VCNT) V-count -void SA1::mmio_w2214(uint8 data) { mmio.vcnt = (mmio.vcnt & 0xff00) | (data << 0); } -void SA1::mmio_w2215(uint8 data) { mmio.vcnt = (mmio.vcnt & 0x00ff) | (data << 8); } - -//(CXB) Super MMC bank C -void SA1::mmio_w2220(uint8 data) { - mmio.cbmode = (data & 0x80); - mmio.cb = (data & 0x07); -} - -//(DXB) Super MMC bank D -void SA1::mmio_w2221(uint8 data) { - mmio.dbmode = (data & 0x80); - mmio.db = (data & 0x07); -} - -//(EXB) Super MMC bank E -void SA1::mmio_w2222(uint8 data) { - mmio.ebmode = (data & 0x80); - mmio.eb = (data & 0x07); -} - -//(FXB) Super MMC bank F -void SA1::mmio_w2223(uint8 data) { - mmio.fbmode = (data & 0x80); - mmio.fb = (data & 0x07); -} - -//(BMAPS) S-CPU BW-RAM address mapping -void SA1::mmio_w2224(uint8 data) { - mmio.sbm = (data & 0x1f); -} - -//(BMAP) SA-1 BW-RAM address mapping -void SA1::mmio_w2225(uint8 data) { - mmio.sw46 = (data & 0x80); - mmio.cbm = (data & 0x7f); -} - -//(SWBE) S-CPU BW-RAM write enable -void SA1::mmio_w2226(uint8 data) { - mmio.swen = (data & 0x80); -} - -//(CWBE) SA-1 BW-RAM write enable -void SA1::mmio_w2227(uint8 data) { - mmio.cwen = (data & 0x80); -} - -//(BWPA) BW-RAM write-protected area -void SA1::mmio_w2228(uint8 data) { - mmio.bwp = (data & 0x0f); -} - -//(SIWP) S-CPU I-RAM write protection -void SA1::mmio_w2229(uint8 data) { - mmio.siwp = data; -} - -//(CIWP) SA-1 I-RAM write protection -void SA1::mmio_w222a(uint8 data) { - mmio.ciwp = data; -} - -//(DCNT) DMA control -void SA1::mmio_w2230(uint8 data) { - mmio.dmaen = (data & 0x80); - mmio.dprio = (data & 0x40); - mmio.cden = (data & 0x20); - mmio.cdsel = (data & 0x10); - mmio.dd = (data & 0x04); - mmio.sd = (data & 0x03); - - if(mmio.dmaen == 0) dma.line = 0; -} - -//(CDMA) character conversion DMA parameters -void SA1::mmio_w2231(uint8 data) { - mmio.chdend = (data & 0x80); - mmio.dmasize = (data >> 2) & 7; - mmio.dmacb = (data & 0x03); - - if(mmio.chdend) cpubwram.dma = false; - if(mmio.dmasize > 5) mmio.dmasize = 5; - if(mmio.dmacb > 2) mmio.dmacb = 2; -} - -//(SDA) DMA source device start address -void SA1::mmio_w2232(uint8 data) { mmio.dsa = (mmio.dsa & 0xffff00) | (data << 0); } -void SA1::mmio_w2233(uint8 data) { mmio.dsa = (mmio.dsa & 0xff00ff) | (data << 8); } -void SA1::mmio_w2234(uint8 data) { mmio.dsa = (mmio.dsa & 0x00ffff) | (data << 16); } - -//(DDA) DMA destination start address -void SA1::mmio_w2235(uint8 data) { - mmio.dda = (mmio.dda & 0xffff00) | (data << 0); -} - -void SA1::mmio_w2236(uint8 data) { - mmio.dda = (mmio.dda & 0xff00ff) | (data << 8); - - if(mmio.dmaen == true) { - if(mmio.cden == 0 && mmio.dd == DMA::DestIRAM) { - dma_normal(); - } else if(mmio.cden == 1 && mmio.cdsel == 1) { - dma_cc1(); - } - } -} - -void SA1::mmio_w2237(uint8 data) { - mmio.dda = (mmio.dda & 0x00ffff) | (data << 16); - - if(mmio.dmaen == true) { - if(mmio.cden == 0 && mmio.dd == DMA::DestBWRAM) { - dma_normal(); - } - } -} - -//(DTC) DMA terminal counter -void SA1::mmio_w2238(uint8 data) { mmio.dtc = (mmio.dtc & 0xff00) | (data << 0); } -void SA1::mmio_w2239(uint8 data) { mmio.dtc = (mmio.dtc & 0x00ff) | (data << 8); } - -//(BBF) BW-RAM bitmap format -void SA1::mmio_w223f(uint8 data) { - mmio.bbf = (data & 0x80); -} - -//(BRF) bitmap register files -void SA1::mmio_w2240(uint8 data) { mmio.brf[ 0] = data; } -void SA1::mmio_w2241(uint8 data) { mmio.brf[ 1] = data; } -void SA1::mmio_w2242(uint8 data) { mmio.brf[ 2] = data; } -void SA1::mmio_w2243(uint8 data) { mmio.brf[ 3] = data; } -void SA1::mmio_w2244(uint8 data) { mmio.brf[ 4] = data; } -void SA1::mmio_w2245(uint8 data) { mmio.brf[ 5] = data; } -void SA1::mmio_w2246(uint8 data) { mmio.brf[ 6] = data; } -void SA1::mmio_w2247(uint8 data) { mmio.brf[ 7] = data; - if(mmio.dmaen == true) { - if(mmio.cden == 1 && mmio.cdsel == 0) { - dma_cc2(); - } - } -} - -void SA1::mmio_w2248(uint8 data) { mmio.brf[ 8] = data; } -void SA1::mmio_w2249(uint8 data) { mmio.brf[ 9] = data; } -void SA1::mmio_w224a(uint8 data) { mmio.brf[10] = data; } -void SA1::mmio_w224b(uint8 data) { mmio.brf[11] = data; } -void SA1::mmio_w224c(uint8 data) { mmio.brf[12] = data; } -void SA1::mmio_w224d(uint8 data) { mmio.brf[13] = data; } -void SA1::mmio_w224e(uint8 data) { mmio.brf[14] = data; } -void SA1::mmio_w224f(uint8 data) { mmio.brf[15] = data; - if(mmio.dmaen == true) { - if(mmio.cden == 1 && mmio.cdsel == 0) { - dma_cc2(); - } - } -} - -//(MCNT) arithmetic control -void SA1::mmio_w2250(uint8 data) { - mmio.acm = (data & 0x02); - mmio.md = (data & 0x01); - - if(mmio.acm) mmio.mr = 0; -} - -//(MAL) multiplicand / dividend low -void SA1::mmio_w2251(uint8 data) { - mmio.ma = (mmio.ma & 0xff00) | data; -} - -//(MAH) multiplicand / dividend high -void SA1::mmio_w2252(uint8 data) { - mmio.ma = (data << 8) | (mmio.ma & 0x00ff); -} - -//(MBL) multiplier / divisor low -void SA1::mmio_w2253(uint8 data) { - mmio.mb = (mmio.mb & 0xff00) | data; -} - -//(MBH) multiplier / divisor high -//multiplication / cumulative sum only resets MB -//division resets both MA and MB -void SA1::mmio_w2254(uint8 data) { - mmio.mb = (data << 8) | (mmio.mb & 0x00ff); - - if(mmio.acm == 0) { - if(mmio.md == 0) { - //signed multiplication - mmio.mr = (int16)mmio.ma * (int16)mmio.mb; - mmio.mb = 0; - } else { - //unsigned division - if(mmio.mb == 0) { - mmio.mr = 0; - } else { - int16 quotient = (int16)mmio.ma / (uint16)mmio.mb; - uint16 remainder = (int16)mmio.ma % (uint16)mmio.mb; - mmio.mr = (remainder << 16) | quotient; - } - mmio.ma = 0; - mmio.mb = 0; - } - } else { - //sigma (accumulative multiplication) - mmio.mr += (int16)mmio.ma * (int16)mmio.mb; - mmio.overflow = (mmio.mr >= (1ULL << 40)); - mmio.mr &= (1ULL << 40) - 1; - mmio.mb = 0; - } -} - -//(VBD) variable-length bit processing -void SA1::mmio_w2258(uint8 data) { - mmio.hl = (data & 0x80); - mmio.vb = (data & 0x0f); - if(mmio.vb == 0) mmio.vb = 16; - - if(mmio.hl == 0) { - //fixed mode - mmio.vbit += mmio.vb; - mmio.va += (mmio.vbit >> 3); - mmio.vbit &= 7; - } -} - -//(VDA) variable-length bit game pak ROM start address -void SA1::mmio_w2259(uint8 data) { mmio.va = (mmio.va & 0xffff00) | (data << 0); } -void SA1::mmio_w225a(uint8 data) { mmio.va = (mmio.va & 0xff00ff) | (data << 8); } -void SA1::mmio_w225b(uint8 data) { mmio.va = (mmio.va & 0x00ffff) | (data << 16); mmio.vbit = 0; } - -//(SFR) S-CPU flag read -uint8 SA1::mmio_r2300() { - uint8 data; - data = mmio.cpu_irqfl << 7; - data |= mmio.cpu_ivsw << 6; - data |= mmio.chdma_irqfl << 5; - data |= mmio.cpu_nvsw << 4; - data |= mmio.cmeg; - return data; -} - -//(CFR) SA-1 flag read -uint8 SA1::mmio_r2301() { - uint8 data; - data = mmio.sa1_irqfl << 7; - data |= mmio.timer_irqfl << 6; - data |= mmio.dma_irqfl << 5; - data |= mmio.sa1_nmifl << 4; - data |= mmio.smeg; - return data; -} - -//(HCR) hcounter read -uint8 SA1::mmio_r2302() { - //latch counters - mmio.hcr = status.hcounter >> 2; - mmio.vcr = status.vcounter; - return mmio.hcr >> 0; } -uint8 SA1::mmio_r2303() { return mmio.hcr >> 8; } - -//(VCR) vcounter read -uint8 SA1::mmio_r2304() { return mmio.vcr >> 0; } -uint8 SA1::mmio_r2305() { return mmio.vcr >> 8; } - -//(MR) arithmetic result -uint8 SA1::mmio_r2306() { return mmio.mr >> 0; } -uint8 SA1::mmio_r2307() { return mmio.mr >> 8; } -uint8 SA1::mmio_r2308() { return mmio.mr >> 16; } -uint8 SA1::mmio_r2309() { return mmio.mr >> 24; } -uint8 SA1::mmio_r230a() { return mmio.mr >> 32; } - -//(OF) arithmetic overflow flag -uint8 SA1::mmio_r230b() { return mmio.overflow << 7; } - -//(VDPL) variable-length data read port low -uint8 SA1::mmio_r230c() { - uint32 data = (vbr_read(mmio.va + 0) << 0) - | (vbr_read(mmio.va + 1) << 8) - | (vbr_read(mmio.va + 2) << 16); - data >>= mmio.vbit; - return data >> 0; -} - -//(VDPH) variable-length data read port high -uint8 SA1::mmio_r230d() { - uint32 data = (vbr_read(mmio.va + 0) << 0) - | (vbr_read(mmio.va + 1) << 8) - | (vbr_read(mmio.va + 2) << 16); - data >>= mmio.vbit; - - if(mmio.hl == 1) { - //auto-increment mode - mmio.vbit += mmio.vb; - mmio.va += (mmio.vbit >> 3); - mmio.vbit &= 7; - } - - return data >> 8; -} - -//(VC) version code register -uint8 SA1::mmio_r230e() { - return 0x01; //true value unknown -} - -uint8 SA1::mmio_read(unsigned addr) { - (co_active() == cpu.thread ? cpu.synchronize_coprocessors() : synchronize_cpu()); - addr &= 0xffff; - - switch(addr) { - case 0x2300: return mmio_r2300(); - case 0x2301: return mmio_r2301(); - case 0x2302: return mmio_r2302(); - case 0x2303: return mmio_r2303(); - case 0x2304: return mmio_r2304(); - case 0x2305: return mmio_r2305(); - case 0x2306: return mmio_r2306(); - case 0x2307: return mmio_r2307(); - case 0x2308: return mmio_r2308(); - case 0x2309: return mmio_r2309(); - case 0x230a: return mmio_r230a(); - case 0x230b: return mmio_r230b(); - case 0x230c: return mmio_r230c(); - case 0x230d: return mmio_r230d(); - case 0x230e: return mmio_r230e(); - } - - return 0x00; -} - -void SA1::mmio_write(unsigned addr, uint8 data) { - (co_active() == cpu.thread ? cpu.synchronize_coprocessors() : synchronize_cpu()); - addr &= 0xffff; - - switch(addr) { - case 0x2200: return mmio_w2200(data); - case 0x2201: return mmio_w2201(data); - case 0x2202: return mmio_w2202(data); - case 0x2203: return mmio_w2203(data); - case 0x2204: return mmio_w2204(data); - case 0x2205: return mmio_w2205(data); - case 0x2206: return mmio_w2206(data); - case 0x2207: return mmio_w2207(data); - case 0x2208: return mmio_w2208(data); - case 0x2209: return mmio_w2209(data); - case 0x220a: return mmio_w220a(data); - case 0x220b: return mmio_w220b(data); - case 0x220c: return mmio_w220c(data); - case 0x220d: return mmio_w220d(data); - case 0x220e: return mmio_w220e(data); - case 0x220f: return mmio_w220f(data); - - case 0x2210: return mmio_w2210(data); - case 0x2211: return mmio_w2211(data); - case 0x2212: return mmio_w2212(data); - case 0x2213: return mmio_w2213(data); - case 0x2214: return mmio_w2214(data); - case 0x2215: return mmio_w2215(data); - - case 0x2220: return mmio_w2220(data); - case 0x2221: return mmio_w2221(data); - case 0x2222: return mmio_w2222(data); - case 0x2223: return mmio_w2223(data); - case 0x2224: return mmio_w2224(data); - case 0x2225: return mmio_w2225(data); - case 0x2226: return mmio_w2226(data); - case 0x2227: return mmio_w2227(data); - case 0x2228: return mmio_w2228(data); - case 0x2229: return mmio_w2229(data); - case 0x222a: return mmio_w222a(data); - - case 0x2230: return mmio_w2230(data); - case 0x2231: return mmio_w2231(data); - case 0x2232: return mmio_w2232(data); - case 0x2233: return mmio_w2233(data); - case 0x2234: return mmio_w2234(data); - case 0x2235: return mmio_w2235(data); - case 0x2236: return mmio_w2236(data); - case 0x2237: return mmio_w2237(data); - case 0x2238: return mmio_w2238(data); - case 0x2239: return mmio_w2239(data); - - case 0x223f: return mmio_w223f(data); - case 0x2240: return mmio_w2240(data); - case 0x2241: return mmio_w2241(data); - case 0x2242: return mmio_w2242(data); - case 0x2243: return mmio_w2243(data); - case 0x2244: return mmio_w2244(data); - case 0x2245: return mmio_w2245(data); - case 0x2246: return mmio_w2246(data); - case 0x2247: return mmio_w2247(data); - case 0x2248: return mmio_w2248(data); - case 0x2249: return mmio_w2249(data); - case 0x224a: return mmio_w224a(data); - case 0x224b: return mmio_w224b(data); - case 0x224c: return mmio_w224c(data); - case 0x224d: return mmio_w224d(data); - case 0x224e: return mmio_w224e(data); - case 0x224f: return mmio_w224f(data); - - case 0x2250: return mmio_w2250(data); - case 0x2251: return mmio_w2251(data); - case 0x2252: return mmio_w2252(data); - case 0x2253: return mmio_w2253(data); - case 0x2254: return mmio_w2254(data); - - case 0x2258: return mmio_w2258(data); - case 0x2259: return mmio_w2259(data); - case 0x225a: return mmio_w225a(data); - case 0x225b: return mmio_w225b(data); - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/sa1/mmio/mmio.hpp b/waterbox/libsnes/bsnes/snes/chip/sa1/mmio/mmio.hpp deleted file mode 100644 index 4eaa146864..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/sa1/mmio/mmio.hpp +++ /dev/null @@ -1,255 +0,0 @@ -uint8 mmio_read(unsigned addr); -void mmio_write(unsigned addr, uint8 data); - -struct MMIO { - //$2200 CCNT - bool sa1_irq; - bool sa1_rdyb; - bool sa1_resb; - bool sa1_nmi; - uint8 smeg; - - //$2201 SIE - bool cpu_irqen; - bool chdma_irqen; - - //$2202 SIC - bool cpu_irqcl; - bool chdma_irqcl; - - //$2203,$2204 CRV - uint16 crv; - - //$2205,$2206 CNV - uint16 cnv; - - //$2207,$2208 CIV - uint16 civ; - - //$2209 SCNT - bool cpu_irq; - bool cpu_ivsw; - bool cpu_nvsw; - uint8 cmeg; - - //$220a CIE - bool sa1_irqen; - bool timer_irqen; - bool dma_irqen; - bool sa1_nmien; - - //$220b CIC - bool sa1_irqcl; - bool timer_irqcl; - bool dma_irqcl; - bool sa1_nmicl; - - //$220c,$220d SNV - uint16 snv; - - //$220e,$220f SIV - uint16 siv; - - //$2210 TMC - bool hvselb; - bool ven; - bool hen; - - //$2212,$2213 - uint16 hcnt; - - //$2214,$2215 - uint16 vcnt; - - //$2220 CXB - bool cbmode; - unsigned cb; - - //$2221 DXB - bool dbmode; - unsigned db; - - //$2222 EXB - bool ebmode; - unsigned eb; - - //$2223 FXB - bool fbmode; - unsigned fb; - - //$2224 BMAPS - uint8 sbm; - - //$2225 BMAP - bool sw46; - uint8 cbm; - - //$2226 SBWE - bool swen; - - //$2227 CBWE - bool cwen; - - //$2228 BWPA - uint8 bwp; - - //$2229 SIWP - uint8 siwp; - - //$222a CIWP - uint8 ciwp; - - //$2230 DCNT - bool dmaen; - bool dprio; - bool cden; - bool cdsel; - bool dd; - uint8 sd; - - //$2231 CDMA - bool chdend; - uint8 dmasize; - uint8 dmacb; - - //$2232-$2234 SDA - uint32 dsa; - - //$2235-$2237 DDA - uint32 dda; - - //$2238,$2239 DTC - uint16 dtc; - - //$223f BBF - bool bbf; - - //$2240-224f BRF - uint8 brf[16]; - - //$2250 MCNT - bool acm; - bool md; - - //$2251,$2252 MA - uint16 ma; - - //$2253,$2254 MB - uint16 mb; - - //$2258 VBD - bool hl; - uint8 vb; - - //$2259-$225b VDA - uint32 va; - uint8 vbit; - - //$2300 SFR - bool cpu_irqfl; - bool chdma_irqfl; - - //$2301 CFR - bool sa1_irqfl; - bool timer_irqfl; - bool dma_irqfl; - bool sa1_nmifl; - - //$2302,$2303 HCR - uint16 hcr; - - //$2304,$2305 VCR - uint16 vcr; - - //$2306-230a MR - uint64 mr; - - //$230b OF - bool overflow; -} mmio; - -void mmio_w2200(uint8); //CCNT -void mmio_w2201(uint8); //SIE -void mmio_w2202(uint8); //SIC -void mmio_w2203(uint8); //CRVL -void mmio_w2204(uint8); //CRVH -void mmio_w2205(uint8); //CNVL -void mmio_w2206(uint8); //CNVH -void mmio_w2207(uint8); //CIVL -void mmio_w2208(uint8); //CIVH -void mmio_w2209(uint8); //SCNT -void mmio_w220a(uint8); //CIE -void mmio_w220b(uint8); //CIC -void mmio_w220c(uint8); //SNVL -void mmio_w220d(uint8); //SNVH -void mmio_w220e(uint8); //SIVL -void mmio_w220f(uint8); //SIVH -void mmio_w2210(uint8); //TMC -void mmio_w2211(uint8); //CTR -void mmio_w2212(uint8); //HCNTL -void mmio_w2213(uint8); //HCNTH -void mmio_w2214(uint8); //VCNTL -void mmio_w2215(uint8); //VCNTH -void mmio_w2220(uint8); //CXB -void mmio_w2221(uint8); //DXB -void mmio_w2222(uint8); //EXB -void mmio_w2223(uint8); //FXB -void mmio_w2224(uint8); //BMAPS -void mmio_w2225(uint8); //BMAP -void mmio_w2226(uint8); //SBWE -void mmio_w2227(uint8); //CBWE -void mmio_w2228(uint8); //BWPA -void mmio_w2229(uint8); //SIWP -void mmio_w222a(uint8); //CIWP -void mmio_w2230(uint8); //DCNT -void mmio_w2231(uint8); //CDMA -void mmio_w2232(uint8); //SDAL -void mmio_w2233(uint8); //SDAH -void mmio_w2234(uint8); //SDAB -void mmio_w2235(uint8); //DDAL -void mmio_w2236(uint8); //DDAH -void mmio_w2237(uint8); //DDAB -void mmio_w2238(uint8); //DTCL -void mmio_w2239(uint8); //DTCH -void mmio_w223f(uint8); //BBF -void mmio_w2240(uint8); //BRF0 -void mmio_w2241(uint8); //BRF1 -void mmio_w2242(uint8); //BRF2 -void mmio_w2243(uint8); //BRF3 -void mmio_w2244(uint8); //BRF4 -void mmio_w2245(uint8); //BRF5 -void mmio_w2246(uint8); //BRF6 -void mmio_w2247(uint8); //BRF7 -void mmio_w2248(uint8); //BRF8 -void mmio_w2249(uint8); //BRF9 -void mmio_w224a(uint8); //BRFA -void mmio_w224b(uint8); //BRFB -void mmio_w224c(uint8); //BRFC -void mmio_w224d(uint8); //BRFD -void mmio_w224e(uint8); //BRFE -void mmio_w224f(uint8); //BRFF -void mmio_w2250(uint8); //MCNT -void mmio_w2251(uint8); //MAL -void mmio_w2252(uint8); //MAH -void mmio_w2253(uint8); //MBL -void mmio_w2254(uint8); //MBH -void mmio_w2258(uint8); //VBD -void mmio_w2259(uint8); //VDAL -void mmio_w225a(uint8); //VDAH -void mmio_w225b(uint8); //VDAB - -uint8 mmio_r2300(); //SFR -uint8 mmio_r2301(); //CFR -uint8 mmio_r2302(); //HCRL -uint8 mmio_r2303(); //HCRH -uint8 mmio_r2304(); //VCRL -uint8 mmio_r2305(); //VCRH -uint8 mmio_r2306(); //MR [00-07] -uint8 mmio_r2307(); //MR [08-15] -uint8 mmio_r2308(); //MR [16-23] -uint8 mmio_r2309(); //MR [24-31] -uint8 mmio_r230a(); //MR [32-40] -uint8 mmio_r230b(); //OF -uint8 mmio_r230c(); //VDPL -uint8 mmio_r230d(); //VDPH -uint8 mmio_r230e(); //VC diff --git a/waterbox/libsnes/bsnes/snes/chip/sa1/sa1.cpp b/waterbox/libsnes/bsnes/snes/chip/sa1/sa1.cpp deleted file mode 100644 index df242a89c0..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/sa1/sa1.cpp +++ /dev/null @@ -1,330 +0,0 @@ -#include - -#define SA1_CPP -namespace SNES { - -SA1 sa1; - -#include "bus/bus.cpp" -#include "dma/dma.cpp" -#include "memory/memory.cpp" -#include "mmio/mmio.cpp" - -void SA1::Enter() { sa1.enter(); } - -void SA1::enter() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - if(mmio.sa1_rdyb || mmio.sa1_resb) { - //SA-1 co-processor is asleep - tick(); - synchronize_cpu(); - continue; - } - - if(status.interrupt_pending) { - status.interrupt_pending = false; - op_irq(); - continue; - } - - (this->*opcode_table[op_readpc()])(); - } -} - -void SA1::op_irq() { - op_read(regs.pc.d); - op_io(); - if(!regs.e) op_writestack(regs.pc.b); - op_writestack(regs.pc.h); - op_writestack(regs.pc.l); - op_writestack(regs.e ? (regs.p & ~0x10) : regs.p); - regs.pc.w = regs.vector; - regs.pc.b = 0x00; - regs.p.i = 1; - regs.p.d = 0; -} - -void SA1::last_cycle() { - if(mmio.sa1_nmi && !mmio.sa1_nmicl) { - status.interrupt_pending = true; - regs.vector = mmio.cnv; - mmio.sa1_nmifl = true; - mmio.sa1_nmicl = 1; - regs.wai = false; - } else if(!regs.p.i) { - if(mmio.timer_irqen && !mmio.timer_irqcl) { - status.interrupt_pending = true; - regs.vector = mmio.civ; - mmio.timer_irqfl = true; - regs.wai = false; - } else if(mmio.dma_irqen && !mmio.dma_irqcl) { - status.interrupt_pending = true; - regs.vector = mmio.civ; - mmio.dma_irqfl = true; - regs.wai = false; - } else if(mmio.sa1_irq && !mmio.sa1_irqcl) { - status.interrupt_pending = true; - regs.vector = mmio.civ; - mmio.sa1_irqfl = true; - regs.wai = false; - } - } -} - -bool SA1::interrupt_pending() { - return status.interrupt_pending; -} - -void SA1::tick() { - step(2); - if(++status.tick_counter == 0) synchronize_cpu(); - - //adjust counters: - //note that internally, status counters are in clocks; - //whereas MMIO register counters are in dots (4 clocks = 1 dot) - if(mmio.hvselb == 0) { - //HV timer - status.hcounter += 2; - if(status.hcounter >= 1364) { - status.hcounter = 0; - if(++status.vcounter >= status.scanlines) status.vcounter = 0; - } - } else { - //linear timer - status.hcounter += 2; - status.vcounter += (status.hcounter >> 11); - status.hcounter &= 0x07ff; - status.vcounter &= 0x01ff; - } - - //test counters for timer IRQ - switch((mmio.ven << 1) + (mmio.hen << 0)) { - case 0: break; - case 1: if(status.hcounter == (mmio.hcnt << 2)) trigger_irq(); break; - case 2: if(status.vcounter == mmio.vcnt && status.hcounter == 0) trigger_irq(); break; - case 3: if(status.vcounter == mmio.hcnt && status.hcounter == (mmio.hcnt << 2)) trigger_irq(); break; - } -} - -void SA1::trigger_irq() { - mmio.timer_irqfl = true; - if(mmio.timer_irqen) mmio.timer_irqcl = 0; -} - -void SA1::init() { - iram.init(); -} - -void SA1::load() { -} - -void SA1::unload() { -} - -void SA1::power() { - regs.a = regs.x = regs.y = 0x0000; - regs.s = 0x01ff; -} - -void SA1::reset() { - create(SA1::Enter, system.cpu_frequency(), 8192); - - cpubwram.dma = false; - for(unsigned addr = 0; addr < iram.size(); addr++) { - iram.write(addr, 0x00); - } - - regs.pc.d = 0x000000; - regs.x.h = 0x00; - regs.y.h = 0x00; - regs.s.h = 0x01; - regs.d = 0x0000; - regs.db = 0x00; - regs.p = 0x34; - regs.e = 1; - regs.mdr = 0x00; - regs.wai = false; - regs.vector = 0x0000; - CPUcore::update_table(); - - status.tick_counter = 0; - - status.interrupt_pending = false; - - status.scanlines = (system.region() == System::Region::NTSC ? 262 : 312); - status.vcounter = 0; - status.hcounter = 0; - - dma.line = 0; - - //$2200 CCNT - mmio.sa1_irq = false; - mmio.sa1_rdyb = false; - mmio.sa1_resb = true; - mmio.sa1_nmi = false; - mmio.smeg = 0; - - //$2201 SIE - mmio.cpu_irqen = false; - mmio.chdma_irqen = false; - - //$2202 SIC - mmio.cpu_irqcl = false; - mmio.chdma_irqcl = false; - - //$2203,$2204 CRV - mmio.crv = 0x0000; - - //$2205,$2206 CNV - mmio.cnv = 0x0000; - - //$2207,$2208 CIV - mmio.civ = 0x0000; - - //$2209 SCNT - mmio.cpu_irq = false; - mmio.cpu_ivsw = false; - mmio.cpu_nvsw = false; - mmio.cmeg = 0; - - //$220a CIE - mmio.sa1_irqen = false; - mmio.timer_irqen = false; - mmio.dma_irqen = false; - mmio.sa1_nmien = false; - - //$220b CIC - mmio.sa1_irqcl = false; - mmio.timer_irqcl = false; - mmio.dma_irqcl = false; - mmio.sa1_nmicl = false; - - //$220c,$220d SNV - mmio.snv = 0x0000; - - //$220e,$220f SIV - mmio.siv = 0x0000; - - //$2210 - mmio.hvselb = false; - mmio.ven = false; - mmio.hen = false; - - //$2212,$2213 HCNT - mmio.hcnt = 0x0000; - - //$2214,$2215 VCNT - mmio.vcnt = 0x0000; - - //$2220-2223 CXB, DXB, EXB, FXB - mmio.cbmode = 1; - mmio.dbmode = 1; - mmio.ebmode = 1; - mmio.fbmode = 1; - - mmio.cb = 0x00; - mmio.db = 0x01; - mmio.eb = 0x00; - mmio.fb = 0x01; - - //$2224 BMAPS - mmio.sbm = 0x00; - - //$2225 BMAP - mmio.sw46 = false; - mmio.cbm = 0x00; - - //$2226 SWBE - mmio.swen = false; - - //$2227 CWBE - mmio.cwen = false; - - //$2228 BWPA - mmio.bwp = 0x0f; - - //$2229 SIWP - mmio.siwp = 0x00; - - //$222a CIWP - mmio.ciwp = 0x00; - - //$2230 DCNT - mmio.dmaen = false; - mmio.dprio = false; - mmio.cden = false; - mmio.cdsel = false; - mmio.dd = 0; - mmio.sd = 0; - - //$2231 CDMA - mmio.chdend = false; - mmio.dmasize = 0; - mmio.dmacb = 0; - - //$2232-$2234 SDA - mmio.dsa = 0x000000; - - //$2235-$2237 DDA - mmio.dda = 0x000000; - - //$2238,$2239 DTC - mmio.dtc = 0x0000; - - //$223f BBF - mmio.bbf = 0; - - //$2240-$224f BRF - for(unsigned i = 0; i < 16; i++) { - mmio.brf[i] = 0x00; - } - - //$2250 MCNT - mmio.acm = 0; - mmio.md = 0; - - //$2251,$2252 MA - mmio.ma = 0x0000; - - //$2253,$2254 MB - mmio.mb = 0x0000; - - //$2258 VBD - mmio.hl = false; - mmio.vb = 16; - - //$2259-$225b - mmio.va = 0x000000; - mmio.vbit = 0; - - //$2300 SFR - mmio.cpu_irqfl = false; - mmio.chdma_irqfl = false; - - //$2301 CFR - mmio.sa1_irqfl = false; - mmio.timer_irqfl = false; - mmio.dma_irqfl = false; - mmio.sa1_nmifl = false; - - //$2302,$2303 HCR - mmio.hcr = 0x0000; - - //$2304,$2305 VCR - mmio.vcr = 0x0000; - - //$2306-$230a MR - mmio.mr = 0; - - //$230b - mmio.overflow = false; -} - -SA1::SA1() : iram(2048, "SA1_IRAM") { -} - -} diff --git a/waterbox/libsnes/bsnes/snes/chip/sa1/sa1.hpp b/waterbox/libsnes/bsnes/snes/chip/sa1/sa1.hpp deleted file mode 100644 index 1f559a97ee..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/sa1/sa1.hpp +++ /dev/null @@ -1,36 +0,0 @@ -class SA1 : public Coprocessor, public CPUcore { -public: - #include "bus/bus.hpp" - #include "dma/dma.hpp" - #include "memory/memory.hpp" - #include "mmio/mmio.hpp" - - struct Status { - uint8 tick_counter; - - bool interrupt_pending; - - uint16 scanlines; - uint16 vcounter; - uint16 hcounter; - } status; - - static void Enter(); - void enter(); - void tick(); - void op_irq(); - - alwaysinline void trigger_irq(); - alwaysinline void last_cycle(); - alwaysinline bool interrupt_pending(); - - void init(); - void load(); - void unload(); - void power(); - void reset(); - - SA1(); -}; - -extern SA1 sa1; diff --git a/waterbox/libsnes/bsnes/snes/chip/sdd1/decomp.cpp b/waterbox/libsnes/bsnes/snes/chip/sdd1/decomp.cpp deleted file mode 100644 index 9975580fc1..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/sdd1/decomp.cpp +++ /dev/null @@ -1,287 +0,0 @@ -//S-DD1 decompression algorithm implementation -//original code written by Andreas Naive (public domain license) -//bsnes port written by byuu - -//note: decompression module does not need to be serialized with bsnes -//this is because decompression only runs during DMA, and bsnes will complete -//any pending DMA transfers prior to serialization. - -//input manager - -void SDD1::Decomp::IM::init(unsigned offset_) { - offset = offset_; - bit_count = 4; -} - -uint8 SDD1::Decomp::IM::get_codeword(uint8 code_length) { - uint8 codeword; - uint8 comp_count; - - codeword = self.rom_read(offset) << bit_count; - bit_count++; - - if(codeword & 0x80) { - codeword |= self.rom_read(offset + 1) >> (9 - bit_count); - bit_count += code_length; - } - - if(bit_count & 0x08) { - offset++; - bit_count &= 0x07; - } - - return codeword; -} - -//golomb-code decoder - -const uint8 SDD1::Decomp::GCD::run_count[] = { - 0x00, 0x00, 0x01, 0x00, 0x03, 0x01, 0x02, 0x00, - 0x07, 0x03, 0x05, 0x01, 0x06, 0x02, 0x04, 0x00, - 0x0f, 0x07, 0x0b, 0x03, 0x0d, 0x05, 0x09, 0x01, - 0x0e, 0x06, 0x0a, 0x02, 0x0c, 0x04, 0x08, 0x00, - 0x1f, 0x0f, 0x17, 0x07, 0x1b, 0x0b, 0x13, 0x03, - 0x1d, 0x0d, 0x15, 0x05, 0x19, 0x09, 0x11, 0x01, - 0x1e, 0x0e, 0x16, 0x06, 0x1a, 0x0a, 0x12, 0x02, - 0x1c, 0x0c, 0x14, 0x04, 0x18, 0x08, 0x10, 0x00, - 0x3f, 0x1f, 0x2f, 0x0f, 0x37, 0x17, 0x27, 0x07, - 0x3b, 0x1b, 0x2b, 0x0b, 0x33, 0x13, 0x23, 0x03, - 0x3d, 0x1d, 0x2d, 0x0d, 0x35, 0x15, 0x25, 0x05, - 0x39, 0x19, 0x29, 0x09, 0x31, 0x11, 0x21, 0x01, - 0x3e, 0x1e, 0x2e, 0x0e, 0x36, 0x16, 0x26, 0x06, - 0x3a, 0x1a, 0x2a, 0x0a, 0x32, 0x12, 0x22, 0x02, - 0x3c, 0x1c, 0x2c, 0x0c, 0x34, 0x14, 0x24, 0x04, - 0x38, 0x18, 0x28, 0x08, 0x30, 0x10, 0x20, 0x00, - 0x7f, 0x3f, 0x5f, 0x1f, 0x6f, 0x2f, 0x4f, 0x0f, - 0x77, 0x37, 0x57, 0x17, 0x67, 0x27, 0x47, 0x07, - 0x7b, 0x3b, 0x5b, 0x1b, 0x6b, 0x2b, 0x4b, 0x0b, - 0x73, 0x33, 0x53, 0x13, 0x63, 0x23, 0x43, 0x03, - 0x7d, 0x3d, 0x5d, 0x1d, 0x6d, 0x2d, 0x4d, 0x0d, - 0x75, 0x35, 0x55, 0x15, 0x65, 0x25, 0x45, 0x05, - 0x79, 0x39, 0x59, 0x19, 0x69, 0x29, 0x49, 0x09, - 0x71, 0x31, 0x51, 0x11, 0x61, 0x21, 0x41, 0x01, - 0x7e, 0x3e, 0x5e, 0x1e, 0x6e, 0x2e, 0x4e, 0x0e, - 0x76, 0x36, 0x56, 0x16, 0x66, 0x26, 0x46, 0x06, - 0x7a, 0x3a, 0x5a, 0x1a, 0x6a, 0x2a, 0x4a, 0x0a, - 0x72, 0x32, 0x52, 0x12, 0x62, 0x22, 0x42, 0x02, - 0x7c, 0x3c, 0x5c, 0x1c, 0x6c, 0x2c, 0x4c, 0x0c, - 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, - 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08, - 0x70, 0x30, 0x50, 0x10, 0x60, 0x20, 0x40, 0x00, -}; - -void SDD1::Decomp::GCD::get_run_count(uint8 code_number, uint8 &mps_count, bool &lps_index) { - uint8 codeword = self.im.get_codeword(code_number); - - if(codeword & 0x80) { - lps_index = 1; - mps_count = run_count[codeword >> (code_number ^ 0x07)]; - } else { - mps_count = 1 << code_number; - } -} - -//bits generator - -void SDD1::Decomp::BG::init() { - mps_count = 0; - lps_index = 0; -} - -uint8 SDD1::Decomp::BG::get_bit(bool &end_of_run) { - if(!(mps_count || lps_index)) self.gcd.get_run_count(code_number, mps_count, lps_index); - - uint8 bit; - if(mps_count) { - bit = 0; - mps_count--; - } else { - bit = 1; - lps_index = 0; - } - - end_of_run = !(mps_count || lps_index); - return bit; -} - -//probability estimation module - -const SDD1::Decomp::PEM::State SDD1::Decomp::PEM::evolution_table[33] = { - { 0, 25, 25 }, - { 0, 2, 1 }, - { 0, 3, 1 }, - { 0, 4, 2 }, - { 0, 5, 3 }, - { 1, 6, 4 }, - { 1, 7, 5 }, - { 1, 8, 6 }, - { 1, 9, 7 }, - { 2, 10, 8 }, - { 2, 11, 9 }, - { 2, 12, 10 }, - { 2, 13, 11 }, - { 3, 14, 12 }, - { 3, 15, 13 }, - { 3, 16, 14 }, - { 3, 17, 15 }, - { 4, 18, 16 }, - { 4, 19, 17 }, - { 5, 20, 18 }, - { 5, 21, 19 }, - { 6, 22, 20 }, - { 6, 23, 21 }, - { 7, 24, 22 }, - { 7, 24, 23 }, - { 0, 26, 1 }, - { 1, 27, 2 }, - { 2, 28, 4 }, - { 3, 29, 8 }, - { 4, 30, 12 }, - { 5, 31, 16 }, - { 6, 32, 18 }, - { 7, 24, 22 }, -}; - -void SDD1::Decomp::PEM::init() { - for(unsigned i = 0; i < 32; i++) { - context_info[i].status = 0; - context_info[i].mps = 0; - } -} - -uint8 SDD1::Decomp::PEM::get_bit(uint8 context) { - ContextInfo &info = context_info[context]; - uint8 current_status = info.status; - uint8 current_mps = info.mps; - const State &s = SDD1::Decomp::PEM::evolution_table[current_status]; - - uint8 bit; - bool end_of_run; - switch(s.code_number) { - case 0: bit = self.bg0.get_bit(end_of_run); break; - case 1: bit = self.bg1.get_bit(end_of_run); break; - case 2: bit = self.bg2.get_bit(end_of_run); break; - case 3: bit = self.bg3.get_bit(end_of_run); break; - case 4: bit = self.bg4.get_bit(end_of_run); break; - case 5: bit = self.bg5.get_bit(end_of_run); break; - case 6: bit = self.bg6.get_bit(end_of_run); break; - case 7: bit = self.bg7.get_bit(end_of_run); break; - } - - if(end_of_run) { - if(bit) { - if(!(current_status & 0xfe)) info.mps ^= 0x01; - info.status = s.next_if_lps; - } else { - info.status = s.next_if_mps; - } - } - - return bit ^ current_mps; -} - -//context model - -void SDD1::Decomp::CM::init(unsigned offset) { - bitplanes_info = self.rom_read(offset) & 0xc0; - context_bits_info = self.rom_read(offset) & 0x30; - bit_number = 0; - for(unsigned i = 0; i < 8; i++) previous_bitplane_bits[i] = 0; - switch(bitplanes_info) { - case 0x00: current_bitplane = 1; break; - case 0x40: current_bitplane = 7; break; - case 0x80: current_bitplane = 3; break; - } -} - -uint8 SDD1::Decomp::CM::get_bit() { - switch(bitplanes_info) { - case 0x00: - current_bitplane ^= 0x01; - break; - case 0x40: - current_bitplane ^= 0x01; - if(!(bit_number & 0x7f)) current_bitplane = ((current_bitplane + 2) & 0x07); - break; - case 0x80: - current_bitplane ^= 0x01; - if(!(bit_number & 0x7f)) current_bitplane ^= 0x02; - break; - case 0xc0: - current_bitplane = bit_number & 0x07; - break; - } - - uint16 &context_bits = previous_bitplane_bits[current_bitplane]; - uint8 current_context = (current_bitplane & 0x01) << 4; - switch(context_bits_info) { - case 0x00: current_context |= ((context_bits & 0x01c0) >> 5) | (context_bits & 0x0001); break; - case 0x10: current_context |= ((context_bits & 0x0180) >> 5) | (context_bits & 0x0001); break; - case 0x20: current_context |= ((context_bits & 0x00c0) >> 5) | (context_bits & 0x0001); break; - case 0x30: current_context |= ((context_bits & 0x0180) >> 5) | (context_bits & 0x0003); break; - } - - uint8 bit = self.pem.get_bit(current_context); - context_bits <<= 1; - context_bits |= bit; - bit_number++; - return bit; -} - -//output logic - -void SDD1::Decomp::OL::init(unsigned offset) { - bitplanes_info = self.rom_read(offset) & 0xc0; - r0 = 0x01; -} - -uint8 SDD1::Decomp::OL::decompress() { - switch(bitplanes_info) { - case 0x00: case 0x40: case 0x80: - if(r0 == 0) { - r0 = ~r0; - return r2; - } - for(r0 = 0x80, r1 = 0, r2 = 0; r0; r0 >>= 1) { - if(self.cm.get_bit()) r1 |= r0; - if(self.cm.get_bit()) r2 |= r0; - } - return r1; - case 0xc0: - for(r0 = 0x01, r1 = 0; r0; r0 <<= 1) { - if(self.cm.get_bit()) r1 |= r0; - } - return r1; - } -} - -//core - -void SDD1::Decomp::init(unsigned offset) { - im.init(offset); - bg0.init(); - bg1.init(); - bg2.init(); - bg3.init(); - bg4.init(); - bg5.init(); - bg6.init(); - bg7.init(); - pem.init(); - cm.init(offset); - ol.init(offset); -} - -uint8 SDD1::Decomp::read() { - return ol.decompress(); -} - -uint8 SDD1::Decomp::rom_read(unsigned offset) { - return sdd1.rom_read(offset); -} - -SDD1::Decomp::Decomp() : im(*this), gcd(*this), - bg0(*this, 0), bg1(*this, 1), bg2(*this, 2), bg3(*this, 3), - bg4(*this, 4), bg5(*this, 5), bg6(*this, 6), bg7(*this, 7), - pem(*this), cm(*this), ol(*this) { -} diff --git a/waterbox/libsnes/bsnes/snes/chip/sdd1/decomp.hpp b/waterbox/libsnes/bsnes/snes/chip/sdd1/decomp.hpp deleted file mode 100644 index 6c83d1d937..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/sdd1/decomp.hpp +++ /dev/null @@ -1,82 +0,0 @@ -struct Decomp { - struct IM { //input manager - Decomp &self; - void init(unsigned offset); - uint8 get_codeword(uint8 code_length); - IM(SDD1::Decomp &self) : self(self) {} - private: - unsigned offset; - unsigned bit_count; - }; - - struct GCD { //golomb-code decoder - Decomp &self; - static const uint8 run_count[256]; - void get_run_count(uint8 code_number, uint8 &mps_count, bool &lps_index); - GCD(SDD1::Decomp &self) : self(self) {} - }; - - struct BG { //bits generator - Decomp &self; - void init(); - uint8 get_bit(bool &end_of_run); - BG(SDD1::Decomp &self, uint8 code_number) : self(self), code_number(code_number) {} - private: - const uint8 code_number; - uint8 mps_count; - bool lps_index; - }; - - struct PEM { //probability estimation module - Decomp &self; - void init(); - uint8 get_bit(uint8 context); - PEM(SDD1::Decomp &self) : self(self) {} - private: - struct State { - uint8 code_number; - uint8 next_if_mps; - uint8 next_if_lps; - }; - static const State evolution_table[33]; - struct ContextInfo { - uint8 status; - uint8 mps; - } context_info[32]; - }; - - struct CM { //context model - Decomp &self; - void init(unsigned offset); - uint8 get_bit(); - CM(SDD1::Decomp &self) : self(self) {} - private: - uint8 bitplanes_info; - uint8 context_bits_info; - uint8 bit_number; - uint8 current_bitplane; - uint16 previous_bitplane_bits[8]; - }; - - struct OL { //output logic - Decomp &self; - void init(unsigned offset); - uint8 decompress(); - OL(SDD1::Decomp &self) : self(self) {} - private: - uint8 bitplanes_info; - uint8 r0, r1, r2; - }; - - void init(unsigned offset); - uint8 read(); - uint8 rom_read(unsigned offset); - Decomp(); - - IM im; - GCD gcd; - BG bg0, bg1, bg2, bg3, bg4, bg5, bg6, bg7; - PEM pem; - CM cm; - OL ol; -}; diff --git a/waterbox/libsnes/bsnes/snes/chip/sdd1/sdd1.cpp b/waterbox/libsnes/bsnes/snes/chip/sdd1/sdd1.cpp deleted file mode 100644 index 01048e5ede..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/sdd1/sdd1.cpp +++ /dev/null @@ -1,151 +0,0 @@ -#include - -#define SDD1_CPP -namespace SNES { - -SDD1 sdd1; - -#include "decomp.cpp" - -void SDD1::init() { -} - -void SDD1::load() { - //hook S-CPU DMA MMIO registers to gather information for struct dma[]; - //buffer address and transfer size information for use in SDD1::mcu_read() - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, { &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 }); - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, { &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 }); -} - -void SDD1::unload() { -} - -void SDD1::power() { -} - -void SDD1::reset() { - sdd1_enable = 0x00; - xfer_enable = 0x00; - dma_ready = false; - - mmc[0] = 0 << 20; - mmc[1] = 1 << 20; - mmc[2] = 2 << 20; - mmc[3] = 3 << 20; - - for(unsigned i = 0; i < 8; i++) { - dma[i].addr = 0; - dma[i].size = 0; - } -} - -uint8 SDD1::mmio_read(unsigned addr) { - addr &= 0xffff; - - if((addr & 0x4380) == 0x4300) { - return cpu.mmio_read(addr); - } - - switch(addr) { - case 0x4804: return mmc[0] >> 20; - case 0x4805: return mmc[1] >> 20; - case 0x4806: return mmc[2] >> 20; - case 0x4807: return mmc[3] >> 20; - } - - return cpu.regs.mdr; -} - -void SDD1::mmio_write(unsigned addr, uint8 data) { - addr &= 0xffff; - - if((addr & 0x4380) == 0x4300) { - unsigned channel = (addr >> 4) & 7; - switch(addr & 15) { - case 2: dma[channel].addr = (dma[channel].addr & 0xffff00) + (data << 0); break; - case 3: dma[channel].addr = (dma[channel].addr & 0xff00ff) + (data << 8); break; - case 4: dma[channel].addr = (dma[channel].addr & 0x00ffff) + (data << 16); break; - - case 5: dma[channel].size = (dma[channel].size & 0xff00) + (data << 0); break; - case 6: dma[channel].size = (dma[channel].size & 0x00ff) + (data << 8); break; - } - return cpu.mmio_write(addr, data); - } - - switch(addr) { - case 0x4800: sdd1_enable = data; break; - case 0x4801: xfer_enable = data; break; - - case 0x4804: mmc[0] = data << 20; break; - case 0x4805: mmc[1] = data << 20; break; - case 0x4806: mmc[2] = data << 20; break; - case 0x4807: mmc[3] = data << 20; break; - } -} - -uint8 SDD1::rom_read(unsigned addr) { - auto myaddr = mmc[(addr >> 20) & 3] + (addr & 0x0fffff); - cdlInfo.set(eCDLog_AddrType_CARTROM, myaddr); - return cartridge.rom.read(myaddr); -} - -//SDD1::mcu_read() is mapped to $c0-ff:0000-ffff -//the design is meant to be as close to the hardware design as possible, thus this code -//avoids adding S-DD1 hooks inside S-CPU::DMA emulation. -// -//the real S-DD1 cannot see $420b (DMA enable) writes, as they are not placed on the bus. -//however, $43x0-$43xf writes (DMAx channel settings) most likely do appear on the bus. -//the S-DD1 also requires fixed addresses for transfers, which wouldn't be necessary if -//it could see $420b writes (eg it would know when the transfer should begin.) -// -//the hardware needs a way to distinguish program code after $4801 writes from DMA -//decompression that follows soon after. -// -//the only plausible design for hardware would be for the S-DD1 to spy on DMAx settings, -//and begin spooling decompression on writes to $4801 that activate a channel. after that, -//it feeds decompressed data only when the ROM read address matches the DMA channel address. -// -//the actual S-DD1 transfer can occur on any channel, but it is most likely limited to -//one transfer per $420b write (for spooling purposes). however, this is not known for certain. -uint8 SDD1::mcu_read(unsigned addr) { - if(sdd1_enable & xfer_enable) { - //at least one channel has S-DD1 decompression enabled ... - for(unsigned i = 0; i < 8; i++) { - if(sdd1_enable & xfer_enable & (1 << i)) { - //S-DD1 always uses fixed transfer mode, so address will not change during transfer - if(addr == dma[i].addr) { - if(!dma_ready) { - //prepare streaming decompression - decomp.init(addr); - dma_ready = true; - } - - //fetch a decompressed byte; once finished, disable channel and invalidate buffer - uint8 data = decomp.read(); - if(--dma[i].size == 0) { - dma_ready = false; - xfer_enable &= ~(1 << i); - } - - return data; - } //address matched - } //channel enabled - } //channel loop - } //S-DD1 decompressor enabled - - //S-DD1 decompression mode inactive; return ROM data - auto myaddr = mmc[(addr >> 20) & 3] + (addr & 0x0fffff); - cdlInfo.set(eCDLog_AddrType_CARTROM, myaddr); - return cartridge.rom.read(myaddr); -} - -void SDD1::mcu_write(unsigned addr, uint8 data) { -} - -SDD1::SDD1() { -} - -SDD1::~SDD1() { -} - -} diff --git a/waterbox/libsnes/bsnes/snes/chip/sdd1/sdd1.hpp b/waterbox/libsnes/bsnes/snes/chip/sdd1/sdd1.hpp deleted file mode 100644 index 1a0fc335a0..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/sdd1/sdd1.hpp +++ /dev/null @@ -1,35 +0,0 @@ -class SDD1 { -public: - void init(); - void load(); - void unload(); - void power(); - void reset(); - - uint8 mmio_read(unsigned addr); - void mmio_write(unsigned addr, uint8 data); - - uint8 rom_read(unsigned addr); - uint8 mcu_read(unsigned addr); - void mcu_write(unsigned addr, uint8 data); - - SDD1(); - ~SDD1(); - -private: - uint8 sdd1_enable; //channel bit-mask - uint8 xfer_enable; //channel bit-mask - bool dma_ready; //used to initialize decompression module - unsigned mmc[4]; //memory map controller ROM indices - - struct { - unsigned addr; //$43x2-$43x4 -- DMA transfer address - uint16 size; //$43x5-$43x6 -- DMA transfer size - } dma[8]; - -public: - #include "decomp.hpp" - Decomp decomp; -}; - -extern SDD1 sdd1; diff --git a/waterbox/libsnes/bsnes/snes/chip/spc7110/decomp.cpp b/waterbox/libsnes/bsnes/snes/chip/spc7110/decomp.cpp deleted file mode 100644 index dd4db59864..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/spc7110/decomp.cpp +++ /dev/null @@ -1,500 +0,0 @@ -#ifdef SPC7110_CPP - -uint8 SPC7110::Decomp::read() { - if(decomp_buffer_length == 0) { - //decompress at least (decomp_buffer_size / 2) bytes to the buffer - switch(decomp_mode) { - case 0: mode0(false); break; - case 1: mode1(false); break; - case 2: mode2(false); break; - default: return 0x00; - } - } - - uint8 data = decomp_buffer[decomp_buffer_rdoffset++]; - decomp_buffer_rdoffset &= decomp_buffer_size - 1; - decomp_buffer_length--; - return data; -} - -void SPC7110::Decomp::write(uint8 data) { - decomp_buffer[decomp_buffer_wroffset++] = data; - decomp_buffer_wroffset &= decomp_buffer_size - 1; - decomp_buffer_length++; -} - -uint8 SPC7110::Decomp::dataread() { - unsigned size = cartridge.rom.size() - spc7110.data_rom_offset; - while(decomp_offset >= size) decomp_offset -= size; - auto myaddr = spc7110.data_rom_offset + decomp_offset++; - cdlInfo.set(eCDLog_AddrType_CARTROM, myaddr); - return cartridge.rom.read(myaddr); -} - -void SPC7110::Decomp::init(unsigned mode, unsigned offset, unsigned index) { - decomp_mode = mode; - decomp_offset = offset; - - decomp_buffer_rdoffset = 0; - decomp_buffer_wroffset = 0; - decomp_buffer_length = 0; - - //reset context states - for(unsigned i = 0; i < 32; i++) { - context[i].index = 0; - context[i].invert = 0; - } - - switch(decomp_mode) { - case 0: mode0(true); break; - case 1: mode1(true); break; - case 2: mode2(true); break; - } - - //decompress up to requested output data index - while(index--) read(); -} - -// - -void SPC7110::Decomp::mode0(bool init) { - static uint8 val, in, span; - static int out, inverts, lps, in_count; - - if(init == true) { - out = inverts = lps = 0; - span = 0xff; - val = dataread(); - in = dataread(); - in_count = 8; - return; - } - - while(decomp_buffer_length < (decomp_buffer_size >> 1)) { - for(unsigned bit = 0; bit < 8; bit++) { - //get context - uint8 mask = (1 << (bit & 3)) - 1; - uint8 con = mask + ((inverts & mask) ^ (lps & mask)); - if(bit > 3) con += 15; - - //get prob and mps - unsigned prob = probability(con); - unsigned mps = (((out >> 15) & 1) ^ context[con].invert); - - //get bit - unsigned flag_lps; - if(val <= span - prob) { //mps - span = span - prob; - out = (out << 1) + mps; - flag_lps = 0; - } else { //lps - val = val - (span - (prob - 1)); - span = prob - 1; - out = (out << 1) + 1 - mps; - flag_lps = 1; - } - - //renormalize - unsigned shift = 0; - while(span < 0x7f) { - shift++; - - span = (span << 1) + 1; - val = (val << 1) + (in >> 7); - - in <<= 1; - if(--in_count == 0) { - in = dataread(); - in_count = 8; - } - } - - //update processing info - lps = (lps << 1) + flag_lps; - inverts = (inverts << 1) + context[con].invert; - - //update context state - if(flag_lps & toggle_invert(con)) context[con].invert ^= 1; - if(flag_lps) context[con].index = next_lps(con); - else if(shift) context[con].index = next_mps(con); - } - - //save byte - write(out); - } -} - -void SPC7110::Decomp::mode1(bool init) { - static int pixelorder[4], realorder[4]; - static uint8 in, val, span; - static int out, inverts, lps, in_count; - - if(init == true) { - for(unsigned i = 0; i < 4; i++) pixelorder[i] = i; - out = inverts = lps = 0; - span = 0xff; - val = dataread(); - in = dataread(); - in_count = 8; - return; - } - - while(decomp_buffer_length < (decomp_buffer_size >> 1)) { - for(unsigned pixel = 0; pixel < 8; pixel++) { - //get first symbol context - unsigned a = ((out >> (1 * 2)) & 3); - unsigned b = ((out >> (7 * 2)) & 3); - unsigned c = ((out >> (8 * 2)) & 3); - unsigned con = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c); - - //update pixel order - unsigned m, n; - for(m = 0; m < 4; m++) if(pixelorder[m] == a) break; - for(n = m; n > 0; n--) pixelorder[n] = pixelorder[n - 1]; - pixelorder[0] = a; - - //calculate the real pixel order - for(m = 0; m < 4; m++) realorder[m] = pixelorder[m]; - - //rotate reference pixel c value to top - for(m = 0; m < 4; m++) if(realorder[m] == c) break; - for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; - realorder[0] = c; - - //rotate reference pixel b value to top - for(m = 0; m < 4; m++) if(realorder[m] == b) break; - for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; - realorder[0] = b; - - //rotate reference pixel a value to top - for(m = 0; m < 4; m++) if(realorder[m] == a) break; - for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; - realorder[0] = a; - - //get 2 symbols - for(unsigned bit = 0; bit < 2; bit++) { - //get prob - unsigned prob = probability(con); - - //get symbol - unsigned flag_lps; - if(val <= span - prob) { //mps - span = span - prob; - flag_lps = 0; - } else { //lps - val = val - (span - (prob - 1)); - span = prob - 1; - flag_lps = 1; - } - - //renormalize - unsigned shift = 0; - while(span < 0x7f) { - shift++; - - span = (span << 1) + 1; - val = (val << 1) + (in >> 7); - - in <<= 1; - if(--in_count == 0) { - in = dataread(); - in_count = 8; - } - } - - //update processing info - lps = (lps << 1) + flag_lps; - inverts = (inverts << 1) + context[con].invert; - - //update context state - if(flag_lps & toggle_invert(con)) context[con].invert ^= 1; - if(flag_lps) context[con].index = next_lps(con); - else if(shift) context[con].index = next_mps(con); - - //get next context - con = 5 + (con << 1) + ((lps ^ inverts) & 1); - } - - //get pixel - b = realorder[(lps ^ inverts) & 3]; - out = (out << 2) + b; - } - - //turn pixel data into bitplanes - unsigned data = deinterleave_2x8(out); - write(data >> 8); - write(data >> 0); - } -} - -void SPC7110::Decomp::mode2(bool init) { - static int pixelorder[16], realorder[16]; - static uint8 bitplanebuffer[16], buffer_index; - static uint8 in, val, span; - static int out0, out1, inverts, lps, in_count; - - if(init == true) { - for(unsigned i = 0; i < 16; i++) pixelorder[i] = i; - buffer_index = 0; - out0 = out1 = inverts = lps = 0; - span = 0xff; - val = dataread(); - in = dataread(); - in_count = 8; - return; - } - - while(decomp_buffer_length < (decomp_buffer_size >> 1)) { - for(unsigned pixel = 0; pixel < 8; pixel++) { - //get first symbol context - unsigned a = ((out0 >> (0 * 4)) & 15); - unsigned b = ((out0 >> (7 * 4)) & 15); - unsigned c = ((out1 >> (0 * 4)) & 15); - unsigned con = 0; - unsigned refcon = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c); - - //update pixel order - unsigned m, n; - for(m = 0; m < 16; m++) if(pixelorder[m] == a) break; - for(n = m; n > 0; n--) pixelorder[n] = pixelorder[n - 1]; - pixelorder[0] = a; - - //calculate the real pixel order - for(m = 0; m < 16; m++) realorder[m] = pixelorder[m]; - - //rotate reference pixel c value to top - for(m = 0; m < 16; m++) if(realorder[m] == c) break; - for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; - realorder[0] = c; - - //rotate reference pixel b value to top - for(m = 0; m < 16; m++) if(realorder[m] == b) break; - for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; - realorder[0] = b; - - //rotate reference pixel a value to top - for(m = 0; m < 16; m++) if(realorder[m] == a) break; - for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; - realorder[0] = a; - - //get 4 symbols - for(unsigned bit = 0; bit < 4; bit++) { - //get prob - unsigned prob = probability(con); - - //get symbol - unsigned flag_lps; - if(val <= span - prob) { //mps - span = span - prob; - flag_lps = 0; - } else { //lps - val = val - (span - (prob - 1)); - span = prob - 1; - flag_lps = 1; - } - - //renormalize - unsigned shift = 0; - while(span < 0x7f) { - shift++; - - span = (span << 1) + 1; - val = (val << 1) + (in >> 7); - - in <<= 1; - if(--in_count == 0) { - in = dataread(); - in_count = 8; - } - } - - //update processing info - lps = (lps << 1) + flag_lps; - unsigned invertbit = context[con].invert; - inverts = (inverts << 1) + invertbit; - - //update context state - if(flag_lps & toggle_invert(con)) context[con].invert ^= 1; - if(flag_lps) context[con].index = next_lps(con); - else if(shift) context[con].index = next_mps(con); - - //get next context - con = mode2_context_table[con][flag_lps ^ invertbit] + (con == 1 ? refcon : 0); - } - - //get pixel - b = realorder[(lps ^ inverts) & 0x0f]; - out1 = (out1 << 4) + ((out0 >> 28) & 0x0f); - out0 = (out0 << 4) + b; - } - - //convert pixel data into bitplanes - unsigned data = deinterleave_4x8(out0); - write(data >> 24); - write(data >> 16); - bitplanebuffer[buffer_index++] = data >> 8; - bitplanebuffer[buffer_index++] = data >> 0; - - if(buffer_index == 16) { - for(unsigned i = 0; i < 16; i++) write(bitplanebuffer[i]); - buffer_index = 0; - } - } -} - -// - -const uint8 SPC7110::Decomp::evolution_table[53][4] = { -//{ prob, nextlps, nextmps, toggle invert }, - - { 0x5a, 1, 1, 1 }, - { 0x25, 6, 2, 0 }, - { 0x11, 8, 3, 0 }, - { 0x08, 10, 4, 0 }, - { 0x03, 12, 5, 0 }, - { 0x01, 15, 5, 0 }, - - { 0x5a, 7, 7, 1 }, - { 0x3f, 19, 8, 0 }, - { 0x2c, 21, 9, 0 }, - { 0x20, 22, 10, 0 }, - { 0x17, 23, 11, 0 }, - { 0x11, 25, 12, 0 }, - { 0x0c, 26, 13, 0 }, - { 0x09, 28, 14, 0 }, - { 0x07, 29, 15, 0 }, - { 0x05, 31, 16, 0 }, - { 0x04, 32, 17, 0 }, - { 0x03, 34, 18, 0 }, - { 0x02, 35, 5, 0 }, - - { 0x5a, 20, 20, 1 }, - { 0x48, 39, 21, 0 }, - { 0x3a, 40, 22, 0 }, - { 0x2e, 42, 23, 0 }, - { 0x26, 44, 24, 0 }, - { 0x1f, 45, 25, 0 }, - { 0x19, 46, 26, 0 }, - { 0x15, 25, 27, 0 }, - { 0x11, 26, 28, 0 }, - { 0x0e, 26, 29, 0 }, - { 0x0b, 27, 30, 0 }, - { 0x09, 28, 31, 0 }, - { 0x08, 29, 32, 0 }, - { 0x07, 30, 33, 0 }, - { 0x05, 31, 34, 0 }, - { 0x04, 33, 35, 0 }, - { 0x04, 33, 36, 0 }, - { 0x03, 34, 37, 0 }, - { 0x02, 35, 38, 0 }, - { 0x02, 36, 5, 0 }, - - { 0x58, 39, 40, 1 }, - { 0x4d, 47, 41, 0 }, - { 0x43, 48, 42, 0 }, - { 0x3b, 49, 43, 0 }, - { 0x34, 50, 44, 0 }, - { 0x2e, 51, 45, 0 }, - { 0x29, 44, 46, 0 }, - { 0x25, 45, 24, 0 }, - - { 0x56, 47, 48, 1 }, - { 0x4f, 47, 49, 0 }, - { 0x47, 48, 50, 0 }, - { 0x41, 49, 51, 0 }, - { 0x3c, 50, 52, 0 }, - { 0x37, 51, 43, 0 }, -}; - -const uint8 SPC7110::Decomp::mode2_context_table[32][2] = { -//{ next 0, next 1 }, - - { 1, 2 }, - - { 3, 8 }, - { 13, 14 }, - - { 15, 16 }, - { 17, 18 }, - { 19, 20 }, - { 21, 22 }, - { 23, 24 }, - { 25, 26 }, - { 25, 26 }, - { 25, 26 }, - { 25, 26 }, - { 25, 26 }, - { 27, 28 }, - { 29, 30 }, - - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - - { 31, 31 }, -}; - -uint8 SPC7110::Decomp::probability (unsigned n) { return evolution_table[context[n].index][0]; } -uint8 SPC7110::Decomp::next_lps (unsigned n) { return evolution_table[context[n].index][1]; } -uint8 SPC7110::Decomp::next_mps (unsigned n) { return evolution_table[context[n].index][2]; } -bool SPC7110::Decomp::toggle_invert(unsigned n) { return evolution_table[context[n].index][3]; } - -unsigned SPC7110::Decomp::deinterleave_2x8(unsigned data) { - //reverse morton lookup: de-interleave two 8-bit values - //15, 13, 11, 9, 7, 5, 3, 1 -> 15- 8 - //14, 12, 10, 8, 6, 4, 2, 0 -> 7- 0 - unsigned result = 0; - for(unsigned mask = 1u << 15; mask; mask >>= 2) result = (result << 1) | (bool)(data & mask); - for(unsigned mask = 1u << 14; mask; mask >>= 2) result = (result << 1) | (bool)(data & mask); - return result; -} - -unsigned SPC7110::Decomp::deinterleave_4x8(unsigned data) { - //reverse morton lookup: de-interleave four 8-bit values - //31, 27, 23, 19, 15, 11, 7, 3 -> 31-24 - //30, 26, 22, 18, 14, 10, 6, 2 -> 23-16 - //29, 25, 21, 17, 13, 9, 5, 1 -> 15- 8 - //28, 24, 20, 16, 12, 8, 4, 0 -> 7- 0 - unsigned result = 0; - for(unsigned mask = 1u << 31; mask; mask >>= 4) result = (result << 1) | (bool)(data & mask); - for(unsigned mask = 1u << 30; mask; mask >>= 4) result = (result << 1) | (bool)(data & mask); - for(unsigned mask = 1u << 29; mask; mask >>= 4) result = (result << 1) | (bool)(data & mask); - for(unsigned mask = 1u << 28; mask; mask >>= 4) result = (result << 1) | (bool)(data & mask); - return result; -} - -// - -void SPC7110::Decomp::reset() { - //mode 3 is invalid; this is treated as a special case to always return 0x00 - //set to mode 3 so that reading decomp port before starting first decomp will return 0x00 - decomp_mode = 3; - - decomp_buffer_rdoffset = 0; - decomp_buffer_wroffset = 0; - decomp_buffer_length = 0; -} - -SPC7110::Decomp::Decomp() { - decomp_buffer = new uint8_t[decomp_buffer_size]; - reset(); -} - -SPC7110::Decomp::~Decomp() { - delete[] decomp_buffer; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/spc7110/decomp.hpp b/waterbox/libsnes/bsnes/snes/chip/spc7110/decomp.hpp deleted file mode 100644 index 41b2924b10..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/spc7110/decomp.hpp +++ /dev/null @@ -1,43 +0,0 @@ -class Decomp { -public: - uint8 read(); - void init(unsigned mode, unsigned offset, unsigned index); - void reset(); - - Decomp(); - ~Decomp(); - -private: - unsigned decomp_mode; - unsigned decomp_offset; - - //read() will spool chunks half the size of decomp_buffer_size - enum { decomp_buffer_size = 64 }; //must be >= 64, and must be a power of two - uint8 *decomp_buffer; - unsigned decomp_buffer_rdoffset; - unsigned decomp_buffer_wroffset; - unsigned decomp_buffer_length; - - void write(uint8 data); - uint8 dataread(); - - void mode0(bool init); - void mode1(bool init); - void mode2(bool init); - - static const uint8 evolution_table[53][4]; - static const uint8 mode2_context_table[32][2]; - - struct ContextState { - uint8 index; - uint8 invert; - } context[32]; - - uint8 probability(unsigned n); - uint8 next_lps(unsigned n); - uint8 next_mps(unsigned n); - bool toggle_invert(unsigned n); - - unsigned deinterleave_2x8(unsigned data); - unsigned deinterleave_4x8(unsigned data); -}; diff --git a/waterbox/libsnes/bsnes/snes/chip/spc7110/spc7110.cpp b/waterbox/libsnes/bsnes/snes/chip/spc7110/spc7110.cpp deleted file mode 100644 index dc72258167..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/spc7110/spc7110.cpp +++ /dev/null @@ -1,704 +0,0 @@ -#include - -#define SPC7110_CPP -namespace SNES { - -SPC7110 spc7110; - -#include "decomp.cpp" - -const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - -void SPC7110::init() { -} - -void SPC7110::load() { - for(unsigned n = 0; n < 20; n++) rtc[n] = 0xff; - if(cartridge.has_spc7110rtc()) cartridge.nvram.append({ "program.rtc", rtc, 20 }); -} - -void SPC7110::unload() { -} - -void SPC7110::power() { -} - -void SPC7110::reset() { - r4801 = 0x00; - r4802 = 0x00; - r4803 = 0x00; - r4804 = 0x00; - r4805 = 0x00; - r4806 = 0x00; - r4807 = 0x00; - r4808 = 0x00; - r4809 = 0x00; - r480a = 0x00; - r480b = 0x00; - r480c = 0x00; - - decomp.reset(); - - r4811 = 0x00; - r4812 = 0x00; - r4813 = 0x00; - r4814 = 0x00; - r4815 = 0x00; - r4816 = 0x00; - r4817 = 0x00; - r4818 = 0x00; - - r481x = 0x00; - r4814_latch = false; - r4815_latch = false; - - r4820 = 0x00; - r4821 = 0x00; - r4822 = 0x00; - r4823 = 0x00; - r4824 = 0x00; - r4825 = 0x00; - r4826 = 0x00; - r4827 = 0x00; - r4828 = 0x00; - r4829 = 0x00; - r482a = 0x00; - r482b = 0x00; - r482c = 0x00; - r482d = 0x00; - r482e = 0x00; - r482f = 0x00; - - r4830 = 0x00; - mmio_write(0x4831, 0); - mmio_write(0x4832, 1); - mmio_write(0x4833, 2); - r4834 = 0x00; - - r4840 = 0x00; - r4841 = 0x00; - r4842 = 0x00; - - if(cartridge.has_spc7110rtc()) { - rtc_state = RTCS_Inactive; - rtc_mode = RTCM_Linear; - rtc_index = 0; - } -} - -unsigned SPC7110::datarom_addr(unsigned addr) { - unsigned size = cartridge.rom.size() - data_rom_offset; - while(addr >= size) addr -= size; - return data_rom_offset + addr; -} - -unsigned SPC7110::data_pointer() { return r4811 + (r4812 << 8) + (r4813 << 16); } -unsigned SPC7110::data_adjust() { return r4814 + (r4815 << 8); } -unsigned SPC7110::data_increment() { return r4816 + (r4817 << 8); } -void SPC7110::set_data_pointer(unsigned addr) { r4811 = addr; r4812 = addr >> 8; r4813 = addr >> 16; } -void SPC7110::set_data_adjust(unsigned addr) { r4814 = addr; r4815 = addr >> 8; } - -void SPC7110::update_time(int offset) { - time_t rtc_time = (rtc[16] << 0) | (rtc[17] << 8) | (rtc[18] << 16) | (rtc[19] << 24); - time_t current_time = SNES::interface()->currentTime() - offset; - - //sizeof(time_t) is platform-dependent; though rtc[] needs to be platform-agnostic. - //yet platforms with 32-bit signed time_t will overflow every ~68 years. handle this by - //accounting for overflow at the cost of 1-bit precision (to catch underflow). this will allow - //rtc[] timestamp to remain valid for up to ~34 years from the last update, even if - //time_t overflows. calculation should be valid regardless of number representation, time_t size, - //or whether time_t is signed or unsigned. - time_t diff - = (current_time >= rtc_time) - ? (current_time - rtc_time) - : (std::numeric_limits::max() - rtc_time + current_time + 1); //compensate for overflow - if(diff > std::numeric_limits::max() / 2) diff = 0; //compensate for underflow - - bool update = true; - if(rtc[13] & 1) update = false; //do not update if CR0 timer disable flag is set - if(rtc[15] & 3) update = false; //do not update if CR2 timer disable flags are set - - if(diff > 0 && update == true) { - unsigned second = rtc[ 0] + rtc[ 1] * 10; - unsigned minute = rtc[ 2] + rtc[ 3] * 10; - unsigned hour = rtc[ 4] + rtc[ 5] * 10; - unsigned day = rtc[ 6] + rtc[ 7] * 10; - unsigned month = rtc[ 8] + rtc[ 9] * 10; - unsigned year = rtc[10] + rtc[11] * 10; - unsigned weekday = rtc[12]; - - day--; - month--; - year += (year >= 90) ? 1900 : 2000; //range = 1990-2089 - - second += diff; - while(second >= 60) { - second -= 60; - - minute++; - if(minute < 60) continue; - minute = 0; - - hour++; - if(hour < 24) continue; - hour = 0; - - day++; - weekday = (weekday + 1) % 7; - unsigned days = months[month % 12]; - if(days == 28) { - bool leapyear = false; - if((year % 4) == 0) { - leapyear = true; - if((year % 100) == 0 && (year % 400) != 0) leapyear = false; - } - if(leapyear) days++; - } - if(day < days) continue; - day = 0; - - month++; - if(month < 12) continue; - month = 0; - - year++; - } - - day++; - month++; - year %= 100; - - rtc[ 0] = second % 10; - rtc[ 1] = second / 10; - rtc[ 2] = minute % 10; - rtc[ 3] = minute / 10; - rtc[ 4] = hour % 10; - rtc[ 5] = hour / 10; - rtc[ 6] = day % 10; - rtc[ 7] = day / 10; - rtc[ 8] = month % 10; - rtc[ 9] = month / 10; - rtc[10] = year % 10; - rtc[11] = (year / 10) % 10; - rtc[12] = weekday % 7; - } - - rtc[16] = current_time >> 0; - rtc[17] = current_time >> 8; - rtc[18] = current_time >> 16; - rtc[19] = current_time >> 24; -} - -uint8 SPC7110::mmio_read(unsigned addr) { - addr &= 0xffff; - - switch(addr) { - //================== - //decompression unit - //================== - - case 0x4800: { - uint16 counter = (r4809 + (r480a << 8)); - counter--; - r4809 = counter; - r480a = counter >> 8; - return decomp.read(); - } - case 0x4801: return r4801; - case 0x4802: return r4802; - case 0x4803: return r4803; - case 0x4804: return r4804; - case 0x4805: return r4805; - case 0x4806: return r4806; - case 0x4807: return r4807; - case 0x4808: return r4808; - case 0x4809: return r4809; - case 0x480a: return r480a; - case 0x480b: return r480b; - case 0x480c: { - uint8 status = r480c; - r480c &= 0x7f; - return status; - } - - //============== - //data port unit - //============== - - case 0x4810: { - if(r481x != 0x07) return 0x00; - - unsigned addr = data_pointer(); - unsigned adjust = data_adjust(); - if(r4818 & 8) adjust = (int16)adjust; //16-bit sign extend - - unsigned adjustaddr = addr; - if(r4818 & 2) { - adjustaddr += adjust; - set_data_adjust(adjust + 1); - } - - auto myaddr = datarom_addr(adjustaddr); - cdlInfo.set(eCDLog_AddrType_CARTROM, myaddr); - uint8 data = cartridge.rom.read(myaddr); - if(!(r4818 & 2)) { - unsigned increment = (r4818 & 1) ? data_increment() : 1; - if(r4818 & 4) increment = (int16)increment; //16-bit sign extend - - if((r4818 & 16) == 0) { - set_data_pointer(addr + increment); - } else { - set_data_adjust(adjust + increment); - } - } - - return data; - } - case 0x4811: return r4811; - case 0x4812: return r4812; - case 0x4813: return r4813; - case 0x4814: return r4814; - case 0x4815: return r4815; - case 0x4816: return r4816; - case 0x4817: return r4817; - case 0x4818: return r4818; - case 0x481a: { - if(r481x != 0x07) return 0x00; - - unsigned addr = data_pointer(); - unsigned adjust = data_adjust(); - if(r4818 & 8) adjust = (int16)adjust; //16-bit sign extend - - auto myaddr = datarom_addr(addr + adjust); - cdlInfo.set(eCDLog_AddrType_CARTROM, myaddr); - uint8 data = cartridge.rom.read(myaddr); - if((r4818 & 0x60) == 0x60) { - if((r4818 & 16) == 0) { - set_data_pointer(addr + adjust); - } else { - set_data_adjust(adjust + adjust); - } - } - - return data; - } - - //========= - //math unit - //========= - - case 0x4820: return r4820; - case 0x4821: return r4821; - case 0x4822: return r4822; - case 0x4823: return r4823; - case 0x4824: return r4824; - case 0x4825: return r4825; - case 0x4826: return r4826; - case 0x4827: return r4827; - case 0x4828: return r4828; - case 0x4829: return r4829; - case 0x482a: return r482a; - case 0x482b: return r482b; - case 0x482c: return r482c; - case 0x482d: return r482d; - case 0x482e: return r482e; - case 0x482f: { - uint8 status = r482f; - r482f &= 0x7f; - return status; - } - - //=================== - //memory mapping unit - //=================== - - case 0x4830: return r4830; - case 0x4831: return r4831; - case 0x4832: return r4832; - case 0x4833: return r4833; - case 0x4834: return r4834; - - //==================== - //real-time clock unit - //==================== - - case 0x4840: return r4840; - case 0x4841: { - if(rtc_state == RTCS_Inactive || rtc_state == RTCS_ModeSelect) return 0x00; - - r4842 = 0x80; - uint8 data = rtc[rtc_index]; - rtc_index = (rtc_index + 1) & 15; - return data; - } - case 0x4842: { - uint8 status = r4842; - r4842 &= 0x7f; - return status; - } - } - - return cpu.regs.mdr; -} - -void SPC7110::mmio_write(unsigned addr, uint8 data) { - addr &= 0xffff; - - switch(addr) { - //================== - //decompression unit - //================== - - case 0x4801: r4801 = data; break; - case 0x4802: r4802 = data; break; - case 0x4803: r4803 = data; break; - case 0x4804: r4804 = data; break; - case 0x4805: r4805 = data; break; - case 0x4806: { - r4806 = data; - - unsigned table = (r4801 + (r4802 << 8) + (r4803 << 16)); - unsigned index = (r4804 << 2); - unsigned length = (r4809 + (r480a << 8)); - unsigned addr = datarom_addr(table + index); - - cdlInfo.set(eCDLog_AddrType_CARTROM, addr + 0); - cdlInfo.set(eCDLog_AddrType_CARTROM, addr + 1); - cdlInfo.set(eCDLog_AddrType_CARTROM, addr + 2); - cdlInfo.set(eCDLog_AddrType_CARTROM, addr + 3); - - unsigned mode = (cartridge.rom.read(addr + 0)); - unsigned offset = (cartridge.rom.read(addr + 1) << 16) - + (cartridge.rom.read(addr + 2) << 8) - + (cartridge.rom.read(addr + 3) << 0); - - decomp.init(mode, offset, (r4805 + (r4806 << 8)) << mode); - r480c = 0x80; - } break; - - case 0x4807: r4807 = data; break; - case 0x4808: r4808 = data; break; - case 0x4809: r4809 = data; break; - case 0x480a: r480a = data; break; - case 0x480b: r480b = data; break; - - //============== - //data port unit - //============== - - case 0x4811: r4811 = data; r481x |= 0x01; break; - case 0x4812: r4812 = data; r481x |= 0x02; break; - case 0x4813: r4813 = data; r481x |= 0x04; break; - case 0x4814: { - r4814 = data; - r4814_latch = true; - if(!r4815_latch) break; - if(!(r4818 & 2)) break; - if(r4818 & 0x10) break; - - if((r4818 & 0x60) == 0x20) { - unsigned increment = data_adjust() & 0xff; - if(r4818 & 8) increment = (int8)increment; //8-bit sign extend - set_data_pointer(data_pointer() + increment); - } else if((r4818 & 0x60) == 0x40) { - unsigned increment = data_adjust(); - if(r4818 & 8) increment = (int16)increment; //16-bit sign extend - set_data_pointer(data_pointer() + increment); - } - } break; - case 0x4815: { - r4815 = data; - r4815_latch = true; - if(!r4814_latch) break; - if(!(r4818 & 2)) break; - if(r4818 & 0x10) break; - - if((r4818 & 0x60) == 0x20) { - unsigned increment = data_adjust() & 0xff; - if(r4818 & 8) increment = (int8)increment; //8-bit sign extend - set_data_pointer(data_pointer() + increment); - } else if((r4818 & 0x60) == 0x40) { - unsigned increment = data_adjust(); - if(r4818 & 8) increment = (int16)increment; //16-bit sign extend - set_data_pointer(data_pointer() + increment); - } - } break; - case 0x4816: r4816 = data; break; - case 0x4817: r4817 = data; break; - case 0x4818: { - if(r481x != 0x07) break; - - r4818 = data; - r4814_latch = r4815_latch = false; - } break; - - //========= - //math unit - //========= - - case 0x4820: r4820 = data; break; - case 0x4821: r4821 = data; break; - case 0x4822: r4822 = data; break; - case 0x4823: r4823 = data; break; - case 0x4824: r4824 = data; break; - case 0x4825: { - r4825 = data; - - if(r482e & 1) { - //signed 16-bit x 16-bit multiplication - int16 r0 = (int16)(r4824 + (r4825 << 8)); - int16 r1 = (int16)(r4820 + (r4821 << 8)); - - signed result = r0 * r1; - r4828 = result; - r4829 = result >> 8; - r482a = result >> 16; - r482b = result >> 24; - } else { - //unsigned 16-bit x 16-bit multiplication - uint16 r0 = (uint16)(r4824 + (r4825 << 8)); - uint16 r1 = (uint16)(r4820 + (r4821 << 8)); - - unsigned result = r0 * r1; - r4828 = result; - r4829 = result >> 8; - r482a = result >> 16; - r482b = result >> 24; - } - - r482f = 0x80; - } break; - case 0x4826: r4826 = data; break; - case 0x4827: { - r4827 = data; - - if(r482e & 1) { - //signed 32-bit x 16-bit division - int32 dividend = (int32)(r4820 + (r4821 << 8) + (r4822 << 16) + (r4823 << 24)); - int16 divisor = (int16)(r4826 + (r4827 << 8)); - - int32 quotient; - int16 remainder; - - if(divisor) { - quotient = (int32)(dividend / divisor); - remainder = (int32)(dividend % divisor); - } else { - //illegal division by zero - quotient = 0; - remainder = dividend & 0xffff; - } - - r4828 = quotient; - r4829 = quotient >> 8; - r482a = quotient >> 16; - r482b = quotient >> 24; - - r482c = remainder; - r482d = remainder >> 8; - } else { - //unsigned 32-bit x 16-bit division - uint32 dividend = (uint32)(r4820 + (r4821 << 8) + (r4822 << 16) + (r4823 << 24)); - uint16 divisor = (uint16)(r4826 + (r4827 << 8)); - - uint32 quotient; - uint16 remainder; - - if(divisor) { - quotient = (uint32)(dividend / divisor); - remainder = (uint16)(dividend % divisor); - } else { - //illegal division by zero - quotient = 0; - remainder = dividend & 0xffff; - } - - r4828 = quotient; - r4829 = quotient >> 8; - r482a = quotient >> 16; - r482b = quotient >> 24; - - r482c = remainder; - r482d = remainder >> 8; - } - - r482f = 0x80; - } break; - - case 0x482e: { - //reset math unit - r4820 = r4821 = r4822 = r4823 = 0; - r4824 = r4825 = r4826 = r4827 = 0; - r4828 = r4829 = r482a = r482b = 0; - r482c = r482d = 0; - - r482e = data; - } break; - - //=================== - //memory mapping unit - //=================== - - case 0x4830: r4830 = data; break; - - case 0x4831: { - r4831 = data; - dx_offset = datarom_addr(data * 0x100000); - } break; - - case 0x4832: { - r4832 = data; - ex_offset = datarom_addr(data * 0x100000); - } break; - - case 0x4833: { - r4833 = data; - fx_offset = datarom_addr(data * 0x100000); - } break; - - case 0x4834: r4834 = data; break; - - //==================== - //real-time clock unit - //==================== - - case 0x4840: { - r4840 = data; - if(!(r4840 & 1)) { - //disable RTC - rtc_state = RTCS_Inactive; - update_time(); - } else { - //enable RTC - r4842 = 0x80; - rtc_state = RTCS_ModeSelect; - } - } break; - - case 0x4841: { - r4841 = data; - - switch(rtc_state) { - case RTCS_ModeSelect: { - if(data == RTCM_Linear || data == RTCM_Indexed) { - r4842 = 0x80; - rtc_state = RTCS_IndexSelect; - rtc_mode = (RTC_Mode)data; - rtc_index = 0; - } - } break; - - case RTCS_IndexSelect: { - r4842 = 0x80; - rtc_index = data & 15; - if(rtc_mode == RTCM_Linear) rtc_state = RTCS_Write; - } break; - - case RTCS_Write: { - r4842 = 0x80; - - //control register 0 - if(rtc_index == 13) { - //increment second counter - if(data & 2) update_time(+1); - - //round minute counter - if(data & 8) { - update_time(); - - unsigned second = rtc[ 0] + rtc[ 1] * 10; - //clear seconds - rtc[0] = 0; - rtc[1] = 0; - - if(second >= 30) update_time(+60); - } - } - - //control register 2 - if(rtc_index == 15) { - //disable timer and clear second counter - if((data & 1) && !(rtc[15] & 1)) { - update_time(); - - //clear seconds - rtc[0] = 0; - rtc[1] = 0; - } - - //disable timer - if((data & 2) && !(rtc[15] & 2)) { - update_time(); - } - } - - rtc[rtc_index] = data & 15; - rtc_index = (rtc_index + 1) & 15; - } break; - } //switch(rtc_state) - } break; - } -} - -SPC7110::SPC7110() : - rtc(nullptr) -{ - -} - -SPC7110::~SPC7110() -{ - interface()->freeSharedMemory(rtc); -} - -void SPC7110::initialize() -{ - rtc = (uint8*)interface()->allocSharedMemory("SPC7110_RTC", 20); -} -//============ -//SPC7110::MCU -//============ - -uint8 SPC7110::mcu_read(unsigned addr) { - if(addr <= 0xdfffff) { - cdlInfo.set(eCDLog_AddrType_CARTROM, dx_offset + (addr & 0x0fffff)); - return cartridge.rom.read(dx_offset + (addr & 0x0fffff)); - } - if(addr <= 0xefffff) { - cdlInfo.set(eCDLog_AddrType_CARTROM, ex_offset + (addr & 0x0fffff)); - return cartridge.rom.read(ex_offset + (addr & 0x0fffff)); - } - if(addr <= 0xffffff) { - cdlInfo.set(eCDLog_AddrType_CARTROM, fx_offset + (addr & 0x0fffff)); - return cartridge.rom.read(fx_offset + (addr & 0x0fffff)); - } - return cpu.regs.mdr; -} - -void SPC7110::mcu_write(unsigned addr, uint8 data) { -} - -//============ -//SPC7110::DCU -//============ - -uint8 SPC7110::dcu_read(unsigned) { - return mmio_read(0x4800); -} - -void SPC7110::dcu_write(unsigned, uint8) { -} - -//============ -//SPC7110::RAM -//============ - -uint8 SPC7110::ram_read(unsigned addr) { - return cartridge.ram.read(addr & 0x1fff); -} - -void SPC7110::ram_write(unsigned addr, uint8 data) { - if(r4830 & 0x80) cartridge.ram.write(addr & 0x1fff, data); -} - -} diff --git a/waterbox/libsnes/bsnes/snes/chip/spc7110/spc7110.hpp b/waterbox/libsnes/bsnes/snes/chip/spc7110/spc7110.hpp deleted file mode 100644 index acf6743fd0..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/spc7110/spc7110.hpp +++ /dev/null @@ -1,132 +0,0 @@ -//SPC7110 emulator - version 0.05 (2011-06-27) -//Copyright (c) 2008-2011, byuu and neviksti - -class SPC7110 { -public: - uint8* rtc; //[20]; - unsigned data_rom_offset; - - void init(); - void load(); - void unload(); - void power(); - void reset(); - - unsigned datarom_addr(unsigned addr); - - unsigned data_pointer(); - unsigned data_adjust(); - unsigned data_increment(); - void set_data_pointer(unsigned addr); - void set_data_adjust(unsigned addr); - - void update_time(int offset = 0); - time_t create_time(); - - uint8 mmio_read(unsigned addr); - void mmio_write(unsigned addr, uint8 data); - - uint8 mcu_read(unsigned addr); - void mcu_write(unsigned addr, uint8 data); - - uint8 dcu_read(unsigned); - void dcu_write(unsigned, uint8); - - uint8 ram_read(unsigned addr); - void ram_write(unsigned addr, uint8 data); - - //spc7110decomp - void decomp_init(); - uint8 decomp_read(); - - SPC7110(); - ~SPC7110(); - void initialize(); - -private: - //================== - //decompression unit - //================== - uint8 r4801; //compression table low - uint8 r4802; //compression table high - uint8 r4803; //compression table bank - uint8 r4804; //compression table index - uint8 r4805; //decompression buffer index low - uint8 r4806; //decompression buffer index high - uint8 r4807; //??? - uint8 r4808; //??? - uint8 r4809; //compression length low - uint8 r480a; //compression length high - uint8 r480b; //decompression control register - uint8 r480c; //decompression status - - #include "decomp.hpp" - Decomp decomp; - - //============== - //data port unit - //============== - uint8 r4811; //data pointer low - uint8 r4812; //data pointer high - uint8 r4813; //data pointer bank - uint8 r4814; //data adjust low - uint8 r4815; //data adjust high - uint8 r4816; //data increment low - uint8 r4817; //data increment high - uint8 r4818; //data port control register - - uint8 r481x; - - bool r4814_latch; - bool r4815_latch; - - //========= - //math unit - //========= - uint8 r4820; //16-bit multiplicand B0, 32-bit dividend B0 - uint8 r4821; //16-bit multiplicand B1, 32-bit dividend B1 - uint8 r4822; //32-bit dividend B2 - uint8 r4823; //32-bit dividend B3 - uint8 r4824; //16-bit multiplier B0 - uint8 r4825; //16-bit multiplier B1 - uint8 r4826; //16-bit divisor B0 - uint8 r4827; //16-bit divisor B1 - uint8 r4828; //32-bit product B0, 32-bit quotient B0 - uint8 r4829; //32-bit product B1, 32-bit quotient B1 - uint8 r482a; //32-bit product B2, 32-bit quotient B2 - uint8 r482b; //32-bit product B3, 32-bit quotient B3 - uint8 r482c; //16-bit remainder B0 - uint8 r482d; //16-bit remainder B1 - uint8 r482e; //math control register - uint8 r482f; //math status - - //=================== - //memory mapping unit - //=================== - uint8 r4830; //SRAM write enable - uint8 r4831; //$[d0-df]:[0000-ffff] mapping - uint8 r4832; //$[e0-ef]:[0000-ffff] mapping - uint8 r4833; //$[f0-ff]:[0000-ffff] mapping - uint8 r4834; //??? - - unsigned dx_offset; - unsigned ex_offset; - unsigned fx_offset; - - //==================== - //real-time clock unit - //==================== - uint8 r4840; //RTC latch - uint8 r4841; //RTC index/data port - uint8 r4842; //RTC status - - enum RTC_State { RTCS_Inactive, RTCS_ModeSelect, RTCS_IndexSelect, RTCS_Write }; - enum RTC_Mode { RTCM_Linear = 0x03, RTCM_Indexed = 0x0c }; - unsigned rtc_state; - unsigned rtc_mode; - unsigned rtc_index; - - static const unsigned months[12]; -}; - -extern SPC7110 spc7110; diff --git a/waterbox/libsnes/bsnes/snes/chip/srtc/srtc.cpp b/waterbox/libsnes/bsnes/snes/chip/srtc/srtc.cpp deleted file mode 100644 index 606eb7502e..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/srtc/srtc.cpp +++ /dev/null @@ -1,241 +0,0 @@ -#include - -#define SRTC_CPP -namespace SNES { - -SRTC srtc; - -const unsigned SRTC::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - -SRTC::SRTC() - : rtc(nullptr) -{ -} - -SRTC::~SRTC() -{ - interface()->freeSharedMemory(rtc); -} - -void SRTC::initialize() -{ - rtc = (uint8*)interface()->allocSharedMemory("RTC",20); -} - -void SRTC::init() { -} - -void SRTC::load() { - for(unsigned n = 0; n < 20; n++) rtc[n] = 0xff; - cartridge.nvram.append({ "program.rtc", rtc, 20 }); -} - -void SRTC::unload() { -} - -void SRTC::power() { -} - -void SRTC::reset() { - rtc_mode = RtcRead; - rtc_index = -1; - update_time(); -} - -void SRTC::update_time() { - time_t rtc_time = (rtc[16] << 0) | (rtc[17] << 8) | (rtc[18] << 16) | (rtc[19] << 24); - time_t current_time = SNES::interface()->currentTime(); - - //sizeof(time_t) is platform-dependent; though rtc[] needs to be platform-agnostic. - //yet platforms with 32-bit signed time_t will overflow every ~68 years. handle this by - //accounting for overflow at the cost of 1-bit precision (to catch underflow). this will allow - //rtc[] timestamp to remain valid for up to ~34 years from the last update, even if - //time_t overflows. calculation should be valid regardless of number representation, time_t size, - //or whether time_t is signed or unsigned. - time_t diff - = (current_time >= rtc_time) - ? (current_time - rtc_time) - : (std::numeric_limits::max() - rtc_time + current_time + 1); //compensate for overflow - if(diff > std::numeric_limits::max() / 2) diff = 0; //compensate for underflow - - if(diff > 0) { - unsigned second = rtc[ 0] + rtc[ 1] * 10; - unsigned minute = rtc[ 2] + rtc[ 3] * 10; - unsigned hour = rtc[ 4] + rtc[ 5] * 10; - unsigned day = rtc[ 6] + rtc[ 7] * 10; - unsigned month = rtc[ 8]; - unsigned year = rtc[ 9] + rtc[10] * 10 + rtc[11] * 100; - unsigned weekday = rtc[12]; - - day--; - month--; - year += 1000; - - second += diff; - while(second >= 60) { - second -= 60; - - minute++; - if(minute < 60) continue; - minute = 0; - - hour++; - if(hour < 24) continue; - hour = 0; - - day++; - weekday = (weekday + 1) % 7; - unsigned days = months[month % 12]; - if(days == 28) { - bool leapyear = false; - if((year % 4) == 0) { - leapyear = true; - if((year % 100) == 0 && (year % 400) != 0) leapyear = false; - } - if(leapyear) days++; - } - if(day < days) continue; - day = 0; - - month++; - if(month < 12) continue; - month = 0; - - year++; - } - - day++; - month++; - year -= 1000; - - rtc[ 0] = second % 10; - rtc[ 1] = second / 10; - rtc[ 2] = minute % 10; - rtc[ 3] = minute / 10; - rtc[ 4] = hour % 10; - rtc[ 5] = hour / 10; - rtc[ 6] = day % 10; - rtc[ 7] = day / 10; - rtc[ 8] = month; - rtc[ 9] = year % 10; - rtc[10] = (year / 10) % 10; - rtc[11] = year / 100; - rtc[12] = weekday % 7; - } - - rtc[16] = current_time >> 0; - rtc[17] = current_time >> 8; - rtc[18] = current_time >> 16; - rtc[19] = current_time >> 24; -} - -//returns day of week for specified date -//eg 0 = Sunday, 1 = Monday, ... 6 = Saturday -//usage: weekday(2008, 1, 1) returns weekday of January 1st, 2008 -unsigned SRTC::weekday(unsigned year, unsigned month, unsigned day) { - unsigned y = 1900, m = 1; //epoch is 1900-01-01 - unsigned sum = 0; //number of days passed since epoch - - year = max(1900, year); - month = max(1, min(12, month)); - day = max(1, min(31, day)); - - while(y < year) { - bool leapyear = false; - if((y % 4) == 0) { - leapyear = true; - if((y % 100) == 0 && (y % 400) != 0) leapyear = false; - } - sum += leapyear ? 366 : 365; - y++; - } - - while(m < month) { - unsigned days = months[m - 1]; - if(days == 28) { - bool leapyear = false; - if((y % 4) == 0) { - leapyear = true; - if((y % 100) == 0 && (y % 400) != 0) leapyear = false; - } - if(leapyear) days++; - } - sum += days; - m++; - } - - sum += day - 1; - return (sum + 1) % 7; //1900-01-01 was a Monday -} - -uint8 SRTC::read(unsigned addr) { - addr &= 0xffff; - - if(addr == 0x2800) { - if(rtc_mode != RtcRead) return 0x00; - - if(rtc_index < 0) { - update_time(); - rtc_index++; - return 0x0f; - } else if(rtc_index > 12) { - rtc_index = -1; - return 0x0f; - } else { - return rtc[rtc_index++]; - } - } - - return cpu.regs.mdr; -} - -void SRTC::write(unsigned addr, uint8 data) { - addr &= 0xffff; - - if(addr == 0x2801) { - data &= 0x0f; //only the low four bits are used - - if(data == 0x0d) { - rtc_mode = RtcRead; - rtc_index = -1; - return; - } - - if(data == 0x0e) { - rtc_mode = RtcCommand; - return; - } - - if(data == 0x0f) return; //unknown behavior - - if(rtc_mode == RtcWrite) { - if(rtc_index >= 0 && rtc_index < 12) { - rtc[rtc_index++] = data; - - if(rtc_index == 12) { - //day of week is automatically calculated and written - unsigned day = rtc[ 6] + rtc[ 7] * 10; - unsigned month = rtc[ 8]; - unsigned year = rtc[ 9] + rtc[10] * 10 + rtc[11] * 100; - year += 1000; - - rtc[rtc_index++] = weekday(year, month, day); - } - } - } else if(rtc_mode == RtcCommand) { - if(data == 0) { - rtc_mode = RtcWrite; - rtc_index = 0; - } else if(data == 4) { - rtc_mode = RtcReady; - rtc_index = -1; - for(unsigned i = 0; i < 13; i++) rtc[i] = 0; - } else { - //unknown behavior - rtc_mode = RtcReady; - } - } - } -} - -} diff --git a/waterbox/libsnes/bsnes/snes/chip/srtc/srtc.hpp b/waterbox/libsnes/bsnes/snes/chip/srtc/srtc.hpp deleted file mode 100644 index c6ce9bbe0c..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/srtc/srtc.hpp +++ /dev/null @@ -1,28 +0,0 @@ -class SRTC { -public: - uint8* rtc; //[20]; - - void init(); - void load(); - void unload(); - void power(); - void reset(); - - uint8 read(unsigned addr); - void write(unsigned addr, uint8 data); - - void initialize(); - SRTC(); - ~SRTC(); - -private: - static const unsigned months[12]; - enum RtcMode { RtcReady, RtcCommand, RtcRead, RtcWrite }; - unsigned rtc_mode; - signed rtc_index; - - void update_time(); - unsigned weekday(unsigned year, unsigned month, unsigned day); -}; - -extern SRTC srtc; diff --git a/waterbox/libsnes/bsnes/snes/chip/sufamiturbo/sufamiturbo.cpp b/waterbox/libsnes/bsnes/snes/chip/sufamiturbo/sufamiturbo.cpp deleted file mode 100644 index 15bbeaa636..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/sufamiturbo/sufamiturbo.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include - -#define SUFAMITURBO_CPP -namespace SNES { - -SufamiTurbo sufamiturbo; - -SufamiTurbo::SufamiTurbo() -{ - slotA.ram.setName("SUFAMI_TURBO_A_RAM"); - slotB.ram.setName("SUFAMI_TURBO_B_RAM"); -} - -void SufamiTurbo::load() { - slotA.ram.map(allocate(128 * 1024, 0xff), 128 * 1024); - slotB.ram.map(allocate(128 * 1024, 0xff), 128 * 1024); - - if(slotA.rom.data()) { - cartridge.nvram.append({ "program.ram", slotA.ram.data(), slotA.ram.size(), Cartridge::Slot::SufamiTurboA }); - } else { - slotA.rom.map(allocate(128 * 1024, 0xff), 128 * 1024); - } - - if(slotB.rom.data()) { - cartridge.nvram.append({ "program.ram", slotB.ram.data(), slotB.ram.size(), Cartridge::Slot::SufamiTurboB }); - } else { - slotB.rom.map(allocate(128 * 1024, 0xff), 128 * 1024); - } -} - -void SufamiTurbo::unload() { - slotA.rom.reset(); - slotA.ram.reset(); - slotB.rom.reset(); - slotB.ram.reset(); -} - -} diff --git a/waterbox/libsnes/bsnes/snes/chip/sufamiturbo/sufamiturbo.hpp b/waterbox/libsnes/bsnes/snes/chip/sufamiturbo/sufamiturbo.hpp deleted file mode 100644 index a2e6a4b5c2..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/sufamiturbo/sufamiturbo.hpp +++ /dev/null @@ -1,14 +0,0 @@ -class SufamiTurbo { -public: - struct Slot { - MappedRAM rom; - MappedRAM ram; - } slotA, slotB; - - void load(); - void unload(); - - SufamiTurbo(); -}; - -extern SufamiTurbo sufamiturbo; diff --git a/waterbox/libsnes/bsnes/snes/chip/superfx/bus/bus.cpp b/waterbox/libsnes/bsnes/snes/chip/superfx/bus/bus.cpp deleted file mode 100644 index 6983f8475b..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/superfx/bus/bus.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#ifdef SUPERFX_CPP - -//ROM / RAM access from the S-CPU - -unsigned SuperFX::ROM::size() const { - return cartridge.rom.size(); -} - -uint8 SuperFX::ROM::read(unsigned addr) { - if(superfx.regs.sfr.g && superfx.regs.scmr.ron) { - static const uint8_t data[16] = { - 0x00, 0x01, 0x00, 0x01, 0x04, 0x01, 0x00, 0x01, - 0x00, 0x01, 0x08, 0x01, 0x00, 0x01, 0x0c, 0x01, - }; - return data[addr & 15]; - } - cdlInfo.set(eCDLog_AddrType_CARTROM, addr); - return cartridge.rom.read(addr); -} - -void SuperFX::ROM::write(unsigned addr, uint8 data) { - cartridge.rom.write(addr, data); -} - -unsigned SuperFX::RAM::size() const { - return cartridge.ram.size(); -} - -uint8 SuperFX::RAM::read(unsigned addr) { - if(superfx.regs.sfr.g && superfx.regs.scmr.ran) return cpu.regs.mdr; - return cartridge.ram.read(addr); -} - -void SuperFX::RAM::write(unsigned addr, uint8 data) { - cartridge.ram.write(addr, data); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/superfx/bus/bus.hpp b/waterbox/libsnes/bsnes/snes/chip/superfx/bus/bus.hpp deleted file mode 100644 index 6e698e68d8..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/superfx/bus/bus.hpp +++ /dev/null @@ -1,11 +0,0 @@ -struct ROM : Memory { - unsigned size() const; - uint8 read(unsigned); - void write(unsigned, uint8); -} rom; - -struct RAM : Memory { - unsigned size() const; - uint8 read(unsigned); - void write(unsigned, uint8); -} ram; diff --git a/waterbox/libsnes/bsnes/snes/chip/superfx/core/core.cpp b/waterbox/libsnes/bsnes/snes/chip/superfx/core/core.cpp deleted file mode 100644 index 92c2afd616..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/superfx/core/core.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#ifdef SUPERFX_CPP - -#include "opcodes.cpp" -#include "opcode_table.cpp" - -uint8 SuperFX::color(uint8 source) { - if(regs.por.highnibble) return (regs.colr & 0xf0) | (source >> 4); - if(regs.por.freezehigh) return (regs.colr & 0xf0) | (source & 0x0f); - return source; -} - -void SuperFX::plot(uint8 x, uint8 y) { - uint8 color = regs.colr; - - if(regs.por.dither && regs.scmr.md != 3) { - if((x ^ y) & 1) color >>= 4; - color &= 0x0f; - } - - if(!regs.por.transparent) { - if(regs.scmr.md == 3) { - if(regs.por.freezehigh) { - if((color & 0x0f) == 0) return; - } else { - if(color == 0) return; - } - } else { - if((color & 0x0f) == 0) return; - } - } - - uint16 offset = (y << 5) + (x >> 3); - if(offset != pixelcache[0].offset) { - pixelcache_flush(pixelcache[1]); - pixelcache[1] = pixelcache[0]; - pixelcache[0].bitpend = 0x00; - pixelcache[0].offset = offset; - } - - x = (x & 7) ^ 7; - pixelcache[0].data[x] = color; - pixelcache[0].bitpend |= 1 << x; - if(pixelcache[0].bitpend == 0xff) { - pixelcache_flush(pixelcache[1]); - pixelcache[1] = pixelcache[0]; - pixelcache[0].bitpend = 0x00; - } -} - -uint8 SuperFX::rpix(uint8 x, uint8 y) { - pixelcache_flush(pixelcache[1]); - pixelcache_flush(pixelcache[0]); - - unsigned cn; //character number - switch(regs.por.obj ? 3 : regs.scmr.ht) { - case 0: cn = ((x & 0xf8) << 1) + ((y & 0xf8) >> 3); break; - case 1: cn = ((x & 0xf8) << 1) + ((x & 0xf8) >> 1) + ((y & 0xf8) >> 3); break; - case 2: cn = ((x & 0xf8) << 1) + ((x & 0xf8) << 0) + ((y & 0xf8) >> 3); break; - case 3: cn = ((y & 0x80) << 2) + ((x & 0x80) << 1) + ((y & 0x78) << 1) + ((x & 0x78) >> 3); break; - } - unsigned bpp = 2 << (regs.scmr.md - (regs.scmr.md >> 1)); // = [regs.scmr.md]{ 2, 4, 4, 8 }; - unsigned addr = 0x700000 + (cn * (bpp << 3)) + (regs.scbr << 10) + ((y & 0x07) * 2); - uint8 data = 0x00; - x = (x & 7) ^ 7; - - for(unsigned n = 0; n < bpp; n++) { - unsigned byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 }; - add_clocks(memory_access_speed); - data |= ((bus_read(addr + byte) >> x) & 1) << n; - } - - return data; -} - -void SuperFX::pixelcache_flush(pixelcache_t &cache) { - if(cache.bitpend == 0x00) return; - - uint8 x = cache.offset << 3; - uint8 y = cache.offset >> 5; - - unsigned cn; //character number - switch(regs.por.obj ? 3 : regs.scmr.ht) { - case 0: cn = ((x & 0xf8) << 1) + ((y & 0xf8) >> 3); break; - case 1: cn = ((x & 0xf8) << 1) + ((x & 0xf8) >> 1) + ((y & 0xf8) >> 3); break; - case 2: cn = ((x & 0xf8) << 1) + ((x & 0xf8) << 0) + ((y & 0xf8) >> 3); break; - case 3: cn = ((y & 0x80) << 2) + ((x & 0x80) << 1) + ((y & 0x78) << 1) + ((x & 0x78) >> 3); break; - } - unsigned bpp = 2 << (regs.scmr.md - (regs.scmr.md >> 1)); // = [regs.scmr.md]{ 2, 4, 4, 8 }; - unsigned addr = 0x700000 + (cn * (bpp << 3)) + (regs.scbr << 10) + ((y & 0x07) * 2); - - for(unsigned n = 0; n < bpp; n++) { - unsigned byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 }; - uint8 data = 0x00; - for(unsigned x = 0; x < 8; x++) data |= ((cache.data[x] >> n) & 1) << x; - if(cache.bitpend != 0xff) { - add_clocks(memory_access_speed); - data &= cache.bitpend; - data |= bus_read(addr + byte) & ~cache.bitpend; - } - add_clocks(memory_access_speed); - bus_write(addr + byte, data); - } - - cache.bitpend = 0x00; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/superfx/core/core.hpp b/waterbox/libsnes/bsnes/snes/chip/superfx/core/core.hpp deleted file mode 100644 index 1c13f1ce67..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/superfx/core/core.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "registers.hpp" - -uint8 color(uint8 source); -void plot(uint8 x, uint8 y); -uint8 rpix(uint8 x, uint8 y); -void pixelcache_flush(pixelcache_t &cache); - -void (SuperFX::*opcode_table[1024])(); -void initialize_opcode_table(); - -//opcodes.cpp -template void op_adc_i(); -template void op_adc_r(); -template void op_add_i(); -template void op_add_r(); -void op_alt1(); -void op_alt2(); -void op_alt3(); -template void op_and_i(); -template void op_and_r(); -void op_asr(); -void op_bge(); -void op_bcc(); -void op_bcs(); -void op_beq(); -template void op_bic_i(); -template void op_bic_r(); -void op_blt(); -void op_bmi(); -void op_bne(); -void op_bpl(); -void op_bra(); -void op_bvc(); -void op_bvs(); -void op_cache(); -void op_cmode(); -template void op_cmp_r(); -void op_color(); -template void op_dec_r(); -void op_div2(); -void op_fmult(); -template void op_from_r(); -void op_getb(); -void op_getbl(); -void op_getbh(); -void op_getbs(); -void op_getc(); -void op_hib(); -template void op_ibt_r(); -template void op_inc_r(); -template void op_iwt_r(); -template void op_jmp_r(); -template void op_ldb_ir(); -template void op_ldw_ir(); -template void op_link(); -template void op_ljmp_r(); -template void op_lm_r(); -template void op_lms_r(); -void op_lmult(); -void op_lob(); -void op_loop(); -void op_lsr(); -void op_merge(); -template void op_mult_i(); -template void op_mult_r(); -void op_nop(); -void op_not(); -template void op_or_i(); -template void op_or_r(); -void op_plot(); -void op_ramb(); -void op_rol(); -void op_romb(); -void op_ror(); -void op_rpix(); -template void op_sbc_r(); -void op_sbk(); -void op_sex(); -template void op_sm_r(); -template void op_sms_r(); -template void op_stb_ir(); -void op_stop(); -template void op_stw_ir(); -template void op_sub_i(); -template void op_sub_r(); -void op_swap(); -template void op_to_r(); -template void op_umult_i(); -template void op_umult_r(); -template void op_with_r(); -template void op_xor_i(); -template void op_xor_r(); diff --git a/waterbox/libsnes/bsnes/snes/chip/superfx/core/opcode_table.cpp b/waterbox/libsnes/bsnes/snes/chip/superfx/core/opcode_table.cpp deleted file mode 100644 index 79082531a1..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/superfx/core/opcode_table.cpp +++ /dev/null @@ -1,270 +0,0 @@ -#ifdef SUPERFX_CPP - -void SuperFX::initialize_opcode_table() { - #define op4(id, name) \ - op(id+ 0, name< 1>) op(id+ 1, name< 2>) op(id+ 2, name< 3>) op(id+ 3, name< 4>) - - #define op6(id, name) \ - op(id+ 0, name< 8>) op(id+ 1, name< 9>) op(id+ 2, name<10>) op(id+ 3, name<11>) \ - op(id+ 4, name<12>) op(id+ 5, name<13>) - - #define op12(id, name) \ - op(id+ 0, name< 0>) op(id+ 1, name< 1>) op(id+ 2, name< 2>) op(id+ 3, name< 3>) \ - op(id+ 4, name< 4>) op(id+ 5, name< 5>) op(id+ 6, name< 6>) op(id+ 7, name< 7>) \ - op(id+ 8, name< 8>) op(id+ 9, name< 9>) op(id+10, name<10>) op(id+11, name<11>) - - #define op15l(id, name) \ - op(id+ 0, name< 0>) op(id+ 1, name< 1>) op(id+ 2, name< 2>) op(id+ 3, name< 3>) \ - op(id+ 4, name< 4>) op(id+ 5, name< 5>) op(id+ 6, name< 6>) op(id+ 7, name< 7>) \ - op(id+ 8, name< 8>) op(id+ 9, name< 9>) op(id+10, name<10>) op(id+11, name<11>) \ - op(id+12, name<12>) op(id+13, name<13>) op(id+14, name<14>) - - #define op15h(id, name) \ - op(id+ 0, name< 1>) op(id+ 1, name< 2>) op(id+ 2, name< 3>) op(id+ 3, name< 4>) \ - op(id+ 4, name< 5>) op(id+ 5, name< 6>) op(id+ 6, name< 7>) op(id+ 7, name< 8>) \ - op(id+ 8, name< 9>) op(id+ 9, name<10>) op(id+10, name<11>) op(id+11, name<12>) \ - op(id+12, name<13>) op(id+13, name<14>) op(id+14, name<15>) - - #define op16(id, name) \ - op(id+ 0, name< 0>) op(id+ 1, name< 1>) op(id+ 2, name< 2>) op(id+ 3, name< 3>) \ - op(id+ 4, name< 4>) op(id+ 5, name< 5>) op(id+ 6, name< 6>) op(id+ 7, name< 7>) \ - op(id+ 8, name< 8>) op(id+ 9, name< 9>) op(id+10, name<10>) op(id+11, name<11>) \ - op(id+12, name<12>) op(id+13, name<13>) op(id+14, name<14>) op(id+15, name<15>) - - //====== - // ALT0 - //====== - - #define op(id, name) opcode_table[ 0 + id] = &SuperFX::op_##name; - op (0x00, stop) - op (0x01, nop) - op (0x02, cache) - op (0x03, lsr) - op (0x04, rol) - op (0x05, bra) - op (0x06, blt) - op (0x07, bge) - op (0x08, bne) - op (0x09, beq) - op (0x0a, bpl) - op (0x0b, bmi) - op (0x0c, bcc) - op (0x0d, bcs) - op (0x0e, bvc) - op (0x0f, bvs) - op16 (0x10, to_r) - op16 (0x20, with_r) - op12 (0x30, stw_ir) - op (0x3c, loop) - op (0x3d, alt1) - op (0x3e, alt2) - op (0x3f, alt3) - op12 (0x40, ldw_ir) - op (0x4c, plot) - op (0x4d, swap) - op (0x4e, color) - op (0x4f, not) - op16 (0x50, add_r) - op16 (0x60, sub_r) - op (0x70, merge) - op15h(0x71, and_r) - op16 (0x80, mult_r) - op (0x90, sbk) - op4 (0x91, link) - op (0x95, sex) - op (0x96, asr) - op (0x97, ror) - op6 (0x98, jmp_r) - op (0x9e, lob) - op (0x9f, fmult) - op16 (0xa0, ibt_r) - op16 (0xb0, from_r) - op (0xc0, hib) - op15h(0xc1, or_r) - op15l(0xd0, inc_r) - op (0xdf, getc) - op15l(0xe0, dec_r) - op (0xef, getb) - op16 (0xf0, iwt_r) - #undef op - - //====== - // ALT1 - //====== - - #define op(id, name) opcode_table[256 + id] = &SuperFX::op_##name; - op (0x00, stop) - op (0x01, nop) - op (0x02, cache) - op (0x03, lsr) - op (0x04, rol) - op (0x05, bra) - op (0x06, blt) - op (0x07, bge) - op (0x08, bne) - op (0x09, beq) - op (0x0a, bpl) - op (0x0b, bmi) - op (0x0c, bcc) - op (0x0d, bcs) - op (0x0e, bvc) - op (0x0f, bvs) - op16 (0x10, to_r) - op16 (0x20, with_r) - op12 (0x30, stb_ir) - op (0x3c, loop) - op (0x3d, alt1) - op (0x3e, alt2) - op (0x3f, alt3) - op12 (0x40, ldb_ir) - op (0x4c, rpix) - op (0x4d, swap) - op (0x4e, cmode) - op (0x4f, not) - op16 (0x50, adc_r) - op16 (0x60, sbc_r) - op (0x70, merge) - op15h(0x71, bic_r) - op16 (0x80, umult_r) - op (0x90, sbk) - op4 (0x91, link) - op (0x95, sex) - op (0x96, div2) - op (0x97, ror) - op6 (0x98, ljmp_r) - op (0x9e, lob) - op (0x9f, lmult) - op16 (0xa0, lms_r) - op16 (0xb0, from_r) - op (0xc0, hib) - op15h(0xc1, xor_r) - op15l(0xd0, inc_r) - op (0xdf, getc) - op15l(0xe0, dec_r) - op (0xef, getbh) - op16 (0xf0, lm_r) - #undef op - - //====== - // ALT2 - //====== - - #define op(id, name) opcode_table[512 + id] = &SuperFX::op_##name; - op (0x00, stop) - op (0x01, nop) - op (0x02, cache) - op (0x03, lsr) - op (0x04, rol) - op (0x05, bra) - op (0x06, blt) - op (0x07, bge) - op (0x08, bne) - op (0x09, beq) - op (0x0a, bpl) - op (0x0b, bmi) - op (0x0c, bcc) - op (0x0d, bcs) - op (0x0e, bvc) - op (0x0f, bvs) - op16 (0x10, to_r) - op16 (0x20, with_r) - op12 (0x30, stw_ir) - op (0x3c, loop) - op (0x3d, alt1) - op (0x3e, alt2) - op (0x3f, alt3) - op12 (0x40, ldw_ir) - op (0x4c, plot) - op (0x4d, swap) - op (0x4e, color) - op (0x4f, not) - op16 (0x50, add_i) - op16 (0x60, sub_i) - op (0x70, merge) - op15h(0x71, and_i) - op16 (0x80, mult_i) - op (0x90, sbk) - op4 (0x91, link) - op (0x95, sex) - op (0x96, asr) - op (0x97, ror) - op6 (0x98, jmp_r) - op (0x9e, lob) - op (0x9f, fmult) - op16 (0xa0, sms_r) - op16 (0xb0, from_r) - op (0xc0, hib) - op15h(0xc1, or_i) - op15l(0xd0, inc_r) - op (0xdf, ramb) - op15l(0xe0, dec_r) - op (0xef, getbl) - op16 (0xf0, sm_r) - #undef op - - //====== - // ALT3 - //====== - - #define op(id, name) opcode_table[768 + id] = &SuperFX::op_##name; - op (0x00, stop) - op (0x01, nop) - op (0x02, cache) - op (0x03, lsr) - op (0x04, rol) - op (0x05, bra) - op (0x06, blt) - op (0x07, bge) - op (0x08, bne) - op (0x09, beq) - op (0x0a, bpl) - op (0x0b, bmi) - op (0x0c, bcc) - op (0x0d, bcs) - op (0x0e, bvc) - op (0x0f, bvs) - op16 (0x10, to_r) - op16 (0x20, with_r) - op12 (0x30, stb_ir) - op (0x3c, loop) - op (0x3d, alt1) - op (0x3e, alt2) - op (0x3f, alt3) - op12 (0x40, ldb_ir) - op (0x4c, rpix) - op (0x4d, swap) - op (0x4e, cmode) - op (0x4f, not) - op16 (0x50, adc_i) - op16 (0x60, cmp_r) - op (0x70, merge) - op15h(0x71, bic_i) - op16 (0x80, umult_i) - op (0x90, sbk) - op4 (0x91, link) - op (0x95, sex) - op (0x96, div2) - op (0x97, ror) - op6 (0x98, ljmp_r) - op (0x9e, lob) - op (0x9f, lmult) - op16 (0xa0, lms_r) - op16 (0xb0, from_r) - op (0xc0, hib) - op15h(0xc1, xor_i) - op15l(0xd0, inc_r) - op (0xdf, romb) - op15l(0xe0, dec_r) - op (0xef, getbs) - op16 (0xf0, lm_r) - #undef op - - #undef op4 - #undef op6 - #undef op12 - #undef op15l - #undef op15h - #undef op16 -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/superfx/core/opcodes.cpp b/waterbox/libsnes/bsnes/snes/chip/superfx/core/opcodes.cpp deleted file mode 100644 index 7d2f13a2f6..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/superfx/core/opcodes.cpp +++ /dev/null @@ -1,661 +0,0 @@ -#ifdef SUPERFX_CPP - -//$00 stop -void SuperFX::op_stop() { - if(regs.cfgr.irq == 0) { - regs.sfr.irq = 1; - cpu.regs.irq = 1; - } - - regs.sfr.g = 0; - regs.pipeline = 0x01; - regs.reset(); -} - -//$01 nop -void SuperFX::op_nop() { - regs.reset(); -} - -//$02 cache -void SuperFX::op_cache() { - if(regs.cbr != (regs.r[15] & 0xfff0)) { - regs.cbr = regs.r[15] & 0xfff0; - cache_flush(); - } - regs.reset(); -} - -//$03 lsr -void SuperFX::op_lsr() { - regs.sfr.cy = (regs.sr() & 1); - regs.dr() = regs.sr() >> 1; - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$04 rol -void SuperFX::op_rol() { - bool carry = (regs.sr() & 0x8000); - regs.dr() = (regs.sr() << 1) | regs.sfr.cy; - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.cy = carry; - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$05 bra e -void SuperFX::op_bra() { - regs.r[15] += (int8)pipe(); -} - -//$06 blt e -void SuperFX::op_blt() { - int e = (int8)pipe(); - if((regs.sfr.s ^ regs.sfr.ov) == 0) regs.r[15] += e; -} - -//$07 bge e -void SuperFX::op_bge() { - int e = (int8)pipe(); - if((regs.sfr.s ^ regs.sfr.ov) == 1) regs.r[15] += e; -} - -//$08 bne e -void SuperFX::op_bne() { - int e = (int8)pipe(); - if(regs.sfr.z == 0) regs.r[15] += e; -} - -//$09 beq e -void SuperFX::op_beq() { - int e = (int8)pipe(); - if(regs.sfr.z == 1) regs.r[15] += e; -} - -//$0a bpl e -void SuperFX::op_bpl() { - int e = (int8)pipe(); - if(regs.sfr.s == 0) regs.r[15] += e; -} - -//$0b bmi e -void SuperFX::op_bmi() { - int e = (int8)pipe(); - if(regs.sfr.s == 1) regs.r[15] += e; -} - -//$0c bcc e -void SuperFX::op_bcc() { - int e = (int8)pipe(); - if(regs.sfr.cy == 0) regs.r[15] += e; -} - -//$0d bcs e -void SuperFX::op_bcs() { - int e = (int8)pipe(); - if(regs.sfr.cy == 1) regs.r[15] += e; -} - -//$0e bvc e -void SuperFX::op_bvc() { - int e = (int8)pipe(); - if(regs.sfr.ov == 0) regs.r[15] += e; -} - -//$0f bvs e -void SuperFX::op_bvs() { - int e = (int8)pipe(); - if(regs.sfr.ov == 1) regs.r[15] += e; -} - -//$10-1f(b0): to rN -//$10-1f(b1): move rN -template void SuperFX::op_to_r() { - if(regs.sfr.b == 0) { - regs.dreg = n; - } else { - regs.r[n] = regs.sr(); - regs.reset(); - } -} - -//$20-2f: with rN -template void SuperFX::op_with_r() { - regs.sreg = n; - regs.dreg = n; - regs.sfr.b = 1; -} - -//$30-3b(alt0): stw (rN) -template void SuperFX::op_stw_ir() { - regs.ramaddr = regs.r[n]; - rambuffer_write(regs.ramaddr ^ 0, regs.sr() >> 0); - rambuffer_write(regs.ramaddr ^ 1, regs.sr() >> 8); - regs.reset(); -} - -//$30-3b(alt1): stb (rN) -template void SuperFX::op_stb_ir() { - regs.ramaddr = regs.r[n]; - rambuffer_write(regs.ramaddr, regs.sr()); - regs.reset(); -} - -//$3c loop -void SuperFX::op_loop() { - regs.r[12]--; - regs.sfr.s = (regs.r[12] & 0x8000); - regs.sfr.z = (regs.r[12] == 0); - if(!regs.sfr.z) regs.r[15] = regs.r[13]; - regs.reset(); -} - -//$3d alt1 -void SuperFX::op_alt1() { - regs.sfr.b = 0; - regs.sfr.alt1 = 1; -} - -//$3e alt2 -void SuperFX::op_alt2() { - regs.sfr.b = 0; - regs.sfr.alt2 = 1; -} - -//$3f alt3 -void SuperFX::op_alt3() { - regs.sfr.b = 0; - regs.sfr.alt1 = 1; - regs.sfr.alt2 = 1; -} - -//$40-4b(alt0): ldw (rN) -template void SuperFX::op_ldw_ir() { - regs.ramaddr = regs.r[n]; - uint16_t data; - data = rambuffer_read(regs.ramaddr ^ 0) << 0; - data |= rambuffer_read(regs.ramaddr ^ 1) << 8; - regs.dr() = data; - regs.reset(); -} - -//$40-4b(alt1): ldb (rN) -template void SuperFX::op_ldb_ir() { - regs.ramaddr = regs.r[n]; - regs.dr() = rambuffer_read(regs.ramaddr); - regs.reset(); -} - -//$4c(alt0): plot -void SuperFX::op_plot() { - plot(regs.r[1], regs.r[2]); - regs.r[1]++; - regs.reset(); -} - -//$4c(alt1): rpix -void SuperFX::op_rpix() { - regs.dr() = rpix(regs.r[1], regs.r[2]); - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$4d: swap -void SuperFX::op_swap() { - regs.dr() = (regs.sr() >> 8) | (regs.sr() << 8); - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$4e(alt0): color -void SuperFX::op_color() { - regs.colr = color(regs.sr()); - regs.reset(); -} - -//$4e(alt1): cmode -void SuperFX::op_cmode() { - regs.por = regs.sr(); - regs.reset(); -} - -//$4f: not -void SuperFX::op_not() { - regs.dr() = ~regs.sr(); - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$50-5f(alt0): add rN -template void SuperFX::op_add_r() { - int r = regs.sr() + regs.r[n]; - regs.sfr.ov = ~(regs.sr() ^ regs.r[n]) & (regs.r[n] ^ r) & 0x8000; - regs.sfr.s = (r & 0x8000); - regs.sfr.cy = (r >= 0x10000); - regs.sfr.z = ((uint16_t)r == 0); - regs.dr() = r; - regs.reset(); -} - -//$50-5f(alt1): adc rN -template void SuperFX::op_adc_r() { - int r = regs.sr() + regs.r[n] + regs.sfr.cy; - regs.sfr.ov = ~(regs.sr() ^ regs.r[n]) & (regs.r[n] ^ r) & 0x8000; - regs.sfr.s = (r & 0x8000); - regs.sfr.cy = (r >= 0x10000); - regs.sfr.z = ((uint16_t)r == 0); - regs.dr() = r; - regs.reset(); -} - -//$50-5f(alt2): add #N -template void SuperFX::op_add_i() { - int r = regs.sr() + n; - regs.sfr.ov = ~(regs.sr() ^ n) & (n ^ r) & 0x8000; - regs.sfr.s = (r & 0x8000); - regs.sfr.cy = (r >= 0x10000); - regs.sfr.z = ((uint16_t)r == 0); - regs.dr() = r; - regs.reset(); -} - -//$50-5f(alt3): adc #N -template void SuperFX::op_adc_i() { - int r = regs.sr() + n + regs.sfr.cy; - regs.sfr.ov = ~(regs.sr() ^ n) & (n ^ r) & 0x8000; - regs.sfr.s = (r & 0x8000); - regs.sfr.cy = (r >= 0x10000); - regs.sfr.z = ((uint16_t)r == 0); - regs.dr() = r; - regs.reset(); -} - -//$60-6f(alt0): sub rN -template void SuperFX::op_sub_r() { - int r = regs.sr() - regs.r[n]; - regs.sfr.ov = (regs.sr() ^ regs.r[n]) & (regs.sr() ^ r) & 0x8000; - regs.sfr.s = (r & 0x8000); - regs.sfr.cy = (r >= 0); - regs.sfr.z = ((uint16_t)r == 0); - regs.dr() = r; - regs.reset(); -} - -//$60-6f(alt1): sbc rN -template void SuperFX::op_sbc_r() { - int r = regs.sr() - regs.r[n] - !regs.sfr.cy; - regs.sfr.ov = (regs.sr() ^ regs.r[n]) & (regs.sr() ^ r) & 0x8000; - regs.sfr.s = (r & 0x8000); - regs.sfr.cy = (r >= 0); - regs.sfr.z = ((uint16_t)r == 0); - regs.dr() = r; - regs.reset(); -} - -//$60-6f(alt2): sub #N -template void SuperFX::op_sub_i() { - int r = regs.sr() - n; - regs.sfr.ov = (regs.sr() ^ n) & (regs.sr() ^ r) & 0x8000; - regs.sfr.s = (r & 0x8000); - regs.sfr.cy = (r >= 0); - regs.sfr.z = ((uint16_t)r == 0); - regs.dr() = r; - regs.reset(); -} - -//$60-6f(alt3): cmp rN -template void SuperFX::op_cmp_r() { - int r = regs.sr() - regs.r[n]; - regs.sfr.ov = (regs.sr() ^ regs.r[n]) & (regs.sr() ^ r) & 0x8000; - regs.sfr.s = (r & 0x8000); - regs.sfr.cy = (r >= 0); - regs.sfr.z = ((uint16_t)r == 0); - regs.reset(); -} - -//$70: merge -void SuperFX::op_merge() { - regs.dr() = (regs.r[7] & 0xff00) | (regs.r[8] >> 8); - regs.sfr.ov = (regs.dr() & 0xc0c0); - regs.sfr.s = (regs.dr() & 0x8080); - regs.sfr.cy = (regs.dr() & 0xe0e0); - regs.sfr.z = (regs.dr() & 0xf0f0); - regs.reset(); -} - -//$71-7f(alt0): and rN -template void SuperFX::op_and_r() { - regs.dr() = regs.sr() & regs.r[n]; - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$71-7f(alt1): bic rN -template void SuperFX::op_bic_r() { - regs.dr() = regs.sr() & ~regs.r[n]; - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$71-7f(alt2): and #N -template void SuperFX::op_and_i() { - regs.dr() = regs.sr() & n; - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$71-7f(alt3): bic #N -template void SuperFX::op_bic_i() { - regs.dr() = regs.sr() & ~n; - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$80-8f(alt0): mult rN -template void SuperFX::op_mult_r() { - regs.dr() = (int8)regs.sr() * (int8)regs.r[n]; - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); - if(!regs.cfgr.ms0) add_clocks(2); -} - -//$80-8f(alt1): umult rN -template void SuperFX::op_umult_r() { - regs.dr() = (uint8)regs.sr() * (uint8)regs.r[n]; - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); - if(!regs.cfgr.ms0) add_clocks(2); -} - -//$80-8f(alt2): mult #N -template void SuperFX::op_mult_i() { - regs.dr() = (int8)regs.sr() * (int8)n; - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); - if(!regs.cfgr.ms0) add_clocks(2); -} - -//$80-8f(alt3): umult #N -template void SuperFX::op_umult_i() { - regs.dr() = (uint8)regs.sr() * (uint8)n; - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); - if(!regs.cfgr.ms0) add_clocks(2); -} - -//$90: sbk -void SuperFX::op_sbk() { - rambuffer_write(regs.ramaddr ^ 0, regs.sr() >> 0); - rambuffer_write(regs.ramaddr ^ 1, regs.sr() >> 8); - regs.reset(); -} - -//$91-94: link #N -template void SuperFX::op_link() { - regs.r[11] = regs.r[15] + n; - regs.reset(); -} - -//$95: sex -void SuperFX::op_sex() { - regs.dr() = (int8)regs.sr(); - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$96(alt0): asr -void SuperFX::op_asr() { - regs.sfr.cy = (regs.sr() & 1); - regs.dr() = (int16_t)regs.sr() >> 1; - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$96(alt1): div2 -void SuperFX::op_div2() { - regs.sfr.cy = (regs.sr() & 1); - regs.dr() = ((int16_t)regs.sr() >> 1) + ((regs.sr() + 1) >> 16); - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$97: ror -void SuperFX::op_ror() { - bool carry = (regs.sr() & 1); - regs.dr() = (regs.sfr.cy << 15) | (regs.sr() >> 1); - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.cy = carry; - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$98-9d(alt0): jmp rN -template void SuperFX::op_jmp_r() { - regs.r[15] = regs.r[n]; - regs.reset(); -} - -//$98-9d(alt1): ljmp rN -template void SuperFX::op_ljmp_r() { - regs.pbr = regs.r[n] & 0x7f; - regs.r[15] = regs.sr(); - regs.cbr = regs.r[15] & 0xfff0; - cache_flush(); - regs.reset(); -} - -//$9e: lob -void SuperFX::op_lob() { - regs.dr() = regs.sr() & 0xff; - regs.sfr.s = (regs.dr() & 0x80); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$9f(alt0): fmult -void SuperFX::op_fmult() { - uint32_t result = (int16_t)regs.sr() * (int16_t)regs.r[6]; - regs.dr() = result >> 16; - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.cy = (result & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); - add_clocks(4 + (regs.cfgr.ms0 << 2)); -} - -//$9f(alt1): lmult -void SuperFX::op_lmult() { - uint32_t result = (int16_t)regs.sr() * (int16_t)regs.r[6]; - regs.r[4] = result; - regs.dr() = result >> 16; - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.cy = (result & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); - add_clocks(4 + (regs.cfgr.ms0 << 2)); -} - -//$a0-af(alt0): ibt rN,#pp -template void SuperFX::op_ibt_r() { - regs.r[n] = (int8)pipe(); - regs.reset(); -} - -//$a0-af(alt1): lms rN,(yy) -template void SuperFX::op_lms_r() { - regs.ramaddr = pipe() << 1; - uint16_t data; - data = rambuffer_read(regs.ramaddr ^ 0) << 0; - data |= rambuffer_read(regs.ramaddr ^ 1) << 8; - regs.r[n] = data; - regs.reset(); -} - -//$a0-af(alt2): sms (yy),rN -template void SuperFX::op_sms_r() { - regs.ramaddr = pipe() << 1; - rambuffer_write(regs.ramaddr ^ 0, regs.r[n] >> 0); - rambuffer_write(regs.ramaddr ^ 1, regs.r[n] >> 8); - regs.reset(); -} - -//$b0-bf(b0): from rN -//$b0-bf(b1): moves rN -template void SuperFX::op_from_r() { - if(regs.sfr.b == 0) { - regs.sreg = n; - } else { - regs.dr() = regs.r[n]; - regs.sfr.ov = (regs.dr() & 0x80); - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); - } -} - -//$c0: hib -void SuperFX::op_hib() { - regs.dr() = regs.sr() >> 8; - regs.sfr.s = (regs.dr() & 0x80); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$c1-cf(alt0): or rN -template void SuperFX::op_or_r() { - regs.dr() = regs.sr() | regs.r[n]; - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$c1-cf(alt1): xor rN -template void SuperFX::op_xor_r() { - regs.dr() = regs.sr() ^ regs.r[n]; - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$c1-cf(alt2): or #N -template void SuperFX::op_or_i() { - regs.dr() = regs.sr() | n; - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$c1-cf(alt3): xor #N -template void SuperFX::op_xor_i() { - regs.dr() = regs.sr() ^ n; - regs.sfr.s = (regs.dr() & 0x8000); - regs.sfr.z = (regs.dr() == 0); - regs.reset(); -} - -//$d0-de: inc rN -template void SuperFX::op_inc_r() { - regs.r[n]++; - regs.sfr.s = (regs.r[n] & 0x8000); - regs.sfr.z = (regs.r[n] == 0); - regs.reset(); -} - -//$df(alt0): getc -void SuperFX::op_getc() { - regs.colr = color(rombuffer_read()); - regs.reset(); -} - -//$df(alt2): ramb -void SuperFX::op_ramb() { - rambuffer_sync(); - regs.rambr = regs.sr(); - regs.reset(); -} - -//$df(alt3): romb -void SuperFX::op_romb() { - rombuffer_sync(); - regs.rombr = regs.sr() & 0x7f; - regs.reset(); -} - -//$e0-ee: dec rN -template void SuperFX::op_dec_r() { - regs.r[n]--; - regs.sfr.s = (regs.r[n] & 0x8000); - regs.sfr.z = (regs.r[n] == 0); - regs.reset(); -} - -//$ef(alt0): getb -void SuperFX::op_getb() { - regs.dr() = rombuffer_read(); - regs.reset(); -} - -//$ef(alt1): getbh -void SuperFX::op_getbh() { - regs.dr() = (rombuffer_read() << 8) | (regs.sr() & 0x00ff); - regs.reset(); -} - -//$ef(alt2): getbl -void SuperFX::op_getbl() { - regs.dr() = (regs.sr() & 0xff00) | (rombuffer_read() << 0); - regs.reset(); -} - -//$ef(alt3): getbs -void SuperFX::op_getbs() { - regs.dr() = (int8)rombuffer_read(); - regs.reset(); -} - -//$f0-ff(alt0): iwt rN,#xx -template void SuperFX::op_iwt_r() { - uint16_t data; - data = pipe() << 0; - data |= pipe() << 8; - regs.r[n] = data; - regs.reset(); -} - -//$f0-ff(alt1): lm rN,(xx) -template void SuperFX::op_lm_r() { - regs.ramaddr = pipe() << 0; - regs.ramaddr |= pipe() << 8; - uint16_t data; - data = rambuffer_read(regs.ramaddr ^ 0) << 0; - data |= rambuffer_read(regs.ramaddr ^ 1) << 8; - regs.r[n] = data; - regs.reset(); -} - -//$f0-ff(alt2): sm (xx),rN -template void SuperFX::op_sm_r() { - regs.ramaddr = pipe() << 0; - regs.ramaddr |= pipe() << 8; - rambuffer_write(regs.ramaddr ^ 0, regs.r[n] >> 0); - rambuffer_write(regs.ramaddr ^ 1, regs.r[n] >> 8); - regs.reset(); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/superfx/core/registers.hpp b/waterbox/libsnes/bsnes/snes/chip/superfx/core/registers.hpp deleted file mode 100644 index ac193a8a7b..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/superfx/core/registers.hpp +++ /dev/null @@ -1,176 +0,0 @@ -//accepts a callback binding so r14 writes can trigger ROM buffering transparently -struct reg16_t { - uint16 data; - function on_modify; - - inline operator unsigned() const { return data; } - inline uint16 assign(uint16 i) { - if(on_modify) on_modify(i); - else data = i; - return data; - } - - inline unsigned operator++() { return assign(data + 1); } - inline unsigned operator--() { return assign(data - 1); } - inline unsigned operator++(int) { unsigned r = data; assign(data + 1); return r; } - inline unsigned operator--(int) { unsigned r = data; assign(data - 1); return r; } - inline unsigned operator = (unsigned i) { return assign(i); } - inline unsigned operator |= (unsigned i) { return assign(data | i); } - inline unsigned operator ^= (unsigned i) { return assign(data ^ i); } - inline unsigned operator &= (unsigned i) { return assign(data & i); } - inline unsigned operator <<= (unsigned i) { return assign(data << i); } - inline unsigned operator >>= (unsigned i) { return assign(data >> i); } - inline unsigned operator += (unsigned i) { return assign(data + i); } - inline unsigned operator -= (unsigned i) { return assign(data - i); } - inline unsigned operator *= (unsigned i) { return assign(data * i); } - inline unsigned operator /= (unsigned i) { return assign(data / i); } - inline unsigned operator %= (unsigned i) { return assign(data % i); } - - inline unsigned operator = (const reg16_t& i) { return assign(i); } - - reg16_t() : data(0) {} - reg16_t(const reg16_t&) = delete; -}; - -struct sfr_t { - bool irq; //interrupt flag - bool b; //WITH flag - bool ih; //immediate higher 8-bit flag - bool il; //immediate lower 8-bit flag - bool alt2; //ALT2 mode - bool alt1; //ALT2 instruction mode - bool r; //ROM r14 read flag - bool g; //GO flag - bool ov; //overflow flag - bool s; //sign flag - bool cy; //carry flag - bool z; //zero flag - - operator unsigned() const { - return (irq << 15) | (b << 12) | (ih << 11) | (il << 10) | (alt2 << 9) | (alt1 << 8) - | (r << 6) | (g << 5) | (ov << 4) | (s << 3) | (cy << 2) | (z << 1); - } - - sfr_t& operator=(uint16_t data) { - irq = data & 0x8000; - b = data & 0x1000; - ih = data & 0x0800; - il = data & 0x0400; - alt2 = data & 0x0200; - alt1 = data & 0x0100; - r = data & 0x0040; - g = data & 0x0020; - ov = data & 0x0010; - s = data & 0x0008; - cy = data & 0x0004; - z = data & 0x0002; - return *this; - } -}; - -struct scmr_t { - unsigned ht; - bool ron; - bool ran; - unsigned md; - - operator unsigned() const { - return ((ht >> 1) << 5) | (ron << 4) | (ran << 3) | ((ht & 1) << 2) | (md); - } - - scmr_t& operator=(uint8 data) { - ht = (bool)(data & 0x20) << 1; - ht |= (bool)(data & 0x04) << 0; - ron = data & 0x10; - ran = data & 0x08; - md = data & 0x03; - return *this; - } -}; - -struct por_t { - bool obj; - bool freezehigh; - bool highnibble; - bool dither; - bool transparent; - - operator unsigned() const { - return (obj << 4) | (freezehigh << 3) | (highnibble << 2) | (dither << 1) | (transparent); - } - - por_t& operator=(uint8 data) { - obj = data & 0x10; - freezehigh = data & 0x08; - highnibble = data & 0x04; - dither = data & 0x02; - transparent = data & 0x01; - return *this; - } -}; - -struct cfgr_t { - bool irq; - bool ms0; - - operator unsigned() const { - return (irq << 7) | (ms0 << 5); - } - - cfgr_t& operator=(uint8 data) { - irq = data & 0x80; - ms0 = data & 0x20; - return *this; - } -}; - -struct regs_t { - uint8 pipeline; - uint16 ramaddr; - - reg16_t r[16]; //general purpose registers - sfr_t sfr; //status flag register - uint8 pbr; //program bank register - uint8 rombr; //game pack ROM bank register - bool rambr; //game pack RAM bank register - uint16 cbr; //cache base register - uint8 scbr; //screen base register - scmr_t scmr; //screen mode register - uint8 colr; //color register - por_t por; //plot option register - bool bramr; //back-up RAM register - uint8 vcr; //version code register - cfgr_t cfgr; //config register - bool clsr; //clock select register - - unsigned romcl; //clock ticks until romdr is valid - uint8 romdr; //ROM buffer data register - - unsigned ramcl; //clock ticks until ramdr is valid - uint16 ramar; //RAM buffer address register - uint8 ramdr; //RAM buffer data register - - unsigned sreg, dreg; - reg16_t& sr() { return r[sreg]; } //source register (from) - reg16_t& dr() { return r[dreg]; } //destination register (to) - - void reset() { - sfr.b = 0; - sfr.alt1 = 0; - sfr.alt2 = 0; - - sreg = 0; - dreg = 0; - } -} regs; - -struct cache_t { - uint8 buffer[512]; - bool valid[32]; -} cache; - -struct pixelcache_t { - uint16 offset; - uint8 bitpend; - uint8 data[8]; -} pixelcache[2]; diff --git a/waterbox/libsnes/bsnes/snes/chip/superfx/disasm/disasm.cpp b/waterbox/libsnes/bsnes/snes/chip/superfx/disasm/disasm.cpp deleted file mode 100644 index f3454e6081..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/superfx/disasm/disasm.cpp +++ /dev/null @@ -1,279 +0,0 @@ -#ifdef SUPERFX_CPP - -void SuperFX::disassemble_opcode(char *output) { - *output = 0; - - if(!regs.sfr.alt2) { - if(!regs.sfr.alt1) { - disassemble_alt0(output); - } else { - disassemble_alt1(output); - } - } else { - if(!regs.sfr.alt1) { - disassemble_alt2(output); - } else { - disassemble_alt3(output); - } - } - - unsigned length = strlen(output); - while(length++ < 20) strcat(output, " "); -} - -#define case4(id) \ - case id+ 0: case id+ 1: case id+ 2: case id+ 3 -#define case6(id) \ - case id+ 0: case id+ 1: case id+ 2: case id+ 3: case id+ 4: case id+ 5 -#define case12(id) \ - case id+ 0: case id+ 1: case id+ 2: case id+ 3: case id+ 4: case id+ 5: case id+ 6: case id+ 7: \ - case id+ 8: case id+ 9: case id+10: case id+11 -#define case15(id) \ - case id+ 0: case id+ 1: case id+ 2: case id+ 3: case id+ 4: case id+ 5: case id+ 6: case id+ 7: \ - case id+ 8: case id+ 9: case id+10: case id+11: case id+12: case id+13: case id+14 -#define case16(id) \ - case id+ 0: case id+ 1: case id+ 2: case id+ 3: case id+ 4: case id+ 5: case id+ 6: case id+ 7: \ - case id+ 8: case id+ 9: case id+10: case id+11: case id+12: case id+13: case id+14: case id+15 - -#define op0 regs.pipeline -#define op1 bus_read((regs.pbr << 16) + regs.r[15] + 0) -#define op2 bus_read((regs.pbr << 16) + regs.r[15] + 1) - -void SuperFX::disassemble_alt0(char *output) { - char t[256] = ""; - switch(op0) { - case (0x00): sprintf(t, "stop"); break; - case (0x01): sprintf(t, "nop"); break; - case (0x02): sprintf(t, "cache"); break; - case (0x03): sprintf(t, "lsr"); break; - case (0x04): sprintf(t, "rol"); break; - case (0x05): sprintf(t, "bra %+d", (int8_t)op1); break; - case (0x06): sprintf(t, "blt %+d", (int8_t)op1); break; - case (0x07): sprintf(t, "bge %+d", (int8_t)op1); break; - case (0x08): sprintf(t, "bne %+d", (int8_t)op1); break; - case (0x09): sprintf(t, "beq %+d", (int8_t)op1); break; - case (0x0a): sprintf(t, "bpl %+d", (int8_t)op1); break; - case (0x0b): sprintf(t, "bmi %+d", (int8_t)op1); break; - case (0x0c): sprintf(t, "bcc %+d", (int8_t)op1); break; - case (0x0d): sprintf(t, "bcs %+d", (int8_t)op1); break; - case (0x0e): sprintf(t, "bvc %+d", (int8_t)op1); break; - case (0x0f): sprintf(t, "bvs %+d", (int8_t)op1); break; - case16(0x10): sprintf(t, "to r%u", op0 & 15); break; - case16(0x20): sprintf(t, "with r%u", op0 & 15); break; - case12(0x30): sprintf(t, "stw (r%u)", op0 & 15); break; - case (0x3c): sprintf(t, "loop"); break; - case (0x3d): sprintf(t, "alt1"); break; - case (0x3e): sprintf(t, "alt2"); break; - case (0x3f): sprintf(t, "alt3"); break; - case12(0x40): sprintf(t, "ldw (r%u)", op0 & 15); break; - case (0x4c): sprintf(t, "plot"); break; - case (0x4d): sprintf(t, "swap"); break; - case (0x4e): sprintf(t, "color"); break; - case (0x4f): sprintf(t, "not"); break; - case16(0x50): sprintf(t, "add r%u", op0 & 15); break; - case16(0x60): sprintf(t, "sub r%u", op0 & 15); break; - case (0x70): sprintf(t, "merge"); break; - case15(0x71): sprintf(t, "and r%u", op0 & 15); break; - case16(0x80): sprintf(t, "mult r%u", op0 & 15); break; - case (0x90): sprintf(t, "sbk"); break; - case4 (0x91): sprintf(t, "link #%u", op0 & 15); break; - case (0x95): sprintf(t, "sex"); break; - case (0x96): sprintf(t, "asr"); break; - case (0x97): sprintf(t, "ror"); break; - case6 (0x98): sprintf(t, "jmp r%u", op0 & 15); break; - case (0x9e): sprintf(t, "lob"); break; - case (0x9f): sprintf(t, "fmult"); break; - case16(0xa0): sprintf(t, "ibt r%u,#$%.2x", op0 & 15, op1); break; - case16(0xb0): sprintf(t, "from r%u", op0 & 15); break; - case (0xc0): sprintf(t, "hib"); - case15(0xc1): sprintf(t, "or r%u", op0 & 15); break; - case15(0xd0): sprintf(t, "inc r%u", op0 & 15); break; - case (0xdf): sprintf(t, "getc"); break; - case15(0xe0): sprintf(t, "dec r%u", op0 & 15); break; - case (0xef): sprintf(t, "getb"); break; - case16(0xf0): sprintf(t, "iwt r%u,#$%.2x%.2x", op0 & 15, op2, op1); break; - } - strcat(output, t); -} - -void SuperFX::disassemble_alt1(char *output) { - char t[256] = ""; - switch(op0) { - case (0x00): sprintf(t, "stop"); break; - case (0x01): sprintf(t, "nop"); break; - case (0x02): sprintf(t, "cache"); break; - case (0x03): sprintf(t, "lsr"); break; - case (0x04): sprintf(t, "rol"); break; - case (0x05): sprintf(t, "bra %+d", (int8_t)op1); break; - case (0x06): sprintf(t, "blt %+d", (int8_t)op1); break; - case (0x07): sprintf(t, "bge %+d", (int8_t)op1); break; - case (0x08): sprintf(t, "bne %+d", (int8_t)op1); break; - case (0x09): sprintf(t, "beq %+d", (int8_t)op1); break; - case (0x0a): sprintf(t, "bpl %+d", (int8_t)op1); break; - case (0x0b): sprintf(t, "bmi %+d", (int8_t)op1); break; - case (0x0c): sprintf(t, "bcc %+d", (int8_t)op1); break; - case (0x0d): sprintf(t, "bcs %+d", (int8_t)op1); break; - case (0x0e): sprintf(t, "bvc %+d", (int8_t)op1); break; - case (0x0f): sprintf(t, "bvs %+d", (int8_t)op1); break; - case16(0x10): sprintf(t, "to r%u", op0 & 15); break; - case16(0x20): sprintf(t, "with r%u", op0 & 15); break; - case12(0x30): sprintf(t, "stb (r%u)", op0 & 15); break; - case (0x3c): sprintf(t, "loop"); break; - case (0x3d): sprintf(t, "alt1"); break; - case (0x3e): sprintf(t, "alt2"); break; - case (0x3f): sprintf(t, "alt3"); break; - case12(0x40): sprintf(t, "ldb (r%u)", op0 & 15); break; - case (0x4c): sprintf(t, "rpix"); break; - case (0x4d): sprintf(t, "swap"); break; - case (0x4e): sprintf(t, "cmode"); break; - case (0x4f): sprintf(t, "not"); break; - case16(0x50): sprintf(t, "adc r%u", op0 & 15); break; - case16(0x60): sprintf(t, "sbc r%u", op0 & 15); break; - case (0x70): sprintf(t, "merge"); break; - case15(0x71): sprintf(t, "bic r%u", op0 & 15); break; - case16(0x80): sprintf(t, "umult r%u", op0 & 15); break; - case (0x90): sprintf(t, "sbk"); break; - case4 (0x91): sprintf(t, "link #%u", op0 & 15); break; - case (0x95): sprintf(t, "sex"); break; - case (0x96): sprintf(t, "div2"); break; - case (0x97): sprintf(t, "ror"); break; - case6 (0x98): sprintf(t, "ljmp r%u", op0 & 15); break; - case (0x9e): sprintf(t, "lob"); break; - case (0x9f): sprintf(t, "lmult"); break; - case16(0xa0): sprintf(t, "lms r%u,(#$%.4x)", op0 & 15, op1 << 1); break; - case16(0xb0): sprintf(t, "from r%u", op0 & 15); break; - case (0xc0): sprintf(t, "hib"); break; - case15(0xc1): sprintf(t, "xor r%u", op0 & 15); break; - case15(0xd0): sprintf(t, "inc r%u", op0 & 15); break; - case (0xdf): sprintf(t, "getc"); break; - case15(0xe0): sprintf(t, "dec r%u", op0 & 15); break; - case (0xef): sprintf(t, "getbh"); break; - case16(0xf0): sprintf(t, "lm r%u", op0 & 15); break; - } - strcat(output, t); -} - -void SuperFX::disassemble_alt2(char *output) { - char t[256] = ""; - switch(op0) { - case (0x00): sprintf(t, "stop"); break; - case (0x01): sprintf(t, "nop"); break; - case (0x02): sprintf(t, "cache"); break; - case (0x03): sprintf(t, "lsr"); break; - case (0x04): sprintf(t, "rol"); break; - case (0x05): sprintf(t, "bra %+d", (int8_t)op1); break; - case (0x06): sprintf(t, "blt %+d", (int8_t)op1); break; - case (0x07): sprintf(t, "bge %+d", (int8_t)op1); break; - case (0x08): sprintf(t, "bne %+d", (int8_t)op1); break; - case (0x09): sprintf(t, "beq %+d", (int8_t)op1); break; - case (0x0a): sprintf(t, "bpl %+d", (int8_t)op1); break; - case (0x0b): sprintf(t, "bmi %+d", (int8_t)op1); break; - case (0x0c): sprintf(t, "bcc %+d", (int8_t)op1); break; - case (0x0d): sprintf(t, "bcs %+d", (int8_t)op1); break; - case (0x0e): sprintf(t, "bvc %+d", (int8_t)op1); break; - case (0x0f): sprintf(t, "bvs %+d", (int8_t)op1); break; - case16(0x10): sprintf(t, "to r%u", op0 & 15); break; - case16(0x20): sprintf(t, "with r%u", op0 & 15); break; - case12(0x30): sprintf(t, "stw (r%u)", op0 & 15); break; - case (0x3c): sprintf(t, "loop"); break; - case (0x3d): sprintf(t, "alt1"); break; - case (0x3e): sprintf(t, "alt2"); break; - case (0x3f): sprintf(t, "alt3"); break; - case12(0x40): sprintf(t, "ldw (r%u)", op0 & 15); break; - case (0x4c): sprintf(t, "plot"); break; - case (0x4d): sprintf(t, "swap"); break; - case (0x4e): sprintf(t, "color"); break; - case (0x4f): sprintf(t, "not"); break; - case16(0x50): sprintf(t, "add #%u", op0 & 15); break; - case16(0x60): sprintf(t, "sub #%u", op0 & 15); break; - case (0x70): sprintf(t, "merge"); break; - case15(0x71): sprintf(t, "and #%u", op0 & 15); break; - case16(0x80): sprintf(t, "mult #%u", op0 & 15); break; - case (0x90): sprintf(t, "sbk"); break; - case4 (0x91): sprintf(t, "link #%u", op0 & 15); break; - case (0x95): sprintf(t, "sex"); break; - case (0x96): sprintf(t, "asr"); break; - case (0x97): sprintf(t, "ror"); break; - case6 (0x98): sprintf(t, "jmp r%u", op0 & 15); break; - case (0x9e): sprintf(t, "lob"); break; - case (0x9f): sprintf(t, "fmult"); break; - case16(0xa0): sprintf(t, "sms r%u,(#$%.4x)", op0 & 15, op1 << 1); break; - case16(0xb0): sprintf(t, "from r%u", op0 & 15); break; - case (0xc0): sprintf(t, "hib"); break; - case15(0xc1): sprintf(t, "or #%u", op0 & 15); break; - case15(0xd0): sprintf(t, "inc r%u", op0 & 15); break; - case (0xdf): sprintf(t, "ramb"); break; - case15(0xe0): sprintf(t, "dec r%u", op0 & 15); break; - case (0xef): sprintf(t, "getbl"); break; - case16(0xf0): sprintf(t, "sm r%u", op0 & 15); break; - } - strcat(output, t); -} - -void SuperFX::disassemble_alt3(char *output) { - char t[256] = ""; - switch(op0) { - case (0x00): sprintf(t, "stop"); break; - case (0x01): sprintf(t, "nop"); break; - case (0x02): sprintf(t, "cache"); break; - case (0x03): sprintf(t, "lsr"); break; - case (0x04): sprintf(t, "rol"); break; - case (0x05): sprintf(t, "bra %+d", (int8_t)op1); break; - case (0x06): sprintf(t, "blt %+d", (int8_t)op1); break; - case (0x07): sprintf(t, "bge %+d", (int8_t)op1); break; - case (0x08): sprintf(t, "bne %+d", (int8_t)op1); break; - case (0x09): sprintf(t, "beq %+d", (int8_t)op1); break; - case (0x0a): sprintf(t, "bpl %+d", (int8_t)op1); break; - case (0x0b): sprintf(t, "bmi %+d", (int8_t)op1); break; - case (0x0c): sprintf(t, "bcc %+d", (int8_t)op1); break; - case (0x0d): sprintf(t, "bcs %+d", (int8_t)op1); break; - case (0x0e): sprintf(t, "bvc %+d", (int8_t)op1); break; - case (0x0f): sprintf(t, "bvs %+d", (int8_t)op1); break; - case16(0x10): sprintf(t, "to r%u", op0 & 15); break; - case16(0x20): sprintf(t, "with r%u", op0 & 15); break; - case12(0x30): sprintf(t, "stb (r%u)", op0 & 15); break; - case (0x3c): sprintf(t, "loop"); break; - case (0x3d): sprintf(t, "alt1"); break; - case (0x3e): sprintf(t, "alt2"); break; - case (0x3f): sprintf(t, "alt3"); break; - case12(0x40): sprintf(t, "ldb (r%u)", op0 & 15); break; - case (0x4c): sprintf(t, "rpix"); break; - case (0x4d): sprintf(t, "swap"); break; - case (0x4e): sprintf(t, "cmode"); break; - case (0x4f): sprintf(t, "not"); break; - case16(0x50): sprintf(t, "adc #%u", op0 & 15); break; - case16(0x60): sprintf(t, "cmp r%u", op0 & 15); break; - case (0x70): sprintf(t, "merge"); break; - case15(0x71): sprintf(t, "bic #%u", op0 & 15); break; - case16(0x80): sprintf(t, "umult #%u", op0 & 15); break; - case (0x90): sprintf(t, "sbk"); break; - case4 (0x91): sprintf(t, "link #%u", op0 & 15); break; - case (0x95): sprintf(t, "sex"); break; - case (0x96): sprintf(t, "div2"); break; - case (0x97): sprintf(t, "ror"); break; - case6 (0x98): sprintf(t, "ljmp r%u", op0 & 15); break; - case (0x9e): sprintf(t, "lob"); break; - case (0x9f): sprintf(t, "lmult"); break; - case16(0xa0): sprintf(t, "lms r%u", op0 & 15); break; - case16(0xb0): sprintf(t, "from r%u", op0 & 15); break; - case (0xc0): sprintf(t, "hib"); break; - case15(0xc1): sprintf(t, "xor #%u", op0 & 15); break; - case15(0xd0): sprintf(t, "inc r%u", op0 & 15); break; - case (0xdf): sprintf(t, "romb"); break; - case15(0xe0): sprintf(t, "dec r%u", op0 & 15); break; - case (0xef): sprintf(t, "getbs"); break; - case16(0xf0): sprintf(t, "lm r%u", op0 & 15); break; - } - strcat(output, t); -} - -#undef case4 -#undef case6 -#undef case12 -#undef case15 -#undef case16 -#undef op0 -#undef op1 -#undef op2 - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/superfx/disasm/disasm.hpp b/waterbox/libsnes/bsnes/snes/chip/superfx/disasm/disasm.hpp deleted file mode 100644 index 903615eb78..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/superfx/disasm/disasm.hpp +++ /dev/null @@ -1,5 +0,0 @@ -void disassemble_opcode(char *output); -void disassemble_alt0(char *output); -void disassemble_alt1(char *output); -void disassemble_alt2(char *output); -void disassemble_alt3(char *output); diff --git a/waterbox/libsnes/bsnes/snes/chip/superfx/memory/memory.cpp b/waterbox/libsnes/bsnes/snes/chip/superfx/memory/memory.cpp deleted file mode 100644 index 7051ddb6da..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/superfx/memory/memory.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#ifdef SUPERFX_CPP - -uint8 SuperFX::bus_read(unsigned addr) { - if((addr & 0xc00000) == 0x000000) { //$00-3f:0000-7fff, $00-3f:8000-ffff - while(!regs.scmr.ron && scheduler.sync != Scheduler::SynchronizeMode::All) { - add_clocks(6); - synchronize_cpu(); - } - auto myaddr = (((addr & 0x3f0000) >> 1) | (addr & 0x7fff)) & rom_mask; - cdlInfo.set(eCDLog_AddrType_CARTROM, addr); - return cartridge.rom.read(myaddr); - } - - if((addr & 0xe00000) == 0x400000) { //$40-5f:0000-ffff - while(!regs.scmr.ron && scheduler.sync != Scheduler::SynchronizeMode::All) { - add_clocks(6); - synchronize_cpu(); - } - auto myaddr = addr & rom_mask; - cdlInfo.set(eCDLog_AddrType_CARTROM, myaddr); - return cartridge.rom.read(myaddr); - } - - if((addr & 0xe00000) == 0x600000) { //$60-7f:0000-ffff - while(!regs.scmr.ran && scheduler.sync != Scheduler::SynchronizeMode::All) { - add_clocks(6); - synchronize_cpu(); - } - return cartridge.ram.read(addr & ram_mask); - } -} - -void SuperFX::bus_write(unsigned addr, uint8 data) { - if((addr & 0xe00000) == 0x600000) { //$60-7f:0000-ffff - while(!regs.scmr.ran && scheduler.sync != Scheduler::SynchronizeMode::All) { - add_clocks(6); - synchronize_cpu(); - } - return cartridge.ram.write(addr & ram_mask, data); - } -} - -uint8 SuperFX::op_read(uint16 addr) { - uint16 offset = addr - regs.cbr; - if(offset < 512) { - if(cache.valid[offset >> 4] == false) { - unsigned dp = offset & 0xfff0; - unsigned sp = (regs.pbr << 16) + ((regs.cbr + dp) & 0xfff0); - for(unsigned n = 0; n < 16; n++) { - add_clocks(memory_access_speed); - cache.buffer[dp++] = bus_read(sp++); - } - cache.valid[offset >> 4] = true; - } else { - add_clocks(cache_access_speed); - } - return cache.buffer[offset]; - } - - if(regs.pbr <= 0x5f) { - //$[00-5f]:[0000-ffff] ROM - rombuffer_sync(); - add_clocks(memory_access_speed); - return bus_read((regs.pbr << 16) + addr); - } else { - //$[60-7f]:[0000-ffff] RAM - rambuffer_sync(); - add_clocks(memory_access_speed); - return bus_read((regs.pbr << 16) + addr); - } -} - -uint8 SuperFX::peekpipe() { - uint8 result = regs.pipeline; - regs.pipeline = op_read(regs.r[15]); - r15_modified = false; - return result; -} - -uint8 SuperFX::pipe() { - uint8 result = regs.pipeline; - regs.pipeline = op_read(++regs.r[15]); - r15_modified = false; - return result; -} - -void SuperFX::cache_flush() { - for(unsigned n = 0; n < 32; n++) cache.valid[n] = false; -} - -uint8 SuperFX::cache_mmio_read(uint16 addr) { - addr = (addr + regs.cbr) & 511; - return cache.buffer[addr]; -} - -void SuperFX::cache_mmio_write(uint16 addr, uint8 data) { - addr = (addr + regs.cbr) & 511; - cache.buffer[addr] = data; - if((addr & 15) == 15) cache.valid[addr >> 4] = true; -} - -void SuperFX::memory_reset() { - rom_mask = cartridge.rom.size() - 1; - ram_mask = cartridge.ram.size() - 1; - - for(unsigned n = 0; n < 512; n++) cache.buffer[n] = 0x00; - for(unsigned n = 0; n < 32; n++) cache.valid[n] = false; - for(unsigned n = 0; n < 2; n++) { - pixelcache[n].offset = ~0; - pixelcache[n].bitpend = 0x00; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/superfx/memory/memory.hpp b/waterbox/libsnes/bsnes/snes/chip/superfx/memory/memory.hpp deleted file mode 100644 index 2ff62857f1..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/superfx/memory/memory.hpp +++ /dev/null @@ -1,14 +0,0 @@ -unsigned rom_mask; //rom_size - 1 -unsigned ram_mask; //ram_size - 1 -uint8 bus_read(unsigned addr); -void bus_write(unsigned addr, uint8 data); - -uint8 op_read(uint16 addr); -alwaysinline uint8 peekpipe(); -alwaysinline uint8 pipe(); - -void cache_flush(); -uint8 cache_mmio_read(uint16 addr); -void cache_mmio_write(uint16 addr, uint8 data); - -void memory_reset(); diff --git a/waterbox/libsnes/bsnes/snes/chip/superfx/mmio/mmio.cpp b/waterbox/libsnes/bsnes/snes/chip/superfx/mmio/mmio.cpp deleted file mode 100644 index 5650a77a60..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/superfx/mmio/mmio.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#ifdef SUPERFX_CPP - -uint8 SuperFX::mmio_read(unsigned addr) { - cpu.synchronize_coprocessors(); - addr &= 0xffff; - - if(addr >= 0x3100 && addr <= 0x32ff) { - return cache_mmio_read(addr - 0x3100); - } - - if(addr >= 0x3000 && addr <= 0x301f) { - return regs.r[(addr >> 1) & 15] >> ((addr & 1) << 3); - } - - switch(addr) { - case 0x3030: { - return regs.sfr >> 0; - } - - case 0x3031: { - uint8 r = regs.sfr >> 8; - regs.sfr.irq = 0; - cpu.regs.irq = 0; - return r; - } - - case 0x3034: { - return regs.pbr; - } - - case 0x3036: { - return regs.rombr; - } - - case 0x303b: { - return regs.vcr; - } - - case 0x303c: { - return regs.rambr; - } - - case 0x303e: { - return regs.cbr >> 0; - } - - case 0x303f: { - return regs.cbr >> 8; - } - } - - return 0x00; -} - -void SuperFX::mmio_write(unsigned addr, uint8 data) { - cpu.synchronize_coprocessors(); - addr &= 0xffff; - - if(addr >= 0x3100 && addr <= 0x32ff) { - return cache_mmio_write(addr - 0x3100, data); - } - - if(addr >= 0x3000 && addr <= 0x301f) { - unsigned n = (addr >> 1) & 15; - if((addr & 1) == 0) { - regs.r[n] = (regs.r[n] & 0xff00) | data; - } else { - regs.r[n] = (data << 8) | (regs.r[n] & 0xff); - } - - if(addr == 0x301f) regs.sfr.g = 1; - return; - } - - switch(addr) { - case 0x3030: { - bool g = regs.sfr.g; - regs.sfr = (regs.sfr & 0xff00) | (data << 0); - if(g == 1 && regs.sfr.g == 0) { - regs.cbr = 0x0000; - cache_flush(); - } - } break; - - case 0x3031: { - regs.sfr = (data << 8) | (regs.sfr & 0x00ff); - } break; - - case 0x3033: { - regs.bramr = data; - } break; - - case 0x3034: { - regs.pbr = data & 0x7f; - cache_flush(); - } break; - - case 0x3037: { - regs.cfgr = data; - update_speed(); - } break; - - case 0x3038: { - regs.scbr = data; - } break; - - case 0x3039: { - regs.clsr = data; - update_speed(); - } break; - - case 0x303a: { - regs.scmr = data; - } break; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/superfx/mmio/mmio.hpp b/waterbox/libsnes/bsnes/snes/chip/superfx/mmio/mmio.hpp deleted file mode 100644 index 08cc85a9e0..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/superfx/mmio/mmio.hpp +++ /dev/null @@ -1,2 +0,0 @@ -uint8 mmio_read(unsigned addr); -void mmio_write(unsigned addr, uint8 data); diff --git a/waterbox/libsnes/bsnes/snes/chip/superfx/superfx.cpp b/waterbox/libsnes/bsnes/snes/chip/superfx/superfx.cpp deleted file mode 100644 index d12736d693..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/superfx/superfx.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include - -#define SUPERFX_CPP -namespace SNES { - -#include "bus/bus.cpp" -#include "core/core.cpp" -#include "memory/memory.cpp" -#include "mmio/mmio.cpp" -#include "timing/timing.cpp" -#include "disasm/disasm.cpp" - -SuperFX superfx; - -void SuperFX::Enter() { superfx.enter(); } - -void SuperFX::enter() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - if(regs.sfr.g == 0) { - add_clocks(6); - synchronize_cpu(); - continue; - } - - (this->*opcode_table[(regs.sfr & 0x0300) + peekpipe()])(); - if(r15_modified == false) regs.r[15]++; - - if(++instruction_counter >= 128) { - instruction_counter = 0; - synchronize_cpu(); - } - } -} - -void SuperFX::init() { - initialize_opcode_table(); - regs.r[14].on_modify = { &SuperFX::r14_modify, this }; - regs.r[15].on_modify = { &SuperFX::r15_modify, this }; -} - -void SuperFX::load() { -} - -void SuperFX::unload() { -} - -void SuperFX::power() { - clockmode = config.superfx.speed; -} - -void SuperFX::reset() { - create(SuperFX::Enter, system.cpu_frequency(), 16384); - instruction_counter = 0; - - for(unsigned n = 0; n < 16; n++) regs.r[n] = 0x0000; - regs.sfr = 0x0000; - regs.pbr = 0x00; - regs.rombr = 0x00; - regs.rambr = 0; - regs.cbr = 0x0000; - regs.scbr = 0x00; - regs.scmr = 0x00; - regs.colr = 0x00; - regs.por = 0x00; - regs.bramr = 0; - regs.vcr = 0x04; - regs.cfgr = 0x00; - regs.clsr = 0; - regs.pipeline = 0x01; //nop - regs.ramaddr = 0x0000; - regs.reset(); - - memory_reset(); - timing_reset(); -} - -} diff --git a/waterbox/libsnes/bsnes/snes/chip/superfx/superfx.hpp b/waterbox/libsnes/bsnes/snes/chip/superfx/superfx.hpp deleted file mode 100644 index 48483ca759..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/superfx/superfx.hpp +++ /dev/null @@ -1,23 +0,0 @@ -class SuperFX : public Coprocessor { -public: - #include "bus/bus.hpp" - #include "core/core.hpp" - #include "memory/memory.hpp" - #include "mmio/mmio.hpp" - #include "timing/timing.hpp" - #include "disasm/disasm.hpp" - - static void Enter(); - void enter(); - void init(); - void load(); - void unload(); - void power(); - void reset(); - -private: - unsigned clockmode; - unsigned instruction_counter; -}; - -extern SuperFX superfx; diff --git a/waterbox/libsnes/bsnes/snes/chip/superfx/timing/timing.cpp b/waterbox/libsnes/bsnes/snes/chip/superfx/timing/timing.cpp deleted file mode 100644 index 527656494b..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/superfx/timing/timing.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#ifdef SUPERFX_CPP - -void SuperFX::add_clocks(unsigned clocks) { - if(regs.romcl) { - regs.romcl -= min(clocks, regs.romcl); - if(regs.romcl == 0) { - regs.sfr.r = 0; - regs.romdr = bus_read((regs.rombr << 16) + regs.r[14]); - } - } - - if(regs.ramcl) { - regs.ramcl -= min(clocks, regs.ramcl); - if(regs.ramcl == 0) { - bus_write(0x700000 + (regs.rambr << 16) + regs.ramar, regs.ramdr); - } - } - - step(clocks); - synchronize_cpu(); -} - -void SuperFX::rombuffer_sync() { - if(regs.romcl) add_clocks(regs.romcl); -} - -void SuperFX::rombuffer_update() { - regs.sfr.r = 1; - regs.romcl = memory_access_speed; -} - -uint8 SuperFX::rombuffer_read() { - rombuffer_sync(); - return regs.romdr; -} - -void SuperFX::rambuffer_sync() { - if(regs.ramcl) add_clocks(regs.ramcl); -} - -uint8 SuperFX::rambuffer_read(uint16 addr) { - rambuffer_sync(); - return bus_read(0x700000 + (regs.rambr << 16) + addr); -} - -void SuperFX::rambuffer_write(uint16 addr, uint8 data) { - rambuffer_sync(); - regs.ramcl = memory_access_speed; - regs.ramar = addr; - regs.ramdr = data; -} - -void SuperFX::r14_modify(uint16 data) { - regs.r[14].data = data; - rombuffer_update(); -} - -void SuperFX::r15_modify(uint16 data) { - regs.r[15].data = data; - r15_modified = true; -} - -void SuperFX::update_speed() { - //force SuperFX1 mode? - if(clockmode == 1) { - cache_access_speed = 2; - memory_access_speed = 6; - return; - } - - //force SuperFX2 mode? - if(clockmode == 2) { - cache_access_speed = 1; - memory_access_speed = 5; - regs.cfgr.ms0 = 0; //cannot use high-speed multiplication in 21MHz mode - return; - } - - //default: allow S-CPU to select mode - cache_access_speed = (regs.clsr ? 1 : 2); - memory_access_speed = (regs.clsr ? 5 : 6); - if(regs.clsr) regs.cfgr.ms0 = 0; //cannot use high-speed multiplication in 21MHz mode -} - -void SuperFX::timing_reset() { - update_speed(); - r15_modified = false; - - regs.romcl = 0; - regs.romdr = 0; - - regs.ramcl = 0; - regs.ramar = 0; - regs.ramdr = 0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/chip/superfx/timing/timing.hpp b/waterbox/libsnes/bsnes/snes/chip/superfx/timing/timing.hpp deleted file mode 100644 index 9ae7e8d497..0000000000 --- a/waterbox/libsnes/bsnes/snes/chip/superfx/timing/timing.hpp +++ /dev/null @@ -1,19 +0,0 @@ -unsigned cache_access_speed; -unsigned memory_access_speed; -bool r15_modified; - -void add_clocks(unsigned clocks); - -void rombuffer_sync(); -void rombuffer_update(); -uint8 rombuffer_read(); - -void rambuffer_sync(); -uint8 rambuffer_read(uint16 addr); -void rambuffer_write(uint16 addr, uint8 data); - -void r14_modify(uint16); -void r15_modify(uint16); - -void update_speed(); -void timing_reset(); diff --git a/waterbox/libsnes/bsnes/snes/config/config.cpp b/waterbox/libsnes/bsnes/snes/config/config.cpp deleted file mode 100644 index 701af94c01..0000000000 --- a/waterbox/libsnes/bsnes/snes/config/config.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifdef SYSTEM_CPP - -Configuration config; - -Configuration::Configuration() { - controller_port1 = Input::Device::Joypad; - controller_port2 = Input::Device::Joypad; - expansion_port = System::ExpansionPortDevice::BSX; - region = System::Region::Autodetect; - random = true; - - cpu.version = 2; - cpu.ntsc_frequency = 21477272; //315 / 88 * 6000000 - cpu.pal_frequency = 21281370; - cpu.wram_init_value = 0x55; - - smp.ntsc_frequency = 24607104; //32040.5 * 768 - smp.pal_frequency = 24607104; - - ppu1.version = 1; - ppu2.version = 3; - - superfx.speed = 0; //0 = auto-select, 1 = force 10.74MHz, 2 = force 21.48MHz -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/config/config.hpp b/waterbox/libsnes/bsnes/snes/config/config.hpp deleted file mode 100644 index 1f4d037cfe..0000000000 --- a/waterbox/libsnes/bsnes/snes/config/config.hpp +++ /dev/null @@ -1,35 +0,0 @@ -struct Configuration { - Input::Device controller_port1; - Input::Device controller_port2; - System::ExpansionPortDevice expansion_port; - System::Region region; - bool random; - - struct CPU { - unsigned version; - unsigned ntsc_frequency; - unsigned pal_frequency; - unsigned wram_init_value; - } cpu; - - struct SMP { - unsigned ntsc_frequency; - unsigned pal_frequency; - } smp; - - struct PPU1 { - unsigned version; - } ppu1; - - struct PPU2 { - unsigned version; - } ppu2; - - struct SuperFX { - unsigned speed; - } superfx; - - Configuration(); -}; - -extern Configuration config; diff --git a/waterbox/libsnes/bsnes/snes/controller/controller.cpp b/waterbox/libsnes/bsnes/snes/controller/controller.cpp deleted file mode 100644 index 8e3791f79f..0000000000 --- a/waterbox/libsnes/bsnes/snes/controller/controller.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include - -#define CONTROLLER_CPP -namespace SNES { - -#include "gamepad/gamepad.cpp" -#include "multitap/multitap.cpp" -#include "mouse/mouse.cpp" -#include "superscope/superscope.cpp" -#include "justifier/justifier.cpp" -#include "usart/usart.cpp" - -void Controller::Enter() { - if(co_active() == input.port1->thread) input.port1->enter(); - if(co_active() == input.port2->thread) input.port2->enter(); -} - -void Controller::enter() { - while(true) step(1); -} - -void Controller::step(unsigned clocks) { - clock += clocks * (uint64)cpu.frequency; - synchronize_cpu(); -} - -void Controller::synchronize_cpu() { - if(CPU::Threaded == true) { - if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); - } else { - while(clock >= 0) cpu.enter(); - } -} - -bool Controller::iobit() { - switch(port) { - case Controller::Port1: return cpu.pio() & 0x40; - case Controller::Port2: return cpu.pio() & 0x80; - } -} - -void Controller::iobit(bool data) { - switch(port) { - case Controller::Port1: bus.write(0x4201, (cpu.pio() & ~0x40) | (data << 6)); break; - case Controller::Port2: bus.write(0x4201, (cpu.pio() & ~0x80) | (data << 7)); break; - } -} - -Controller::Controller(bool port) : port(port) { - if(!thread) create(Controller::Enter, 1, 4096); -} - - -} diff --git a/waterbox/libsnes/bsnes/snes/controller/controller.hpp b/waterbox/libsnes/bsnes/snes/controller/controller.hpp deleted file mode 100644 index 94ab2ce7cd..0000000000 --- a/waterbox/libsnes/bsnes/snes/controller/controller.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// SNES controller port pinout: -// ------------------------------- -// | (1) (2) (3) (4) | (5) (6) (7) ) -// ------------------------------- -// pin name port1 port2 -// 1: +5v -// 2: clock $4016 read $4017 read -// 3: latch $4016.d0 write $4016.d0 write -// 4: data1 $4016.d0 read $4017.d0 read -// 5: data2 $4016.d1 read $4017.d1 read -// 6: iobit $4201.d6 write; $4213.d6 read $4201.d7 write; $4213.d7 read -// 7: gnd - -struct Controller : Processor { - enum : bool { Port1 = 0, Port2 = 1 }; - enum { SaveSize = 16 }; - const bool port; - - static void Enter(); - virtual void enter(); - void step(unsigned clocks); - void synchronize_cpu(); - - bool iobit(); - void iobit(bool data); - virtual uint2 data() { return 0; } - virtual void latch(bool data) {} - Controller(bool port); -}; - -#include "gamepad/gamepad.hpp" -#include "multitap/multitap.hpp" -#include "mouse/mouse.hpp" -#include "superscope/superscope.hpp" -#include "justifier/justifier.hpp" -#include "usart/usart.hpp" diff --git a/waterbox/libsnes/bsnes/snes/controller/gamepad/gamepad.cpp b/waterbox/libsnes/bsnes/snes/controller/gamepad/gamepad.cpp deleted file mode 100644 index b37d099b30..0000000000 --- a/waterbox/libsnes/bsnes/snes/controller/gamepad/gamepad.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#ifdef CONTROLLER_CPP - -uint2 Gamepad::data() { - if(counter >= 16) return 1; - uint2 result = interface()->inputPoll(port, Input::Device::Joypad, 0, counter); - if(latched == 0) counter++; - return result; -} - -void Gamepad::latch(bool data) { - if(latched == data) return; - latched = data; - counter = 0; -} - -Gamepad::Gamepad(bool port) : Controller(port) { - latched = 0; - counter = 0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/controller/gamepad/gamepad.hpp b/waterbox/libsnes/bsnes/snes/controller/gamepad/gamepad.hpp deleted file mode 100644 index 63394dd44b..0000000000 --- a/waterbox/libsnes/bsnes/snes/controller/gamepad/gamepad.hpp +++ /dev/null @@ -1,8 +0,0 @@ -struct Gamepad : Controller { - uint2 data(); - void latch(bool data); - Gamepad(bool port); -private: - bool latched; - unsigned counter; -}; diff --git a/waterbox/libsnes/bsnes/snes/controller/justifier/justifier.cpp b/waterbox/libsnes/bsnes/snes/controller/justifier/justifier.cpp deleted file mode 100644 index af8ff3edfb..0000000000 --- a/waterbox/libsnes/bsnes/snes/controller/justifier/justifier.cpp +++ /dev/null @@ -1,126 +0,0 @@ -#ifdef CONTROLLER_CPP - -void Justifier::enter() { - unsigned prev = 0; - while(true) { - unsigned next = cpu.vcounter() * 1364 + cpu.hcounter(); - - signed x = (active == 0 ? player1.x : player2.x), y = (active == 0 ? player1.y : player2.y); - bool offscreen = (x < 0 || y < 0 || x >= 256 || y >= (ppu.overscan() ? 240 : 225)); - - if(offscreen == false) { - unsigned target = y * 1364 + (x + 24) * 4; - if(next >= target && prev < target) { - //CRT raster detected, toggle iobit to latch counters - iobit(0); - iobit(1); - } - } - - if(next < prev) { - int nx1 = interface()->inputPoll(port, Input::Device::Justifier, 0, (unsigned)Input::JustifierID::X); - int ny1 = interface()->inputPoll(port, Input::Device::Justifier, 0, (unsigned)Input::JustifierID::Y); - - player1.x = max(-16, min(256 + 16, nx1)); - player1.y = max(-16, min(240 + 16, ny1)); - } - - if(next < prev && chained) { - int nx2 = interface()->inputPoll(port, Input::Device::Justifiers, 1, (unsigned)Input::JustifierID::X); - int ny2 = interface()->inputPoll(port, Input::Device::Justifiers, 1, (unsigned)Input::JustifierID::Y); - - player2.x = max(-16, min(256 + 16, nx2)); - player2.y = max(-16, min(240 + 16, ny2)); - } - - prev = next; - step(2); - } -} - -uint2 Justifier::data() { - if(counter >= 32) return 1; - - if(counter == 0) { - player1.trigger = interface()->inputPoll(port, Input::Device::Justifier, 0, (unsigned)Input::JustifierID::Trigger); - player1.start = interface()->inputPoll(port, Input::Device::Justifier, 0, (unsigned)Input::JustifierID::Start); - } - - if(counter == 0 && chained) { - player2.trigger = interface()->inputPoll(port, Input::Device::Justifiers, 1, (unsigned)Input::JustifierID::Trigger); - player2.start = interface()->inputPoll(port, Input::Device::Justifiers, 1, (unsigned)Input::JustifierID::Start); - } - - switch(counter++) { - case 0: return 0; - case 1: return 0; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - case 6: return 0; - case 7: return 0; - case 8: return 0; - case 9: return 0; - case 10: return 0; - case 11: return 0; - - case 12: return 1; //signature - case 13: return 1; // || - case 14: return 1; // || - case 15: return 0; // || - - case 16: return 0; - case 17: return 1; - case 18: return 0; - case 19: return 1; - case 20: return 0; - case 21: return 1; - case 22: return 0; - case 23: return 1; - - case 24: return player1.trigger; - case 25: return player2.trigger; - case 26: return player1.start; - case 27: return player2.start; - case 28: return active; - - case 29: return 0; - case 30: return 0; - case 31: return 0; - } -} - -void Justifier::latch(bool data) { - if(latched == data) return; - latched = data; - counter = 0; - if(latched == 0) active = !active; //toggle between both controllers, even when unchained -} - -Justifier::Justifier(bool port, bool chained) : Controller(port), chained(chained) { - create(Controller::Enter, 21477272, 8192); - latched = 0; - counter = 0; - active = 0; - - player1.x = 256 / 2; - player1.y = 240 / 2; - player1.trigger = false; - player2.start = false; - - player2.x = 256 / 2; - player2.y = 240 / 2; - player2.trigger = false; - player2.start = false; - - if(chained == false) { - player2.x = -1; - player2.y = -1; - } else { - player1.x -= 16; - player2.x += 16; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/controller/justifier/justifier.hpp b/waterbox/libsnes/bsnes/snes/controller/justifier/justifier.hpp deleted file mode 100644 index f927acf6bf..0000000000 --- a/waterbox/libsnes/bsnes/snes/controller/justifier/justifier.hpp +++ /dev/null @@ -1,17 +0,0 @@ -struct Justifier : Controller { - void enter(); - uint2 data(); - void latch(bool data); - Justifier(bool port, bool chained); - -//private: - const bool chained; //true if the second justifier is attached to the first - bool latched; - unsigned counter; - - bool active; - struct Player { - signed x, y; - bool trigger, start; - } player1, player2; -}; diff --git a/waterbox/libsnes/bsnes/snes/controller/mouse/mouse.cpp b/waterbox/libsnes/bsnes/snes/controller/mouse/mouse.cpp deleted file mode 100644 index 97d0339170..0000000000 --- a/waterbox/libsnes/bsnes/snes/controller/mouse/mouse.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#ifdef CONTROLLER_CPP - -uint2 Mouse::data() { - if(counter >= 32) return 1; - - if(counter == 0) { - position_x = interface()->inputPoll(port, Input::Device::Mouse, 0, (unsigned)Input::MouseID::X); //-n = left, 0 = center, +n = right - position_y = interface()->inputPoll(port, Input::Device::Mouse, 0, (unsigned)Input::MouseID::Y); //-n = up, 0 = center, +n = down - } - - - bool direction_x = position_x < 0; //0 = right, 1 = left - bool direction_y = position_y < 0; //0 = down, 1 = up - - int position_x_fixed = position_x; - int position_y_fixed = position_y; - - if(position_x < 0) position_x_fixed = -position_x; //abs(position_x) - if(position_y < 0) position_y_fixed = -position_y; //abs(position_y) - - position_x_fixed = min(127, position_x_fixed); //range = 0 - 127 - position_y_fixed = min(127, position_y_fixed); - - - switch(counter++) { default: - case 0: return 0; - case 1: return 0; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - case 6: return 0; - case 7: return 0; - - case 8: return interface()->inputPoll(port, Input::Device::Mouse, 0, (unsigned)Input::MouseID::Right); - case 9: return interface()->inputPoll(port, Input::Device::Mouse, 0, (unsigned)Input::MouseID::Left); - case 10: return 0; //speed (0 = slow, 1 = normal, 2 = fast, 3 = unused) - case 11: return 0; // || - - case 12: return 0; //signature - case 13: return 0; // || - case 14: return 0; // || - case 15: return 1; // || - - case 16: return (direction_y)?1:0; - case 17: return (position_y_fixed >> 6) & 1; - case 18: return (position_y_fixed >> 5) & 1; - case 19: return (position_y_fixed >> 4) & 1; - case 20: return (position_y_fixed >> 3) & 1; - case 21: return (position_y_fixed >> 2) & 1; - case 22: return (position_y_fixed >> 1) & 1; - case 23: return (position_y_fixed >> 0) & 1; - - case 24: return (direction_x) ? 1 : 0; - case 25: return (position_x_fixed >> 6) & 1; - case 26: return (position_x_fixed >> 5) & 1; - case 27: return (position_x_fixed >> 4) & 1; - case 28: return (position_x_fixed >> 3) & 1; - case 29: return (position_x_fixed >> 2) & 1; - case 30: return (position_x_fixed >> 1) & 1; - case 31: return (position_x_fixed >> 0) & 1; - } -} - -void Mouse::latch(bool data) { - if(latched == data) return; - latched = data; - counter = 0; -} - -Mouse::Mouse(bool port) : Controller(port) { - latched = 0; - counter = 0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/controller/mouse/mouse.hpp b/waterbox/libsnes/bsnes/snes/controller/mouse/mouse.hpp deleted file mode 100644 index dd4d239995..0000000000 --- a/waterbox/libsnes/bsnes/snes/controller/mouse/mouse.hpp +++ /dev/null @@ -1,10 +0,0 @@ -struct Mouse : Controller { - uint2 data(); - void latch(bool data); - Mouse(bool port); -private: - bool latched; - unsigned counter; - int position_x; - int position_y; -}; diff --git a/waterbox/libsnes/bsnes/snes/controller/multitap/multitap.cpp b/waterbox/libsnes/bsnes/snes/controller/multitap/multitap.cpp deleted file mode 100644 index 9409946479..0000000000 --- a/waterbox/libsnes/bsnes/snes/controller/multitap/multitap.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#ifdef CONTROLLER_CPP - -uint2 Multitap::data() { - if (latched) - return connected ? 2 : 0; - - unsigned index, port1, port2; - - if(iobit()) { - index = counter1; - if(index >= 16) return 3; - counter1++; - port1 = 0; //controller 1 - port2 = 1; //controller 2 - } else { - index = counter2; - if(index >= 16) return 3; - counter2++; - port1 = 2; //controller 3 - port2 = 3; //controller 4 - } - - bool data1 = interface()->inputPoll(port, Input::Device::Multitap, port1, index); - bool data2 = interface()->inputPoll(port, Input::Device::Multitap, port2, index); - return (data2 << 1) | (data1 << 0); -} - -void Multitap::latch(bool data) { - if(latched == data) return; - bool newtoggleConnectedInput = interface()->inputPoll(port, Input::Device::Multitap, 0, 16); - if (newtoggleConnectedInput > toggleConnectedInput) - connected ^= true; - toggleConnectedInput = newtoggleConnectedInput; - - - latched = data; - counter1 = 0; - counter2 = 0; -} - -Multitap::Multitap(bool port) : Controller(port) { - latched = 0; - counter1 = 0; - counter2 = 0; - connected = true; - toggleConnectedInput = false; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/controller/multitap/multitap.hpp b/waterbox/libsnes/bsnes/snes/controller/multitap/multitap.hpp deleted file mode 100644 index b64feb44b3..0000000000 --- a/waterbox/libsnes/bsnes/snes/controller/multitap/multitap.hpp +++ /dev/null @@ -1,11 +0,0 @@ -struct Multitap : Controller { - uint2 data(); - void latch(bool data); - Multitap(bool port); -private: - bool connected; - bool toggleConnectedInput; - bool latched; - unsigned counter1; - unsigned counter2; -}; diff --git a/waterbox/libsnes/bsnes/snes/controller/superscope/superscope.cpp b/waterbox/libsnes/bsnes/snes/controller/superscope/superscope.cpp deleted file mode 100644 index 09967f2676..0000000000 --- a/waterbox/libsnes/bsnes/snes/controller/superscope/superscope.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#ifdef CONTROLLER_CPP - -//The Super Scope is a light-gun: it detects the CRT beam cannon position, -//and latches the counters by toggling iobit. This only works on controller -//port 2, as iobit there is connected to the PPU H/V counter latch. -//(PIO $4201.d7) - -//It is obviously not possible to perfectly simulate an IR light detecting -//a CRT beam cannon, hence this class will read the PPU raster counters. - -//A Super Scope can still technically be used in port 1, however it would -//require manual polling of PIO ($4201.d6) to determine when iobit was written. -//Note that no commercial game ever utilizes a Super Scope in port 1. - -void SuperScope::enter() { - unsigned prev = 0; - while(true) { - unsigned next = cpu.vcounter() * 1364 + cpu.hcounter(); - - if(offscreen == false) { - unsigned target = y * 1364 + (x + 24) * 4; - if(next >= target && prev < target) { - //CRT raster detected, toggle iobit to latch counters - iobit(0); - iobit(1); - } - } - - if(next < prev) { - //Vcounter wrapped back to zero; update cursor coordinates for start of new frame - int nx = interface()->inputPoll(port, Input::Device::SuperScope, 0, (unsigned)Input::SuperScopeID::X); - int ny = interface()->inputPoll(port, Input::Device::SuperScope, 0, (unsigned)Input::SuperScopeID::Y); - x = max(-16, min(256 + 16, nx)); - y = max(-16, min(240 + 16, ny)); - offscreen = (x < 0 || y < 0 || x >= 256 || y >= (ppu.overscan() ? 240 : 225)); - } - - prev = next; - step(2); - } -} - -uint2 SuperScope::data() { - if(counter >= 8) return 1; - - if(counter == 0) { - //turbo is a switch; toggle is edge sensitive - bool newturbo = interface()->inputPoll(port, Input::Device::SuperScope, 0, (unsigned)Input::SuperScopeID::Turbo); - if(newturbo && !turbo) { - turbo = !turbo; //toggle state - turbolock = true; - } else { - turbolock = false; - } - - //trigger is a button - //if turbo is active, trigger is level sensitive; otherwise, it is edge sensitive - trigger = false; - bool newtrigger = interface()->inputPoll(port, Input::Device::SuperScope, 0, (unsigned)Input::SuperScopeID::Trigger); - if(newtrigger && (turbo || !triggerlock)) { - trigger = true; - triggerlock = true; - } else if(!newtrigger) { - triggerlock = false; - } - - //cursor is a button; it is always level sensitive - cursor = interface()->inputPoll(port, Input::Device::SuperScope, 0, (unsigned)Input::SuperScopeID::Cursor); - - //pause is a button; it is always edge sensitive - pause = false; - bool newpause = interface()->inputPoll(port, Input::Device::SuperScope, 0, (unsigned)Input::SuperScopeID::Pause); - if(newpause && !pauselock) { - pause = true; - pauselock = true; - } else if(!newpause) { - pauselock = false; - } - - offscreen = (x < 0 || y < 0 || x >= 256 || y >= (ppu.overscan() ? 240 : 225)); - } - - switch(counter++) { - case 0: return offscreen ? 0 : trigger; - case 1: return cursor; - case 2: return turbo; - case 3: return pause; - case 4: return 0; - case 5: return 0; - case 6: return offscreen; - case 7: return 0; //noise (1 = yes) - } -} - -void SuperScope::latch(bool data) { - if(latched == data) return; - latched = data; - counter = 0; -} - -SuperScope::SuperScope(bool port) : Controller(port) { - create(Controller::Enter, 21477272, 8192); - latched = 0; - counter = 0; - - //center cursor onscreen - x = 256 / 2; - y = 240 / 2; - - trigger = false; - cursor = false; - turbo = false; - pause = false; - offscreen = false; - - turbolock = false; - triggerlock = false; - pauselock = false; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/controller/superscope/superscope.hpp b/waterbox/libsnes/bsnes/snes/controller/superscope/superscope.hpp deleted file mode 100644 index a7a90b71a3..0000000000 --- a/waterbox/libsnes/bsnes/snes/controller/superscope/superscope.hpp +++ /dev/null @@ -1,22 +0,0 @@ -struct SuperScope : Controller { - void enter(); - uint2 data(); - void latch(bool data); - SuperScope(bool port); - -//private: - bool latched; - unsigned counter; - - signed x, y; - - bool trigger; - bool cursor; - bool turbo; - bool pause; - bool offscreen; - - bool turbolock; - bool triggerlock; - bool pauselock; -}; diff --git a/waterbox/libsnes/bsnes/snes/controller/usart/usart.cpp b/waterbox/libsnes/bsnes/snes/controller/usart/usart.cpp deleted file mode 100644 index 2573d8794d..0000000000 --- a/waterbox/libsnes/bsnes/snes/controller/usart/usart.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#ifdef CONTROLLER_CPP - -//Synchronous serial communications cable emulation - -//Hardware: -//Teensy++ 2.0 USB -//AT90USB1286 - -//Connection Diagram: -//[SNES] [Teensy] -// +5v --- -// Clock D5 -// Latch D2 -// Data1 D3 -// Data2 --- -// IOBit --- -// GND GND - -void USART::enter() { - if(init && main) { - init({ &USART::usleep, this }, { &USART::read, this }, { &USART::write, this }); - main(); - } - while(true) step(1000000); //fallback; main should never return -} - -void USART::usleep(unsigned milliseconds) { - step(milliseconds); -} - -//SNES -> USART -uint8 USART::read() { - while(txbuffer.size() == 0) step(1); - uint8 data = txbuffer[0]; - txbuffer.remove(0); - return data; -} - -//USART -> SNES -void USART::write(uint8 data) { - rxbuffer.append(data ^ 0xff); -} - -//clock -uint2 USART::data() { - //SNES -> USART - if(txlength == 0) { - if(latched == 0) txlength++; - } else if(txlength <= 8) { - txdata = (latched << 7) | (txdata >> 1); - txlength++; - } else { - if(latched == 1) txbuffer.append(txdata); - txlength = 0; - } - - //USART -> SNES - if(rxlength == 0 && rxbuffer.size()) { - data1 = 1; - rxdata = rxbuffer[0]; - rxbuffer.remove(0); - rxlength++; - } else if(rxlength <= 8) { - data1 = rxdata & 1; - rxdata >>= 1; - rxlength++; - } else { - data1 = 0; - rxlength = 0; - } - - return (data2 << 1) | (data1 << 0); -} - -//latch -void USART::latch(bool data) { - latched = data; -} - -USART::USART(bool port) : Controller(port) { - latched = 0; - data1 = 0; - data2 = 0; - - rxlength = 0; - rxdata = 0; - - txlength = 0; - txdata = 0; - - string filename = interface()->path(Cartridge::Slot::Base, "usart.so"); - if(0 /*open_absolute(filename)*/) { - init = sym("usart_init"); - main = sym("usart_main"); - if(init && main) create(Controller::Enter, 1000000, 8192); - } -} - -USART::~USART() { - if(opened()) close(); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/controller/usart/usart.hpp b/waterbox/libsnes/bsnes/snes/controller/usart/usart.hpp deleted file mode 100644 index dcf3907729..0000000000 --- a/waterbox/libsnes/bsnes/snes/controller/usart/usart.hpp +++ /dev/null @@ -1,28 +0,0 @@ -struct USART : Controller, public library { - void enter(); - void usleep(unsigned milliseconds); - uint8 read(); - void write(uint8 data); - - uint2 data(); - void latch(bool data); - - USART(bool port); - ~USART(); - -private: - bool latched; - bool data1; - bool data2; - - uint8 rxlength; - uint8 rxdata; - vector rxbuffer; - - uint8 txlength; - uint8 txdata; - vector txbuffer; - - function, function, function)> init; - function main; -}; diff --git a/waterbox/libsnes/bsnes/snes/cpu/core/algorithms.cpp b/waterbox/libsnes/bsnes/snes/cpu/core/algorithms.cpp deleted file mode 100644 index 9b6ba032bd..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/core/algorithms.cpp +++ /dev/null @@ -1,331 +0,0 @@ -#ifdef CPUCORE_CPP - -inline void CPUcore::op_adc_b() { - int result; - - if(!regs.p.d) { - result = regs.a.l + rd.l + regs.p.c; - } else { - result = (regs.a.l & 0x0f) + (rd.l & 0x0f) + (regs.p.c << 0); - if(result > 0x09) result += 0x06; - regs.p.c = result > 0x0f; - result = (regs.a.l & 0xf0) + (rd.l & 0xf0) + (regs.p.c << 4) + (result & 0x0f); - } - - regs.p.v = ~(regs.a.l ^ rd.l) & (regs.a.l ^ result) & 0x80; - if(regs.p.d && result > 0x9f) result += 0x60; - regs.p.c = result > 0xff; - regs.p.n = result & 0x80; - regs.p.z = (uint8_t)result == 0; - - regs.a.l = result; -} - -inline void CPUcore::op_adc_w() { - int result; - - if(!regs.p.d) { - result = regs.a.w + rd.w + regs.p.c; - } else { - result = (regs.a.w & 0x000f) + (rd.w & 0x000f) + (regs.p.c << 0); - if(result > 0x0009) result += 0x0006; - regs.p.c = result > 0x000f; - result = (regs.a.w & 0x00f0) + (rd.w & 0x00f0) + (regs.p.c << 4) + (result & 0x000f); - if(result > 0x009f) result += 0x0060; - regs.p.c = result > 0x00ff; - result = (regs.a.w & 0x0f00) + (rd.w & 0x0f00) + (regs.p.c << 8) + (result & 0x00ff); - if(result > 0x09ff) result += 0x0600; - regs.p.c = result > 0x0fff; - result = (regs.a.w & 0xf000) + (rd.w & 0xf000) + (regs.p.c << 12) + (result & 0x0fff); - } - - regs.p.v = ~(regs.a.w ^ rd.w) & (regs.a.w ^ result) & 0x8000; - if(regs.p.d && result > 0x9fff) result += 0x6000; - regs.p.c = result > 0xffff; - regs.p.n = result & 0x8000; - regs.p.z = (uint16_t)result == 0; - - regs.a.w = result; -} - -inline void CPUcore::op_and_b() { - regs.a.l &= rd.l; - regs.p.n = regs.a.l & 0x80; - regs.p.z = regs.a.l == 0; -} - -inline void CPUcore::op_and_w() { - regs.a.w &= rd.w; - regs.p.n = regs.a.w & 0x8000; - regs.p.z = regs.a.w == 0; -} - -inline void CPUcore::op_bit_b() { - regs.p.n = rd.l & 0x80; - regs.p.v = rd.l & 0x40; - regs.p.z = (rd.l & regs.a.l) == 0; -} - -inline void CPUcore::op_bit_w() { - regs.p.n = rd.w & 0x8000; - regs.p.v = rd.w & 0x4000; - regs.p.z = (rd.w & regs.a.w) == 0; -} - -inline void CPUcore::op_cmp_b() { - int r = regs.a.l - rd.l; - regs.p.n = r & 0x80; - regs.p.z = (uint8)r == 0; - regs.p.c = r >= 0; -} - -inline void CPUcore::op_cmp_w() { - int r = regs.a.w - rd.w; - regs.p.n = r & 0x8000; - regs.p.z = (uint16)r == 0; - regs.p.c = r >= 0; -} - -inline void CPUcore::op_cpx_b() { - int r = regs.x.l - rd.l; - regs.p.n = r & 0x80; - regs.p.z = (uint8)r == 0; - regs.p.c = r >= 0; -} - -inline void CPUcore::op_cpx_w() { - int r = regs.x.w - rd.w; - regs.p.n = r & 0x8000; - regs.p.z = (uint16)r == 0; - regs.p.c = r >= 0; -} - -inline void CPUcore::op_cpy_b() { - int r = regs.y.l - rd.l; - regs.p.n = r & 0x80; - regs.p.z = (uint8)r == 0; - regs.p.c = r >= 0; -} - -inline void CPUcore::op_cpy_w() { - int r = regs.y.w - rd.w; - regs.p.n = r & 0x8000; - regs.p.z = (uint16)r == 0; - regs.p.c = r >= 0; -} - -inline void CPUcore::op_eor_b() { - regs.a.l ^= rd.l; - regs.p.n = regs.a.l & 0x80; - regs.p.z = regs.a.l == 0; -} - -inline void CPUcore::op_eor_w() { - regs.a.w ^= rd.w; - regs.p.n = regs.a.w & 0x8000; - regs.p.z = regs.a.w == 0; -} - -inline void CPUcore::op_lda_b() { - regs.a.l = rd.l; - regs.p.n = regs.a.l & 0x80; - regs.p.z = regs.a.l == 0; -} - -inline void CPUcore::op_lda_w() { - regs.a.w = rd.w; - regs.p.n = regs.a.w & 0x8000; - regs.p.z = regs.a.w == 0; -} - -inline void CPUcore::op_ldx_b() { - regs.x.l = rd.l; - regs.p.n = regs.x.l & 0x80; - regs.p.z = regs.x.l == 0; -} - -inline void CPUcore::op_ldx_w() { - regs.x.w = rd.w; - regs.p.n = regs.x.w & 0x8000; - regs.p.z = regs.x.w == 0; -} - -inline void CPUcore::op_ldy_b() { - regs.y.l = rd.l; - regs.p.n = regs.y.l & 0x80; - regs.p.z = regs.y.l == 0; -} - -inline void CPUcore::op_ldy_w() { - regs.y.w = rd.w; - regs.p.n = regs.y.w & 0x8000; - regs.p.z = regs.y.w == 0; -} - -inline void CPUcore::op_ora_b() { - regs.a.l |= rd.l; - regs.p.n = regs.a.l & 0x80; - regs.p.z = regs.a.l == 0; -} - -inline void CPUcore::op_ora_w() { - regs.a.w |= rd.w; - regs.p.n = regs.a.w & 0x8000; - regs.p.z = regs.a.w == 0; -} - -inline void CPUcore::op_sbc_b() { - int result; - rd.l ^= 0xff; - - if(!regs.p.d) { - result = regs.a.l + rd.l + regs.p.c; - } else { - result = (regs.a.l & 0x0f) + (rd.l & 0x0f) + (regs.p.c << 0); - if(result <= 0x0f) result -= 0x06; - regs.p.c = result > 0x0f; - result = (regs.a.l & 0xf0) + (rd.l & 0xf0) + (regs.p.c << 4) + (result & 0x0f); - } - - regs.p.v = ~(regs.a.l ^ rd.l) & (regs.a.l ^ result) & 0x80; - if(regs.p.d && result <= 0xff) result -= 0x60; - regs.p.c = result > 0xff; - regs.p.n = result & 0x80; - regs.p.z = (uint8_t)result == 0; - - regs.a.l = result; -} - -inline void CPUcore::op_sbc_w() { - int result; - rd.w ^= 0xffff; - - if(!regs.p.d) { - result = regs.a.w + rd.w + regs.p.c; - } else { - result = (regs.a.w & 0x000f) + (rd.w & 0x000f) + (regs.p.c << 0); - if(result <= 0x000f) result -= 0x0006; - regs.p.c = result > 0x000f; - result = (regs.a.w & 0x00f0) + (rd.w & 0x00f0) + (regs.p.c << 4) + (result & 0x000f); - if(result <= 0x00ff) result -= 0x0060; - regs.p.c = result > 0x00ff; - result = (regs.a.w & 0x0f00) + (rd.w & 0x0f00) + (regs.p.c << 8) + (result & 0x00ff); - if(result <= 0x0fff) result -= 0x0600; - regs.p.c = result > 0x0fff; - result = (regs.a.w & 0xf000) + (rd.w & 0xf000) + (regs.p.c << 12) + (result & 0x0fff); - } - - regs.p.v = ~(regs.a.w ^ rd.w) & (regs.a.w ^ result) & 0x8000; - if(regs.p.d && result <= 0xffff) result -= 0x6000; - regs.p.c = result > 0xffff; - regs.p.n = result & 0x8000; - regs.p.z = (uint16_t)result == 0; - - regs.a.w = result; -} - -inline void CPUcore::op_inc_b() { - rd.l++; - regs.p.n = rd.l & 0x80; - regs.p.z = rd.l == 0; -} - -inline void CPUcore::op_inc_w() { - rd.w++; - regs.p.n = rd.w & 0x8000; - regs.p.z = rd.w == 0; -} - -inline void CPUcore::op_dec_b() { - rd.l--; - regs.p.n = rd.l & 0x80; - regs.p.z = rd.l == 0; -} - -inline void CPUcore::op_dec_w() { - rd.w--; - regs.p.n = rd.w & 0x8000; - regs.p.z = rd.w == 0; -} - -inline void CPUcore::op_asl_b() { - regs.p.c = rd.l & 0x80; - rd.l <<= 1; - regs.p.n = rd.l & 0x80; - regs.p.z = rd.l == 0; -} - -inline void CPUcore::op_asl_w() { - regs.p.c = rd.w & 0x8000; - rd.w <<= 1; - regs.p.n = rd.w & 0x8000; - regs.p.z = rd.w == 0; -} - -inline void CPUcore::op_lsr_b() { - regs.p.c = rd.l & 1; - rd.l >>= 1; - regs.p.n = rd.l & 0x80; - regs.p.z = rd.l == 0; -} - -inline void CPUcore::op_lsr_w() { - regs.p.c = rd.w & 1; - rd.w >>= 1; - regs.p.n = rd.w & 0x8000; - regs.p.z = rd.w == 0; -} - -inline void CPUcore::op_rol_b() { - unsigned carry = (unsigned)regs.p.c; - regs.p.c = rd.l & 0x80; - rd.l = (rd.l << 1) | carry; - regs.p.n = rd.l & 0x80; - regs.p.z = rd.l == 0; -} - -inline void CPUcore::op_rol_w() { - unsigned carry = (unsigned)regs.p.c; - regs.p.c = rd.w & 0x8000; - rd.w = (rd.w << 1) | carry; - regs.p.n = rd.w & 0x8000; - regs.p.z = rd.w == 0; -} - -inline void CPUcore::op_ror_b() { - unsigned carry = (unsigned)regs.p.c << 7; - regs.p.c = rd.l & 1; - rd.l = carry | (rd.l >> 1); - regs.p.n = rd.l & 0x80; - regs.p.z = rd.l == 0; -} - -inline void CPUcore::op_ror_w() { - unsigned carry = (unsigned)regs.p.c << 15; - regs.p.c = rd.w & 1; - rd.w = carry | (rd.w >> 1); - regs.p.n = rd.w & 0x8000; - regs.p.z = rd.w == 0; -} - -inline void CPUcore::op_trb_b() { - regs.p.z = (rd.l & regs.a.l) == 0; - rd.l &= ~regs.a.l; -} - -inline void CPUcore::op_trb_w() { - regs.p.z = (rd.w & regs.a.w) == 0; - rd.w &= ~regs.a.w; -} - -inline void CPUcore::op_tsb_b() { - regs.p.z = (rd.l & regs.a.l) == 0; - rd.l |= regs.a.l; -} - -inline void CPUcore::op_tsb_w() { - regs.p.z = (rd.w & regs.a.w) == 0; - rd.w |= regs.a.w; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/cpu/core/core.cpp b/waterbox/libsnes/bsnes/snes/cpu/core/core.cpp deleted file mode 100644 index bef86eae07..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/core/core.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include - -#define CPUCORE_CPP -namespace SNES { - -#include "algorithms.cpp" -#include "disassembler/disassembler.cpp" - -#define L last_cycle(); -#define A 0 -#define X 1 -#define Y 2 -#define Z 3 -#define S 4 -#define D 5 -#define call(op) (this->*op)() - -#include "opcode_read.cpp" -#include "opcode_write.cpp" -#include "opcode_rmw.cpp" -#include "opcode_pc.cpp" -#include "opcode_misc.cpp" -#include "table.cpp" - -#undef L -#undef A -#undef X -#undef Y -#undef Z -#undef S -#undef D -#undef call - -//immediate, 2-cycle opcodes with I/O cycle will become bus read -//when an IRQ is to be triggered immediately after opcode completion. -//this affects the following opcodes: -// clc, cld, cli, clv, sec, sed, sei, -// tax, tay, txa, txy, tya, tyx, -// tcd, tcs, tdc, tsc, tsx, txs, -// inc, inx, iny, dec, dex, dey, -// asl, lsr, rol, ror, nop, xce. -alwaysinline void CPUcore::op_io_irq() { - if(interrupt_pending()) { - //modify I/O cycle to bus read cycle, do not increment PC - op_read(regs.pc.d); - } else { - op_io(); - } -} - -alwaysinline void CPUcore::op_io_cond2() { - if(regs.d.l != 0x00) { - op_io(); - } -} - -alwaysinline void CPUcore::op_io_cond4(uint16 x, uint16 y) { - if(!regs.p.x || (x & 0xff00) != (y & 0xff00)) { - op_io(); - } -} - -alwaysinline void CPUcore::op_io_cond6(uint16 addr) { - if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) { - op_io(); - } -} - -void CPUcore::op_irq() { - op_read(regs.pc.d); - op_io(); - if(!regs.e) op_writestack(regs.pc.b); - op_writestack(regs.pc.h); - op_writestack(regs.pc.l); - op_writestack(regs.e ? (regs.p & ~0x10) : regs.p); - rd.l = op_read(regs.vector + 0); - regs.pc.b = 0x00; - regs.p.i = 1; - regs.p.d = 0; - rd.h = op_read(regs.vector + 1); - regs.pc.w = rd.w; -} - -CPUcore::CPUcore() { - initialize_opcode_table(); -} - -} diff --git a/waterbox/libsnes/bsnes/snes/cpu/core/core.hpp b/waterbox/libsnes/bsnes/snes/cpu/core/core.hpp deleted file mode 100644 index 825ccd390b..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/core/core.hpp +++ /dev/null @@ -1,216 +0,0 @@ -struct CPUcore { - #include "registers.hpp" - #include "memory.hpp" - #include "disassembler/disassembler.hpp" - - regs_t regs; - reg24_t aa, rd; - uint8_t sp, dp; - - virtual void op_io() = 0; - virtual uint8_t op_read(uint32_t addr, eCDLog_Flags flags = eCDLog_Flags_CPUData) = 0; - virtual void op_write(uint32_t addr, uint8_t data) = 0; - virtual void last_cycle() = 0; - virtual bool interrupt_pending() = 0; - virtual void op_irq(); - - void op_io_irq(); - void op_io_cond2(); - void op_io_cond4(uint16 x, uint16 y); - void op_io_cond6(uint16 addr); - - void op_adc_b(); - void op_adc_w(); - void op_and_b(); - void op_and_w(); - void op_bit_b(); - void op_bit_w(); - void op_cmp_b(); - void op_cmp_w(); - void op_cpx_b(); - void op_cpx_w(); - void op_cpy_b(); - void op_cpy_w(); - void op_eor_b(); - void op_eor_w(); - void op_lda_b(); - void op_lda_w(); - void op_ldx_b(); - void op_ldx_w(); - void op_ldy_b(); - void op_ldy_w(); - void op_ora_b(); - void op_ora_w(); - void op_sbc_b(); - void op_sbc_w(); - - void op_inc_b(); - void op_inc_w(); - void op_dec_b(); - void op_dec_w(); - void op_asl_b(); - void op_asl_w(); - void op_lsr_b(); - void op_lsr_w(); - void op_rol_b(); - void op_rol_w(); - void op_ror_b(); - void op_ror_w(); - void op_trb_b(); - void op_trb_w(); - void op_tsb_b(); - void op_tsb_w(); - - template void op_read_const_b(); - template void op_read_const_w(); - void op_read_bit_const_b(); - void op_read_bit_const_w(); - template void op_read_addr_b(); - template void op_read_addr_w(); - template void op_read_addrx_b(); - template void op_read_addrx_w(); - template void op_read_addry_b(); - template void op_read_addry_w(); - template void op_read_long_b(); - template void op_read_long_w(); - template void op_read_longx_b(); - template void op_read_longx_w(); - template void op_read_dp_b(); - template void op_read_dp_w(); - template void op_read_dpr_b(); - template void op_read_dpr_w(); - template void op_read_idp_b(); - template void op_read_idp_w(); - template void op_read_idpx_b(); - template void op_read_idpx_w(); - template void op_read_idpy_b(); - template void op_read_idpy_w(); - template void op_read_ildp_b(); - template void op_read_ildp_w(); - template void op_read_ildpy_b(); - template void op_read_ildpy_w(); - template void op_read_sr_b(); - template void op_read_sr_w(); - template void op_read_isry_b(); - template void op_read_isry_w(); - - template void op_write_addr_b(); - template void op_write_addr_w(); - template void op_write_addrr_b(); - template void op_write_addrr_w(); - template void op_write_longr_b(); - template void op_write_longr_w(); - template void op_write_dp_b(); - template void op_write_dp_w(); - template void op_write_dpr_b(); - template void op_write_dpr_w(); - void op_sta_idp_b(); - void op_sta_idp_w(); - void op_sta_ildp_b(); - void op_sta_ildp_w(); - void op_sta_idpx_b(); - void op_sta_idpx_w(); - void op_sta_idpy_b(); - void op_sta_idpy_w(); - void op_sta_ildpy_b(); - void op_sta_ildpy_w(); - void op_sta_sr_b(); - void op_sta_sr_w(); - void op_sta_isry_b(); - void op_sta_isry_w(); - - template void op_adjust_imm_b(); - template void op_adjust_imm_w(); - void op_asl_imm_b(); - void op_asl_imm_w(); - void op_lsr_imm_b(); - void op_lsr_imm_w(); - void op_rol_imm_b(); - void op_rol_imm_w(); - void op_ror_imm_b(); - void op_ror_imm_w(); - template void op_adjust_addr_b(); - template void op_adjust_addr_w(); - template void op_adjust_addrx_b(); - template void op_adjust_addrx_w(); - template void op_adjust_dp_b(); - template void op_adjust_dp_w(); - template void op_adjust_dpx_b(); - template void op_adjust_dpx_w(); - - template void op_branch(); - void op_bra(); - void op_brl(); - void op_jmp_addr(); - void op_jmp_long(); - void op_jmp_iaddr(); - void op_jmp_iaddrx(); - void op_jmp_iladdr(); - void op_jsr_addr(); - void op_jsr_long_e(); - void op_jsr_long_n(); - void op_jsr_iaddrx_e(); - void op_jsr_iaddrx_n(); - void op_rti_e(); - void op_rti_n(); - void op_rts(); - void op_rtl_e(); - void op_rtl_n(); - - void op_nop(); - void op_wdm(); - void op_xba(); - template void op_move_b(); - template void op_move_w(); - template void op_interrupt_e(); - template void op_interrupt_n(); - void op_stp(); - void op_wai(); - void op_xce(); - template void op_flag(); - template void op_pflag_e(); - template void op_pflag_n(); - template void op_transfer_b(); - template void op_transfer_w(); - void op_tcs_e(); - void op_tcs_n(); - void op_tsx_b(); - void op_tsx_w(); - void op_txs_e(); - void op_txs_n(); - template void op_push_b(); - template void op_push_w(); - void op_phd_e(); - void op_phd_n(); - void op_phb(); - void op_phk(); - void op_php(); - template void op_pull_b(); - template void op_pull_w(); - void op_pld_e(); - void op_pld_n(); - void op_plb(); - void op_plp_e(); - void op_plp_n(); - void op_pea_e(); - void op_pea_n(); - void op_pei_e(); - void op_pei_n(); - void op_per_e(); - void op_per_n(); - - void (CPUcore::**opcode_table)(); - void (CPUcore::*op_table[256 * 5])(); - void initialize_opcode_table(); - void update_table(); - - enum { - table_EM = 0, // 8-bit accumulator, 8-bit index (emulation mode) - table_MX = 256, // 8-bit accumulator, 8-bit index - table_Mx = 512, // 8-bit accumulator, 16-bit index - table_mX = 768, //16-bit accumulator, 8-bit index - table_mx = 1024, //16-bit accumulator, 16-bit index - }; - - CPUcore(); -}; diff --git a/waterbox/libsnes/bsnes/snes/cpu/core/disassembler/disassembler.cpp b/waterbox/libsnes/bsnes/snes/cpu/core/disassembler/disassembler.cpp deleted file mode 100644 index 77a9bd4a9e..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/core/disassembler/disassembler.cpp +++ /dev/null @@ -1,448 +0,0 @@ -#ifdef CPUCORE_CPP - -uint8 CPUcore::dreadb(uint32 addr) { - if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) { - //$[00-3f|80-bf]:[2000-5fff] - //do not read MMIO registers within debugger - return 0x00; - } - return bus.read(addr); -} - -uint16 CPUcore::dreadw(uint32 addr) { - uint16 r; - r = dreadb((addr + 0) & 0xffffff) << 0; - r |= dreadb((addr + 1) & 0xffffff) << 8; - return r; -} - -uint32 CPUcore::dreadl(uint32 addr) { - uint32 r; - r = dreadb((addr + 0) & 0xffffff) << 0; - r |= dreadb((addr + 1) & 0xffffff) << 8; - r |= dreadb((addr + 2) & 0xffffff) << 16; - return r; -} - -uint32 CPUcore::decode(uint8 offset_type, uint32 addr) { - uint32 r = 0; - - switch(offset_type) { - case OPTYPE_DP: - r = (regs.d + (addr & 0xffff)) & 0xffff; - break; - case OPTYPE_DPX: - r = (regs.d + regs.x + (addr & 0xffff)) & 0xffff; - break; - case OPTYPE_DPY: - r = (regs.d + regs.y + (addr & 0xffff)) & 0xffff; - break; - case OPTYPE_IDP: - addr = (regs.d + (addr & 0xffff)) & 0xffff; - r = (regs.db << 16) + dreadw(addr); - break; - case OPTYPE_IDPX: - addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff; - r = (regs.db << 16) + dreadw(addr); - break; - case OPTYPE_IDPY: - addr = (regs.d + (addr & 0xffff)) & 0xffff; - r = (regs.db << 16) + dreadw(addr) + regs.y; - break; - case OPTYPE_ILDP: - addr = (regs.d + (addr & 0xffff)) & 0xffff; - r = dreadl(addr); - break; - case OPTYPE_ILDPY: - addr = (regs.d + (addr & 0xffff)) & 0xffff; - r = dreadl(addr) + regs.y; - break; - case OPTYPE_ADDR: - r = (regs.db << 16) + (addr & 0xffff); - break; - case OPTYPE_ADDR_PC: - r = (regs.pc.b << 16) + (addr & 0xffff); - break; - case OPTYPE_ADDRX: - r = (regs.db << 16) + (addr & 0xffff) + regs.x; - break; - case OPTYPE_ADDRY: - r = (regs.db << 16) + (addr & 0xffff) + regs.y; - break; - case OPTYPE_IADDR_PC: - r = (regs.pc.b << 16) + (addr & 0xffff); - break; - case OPTYPE_IADDRX: - r = (regs.pc.b << 16) + ((addr + regs.x) & 0xffff); - break; - case OPTYPE_ILADDR: - r = addr; - break; - case OPTYPE_LONG: - r = addr; - break; - case OPTYPE_LONGX: - r = (addr + regs.x); - break; - case OPTYPE_SR: - r = (regs.s + (addr & 0xff)) & 0xffff; - break; - case OPTYPE_ISRY: - addr = (regs.s + (addr & 0xff)) & 0xffff; - r = (regs.db << 16) + dreadw(addr) + regs.y; - break; - case OPTYPE_RELB: - r = (regs.pc.b << 16) + ((regs.pc.w + 2) & 0xffff); - r += int8(addr); - break; - case OPTYPE_RELW: - r = (regs.pc.b << 16) + ((regs.pc.w + 3) & 0xffff); - r += int16(addr); - break; - } - - return(r & 0xffffff); -} - -void CPUcore::disassemble_opcode(char *output, uint32 addr) { - static reg24_t pc; - char t[256]; - char *s = output; - - if(false /* in_opcode() == true */) { - strcpy(s, "?????? "); - return; - } - - pc.d = addr; - sprintf(s, "%.6x: ", (uint32)pc.d); - - uint8 op = dreadb(pc.d); pc.w++; - uint8 op0 = dreadb(pc.d); pc.w++; - uint8 op1 = dreadb(pc.d); pc.w++; - uint8 op2 = dreadb(pc.d); - - #define op8 ((op0)) - #define op16 ((op0) | (op1 << 8)) - #define op24 ((op0) | (op1 << 8) | (op2 << 16)) - #define a8 (regs.e || regs.p.m) - #define x8 (regs.e || regs.p.x) - - switch(op) { - case 0x00: sprintf(t, "brk #$%.2x ", op8); break; - case 0x01: sprintf(t, "ora ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break; - case 0x02: sprintf(t, "cop #$%.2x ", op8); break; - case 0x03: sprintf(t, "ora $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break; - case 0x04: sprintf(t, "tsb $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0x05: sprintf(t, "ora $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0x06: sprintf(t, "asl $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0x07: sprintf(t, "ora [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break; - case 0x08: sprintf(t, "php "); break; - case 0x09: - if(a8)sprintf(t, "ora #$%.2x ", op8); - else sprintf(t, "ora #$%.4x ", op16); break; - case 0x0a: sprintf(t, "asl a "); break; - case 0x0b: sprintf(t, "phd "); break; - case 0x0c: sprintf(t, "tsb $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0x0d: sprintf(t, "ora $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0x0e: sprintf(t, "asl $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0x0f: sprintf(t, "ora $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0x10: sprintf(t, "bpl $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; - case 0x11: sprintf(t, "ora ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break; - case 0x12: sprintf(t, "ora ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break; - case 0x13: sprintf(t, "ora ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break; - case 0x14: sprintf(t, "trb $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0x15: sprintf(t, "ora $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0x16: sprintf(t, "asl $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0x17: sprintf(t, "ora [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break; - case 0x18: sprintf(t, "clc "); break; - case 0x19: sprintf(t, "ora $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; - case 0x1a: sprintf(t, "inc "); break; - case 0x1b: sprintf(t, "tcs "); break; - case 0x1c: sprintf(t, "trb $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0x1d: sprintf(t, "ora $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; - case 0x1e: sprintf(t, "asl $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; - case 0x1f: sprintf(t, "ora $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break; - case 0x20: sprintf(t, "jsr $%.4x [%.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break; - case 0x21: sprintf(t, "and ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break; - case 0x22: sprintf(t, "jsl $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0x23: sprintf(t, "and $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break; - case 0x24: sprintf(t, "bit $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0x25: sprintf(t, "and $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0x26: sprintf(t, "rol $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0x27: sprintf(t, "and [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break; - case 0x28: sprintf(t, "plp "); break; - case 0x29: - if(a8)sprintf(t, "and #$%.2x ", op8); - else sprintf(t, "and #$%.4x ", op16); break; - case 0x2a: sprintf(t, "rol a "); break; - case 0x2b: sprintf(t, "pld "); break; - case 0x2c: sprintf(t, "bit $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0x2d: sprintf(t, "and $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0x2e: sprintf(t, "rol $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0x2f: sprintf(t, "and $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0x30: sprintf(t, "bmi $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; - case 0x31: sprintf(t, "and ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break; - case 0x32: sprintf(t, "and ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break; - case 0x33: sprintf(t, "and ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break; - case 0x34: sprintf(t, "bit $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0x35: sprintf(t, "and $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0x36: sprintf(t, "rol $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0x37: sprintf(t, "and [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break; - case 0x38: sprintf(t, "sec "); break; - case 0x39: sprintf(t, "and $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; - case 0x3a: sprintf(t, "dec "); break; - case 0x3b: sprintf(t, "tsc "); break; - case 0x3c: sprintf(t, "bit $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; - case 0x3d: sprintf(t, "and $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; - case 0x3e: sprintf(t, "rol $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; - case 0x3f: sprintf(t, "and $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break; - case 0x40: sprintf(t, "rti "); break; - case 0x41: sprintf(t, "eor ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break; - case 0x42: sprintf(t, "wdm "); break; - case 0x43: sprintf(t, "eor $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break; - case 0x44: sprintf(t, "mvp $%.2x,$%.2x ", op1, op8); break; - case 0x45: sprintf(t, "eor $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0x46: sprintf(t, "lsr $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0x47: sprintf(t, "eor [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break; - case 0x48: sprintf(t, "pha "); break; - case 0x49: - if(a8)sprintf(t, "eor #$%.2x ", op8); - else sprintf(t, "eor #$%.4x ", op16); break; - case 0x4a: sprintf(t, "lsr a "); break; - case 0x4b: sprintf(t, "phk "); break; - case 0x4c: sprintf(t, "jmp $%.4x [%.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break; - case 0x4d: sprintf(t, "eor $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0x4e: sprintf(t, "lsr $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0x4f: sprintf(t, "eor $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0x50: sprintf(t, "bvc $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; - case 0x51: sprintf(t, "eor ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break; - case 0x52: sprintf(t, "eor ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break; - case 0x53: sprintf(t, "eor ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break; - case 0x54: sprintf(t, "mvn $%.2x,$%.2x ", op1, op8); break; - case 0x55: sprintf(t, "eor $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0x56: sprintf(t, "lsr $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0x57: sprintf(t, "eor [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break; - case 0x58: sprintf(t, "cli "); break; - case 0x59: sprintf(t, "eor $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; - case 0x5a: sprintf(t, "phy "); break; - case 0x5b: sprintf(t, "tcd "); break; - case 0x5c: sprintf(t, "jml $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0x5d: sprintf(t, "eor $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; - case 0x5e: sprintf(t, "lsr $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; - case 0x5f: sprintf(t, "eor $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break; - case 0x60: sprintf(t, "rts "); break; - case 0x61: sprintf(t, "adc ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break; - case 0x62: sprintf(t, "per $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0x63: sprintf(t, "adc $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break; - case 0x64: sprintf(t, "stz $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0x65: sprintf(t, "adc $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0x66: sprintf(t, "ror $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0x67: sprintf(t, "adc [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break; - case 0x68: sprintf(t, "pla "); break; - case 0x69: - if(a8)sprintf(t, "adc #$%.2x ", op8); - else sprintf(t, "adc #$%.4x ", op16); break; - case 0x6a: sprintf(t, "ror a "); break; - case 0x6b: sprintf(t, "rtl "); break; - case 0x6c: sprintf(t, "jmp ($%.4x) [%.6x]", op16, decode(OPTYPE_IADDR_PC, op16)); break; - case 0x6d: sprintf(t, "adc $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0x6e: sprintf(t, "ror $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0x6f: sprintf(t, "adc $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0x70: sprintf(t, "bvs $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; - case 0x71: sprintf(t, "adc ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break; - case 0x72: sprintf(t, "adc ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break; - case 0x73: sprintf(t, "adc ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break; - case 0x74: sprintf(t, "stz $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0x75: sprintf(t, "adc $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0x76: sprintf(t, "ror $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0x77: sprintf(t, "adc [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break; - case 0x78: sprintf(t, "sei "); break; - case 0x79: sprintf(t, "adc $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; - case 0x7a: sprintf(t, "ply "); break; - case 0x7b: sprintf(t, "tdc "); break; - case 0x7c: sprintf(t, "jmp ($%.4x,x) [%.6x]", op16, decode(OPTYPE_IADDRX, op16)); break; - case 0x7d: sprintf(t, "adc $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; - case 0x7e: sprintf(t, "ror $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; - case 0x7f: sprintf(t, "adc $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break; - case 0x80: sprintf(t, "bra $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; - case 0x81: sprintf(t, "sta ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break; - case 0x82: sprintf(t, "brl $%.4x [%.6x]", uint16(decode(OPTYPE_RELW, op16)), decode(OPTYPE_RELW, op16)); break; - case 0x83: sprintf(t, "sta $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break; - case 0x84: sprintf(t, "sty $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0x85: sprintf(t, "sta $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0x86: sprintf(t, "stx $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0x87: sprintf(t, "sta [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break; - case 0x88: sprintf(t, "dey "); break; - case 0x89: - if(a8)sprintf(t, "bit #$%.2x ", op8); - else sprintf(t, "bit #$%.4x ", op16); break; - case 0x8a: sprintf(t, "txa "); break; - case 0x8b: sprintf(t, "phb "); break; - case 0x8c: sprintf(t, "sty $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0x8d: sprintf(t, "sta $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0x8e: sprintf(t, "stx $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0x8f: sprintf(t, "sta $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0x90: sprintf(t, "bcc $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; - case 0x91: sprintf(t, "sta ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break; - case 0x92: sprintf(t, "sta ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break; - case 0x93: sprintf(t, "sta ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break; - case 0x94: sprintf(t, "sty $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0x95: sprintf(t, "sta $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0x96: sprintf(t, "stx $%.2x,y [%.6x]", op8, decode(OPTYPE_DPY, op8)); break; - case 0x97: sprintf(t, "sta [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break; - case 0x98: sprintf(t, "tya "); break; - case 0x99: sprintf(t, "sta $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; - case 0x9a: sprintf(t, "txs "); break; - case 0x9b: sprintf(t, "txy "); break; - case 0x9c: sprintf(t, "stz $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0x9d: sprintf(t, "sta $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; - case 0x9e: sprintf(t, "stz $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; - case 0x9f: sprintf(t, "sta $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break; - case 0xa0: - if(x8)sprintf(t, "ldy #$%.2x ", op8); - else sprintf(t, "ldy #$%.4x ", op16); break; - case 0xa1: sprintf(t, "lda ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break; - case 0xa2: - if(x8)sprintf(t, "ldx #$%.2x ", op8); - else sprintf(t, "ldx #$%.4x ", op16); break; - case 0xa3: sprintf(t, "lda $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break; - case 0xa4: sprintf(t, "ldy $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0xa5: sprintf(t, "lda $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0xa6: sprintf(t, "ldx $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0xa7: sprintf(t, "lda [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break; - case 0xa8: sprintf(t, "tay "); break; - case 0xa9: - if(a8)sprintf(t, "lda #$%.2x ", op8); - else sprintf(t, "lda #$%.4x ", op16); break; - case 0xaa: sprintf(t, "tax "); break; - case 0xab: sprintf(t, "plb "); break; - case 0xac: sprintf(t, "ldy $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0xad: sprintf(t, "lda $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0xae: sprintf(t, "ldx $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0xaf: sprintf(t, "lda $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0xb0: sprintf(t, "bcs $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; - case 0xb1: sprintf(t, "lda ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break; - case 0xb2: sprintf(t, "lda ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break; - case 0xb3: sprintf(t, "lda ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break; - case 0xb4: sprintf(t, "ldy $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0xb5: sprintf(t, "lda $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0xb6: sprintf(t, "ldx $%.2x,y [%.6x]", op8, decode(OPTYPE_DPY, op8)); break; - case 0xb7: sprintf(t, "lda [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break; - case 0xb8: sprintf(t, "clv "); break; - case 0xb9: sprintf(t, "lda $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; - case 0xba: sprintf(t, "tsx "); break; - case 0xbb: sprintf(t, "tyx "); break; - case 0xbc: sprintf(t, "ldy $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; - case 0xbd: sprintf(t, "lda $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; - case 0xbe: sprintf(t, "ldx $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; - case 0xbf: sprintf(t, "lda $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break; - case 0xc0: - if(x8)sprintf(t, "cpy #$%.2x ", op8); - else sprintf(t, "cpy #$%.4x ", op16); break; - case 0xc1: sprintf(t, "cmp ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break; - case 0xc2: sprintf(t, "rep #$%.2x ", op8); break; - case 0xc3: sprintf(t, "cmp $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break; - case 0xc4: sprintf(t, "cpy $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0xc5: sprintf(t, "cmp $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0xc6: sprintf(t, "dec $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0xc7: sprintf(t, "cmp [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break; - case 0xc8: sprintf(t, "iny "); break; - case 0xc9: - if(a8)sprintf(t, "cmp #$%.2x ", op8); - else sprintf(t, "cmp #$%.4x ", op16); break; - case 0xca: sprintf(t, "dex "); break; - case 0xcb: sprintf(t, "wai "); break; - case 0xcc: sprintf(t, "cpy $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0xcd: sprintf(t, "cmp $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0xce: sprintf(t, "dec $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0xcf: sprintf(t, "cmp $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0xd0: sprintf(t, "bne $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; - case 0xd1: sprintf(t, "cmp ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break; - case 0xd2: sprintf(t, "cmp ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break; - case 0xd3: sprintf(t, "cmp ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break; - case 0xd4: sprintf(t, "pei ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break; - case 0xd5: sprintf(t, "cmp $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0xd6: sprintf(t, "dec $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0xd7: sprintf(t, "cmp [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break; - case 0xd8: sprintf(t, "cld "); break; - case 0xd9: sprintf(t, "cmp $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; - case 0xda: sprintf(t, "phx "); break; - case 0xdb: sprintf(t, "stp "); break; - case 0xdc: sprintf(t, "jmp [$%.4x] [%.6x]", op16, decode(OPTYPE_ILADDR, op16)); break; - case 0xdd: sprintf(t, "cmp $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; - case 0xde: sprintf(t, "dec $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; - case 0xdf: sprintf(t, "cmp $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break; - case 0xe0: - if(x8)sprintf(t, "cpx #$%.2x ", op8); - else sprintf(t, "cpx #$%.4x ", op16); break; - case 0xe1: sprintf(t, "sbc ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break; - case 0xe2: sprintf(t, "sep #$%.2x ", op8); break; - case 0xe3: sprintf(t, "sbc $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break; - case 0xe4: sprintf(t, "cpx $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0xe5: sprintf(t, "sbc $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0xe6: sprintf(t, "inc $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; - case 0xe7: sprintf(t, "sbc [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break; - case 0xe8: sprintf(t, "inx "); break; - case 0xe9: - if(a8)sprintf(t, "sbc #$%.2x ", op8); - else sprintf(t, "sbc #$%.4x ", op16); break; - case 0xea: sprintf(t, "nop "); break; - case 0xeb: sprintf(t, "xba "); break; - case 0xec: sprintf(t, "cpx $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0xed: sprintf(t, "sbc $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0xee: sprintf(t, "inc $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0xef: sprintf(t, "sbc $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0xf0: sprintf(t, "beq $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; - case 0xf1: sprintf(t, "sbc ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break; - case 0xf2: sprintf(t, "sbc ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break; - case 0xf3: sprintf(t, "sbc ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break; - case 0xf4: sprintf(t, "pea $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; - case 0xf5: sprintf(t, "sbc $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0xf6: sprintf(t, "inc $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break; - case 0xf7: sprintf(t, "sbc [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break; - case 0xf8: sprintf(t, "sed "); break; - case 0xf9: sprintf(t, "sbc $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; - case 0xfa: sprintf(t, "plx "); break; - case 0xfb: sprintf(t, "xce "); break; - case 0xfc: sprintf(t, "jsr ($%.4x,x) [%.6x]", op16, decode(OPTYPE_IADDRX, op16)); break; - case 0xfd: sprintf(t, "sbc $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; - case 0xfe: sprintf(t, "inc $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; - case 0xff: sprintf(t, "sbc $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break; - } - - #undef op8 - #undef op16 - #undef op24 - #undef a8 - #undef x8 - - strcat(s, t); - strcat(s, " "); - - sprintf(t, "A:%.4x X:%.4x Y:%.4x S:%.4x D:%.4x DB:%.2x ", - regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d.w, regs.db); - strcat(s, t); - - if(regs.e) { - sprintf(t, "%c%c%c%c%c%c%c%c", - regs.p.n ? 'N' : 'n', regs.p.v ? 'V' : 'v', - regs.p.m ? '1' : '0', regs.p.x ? 'B' : 'b', - regs.p.d ? 'D' : 'd', regs.p.i ? 'I' : 'i', - regs.p.z ? 'Z' : 'z', regs.p.c ? 'C' : 'c'); - } else { - sprintf(t, "%c%c%c%c%c%c%c%c", - regs.p.n ? 'N' : 'n', regs.p.v ? 'V' : 'v', - regs.p.m ? 'M' : 'm', regs.p.x ? 'X' : 'x', - regs.p.d ? 'D' : 'd', regs.p.i ? 'I' : 'i', - regs.p.z ? 'Z' : 'z', regs.p.c ? 'C' : 'c'); - } - - strcat(s, t); - strcat(s, " "); - - sprintf(t, "V:%3d H:%3d", cpu.vcounter(), cpu.hdot()); - strcat(s, t); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/cpu/core/disassembler/disassembler.hpp b/waterbox/libsnes/bsnes/snes/cpu/core/disassembler/disassembler.hpp deleted file mode 100644 index a57ca635ad..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/core/disassembler/disassembler.hpp +++ /dev/null @@ -1,29 +0,0 @@ -enum { - OPTYPE_DP = 0, //dp - OPTYPE_DPX, //dp,x - OPTYPE_DPY, //dp,y - OPTYPE_IDP, //(dp) - OPTYPE_IDPX, //(dp,x) - OPTYPE_IDPY, //(dp),y - OPTYPE_ILDP, //[dp] - OPTYPE_ILDPY, //[dp],y - OPTYPE_ADDR, //addr - OPTYPE_ADDRX, //addr,x - OPTYPE_ADDRY, //addr,y - OPTYPE_IADDRX, //(addr,x) - OPTYPE_ILADDR, //[addr] - OPTYPE_LONG, //long - OPTYPE_LONGX, //long, x - OPTYPE_SR, //sr,s - OPTYPE_ISRY, //(sr,s),y - OPTYPE_ADDR_PC, //pbr:addr - OPTYPE_IADDR_PC, //pbr:(addr) - OPTYPE_RELB, //relb - OPTYPE_RELW, //relw -}; - -void disassemble_opcode(char *output, uint32 addr); -uint8 dreadb(uint32 addr); -uint16 dreadw(uint32 addr); -uint32 dreadl(uint32 addr); -uint32 decode(uint8 offset_type, uint32 addr); diff --git a/waterbox/libsnes/bsnes/snes/cpu/core/memory.hpp b/waterbox/libsnes/bsnes/snes/cpu/core/memory.hpp deleted file mode 100644 index 825c1743f1..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/core/memory.hpp +++ /dev/null @@ -1,89 +0,0 @@ -alwaysinline uint8_t op_readpcfirst() { - return op_read((regs.pc.b << 16) + regs.pc.w++, (eCDLog_Flags)(eCDLog_Flags_ExecFirst | (regs.p & 0x30))); -} - -alwaysinline uint8_t op_readpc() { - return op_read((regs.pc.b << 16) + regs.pc.w++, eCDLog_Flags_ExecOperand); -} - -alwaysinline uint8_t op_readstack() { - cdlInfo.currFlags = eCDLog_Flags_CPUData; - regs.e ? regs.s.l++ : regs.s.w++; - return op_read(regs.s.w); -} - -alwaysinline uint8_t op_readstackn() { - cdlInfo.currFlags = eCDLog_Flags_CPUData; - return op_read(++regs.s.w); -} - -alwaysinline uint8_t op_readaddr(uint32_t addr) { - cdlInfo.currFlags = eCDLog_Flags_CPUData; - return op_read(addr & 0xffff); -} - -alwaysinline uint8_t op_readlong(uint32_t addr) { - cdlInfo.currFlags = eCDLog_Flags_CPUData; - return op_read(addr & 0xffffff); -} - -alwaysinline uint8_t op_readdbr(uint32_t addr) { - cdlInfo.currFlags = eCDLog_Flags_CPUData; - return op_read(((regs.db << 16) + addr) & 0xffffff); -} - -alwaysinline uint8_t op_readpbr(uint32_t addr) { - cdlInfo.currFlags = eCDLog_Flags_CPUData; - return op_read((regs.pc.b << 16) + (addr & 0xffff)); -} - -alwaysinline uint8_t op_readdp(uint32_t addr) { - cdlInfo.currFlags = eCDLog_Flags_CPUData; - if(regs.e && regs.d.l == 0x00) { - return op_read((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff)); - } else { - return op_read((regs.d + (addr & 0xffff)) & 0xffff); - } -} - -alwaysinline uint8_t op_readsp(uint32_t addr) { - cdlInfo.currFlags = eCDLog_Flags_CPUData; - return op_read((regs.s + (addr & 0xffff)) & 0xffff); -} - -alwaysinline void op_writestack(uint8_t data) { - op_write(regs.s.w, data); - regs.e ? regs.s.l-- : regs.s.w--; -} - -alwaysinline void op_writestackn(uint8_t data) { - op_write(regs.s.w--, data); -} - -alwaysinline void op_writeaddr(uint32_t addr, uint8_t data) { - op_write(addr & 0xffff, data); -} - -alwaysinline void op_writelong(uint32_t addr, uint8_t data) { - op_write(addr & 0xffffff, data); -} - -alwaysinline void op_writedbr(uint32_t addr, uint8_t data) { - op_write(((regs.db << 16) + addr) & 0xffffff, data); -} - -alwaysinline void op_writepbr(uint32_t addr, uint8_t data) { - op_write((regs.pc.b << 16) + (addr & 0xffff), data); -} - -alwaysinline void op_writedp(uint32_t addr, uint8_t data) { - if(regs.e && regs.d.l == 0x00) { - op_write((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff), data); - } else { - op_write((regs.d + (addr & 0xffff)) & 0xffff, data); - } -} - -alwaysinline void op_writesp(uint32_t addr, uint8_t data) { - op_write((regs.s + (addr & 0xffff)) & 0xffff, data); -} diff --git a/waterbox/libsnes/bsnes/snes/cpu/core/opcode_misc.cpp b/waterbox/libsnes/bsnes/snes/cpu/core/opcode_misc.cpp deleted file mode 100644 index 8087fe66e1..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/core/opcode_misc.cpp +++ /dev/null @@ -1,338 +0,0 @@ -#ifdef CPUCORE_CPP - -void CPUcore::op_nop() { -L op_io_irq(); -} - -void CPUcore::op_wdm() { -L op_readpc(); -} - -void CPUcore::op_xba() { - op_io(); -L op_io(); - regs.a.l ^= regs.a.h; - regs.a.h ^= regs.a.l; - regs.a.l ^= regs.a.h; - regs.p.n = (regs.a.l & 0x80); - regs.p.z = (regs.a.l == 0); -} - -template void CPUcore::op_move_b() { - dp = op_readpc(); - sp = op_readpc(); - regs.db = dp; - rd.l = op_readlong((sp << 16) | regs.x.w); - op_writelong((dp << 16) | regs.y.w, rd.l); - op_io(); - regs.x.l += adjust; - regs.y.l += adjust; -L op_io(); - if(regs.a.w--) regs.pc.w -= 3; -} - -template void CPUcore::op_move_w() { - dp = op_readpc(); - sp = op_readpc(); - regs.db = dp; - rd.l = op_readlong((sp << 16) | regs.x.w); - op_writelong((dp << 16) | regs.y.w, rd.l); - op_io(); - regs.x.w += adjust; - regs.y.w += adjust; -L op_io(); - if(regs.a.w--) regs.pc.w -= 3; -} - -template void CPUcore::op_interrupt_e() { - op_readpc(); - op_writestack(regs.pc.h); - op_writestack(regs.pc.l); - op_writestack(regs.p); - rd.l = op_readlong(vectorE + 0); - regs.pc.b = 0; - regs.p.i = 1; - regs.p.d = 0; -L rd.h = op_readlong(vectorE + 1); - regs.pc.w = rd.w; -} - -template void CPUcore::op_interrupt_n() { - op_readpc(); - op_writestack(regs.pc.b); - op_writestack(regs.pc.h); - op_writestack(regs.pc.l); - op_writestack(regs.p); - rd.l = op_readlong(vectorN + 0); - regs.pc.b = 0x00; - regs.p.i = 1; - regs.p.d = 0; -L rd.h = op_readlong(vectorN + 1); - regs.pc.w = rd.w; -} - -void CPUcore::op_stp() { - while(regs.wai = true) { -L op_io(); - } -} - -void CPUcore::op_wai() { - regs.wai = true; - while(regs.wai) { -L op_io(); - } - op_io(); -} - -void CPUcore::op_xce() { -L op_io_irq(); - bool carry = regs.p.c; - regs.p.c = regs.e; - regs.e = carry; - if(regs.e) { - regs.p |= 0x30; - regs.s.h = 0x01; - } - if(regs.p.x) { - regs.x.h = 0x00; - regs.y.h = 0x00; - } - update_table(); -} - -template void CPUcore::op_flag() { -L op_io_irq(); - regs.p = (regs.p & ~mask) | value; -} - -template void CPUcore::op_pflag_e() { - rd.l = op_readpc(); -L op_io(); - regs.p = (mode ? regs.p | rd.l : regs.p & ~rd.l); - regs.p |= 0x30; - if(regs.p.x) { - regs.x.h = 0x00; - regs.y.h = 0x00; - } - update_table(); -} - -template void CPUcore::op_pflag_n() { - rd.l = op_readpc(); -L op_io(); - regs.p = (mode ? regs.p | rd.l : regs.p & ~rd.l); - if(regs.p.x) { - regs.x.h = 0x00; - regs.y.h = 0x00; - } - update_table(); -} - -template void CPUcore::op_transfer_b() { -L op_io_irq(); - regs.r[to].l = regs.r[from].l; - regs.p.n = (regs.r[to].l & 0x80); - regs.p.z = (regs.r[to].l == 0); -} - -template void CPUcore::op_transfer_w() { -L op_io_irq(); - regs.r[to].w = regs.r[from].w; - regs.p.n = (regs.r[to].w & 0x8000); - regs.p.z = (regs.r[to].w == 0); -} - -void CPUcore::op_tcs_e() { -L op_io_irq(); - regs.s.l = regs.a.l; -} - -void CPUcore::op_tcs_n() { -L op_io_irq(); - regs.s.w = regs.a.w; -} - -void CPUcore::op_tsx_b() { -L op_io_irq(); - regs.x.l = regs.s.l; - regs.p.n = (regs.x.l & 0x80); - regs.p.z = (regs.x.l == 0); -} - -void CPUcore::op_tsx_w() { -L op_io_irq(); - regs.x.w = regs.s.w; - regs.p.n = (regs.x.w & 0x8000); - regs.p.z = (regs.x.w == 0); -} - -void CPUcore::op_txs_e() { -L op_io_irq(); - regs.s.l = regs.x.l; -} - -void CPUcore::op_txs_n() { -L op_io_irq(); - regs.s.w = regs.x.w; -} - -template void CPUcore::op_push_b() { - op_io(); -L op_writestack(regs.r[n].l); -} - -template void CPUcore::op_push_w() { - op_io(); - op_writestack(regs.r[n].h); -L op_writestack(regs.r[n].l); -} - -void CPUcore::op_phd_e() { - op_io(); - op_writestackn(regs.d.h); -L op_writestackn(regs.d.l); - regs.s.h = 0x01; -} - -void CPUcore::op_phd_n() { - op_io(); - op_writestackn(regs.d.h); -L op_writestackn(regs.d.l); -} - -void CPUcore::op_phb() { - op_io(); -L op_writestack(regs.db); -} - -void CPUcore::op_phk() { - op_io(); -L op_writestack(regs.pc.b); -} - -void CPUcore::op_php() { - op_io(); -L op_writestack(regs.p); -} - -template void CPUcore::op_pull_b() { - op_io(); - op_io(); -L regs.r[n].l = op_readstack(); - regs.p.n = (regs.r[n].l & 0x80); - regs.p.z = (regs.r[n].l == 0); -} - -template void CPUcore::op_pull_w() { - op_io(); - op_io(); - regs.r[n].l = op_readstack(); -L regs.r[n].h = op_readstack(); - regs.p.n = (regs.r[n].w & 0x8000); - regs.p.z = (regs.r[n].w == 0); -} - -void CPUcore::op_pld_e() { - op_io(); - op_io(); - regs.d.l = op_readstackn(); -L regs.d.h = op_readstackn(); - regs.p.n = (regs.d.w & 0x8000); - regs.p.z = (regs.d.w == 0); - regs.s.h = 0x01; -} - -void CPUcore::op_pld_n() { - op_io(); - op_io(); - regs.d.l = op_readstackn(); -L regs.d.h = op_readstackn(); - regs.p.n = (regs.d.w & 0x8000); - regs.p.z = (regs.d.w == 0); -} - -void CPUcore::op_plb() { - op_io(); - op_io(); -L regs.db = op_readstack(); - regs.p.n = (regs.db & 0x80); - regs.p.z = (regs.db == 0); -} - -void CPUcore::op_plp_e() { - op_io(); - op_io(); -L regs.p = op_readstack() | 0x30; - if(regs.p.x) { - regs.x.h = 0x00; - regs.y.h = 0x00; - } - update_table(); -} - -void CPUcore::op_plp_n() { - op_io(); - op_io(); -L regs.p = op_readstack(); - if(regs.p.x) { - regs.x.h = 0x00; - regs.y.h = 0x00; - } - update_table(); -} - -void CPUcore::op_pea_e() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_writestackn(aa.h); -L op_writestackn(aa.l); - regs.s.h = 0x01; -} - -void CPUcore::op_pea_n() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_writestackn(aa.h); -L op_writestackn(aa.l); -} - -void CPUcore::op_pei_e() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - op_writestackn(aa.h); -L op_writestackn(aa.l); - regs.s.h = 0x01; -} - -void CPUcore::op_pei_n() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - op_writestackn(aa.h); -L op_writestackn(aa.l); -} - -void CPUcore::op_per_e() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io(); - rd.w = regs.pc.d + (int16)aa.w; - op_writestackn(rd.h); -L op_writestackn(rd.l); - regs.s.h = 0x01; -} - -void CPUcore::op_per_n() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io(); - rd.w = regs.pc.d + (int16)aa.w; - op_writestackn(rd.h); -L op_writestackn(rd.l); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/cpu/core/opcode_pc.cpp b/waterbox/libsnes/bsnes/snes/cpu/core/opcode_pc.cpp deleted file mode 100644 index 3b4543f378..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/core/opcode_pc.cpp +++ /dev/null @@ -1,181 +0,0 @@ -#ifdef CPUCORE_CPP - -template void CPUcore::op_branch() { - if((bool)(regs.p & bit) != val) { -L rd.l = op_readpc(); - } else { - rd.l = op_readpc(); - aa.w = regs.pc.d + (int8)rd.l; - op_io_cond6(aa.w); -L op_io(); - regs.pc.w = aa.w; - } -} - -void CPUcore::op_bra() { - rd.l = op_readpc(); - aa.w = regs.pc.d + (int8)rd.l; - op_io_cond6(aa.w); -L op_io(); - regs.pc.w = aa.w; -} - -void CPUcore::op_brl() { - rd.l = op_readpc(); - rd.h = op_readpc(); -L op_io(); - regs.pc.w = regs.pc.d + (int16)rd.w; -} - -void CPUcore::op_jmp_addr() { - rd.l = op_readpc(); -L rd.h = op_readpc(); - regs.pc.w = rd.w; -} - -void CPUcore::op_jmp_long() { - rd.l = op_readpc(); - rd.h = op_readpc(); -L rd.b = op_readpc(); - regs.pc.d = rd.d & 0xffffff; -} - -void CPUcore::op_jmp_iaddr() { - aa.l = op_readpc(); - aa.h = op_readpc(); - rd.l = op_readaddr(aa.w + 0); -L rd.h = op_readaddr(aa.w + 1); - regs.pc.w = rd.w; -} - -void CPUcore::op_jmp_iaddrx() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io(); - rd.l = op_readpbr(aa.w + regs.x.w + 0); -L rd.h = op_readpbr(aa.w + regs.x.w + 1); - regs.pc.w = rd.w; -} - -void CPUcore::op_jmp_iladdr() { - aa.l = op_readpc(); - aa.h = op_readpc(); - rd.l = op_readaddr(aa.w + 0); - rd.h = op_readaddr(aa.w + 1); -L rd.b = op_readaddr(aa.w + 2); - regs.pc.d = rd.d & 0xffffff; -} - -void CPUcore::op_jsr_addr() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io(); - regs.pc.w--; - op_writestack(regs.pc.h); -L op_writestack(regs.pc.l); - regs.pc.w = aa.w; -} - -void CPUcore::op_jsr_long_e() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_writestackn(regs.pc.b); - op_io(); - aa.b = op_readpc(); - regs.pc.w--; - op_writestackn(regs.pc.h); -L op_writestackn(regs.pc.l); - regs.pc.d = aa.d & 0xffffff; - regs.s.h = 0x01; -} - -void CPUcore::op_jsr_long_n() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_writestackn(regs.pc.b); - op_io(); - aa.b = op_readpc(); - regs.pc.w--; - op_writestackn(regs.pc.h); -L op_writestackn(regs.pc.l); - regs.pc.d = aa.d & 0xffffff; -} - -void CPUcore::op_jsr_iaddrx_e() { - aa.l = op_readpc(); - op_writestackn(regs.pc.h); - op_writestackn(regs.pc.l); - aa.h = op_readpc(); - op_io(); - rd.l = op_readpbr(aa.w + regs.x.w + 0); -L rd.h = op_readpbr(aa.w + regs.x.w + 1); - regs.pc.w = rd.w; - regs.s.h = 0x01; -} - -void CPUcore::op_jsr_iaddrx_n() { - aa.l = op_readpc(); - op_writestackn(regs.pc.h); - op_writestackn(regs.pc.l); - aa.h = op_readpc(); - op_io(); - rd.l = op_readpbr(aa.w + regs.x.w + 0); -L rd.h = op_readpbr(aa.w + regs.x.w + 1); - regs.pc.w = rd.w; -} - -void CPUcore::op_rti_e() { - op_io(); - op_io(); - regs.p = op_readstack() | 0x30; - rd.l = op_readstack(); -L rd.h = op_readstack(); - regs.pc.w = rd.w; -} - -void CPUcore::op_rti_n() { - op_io(); - op_io(); - regs.p = op_readstack(); - if(regs.p.x) { - regs.x.h = 0x00; - regs.y.h = 0x00; - } - rd.l = op_readstack(); - rd.h = op_readstack(); -L rd.b = op_readstack(); - regs.pc.d = rd.d & 0xffffff; - update_table(); -} - -void CPUcore::op_rts() { - op_io(); - op_io(); - rd.l = op_readstack(); - rd.h = op_readstack(); -L op_io(); - regs.pc.w = ++rd.w; -} - -void CPUcore::op_rtl_e() { - op_io(); - op_io(); - rd.l = op_readstackn(); - rd.h = op_readstackn(); -L rd.b = op_readstackn(); - regs.pc.b = rd.b; - regs.pc.w = ++rd.w; - regs.s.h = 0x01; -} - -void CPUcore::op_rtl_n() { - op_io(); - op_io(); - rd.l = op_readstackn(); - rd.h = op_readstackn(); -L rd.b = op_readstackn(); - regs.pc.b = rd.b; - regs.pc.w = ++rd.w; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/cpu/core/opcode_read.cpp b/waterbox/libsnes/bsnes/snes/cpu/core/opcode_read.cpp deleted file mode 100644 index 61a7feb341..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/core/opcode_read.cpp +++ /dev/null @@ -1,279 +0,0 @@ -#ifdef CPUCORE_CPP - -template void CPUcore::op_read_const_b() { -L rd.l = op_readpc(); - call(op); -} - -template void CPUcore::op_read_const_w() { - rd.l = op_readpc(); -L rd.h = op_readpc(); - call(op); -} - -void CPUcore::op_read_bit_const_b() { -L rd.l = op_readpc(); - regs.p.z = ((rd.l & regs.a.l) == 0); -} - -void CPUcore::op_read_bit_const_w() { - rd.l = op_readpc(); -L rd.h = op_readpc(); - regs.p.z = ((rd.w & regs.a.w) == 0); -} - -template void CPUcore::op_read_addr_b() { - aa.l = op_readpc(); - aa.h = op_readpc(); -L rd.l = op_readdbr(aa.w); - call(op); -} - -template void CPUcore::op_read_addr_w() { - aa.l = op_readpc(); - aa.h = op_readpc(); - rd.l = op_readdbr(aa.w + 0); -L rd.h = op_readdbr(aa.w + 1); - call(op); -} - -template void CPUcore::op_read_addrx_b() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io_cond4(aa.w, aa.w + regs.x.w); -L rd.l = op_readdbr(aa.w + regs.x.w); - call(op); -} - -template void CPUcore::op_read_addrx_w() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io_cond4(aa.w, aa.w + regs.x.w); - rd.l = op_readdbr(aa.w + regs.x.w + 0); -L rd.h = op_readdbr(aa.w + regs.x.w + 1); - call(op); -} - -template void CPUcore::op_read_addry_b() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io_cond4(aa.w, aa.w + regs.y.w); -L rd.l = op_readdbr(aa.w + regs.y.w); - call(op); -} - -template void CPUcore::op_read_addry_w() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io_cond4(aa.w, aa.w + regs.y.w); - rd.l = op_readdbr(aa.w + regs.y.w + 0); -L rd.h = op_readdbr(aa.w + regs.y.w + 1); - call(op); -} - -template void CPUcore::op_read_long_b() { - aa.l = op_readpc(); - aa.h = op_readpc(); - aa.b = op_readpc(); -L rd.l = op_readlong(aa.d); - call(op); -} - -template void CPUcore::op_read_long_w() { - aa.l = op_readpc(); - aa.h = op_readpc(); - aa.b = op_readpc(); - rd.l = op_readlong(aa.d + 0); -L rd.h = op_readlong(aa.d + 1); - call(op); -} - -template void CPUcore::op_read_longx_b() { - aa.l = op_readpc(); - aa.h = op_readpc(); - aa.b = op_readpc(); -L rd.l = op_readlong(aa.d + regs.x.w); - call(op); -} - -template void CPUcore::op_read_longx_w() { - aa.l = op_readpc(); - aa.h = op_readpc(); - aa.b = op_readpc(); - rd.l = op_readlong(aa.d + regs.x.w + 0); -L rd.h = op_readlong(aa.d + regs.x.w + 1); - call(op); -} - -template void CPUcore::op_read_dp_b() { - dp = op_readpc(); - op_io_cond2(); -L rd.l = op_readdp(dp); - call(op); -} - -template void CPUcore::op_read_dp_w() { - dp = op_readpc(); - op_io_cond2(); - rd.l = op_readdp(dp + 0); -L rd.h = op_readdp(dp + 1); - call(op); -} - -template void CPUcore::op_read_dpr_b() { - dp = op_readpc(); - op_io_cond2(); - op_io(); -L rd.l = op_readdp(dp + regs.r[n].w); - call(op); -} - -template void CPUcore::op_read_dpr_w() { - dp = op_readpc(); - op_io_cond2(); - op_io(); - rd.l = op_readdp(dp + regs.r[n].w + 0); -L rd.h = op_readdp(dp + regs.r[n].w + 1); - call(op); -} - -template void CPUcore::op_read_idp_b() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); -L rd.l = op_readdbr(aa.w); - call(op); -} - -template void CPUcore::op_read_idp_w() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - rd.l = op_readdbr(aa.w + 0); -L rd.h = op_readdbr(aa.w + 1); - call(op); -} - -template void CPUcore::op_read_idpx_b() { - dp = op_readpc(); - op_io_cond2(); - op_io(); - aa.l = op_readdp(dp + regs.x.w + 0); - aa.h = op_readdp(dp + regs.x.w + 1); -L rd.l = op_readdbr(aa.w); - call(op); -} - -template void CPUcore::op_read_idpx_w() { - dp = op_readpc(); - op_io_cond2(); - op_io(); - aa.l = op_readdp(dp + regs.x.w + 0); - aa.h = op_readdp(dp + regs.x.w + 1); - rd.l = op_readdbr(aa.w + 0); -L rd.h = op_readdbr(aa.w + 1); - call(op); -} - -template void CPUcore::op_read_idpy_b() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - op_io_cond4(aa.w, aa.w + regs.y.w); -L rd.l = op_readdbr(aa.w + regs.y.w); - call(op); -} - -template void CPUcore::op_read_idpy_w() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - op_io_cond4(aa.w, aa.w + regs.y.w); - rd.l = op_readdbr(aa.w + regs.y.w + 0); -L rd.h = op_readdbr(aa.w + regs.y.w + 1); - call(op); -} - -template void CPUcore::op_read_ildp_b() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - aa.b = op_readdp(dp + 2); -L rd.l = op_readlong(aa.d); - call(op); -} - -template void CPUcore::op_read_ildp_w() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - aa.b = op_readdp(dp + 2); - rd.l = op_readlong(aa.d + 0); -L rd.h = op_readlong(aa.d + 1); - call(op); -} - -template void CPUcore::op_read_ildpy_b() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - aa.b = op_readdp(dp + 2); -L rd.l = op_readlong(aa.d + regs.y.w); - call(op); -} - -template void CPUcore::op_read_ildpy_w() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - aa.b = op_readdp(dp + 2); - rd.l = op_readlong(aa.d + regs.y.w + 0); -L rd.h = op_readlong(aa.d + regs.y.w + 1); - call(op); -} - -template void CPUcore::op_read_sr_b() { - sp = op_readpc(); - op_io(); -L rd.l = op_readsp(sp); - call(op); -} - -template void CPUcore::op_read_sr_w() { - sp = op_readpc(); - op_io(); - rd.l = op_readsp(sp + 0); -L rd.h = op_readsp(sp + 1); - call(op); -} - -template void CPUcore::op_read_isry_b() { - sp = op_readpc(); - op_io(); - aa.l = op_readsp(sp + 0); - aa.h = op_readsp(sp + 1); - op_io(); -L rd.l = op_readdbr(aa.w + regs.y.w); - call(op); -} - -template void CPUcore::op_read_isry_w() { - sp = op_readpc(); - op_io(); - aa.l = op_readsp(sp + 0); - aa.h = op_readsp(sp + 1); - op_io(); - rd.l = op_readdbr(aa.w + regs.y.w + 0); -L rd.h = op_readdbr(aa.w + regs.y.w + 1); - call(op); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/cpu/core/opcode_rmw.cpp b/waterbox/libsnes/bsnes/snes/cpu/core/opcode_rmw.cpp deleted file mode 100644 index fed939e1c3..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/core/opcode_rmw.cpp +++ /dev/null @@ -1,169 +0,0 @@ -#ifdef CPUCORE_CPP - -template void CPUcore::op_adjust_imm_b() { -L op_io_irq(); - regs.r[n].l += adjust; - regs.p.n = (regs.r[n].l & 0x80); - regs.p.z = (regs.r[n].l == 0); -} - -template void CPUcore::op_adjust_imm_w() { -L op_io_irq(); - regs.r[n].w += adjust; - regs.p.n = (regs.r[n].w & 0x8000); - regs.p.z = (regs.r[n].w == 0); -} - -void CPUcore::op_asl_imm_b() { -L op_io_irq(); - regs.p.c = (regs.a.l & 0x80); - regs.a.l <<= 1; - regs.p.n = (regs.a.l & 0x80); - regs.p.z = (regs.a.l == 0); -} - -void CPUcore::op_asl_imm_w() { -L op_io_irq(); - regs.p.c = (regs.a.w & 0x8000); - regs.a.w <<= 1; - regs.p.n = (regs.a.w & 0x8000); - regs.p.z = (regs.a.w == 0); -} - -void CPUcore::op_lsr_imm_b() { -L op_io_irq(); - regs.p.c = (regs.a.l & 0x01); - regs.a.l >>= 1; - regs.p.n = (regs.a.l & 0x80); - regs.p.z = (regs.a.l == 0); -} - -void CPUcore::op_lsr_imm_w() { -L op_io_irq(); - regs.p.c = (regs.a.w & 0x0001); - regs.a.w >>= 1; - regs.p.n = (regs.a.w & 0x8000); - regs.p.z = (regs.a.w == 0); -} - -void CPUcore::op_rol_imm_b() { -L op_io_irq(); - bool carry = regs.p.c; - regs.p.c = (regs.a.l & 0x80); - regs.a.l = (regs.a.l << 1) | carry; - regs.p.n = (regs.a.l & 0x80); - regs.p.z = (regs.a.l == 0); -} - -void CPUcore::op_rol_imm_w() { -L op_io_irq(); - bool carry = regs.p.c; - regs.p.c = (regs.a.w & 0x8000); - regs.a.w = (regs.a.w << 1) | carry; - regs.p.n = (regs.a.w & 0x8000); - regs.p.z = (regs.a.w == 0); -} - -void CPUcore::op_ror_imm_b() { -L op_io_irq(); - bool carry = regs.p.c; - regs.p.c = (regs.a.l & 0x01); - regs.a.l = (carry << 7) | (regs.a.l >> 1); - regs.p.n = (regs.a.l & 0x80); - regs.p.z = (regs.a.l == 0); -} - -void CPUcore::op_ror_imm_w() { -L op_io_irq(); - bool carry = regs.p.c; - regs.p.c = (regs.a.w & 0x0001); - regs.a.w = (carry << 15) | (regs.a.w >> 1); - regs.p.n = (regs.a.w & 0x8000); - regs.p.z = (regs.a.w == 0); -} - -template void CPUcore::op_adjust_addr_b() { - aa.l = op_readpc(); - aa.h = op_readpc(); - rd.l = op_readdbr(aa.w); - op_io(); - call(op); -L op_writedbr(aa.w, rd.l); -} - -template void CPUcore::op_adjust_addr_w() { - aa.l = op_readpc(); - aa.h = op_readpc(); - rd.l = op_readdbr(aa.w + 0); - rd.h = op_readdbr(aa.w + 1); - op_io(); - call(op); - op_writedbr(aa.w + 1, rd.h); -L op_writedbr(aa.w + 0, rd.l); -} - -template void CPUcore::op_adjust_addrx_b() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io(); - rd.l = op_readdbr(aa.w + regs.x.w); - op_io(); - call(op); -L op_writedbr(aa.w + regs.x.w, rd.l); -} - -template void CPUcore::op_adjust_addrx_w() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io(); - rd.l = op_readdbr(aa.w + regs.x.w + 0); - rd.h = op_readdbr(aa.w + regs.x.w + 1); - op_io(); - call(op); - op_writedbr(aa.w + regs.x.w + 1, rd.h); -L op_writedbr(aa.w + regs.x.w + 0, rd.l); -} - -template void CPUcore::op_adjust_dp_b() { - dp = op_readpc(); - op_io_cond2(); - rd.l = op_readdp(dp); - op_io(); - call(op); -L op_writedp(dp, rd.l); -} - -template void CPUcore::op_adjust_dp_w() { - dp = op_readpc(); - op_io_cond2(); - rd.l = op_readdp(dp + 0); - rd.h = op_readdp(dp + 1); - op_io(); - call(op); - op_writedp(dp + 1, rd.h); -L op_writedp(dp + 0, rd.l); -} - -template void CPUcore::op_adjust_dpx_b() { - dp = op_readpc(); - op_io_cond2(); - op_io(); - rd.l = op_readdp(dp + regs.x.w); - op_io(); - call(op); -L op_writedp(dp + regs.x.w, rd.l); -} - -template void CPUcore::op_adjust_dpx_w() { - dp = op_readpc(); - op_io_cond2(); - op_io(); - rd.l = op_readdp(dp + regs.x.w + 0); - rd.h = op_readdp(dp + regs.x.w + 1); - op_io(); - call(op); - op_writedp(dp + regs.x.w + 1, rd.h); -L op_writedp(dp + regs.x.w + 0, rd.l); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/cpu/core/opcode_write.cpp b/waterbox/libsnes/bsnes/snes/cpu/core/opcode_write.cpp deleted file mode 100644 index de85e672d3..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/core/opcode_write.cpp +++ /dev/null @@ -1,199 +0,0 @@ -#ifdef CPUCORE_CPP - -template void CPUcore::op_write_addr_b() { - aa.l = op_readpc(); - aa.h = op_readpc(); -L op_writedbr(aa.w, regs.r[n]); -} - -template void CPUcore::op_write_addr_w() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_writedbr(aa.w + 0, regs.r[n] >> 0); -L op_writedbr(aa.w + 1, regs.r[n] >> 8); -} - -template void CPUcore::op_write_addrr_b() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io(); -L op_writedbr(aa.w + regs.r[i], regs.r[n]); -} - -template void CPUcore::op_write_addrr_w() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io(); - op_writedbr(aa.w + regs.r[i] + 0, regs.r[n] >> 0); -L op_writedbr(aa.w + regs.r[i] + 1, regs.r[n] >> 8); -} - -template void CPUcore::op_write_longr_b() { - aa.l = op_readpc(); - aa.h = op_readpc(); - aa.b = op_readpc(); -L op_writelong(aa.d + regs.r[i], regs.a.l); -} - -template void CPUcore::op_write_longr_w() { - aa.l = op_readpc(); - aa.h = op_readpc(); - aa.b = op_readpc(); - op_writelong(aa.d + regs.r[i] + 0, regs.a.l); -L op_writelong(aa.d + regs.r[i] + 1, regs.a.h); -} - -template void CPUcore::op_write_dp_b() { - dp = op_readpc(); - op_io_cond2(); -L op_writedp(dp, regs.r[n]); -} - -template void CPUcore::op_write_dp_w() { - dp = op_readpc(); - op_io_cond2(); - op_writedp(dp + 0, regs.r[n] >> 0); -L op_writedp(dp + 1, regs.r[n] >> 8); -} - -template void CPUcore::op_write_dpr_b() { - dp = op_readpc(); - op_io_cond2(); - op_io(); -L op_writedp(dp + regs.r[i], regs.r[n]); -} - -template void CPUcore::op_write_dpr_w() { - dp = op_readpc(); - op_io_cond2(); - op_io(); - op_writedp(dp + regs.r[i] + 0, regs.r[n] >> 0); -L op_writedp(dp + regs.r[i] + 1, regs.r[n] >> 8); -} - -void CPUcore::op_sta_idp_b() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); -L op_writedbr(aa.w, regs.a.l); -} - -void CPUcore::op_sta_idp_w() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - op_writedbr(aa.w + 0, regs.a.l); -L op_writedbr(aa.w + 1, regs.a.h); -} - -void CPUcore::op_sta_ildp_b() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - aa.b = op_readdp(dp + 2); -L op_writelong(aa.d, regs.a.l); -} - -void CPUcore::op_sta_ildp_w() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - aa.b = op_readdp(dp + 2); - op_writelong(aa.d + 0, regs.a.l); -L op_writelong(aa.d + 1, regs.a.h); -} - -void CPUcore::op_sta_idpx_b() { - dp = op_readpc(); - op_io_cond2(); - op_io(); - aa.l = op_readdp(dp + regs.x.w + 0); - aa.h = op_readdp(dp + regs.x.w + 1); -L op_writedbr(aa.w, regs.a.l); -} - -void CPUcore::op_sta_idpx_w() { - dp = op_readpc(); - op_io_cond2(); - op_io(); - aa.l = op_readdp(dp + regs.x.w + 0); - aa.h = op_readdp(dp + regs.x.w + 1); - op_writedbr(aa.w + 0, regs.a.l); -L op_writedbr(aa.w + 1, regs.a.h); -} - -void CPUcore::op_sta_idpy_b() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - op_io(); -L op_writedbr(aa.w + regs.y.w, regs.a.l); -} - -void CPUcore::op_sta_idpy_w() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - op_io(); - op_writedbr(aa.w + regs.y.w + 0, regs.a.l); -L op_writedbr(aa.w + regs.y.w + 1, regs.a.h); -} - -void CPUcore::op_sta_ildpy_b() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - aa.b = op_readdp(dp + 2); -L op_writelong(aa.d + regs.y.w, regs.a.l); -} - -void CPUcore::op_sta_ildpy_w() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - aa.b = op_readdp(dp + 2); - op_writelong(aa.d + regs.y.w + 0, regs.a.l); -L op_writelong(aa.d + regs.y.w + 1, regs.a.h); -} - -void CPUcore::op_sta_sr_b() { - sp = op_readpc(); - op_io(); -L op_writesp(sp, regs.a.l); -} - -void CPUcore::op_sta_sr_w() { - sp = op_readpc(); - op_io(); - op_writesp(sp + 0, regs.a.l); -L op_writesp(sp + 1, regs.a.h); -} - -void CPUcore::op_sta_isry_b() { - sp = op_readpc(); - op_io(); - aa.l = op_readsp(sp + 0); - aa.h = op_readsp(sp + 1); - op_io(); -L op_writedbr(aa.w + regs.y.w, regs.a.l); -} - -void CPUcore::op_sta_isry_w() { - sp = op_readpc(); - op_io(); - aa.l = op_readsp(sp + 0); - aa.h = op_readsp(sp + 1); - op_io(); - op_writedbr(aa.w + regs.y.w + 0, regs.a.l); -L op_writedbr(aa.w + regs.y.w + 1, regs.a.h); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/cpu/core/registers.hpp b/waterbox/libsnes/bsnes/snes/cpu/core/registers.hpp deleted file mode 100644 index f219e00fd0..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/core/registers.hpp +++ /dev/null @@ -1,83 +0,0 @@ -struct flag_t { - bool n, v, m, x, d, i, z, c; - - inline operator unsigned() const { - return (n << 7) + (v << 6) + (m << 5) + (x << 4) - + (d << 3) + (i << 2) + (z << 1) + (c << 0); - } - - inline unsigned operator=(uint8 data) { - n = data & 0x80; v = data & 0x40; m = data & 0x20; x = data & 0x10; - d = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01; - return data; - } - - inline unsigned operator|=(unsigned data) { return this->operator=(operator unsigned() | data); } - inline unsigned operator^=(unsigned data) { return this->operator=(operator unsigned() ^ data); } - inline unsigned operator&=(unsigned data) { return this->operator=(operator unsigned() & data); } - - flag_t() : n(0), v(0), m(0), x(0), d(0), i(0), z(0), c(0) {} -}; - -struct reg16_t { - union { - uint16 w; - struct { uint8 order_lsb2(l, h); }; - }; - - inline operator unsigned() const { return w; } - inline unsigned operator = (unsigned i) { return w = i; } - inline unsigned operator |= (unsigned i) { return w |= i; } - inline unsigned operator ^= (unsigned i) { return w ^= i; } - inline unsigned operator &= (unsigned i) { return w &= i; } - inline unsigned operator <<= (unsigned i) { return w <<= i; } - inline unsigned operator >>= (unsigned i) { return w >>= i; } - inline unsigned operator += (unsigned i) { return w += i; } - inline unsigned operator -= (unsigned i) { return w -= i; } - inline unsigned operator *= (unsigned i) { return w *= i; } - inline unsigned operator /= (unsigned i) { return w /= i; } - inline unsigned operator %= (unsigned i) { return w %= i; } - - reg16_t() : w(0) {} -}; - -struct reg24_t { - union { - uint32 d; - struct { uint16 order_lsb2(w, wh); }; - struct { uint8 order_lsb4(l, h, b, bh); }; - }; - - inline operator unsigned() const { return d; } - inline unsigned operator = (unsigned i) { return d = uclip<24>(i); } - inline unsigned operator |= (unsigned i) { return d = uclip<24>(d | i); } - inline unsigned operator ^= (unsigned i) { return d = uclip<24>(d ^ i); } - inline unsigned operator &= (unsigned i) { return d = uclip<24>(d & i); } - inline unsigned operator <<= (unsigned i) { return d = uclip<24>(d << i); } - inline unsigned operator >>= (unsigned i) { return d = uclip<24>(d >> i); } - inline unsigned operator += (unsigned i) { return d = uclip<24>(d + i); } - inline unsigned operator -= (unsigned i) { return d = uclip<24>(d - i); } - inline unsigned operator *= (unsigned i) { return d = uclip<24>(d * i); } - inline unsigned operator /= (unsigned i) { return d = uclip<24>(d / i); } - inline unsigned operator %= (unsigned i) { return d = uclip<24>(d % i); } - - reg24_t() : d(0) {} -}; - -struct regs_t { - reg24_t pc; - reg16_t r[6], &a, &x, &y, &z, &s, &d; - flag_t p; - uint8 db; - bool e; - - bool irq; //IRQ pin (0 = low, 1 = trigger) - bool wai; //raised during wai, cleared after interrupt triggered - uint8 mdr; //memory data register - uint16 vector; //interrupt vector address - - regs_t(): - a(r[0]), x(r[1]), y(r[2]), z(r[3]), s(r[4]), d(r[5]), db(0), e(false), irq(false), wai(false), mdr(0), vector(0) { - z = 0; - } -}; diff --git a/waterbox/libsnes/bsnes/snes/cpu/core/table.cpp b/waterbox/libsnes/bsnes/snes/cpu/core/table.cpp deleted file mode 100644 index 6575a4db82..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/core/table.cpp +++ /dev/null @@ -1,312 +0,0 @@ -#ifdef CPUCORE_CPP - -void CPUcore::initialize_opcode_table() { - #define opA( id, name ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name; - #define opAII(id, name, x, y ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name; - #define opE( id, name ) op_table[table_EM + id] = &CPUcore::op_##name##_e; op_table[table_MX + id] = op_table[table_Mx + id] = op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_n; - #define opEI( id, name, x ) op_table[table_EM + id] = &CPUcore::op_##name##_e; op_table[table_MX + id] = op_table[table_Mx + id] = op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_n; - #define opEII(id, name, x, y ) op_table[table_EM + id] = &CPUcore::op_##name##_e; op_table[table_MX + id] = op_table[table_Mx + id] = op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_n; - #define opM( id, name ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = &CPUcore::op_##name##_b; op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w; - #define opMI( id, name, x ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = &CPUcore::op_##name##_b; op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w; - #define opMII(id, name, x, y ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = &CPUcore::op_##name##_b; op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w; - #define opMF( id, name, fn ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = &CPUcore::op_##name##_b<&CPUcore::op_##fn##_b>; op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<&CPUcore::op_##fn##_w>; - #define opMFI(id, name, fn, x) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = &CPUcore::op_##name##_b<&CPUcore::op_##fn##_b, x>; op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<&CPUcore::op_##fn##_w, x>; - #define opX( id, name ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_mX + id] = &CPUcore::op_##name##_b; op_table[table_Mx + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w; - #define opXI( id, name, x ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_mX + id] = &CPUcore::op_##name##_b; op_table[table_Mx + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w; - #define opXII(id, name, x, y ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_mX + id] = &CPUcore::op_##name##_b; op_table[table_Mx + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w; - #define opXF( id, name, fn ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_mX + id] = &CPUcore::op_##name##_b<&CPUcore::op_##fn##_b>; op_table[table_Mx + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<&CPUcore::op_##fn##_w>; - #define opXFI(id, name, fn, x) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_mX + id] = &CPUcore::op_##name##_b<&CPUcore::op_##fn##_b, x>; op_table[table_Mx + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<&CPUcore::op_##fn##_w, x>; - - opEII(0x00, interrupt, 0xfffe, 0xffe6) - opMF (0x01, read_idpx, ora) - opEII(0x02, interrupt, 0xfff4, 0xffe4) - opMF (0x03, read_sr, ora) - opMF (0x04, adjust_dp, tsb) - opMF (0x05, read_dp, ora) - opMF (0x06, adjust_dp, asl) - opMF (0x07, read_ildp, ora) - opA (0x08, php) - opMF (0x09, read_const, ora) - opM (0x0a, asl_imm) - opE (0x0b, phd) - opMF (0x0c, adjust_addr, tsb) - opMF (0x0d, read_addr, ora) - opMF (0x0e, adjust_addr, asl) - opMF (0x0f, read_long, ora) - opAII(0x10, branch, 0x80, false) - opMF (0x11, read_idpy, ora) - opMF (0x12, read_idp, ora) - opMF (0x13, read_isry, ora) - opMF (0x14, adjust_dp, trb) - opMFI(0x15, read_dpr, ora, X) - opMF (0x16, adjust_dpx, asl) - opMF (0x17, read_ildpy, ora) - opAII(0x18, flag, 0x01, 0x00) - opMF (0x19, read_addry, ora) - opMII(0x1a, adjust_imm, A, +1) - opE (0x1b, tcs) - opMF (0x1c, adjust_addr, trb) - opMF (0x1d, read_addrx, ora) - opMF (0x1e, adjust_addrx, asl) - opMF (0x1f, read_longx, ora) - opA (0x20, jsr_addr) - opMF (0x21, read_idpx, and) - opE (0x22, jsr_long) - opMF (0x23, read_sr, and) - opMF (0x24, read_dp, bit) - opMF (0x25, read_dp, and) - opMF (0x26, adjust_dp, rol) - opMF (0x27, read_ildp, and) - opE (0x28, plp) - opMF (0x29, read_const, and) - opM (0x2a, rol_imm) - opE (0x2b, pld) - opMF (0x2c, read_addr, bit) - opMF (0x2d, read_addr, and) - opMF (0x2e, adjust_addr, rol) - opMF (0x2f, read_long, and) - opAII(0x30, branch, 0x80, true) - opMF (0x31, read_idpy, and) - opMF (0x32, read_idp, and) - opMF (0x33, read_isry, and) - opMFI(0x34, read_dpr, bit, X) - opMFI(0x35, read_dpr, and, X) - opMF (0x36, adjust_dpx, rol) - opMF (0x37, read_ildpy, and) - opAII(0x38, flag, 0x01, 0x01) - opMF (0x39, read_addry, and) - opMII(0x3a, adjust_imm, A, -1) - opAII(0x3b, transfer_w, S, A) - opMF (0x3c, read_addrx, bit) - opMF (0x3d, read_addrx, and) - opMF (0x3e, adjust_addrx, rol) - opMF (0x3f, read_longx, and) - opE (0x40, rti) - opMF (0x41, read_idpx, eor) - opA (0x42, wdm) - opMF (0x43, read_sr, eor) - opXI (0x44, move, -1) - opMF (0x45, read_dp, eor) - opMF (0x46, adjust_dp, lsr) - opMF (0x47, read_ildp, eor) - opMI (0x48, push, A) - opMF (0x49, read_const, eor) - opM (0x4a, lsr_imm) - opA (0x4b, phk) - opA (0x4c, jmp_addr) - opMF (0x4d, read_addr, eor) - opMF (0x4e, adjust_addr, lsr) - opMF (0x4f, read_long, eor) - opAII(0x50, branch, 0x40, false) - opMF (0x51, read_idpy, eor) - opMF (0x52, read_idp, eor) - opMF (0x53, read_isry, eor) - opXI (0x54, move, +1) - opMFI(0x55, read_dpr, eor, X) - opMF (0x56, adjust_dpx, lsr) - opMF (0x57, read_ildpy, eor) - opAII(0x58, flag, 0x04, 0x00) - opMF (0x59, read_addry, eor) - opXI (0x5a, push, Y) - opAII(0x5b, transfer_w, A, D) - opA (0x5c, jmp_long) - opMF (0x5d, read_addrx, eor) - opMF (0x5e, adjust_addrx, lsr) - opMF (0x5f, read_longx, eor) - opA (0x60, rts) - opMF (0x61, read_idpx, adc) - opE (0x62, per) - opMF (0x63, read_sr, adc) - opMI (0x64, write_dp, Z) - opMF (0x65, read_dp, adc) - opMF (0x66, adjust_dp, ror) - opMF (0x67, read_ildp, adc) - opMI (0x68, pull, A) - opMF (0x69, read_const, adc) - opM (0x6a, ror_imm) - opE (0x6b, rtl) - opA (0x6c, jmp_iaddr) - opMF (0x6d, read_addr, adc) - opMF (0x6e, adjust_addr, ror) - opMF (0x6f, read_long, adc) - opAII(0x70, branch, 0x40, true) - opMF (0x71, read_idpy, adc) - opMF (0x72, read_idp, adc) - opMF (0x73, read_isry, adc) - opMII(0x74, write_dpr, Z, X) - opMFI(0x75, read_dpr, adc, X) - opMF (0x76, adjust_dpx, ror) - opMF (0x77, read_ildpy, adc) - opAII(0x78, flag, 0x04, 0x04) - opMF (0x79, read_addry, adc) - opXI (0x7a, pull, Y) - opAII(0x7b, transfer_w, D, A) - opA (0x7c, jmp_iaddrx) - opMF (0x7d, read_addrx, adc) - opMF (0x7e, adjust_addrx, ror) - opMF (0x7f, read_longx, adc) - opA (0x80, bra) - opM (0x81, sta_idpx) - opA (0x82, brl) - opM (0x83, sta_sr) - opXI (0x84, write_dp, Y) - opMI (0x85, write_dp, A) - opXI (0x86, write_dp, X) - opM (0x87, sta_ildp) - opXII(0x88, adjust_imm, Y, -1) - opM (0x89, read_bit_const) - opMII(0x8a, transfer, X, A) - opA (0x8b, phb) - opXI (0x8c, write_addr, Y) - opMI (0x8d, write_addr, A) - opXI (0x8e, write_addr, X) - opMI (0x8f, write_longr, Z) - opAII(0x90, branch, 0x01, false) - opM (0x91, sta_idpy) - opM (0x92, sta_idp) - opM (0x93, sta_isry) - opXII(0x94, write_dpr, Y, X) - opMII(0x95, write_dpr, A, X) - opXII(0x96, write_dpr, X, Y) - opM (0x97, sta_ildpy) - opMII(0x98, transfer, Y, A) - opMII(0x99, write_addrr, A, Y) - opE (0x9a, txs) - opXII(0x9b, transfer, X, Y) - opMI (0x9c, write_addr, Z) - opMII(0x9d, write_addrr, A, X) - opMII(0x9e, write_addrr, Z, X) - opMI (0x9f, write_longr, X) - opXF (0xa0, read_const, ldy) - opMF (0xa1, read_idpx, lda) - opXF (0xa2, read_const, ldx) - opMF (0xa3, read_sr, lda) - opXF (0xa4, read_dp, ldy) - opMF (0xa5, read_dp, lda) - opXF (0xa6, read_dp, ldx) - opMF (0xa7, read_ildp, lda) - opXII(0xa8, transfer, A, Y) - opMF (0xa9, read_const, lda) - opXII(0xaa, transfer, A, X) - opA (0xab, plb) - opXF (0xac, read_addr, ldy) - opMF (0xad, read_addr, lda) - opXF (0xae, read_addr, ldx) - opMF (0xaf, read_long, lda) - opAII(0xb0, branch, 0x01, true) - opMF (0xb1, read_idpy, lda) - opMF (0xb2, read_idp, lda) - opMF (0xb3, read_isry, lda) - opXFI(0xb4, read_dpr, ldy, X) - opMFI(0xb5, read_dpr, lda, X) - opXFI(0xb6, read_dpr, ldx, Y) - opMF (0xb7, read_ildpy, lda) - opAII(0xb8, flag, 0x40, 0x00) - opMF (0xb9, read_addry, lda) - opX (0xba, tsx) - opXII(0xbb, transfer, Y, X) - opXF (0xbc, read_addrx, ldy) - opMF (0xbd, read_addrx, lda) - opXF (0xbe, read_addry, ldx) - opMF (0xbf, read_longx, lda) - opXF (0xc0, read_const, cpy) - opMF (0xc1, read_idpx, cmp) - opEI (0xc2, pflag, 0) - opMF (0xc3, read_sr, cmp) - opXF (0xc4, read_dp, cpy) - opMF (0xc5, read_dp, cmp) - opMF (0xc6, adjust_dp, dec) - opMF (0xc7, read_ildp, cmp) - opXII(0xc8, adjust_imm, Y, +1) - opMF (0xc9, read_const, cmp) - opXII(0xca, adjust_imm, X, -1) - opA (0xcb, wai) - opXF (0xcc, read_addr, cpy) - opMF (0xcd, read_addr, cmp) - opMF (0xce, adjust_addr, dec) - opMF (0xcf, read_long, cmp) - opAII(0xd0, branch, 0x02, false) - opMF (0xd1, read_idpy, cmp) - opMF (0xd2, read_idp, cmp) - opMF (0xd3, read_isry, cmp) - opE (0xd4, pei) - opMFI(0xd5, read_dpr, cmp, X) - opMF (0xd6, adjust_dpx, dec) - opMF (0xd7, read_ildpy, cmp) - opAII(0xd8, flag, 0x08, 0x00) - opMF (0xd9, read_addry, cmp) - opXI (0xda, push, X) - opA (0xdb, stp) - opA (0xdc, jmp_iladdr) - opMF (0xdd, read_addrx, cmp) - opMF (0xde, adjust_addrx, dec) - opMF (0xdf, read_longx, cmp) - opXF (0xe0, read_const, cpx) - opMF (0xe1, read_idpx, sbc) - opEI (0xe2, pflag, 1) - opMF (0xe3, read_sr, sbc) - opXF (0xe4, read_dp, cpx) - opMF (0xe5, read_dp, sbc) - opMF (0xe6, adjust_dp, inc) - opMF (0xe7, read_ildp, sbc) - opXII(0xe8, adjust_imm, X, +1) - opMF (0xe9, read_const, sbc) - opA (0xea, nop) - opA (0xeb, xba) - opXF (0xec, read_addr, cpx) - opMF (0xed, read_addr, sbc) - opMF (0xee, adjust_addr, inc) - opMF (0xef, read_long, sbc) - opAII(0xf0, branch, 0x02, true) - opMF (0xf1, read_idpy, sbc) - opMF (0xf2, read_idp, sbc) - opMF (0xf3, read_isry, sbc) - opE (0xf4, pea) - opMFI(0xf5, read_dpr, sbc, X) - opMF (0xf6, adjust_dpx, inc) - opMF (0xf7, read_ildpy, sbc) - opAII(0xf8, flag, 0x08, 0x08) - opMF (0xf9, read_addry, sbc) - opXI (0xfa, pull, X) - opA (0xfb, xce) - opE (0xfc, jsr_iaddrx) - opMF (0xfd, read_addrx, sbc) - opMF (0xfe, adjust_addrx, inc) - opMF (0xff, read_longx, sbc) - - #undef opA - #undef opAII - #undef opE - #undef opEI - #undef opEII - #undef opM - #undef opMI - #undef opMII - #undef opMF - #undef opMFI - #undef opX - #undef opXI - #undef opXII - #undef opXF - #undef opXFI -} - -void CPUcore::update_table() { - if(regs.e) { - opcode_table = &op_table[table_EM]; - } else if(regs.p.m) { - if(regs.p.x) { - opcode_table = &op_table[table_MX]; - } else { - opcode_table = &op_table[table_Mx]; - } - } else { - if(regs.p.x) { - opcode_table = &op_table[table_mX]; - } else { - opcode_table = &op_table[table_mx]; - } - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/cpu/cpu.cpp b/waterbox/libsnes/bsnes/snes/cpu/cpu.cpp deleted file mode 100644 index 654a2d0969..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/cpu.cpp +++ /dev/null @@ -1,179 +0,0 @@ -#include - -#define CPU_CPP -namespace SNES { - -CPU cpu; - -#include "dma/dma.cpp" -#include "memory/memory.cpp" -#include "mmio/mmio.cpp" -#include "timing/timing.cpp" - -void CPU::step(unsigned clocks) { - smp.clock -= clocks * (uint64)smp.frequency; - ppu.clock -= clocks; - for(unsigned i = 0; i < coprocessors.size(); i++) { - Processor &chip = *coprocessors[i]; - chip.clock -= clocks * (uint64)chip.frequency; - } - input.port1->clock -= clocks * (uint64)input.port1->frequency; - input.port2->clock -= clocks * (uint64)input.port2->frequency; - synchronize_controllers(); -} - -void CPU::synchronize_smp() { - if(SMP::Threaded == true) { - if(smp.clock < 0) co_switch(smp.thread); - } else { - while(smp.clock < 0) smp.enter(); - } -} - -void CPU::synchronize_ppu() { - if(PPU::Threaded == true) { - if(ppu.clock < 0) co_switch(ppu.thread); - } else { - while(ppu.clock < 0) ppu.enter(); - } -} - -void CPU::synchronize_coprocessors() { - for(unsigned i = 0; i < coprocessors.size(); i++) { - Processor &chip = *coprocessors[i]; - if(chip.clock < 0) co_switch(chip.thread); - } -} - -void CPU::synchronize_controllers() { - if(input.port1->clock < 0) co_switch(input.port1->thread); - if(input.port2->clock < 0) co_switch(input.port2->thread); -} - -void CPU::Enter() { cpu.enter(); } - -void CPU::enter() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::CPU) { - scheduler.sync = Scheduler::SynchronizeMode::All; - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - if(status.interrupt_pending) { - status.interrupt_pending = false; - if(status.nmi_pending) { - status.nmi_pending = false; - regs.vector = (regs.e == false ? 0xffea : 0xfffa); - op_irq(); - debugger.op_nmi(); - } else if(status.irq_pending) { - status.irq_pending = false; - regs.vector = (regs.e == false ? 0xffee : 0xfffe); - op_irq(); - debugger.op_irq(); - } else if(status.reset_pending) { - status.reset_pending = false; - add_clocks(186); - regs.pc.l = bus.read(0xfffc); - regs.pc.h = bus.read(0xfffd); - } - } - - op_step(); - } -} - -void CPU::op_step() { - debugger.op_exec(regs.pc.d); - - if (interface()->wanttrace & TRACE_CPU_MASK) - { - char tmp[512]; - disassemble_opcode(tmp, regs.pc.d); - tmp[511] = 0; - interface()->cpuTrace(TRACE_CPU, tmp); - } - - (this->*opcode_table[op_readpcfirst()])(); -} - -void CPU::enable() { - function read = { &CPU::mmio_read, (CPU*)&cpu }; - function write = { &CPU::mmio_write, (CPU*)&cpu }; - - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, read, write); - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, read, write); - - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, read, write); - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, read, write); - - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, read, write); - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, read, write); - - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, read, write); - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, read, write); - - read = [](unsigned addr) { cdlInfo.set(eCDLog_AddrType_WRAM, addr); return cpu.wram[addr]; }; - write = [](unsigned addr, uint8 data) { cpu.wram[addr] = data; }; - - bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, read, write, 0x000000, 0x002000); - bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, read, write, 0x000000, 0x002000); - bus.map(Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff, read, write); -} - -void CPU::power() { - cpu_version = config.cpu.version; - for(int i=0;i<128*1024;i++) wram[i] = random(config.cpu.wram_init_value); - - regs.a = regs.x = regs.y = 0x0000; - regs.s = 0x01ff; - - mmio_power(); - dma_power(); - timing_power(); - - //zero 01-dec-2012 - //gotta clear these to something, sometime - rd.d = sp = dp = 0; -} - -void CPU::reset() { - create(Enter, system.cpu_frequency(), 16384); - coprocessors.reset(); - PPUcounter::reset(); - - //note: some registers are not fully reset by SNES - regs.pc = 0x000000; - regs.x.h = 0x00; - regs.y.h = 0x00; - regs.s.h = 0x01; - regs.d = 0x0000; - regs.db = 0x00; - regs.p = 0x34; - regs.e = 1; - regs.mdr = 0x00; - regs.wai = false; - regs.vector = 0xfffc; //reset vector address - update_table(); - - mmio_reset(); - dma_reset(); - timing_reset(); -} - -CPU::CPU() - : wram(nullptr) -{ - PPUcounter::scanline = { &CPU::scanline, this }; -} - -CPU::~CPU() { - interface()->freeSharedMemory(wram); -} - -void CPU::initialize() -{ - wram = (uint8*)interface()->allocSharedMemory("WRAM",128 * 1024); -} - -} diff --git a/waterbox/libsnes/bsnes/snes/cpu/cpu.hpp b/waterbox/libsnes/bsnes/snes/cpu/cpu.hpp deleted file mode 100644 index bf0ecd2fdb..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/cpu.hpp +++ /dev/null @@ -1,150 +0,0 @@ -struct CPU : public Processor, public CPUcore, public PPUcounter { - uint8 *wram; //[128 * 1024]; - - function read_wram; - function write_wram; - - enum : bool { Threaded = true }; - array coprocessors; - alwaysinline void step(unsigned clocks); - alwaysinline void synchronize_smp(); - void synchronize_ppu(); - void synchronize_coprocessors(); - void synchronize_controllers(); - - uint8 port_read(uint2 port) const; - void port_write(uint2 port, uint8 data); - - uint8 pio(); - bool joylatch(); - alwaysinline bool interrupt_pending() { return status.interrupt_pending; } - - void enter(); - void enable(); - void power(); - void reset(); - - CPU(); - ~CPU(); - void initialize(); - -privileged: - #include "dma/dma.hpp" - #include "memory/memory.hpp" - #include "mmio/mmio.hpp" - #include "timing/timing.hpp" - - uint8 cpu_version; - - struct Status { - bool interrupt_pending; - - unsigned clock_count; - unsigned line_clocks; - - //timing - bool irq_lock; - - unsigned dram_refresh_position; - bool dram_refreshed; - - unsigned hdma_init_position; - bool hdma_init_triggered; - - unsigned hdma_position; - bool hdma_triggered; - - bool nmi_valid; - bool nmi_line; - bool nmi_transition; - bool nmi_pending; - bool nmi_hold; - - bool irq_valid; - bool irq_line; - bool irq_transition; - bool irq_pending; - bool irq_hold; - - bool reset_pending; - - //DMA - bool dma_active; - unsigned dma_counter; - unsigned dma_clocks; - bool dma_pending; - bool hdma_pending; - bool hdma_mode; //0 = init, 1 = run - - //auto joypad polling - bool auto_joypad_active; - bool auto_joypad_latch; - unsigned auto_joypad_counter; - unsigned auto_joypad_clock; - - //MMIO - //$2140-217f - uint8 port[4]; - - //$2181-$2183 - uint17 wram_addr; - - //$4016-$4017 - bool joypad_strobe_latch; - uint32 joypad1_bits; - uint32 joypad2_bits; - - //$4200 - bool nmi_enabled; - bool hirq_enabled, virq_enabled; - bool auto_joypad_poll; - - //$4201 - uint8 pio; - - //$4202-$4203 - uint8 wrmpya; - uint8 wrmpyb; - - //$4204-$4206 - uint16 wrdiva; - uint8 wrdivb; - - //$4207-$420a - uint9 hirq_pos; - uint9 virq_pos; - - //$420d - unsigned rom_speed; - - //$4214-$4217 - uint16 rddiv; - uint16 rdmpy; - - //$4218-$421f - uint16 joy1; - uint16 joy2; - uint16 joy3; - uint16 joy4; - } status; - - struct ALU { - unsigned mpyctr; - unsigned divctr; - unsigned shift; - } alu; - - static void Enter(); - void op_step(); - -public: - struct Debugger { - hook op_exec; - hook op_read; - hook op_write; - hook op_nmi; - hook op_irq; - } debugger; -}; - -extern CPU cpu; diff --git a/waterbox/libsnes/bsnes/snes/cpu/dma/dma.cpp b/waterbox/libsnes/bsnes/snes/cpu/dma/dma.cpp deleted file mode 100644 index 61378e432d..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/dma/dma.cpp +++ /dev/null @@ -1,290 +0,0 @@ -#ifdef CPU_CPP - -void CPU::dma_add_clocks(unsigned clocks) { - status.dma_clocks += clocks; - add_clocks(clocks); -} - -//============= -//memory access -//============= - -bool CPU::dma_transfer_valid(uint8 bbus, uint32 abus) { - //transfers from WRAM to WRAM are invalid; chip only has one address bus - if(bbus == 0x80 && ((abus & 0xfe0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) return false; - return true; -} - -bool CPU::dma_addr_valid(uint32 abus) { - //A-bus access to B-bus or S-CPU registers are invalid - if((abus & 0x40ff00) == 0x2100) return false; //$[00-3f|80-bf]:[2100-21ff] - if((abus & 0x40fe00) == 0x4000) return false; //$[00-3f|80-bf]:[4000-41ff] - if((abus & 0x40ffe0) == 0x4200) return false; //$[00-3f|80-bf]:[4200-421f] - if((abus & 0x40ff80) == 0x4300) return false; //$[00-3f|80-bf]:[4300-437f] - return true; -} - -uint8 CPU::dma_read(uint32 abus) { - if(dma_addr_valid(abus) == false) return 0x00; - cdlInfo.currFlags = eCDLog_Flags_DMAData; - return bus.read(abus); -} - -//simulate two-stage pipeline for DMA transfers; example: -//cycle 0: read N+0 -//cycle 1: write N+0 & read N+1 (parallel; one on A-bus, one on B-bus) -//cycle 2: write N+1 & read N+2 (parallel) -//cycle 3: write N+2 -void CPU::dma_write(bool valid, unsigned addr, uint8 data) { - if(pipe.valid) bus.write(pipe.addr, pipe.data); - pipe.valid = valid; - pipe.addr = addr; - pipe.data = data; -} - -void CPU::dma_transfer(bool direction, uint8 bbus, uint32 abus) { - if(direction == 0) { - dma_add_clocks(4); - regs.mdr = dma_read(abus); - dma_add_clocks(4); - dma_write(dma_transfer_valid(bbus, abus), 0x2100 | bbus, regs.mdr); - } else { - dma_add_clocks(4); - regs.mdr = dma_transfer_valid(bbus, abus) ? bus.read(0x2100 | bbus) : 0x00; - dma_add_clocks(4); - dma_write(dma_addr_valid(abus), abus, regs.mdr); - } -} - -//=================== -//address calculation -//=================== - -uint8 CPU::dma_bbus(unsigned i, unsigned index) { - switch(channel[i].transfer_mode) { default: - case 0: return (channel[i].dest_addr); //0 - case 1: return (channel[i].dest_addr + (index & 1)); //0,1 - case 2: return (channel[i].dest_addr); //0,0 - case 3: return (channel[i].dest_addr + ((index >> 1) & 1)); //0,0,1,1 - case 4: return (channel[i].dest_addr + (index & 3)); //0,1,2,3 - case 5: return (channel[i].dest_addr + (index & 1)); //0,1,0,1 - case 6: return (channel[i].dest_addr); //0,0 [2] - case 7: return (channel[i].dest_addr + ((index >> 1) & 1)); //0,0,1,1 [3] - } -} - -inline uint32 CPU::dma_addr(unsigned i) { - uint32 r = (channel[i].source_bank << 16) | (channel[i].source_addr); - - if(channel[i].fixed_transfer == false) { - if(channel[i].reverse_transfer == false) { - channel[i].source_addr++; - } else { - channel[i].source_addr--; - } - } - - return r; -} - -inline uint32 CPU::hdma_addr(unsigned i) { - return (channel[i].source_bank << 16) | (channel[i].hdma_addr++); -} - -inline uint32 CPU::hdma_iaddr(unsigned i) { - return (channel[i].indirect_bank << 16) | (channel[i].indirect_addr++); -} - -//============== -//channel status -//============== - -uint8 CPU::dma_enabled_channels() { - uint8 r = 0; - for(unsigned i = 0; i < 8; i++) { - if(channel[i].dma_enabled) r++; - } - return r; -} - -inline bool CPU::hdma_active(unsigned i) { - return (channel[i].hdma_enabled && !channel[i].hdma_completed); -} - -inline bool CPU::hdma_active_after(unsigned i) { - for(unsigned n = i + 1; n < 8; n++) { - if(hdma_active(n) == true) return true; - } - return false; -} - -inline uint8 CPU::hdma_enabled_channels() { - uint8 r = 0; - for(unsigned i = 0; i < 8; i++) { - if(channel[i].hdma_enabled) r++; - } - return r; -} - -inline uint8 CPU::hdma_active_channels() { - uint8 r = 0; - for(unsigned i = 0; i < 8; i++) { - if(hdma_active(i) == true) r++; - } - return r; -} - -//============== -//core functions -//============== - -void CPU::dma_run() { - dma_add_clocks(8); - dma_write(false); - dma_edge(); - - for(unsigned i = 0; i < 8; i++) { - if(channel[i].dma_enabled == false) continue; - - unsigned index = 0; - do { - dma_transfer(channel[i].direction, dma_bbus(i, index++), dma_addr(i)); - dma_edge(); - } while(channel[i].dma_enabled && --channel[i].transfer_size); - - dma_add_clocks(8); - dma_write(false); - dma_edge(); - - channel[i].dma_enabled = false; - } - - status.irq_lock = true; -} - -void CPU::hdma_update(unsigned i) { - dma_add_clocks(4); - regs.mdr = dma_read((channel[i].source_bank << 16) | channel[i].hdma_addr); - dma_add_clocks(4); - dma_write(false); - - if((channel[i].line_counter & 0x7f) == 0) { - channel[i].line_counter = regs.mdr; - channel[i].hdma_addr++; - - channel[i].hdma_completed = (channel[i].line_counter == 0); - channel[i].hdma_do_transfer = !channel[i].hdma_completed; - - if(channel[i].indirect) { - dma_add_clocks(4); - regs.mdr = dma_read(hdma_addr(i)); - channel[i].indirect_addr = regs.mdr << 8; - dma_add_clocks(4); - dma_write(false); - - if(!channel[i].hdma_completed || hdma_active_after(i)) { - dma_add_clocks(4); - regs.mdr = dma_read(hdma_addr(i)); - channel[i].indirect_addr >>= 8; - channel[i].indirect_addr |= regs.mdr << 8; - dma_add_clocks(4); - dma_write(false); - } - } - } -} - -void CPU::hdma_run() { - dma_add_clocks(8); - dma_write(false); - - for(unsigned i = 0; i < 8; i++) { - if(hdma_active(i) == false) continue; - channel[i].dma_enabled = false; //HDMA run during DMA will stop DMA mid-transfer - - if(channel[i].hdma_do_transfer) { - static const unsigned transfer_length[8] = { 1, 2, 2, 4, 4, 4, 2, 4 }; - unsigned length = transfer_length[channel[i].transfer_mode]; - for(unsigned index = 0; index < length; index++) { - unsigned addr = channel[i].indirect == false ? hdma_addr(i) : hdma_iaddr(i); - dma_transfer(channel[i].direction, dma_bbus(i, index), addr); - } - } - } - - for(unsigned i = 0; i < 8; i++) { - if(hdma_active(i) == false) continue; - - channel[i].line_counter--; - channel[i].hdma_do_transfer = channel[i].line_counter & 0x80; - hdma_update(i); - } - - status.irq_lock = true; -} - -void CPU::hdma_init_reset() { - for(unsigned i = 0; i < 8; i++) { - channel[i].hdma_completed = false; - channel[i].hdma_do_transfer = false; - } -} - -void CPU::hdma_init() { - dma_add_clocks(8); - dma_write(false); - - for(unsigned i = 0; i < 8; i++) { - if(!channel[i].hdma_enabled) continue; - channel[i].dma_enabled = false; //HDMA init during DMA will stop DMA mid-transfer - - channel[i].hdma_addr = channel[i].source_addr; - channel[i].line_counter = 0; - hdma_update(i); - } - - status.irq_lock = true; -} - -//============== -//initialization -//============== - -void CPU::dma_power() { - for(unsigned i = 0; i < 8; i++) { - channel[i].direction = 1; - channel[i].indirect = true; - channel[i].unused = true; - channel[i].reverse_transfer = true; - channel[i].fixed_transfer = true; - channel[i].transfer_mode = 7; - - channel[i].dest_addr = 0xff; - - channel[i].source_addr = 0xffff; - channel[i].source_bank = 0xff; - - channel[i].transfer_size = 0xffff; - channel[i].indirect_bank = 0xff; - - channel[i].hdma_addr = 0xffff; - channel[i].line_counter = 0xff; - channel[i].unknown = 0xff; - } -} - -void CPU::dma_reset() { - for(unsigned i = 0; i < 8; i++) { - channel[i].dma_enabled = false; - channel[i].hdma_enabled = false; - - channel[i].hdma_completed = false; - channel[i].hdma_do_transfer = false; - } - - pipe.valid = false; - pipe.addr = 0; - pipe.data = 0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/cpu/dma/dma.hpp b/waterbox/libsnes/bsnes/snes/cpu/dma/dma.hpp deleted file mode 100644 index 33755bdee6..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/dma/dma.hpp +++ /dev/null @@ -1,79 +0,0 @@ -struct { - //$420b - bool dma_enabled; - - //$420c - bool hdma_enabled; - - //$43x0 - bool direction; - bool indirect; - bool unused; - bool reverse_transfer; - bool fixed_transfer; - uint3 transfer_mode; - - //$43x1 - uint8 dest_addr; - - //$43x2-$43x3 - uint16 source_addr; - - //$43x4 - uint8 source_bank; - - //$43x5-$43x6 - union { - uint16 transfer_size; - uint16 indirect_addr; - }; - - //$43x7 - uint8 indirect_bank; - - //$43x8-$43x9 - uint16 hdma_addr; - - //$43xa - uint8 line_counter; - - //$43xb/$43xf - uint8 unknown; - - //internal state - bool hdma_completed; - bool hdma_do_transfer; -} channel[8]; - -struct { - bool valid; - unsigned addr; - uint8 data; -} pipe; - -void dma_add_clocks(unsigned clocks); -bool dma_transfer_valid(uint8 bbus, uint32 abus); -bool dma_addr_valid(uint32 abus); -uint8 dma_read(uint32 abus); -void dma_write(bool valid, unsigned addr = 0, uint8 data = 0); -void dma_transfer(bool direction, uint8 bbus, uint32 abus); - -uint8 dma_bbus(unsigned i, unsigned channel); -uint32 dma_addr(unsigned i); -uint32 hdma_addr(unsigned i); -uint32 hdma_iaddr(unsigned i); - -uint8 dma_enabled_channels(); -bool hdma_active(unsigned i); -bool hdma_active_after(unsigned i); -uint8 hdma_enabled_channels(); -uint8 hdma_active_channels(); - -void dma_run(); -void hdma_update(unsigned i); -void hdma_run(); -void hdma_init_reset(); -void hdma_init(); - -void dma_power(); -void dma_reset(); diff --git a/waterbox/libsnes/bsnes/snes/cpu/memory/memory.cpp b/waterbox/libsnes/bsnes/snes/cpu/memory/memory.cpp deleted file mode 100644 index bc4ab661fe..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/memory/memory.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifdef CPU_CPP - -uint8 CPU::port_read(uint2 port) const { return status.port[port]; } -void CPU::port_write(uint2 port, uint8 data) { status.port[port] = data; } - -void CPU::op_io() { - status.clock_count = 6; - dma_edge(); - add_clocks(6); - alu_edge(); -} - -uint8 CPU::op_read(uint32 addr, eCDLog_Flags flags) { - debugger.op_read(addr); - - status.clock_count = speed(addr); - dma_edge(); - add_clocks(status.clock_count - 4); - cdlInfo.currFlags = flags; - regs.mdr = bus.read(addr); - add_clocks(4); - alu_edge(); - return regs.mdr; -} - -void CPU::op_write(uint32 addr, uint8 data) { - debugger.op_write(addr, data); - - alu_edge(); - status.clock_count = speed(addr); - dma_edge(); - add_clocks(status.clock_count); - bus.write(addr, regs.mdr = data); -} - -unsigned CPU::speed(unsigned addr) const { - if(addr & 0x408000) { - if(addr & 0x800000) return status.rom_speed; - return 8; - } - if((addr + 0x6000) & 0x4000) return 8; - if((addr - 0x4000) & 0x7e00) return 6; - return 12; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/cpu/memory/memory.hpp b/waterbox/libsnes/bsnes/snes/cpu/memory/memory.hpp deleted file mode 100644 index 638e892231..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/memory/memory.hpp +++ /dev/null @@ -1,4 +0,0 @@ -void op_io(); -uint8 op_read(uint32 addr, eCDLog_Flags flags = eCDLog_Flags_CPUData); -void op_write(uint32 addr, uint8 data); -alwaysinline unsigned speed(unsigned addr) const; diff --git a/waterbox/libsnes/bsnes/snes/cpu/mmio/mmio.cpp b/waterbox/libsnes/bsnes/snes/cpu/mmio/mmio.cpp deleted file mode 100644 index 554c2b27cf..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/mmio/mmio.cpp +++ /dev/null @@ -1,523 +0,0 @@ -#ifdef CPU_CPP - -uint8 CPU::pio() { return status.pio; } -bool CPU::joylatch() { return status.joypad_strobe_latch; } - -//WMDATA -uint8 CPU::mmio_r2180() { - return bus.read(0x7e0000 | status.wram_addr++); -} - -//WMDATA -void CPU::mmio_w2180(uint8 data) { - bus.write(0x7e0000 | status.wram_addr++, data); -} - -//WMADDL -void CPU::mmio_w2181(uint8 data) { - status.wram_addr = (status.wram_addr & 0x01ff00) | (data << 0); -} - -//WMADDM -void CPU::mmio_w2182(uint8 data) { - status.wram_addr = (status.wram_addr & 0x0100ff) | (data << 8); -} - -//WMADDH -void CPU::mmio_w2183(uint8 data) { - status.wram_addr = (status.wram_addr & 0x00ffff) | (data << 16); -} - -//JOYSER0 -//bit 0 is shared between JOYSER0 and JOYSER1, therefore -//strobing $4016.d0 affects both controller port latches. -//$4017 bit 0 writes are ignored. -void CPU::mmio_w4016(uint8 data) { - input.port1->latch(data & 1); - input.port2->latch(data & 1); - interface()->inputNotify(data & 1); -} - -//JOYSER0 -//7-2 = MDR -//1-0 = Joypad serial data -uint8 CPU::mmio_r4016() { - uint8 r = regs.mdr & 0xfc; - r |= input.port1->data(); - if (!status.auto_joypad_poll) interface()->inputNotify(0x4016); - return r; -} - -//JOYSER1 -//7-5 = MDR -//4-2 = Always 1 (pins are connected to GND) -//1-0 = Joypad serial data -uint8 CPU::mmio_r4017() { - uint8 r = (regs.mdr & 0xe0) | 0x1c; - r |= input.port2->data(); - if (!status.auto_joypad_poll) interface()->inputNotify(0x4017); - return r; -} - -//NMITIMEN -void CPU::mmio_w4200(uint8 data) { - status.auto_joypad_poll = data & 1; - nmitimen_update(data); -} - -//WRIO -void CPU::mmio_w4201(uint8 data) { - if((status.pio & 0x80) && !(data & 0x80)) ppu.latch_counters(); - status.pio = data; -} - -//WRMPYA -void CPU::mmio_w4202(uint8 data) { - status.wrmpya = data; -} - -//WRMPYB -void CPU::mmio_w4203(uint8 data) { - status.rdmpy = 0; - if(alu.mpyctr || alu.divctr) return; - - status.wrmpyb = data; - status.rddiv = (status.wrmpyb << 8) | status.wrmpya; - - alu.mpyctr = 8; //perform multiplication over the next eight cycles - alu.shift = status.wrmpyb; -} - -//WRDIVL -void CPU::mmio_w4204(uint8 data) { - status.wrdiva = (status.wrdiva & 0xff00) | (data << 0); -} - -//WRDIVH -void CPU::mmio_w4205(uint8 data) { - status.wrdiva = (status.wrdiva & 0x00ff) | (data << 8); -} - -//WRDIVB -void CPU::mmio_w4206(uint8 data) { - status.rdmpy = status.wrdiva; - if(alu.mpyctr || alu.divctr) return; - - status.wrdivb = data; - - alu.divctr = 16; //perform division over the next sixteen cycles - alu.shift = status.wrdivb << 16; -} - -//HTIMEL -void CPU::mmio_w4207(uint8 data) { - status.hirq_pos = (status.hirq_pos & 0x0100) | (data << 0); -} - -//HTIMEH -void CPU::mmio_w4208(uint8 data) { - status.hirq_pos = (status.hirq_pos & 0x00ff) | (data << 8); -} - -//VTIMEL -void CPU::mmio_w4209(uint8 data) { - status.virq_pos = (status.virq_pos & 0x0100) | (data << 0); -} - -//VTIMEH -void CPU::mmio_w420a(uint8 data) { - status.virq_pos = (status.virq_pos & 0x00ff) | (data << 8); -} - -//DMAEN -void CPU::mmio_w420b(uint8 data) { - for(unsigned i = 0; i < 8; i++) { - channel[i].dma_enabled = data & (1 << i); - } - if(data) status.dma_pending = true; -} - -//HDMAEN -void CPU::mmio_w420c(uint8 data) { - for(unsigned i = 0; i < 8; i++) { - channel[i].hdma_enabled = data & (1 << i); - } -} - -//MEMSEL -void CPU::mmio_w420d(uint8 data) { - status.rom_speed = (data & 1 ? 6 : 8); -} - -//RDNMI -//7 = NMI acknowledge -//6-4 = MDR -//3-0 = CPU (5a22) version -uint8 CPU::mmio_r4210() { - uint8 r = (regs.mdr & 0x70); - r |= (uint8)(rdnmi()) << 7; - r |= (cpu_version & 0x0f); - return r; -} - -//TIMEUP -//7 = IRQ acknowledge -//6-0 = MDR -uint8 CPU::mmio_r4211() { - uint8 r = (regs.mdr & 0x7f); - r |= (uint8)(timeup()) << 7; - return r; -} - -//HVBJOY -//7 = VBLANK acknowledge -//6 = HBLANK acknowledge -//5-1 = MDR -//0 = JOYPAD acknowledge -uint8 CPU::mmio_r4212() { - uint8 r = (regs.mdr & 0x3e); - if(status.auto_joypad_active) r |= 0x01; - if(hcounter() <= 2 || hcounter() >= 1096) r |= 0x40; //hblank - if(vcounter() >= (ppu.overscan() == false ? 225 : 240)) r |= 0x80; //vblank - return r; -} - -//RDIO -uint8 CPU::mmio_r4213() { - // interface()->inputNotify(0x4213); // if there are lag counter issues with super scope, uncomment this - return status.pio; -} - -//RDDIVL -uint8 CPU::mmio_r4214() { - return status.rddiv >> 0; -} - -//RDDIVH -uint8 CPU::mmio_r4215() { - return status.rddiv >> 8; -} - -//RDMPYL -uint8 CPU::mmio_r4216() { - return status.rdmpy >> 0; -} - -//RDMPYH -uint8 CPU::mmio_r4217() { - return status.rdmpy >> 8; -} - -uint8 CPU::mmio_r4218() { interface()->inputNotify(0x4218); return status.joy1 >> 0; } //JOY1L -uint8 CPU::mmio_r4219() { interface()->inputNotify(0x4219); return status.joy1 >> 8; } //JOY1H -uint8 CPU::mmio_r421a() { interface()->inputNotify(0x421a); return status.joy2 >> 0; } //JOY2L -uint8 CPU::mmio_r421b() { interface()->inputNotify(0x421b); return status.joy2 >> 8; } //JOY2H -uint8 CPU::mmio_r421c() { interface()->inputNotify(0x421c); return status.joy3 >> 0; } //JOY3L -uint8 CPU::mmio_r421d() { interface()->inputNotify(0x421d); return status.joy3 >> 8; } //JOY3H -uint8 CPU::mmio_r421e() { interface()->inputNotify(0x421e); return status.joy4 >> 0; } //JOY4L -uint8 CPU::mmio_r421f() { interface()->inputNotify(0x421f); return status.joy4 >> 8; } //JOY4H - -//DMAPx -uint8 CPU::mmio_r43x0(uint8 i) { - return (channel[i].direction << 7) - | (channel[i].indirect << 6) - | (channel[i].unused << 5) - | (channel[i].reverse_transfer << 4) - | (channel[i].fixed_transfer << 3) - | (channel[i].transfer_mode << 0); -} - -//BBADx -uint8 CPU::mmio_r43x1(uint8 i) { - return channel[i].dest_addr; -} - -//A1TxL -uint8 CPU::mmio_r43x2(uint8 i) { - return channel[i].source_addr >> 0; -} - -//A1TxH -uint8 CPU::mmio_r43x3(uint8 i) { - return channel[i].source_addr >> 8; -} - -//A1Bx -uint8 CPU::mmio_r43x4(uint8 i) { - return channel[i].source_bank; -} - -//DASxL -//union { uint16 transfer_size; uint16 indirect_addr; }; -uint8 CPU::mmio_r43x5(uint8 i) { - return channel[i].transfer_size >> 0; -} - -//DASxH -//union { uint16 transfer_size; uint16 indirect_addr; }; -uint8 CPU::mmio_r43x6(uint8 i) { - return channel[i].transfer_size >> 8; -} - -//DASBx -uint8 CPU::mmio_r43x7(uint8 i) { - return channel[i].indirect_bank; -} - -//A2AxL -uint8 CPU::mmio_r43x8(uint8 i) { - return channel[i].hdma_addr >> 0; -} - -//A2AxH -uint8 CPU::mmio_r43x9(uint8 i) { - return channel[i].hdma_addr >> 8; -} - -//NTRLx -uint8 CPU::mmio_r43xa(uint8 i) { - return channel[i].line_counter; -} - -//??? -uint8 CPU::mmio_r43xb(uint8 i) { - return channel[i].unknown; -} - -//DMAPx -void CPU::mmio_w43x0(uint8 i, uint8 data) { - channel[i].direction = data & 0x80; - channel[i].indirect = data & 0x40; - channel[i].unused = data & 0x20; - channel[i].reverse_transfer = data & 0x10; - channel[i].fixed_transfer = data & 0x08; - channel[i].transfer_mode = data & 0x07; -} - -//DDBADx -void CPU::mmio_w43x1(uint8 i, uint8 data) { - channel[i].dest_addr = data; -} - -//A1TxL -void CPU::mmio_w43x2(uint8 i, uint8 data) { - channel[i].source_addr = (channel[i].source_addr & 0xff00) | (data << 0); -} - -//A1TxH -void CPU::mmio_w43x3(uint8 i, uint8 data) { - channel[i].source_addr = (channel[i].source_addr & 0x00ff) | (data << 8); -} - -//A1Bx -void CPU::mmio_w43x4(uint8 i, uint8 data) { - channel[i].source_bank = data; -} - -//DASxL -//union { uint16 transfer_size; uint16 indirect_addr; }; -void CPU::mmio_w43x5(uint8 i, uint8 data) { - channel[i].transfer_size = (channel[i].transfer_size & 0xff00) | (data << 0); -} - -//DASxH -//union { uint16 transfer_size; uint16 indirect_addr; }; -void CPU::mmio_w43x6(uint8 i, uint8 data) { - channel[i].transfer_size = (channel[i].transfer_size & 0x00ff) | (data << 8); -} - -//DASBx -void CPU::mmio_w43x7(uint8 i, uint8 data) { - channel[i].indirect_bank = data; -} - -//A2AxL -void CPU::mmio_w43x8(uint8 i, uint8 data) { - channel[i].hdma_addr = (channel[i].hdma_addr & 0xff00) | (data << 0); -} - -//A2AxH -void CPU::mmio_w43x9(uint8 i, uint8 data) { - channel[i].hdma_addr = (channel[i].hdma_addr & 0x00ff) | (data << 8); -} - -//NTRLx -void CPU::mmio_w43xa(uint8 i, uint8 data) { - channel[i].line_counter = data; -} - -//??? -void CPU::mmio_w43xb(uint8 i, uint8 data) { - channel[i].unknown = data; -} - -void CPU::mmio_power() { -} - -void CPU::mmio_reset() { - //$2140-217f - for(auto &port : status.port) port = 0x00; - - //$2181-$2183 - status.wram_addr = 0x000000; - - //$4016-$4017 - status.joypad_strobe_latch = 0; - status.joypad1_bits = ~0; - status.joypad2_bits = ~0; - - //$4200 - status.nmi_enabled = false; - status.hirq_enabled = false; - status.virq_enabled = false; - status.auto_joypad_poll = false; - - //$4201 - status.pio = 0xff; - - //$4202-$4203 - status.wrmpya = 0xff; - status.wrmpyb = 0xff; - - //$4204-$4206 - status.wrdiva = 0xffff; - status.wrdivb = 0xff; - - //$4207-$420a - status.hirq_pos = 0x01ff; - status.virq_pos = 0x01ff; - - //$420d - status.rom_speed = 8; - - //$4214-$4217 - status.rddiv = 0x0000; - status.rdmpy = 0x0000; - - //$4218-$421f - status.joy1 = 0x0000; - status.joy2 = 0x0000; - status.joy3 = 0x0000; - status.joy4 = 0x0000; - - //ALU - alu.mpyctr = 0; - alu.divctr = 0; - alu.shift = 0; -} - -uint8 CPU::mmio_read(unsigned addr) { - addr &= 0xffff; - - //APU - if((addr & 0xffc0) == 0x2140) { //$2140-$217f - synchronize_smp(); - return smp.port_read(addr); - } - - //DMA - if((addr & 0xff80) == 0x4300) { //$4300-$437f - unsigned i = (addr >> 4) & 7; - switch(addr & 0xf) { - case 0x0: return mmio_r43x0(i); - case 0x1: return mmio_r43x1(i); - case 0x2: return mmio_r43x2(i); - case 0x3: return mmio_r43x3(i); - case 0x4: return mmio_r43x4(i); - case 0x5: return mmio_r43x5(i); - case 0x6: return mmio_r43x6(i); - case 0x7: return mmio_r43x7(i); - case 0x8: return mmio_r43x8(i); - case 0x9: return mmio_r43x9(i); - case 0xa: return mmio_r43xa(i); - case 0xb: return mmio_r43xb(i); - case 0xc: return regs.mdr; //unmapped - case 0xd: return regs.mdr; //unmapped - case 0xe: return regs.mdr; //unmapped - case 0xf: return mmio_r43xb(i); //mirror of $43xb - } - } - - switch(addr) { - case 0x2180: return mmio_r2180(); - case 0x4016: return mmio_r4016(); - case 0x4017: return mmio_r4017(); - case 0x4210: return mmio_r4210(); - case 0x4211: return mmio_r4211(); - case 0x4212: return mmio_r4212(); - case 0x4213: return mmio_r4213(); - case 0x4214: return mmio_r4214(); - case 0x4215: return mmio_r4215(); - case 0x4216: return mmio_r4216(); - case 0x4217: return mmio_r4217(); - case 0x4218: return mmio_r4218(); - case 0x4219: return mmio_r4219(); - case 0x421a: return mmio_r421a(); - case 0x421b: return mmio_r421b(); - case 0x421c: return mmio_r421c(); - case 0x421d: return mmio_r421d(); - case 0x421e: return mmio_r421e(); - case 0x421f: return mmio_r421f(); - } - - return regs.mdr; -} - -void CPU::mmio_write(unsigned addr, uint8 data) { - addr &= 0xffff; - - //APU - if((addr & 0xffc0) == 0x2140) { //$2140-$217f - synchronize_smp(); - port_write(addr, data); - return; - } - - //DMA - if((addr & 0xff80) == 0x4300) { //$4300-$437f - unsigned i = (addr >> 4) & 7; - switch(addr & 0xf) { - case 0x0: mmio_w43x0(i, data); return; - case 0x1: mmio_w43x1(i, data); return; - case 0x2: mmio_w43x2(i, data); return; - case 0x3: mmio_w43x3(i, data); return; - case 0x4: mmio_w43x4(i, data); return; - case 0x5: mmio_w43x5(i, data); return; - case 0x6: mmio_w43x6(i, data); return; - case 0x7: mmio_w43x7(i, data); return; - case 0x8: mmio_w43x8(i, data); return; - case 0x9: mmio_w43x9(i, data); return; - case 0xa: mmio_w43xa(i, data); return; - case 0xb: mmio_w43xb(i, data); return; - case 0xc: return; //unmapped - case 0xd: return; //unmapped - case 0xe: return; //unmapped - case 0xf: mmio_w43xb(i, data); return; //mirror of $43xb - } - } - - switch(addr) { - case 0x2180: mmio_w2180(data); return; - case 0x2181: mmio_w2181(data); return; - case 0x2182: mmio_w2182(data); return; - case 0x2183: mmio_w2183(data); return; - case 0x4016: mmio_w4016(data); return; - case 0x4017: return; //unmapped - case 0x4200: mmio_w4200(data); return; - case 0x4201: mmio_w4201(data); return; - case 0x4202: mmio_w4202(data); return; - case 0x4203: mmio_w4203(data); return; - case 0x4204: mmio_w4204(data); return; - case 0x4205: mmio_w4205(data); return; - case 0x4206: mmio_w4206(data); return; - case 0x4207: mmio_w4207(data); return; - case 0x4208: mmio_w4208(data); return; - case 0x4209: mmio_w4209(data); return; - case 0x420a: mmio_w420a(data); return; - case 0x420b: mmio_w420b(data); return; - case 0x420c: mmio_w420c(data); return; - case 0x420d: mmio_w420d(data); return; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/cpu/mmio/mmio.hpp b/waterbox/libsnes/bsnes/snes/cpu/mmio/mmio.hpp deleted file mode 100644 index f2cd7712b6..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/mmio/mmio.hpp +++ /dev/null @@ -1,71 +0,0 @@ -public: -uint8 mmio_read(unsigned addr); -void mmio_write(unsigned addr, uint8 data); - -privileged: -void mmio_power(); -void mmio_reset(); - -uint8 mmio_r2180(); -uint8 mmio_r4016(); -uint8 mmio_r4017(); -uint8 mmio_r4210(); -uint8 mmio_r4211(); -uint8 mmio_r4212(); -uint8 mmio_r4213(); -uint8 mmio_r4214(); -uint8 mmio_r4215(); -uint8 mmio_r4216(); -uint8 mmio_r4217(); -uint8 mmio_r4218(); -uint8 mmio_r4219(); -uint8 mmio_r421a(); -uint8 mmio_r421b(); -uint8 mmio_r421c(); -uint8 mmio_r421d(); -uint8 mmio_r421e(); -uint8 mmio_r421f(); -uint8 mmio_r43x0(uint8 i); -uint8 mmio_r43x1(uint8 i); -uint8 mmio_r43x2(uint8 i); -uint8 mmio_r43x3(uint8 i); -uint8 mmio_r43x4(uint8 i); -uint8 mmio_r43x5(uint8 i); -uint8 mmio_r43x6(uint8 i); -uint8 mmio_r43x7(uint8 i); -uint8 mmio_r43x8(uint8 i); -uint8 mmio_r43x9(uint8 i); -uint8 mmio_r43xa(uint8 i); -uint8 mmio_r43xb(uint8 i); - -void mmio_w2180(uint8 data); -void mmio_w2181(uint8 data); -void mmio_w2182(uint8 data); -void mmio_w2183(uint8 data); -void mmio_w4016(uint8 data); -void mmio_w4200(uint8 data); -void mmio_w4201(uint8 data); -void mmio_w4202(uint8 data); -void mmio_w4203(uint8 data); -void mmio_w4204(uint8 data); -void mmio_w4205(uint8 data); -void mmio_w4206(uint8 data); -void mmio_w4207(uint8 data); -void mmio_w4208(uint8 data); -void mmio_w4209(uint8 data); -void mmio_w420a(uint8 data); -void mmio_w420b(uint8 data); -void mmio_w420c(uint8 data); -void mmio_w420d(uint8 data); -void mmio_w43x0(uint8 i, uint8 data); -void mmio_w43x1(uint8 i, uint8 data); -void mmio_w43x2(uint8 i, uint8 data); -void mmio_w43x3(uint8 i, uint8 data); -void mmio_w43x4(uint8 i, uint8 data); -void mmio_w43x5(uint8 i, uint8 data); -void mmio_w43x6(uint8 i, uint8 data); -void mmio_w43x7(uint8 i, uint8 data); -void mmio_w43x8(uint8 i, uint8 data); -void mmio_w43x9(uint8 i, uint8 data); -void mmio_w43xa(uint8 i, uint8 data); -void mmio_w43xb(uint8 i, uint8 data); diff --git a/waterbox/libsnes/bsnes/snes/cpu/timing/irq.cpp b/waterbox/libsnes/bsnes/snes/cpu/timing/irq.cpp deleted file mode 100644 index 506a435edb..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/timing/irq.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#ifdef CPU_CPP - -//called once every four clock cycles; -//as NMI steps by scanlines (divisible by 4) and IRQ by PPU 4-cycle dots. -// -//ppu.(vh)counter(n) returns the value of said counters n-clocks before current time; -//it is used to emulate hardware communication delay between opcode and interrupt units. -void CPU::poll_interrupts() { - //NMI hold - if(status.nmi_hold) { - status.nmi_hold = false; - if(status.nmi_enabled) status.nmi_transition = true; - } - - //NMI test - bool nmi_valid = (vcounter(2) >= (!ppu.overscan() ? 225 : 240)); - if(!status.nmi_valid && nmi_valid) { - //0->1 edge sensitive transition - status.nmi_line = true; - status.nmi_hold = true; //hold /NMI for four cycles - } else if(status.nmi_valid && !nmi_valid) { - //1->0 edge sensitive transition - status.nmi_line = false; - } - status.nmi_valid = nmi_valid; - - //IRQ hold - status.irq_hold = false; - if(status.irq_line) { - if(status.virq_enabled || status.hirq_enabled) status.irq_transition = true; - } - - //IRQ test - bool irq_valid = (status.virq_enabled || status.hirq_enabled); - if(irq_valid) { - if((status.virq_enabled && vcounter(10) != (status.virq_pos)) - || (status.hirq_enabled && hcounter(10) != (status.hirq_pos + 1) * 4) - || (status.virq_pos && vcounter(6) == 0) //IRQs cannot trigger on last dot of field - ) irq_valid = false; - } - if(!status.irq_valid && irq_valid) { - //0->1 edge sensitive transition - status.irq_line = true; - status.irq_hold = true; //hold /IRQ for four cycles - } - status.irq_valid = irq_valid; -} - -void CPU::nmitimen_update(uint8 data) { - bool nmi_enabled = status.nmi_enabled; - bool virq_enabled = status.virq_enabled; - bool hirq_enabled = status.hirq_enabled; - status.nmi_enabled = data & 0x80; - status.virq_enabled = data & 0x20; - status.hirq_enabled = data & 0x10; - - //0->1 edge sensitive transition - if(!nmi_enabled && status.nmi_enabled && status.nmi_line) { - status.nmi_transition = true; - } - - //?->1 level sensitive transition - if(status.virq_enabled && !status.hirq_enabled && status.irq_line) { - status.irq_transition = true; - } - - if(!status.virq_enabled && !status.hirq_enabled) { - status.irq_line = false; - status.irq_transition = false; - } - - status.irq_lock = true; -} - -bool CPU::rdnmi() { - bool result = status.nmi_line; - if(!status.nmi_hold) { - status.nmi_line = false; - } - return result; -} - -bool CPU::timeup() { - bool result = status.irq_line; - if(!status.irq_hold) { - status.irq_line = false; - status.irq_transition = false; - } - return result; -} - -bool CPU::nmi_test() { - if(!status.nmi_transition) return false; - status.nmi_transition = false; - regs.wai = false; - return true; -} - -bool CPU::irq_test() { - if(!status.irq_transition && !regs.irq) return false; - status.irq_transition = false; - regs.wai = false; - return !regs.p.i; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/cpu/timing/joypad.cpp b/waterbox/libsnes/bsnes/snes/cpu/timing/joypad.cpp deleted file mode 100644 index 9df4a0d2e2..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/timing/joypad.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifdef CPU_CPP - -//called every 256 clocks; see CPU::add_clocks() -void CPU::step_auto_joypad_poll() { - if(vcounter() >= (ppu.overscan() == false ? 225 : 240)) { - //cache enable state at first iteration - if(status.auto_joypad_counter == 0) status.auto_joypad_latch = status.auto_joypad_poll; - status.auto_joypad_active = status.auto_joypad_counter <= 15; - - if(status.auto_joypad_active && status.auto_joypad_latch) { - if(status.auto_joypad_counter == 0) { - input.port1->latch(1); - input.port2->latch(1); - input.port1->latch(0); - input.port2->latch(0); - interface()->inputNotify(1); - interface()->inputNotify(0); - } - - uint2 port0 = input.port1->data(); - uint2 port1 = input.port2->data(); - - status.joy1 = (status.joy1 << 1) | (bool)(port0 & 1); - status.joy2 = (status.joy2 << 1) | (bool)(port1 & 1); - status.joy3 = (status.joy3 << 1) | (bool)(port0 & 2); - status.joy4 = (status.joy4 << 1) | (bool)(port1 & 2); - } - - status.auto_joypad_counter++; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/cpu/timing/timing.cpp b/waterbox/libsnes/bsnes/snes/cpu/timing/timing.cpp deleted file mode 100644 index 8189c01b26..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/timing/timing.cpp +++ /dev/null @@ -1,205 +0,0 @@ -#ifdef CPU_CPP - -#include "irq.cpp" -#include "joypad.cpp" - -unsigned CPU::dma_counter() { - return (status.dma_counter + hcounter()) & 7; -} - -void CPU::add_clocks(unsigned clocks) { - status.irq_lock = false; - unsigned ticks = clocks >> 1; - while(ticks--) { - tick(); - if(hcounter() & 2) poll_interrupts(); - } - - step(clocks); - - status.auto_joypad_clock += clocks; - if(status.auto_joypad_clock >= 256) { - status.auto_joypad_clock -= 256; - step_auto_joypad_poll(); - } - - if(status.dram_refreshed == false && hcounter() >= status.dram_refresh_position) { - status.dram_refreshed = true; - add_clocks(40); - } - - #if defined(DEBUGGER) - synchronize_smp(); - synchronize_ppu(); - synchronize_coprocessors(); - #endif -} - -//called by ppu.tick() when Hcounter=0 -void CPU::scanline() { - status.dma_counter = (status.dma_counter + status.line_clocks) & 7; - status.line_clocks = lineclocks(); - - //forcefully sync S-CPU to other processors, in case chips are not communicating - synchronize_smp(); - synchronize_ppu(); - synchronize_coprocessors(); - system.scanline(); - - if(vcounter() == 0) { - //HDMA init triggers once every frame - status.hdma_init_position = (cpu_version == 1 ? 12 + 8 - dma_counter() : 12 + dma_counter()); - status.hdma_init_triggered = false; - - status.auto_joypad_counter = 0; - } - - //DRAM refresh occurs once every scanline - if(cpu_version == 2) status.dram_refresh_position = 530 + 8 - dma_counter(); - status.dram_refreshed = false; - - //HDMA triggers once every visible scanline - if(vcounter() <= (ppu.overscan() == false ? 224 : 239)) { - status.hdma_position = 1104; - status.hdma_triggered = false; - } -} - -void CPU::alu_edge() { - if(alu.mpyctr) { - alu.mpyctr--; - if(status.rddiv & 1) status.rdmpy += alu.shift; - status.rddiv >>= 1; - alu.shift <<= 1; - } - - if(alu.divctr) { - alu.divctr--; - status.rddiv <<= 1; - alu.shift >>= 1; - if(status.rdmpy >= alu.shift) { - status.rdmpy -= alu.shift; - status.rddiv |= 1; - } - } -} - -void CPU::dma_edge() { - //H/DMA pending && DMA inactive? - //.. Run one full CPU cycle - //.. HDMA pending && HDMA enabled ? DMA sync + HDMA run - //.. DMA pending && DMA enabled ? DMA sync + DMA run - //.... HDMA during DMA && HDMA enabled ? DMA sync + HDMA run - //.. Run one bus CPU cycle - //.. CPU sync - - if(status.dma_active == true) { - if(status.hdma_pending) { - status.hdma_pending = false; - if(hdma_enabled_channels()) { - if(!dma_enabled_channels()) { - dma_add_clocks(8 - dma_counter()); - } - status.hdma_mode == 0 ? hdma_init() : hdma_run(); - if(!dma_enabled_channels()) { - add_clocks(status.clock_count - (status.dma_clocks % status.clock_count)); - status.dma_active = false; - } - } - } - - if(status.dma_pending) { - status.dma_pending = false; - if(dma_enabled_channels()) { - dma_add_clocks(8 - dma_counter()); - dma_run(); - add_clocks(status.clock_count - (status.dma_clocks % status.clock_count)); - status.dma_active = false; - } - } - } - - if(status.hdma_init_triggered == false && hcounter() >= status.hdma_init_position) { - status.hdma_init_triggered = true; - hdma_init_reset(); - if(hdma_enabled_channels()) { - status.hdma_pending = true; - status.hdma_mode = 0; - } - } - - if(status.hdma_triggered == false && hcounter() >= status.hdma_position) { - status.hdma_triggered = true; - if(hdma_active_channels()) { - status.hdma_pending = true; - status.hdma_mode = 1; - } - } - - if(status.dma_active == false) { - if(status.dma_pending || status.hdma_pending) { - status.dma_clocks = 0; - status.dma_active = true; - } - } -} - -//used to test for NMI/IRQ, which can trigger on the edge of every opcode. -//test one cycle early to simulate two-stage pipeline of x816 CPU. -// -//status.irq_lock is used to simulate hardware delay before interrupts can -//trigger during certain events (immediately after DMA, writes to $4200, etc) -void CPU::last_cycle() { - if(status.irq_lock == false) { - status.nmi_pending |= nmi_test(); - status.irq_pending |= irq_test(); - status.interrupt_pending = (status.nmi_pending || status.irq_pending); - } -} - -void CPU::timing_power() { -} - -void CPU::timing_reset() { - status.clock_count = 0; - status.line_clocks = lineclocks(); - - status.irq_lock = false; - status.dram_refresh_position = (cpu_version == 1 ? 530 : 538); - status.dram_refreshed = false; - - status.hdma_init_position = (cpu_version == 1 ? 12 + 8 - dma_counter() : 12 + dma_counter()); - status.hdma_init_triggered = false; - - status.hdma_position = 1104; - status.hdma_triggered = false; - - status.nmi_valid = false; - status.nmi_line = false; - status.nmi_transition = false; - status.nmi_pending = false; - status.nmi_hold = false; - - status.irq_valid = false; - status.irq_line = false; - status.irq_transition = false; - status.irq_pending = false; - status.irq_hold = false; - - status.reset_pending = true; - status.interrupt_pending = true; - - status.dma_active = false; - status.dma_counter = 0; - status.dma_clocks = 0; - status.dma_pending = false; - status.hdma_pending = false; - status.hdma_mode = 0; - - status.auto_joypad_active = false; - status.auto_joypad_latch = false; - status.auto_joypad_counter = 0; - status.auto_joypad_clock = 0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/cpu/timing/timing.hpp b/waterbox/libsnes/bsnes/snes/cpu/timing/timing.hpp deleted file mode 100644 index 6c225dab5d..0000000000 --- a/waterbox/libsnes/bsnes/snes/cpu/timing/timing.hpp +++ /dev/null @@ -1,24 +0,0 @@ -//timing.cpp -unsigned dma_counter(); - -void add_clocks(unsigned clocks); -void scanline(); - -alwaysinline void alu_edge(); -alwaysinline void dma_edge(); -alwaysinline void last_cycle(); - -void timing_power(); -void timing_reset(); - -//irq.cpp -alwaysinline void poll_interrupts(); -void nmitimen_update(uint8 data); -bool rdnmi(); -bool timeup(); - -alwaysinline bool nmi_test(); -alwaysinline bool irq_test(); - -//joypad.cpp -void step_auto_joypad_poll(); diff --git a/waterbox/libsnes/bsnes/snes/dsp/brr.cpp b/waterbox/libsnes/bsnes/snes/dsp/brr.cpp deleted file mode 100644 index 8552d7aa5d..0000000000 --- a/waterbox/libsnes/bsnes/snes/dsp/brr.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifdef DSP_CPP - -void DSP::brr_decode(voice_t &v) { - //state.t_brr_byte = ram[v.brr_addr + v.brr_offset] cached from previous clock cycle - int nybbles = (state.t_brr_byte << 8) + smp.apuram[(uint16)(v.brr_addr + v.brr_offset + 1)]; - - const int filter = (state.t_brr_header >> 2) & 3; - const int scale = (state.t_brr_header >> 4); - - //decode four samples - for(unsigned i = 0; i < 4; i++) { - //bits 12-15 = current nybble; sign extend, then shift right to 4-bit precision - //result: s = 4-bit sign-extended sample value - int s = (int16)nybbles >> 12; - nybbles <<= 4; //slide nybble so that on next loop iteration, bits 12-15 = current nybble - - if(scale <= 12) { - s <<= scale; - s >>= 1; - } else { - s &= ~0x7ff; - } - - //apply IIR filter (2 is the most commonly used) - const int p1 = v.buffer[v.buf_pos - 1]; - const int p2 = v.buffer[v.buf_pos - 2] >> 1; - - switch(filter) { - case 0: break; //no filter - - case 1: { - //s += p1 * 0.46875 - s += p1 >> 1; - s += (-p1) >> 5; - } break; - - case 2: { - //s += p1 * 0.953125 - p2 * 0.46875 - s += p1; - s -= p2; - s += p2 >> 4; - s += (p1 * -3) >> 6; - } break; - - case 3: { - //s += p1 * 0.8984375 - p2 * 0.40625 - s += p1; - s -= p2; - s += (p1 * -13) >> 7; - s += (p2 * 3) >> 4; - } break; - } - - //adjust and write sample - s = sclamp<16>(s); - s = (int16)(s << 1); - v.buffer.write(v.buf_pos++, s); - if(v.buf_pos >= brr_buf_size) v.buf_pos = 0; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/dsp/counter.cpp b/waterbox/libsnes/bsnes/snes/dsp/counter.cpp deleted file mode 100644 index f65fdd26a9..0000000000 --- a/waterbox/libsnes/bsnes/snes/dsp/counter.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifdef DSP_CPP - -//counter_rate = number of samples per counter event -//all rates are evenly divisible by counter_range (0x7800, 30720, or 2048 * 5 * 3) -//note that rate[0] is a special case, which never triggers - -const uint16 DSP::counter_rate[32] = { - 0, 2048, 1536, - 1280, 1024, 768, - 640, 512, 384, - 320, 256, 192, - 160, 128, 96, - 80, 64, 48, - 40, 32, 24, - 20, 16, 12, - 10, 8, 6, - 5, 4, 3, - 2, - 1, -}; - -//counter_offset = counter offset from zero -//counters do not appear to be aligned at zero for all rates - -const uint16 DSP::counter_offset[32] = { - 0, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 0, - 0, -}; - -inline void DSP::counter_tick() { - state.counter--; - if(state.counter < 0) state.counter = counter_range - 1; -} - -//return true if counter event should trigger - -inline bool DSP::counter_poll(unsigned rate) { - if(rate == 0) return false; - return (((unsigned)state.counter + counter_offset[rate]) % counter_rate[rate]) == 0; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/dsp/dsp.cpp b/waterbox/libsnes/bsnes/snes/dsp/dsp.cpp deleted file mode 100644 index 75255205d7..0000000000 --- a/waterbox/libsnes/bsnes/snes/dsp/dsp.cpp +++ /dev/null @@ -1,307 +0,0 @@ -#include - -#define DSP_CPP -namespace SNES { - -DSP dsp; - -#define REG(n) state.regs[r_##n] -#define VREG(n) state.regs[v.vidx + v_##n] - -#include "gaussian.cpp" -#include "counter.cpp" -#include "envelope.cpp" -#include "brr.cpp" -#include "misc.cpp" -#include "voice.cpp" -#include "echo.cpp" - -/* timing */ - -void DSP::step(unsigned clocks) { - clock += clocks; -} - -void DSP::synchronize_smp() { - if(SMP::Threaded == true) { - if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(smp.thread); - } else { - while(clock >= 0) smp.enter(); - } -} - -void DSP::Enter() { dsp.enter(); } - -void DSP::enter() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - voice_5(voice[0]); - voice_2(voice[1]); - tick(); - - voice_6(voice[0]); - voice_3(voice[1]); - tick(); - - voice_7(voice[0]); - voice_4(voice[1]); - voice_1(voice[3]); - tick(); - - voice_8(voice[0]); - voice_5(voice[1]); - voice_2(voice[2]); - tick(); - - voice_9(voice[0]); - voice_6(voice[1]); - voice_3(voice[2]); - tick(); - - voice_7(voice[1]); - voice_4(voice[2]); - voice_1(voice[4]); - tick(); - - voice_8(voice[1]); - voice_5(voice[2]); - voice_2(voice[3]); - tick(); - - voice_9(voice[1]); - voice_6(voice[2]); - voice_3(voice[3]); - tick(); - - voice_7(voice[2]); - voice_4(voice[3]); - voice_1(voice[5]); - tick(); - - voice_8(voice[2]); - voice_5(voice[3]); - voice_2(voice[4]); - tick(); - - voice_9(voice[2]); - voice_6(voice[3]); - voice_3(voice[4]); - tick(); - - voice_7(voice[3]); - voice_4(voice[4]); - voice_1(voice[6]); - tick(); - - voice_8(voice[3]); - voice_5(voice[4]); - voice_2(voice[5]); - tick(); - - voice_9(voice[3]); - voice_6(voice[4]); - voice_3(voice[5]); - tick(); - - voice_7(voice[4]); - voice_4(voice[5]); - voice_1(voice[7]); - tick(); - - voice_8(voice[4]); - voice_5(voice[5]); - voice_2(voice[6]); - tick(); - - voice_9(voice[4]); - voice_6(voice[5]); - voice_3(voice[6]); - tick(); - - voice_1(voice[0]); - voice_7(voice[5]); - voice_4(voice[6]); - tick(); - - voice_8(voice[5]); - voice_5(voice[6]); - voice_2(voice[7]); - tick(); - - voice_9(voice[5]); - voice_6(voice[6]); - voice_3(voice[7]); - tick(); - - voice_1(voice[1]); - voice_7(voice[6]); - voice_4(voice[7]); - tick(); - - voice_8(voice[6]); - voice_5(voice[7]); - voice_2(voice[0]); - tick(); - - voice_3a(voice[0]); - voice_9(voice[6]); - voice_6(voice[7]); - echo_22(); - tick(); - - voice_7(voice[7]); - echo_23(); - tick(); - - voice_8(voice[7]); - echo_24(); - tick(); - - voice_3b(voice[0]); - voice_9(voice[7]); - echo_25(); - tick(); - - echo_26(); - tick(); - - misc_27(); - echo_27(); - tick(); - - misc_28(); - echo_28(); - tick(); - - misc_29(); - echo_29(); - tick(); - - misc_30(); - voice_3c(voice[0]); - echo_30(); - tick(); - - voice_4(voice[0]); - voice_1(voice[2]); - tick(); - } -} - -void DSP::tick() { - step(3 * 8); - synchronize_smp(); -} - -/* register interface for S-SMP $00f2,$00f3 */ - -uint8 DSP::read(uint8 addr) { - return state.regs[addr]; -} - -void DSP::write(uint8 addr, uint8 data) { - state.regs[addr] = data; - - if((addr & 0x0f) == v_envx) { - state.envx_buf = data; - } else if((addr & 0x0f) == v_outx) { - state.outx_buf = data; - } else if(addr == r_kon) { - state.new_kon = data; - } else if(addr == r_endx) { - //always cleared, regardless of data written - state.endx_buf = 0; - state.regs[r_endx] = 0; - } -} - -/* initialization */ - -void DSP::power() { - memset(&state.regs, 0, sizeof state.regs); - - //zero 01-dec-2012 - gotta reset these sometime, somewhere - //zero 17-may-2014 - WHAT? - //state.echo_hist[0] = state.echo_hist[1] = 0; - - state.echo_hist_pos = 0; - state.every_other_sample = false; - state.kon = 0; - state.noise = 0; - state.counter = 0; - state.echo_offset = 0; - state.echo_length = 0; - state.new_kon = 0; - state.endx_buf = 0; - state.envx_buf = 0; - state.outx_buf = 0; - state.t_pmon = 0; - state.t_non = 0; - state.t_eon = 0; - state.t_dir = 0; - state.t_koff = 0; - state.t_brr_next_addr = 0; - state.t_adsr0 = 0; - state.t_brr_header = 0; - state.t_brr_byte = 0; - state.t_srcn = 0; - state.t_esa = 0; - state.t_echo_disabled = 0; - state.t_dir_addr = 0; - state.t_pitch = 0; - state.t_output = 0; - state.t_looped = 0; - state.t_echo_ptr = 0; - state.t_main_out[0] = state.t_main_out[1] = 0; - state.t_echo_out[0] = state.t_echo_out[1] = 0; - state.t_echo_in[0] = state.t_echo_in[1] = 0; - - for(unsigned i = 0; i < 8; i++) { - voice[i].buf_pos = 0; - voice[i].interp_pos = 0; - voice[i].brr_addr = 0; - voice[i].brr_offset = 1; - voice[i].vbit = 1 << i; - voice[i].vidx = i * 0x10; - voice[i].kon_delay = 0; - voice[i].env_mode = env_release; - voice[i].env = 0; - voice[i].t_envx_out = 0; - voice[i].hidden_env = 0; - } -} - -void DSP::reset() { - create(Enter, system.apu_frequency()); - - REG(flg) = 0xe0; - - state.noise = 0x4000; - state.echo_hist_pos = 0; - state.every_other_sample = 1; - state.echo_offset = 0; - state.counter = 0; -} - -DSP::DSP() { - static_assert(sizeof(int) >= 32 / 8, "int >= 32-bits"); - static_assert((int8)0x80 == -0x80, "8-bit sign extension"); - static_assert((int16)0x8000 == -0x8000, "16-bit sign extension"); - static_assert((uint16)0xffff0000 == 0, "16-bit unsigned clip"); - static_assert((-1 >> 1) == -1, "arithmetic shift right"); - - //-0x8000 <= n <= +0x7fff - assert(sclamp<16>(+0x8000) == +0x7fff); - assert(sclamp<16>(-0x8001) == -0x8000); -} - -DSP::~DSP() { -} - -#undef REG -#undef VREG - -} diff --git a/waterbox/libsnes/bsnes/snes/dsp/dsp.hpp b/waterbox/libsnes/bsnes/snes/dsp/dsp.hpp deleted file mode 100644 index 532fcbecab..0000000000 --- a/waterbox/libsnes/bsnes/snes/dsp/dsp.hpp +++ /dev/null @@ -1,171 +0,0 @@ -struct DSP : public Processor { - enum : bool { Threaded = true }; - alwaysinline void step(unsigned clocks); - alwaysinline void synchronize_smp(); - - uint8 read(uint8 addr); - void write(uint8 addr, uint8 data); - - void enter(); - void power(); - void reset(); - - DSP(); - ~DSP(); - -privileged: - //global registers - enum global_reg_t { - r_mvoll = 0x0c, r_mvolr = 0x1c, - r_evoll = 0x2c, r_evolr = 0x3c, - r_kon = 0x4c, r_koff = 0x5c, - r_flg = 0x6c, r_endx = 0x7c, - r_efb = 0x0d, r_pmon = 0x2d, - r_non = 0x3d, r_eon = 0x4d, - r_dir = 0x5d, r_esa = 0x6d, - r_edl = 0x7d, r_fir = 0x0f, //8 coefficients at 0x0f, 0x1f, ... 0x7f - }; - - //voice registers - enum voice_reg_t { - v_voll = 0x00, v_volr = 0x01, - v_pitchl = 0x02, v_pitchh = 0x03, - v_srcn = 0x04, v_adsr0 = 0x05, - v_adsr1 = 0x06, v_gain = 0x07, - v_envx = 0x08, v_outx = 0x09, - }; - - //internal envelope modes - enum env_mode_t { env_release, env_attack, env_decay, env_sustain }; - - //internal constants - enum { echo_hist_size = 8 }; - enum { brr_buf_size = 12 }; - enum { brr_block_size = 9 }; - - //global state - struct state_t { - uint8 regs[128]; - - modulo_array echo_hist[2]; //echo history keeps most recent 8 samples - int echo_hist_pos; - - bool every_other_sample; //toggles every sample - int kon; //KON value when last checked - int noise; - int counter; - int echo_offset; //offset from ESA in echo buffer - int echo_length; //number of bytes that echo_offset will stop at - - //hidden registers also written to when main register is written to - int new_kon; - int endx_buf; - int envx_buf; - int outx_buf; - - //temporary state between clocks - - //read once per sample - int t_pmon; - int t_non; - int t_eon; - int t_dir; - int t_koff; - - //read a few clocks ahead before used - int t_brr_next_addr; - int t_adsr0; - int t_brr_header; - int t_brr_byte; - int t_srcn; - int t_esa; - int t_echo_disabled; - - //internal state that is recalculated every sample - int t_dir_addr; - int t_pitch; - int t_output; - int t_looped; - int t_echo_ptr; - - //left/right sums - int t_main_out[2]; - int t_echo_out[2]; - int t_echo_in [2]; - } state; - - //voice state - struct voice_t { - modulo_array buffer; //decoded samples - int buf_pos; //place in buffer where next samples will be decoded - int interp_pos; //relative fractional position in sample (0x1000 = 1.0) - int brr_addr; //address of current BRR block - int brr_offset; //current decoding offset in BRR block - int vbit; //bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc - int vidx; //voice channel register index: 0x00 for voice 0, 0x10 for voice 1, etc - int kon_delay; //KON delay/current setup phase - int env_mode; - int env; //current envelope level - int t_envx_out; - int hidden_env; //used by GAIN mode 7, very obscure quirk - } voice[8]; - - //gaussian - static const int16 gaussian_table[512]; - int gaussian_interpolate(const voice_t &v); - - //counter - enum { counter_range = 2048 * 5 * 3 }; //30720 (0x7800) - static const uint16 counter_rate[32]; - static const uint16 counter_offset[32]; - void counter_tick(); - bool counter_poll(unsigned rate); - - //envelope - void envelope_run(voice_t &v); - - //brr - void brr_decode(voice_t &v); - - //misc - void misc_27(); - void misc_28(); - void misc_29(); - void misc_30(); - - //voice - void voice_output(voice_t &v, bool channel); - void voice_1 (voice_t &v); - void voice_2 (voice_t &v); - void voice_3 (voice_t &v); - void voice_3a(voice_t &v); - void voice_3b(voice_t &v); - void voice_3c(voice_t &v); - void voice_4 (voice_t &v); - void voice_5 (voice_t &v); - void voice_6 (voice_t &v); - void voice_7 (voice_t &v); - void voice_8 (voice_t &v); - void voice_9 (voice_t &v); - - //echo - int calc_fir(int i, bool channel); - int echo_output(bool channel); - void echo_read(bool channel); - void echo_write(bool channel); - void echo_22(); - void echo_23(); - void echo_24(); - void echo_25(); - void echo_26(); - void echo_27(); - void echo_28(); - void echo_29(); - void echo_30(); - - //dsp - static void Enter(); - void tick(); -}; - -extern DSP dsp; diff --git a/waterbox/libsnes/bsnes/snes/dsp/echo.cpp b/waterbox/libsnes/bsnes/snes/dsp/echo.cpp deleted file mode 100644 index b80de85df6..0000000000 --- a/waterbox/libsnes/bsnes/snes/dsp/echo.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#ifdef DSP_CPP - -int DSP::calc_fir(int i, bool channel) { - int s = state.echo_hist[channel][state.echo_hist_pos + i + 1]; - return (s * (int8)REG(fir + i * 0x10)) >> 6; -} - -int DSP::echo_output(bool channel) { - int output = (int16)((state.t_main_out[channel] * (int8)REG(mvoll + channel * 0x10)) >> 7) - + (int16)((state.t_echo_in [channel] * (int8)REG(evoll + channel * 0x10)) >> 7); - return sclamp<16>(output); -} - -void DSP::echo_read(bool channel) { - unsigned addr = state.t_echo_ptr + channel * 2; - uint8 lo = smp.apuram[(uint16)(addr + 0)]; - uint8 hi = smp.apuram[(uint16)(addr + 1)]; - int s = (int16)((hi << 8) + lo); - state.echo_hist[channel].write(state.echo_hist_pos, s >> 1); -} - -void DSP::echo_write(bool channel) { - if(!(state.t_echo_disabled & 0x20)) { - unsigned addr = state.t_echo_ptr + channel * 2; - int s = state.t_echo_out[channel]; - smp.apuram[(uint16)(addr + 0)] = s; - smp.apuram[(uint16)(addr + 1)] = s >> 8; - } - - state.t_echo_out[channel] = 0; -} - -void DSP::echo_22() { - //history - state.echo_hist_pos++; - if(state.echo_hist_pos >= echo_hist_size) state.echo_hist_pos = 0; - - state.t_echo_ptr = (uint16)((state.t_esa << 8) + state.echo_offset); - echo_read(0); - - //FIR - int l = calc_fir(0, 0); - int r = calc_fir(0, 1); - - state.t_echo_in[0] = l; - state.t_echo_in[1] = r; -} - -void DSP::echo_23() { - int l = calc_fir(1, 0) + calc_fir(2, 0); - int r = calc_fir(1, 1) + calc_fir(2, 1); - - state.t_echo_in[0] += l; - state.t_echo_in[1] += r; - - echo_read(1); -} - -void DSP::echo_24() { - int l = calc_fir(3, 0) + calc_fir(4, 0) + calc_fir(5, 0); - int r = calc_fir(3, 1) + calc_fir(4, 1) + calc_fir(5, 1); - - state.t_echo_in[0] += l; - state.t_echo_in[1] += r; -} - -void DSP::echo_25() { - int l = state.t_echo_in[0] + calc_fir(6, 0); - int r = state.t_echo_in[1] + calc_fir(6, 1); - - l = (int16)l; - r = (int16)r; - - l += (int16)calc_fir(7, 0); - r += (int16)calc_fir(7, 1); - - state.t_echo_in[0] = sclamp<16>(l) & ~1; - state.t_echo_in[1] = sclamp<16>(r) & ~1; -} - -void DSP::echo_26() { - //left output volumes - //(save sample for next clock so we can output both together) - state.t_main_out[0] = echo_output(0); - - //echo feedback - int l = state.t_echo_out[0] + (int16)((state.t_echo_in[0] * (int8)REG(efb)) >> 7); - int r = state.t_echo_out[1] + (int16)((state.t_echo_in[1] * (int8)REG(efb)) >> 7); - - state.t_echo_out[0] = sclamp<16>(l) & ~1; - state.t_echo_out[1] = sclamp<16>(r) & ~1; -} - -void DSP::echo_27() { - //output - int outl = state.t_main_out[0]; - int outr = echo_output(1); - state.t_main_out[0] = 0; - state.t_main_out[1] = 0; - - //TODO: global muting isn't this simple - //(turns DAC on and off or something, causing small ~37-sample pulse when first muted) - if(REG(flg) & 0x40) { - outl = 0; - outr = 0; - } - - //output sample to DAC - audio.sample(outl, outr); -} - -void DSP::echo_28() { - state.t_echo_disabled = REG(flg); -} - -void DSP::echo_29() { - state.t_esa = REG(esa); - - if(!state.echo_offset) state.echo_length = (REG(edl) & 0x0f) << 11; - - state.echo_offset += 4; - if(state.echo_offset >= state.echo_length) state.echo_offset = 0; - - //write left echo - echo_write(0); - - state.t_echo_disabled = REG(flg); -} - -void DSP::echo_30() { - //write right echo - echo_write(1); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/dsp/envelope.cpp b/waterbox/libsnes/bsnes/snes/dsp/envelope.cpp deleted file mode 100644 index 9ae0d3e06e..0000000000 --- a/waterbox/libsnes/bsnes/snes/dsp/envelope.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifdef DSP_CPP - -void DSP::envelope_run(voice_t &v) { - int env = v.env; - - if(v.env_mode == env_release) { //60% - env -= 0x8; - if(env < 0) env = 0; - v.env = env; - return; - } - - int rate; - int env_data = VREG(adsr1); - if(state.t_adsr0 & 0x80) { //99% ADSR - if(v.env_mode >= env_decay) { //99% - env--; - env -= env >> 8; - rate = env_data & 0x1f; - if(v.env_mode == env_decay) { //1% - rate = ((state.t_adsr0 >> 3) & 0x0e) + 0x10; - } - } else { //env_attack - rate = ((state.t_adsr0 & 0x0f) << 1) + 1; - env += rate < 31 ? 0x20 : 0x400; - } - } else { //GAIN - env_data = VREG(gain); - int mode = env_data >> 5; - if(mode < 4) { //direct - env = env_data << 4; - rate = 31; - } else { - rate = env_data & 0x1f; - if(mode == 4) { //4: linear decrease - env -= 0x20; - } else if(mode < 6) { //5: exponential decrease - env--; - env -= env >> 8; - } else { //6, 7: linear increase - env += 0x20; - if(mode > 6 && (unsigned)v.hidden_env >= 0x600) { - env += 0x8 - 0x20; //7: two-slope linear increase - } - } - } - } - - //sustain level - if((env >> 8) == (env_data >> 5) && v.env_mode == env_decay) v.env_mode = env_sustain; - v.hidden_env = env; - - //unsigned cast because linear decrease underflowing also triggers this - if((unsigned)env > 0x7ff) { - env = (env < 0 ? 0 : 0x7ff); - if(v.env_mode == env_attack) v.env_mode = env_decay; - } - - if(counter_poll(rate) == true) v.env = env; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/dsp/gaussian.cpp b/waterbox/libsnes/bsnes/snes/dsp/gaussian.cpp deleted file mode 100644 index 80aed8ad8a..0000000000 --- a/waterbox/libsnes/bsnes/snes/dsp/gaussian.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#ifdef DSP_CPP - -const int16 DSP::gaussian_table[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, - 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, - 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, - 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17, - 18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 24, 24, 25, 26, 27, 27, - 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 36, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 58, 59, 60, 61, 62, 64, 65, 66, 67, 69, 70, 71, 73, 74, 76, 77, - 78, 80, 81, 83, 84, 86, 87, 89, 90, 92, 94, 95, 97, 99, 100, 102, - 104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132, - 134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168, - 171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210, - 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257, - 260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311, - 314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370, - 374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434, - 439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504, - 508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577, - 582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654, - 659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732, - 737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811, - 816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889, - 894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965, - 969, 974, 978, 983, 988, 992, 997, 1001, 1005, 1010, 1014, 1019, 1023, 1027, 1032, 1036, - 1040, 1045, 1049, 1053, 1057, 1061, 1066, 1070, 1074, 1078, 1082, 1086, 1090, 1094, 1098, 1102, - 1106, 1109, 1113, 1117, 1121, 1125, 1128, 1132, 1136, 1139, 1143, 1146, 1150, 1153, 1157, 1160, - 1164, 1167, 1170, 1174, 1177, 1180, 1183, 1186, 1190, 1193, 1196, 1199, 1202, 1205, 1207, 1210, - 1213, 1216, 1219, 1221, 1224, 1227, 1229, 1232, 1234, 1237, 1239, 1241, 1244, 1246, 1248, 1251, - 1253, 1255, 1257, 1259, 1261, 1263, 1265, 1267, 1269, 1270, 1272, 1274, 1275, 1277, 1279, 1280, - 1282, 1283, 1284, 1286, 1287, 1288, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1297, 1298, - 1299, 1300, 1300, 1301, 1302, 1302, 1303, 1303, 1303, 1304, 1304, 1304, 1304, 1304, 1305, 1305, -}; - -int DSP::gaussian_interpolate(const voice_t &v) { - //make pointers into gaussian table based on fractional position between samples - int offset = (v.interp_pos >> 4) & 0xff; - const int16 *fwd = gaussian_table + 255 - offset; - const int16 *rev = gaussian_table + offset; //mirror left half of gaussian table - - offset = v.buf_pos + (v.interp_pos >> 12); - int output; - output = (fwd[ 0] * v.buffer[offset + 0]) >> 11; - output += (fwd[256] * v.buffer[offset + 1]) >> 11; - output += (rev[256] * v.buffer[offset + 2]) >> 11; - output = (int16)output; - output += (rev[ 0] * v.buffer[offset + 3]) >> 11; - return sclamp<16>(output) & ~1; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/dsp/misc.cpp b/waterbox/libsnes/bsnes/snes/dsp/misc.cpp deleted file mode 100644 index 244fc51f87..0000000000 --- a/waterbox/libsnes/bsnes/snes/dsp/misc.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#ifdef DSP_CPP - -void DSP::misc_27() { - state.t_pmon = REG(pmon) & ~1; //voice 0 doesn't support PMON -} - -void DSP::misc_28() { - state.t_non = REG(non); - state.t_eon = REG(eon); - state.t_dir = REG(dir); -} - -void DSP::misc_29() { - state.every_other_sample ^= 1; - if(state.every_other_sample) { - state.new_kon &= ~state.kon; //clears KON 63 clocks after it was last read - } -} - -void DSP::misc_30() { - if(state.every_other_sample) { - state.kon = state.new_kon; - state.t_koff = REG(koff); - } - - counter_tick(); - - //noise - if(counter_poll(REG(flg) & 0x1f) == true) { - int feedback = (state.noise << 13) ^ (state.noise << 14); - state.noise = (feedback & 0x4000) ^ (state.noise >> 1); - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/dsp/voice.cpp b/waterbox/libsnes/bsnes/snes/dsp/voice.cpp deleted file mode 100644 index f4fcd8c060..0000000000 --- a/waterbox/libsnes/bsnes/snes/dsp/voice.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#ifdef DSP_CPP - -inline void DSP::voice_output(voice_t &v, bool channel) { - //apply left/right volume - int amp = (state.t_output * (int8)VREG(voll + channel)) >> 7; - - //add to output total - state.t_main_out[channel] += amp; - state.t_main_out[channel] = sclamp<16>(state.t_main_out[channel]); - - //optionally add to echo total - if(state.t_eon & v.vbit) { - state.t_echo_out[channel] += amp; - state.t_echo_out[channel] = sclamp<16>(state.t_echo_out[channel]); - } -} - -void DSP::voice_1(voice_t &v) { - state.t_dir_addr = (state.t_dir << 8) + (state.t_srcn << 2); - state.t_srcn = VREG(srcn); -} - -void DSP::voice_2(voice_t &v) { - //read sample pointer (ignored if not needed) - uint16 addr = state.t_dir_addr; - if(!v.kon_delay) addr += 2; - uint8 lo = smp.apuram[(uint16)(addr + 0)]; - uint8 hi = smp.apuram[(uint16)(addr + 1)]; - state.t_brr_next_addr = ((hi << 8) + lo); - - state.t_adsr0 = VREG(adsr0); - - //read pitch, spread over two clocks - state.t_pitch = VREG(pitchl); -} - -void DSP::voice_3(voice_t &v) { - voice_3a(v); - voice_3b(v); - voice_3c(v); -} - -void DSP::voice_3a(voice_t &v) { - state.t_pitch += (VREG(pitchh) & 0x3f) << 8; -} - -void DSP::voice_3b(voice_t &v) { - state.t_brr_byte = smp.apuram[(uint16)(v.brr_addr + v.brr_offset)]; - state.t_brr_header = smp.apuram[(uint16)(v.brr_addr)]; -} - -void DSP::voice_3c(voice_t &v) { - //pitch modulation using previous voice's output - - if(state.t_pmon & v.vbit) { - state.t_pitch += ((state.t_output >> 5) * state.t_pitch) >> 10; - } - - if(v.kon_delay) { - //get ready to start BRR decoding on next sample - if(v.kon_delay == 5) { - v.brr_addr = state.t_brr_next_addr; - v.brr_offset = 1; - v.buf_pos = 0; - state.t_brr_header = 0; //header is ignored on this sample - } - - //envelope is never run during KON - v.env = 0; - v.hidden_env = 0; - - //disable BRR decoding until last three samples - v.interp_pos = 0; - v.kon_delay--; - if(v.kon_delay & 3) v.interp_pos = 0x4000; - - //pitch is never added during KON - state.t_pitch = 0; - } - - //gaussian interpolation - int output = gaussian_interpolate(v); - - //noise - if(state.t_non & v.vbit) { - output = (int16)(state.noise << 1); - } - - //apply envelope - state.t_output = ((output * v.env) >> 11) & ~1; - v.t_envx_out = v.env >> 4; - - //immediate silence due to end of sample or soft reset - if(REG(flg) & 0x80 || (state.t_brr_header & 3) == 1) { - v.env_mode = env_release; - v.env = 0; - } - - if(state.every_other_sample) { - //KOFF - if(state.t_koff & v.vbit) { - v.env_mode = env_release; - } - - //KON - if(state.kon & v.vbit) { - v.kon_delay = 5; - v.env_mode = env_attack; - } - } - - //run envelope for next sample - if(!v.kon_delay) envelope_run(v); -} - -void DSP::voice_4(voice_t &v) { - //decode BRR - state.t_looped = 0; - if(v.interp_pos >= 0x4000) { - brr_decode(v); - v.brr_offset += 2; - if(v.brr_offset >= 9) { - //start decoding next BRR block - v.brr_addr = (uint16)(v.brr_addr + 9); - if(state.t_brr_header & 1) { - v.brr_addr = state.t_brr_next_addr; - state.t_looped = v.vbit; - } - v.brr_offset = 1; - } - } - - //apply pitch - v.interp_pos = (v.interp_pos & 0x3fff) + state.t_pitch; - - //keep from getting too far ahead (when using pitch modulation) - if(v.interp_pos > 0x7fff) v.interp_pos = 0x7fff; - - //output left - voice_output(v, 0); -} - -void DSP::voice_5(voice_t &v) { - //output right - voice_output(v, 1); - - //ENDX, OUTX and ENVX won't update if you wrote to them 1-2 clocks earlier - state.endx_buf = REG(endx) | state.t_looped; - - //clear bit in ENDX if KON just began - if(v.kon_delay == 5) state.endx_buf &= ~v.vbit; -} - -void DSP::voice_6(voice_t &v) { - state.outx_buf = state.t_output >> 8; -} - -void DSP::voice_7(voice_t &v) { - //update ENDX - REG(endx) = (uint8)state.endx_buf; - state.envx_buf = v.t_envx_out; -} - -void DSP::voice_8(voice_t &v) { - //update OUTX - VREG(outx) = (uint8)state.outx_buf; -} - -void DSP::voice_9(voice_t &v) { - //update ENVX - VREG(envx) = (uint8)state.envx_buf; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/interface/interface.cpp b/waterbox/libsnes/bsnes/snes/interface/interface.cpp deleted file mode 100644 index a117889cae..0000000000 --- a/waterbox/libsnes/bsnes/snes/interface/interface.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include - -namespace SNES { - -Interface::Interface() - : wanttrace(false) -{ -} - -void Interface::videoRefresh(const uint32_t *data, bool hires, bool interlace, bool overscan) { -} - -void Interface::audioSample(int16_t l_sample, int16_t r_sample) { -} - -int16_t Interface::inputPoll(bool port, Input::Device device, unsigned index, unsigned id) { - return 0; -} - -void Interface::inputNotify(int index) { -} - -void Interface::message(const string &text) { - print(text, "\n"); -} - -time_t Interface::currentTime() -{ - return time(0); -} - -time_t Interface::randomSeed() -{ - return time(0); -} - -int Interface::getBackdropColor() -{ - return -1; -} - -void Interface::cpuTrace(uint32_t which, const char *msg) { -} - -} diff --git a/waterbox/libsnes/bsnes/snes/interface/interface.hpp b/waterbox/libsnes/bsnes/snes/interface/interface.hpp deleted file mode 100644 index f8c152f8c1..0000000000 --- a/waterbox/libsnes/bsnes/snes/interface/interface.hpp +++ /dev/null @@ -1,38 +0,0 @@ - -#define TRACE_CPU 0 -#define TRACE_SMP 1 -#define TRACE_GB 2 - -#define TRACE_MASK_NONE (0) -#define TRACE_CPU_MASK (1<allocSharedMemory(name_, size_); } - -//MappedRAM - -void MappedRAM::reset() { - if(data_) { - /*if(name_) interface()->freeSharedMemory(data_); - else free(data_); - data_ = 0;*/ - abort(); - } - size_ = 0; - write_protect_ = false; -} - -void MappedRAM::map(uint8 *source, unsigned length) { - reset(); - data_ = source; - size_ = data_ ? length : 0; -} - -void MappedRAM::copy(const uint8 *data, unsigned size) { - if(!data_) { - size_ = (size & ~255) + ((bool)(size & 255) << 8); - if(name_) data_ = (uint8*)interface()->allocSharedMemory(name_, size_); - else data_ = new uint8[size_](); - } - memcpy(data_, data, min(size_, size)); -} - -void MappedRAM::write_protect(bool status) { write_protect_ = status; } -uint8* MappedRAM::data() { return data_; } -unsigned MappedRAM::size() const { return size_; } - -uint8 MappedRAM::read(unsigned addr) { return data_[addr]; } -void MappedRAM::write(unsigned addr, uint8 n) { if(!write_protect_) data_[addr] = n; } -const uint8& MappedRAM::operator[](unsigned addr) const { return data_[addr]; } -MappedRAM::MappedRAM(const char* name) : data_(0), size_(0), write_protect_(false), name_(name) {} - -//Bus - -uint8 Bus::read(unsigned addr) { - return reader[lookup[addr]](target[addr]); -} - -void Bus::write(unsigned addr, uint8 data) { - return writer[lookup[addr]](target[addr], data); -} diff --git a/waterbox/libsnes/bsnes/snes/memory/memory.cpp b/waterbox/libsnes/bsnes/snes/memory/memory.cpp deleted file mode 100644 index a2ced25c58..0000000000 --- a/waterbox/libsnes/bsnes/snes/memory/memory.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include - -#define MEMORY_CPP -namespace SNES { - -Bus bus; - -unsigned Bus::mirror(unsigned addr, unsigned size) { - unsigned base = 0; - if(size) { - unsigned mask = 1 << 23; - while(addr >= size) { - while(!(addr & mask)) mask >>= 1; - addr -= mask; - if(size > mask) { - size -= mask; - base += mask; - } - mask >>= 1; - } - base += addr; - } - return base; -} - -void Bus::map( - MapMode mode, - unsigned bank_lo, unsigned bank_hi, - unsigned addr_lo, unsigned addr_hi, - const function &rd, - const function &wr, - unsigned base, unsigned length -) { - assert(bank_lo <= bank_hi && bank_lo <= 0xff); - assert(addr_lo <= addr_hi && addr_lo <= 0xffff); - unsigned id = idcount++; - assert(id < 255); - reader[id] = rd; - writer[id] = wr; - - if(length == 0) length = (bank_hi - bank_lo + 1) * (addr_hi - addr_lo + 1); - - unsigned offset = 0; - for(unsigned bank = bank_lo; bank <= bank_hi; bank++) { - for(unsigned addr = addr_lo; addr <= addr_hi; addr++) { - unsigned destaddr = (bank << 16) | addr; - if(mode == MapMode::Linear) destaddr = mirror(base + offset++, length); - if(mode == MapMode::Shadow) destaddr = mirror(base + destaddr, length); - lookup[(bank << 16) | addr] = id; - target[(bank << 16) | addr] = destaddr; - } - } -} - -void Bus::map_reset() { - function reader = [](unsigned) { return cpu.regs.mdr; }; - function writer = [](unsigned, uint8) {}; - - idcount = 0; - map(MapMode::Direct, 0x00, 0xff, 0x0000, 0xffff, reader, writer); -} - -void Bus::map_xml() { - for(auto &m : cartridge.mapping) { - map(m.mode, m.banklo, m.bankhi, m.addrlo, m.addrhi, m.read, m.write, m.offset, m.size); - } -} - -Bus::Bus() { - lookup = (uint8*)alloc_sealed(16 * 1024 * 1024); - target = (uint32*)alloc_sealed(16 * 1024 * 1024 * sizeof(uint32)); -} - -Bus::~Bus() { -} - -} diff --git a/waterbox/libsnes/bsnes/snes/memory/memory.hpp b/waterbox/libsnes/bsnes/snes/memory/memory.hpp deleted file mode 100644 index 4fa706e115..0000000000 --- a/waterbox/libsnes/bsnes/snes/memory/memory.hpp +++ /dev/null @@ -1,80 +0,0 @@ -struct Memory { - virtual inline unsigned size() const; - virtual uint8 read(unsigned addr) = 0; - virtual void write(unsigned addr, uint8 data) = 0; -}; - -struct StaticRAM : Memory { - inline uint8* data(); - inline unsigned size() const; - - inline uint8 read(unsigned addr); - inline void write(unsigned addr, uint8 n); - inline uint8& operator[](unsigned addr); - inline const uint8& operator[](unsigned addr) const; - - inline StaticRAM(unsigned size, const char* name = NULL); - inline ~StaticRAM(); - - inline void init(); - -private: - uint8 *data_; - unsigned size_; - const char* name_; -}; - -struct MappedRAM : Memory { - inline void reset(); - inline void map(uint8*, unsigned); - inline void copy(const uint8*, unsigned); - - inline void write_protect(bool status); - inline uint8* data(); - inline unsigned size() const; - - inline uint8 read(unsigned addr); - inline void write(unsigned addr, uint8 n); - inline const uint8& operator[](unsigned addr) const; - inline MappedRAM(const char* name = NULL); - - inline void setName(const char* name) { name_ = name; } - -private: - uint8 *data_; - unsigned size_; - bool write_protect_; - const char* name_; -}; - -struct Bus { - unsigned mirror(unsigned addr, unsigned size); - - alwaysinline uint8 read(unsigned addr); - alwaysinline void write(unsigned addr, uint8 data); - - uint8 *lookup; - uint32 *target; - - unsigned idcount; - function reader[256]; - function writer[256]; - - enum class MapMode : unsigned { Direct, Linear, Shadow }; - void map( - MapMode mode, - unsigned bank_lo, unsigned bank_hi, - unsigned addr_lo, unsigned addr_hi, - const function &read, - const function &write, - unsigned base = 0, unsigned length = 0 - ); - - void map_reset(); - void map_xml(); - - Bus(); - ~Bus(); -}; - -extern Bus bus; diff --git a/waterbox/libsnes/bsnes/snes/ppu/background/background.cpp b/waterbox/libsnes/bsnes/snes/ppu/background/background.cpp deleted file mode 100644 index d989323b81..0000000000 --- a/waterbox/libsnes/bsnes/snes/ppu/background/background.cpp +++ /dev/null @@ -1,277 +0,0 @@ -#ifdef PPU_CPP - -#include "mode7.cpp" - -//V = 0, H = 0 -void PPU::Background::frame() { -} - -//H = 0 -void PPU::Background::scanline() { -} - -//H = 60 -void PPU::Background::begin() { - bool hires = (self.regs.bgmode == 5 || self.regs.bgmode == 6); - x = -7; - y = self.vcounter(); - - if(y == 1) { - mosaic.vcounter = regs.mosaic + 1; - mosaic.voffset = 1; - cache.hoffset = regs.hoffset; - cache.voffset = regs.voffset; - } else if(--mosaic.vcounter == 0) { - mosaic.vcounter = regs.mosaic + 1; - mosaic.voffset += regs.mosaic + 1; - cache.hoffset = regs.hoffset; - cache.voffset = regs.voffset; - } - - tile_counter = (7 - (cache.hoffset & 7)) << hires; - for(unsigned n = 0; n < 8; n++) data[n] = 0; - - mosaic.hcounter = regs.mosaic + 1; - mosaic.hoffset = 0; - - if(regs.mode == Mode::Mode7) return begin_mode7(); - if(regs.mosaic == 0) { - cache.hoffset = regs.hoffset; - cache.voffset = regs.voffset; - } -} - -void PPU::Background::get_tile() { - bool hires = (self.regs.bgmode == 5 || self.regs.bgmode == 6); - - 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); - - unsigned tile_height = (regs.tile_size == TileSize::Size8x8 ? 3 : 4); - unsigned tile_width = (!hires ? tile_height : 4); - - unsigned width = 256 << hires; - - unsigned hmask = (tile_height == 3 ? width : width << 1); - unsigned vmask = hmask; - if(regs.screen_size & 1) hmask <<= 1; - if(regs.screen_size & 2) vmask <<= 1; - hmask--; - vmask--; - - unsigned px = x << hires; - unsigned py = (regs.mosaic == 0 ? y : mosaic.voffset); - - unsigned hscroll = cache.hoffset; - unsigned vscroll = cache.voffset; - if(hires) { - hscroll <<= 1; - if(self.regs.interlace) py = (py << 1) + self.field(); - } - - unsigned hoffset = hscroll + px; - unsigned voffset = vscroll + py; - - if(self.regs.bgmode == 2 || self.regs.bgmode == 4 || self.regs.bgmode == 6) { - uint16 offset_x = (x + (hscroll & 7)); - - if(offset_x >= 8) { - unsigned hval = self.bg3.get_tile((offset_x - 8) + (self.bg3.cache.hoffset & ~7), self.bg3.cache.voffset + 0); - unsigned vval = self.bg3.get_tile((offset_x - 8) + (self.bg3.cache.hoffset & ~7), self.bg3.cache.voffset + 8); - unsigned valid_mask = (id == ID::BG1 ? 0x2000 : 0x4000); - - if(self.regs.bgmode == 4) { - if(hval & valid_mask) { - if((hval & 0x8000) == 0) { - hoffset = offset_x + (hval & ~7); - } else { - voffset = y + hval; - } - } - } else { - if(hval & valid_mask) hoffset = offset_x + (hval & ~7); - if(vval & valid_mask) voffset = y + vval; - } - } - } - - hoffset &= hmask; - voffset &= vmask; - - unsigned screen_x = (regs.screen_size & 1 ? 32 << 5 : 0); - unsigned screen_y = (regs.screen_size & 2 ? 32 << 5 : 0); - if(regs.screen_size == 3) screen_y <<= 1; - - unsigned tx = hoffset >> tile_width; - unsigned ty = voffset >> tile_height; - - uint16 offset = ((ty & 0x1f) << 5) + (tx & 0x1f); - if(tx & 0x20) offset += screen_x; - if(ty & 0x20) offset += screen_y; - - uint16 addr = regs.screen_addr + (offset << 1); - tile = (ppu.vram[addr + 0] << 0) + (ppu.vram[addr + 1] << 8); - bool mirror_y = tile & 0x8000; - bool mirror_x = tile & 0x4000; - priority = (tile & 0x2000 ? regs.priority1 : regs.priority0); - palette_number = (tile >> 10) & 7; - palette_index = palette_offset + (palette_number << palette_size); - - if(tile_width == 4 && (bool)(hoffset & 8) != mirror_x) tile += 1; - if(tile_height == 4 && (bool)(voffset & 8) != mirror_y) tile += 16; - uint16 character = ((tile & 0x03ff) + tiledata_index) & tile_mask; - - if(mirror_y) voffset ^= 7; - offset = (character << (4 + color_depth)) + ((voffset & 7) << 1); - - switch(regs.mode) { - case Mode::BPP8: - data[7] = ppu.vram[offset + 49]; - data[6] = ppu.vram[offset + 48]; - data[5] = ppu.vram[offset + 33]; - data[4] = ppu.vram[offset + 32]; - case Mode::BPP4: - data[3] = ppu.vram[offset + 17]; - data[2] = ppu.vram[offset + 16]; - case Mode::BPP2: - data[1] = ppu.vram[offset + 1]; - data[0] = ppu.vram[offset + 0]; - } - - if(mirror_x) for(unsigned n = 0; n < 8; n++) { - //reverse data bits in data[n]: 01234567 -> 76543210 - data[n] = ((data[n] >> 4) & 0x0f) | ((data[n] << 4) & 0xf0); - data[n] = ((data[n] >> 2) & 0x33) | ((data[n] << 2) & 0xcc); - data[n] = ((data[n] >> 1) & 0x55) | ((data[n] << 1) & 0xaa); - } -} - -void PPU::Background::run(bool screen) { - if(self.vcounter() == 0) return; - bool hires = (self.regs.bgmode == 5 || self.regs.bgmode == 6); - - if(screen == Screen::Sub) { - output.main.priority = 0; - output.sub.priority = 0; - if(hires == false) return; - } - - if(regs.mode == Mode::Inactive) return; - if(regs.mode == Mode::Mode7) return run_mode7(); - - if(tile_counter-- == 0) { - tile_counter = 7; - get_tile(); - } - - uint8 palette = get_tile_color(); - if(x == 0) mosaic.hcounter = 1; - if(x >= 0 && --mosaic.hcounter == 0) { - mosaic.hcounter = regs.mosaic + 1; - mosaic.priority = priority; - mosaic.palette = palette ? palette_index + palette : 0; - mosaic.tile = tile; - } - if(screen == Screen::Main) x++; - if(mosaic.palette == 0) return; - - if(hires == false || screen == Screen::Main) if(regs.main_enable) output.main = mosaic; - if(hires == false || screen == Screen::Sub ) if(regs.sub_enable ) output.sub = mosaic; -} - -unsigned PPU::Background::get_tile_color() { - unsigned color = 0; - - switch(regs.mode) { - case Mode::BPP8: - color += (data[7] >> 0) & 0x80; data[7] <<= 1; - color += (data[6] >> 1) & 0x40; data[6] <<= 1; - color += (data[5] >> 2) & 0x20; data[5] <<= 1; - color += (data[4] >> 3) & 0x10; data[4] <<= 1; - case Mode::BPP4: - color += (data[3] >> 4) & 0x08; data[3] <<= 1; - color += (data[2] >> 5) & 0x04; data[2] <<= 1; - case Mode::BPP2: - color += (data[1] >> 6) & 0x02; data[1] <<= 1; - color += (data[0] >> 7) & 0x01; data[0] <<= 1; - } - - return color; -} - -void PPU::Background::reset() { - regs.tiledata_addr = (random(0x0000) & 0x07) << 13; - regs.screen_addr = (random(0x0000) & 0x7c) << 9; - regs.screen_size = random(0); - regs.mosaic = random(0); - regs.tile_size = random(0); - regs.mode = 0; - regs.priority0 = 0; - regs.priority1 = 0; - regs.main_enable = random(0); - regs.sub_enable = random(0); - regs.hoffset = random(0x0000); - regs.voffset = random(0x0000); - - cache.hoffset = 0; - cache.voffset = 0; - - output.main.palette = 0; - output.main.priority = 0; - output.sub.palette = 0; - output.sub.priority = 0; - - mosaic.priority = 0; - mosaic.palette = 0; - mosaic.tile = 0; - - mosaic.vcounter = 0; - mosaic.voffset = 0; - mosaic.hcounter = 0; - mosaic.hoffset = 0; - - x = 0; - y = 0; - - tile_counter = 0; - tile = 0; - priority = 0; - palette_number = 0; - palette_index = 0; - for(unsigned n = 0; n < 8; n++) data[n] = 0; -} - -unsigned PPU::Background::get_tile(unsigned x, unsigned y) { - bool hires = (self.regs.bgmode == 5 || self.regs.bgmode == 6); - unsigned tile_height = (regs.tile_size == TileSize::Size8x8 ? 3 : 4); - unsigned tile_width = (!hires ? tile_height : 4); - unsigned width = (!hires ? 256 : 512); - 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_x = (regs.screen_size & 1 ? 32 << 5 : 0); - unsigned screen_y = (regs.screen_size & 2 ? 32 << 5 : 0); - if(regs.screen_size == 3) screen_y <<= 1; - - x = (x & mask_x) >> tile_width; - y = (y & mask_y) >> tile_height; - - uint16 offset = ((y & 0x1f) << 5) + (x & 0x1f); - if(x & 0x20) offset += screen_x; - if(y & 0x20) offset += screen_y; - - uint16 addr = regs.screen_addr + (offset << 1); - return (ppu.vram[addr + 0] << 0) + (ppu.vram[addr + 1] << 8); -} - -PPU::Background::Background(PPU &self, unsigned id) : self(self), id(id) { -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/ppu/background/background.hpp b/waterbox/libsnes/bsnes/snes/ppu/background/background.hpp deleted file mode 100644 index 080e37cb39..0000000000 --- a/waterbox/libsnes/bsnes/snes/ppu/background/background.hpp +++ /dev/null @@ -1,77 +0,0 @@ -struct Background { - 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 Screen { enum { Main, Sub }; }; - - struct Regs { - uint16 tiledata_addr; - uint16 screen_addr; - uint2 screen_size; - uint4 mosaic; - bool tile_size; - - unsigned mode; - unsigned priority0; - unsigned priority1; - - bool main_enable; - bool sub_enable; - - uint16 hoffset; - uint16 voffset; - } regs; - - struct Cache { - uint16 hoffset; - uint16 voffset; - } cache; - - struct Output { - struct Pixel { - unsigned priority; //0 = none (transparent) - uint8 palette; - uint16 tile; - } main, sub; - } output; - - struct Mosaic : Output::Pixel { - unsigned vcounter; - unsigned voffset; - unsigned hcounter; - unsigned hoffset; - } mosaic; - - struct { - signed x; - signed y; - - unsigned tile_counter; - unsigned tile; - unsigned priority; - unsigned palette_number; - unsigned palette_index; - uint8 data[8]; - }; - - void frame(); - void scanline(); - void begin(); - void run(bool screen); - void reset(); - - void get_tile(); - unsigned get_tile_color(); - unsigned get_tile(unsigned x, unsigned y); - signed clip(signed n); - void begin_mode7(); - void run_mode7(); - - Background(PPU &self, unsigned id); - - PPU &self; - friend class PPU; -}; diff --git a/waterbox/libsnes/bsnes/snes/ppu/background/mode7.cpp b/waterbox/libsnes/bsnes/snes/ppu/background/mode7.cpp deleted file mode 100644 index bb63064791..0000000000 --- a/waterbox/libsnes/bsnes/snes/ppu/background/mode7.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#ifdef PPU_CPP - -signed PPU::Background::clip(signed n) { - //13-bit sign extend: --s---nnnnnnnnnn -> ssssssnnnnnnnnnn - return n & 0x2000 ? (n | ~1023) : (n & 1023); -} - -//H = 60 -void PPU::Background::begin_mode7() { - cache.hoffset = self.regs.mode7_hoffset; - cache.voffset = self.regs.mode7_voffset; -} - -void PPU::Background::run_mode7() { - signed a = sclip<16>(self.regs.m7a); - signed b = sclip<16>(self.regs.m7b); - signed c = sclip<16>(self.regs.m7c); - signed d = sclip<16>(self.regs.m7d); - - signed cx = sclip<13>(self.regs.m7x); - signed cy = sclip<13>(self.regs.m7y); - signed hoffset = sclip<13>(cache.hoffset); - signed voffset = sclip<13>(cache.voffset); - - if(Background::x++ & ~255) return; - unsigned x = mosaic.hoffset; - unsigned y = self.bg1.mosaic.voffset; //BG2 vertical mosaic uses BG1 mosaic size - - if(--mosaic.hcounter == 0) { - mosaic.hcounter = regs.mosaic + 1; - mosaic.hoffset += regs.mosaic + 1; - } - - if(self.regs.mode7_hflip) x = 255 - x; - if(self.regs.mode7_vflip) y = 255 - y; - - signed psx = ((a * clip(hoffset - cx)) & ~63) + ((b * clip(voffset - cy)) & ~63) + ((b * y) & ~63) + (cx << 8); - signed psy = ((c * clip(hoffset - cx)) & ~63) + ((d * clip(voffset - cy)) & ~63) + ((d * y) & ~63) + (cy << 8); - - signed px = psx + (a * x); - signed py = psy + (c * x); - - //mask pseudo-FP bits - px >>= 8; - py >>= 8; - - unsigned tile; - unsigned palette; - switch(self.regs.mode7_repeat) { - //screen repetition outside of screen area - case 0: - case 1: { - px &= 1023; - py &= 1023; - tile = ppu.vram[((py >> 3) * 128 + (px >> 3)) << 1]; - palette = ppu.vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1]; - break; - } - - //palette color 0 outside of screen area - case 2: { - if((px | py) & ~1023) { - palette = 0; - } else { - px &= 1023; - py &= 1023; - tile = ppu.vram[((py >> 3) * 128 + (px >> 3)) << 1]; - palette = ppu.vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1]; - } - break; - } - - //character 0 repetition outside of screen area - case 3: { - if((px | py) & ~1023) { - tile = 0; - } else { - px &= 1023; - py &= 1023; - tile = ppu.vram[((py >> 3) * 128 + (px >> 3)) << 1]; - } - palette = ppu.vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1]; - break; - } - } - - unsigned priority; - if(id == ID::BG1) { - priority = regs.priority0; - } else if(id == ID::BG2) { - priority = (palette & 0x80 ? regs.priority1 : regs.priority0); - palette &= 0x7f; - } - - if(palette == 0) return; - - if(regs.main_enable) { - output.main.palette = palette; - output.main.priority = priority; - output.main.tile = 0; - } - - if(regs.sub_enable) { - output.sub.palette = palette; - output.sub.priority = priority; - output.sub.tile = 0; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/ppu/counter/counter-inline.hpp b/waterbox/libsnes/bsnes/snes/ppu/counter/counter-inline.hpp deleted file mode 100644 index 2c21b6d1dc..0000000000 --- a/waterbox/libsnes/bsnes/snes/ppu/counter/counter-inline.hpp +++ /dev/null @@ -1,85 +0,0 @@ -//this should only be called by CPU::PPUcounter::tick(); -//keeps track of previous counter positions in history table -void PPUcounter::tick() { - status.hcounter += 2; //increment by smallest unit of time - if(status.hcounter >= 1360 && status.hcounter == lineclocks()) { - status.hcounter = 0; - vcounter_tick(); - } - - history.index = (history.index + 1) & 2047; - history.field [history.index] = status.field; - history.vcounter[history.index] = status.vcounter; - history.hcounter[history.index] = status.hcounter; -} - -//this should only be called by PPU::PPUcounter::tick(n); -//allows stepping by more than the smallest unit of time -void PPUcounter::tick(unsigned clocks) { - status.hcounter += clocks; - if(status.hcounter >= lineclocks()) { - status.hcounter -= lineclocks(); - vcounter_tick(); - } -} - -//internal -void PPUcounter::vcounter_tick() { - if(++status.vcounter == 128) status.interlace = ppu.interlace(); - - if((system.region() == System::Region::NTSC && status.interlace == false && status.vcounter == 262) - || (system.region() == System::Region::NTSC && status.interlace == true && status.vcounter == 263) - || (system.region() == System::Region::NTSC && status.interlace == true && status.vcounter == 262 && status.field == 1) - || (system.region() == System::Region::PAL && status.interlace == false && status.vcounter == 312) - || (system.region() == System::Region::PAL && status.interlace == true && status.vcounter == 313) - || (system.region() == System::Region::PAL && status.interlace == true && status.vcounter == 312 && status.field == 1) - ) { - status.vcounter = 0; - status.field = !status.field; - } - if(scanline) scanline(); -} - -bool PPUcounter::field () const { return status.field; } -uint16 PPUcounter::vcounter() const { return status.vcounter; } -uint16 PPUcounter::hcounter() const { return status.hcounter; } - -bool PPUcounter::field (unsigned offset) const { return history.field [(history.index - (offset >> 1)) & 2047]; } -uint16 PPUcounter::vcounter(unsigned offset) const { return history.vcounter[(history.index - (offset >> 1)) & 2047]; } -uint16 PPUcounter::hcounter(unsigned offset) const { return history.hcounter[(history.index - (offset >> 1)) & 2047]; } - -//one PPU dot = 4 CPU clocks -// -//PPU dots 323 and 327 are 6 CPU clocks long. -//this does not apply to NTSC non-interlace scanline 240 on odd fields. this is -//because the PPU skips one dot to alter the color burst phase of the video signal. -// -//dot 323 range = { 1292, 1294, 1296 } -//dot 327 range = { 1310, 1312, 1314 } - -uint16 PPUcounter::hdot() const { - if(system.region() == System::Region::NTSC && status.interlace == false && vcounter() == 240 && field() == 1) { - return (hcounter() >> 2); - } else { - return (hcounter() - ((hcounter() > 1292) << 1) - ((hcounter() > 1310) << 1)) >> 2; - } -} - -uint16 PPUcounter::lineclocks() const { - if(system.region() == System::Region::NTSC && status.interlace == false && vcounter() == 240 && field() == 1) return 1360; - return 1364; -} - -void PPUcounter::reset() { - status.interlace = false; - status.field = 0; - status.vcounter = 0; - status.hcounter = 0; - history.index = 0; - - for(unsigned i = 0; i < 2048; i++) { - history.field [i] = 0; - history.vcounter[i] = 0; - history.hcounter[i] = 0; - } -} diff --git a/waterbox/libsnes/bsnes/snes/ppu/counter/counter.hpp b/waterbox/libsnes/bsnes/snes/ppu/counter/counter.hpp deleted file mode 100644 index f872d6b1b7..0000000000 --- a/waterbox/libsnes/bsnes/snes/ppu/counter/counter.hpp +++ /dev/null @@ -1,48 +0,0 @@ -//PPUcounter emulates the H/V latch counters of the S-PPU2. -// -//real hardware has the S-CPU maintain its own copy of these counters that are -//updated based on the state of the S-PPU Vblank and Hblank pins. emulating this -//would require full lock-step synchronization for every clock tick. -//to bypass this and allow the two to run out-of-order, both the CPU and PPU -//classes inherit PPUcounter and keep their own counters. -//the timers are kept in sync, as the only differences occur on V=240 and V=261, -//based on interlace. thus, we need only synchronize and fetch interlace at any -//point before this in the frame, which is handled internally by this class at -//V=128. - -class PPUcounter { -public: - alwaysinline void tick(); - alwaysinline void tick(unsigned clocks); - - alwaysinline bool field () const; - alwaysinline uint16 vcounter() const; - alwaysinline uint16 hcounter() const; - inline uint16 hdot() const; - inline uint16 lineclocks() const; - - alwaysinline bool field (unsigned offset) const; - alwaysinline uint16 vcounter(unsigned offset) const; - alwaysinline uint16 hcounter(unsigned offset) const; - - inline void reset(); - function scanline; - -private: - inline void vcounter_tick(); - - struct { - bool interlace; - bool field; - uint16 vcounter; - uint16 hcounter; - } status; - - struct { - bool field[2048]; - uint16 vcounter[2048]; - uint16 hcounter[2048]; - - int32 index; - } history; -}; diff --git a/waterbox/libsnes/bsnes/snes/ppu/mmio/mmio.cpp b/waterbox/libsnes/bsnes/snes/ppu/mmio/mmio.cpp deleted file mode 100644 index 39b25c2049..0000000000 --- a/waterbox/libsnes/bsnes/snes/ppu/mmio/mmio.cpp +++ /dev/null @@ -1,894 +0,0 @@ -#ifdef PPU_CPP - -bool PPU::interlace() const { - return display.interlace; -} - -bool PPU::overscan() const { - return display.overscan; -} - -bool PPU::hires() const { - return true; -} - -void PPU::latch_counters() { - cpu.synchronize_ppu(); - regs.hcounter = hdot(); - regs.vcounter = vcounter(); - regs.counters_latched = true; -} - -uint16 PPU::get_vram_address() { - uint16 addr = regs.vram_addr; - switch(regs.vram_mapping) { - case 0: break; //direct mapping - case 1: addr = (addr & 0xff00) | ((addr & 0x001f) << 3) | ((addr >> 5) & 7); break; - case 2: addr = (addr & 0xfe00) | ((addr & 0x003f) << 3) | ((addr >> 6) & 7); break; - case 3: addr = (addr & 0xfc00) | ((addr & 0x007f) << 3) | ((addr >> 7) & 7); break; - } - return (addr << 1); -} - -uint8 PPU::vram_read(unsigned addr) { - debugger.vram_read(addr); - - if(regs.display_disable || vcounter() >= (!regs.overscan ? 225 : 240)) { - return vram[addr]; - } - return 0x00; -} - -void PPU::vram_write(unsigned addr, uint8 data) { - debugger.vram_write(addr, data); - - if(regs.display_disable || vcounter() >= (!regs.overscan ? 225 : 240)) { - vram[addr] = data; - } -} - -uint8 PPU::oam_read(unsigned addr) { - debugger.oam_read(addr); - - return oam[addr]; -} - -void PPU::oam_write(unsigned addr, uint8 data) { - debugger.oam_write(addr, data); - - oam[addr] = data; - sprite.update(addr, data); -} - -uint8 PPU::cgram_read(unsigned addr) { - debugger.cgram_read(addr); - - return cgram[addr]; -} - -void PPU::cgram_write(unsigned addr, uint8 data) { - debugger.cgram_write(addr, data); - - cgram[addr] = data; -} - -void PPU::mmio_update_video_mode() { - 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; - sprite.regs.priority0 = 3; sprite.regs.priority1 = 6; sprite.regs.priority2 = 9; sprite.regs.priority3 = 12; - } 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; - sprite.regs.priority0 = 2; sprite.regs.priority1 = 3; sprite.regs.priority2 = 6; sprite.regs.priority3 = 9; - } 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; - sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 7; sprite.regs.priority3 = 10; - } - } 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; - sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8; - } 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; - sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8; - } 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; - sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8; - } 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; - sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8; - } 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; - sprite.regs.priority0 = 1; sprite.regs.priority1 = 3; sprite.regs.priority2 = 4; sprite.regs.priority3 = 6; - } break; - - case 7: { - if(regs.mode7_extbg == false) { - bg1.regs.mode = Background::Mode::Mode7; - 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 = 2; - sprite.regs.priority0 = 1; sprite.regs.priority1 = 3; sprite.regs.priority2 = 4; sprite.regs.priority3 = 5; - } else { - bg1.regs.mode = Background::Mode::Mode7; - bg2.regs.mode = Background::Mode::Mode7; - bg3.regs.mode = Background::Mode::Inactive; - bg4.regs.mode = Background::Mode::Inactive; - bg1.regs.priority0 = 3; bg1.regs.priority1 = 3; - bg2.regs.priority0 = 1; bg2.regs.priority1 = 5; - sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 7; - } - } break; - } -} - -//INIDISP -void PPU::mmio_w2100(uint8 data) { - if(regs.display_disable && vcounter() == (!regs.overscan ? 225 : 240)) sprite.address_reset(); - regs.display_disable = data & 0x80; - regs.display_brightness = data & 0x0f; -} - -//OBSEL -void PPU::mmio_w2101(uint8 data) { - sprite.regs.base_size = (data >> 5) & 7; - sprite.regs.nameselect = (data >> 3) & 3; - sprite.regs.tiledata_addr = (data & 3) << 14; -} - -//OAMADDL -void PPU::mmio_w2102(uint8 data) { - regs.oam_baseaddr = (regs.oam_baseaddr & 0x0200) | (data << 1); - sprite.address_reset(); -} - -//OAMADDH -void PPU::mmio_w2103(uint8 data) { - regs.oam_priority = data & 0x80; - regs.oam_baseaddr = ((data & 0x01) << 9) | (regs.oam_baseaddr & 0x01fe); - sprite.address_reset(); -} - -//OAMDATA -void PPU::mmio_w2104(uint8 data) { - bool latch = regs.oam_addr & 1; - uint10 addr = regs.oam_addr++; - if(regs.display_disable == false && vcounter() < (!regs.overscan ? 225 : 240)) addr = regs.oam_iaddr; - if(addr & 0x0200) addr &= 0x021f; - - if(latch == 0) regs.oam_latchdata = data; - if(addr & 0x0200) { - oam_write(addr, data); - } else if(latch == 1) { - oam_write((addr & ~1) + 0, regs.oam_latchdata); - oam_write((addr & ~1) + 1, data); - } - sprite.set_first_sprite(); -} - -//BGMODE -void PPU::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); - mmio_update_video_mode(); -} - -//MOSAIC -void PPU::mmio_w2106(uint8 data) { - unsigned mosaic_size = (data >> 4) & 15; - bg4.regs.mosaic = (data & 0x08 ? mosaic_size : 0); - bg3.regs.mosaic = (data & 0x04 ? mosaic_size : 0); - bg2.regs.mosaic = (data & 0x02 ? mosaic_size : 0); - bg1.regs.mosaic = (data & 0x01 ? mosaic_size : 0); -} - -//BG1SC -void PPU::mmio_w2107(uint8 data) { - bg1.regs.screen_addr = (data & 0x7c) << 9; - bg1.regs.screen_size = data & 3; -} - -//BG2SC -void PPU::mmio_w2108(uint8 data) { - bg2.regs.screen_addr = (data & 0x7c) << 9; - bg2.regs.screen_size = data & 3; -} - -//BG3SC -void PPU::mmio_w2109(uint8 data) { - bg3.regs.screen_addr = (data & 0x7c) << 9; - bg3.regs.screen_size = data & 3; -} - -//BG4SC -void PPU::mmio_w210a(uint8 data) { - bg4.regs.screen_addr = (data & 0x7c) << 9; - bg4.regs.screen_size = data & 3; -} - -//BG12NBA -void PPU::mmio_w210b(uint8 data) { - bg1.regs.tiledata_addr = (data & 0x07) << 13; - bg2.regs.tiledata_addr = (data & 0x70) << 9; -} - -//BG34NBA -void PPU::mmio_w210c(uint8 data) { - bg3.regs.tiledata_addr = (data & 0x07) << 13; - bg4.regs.tiledata_addr = (data & 0x70) << 9; -} - -//BG1HOFS -void PPU::mmio_w210d(uint8 data) { - regs.mode7_hoffset = (data << 8) | regs.mode7_latchdata; - regs.mode7_latchdata = data; - - bg1.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg1.regs.hoffset >> 8) & 7); - regs.bgofs_latchdata = data; -} - -//BG1VOFS -void PPU::mmio_w210e(uint8 data) { - regs.mode7_voffset = (data << 8) | regs.mode7_latchdata; - regs.mode7_latchdata = data; - - bg1.regs.voffset = (data << 8) | regs.bgofs_latchdata; - regs.bgofs_latchdata = data; -} - -//BG2HOFS -void PPU::mmio_w210f(uint8 data) { - bg2.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg2.regs.hoffset >> 8) & 7); - regs.bgofs_latchdata = data; -} - -//BG2VOFS -void PPU::mmio_w2110(uint8 data) { - bg2.regs.voffset = (data << 8) | regs.bgofs_latchdata; - regs.bgofs_latchdata = data; -} - -//BG3HOFS -void PPU::mmio_w2111(uint8 data) { - bg3.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg3.regs.hoffset >> 8) & 7); - regs.bgofs_latchdata = data; -} - -//BG3VOFS -void PPU::mmio_w2112(uint8 data) { - bg3.regs.voffset = (data << 8) | regs.bgofs_latchdata; - regs.bgofs_latchdata = data; -} - -//BG4HOFS -void PPU::mmio_w2113(uint8 data) { - bg4.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg4.regs.hoffset >> 8) & 7); - regs.bgofs_latchdata = data; -} - -//BG4VOFS -void PPU::mmio_w2114(uint8 data) { - bg4.regs.voffset = (data << 8) | regs.bgofs_latchdata; - regs.bgofs_latchdata = data; -} - -//VMAIN -void PPU::mmio_w2115(uint8 data) { - regs.vram_incmode = data & 0x80; - regs.vram_mapping = (data >> 2) & 3; - switch(data & 3) { - case 0: regs.vram_incsize = 1; break; - case 1: regs.vram_incsize = 32; break; - case 2: regs.vram_incsize = 128; break; - case 3: regs.vram_incsize = 128; break; - } -} - -//VMADDL -void PPU::mmio_w2116(uint8 data) { - regs.vram_addr &= 0xff00; - regs.vram_addr |= (data << 0); - uint16 addr = get_vram_address(); - regs.vram_readbuffer = vram_read(addr + 0) << 0; - regs.vram_readbuffer |= vram_read(addr + 1) << 8; -} - -//VMADDH -void PPU::mmio_w2117(uint8 data) { - regs.vram_addr &= 0x00ff; - regs.vram_addr |= (data << 8); - uint16 addr = get_vram_address(); - regs.vram_readbuffer = vram_read(addr + 0) << 0; - regs.vram_readbuffer |= vram_read(addr + 1) << 8; -} - -//VMDATAL -void PPU::mmio_w2118(uint8 data) { - uint16 addr = get_vram_address() + 0; - vram_write(addr, data); - if(regs.vram_incmode == 0) regs.vram_addr += regs.vram_incsize; -} - -//VMDATAH -void PPU::mmio_w2119(uint8 data) { - uint16 addr = get_vram_address() + 1; - vram_write(addr, data); - if(regs.vram_incmode == 1) regs.vram_addr += regs.vram_incsize; -} - -//M7SEL -void PPU::mmio_w211a(uint8 data) { - regs.mode7_repeat = (data >> 6) & 3; - regs.mode7_vflip = data & 0x02; - regs.mode7_hflip = data & 0x01; -} - -//M7A -void PPU::mmio_w211b(uint8 data) { - regs.m7a = (data << 8) | regs.mode7_latchdata; - regs.mode7_latchdata = data; -} - -//M7B -void PPU::mmio_w211c(uint8 data) { - regs.m7b = (data << 8) | regs.mode7_latchdata; - regs.mode7_latchdata = data; -} - -//M7C -void PPU::mmio_w211d(uint8 data) { - regs.m7c = (data << 8) | regs.mode7_latchdata; - regs.mode7_latchdata = data; -} - -//M7D -void PPU::mmio_w211e(uint8 data) { - regs.m7d = (data << 8) | regs.mode7_latchdata; - regs.mode7_latchdata = data; -} - -//M7X -void PPU::mmio_w211f(uint8 data) { - regs.m7x = (data << 8) | regs.mode7_latchdata; - regs.mode7_latchdata = data; -} - -//M7Y -void PPU::mmio_w2120(uint8 data) { - regs.m7y = (data << 8) | regs.mode7_latchdata; - regs.mode7_latchdata = data; -} - -//CGADD -void PPU::mmio_w2121(uint8 data) { - regs.cgram_addr = data << 1; -} - -//CGDATA -void PPU::mmio_w2122(uint8 data) { - bool latch = regs.cgram_addr & 1; - uint9 addr = regs.cgram_addr++; - if(regs.display_disable == false - && vcounter() > 0 && vcounter() < (!regs.overscan ? 225 : 240) - && hcounter() >= 88 && hcounter() < 1096 - ) addr = regs.cgram_iaddr; - - if(latch == 0) { - regs.cgram_latchdata = data; - } else { - cgram_write((addr & ~1) + 0, regs.cgram_latchdata); - cgram_write((addr & ~1) + 1, data & 0x7f); - } -} - -//W12SEL -void PPU::mmio_w2123(uint8 data) { - window.regs.bg2_two_enable = data & 0x80; - window.regs.bg2_two_invert = data & 0x40; - window.regs.bg2_one_enable = data & 0x20; - window.regs.bg2_one_invert = data & 0x10; - window.regs.bg1_two_enable = data & 0x08; - window.regs.bg1_two_invert = data & 0x04; - window.regs.bg1_one_enable = data & 0x02; - window.regs.bg1_one_invert = data & 0x01; -} - -//W34SEL -void PPU::mmio_w2124(uint8 data) { - window.regs.bg4_two_enable = data & 0x80; - window.regs.bg4_two_invert = data & 0x40; - window.regs.bg4_one_enable = data & 0x20; - window.regs.bg4_one_invert = data & 0x10; - window.regs.bg3_two_enable = data & 0x08; - window.regs.bg3_two_invert = data & 0x04; - window.regs.bg3_one_enable = data & 0x02; - window.regs.bg3_one_invert = data & 0x01; -} - -//WOBJSEL -void PPU::mmio_w2125(uint8 data) { - window.regs.col_two_enable = data & 0x80; - window.regs.col_two_invert = data & 0x40; - window.regs.col_one_enable = data & 0x20; - window.regs.col_one_invert = data & 0x10; - window.regs.oam_two_enable = data & 0x08; - window.regs.oam_two_invert = data & 0x04; - window.regs.oam_one_enable = data & 0x02; - window.regs.oam_one_invert = data & 0x01; -} - -//WH0 -void PPU::mmio_w2126(uint8 data) { - window.regs.one_left = data; -} - -//WH1 -void PPU::mmio_w2127(uint8 data) { - window.regs.one_right = data; -} - -//WH2 -void PPU::mmio_w2128(uint8 data) { - window.regs.two_left = data; -} - -//WH3 -void PPU::mmio_w2129(uint8 data) { - window.regs.two_right = data; -} - -//WBGLOG -void PPU::mmio_w212a(uint8 data) { - window.regs.bg4_mask = (data >> 6) & 3; - window.regs.bg3_mask = (data >> 4) & 3; - window.regs.bg2_mask = (data >> 2) & 3; - window.regs.bg1_mask = (data >> 0) & 3; -} - -//WOBJLOG -void PPU::mmio_w212b(uint8 data) { - window.regs.col_mask = (data >> 2) & 3; - window.regs.oam_mask = (data >> 0) & 3; -} - -//TM -void PPU::mmio_w212c(uint8 data) { - sprite.regs.main_enable = data & 0x10; - bg4.regs.main_enable = data & 0x08; - bg3.regs.main_enable = data & 0x04; - bg2.regs.main_enable = data & 0x02; - bg1.regs.main_enable = data & 0x01; -} - -//TS -void PPU::mmio_w212d(uint8 data) { - sprite.regs.sub_enable = data & 0x10; - bg4.regs.sub_enable = data & 0x08; - bg3.regs.sub_enable = data & 0x04; - bg2.regs.sub_enable = data & 0x02; - bg1.regs.sub_enable = data & 0x01; -} - -//TMW -void PPU::mmio_w212e(uint8 data) { - window.regs.oam_main_enable = data & 0x10; - window.regs.bg4_main_enable = data & 0x08; - window.regs.bg3_main_enable = data & 0x04; - window.regs.bg2_main_enable = data & 0x02; - window.regs.bg1_main_enable = data & 0x01; -} - -//TSW -void PPU::mmio_w212f(uint8 data) { - window.regs.oam_sub_enable = data & 0x10; - window.regs.bg4_sub_enable = data & 0x08; - window.regs.bg3_sub_enable = data & 0x04; - window.regs.bg2_sub_enable = data & 0x02; - window.regs.bg1_sub_enable = data & 0x01; -} - -//CGWSEL -void PPU::mmio_w2130(uint8 data) { - window.regs.col_main_mask = (data >> 6) & 3; - window.regs.col_sub_mask = (data >> 4) & 3; - screen.regs.addsub_mode = data & 0x02; - screen.regs.direct_color = data & 0x01; -} - -//CGADDSUB -void PPU::mmio_w2131(uint8 data) { - screen.regs.color_mode = data & 0x80; - screen.regs.color_halve = data & 0x40; - screen.regs.back_color_enable = data & 0x20; - screen.regs.oam_color_enable = data & 0x10; - screen.regs.bg4_color_enable = data & 0x08; - screen.regs.bg3_color_enable = data & 0x04; - screen.regs.bg2_color_enable = data & 0x02; - screen.regs.bg1_color_enable = data & 0x01; -} - -//COLDATA -void PPU::mmio_w2132(uint8 data) { - if(data & 0x80) screen.regs.color_b = data & 0x1f; - if(data & 0x40) screen.regs.color_g = data & 0x1f; - if(data & 0x20) screen.regs.color_r = data & 0x1f; -} - -//SETINI -void PPU::mmio_w2133(uint8 data) { - regs.mode7_extbg = data & 0x40; - regs.pseudo_hires = data & 0x08; - regs.overscan = data & 0x04; - sprite.regs.interlace = data & 0x02; - regs.interlace = data & 0x01; - mmio_update_video_mode(); -} - -//MPYL -uint8 PPU::mmio_r2134() { - unsigned result = ((int16)regs.m7a * (int8)(regs.m7b >> 8)); - regs.ppu1_mdr = (result >> 0); - return regs.ppu1_mdr; -} - -//MPYM -uint8 PPU::mmio_r2135() { - unsigned result = ((int16)regs.m7a * (int8)(regs.m7b >> 8)); - regs.ppu1_mdr = (result >> 8); - return regs.ppu1_mdr; -} - -//MPYH -uint8 PPU::mmio_r2136() { - unsigned result = ((int16)regs.m7a * (int8)(regs.m7b >> 8)); - regs.ppu1_mdr = (result >> 16); - return regs.ppu1_mdr; -} - -//SLHV -uint8 PPU::mmio_r2137() { - if(cpu.pio() & 0x80) latch_counters(); - return cpu.regs.mdr; -} - -//OAMDATAREAD -uint8 PPU::mmio_r2138() { - uint10 addr = regs.oam_addr++; - if(regs.display_disable == false && vcounter() < (!regs.overscan ? 225 : 240)) addr = regs.oam_iaddr; - if(addr & 0x0200) addr &= 0x021f; - - regs.ppu1_mdr = oam_read(addr); - sprite.set_first_sprite(); - return regs.ppu1_mdr; -} - -//VMDATALREAD -uint8 PPU::mmio_r2139() { - uint16 addr = get_vram_address() + 0; - regs.ppu1_mdr = regs.vram_readbuffer >> 0; - if(regs.vram_incmode == 0) { - addr &= ~1; - regs.vram_readbuffer = vram_read(addr + 0) << 0; - regs.vram_readbuffer |= vram_read(addr + 1) << 8; - regs.vram_addr += regs.vram_incsize; - } - return regs.ppu1_mdr; -} - -//VMDATAHREAD -uint8 PPU::mmio_r213a() { - uint16 addr = get_vram_address() + 1; - regs.ppu1_mdr = regs.vram_readbuffer >> 8; - if(regs.vram_incmode == 1) { - addr &= ~1; - regs.vram_readbuffer = vram_read(addr + 0) << 0; - regs.vram_readbuffer |= vram_read(addr + 1) << 8; - regs.vram_addr += regs.vram_incsize; - } - return regs.ppu1_mdr; -} - -//CGDATAREAD -uint8 PPU::mmio_r213b() { - bool latch = regs.cgram_addr & 1; - uint9 addr = regs.cgram_addr++; - if(regs.display_disable == false - && vcounter() > 0 && vcounter() < (!regs.overscan ? 225 : 240) - && hcounter() >= 88 && hcounter() < 1096 - ) addr = regs.cgram_iaddr; - - if(latch == 0) { - regs.ppu2_mdr = cgram_read(addr); - } else { - regs.ppu2_mdr &= 0x80; - regs.ppu2_mdr |= cgram_read(addr); - } - return regs.ppu2_mdr; -} - -//OPHCT -uint8 PPU::mmio_r213c() { - if(regs.latch_hcounter == 0) { - regs.ppu2_mdr = (regs.hcounter >> 0); - } else { - regs.ppu2_mdr &= 0xfe; - regs.ppu2_mdr |= (regs.hcounter >> 8) & 1; - } - regs.latch_hcounter ^= 1; - return regs.ppu2_mdr; -} - -//OPVCT -uint8 PPU::mmio_r213d() { - if(regs.latch_vcounter == 0) { - regs.ppu2_mdr = (regs.vcounter >> 0); - } else { - regs.ppu2_mdr &= 0xfe; - regs.ppu2_mdr |= (regs.vcounter >> 8) & 1; - } - regs.latch_vcounter ^= 1; - return regs.ppu2_mdr; -} - -//STAT77 -uint8 PPU::mmio_r213e() { - regs.ppu1_mdr &= 0x10; - regs.ppu1_mdr |= sprite.regs.time_over << 7; - regs.ppu1_mdr |= sprite.regs.range_over << 6; - regs.ppu1_mdr |= ppu1_version & 0x0f; - return regs.ppu1_mdr; -} - -//STAT78 -uint8 PPU::mmio_r213f() { - regs.latch_hcounter = 0; - regs.latch_vcounter = 0; - - regs.ppu2_mdr &= 0x20; - regs.ppu2_mdr |= field() << 7; - if((cpu.pio() & 0x80) == 0) { - regs.ppu2_mdr |= 0x40; - } else if(regs.counters_latched) { - regs.ppu2_mdr |= 0x40; - regs.counters_latched = false; - } - regs.ppu2_mdr |= (system.region() == System::Region::NTSC ? 0 : 1) << 4; - regs.ppu2_mdr |= ppu2_version & 0x0f; - return regs.ppu2_mdr; -} - -void PPU::mmio_reset() { - regs.ppu1_mdr = random(0xff); - regs.ppu2_mdr = random(0xff); - - regs.vram_readbuffer = random(0x0000); - regs.oam_latchdata = random(0x00); - regs.cgram_latchdata = random(0x00); - regs.bgofs_latchdata = random(0x00); - regs.mode7_latchdata = random(0x00); - regs.counters_latched = false; - regs.latch_hcounter = 0; - regs.latch_vcounter = 0; - - regs.oam_iaddr = 0x0000; - regs.cgram_iaddr = 0x00; - - //$2100 INIDISP - regs.display_disable = true; - regs.display_brightness = 0; - - //$2102 OAMADDL - //$2103 OAMADDH - regs.oam_baseaddr = random(0x0000); - regs.oam_addr = random(0x0000); - regs.oam_priority = random(false); - - //$2105 BGMODE - regs.bg3_priority = false; - regs.bgmode = 0; - - //$210d BG1HOFS - regs.mode7_hoffset = random(0x0000); - - //$210e BG1VOFS - regs.mode7_voffset = random(0x0000); - - //$2115 VMAIN - regs.vram_incmode = random(1); - regs.vram_mapping = random(0); - regs.vram_incsize = 1; - - //$2116 VMADDL - //$2117 VMADDH - regs.vram_addr = random(0x0000); - - //$211a M7SEL - regs.mode7_repeat = random(0); - regs.mode7_vflip = random(false); - regs.mode7_hflip = random(false); - - //$211b M7A - regs.m7a = random(0x0000); - - //$211c M7B - regs.m7b = random(0x0000); - - //$211d M7C - regs.m7c = random(0x0000); - - //$211e M7D - regs.m7d = random(0x0000); - - //$211f M7X - regs.m7x = random(0x0000); - - //$2120 M7Y - regs.m7y = random(0x0000); - - //$2121 CGADD - regs.cgram_addr = random(0x0000); - - //$2133 SETINI - regs.mode7_extbg = random(false); - regs.pseudo_hires = random(false); - regs.overscan = false; - regs.interlace = false; - - //$213c OPHCT - regs.hcounter = 0; - - //$213d OPVCT - regs.vcounter = 0; -} - -uint8 PPU::mmio_read(unsigned addr) { - cpu.synchronize_ppu(); - - switch(addr & 0xffff) { - case 0x2104: - case 0x2105: - case 0x2106: - case 0x2108: - case 0x2109: - case 0x210a: - case 0x2114: - case 0x2115: - case 0x2116: - case 0x2118: - case 0x2119: - case 0x211a: - case 0x2124: - case 0x2125: - case 0x2126: - case 0x2128: - case 0x2129: - case 0x212a: return regs.ppu1_mdr; - case 0x2134: return mmio_r2134(); //MPYL - case 0x2135: return mmio_r2135(); //MPYM - case 0x2136: return mmio_r2136(); //MYPH - case 0x2137: return mmio_r2137(); //SLHV - case 0x2138: return mmio_r2138(); //OAMDATAREAD - case 0x2139: return mmio_r2139(); //VMDATALREAD - case 0x213a: return mmio_r213a(); //VMDATAHREAD - case 0x213b: return mmio_r213b(); //CGDATAREAD - case 0x213c: return mmio_r213c(); //OPHCT - case 0x213d: return mmio_r213d(); //OPVCT - case 0x213e: return mmio_r213e(); //STAT77 - case 0x213f: return mmio_r213f(); //STAT78 - } - - return cpu.regs.mdr; -} - -void PPU::mmio_write(unsigned addr, uint8 data) { - cpu.synchronize_ppu(); - - switch(addr & 0xffff) { - case 0x2100: return mmio_w2100(data); //INIDISP - case 0x2101: return mmio_w2101(data); //OBSEL - case 0x2102: return mmio_w2102(data); //OAMADDL - case 0x2103: return mmio_w2103(data); //OAMADDH - case 0x2104: return mmio_w2104(data); //OAMDATA - case 0x2105: return mmio_w2105(data); //BGMODE - case 0x2106: return mmio_w2106(data); //MOSAIC - case 0x2107: return mmio_w2107(data); //BG1SC - case 0x2108: return mmio_w2108(data); //BG2SC - case 0x2109: return mmio_w2109(data); //BG3SC - case 0x210a: return mmio_w210a(data); //BG4SC - case 0x210b: return mmio_w210b(data); //BG12NBA - case 0x210c: return mmio_w210c(data); //BG34NBA - case 0x210d: return mmio_w210d(data); //BG1HOFS - case 0x210e: return mmio_w210e(data); //BG1VOFS - case 0x210f: return mmio_w210f(data); //BG2HOFS - case 0x2110: return mmio_w2110(data); //BG2VOFS - case 0x2111: return mmio_w2111(data); //BG3HOFS - case 0x2112: return mmio_w2112(data); //BG3VOFS - case 0x2113: return mmio_w2113(data); //BG4HOFS - case 0x2114: return mmio_w2114(data); //BG4VOFS - case 0x2115: return mmio_w2115(data); //VMAIN - case 0x2116: return mmio_w2116(data); //VMADDL - case 0x2117: return mmio_w2117(data); //VMADDH - case 0x2118: return mmio_w2118(data); //VMDATAL - case 0x2119: return mmio_w2119(data); //VMDATAH - case 0x211a: return mmio_w211a(data); //M7SEL - case 0x211b: return mmio_w211b(data); //M7A - case 0x211c: return mmio_w211c(data); //M7B - case 0x211d: return mmio_w211d(data); //M7C - case 0x211e: return mmio_w211e(data); //M7D - case 0x211f: return mmio_w211f(data); //M7X - case 0x2120: return mmio_w2120(data); //M7Y - case 0x2121: return mmio_w2121(data); //CGADD - case 0x2122: return mmio_w2122(data); //CGDATA - case 0x2123: return mmio_w2123(data); //W12SEL - case 0x2124: return mmio_w2124(data); //W34SEL - case 0x2125: return mmio_w2125(data); //WOBJSEL - case 0x2126: return mmio_w2126(data); //WH0 - case 0x2127: return mmio_w2127(data); //WH1 - case 0x2128: return mmio_w2128(data); //WH2 - case 0x2129: return mmio_w2129(data); //WH3 - case 0x212a: return mmio_w212a(data); //WBGLOG - case 0x212b: return mmio_w212b(data); //WOBJLOG - case 0x212c: return mmio_w212c(data); //TM - case 0x212d: return mmio_w212d(data); //TS - case 0x212e: return mmio_w212e(data); //TMW - case 0x212f: return mmio_w212f(data); //TSW - case 0x2130: return mmio_w2130(data); //CGWSEL - case 0x2131: return mmio_w2131(data); //CGADDSUB - case 0x2132: return mmio_w2132(data); //COLDATA - case 0x2133: return mmio_w2133(data); //SETINI - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/ppu/mmio/mmio.hpp b/waterbox/libsnes/bsnes/snes/ppu/mmio/mmio.hpp deleted file mode 100644 index 7a30c3ebe6..0000000000 --- a/waterbox/libsnes/bsnes/snes/ppu/mmio/mmio.hpp +++ /dev/null @@ -1,165 +0,0 @@ -public: - uint8 mmio_read(unsigned addr); - void mmio_write(unsigned addr, uint8 data); -privileged: - -struct { - uint8 ppu1_mdr; - uint8 ppu2_mdr; - - uint16 vram_readbuffer; - uint8 oam_latchdata; - uint8 cgram_latchdata; - uint8 bgofs_latchdata; - uint8 mode7_latchdata; - bool counters_latched; - bool latch_hcounter; - bool latch_vcounter; - - uint10 oam_iaddr; - uint9 cgram_iaddr; - - //$2100 INIDISP - bool display_disable; - uint4 display_brightness; - - //$2102 OAMADDL - //$2103 OAMADDH - uint10 oam_baseaddr; - uint10 oam_addr; - bool oam_priority; - - //$2105 BGMODE - bool bg3_priority; - uint8 bgmode; - - //$210d BG1HOFS - uint16 mode7_hoffset; - - //$210e BG1VOFS - uint16 mode7_voffset; - - //$2115 VMAIN - bool vram_incmode; - uint2 vram_mapping; - uint8 vram_incsize; - - //$2116 VMADDL - //$2117 VMADDH - uint16 vram_addr; - - //$211a M7SEL - uint2 mode7_repeat; - bool mode7_vflip; - bool mode7_hflip; - - //$211b M7A - uint16 m7a; - - //$211c M7B - uint16 m7b; - - //$211d M7C - uint16 m7c; - - //$211e M7D - uint16 m7d; - - //$211f M7X - uint16 m7x; - - //$2120 M7Y - uint16 m7y; - - //$2121 CGADD - uint9 cgram_addr; - - //$2133 SETINI - bool mode7_extbg; - bool pseudo_hires; - bool overscan; - bool interlace; - - //$213c OPHCT - uint16 hcounter; - - //$213d OPVCT - uint16 vcounter; -} regs; - -uint16 get_vram_address(); -uint8 vram_read(unsigned addr); -void vram_write(unsigned addr, uint8 data); -uint8 oam_read(unsigned addr); -void oam_write(unsigned addr, uint8 data); -uint8 cgram_read(unsigned addr); -void cgram_write(unsigned addr, uint8 data); - -void mmio_update_video_mode(); - -void mmio_w2100(uint8); //INIDISP -void mmio_w2101(uint8); //OBSEL -void mmio_w2102(uint8); //OAMADDL -void mmio_w2103(uint8); //OAMADDH -void mmio_w2104(uint8); //OAMDATA -void mmio_w2105(uint8); //BGMODE -void mmio_w2106(uint8); //MOSAIC -void mmio_w2107(uint8); //BG1SC -void mmio_w2108(uint8); //BG2SC -void mmio_w2109(uint8); //BG3SC -void mmio_w210a(uint8); //BG4SC -void mmio_w210b(uint8); //BG12NBA -void mmio_w210c(uint8); //BG34NBA -void mmio_w210d(uint8); //BG1HOFS -void mmio_w210e(uint8); //BG1VOFS -void mmio_w210f(uint8); //BG2HOFS -void mmio_w2110(uint8); //BG2VOFS -void mmio_w2111(uint8); //BG3HOFS -void mmio_w2112(uint8); //BG3VOFS -void mmio_w2113(uint8); //BG4HOFS -void mmio_w2114(uint8); //BG4VOFS -void mmio_w2115(uint8); //VMAIN -void mmio_w2116(uint8); //VMADDL -void mmio_w2117(uint8); //VMADDH -void mmio_w2118(uint8); //VMDATAL -void mmio_w2119(uint8); //VMDATAH -void mmio_w211a(uint8); //M7SEL -void mmio_w211b(uint8); //M7A -void mmio_w211c(uint8); //M7B -void mmio_w211d(uint8); //M7C -void mmio_w211e(uint8); //M7D -void mmio_w211f(uint8); //M7X -void mmio_w2120(uint8); //M7Y -void mmio_w2121(uint8); //CGADD -void mmio_w2122(uint8); //CGDATA -void mmio_w2123(uint8); //W12SEL -void mmio_w2124(uint8); //W34SEL -void mmio_w2125(uint8); //WOBJSEL -void mmio_w2126(uint8); //WH0 -void mmio_w2127(uint8); //WH1 -void mmio_w2128(uint8); //WH2 -void mmio_w2129(uint8); //WH3 -void mmio_w212a(uint8); //WBGLOG -void mmio_w212b(uint8); //WOBJLOG -void mmio_w212c(uint8); //TM -void mmio_w212d(uint8); //TS -void mmio_w212e(uint8); //TMW -void mmio_w212f(uint8); //TSW -void mmio_w2130(uint8); //CGWSEL -void mmio_w2131(uint8); //CGADDSUB -void mmio_w2132(uint8); //COLDATA -void mmio_w2133(uint8); //SETINI -uint8 mmio_r2134(); //MPYL -uint8 mmio_r2135(); //MPYM -uint8 mmio_r2136(); //MPYH -uint8 mmio_r2137(); //SLHV -uint8 mmio_r2138(); //OAMDATAREAD -uint8 mmio_r2139(); //VMDATALREAD -uint8 mmio_r213a(); //VMDATAHREAD -uint8 mmio_r213b(); //CGDATAREAD -uint8 mmio_r213c(); //OPHCT -uint8 mmio_r213d(); //OPVCT -uint8 mmio_r213e(); //STAT77 -uint8 mmio_r213f(); //STAT78 - -void mmio_reset(); diff --git a/waterbox/libsnes/bsnes/snes/ppu/ppu.cpp b/waterbox/libsnes/bsnes/snes/ppu/ppu.cpp deleted file mode 100644 index f78373e557..0000000000 --- a/waterbox/libsnes/bsnes/snes/ppu/ppu.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#include - -#define PPU_CPP -namespace SNES { - -PPU ppu; - -#include "background/background.cpp" -#include "mmio/mmio.cpp" -#include "screen/screen.cpp" -#include "sprite/sprite.cpp" -#include "window/window.cpp" - -void PPU::step(unsigned clocks) { - clock += clocks; -} - -void PPU::synchronize_cpu() { - if(CPU::Threaded == true) { - if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); - } else { - while(clock >= 0) cpu.enter(); - } -} - -void PPU::Enter() { ppu.enter(); } - -void PPU::enter() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - scanline(); - add_clocks(68); - bg1.begin(); - bg2.begin(); - bg3.begin(); - bg4.begin(); - - if(vcounter() <= 239) { - for(signed pixel = -7; pixel <= 255; pixel++) { - bg1.run(1); - bg2.run(1); - bg3.run(1); - bg4.run(1); - add_clocks(2); - - bg1.run(0); - bg2.run(0); - bg3.run(0); - bg4.run(0); - if(pixel >= 0) { - sprite.run(); - window.run(); - screen.run(); - } - add_clocks(2); - } - - add_clocks(14); - sprite.tilefetch(); - } else { - add_clocks(1052 + 14 + 136); - } - - add_clocks(lineclocks() - 68 - 1052 - 14 - 136); - } -} - -void PPU::add_clocks(unsigned clocks) { - clocks >>= 1; - while(clocks--) { - tick(2); - step(2); - synchronize_cpu(); - } -} - -void PPU::enable() { - function read = { &PPU::mmio_read, (PPU*)&ppu }; - function write = { &PPU::mmio_write, (PPU*)&ppu }; - - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, read, write); - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, read, write); -} - -void PPU::power() { - ppu1_version = config.ppu1.version; - ppu2_version = config.ppu2.version; - - for(int i=0;i<128*1024;i++) vram[i] = 0; - for(int i=0;i<544;i++) oam[i] = 0; - for(int i=0;i<512;i++) cgram[i] = 0; - -//not sure about this -reset(); - -} - -void PPU::reset() { - create(Enter, system.cpu_frequency()); - PPUcounter::reset(); - memset(surface, 0, 512 * 512 * sizeof(uint32)); - - mmio_reset(); - bg1.reset(); - bg2.reset(); - bg3.reset(); - bg4.reset(); - sprite.reset(); - window.reset(); - screen.reset(); - - frame(); -} - -void PPU::scanline() { - if(vcounter() == 0) { - frame(); - bg1.frame(); - bg2.frame(); - bg3.frame(); - bg4.frame(); - } - - bg1.scanline(); - bg2.scanline(); - bg3.scanline(); - bg4.scanline(); - sprite.scanline(); - window.scanline(); - screen.scanline(); -} - -void PPU::frame() { - system.frame(); - sprite.frame(); - - display.interlace = regs.interlace; - display.overscan = regs.overscan; -} - -void PPU::layer_enable(unsigned layer, unsigned priority, bool enable) -{ - //TODO -} - -void PPU::initialize() -{ - vram = (uint8*)interface()->allocSharedMemory("VRAM",128 * 1024); - oam = (uint8*)interface()->allocSharedMemory("OAM",544); - cgram = (uint8*)interface()->allocSharedMemory("CGRAM",512); - surface = (uint32_t*)alloc_invisible(512 * 512 * sizeof(uint32_t)); - output = surface + 16 * 512; -} - -PPU::PPU() : -bg1(*this, Background::ID::BG1), -bg2(*this, Background::ID::BG2), -bg3(*this, Background::ID::BG3), -bg4(*this, Background::ID::BG4), -sprite(*this), -window(*this), -screen(*this) { - -} - -PPU::~PPU() { - abort(); -} - -} diff --git a/waterbox/libsnes/bsnes/snes/ppu/ppu.hpp b/waterbox/libsnes/bsnes/snes/ppu/ppu.hpp deleted file mode 100644 index d099251083..0000000000 --- a/waterbox/libsnes/bsnes/snes/ppu/ppu.hpp +++ /dev/null @@ -1,73 +0,0 @@ -struct PPU : public Processor, public PPUcounter { - uint8 *vram; //[64 * 1024]; - uint8 *oam; //[544]; - uint8 *cgram; //[512]; - - enum : bool { Threaded = true }; - alwaysinline void step(unsigned clocks); - alwaysinline void synchronize_cpu(); - - void latch_counters(); - bool interlace() const; - bool overscan() const; - bool hires() const; - - void enter(); - void enable(); - void power(); - void reset(); - void layer_enable(unsigned layer, unsigned priority, bool enable); - - void initialize(); - PPU(); - ~PPU(); - -privileged: - uint32 *surface; - uint32 *output; - - uint8 ppu1_version; - uint8 ppu2_version; - - struct { - bool interlace; - bool overscan; - } display; - - #include "background/background.hpp" - #include "mmio/mmio.hpp" - #include "screen/screen.hpp" - #include "sprite/sprite.hpp" - #include "window/window.hpp" - - Background bg1; - Background bg2; - Background bg3; - Background bg4; - Sprite sprite; - Window window; - Screen screen; - - static void Enter(); - void add_clocks(unsigned); - - void scanline(); - void frame(); - - friend class PPU::Background; - friend class PPU::Sprite; - friend class PPU::Window; - friend class PPU::Screen; - friend class Video; - - struct Debugger { - hook vram_read; - hook oam_read; - hook cgram_read; - hook vram_write; - hook oam_write; - hook cgram_write; - } debugger; -}; - -extern PPU ppu; diff --git a/waterbox/libsnes/bsnes/snes/ppu/screen/screen.cpp b/waterbox/libsnes/bsnes/snes/ppu/screen/screen.cpp deleted file mode 100644 index aaf0427f54..0000000000 --- a/waterbox/libsnes/bsnes/snes/ppu/screen/screen.cpp +++ /dev/null @@ -1,210 +0,0 @@ -#ifdef PPU_CPP - -void PPU::Screen::scanline() { - output = self.output + self.vcounter() * 1024; - if(self.display.interlace && self.field()) output += 512; -} - -void PPU::Screen::run() { - if(ppu.vcounter() == 0) return; - - uint32 color; - if(self.regs.pseudo_hires == false && self.regs.bgmode != 5 && self.regs.bgmode != 6) { - color = get_pixel(0); - *output++ = color; - *output++ = color; - } else { - color = get_pixel(1); - *output++ = color; - color = get_pixel(0); - *output++ = color; - } -} - -uint32 PPU::Screen::get_pixel(bool swap) { - if(ppu.regs.overscan == false && ppu.vcounter() >= 225) return 0x0000; - - enum source_t { BG1, BG2, BG3, BG4, OAM, BACK }; - bool color_enable[] = { regs.bg1_color_enable, regs.bg2_color_enable, regs.bg3_color_enable, regs.bg4_color_enable, regs.oam_color_enable, regs.back_color_enable }; - - //=========== - //main screen - //=========== - - unsigned priority_main = 0; - unsigned color_main; - unsigned source_main; - - if(self.bg1.output.main.priority) { - priority_main = self.bg1.output.main.priority; - if(regs.direct_color && (self.regs.bgmode == 3 || self.regs.bgmode == 4 || self.regs.bgmode == 7)) { - color_main = get_direct_color(self.bg1.output.main.palette, self.bg1.output.main.tile); - } else { - color_main = get_color(self.bg1.output.main.palette); - } - source_main = BG1; - } - if(self.bg2.output.main.priority > priority_main) { - priority_main = self.bg2.output.main.priority; - color_main = get_color(self.bg2.output.main.palette); - source_main = BG2; - } - if(self.bg3.output.main.priority > priority_main) { - priority_main = self.bg3.output.main.priority; - color_main = get_color(self.bg3.output.main.palette); - source_main = BG3; - } - if(self.bg4.output.main.priority > priority_main) { - priority_main = self.bg4.output.main.priority; - color_main = get_color(self.bg4.output.main.palette); - source_main = BG4; - } - if(self.sprite.output.main.priority > priority_main) { - priority_main = self.sprite.output.main.priority; - color_main = get_color(self.sprite.output.main.palette); - source_main = OAM; - } - if(priority_main == 0) { - color_main = get_color(0); - source_main = BACK; - } - - //========== - //sub screen - //========== - - unsigned priority_sub = 0; - unsigned color_sub; - unsigned source_sub; - - if(self.bg1.output.sub.priority) { - priority_sub = self.bg1.output.sub.priority; - if(regs.direct_color && (self.regs.bgmode == 3 || self.regs.bgmode == 4 || self.regs.bgmode == 7)) { - color_sub = get_direct_color(self.bg1.output.sub.palette, self.bg1.output.sub.tile); - } else { - color_sub = get_color(self.bg1.output.sub.palette); - } - source_sub = BG1; - } - if(self.bg2.output.sub.priority > priority_sub) { - priority_sub = self.bg2.output.sub.priority; - color_sub = get_color(self.bg2.output.sub.palette); - source_sub = BG2; - } - if(self.bg3.output.sub.priority > priority_sub) { - priority_sub = self.bg3.output.sub.priority; - color_sub = get_color(self.bg3.output.sub.palette); - source_sub = BG3; - } - if(self.bg4.output.sub.priority > priority_sub) { - priority_sub = self.bg4.output.sub.priority; - color_sub = get_color(self.bg4.output.sub.palette); - source_sub = BG4; - } - if(self.sprite.output.sub.priority > priority_sub) { - priority_sub = self.sprite.output.sub.priority; - color_sub = get_color(self.sprite.output.sub.palette); - source_sub = OAM; - } - if(priority_sub == 0) { - if(self.regs.pseudo_hires == true || self.regs.bgmode == 5 || self.regs.bgmode == 6) { - color_sub = get_color(0); - } else { - color_sub = (regs.color_b << 10) + (regs.color_g << 5) + (regs.color_r << 0); - } - source_sub = BACK; - } - - if(swap == true) { - std::swap(priority_main, priority_sub); - std::swap(color_main, color_sub); - std::swap(source_main, source_sub); - } - - uint16 output; - if(!regs.addsub_mode) { - source_sub = BACK; - color_sub = (regs.color_b << 10) + (regs.color_g << 5) + (regs.color_r << 0); - } - - if(self.window.output.main.color_enable == false) { - if(self.window.output.sub.color_enable == false) { - return 0x0000; - } - color_main = 0x0000; - } - - bool color_exempt = (source_main == OAM && self.sprite.output.main.palette < 192); - if(!color_exempt && color_enable[source_main] && self.window.output.sub.color_enable) { - bool halve = false; - if(regs.color_halve && self.window.output.main.color_enable) { - if(!regs.addsub_mode || source_sub != BACK) halve = true; - } - output = addsub(color_main, color_sub, halve); - } else { - output = color_main; - } - - //======== - //lighting - //======== - - if(self.regs.display_disable) return 0; - return (self.regs.display_brightness << 15) | output; -} - -uint16 PPU::Screen::addsub(unsigned x, unsigned y, bool halve) { - if(!regs.color_mode) { - if(!halve) { - unsigned sum = x + y; - unsigned carry = (sum - ((x ^ y) & 0x0421)) & 0x8420; - return (sum - carry) | (carry - (carry >> 5)); - } else { - return (x + y - ((x ^ y) & 0x0421)) >> 1; - } - } else { - unsigned diff = x - y + 0x8420; - unsigned borrow = (diff - ((x ^ y) & 0x8420)) & 0x8420; - if(!halve) { - return (diff - borrow) & (borrow - (borrow >> 5)); - } else { - return (((diff - borrow) & (borrow - (borrow >> 5))) & 0x7bde) >> 1; - } - } -} - -uint16 PPU::Screen::get_color(unsigned palette) { - palette <<= 1; - self.regs.cgram_iaddr = palette; - return ppu.cgram[palette + 0] + (ppu.cgram[palette + 1] << 8); -} - -uint16 PPU::Screen::get_direct_color(unsigned palette, unsigned tile) { - //palette = -------- BBGGGRRR - //tile = ---bgr-- -------- - //output = 0BBb00GG Gg0RRRr0 - return ((palette << 7) & 0x6000) + ((tile >> 0) & 0x1000) - + ((palette << 4) & 0x0380) + ((tile >> 5) & 0x0040) - + ((palette << 2) & 0x001c) + ((tile >> 9) & 0x0002); -} - -void PPU::Screen::reset() { - regs.addsub_mode = random(false); - regs.direct_color = random(false); - regs.color_mode = random(false); - regs.color_halve = random(false); - regs.bg1_color_enable = random(false); - regs.bg2_color_enable = random(false); - regs.bg3_color_enable = random(false); - regs.bg4_color_enable = random(false); - regs.oam_color_enable = random(false); - regs.back_color_enable = random(false); - regs.color_r = random(0); - regs.color_g = random(0); - regs.color_b = random(0); -} - -PPU::Screen::Screen(PPU &self) : self(self) { -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/ppu/screen/screen.hpp b/waterbox/libsnes/bsnes/snes/ppu/screen/screen.hpp deleted file mode 100644 index a194f7a5a4..0000000000 --- a/waterbox/libsnes/bsnes/snes/ppu/screen/screen.hpp +++ /dev/null @@ -1,35 +0,0 @@ -struct Screen { - uint32 *output; - - struct Regs { - bool addsub_mode; - bool direct_color; - - bool color_mode; - bool color_halve; - bool bg1_color_enable; - bool bg2_color_enable; - bool bg3_color_enable; - bool bg4_color_enable; - bool oam_color_enable; - bool back_color_enable; - - uint5 color_b; - uint5 color_g; - uint5 color_r; - } regs; - - void scanline(); - void run(); - void reset(); - - uint32 get_pixel(bool swap); - uint16 addsub(unsigned x, unsigned y, bool halve); - uint16 get_color(unsigned palette); - uint16 get_direct_color(unsigned palette, unsigned tile); - - Screen(PPU &self); - - PPU &self; - friend class PPU; -}; diff --git a/waterbox/libsnes/bsnes/snes/ppu/sprite/list.cpp b/waterbox/libsnes/bsnes/snes/ppu/sprite/list.cpp deleted file mode 100644 index ae684a7d33..0000000000 --- a/waterbox/libsnes/bsnes/snes/ppu/sprite/list.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#ifdef PPU_CPP - -void PPU::Sprite::update(unsigned addr, uint8 data) { - if(addr < 0x0200) { - unsigned n = addr >> 2; - addr &= 3; - if(addr == 0) { - list[n].x = (list[n].x & 0x100) | data; - } else if(addr == 1) { - list[n].y = data; - } else if(addr == 2) { - list[n].character = data; - } else { //(addr == 3) - list[n].vflip = data & 0x80; - list[n].hflip = data & 0x40; - list[n].priority = (data >> 4) & 3; - list[n].palette = (data >> 1) & 7; - list[n].nameselect = data & 1; - } - } else { - unsigned n = (addr & 0x1f) << 2; - list[n + 0].x = ((data & 0x01) << 8) | (list[n + 0].x & 0xff); - list[n + 0].size = data & 0x02; - list[n + 1].x = ((data & 0x04) << 6) | (list[n + 1].x & 0xff); - list[n + 1].size = data & 0x08; - list[n + 2].x = ((data & 0x10) << 4) | (list[n + 2].x & 0xff); - list[n + 2].size = data & 0x20; - list[n + 3].x = ((data & 0x40) << 2) | (list[n + 3].x & 0xff); - list[n + 3].size = data & 0x80; - } -} - -void PPU::Sprite::synchronize() { - for(unsigned n = 0; n < 544; n++) update(n, ppu.oam[n]); -} - -unsigned PPU::Sprite::SpriteItem::width() const { - if(size == 0) { - static unsigned width[] = { 8, 8, 8, 16, 16, 32, 16, 16 }; - return width[ppu.sprite.regs.base_size]; - } else { - static unsigned width[] = { 16, 32, 64, 32, 64, 64, 32, 32 }; - return width[ppu.sprite.regs.base_size]; - } -} - -unsigned PPU::Sprite::SpriteItem::height() const { - if(size == 0) { - if(ppu.sprite.regs.interlace && ppu.sprite.regs.base_size >= 6) return 16; - static unsigned height[] = { 8, 8, 8, 16, 16, 32, 32, 32 }; - return height[ppu.sprite.regs.base_size]; - } else { - static unsigned height[] = { 16, 32, 64, 32, 64, 64, 64, 32 }; - return height[ppu.sprite.regs.base_size]; - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/ppu/sprite/sprite.cpp b/waterbox/libsnes/bsnes/snes/ppu/sprite/sprite.cpp deleted file mode 100644 index 66c71103f7..0000000000 --- a/waterbox/libsnes/bsnes/snes/ppu/sprite/sprite.cpp +++ /dev/null @@ -1,223 +0,0 @@ -#ifdef PPU_CPP - -#include "list.cpp" - -void PPU::Sprite::address_reset() { - self.regs.oam_addr = self.regs.oam_baseaddr; - set_first_sprite(); -} - -void PPU::Sprite::set_first_sprite() { - regs.first_sprite = (self.regs.oam_priority == false ? 0 : (self.regs.oam_addr >> 2) & 127); -} - -void PPU::Sprite::frame() { - regs.time_over = false; - regs.range_over = false; -} - -void PPU::Sprite::scanline() { - t.x = 0; - t.y = self.vcounter(); - - t.item_count = 0; - t.tile_count = 0; - - t.active = !t.active; - auto oam_item = t.item[t.active]; - auto oam_tile = t.tile[t.active]; - - if(t.y == (!self.regs.overscan ? 225 : 240) && self.regs.display_disable == false) address_reset(); - if(t.y >= (!self.regs.overscan ? 224 : 239)) return; - - memset(oam_item, 0xff, 32); //default to invalid - for(unsigned i = 0; i < 34; i++) oam_tile[i].x = 0xffff; //default to invalid - - for(unsigned i = 0; i < 128; i++) { - unsigned sprite = (regs.first_sprite + i) & 127; - if(on_scanline(list[sprite]) == false) continue; - if(t.item_count++ >= 32) break; - oam_item[t.item_count - 1] = sprite; - } - - if(t.item_count > 0 && oam_item[t.item_count - 1] != 0xff) { - ppu.regs.oam_iaddr = 0x0200 + (oam_item[t.item_count - 1] >> 2); - } -} - -bool PPU::Sprite::on_scanline(SpriteItem &sprite) { - if(sprite.x > 256 && (sprite.x + sprite.width() - 1) < 512) return false; - signed height = (regs.interlace == false ? sprite.height() : (sprite.height() >> 1)); - if(t.y >= sprite.y && t.y < (sprite.y + height)) return true; - if((sprite.y + height) >= 256 && t.y < ((sprite.y + height) & 255)) return true; - return false; -} - -void PPU::Sprite::run() { - output.main.priority = 0; - output.sub.priority = 0; - - auto oam_tile = t.tile[!t.active]; - unsigned priority_table[] = { regs.priority0, regs.priority1, regs.priority2, regs.priority3 }; - unsigned x = t.x++; - - for(unsigned n = 0; n < 34; n++) { - auto tile = oam_tile[n]; - if(tile.x == 0xffff) break; - - int px = x - sclip<9>(tile.x); - if(px & ~7) continue; - - unsigned mask = 0x80 >> (tile.hflip == false ? px : 7 - px); - unsigned color; - color = ((bool)(tile.d0 & mask)) << 0; - color |= ((bool)(tile.d1 & mask)) << 1; - color |= ((bool)(tile.d2 & mask)) << 2; - color |= ((bool)(tile.d3 & mask)) << 3; - - if(color) { - if(regs.main_enable) { - output.main.palette = tile.palette + color; - output.main.priority = priority_table[tile.priority]; - } - - if(regs.sub_enable) { - output.sub.palette = tile.palette + color; - output.sub.priority = priority_table[tile.priority]; - } - } - } -} - -void PPU::Sprite::tilefetch() { - auto oam_item = t.item[t.active]; - auto oam_tile = t.tile[t.active]; - - for(signed i = 31; i >= 0; i--) { - if(oam_item[i] == 0xff) continue; - auto sprite = list[oam_item[i]]; - - unsigned tile_width = sprite.width() >> 3; - signed x = sprite.x; - signed y = (t.y - sprite.y) & 0xff; - if(regs.interlace) y <<= 1; - - if(sprite.vflip) { - if(sprite.width() == sprite.height()) { - y = (sprite.height() - 1) - y; - } else if(y < sprite.width()) { - y = (sprite.width() - 1) - y; - } else { - y = sprite.width() + ((sprite.width() - 1) - (y - sprite.width())); - } - } - - if(regs.interlace) { - y = (sprite.vflip == false ? y + self.field() : y - self.field()); - } - - x &= 511; - y &= 255; - - uint16 tiledata_addr = regs.tiledata_addr; - uint16 chrx = (sprite.character >> 0) & 15; - uint16 chry = (sprite.character >> 4) & 15; - if(sprite.nameselect) { - tiledata_addr += (256 * 32) + (regs.nameselect << 13); - } - chry += (y >> 3); - chry &= 15; - chry <<= 4; - - for(unsigned tx = 0; tx < tile_width; tx++) { - unsigned sx = (x + (tx << 3)) & 511; - if(x != 256 && sx >= 256 && (sx + 7) < 512) continue; - if(t.tile_count++ >= 34) break; - - unsigned n = t.tile_count - 1; - oam_tile[n].x = sx; - oam_tile[n].priority = sprite.priority; - oam_tile[n].palette = 128 + (sprite.palette << 4); - oam_tile[n].hflip = sprite.hflip; - - unsigned mx = (sprite.hflip == false) ? tx : ((tile_width - 1) - tx); - unsigned pos = tiledata_addr + ((chry + ((chrx + mx) & 15)) << 5); - uint16 addr = (pos & 0xffe0) + ((y & 7) * 2); - - oam_tile[n].d0 = ppu.vram[addr + 0]; - oam_tile[n].d1 = ppu.vram[addr + 1]; - self.add_clocks(2); - - oam_tile[n].d2 = ppu.vram[addr + 16]; - oam_tile[n].d3 = ppu.vram[addr + 17]; - self.add_clocks(2); - } - } - - if(t.tile_count < 34) self.add_clocks((34 - t.tile_count) * 4); - regs.time_over |= (t.tile_count > 34); - regs.range_over |= (t.item_count > 32); -} - -void PPU::Sprite::reset() { - for(unsigned i = 0; i < 128; i++) { - list[i].x = 0; - list[i].y = 0; - list[i].character = 0; - list[i].nameselect = 0; - list[i].vflip = 0; - list[i].hflip = 0; - list[i].priority = 0; - list[i].palette = 0; - list[i].size = 0; - } - synchronize(); - - t.x = 0; - t.y = 0; - - t.item_count = 0; - t.tile_count = 0; - - t.active = 0; - for(unsigned n = 0; n < 2; n++) { - memset(t.item[n], 0, 32); - for(unsigned i = 0; i < 34; i++) { - t.tile[n][i].x = 0; - t.tile[n][i].priority = 0; - t.tile[n][i].palette = 0; - t.tile[n][i].hflip = 0; - t.tile[n][i].d0 = 0; - t.tile[n][i].d1 = 0; - t.tile[n][i].d2 = 0; - t.tile[n][i].d3 = 0; - } - } - - regs.main_enable = random(false); - regs.sub_enable = random(false); - regs.interlace = random(false); - - regs.base_size = random(0); - regs.nameselect = random(0); - regs.tiledata_addr = (random(0x0000) & 3) << 14; - regs.first_sprite = 0; - - regs.priority0 = 0; - regs.priority1 = 0; - regs.priority2 = 0; - regs.priority3 = 0; - - regs.time_over = false; - regs.range_over = false; - - output.main.palette = 0; - output.main.priority = 0; - output.sub.palette = 0; - output.sub.priority = 0; -} - -PPU::Sprite::Sprite(PPU &self) : self(self) { -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/ppu/sprite/sprite.hpp b/waterbox/libsnes/bsnes/snes/ppu/sprite/sprite.hpp deleted file mode 100644 index 925bc4e502..0000000000 --- a/waterbox/libsnes/bsnes/snes/ppu/sprite/sprite.hpp +++ /dev/null @@ -1,81 +0,0 @@ -struct Sprite { - struct SpriteItem { - uint16 x; - uint16 y; - uint8 character; - bool nameselect; - bool vflip; - bool hflip; - uint8 priority; - uint8 palette; - bool size; - unsigned width() const; - unsigned height() const; - } list[128]; - - struct TileItem { - uint16 x; - uint16 priority; - uint16 palette; - bool hflip; - uint8 d0, d1, d2, d3; - }; - - struct State { - unsigned x; - unsigned y; - - unsigned item_count; - unsigned tile_count; - - bool active; - uint8 item[2][32]; - TileItem tile[2][34]; - } t; - - struct Regs { - bool main_enable; - bool sub_enable; - bool interlace; - - uint3 base_size; - uint2 nameselect; - uint16 tiledata_addr; - uint8 first_sprite; - - unsigned priority0; - unsigned priority1; - unsigned priority2; - unsigned priority3; - - bool time_over; - bool range_over; - } regs; - - struct Output { - struct Pixel { - unsigned priority; //0 = none (transparent) - uint8 palette; - } main, sub; - } output; - - //list.cpp - void update(unsigned addr, uint8 data); - void synchronize(); - - //sprite.cpp - void address_reset(); - void set_first_sprite(); - void frame(); - void scanline(); - void run(); - void tilefetch(); - void reset(); - - bool on_scanline(SpriteItem&); - - Sprite(PPU &self); - - PPU &self; - friend class PPU; -}; diff --git a/waterbox/libsnes/bsnes/snes/ppu/window/window.cpp b/waterbox/libsnes/bsnes/snes/ppu/window/window.cpp deleted file mode 100644 index dec0587678..0000000000 --- a/waterbox/libsnes/bsnes/snes/ppu/window/window.cpp +++ /dev/null @@ -1,169 +0,0 @@ -#ifdef PPU_CPP - -void PPU::Window::scanline() { - x = 0; -} - -void PPU::Window::run() { - bool main, sub; - one = (x >= regs.one_left && x <= regs.one_right); - two = (x >= regs.two_left && x <= regs.two_right); - x++; - - test( - main, sub, - regs.bg1_one_enable, regs.bg1_one_invert, - regs.bg1_two_enable, regs.bg1_two_invert, - regs.bg1_mask, regs.bg1_main_enable, regs.bg1_sub_enable - ); - if(main) self.bg1.output.main.priority = 0; - if(sub) self.bg1.output.sub.priority = 0; - - test( - main, sub, - regs.bg2_one_enable, regs.bg2_one_invert, - regs.bg2_two_enable, regs.bg2_two_invert, - regs.bg2_mask, regs.bg2_main_enable, regs.bg2_sub_enable - ); - if(main) self.bg2.output.main.priority = 0; - if(sub) self.bg2.output.sub.priority = 0; - - test( - main, sub, - regs.bg3_one_enable, regs.bg3_one_invert, - regs.bg3_two_enable, regs.bg3_two_invert, - regs.bg3_mask, regs.bg3_main_enable, regs.bg3_sub_enable - ); - if(main) self.bg3.output.main.priority = 0; - if(sub) self.bg3.output.sub.priority = 0; - - test( - main, sub, - regs.bg4_one_enable, regs.bg4_one_invert, - regs.bg4_two_enable, regs.bg4_two_invert, - regs.bg4_mask, regs.bg4_main_enable, regs.bg4_sub_enable - ); - if(main) self.bg4.output.main.priority = 0; - if(sub) self.bg4.output.sub.priority = 0; - - test( - main, sub, - regs.oam_one_enable, regs.oam_one_invert, - regs.oam_two_enable, regs.oam_two_invert, - regs.oam_mask, regs.oam_main_enable, regs.oam_sub_enable - ); - if(main) self.sprite.output.main.priority = 0; - if(sub) self.sprite.output.sub.priority = 0; - - test( - main, sub, - regs.col_one_enable, regs.col_one_invert, - regs.col_two_enable, regs.col_two_invert, - regs.col_mask, true, true - ); - - switch(regs.col_main_mask) { - case 0: main = true; break; - case 1: break; - case 2: main = !main; break; - case 3: main = false; break; - } - - switch(regs.col_sub_mask) { - case 0: sub = true; break; - case 1: break; - case 2: sub = !sub; break; - case 3: sub = false; break; - } - - output.main.color_enable = main; - output.sub.color_enable = sub; -} - -void PPU::Window::test( - bool &main, bool &sub, - bool one_enable, bool one_invert, - bool two_enable, bool two_invert, - uint8 mask, bool main_enable, bool sub_enable -) { - bool one = Window::one ^ one_invert; - bool two = Window::two ^ two_invert; - bool output; - - if(one_enable == false && two_enable == false) { - output = false; - } else if(one_enable == true && two_enable == false) { - output = one; - } else if(one_enable == false && two_enable == true) { - output = two; - } else switch(mask) { - case 0: output = (one | two) == 1; break; - case 1: output = (one & two) == 1; break; - case 2: output = (one ^ two) == 1; break; - case 3: output = (one ^ two) == 0; break; - } - - main = main_enable ? output : false; - sub = sub_enable ? output : false; -} - -void PPU::Window::reset() { - regs.bg1_one_enable = random(false); - regs.bg1_one_invert = random(false); - regs.bg1_two_enable = random(false); - regs.bg1_two_invert = random(false); - regs.bg2_one_enable = random(false); - regs.bg2_one_invert = random(false); - regs.bg2_two_enable = random(false); - regs.bg2_two_invert = random(false); - regs.bg3_one_enable = random(false); - regs.bg3_one_invert = random(false); - regs.bg3_two_enable = random(false); - regs.bg3_two_invert = random(false); - regs.bg4_one_enable = random(false); - regs.bg4_one_invert = random(false); - regs.bg4_two_enable = random(false); - regs.bg4_two_invert = random(false); - regs.oam_one_enable = random(false); - regs.oam_one_invert = random(false); - regs.oam_two_enable = random(false); - regs.oam_two_invert = random(false); - regs.col_one_enable = random(false); - regs.col_one_invert = random(false); - regs.col_two_enable = random(false); - regs.col_two_invert = random(false); - regs.one_left = random(0x00); - regs.one_right = random(0x00); - regs.two_left = random(0x00); - regs.two_right = random(0x00); - regs.bg1_mask = random(0); - regs.bg2_mask = random(0); - regs.bg3_mask = random(0); - regs.bg4_mask = random(0); - regs.oam_mask = random(0); - regs.col_mask = random(0); - regs.bg1_main_enable = random(false); - regs.bg1_sub_enable = random(false); - regs.bg2_main_enable = random(false); - regs.bg2_sub_enable = random(false); - regs.bg3_main_enable = random(false); - regs.bg3_sub_enable = random(false); - regs.bg4_main_enable = random(false); - regs.bg4_sub_enable = random(false); - regs.oam_main_enable = random(false); - regs.oam_sub_enable = random(false); - regs.col_main_mask = random(0); - regs.col_sub_mask = random(0); - - output.main.color_enable = 0; - output.sub.color_enable = 0; - - x = 0; - one = 0; - two = 0; -} - -PPU::Window::Window(PPU &self) : self(self) { -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/ppu/window/window.hpp b/waterbox/libsnes/bsnes/snes/ppu/window/window.hpp deleted file mode 100644 index fe3ddc7b69..0000000000 --- a/waterbox/libsnes/bsnes/snes/ppu/window/window.hpp +++ /dev/null @@ -1,87 +0,0 @@ -struct Window { - struct { - bool bg1_one_enable; - bool bg1_one_invert; - bool bg1_two_enable; - bool bg1_two_invert; - - bool bg2_one_enable; - bool bg2_one_invert; - bool bg2_two_enable; - bool bg2_two_invert; - - bool bg3_one_enable; - bool bg3_one_invert; - bool bg3_two_enable; - bool bg3_two_invert; - - bool bg4_one_enable; - bool bg4_one_invert; - bool bg4_two_enable; - bool bg4_two_invert; - - bool oam_one_enable; - bool oam_one_invert; - bool oam_two_enable; - bool oam_two_invert; - - bool col_one_enable; - bool col_one_invert; - bool col_two_enable; - bool col_two_invert; - - uint8 one_left; - uint8 one_right; - uint8 two_left; - uint8 two_right; - - uint2 bg1_mask; - uint2 bg2_mask; - uint2 bg3_mask; - uint2 bg4_mask; - uint2 oam_mask; - uint2 col_mask; - - bool bg1_main_enable; - bool bg1_sub_enable; - bool bg2_main_enable; - bool bg2_sub_enable; - bool bg3_main_enable; - bool bg3_sub_enable; - bool bg4_main_enable; - bool bg4_sub_enable; - bool oam_main_enable; - bool oam_sub_enable; - - uint2 col_main_mask; - uint2 col_sub_mask; - } regs; - - struct Output { - struct Pixel { - bool color_enable; - } main, sub; - } output; - - struct { - unsigned x; - bool one; - bool two; - }; - - void scanline(); - void run(); - void reset(); - - void test( - bool &main, bool &sub, - bool one_enable, bool one_invert, - bool two_enable, bool two_invert, - uint8 mask, bool main_enable, bool sub_enable - ); - - Window(PPU &self); - - PPU &self; - friend class PPU; -}; diff --git a/waterbox/libsnes/bsnes/snes/profile-accuracy.hpp b/waterbox/libsnes/bsnes/snes/profile-accuracy.hpp deleted file mode 100644 index 7b6dded8f8..0000000000 --- a/waterbox/libsnes/bsnes/snes/profile-accuracy.hpp +++ /dev/null @@ -1,8 +0,0 @@ -namespace Info { - static const char Profile[] = "Accuracy"; -} - -#include -#include -#include -#include diff --git a/waterbox/libsnes/bsnes/snes/profile-compatibility.hpp b/waterbox/libsnes/bsnes/snes/profile-compatibility.hpp deleted file mode 100644 index bbf3582ddc..0000000000 --- a/waterbox/libsnes/bsnes/snes/profile-compatibility.hpp +++ /dev/null @@ -1,8 +0,0 @@ -namespace Info { - static const char Profile[] = "Compatibility"; -} - -#include -#include -#include -#include diff --git a/waterbox/libsnes/bsnes/snes/profile-performance.hpp b/waterbox/libsnes/bsnes/snes/profile-performance.hpp deleted file mode 100644 index 1d379fdc86..0000000000 --- a/waterbox/libsnes/bsnes/snes/profile-performance.hpp +++ /dev/null @@ -1,12 +0,0 @@ -namespace Info { - static const char Profile[] = "Performance"; -} - -#if defined(DEBUGGER) - #error "bsnes: debugger not supported with performance profile." -#endif - -#include -#include -#include -#include diff --git a/waterbox/libsnes/bsnes/snes/random/random.cpp b/waterbox/libsnes/bsnes/snes/random/random.cpp deleted file mode 100644 index 09c9095bf2..0000000000 --- a/waterbox/libsnes/bsnes/snes/random/random.cpp +++ /dev/null @@ -1,14 +0,0 @@ -Random random; - -void Random::seed(unsigned seed_iter) { - iter = seed_iter; -} - -unsigned Random::operator()(unsigned result) { - if(config.random == false) return result; - return iter = (iter >> 1) ^ (((iter & 1) - 1) & 0xedb88320); -} - -Random::Random() { - iter = 0; -} diff --git a/waterbox/libsnes/bsnes/snes/random/random.hpp b/waterbox/libsnes/bsnes/snes/random/random.hpp deleted file mode 100644 index e424da8cf9..0000000000 --- a/waterbox/libsnes/bsnes/snes/random/random.hpp +++ /dev/null @@ -1,10 +0,0 @@ -struct Random { - void seed(unsigned seed); - unsigned operator()(unsigned result = 0); - Random(); - -private: - unsigned iter; -}; - -extern Random random; diff --git a/waterbox/libsnes/bsnes/snes/scheduler/scheduler.cpp b/waterbox/libsnes/bsnes/snes/scheduler/scheduler.cpp deleted file mode 100644 index 0576eee5ce..0000000000 --- a/waterbox/libsnes/bsnes/snes/scheduler/scheduler.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifdef SYSTEM_CPP - -Scheduler scheduler; - -void Scheduler::enter() { - host_thread = co_active(); - co_switch(thread); -} - -void Scheduler::exit(ExitReason reason) { - exit_reason = reason; - thread = co_active(); - co_switch(host_thread); -} - -void Scheduler::debug() { - exit(ExitReason::DebuggerEvent); -} - -void Scheduler::init() { - host_thread = co_active(); - thread = cpu.thread; - sync = SynchronizeMode::None; -} - -Scheduler::Scheduler() { - host_thread = 0; - thread = 0; - exit_reason = ExitReason::UnknownEvent; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/scheduler/scheduler.hpp b/waterbox/libsnes/bsnes/snes/scheduler/scheduler.hpp deleted file mode 100644 index db67f3727a..0000000000 --- a/waterbox/libsnes/bsnes/snes/scheduler/scheduler.hpp +++ /dev/null @@ -1,19 +0,0 @@ -struct Scheduler : property { - enum class SynchronizeMode : unsigned { None, CPU, All } sync; - enum class ExitReason : unsigned { UnknownEvent, FrameEvent, SynchronizeEvent, DebuggerEvent }; - readonly exit_reason; - - void clearExitReason() { exit_reason = ExitReason::UnknownEvent; } - - cothread_t host_thread; //program thread (used to exit emulation) - cothread_t thread; //active emulation thread (used to enter emulation) - - void enter(); - void exit(ExitReason); - void debug(); - - void init(); - Scheduler(); -}; - -extern Scheduler scheduler; diff --git a/waterbox/libsnes/bsnes/snes/smp/core/algorithms.cpp b/waterbox/libsnes/bsnes/snes/smp/core/algorithms.cpp deleted file mode 100644 index 69504cdf9d..0000000000 --- a/waterbox/libsnes/bsnes/snes/smp/core/algorithms.cpp +++ /dev/null @@ -1,138 +0,0 @@ -#ifdef SMPCORE_CPP - -uint8 SMPcore::op_adc(uint8 x, uint8 y) { - int r = x + y + regs.p.c; - regs.p.n = r & 0x80; - regs.p.v = ~(x ^ y) & (x ^ r) & 0x80; - regs.p.h = (x ^ y ^ r) & 0x10; - regs.p.z = (uint8)r == 0; - regs.p.c = r > 0xff; - return r; -} - -uint8 SMPcore::op_and(uint8 x, uint8 y) { - x &= y; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMPcore::op_asl(uint8 x) { - regs.p.c = x & 0x80; - x <<= 1; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMPcore::op_cmp(uint8 x, uint8 y) { - int r = x - y; - regs.p.n = r & 0x80; - regs.p.z = (uint8)r == 0; - regs.p.c = r >= 0; - return x; -} - -uint8 SMPcore::op_dec(uint8 x) { - x--; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMPcore::op_eor(uint8 x, uint8 y) { - x ^= y; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMPcore::op_inc(uint8 x) { - x++; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMPcore::op_ld(uint8 x, uint8 y) { - regs.p.n = y & 0x80; - regs.p.z = y == 0; - return y; -} - -uint8 SMPcore::op_lsr(uint8 x) { - regs.p.c = x & 0x01; - x >>= 1; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMPcore::op_or(uint8 x, uint8 y) { - x |= y; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMPcore::op_rol(uint8 x) { - unsigned carry = regs.p.c << 0; - regs.p.c = x & 0x80; - x = (x << 1) | carry; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMPcore::op_ror(uint8 x) { - unsigned carry = regs.p.c << 7; - regs.p.c = x & 0x01; - x = carry | (x >> 1); - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMPcore::op_sbc(uint8 x, uint8 y) { - return op_adc(x, ~y); -} - -uint8 SMPcore::op_st(uint8 x, uint8 y) { - return y; -} - -// - -uint16 SMPcore::op_adw(uint16 x, uint16 y) { - uint16 r; - regs.p.c = 0; - r = op_adc(x, y); - r |= op_adc(x >> 8, y >> 8) << 8; - regs.p.z = r == 0; - return r; -} - -uint16 SMPcore::op_cpw(uint16 x, uint16 y) { - int r = x - y; - regs.p.n = r & 0x8000; - regs.p.z = (uint16)r == 0; - regs.p.c = r >= 0; - return x; -} - -uint16 SMPcore::op_ldw(uint16 x, uint16 y) { - regs.p.n = y & 0x8000; - regs.p.z = y == 0; - return y; -} - -uint16 SMPcore::op_sbw(uint16 x, uint16 y) { - uint16 r; - regs.p.c = 1; - r = op_sbc(x, y); - r |= op_sbc(x >> 8, y >> 8) << 8; - regs.p.z = r == 0; - return r; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/smp/core/core.cpp b/waterbox/libsnes/bsnes/snes/smp/core/core.cpp deleted file mode 100644 index 6908884eff..0000000000 --- a/waterbox/libsnes/bsnes/snes/smp/core/core.cpp +++ /dev/null @@ -1,271 +0,0 @@ -#include - -#define SMPCORE_CPP -namespace SNES { - -#include "algorithms.cpp" -#include "opcodes.cpp" -#include "disassembler.cpp" - -void SMPcore::op_step() { - switch(opcode = op_readpc()) { - case 0x00: return op_nop(); - case 0x01: return op_jst(); - case 0x02: return op_set_bit(); - case 0x03: return op_branch_bit(); - case 0x04: return op_read_dp<&SMPcore::op_or>(regs.a); - case 0x05: return op_read_addr<&SMPcore::op_or>(regs.a); - case 0x06: return op_read_ix<&SMPcore::op_or>(); - case 0x07: return op_read_idpx<&SMPcore::op_or>(); - case 0x08: return op_read_const<&SMPcore::op_or>(regs.a); - case 0x09: return op_write_dp_dp<&SMPcore::op_or>(); - case 0x0a: return op_set_addr_bit(); - case 0x0b: return op_adjust_dp<&SMPcore::op_asl>(); - case 0x0c: return op_adjust_addr<&SMPcore::op_asl>(); - case 0x0d: return op_push(regs.p); - case 0x0e: return op_test_addr(1); - case 0x0f: return op_brk(); - case 0x10: return op_branch(regs.p.n == 0); - case 0x11: return op_jst(); - case 0x12: return op_set_bit(); - case 0x13: return op_branch_bit(); - case 0x14: return op_read_dpi<&SMPcore::op_or>(regs.a, regs.x); - case 0x15: return op_read_addri<&SMPcore::op_or>(regs.x); - case 0x16: return op_read_addri<&SMPcore::op_or>(regs.y); - case 0x17: return op_read_idpy<&SMPcore::op_or>(); - case 0x18: return op_write_dp_const<&SMPcore::op_or>(); - case 0x19: return op_write_ix_iy<&SMPcore::op_or>(); - case 0x1a: return op_adjust_dpw(-1); - case 0x1b: return op_adjust_dpx<&SMPcore::op_asl>(); - case 0x1c: return op_adjust<&SMPcore::op_asl>(regs.a); - case 0x1d: return op_adjust<&SMPcore::op_dec>(regs.x); - case 0x1e: return op_read_addr<&SMPcore::op_cmp>(regs.x); - case 0x1f: return op_jmp_iaddrx(); - case 0x20: return op_set_flag(regs.p.p, 0); - case 0x21: return op_jst(); - case 0x22: return op_set_bit(); - case 0x23: return op_branch_bit(); - case 0x24: return op_read_dp<&SMPcore::op_and>(regs.a); - case 0x25: return op_read_addr<&SMPcore::op_and>(regs.a); - case 0x26: return op_read_ix<&SMPcore::op_and>(); - case 0x27: return op_read_idpx<&SMPcore::op_and>(); - case 0x28: return op_read_const<&SMPcore::op_and>(regs.a); - case 0x29: return op_write_dp_dp<&SMPcore::op_and>(); - case 0x2a: return op_set_addr_bit(); - case 0x2b: return op_adjust_dp<&SMPcore::op_rol>(); - case 0x2c: return op_adjust_addr<&SMPcore::op_rol>(); - case 0x2d: return op_push(regs.a); - case 0x2e: return op_bne_dp(); - case 0x2f: return op_branch(true); - case 0x30: return op_branch(regs.p.n == 1); - case 0x31: return op_jst(); - case 0x32: return op_set_bit(); - case 0x33: return op_branch_bit(); - case 0x34: return op_read_dpi<&SMPcore::op_and>(regs.a, regs.x); - case 0x35: return op_read_addri<&SMPcore::op_and>(regs.x); - case 0x36: return op_read_addri<&SMPcore::op_and>(regs.y); - case 0x37: return op_read_idpy<&SMPcore::op_and>(); - case 0x38: return op_write_dp_const<&SMPcore::op_and>(); - case 0x39: return op_write_ix_iy<&SMPcore::op_and>(); - case 0x3a: return op_adjust_dpw(+1); - case 0x3b: return op_adjust_dpx<&SMPcore::op_rol>(); - case 0x3c: return op_adjust<&SMPcore::op_rol>(regs.a); - case 0x3d: return op_adjust<&SMPcore::op_inc>(regs.x); - case 0x3e: return op_read_dp<&SMPcore::op_cmp>(regs.x); - case 0x3f: return op_jsr_addr(); - case 0x40: return op_set_flag(regs.p.p, 1); - case 0x41: return op_jst(); - case 0x42: return op_set_bit(); - case 0x43: return op_branch_bit(); - case 0x44: return op_read_dp<&SMPcore::op_eor>(regs.a); - case 0x45: return op_read_addr<&SMPcore::op_eor>(regs.a); - case 0x46: return op_read_ix<&SMPcore::op_eor>(); - case 0x47: return op_read_idpx<&SMPcore::op_eor>(); - case 0x48: return op_read_const<&SMPcore::op_eor>(regs.a); - case 0x49: return op_write_dp_dp<&SMPcore::op_eor>(); - case 0x4a: return op_set_addr_bit(); - case 0x4b: return op_adjust_dp<&SMPcore::op_lsr>(); - case 0x4c: return op_adjust_addr<&SMPcore::op_lsr>(); - case 0x4d: return op_push(regs.x); - case 0x4e: return op_test_addr(0); - case 0x4f: return op_jsp_dp(); - case 0x50: return op_branch(regs.p.v == 0); - case 0x51: return op_jst(); - case 0x52: return op_set_bit(); - case 0x53: return op_branch_bit(); - case 0x54: return op_read_dpi<&SMPcore::op_eor>(regs.a, regs.x); - case 0x55: return op_read_addri<&SMPcore::op_eor>(regs.x); - case 0x56: return op_read_addri<&SMPcore::op_eor>(regs.y); - case 0x57: return op_read_idpy<&SMPcore::op_eor>(); - case 0x58: return op_write_dp_const<&SMPcore::op_eor>(); - case 0x59: return op_write_ix_iy<&SMPcore::op_eor>(); - case 0x5a: return op_read_dpw<&SMPcore::op_cpw>(); - case 0x5b: return op_adjust_dpx<&SMPcore::op_lsr>(); - case 0x5c: return op_adjust<&SMPcore::op_lsr>(regs.a); - case 0x5d: return op_transfer(regs.a, regs.x); - case 0x5e: return op_read_addr<&SMPcore::op_cmp>(regs.y); - case 0x5f: return op_jmp_addr(); - case 0x60: return op_set_flag(regs.p.c, 0); - case 0x61: return op_jst(); - case 0x62: return op_set_bit(); - case 0x63: return op_branch_bit(); - case 0x64: return op_read_dp<&SMPcore::op_cmp>(regs.a); - case 0x65: return op_read_addr<&SMPcore::op_cmp>(regs.a); - case 0x66: return op_read_ix<&SMPcore::op_cmp>(); - case 0x67: return op_read_idpx<&SMPcore::op_cmp>(); - case 0x68: return op_read_const<&SMPcore::op_cmp>(regs.a); - case 0x69: return op_write_dp_dp<&SMPcore::op_cmp>(); - case 0x6a: return op_set_addr_bit(); - case 0x6b: return op_adjust_dp<&SMPcore::op_ror>(); - case 0x6c: return op_adjust_addr<&SMPcore::op_ror>(); - case 0x6d: return op_push(regs.y); - case 0x6e: return op_bne_dpdec(); - case 0x6f: return op_rts(); - case 0x70: return op_branch(regs.p.v == 1); - case 0x71: return op_jst(); - case 0x72: return op_set_bit(); - case 0x73: return op_branch_bit(); - case 0x74: return op_read_dpi<&SMPcore::op_cmp>(regs.a, regs.x); - case 0x75: return op_read_addri<&SMPcore::op_cmp>(regs.x); - case 0x76: return op_read_addri<&SMPcore::op_cmp>(regs.y); - case 0x77: return op_read_idpy<&SMPcore::op_cmp>(); - case 0x78: return op_write_dp_const<&SMPcore::op_cmp>(); - case 0x79: return op_write_ix_iy<&SMPcore::op_cmp>(); - case 0x7a: return op_read_dpw<&SMPcore::op_adw>(); - case 0x7b: return op_adjust_dpx<&SMPcore::op_ror>(); - case 0x7c: return op_adjust<&SMPcore::op_ror>(regs.a); - case 0x7d: return op_transfer(regs.x, regs.a); - case 0x7e: return op_read_dp<&SMPcore::op_cmp>(regs.y); - case 0x7f: return op_rti(); - case 0x80: return op_set_flag(regs.p.c, 1); - case 0x81: return op_jst(); - case 0x82: return op_set_bit(); - case 0x83: return op_branch_bit(); - case 0x84: return op_read_dp<&SMPcore::op_adc>(regs.a); - case 0x85: return op_read_addr<&SMPcore::op_adc>(regs.a); - case 0x86: return op_read_ix<&SMPcore::op_adc>(); - case 0x87: return op_read_idpx<&SMPcore::op_adc>(); - case 0x88: return op_read_const<&SMPcore::op_adc>(regs.a); - case 0x89: return op_write_dp_dp<&SMPcore::op_adc>(); - case 0x8a: return op_set_addr_bit(); - case 0x8b: return op_adjust_dp<&SMPcore::op_dec>(); - case 0x8c: return op_adjust_addr<&SMPcore::op_dec>(); - case 0x8d: return op_read_const<&SMPcore::op_ld>(regs.y); - case 0x8e: return op_plp(); - case 0x8f: return op_write_dp_const<&SMPcore::op_st>(); - case 0x90: return op_branch(regs.p.c == 0); - case 0x91: return op_jst(); - case 0x92: return op_set_bit(); - case 0x93: return op_branch_bit(); - case 0x94: return op_read_dpi<&SMPcore::op_adc>(regs.a, regs.x); - case 0x95: return op_read_addri<&SMPcore::op_adc>(regs.x); - case 0x96: return op_read_addri<&SMPcore::op_adc>(regs.y); - case 0x97: return op_read_idpy<&SMPcore::op_adc>(); - case 0x98: return op_write_dp_const<&SMPcore::op_adc>(); - case 0x99: return op_write_ix_iy<&SMPcore::op_adc>(); - case 0x9a: return op_read_dpw<&SMPcore::op_sbw>(); - case 0x9b: return op_adjust_dpx<&SMPcore::op_dec>(); - case 0x9c: return op_adjust<&SMPcore::op_dec>(regs.a); - case 0x9d: return op_transfer(regs.s, regs.x); - case 0x9e: return op_div_ya_x(); - case 0x9f: return op_xcn(); - case 0xa0: return op_set_flag(regs.p.i, 1); - case 0xa1: return op_jst(); - case 0xa2: return op_set_bit(); - case 0xa3: return op_branch_bit(); - case 0xa4: return op_read_dp<&SMPcore::op_sbc>(regs.a); - case 0xa5: return op_read_addr<&SMPcore::op_sbc>(regs.a); - case 0xa6: return op_read_ix<&SMPcore::op_sbc>(); - case 0xa7: return op_read_idpx<&SMPcore::op_sbc>(); - case 0xa8: return op_read_const<&SMPcore::op_sbc>(regs.a); - case 0xa9: return op_write_dp_dp<&SMPcore::op_sbc>(); - case 0xaa: return op_set_addr_bit(); - case 0xab: return op_adjust_dp<&SMPcore::op_inc>(); - case 0xac: return op_adjust_addr<&SMPcore::op_inc>(); - case 0xad: return op_read_const<&SMPcore::op_cmp>(regs.y); - case 0xae: return op_pull(regs.a); - case 0xaf: return op_sta_ixinc(); - case 0xb0: return op_branch(regs.p.c == 1); - case 0xb1: return op_jst(); - case 0xb2: return op_set_bit(); - case 0xb3: return op_branch_bit(); - case 0xb4: return op_read_dpi<&SMPcore::op_sbc>(regs.a, regs.x); - case 0xb5: return op_read_addri<&SMPcore::op_sbc>(regs.x); - case 0xb6: return op_read_addri<&SMPcore::op_sbc>(regs.y); - case 0xb7: return op_read_idpy<&SMPcore::op_sbc>(); - case 0xb8: return op_write_dp_const<&SMPcore::op_sbc>(); - case 0xb9: return op_write_ix_iy<&SMPcore::op_sbc>(); - case 0xba: return op_read_dpw<&SMPcore::op_ldw>(); - case 0xbb: return op_adjust_dpx<&SMPcore::op_inc>(); - case 0xbc: return op_adjust<&SMPcore::op_inc>(regs.a); - case 0xbd: return op_transfer(regs.x, regs.s); - case 0xbe: return op_das(); - case 0xbf: return op_lda_ixinc(); - case 0xc0: return op_set_flag(regs.p.i, 0); - case 0xc1: return op_jst(); - case 0xc2: return op_set_bit(); - case 0xc3: return op_branch_bit(); - case 0xc4: return op_write_dp(regs.a); - case 0xc5: return op_write_addr(regs.a); - case 0xc6: return op_sta_ix(); - case 0xc7: return op_sta_idpx(); - case 0xc8: return op_read_const<&SMPcore::op_cmp>(regs.x); - case 0xc9: return op_write_addr(regs.x); - case 0xca: return op_set_addr_bit(); - case 0xcb: return op_write_dp(regs.y); - case 0xcc: return op_write_addr(regs.y); - case 0xcd: return op_read_const<&SMPcore::op_ld>(regs.x); - case 0xce: return op_pull(regs.x); - case 0xcf: return op_mul_ya(); - case 0xd0: return op_branch(regs.p.z == 0); - case 0xd1: return op_jst(); - case 0xd2: return op_set_bit(); - case 0xd3: return op_branch_bit(); - case 0xd4: return op_write_dpi(regs.a, regs.x); - case 0xd5: return op_write_addri(regs.x); - case 0xd6: return op_write_addri(regs.y); - case 0xd7: return op_sta_idpy(); - case 0xd8: return op_write_dp(regs.x); - case 0xd9: return op_write_dpi(regs.x, regs.y); - case 0xda: return op_stw_dp(); - case 0xdb: return op_write_dpi(regs.y, regs.x); - case 0xdc: return op_adjust<&SMPcore::op_dec>(regs.y); - case 0xdd: return op_transfer(regs.y, regs.a); - case 0xde: return op_bne_dpx(); - case 0xdf: return op_daa(); - case 0xe0: return op_clv(); - case 0xe1: return op_jst(); - case 0xe2: return op_set_bit(); - case 0xe3: return op_branch_bit(); - case 0xe4: return op_read_dp<&SMPcore::op_ld>(regs.a); - case 0xe5: return op_read_addr<&SMPcore::op_ld>(regs.a); - case 0xe6: return op_read_ix<&SMPcore::op_ld>(); - case 0xe7: return op_read_idpx<&SMPcore::op_ld>(); - case 0xe8: return op_read_const<&SMPcore::op_ld>(regs.a); - case 0xe9: return op_read_addr<&SMPcore::op_ld>(regs.x); - case 0xea: return op_set_addr_bit(); - case 0xeb: return op_read_dp<&SMPcore::op_ld>(regs.y); - case 0xec: return op_read_addr<&SMPcore::op_ld>(regs.y); - case 0xed: return op_cmc(); - case 0xee: return op_pull(regs.y); - case 0xef: return op_wait(); - case 0xf0: return op_branch(regs.p.z == 1); - case 0xf1: return op_jst(); - case 0xf2: return op_set_bit(); - case 0xf3: return op_branch_bit(); - case 0xf4: return op_read_dpi<&SMPcore::op_ld>(regs.a, regs.x); - case 0xf5: return op_read_addri<&SMPcore::op_ld>(regs.x); - case 0xf6: return op_read_addri<&SMPcore::op_ld>(regs.y); - case 0xf7: return op_read_idpy<&SMPcore::op_ld>(); - case 0xf8: return op_read_dp<&SMPcore::op_ld>(regs.x); - case 0xf9: return op_read_dpi<&SMPcore::op_ld>(regs.x, regs.y); - case 0xfa: return op_write_dp_dp<&SMPcore::op_st>(); - case 0xfb: return op_read_dpi<&SMPcore::op_ld>(regs.y, regs.x); - case 0xfc: return op_adjust<&SMPcore::op_inc>(regs.y); - case 0xfd: return op_transfer(regs.a, regs.y); - case 0xfe: return op_bne_ydec(); - case 0xff: return op_wait(); - } -} - -} diff --git a/waterbox/libsnes/bsnes/snes/smp/core/core.hpp b/waterbox/libsnes/bsnes/snes/smp/core/core.hpp deleted file mode 100644 index b7f30d9f9a..0000000000 --- a/waterbox/libsnes/bsnes/snes/smp/core/core.hpp +++ /dev/null @@ -1,95 +0,0 @@ -struct SMPcore { - virtual void op_io() = 0; - virtual uint8 op_read(uint16 addr, eCDLog_Flags flags = eCDLog_Flags_CPUData) = 0; - virtual void op_write(uint16 addr, uint8 data) = 0; - void op_step(); - - #include "registers.hpp" - #include "memory.hpp" - - regs_t regs; - word_t dp, sp, rd, wr, bit, ya; - uint8 opcode; - - string disassemble_opcode(uint16 addr); - -protected: - uint8 op_adc(uint8, uint8); - uint8 op_and(uint8, uint8); - uint8 op_asl(uint8); - uint8 op_cmp(uint8, uint8); - uint8 op_dec(uint8); - uint8 op_eor(uint8, uint8); - uint8 op_inc(uint8); - uint8 op_ld (uint8, uint8); - uint8 op_lsr(uint8); - uint8 op_or (uint8, uint8); - uint8 op_rol(uint8); - uint8 op_ror(uint8); - uint8 op_sbc(uint8, uint8); - uint8 op_st (uint8, uint8); - uint16 op_adw(uint16, uint16); - uint16 op_cpw(uint16, uint16); - uint16 op_ldw(uint16, uint16); - uint16 op_sbw(uint16, uint16); - - template void op_adjust(uint8&); - template void op_adjust_addr(); - template void op_adjust_dp(); - void op_adjust_dpw(signed); - template void op_adjust_dpx(); - void op_branch(bool); - void op_branch_bit(); - void op_pull(uint8&); - void op_push(uint8); - template void op_read_addr(uint8&); - template void op_read_addri(uint8&); - template void op_read_const(uint8&); - template void op_read_dp(uint8&); - template void op_read_dpi(uint8&, uint8&); - template void op_read_dpw(); - template void op_read_idpx(); - template void op_read_idpy(); - template void op_read_ix(); - void op_set_addr_bit(); - void op_set_bit(); - void op_set_flag(bool&, bool); - void op_test_addr(bool); - void op_transfer(uint8&, uint8&); - void op_write_addr(uint8&); - void op_write_addri(uint8&); - void op_write_dp(uint8&); - void op_write_dpi(uint8&, uint8&); - template void op_write_dp_const(); - template void op_write_dp_dp(); - template void op_write_ix_iy(); - - void op_bne_dp(); - void op_bne_dpdec(); - void op_bne_dpx(); - void op_bne_ydec(); - void op_brk(); - void op_clv(); - void op_cmc(); - void op_daa(); - void op_das(); - void op_div_ya_x(); - void op_jmp_addr(); - void op_jmp_iaddrx(); - void op_jsp_dp(); - void op_jsr_addr(); - void op_jst(); - void op_lda_ixinc(); - void op_mul_ya(); - void op_nop(); - void op_plp(); - void op_rti(); - void op_rts(); - void op_sta_idpx(); - void op_sta_idpy(); - void op_sta_ix(); - void op_sta_ixinc(); - void op_stw_dp(); - void op_wait(); - void op_xcn(); -}; diff --git a/waterbox/libsnes/bsnes/snes/smp/core/disassembler.cpp b/waterbox/libsnes/bsnes/snes/smp/core/disassembler.cpp deleted file mode 100644 index e1b1d89aa3..0000000000 --- a/waterbox/libsnes/bsnes/snes/smp/core/disassembler.cpp +++ /dev/null @@ -1,311 +0,0 @@ -#ifdef SMPCORE_CPP - -string SMPcore::disassemble_opcode(uint16 addr) { - auto read = [&](uint16 addr) -> uint8 { - if((addr & 0xfff0) == 0x00f0) return 0x00; - if((addr & 0xffc0) == 0xffc0) return smp.iplrom[addr & 0x3f]; - return smp.apuram[addr]; - }; - - auto relative = [&](unsigned length, int8 offset) -> uint16 { - uint16 pc = addr + length; - return pc + offset; - }; - - auto a = [&] { return hex<4>((read(addr + 1) << 0) + (read(addr + 2) << 8)); }; - auto b = [&](unsigned n) { return hex<2>(read(addr + 1 + n)); }; - auto r = [&](unsigned r, unsigned n = 0) { return hex<4>(addr + r + (int8)read(addr + 1 + n)); }; - auto dp = [&](unsigned n) { return hex<3>((regs.p.p << 8) + read(addr + 1 + n)); }; - auto ab = [&] { - unsigned n = (read(addr + 1) << 0) + (read(addr + 2) << 8); - return string{ hex<4>(n & 0x1fff), ":", hex<1>(n >> 13) }; - }; - - auto mnemonic = [&]() -> string { - switch(read(addr)) { - case 0x00: return { "nop" }; - case 0x01: return { "jst $ffde" }; - case 0x02: return { "set $", dp(0), ":0" }; - case 0x03: return { "bbs $", dp(0), ":0=$", r(+3, 1) }; - case 0x04: return { "ora $", dp(0) }; - case 0x05: return { "ora $", a() }; - case 0x06: return { "ora (x)" }; - case 0x07: return { "ora ($", dp(0), ",x)" }; - case 0x08: return { "ora #$", b(0) }; - case 0x09: return { "orr $", dp(1), "=$", dp(0) }; - case 0x0a: return { "orc $", ab() }; - case 0x0b: return { "asl $", dp(0) }; - case 0x0c: return { "asl $", a() }; - case 0x0d: return { "php" }; - case 0x0e: return { "tsb $", a() }; - case 0x0f: return { "brk" }; - case 0x10: return { "bpl $", r(+2) }; - case 0x11: return { "jst $ffdc" }; - case 0x12: return { "clr $", dp(0), ":0" }; - case 0x13: return { "bbc $", dp(0), ":0=$", r(+3, 1) }; - case 0x14: return { "ora $", dp(0), ",x" }; - case 0x15: return { "ora $", a(), ",x" }; - case 0x16: return { "ora $", a(), ",y" }; - case 0x17: return { "ora ($", dp(0), "),y" }; - case 0x18: return { "orr $", dp(1), "=#$", b(0) }; - case 0x19: return { "orr (x)=(y)" }; - case 0x1a: return { "dew $", dp(0) }; - case 0x1b: return { "asl $", dp(0), ",x" }; - case 0x1c: return { "asl" }; - case 0x1d: return { "dex" }; - case 0x1e: return { "cpx $", a() }; - case 0x1f: return { "jmp ($", a(), ",x)" }; - case 0x20: return { "clp" }; - case 0x21: return { "jst $ffda" }; - case 0x22: return { "set $", dp(0), ":1" }; - case 0x23: return { "bbs $", dp(0), ":1=$", r(+3, 1) }; - case 0x24: return { "and $", dp(0) }; - case 0x25: return { "and $", a() }; - case 0x26: return { "and (x)" }; - case 0x27: return { "and ($", dp(0), ",x)" }; - case 0x29: return { "and $", dp(1), "=$", dp(0) }; - case 0x2a: return { "orc !$", ab() }; - case 0x2b: return { "rol $", dp(0) }; - case 0x2c: return { "rol $", a() }; - case 0x2d: return { "pha" }; - case 0x2e: return { "bne $", dp(0), "=$", r(+3, 1) }; - case 0x28: return { "and #$", b(0) }; - case 0x2f: return { "bra $", r(+2) }; - case 0x30: return { "bmi $", r(+2) }; - case 0x31: return { "jst $ffd8" }; - case 0x32: return { "clr $", dp(0), ":1" }; - case 0x33: return { "bbc $", dp(0), ":1=$", r(+3, 1) }; - case 0x34: return { "and $", dp(0), ",x" }; - case 0x35: return { "and $", a(), ",x" }; - case 0x36: return { "and $", a(), ",y" }; - case 0x37: return { "and ($", dp(0), "),y" }; - case 0x38: return { "and $", dp(1), "=#$", b(0) }; - case 0x39: return { "and (x)=(y)" }; - case 0x3a: return { "inw $", dp(0) }; - case 0x3b: return { "rol $", dp(0), ",x" }; - case 0x3c: return { "rol" }; - case 0x3d: return { "inx" }; - case 0x3e: return { "cpx $", dp(0) }; - case 0x3f: return { "jsr $", a() }; - case 0x40: return { "sep" }; - case 0x41: return { "jst $ffd6" }; - case 0x42: return { "set $", dp(0), ":2" }; - case 0x43: return { "bbs $", dp(0), ":2=$", r(+3, 1) }; - case 0x44: return { "eor $", dp(0) }; - case 0x45: return { "eor $", a() }; - case 0x46: return { "eor (x)" }; - case 0x47: return { "eor ($", dp(0), ",x)" }; - case 0x48: return { "eor #$", b(0) }; - case 0x49: return { "eor $", dp(1), "=$", dp(0) }; - case 0x4a: return { "and $", ab() }; - case 0x4b: return { "lsr $", dp(0) }; - case 0x4c: return { "lsr $", a() }; - case 0x4d: return { "phx" }; - case 0x4e: return { "trb $", a() }; - case 0x4f: return { "jsp $ff", b(0) }; - case 0x50: return { "bvc $", r(+2) }; - case 0x51: return { "jst $ffd4" }; - case 0x52: return { "clr $", dp(0), ":2" }; - case 0x53: return { "bbc $", dp(0), ":2=$", r(+3, 1) }; - case 0x54: return { "eor $", dp(0), ",x" }; - case 0x55: return { "eor $", a(), ",x" }; - case 0x56: return { "eor $", a(), ",y" }; - case 0x57: return { "eor ($", dp(0), "),y" }; - case 0x58: return { "eor $", dp(1), "=#$", b(0) }; - case 0x59: return { "eor (x)=(y)" }; - case 0x5a: return { "cpw $", a() }; - case 0x5b: return { "lsr $", dp(0), ",x" }; - case 0x5c: return { "lsr" }; - case 0x5d: return { "tax" }; - case 0x5e: return { "cpy $", a() }; - case 0x5f: return { "jmp $", a() }; - case 0x60: return { "clc" }; - case 0x61: return { "jst $ffd2" }; - case 0x62: return { "set $", dp(0), ":3" }; - case 0x63: return { "bbs $", dp(0), ":3=$", r(+3, 1) }; - case 0x64: return { "cmp $", dp(0) }; - case 0x65: return { "cmp $", a() }; - case 0x66: return { "cmp (x)" }; - case 0x67: return { "cmp ($", dp(0), ",x)" }; - case 0x68: return { "cmp #$", b(0) }; - case 0x69: return { "cmp $", dp(1), "=$", dp(0) }; - case 0x6a: return { "and !$", ab() }; - case 0x6b: return { "ror $", dp(0) }; - case 0x6c: return { "ror $", a() }; - case 0x6d: return { "phy" }; - case 0x6e: return { "bne --$", dp(0), "=$", r(+3, 1) }; - case 0x6f: return { "rts" }; - case 0x70: return { "bvs $", r(+2) }; - case 0x71: return { "jst $ffd0" }; - case 0x72: return { "clr $", dp(0), ":3" }; - case 0x73: return { "bbc $", dp(0), ":3=$", r(+3, 1) }; - case 0x74: return { "cmp $", dp(0), ",x" }; - case 0x75: return { "cmp $", a(), ",x" }; - case 0x76: return { "cmp $", a(), ",y" }; - case 0x77: return { "cmp ($", dp(0), "),y" }; - case 0x78: return { "cmp $", dp(1), "=#$", b(0) }; - case 0x79: return { "cmp (x)=(y)" }; - case 0x7a: return { "adw $", a() }; - case 0x7b: return { "ror $", dp(0), ",x" }; - case 0x7c: return { "ror" }; - case 0x7d: return { "txa" }; - case 0x7e: return { "cpy $", dp(0) }; - case 0x7f: return { "rti" }; - case 0x80: return { "sec" }; - case 0x81: return { "jst $ffce" }; - case 0x82: return { "set $", dp(0), ":4" }; - case 0x83: return { "bbs $", dp(0), ":4=$", r(+3, 1) }; - case 0x84: return { "adc $", dp(0) }; - case 0x85: return { "adc $", a() }; - case 0x86: return { "adc (x)" }; - case 0x87: return { "adc ($", dp(0), ",x)" }; - case 0x88: return { "adc #$", b(0) }; - case 0x89: return { "adc $", dp(1), "=$", dp(0) }; - case 0x8a: return { "eor $", ab() }; - case 0x8b: return { "dec $", dp(0) }; - case 0x8c: return { "dec $", a() }; - case 0x8d: return { "ldy #$", b(0) }; - case 0x8e: return { "plp" }; - case 0x8f: return { "str $", dp(1), "=#$", b(0) }; - case 0x90: return { "bcc $", r(+2) }; - case 0x91: return { "jst $ffcc" }; - case 0x92: return { "clr $", dp(0), ":4" }; - case 0x93: return { "bbc $", dp(0), ":4=$", r(+3, 1) }; - case 0x94: return { "adc $", dp(0), ",x" }; - case 0x95: return { "adc $", a(), ",x" }; - case 0x96: return { "adc $", a(), ",y" }; - case 0x97: return { "adc ($", dp(0), "),y" }; - case 0x98: return { "adc $", dp(1), "=#$", b(0) }; - case 0x99: return { "adc (x)=(y)" }; - case 0x9a: return { "sbw $", a() }; - case 0x9b: return { "dec $", dp(0), ",x" }; - case 0x9c: return { "dec" }; - case 0x9d: return { "tsx" }; - case 0x9e: return { "div" }; - case 0x9f: return { "xcn" }; - case 0xa0: return { "sei" }; - case 0xa1: return { "jst $ffca" }; - case 0xa2: return { "set $", dp(0), ":5" }; - case 0xa3: return { "bbs $", dp(0), ":5=$", r(+3, 1) }; - case 0xa4: return { "sbc $", dp(0) }; - case 0xa5: return { "sbc $", a() }; - case 0xa6: return { "sbc (x)" }; - case 0xa7: return { "sbc ($", dp(0), ",x)" }; - case 0xa8: return { "sbc #$", b(0) }; - case 0xa9: return { "sbc $", dp(1), "=$", dp(0) }; - case 0xaa: return { "ldc $", ab() }; - case 0xab: return { "inc $", dp(0) }; - case 0xac: return { "inc $", a() }; - case 0xad: return { "cpy #$", b(0) }; - case 0xae: return { "pla" }; - case 0xaf: return { "sta (x++)" }; - case 0xb0: return { "bcs $", r(+2) }; - case 0xb1: return { "jst $ffc8" }; - case 0xb2: return { "clr $", dp(0), ":5" }; - case 0xb3: return { "bbc $", dp(0), ":5=$", r(+3, 1) }; - case 0xb4: return { "sbc $", dp(0), ",x" }; - case 0xb5: return { "sbc $", a(), ",x" }; - case 0xb6: return { "sbc $", a(), ",y" }; - case 0xb7: return { "sbc ($", dp(0), "),y" }; - case 0xb8: return { "sbc $", dp(1), "=#$", b(0) }; - case 0xb9: return { "sbc (x)=(y)" }; - case 0xba: return { "ldw $", dp(0) }; - case 0xbb: return { "inc $", dp(0), ",x" }; - case 0xbc: return { "inc" }; - case 0xbd: return { "txs" }; - case 0xbe: return { "das" }; - case 0xbf: return { "lda (x++)" }; - case 0xc0: return { "cli" }; - case 0xc1: return { "jst $ffc6" }; - case 0xc2: return { "set $", dp(0), ":6" }; - case 0xc3: return { "bbs $", dp(0), ":6=$", r(+3, 1) }; - case 0xc4: return { "sta $", dp(0) }; - case 0xc5: return { "sta $", a() }; - case 0xc6: return { "sta (x)" }; - case 0xc7: return { "sta ($", dp(0), ",x)" }; - case 0xc8: return { "cpx #$", b(0) }; - case 0xc9: return { "stx $", a() }; - case 0xca: return { "stc $", ab() }; - case 0xcb: return { "sty $", dp(0) }; - case 0xcc: return { "sty $", a() }; - case 0xcd: return { "ldx #$", b(0) }; - case 0xce: return { "plx" }; - case 0xcf: return { "mul" }; - case 0xd0: return { "bne $", r(+2) }; - case 0xd1: return { "jst $ffc4" }; - case 0xd2: return { "clr $", dp(0), ":6" }; - case 0xd3: return { "bbc $", dp(0), ":6=$", r(+3, 1) }; - case 0xd4: return { "sta $", dp(0), ",x" }; - case 0xd5: return { "sta $", a(), ",x" }; - case 0xd6: return { "sta $", a(), ",y" }; - case 0xd7: return { "sta ($", dp(0), "),y" }; - case 0xd8: return { "stx $", dp(0) }; - case 0xd9: return { "stx $", dp(0), ",y" }; - case 0xda: return { "stw $", dp(0) }; - case 0xdb: return { "sty $", dp(0), ",x" }; - case 0xdc: return { "dey" }; - case 0xdd: return { "tya" }; - case 0xde: return { "bne $", dp(0), ",x=$", r(+3, 1) }; - case 0xdf: return { "daa" }; - case 0xe0: return { "clv" }; - case 0xe1: return { "jst $ffc2" }; - case 0xe2: return { "set $", dp(0), ":7" }; - case 0xe3: return { "bbs $", dp(0), ":7=$", r(+3, 1) }; - case 0xe4: return { "lda $", dp(0) }; - case 0xe5: return { "lda $", a() }; - case 0xe6: return { "lda (x)" }; - case 0xe7: return { "lda ($", dp(0), ",x)" }; - case 0xe8: return { "lda #$", b(0) }; - case 0xe9: return { "ldx $", a() }; - case 0xea: return { "not $", ab() }; - case 0xeb: return { "ldy $", dp(0) }; - case 0xec: return { "ldy $", a() }; - case 0xed: return { "cmc" }; - case 0xee: return { "ply" }; - case 0xef: return { "wai" }; - case 0xf0: return { "beq $", r(+2) }; - case 0xf1: return { "jst $ffc0" }; - case 0xf2: return { "clr $", dp(0), ":7" }; - case 0xf3: return { "bbc $", dp(0), ":7=$", r(+3, 1) }; - case 0xf4: return { "lda $", dp(0), ",x" }; - case 0xf5: return { "lda $", a(), ",x" }; - case 0xf6: return { "lda $", a(), ",y" }; - case 0xf7: return { "lda ($", dp(0), "),y" }; - case 0xf8: return { "ldx $", dp(0) }; - case 0xf9: return { "ldx $", dp(0), ",y" }; - case 0xfa: return { "str $", dp(1), "=$", dp(0) }; - case 0xfb: return { "ldy $", dp(0), ",x" }; - case 0xfc: return { "iny" }; - case 0xfd: return { "tay" }; - case 0xfe: return { "bne --y=$", r(+2) }; - case 0xff: return { "stp" }; - } - throw; - }; - - string output = { "..", hex<4>(addr), " ", mnemonic() }; - - unsigned length = output.length(); - while(length++ < 30) output.append(" "); - - output.append( - "YA:", hex<4>(regs.ya), - " A:", hex<2>(regs.a), - " X:", hex<2>(regs.x), - " Y:", hex<2>(regs.y), - " S:", hex<2>(regs.s), - " ", - regs.p.n ? "N" : "n", - regs.p.v ? "V" : "v", - regs.p.p ? "P" : "p", - regs.p.b ? "B" : "b", - regs.p.h ? "H" : "h", - regs.p.i ? "I" : "i", - regs.p.z ? "Z" : "z", - regs.p.c ? "C" : "c" - ); - - return output; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/smp/core/memory.hpp b/waterbox/libsnes/bsnes/snes/smp/core/memory.hpp deleted file mode 100644 index 973a2d6840..0000000000 --- a/waterbox/libsnes/bsnes/snes/smp/core/memory.hpp +++ /dev/null @@ -1,28 +0,0 @@ -alwaysinline uint8 op_readpcfirst() { - return op_read(regs.pc++, eCDLog_Flags_ExecFirst); -} - -alwaysinline uint8 op_readpc() { - return op_read(regs.pc++, eCDLog_Flags_ExecOperand); -} - -alwaysinline uint8 op_readsp() { - return op_read(0x0100 | ++regs.s); -} - -alwaysinline void op_writesp(uint8 data) { - return op_write(0x0100 | regs.s--, data); -} - -alwaysinline uint8 op_readdp(uint8 addr) { - return op_read((regs.p.p << 8) + addr); -} - -alwaysinline void op_writedp(uint8 addr, uint8 data) { - return op_write((regs.p.p << 8) + addr, data); -} - -alwaysinline void op_next() { - opcode = op_readpcfirst(); -} - diff --git a/waterbox/libsnes/bsnes/snes/smp/core/opcodes.cpp b/waterbox/libsnes/bsnes/snes/smp/core/opcodes.cpp deleted file mode 100644 index 95b9844f66..0000000000 --- a/waterbox/libsnes/bsnes/snes/smp/core/opcodes.cpp +++ /dev/null @@ -1,559 +0,0 @@ -#ifdef SMPCORE_CPP -#define call (this->*op) - -template -void SMPcore::op_adjust(uint8 &r) { - op_io(); - r = call(r); -} - -template -void SMPcore::op_adjust_addr() { - dp.l = op_readpc(); - dp.h = op_readpc(); - rd = op_read(dp); - rd = call(rd); - op_write(dp, rd); -} - -template -void SMPcore::op_adjust_dp() { - dp = op_readpc(); - rd = op_readdp(dp); - rd = call(rd); - op_writedp(dp, rd); -} - -void SMPcore::op_adjust_dpw(signed n) { - dp = op_readpc(); - rd.w = op_readdp(dp) + n; - op_writedp(dp++, rd.l); - rd.h += op_readdp(dp); - op_writedp(dp++, rd.h); - regs.p.n = rd & 0x8000; - regs.p.z = rd == 0; -} - -template -void SMPcore::op_adjust_dpx() { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = call(rd); - op_writedp(dp + regs.x, rd); -} - -void SMPcore::op_branch(bool condition) { - rd = op_readpc(); - if(condition == false) return; - op_io(); - op_io(); - regs.pc += (int8)rd; -} - -void SMPcore::op_branch_bit() { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((bool)(sp & (1 << (opcode >> 5))) == (bool)(opcode & 0x10)) return; - op_io(); - op_io(); - regs.pc += (int8)rd; -} - -void SMPcore::op_pull(uint8 &r) { - op_io(); - op_io(); - r = op_readsp(); -} - -void SMPcore::op_push(uint8 r) { - op_io(); - op_io(); - op_writesp(r); -} - -template -void SMPcore::op_read_addr(uint8 &r) { - dp.l = op_readpc(); - dp.h = op_readpc(); - rd = op_read(dp); - r = call(r, rd); -} - -template -void SMPcore::op_read_addri(uint8 &r) { - dp.l = op_readpc(); - dp.h = op_readpc(); - op_io(); - rd = op_read(dp + r); - regs.a = call(regs.a, rd); -} - -template -void SMPcore::op_read_const(uint8 &r) { - rd = op_readpc(); - r = call(r, rd); -} - -template -void SMPcore::op_read_dp(uint8 &r) { - dp = op_readpc(); - rd = op_readdp(dp); - r = call(r, rd); -} - -template -void SMPcore::op_read_dpi(uint8 &r, uint8 &i) { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + i); - r = call(r, rd); -} - -template -void SMPcore::op_read_dpw() { - dp = op_readpc(); - rd.l = op_readdp(dp++); - if(op != &SMPcore::op_cpw) op_io(); - rd.h = op_readdp(dp++); - regs.ya = call(regs.ya, rd); -} - -template -void SMPcore::op_read_idpx() { - dp = op_readpc() + regs.x; - op_io(); - sp.l = op_readdp(dp++); - sp.h = op_readdp(dp++); - rd = op_read(sp); - regs.a = call(regs.a, rd); -} - -template -void SMPcore::op_read_idpy() { - dp = op_readpc(); - op_io(); - sp.l = op_readdp(dp++); - sp.h = op_readdp(dp++); - rd = op_read(sp + regs.y); - regs.a = call(regs.a, rd); -} - -template -void SMPcore::op_read_ix() { - op_io(); - rd = op_readdp(regs.x); - regs.a = call(regs.a, rd); -} - -void SMPcore::op_set_addr_bit() { - dp.l = op_readpc(); - dp.h = op_readpc(); - bit = dp >> 13; - dp &= 0x1fff; - rd = op_read(dp); - switch(opcode >> 5) { - case 0: //orc addr:bit - case 1: //orc !addr:bit - op_io(); - regs.p.c |= (rd & (1 << bit)) ^ (bool)(opcode & 0x20); - break; - case 2: //and addr:bit - case 3: //and !addr:bit - regs.p.c &= (rd & (1 << bit)) ^ (bool)(opcode & 0x20); - break; - case 4: //eor addr:bit - op_io(); - regs.p.c ^= (bool)(rd & (1 << bit)); - break; - case 5: //ldc addr:bit - regs.p.c = (rd & (1 << bit)); - break; - case 6: //stc addr:bit - op_io(); - rd = (rd & ~(1 << bit)) | (regs.p.c << bit); - op_write(dp, rd); - break; - case 7: //not addr:bit - rd ^= 1 << bit; - op_write(dp, rd); - break; - } -} - -void SMPcore::op_set_bit() { - dp = op_readpc(); - rd = op_readdp(dp) & ~(1 << (opcode >> 5)); - op_writedp(dp, rd | (!(opcode & 0x10) << (opcode >> 5))); -} - -void SMPcore::op_set_flag(bool &flag, bool data) { - op_io(); - if(&flag == ®s.p.i) op_io(); - flag = data; -} - -void SMPcore::op_test_addr(bool set) { - dp.l = op_readpc(); - dp.h = op_readpc(); - rd = op_read(dp); - regs.p.n = (regs.a - rd) & 0x80; - regs.p.z = (regs.a - rd) == 0; - op_read(dp); - op_write(dp, set ? rd | regs.a : rd & ~regs.a); -} - -void SMPcore::op_transfer(uint8 &from, uint8 &to) { - op_io(); - to = from; - if(&to == ®s.s) return; - regs.p.n = (to & 0x80); - regs.p.z = (to == 0); -} - -void SMPcore::op_write_addr(uint8 &r) { - dp.l = op_readpc(); - dp.h = op_readpc(); - op_read(dp); - op_write(dp, r); -} - -void SMPcore::op_write_addri(uint8 &i) { - dp.l = op_readpc(); - dp.h = op_readpc(); - op_io(); - dp += i; - op_read(dp); - op_write(dp, regs.a); -} - -void SMPcore::op_write_dp(uint8 &r) { - dp = op_readpc(); - op_readdp(dp); - op_writedp(dp, r); -} - -void SMPcore::op_write_dpi(uint8 &r, uint8 &i) { - dp = op_readpc() + i; - op_io(); - op_readdp(dp); - op_writedp(dp, r); -} - -template -void SMPcore::op_write_dp_const() { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = call(wr, rd); - op != &SMPcore::op_cmp ? op_writedp(dp, wr) : op_io(); -} - -template -void SMPcore::op_write_dp_dp() { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - if(op != &SMPcore::op_st) wr = op_readdp(dp); - wr = call(wr, rd); - op != &SMPcore::op_cmp ? op_writedp(dp, wr) : op_io(); -} - -template -void SMPcore::op_write_ix_iy() { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = call(wr, rd); - op != &SMPcore::op_cmp ? op_writedp(regs.x, wr) : op_io(); -} - -// - -void SMPcore::op_bne_dp() { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if(regs.a == sp) return; - op_io(); - op_io(); - regs.pc += (int8)rd; -} - -void SMPcore::op_bne_dpdec() { - dp = op_readpc(); - wr = op_readdp(dp); - op_writedp(dp, --wr); - rd = op_readpc(); - if(wr == 0) return; - op_io(); - op_io(); - regs.pc += (int8)rd; -} - -void SMPcore::op_bne_dpx() { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp + regs.x); - rd = op_readpc(); - op_io(); - if(regs.a == sp) return; - op_io(); - op_io(); - regs.pc += (int8)rd; -} - -void SMPcore::op_bne_ydec() { - rd = op_readpc(); - op_io(); - op_io(); - if(--regs.y == 0) return; - op_io(); - op_io(); - regs.pc += (int8)rd; -} - -void SMPcore::op_brk() { - rd.l = op_read(0xffde); - rd.h = op_read(0xffdf); - op_io(); - op_io(); - op_writesp(regs.pc.h); - op_writesp(regs.pc.l); - op_writesp(regs.p); - regs.pc = rd; - regs.p.b = 1; - regs.p.i = 0; -} - -void SMPcore::op_clv() { - op_io(); - regs.p.v = 0; - regs.p.h = 0; -} - -void SMPcore::op_cmc() { - op_io(); - op_io(); - regs.p.c = !regs.p.c; -} - -void SMPcore::op_daa() { - op_io(); - op_io(); - if(regs.p.c || (regs.a) > 0x99) { - regs.a += 0x60; - regs.p.c = 1; - } - if(regs.p.h || (regs.a & 15) > 0x09) { - regs.a += 0x06; - } - regs.p.n = (regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -void SMPcore::op_das() { - op_io(); - op_io(); - if(!regs.p.c || (regs.a) > 0x99) { - regs.a -= 0x60; - regs.p.c = 0; - } - if(!regs.p.h || (regs.a & 15) > 0x09) { - regs.a -= 0x06; - } - regs.p.n = (regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -void SMPcore::op_div_ya_x() { - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - ya = regs.ya; - //overflow set if quotient >= 256 - regs.p.v = (regs.y >= regs.x); - regs.p.h = ((regs.y & 15) >= (regs.x & 15)); - if(regs.y < (regs.x << 1)) { - //if quotient is <= 511 (will fit into 9-bit result) - regs.a = ya / regs.x; - regs.y = ya % regs.x; - } else { - //otherwise, the quotient won't fit into regs.p.v + regs.a - //this emulates the odd behavior of the S-SMP in this case - regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); - regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); - } - //result is set based on a (quotient) only - regs.p.n = (regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -void SMPcore::op_jmp_addr() { - rd.l = op_readpc(); - rd.h = op_readpc(); - regs.pc = rd; -} - -void SMPcore::op_jmp_iaddrx() { - dp.l = op_readpc(); - dp.h = op_readpc(); - op_io(); - dp += regs.x; - rd.l = op_read(dp++); - rd.h = op_read(dp++); - regs.pc = rd; -} - -void SMPcore::op_jsp_dp() { - rd = op_readpc(); - op_io(); - op_io(); - op_writesp(regs.pc.h); - op_writesp(regs.pc.l); - regs.pc = 0xff00 | rd; -} - -void SMPcore::op_jsr_addr() { - rd.l = op_readpc(); - rd.h = op_readpc(); - op_io(); - op_io(); - op_io(); - op_writesp(regs.pc.h); - op_writesp(regs.pc.l); - regs.pc = rd; -} - -void SMPcore::op_jst() { - dp = 0xffde - ((opcode >> 4) << 1); - rd.l = op_read(dp++); - rd.h = op_read(dp++); - op_io(); - op_io(); - op_io(); - op_writesp(regs.pc.h); - op_writesp(regs.pc.l); - regs.pc = rd; -} - -void SMPcore::op_lda_ixinc() { - op_io(); - regs.a = op_readdp(regs.x++); - op_io(); - regs.p.n = regs.a & 0x80; - regs.p.z = regs.a == 0; -} - -void SMPcore::op_mul_ya() { - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - op_io(); - ya = regs.y * regs.a; - regs.a = ya; - regs.y = ya >> 8; - //result is set based on y (high-byte) only - regs.p.n = (regs.y & 0x80); - regs.p.z = (regs.y == 0); -} - -void SMPcore::op_nop() { - op_io(); -} - -void SMPcore::op_plp() { - op_io(); - op_io(); - regs.p = op_readsp(); -} - -void SMPcore::op_rti() { - regs.p = op_readsp(); - rd.l = op_readsp(); - rd.h = op_readsp(); - op_io(); - op_io(); - regs.pc = rd; -} - -void SMPcore::op_rts() { - rd.l = op_readsp(); - rd.h = op_readsp(); - op_io(); - op_io(); - regs.pc = rd; -} - -void SMPcore::op_sta_idpx() { - sp = op_readpc() + regs.x; - op_io(); - dp.l = op_readdp(sp++); - dp.h = op_readdp(sp++); - op_read(dp); - op_write(dp, regs.a); -} - -void SMPcore::op_sta_idpy() { - sp = op_readpc(); - dp.l = op_readdp(sp++); - dp.h = op_readdp(sp++); - op_io(); - dp += regs.y; - op_read(dp); - op_write(dp, regs.a); -} - -void SMPcore::op_sta_ix() { - op_io(); - op_readdp(regs.x); - op_writedp(regs.x, regs.a); -} - -void SMPcore::op_sta_ixinc() { - op_io(); - op_io(); - op_writedp(regs.x++, regs.a); -} - -void SMPcore::op_stw_dp() { - dp = op_readpc(); - op_readdp(dp); - op_writedp(dp++, regs.a); - op_writedp(dp++, regs.y); -} - -void SMPcore::op_wait() { - while(true) { - op_io(); - op_io(); - } -} - -void SMPcore::op_xcn() { - op_io(); - op_io(); - op_io(); - op_io(); - regs.a = (regs.a >> 4) | (regs.a << 4); - regs.p.n = regs.a & 0x80; - regs.p.z = regs.a == 0; -} - -#undef call -#endif diff --git a/waterbox/libsnes/bsnes/snes/smp/core/registers.hpp b/waterbox/libsnes/bsnes/snes/smp/core/registers.hpp deleted file mode 100644 index 48aa92c82f..0000000000 --- a/waterbox/libsnes/bsnes/snes/smp/core/registers.hpp +++ /dev/null @@ -1,51 +0,0 @@ -struct flag_t { - bool n, v, p, b, h, i, z, c; - - inline operator unsigned() const { - return (n << 7) | (v << 6) | (p << 5) | (b << 4) - | (h << 3) | (i << 2) | (z << 1) | (c << 0); - } - - inline unsigned operator=(uint8 data) { - n = data & 0x80; v = data & 0x40; p = data & 0x20; b = data & 0x10; - h = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01; - return data; - } - - inline unsigned operator|=(uint8 data) { return operator=(operator unsigned() | data); } - inline unsigned operator^=(uint8 data) { return operator=(operator unsigned() ^ data); } - inline unsigned operator&=(uint8 data) { return operator=(operator unsigned() & data); } -}; - -struct word_t { - union { - uint16 w; - struct { uint8 order_lsb2(l, h); }; - }; - - inline operator unsigned() const { return w; } - inline unsigned operator=(unsigned data) { return w = data; } - - inline unsigned operator++() { return ++w; } - inline unsigned operator--() { return --w; } - - inline unsigned operator++(int) { unsigned data = w++; return data; } - inline unsigned operator--(int) { unsigned data = w--; return data; } - - inline unsigned operator+=(unsigned data) { return w += data;; } - inline unsigned operator-=(unsigned data) { return w -= data;; } - - inline unsigned operator|=(unsigned data) { return w |= data; } - inline unsigned operator^=(unsigned data) { return w ^= data; } - inline unsigned operator&=(unsigned data) { return w &= data; } -}; - -struct regs_t { - word_t pc; - union { - uint16 ya; - struct { uint8 order_lsb2(a, y); }; - }; - uint8 x, s; - flag_t p; -}; diff --git a/waterbox/libsnes/bsnes/snes/smp/iplrom.cpp b/waterbox/libsnes/bsnes/snes/smp/iplrom.cpp deleted file mode 100644 index a2ade89d94..0000000000 --- a/waterbox/libsnes/bsnes/snes/smp/iplrom.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#ifdef SMP_CPP - -//this is the IPLROM for the S-SMP coprocessor. -//the S-SMP does not allow writing to the IPLROM. -//all writes are instead mapped to the extended -//RAM region, accessible when $f1.d7 is clear. - -const uint8 SMP::iplrom[64] = { -/*ffc0*/ 0xcd, 0xef, //mov x,#$ef -/*ffc2*/ 0xbd, //mov sp,x -/*ffc3*/ 0xe8, 0x00, //mov a,#$00 -/*ffc5*/ 0xc6, //mov (x),a -/*ffc6*/ 0x1d, //dec x -/*ffc7*/ 0xd0, 0xfc, //bne $ffc5 -/*ffc9*/ 0x8f, 0xaa, 0xf4, //mov $f4,#$aa -/*ffcc*/ 0x8f, 0xbb, 0xf5, //mov $f5,#$bb -/*ffcf*/ 0x78, 0xcc, 0xf4, //cmp $f4,#$cc -/*ffd2*/ 0xd0, 0xfb, //bne $ffcf -/*ffd4*/ 0x2f, 0x19, //bra $ffef -/*ffd6*/ 0xeb, 0xf4, //mov y,$f4 -/*ffd8*/ 0xd0, 0xfc, //bne $ffd6 -/*ffda*/ 0x7e, 0xf4, //cmp y,$f4 -/*ffdc*/ 0xd0, 0x0b, //bne $ffe9 -/*ffde*/ 0xe4, 0xf5, //mov a,$f5 -/*ffe0*/ 0xcb, 0xf4, //mov $f4,y -/*ffe2*/ 0xd7, 0x00, //mov ($00)+y,a -/*ffe4*/ 0xfc, //inc y -/*ffe5*/ 0xd0, 0xf3, //bne $ffda -/*ffe7*/ 0xab, 0x01, //inc $01 -/*ffe9*/ 0x10, 0xef, //bpl $ffda -/*ffeb*/ 0x7e, 0xf4, //cmp y,$f4 -/*ffed*/ 0x10, 0xeb, //bpl $ffda -/*ffef*/ 0xba, 0xf6, //movw ya,$f6 -/*fff1*/ 0xda, 0x00, //movw $00,ya -/*fff3*/ 0xba, 0xf4, //movw ya,$f4 -/*fff5*/ 0xc4, 0xf4, //mov $f4,a -/*fff7*/ 0xdd, //mov a,y -/*fff8*/ 0x5d, //mov x,a -/*fff9*/ 0xd0, 0xdb, //bne $ffd6 -/*fffb*/ 0x1f, 0x00, 0x00, //jmp ($0000+x) -/*fffe*/ 0xc0, 0xff //reset vector location ($ffc0) -}; - -#endif diff --git a/waterbox/libsnes/bsnes/snes/smp/memory/memory.cpp b/waterbox/libsnes/bsnes/snes/smp/memory/memory.cpp deleted file mode 100644 index b46dc45802..0000000000 --- a/waterbox/libsnes/bsnes/snes/smp/memory/memory.cpp +++ /dev/null @@ -1,203 +0,0 @@ -#ifdef SMP_CPP - -alwaysinline uint8 SMP::ram_read(uint16 addr) { - if(addr >= 0xffc0 && status.iplrom_enable) return iplrom[addr & 0x3f]; - if(status.ram_disable) return 0x5a; //0xff on mini-SNES - return apuram[addr]; -} - -alwaysinline void SMP::ram_write(uint16 addr, uint8 data) { - //writes to $ffc0-$ffff always go to apuram, even if the iplrom is enabled - if(status.ram_writable && !status.ram_disable) apuram[addr] = data; -} - -uint8 SMP::port_read(uint2 port) const { - return apuram[0xf4 + port]; -} - -void SMP::port_write(uint2 port, uint8 data) { - apuram[0xf4 + port] = data; -} - -uint8 SMP::op_busread(uint16 addr) { - unsigned result; - - switch(addr) { - case 0xf0: //TEST -- write-only register - return 0x00; - - case 0xf1: //CONTROL -- write-only register - return 0x00; - - case 0xf2: //DSPADDR - return status.dsp_addr; - - case 0xf3: //DSPDATA - //0x80-0xff are read-only mirrors of 0x00-0x7f - return dsp.read(status.dsp_addr & 0x7f); - - case 0xf4: //CPUIO0 - case 0xf5: //CPUIO1 - case 0xf6: //CPUIO2 - case 0xf7: //CPUIO3 - synchronize_cpu(); - return cpu.port_read(addr); - - case 0xf8: //RAM0 - return status.ram00f8; - - case 0xf9: //RAM1 - return status.ram00f9; - - case 0xfa: //T0TARGET - case 0xfb: //T1TARGET - case 0xfc: //T2TARGET -- write-only registers - return 0x00; - - case 0xfd: //T0OUT -- 4-bit counter value - result = timer0.stage3_ticks; - timer0.stage3_ticks = 0; - return result; - - case 0xfe: //T1OUT -- 4-bit counter value - result = timer1.stage3_ticks; - timer1.stage3_ticks = 0; - return result; - - case 0xff: //T2OUT -- 4-bit counter value - result = timer2.stage3_ticks; - timer2.stage3_ticks = 0; - return result; - } - - cdlInfo.set(eCDLog_AddrType_APURAM, addr); - return ram_read(addr); -} - -void SMP::op_buswrite(uint16 addr, uint8 data) { - switch(addr) { - case 0xf0: //TEST - if(regs.p.p) break; //writes only valid when P flag is clear - - status.clock_speed = (data >> 6) & 3; - status.timer_speed = (data >> 4) & 3; - status.timers_enable = data & 0x08; - status.ram_disable = data & 0x04; - status.ram_writable = data & 0x02; - status.timers_disable = data & 0x01; - - status.timer_step = (1 << status.clock_speed) + (2 << status.timer_speed); - - timer0.synchronize_stage1(); - timer1.synchronize_stage1(); - timer2.synchronize_stage1(); - break; - - case 0xf1: //CONTROL - status.iplrom_enable = data & 0x80; - - if(data & 0x30) { - //one-time clearing of APU port read registers, - //emulated by simulating CPU writes of 0x00 - synchronize_cpu(); - if(data & 0x20) { - cpu.port_write(2, 0x00); - cpu.port_write(3, 0x00); - } - if(data & 0x10) { - cpu.port_write(0, 0x00); - cpu.port_write(1, 0x00); - } - } - - //0->1 transistion resets timers - if(timer2.enable == false && (data & 0x04)) { - timer2.stage2_ticks = 0; - timer2.stage3_ticks = 0; - } - timer2.enable = data & 0x04; - - if(timer1.enable == false && (data & 0x02)) { - timer1.stage2_ticks = 0; - timer1.stage3_ticks = 0; - } - timer1.enable = data & 0x02; - - if(timer0.enable == false && (data & 0x01)) { - timer0.stage2_ticks = 0; - timer0.stage3_ticks = 0; - } - timer0.enable = data & 0x01; - break; - - case 0xf2: //DSPADDR - status.dsp_addr = data; - break; - - case 0xf3: //DSPDATA - if(status.dsp_addr & 0x80) break; //0x80-0xff are read-only mirrors of 0x00-0x7f - dsp.write(status.dsp_addr & 0x7f, data); - break; - - case 0xf4: //CPUIO0 - case 0xf5: //CPUIO1 - case 0xf6: //CPUIO2 - case 0xf7: //CPUIO3 - synchronize_cpu(); - port_write(addr, data); - break; - - case 0xf8: //RAM0 - status.ram00f8 = data; - break; - - case 0xf9: //RAM1 - status.ram00f9 = data; - break; - - case 0xfa: //T0TARGET - timer0.target = data; - break; - - case 0xfb: //T1TARGET - timer1.target = data; - break; - - case 0xfc: //T2TARGET - timer2.target = data; - break; - - case 0xfd: //T0OUT - case 0xfe: //T1OUT - case 0xff: //T2OUT -- read-only registers - break; - } - - ram_write(addr, data); //all writes, even to MMIO registers, appear on bus -} - -void SMP::op_io() { - add_clocks(24); - cycle_edge(); -} - -uint8 SMP::op_read(uint16 addr, eCDLog_Flags flags) { - debugger.op_read(addr); - - add_clocks(12); - cdlInfo.currFlags = flags; - uint8 r = op_busread(addr); - add_clocks(12); - cycle_edge(); - return r; -} - -void SMP::op_write(uint16 addr, uint8 data) { - debugger.op_write(addr, data); - - add_clocks(24); - op_buswrite(addr, data); - cycle_edge(); -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/smp/memory/memory.hpp b/waterbox/libsnes/bsnes/snes/smp/memory/memory.hpp deleted file mode 100644 index 717947abef..0000000000 --- a/waterbox/libsnes/bsnes/snes/smp/memory/memory.hpp +++ /dev/null @@ -1,9 +0,0 @@ -uint8 ram_read(uint16 addr); -void ram_write(uint16 addr, uint8 data); - -uint8 op_busread(uint16 addr); -void op_buswrite(uint16 addr, uint8 data); - -void op_io(); -uint8 op_read(uint16 addr, eCDLog_Flags flags = eCDLog_Flags_CPUData); -void op_write(uint16 addr, uint8 data); diff --git a/waterbox/libsnes/bsnes/snes/smp/smp.cpp b/waterbox/libsnes/bsnes/snes/smp/smp.cpp deleted file mode 100644 index 8d84b8f61c..0000000000 --- a/waterbox/libsnes/bsnes/snes/smp/smp.cpp +++ /dev/null @@ -1,139 +0,0 @@ -#include - -#define SMP_CPP -namespace SNES { - -SMP smp; - -#include "iplrom.cpp" -#include "memory/memory.cpp" -#include "timing/timing.cpp" - -void SMP::step(unsigned clocks) { - clock += clocks * (uint64)cpu.frequency; - dsp.clock -= clocks; -} - -void SMP::synchronize_cpu() { - if(CPU::Threaded == true) { - if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); - } else { - while(clock >= 0) cpu.enter(); - } -} - -void SMP::synchronize_dsp() { - if(DSP::Threaded == true) { - if(dsp.clock < 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(dsp.thread); - } else { - while(dsp.clock < 0) dsp.enter(); - } -} - -void SMP::Enter() { smp.enter(); } - -void SMP::enter() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - debugger.op_exec(regs.pc); - if(interface()->wanttrace & TRACE_SMP_MASK) - { - auto str = disassemble_opcode(regs.pc); - interface()->cpuTrace(TRACE_SMP, (const char*)str); - } - op_step(); - } -} - -void SMP::power() { - //targets not initialized/changed upon reset - timer0.target = 0; - timer1.target = 0; - timer2.target = 0; - - //zero 01-dec-2012 - //gotta clear these to something, sometime - dp.w = sp.w = rd.w = wr.w = bit.w = ya.w = 0; -} - -void SMP::reset() { - create(Enter, system.apu_frequency(), 16384); - - regs.pc = 0xffc0; - regs.a = 0x00; - regs.x = 0x00; - regs.y = 0x00; - regs.s = 0xef; - regs.p = 0x02; - - for(int i=0;i<64*1024;i++) apuram[i] = random(0x00); - apuram[0x00f4] = 0x00; - apuram[0x00f5] = 0x00; - apuram[0x00f6] = 0x00; - apuram[0x00f7] = 0x00; - - status.clock_counter = 0; - status.dsp_counter = 0; - status.timer_step = 3; - - //$00f0 - status.clock_speed = 0; - status.timer_speed = 0; - status.timers_enable = true; - status.ram_disable = false; - status.ram_writable = true; - status.timers_disable = false; - - //$00f1 - status.iplrom_enable = true; - - //$00f2 - status.dsp_addr = 0x00; - - //$00f8,$00f9 - status.ram00f8 = 0x00; - status.ram00f9 = 0x00; - - timer0.stage0_ticks = 0; - timer1.stage0_ticks = 0; - timer2.stage0_ticks = 0; - - timer0.stage1_ticks = 0; - timer1.stage1_ticks = 0; - timer2.stage1_ticks = 0; - - timer0.stage2_ticks = 0; - timer1.stage2_ticks = 0; - timer2.stage2_ticks = 0; - - timer0.stage3_ticks = 0; - timer1.stage3_ticks = 0; - timer2.stage3_ticks = 0; - - timer0.current_line = 0; - timer1.current_line = 0; - timer2.current_line = 0; - - timer0.enable = false; - timer1.enable = false; - timer2.enable = false; -} - -SMP::SMP() - : apuram(nullptr) -{ -} - -SMP::~SMP() { - interface()->freeSharedMemory(apuram); -} - -void SMP::initialize() -{ - apuram = (uint8*)interface()->allocSharedMemory("APURAM",64 * 1024); -} - -} diff --git a/waterbox/libsnes/bsnes/snes/smp/smp.hpp b/waterbox/libsnes/bsnes/snes/smp/smp.hpp deleted file mode 100644 index 2923092c38..0000000000 --- a/waterbox/libsnes/bsnes/snes/smp/smp.hpp +++ /dev/null @@ -1,61 +0,0 @@ -struct SMP : public Processor, public SMPcore { - static const uint8 iplrom[64]; - uint8* apuram; //[64 * 1024]; - - enum : bool { Threaded = true }; - alwaysinline void step(unsigned clocks); - alwaysinline void synchronize_cpu(); - alwaysinline void synchronize_dsp(); - - uint8 port_read(uint2 port) const; - void port_write(uint2 port, uint8 data); - - void enter(); - void power(); - void reset(); - - SMP(); - ~SMP(); - void initialize(); - - struct Debugger { - hook op_exec; - hook op_read; - hook op_write; - } debugger; - -privileged: - #include "memory/memory.hpp" - #include "timing/timing.hpp" - - struct { - //timing - unsigned clock_counter; - unsigned dsp_counter; - unsigned timer_step; - - //$00f0 - uint8 clock_speed; - uint8 timer_speed; - bool timers_enable; - bool ram_disable; - bool ram_writable; - bool timers_disable; - - //$00f1 - bool iplrom_enable; - - //$00f2 - uint8 dsp_addr; - - //$00f8,$00f9 - uint8 ram00f8; - uint8 ram00f9; - } status; - - static void Enter(); - - friend class SMPcore; -}; - -extern SMP smp; diff --git a/waterbox/libsnes/bsnes/snes/smp/timing/timing.cpp b/waterbox/libsnes/bsnes/snes/smp/timing/timing.cpp deleted file mode 100644 index 3709ba9887..0000000000 --- a/waterbox/libsnes/bsnes/snes/smp/timing/timing.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifdef SMP_CPP - -void SMP::add_clocks(unsigned clocks) { - step(clocks); - synchronize_dsp(); - - #if defined(DEBUGGER) - synchronize_cpu(); - #else - //forcefully sync S-SMP to S-CPU in case chips are not communicating - //sync if S-SMP is more than 24 samples ahead of S-CPU - if(clock > +(768 * 24 * (int64)24000000)) synchronize_cpu(); - #endif -} - -void SMP::cycle_edge() { - timer0.tick(); - timer1.tick(); - timer2.tick(); - - //TEST register S-SMP speed control - //24 clocks have already been added for this cycle at this point - switch(status.clock_speed) { - case 0: break; //100% speed - case 1: add_clocks(24); break; // 50% speed - case 2: while(true) add_clocks(24); // 0% speed -- locks S-SMP - case 3: add_clocks(24 * 9); break; // 10% speed - } -} - -template -void SMP::Timer::tick() { - //stage 0 increment - stage0_ticks += smp.status.timer_step; - if(stage0_ticks < timer_frequency) return; - stage0_ticks -= timer_frequency; - - //stage 1 increment - stage1_ticks ^= 1; - synchronize_stage1(); -} - -template -void SMP::Timer::synchronize_stage1() { - bool new_line = stage1_ticks; - if(smp.status.timers_enable == false) new_line = false; - if(smp.status.timers_disable == true) new_line = false; - - bool old_line = current_line; - current_line = new_line; - if(old_line != 1 || new_line != 0) return; //only pulse on 1->0 transition - - //stage 2 increment - if(enable == false) return; - if(++stage2_ticks != target) return; - - //stage 3 increment - stage2_ticks = 0; - stage3_ticks++; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/smp/timing/timing.hpp b/waterbox/libsnes/bsnes/snes/smp/timing/timing.hpp deleted file mode 100644 index 2c282455b5..0000000000 --- a/waterbox/libsnes/bsnes/snes/smp/timing/timing.hpp +++ /dev/null @@ -1,21 +0,0 @@ -template -class Timer { -public: - uint8 stage0_ticks; - uint8 stage1_ticks; - uint8 stage2_ticks; - uint4 stage3_ticks; - bool current_line; - bool enable; - uint8 target; - - void tick(); - void synchronize_stage1(); -}; - -Timer<192> timer0; -Timer<192> timer1; -Timer< 24> timer2; - -alwaysinline void add_clocks(unsigned clocks); -alwaysinline void cycle_edge(); diff --git a/waterbox/libsnes/bsnes/snes/snes.hpp b/waterbox/libsnes/bsnes/snes/snes.hpp deleted file mode 100644 index 6ca7ae969b..0000000000 --- a/waterbox/libsnes/bsnes/snes/snes.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef SNES_HPP -#define SNES_HPP - -#include -#include - -/* - bsnes - SNES emulator - author: byuu - license: GPLv3 - project started: 2004-10-14 -*/ - -#include - -#if defined(GAMEBOY) - #include -#endif - -namespace SNES { - struct Processor { - cothread_t thread; - unsigned frequency; - int64 clock; - - inline void create(void (*entrypoint)(), unsigned frequency, int size) { - if(thread) co_delete(thread); - thread = co_create(size * sizeof(void*), entrypoint); - this->frequency = frequency; - clock = 0; - } - - inline Processor() : thread(nullptr) { - } - - inline ~Processor() { - if(thread) co_delete(thread); - } - }; - - #include - #include - #include - #include - - #if defined(PROFILE_ACCURACY) - #include "profile-accuracy.hpp" - #elif defined(PROFILE_COMPATIBILITY) - #include "profile-compatibility.hpp" - #elif defined(PROFILE_PERFORMANCE) - #include "profile-performance.hpp" - #endif - - #include - #include - #include - #include - #include - - #include - #include -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/system/audio.cpp b/waterbox/libsnes/bsnes/snes/system/audio.cpp deleted file mode 100644 index 5a8722cd64..0000000000 --- a/waterbox/libsnes/bsnes/snes/system/audio.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#ifdef SYSTEM_CPP - -Audio audio; - -void Audio::coprocessor_enable(bool state) { - coprocessor = state; - dspaudio.clear(); - - dsp_rdoffset = cop_rdoffset = 0; - dsp_wroffset = cop_wroffset = 0; - dsp_length = cop_length = 0; -} - -void Audio::coprocessor_frequency(double input_frequency) { - dspaudio.setFrequency(input_frequency); - dspaudio.setResampler(nall::DSP::ResampleEngine::Sinc); - dspaudio.setResamplerFrequency(system.apu_frequency() / 768.0); -} - -void Audio::sample(int16 lsample, int16 rsample) { - if(coprocessor == false) return interface()->audioSample(lsample, rsample); - - dsp_buffer[dsp_wroffset] = ((uint16)lsample << 0) + ((uint16)rsample << 16); - dsp_wroffset = (dsp_wroffset + 1) & buffer_mask; - dsp_length = (dsp_length + 1) & buffer_mask; - flush(); -} - -void Audio::coprocessor_sample(int16 lsample, int16 rsample) { - signed samples[] = { lsample, rsample }; - dspaudio.sample(samples); - while(dspaudio.pending()) { - dspaudio.read(samples); - - cop_buffer[cop_wroffset] = ((uint16)samples[0] << 0) + ((uint16)samples[1] << 16); - cop_wroffset = (cop_wroffset + 1) & buffer_mask; - cop_length = (cop_length + 1) & buffer_mask; - flush(); - } -} - -void Audio::init() { -} - -void Audio::flush() { - while(dsp_length > 0 && cop_length > 0) { - uint32 dsp_sample = dsp_buffer[dsp_rdoffset]; - uint32 cop_sample = cop_buffer[cop_rdoffset]; - - dsp_rdoffset = (dsp_rdoffset + 1) & buffer_mask; - cop_rdoffset = (cop_rdoffset + 1) & buffer_mask; - - dsp_length--; - cop_length--; - - signed dsp_left = (int16)(dsp_sample >> 0); - signed dsp_right = (int16)(dsp_sample >> 16); - - signed cop_left = (int16)(cop_sample >> 0); - signed cop_right = (int16)(cop_sample >> 16); - - interface()->audioSample( - sclamp<16>((dsp_left + cop_left ) / 2), - sclamp<16>((dsp_right + cop_right) / 2) - ); - } -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/system/audio.hpp b/waterbox/libsnes/bsnes/snes/system/audio.hpp deleted file mode 100644 index 1b4dc36550..0000000000 --- a/waterbox/libsnes/bsnes/snes/system/audio.hpp +++ /dev/null @@ -1,20 +0,0 @@ -struct Audio { - void coprocessor_enable(bool state); - void coprocessor_frequency(double frequency); - void sample(int16 lsample, int16 rsample); - void coprocessor_sample(int16 lsample, int16 rsample); - void init(); - -private: - nall::DSP dspaudio; - bool coprocessor; - enum : unsigned { buffer_size = 256, buffer_mask = buffer_size - 1 }; - uint32 dsp_buffer[buffer_size], cop_buffer[buffer_size]; - unsigned dsp_rdoffset, cop_rdoffset; - unsigned dsp_wroffset, cop_wroffset; - unsigned dsp_length, cop_length; - - void flush(); -}; - -extern Audio audio; diff --git a/waterbox/libsnes/bsnes/snes/system/input.cpp b/waterbox/libsnes/bsnes/snes/system/input.cpp deleted file mode 100644 index 894de0e763..0000000000 --- a/waterbox/libsnes/bsnes/snes/system/input.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifdef SYSTEM_CPP - -Input input; - -void Input::connect(bool port, Input::Device id) { - Controller *&controller = (port == Controller::Port1 ? port1 : port2); - if(controller) { - delete controller; - controller = nullptr; - } - - switch(id) { default: - case Device::None: controller = new Controller(port); break; - case Device::Joypad: controller = new Gamepad(port); break; - case Device::Multitap: controller = new Multitap(port); break; - case Device::Mouse: controller = new Mouse(port); break; - case Device::SuperScope: controller = new SuperScope(port); break; - case Device::Justifier: controller = new Justifier(port, false); break; - case Device::Justifiers: controller = new Justifier(port, true); break; - case Device::USART: controller = new USART(port); break; - } - - switch(port) { - case Controller::Port1: config.controller_port1 = id; break; - case Controller::Port2: config.controller_port2 = id; break; - } -} - -Input::Input() : port1(nullptr), port2(nullptr) { - connect(Controller::Port1, Input::Device::Joypad); - connect(Controller::Port2, Input::Device::Joypad); -} - -Input::~Input() { - if(port1) delete port1; - if(port2) delete port2; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/system/input.hpp b/waterbox/libsnes/bsnes/snes/system/input.hpp deleted file mode 100644 index 7a6bd9e705..0000000000 --- a/waterbox/libsnes/bsnes/snes/system/input.hpp +++ /dev/null @@ -1,39 +0,0 @@ -struct Input { - enum class Device : unsigned { - None, - Joypad, - Multitap, - Mouse, - SuperScope, - Justifier, - Justifiers, - USART, - }; - - enum class JoypadID : unsigned { - B = 0, Y = 1, Select = 2, Start = 3, - Up = 4, Down = 5, Left = 6, Right = 7, - A = 8, X = 9, L = 10, R = 11, - }; - - enum class MouseID : unsigned { - X = 0, Y = 1, Left = 2, Right = 3, - }; - - enum class SuperScopeID : unsigned { - X = 0, Y = 1, Trigger = 2, Cursor = 3, Turbo = 4, Pause = 5, - }; - - enum class JustifierID : unsigned { - X = 0, Y = 1, Trigger = 2, Start = 3, - }; - - Controller *port1; - Controller *port2; - - void connect(bool port, Input::Device id); - Input(); - ~Input(); -}; - -extern Input input; diff --git a/waterbox/libsnes/bsnes/snes/system/system.cpp b/waterbox/libsnes/bsnes/snes/system/system.cpp deleted file mode 100644 index 8836b03fd7..0000000000 --- a/waterbox/libsnes/bsnes/snes/system/system.cpp +++ /dev/null @@ -1,264 +0,0 @@ -#include - -#define SYSTEM_CPP -namespace SNES { - -System system; - -#include -#include -#include - -#include "video.cpp" -#include "audio.cpp" -#include "input.cpp" - -void System::run() { - scheduler.sync = Scheduler::SynchronizeMode::None; - - scheduler.enter(); - if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) { - video.update(); - } -} - -void System::runtosave() { - if(CPU::Threaded == true) { - scheduler.sync = Scheduler::SynchronizeMode::CPU; - runthreadtosave(); - } - - if(SMP::Threaded == true) { - scheduler.thread = smp.thread; - runthreadtosave(); - } - - if(PPU::Threaded == true) { - scheduler.thread = ppu.thread; - runthreadtosave(); - } - - if(DSP::Threaded == true) { - scheduler.thread = dsp.thread; - runthreadtosave(); - } - - for(unsigned i = 0; i < cpu.coprocessors.size(); i++) { - Processor &chip = *cpu.coprocessors[i]; - scheduler.thread = chip.thread; - runthreadtosave(); - } -} - -void System::runthreadtosave() { - while(true) { - scheduler.enter(); - if(scheduler.exit_reason() == Scheduler::ExitReason::SynchronizeEvent) break; - if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) { - video.update(); - } - } -} - -void System::init() { - assert(interface != 0); - - #if defined(GAMEBOY) - icd2.init(); - #endif - nss.init(); - superfx.init(); - sa1.init(); - necdsp.init(); - hitachidsp.init(); - armdsp.init(); - bsxsatellaview.init(); - bsxcartridge.init(); - bsxflash.init(); - srtc.init(); - sdd1.init(); - spc7110.init(); - obc1.init(); - msu1.init(); - link.init(); - - video.init(); - audio.init(); - - input.connect(0, config.controller_port1); - input.connect(1, config.controller_port2); -} - -void System::term() { -} - -void System::load() { - audio.coprocessor_enable(false); - - bus.map_reset(); - bus.map_xml(); - - cpu.enable(); - ppu.enable(); - - if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.load(); - if(cartridge.mode() == Cartridge::Mode::Bsx) bsxcartridge.load(); - if(cartridge.mode() == Cartridge::Mode::SufamiTurbo) sufamiturbo.load(); - #if defined(GAMEBOY) - if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) icd2.load(); - #endif - - if(cartridge.has_bsx_slot()) bsxflash.load(); - if(cartridge.has_nss_dip()) nss.load(); - if(cartridge.has_superfx()) superfx.load(); - if(cartridge.has_sa1()) sa1.load(); - if(cartridge.has_necdsp()) necdsp.load(); - if(cartridge.has_hitachidsp()) hitachidsp.load(); - if(cartridge.has_armdsp()) armdsp.load(); - if(cartridge.has_srtc()) srtc.load(); - if(cartridge.has_sdd1()) sdd1.load(); - if(cartridge.has_spc7110()) spc7110.load(); - if(cartridge.has_obc1()) obc1.load(); - if(cartridge.has_msu1()) msu1.load(); - if(cartridge.has_link()) link.load(); -} - -void System::unload() { - if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.unload(); - if(cartridge.mode() == Cartridge::Mode::Bsx) bsxcartridge.unload(); - if(cartridge.mode() == Cartridge::Mode::SufamiTurbo) sufamiturbo.unload(); - #if defined(GAMEBOY) - if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) icd2.unload(); - #endif - - if(cartridge.has_bsx_slot()) bsxflash.unload(); - if(cartridge.has_nss_dip()) nss.unload(); - if(cartridge.has_superfx()) superfx.unload(); - if(cartridge.has_sa1()) sa1.unload(); - if(cartridge.has_necdsp()) necdsp.unload(); - if(cartridge.has_hitachidsp()) hitachidsp.unload(); - if(cartridge.has_armdsp()) armdsp.unload(); - if(cartridge.has_srtc()) srtc.unload(); - if(cartridge.has_sdd1()) sdd1.unload(); - if(cartridge.has_spc7110()) spc7110.unload(); - if(cartridge.has_obc1()) obc1.unload(); - if(cartridge.has_msu1()) msu1.unload(); - if(cartridge.has_link()) link.unload(); -} - -void System::power() { - random.seed((unsigned)interface()->randomSeed()); - - region = config.region; - expansion = config.expansion_port; - if(region.value == Region::Autodetect) { - region = (cartridge.region() == Cartridge::Region::NTSC ? Region::NTSC : Region::PAL); - } - - cpu_frequency = region() == Region::NTSC ? config.cpu.ntsc_frequency : config.cpu.pal_frequency; - apu_frequency = region() == Region::NTSC ? config.smp.ntsc_frequency : config.smp.pal_frequency; - - cpu.power(); - smp.power(); - dsp.power(); - ppu.power(); - - if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.power(); - if(cartridge.mode() == Cartridge::Mode::Bsx) bsxcartridge.power(); - #if defined(GAMEBOY) - if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) icd2.power(); - #endif - - if(cartridge.has_bsx_slot()) bsxflash.power(); - if(cartridge.has_nss_dip()) nss.power(); - if(cartridge.has_superfx()) superfx.power(); - if(cartridge.has_sa1()) sa1.power(); - if(cartridge.has_necdsp()) necdsp.power(); - if(cartridge.has_hitachidsp()) hitachidsp.power(); - if(cartridge.has_armdsp()) armdsp.power(); - if(cartridge.has_srtc()) srtc.power(); - if(cartridge.has_sdd1()) sdd1.power(); - if(cartridge.has_spc7110()) spc7110.power(); - if(cartridge.has_obc1()) obc1.power(); - if(cartridge.has_msu1()) msu1.power(); - if(cartridge.has_link()) link.power(); - - reset(); -} - -void System::reset() { - cpu.reset(); - smp.reset(); - dsp.reset(); - ppu.reset(); - - if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.reset(); - - if(cartridge.mode() == Cartridge::Mode::Bsx) bsxcartridge.reset(); - #if defined(GAMEBOY) - if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) icd2.reset(); - #endif - - if(cartridge.has_bsx_slot()) bsxflash.reset(); - if(cartridge.has_nss_dip()) nss.reset(); - if(cartridge.has_superfx()) superfx.reset(); - if(cartridge.has_sa1()) sa1.reset(); - if(cartridge.has_necdsp()) necdsp.reset(); - if(cartridge.has_hitachidsp()) hitachidsp.reset(); - if(cartridge.has_armdsp()) armdsp.reset(); - if(cartridge.has_srtc()) srtc.reset(); - if(cartridge.has_sdd1()) sdd1.reset(); - if(cartridge.has_spc7110()) spc7110.reset(); - if(cartridge.has_obc1()) obc1.reset(); - if(cartridge.has_msu1()) msu1.reset(); - if(cartridge.has_link()) link.reset(); - - #if defined(GAMEBOY) - if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) cpu.coprocessors.append(&icd2); - #endif - if(cartridge.has_superfx()) cpu.coprocessors.append(&superfx); - if(cartridge.has_sa1()) cpu.coprocessors.append(&sa1); - if(cartridge.has_necdsp()) cpu.coprocessors.append(&necdsp); - if(cartridge.has_hitachidsp()) cpu.coprocessors.append(&hitachidsp); - if(cartridge.has_armdsp()) cpu.coprocessors.append(&armdsp); - if(cartridge.has_msu1()) cpu.coprocessors.append(&msu1); - if(cartridge.has_link()) cpu.coprocessors.append(&link); - - scheduler.init(); - input.connect(0, config.controller_port1); - input.connect(1, config.controller_port2); -} - -void System::scanline() { - video.scanline(); - /* - * the idea is to have the frame boundary (for framestep tasing) come as soon as possible - * after the end of a visible frame, so it comes before the input poll. - * the old number was constant 241, which is at a very odd time for NTSC. - * the new numbers are the minimum possible to still capture a full frame; any lower, - * and the last scanline(s) of the frame are still from the old frame. - */ - int stopline; - if (ppu.overscan()) // (region != Region::NTSC) - stopline = 240; - else - stopline = 225; - if(cpu.vcounter() == stopline) scheduler.exit(Scheduler::ExitReason::FrameEvent); -} - -void System::frame() { -} - -System::System() { - region = Region::Autodetect; - expansion = ExpansionPortDevice::BSX; -} - -} - - -//zero 04-sep-2012 -extern "C" void snes_set_layer_enable(int layer, int priority, bool enable) -{ - SNES::ppu.layer_enable(layer, priority, enable); -} diff --git a/waterbox/libsnes/bsnes/snes/system/system.hpp b/waterbox/libsnes/bsnes/snes/system/system.hpp deleted file mode 100644 index 299fb88129..0000000000 --- a/waterbox/libsnes/bsnes/snes/system/system.hpp +++ /dev/null @@ -1,45 +0,0 @@ -struct Interface; - -struct System : property { - enum class Region : unsigned { NTSC = 0, PAL = 1, Autodetect = 2 }; - enum class ExpansionPortDevice : unsigned { None = 0, BSX = 1 }; - - void run(); - void runtosave(); - - void init(); - void term(); - void load(); - void unload(); - void power(); - void reset(); - - void frame(); - void scanline(); - - //return *active* system information (settings are cached upon power-on) - readonly region; - readonly expansion; - readonly cpu_frequency; - readonly apu_frequency; - - System(); - -private: - void runthreadtosave(); - - friend class Cartridge; - friend class Video; - friend class Audio; - friend class Input; -}; - -#include "video.hpp" -#include "audio.hpp" -#include "input.hpp" - -#include -#include -#include - -extern System system; diff --git a/waterbox/libsnes/bsnes/snes/system/video.cpp b/waterbox/libsnes/bsnes/snes/system/video.cpp deleted file mode 100644 index 4500be24c6..0000000000 --- a/waterbox/libsnes/bsnes/snes/system/video.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#ifdef SYSTEM_CPP - -Video video; - -//internal - -const uint8_t Video::cursor[15 * 15] = { - 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0, - 0,0,0,0,1,1,2,2,2,1,1,0,0,0,0, - 0,0,0,1,2,2,1,2,1,2,2,1,0,0,0, - 0,0,1,2,1,1,0,1,0,1,1,2,1,0,0, - 0,1,2,1,0,0,0,1,0,0,0,1,2,1,0, - 0,1,2,1,0,0,1,2,1,0,0,1,2,1,0, - 1,2,1,0,0,1,1,2,1,1,0,0,1,2,1, - 1,2,2,1,1,2,2,2,2,2,1,1,2,2,1, - 1,2,1,0,0,1,1,2,1,1,0,0,1,2,1, - 0,1,2,1,0,0,1,2,1,0,0,1,2,1,0, - 0,1,2,1,0,0,0,1,0,0,0,1,2,1,0, - 0,0,1,2,1,1,0,1,0,1,1,2,1,0,0, - 0,0,0,1,2,2,1,2,1,2,2,1,0,0,0, - 0,0,0,0,1,1,2,2,2,1,1,0,0,0,0, - 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0, -}; - -void Video::draw_cursor(uint16_t color, int x, int y) { - uint32_t *data = (uint32_t*)ppu.output; - if(ppu.interlace() && ppu.field()) data += 512; - - for(int cy = 0; cy < 15; cy++) { - int vy = y + cy - 7; - if(vy <= 0 || vy >= 240) continue; //do not draw offscreen - - bool hires = (line_width[vy] == 512); - for(int cx = 0; cx < 15; cx++) { - int vx = x + cx - 7; - if(vx < 0 || vx >= 256) continue; //do not draw offscreen - uint8_t pixel = cursor[cy * 15 + cx]; - if(pixel == 0) continue; - uint32_t pixelcolor = (15 << 15) | ((pixel == 1) ? 0 : color); - - if(hires == false) { - *((uint32_t*)data + vy * 1024 + vx) = pixelcolor; - } else { - *((uint32_t*)data + vy * 1024 + vx * 2 + 0) = pixelcolor; - *((uint32_t*)data + vy * 1024 + vx * 2 + 1) = pixelcolor; - } - } - } -} - -void Video::update() { - switch(config.controller_port2) { - case Input::Device::SuperScope: - if(dynamic_cast(input.port2)) { - SuperScope &device = (SuperScope&)*input.port2; - draw_cursor(0x7c00, device.x, device.y); - } - break; - case Input::Device::Justifier: - case Input::Device::Justifiers: - if(dynamic_cast(input.port2)) { - Justifier &device = (Justifier&)*input.port2; - draw_cursor(0x001f, device.player1.x, device.player1.y); - if(device.chained == false) break; - draw_cursor(0x02e0, device.player2.x, device.player2.y); - } - break; - } - - uint32_t *data = (uint32_t*)ppu.output; - if(ppu.interlace() && ppu.field()) data += 512; - - if(hires) { - //normalize line widths - for(unsigned y = 0; y < 240; y++) { - if(line_width[y] == 512) continue; - uint32_t *buffer = data + y * 1024; - for(signed x = 255; x >= 0; x--) { - buffer[(x * 2) + 0] = buffer[(x * 2) + 1] = buffer[x]; - } - } - } - - interface()->videoRefresh(ppu.surface, hires, ppu.interlace(), ppu.overscan()); - - hires = false; -} - -void Video::scanline() { - unsigned y = cpu.vcounter(); - if(y >= 240) return; - - hires |= ppu.hires(); - unsigned width = (ppu.hires() == false ? 256 : 512); - line_width[y] = width; -} - -void Video::init() { - hires = false; - for(auto &n : line_width) n = 256; -} - -#endif diff --git a/waterbox/libsnes/bsnes/snes/system/video.hpp b/waterbox/libsnes/bsnes/snes/system/video.hpp deleted file mode 100644 index f0c096832d..0000000000 --- a/waterbox/libsnes/bsnes/snes/system/video.hpp +++ /dev/null @@ -1,19 +0,0 @@ -struct Video { - enum class Format : unsigned { RGB30, RGB24, RGB16, RGB15 }; -public: - void update(); - -private: - bool hires; - unsigned line_width[240]; - - void scanline(); - void init(); - - static const uint8_t cursor[15 * 15]; - void draw_cursor(uint16_t color, int x, int y); - - friend class System; -}; - -extern Video video; diff --git a/waterbox/libsnes/bsnes/target-libsnes/libsnes.cpp b/waterbox/libsnes/bsnes/target-libsnes/libsnes.cpp deleted file mode 100644 index d05646122c..0000000000 --- a/waterbox/libsnes/bsnes/target-libsnes/libsnes.cpp +++ /dev/null @@ -1,701 +0,0 @@ -#include "libsnes.hpp" -#include - -#include -#include - -#include - -using namespace nall; - -struct Interface : public SNES::Interface { - typedef SNES::Interface BaseType; - - snes_video_refresh_t pvideo_refresh; - snes_audio_sample_t paudio_sample; - snes_input_poll_t pinput_poll; - snes_input_state_t pinput_state; - snes_input_notify_t pinput_notify; - snes_path_request_t ppath_request; - snes_allocSharedMemory_t pallocSharedMemory; - snes_freeSharedMemory_t pfreeSharedMemory; - snes_trace_t ptrace; - string basename; - uint32_t *buffer; - uint32_t *palette; - - SnesCartridge cart; - - //zero 11-sep-2012 - time_t randomSeed() { return 0; } - - //zero 26-sep-2012 - std::queue messages; - - //zero 17-oct-2012 - int backdropColor; - int getBackdropColor() - { - return backdropColor; - } - - void videoRefresh(const uint32_t *data, bool hires, bool interlace, bool overscan) { - unsigned width = hires ? 512 : 256; - unsigned height = overscan ? 239 : 224; - unsigned pitch = 1024 >> interlace; - if(interlace) height <<= 1; - data += 9 * 1024; //skip front porch - - for(unsigned y = 0; y < height; y++) { - const uint32_t *sp = data + y * pitch; - uint32_t *dp = buffer + y * pitch; - for(unsigned x = 0; x < width; x++) { - *dp++ = palette[*sp++]; - } - } - - if(pvideo_refresh) pvideo_refresh(buffer, width, height); - if(pinput_poll) pinput_poll(); - } - - void audioSample(int16_t left, int16_t right) { - if(paudio_sample) return paudio_sample(left, right); - } - - //zero 27-sep-2012 - snes_scanlineStart_t pScanlineStart; - void scanlineStart(int line) - { - if(pScanlineStart) pScanlineStart((int)line); - } - - int16_t inputPoll(bool port, SNES::Input::Device device, unsigned index, unsigned id) { - if(pinput_state) return pinput_state(port?1:0, (unsigned)device, index, id); - return 0; - } - - void inputNotify(int index) { - if (pinput_notify) pinput_notify(index); - } - - void message(const string &text) { - messages.push(text); - } - - void cpuTrace(uint32_t which, const char *msg) { - if (ptrace) - ptrace(which, (const char *)msg); - } - - string path(SNES::Cartridge::Slot slot, const string &hint) - { - if(ppath_request) - { - const char* path = ppath_request((int)slot, (const char*)hint); - return path; - } - return { basename, hint }; - } - - - //zero 23-dec-2012 - void* allocSharedMemory(const char* memtype, size_t amt, int initialByte = -1) - { - void* ret; - //if pallocSharedMemory isnt set up yet, we're going to have serious problems - ret = pallocSharedMemory(memtype,amt); - if(initialByte != -1) - { - for(unsigned i = 0; i < amt; i++) ((uint8*)ret)[i] = (uint8)initialByte; - } - return ret; - } - void freeSharedMemory(void* ptr) - { - if(!pfreeSharedMemory) return; //?? - pfreeSharedMemory(ptr); - } - - Interface() : - pvideo_refresh(0), - paudio_sample(0), - pinput_poll(0), - pinput_state(0), - pinput_notify(0), - ppath_request(0), - pScanlineStart(0), - pallocSharedMemory(0), - pfreeSharedMemory(0), - backdropColor(-1), - ptrace(0), - cart(nullptr, 0) - { - buffer = (uint32_t*)alloc_invisible(512 * 480 * sizeof(uint32_t)); - palette = (uint32_t*)alloc_invisible(16 * 32768 * sizeof(uint32_t)); - memset(&cdlInfo,0,sizeof(cdlInfo)); - } - - ~Interface() { - abort(); - } -}; - -void pwrap_init(); -Interface *iface = nullptr; -namespace SNES { -SNES::Interface *interface() -{ - if(iface != nullptr) return iface; - iface = new ::Interface(); - pwrap_init(); - return iface; -} -} - -const char* snes_library_id(void) { - static string version = {"bsnes v", Version}; - return version; -} - -unsigned snes_library_revision_major(void) { - return 1; -} - -unsigned snes_library_revision_minor(void) { - return 3; -} - -void snes_set_allocSharedMemory(snes_allocSharedMemory_t cb) -{ - iface->pallocSharedMemory = cb; -} -void snes_set_freeSharedMemory(snes_freeSharedMemory_t cb) -{ - iface->pfreeSharedMemory = cb; -} - -void snes_set_video_refresh(snes_video_refresh_t video_refresh) { - iface->pvideo_refresh = video_refresh; -} - -void snes_set_color_lut(uint32_t * colors) { - for (int i = 0; i < 16 * 32768; i++) - iface->palette[i] = colors[i]; -} - -void snes_set_audio_sample(snes_audio_sample_t audio_sample) { - iface->paudio_sample = audio_sample; -} - -void snes_set_input_poll(snes_input_poll_t input_poll) { - iface->pinput_poll = input_poll; -} - -void snes_set_input_state(snes_input_state_t input_state) { - iface->pinput_state = input_state; -} - -void snes_set_input_notify(snes_input_notify_t input_notify) { - iface->pinput_notify = input_notify; -} - -void snes_set_path_request(snes_path_request_t path_request) -{ - iface->ppath_request = path_request; -} - -void snes_set_controller_port_device(bool port, unsigned device) { - SNES::input.connect(port, (SNES::Input::Device)device); -} - -void snes_set_cartridge_basename(const char *basename) { - iface->basename = basename; -} - -template inline void reconstruct(T* t) { - /*t->~T(); - memset(t,0,sizeof(*t)); - new(t) T();*/ -} - -void snes_init(void) { - - //force everything to get initialized, even though it probably already is - SNES::interface(); - - //zero 01-sep-2014 - this is too slow. made rewind totally boring. made other edits to firmware chips to preserve their roms instead - //zero 22-may-2014 - why not this too, for the sake of completeness? - //reconstruct(&SNES::cartridge); - - //zero 01-dec-2012 - due to systematic variable initialization fails in bsnes components, these reconstructions are necessary, - //and the previous comment here which called this paranoid has been removed. - reconstruct(&SNES::icd2); - reconstruct(&SNES::nss); - reconstruct(&SNES::superfx); - reconstruct(&SNES::sa1); - reconstruct(&SNES::necdsp); - reconstruct(&SNES::hitachidsp); - reconstruct(&SNES::armdsp); - reconstruct(&SNES::bsxsatellaview); - reconstruct(&SNES::bsxcartridge); - reconstruct(&SNES::bsxflash); - reconstruct(&SNES::srtc); SNES::srtc.initialize(); - reconstruct(&SNES::sdd1); - reconstruct(&SNES::spc7110); SNES::spc7110.initialize(); - reconstruct(&SNES::obc1); - reconstruct(&SNES::msu1); - reconstruct(&SNES::link); - reconstruct(&SNES::video); - reconstruct(&SNES::audio); - - //zero 01-dec-2012 - forgot to do all these. massive desync chaos! - //remove these to make it easier to find initialization fails in the component power-ons / constructors / etc. - //or just forget about it. this snes_init gets called paranoidly frequently by bizhawk, so things should stay zeroed correctly - reconstruct(&SNES::cpu); SNES::cpu.initialize(); - reconstruct(&SNES::smp); SNES::smp.initialize(); - reconstruct(&SNES::dsp); - reconstruct(&SNES::ppu); - SNES::ppu.initialize(); - SNES::system.init(); - - //zero 26-aug-2013 - yup. still more - reconstruct(&GameBoy::cpu); GameBoy::cpu.initialize(); -} - -void snes_term(void) { - SNES::system.term(); -} - -void snes_power(void) { - SNES::system.power(); -} - -void snes_reset(void) { - SNES::system.reset(); -} - -void snes_run(void) { - SNES::system.run(); -} - -//zero 21-sep-2012 -void snes_set_scanlineStart(snes_scanlineStart_t cb) -{ - iface->pScanlineStart = cb; -} - -//zero 03-sep-2012 -bool snes_check_cartridge(const uint8_t *rom_data, unsigned rom_size) -{ - //tries to determine whether this rom is a snes rom - BUT THIS TRIES TO ACCEPT EVERYTHING! so we cant really use it - SnesCartridge temp(rom_data, rom_size); - return temp.type != SnesCartridge::TypeUnknown && temp.type != SnesCartridge::TypeGameBoy; -} - -//zero 05-sep-2012 -int snes_peek_logical_register(int reg) -{ - switch(reg) - { - //$2105 - //zero 17-may-2014 TODO - enable these for other profiles -#if !defined(PROFILE_PERFORMANCE) && !defined(PROFILE_ACCURACY) - case SNES_REG_BG_MODE: return SNES::ppu.regs.bg_mode; - case SNES_REG_BG3_PRIORITY: return SNES::ppu.regs.bg3_priority; - case SNES_REG_BG1_TILESIZE: return SNES::ppu.regs.bg_tilesize[SNES::PPU::BG1]; - case SNES_REG_BG2_TILESIZE: return SNES::ppu.regs.bg_tilesize[SNES::PPU::BG2]; - case SNES_REG_BG3_TILESIZE: return SNES::ppu.regs.bg_tilesize[SNES::PPU::BG3]; - case SNES_REG_BG4_TILESIZE: return SNES::ppu.regs.bg_tilesize[SNES::PPU::BG4]; - - //$2107 - case SNES_REG_BG1_SCADDR: return SNES::ppu.regs.bg_scaddr[SNES::PPU::BG1]>>9; - case SNES_REG_BG1_SCSIZE: return SNES::ppu.regs.bg_scsize[SNES::PPU::BG1]; - //$2108 - case SNES_REG_BG2_SCADDR: return SNES::ppu.regs.bg_scaddr[SNES::PPU::BG2]>>9; - case SNES_REG_BG2_SCSIZE: return SNES::ppu.regs.bg_scsize[SNES::PPU::BG2]; - //$2109 - case SNES_REG_BG3_SCADDR: return SNES::ppu.regs.bg_scaddr[SNES::PPU::BG3]>>9; - case SNES_REG_BG3_SCSIZE: return SNES::ppu.regs.bg_scsize[SNES::PPU::BG3]; - //$210A - case SNES_REG_BG4_SCADDR: return SNES::ppu.regs.bg_scaddr[SNES::PPU::BG4]>>9; - case SNES_REG_BG4_SCSIZE: return SNES::ppu.regs.bg_scsize[SNES::PPU::BG4]; - //$210B - case SNES_REG_BG1_TDADDR: return SNES::ppu.regs.bg_tdaddr[SNES::PPU::BG1]>>13; - case SNES_REG_BG2_TDADDR: return SNES::ppu.regs.bg_tdaddr[SNES::PPU::BG2]>>13; - //$210C - case SNES_REG_BG3_TDADDR: return SNES::ppu.regs.bg_tdaddr[SNES::PPU::BG3]>>13; - case SNES_REG_BG4_TDADDR: return SNES::ppu.regs.bg_tdaddr[SNES::PPU::BG4]>>13; - //$2133 SETINI - case SNES_REG_SETINI_MODE7_EXTBG: return SNES::ppu.regs.mode7_extbg?1:0; - case SNES_REG_SETINI_HIRES: return SNES::ppu.regs.pseudo_hires?1:0; - case SNES_REG_SETINI_OVERSCAN: return SNES::ppu.regs.overscan?1:0; - case SNES_REG_SETINI_OBJ_INTERLACE: return SNES::ppu.regs.oam_interlace?1:0; - case SNES_REG_SETINI_SCREEN_INTERLACE: return SNES::ppu.regs.interlace?1:0; - //$2130 CGWSEL - case SNES_REG_CGWSEL_COLORMASK: return SNES::ppu.regs.color_mask; - case SNES_REG_CGWSEL_COLORSUBMASK: return SNES::ppu.regs.colorsub_mask; - case SNES_REG_CGWSEL_ADDSUBMODE: return SNES::ppu.regs.addsub_mode?1:0; - case SNES_REG_CGWSEL_DIRECTCOLOR: return SNES::ppu.regs.direct_color?1:0; - //$2101 OBSEL - case SNES_REG_OBSEL_NAMEBASE: return SNES::ppu.regs.oam_tdaddr>>14; - case SNES_REG_OBSEL_NAMESEL: return SNES::ppu.regs.oam_nameselect; - case SNES_REG_OBSEL_SIZE: return SNES::ppu.regs.oam_basesize; - //$2131 CGADSUB - //enum { BG1 = 0, BG2 = 1, BG3 = 2, BG4 = 3, OAM = 4, BACK = 5, COL = 5 }; - case SNES_REG_CGADSUB_MODE: return SNES::ppu.regs.color_mode; - case SNES_REG_CGADSUB_HALF: return SNES::ppu.regs.color_halve; - case SNES_REG_CGADSUB_BG4: return SNES::ppu.regs.color_enabled[3]; - case SNES_REG_CGADSUB_BG3: return SNES::ppu.regs.color_enabled[2]; - case SNES_REG_CGADSUB_BG2: return SNES::ppu.regs.color_enabled[1]; - case SNES_REG_CGADSUB_BG1: return SNES::ppu.regs.color_enabled[0]; - case SNES_REG_CGADSUB_OBJ: return SNES::ppu.regs.color_enabled[4]; - case SNES_REG_CGADSUB_BACKDROP: return SNES::ppu.regs.color_enabled[5]; - //$212C TM - case SNES_REG_TM_BG1: return SNES::ppu.regs.bg_enabled[0]; - case SNES_REG_TM_BG2: return SNES::ppu.regs.bg_enabled[1]; - case SNES_REG_TM_BG3: return SNES::ppu.regs.bg_enabled[2]; - case SNES_REG_TM_BG4: return SNES::ppu.regs.bg_enabled[3]; - case SNES_REG_TM_OBJ: return SNES::ppu.regs.bg_enabled[4]; - //$212D TM - case SNES_REG_TS_BG1: return SNES::ppu.regs.bgsub_enabled[0]; - case SNES_REG_TS_BG2: return SNES::ppu.regs.bgsub_enabled[1]; - case SNES_REG_TS_BG3: return SNES::ppu.regs.bgsub_enabled[2]; - case SNES_REG_TS_BG4: return SNES::ppu.regs.bgsub_enabled[3]; - case SNES_REG_TS_OBJ: return SNES::ppu.regs.bgsub_enabled[4]; - //Mode7 regs - case SNES_REG_M7SEL_REPEAT: return SNES::ppu.regs.mode7_repeat; - case SNES_REG_M7SEL_HFLIP: return SNES::ppu.regs.mode7_vflip; - case SNES_REG_M7SEL_VFLIP: return SNES::ppu.regs.mode7_hflip; - case SNES_REG_M7A: return SNES::ppu.regs.m7a; - case SNES_REG_M7B: return SNES::ppu.regs.m7b; - case SNES_REG_M7C: return SNES::ppu.regs.m7c; - case SNES_REG_M7D: return SNES::ppu.regs.m7d; - case SNES_REG_M7X: return SNES::ppu.regs.m7x; - case SNES_REG_M7Y: return SNES::ppu.regs.m7y; - //BG scroll regs - case SNES_REG_BG1HOFS: return SNES::ppu.regs.bg_hofs[0] & 0x3FF; - case SNES_REG_BG1VOFS: return SNES::ppu.regs.bg_vofs[0] & 0x3FF; - case SNES_REG_BG2HOFS: return SNES::ppu.regs.bg_hofs[1] & 0x3FF; - case SNES_REG_BG2VOFS: return SNES::ppu.regs.bg_vofs[1] & 0x3FF; - case SNES_REG_BG3HOFS: return SNES::ppu.regs.bg_hofs[2] & 0x3FF; - case SNES_REG_BG3VOFS: return SNES::ppu.regs.bg_vofs[2] & 0x3FF; - case SNES_REG_BG4HOFS: return SNES::ppu.regs.bg_hofs[3] & 0x3FF; - case SNES_REG_BG4VOFS: return SNES::ppu.regs.bg_vofs[3] & 0x3FF; - case SNES_REG_M7HOFS: return SNES::ppu.regs.m7_hofs & 0x1FFF; //rememebr to make these signed with <<19>>19 - case SNES_REG_M7VOFS: return SNES::ppu.regs.m7_vofs & 0x1FFF; //rememebr to make these signed with <<19>>19 -#endif - - } - return 0; -} - -bool snes_load_cartridge_normal( - const char *rom_xml, const uint8_t *rom_data, unsigned rom_size -) { - if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size); - iface->cart = SnesCartridge(rom_data, rom_size); - string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup; - SNES::cartridge.load(SNES::Cartridge::Mode::Normal, { xmlrom }); - SNES::system.power(); - return true; -} - -bool snes_load_cartridge_bsx_slotted( - const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, - const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size -) { - if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size); - iface->cart = SnesCartridge(rom_data, rom_size); - string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup; - if(bsx_data) SNES::bsxflash.memory.copy(bsx_data, bsx_size); - string xmlbsx = (bsx_xml && *bsx_xml) ? string(bsx_xml) : SnesCartridge(bsx_data, bsx_size).markup; - SNES::cartridge.load(SNES::Cartridge::Mode::BsxSlotted, xmlrom); - SNES::system.power(); - return true; -} - -bool snes_load_cartridge_bsx( - const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, - const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size -) { - if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size); - iface->cart = SnesCartridge(rom_data, rom_size); - string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup; - if(bsx_data) SNES::bsxflash.memory.copy(bsx_data, bsx_size); - string xmlbsx = (bsx_xml && *bsx_xml) ? string(bsx_xml) : SnesCartridge(bsx_data, bsx_size).markup; - SNES::cartridge.load(SNES::Cartridge::Mode::Bsx, xmlrom); - SNES::system.power(); - return true; -} - -bool snes_load_cartridge_sufami_turbo( - const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, - const char *sta_xml, const uint8_t *sta_data, unsigned sta_size, - const char *stb_xml, const uint8_t *stb_data, unsigned stb_size -) { - if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size); - iface->cart = SnesCartridge(rom_data, rom_size); - string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup; - if(sta_data) SNES::sufamiturbo.slotA.rom.copy(sta_data, sta_size); - string xmlsta = (sta_xml && *sta_xml) ? string(sta_xml) : SnesCartridge(sta_data, sta_size).markup; - if(stb_data) SNES::sufamiturbo.slotB.rom.copy(stb_data, stb_size); - string xmlstb = (stb_xml && *stb_xml) ? string(stb_xml) : SnesCartridge(stb_data, stb_size).markup; - SNES::cartridge.load(SNES::Cartridge::Mode::SufamiTurbo, xmlrom); - SNES::system.power(); - return true; -} - -bool snes_load_cartridge_super_game_boy( - const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, - const char *dmg_xml, const uint8_t *dmg_data, unsigned dmg_size -) { - if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size); - iface->cart = SnesCartridge(rom_data, rom_size); - string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup; - if(dmg_data) { - //GameBoyCartridge needs to modify dmg_data (for MMM01 emulation); so copy data - uint8_t *data = new uint8_t[dmg_size]; - memcpy(data, dmg_data, dmg_size); - string xmldmg = (dmg_xml && *dmg_xml) ? string(dmg_xml) : GameBoyCartridge(data, dmg_size).markup; - GameBoy::cartridge.load(GameBoy::System::Revision::SuperGameBoy, xmldmg, data, dmg_size); - delete[] data; - } - SNES::cartridge.load(SNES::Cartridge::Mode::SuperGameBoy, xmlrom); - SNES::system.power(); - return true; -} - -void snes_unload_cartridge(void) { - SNES::cartridge.unload(); -} - -bool snes_get_region(void) { - return SNES::system.region() == SNES::System::Region::NTSC ? 0 : 1; -} - -char snes_get_mapper(void) { - return iface->cart.mapper; -} - -uint8_t* snes_get_memory_data(unsigned id) { - if(SNES::cartridge.loaded() == false) return 0; - - switch(id) { - case SNES_MEMORY_CARTRIDGE_RAM: - return SNES::cartridge.ram.data(); - case SNES_MEMORY_CARTRIDGE_RTC: - if(SNES::cartridge.has_srtc()) return SNES::srtc.rtc; - if(SNES::cartridge.has_spc7110rtc()) return SNES::spc7110.rtc; - return 0; - case SNES_MEMORY_BSX_RAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break; - return SNES::bsxcartridge.sram.data(); - case SNES_MEMORY_BSX_PRAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break; - return SNES::bsxcartridge.psram.data(); - case SNES_MEMORY_SUFAMI_TURBO_A_RAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break; - return SNES::sufamiturbo.slotA.ram.data(); - case SNES_MEMORY_SUFAMI_TURBO_B_RAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break; - return SNES::sufamiturbo.slotB.ram.data(); - case SNES_MEMORY_GAME_BOY_CARTRAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break; - return GameBoy::cartridge.ramdata; - //case SNES_MEMORY_GAME_BOY_RTC: - // if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break; - // return GameBoy::cartridge.rtcdata; - case SNES_MEMORY_GAME_BOY_WRAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break; - return GameBoy::cpu.wram; - case SNES_MEMORY_GAME_BOY_HRAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break; - return GameBoy::cpu.hram; - case SNES_MEMORY_SA1_IRAM: - if(!SNES::cartridge.has_sa1()) break; - return SNES::sa1.iram.data(); - - case SNES_MEMORY_WRAM: - return SNES::cpu.wram; - case SNES_MEMORY_APURAM: - return SNES::smp.apuram; - case SNES_MEMORY_VRAM: - return SNES::ppu.vram; - case SNES_MEMORY_OAM: - return SNES::ppu.oam; - case SNES_MEMORY_CGRAM: - return SNES::ppu.cgram; - - case SNES_MEMORY_CARTRIDGE_ROM: - return SNES::cartridge.rom.data(); - } - - return 0; -} - -const char* snes_get_memory_id_name(unsigned id) { - if(SNES::cartridge.loaded() == false) return nullptr; - - switch(id) { - case SNES_MEMORY_CARTRIDGE_RAM: - return "CARTRIDGE_RAM"; - case SNES_MEMORY_CARTRIDGE_RTC: - if(SNES::cartridge.has_srtc()) return "RTC"; - if(SNES::cartridge.has_spc7110rtc()) return "SPC7110_RTC"; - return nullptr; - case SNES_MEMORY_BSX_RAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break; - return "BSX_SRAM"; - case SNES_MEMORY_BSX_PRAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break; - return "BSX_PSRAM"; - case SNES_MEMORY_SUFAMI_TURBO_A_RAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break; - return "SUFAMI_SLOTARAM"; - case SNES_MEMORY_SUFAMI_TURBO_B_RAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break; - return "SUFAMI_SLOTBRAM"; - case SNES_MEMORY_GAME_BOY_CARTRAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break; - //return GameBoy::cartridge.ramdata; - return "SGB_CARTRAM"; - //case SNES_MEMORY_GAME_BOY_RTC: - // if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break; - // return GameBoy::cartridge.rtcdata; - case SNES_MEMORY_GAME_BOY_WRAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break; - //see notes in SetupMemoryDomains in bizhawk - return "SGB_WRAM"; - case SNES_MEMORY_GAME_BOY_HRAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break; - return "SGB_HRAM"; - case SNES_MEMORY_SA1_IRAM: - if(!SNES::cartridge.has_sa1()) break; - return "SA1_IRAM"; - - case SNES_MEMORY_WRAM: - //return SNES::cpu.wram; - return "WRAM"; - case SNES_MEMORY_APURAM: - //return SNES::smp.apuram; - return "APURAM"; - case SNES_MEMORY_VRAM: - return "VRAM"; - case SNES_MEMORY_OAM: - return "OAM"; - case SNES_MEMORY_CGRAM: - return "CGRAM"; - - case SNES_MEMORY_CARTRIDGE_ROM: - return "CARTRIDGE_ROM"; - } - - return nullptr; -} - -unsigned snes_get_memory_size(unsigned id) { - if(SNES::cartridge.loaded() == false) return 0; - unsigned size = 0; - - switch(id) { - case SNES_MEMORY_CARTRIDGE_RAM: - size = SNES::cartridge.ram.size(); - break; - case SNES_MEMORY_CARTRIDGE_RTC: - if(SNES::cartridge.has_srtc() || SNES::cartridge.has_spc7110rtc()) size = 20; - break; - case SNES_MEMORY_BSX_RAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break; - size = SNES::bsxcartridge.sram.size(); - break; - case SNES_MEMORY_BSX_PRAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break; - size = SNES::bsxcartridge.psram.size(); - break; - case SNES_MEMORY_SUFAMI_TURBO_A_RAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break; - size = SNES::sufamiturbo.slotA.ram.size(); - break; - case SNES_MEMORY_SUFAMI_TURBO_B_RAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break; - size = SNES::sufamiturbo.slotB.ram.size(); - break; - case SNES_MEMORY_GAME_BOY_CARTRAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break; - size = GameBoy::cartridge.ramsize; - break; - //case SNES_MEMORY_GAME_BOY_RTC: - // if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break; - // size = GameBoy::cartridge.rtcsize; - // break; - case SNES_MEMORY_GAME_BOY_WRAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break; - //see notes in SetupMemoryDomains in bizhawk - size = 32768; - break; - case SNES_MEMORY_GAME_BOY_HRAM: - if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break; - size = 128; - break; - case SNES_MEMORY_SA1_IRAM: - if(!SNES::cartridge.has_sa1()) break; - size = SNES::sa1.iram.size(); - break; - - case SNES_MEMORY_WRAM: - size = 128 * 1024; - break; - case SNES_MEMORY_APURAM: - size = 64 * 1024; - break; - case SNES_MEMORY_VRAM: - size = 64 * 1024; - break; - case SNES_MEMORY_OAM: - size = 544; - break; - case SNES_MEMORY_CGRAM: - size = 512; - break; - - case SNES_MEMORY_CARTRIDGE_ROM: - size = SNES::cartridge.rom.size(); - break; - } - - if(size == -1U) size = 0; - return size; -} - -uint8_t bus_read(unsigned addr) { - return SNES::bus.read(addr); -} -void bus_write(unsigned addr, uint8_t val) { - SNES::bus.write(addr, val); -} - -int snes_poll_message() -{ - if(iface->messages.empty()) return -1; - return iface->messages.front().length(); -} -void snes_dequeue_message(char* buffer) -{ - int len = iface->messages.front().length(); - memcpy(buffer,(const char*)iface->messages.front(),len); - iface->messages.pop(); -} - -void snes_set_backdropColor(int color) -{ - iface->backdropColor = color; -} - -void snes_set_trace_callback(uint32_t mask, snes_trace_t callback) -{ - iface->wanttrace = mask; - if (mask) - iface->ptrace = callback; - else - iface->ptrace = nullptr; -} \ No newline at end of file diff --git a/waterbox/libsnes/bsnes/target-libsnes/libsnes.hpp b/waterbox/libsnes/bsnes/target-libsnes/libsnes.hpp deleted file mode 100644 index d01df3526e..0000000000 --- a/waterbox/libsnes/bsnes/target-libsnes/libsnes.hpp +++ /dev/null @@ -1,263 +0,0 @@ -#ifndef LIBSNES_HPP -#define LIBSNES_HPP - -#include -#include - -#if defined(LIBSNES_IMPORT) -#define LIBSNES_IMPORTDECL __declspec(dllimport) -#elif defined(LIBSNES_EXPORT) -#define LIBSNES_IMPORTDECL __declspec(dllexport) -#else -#define LIBSNES_IMPORTDECL -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#define SNES_PORT_1 0 -#define SNES_PORT_2 1 - -#define SNES_DEVICE_NONE 0 -#define SNES_DEVICE_JOYPAD 1 -#define SNES_DEVICE_MULTITAP 2 -#define SNES_DEVICE_MOUSE 3 -#define SNES_DEVICE_SUPER_SCOPE 4 -#define SNES_DEVICE_JUSTIFIER 5 -#define SNES_DEVICE_JUSTIFIERS 6 -#define SNES_DEVICE_SERIAL_CABLE 7 - -#define SNES_DEVICE_ID_JOYPAD_B 0 -#define SNES_DEVICE_ID_JOYPAD_Y 1 -#define SNES_DEVICE_ID_JOYPAD_SELECT 2 -#define SNES_DEVICE_ID_JOYPAD_START 3 -#define SNES_DEVICE_ID_JOYPAD_UP 4 -#define SNES_DEVICE_ID_JOYPAD_DOWN 5 -#define SNES_DEVICE_ID_JOYPAD_LEFT 6 -#define SNES_DEVICE_ID_JOYPAD_RIGHT 7 -#define SNES_DEVICE_ID_JOYPAD_A 8 -#define SNES_DEVICE_ID_JOYPAD_X 9 -#define SNES_DEVICE_ID_JOYPAD_L 10 -#define SNES_DEVICE_ID_JOYPAD_R 11 - -#define SNES_DEVICE_ID_MOUSE_X 0 -#define SNES_DEVICE_ID_MOUSE_Y 1 -#define SNES_DEVICE_ID_MOUSE_LEFT 2 -#define SNES_DEVICE_ID_MOUSE_RIGHT 3 - -#define SNES_DEVICE_ID_SUPER_SCOPE_X 0 -#define SNES_DEVICE_ID_SUPER_SCOPE_Y 1 -#define SNES_DEVICE_ID_SUPER_SCOPE_TRIGGER 2 -#define SNES_DEVICE_ID_SUPER_SCOPE_CURSOR 3 -#define SNES_DEVICE_ID_SUPER_SCOPE_TURBO 4 -#define SNES_DEVICE_ID_SUPER_SCOPE_PAUSE 5 - -#define SNES_DEVICE_ID_JUSTIFIER_X 0 -#define SNES_DEVICE_ID_JUSTIFIER_Y 1 -#define SNES_DEVICE_ID_JUSTIFIER_TRIGGER 2 -#define SNES_DEVICE_ID_JUSTIFIER_START 3 - -#define SNES_REGION_NTSC 0 -#define SNES_REGION_PAL 1 - -#define SNES_MEMORY_CARTRIDGE_RAM 0 -#define SNES_MEMORY_CARTRIDGE_RTC 1 -#define SNES_MEMORY_BSX_RAM 2 -#define SNES_MEMORY_BSX_PRAM 3 -#define SNES_MEMORY_SUFAMI_TURBO_A_RAM 4 -#define SNES_MEMORY_SUFAMI_TURBO_B_RAM 5 -#define SNES_MEMORY_GAME_BOY_CARTRAM 6 -#define SNES_MEMORY_GAME_BOY_RTC 7 -#define SNES_MEMORY_GAME_BOY_WRAM 8 -#define SNES_MEMORY_GAME_BOY_HRAM 9 -#define SNES_MEMORY_SA1_IRAM 10 - -#define SNES_MEMORY_WRAM 100 -#define SNES_MEMORY_APURAM 101 -#define SNES_MEMORY_VRAM 102 -#define SNES_MEMORY_OAM 103 -#define SNES_MEMORY_CGRAM 104 - -#define SNES_MEMORY_CARTRIDGE_ROM 105 - -#define SNES_MEMORY_SYSBUS 200 -#define SNES_MEMORY_LOGICAL_REGS 201 - -typedef void (*snes_video_refresh_t)(const uint32_t *data, unsigned width, unsigned height); -typedef void (*snes_audio_sample_t)(uint16_t left, uint16_t right); -typedef void (*snes_input_poll_t)(void); -typedef int16_t (*snes_input_state_t)(unsigned port, unsigned device, unsigned index, unsigned id); -typedef void (*snes_input_notify_t)(int index); -typedef void (*snes_trace_t)(uint32_t which, const char *msg); -typedef void* (*snes_allocSharedMemory_t)(const char* memtype, size_t amt); -typedef void (*snes_freeSharedMemory_t)(void* ptr); - -const char* snes_library_id(void); -unsigned snes_library_revision_major(void); -unsigned snes_library_revision_minor(void); - -void snes_set_video_refresh(snes_video_refresh_t); -void snes_set_audio_sample(snes_audio_sample_t); -void snes_set_input_poll(snes_input_poll_t); -void snes_set_input_state(snes_input_state_t); -void snes_set_input_notify(snes_input_notify_t); - -void snes_set_allocSharedMemory(snes_allocSharedMemory_t); -void snes_set_freeSharedMemory(snes_freeSharedMemory_t); - -void snes_set_controller_port_device(bool port, unsigned device); -void snes_set_cartridge_basename(const char *basename); - -void snes_init(void); -void snes_term(void); -void snes_power(void); -void snes_reset(void); -void snes_run(void); - -bool snes_load_cartridge_normal( - const char *rom_xml, const uint8_t *rom_data, unsigned rom_size -); - -bool snes_load_cartridge_bsx_slotted( - const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, - const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size -); - -bool snes_load_cartridge_bsx( - const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, - const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size -); - -bool snes_load_cartridge_sufami_turbo( - const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, - const char *sta_xml, const uint8_t *sta_data, unsigned sta_size, - const char *stb_xml, const uint8_t *stb_data, unsigned stb_size -); - -bool snes_load_cartridge_super_game_boy( - const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, - const char *dmg_xml, const uint8_t *dmg_data, unsigned dmg_size -); - -void snes_unload_cartridge(void); - -bool snes_get_region(void); -char snes_get_mapper(void); -uint8_t* snes_get_memory_data(unsigned id); -const char* snes_get_memory_id_name(unsigned id); -unsigned snes_get_memory_size(unsigned id); - -//zeromus additions -bool snes_check_cartridge(const uint8_t *rom_data, unsigned rom_size); -void snes_set_layer_enable(int layer, int priority, bool enable); -typedef void (*snes_scanlineStart_t)(int); -void snes_set_scanlineStart(snes_scanlineStart_t); -void snes_set_backdropColor(int color); -//returns -1 if no messages, messagelength if there is one -int snes_poll_message(); -//give us a buffer of messagelength and we'll dequeue a message into it. you better take care of the null pointer -void snes_dequeue_message(char* buffer); -typedef const char* (*snes_path_request_t)(int slot, const char* hint); -void snes_set_path_request(snes_path_request_t path_request); - -void snes_set_color_lut(uint32_t * colors); - -void snes_set_trace_callback(uint32_t mask, void (*callback)(uint32_t mask, const char *)); - -// system bus implementation -uint8_t bus_read(unsigned addr); -void bus_write(unsigned addr, uint8_t val); - - -//$2105 -#define SNES_REG_BG_MODE 0 -#define SNES_REG_BG3_PRIORITY 1 -#define SNES_REG_BG1_TILESIZE 2 -#define SNES_REG_BG2_TILESIZE 3 -#define SNES_REG_BG3_TILESIZE 4 -#define SNES_REG_BG4_TILESIZE 5 -//$2107 -#define SNES_REG_BG1_SCADDR 10 -#define SNES_REG_BG1_SCSIZE 11 -//$2108 -#define SNES_REG_BG2_SCADDR 12 -#define SNES_REG_BG2_SCSIZE 13 -//$2109 -#define SNES_REG_BG3_SCADDR 14 -#define SNES_REG_BG3_SCSIZE 15 -//$210A -#define SNES_REG_BG4_SCADDR 16 -#define SNES_REG_BG4_SCSIZE 17 -//$210B -#define SNES_REG_BG1_TDADDR 20 -#define SNES_REG_BG2_TDADDR 21 -//$210C -#define SNES_REG_BG3_TDADDR 22 -#define SNES_REG_BG4_TDADDR 23 -//$2133 SETINI -#define SNES_REG_SETINI_MODE7_EXTBG 30 -#define SNES_REG_SETINI_HIRES 31 -#define SNES_REG_SETINI_OVERSCAN 32 -#define SNES_REG_SETINI_OBJ_INTERLACE 33 -#define SNES_REG_SETINI_SCREEN_INTERLACE 34 -//$2130 CGWSEL -#define SNES_REG_CGWSEL_COLORMASK 40 -#define SNES_REG_CGWSEL_COLORSUBMASK 41 -#define SNES_REG_CGWSEL_ADDSUBMODE 42 -#define SNES_REG_CGWSEL_DIRECTCOLOR 43 -//$2101 OBSEL -#define SNES_REG_OBSEL_NAMEBASE 50 -#define SNES_REG_OBSEL_NAMESEL 51 -#define SNES_REG_OBSEL_SIZE 52 -//$2131 CGADSUB -#define SNES_REG_CGADSUB_MODE 60 -#define SNES_REG_CGADSUB_HALF 61 -#define SNES_REG_CGADSUB_BG4 62 -#define SNES_REG_CGADSUB_BG3 63 -#define SNES_REG_CGADSUB_BG2 64 -#define SNES_REG_CGADSUB_BG1 65 -#define SNES_REG_CGADSUB_OBJ 66 -#define SNES_REG_CGADSUB_BACKDROP 67 -//$212C TM -#define SNES_REG_TM_BG1 70 -#define SNES_REG_TM_BG2 71 -#define SNES_REG_TM_BG3 72 -#define SNES_REG_TM_BG4 73 -#define SNES_REG_TM_OBJ 74 -//$212D TM -#define SNES_REG_TS_BG1 80 -#define SNES_REG_TS_BG2 81 -#define SNES_REG_TS_BG3 82 -#define SNES_REG_TS_BG4 83 -#define SNES_REG_TS_OBJ 84 -//Mode7 regs -#define SNES_REG_M7SEL_REPEAT 90 -#define SNES_REG_M7SEL_HFLIP 91 -#define SNES_REG_M7SEL_VFLIP 92 -#define SNES_REG_M7A 93 -#define SNES_REG_M7B 94 -#define SNES_REG_M7C 95 -#define SNES_REG_M7D 96 -#define SNES_REG_M7X 97 -#define SNES_REG_M7Y 98 -//BG scroll regs -#define SNES_REG_BG1HOFS 100 -#define SNES_REG_BG1VOFS 101 -#define SNES_REG_BG2HOFS 102 -#define SNES_REG_BG2VOFS 103 -#define SNES_REG_BG3HOFS 104 -#define SNES_REG_BG3VOFS 105 -#define SNES_REG_BG4HOFS 106 -#define SNES_REG_BG4VOFS 107 -#define SNES_REG_M7HOFS 108 -#define SNES_REG_M7VOFS 109 - - -int snes_peek_logical_register(int reg); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/waterbox/libsnes/bsnes/target-libsnes/libsnes_pwrap.cpp b/waterbox/libsnes/bsnes/target-libsnes/libsnes_pwrap.cpp deleted file mode 100644 index 163e5f2183..0000000000 --- a/waterbox/libsnes/bsnes/target-libsnes/libsnes_pwrap.cpp +++ /dev/null @@ -1,700 +0,0 @@ -//types of messages: -//cmd: frontend->core: "command to core" a command from the frontend which causes emulation to proceed. when sending a command, the frontend should wait for an eMessage_BRK_Complete before proceeding, although a debugger might proceed after any BRK -//query: frontend->core: "query to core" a query from the frontend which can (and should) be satisfied immediately by the core but which does not result in emulation processes (notably, nothing resembling a CMD and nothing which can trigger a BRK) -//sig: core->frontend: "core signal" a synchronous operation called from the emulation process which the frontend should handle immediately without issuing any calls into the core -//brk: core->frontend: "core break" the emulation process has suspended. the frontend is free to do whatever it wishes. - -#define LIBSNES_IMPORT -#include "snes/snes.hpp" -#include "libsnes.hpp" -#include - -#include - -#include -#include -#include - -#include -#include - -extern SNES::Interface *iface; - -typedef uint8 u8; -typedef uint16 u16; -typedef uint64 u64; -typedef uint32 u32; - -typedef int32 s32; - -typedef void(*Action)(); - -enum eMessage : int32 -{ - eMessage_NotSet, - - eMessage_Resume, - - eMessage_QUERY_FIRST, - eMessage_QUERY_get_memory_size, - eMessage_QUERY_peek, - eMessage_QUERY_poke, - eMessage_QUERY_serialize_size, - eMessage_QUERY_set_color_lut, - eMessage_QUERY_GetMemoryIdName, - eMessage_QUERY_state_hook_exec, - eMessage_QUERY_state_hook_read, - eMessage_QUERY_state_hook_write, - eMessage_QUERY_state_hook_nmi, - eMessage_QUERY_state_hook_irq, - eMessage_QUERY_state_hook_exec_smp, - eMessage_QUERY_state_hook_read_smp, - eMessage_QUERY_state_hook_write_smp, - eMessage_QUERY_enable_trace, - eMessage_QUERY_enable_scanline, - eMessage_QUERY_enable_audio, - eMessage_QUERY_set_layer_enable, - eMessage_QUERY_set_backdropColor, - eMessage_QUERY_peek_logical_register, - eMessage_QUERY_peek_cpu_regs, - eMessage_QUERY_set_cdl, - eMessage_QUERY_LAST, - - eMessage_CMD_FIRST, - eMessage_CMD_init, - eMessage_CMD_power, - eMessage_CMD_reset, - eMessage_CMD_run, - eMessage_CMD_serialize, - eMessage_CMD_unserialize, - eMessage_CMD_load_cartridge_normal, - eMessage_CMD_load_cartridge_sgb, - eMessage_CMD_term, - eMessage_CMD_unload_cartridge, - eMessage_CMD_LAST, - - eMessage_SIG_video_refresh, - eMessage_SIG_input_poll, - eMessage_SIG_input_state, - eMessage_SIG_input_notify, - eMessage_SIG_audio_flush, - eMessage_SIG_path_request, - eMessage_SIG_trace_callback, - eMessage_SIG_allocSharedMemory, - eMessage_SIG_freeSharedMemory, - - eMessage_BRK_Complete, - eMessage_BRK_hook_exec, - eMessage_BRK_hook_read, - eMessage_BRK_hook_write, - eMessage_BRK_hook_nmi, - eMessage_BRK_hook_irq, - eMessage_BRK_hook_exec_smp, - eMessage_BRK_hook_read_smp, - eMessage_BRK_hook_write_smp, - eMessage_BRK_scanlineStart, -}; - -enum eStatus : int32 -{ - eStatus_Idle, - eStatus_CMD, - eStatus_BRK -}; - - -//watch it! the size of this struct is important! -#ifdef _MSC_VER -#pragma pack(push,1) -#endif -struct CPURegsComm { - u32 pc; - u16 a, x, y, s, d, vector; //6x - u8 p, db, nothing, nothing2; - u16 v, h; -} -#ifndef _MSC_VER -__attribute__((__packed__)) -#endif -; -#ifdef _MSC_VER -#pragma pack(pop) -#endif - -struct LayerEnablesComm -{ - u8 BG1_Prio0, BG1_Prio1; - u8 BG2_Prio0, BG2_Prio1; - u8 BG3_Prio0, BG3_Prio1; - u8 BG4_Prio0, BG4_Prio1; - u8 Obj_Prio0, Obj_Prio1, Obj_Prio2, Obj_Prio3; -}; - -//TODO: do any of these need to be volatile? -struct CommStruct -{ - //the cmd being executed - eMessage cmd; - - //the status of the core - eStatus status; - - //the SIG or BRK that the core is halted in - eMessage reason; - - int32 padding1; - - //flexible in/out parameters - //these are all "overloaded" a little so it isn't clear what's used for what in for any particular message.. - //but I think it will beat having to have some kind of extremely verbose custom layouts for every message - char* str; - void* ptr; - uint32 id, addr, value, size; - int32 port, device, index, slot; - int32 width, height; - int32 scanline; - SNES::Input::Device inports[2]; - - int32 padding2; - - //always used in pairs - void* buf[3]; - int32 buf_size[3]; - - int32 padding3; - - int64 cdl_ptr[16]; - int32 cdl_size[16]; - - CPURegsComm cpuregs; - LayerEnablesComm layerEnables; - - //static configuration-type information which can be grabbed off the core at any time without even needing a QUERY command - uint32 region; - uint32 mapper; - uint32 BLANKO; - - //=========================================================== - - //private stuff - void* privbuf[3]; //TODO remember to tidy this.. - - void CopyBuffer(int id, void* ptr, int32 size) - { - if (privbuf[id]) free(privbuf[id]); - buf[id] = privbuf[id] = malloc(size); - memcpy(buf[id], ptr, size); - buf_size[id] = size; - } - - void SetBuffer(int id, void* ptr, int32 size) - { - if (privbuf[id]) free(privbuf[id]); - privbuf[id] = nullptr; - buf[id] = ptr; - buf_size[id] = size; - } - - -} comm; - -//coroutines -cothread_t co_control, co_emu, co_emu_suspended; - -//internal state -bool audio_en = false; -static const int AUDIOBUFFER_SIZE = 44100 * 2; -uint16_t audiobuffer[AUDIOBUFFER_SIZE]; -int audiobuffer_idx = 0; -Action CMD_cb; - -void BREAK(eMessage msg) -{ - comm.status = eStatus_BRK; - comm.reason = msg; - co_emu_suspended = co_active(); - co_switch(co_control); - comm.status = eStatus_CMD; -} - -void snes_video_refresh(const uint32_t *data, unsigned width, unsigned height) -{ - comm.width = width; - comm.height = height; - comm.ptr = (void*)data; - - BREAK(eMessage_SIG_video_refresh); -} - -void do_SIG_audio_flush() -{ - comm.ptr = audiobuffer; - comm.size = audiobuffer_idx; - BREAK(eMessage_SIG_audio_flush); - audiobuffer_idx = 0; -} - -//this is the raw callback from the emulator internals when a new audio sample is available -void snes_audio_sample(uint16_t left, uint16_t right) -{ - if(!audio_en) return; - - //if theres no room in the audio buffer, we need to send a flush signal - if (audiobuffer_idx == AUDIOBUFFER_SIZE) - { - do_SIG_audio_flush(); - } - - audiobuffer[audiobuffer_idx++] = left; - audiobuffer[audiobuffer_idx++] = right; -} - -void snes_input_poll(void) -{ - BREAK(eMessage_SIG_input_poll); -} - -int16_t snes_input_state(unsigned port, unsigned device, unsigned index, unsigned id) -{ - comm.port = port; - comm.device = device; - comm.index = index; - comm.id = id; - BREAK(eMessage_SIG_input_state); - return comm.value; -} -void snes_input_notify(int index) -{ - comm.index = index; - BREAK(eMessage_SIG_input_notify); -} - -void snes_trace(uint32_t which, const char *msg) -{ - comm.value = which; - comm.str = (char*) msg; - BREAK(eMessage_SIG_trace_callback); -} - -const char* snes_path_request(int slot, const char* hint) -{ - comm.slot = slot; - comm.str= (char *)hint; - BREAK(eMessage_SIG_path_request); - return (const char*)comm.buf[0]; -} - -void snes_scanlineStart(int line) -{ - comm.scanline = line; - BREAK(eMessage_BRK_scanlineStart); -} - -void* snes_allocSharedMemory(const char* memtype, size_t amt) -{ - //its important that this happen before the message marshaling because allocation/free attempts can happen before the marshaling is setup (or at shutdown time, in case of errors?) - //if(!running) return NULL; - - void* ret; - - ret = alloc_plain(amt); - - comm.str = (char*)memtype; - comm.size = amt; - comm.ptr = ret; - - BREAK(eMessage_SIG_allocSharedMemory); - - return comm.ptr; -} - -void snes_freeSharedMemory(void* ptr) -{ - //its important that this happen before the message marshaling because allocation/free attempts can happen before the marshaling is setup (or at shutdown time, in case of errors?) - //if(!running) return; - - if (!ptr) return; - - comm.ptr = ptr; - - BREAK(eMessage_SIG_freeSharedMemory); -} - -static void debug_op_exec(uint24 addr) -{ - comm.addr = addr; - BREAK(eMessage_BRK_hook_exec); -} - -static void debug_op_read(uint24 addr) -{ - comm.addr = addr; - BREAK(eMessage_BRK_hook_read); -} - -static void debug_op_write(uint24 addr, uint8 value) -{ - comm.addr = addr; - comm.value = value; - BREAK(eMessage_BRK_hook_write); -} - -static void debug_op_nmi() -{ - BREAK(eMessage_BRK_hook_nmi); -} - -static void debug_op_irq() -{ - BREAK(eMessage_BRK_hook_irq); -} - -static void debug_op_exec_smp(uint24 addr) -{ - comm.addr = addr; - BREAK(eMessage_BRK_hook_exec_smp); -} - -static void debug_op_read_smp(uint24 addr) -{ - comm.addr = addr; - BREAK(eMessage_BRK_hook_read_smp); -} - -static void debug_op_write_smp(uint24 addr, uint8 value) -{ - comm.addr = addr; - comm.value = value; - BREAK(eMessage_BRK_hook_write_smp); -} - -void pwrap_init() -{ - //bsnes's interface initialization calls into this after initializing itself, so we can get a chance to mod it for pwrap functionalities - snes_set_video_refresh(snes_video_refresh); - snes_set_audio_sample(snes_audio_sample); - snes_set_input_poll(snes_input_poll); - snes_set_input_state(snes_input_state); - snes_set_input_notify(snes_input_notify); - snes_set_path_request(snes_path_request); - snes_set_allocSharedMemory(snes_allocSharedMemory); - snes_set_freeSharedMemory(snes_freeSharedMemory); -} - -static void Analyze() -{ - //gather some "static" type information, so we dont have to poll annoyingly for it later - comm.mapper = snes_get_mapper(); - comm.region = snes_get_region(); -} - -void CMD_LoadCartridgeNormal() -{ - const char* xml = (const char*)comm.buf[0]; - if(!xml[0]) xml = nullptr; - bool ret = snes_load_cartridge_normal(xml, (const uint8_t*)comm.buf[1], comm.buf_size[1]); - comm.value = ret?1:0; - - if(ret) - Analyze(); -} - -void CMD_LoadCartridgeSGB() -{ - bool ret = snes_load_cartridge_super_game_boy((const char*)comm.buf[0], (const u8*)comm.buf[1], comm.buf_size[1], nullptr, (const u8*)comm.buf[2], comm.buf_size[2]); - comm.value = ret ? 1 : 0; - - if(ret) - Analyze(); -} - -void CMD_init() -{ - SNES::config.random = !!comm.value; - snes_init(); - - SNES::input.connect(SNES::Controller::Port1, comm.inports[0]); - SNES::input.connect(SNES::Controller::Port2, comm.inports[1]); -} - -static void CMD_Run() -{ - do_SIG_audio_flush(); - - //we could avoid this if we saved the current thread before jumping back to co_control, instead of always jumping back to co_emu - //in effect, we're scrambling the scheduler - //EDIT - well, we changed that, but.. we still want this probably, for debugging and stuff - for (;;) - { - SNES::scheduler.sync = SNES::Scheduler::SynchronizeMode::None; - SNES::scheduler.clearExitReason(); - SNES::scheduler.enter(); - if (SNES::scheduler.exit_reason() == SNES::Scheduler::ExitReason::FrameEvent) - { - SNES::video.update(); - break; - } - //not used yet - if (SNES::scheduler.exit_reason() == SNES::Scheduler::ExitReason::DebuggerEvent) - break; - } - - do_SIG_audio_flush(); -} - -void QUERY_get_memory_size() { - comm.value = snes_get_memory_size(comm.value); -} -void QUERY_peek() { - if (comm.id == SNES_MEMORY_SYSBUS) - comm.value = bus_read(comm.addr); - else comm.value = snes_get_memory_data(comm.id)[comm.addr]; -} -void QUERY_poke() { - if (comm.id == SNES_MEMORY_SYSBUS) - bus_write(comm.addr, comm.value); - else snes_get_memory_data(comm.id)[comm.addr] = comm.value; -} -void QUERY_set_color_lut() { - snes_set_color_lut((uint32_t*)comm.ptr); -} -void QUERY_GetMemoryIdName() { - comm.str = (char* )snes_get_memory_id_name(comm.id); -} -void QUERY_state_hook_exec() { - SNES::cpu.debugger.op_exec = comm.value ? debug_op_exec : hook(); -} -void QUERY_state_hook_read() { - SNES::cpu.debugger.op_read = comm.value ? debug_op_read : hook(); -} -void QUERY_state_hook_write() { - SNES::cpu.debugger.op_write = comm.value ? debug_op_write : hook(); -} -void QUERY_state_hook_nmi() { - SNES::cpu.debugger.op_nmi = comm.value ? debug_op_nmi : hook(); -} -void QUERY_state_hook_irq() { - SNES::cpu.debugger.op_irq = comm.value ? debug_op_irq : hook(); -} -void QUERY_state_hook_exec_smp() { - SNES::smp.debugger.op_exec = comm.value ? debug_op_exec_smp : hook(); -} -void QUERY_state_hook_read_smp() { - SNES::smp.debugger.op_read = comm.value ? debug_op_read_smp : hook(); -} -void QUERY_state_hook_write_smp() { - SNES::smp.debugger.op_write = comm.value ? debug_op_write_smp : hook(); -} -void QUERY_state_enable_trace() { - snes_set_trace_callback(comm.value, snes_trace); -} -void QUERY_state_enable_scanline() { - if (comm.value) - snes_set_scanlineStart(snes_scanlineStart); - else snes_set_scanlineStart(nullptr); -} -void QUERY_state_enable_audio() { - audio_en = !!comm.value; -} -void QUERY_state_set_layer_enable() { - snes_set_layer_enable(0, 0, !!comm.layerEnables.BG1_Prio0); - snes_set_layer_enable(0, 1, !!comm.layerEnables.BG1_Prio1); - snes_set_layer_enable(1, 0, !!comm.layerEnables.BG2_Prio0); - snes_set_layer_enable(1, 1, !!comm.layerEnables.BG2_Prio1); - snes_set_layer_enable(2, 0, !!comm.layerEnables.BG3_Prio0); - snes_set_layer_enable(2, 1, !!comm.layerEnables.BG3_Prio1); - snes_set_layer_enable(3, 0, !!comm.layerEnables.BG4_Prio0); - snes_set_layer_enable(3, 1, !!comm.layerEnables.BG4_Prio1); - snes_set_layer_enable(4, 0, !!comm.layerEnables.Obj_Prio0); - snes_set_layer_enable(4, 1, !!comm.layerEnables.Obj_Prio1); - snes_set_layer_enable(4, 2, !!comm.layerEnables.Obj_Prio2); - snes_set_layer_enable(4, 3, !!comm.layerEnables.Obj_Prio3); -} -void QUERY_set_backdropColor() { - snes_set_backdropColor((s32)comm.value); -} -void QUERY_peek_logical_register() { - comm.value = snes_peek_logical_register(comm.id); -} -void QUERY_peek_cpu_regs() { - comm.cpuregs.pc = (u32)SNES::cpu.regs.pc; - comm.cpuregs.a = SNES::cpu.regs.a; - comm.cpuregs.x = SNES::cpu.regs.x; - comm.cpuregs.y = SNES::cpu.regs.y; - comm.cpuregs.s = SNES::cpu.regs.s; - comm.cpuregs.d = SNES::cpu.regs.d; - comm.cpuregs.db = SNES::cpu.regs.db; - comm.cpuregs.vector = SNES::cpu.regs.vector; - comm.cpuregs.p = SNES::cpu.regs.p; - comm.cpuregs.nothing = 0; - comm.cpuregs.nothing2 = 0; - comm.cpuregs.v = SNES::cpu.vcounter(); - comm.cpuregs.h = SNES::cpu.hdot(); -} -void QUERY_peek_set_cdl() { - for (int i = 0; i<16; i++) - { - cdlInfo.blocks[i] = (uint8*)comm.cdl_ptr[i]; - cdlInfo.blockSizes[i] = comm.cdl_size[i]; - } -} - -const Action kHandlers_CMD[] = { - CMD_init, - snes_power, - snes_reset, - CMD_Run, - nullptr, - nullptr, - CMD_LoadCartridgeNormal, - CMD_LoadCartridgeSGB, - snes_term, - snes_unload_cartridge, -}; - -const Action kHandlers_QUERY[] = { - QUERY_get_memory_size, //eMessage_QUERY_get_memory_size TODO - grab during bootup (for all possible memdomains) - QUERY_peek, - QUERY_poke, - nullptr, //eMessage_QUERY_serialize_size TODO - grab during bootup/reset (for all possible memdomains) - QUERY_set_color_lut, - QUERY_GetMemoryIdName, //snes_get_memory_id_name TODO - grab during bootup (for all possible memdomains) - QUERY_state_hook_exec, //eMessage_QUERY_state_hook_exec - QUERY_state_hook_read, //eMessage_QUERY_state_hook_read - QUERY_state_hook_write, //eMessage_QUERY_state_hook_write - QUERY_state_hook_exec_smp, //eMessage_QUERY_state_hook_exec_smp - QUERY_state_hook_read_smp, //eMessage_QUERY_state_hook_read_smp - QUERY_state_hook_write_smp, //eMessage_QUERY_state_hook_write_smp - QUERY_state_hook_nmi, //eMessage_QUERY_state_hook_nmi - QUERY_state_hook_irq, //eMessage_QUERY_state_hook_irq - QUERY_state_enable_trace, //eMessage_QUERY_enable_trace TODO - consolidate enable flags - QUERY_state_enable_scanline, //eMessage_QUERY_enable_scanline TODO - consolidate enable flags - QUERY_state_enable_audio, //eMessage_QUERY_enable_audio TODO - consolidate enable flags - QUERY_state_set_layer_enable, //eMessage_QUERY_set_layer_enable - QUERY_set_backdropColor, //eMessage_QUERY_set_backdropColor - QUERY_peek_logical_register, //eMessage_QUERY_peek_logical_register - QUERY_peek_cpu_regs, //eMessage_QUERY_peek_cpu_regs - QUERY_peek_set_cdl, //eMessage_QUERY_set_cdl -}; - -//all this does is run commands on the emulation thread infinitely forever -//(I should probably make a mechanism for bailing...) -void new_emuthread() -{ - for (;;) - { - //process the current CMD - CMD_cb(); - - //when that returned, we're definitely done with the CMD--so we're now IDLE - comm.status = eStatus_Idle; - - co_switch(co_control); - } -} - -//------------------------------------------------ -//DLL INTERFACE - -#include - -ECL_EXPORT void* DllInit() -{ - #define T(s,n) static_assert(offsetof(CommStruct,s)==n,#n) - T(cmd, 0); - T(status, 4); - T(reason, 8); - T(str, 16); - T(ptr, 24); - T(id, 32); - T(port, 48); - T(width, 64); - T(scanline, 72); - T(inports, 76); - T(buf, 88); - T(buf_size, 112); - T(cdl_ptr, 128); - T(cdl_size, 256); - T(cpuregs, 320); - T(layerEnables, 344); - T(region, 356); - T(mapper, 360); - T(BLANKO, 364); - // start of private stuff - T(privbuf, 368); - #undef T - - memset(&comm, 0, sizeof(comm)); - - //make a coroutine thread to run the emulation in. we'll switch back to this cothread when communicating with the frontend - co_control = co_active(); - if (co_emu) - { - // if this was called again, that's OK; delete the old emuthread - co_delete(co_emu); - co_emu = nullptr; - } - co_emu = co_create(32768 * sizeof(void*), new_emuthread); - - return &comm; -} - -ECL_EXPORT void Message(eMessage msg) -{ - if (msg == eMessage_Resume) - { - cothread_t temp = co_emu_suspended; - co_emu_suspended = NULL; - co_switch(temp); - } - - if (msg >= eMessage_CMD_FIRST && msg <= eMessage_CMD_LAST) - { - //CMD is only valid if status is idle - if (comm.status != eStatus_Idle) - { - printf("ERROR: cmd during non-idle\n"); - return; - } - - comm.status = eStatus_CMD; - comm.cmd = msg; - - CMD_cb = kHandlers_CMD[msg - eMessage_CMD_FIRST - 1]; - co_switch(co_emu); - - //we could be in ANY STATE when we return from here - } - - //QUERY can run any time - //but... some of them might not be safe for re-entrancy. - //later, we should have metadata for messages that indicates that - if (msg >= eMessage_QUERY_FIRST && msg <= eMessage_QUERY_LAST) - { - Action cb = kHandlers_QUERY[msg - eMessage_QUERY_FIRST - 1]; - if (cb) cb(); - } -} - - -//receives the given buffer and COPIES it. use this for returning values from SIGs -ECL_EXPORT void CopyBuffer(int id, void* ptr, int32 size) -{ - comm.CopyBuffer(id, ptr, size); -} - -//receives the given buffer and STASHES IT. use this (carefully) for sending params for CMDs -ECL_EXPORT void SetBuffer(int id, void* ptr, int32 size) -{ - comm.SetBuffer(id, ptr, size); -} - -ECL_EXPORT void PostLoadState() -{ - SNES::ppu.flush_tiledata_cache(); -} - -int main() -{ - return 0; -} diff --git a/waterbox/libsnes/libco_debugging/build.sh b/waterbox/libsnes/libco_debugging/build.sh deleted file mode 100644 index 27160d209a..0000000000 --- a/waterbox/libsnes/libco_debugging/build.sh +++ /dev/null @@ -1,2 +0,0 @@ -gcc libco_win32threads.c -o libco.dll -Wall -shared -O0 -g -mv libco.dll ../../BizHawk.MultiClient/output/dll/libco_msvc_win32.dll \ No newline at end of file diff --git a/waterbox/libsnes/libco_debugging/libco.h b/waterbox/libsnes/libco_debugging/libco.h deleted file mode 100644 index deb954fb4d..0000000000 --- a/waterbox/libsnes/libco_debugging/libco.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - libco - version: 0.16 (2010-12-24) - license: public domain -*/ - -#ifndef LIBCO_H -#define LIBCO_H - -#ifdef LIBCO_C - #ifdef LIBCO_MP - #define thread_local __thread - #else - #define thread_local - #endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void* cothread_t; - -cothread_t co_active(); -cothread_t co_create(unsigned int, void (*)(void)); -void co_delete(cothread_t); -void co_switch(cothread_t); - -#ifdef __cplusplus -} -#endif - -/* ifndef LIBCO_H */ -#endif diff --git a/waterbox/libsnes/libco_debugging/libco_win32threads.c b/waterbox/libsnes/libco_debugging/libco_win32threads.c deleted file mode 100644 index f33bb7b4bb..0000000000 --- a/waterbox/libsnes/libco_debugging/libco_win32threads.c +++ /dev/null @@ -1,138 +0,0 @@ -/* -win32 implementation of libco using actual threads. much slower than other implementations, -but far from glacial. may be useful for debuggers that don't understand libco cothreads. - -compiles in mingw. try: -gcc libco_win32threads.c -o libco.dll -Wall -shared -O0 -g -*/ - -#include -#include // asserts don't happen in co_switch(), so no real performance gain from turning them off -#define LIBCO_C -#include "libco.h" -#define WIN32_LEAN_AND_MEAN -#include - -typedef struct -{ - HANDLE thread; - HANDLE sem; - int wantdie; - void (*entrypoint)(void); -} coprivate; - -static __thread coprivate *libco_priv = NULL; - - -/* -Return handle to current cothread. Always returns a valid handle, even when called from the main program thread. -*/ -cothread_t co_active(void) -{ - if (!libco_priv) - { - // thread started out as a real thread, so we must make a libco_priv for it - libco_priv = malloc(sizeof (*libco_priv)); - assert(libco_priv); - DWORD ret = DuplicateHandle - ( - GetCurrentProcess(), - GetCurrentThread(), - GetCurrentProcess(), - &libco_priv->thread, - 0, - FALSE, - DUPLICATE_SAME_ACCESS - ); - assert(ret); - libco_priv->sem = CreateSemaphore(NULL, 0, 1, NULL); - assert(libco_priv->sem); - libco_priv->wantdie = 0; - libco_priv->entrypoint = NULL; - } - return (cothread_t) libco_priv; -} - -void waittorun(void) -{ - // i suppose it would be possible to switch off the main thread - // without ever having made a context for it. then it would never - // be able to activate again. - coprivate *this = (coprivate *) co_active(); - WaitForSingleObject(this->sem, INFINITE); - if (this->wantdie) - { - CloseHandle(this->sem); - ExitThread(0); - } -} - -DWORD WINAPI thread_entry(LPVOID lpParameter) -{ - libco_priv = (coprivate *) lpParameter; - waittorun(); - libco_priv->entrypoint(); - assert(0); // returning from entry point not allowed - return 0; -} - -/* -Create new cothread. -Heapsize is the amount of memory allocated for the cothread stack, specified in bytes. This is unfortunately impossible to make fully portable. It is recommended to specify sizes using `n * sizeof(void*)'. It is better to err on the side of caution and allocate more memory than will be needed to ensure compatibility with other platforms, within reason. A typical heapsize for a 32-bit architecture is ~1MB. -When the new cothread is first called, program execution jumps to coentry. This function does not take any arguments, due to portability issues with passing function arguments. However, arguments can be simulated by the use of global variables, which can be set before the first call to each cothread. -coentry() must not return, and should end with an appropriate co_switch() statement. Behavior is undefined if entry point returns normally. -Library is responsible for allocating cothread stack memory, to free the user from needing to allocate special memory capable of being used as program stack memory on platforms where this is required. -User is always responsible for deleting cothreads with co_delete(). -Return value of null (0) indicates cothread creation failed. -*/ -cothread_t co_create(unsigned int heapsize, void (*entry)(void)) -{ - coprivate *new_thread = malloc(sizeof (*new_thread)); - assert(new_thread); - new_thread->sem = CreateSemaphore(NULL, 0, 1, NULL); - assert(new_thread->sem); - new_thread->wantdie = 0; - new_thread->entrypoint = entry; - assert(new_thread->entrypoint); - new_thread->thread = CreateThread - ( - NULL, - heapsize, - thread_entry, - (void *)new_thread, - 0, // runs immediately - NULL - ); - assert(new_thread->thread); - return (cothread_t) new_thread; -} - -/* -Delete specified cothread. -Null (0) or invalid cothread handle is not allowed. -Passing handle of active cothread to this function is not allowed. -Passing handle of primary cothread is not allowed. -*/ -void co_delete(cothread_t _thread) -{ - coprivate *thread = (coprivate *) _thread; - assert(thread); - assert(thread->entrypoint); // Passing handle of primary cothread is not allowed - thread->wantdie = 1; - ReleaseSemaphore(thread->sem, 1, NULL); - WaitForSingleObject(thread->thread, INFINITE); - CloseHandle(thread->thread); - free(thread); -} - -/* -Switch to specified cothread. -Null (0) or invalid cothread handle is not allowed. -Passing handle of active cothread to this function is not allowed. -*/ -void co_switch(cothread_t _thread) -{ - coprivate *thread = (coprivate *) _thread; - ReleaseSemaphore(thread->sem, 1, NULL); - waittorun(); -} diff --git a/waterbox/libsnes/libco_debugging/makefile b/waterbox/libsnes/libco_debugging/makefile deleted file mode 100644 index 72bb5bd15e..0000000000 --- a/waterbox/libsnes/libco_debugging/makefile +++ /dev/null @@ -1,2 +0,0 @@ -libco.dll: libco_win32threads.c - gcc libco_win32threads.c -o libco.dll -Wall -shared -O0 -g diff --git a/waterbox/libsnes/lsnes_patches/0001-Don-t-use-time-in-emulating-chips.patch b/waterbox/libsnes/lsnes_patches/0001-Don-t-use-time-in-emulating-chips.patch deleted file mode 100644 index 7df8070176..0000000000 --- a/waterbox/libsnes/lsnes_patches/0001-Don-t-use-time-in-emulating-chips.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 22205d4d339cfa11f6d53e644eae1c859a56d349 Mon Sep 17 00:00:00 2001 -From: Ilari Liusvaara -Date: Wed, 9 Nov 2011 00:37:44 +0200 -Subject: [PATCH 1/4] Don't use time() in emulating chips - -Instead of using time() in chip emulation, create new interface method -currentTime(), defaulting to time(0). This way frontend can cleanly -override the current time bsnes is using. ---- - snes/chip/bsx/satellaview/satellaview.cpp | 2 +- - snes/chip/spc7110/spc7110.cpp | 2 +- - snes/chip/srtc/srtc.cpp | 2 +- - snes/interface/interface.cpp | 5 +++++ - snes/interface/interface.hpp | 1 + - 5 files changed, 9 insertions(+), 3 deletions(-) - -diff --git a/snes/chip/bsx/satellaview/satellaview.cpp b/snes/chip/bsx/satellaview/satellaview.cpp -index 386fb62..3c98019 100755 ---- snes/chip/bsx/satellaview/satellaview.cpp -+++ snes/chip/bsx/satellaview/satellaview.cpp -@@ -38,7 +38,7 @@ uint8 BSXSatellaview::mmio_read(unsigned addr) { - - if(counter == 0) { - time_t rawtime; -- time(&rawtime); -+ rawtime = SNES::interface->currentTime(); - tm *t = localtime(&rawtime); - - regs.r2192_hour = t->tm_hour; -diff --git a/snes/chip/spc7110/spc7110.cpp b/snes/chip/spc7110/spc7110.cpp -index 27b8b77..061aa5e 100755 ---- snes/chip/spc7110/spc7110.cpp -+++ snes/chip/spc7110/spc7110.cpp -@@ -101,7 +101,7 @@ void SPC7110::set_data_adjust(unsigned addr) { r4814 = addr; r4815 = addr >> 8; - - void SPC7110::update_time(int offset) { - time_t rtc_time = (rtc[16] << 0) | (rtc[17] << 8) | (rtc[18] << 16) | (rtc[19] << 24); -- time_t current_time = time(0) - offset; -+ time_t current_time = SNES::interface->currentTime() - offset; - - //sizeof(time_t) is platform-dependent; though rtc[] needs to be platform-agnostic. - //yet platforms with 32-bit signed time_t will overflow every ~68 years. handle this by -diff --git a/snes/chip/srtc/srtc.cpp b/snes/chip/srtc/srtc.cpp -index 0044113..725e891 100755 ---- snes/chip/srtc/srtc.cpp -+++ snes/chip/srtc/srtc.cpp -@@ -31,7 +31,7 @@ void SRTC::reset() { - - void SRTC::update_time() { - time_t rtc_time = (rtc[16] << 0) | (rtc[17] << 8) | (rtc[18] << 16) | (rtc[19] << 24); -- time_t current_time = time(0); -+ time_t current_time = SNES::interface->currentTime(); - - //sizeof(time_t) is platform-dependent; though rtc[] needs to be platform-agnostic. - //yet platforms with 32-bit signed time_t will overflow every ~68 years. handle this by -diff --git a/snes/interface/interface.cpp b/snes/interface/interface.cpp -index a0e3a81..b3017c9 100755 ---- snes/interface/interface.cpp -+++ snes/interface/interface.cpp -@@ -18,4 +18,9 @@ void Interface::message(const string &text) { - print(text, "\n"); - } - -+time_t Interface::currentTime() -+{ -+ return time(0); -+} -+ - } -diff --git a/snes/interface/interface.hpp b/snes/interface/interface.hpp -index f1a48c0..df975e8 100755 ---- snes/interface/interface.hpp -+++ snes/interface/interface.hpp -@@ -5,6 +5,7 @@ struct Interface { - - virtual string path(Cartridge::Slot slot, const string &hint) = 0; - virtual void message(const string &text); -+ virtual time_t currentTime(); - }; - - extern Interface *interface; --- -1.7.9.48.g85da4d - diff --git a/waterbox/libsnes/lsnes_patches/0002-Save-controller-state-when-savestating.patch b/waterbox/libsnes/lsnes_patches/0002-Save-controller-state-when-savestating.patch deleted file mode 100644 index a585958334..0000000000 --- a/waterbox/libsnes/lsnes_patches/0002-Save-controller-state-when-savestating.patch +++ /dev/null @@ -1,346 +0,0 @@ -From fe11984ad18561506a7cc874cb7c0421f1e21ad1 Mon Sep 17 00:00:00 2001 -From: Ilari Liusvaara -Date: Wed, 9 Nov 2011 01:52:08 +0200 -Subject: [PATCH 2/4] Save controller state when savestating - -When savestating, save the controller state and restore it upon loadstate. -Prevents libsnes from mixing up buttons. ---- - snes/controller/controller.cpp | 8 ++++++ - snes/controller/controller.hpp | 2 + - snes/controller/gamepad/gamepad.cpp | 13 ++++++++++ - snes/controller/gamepad/gamepad.hpp | 2 +- - snes/controller/justifier/justifier.cpp | 36 +++++++++++++++++++++++++++++ - snes/controller/justifier/justifier.hpp | 1 + - snes/controller/mouse/mouse.cpp | 13 ++++++++++ - snes/controller/mouse/mouse.hpp | 2 +- - snes/controller/multitap/multitap.cpp | 16 +++++++++++++ - snes/controller/multitap/multitap.hpp | 2 +- - snes/controller/superscope/superscope.cpp | 31 +++++++++++++++++++++++++ - snes/controller/superscope/superscope.hpp | 1 + - snes/system/input.cpp | 16 +++++++++++++ - snes/system/input.hpp | 1 + - snes/system/serialization.cpp | 1 + - 15 files changed, 142 insertions(+), 3 deletions(-) - -diff --git a/snes/controller/controller.cpp b/snes/controller/controller.cpp -index fa8e07d..5f37849 100755 ---- snes/controller/controller.cpp -+++ snes/controller/controller.cpp -@@ -46,8 +46,16 @@ void Controller::iobit(bool data) { - } - } - -+void Controller::serialize(serializer& s) { -+ Processor::serialize(s); -+ //Save a zero block. -+ unsigned char blockzeroes[SaveSize] = {0}; -+ s.array(blockzeroes, SaveSize); -+} -+ - Controller::Controller(bool port) : port(port) { - if(!thread) create(Controller::Enter, 1); - } - -+ - } -diff --git a/snes/controller/controller.hpp b/snes/controller/controller.hpp -index dd748a1..46095a8 100755 ---- snes/controller/controller.hpp -+++ snes/controller/controller.hpp -@@ -13,12 +13,14 @@ - - struct Controller : Processor { - enum : bool { Port1 = 0, Port2 = 1 }; -+ enum { SaveSize = 16 }; - const bool port; - - static void Enter(); - virtual void enter(); - void step(unsigned clocks); - void synchronize_cpu(); -+ virtual void serialize(serializer& s); - - bool iobit(); - void iobit(bool data); -diff --git a/snes/controller/gamepad/gamepad.cpp b/snes/controller/gamepad/gamepad.cpp -index 594020d..4fa1c99 100755 ---- snes/controller/gamepad/gamepad.cpp -+++ snes/controller/gamepad/gamepad.cpp -@@ -13,6 +13,19 @@ void Gamepad::latch(bool data) { - counter = 0; - } - -+void Gamepad::serialize(serializer& s) { -+ Processor::serialize(s); -+ //Save block. -+ unsigned char block[Controller::SaveSize] = {0}; -+ block[0] = latched ? 1 : 0; -+ block[1] = counter; -+ s.array(block, Controller::SaveSize); -+ if(s.mode() == nall::serializer::Load) { -+ latched = (block[0] != 0); -+ counter = block[1]; -+ } -+} -+ - Gamepad::Gamepad(bool port) : Controller(port) { - latched = 0; - counter = 0; -diff --git a/snes/controller/gamepad/gamepad.hpp b/snes/controller/gamepad/gamepad.hpp -index c5ca69c..a2392d1 100755 ---- snes/controller/gamepad/gamepad.hpp -+++ snes/controller/gamepad/gamepad.hpp -@@ -2,7 +2,7 @@ struct Gamepad : Controller { - uint2 data(); - void latch(bool data); - Gamepad(bool port); -- -+ void serialize(serializer& s); - private: - bool latched; - unsigned counter; -diff --git a/snes/controller/justifier/justifier.cpp b/snes/controller/justifier/justifier.cpp -index 6207916..ad13a9b 100755 ---- snes/controller/justifier/justifier.cpp -+++ snes/controller/justifier/justifier.cpp -@@ -100,6 +100,42 @@ void Justifier::latch(bool data) { - if(latched == 0) active = !active; //toggle between both controllers, even when unchained - } - -+void Justifier::serialize(serializer& s) { -+ Processor::serialize(s); -+ //Save block. -+ unsigned char block[Controller::SaveSize] = {0}; -+ block[0] = latched ? 1 : 0; -+ block[1] = counter; -+ block[2] = active ? 1 : 0; -+ block[3] = player1.trigger ? 1 : 0; -+ block[4] = player2.trigger ? 1 : 0; -+ block[5] = player1.start ? 1 : 0; -+ block[6] = player2.start ? 1 : 0; -+ block[7] = (unsigned short)player1.x >> 8; -+ block[8] = (unsigned short)player1.x; -+ block[9] = (unsigned short)player2.x >> 8; -+ block[10] = (unsigned short)player2.x; -+ block[11] = (unsigned short)player1.y >> 8; -+ block[12] = (unsigned short)player1.y; -+ block[13] = (unsigned short)player2.y >> 8; -+ block[14] = (unsigned short)player2.y; -+ s.array(block, Controller::SaveSize); -+ if(s.mode() == nall::serializer::Load) { -+ latched = (block[0] != 0); -+ counter = block[1]; -+ active = (block[2] != 0); -+ player1.trigger = (block[3] != 0); -+ player2.trigger = (block[4] != 0); -+ player1.start = (block[5] != 0); -+ player2.start = (block[6] != 0); -+ player1.x = (short)(((unsigned short)block[7] << 8) | (unsigned short)block[8]); -+ player2.x = (short)(((unsigned short)block[9] << 8) | (unsigned short)block[10]); -+ player1.y = (short)(((unsigned short)block[11] << 8) | (unsigned short)block[12]); -+ player2.y = (short)(((unsigned short)block[13] << 8) | (unsigned short)block[14]); -+ } -+} -+ -+ - Justifier::Justifier(bool port, bool chained) : Controller(port), chained(chained) { - create(Controller::Enter, 21477272); - latched = 0; -diff --git a/snes/controller/justifier/justifier.hpp b/snes/controller/justifier/justifier.hpp -index f927acf..6b7bba0 100755 ---- snes/controller/justifier/justifier.hpp -+++ snes/controller/justifier/justifier.hpp -@@ -2,6 +2,7 @@ struct Justifier : Controller { - void enter(); - uint2 data(); - void latch(bool data); -+ void serialize(serializer& s); - Justifier(bool port, bool chained); - - //private: -diff --git a/snes/controller/mouse/mouse.cpp b/snes/controller/mouse/mouse.cpp -index c9f5d16..6b26fae 100755 ---- snes/controller/mouse/mouse.cpp -+++ snes/controller/mouse/mouse.cpp -@@ -61,6 +61,19 @@ void Mouse::latch(bool data) { - counter = 0; - } - -+void Mouse::serialize(serializer& s) { -+ Processor::serialize(s); -+ //Save block. -+ unsigned char block[Controller::SaveSize] = {0}; -+ block[0] = latched ? 1 : 0; -+ block[1] = counter; -+ s.array(block, Controller::SaveSize); -+ if(s.mode() == nall::serializer::Load) { -+ latched = (block[0] != 0); -+ counter = block[1]; -+ } -+} -+ - Mouse::Mouse(bool port) : Controller(port) { - latched = 0; - counter = 0; -diff --git a/snes/controller/mouse/mouse.hpp b/snes/controller/mouse/mouse.hpp -index 95e24b6..b66ea51 100755 ---- snes/controller/mouse/mouse.hpp -+++ snes/controller/mouse/mouse.hpp -@@ -2,7 +2,7 @@ struct Mouse : Controller { - uint2 data(); - void latch(bool data); - Mouse(bool port); -- -+ void serialize(serializer& s); - private: - bool latched; - unsigned counter; -diff --git a/snes/controller/multitap/multitap.cpp b/snes/controller/multitap/multitap.cpp -index 3a6eb72..146c41d 100755 ---- snes/controller/multitap/multitap.cpp -+++ snes/controller/multitap/multitap.cpp -@@ -30,6 +30,22 @@ void Multitap::latch(bool data) { - counter2 = 0; - } - -+void Multitap::serialize(serializer& s) { -+ Processor::serialize(s); -+ //Save block. -+ unsigned char block[Controller::SaveSize] = {0}; -+ block[0] = latched ? 1 : 0; -+ block[1] = counter1; -+ block[2] = counter2; -+ s.array(block, Controller::SaveSize); -+ if(s.mode() == nall::serializer::Load) { -+ latched = (block[0] != 0); -+ counter1 = block[1]; -+ counter2 = block[2]; -+ } -+} -+ -+ - Multitap::Multitap(bool port) : Controller(port) { - latched = 0; - counter1 = 0; -diff --git a/snes/controller/multitap/multitap.hpp b/snes/controller/multitap/multitap.hpp -index 0540af7..e6324ac 100755 ---- snes/controller/multitap/multitap.hpp -+++ snes/controller/multitap/multitap.hpp -@@ -2,7 +2,7 @@ struct Multitap : Controller { - uint2 data(); - void latch(bool data); - Multitap(bool port); -- -+ void serialize(serializer& s); - private: - bool latched; - unsigned counter1; -diff --git a/snes/controller/superscope/superscope.cpp b/snes/controller/superscope/superscope.cpp -index 12068f0..1a1dfbf 100755 ---- snes/controller/superscope/superscope.cpp -+++ snes/controller/superscope/superscope.cpp -@@ -100,6 +100,37 @@ void SuperScope::latch(bool data) { - counter = 0; - } - -+void SuperScope::serialize(serializer& s) { -+ Processor::serialize(s); -+ //Save block. -+ unsigned char block[Controller::SaveSize] = {0}; -+ block[0] = latched ? 1 : 0; -+ block[1] = counter; -+ block[2] = trigger ? 1 : 0; -+ block[3] = cursor ? 1 : 0; -+ block[4] = turbo ? 1 : 0; -+ block[5] = pause ? 1 : 0; -+ block[6] = offscreen ? 1 : 0; -+ block[7] = (unsigned short)x >> 8; -+ block[8] = (unsigned short)x; -+ block[9] = (unsigned short)y >> 8; -+ block[10] = (unsigned short)y; -+ -+ s.array(block, Controller::SaveSize); -+ if(s.mode() == nall::serializer::Load) { -+ latched = (block[0] != 0); -+ counter = block[1]; -+ trigger = (block[2] != 0); -+ cursor = (block[3] != 0); -+ turbo = (block[4] != 0); -+ pause = (block[5] != 0); -+ offscreen = (block[6] != 0); -+ x = (short)(((unsigned short)block[7] << 8) | (unsigned short)block[8]); -+ y = (short)(((unsigned short)block[9] << 8) | (unsigned short)block[10]); -+ } -+} -+ -+ - SuperScope::SuperScope(bool port) : Controller(port) { - create(Controller::Enter, 21477272); - latched = 0; -diff --git a/snes/controller/superscope/superscope.hpp b/snes/controller/superscope/superscope.hpp -index a7a90b7..93509d7 100755 ---- snes/controller/superscope/superscope.hpp -+++ snes/controller/superscope/superscope.hpp -@@ -2,6 +2,7 @@ struct SuperScope : Controller { - void enter(); - uint2 data(); - void latch(bool data); -+ void serialize(serializer& s); - SuperScope(bool port); - - //private: -diff --git a/snes/system/input.cpp b/snes/system/input.cpp -index 894de0e..4479acc 100755 ---- snes/system/input.cpp -+++ snes/system/input.cpp -@@ -26,6 +26,22 @@ void Input::connect(bool port, Input::Device id) { - } - } - -+void Input::serialize(serializer &s) -+{ -+ int p1, p2; -+ p1 = (int)config.controller_port1; -+ p2 = (int)config.controller_port2; -+ s.integer(p1); -+ s.integer(p2); -+ if(s.mode() == nall::serializer::Load) { -+ connect(Controller::Port1, (Device)p1); -+ connect(Controller::Port2, (Device)p2); -+ } -+ port1->serialize(s); -+ port2->serialize(s); -+} -+ -+ - Input::Input() : port1(nullptr), port2(nullptr) { - connect(Controller::Port1, Input::Device::Joypad); - connect(Controller::Port2, Input::Device::Joypad); -diff --git a/snes/system/input.hpp b/snes/system/input.hpp -index 7a6bd9e..d2f5fef 100755 ---- snes/system/input.hpp -+++ snes/system/input.hpp -@@ -31,6 +31,7 @@ struct Input { - Controller *port1; - Controller *port2; - -+ void serialize(serializer &s); - void connect(bool port, Input::Device id); - Input(); - ~Input(); -diff --git a/snes/system/serialization.cpp b/snes/system/serialization.cpp -index f746c3a..67e08a2 100755 ---- snes/system/serialization.cpp -+++ snes/system/serialization.cpp -@@ -56,6 +56,7 @@ void System::serialize_all(serializer &s) { - smp.serialize(s); - ppu.serialize(s); - dsp.serialize(s); -+ input.serialize(s); - - if(cartridge.mode() == Cartridge::Mode::SufamiTurbo) sufamiturbo.serialize(s); - #if defined(GAMEBOY) --- -1.7.9.48.g85da4d - diff --git a/waterbox/libsnes/lsnes_patches/0003-Allow-frontend-to-control-random-number-seed.patch b/waterbox/libsnes/lsnes_patches/0003-Allow-frontend-to-control-random-number-seed.patch deleted file mode 100644 index 828e83a810..0000000000 --- a/waterbox/libsnes/lsnes_patches/0003-Allow-frontend-to-control-random-number-seed.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 5f76449a70c9a546e18c2fdebe7588bbe90b56d2 Mon Sep 17 00:00:00 2001 -From: Ilari Liusvaara -Date: Fri, 11 Nov 2011 19:49:46 +0200 -Subject: [PATCH 3/4] Allow frontend to control random number seed - ---- - snes/interface/interface.cpp | 5 +++++ - snes/interface/interface.hpp | 1 + - snes/system/system.cpp | 2 +- - 3 files changed, 7 insertions(+), 1 deletions(-) - -diff --git a/snes/interface/interface.cpp b/snes/interface/interface.cpp -index b3017c9..0a21a13 100755 ---- snes/interface/interface.cpp -+++ snes/interface/interface.cpp -@@ -23,4 +23,9 @@ time_t Interface::currentTime() - return time(0); - } - -+time_t Interface::randomSeed() -+{ -+ return time(0); -+} -+ - } -diff --git a/snes/interface/interface.hpp b/snes/interface/interface.hpp -index df975e8..30ee7fd 100755 ---- snes/interface/interface.hpp -+++ snes/interface/interface.hpp -@@ -6,6 +6,7 @@ struct Interface { - virtual string path(Cartridge::Slot slot, const string &hint) = 0; - virtual void message(const string &text); - virtual time_t currentTime(); -+ virtual time_t randomSeed(); - }; - - extern Interface *interface; -diff --git a/snes/system/system.cpp b/snes/system/system.cpp -index 9b70bbf..cbd096c 100755 ---- snes/system/system.cpp -+++ snes/system/system.cpp -@@ -151,7 +151,7 @@ void System::unload() { - } - - void System::power() { -- random.seed((unsigned)time(0)); -+ random.seed((unsigned)interface->randomSeed()); - - region = config.region; - expansion = config.expansion_port; --- -1.7.9.48.g85da4d - diff --git a/waterbox/libsnes/lsnes_patches/0004-Fix-mouse-polling.patch b/waterbox/libsnes/lsnes_patches/0004-Fix-mouse-polling.patch deleted file mode 100644 index bdecda2782..0000000000 --- a/waterbox/libsnes/lsnes_patches/0004-Fix-mouse-polling.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 160dedf35571478781737ee35307b9321cfb41bb Mon Sep 17 00:00:00 2001 -From: Ilari Liusvaara -Date: Wed, 7 Mar 2012 16:57:18 +0200 -Subject: [PATCH 4/4] Fix mouse polling - -Don't poll for mouse motion excessive number of times (no need to poll it for -each bit!) ---- - snes/controller/mouse/mouse.cpp | 12 ++++++++++-- - snes/controller/mouse/mouse.hpp | 2 ++ - 2 files changed, 12 insertions(+), 2 deletions(-) - -diff --git a/snes/controller/mouse/mouse.cpp b/snes/controller/mouse/mouse.cpp -index 6b26fae..824ecd3 100755 ---- snes/controller/mouse/mouse.cpp -+++ snes/controller/mouse/mouse.cpp -@@ -3,8 +3,10 @@ - uint2 Mouse::data() { - if(counter >= 32) return 1; - -- int position_x = interface->inputPoll(port, Input::Device::Mouse, 0, (unsigned)Input::MouseID::X); //-n = left, 0 = center, +n = right -- int position_y = interface->inputPoll(port, Input::Device::Mouse, 0, (unsigned)Input::MouseID::Y); //-n = up, 0 = center, +n = down -+ if(counter == 0) { -+ position_x = interface->inputPoll(port, Input::Device::Mouse, 0, (unsigned)Input::MouseID::X); //-n = left, 0 = center, +n = right -+ position_y = interface->inputPoll(port, Input::Device::Mouse, 0, (unsigned)Input::MouseID::Y); //-n = up, 0 = center, +n = down -+ } - - bool direction_x = position_x < 0; //0 = right, 1 = left - bool direction_y = position_y < 0; //0 = down, 1 = up -@@ -67,10 +69,16 @@ void Mouse::serialize(serializer& s) { - unsigned char block[Controller::SaveSize] = {0}; - block[0] = latched ? 1 : 0; - block[1] = counter; -+ block[2] = (unsigned short)position_x >> 8; -+ block[3] = (unsigned short)position_x; -+ block[4] = (unsigned short)position_y >> 8; -+ block[5] = (unsigned short)position_y; - s.array(block, Controller::SaveSize); - if(s.mode() == nall::serializer::Load) { - latched = (block[0] != 0); - counter = block[1]; -+ position_x = (short)(((unsigned short)block[2] << 8) | (unsigned short)block[3]); -+ position_y = (short)(((unsigned short)block[4] << 8) | (unsigned short)block[5]); - } - } - -diff --git a/snes/controller/mouse/mouse.hpp b/snes/controller/mouse/mouse.hpp -index b66ea51..6074f34 100755 ---- snes/controller/mouse/mouse.hpp -+++ snes/controller/mouse/mouse.hpp -@@ -6,4 +6,6 @@ struct Mouse : Controller { - private: - bool latched; - unsigned counter; -+ int position_x; -+ int position_y; - }; --- -1.7.9.48.g85da4d - diff --git a/waterbox/make-all-cores.sh b/waterbox/make-all-cores.sh index d85f95f0e1..5fd76838e2 100755 --- a/waterbox/make-all-cores.sh +++ b/waterbox/make-all-cores.sh @@ -8,7 +8,6 @@ make -C libco $1 -j make -C bsnescore $1 -j make -C dsda $1 -j make -C gpgx $1 -j -make -C libsnes $1 -j make -C melon $1 -j make -C picodrive $1 -j make -C stella $1 -j diff --git a/waterbox/readme.txt b/waterbox/readme.txt index 6ce1c87ecd..960576dbd3 100644 --- a/waterbox/readme.txt +++ b/waterbox/readme.txt @@ -67,7 +67,6 @@ It consists of a modified musl libc, and build scripts to tie it all together. cd bsnescore && make install cd dsda && make install cd gpgx && make install - cd libsnes && make install cd mame-arcade && make install cd melon && make install cd nyma && make -f faust.mak install