From 970dcea0ac62aa48ac0a6a1103424951ea83f719 Mon Sep 17 00:00:00 2001 From: byuu Date: Wed, 3 Aug 2005 21:22:42 +0000 Subject: [PATCH] Update to bsnes v010 release. bsnes now supports SPC700 emulation (no DSP or sound support, however), and has greatly improved compatibility. It also now contains a keyboard-only joypad configuration tool. --- bsnes.cfg | 21 + bsnes.exe | Bin 0 -> 614400 bytes bsnes_g2.exe | Bin 315392 -> 0 bytes license.txt | 23 +- src/apu/apu.cpp | 2 + src/apu/apu.h | 28 + src/apu/apuregs.h | 48 + src/apu/bapu/bapu.cpp | 293 ++++ src/apu/bapu/bapu.h | 79 + src/apu/bapu/bapu_exec.cpp | 20 + src/apu/bapu/bapu_op.h | 256 +++ src/apu/bapu/bapu_op_fn.cpp | 140 ++ src/apu/bapu/bapu_op_misc.cpp | 643 ++++++++ src/apu/bapu/bapu_op_mov.cpp | 710 ++++++++ src/apu/bapu/bapu_op_pc.cpp | 1155 +++++++++++++ src/apu/bapu/bapu_op_read.cpp | 1467 +++++++++++++++++ src/apu/bapu/bapu_op_rmw.cpp | 452 +++++ src/apu/bapu/bapu_optable.cpp | 256 +++ src/apu/bapu/bapugen.cpp | 168 ++ src/apu/bapu/bapugen.exe | Bin 0 -> 53248 bytes src/apu/bapu/cc.bat | 3 + src/apu/bapu/clean.bat | 1 + src/apu/bapu/op_misc.b | 164 ++ src/apu/bapu/op_mov.b | 207 +++ src/apu/bapu/op_pc.b | 157 ++ src/apu/bapu/op_read.b | 194 +++ src/apu/bapu/op_rmw.b | 60 + src/apu/bapuskip/bapuskip.cpp | 171 ++ src/apu/bapuskip/bapuskip.h | 33 + src/apu/dapu.cpp | 295 ++++ src/apu/iplrom.h | 48 + src/base.h | 1 + src/clock/bclock/bclock.cpp | 201 --- src/clock/bclock/bclock.h | 37 - src/clock/clock.cpp | 49 - src/clock/clock.h | 36 - src/cpu/bcpu/bcpu.cpp | 439 ++--- src/cpu/bcpu/bcpu.h | 742 ++------- src/cpu/bcpu/bcpu_dma.cpp | 241 +++ src/cpu/bcpu/bcpu_exec.cpp | 549 +------ src/cpu/bcpu/bcpu_mmio.cpp | 519 +++--- src/cpu/bcpu/bcpu_op.h | 256 +++ src/cpu/bcpu/bcpu_op_adc.cpp | 464 ------ src/cpu/bcpu/bcpu_op_and.cpp | 444 ----- src/cpu/bcpu/bcpu_op_cmp.cpp | 448 ----- src/cpu/bcpu/bcpu_op_eor.cpp | 444 ----- src/cpu/bcpu/bcpu_op_incdec.cpp | 433 ----- src/cpu/bcpu/bcpu_op_lda.cpp | 444 ----- src/cpu/bcpu/bcpu_op_misc.cpp | 1799 +++++--------------- src/cpu/bcpu/bcpu_op_ora.cpp | 444 ----- src/cpu/bcpu/bcpu_op_pc.cpp | 659 +++----- src/cpu/bcpu/bcpu_op_read.cpp | 1913 ++++++++++++++++++++++ src/cpu/bcpu/bcpu_op_rmw.cpp | 740 +++++++++ src/cpu/bcpu/bcpu_op_sbc.cpp | 464 ------ src/cpu/bcpu/bcpu_op_shift.cpp | 779 --------- src/cpu/bcpu/bcpu_op_sta.cpp | 387 ----- src/cpu/bcpu/bcpu_op_stack.cpp | 317 ---- src/cpu/bcpu/bcpu_op_write.cpp | 340 ++++ src/cpu/bcpu/bcpu_opfn.cpp | 295 ++++ src/cpu/bcpu/bcpu_optable.cpp | 256 +++ src/cpu/bcpu/bcpu_timing.cpp | 141 ++ src/cpu/bcpu/bcpu_timing.h | 38 + src/cpu/bcpu/bcpugen.cpp | 168 ++ src/cpu/bcpu/bcpugen.exe | Bin 0 -> 53248 bytes src/cpu/bcpu/cc.bat | 3 + src/cpu/bcpu/clean.bat | 8 + src/cpu/bcpu/op_misc.b | 252 +++ src/cpu/bcpu/op_pc.b | 137 ++ src/cpu/bcpu/op_read.b | 283 ++++ src/cpu/bcpu/op_rmw.b | 175 ++ src/cpu/bcpu/op_write.b | 151 ++ src/cpu/bcpu/srtc.cpp | 158 ++ src/cpu/bcpu/srtc.h | 48 + src/cpu/cpu.h | 26 +- src/cpu/cpuregs.h | 33 +- src/cpu/dcpu.cpp | 2 +- src/interface.h | 19 +- src/lib/libconfig.cpp | 135 +- src/lib/libconfig.h | 2 +- src/lib/libstring.cpp | 8 +- src/lib/libstring.h | 38 +- src/lib/libstring_sprintf.cpp | 2 +- src/lib/libvector.h | 3 +- src/memory/bmemory/bcart_exhirom.cpp | 108 ++ src/memory/bmemory/bcart_exhirom.h | 14 + src/memory/bmemory/bcart_hirom.cpp | 86 + src/memory/bmemory/bcart_hirom.h | 14 + src/memory/bmemory/bcart_lorom.cpp | 104 ++ src/memory/bmemory/bcart_lorom.h | 14 + src/memory/bmemory/bmemory.cpp | 274 ++-- src/memory/bmemory/bmemory.h | 37 +- src/memory/memory.h | 22 +- src/ppu/bppu/bppu.cpp | 79 +- src/ppu/bppu/bppu.h | 32 +- src/ppu/bppu/bppu_mmio.cpp | 52 +- src/ppu/bppu/bppu_old_render.cpp | 133 -- src/ppu/bppu/bppu_old_render.h | 70 - src/ppu/bppu/bppu_old_render_cache.cpp | 33 - src/ppu/bppu/bppu_old_render_main.cpp | 696 -------- src/ppu/bppu/bppu_old_render_mode7.cpp | 110 -- src/ppu/bppu/bppu_old_render_windows.cpp | 159 -- src/ppu/bppu/bppu_render.h | 21 +- src/ppu/bppu/bppu_render_bg.cpp | 2 + src/ppu/bppu/bppu_render_oam.cpp | 300 ++-- src/ppu/bppu/old_bppu_render_oam.cpp | 230 +++ src/ppu/ppu.cpp | 2 + src/ppu/ppu.h | 1 + src/sdl/Makefile | 81 + src/sdl/Makefile.win32 | 82 + src/sdl/bsnes.cpp | 90 + src/sdl/bsnes.h | 30 + src/sdl/bsnes_sdl.cfg | 18 + src/sdl/cc.bat | 3 + src/sdl/clean.bat | 1 + src/sdl/config.cpp | 47 + src/sdl/render.cpp | 110 ++ src/sdl/rom.cpp | 99 ++ src/sdl/sdlmain.cpp | 181 ++ src/sdl/sdlmain.h | 17 + src/sdl/sdlrun.bat | 1 + src/snes/snes.cpp | 15 +- src/snes/snes.h | 14 +- src/win/Makefile | 28 +- src/win/bsnes.cpp | 147 +- src/win/bsnes.h | 11 +- src/win/bsnes.ico | Bin 0 -> 4286 bytes src/win/bsnes.lnk | Bin 0 -> 1292 bytes src/win/bsnes.rc | 5 + src/win/bsnes.res | Bin 0 -> 244452 bytes src/win/bsnes_g2.lnk | Bin 469 -> 0 bytes src/win/cc.bat | 2 +- src/win/config.cpp | 30 +- src/win/dd_renderer.cpp | 2 +- src/win/dd_renderer16.cpp | 24 +- src/win/dd_renderer32.cpp | 24 +- src/win/lib.cpp | 6 +- src/win/rom.cpp | 34 +- src/win/snes_controller.bmp | Bin 0 -> 240054 bytes src/win/ui.cpp | 28 +- src/win/ui.h | 92 +- src/win/ui_about.cpp | 53 + src/win/ui_bp.cpp | 91 +- src/win/ui_console.cpp | 304 ++-- src/win/ui_inputconfig.cpp | 138 ++ src/win/ui_main.cpp | 45 +- src/win/ui_memory.cpp | 328 ++-- src/win/ui_window.cpp | 2 + src/win/uictl_editex.cpp | 75 + src/win/winmain.cpp | 35 +- src/win/winmain.h | 1 + 150 files changed, 16980 insertions(+), 10971 deletions(-) create mode 100644 bsnes.exe delete mode 100644 bsnes_g2.exe create mode 100644 src/apu/apu.cpp create mode 100644 src/apu/apu.h create mode 100644 src/apu/apuregs.h create mode 100644 src/apu/bapu/bapu.cpp create mode 100644 src/apu/bapu/bapu.h create mode 100644 src/apu/bapu/bapu_exec.cpp create mode 100644 src/apu/bapu/bapu_op.h create mode 100644 src/apu/bapu/bapu_op_fn.cpp create mode 100644 src/apu/bapu/bapu_op_misc.cpp create mode 100644 src/apu/bapu/bapu_op_mov.cpp create mode 100644 src/apu/bapu/bapu_op_pc.cpp create mode 100644 src/apu/bapu/bapu_op_read.cpp create mode 100644 src/apu/bapu/bapu_op_rmw.cpp create mode 100644 src/apu/bapu/bapu_optable.cpp create mode 100644 src/apu/bapu/bapugen.cpp create mode 100644 src/apu/bapu/bapugen.exe create mode 100644 src/apu/bapu/cc.bat create mode 100644 src/apu/bapu/clean.bat create mode 100644 src/apu/bapu/op_misc.b create mode 100644 src/apu/bapu/op_mov.b create mode 100644 src/apu/bapu/op_pc.b create mode 100644 src/apu/bapu/op_read.b create mode 100644 src/apu/bapu/op_rmw.b create mode 100644 src/apu/bapuskip/bapuskip.cpp create mode 100644 src/apu/bapuskip/bapuskip.h create mode 100644 src/apu/dapu.cpp create mode 100644 src/apu/iplrom.h delete mode 100644 src/clock/bclock/bclock.cpp delete mode 100644 src/clock/bclock/bclock.h delete mode 100644 src/clock/clock.cpp delete mode 100644 src/clock/clock.h create mode 100644 src/cpu/bcpu/bcpu_dma.cpp create mode 100644 src/cpu/bcpu/bcpu_op.h delete mode 100644 src/cpu/bcpu/bcpu_op_adc.cpp delete mode 100644 src/cpu/bcpu/bcpu_op_and.cpp delete mode 100644 src/cpu/bcpu/bcpu_op_cmp.cpp delete mode 100644 src/cpu/bcpu/bcpu_op_eor.cpp delete mode 100644 src/cpu/bcpu/bcpu_op_incdec.cpp delete mode 100644 src/cpu/bcpu/bcpu_op_lda.cpp delete mode 100644 src/cpu/bcpu/bcpu_op_ora.cpp create mode 100644 src/cpu/bcpu/bcpu_op_read.cpp create mode 100644 src/cpu/bcpu/bcpu_op_rmw.cpp delete mode 100644 src/cpu/bcpu/bcpu_op_sbc.cpp delete mode 100644 src/cpu/bcpu/bcpu_op_shift.cpp delete mode 100644 src/cpu/bcpu/bcpu_op_sta.cpp delete mode 100644 src/cpu/bcpu/bcpu_op_stack.cpp create mode 100644 src/cpu/bcpu/bcpu_op_write.cpp create mode 100644 src/cpu/bcpu/bcpu_opfn.cpp create mode 100644 src/cpu/bcpu/bcpu_optable.cpp create mode 100644 src/cpu/bcpu/bcpu_timing.cpp create mode 100644 src/cpu/bcpu/bcpu_timing.h create mode 100644 src/cpu/bcpu/bcpugen.cpp create mode 100644 src/cpu/bcpu/bcpugen.exe create mode 100644 src/cpu/bcpu/cc.bat create mode 100644 src/cpu/bcpu/clean.bat create mode 100644 src/cpu/bcpu/op_misc.b create mode 100644 src/cpu/bcpu/op_pc.b create mode 100644 src/cpu/bcpu/op_read.b create mode 100644 src/cpu/bcpu/op_rmw.b create mode 100644 src/cpu/bcpu/op_write.b create mode 100644 src/cpu/bcpu/srtc.cpp create mode 100644 src/cpu/bcpu/srtc.h create mode 100644 src/memory/bmemory/bcart_exhirom.cpp create mode 100644 src/memory/bmemory/bcart_exhirom.h create mode 100644 src/memory/bmemory/bcart_hirom.cpp create mode 100644 src/memory/bmemory/bcart_hirom.h create mode 100644 src/memory/bmemory/bcart_lorom.cpp create mode 100644 src/memory/bmemory/bcart_lorom.h delete mode 100644 src/ppu/bppu/bppu_old_render.cpp delete mode 100644 src/ppu/bppu/bppu_old_render.h delete mode 100644 src/ppu/bppu/bppu_old_render_cache.cpp delete mode 100644 src/ppu/bppu/bppu_old_render_main.cpp delete mode 100644 src/ppu/bppu/bppu_old_render_mode7.cpp delete mode 100644 src/ppu/bppu/bppu_old_render_windows.cpp create mode 100644 src/ppu/bppu/old_bppu_render_oam.cpp create mode 100644 src/sdl/Makefile create mode 100644 src/sdl/Makefile.win32 create mode 100644 src/sdl/bsnes.cpp create mode 100644 src/sdl/bsnes.h create mode 100644 src/sdl/bsnes_sdl.cfg create mode 100644 src/sdl/cc.bat create mode 100644 src/sdl/clean.bat create mode 100644 src/sdl/config.cpp create mode 100644 src/sdl/render.cpp create mode 100644 src/sdl/rom.cpp create mode 100644 src/sdl/sdlmain.cpp create mode 100644 src/sdl/sdlmain.h create mode 100644 src/sdl/sdlrun.bat create mode 100644 src/win/bsnes.ico create mode 100644 src/win/bsnes.lnk create mode 100644 src/win/bsnes.rc create mode 100644 src/win/bsnes.res delete mode 100644 src/win/bsnes_g2.lnk create mode 100644 src/win/snes_controller.bmp create mode 100644 src/win/ui_about.cpp create mode 100644 src/win/ui_inputconfig.cpp create mode 100644 src/win/uictl_editex.cpp diff --git a/bsnes.cfg b/bsnes.cfg index 897d2416..2e683772 100644 --- a/bsnes.cfg +++ b/bsnes.cfg @@ -1,5 +1,8 @@ #[bsnes v0.009 configuration file] +#[apu enable] +apu.enabled = true + #[video mode] # 0: 256x224w # 1: 512x448w @@ -34,3 +37,21 @@ gui.show_fps = true #[wait for vertical retrace] video.vblank = false + +#[joypad 1 configuration] +# Key numbers are standard windows VK_* keys. +# Unfortunately, I don't have a table of common +# key mappings to list here... use GUI joypad +# configuration utility to edit these. +input.joypad1.up = 0x26 +input.joypad1.down = 0x28 +input.joypad1.left = 0x25 +input.joypad1.right = 0x27 +input.joypad1.a = 0x58 +input.joypad1.b = 0x5a +input.joypad1.x = 0x53 +input.joypad1.y = 0x41 +input.joypad1.l = 0x44 +input.joypad1.r = 0x43 +input.joypad1.select = 0x10 +input.joypad1.start = 0x0d diff --git a/bsnes.exe b/bsnes.exe new file mode 100644 index 0000000000000000000000000000000000000000..520068391f76476f5531fd11258b8bcb01fcffdd GIT binary patch literal 614400 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 g^b27ign class bit { + public: + uint8 _b; + inline operator bool() { return (_b & B); } + inline bool operator = (bool i) { (i) ? _b |= B : _b &= ~B; return (_b & B); } + inline bool operator & (bool i) { if(i)_b &= ~B; return (_b & B); } + inline bool operator &= (bool i) { if(i)_b &= ~B; return (_b & B); } + inline bool operator | (bool i) { if(i)_b |= B; return (_b & B); } + inline bool operator |= (bool i) { if(i)_b |= B; return (_b & B); } + inline bool operator ^ (bool i) { if(i)_b ^= B; return (_b & B); } + inline bool operator ^= (bool i) { if(i)_b ^= B; return (_b & B); } + }; +public: + union { + uint8 _b; + bit<0x80> n; + bit<0x40> v; + bit<0x20> p; + bit<0x10> b; + bit<0x08> h; + bit<0x04> i; + bit<0x02> z; + bit<0x01> c; + }; + + APURegFlags() { _b = 0; } + inline operator uint8() { return _b; } + inline unsigned operator = (uint8 i) { _b = i; return _b; } + inline unsigned operator &= (uint8 i) { _b &= i; return _b; } + inline unsigned operator |= (uint8 i) { _b |= i; return _b; } + inline unsigned operator ^= (uint8 i) { _b ^= i; return _b; } +}; + +class APURegs { +public: +uint16 pc; +union { + uint16 ya; +//not endian-safe + struct { + uint8 a, y; + }; +}; +uint8 x, sp; +APURegFlags p; +}; diff --git a/src/apu/bapu/bapu.cpp b/src/apu/bapu/bapu.cpp new file mode 100644 index 00000000..0ff12828 --- /dev/null +++ b/src/apu/bapu/bapu.cpp @@ -0,0 +1,293 @@ +#include "../../base.h" + +#include "bapu_op_fn.cpp" +#include "bapu_op_mov.cpp" +#include "bapu_op_pc.cpp" +#include "bapu_op_read.cpp" +#include "bapu_op_rmw.cpp" +#include "bapu_op_misc.cpp" + +#include "bapu_exec.cpp" + +uint8 bAPU::spcram_read(uint16 addr) { +uint8 r; + if(addr >= 0x00f0 && addr <= 0x00ff) { + switch(addr) { + case 0xf0: //TEST -- operation unknown, supposedly returns 0x00 + r = 0x00; + break; + case 0xf1: //CONTROL -- write-only register, always returns 0x00 + r = 0x00; + break; + case 0xf2: //DSPADDR + r = status.dsp_addr; + break; + case 0xf3: //DSPDATA + //0x80-0xff is a read-only mirror of 0x00-0x7f + r = dsp_regs[status.dsp_addr & 0x7f]; + break; + case 0xf4: //CPUIO0 + case 0xf5: //CPUIO1 + case 0xf6: //CPUIO2 + case 0xf7: //CPUIO3 + r = cpu->port_read(addr & 3); + break; + case 0xf8: //??? + case 0xf9: //??? -- Mapped to SPCRAM + r = spcram[addr]; + break; + case 0xfa: //T0TARGET + case 0xfb: //T1TARGET + case 0xfc: //T2TARGET -- write-only registers, always return 0x00 + r = 0x00; + break; + case 0xfd: //T0OUT -- 4-bit counter value + r = t0.stage3_ticks & 15; + t0.stage3_ticks = 0; + break; + case 0xfe: //T1OUT -- 4-bit counter value + r = t1.stage3_ticks & 15; + t1.stage3_ticks = 0; + break; + case 0xff: //T2OUT -- 4-bit counter value + r = t2.stage3_ticks & 15; + t2.stage3_ticks = 0; + break; + } + } else if(addr < 0xffc0) { + r = spcram[addr]; + } else { + if(status.iplrom_enabled == true) { + r = iplrom[addr & 0x3f]; + } else { + r = spcram[addr]; + } + } + snes->notify(SNES::SPCRAM_READ, addr, r); + return r; +} + +void bAPU::spcram_write(uint16 addr, uint8 value) { + if(addr >= 0x00f0 && addr <= 0x00ff) { + switch(addr) { + case 0xf0: //TEST -- operation unknown + break; + case 0xf1: //CONTROL + status.iplrom_enabled = !!(value & 0x80); + + //one-time clearing of APU port read registers, + //emulated by simulating CPU writes of 0x00 + if(value & 0x20) { + cpu->port_write(2, 0x00); + cpu->port_write(3, 0x00); + } + if(value & 0x10) { + cpu->port_write(0, 0x00); + cpu->port_write(1, 0x00); + } + + //0->1 transistion resets timers + if(t2.enabled == false && (value & 0x04)) { + t2.stage2_ticks = 0; + t2.stage3_ticks = 0; + } + t2.enabled = !!(value & 0x04); + + if(t1.enabled == false && (value & 0x02)) { + t1.stage2_ticks = 0; + t1.stage3_ticks = 0; + } + t1.enabled = !!(value & 0x02); + + if(t0.enabled == false && (value & 0x01)) { + t0.stage2_ticks = 0; + t0.stage3_ticks = 0; + } + t0.enabled = !!(value & 0x01); + break; + case 0xf2: //DSPADDR + status.dsp_addr = value; + break; + case 0xf3: //DSPDATA + //0x80-0xff is a read-only mirror of 0x00-0x7f + if(status.dsp_addr < 0x80) { + dsp_regs[status.dsp_addr & 0x7f] = value; + } + break; + case 0xf4: //CPUIO0 + case 0xf5: //CPUIO1 + case 0xf6: //CPUIO2 + case 0xf7: //CPUIO3 + port_write(addr & 3, value); + break; + case 0xf8: //??? + case 0xf9: //??? - Mapped to SPCRAM + spcram[addr] = value; + break; + case 0xfa: //T0TARGET + t0.target = value; + break; + case 0xfb: //T1TARGET + t1.target = value; + break; + case 0xfc: //T2TARGET + t2.target = value; + break; + case 0xfd: //T0OUT + case 0xfe: //T1OUT + case 0xff: //T2OUT -- read-only registers + break; + } + } else { + //writes to $ffc0-$ffff always go to spcram, + //even if the iplrom is enabled. + spcram[addr] = value; + } + snes->notify(SNES::SPCRAM_WRITE, addr, value); +} + +uint8 bAPU::port_read(uint8 port) { + return spcram[0xf4 + (port & 3)]; +} + +void bAPU::port_write(uint8 port, uint8 value) { + spcram[0xf4 + (port & 0x03)] = value; +} + +void bAPU::add_cycles(int cycles) { + status.cycles_executed += cycles; + + t0.add_cycles(cycles); + t1.add_cycles(cycles); + t2.add_cycles(cycles); +} + +uint32 bAPU::cycles_executed() { +uint32 r = status.cycles_executed; + status.cycles_executed = 0; + return (r << 4) + (r << 3); +} + +uint8 bAPU::op_read() { +uint8 r; + r = spcram_read(regs.pc); + regs.pc++; + return r; +} + +uint8 bAPU::op_read(uint8 mode, uint16 addr) { +uint8 r; + switch(mode) { + case OPMODE_ADDR: + r = spcram_read(addr); + break; + case OPMODE_DP: + r = spcram_read(((regs.p.p)?0x100:0x000) + (addr & 0xff)); + break; + } + return r; +} + +void bAPU::op_write(uint8 mode, uint16 addr, uint8 value) { + switch(mode) { + case OPMODE_ADDR: + spcram_write(addr, value); + break; + case OPMODE_DP: + spcram_write(((regs.p.p)?0x100:0x000) + (addr & 0xff), value); + break; + } +} + +uint8 bAPU::stack_read() { + regs.sp++; + return spcram_read(0x0100 | regs.sp); +} + +void bAPU::stack_write(uint8 value) { + spcram_write(0x0100 | regs.sp, value); + regs.sp--; +} + +void bAPU::run() { + exec_cycle(); +} + +void bAPU::power() { + memset(spcram, 0x00, 65536); + reset(); +} + +void bAPU::reset() { + regs.pc = 0xffc0; + regs.a = 0x00; + regs.x = 0x00; + regs.y = 0x00; + regs.sp = 0xef; + regs.p = 0x02; + + status.cycle_pos = 0; + +//$f1 + status.iplrom_enabled = true; + + t0.enabled = false; + t1.enabled = false; + t2.enabled = false; + + t0.stage1_ticks = 0; + t1.stage1_ticks = 0; + t2.stage1_ticks = 0; + + t0.stage2_ticks = 0; + t1.stage2_ticks = 0; + t2.stage2_ticks = 0; + + t0.stage3_ticks = 0; + t1.stage3_ticks = 0; + t2.stage3_ticks = 0; + + memset(dsp_regs, 0, 128); +} + +bAPU::bAPU() { + init_op_table(); + + spcram = (uint8*)malloc(65536); + memcpy(iplrom, spc700_iplrom, 64); + + t0.cycle_frequency = 128; //1.024mhz / 8khz = 128 + t1.cycle_frequency = 128; //1.024mhz / 8khz = 128 + t2.cycle_frequency = 16; //1.024mhz / 64khz = 16 + +//targets not initialized/changed upon reset + t0.target = 0; + t1.target = 0; + t2.target = 0; +} + +bAPU::~bAPU() { + if(spcram)free(spcram); +} + +//cycles should never be greater than 12. since the minimum +//cycle_frequency value is 16, we don't have to worry about +//two ticks occuring in one call to this function. +void bAPUTimer::add_cycles(int cycles) { +//stage 1 increment + stage1_ticks += cycles; + if(stage1_ticks < cycle_frequency)return; + + stage1_ticks -= cycle_frequency; + if(enabled == false)return; + +//stage 2 increment + stage2_ticks++; + + if(stage2_ticks != target)return; + +//stage 3 increment + stage2_ticks = 0; + stage3_ticks++; + stage3_ticks &= 15; +} diff --git a/src/apu/bapu/bapu.h b/src/apu/bapu/bapu.h new file mode 100644 index 00000000..a603c547 --- /dev/null +++ b/src/apu/bapu/bapu.h @@ -0,0 +1,79 @@ +class bAPU; + +class bAPUTimer { +public: +uint8 cycle_frequency, target; +uint8 stage1_ticks, stage2_ticks, stage3_ticks; +bool enabled; + inline void add_cycles(int cycles); +}; + +class bAPU : public APU { +private: +typedef void (bAPU::*op)(); +op optbl[256]; + +public: +uint16 dp, sp, rd, wr, bit, ya; + +struct { + uint8 cycle_pos, opcode; + uint32 cycles_executed; + +//$f1 + bool iplrom_enabled; + +//$f2 + uint8 dsp_addr; +}status; + +bAPUTimer t0, t1, t2; + +uint8 *spcram, iplrom[64], dsp_regs[128]; + inline uint8 spcram_read (uint16 addr); + inline void spcram_write(uint16 addr, uint8 value); + inline uint8 port_read (uint8 port); + inline void port_write(uint8 port, uint8 value); + + inline void run(); + inline uint32 cycles_executed(); + inline void power(); + inline void reset(); + + inline void add_cycles(int cycles); + +enum { + OPMODE_ADDR = 0, + OPMODE_DP = 1 +}; + inline uint8 op_read(); + inline uint8 op_read (uint8 mode, uint16 addr); + inline void op_write(uint8 mode, uint16 addr, uint8 value); + inline uint8 stack_read(); + inline void stack_write(uint8 value); + + inline void exec_cycle(); + inline void init_op_table(); + + inline uint8 op_adc (uint8 x, uint8 y); + inline uint16 op_addw(uint16 x, uint16 y); + inline uint8 op_and (uint8 x, uint8 y); + inline uint8 op_cmp (uint8 x, uint8 y); + inline uint16 op_cmpw(uint16 x, uint16 y); + inline uint8 op_eor (uint8 x, uint8 y); + inline uint8 op_inc (uint8 x); + inline uint16 op_incw(uint16 x); + inline uint8 op_dec (uint8 x); + inline uint16 op_decw(uint16 x); + inline uint8 op_or (uint8 x, uint8 y); + inline uint8 op_sbc (uint8 x, uint8 y); + inline uint16 op_subw(uint16 x, uint16 y); + inline uint8 op_asl (uint8 x); + inline uint8 op_lsr (uint8 x); + inline uint8 op_rol (uint8 x); + inline uint8 op_ror (uint8 x); +#include "bapu_op.h" + + bAPU(); + ~bAPU(); +}; diff --git a/src/apu/bapu/bapu_exec.cpp b/src/apu/bapu/bapu_exec.cpp new file mode 100644 index 00000000..279d5fcb --- /dev/null +++ b/src/apu/bapu/bapu_exec.cpp @@ -0,0 +1,20 @@ +void bAPU::exec_cycle() { +uint8 op; + if(status.cycle_pos == 0) { + op = spcram_read(regs.pc); + snes->notify(SNES::APU_EXEC_OPCODE_BEGIN); + status.opcode = op_read(); + status.cycle_pos = 1; + add_cycles(1); + } else { + (this->*optbl[status.opcode])(); + add_cycles(1); + if(status.cycle_pos == 0) { + snes->notify(SNES::APU_EXEC_OPCODE_END); + } + } +} + +void bAPU::init_op_table() { +#include "bapu_optable.cpp" +} diff --git a/src/apu/bapu/bapu_op.h b/src/apu/bapu/bapu_op.h new file mode 100644 index 00000000..da2b2856 --- /dev/null +++ b/src/apu/bapu/bapu_op.h @@ -0,0 +1,256 @@ +void op_mov_a_x(); +void op_mov_a_y(); +void op_mov_x_a(); +void op_mov_y_a(); +void op_mov_x_sp(); +void op_mov_sp_x(); +void op_mov_a_const(); +void op_mov_x_const(); +void op_mov_y_const(); +void op_mov_a_ix(); +void op_mov_a_ixinc(); +void op_mov_a_dp(); +void op_mov_x_dp(); +void op_mov_y_dp(); +void op_mov_a_dpx(); +void op_mov_x_dpy(); +void op_mov_y_dpx(); +void op_mov_a_addr(); +void op_mov_x_addr(); +void op_mov_y_addr(); +void op_mov_a_addrx(); +void op_mov_a_addry(); +void op_mov_a_idpx(); +void op_mov_a_idpy(); +void op_mov_dp_dp(); +void op_mov_dp_const(); +void op_mov_ix_a(); +void op_mov_ixinc_a(); +void op_mov_dp_a(); +void op_mov_dp_x(); +void op_mov_dp_y(); +void op_mov_dpx_a(); +void op_mov_dpy_x(); +void op_mov_dpx_y(); +void op_mov_addr_a(); +void op_mov_addr_x(); +void op_mov_addr_y(); +void op_mov_addrx_a(); +void op_mov_addry_a(); +void op_mov_idpx_a(); +void op_mov_idpy_a(); +void op_movw_ya_dp(); +void op_movw_dp_ya(); +void op_mov1_c_bit(); +void op_mov1_bit_c(); +void op_bra(); +void op_beq(); +void op_bne(); +void op_bcs(); +void op_bcc(); +void op_bvs(); +void op_bvc(); +void op_bmi(); +void op_bpl(); +void op_bbs0(); +void op_bbc0(); +void op_bbs1(); +void op_bbc1(); +void op_bbs2(); +void op_bbc2(); +void op_bbs3(); +void op_bbc3(); +void op_bbs4(); +void op_bbc4(); +void op_bbs5(); +void op_bbc5(); +void op_bbs6(); +void op_bbc6(); +void op_bbs7(); +void op_bbc7(); +void op_cbne_dp(); +void op_cbne_dpx(); +void op_dbnz_dp(); +void op_dbnz_y(); +void op_jmp_addr(); +void op_jmp_iaddrx(); +void op_call(); +void op_pcall(); +void op_tcall_0(); +void op_tcall_1(); +void op_tcall_2(); +void op_tcall_3(); +void op_tcall_4(); +void op_tcall_5(); +void op_tcall_6(); +void op_tcall_7(); +void op_tcall_8(); +void op_tcall_9(); +void op_tcall_10(); +void op_tcall_11(); +void op_tcall_12(); +void op_tcall_13(); +void op_tcall_14(); +void op_tcall_15(); +void op_brk(); +void op_ret(); +void op_reti(); +void op_adc_a_const(); +void op_and_a_const(); +void op_cmp_a_const(); +void op_cmp_x_const(); +void op_cmp_y_const(); +void op_eor_a_const(); +void op_or_a_const(); +void op_sbc_a_const(); +void op_adc_a_ix(); +void op_and_a_ix(); +void op_cmp_a_ix(); +void op_eor_a_ix(); +void op_or_a_ix(); +void op_sbc_a_ix(); +void op_adc_a_dp(); +void op_and_a_dp(); +void op_cmp_a_dp(); +void op_cmp_x_dp(); +void op_cmp_y_dp(); +void op_eor_a_dp(); +void op_or_a_dp(); +void op_sbc_a_dp(); +void op_adc_a_dpx(); +void op_and_a_dpx(); +void op_cmp_a_dpx(); +void op_eor_a_dpx(); +void op_or_a_dpx(); +void op_sbc_a_dpx(); +void op_adc_a_addr(); +void op_and_a_addr(); +void op_cmp_a_addr(); +void op_cmp_x_addr(); +void op_cmp_y_addr(); +void op_eor_a_addr(); +void op_or_a_addr(); +void op_sbc_a_addr(); +void op_adc_a_addrx(); +void op_adc_a_addry(); +void op_and_a_addrx(); +void op_and_a_addry(); +void op_cmp_a_addrx(); +void op_cmp_a_addry(); +void op_eor_a_addrx(); +void op_eor_a_addry(); +void op_or_a_addrx(); +void op_or_a_addry(); +void op_sbc_a_addrx(); +void op_sbc_a_addry(); +void op_adc_a_idpx(); +void op_and_a_idpx(); +void op_cmp_a_idpx(); +void op_eor_a_idpx(); +void op_or_a_idpx(); +void op_sbc_a_idpx(); +void op_adc_a_idpy(); +void op_and_a_idpy(); +void op_cmp_a_idpy(); +void op_eor_a_idpy(); +void op_or_a_idpy(); +void op_sbc_a_idpy(); +void op_adc_ix_iy(); +void op_and_ix_iy(); +void op_cmp_ix_iy(); +void op_eor_ix_iy(); +void op_or_ix_iy(); +void op_sbc_ix_iy(); +void op_adc_dp_dp(); +void op_and_dp_dp(); +void op_cmp_dp_dp(); +void op_eor_dp_dp(); +void op_or_dp_dp(); +void op_sbc_dp_dp(); +void op_adc_dp_const(); +void op_and_dp_const(); +void op_cmp_dp_const(); +void op_eor_dp_const(); +void op_or_dp_const(); +void op_sbc_dp_const(); +void op_addw_ya_dp(); +void op_cmpw_ya_dp(); +void op_subw_ya_dp(); +void op_and1_bit(); +void op_and1_notbit(); +void op_eor1_bit(); +void op_not1_bit(); +void op_or1_bit(); +void op_or1_notbit(); +void op_inc_a(); +void op_inc_x(); +void op_inc_y(); +void op_dec_a(); +void op_dec_x(); +void op_dec_y(); +void op_asl_a(); +void op_lsr_a(); +void op_rol_a(); +void op_ror_a(); +void op_inc_dp(); +void op_dec_dp(); +void op_asl_dp(); +void op_lsr_dp(); +void op_rol_dp(); +void op_ror_dp(); +void op_inc_dpx(); +void op_dec_dpx(); +void op_asl_dpx(); +void op_lsr_dpx(); +void op_rol_dpx(); +void op_ror_dpx(); +void op_inc_addr(); +void op_dec_addr(); +void op_asl_addr(); +void op_lsr_addr(); +void op_rol_addr(); +void op_ror_addr(); +void op_incw_dp(); +void op_decw_dp(); +void op_nop(); +void op_sleep(); +void op_stop(); +void op_xcn(); +void op_daa(); +void op_das(); +void op_clrc(); +void op_clrp(); +void op_setc(); +void op_setp(); +void op_clrv(); +void op_notc(); +void op_ei(); +void op_di(); +void op_set0_dp(); +void op_clr0_dp(); +void op_set1_dp(); +void op_clr1_dp(); +void op_set2_dp(); +void op_clr2_dp(); +void op_set3_dp(); +void op_clr3_dp(); +void op_set4_dp(); +void op_clr4_dp(); +void op_set5_dp(); +void op_clr5_dp(); +void op_set6_dp(); +void op_clr6_dp(); +void op_set7_dp(); +void op_clr7_dp(); +void op_tset_addr_a(); +void op_tclr_addr_a(); +void op_push_a(); +void op_push_x(); +void op_push_y(); +void op_push_p(); +void op_pop_a(); +void op_pop_x(); +void op_pop_y(); +void op_pop_p(); +void op_mul_ya(); +void op_div_ya_x(); diff --git a/src/apu/bapu/bapu_op_fn.cpp b/src/apu/bapu/bapu_op_fn.cpp new file mode 100644 index 00000000..4819c448 --- /dev/null +++ b/src/apu/bapu/bapu_op_fn.cpp @@ -0,0 +1,140 @@ +uint8 bAPU::op_adc(uint8 x, uint8 y) { +int16 r = x + y + regs.p.c; + regs.p.n = !!(r & 0x80); + regs.p.v = !!(~(x ^ y) & (y ^ (uint8)r) & 0x80); + regs.p.h = !!((x ^ y ^ (uint8)r) & 0x10); + regs.p.z = ((uint8)r == 0); + regs.p.c = (r > 0xff); + return r; +} + +uint16 bAPU::op_addw(uint16 x, uint16 y) { +int32 r = x + y; + regs.p.n = !!(r & 0x8000); + regs.p.v = !!(~(x ^ y) & (y ^ (uint16)r) & 0x8000); + regs.p.h = !!((x ^ y ^ (uint16)r) & 0x10); + regs.p.z = ((uint16)r == 0); + regs.p.c = (r > 0xffff); + return r; +} + +uint8 bAPU::op_and(uint8 x, uint8 y) { + x &= y; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} + +uint8 bAPU::op_cmp(uint8 x, uint8 y) { +int16 r = x - y; + regs.p.n = !!(r & 0x80); + regs.p.z = ((uint8)r == 0); + regs.p.c = (r >= 0); + return x; +} + +uint16 bAPU::op_cmpw(uint16 x, uint16 y) { +int32 r = x - y; + regs.p.n = !!(r & 0x8000); + regs.p.z = ((uint16)r == 0); + regs.p.c = (r >= 0); + return x; +} + +uint8 bAPU::op_eor(uint8 x, uint8 y) { + x ^= y; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} + +uint8 bAPU::op_or(uint8 x, uint8 y) { + x |= y; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} + +uint8 bAPU::op_sbc(uint8 x, uint8 y) { +int16 r = x - y - !regs.p.c; + regs.p.n = !!(r & 0x80); + regs.p.v = !!((x ^ y) & (x ^ (uint8)r) & 0x80); + regs.p.h = !((x ^ y ^ (uint8)r) & 0x10); + regs.p.z = ((uint8)r == 0); + regs.p.c = (r >= 0); + return r; +} + +uint16 bAPU::op_subw(uint16 x, uint16 y) { +int32 r = x - y; + regs.p.n = !!(r & 0x8000); + regs.p.v = !!((x ^ y) & (x ^ (uint16)r) & 0x8000); + regs.p.h = !((x ^ y ^ (uint16)r) & 0x10); + regs.p.z = ((uint16)r == 0); + regs.p.c = (r >= 0); + return r; +} + +uint8 bAPU::op_inc(uint8 x) { + x++; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} + +uint16 bAPU::op_incw(uint16 x) { + x++; + regs.p.n = !!(x & 0x8000); + regs.p.z = (x == 0); + return x; +} + +uint8 bAPU::op_dec(uint8 x) { + x--; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} + +uint16 bAPU::op_decw(uint16 x) { + x--; + regs.p.n = !!(x & 0x8000); + regs.p.z = (x == 0); + return x; +} + +uint8 bAPU::op_asl(uint8 x) { + regs.p.c = !!(x & 0x80); + x <<= 1; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} + +uint8 bAPU::op_lsr(uint8 x) { + regs.p.c = !!(x & 0x01); + x >>= 1; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} + +uint8 bAPU::op_rol(uint8 x) { +uint8 c = regs.p.c; + regs.p.c = !!(x & 0x80); + x <<= 1; + x |= c; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} + +uint8 bAPU::op_ror(uint8 x) { +uint8 c = (regs.p.c)?0x80:0x00; + regs.p.c = !!(x & 0x01); + x >>= 1; + x |= c; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} diff --git a/src/apu/bapu/bapu_op_misc.cpp b/src/apu/bapu/bapu_op_misc.cpp new file mode 100644 index 00000000..43978f61 --- /dev/null +++ b/src/apu/bapu/bapu_op_misc.cpp @@ -0,0 +1,643 @@ +void bAPU::op_nop() { + switch(status.cycle_pos++) { + case 1: + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_sleep() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + regs.pc--; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_stop() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + regs.pc--; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_xcn() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + regs.a = (regs.a >> 4) | (regs.a << 4); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_daa() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + 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); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_das() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + 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); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_clrc() { + switch(status.cycle_pos++) { + case 1: + regs.p.c = 0; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_clrp() { + switch(status.cycle_pos++) { + case 1: + regs.p.p = 0; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_setc() { + switch(status.cycle_pos++) { + case 1: + regs.p.c = 1; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_setp() { + switch(status.cycle_pos++) { + case 1: + regs.p.p = 1; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_clrv() { + switch(status.cycle_pos++) { + case 1: + regs.p.v = 0; + regs.p.h = 0; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_notc() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + regs.p.c ^= 1; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_ei() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + regs.p.i = 1; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_di() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + regs.p.i = 0; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_set0_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd |= 0x01; + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_clr0_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd &= ~0x01; + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_set1_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd |= 0x02; + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_clr1_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd &= ~0x02; + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_set2_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd |= 0x04; + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_clr2_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd &= ~0x04; + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_set3_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd |= 0x08; + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_clr3_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd &= ~0x08; + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_set4_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd |= 0x10; + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_clr4_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd &= ~0x10; + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_set5_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd |= 0x20; + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_clr5_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd &= ~0x20; + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_set6_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd |= 0x40; + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_clr6_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd &= ~0x40; + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_set7_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd |= 0x80; + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_clr7_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd &= ~0x80; + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tset_addr_a() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + rd = op_read(OPMODE_ADDR, dp); + break; + case 4: + regs.p.n = !!((rd & regs.a) & 0x80); + regs.p.z = ((rd & regs.a) == 0); + rd |= regs.a; + break; + case 5: + op_write(OPMODE_ADDR, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tclr_addr_a() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + rd = op_read(OPMODE_ADDR, dp); + break; + case 4: + regs.p.n = !!((rd & regs.a) & 0x80); + regs.p.z = ((rd & regs.a) == 0); + rd &=~ regs.a; + break; + case 5: + op_write(OPMODE_ADDR, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_push_a() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + break; + case 3: + stack_write(regs.a); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_push_x() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + break; + case 3: + stack_write(regs.x); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_push_y() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + break; + case 3: + stack_write(regs.y); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_push_p() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + break; + case 3: + stack_write(regs.p); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_pop_a() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + break; + case 3: + regs.a = stack_read(); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_pop_x() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + break; + case 3: + regs.x = stack_read(); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_pop_y() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + break; + case 3: + regs.y = stack_read(); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_pop_p() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + break; + case 3: + regs.p = stack_read(); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mul_ya() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + 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); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_div_ya_x() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + 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 SPC700 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); + status.cycle_pos = 0; + break; + } +} + diff --git a/src/apu/bapu/bapu_op_mov.cpp b/src/apu/bapu/bapu_op_mov.cpp new file mode 100644 index 00000000..c97d8132 --- /dev/null +++ b/src/apu/bapu/bapu_op_mov.cpp @@ -0,0 +1,710 @@ +void bAPU::op_mov_a_x() { + switch(status.cycle_pos++) { + case 1: + regs.a = regs.x; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_a_y() { + switch(status.cycle_pos++) { + case 1: + regs.a = regs.y; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_x_a() { + switch(status.cycle_pos++) { + case 1: + regs.x = regs.a; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_y_a() { + switch(status.cycle_pos++) { + case 1: + regs.y = regs.a; + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_x_sp() { + switch(status.cycle_pos++) { + case 1: + regs.x = regs.sp; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_sp_x() { + switch(status.cycle_pos++) { + case 1: + regs.sp = regs.x; + regs.p.n = !!(regs.sp & 0x80); + regs.p.z = (regs.sp == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_a_const() { + switch(status.cycle_pos++) { + case 1: + regs.a = op_read(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_x_const() { + switch(status.cycle_pos++) { + case 1: + regs.x = op_read(); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_y_const() { + switch(status.cycle_pos++) { + case 1: + regs.y = op_read(); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_a_ix() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + regs.a = op_read(OPMODE_DP, regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_a_ixinc() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + break; + case 3: + regs.a = op_read(OPMODE_DP, regs.x++); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_a_dp() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + regs.a = op_read(OPMODE_DP, sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_x_dp() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + regs.x = op_read(OPMODE_DP, sp); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_y_dp() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + regs.y = op_read(OPMODE_DP, sp); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_a_dpx() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + break; + case 3: + regs.a = op_read(OPMODE_DP, sp + regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_x_dpy() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + break; + case 3: + regs.x = op_read(OPMODE_DP, sp + regs.y); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_y_dpx() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + break; + case 3: + regs.y = op_read(OPMODE_DP, sp + regs.x); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_a_addr() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + sp |= op_read() << 8; + break; + case 3: + regs.a = op_read(OPMODE_ADDR, sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_x_addr() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + sp |= op_read() << 8; + break; + case 3: + regs.x = op_read(OPMODE_ADDR, sp); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_y_addr() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + sp |= op_read() << 8; + break; + case 3: + regs.y = op_read(OPMODE_ADDR, sp); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_a_addrx() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + sp |= op_read() << 8; + break; + case 3: + break; + case 4: + regs.a = op_read(OPMODE_ADDR, sp + regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_a_addry() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + sp |= op_read() << 8; + break; + case 3: + break; + case 4: + regs.a = op_read(OPMODE_ADDR, sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_a_idpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read() + regs.x; + break; + case 2: + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + sp |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 5: + regs.a = op_read(OPMODE_ADDR, sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_a_idpy() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + sp |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 5: + regs.a = op_read(OPMODE_ADDR, sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_dp_dp() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + dp = op_read(); + break; + case 3: + rd = op_read(OPMODE_DP, sp); + break; + case 4: + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_dp_const() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + break; + case 2: + dp = op_read(); + break; + case 3: + break; + case 4: + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_ix_a() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + break; + case 3: + op_write(OPMODE_DP, regs.x, regs.a); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_ixinc_a() { + switch(status.cycle_pos++) { + case 1: + break; + case 2: + break; + case 3: + op_write(OPMODE_DP, regs.x++, regs.a); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_dp_a() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + op_write(OPMODE_DP, dp, regs.a); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_dp_x() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + op_write(OPMODE_DP, dp, regs.x); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_dp_y() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + op_write(OPMODE_DP, dp, regs.y); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_dpx_a() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + break; + case 4: + op_write(OPMODE_DP, dp + regs.x, regs.a); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_dpy_x() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + break; + case 4: + op_write(OPMODE_DP, dp + regs.y, regs.x); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_dpx_y() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + break; + case 4: + op_write(OPMODE_DP, dp + regs.x, regs.y); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_addr_a() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + break; + case 4: + op_write(OPMODE_ADDR, dp, regs.a); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_addr_x() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + break; + case 4: + op_write(OPMODE_ADDR, dp, regs.x); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_addr_y() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + break; + case 4: + op_write(OPMODE_ADDR, dp, regs.y); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_addrx_a() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + break; + case 4: + break; + case 5: + op_write(OPMODE_ADDR, dp + regs.x, regs.a); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_addry_a() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + break; + case 4: + break; + case 5: + op_write(OPMODE_ADDR, dp + regs.y, regs.a); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_idpx_a() { + switch(status.cycle_pos++) { + case 1: + sp = op_read() + regs.x; + break; + case 2: + break; + case 3: + dp = op_read(OPMODE_DP, sp); + break; + case 4: + dp |= op_read(OPMODE_DP, sp + 1) << 8; + break; + case 5: + break; + case 6: + op_write(OPMODE_ADDR, dp, regs.a); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov_idpy_a() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + break; + case 3: + dp = op_read(OPMODE_DP, sp); + break; + case 4: + dp |= op_read(OPMODE_DP, sp + 1) << 8; + break; + case 5: + break; + case 6: + op_write(OPMODE_ADDR, dp + regs.y, regs.a); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_movw_ya_dp() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + break; + case 3: + regs.a = op_read(OPMODE_DP, sp); + break; + case 4: + regs.y = op_read(OPMODE_DP, sp + 1); + regs.p.n = !!(regs.ya & 0x8000); + regs.p.z = (regs.ya == 0); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_movw_dp_ya() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + op_write(OPMODE_DP, dp, regs.a); + break; + case 4: + op_write(OPMODE_DP, dp + 1, regs.y); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov1_c_bit() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + sp |= op_read() << 8; + break; + case 3: + bit = sp >> 13; + sp &= 0x1fff; + rd = op_read(OPMODE_ADDR, sp); + regs.p.c = !!(rd & (1 << bit)); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_mov1_bit_c() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_read(OPMODE_ADDR, dp); + if(regs.p.c)rd |= (1 << bit); + else rd &= ~(1 << bit); + break; + case 4: + op_write(OPMODE_ADDR, dp, rd); + status.cycle_pos = 0; + break; + } +} + diff --git a/src/apu/bapu/bapu_op_pc.cpp b/src/apu/bapu/bapu_op_pc.cpp new file mode 100644 index 00000000..98f4e788 --- /dev/null +++ b/src/apu/bapu/bapu_op_pc.cpp @@ -0,0 +1,1155 @@ +void bAPU::op_bra() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + if(0)status.cycle_pos = 0; + break; + case 2: + break; + case 3: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_beq() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + if(!regs.p.z)status.cycle_pos = 0; + break; + case 2: + break; + case 3: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bne() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + if(regs.p.z)status.cycle_pos = 0; + break; + case 2: + break; + case 3: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bcs() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + if(!regs.p.c)status.cycle_pos = 0; + break; + case 2: + break; + case 3: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bcc() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + if(regs.p.c)status.cycle_pos = 0; + break; + case 2: + break; + case 3: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bvs() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + if(!regs.p.v)status.cycle_pos = 0; + break; + case 2: + break; + case 3: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bvc() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + if(regs.p.v)status.cycle_pos = 0; + break; + case 2: + break; + case 3: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bmi() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + if(!regs.p.n)status.cycle_pos = 0; + break; + case 2: + break; + case 3: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bpl() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + if(regs.p.n)status.cycle_pos = 0; + break; + case 2: + break; + case 3: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bbs0() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + if((sp & 0x01) != 0x01)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bbc0() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + if((sp & 0x01) == 0x01)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bbs1() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + if((sp & 0x02) != 0x02)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bbc1() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + if((sp & 0x02) == 0x02)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bbs2() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + if((sp & 0x04) != 0x04)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bbc2() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + if((sp & 0x04) == 0x04)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bbs3() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + if((sp & 0x08) != 0x08)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bbc3() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + if((sp & 0x08) == 0x08)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bbs4() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + if((sp & 0x10) != 0x10)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bbc4() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + if((sp & 0x10) == 0x10)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bbs5() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + if((sp & 0x20) != 0x20)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bbc5() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + if((sp & 0x20) == 0x20)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bbs6() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + if((sp & 0x40) != 0x40)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bbc6() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + if((sp & 0x40) == 0x40)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bbs7() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + if((sp & 0x80) != 0x80)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_bbc7() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + if((sp & 0x80) == 0x80)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cbne_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp + 0); + break; + case 4: + if(regs.a == sp)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cbne_dpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + sp = op_read(OPMODE_DP, dp + regs.x); + break; + case 4: + if(regs.a == sp)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_dbnz_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(); + break; + case 3: + wr = op_read(OPMODE_DP, dp); + break; + case 4: + wr--; + op_write(OPMODE_DP, dp, wr); + if(wr == 0x00)status.cycle_pos = 0; + break; + case 5: + break; + case 6: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_dbnz_y() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + break; + case 2: + regs.y--; + break; + case 3: + if(regs.y == 0x00)status.cycle_pos = 0; + break; + case 4: + break; + case 5: + regs.pc += (int8)rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_jmp_addr() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + break; + case 2: + rd |= op_read() << 8; + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_jmp_iaddrx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + dp += regs.x; + break; + case 4: + rd = op_read(OPMODE_ADDR, dp); + break; + case 5: + rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_call() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + break; + case 2: + rd |= op_read() << 8; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + stack_write(regs.pc >> 8); + break; + case 7: + stack_write(regs.pc); + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_pcall() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + break; + case 2: + break; + case 3: + break; + case 4: + stack_write(regs.pc >> 8); + break; + case 5: + stack_write(regs.pc); + regs.pc = 0xff00 | rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tcall_0() { + switch(status.cycle_pos++) { + case 1: + dp = 0xffde - (0 << 1); + rd = op_read(OPMODE_ADDR, dp); + break; + case 2: + rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + stack_write(regs.pc >> 8); + break; + case 7: + stack_write(regs.pc); + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tcall_1() { + switch(status.cycle_pos++) { + case 1: + dp = 0xffde - (1 << 1); + rd = op_read(OPMODE_ADDR, dp); + break; + case 2: + rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + stack_write(regs.pc >> 8); + break; + case 7: + stack_write(regs.pc); + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tcall_2() { + switch(status.cycle_pos++) { + case 1: + dp = 0xffde - (2 << 1); + rd = op_read(OPMODE_ADDR, dp); + break; + case 2: + rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + stack_write(regs.pc >> 8); + break; + case 7: + stack_write(regs.pc); + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tcall_3() { + switch(status.cycle_pos++) { + case 1: + dp = 0xffde - (3 << 1); + rd = op_read(OPMODE_ADDR, dp); + break; + case 2: + rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + stack_write(regs.pc >> 8); + break; + case 7: + stack_write(regs.pc); + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tcall_4() { + switch(status.cycle_pos++) { + case 1: + dp = 0xffde - (4 << 1); + rd = op_read(OPMODE_ADDR, dp); + break; + case 2: + rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + stack_write(regs.pc >> 8); + break; + case 7: + stack_write(regs.pc); + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tcall_5() { + switch(status.cycle_pos++) { + case 1: + dp = 0xffde - (5 << 1); + rd = op_read(OPMODE_ADDR, dp); + break; + case 2: + rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + stack_write(regs.pc >> 8); + break; + case 7: + stack_write(regs.pc); + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tcall_6() { + switch(status.cycle_pos++) { + case 1: + dp = 0xffde - (6 << 1); + rd = op_read(OPMODE_ADDR, dp); + break; + case 2: + rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + stack_write(regs.pc >> 8); + break; + case 7: + stack_write(regs.pc); + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tcall_7() { + switch(status.cycle_pos++) { + case 1: + dp = 0xffde - (7 << 1); + rd = op_read(OPMODE_ADDR, dp); + break; + case 2: + rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + stack_write(regs.pc >> 8); + break; + case 7: + stack_write(regs.pc); + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tcall_8() { + switch(status.cycle_pos++) { + case 1: + dp = 0xffde - (8 << 1); + rd = op_read(OPMODE_ADDR, dp); + break; + case 2: + rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + stack_write(regs.pc >> 8); + break; + case 7: + stack_write(regs.pc); + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tcall_9() { + switch(status.cycle_pos++) { + case 1: + dp = 0xffde - (9 << 1); + rd = op_read(OPMODE_ADDR, dp); + break; + case 2: + rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + stack_write(regs.pc >> 8); + break; + case 7: + stack_write(regs.pc); + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tcall_10() { + switch(status.cycle_pos++) { + case 1: + dp = 0xffde - (10 << 1); + rd = op_read(OPMODE_ADDR, dp); + break; + case 2: + rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + stack_write(regs.pc >> 8); + break; + case 7: + stack_write(regs.pc); + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tcall_11() { + switch(status.cycle_pos++) { + case 1: + dp = 0xffde - (11 << 1); + rd = op_read(OPMODE_ADDR, dp); + break; + case 2: + rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + stack_write(regs.pc >> 8); + break; + case 7: + stack_write(regs.pc); + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tcall_12() { + switch(status.cycle_pos++) { + case 1: + dp = 0xffde - (12 << 1); + rd = op_read(OPMODE_ADDR, dp); + break; + case 2: + rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + stack_write(regs.pc >> 8); + break; + case 7: + stack_write(regs.pc); + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tcall_13() { + switch(status.cycle_pos++) { + case 1: + dp = 0xffde - (13 << 1); + rd = op_read(OPMODE_ADDR, dp); + break; + case 2: + rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + stack_write(regs.pc >> 8); + break; + case 7: + stack_write(regs.pc); + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tcall_14() { + switch(status.cycle_pos++) { + case 1: + dp = 0xffde - (14 << 1); + rd = op_read(OPMODE_ADDR, dp); + break; + case 2: + rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + stack_write(regs.pc >> 8); + break; + case 7: + stack_write(regs.pc); + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_tcall_15() { + switch(status.cycle_pos++) { + case 1: + dp = 0xffde - (15 << 1); + rd = op_read(OPMODE_ADDR, dp); + break; + case 2: + rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + stack_write(regs.pc >> 8); + break; + case 7: + stack_write(regs.pc); + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_brk() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(OPMODE_ADDR, 0xffde); + break; + case 2: + rd |= op_read(OPMODE_ADDR, 0xffdf) << 8; + break; + case 3: + break; + case 4: + break; + case 5: + stack_write(regs.pc >> 8); + break; + case 6: + stack_write(regs.pc); + break; + case 7: + stack_write(regs.p); + regs.pc = rd; + regs.p.b = 1; + regs.p.i = 0; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_ret() { + switch(status.cycle_pos++) { + case 1: + rd = stack_read(); + break; + case 2: + rd |= stack_read() << 8; + break; + case 3: + break; + case 4: + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_reti() { + switch(status.cycle_pos++) { + case 1: + regs.p = stack_read(); + break; + case 2: + rd = stack_read(); + break; + case 3: + rd |= stack_read() << 8; + break; + case 4: + break; + case 5: + regs.pc = rd; + status.cycle_pos = 0; + break; + } +} + diff --git a/src/apu/bapu/bapu_op_read.cpp b/src/apu/bapu/bapu_op_read.cpp new file mode 100644 index 00000000..c83f37c0 --- /dev/null +++ b/src/apu/bapu/bapu_op_read.cpp @@ -0,0 +1,1467 @@ +void bAPU::op_adc_a_const() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + regs.a = op_adc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_and_a_const() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + regs.a = op_and(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_a_const() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + regs.a = op_cmp(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_x_const() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + regs.x = op_cmp(regs.x, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_y_const() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + regs.y = op_cmp(regs.y, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_eor_a_const() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + regs.a = op_eor(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_or_a_const() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + regs.a = op_or(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_sbc_a_const() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + regs.a = op_sbc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_adc_a_ix() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(OPMODE_DP, regs.x); + break; + case 2: + regs.a = op_adc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_and_a_ix() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(OPMODE_DP, regs.x); + break; + case 2: + regs.a = op_and(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_a_ix() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(OPMODE_DP, regs.x); + break; + case 2: + regs.a = op_cmp(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_eor_a_ix() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(OPMODE_DP, regs.x); + break; + case 2: + regs.a = op_eor(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_or_a_ix() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(OPMODE_DP, regs.x); + break; + case 2: + regs.a = op_or(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_sbc_a_ix() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(OPMODE_DP, regs.x); + break; + case 2: + regs.a = op_sbc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_adc_a_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + regs.a = op_adc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_and_a_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + regs.a = op_and(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_a_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + regs.a = op_cmp(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_x_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + regs.x = op_cmp(regs.x, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_y_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + regs.y = op_cmp(regs.y, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_eor_a_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + regs.a = op_eor(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_or_a_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + regs.a = op_or(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_sbc_a_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + regs.a = op_sbc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_adc_a_dpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + rd = op_read(OPMODE_DP, dp + regs.x); + regs.a = op_adc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_and_a_dpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + rd = op_read(OPMODE_DP, dp + regs.x); + regs.a = op_and(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_a_dpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + rd = op_read(OPMODE_DP, dp + regs.x); + regs.a = op_cmp(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_eor_a_dpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + rd = op_read(OPMODE_DP, dp + regs.x); + regs.a = op_eor(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_or_a_dpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + rd = op_read(OPMODE_DP, dp + regs.x); + regs.a = op_or(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_sbc_a_dpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + rd = op_read(OPMODE_DP, dp + regs.x); + regs.a = op_sbc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_adc_a_addr() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + rd = op_read(OPMODE_ADDR, dp); + regs.a = op_adc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_and_a_addr() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + rd = op_read(OPMODE_ADDR, dp); + regs.a = op_and(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_a_addr() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + rd = op_read(OPMODE_ADDR, dp); + regs.a = op_cmp(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_x_addr() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + rd = op_read(OPMODE_ADDR, dp); + regs.x = op_cmp(regs.x, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_y_addr() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + rd = op_read(OPMODE_ADDR, dp); + regs.y = op_cmp(regs.y, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_eor_a_addr() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + rd = op_read(OPMODE_ADDR, dp); + regs.a = op_eor(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_or_a_addr() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + rd = op_read(OPMODE_ADDR, dp); + regs.a = op_or(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_sbc_a_addr() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + rd = op_read(OPMODE_ADDR, dp); + regs.a = op_sbc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_adc_a_addrx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + break; + case 4: + rd = op_read(OPMODE_ADDR, dp + regs.x); + regs.a = op_adc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_adc_a_addry() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + break; + case 4: + rd = op_read(OPMODE_ADDR, dp + regs.y); + regs.a = op_adc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_and_a_addrx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + break; + case 4: + rd = op_read(OPMODE_ADDR, dp + regs.x); + regs.a = op_and(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_and_a_addry() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + break; + case 4: + rd = op_read(OPMODE_ADDR, dp + regs.y); + regs.a = op_and(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_a_addrx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + break; + case 4: + rd = op_read(OPMODE_ADDR, dp + regs.x); + regs.a = op_cmp(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_a_addry() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + break; + case 4: + rd = op_read(OPMODE_ADDR, dp + regs.y); + regs.a = op_cmp(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_eor_a_addrx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + break; + case 4: + rd = op_read(OPMODE_ADDR, dp + regs.x); + regs.a = op_eor(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_eor_a_addry() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + break; + case 4: + rd = op_read(OPMODE_ADDR, dp + regs.y); + regs.a = op_eor(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_or_a_addrx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + break; + case 4: + rd = op_read(OPMODE_ADDR, dp + regs.x); + regs.a = op_or(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_or_a_addry() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + break; + case 4: + rd = op_read(OPMODE_ADDR, dp + regs.y); + regs.a = op_or(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_sbc_a_addrx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + break; + case 4: + rd = op_read(OPMODE_ADDR, dp + regs.x); + regs.a = op_sbc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_sbc_a_addry() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + break; + case 4: + rd = op_read(OPMODE_ADDR, dp + regs.y); + regs.a = op_sbc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_adc_a_idpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read() + regs.x; + break; + case 2: + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + sp |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 5: + rd = op_read(OPMODE_ADDR, sp); + regs.a = op_adc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_and_a_idpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read() + regs.x; + break; + case 2: + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + sp |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 5: + rd = op_read(OPMODE_ADDR, sp); + regs.a = op_and(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_a_idpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read() + regs.x; + break; + case 2: + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + sp |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 5: + rd = op_read(OPMODE_ADDR, sp); + regs.a = op_cmp(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_eor_a_idpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read() + regs.x; + break; + case 2: + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + sp |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 5: + rd = op_read(OPMODE_ADDR, sp); + regs.a = op_eor(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_or_a_idpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read() + regs.x; + break; + case 2: + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + sp |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 5: + rd = op_read(OPMODE_ADDR, sp); + regs.a = op_or(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_sbc_a_idpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read() + regs.x; + break; + case 2: + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + sp |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 5: + rd = op_read(OPMODE_ADDR, sp); + regs.a = op_sbc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_adc_a_idpy() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + sp |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 5: + rd = op_read(OPMODE_ADDR, sp + regs.y); + regs.a = op_adc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_and_a_idpy() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + sp |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 5: + rd = op_read(OPMODE_ADDR, sp + regs.y); + regs.a = op_and(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_a_idpy() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + sp |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 5: + rd = op_read(OPMODE_ADDR, sp + regs.y); + regs.a = op_cmp(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_eor_a_idpy() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + sp |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 5: + rd = op_read(OPMODE_ADDR, sp + regs.y); + regs.a = op_eor(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_or_a_idpy() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + sp |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 5: + rd = op_read(OPMODE_ADDR, sp + regs.y); + regs.a = op_or(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_sbc_a_idpy() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + sp = op_read(OPMODE_DP, dp); + break; + case 4: + sp |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 5: + rd = op_read(OPMODE_ADDR, sp + regs.y); + regs.a = op_sbc(regs.a, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_adc_ix_iy() { + switch(status.cycle_pos++) { + case 1: + wr = op_read(OPMODE_DP, regs.x); + break; + case 2: + rd = op_read(OPMODE_DP, regs.y); + break; + case 3: + wr = op_adc(wr, rd); + break; + case 4: + if(1)op_write(OPMODE_DP, regs.x, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_and_ix_iy() { + switch(status.cycle_pos++) { + case 1: + wr = op_read(OPMODE_DP, regs.x); + break; + case 2: + rd = op_read(OPMODE_DP, regs.y); + break; + case 3: + wr = op_and(wr, rd); + break; + case 4: + if(1)op_write(OPMODE_DP, regs.x, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_ix_iy() { + switch(status.cycle_pos++) { + case 1: + wr = op_read(OPMODE_DP, regs.x); + break; + case 2: + rd = op_read(OPMODE_DP, regs.y); + break; + case 3: + wr = op_cmp(wr, rd); + break; + case 4: + if(0)op_write(OPMODE_DP, regs.x, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_eor_ix_iy() { + switch(status.cycle_pos++) { + case 1: + wr = op_read(OPMODE_DP, regs.x); + break; + case 2: + rd = op_read(OPMODE_DP, regs.y); + break; + case 3: + wr = op_eor(wr, rd); + break; + case 4: + if(1)op_write(OPMODE_DP, regs.x, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_or_ix_iy() { + switch(status.cycle_pos++) { + case 1: + wr = op_read(OPMODE_DP, regs.x); + break; + case 2: + rd = op_read(OPMODE_DP, regs.y); + break; + case 3: + wr = op_or(wr, rd); + break; + case 4: + if(1)op_write(OPMODE_DP, regs.x, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_sbc_ix_iy() { + switch(status.cycle_pos++) { + case 1: + wr = op_read(OPMODE_DP, regs.x); + break; + case 2: + rd = op_read(OPMODE_DP, regs.y); + break; + case 3: + wr = op_sbc(wr, rd); + break; + case 4: + if(1)op_write(OPMODE_DP, regs.x, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_adc_dp_dp() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + dp = op_read(); + break; + case 3: + wr = op_read(OPMODE_DP, dp); + break; + case 4: + rd = op_read(OPMODE_DP, sp); + break; + case 5: + wr = op_adc(wr, rd); + if(1)op_write(OPMODE_DP, dp, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_and_dp_dp() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + dp = op_read(); + break; + case 3: + wr = op_read(OPMODE_DP, dp); + break; + case 4: + rd = op_read(OPMODE_DP, sp); + break; + case 5: + wr = op_and(wr, rd); + if(1)op_write(OPMODE_DP, dp, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_dp_dp() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + dp = op_read(); + break; + case 3: + wr = op_read(OPMODE_DP, dp); + break; + case 4: + rd = op_read(OPMODE_DP, sp); + break; + case 5: + wr = op_cmp(wr, rd); + if(0)op_write(OPMODE_DP, dp, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_eor_dp_dp() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + dp = op_read(); + break; + case 3: + wr = op_read(OPMODE_DP, dp); + break; + case 4: + rd = op_read(OPMODE_DP, sp); + break; + case 5: + wr = op_eor(wr, rd); + if(1)op_write(OPMODE_DP, dp, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_or_dp_dp() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + dp = op_read(); + break; + case 3: + wr = op_read(OPMODE_DP, dp); + break; + case 4: + rd = op_read(OPMODE_DP, sp); + break; + case 5: + wr = op_or(wr, rd); + if(1)op_write(OPMODE_DP, dp, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_sbc_dp_dp() { + switch(status.cycle_pos++) { + case 1: + sp = op_read(); + break; + case 2: + dp = op_read(); + break; + case 3: + wr = op_read(OPMODE_DP, dp); + break; + case 4: + rd = op_read(OPMODE_DP, sp); + break; + case 5: + wr = op_sbc(wr, rd); + if(1)op_write(OPMODE_DP, dp, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_adc_dp_const() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + break; + case 2: + dp = op_read(); + break; + case 3: + wr = op_read(OPMODE_DP, dp); + break; + case 4: + wr = op_adc(wr, rd); + if(1)op_write(OPMODE_DP, dp, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_and_dp_const() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + break; + case 2: + dp = op_read(); + break; + case 3: + wr = op_read(OPMODE_DP, dp); + break; + case 4: + wr = op_and(wr, rd); + if(1)op_write(OPMODE_DP, dp, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmp_dp_const() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + break; + case 2: + dp = op_read(); + break; + case 3: + wr = op_read(OPMODE_DP, dp); + break; + case 4: + wr = op_cmp(wr, rd); + if(0)op_write(OPMODE_DP, dp, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_eor_dp_const() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + break; + case 2: + dp = op_read(); + break; + case 3: + wr = op_read(OPMODE_DP, dp); + break; + case 4: + wr = op_eor(wr, rd); + if(1)op_write(OPMODE_DP, dp, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_or_dp_const() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + break; + case 2: + dp = op_read(); + break; + case 3: + wr = op_read(OPMODE_DP, dp); + break; + case 4: + wr = op_or(wr, rd); + if(1)op_write(OPMODE_DP, dp, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_sbc_dp_const() { + switch(status.cycle_pos++) { + case 1: + rd = op_read(); + break; + case 2: + dp = op_read(); + break; + case 3: + wr = op_read(OPMODE_DP, dp); + break; + case 4: + wr = op_sbc(wr, rd); + if(1)op_write(OPMODE_DP, dp, wr); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_addw_ya_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 4: + regs.ya = op_addw(regs.ya, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_cmpw_ya_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 4: + regs.ya = op_cmpw(regs.ya, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_subw_ya_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 4: + regs.ya = op_subw(regs.ya, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_and1_bit() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_read(OPMODE_ADDR, dp); + regs.p.c = regs.p.c & !!(rd & (1 << bit)); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_and1_notbit() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_read(OPMODE_ADDR, dp); + regs.p.c = regs.p.c & !(rd & (1 << bit)); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_eor1_bit() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_read(OPMODE_ADDR, dp); + break; + case 4: + regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_not1_bit() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_read(OPMODE_ADDR, dp); + rd ^= (1 << bit); + break; + case 4: + op_write(OPMODE_ADDR, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_or1_bit() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_read(OPMODE_ADDR, dp); + break; + case 4: + regs.p.c = regs.p.c | !!(rd & (1 << bit)); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_or1_notbit() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_read(OPMODE_ADDR, dp); + break; + case 4: + regs.p.c = regs.p.c | !(rd & (1 << bit)); + status.cycle_pos = 0; + break; + } +} + diff --git a/src/apu/bapu/bapu_op_rmw.cpp b/src/apu/bapu/bapu_op_rmw.cpp new file mode 100644 index 00000000..dd7909bf --- /dev/null +++ b/src/apu/bapu/bapu_op_rmw.cpp @@ -0,0 +1,452 @@ +void bAPU::op_inc_a() { + switch(status.cycle_pos++) { + case 1: + regs.a = op_inc(regs.a); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_inc_x() { + switch(status.cycle_pos++) { + case 1: + regs.x = op_inc(regs.x); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_inc_y() { + switch(status.cycle_pos++) { + case 1: + regs.y = op_inc(regs.y); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_dec_a() { + switch(status.cycle_pos++) { + case 1: + regs.a = op_dec(regs.a); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_dec_x() { + switch(status.cycle_pos++) { + case 1: + regs.x = op_dec(regs.x); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_dec_y() { + switch(status.cycle_pos++) { + case 1: + regs.y = op_dec(regs.y); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_asl_a() { + switch(status.cycle_pos++) { + case 1: + regs.a = op_asl(regs.a); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_lsr_a() { + switch(status.cycle_pos++) { + case 1: + regs.a = op_lsr(regs.a); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_rol_a() { + switch(status.cycle_pos++) { + case 1: + regs.a = op_rol(regs.a); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_ror_a() { + switch(status.cycle_pos++) { + case 1: + regs.a = op_ror(regs.a); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_inc_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd = op_inc(rd); + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_dec_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd = op_dec(rd); + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_asl_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd = op_asl(rd); + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_lsr_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd = op_lsr(rd); + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_rol_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd = op_rol(rd); + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_ror_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd = op_ror(rd); + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_inc_dpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + rd = op_read(OPMODE_DP, dp + regs.x); + break; + case 4: + rd = op_inc(rd); + op_write(OPMODE_DP, dp + regs.x, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_dec_dpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + rd = op_read(OPMODE_DP, dp + regs.x); + break; + case 4: + rd = op_dec(rd); + op_write(OPMODE_DP, dp + regs.x, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_asl_dpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + rd = op_read(OPMODE_DP, dp + regs.x); + break; + case 4: + rd = op_asl(rd); + op_write(OPMODE_DP, dp + regs.x, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_lsr_dpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + rd = op_read(OPMODE_DP, dp + regs.x); + break; + case 4: + rd = op_lsr(rd); + op_write(OPMODE_DP, dp + regs.x, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_rol_dpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + rd = op_read(OPMODE_DP, dp + regs.x); + break; + case 4: + rd = op_rol(rd); + op_write(OPMODE_DP, dp + regs.x, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_ror_dpx() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + break; + case 3: + rd = op_read(OPMODE_DP, dp + regs.x); + break; + case 4: + rd = op_ror(rd); + op_write(OPMODE_DP, dp + regs.x, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_inc_addr() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + rd = op_read(OPMODE_ADDR, dp); + break; + case 4: + rd = op_inc(rd); + op_write(OPMODE_ADDR, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_dec_addr() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + rd = op_read(OPMODE_ADDR, dp); + break; + case 4: + rd = op_dec(rd); + op_write(OPMODE_ADDR, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_asl_addr() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + rd = op_read(OPMODE_ADDR, dp); + break; + case 4: + rd = op_asl(rd); + op_write(OPMODE_ADDR, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_lsr_addr() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + rd = op_read(OPMODE_ADDR, dp); + break; + case 4: + rd = op_lsr(rd); + op_write(OPMODE_ADDR, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_rol_addr() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + rd = op_read(OPMODE_ADDR, dp); + break; + case 4: + rd = op_rol(rd); + op_write(OPMODE_ADDR, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_ror_addr() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + dp |= op_read() << 8; + break; + case 3: + rd = op_read(OPMODE_ADDR, dp); + break; + case 4: + rd = op_ror(rd); + op_write(OPMODE_ADDR, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_incw_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 4: + rd = op_incw(rd); + op_write(OPMODE_DP, dp + 1, rd >> 8); + break; + case 5: + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + +void bAPU::op_decw_dp() { + switch(status.cycle_pos++) { + case 1: + dp = op_read(); + break; + case 2: + rd = op_read(OPMODE_DP, dp); + break; + case 3: + rd |= op_read(OPMODE_DP, dp + 1) << 8; + break; + case 4: + rd = op_decw(rd); + op_write(OPMODE_DP, dp + 1, rd >> 8); + break; + case 5: + op_write(OPMODE_DP, dp, rd); + status.cycle_pos = 0; + break; + } +} + diff --git a/src/apu/bapu/bapu_optable.cpp b/src/apu/bapu/bapu_optable.cpp new file mode 100644 index 00000000..1dc4c66b --- /dev/null +++ b/src/apu/bapu/bapu_optable.cpp @@ -0,0 +1,256 @@ +optbl[0x7d] = &bAPU::op_mov_a_x; +optbl[0xdd] = &bAPU::op_mov_a_y; +optbl[0x5d] = &bAPU::op_mov_x_a; +optbl[0xfd] = &bAPU::op_mov_y_a; +optbl[0x9d] = &bAPU::op_mov_x_sp; +optbl[0xbd] = &bAPU::op_mov_sp_x; +optbl[0xe8] = &bAPU::op_mov_a_const; +optbl[0xcd] = &bAPU::op_mov_x_const; +optbl[0x8d] = &bAPU::op_mov_y_const; +optbl[0xe6] = &bAPU::op_mov_a_ix; +optbl[0xbf] = &bAPU::op_mov_a_ixinc; +optbl[0xe4] = &bAPU::op_mov_a_dp; +optbl[0xf8] = &bAPU::op_mov_x_dp; +optbl[0xeb] = &bAPU::op_mov_y_dp; +optbl[0xf4] = &bAPU::op_mov_a_dpx; +optbl[0xf9] = &bAPU::op_mov_x_dpy; +optbl[0xfb] = &bAPU::op_mov_y_dpx; +optbl[0xe5] = &bAPU::op_mov_a_addr; +optbl[0xe9] = &bAPU::op_mov_x_addr; +optbl[0xec] = &bAPU::op_mov_y_addr; +optbl[0xf5] = &bAPU::op_mov_a_addrx; +optbl[0xf6] = &bAPU::op_mov_a_addry; +optbl[0xe7] = &bAPU::op_mov_a_idpx; +optbl[0xf7] = &bAPU::op_mov_a_idpy; +optbl[0xfa] = &bAPU::op_mov_dp_dp; +optbl[0x8f] = &bAPU::op_mov_dp_const; +optbl[0xc6] = &bAPU::op_mov_ix_a; +optbl[0xaf] = &bAPU::op_mov_ixinc_a; +optbl[0xc4] = &bAPU::op_mov_dp_a; +optbl[0xd8] = &bAPU::op_mov_dp_x; +optbl[0xcb] = &bAPU::op_mov_dp_y; +optbl[0xd4] = &bAPU::op_mov_dpx_a; +optbl[0xd9] = &bAPU::op_mov_dpy_x; +optbl[0xdb] = &bAPU::op_mov_dpx_y; +optbl[0xc5] = &bAPU::op_mov_addr_a; +optbl[0xc9] = &bAPU::op_mov_addr_x; +optbl[0xcc] = &bAPU::op_mov_addr_y; +optbl[0xd5] = &bAPU::op_mov_addrx_a; +optbl[0xd6] = &bAPU::op_mov_addry_a; +optbl[0xc7] = &bAPU::op_mov_idpx_a; +optbl[0xd7] = &bAPU::op_mov_idpy_a; +optbl[0xba] = &bAPU::op_movw_ya_dp; +optbl[0xda] = &bAPU::op_movw_dp_ya; +optbl[0xaa] = &bAPU::op_mov1_c_bit; +optbl[0xca] = &bAPU::op_mov1_bit_c; +optbl[0x2f] = &bAPU::op_bra; +optbl[0xf0] = &bAPU::op_beq; +optbl[0xd0] = &bAPU::op_bne; +optbl[0xb0] = &bAPU::op_bcs; +optbl[0x90] = &bAPU::op_bcc; +optbl[0x70] = &bAPU::op_bvs; +optbl[0x50] = &bAPU::op_bvc; +optbl[0x30] = &bAPU::op_bmi; +optbl[0x10] = &bAPU::op_bpl; +optbl[0x03] = &bAPU::op_bbs0; +optbl[0x13] = &bAPU::op_bbc0; +optbl[0x23] = &bAPU::op_bbs1; +optbl[0x33] = &bAPU::op_bbc1; +optbl[0x43] = &bAPU::op_bbs2; +optbl[0x53] = &bAPU::op_bbc2; +optbl[0x63] = &bAPU::op_bbs3; +optbl[0x73] = &bAPU::op_bbc3; +optbl[0x83] = &bAPU::op_bbs4; +optbl[0x93] = &bAPU::op_bbc4; +optbl[0xa3] = &bAPU::op_bbs5; +optbl[0xb3] = &bAPU::op_bbc5; +optbl[0xc3] = &bAPU::op_bbs6; +optbl[0xd3] = &bAPU::op_bbc6; +optbl[0xe3] = &bAPU::op_bbs7; +optbl[0xf3] = &bAPU::op_bbc7; +optbl[0x2e] = &bAPU::op_cbne_dp; +optbl[0xde] = &bAPU::op_cbne_dpx; +optbl[0x6e] = &bAPU::op_dbnz_dp; +optbl[0xfe] = &bAPU::op_dbnz_y; +optbl[0x5f] = &bAPU::op_jmp_addr; +optbl[0x1f] = &bAPU::op_jmp_iaddrx; +optbl[0x3f] = &bAPU::op_call; +optbl[0x4f] = &bAPU::op_pcall; +optbl[0x01] = &bAPU::op_tcall_0; +optbl[0x11] = &bAPU::op_tcall_1; +optbl[0x21] = &bAPU::op_tcall_2; +optbl[0x31] = &bAPU::op_tcall_3; +optbl[0x41] = &bAPU::op_tcall_4; +optbl[0x51] = &bAPU::op_tcall_5; +optbl[0x61] = &bAPU::op_tcall_6; +optbl[0x71] = &bAPU::op_tcall_7; +optbl[0x81] = &bAPU::op_tcall_8; +optbl[0x91] = &bAPU::op_tcall_9; +optbl[0xa1] = &bAPU::op_tcall_10; +optbl[0xb1] = &bAPU::op_tcall_11; +optbl[0xc1] = &bAPU::op_tcall_12; +optbl[0xd1] = &bAPU::op_tcall_13; +optbl[0xe1] = &bAPU::op_tcall_14; +optbl[0xf1] = &bAPU::op_tcall_15; +optbl[0x0f] = &bAPU::op_brk; +optbl[0x6f] = &bAPU::op_ret; +optbl[0x7f] = &bAPU::op_reti; +optbl[0x88] = &bAPU::op_adc_a_const; +optbl[0x28] = &bAPU::op_and_a_const; +optbl[0x68] = &bAPU::op_cmp_a_const; +optbl[0xc8] = &bAPU::op_cmp_x_const; +optbl[0xad] = &bAPU::op_cmp_y_const; +optbl[0x48] = &bAPU::op_eor_a_const; +optbl[0x08] = &bAPU::op_or_a_const; +optbl[0xa8] = &bAPU::op_sbc_a_const; +optbl[0x86] = &bAPU::op_adc_a_ix; +optbl[0x26] = &bAPU::op_and_a_ix; +optbl[0x66] = &bAPU::op_cmp_a_ix; +optbl[0x46] = &bAPU::op_eor_a_ix; +optbl[0x06] = &bAPU::op_or_a_ix; +optbl[0xa6] = &bAPU::op_sbc_a_ix; +optbl[0x84] = &bAPU::op_adc_a_dp; +optbl[0x24] = &bAPU::op_and_a_dp; +optbl[0x64] = &bAPU::op_cmp_a_dp; +optbl[0x3e] = &bAPU::op_cmp_x_dp; +optbl[0x7e] = &bAPU::op_cmp_y_dp; +optbl[0x44] = &bAPU::op_eor_a_dp; +optbl[0x04] = &bAPU::op_or_a_dp; +optbl[0xa4] = &bAPU::op_sbc_a_dp; +optbl[0x94] = &bAPU::op_adc_a_dpx; +optbl[0x34] = &bAPU::op_and_a_dpx; +optbl[0x74] = &bAPU::op_cmp_a_dpx; +optbl[0x54] = &bAPU::op_eor_a_dpx; +optbl[0x14] = &bAPU::op_or_a_dpx; +optbl[0xb4] = &bAPU::op_sbc_a_dpx; +optbl[0x85] = &bAPU::op_adc_a_addr; +optbl[0x25] = &bAPU::op_and_a_addr; +optbl[0x65] = &bAPU::op_cmp_a_addr; +optbl[0x1e] = &bAPU::op_cmp_x_addr; +optbl[0x5e] = &bAPU::op_cmp_y_addr; +optbl[0x45] = &bAPU::op_eor_a_addr; +optbl[0x05] = &bAPU::op_or_a_addr; +optbl[0xa5] = &bAPU::op_sbc_a_addr; +optbl[0x95] = &bAPU::op_adc_a_addrx; +optbl[0x96] = &bAPU::op_adc_a_addry; +optbl[0x35] = &bAPU::op_and_a_addrx; +optbl[0x36] = &bAPU::op_and_a_addry; +optbl[0x75] = &bAPU::op_cmp_a_addrx; +optbl[0x76] = &bAPU::op_cmp_a_addry; +optbl[0x55] = &bAPU::op_eor_a_addrx; +optbl[0x56] = &bAPU::op_eor_a_addry; +optbl[0x15] = &bAPU::op_or_a_addrx; +optbl[0x16] = &bAPU::op_or_a_addry; +optbl[0xb5] = &bAPU::op_sbc_a_addrx; +optbl[0xb6] = &bAPU::op_sbc_a_addry; +optbl[0x87] = &bAPU::op_adc_a_idpx; +optbl[0x27] = &bAPU::op_and_a_idpx; +optbl[0x67] = &bAPU::op_cmp_a_idpx; +optbl[0x47] = &bAPU::op_eor_a_idpx; +optbl[0x07] = &bAPU::op_or_a_idpx; +optbl[0xa7] = &bAPU::op_sbc_a_idpx; +optbl[0x97] = &bAPU::op_adc_a_idpy; +optbl[0x37] = &bAPU::op_and_a_idpy; +optbl[0x77] = &bAPU::op_cmp_a_idpy; +optbl[0x57] = &bAPU::op_eor_a_idpy; +optbl[0x17] = &bAPU::op_or_a_idpy; +optbl[0xb7] = &bAPU::op_sbc_a_idpy; +optbl[0x99] = &bAPU::op_adc_ix_iy; +optbl[0x39] = &bAPU::op_and_ix_iy; +optbl[0x79] = &bAPU::op_cmp_ix_iy; +optbl[0x59] = &bAPU::op_eor_ix_iy; +optbl[0x19] = &bAPU::op_or_ix_iy; +optbl[0xb9] = &bAPU::op_sbc_ix_iy; +optbl[0x89] = &bAPU::op_adc_dp_dp; +optbl[0x29] = &bAPU::op_and_dp_dp; +optbl[0x69] = &bAPU::op_cmp_dp_dp; +optbl[0x49] = &bAPU::op_eor_dp_dp; +optbl[0x09] = &bAPU::op_or_dp_dp; +optbl[0xa9] = &bAPU::op_sbc_dp_dp; +optbl[0x98] = &bAPU::op_adc_dp_const; +optbl[0x38] = &bAPU::op_and_dp_const; +optbl[0x78] = &bAPU::op_cmp_dp_const; +optbl[0x58] = &bAPU::op_eor_dp_const; +optbl[0x18] = &bAPU::op_or_dp_const; +optbl[0xb8] = &bAPU::op_sbc_dp_const; +optbl[0x7a] = &bAPU::op_addw_ya_dp; +optbl[0x5a] = &bAPU::op_cmpw_ya_dp; +optbl[0x9a] = &bAPU::op_subw_ya_dp; +optbl[0x4a] = &bAPU::op_and1_bit; +optbl[0x6a] = &bAPU::op_and1_notbit; +optbl[0x8a] = &bAPU::op_eor1_bit; +optbl[0xea] = &bAPU::op_not1_bit; +optbl[0x0a] = &bAPU::op_or1_bit; +optbl[0x2a] = &bAPU::op_or1_notbit; +optbl[0xbc] = &bAPU::op_inc_a; +optbl[0x3d] = &bAPU::op_inc_x; +optbl[0xfc] = &bAPU::op_inc_y; +optbl[0x9c] = &bAPU::op_dec_a; +optbl[0x1d] = &bAPU::op_dec_x; +optbl[0xdc] = &bAPU::op_dec_y; +optbl[0x1c] = &bAPU::op_asl_a; +optbl[0x5c] = &bAPU::op_lsr_a; +optbl[0x3c] = &bAPU::op_rol_a; +optbl[0x7c] = &bAPU::op_ror_a; +optbl[0xab] = &bAPU::op_inc_dp; +optbl[0x8b] = &bAPU::op_dec_dp; +optbl[0x0b] = &bAPU::op_asl_dp; +optbl[0x4b] = &bAPU::op_lsr_dp; +optbl[0x2b] = &bAPU::op_rol_dp; +optbl[0x6b] = &bAPU::op_ror_dp; +optbl[0xbb] = &bAPU::op_inc_dpx; +optbl[0x9b] = &bAPU::op_dec_dpx; +optbl[0x1b] = &bAPU::op_asl_dpx; +optbl[0x5b] = &bAPU::op_lsr_dpx; +optbl[0x3b] = &bAPU::op_rol_dpx; +optbl[0x7b] = &bAPU::op_ror_dpx; +optbl[0xac] = &bAPU::op_inc_addr; +optbl[0x8c] = &bAPU::op_dec_addr; +optbl[0x0c] = &bAPU::op_asl_addr; +optbl[0x4c] = &bAPU::op_lsr_addr; +optbl[0x2c] = &bAPU::op_rol_addr; +optbl[0x6c] = &bAPU::op_ror_addr; +optbl[0x3a] = &bAPU::op_incw_dp; +optbl[0x1a] = &bAPU::op_decw_dp; +optbl[0x00] = &bAPU::op_nop; +optbl[0xef] = &bAPU::op_sleep; +optbl[0xff] = &bAPU::op_stop; +optbl[0x9f] = &bAPU::op_xcn; +optbl[0xdf] = &bAPU::op_daa; +optbl[0xbe] = &bAPU::op_das; +optbl[0x60] = &bAPU::op_clrc; +optbl[0x20] = &bAPU::op_clrp; +optbl[0x80] = &bAPU::op_setc; +optbl[0x40] = &bAPU::op_setp; +optbl[0xe0] = &bAPU::op_clrv; +optbl[0xed] = &bAPU::op_notc; +optbl[0xa0] = &bAPU::op_ei; +optbl[0xc0] = &bAPU::op_di; +optbl[0x02] = &bAPU::op_set0_dp; +optbl[0x12] = &bAPU::op_clr0_dp; +optbl[0x22] = &bAPU::op_set1_dp; +optbl[0x32] = &bAPU::op_clr1_dp; +optbl[0x42] = &bAPU::op_set2_dp; +optbl[0x52] = &bAPU::op_clr2_dp; +optbl[0x62] = &bAPU::op_set3_dp; +optbl[0x72] = &bAPU::op_clr3_dp; +optbl[0x82] = &bAPU::op_set4_dp; +optbl[0x92] = &bAPU::op_clr4_dp; +optbl[0xa2] = &bAPU::op_set5_dp; +optbl[0xb2] = &bAPU::op_clr5_dp; +optbl[0xc2] = &bAPU::op_set6_dp; +optbl[0xd2] = &bAPU::op_clr6_dp; +optbl[0xe2] = &bAPU::op_set7_dp; +optbl[0xf2] = &bAPU::op_clr7_dp; +optbl[0x0e] = &bAPU::op_tset_addr_a; +optbl[0x4e] = &bAPU::op_tclr_addr_a; +optbl[0x2d] = &bAPU::op_push_a; +optbl[0x4d] = &bAPU::op_push_x; +optbl[0x6d] = &bAPU::op_push_y; +optbl[0x0d] = &bAPU::op_push_p; +optbl[0xae] = &bAPU::op_pop_a; +optbl[0xce] = &bAPU::op_pop_x; +optbl[0xee] = &bAPU::op_pop_y; +optbl[0x8e] = &bAPU::op_pop_p; +optbl[0xcf] = &bAPU::op_mul_ya; +optbl[0x9e] = &bAPU::op_div_ya_x; diff --git a/src/apu/bapu/bapugen.cpp b/src/apu/bapu/bapugen.cpp new file mode 100644 index 00000000..8c5169e9 --- /dev/null +++ b/src/apu/bapu/bapugen.cpp @@ -0,0 +1,168 @@ +#include "../../lib/libbase.h" +#include "../../lib/libstring.h" +#include "../../lib/libstring.cpp" + +FILE *fp, *fph, *fpt; + +string data, line, part, subpart; +string output_table, output_header, output_op; + +int op_count; +struct _op_list { +string name; +string arg; +}op_list[64]; + +int line_num; + +void clear_op_list() { + op_count = 0; + for(int i=0;i<64;i++) { + strcpy(op_list[i].name, ""); + for(int l=0;l<8;l++) { + strcpy(op_list[i].arg[l], ""); + } + } +} + +void gen_header() { +int i = line_num, l, n, z; +char t[4096]; + clear_op_list(); + while(1) { + z = op_count++; + strcpy(part, line[i]); + strrtrim(part, "),"); + strrtrim(part, ") {"); + split(subpart, "(", part); + strcpy(op_list[z].name, subpart[0]); + split(part, ", ", subpart[1]); + for(l=0;l= count(line))break; + + gen_header(); + gen_op(); + gen_final(); + } + + fclose(fp); +} + +int main() { + fph = fopen("bapu_op.h", "wb"); + fpt = fopen("bapu_optable.cpp", "wb"); + + generate("bapu_op_mov.cpp", "op_mov.b"); + generate("bapu_op_pc.cpp", "op_pc.b"); + generate("bapu_op_read.cpp", "op_read.b"); + generate("bapu_op_rmw.cpp", "op_rmw.b"); + generate("bapu_op_misc.cpp", "op_misc.b"); + + fclose(fph); + fclose(fpt); + + return 0; +} diff --git a/src/apu/bapu/bapugen.exe b/src/apu/bapu/bapugen.exe new file mode 100644 index 0000000000000000000000000000000000000000..e08b8e2d9893b5b92d7b80da982b840fc6946bc0 GIT binary patch literal 53248 zcmeFa4_p-2)jvGT4luytt_q3~;~Fv1Vk{9&B#Uto7SM<;BD)eJ#zqVhqXuTwq@YU% zT87CawolrpeVVqhrfu5h*MI3_Nt-{w8bD2rf6~OnJgsSLI%G_O(ZH(cyx((YK}?gr zzvuV+y`Rtfz8~>3J2Us5d+xdCo_p@O=bk&3+_j6da~#LxGEI(a!=3)T?Dt>)97gu2 z$$uEd{Vw58Q`&4x{xoGp^@ck4mfFqt)vkTOeec>$n>LH?uT;5frA_V)o7@G<%G?iZ zURO0MIXN*Siu&+dDe@C-4S=eU3K zdk-G|7VgV8+*?g$hbZ;?IBto}&Xw%`XyH)WNzQ3Yvc+*+2r2hisb8Cky9?JYdiPq- zcqcy4-_V`w!wbRTkNCu1*gJlr>Cqd@-S-5?O=nO4hktf)T>HO3IZLeCE+Rjjeu$t@ z^p4xmpBt^8Rl9DjxR&GoA|Mqwukc_9igCj`%L3!LJCXhruB_-Cx1m4pzb0u2?ArYr z2d;788V9a%;2H<6ao`#Uu5sWR2d;788V9a%;Qs|22&iXjMt2wTv}DwGj^j9aAFsr9 zah%#!8Q!&PmumCt*Nx}63VOkxeA=NFWVp)Ix4cS0h9f86<&^&mWy=G>8bPlBBoH*W zi^*z_{*-B&0CF2bH-4$HYMo2{D(@Lk#EcXzU{lIm_1o1ug*F@Vj-2##?40N6Y?voU zYz=4Bk3GFRV$@#G$6~oQ=YLS?fc}?M;JA}V6>7xOtJG(>>PM;BXMb#5r}i4Jsk(7c zJ)~x=|A&i+_EAirxr`?PBJ>nqVPbxB5wDrTfn1Cx~dc~70NBS|geRl8QOYtV>Q zlQjM}>WU1v;zA44sAZ4LKnvDXu3jbYb9C|?wZF715LD}d=`C%WEvL>^7Z=p^%ccpc z%01`nMKxb|k+tUU9v!Xus3BgyM6K!d=xB}Z=@m7o=JRUOno6ypad4H&Re)l3tj7OgO=a|r=%@bn zM*F+FkemQEy(J~u?b+?>A-_`SPzqi8SZb6d15|G4Pd+W6?}O@BUCY3J!P)WxP?QJM zI^J`+{;TLqEol4P?))g)oga$rd2?~{4k nF~kJVSE)OR1Jr(W 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%0A4$0Kw)V0^Pq8*)u*T4-BO_7 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 4) | (regs.a << 4); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +daa(0xdf) { +1: +2: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: +2: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:$1; +} + +clrv(0xe0) { +1:regs.p.v = 0; + regs.p.h = 0; +} + +notc(0xed) { +1: +2:regs.p.c ^= 1; +} + +ei(0xa0, 1), +di(0xc0, 0) { +1: +2: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_read(); +2:rd = op_read(OPMODE_DP, dp); +3:$1; + op_write(OPMODE_DP, dp, rd); +} + +tset_addr_a(0x0e, |=), +tclr_addr_a(0x4e, &=~) { +1:dp = op_read(); +2:dp |= op_read() << 8; +3:rd = op_read(OPMODE_ADDR, dp); +4:regs.p.n = !!((rd & regs.a) & 0x80); + regs.p.z = ((rd & regs.a) == 0); + rd $1 regs.a; +5:op_write(OPMODE_ADDR, dp, rd); +} + +push_a(0x2d, a), +push_x(0x4d, x), +push_y(0x6d, y), +push_p(0x0d, p) { +1: +2: +3:stack_write(regs.$1); +} + +pop_a(0xae, a), +pop_x(0xce, x), +pop_y(0xee, y), +pop_p(0x8e, p) { +1: +2: +3:regs.$1 = stack_read(); +} + +mul_ya(0xcf) { +1: +2: +3: +4: +5: +6: +7: +8: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: +2: +3: +4: +5: +6: +7: +8: +9: +10: +11: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 SPC700 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/src/apu/bapu/op_mov.b b/src/apu/bapu/op_mov.b new file mode 100644 index 00000000..43b1d58d --- /dev/null +++ b/src/apu/bapu/op_mov.b @@ -0,0 +1,207 @@ +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), +mov_sp_x(0xbd, sp, x) { +1:regs.$1 = regs.$2; + regs.p.n = !!(regs.$1 & 0x80); + regs.p.z = (regs.$1 == 0); +} + +mov_a_const(0xe8, a), +mov_x_const(0xcd, x), +mov_y_const(0x8d, y) { +1:regs.$1 = op_read(); + regs.p.n = !!(regs.$1 & 0x80); + regs.p.z = (regs.$1 == 0); +} + +mov_a_ix(0xe6) { +1: +2:regs.a = op_read(OPMODE_DP, regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_a_ixinc(0xbf) { +1: +2: +3:regs.a = op_read(OPMODE_DP, regs.x++); + 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_read(); +2:regs.$1 = op_read(OPMODE_DP, 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_read(); +2: +3:regs.$1 = op_read(OPMODE_DP, 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_read(); +2:sp |= op_read() << 8; +3:regs.$1 = op_read(OPMODE_ADDR, 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_read(); +2:sp |= op_read() << 8; +3: +4:regs.a = op_read(OPMODE_ADDR, sp + regs.$1); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_a_idpx(0xe7) { +1:dp = op_read() + regs.x; +2: +3:sp = op_read(OPMODE_DP, dp); +4:sp |= op_read(OPMODE_DP, dp + 1) << 8; +5:regs.a = op_read(OPMODE_ADDR, sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_a_idpy(0xf7) { +1:dp = op_read(); +2: +3:sp = op_read(OPMODE_DP, dp); +4:sp |= op_read(OPMODE_DP, dp + 1) << 8; +5:regs.a = op_read(OPMODE_ADDR, sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_dp_dp(0xfa) { +1:sp = op_read(); +2:dp = op_read(); +3:rd = op_read(OPMODE_DP, sp); +4:op_write(OPMODE_DP, dp, rd); +} + +mov_dp_const(0x8f) { +1:rd = op_read(); +2:dp = op_read(); +3: +4:op_write(OPMODE_DP, dp, rd); +} + +mov_ix_a(0xc6) { +1: +2: +3:op_write(OPMODE_DP, regs.x, regs.a); +} + +mov_ixinc_a(0xaf) { +1: +2: +3:op_write(OPMODE_DP, regs.x++, regs.a); +} + +mov_dp_a(0xc4, a), +mov_dp_x(0xd8, x), +mov_dp_y(0xcb, y) { +1:dp = op_read(); +2: +3:op_write(OPMODE_DP, dp, regs.$1); +} + +mov_dpx_a(0xd4, x, a), +mov_dpy_x(0xd9, y, x), +mov_dpx_y(0xdb, x, y) { +1:dp = op_read(); +2: +3: +4:op_write(OPMODE_DP, dp + regs.$1, regs.$2); +} + +mov_addr_a(0xc5, a), +mov_addr_x(0xc9, x), +mov_addr_y(0xcc, y) { +1:dp = op_read(); +2:dp |= op_read() << 8; +3: +4:op_write(OPMODE_ADDR, dp, regs.$1); +} + +mov_addrx_a(0xd5, x), +mov_addry_a(0xd6, y) { +1:dp = op_read(); +2:dp |= op_read() << 8; +3: +4: +5:op_write(OPMODE_ADDR, dp + regs.$1, regs.a); +} + +mov_idpx_a(0xc7) { +1:sp = op_read() + regs.x; +2: +3:dp = op_read(OPMODE_DP, sp); +4:dp |= op_read(OPMODE_DP, sp + 1) << 8; +5: +6:op_write(OPMODE_ADDR, dp, regs.a); +} + +mov_idpy_a(0xd7) { +1:sp = op_read(); +2: +3:dp = op_read(OPMODE_DP, sp); +4:dp |= op_read(OPMODE_DP, sp + 1) << 8; +5: +6:op_write(OPMODE_ADDR, dp + regs.y, regs.a); +} + +movw_ya_dp(0xba) { +1:sp = op_read(); +2: +3:regs.a = op_read(OPMODE_DP, sp); +4:regs.y = op_read(OPMODE_DP, sp + 1); + regs.p.n = !!(regs.ya & 0x8000); + regs.p.z = (regs.ya == 0); +} + +movw_dp_ya(0xda) { +1:dp = op_read(); +2: +3:op_write(OPMODE_DP, dp, regs.a); +4:op_write(OPMODE_DP, dp + 1, regs.y); +} + +mov1_c_bit(0xaa) { +1:sp = op_read(); +2:sp |= op_read() << 8; +3:bit = sp >> 13; + sp &= 0x1fff; + rd = op_read(OPMODE_ADDR, sp); + regs.p.c = !!(rd & (1 << bit)); +} + +mov1_bit_c(0xca) { +1:dp = op_read(); +2:dp |= op_read() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_read(OPMODE_ADDR, dp); + if(regs.p.c)rd |= (1 << bit); + else rd &= ~(1 << bit); +4:op_write(OPMODE_ADDR, dp, rd); +} diff --git a/src/apu/bapu/op_pc.b b/src/apu/bapu/op_pc.b new file mode 100644 index 00000000..d6e0b989 --- /dev/null +++ b/src/apu/bapu/op_pc.b @@ -0,0 +1,157 @@ +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_read(); + if($1)end; +2: +3: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_read(); +2:rd = op_read(); +3:sp = op_read(OPMODE_DP, dp); +4:if((sp & $1) $2 $1)end; +5: +6:regs.pc += (int8)rd; +} + +cbne_dp(0x2e, 0), +cbne_dpx(0xde, regs.x) { +1:dp = op_read(); +2:rd = op_read(); +3:sp = op_read(OPMODE_DP, dp + $1); +4:if(regs.a == sp)end; +5: +6:regs.pc += (int8)rd; +} + +dbnz_dp(0x6e) { +1:dp = op_read(); +2:rd = op_read(); +3:wr = op_read(OPMODE_DP, dp); +4:wr--; + op_write(OPMODE_DP, dp, wr); + if(wr == 0x00)end; +5: +6:regs.pc += (int8)rd; +} + +dbnz_y(0xfe) { +1:rd = op_read(); +2:regs.y--; +3:if(regs.y == 0x00)end; +4: +5:regs.pc += (int8)rd; +} + +jmp_addr(0x5f) { +1:rd = op_read(); +2:rd |= op_read() << 8; + regs.pc = rd; +} + +jmp_iaddrx(0x1f) { +1:dp = op_read(); +2:dp |= op_read() << 8; +3:dp += regs.x; +4:rd = op_read(OPMODE_ADDR, dp); +5:rd |= op_read(OPMODE_ADDR, dp + 1) << 8; + regs.pc = rd; +} + +call(0x3f) { +1:rd = op_read(); +2:rd |= op_read() << 8; +3: +4: +5: +6:stack_write(regs.pc >> 8); +7:stack_write(regs.pc); + regs.pc = rd; +} + +pcall(0x4f) { +1:rd = op_read(); +2: +3: +4:stack_write(regs.pc >> 8); +5:stack_write(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_read(OPMODE_ADDR, dp); +2:rd |= op_read(OPMODE_ADDR, dp + 1) << 8; +3: +4: +5: +6:stack_write(regs.pc >> 8); +7:stack_write(regs.pc); + regs.pc = rd; +} + +brk(0x0f) { +1:rd = op_read(OPMODE_ADDR, 0xffde); +2:rd |= op_read(OPMODE_ADDR, 0xffdf) << 8; +3: +4: +5:stack_write(regs.pc >> 8); +6:stack_write(regs.pc); +7:stack_write(regs.p); + regs.pc = rd; + regs.p.b = 1; + regs.p.i = 0; +} + +ret(0x6f) { +1:rd = stack_read(); +2:rd |= stack_read() << 8; +3: +4:regs.pc = rd; +} + +reti(0x7f) { +1:regs.p = stack_read(); +2:rd = stack_read(); +3:rd |= stack_read() << 8; +4: +5:regs.pc = rd; +} diff --git a/src/apu/bapu/op_read.b b/src/apu/bapu/op_read.b new file mode 100644 index 00000000..c67f3571 --- /dev/null +++ b/src/apu/bapu/op_read.b @@ -0,0 +1,194 @@ +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_read(); + 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:rd = op_read(OPMODE_DP, regs.x); +2: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_read(); +2:rd = op_read(OPMODE_DP, 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_read(); +2: +3:rd = op_read(OPMODE_DP, 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_read(); +2:dp |= op_read() << 8; +3:rd = op_read(OPMODE_ADDR, 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_read(); +2:dp |= op_read() << 8; +3: +4:rd = op_read(OPMODE_ADDR, 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_read() + regs.x; +2: +3:sp = op_read(OPMODE_DP, dp); +4:sp |= op_read(OPMODE_DP, dp + 1) << 8; +5:rd = op_read(OPMODE_ADDR, 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_read(); +2: +3:sp = op_read(OPMODE_DP, dp); +4:sp |= op_read(OPMODE_DP, dp + 1) << 8; +5:rd = op_read(OPMODE_ADDR, 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:wr = op_read(OPMODE_DP, regs.x); +2:rd = op_read(OPMODE_DP, regs.y); +3:wr = op_$1(wr, rd); +4:if($2)op_write(OPMODE_DP, regs.x, wr); +} + +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_read(); +2:dp = op_read(); +3:wr = op_read(OPMODE_DP, dp); +4:rd = op_read(OPMODE_DP, sp); +5:wr = op_$1(wr, rd); + if($2)op_write(OPMODE_DP, dp, wr); +} + +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_read(); +2:dp = op_read(); +3:wr = op_read(OPMODE_DP, dp); +4:wr = op_$1(wr, rd); + if($2)op_write(OPMODE_DP, dp, wr); +} + +addw_ya_dp(0x7a, addw), +cmpw_ya_dp(0x5a, cmpw), +subw_ya_dp(0x9a, subw) { +1:dp = op_read(); +2:rd = op_read(OPMODE_DP, dp); +3:rd |= op_read(OPMODE_DP, dp + 1) << 8; +4:regs.ya = op_$1(regs.ya, rd); +} + +and1_bit(0x4a, !!), +and1_notbit(0x6a, !) { +1:dp = op_read(); +2:dp |= op_read() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_read(OPMODE_ADDR, dp); + regs.p.c = regs.p.c & $1(rd & (1 << bit)); +} + +eor1_bit(0x8a) { +1:dp = op_read(); +2:dp |= op_read() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_read(OPMODE_ADDR, dp); +4:regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); +} + +not1_bit(0xea) { +1:dp = op_read(); +2:dp |= op_read() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_read(OPMODE_ADDR, dp); + rd ^= (1 << bit); +4:op_write(OPMODE_ADDR, dp, rd); +} + +or1_bit(0x0a, !!), +or1_notbit(0x2a, !) { +1:dp = op_read(); +2:dp |= op_read() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_read(OPMODE_ADDR, dp); +4:regs.p.c = regs.p.c | $1(rd & (1 << bit)); +} diff --git a/src/apu/bapu/op_rmw.b b/src/apu/bapu/op_rmw.b new file mode 100644 index 00000000..6084310d --- /dev/null +++ b/src/apu/bapu/op_rmw.b @@ -0,0 +1,60 @@ +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: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_read(); +2:rd = op_read(OPMODE_DP, dp); +3:rd = op_$1(rd); + op_write(OPMODE_DP, 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_read(); +2: +3:rd = op_read(OPMODE_DP, dp + regs.x); +4:rd = op_$1(rd); + op_write(OPMODE_DP, 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_read(); +2:dp |= op_read() << 8; +3:rd = op_read(OPMODE_ADDR, dp); +4:rd = op_$1(rd); + op_write(OPMODE_ADDR, dp, rd); +} + +incw_dp(0x3a, incw), +decw_dp(0x1a, decw) { +1:dp = op_read(); +2:rd = op_read(OPMODE_DP, dp); +3:rd |= op_read(OPMODE_DP, dp + 1) << 8; +4:rd = op_$1(rd); + op_write(OPMODE_DP, dp + 1, rd >> 8); +5:op_write(OPMODE_DP, dp, rd); +} diff --git a/src/apu/bapuskip/bapuskip.cpp b/src/apu/bapuskip/bapuskip.cpp new file mode 100644 index 00000000..597a93bd --- /dev/null +++ b/src/apu/bapuskip/bapuskip.cpp @@ -0,0 +1,171 @@ +#include "../../base.h" + +uint8 bAPUSkip::spcram_read (uint16 addr) { return 0xff; } +void bAPUSkip::spcram_write(uint16 addr, uint8 value) {} + +/* + This routine is very serious. It will eat holes through + the ROM to skip APU test conditions. Or in other words, + it will disable and/or force branches when neccesary. + + It can very easily break or corrupt a game and prevent it + from being playable until the ROM is reloaded (ROM writes + are only performed in memory, of course). + + However, this kind of brute force approach is required to + get many games playable without proper SPC700 emulation. +*/ +uint8 bAPUSkip::port_read(uint8 port) { + port &= 3; +_apu_port *p = &apu_port[port]; +int i, x, y, z, t; +uint32 addr; + + addr = cpu->regs.pc.d; + p->read_addr[p->read_pos & 31] = addr; + +//- lda $214x +// cmp $214x +// bne - +// cmp ??? +// beq/bne - +__test1: +//look for an lda/cmp read pattern + if(addr == p->read_addr[(p->read_pos - 1) & 31])goto __test2; + if(addr != p->read_addr[(p->read_pos - 2) & 31])goto __test2; + if(addr == p->read_addr[(p->read_pos - 3) & 31])goto __test2; + if(addr != p->read_addr[(p->read_pos - 4) & 31])goto __test2; + if(p->read_addr[(p->read_pos - 1) & 31] != p->read_addr[(p->read_pos - 3) & 31])goto __test2; +//try and find compare opcode + for(i=0;i<24;i++) { + x = mem_bus->read(addr + i); + if(x == OP_CMP_CONST || x == OP_CPX_CONST || x == OP_CPY_CONST)break; + if(x == OP_CMP_ADDR || x == OP_CPX_ADDR || x == OP_CPY_ADDR) break; + if(x == OP_CMP_LONG)break; + } + if(i == 24)goto __test2; +//seek to next opcode + if(x == OP_CMP_CONST) { + i += (cpu->regs.p.m)?2:3; + } else if(x == OP_CPX_CONST || x == OP_CPY_CONST) { + i += (cpu->regs.p.x)?2:3; + } else if(x == OP_CMP_ADDR || x == OP_CPX_ADDR || x == OP_CPY_ADDR) { + i += 3; + } else { //(x == OP_CMP_LONG) { + i += 4; + } + x = mem_bus->read(addr + i); + if(x == OP_BNE) { + mem_bus->cart->write_protect(false); + mem_bus->write(addr + i, OP_NOP); + mem_bus->write(addr + i + 1, OP_NOP); + mem_bus->cart->write_protect(true); + } else if(x == OP_BEQ) { + mem_bus->cart->write_protect(false); + mem_bus->write(addr + i, OP_BRA); + mem_bus->cart->write_protect(true); + } else goto __test2; + goto __pass; + +//- lda $214x +// cmp ??? +// beq/bne - +__test2: +//look for a repeated read pattern + if(addr != p->read_addr[(p->read_pos - 1) & 31])goto __test3; + if(addr != p->read_addr[(p->read_pos - 2) & 31])goto __test3; + if(addr != p->read_addr[(p->read_pos - 3) & 31])goto __test3; + if(addr != p->read_addr[(p->read_pos - 4) & 31])goto __test3; + if(addr != p->read_addr[(p->read_pos - 5) & 31])goto __test3; + if(addr != p->read_addr[(p->read_pos - 6) & 31])goto __test3; + if(addr != p->read_addr[(p->read_pos - 7) & 31])goto __test3; + if(addr != p->read_addr[(p->read_pos - 8) & 31])goto __test3; +//try and find compare opcode + for(i=0;i<24;i++) { + x = mem_bus->read(addr + i); + if(x == OP_CMP_CONST || x == OP_CPX_CONST || x == OP_CPY_CONST)break; + if(x == OP_CMP_ADDR || x == OP_CPX_ADDR || x == OP_CPY_ADDR) break; + if(x == OP_CMP_LONG)break; + } + if(i == 24)goto __test3; +//seek to next opcode + if(x == OP_CMP_CONST) { + i += (cpu->regs.p.m)?2:3; + } else if(x == OP_CPX_CONST || x == OP_CPY_CONST) { + i += (cpu->regs.p.x)?2:3; + } else if(x == OP_CMP_ADDR || x == OP_CPX_ADDR || x == OP_CPY_ADDR) { + i += 3; + } else if(x == OP_CMP_LONG) { + i += 4; + } + x = mem_bus->read(addr + i); + if(x == OP_BNE) { + mem_bus->cart->write_protect(false); + mem_bus->write(addr + i, OP_NOP); + mem_bus->write(addr + i + 1, OP_NOP); + mem_bus->cart->write_protect(true); + } else if(x == OP_BEQ) { + mem_bus->cart->write_protect(false); + mem_bus->write(addr + i, OP_BRA); + mem_bus->cart->write_protect(true); + } else goto __test3; + goto __pass; + +//fallback +__test3: + if(p->pos < 4) { + if(!(port & 1)) { + p->value = cpu->regs.a.l; + } else { + p->value = cpu->regs.a.h; + } + } else if(p->pos < 8) { + if(!(port & 1)) { + p->value = cpu->regs.x.l; + } else { + p->value = cpu->regs.x.h; + } + } else if(p->pos < 12) { + if(!(port & 1)) { + p->value = cpu->regs.y.l; + } else { + p->value = cpu->regs.y.h; + } + } else if(p->pos < 16) { + p->value = rand(); + } + if(++p->pos == 16)p->pos = 0; + +__pass: + p->read_pos++; + p->read_pos &= 31; + return p->value; +} + +void bAPUSkip::port_write(uint8 port, uint8 value) { + port &= 3; + apu_port[port].value = value; +} + +void bAPUSkip::run() { + snes->notify(SNES::APU_EXEC_OPCODE_BEGIN); + snes->notify(SNES::APU_EXEC_OPCODE_END); +} + +void bAPUSkip::power() { + reset(); +} + +void bAPUSkip::reset() { + regs.a = 0x00; + regs.x = 0x00; + regs.y = 0x00; + regs.sp = 0x00; + regs.p = 0x02; + regs.pc = 0xffc0; + + memset(&apu_port[0], 0, sizeof(_apu_port)); + memset(&apu_port[1], 0, sizeof(_apu_port)); + memset(&apu_port[2], 0, sizeof(_apu_port)); + memset(&apu_port[3], 0, sizeof(_apu_port)); +} diff --git a/src/apu/bapuskip/bapuskip.h b/src/apu/bapuskip/bapuskip.h new file mode 100644 index 00000000..9d907c23 --- /dev/null +++ b/src/apu/bapuskip/bapuskip.h @@ -0,0 +1,33 @@ +class bAPUSkip : public APU { +public: + +struct _apu_port { + uint8 value; + uint8 step, pos; + uint32 read_addr[32], read_pos; +}apu_port[4]; + +enum { + OP_CMP_CONST = 0xc9, + OP_CPX_CONST = 0xe0, + OP_CPY_CONST = 0xc0, + OP_CMP_ADDR = 0xcd, + OP_CPX_ADDR = 0xec, + OP_CPY_ADDR = 0xcc, + OP_CMP_LONG = 0xcf, + OP_BNE = 0xd0, + OP_BEQ = 0xf0, + OP_BRA = 0x80, + OP_NOP = 0xea +}; + + uint8 spcram_read (uint16 addr); + void spcram_write(uint16 addr, uint8 value); + uint8 port_read (uint8 port); + void port_write (uint8 port, uint8 value); + + void run(); + uint32 cycles_executed() { return 12 * 24; } + void power(); + void reset(); +}; diff --git a/src/apu/dapu.cpp b/src/apu/dapu.cpp new file mode 100644 index 00000000..5377cadd --- /dev/null +++ b/src/apu/dapu.cpp @@ -0,0 +1,295 @@ +uint16 APU::__relb(int8 offset, int op_len) { +uint16 pc = regs.pc + op_len; + return pc + offset; +} + +void APU::disassemble_opcode(char *output) { +char *s = output, t[512]; +uint8 op, op0, op1; +uint16 opw, opdp0, opdp1; + sprintf(s, "..%0.4x ", regs.pc); + + op = spcram_read(regs.pc); + op0 = spcram_read(regs.pc + 1); + op1 = spcram_read(regs.pc + 2); + opw = (op0) | (op1 << 8); + opdp0 = ((regs.p.p)?0x100:0x000) + op0; + opdp1 = ((regs.p.p)?0x100:0x000) + op1; + + strcpy(t, " "); + switch(op) { + case 0x00:sprintf(t, "nop"); break; + case 0x01:sprintf(t, "tcall 0"); break; + case 0x02:sprintf(t, "set0 $%0.3x", opdp0); break; + case 0x03:sprintf(t, "bbs0 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0x04:sprintf(t, "or a,$%0.3x", opdp0); break; + case 0x05:sprintf(t, "or a,$%0.4x", opw); break; + case 0x06:sprintf(t, "or a,(x)"); break; + case 0x07:sprintf(t, "or a,($%0.3x+x)", opdp0); break; + case 0x08:sprintf(t, "or a,#$%0.2x", op0); break; + case 0x09:sprintf(t, "or $%0.3x,$%0.3x", opdp1, opdp0); break; + case 0x0a:sprintf(t, "or1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0x0b:sprintf(t, "asl $%0.3x", opdp0); break; + case 0x0c:sprintf(t, "asl $%0.4x", opw); break; + case 0x0d:sprintf(t, "push p"); break; + case 0x0e:sprintf(t, "tset $%0.4x,a", opw); break; + case 0x0f:sprintf(t, "brk"); break; + case 0x10:sprintf(t, "bpl $%0.4x", __relb(op0, 2)); break; + case 0x11:sprintf(t, "tcall 1"); break; + case 0x12:sprintf(t, "clr0 $%0.3x", opdp0); break; + case 0x13:sprintf(t, "bbc0 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0x14:sprintf(t, "or a,$%0.3x+x", opdp0); break; + case 0x15:sprintf(t, "or a,$%0.4x+x", opw); break; + case 0x16:sprintf(t, "or a,$%0.4x+y", opw); break; + case 0x17:sprintf(t, "or a,($%0.3x)+y", opdp0); break; + case 0x18:sprintf(t, "or $%0.3x,#$%0.2x", opdp1, op0); break; + case 0x19:sprintf(t, "or (x),(y)"); break; + case 0x1a:sprintf(t, "decw $%0.3x", opdp0); break; + case 0x1b:sprintf(t, "asl $%0.3x+x", opdp0); break; + case 0x1c:sprintf(t, "asl a"); break; + case 0x1d:sprintf(t, "dec x"); break; + case 0x1e:sprintf(t, "cmp x,$%0.4x", opw); break; + case 0x1f:sprintf(t, "jmp ($%0.4x+x)", opw); break; + case 0x20:sprintf(t, "clrp"); break; + case 0x21:sprintf(t, "tcall 2"); break; + case 0x22:sprintf(t, "set1 $%0.3x", opdp0); break; + case 0x23:sprintf(t, "bbs1 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0x24:sprintf(t, "and a,$%0.3x", opdp0); break; + case 0x25:sprintf(t, "and a,$%0.4x", opw); break; + case 0x26:sprintf(t, "and a,(x)"); break; + case 0x27:sprintf(t, "and a,($%0.3x+x)", opdp0); break; + case 0x28:sprintf(t, "and a,#$%0.2x", op0); break; + case 0x29:sprintf(t, "and $%0.3x,$%0.3x", opdp1, opdp0); break; + case 0x2a:sprintf(t, "or1 c,!$%0.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0x2b:sprintf(t, "rol $%0.3x", opdp0); break; + case 0x2c:sprintf(t, "rol $%0.4x", opw); break; + case 0x2d:sprintf(t, "push a"); break; + case 0x2e:sprintf(t, "cbne $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0x2f:sprintf(t, "bra $%0.4x", __relb(op0, 2)); break; + case 0x30:sprintf(t, "bmi $%0.4x", __relb(op0, 2)); break; + case 0x31:sprintf(t, "tcall 3"); break; + case 0x32:sprintf(t, "clr1 $%0.3x", opdp0); break; + case 0x33:sprintf(t, "bbc1 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0x34:sprintf(t, "and a,$%0.3x+x", opdp0); break; + case 0x35:sprintf(t, "and a,$%0.4x+x", opw); break; + case 0x36:sprintf(t, "and a,$%0.4x+y", opw); break; + case 0x37:sprintf(t, "and a,($%0.3x)+y", opdp0); break; + case 0x38:sprintf(t, "and $%0.3x,#$%0.2x", opdp1, op0); break; + case 0x39:sprintf(t, "and (x),(y)"); break; + case 0x3a:sprintf(t, "incw $%0.3x", opdp0); break; + case 0x3b:sprintf(t, "rol $%0.3x+x", opdp0); break; + case 0x3c:sprintf(t, "rol a"); break; + case 0x3d:sprintf(t, "inc x"); break; + case 0x3e:sprintf(t, "cmp x,$%0.3x", opdp0); break; + case 0x3f:sprintf(t, "call $%0.4x", opw); break; + case 0x40:sprintf(t, "setp"); break; + case 0x41:sprintf(t, "tcall 4"); break; + case 0x42:sprintf(t, "set2 $%0.3x", opdp0); break; + case 0x43:sprintf(t, "bbs2 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0x44:sprintf(t, "eor a,$%0.3x", opdp0); break; + case 0x45:sprintf(t, "eor a,$%0.4x", opw); break; + case 0x46:sprintf(t, "eor a,(x)"); break; + case 0x47:sprintf(t, "eor a,($%0.3x+x)", opdp0); break; + case 0x48:sprintf(t, "eor a,#$%0.2x", op0); break; + case 0x49:sprintf(t, "eor $%0.3x,$%0.3x", opdp1, opdp0); break; + case 0x4a:sprintf(t, "and1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0x4b:sprintf(t, "lsr $%0.3x", opdp0); break; + case 0x4c:sprintf(t, "lsr $%0.4x", opw); break; + case 0x4d:sprintf(t, "push x"); break; + case 0x4e:sprintf(t, "tclr $%0.4x,a", opw); break; + case 0x4f:sprintf(t, "pcall $ff%0.2x", op0); break; + case 0x50:sprintf(t, "bvc $%0.4x", __relb(op0, 2)); break; + case 0x51:sprintf(t, "tcall 5"); break; + case 0x52:sprintf(t, "clr2 $%0.3x", opdp0); break; + case 0x53:sprintf(t, "bbc2 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0x54:sprintf(t, "eor a,$%0.3x+x", opdp0); break; + case 0x55:sprintf(t, "eor a,$%0.4x+x", opw); break; + case 0x56:sprintf(t, "eor a,$%0.4x+y", opw); break; + case 0x57:sprintf(t, "eor a,($%0.3x)+y", opdp0); break; + case 0x58:sprintf(t, "eor $%0.3x,#$%0.2x", opdp1, op0); break; + case 0x59:sprintf(t, "eor (x),(y)"); break; + case 0x5a:sprintf(t, "cmpw ya,$%0.3x", opdp0); break; + case 0x5b:sprintf(t, "lsr $%0.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,$%0.4x", opw); break; + case 0x5f:sprintf(t, "jmp $%0.4x", opw); break; + case 0x60:sprintf(t, "clrc"); break; + case 0x61:sprintf(t, "tcall 6"); break; + case 0x62:sprintf(t, "set3 $%0.3x", opdp0); break; + case 0x63:sprintf(t, "bbs3 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0x64:sprintf(t, "cmp a,$%0.3x", opdp0); break; + case 0x65:sprintf(t, "cmp a,$%0.4x", opw); break; + case 0x66:sprintf(t, "cmp a,(x)"); break; + case 0x67:sprintf(t, "cmp a,($%0.3x+x)", opdp0); break; + case 0x68:sprintf(t, "cmp a,#$%0.2x", op0); break; + case 0x69:sprintf(t, "cmp $%0.3x,$%0.3x", opdp1, opdp0); break; + case 0x6a:sprintf(t, "and1 c,!$%0.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0x6b:sprintf(t, "ror $%0.3x", opdp0); break; + case 0x6c:sprintf(t, "ror $%0.4x", opw); break; + case 0x6d:sprintf(t, "push y"); break; + case 0x6e:sprintf(t, "dbnz $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0x6f:sprintf(t, "ret"); break; + case 0x70:sprintf(t, "bvs $%0.4x", __relb(op0, 2)); break; + case 0x71:sprintf(t, "tcall 7"); break; + case 0x72:sprintf(t, "clr3 $%0.3x", opdp0); break; + case 0x73:sprintf(t, "bbc3 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0x74:sprintf(t, "cmp a,$%0.3x+x", opdp0); break; + case 0x75:sprintf(t, "cmp a,$%0.4x+x", opw); break; + case 0x76:sprintf(t, "cmp a,$%0.4x+y", opw); break; + case 0x77:sprintf(t, "cmp a,($%0.3x)+y", opdp0); break; + case 0x78:sprintf(t, "cmp $%0.3x,#$%0.2x", opdp1, op0); break; + case 0x79:sprintf(t, "cmp (x),(y)"); break; + case 0x7a:sprintf(t, "addw ya,$%0.3x", opdp0); break; + case 0x7b:sprintf(t, "ror $%0.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,$%0.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 $%0.3x", opdp0); break; + case 0x83:sprintf(t, "bbs4 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0x84:sprintf(t, "adc a,$%0.3x", opdp0); break; + case 0x85:sprintf(t, "adc a,$%0.4x", opw); break; + case 0x86:sprintf(t, "adc a,(x)"); break; + case 0x87:sprintf(t, "adc a,($%0.3x+x)", opdp0); break; + case 0x88:sprintf(t, "adc a,#$%0.2x", op0); break; + case 0x89:sprintf(t, "adc $%0.3x,$%0.3x", opdp1, opdp0); break; + case 0x8a:sprintf(t, "eor1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0x8b:sprintf(t, "dec $%0.3x", opdp0); break; + case 0x8c:sprintf(t, "dec $%0.4x", opw); break; + case 0x8d:sprintf(t, "mov y,#$%0.2x", op0); break; + case 0x8e:sprintf(t, "pop p"); break; + case 0x8f:sprintf(t, "mov $%0.3x,#$%0.2x", opdp1, op0); break; + case 0x90:sprintf(t, "bcc $%0.4x", __relb(op0, 2)); break; + case 0x91:sprintf(t, "tcall 9"); break; + case 0x92:sprintf(t, "clr4 $%0.3x", opdp0); break; + case 0x93:sprintf(t, "bbc4 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0x94:sprintf(t, "adc a,$%0.3x+x", opdp0); break; + case 0x95:sprintf(t, "adc a,$%0.4x+x", opw); break; + case 0x96:sprintf(t, "adc a,$%0.4x+y", opw); break; + case 0x97:sprintf(t, "adc a,($%0.3x)+y", opdp0); break; + case 0x98:sprintf(t, "adc $%0.3x,#$%0.2x", opdp1, op0); break; + case 0x99:sprintf(t, "adc (x),(y)"); break; + case 0x9a:sprintf(t, "subw ya,$%0.3x", opdp0); break; + case 0x9b:sprintf(t, "dec $%0.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 $%0.3x", opdp0); break; + case 0xa3:sprintf(t, "bbs5 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0xa4:sprintf(t, "sbc a,$%0.3x", opdp0); break; + case 0xa5:sprintf(t, "sbc a,$%0.4x", opw); break; + case 0xa6:sprintf(t, "sbc a,(x)"); break; + case 0xa7:sprintf(t, "sbc a,($%0.3x+x)", opdp0); break; + case 0xa8:sprintf(t, "sbc a,#$%0.2x", op0); break; + case 0xa9:sprintf(t, "sbc $%0.3x,$%0.3x", opdp1, opdp0); break; + case 0xaa:sprintf(t, "mov1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0xab:sprintf(t, "inc $%0.3x", opdp0); break; + case 0xac:sprintf(t, "inc $%0.4x", opw); break; + case 0xad:sprintf(t, "cmp y,#$%0.2x", op0); break; + case 0xae:sprintf(t, "pop a"); break; + case 0xaf:sprintf(t, "mov (x)+,a"); break; + case 0xb0:sprintf(t, "bcs $%0.4x", __relb(op0, 2)); break; + case 0xb1:sprintf(t, "tcall 11"); break; + case 0xb2:sprintf(t, "clr5 $%0.3x", opdp0); break; + case 0xb3:sprintf(t, "bbc5 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0xb4:sprintf(t, "sbc a,$%0.3x+x", opdp0); break; + case 0xb5:sprintf(t, "sbc a,$%0.4x+x", opw); break; + case 0xb6:sprintf(t, "sbc a,$%0.4x+y", opw); break; + case 0xb7:sprintf(t, "sbc a,($%0.3x)+y", opdp0); break; + case 0xb8:sprintf(t, "sbc $%0.3x,#$%0.2x", opdp1, op0); break; + case 0xb9:sprintf(t, "sbc (x),(y)"); break; + case 0xba:sprintf(t, "movw ya,$%0.3x", opdp0); break; + case 0xbb:sprintf(t, "inc $%0.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 $%0.3x", opdp0); break; + case 0xc3:sprintf(t, "bbs6 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0xc4:sprintf(t, "mov $%0.3x,a", opdp0); break; + case 0xc5:sprintf(t, "mov $%0.4x,a", opw); break; + case 0xc6:sprintf(t, "mov (x),a"); break; + case 0xc7:sprintf(t, "mov ($%0.3x+x),a", opdp0); break; + case 0xc8:sprintf(t, "cmp x,#$%0.2x", op0); break; + case 0xc9:sprintf(t, "mov $%0.4x,x", opw); break; + case 0xca:sprintf(t, "mov1 $%0.4x:%d,c", opw & 0x1fff, opw >> 13); break; + case 0xcb:sprintf(t, "mov $%0.3x,y", opdp0); break; + case 0xcc:sprintf(t, "mov $%0.4x,y", opw); break; + case 0xcd:sprintf(t, "mov x,#$%0.2x", op0); break; + case 0xce:sprintf(t, "pop x"); break; + case 0xcf:sprintf(t, "mul ya"); break; + case 0xd0:sprintf(t, "bne $%0.4x", __relb(op0, 2)); break; + case 0xd1:sprintf(t, "tcall 13"); break; + case 0xd2:sprintf(t, "clr6 $%0.3x", opdp0); break; + case 0xd3:sprintf(t, "bbc6 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0xd4:sprintf(t, "mov $%0.3x+x,a", opdp0); break; + case 0xd5:sprintf(t, "mov $%0.4x+x,a", opw); break; + case 0xd6:sprintf(t, "mov $%0.4x+y,a", opw); break; + case 0xd7:sprintf(t, "mov ($%0.3x)+y,a", opdp0); break; + case 0xd8:sprintf(t, "mov $%0.3x,x", opdp0); break; + case 0xd9:sprintf(t, "mov $%0.3x+y,x", opdp0); break; + case 0xda:sprintf(t, "movw $%0.3x,ya", opdp0); break; + case 0xdb:sprintf(t, "mov $%0.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 $%0.3x+x,$%0.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 $%0.3x", opdp0); break; + case 0xe3:sprintf(t, "bbs7 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0xe4:sprintf(t, "mov a,$%0.3x", opdp0); break; + case 0xe5:sprintf(t, "mov a,$%0.4x", opw); break; + case 0xe6:sprintf(t, "mov a,(x)"); break; + case 0xe7:sprintf(t, "mov a,($%0.3x+x)", opdp0); break; + case 0xe8:sprintf(t, "mov a,#$%0.2x", op0); break; + case 0xe9:sprintf(t, "mov x,$%0.4x", opw); break; + case 0xea:sprintf(t, "not1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0xeb:sprintf(t, "mov y,$%0.3x", opdp0); break; + case 0xec:sprintf(t, "mov y,$%0.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 $%0.4x", __relb(op0, 2)); break; + case 0xf1:sprintf(t, "tcall 15"); break; + case 0xf2:sprintf(t, "clr7 $%0.3x", opdp0); break; + case 0xf3:sprintf(t, "bbc7 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break; + case 0xf4:sprintf(t, "mov a,$%0.3x+x", opdp0); break; + case 0xf5:sprintf(t, "mov a,$%0.4x+x", opw); break; + case 0xf6:sprintf(t, "mov a,$%0.4x+y", opw); break; + case 0xf7:sprintf(t, "mov a,($%0.3x)+y", opdp0); break; + case 0xf8:sprintf(t, "mov x,$%0.3x", opdp0); break; + case 0xf9:sprintf(t, "mov x,$%0.3x+y", opdp0); break; + case 0xfa:sprintf(t, "mov $%0.3x,$%0.3x", opdp1, opdp0); break; + case 0xfb:sprintf(t, "mov y,$%0.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,$%0.4x", __relb(op0, 2)); break; + case 0xff:sprintf(t, "stop"); break; + } + t[strlen(t)] = ' '; + strcat(s, t); + + sprintf(t, "A:%0.2x X:%0.2x Y:%0.2x SP:01%0.2x YA:%0.4x ", + regs.a, regs.x, regs.y, regs.sp, 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/src/apu/iplrom.h b/src/apu/iplrom.h new file mode 100644 index 00000000..84cb6441 --- /dev/null +++ b/src/apu/iplrom.h @@ -0,0 +1,48 @@ +//This is the IPLROM for the SPC700 coprocessor. +//This array is *read-only*. The SPC700 does not +//allow writing to the IPLROM, all writes are +//instead mapped to the extended SPC700 RAM region, +//accessible when $f1 bit 7 is clear. +//If you use this buffer directly, make sure not +//to write to it, as this will break other APU +//implementations that attempt to use this buffer. + +#ifdef _APU_IPLROM +const uint8 spc700_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) +}; +#else +extern const uint8 spc700_iplrom[64]; +#endif diff --git a/src/base.h b/src/base.h index 0be99a9b..98efb23d 100644 --- a/src/base.h +++ b/src/base.h @@ -1,3 +1,4 @@ +#include #include "lib/libbase.h" //structs diff --git a/src/clock/bclock/bclock.cpp b/src/clock/bclock/bclock.cpp deleted file mode 100644 index 4c38f5d9..00000000 --- a/src/clock/bclock/bclock.cpp +++ /dev/null @@ -1,201 +0,0 @@ -#include "../../base.h" - -void bClock::frameskip_update_status() { - if(frameskip.changed == true) { - frameskip.changed = false; - frameskip.count = frameskip.new_count; - frameskip.pos = 0; - } else { - frameskip.pos++; - frameskip.pos %= (frameskip.count + 1); - } - - frameskip.notify_ppu = (frameskip.pos == 0)?true:false; -} - -void bClock::dram_refresh_test() { - if(cc1.dram_refreshed == false && status.hcycles >= cc1.dram_refresh_pos) { - cc1.dram_refreshed = true; - - if(status.interlace != false || status.interlace_field != 1 || status.vcounter != 240) { - if(cc1.dram_refresh_pos == 534) { - cc1.dram_refresh_pos = 538; - } else { //cc1.dram_refresh_pos == 538 - cc1.dram_refresh_pos = 534; - } - } - - cc1.pos += 40; - cc1.frame_pos += 40; - status.hcycles += 40; - } -} - -/* - all scanlines are 1364 cycles long, except scanline 240 - on non-interlace odd-frames, which is 1360 cycles long. - interlace mode has 525 scanlines: 263 on the even frame, - and 262 on the odd. - non-interlace mode has 524 scanlines: 262 scanlines on - both even and odd frames. - - cycles per frame: - 263 * 1364 = 358732 - 262 * 1364 = 357368 - 262 * 1364 - 4 = 357364 -*/ -void bClock::inc_vcounter() { - status.hcycles -= cc1.line_cycles; - - status.vcounter++; - if(status.vcounter >= cc1.frame_lines) { - frameskip_update_status(); - - cc1.frame_pos -= cc1.frame_cycles; - status.vcounter = 0; - status.interlace_field ^= 1; - if(status.interlace == true) { - if(status.interlace_field == 0) { - cc1.frame_cycles = 263 * 1364; - cc1.frame_lines = 263; - } else { - cc1.frame_cycles = 262 * 1364; - cc1.frame_lines = 262; - } - } else { - if(status.interlace_field == 0) { - cc1.frame_cycles = 262 * 1364; - cc1.frame_lines = 262; - } else { - cc1.frame_cycles = (262 * 1364) - 4; - cc1.frame_lines = 262; - } - } - signal_frame = true; - } - - if(status.interlace == false && status.interlace_field == 1 && status.vcounter == 240) { - cc1.line_cycles = 1360; - } else { - cc1.line_cycles = 1364; - } - - cc1.dram_refreshed = false; - signal_scanline = true; -} - -/* - all dots are 4 cycles long, except dots 322 and 326. dots 322 and 326 - are 6 cycles long. this holds true for all scanlines except scanline - 240 on non-interlace odd frames. the reason for this is because this - scanline is only 1360 cycles long, instead of 1364 like all other - scanlines. - this makes the effective range of hscan_pos 0-339 at all times. - dot 322 range = { 1288, 1290, 1292 } - dot 326 range = { 1306, 1308, 1310 } -*/ -void bClock::sync() { -uint32 new_cycles, cycles; - new_cycles = cc1.pos - cc1.last_pos; - while(new_cycles) { - if(new_cycles > 40) { - cycles = 40; - new_cycles -= 40; - } else { - cycles = new_cycles; - new_cycles = 0; - } - - status.hcycles += cycles; - cc1.frame_pos += cycles; - dram_refresh_test(); - if(status.hcycles >= cc1.line_cycles) { - inc_vcounter(); - } - } - - if(status.interlace == false && status.interlace_field == 1 && status.vcounter == 240) { - status.hcounter = status.hcycles >> 2; - } else { - //1288 = 322 * 4, 1306 = 326 * 4 + 2 - status.hcounter = (status.hcycles - ((status.hcycles > 1288) << 1) - ((status.hcycles > 1306) << 1)) >> 2; - } - - cc1.last_pos = cc1.pos; - if(cc1.pos > cc1.frequency) { - cc1.pos -= cc1.frequency; - cc1.last_pos -= cc1.frequency; - } -} - -void bClock::set_frameskip(uint8 fs) { - frameskip.changed = true; - frameskip.new_count = fs; -} - -void bClock::power() { - reset(); -} - -void bClock::reset() { -//upon SNES reset, start at scanline 0 non-interlace - cc1.frame_cycles = 262 * 1364; - cc1.frame_lines = 262; - cc1.line_cycles = 1364; - -/* - Initial latch values for $213c/$213d - 0035:0000 (53.0 -> 212) [lda $2137] - 0038:0000 (56.5 -> 226) [nop : lda $2137] -*/ - cc1.pos = 188; - cc1.last_pos = 0; - cc1.frame_pos = 0; - status.vcounter = 0; - status.hcounter = 0; - status.hcycles = 0; - - cc1.dram_refresh_pos = 538; - cc1.dram_refreshed = false; - - cc2.pos = 0; - - signal_scanline = false; - signal_frame = false; - sync(); -} - -void bClock::run() { - cpu->run(); - if(frameskip.notify_ppu == true)ppu->run(); - sync(); - - if(signal_frame == true) { - signal_frame = false; - cpu->frame(); - if(frameskip.notify_ppu == true)ppu->frame(); - } - - if(signal_scanline == true) { - signal_scanline = false; - cpu->scanline(); - if(frameskip.notify_ppu == true)ppu->scanline(); - } -} - -void bClock::add_cc1_cycles(uint32 cycles) { - cc1.pos += cycles; -} - -void bClock::add_cc2_cycles(uint32 cycles) { - cc2.pos += cycles; -} - -bClock::bClock() { - cc1.frequency = 21477272; - cc2.frequency = 24576000; - - frameskip.changed = false; - frameskip.count = 0; - frameskip.pos = 0; -} diff --git a/src/clock/bclock/bclock.h b/src/clock/bclock/bclock.h deleted file mode 100644 index 4de562e6..00000000 --- a/src/clock/bclock/bclock.h +++ /dev/null @@ -1,37 +0,0 @@ -class bClock : public Clock { -private: -struct { -bool changed, notify_ppu; -uint8 count, new_count, pos; -}frameskip; -bool signal_scanline, signal_frame; - inline void frameskip_update_status(); - inline void inc_vcounter(); - inline void dram_refresh_test(); - -public: - struct { - uint32 frequency; - uint32 pos, last_pos; - uint32 frame_cycles, frame_lines, frame_pos; - uint16 line_cycles; - bool dram_refreshed; //whether or not dram has been refreshed on this line - uint16 dram_refresh_pos; - }cc1; - struct { - uint32 frequency; - uint32 pos, last_pos; - }cc2; - - inline void set_frameskip(uint8 fs); - - inline void add_cc1_cycles(uint32 cycles); - inline void add_cc2_cycles(uint32 cycles); - inline void sync(); - inline void run(); - inline void power(); - inline void reset(); - - bClock(); - ~bClock(); -}; diff --git a/src/clock/clock.cpp b/src/clock/clock.cpp deleted file mode 100644 index 5bfc6823..00000000 --- a/src/clock/clock.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "../base.h" - -void Clock::enable_overscan(bool n) { - status.overscan = n; -} - -void Clock::enable_interlace(bool n) { - status.interlace = n; -} - -bool Clock::overscan() { - return status.overscan; -} - -bool Clock::interlace() { - return status.interlace; -} - -bool Clock::interlace_field() { - return status.interlace_field; -} - -uint16 Clock::vcounter() { - return status.vcounter; -} - -uint16 Clock::hcounter() { - return status.hcounter; -} - -uint16 Clock::hcycles() { - return status.hcycles; -} - -uint16 Clock::visible_scanlines() { - return (status.overscan)?239:224; -} - -void Clock::set_frameskip(uint8 fs) {} - -Clock::Clock() { - status.overscan = false; - status.interlace = false; - status.interlace_field = 0; - - status.vcounter = 0; - status.hcounter = 0; - status.hcycles = 0; -} diff --git a/src/clock/clock.h b/src/clock/clock.h deleted file mode 100644 index 4795c330..00000000 --- a/src/clock/clock.h +++ /dev/null @@ -1,36 +0,0 @@ -class Clock { -private: -struct { - bool overscan; - bool interlace; - bool interlace_field; - - uint16 vcounter; - uint16 hcounter; - uint16 hcycles; -}status; - -public: - virtual void enable_overscan(bool n); - virtual void enable_interlace(bool n); - virtual bool overscan(); - virtual bool interlace(); - virtual bool interlace_field(); - virtual uint16 vcounter(); - virtual uint16 hcounter(); - virtual uint16 hcycles(); - virtual uint16 visible_scanlines(); - - virtual void set_frameskip(uint8 fs); - - virtual void add_cc1_cycles(uint32 cycles) = 0; - virtual void add_cc2_cycles(uint32 cycles) = 0; - virtual void sync() = 0; - virtual void run() = 0; - virtual void power() = 0; - virtual void reset() = 0; - - Clock(); - - friend class bClock; -}; diff --git a/src/cpu/bcpu/bcpu.cpp b/src/cpu/bcpu/bcpu.cpp index 410300e2..94fe4f44 100644 --- a/src/cpu/bcpu/bcpu.cpp +++ b/src/cpu/bcpu/bcpu.cpp @@ -1,20 +1,19 @@ #include "../../base.h" -#include "bcpu_op_adc.cpp" -#include "bcpu_op_and.cpp" -#include "bcpu_op_cmp.cpp" -#include "bcpu_op_eor.cpp" -#include "bcpu_op_incdec.cpp" -#include "bcpu_op_lda.cpp" -#include "bcpu_op_misc.cpp" -#include "bcpu_op_ora.cpp" +#include "srtc.cpp" + +#include "bcpu_opfn.cpp" +#include "bcpu_op_read.cpp" +#include "bcpu_op_rmw.cpp" +#include "bcpu_op_write.cpp" #include "bcpu_op_pc.cpp" -#include "bcpu_op_sbc.cpp" -#include "bcpu_op_shift.cpp" -#include "bcpu_op_sta.cpp" -#include "bcpu_op_stack.cpp" +#include "bcpu_op_misc.cpp" + #include "bcpu_exec.cpp" #include "bcpu_mmio.cpp" +#include "bcpu_dma.cpp" + +#include "bcpu_timing.cpp" uint8 bCPU::pio_status() { return status.pio; @@ -24,7 +23,7 @@ uint8 bCPU::pio_status() { *** IRQ *** *********** cycles: - [1] pbr,pc ; io + [1] pbr,pc ; io/opcode [2] pbr,pc ; io [3] 0,s ; pbr [4] 0,s-1 ; pch @@ -34,90 +33,117 @@ cycles: [8] 0,va+1 ; aavh */ void bCPU::irq(uint16 addr) { - if(cpustate == CPUSTATE_WAI) { + if(status.cpu_state == CPUSTATE_WAI) { + status.cpu_state = CPUSTATE_RUN; regs.pc.w++; - cpustate = CPUSTATE_RUN; } - clock->add_cc1_cycles(mem_bus->speed(regs.pc)); //1 - clock->add_cc1_cycles(6); //2 - stack_write(regs.pc.b); //3 - stack_write(regs.pc.h); //4 - stack_write(regs.pc.l); //5 - stack_write(regs.p); //6 - rd.l = op_read(OPMODE_ADDR, addr); //7 - rd.h = op_read(OPMODE_ADDR, addr + 1); //8 +//GTE documentation is incorrect, first cycle +//is a memory read fetch from PBR:PC + add_cycles(mem_bus->speed(regs.pc.d)); + add_cycles(6); + stack_write(regs.pc.b); + stack_write(regs.pc.h); + stack_write(regs.pc.l); + stack_write(regs.p); + rd.l = op_read(OPMODE_ADDR, addr); + rd.h = op_read(OPMODE_ADDR, addr + 1); + regs.pc.b = 0x00; regs.pc.w = rd.w; + regs.p.i = 1; + regs.p.d = 0; - regs.p.d = 0; - regs.p.i = 1; +//let debugger know the new IRQ opcode address + snes->notify(SNES::CPU_EXEC_OPCODE_END); +} - snes->notify(SNES::CPU_EXEC_OPCODE); +bool bCPU::hdma_test() { + if(status.hdma_triggered == false) { + if(vcounter() < (overscan()?239:224) && hcounter() >= 278) { + status.hdma_triggered = true; + return true; + } + } + return false; +} + +bool bCPU::nmi_test() { + if(vcounter() >= ((overscan()?239:224) + 1) && status.nmi_triggered == false) { + if((vcounter() == ((overscan()?239:224) + 1) && hcycles() >= 12) || (vcounter() > ((overscan()?239:224) + 1))) { + status.nmi_triggered = true; + status.nmi_pin = 0; + if(status.nmi_enabled == true) { + return true; + } + } + } + return false; +} + +bool bCPU::irq_test() { +int vpos, hpos; + if(regs.p.i)return false; //no interrupt can occur with I flag set + if(status.irq_pin == 0)return false; //same as above + if(status.virq_enabled == false && status.hirq_enabled == false)return false; + +//calculate V/H positions required for IRQ to trigger + vpos = status.virq_pos; + hpos = (status.hirq_enabled) ? status.hirq_pos : 0; + +//positions that can never be latched + if(vpos == 261 && hpos == 339 && interlace() == false)return false; + if(vpos == 262 && interlace() == false)return false; + if(vpos == 262 && hpos == 339)return false; + if(vpos > 262)return false; + if(hpos > 339)return false; + + if(hpos == 0) { + hpos = 24; + } else { + hpos <<= 2; + hpos += 24; //30 - status.cycle_count; + //it should be OK to use the current line cycles/frame lines, + //as the IRQ will only trigger on the correct scanline anyway... + if(hpos >= time.line_cycles) { + hpos -= time.line_cycles; + vpos++; + if(vpos >= time.frame_lines) { + vpos = 0; + } + } + } + + if(status.virq_enabled == true && vcounter() != vpos)return false; + + if(hcycles() >= hpos && status.irq_pin == 1) { + //dprintf("* vpos=%3d,hpos=%4d; v=%3d,h=%4d; lc=%d,virq=%3d,hirq=%3d", + // vpos, hpos, vcounter(), hcycles(), status.cycle_count, status.virq_pos, status.hirq_pos); + status.irq_triggered = true; + status.irq_pin = 0; + return true; + } + + return false; } void bCPU::run() { -uint16 v, h, hc, vs; - v = clock->vcounter(); - h = clock->hcounter(); - hc = clock->hcycles(); - vs = clock->visible_scanlines(); - -//HDMA test - if(v < vs && h >= 278) { - if(status.hdma_triggered == false) { - status.hdma_triggered = true; - dma->hdma_run(); - return; - } - } - - switch(cpustate) { + switch(status.cpu_state) { + case CPUSTATE_DMA: + dma_run(); + break; case CPUSTATE_RUN: case CPUSTATE_WAI: - //NMI test - if(v >= (vs + 1) && status.nmi_triggered == false) { - if((v == (vs + 1) && hc >= 12) || (v > (vs + 1))) { - status.nmi_triggered = true; - status.nmi_pin = 0; - if(status.nmi_enabled == true) { - irq(0xffea); - return; - } - } + if(nmi_test() == true) { + irq(0xffea); + break; } - - //IRQ test - if(!regs.p.i) { - if(status.virq_enabled == true && status.hirq_enabled == true) { - if(v == status.virq_pos && h >= status.hirq_pos && status.irq_pin == 1) { - status.irq_triggered = true; - status.irq_pin = 0; - irq(0xffee); - return; - } - } else if(status.virq_enabled == true) { - if(v == status.virq_pos && status.irq_pin == 1) { - status.irq_triggered = true; - status.irq_pin = 0; - irq(0xffee); - return; - } - } else if(status.hirq_enabled == true) { - if(h >= status.hirq_pos && status.irq_pin == 1) { - status.irq_triggered = true; - status.irq_pin = 0; - irq(0xffee); - return; - } - } + if(irq_test() == true) { + irq(0xffee); + break; } - exec_opcode(); break; - case CPUSTATE_DMA: - dma->run(); - break; case CPUSTATE_STP: exec_opcode(); break; @@ -125,62 +151,25 @@ uint16 v, h, hc, vs; } void bCPU::scanline() { -uint16 v = clock->vcounter(); status.hdma_triggered = false; - if(v == 225 && status.auto_joypad_poll == true) { + if(vcounter() == 225 && status.auto_joypad_poll == true) { snes->poll_input(); -//When the SNES auto-polls the joypads, it writes 1, then 0 to -//$4016, then reads from each 16 times to get the joypad state -//information. As a result, the joypad read positions are set -//to 16 after such a poll. Position 16 is the controller -//connected status bit. + //When the SNES auto-polls the joypads, it writes 1, then 0 to + //$4016, then reads from each 16 times to get the joypad state + //information. As a result, the joypad read positions are set + //to 16 after such a poll. Position 16 is the controller + //connected status bit. status.joypad1_read_pos = 16; } + if(status.virq_enabled == false) { status.irq_pin = 1; } } void bCPU::frame() { - status.hdma_triggered = false; - - status.nmi_triggered = false; - status.r4210_read = false; - - status.irq_triggered = false; - status.irq_pin = 1; - - dma->hdma_initialize(); -} - -void bCPU::power() { - regs.a = regs.x = regs.y = 0x0000; - regs.s = 0x01ff; - reset(); -} - -void bCPU::reset() { -/* reset vector location */ - regs.pc = mem_bus->read(0xfffc) | (mem_bus->read(0xfffd) << 8); - -/* registers are not fully reset by SNES */ - regs.x.h = 0x00; - regs.y.h = 0x00; - regs.s.h = 0x01; - regs.d = 0x0000; - regs.db = 0x00; - regs.p = 0x34; - regs.e = 1; - - cpustate = CPUSTATE_RUN; - - dma->reset(); - mmio_reset(); - - optbl = optbl_e; - - status.hdma_triggered = false; + hdma_initialize(); status.nmi_triggered = false; status.nmi_pin = 1; @@ -190,113 +179,164 @@ void bCPU::reset() { status.irq_pin = 1; } +void bCPU::power() { + srtc_power(); + + regs.a = regs.x = regs.y = 0x0000; + regs.s = 0x01ff; + reset(); +} + +void bCPU::reset() { + srtc_reset(); + + frame(); + +//reset vector location + regs.pc = mem_bus->read(0xfffc) | (mem_bus->read(0xfffd) << 8); + +//registers are not fully reset by SNES + regs.x.h = 0x00; + regs.y.h = 0x00; + regs.s.h = 0x01; + regs.d = 0x0000; + regs.db = 0x00; + regs.p = 0x34; + regs.e = 1; + + time_reset(); + mmio_reset(); + dma_reset(); + + status.cpu_state = CPUSTATE_RUN; + + status.hdma_triggered = false; + + status.nmi_triggered = false; + status.nmi_pin = 1; + status.r4210_read = false; + + status.irq_triggered = false; + status.irq_pin = 1; + + apu_port[0] = 0x00; + apu_port[1] = 0x00; + apu_port[2] = 0x00; + apu_port[3] = 0x00; +} + +uint8 bCPU::port_read(uint8 port) { + return apu_port[port & 3]; +} + +void bCPU::port_write(uint8 port, uint8 value) { + apu_port[port & 3] = value; +} + void bCPU::cpu_c2() { if(regs.d.l != 0x00) { - clock->add_cc1_cycles(6); + status.cycle_count = 6; + cycle_edge(); + add_cycles(6); } } -void bCPU::cpu_c4(uint16 a, uint16 b) { - if(((a & 0xff00) != (b & 0xff00)) || !regs.p.x) { - clock->add_cc1_cycles(6); +void bCPU::cpu_c4(uint16 x, uint16 y) { + if(!regs.p.x && (x & 0xff00) != (y & 0xff00)) { + status.cycle_count = 6; + cycle_edge(); + add_cycles(6); } } -void bCPU::cpu_c6(uint16 a) { - if(regs.e) { - if((regs.pc.w & 0xff00) != (a & 0xff00)) { - clock->add_cc1_cycles(6); - } +void bCPU::cpu_c6(uint16 addr) { + if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) { + status.cycle_count = 6; + cycle_edge(); + add_cycles(6); } } void bCPU::cpu_io() { - clock->add_cc1_cycles(6); + status.cycle_count = 6; + cycle_edge(); + add_cycles(6); +} + +uint8 bCPU::mem_read(uint32 addr) { +uint8 r; + status.cycle_count = mem_bus->speed(addr); + cycle_edge(); + add_cycles(2); + r = mem_bus->read(addr); + add_cycles(status.cycle_count - 2); + return r; +} + +void bCPU::mem_write(uint32 addr, uint8 value) { + status.cycle_count = mem_bus->speed(addr); + cycle_edge(); + add_cycles(6); + mem_bus->write(addr, value); + add_cycles(status.cycle_count - 6); +} + +uint32 bCPU::op_addr(uint8 mode, uint32 addr) { + switch(mode) { + case OPMODE_ADDR: + addr &= 0xffff; + break; + case OPMODE_LONG: + addr &= 0xffffff; + break; + case OPMODE_DBR: + addr &= 0xffffff; + addr = (regs.db << 16) + addr; + break; + case OPMODE_PBR: + addr &= 0xffff; + addr = (regs.pc.b << 16) | addr; + break; + case OPMODE_DP: + addr &= 0xffff; + addr = (regs.d + addr) & 0xffff; + break; + case OPMODE_SP: + addr &= 0xffff; + addr = (regs.s + addr) & 0xffff; + break; + } + return addr; } uint8 bCPU::op_read() { uint8 r; - r = mem_bus->read(regs.pc); - clock->add_cc1_cycles(mem_bus->speed(regs.pc)); + r = mem_read(regs.pc.d); regs.pc.w++; return r; } uint8 bCPU::op_read(uint8 mode, uint32 addr) { -uint8 r; - switch(mode) { - case OPMODE_ADDR: - addr &= 0xffff; - break; - case OPMODE_LONG: - addr &= 0xffffff; - break; - case OPMODE_DBR: - addr &= 0xffffff; - addr = (regs.db << 16) + addr; - break; - case OPMODE_PBR: - addr &= 0xffff; - addr = (regs.pc.b << 16) | addr; - break; - case OPMODE_DP: - addr &= 0xffff; - addr = (regs.d + addr) & 0xffff; - break; - case OPMODE_SP: - addr &= 0xffff; - addr = (regs.s + addr) & 0xffff; - break; - } - r = mem_bus->read(addr); - clock->add_cc1_cycles(mem_bus->speed(addr)); - return r; + addr = op_addr(mode, addr); + return mem_read(addr); } void bCPU::op_write(uint8 mode, uint32 addr, uint8 value) { - switch(mode) { - case OPMODE_ADDR: - addr &= 0xffff; - break; - case OPMODE_LONG: - addr &= 0xffffff; - break; - case OPMODE_DBR: - addr &= 0xffffff; - addr = (regs.db << 16) + addr; - break; - case OPMODE_PBR: - addr &= 0xffff; - addr = (regs.pc.b << 16) | addr; - break; - case OPMODE_DP: - addr &= 0xffff; - addr = (regs.d + addr) & 0xffff; - break; - case OPMODE_SP: - addr &= 0xffff; - addr = (regs.s + addr) & 0xffff; - break; - } - mem_bus->write(addr, value); - clock->add_cc1_cycles(mem_bus->speed(addr)); + addr = op_addr(mode, addr); + mem_write(addr, value); } uint8 bCPU::stack_read() { -byte r; if(regs.e) { regs.s.l++; } else { regs.s.w++; } - r = mem_bus->read(regs.s); - clock->add_cc1_cycles(mem_bus->speed(regs.s)); - return r; + return mem_read(regs.s); } void bCPU::stack_write(uint8 value) { - mem_bus->write(regs.s, value); - clock->add_cc1_cycles(mem_bus->speed(regs.s)); + mem_write(regs.s, value); if(regs.e) { regs.s.l--; } else { @@ -305,7 +345,7 @@ void bCPU::stack_write(uint8 value) { } bCPU::bCPU() { - dma = new bDMA(this); + time_init(); mmio = new bCPUMMIO(this); init_op_tables(); @@ -313,5 +353,4 @@ bCPU::bCPU() { bCPU::~bCPU() { delete(mmio); - delete(dma); } diff --git a/src/cpu/bcpu/bcpu.h b/src/cpu/bcpu/bcpu.h index 4570bf8a..c398160d 100644 --- a/src/cpu/bcpu/bcpu.h +++ b/src/cpu/bcpu/bcpu.h @@ -1,79 +1,55 @@ class bCPU; -class bDMA { -public: -bCPU *cpu; -struct { -//$420b - bool active; -//$420c - bool hdma_active; -//$43x0 - bool direction; - bool hdma_indirect; - int8 incmode; - bool fixedxfer; - uint8 xfermode; -//$43x1 - uint8 destaddr; -//$43x2-$43x4 - uint32 srcaddr; -//$43x5-$43x6 - uint16 xfersize; -//$43x7 - uint8 hdma_indirect_bank; - -//hdma-specific - bool hdma_first_line; - bool hdma_repeat; - uint16 hdma_line_counter; - uint32 hdma_address, hdma_iaddress; - bool hdma_completed; -}channel[8]; - void hdma_write(uint8 i, uint8 l, uint8 x); - void hdma_run(); - void hdma_initialize(); - void run(); - void reset(); - uint16 dma_cputommio(uint8 i, uint8 index); - uint16 dma_mmiotocpu(uint8 i, uint8 index); - void dma_xfer_type0(uint8 i); - void dma_xfer_type1(uint8 i); - void dma_xfer_type2(uint8 i); - void dma_xfer_type3(uint8 i); - void dma_xfer_type4(uint8 i); - void dma_xfer_type5(uint8 i); - - bDMA(bCPU *_cpu); -}; - class bCPUMMIO : public MMIO { public: bCPU *cpu; - uint8 read (uint32 addr); - void write(uint32 addr, uint8 value); + inline uint8 read (uint32 addr); + inline void write(uint32 addr, uint8 value); bCPUMMIO(bCPU *_cpu); }; class bCPU : public CPU { private: typedef void (bCPU::*op)(); -op *optbl, optbl_e[256], optbl_MX[256], optbl_Mx[256], optbl_mX[256], optbl_mx[256]; +op optbl[256]; public: -enum { CPUSTATE_RUN = 0, CPUSTATE_DMA, CPUSTATE_WAI, CPUSTATE_STP }; -uint8 cpustate; +#include "srtc.h" +#include "bcpu_timing.h" + +uint8 apu_port[4]; + inline uint8 port_read (uint8 port); + inline void port_write(uint8 port, uint8 value); + +enum { + OPMODE_ADDR = 1, OPMODE_LONG = 2, + OPMODE_DBR = 3, OPMODE_PBR = 4, + OPMODE_DP = 5, OPMODE_SP = 6 +}; -bDMA *dma; - enum { - OPMODE_ADDR = 1, OPMODE_LONG = 2, - OPMODE_DBR = 3, OPMODE_PBR = 4, - OPMODE_DP = 5, OPMODE_SP = 6 - }; CPUReg24 aa, rd; uint8 dp, sp; +enum { + CPUSTATE_RUN = 0, + CPUSTATE_WAI, + CPUSTATE_STP, + CPUSTATE_DMA +}; + +enum { + DMASTATE_STOP = 0, + DMASTATE_INIT, + DMASTATE_DMASYNC, + DMASTATE_RUN, + DMASTATE_CPUSYNC +}; + struct { + uint8 cpu_state, cycle_count; + + uint8 dma_state; + uint32 dma_cycle_count; bool hdma_triggered; bool nmi_triggered; @@ -82,6 +58,7 @@ struct { bool irq_triggered; bool irq_pin; + uint16 virq_trigger, hirq_trigger; //$2181-$2183 uint32 wram_addr; @@ -113,13 +90,66 @@ struct { uint16 r4216; }status; - uint8 pio_status(); - void irq(uint16 addr); - void run(); - void scanline(); - void frame(); - void power(); - void reset(); +struct { +//$420b + bool active; +//$420c + bool hdma_active; +//$43x0 + uint8 dmap; + bool direction; + bool hdma_indirect; + int8 incmode; + bool fixedxfer; + uint8 xfermode; +//$43x1 + uint8 destaddr; +//$43x2-$43x4 + uint32 srcaddr; +//$43x5-$43x6 + uint16 xfersize; +//$43x7 + uint8 hdma_indirect_bank; +//$43x8-$43x9 + uint32 hdma_taddr; +//$43xa + uint8 hdma_line_counter; +//$43xb/$43xf + uint8 hdma_unknown; + +//hdma-specific + bool hdma_first_line; + bool hdma_repeat; + uint32 hdma_itaddr; + bool hdma_completed; +}channel[8]; + + inline bool hdma_test(); + inline bool nmi_test(); + inline bool irq_test(); + inline void irq(uint16 addr); + + inline uint8 pio_status(); + inline void run(); + inline void scanline(); + inline void frame(); + inline void power(); + inline void reset(); + +//dma commands + inline void dma_run(); + inline void hdma_run(); + inline void hdma_initialize(); + inline uint16 dma_cputommio(uint8 i, uint8 index); + inline uint16 dma_mmiotocpu(uint8 i, uint8 index); + inline void dma_xfer_type0(uint8 i); + inline void dma_xfer_type1(uint8 i); + inline void dma_xfer_type2(uint8 i); + inline void dma_xfer_type3(uint8 i); + inline void dma_xfer_type4(uint8 i); + inline void dma_xfer_type5(uint8 i); + inline void hdma_write(uint8 i, uint8 l, uint8 x); + inline void dma_reset(); //mmio commands void mmio_reset(); @@ -137,6 +167,18 @@ struct { uint8 mmio_r4217(); uint8 mmio_r4218(); uint8 mmio_r4219(); + 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 value); void mmio_w2181(uint8 value); void mmio_w2182(uint8 value); @@ -164,520 +206,76 @@ struct { void mmio_w43x5(uint8 value, uint8 i); void mmio_w43x6(uint8 value, uint8 i); void mmio_w43x7(uint8 value, uint8 i); + void mmio_w43x8(uint8 value, uint8 i); + void mmio_w43x9(uint8 value, uint8 i); + void mmio_w43xa(uint8 value, uint8 i); + void mmio_w43xb(uint8 value, uint8 i); - inline void exec_opcode(); - - inline uint8 op_read (); - inline uint8 op_read (uint8 mode, uint32 addr); - inline void op_write(uint8 mode, uint32 addr, uint8 value); - inline uint8 stack_read (); - inline void stack_write(uint8 value); +enum { CYCLE_OPREAD = 0, CYCLE_READ, CYCLE_WRITE, CYCLE_IO }; + inline void exec_opcode(); + inline void cycle_edge(); //cpu extra-cycle conditions inline void cpu_c2(); - inline void cpu_c4(uint16 a, uint16 b); - inline void cpu_c6(uint16 a); + inline void cpu_c4(uint16 x, uint16 y); + inline void cpu_c6(uint16 addr); inline void cpu_io(); -//opcode functions - void init_op_tables(); + inline uint8 mem_read (uint32 addr); + inline void mem_write(uint32 addr, uint8 value); + inline uint32 op_addr(uint8 mode, uint32 addr); + inline uint8 op_read(); + inline uint8 op_read(uint8 mode, uint32 addr); + inline void op_write(uint8 mode, uint32 addr, uint8 value); + inline uint8 stack_read(); + inline void stack_write(uint8 value); -//op_adc - inline void flags_adc_b(); - inline void flags_adc_w(); - void op_adc_constb(); - void op_adc_constw(); - void op_adc_addrb(); - void op_adc_addrw(); - void op_adc_addrxb(); - void op_adc_addrxw(); - void op_adc_dpb(); - void op_adc_dpw(); - void op_adc_idpb(); - void op_adc_idpw(); - void op_adc_ildpb(); - void op_adc_ildpw(); - void op_adc_longb(); - void op_adc_longw(); - void op_adc_longxb(); - void op_adc_longxw(); - void op_adc_addryb(); - void op_adc_addryw(); - void op_adc_dpxb(); - void op_adc_dpxw(); - void op_adc_idpxb(); - void op_adc_idpxw(); - void op_adc_idpyb(); - void op_adc_idpyw(); - void op_adc_ildpyb(); - void op_adc_ildpyw(); - void op_adc_srb(); - void op_adc_srw(); - void op_adc_isryb(); - void op_adc_isryw(); -//op_and - inline void flags_and_b(); - inline void flags_and_w(); - void op_and_constb(); - void op_and_constw(); - void op_and_addrb(); - void op_and_addrw(); - void op_and_addrxb(); - void op_and_addrxw(); - void op_and_dpb(); - void op_and_dpw(); - void op_and_idpb(); - void op_and_idpw(); - void op_and_ildpb(); - void op_and_ildpw(); - void op_and_longb(); - void op_and_longw(); - void op_and_longxb(); - void op_and_longxw(); - void op_and_addryb(); - void op_and_addryw(); - void op_and_dpxb(); - void op_and_dpxw(); - void op_and_idpxb(); - void op_and_idpxw(); - void op_and_idpyb(); - void op_and_idpyw(); - void op_and_ildpyb(); - void op_and_ildpyw(); - void op_and_srb(); - void op_and_srw(); - void op_and_isryb(); - void op_and_isryw(); -//op_cmp - inline void flags_cmp_b(); - inline void flags_cmp_w(); - void op_cmp_constb(); - void op_cmp_constw(); - void op_cmp_addrb(); - void op_cmp_addrw(); - void op_cmp_addrxb(); - void op_cmp_addrxw(); - void op_cmp_dpb(); - void op_cmp_dpw(); - void op_cmp_idpb(); - void op_cmp_idpw(); - void op_cmp_ildpb(); - void op_cmp_ildpw(); - void op_cmp_longb(); - void op_cmp_longw(); - void op_cmp_longxb(); - void op_cmp_longxw(); - void op_cmp_addryb(); - void op_cmp_addryw(); - void op_cmp_dpxb(); - void op_cmp_dpxw(); - void op_cmp_idpxb(); - void op_cmp_idpxw(); - void op_cmp_idpyb(); - void op_cmp_idpyw(); - void op_cmp_ildpyb(); - void op_cmp_ildpyw(); - void op_cmp_srb(); - void op_cmp_srw(); - void op_cmp_isryb(); - void op_cmp_isryw(); -//op_eor - inline void flags_eor_b(); - inline void flags_eor_w(); - void op_eor_constb(); - void op_eor_constw(); - void op_eor_addrb(); - void op_eor_addrw(); - void op_eor_addrxb(); - void op_eor_addrxw(); - void op_eor_dpb(); - void op_eor_dpw(); - void op_eor_idpb(); - void op_eor_idpw(); - void op_eor_ildpb(); - void op_eor_ildpw(); - void op_eor_longb(); - void op_eor_longw(); - void op_eor_longxb(); - void op_eor_longxw(); - void op_eor_addryb(); - void op_eor_addryw(); - void op_eor_dpxb(); - void op_eor_dpxw(); - void op_eor_idpxb(); - void op_eor_idpxw(); - void op_eor_idpyb(); - void op_eor_idpyw(); - void op_eor_ildpyb(); - void op_eor_ildpyw(); - void op_eor_srb(); - void op_eor_srw(); - void op_eor_isryb(); - void op_eor_isryw(); -//op_incdec - void op_incb(); - void op_incw(); - void op_inc_addrb(); - void op_inc_addrw(); - void op_inc_addrxb(); - void op_inc_addrxw(); - void op_inc_dpb(); - void op_inc_dpw(); - void op_inc_dpxb(); - void op_inc_dpxw(); - void op_inxb(); - void op_inxw(); - void op_inyb(); - void op_inyw(); - void op_decb(); - void op_decw(); - void op_dec_addrb(); - void op_dec_addrw(); - void op_dec_addrxb(); - void op_dec_addrxw(); - void op_dec_dpb(); - void op_dec_dpw(); - void op_dec_dpxb(); - void op_dec_dpxw(); - void op_dexb(); - void op_dexw(); - void op_deyb(); - void op_deyw(); -//op_lda - inline void flags_lda_b(); - inline void flags_lda_w(); - void op_lda_constb(); - void op_lda_constw(); - void op_lda_addrb(); - void op_lda_addrw(); - void op_lda_addrxb(); - void op_lda_addrxw(); - void op_lda_dpb(); - void op_lda_dpw(); - void op_lda_idpb(); - void op_lda_idpw(); - void op_lda_ildpb(); - void op_lda_ildpw(); - void op_lda_longb(); - void op_lda_longw(); - void op_lda_longxb(); - void op_lda_longxw(); - void op_lda_addryb(); - void op_lda_addryw(); - void op_lda_dpxb(); - void op_lda_dpxw(); - void op_lda_idpxb(); - void op_lda_idpxw(); - void op_lda_idpyb(); - void op_lda_idpyw(); - void op_lda_ildpyb(); - void op_lda_ildpyw(); - void op_lda_srb(); - void op_lda_srw(); - void op_lda_isryb(); - void op_lda_isryw(); -//op_misc - inline void flags_bit_b(); - inline void flags_bit_w(); - void op_bit_constb(); - void op_bit_constw(); - void op_bit_addrb(); - void op_bit_addrw(); - void op_bit_addrxb(); - void op_bit_addrxw(); - void op_bit_dpb(); - void op_bit_dpw(); - void op_bit_dpxb(); - void op_bit_dpxw(); - inline void flags_cpx_b(); - inline void flags_cpx_w(); - void op_cpx_constb(); - void op_cpx_constw(); - void op_cpx_addrb(); - void op_cpx_addrw(); - void op_cpx_dpb(); - void op_cpx_dpw(); - inline void flags_cpy_b(); - inline void flags_cpy_w(); - void op_cpy_constb(); - void op_cpy_constw(); - void op_cpy_addrb(); - void op_cpy_addrw(); - void op_cpy_dpb(); - void op_cpy_dpw(); - inline void flags_ldx_b(); - inline void flags_ldx_w(); - void op_ldx_constb(); - void op_ldx_constw(); - void op_ldx_addrb(); - void op_ldx_addrw(); - void op_ldx_addryb(); - void op_ldx_addryw(); - void op_ldx_dpb(); - void op_ldx_dpw(); - void op_ldx_dpyb(); - void op_ldx_dpyw(); - inline void flags_ldy_b(); - inline void flags_ldy_w(); - void op_ldy_constb(); - void op_ldy_constw(); - void op_ldy_addrb(); - void op_ldy_addrw(); - void op_ldy_addrxb(); - void op_ldy_addrxw(); - void op_ldy_dpb(); - void op_ldy_dpw(); - void op_ldy_dpxb(); - void op_ldy_dpxw(); - void op_stx_addrb(); - void op_stx_addrw(); - void op_stx_dpb(); - void op_stx_dpw(); - void op_stx_dpyb(); - void op_stx_dpyw(); - void op_sty_addrb(); - void op_sty_addrw(); - void op_sty_dpb(); - void op_sty_dpw(); - void op_sty_dpxb(); - void op_sty_dpxw(); - void op_stz_addrb(); - void op_stz_addrw(); - void op_stz_addrxb(); - void op_stz_addrxw(); - void op_stz_dpb(); - void op_stz_dpw(); - void op_stz_dpxb(); - void op_stz_dpxw(); - void op_xba(); - void op_trb_addrb(); - void op_trb_addrw(); - void op_trb_dpb(); - void op_trb_dpw(); - void op_tsb_addrb(); - void op_tsb_addrw(); - void op_tsb_dpb(); - void op_tsb_dpw(); - void op_mvn(); - void op_mvp(); - void op_brk(); - void op_cop(); - void op_stp(); - void op_wai(); - void op_xce(); - void op_nop(); - void op_wdm(); - void op_clc(); - void op_cld(); - void op_cli(); - void op_clv(); - void op_sec(); - void op_sed(); - void op_sei(); - void op_rep(); - void op_sep(); - void op_taxb(); - void op_taxw(); - void op_tayb(); - void op_tayw(); - void op_tcd(); - void op_tcs(); - void op_tdc(); - void op_tsc(); - void op_tsxb(); - void op_tsxw(); - void op_txab(); - void op_txaw(); - void op_txsb(); - void op_txsw(); - void op_txyb(); - void op_txyw(); - void op_tyab(); - void op_tyaw(); - void op_tyxb(); - void op_tyxw(); -//op_ora - inline void flags_ora_b(); - inline void flags_ora_w(); - void op_ora_constb(); - void op_ora_constw(); - void op_ora_addrb(); - void op_ora_addrw(); - void op_ora_addrxb(); - void op_ora_addrxw(); - void op_ora_dpb(); - void op_ora_dpw(); - void op_ora_idpb(); - void op_ora_idpw(); - void op_ora_ildpb(); - void op_ora_ildpw(); - void op_ora_longb(); - void op_ora_longw(); - void op_ora_longxb(); - void op_ora_longxw(); - void op_ora_addryb(); - void op_ora_addryw(); - void op_ora_dpxb(); - void op_ora_dpxw(); - void op_ora_idpxb(); - void op_ora_idpxw(); - void op_ora_idpyb(); - void op_ora_idpyw(); - void op_ora_ildpyb(); - void op_ora_ildpyw(); - void op_ora_srb(); - void op_ora_srw(); - void op_ora_isryb(); - void op_ora_isryw(); -//op_pc - 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(); - void op_jsr_iaddrx(); - void op_rtie(); - void op_rtin(); - void op_rts(); - void op_rtl(); - void op_bra(); - void op_brl(); - void op_bcc(); - void op_bcs(); - void op_bne(); - void op_beq(); - void op_bpl(); - void op_bmi(); - void op_bvc(); - void op_bvs(); -//op_sbc - inline void flags_sbc_b(); - inline void flags_sbc_w(); - void op_sbc_constb(); - void op_sbc_constw(); - void op_sbc_addrb(); - void op_sbc_addrw(); - void op_sbc_addrxb(); - void op_sbc_addrxw(); - void op_sbc_dpb(); - void op_sbc_dpw(); - void op_sbc_idpb(); - void op_sbc_idpw(); - void op_sbc_ildpb(); - void op_sbc_ildpw(); - void op_sbc_longb(); - void op_sbc_longw(); - void op_sbc_longxb(); - void op_sbc_longxw(); - void op_sbc_addryb(); - void op_sbc_addryw(); - void op_sbc_dpxb(); - void op_sbc_dpxw(); - void op_sbc_idpxb(); - void op_sbc_idpxw(); - void op_sbc_idpyb(); - void op_sbc_idpyw(); - void op_sbc_ildpyb(); - void op_sbc_ildpyw(); - void op_sbc_srb(); - void op_sbc_srw(); - void op_sbc_isryb(); - void op_sbc_isryw(); -//op_shift - void op_aslb(); - void op_aslw(); - void op_asl_addrb(); - void op_asl_addrw(); - void op_asl_addrxb(); - void op_asl_addrxw(); - void op_asl_dpb(); - void op_asl_dpw(); - void op_asl_dpxb(); - void op_asl_dpxw(); - void op_lsrb(); - void op_lsrw(); - void op_lsr_addrb(); - void op_lsr_addrw(); - void op_lsr_addrxb(); - void op_lsr_addrxw(); - void op_lsr_dpb(); - void op_lsr_dpw(); - void op_lsr_dpxb(); - void op_lsr_dpxw(); - void op_rolb(); - void op_rolw(); - void op_rol_addrb(); - void op_rol_addrw(); - void op_rol_addrxb(); - void op_rol_addrxw(); - void op_rol_dpb(); - void op_rol_dpw(); - void op_rol_dpxb(); - void op_rol_dpxw(); - void op_rorb(); - void op_rorw(); - void op_ror_addrb(); - void op_ror_addrw(); - void op_ror_addrxb(); - void op_ror_addrxw(); - void op_ror_dpb(); - void op_ror_dpw(); - void op_ror_dpxb(); - void op_ror_dpxw(); -//op_sta - void op_sta_addrb(); - void op_sta_addrw(); - void op_sta_addrxb(); - void op_sta_addrxw(); - void op_sta_dpb(); - void op_sta_dpw(); - void op_sta_idpb(); - void op_sta_idpw(); - void op_sta_ildpb(); - void op_sta_ildpw(); - void op_sta_longb(); - void op_sta_longw(); - void op_sta_longxb(); - void op_sta_longxw(); - void op_sta_addryb(); - void op_sta_addryw(); - void op_sta_dpxb(); - void op_sta_dpxw(); - void op_sta_idpxb(); - void op_sta_idpxw(); - void op_sta_idpyb(); - void op_sta_idpyw(); - void op_sta_ildpyb(); - void op_sta_ildpyw(); - void op_sta_srb(); - void op_sta_srw(); - void op_sta_isryb(); - void op_sta_isryw(); -//op_stack - void op_phab(); - void op_phaw(); - void op_phb(); - void op_phd(); - void op_phk(); - void op_php(); - void op_phxb(); - void op_phxw(); - void op_phyb(); - void op_phyw(); - void op_plab(); - void op_plaw(); - void op_plb(); - void op_pld(); - void op_plp(); - void op_plxb(); - void op_plxw(); - void op_plyb(); - void op_plyw(); - void op_pea(); - void op_pei(); - void op_per(); +//opcode functions + inline void init_op_tables(); + +//op_read + inline void op_adc_b(); + inline void op_adc_w(); + inline void op_and_b(); + inline void op_and_w(); + inline void op_bit_b(); + inline void op_bit_w(); + inline void op_cmp_b(); + inline void op_cmp_w(); + inline void op_cpx_b(); + inline void op_cpx_w(); + inline void op_cpy_b(); + inline void op_cpy_w(); + inline void op_eor_b(); + inline void op_eor_w(); + inline void op_lda_b(); + inline void op_lda_w(); + inline void op_ldx_b(); + inline void op_ldx_w(); + inline void op_ldy_b(); + inline void op_ldy_w(); + inline void op_ora_b(); + inline void op_ora_w(); + inline void op_sbc_b(); + inline void op_sbc_w(); +//op_rmw + inline void op_inc_b(); + inline void op_inc_w(); + inline void op_dec_b(); + inline void op_dec_w(); + inline void op_asl_b(); + inline void op_asl_w(); + inline void op_lsr_b(); + inline void op_lsr_w(); + inline void op_rol_b(); + inline void op_rol_w(); + inline void op_ror_b(); + inline void op_ror_w(); + inline void op_trb_b(); + inline void op_trb_w(); + inline void op_tsb_b(); + inline void op_tsb_w(); +#include "bcpu_op.h" bCPU(); ~bCPU(); diff --git a/src/cpu/bcpu/bcpu_dma.cpp b/src/cpu/bcpu/bcpu_dma.cpp new file mode 100644 index 00000000..56957dcb --- /dev/null +++ b/src/cpu/bcpu/bcpu_dma.cpp @@ -0,0 +1,241 @@ +uint16 bCPU::dma_cputommio(uint8 i, uint8 index) { +uint8 x; + x = mem_bus->read(channel[i].srcaddr); + mem_bus->write(0x2100 | ((channel[i].destaddr + index) & 0xff), x); + if(channel[i].fixedxfer == false) { + channel[i].srcaddr = (channel[i].srcaddr & 0xff0000) + ((channel[i].srcaddr + channel[i].incmode) & 0xffff); + } + add_cycles(8); + return --channel[i].xfersize; +} + +uint16 bCPU::dma_mmiotocpu(uint8 i, uint8 index) { +uint8 x; + x = mem_bus->read(0x2100 | ((channel[i].destaddr + index) & 0xff)); + mem_bus->write(channel[i].srcaddr, x); + if(channel[i].fixedxfer == false) { + channel[i].srcaddr = (channel[i].srcaddr & 0xff0000) + ((channel[i].srcaddr + channel[i].incmode) & 0xffff); + } + add_cycles(8); + return --channel[i].xfersize; +} + +void bCPU::dma_xfer_type0(uint8 i) { + if(channel[i].direction == 0) { + if(dma_cputommio(i, 0) == 0)return; + } else { + if(dma_mmiotocpu(i, 0) == 0)return; + } +} + +void bCPU::dma_xfer_type1(uint8 i) { + if(channel[i].direction == 0) { + if(dma_cputommio(i, 0) == 0)return; + if(dma_cputommio(i, 1) == 0)return; + } else { + if(dma_mmiotocpu(i, 0) == 0)return; + if(dma_mmiotocpu(i, 1) == 0)return; + } +} + +void bCPU::dma_xfer_type2(uint8 i) { + if(channel[i].direction == 0) { + if(dma_cputommio(i, 0) == 0)return; + if(dma_cputommio(i, 0) == 0)return; + } else { + if(dma_mmiotocpu(i, 0) == 0)return; + if(dma_mmiotocpu(i, 0) == 0)return; + } +} + +void bCPU::dma_xfer_type3(uint8 i) { + if(channel[i].direction == 0) { + if(dma_cputommio(i, 0) == 0)return; + if(dma_cputommio(i, 0) == 0)return; + if(dma_cputommio(i, 1) == 0)return; + if(dma_cputommio(i, 1) == 0)return; + } else { + if(dma_mmiotocpu(i, 0) == 0)return; + if(dma_mmiotocpu(i, 0) == 0)return; + if(dma_mmiotocpu(i, 1) == 0)return; + if(dma_mmiotocpu(i, 1) == 0)return; + } +} + +void bCPU::dma_xfer_type4(uint8 i) { + if(channel[i].direction == 0) { + if(dma_cputommio(i, 0) == 0)return; + if(dma_cputommio(i, 1) == 0)return; + if(dma_cputommio(i, 2) == 0)return; + if(dma_cputommio(i, 3) == 0)return; + } else { + if(dma_mmiotocpu(i, 0) == 0)return; + if(dma_mmiotocpu(i, 1) == 0)return; + if(dma_mmiotocpu(i, 2) == 0)return; + if(dma_mmiotocpu(i, 3) == 0)return; + } +} + +void bCPU::dma_xfer_type5(uint8 i) { + if(channel[i].direction == 0) { + if(dma_cputommio(i, 0) == 0)return; + if(dma_cputommio(i, 1) == 0)return; + if(dma_cputommio(i, 0) == 0)return; + if(dma_cputommio(i, 1) == 0)return; + } else { + if(dma_mmiotocpu(i, 0) == 0)return; + if(dma_mmiotocpu(i, 1) == 0)return; + if(dma_mmiotocpu(i, 0) == 0)return; + if(dma_mmiotocpu(i, 1) == 0)return; + } +} + +void bCPU::dma_run() { +int i; + for(i=0;i<8;i++) { + if(channel[i].active == false)continue; + + switch(channel[i].xfermode) { + case 0:dma_xfer_type0(i);break; + case 1:dma_xfer_type1(i);break; + case 2:dma_xfer_type2(i);break; + case 3:dma_xfer_type3(i);break; + case 4:dma_xfer_type4(i);break; + case 5:dma_xfer_type5(i);break; + case 6:dma_xfer_type2(i);break; + case 7:dma_xfer_type3(i);break; + } + + if(channel[i].xfersize == 0) { + channel[i].active = false; + } + + return; + } + + status.dma_state = DMASTATE_CPUSYNC; +} + +void bCPU::hdma_write(uint8 i, uint8 l, uint8 x) { + switch(channel[i].xfermode) { + case 0:mem_bus->write(0x2100 | ((channel[i].destaddr) & 0xff), x);break; + case 1:mem_bus->write(0x2100 | ((channel[i].destaddr + l) & 0xff), x);break; + case 2:mem_bus->write(0x2100 | ((channel[i].destaddr) & 0xff), x);break; + case 3:mem_bus->write(0x2100 | ((channel[i].destaddr + (l >> 1)) & 0xff), x);break; + case 4:mem_bus->write(0x2100 | ((channel[i].destaddr + l) & 0xff), x);break; + case 5:mem_bus->write(0x2100 | ((channel[i].destaddr + (l & 1)) & 0xff), x);break; + case 6:mem_bus->write(0x2100 | ((channel[i].destaddr) & 0xff), x);break; + case 7:mem_bus->write(0x2100 | ((channel[i].destaddr + (l >> 1)) & 0xff), x);break; + } +} + +void bCPU::hdma_run() { +int l, xferlen; +uint8 x, active_channels = 0; + for(int i=0;i<8;i++) { + if(channel[i].hdma_completed == true)continue; +// add_cycles(8); + active_channels++; + if(channel[i].hdma_line_counter == 0) { + channel[i].hdma_line_counter = mem_bus->read(channel[i].hdma_taddr++); + if(channel[i].hdma_line_counter == 0) { + channel[i].hdma_completed = true; + continue; + } + + if(channel[i].hdma_line_counter > 0x80) { + channel[i].hdma_repeat = true; + channel[i].hdma_line_counter -= 0x80; + } else { + channel[i].hdma_repeat = false; + } + + channel[i].hdma_first_line = true; + if(channel[i].hdma_indirect == false) { + channel[i].hdma_itaddr = channel[i].hdma_taddr; + } else { + channel[i].hdma_itaddr = mem_bus->read(channel[i].hdma_taddr++); + channel[i].hdma_itaddr |= mem_bus->read(channel[i].hdma_taddr++) << 8; + channel[i].hdma_itaddr |= channel[i].hdma_indirect_bank << 16; +// add_cycles(16); + } + } + + channel[i].hdma_line_counter--; + if(channel[i].hdma_first_line == false && channel[i].hdma_repeat == false)continue; + channel[i].hdma_first_line = false; + + if(channel[i].hdma_indirect == false) { + channel[i].hdma_itaddr = channel[i].hdma_taddr; + } + + switch(channel[i].xfermode) { + case 0: xferlen = 1;break; + case 1:case 2:case 6: xferlen = 2;break; + case 3:case 4:case 5:case 7:xferlen = 4;break; + } + + for(l=0;lread(channel[i].hdma_itaddr++); + if(channel[i].hdma_indirect == false) { + channel[i].hdma_taddr++; + } + hdma_write(i, l, x); +// add_cycles(8); + } + } + + if(active_channels != 0) { +// add_cycles(18); + } +} + +void bCPU::hdma_initialize() { +uint8 active_channels = 0; + for(int i=0;i<8;i++) { + if(channel[i].hdma_active == false) { + channel[i].hdma_completed = true; + continue; + } + active_channels++; + channel[i].hdma_first_line = true; + channel[i].hdma_repeat = false; + channel[i].hdma_taddr = channel[i].srcaddr; + channel[i].hdma_line_counter = 0x00; + channel[i].hdma_completed = false; + if(channel[i].hdma_indirect == false) { + add_cycles(8); + } else { + add_cycles(24); + } + } + + if(active_channels != 0) { + add_cycles(18); + } +} + +void bCPU::dma_reset() { + for(int i=0;i<8;i++) { + channel[i].active = false; + channel[i].hdma_active = false; + channel[i].dmap = 0x00; + channel[i].direction = 0; + channel[i].hdma_indirect = false; + channel[i].incmode = 1; + channel[i].fixedxfer = false; + channel[i].xfermode = 0; + channel[i].destaddr = 0; + channel[i].srcaddr = 0; + channel[i].xfersize = 0; + channel[i].hdma_indirect_bank = 0; + channel[i].hdma_taddr = 0x000000; + channel[i].hdma_line_counter = 0x00; + channel[i].hdma_unknown = 0x00; + + channel[i].hdma_first_line = false; + channel[i].hdma_repeat = false; + channel[i].hdma_itaddr = 0x000000; + channel[i].hdma_completed = true; + } +} diff --git a/src/cpu/bcpu/bcpu_exec.cpp b/src/cpu/bcpu/bcpu_exec.cpp index b809ce03..0ddebc2c 100644 --- a/src/cpu/bcpu/bcpu_exec.cpp +++ b/src/cpu/bcpu/bcpu_exec.cpp @@ -1,519 +1,42 @@ +inline void bCPU::cycle_edge() { +int c, n, z; + if(status.dma_state != DMASTATE_STOP) { + switch(status.dma_state) { + case DMASTATE_INIT: + status.dma_state = DMASTATE_DMASYNC; + break; + case DMASTATE_DMASYNC: + n = 8 - dma_counter() + 8; + add_cycles(n); + status.dma_cycle_count = n; + for(z=0;z<8;z++) { + if(channel[z].active == false)continue; + add_cycles(8); + status.dma_cycle_count += 8; + status.dma_cycle_count += channel[z].xfersize << 3; + } + status.cpu_state = CPUSTATE_DMA; + status.dma_state = DMASTATE_RUN; + while(status.dma_state == DMASTATE_RUN) { + dma_run(); + } + status.cpu_state = CPUSTATE_RUN; + c = status.cycle_count; + z = c - (status.dma_cycle_count % c); + if(!z)z = c; + add_cycles(z); + status.dma_state = DMASTATE_STOP; + break; + } + } +} + void bCPU::exec_opcode() { + snes->notify(SNES::CPU_EXEC_OPCODE_BEGIN); (this->*optbl[op_read()])(); - snes->notify(SNES::CPU_EXEC_OPCODE); + snes->notify(SNES::CPU_EXEC_OPCODE_END); } void bCPU::init_op_tables() { - optbl = optbl_e; - -/* 0x */ - optbl[0x00] = op_brk; - optbl[0x01] = op_ora_idpxb; - optbl[0x02] = op_cop; - optbl[0x03] = op_ora_srb; - optbl[0x04] = op_tsb_dpb; - optbl[0x05] = op_ora_dpb; - optbl[0x06] = op_asl_dpb; - optbl[0x07] = op_ora_ildpb; - optbl[0x08] = op_php; - optbl[0x09] = op_ora_constb; - optbl[0x0a] = op_aslb; - optbl[0x0b] = op_phd; - optbl[0x0c] = op_tsb_addrb; - optbl[0x0d] = op_ora_addrb; - optbl[0x0e] = op_asl_addrb; - optbl[0x0f] = op_ora_longb; -/* 1x */ - optbl[0x10] = op_bpl; - optbl[0x11] = op_ora_idpyb; - optbl[0x12] = op_ora_idpb; - optbl[0x13] = op_ora_isryb; - optbl[0x14] = op_trb_dpb; - optbl[0x15] = op_ora_dpxb; - optbl[0x16] = op_asl_dpxb; - optbl[0x17] = op_ora_ildpyb; - optbl[0x18] = op_clc; - optbl[0x19] = op_ora_addryb; - optbl[0x1a] = op_incb; - optbl[0x1b] = op_tcs; - optbl[0x1c] = op_trb_addrb; - optbl[0x1d] = op_ora_addrxb; - optbl[0x1e] = op_asl_addrxb; - optbl[0x1f] = op_ora_longxb; -/* 2x */ - optbl[0x20] = op_jsr_addr; - optbl[0x21] = op_and_idpxb; - optbl[0x22] = op_jsr_long; - optbl[0x23] = op_and_srb; - optbl[0x24] = op_bit_dpb; - optbl[0x25] = op_and_dpb; - optbl[0x26] = op_rol_dpb; - optbl[0x27] = op_and_ildpb; - optbl[0x28] = op_plp; - optbl[0x29] = op_and_constb; - optbl[0x2a] = op_rolb; - optbl[0x2b] = op_pld; - optbl[0x2c] = op_bit_addrb; - optbl[0x2d] = op_and_addrb; - optbl[0x2e] = op_rol_addrb; - optbl[0x2f] = op_and_longb; -/* 3x */ - optbl[0x30] = op_bmi; - optbl[0x31] = op_and_idpyb; - optbl[0x32] = op_and_idpb; - optbl[0x33] = op_and_isryb; - optbl[0x34] = op_bit_dpxb; - optbl[0x35] = op_and_dpxb; - optbl[0x36] = op_rol_dpxb; - optbl[0x37] = op_and_ildpyb; - optbl[0x38] = op_sec; - optbl[0x39] = op_and_addryb; - optbl[0x3a] = op_decb; - optbl[0x3b] = op_tsc; - optbl[0x3c] = op_bit_addrxb; - optbl[0x3d] = op_and_addrxb; - optbl[0x3e] = op_rol_addrxb; - optbl[0x3f] = op_and_longxb; -/* 4x */ - optbl[0x40] = op_rtie; - optbl[0x41] = op_eor_idpxb; - optbl[0x42] = op_wdm; - optbl[0x43] = op_eor_srb; - optbl[0x44] = op_mvp; - optbl[0x45] = op_eor_dpb; - optbl[0x46] = op_lsr_dpb; - optbl[0x47] = op_eor_ildpb; - optbl[0x48] = op_phab; - optbl[0x49] = op_eor_constb; - optbl[0x4a] = op_lsrb; - optbl[0x4b] = op_phk; - optbl[0x4c] = op_jmp_addr; - optbl[0x4d] = op_eor_addrb; - optbl[0x4e] = op_lsr_addrb; - optbl[0x4f] = op_eor_longb; -/* 5x */ - optbl[0x50] = op_bvc; - optbl[0x51] = op_eor_idpyb; - optbl[0x52] = op_eor_idpb; - optbl[0x53] = op_eor_isryb; - optbl[0x54] = op_mvn; - optbl[0x55] = op_eor_dpxb; - optbl[0x56] = op_lsr_dpxb; - optbl[0x57] = op_eor_ildpyb; - optbl[0x58] = op_cli; - optbl[0x59] = op_eor_addryb; - optbl[0x5a] = op_phyb; - optbl[0x5b] = op_tcd; - optbl[0x5c] = op_jmp_long; - optbl[0x5d] = op_eor_addrxb; - optbl[0x5e] = op_lsr_addrxb; - optbl[0x5f] = op_eor_longxb; -/* 6x */ - optbl[0x60] = op_rts; - optbl[0x61] = op_adc_idpxb; - optbl[0x62] = op_per; - optbl[0x63] = op_adc_srb; - optbl[0x64] = op_stz_dpb; - optbl[0x65] = op_adc_dpb; - optbl[0x66] = op_ror_dpb; - optbl[0x67] = op_adc_ildpb; - optbl[0x68] = op_plab; - optbl[0x69] = op_adc_constb; - optbl[0x6a] = op_rorb; - optbl[0x6b] = op_rtl; - optbl[0x6c] = op_jmp_iaddr; - optbl[0x6d] = op_adc_addrb; - optbl[0x6e] = op_ror_addrb; - optbl[0x6f] = op_adc_longb; -/* 7x */ - optbl[0x70] = op_bvs; - optbl[0x71] = op_adc_idpyb; - optbl[0x72] = op_adc_idpb; - optbl[0x73] = op_adc_isryb; - optbl[0x74] = op_stz_dpxb; - optbl[0x75] = op_adc_dpxb; - optbl[0x76] = op_ror_dpxb; - optbl[0x77] = op_adc_ildpyb; - optbl[0x78] = op_sei; - optbl[0x79] = op_adc_addryb; - optbl[0x7a] = op_plyb; - optbl[0x7b] = op_tdc; - optbl[0x7c] = op_jmp_iaddrx; - optbl[0x7d] = op_adc_addrxb; - optbl[0x7e] = op_ror_addrxb; - optbl[0x7f] = op_adc_longxb; -/* 8x */ - optbl[0x80] = op_bra; - optbl[0x81] = op_sta_idpxb; - optbl[0x82] = op_brl; - optbl[0x83] = op_sta_srb; - optbl[0x84] = op_sty_dpb; - optbl[0x85] = op_sta_dpb; - optbl[0x86] = op_stx_dpb; - optbl[0x87] = op_sta_ildpb; - optbl[0x88] = op_deyb; - optbl[0x89] = op_bit_constb; - optbl[0x8a] = op_txab; - optbl[0x8b] = op_phb; - optbl[0x8c] = op_sty_addrb; - optbl[0x8d] = op_sta_addrb; - optbl[0x8e] = op_stx_addrb; - optbl[0x8f] = op_sta_longb; -/* 9x */ - optbl[0x90] = op_bcc; - optbl[0x91] = op_sta_idpyb; - optbl[0x92] = op_sta_idpb; - optbl[0x93] = op_sta_isryb; - optbl[0x94] = op_sty_dpxb; - optbl[0x95] = op_sta_dpxb; - optbl[0x96] = op_stx_dpyb; - optbl[0x97] = op_sta_ildpyb; - optbl[0x98] = op_tyab; - optbl[0x99] = op_sta_addryb; - optbl[0x9a] = op_txsb; - optbl[0x9b] = op_txyb; - optbl[0x9c] = op_stz_addrb; - optbl[0x9d] = op_sta_addrxb; - optbl[0x9e] = op_stz_addrxb; - optbl[0x9f] = op_sta_longxb; -/* ax */ - optbl[0xa0] = op_ldy_constb; - optbl[0xa1] = op_lda_idpxb; - optbl[0xa2] = op_ldx_constb; - optbl[0xa3] = op_lda_srb; - optbl[0xa4] = op_ldy_dpb; - optbl[0xa5] = op_lda_dpb; - optbl[0xa6] = op_ldx_dpb; - optbl[0xa7] = op_lda_ildpb; - optbl[0xa8] = op_tayb; - optbl[0xa9] = op_lda_constb; - optbl[0xaa] = op_taxb; - optbl[0xab] = op_plb; - optbl[0xac] = op_ldy_addrb; - optbl[0xad] = op_lda_addrb; - optbl[0xae] = op_ldx_addrb; - optbl[0xaf] = op_lda_longb; -/* bx */ - optbl[0xb0] = op_bcs; - optbl[0xb1] = op_lda_idpyb; - optbl[0xb2] = op_lda_idpb; - optbl[0xb3] = op_lda_isryb; - optbl[0xb4] = op_ldy_dpxb; - optbl[0xb5] = op_lda_dpxb; - optbl[0xb6] = op_ldx_dpyb; - optbl[0xb7] = op_lda_ildpyb; - optbl[0xb8] = op_clv; - optbl[0xb9] = op_lda_addryb; - optbl[0xba] = op_tsxb; - optbl[0xbb] = op_tyxb; - optbl[0xbc] = op_ldy_addrxb; - optbl[0xbd] = op_lda_addrxb; - optbl[0xbe] = op_ldx_addryb; - optbl[0xbf] = op_lda_longxb; -/* cx */ - optbl[0xc0] = op_cpy_constb; - optbl[0xc1] = op_cmp_idpxb; - optbl[0xc2] = op_rep; - optbl[0xc3] = op_cmp_srb; - optbl[0xc4] = op_cpy_dpb; - optbl[0xc5] = op_cmp_dpb; - optbl[0xc6] = op_dec_dpb; - optbl[0xc7] = op_cmp_ildpb; - optbl[0xc8] = op_inyb; - optbl[0xc9] = op_cmp_constb; - optbl[0xca] = op_dexb; - optbl[0xcb] = op_wai; - optbl[0xcc] = op_cpy_addrb; - optbl[0xcd] = op_cmp_addrb; - optbl[0xce] = op_dec_addrb; - optbl[0xcf] = op_cmp_longb; -/* dx */ - optbl[0xd0] = op_bne; - optbl[0xd1] = op_cmp_idpyb; - optbl[0xd2] = op_cmp_idpb; - optbl[0xd3] = op_cmp_isryb; - optbl[0xd4] = op_pei; - optbl[0xd5] = op_cmp_dpxb; - optbl[0xd6] = op_dec_dpxb; - optbl[0xd7] = op_cmp_ildpyb; - optbl[0xd8] = op_cld; - optbl[0xd9] = op_cmp_addryb; - optbl[0xda] = op_phxb; - optbl[0xdb] = op_stp; - optbl[0xdc] = op_jmp_iladdr; - optbl[0xdd] = op_cmp_addrxb; - optbl[0xde] = op_dec_addrxb; - optbl[0xdf] = op_cmp_longxb; -/* ex */ - optbl[0xe0] = op_cpx_constb; - optbl[0xe1] = op_sbc_idpxb; - optbl[0xe2] = op_sep; - optbl[0xe3] = op_sbc_srb; - optbl[0xe4] = op_cpx_dpb; - optbl[0xe5] = op_sbc_dpb; - optbl[0xe6] = op_inc_dpb; - optbl[0xe7] = op_sbc_ildpb; - optbl[0xe8] = op_inxb; - optbl[0xe9] = op_sbc_constb; - optbl[0xea] = op_nop; - optbl[0xeb] = op_xba; - optbl[0xec] = op_cpx_addrb; - optbl[0xed] = op_sbc_addrb; - optbl[0xee] = op_inc_addrb; - optbl[0xef] = op_sbc_longb; -/* fx */ - optbl[0xf0] = op_beq; - optbl[0xf1] = op_sbc_idpyb; - optbl[0xf2] = op_sbc_idpb; - optbl[0xf3] = op_sbc_isryb; - optbl[0xf4] = op_pea; - optbl[0xf5] = op_sbc_dpxb; - optbl[0xf6] = op_inc_dpxb; - optbl[0xf7] = op_sbc_ildpyb; - optbl[0xf8] = op_sed; - optbl[0xf9] = op_sbc_addryb; - optbl[0xfa] = op_plxb; - optbl[0xfb] = op_xce; - optbl[0xfc] = op_jsr_iaddrx; - optbl[0xfd] = op_sbc_addrxb; - optbl[0xfe] = op_inc_addrxb; - optbl[0xff] = op_sbc_longxb; - - memcpy(optbl_MX, optbl_e, sizeof(optbl_e)); - memcpy(optbl_Mx, optbl_e, sizeof(optbl_e)); - memcpy(optbl_mX, optbl_e, sizeof(optbl_e)); - memcpy(optbl_mx, optbl_e, sizeof(optbl_e)); - -/* adc */ - optbl_mX[0x69] = optbl_mx[0x69] = op_adc_constw; - optbl_mX[0x6d] = optbl_mx[0x6d] = op_adc_addrw; - optbl_mX[0x7d] = optbl_mx[0x7d] = op_adc_addrxw; - optbl_mX[0x65] = optbl_mx[0x65] = op_adc_dpw; - optbl_mX[0x72] = optbl_mx[0x72] = op_adc_idpw; - optbl_mX[0x67] = optbl_mx[0x67] = op_adc_ildpw; - optbl_mX[0x6f] = optbl_mx[0x6f] = op_adc_longw; - optbl_mX[0x7f] = optbl_mx[0x7f] = op_adc_longxw; - optbl_mX[0x79] = optbl_mx[0x79] = op_adc_addryw; - optbl_mX[0x75] = optbl_mx[0x75] = op_adc_dpxw; - optbl_mX[0x61] = optbl_mx[0x61] = op_adc_idpxw; - optbl_mX[0x71] = optbl_mx[0x71] = op_adc_idpyw; - optbl_mX[0x77] = optbl_mx[0x77] = op_adc_ildpyw; - optbl_mX[0x63] = optbl_mx[0x63] = op_adc_srw; - optbl_mX[0x73] = optbl_mx[0x73] = op_adc_isryw; - -/* and */ - optbl_mX[0x29] = optbl_mx[0x29] = op_and_constw; - optbl_mX[0x2d] = optbl_mx[0x2d] = op_and_addrw; - optbl_mX[0x3d] = optbl_mx[0x3d] = op_and_addrxw; - optbl_mX[0x25] = optbl_mx[0x25] = op_and_dpw; - optbl_mX[0x32] = optbl_mx[0x32] = op_and_idpw; - optbl_mX[0x27] = optbl_mx[0x27] = op_and_ildpw; - optbl_mX[0x2f] = optbl_mx[0x2f] = op_and_longw; - optbl_mX[0x3f] = optbl_mx[0x3f] = op_and_longxw; - optbl_mX[0x39] = optbl_mx[0x39] = op_and_addryw; - optbl_mX[0x35] = optbl_mx[0x35] = op_and_dpxw; - optbl_mX[0x21] = optbl_mx[0x21] = op_and_idpxw; - optbl_mX[0x31] = optbl_mx[0x31] = op_and_idpyw; - optbl_mX[0x37] = optbl_mx[0x37] = op_and_ildpyw; - optbl_mX[0x23] = optbl_mx[0x23] = op_and_srw; - optbl_mX[0x33] = optbl_mx[0x33] = op_and_isryw; - -/* cmp */ - optbl_mX[0xc9] = optbl_mx[0xc9] = op_cmp_constw; - optbl_mX[0xcd] = optbl_mx[0xcd] = op_cmp_addrw; - optbl_mX[0xdd] = optbl_mx[0xdd] = op_cmp_addrxw; - optbl_mX[0xc5] = optbl_mx[0xc5] = op_cmp_dpw; - optbl_mX[0xd2] = optbl_mx[0xd2] = op_cmp_idpw; - optbl_mX[0xc7] = optbl_mx[0xc7] = op_cmp_ildpw; - optbl_mX[0xcf] = optbl_mx[0xcf] = op_cmp_longw; - optbl_mX[0xdf] = optbl_mx[0xdf] = op_cmp_longxw; - optbl_mX[0xd9] = optbl_mx[0xd9] = op_cmp_addryw; - optbl_mX[0xd5] = optbl_mx[0xd5] = op_cmp_dpxw; - optbl_mX[0xc1] = optbl_mx[0xc1] = op_cmp_idpxw; - optbl_mX[0xd1] = optbl_mx[0xd1] = op_cmp_idpyw; - optbl_mX[0xd7] = optbl_mx[0xd7] = op_cmp_ildpyw; - optbl_mX[0xc3] = optbl_mx[0xc3] = op_cmp_srw; - optbl_mX[0xd3] = optbl_mx[0xd3] = op_cmp_isryw; - -/* eor */ - optbl_mX[0x49] = optbl_mx[0x49] = op_eor_constw; - optbl_mX[0x4d] = optbl_mx[0x4d] = op_eor_addrw; - optbl_mX[0x5d] = optbl_mx[0x5d] = op_eor_addrxw; - optbl_mX[0x45] = optbl_mx[0x45] = op_eor_dpw; - optbl_mX[0x52] = optbl_mx[0x52] = op_eor_idpw; - optbl_mX[0x47] = optbl_mx[0x47] = op_eor_ildpw; - optbl_mX[0x4f] = optbl_mx[0x4f] = op_eor_longw; - optbl_mX[0x5f] = optbl_mx[0x5f] = op_eor_longxw; - optbl_mX[0x59] = optbl_mx[0x59] = op_eor_addryw; - optbl_mX[0x55] = optbl_mx[0x55] = op_eor_dpxw; - optbl_mX[0x41] = optbl_mx[0x41] = op_eor_idpxw; - optbl_mX[0x51] = optbl_mx[0x51] = op_eor_idpyw; - optbl_mX[0x57] = optbl_mx[0x57] = op_eor_ildpyw; - optbl_mX[0x43] = optbl_mx[0x43] = op_eor_srw; - optbl_mX[0x53] = optbl_mx[0x53] = op_eor_isryw; - -/* lda */ - optbl_mX[0xa9] = optbl_mx[0xa9] = op_lda_constw; - optbl_mX[0xad] = optbl_mx[0xad] = op_lda_addrw; - optbl_mX[0xbd] = optbl_mx[0xbd] = op_lda_addrxw; - optbl_mX[0xa5] = optbl_mx[0xa5] = op_lda_dpw; - optbl_mX[0xb2] = optbl_mx[0xb2] = op_lda_idpw; - optbl_mX[0xa7] = optbl_mx[0xa7] = op_lda_ildpw; - optbl_mX[0xaf] = optbl_mx[0xaf] = op_lda_longw; - optbl_mX[0xbf] = optbl_mx[0xbf] = op_lda_longxw; - optbl_mX[0xb9] = optbl_mx[0xb9] = op_lda_addryw; - optbl_mX[0xb5] = optbl_mx[0xb5] = op_lda_dpxw; - optbl_mX[0xa1] = optbl_mx[0xa1] = op_lda_idpxw; - optbl_mX[0xb1] = optbl_mx[0xb1] = op_lda_idpyw; - optbl_mX[0xb7] = optbl_mx[0xb7] = op_lda_ildpyw; - optbl_mX[0xa3] = optbl_mx[0xa3] = op_lda_srw; - optbl_mX[0xb3] = optbl_mx[0xb3] = op_lda_isryw; - -/* ora */ - optbl_mX[0x09] = optbl_mx[0x09] = op_ora_constw; - optbl_mX[0x0d] = optbl_mx[0x0d] = op_ora_addrw; - optbl_mX[0x1d] = optbl_mx[0x1d] = op_ora_addrxw; - optbl_mX[0x05] = optbl_mx[0x05] = op_ora_dpw; - optbl_mX[0x12] = optbl_mx[0x12] = op_ora_idpw; - optbl_mX[0x07] = optbl_mx[0x07] = op_ora_ildpw; - optbl_mX[0x0f] = optbl_mx[0x0f] = op_ora_longw; - optbl_mX[0x1f] = optbl_mx[0x1f] = op_ora_longxw; - optbl_mX[0x19] = optbl_mx[0x19] = op_ora_addryw; - optbl_mX[0x15] = optbl_mx[0x15] = op_ora_dpxw; - optbl_mX[0x01] = optbl_mx[0x01] = op_ora_idpxw; - optbl_mX[0x11] = optbl_mx[0x11] = op_ora_idpyw; - optbl_mX[0x17] = optbl_mx[0x17] = op_ora_ildpyw; - optbl_mX[0x03] = optbl_mx[0x03] = op_ora_srw; - optbl_mX[0x13] = optbl_mx[0x13] = op_ora_isryw; - -/* sbc */ - optbl_mX[0xe9] = optbl_mx[0xe9] = op_sbc_constw; - optbl_mX[0xed] = optbl_mx[0xed] = op_sbc_addrw; - optbl_mX[0xfd] = optbl_mx[0xfd] = op_sbc_addrxw; - optbl_mX[0xe5] = optbl_mx[0xe5] = op_sbc_dpw; - optbl_mX[0xf2] = optbl_mx[0xf2] = op_sbc_idpw; - optbl_mX[0xe7] = optbl_mx[0xe7] = op_sbc_ildpw; - optbl_mX[0xef] = optbl_mx[0xef] = op_sbc_longw; - optbl_mX[0xff] = optbl_mx[0xff] = op_sbc_longxw; - optbl_mX[0xf9] = optbl_mx[0xf9] = op_sbc_addryw; - optbl_mX[0xf5] = optbl_mx[0xf5] = op_sbc_dpxw; - optbl_mX[0xe1] = optbl_mx[0xe1] = op_sbc_idpxw; - optbl_mX[0xf1] = optbl_mx[0xf1] = op_sbc_idpyw; - optbl_mX[0xf7] = optbl_mx[0xf7] = op_sbc_ildpyw; - optbl_mX[0xe3] = optbl_mx[0xe3] = op_sbc_srw; - optbl_mX[0xf3] = optbl_mx[0xf3] = op_sbc_isryw; - -/* sta */ - optbl_mX[0x8d] = optbl_mx[0x8d] = op_sta_addrw; - optbl_mX[0x9d] = optbl_mx[0x9d] = op_sta_addrxw; - optbl_mX[0x85] = optbl_mx[0x85] = op_sta_dpw; - optbl_mX[0x92] = optbl_mx[0x92] = op_sta_idpw; - optbl_mX[0x87] = optbl_mx[0x87] = op_sta_ildpw; - optbl_mX[0x8f] = optbl_mx[0x8f] = op_sta_longw; - optbl_mX[0x9f] = optbl_mx[0x9f] = op_sta_longxw; - optbl_mX[0x99] = optbl_mx[0x99] = op_sta_addryw; - optbl_mX[0x95] = optbl_mx[0x95] = op_sta_dpxw; - optbl_mX[0x81] = optbl_mx[0x81] = op_sta_idpxw; - optbl_mX[0x91] = optbl_mx[0x91] = op_sta_idpyw; - optbl_mX[0x97] = optbl_mx[0x97] = op_sta_ildpyw; - optbl_mX[0x83] = optbl_mx[0x83] = op_sta_srw; - optbl_mX[0x93] = optbl_mx[0x93] = op_sta_isryw; - -/* incdec */ - optbl_mX[0x1a] = optbl_mx[0x1a] = op_incw; - optbl_mX[0xee] = optbl_mx[0xee] = op_inc_addrw; - optbl_mX[0xfe] = optbl_mx[0xfe] = op_inc_addrxw; - optbl_mX[0xe6] = optbl_mx[0xe6] = op_inc_dpw; - optbl_mX[0xf6] = optbl_mx[0xf6] = op_inc_dpxw; - optbl_mX[0x3a] = optbl_mx[0x3a] = op_decw; - optbl_mX[0xce] = optbl_mx[0xce] = op_dec_addrw; - optbl_mX[0xde] = optbl_mx[0xde] = op_dec_addrxw; - optbl_mX[0xc6] = optbl_mx[0xc6] = op_dec_dpw; - optbl_mX[0xd6] = optbl_mx[0xd6] = op_dec_dpxw; - - optbl_Mx[0xe8] = optbl_mx[0xe8] = op_inxw; - optbl_Mx[0xc8] = optbl_mx[0xc8] = op_inyw; - optbl_Mx[0xca] = optbl_mx[0xca] = op_dexw; - optbl_Mx[0x88] = optbl_mx[0x88] = op_deyw; - -/* misc */ - optbl_mX[0x89] = optbl_mx[0x89] = op_bit_constw; - optbl_mX[0x2c] = optbl_mx[0x2c] = op_bit_addrw; - optbl_mX[0x3c] = optbl_mx[0x3c] = op_bit_addrxw; - optbl_mX[0x24] = optbl_mx[0x24] = op_bit_dpw; - optbl_mX[0x34] = optbl_mx[0x34] = op_bit_dpxw; - optbl_mX[0x9c] = optbl_mx[0x9c] = op_stz_addrw; - optbl_mX[0x9e] = optbl_mx[0x9e] = op_stz_addrxw; - optbl_mX[0x64] = optbl_mx[0x64] = op_stz_dpw; - optbl_mX[0x74] = optbl_mx[0x74] = op_stz_dpxw; - optbl_mX[0x1c] = optbl_mx[0x1c] = op_trb_addrw; - optbl_mX[0x14] = optbl_mx[0x14] = op_trb_dpw; - optbl_mX[0x0c] = optbl_mx[0x0c] = op_tsb_addrw; - optbl_mX[0x04] = optbl_mx[0x04] = op_tsb_dpw; - optbl_mX[0x8a] = optbl_mx[0x8a] = op_txaw; - optbl_mX[0x98] = optbl_mx[0x98] = op_tyaw; - - optbl_Mx[0xe0] = optbl_mx[0xe0] = op_cpx_constw; - optbl_Mx[0xec] = optbl_mx[0xec] = op_cpx_addrw; - optbl_Mx[0xe4] = optbl_mx[0xe4] = op_cpx_dpw; - optbl_Mx[0xc0] = optbl_mx[0xc0] = op_cpy_constw; - optbl_Mx[0xcc] = optbl_mx[0xcc] = op_cpy_addrw; - optbl_Mx[0xc4] = optbl_mx[0xc4] = op_cpy_dpw; - optbl_Mx[0xa2] = optbl_mx[0xa2] = op_ldx_constw; - optbl_Mx[0xae] = optbl_mx[0xae] = op_ldx_addrw; - optbl_Mx[0xbe] = optbl_mx[0xbe] = op_ldx_addryw; - optbl_Mx[0xa6] = optbl_mx[0xa6] = op_ldx_dpw; - optbl_Mx[0xb6] = optbl_mx[0xb6] = op_ldx_dpyw; - optbl_Mx[0xa0] = optbl_mx[0xa0] = op_ldy_constw; - optbl_Mx[0xac] = optbl_mx[0xac] = op_ldy_addrw; - optbl_Mx[0xbc] = optbl_mx[0xbc] = op_ldy_addrxw; - optbl_Mx[0xa4] = optbl_mx[0xa4] = op_ldy_dpw; - optbl_Mx[0xb4] = optbl_mx[0xb4] = op_ldy_dpxw; - optbl_Mx[0x8e] = optbl_mx[0x8e] = op_stx_addrw; - optbl_Mx[0x86] = optbl_mx[0x86] = op_stx_dpw; - optbl_Mx[0x96] = optbl_mx[0x96] = op_stx_dpyw; - optbl_Mx[0x8c] = optbl_mx[0x8c] = op_sty_addrw; - optbl_Mx[0x84] = optbl_mx[0x84] = op_sty_dpw; - optbl_Mx[0x94] = optbl_mx[0x94] = op_sty_dpxw; - optbl_Mx[0xaa] = optbl_mx[0xaa] = op_taxw; - optbl_Mx[0xa8] = optbl_mx[0xa8] = op_tayw; - optbl_Mx[0xba] = optbl_mx[0xba] = op_tsxw; - optbl_Mx[0x9a] = optbl_mx[0x9a] = op_txsw; - optbl_Mx[0x9b] = optbl_mx[0x9b] = op_txyw; - optbl_Mx[0xbb] = optbl_mx[0xbb] = op_tyxw; - -/* pc */ - optbl_MX[0x40] = optbl_Mx[0x40] = op_rtin; - optbl_mX[0x40] = optbl_mx[0x40] = op_rtin; - -/* shift */ - optbl_mX[0x0a] = optbl_mx[0x0a] = op_aslw; - optbl_mX[0x0e] = optbl_mx[0x0e] = op_asl_addrw; - optbl_mX[0x1e] = optbl_mx[0x1e] = op_asl_addrxw; - optbl_mX[0x06] = optbl_mx[0x06] = op_asl_dpw; - optbl_mX[0x16] = optbl_mx[0x16] = op_asl_dpxw; - optbl_mX[0x4a] = optbl_mx[0x4a] = op_lsrw; - optbl_mX[0x4e] = optbl_mx[0x4e] = op_lsr_addrw; - optbl_mX[0x5e] = optbl_mx[0x5e] = op_lsr_addrxw; - optbl_mX[0x46] = optbl_mx[0x46] = op_lsr_dpw; - optbl_mX[0x56] = optbl_mx[0x56] = op_lsr_dpxw; - optbl_mX[0x2a] = optbl_mx[0x2a] = op_rolw; - optbl_mX[0x2e] = optbl_mx[0x2e] = op_rol_addrw; - optbl_mX[0x3e] = optbl_mx[0x3e] = op_rol_addrxw; - optbl_mX[0x26] = optbl_mx[0x26] = op_rol_dpw; - optbl_mX[0x36] = optbl_mx[0x36] = op_rol_dpxw; - optbl_mX[0x6a] = optbl_mx[0x6a] = op_rorw; - optbl_mX[0x6e] = optbl_mx[0x6e] = op_ror_addrw; - optbl_mX[0x7e] = optbl_mx[0x7e] = op_ror_addrxw; - optbl_mX[0x66] = optbl_mx[0x66] = op_ror_dpw; - optbl_mX[0x76] = optbl_mx[0x76] = op_ror_dpxw; - -/* stack */ - optbl_mX[0x48] = optbl_mx[0x48] = op_phaw; - optbl_mX[0x68] = optbl_mx[0x68] = op_plaw; - - optbl_Mx[0xda] = optbl_mx[0xda] = op_phxw; - optbl_Mx[0x5a] = optbl_mx[0x5a] = op_phyw; - optbl_Mx[0xfa] = optbl_mx[0xfa] = op_plxw; - optbl_Mx[0x7a] = optbl_mx[0x7a] = op_plyw; +#include "bcpu_optable.cpp" } diff --git a/src/cpu/bcpu/bcpu_mmio.cpp b/src/cpu/bcpu/bcpu_mmio.cpp index 55c175f7..6a609ea1 100644 --- a/src/cpu/bcpu/bcpu_mmio.cpp +++ b/src/cpu/bcpu/bcpu_mmio.cpp @@ -91,26 +91,22 @@ uint8 r = 0x00; //RDNMI uint8 bCPU::mmio_r4210() { uint8 r = 0x00; -uint16 v, h, hcycles, visible_scanlines; - v = clock->vcounter(); - h = clock->hcounter(); - hcycles = clock->hcycles(); - visible_scanlines = clock->visible_scanlines(); +uint16 v, h, hc, vs; + v = vcounter(); + h = hcounter(); + hc = hcycles(); + vs = (overscan()?239:224); + if(status.r4210_read == false) { - if(v == 0 && hcycles < 2) { - r |= 0x80; - status.r4210_read = true; - } else if(v == (visible_scanlines + 1) && hcycles >= 2) { - r |= 0x80; - status.r4210_read = true; - } else if(v >= (visible_scanlines + 1)) { + if((v == (vs + 1) && hc >= 2) || v > (vs + 1)) { r |= 0x80; status.r4210_read = true; + status.nmi_pin = 1; } } + r |= 0x40; r |= 0x02; //cpu version number - status.nmi_pin = 1; return r; } @@ -126,24 +122,22 @@ uint8 r = 0x00; //HVBJOY uint8 bCPU::mmio_r4212() { uint8 r; -uint16 v, h, hcycles, visible_scanlines; +uint16 v, h, hc, vs; r = 0x00; - v = clock->vcounter(); - h = clock->hcounter(); - hcycles = clock->hcycles(); - visible_scanlines = clock->visible_scanlines(); + v = vcounter(); + h = hcounter(); + hc = hcycles(); + vs = (overscan()?239:224); //auto joypad polling - if(v >= (visible_scanlines + 1) && v <= (visible_scanlines + 3))r |= 0x01; + if(v >= (vs + 1) && v <= (vs + 3))r |= 0x01; //hblank - if(hcycles <= 4 || hcycles >= 1098)r |= 0x40; + if(hc <= 2 || hc >= 1096)r |= 0x40; //vblank - if(v == 0 && hcycles < 2)r |= 0x80; - if(v == (visible_scanlines + 1) && hcycles >= 2)r |= 0x80; - if(v > (visible_scanlines + 1))r |= 0x80; + if(v >= (vs + 1))r |= 0x80; return r; } @@ -175,7 +169,7 @@ uint8 bCPU::mmio_r4217() { //JOY1L uint8 bCPU::mmio_r4218() { uint8 r = 0x00; -uint16 v = clock->vcounter(); +uint16 v = vcounter(); if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled //if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_A) << 7; @@ -188,7 +182,7 @@ uint16 v = clock->vcounter(); //JOY1H uint8 bCPU::mmio_r4219() { uint8 r = 0x00; -uint16 v = clock->vcounter(); +uint16 v = vcounter(); if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled //if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B) << 7; @@ -202,12 +196,103 @@ uint16 v = clock->vcounter(); return r; } +//DMAPx +uint8 bCPU::mmio_r43x0(uint8 i) { + return channel[i].dmap; +} + +//BBADx +uint8 bCPU::mmio_r43x1(uint8 i) { + return channel[i].destaddr; +} + +//A1TxL +uint8 bCPU::mmio_r43x2(uint8 i) { + return channel[i].srcaddr; +} + +//A1TxH +uint8 bCPU::mmio_r43x3(uint8 i) { + return channel[i].srcaddr >> 8; +} + +//A1Bx +uint8 bCPU::mmio_r43x4(uint8 i) { + return channel[i].srcaddr >> 16; +} + +//DASxL +uint8 bCPU::mmio_r43x5(uint8 i) { + return channel[i].xfersize; +} + +//DASxH +uint8 bCPU::mmio_r43x6(uint8 i) { + return channel[i].xfersize >> 8; +} + +//DASBx +uint8 bCPU::mmio_r43x7(uint8 i) { + return channel[i].hdma_indirect_bank; +} + +//A2AxL +uint8 bCPU::mmio_r43x8(uint8 i) { + return channel[i].hdma_taddr; +} + +//A2AxH +uint8 bCPU::mmio_r43x9(uint8 i) { + return channel[i].hdma_taddr >> 8; +} + +//NTRLx +uint8 bCPU::mmio_r43xa(uint8 i) { + return channel[i].hdma_line_counter; +} + +//??? +uint8 bCPU::mmio_r43xb(uint8 i) { + return channel[i].hdma_unknown; +} + uint8 bCPUMMIO::read(uint32 addr) { - clock->sync(); +uint8 i; +//cpu->sync(); + +//APU + if(addr >= 0x2140 && addr <= 0x217f) { + return apu->port_read(addr & 3); + } + +//HDMA + if(addr >= 0x4300 && addr <= 0x437f) { + i = (addr >> 4) & 7; + switch(addr & 0xf) { + case 0x0:return cpu->mmio_r43x0(i); + case 0x1:return cpu->mmio_r43x1(i); + case 0x2:return cpu->mmio_r43x2(i); + case 0x3:return cpu->mmio_r43x3(i); + case 0x4:return cpu->mmio_r43x4(i); + case 0x5:return cpu->mmio_r43x5(i); + case 0x6:return cpu->mmio_r43x6(i); + case 0x7:return cpu->mmio_r43x7(i); + case 0x8:return cpu->mmio_r43x8(i); + case 0x9:return cpu->mmio_r43x9(i); + case 0xa:return cpu->mmio_r43xa(i); + case 0xb:return cpu->mmio_r43xb(i); + case 0xc:return 0x43; //unmapped + case 0xd:return 0x43; //unmapped + case 0xe:return 0x43; //unmapped + case 0xf:return cpu->mmio_r43xb(i); //mirror of 43xb + } + } + switch(addr) { case 0x2180:return cpu->mmio_r2180(); //WMDATA case 0x21c2:return cpu->mmio_r21c2(); //??? case 0x21c3:return cpu->mmio_r21c3(); //??? + case 0x2800:return cpu->srtc_read(); case 0x4016:return cpu->mmio_r4016(); //JOYSER0 case 0x4210:return cpu->mmio_r4210(); //RDNMI case 0x4211:return cpu->mmio_r4211(); //TIMEUP @@ -219,6 +304,7 @@ uint8 bCPUMMIO::read(uint32 addr) { case 0x4217:return cpu->mmio_r4217(); //RDMPYH case 0x4218:return cpu->mmio_r4218(); //JOY1L case 0x4219:return cpu->mmio_r4219(); //JOY1H + case 0x421a:case 0x421b:case 0x421c:case 0x421d:case 0x421e:case 0x421f:return 0x00; } return 0x00; } @@ -263,6 +349,14 @@ void bCPU::mmio_w4200(uint8 value) { status.virq_enabled = !!(value & 0x20); status.hirq_enabled = !!(value & 0x10); status.auto_joypad_poll = !!(value & 0x01); + + if(status.nmi_enabled == false) { + status.nmi_pin = 0; + } + + if(status.virq_enabled == false && status.hirq_enabled == false) { + status.irq_pin = 0; + } } //WRIO @@ -296,8 +390,8 @@ void bCPU::mmio_w4205(uint8 value) { //WRDIVB void bCPU::mmio_w4206(uint8 value) { status.div_b = value; - status.r4214 = (status.div_b)?status.div_a / status.div_b:0; - status.r4216 = (status.div_b)?status.div_a % status.div_b:0; + status.r4214 = (status.div_b)?status.div_a / status.div_b : 0xffff; + status.r4216 = (status.div_b)?status.div_a % status.div_b : status.div_a; } //HTIMEL @@ -327,15 +421,13 @@ void bCPU::mmio_w420a(uint8 value) { //DMAEN void bCPU::mmio_w420b(uint8 value) { if(value != 0x00) { - clock->add_cc1_cycles(18); + status.dma_state = DMASTATE_INIT; } for(int i=0;i<8;i++) { if(value & (1 << i)) { - dma->channel[i].active = true; - dma->channel[i].hdma_active = false; - clock->add_cc1_cycles(8); - cpustate = CPUSTATE_DMA; + channel[i].active = true; + channel[i].hdma_active = false; } } } @@ -343,7 +435,7 @@ void bCPU::mmio_w420b(uint8 value) { //HDMAEN void bCPU::mmio_w420c(uint8 value) { for(int i=0;i<8;i++) { - dma->channel[i].hdma_active = !!(value & (1 << i)); + channel[i].hdma_active = !!(value & (1 << i)); } } @@ -354,56 +446,108 @@ void bCPU::mmio_w420d(uint8 value) { //DMAPx void bCPU::mmio_w43x0(uint8 value, uint8 i) { - dma->channel[i].direction = !!(value & 0x80); - dma->channel[i].hdma_indirect = !!(value & 0x40); - dma->channel[i].incmode = (value & 0x10)?-1:1; - dma->channel[i].fixedxfer = !!(value & 0x08); - dma->channel[i].xfermode = value & 7; + channel[i].dmap = value; + channel[i].direction = !!(value & 0x80); + channel[i].hdma_indirect = !!(value & 0x40); + channel[i].incmode = (value & 0x10)?-1:1; + channel[i].fixedxfer = !!(value & 0x08); + channel[i].xfermode = value & 7; } //BBADx void bCPU::mmio_w43x1(uint8 value, uint8 i) { - dma->channel[i].destaddr = value; + channel[i].destaddr = value; } //A1TxL void bCPU::mmio_w43x2(uint8 value, uint8 i) { - dma->channel[i].srcaddr = (dma->channel[i].srcaddr & 0xffff00) | value; + channel[i].srcaddr = (channel[i].srcaddr & 0xffff00) | value; } //A1TxH void bCPU::mmio_w43x3(uint8 value, uint8 i) { - dma->channel[i].srcaddr = (dma->channel[i].srcaddr & 0xff00ff) | (value << 8); + channel[i].srcaddr = (channel[i].srcaddr & 0xff00ff) | (value << 8); } //A1Bx void bCPU::mmio_w43x4(uint8 value, uint8 i) { - dma->channel[i].srcaddr = (dma->channel[i].srcaddr & 0x00ffff) | (value << 16); + channel[i].srcaddr = (channel[i].srcaddr & 0x00ffff) | (value << 16); } //DASxL void bCPU::mmio_w43x5(uint8 value, uint8 i) { - dma->channel[i].xfersize = (dma->channel[i].xfersize & 0xff00) | value; + channel[i].xfersize = (channel[i].xfersize & 0xff00) | value; } //DASxH void bCPU::mmio_w43x6(uint8 value, uint8 i) { - dma->channel[i].xfersize = (dma->channel[i].xfersize & 0x00ff) | (value << 8); + channel[i].xfersize = (channel[i].xfersize & 0x00ff) | (value << 8); } //DASBx void bCPU::mmio_w43x7(uint8 value, uint8 i) { - dma->channel[i].hdma_indirect_bank = value; + channel[i].hdma_indirect_bank = value; +} + +//A2AxL +void bCPU::mmio_w43x8(uint8 value, uint8 i) { + channel[i].hdma_taddr = (channel[i].hdma_taddr & 0xffff00) | value; +} + +//A2AxH +void bCPU::mmio_w43x9(uint8 value, uint8 i) { + channel[i].hdma_taddr = (channel[i].hdma_taddr & 0xff00ff) | (value << 8); +} + +//NTRLx +void bCPU::mmio_w43xa(uint8 value, uint8 i) { + channel[i].hdma_line_counter = value; +} + +//??? +void bCPU::mmio_w43xb(uint8 value, uint8 i) { + channel[i].hdma_unknown = value; } void bCPUMMIO::write(uint32 addr, uint8 value) { -int i; - clock->sync(); +uint8 i; +//cpu->sync(); + +//APU + if(addr >= 0x2140 && addr <= 0x217f) { + cpu->port_write(addr & 3, value); + return; + } + +//HDMA + if(addr >= 0x4300 && addr <= 0x437f) { + i = (addr >> 4) & 7; + switch(addr & 0xf) { + case 0x0:cpu->mmio_w43x0(value, i);return; + case 0x1:cpu->mmio_w43x1(value, i);return; + case 0x2:cpu->mmio_w43x2(value, i);return; + case 0x3:cpu->mmio_w43x3(value, i);return; + case 0x4:cpu->mmio_w43x4(value, i);return; + case 0x5:cpu->mmio_w43x5(value, i);return; + case 0x6:cpu->mmio_w43x6(value, i);return; + case 0x7:cpu->mmio_w43x7(value, i);return; + case 0x8:cpu->mmio_w43x8(value, i);return; + case 0x9:cpu->mmio_w43x9(value, i);return; + case 0xa:cpu->mmio_w43xa(value, i);return; + case 0xb:cpu->mmio_w43xb(value, i);return; + case 0xc:return; //unmapped + case 0xd:return; //unmapped + case 0xe:return; //unmapped + case 0xf:cpu->mmio_w43xb(value, i);return; //mirror of 43xb + } + } + switch(addr) { case 0x2180:cpu->mmio_w2180(value);return; //WMDATA case 0x2181:cpu->mmio_w2181(value);return; //WMADDL case 0x2182:cpu->mmio_w2182(value);return; //WMADDM case 0x2183:cpu->mmio_w2183(value);return; //WMADDH + case 0x2801:cpu->srtc_write(value);return; case 0x4016:cpu->mmio_w4016(value);return; //JOYSER0 case 0x4200:cpu->mmio_w4200(value);return; //NMITIMEN case 0x4201:cpu->mmio_w4201(value);return; //WRIO @@ -419,288 +563,9 @@ int i; case 0x420b:cpu->mmio_w420b(value);return; //DMAEN case 0x420c:cpu->mmio_w420c(value);return; //HDMAEN case 0x420d:cpu->mmio_w420d(value);return; //MEMSEL -//DMAPx - case 0x4300:case 0x4310:case 0x4320:case 0x4330: - case 0x4340:case 0x4350:case 0x4360:case 0x4370: - cpu->mmio_w43x0(value, (addr >> 4) & 7); - return; -//BBADx - case 0x4301:case 0x4311:case 0x4321:case 0x4331: - case 0x4341:case 0x4351:case 0x4361:case 0x4371: - cpu->mmio_w43x1(value, (addr >> 4) & 7); - return; -//A1TxL - case 0x4302:case 0x4312:case 0x4322:case 0x4332: - case 0x4342:case 0x4352:case 0x4362:case 0x4372: - cpu->mmio_w43x2(value, (addr >> 4) & 7); - return; -//A1TxH - case 0x4303:case 0x4313:case 0x4323:case 0x4333: - case 0x4343:case 0x4353:case 0x4363:case 0x4373: - cpu->mmio_w43x3(value, (addr >> 4) & 7); - return; -//A1Bx - case 0x4304:case 0x4314:case 0x4324:case 0x4334: - case 0x4344:case 0x4354:case 0x4364:case 0x4374: - cpu->mmio_w43x4(value, (addr >> 4) & 7); - return; -//DASxL - case 0x4305:case 0x4315:case 0x4325:case 0x4335: - case 0x4345:case 0x4355:case 0x4365:case 0x4375: - cpu->mmio_w43x5(value, (addr >> 4) & 7); - return; -//DASxH - case 0x4306:case 0x4316:case 0x4326:case 0x4336: - case 0x4346:case 0x4356:case 0x4366:case 0x4376: - cpu->mmio_w43x6(value, (addr >> 4) & 7); - return; -//DASBx - case 0x4307:case 0x4317:case 0x4327:case 0x4337: - case 0x4347:case 0x4357:case 0x4367:case 0x4377: - cpu->mmio_w43x7(value, (addr >> 4) & 7); - return; } } bCPUMMIO::bCPUMMIO(bCPU *_cpu) { cpu = _cpu; } - -uint16 bDMA::dma_cputommio(uint8 i, uint8 index) { -uint8 x; - x = mem_bus->read(channel[i].srcaddr); - mem_bus->write(0x2100 | ((channel[i].destaddr + index) & 0xff), x); - if(channel[i].fixedxfer == false) { - channel[i].srcaddr = (channel[i].srcaddr & 0xff0000) + ((channel[i].srcaddr + channel[i].incmode) & 0xffff); - } - clock->add_cc1_cycles(8); - return --channel[i].xfersize; -} - -uint16 bDMA::dma_mmiotocpu(uint8 i, uint8 index) { -uint8 x; - x = mem_bus->read(0x2100 | ((channel[i].destaddr + index) & 0xff)); - mem_bus->write(channel[i].srcaddr, x); - if(channel[i].fixedxfer == false) { - channel[i].srcaddr = (channel[i].srcaddr & 0xff0000) + ((channel[i].srcaddr + channel[i].incmode) & 0xffff); - } - clock->add_cc1_cycles(8); - return --channel[i].xfersize; -} - -void bDMA::dma_xfer_type0(uint8 i) { - if(channel[i].direction == 0) { - if(dma_cputommio(i, 0) == 0)return; - } else { - if(dma_mmiotocpu(i, 0) == 0)return; - } -} - -void bDMA::dma_xfer_type1(uint8 i) { - if(channel[i].direction == 0) { - if(dma_cputommio(i, 0) == 0)return; - if(dma_cputommio(i, 1) == 0)return; - } else { - if(dma_mmiotocpu(i, 0) == 0)return; - if(dma_mmiotocpu(i, 1) == 0)return; - } -} - -void bDMA::dma_xfer_type2(uint8 i) { - if(channel[i].direction == 0) { - if(dma_cputommio(i, 0) == 0)return; - if(dma_cputommio(i, 0) == 0)return; - } else { - if(dma_mmiotocpu(i, 0) == 0)return; - if(dma_mmiotocpu(i, 0) == 0)return; - } -} - -void bDMA::dma_xfer_type3(uint8 i) { - if(channel[i].direction == 0) { - if(dma_cputommio(i, 0) == 0)return; - if(dma_cputommio(i, 0) == 0)return; - if(dma_cputommio(i, 1) == 0)return; - if(dma_cputommio(i, 1) == 0)return; - } else { - if(dma_mmiotocpu(i, 0) == 0)return; - if(dma_mmiotocpu(i, 0) == 0)return; - if(dma_mmiotocpu(i, 1) == 0)return; - if(dma_mmiotocpu(i, 1) == 0)return; - } -} - -void bDMA::dma_xfer_type4(uint8 i) { - if(channel[i].direction == 0) { - if(dma_cputommio(i, 0) == 0)return; - if(dma_cputommio(i, 1) == 0)return; - if(dma_cputommio(i, 2) == 0)return; - if(dma_cputommio(i, 3) == 0)return; - } else { - if(dma_mmiotocpu(i, 0) == 0)return; - if(dma_mmiotocpu(i, 1) == 0)return; - if(dma_mmiotocpu(i, 2) == 0)return; - if(dma_mmiotocpu(i, 3) == 0)return; - } -} - -void bDMA::dma_xfer_type5(uint8 i) { - if(channel[i].direction == 0) { - if(dma_cputommio(i, 0) == 0)return; - if(dma_cputommio(i, 1) == 0)return; - if(dma_cputommio(i, 0) == 0)return; - if(dma_cputommio(i, 1) == 0)return; - } else { - if(dma_mmiotocpu(i, 0) == 0)return; - if(dma_mmiotocpu(i, 1) == 0)return; - if(dma_mmiotocpu(i, 0) == 0)return; - if(dma_mmiotocpu(i, 1) == 0)return; - } -} - -void bDMA::run() { - for(int i=0;i<8;i++) { - if(channel[i].active == false)continue; - switch(channel[i].xfermode) { - case 0:dma_xfer_type0(i);break; - case 1:dma_xfer_type1(i);break; - case 2:dma_xfer_type2(i);break; - case 3:dma_xfer_type3(i);break; - case 4:dma_xfer_type4(i);break; - case 5:dma_xfer_type5(i);break; - case 6:dma_xfer_type2(i);break; - case 7:dma_xfer_type3(i);break; - } - if(channel[i].xfersize == 0) { - channel[i].active = false; - } - return; - } - cpu->cpustate = bCPU::CPUSTATE_RUN; -} - -void bDMA::hdma_write(uint8 i, uint8 l, uint8 x) { - switch(channel[i].xfermode) { - case 0:mem_bus->write(0x2100 | ((channel[i].destaddr) & 0xff), x);break; - case 1:mem_bus->write(0x2100 | ((channel[i].destaddr + l) & 0xff), x);break; - case 2:mem_bus->write(0x2100 | ((channel[i].destaddr) & 0xff), x);break; - case 3:mem_bus->write(0x2100 | ((channel[i].destaddr + (l >> 1)) & 0xff), x);break; - case 4:mem_bus->write(0x2100 | ((channel[i].destaddr + l) & 0xff), x);break; - case 5:mem_bus->write(0x2100 | ((channel[i].destaddr + (l & 1)) & 0xff), x);break; - case 6:mem_bus->write(0x2100 | ((channel[i].destaddr) & 0xff), x);break; - case 7:mem_bus->write(0x2100 | ((channel[i].destaddr + (l >> 1)) & 0xff), x);break; - } -} - -void bDMA::hdma_run() { -int l, xferlen; -uint8 x, active_channels = 0; - for(int i=0;i<8;i++) { - if(channel[i].hdma_completed == true)continue; - clock->add_cc1_cycles(8); - active_channels++; - if(channel[i].hdma_line_counter == 0) { - channel[i].hdma_line_counter = mem_bus->read(channel[i].hdma_address++); -// channel[i].r43x8 = channel[i].hdma_address; - if(channel[i].hdma_line_counter == 0) { - channel[i].hdma_completed = true; - continue; - } - - if(channel[i].hdma_line_counter > 0x80) { - channel[i].hdma_repeat = true; - channel[i].hdma_line_counter -= 0x80; - } else { - channel[i].hdma_repeat = false; - } - - channel[i].hdma_first_line = true; - if(channel[i].hdma_indirect == false) { - channel[i].hdma_iaddress = channel[i].hdma_address; - } else { - channel[i].hdma_iaddress = mem_bus->read(channel[i].hdma_address); - channel[i].hdma_iaddress |= mem_bus->read(channel[i].hdma_address + 1) << 8; - channel[i].hdma_iaddress |= channel[i].hdma_indirect_bank << 16; - channel[i].hdma_address += 2; - clock->add_cc1_cycles(16); - } - } - - channel[i].hdma_line_counter--; - if(channel[i].hdma_first_line == false && channel[i].hdma_repeat == false)continue; - channel[i].hdma_first_line = false; - - if(channel[i].hdma_indirect == false) { - channel[i].hdma_iaddress = channel[i].hdma_address; - } - - switch(channel[i].xfermode) { - case 0: xferlen = 1;break; - case 1:case 2:case 6: xferlen = 2;break; - case 3:case 4:case 5:case 7:xferlen = 4;break; - } - - for(l=0;lread(channel[i].hdma_iaddress++); - if(channel[i].hdma_indirect == false) { - channel[i].hdma_address++; - } - hdma_write(i, l, x); - clock->add_cc1_cycles(8); - } - } - if(active_channels != 0) { - clock->add_cc1_cycles(18); - } -} - -void bDMA::hdma_initialize() { -uint8 active_channels = 0; - for(int i=0;i<8;i++) { - if(channel[i].hdma_active == false) { - channel[i].hdma_completed = true; - continue; - } - active_channels++; - channel[i].hdma_first_line = true; - channel[i].hdma_repeat = false; - channel[i].hdma_line_counter = 0; - channel[i].hdma_address = channel[i].srcaddr; - channel[i].hdma_completed = false; - if(channel[i].hdma_indirect == false) { - clock->add_cc1_cycles(8); - } else { - clock->add_cc1_cycles(24); - } - } - if(active_channels != 0) { - clock->add_cc1_cycles(18); - } -} - -void bDMA::reset() { - for(int i=0;i<8;i++) { - channel[i].active = false; - channel[i].hdma_active = false; - channel[i].direction = 0; - channel[i].hdma_indirect = false; - channel[i].incmode = 1; - channel[i].fixedxfer = false; - channel[i].xfermode = 0; - channel[i].destaddr = 0; - channel[i].srcaddr = 0; - channel[i].xfersize = 0; - channel[i].hdma_indirect_bank = 0; - channel[i].hdma_first_line = false; - channel[i].hdma_repeat = false; - channel[i].hdma_line_counter = 0; - channel[i].hdma_address = 0; - channel[i].hdma_iaddress = 0; - channel[i].hdma_completed = true; - } -} - -bDMA::bDMA(bCPU *_cpu) { - cpu = _cpu; - reset(); -} diff --git a/src/cpu/bcpu/bcpu_op.h b/src/cpu/bcpu/bcpu_op.h new file mode 100644 index 00000000..63b88b2d --- /dev/null +++ b/src/cpu/bcpu/bcpu_op.h @@ -0,0 +1,256 @@ +void op_adc_const(); +void op_and_const(); +void op_cmp_const(); +void op_cpx_const(); +void op_cpy_const(); +void op_eor_const(); +void op_lda_const(); +void op_ldx_const(); +void op_ldy_const(); +void op_ora_const(); +void op_sbc_const(); +void op_adc_addr(); +void op_and_addr(); +void op_bit_addr(); +void op_cmp_addr(); +void op_cpx_addr(); +void op_cpy_addr(); +void op_eor_addr(); +void op_lda_addr(); +void op_ldx_addr(); +void op_ldy_addr(); +void op_ora_addr(); +void op_sbc_addr(); +void op_adc_addrx(); +void op_and_addrx(); +void op_bit_addrx(); +void op_cmp_addrx(); +void op_eor_addrx(); +void op_lda_addrx(); +void op_ldy_addrx(); +void op_ora_addrx(); +void op_sbc_addrx(); +void op_adc_addry(); +void op_and_addry(); +void op_cmp_addry(); +void op_eor_addry(); +void op_lda_addry(); +void op_ldx_addry(); +void op_ora_addry(); +void op_sbc_addry(); +void op_adc_long(); +void op_and_long(); +void op_cmp_long(); +void op_eor_long(); +void op_lda_long(); +void op_ora_long(); +void op_sbc_long(); +void op_adc_longx(); +void op_and_longx(); +void op_cmp_longx(); +void op_eor_longx(); +void op_lda_longx(); +void op_ora_longx(); +void op_sbc_longx(); +void op_adc_dp(); +void op_and_dp(); +void op_bit_dp(); +void op_cmp_dp(); +void op_cpx_dp(); +void op_cpy_dp(); +void op_eor_dp(); +void op_lda_dp(); +void op_ldx_dp(); +void op_ldy_dp(); +void op_ora_dp(); +void op_sbc_dp(); +void op_adc_dpx(); +void op_and_dpx(); +void op_bit_dpx(); +void op_cmp_dpx(); +void op_eor_dpx(); +void op_lda_dpx(); +void op_ldy_dpx(); +void op_ora_dpx(); +void op_sbc_dpx(); +void op_ldx_dpy(); +void op_adc_idp(); +void op_and_idp(); +void op_cmp_idp(); +void op_eor_idp(); +void op_lda_idp(); +void op_ora_idp(); +void op_sbc_idp(); +void op_adc_idpx(); +void op_and_idpx(); +void op_cmp_idpx(); +void op_eor_idpx(); +void op_lda_idpx(); +void op_ora_idpx(); +void op_sbc_idpx(); +void op_adc_idpy(); +void op_and_idpy(); +void op_cmp_idpy(); +void op_eor_idpy(); +void op_lda_idpy(); +void op_ora_idpy(); +void op_sbc_idpy(); +void op_adc_ildp(); +void op_and_ildp(); +void op_cmp_ildp(); +void op_eor_ildp(); +void op_lda_ildp(); +void op_ora_ildp(); +void op_sbc_ildp(); +void op_adc_ildpy(); +void op_and_ildpy(); +void op_cmp_ildpy(); +void op_eor_ildpy(); +void op_lda_ildpy(); +void op_ora_ildpy(); +void op_sbc_ildpy(); +void op_adc_sr(); +void op_and_sr(); +void op_cmp_sr(); +void op_eor_sr(); +void op_lda_sr(); +void op_ora_sr(); +void op_sbc_sr(); +void op_adc_isry(); +void op_and_isry(); +void op_cmp_isry(); +void op_eor_isry(); +void op_lda_isry(); +void op_ora_isry(); +void op_sbc_isry(); +void op_bit_const(); +void op_inc(); +void op_inx(); +void op_iny(); +void op_dec(); +void op_dex(); +void op_dey(); +void op_asl(); +void op_lsr(); +void op_rol(); +void op_ror(); +void op_inc_addr(); +void op_dec_addr(); +void op_asl_addr(); +void op_lsr_addr(); +void op_rol_addr(); +void op_ror_addr(); +void op_trb_addr(); +void op_tsb_addr(); +void op_inc_addrx(); +void op_dec_addrx(); +void op_asl_addrx(); +void op_lsr_addrx(); +void op_rol_addrx(); +void op_ror_addrx(); +void op_inc_dp(); +void op_dec_dp(); +void op_asl_dp(); +void op_lsr_dp(); +void op_rol_dp(); +void op_ror_dp(); +void op_trb_dp(); +void op_tsb_dp(); +void op_inc_dpx(); +void op_dec_dpx(); +void op_asl_dpx(); +void op_lsr_dpx(); +void op_rol_dpx(); +void op_ror_dpx(); +void op_sta_addr(); +void op_stx_addr(); +void op_sty_addr(); +void op_stz_addr(); +void op_sta_addrx(); +void op_stz_addrx(); +void op_sta_addry(); +void op_sta_long(); +void op_sta_longx(); +void op_sta_dp(); +void op_stx_dp(); +void op_sty_dp(); +void op_stz_dp(); +void op_sta_dpx(); +void op_sty_dpx(); +void op_stz_dpx(); +void op_stx_dpy(); +void op_sta_idp(); +void op_sta_ildp(); +void op_sta_idpx(); +void op_sta_idpy(); +void op_sta_ildpy(); +void op_sta_sr(); +void op_sta_isry(); +void op_bra(); +void op_bcc(); +void op_bcs(); +void op_bne(); +void op_beq(); +void op_bpl(); +void op_bmi(); +void op_bvc(); +void op_bvs(); +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(); +void op_jsr_iaddrx(); +void op_rti(); +void op_rts(); +void op_rtl(); +void op_nop(); +void op_wdm(); +void op_xba(); +void op_mvn(); +void op_mvp(); +void op_brk(); +void op_cop(); +void op_stp(); +void op_wai(); +void op_xce(); +void op_clc(); +void op_cld(); +void op_cli(); +void op_clv(); +void op_sec(); +void op_sed(); +void op_sei(); +void op_rep(); +void op_sep(); +void op_tax(); +void op_tay(); +void op_txa(); +void op_txy(); +void op_tya(); +void op_tyx(); +void op_tcd(); +void op_tcs(); +void op_tdc(); +void op_tsc(); +void op_tsx(); +void op_txs(); +void op_pha(); +void op_phx(); +void op_phy(); +void op_phd(); +void op_phb(); +void op_phk(); +void op_php(); +void op_pla(); +void op_plx(); +void op_ply(); +void op_pld(); +void op_plb(); +void op_plp(); +void op_pea(); +void op_pei(); +void op_per(); diff --git a/src/cpu/bcpu/bcpu_op_adc.cpp b/src/cpu/bcpu/bcpu_op_adc.cpp deleted file mode 100644 index fdf6e152..00000000 --- a/src/cpu/bcpu/bcpu_op_adc.cpp +++ /dev/null @@ -1,464 +0,0 @@ -inline void bCPU::flags_adc_b() { -int32 r = regs.a.l + rd.l + regs.p.c; -//bcd - if(regs.p.d) { - if(((r ) & 15) > 9)r += 6; - if(((r >> 4) & 15) > 9)r += 6 << 4; - } - regs.p.n = !!(r & 0x80); - regs.p.v = !!(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80); - regs.p.z = ((byte)r == 0); - regs.p.c = (r > 0xff); - regs.a.l = r; -} - -inline void bCPU::flags_adc_w() { -int32 r = regs.a.w + rd.w + regs.p.c; -//bcd - if(regs.p.d) { - if(((r ) & 15) > 9)r += 6; - if(((r >> 4) & 15) > 9)r += 6 << 4; - if(((r >> 8) & 15) > 9)r += 6 << 8; - if(((r >> 12) & 15) > 9)r += 6 << 12; - } - regs.p.n = !!(r & 0x8000); - regs.p.v = !!(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000); - regs.p.z = ((word)r == 0); - regs.p.c = (r > 0xffff); - regs.a.w = r; -} - -/************************ - *** 0x69: adc #const *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; idl - [2a] pbr,pc+2 ; idh [1] -*/ -void bCPU::op_adc_constb() { - rd.l = op_read(); //2 - flags_adc_b(); -} - -void bCPU::op_adc_constw() { - rd.l = op_read(); //2 - rd.h = op_read(); //2a - flags_adc_w(); -} - -/********************** - *** 0x6d: adc addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_adc_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - flags_adc_b(); -} - -void bCPU::op_adc_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a - flags_adc_w(); -} - -/************************ - *** 0x7d: adc addr,x *** - ************************ -cycles: - [1 ] pbr,pc ; operadc - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+xl ; io [4] - [4 ] dbr,aa+x ; data low - [4a] dbr,aa+x+1 ; data high [1] -*/ -void bCPU::op_adc_addrxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - flags_adc_b(); -} - -void bCPU::op_adc_addrxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a - flags_adc_w(); -} - -/******************** - *** 0x65: adc dp *** - ******************** -cycles: - [1 ] pbr,pc ; operadc - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] -*/ -void bCPU::op_adc_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - flags_adc_b(); -} - -void bCPU::op_adc_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - rd.h = op_read(OPMODE_DP, dp + 1); //3a - flags_adc_w(); -} - -/********************** - *** 0x72: adc (dp) *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] dbr,aa ; data low - [5a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_adc_idpb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - rd.l = op_read(OPMODE_DBR, aa.w); //5 - flags_adc_b(); -} - -void bCPU::op_adc_idpw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - rd.l = op_read(OPMODE_DBR, aa.w); //5 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //5 - flags_adc_w(); -} - -/********************** - *** 0x67: adc [dp] *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] 0,d+dp+2 ; aab - [6 ] aab,aa ; data low - [6a] aab,aa+1 ; data high [1] -*/ -void bCPU::op_adc_ildpb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - rd.l = op_read(OPMODE_LONG, aa.d); //6 - flags_adc_b(); -} - -void bCPU::op_adc_ildpw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - rd.l = op_read(OPMODE_LONG, aa.d); //6 - rd.h = op_read(OPMODE_LONG, aa.d + 1); //6a - flags_adc_w(); -} - -/********************** - *** 0x6f: adc long *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] pbr,pc+3 ; aab - [5 ] aab,aa ; data low - [5a] aab,aa+1 ; data high -*/ -void bCPU::op_adc_longb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - rd.l = op_read(OPMODE_LONG, aa.d); //5 - flags_adc_b(); -} - -void bCPU::op_adc_longw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - rd.l = op_read(OPMODE_LONG, aa.d); //5 - rd.h = op_read(OPMODE_LONG, aa.d + 1); //5a - flags_adc_w(); -} - -/************************ - *** 0x7f: adc long,x *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] pbr,pc+3 ; aab - [5 ] aab,aa+x ; data low - [5a] aab,aa+x+1 ; data high -*/ -void bCPU::op_adc_longxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5 - flags_adc_b(); -} - -void bCPU::op_adc_longxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5 - rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a - flags_adc_w(); -} - -/************************ - *** 0x79: adc addr,y *** - ************************ -cycles: - [1 ] pbr,pc ; operadc - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+yl ; io [4] - [4 ] dbr,aa+y ; data low - [4a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_adc_addryb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4 - flags_adc_b(); -} - -void bCPU::op_adc_addryw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a - flags_adc_w(); -} - -/********************** - *** 0x75: adc dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high -*/ -void bCPU::op_adc_dpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - flags_adc_b(); -} - -void bCPU::op_adc_dpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a - flags_adc_w(); -} - -/************************ - *** 0x61: adc (dp,x) *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; aal - [5 ] 0,d+dp+x+1 ; aah - [6 ] dbr,aa ; data low - [6a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_adc_idpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5 - rd.l = op_read(OPMODE_DBR, aa.w); //6 - flags_adc_b(); -} - -void bCPU::op_adc_idpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5 - rd.l = op_read(OPMODE_DBR, aa.w); //6 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //6a - flags_adc_w(); -} - -/************************ - *** 0x71: adc (dp),y *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [4a] dbr,aah,aal+yl ; io [4] - [5 ] dbr,aa+y ; data low - [5a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_adc_idpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - cpu_c4(aa.w, aa.w + regs.y.w); //4a - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5 - flags_adc_b(); -} - -void bCPU::op_adc_idpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - cpu_c4(aa.w, aa.w + regs.y.w); //4a - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5 - rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a - flags_adc_w(); -} - -/************************ - *** 0x77: adc [dp],y *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] 0,d+dp+2 ; aab - [6 ] aab,aa+y ; data low - [6a] aab,aa+y+1 ; data high [1] -*/ -void bCPU::op_adc_ildpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6 - flags_adc_b(); -} - -void bCPU::op_adc_ildpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6 - rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a - flags_adc_w(); -} - -/********************** - *** 0x63: adc sr,s *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; sp - [3 ] pbr,pc+1 ; io - [4 ] 0,s+sp ; data low - [4a] 0,s+sp+1 ; data high [1] -*/ -void bCPU::op_adc_srb() { - sp = op_read(); //2 - cpu_io(); //3 - rd.l = op_read(OPMODE_SP, sp); //4 - flags_adc_b(); -} - -void bCPU::op_adc_srw() { - sp = op_read(); //2 - cpu_io(); //3 - rd.l = op_read(OPMODE_SP, sp); //4 - rd.h = op_read(OPMODE_SP, sp + 1); //4a - flags_adc_w(); -} - -/************************** - *** 0x73: adc (sr,s),y *** - ************************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; sp - [3 ] pbr,pc+1 ; io - [4 ] 0,s+sp ; aal - [5 ] 0,s+sp+1 ; aah - [6 ] 0,s+sp+1 ; io - [7 ] dbr,aa+y ; data low - [7a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_adc_isryb() { - sp = op_read(); //2 - cpu_io(); //3 - aa.l = op_read(OPMODE_SP, sp); //4 - aa.h = op_read(OPMODE_SP, sp + 1); //5 - cpu_io(); //6 - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7 - flags_adc_b(); -} - -void bCPU::op_adc_isryw() { - sp = op_read(); //2 - cpu_io(); //3 - aa.l = op_read(OPMODE_SP, sp); //4 - aa.h = op_read(OPMODE_SP, sp + 1); //5 - cpu_io(); //6 - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7 - rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a - flags_adc_w(); -} diff --git a/src/cpu/bcpu/bcpu_op_and.cpp b/src/cpu/bcpu/bcpu_op_and.cpp deleted file mode 100644 index 4960ae05..00000000 --- a/src/cpu/bcpu/bcpu_op_and.cpp +++ /dev/null @@ -1,444 +0,0 @@ -inline void bCPU::flags_and_b() { - regs.p.n = !!(regs.a.l & 0x80); - regs.p.z = (regs.a.l == 0); -} - -inline void bCPU::flags_and_w() { - regs.p.n = !!(regs.a.w & 0x8000); - regs.p.z = (regs.a.w == 0); -} - -/************************ - *** 0x29: and #const *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; idl - [2a] pbr,pc+2 ; idh [1] -*/ -void bCPU::op_and_constb() { - regs.a.l &= op_read(); //2 - flags_and_b(); -} - -void bCPU::op_and_constw() { - regs.a.l &= op_read(); //2 - regs.a.h &= op_read(); //2a - flags_and_w(); -} - -/********************** - *** 0x2d: and addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_and_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - regs.a.l &= op_read(OPMODE_DBR, aa.w); //4 - flags_and_b(); -} - -void bCPU::op_and_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - regs.a.l &= op_read(OPMODE_DBR, aa.w); //4 - regs.a.h &= op_read(OPMODE_DBR, aa.w + 1); //4a - flags_and_w(); -} - -/************************ - *** 0x3d: and addr,x *** - ************************ -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+xl ; io [4] - [4 ] dbr,aa+x ; data low - [4a] dbr,aa+x+1 ; data high [1] -*/ -void bCPU::op_and_addrxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - flags_and_b(); -} - -void bCPU::op_and_addrxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - regs.a.h &= op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a - flags_and_w(); -} - -/******************** - *** 0x25: and dp *** - ******************** -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] -*/ -void bCPU::op_and_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - regs.a.l &= op_read(OPMODE_DP, dp); //3 - flags_and_b(); -} - -void bCPU::op_and_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - regs.a.l &= op_read(OPMODE_DP, dp); //3 - regs.a.h &= op_read(OPMODE_DP, dp + 1); //3a - flags_and_w(); -} - -/********************** - *** 0x32: and (dp) *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] dbr,aa ; data low - [5a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_and_idpb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - regs.a.l &= op_read(OPMODE_DBR, aa.w); //5 - flags_and_b(); -} - -void bCPU::op_and_idpw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - regs.a.l &= op_read(OPMODE_DBR, aa.w); //5 - regs.a.h &= op_read(OPMODE_DBR, aa.w + 1); //5 - flags_and_w(); -} - -/********************** - *** 0x27: and [dp] *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] 0,d+dp+2 ; aab - [6 ] aab,aa ; data low - [6a] aab,aa+1 ; data high [1] -*/ -void bCPU::op_and_ildpb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - regs.a.l &= op_read(OPMODE_LONG, aa.d); //6 - flags_and_b(); -} - -void bCPU::op_and_ildpw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - regs.a.l &= op_read(OPMODE_LONG, aa.d); //6 - regs.a.h &= op_read(OPMODE_LONG, aa.d + 1); //6a - flags_and_w(); -} - -/********************** - *** 0x2f: and long *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] pbr,pc+3 ; aab - [5 ] aab,aa ; data low - [5a] aab,aa+1 ; data high -*/ -void bCPU::op_and_longb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - regs.a.l &= op_read(OPMODE_LONG, aa.d); //5 - flags_and_b(); -} - -void bCPU::op_and_longw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - regs.a.l &= op_read(OPMODE_LONG, aa.d); //5 - regs.a.h &= op_read(OPMODE_LONG, aa.d + 1); //5a - flags_and_w(); -} - -/************************ - *** 0x3f: and long,x *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] pbr,pc+3 ; aab - [5 ] aab,aa+x ; data low - [5a] aab,aa+x+1 ; data high -*/ -void bCPU::op_and_longxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - regs.a.l &= op_read(OPMODE_LONG, aa.d + regs.x.w); //5 - flags_and_b(); -} - -void bCPU::op_and_longxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - regs.a.l &= op_read(OPMODE_LONG, aa.d + regs.x.w); //5 - regs.a.h &= op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a - flags_and_w(); -} - -/************************ - *** 0x39: and addr,y *** - ************************ -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+yl ; io [4] - [4 ] dbr,aa+y ; data low - [4a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_and_addryb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //4 - flags_and_b(); -} - -void bCPU::op_and_addryw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //4 - regs.a.h &= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a - flags_and_w(); -} - -/********************** - *** 0x35: and dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high -*/ -void bCPU::op_and_dpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - regs.a.l &= op_read(OPMODE_DP, dp + regs.x.w); //4 - flags_and_b(); -} - -void bCPU::op_and_dpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - regs.a.l &= op_read(OPMODE_DP, dp + regs.x.w); //4 - regs.a.h &= op_read(OPMODE_DP, dp + regs.x.w + 1); //4a - flags_and_w(); -} - -/************************ - *** 0x21: and (dp,x) *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; aal - [5 ] 0,d+dp+x+1 ; aah - [6 ] dbr,aa ; data low - [6a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_and_idpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5 - regs.a.l &= op_read(OPMODE_DBR, aa.w); //6 - flags_and_b(); -} - -void bCPU::op_and_idpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5 - regs.a.l &= op_read(OPMODE_DBR, aa.w); //6 - regs.a.h &= op_read(OPMODE_DBR, aa.w + 1); //6a - flags_and_w(); -} - -/************************ - *** 0x31: and (dp),y *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [4a] dbr,aah,aal+yl ; io [4] - [5 ] dbr,aa+y ; data low - [5a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_and_idpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - cpu_c4(aa.w, aa.w + regs.y.w); //4a - regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //5 - flags_and_b(); -} - -void bCPU::op_and_idpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - cpu_c4(aa.w, aa.w + regs.y.w); //4a - regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //5 - regs.a.h &= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a - flags_and_w(); -} - -/************************ - *** 0x37: and [dp],y *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] 0,d+dp+2 ; aab - [6 ] aab,aa+y ; data low - [6a] aab,aa+y+1 ; data high [1] -*/ -void bCPU::op_and_ildpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - regs.a.l &= op_read(OPMODE_LONG, aa.d + regs.y.w); //6 - flags_and_b(); -} - -void bCPU::op_and_ildpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - regs.a.l &= op_read(OPMODE_LONG, aa.d + regs.y.w); //6 - regs.a.h &= op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a - flags_and_w(); -} - -/********************** - *** 0x23: and sr,s *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; sp - [3 ] pbr,pc+1 ; io - [4 ] 0,s+sp ; data low - [4a] 0,s+sp+1 ; data high [1] -*/ -void bCPU::op_and_srb() { - sp = op_read(); //2 - cpu_io(); //3 - regs.a.l &= op_read(OPMODE_SP, sp); //4 - flags_and_b(); -} - -void bCPU::op_and_srw() { - sp = op_read(); //2 - cpu_io(); //3 - regs.a.l &= op_read(OPMODE_SP, sp); //4 - regs.a.h &= op_read(OPMODE_SP, sp + 1); //4a - flags_and_w(); -} - -/************************** - *** 0x33: and (sr,s),y *** - ************************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; sp - [3 ] pbr,pc+1 ; io - [4 ] 0,s+sp ; aal - [5 ] 0,s+sp+1 ; aah - [6 ] 0,s+sp+1 ; io - [7 ] dbr,aa+y ; data low - [7a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_and_isryb() { - sp = op_read(); //2 - cpu_io(); //3 - aa.l = op_read(OPMODE_SP, sp); //4 - aa.h = op_read(OPMODE_SP, sp + 1); //5 - cpu_io(); //6 - regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //7 - flags_and_b(); -} - -void bCPU::op_and_isryw() { - sp = op_read(); //2 - cpu_io(); //3 - aa.l = op_read(OPMODE_SP, sp); //4 - aa.h = op_read(OPMODE_SP, sp + 1); //5 - cpu_io(); //6 - regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //7 - regs.a.h &= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a - flags_and_w(); -} diff --git a/src/cpu/bcpu/bcpu_op_cmp.cpp b/src/cpu/bcpu/bcpu_op_cmp.cpp deleted file mode 100644 index fd370f3c..00000000 --- a/src/cpu/bcpu/bcpu_op_cmp.cpp +++ /dev/null @@ -1,448 +0,0 @@ -inline void bCPU::flags_cmp_b() { -int32 r = regs.a.l - rd.l; - regs.p.n = !!(r & 0x80); - regs.p.z = ((uint8)r == 0); - regs.p.c = (r >= 0); -} - -inline void bCPU::flags_cmp_w() { -int32 r = regs.a.w - rd.w; - regs.p.n = !!(r & 0x8000); - regs.p.z = ((uint16)r == 0); - regs.p.c = (r >= 0); -} - -/************************ - *** 0xc9: cmp #const *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; idl - [2a] pbr,pc+2 ; idh [1] -*/ -void bCPU::op_cmp_constb() { - rd.l = op_read(); //2 - flags_cmp_b(); -} - -void bCPU::op_cmp_constw() { - rd.l = op_read(); //2 - rd.h = op_read(); //2a - flags_cmp_w(); -} - -/********************** - *** 0xcd: cmp addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_cmp_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - flags_cmp_b(); -} - -void bCPU::op_cmp_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a - flags_cmp_w(); -} - -/************************ - *** 0xdd: cmp addr,x *** - ************************ -cycles: - [1 ] pbr,pc ; opercmp - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+xl ; io [4] - [4 ] dbr,aa+x ; data low - [4a] dbr,aa+x+1 ; data high [1] -*/ -void bCPU::op_cmp_addrxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - flags_cmp_b(); -} - -void bCPU::op_cmp_addrxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a - flags_cmp_w(); -} - -/******************** - *** 0xc5: cmp dp *** - ******************** -cycles: - [1 ] pbr,pc ; opercmp - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] -*/ -void bCPU::op_cmp_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - flags_cmp_b(); -} - -void bCPU::op_cmp_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - rd.h = op_read(OPMODE_DP, dp + 1); //3a - flags_cmp_w(); -} - -/********************** - *** 0xd2: cmp (dp) *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] dbr,aa ; data low - [5a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_cmp_idpb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - rd.l = op_read(OPMODE_DBR, aa.w); //5 - flags_cmp_b(); -} - -void bCPU::op_cmp_idpw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - rd.l = op_read(OPMODE_DBR, aa.w); //5 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //5 - flags_cmp_w(); -} - -/********************** - *** 0xc7: cmp [dp] *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] 0,d+dp+2 ; aab - [6 ] aab,aa ; data low - [6a] aab,aa+1 ; data high [1] -*/ -void bCPU::op_cmp_ildpb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - rd.l = op_read(OPMODE_LONG, aa.d); //6 - flags_cmp_b(); -} - -void bCPU::op_cmp_ildpw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - rd.l = op_read(OPMODE_LONG, aa.d); //6 - rd.h = op_read(OPMODE_LONG, aa.d + 1); //6a - flags_cmp_w(); -} - -/********************** - *** 0xcf: cmp long *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] pbr,pc+3 ; aab - [5 ] aab,aa ; data low - [5a] aab,aa+1 ; data high -*/ -void bCPU::op_cmp_longb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - rd.l = op_read(OPMODE_LONG, aa.d); //5 - flags_cmp_b(); -} - -void bCPU::op_cmp_longw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - rd.l = op_read(OPMODE_LONG, aa.d); //5 - rd.h = op_read(OPMODE_LONG, aa.d + 1); //5a - flags_cmp_w(); -} - -/************************ - *** 0xdf: cmp long,x *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] pbr,pc+3 ; aab - [5 ] aab,aa+x ; data low - [5a] aab,aa+x+1 ; data high -*/ -void bCPU::op_cmp_longxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5 - flags_cmp_b(); -} - -void bCPU::op_cmp_longxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5 - rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a - flags_cmp_w(); -} - -/************************ - *** 0xd9: cmp addr,y *** - ************************ -cycles: - [1 ] pbr,pc ; opercmp - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+yl ; io [4] - [4 ] dbr,aa+y ; data low - [4a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_cmp_addryb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4 - flags_cmp_b(); -} - -void bCPU::op_cmp_addryw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a - flags_cmp_w(); -} - -/********************** - *** 0xd5: cmp dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high -*/ -void bCPU::op_cmp_dpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - flags_cmp_b(); -} - -void bCPU::op_cmp_dpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a - flags_cmp_w(); -} - -/************************ - *** 0xc1: cmp (dp,x) *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; aal - [5 ] 0,d+dp+x+1 ; aah - [6 ] dbr,aa ; data low - [6a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_cmp_idpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5 - rd.l = op_read(OPMODE_DBR, aa.w); //6 - flags_cmp_b(); -} - -void bCPU::op_cmp_idpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5 - rd.l = op_read(OPMODE_DBR, aa.w); //6 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //6a - flags_cmp_w(); -} - -/************************ - *** 0xd1: cmp (dp),y *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [4a] dbr,aah,aal+yl ; io [4] - [5 ] dbr,aa+y ; data low - [5a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_cmp_idpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - cpu_c4(aa.w, aa.w + regs.y.w); //4a - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5 - flags_cmp_b(); -} - -void bCPU::op_cmp_idpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - cpu_c4(aa.w, aa.w + regs.y.w); //4a - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5 - rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a - flags_cmp_w(); -} - -/************************ - *** 0xd7: cmp [dp],y *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] 0,d+dp+2 ; aab - [6 ] aab,aa+y ; data low - [6a] aab,aa+y+1 ; data high [1] -*/ -void bCPU::op_cmp_ildpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6 - flags_cmp_b(); -} - -void bCPU::op_cmp_ildpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6 - rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a - flags_cmp_w(); -} - -/********************** - *** 0xc3: cmp sr,s *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; sp - [3 ] pbr,pc+1 ; io - [4 ] 0,s+sp ; data low - [4a] 0,s+sp+1 ; data high [1] -*/ -void bCPU::op_cmp_srb() { - sp = op_read(); //2 - cpu_io(); //3 - rd.l = op_read(OPMODE_SP, sp); //4 - flags_cmp_b(); -} - -void bCPU::op_cmp_srw() { - sp = op_read(); //2 - cpu_io(); //3 - rd.l = op_read(OPMODE_SP, sp); //4 - rd.h = op_read(OPMODE_SP, sp + 1); //4a - flags_cmp_w(); -} - -/************************** - *** 0xd3: cmp (sr,s),y *** - ************************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; sp - [3 ] pbr,pc+1 ; io - [4 ] 0,s+sp ; aal - [5 ] 0,s+sp+1 ; aah - [6 ] 0,s+sp+1 ; io - [7 ] dbr,aa+y ; data low - [7a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_cmp_isryb() { - sp = op_read(); //2 - cpu_io(); //3 - aa.l = op_read(OPMODE_SP, sp); //4 - aa.h = op_read(OPMODE_SP, sp + 1); //5 - cpu_io(); //6 - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7 - flags_cmp_b(); -} - -void bCPU::op_cmp_isryw() { - sp = op_read(); //2 - cpu_io(); //3 - aa.l = op_read(OPMODE_SP, sp); //4 - aa.h = op_read(OPMODE_SP, sp + 1); //5 - cpu_io(); //6 - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7 - rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a - flags_cmp_w(); -} diff --git a/src/cpu/bcpu/bcpu_op_eor.cpp b/src/cpu/bcpu/bcpu_op_eor.cpp deleted file mode 100644 index 98508be7..00000000 --- a/src/cpu/bcpu/bcpu_op_eor.cpp +++ /dev/null @@ -1,444 +0,0 @@ -inline void bCPU::flags_eor_b() { - regs.p.n = !!(regs.a.l & 0x80); - regs.p.z = (regs.a.l == 0); -} - -inline void bCPU::flags_eor_w() { - regs.p.n = !!(regs.a.w & 0x8000); - regs.p.z = (regs.a.w == 0); -} - -/************************ - *** 0x49: eor #const *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; idl - [2a] pbr,pc+2 ; idh [1] -*/ -void bCPU::op_eor_constb() { - regs.a.l ^= op_read(); //2 - flags_eor_b(); -} - -void bCPU::op_eor_constw() { - regs.a.l ^= op_read(); //2 - regs.a.h ^= op_read(); //2a - flags_eor_w(); -} - -/********************** - *** 0x4d: eor addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_eor_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - regs.a.l ^= op_read(OPMODE_DBR, aa.w); //4 - flags_eor_b(); -} - -void bCPU::op_eor_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - regs.a.l ^= op_read(OPMODE_DBR, aa.w); //4 - regs.a.h ^= op_read(OPMODE_DBR, aa.w + 1); //4a - flags_eor_w(); -} - -/************************ - *** 0x5d: eor addr,x *** - ************************ -cycles: - [1 ] pbr,pc ; opereor - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+xl ; io [4] - [4 ] dbr,aa+x ; data low - [4a] dbr,aa+x+1 ; data high [1] -*/ -void bCPU::op_eor_addrxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - flags_eor_b(); -} - -void bCPU::op_eor_addrxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - regs.a.h ^= op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a - flags_eor_w(); -} - -/******************** - *** 0x45: eor dp *** - ******************** -cycles: - [1 ] pbr,pc ; opereor - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] -*/ -void bCPU::op_eor_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - regs.a.l ^= op_read(OPMODE_DP, dp); //3 - flags_eor_b(); -} - -void bCPU::op_eor_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - regs.a.l ^= op_read(OPMODE_DP, dp); //3 - regs.a.h ^= op_read(OPMODE_DP, dp + 1); //3a - flags_eor_w(); -} - -/********************** - *** 0x52: eor (dp) *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] dbr,aa ; data low - [5a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_eor_idpb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - regs.a.l ^= op_read(OPMODE_DBR, aa.w); //5 - flags_eor_b(); -} - -void bCPU::op_eor_idpw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - regs.a.l ^= op_read(OPMODE_DBR, aa.w); //5 - regs.a.h ^= op_read(OPMODE_DBR, aa.w + 1); //5 - flags_eor_w(); -} - -/********************** - *** 0x47: eor [dp] *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] 0,d+dp+2 ; aab - [6 ] aab,aa ; data low - [6a] aab,aa+1 ; data high [1] -*/ -void bCPU::op_eor_ildpb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - regs.a.l ^= op_read(OPMODE_LONG, aa.d); //6 - flags_eor_b(); -} - -void bCPU::op_eor_ildpw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - regs.a.l ^= op_read(OPMODE_LONG, aa.d); //6 - regs.a.h ^= op_read(OPMODE_LONG, aa.d + 1); //6a - flags_eor_w(); -} - -/********************** - *** 0x4f: eor long *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] pbr,pc+3 ; aab - [5 ] aab,aa ; data low - [5a] aab,aa+1 ; data high -*/ -void bCPU::op_eor_longb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - regs.a.l ^= op_read(OPMODE_LONG, aa.d); //5 - flags_eor_b(); -} - -void bCPU::op_eor_longw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - regs.a.l ^= op_read(OPMODE_LONG, aa.d); //5 - regs.a.h ^= op_read(OPMODE_LONG, aa.d + 1); //5a - flags_eor_w(); -} - -/************************ - *** 0x5f: eor long,x *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] pbr,pc+3 ; aab - [5 ] aab,aa+x ; data low - [5a] aab,aa+x+1 ; data high -*/ -void bCPU::op_eor_longxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - regs.a.l ^= op_read(OPMODE_LONG, aa.d + regs.x.w); //5 - flags_eor_b(); -} - -void bCPU::op_eor_longxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - regs.a.l ^= op_read(OPMODE_LONG, aa.d + regs.x.w); //5 - regs.a.h ^= op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a - flags_eor_w(); -} - -/************************ - *** 0x59: eor addr,y *** - ************************ -cycles: - [1 ] pbr,pc ; opereor - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+yl ; io [4] - [4 ] dbr,aa+y ; data low - [4a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_eor_addryb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //4 - flags_eor_b(); -} - -void bCPU::op_eor_addryw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //4 - regs.a.h ^= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a - flags_eor_w(); -} - -/********************** - *** 0x55: eor dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high -*/ -void bCPU::op_eor_dpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - regs.a.l ^= op_read(OPMODE_DP, dp + regs.x.w); //4 - flags_eor_b(); -} - -void bCPU::op_eor_dpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - regs.a.l ^= op_read(OPMODE_DP, dp + regs.x.w); //4 - regs.a.h ^= op_read(OPMODE_DP, dp + regs.x.w + 1); //4a - flags_eor_w(); -} - -/************************ - *** 0x41: eor (dp,x) *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; aal - [5 ] 0,d+dp+x+1 ; aah - [6 ] dbr,aa ; data low - [6a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_eor_idpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5 - regs.a.l ^= op_read(OPMODE_DBR, aa.w); //6 - flags_eor_b(); -} - -void bCPU::op_eor_idpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5 - regs.a.l ^= op_read(OPMODE_DBR, aa.w); //6 - regs.a.h ^= op_read(OPMODE_DBR, aa.w + 1); //6a - flags_eor_w(); -} - -/************************ - *** 0x51: eor (dp),y *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [4a] dbr,aah,aal+yl ; io [4] - [5 ] dbr,aa+y ; data low - [5a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_eor_idpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - cpu_c4(aa.w, aa.w + regs.y.w); //4a - regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //5 - flags_eor_b(); -} - -void bCPU::op_eor_idpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - cpu_c4(aa.w, aa.w + regs.y.w); //4a - regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //5 - regs.a.h ^= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a - flags_eor_w(); -} - -/************************ - *** 0x57: eor [dp],y *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] 0,d+dp+2 ; aab - [6 ] aab,aa+y ; data low - [6a] aab,aa+y+1 ; data high [1] -*/ -void bCPU::op_eor_ildpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - regs.a.l ^= op_read(OPMODE_LONG, aa.d + regs.y.w); //6 - flags_eor_b(); -} - -void bCPU::op_eor_ildpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - regs.a.l ^= op_read(OPMODE_LONG, aa.d + regs.y.w); //6 - regs.a.h ^= op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a - flags_eor_w(); -} - -/********************** - *** 0x43: eor sr,s *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; sp - [3 ] pbr,pc+1 ; io - [4 ] 0,s+sp ; data low - [4a] 0,s+sp+1 ; data high [1] -*/ -void bCPU::op_eor_srb() { - sp = op_read(); //2 - cpu_io(); //3 - regs.a.l ^= op_read(OPMODE_SP, sp); //4 - flags_eor_b(); -} - -void bCPU::op_eor_srw() { - sp = op_read(); //2 - cpu_io(); //3 - regs.a.l ^= op_read(OPMODE_SP, sp); //4 - regs.a.h ^= op_read(OPMODE_SP, sp + 1); //4a - flags_eor_w(); -} - -/************************** - *** 0x53: eor (sr,s),y *** - ************************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; sp - [3 ] pbr,pc+1 ; io - [4 ] 0,s+sp ; aal - [5 ] 0,s+sp+1 ; aah - [6 ] 0,s+sp+1 ; io - [7 ] dbr,aa+y ; data low - [7a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_eor_isryb() { - sp = op_read(); //2 - cpu_io(); //3 - aa.l = op_read(OPMODE_SP, sp); //4 - aa.h = op_read(OPMODE_SP, sp + 1); //5 - cpu_io(); //6 - regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //7 - flags_eor_b(); -} - -void bCPU::op_eor_isryw() { - sp = op_read(); //2 - cpu_io(); //3 - aa.l = op_read(OPMODE_SP, sp); //4 - aa.h = op_read(OPMODE_SP, sp + 1); //5 - cpu_io(); //6 - regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //7 - regs.a.h ^= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a - flags_eor_w(); -} diff --git a/src/cpu/bcpu/bcpu_op_incdec.cpp b/src/cpu/bcpu/bcpu_op_incdec.cpp deleted file mode 100644 index 64a28e0c..00000000 --- a/src/cpu/bcpu/bcpu_op_incdec.cpp +++ /dev/null @@ -1,433 +0,0 @@ -/***************** - *** 0x1a: inc *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_incb() { - cpu_io(); //2 - regs.a.l++; - regs.p.n = !!(regs.a.l & 0x80); - regs.p.z = (regs.a.l == 0); -} - -void bCPU::op_incw() { - cpu_io(); //2 - regs.a.w++; - regs.p.n = !!(regs.a.w & 0x8000); - regs.p.z = (regs.a.w == 0); -} - -/********************** - *** 0xee: inc addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] - [5 ] dbr,aa+1 ; io - [6a] dbr,aa+1 ; data high [1] - [6 ] dbr,aa ; data low -*/ -void bCPU::op_inc_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - rd.l++; - cpu_io(); //5 - op_write(OPMODE_DBR, aa.w, rd.l); //6 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_inc_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a - rd.w++; - cpu_io(); //5 - op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a - op_write(OPMODE_DBR, aa.w, rd.l); //6 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/************************ - *** 0xfe: inc addr,x *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aah,aal+xl ; io - [5 ] dbr,aa+x ; data low - [5a] dbr,aa+x+1 ; data high [1] - [6 ] dbr,aa+x+1 ; io - [7a] dbr,aa+x+1 ; data high [1] - [7 ] dbr,aa+x ; data low -*/ -void bCPU::op_inc_addrxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_io(); //4 - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5 - rd.l++; - cpu_io(); //6 - op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_inc_addrxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_io(); //4 - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5 - rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a - rd.w++; - cpu_io(); //6 - op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a - op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/******************** - *** 0xe6: inc dp *** - ******************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] - [4 ] 0,d+dp+1 ; io - [5a] 0,d+dp+1 ; data high [1] - [5 ] 0,d+dp ; data low -*/ -void bCPU::op_inc_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - rd.l++; - cpu_io(); //4 - op_write(OPMODE_DP, dp, rd.l); //5 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_inc_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - rd.h = op_read(OPMODE_DP, dp + 1); //3a - rd.w++; - cpu_io(); //4 - op_write(OPMODE_DP, dp + 1, rd.h); //5a - op_write(OPMODE_DP, dp, rd.l); //5 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/********************** - *** 0xf6: inc dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high [1] - [5 ] 0,d+dp+x+1 ; io - [6a] 0,d+dp+x+1 ; data high [1] - [6 ] 0,d+dp+x ; data low -*/ -void bCPU::op_inc_dpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - rd.l++; - cpu_io(); //5 - op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_inc_dpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a - rd.w++; - cpu_io(); //5 - op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a - op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/***************** - *** 0xe8: inx *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_inxb() { - cpu_io(); //2 - regs.x.l++; - regs.p.n = !!(regs.x.l & 0x80); - regs.p.z = (regs.x.l == 0); -} - -void bCPU::op_inxw() { - cpu_io(); //2 - regs.x.w++; - regs.p.n = !!(regs.x.w & 0x8000); - regs.p.z = (regs.x.w == 0); -} - -/***************** - *** 0xc8: iny *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_inyb() { - cpu_io(); //2 - regs.y.l++; - regs.p.n = !!(regs.y.l & 0x80); - regs.p.z = (regs.y.l == 0); -} - -void bCPU::op_inyw() { - cpu_io(); //2 - regs.y.w++; - regs.p.n = !!(regs.y.w & 0x8000); - regs.p.z = (regs.y.w == 0); -} - -/***************** - *** 0x3a: dec *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_decb() { - cpu_io(); //2 - regs.a.l--; - regs.p.n = !!(regs.a.l & 0x80); - regs.p.z = (regs.a.l == 0); -} - -void bCPU::op_decw() { - cpu_io(); //2 - regs.a.w--; - regs.p.n = !!(regs.a.w & 0x8000); - regs.p.z = (regs.a.w == 0); -} - -/********************** - *** 0xce: dec addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] - [5 ] dbr,aa+1 ; io - [6a] dbr,aa+1 ; data high [1] - [6 ] dbr,aa ; data low -*/ -void bCPU::op_dec_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - rd.l--; - cpu_io(); //5 - op_write(OPMODE_DBR, aa.w, rd.l); //6 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_dec_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a - rd.w--; - cpu_io(); //5 - op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a - op_write(OPMODE_DBR, aa.w, rd.l); //6 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/************************ - *** 0xde: dec addr,x *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aah,aal+xl ; io - [5 ] dbr,aa+x ; data low - [5a] dbr,aa+x+1 ; data high [1] - [6 ] dbr,aa+x+1 ; io - [7a] dbr,aa+x+1 ; data high [1] - [7 ] dbr,aa+x ; data low -*/ -void bCPU::op_dec_addrxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_io(); //4 - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5 - rd.l--; - cpu_io(); //6 - op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_dec_addrxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_io(); //4 - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5 - rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a - rd.w--; - cpu_io(); //6 - op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a - op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/******************** - *** 0xc6: dec dp *** - ******************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] - [4 ] 0,d+dp+1 ; io - [5a] 0,d+dp+1 ; data high [1] - [5 ] 0,d+dp ; data low -*/ -void bCPU::op_dec_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - rd.l--; - cpu_io(); //4 - op_write(OPMODE_DP, dp, rd.l); //5 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_dec_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - rd.h = op_read(OPMODE_DP, dp + 1); //3a - rd.w--; - cpu_io(); //4 - op_write(OPMODE_DP, dp + 1, rd.h); //5a - op_write(OPMODE_DP, dp, rd.l); //5 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/********************** - *** 0xd6: dec dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high [1] - [5 ] 0,d+dp+x+1 ; io - [6a] 0,d+dp+x+1 ; data high [1] - [6 ] 0,d+dp+x ; data low -*/ -void bCPU::op_dec_dpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - rd.l--; - cpu_io(); //5 - op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_dec_dpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a - rd.w--; - cpu_io(); //5 - op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a - op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/***************** - *** 0xca: dex *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_dexb() { - cpu_io(); //2 - regs.x.l--; - regs.p.n = !!(regs.x.l & 0x80); - regs.p.z = (regs.x.l == 0); -} - -void bCPU::op_dexw() { - cpu_io(); //2 - regs.x.w--; - regs.p.n = !!(regs.x.w & 0x8000); - regs.p.z = (regs.x.w == 0); -} - -/***************** - *** 0x88: dey *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_deyb() { - cpu_io(); //2 - regs.y.l--; - regs.p.n = !!(regs.y.l & 0x80); - regs.p.z = (regs.y.l == 0); -} - -void bCPU::op_deyw() { - cpu_io(); //2 - regs.y.w--; - regs.p.n = !!(regs.y.w & 0x8000); - regs.p.z = (regs.y.w == 0); -} diff --git a/src/cpu/bcpu/bcpu_op_lda.cpp b/src/cpu/bcpu/bcpu_op_lda.cpp deleted file mode 100644 index 09acc1a6..00000000 --- a/src/cpu/bcpu/bcpu_op_lda.cpp +++ /dev/null @@ -1,444 +0,0 @@ -inline void bCPU::flags_lda_b() { - regs.p.n = !!(regs.a.l & 0x80); - regs.p.z = (regs.a.l == 0); -} - -inline void bCPU::flags_lda_w() { - regs.p.n = !!(regs.a.w & 0x8000); - regs.p.z = (regs.a.w == 0); -} - -/************************ - *** 0xa9: lda #const *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; idl - [2a] pbr,pc+2 ; idh [1] -*/ -void bCPU::op_lda_constb() { - regs.a.l = op_read(); //2 - flags_lda_b(); -} - -void bCPU::op_lda_constw() { - regs.a.l = op_read(); //2 - regs.a.h = op_read(); //2a - flags_lda_w(); -} - -/********************** - *** 0xad: lda addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_lda_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - regs.a.l = op_read(OPMODE_DBR, aa.w); //4 - flags_lda_b(); -} - -void bCPU::op_lda_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - regs.a.l = op_read(OPMODE_DBR, aa.w); //4 - regs.a.h = op_read(OPMODE_DBR, aa.w + 1); //4a - flags_lda_w(); -} - -/************************ - *** 0xbd: lda addr,x *** - ************************ -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+xl ; io [4] - [4 ] dbr,aa+x ; data low - [4a] dbr,aa+x+1 ; data high [1] -*/ -void bCPU::op_lda_addrxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - regs.a.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - flags_lda_b(); -} - -void bCPU::op_lda_addrxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - regs.a.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - regs.a.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a - flags_lda_w(); -} - -/******************** - *** 0xa5: lda dp *** - ******************** -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] -*/ -void bCPU::op_lda_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - regs.a.l = op_read(OPMODE_DP, dp); //3 - flags_lda_b(); -} - -void bCPU::op_lda_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - regs.a.l = op_read(OPMODE_DP, dp); //3 - regs.a.h = op_read(OPMODE_DP, dp + 1); //3a - flags_lda_w(); -} - -/********************** - *** 0xb2: lda (dp) *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] dbr,aa ; data low - [5a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_lda_idpb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - regs.a.l = op_read(OPMODE_DBR, aa.w); //5 - flags_lda_b(); -} - -void bCPU::op_lda_idpw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - regs.a.l = op_read(OPMODE_DBR, aa.w); //5 - regs.a.h = op_read(OPMODE_DBR, aa.w + 1); //5 - flags_lda_w(); -} - -/********************** - *** 0xa7: lda [dp] *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] 0,d+dp+2 ; aab - [6 ] aab,aa ; data low - [6a] aab,aa+1 ; data high [1] -*/ -void bCPU::op_lda_ildpb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - regs.a.l = op_read(OPMODE_LONG, aa.d); //6 - flags_lda_b(); -} - -void bCPU::op_lda_ildpw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - regs.a.l = op_read(OPMODE_LONG, aa.d); //6 - regs.a.h = op_read(OPMODE_LONG, aa.d + 1); //6a - flags_lda_w(); -} - -/********************** - *** 0xaf: lda long *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] pbr,pc+3 ; aab - [5 ] aab,aa ; data low - [5a] aab,aa+1 ; data high -*/ -void bCPU::op_lda_longb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - regs.a.l = op_read(OPMODE_LONG, aa.d); //5 - flags_lda_b(); -} - -void bCPU::op_lda_longw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - regs.a.l = op_read(OPMODE_LONG, aa.d); //5 - regs.a.h = op_read(OPMODE_LONG, aa.d + 1); //5a - flags_lda_w(); -} - -/************************ - *** 0xbf: lda long,x *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] pbr,pc+3 ; aab - [5 ] aab,aa+x ; data low - [5a] aab,aa+x+1 ; data high -*/ -void bCPU::op_lda_longxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - regs.a.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5 - flags_lda_b(); -} - -void bCPU::op_lda_longxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - regs.a.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5 - regs.a.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a - flags_lda_w(); -} - -/************************ - *** 0xb9: lda addr,y *** - ************************ -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+yl ; io [4] - [4 ] dbr,aa+y ; data low - [4a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_lda_addryb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4 - flags_lda_b(); -} - -void bCPU::op_lda_addryw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4 - regs.a.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a - flags_lda_w(); -} - -/********************** - *** 0xb5: lda dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high -*/ -void bCPU::op_lda_dpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - regs.a.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - flags_lda_b(); -} - -void bCPU::op_lda_dpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - regs.a.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - regs.a.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a - flags_lda_w(); -} - -/************************ - *** 0xa1: lda (dp,x) *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; aal - [5 ] 0,d+dp+x+1 ; aah - [6 ] dbr,aa ; data low - [6a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_lda_idpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5 - regs.a.l = op_read(OPMODE_DBR, aa.w); //6 - flags_lda_b(); -} - -void bCPU::op_lda_idpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5 - regs.a.l = op_read(OPMODE_DBR, aa.w); //6 - regs.a.h = op_read(OPMODE_DBR, aa.w + 1); //6a - flags_lda_w(); -} - -/************************ - *** 0xb1: lda (dp),y *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [4a] dbr,aah,aal+yl ; io [4] - [5 ] dbr,aa+y ; data low - [5a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_lda_idpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - cpu_c4(aa.w, aa.w + regs.y.w); //4a - regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5 - flags_lda_b(); -} - -void bCPU::op_lda_idpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - cpu_c4(aa.w, aa.w + regs.y.w); //4a - regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5 - regs.a.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a - flags_lda_w(); -} - -/************************ - *** 0xb7: lda [dp],y *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] 0,d+dp+2 ; aab - [6 ] aab,aa+y ; data low - [6a] aab,aa+y+1 ; data high [1] -*/ -void bCPU::op_lda_ildpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - regs.a.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6 - flags_lda_b(); -} - -void bCPU::op_lda_ildpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - regs.a.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6 - regs.a.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a - flags_lda_w(); -} - -/********************** - *** 0xa3: lda sr,s *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; sp - [3 ] pbr,pc+1 ; io - [4 ] 0,s+sp ; data low - [4a] 0,s+sp+1 ; data high [1] -*/ -void bCPU::op_lda_srb() { - sp = op_read(); //2 - cpu_io(); //3 - regs.a.l = op_read(OPMODE_SP, sp); //4 - flags_lda_b(); -} - -void bCPU::op_lda_srw() { - sp = op_read(); //2 - cpu_io(); //3 - regs.a.l = op_read(OPMODE_SP, sp); //4 - regs.a.h = op_read(OPMODE_SP, sp + 1); //4a - flags_lda_w(); -} - -/************************** - *** 0xb3: lda (sr,s),y *** - ************************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; sp - [3 ] pbr,pc+1 ; io - [4 ] 0,s+sp ; aal - [5 ] 0,s+sp+1 ; aah - [6 ] 0,s+sp+1 ; io - [7 ] dbr,aa+y ; data low - [7a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_lda_isryb() { - sp = op_read(); //2 - cpu_io(); //3 - aa.l = op_read(OPMODE_SP, sp); //4 - aa.h = op_read(OPMODE_SP, sp + 1); //5 - cpu_io(); //6 - regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7 - flags_lda_b(); -} - -void bCPU::op_lda_isryw() { - sp = op_read(); //2 - cpu_io(); //3 - aa.l = op_read(OPMODE_SP, sp); //4 - aa.h = op_read(OPMODE_SP, sp + 1); //5 - cpu_io(); //6 - regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7 - regs.a.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a - flags_lda_w(); -} diff --git a/src/cpu/bcpu/bcpu_op_misc.cpp b/src/cpu/bcpu/bcpu_op_misc.cpp index f09ded99..e37c6e5f 100644 --- a/src/cpu/bcpu/bcpu_op_misc.cpp +++ b/src/cpu/bcpu/bcpu_op_misc.cpp @@ -1,829 +1,19 @@ -inline void bCPU::flags_bit_b() { - regs.p.n = !!(rd.l & 0x80); - regs.p.v = !!(rd.l & 0x40); - regs.p.z = ((rd.l & regs.a.l) == 0); +void bCPU::op_nop() { +l1: + cpu_io(); } -inline void bCPU::flags_bit_w() { - regs.p.n = !!(rd.w & 0x8000); - regs.p.v = !!(rd.w & 0x4000); - regs.p.z = ((rd.w & regs.a.w) == 0); +void bCPU::op_wdm() { +l1: + cpu_io(); + regs.pc.w++; } -/************************ - *** 0x89: bit #const *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; idl - [2a] pbr,pc+2 ; idh [1] -*/ -void bCPU::op_bit_constb() { - rd.l = op_read(); //2 - regs.p.z = ((rd.l & regs.a.l) == 0); -} - -void bCPU::op_bit_constw() { - rd.l = op_read(); //2 - rd.h = op_read(); //2a - regs.p.z = ((rd.w & regs.a.w) == 0); -} - -/********************** - *** 0x2c: bit addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_bit_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - flags_bit_b(); -} - -void bCPU::op_bit_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a - flags_bit_w(); -} - -/************************ - *** 0x3c: bit addr,x *** - ************************ -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+xl ; io [4] - [4 ] dbr,aa+x ; data low - [4a] dbr,aa+x+1 ; data high [1] -*/ -void bCPU::op_bit_addrxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - flags_bit_b(); -} - -void bCPU::op_bit_addrxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a - flags_bit_w(); -} - -/******************** - *** 0x24: bit dp *** - ******************** -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] -*/ -void bCPU::op_bit_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - flags_bit_b(); -} - -void bCPU::op_bit_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - rd.h = op_read(OPMODE_DP, dp + 1); //3a - flags_bit_w(); -} - -/********************** - *** 0x34: bit dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high -*/ -void bCPU::op_bit_dpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - flags_bit_b(); -} - -void bCPU::op_bit_dpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a - flags_bit_w(); -} - -inline void bCPU::flags_cpx_b() { -int32 r = regs.x.l - rd.l; - regs.p.n = !!(r & 0x80); - regs.p.z = ((uint8)r == 0); - regs.p.c = (r >= 0); -} - -inline void bCPU::flags_cpx_w() { -int32 r = regs.x.w - rd.w; - regs.p.n = !!(r & 0x8000); - regs.p.z = ((uint16)r == 0); - regs.p.c = (r >= 0); -} - -/************************ - *** 0xe0: cpx #const *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; idl - [2a] pbr,pc+2 ; idh [1] -*/ -void bCPU::op_cpx_constb() { - rd.l = op_read(); //2 - flags_cpx_b(); -} - -void bCPU::op_cpx_constw() { - rd.l = op_read(); //2 - rd.h = op_read(); //2a - flags_cpx_w(); -} - -/********************** - *** 0xec: cpx addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_cpx_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - flags_cpx_b(); -} - -void bCPU::op_cpx_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a - flags_cpx_w(); -} - -/******************** - *** 0xe4: cpx dp *** - ******************** -cycles: - [1 ] pbr,pc ; opercmp - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] -*/ -void bCPU::op_cpx_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - flags_cpx_b(); -} - -void bCPU::op_cpx_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - rd.h = op_read(OPMODE_DP, dp + 1); //3a - flags_cpx_w(); -} - -inline void bCPU::flags_cpy_b() { -int32 r = regs.y.l - rd.l; - regs.p.n = !!(r & 0x80); - regs.p.z = ((uint8)r == 0); - regs.p.c = (r >= 0); -} - -inline void bCPU::flags_cpy_w() { -int32 r = regs.y.w - rd.w; - regs.p.n = !!(r & 0x8000); - regs.p.z = ((uint16)r == 0); - regs.p.c = (r >= 0); -} - -/************************ - *** 0xc0: cpy #const *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; idl - [2a] pbr,pc+2 ; idh [1] -*/ -void bCPU::op_cpy_constb() { - rd.l = op_read(); //2 - flags_cpy_b(); -} - -void bCPU::op_cpy_constw() { - rd.l = op_read(); //2 - rd.h = op_read(); //2a - flags_cpy_w(); -} - -/********************** - *** 0xcc: cpy addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_cpy_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - flags_cpy_b(); -} - -void bCPU::op_cpy_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a - flags_cpy_w(); -} - -/******************** - *** 0xc4: cpy dp *** - ******************** -cycles: - [1 ] pbr,pc ; opercmp - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] -*/ -void bCPU::op_cpy_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - flags_cpy_b(); -} - -void bCPU::op_cpy_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - rd.h = op_read(OPMODE_DP, dp + 1); //3a - flags_cpy_w(); -} - -inline void bCPU::flags_ldx_b() { - regs.p.n = !!(regs.x.l & 0x80); - regs.p.z = (regs.x.l == 0); -} - -inline void bCPU::flags_ldx_w() { - regs.p.n = !!(regs.x.w & 0x8000); - regs.p.z = (regs.x.w == 0); -} - -/************************ - *** 0xa2: ldx #const *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; idl - [2a] pbr,pc+2 ; idh [1] -*/ -void bCPU::op_ldx_constb() { - regs.x.l = op_read(); //2 - flags_ldx_b(); -} - -void bCPU::op_ldx_constw() { - regs.x.l = op_read(); //2 - regs.x.h = op_read(); //2a - flags_ldx_w(); -} - -/********************** - *** 0xae: ldx addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_ldx_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - regs.x.l = op_read(OPMODE_DBR, aa.w); //4 - flags_ldx_b(); -} - -void bCPU::op_ldx_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - regs.x.l = op_read(OPMODE_DBR, aa.w); //4 - regs.x.h = op_read(OPMODE_DBR, aa.w + 1); //4a - flags_ldx_w(); -} - -/************************ - *** 0xbe: ldx addr,y *** - ************************ -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+xl ; io [4] - [4 ] dbr,aa+x ; data low - [4a] dbr,aa+x+1 ; data high [1] -*/ -void bCPU::op_ldx_addryb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - regs.x.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4 - flags_ldx_b(); -} - -void bCPU::op_ldx_addryw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - regs.x.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4 - regs.x.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a - flags_ldx_w(); -} - -/******************** - *** 0xa6: ldx dp *** - ******************** -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] -*/ -void bCPU::op_ldx_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - regs.x.l = op_read(OPMODE_DP, dp); //3 - flags_ldx_b(); -} - -void bCPU::op_ldx_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - regs.x.l = op_read(OPMODE_DP, dp); //3 - regs.x.h = op_read(OPMODE_DP, dp + 1); //3a - flags_ldx_w(); -} - -/********************** - *** 0xb6: ldx dp,y *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high -*/ -void bCPU::op_ldx_dpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - regs.x.l = op_read(OPMODE_DP, dp + regs.y.w); //4 - flags_ldx_b(); -} - -void bCPU::op_ldx_dpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - regs.x.l = op_read(OPMODE_DP, dp + regs.y.w); //4 - regs.x.h = op_read(OPMODE_DP, dp + regs.y.w + 1); //4a - flags_ldx_w(); -} - -inline void bCPU::flags_ldy_b() { - regs.p.n = !!(regs.y.l & 0x80); - regs.p.z = (regs.y.l == 0); -} - -inline void bCPU::flags_ldy_w() { - regs.p.n = !!(regs.y.w & 0x8000); - regs.p.z = (regs.y.w == 0); -} - -/************************ - *** 0xa0: ldy #const *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; idl - [2a] pbr,pc+2 ; idh [1] -*/ -void bCPU::op_ldy_constb() { - regs.y.l = op_read(); //2 - flags_ldy_b(); -} - -void bCPU::op_ldy_constw() { - regs.y.l = op_read(); //2 - regs.y.h = op_read(); //2a - flags_ldy_w(); -} - -/********************** - *** 0xac: ldy addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_ldy_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - regs.y.l = op_read(OPMODE_DBR, aa.w); //4 - flags_ldy_b(); -} - -void bCPU::op_ldy_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - regs.y.l = op_read(OPMODE_DBR, aa.w); //4 - regs.y.h = op_read(OPMODE_DBR, aa.w + 1); //4a - flags_ldy_w(); -} - -/************************ - *** 0xbc: ldy addr,x *** - ************************ -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+xl ; io [4] - [4 ] dbr,aa+x ; data low - [4a] dbr,aa+x+1 ; data high [1] -*/ -void bCPU::op_ldy_addrxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - regs.y.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - flags_ldy_b(); -} - -void bCPU::op_ldy_addrxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - regs.y.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - regs.y.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a - flags_ldy_w(); -} - -/******************** - *** 0xa4: ldy dp *** - ******************** -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] -*/ -void bCPU::op_ldy_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - regs.y.l = op_read(OPMODE_DP, dp); //3 - flags_ldy_b(); -} - -void bCPU::op_ldy_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - regs.y.l = op_read(OPMODE_DP, dp); //3 - regs.y.h = op_read(OPMODE_DP, dp + 1); //3a - flags_ldy_w(); -} - -/********************** - *** 0xb4: ldy dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high -*/ -void bCPU::op_ldy_dpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - regs.y.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - flags_ldy_b(); -} - -void bCPU::op_ldy_dpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - regs.y.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - regs.y.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a - flags_ldy_w(); -} - -/********************** - *** 0x8e: stx addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_stx_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - op_write(OPMODE_DBR, aa.w, regs.x.l); //4 -} - -void bCPU::op_stx_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - op_write(OPMODE_DBR, aa.w, regs.x.l); //4 - op_write(OPMODE_DBR, aa.w + 1, regs.x.h); //4a -} - -/******************** - *** 0x86: stx dp *** - ******************** -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] -*/ -void bCPU::op_stx_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - op_write(OPMODE_DP, dp, regs.x.l); //3 -} - -void bCPU::op_stx_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - op_write(OPMODE_DP, dp, regs.x.l); //3 - op_write(OPMODE_DP, dp + 1, regs.x.h); //3a -} - -/********************** - *** 0x96: stx dp,y *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high -*/ -void bCPU::op_stx_dpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - op_write(OPMODE_DP, dp + regs.y.w, regs.x.l); //4 -} - -void bCPU::op_stx_dpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - op_write(OPMODE_DP, dp + regs.y.w, regs.x.l); //4 - op_write(OPMODE_DP, dp + regs.y.w + 1, regs.x.h); //4a -} - -/********************** - *** 0x8c: sty addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_sty_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - op_write(OPMODE_DBR, aa.w, regs.y.l); //4 -} - -void bCPU::op_sty_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - op_write(OPMODE_DBR, aa.w, regs.y.l); //4 - op_write(OPMODE_DBR, aa.w + 1, regs.y.h); //4a -} - -/******************** - *** 0x84: sty dp *** - ******************** -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] -*/ -void bCPU::op_sty_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - op_write(OPMODE_DP, dp, regs.y.l); //3 -} - -void bCPU::op_sty_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - op_write(OPMODE_DP, dp, regs.y.l); //3 - op_write(OPMODE_DP, dp + 1, regs.y.h); //3a -} - -/********************** - *** 0x94: sty dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high -*/ -void bCPU::op_sty_dpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - op_write(OPMODE_DP, dp + regs.x.w, regs.y.l); //4 -} - -void bCPU::op_sty_dpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - op_write(OPMODE_DP, dp + regs.x.w, regs.y.l); //4 - op_write(OPMODE_DP, dp + regs.x.w + 1, regs.y.h); //4a -} - -/********************** - *** 0x9c: stz addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_stz_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - op_write(OPMODE_DBR, aa.w, 0); //4 -} - -void bCPU::op_stz_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - op_write(OPMODE_DBR, aa.w, 0); //4 - op_write(OPMODE_DBR, aa.w + 1, 0); //4a -} - -/************************ - *** 0x9e: stz addr,x *** - ************************ -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+xl ; io [4] - [4 ] dbr,aa+x ; data low - [4a] dbr,aa+x+1 ; data high [1] -*/ -void bCPU::op_stz_addrxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - op_write(OPMODE_DBR, aa.w + regs.x.w, 0); //4 -} - -void bCPU::op_stz_addrxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - op_write(OPMODE_DBR, aa.w + regs.x.w, 0); //4 - op_write(OPMODE_DBR, aa.w + regs.x.w + 1, 0); //4a -} - -/******************** - *** 0x64: stz dp *** - ******************** -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] -*/ -void bCPU::op_stz_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - op_write(OPMODE_DP, dp, 0); //3 -} - -void bCPU::op_stz_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - op_write(OPMODE_DP, dp, 0); //3 - op_write(OPMODE_DP, dp + 1, 0); //3a -} - -/********************** - *** 0x74: stz dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high -*/ -void bCPU::op_stz_dpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - op_write(OPMODE_DP, dp + regs.x.w, 0); //4 -} - -void bCPU::op_stz_dpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - op_write(OPMODE_DP, dp + regs.x.w, 0); //4 - op_write(OPMODE_DP, dp + regs.x.w + 1, 0); //4a -} - -/***************** - *** 0xeb: xba *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io - [3] pbr,pc+1 ; io -*/ void bCPU::op_xba() { - cpu_io(); //2 - cpu_io(); //3 +l1: + cpu_io(); +l2: + cpu_io(); regs.a.l ^= regs.a.h; regs.a.h ^= regs.a.l; regs.a.l ^= regs.a.h; @@ -831,588 +21,298 @@ void bCPU::op_xba() { regs.p.z = (regs.a.l == 0); } -/********************** - *** 0x1c: trb addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] - [5 ] dbr,aa+1 ; io - [6a] dbr,aa+1 ; data high [1] - [6 ] dbr,aa ; data low -*/ -void bCPU::op_trb_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - cpu_io(); //5 - regs.p.z = ((rd.l & regs.a.l) == 0); - rd.l &= ~regs.a.l; - op_write(OPMODE_DBR, aa.w, rd.l); //6 -} - -void bCPU::op_trb_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a - cpu_io(); //5 - regs.p.z = ((rd.w & regs.a.w) == 0); - rd.w &= ~regs.a.w; - op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a - op_write(OPMODE_DBR, aa.w, rd.l); //6 -} - -/******************** - *** 0x14: trb dp *** - ******************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] - [4 ] 0,d+dp+1 ; io - [5a] 0,d+dp+1 ; data high [1] - [5 ] 0,d+dp ; data low -*/ -void bCPU::op_trb_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - cpu_io(); //4 - regs.p.z = ((rd.l & regs.a.l) == 0); - rd.l &= ~regs.a.l; - op_write(OPMODE_DP, dp, rd.l); //5 -} - -void bCPU::op_trb_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - rd.h = op_read(OPMODE_DP, dp + 1); //3a - cpu_io(); //4 - regs.p.z = ((rd.w & regs.a.w) == 0); - rd.w &= ~regs.a.w; - op_write(OPMODE_DP, dp + 1, rd.h); //5a - op_write(OPMODE_DP, dp, rd.l); //5 -} - -/********************** - *** 0x0c: tsb addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] - [5 ] dbr,aa+1 ; io - [6a] dbr,aa+1 ; data high [1] - [6 ] dbr,aa ; data low -*/ -void bCPU::op_tsb_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - cpu_io(); //5 - regs.p.z = ((rd.l & regs.a.l) == 0); - rd.l |= regs.a.l; - op_write(OPMODE_DBR, aa.w, rd.l); //6 -} - -void bCPU::op_tsb_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a - cpu_io(); //5 - regs.p.z = ((rd.w & regs.a.w) == 0); - rd.w |= regs.a.w; - op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a - op_write(OPMODE_DBR, aa.w, rd.l); //6 -} - -/******************** - *** 0x04: tsb dp *** - ******************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] - [4 ] 0,d+dp+1 ; io - [5a] 0,d+dp+1 ; data high [1] - [5 ] 0,d+dp ; data low -*/ -void bCPU::op_tsb_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - cpu_io(); //4 - regs.p.z = ((rd.l & regs.a.l) == 0); - rd.l |= regs.a.l; - op_write(OPMODE_DP, dp, rd.l); //5 -} - -void bCPU::op_tsb_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - rd.h = op_read(OPMODE_DP, dp + 1); //3a - cpu_io(); //4 - regs.p.z = ((rd.w & regs.a.w) == 0); - rd.w |= regs.a.w; - op_write(OPMODE_DP, dp + 1, rd.h); //5a - op_write(OPMODE_DP, dp, rd.l); //5 -} - -/************************** - *** 0x54: mvn src,dest *** - ************************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; dba - [3] pbr,pc+2 ; sba - [4] sba,x ; src data - [5] dba,y ; dest data - [6] dba,y ; io - [7] dba,y ; io -*/ void bCPU::op_mvn() { -uint32 src, dest; -uint8 sb, db; - db = op_read(); //2 - sb = op_read(); //3 - regs.db = db; - regs.a.w--; - dest = (db << 16) | regs.y.w; - src = (sb << 16) | regs.x.w; - rd.l = op_read(OPMODE_LONG, src); //4 - op_write(OPMODE_LONG, dest, rd.l); //5 - if(regs.p.x) { - regs.x.l++; - regs.y.l++; - } else { - regs.x.w++; - regs.y.w++; - } - if(regs.a.w != 0xffff) { - regs.pc.w -= 3; - } - cpu_io(); //6 - cpu_io(); //7 +l1: + dp = op_read(); +l2: + sp = op_read(); +l3: + regs.db = dp; + rd.l = op_read(OPMODE_LONG, (sp << 16) | regs.x.w); +l4: + op_write(OPMODE_LONG, (dp << 16) | regs.y.w, rd.l); +l5: + cpu_io(); + if(regs.p.x) { regs.x.l++; regs.y.l++; } + else { regs.x.w++; regs.y.w++; } +l6: + cpu_io(); + if(regs.a.w--)regs.pc.w -= 3; } -/************************** - *** 0x44: mvp src,dest *** - ************************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; dba - [3] pbr,pc+2 ; sba - [4] sba,x ; src data - [5] dba,y ; dest data - [6] dba,y ; io - [7] dba,y ; io -*/ void bCPU::op_mvp() { -uint32 src, dest; -uint8 sb, db; - db = op_read(); //2 - sb = op_read(); //3 - regs.db = db; - regs.a.w--; - dest = (db << 16) | regs.y.w; - src = (sb << 16) | regs.x.w; - rd.l = op_read(OPMODE_LONG, src); //4 - op_write(OPMODE_LONG, dest, rd.l); //5 - if(regs.p.x) { - regs.x.l--; - regs.y.l--; - } else { - regs.x.w--; - regs.y.w--; - } - if(regs.a.w != 0xffff) { - regs.pc.w -= 3; - } - cpu_io(); //6 - cpu_io(); //7 +l1: + dp = op_read(); +l2: + sp = op_read(); +l3: + regs.db = dp; + rd.l = op_read(OPMODE_LONG, (sp << 16) | regs.x.w); +l4: + op_write(OPMODE_LONG, (dp << 16) | regs.y.w, rd.l); +l5: + cpu_io(); + if(regs.p.x) { regs.x.l--; regs.y.l--; } + else { regs.x.w--; regs.y.w--; } +l6: + cpu_io(); + if(regs.a.w--)regs.pc.w -= 3; } -/************************ - *** 0x00: brk #const *** - ************************ -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; signature -* [3] 0,s ; pbr [3] - [4] 0,s-1 ; pch - [5] 0,s-2 ; pcl - [6] 0,s-3 ; p - [7] 0,va ; aavl - [8] 0,va+1 ; aavh -*/ void bCPU::op_brk() { -uint16 aavw = (regs.e)?0xfffe:0xffe6; - op_read(); //2 - stack_write(regs.pc.b); //3 - stack_write(regs.pc.h); //4 - stack_write(regs.pc.l); //5 - stack_write(regs.p); //6 - rd.l = op_read(OPMODE_LONG, aavw ); //7 - rd.h = op_read(OPMODE_LONG, aavw + 1); //8 +l1: + op_read(); + if(regs.e)goto l3; +l2: + stack_write(regs.pc.b); +l3: + stack_write(regs.pc.h); +l4: + stack_write(regs.pc.l); +l5: + stack_write(regs.p); +l6: + rd.l = op_read(OPMODE_LONG, (regs.e)?0xfffe:0xffe6); +l7: + rd.h = op_read(OPMODE_LONG, (regs.e)?0xffff:0xffe7); regs.pc.b = 0x00; regs.pc.w = rd.w; - regs.p.i = 1; - regs.p.d = 0; + regs.p.i = 1; + regs.p.d = 0; } -/************************ - *** 0x02: cop #const *** - ************************ -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; signature -* [3] 0,s ; pbr [3] - [4] 0,s-1 ; pch - [5] 0,s-2 ; pcl - [6] 0,s-3 ; p - [7] 0,va ; aavl - [8] 0,va+1 ; aavh -*/ void bCPU::op_cop() { -uint16 aavw = (regs.e)?0xfff4:0xffe4; - op_read(); //2 - stack_write(regs.pc.b); //3 - stack_write(regs.pc.h); //4 - stack_write(regs.pc.l); //5 - stack_write(regs.p); //6 - rd.l = op_read(OPMODE_LONG, aavw ); //7 - rd.h = op_read(OPMODE_LONG, aavw + 1); //8 +l1: + op_read(); + if(regs.e)goto l3; +l2: + stack_write(regs.pc.b); +l3: + stack_write(regs.pc.h); +l4: + stack_write(regs.pc.l); +l5: + stack_write(regs.p); +l6: + rd.l = op_read(OPMODE_LONG, (regs.e)?0xfff4:0xffe4); +l7: + rd.h = op_read(OPMODE_LONG, (regs.e)?0xfff5:0xffe5); regs.pc.b = 0x00; regs.pc.w = rd.w; - regs.p.i = 1; - regs.p.d = 0; + regs.p.i = 1; + regs.p.d = 0; } -/***************** - *** 0xdb: stp *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io - [3] pbr,pc+1 ; io -*/ void bCPU::op_stp() { +l1: cpu_io(); + status.cpu_state = CPUSTATE_STP; +l2: cpu_io(); regs.pc.w--; - cpustate = CPUSTATE_STP; } -/***************** - *** 0xcb: wai *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io - [3] pbr,pc+1 ; io -*/ void bCPU::op_wai() { +l1: cpu_io(); + status.cpu_state = CPUSTATE_WAI; +l2: cpu_io(); regs.pc.w--; - cpustate = CPUSTATE_WAI; } -/***************** - *** 0xfb: xce *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ void bCPU::op_xce() { +l1: + cpu_io(); bool c = regs.p.c; - cpu_io(); //2 regs.p.c = regs.e; regs.e = c; if(regs.e) { - regs.p.m = 1; - regs.p.x = 1; + regs.p |= 0x30; regs.x.h = 0x00; regs.y.h = 0x00; regs.s.h = 0x01; - optbl = optbl_e; - } else { - switch((regs.p >> 4) & 3) { - case 0:optbl = optbl_mx;break; - case 1:optbl = optbl_mX;break; - case 2:optbl = optbl_Mx;break; - case 3:optbl = optbl_MX;break; - } } } -/***************** - *** 0xea: nop *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_nop() { - cpu_io(); //2 -} - -/***************** - *** 0x42: wdm *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_wdm() { - cpu_io(); - regs.pc.w++; -} - -/***************** - *** 0x18: clc *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ void bCPU::op_clc() { +l1: cpu_io(); regs.p.c = 0; } -/***************** - *** 0xd8: cld *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ void bCPU::op_cld() { +l1: cpu_io(); regs.p.d = 0; } -/***************** - *** 0x58: cli *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ void bCPU::op_cli() { +l1: cpu_io(); regs.p.i = 0; } -/***************** - *** 0xb8: clv *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ void bCPU::op_clv() { +l1: cpu_io(); regs.p.v = 0; } -/***************** - *** 0x38: sec *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ void bCPU::op_sec() { +l1: cpu_io(); regs.p.c = 1; } -/***************** - *** 0xf8: sed *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ void bCPU::op_sed() { +l1: cpu_io(); regs.p.d = 1; } -/***************** - *** 0x78: sei *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ void bCPU::op_sei() { +l1: cpu_io(); regs.p.i = 1; } -/************************ - *** 0xc2: rep #const *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; idl - [2a] pbr,pc+1 ; idl -*/ void bCPU::op_rep() { - rd.l = op_read(); //2 - cpu_io(); //2a - regs.p &= ~rd.l; - if(regs.e) { - regs.p |= 0x30; - } else { - switch((regs.p >> 4) & 3) { - case 0:optbl = optbl_mx;break; - case 1:optbl = optbl_mX;break; - case 2:optbl = optbl_Mx;break; - case 3:optbl = optbl_MX;break; - } - } -} - -/************************ - *** 0xe2: sep #const *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; idl - [2a] pbr,pc+1 ; idl -*/ -void bCPU::op_sep() { - rd.l = op_read(); //2 - cpu_io(); //2a - regs.p |= rd.l; - if(regs.e) { - regs.p |= 0x30; - } else { - switch((regs.p >> 4) & 3) { - case 0:optbl = optbl_mx;break; - case 1:optbl = optbl_mX;break; - case 2:optbl = optbl_Mx;break; - case 3:optbl = optbl_MX;break; - } - } +l1: + rd.l = op_read(); +l2: + cpu_io(); + regs.p &=~ rd.l; + if(regs.e)regs.p |= 0x30; if(regs.p.x) { regs.x.h = 0x00; regs.y.h = 0x00; } } -/***************** - *** 0xaa: tax *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_taxb() { - cpu_io(); //2 - regs.x.l = regs.a.l; - regs.p.n = !!(regs.x.l & 0x80); - regs.p.z = (regs.x.l == 0); +void bCPU::op_sep() { +l1: + rd.l = op_read(); +l2: + cpu_io(); + regs.p |= rd.l; + if(regs.e)regs.p |= 0x30; + if(regs.p.x) { + regs.x.h = 0x00; + regs.y.h = 0x00; + } } -void bCPU::op_taxw() { - cpu_io(); //2 - regs.x.w = regs.a.w; - regs.p.n = !!(regs.x.w & 0x8000); - regs.p.z = (regs.x.w == 0); +void bCPU::op_tax() { +l1: + cpu_io(); + if(regs.p.x) { + regs.x.l = regs.a.l; + regs.p.n = !!(regs.x.l & 0x80); + regs.p.z = (regs.x.l == 0); + } else { + regs.x.w = regs.a.w; + regs.p.n = !!(regs.x.w & 0x8000); + regs.p.z = (regs.x.w == 0); + } } -/***************** - *** 0xa8: tay *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_tayb() { - cpu_io(); //2 - regs.y.l = regs.a.l; - regs.p.n = !!(regs.y.l & 0x80); - regs.p.z = (regs.y.l == 0); +void bCPU::op_tay() { +l1: + cpu_io(); + if(regs.p.x) { + regs.y.l = regs.a.l; + regs.p.n = !!(regs.y.l & 0x80); + regs.p.z = (regs.y.l == 0); + } else { + regs.y.w = regs.a.w; + regs.p.n = !!(regs.y.w & 0x8000); + regs.p.z = (regs.y.w == 0); + } } -void bCPU::op_tayw() { - cpu_io(); //2 - regs.y.w = regs.a.w; - regs.p.n = !!(regs.y.w & 0x8000); - regs.p.z = (regs.y.w == 0); +void bCPU::op_txa() { +l1: + cpu_io(); + if(regs.p.m) { + regs.a.l = regs.x.l; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.a.w = regs.x.w; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} + +void bCPU::op_txy() { +l1: + cpu_io(); + if(regs.p.x) { + regs.y.l = regs.x.l; + regs.p.n = !!(regs.y.l & 0x80); + regs.p.z = (regs.y.l == 0); + } else { + regs.y.w = regs.x.w; + regs.p.n = !!(regs.y.w & 0x8000); + regs.p.z = (regs.y.w == 0); + } +} + +void bCPU::op_tya() { +l1: + cpu_io(); + if(regs.p.m) { + regs.a.l = regs.y.l; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.a.w = regs.y.w; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} + +void bCPU::op_tyx() { +l1: + cpu_io(); + if(regs.p.x) { + regs.x.l = regs.y.l; + regs.p.n = !!(regs.x.l & 0x80); + regs.p.z = (regs.x.l == 0); + } else { + regs.x.w = regs.y.w; + regs.p.n = !!(regs.x.w & 0x8000); + regs.p.z = (regs.x.w == 0); + } } -/***************** - *** 0x5b: tcd *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ void bCPU::op_tcd() { - cpu_io(); //2 +l1: + cpu_io(); regs.d.w = regs.a.w; regs.p.n = !!(regs.d.w & 0x8000); regs.p.z = (regs.d.w == 0); } -/***************** - *** 0x1b: tcs *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ void bCPU::op_tcs() { - cpu_io(); //2 +l1: + cpu_io(); regs.s.w = regs.a.w; - if(regs.e) { - regs.s.h = 0x01; - } + if(regs.e)regs.s.h = 0x01; } -/***************** - *** 0x7b: tdc *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ void bCPU::op_tdc() { - cpu_io(); //2 +l1: + cpu_io(); regs.a.w = regs.d.w; regs.p.n = !!(regs.a.w & 0x8000); regs.p.z = (regs.a.w == 0); } -/***************** - *** 0x3b: tsc *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ void bCPU::op_tsc() { - cpu_io(); //2 +l1: + cpu_io(); regs.a.w = regs.s.w; if(regs.e) { regs.p.n = !!(regs.a.l & 0x80); @@ -1423,128 +323,229 @@ void bCPU::op_tsc() { } } -/***************** - *** 0xba: tsx *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_tsxb() { - cpu_io(); //2 - regs.x.l = regs.s.l; - regs.p.n = !!(regs.x.l & 0x80); - regs.p.z = (regs.x.l == 0); +void bCPU::op_tsx() { +l1: + cpu_io(); + if(regs.p.x) { + regs.x.l = regs.s.l; + regs.p.n = !!(regs.x.l & 0x80); + regs.p.z = (regs.x.l == 0); + } else { + regs.x.w = regs.s.w; + regs.p.n = !!(regs.x.w & 0x8000); + regs.p.z = (regs.x.w == 0); + } } -void bCPU::op_tsxw() { - cpu_io(); //2 - regs.x.w = regs.s.w; - regs.p.n = !!(regs.x.w & 0x8000); - regs.p.z = (regs.x.w == 0); +void bCPU::op_txs() { +l1: + cpu_io(); + if(regs.e) { + regs.s.l = regs.x.l; + regs.p.n = !!(regs.s.l & 0x80); + regs.p.z = (regs.s.l == 0); + } else { + regs.s.w = regs.x.w; + regs.p.n = !!(regs.s.w & 0x8000); + regs.p.z = (regs.s.w == 0); + } } -/***************** - *** 0x8a: txa *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_txab() { - cpu_io(); //2 - regs.a.l = regs.x.l; - regs.p.n = !!(regs.a.l & 0x80); - regs.p.z = (regs.a.l == 0); +void bCPU::op_pha() { +l1: + cpu_io(); + if(regs.p.m)goto l3; +l2: + stack_write(regs.a.h); +l3: + stack_write(regs.a.l); } -void bCPU::op_txaw() { - cpu_io(); //2 - regs.a.w = regs.x.w; +void bCPU::op_phx() { +l1: + cpu_io(); + if(regs.p.x)goto l3; +l2: + stack_write(regs.x.h); +l3: + stack_write(regs.x.l); +} + +void bCPU::op_phy() { +l1: + cpu_io(); + if(regs.p.x)goto l3; +l2: + stack_write(regs.y.h); +l3: + stack_write(regs.y.l); +} + +void bCPU::op_phd() { +l1: + cpu_io(); + if(0)goto l3; +l2: + stack_write(regs. d.h); +l3: + stack_write(regs. d.l); +} + +void bCPU::op_phb() { +l1: + cpu_io(); +l2: + stack_write(regs.db); +} + +void bCPU::op_phk() { +l1: + cpu_io(); +l2: + stack_write(regs.pc.b); +} + +void bCPU::op_php() { +l1: + cpu_io(); +l2: + stack_write(regs.p); +} + +void bCPU::op_pla() { +l1: + cpu_io(); +l2: + cpu_io(); +l3: + regs.a.l = stack_read(); + if(regs.p.m) { + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + return; + } +l4: + regs.a.h = stack_read(); regs.p.n = !!(regs.a.w & 0x8000); regs.p.z = (regs.a.w == 0); } -/***************** - *** 0x9a: txs *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_txsb() { - cpu_io(); //2 - regs.s.l = regs.x.l; - regs.p.n = !!(regs.s.l & 0x80); - regs.p.z = (regs.s.l == 0); +void bCPU::op_plx() { +l1: + cpu_io(); +l2: + cpu_io(); +l3: + regs.x.l = stack_read(); + if(regs.p.x) { + regs.p.n = !!(regs.x.l & 0x80); + regs.p.z = (regs.x.l == 0); + return; + } +l4: + regs.x.h = stack_read(); + regs.p.n = !!(regs.x.w & 0x8000); + regs.p.z = (regs.x.w == 0); } -void bCPU::op_txsw() { - cpu_io(); //2 - regs.s.w = regs.x.w; - regs.p.n = !!(regs.s.w & 0x8000); - regs.p.z = (regs.s.w == 0); -} - -/***************** - *** 0x9b: txy *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_txyb() { - cpu_io(); //2 - regs.y.l = regs.x.l; - regs.p.n = !!(regs.y.l & 0x80); - regs.p.z = (regs.y.l == 0); -} - -void bCPU::op_txyw() { - cpu_io(); //2 - regs.y.w = regs.x.w; +void bCPU::op_ply() { +l1: + cpu_io(); +l2: + cpu_io(); +l3: + regs.y.l = stack_read(); + if(regs.p.x) { + regs.p.n = !!(regs.y.l & 0x80); + regs.p.z = (regs.y.l == 0); + return; + } +l4: + regs.y.h = stack_read(); regs.p.n = !!(regs.y.w & 0x8000); regs.p.z = (regs.y.w == 0); } -/***************** - *** 0x98: tya *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_tyab() { - cpu_io(); //2 - regs.a.l = regs.y.l; - regs.p.n = !!(regs.a.l & 0x80); - regs.p.z = (regs.a.l == 0); +void bCPU::op_pld() { +l1: + cpu_io(); +l2: + cpu_io(); +l3: + regs. d.l = stack_read(); + if(0) { + regs.p.n = !!(regs. d.l & 0x80); + regs.p.z = (regs. d.l == 0); + return; + } +l4: + regs. d.h = stack_read(); + regs.p.n = !!(regs. d.w & 0x8000); + regs.p.z = (regs. d.w == 0); } -void bCPU::op_tyaw() { - cpu_io(); //2 - regs.a.w = regs.y.w; - regs.p.n = !!(regs.a.w & 0x8000); - regs.p.z = (regs.a.w == 0); +void bCPU::op_plb() { +l1: + cpu_io(); +l2: + cpu_io(); +l3: + regs.db = stack_read(); + regs.p.n = !!(regs.db & 0x80); + regs.p.z = (regs.db == 0); } -/***************** - *** 0xbb: tyx *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_tyxb() { - cpu_io(); //2 - regs.x.l = regs.y.l; - regs.p.n = !!(regs.x.l & 0x80); - regs.p.z = (regs.x.l == 0); +void bCPU::op_plp() { +l1: + cpu_io(); +l2: + cpu_io(); +l3: + regs.p = stack_read(); + if(regs.e)regs.p |= 0x30; + if(regs.p.x) { + regs.x.h = 0x00; + regs.y.h = 0x00; + } } -void bCPU::op_tyxw() { - cpu_io(); //2 - regs.x.w = regs.y.w; - regs.p.n = !!(regs.x.w & 0x8000); - regs.p.z = (regs.x.w == 0); +void bCPU::op_pea() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + stack_write(aa.h); +l4: + stack_write(aa.l); } + +void bCPU::op_pei() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + stack_write(aa.h); +l6: + stack_write(aa.l); +} + +void bCPU::op_per() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_io(); + rd.w = regs.pc.d + (int16)aa.w; +l4: + stack_write(rd.h); +l5: + stack_write(rd.l); +} + diff --git a/src/cpu/bcpu/bcpu_op_ora.cpp b/src/cpu/bcpu/bcpu_op_ora.cpp deleted file mode 100644 index 33e86b90..00000000 --- a/src/cpu/bcpu/bcpu_op_ora.cpp +++ /dev/null @@ -1,444 +0,0 @@ -inline void bCPU::flags_ora_b() { - regs.p.n = !!(regs.a.l & 0x80); - regs.p.z = (regs.a.l == 0); -} - -inline void bCPU::flags_ora_w() { - regs.p.n = !!(regs.a.w & 0x8000); - regs.p.z = (regs.a.w == 0); -} - -/************************ - *** 0x09: ora #const *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; idl - [2a] pbr,pc+2 ; idh [1] -*/ -void bCPU::op_ora_constb() { - regs.a.l |= op_read(); //2 - flags_ora_b(); -} - -void bCPU::op_ora_constw() { - regs.a.l |= op_read(); //2 - regs.a.h |= op_read(); //2a - flags_ora_w(); -} - -/********************** - *** 0x0d: ora addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_ora_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - regs.a.l |= op_read(OPMODE_DBR, aa.w); //4 - flags_ora_b(); -} - -void bCPU::op_ora_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - regs.a.l |= op_read(OPMODE_DBR, aa.w); //4 - regs.a.h |= op_read(OPMODE_DBR, aa.w + 1); //4a - flags_ora_w(); -} - -/************************ - *** 0x1d: ora addr,x *** - ************************ -cycles: - [1 ] pbr,pc ; operora - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+xl ; io [4] - [4 ] dbr,aa+x ; data low - [4a] dbr,aa+x+1 ; data high [1] -*/ -void bCPU::op_ora_addrxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - flags_ora_b(); -} - -void bCPU::op_ora_addrxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - regs.a.h |= op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a - flags_ora_w(); -} - -/******************** - *** 0x05: ora dp *** - ******************** -cycles: - [1 ] pbr,pc ; operora - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] -*/ -void bCPU::op_ora_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - regs.a.l |= op_read(OPMODE_DP, dp); //3 - flags_ora_b(); -} - -void bCPU::op_ora_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - regs.a.l |= op_read(OPMODE_DP, dp); //3 - regs.a.h |= op_read(OPMODE_DP, dp + 1); //3a - flags_ora_w(); -} - -/********************** - *** 0x12: ora (dp) *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] dbr,aa ; data low - [5a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_ora_idpb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - regs.a.l |= op_read(OPMODE_DBR, aa.w); //5 - flags_ora_b(); -} - -void bCPU::op_ora_idpw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - regs.a.l |= op_read(OPMODE_DBR, aa.w); //5 - regs.a.h |= op_read(OPMODE_DBR, aa.w + 1); //5 - flags_ora_w(); -} - -/********************** - *** 0x07: ora [dp] *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] 0,d+dp+2 ; aab - [6 ] aab,aa ; data low - [6a] aab,aa+1 ; data high [1] -*/ -void bCPU::op_ora_ildpb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - regs.a.l |= op_read(OPMODE_LONG, aa.d); //6 - flags_ora_b(); -} - -void bCPU::op_ora_ildpw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - regs.a.l |= op_read(OPMODE_LONG, aa.d); //6 - regs.a.h |= op_read(OPMODE_LONG, aa.d + 1); //6a - flags_ora_w(); -} - -/********************** - *** 0x0f: ora long *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] pbr,pc+3 ; aab - [5 ] aab,aa ; data low - [5a] aab,aa+1 ; data high -*/ -void bCPU::op_ora_longb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - regs.a.l |= op_read(OPMODE_LONG, aa.d); //5 - flags_ora_b(); -} - -void bCPU::op_ora_longw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - regs.a.l |= op_read(OPMODE_LONG, aa.d); //5 - regs.a.h |= op_read(OPMODE_LONG, aa.d + 1); //5a - flags_ora_w(); -} - -/************************ - *** 0x1f: ora long,x *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] pbr,pc+3 ; aab - [5 ] aab,aa+x ; data low - [5a] aab,aa+x+1 ; data high -*/ -void bCPU::op_ora_longxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - regs.a.l |= op_read(OPMODE_LONG, aa.d + regs.x.w); //5 - flags_ora_b(); -} - -void bCPU::op_ora_longxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - regs.a.l |= op_read(OPMODE_LONG, aa.d + regs.x.w); //5 - regs.a.h |= op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a - flags_ora_w(); -} - -/************************ - *** 0x19: ora addr,y *** - ************************ -cycles: - [1 ] pbr,pc ; operora - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+yl ; io [4] - [4 ] dbr,aa+y ; data low - [4a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_ora_addryb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //4 - flags_ora_b(); -} - -void bCPU::op_ora_addryw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //4 - regs.a.h |= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a - flags_ora_w(); -} - -/********************** - *** 0x15: ora dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high -*/ -void bCPU::op_ora_dpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - regs.a.l |= op_read(OPMODE_DP, dp + regs.x.w); //4 - flags_ora_b(); -} - -void bCPU::op_ora_dpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - regs.a.l |= op_read(OPMODE_DP, dp + regs.x.w); //4 - regs.a.h |= op_read(OPMODE_DP, dp + regs.x.w + 1); //4a - flags_ora_w(); -} - -/************************ - *** 0x01: ora (dp,x) *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; aal - [5 ] 0,d+dp+x+1 ; aah - [6 ] dbr,aa ; data low - [6a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_ora_idpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5 - regs.a.l |= op_read(OPMODE_DBR, aa.w); //6 - flags_ora_b(); -} - -void bCPU::op_ora_idpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5 - regs.a.l |= op_read(OPMODE_DBR, aa.w); //6 - regs.a.h |= op_read(OPMODE_DBR, aa.w + 1); //6a - flags_ora_w(); -} - -/************************ - *** 0x11: ora (dp),y *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [4a] dbr,aah,aal+yl ; io [4] - [5 ] dbr,aa+y ; data low - [5a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_ora_idpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - cpu_c4(aa.w, aa.w + regs.y.w); //4a - regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //5 - flags_ora_b(); -} - -void bCPU::op_ora_idpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - cpu_c4(aa.w, aa.w + regs.y.w); //4a - regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //5 - regs.a.h |= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a - flags_ora_w(); -} - -/************************ - *** 0x17: ora [dp],y *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] 0,d+dp+2 ; aab - [6 ] aab,aa+y ; data low - [6a] aab,aa+y+1 ; data high [1] -*/ -void bCPU::op_ora_ildpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - regs.a.l |= op_read(OPMODE_LONG, aa.d + regs.y.w); //6 - flags_ora_b(); -} - -void bCPU::op_ora_ildpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - regs.a.l |= op_read(OPMODE_LONG, aa.d + regs.y.w); //6 - regs.a.h |= op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a - flags_ora_w(); -} - -/********************** - *** 0x03: ora sr,s *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; sp - [3 ] pbr,pc+1 ; io - [4 ] 0,s+sp ; data low - [4a] 0,s+sp+1 ; data high [1] -*/ -void bCPU::op_ora_srb() { - sp = op_read(); //2 - cpu_io(); //3 - regs.a.l |= op_read(OPMODE_SP, sp); //4 - flags_ora_b(); -} - -void bCPU::op_ora_srw() { - sp = op_read(); //2 - cpu_io(); //3 - regs.a.l |= op_read(OPMODE_SP, sp); //4 - regs.a.h |= op_read(OPMODE_SP, sp + 1); //4a - flags_ora_w(); -} - -/************************** - *** 0x13: ora (sr,s),y *** - ************************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; sp - [3 ] pbr,pc+1 ; io - [4 ] 0,s+sp ; aal - [5 ] 0,s+sp+1 ; aah - [6 ] 0,s+sp+1 ; io - [7 ] dbr,aa+y ; data low - [7a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_ora_isryb() { - sp = op_read(); //2 - cpu_io(); //3 - aa.l = op_read(OPMODE_SP, sp); //4 - aa.h = op_read(OPMODE_SP, sp + 1); //5 - cpu_io(); //6 - regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //7 - flags_ora_b(); -} - -void bCPU::op_ora_isryw() { - sp = op_read(); //2 - cpu_io(); //3 - aa.l = op_read(OPMODE_SP, sp); //4 - aa.h = op_read(OPMODE_SP, sp + 1); //5 - cpu_io(); //6 - regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //7 - regs.a.h |= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a - flags_ora_w(); -} diff --git a/src/cpu/bcpu/bcpu_op_pc.cpp b/src/cpu/bcpu/bcpu_op_pc.cpp index 2ec8b225..c17a7df6 100644 --- a/src/cpu/bcpu/bcpu_op_pc.cpp +++ b/src/cpu/bcpu/bcpu_op_pc.cpp @@ -1,441 +1,310 @@ -/********************** - *** 0x4c: jmp addr *** - ********************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; new pcl - [3] pbr,pc+2 ; new pch -*/ +void bCPU::op_bra() { +l1: + rd.l = op_read(); + if(1) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + return; + } +l2: + cpu_c6(aa.w); +l3: + cpu_io(); +} + +void bCPU::op_bcc() { +l1: + rd.l = op_read(); + if(!regs.p.c) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + return; + } +l2: + cpu_c6(aa.w); +l3: + cpu_io(); +} + +void bCPU::op_bcs() { +l1: + rd.l = op_read(); + if(regs.p.c) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + return; + } +l2: + cpu_c6(aa.w); +l3: + cpu_io(); +} + +void bCPU::op_bne() { +l1: + rd.l = op_read(); + if(!regs.p.z) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + return; + } +l2: + cpu_c6(aa.w); +l3: + cpu_io(); +} + +void bCPU::op_beq() { +l1: + rd.l = op_read(); + if(regs.p.z) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + return; + } +l2: + cpu_c6(aa.w); +l3: + cpu_io(); +} + +void bCPU::op_bpl() { +l1: + rd.l = op_read(); + if(!regs.p.n) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + return; + } +l2: + cpu_c6(aa.w); +l3: + cpu_io(); +} + +void bCPU::op_bmi() { +l1: + rd.l = op_read(); + if(regs.p.n) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + return; + } +l2: + cpu_c6(aa.w); +l3: + cpu_io(); +} + +void bCPU::op_bvc() { +l1: + rd.l = op_read(); + if(!regs.p.v) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + return; + } +l2: + cpu_c6(aa.w); +l3: + cpu_io(); +} + +void bCPU::op_bvs() { +l1: + rd.l = op_read(); + if(regs.p.v) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + return; + } +l2: + cpu_c6(aa.w); +l3: + cpu_io(); +} + +void bCPU::op_brl() { +l1: + rd.l = op_read(); +l2: + rd.h = op_read(); +l3: + cpu_io(); + regs.pc.w = regs.pc.d + (int16)rd.w; +} + void bCPU::op_jmp_addr() { - rd.l = op_read(); //2 - rd.h = op_read(); //3 +l1: + rd.l = op_read(); +l2: + rd.h = op_read(); regs.pc.w = rd.w; } -/********************** - *** 0x5c: jmp long *** - ********************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; new pcl - [3] pbr,pc+2 ; new pch - [4] pbr,pc+3 ; new pbr -*/ void bCPU::op_jmp_long() { - rd.l = op_read(); //2 - rd.h = op_read(); //3 - rd.b = op_read(); //4 - regs.pc.d = rd.d; +l1: + rd.l = op_read(); +l2: + rd.h = op_read(); +l3: + rd.b = op_read(); + regs.pc.d = rd.d & 0xffffff; } -/************************ - *** 0x6c: jmp (addr) *** - ************************ -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; aal - [3] pbr,pc+2 ; aah - [4] 0,aa ; new pcl - [5] 0,aa+1 ; new pch -*/ void bCPU::op_jmp_iaddr() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_ADDR, aa.w); //4 - rd.h = op_read(OPMODE_ADDR, aa.w + 1); //5 +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_ADDR, aa.w); +l4: + rd.h = op_read(OPMODE_ADDR, aa.w + 1); regs.pc.w = rd.w; } -/************************** - *** 0x7c: jmp (addr,x) *** - ************************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; aal - [3] pbr,pc+2 ; aah - [4] pbr,pc+2 ; io - [5] pbr,aa+x ; new pcl - [6] pbr,aa+x+1 ; new pch -*/ void bCPU::op_jmp_iaddrx() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_io(); //4 - rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w); //5 - rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1); //6 +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w); +l5: + rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1); regs.pc.w = rd.w; } -/************************ - *** 0xdc: jmp [addr] *** - ************************ -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; aal - [3] pbr,pc+2 ; aah - [4] 0,aa ; new pcl - [5] 0,aa+1 ; new pch - [6] 0,aa+2 ; new pbr -*/ void bCPU::op_jmp_iladdr() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_ADDR, aa.w); //4 - rd.h = op_read(OPMODE_ADDR, aa.w + 1); //5 - rd.b = op_read(OPMODE_ADDR, aa.w + 2); //6 - regs.pc.d = rd.d; +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_ADDR, aa.w); +l4: + rd.h = op_read(OPMODE_ADDR, aa.w + 1); +l5: + rd.b = op_read(OPMODE_ADDR, aa.w + 2); + regs.pc.d = rd.d & 0xffffff; } -/********************** - *** 0x20: jsr addr *** - ********************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; new pcl - [3] pbr,pc+2 ; new pch - [4] pbr,pc+2 ; io - [5] 0,s ; pch - [6] 0,s-1 ; pcl -*/ void bCPU::op_jsr_addr() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_io(); //4 +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_io(); +l4: regs.pc.w--; - stack_write(regs.pc.h); //5 - stack_write(regs.pc.l); //6 + stack_write(regs.pc.h); +l5: + stack_write(regs.pc.l); regs.pc.w = aa.w; } -/********************** - *** 0x22: jsr long *** - ********************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; new pcl - [3] pbr,pc+2 ; new pch - [4] 0,s ; pbr - [5] 0,s ; io - [6] pbr,pc+3 ; new pbr - [7] 0,s-1 ; pch - [8] 0,s-2 ; pcl -*/ void bCPU::op_jsr_long() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - stack_write(regs.pc.b); //4 - cpu_io(); //5 - aa.b = op_read(); //6 +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + stack_write(regs.pc.b); +l4: + cpu_io(); +l5: + aa.b = op_read(); +l6: regs.pc.w--; - stack_write(regs.pc.h); //7 - stack_write(regs.pc.l); //8 - regs.pc.d = aa.d; + stack_write(regs.pc.h); +l7: + stack_write(regs.pc.l); + regs.pc.d = aa.d & 0xffffff; } -/************************** - *** 0xfc: jsr (addr,x) *** - ************************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; aal - [3] 0,s ; pch - [4] 0,s-1 ; pcl - [5] pbr,pc+2 ; aah - [6] pbr,pc+2 ; io - [7] pbr,aa+x ; new pcl - [8] pbr,aa+x+1 ; new pch -*/ void bCPU::op_jsr_iaddrx() { - aa.l = op_read(); //2 - stack_write(regs.pc.h); //3 - stack_write(regs.pc.l); //4 - aa.h = op_read(); //5 - cpu_io(); //6 - rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w); //7 - rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1); //8 +l1: + aa.l = op_read(); +l2: + stack_write(regs.pc.h); +l3: + stack_write(regs.pc.l); +l4: + aa.h = op_read(); +l5: + cpu_io(); +l6: + rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w); +l7: + rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1); regs.pc.w = rd.w; } -/***************** - *** 0x40: rti *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io - [3] pbr,pc+1 ; io - [4] 0,s+1 ; p - [5] 0,s+2 ; new pcl - [6] 0,s+3 ; new pch - [7] 0,s+4 ; pbr [7] -*/ -void bCPU::op_rtie() { - cpu_io(); //2 - cpu_io(); //3 - regs.p = stack_read(); //4 - rd.l = stack_read(); //5 - rd.h = stack_read(); //6 +void bCPU::op_rti() { +l1: + cpu_io(); +l2: + cpu_io(); +l3: + regs.p = stack_read(); + if(regs.e)regs.p |= 0x30; if(regs.p.x) { regs.x.h = 0x00; regs.y.h = 0x00; } - regs.pc.w = rd.w; +l4: + rd.l = stack_read(); +l5: + rd.h = stack_read(); + if(regs.e) { + regs.pc.w = rd.w; + return; + } +l6: + rd.b = stack_read(); + regs.pc.d = rd.d & 0xffffff; } -void bCPU::op_rtin() { - cpu_io(); //2 - cpu_io(); //3 - regs.p = stack_read(); //4 - rd.l = stack_read(); //5 - rd.h = stack_read(); //6 - rd.b = stack_read(); //7 - if(regs.p.x) { - regs.x.h = 0x00; - regs.y.h = 0x00; - } - regs.pc.d = rd.d; - - switch((regs.p >> 4) & 3) { - case 0:optbl = optbl_mx;break; - case 1:optbl = optbl_mX;break; - case 2:optbl = optbl_Mx;break; - case 3:optbl = optbl_MX;break; - } -} - -/***************** - *** 0x60: rts *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io - [3] pbr,pc+1 ; io - [4] 0,s+1 ; pcl - [5] 0,s+2 ; pch - [6] 0,s+2 ; io -*/ void bCPU::op_rts() { - cpu_io(); //2 - cpu_io(); //3 - rd.l = stack_read(); //4 - rd.h = stack_read(); //5 - cpu_io(); //6 +l1: + cpu_io(); +l2: + cpu_io(); +l3: + rd.l = stack_read(); +l4: + rd.h = stack_read(); +l5: + cpu_io(); regs.pc.w = rd.w; regs.pc.w++; } -/***************** - *** 0x6b: rtl *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io - [3] pbr,pc+1 ; io - [4] 0,s+1 ; pcl - [5] 0,s+2 ; pch - [6] 0,s+3 ; pbr -*/ void bCPU::op_rtl() { - cpu_io(); //2 - cpu_io(); //3 - rd.l = stack_read(); //4 - rd.h = stack_read(); //5 - rd.b = stack_read(); //6 - regs.pc.d = rd.d; +l1: + cpu_io(); +l2: + cpu_io(); +l3: + rd.l = stack_read(); +l4: + rd.h = stack_read(); +l5: + rd.b = stack_read(); + regs.pc.d = rd.d & 0xffffff; regs.pc.w++; } -/********************** - *** 0x80: bra near *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; offset - [2a] pbr,pc+1 ; io [5] - [2b] pbr,pc+1 ; io [6] -*/ -void bCPU::op_bra() { -uint16 r; - rd.l = op_read(); //2 - cpu_io(); //2a - r = regs.pc + (int8)rd.l; - cpu_c6(r); //2b - regs.pc.w = r; -} - -/********************* - *** 0x82: brl far *** - ********************* -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; offset low - [3] pbr,pc+2 ; offset high - [4] pbr,pc+2 ; io -*/ -void bCPU::op_brl() { -uint16 r; - rd.l = op_read(); //2 - rd.h = op_read(); //3 - cpu_io(); //4 - r = regs.pc + (int16)rd.w; - regs.pc.w = r; -} - -/********************** - *** 0x90: bcc near *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; offset - [2a] pbr,pc+1 ; io [5] - [2b] pbr,pc+1 ; io [6] -*/ -void bCPU::op_bcc() { -uint16 r; - rd.l = op_read(); //2 - if(!regs.p.c) { - cpu_io(); //2a - r = regs.pc + (int8)rd.l; - cpu_c6(r); //2b - regs.pc.w = r; - } -} - -/********************** - *** 0xb0: bcs near *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; offset - [2a] pbr,pc+1 ; io [5] - [2b] pbr,pc+1 ; io [6] -*/ -void bCPU::op_bcs() { -uint16 r; - rd.l = op_read(); //2 - if(regs.p.c) { - cpu_io(); //2a - r = regs.pc + (int8)rd.l; - cpu_c6(r); //2b - regs.pc.w = r; - } -} - -/********************** - *** 0xd0: bne near *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; offset - [2a] pbr,pc+1 ; io [5] - [2b] pbr,pc+1 ; io [6] -*/ -void bCPU::op_bne() { -uint16 r; - rd.l = op_read(); //2 - if(!regs.p.z) { - cpu_io(); //2a - r = regs.pc + (int8)rd.l; - cpu_c6(r); //2b - regs.pc.w = r; - } -} - -/********************** - *** 0xf0: beq near *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; offset - [2a] pbr,pc+1 ; io [5] - [2b] pbr,pc+1 ; io [6] -*/ -void bCPU::op_beq() { -uint16 r; - rd.l = op_read(); //2 - if(regs.p.z) { - cpu_io(); //2a - r = regs.pc + (int8)rd.l; - cpu_c6(r); //2b - regs.pc.w = r; - } -} - -/********************** - *** 0x10: bpl near *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; offset - [2a] pbr,pc+1 ; io [5] - [2b] pbr,pc+1 ; io [6] -*/ -void bCPU::op_bpl() { -uint16 r; - rd.l = op_read(); //2 - if(!regs.p.n) { - cpu_io(); //2a - r = regs.pc + (int8)rd.l; - cpu_c6(r); //2b - regs.pc.w = r; - } -} - -/********************** - *** 0x30: bmi near *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; offset - [2a] pbr,pc+1 ; io [5] - [2b] pbr,pc+1 ; io [6] -*/ -void bCPU::op_bmi() { -uint16 r; - rd.l = op_read(); //2 - if(regs.p.n) { - cpu_io(); //2a - r = regs.pc + (int8)rd.l; - cpu_c6(r); //2b - regs.pc.w = r; - } -} - -/********************** - *** 0x50: bvc near *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; offset - [2a] pbr,pc+1 ; io [5] - [2b] pbr,pc+1 ; io [6] -*/ -void bCPU::op_bvc() { -uint16 r; - rd.l = op_read(); //2 - if(!regs.p.v) { - cpu_io(); //2a - r = regs.pc + (int8)rd.l; - cpu_c6(r); //2b - regs.pc.w = r; - } -} - -/********************** - *** 0x70: bvs near *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; offset - [2a] pbr,pc+1 ; io [5] - [2b] pbr,pc+1 ; io [6] -*/ -void bCPU::op_bvs() { -uint16 r; - rd.l = op_read(); //2 - if(regs.p.v) { - cpu_io(); //2a - r = regs.pc + (int8)rd.l; - cpu_c6(r); //2b - regs.pc.w = r; - } -} diff --git a/src/cpu/bcpu/bcpu_op_read.cpp b/src/cpu/bcpu/bcpu_op_read.cpp new file mode 100644 index 00000000..d670a879 --- /dev/null +++ b/src/cpu/bcpu/bcpu_op_read.cpp @@ -0,0 +1,1913 @@ +void bCPU::op_adc_const() { +l1: + rd.l = op_read(); + if(regs.p.m) { op_adc_b(); return; } +l2: + rd.h = op_read(); + op_adc_w(); +} + +void bCPU::op_and_const() { +l1: + rd.l = op_read(); + if(regs.p.m) { op_and_b(); return; } +l2: + rd.h = op_read(); + op_and_w(); +} + +void bCPU::op_cmp_const() { +l1: + rd.l = op_read(); + if(regs.p.m) { op_cmp_b(); return; } +l2: + rd.h = op_read(); + op_cmp_w(); +} + +void bCPU::op_cpx_const() { +l1: + rd.l = op_read(); + if(regs.p.x) { op_cpx_b(); return; } +l2: + rd.h = op_read(); + op_cpx_w(); +} + +void bCPU::op_cpy_const() { +l1: + rd.l = op_read(); + if(regs.p.x) { op_cpy_b(); return; } +l2: + rd.h = op_read(); + op_cpy_w(); +} + +void bCPU::op_eor_const() { +l1: + rd.l = op_read(); + if(regs.p.m) { op_eor_b(); return; } +l2: + rd.h = op_read(); + op_eor_w(); +} + +void bCPU::op_lda_const() { +l1: + rd.l = op_read(); + if(regs.p.m) { op_lda_b(); return; } +l2: + rd.h = op_read(); + op_lda_w(); +} + +void bCPU::op_ldx_const() { +l1: + rd.l = op_read(); + if(regs.p.x) { op_ldx_b(); return; } +l2: + rd.h = op_read(); + op_ldx_w(); +} + +void bCPU::op_ldy_const() { +l1: + rd.l = op_read(); + if(regs.p.x) { op_ldy_b(); return; } +l2: + rd.h = op_read(); + op_ldy_w(); +} + +void bCPU::op_ora_const() { +l1: + rd.l = op_read(); + if(regs.p.m) { op_ora_b(); return; } +l2: + rd.h = op_read(); + op_ora_w(); +} + +void bCPU::op_sbc_const() { +l1: + rd.l = op_read(); + if(regs.p.m) { op_sbc_b(); return; } +l2: + rd.h = op_read(); + op_sbc_w(); +} + +void bCPU::op_adc_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_adc_b(); return; } +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_adc_w(); +} + +void bCPU::op_and_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_and_b(); return; } +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_and_w(); +} + +void bCPU::op_bit_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_bit_b(); return; } +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_bit_w(); +} + +void bCPU::op_cmp_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_cmp_b(); return; } +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_cmp_w(); +} + +void bCPU::op_cpx_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.x) { op_cpx_b(); return; } +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_cpx_w(); +} + +void bCPU::op_cpy_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.x) { op_cpy_b(); return; } +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_cpy_w(); +} + +void bCPU::op_eor_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_eor_b(); return; } +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_eor_w(); +} + +void bCPU::op_lda_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_lda_b(); return; } +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_lda_w(); +} + +void bCPU::op_ldx_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.x) { op_ldx_b(); return; } +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_ldx_w(); +} + +void bCPU::op_ldy_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.x) { op_ldy_b(); return; } +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_ldy_w(); +} + +void bCPU::op_ora_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_ora_b(); return; } +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_ora_w(); +} + +void bCPU::op_sbc_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_sbc_b(); return; } +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_sbc_w(); +} + +void bCPU::op_adc_addrx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.x.w); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); + if(regs.p.m) { op_adc_b(); return; } +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); + op_adc_w(); +} + +void bCPU::op_and_addrx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.x.w); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); + if(regs.p.m) { op_and_b(); return; } +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); + op_and_w(); +} + +void bCPU::op_bit_addrx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.x.w); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); + if(regs.p.m) { op_bit_b(); return; } +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); + op_bit_w(); +} + +void bCPU::op_cmp_addrx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.x.w); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); + if(regs.p.m) { op_cmp_b(); return; } +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); + op_cmp_w(); +} + +void bCPU::op_eor_addrx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.x.w); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); + if(regs.p.m) { op_eor_b(); return; } +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); + op_eor_w(); +} + +void bCPU::op_lda_addrx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.x.w); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); + if(regs.p.m) { op_lda_b(); return; } +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); + op_lda_w(); +} + +void bCPU::op_ldy_addrx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.x.w); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); + if(regs.p.x) { op_ldy_b(); return; } +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); + op_ldy_w(); +} + +void bCPU::op_ora_addrx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.x.w); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); + if(regs.p.m) { op_ora_b(); return; } +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); + op_ora_w(); +} + +void bCPU::op_sbc_addrx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.x.w); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); + if(regs.p.m) { op_sbc_b(); return; } +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); + op_sbc_w(); +} + +void bCPU::op_adc_addry() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.y.w); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_adc_b(); return; } +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_adc_w(); +} + +void bCPU::op_and_addry() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.y.w); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_and_b(); return; } +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_and_w(); +} + +void bCPU::op_cmp_addry() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.y.w); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_cmp_b(); return; } +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_cmp_w(); +} + +void bCPU::op_eor_addry() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.y.w); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_eor_b(); return; } +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_eor_w(); +} + +void bCPU::op_lda_addry() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.y.w); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_lda_b(); return; } +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_lda_w(); +} + +void bCPU::op_ldx_addry() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.y.w); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.x) { op_ldx_b(); return; } +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_ldx_w(); +} + +void bCPU::op_ora_addry() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.y.w); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_ora_b(); return; } +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_ora_w(); +} + +void bCPU::op_sbc_addry() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.y.w); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_sbc_b(); return; } +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_sbc_w(); +} + +void bCPU::op_adc_long() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + aa.b = op_read(); +l4: + rd.l = op_read(OPMODE_LONG, aa.d); + if(regs.p.m) { op_adc_b(); return; } +l5: + rd.h = op_read(OPMODE_LONG, aa.d + 1); + op_adc_w(); +} + +void bCPU::op_and_long() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + aa.b = op_read(); +l4: + rd.l = op_read(OPMODE_LONG, aa.d); + if(regs.p.m) { op_and_b(); return; } +l5: + rd.h = op_read(OPMODE_LONG, aa.d + 1); + op_and_w(); +} + +void bCPU::op_cmp_long() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + aa.b = op_read(); +l4: + rd.l = op_read(OPMODE_LONG, aa.d); + if(regs.p.m) { op_cmp_b(); return; } +l5: + rd.h = op_read(OPMODE_LONG, aa.d + 1); + op_cmp_w(); +} + +void bCPU::op_eor_long() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + aa.b = op_read(); +l4: + rd.l = op_read(OPMODE_LONG, aa.d); + if(regs.p.m) { op_eor_b(); return; } +l5: + rd.h = op_read(OPMODE_LONG, aa.d + 1); + op_eor_w(); +} + +void bCPU::op_lda_long() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + aa.b = op_read(); +l4: + rd.l = op_read(OPMODE_LONG, aa.d); + if(regs.p.m) { op_lda_b(); return; } +l5: + rd.h = op_read(OPMODE_LONG, aa.d + 1); + op_lda_w(); +} + +void bCPU::op_ora_long() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + aa.b = op_read(); +l4: + rd.l = op_read(OPMODE_LONG, aa.d); + if(regs.p.m) { op_ora_b(); return; } +l5: + rd.h = op_read(OPMODE_LONG, aa.d + 1); + op_ora_w(); +} + +void bCPU::op_sbc_long() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + aa.b = op_read(); +l4: + rd.l = op_read(OPMODE_LONG, aa.d); + if(regs.p.m) { op_sbc_b(); return; } +l5: + rd.h = op_read(OPMODE_LONG, aa.d + 1); + op_sbc_w(); +} + +void bCPU::op_adc_longx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + aa.b = op_read(); +l4: + rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); + if(regs.p.m) { op_adc_b(); return; } +l5: + rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); + op_adc_w(); +} + +void bCPU::op_and_longx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + aa.b = op_read(); +l4: + rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); + if(regs.p.m) { op_and_b(); return; } +l5: + rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); + op_and_w(); +} + +void bCPU::op_cmp_longx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + aa.b = op_read(); +l4: + rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); + if(regs.p.m) { op_cmp_b(); return; } +l5: + rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); + op_cmp_w(); +} + +void bCPU::op_eor_longx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + aa.b = op_read(); +l4: + rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); + if(regs.p.m) { op_eor_b(); return; } +l5: + rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); + op_eor_w(); +} + +void bCPU::op_lda_longx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + aa.b = op_read(); +l4: + rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); + if(regs.p.m) { op_lda_b(); return; } +l5: + rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); + op_lda_w(); +} + +void bCPU::op_ora_longx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + aa.b = op_read(); +l4: + rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); + if(regs.p.m) { op_ora_b(); return; } +l5: + rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); + op_ora_w(); +} + +void bCPU::op_sbc_longx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + aa.b = op_read(); +l4: + rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); + if(regs.p.m) { op_sbc_b(); return; } +l5: + rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); + op_sbc_w(); +} + +void bCPU::op_adc_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.m) { op_adc_b(); return; } +l4: + rd.h = op_read(OPMODE_DP, dp + 1); + op_adc_w(); +} + +void bCPU::op_and_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.m) { op_and_b(); return; } +l4: + rd.h = op_read(OPMODE_DP, dp + 1); + op_and_w(); +} + +void bCPU::op_bit_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.m) { op_bit_b(); return; } +l4: + rd.h = op_read(OPMODE_DP, dp + 1); + op_bit_w(); +} + +void bCPU::op_cmp_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.m) { op_cmp_b(); return; } +l4: + rd.h = op_read(OPMODE_DP, dp + 1); + op_cmp_w(); +} + +void bCPU::op_cpx_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.x) { op_cpx_b(); return; } +l4: + rd.h = op_read(OPMODE_DP, dp + 1); + op_cpx_w(); +} + +void bCPU::op_cpy_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.x) { op_cpy_b(); return; } +l4: + rd.h = op_read(OPMODE_DP, dp + 1); + op_cpy_w(); +} + +void bCPU::op_eor_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.m) { op_eor_b(); return; } +l4: + rd.h = op_read(OPMODE_DP, dp + 1); + op_eor_w(); +} + +void bCPU::op_lda_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.m) { op_lda_b(); return; } +l4: + rd.h = op_read(OPMODE_DP, dp + 1); + op_lda_w(); +} + +void bCPU::op_ldx_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.x) { op_ldx_b(); return; } +l4: + rd.h = op_read(OPMODE_DP, dp + 1); + op_ldx_w(); +} + +void bCPU::op_ldy_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.x) { op_ldy_b(); return; } +l4: + rd.h = op_read(OPMODE_DP, dp + 1); + op_ldy_w(); +} + +void bCPU::op_ora_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.m) { op_ora_b(); return; } +l4: + rd.h = op_read(OPMODE_DP, dp + 1); + op_ora_w(); +} + +void bCPU::op_sbc_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.m) { op_sbc_b(); return; } +l4: + rd.h = op_read(OPMODE_DP, dp + 1); + op_sbc_w(); +} + +void bCPU::op_adc_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DP, dp + regs.x.w); + if(regs.p.m) { op_adc_b(); return; } +l5: + rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); + op_adc_w(); +} + +void bCPU::op_and_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DP, dp + regs.x.w); + if(regs.p.m) { op_and_b(); return; } +l5: + rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); + op_and_w(); +} + +void bCPU::op_bit_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DP, dp + regs.x.w); + if(regs.p.m) { op_bit_b(); return; } +l5: + rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); + op_bit_w(); +} + +void bCPU::op_cmp_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DP, dp + regs.x.w); + if(regs.p.m) { op_cmp_b(); return; } +l5: + rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); + op_cmp_w(); +} + +void bCPU::op_eor_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DP, dp + regs.x.w); + if(regs.p.m) { op_eor_b(); return; } +l5: + rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); + op_eor_w(); +} + +void bCPU::op_lda_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DP, dp + regs.x.w); + if(regs.p.m) { op_lda_b(); return; } +l5: + rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); + op_lda_w(); +} + +void bCPU::op_ldy_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DP, dp + regs.x.w); + if(regs.p.x) { op_ldy_b(); return; } +l5: + rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); + op_ldy_w(); +} + +void bCPU::op_ora_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DP, dp + regs.x.w); + if(regs.p.m) { op_ora_b(); return; } +l5: + rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); + op_ora_w(); +} + +void bCPU::op_sbc_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DP, dp + regs.x.w); + if(regs.p.m) { op_sbc_b(); return; } +l5: + rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); + op_sbc_w(); +} + +void bCPU::op_ldx_dpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DP, dp + regs.y.w); + if(regs.p.x) { op_ldx_b(); return; } +l5: + rd.h = op_read(OPMODE_DP, dp + regs.y.w + 1); + op_ldx_w(); +} + +void bCPU::op_adc_idp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_adc_b(); return; } +l6: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_adc_w(); +} + +void bCPU::op_and_idp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_and_b(); return; } +l6: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_and_w(); +} + +void bCPU::op_cmp_idp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_cmp_b(); return; } +l6: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_cmp_w(); +} + +void bCPU::op_eor_idp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_eor_b(); return; } +l6: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_eor_w(); +} + +void bCPU::op_lda_idp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_lda_b(); return; } +l6: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_lda_w(); +} + +void bCPU::op_ora_idp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_ora_b(); return; } +l6: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_ora_w(); +} + +void bCPU::op_sbc_idp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_sbc_b(); return; } +l6: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_sbc_w(); +} + +void bCPU::op_adc_idpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + aa.l = op_read(OPMODE_DP, dp + regs.x.w); +l5: + aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); +l6: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_adc_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_adc_w(); +} + +void bCPU::op_and_idpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + aa.l = op_read(OPMODE_DP, dp + regs.x.w); +l5: + aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); +l6: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_and_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_and_w(); +} + +void bCPU::op_cmp_idpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + aa.l = op_read(OPMODE_DP, dp + regs.x.w); +l5: + aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); +l6: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_cmp_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_cmp_w(); +} + +void bCPU::op_eor_idpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + aa.l = op_read(OPMODE_DP, dp + regs.x.w); +l5: + aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); +l6: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_eor_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_eor_w(); +} + +void bCPU::op_lda_idpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + aa.l = op_read(OPMODE_DP, dp + regs.x.w); +l5: + aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); +l6: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_lda_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_lda_w(); +} + +void bCPU::op_ora_idpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + aa.l = op_read(OPMODE_DP, dp + regs.x.w); +l5: + aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); +l6: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_ora_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_ora_w(); +} + +void bCPU::op_sbc_idpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + aa.l = op_read(OPMODE_DP, dp + regs.x.w); +l5: + aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); +l6: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m) { op_sbc_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + 1); + op_sbc_w(); +} + +void bCPU::op_adc_idpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + cpu_c4(aa.w, aa.w + regs.y.w); +l6: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_adc_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_adc_w(); +} + +void bCPU::op_and_idpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + cpu_c4(aa.w, aa.w + regs.y.w); +l6: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_and_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_and_w(); +} + +void bCPU::op_cmp_idpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + cpu_c4(aa.w, aa.w + regs.y.w); +l6: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_cmp_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_cmp_w(); +} + +void bCPU::op_eor_idpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + cpu_c4(aa.w, aa.w + regs.y.w); +l6: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_eor_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_eor_w(); +} + +void bCPU::op_lda_idpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + cpu_c4(aa.w, aa.w + regs.y.w); +l6: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_lda_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_lda_w(); +} + +void bCPU::op_ora_idpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + cpu_c4(aa.w, aa.w + regs.y.w); +l6: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_ora_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_ora_w(); +} + +void bCPU::op_sbc_idpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + cpu_c4(aa.w, aa.w + regs.y.w); +l6: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_sbc_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_sbc_w(); +} + +void bCPU::op_adc_ildp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + aa.b = op_read(OPMODE_DP, dp + 2); +l6: + rd.l = op_read(OPMODE_LONG, aa.d); + if(regs.p.m) { op_adc_b(); return; } +l7: + rd.h = op_read(OPMODE_LONG, aa.d + 1); + op_adc_w(); +} + +void bCPU::op_and_ildp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + aa.b = op_read(OPMODE_DP, dp + 2); +l6: + rd.l = op_read(OPMODE_LONG, aa.d); + if(regs.p.m) { op_and_b(); return; } +l7: + rd.h = op_read(OPMODE_LONG, aa.d + 1); + op_and_w(); +} + +void bCPU::op_cmp_ildp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + aa.b = op_read(OPMODE_DP, dp + 2); +l6: + rd.l = op_read(OPMODE_LONG, aa.d); + if(regs.p.m) { op_cmp_b(); return; } +l7: + rd.h = op_read(OPMODE_LONG, aa.d + 1); + op_cmp_w(); +} + +void bCPU::op_eor_ildp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + aa.b = op_read(OPMODE_DP, dp + 2); +l6: + rd.l = op_read(OPMODE_LONG, aa.d); + if(regs.p.m) { op_eor_b(); return; } +l7: + rd.h = op_read(OPMODE_LONG, aa.d + 1); + op_eor_w(); +} + +void bCPU::op_lda_ildp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + aa.b = op_read(OPMODE_DP, dp + 2); +l6: + rd.l = op_read(OPMODE_LONG, aa.d); + if(regs.p.m) { op_lda_b(); return; } +l7: + rd.h = op_read(OPMODE_LONG, aa.d + 1); + op_lda_w(); +} + +void bCPU::op_ora_ildp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + aa.b = op_read(OPMODE_DP, dp + 2); +l6: + rd.l = op_read(OPMODE_LONG, aa.d); + if(regs.p.m) { op_ora_b(); return; } +l7: + rd.h = op_read(OPMODE_LONG, aa.d + 1); + op_ora_w(); +} + +void bCPU::op_sbc_ildp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + aa.b = op_read(OPMODE_DP, dp + 2); +l6: + rd.l = op_read(OPMODE_LONG, aa.d); + if(regs.p.m) { op_sbc_b(); return; } +l7: + rd.h = op_read(OPMODE_LONG, aa.d + 1); + op_sbc_w(); +} + +void bCPU::op_adc_ildpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + aa.b = op_read(OPMODE_DP, dp + 2); +l6: + rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); + if(regs.p.m) { op_adc_b(); return; } +l7: + rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); + op_adc_w(); +} + +void bCPU::op_and_ildpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + aa.b = op_read(OPMODE_DP, dp + 2); +l6: + rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); + if(regs.p.m) { op_and_b(); return; } +l7: + rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); + op_and_w(); +} + +void bCPU::op_cmp_ildpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + aa.b = op_read(OPMODE_DP, dp + 2); +l6: + rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); + if(regs.p.m) { op_cmp_b(); return; } +l7: + rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); + op_cmp_w(); +} + +void bCPU::op_eor_ildpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + aa.b = op_read(OPMODE_DP, dp + 2); +l6: + rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); + if(regs.p.m) { op_eor_b(); return; } +l7: + rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); + op_eor_w(); +} + +void bCPU::op_lda_ildpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + aa.b = op_read(OPMODE_DP, dp + 2); +l6: + rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); + if(regs.p.m) { op_lda_b(); return; } +l7: + rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); + op_lda_w(); +} + +void bCPU::op_ora_ildpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + aa.b = op_read(OPMODE_DP, dp + 2); +l6: + rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); + if(regs.p.m) { op_ora_b(); return; } +l7: + rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); + op_ora_w(); +} + +void bCPU::op_sbc_ildpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + aa.b = op_read(OPMODE_DP, dp + 2); +l6: + rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); + if(regs.p.m) { op_sbc_b(); return; } +l7: + rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); + op_sbc_w(); +} + +void bCPU::op_adc_sr() { +l1: + sp = op_read(); +l2: + cpu_io(); +l3: + rd.l = op_read(OPMODE_SP, sp); + if(regs.p.m) { op_adc_b(); return; } +l4: + rd.h = op_read(OPMODE_SP, sp + 1); + op_adc_w(); +} + +void bCPU::op_and_sr() { +l1: + sp = op_read(); +l2: + cpu_io(); +l3: + rd.l = op_read(OPMODE_SP, sp); + if(regs.p.m) { op_and_b(); return; } +l4: + rd.h = op_read(OPMODE_SP, sp + 1); + op_and_w(); +} + +void bCPU::op_cmp_sr() { +l1: + sp = op_read(); +l2: + cpu_io(); +l3: + rd.l = op_read(OPMODE_SP, sp); + if(regs.p.m) { op_cmp_b(); return; } +l4: + rd.h = op_read(OPMODE_SP, sp + 1); + op_cmp_w(); +} + +void bCPU::op_eor_sr() { +l1: + sp = op_read(); +l2: + cpu_io(); +l3: + rd.l = op_read(OPMODE_SP, sp); + if(regs.p.m) { op_eor_b(); return; } +l4: + rd.h = op_read(OPMODE_SP, sp + 1); + op_eor_w(); +} + +void bCPU::op_lda_sr() { +l1: + sp = op_read(); +l2: + cpu_io(); +l3: + rd.l = op_read(OPMODE_SP, sp); + if(regs.p.m) { op_lda_b(); return; } +l4: + rd.h = op_read(OPMODE_SP, sp + 1); + op_lda_w(); +} + +void bCPU::op_ora_sr() { +l1: + sp = op_read(); +l2: + cpu_io(); +l3: + rd.l = op_read(OPMODE_SP, sp); + if(regs.p.m) { op_ora_b(); return; } +l4: + rd.h = op_read(OPMODE_SP, sp + 1); + op_ora_w(); +} + +void bCPU::op_sbc_sr() { +l1: + sp = op_read(); +l2: + cpu_io(); +l3: + rd.l = op_read(OPMODE_SP, sp); + if(regs.p.m) { op_sbc_b(); return; } +l4: + rd.h = op_read(OPMODE_SP, sp + 1); + op_sbc_w(); +} + +void bCPU::op_adc_isry() { +l1: + sp = op_read(); +l2: + cpu_io(); +l3: + aa.l = op_read(OPMODE_SP, sp); +l4: + aa.h = op_read(OPMODE_SP, sp + 1); +l5: + cpu_io(); +l6: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_adc_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_adc_w(); +} + +void bCPU::op_and_isry() { +l1: + sp = op_read(); +l2: + cpu_io(); +l3: + aa.l = op_read(OPMODE_SP, sp); +l4: + aa.h = op_read(OPMODE_SP, sp + 1); +l5: + cpu_io(); +l6: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_and_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_and_w(); +} + +void bCPU::op_cmp_isry() { +l1: + sp = op_read(); +l2: + cpu_io(); +l3: + aa.l = op_read(OPMODE_SP, sp); +l4: + aa.h = op_read(OPMODE_SP, sp + 1); +l5: + cpu_io(); +l6: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_cmp_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_cmp_w(); +} + +void bCPU::op_eor_isry() { +l1: + sp = op_read(); +l2: + cpu_io(); +l3: + aa.l = op_read(OPMODE_SP, sp); +l4: + aa.h = op_read(OPMODE_SP, sp + 1); +l5: + cpu_io(); +l6: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_eor_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_eor_w(); +} + +void bCPU::op_lda_isry() { +l1: + sp = op_read(); +l2: + cpu_io(); +l3: + aa.l = op_read(OPMODE_SP, sp); +l4: + aa.h = op_read(OPMODE_SP, sp + 1); +l5: + cpu_io(); +l6: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_lda_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_lda_w(); +} + +void bCPU::op_ora_isry() { +l1: + sp = op_read(); +l2: + cpu_io(); +l3: + aa.l = op_read(OPMODE_SP, sp); +l4: + aa.h = op_read(OPMODE_SP, sp + 1); +l5: + cpu_io(); +l6: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_ora_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_ora_w(); +} + +void bCPU::op_sbc_isry() { +l1: + sp = op_read(); +l2: + cpu_io(); +l3: + aa.l = op_read(OPMODE_SP, sp); +l4: + aa.h = op_read(OPMODE_SP, sp + 1); +l5: + cpu_io(); +l6: + rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); + if(regs.p.m) { op_sbc_b(); return; } +l7: + rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); + op_sbc_w(); +} + +void bCPU::op_bit_const() { +l1: + rd.l = op_read(); + if(regs.p.m) { + regs.p.z = ((rd.l & regs.a.l) == 0); + return; + } +l2: + rd.h = op_read(); + regs.p.z = ((rd.w & regs.a.w) == 0); +} + diff --git a/src/cpu/bcpu/bcpu_op_rmw.cpp b/src/cpu/bcpu/bcpu_op_rmw.cpp new file mode 100644 index 00000000..6c4af89a --- /dev/null +++ b/src/cpu/bcpu/bcpu_op_rmw.cpp @@ -0,0 +1,740 @@ +void bCPU::op_inc() { +l1: + cpu_io(); + if(regs.p.m) { + regs.a.l++; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.a.w++; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} + +void bCPU::op_inx() { +l1: + cpu_io(); + if(regs.p.x) { + regs.x.l++; + regs.p.n = !!(regs.x.l & 0x80); + regs.p.z = (regs.x.l == 0); + } else { + regs.x.w++; + regs.p.n = !!(regs.x.w & 0x8000); + regs.p.z = (regs.x.w == 0); + } +} + +void bCPU::op_iny() { +l1: + cpu_io(); + if(regs.p.x) { + regs.y.l++; + regs.p.n = !!(regs.y.l & 0x80); + regs.p.z = (regs.y.l == 0); + } else { + regs.y.w++; + regs.p.n = !!(regs.y.w & 0x8000); + regs.p.z = (regs.y.w == 0); + } +} + +void bCPU::op_dec() { +l1: + cpu_io(); + if(regs.p.m) { + regs.a.l--; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.a.w--; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} + +void bCPU::op_dex() { +l1: + cpu_io(); + if(regs.p.x) { + regs.x.l--; + regs.p.n = !!(regs.x.l & 0x80); + regs.p.z = (regs.x.l == 0); + } else { + regs.x.w--; + regs.p.n = !!(regs.x.w & 0x8000); + regs.p.z = (regs.x.w == 0); + } +} + +void bCPU::op_dey() { +l1: + cpu_io(); + if(regs.p.x) { + regs.y.l--; + regs.p.n = !!(regs.y.l & 0x80); + regs.p.z = (regs.y.l == 0); + } else { + regs.y.w--; + regs.p.n = !!(regs.y.w & 0x8000); + regs.p.z = (regs.y.w == 0); + } +} + +void bCPU::op_asl() { +l1: + cpu_io(); + if(regs.p.m) { + 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); + } else { + 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 bCPU::op_lsr() { +l1: + cpu_io(); + if(regs.p.m) { + regs.p.c = regs.a.l & 1; + regs.a.l >>= 1; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.p.c = regs.a.w & 1; + regs.a.w >>= 1; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} + +void bCPU::op_rol() { +l1: + cpu_io(); + uint16 c = regs.p.c; + if(regs.p.m) { + regs.p.c = !!(regs.a.l & 0x80); + regs.a.l <<= 1; + regs.a.l |= c; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.p.c = !!(regs.a.w & 0x8000); + regs.a.w <<= 1; + regs.a.w |= c; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} + +void bCPU::op_ror() { +l1: + cpu_io(); + uint16 c; + if(regs.p.m) { + c = (regs.p.c)?0x80:0; + regs.p.c = regs.a.l & 1; + regs.a.l >>= 1; + regs.a.l |= c; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + c = (regs.p.c)?0x8000:0; + regs.p.c = regs.a.w & 1; + regs.a.w >>= 1; + regs.a.w |= c; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} + +void bCPU::op_inc_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m)goto l5; +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); +l5: + cpu_io(); + if(regs.p.m) { op_inc_b(); goto l7; } + else op_inc_w(); +l6: + op_write(OPMODE_DBR, aa.w + 1, rd.h); +l7: + op_write(OPMODE_DBR, aa.w, rd.l); +} + +void bCPU::op_dec_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m)goto l5; +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); +l5: + cpu_io(); + if(regs.p.m) { op_dec_b(); goto l7; } + else op_dec_w(); +l6: + op_write(OPMODE_DBR, aa.w + 1, rd.h); +l7: + op_write(OPMODE_DBR, aa.w, rd.l); +} + +void bCPU::op_asl_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m)goto l5; +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); +l5: + cpu_io(); + if(regs.p.m) { op_asl_b(); goto l7; } + else op_asl_w(); +l6: + op_write(OPMODE_DBR, aa.w + 1, rd.h); +l7: + op_write(OPMODE_DBR, aa.w, rd.l); +} + +void bCPU::op_lsr_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m)goto l5; +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); +l5: + cpu_io(); + if(regs.p.m) { op_lsr_b(); goto l7; } + else op_lsr_w(); +l6: + op_write(OPMODE_DBR, aa.w + 1, rd.h); +l7: + op_write(OPMODE_DBR, aa.w, rd.l); +} + +void bCPU::op_rol_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m)goto l5; +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); +l5: + cpu_io(); + if(regs.p.m) { op_rol_b(); goto l7; } + else op_rol_w(); +l6: + op_write(OPMODE_DBR, aa.w + 1, rd.h); +l7: + op_write(OPMODE_DBR, aa.w, rd.l); +} + +void bCPU::op_ror_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m)goto l5; +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); +l5: + cpu_io(); + if(regs.p.m) { op_ror_b(); goto l7; } + else op_ror_w(); +l6: + op_write(OPMODE_DBR, aa.w + 1, rd.h); +l7: + op_write(OPMODE_DBR, aa.w, rd.l); +} + +void bCPU::op_trb_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m)goto l5; +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); +l5: + cpu_io(); + if(regs.p.m) { op_trb_b(); goto l7; } + else op_trb_w(); +l6: + op_write(OPMODE_DBR, aa.w + 1, rd.h); +l7: + op_write(OPMODE_DBR, aa.w, rd.l); +} + +void bCPU::op_tsb_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m)goto l5; +l4: + rd.h = op_read(OPMODE_DBR, aa.w + 1); +l5: + cpu_io(); + if(regs.p.m) { op_tsb_b(); goto l7; } + else op_tsb_w(); +l6: + op_write(OPMODE_DBR, aa.w + 1, rd.h); +l7: + op_write(OPMODE_DBR, aa.w, rd.l); +} + +void bCPU::op_inc_addrx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); + if(regs.p.m)goto l6; +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); +l6: + cpu_io(); + if(regs.p.m) { op_inc_b(); goto l8; } + else op_inc_w(); +l7: + op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); +l8: + op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); +} + +void bCPU::op_dec_addrx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); + if(regs.p.m)goto l6; +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); +l6: + cpu_io(); + if(regs.p.m) { op_dec_b(); goto l8; } + else op_dec_w(); +l7: + op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); +l8: + op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); +} + +void bCPU::op_asl_addrx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); + if(regs.p.m)goto l6; +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); +l6: + cpu_io(); + if(regs.p.m) { op_asl_b(); goto l8; } + else op_asl_w(); +l7: + op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); +l8: + op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); +} + +void bCPU::op_lsr_addrx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); + if(regs.p.m)goto l6; +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); +l6: + cpu_io(); + if(regs.p.m) { op_lsr_b(); goto l8; } + else op_lsr_w(); +l7: + op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); +l8: + op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); +} + +void bCPU::op_rol_addrx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); + if(regs.p.m)goto l6; +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); +l6: + cpu_io(); + if(regs.p.m) { op_rol_b(); goto l8; } + else op_rol_w(); +l7: + op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); +l8: + op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); +} + +void bCPU::op_ror_addrx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); + if(regs.p.m)goto l6; +l5: + rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); +l6: + cpu_io(); + if(regs.p.m) { op_ror_b(); goto l8; } + else op_ror_w(); +l7: + op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); +l8: + op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); +} + +void bCPU::op_inc_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.m)goto l5; +l4: + rd.h = op_read(OPMODE_DP, dp + 1); +l5: + cpu_io(); + if(regs.p.m) { op_inc_b(); goto l7; } + else op_inc_w(); +l6: + op_write(OPMODE_DP, dp + 1, rd.h); +l7: + op_write(OPMODE_DP, dp, rd.l); +} + +void bCPU::op_dec_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.m)goto l5; +l4: + rd.h = op_read(OPMODE_DP, dp + 1); +l5: + cpu_io(); + if(regs.p.m) { op_dec_b(); goto l7; } + else op_dec_w(); +l6: + op_write(OPMODE_DP, dp + 1, rd.h); +l7: + op_write(OPMODE_DP, dp, rd.l); +} + +void bCPU::op_asl_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.m)goto l5; +l4: + rd.h = op_read(OPMODE_DP, dp + 1); +l5: + cpu_io(); + if(regs.p.m) { op_asl_b(); goto l7; } + else op_asl_w(); +l6: + op_write(OPMODE_DP, dp + 1, rd.h); +l7: + op_write(OPMODE_DP, dp, rd.l); +} + +void bCPU::op_lsr_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.m)goto l5; +l4: + rd.h = op_read(OPMODE_DP, dp + 1); +l5: + cpu_io(); + if(regs.p.m) { op_lsr_b(); goto l7; } + else op_lsr_w(); +l6: + op_write(OPMODE_DP, dp + 1, rd.h); +l7: + op_write(OPMODE_DP, dp, rd.l); +} + +void bCPU::op_rol_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.m)goto l5; +l4: + rd.h = op_read(OPMODE_DP, dp + 1); +l5: + cpu_io(); + if(regs.p.m) { op_rol_b(); goto l7; } + else op_rol_w(); +l6: + op_write(OPMODE_DP, dp + 1, rd.h); +l7: + op_write(OPMODE_DP, dp, rd.l); +} + +void bCPU::op_ror_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.m)goto l5; +l4: + rd.h = op_read(OPMODE_DP, dp + 1); +l5: + cpu_io(); + if(regs.p.m) { op_ror_b(); goto l7; } + else op_ror_w(); +l6: + op_write(OPMODE_DP, dp + 1, rd.h); +l7: + op_write(OPMODE_DP, dp, rd.l); +} + +void bCPU::op_trb_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.m)goto l5; +l4: + rd.h = op_read(OPMODE_DP, dp + 1); +l5: + cpu_io(); + if(regs.p.m) { op_trb_b(); goto l7; } + else op_trb_w(); +l6: + op_write(OPMODE_DP, dp + 1, rd.h); +l7: + op_write(OPMODE_DP, dp, rd.l); +} + +void bCPU::op_tsb_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + rd.l = op_read(OPMODE_DP, dp); + if(regs.p.m)goto l5; +l4: + rd.h = op_read(OPMODE_DP, dp + 1); +l5: + cpu_io(); + if(regs.p.m) { op_tsb_b(); goto l7; } + else op_tsb_w(); +l6: + op_write(OPMODE_DP, dp + 1, rd.h); +l7: + op_write(OPMODE_DP, dp, rd.l); +} + +void bCPU::op_inc_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DP, dp + regs.x.w); + if(regs.p.m)goto l6; +l5: + rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); +l6: + cpu_io(); + if(regs.p.m) { op_inc_b(); goto l8; } + else op_inc_w(); +l7: + op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); +l8: + op_write(OPMODE_DP, dp + regs.x.w, rd.l); +} + +void bCPU::op_dec_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DP, dp + regs.x.w); + if(regs.p.m)goto l6; +l5: + rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); +l6: + cpu_io(); + if(regs.p.m) { op_dec_b(); goto l8; } + else op_dec_w(); +l7: + op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); +l8: + op_write(OPMODE_DP, dp + regs.x.w, rd.l); +} + +void bCPU::op_asl_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DP, dp + regs.x.w); + if(regs.p.m)goto l6; +l5: + rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); +l6: + cpu_io(); + if(regs.p.m) { op_asl_b(); goto l8; } + else op_asl_w(); +l7: + op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); +l8: + op_write(OPMODE_DP, dp + regs.x.w, rd.l); +} + +void bCPU::op_lsr_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DP, dp + regs.x.w); + if(regs.p.m)goto l6; +l5: + rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); +l6: + cpu_io(); + if(regs.p.m) { op_lsr_b(); goto l8; } + else op_lsr_w(); +l7: + op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); +l8: + op_write(OPMODE_DP, dp + regs.x.w, rd.l); +} + +void bCPU::op_rol_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DP, dp + regs.x.w); + if(regs.p.m)goto l6; +l5: + rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); +l6: + cpu_io(); + if(regs.p.m) { op_rol_b(); goto l8; } + else op_rol_w(); +l7: + op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); +l8: + op_write(OPMODE_DP, dp + regs.x.w, rd.l); +} + +void bCPU::op_ror_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + rd.l = op_read(OPMODE_DP, dp + regs.x.w); + if(regs.p.m)goto l6; +l5: + rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); +l6: + cpu_io(); + if(regs.p.m) { op_ror_b(); goto l8; } + else op_ror_w(); +l7: + op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); +l8: + op_write(OPMODE_DP, dp + regs.x.w, rd.l); +} + diff --git a/src/cpu/bcpu/bcpu_op_sbc.cpp b/src/cpu/bcpu/bcpu_op_sbc.cpp deleted file mode 100644 index 012a7ff5..00000000 --- a/src/cpu/bcpu/bcpu_op_sbc.cpp +++ /dev/null @@ -1,464 +0,0 @@ -inline void bCPU::flags_sbc_b() { -int32 r = regs.a.l - rd.l - !regs.p.c; -//bcd - if(regs.p.d) { - if(((r ) & 15) > 9)r -= 6; - if(((r >> 4) & 15) > 9)r -= 6 << 4; - } - regs.p.n = !!(r & 0x80); - regs.p.v = !!((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80); - regs.p.z = ((byte)r == 0); - regs.p.c = (r >= 0); - regs.a.l = r; -} - -inline void bCPU::flags_sbc_w() { -int32 r = regs.a.w - rd.w - !regs.p.c; -//bcd - if(regs.p.d) { - if(((r ) & 15) > 9)r -= 6; - if(((r >> 4) & 15) > 9)r -= 6 << 4; - if(((r >> 8) & 15) > 9)r -= 6 << 8; - if(((r >> 12) & 15) > 9)r -= 6 << 12; - } - regs.p.n = !!(r & 0x8000); - regs.p.v = !!((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000); - regs.p.z = ((word)r == 0); - regs.p.c = (r >= 0); - regs.a.w = r; -} - -/************************ - *** 0xe9: sbc #const *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; idl - [2a] pbr,pc+2 ; idh [1] -*/ -void bCPU::op_sbc_constb() { - rd.l = op_read(); //2 - flags_sbc_b(); -} - -void bCPU::op_sbc_constw() { - rd.l = op_read(); //2 - rd.h = op_read(); //2a - flags_sbc_w(); -} - -/********************** - *** 0xed: sbc addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_sbc_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - flags_sbc_b(); -} - -void bCPU::op_sbc_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a - flags_sbc_w(); -} - -/************************ - *** 0xfd: sbc addr,x *** - ************************ -cycles: - [1 ] pbr,pc ; opersbc - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+xl ; io [4] - [4 ] dbr,aa+x ; data low - [4a] dbr,aa+x+1 ; data high [1] -*/ -void bCPU::op_sbc_addrxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - flags_sbc_b(); -} - -void bCPU::op_sbc_addrxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a - flags_sbc_w(); -} - -/******************** - *** 0xe5: sbc dp *** - ******************** -cycles: - [1 ] pbr,pc ; opersbc - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] -*/ -void bCPU::op_sbc_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - flags_sbc_b(); -} - -void bCPU::op_sbc_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - rd.h = op_read(OPMODE_DP, dp + 1); //3a - flags_sbc_w(); -} - -/********************** - *** 0xf2: sbc (dp) *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] dbr,aa ; data low - [5a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_sbc_idpb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - rd.l = op_read(OPMODE_DBR, aa.w); //5 - flags_sbc_b(); -} - -void bCPU::op_sbc_idpw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - rd.l = op_read(OPMODE_DBR, aa.w); //5 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //5 - flags_sbc_w(); -} - -/********************** - *** 0xe7: sbc [dp] *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] 0,d+dp+2 ; aab - [6 ] aab,aa ; data low - [6a] aab,aa+1 ; data high [1] -*/ -void bCPU::op_sbc_ildpb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - rd.l = op_read(OPMODE_LONG, aa.d); //6 - flags_sbc_b(); -} - -void bCPU::op_sbc_ildpw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - rd.l = op_read(OPMODE_LONG, aa.d); //6 - rd.h = op_read(OPMODE_LONG, aa.d + 1); //6a - flags_sbc_w(); -} - -/********************** - *** 0xef: sbc long *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] pbr,pc+3 ; aab - [5 ] aab,aa ; data low - [5a] aab,aa+1 ; data high -*/ -void bCPU::op_sbc_longb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - rd.l = op_read(OPMODE_LONG, aa.d); //5 - flags_sbc_b(); -} - -void bCPU::op_sbc_longw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - rd.l = op_read(OPMODE_LONG, aa.d); //5 - rd.h = op_read(OPMODE_LONG, aa.d + 1); //5a - flags_sbc_w(); -} - -/************************ - *** 0xff: sbc long,x *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] pbr,pc+3 ; aab - [5 ] aab,aa+x ; data low - [5a] aab,aa+x+1 ; data high -*/ -void bCPU::op_sbc_longxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5 - flags_sbc_b(); -} - -void bCPU::op_sbc_longxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5 - rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a - flags_sbc_w(); -} - -/************************ - *** 0xf9: sbc addr,y *** - ************************ -cycles: - [1 ] pbr,pc ; opersbc - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+yl ; io [4] - [4 ] dbr,aa+y ; data low - [4a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_sbc_addryb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4 - flags_sbc_b(); -} - -void bCPU::op_sbc_addryw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a - flags_sbc_w(); -} - -/********************** - *** 0xf5: sbc dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high -*/ -void bCPU::op_sbc_dpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - flags_sbc_b(); -} - -void bCPU::op_sbc_dpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a - flags_sbc_w(); -} - -/************************ - *** 0xe1: sbc (dp,x) *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; aal - [5 ] 0,d+dp+x+1 ; aah - [6 ] dbr,aa ; data low - [6a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_sbc_idpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5 - rd.l = op_read(OPMODE_DBR, aa.w); //6 - flags_sbc_b(); -} - -void bCPU::op_sbc_idpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5 - rd.l = op_read(OPMODE_DBR, aa.w); //6 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //6a - flags_sbc_w(); -} - -/************************ - *** 0xf1: sbc (dp),y *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [4a] dbr,aah,aal+yl ; io [4] - [5 ] dbr,aa+y ; data low - [5a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_sbc_idpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - cpu_c4(aa.w, aa.w + regs.y.w); //4a - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5 - flags_sbc_b(); -} - -void bCPU::op_sbc_idpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - cpu_c4(aa.w, aa.w + regs.y.w); //4a - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5 - rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a - flags_sbc_w(); -} - -/************************ - *** 0xf7: sbc [dp],y *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] 0,d+dp+2 ; aab - [6 ] aab,aa+y ; data low - [6a] aab,aa+y+1 ; data high [1] -*/ -void bCPU::op_sbc_ildpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6 - flags_sbc_b(); -} - -void bCPU::op_sbc_ildpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6 - rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a - flags_sbc_w(); -} - -/********************** - *** 0xe3: sbc sr,s *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; sp - [3 ] pbr,pc+1 ; io - [4 ] 0,s+sp ; data low - [4a] 0,s+sp+1 ; data high [1] -*/ -void bCPU::op_sbc_srb() { - sp = op_read(); //2 - cpu_io(); //3 - rd.l = op_read(OPMODE_SP, sp); //4 - flags_sbc_b(); -} - -void bCPU::op_sbc_srw() { - sp = op_read(); //2 - cpu_io(); //3 - rd.l = op_read(OPMODE_SP, sp); //4 - rd.h = op_read(OPMODE_SP, sp + 1); //4a - flags_sbc_w(); -} - -/************************** - *** 0xf3: sbc (sr,s),y *** - ************************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; sp - [3 ] pbr,pc+1 ; io - [4 ] 0,s+sp ; aal - [5 ] 0,s+sp+1 ; aah - [6 ] 0,s+sp+1 ; io - [7 ] dbr,aa+y ; data low - [7a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_sbc_isryb() { - sp = op_read(); //2 - cpu_io(); //3 - aa.l = op_read(OPMODE_SP, sp); //4 - aa.h = op_read(OPMODE_SP, sp + 1); //5 - cpu_io(); //6 - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7 - flags_sbc_b(); -} - -void bCPU::op_sbc_isryw() { - sp = op_read(); //2 - cpu_io(); //3 - aa.l = op_read(OPMODE_SP, sp); //4 - aa.h = op_read(OPMODE_SP, sp + 1); //5 - cpu_io(); //6 - rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7 - rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a - flags_sbc_w(); -} diff --git a/src/cpu/bcpu/bcpu_op_shift.cpp b/src/cpu/bcpu/bcpu_op_shift.cpp deleted file mode 100644 index 23171da3..00000000 --- a/src/cpu/bcpu/bcpu_op_shift.cpp +++ /dev/null @@ -1,779 +0,0 @@ -/***************** - *** 0x0a: asl *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_aslb() { - cpu_io(); //2 - 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 bCPU::op_aslw() { - cpu_io(); //2 - 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); -} - -/********************** - *** 0x0e: asl addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] - [5 ] dbr,aa+1 ; io - [6a] dbr,aa+1 ; data high [1] - [6 ] dbr,aa ; data low -*/ -void bCPU::op_asl_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - regs.p.c = !!(rd.l & 0x80); - rd.l <<= 1; - cpu_io(); //5 - op_write(OPMODE_DBR, aa.w, rd.l); //6 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_asl_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a - regs.p.c = !!(rd.w & 0x8000); - rd.w <<= 1; - cpu_io(); //5 - op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a - op_write(OPMODE_DBR, aa.w, rd.l); //6 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/************************ - *** 0x1e: asl addr,x *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aah,aal+xl ; io - [5 ] dbr,aa+x ; data low - [5a] dbr,aa+x+1 ; data high [1] - [6 ] dbr,aa+x+1 ; io - [7a] dbr,aa+x+1 ; data high [1] - [7 ] dbr,aa+x ; data low -*/ -void bCPU::op_asl_addrxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_io(); //4 - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5 - regs.p.c = !!(rd.l & 0x80); - rd.l <<= 1; - cpu_io(); //6 - op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_asl_addrxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_io(); //4 - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5 - rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a - regs.p.c = !!(rd.w & 0x8000); - rd.w <<= 1; - cpu_io(); //6 - op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a - op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/******************** - *** 0x06: asl dp *** - ******************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] - [4 ] 0,d+dp+1 ; io - [5a] 0,d+dp+1 ; data high [1] - [5 ] 0,d+dp ; data low -*/ -void bCPU::op_asl_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - regs.p.c = !!(rd.l & 0x80); - rd.l <<= 1; - cpu_io(); //4 - op_write(OPMODE_DP, dp, rd.l); //5 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_asl_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - rd.h = op_read(OPMODE_DP, dp + 1); //3a - regs.p.c = !!(rd.w & 0x8000); - rd.w <<= 1; - cpu_io(); //4 - op_write(OPMODE_DP, dp + 1, rd.h); //5a - op_write(OPMODE_DP, dp, rd.l); //5 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/********************** - *** 0x16: asl dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high [1] - [5 ] 0,d+dp+x+1 ; io - [6a] 0,d+dp+x+1 ; data high [1] - [6 ] 0,d+dp+x ; data low -*/ -void bCPU::op_asl_dpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - regs.p.c = !!(rd.l & 0x80); - rd.l <<= 1; - cpu_io(); //5 - op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_asl_dpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a - regs.p.c = !!(rd.w & 0x8000); - rd.w <<= 1; - cpu_io(); //5 - op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a - op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/***************** - *** 0x4a: lsr *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_lsrb() { - cpu_io(); //2 - regs.p.c = regs.a.l & 1; - regs.a.l >>= 1; - regs.p.n = !!(regs.a.l & 0x80); - regs.p.z = (regs.a.l == 0); -} - -void bCPU::op_lsrw() { - cpu_io(); //2 - regs.p.c = regs.a.w & 1; - regs.a.w >>= 1; - regs.p.n = !!(regs.a.w & 0x8000); - regs.p.z = (regs.a.w == 0); -} - -/********************** - *** 0x4e: lsr addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] - [5 ] dbr,aa+1 ; io - [6a] dbr,aa+1 ; data high [1] - [6 ] dbr,aa ; data low -*/ -void bCPU::op_lsr_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - regs.p.c = rd.l & 1; - rd.l >>= 1; - cpu_io(); //5 - op_write(OPMODE_DBR, aa.w, rd.l); //6 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_lsr_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a - regs.p.c = rd.w & 1; - rd.w >>= 1; - cpu_io(); //5 - op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a - op_write(OPMODE_DBR, aa.w, rd.l); //6 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/************************ - *** 0x5e: lsr addr,x *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aah,aal+xl ; io - [5 ] dbr,aa+x ; data low - [5a] dbr,aa+x+1 ; data high [1] - [6 ] dbr,aa+x+1 ; io - [7a] dbr,aa+x+1 ; data high [1] - [7 ] dbr,aa+x ; data low -*/ -void bCPU::op_lsr_addrxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_io(); //4 - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5 - regs.p.c = rd.l & 1; - rd.l >>= 1; - cpu_io(); //6 - op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_lsr_addrxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_io(); //4 - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5 - rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a - regs.p.c = rd.w & 1; - rd.w >>= 1; - cpu_io(); //6 - op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a - op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/******************** - *** 0x46: lsr dp *** - ******************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] - [4 ] 0,d+dp+1 ; io - [5a] 0,d+dp+1 ; data high [1] - [5 ] 0,d+dp ; data low -*/ -void bCPU::op_lsr_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - regs.p.c = rd.l & 1; - rd.l >>= 1; - cpu_io(); //4 - op_write(OPMODE_DP, dp, rd.l); //5 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_lsr_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - rd.h = op_read(OPMODE_DP, dp + 1); //3a - regs.p.c = rd.w & 1; - rd.w >>= 1; - cpu_io(); //4 - op_write(OPMODE_DP, dp + 1, rd.h); //5a - op_write(OPMODE_DP, dp, rd.l); //5 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/********************** - *** 0x56: lsr dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high [1] - [5 ] 0,d+dp+x+1 ; io - [6a] 0,d+dp+x+1 ; data high [1] - [6 ] 0,d+dp+x ; data low -*/ -void bCPU::op_lsr_dpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - regs.p.c = rd.l & 1; - rd.l >>= 1; - cpu_io(); //5 - op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_lsr_dpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a - regs.p.c = rd.w & 1; - rd.w >>= 1; - cpu_io(); //5 - op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a - op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/***************** - *** 0x2a: rol *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_rolb() { -uint8 c = regs.p.c; - cpu_io(); //2 - regs.p.c = !!(regs.a.l & 0x80); - regs.a.l <<= 1; - regs.a.l |= c; - regs.p.n = !!(regs.a.l & 0x80); - regs.p.z = (regs.a.l == 0); -} - -void bCPU::op_rolw() { -uint16 c = regs.p.c; - cpu_io(); //2 - regs.p.c = !!(regs.a.w & 0x8000); - regs.a.w <<= 1; - regs.a.w |= c; - regs.p.n = !!(regs.a.w & 0x8000); - regs.p.z = (regs.a.w == 0); -} - -/********************** - *** 0x2e: rol addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] - [5 ] dbr,aa+1 ; io - [6a] dbr,aa+1 ; data high [1] - [6 ] dbr,aa ; data low -*/ -void bCPU::op_rol_addrb() { -uint8 c = regs.p.c; - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - regs.p.c = !!(rd.l & 0x80); - rd.l <<= 1; - rd.l |= c; - cpu_io(); //5 - op_write(OPMODE_DBR, aa.w, rd.l); //6 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_rol_addrw() { -uint16 c = regs.p.c; - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a - regs.p.c = !!(rd.w & 0x8000); - rd.w <<= 1; - rd.w |= c; - cpu_io(); //5 - op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a - op_write(OPMODE_DBR, aa.w, rd.l); //6 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/************************ - *** 0x3e: rol addr,x *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aah,aal+xl ; io - [5 ] dbr,aa+x ; data low - [5a] dbr,aa+x+1 ; data high [1] - [6 ] dbr,aa+x+1 ; io - [7a] dbr,aa+x+1 ; data high [1] - [7 ] dbr,aa+x ; data low -*/ -void bCPU::op_rol_addrxb() { -uint8 c = regs.p.c; - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_io(); //4 - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5 - regs.p.c = !!(rd.l & 0x80); - rd.l <<= 1; - rd.l |= c; - cpu_io(); //6 - op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_rol_addrxw() { -uint16 c = regs.p.c; - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_io(); //4 - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5 - rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a - regs.p.c = !!(rd.w & 0x8000); - rd.w <<= 1; - rd.w |= c; - cpu_io(); //6 - op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a - op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/******************** - *** 0x26: rol dp *** - ******************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] - [4 ] 0,d+dp+1 ; io - [5a] 0,d+dp+1 ; data high [1] - [5 ] 0,d+dp ; data low -*/ -void bCPU::op_rol_dpb() { -uint8 c = regs.p.c; - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - regs.p.c = !!(rd.l & 0x80); - rd.l <<= 1; - rd.l |= c; - cpu_io(); //4 - op_write(OPMODE_DP, dp, rd.l); //5 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_rol_dpw() { -uint16 c = regs.p.c; - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - rd.h = op_read(OPMODE_DP, dp + 1); //3a - regs.p.c = !!(rd.w & 0x8000); - rd.w <<= 1; - rd.w |= c; - cpu_io(); //4 - op_write(OPMODE_DP, dp + 1, rd.h); //5a - op_write(OPMODE_DP, dp, rd.l); //5 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/********************** - *** 0x36: rol dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high [1] - [5 ] 0,d+dp+x+1 ; io - [6a] 0,d+dp+x+1 ; data high [1] - [6 ] 0,d+dp+x ; data low -*/ -void bCPU::op_rol_dpxb() { -uint8 c = regs.p.c; - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - regs.p.c = !!(rd.l & 0x80); - rd.l <<= 1; - rd.l |= c; - cpu_io(); //5 - op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_rol_dpxw() { -uint16 c = regs.p.c; - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a - regs.p.c = !!(rd.w & 0x8000); - rd.w <<= 1; - rd.w |= c; - cpu_io(); //5 - op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a - op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/***************** - *** 0x6a: ror *** - ***************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; io -*/ -void bCPU::op_rorb() { -uint8 c = (regs.p.c)?0x80:0; - cpu_io(); //2 - regs.p.c = regs.a.l & 1; - regs.a.l >>= 1; - regs.a.l |= c; - regs.p.n = !!(regs.a.l & 0x80); - regs.p.z = (regs.a.l == 0); -} - -void bCPU::op_rorw() { -uint16 c = (regs.p.c)?0x8000:0; - cpu_io(); //2 - regs.p.c = regs.a.w & 1; - regs.a.w >>= 1; - regs.a.w |= c; - regs.p.n = !!(regs.a.w & 0x8000); - regs.p.z = (regs.a.w == 0); -} - -/********************** - *** 0x6e: ror addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] - [5 ] dbr,aa+1 ; io - [6a] dbr,aa+1 ; data high [1] - [6 ] dbr,aa ; data low -*/ -void bCPU::op_ror_addrb() { -uint8 c = (regs.p.c)?0x80:0; - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - regs.p.c = rd.l & 1; - rd.l >>= 1; - rd.l |= c; - cpu_io(); //5 - op_write(OPMODE_DBR, aa.w, rd.l); //6 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_ror_addrw() { -uint16 c = (regs.p.c)?0x8000:0; - aa.l = op_read(); //2 - aa.h = op_read(); //3 - rd.l = op_read(OPMODE_DBR, aa.w); //4 - rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a - regs.p.c = rd.w & 1; - rd.w >>= 1; - rd.w |= c; - cpu_io(); //5 - op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a - op_write(OPMODE_DBR, aa.w, rd.l); //6 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/************************ - *** 0x7e: ror addr,x *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aah,aal+xl ; io - [5 ] dbr,aa+x ; data low - [5a] dbr,aa+x+1 ; data high [1] - [6 ] dbr,aa+x+1 ; io - [7a] dbr,aa+x+1 ; data high [1] - [7 ] dbr,aa+x ; data low -*/ -void bCPU::op_ror_addrxb() { -uint8 c = (regs.p.c)?0x80:0; - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_io(); //4 - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5 - regs.p.c = rd.l & 1; - rd.l >>= 1; - rd.l |= c; - cpu_io(); //6 - op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_ror_addrxw() { -uint16 c = (regs.p.c)?0x8000:0; - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_io(); //4 - rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5 - rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a - regs.p.c = rd.w & 1; - rd.w >>= 1; - rd.w |= c; - cpu_io(); //6 - op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a - op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/******************** - *** 0x66: ror dp *** - ******************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] - [4 ] 0,d+dp+1 ; io - [5a] 0,d+dp+1 ; data high [1] - [5 ] 0,d+dp ; data low -*/ -void bCPU::op_ror_dpb() { -uint8 c = (regs.p.c)?0x80:0; - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - regs.p.c = rd.l & 1; - rd.l >>= 1; - rd.l |= c; - cpu_io(); //4 - op_write(OPMODE_DP, dp, rd.l); //5 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_ror_dpw() { -uint16 c = (regs.p.c)?0x8000:0; - dp = op_read(); //2 - cpu_c2(); //2a - rd.l = op_read(OPMODE_DP, dp); //3 - rd.h = op_read(OPMODE_DP, dp + 1); //3a - regs.p.c = rd.w & 1; - rd.w >>= 1; - rd.w |= c; - cpu_io(); //4 - op_write(OPMODE_DP, dp + 1, rd.h); //5a - op_write(OPMODE_DP, dp, rd.l); //5 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} - -/********************** - *** 0x76: ror dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high [1] - [5 ] 0,d+dp+x+1 ; io - [6a] 0,d+dp+x+1 ; data high [1] - [6 ] 0,d+dp+x ; data low -*/ -void bCPU::op_ror_dpxb() { -uint8 c = (regs.p.c)?0x80:0; - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - regs.p.c = rd.l & 1; - rd.l >>= 1; - rd.l |= c; - cpu_io(); //5 - op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6 - regs.p.n = !!(rd.l & 0x80); - regs.p.z = (rd.l == 0); -} - -void bCPU::op_ror_dpxw() { -uint16 c = (regs.p.c)?0x8000:0; - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a - regs.p.c = rd.w & 1; - rd.w >>= 1; - rd.w |= c; - cpu_io(); //5 - op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a - op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6 - regs.p.n = !!(rd.w & 0x8000); - regs.p.z = (rd.w == 0); -} diff --git a/src/cpu/bcpu/bcpu_op_sta.cpp b/src/cpu/bcpu/bcpu_op_sta.cpp deleted file mode 100644 index eb88afaf..00000000 --- a/src/cpu/bcpu/bcpu_op_sta.cpp +++ /dev/null @@ -1,387 +0,0 @@ -/********************** - *** 0x8d: sta addr *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] dbr,aa ; data low - [4a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_sta_addrb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - op_write(OPMODE_DBR, aa.w, regs.a.l); //4 -} - -void bCPU::op_sta_addrw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - op_write(OPMODE_DBR, aa.w, regs.a.l); //4 - op_write(OPMODE_DBR, aa.w + 1, regs.a.h); //4a -} - -/************************ - *** 0x9d: sta addr,x *** - ************************ -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+xl ; io [4] - [4 ] dbr,aa+x ; data low - [4a] dbr,aa+x+1 ; data high [1] -*/ -void bCPU::op_sta_addrxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - op_write(OPMODE_DBR, aa.w + regs.x.w, regs.a.l); //4 -} - -void bCPU::op_sta_addrxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.x.w); //3a - op_write(OPMODE_DBR, aa.w + regs.x.w, regs.a.l); //4 - op_write(OPMODE_DBR, aa.w + regs.x.w + 1, regs.a.h); //4a -} - -/******************** - *** 0x85: sta dp *** - ******************** -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; data low - [3a] 0,d+dp+1 ; data high [1] -*/ -void bCPU::op_sta_dpb() { - dp = op_read(); //2 - cpu_c2(); //2a - op_write(OPMODE_DP, dp, regs.a.l); //3 -} - -void bCPU::op_sta_dpw() { - dp = op_read(); //2 - cpu_c2(); //2a - op_write(OPMODE_DP, dp, regs.a.l); //3 - op_write(OPMODE_DP, dp + 1, regs.a.h); //3a -} - -/********************** - *** 0x92: sta (dp) *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] dbr,aa ; data low - [5a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_sta_idpb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - op_write(OPMODE_DBR, aa.w, regs.a.l); //5 -} - -void bCPU::op_sta_idpw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - op_write(OPMODE_DBR, aa.w, regs.a.l); //5 - op_write(OPMODE_DBR, aa.w + 1, regs.a.h); //5 -} - -/********************** - *** 0x87: sta [dp] *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] 0,d+dp+2 ; aab - [6 ] aab,aa ; data low - [6a] aab,aa+1 ; data high [1] -*/ -void bCPU::op_sta_ildpb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - op_write(OPMODE_LONG, aa.d, regs.a.l); //6 -} - -void bCPU::op_sta_ildpw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - op_write(OPMODE_LONG, aa.d, regs.a.l); //6 - op_write(OPMODE_LONG, aa.d + 1, regs.a.h); //6a -} - -/********************** - *** 0x8f: sta long *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] pbr,pc+3 ; aab - [5 ] aab,aa ; data low - [5a] aab,aa+1 ; data high -*/ -void bCPU::op_sta_longb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - op_write(OPMODE_LONG, aa.d, regs.a.l); //5 -} - -void bCPU::op_sta_longw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - op_write(OPMODE_LONG, aa.d, regs.a.l); //5 - op_write(OPMODE_LONG, aa.d + 1, regs.a.h); //5a -} - -/************************ - *** 0x9f: sta long,x *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [4 ] pbr,pc+3 ; aab - [5 ] aab,aa+x ; data low - [5a] aab,aa+x+1 ; data high -*/ -void bCPU::op_sta_longxb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - op_write(OPMODE_LONG, aa.d + regs.x.w, regs.a.l); //5 -} - -void bCPU::op_sta_longxw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - aa.b = op_read(); //4 - op_write(OPMODE_LONG, aa.d + regs.x.w, regs.a.l); //5 - op_write(OPMODE_LONG, aa.d + regs.x.w + 1, regs.a.h); //5a -} - -/************************ - *** 0x99: sta addr,y *** - ************************ -cycles: - [1 ] pbr,pc ; operand - [2 ] pbr,pc+1 ; aal - [3 ] pbr,pc+2 ; aah - [3a] dbr,aah,aal+yl ; io [4] - [4 ] dbr,aa+y ; data low - [4a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_sta_addryb() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //4 -} - -void bCPU::op_sta_addryw() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_c4(aa.w, aa.w + regs.y.w); //3a - op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //4 - op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); //4a -} - -/********************** - *** 0x95: sta dp,x *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; data low - [4a] 0,d+dp+x+1 ; data high -*/ -void bCPU::op_sta_dpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - op_write(OPMODE_DP, dp + regs.x.w, regs.a.l); //4 -} - -void bCPU::op_sta_dpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - op_write(OPMODE_DP, dp + regs.x.w, regs.a.l); //4 - op_write(OPMODE_DP, dp + regs.x.w + 1, regs.a.h); //4a -} - -/************************ - *** 0x81: sta (dp,x) *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] pbr,pc+1 ; io - [4 ] 0,d+dp+x ; aal - [5 ] 0,d+dp+x+1 ; aah - [6 ] dbr,aa ; data low - [6a] dbr,aa+1 ; data high [1] -*/ -void bCPU::op_sta_idpxb() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5 - op_write(OPMODE_DBR, aa.w, regs.a.l); //6 -} - -void bCPU::op_sta_idpxw() { - dp = op_read(); //2 - cpu_c2(); //2a - cpu_io(); //3 - aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4 - aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5 - op_write(OPMODE_DBR, aa.w, regs.a.l); //6 - op_write(OPMODE_DBR, aa.w + 1, regs.a.h); //6a -} - -/************************ - *** 0x91: sta (dp),y *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [4a] dbr,aah,aal+yl ; io [4] - [5 ] dbr,aa+y ; data low - [5a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_sta_idpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - cpu_c4(aa.w, aa.w + regs.y.w); //4a - op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //5 -} - -void bCPU::op_sta_idpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - cpu_c4(aa.w, aa.w + regs.y.w); //4a - op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //5 - op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); //5a -} - -/************************ - *** 0x97: sta [dp],y *** - ************************ -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io [2] - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] 0,d+dp+2 ; aab - [6 ] aab,aa+y ; data low - [6a] aab,aa+y+1 ; data high [1] -*/ -void bCPU::op_sta_ildpyb() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - op_write(OPMODE_LONG, aa.d + regs.y.w, regs.a.l); //6 -} - -void bCPU::op_sta_ildpyw() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - aa.b = op_read(OPMODE_DP, dp + 2); //5 - op_write(OPMODE_LONG, aa.d + regs.y.w, regs.a.l); //6 - op_write(OPMODE_LONG, aa.d + regs.y.w + 1, regs.a.h); //6a -} - -/********************** - *** 0x83: sta sr,s *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; sp - [3 ] pbr,pc+1 ; io - [4 ] 0,s+sp ; data low - [4a] 0,s+sp+1 ; data high [1] -*/ -void bCPU::op_sta_srb() { - sp = op_read(); //2 - cpu_io(); //3 - op_write(OPMODE_SP, sp, regs.a.l); //4 -} - -void bCPU::op_sta_srw() { - sp = op_read(); //2 - cpu_io(); //3 - op_write(OPMODE_SP, sp, regs.a.l); //4 - op_write(OPMODE_SP, sp + 1, regs.a.h); //4a -} - -/************************** - *** 0x93: sta (sr,s),y *** - ************************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; sp - [3 ] pbr,pc+1 ; io - [4 ] 0,s+sp ; aal - [5 ] 0,s+sp+1 ; aah - [6 ] 0,s+sp+1 ; io - [7 ] dbr,aa+y ; data low - [7a] dbr,aa+y+1 ; data high [1] -*/ -void bCPU::op_sta_isryb() { - sp = op_read(); //2 - cpu_io(); //3 - aa.l = op_read(OPMODE_SP, sp); //4 - aa.h = op_read(OPMODE_SP, sp + 1); //5 - cpu_io(); //6 - op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //7 -} - -void bCPU::op_sta_isryw() { - sp = op_read(); //2 - cpu_io(); //3 - aa.l = op_read(OPMODE_SP, sp); //4 - aa.h = op_read(OPMODE_SP, sp + 1); //5 - cpu_io(); //6 - op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //7 - op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); //7a -} diff --git a/src/cpu/bcpu/bcpu_op_stack.cpp b/src/cpu/bcpu/bcpu_op_stack.cpp deleted file mode 100644 index bb741e84..00000000 --- a/src/cpu/bcpu/bcpu_op_stack.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/***************** - *** 0x48: pha *** - ***************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; io - [3a] 0,s ; reg high [1] - [3 ] 0,s-1 ; reg low -*/ -void bCPU::op_phab() { - cpu_io(); //2 - stack_write(regs.a.l); //3 -} - -void bCPU::op_phaw() { - cpu_io(); //2 - stack_write(regs.a.h); //3a - stack_write(regs.a.l); //3 -} - -/***************** - *** 0x8b: phb *** - ***************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; io - [3 ] 0,s-1 ; dbr -*/ -void bCPU::op_phb() { - cpu_io(); //2 - stack_write(regs.db); //3 -} - -/***************** - *** 0x0b: phd *** - ***************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; io - [3a] 0,s ; reg high - [3 ] 0,s-1 ; reg low -*/ -void bCPU::op_phd() { - cpu_io(); //2 - stack_write(regs.d.h); //3a - stack_write(regs.d.l); //3 -} - -/***************** - *** 0x4b: phk *** - ***************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; io - [3 ] 0,s-1 ; pcb -*/ -void bCPU::op_phk() { - cpu_io(); //2 - stack_write(regs.pc.b); //3 -} - -/***************** - *** 0x08: php *** - ***************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; io - [3 ] 0,s-1 ; reg low -*/ -void bCPU::op_php() { - cpu_io(); //2 - stack_write(regs.p); //3 -} - -/***************** - *** 0xda: phx *** - ***************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; io - [3a] 0,s ; reg high [1] - [3 ] 0,s-1 ; reg low -*/ -void bCPU::op_phxb() { - cpu_io(); //2 - stack_write(regs.x.l); //3 -} - -void bCPU::op_phxw() { - cpu_io(); //2 - stack_write(regs.x.h); //3a - stack_write(regs.x.l); //3 -} - -/***************** - *** 0x5a: phy *** - ***************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; io - [3a] 0,s ; reg high [1] - [3 ] 0,s-1 ; reg low -*/ -void bCPU::op_phyb() { - cpu_io(); //2 - stack_write(regs.y.l); //3 -} - -void bCPU::op_phyw() { - cpu_io(); //2 - stack_write(regs.y.h); //3a - stack_write(regs.y.l); //3 -} - -/***************** - *** 0x68: pla *** - ***************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,s+1 ; reg low - [4a] 0,s+2 ; reg high [1] -*/ -void bCPU::op_plab() { - cpu_io(); //2 - cpu_io(); //3 - regs.a.l = stack_read(); //4 - regs.p.n = !!(regs.a.l & 0x80); - regs.p.z = (regs.a.l == 0); -} - -void bCPU::op_plaw() { - cpu_io(); //2 - cpu_io(); //3 - regs.a.l = stack_read(); //4 - regs.a.h = stack_read(); //4a - regs.p.n = !!(regs.a.w & 0x8000); - regs.p.z = (regs.a.w == 0); -} - -/***************** - *** 0xab: plb *** - ***************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,s+1 ; reg low -*/ -void bCPU::op_plb() { - cpu_io(); //2 - cpu_io(); //3 - regs.db = stack_read(); //4 - regs.p.n = !!(regs.db & 0x80); - regs.p.z = (regs.db == 0); -} - -/***************** - *** 0x2b: pld *** - ***************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,s+1 ; reg low - [4a] 0,s+2 ; reg high -*/ -void bCPU::op_pld() { - cpu_io(); //2 - cpu_io(); //3 - regs.d.l = stack_read(); //4 - regs.d.h = stack_read(); //4a - regs.p.n = !!(regs.d.w & 0x8000); - regs.p.z = (regs.d.w == 0); -} - -/***************** - *** 0x28: plp *** - ***************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,s+1 ; reg low -*/ -void bCPU::op_plp() { - cpu_io(); //2 - cpu_io(); //3 - regs.p = stack_read(); //4 - if(regs.e) { - regs.p |= 0x30; - } else { - switch((regs.p >> 4) & 3) { - case 0:optbl = optbl_mx;break; - case 1:optbl = optbl_mX;break; - case 2:optbl = optbl_Mx;break; - case 3:optbl = optbl_MX;break; - } - } - if(regs.p.x) { - regs.x.h = 0x00; - regs.y.h = 0x00; - } -} - -/***************** - *** 0xfa: plx *** - ***************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,s+1 ; reg low - [4a] 0,s+2 ; reg high [1] -*/ -void bCPU::op_plxb() { - cpu_io(); //2 - cpu_io(); //3 - regs.x.l = stack_read(); //4 - regs.p.n = !!(regs.x.l & 0x80); - regs.p.z = (regs.x.l == 0); -} - -void bCPU::op_plxw() { - cpu_io(); //2 - cpu_io(); //3 - regs.x.l = stack_read(); //4 - regs.x.h = stack_read(); //4a - regs.p.n = !!(regs.x.w & 0x8000); - regs.p.z = (regs.x.w == 0); -} - -/***************** - *** 0x7a: ply *** - ***************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; io - [3 ] pbr,pc+1 ; io - [4 ] 0,s+1 ; reg low - [4a] 0,s+2 ; reg high [1] -*/ -void bCPU::op_plyb() { - cpu_io(); //2 - cpu_io(); //3 - regs.y.l = stack_read(); //4 - regs.p.n = !!(regs.y.l & 0x80); - regs.p.z = (regs.y.l == 0); -} - -void bCPU::op_plyw() { - cpu_io(); //2 - cpu_io(); //3 - regs.y.l = stack_read(); //4 - regs.y.h = stack_read(); //4a - regs.p.n = !!(regs.y.w & 0x8000); - regs.p.z = (regs.y.w == 0); -} - -/********************** - *** 0xf4: pea addr *** - ********************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; aal - [3] pbr,pc+2 ; aah - [4] 0,s ; aah - [5] 0,s-1 ; aal -*/ -void bCPU::op_pea() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - stack_write(aa.h); //4 - stack_write(aa.l); //5 -} - -/********************** - *** 0xd4: pei (dp) *** - ********************** -cycles: - [1 ] pbr,pc ; opcode - [2 ] pbr,pc+1 ; dp - [2a] pbr,pc+1 ; io - [3 ] 0,d+dp ; aal - [4 ] 0,d+dp+1 ; aah - [5 ] 0,s ; aah - [6 ] 0,s-1 ; aal -*/ -void bCPU::op_pei() { - dp = op_read(); //2 - cpu_c2(); //2a - aa.l = op_read(OPMODE_DP, dp); //3 - aa.h = op_read(OPMODE_DP, dp + 1); //4 - stack_write(aa.h); //5 - stack_write(aa.l); //6 -} - -/********************** - *** 0x62: per addr *** - ********************** -cycles: - [1] pbr,pc ; opcode - [2] pbr,pc+1 ; offset low - [3] pbr,pc+2 ; offset high - [4] pbr,pc+2 ; io - [5] 0,s ; pch+offset - [6] 0,s-1 ; pcl+offset -*/ -void bCPU::op_per() { - aa.l = op_read(); //2 - aa.h = op_read(); //3 - cpu_io(); //4 - rd.w = regs.pc.d + (int16)aa.w; - stack_write(rd.h); //5 - stack_write(rd.l); //6 -} diff --git a/src/cpu/bcpu/bcpu_op_write.cpp b/src/cpu/bcpu/bcpu_op_write.cpp new file mode 100644 index 00000000..8a294337 --- /dev/null +++ b/src/cpu/bcpu/bcpu_op_write.cpp @@ -0,0 +1,340 @@ +void bCPU::op_sta_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + op_write(OPMODE_DBR, aa.w, regs.a.w); + if(regs.p.m)return; +l4: + op_write(OPMODE_DBR, aa.w + 1, regs.a.w >> 8); +} + +void bCPU::op_stx_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + op_write(OPMODE_DBR, aa.w, regs.x.w); + if(regs.p.x)return; +l4: + op_write(OPMODE_DBR, aa.w + 1, regs.x.w >> 8); +} + +void bCPU::op_sty_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + op_write(OPMODE_DBR, aa.w, regs.y.w); + if(regs.p.x)return; +l4: + op_write(OPMODE_DBR, aa.w + 1, regs.y.w >> 8); +} + +void bCPU::op_stz_addr() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + op_write(OPMODE_DBR, aa.w, 0x0000); + if(regs.p.m)return; +l4: + op_write(OPMODE_DBR, aa.w + 1, 0x0000 >> 8); +} + +void bCPU::op_sta_addrx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.x.w); +l4: + op_write(OPMODE_DBR, aa.w + regs.x.w, regs.a.w); + if(regs.p.m)return; +l5: + op_write(OPMODE_DBR, aa.w + regs.x.w + 1, regs.a.w >> 8); +} + +void bCPU::op_stz_addrx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.x.w); +l4: + op_write(OPMODE_DBR, aa.w + regs.x.w, 0x0000); + if(regs.p.m)return; +l5: + op_write(OPMODE_DBR, aa.w + regs.x.w + 1, 0x0000 >> 8); +} + +void bCPU::op_sta_addry() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + cpu_c4(aa.w, aa.w + regs.y.w); +l4: + op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); + if(regs.p.m)return; +l5: + op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); +} + +void bCPU::op_sta_long() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + aa.b = op_read(); +l4: + op_write(OPMODE_LONG, aa.d, regs.a.l); + if(regs.p.m)return; +l5: + op_write(OPMODE_LONG, aa.d + 1, regs.a.h); +} + +void bCPU::op_sta_longx() { +l1: + aa.l = op_read(); +l2: + aa.h = op_read(); +l3: + aa.b = op_read(); +l4: + op_write(OPMODE_LONG, aa.d + regs.x.w, regs.a.l); + if(regs.p.m)return; +l5: + op_write(OPMODE_LONG, aa.d + regs.x.w + 1, regs.a.h); +} + +void bCPU::op_sta_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + op_write(OPMODE_DP, dp, regs.a.w); + if(regs.p.m)return; +l4: + op_write(OPMODE_DP, dp + 1, regs.a.w >> 8); +} + +void bCPU::op_stx_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + op_write(OPMODE_DP, dp, regs.x.w); + if(regs.p.x)return; +l4: + op_write(OPMODE_DP, dp + 1, regs.x.w >> 8); +} + +void bCPU::op_sty_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + op_write(OPMODE_DP, dp, regs.y.w); + if(regs.p.x)return; +l4: + op_write(OPMODE_DP, dp + 1, regs.y.w >> 8); +} + +void bCPU::op_stz_dp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + op_write(OPMODE_DP, dp, 0x0000); + if(regs.p.m)return; +l4: + op_write(OPMODE_DP, dp + 1, 0x0000 >> 8); +} + +void bCPU::op_sta_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + op_write(OPMODE_DP, dp + regs.x.w, regs.a.w); + if(regs.p.m)return; +l5: + op_write(OPMODE_DP, dp + regs.x.w + 1, regs.a.w >> 8); +} + +void bCPU::op_sty_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + op_write(OPMODE_DP, dp + regs.x.w, regs.y.w); + if(regs.p.x)return; +l5: + op_write(OPMODE_DP, dp + regs.x.w + 1, regs.y.w >> 8); +} + +void bCPU::op_stz_dpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + op_write(OPMODE_DP, dp + regs.x.w, 0x0000); + if(regs.p.m)return; +l5: + op_write(OPMODE_DP, dp + regs.x.w + 1, 0x0000 >> 8); +} + +void bCPU::op_stx_dpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + op_write(OPMODE_DP, dp + regs.y.w, regs.x.l); + if(regs.p.x)return; +l5: + op_write(OPMODE_DP, dp + regs.y.w + 1, regs.x.h); +} + +void bCPU::op_sta_idp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + op_write(OPMODE_DBR, aa.w, regs.a.l); + if(regs.p.m)return; +l6: + op_write(OPMODE_DBR, aa.w + 1, regs.a.h); +} + +void bCPU::op_sta_ildp() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + aa.b = op_read(OPMODE_DP, dp + 2); +l6: + op_write(OPMODE_LONG, aa.d, regs.a.l); + if(regs.p.m)return; +l7: + op_write(OPMODE_LONG, aa.d + 1, regs.a.h); +} + +void bCPU::op_sta_idpx() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + cpu_io(); +l4: + aa.l = op_read(OPMODE_DP, dp + regs.x.w); +l5: + aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); +l6: + op_write(OPMODE_DBR, aa.w, regs.a.l); + if(regs.p.m)return; +l7: + op_write(OPMODE_DBR, aa.w + 1, regs.a.h); +} + +void bCPU::op_sta_idpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + cpu_c4(aa.w, aa.w + regs.y.w); +l6: + op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); + if(regs.p.m)return; +l7: + op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); +} + +void bCPU::op_sta_ildpy() { +l1: + dp = op_read(); +l2: + cpu_c2(); +l3: + aa.l = op_read(OPMODE_DP, dp); +l4: + aa.h = op_read(OPMODE_DP, dp + 1); +l5: + aa.b = op_read(OPMODE_DP, dp + 2); +l6: + op_write(OPMODE_LONG, aa.d + regs.y.w, regs.a.l); + if(regs.p.m)return; +l7: + op_write(OPMODE_LONG, aa.d + regs.y.w + 1, regs.a.h); +} + +void bCPU::op_sta_sr() { +l1: + sp = op_read(); +l2: + cpu_io(); +l3: + op_write(OPMODE_SP, sp, regs.a.l); + if(regs.p.m)return; +l4: + op_write(OPMODE_SP, sp + 1, regs.a.h); +} + +void bCPU::op_sta_isry() { +l1: + sp = op_read(); +l2: + cpu_io(); +l3: + aa.l = op_read(OPMODE_SP, sp); +l4: + aa.h = op_read(OPMODE_SP, sp + 1); +l5: + cpu_io(); +l6: + op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); + if(regs.p.m)return; +l7: + op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); +} + diff --git a/src/cpu/bcpu/bcpu_opfn.cpp b/src/cpu/bcpu/bcpu_opfn.cpp new file mode 100644 index 00000000..b6f13563 --- /dev/null +++ b/src/cpu/bcpu/bcpu_opfn.cpp @@ -0,0 +1,295 @@ +//op_read +inline void bCPU::op_adc_b() { +int32 r = regs.a.l + rd.l + regs.p.c; +//bcd + if(regs.p.d) { + if(((r ) & 15) > 9)r += 6; + if(((r >> 4) & 15) > 9)r += 6 << 4; + } + regs.p.n = !!(r & 0x80); + regs.p.v = !!(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80); + regs.p.z = ((uint8)r == 0); + regs.p.c = (r > 0xff); + regs.a.l = r; +} + +inline void bCPU::op_adc_w() { +int32 r = regs.a.w + rd.w + regs.p.c; +//bcd + if(regs.p.d) { + if(((r ) & 15) > 9)r += 6; + if(((r >> 4) & 15) > 9)r += 6 << 4; + if(((r >> 8) & 15) > 9)r += 6 << 8; + if(((r >> 12) & 15) > 9)r += 6 << 12; + } + regs.p.n = !!(r & 0x8000); + regs.p.v = !!(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000); + regs.p.z = ((uint16)r == 0); + regs.p.c = (r > 0xffff); + regs.a.w = r; +} + +inline void bCPU::op_and_b() { + regs.a.l &= rd.l; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); +} + +inline void bCPU::op_and_w() { + regs.a.w &= rd.w; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); +} + +inline void bCPU::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 bCPU::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 bCPU::op_cmp_b() { +int32 r = regs.a.l - rd.l; + regs.p.n = !!(r & 0x80); + regs.p.z = ((uint8)r == 0); + regs.p.c = (r >= 0); +} + +inline void bCPU::op_cmp_w() { +int32 r = regs.a.w - rd.w; + regs.p.n = !!(r & 0x8000); + regs.p.z = ((uint16)r == 0); + regs.p.c = (r >= 0); +} + +inline void bCPU::op_cpx_b() { +int32 r = regs.x.l - rd.l; + regs.p.n = !!(r & 0x80); + regs.p.z = ((uint8)r == 0); + regs.p.c = (r >= 0); +} + +inline void bCPU::op_cpx_w() { +int32 r = regs.x.w - rd.w; + regs.p.n = !!(r & 0x8000); + regs.p.z = ((uint16)r == 0); + regs.p.c = (r >= 0); +} + +inline void bCPU::op_cpy_b() { +int32 r = regs.y.l - rd.l; + regs.p.n = !!(r & 0x80); + regs.p.z = ((uint8)r == 0); + regs.p.c = (r >= 0); +} + +inline void bCPU::op_cpy_w() { +int32 r = regs.y.w - rd.w; + regs.p.n = !!(r & 0x8000); + regs.p.z = ((uint16)r == 0); + regs.p.c = (r >= 0); +} + +inline void bCPU::op_eor_b() { + regs.a.l ^= rd.l; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); +} + +inline void bCPU::op_eor_w() { + regs.a.w ^= rd.w; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); +} + +inline void bCPU::op_lda_b() { + regs.a.l = rd.l; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); +} + +inline void bCPU::op_lda_w() { + regs.a.w = rd.w; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); +} + +inline void bCPU::op_ldx_b() { + regs.x.l = rd.l; + regs.p.n = !!(regs.x.l & 0x80); + regs.p.z = (regs.x.l == 0); +} + +inline void bCPU::op_ldx_w() { + regs.x.w = rd.w; + regs.p.n = !!(regs.x.w & 0x8000); + regs.p.z = (regs.x.w == 0); +} + +inline void bCPU::op_ldy_b() { + regs.y.l = rd.l; + regs.p.n = !!(regs.y.l & 0x80); + regs.p.z = (regs.y.l == 0); +} + +inline void bCPU::op_ldy_w() { + regs.y.w = rd.w; + regs.p.n = !!(regs.y.w & 0x8000); + regs.p.z = (regs.y.w == 0); +} + +inline void bCPU::op_ora_b() { + regs.a.l |= rd.l; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); +} + +inline void bCPU::op_ora_w() { + regs.a.w |= rd.w; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); +} + +inline void bCPU::op_sbc_b() { +int32 r = regs.a.l - rd.l - !regs.p.c; +//bcd + if(regs.p.d) { + if(((r ) & 15) > 9)r -= 6; + if(((r >> 4) & 15) > 9)r -= 6 << 4; + } + regs.p.n = !!(r & 0x80); + regs.p.v = !!((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80); + regs.p.z = ((byte)r == 0); + regs.p.c = (r >= 0); + regs.a.l = r; +} + +inline void bCPU::op_sbc_w() { +int32 r = regs.a.w - rd.w - !regs.p.c; +//bcd + if(regs.p.d) { + if(((r ) & 15) > 9)r -= 6; + if(((r >> 4) & 15) > 9)r -= 6 << 4; + if(((r >> 8) & 15) > 9)r -= 6 << 8; + if(((r >> 12) & 15) > 9)r -= 6 << 12; + } + regs.p.n = !!(r & 0x8000); + regs.p.v = !!((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000); + regs.p.z = ((word)r == 0); + regs.p.c = (r >= 0); + regs.a.w = r; +} + +//op_rmw +inline void bCPU::op_inc_b() { + rd.l++; + regs.p.n = !!(rd.l & 0x80); + regs.p.z = (rd.l == 0); +} + +inline void bCPU::op_inc_w() { + rd.w++; + regs.p.n = !!(rd.w & 0x8000); + regs.p.z = (rd.w == 0); +} + +inline void bCPU::op_dec_b() { + rd.l--; + regs.p.n = !!(rd.l & 0x80); + regs.p.z = (rd.l == 0); +} + +inline void bCPU::op_dec_w() { + rd.w--; + regs.p.n = !!(rd.w & 0x8000); + regs.p.z = (rd.w == 0); +} + +inline void bCPU::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 bCPU::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 bCPU::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 bCPU::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 bCPU::op_rol_b() { +uint16 c = regs.p.c; + regs.p.c = !!(rd.l & 0x80); + rd.l <<= 1; + rd.l |= c; + regs.p.n = !!(rd.l & 0x80); + regs.p.z = (rd.l == 0); +} + +inline void bCPU::op_rol_w() { +uint16 c = regs.p.c; + regs.p.c = !!(rd.w & 0x8000); + rd.w <<= 1; + rd.w |= c; + regs.p.n = !!(rd.w & 0x8000); + regs.p.z = (rd.w == 0); +} + +inline void bCPU::op_ror_b() { +uint16 c = (regs.p.c)?0x80:0; + regs.p.c = rd.l & 1; + rd.l >>= 1; + rd.l |= c; + regs.p.n = !!(rd.l & 0x80); + regs.p.z = (rd.l == 0); +} + +inline void bCPU::op_ror_w() { +uint16 c = (regs.p.c)?0x8000:0; + regs.p.c = rd.w & 1; + rd.w >>= 1; + rd.w |= c; + regs.p.n = !!(rd.w & 0x8000); + regs.p.z = (rd.w == 0); +} + +inline void bCPU::op_trb_b() { + regs.p.z = ((rd.l & regs.a.l) == 0); + rd.l &= ~regs.a.l; +} + +inline void bCPU::op_trb_w() { + regs.p.z = ((rd.w & regs.a.w) == 0); + rd.w &= ~regs.a.w; +} + +inline void bCPU::op_tsb_b() { + regs.p.z = ((rd.l & regs.a.l) == 0); + rd.l |= regs.a.l; +} + +inline void bCPU::op_tsb_w() { + regs.p.z = ((rd.w & regs.a.w) == 0); + rd.w |= regs.a.w; +} diff --git a/src/cpu/bcpu/bcpu_optable.cpp b/src/cpu/bcpu/bcpu_optable.cpp new file mode 100644 index 00000000..253f75b9 --- /dev/null +++ b/src/cpu/bcpu/bcpu_optable.cpp @@ -0,0 +1,256 @@ +optbl[0x69] = &bCPU::op_adc_const; +optbl[0x29] = &bCPU::op_and_const; +optbl[0xc9] = &bCPU::op_cmp_const; +optbl[0xe0] = &bCPU::op_cpx_const; +optbl[0xc0] = &bCPU::op_cpy_const; +optbl[0x49] = &bCPU::op_eor_const; +optbl[0xa9] = &bCPU::op_lda_const; +optbl[0xa2] = &bCPU::op_ldx_const; +optbl[0xa0] = &bCPU::op_ldy_const; +optbl[0x09] = &bCPU::op_ora_const; +optbl[0xe9] = &bCPU::op_sbc_const; +optbl[0x6d] = &bCPU::op_adc_addr; +optbl[0x2d] = &bCPU::op_and_addr; +optbl[0x2c] = &bCPU::op_bit_addr; +optbl[0xcd] = &bCPU::op_cmp_addr; +optbl[0xec] = &bCPU::op_cpx_addr; +optbl[0xcc] = &bCPU::op_cpy_addr; +optbl[0x4d] = &bCPU::op_eor_addr; +optbl[0xad] = &bCPU::op_lda_addr; +optbl[0xae] = &bCPU::op_ldx_addr; +optbl[0xac] = &bCPU::op_ldy_addr; +optbl[0x0d] = &bCPU::op_ora_addr; +optbl[0xed] = &bCPU::op_sbc_addr; +optbl[0x7d] = &bCPU::op_adc_addrx; +optbl[0x3d] = &bCPU::op_and_addrx; +optbl[0x3c] = &bCPU::op_bit_addrx; +optbl[0xdd] = &bCPU::op_cmp_addrx; +optbl[0x5d] = &bCPU::op_eor_addrx; +optbl[0xbd] = &bCPU::op_lda_addrx; +optbl[0xbc] = &bCPU::op_ldy_addrx; +optbl[0x1d] = &bCPU::op_ora_addrx; +optbl[0xfd] = &bCPU::op_sbc_addrx; +optbl[0x79] = &bCPU::op_adc_addry; +optbl[0x39] = &bCPU::op_and_addry; +optbl[0xd9] = &bCPU::op_cmp_addry; +optbl[0x59] = &bCPU::op_eor_addry; +optbl[0xb9] = &bCPU::op_lda_addry; +optbl[0xbe] = &bCPU::op_ldx_addry; +optbl[0x19] = &bCPU::op_ora_addry; +optbl[0xf9] = &bCPU::op_sbc_addry; +optbl[0x6f] = &bCPU::op_adc_long; +optbl[0x2f] = &bCPU::op_and_long; +optbl[0xcf] = &bCPU::op_cmp_long; +optbl[0x4f] = &bCPU::op_eor_long; +optbl[0xaf] = &bCPU::op_lda_long; +optbl[0x0f] = &bCPU::op_ora_long; +optbl[0xef] = &bCPU::op_sbc_long; +optbl[0x7f] = &bCPU::op_adc_longx; +optbl[0x3f] = &bCPU::op_and_longx; +optbl[0xdf] = &bCPU::op_cmp_longx; +optbl[0x5f] = &bCPU::op_eor_longx; +optbl[0xbf] = &bCPU::op_lda_longx; +optbl[0x1f] = &bCPU::op_ora_longx; +optbl[0xff] = &bCPU::op_sbc_longx; +optbl[0x65] = &bCPU::op_adc_dp; +optbl[0x25] = &bCPU::op_and_dp; +optbl[0x24] = &bCPU::op_bit_dp; +optbl[0xc5] = &bCPU::op_cmp_dp; +optbl[0xe4] = &bCPU::op_cpx_dp; +optbl[0xc4] = &bCPU::op_cpy_dp; +optbl[0x45] = &bCPU::op_eor_dp; +optbl[0xa5] = &bCPU::op_lda_dp; +optbl[0xa6] = &bCPU::op_ldx_dp; +optbl[0xa4] = &bCPU::op_ldy_dp; +optbl[0x05] = &bCPU::op_ora_dp; +optbl[0xe5] = &bCPU::op_sbc_dp; +optbl[0x75] = &bCPU::op_adc_dpx; +optbl[0x35] = &bCPU::op_and_dpx; +optbl[0x34] = &bCPU::op_bit_dpx; +optbl[0xd5] = &bCPU::op_cmp_dpx; +optbl[0x55] = &bCPU::op_eor_dpx; +optbl[0xb5] = &bCPU::op_lda_dpx; +optbl[0xb4] = &bCPU::op_ldy_dpx; +optbl[0x15] = &bCPU::op_ora_dpx; +optbl[0xf5] = &bCPU::op_sbc_dpx; +optbl[0xb6] = &bCPU::op_ldx_dpy; +optbl[0x72] = &bCPU::op_adc_idp; +optbl[0x32] = &bCPU::op_and_idp; +optbl[0xd2] = &bCPU::op_cmp_idp; +optbl[0x52] = &bCPU::op_eor_idp; +optbl[0xb2] = &bCPU::op_lda_idp; +optbl[0x12] = &bCPU::op_ora_idp; +optbl[0xf2] = &bCPU::op_sbc_idp; +optbl[0x61] = &bCPU::op_adc_idpx; +optbl[0x21] = &bCPU::op_and_idpx; +optbl[0xc1] = &bCPU::op_cmp_idpx; +optbl[0x41] = &bCPU::op_eor_idpx; +optbl[0xa1] = &bCPU::op_lda_idpx; +optbl[0x01] = &bCPU::op_ora_idpx; +optbl[0xe1] = &bCPU::op_sbc_idpx; +optbl[0x71] = &bCPU::op_adc_idpy; +optbl[0x31] = &bCPU::op_and_idpy; +optbl[0xd1] = &bCPU::op_cmp_idpy; +optbl[0x51] = &bCPU::op_eor_idpy; +optbl[0xb1] = &bCPU::op_lda_idpy; +optbl[0x11] = &bCPU::op_ora_idpy; +optbl[0xf1] = &bCPU::op_sbc_idpy; +optbl[0x67] = &bCPU::op_adc_ildp; +optbl[0x27] = &bCPU::op_and_ildp; +optbl[0xc7] = &bCPU::op_cmp_ildp; +optbl[0x47] = &bCPU::op_eor_ildp; +optbl[0xa7] = &bCPU::op_lda_ildp; +optbl[0x07] = &bCPU::op_ora_ildp; +optbl[0xe7] = &bCPU::op_sbc_ildp; +optbl[0x77] = &bCPU::op_adc_ildpy; +optbl[0x37] = &bCPU::op_and_ildpy; +optbl[0xd7] = &bCPU::op_cmp_ildpy; +optbl[0x57] = &bCPU::op_eor_ildpy; +optbl[0xb7] = &bCPU::op_lda_ildpy; +optbl[0x17] = &bCPU::op_ora_ildpy; +optbl[0xf7] = &bCPU::op_sbc_ildpy; +optbl[0x63] = &bCPU::op_adc_sr; +optbl[0x23] = &bCPU::op_and_sr; +optbl[0xc3] = &bCPU::op_cmp_sr; +optbl[0x43] = &bCPU::op_eor_sr; +optbl[0xa3] = &bCPU::op_lda_sr; +optbl[0x03] = &bCPU::op_ora_sr; +optbl[0xe3] = &bCPU::op_sbc_sr; +optbl[0x73] = &bCPU::op_adc_isry; +optbl[0x33] = &bCPU::op_and_isry; +optbl[0xd3] = &bCPU::op_cmp_isry; +optbl[0x53] = &bCPU::op_eor_isry; +optbl[0xb3] = &bCPU::op_lda_isry; +optbl[0x13] = &bCPU::op_ora_isry; +optbl[0xf3] = &bCPU::op_sbc_isry; +optbl[0x89] = &bCPU::op_bit_const; +optbl[0x1a] = &bCPU::op_inc; +optbl[0xe8] = &bCPU::op_inx; +optbl[0xc8] = &bCPU::op_iny; +optbl[0x3a] = &bCPU::op_dec; +optbl[0xca] = &bCPU::op_dex; +optbl[0x88] = &bCPU::op_dey; +optbl[0x0a] = &bCPU::op_asl; +optbl[0x4a] = &bCPU::op_lsr; +optbl[0x2a] = &bCPU::op_rol; +optbl[0x6a] = &bCPU::op_ror; +optbl[0xee] = &bCPU::op_inc_addr; +optbl[0xce] = &bCPU::op_dec_addr; +optbl[0x0e] = &bCPU::op_asl_addr; +optbl[0x4e] = &bCPU::op_lsr_addr; +optbl[0x2e] = &bCPU::op_rol_addr; +optbl[0x6e] = &bCPU::op_ror_addr; +optbl[0x1c] = &bCPU::op_trb_addr; +optbl[0x0c] = &bCPU::op_tsb_addr; +optbl[0xfe] = &bCPU::op_inc_addrx; +optbl[0xde] = &bCPU::op_dec_addrx; +optbl[0x1e] = &bCPU::op_asl_addrx; +optbl[0x5e] = &bCPU::op_lsr_addrx; +optbl[0x3e] = &bCPU::op_rol_addrx; +optbl[0x7e] = &bCPU::op_ror_addrx; +optbl[0xe6] = &bCPU::op_inc_dp; +optbl[0xc6] = &bCPU::op_dec_dp; +optbl[0x06] = &bCPU::op_asl_dp; +optbl[0x46] = &bCPU::op_lsr_dp; +optbl[0x26] = &bCPU::op_rol_dp; +optbl[0x66] = &bCPU::op_ror_dp; +optbl[0x14] = &bCPU::op_trb_dp; +optbl[0x04] = &bCPU::op_tsb_dp; +optbl[0xf6] = &bCPU::op_inc_dpx; +optbl[0xd6] = &bCPU::op_dec_dpx; +optbl[0x16] = &bCPU::op_asl_dpx; +optbl[0x56] = &bCPU::op_lsr_dpx; +optbl[0x36] = &bCPU::op_rol_dpx; +optbl[0x76] = &bCPU::op_ror_dpx; +optbl[0x8d] = &bCPU::op_sta_addr; +optbl[0x8e] = &bCPU::op_stx_addr; +optbl[0x8c] = &bCPU::op_sty_addr; +optbl[0x9c] = &bCPU::op_stz_addr; +optbl[0x9d] = &bCPU::op_sta_addrx; +optbl[0x9e] = &bCPU::op_stz_addrx; +optbl[0x99] = &bCPU::op_sta_addry; +optbl[0x8f] = &bCPU::op_sta_long; +optbl[0x9f] = &bCPU::op_sta_longx; +optbl[0x85] = &bCPU::op_sta_dp; +optbl[0x86] = &bCPU::op_stx_dp; +optbl[0x84] = &bCPU::op_sty_dp; +optbl[0x64] = &bCPU::op_stz_dp; +optbl[0x95] = &bCPU::op_sta_dpx; +optbl[0x94] = &bCPU::op_sty_dpx; +optbl[0x74] = &bCPU::op_stz_dpx; +optbl[0x96] = &bCPU::op_stx_dpy; +optbl[0x92] = &bCPU::op_sta_idp; +optbl[0x87] = &bCPU::op_sta_ildp; +optbl[0x81] = &bCPU::op_sta_idpx; +optbl[0x91] = &bCPU::op_sta_idpy; +optbl[0x97] = &bCPU::op_sta_ildpy; +optbl[0x83] = &bCPU::op_sta_sr; +optbl[0x93] = &bCPU::op_sta_isry; +optbl[0x80] = &bCPU::op_bra; +optbl[0x90] = &bCPU::op_bcc; +optbl[0xb0] = &bCPU::op_bcs; +optbl[0xd0] = &bCPU::op_bne; +optbl[0xf0] = &bCPU::op_beq; +optbl[0x10] = &bCPU::op_bpl; +optbl[0x30] = &bCPU::op_bmi; +optbl[0x50] = &bCPU::op_bvc; +optbl[0x70] = &bCPU::op_bvs; +optbl[0x82] = &bCPU::op_brl; +optbl[0x4c] = &bCPU::op_jmp_addr; +optbl[0x5c] = &bCPU::op_jmp_long; +optbl[0x6c] = &bCPU::op_jmp_iaddr; +optbl[0x7c] = &bCPU::op_jmp_iaddrx; +optbl[0xdc] = &bCPU::op_jmp_iladdr; +optbl[0x20] = &bCPU::op_jsr_addr; +optbl[0x22] = &bCPU::op_jsr_long; +optbl[0xfc] = &bCPU::op_jsr_iaddrx; +optbl[0x40] = &bCPU::op_rti; +optbl[0x60] = &bCPU::op_rts; +optbl[0x6b] = &bCPU::op_rtl; +optbl[0xea] = &bCPU::op_nop; +optbl[0x42] = &bCPU::op_wdm; +optbl[0xeb] = &bCPU::op_xba; +optbl[0x54] = &bCPU::op_mvn; +optbl[0x44] = &bCPU::op_mvp; +optbl[0x00] = &bCPU::op_brk; +optbl[0x02] = &bCPU::op_cop; +optbl[0xdb] = &bCPU::op_stp; +optbl[0xcb] = &bCPU::op_wai; +optbl[0xfb] = &bCPU::op_xce; +optbl[0x18] = &bCPU::op_clc; +optbl[0xd8] = &bCPU::op_cld; +optbl[0x58] = &bCPU::op_cli; +optbl[0xb8] = &bCPU::op_clv; +optbl[0x38] = &bCPU::op_sec; +optbl[0xf8] = &bCPU::op_sed; +optbl[0x78] = &bCPU::op_sei; +optbl[0xc2] = &bCPU::op_rep; +optbl[0xe2] = &bCPU::op_sep; +optbl[0xaa] = &bCPU::op_tax; +optbl[0xa8] = &bCPU::op_tay; +optbl[0x8a] = &bCPU::op_txa; +optbl[0x9b] = &bCPU::op_txy; +optbl[0x98] = &bCPU::op_tya; +optbl[0xbb] = &bCPU::op_tyx; +optbl[0x5b] = &bCPU::op_tcd; +optbl[0x1b] = &bCPU::op_tcs; +optbl[0x7b] = &bCPU::op_tdc; +optbl[0x3b] = &bCPU::op_tsc; +optbl[0xba] = &bCPU::op_tsx; +optbl[0x9a] = &bCPU::op_txs; +optbl[0x48] = &bCPU::op_pha; +optbl[0xda] = &bCPU::op_phx; +optbl[0x5a] = &bCPU::op_phy; +optbl[0x0b] = &bCPU::op_phd; +optbl[0x8b] = &bCPU::op_phb; +optbl[0x4b] = &bCPU::op_phk; +optbl[0x08] = &bCPU::op_php; +optbl[0x68] = &bCPU::op_pla; +optbl[0xfa] = &bCPU::op_plx; +optbl[0x7a] = &bCPU::op_ply; +optbl[0x2b] = &bCPU::op_pld; +optbl[0xab] = &bCPU::op_plb; +optbl[0x28] = &bCPU::op_plp; +optbl[0xf4] = &bCPU::op_pea; +optbl[0xd4] = &bCPU::op_pei; +optbl[0x62] = &bCPU::op_per; diff --git a/src/cpu/bcpu/bcpu_timing.cpp b/src/cpu/bcpu/bcpu_timing.cpp new file mode 100644 index 00000000..3e9cd83e --- /dev/null +++ b/src/cpu/bcpu/bcpu_timing.cpp @@ -0,0 +1,141 @@ +uint16 bCPU::vcounter() { return time.v; } +uint16 bCPU::hcounter() { return get_hcounter(); } +uint16 bCPU::hcycles() { return time.hc; } +bool bCPU::interlace() { return time.interlace; } +bool bCPU::interlace_field() { return time.interlace_field; } +bool bCPU::overscan() { return time.overscan; } + +void bCPU::set_interlace(bool r) { time.interlace = r; } +void bCPU::set_overscan(bool r) { time.overscan = r; } + +uint8 bCPU::dma_counter() { return (time.dma_counter + time.hc) & 6; } + +//all scanlines are 1364 cycles long, except scanline 240 +//on non-interlace odd-frames, which is 1360 cycles long. +//interlace mode has 525 scanlines: 263 on the even frame, +//and 262 on the odd. +//non-interlace mode has 524 scanlines: 262 scanlines on +//both even and odd frames. +// +//cycles per frame: +// 263 * 1364 = 358732 +// 262 * 1364 = 357368 +// 262 * 1364 - 4 = 357364 +void bCPU::inc_vcounter() { + time.v++; + if(time.v >= time.frame_lines) { + time.v = 0; + time.interlace_field ^= 1; + + if(time.interlace == true && time.interlace_field == 0) { + time.frame_lines = 263; + } else { + time.frame_lines = 262; + } + } + + time.hc = 0; + time.dma_counter = time.line_cycles & 6; + if(time.v == 240 && time.interlace == false && time.interlace_field == 1) { + time.line_cycles = 1360; + } else { + time.line_cycles = 1364; + } + time.dram_refreshed = false; +} + +//all dots are 4 cycles long, except dots 322 and 326. dots 322 and 326 +//are 6 cycles long. this holds true for all scanlines except scanline +//240 on non-interlace odd frames. the reason for this is because this +//scanline is only 1360 cycles long, instead of 1364 like all other +//scanlines. +//this makes the effective range of hscan_pos 0-339 at all times. +//dot 322 range = { 1288, 1290, 1292 } +//dot 326 range = { 1306, 1308, 1310 } +uint16 bCPU::get_hcounter() { + if(time.v == 240 && time.interlace == false && time.interlace_field == 1) { + return time.hc >> 2; + } + return (time.hc - ((time.hc > 1288) << 1) - ((time.hc > 1306) << 1)) >> 2; +} + +void bCPU::apu_sync() { +int cycles; + while(apusync.cycles >= 0) { + apu->run(); + + cycles = apu->cycles_executed(); + if(cycles) { + apusync.cycles -= apusync.cpu_multbl[cycles]; + } + } +} + +void bCPU::dram_refresh() { + time.dram_refreshed = true; + add_cycles(40); + if(time.v != 240 || time.interlace != false || time.interlace_field != 1) { + //alternate between 534 and 538 every scanline except 240ni1 + time.dram_refresh_pos ^= 12; + } +} + +void bCPU::add_cycles(int cycles) { + cycles >>= 1; + while(cycles--) { + apusync.cycles += apusync.apu_freq << 1; + apu_sync(); + time.hc += 2; + + if(time.hc >= time.line_cycles) { + inc_vcounter(); + if(time.v == 0) { + frame(); + ppu->frame(); + } + scanline(); + ppu->scanline(); + } + + if(time.dram_refreshed == false && time.hc >= time.dram_refresh_pos) { + dram_refresh(); + } + + if(hdma_test() == true) { + hdma_run(); + } + } +} + +void bCPU::time_reset() { +//initial latch values for $213c/$213d +//[x]0035 : [y]0000 (53.0 -> 212) [lda $2137] +//[x]0038 : [y]0000 (56.5 -> 226) [nop : lda $2137] + time.v = 0; + time.hc = 186; + +//upon SNES reset, start at scanline 0 non-interlace + time.interlace = false; + time.interlace_field = false; + time.overscan = false; + time.line_cycles = 1364; + time.frame_lines = 262; + + time.dram_refreshed = false; + time.dram_refresh_pos = 538; + + time.dma_counter = 0; + + apusync.cycles = apusync.cpu_multbl[255]; +} + +void bCPU::time_init() { + apusync.cpu_freq = 21477272 >> 3; + apusync.apu_freq = 24576000 >> 3; + +int i; + for(i=0;i<1024;i++) { + apusync.cpu_multbl[i] = i * apusync.cpu_freq; + apusync.apu_multbl[i] = i * apusync.apu_freq; + } +} diff --git a/src/cpu/bcpu/bcpu_timing.h b/src/cpu/bcpu/bcpu_timing.h new file mode 100644 index 00000000..76a91a15 --- /dev/null +++ b/src/cpu/bcpu/bcpu_timing.h @@ -0,0 +1,38 @@ +struct { + uint16 v, hc; + + bool interlace, interlace_field, overscan; + uint16 line_cycles, frame_lines; + + bool dram_refreshed; + uint16 dram_refresh_pos; + + uint8 dma_counter; +}time; + +inline uint16 vcounter(); +inline uint16 hcounter(); +inline uint16 hcycles(); +inline bool interlace(); +inline bool interlace_field(); +inline bool overscan(); + +inline void set_interlace(bool r); +inline void set_overscan (bool r); + +inline uint8 dma_counter(); + +inline void inc_vcounter(); +inline uint16 get_hcounter(); +inline void apu_sync(); +inline void dram_refresh(); +inline void add_cycles(int cycles); +inline void time_reset(); +inline void time_init(); + +//APU synchronization +struct { +int32 cpu_freq, apu_freq; +int32 cpu_multbl[1024], apu_multbl[1024]; +int32 cycles; +}apusync; diff --git a/src/cpu/bcpu/bcpugen.cpp b/src/cpu/bcpu/bcpugen.cpp new file mode 100644 index 00000000..ca22a068 --- /dev/null +++ b/src/cpu/bcpu/bcpugen.cpp @@ -0,0 +1,168 @@ +#include "../../lib/libbase.h" +#include "../../lib/libstring.h" +#include "../../lib/libstring.cpp" + +FILE *fp, *fph, *fpt; + +string data, line, part, subpart; +string output_table, output_header, output_op; + +int op_count; +struct _op_list { +string name; +string arg; +}op_list[64]; + +int line_num; + +void clear_op_list() { + op_count = 0; + for(int i=0;i<64;i++) { + strcpy(op_list[i].name, ""); + for(int l=0;l<8;l++) { + strcpy(op_list[i].arg[l], ""); + } + } +} + +void gen_header() { +int i = line_num, l, n, z; +char t[4096]; + clear_op_list(); + while(1) { + z = op_count++; + strcpy(part, line[i]); + strrtrim(part, "),"); + strrtrim(part, ") {"); + split(subpart, "(", part); + strcpy(op_list[z].name, subpart[0]); + split(part, ", ", subpart[1]); + for(l=0;l= count(line))break; + + gen_header(); + gen_op(); + gen_final(); + } + + fclose(fp); +} + +int main() { + fph = fopen("bcpu_op.h", "wb"); + fpt = fopen("bcpu_optable.cpp", "wb"); + + generate("bcpu_op_read.cpp", "op_read.b"); + generate("bcpu_op_rmw.cpp", "op_rmw.b"); + generate("bcpu_op_write.cpp", "op_write.b"); + generate("bcpu_op_pc.cpp", "op_pc.b"); + generate("bcpu_op_misc.cpp", "op_misc.b"); + + fclose(fph); + fclose(fpt); + + return 0; +} diff --git a/src/cpu/bcpu/bcpugen.exe b/src/cpu/bcpu/bcpugen.exe new file mode 100644 index 0000000000000000000000000000000000000000..2f635841944cc3c1bd384b9f2d64b343936d3eb0 GIT binary patch literal 53248 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 1; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.p.c = regs.a.w & 1; + regs.a.w >>= 1; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} + +rol(0x2a) { +1:cpu_io(); + uint16 c = regs.p.c; + if(regs.p.m) { + regs.p.c = !!(regs.a.l & 0x80); + regs.a.l <<= 1; + regs.a.l |= c; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.p.c = !!(regs.a.w & 0x8000); + regs.a.w <<= 1; + regs.a.w |= c; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} + +ror(0x6a) { +1:cpu_io(); + uint16 c; + if(regs.p.m) { + c = (regs.p.c)?0x80:0; + regs.p.c = regs.a.l & 1; + regs.a.l >>= 1; + regs.a.l |= c; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + c = (regs.p.c)?0x8000:0; + regs.p.c = regs.a.w & 1; + regs.a.w >>= 1; + regs.a.w |= c; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} + +inc_addr(0xee, inc), +dec_addr(0xce, dec), +asl_addr(0x0e, asl), +lsr_addr(0x4e, lsr), +rol_addr(0x2e, rol), +ror_addr(0x6e, ror), +trb_addr(0x1c, trb), +tsb_addr(0x0c, tsb) { +1:aa.l = op_read(); +2:aa.h = op_read(); +3:rd.l = op_read(OPMODE_DBR, aa.w); + if(regs.p.m)skip; +4:rd.h = op_read(OPMODE_DBR, aa.w + 1); +5:cpu_io(); + if(regs.p.m) { op_$1_b(); skip; } + else op_$1_w(); +6:op_write(OPMODE_DBR, aa.w + 1, rd.h); +7:op_write(OPMODE_DBR, aa.w, rd.l); +} + +inc_addrx(0xfe, inc), +dec_addrx(0xde, dec), +asl_addrx(0x1e, asl), +lsr_addrx(0x5e, lsr), +rol_addrx(0x3e, rol), +ror_addrx(0x7e, ror) { +1:aa.l = op_read(); +2:aa.h = op_read(); +3:cpu_io(); +4:rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); + if(regs.p.m)skip; +5:rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); +6:cpu_io(); + if(regs.p.m) { op_$1_b(); skip; } + else op_$1_w(); +7:op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); +8:op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); +} + +inc_dp(0xe6, inc), +dec_dp(0xc6, dec), +asl_dp(0x06, asl), +lsr_dp(0x46, lsr), +rol_dp(0x26, rol), +ror_dp(0x66, ror), +trb_dp(0x14, trb), +tsb_dp(0x04, tsb) { +1:dp = op_read(); +2:cpu_c2(); +3:rd.l = op_read(OPMODE_DP, dp); + if(regs.p.m)skip; +4:rd.h = op_read(OPMODE_DP, dp + 1); +5:cpu_io(); + if(regs.p.m) { op_$1_b(); skip; } + else op_$1_w(); +6:op_write(OPMODE_DP, dp + 1, rd.h); +7:op_write(OPMODE_DP, dp, rd.l); +} + +inc_dpx(0xf6, inc), +dec_dpx(0xd6, dec), +asl_dpx(0x16, asl), +lsr_dpx(0x56, lsr), +rol_dpx(0x36, rol), +ror_dpx(0x76, ror) { +1:dp = op_read(); +2:cpu_c2(); +3:cpu_io(); +4:rd.l = op_read(OPMODE_DP, dp + regs.x.w); + if(regs.p.m)skip; +5:rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); +6:cpu_io(); + if(regs.p.m) { op_$1_b(); skip; } + else op_$1_w(); +7:op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); +8:op_write(OPMODE_DP, dp + regs.x.w, rd.l); +} diff --git a/src/cpu/bcpu/op_write.b b/src/cpu/bcpu/op_write.b new file mode 100644 index 00000000..e1ba5c14 --- /dev/null +++ b/src/cpu/bcpu/op_write.b @@ -0,0 +1,151 @@ +sta_addr(0x8d, regs.p.m, regs.a.w), +stx_addr(0x8e, regs.p.x, regs.x.w), +sty_addr(0x8c, regs.p.x, regs.y.w), +stz_addr(0x9c, regs.p.m, 0x0000) { +1:aa.l = op_read(); +2:aa.h = op_read(); +3:op_write(OPMODE_DBR, aa.w, $2); + if($1)end; +4:op_write(OPMODE_DBR, aa.w + 1, $2 >> 8); +} + +sta_addrx(0x9d, regs.p.m, regs.a.w), +stz_addrx(0x9e, regs.p.m, 0x0000) { +1:aa.l = op_read(); +2:aa.h = op_read(); +3:cpu_c4(aa.w, aa.w + regs.x.w); +4:op_write(OPMODE_DBR, aa.w + regs.x.w, $2); + if($1)end; +5:op_write(OPMODE_DBR, aa.w + regs.x.w + 1, $2 >> 8); +} + +sta_addry(0x99) { +1:aa.l = op_read(); +2:aa.h = op_read(); +3:cpu_c4(aa.w, aa.w + regs.y.w); +4:op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); + if(regs.p.m)end; +5:op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); +} + +sta_long(0x8f) { +1:aa.l = op_read(); +2:aa.h = op_read(); +3:aa.b = op_read(); +4:op_write(OPMODE_LONG, aa.d, regs.a.l); + if(regs.p.m)end; +5:op_write(OPMODE_LONG, aa.d + 1, regs.a.h); +} + +sta_longx(0x9f) { +1:aa.l = op_read(); +2:aa.h = op_read(); +3:aa.b = op_read(); +4:op_write(OPMODE_LONG, aa.d + regs.x.w, regs.a.l); + if(regs.p.m)end; +5:op_write(OPMODE_LONG, aa.d + regs.x.w + 1, regs.a.h); +} + +sta_dp(0x85, regs.p.m, regs.a.w), +stx_dp(0x86, regs.p.x, regs.x.w), +sty_dp(0x84, regs.p.x, regs.y.w), +stz_dp(0x64, regs.p.m, 0x0000) { +1:dp = op_read(); +2:cpu_c2(); +3:op_write(OPMODE_DP, dp, $2); + if($1)end; +4:op_write(OPMODE_DP, dp + 1, $2 >> 8); +} + +sta_dpx(0x95, regs.p.m, regs.a.w), +sty_dpx(0x94, regs.p.x, regs.y.w), +stz_dpx(0x74, regs.p.m, 0x0000) { +1:dp = op_read(); +2:cpu_c2(); +3:cpu_io(); +4:op_write(OPMODE_DP, dp + regs.x.w, $2); + if($1)end; +5:op_write(OPMODE_DP, dp + regs.x.w + 1, $2 >> 8); +} + +stx_dpy(0x96) { +1:dp = op_read(); +2:cpu_c2(); +3:cpu_io(); +4:op_write(OPMODE_DP, dp + regs.y.w, regs.x.l); + if(regs.p.x)end; +5:op_write(OPMODE_DP, dp + regs.y.w + 1, regs.x.h); +} + +sta_idp(0x92) { +1:dp = op_read(); +2:cpu_c2(); +3:aa.l = op_read(OPMODE_DP, dp); +4:aa.h = op_read(OPMODE_DP, dp + 1); +5:op_write(OPMODE_DBR, aa.w, regs.a.l); + if(regs.p.m)end; +6:op_write(OPMODE_DBR, aa.w + 1, regs.a.h); +} + +sta_ildp(0x87) { +1:dp = op_read(); +2:cpu_c2(); +3:aa.l = op_read(OPMODE_DP, dp); +4:aa.h = op_read(OPMODE_DP, dp + 1); +5:aa.b = op_read(OPMODE_DP, dp + 2); +6:op_write(OPMODE_LONG, aa.d, regs.a.l); + if(regs.p.m)end; +7:op_write(OPMODE_LONG, aa.d + 1, regs.a.h); +} + +sta_idpx(0x81) { +1:dp = op_read(); +2:cpu_c2(); +3:cpu_io(); +4:aa.l = op_read(OPMODE_DP, dp + regs.x.w); +5:aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); +6:op_write(OPMODE_DBR, aa.w, regs.a.l); + if(regs.p.m)end; +7:op_write(OPMODE_DBR, aa.w + 1, regs.a.h); +} + +sta_idpy(0x91) { +1:dp = op_read(); +2:cpu_c2(); +3:aa.l = op_read(OPMODE_DP, dp); +4:aa.h = op_read(OPMODE_DP, dp + 1); +5:cpu_c4(aa.w, aa.w + regs.y.w); +6:op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); + if(regs.p.m)end; +7:op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); +} + +sta_ildpy(0x97) { +1:dp = op_read(); +2:cpu_c2(); +3:aa.l = op_read(OPMODE_DP, dp); +4:aa.h = op_read(OPMODE_DP, dp + 1); +5:aa.b = op_read(OPMODE_DP, dp + 2); +6:op_write(OPMODE_LONG, aa.d + regs.y.w, regs.a.l); + if(regs.p.m)end; +7:op_write(OPMODE_LONG, aa.d + regs.y.w + 1, regs.a.h); +} + +sta_sr(0x83) { +1:sp = op_read(); +2:cpu_io(); +3:op_write(OPMODE_SP, sp, regs.a.l); + if(regs.p.m)end; +4:op_write(OPMODE_SP, sp + 1, regs.a.h); +} + +sta_isry(0x93) { +1:sp = op_read(); +2:cpu_io(); +3:aa.l = op_read(OPMODE_SP, sp); +4:aa.h = op_read(OPMODE_SP, sp + 1); +5:cpu_io(); +6:op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); + if(regs.p.m)end; +7:op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); +} diff --git a/src/cpu/bcpu/srtc.cpp b/src/cpu/bcpu/srtc.cpp new file mode 100644 index 00000000..d1c1281d --- /dev/null +++ b/src/cpu/bcpu/srtc.cpp @@ -0,0 +1,158 @@ +/* + S-RTC chip emulation + Used by Hudson Soft in Dai Kaijuu Monogatari II and Far East of Eden Zero. + Currently, only the former is supported by bsnes. + + Original S-RTC emulation code via John Weidman/SNES9x + Rewritten for compatibility with bsnes via byuu + + The S-RTC is a real-time clock chip that was added to the above two carts + to allow the games to maintain the current time, even when the game was not + powered on. Thus allowing special events at certain times, and on certain + dates. Hudson Soft called this the PLG (Player's Life Gameplay System). + + This chip is a special case to the term 'emulation' itself. + There are a few different ways to go about emulating this chip, and each + result in a different style of emulation. + + The first is to simply return the current PC system time when the S-RTC is + read from. This emulates the original S-RTC in the sense that it always + returns the true current time, ignoring the speed that the SNES itself is + running at. The downside to this method is that you lose the ability to set + the time to whatever you choose inside the game itself. It will always return + the true time, regardless. This can be overcome by changing the PC system time, + which actually adds a greater degree of control over event timing, very useful + for emulation. It also has a timeshifting flaw discussed below. + + The second is to run the S-RTC relative to the SNES speed. This means that + if the emulator is sped up (via fast forward key, frameskipping, etc), or + slowed down (via slowdown key, system bottlenecking, etc); the time increments + slower, thus ~60 frames on the SNES equal one second. Without this, timeshifting + will occur between the S-RTC and the real SNES. + + The third and final method is to save a copy of the local system time when the + S-RTC is initially set, and compare the current system time against this value + when setting the S-RTC time. This overcomes the first methods' shortcoming of + not allowing the player to set the time in-game, however a new problem arises. + You now have to save the time when the RTC was initially set to both savestates + and to save-game data. This would require an extra file, or the breaking of + perhaps the only standard format (.srm savegame backups) in the entire SNES + emulation scene. You also give up the control of being able to override the + RTC clock at will via the PC system time outside of emulation. + The first method has another advantage over the third: Dai Kaijuu Monogatari II + only allows dates in the range of the years 1996-2199. The first method gets + around this limitation. But who knows, maybe it will break something in the + game if the date exceeds 2199... I guess we'll worry about that in two hundred + years from now. + + For my implementation, I chose to go with the first method. Both for simplicity + and because I did not wish to create a new method for saving the system time + whenever the RTC is set. +*/ + +void bCPU::srtc_set_time() { +time_t rawtime; +tm *t; + ::time(&rawtime); + t = localtime(&rawtime); + +//see srtc.h for format of srtc.data[] + srtc.data[0] = t->tm_sec % 10; + srtc.data[1] = t->tm_sec / 10; + srtc.data[2] = t->tm_min % 10; + srtc.data[3] = t->tm_min / 10; + srtc.data[4] = t->tm_hour % 10; + srtc.data[5] = t->tm_hour / 10; + srtc.data[6] = t->tm_mday % 10; + srtc.data[7] = t->tm_mday / 10; + srtc.data[8] = t->tm_mon + 1; + srtc.data[9] = t->tm_year % 10; + srtc.data[10] = (t->tm_year / 10) % 10; + srtc.data[11] = 9 + (t->tm_year / 100); + srtc.data[12] = t->tm_wday; +} + +void bCPU::srtc_power() { + memset(&srtc, 0, sizeof(srtc)); + reset(); +} + +void bCPU::srtc_reset() { + srtc.index = -1; + srtc.mode = SRTC_READ; +} + +//Please see notes above about the implementation of the S-RTC +//Writes are stored the srtc.data[] array, but they are ignored +//as reads will refresh the data array with the current system +//time. The write method is only here for the sake of faux +//emulation of the real hardware. +void bCPU::srtc_write(uint8 data) { + data &= 0x0f; //only the low four bits are used + + if(data >= 0x0d) { + switch(data) { + case 0x0d: + srtc.mode = SRTC_READ; + srtc.index = -1; + break; + case 0x0e: + srtc.mode = SRTC_COMMAND; + break; + case 0x0f: + //unknown behaviour + break; + } + return; + } + + if(srtc.mode == SRTC_WRITE) { + if(srtc.index >= 0 && srtc.index < MAX_SRTC_INDEX) { + srtc.data[srtc.index++] = data; + + if(srtc.index == MAX_SRTC_INDEX) { + //all S-RTC data has been loaded by program + srtc.data[srtc.index++] = 0x00; //day_of_week + } + } + } else if(srtc.mode == SRTC_COMMAND) { + switch(data) { + case SRTC_COMMAND_CLEAR: + memset(srtc.data, 0, MAX_SRTC_INDEX + 1); + srtc.index = -1; + srtc.mode = SRTC_READY; + break; + case SRTC_COMMAND_WRITE: + srtc.index = 0; + srtc.mode = SRTC_WRITE; + break; + default: + //unknown behaviour + srtc.mode = SRTC_READY; + break; + } + } else { + if(srtc.mode == SRTC_READ) { + //ignore writes while in read mode + } else if(srtc.mode == SRTC_READY) { + //unknown behaviour + } + } +} + +uint8 bCPU::srtc_read() { + if(srtc.mode == SRTC_READ) { + if(srtc.index < 0) { + srtc_set_time(); + srtc.index++; + return 0x0f; //send start message + } else if(srtc.index > MAX_SRTC_INDEX) { + srtc.index = -1; + return 0x0f; //send finished message + } else { + return srtc.data[srtc.index++]; + } + } else { + return 0x00; + } +} diff --git a/src/cpu/bcpu/srtc.h b/src/cpu/bcpu/srtc.h new file mode 100644 index 00000000..4a828e3f --- /dev/null +++ b/src/cpu/bcpu/srtc.h @@ -0,0 +1,48 @@ +void srtc_set_time(); +void srtc_power(); +void srtc_reset(); +void srtc_write(uint8 data); +uint8 srtc_read(); + +#define MAX_SRTC_INDEX 0x0c + +enum { + SRTC_READ = 0, + SRTC_WRITE, + SRTC_COMMAND, + SRTC_READY +}; + +enum { + SRTC_COMMAND_WRITE = 0, + SRTC_COMMAND_CLEAR = 4 +}; + +#define DAYTICKS (60*60*24) +#define HOURTICKS (60*60) +#define MINUTETICKS (60) + +/****************************** +[srtc.data structure] +Index Description Range +----- ----------- ----- + 0 Seconds low 0-9 + 1 Seconds high 0-5 + 2 Minutes low 0-9 + 3 Minutes high 0-5 + 4 Hour low 0-9 + 5 Hour high 0-2 + 6 Day low 0-9 + 7 Day high 0-3 + 8 Month 1-12 + 9 Year ones 0-9 + 10 Year tens 0-9 + 11 Year hundreds 9-11 (9=19xx, 10=20xx, 11=21xx) + 12 Day of week 0-6 (0=Sunday, ...) +******************************/ + +struct { + int8 index; + uint8 mode; + uint8 data[MAX_SRTC_INDEX + 1]; +}srtc; diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 9ecbf73f..92777167 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -2,20 +2,34 @@ class CPU { public: +//timing + virtual uint16 vcounter() = 0; + virtual uint16 hcounter() = 0; + virtual uint16 hcycles() = 0; + virtual bool interlace() = 0; + virtual bool interlace_field() = 0; + virtual bool overscan() = 0; + + virtual void set_interlace(bool r) = 0; + virtual void set_overscan (bool r) = 0; + MMIO *mmio; CPURegs regs; + virtual uint8 port_read (uint8 port) = 0; + virtual void port_write(uint8 port, uint8 value) = 0; + enum { FLAG_N = 0x80, FLAG_V = 0x40, FLAG_M = 0x20, FLAG_X = 0x10, FLAG_D = 0x08, FLAG_I = 0x04, FLAG_Z = 0x02, FLAG_C = 0x01 }; - virtual uint8 pio_status() = 0; - virtual void run() = 0; - virtual void scanline() = 0; - virtual void frame() = 0; - virtual void power() = 0; - virtual void reset() = 0; + virtual uint8 pio_status() = 0; + virtual void run() = 0; + virtual void scanline() = 0; + virtual void frame() = 0; + virtual void power() = 0; + virtual void reset() = 0; //opcode disassembler enum { diff --git a/src/cpu/cpuregs.h b/src/cpu/cpuregs.h index 6725fe2a..215ef2eb 100644 --- a/src/cpu/cpuregs.h +++ b/src/cpu/cpuregs.h @@ -2,32 +2,35 @@ class CPURegFlags { private: template class bit { public: - uint8 b; - inline operator bool() { return (b & B); } - inline operator = (bool i) { (i) ? b |= B : b &= ~B; return (b & B); } - inline operator & (bool i) { if(i)b &= ~B; return (b & B); } - inline operator | (bool i) { if(i)b |= B; return (b & B); } - inline operator ^ (bool i) { if(i)b ^= B; return (b & B); } + uint8 _b; + inline operator bool() { return (_b & B); } + inline bool operator = (bool i) { (i) ? _b |= B : _b &= ~B; return (_b & B); } + inline bool operator & (bool i) { if(i)_b &= ~B; return (_b & B); } + inline bool operator &= (bool i) { if(i)_b &= ~B; return (_b & B); } + inline bool operator | (bool i) { if(i)_b |= B; return (_b & B); } + inline bool operator |= (bool i) { if(i)_b |= B; return (_b & B); } + inline bool operator ^ (bool i) { if(i)_b ^= B; return (_b & B); } + inline bool operator ^= (bool i) { if(i)_b ^= B; return (_b & B); } }; public: union { - uint8 b; + uint8 _b; bit<0x80> n; bit<0x40> v; - bit<0x20> m; - bit<0x10> x; + bit<0x20> m, p; + bit<0x10> x, b; bit<0x08> d; bit<0x04> i; bit<0x02> z; bit<0x01> c; }; - CPURegFlags() { b = 0; } - inline operator uint8() { return b; } - inline unsigned operator = (uint8 i) { b = i; return b; } - inline unsigned operator &= (uint8 i) { b &= i; return b; } - inline unsigned operator |= (uint8 i) { b |= i; return b; } - inline unsigned operator ^= (uint8 i) { b ^= i; return b; } + CPURegFlags() { _b = 0; } + inline operator uint8() { return _b; } + inline unsigned operator = (uint8 i) { _b = i; return _b; } + inline unsigned operator &= (uint8 i) { _b &= i; return _b; } + inline unsigned operator |= (uint8 i) { _b |= i; return _b; } + inline unsigned operator ^= (uint8 i) { _b ^= i; return _b; } }; class CPUReg16 { diff --git a/src/cpu/dcpu.cpp b/src/cpu/dcpu.cpp index 240bcaab..26137d2d 100644 --- a/src/cpu/dcpu.cpp +++ b/src/cpu/dcpu.cpp @@ -378,7 +378,7 @@ uint8 op, op0, op1, op2; strcat(s, " "); sprintf(t, "A:%0.4x X:%0.4x Y:%0.4x S:%0.4x D:%0.4x DB:%0.2x ", - regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d, regs.db); + 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", diff --git a/src/interface.h b/src/interface.h index d4e45224..0a6cedca 100644 --- a/src/interface.h +++ b/src/interface.h @@ -1,9 +1,5 @@ #include "reader/reader.h" -#include "clock/clock.h" -#include "clock/bclock/bclock.h" -extern Clock *clock; - #include "memory/memory.h" #include "memory/bmemory/bmemory.h" extern MMIO mmio_unmapped; @@ -13,6 +9,11 @@ extern MemBus *mem_bus; #include "cpu/bcpu/bcpu.h" extern CPU *cpu; +#include "apu/apu.h" +#include "apu/bapu/bapu.h" +#include "apu/bapuskip/bapuskip.h" +extern APU *apu; + #include "ppu/ppu.h" #include "ppu/bppu/bppu.h" extern PPU *ppu; @@ -21,9 +22,9 @@ extern PPU *ppu; extern SNES *snes; #ifdef INTERFACE_MAIN - Clock *clock; - MemBus *mem_bus; - CPU *cpu; - PPU *ppu; - SNES *snes; + MemBus *mem_bus; + CPU *cpu; + APU *apu; + PPU *ppu; + SNES *snes; #endif diff --git a/src/lib/libconfig.cpp b/src/lib/libconfig.cpp index 5fb4cf31..247ea6f2 100644 --- a/src/lib/libconfig.cpp +++ b/src/lib/libconfig.cpp @@ -1,18 +1,29 @@ #include "libbase.h" #include "libconfig.h" +//if this function returns true, the option is written +//to the configuration file. by always returning true, +//every option is always written. disable the first line +//to only output options after they have been changed by +//the program from their default values first. bool config_item::changed() { - return (is_string == true) ? (*strsource != strdef) : (*source != def); + return true; + + if(is_string == true) { + if(!strcmp(*strsource, strdef))return false; + return true; + } + return (*source != def); } config_item::config_item() { + strcpy(name, ""); + strcpy(strdef, ""); is_string = false; source = 0; strsource = 0; def = 0; - strdef = ""; type = 0; - name = ""; } void config::add(uint32 *variable, char *name, uint32 def, uint32 type) { @@ -21,13 +32,12 @@ int n; n = item_count; item[n] = new config_item(); - + strcpy(item[n]->name, name); item[n]->is_string = false; - item[n]->name = name; - item[n]->source = variable; item[n]->def = def; - item[n]->type = type; + item[n]->source = variable; *item[n]->source = item[n]->def; + item[n]->type = type; item_count++; } @@ -38,18 +48,19 @@ int n; n = item_count; item[n] = new config_item(); - item[n]->is_string = true; - item[n]->name = name; - item[n]->strsource = variable; - item[n]->strdef = def; - *item[n]->strsource = item[n]->strdef; + strcpy(item[n]->name, name); + item[n]->is_string = true; + strcpy(item[n]->strdef, def); + item[n]->strsource = variable; + strcpy(*item[n]->strsource, item[n]->strdef); + item[n]->type = type; item_count++; } uint32 config::find(char *name) { for(int i=0;iname == name) { + if(!strcmp(item[i]->name, name)) { return i; } } @@ -66,7 +77,7 @@ string &config::strget(char *name) { int i = find(name); if(i == null) { static string not_found; - not_found = ""; + strcmp(not_found, ""); return not_found; } return *item[i]->strsource; @@ -81,7 +92,7 @@ int i = find(name); void config::set(char *name, char *value) { int i = find(name); if(i == null)return; - *item[i]->strsource = value; + strcpy(*item[i]->strsource, value); } void config::load(char *fn) { @@ -90,14 +101,14 @@ char *buffer; int i, fsize; uint32 l; fp = fopen(fn, "rb"); -/* file doesn't exist yet, do nothing */ +//file doesn't exist yet, do nothing if(!fp)return; fseek(fp, 0, SEEK_END); fsize = ftell(fp); fseek(fp, 0, SEEK_SET); -/* blank file, do nothing */ +//blank file, do nothing if(fsize == 0) { fclose(fp); return; @@ -108,7 +119,7 @@ uint32 l; fclose(fp); buffer[fsize] = 0; - data = buffer; + strcpy(data, buffer); free(buffer); replace(data, "\r\n", "\n"); qreplace(data, "\t", " "); @@ -118,29 +129,31 @@ uint32 l; for(i=0;isource = 1; - } else if(part[1] == "false" || part[1] == "no" || part[1] == "off" || part[1] == "disabled") { + } else if(!strcmp(part[1], "false") || !strcmp(part[1], "no") || + !strcmp(part[1], "off") || !strcmp(part[1], "disabled")) { *item[l]->source = 0; } else if(item[l]->type == HEX) { - *item[l]->source = strhex(part[1]); + *item[l]->source = strhex(*part[1] + 2); //skip 0x prefix } else { /* fall back on DEC */ *item[l]->source = strdec(part[1]); } @@ -149,38 +162,38 @@ uint32 l; } } -/* create a text string from config item[i] to be output via config->save() */ +//create a text string from config item[i] to be output via config->save() void config::set_newline(int i) { char t[16]; if(item[i]->is_string == true) { - newline = item[i]->name; - newline += " = \""; - newline += *item[i]->strsource; - newline += "\""; + strcpy(newline, item[i]->name); + strcat(newline, " = \""); + strcat(newline, *item[i]->strsource); + strcat(newline, "\""); } else { - newline = item[i]->name; - newline += " = "; + strcpy(newline, item[i]->name); + strcat(newline, " = "); switch(item[i]->type) { case TRUEFALSE: - newline += (*item[i]->source)?"true":"false"; + strcat(newline, (*item[i]->source)?"true":"false"); break; case YESNO: - newline += (*item[i]->source)?"yes":"no"; + strcat(newline, (*item[i]->source)?"yes":"no"); break; case ONOFF: - newline += (*item[i]->source)?"on":"off"; + strcat(newline, (*item[i]->source)?"on":"off"); break; case ENABLED: - newline += (*item[i]->source)?"enabled":"disabled"; + strcat(newline, (*item[i]->source)?"enabled":"disabled"); break; case HEX: - sprintf(t, "%x", *item[i]->source); - newline += t; + sprintf(t, "0x%0.2x", *item[i]->source); + strcat(newline, t); break; case DEC: default: sprintf(t, "%d", *item[i]->source); - newline += t; + strcat(newline, t); break; } } @@ -206,21 +219,21 @@ bool blank = false; } else { buffer = (char*)malloc(fsize + 1); fread(buffer, 1, fsize, fp); - fclose(fp); buffer[fsize] = 0; - data = buffer; + strcpy(data, buffer); free(buffer); } + fclose(fp); } fp = fopen(fn, "wb"); -/* no write access? */ +//no write access? if(!fp)return; -/* list of config items. if the item is set in the - existing config file, then don't test it to see - if it needs to be written again later on */ +//list of config items. if the item is set in the +//existing config file, then don't test it to see +//if it needs to be written again later on memset(set, 0, item_count); if(blank == false) { @@ -237,9 +250,9 @@ bool blank = false; strset(line[i], strqpos(line[i], "#"), 0); } - /* this line is empty, restore the old line and continue */ + //this line is empty, restore the old line and continue if(strlen(line[i]) == 0) { - line[i] = oldline[i]; + strcpy(line[i], oldline[i]); continue; } @@ -247,44 +260,44 @@ bool blank = false; l = find(*part[0]); if(l == null) { - /* invalid item name, restore the old line and continue */ - line[i] = oldline[i]; + //invalid item name, restore the old line and continue + strcpy(line[i], oldline[i]); continue; } set[l] = 1; set_newline(l); - /* copy the user comment from the old config file, if it exists */ + //copy the user comment from the old config file, if it exists if(strqpos(oldline[i], "#") != null) { - newline += " "; - newline += *oldline[i] + strqpos(oldline[i], "#"); + strcat(newline, " "); + strcat(newline, *oldline[i] + strqpos(oldline[i], "#")); } - line[i] = newline; + strcpy(line[i], newline); } - /* write out the old config file + changes first */ + //write out the old config file + changes first for(i=0;ichanged() == false)continue; set_newline(i); - /* prevent a newline from appearing at the top of the file - when the config file is created for the first time */ + //prevent a newline from appearing at the top of the file + //when the config file is created for the first time if(lines_written == 0 && blank == false)fprintf(fp, "\r\n"); fprintf(fp, "%s\r\n", *newline); lines_written++; diff --git a/src/lib/libconfig.h b/src/lib/libconfig.h index dfe4674b..57373799 100644 --- a/src/lib/libconfig.h +++ b/src/lib/libconfig.h @@ -1,5 +1,5 @@ /* - libconfig : version 0.01 ~byuu + libconfig : version 0.02 ~byuu */ #ifndef __LIBCONFIG diff --git a/src/lib/libstring.cpp b/src/lib/libstring.cpp index effc189c..97e66b71 100644 --- a/src/lib/libstring.cpp +++ b/src/lib/libstring.cpp @@ -247,10 +247,10 @@ int ssl = strlen(str), ksl = strlen(key); /* does not work on type char* because function increases string length */ void strquote(_string &str) { static string t; - t = "\""; - t += str; - t += "\""; - str = t; + strcpy(t, "\""); + strcat(t, str); + strcat(t, "\""); + strcpy(str, t); } bool strunquote(char *str) { diff --git a/src/lib/libstring.h b/src/lib/libstring.h index fd924a94..b41ff4dd 100644 --- a/src/lib/libstring.h +++ b/src/lib/libstring.h @@ -1,5 +1,5 @@ /* - libstring : version 0.04 ~byuu + libstring : version 0.05 ~byuu */ #ifndef __LIBSTRING @@ -49,34 +49,29 @@ class _string { public: char *s; uint32 size; - -/* * */ inline char* operator*() { return s; } -/* = */ +#ifdef __LIBSTRING_OVERLOADS inline _string& operator=(char *cpy); inline _string& operator=(_string &cpy); inline _string& operator=(string &cpy); -/* += */ inline _string& operator+=(char *cat); inline _string& operator+=(_string &cat); inline _string& operator+=(string &cat); -/* -= */ inline _string& operator-=(char *cut); inline _string& operator-=(_string &cut); inline _string& operator-=(string &cut); -/* == */ inline bool operator==(char *cmp); inline bool operator==(_string &cmp); inline bool operator==(string &cmp); -/* != */ inline bool operator!=(char *cmp); inline bool operator!=(_string &cmp); inline bool operator!=(string &cmp); +#endif inline operator char*() { return s; } @@ -91,33 +86,29 @@ uint32 count, listcount; void addto(uint32 num); //creates all needed strings to make list[num] valid _string &str(uint32 num); //gets a _string reference, creating it + new strings if needed -/* * */ inline char* operator*() { return strptr(str(0)); } -/* = */ +#ifdef __LIBSTRING_OVERLOADS inline string& operator=(char *cpy); inline string& operator=(_string &cpy); inline string& operator=(string &cpy); -/* += */ inline string& operator+=(char *cat); inline string& operator+=(_string &cat); inline string& operator+=(string &cat); -/* -= */ inline string& operator-=(char *cut); inline string& operator-=(_string &cut); inline string& operator-=(string &cut); -/* == */ inline bool operator==(char *cmp); inline bool operator==(_string &cmp); inline bool operator==(string &cmp); -/* != */ inline bool operator!=(char *cmp); inline bool operator!=(_string &cmp); inline bool operator!=(string &cmp); +#endif inline operator char*() { return str(0).s; } inline operator _string&() { return str(0); } @@ -128,9 +119,7 @@ uint32 count, listcount; ~string(); }; -// -// = -// +#ifdef __LIBSTRING_OVERLOADS inline _string& _string::operator=(char *cpy) { strcpy(*this, cpy); return *this; @@ -157,9 +146,6 @@ inline string& string::operator=(string &cpy) { return *this; } -// -// += -// inline _string& _string::operator+=(char *cat) { strcat(*this, cat); return *this; @@ -186,9 +172,6 @@ inline string& string::operator+=(string &cat) { return *this; } -// -// -= -// inline _string& _string::operator-=(char *cut) { strrtrim(*this, cut); return *this; @@ -215,9 +198,6 @@ inline string& string::operator-=(string &cut) { return *this; } -// -// == -// inline bool _string::operator==(char *cmp) { if(!strcmp(*this, cmp))return true; return false; @@ -244,9 +224,6 @@ inline bool string::operator==(string &cmp) { return false; } -// -// != -// inline bool _string::operator!=(char *cmp) { if(!strcmp(*this, cmp))return false; return true; @@ -272,5 +249,6 @@ inline bool string::operator!=(string &cmp) { if(!strcmp(str(0), cmp.str(0)))return false; return true; } +#endif //__LIBSTRING_OVERLOADS -#endif +#endif //__LIBSTRING diff --git a/src/lib/libstring_sprintf.cpp b/src/lib/libstring_sprintf.cpp index ab86833d..d1c0ab40 100644 --- a/src/lib/libstring_sprintf.cpp +++ b/src/lib/libstring_sprintf.cpp @@ -17,7 +17,7 @@ uint8 pad_type, pad_len; uint32 num; char *r; va_start(args, s); - strcpy(str, ""); + strcpy(*str, ""); for(i=0;i= size)resize(index + 1); - if(index > sizelimit)return __null; + if(index > sizelimit)return array[size - 1]; return array[index]; } }; diff --git a/src/memory/bmemory/bcart_exhirom.cpp b/src/memory/bmemory/bcart_exhirom.cpp new file mode 100644 index 00000000..86a85943 --- /dev/null +++ b/src/memory/bmemory/bcart_exhirom.cpp @@ -0,0 +1,108 @@ +void bCartExHiROM::write_protect(bool r) { write_protected = r; } + +uint8 bCartExHiROM::read(uint32 addr) { +uint32 b, w; + addr &= 0xffffff; + b = (addr >> 16); + w = (addr & 0xffff); + +//SRAM Region A + if((b & 0x7f) >= 0x30 && (b & 0x7f) <= 0x3f && (w & 0xe000) == 0x6000) { + b &= 0x7f; + if(b >= 0x30 && b <= 0x3f) { + if(sram_size) { + addr = (b - 0x30) * 0x2000 + (w - 0x6000); + addr &= (sram_size - 1); + return sram[addr]; + } else { + return 0x00; //no SRAM available + } + } else { + return 0x00; //unmapped + } + } + +//SRAM Region B + if(b >= 0x70 && b <= 0x7d) { + if(sram_size) { + addr = (addr & 0xffffff) - 0x700000; + addr &= (sram_size - 1); + return sram[addr]; + } else { + return 0x00; //no SRAM available + } + } + + if(b <= 0x3f) { + addr &= 0x3fffff; + addr += 0x400000; + } else if(b <= 0x7f) { + addr &= 0x3fffff; + addr += 0x400000; + } else if(b <= 0xbf) { + addr &= 0x3fffff; + } else { + addr &= 0x3fffff; + } + + if(addr < rom_size)return rom[addr]; + return 0x00; +} + +void bCartExHiROM::write(uint32 addr, uint8 value) { +uint32 b, w; + addr &= 0xffffff; + b = (addr >> 16); + w = (addr & 0xffff); + +//SRAM Region A + if((b & 0x7f) >= 0x30 && (b & 0x7f) <= 0x3f && (w & 0xe000) == 0x6000) { + b &= 0x7f; + if(b >= 0x30 && b <= 0x3f) { + if(sram_size) { + addr = (b - 0x30) * 0x2000 + (w - 0x6000); + addr &= (sram_size - 1); + sram[addr] = value; + return; + } else { + return; //no SRAM available + } + } else { + return; //unmapped + } + } + +//SRAM Region B + if(b >= 0x70 && b <= 0x7d) { + if(sram_size) { + addr = (addr & 0xffffff) - 0x700000; + addr &= (sram_size - 1); + sram[addr] = value; + } else { + return; //no SRAM available + } + } + + if(write_protected == true)return; + + if(b <= 0x3f) { + addr &= 0x3fffff; + addr += 0x400000; + } else if(b <= 0x7f) { + addr &= 0x3fffff; + addr += 0x400000; + } else if(b <= 0xbf) { + addr &= 0x3fffff; + } else { + addr &= 0x3fffff; + } + + if(addr < rom_size)rom[addr] = value; +} + +void bCartExHiROM::set_cartinfo(CartInfo *ci) { + rom = ci->rom; + sram = ci->sram; + rom_size = ci->rom_size; + sram_size = ci->sram_size; +} diff --git a/src/memory/bmemory/bcart_exhirom.h b/src/memory/bmemory/bcart_exhirom.h new file mode 100644 index 00000000..63b48660 --- /dev/null +++ b/src/memory/bmemory/bcart_exhirom.h @@ -0,0 +1,14 @@ +class bCartExHiROM : public Cart { +private: +bool write_protected; + +public: +uint8 *rom, *sram; +uint32 rom_size, sram_size; + uint8 read (uint32 addr); + void write(uint32 addr, byte value); + void write_protect(bool r); + void set_cartinfo(CartInfo *ci); + + bCartExHiROM() : write_protected(true) {} +}; diff --git a/src/memory/bmemory/bcart_hirom.cpp b/src/memory/bmemory/bcart_hirom.cpp new file mode 100644 index 00000000..3bbc9e53 --- /dev/null +++ b/src/memory/bmemory/bcart_hirom.cpp @@ -0,0 +1,86 @@ +void bCartHiROM::write_protect(bool r) { write_protected = r; } + +uint8 bCartHiROM::read(uint32 addr) { +uint32 b, w; + addr &= 0xffffff; + b = (addr >> 16); + w = (addr & 0xffff); + +//SRAM Region A + if((b & 0x7f) >= 0x30 && (b & 0x7f) <= 0x3f && (w & 0xe000) == 0x6000) { + b &= 0x7f; + if(b >= 0x30 && b <= 0x3f) { + if(sram_size) { + addr = (b - 0x30) * 0x2000 + (w - 0x6000); + addr &= (sram_size - 1); + return sram[addr]; + } else { + return 0x00; //no SRAM available + } + } else { + return 0x00; //unmapped + } + } + +//SRAM Region B + if(b >= 0x70 && b <= 0x7d) { + if(sram_size) { + addr = (addr & 0xffffff) - 0x700000; + addr &= (sram_size - 1); + return sram[addr]; + } else { + return 0x00; //no SRAM available + } + } + + addr &= 0x3fffff; + if(addr < rom_size)return rom[addr]; + + return 0x00; +} + +void bCartHiROM::write(uint32 addr, uint8 value) { +uint32 b, w; + addr &= 0xffffff; + b = (addr >> 16); + w = (addr & 0xffff); + +//SRAM Region A + if((b & 0x7f) >= 0x30 && (b & 0x7f) <= 0x3f && (w & 0xe000) == 0x6000) { + b &= 0x7f; + if(b >= 0x30 && b <= 0x3f) { + if(sram_size) { + addr = (b - 0x30) * 0x2000 + (w - 0x6000); + addr &= (sram_size - 1); + sram[addr] = value; + return; + } else { + return; //no SRAM available + } + } else { + return; //unmapped + } + } + +//SRAM Region B + if(b >= 0x70 && b <= 0x7d) { + if(sram_size) { + addr = (addr & 0xffffff) - 0x700000; + addr &= (sram_size - 1); + sram[addr] = value; + } else { + return; //no SRAM available + } + } + + if(write_protected == true)return; + addr &= 0x3fffff; + if(addr < rom_size)rom[addr] = value; +} + +void bCartHiROM::set_cartinfo(CartInfo *ci) { + rom = ci->rom; + sram = ci->sram; + rom_size = ci->rom_size; + sram_size = ci->sram_size; +} diff --git a/src/memory/bmemory/bcart_hirom.h b/src/memory/bmemory/bcart_hirom.h new file mode 100644 index 00000000..cccce628 --- /dev/null +++ b/src/memory/bmemory/bcart_hirom.h @@ -0,0 +1,14 @@ +class bCartHiROM : public Cart { +private: +bool write_protected; + +public: +uint8 *rom, *sram; +uint32 rom_size, sram_size; + uint8 read (uint32 addr); + void write(uint32 addr, byte value); + void write_protect(bool r); + void set_cartinfo(CartInfo *ci); + + bCartHiROM() : write_protected(true) {} +}; diff --git a/src/memory/bmemory/bcart_lorom.cpp b/src/memory/bmemory/bcart_lorom.cpp new file mode 100644 index 00000000..85ea74d7 --- /dev/null +++ b/src/memory/bmemory/bcart_lorom.cpp @@ -0,0 +1,104 @@ +void bCartLoROM::write_protect(bool r) { write_protected = r; } + +uint8 bCartLoROM::read(uint32 addr) { +uint32 b, w; + addr &= 0xffffff; + b = (addr >> 16); + w = (addr & 0xffff); + +//SRAM Region A + if((b & 0x7f) >= 0x30 && (b & 0x7f) <= 0x3f && (w & 0xe000) == 0x6000) { + b &= 0x7f; + if(b >= 0x30 && b <= 0x3f) { + if(sram_size) { + addr = (b - 0x30) * 0x2000 + (w - 0x6000); + addr &= (sram_size - 1); + return sram[addr]; + } else { + return 0x00; //no SRAM available + } + } else { + return 0x00; //unmapped + } + } + +//SRAM Region B + if(b >= 0x70 && b <= 0x7d) { + if(sram_size) { + addr = (addr & 0xffffff) - 0x700000; + addr &= (sram_size - 1); + return sram[addr]; + } else { + return 0x00; //no SRAM available + } + } + + if(w & 0x8000) { + b &= 0x7f; + b %= 0x60; + addr = (b << 15) | (addr & 0x7fff); + } else { + b &= 0x7f; + b %= 0x60; + if(b == 0x00)b = 0x60; + addr = (((b << 15) | (addr & 0x7fff)) - 0x8000); + } + if(addr < rom_size)return rom[addr]; + + return 0x00; +} + +void bCartLoROM::write(uint32 addr, uint8 value) { +uint32 b, w; + addr &= 0xffffff; + b = (addr >> 16); + w = (addr & 0xffff); + +//SRAM Region A + if((b & 0x7f) >= 0x30 && (b & 0x7f) <= 0x3f && (w & 0xe000) == 0x6000) { + b &= 0x7f; + if(b >= 0x30 && b <= 0x3f) { + if(sram_size) { + addr = (b - 0x30) * 0x2000 + (w - 0x6000); + addr &= (sram_size - 1); + sram[addr] = value; + return; + } else { + return; //no SRAM available + } + } else { + return; //unmapped + } + } + +//SRAM Region B + if(b >= 0x70 && b <= 0x7d) { + if(sram_size) { + addr = (addr & 0xffffff) - 0x700000; + addr &= (sram_size - 1); + sram[addr] = value; + } else { + return; //no SRAM available + } + } + + if(write_protected == true)return; + if(w & 0x8000) { + b &= 0x7f; + b %= 0x60; + addr = (b << 15) | (addr & 0x7fff); + } else { + b &= 0x7f; + b %= 0x60; + if(b == 0x00)b = 0x60; + addr = (((b << 15) | (addr & 0x7fff)) - 0x8000); + } + if(addr < rom_size)rom[addr] = value; +} + +void bCartLoROM::set_cartinfo(CartInfo *ci) { + rom = ci->rom; + sram = ci->sram; + rom_size = ci->rom_size; + sram_size = ci->sram_size; +} diff --git a/src/memory/bmemory/bcart_lorom.h b/src/memory/bmemory/bcart_lorom.h new file mode 100644 index 00000000..cf279308 --- /dev/null +++ b/src/memory/bmemory/bcart_lorom.h @@ -0,0 +1,14 @@ +class bCartLoROM : public Cart { +private: +bool write_protected; + +public: +uint8 *rom, *sram; +uint32 rom_size, sram_size; + uint8 read (uint32 addr); + void write(uint32 addr, byte value); + void write_protect(bool r); + void set_cartinfo(CartInfo *ci); + + bCartLoROM() : write_protected(true) {} +}; diff --git a/src/memory/bmemory/bmemory.cpp b/src/memory/bmemory/bmemory.cpp index 9d4b1827..66cde60b 100644 --- a/src/memory/bmemory/bmemory.cpp +++ b/src/memory/bmemory/bmemory.cpp @@ -1,147 +1,32 @@ #include "../../base.h" +#include "bcart_lorom.cpp" +#include "bcart_hirom.cpp" +#include "bcart_exhirom.cpp" -uint8 bROM::read(uint32 addr) { -uint32 b, w; - addr &= 0xffffff; - b = (addr >> 16); - w = (addr & 0xffff); +bool bMemBus::load_cart(Reader *rf) { +uint32 cksum, icksum, index; +char cart_title[24]; +uint8 mapper; + if(rom_loaded == true)return false; -/* SRAM Region A */ - if((b & 0x7f) >= 0x30 && (b & 0x7f) <= 0x3f && (w & 0xe000) == 0x6000) { - b &= 0x7f; - if(b >= 0x30 && b <= 0x3f) { - if(sram_size) { - addr = (b - 0x30) * 0x2000 + (w - 0x6000); - addr &= (sram_size - 1); - return sram_data[addr]; - } else { - return 0x00; //no SRAM available - } - } else { - return 0x00; //unmapped - } - } + rf->read(&rom); -/* SRAM Region B */ - if(b >= 0x70 && b <= 0x7d) { - if(sram_size) { - addr = (addr & 0xffffff) - 0x700000; - addr &= (sram_size - 1); - return sram_data[addr]; - } else { - return 0x00; //no SRAM available - } - } + rom_size = rf->size(); - switch(mapper) { - case LOROM: - if(w & 0x8000) { - b &= 0x7f; - b %= 0x60; - addr = (b << 15) | (addr & 0x7fff); - } else { - b &= 0x7f; - b %= 0x60; - if(b == 0x00)b = 0x60; - addr = (((b << 15) | (addr & 0x7fff)) - 0x8000); - } - if(addr < size)return data[addr]; - break; - case HIROM: - addr &= 0x3fffff; - if(addr < size)return data[addr]; - break; - } - return 0x00; -} + if(rom_size < 32768)return false; -void bROM::write(uint32 addr, uint8 value) { -uint32 b, w; - addr &= 0xffffff; - b = (addr >> 16); - w = (addr & 0xffff); - -/* SRAM Region A */ - if((b & 0x7f) >= 0x30 && (b & 0x7f) <= 0x3f && (w & 0xe000) == 0x6000) { - b &= 0x7f; - if(b >= 0x30 && b <= 0x3f) { - if(sram_size) { - addr = (b - 0x30) * 0x2000 + (w - 0x6000); - addr &= (sram_size - 1); - sram_data[addr] = value; - return; - } else { - return; //no SRAM available - } - } else { - return; //unmapped - } - } - -/* SRAM Region B */ - if(b >= 0x70 && b <= 0x7d) { - if(sram_size) { - addr = (addr & 0xffffff) - 0x700000; - addr &= (sram_size - 1); - sram_data[addr] = value; - } else { - return; //no SRAM available - } - } - -/* Block write attempts to ROM by default, debugger can override this */ - if(write_protection == true)return; - - switch(mapper) { - case LOROM: - if(w & 0x8000) { - b &= 0x7f; - b %= 0x60; - addr = (b << 15) | (addr & 0x7fff); - } else { - b &= 0x7f; - b %= 0x60; - if(b == 0x00)b = 0x60; - addr = (((b << 15) | (addr & 0x7fff)) - 0x8000); - } - if(addr < size)data[addr] = value; - break; - case HIROM: - addr &= 0x3fffff; - if(addr < size)data[addr] = value; - break; - } -} - -void bROM::load_sram(Reader *rf) { - if(rom_loaded == false)return; - - rf->read(&sram_data, sram_size); -} - -void bROM::save_sram(Writer *wf) { - if(rom_loaded == false)return; - if(!sram_size)return; - - wf->write(sram_data, sram_size); -} - -void bROM::load_rom(Reader *rf) { -uint16 cksum, icksum, index; -char cart_title[24]; - if(rom_loaded == true)return; - - rf->read(&data); - - size = rf->size(); - if(size < 65536) { - mapper = LOROM; - strcpy(cart_title, ""); + if(rom_size >= 0x410000) { + mapper = EXHIROM; goto end; } - cksum = data[0xffdc] | (data[0xffdd] << 8); - icksum = data[0xffde] | (data[0xffdf] << 8); + if(rom_size < 65536) { + mapper = LOROM; + goto end; + } + + cksum = rom[0xffdc] | (rom[0xffdd] << 8); + icksum = rom[0xffde] | (rom[0xffdf] << 8); if(cksum + icksum == 0xffff) { mapper = HIROM; } else { @@ -149,13 +34,15 @@ char cart_title[24]; } end: - if(size >= 32768) { - memcpy(cart_title, (char*)data + ((mapper == LOROM)?0x7fc0:0xffc0), 21); - } else *cart_title = 0; + switch(mapper) { + case LOROM: index = 0x007fc0;break; + case HIROM: index = 0x00ffc0;break; + case EXHIROM:index = 0x40ffc0;break; + } + memcpy(cart_title, (char*)rom + index, 21); cart_title[21] = 0; - index = (mapper == HIROM)?0x8000:0x0000; - switch(data[index + 0x7fd8] & 7) { + switch(rom[index + 0x18] & 7) { case 0:sram_size = 0; break; case 1:sram_size = 2 * 1024;break; case 2:sram_size = 4 * 1024;break; @@ -166,45 +53,73 @@ end: case 7:sram_size = 128 * 1024;break; } - dprintf("Image Name : \"%s\"", cart_title); - dprintf("Image Type : %s", (mapper == LOROM)?"LoROM":"HiROM"); - dprintf("SRAM Size : %dkb", sram_size / 1024); - dprintf("Reset:%0.4x NMI:%0.4x IRQ:%0.4x BRK[n]:%0.4x COP[n]:%0.4x BRK[e]:%0.4x COP[e]:%0.4x", - data[index + 0x7ffc] | (data[index + 0x7ffd] << 8), //Reset - data[index + 0x7fea] | (data[index + 0x7feb] << 8), //NMI - data[index + 0x7fee] | (data[index + 0x7fef] << 8), //IRQ - data[index + 0x7fe6] | (data[index + 0x7fe7] << 8), //BRK[n] - data[index + 0x7fe4] | (data[index + 0x7fe5] << 8), //COP[n] - data[index + 0x7ffe] | (data[index + 0x7fff] << 8), //BRK[e] - data[index + 0x7ff4] | (data[index + 0x7ff5] << 8) //COP[e] + dprintf("* Image Name : \"%s\"", cart_title); + dprintf("* MAD : %0.2x", mapper); + dprintf("* SRAM Size : %dkb", sram_size / 1024); + dprintf("* Reset:%0.4x NMI:%0.4x IRQ:%0.4x BRK[n]:%0.4x COP[n]:%0.4x BRK[e]:%0.4x COP[e]:%0.4x", + rom[index + 0x3c] | (rom[index + 0x3d] << 8), //Reset + rom[index + 0x2a] | (rom[index + 0x2b] << 8), //NMI + rom[index + 0x2e] | (rom[index + 0x2f] << 8), //IRQ + rom[index + 0x26] | (rom[index + 0x27] << 8), //BRK[n] + rom[index + 0x24] | (rom[index + 0x25] << 8), //COP[n] + rom[index + 0x3e] | (rom[index + 0x3f] << 8), //BRK[e] + rom[index + 0x34] | (rom[index + 0x35] << 8) //COP[e] ); dprintf(""); +CartInfo ci; + ci.rom = rom; + ci.sram = sram; + ci.rom_size = rom_size; + ci.sram_size = sram_size; + + switch(mapper) { + case LOROM: cart = new bCartLoROM(); break; + case HIROM: cart = new bCartHiROM(); break; + case EXHIROM:cart = new bCartExHiROM();break; + default:return false; + } + + cart->set_cartinfo(&ci); rom_loaded = true; + return true; } -void bROM::unload() { +bool bMemBus::load_sram(Reader *rf) { + if(rom_loaded == false || sram_size == 0)return false; + rf->read(&sram, sram_size); + +CartInfo ci; + ci.rom = rom; + ci.sram = sram; + ci.rom_size = rom_size; + ci.sram_size = sram_size; + cart->set_cartinfo(&ci); + + return true; +} + +bool bMemBus::save_sram(Writer *wf) { + if(rom_loaded == false || sram_size == 0)return false; + wf->write(sram, sram_size); + return true; +} + +void bMemBus::unload_cart() { if(rom_loaded == false)return; - if(data)memfree(data, "bROM::data"); - if(sram_data)memfree(sram_data, "bROM::sram_data"); + if(rom) free(rom); + if(sram)free(sram); + delete(cart); rom_loaded = false; } -void bROM::write_protect(bool yn) { - write_protection = yn; -} - -bROM::bROM() { - sram_size = 0; - sram_data = 0; - write_protection = true; - - rom_loaded = false; -} - -bROM::~bROM() { +void bMemBus::get_cartinfo(CartInfo *ci) { + ci->rom = rom; + ci->sram = sram; + ci->rom_size = rom_size; + ci->sram_size = sram_size; } /*********************** @@ -235,10 +150,10 @@ uint32 b, w, r; } else if(w <= 0x5fff) { r = mmio[w - 0x2000]->read(w); } else { - r = rom->read(addr); + r = cart->read(addr); } } else if(b <= 0x7d) { - r = rom->read(addr); + r = cart->read(addr); } else if(b <= 0x7f) { r = wram[addr & 0x01ffff]; } else if(b <= 0xbf) { @@ -247,10 +162,10 @@ uint32 b, w, r; } else if(w <= 0x5fff) { r = mmio[w - 0x2000]->read(w); } else { - r = rom->read(addr); + r = cart->read(addr); } } else { - r = rom->read(addr); + r = cart->read(addr); } snes->notify(SNES::MEM_READ, addr, r); @@ -269,10 +184,10 @@ uint32 b, w; } else if(w <= 0x5fff) { mmio[w - 0x2000]->write(w, value); } else { - rom->write(addr, value); + cart->write(addr, value); } } else if(b <= 0x7d) { - rom->write(addr, value); + cart->write(addr, value); } else if(b <= 0x7f) { wram[addr & 0x01ffff] = value; } else if(b <= 0xbf) { @@ -281,10 +196,10 @@ uint32 b, w; } else if(w <= 0x5fff) { mmio[w - 0x2000]->write(w, value); } else { - rom->write(addr, value); + cart->write(addr, value); } } else { - rom->write(addr, value); + cart->write(addr, value); } snes->notify(SNES::MEM_WRITE, addr, value); @@ -300,14 +215,11 @@ void bMemBus::reset() { } bMemBus::bMemBus() { - rom = new bROM(); - - wram = (byte*)memalloc(0x020000, "bMemBus::wram"); + wram = (byte*)malloc(0x020000); memset(wram, 0, 0x020000); + rom_loaded = false; } bMemBus::~bMemBus() { - delete(rom); - - if(wram)memfree(wram, "bMemBus::wram"); + if(wram)free(wram); } diff --git a/src/memory/bmemory/bmemory.h b/src/memory/bmemory/bmemory.h index fc89a116..ae9831f9 100644 --- a/src/memory/bmemory/bmemory.h +++ b/src/memory/bmemory/bmemory.h @@ -1,31 +1,24 @@ -class bROM : public ROM { -private: -bool write_protection; -bool rom_loaded; - -public: -enum { LOROM = 0, HIROM = 1 }; -uint8 *data, *sram_data; -uint8 mapper; -uint32 size, sram_size; - void load_rom(Reader *rf); - void load_sram(Reader *rf); - void save_sram(Writer *wf); - void unload(); - uint8 read (uint32 addr); - void write(uint32 addr, byte value); - void write_protect(bool yn); - - bROM(); - ~bROM(); -}; +#include "bcart_lorom.h" +#include "bcart_hirom.h" +#include "bcart_exhirom.h" class bMemBus : public MemBus { public: -byte *wram; +uint8 *rom, *sram, *wram; +uint32 rom_size, sram_size; + +bool rom_loaded; +enum { LOROM = 0x20, HIROM = 0x21, EXHIROM = 0x25 }; + uint8 read (uint32 addr); void write(uint32 addr, byte value); + bool load_cart(Reader *rf); + bool load_sram(Reader *rf); + bool save_sram(Writer *wf); + void unload_cart(); + void get_cartinfo(CartInfo *ci); + void power(); void reset(); diff --git a/src/memory/memory.h b/src/memory/memory.h index 48bed7d6..9c7a10b5 100644 --- a/src/memory/memory.h +++ b/src/memory/memory.h @@ -9,13 +9,15 @@ enum { WRAP_NONE = 0, WRAP_BANK = 1, WRAP_PAGE = 2 }; virtual void write_long(uint32 addr, uint32 value, uint8 wrap = WRAP_NONE); }; -class ROM : public Memory { +typedef struct { +uint8 *rom, *sram; +uint32 rom_size, sram_size; +}CartInfo; + +class Cart : public Memory { public: - virtual void load_rom(Reader *rf) = 0; - virtual void load_sram(Reader *rf) = 0; - virtual void save_sram(Writer *wf) = 0; - virtual void unload() = 0; - virtual void write_protect(bool yn) = 0; + virtual void write_protect(bool r) = 0; + virtual void set_cartinfo(CartInfo *ci) = 0; }; class MMIO : public Memory { @@ -26,13 +28,19 @@ public: class MemBus : public Memory { public: -ROM *rom; +Cart *cart; MMIO *mmio[0x4000]; bool fastROM; virtual void flush_mmio_mappers(); virtual bool set_mmio_mapper(uint16 addr, MMIO *mapper); virtual uint8 speed(uint32 addr); + virtual bool load_cart(Reader *rf) = 0; + virtual bool load_sram(Reader *rf) = 0; + virtual bool save_sram(Writer *wf) = 0; + virtual void unload_cart() = 0; + virtual void get_cartinfo(CartInfo *ci) = 0; + virtual void power() = 0; virtual void reset() = 0; diff --git a/src/ppu/bppu/bppu.cpp b/src/ppu/bppu/bppu.cpp index 1e61bbf9..44868895 100644 --- a/src/ppu/bppu/bppu.cpp +++ b/src/ppu/bppu/bppu.cpp @@ -1,21 +1,39 @@ #include "../../base.h" #include "bppu_mmio.cpp" - -#ifdef _BPPU_OLDRENDER -#include "bppu_old_render.cpp" -#else #include "bppu_render.cpp" -#endif void bPPU::run() {} void bPPU::scanline() { - _y = clock->vcounter(); + _y = cpu->vcounter(); _screen_width = (regs.bg_mode == 5 || regs.bg_mode == 6)?512:256; - _interlace = clock->interlace(); - _interlace_field = clock->interlace_field(); + _interlace = cpu->interlace(); + _interlace_field = cpu->interlace_field(); - if(_y > 0 && _y < clock->visible_scanlines()) { + if(_y == 0) { + //RTO flag reset + regs.time_over = false; + regs.range_over = false; + } + + if(_y == 1) { + //OAM FirstSprite priority set + if(regs.oam_priority == true) { + regs.oam_firstsprite = (regs.oam_addr & 0xfe) >> 1; + } else { + regs.oam_firstsprite = 0; + } + } + + if(_y == (cpu->overscan()?239:224) && regs.display_disabled == false) { + //OAM address reset + regs.oam_addr = ((regs.oam_addrh << 8) | regs.oam_addrl) << 1; + } + +//only allow frameskip setting to ignore actual rendering; not RTO, etc. + if(settings.frameskip_pos != 0)return; + + if(_y > 0 && _y < (cpu->overscan()?239:224)) { if(regs.bg_mode == 5 || regs.bg_mode == 6) { output->hires = true; output->line[_y].hires = true; @@ -29,6 +47,16 @@ void bPPU::scanline() { } void bPPU::frame() { + if(settings.frameskip_changed == true) { + settings.frameskip_changed = false; + settings.frameskip_pos = 0; + } else { + settings.frameskip_pos++; + settings.frameskip_pos %= (settings.frameskip + 1); + } + + if(settings.frameskip_pos != 0)return; + snes->notify(SNES::RENDER_FRAME); output->hires = false; output->interlace = false; @@ -38,6 +66,11 @@ void bPPU::frame() { } } +void bPPU::set_frameskip(int fs) { + settings.frameskip = fs; + settings.frameskip_changed = true; +} + void bPPU::power() { memset(vram, 0, 65536); memset(oam, 0, 544); @@ -49,6 +82,8 @@ void bPPU::reset() { memset(output->buffer, 0, 512 * 478 * 2); frame(); + memset(sprite_list, 0, sizeof(sprite_list)); + //$2100 regs.display_disabled = 0; regs.display_brightness = 0; @@ -59,10 +94,12 @@ void bPPU::reset() { regs.oam_tdaddr = 0x0000; //$2102-$2103 - regs.oam_addrl = 0x00; - regs.oam_addrh = 0x00; - regs.oam_addr = 0x0000; - regs.oam_latchdata = 0x00; + regs.oam_addrl = 0x00; + regs.oam_addrh = 0x00; + regs.oam_addr = 0x0000; + regs.oam_latchdata = 0x00; + regs.oam_priority = false; + regs.oam_firstsprite = 0x00; //$2105 regs.bg_tilesize[BG1] = 0; @@ -226,6 +263,11 @@ void bPPU::reset() { //$2139-$213a regs.vram_readbuffer = 0x0000; +//$213e + regs.time_over = false; + regs.range_over = false; + + update_sprite_list_sizes(); clear_tiledata_cache(); } @@ -252,6 +294,7 @@ uint8 r; void bPPU::oam_write(uint16 addr, uint8 value) { if(addr >= 0x0200)addr = 0x0200 | (addr & 31); oam[addr] = value; + update_sprite_list(addr); snes->notify(SNES::OAM_WRITE, addr, value); } @@ -268,6 +311,10 @@ void bPPU::cgram_write(uint16 addr, uint8 value) { } bPPU::bPPU() { + settings.frameskip = 0; + settings.frameskip_pos = 0; + settings.frameskip_changed = false; + mmio = new bPPUMMIO(this); vram = (uint8*)memalloc(65536, "bPPU::vram"); @@ -301,9 +348,9 @@ uint16 *ptr; if(l == 0) { r = g = b = 0; } else if(l == 15); else { - r = (double)r * m; - g = (double)g * m; - b = (double)b * m; + r = (uint8)((double)r * m); + g = (uint8)((double)g * m); + b = (uint8)((double)b * m); } *ptr++ = (r) | (g << 5) | (b << 10); } diff --git a/src/ppu/bppu/bppu.h b/src/ppu/bppu/bppu.h index f89d7493..6a30848b 100644 --- a/src/ppu/bppu/bppu.h +++ b/src/ppu/bppu/bppu.h @@ -1,5 +1,3 @@ -//#define _BPPU_OLDRENDER - class bPPU; class bPPUMMIO : public MMIO { @@ -17,6 +15,21 @@ uint8 *vram, *oam, *cgram; enum { BG1 = 0, BG2 = 1, BG3 = 2, BG4 = 3, OAM = 4, BACK = 5 }; enum { SC_32x32 = 0, SC_32x64 = 1, SC_64x32 = 2, SC_64x64 = 3 }; +struct sprite_item { + uint8 width, height; + uint16 x, y; + uint8 character; + bool use_nameselect; + bool vflip, hflip; + uint8 palette; + uint8 priority; +}sprite_list[128]; + +struct { + int32 frameskip, frameskip_pos; + bool frameskip_changed; +}settings; + struct { //$2100 bool display_disabled; @@ -31,6 +44,8 @@ struct { uint8 oam_addrl, oam_addrh; uint16 oam_addr; uint8 oam_latchdata; + bool oam_priority; + uint8 oam_firstsprite; //$2105 bool bg_tilesize[4]; @@ -118,6 +133,10 @@ struct { //$2139-$213a uint16 vram_readbuffer; + +//$213e + bool time_over, range_over; + uint16 oam_itemcount, oam_tilecount; }regs; uint8 vram_read (uint16 addr); void vram_write (uint16 addr, uint8 value); @@ -126,6 +145,9 @@ struct { uint8 cgram_read (uint16 addr); void cgram_write(uint16 addr, uint8 value); + void get_sprite_size(int i, bool size); + void update_sprite_list(uint16 addr); + void update_sprite_list_sizes(); uint16 get_vram_address(); void mmio_w2100(uint8 value); //INIDISP @@ -197,22 +219,20 @@ struct { /* PPU render functions */ -#ifdef _BPPU_OLDRENDER -#include "bppu_old_render.h" -#else #include "bppu_render.h" -#endif uint16 *light_table; uint16 *mosaic_table[16]; void render_line(); + void update_oam_status(); /* Required functions */ void run(); void scanline(); void frame(); void power(); void reset(); + void set_frameskip(int fs); bPPU(); ~bPPU(); diff --git a/src/ppu/bppu/bppu_mmio.cpp b/src/ppu/bppu/bppu_mmio.cpp index 6b58b0ce..2f81b8ea 100644 --- a/src/ppu/bppu/bppu_mmio.cpp +++ b/src/ppu/bppu/bppu_mmio.cpp @@ -1,6 +1,6 @@ void bPPU::latch_counters() { - regs.hcounter = clock->hcounter(); - regs.vcounter = clock->vcounter(); + regs.hcounter = cpu->hcounter(); + regs.vcounter = cpu->vcounter(); regs.counters_latched = true; } @@ -27,6 +27,7 @@ void bPPU::mmio_w2101(uint8 value) { regs.oam_basesize = (value >> 5) & 7; regs.oam_nameselect = (value >> 3) & 3; regs.oam_tdaddr = (value & 3) << 14; + update_sprite_list_sizes(); } //OAMADDL @@ -37,8 +38,9 @@ void bPPU::mmio_w2102(uint8 value) { //OAMADDH void bPPU::mmio_w2103(uint8 value) { - regs.oam_addrh = value & 1; - regs.oam_addr = ((regs.oam_addrh << 8) | regs.oam_addrl) << 1; + regs.oam_priority = !!(value & 0x80); + regs.oam_addrh = value & 1; + regs.oam_addr = ((regs.oam_addrh << 8) | regs.oam_addrl) << 1; } //OAMDATA @@ -168,11 +170,17 @@ void bPPU::mmio_w2115(uint8 value) { //VMADDL void bPPU::mmio_w2116(uint8 value) { regs.vram_addr = (regs.vram_addr & 0xff00) | value; +uint16 addr = get_vram_address(); + regs.vram_readbuffer = vram_read(addr); + regs.vram_readbuffer |= vram_read(addr + 1) << 8; } //VMADDH void bPPU::mmio_w2117(uint8 value) { regs.vram_addr = (value << 8) | (regs.vram_addr & 0x00ff); +uint16 addr = get_vram_address(); + regs.vram_readbuffer = vram_read(addr); + regs.vram_readbuffer |= vram_read(addr + 1) << 8; } //VMDATAL @@ -388,8 +396,8 @@ void bPPU::mmio_w2133(uint8 value) { regs.oam_halve = !!(value & 0x02); regs.interlace = !!(value & 0x01); - clock->enable_overscan(regs.overscan); - clock->enable_interlace(regs.interlace); + cpu->set_overscan(regs.overscan); + cpu->set_interlace(regs.interlace); } //MPYL @@ -487,6 +495,8 @@ uint16 r = regs.vcounter; //STAT77 uint8 bPPU::mmio_r213e() { uint8 r = 0x00; + r |= (regs.time_over) ?0x80:0x00; + r |= (regs.range_over)?0x40:0x00; r |= 0x01; //PPU1 version number return r; } @@ -497,7 +507,7 @@ uint8 r = 0x00; regs.latch_hcounter = 0; regs.latch_vcounter = 0; - r |= clock->interlace_field() << 7; + r |= cpu->interlace_field() << 7; if(!(cpu->pio_status() & 0x80)) { r |= 1 << 6; } else if(regs.counters_latched == true) { @@ -510,7 +520,7 @@ uint8 r = 0x00; } uint8 bPPUMMIO::read(uint32 addr) { - clock->sync(); +//cpu->sync(); switch(addr) { case 0x2134:return ppu->mmio_r2134(); //MPYL case 0x2135:return ppu->mmio_r2135(); //MPYM @@ -524,36 +534,12 @@ uint8 bPPUMMIO::read(uint32 addr) { case 0x213d:return ppu->mmio_r213d(); //OPVCT case 0x213e:return ppu->mmio_r213e(); //STAT77 case 0x213f:return ppu->mmio_r213f(); //STAT78 - - case 0x2140:case 0x2141:case 0x2142:case 0x2143: - static uint8 t = 0, counter = 0; - uint8 x, port = (addr & 3); - if(rand() & 1) { - x = rand() & 7; - if(x == 0) { - if(!(port & 1))t = cpu->regs.a; - else t = cpu->regs.a >> 8; - } - else if(x == 1) { - if(!(port & 1))t = cpu->regs.x; - else t = cpu->regs.x >> 8; - } - else if(x == 2) { - if(!(port & 1))t = cpu->regs.y; - else t = cpu->regs.y >> 8; - } - else if(x == 3)t = 0xaa; - else if(x == 4)t = 0xbb; - else if(x == 5)t = 0xcc; - else { t = counter++; } - } - return t; } return 0x00; } void bPPUMMIO::write(uint32 addr, uint8 value) { - clock->sync(); +//cpu->sync(); switch(addr) { case 0x2100:ppu->mmio_w2100(value);return; //INIDISP case 0x2101:ppu->mmio_w2101(value);return; //OBSEL diff --git a/src/ppu/bppu/bppu_old_render.cpp b/src/ppu/bppu/bppu_old_render.cpp deleted file mode 100644 index 9bdc3cf6..00000000 --- a/src/ppu/bppu/bppu_old_render.cpp +++ /dev/null @@ -1,133 +0,0 @@ -#include "bppu_old_render_cache.cpp" -#include "bppu_old_render_windows.cpp" -#include "bppu_old_render_main.cpp" -#include "bppu_old_render_mode7.cpp" - -namespace bPPURenderTables { -enum { BG1 = 0, BG2 = 1, BG3 = 2, BG4 = 3, OAM = 4, BACK = 5 }; - uint8 lookup_mode0[12] = { - BG4, BG3, OAM, BG4, BG3, OAM, BG2, BG1, OAM, BG2, BG1, OAM - }; - uint8 lookup_mode1_pri0[10] = { - BG3, OAM, BG3, OAM, BG2, BG1, OAM, BG2, BG1, OAM - }; - uint8 lookup_mode1_pri1[10] = { - BG3, OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM, BG3 - }; - uint8 lookup_mode2[8] = { - OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM - }; - uint8 lookup_mode3[8] = { - OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM - }; - uint8 lookup_mode4[8] = { - OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM - }; - uint8 lookup_mode5[8] = { - OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM - }; - uint8 lookup_mode6[6] = { - OAM, OAM, BG1, OAM, BG1, OAM - }; - uint8 lookup_mode7[5] = { - OAM, BG1, OAM, OAM, OAM - }; - uint8 lookup_mode7_extbg[6] = { - BG2, OAM, OAM, BG2, OAM, OAM - }; -}; - -void bPPU::render_line_mode0() { - render_line_bg (7, 10, COLORDEPTH_4, BG1); - render_line_bg (6, 9, COLORDEPTH_4, BG2); - render_line_bg (1, 4, COLORDEPTH_4, BG3); - render_line_bg (0, 3, COLORDEPTH_4, BG4); - render_line_oam(2, 5, 8, 11); - set_layer_pixels(12, bPPURenderTables::lookup_mode0); -} - -void bPPU::render_line_mode1() { - switch(regs.bg3_priority) { - case 0: - render_line_bg (5, 8, COLORDEPTH_16, BG1); - render_line_bg (4, 7, COLORDEPTH_16, BG2); - render_line_bg (0, 2, COLORDEPTH_4, BG3); - render_line_oam(1, 3, 6, 9); - set_layer_pixels(10, bPPURenderTables::lookup_mode1_pri0); - break; - case 1: - render_line_bg (4, 7, COLORDEPTH_16, BG1); - render_line_bg (3, 6, COLORDEPTH_16, BG2); - render_line_bg (0, 9, COLORDEPTH_4, BG3); - render_line_oam(1, 2, 5, 8); - set_layer_pixels(10, bPPURenderTables::lookup_mode1_pri1); - break; - } -} - -void bPPU::render_line_mode2() { - render_line_bg (3, 6, COLORDEPTH_16, BG1); - render_line_bg (2, 5, COLORDEPTH_16, BG2); - render_line_oam(0, 1, 4, 7); - set_layer_pixels(8, bPPURenderTables::lookup_mode2); -} - -void bPPU::render_line_mode3() { - render_line_bg (3, 6, COLORDEPTH_256, BG1); - render_line_bg (2, 5, COLORDEPTH_16, BG2); - render_line_oam(0, 1, 4, 7); - set_layer_pixels(8, bPPURenderTables::lookup_mode3); -} - -void bPPU::render_line_mode4() { - render_line_bg (3, 6, COLORDEPTH_256, BG1); - render_line_bg (2, 5, COLORDEPTH_4, BG2); - render_line_oam(0, 1, 4, 7); - set_layer_pixels(8, bPPURenderTables::lookup_mode4); -} - -void bPPU::render_line_mode5() { - render_line_bg (3, 6, COLORDEPTH_16, BG1); - render_line_bg (2, 5, COLORDEPTH_4, BG2); - render_line_oam(0, 1, 4, 7); - set_layer_pixels(8, bPPURenderTables::lookup_mode5); -} - -void bPPU::render_line_mode6() { - render_line_bg (2, 4, COLORDEPTH_16, BG1); - render_line_oam(0, 1, 3, 5); - set_layer_pixels(8, bPPURenderTables::lookup_mode6); -} - -void bPPU::render_line_mode7() { - if(regs.mode7_extbg == false) { - render_line_m7 (1, 0, 0); //bg2 priorities are ignored - render_line_oam(0, 2, 3, 4); - set_layer_pixels(5, bPPURenderTables::lookup_mode7); - } else { - render_line_m7 (0, 0, 3); //bg1 priority is ignored - render_line_oam(1, 2, 4, 5); - set_layer_pixels(6, bPPURenderTables::lookup_mode7_extbg); - } -} - -void bPPU::render_line() { - if(regs.display_disabled == true) { - memset(output->buffer + (_y << 1) * 512, 0, 2048); - return; - } - - clear_layer_cache(); - clear_pixel_cache(); - 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_to_output(); -} diff --git a/src/ppu/bppu/bppu_old_render.h b/src/ppu/bppu/bppu_old_render.h deleted file mode 100644 index 128b54ec..00000000 --- a/src/ppu/bppu/bppu_old_render.h +++ /dev/null @@ -1,70 +0,0 @@ -//bppu_render.cpp -void render_line_mode0(); -void render_line_mode1(); -void render_line_mode2(); -void render_line_mode3(); -void render_line_mode4(); -void render_line_mode5(); -void render_line_mode6(); -void render_line_mode7(); - -//bppu_render_cache.cpp -enum { BLENDTYPE_BACK = 0, BLENDTYPE_MAIN = 1, BLENDTYPE_SUB = 2, BLENDTYPE_COMBINE = 3 }; -enum { COLORDEPTH_4 = 0, COLORDEPTH_16 = 1, COLORDEPTH_256 = 2 }; -enum { TILE_2BIT = 0, TILE_4BIT = 1, TILE_8BIT = 2 }; - -struct { - uint8 color_main, color_sub; - uint8 src_main, src_sub; - uint8 blend_type; -}pixel_cache[512]; -uint8 layer_cache[512 * 12]; - -uint8 *bg_tiledata[3]; -uint8 *bg_tiledata_state[3]; - -void clear_pixel_cache(void); -void clear_layer_cache(void); -void init_tiledata_cache(void); -void clear_tiledata_cache(void); - -//bppu_render_windows.cpp -enum { WINDOWMASK_OR = 0, WINDOWMASK_AND = 1, WINDOWMASK_XOR = 2, WINDOWMASK_XNOR = 3 }; - -bool windows_not_obstructing(uint8 layer, uint8 bg, uint16 x); -bool color_windows_not_obstructing(uint16 x, uint8 color_mask_type); - -//bppu_render_main.cpp -enum { - SH_2 = 1, SH_4 = 2, SH_8 = 3, SH_16 = 4, - SH_32 = 5, SH_64 = 6, SH_128 = 7, SH_256 = 8, - SH_512 = 9, SH_1024 = 10, SH_2048 = 11, SH_4096 = 12 -}; -enum { COLORMODE_ADD = 0, COLORMODE_SUB = 1 }; -enum { PPU_MAIN = 0, PPU_SUB = 1 }; -enum { OAM_PRI_NONE = 4 }; -uint8 oam_line_pal[512], oam_line_pri[512]; - -struct { - byte num; - byte width, height; - word x, y; - word character; - byte v_flip, h_flip; - byte palette; - byte priority; -}current_sprite; - -void render_line_to_output(); -inline uint16 addsub_pixels(uint8 x, uint8 cdest_index, uint8 cdest_bg, uint8 csrc_index, uint8 csrc_bg); -inline uint16 addsub_pixel(uint8 x, uint8 cdest_index, uint8 cdest_bg); -void render_bg_tile(uint8 color_depth, uint8 bg, uint16 tile_num); -void set_pixel(uint8 bg, uint16 x, uint8 pal_index); -void set_layer_pixels(uint8 layer_count, uint8 *layer_bg_lookup); -void set_sprite_attributes(uint8 sprite_num); -void render_oam_sprite(void); -void render_line_oam(uint8 layer_pos_pri0, uint8 layer_pos_pri1, uint8 layer_pos_pri2, uint8 layer_pos_pri3); -void render_line_bg(uint8 layer_pos_pri0, uint8 layer_pos_pri1, uint8 color_depth, uint8 bg); - -//bppu_render_mode7.cpp -void render_line_m7(uint8 layer_pos_bg1, uint8 layer_pos_bg2_pri0, uint8 layer_pos_bg2_pri1); diff --git a/src/ppu/bppu/bppu_old_render_cache.cpp b/src/ppu/bppu/bppu_old_render_cache.cpp deleted file mode 100644 index 508aed97..00000000 --- a/src/ppu/bppu/bppu_old_render_cache.cpp +++ /dev/null @@ -1,33 +0,0 @@ -//this should be reset once every scanline -void bPPU::clear_pixel_cache(void) { - for(int i=0;i<512;i++) { - pixel_cache[i].color_main = 0; - pixel_cache[i].color_sub = 0; - pixel_cache[i].src_main = BACK; - pixel_cache[i].src_sub = BACK; - pixel_cache[i].blend_type = BLENDTYPE_BACK; - } -} - -//this should be reset once every scanline -void bPPU::clear_layer_cache(void) { - memset(&layer_cache, 0, 512 * 12); -} - -void bPPU::init_tiledata_cache(void) { - bg_tiledata[TILE_2BIT] = (uint8*)malloc(262144); - bg_tiledata[TILE_4BIT] = (uint8*)malloc(131072); - bg_tiledata[TILE_8BIT] = (uint8*)malloc( 65536); - bg_tiledata_state[TILE_2BIT] = (uint8*)malloc( 4096); - bg_tiledata_state[TILE_4BIT] = (uint8*)malloc( 2048); - bg_tiledata_state[TILE_8BIT] = (uint8*)malloc( 1024); -} - -void bPPU::clear_tiledata_cache(void) { - memset(bg_tiledata[TILE_2BIT], 0, 262144); - memset(bg_tiledata[TILE_4BIT], 0, 131072); - memset(bg_tiledata[TILE_4BIT], 0, 65536); - memset(bg_tiledata_state[TILE_2BIT], 0, 4096); - memset(bg_tiledata_state[TILE_4BIT], 0, 2048); - memset(bg_tiledata_state[TILE_8BIT], 0, 1024); -} diff --git a/src/ppu/bppu/bppu_old_render_main.cpp b/src/ppu/bppu/bppu_old_render_main.cpp deleted file mode 100644 index e7ae5c4a..00000000 --- a/src/ppu/bppu/bppu_old_render_main.cpp +++ /dev/null @@ -1,696 +0,0 @@ -#define set_layer_pixel(__x, __c) layer_cache[(__x) * 12 + layer_pos] = __c -#define pal_pixel(__i) (*((uint16*)cgram + __i)) - -namespace bPPUAddSubTables { - uint8 adjust_buffer_full[96] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 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 - }; - uint8 adjust_buffer_half[96] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 - }; -}; - -inline uint16 bPPU::addsub_pixels(uint8 x, uint8 cdest_index, uint8 cdest_bg, uint8 csrc_index, uint8 csrc_bg) { -int r, g, b; -uint16 cdest = pal_pixel(cdest_index); -uint16 csrc = pal_pixel(csrc_index); -uint16 res; -//oam palettes 0-3 are not affected by color add/sub - if(cdest_bg == OAM) { - if(cdest_index < 192) { - return cdest; - } - } - switch(regs.color_mode) { - case COLORMODE_ADD: - if(regs.bg_color_enabled[cdest_bg] == true && regs.color_halve == true) { - r = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1; - g = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )) >> 1; - b = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )) >> 1; - } else { - r = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )); - g = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )); - b = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )); - } - break; - case COLORMODE_SUB: - if(regs.bg_color_enabled[cdest_bg] == true && regs.color_halve == true) { - r = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1; - g = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )) >> 1; - b = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )) >> 1; - } else { - r = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest ) & 31) - ((csrc ) & 31) )); - g = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest >> 5) & 31) - ((csrc >> 5) & 31) )); - b = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest >> 10) & 31) - ((csrc >> 10) & 31) )); - } - break; - } - return ((r) | (g << 5) | (b << 10)); -} - -inline uint16 bPPU::addsub_pixel(uint8 x, uint8 cdest_index, uint8 cdest_bg) { -int r, g, b; -uint16 cdest = pal_pixel(cdest_index); -uint16 csrc = (regs.color_r) | (regs.color_g << 5) | (regs.color_b << 10); -uint16 res; -//only oam palettes 4-7 are affected by color add/sub - if(cdest_bg == OAM) { - if(cdest_index < 192) { - return cdest; - } - } - switch(regs.color_mode) { - case COLORMODE_ADD: - if(regs.bg_color_enabled[cdest_bg] == true && regs.color_halve == true && regs.addsub_mode == 0) { - r = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1; - g = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )) >> 1; - b = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )) >> 1; - } else { - r = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )); - g = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )); - b = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )); - } - break; - case COLORMODE_SUB: - if(regs.bg_color_enabled[cdest_bg] == true && regs.color_halve == true && regs.addsub_mode == 0) { - r = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1; - g = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )) >> 1; - b = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )) >> 1; - } else { - r = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest ) & 31) - ((csrc ) & 31) )); - g = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest >> 5) & 31) - ((csrc >> 5) & 31) )); - b = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest >> 10) & 31) - ((csrc >> 10) & 31) )); - } - break; - } - return ((r) | (g << 5) | (b << 10)); -} - -#define render_bg_tile_line_4(__m) \ - col = 0; \ - if(d0 & __m)col += 1; \ - if(d1 & __m)col += 2; \ - *dest++ = col -#define render_bg_tile_line_16(__m) \ - col = 0; \ - if(d0 & __m)col += 1; \ - if(d1 & __m)col += 2; \ - if(d2 & __m)col += 4; \ - if(d3 & __m)col += 8; \ - *dest++ = col -#define render_bg_tile_line_256(__m) \ - col = 0; \ - if(d0 & __m)col += 1; \ - if(d1 & __m)col += 2; \ - if(d2 & __m)col += 4; \ - if(d3 & __m)col += 8; \ - if(d4 & __m)col += 16; \ - if(d5 & __m)col += 32; \ - if(d6 & __m)col += 64; \ - if(d7 & __m)col += 128; \ - *dest++ = col - -void bPPU::render_bg_tile(uint8 color_depth, uint8 bg, uint16 tile_num) { -uint8 mask, d0, d1, d2, d3, d4, d5, d6, d7, col; -int x, y; -uint32 pos; -uint8 *dest; - switch(color_depth) { - case COLORDEPTH_4: - dest = (uint8*)bg_tiledata[TILE_2BIT] + tile_num * 64; - pos = tile_num * 16; - y = 8; - while(y--) { - d0 = vram[pos ]; - d1 = vram[pos + 1]; - render_bg_tile_line_4(0x80); - render_bg_tile_line_4(0x40); - render_bg_tile_line_4(0x20); - render_bg_tile_line_4(0x10); - render_bg_tile_line_4(0x08); - render_bg_tile_line_4(0x04); - render_bg_tile_line_4(0x02); - render_bg_tile_line_4(0x01); - pos += 2; - } - bg_tiledata_state[TILE_2BIT][tile_num] = 0; - break; - case COLORDEPTH_16: - dest = (uint8*)bg_tiledata[TILE_4BIT] + tile_num * 64; - pos = tile_num * 32; - y = 8; - while(y--) { - d0 = vram[pos ]; - d1 = vram[pos + 1]; - d2 = vram[pos + 16]; - d3 = vram[pos + 17]; - render_bg_tile_line_16(0x80); - render_bg_tile_line_16(0x40); - render_bg_tile_line_16(0x20); - render_bg_tile_line_16(0x10); - render_bg_tile_line_16(0x08); - render_bg_tile_line_16(0x04); - render_bg_tile_line_16(0x02); - render_bg_tile_line_16(0x01); - pos += 2; - } - bg_tiledata_state[TILE_4BIT][tile_num] = 0; - break; - case COLORDEPTH_256: - dest = (uint8*)bg_tiledata[TILE_8BIT] + tile_num * 64; - pos = tile_num * 64; - 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_256(0x80); - render_bg_tile_line_256(0x40); - render_bg_tile_line_256(0x20); - render_bg_tile_line_256(0x10); - render_bg_tile_line_256(0x08); - render_bg_tile_line_256(0x04); - render_bg_tile_line_256(0x02); - render_bg_tile_line_256(0x01); - pos += 2; - } - bg_tiledata_state[TILE_8BIT][tile_num] = 0; - break; - } -} - -void bPPU::render_line_to_output() { -int x, x1; -uint16 *ptr, *ltable; -uint16 c, cx, cy; -uint16 screen_width; -uint16 v, vline_pos = clock->vcounter(); - v = vline_pos; - screen_width = (output->line[v].hires)?512:256; - - if(output->line[v].interlace == false) { - ptr = (uint16*)output->buffer + ((vline_pos << 1)) * 512; - } else { - ptr = (uint16*)output->buffer + ((vline_pos << 1) + clock->interlace_field()) * 512; - } - ltable = (uint16*)light_table + (regs.display_brightness * 65536); - - for(x=x1=0;x= 192)) { - if(regs.bg_color_enabled[pixel_cache[x].src_main] == true) { - pixel_cache[x].blend_type = BLENDTYPE_COMBINE; - } - } - } - } -} - -void bPPU::set_layer_pixels(uint8 layer_count, uint8 *layer_bg_lookup) { -int layer, x = 0, x1; -uint8 pal; -uint16 width = (regs.bg_mode == 5 || regs.bg_mode == 6)?512:256; - do { - layer = 0; - x1 = x * 12; - do { - pal = layer_cache[x1 + layer]; - if(pal) { - set_pixel(layer_bg_lookup[layer], x, pal); - } - layer++; - } while(layer < layer_count); - x++; - } while(x < width); -} - -void bPPU::set_sprite_attributes(uint8 sprite_num) { -uint32 t; -uint8 size, b; -uint16 x; - t = *((uint32*)oam + sprite_num); - b = oam[512 + (sprite_num >> 2)]; - - switch(sprite_num & 3) { - case 0: size = !!(b & 0x02); x = (b & 0x01)?0x100:0; break; - case 1: size = !!(b & 0x08); x = (b & 0x04)?0x100:0; break; - case 2: size = !!(b & 0x20); x = (b & 0x10)?0x100:0; break; - case 3: size = !!(b & 0x80); x = (b & 0x40)?0x100:0; break; - } - - current_sprite.num = sprite_num; - current_sprite.priority = (t >> 28) & 3; - current_sprite.x = x | (t & 0xff); - current_sprite.y = ((t >> 8) + 1) & 0xff; - current_sprite.v_flip = !!(t & 0x80000000); - current_sprite.h_flip = !!(t & 0x40000000); - current_sprite.palette = (t >> 25) & 7; - current_sprite.character = (t >> 16) & 0x01ff; - -//size: 0 = small, 1 = large - switch(regs.oam_basesize) { - case 0: - if(!size) { current_sprite.width = 8; current_sprite.height = 8; } - else { current_sprite.width = 16; current_sprite.height = 16; } - break; - case 1: - if(!size) { current_sprite.width = 8; current_sprite.height = 8; } - else { current_sprite.width = 32; current_sprite.height = 32; } - break; - case 2: - if(!size) { current_sprite.width = 8; current_sprite.height = 8; } - else { current_sprite.width = 64; current_sprite.height = 64; } - break; - case 3: - if(!size) { current_sprite.width = 16; current_sprite.height = 16; } - else { current_sprite.width = 32; current_sprite.height = 32; } - break; - case 4: - if(!size) { current_sprite.width = 16; current_sprite.height = 16; } - else { current_sprite.width = 64; current_sprite.height = 64; } - break; - case 5: - if(!size) { current_sprite.width = 32; current_sprite.height = 32; } - else { current_sprite.width = 64; current_sprite.height = 64; } - break; - case 6: - if(!size) { current_sprite.width = 16; current_sprite.height = 32; } - else { current_sprite.width = 32; current_sprite.height = 64; } - break; - case 7: - if(!size) { current_sprite.width = 16; current_sprite.height = 32; } - else { current_sprite.width = 32; current_sprite.height = 32; } - break; - } -} - -void bPPU::render_oam_sprite(void) { -uint16 pos, col, chr, tiledata_inc; -uint8 d0, d1, d2, d3, pal_index; -int x, y, z, x1, mx, mask, p; -int tile_width; -int vline_pos = clock->vcounter(); -int snes_width = (regs.bg_mode == 5 || regs.bg_mode == 6)?512:256; - if(regs.bg_enabled[OAM] == false && regs.bgsub_enabled[OAM] == false)return; - - tile_width = current_sprite.width >> SH_8; //e.x. 16x16 sprite = 2x2 tiles - - if(clock->interlace() == true && (regs.bg_mode == 5 || regs.bg_mode == 6)) { - y = (vline_pos << SH_2) + clock->interlace_field(); - } else { - y = vline_pos; - } - - x = current_sprite.x; - if(snes_width == 512) { - x <<= SH_2; - } - - if(current_sprite.v_flip) { - y = ((current_sprite.height - 1) - (vline_pos - current_sprite.y)); - } else { - y = (vline_pos - current_sprite.y); - } - y &= 255; - if(regs.oam_halve == true) { - y <<= 1; - y += clock->interlace_field(); - } - - chr = current_sprite.character; - tiledata_inc = (chr & 0x100)?(regs.oam_nameselect << 13):0; - chr += (y >> SH_8) << SH_16; - pal_index = (current_sprite.palette << SH_16); - for(x1=0;x1> z; - } - x &= 511; - if(x < snes_width) { - col = 0; - if(d0 & mask)col += 1; - if(d1 & mask)col += 2; - if(d2 & mask)col += 4; - if(d3 & mask)col += 8; - if(col) { - col += pal_index; - col += 128; - if(oam_line_pri[x] == OAM_PRI_NONE) { - oam_line_pal[x] = col; - oam_line_pri[x] = current_sprite.priority; - } - if(snes_width == 512) { - if(oam_line_pri[x + 1] == OAM_PRI_NONE) { - oam_line_pal[x + 1] = col; - oam_line_pri[x + 1] = current_sprite.priority; - } - } - } - } - x++; - if(snes_width == 512) { - x++; - } - } - } -} - -void bPPU::render_line_oam(uint8 layer_pos_pri0, uint8 layer_pos_pri1, uint8 layer_pos_pri2, uint8 layer_pos_pri3) { -int i, s; -int vline_pos = clock->vcounter(); -int snes_width = (regs.bg_mode == 5 || regs.bg_mode == 6)?512:256; -uint8 layer_pos; - if(regs.bg_enabled[OAM] != true && regs.bgsub_enabled[OAM] != true)return; - - memset(oam_line_pri, OAM_PRI_NONE, 512); - for(s=0;s<128;s++) { - set_sprite_attributes(s); - if(regs.oam_halve == false) { - if(vline_pos >= current_sprite.y && vline_pos < (current_sprite.y + current_sprite.height)) { - render_oam_sprite(); - } else if((current_sprite.y + current_sprite.height) >= 256 && vline_pos < ((current_sprite.y + current_sprite.height) & 255)) { - render_oam_sprite(); - } - } else { - if(vline_pos >= current_sprite.y && vline_pos < (current_sprite.y + (current_sprite.height >> 1))) { - render_oam_sprite(); - } else if((current_sprite.y + current_sprite.height) >= 256 && vline_pos < ((current_sprite.y + (current_sprite.height >> 1)) & 255)) { - render_oam_sprite(); - } - } - } - - for(i=0;ivcounter(); -uint16 t, base_xpos, base_pos, pos, ppos = 0; -uint16 col; -uint8 *src, *bg_td, *bg_td_state, *tile_ptr; -uint8 tiledata_size; -uint8 tile_size, tile_width, tile_height, tile_x; -uint8 mask, pal_index, pal_size; -uint16 tile_num, screen_width, screen_height, screen_width_mask, screen_height_mask, map_index; -uint16 *mtable; -uint8 layer_pos; -uint16 opt_valid_bit, voffset, hoffset, vscroll, hscroll; - if(regs.bg_enabled[bg] == false && regs.bgsub_enabled[bg] == false)return; - - if (bg == BG1)opt_valid_bit = 0x2000; - else if(bg == BG2)opt_valid_bit = 0x4000; - else opt_valid_bit = 0x0000; - - switch(color_depth) { - case COLORDEPTH_4: - pal_size = 4; - tiledata_size = SH_16; - break; - case COLORDEPTH_16: - pal_size = 16; - tiledata_size = SH_32; - break; - case COLORDEPTH_256: - pal_size = 256; - tiledata_size = SH_64; - break; - } - bg_td = (byte*)bg_tiledata[color_depth]; - bg_td_state = (byte*)bg_tiledata_state[color_depth]; - - screen_width = snes_width; - screen_height = snes_width; //this is correct -- ppu tilemap is based around 256x256, etc. - tile_size = (regs.bg_tilesize[bg])?SH_16:SH_8; - tile_width = tile_size; - tile_height = tile_size; - - if(clock->interlace() == true && (regs.bg_mode == 5 || regs.bg_mode == 6)) { - screen_y = (vline_pos << SH_2) + clock->interlace_field(); - } else { - screen_y = vline_pos; - } - -//Modes 5 and 6 seem to force 16-width tiles due to having twice the resolution. -//The tile size attribute in $2105 has no effect on tile width. - if(regs.bg_mode == 5 || regs.bg_mode == 6) { - tile_width = SH_16; - } - - if(tile_size == SH_16) { - screen_width <<= SH_2; - screen_height <<= SH_2; - } - - if(regs.bg_scsize[bg] & 0x01)screen_width <<= SH_2; - if(regs.bg_scsize[bg] & 0x02)screen_height <<= SH_2; - - screen_width_mask = screen_width - 1; - screen_height_mask = screen_height - 1; - - if(snes_width == 512) { - hscroll = (regs.bg_hofs[bg] << SH_2) & screen_width_mask; - } else { - hscroll = regs.bg_hofs[bg] & screen_width_mask; - } - bg_x = hscroll; - - if(snes_width == 512 && clock->interlace() == true) { - vscroll = (regs.bg_vofs[bg] << SH_2) & screen_height_mask; - } else { - vscroll = regs.bg_vofs[bg] & screen_height_mask; - } - bg_y = (screen_y + vscroll) & screen_height_mask; - - if(regs.mosaic_enabled[bg] == true) { - mtable = (uint16*)mosaic_table[regs.mosaic_size]; - } else { - mtable = (uint16*)mosaic_table[0]; - } - mosaic_x = mtable[bg_x]; - mosaic_y = mtable[bg_y]; - - for(screen_x=0;screen_x> SH_16); - } else { - tile_x = (mtable[screen_x + (hscroll & 7)] >> SH_8); - } - hoffset = hscroll; - voffset = vscroll; - if(tile_x != 0) { - tile_x = (tile_x - 1) & 31; - if(regs.bg_mode == 4) { - pos = regs.bg_scaddr[BG3] + (tile_x << SH_2); - t = *((uint16*)vram + (pos >> SH_2)); - if(t & opt_valid_bit) { - if(!(t & 0x8000)) { - hoffset = ((t & 0x1ff8) | (hscroll & 7)) & screen_width_mask; - } else { - voffset = (t & 0x1fff) & screen_height_mask; - } - } - } else { - pos = regs.bg_scaddr[BG3] + (tile_x << SH_2); - t = *((uint16*)vram + (pos >> SH_2)); - if(t & opt_valid_bit) { - hoffset = ((t & 0x1ff8) | (hscroll & 7)) & screen_width_mask; - } - pos = regs.bg_scaddr[BG3] + 64 + (tile_x << SH_2); - t = *((uint16*)vram + (pos >> SH_2)); - if(t & opt_valid_bit) { - voffset = (t & 0x1fff) & screen_height_mask; - } - } - } - mosaic_x = mtable[(screen_x + hoffset) & screen_width_mask ]; - mosaic_y = mtable[(screen_y + voffset) & screen_height_mask]; - } - - switch(regs.bg_scsize[bg]) { - case 0: - map_index = 0; - break; - case 1: - map_index = ((mosaic_x >> tile_size) >> SH_32) << SH_2048; - break; - case 2: - map_index = ((mosaic_y >> tile_size) >> SH_32) << SH_2048; - break; - case 3: - map_index = ((mosaic_x >> tile_size) >> SH_32) << SH_2048 | - ((mosaic_y >> tile_size) >> SH_32) << SH_4096; - break; - } - - base_xpos = ((mosaic_x >> SH_8) & 31); - base_pos = (((mosaic_y >> tile_height) & 31) << SH_32) + ((mosaic_x >> tile_width) & 31); - pos = regs.bg_scaddr[bg] + map_index + (base_pos << SH_2); - t = *((uint16*)vram + (pos >> SH_2)); - mirror_y = (t & 0x8000)?1:0; - mirror_x = (t & 0x4000)?1:0; - - if((t & 0x2000) == 0) { - layer_pos = layer_pos_pri0; - } else { - layer_pos = layer_pos_pri1; - } - - tile_num = t & 0x03ff; - if(tile_width == SH_16) { - if(((mosaic_x & 15) >= 8 && !mirror_x) || - ((mosaic_x & 15) < 8 && mirror_x))tile_num++; - tile_num &= 0x03ff; - } - if(tile_height == SH_16) { - if(((mosaic_y & 15) >= 8 && !mirror_y) || - ((mosaic_y & 15) < 8 && mirror_y))tile_num += 16; - tile_num &= 0x03ff; - } - tile_num += (regs.bg_tdaddr[bg] >> tiledata_size); - - if(bg_td_state[tile_num] == 1) { - render_bg_tile(color_depth, bg, tile_num); - } - - pal_index = ((t >> 10) & 7) * pal_size; - - if(mirror_y) { ypos = (7 - (mosaic_y & 7)); } - else { ypos = ( (mosaic_y & 7)); } - -//loop while we are rendering from the same tile, as there's no need to do all of the above work -//unless we have rendered all of the visible tile, taking mosaic into account. - tile_ptr = (uint8*)bg_td + (tile_num << SH_64) + (ypos << SH_8); - while(1) { - if(mirror_x) { xpos = (7 - (mosaic_x & 7)); } - else { xpos = ( (mosaic_x & 7)); } - col = *(tile_ptr + xpos); - if(col) { - set_layer_pixel(screen_x, col + pal_index); - } - - bg_x++; - bg_x &= screen_width_mask; - mosaic_x = mtable[bg_x]; - - if(base_xpos != ((mosaic_x >> SH_8) & 31))break; - screen_x++; - if(screen_x >= snes_width)break; - } - } -} diff --git a/src/ppu/bppu/bppu_old_render_mode7.cpp b/src/ppu/bppu/bppu_old_render_mode7.cpp deleted file mode 100644 index 823eb555..00000000 --- a/src/ppu/bppu/bppu_old_render_mode7.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#define CLIP_10BIT_SIGNED(x) \ - ((x) & ((1 << 10) - 1)) + (((((x) & (1 << 13)) ^ (1 << 13)) - (1 << 13)) >> 3) - -#define CAST_WORDTOINT(x) \ - (int)(((x & 0x8000)?(x | 0xffff0000):(x & 0x00007fff))) - -void bPPU::render_line_m7(uint8 layer_pos_bg1, uint8 layer_pos_bg2_pri0, uint8 layer_pos_bg2_pri1) { -int x; -int step_m7a, step_m7c, m7a, m7b, m7c, m7d; -int hoffset, voffset; -int centerx, centery; -int xx, yy; -int px, py; -int tx, ty, tile, palette, priority; -uint8 layer_pos; - hoffset = (CAST_WORDTOINT(regs.bg_hofs[BG1]) << 7) >> 7; - voffset = (CAST_WORDTOINT(regs.bg_vofs[BG1]) << 7) >> 7; - - centerx = (CAST_WORDTOINT(regs.m7x) << 7) >> 7; - centery = (CAST_WORDTOINT(regs.m7y) << 7) >> 7; - - if(regs.mode7_vflip == true) { - yy = 223 - clock->vcounter(); - } else { - yy = clock->vcounter(); - } - yy += CLIP_10BIT_SIGNED(voffset - centery); - - m7b = CAST_WORDTOINT(regs.m7b) * yy + (centerx << 8); - m7d = CAST_WORDTOINT(regs.m7d) * yy + (centery << 8); - - step_m7a = CAST_WORDTOINT(regs.m7a); - step_m7c = CAST_WORDTOINT(regs.m7c); - - xx = CLIP_10BIT_SIGNED(hoffset - centerx); - - m7a = CAST_WORDTOINT(regs.m7a) * xx; - m7c = CAST_WORDTOINT(regs.m7c) * xx; - - for(x=0;x<256;x++) { - px = ((m7a + m7b) >> 8); - py = ((m7c + m7d) >> 8); - - switch(regs.mode7_repeat) { - case 0: //screen repitition outside of screen area - case 1: //same as case 0 - px &= 1023; - py &= 1023; - tx = ((px >> SH_8) & 127); - ty = ((py >> SH_8) & 127); - tile = vram[(ty * 128 + tx) << 1]; - palette = vram[(((tile << SH_64) + ((py & 7) << SH_8) + (px & 7)) << 1) + 1]; - break; - case 2: //character 0 repetition outside of screen area - if(px < 0 || px > 1023 || py < 0 || py > 1023) { - tx = 0; - ty = 0; - } else { - px &= 1023; - py &= 1023; - tx = ((px >> SH_8) & 127); - ty = ((py >> SH_8) & 127); - } - tile = vram[(ty * 128 + tx) << 1]; - palette = vram[(((tile << SH_64) + ((py & 7) << SH_8) + (px & 7)) << 1) + 1]; - break; - case 3: //palette color 0 outside of screen area - if(px < 0 || px > 1023 || py < 0 || py > 1023) { - palette = 0; - } else { - px &= 1023; - py &= 1023; - tx = ((px >> SH_8) & 127); - ty = ((py >> SH_8) & 127); - tile = vram[(ty * 128 + tx) << 1]; - palette = vram[(((tile << SH_64) + ((py & 7) << SH_8) + (px & 7)) << 1) + 1]; - } - break; - } - - if(regs.mode7_extbg == false) { - if(palette) { - layer_pos = layer_pos_bg1; - if(regs.mode7_hflip == true) { - set_layer_pixel(255 - x, palette); - } else { - set_layer_pixel(x, palette); - } - } - } else { - priority = (palette >> 7); - palette &= 0x7f; - if(palette) { - if(priority == 0) { - layer_pos = layer_pos_bg2_pri0; - } else { - layer_pos = layer_pos_bg2_pri1; - } - if(regs.mode7_hflip == true) { - set_layer_pixel(255 - x, palette); - } else { - set_layer_pixel(x, palette); - } - } - } - - m7a += step_m7a; - m7c += step_m7c; - } -} diff --git a/src/ppu/bppu/bppu_old_render_windows.cpp b/src/ppu/bppu/bppu_old_render_windows.cpp deleted file mode 100644 index cc0cc5e4..00000000 --- a/src/ppu/bppu/bppu_old_render_windows.cpp +++ /dev/null @@ -1,159 +0,0 @@ -bool bPPU::windows_not_obstructing(uint8 layer, uint8 bg, uint16 x) { -uint8 w1_mask, w2_mask; //1 = masked, 0 = not masked -uint16 window1_left, window1_right, window2_left, window2_right; - if(layer == PPU_MAIN) { - if(regs.bg_window_enabled[bg] == false)return true; - } else if(layer == PPU_SUB) { - if(regs.bgsub_window_enabled[bg] == false)return true; - } - - window1_left = regs.window1_left; - window1_right = regs.window1_right; - window2_left = regs.window2_left; - window2_right = regs.window2_right; - - if(regs.bg_mode == 5 || regs.bg_mode == 6) { - window1_left <<= 1; - window1_right <<= 1; - window2_left <<= 1; - window2_right <<= 1; - } - - if(regs.bg_window1_enabled[bg] == true && regs.bg_window2_enabled[bg] == false) { - if(regs.bg_window1_invert[bg] == false) { - if(x >= window1_left && x <= window1_right)return false; - return true; - } else { - if(x < window1_left || x > window1_right)return false; - return true; - } - } else if(regs.bg_window2_enabled[bg] == true && regs.bg_window1_enabled[bg] == false) { - if(regs.bg_window2_invert[bg] == false) { - if(x >= window2_left && x <= window2_right)return false; - return true; - } else { - if(x < window2_left || x > window2_right)return false; - return true; - } - } else if(regs.bg_window1_enabled[bg] == true && regs.bg_window2_enabled[bg] == true) { - if(regs.bg_window1_invert[bg] == false) { - if(x >= window1_left && x <= window1_right)w1_mask = 1; - else w1_mask = 0; - } else { - if(x < window1_left || x > window1_right)w1_mask = 1; - else w1_mask = 0; - } - - if(regs.bg_window2_invert[bg] == false) { - if(x >= window2_left && x <= window2_right)w2_mask = 1; - else w2_mask = 0; - } else { - if(x < window2_left || x > window2_right)w2_mask = 1; - else w2_mask = 0; - } - - switch(regs.bg_window_mask[bg]) { - case WINDOWMASK_OR: - if((w1_mask | w2_mask) == 1)return false; - return true; - case WINDOWMASK_AND: - if((w1_mask & w2_mask) == 1)return false; - return true; - case WINDOWMASK_XOR: - if((w1_mask ^ w2_mask) == 1)return false; - return true; - case WINDOWMASK_XNOR: - if((w1_mask ^ w2_mask) == 0)return false; - return true; - } - } - return true; -} - -bool bPPU::color_windows_not_obstructing(uint16 x, uint8 color_mask_type) { -uint8 w1_mask, w2_mask; //1 = masked, 0 = not masked -uint8 color_mask; -bool r; -uint16 window1_left, window1_right, window2_left, window2_right; - if(color_mask_type == PPU_MAIN) { - color_mask = regs.color_mask; - } else { - color_mask = regs.colorsub_mask; - } - - if(color_mask == 0)return false; - if(color_mask == 3)return true; - - window1_left = regs.window1_left; - window1_right = regs.window1_right; - window2_left = regs.window2_left; - window2_right = regs.window2_right; - - if(regs.bg_mode == 5 || regs.bg_mode == 6) { - window1_left <<= 1; - window1_right <<= 1; - window2_left <<= 1; - window2_right <<= 1; - } - - if(regs.color_window1_enabled == false && regs.color_window2_enabled == false) { - r = true; - } else if(regs.color_window1_enabled == true && regs.color_window2_enabled == false) { - if(regs.color_window1_invert == false) { - if(x >= window1_left && x <= window1_right)r = false; - else r = true; - } else { - if(x < window1_left || x > window1_right)r = false; - else r = true; - } - } else if(regs.color_window1_enabled == false && regs.color_window2_enabled == true) { - if(regs.color_window2_invert == false) { - if(x >= window2_left && x <= window2_right)r = false; - else r = true; - } else { - if(x < window2_left || x > window2_right)r = false; - else r = true; - } - } else if(regs.color_window1_enabled == true && regs.color_window2_enabled == true) { - if(regs.color_window1_invert == false) { - if(x >= window1_left && x <= window1_right)w1_mask = 1; - else w1_mask = 0; - } else { - if(x < window1_left || x > window1_right)w1_mask = 1; - else w1_mask = 0; - } - - if(regs.color_window2_invert == false) { - if(x >= window2_left && x <= window2_right)w2_mask = 1; - else w2_mask = 0; - } else { - if(x < window2_left || x > window2_right)w2_mask = 1; - else w2_mask = 0; - } - - switch(regs.color_window_mask) { - case WINDOWMASK_OR: - if((w1_mask | w2_mask) == 1)r = false; - else r = true; - break; - case WINDOWMASK_AND: - if((w1_mask & w2_mask) == 1)r = false; - else r = true; - break; - case WINDOWMASK_XOR: - if((w1_mask ^ w2_mask) == 1)r = false; - else r = true; - break; - case WINDOWMASK_XNOR: - if((w1_mask ^ w2_mask) == 0)r = false; - else r = true; - break; - } - } - - if(color_mask == 2) { - r = (r == true)?false:true; - } - - return r; -} diff --git a/src/ppu/bppu/bppu_render.h b/src/ppu/bppu/bppu_render.h index cfaafba7..89ebdb10 100644 --- a/src/ppu/bppu/bppu_render.h +++ b/src/ppu/bppu/bppu_render.h @@ -49,21 +49,20 @@ void build_color_window_tables(); void render_line_bg(uint8 bg, uint8 color_depth, uint8 pri0_pos, uint8 pri1_pos); //bppu_render_oam.cpp -struct { - byte num; - byte width, height; - word x, y; - word character; - byte v_flip, h_flip; - byte palette; - byte priority; -}current_sprite; +sprite_item *spr; + +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[512], oam_line_pri[512]; -void set_sprite_attributes(uint8 sprite_num); -void render_oam_sprite(); +bool is_sprite_on_scanline(); +void load_oam_tiles(); +void render_oam_tile(int tile_num); void render_line_oam(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 pri3_pos); //bppu_render_mode7.cpp diff --git a/src/ppu/bppu/bppu_render_bg.cpp b/src/ppu/bppu/bppu_render_bg.cpp index a131b09c..d0b52853 100644 --- a/src/ppu/bppu/bppu_render_bg.cpp +++ b/src/ppu/bppu/bppu_render_bg.cpp @@ -111,6 +111,8 @@ uint8 *wt_main = main_windowtable[bg]; uint8 *wt_sub = sub_windowtable[bg]; build_window_tables(bg); for(screen_x=0;screen_x<_screen_width;screen_x++) { + //offset-per-tile mode. horizontal OPT is buggy, so it is disabled + //vertical OPT seems to be working OK... if(regs.bg_mode == 2 || regs.bg_mode == 4 || regs.bg_mode == 6) { if(regs.bg_mode == 6) { tile_x = (mtable[screen_x + (hscroll & 15)] >> 4); diff --git a/src/ppu/bppu/bppu_render_oam.cpp b/src/ppu/bppu/bppu_render_oam.cpp index b487604b..be44c52f 100644 --- a/src/ppu/bppu/bppu_render_oam.cpp +++ b/src/ppu/bppu/bppu_render_oam.cpp @@ -1,86 +1,131 @@ -void bPPU::set_sprite_attributes(uint8 sprite_num) { -uint32 t; -uint8 size, b; -uint16 x; - t = *((uint32*)oam + sprite_num); - b = oam[512 + (sprite_num >> 2)]; - - switch(sprite_num & 3) { - case 0: size = !!(b & 0x02); x = (b & 0x01)?0x100:0; break; - case 1: size = !!(b & 0x08); x = (b & 0x04)?0x100:0; break; - case 2: size = !!(b & 0x20); x = (b & 0x10)?0x100:0; break; - case 3: size = !!(b & 0x80); x = (b & 0x40)?0x100:0; break; - } - - current_sprite.num = sprite_num; - current_sprite.priority = (t >> 28) & 3; - current_sprite.x = x | (t & 0xff); - current_sprite.y = ((t >> 8) + 1) & 0xff; - current_sprite.v_flip = !!(t & 0x80000000); - current_sprite.h_flip = !!(t & 0x40000000); - current_sprite.palette = (t >> 25) & 7; - current_sprite.character = (t >> 16) & 0x01ff; - -//size: 0 = small, 1 = large +void bPPU::get_sprite_size(int i, bool size) { switch(regs.oam_basesize) { case 0: - if(!size) { current_sprite.width = 8; current_sprite.height = 8; } - else { current_sprite.width = 16; current_sprite.height = 16; } + if(!size) { sprite_list[i].width = 8; sprite_list[i].height = 8; } + else { sprite_list[i].width = 16; sprite_list[i].height = 16; } break; case 1: - if(!size) { current_sprite.width = 8; current_sprite.height = 8; } - else { current_sprite.width = 32; current_sprite.height = 32; } + if(!size) { sprite_list[i].width = 8; sprite_list[i].height = 8; } + else { sprite_list[i].width = 32; sprite_list[i].height = 32; } break; case 2: - if(!size) { current_sprite.width = 8; current_sprite.height = 8; } - else { current_sprite.width = 64; current_sprite.height = 64; } + if(!size) { sprite_list[i].width = 8; sprite_list[i].height = 8; } + else { sprite_list[i].width = 64; sprite_list[i].height = 64; } break; case 3: - if(!size) { current_sprite.width = 16; current_sprite.height = 16; } - else { current_sprite.width = 32; current_sprite.height = 32; } + if(!size) { sprite_list[i].width = 16; sprite_list[i].height = 16; } + else { sprite_list[i].width = 32; sprite_list[i].height = 32; } break; case 4: - if(!size) { current_sprite.width = 16; current_sprite.height = 16; } - else { current_sprite.width = 64; current_sprite.height = 64; } + if(!size) { sprite_list[i].width = 16; sprite_list[i].height = 16; } + else { sprite_list[i].width = 64; sprite_list[i].height = 64; } break; case 5: - if(!size) { current_sprite.width = 32; current_sprite.height = 32; } - else { current_sprite.width = 64; current_sprite.height = 64; } + if(!size) { sprite_list[i].width = 32; sprite_list[i].height = 32; } + else { sprite_list[i].width = 64; sprite_list[i].height = 64; } break; case 6: - if(!size) { current_sprite.width = 16; current_sprite.height = 32; } - else { current_sprite.width = 32; current_sprite.height = 64; } + if(!size) { sprite_list[i].width = 16; sprite_list[i].height = 32; } + else { sprite_list[i].width = 32; sprite_list[i].height = 64; } break; case 7: - if(!size) { current_sprite.width = 16; current_sprite.height = 32; } - else { current_sprite.width = 32; current_sprite.height = 32; } + if(!size) { sprite_list[i].width = 16; sprite_list[i].height = 32; } + else { sprite_list[i].width = 32; sprite_list[i].height = 32; } break; } } -void bPPU::render_oam_sprite() { -uint16 pos, col, chr, tiledata_inc; -uint8 d0, d1, d2, d3, pal_index; -int x, y, z, x1, mx, mask, p; -int tile_width; - tile_width = current_sprite.width >> 3; //e.x. 16x16 sprite = 2x2 tiles - - if(_interlace == true && _screen_width == 512) { - y = (_y << 1) + _interlace_field; +//called whenever OAM memory is written to +void bPPU::update_sprite_list(uint16 addr) { +int i, z; +uint16 width, height; + if(addr < 0x0200) { + i = addr >> 2; + switch(addr & 3) { + case 0: + sprite_list[i].x = (sprite_list[i].x & 0x0100) | oam[addr]; + break; + case 1: + sprite_list[i].y = oam[addr] + 1; + break; + case 2: + sprite_list[i].character = oam[addr]; + break; + case 3: + sprite_list[i].vflip = !!(oam[addr] & 0x80); + sprite_list[i].hflip = !!(oam[addr] & 0x40); + sprite_list[i].priority = (oam[addr] >> 4) & 3; + sprite_list[i].palette = (oam[addr] >> 1) & 7; + sprite_list[i].use_nameselect = oam[addr] & 1; + break; + } } else { - y = _y; + addr &= 0x001f; + z = oam[0x0200 + addr]; + i = addr << 2; + sprite_list[i ].x = ((z & 0x01)?0x0100:0x0000) + (sprite_list[i ].x & 0xff); + sprite_list[i + 1].x = ((z & 0x04)?0x0100:0x0000) + (sprite_list[i + 1].x & 0xff); + sprite_list[i + 2].x = ((z & 0x10)?0x0100:0x0000) + (sprite_list[i + 2].x & 0xff); + sprite_list[i + 3].x = ((z & 0x40)?0x0100:0x0000) + (sprite_list[i + 3].x & 0xff); + get_sprite_size(i, !!(z & 0x02)); + get_sprite_size(i + 1, !!(z & 0x08)); + get_sprite_size(i + 2, !!(z & 0x20)); + get_sprite_size(i + 3, !!(z & 0x80)); } +} - x = current_sprite.x; - if(_screen_width == 512) { - x <<= 1; +//called when sprite sizes are changed via $2101 write +void bPPU::update_sprite_list_sizes() { +int i, z; +uint16 addr = 0x0200; + for(i=0;i<128;i+=4) { + z = oam[addr++]; + get_sprite_size(i, !!(z & 0x02)); + get_sprite_size(i + 1, !!(z & 0x08)); + get_sprite_size(i + 2, !!(z & 0x20)); + get_sprite_size(i + 3, !!(z & 0x80)); } +} - if(current_sprite.v_flip) { - y = ((current_sprite.height - 1) - (_y - current_sprite.y)); +bool bPPU::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. 256 is correct, and not 255 -- as one might first expect + if(spr->x > 256 && (spr->x + spr->width) < 512 && _screen_width != 512)return false; + + if(regs.oam_halve == false) { + if(_y >= spr->y && _y < (spr->y + spr->height)) { + return true; + } else if((spr->y + spr->height) >= 256 && _y < ((spr->y + spr->height) & 255)) { + return true; + } } else { - y = (_y - current_sprite.y); + if(_y >= spr->y && _y < (spr->y + (spr->height >> 1))) { + return true; + } else if((spr->y + (spr->height >> 1)) >= 256 && _y < ((spr->y + (spr->height >> 1)) & 255)) { + return true; + } } + + return false; +} + +void bPPU::load_oam_tiles() { +uint16 tile_width; + tile_width = spr->width >> 3; + +int x, y, chr, nameselect_index; + x = spr->x; + if(_screen_width == 512)x <<= 1; + x &= 511; + + if(spr->vflip) { + y = ((spr->height - 1) - (_y - spr->y)); + } else { + y = (_y - spr->y); + } +//todo: double-check code below. seems that interlace_field +//should be added to hires 512x448 sprites as well, and not +//just when oam_halve is enabled... if(regs.oam_halve == true) { y <<= 1; if(_interlace == true && _screen_width == 512) { @@ -89,81 +134,114 @@ int tile_width; } y &= 255; - chr = current_sprite.character; - tiledata_inc = (chr & 0x100)?(regs.oam_nameselect << 13):0; + chr = spr->character; + if(spr->use_nameselect == true) { + chr += 256; + nameselect_index = regs.oam_nameselect << 13; + } else { + nameselect_index = 0x0000; + } chr += (y >> 3) << 4; - pal_index = (current_sprite.palette << 4); - for(x1=0;x1> z; - } - x &= 511; - if(x < _screen_width) { - col = 0; - if(d0 & mask)col += 1; - if(d1 & mask)col += 2; - if(d2 & mask)col += 4; - if(d3 & mask)col += 8; - if(col) { - col += pal_index; - col += 128; - if(oam_line_pri[x] == OAM_PRI_NONE) { - oam_line_pal[x] = col; - oam_line_pri[x] = current_sprite.priority; - } - if(_screen_width == 512) { - if(oam_line_pri[x + 1] == OAM_PRI_NONE) { - oam_line_pal[x + 1] = col; - oam_line_pri[x + 1] = current_sprite.priority; - } - } + +int i, n, mx, pos, z; + for(i=0;i= 257 && (z + 7) < 512 && _screen_width != 512)continue; + + if(regs.oam_tilecount++ > 34)break; + n = regs.oam_tilecount - 1; + oam_tilelist[n].x = z; + oam_tilelist[n].y = y; + oam_tilelist[n].pri = spr->priority; + oam_tilelist[n].pal = (spr->palette << 4) + 128; + oam_tilelist[n].hflip = spr->hflip; + + if(oam_tilelist[n].hflip) { + mx = (tile_width - 1) - i; + } else { + mx = i; + } + pos = regs.oam_tdaddr + ((chr + mx) << 5) + ((y & 7) << 1) + nameselect_index; + oam_tilelist[n].tile = (pos >> 5) & 0x07ff; + } +} + +void bPPU::render_oam_tile(int tile_num) { +uint8 *oam_td, *oam_td_state, *tile_ptr; +oam_tileitem *t = &oam_tilelist[tile_num]; + oam_td = (uint8*)bg_tiledata[COLORDEPTH_16]; + oam_td_state = (uint8*)bg_tiledata_state[COLORDEPTH_16]; + + if(oam_td_state[t->tile] == 1) { + render_bg_tile(COLORDEPTH_16, t->tile); + } + +int x, sx, col; + sx = t->x; +//tile_ptr = tiledata + (tile * (8_width * 8_height)) + ((y & 7_height_mask) * 8_width); + tile_ptr = (uint8*)oam_td + (t->tile << 6) + ((t->y & 7) << 3); + for(x=0;x<8;x++) { + sx &= 511; + if(sx < _screen_width) { + col = *(tile_ptr + ((t->hflip)?7-x:x)); + if(col) { + col += t->pal; + oam_line_pal[sx] = col; + oam_line_pri[sx] = t->pri; + if(_screen_width == 512) { + oam_line_pal[sx + 1] = col; + oam_line_pri[sx + 1] = t->pri; } } - x += (_screen_width == 512)?2:1; } + sx += (_screen_width == 512)?2:1; } } void bPPU::render_line_oam(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 pri3_pos) { -int s; +int s, x; bool _bg_enabled = regs.bg_enabled[OAM]; bool _bgsub_enabled = regs.bgsub_enabled[OAM]; - if(_bg_enabled == false && _bgsub_enabled == false)return; uint8 *wt_main = main_windowtable[OAM]; uint8 *wt_sub = sub_windowtable[OAM]; build_window_tables(OAM); + regs.oam_itemcount = 0; + regs.oam_tilecount = 0; memset(oam_line_pri, OAM_PRI_NONE, 512); + + memset(oam_itemlist, 0xff, 32); for(s=0;s<128;s++) { - set_sprite_attributes(s); - if(regs.oam_halve == false) { - if(_y >= current_sprite.y && _y < (current_sprite.y + current_sprite.height)) { - render_oam_sprite(); - } else if((current_sprite.y + current_sprite.height) >= 256 && _y < ((current_sprite.y + current_sprite.height) & 255)) { - render_oam_sprite(); - } - } else { - if(_y >= current_sprite.y && _y < (current_sprite.y + (current_sprite.height >> 1))) { - render_oam_sprite(); - } else if((current_sprite.y + current_sprite.height) >= 256 && _y < ((current_sprite.y + (current_sprite.height >> 1)) & 255)) { - render_oam_sprite(); - } - } + spr = &sprite_list[(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; } + for(s=0;s<34;s++)oam_tilelist[s].tile = 0xffff; + + for(s=31;s>=0;s--) { + if(oam_itemlist[s] == 0xff)continue; + spr = &sprite_list[oam_itemlist[s]]; + load_oam_tiles(); + } + + for(s=0;s<34;s++) { + if(oam_tilelist[s].tile == 0xffff)continue; + render_oam_tile(s); + } + + regs.time_over |= (regs.oam_tilecount > 34); + regs.range_over |= (regs.oam_itemcount > 32); + + if(_bg_enabled == false && _bgsub_enabled == false)return; int _pri; - for(int x=0;x<_screen_width;x++) { + for(x=0;x<_screen_width;x++) { if(oam_line_pri[x] == OAM_PRI_NONE)continue; switch(oam_line_pri[x]) { diff --git a/src/ppu/bppu/old_bppu_render_oam.cpp b/src/ppu/bppu/old_bppu_render_oam.cpp new file mode 100644 index 00000000..c6060e19 --- /dev/null +++ b/src/ppu/bppu/old_bppu_render_oam.cpp @@ -0,0 +1,230 @@ +void bPPU::set_sprite_attributes(uint8 sprite_num) { +uint32 t; +uint8 size, b; +uint16 x; + t = *((uint32*)oam + sprite_num); + b = oam[512 + (sprite_num >> 2)]; + + switch(sprite_num & 3) { + case 0: size = !!(b & 0x02); x = (b & 0x01)?0x100:0; break; + case 1: size = !!(b & 0x08); x = (b & 0x04)?0x100:0; break; + case 2: size = !!(b & 0x20); x = (b & 0x10)?0x100:0; break; + case 3: size = !!(b & 0x80); x = (b & 0x40)?0x100:0; break; + } + + current_sprite.num = sprite_num; + current_sprite.priority = (t >> 28) & 3; + current_sprite.x = x | (t & 0xff); + current_sprite.y = ((t >> 8) + 1) & 0xff; + current_sprite.v_flip = !!(t & 0x80000000); + current_sprite.h_flip = !!(t & 0x40000000); + current_sprite.palette = (t >> 25) & 7; + current_sprite.character = (t >> 16) & 0x01ff; + +//size: 0 = small, 1 = large + switch(regs.oam_basesize) { + case 0: + if(!size) { current_sprite.width = 8; current_sprite.height = 8; } + else { current_sprite.width = 16; current_sprite.height = 16; } + break; + case 1: + if(!size) { current_sprite.width = 8; current_sprite.height = 8; } + else { current_sprite.width = 32; current_sprite.height = 32; } + break; + case 2: + if(!size) { current_sprite.width = 8; current_sprite.height = 8; } + else { current_sprite.width = 64; current_sprite.height = 64; } + break; + case 3: + if(!size) { current_sprite.width = 16; current_sprite.height = 16; } + else { current_sprite.width = 32; current_sprite.height = 32; } + break; + case 4: + if(!size) { current_sprite.width = 16; current_sprite.height = 16; } + else { current_sprite.width = 64; current_sprite.height = 64; } + break; + case 5: + if(!size) { current_sprite.width = 32; current_sprite.height = 32; } + else { current_sprite.width = 64; current_sprite.height = 64; } + break; + case 6: + if(!size) { current_sprite.width = 16; current_sprite.height = 32; } + else { current_sprite.width = 32; current_sprite.height = 64; } + break; + case 7: + if(!size) { current_sprite.width = 16; current_sprite.height = 32; } + else { current_sprite.width = 32; current_sprite.height = 32; } + break; + } +} + +void bPPU::render_oam_sprite() { +uint16 pos, col, chr, tiledata_inc; +uint8 d0, d1, d2, d3, pal_index; +int x, y, z, x1, mx, mask, p; +int tile_width; +//uint8 item_inc, tile_inc; + tile_width = current_sprite.width >> 3; //e.x. 16x16 sprite = 2x2 tiles + + regs.oam_itemcount++; +//add all visible tiles to regs.oam_tilecount + if(current_sprite.x > 256) { + //if sprite clips on left edge of the screen + regs.oam_tilecount += ((current_sprite.x + current_sprite.width + 7) & 511) >> 3; + } else if(current_sprite.x + current_sprite.width >= 257) { + //if sprite clips on right edge of screen + regs.oam_tilecount += (257 - current_sprite.x + 7) >> 3; + } else { + //if entire sprite is visible + regs.oam_tilecount += current_sprite.width >> 3; + } + +//if(_y == 0xa0)dprintf("* oam_itemcount=%d, oam_tilecount=%d", regs.oam_itemcount, regs.oam_tilecount); + + if(regs.bg_enabled[OAM] == false && regs.bgsub_enabled[OAM] == false)return; + if(regs.oam_tilecount > 34)return; + if(regs.oam_itemcount > 32)return; + + if(_interlace == true && _screen_width == 512) { + y = (_y << 1) + _interlace_field; + } else { + y = _y; + } + + x = current_sprite.x; + if(_screen_width == 512) { + x <<= 1; + } + + if(current_sprite.v_flip) { + y = ((current_sprite.height - 1) - (_y - current_sprite.y)); + } else { + y = (_y - current_sprite.y); + } + if(regs.oam_halve == true) { + y <<= 1; + if(_interlace == true && _screen_width == 512) { + y += _interlace_field; + } + } + y &= 255; + + chr = current_sprite.character; + tiledata_inc = (chr & 0x100)?(regs.oam_nameselect << 13):0; + chr += (y >> 3) << 4; + pal_index = (current_sprite.palette << 4); + for(x1=0;x1> z; + } + x &= 511; + if(x < _screen_width) { + col = 0; + if(d0 & mask)col += 1; + if(d1 & mask)col += 2; + if(d2 & mask)col += 4; + if(d3 & mask)col += 8; + if(col) { + col += pal_index; + col += 128; + if(oam_line_pri[x] == OAM_PRI_NONE) { + oam_line_pal[x] = col; + oam_line_pri[x] = current_sprite.priority; + } + if(_screen_width == 512) { + if(oam_line_pri[x + 1] == OAM_PRI_NONE) { + oam_line_pal[x + 1] = col; + oam_line_pri[x + 1] = current_sprite.priority; + } + } + } + } + x += (_screen_width == 512)?2:1; + } + } +} + +void bPPU::render_line_oam(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 pri3_pos) { +int s, x; +bool _bg_enabled = regs.bg_enabled[OAM]; +bool _bgsub_enabled = regs.bgsub_enabled[OAM]; + +uint8 *wt_main = main_windowtable[OAM]; +uint8 *wt_sub = sub_windowtable[OAM]; + build_window_tables(OAM); + + regs.oam_itemcount = 0; + regs.oam_tilecount = 0; + memset(oam_line_pri, OAM_PRI_NONE, 512); + for(s=0;s<128;s++) { + set_sprite_attributes((s + regs.oam_firstsprite) & 127); + + //if sprite is entirely offscreen and doesn't wrap around to the left side of the screen, + //then it is not counted. 256 is correct, and not 255 -- as one might first expect + if(current_sprite.x > 256 && ((current_sprite.x + current_sprite.width) & 511) > 256)continue; + +//if(_y == 0xa0) +//dprintf("* y: %d, fs: %d, sprite: %d, width: %d, height: %d, x: %d, y: %d", +// _y, regs.oam_firstsprite, (s + regs.oam_firstsprite) & 127, +// current_sprite.width, current_sprite.height, current_sprite.x, current_sprite.y); + + if(regs.oam_halve == false) { + if(_y >= current_sprite.y && _y < (current_sprite.y + current_sprite.height)) { + render_oam_sprite(); + } else if((current_sprite.y + current_sprite.height) >= 256 && _y < ((current_sprite.y + current_sprite.height) & 255)) { + render_oam_sprite(); + } + } else { + if(_y >= current_sprite.y && _y < (current_sprite.y + (current_sprite.height >> 1))) { + render_oam_sprite(); + } else if((current_sprite.y + (current_sprite.height >> 1)) >= 256 && _y < ((current_sprite.y + (current_sprite.height >> 1)) & 255)) { + render_oam_sprite(); + } + } + } + + regs.time_over |= (regs.oam_tilecount > 34); + regs.range_over |= (regs.oam_itemcount > 32); +//dprintf("* line: %d, t = %d, r = %d, tc = %d, ic = %d", _y, +//regs.time_over, regs.range_over, regs.oam_tilecount, regs.oam_itemcount); + + if(_bg_enabled == false && _bgsub_enabled == false)return; +int _pri; + for(x=0;x<_screen_width;x++) { + if(oam_line_pri[x] == OAM_PRI_NONE)continue; + + switch(oam_line_pri[x]) { + case 0:_pri = pri0_pos;break; + case 1:_pri = pri1_pos;break; + case 2:_pri = pri2_pos;break; + case 3:_pri = pri3_pos;break; + } + + if(main_colorwindowtable[x]) { + if(_bg_enabled == true && !wt_main[x]) { + if(pixel_cache[x].pri_main < _pri) { + pixel_cache[x].pri_main = _pri; + pixel_cache[x].bg_main = PC_OAM; + pixel_cache[x].src_main = oam_line_pal[x]; + } + } + if(_bgsub_enabled == true && !wt_sub[x]) { + if(pixel_cache[x].pri_sub < _pri) { + pixel_cache[x].pri_sub = _pri; + pixel_cache[x].bg_sub = PC_OAM; + pixel_cache[x].src_sub = oam_line_pal[x]; + } + } + } + } +} diff --git a/src/ppu/ppu.cpp b/src/ppu/ppu.cpp index 8f9ff5b5..3f7a90ce 100644 --- a/src/ppu/ppu.cpp +++ b/src/ppu/ppu.cpp @@ -15,6 +15,8 @@ PPUOutput::~PPUOutput() { if(buffer)memfree(buffer, "PPUOutput::buffer"); } +void PPU::set_frameskip(int fs) {} + PPU::PPU() { mmio = &mmio_unmapped; output = new PPUOutput(); diff --git a/src/ppu/ppu.h b/src/ppu/ppu.h index 4aeefdff..f4c20eca 100644 --- a/src/ppu/ppu.h +++ b/src/ppu/ppu.h @@ -28,6 +28,7 @@ MMIO *mmio; virtual void frame() = 0; virtual void power() = 0; virtual void reset() = 0; + virtual void set_frameskip(int fs); PPU(); ~PPU(); diff --git a/src/sdl/Makefile b/src/sdl/Makefile new file mode 100644 index 00000000..eba1c93b --- /dev/null +++ b/src/sdl/Makefile @@ -0,0 +1,81 @@ +CC = c++ +CFLAGS = -O2 +OBJS = sdlmain.o \ + libstring.o libconfig.o \ + reader.o \ + memory.o bmemory.o \ + cpu.o bcpu.o \ + apu.o bapu.o bapuskip.o \ + ppu.o bppu.o \ + snes.o + +all: $(OBJS) + $(CC) $(CFLAGS) $(OBJS) `sdl11-config --cflags --libs` -o bsnes_sdl + +clean: + rm *.o + +#################### +### sdl-specific ### +#################### +sdlmain.o: *.cpp *.h + $(CC) $(CFLAGS) -c sdlmain.cpp `sdl11-config --cflags` + +################# +### libraries ### +################# +libstring.o: ../lib/*.cpp ../lib/*.h + $(CC) $(CFLAGS) -c ../lib/libstring.cpp +libconfig.o: ../lib/*.cpp ../lib/*.h + $(CC) $(CFLAGS) -c ../lib/libconfig.cpp + +############## +### memory ### +############## +memory.o: ../memory/memory.cpp ../memory/memory.h + $(CC) $(CFLAGS) -c ../memory/memory.cpp + +bmemory.o: ../memory/bmemory/* + $(CC) $(CFLAGS) -c ../memory/bmemory/bmemory.cpp + +########### +### cpu ### +########### +cpu.o: ../cpu/*.cpp ../cpu/*.h + $(CC) $(CFLAGS) -c ../cpu/cpu.cpp + +bcpu.o: ../cpu/bcpu/* + $(CC) $(CFLAGS) -c ../cpu/bcpu/bcpu.cpp + +########### +### apu ### +########### +apu.o: ../apu/* + $(CC) $(CFLAGS) -c ../apu/apu.cpp + +bapu.o: ../apu/bapu/* + $(CC) $(CFLAGS) -c ../apu/bapu/bapu.cpp + +bapuskip.o: ../apu/bapuskip/* + $(CC) $(CFLAGS) -c ../apu/bapuskip/bapuskip.cpp + +########### +### ppu ### +########### +ppu.o: ../ppu/*.cpp ../ppu/*.h + $(CC) $(CFLAGS) -c ../ppu/ppu.cpp + +bppu.o: ../ppu/bppu/* + $(CC) $(CFLAGS) -c ../ppu/bppu/bppu.cpp + +############## +### reader ### +############## +reader.o: ../reader/reader.cpp ../reader/reader.h + $(CC) $(CFLAGS) -c ../reader/reader.cpp + +############ +### snes ### +############ +snes.o: ../snes/*.cpp ../snes/*.h + $(CC) $(CFLAGS) -c ../snes/snes.cpp diff --git a/src/sdl/Makefile.win32 b/src/sdl/Makefile.win32 new file mode 100644 index 00000000..fee7b835 --- /dev/null +++ b/src/sdl/Makefile.win32 @@ -0,0 +1,82 @@ +CC = cl +CFLAGS = /nologo /O2 /Ogityb2 /Gr /Gs +OBJS = sdlmain.obj \ + libstring.obj libconfig.obj \ + reader.obj \ + memory.obj bmemory.obj \ + cpu.obj bcpu.obj \ + apu.obj bapu.obj bapuskip.obj \ + ppu.obj bppu.obj \ + snes.obj +LIBS = kernel32.lib user32.lib gdi32.lib sdlmain.lib sdl.lib + +all: $(OBJS) + $(CC) /Febsnes_sdl.exe $(CFLAGS) $(OBJS) $(LIBS) + +clean: + del *.obj + +#################### +### sdl-specific ### +#################### +sdlmain.obj: *.cpp *.h + $(CC) $(CFLAGS) /c sdlmain.cpp + +################# +### libraries ### +################# +libstring.obj: ../lib/*.cpp ../lib/*.h + $(CC) $(CFLAGS) /c ../lib/libstring.cpp +libconfig.obj: ../lib/*.cpp ../lib/*.h + $(CC) $(CFLAGS) /c ../lib/libconfig.cpp + +############## +### memory ### +############## +memory.obj: ../memory/memory.cpp ../memory/memory.h + $(CC) $(CFLAGS) /c ../memory/memory.cpp + +bmemory.obj: ../memory/bmemory/* + $(CC) $(CFLAGS) /c ../memory/bmemory/bmemory.cpp + +########### +### cpu ### +########### +cpu.obj: ../cpu/*.cpp ../cpu/*.h + $(CC) $(CFLAGS) /c ../cpu/cpu.cpp + +bcpu.obj: ../cpu/bcpu/* + $(CC) $(CFLAGS) /c ../cpu/bcpu/bcpu.cpp + +########### +### apu ### +########### +apu.obj: ../apu/* + $(CC) $(CFLAGS) /c ../apu/apu.cpp + +bapu.obj: ../apu/bapu/* + $(CC) $(CFLAGS) /c ../apu/bapu/bapu.cpp + +bapuskip.obj: ../apu/bapuskip/* + $(CC) $(CFLAGS) /c ../apu/bapuskip/bapuskip.cpp + +########### +### ppu ### +########### +ppu.obj: ../ppu/*.cpp ../ppu/*.h + $(CC) $(CFLAGS) /c ../ppu/ppu.cpp + +bppu.obj: ../ppu/bppu/* + $(CC) $(CFLAGS) /c ../ppu/bppu/bppu.cpp + +############## +### reader ### +############## +reader.obj: ../reader/reader.cpp ../reader/reader.h + $(CC) $(CFLAGS) /c ../reader/reader.cpp + +############ +### snes ### +############ +snes.obj: ../snes/*.cpp ../snes/*.h + $(CC) $(CFLAGS) /c ../snes/snes.cpp diff --git a/src/sdl/bsnes.cpp b/src/sdl/bsnes.cpp new file mode 100644 index 00000000..50336b7a --- /dev/null +++ b/src/sdl/bsnes.cpp @@ -0,0 +1,90 @@ +void bSNES::set_status(uint32 new_status) { run_status = new_status; } +uint32 bSNES::get_status() { return run_status; } + +void bSNES::snes_run() { + if(!rom_image->loaded())return; + + switch(run_status) { + case RUN: + while(update_frame == false) { + run(); + } + update_frame = false; + render(); + return; + case STOP: + break; + } +} + +void bSNES::render_frame() {} + +/*********************** + *** Input functions *** + ***********************/ + +//It would appear that keystate does not need to be free'd +//after calling SDL_GetKeyState... doing so causes libSDL +//to throw error messages about a bad free call to stdout... +void bSNES::poll_input() { +uint8 *keystate = SDL_GetKeyState(0); + joypad1.up = keystate[cfg.input.joypad1.up]; + joypad1.down = keystate[cfg.input.joypad1.down]; + joypad1.left = keystate[cfg.input.joypad1.left]; + joypad1.right = keystate[cfg.input.joypad1.right]; + joypad1.select = keystate[cfg.input.joypad1.select]; + joypad1.start = keystate[cfg.input.joypad1.start]; + joypad1.y = keystate[cfg.input.joypad1.y]; + joypad1.b = keystate[cfg.input.joypad1.b]; + joypad1.x = keystate[cfg.input.joypad1.x]; + joypad1.a = keystate[cfg.input.joypad1.a]; + joypad1.l = keystate[cfg.input.joypad1.l]; + joypad1.r = keystate[cfg.input.joypad1.r]; + +//It's impossible to hold both up+down, or left+right down +//at the same time on a directional pad; and besides, allowing +//this to happen causes glitches in many SNES games. + if(joypad1.up) joypad1.down = 0; + if(joypad1.left)joypad1.right = 0; +} + +bool bSNES::get_input_status(uint8 device, uint8 button) { + switch(device) { + case DEV_JOYPAD1: + switch(button) { + case JOYPAD_UP: return joypad1.up; + case JOYPAD_DOWN: return joypad1.down; + case JOYPAD_LEFT: return joypad1.left; + case JOYPAD_RIGHT: return joypad1.right; + case JOYPAD_A: return joypad1.a; + case JOYPAD_B: return joypad1.b; + case JOYPAD_X: return joypad1.x; + case JOYPAD_Y: return joypad1.y; + case JOYPAD_L: return joypad1.l; + case JOYPAD_R: return joypad1.r; + case JOYPAD_SELECT:return joypad1.select; + case JOYPAD_START: return joypad1.start; + } + break; + } + return 0; +} + +bJoypad::bJoypad() { + up = down = left = right = false; + a = b = x = y = false; + l = r = select = start = false; +} + +void bSNES::notify(uint32 message, uint32 param1, uint32 param2) { + switch(message) { + case RENDER_FRAME: + update_frame = true; + break; + } +} + +bSNES::bSNES() { + run_status = STOP; + update_frame = false; +} diff --git a/src/sdl/bsnes.h b/src/sdl/bsnes.h new file mode 100644 index 00000000..472df4e5 --- /dev/null +++ b/src/sdl/bsnes.h @@ -0,0 +1,30 @@ +class bJoypad { +public: +bool up, down, left, right; +bool a, b, x, y; +bool l, r, select, start; + bJoypad(); +}; + +class bSNES : public SNES { +private: +uint32 run_status; +bool update_frame; +bJoypad joypad1, joypad2; + +public: +enum { STOP = 0, RUN }; + void set_status(uint32 new_status); + uint32 get_status(); + void snes_run(); + void render_frame(); + +//input functions + void poll_input(); + bool get_input_status(uint8 device, uint8 button); + + void notify(uint32 message, uint32 param1 = 0, uint32 param2 = 0); + bSNES(); +}; + +bSNES *bsnes; diff --git a/src/sdl/bsnes_sdl.cfg b/src/sdl/bsnes_sdl.cfg new file mode 100644 index 00000000..3e9cb767 --- /dev/null +++ b/src/sdl/bsnes_sdl.cfg @@ -0,0 +1,18 @@ +apu.enabled = true +video.fullscreen = false +video.display_width = 256 +video.display_height = 223 +video.output_width = 256 +video.output_height = 223 +input.joypad1.up = 0x111 +input.joypad1.down = 0x112 +input.joypad1.left = 0x114 +input.joypad1.right = 0x113 +input.joypad1.a = 0x78 +input.joypad1.b = 0x7a +input.joypad1.x = 0x73 +input.joypad1.y = 0x61 +input.joypad1.l = 0x64 +input.joypad1.r = 0x63 +input.joypad1.select = 0x12f +input.joypad1.start = 0x0d diff --git a/src/sdl/cc.bat b/src/sdl/cc.bat new file mode 100644 index 00000000..413eb640 --- /dev/null +++ b/src/sdl/cc.bat @@ -0,0 +1,3 @@ +@nmake /NOLOGO /f Makefile.win32 +@move bsnes_sdl.exe ../../bsnes_sdl.exe>nul +@pause \ No newline at end of file diff --git a/src/sdl/clean.bat b/src/sdl/clean.bat new file mode 100644 index 00000000..81715981 --- /dev/null +++ b/src/sdl/clean.bat @@ -0,0 +1 @@ +@nmake /NOLOGO /f Makefile.win32 clean diff --git a/src/sdl/config.cpp b/src/sdl/config.cpp new file mode 100644 index 00000000..62177565 --- /dev/null +++ b/src/sdl/config.cpp @@ -0,0 +1,47 @@ +#define __config_add(name, def, type) add(&name, #name, def, type) + +class Config : public config { +public: + +struct { + uint32 enabled; +}apu; + +struct { + uint32 fullscreen; + uint32 display_width, display_height; + uint32 output_width, output_height; +}video; + +struct { + struct { + uint32 up, down, left, right; + uint32 a, b, x, y, l, r; + uint32 select, start; + }joypad1; +}input; + + Config() { + __config_add(apu.enabled, true, TRUEFALSE); + + __config_add(video.fullscreen, false, TRUEFALSE); + __config_add(video.display_width, 256, DEC); + __config_add(video.display_height, 223, DEC); + __config_add(video.output_width, 256, DEC); + __config_add(video.output_height, 223, DEC); + + __config_add(input.joypad1.up, SDLK_UP, HEX); + __config_add(input.joypad1.down, SDLK_DOWN, HEX); + __config_add(input.joypad1.left, SDLK_LEFT, HEX); + __config_add(input.joypad1.right, SDLK_RIGHT, HEX); + __config_add(input.joypad1.a, SDLK_x, HEX); + __config_add(input.joypad1.b, SDLK_z, HEX); + __config_add(input.joypad1.x, SDLK_s, HEX); + __config_add(input.joypad1.y, SDLK_a, HEX); + __config_add(input.joypad1.l, SDLK_d, HEX); + __config_add(input.joypad1.r, SDLK_c, HEX); + __config_add(input.joypad1.select, SDLK_RSHIFT, HEX); + __config_add(input.joypad1.start, SDLK_RETURN, HEX); + } + +}cfg; diff --git a/src/sdl/render.cpp b/src/sdl/render.cpp new file mode 100644 index 00000000..69b9ebec --- /dev/null +++ b/src/sdl/render.cpp @@ -0,0 +1,110 @@ +uint8 color_curve_table[32]; +uint32 color_lookup_table[65536]; + +void update_color_lookup_table() { +int i, r, g, b, c; + for(i=0,c=0;i<16;i++) { + color_curve_table[i] = c; + c = c + i + 1; + } + for(;i<31;i++) { + color_curve_table[i] = c; + c += 8; + } + color_curve_table[i] = 0xff; + +int color_depth = 16; + if(color_depth == 15) { + for(i=0;i<65536;i++) { + r = (i ) & 31; + g = (i >> 5) & 31; + b = (i >> 10) & 31; + r = color_curve_table[r] >> 3; + g = color_curve_table[g] >> 3; + b = color_curve_table[b] >> 3; + color_lookup_table[i] = (r << 10) | (g << 5) | (b); + } + } else if(color_depth == 16) { + for(i=0;i<65536;i++) { + r = (i ) & 31; + g = (i >> 5) & 31; + b = (i >> 10) & 31; + r = color_curve_table[r] >> 3; + g = color_curve_table[g] >> 2; + b = color_curve_table[b] >> 3; + color_lookup_table[i] = (r << 11) | (g << 5) | (b); + } + } else if(color_depth == 32) { + for(i=0;i<65536;i++) { + r = (i ) & 31; + g = (i >> 5) & 31; + b = (i >> 10) & 31; + r = color_curve_table[r]; + g = color_curve_table[g]; + b = color_curve_table[b]; + color_lookup_table[i] = (r << 16) | (g << 8) | (b); + } + } else { + alert("Error: Unsupported color depth [%d]", color_depth); + } +} + +void render16() { +uint16 *src, *dest; +uint32 pitch; +int x, y; + pitch = (backbuffer->pitch >> 1) - 256; + src = (uint16*)ppu->output->buffer + (1 << 10); + dest = (uint16*)backbuffer->pixels; + for(y=0;y<223;y++) { + for(x=0;x<256;x++) { + *dest++ = color_lookup_table[*src]; + src += 2; + } + dest += pitch; + src += 512; + } +} + +void render32() { +uint16 *src; +uint32 *dest, pitch; +int x, y; + pitch = (screen->pitch >> 2) - 256; + src = (uint16*)ppu->output->buffer + (1 << 10); + dest = (uint32*)screen->pixels; + for(y=0;y<223;y++) { + for(x=0;x<256;x++) { + *dest++ = color_lookup_table[*src]; + src += 2; + } + dest += pitch; + src += 512; + } +} + +void render() { + if(SDL_MUSTLOCK(screen)) { + SDL_LockSurface(screen); + } + if(SDL_MUSTLOCK(backbuffer)) { + SDL_LockSurface(backbuffer); + } + + render16(); + +//documentation says not to use this, but it's rather ridiculous that a graphics +//library wouldn't support simple image scaling... so let's use it anyway and see +//what happens... + SDL_SoftStretch(backbuffer, &screen_info.rs, screen, &screen_info.rd); +//SDL_BlitSurface(backbuffer, &screen_info.rs, screen, &screen_info.rd); + + if(SDL_MUSTLOCK(backbuffer)) { + SDL_UnlockSurface(backbuffer); + } + if(SDL_MUSTLOCK(screen)) { + SDL_UnlockSurface(screen); + } + + SDL_UpdateRect(screen, screen_info.rd.x, screen_info.rd.y, screen_info.rd.w, screen_info.rd.h); +} diff --git a/src/sdl/rom.cpp b/src/sdl/rom.cpp new file mode 100644 index 00000000..7df0f250 --- /dev/null +++ b/src/sdl/rom.cpp @@ -0,0 +1,99 @@ +class ROMImage { +private: +char rom_fn[4096]; +char sram_fn[4096]; +bool file_loaded; + +public: + bool loaded(); + bool load(); + void unload(); + void select(char *fn); + ROMImage(); + ~ROMImage(); +}; + +bool ROMImage::loaded() { + return file_loaded; +} + +bool ROMImage::load() { + if(file_loaded == true)return false; + + dprintf("* Loading \"%s\"...", rom_fn); + +FileReader *rf = new FileReader(); + if(!rf->open(FileReader::TYPE_ROM, rom_fn)) { + alert("Error loading image file [%s]!", rom_fn); + return false; + } + mem_bus->load_cart(static_cast(rf)); + rf->close(); + +CartInfo ci; + mem_bus->get_cartinfo(&ci); + if(ci.sram_size != 0) { + rf->open(FileReader::TYPE_SRAM, sram_fn); + mem_bus->load_sram(static_cast(rf)); + rf->close(); + } + + delete(rf); + + file_loaded = true; + return true; +} + +void ROMImage::unload() { + if(file_loaded == false)return; + +FileWriter *wf; +CartInfo ci; + mem_bus->get_cartinfo(&ci); + if(ci.sram_size != 0) { + wf = new FileWriter(); + wf->open(sram_fn); + mem_bus->save_sram(static_cast(wf)); + wf->close(); + delete(wf); + } + + file_loaded = false; + + mem_bus->unload_cart(); +} + +void ROMImage::select(char *fn) { +int i; + if(file_loaded == true)return; + +/* Remove quotes */ + if(fn[0] == '\"') { + strcpy(rom_fn, fn + 1); + rom_fn[strlen(rom_fn) - 1] = 0; + } else { + strcpy(rom_fn, fn); + } + + for(i=strlen(rom_fn)-1;i>=0;i--) { + if(rom_fn[i] == '.')break; + } + + strcpy(sram_fn, rom_fn); + if(rom_fn[i] == '.')sram_fn[i] = 0; + strcat(sram_fn, ".srm"); +} + +ROMImage::ROMImage() { + *rom_fn = 0; + *sram_fn = 0; + file_loaded = false; +} + +ROMImage::~ROMImage() { + if(file_loaded == true) { + unload(); + } +} + +ROMImage *rom_image; diff --git a/src/sdl/sdlmain.cpp b/src/sdl/sdlmain.cpp new file mode 100644 index 00000000..1648d9b1 --- /dev/null +++ b/src/sdl/sdlmain.cpp @@ -0,0 +1,181 @@ +#define _WIN32_ + +#define INTERFACE_MAIN +#define BSNES_VERSION "0.010" +#define BSNES_TITLE "bsnes/SDL v" BSNES_VERSION +#include "sdlmain.h" +#include "../base.h" + +#ifdef _WIN32_ +HWND hwnd; +#endif + +#include "config.cpp" +#include "bsnes.h" +#include "rom.cpp" +#include "render.cpp" +#include "bsnes.cpp" + +void *memalloc(uint32 size, char *name, ...) { + return (void*)malloc(size); +} + +void memfree(void *mem, char *name, ...) { + free(mem); +} + +void alert(char *s, ...) { +char str[4096]; +va_list args; + va_start(args, s); + vsprintf(str, s, args); + va_end(args); +#ifdef _WIN32_ + MessageBox(0, str, "bsnes", MB_OK); +#else + fprintf(stdout, "%s\r\n", str); +#endif +} + +void dprintf(char *s, ...) { +char str[4096]; +va_list args; + va_start(args, s); + vsprintf(str, s, args); + va_end(args); + fprintf(stdout, "%s\r\n", str); +} + +void init_snes() { + mem_bus = new bMemBus(); + cpu = new bCPU(); + if(cfg.apu.enabled) { + apu = new bAPU(); + } else { + apu = new bAPUSkip(); + } + ppu = new bPPU(); + snes = new bSNES(); + bsnes = static_cast(snes); +} + +void term_snes() { + if(mem_bus) { delete(mem_bus); mem_bus = 0; } + if(cpu) { delete(cpu); cpu = 0; } + if(apu) { delete(apu); apu = 0; } + if(ppu) { delete(ppu); ppu = 0; } + if(snes) { delete(snes); snes = 0; } +} + +void center_window() { +#ifdef _WIN32_ +RECT rc; +int x, y; + GetWindowRect(hwnd, &rc); + x = (GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) >> 1; + y = (GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) >> 1; + SetWindowPos(hwnd, HWND_TOPMOST, x, y, 0, 0, SWP_NOSIZE); +#endif +} + +void set_window_info() { +//SDL won't draw anything if you blit an image that's larger than +//the display mode/window, even if you use the SoftStretch blit and +//clip the source + dest rectangles properly... + if(cfg.video.display_width < cfg.video.output_width) { + cfg.video.display_width = cfg.video.output_width; + } + if(cfg.video.display_height < cfg.video.output_height) { + cfg.video.display_height = cfg.video.output_height; + } + + screen_info.rd.x = (cfg.video.display_width - cfg.video.output_width ) >> 1; + screen_info.rd.y = (cfg.video.display_height - cfg.video.output_height) >> 1; + screen_info.rd.w = cfg.video.output_width; + screen_info.rd.h = cfg.video.output_height; + + screen_info.rs.x = 0; + screen_info.rs.y = 0; + screen_info.rs.w = 256; + screen_info.rs.h = 223; +} + +#ifdef _WIN32_ +int __stdcall WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) { +int argc = __argc; +char **argv = __argv; +#else +int main(int argc, char *argv[]) { +#endif + +SDL_Event event; + + if(argc < 2) { + alert("Usage: bsnes_sdl "); + return 0; + } + + cfg.load("bsnes_sdl.cfg"); + + rom_image = new ROMImage(); + init_snes(); + + rom_image->select(argv[1]); + rom_image->load(); + snes->power(); + + if(rom_image->loaded() == false) { + alert("Failed to load image. Usage: bsnes_sdl "); + goto _end; + } + + SDL_Init(SDL_INIT_VIDEO); + atexit(SDL_Quit); + set_window_info(); + screen = SDL_SetVideoMode(cfg.video.display_width, cfg.video.display_height, 16, + SDL_SWSURFACE | ((cfg.video.fullscreen)?SDL_FULLSCREEN:0)); + if(!screen) { + alert("Failed to initialize SDL"); + goto _end; + } + backbuffer = SDL_CreateRGBSurface(SDL_SWSURFACE, 256, 223, 16, 0xf800, 0x07e0, 0x001f, 0x0000); + + SDL_WM_SetCaption(BSNES_TITLE, 0); +#ifdef _WIN32_ + hwnd = FindWindow(0, BSNES_TITLE); +#endif + center_window(); + + update_color_lookup_table(); + bsnes->set_status(bSNES::RUN); + +int cursor_status; + while(1) { + bsnes->snes_run(); + while(SDL_PollEvent(&event)) { + switch(event.type) { + case SDL_KEYUP: + switch(event.key.keysym.sym) { + case SDLK_ESCAPE: + goto _end; + case SDLK_F10: //toggle cursor display + cursor_status = (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE)?SDL_DISABLE:SDL_ENABLE; + SDL_ShowCursor(cursor_status); + break; + case SDLK_F11: //only supported on X11 + SDL_WM_ToggleFullScreen(screen); + break; + } + break; + case SDL_QUIT: + goto _end; + } + } + } + +_end: + cfg.save("bsnes_sdl.cfg"); + term_snes(); + + return 0; +} diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h new file mode 100644 index 00000000..d86de697 --- /dev/null +++ b/src/sdl/sdlmain.h @@ -0,0 +1,17 @@ +#ifdef _WIN32_ +#include +#include +#else +#include "SDL.h" +#endif + +#include "../lib/libbase.h" +#include "../lib/libvector.h" +#include "../lib/libstring.h" +#include "../lib/libconfig.h" + +SDL_Surface *screen, *backbuffer; + +struct { +SDL_Rect rs, rd; +}screen_info; diff --git a/src/sdl/sdlrun.bat b/src/sdl/sdlrun.bat new file mode 100644 index 00000000..2aaf95ea --- /dev/null +++ b/src/sdl/sdlrun.bat @@ -0,0 +1 @@ +c:\root\bsnes_g2\bsnes_sdl.exe c:\root\bsnes_testrom\zelda_us.smc \ No newline at end of file diff --git a/src/snes/snes.cpp b/src/snes/snes.cpp index a5510833..9ba56f14 100644 --- a/src/snes/snes.cpp +++ b/src/snes/snes.cpp @@ -1,22 +1,28 @@ #include "../base.h" void SNES::run() { - clock->run(); + cpu->run(); } void SNES::power() { - clock->power(); cpu->power(); + apu->power(); ppu->power(); +//clock->power(); mem_bus->power(); int i; mem_bus->flush_mmio_mappers(); for(i=0x2100;i<=0x213f;i++)mem_bus->set_mmio_mapper(i, ppu->mmio); - for(i=0x2140;i<=0x2143;i++)mem_bus->set_mmio_mapper(i, ppu->mmio); + for(i=0x2140;i<=0x217f;i++)mem_bus->set_mmio_mapper(i, cpu->mmio); for(i=0x2180;i<=0x2183;i++)mem_bus->set_mmio_mapper(i, cpu->mmio); +//unknown mem_bus->set_mmio_mapper(0x21c2, cpu->mmio); mem_bus->set_mmio_mapper(0x21c3, cpu->mmio); +//S-RTC + mem_bus->set_mmio_mapper(0x2800, cpu->mmio); + mem_bus->set_mmio_mapper(0x2801, cpu->mmio); +//input mem_bus->set_mmio_mapper(0x4016, cpu->mmio); mem_bus->set_mmio_mapper(0x4017, cpu->mmio); for(i=0x4200;i<=0x421f;i++)mem_bus->set_mmio_mapper(i, cpu->mmio); @@ -24,9 +30,10 @@ int i; } void SNES::reset() { - clock->reset(); cpu->reset(); + apu->reset(); ppu->reset(); +//clock->reset(); mem_bus->reset(); } diff --git a/src/snes/snes.h b/src/snes/snes.h index aeff4b21..b66abed2 100644 --- a/src/snes/snes.h +++ b/src/snes/snes.h @@ -4,7 +4,7 @@ bool is_debugger_enabled; public: //system functions - virtual void run(); + void run(); virtual void render_frame() = 0; virtual void power(); virtual void reset(); @@ -29,11 +29,13 @@ enum { enum { NO_ACTION = 0, RENDER_FRAME, - CPU_EXEC_OPCODE, - MEM_READ, MEM_WRITE, - VRAM_READ, VRAM_WRITE, - OAM_READ, OAM_WRITE, - CGRAM_READ, CGRAM_WRITE, + CPU_EXEC_OPCODE_BEGIN, CPU_EXEC_OPCODE_END, + APU_EXEC_OPCODE_BEGIN, APU_EXEC_OPCODE_END, + MEM_READ, MEM_WRITE, + SPCRAM_READ, SPCRAM_WRITE, + VRAM_READ, VRAM_WRITE, + OAM_READ, OAM_WRITE, + CGRAM_READ, CGRAM_WRITE, }; virtual void notify(uint32 message, uint32 param1 = 0, uint32 param2 = 0); virtual void debugger_enable(); diff --git a/src/win/Makefile b/src/win/Makefile index 40414f21..ceb050d9 100644 --- a/src/win/Makefile +++ b/src/win/Makefile @@ -2,16 +2,17 @@ CC = cl CFLAGS = /nologo /O2 /Ogityb2 /Gr /Gs OBJS = winmain.obj \ libstring.obj libconfig.obj \ - clock.obj bclock.obj \ - memory.obj bmemory.obj \ reader.obj \ + memory.obj bmemory.obj \ cpu.obj bcpu.obj \ + apu.obj bapu.obj bapuskip.obj \ ppu.obj bppu.obj \ snes.obj LIBS = kernel32.lib user32.lib gdi32.lib comdlg32.lib ddraw.lib dxguid.lib all: $(OBJS) - $(CC) /Febsnes_g2.exe $(CFLAGS) $(OBJS) $(LIBS) + rc /r /fobsnes.res bsnes.rc + $(CC) /Febsnes.exe $(CFLAGS) $(OBJS) bsnes.res $(LIBS) clean: del *.obj @@ -30,15 +31,6 @@ libstring.obj: ../lib/*.cpp ../lib/*.h libconfig.obj: ../lib/*.cpp ../lib/*.h $(CC) $(CFLAGS) /c ../lib/libconfig.cpp -############# -### clock ### -############# -clock.obj: ../clock/*.cpp ../clock/*.h - $(CC) $(CFLAGS) /c ../clock/clock.cpp - -bclock.obj: ../clock/bclock/* - $(CC) $(CFLAGS) /c ../clock/bclock/bclock.cpp - ############## ### memory ### ############## @@ -57,6 +49,18 @@ cpu.obj: ../cpu/*.cpp ../cpu/*.h bcpu.obj: ../cpu/bcpu/* $(CC) $(CFLAGS) /c ../cpu/bcpu/bcpu.cpp +########### +### apu ### +########### +apu.obj: ../apu/* + $(CC) $(CFLAGS) /c ../apu/apu.cpp + +bapu.obj: ../apu/bapu/* + $(CC) $(CFLAGS) /c ../apu/bapu/bapu.cpp + +bapuskip.obj: ../apu/bapuskip/* + $(CC) $(CFLAGS) /c ../apu/bapuskip/bapuskip.cpp + ########### ### ppu ### ########### diff --git a/src/win/bsnes.cpp b/src/win/bsnes.cpp index 91738a51..c8063fed 100644 --- a/src/win/bsnes.cpp +++ b/src/win/bsnes.cpp @@ -6,6 +6,7 @@ uint8 cpu_op; case STOP: w_console->is_running(false); w_console->update_status(); + w_memory->refresh(); break; case RUNTOCPUSTEP: status.cpu_ran = false; @@ -21,6 +22,9 @@ uint8 cpu_op; run_status = RUNTOCPUSTEP; } break; + case RUNTOAPUSTEP: + status.apu_ran = false; + break; } } @@ -28,60 +32,73 @@ uint32 bSNES::get_status() { return run_status; } -void bSNES::run() { +void bSNES::snes_run() { if(!rom_image->loaded())return; switch(run_status) { case RUN: while(update_frame == false) { - clock->run(); + run(); } update_frame = false; return; case STOP: break; case RUNONCE: - clock->run(); + run(); set_status(STOP); break; case RUNTOSIGNAL: - clock->run(); + run(); if(w_bp->hit() == true) { set_status(STOP); - disassemble_cpu_op(); + disassemble_bp_op(); } break; case RUNTOFRAME: - clock->run(); + run(); if(update_frame == true) { update_frame = false; + set_status(STOP); + disassemble_apu_op(); + disassemble_cpu_op(); + } else if(w_bp->hit() == true) { + set_status(STOP); + disassemble_bp_op(); + } + return; + case RUNTOCPUSTEP: + run(); + if(status.cpu_ran == true) { + set_status(STOP); + } else if(w_bp->hit() == true) { + set_status(STOP); + disassemble_bp_op(); + } + break; + case RUNTOCPUPROCEED: + run(); + if(status.cpu_stop_pos == cpu->regs.pc) { set_status(STOP); disassemble_cpu_op(); } else if(w_bp->hit() == true) { set_status(STOP); - disassemble_cpu_op(); - } - return; - case RUNTOCPUSTEP: - clock->run(); - if(status.cpu_ran == true || w_bp->hit() == true) { - set_status(STOP); - } - break; - case RUNTOCPUPROCEED: - clock->run(); - if(status.cpu_stop_pos == cpu->regs.pc || w_bp->hit() == true) { - set_status(STOP); - disassemble_cpu_op(); + disassemble_bp_op(); } break; case RUNTOCPUTRACE: - clock->run(); + run(); if(status.cpu_trace_pos >= status.cpu_trace_stop) { set_status(STOP); disassemble_cpu_op(); } break; + case RUNTOAPUSTEP: + run(); + if(status.apu_ran == true || w_bp->hit() == true) { + set_status(STOP); + } + break; } } @@ -92,22 +109,26 @@ void bSNES::render_frame() { /*********************** *** Input functions *** ***********************/ -#define KeyState(key) ((GetAsyncKeyState(key) & 0x8000)?1:0) void bSNES::poll_input() { /* Only capture input when main window has focus */ if(GetForegroundWindow() == w_main->hwnd) { - joypad1.up = KeyState(VK_UP); - joypad1.down = KeyState(VK_DOWN); - joypad1.left = KeyState(VK_LEFT); - joypad1.right = KeyState(VK_RIGHT); - joypad1.select = KeyState(VK_LSHIFT) | KeyState(VK_RSHIFT); - joypad1.start = KeyState(VK_RETURN); - joypad1.y = KeyState('A'); - joypad1.b = KeyState('Z'); - joypad1.x = KeyState('S'); - joypad1.a = KeyState('X'); - joypad1.l = KeyState('D'); - joypad1.r = KeyState('C'); + joypad1.up = KeyDown(cfg.input.joypad1.up); + joypad1.down = KeyDown(cfg.input.joypad1.down); + joypad1.left = KeyDown(cfg.input.joypad1.left); + joypad1.right = KeyDown(cfg.input.joypad1.right); + joypad1.select = KeyDown(cfg.input.joypad1.select); + joypad1.start = KeyDown(cfg.input.joypad1.start); + joypad1.y = KeyDown(cfg.input.joypad1.y); + joypad1.b = KeyDown(cfg.input.joypad1.b); + joypad1.x = KeyDown(cfg.input.joypad1.x); + joypad1.a = KeyDown(cfg.input.joypad1.a); + joypad1.l = KeyDown(cfg.input.joypad1.l); + joypad1.r = KeyDown(cfg.input.joypad1.r); + } else { + joypad1.up = joypad1.down = joypad1.left = joypad1.right = + joypad1.select = joypad1.start = + joypad1.y = joypad1.b = joypad1.x = joypad1.a = + joypad1.l = joypad1.r = 0; } //Check for debugger-based key locks @@ -175,7 +196,7 @@ uint8 r = 0x00; a = addr & 0xffff; if((bank >= 0x00 && bank <= 0x3f) || (bank >= 0x80 && bank <= 0xbf)) { - /* Don't let the debugger poll MMIO ports */ + //don't let the debugger poll MMIO ports if(a >= 0x2000 && a <= 0x5fff) { r = 0x00; } else { @@ -185,6 +206,10 @@ uint8 r = 0x00; r = mem_bus->read(addr); } break; + case SPCRAM: + addr &= 0xffff; + r = apu->spcram_read(addr); + break; case VRAM: addr &= 0xffff; r = ppu->vram_read(addr); @@ -207,9 +232,13 @@ void bSNES::write(uint8 type, uint32 addr, uint8 value) { switch(type) { case DRAM: addr &= 0xffffff; - mem_bus->rom->write_protect(false); + mem_bus->cart->write_protect(false); mem_bus->write(addr, value); - mem_bus->rom->write_protect(true); + mem_bus->cart->write_protect(true); + break; + case SPCRAM: + addr &= 0xffff; + apu->spcram_write(addr, value); break; case VRAM: addr &= 0xffff; @@ -228,7 +257,7 @@ void bSNES::write(uint8 type, uint32 addr, uint8 value) { } void bSNES::notify(uint32 message, uint32 param1, uint32 param2) { -/* system messages */ +//system messages switch(message) { case RENDER_FRAME: update_frame = true; @@ -236,17 +265,27 @@ void bSNES::notify(uint32 message, uint32 param1, uint32 param2) { break; } -/* debugging messages */ +//debugging messages if(is_debugger_enabled == false)return; switch(message) { - case CPU_EXEC_OPCODE: + case CPU_EXEC_OPCODE_BEGIN: + break; + case CPU_EXEC_OPCODE_END: status.cpu_ran = true; status.cpu_trace_pos++; w_bp->test(message, cpu->regs.pc.d, 0); disassemble_cpu_op(); break; + case APU_EXEC_OPCODE_BEGIN: + break; + case APU_EXEC_OPCODE_END: + status.apu_ran = true; + w_bp->test(message, apu->regs.pc, 0); + disassemble_apu_op(); + break; case MEM_READ: + case SPCRAM_READ: case VRAM_READ: case OAM_READ: case CGRAM_READ: @@ -255,14 +294,15 @@ void bSNES::notify(uint32 message, uint32 param1, uint32 param2) { } break; case MEM_WRITE: + case SPCRAM_WRITE: case VRAM_WRITE: case OAM_WRITE: case CGRAM_WRITE: if(debug_command == false) { w_bp->test(message, param1, param2); } - /* this needs to be called after the breakpoint test, - as it will access read() and clear debug_command */ + //this needs to be called after the breakpoint test, + //as it will access read() and clear debug_command w_memory->refresh(message, param1); break; } @@ -270,16 +310,34 @@ void bSNES::notify(uint32 message, uint32 param1, uint32 param2) { void bSNES::disassemble_cpu_op() { char t[512]; -/* don't disassemble opcodes when no ROM is loaded */ +//don't disassemble opcodes when no ROM is loaded if(is_debugger_activated == false)return; -/* don't disassemble opcodes that won't be printed to console/traced to log anyway */ +//don't disassemble opcodes that won't be printed to console/traced to log anyway if(!w_console->can_write(Console::CPU_MESSAGE) && !w_console->tracing_enabled)return; cpu->disassemble_opcode(t); w_console->write(t, Console::CPU_MESSAGE); } +void bSNES::disassemble_apu_op() { +char t[512]; + if(is_debugger_activated == false)return; + + if(!w_console->can_write(Console::APU_MESSAGE) && !w_console->tracing_enabled)return; + + apu->disassemble_opcode(t); + w_console->write(t, Console::APU_MESSAGE); +} + +void bSNES::disassemble_bp_op() { + if(w_bp->bp[w_bp->bp_hit_num].source == SPCRAM) { + disassemble_apu_op(); + } else { + disassemble_cpu_op(); + } +} + bool bSNES::debugger_enabled() { return is_debugger_enabled; } @@ -319,6 +377,7 @@ void bSNES::debugger_update() { w_console->update_status(); w_bp->refresh(); w_memory->refresh(); + disassemble_apu_op(); disassemble_cpu_op(); } diff --git a/src/win/bsnes.h b/src/win/bsnes.h index bcb23c0b..049e0400 100644 --- a/src/win/bsnes.h +++ b/src/win/bsnes.h @@ -31,12 +31,13 @@ enum { RUNTOFRAME, RUNTOCPUSTEP, RUNTOCPUPROCEED, - RUNTOCPUTRACE + RUNTOCPUTRACE, + RUNTOAPUSTEP }; -enum { DRAM = 0, VRAM = 1, OAM = 2, CGRAM = 3 }; +enum { DRAM = 0, SPCRAM = 1, VRAM = 2, OAM = 3, CGRAM = 4 }; void set_status(uint32 new_status); uint32 get_status(); - void run(); + void snes_run(); void render_frame(); //input functions @@ -47,12 +48,14 @@ enum { DRAM = 0, VRAM = 1, OAM = 2, CGRAM = 3 }; struct { uint32 cpu_stop_pos; uint32 cpu_trace_pos, cpu_trace_stop; - bool cpu_ran; + bool cpu_ran, apu_ran; }status; uint8 read (uint8 type, uint32 addr); void write(uint8 type, uint32 addr, uint8 value); void notify(uint32 message, uint32 param1 = 0, uint32 param2 = 0); void disassemble_cpu_op(); + void disassemble_apu_op(); + void disassemble_bp_op(); //whether or not the user requests the debugger open bool debugger_enabled(); diff --git a/src/win/bsnes.ico b/src/win/bsnes.ico new file mode 100644 index 0000000000000000000000000000000000000000..a396add1a72bc149ec45f1cf5b39cd34a25bd022 GIT binary patch literal 4286 zcmeH}Pe@cz6o>DmIa1|IK*cf;+GiDl>7rK^g>-FbOZ<7({donjPT57$hK>YjthjzyNe)eeGEW@f1kIM>v}4@yr%7j_T1EF(_TZ=9eyD-NGne5{zWzEA^rpb?QR@1w zo4>G5@)i8PbL;TT1^j0mYtX#w>W^qA9EZKIF<+Am(K}t>OUkS|^7o!;LsM%gwFlb& z651KO3`QXh@8N#dU%zXTD(W@2hInS2XByEx0{VREbExxFzc@_55OhPM=Hqt|UW1*~ z7}tlm-3ssWVcT7_?a9{de#U15yz+UgxUPf7*atZY35Oa!ku$IN6Z*RDpCM>Mlf*C5 z#c!3|fMjr5X6SeNoZn06)?AjsRsZqwgHigFG{!9Md^&kwi;OI%kRy*2O@bd9Y~ zv9_O_ZFz0c{n!tepc_`?`$}J-wGz%l5{h}+c#52x&{|sAEd#B^a0Oia$H}{@W8Bo; zve0V-{eI1WovXjqeThL7+TB#$v(OB|VHk$O=TB>j=lXcZ{JjH@eef8bgU(rb0QaEm z^A4H`J`JFC^uY<(9hA2aTUddAWd-;fJ^M(7L}L8TL{0B+V&+41RmCGOA|ocuQy=D) uQpMlonr0K-z9}S$x{$=GDC8q3-uo;U5FdOWjCVW#*I!}7ZowK6iWThof${e>Z+UG;XCKdd7nG?P7y#P86^c? zDvI;(3xGkn73-KeeCJgJbH(Yqx5@3!mU=h#D9?zZA^C_Tj$Qt6X~9^|S9Ir{hLgG6 zgG1;V%$Gy2pHdIHm3+@Eb?c~As|_g|LmVqFM7M6jNYbN*Djyn|zTn5)H?KU_FLX(&kn!V0AH?2~t#?k9%baHTXnXDYN>IteQ_9Dxt?9;H_pq!3D7s)L&Tzc#DEsR-o?ZIyb6w7$sg@;IamBSIzpO3)7s~4WQ{u~x zxI~!ofl7H>9gJ-EHH$1zBTi@FDBSPz7pYeHh38m`+=3Py=_9ihyto3VA dxqvA`{A6{~M<-4(=kDPpJJYqO=9U<-{{W*8;VS?D literal 0 HcmV?d00001 diff --git a/src/win/bsnes.rc b/src/win/bsnes.rc new file mode 100644 index 00000000..08f24c00 --- /dev/null +++ b/src/win/bsnes.rc @@ -0,0 +1,5 @@ +#define IDB_SNES_CONTROLLER 100 +#define IDI_APP_ICON 101 + +IDB_SNES_CONTROLLER BITMAP DISCARDABLE "snes_controller.bmp" +IDI_APP_ICON ICON DISCARDABLE "bsnes.ico" diff --git a/src/win/bsnes.res b/src/win/bsnes.res new file mode 100644 index 0000000000000000000000000000000000000000..412d6082b3bd48978a73a538c1d15964c9606a6e GIT binary patch literal 244452 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 literal 0 HcmV?d00001 diff --git a/src/win/bsnes_g2.lnk b/src/win/bsnes_g2.lnk deleted file mode 100644 index 3dd9544d9dab461d1afe3e8f0dbefe01166db56b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 469 zcmeZaU|?VrVFHp23?^6@jJ@Mpm5BN2}Db+fbbtMf>lCDFcVC? zXAohK4|w2zLE)8Erof^b91Pk926H7D^qs9@5USuT69z*td%97up#VcsetrqaT4n|o zhWGnGV$+Qn6hwe3iWu^N5GV;W-T|s-hEc>a0fwaFywu|ObRz}^4X8el_zbANB!*&! zJcd*t8PAZ;093>v!Qca;fzDrOnul +@move bsnes.exe ../../bsnes.exe>nul @pause \ No newline at end of file diff --git a/src/win/config.cpp b/src/win/config.cpp index 79a0f1c5..9520d449 100644 --- a/src/win/config.cpp +++ b/src/win/config.cpp @@ -3,6 +3,10 @@ class Config : public config { public: +struct { + uint32 enabled; +}apu; + struct { uint32 mode; uint32 use_vram; @@ -10,15 +14,39 @@ struct { uint32 vblank; }video; +struct { + struct { + uint32 up, down, left, right; + uint32 a, b, x, y, l, r; + uint32 select, start; + }joypad1; +}input; + struct { uint32 show_fps; }gui; Config() { + __config_add(apu.enabled, true, TRUEFALSE); + __config_add(video.mode, 1, DEC); __config_add(video.use_vram, true, TRUEFALSE); __config_add(video.color_curve, true, ENABLED); __config_add(video.vblank, false, TRUEFALSE); - __config_add(gui.show_fps, true, TRUEFALSE); + + __config_add(input.joypad1.up, VK_UP, HEX); + __config_add(input.joypad1.down, VK_DOWN, HEX); + __config_add(input.joypad1.left, VK_LEFT, HEX); + __config_add(input.joypad1.right, VK_RIGHT, HEX); + __config_add(input.joypad1.a, 'X', HEX); + __config_add(input.joypad1.b, 'Z', HEX); + __config_add(input.joypad1.x, 'S', HEX); + __config_add(input.joypad1.y, 'A', HEX); + __config_add(input.joypad1.l, 'D', HEX); + __config_add(input.joypad1.r, 'C', HEX); + __config_add(input.joypad1.select, VK_SHIFT, HEX); + __config_add(input.joypad1.start, VK_RETURN, HEX); + + __config_add(gui.show_fps, true, TRUEFALSE); } }cfg; diff --git a/src/win/dd_renderer.cpp b/src/win/dd_renderer.cpp index 6d3d2618..4aace022 100644 --- a/src/win/dd_renderer.cpp +++ b/src/win/dd_renderer.cpp @@ -235,7 +235,7 @@ int rx, ry; lpddsb->Restore(); } - if(cfg.gui.show_fps == false)return; + if(cfg.gui.show_fps == false || bsnes->get_status() == bSNES::STOP)return; uint32 fps; char s[256], t[256]; fps_timer->tick(); diff --git a/src/win/dd_renderer16.cpp b/src/win/dd_renderer16.cpp index 00fa4b2b..0f50abb5 100644 --- a/src/win/dd_renderer16.cpp +++ b/src/win/dd_renderer16.cpp @@ -8,9 +8,9 @@ int x, y; pitch = (ddsd.lPitch >> 1) - 256; int overscan_adjust = 0; - if(clock->overscan() == true) { - src += 8 << 10; - overscan_adjust = 8; + if(cpu->overscan() == true) { + src += 7 << 10; + overscan_adjust = 7; } for(y=1+overscan_adjust;y<224+overscan_adjust;y++) { @@ -34,9 +34,9 @@ int x, y; pitch = (ddsd.lPitch >> 1) - 256; int overscan_adjust = 0; - if(clock->overscan() == true) { - src += 8 << 10; - overscan_adjust = 16; + if(cpu->overscan() == true) { + src += 7 << 10; + overscan_adjust = 14; } for(y=2+overscan_adjust;y<448+overscan_adjust;y++) { @@ -62,9 +62,9 @@ int x, y; pitch = (ddsd.lPitch >> 1) - 512; int overscan_adjust = 0; - if(clock->overscan() == true) { - src += 8 << 10; - overscan_adjust = 8; + if(cpu->overscan() == true) { + src += 7 << 10; + overscan_adjust = 7; } for(y=1+overscan_adjust;y<224+overscan_adjust;y++) { @@ -96,9 +96,9 @@ int x, y; pitch = (ddsd.lPitch >> 1) - 512; int overscan_adjust = 0; - if(clock->overscan() == true) { - src += 8 << 10; - overscan_adjust = 16; + if(cpu->overscan() == true) { + src += 7 << 10; + overscan_adjust = 14; } for(y=2+overscan_adjust;y<448+overscan_adjust;y++) { diff --git a/src/win/dd_renderer32.cpp b/src/win/dd_renderer32.cpp index 9a097583..6b4893ea 100644 --- a/src/win/dd_renderer32.cpp +++ b/src/win/dd_renderer32.cpp @@ -8,9 +8,9 @@ int x, y; pitch = (ddsd.lPitch >> 2) - 256; int overscan_adjust = 0; - if(clock->overscan() == true) { - src += 8 << 10; - overscan_adjust = 8; + if(cpu->overscan() == true) { + src += 7 << 10; + overscan_adjust = 7; } for(y=1+overscan_adjust;y<224+overscan_adjust;y++) { @@ -34,9 +34,9 @@ int x, y; pitch = (ddsd.lPitch >> 2) - 256; int overscan_adjust = 0; - if(clock->overscan() == true) { - src += 8 << 10; - overscan_adjust = 16; + if(cpu->overscan() == true) { + src += 7 << 10; + overscan_adjust = 14; } for(y=2+overscan_adjust;y<448+overscan_adjust;y++) { @@ -62,9 +62,9 @@ int x, y; pitch = (ddsd.lPitch >> 2) - 512; int overscan_adjust = 0; - if(clock->overscan() == true) { - src += 8 << 10; - overscan_adjust = 8; + if(cpu->overscan() == true) { + src += 7 << 10; + overscan_adjust = 7; } for(y=1+overscan_adjust;y<224+overscan_adjust;y++) { @@ -96,9 +96,9 @@ int x, y; pitch = (ddsd.lPitch >> 2) - 512; int overscan_adjust = 0; - if(clock->overscan() == true) { - src += 8 << 10; - overscan_adjust = 16; + if(cpu->overscan() == true) { + src += 7 << 10; + overscan_adjust = 14; } for(y=2+overscan_adjust;y<448+overscan_adjust;y++) { diff --git a/src/win/lib.cpp b/src/win/lib.cpp index 03e21d53..5f54aff3 100644 --- a/src/win/lib.cpp +++ b/src/win/lib.cpp @@ -60,10 +60,10 @@ va_list args; void dprintf(char *s, ...) { char str[4096]; va_list args; + if(!w_console)return; + if(!w_console->can_write(Console::DEBUG_MESSAGE))return; va_start(args, s); vsprintf(str, s, args); va_end(args); - if(w_console) { - w_console->write(str, Console::DEBUG_MESSAGE); - } + w_console->write(str, Console::DEBUG_MESSAGE); } diff --git a/src/win/rom.cpp b/src/win/rom.cpp index 7e700d59..282be928 100644 --- a/src/win/rom.cpp +++ b/src/win/rom.cpp @@ -20,19 +20,23 @@ bool ROMImage::loaded() { bool ROMImage::load() { if(file_loaded == true)return false; - dprintf("* Loading [%s]...", rom_fn); + dprintf("* Loading \"%s\"...", rom_fn); FileReader *rf = new FileReader(); if(!rf->open(FileReader::TYPE_ROM, rom_fn)) { alert("Error loading image file [%s]!", rom_fn); return false; } - mem_bus->rom->load_rom(static_cast(rf)); + mem_bus->load_cart(static_cast(rf)); rf->close(); - rf->open(FileReader::TYPE_SRAM, sram_fn); - mem_bus->rom->load_sram(static_cast(rf)); - rf->close(); +CartInfo ci; + mem_bus->get_cartinfo(&ci); + if(ci.sram_size != 0) { + rf->open(FileReader::TYPE_SRAM, sram_fn); + mem_bus->load_sram(static_cast(rf)); + rf->close(); + } delete(rf); @@ -44,19 +48,25 @@ FileReader *rf = new FileReader(); void ROMImage::unload() { if(file_loaded == false)return; -FileWriter *wf = new FileWriter(); - wf->open(sram_fn); - mem_bus->rom->save_sram(static_cast(wf)); - wf->close(); - delete(wf); +FileWriter *wf; +CartInfo ci; + mem_bus->get_cartinfo(&ci); + if(ci.sram_size != 0) { + wf = new FileWriter(); + wf->open(sram_fn); + mem_bus->save_sram(static_cast(wf)); + wf->close(); + delete(wf); + } file_loaded = false; bsnes->debugger_deactivate(); - mem_bus->rom->unload(); + mem_bus->unload_cart(); } void ROMImage::select(char *fn) { +int i; if(file_loaded == true)return; /* Remove quotes */ @@ -67,7 +77,7 @@ void ROMImage::select(char *fn) { strcpy(rom_fn, fn); } - for(int i=strlen(rom_fn)-1;i>=0;i--) { + for(i=strlen(rom_fn)-1;i>=0;i--) { if(rom_fn[i] == '.')break; } diff --git a/src/win/snes_controller.bmp b/src/win/snes_controller.bmp new file mode 100644 index 0000000000000000000000000000000000000000..90b6265e64ef4dad722b2c2450e9ea44e6d152f2 GIT binary patch literal 240054 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 &2Nd{sy#HE<%Nk~SN>Y6q`)YUE1@ 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 + w_console->create(); + w_bp->create(); + w_memory->create(); + w_inputconfig->create(); + w_about->create(); } void init_ui0() { - dd_renderer = new DDRenderer(); - w_main = new MainWindow(); - w_console = new Console(); - w_bp = new BreakpointEditor(); - w_memory = new MemoryEditor(); + dd_renderer = new DDRenderer(); + w_main = new MainWindow(); + w_console = new Console(); + w_bp = new BreakpointEditor(); + w_memory = new MemoryEditor(); + w_inputconfig = new InputConfig(); + w_about = new AboutWindow(); } void init_ui1() { diff --git a/src/win/ui.h b/src/win/ui.h index 41d27037..eda78049 100644 --- a/src/win/ui.h +++ b/src/win/ui.h @@ -1,3 +1,5 @@ +#define KeyDown(key) ((GetAsyncKeyState(key) & 0x8000)?1:0) + enum { VIDEOMODE_256x224w = 0, VIDEOMODE_512x448w, @@ -31,7 +33,10 @@ enum { MENU_SETTINGS_VBLANK, MENU_SETTINGS_COLORCURVE, MENU_SETTINGS_SHOWFPS, - MENU_SETTINGS_DEBUGGER + MENU_SETTINGS_APUENABLED, + MENU_SETTINGS_INPUTCFG_JOYPAD1, + MENU_SETTINGS_DEBUGGER, + MENU_MISC_ABOUT }; enum { @@ -118,14 +123,13 @@ enum { MEMORYEDITOR_FSOURCE, MEMORYEDITOR_FEXPORT, - MEMORYEDITOR_UP40, - MEMORYEDITOR_DOWN40, - MEMORYEDITOR_UP400, - MEMORYEDITOR_DOWN400, - MEMORYEDITOR_UP4000, - MEMORYEDITOR_DOWN4000, - MEMORYEDITOR_UP40000, - MEMORYEDITOR_DOWN40000 + MEMORYEDITOR_UPDATE, + MEMORYEDITOR_AUTOUPDATE +}; + +enum { + ABOUT_STATIC = 100, + ABOUT_OK }; class Window { @@ -156,6 +160,7 @@ class MainWindow : public Window { public: uint8 frameskip; int width, height; + void create(); void to_fullscreen(); void to_windowed(); void set_frameskip(uint8 fs); @@ -163,23 +168,22 @@ int width, height; void set_video_mode(uint8 mode); void menu_load(); void menu_unload(); +}*w_main = 0; - MainWindow(); -}; - -MainWindow *w_main; - -#define CONSOLE_LINES 256 +#define CONSOLE_LINES 240 class Console : public Window { private: bool _is_running; //used to swap "Run"/"Stop" text on console window + public: bool ctl_disabled[100]; +bool outputcpu, outputapu, outputdbg; enum { DEBUG_MESSAGE = 0, CPU_MESSAGE, APU_MESSAGE }; enum { REGTYPE_CPU = 0, REGTYPE_APU }; -char output_line[CONSOLE_LINES][512]; -char output_data[CONSOLE_LINES * 512]; +char output_line[CONSOLE_LINES][128]; +uint8 output_linecol[CONSOLE_LINES]; +char output_data[CONSOLE_LINES * 128]; FILE *log_fp; bool tracing_enabled; @@ -189,8 +193,9 @@ struct { bool l, r, select, start; }joypad_lock; + void create(); + long wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); void clear(); - void create_controls(); void update_status(); void set_reg_list_type(uint8 list_type); bool can_write(uint32 message_type); @@ -198,15 +203,13 @@ struct { void is_running(bool n); //API access to _is_running Console(); -}; - -Console *w_console; +}*w_console = 0; class BreakpointEditor : public Window { public: bool ctl_disabled[100]; -enum { DRAM = 0, VRAM = 1, OAM = 2, CGRAM = 3 }; +enum { DRAM = 0, SPCRAM = 1, VRAM = 2, OAM = 3, CGRAM = 4 }; enum { FLAG_NONE = 0, FLAG_R = 1, FLAG_W = 2, FLAG_X = 4, FLAG_V = 8 }; struct { uint32 addr; @@ -216,29 +219,54 @@ struct { uint32 hit_count; bool set; }bp[16]; -bool bp_enabled, bp_hit; +bool bp_enabled, bp_hit; +//indicates which breakpoint was hit, used to tell whether to disassemble +//a cpu or apu opcode once the emulation status is set to stop. +uint8 bp_hit_num; void clear(); - void create_controls(); + void create(); bool hit(); void test(uint32 message, uint32 addr, uint32 value); void refresh(); BreakpointEditor(); -}; - -BreakpointEditor *w_bp; +}*w_bp = 0; class MemoryEditor : public Window { public: bool ctl_disabled[100]; -enum { MODE_DRAM = 0, MODE_ROM, MODE_SRAM, MODE_VRAM, MODE_OAM, MODE_CGRAM }; +enum { MODE_DRAM = 0, MODE_ROM, MODE_SRAM, MODE_SPCRAM, MODE_VRAM, MODE_OAM, MODE_CGRAM }; uint32 edit_mode, edit_addr, edit_mask; +bool auto_update; //update memory window whenever visible value is written to when true void clear(); - void create_controls(); + void create(); uint8 read_byte(uint32 addr); - void refresh(uint32 type = 0, uint32 addr = 0); + void write_byte(uint32 addr, uint8 value); + void refresh(uint32 type = null, uint32 addr = 0); void export(uint32 type); -}; +}*w_memory = 0; -MemoryEditor *w_memory; +class InputConfig : public Window { +public: +enum { + JOYPAD1 = 0 +}; +enum { + ID_COMMAND = 100 +}; +int config_type, config_pos; +bool polling; + long wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); + void update_polling(int key); + void update_command(); + void set_text(char *str); + void begin_config(int type); + void create(); +}*w_inputconfig = 0; + +class AboutWindow : public Window { +public: + long wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); + void create(); +}*w_about = 0; diff --git a/src/win/ui_about.cpp b/src/win/ui_about.cpp new file mode 100644 index 00000000..7d8b9f74 --- /dev/null +++ b/src/win/ui_about.cpp @@ -0,0 +1,53 @@ +long AboutWindow::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + switch(msg) { + case WM_COMMAND: + switch(LOWORD(wparam)) { + case ABOUT_OK: + w_about->hide(); + break; + } + break; + case WM_CLOSE: + w_about->hide(); + return TRUE; + } + return DefWindowProc(hwnd, msg, wparam, lparam); +} + +long __stdcall wndproc_aboutwindow(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + return w_about->wndproc(hwnd, msg, wparam, lparam); +} + +void AboutWindow::create() { +WNDCLASS wc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + wc.hCursor = LoadCursor(0, IDC_ARROW); + wc.hIcon = LoadIcon(0, IDI_APPLICATION); + wc.hInstance = GetModuleHandle(0); + wc.lpfnWndProc = wndproc_aboutwindow; + wc.lpszClassName = "bsnes_aboutwindow"; + wc.lpszMenuName = 0; + wc.style = CS_HREDRAW | CS_VREDRAW; + RegisterClass(&wc); + + hwnd = CreateWindow("bsnes_aboutwindow", "About bsnes...", + WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, + 0, 0, 275, 55, 0, 0, wc.hInstance, 0); + resize(275, 55); + center(); + + CreateWindowEx(WS_EX_STATICEDGE, "STATIC", "", WS_CHILD | WS_VISIBLE, + 5, 5, 200, 45, hwnd, (HMENU)ABOUT_STATIC, wc.hInstance, 0); + SetDlgItemText(hwnd, ABOUT_STATIC, "" + " bsnes -- Version " BSNES_VERSION "\r\n" + " Written by: byuu\r\n" + " http://byuu.org/" + ); + CreateWindow("BUTTON", "OK", WS_CHILD | WS_VISIBLE, + 210, 5, 60, 20, hwnd, (HMENU)ABOUT_OK, wc.hInstance, 0); + + SendDlgItemMessage(hwnd, ABOUT_STATIC, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwnd, ABOUT_OK, WM_SETFONT, (WPARAM)hFont, TRUE); +} diff --git a/src/win/ui_bp.cpp b/src/win/ui_bp.cpp index 0a367035..af88494e 100644 --- a/src/win/ui_bp.cpp +++ b/src/win/ui_bp.cpp @@ -1,4 +1,5 @@ bool BreakpointEditor::hit() { +//breakpoints are disabled when BP window is closed if(visible == false)return false; if(bp_hit == true) { @@ -17,7 +18,7 @@ int i; if(bp[i].set == false)continue; switch(message) { - case SNES::CPU_EXEC_OPCODE: + case SNES::CPU_EXEC_OPCODE_END: if(!(bp[i].flags & FLAG_X))continue; if(bp[i].source != DRAM)continue; if(bp[i].addr != addr)continue; @@ -26,13 +27,24 @@ int i; bp_hit = true; w_bp->refresh(); break; + case SNES::APU_EXEC_OPCODE_END: + if(!(bp[i].flags & FLAG_X))continue; + if(bp[i].source != SPCRAM)continue; + if(bp[i].addr != addr)continue; + dprintf("* Breakpoint %d hit (exec)", i); + bp[i].hit_count++; + bp_hit = true; + w_bp->refresh(); + break; case SNES::MEM_READ: + case SNES::SPCRAM_READ: case SNES::VRAM_READ: case SNES::OAM_READ: case SNES::CGRAM_READ: if(!(bp[i].flags & FLAG_R))continue; if(bp[i].addr != addr)continue; if(message == SNES::MEM_READ && bp[i].source == DRAM); + else if(message == SNES::SPCRAM_READ && bp[i].source == SPCRAM); else if(message == SNES::VRAM_READ && bp[i].source == VRAM); else if(message == SNES::OAM_READ && bp[i].source == OAM); else if(message == SNES::CGRAM_READ && bp[i].source == CGRAM); @@ -46,12 +58,14 @@ int i; w_bp->refresh(); break; case SNES::MEM_WRITE: + case SNES::SPCRAM_WRITE: case SNES::VRAM_WRITE: case SNES::OAM_WRITE: case SNES::CGRAM_WRITE: if(!(bp[i].flags & FLAG_W))continue; if(bp[i].addr != addr)continue; if(message == SNES::MEM_WRITE && bp[i].source == DRAM); + else if(message == SNES::SPCRAM_WRITE && bp[i].source == SPCRAM); else if(message == SNES::VRAM_WRITE && bp[i].source == VRAM); else if(message == SNES::OAM_WRITE && bp[i].source == OAM); else if(message == SNES::CGRAM_WRITE && bp[i].source == CGRAM); @@ -65,13 +79,24 @@ int i; w_bp->refresh(); break; } + if(bp_hit == true) { + bp_hit_num = i; + } } } long __stdcall wndproc_bp(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { char t[256]; uint32 n, addr; +HDC hdc; switch(msg) { + case WM_CTLCOLORSTATIC: + if((HWND)lparam != GetDlgItem(hwnd, BREAKPOINT_LIST))break; + hdc = (HDC)wparam; + SetTextColor(hdc, RGB(255, 255, 255)); + SetBkColor(hdc, RGB(0, 0, 0)); + SetBkMode(hdc, TRANSPARENT); + return (long)hbr_backbrush; case WM_COMMAND: switch(LOWORD(wparam)) { case BREAKPOINT_SET: @@ -136,32 +161,6 @@ uint32 n, addr; return DefWindowProc(hwnd, msg, wparam, lparam); } -void CreateWindowBreakpoint() { -WNDCLASS wc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hbrBackground = (HBRUSH)COLOR_WINDOW; - wc.hCursor = LoadCursor(0, IDC_ARROW); - wc.hIcon = LoadIcon(0, IDI_APPLICATION); - wc.hInstance = GetModuleHandle(0); - wc.lpfnWndProc = wndproc_bp; - wc.lpszClassName = "bsnes_breakpoint"; - wc.lpszMenuName = 0; - wc.style = CS_HREDRAW | CS_VREDRAW; - RegisterClass(&wc); - - w_bp->hwnd = CreateWindow("bsnes_breakpoint", "bsnes breakpoint editor", - WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, - 0, 0, 395, 245, - 0, 0, GetModuleHandle(0), 0); - - w_bp->resize(395, 245); - w_bp->to_left(); - w_bp->to_bottom(w_console->hwnd); - - w_bp->create_controls(); -} - void BreakpointEditor::clear() { SetDlgItemText(hwnd, BREAKPOINT_LIST, ""); } @@ -175,11 +174,12 @@ char s[256 * 16], t[256], source[256], v[16]; for(int i=0;i<16;i++) { if(bp[i].set == true) { switch(bp[i].source) { - case DRAM: strcpy(source, "DRAM ");break; - case VRAM: strcpy(source, "VRAM ");break; - case OAM: strcpy(source, "OAM ");break; - case CGRAM:strcpy(source, "CGRAM ");break; - default: strcpy(source, "??????");break; + case DRAM: strcpy(source, "DRAM ");break; + case SPCRAM:strcpy(source, "SPCRAM");break; + case VRAM: strcpy(source, "VRAM ");break; + case OAM: strcpy(source, "OAM ");break; + case CGRAM: strcpy(source, "CGRAM ");break; + default: strcpy(source, "??????");break; } if(bp[i].flags & FLAG_V)sprintf(v, "%0.2x", bp[i].value); else strcpy(v, "--"); @@ -197,7 +197,29 @@ char s[256 * 16], t[256], source[256], v[16]; SetDlgItemText(hwnd, BREAKPOINT_LIST, s); } -void BreakpointEditor::create_controls() { +void BreakpointEditor::create() { +WNDCLASS wc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + wc.hCursor = LoadCursor(0, IDC_ARROW); + wc.hIcon = LoadIcon(0, IDI_APPLICATION); + wc.hInstance = GetModuleHandle(0); + wc.lpfnWndProc = wndproc_bp; + wc.lpszClassName = "bsnes_breakpoint"; + wc.lpszMenuName = 0; + wc.style = CS_HREDRAW | CS_VREDRAW; + RegisterClass(&wc); + + hwnd = CreateWindow("bsnes_breakpoint", "bsnes Breakpoint Editor", + WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, + 0, 0, 395, 245, + 0, 0, GetModuleHandle(0), 0); + + resize(395, 245); + to_left(); + to_bottom(w_console->hwnd); + CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_READONLY, 5, 5, 260, 235, hwnd, (HMENU)BREAKPOINT_LIST, GetModuleHandle(0), 0); @@ -243,6 +265,7 @@ void BreakpointEditor::create_controls() { CreateWindow("COMBOBOX", "", WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS, 305, 75, 85, 200, hwnd, (HMENU)BREAKPOINT_SOURCE, GetModuleHandle(0), 0); SendDlgItemMessage(hwnd, BREAKPOINT_SOURCE, CB_ADDSTRING, 0, (LPARAM)"DRAM"); + SendDlgItemMessage(hwnd, BREAKPOINT_SOURCE, CB_ADDSTRING, 0, (LPARAM)"SPCRAM"); SendDlgItemMessage(hwnd, BREAKPOINT_SOURCE, CB_ADDSTRING, 0, (LPARAM)"VRAM"); SendDlgItemMessage(hwnd, BREAKPOINT_SOURCE, CB_ADDSTRING, 0, (LPARAM)"OAM"); SendDlgItemMessage(hwnd, BREAKPOINT_SOURCE, CB_ADDSTRING, 0, (LPARAM)"CGRAM"); @@ -254,7 +277,7 @@ void BreakpointEditor::create_controls() { 330, 100, 60, 20, hwnd, (HMENU)BREAKPOINT_CLEAR, GetModuleHandle(0), 0); CreateWindow("BUTTON", "Enable Breakpoints", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, - 270, 160, 120, 15, hwnd, (HMENU)BREAKPOINT_ENABLE, GetModuleHandle(0), 0); + 270, 163, 120, 15, hwnd, (HMENU)BREAKPOINT_ENABLE, GetModuleHandle(0), 0); SendDlgItemMessage(hwnd, BREAKPOINT_ENABLE, BM_SETCHECK, (WPARAM)true, 0); CreateWindow("BUTTON", "Clear All Breakpoints", WS_CHILD | WS_VISIBLE, 270, 180, 120, 20, hwnd, (HMENU)BREAKPOINT_CLEARALL, GetModuleHandle(0), 0); diff --git a/src/win/ui_console.cpp b/src/win/ui_console.cpp index b5afdc19..eb2a8f68 100644 --- a/src/win/ui_console.cpp +++ b/src/win/ui_console.cpp @@ -7,11 +7,19 @@ SendDlgItemMessage(hwnd, CONSOLE_CFGLOCK##l##, BM_SETCHECK, (WPARAM)true, 0); \ } -long __stdcall wndproc_console(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { +long Console::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { char t[256]; int i, pos; uint32 addr, len, value; +HDC hdc; switch(msg) { + case WM_CTLCOLORSTATIC: + if((HWND)lparam != GetDlgItem(hwnd, CONSOLE_STATUS))break; + hdc = (HDC)wparam; + SetTextColor(hdc, RGB(255, 255, 255)); + SetBkColor(hdc, RGB(0, 0, 0)); + SetBkMode(hdc, TRANSPARENT); + return (long)hbr_backbrush; case WM_COMMAND: switch(LOWORD(wparam)) { case CONSOLE_CPUSTEP: @@ -46,17 +54,23 @@ uint32 addr, len, value; for(i=0;iwrite(bSNES::DRAM, (addr & 0xff0000) | ((addr + i) & 0xffff), 0xea); } - cpu->regs.pc.w += len; +// cpu->regs.pc.w += len; bsnes->disassemble_cpu_op(); } break; + case CONSOLE_APUSTEP: + if(bsnes->get_status() == bSNES::STOP) { + bsnes->set_status(bSNES::RUNTOAPUSTEP); + } + break; case CONSOLE_SYSRUN: if(bsnes->get_status() == bSNES::STOP) { - w_console->is_running(true); + is_running(true); bsnes->set_status(bSNES::RUNTOSIGNAL); } else { - w_console->is_running(false); + is_running(false); bsnes->set_status(bSNES::STOP); + bsnes->disassemble_apu_op(); bsnes->disassemble_cpu_op(); } break; @@ -65,16 +79,31 @@ uint32 addr, len, value; bsnes->set_status(bSNES::RUNTOFRAME); } break; + case CONSOLE_CFGOUTPUTCPU: + outputcpu ^= 1; + SendDlgItemMessage(hwnd, CONSOLE_CFGOUTPUTCPU, BM_SETCHECK, (WPARAM)outputcpu, 0); + break; + case CONSOLE_CFGOUTPUTAPU: + outputapu ^= 1; + SendDlgItemMessage(hwnd, CONSOLE_CFGOUTPUTAPU, BM_SETCHECK, (WPARAM)outputapu, 0); + break; + case CONSOLE_CFGOUTPUTDBG: + outputdbg ^= 1; + SendDlgItemMessage(hwnd, CONSOLE_CFGOUTPUTDBG, BM_SETCHECK, (WPARAM)outputdbg, 0); + break; case CONSOLE_CFGTRACE: - if(w_console->tracing_enabled == false) { - w_console->tracing_enabled = true; - w_console->log_fp = fopen("trace.log", "wb"); + if(tracing_enabled == false) { + write("* Tracing enabled"); + tracing_enabled = true; + log_fp = fopen("trace.log", "wb"); + bsnes->disassemble_apu_op(); bsnes->disassemble_cpu_op(); SendDlgItemMessage(hwnd, CONSOLE_CFGTRACE, BM_SETCHECK, (WPARAM)true, 0); } else { - w_console->tracing_enabled = false; - fclose(w_console->log_fp); + tracing_enabled = false; + fclose(log_fp); SendDlgItemMessage(hwnd, CONSOLE_CFGTRACE, BM_SETCHECK, (WPARAM)false, 0); + write("* Tracing disabled"); } break; case CONSOLE_CFGREGSET: @@ -94,9 +123,8 @@ uint32 addr, len, value; case 7:cpu->regs.e = value;break; case 8:cpu->regs.pc.d = value;break; } - /* these bits can *never* be clear in emulation mode */ + //these bits can never be clear in emulation mode if(cpu->regs.e)cpu->regs.p |= 0x30; - /* disassemble current opcode again to reflect new register values */ bsnes->disassemble_cpu_op(); } else { //Set APU register } @@ -115,12 +143,9 @@ uint32 addr, len, value; case CONSOLE_CFGLOCKSTART: __console_joypad_lock(start, START); break; } break; -/* Usually, bsnes will catch the close request here, and replace it - with a hide command instead. */ case WM_CLOSE: bsnes->debugger_disable(); return 0; -/* Just in case something sends a DestroyWindow command to bsnes... */ case WM_DESTROY: alert("Error: bsnes debugging console window has been destroyed!\n" "The emulator will still run, but it must be restarted before\n" @@ -132,15 +157,26 @@ uint32 addr, len, value; return DefWindowProc(hwnd, msg, wparam, lparam); } +long __stdcall wndproc_console(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + return w_console->wndproc(hwnd, msg, wparam, lparam); +} + void Console::clear() { +static uint8 linecol[4] = { 0, 0, 0 }; for(int i=0;iget_status()) { @@ -154,30 +190,58 @@ bool Console::can_write(uint32 message_type) { } void Console::write(char *s, uint32 message_type) { -char t[512]; +char t[128]; +bool blank_line; if(tracing_enabled == true) { - fprintf(log_fp, "%s\r\n", s); + if (message_type == Console::CPU_MESSAGE && outputcpu == false); + else if(message_type == Console::APU_MESSAGE && outputapu == false); + else if(message_type == Console::DEBUG_MESSAGE && outputdbg == false); + else fprintf(log_fp, "%s\r\n", s); } if(!can_write(message_type)) { return; } - for(int i=0;i= 80) { + memcpy(t, s, 80); + } else { + blank_line = (sl == 0); + strcpy(t, s); + memset(t + sl, 0x20, 80 - sl); + } + t[80] = 0; +//only allow ascii characters. other characters will force the +//font to change to one that supports non-ascii characters, +//which will break the line highlighting and alignment of text + for(int i=0;i<80;i++) { + if(t[i] & 0x80)t[i] = '?'; + } + + for(i=0;ihwnd = CreateWindow("bsnes_console", "bsnes debug console", - WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, - 0, 0, 850, 355, - 0, 0, GetModuleHandle(0), 0); - - w_console->resize(850, 355); - w_console->to_left(); - w_console->to_bottom(); - - w_console->create_controls(); -} - void Console::update_status() { -char s[4096], t[256]; +char s[4096], t[512]; +static uint8 linecol[4] = { 1, 2, 3 }; if(rom_image->loaded() == false)return; strcpy(s, ""); sprintf(t, "V:%3d H:%3d HC:%4d I:%d IF:%d O:%d", - clock->vcounter(), clock->hcounter(), clock->hcycles(), - clock->interlace(), clock->interlace_field(), clock->overscan()); + cpu->vcounter(), cpu->hcounter(), cpu->hcycles(), + cpu->interlace(), cpu->interlace_field(), cpu->overscan()); strcat(s, t); + if(cfg.apu.enabled) { + sprintf(t, " -- CPU[$%0.2x,$%0.2x,$%0.2x,$%0.2x]<>APU[$%0.2x,$%0.2x,$%0.2x,$%0.2x]", + cpu->port_read(0), cpu->port_read(1), cpu->port_read(2), cpu->port_read(3), + apu->port_read(0), apu->port_read(1), apu->port_read(2), apu->port_read(3) + ); + strcat(s, t); + } SetDlgItemText(hwnd, CONSOLE_STATUS, s); } @@ -248,84 +294,114 @@ void Console::set_reg_list_type(uint8 list_type) { } } -void Console::create_controls() { +void Console::create() { +WNDCLASS wc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + wc.hCursor = LoadCursor(0, IDC_ARROW); + wc.hIcon = LoadIcon(0, IDI_APPLICATION); + wc.hInstance = GetModuleHandle(0); + wc.lpfnWndProc = wndproc_console; + wc.lpszClassName = "bsnes_console"; + wc.lpszMenuName = 0; + wc.style = CS_HREDRAW | CS_VREDRAW; + RegisterClass(&wc); + + hwnd = CreateWindow("bsnes_console", "bsnes Debug Console", + WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, + 0, 0, 847, 354, + 0, 0, GetModuleHandle(0), 0); + + resize(847, 354); + to_left(); + to_bottom(); + int x, y; - CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", - WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_READONLY, - 5, 5, 585, 290, + CreateWindowEx(WS_EX_CLIENTEDGE, RICHEDIT_CLASS, "", WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_READONLY, + 5, 5, 582, 285, hwnd, (HMENU)CONSOLE_OUTPUT, GetModuleHandle(0), 0); - CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", - WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_READONLY, 5, 300, 585, 50, + editex_setbackcolor(GetDlgItem(hwnd, CONSOLE_OUTPUT), RGB(32, 32, 32)); + CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_READONLY, + 5, 290, 582, 59, hwnd, (HMENU)CONSOLE_STATUS, GetModuleHandle(0), 0); - x = 595; + x = 592; + y = 5; CreateWindow("BUTTON", "cpu (wdc 65c816)", WS_CHILD | WS_VISIBLE | BS_GROUPBOX, - x, 5, 250, 60, hwnd, (HMENU)CONSOLE_CPUGROUP, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Step", WS_CHILD | WS_VISIBLE, x + 5, 20, 80, 20, hwnd, (HMENU)CONSOLE_CPUSTEP, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Proceed", WS_CHILD | WS_VISIBLE, x + 85, 20, 80, 20, hwnd, (HMENU)CONSOLE_CPUPROCEED, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Skip", WS_CHILD | WS_VISIBLE, x + 165, 20, 80, 20, hwnd, (HMENU)CONSOLE_CPUSKIP, GetModuleHandle(0), 0); + x, y, 250, 60, hwnd, (HMENU)CONSOLE_CPUGROUP, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Step", WS_CHILD | WS_VISIBLE, x + 5, y + 15, 80, 20, hwnd, (HMENU)CONSOLE_CPUSTEP, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Proceed", WS_CHILD | WS_VISIBLE, x + 85, y + 15, 80, 20, hwnd, (HMENU)CONSOLE_CPUPROCEED, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Skip", WS_CHILD | WS_VISIBLE, x + 165, y + 15, 80, 20, hwnd, (HMENU)CONSOLE_CPUSKIP, GetModuleHandle(0), 0); CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "0", WS_CHILD | WS_VISIBLE, - x + 5, 40, 80, 20, hwnd, (HMENU)CONSOLE_CPUTRACENUM, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Trace", WS_CHILD | WS_VISIBLE, x + 85, 40, 80, 20, hwnd, (HMENU)CONSOLE_CPUTRACE, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Disable", WS_CHILD | WS_VISIBLE, x + 165, 40, 80, 20, hwnd, (HMENU)CONSOLE_CPUDISABLE, GetModuleHandle(0), 0); + x + 5, y + 35, 80, 20, hwnd, (HMENU)CONSOLE_CPUTRACENUM, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Trace", WS_CHILD | WS_VISIBLE, x + 85, y + 35, 80, 20, hwnd, (HMENU)CONSOLE_CPUTRACE, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Disable", WS_CHILD | WS_VISIBLE, x + 165, y + 35, 80, 20, hwnd, (HMENU)CONSOLE_CPUDISABLE, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "apu (sony spc700)", WS_CHILD | WS_VISIBLE | WS_DISABLED | BS_GROUPBOX, - x, 70, 250, 60, hwnd, (HMENU)CONSOLE_APUGROUP, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Step", WS_CHILD | WS_VISIBLE | WS_DISABLED, x + 5, 85, 80, 20, hwnd, (HMENU)CONSOLE_APUSTEP, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Proceed", WS_CHILD | WS_VISIBLE | WS_DISABLED, x + 85, 85, 80, 20, hwnd, (HMENU)CONSOLE_APUPROCEED, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Skip", WS_CHILD | WS_VISIBLE | WS_DISABLED, x + 165, 85, 80, 20, hwnd, (HMENU)CONSOLE_APUSKIP, GetModuleHandle(0), 0); + y += 66; + CreateWindow("BUTTON", "apu (sony spc700)", WS_CHILD | WS_VISIBLE | BS_GROUPBOX, + x, y, 250, 60, hwnd, (HMENU)CONSOLE_APUGROUP, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Step", WS_CHILD | WS_VISIBLE, x + 5, y + 15, 80, 20, hwnd, (HMENU)CONSOLE_APUSTEP, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Proceed", WS_CHILD | WS_VISIBLE | WS_DISABLED, x + 85, y + 15, 80, 20, hwnd, (HMENU)CONSOLE_APUPROCEED, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Skip", WS_CHILD | WS_VISIBLE | WS_DISABLED, x + 165, y + 15, 80, 20, hwnd, (HMENU)CONSOLE_APUSKIP, GetModuleHandle(0), 0); CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "0", WS_CHILD | WS_VISIBLE | WS_DISABLED, - x + 5, 105, 80, 20, hwnd, (HMENU)CONSOLE_APUTRACENUM, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Trace", WS_CHILD | WS_VISIBLE | WS_DISABLED, x + 85, 105, 80, 20, hwnd, (HMENU)CONSOLE_APUTRACE, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Disable", WS_CHILD | WS_VISIBLE | WS_DISABLED, x + 165, 105, 80, 20, hwnd, (HMENU)CONSOLE_APUDISABLE, GetModuleHandle(0), 0); + x + 5, y + 35, 80, 20, hwnd, (HMENU)CONSOLE_APUTRACENUM, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Trace", WS_CHILD | WS_VISIBLE | WS_DISABLED, x + 85, y + 35, 80, 20, hwnd, (HMENU)CONSOLE_APUTRACE, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Disable", WS_CHILD | WS_VISIBLE | WS_DISABLED, x + 165, y + 35, 80, 20, hwnd, (HMENU)CONSOLE_APUDISABLE, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "System", WS_CHILD | WS_VISIBLE | BS_GROUPBOX, x, 135, 250, 40, hwnd, (HMENU)CONSOLE_SYSGROUP, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Run", WS_CHILD | WS_VISIBLE, x + 5, 150, 80, 20, hwnd, (HMENU)CONSOLE_SYSRUN, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "To Frame", WS_CHILD | WS_VISIBLE, x + 85, 150, 80, 20, hwnd, (HMENU)CONSOLE_SYSRUNTOFRAME, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "To NMI", WS_CHILD | WS_VISIBLE | WS_DISABLED, x + 165, 150, 80, 20, hwnd, (HMENU)CONSOLE_SYSRUNTONMI, GetModuleHandle(0), 0); + y += 66; + CreateWindow("BUTTON", "System", WS_CHILD | WS_VISIBLE | BS_GROUPBOX, x, y, 250, 40, hwnd, (HMENU)CONSOLE_SYSGROUP, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Run", WS_CHILD | WS_VISIBLE, x + 5, y + 15, 80, 20, hwnd, (HMENU)CONSOLE_SYSRUN, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "To Frame", WS_CHILD | WS_VISIBLE, x + 85, y + 15, 80, 20, hwnd, (HMENU)CONSOLE_SYSRUNTOFRAME, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "To NMI", WS_CHILD | WS_VISIBLE | WS_DISABLED, x + 165, y + 15, 80, 20, hwnd, (HMENU)CONSOLE_SYSRUNTONMI, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Settings", WS_CHILD | WS_VISIBLE | BS_GROUPBOX, x, 180, 250, 170, hwnd, (HMENU)CONSOLE_CFGGROUP, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Output CPU instructions to console", WS_CHILD | WS_VISIBLE | WS_DISABLED | BS_CHECKBOX, - x + 5, 195, 240, 15, hwnd, (HMENU)CONSOLE_CFGOUTPUTCPU, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Output APU instructions to console", WS_CHILD | WS_VISIBLE | WS_DISABLED | BS_CHECKBOX, - x + 5, 210, 240, 15, hwnd, (HMENU)CONSOLE_CFGOUTPUTAPU, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Output debug messages to console", WS_CHILD | WS_VISIBLE | WS_DISABLED | BS_CHECKBOX, - x + 5, 225, 240, 15, hwnd, (HMENU)CONSOLE_CFGOUTPUTDBG, GetModuleHandle(0), 0); + y += 46; + CreateWindow("BUTTON", "Settings", WS_CHILD | WS_VISIBLE | BS_GROUPBOX, x, y, 250, 166, hwnd, (HMENU)CONSOLE_CFGGROUP, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Output CPU instructions to console", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, + x + 5, y + 15, 240, 15, hwnd, (HMENU)CONSOLE_CFGOUTPUTCPU, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Output APU instructions to console", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, + x + 5, y + 30, 240, 15, hwnd, (HMENU)CONSOLE_CFGOUTPUTAPU, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Output debug messages to console", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, + x + 5, y + 45, 240, 15, hwnd, (HMENU)CONSOLE_CFGOUTPUTDBG, GetModuleHandle(0), 0); CreateWindow("BUTTON", "Trace console output to file", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, - x + 5, 240, 240, 15, hwnd, (HMENU)CONSOLE_CFGTRACE, GetModuleHandle(0), 0); + x + 5, y + 60, 240, 15, hwnd, (HMENU)CONSOLE_CFGTRACE, GetModuleHandle(0), 0); + + y += 77; CreateWindow("COMBOBOX", "", WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS, - x + 5, 260, 60, 200, hwnd, (HMENU)CONSOLE_CFGREGTYPE, GetModuleHandle(0), 0); + x + 5, y, 60, 200, hwnd, (HMENU)CONSOLE_CFGREGTYPE, GetModuleHandle(0), 0); CreateWindow("COMBOBOX", "", WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS, - x + 65, 260, 60, 200, hwnd, (HMENU)CONSOLE_CFGREGNUM, GetModuleHandle(0), 0); + x + 65, y, 60, 200, hwnd, (HMENU)CONSOLE_CFGREGNUM, GetModuleHandle(0), 0); CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "0", WS_CHILD | WS_VISIBLE, - x + 125, 260, 60, 21, hwnd, (HMENU)CONSOLE_CFGREGVAL, GetModuleHandle(0), 0); + x + 125, y, 60, 21, hwnd, (HMENU)CONSOLE_CFGREGVAL, GetModuleHandle(0), 0); CreateWindow("BUTTON", "Set Reg", WS_CHILD | WS_VISIBLE, - x + 185, 260, 60, 21, hwnd, (HMENU)CONSOLE_CFGREGSET, GetModuleHandle(0), 0); - CreateWindow("STATIC", "Lock Joypad Button(s) Down:", WS_CHILD | WS_VISIBLE, x + 5, 285, 240, 15, hwnd, (HMENU)CONSOLE_CFGLOCK, GetModuleHandle(0), 0); + x + 185, y, 60, 21, hwnd, (HMENU)CONSOLE_CFGREGSET, GetModuleHandle(0), 0); + + y += 24; + CreateWindow("STATIC", "Lock Joypad Button(s) Down:", WS_CHILD | WS_VISIBLE, x + 5, y, 240, 15, hwnd, (HMENU)CONSOLE_CFGLOCK, GetModuleHandle(0), 0); CreateWindow("BUTTON", "Up", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, - x + 5, 300, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKUP, GetModuleHandle(0), 0); + x + 5, y + 15, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKUP, GetModuleHandle(0), 0); CreateWindow("BUTTON", "Down", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, - x + 65, 300, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKDOWN, GetModuleHandle(0), 0); + x + 65, y + 15, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKDOWN, GetModuleHandle(0), 0); CreateWindow("BUTTON", "Left", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, - x + 125, 300, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKLEFT, GetModuleHandle(0), 0); + x + 125, y + 15, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKLEFT, GetModuleHandle(0), 0); CreateWindow("BUTTON", "Right", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, - x + 185, 300, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKRIGHT, GetModuleHandle(0), 0); + x + 185, y + 15, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKRIGHT, GetModuleHandle(0), 0); CreateWindow("BUTTON", "A", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, - x + 5, 315, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKA, GetModuleHandle(0), 0); + x + 5, y + 30, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKA, GetModuleHandle(0), 0); CreateWindow("BUTTON", "B", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, - x + 65, 315, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKB, GetModuleHandle(0), 0); + x + 65, y + 30, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKB, GetModuleHandle(0), 0); CreateWindow("BUTTON", "X", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, - x + 125, 315, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKX, GetModuleHandle(0), 0); + x + 125, y + 30, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKX, GetModuleHandle(0), 0); CreateWindow("BUTTON", "Y", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, - x + 185, 315, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKY, GetModuleHandle(0), 0); + x + 185, y + 30, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKY, GetModuleHandle(0), 0); CreateWindow("BUTTON", "L", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, - x + 5, 330, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKL, GetModuleHandle(0), 0); + x + 5, y + 45, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKL, GetModuleHandle(0), 0); CreateWindow("BUTTON", "R", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, - x + 65, 330, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKR, GetModuleHandle(0), 0); + x + 65, y + 45, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKR, GetModuleHandle(0), 0); CreateWindow("BUTTON", "Select", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, - x + 125, 330, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKSELECT, GetModuleHandle(0), 0); + x + 125, y + 45, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKSELECT, GetModuleHandle(0), 0); CreateWindow("BUTTON", "Start", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, - x + 185, 330, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKSTART, GetModuleHandle(0), 0); + x + 185, y + 45, 60, 15, hwnd, (HMENU)CONSOLE_CFGLOCKSTART, GetModuleHandle(0), 0); SendDlgItemMessage(hwnd, CONSOLE_OUTPUT, WM_SETFONT, (WPARAM)hMonofont, TRUE); SendDlgItemMessage(hwnd, CONSOLE_STATUS, WM_SETFONT, (WPARAM)hMonofont, TRUE); @@ -374,7 +450,11 @@ int x, y; SendDlgItemMessage(hwnd, CONSOLE_CFGLOCKSELECT, WM_SETFONT, (WPARAM)hFont, TRUE); SendDlgItemMessage(hwnd, CONSOLE_CFGLOCKSTART, WM_SETFONT, (WPARAM)hFont, TRUE); + outputcpu = true; + outputapu = true; + outputdbg = true; SendDlgItemMessage(hwnd, CONSOLE_CFGOUTPUTCPU, BM_SETCHECK, (WPARAM)true, 0); + SendDlgItemMessage(hwnd, CONSOLE_CFGOUTPUTAPU, BM_SETCHECK, (WPARAM)true, 0); SendDlgItemMessage(hwnd, CONSOLE_CFGOUTPUTDBG, BM_SETCHECK, (WPARAM)true, 0); SendDlgItemMessage(hwnd, CONSOLE_CFGREGTYPE, CB_ADDSTRING, 0, (LPARAM)"CPU"); @@ -396,10 +476,10 @@ Console::Console() { for(int i=0;iwndproc(hwnd, msg, wparam, lparam); +} + +void InputConfig::update_polling(int key) { +bool end_config = false; + if(polling == false)return; + + switch(config_type) { + case JOYPAD1: + switch(config_pos) { + case 0:cfg.input.joypad1.up = key;break; + case 1:cfg.input.joypad1.down = key;break; + case 2:cfg.input.joypad1.left = key;break; + case 3:cfg.input.joypad1.right = key;break; + case 4:cfg.input.joypad1.select = key;break; + case 5:cfg.input.joypad1.start = key;break; + case 6:cfg.input.joypad1.x = key;break; + case 7:cfg.input.joypad1.y = key;break; + case 8:cfg.input.joypad1.a = key;break; + case 9:cfg.input.joypad1.b = key;break; + case 10:cfg.input.joypad1.l = key;break; + case 11:cfg.input.joypad1.r = key;break; + case 12:end_config = true;break; + } + config_pos++; + } + if(end_config == true) { + polling = false; + hide(); + return; + } + update_command(); +} + +void InputConfig::update_command() { + switch(config_type) { + case JOYPAD1: + switch(config_pos) { + case 0:set_text("Press key for Up..."); break; + case 1:set_text("Press key for Down..."); break; + case 2:set_text("Press key for Left..."); break; + case 3:set_text("Press key for Right..."); break; + case 4:set_text("Press key for Select...");break; + case 5:set_text("Press key for Start..."); break; + case 6:set_text("Press key for X..."); break; + case 7:set_text("Press key for Y..."); break; + case 8:set_text("Press key for A..."); break; + case 9:set_text("Press key for B..."); break; + case 10:set_text("Press key for L..."); break; + case 11:set_text("Press key for R..."); break; + case 12:set_text("Configuration complete. Press any key to close window...");break; + } + break; + } +} + +void InputConfig::begin_config(int type) { + if(visible == true) { + center(); + SetFocus(hwnd); + return; + } + config_type = type; + config_pos = 0; + switch(config_type) { + case JOYPAD1: + SetWindowText(hwnd, "bsnes Input Configuration : Joypad1"); + break; + default: + return; + } + polling = true; + update_command(); + center(); + show(); +} + +void InputConfig::set_text(char *str) { + SetDlgItemText(hwnd, ID_COMMAND, str); +} + +void InputConfig::create() { +WNDCLASS wc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + wc.hCursor = LoadCursor(0, IDC_ARROW); + wc.hIcon = LoadIcon(0, IDI_APPLICATION); + wc.hInstance = GetModuleHandle(0); + wc.lpfnWndProc = wndproc_inputconfig; + wc.lpszClassName = "bsnes_inputconfig"; + wc.lpszMenuName = 0; + wc.style = CS_HREDRAW | CS_VREDRAW; + RegisterClass(&wc); + + hwnd = CreateWindow("bsnes_inputconfig", "bsnes input configuration", + WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, + 0, 0, 410, 230, + 0, 0, GetModuleHandle(0), 0); + + resize(410, 230); + center(); + + CreateWindow("STATIC", "", WS_CHILD | WS_VISIBLE, 5, 5, 350, 15, hwnd, (HMENU)ID_COMMAND, GetModuleHandle(0), 0); + + SendDlgItemMessage(hwnd, ID_COMMAND, WM_SETFONT, (WPARAM)hFont, 0); + SendDlgItemMessage(hwnd, 120, WM_SETFONT, (WPARAM)hFont, 0); +} diff --git a/src/win/ui_main.cpp b/src/win/ui_main.cpp index dfd8b6a1..efa883c6 100644 --- a/src/win/ui_main.cpp +++ b/src/win/ui_main.cpp @@ -11,7 +11,7 @@ void MainWindow::set_frameskip(uint8 fs) { CheckMenuItem(w_main->hmenu, MENU_SETTINGS_FRAMESKIP_9, MF_UNCHECKED); CheckMenuItem(w_main->hmenu, MENU_SETTINGS_FRAMESKIP_OFF + fs, MF_CHECKED); - clock->set_frameskip(fs); + ppu->set_frameskip(fs); w_main->frameskip = fs; } @@ -212,6 +212,13 @@ long __stdcall wndproc_main(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { SetWindowText(w_main->hwnd, BSNES_TITLE); CheckMenuItem(w_main->hmenu, MENU_SETTINGS_SHOWFPS, (cfg.gui.show_fps)?MF_CHECKED:MF_UNCHECKED); break; + case MENU_SETTINGS_APUENABLED: + cfg.apu.enabled ^= 1; + CheckMenuItem(w_main->hmenu, MENU_SETTINGS_APUENABLED, (cfg.apu.enabled)?MF_CHECKED:MF_UNCHECKED); + break; + case MENU_SETTINGS_INPUTCFG_JOYPAD1: + w_inputconfig->begin_config(InputConfig::JOYPAD1); + break; case MENU_SETTINGS_DEBUGGER: if(bsnes->debugger_enabled() == true) { bsnes->debugger_disable(); @@ -220,6 +227,11 @@ long __stdcall wndproc_main(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { w_main->set_video_mode(VIDEOMODE_256x224w); } break; + case MENU_MISC_ABOUT: + w_about->center(); + w_about->show(); + SetFocus(w_about->hwnd); + break; } break; case WM_DESTROY: @@ -232,13 +244,13 @@ long __stdcall wndproc_main(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { return DefWindowProc(hwnd, msg, wparam, lparam); } -void CreateWindowMain() { +void MainWindow::create() { WNDCLASS wc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0)); wc.hCursor = LoadCursor(0, IDC_ARROW); - wc.hIcon = LoadIcon(0, IDI_APPLICATION); + wc.hIcon = LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(101)); wc.hInstance = GetModuleHandle(0); wc.lpfnWndProc = wndproc_main; wc.lpszClassName = "bsnes"; @@ -246,13 +258,13 @@ WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; RegisterClass(&wc); - w_main->hwnd = CreateWindowEx(0, "bsnes", "bsnes v" BSNES_VERSION " ~byuu", + hwnd = CreateWindowEx(0, "bsnes", BSNES_TITLE, WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 0, 0, 512, 446, 0, 0, GetModuleHandle(0), 0); HMENU hsubmenu, hbranchmenu; - w_main->hmenu = CreateMenu(); + hmenu = CreateMenu(); hsubmenu = CreatePopupMenu(); AppendMenu(hsubmenu, MF_STRING, MENU_FILE_LOAD, "&Load ROM"); @@ -262,7 +274,7 @@ HMENU hsubmenu, hbranchmenu; AppendMenu(hsubmenu, MF_STRING, MENU_FILE_POWER, "&Power (Hard Reset)"); AppendMenu(hsubmenu, MF_SEPARATOR, 0, ""); AppendMenu(hsubmenu, MF_STRING, MENU_FILE_EXIT, "E&xit"); - AppendMenu(w_main->hmenu, MF_STRING | MF_POPUP, (unsigned int)hsubmenu, "&File"); + AppendMenu(hmenu, MF_STRING | MF_POPUP, (unsigned int)hsubmenu, "&File"); hsubmenu = CreatePopupMenu(); @@ -292,16 +304,23 @@ HMENU hsubmenu, hbranchmenu; AppendMenu(hsubmenu, MF_STRING, MENU_SETTINGS_VBLANK, "&Wait for Vertical Retrace"); AppendMenu(hsubmenu, MF_STRING, MENU_SETTINGS_COLORCURVE, "Use &Color Curve"); AppendMenu(hsubmenu, MF_STRING, MENU_SETTINGS_SHOWFPS, "&Show FPS"); + AppendMenu(hsubmenu, MF_STRING, MENU_SETTINGS_APUENABLED, "&Enable APU"); + + hbranchmenu = CreatePopupMenu(); + AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_INPUTCFG_JOYPAD1, "Joypad 1"); + AppendMenu(hsubmenu, MF_STRING | MF_POPUP, (unsigned int)hbranchmenu, "&Configure Input Devices"); AppendMenu(hsubmenu, MF_SEPARATOR, 0, ""); AppendMenu(hsubmenu, MF_STRING, MENU_SETTINGS_DEBUGGER, "&Debugger"); - AppendMenu(w_main->hmenu, MF_STRING | MF_POPUP, (unsigned int)hsubmenu, "&Settings"); + AppendMenu(hmenu, MF_STRING | MF_POPUP, (unsigned int)hsubmenu, "&Settings"); - CheckMenuItem(w_main->hmenu, MENU_SETTINGS_USEVRAM, (cfg.video.use_vram)?MF_CHECKED:MF_UNCHECKED); - CheckMenuItem(w_main->hmenu, MENU_SETTINGS_VBLANK, (cfg.video.vblank)?MF_CHECKED:MF_UNCHECKED); - CheckMenuItem(w_main->hmenu, MENU_SETTINGS_COLORCURVE, (cfg.video.color_curve)?MF_CHECKED:MF_UNCHECKED); - CheckMenuItem(w_main->hmenu, MENU_SETTINGS_SHOWFPS, (cfg.gui.show_fps)?MF_CHECKED:MF_UNCHECKED); -} + hsubmenu = CreatePopupMenu(); + AppendMenu(hsubmenu, MF_STRING, MENU_MISC_ABOUT, "&About..."); + AppendMenu(hmenu, MF_STRING | MF_POPUP, (unsigned int)hsubmenu, "&Misc"); -MainWindow::MainWindow() { + CheckMenuItem(hmenu, MENU_SETTINGS_USEVRAM, (cfg.video.use_vram)?MF_CHECKED:MF_UNCHECKED); + CheckMenuItem(hmenu, MENU_SETTINGS_VBLANK, (cfg.video.vblank)?MF_CHECKED:MF_UNCHECKED); + CheckMenuItem(hmenu, MENU_SETTINGS_COLORCURVE, (cfg.video.color_curve)?MF_CHECKED:MF_UNCHECKED); + CheckMenuItem(hmenu, MENU_SETTINGS_SHOWFPS, (cfg.gui.show_fps)?MF_CHECKED:MF_UNCHECKED); + CheckMenuItem(hmenu, MENU_SETTINGS_APUENABLED, (cfg.apu.enabled)?MF_CHECKED:MF_UNCHECKED); } diff --git a/src/win/ui_memory.cpp b/src/win/ui_memory.cpp index 651b0215..380d9fef 100644 --- a/src/win/ui_memory.cpp +++ b/src/win/ui_memory.cpp @@ -1,7 +1,101 @@ +WNDPROC wndproc_oldmemoryeditbox; + +long __stdcall wndproc_memoryeditbox(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { +int pos, len, xpos, ypos, t, z, read; + switch(msg) { + case WM_KEYDOWN: + pos = SendMessage(hwnd, EM_GETSEL, 0, 0); + pos = LOWORD(pos); + ypos = pos / 57; + xpos = pos % 57; + + if(wparam == VK_UP) { + if(ypos != 0)break; + w_memory->edit_addr -= 16; + w_memory->edit_addr &= w_memory->edit_mask; + w_memory->refresh(); + SendMessage(hwnd, EM_SETSEL, pos, pos); + break; + } + + if(wparam == VK_DOWN) { + if(ypos != 15)break; + w_memory->edit_addr += 16; + w_memory->edit_addr &= w_memory->edit_mask; + w_memory->refresh(); + SendMessage(hwnd, EM_SETSEL, pos, pos); + break; + } + + if(wparam == VK_PRIOR) { + if(KeyDown(VK_CONTROL))len = 65536; + else if(KeyDown(VK_SHIFT))len = 4096; + else len = 256; + w_memory->edit_addr -= len; + w_memory->edit_addr &= w_memory->edit_mask; + w_memory->refresh(); + SendMessage(hwnd, EM_SETSEL, pos, pos); + break; + } + + if(wparam == VK_NEXT) { + if(KeyDown(VK_CONTROL))len = 65536; + else if(KeyDown(VK_SHIFT))len = 4096; + else len = 256; + w_memory->edit_addr += len; + w_memory->edit_addr &= w_memory->edit_mask; + w_memory->refresh(); + SendMessage(hwnd, EM_SETSEL, pos, pos); + break; + } + + if(xpos < 8)break; + xpos -= 8; + t = xpos % 3; + xpos /= 3; + if(xpos > 15)break; + + if(wparam >= '0' && wparam <= '9')read = wparam - '0'; + else if(wparam >= 'A' && wparam <= 'F')read = wparam - 'A' + 0x0a; + else if(wparam >= 'a' && wparam <= 'f')read = wparam - 'a' + 0x0a; + else break; + + z = w_memory->read_byte(w_memory->edit_addr + ypos * 16 + xpos); + if(t == 0) { + z = (read << 4) | (z & 0x0f); + pos++; + } else { + z = (z & 0xf0) | (read); + if(xpos == 15) { //go to new line + if(ypos == 15) { //so long as we aren't on the last one + pos++; + } else { + pos += 11; + } + } else { //go to next byte + pos += 2; + } + } + w_memory->write_byte(w_memory->edit_addr + ypos * 16 + xpos, z); + w_memory->refresh(); + SendMessage(hwnd, EM_SETSEL, pos, pos); + break; + } + return wndproc_oldmemoryeditbox(hwnd, msg, wparam, lparam); +} + long __stdcall wndproc_memoryeditor(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { char t[256]; uint32 addr, value, pos; +HDC hdc; switch(msg) { + case WM_CTLCOLORSTATIC: + if((HWND)lparam != GetDlgItem(hwnd, MEMORYEDITOR_VIEW))break; + hdc = (HDC)wparam; + SetTextColor(hdc, RGB(255, 255, 255)); + SetBkColor(hdc, RGB(0, 0, 0)); + SetBkMode(hdc, TRANSPARENT); + return (long)hbr_backbrush; case WM_COMMAND: switch(LOWORD(wparam)) { case MEMORYEDITOR_MODE: @@ -20,14 +114,18 @@ uint32 addr, value, pos; w_memory->edit_addr = 0x700000; w_memory->edit_mask = 0xffffff; } else if(pos == 3) { - w_memory->edit_mode = MemoryEditor::MODE_VRAM; + w_memory->edit_mode = MemoryEditor::MODE_SPCRAM; w_memory->edit_addr = 0x0000; w_memory->edit_mask = 0xffff; } else if(pos == 4) { + w_memory->edit_mode = MemoryEditor::MODE_VRAM; + w_memory->edit_addr = 0x0000; + w_memory->edit_mask = 0xffff; + } else if(pos == 5) { w_memory->edit_mode = MemoryEditor::MODE_OAM; w_memory->edit_addr = 0x0000; w_memory->edit_mask = 0x03ff; - } else if(pos == 5) { + } else if(pos == 6) { w_memory->edit_mode = MemoryEditor::MODE_CGRAM; w_memory->edit_addr = 0x0000; w_memory->edit_mask = 0x01ff; @@ -47,54 +145,26 @@ uint32 addr, value, pos; GetDlgItemText(hwnd, MEMORYEDITOR_VALUE, t, 255); value = strhex(t) & 0xff; switch(w_memory->edit_mode) { - case MemoryEditor::MODE_DRAM: bsnes->write(bSNES::DRAM, addr, value);break; - case MemoryEditor::MODE_VRAM: bsnes->write(bSNES::VRAM, addr, value);break; - case MemoryEditor::MODE_OAM: bsnes->write(bSNES::OAM, addr, value);break; - case MemoryEditor::MODE_CGRAM:bsnes->write(bSNES::CGRAM, addr, value);break; + case MemoryEditor::MODE_DRAM: bsnes->write(bSNES::DRAM, addr, value);break; + case MemoryEditor::MODE_SPCRAM:bsnes->write(bSNES::SPCRAM, addr, value);break; + case MemoryEditor::MODE_VRAM: bsnes->write(bSNES::VRAM, addr, value);break; + case MemoryEditor::MODE_OAM: bsnes->write(bSNES::OAM, addr, value);break; + case MemoryEditor::MODE_CGRAM: bsnes->write(bSNES::CGRAM, addr, value);break; } break; case MEMORYEDITOR_FEXPORT: pos = SendDlgItemMessage(hwnd, MEMORYEDITOR_FSOURCE, CB_GETCURSEL, 0, 0); w_memory->export(pos); break; - case MEMORYEDITOR_UP40: - w_memory->edit_addr -= 0x40; - w_memory->edit_addr &= w_memory->edit_mask; - w_memory->refresh(); + case MEMORYEDITOR_AUTOUPDATE: + if(w_memory->auto_update == false) { + w_memory->auto_update = true; + } else { + w_memory->auto_update = false; + } + SendDlgItemMessage(hwnd, MEMORYEDITOR_AUTOUPDATE, BM_SETCHECK, (WPARAM)w_memory->auto_update, 0); break; - case MEMORYEDITOR_DOWN40: - w_memory->edit_addr += 0x40; - w_memory->edit_addr &= w_memory->edit_mask; - w_memory->refresh(); - break; - case MEMORYEDITOR_UP400: - w_memory->edit_addr -= 0x400; - w_memory->edit_addr &= w_memory->edit_mask; - w_memory->refresh(); - break; - case MEMORYEDITOR_DOWN400: - w_memory->edit_addr += 0x400; - w_memory->edit_addr &= w_memory->edit_mask; - w_memory->refresh(); - break; - case MEMORYEDITOR_UP4000: - w_memory->edit_addr -= 0x4000; - w_memory->edit_addr &= w_memory->edit_mask; - w_memory->refresh(); - break; - case MEMORYEDITOR_DOWN4000: - w_memory->edit_addr += 0x4000; - w_memory->edit_addr &= w_memory->edit_mask; - w_memory->refresh(); - break; - case MEMORYEDITOR_UP40000: - w_memory->edit_addr -= 0x40000; - w_memory->edit_addr &= w_memory->edit_mask; - w_memory->refresh(); - break; - case MEMORYEDITOR_DOWN40000: - w_memory->edit_addr += 0x40000; - w_memory->edit_addr &= w_memory->edit_mask; + case MEMORYEDITOR_UPDATE: w_memory->refresh(); break; } @@ -116,32 +186,6 @@ uint32 addr, value, pos; return DefWindowProc(hwnd, msg, wparam, lparam); } -void CreateWindowMemory() { -WNDCLASS wc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hbrBackground = (HBRUSH)COLOR_WINDOW; - wc.hCursor = LoadCursor(0, IDC_ARROW); - wc.hIcon = LoadIcon(0, IDI_APPLICATION); - wc.hInstance = GetModuleHandle(0); - wc.lpfnWndProc = wndproc_memoryeditor; - wc.lpszClassName = "bsnes_memoryeditor"; - wc.lpszMenuName = 0; - wc.style = CS_HREDRAW | CS_VREDRAW; - RegisterClass(&wc); - - w_memory->hwnd = CreateWindow("bsnes_memoryeditor", "bsnes memory editor", - WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, - 0, 0, 500, 245, - 0, 0, GetModuleHandle(0), 0); - - w_memory->resize(500, 245); - w_memory->to_left(w_bp->hwnd); - w_memory->to_bottom(w_console->hwnd); - - w_memory->create_controls(); -} - void MemoryEditor::export(uint32 type) { FILE *fp; int i, x; @@ -160,46 +204,65 @@ int i, x; fputc(x, fp); } fclose(fp); - } else if(type == 2) { //VRAM + } else if(type == 2) { //SPCRAM + fp = fopen("spcram.bin", "wb"); + for(i=0x0000;i<=0xffff;i++) { + x = bsnes->read(bSNES::SPCRAM, i); + fputc(x, fp); + } + fclose(fp); + } else if(type == 3) { //VRAM fp = fopen("vram.bin", "wb"); for(i=0x0000;i<=0xffff;i++) { x = bsnes->read(bSNES::VRAM, i); fputc(x, fp); } fclose(fp); - } else if(type == 3) { //OAM + } else if(type == 4) { //OAM fp = fopen("oam.bin", "wb"); for(i=0x0000;i<=0x021f;i++) { x = bsnes->read(bSNES::OAM, i); fputc(x, fp); } fclose(fp); - } else if(type == 4) { //CGRAM + } else if(type == 5) { //CGRAM fp = fopen("cgram.bin", "wb"); for(i=0x0000;i<=0x01ff;i++) { x = bsnes->read(bSNES::CGRAM, i); fputc(x, fp); } fclose(fp); - } else if(type == 5) { //All + } else if(type == 6) { //All export(0); export(1); export(2); export(3); export(4); + export(5); } } uint8 MemoryEditor::read_byte(uint32 addr) { switch(edit_mode) { - case MODE_DRAM: return bsnes->read(bSNES::DRAM, addr); - case MODE_VRAM: return bsnes->read(bSNES::VRAM, addr); - case MODE_OAM: return bsnes->read(bSNES::OAM, addr); - case MODE_CGRAM:return bsnes->read(bSNES::CGRAM, addr); + case MODE_DRAM: return bsnes->read(bSNES::DRAM, addr); + case MODE_SPCRAM:return bsnes->read(bSNES::SPCRAM, addr); + case MODE_VRAM: return bsnes->read(bSNES::VRAM, addr); + case MODE_OAM: return bsnes->read(bSNES::OAM, addr); + case MODE_CGRAM: return bsnes->read(bSNES::CGRAM, addr); } return 0x00; } +void MemoryEditor::write_byte(uint32 addr, uint8 value) { + switch(edit_mode) { + case MODE_DRAM: bsnes->write(bSNES::DRAM, addr, value);break; + case MODE_SPCRAM:bsnes->write(bSNES::SPCRAM, addr, value);break; + case MODE_VRAM: bsnes->write(bSNES::VRAM, addr, value);break; + case MODE_OAM: bsnes->write(bSNES::OAM, addr, value);break; + case MODE_CGRAM: bsnes->write(bSNES::CGRAM, addr, value);break; + } +} + void MemoryEditor::clear() { SetDlgItemText(hwnd, MEMORYEDITOR_VIEW, ""); } @@ -210,18 +273,25 @@ int x, y; if(rom_image->loaded() == false)return; if(visible == false)return; - if(type == SNES::MEM_WRITE) { - if(edit_mode != MODE_DRAM)return; - if(addr < edit_addr || addr >= edit_addr + 256)return; - } else if(type == SNES::VRAM_WRITE) { - if(edit_mode != MODE_VRAM)return; - if(addr < edit_addr || addr >= edit_addr + 256)return; - } else if(type == SNES::OAM_WRITE) { - if(edit_mode != MODE_OAM)return; - if(addr < edit_addr || addr >= edit_addr + 256)return; - } else if(type == SNES::CGRAM_WRITE) { - if(edit_mode != MODE_CGRAM)return; - if(addr < edit_addr || addr >= edit_addr + 256)return; + if(type != null) { + if(auto_update == false && bsnes->get_status() != bSNES::STOP)return; + + if(type == SNES::MEM_WRITE) { + if(edit_mode != MODE_DRAM)return; + if(addr < edit_addr || addr >= edit_addr + 256)return; + } else if(type == SNES::SPCRAM_WRITE) { + if(edit_mode != MODE_SPCRAM)return; + if(addr < edit_addr || addr >= edit_addr + 256)return; + } else if(type == SNES::VRAM_WRITE) { + if(edit_mode != MODE_VRAM)return; + if(addr < edit_addr || addr >= edit_addr + 256)return; + } else if(type == SNES::OAM_WRITE) { + if(edit_mode != MODE_OAM)return; + if(addr < edit_addr || addr >= edit_addr + 256)return; + } else if(type == SNES::CGRAM_WRITE) { + if(edit_mode != MODE_CGRAM)return; + if(addr < edit_addr || addr >= edit_addr + 256)return; + } } strcpy(s, ""); @@ -238,9 +308,33 @@ int x, y; SetDlgItemText(hwnd, MEMORYEDITOR_VIEW, s); } -void MemoryEditor::create_controls() { +void MemoryEditor::create() { +WNDCLASS wc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + wc.hCursor = LoadCursor(0, IDC_ARROW); + wc.hIcon = LoadIcon(0, IDI_APPLICATION); + wc.hInstance = GetModuleHandle(0); + wc.lpfnWndProc = wndproc_memoryeditor; + wc.lpszClassName = "bsnes_memoryeditor"; + wc.lpszMenuName = 0; + wc.style = CS_HREDRAW | CS_VREDRAW; + RegisterClass(&wc); + + hwnd = CreateWindow("bsnes_memoryeditor", "bsnes Memory Editor", + WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, + 0, 0, 500, 245, + 0, 0, GetModuleHandle(0), 0); + + resize(500, 245); + to_left(w_bp->hwnd); + to_bottom(w_console->hwnd); + CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_READONLY, 5, 5, 395, 235, hwnd, (HMENU)MEMORYEDITOR_VIEW, GetModuleHandle(0), 0); + wndproc_oldmemoryeditbox = (WNDPROC)GetWindowLong(GetDlgItem(hwnd, MEMORYEDITOR_VIEW), GWL_WNDPROC); + SetWindowLong(GetDlgItem(hwnd, MEMORYEDITOR_VIEW), GWL_WNDPROC, (long)wndproc_memoryeditbox); CreateWindow("COMBOBOX", "", WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS, 405, 5, 90, 200, hwnd, (HMENU)MEMORYEDITOR_MODE, GetModuleHandle(0), 0); @@ -263,45 +357,28 @@ void MemoryEditor::create_controls() { CreateWindow("BUTTON", "Export...", WS_CHILD | WS_VISIBLE, 405, 131, 90, 20, hwnd, (HMENU)MEMORYEDITOR_FEXPORT, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "-40", WS_CHILD | WS_VISIBLE, - 405, 160, 45, 20, hwnd, (HMENU)MEMORYEDITOR_UP40, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "+40", WS_CHILD | WS_VISIBLE, - 450, 160, 45, 20, hwnd, (HMENU)MEMORYEDITOR_DOWN40, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "-400", WS_CHILD | WS_VISIBLE, - 405, 180, 45, 20, hwnd, (HMENU)MEMORYEDITOR_UP400, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "+400", WS_CHILD | WS_VISIBLE, - 450, 180, 45, 20, hwnd, (HMENU)MEMORYEDITOR_DOWN400, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "-4000", WS_CHILD | WS_VISIBLE, - 405, 200, 45, 20, hwnd, (HMENU)MEMORYEDITOR_UP4000, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "+4000", WS_CHILD | WS_VISIBLE, - 450, 200, 45, 20, hwnd, (HMENU)MEMORYEDITOR_DOWN4000, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "-40000", WS_CHILD | WS_VISIBLE, - 405, 220, 45, 20, hwnd, (HMENU)MEMORYEDITOR_UP40000, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "+40000", WS_CHILD | WS_VISIBLE, - 450, 220, 45, 20, hwnd, (HMENU)MEMORYEDITOR_DOWN40000, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Auto Update", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, + 405, 203, 90, 15, hwnd, (HMENU)MEMORYEDITOR_AUTOUPDATE, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Update", WS_CHILD | WS_VISIBLE, + 405, 220, 90, 20, hwnd, (HMENU)MEMORYEDITOR_UPDATE, GetModuleHandle(0), 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_VIEW, WM_SETFONT, (WPARAM)hMonofont, 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_MODE, WM_SETFONT, (WPARAM)hFont, 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_GOTOADDR, WM_SETFONT, (WPARAM)hMonofont, 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_GOTO, WM_SETFONT, (WPARAM)hFont, 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_STATIC1, WM_SETFONT, (WPARAM)hFont, 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_OFFSET, WM_SETFONT, (WPARAM)hMonofont, 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_VALUE, WM_SETFONT, (WPARAM)hMonofont, 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_EDIT, WM_SETFONT, (WPARAM)hFont, 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_FSOURCE, WM_SETFONT, (WPARAM)hFont, 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_FEXPORT, WM_SETFONT, (WPARAM)hFont, 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_UP40, WM_SETFONT, (WPARAM)hFont, 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_DOWN40, WM_SETFONT, (WPARAM)hFont, 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_UP400, WM_SETFONT, (WPARAM)hFont, 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_DOWN400, WM_SETFONT, (WPARAM)hFont, 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_UP4000, WM_SETFONT, (WPARAM)hFont, 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_DOWN4000, WM_SETFONT, (WPARAM)hFont, 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_UP40000, WM_SETFONT, (WPARAM)hFont, 0); - SendDlgItemMessage(hwnd, MEMORYEDITOR_DOWN40000, WM_SETFONT, (WPARAM)hFont, 0); + SendDlgItemMessage(hwnd, MEMORYEDITOR_VIEW, WM_SETFONT, (WPARAM)hMonofont, 0); + SendDlgItemMessage(hwnd, MEMORYEDITOR_MODE, WM_SETFONT, (WPARAM)hFont, 0); + SendDlgItemMessage(hwnd, MEMORYEDITOR_GOTOADDR, WM_SETFONT, (WPARAM)hMonofont, 0); + SendDlgItemMessage(hwnd, MEMORYEDITOR_GOTO, WM_SETFONT, (WPARAM)hFont, 0); + SendDlgItemMessage(hwnd, MEMORYEDITOR_STATIC1, WM_SETFONT, (WPARAM)hFont, 0); + SendDlgItemMessage(hwnd, MEMORYEDITOR_OFFSET, WM_SETFONT, (WPARAM)hMonofont, 0); + SendDlgItemMessage(hwnd, MEMORYEDITOR_VALUE, WM_SETFONT, (WPARAM)hMonofont, 0); + SendDlgItemMessage(hwnd, MEMORYEDITOR_EDIT, WM_SETFONT, (WPARAM)hFont, 0); + SendDlgItemMessage(hwnd, MEMORYEDITOR_FSOURCE, WM_SETFONT, (WPARAM)hFont, 0); + SendDlgItemMessage(hwnd, MEMORYEDITOR_FEXPORT, WM_SETFONT, (WPARAM)hFont, 0); + SendDlgItemMessage(hwnd, MEMORYEDITOR_AUTOUPDATE, WM_SETFONT, (WPARAM)hFont, 0); + SendDlgItemMessage(hwnd, MEMORYEDITOR_UPDATE, WM_SETFONT, (WPARAM)hFont, 0); SendDlgItemMessage(hwnd, MEMORYEDITOR_MODE, CB_ADDSTRING, 0, (LPARAM)"DRAM"); SendDlgItemMessage(hwnd, MEMORYEDITOR_MODE, CB_ADDSTRING, 0, (LPARAM)"ROM"); SendDlgItemMessage(hwnd, MEMORYEDITOR_MODE, CB_ADDSTRING, 0, (LPARAM)"SRAM"); + SendDlgItemMessage(hwnd, MEMORYEDITOR_MODE, CB_ADDSTRING, 0, (LPARAM)"SPCRAM"); SendDlgItemMessage(hwnd, MEMORYEDITOR_MODE, CB_ADDSTRING, 0, (LPARAM)"VRAM"); SendDlgItemMessage(hwnd, MEMORYEDITOR_MODE, CB_ADDSTRING, 0, (LPARAM)"OAM"); SendDlgItemMessage(hwnd, MEMORYEDITOR_MODE, CB_ADDSTRING, 0, (LPARAM)"CGRAM"); @@ -309,6 +386,7 @@ void MemoryEditor::create_controls() { SendDlgItemMessage(hwnd, MEMORYEDITOR_FSOURCE, CB_ADDSTRING, 0, (LPARAM)"DRAM"); SendDlgItemMessage(hwnd, MEMORYEDITOR_FSOURCE, CB_ADDSTRING, 0, (LPARAM)"SRAM"); + SendDlgItemMessage(hwnd, MEMORYEDITOR_FSOURCE, CB_ADDSTRING, 0, (LPARAM)"SPCRAM"); SendDlgItemMessage(hwnd, MEMORYEDITOR_FSOURCE, CB_ADDSTRING, 0, (LPARAM)"VRAM"); SendDlgItemMessage(hwnd, MEMORYEDITOR_FSOURCE, CB_ADDSTRING, 0, (LPARAM)"OAM"); SendDlgItemMessage(hwnd, MEMORYEDITOR_FSOURCE, CB_ADDSTRING, 0, (LPARAM)"CGRAM"); @@ -324,4 +402,6 @@ uint32 style; style = GetWindowLong(h, GWL_STYLE); if(style & WS_DISABLED)ctl_disabled[i] = true; } + + auto_update = false; } diff --git a/src/win/ui_window.cpp b/src/win/ui_window.cpp index 1696d73c..14695fe2 100644 --- a/src/win/ui_window.cpp +++ b/src/win/ui_window.cpp @@ -80,6 +80,7 @@ int width, height; void Window::show() { int style; + visible = true; style = GetWindowLong(hwnd, GWL_STYLE); if(style & WS_VISIBLE)return; ShowWindow(hwnd, SW_NORMAL); @@ -87,6 +88,7 @@ int style; void Window::hide() { int style; + visible = false; style = GetWindowLong(hwnd, GWL_STYLE); if(!(style & WS_VISIBLE))return; ShowWindow(hwnd, SW_HIDE); diff --git a/src/win/uictl_editex.cpp b/src/win/uictl_editex.cpp new file mode 100644 index 00000000..e05dd5a9 --- /dev/null +++ b/src/win/uictl_editex.cpp @@ -0,0 +1,75 @@ +void editex_setbackcolor(HWND hwnd, COLORREF color) { + SendMessage(hwnd, EM_SETBKGNDCOLOR, 0, color); +} + +/* + This command attempts to apply line color highlighting + to a RichEdit 2.0 control. It tries to set the colors + of blank lines, CPU message lines, APU message lines, + and debug message lines to differing colors to aid in + readability. It expects the input variable char *str + to be in a special format where every line is exactly + 80 characters long. This is so that setting the + background color of the line covers the entire width + of the window. + + It auto-detects what type of message each line is by + assuming formatting information returned by + cpu->disassemble_op(n) and apu->disassemble_op(n). +*/ +enum { EDITEX_NOALIGN = 0, EDITEX_ALIGNTOP, EDITEX_ALIGNBOTTOM }; +void editex_settext(HWND hwnd, char *str, uint8 *linecol, uint8 align) { +char *t; +int sl, lines; + SetWindowText(hwnd, str); + if(!strcmp(str, ""))return; + + sl = strlen(str); + lines = (sl + 1) / 80; + +CHARFORMAT2 cf; +CHARRANGE cr; + memset(&cf, 0, sizeof(cf)); + cf.cbSize = sizeof(cf); + cf.dwMask = CFM_COLOR | CFM_BACKCOLOR; + cf.crTextColor = RGB(255, 255, 255); + +int pos = 0; + for(int i=0;i(snes); } void term_snes() { - if(clock) { delete(clock); clock = 0; } +//if(clock) { delete(clock); clock = 0; } if(mem_bus) { delete(mem_bus); mem_bus = 0; } if(cpu) { delete(cpu); cpu = 0; } + if(apu) { delete(apu); apu = 0; } if(ppu) { delete(ppu); ppu = 0; } if(snes) { delete(snes); snes = 0; } } @@ -39,9 +45,9 @@ void term_snes() { void get_config_fn(string &str) { char *t = (char*)malloc(4096); _getcwd(t, 4095); - str = t; + strcpy(str, t); free(t); - str += "\\bsnes.cfg"; + strcat(str, "\\bsnes.cfg"); } int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { @@ -58,13 +64,14 @@ string cfg_fn; init_snes(); init_ui1(); - if(lpCmdLine) { - if(*lpCmdLine) { - rom_image->select(lpCmdLine); - rom_image->load(); - snes->power(); - bsnes->debugger_update(); - } +int argc = __argc; +char **argv = __argv; + + if(argc >= 2) { + rom_image->select(argv[1]); + rom_image->load(); + snes->power(); + bsnes->debugger_update(); } while(1) { @@ -73,7 +80,7 @@ string cfg_fn; TranslateMessage(&msg); DispatchMessage(&msg); } - bsnes->run(); + bsnes->snes_run(); } cfg.save(cfg_fn); diff --git a/src/win/winmain.h b/src/win/winmain.h index f990b93c..2784204e 100644 --- a/src/win/winmain.h +++ b/src/win/winmain.h @@ -2,6 +2,7 @@ //#define WIN32_LEAN_AND_MEAN #include #include +#include #include "../lib/libbase.h" #include "../lib/libvector.h" #include "../lib/libstring.h"