From 6f7cf1bd31aa491922cd68379e6a53be83d6607d Mon Sep 17 00:00:00 2001 From: byuu Date: Sun, 6 Feb 2005 04:04:32 +0000 Subject: [PATCH] Update to bsnes v005a release. [No changelog available] --- bsnes/Makefile | 11 +- bsnes/apu/dspc700.cpp | 314 ++++++ bsnes/apu/spc700.cpp | 49 + bsnes/apu/spc700.h | 24 + bsnes/apu/spc700_iplrom.h | 35 + bsnes/apu/spc700_ops.cpp | 194 ++++ bsnes/apu/spc700_ops_adc.cpp | 114 ++ bsnes/apu/spc700_ops_and.cpp | 147 +++ bsnes/apu/spc700_ops_cmp.cpp | 142 +++ bsnes/apu/spc700_ops_eor.cpp | 148 +++ bsnes/apu/spc700_ops_flags.cpp | 48 + bsnes/apu/spc700_ops_incdec.cpp | 135 +++ bsnes/apu/spc700_ops_misc.cpp | 241 ++++ bsnes/apu/spc700_ops_mov.cpp | 377 +++++++ bsnes/apu/spc700_ops_or.cpp | 147 +++ bsnes/apu/spc700_ops_pc.cpp | 342 ++++++ bsnes/apu/spc700_ops_sbc.cpp | 111 ++ bsnes/apu/spc700_ops_shift.cpp | 195 ++++ bsnes/apu/spc700_ops_stack.cpp | 48 + bsnes/base.h | 190 +++- bsnes/bridge/bridge.cpp | 26 + bsnes/bridge/bridge.h | 11 + bsnes/bsnes.exe | Bin 233472 -> 258048 bytes bsnes/cpu/d65816.cpp | 18 +- bsnes/cpu/g65816.cpp | 132 +-- bsnes/cpu/g65816.h | 44 +- bsnes/cpu/g65816_ops.cpp | 25 +- bsnes/cpu/g65816_ops_adc.cpp | 845 ++++++++------ bsnes/cpu/g65816_ops_and.cpp | 811 ++++++++------ bsnes/cpu/g65816_ops_cmp.cpp | 811 ++++++++------ bsnes/cpu/g65816_ops_eor.cpp | 811 ++++++++------ bsnes/cpu/g65816_ops_incdec.cpp | 584 ++++++---- bsnes/cpu/g65816_ops_lda.cpp | 811 ++++++++------ bsnes/cpu/g65816_ops_misc.cpp | 1868 +++++++++++++++++++------------ bsnes/cpu/g65816_ops_ora.cpp | 811 ++++++++------ bsnes/cpu/g65816_ops_pc.cpp | 544 ++++++--- bsnes/cpu/g65816_ops_sbc.cpp | 845 ++++++++------ bsnes/cpu/g65816_ops_shift.cpp | 1050 ++++++++++------- bsnes/cpu/g65816_ops_sta.cpp | 507 ++++++--- bsnes/cpu/g65816_ops_stack.cpp | 392 ++++--- bsnes/d65816.obj | Bin 84902 -> 0 bytes bsnes/demo.smc | Bin 131584 -> 0 bytes bsnes/demo.srm | Bin 8192 -> 0 bytes bsnes/demo_mode1.smc | Bin 131584 -> 0 bytes bsnes/demo_mode1.srm | Bin 8192 -> 0 bytes bsnes/demo_mode4.smc | Bin 131584 -> 0 bytes bsnes/demo_mode4.srm | Bin 8192 -> 0 bytes bsnes/g65816.obj | Bin 289767 -> 0 bytes bsnes/gui.obj | Bin 67128 -> 0 bytes bsnes/libstr.obj | Bin 38996 -> 0 bytes bsnes/main.cpp | 183 ++- bsnes/main.h | 19 +- bsnes/main.obj | Bin 11653 -> 0 bytes bsnes/mem/memory.cpp | 300 ++--- bsnes/memory.obj | Bin 11196 -> 0 bytes bsnes/mmio.obj | Bin 81207 -> 0 bytes bsnes/ppu/mmio.cpp | 112 +- bsnes/ppu/ppu.cpp | 366 +++--- bsnes/ppu/ppu_cache.cpp | 13 +- bsnes/ppu/ppu_dma.cpp | 581 ++++------ bsnes/ppu/ppu_mode7.cpp | 33 +- bsnes/ppu/ppu_muldiv.cpp | 15 +- bsnes/ppu/ppu_palette.cpp | 13 +- bsnes/ppu/ppu_render.cpp | 556 +++++---- bsnes/ppu/ppu_render_mode7.cpp | 121 ++ bsnes/ppu/ppu_render_mode7f.cpp | 74 -- bsnes/ppu/ppu_render_mode7i.cpp | 66 -- bsnes/ppu/ppu_screen.cpp | 21 +- bsnes/ppu/ppu_scroll.cpp | 6 +- bsnes/ppu/ppu_spc.cpp | 34 + bsnes/ppu/ppu_timing.cpp | 124 +- bsnes/ppu/ppu_vram.cpp | 75 +- bsnes/ppu/ppu_wram.cpp | 12 +- bsnes/timing.obj | Bin 3162 -> 0 bytes bsnes/timing/timing.cpp | 427 +++++-- bsnes/timing/timing.h | 50 +- bsnes/win/gui.cpp | 79 +- bsnes/win/gui_bp.cpp | 224 ++-- bsnes/win/gui_cpu.cpp | 503 ++++++--- bsnes/win/gui_mem.cpp | 196 ++-- bsnes/win/render.cpp | 160 +-- bsnes/win/render_modes.cpp | 337 +----- 82 files changed, 12410 insertions(+), 6248 deletions(-) create mode 100644 bsnes/apu/dspc700.cpp create mode 100644 bsnes/apu/spc700.cpp create mode 100644 bsnes/apu/spc700.h create mode 100644 bsnes/apu/spc700_iplrom.h create mode 100644 bsnes/apu/spc700_ops.cpp create mode 100644 bsnes/apu/spc700_ops_adc.cpp create mode 100644 bsnes/apu/spc700_ops_and.cpp create mode 100644 bsnes/apu/spc700_ops_cmp.cpp create mode 100644 bsnes/apu/spc700_ops_eor.cpp create mode 100644 bsnes/apu/spc700_ops_flags.cpp create mode 100644 bsnes/apu/spc700_ops_incdec.cpp create mode 100644 bsnes/apu/spc700_ops_misc.cpp create mode 100644 bsnes/apu/spc700_ops_mov.cpp create mode 100644 bsnes/apu/spc700_ops_or.cpp create mode 100644 bsnes/apu/spc700_ops_pc.cpp create mode 100644 bsnes/apu/spc700_ops_sbc.cpp create mode 100644 bsnes/apu/spc700_ops_shift.cpp create mode 100644 bsnes/apu/spc700_ops_stack.cpp create mode 100644 bsnes/bridge/bridge.cpp create mode 100644 bsnes/bridge/bridge.h delete mode 100644 bsnes/d65816.obj delete mode 100644 bsnes/demo.smc delete mode 100644 bsnes/demo.srm delete mode 100644 bsnes/demo_mode1.smc delete mode 100644 bsnes/demo_mode1.srm delete mode 100644 bsnes/demo_mode4.smc delete mode 100644 bsnes/demo_mode4.srm delete mode 100644 bsnes/g65816.obj delete mode 100644 bsnes/gui.obj delete mode 100644 bsnes/libstr.obj delete mode 100644 bsnes/main.obj delete mode 100644 bsnes/memory.obj delete mode 100644 bsnes/mmio.obj create mode 100644 bsnes/ppu/ppu_render_mode7.cpp delete mode 100644 bsnes/ppu/ppu_render_mode7f.cpp delete mode 100644 bsnes/ppu/ppu_render_mode7i.cpp create mode 100644 bsnes/ppu/ppu_spc.cpp delete mode 100644 bsnes/timing.obj diff --git a/bsnes/Makefile b/bsnes/Makefile index c037c5e1..f9bf879a 100644 --- a/bsnes/Makefile +++ b/bsnes/Makefile @@ -1,6 +1,6 @@ CC = cl CFLAGS = /nologo /O2 -OBJS = main.obj timing.obj g65816.obj d65816.obj memory.obj mmio.obj gui.obj libstr.obj +OBJS = main.obj timing.obj g65816.obj d65816.obj spc700.obj dspc700.obj memory.obj mmio.obj bridge.obj gui.obj libstr.obj LIBS = kernel32.lib user32.lib gdi32.lib comdlg32.lib ddraw.lib all: $(OBJS) @@ -21,12 +21,21 @@ g65816.obj: cpu/g65816*.cpp cpu/g65816.h d65816.obj: cpu/d65816.cpp $(CC) $(CFLAGS) /c cpu/d65816.cpp +spc700.obj: apu/spc700*.cpp apu/spc700*.h + $(CC) $(CFLAGS) /c apu/spc700.cpp + +dspc700.obj: apu/dspc700.cpp + $(CC) $(CFLAGS) /c apu/dspc700.cpp + memory.obj: mem/memory.cpp $(CC) $(CFLAGS) /c mem/memory.cpp mmio.obj: ppu/mmio.cpp ppu/ppu*.cpp $(CC) $(CFLAGS) /c ppu/mmio.cpp +bridge.obj: bridge/bridge.cpp bridge/bridge.h + $(CC) $(CFLAGS) /c bridge/bridge.cpp + gui.obj: win/gui*.cpp win/render*.cpp $(CC) $(CFLAGS) /c win/gui.cpp diff --git a/bsnes/apu/dspc700.cpp b/bsnes/apu/dspc700.cpp new file mode 100644 index 00000000..2359ac59 --- /dev/null +++ b/bsnes/apu/dspc700.cpp @@ -0,0 +1,314 @@ +#include "../base.h" +#include "spc700.h" +extern sony_spc700 *spc700; +extern debugstate debugger; + +char __disas_spc700_str[256]; + +word __disas_spc700_relb(byte arg, byte offset) { +word r = spc700->regs.pc + (signed char)arg; + r += offset; + return r; +} + +void __disas_spc700_op(byte op, byte op0, byte op1) { +char *s = (char*)__disas_spc700_str; +word opw = (op1 << 8) | (op0); + switch(op) { + case 0x00:sprintf(s, "nop");break; + case 0x01:sprintf(s, "tcall 0");break; + case 0x02:sprintf(s, "set0 $%0.2x", op0);break; + case 0x03:sprintf(s, "bbs0 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0x04:sprintf(s, "or a,$%0.2x", op0);break; + case 0x05:sprintf(s, "or a,$%0.4x", opw);break; + case 0x06:sprintf(s, "or a,(x)");break; + case 0x07:sprintf(s, "or a,($%0.2x+x)", op0);break; + case 0x08:sprintf(s, "or a,#$%0.2x", op0);break; + case 0x09:sprintf(s, "or ($%0.2x),($%0.2x)", op1, op0);break; + case 0x0a:sprintf(s, "or1 c,$%0.4x,%d", opw & 0x1fff, opw >> 13);break; + case 0x0b:sprintf(s, "asl $%0.2x", op0);break; + case 0x0c:sprintf(s, "mov $%0.4x,y", opw);break; + case 0x0d:sprintf(s, "push psw");break; + case 0x0e:sprintf(s, "tset1 $%0.4x", opw);break; + case 0x0f:sprintf(s, "brk");break; + case 0x10:sprintf(s, "bpl $%0.4x", __disas_spc700_relb(op0, 2));break; + case 0x11:sprintf(s, "tcall 1");break; + case 0x12:sprintf(s, "clr0 $%0.2x", op0);break; + case 0x13:sprintf(s, "bbc0 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0x14:sprintf(s, "or a,$%0.2x+x", op0);break; + case 0x15:sprintf(s, "or a,$%0.4x+x", opw);break; + case 0x16:sprintf(s, "or a,$%0.4x+y", opw);break; + case 0x17:sprintf(s, "or a,($%0.2x)+y", op0);break; + case 0x18:sprintf(s, "or $%0.2x,#$%0.2x", op1, op0);break; + case 0x19:sprintf(s, "or (x),(y)");break; + case 0x1a:sprintf(s, "decw $%0.2x", op0);break; + case 0x1b:sprintf(s, "asl $%0.2x+x", op0);break; + case 0x1c:sprintf(s, "asl a");break; + case 0x1d:sprintf(s, "dec x");break; + case 0x1e:sprintf(s, "cmp x,$%0.4x", opw);break; + case 0x1f:sprintf(s, "jmp ($%0.4x+x)", opw);break; + case 0x20:sprintf(s, "clrp");break; + case 0x21:sprintf(s, "tcall 2");break; + case 0x22:sprintf(s, "set1 $%0.2x", op0);break; + case 0x23:sprintf(s, "bbs1 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0x24:sprintf(s, "and a,$%0.2x", op0);break; + case 0x25:sprintf(s, "and a,$%0.4x", opw);break; + case 0x26:sprintf(s, "and a,(x)", op0);break; + case 0x27:sprintf(s, "and a,($%0.2x+x)", op0);break; + case 0x28:sprintf(s, "and a,#$%0.2x", op0);break; + case 0x29:sprintf(s, "and ($%0.2x),($%0.2x)", op1, op0);break; + case 0x2a:sprintf(s, "or1 c,!$%0.4x,%d", opw & 0x1fff, opw >> 13);break; + case 0x2b:sprintf(s, "rol $%0.2x", op0);break; + case 0x2c:sprintf(s, "rol $%0.4x", opw);break; + case 0x2d:sprintf(s, "push a");break; + case 0x2e:sprintf(s, "cbne $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0x2f:sprintf(s, "bra $%0.4x", __disas_spc700_relb(op0, 2));break; + case 0x30:sprintf(s, "bmi $%0.4x", __disas_spc700_relb(op0, 2));break; + case 0x31:sprintf(s, "tcall 3");break; + case 0x32:sprintf(s, "clr1 $%0.2x", op0);break; + case 0x33:sprintf(s, "bbc1 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0x34:sprintf(s, "and a,$%0.2x+x", op0);break; + case 0x35:sprintf(s, "and a,$%0.4x+x", opw);break; + case 0x36:sprintf(s, "and a,$%0.4x+y", opw);break; + case 0x37:sprintf(s, "and a,($%0.2x)+y", op0);break; + case 0x38:sprintf(s, "and $%0.2x,#$%0.2x", op1, op0);break; + case 0x39:sprintf(s, "and (x),(y)");break; + case 0x3a:sprintf(s, "incw $%0.2x", op0);break; + case 0x3b:sprintf(s, "rol $%0.2x+x", op0);break; + case 0x3c:sprintf(s, "rol a");break; + case 0x3d:sprintf(s, "inc x");break; + case 0x3e:sprintf(s, "cmp x,$%0.2x", op0);break; + case 0x3f:sprintf(s, "call $%0.4x", opw);break; + case 0x40:sprintf(s, "setp");break; + case 0x41:sprintf(s, "tcall 4");break; + case 0x42:sprintf(s, "set2 $%0.2x", op0);break; + case 0x43:sprintf(s, "bbs2 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0x44:sprintf(s, "eor a,$%0.2x", op0);break; + case 0x45:sprintf(s, "eor a,$%0.4x", opw);break; + case 0x46:sprintf(s, "eor a,(x)");break; + case 0x47:sprintf(s, "eor a,($%0.2x+x)", op0);break; + case 0x48:sprintf(s, "eor a,#$%0.2x", op0);break; + case 0x49:sprintf(s, "eor ($%0.2x),($%0.2x)", op1, op0);break; + case 0x4a:sprintf(s, "and1 c,$%0.4x,%d", opw & 0x1fff, opw >> 13);break; + case 0x4b:sprintf(s, "lsr $%0.2x", op0);break; + case 0x4c:sprintf(s, "lsr $%0.4x", opw);break; + case 0x4d:sprintf(s, "push x");break; + case 0x4e:sprintf(s, "tclr1 $%0.4x", opw);break; + case 0x4f:sprintf(s, "pcall $%0.2x", op0);break; + case 0x50:sprintf(s, "bvc $%0.4x", __disas_spc700_relb(op0, 2));break; + case 0x51:sprintf(s, "tcall 5");break; + case 0x52:sprintf(s, "clr2 $%0.2x", op0);break; + case 0x53:sprintf(s, "bbc2 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0x54:sprintf(s, "eor a,$%0.2x+x", op0);break; + case 0x55:sprintf(s, "eor a,$%0.4x+x", opw);break; + case 0x56:sprintf(s, "eor a,$%0.4x+y", opw);break; + case 0x57:sprintf(s, "eor a,($%0.2x)+y", op0);break; + case 0x58:sprintf(s, "eor $%0.2x,#$%0.2x", op1, op0);break; + case 0x59:sprintf(s, "eor (x),(y)", op0);break; + case 0x5a:sprintf(s, "cmpw ya,$%0.2x", op0);break; + case 0x5b:sprintf(s, "lsr $%0.2x+x", op0);break; + case 0x5c:sprintf(s, "lsr a");break; + case 0x5d:sprintf(s, "mov x,a");break; + case 0x5e:sprintf(s, "cmp y,$%0.4x", opw);break; + case 0x5f:sprintf(s, "jmp $%0.4x", opw);break; + case 0x60:sprintf(s, "clrc");break; + case 0x61:sprintf(s, "tcall 6");break; + case 0x62:sprintf(s, "set3 $%0.2x", op0);break; + case 0x63:sprintf(s, "bbs3 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0x64:sprintf(s, "cmp a,$%0.2x", op0);break; + case 0x65:sprintf(s, "cmp a,$%0.4x", opw);break; + case 0x66:sprintf(s, "cmp a,(x)", op0);break; + case 0x67:sprintf(s, "cmp a,($%0.2x+x)", op0);break; + case 0x68:sprintf(s, "cmp a,#$%0.2x", op0);break; + case 0x69:sprintf(s, "cmp ($%0.2x),($%0.2x)", op1, op0);break; + case 0x6a:sprintf(s, "and1 c,!$%0.4x,%d", opw & 0x1fff, opw >> 13);break; + case 0x6b:sprintf(s, "ror $%0.2x", op0);break; + case 0x6c:sprintf(s, "ror $%0.4x", opw);break; + case 0x6d:sprintf(s, "push y");break; + case 0x6e:sprintf(s, "dbnz $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0x6f:sprintf(s, "ret");break; + case 0x70:sprintf(s, "bvs $%0.4x", __disas_spc700_relb(op0, 2));break; + case 0x71:sprintf(s, "tcall 7");break; + case 0x72:sprintf(s, "clr3 $%0.2x", op0);break; + case 0x73:sprintf(s, "bbc3 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0x74:sprintf(s, "cmp a,$%0.2x+x", op0);break; + case 0x75:sprintf(s, "cmp a,$%0.4x+x", opw);break; + case 0x76:sprintf(s, "cmp a,$%0.4x+y", opw);break; + case 0x77:sprintf(s, "cmp a,($%0.2x)+y", op0);break; + case 0x78:sprintf(s, "cmp $%0.2x,#$%0.2x", op1, op0);break; + case 0x79:sprintf(s, "cmp (x),(y)");break; + case 0x7a:sprintf(s, "addw ya,$%0.2x", op0);break; + case 0x7b:sprintf(s, "ror $%0.2x+x", op0);break; + case 0x7c:sprintf(s, "ror a");break; + case 0x7d:sprintf(s, "mov a,x");break; + case 0x7e:sprintf(s, "cmp y,$%0.2x", op0);break; + case 0x7f:sprintf(s, "reti");break; + case 0x80:sprintf(s, "setc");break; + case 0x81:sprintf(s, "tcall 8");break; + case 0x82:sprintf(s, "set4 $%0.2x", op0);break; + case 0x83:sprintf(s, "bbs4 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0x84:sprintf(s, "adc a,$%0.2x", op0);break; + case 0x85:sprintf(s, "adc a,$%0.4x", opw);break; + case 0x86:sprintf(s, "adc a,(x)", op0);break; + case 0x87:sprintf(s, "adc a,($%0.2x+x)", op0);break; + case 0x88:sprintf(s, "adc a,#$%0.2x", op0);break; + case 0x89:sprintf(s, "adc ($%0.2x),($%0.2x)", op1, op0);break; + case 0x8a:sprintf(s, "eor1 c,$%0.4x,%d", opw & 0x1fff, opw >> 13);break; + case 0x8b:sprintf(s, "dec $%0.2x", op0);break; + case 0x8c:sprintf(s, "dec $%0.4x", opw);break; + case 0x8d:sprintf(s, "mov y,#$%0.2x", op0);break; + case 0x8e:sprintf(s, "pop psw");break; + case 0x8f:sprintf(s, "mov $%0.2x,#$%0.2x", op1, op0);break; + case 0x90:sprintf(s, "bcc $%0.4x", __disas_spc700_relb(op0, 2));break; + case 0x91:sprintf(s, "tcall 9");break; + case 0x92:sprintf(s, "clr4 $%0.2x", op0);break; + case 0x93:sprintf(s, "bbc4 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0x94:sprintf(s, "adc a,$%0.2x+x", op0);break; + case 0x95:sprintf(s, "adc a,$%0.4x+x", opw);break; + case 0x96:sprintf(s, "adc a,$%0.4x+y", opw);break; + case 0x97:sprintf(s, "adc a,($%0.2x)+y", op0);break; + case 0x98:sprintf(s, "adc $%0.2x,#$%0.2x", op1, op0);break; + case 0x99:sprintf(s, "adc (x),(y)", op0);break; + case 0x9a:sprintf(s, "subw ya,$%0.2x", op0);break; + case 0x9b:sprintf(s, "dec $%0.2x+x", op0);break; + case 0x9c:sprintf(s, "dec a");break; + case 0x9d:sprintf(s, "mov x,sp");break; + case 0x9e:sprintf(s, "div ya,x");break; + case 0x9f:sprintf(s, "xcn a");break; + case 0xa0:sprintf(s, "ei");break; + case 0xa1:sprintf(s, "tcall 10");break; + case 0xa2:sprintf(s, "set5 $%0.2x", op0);break; + case 0xa3:sprintf(s, "bbs5 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0xa4:sprintf(s, "sbc a,$%0.2x", op0);break; + case 0xa5:sprintf(s, "sbc a,$%0.4x", opw);break; + case 0xa6:sprintf(s, "sbc a,(x)", op0);break; + case 0xa7:sprintf(s, "sbc a,($%0.2x+x)", op0);break; + case 0xa8:sprintf(s, "sbc a,#$%0.2x", op0);break; + case 0xa9:sprintf(s, "sbc ($%0.2x),($%0.2x)", op1, op0);break; + case 0xaa:sprintf(s, "mov1 c,$%0.4x,%d", opw & 0x1fff, opw >> 13);break; + case 0xab:sprintf(s, "inc $%0.2x", op0);break; + case 0xac:sprintf(s, "inc $%0.4x", opw);break; + case 0xad:sprintf(s, "cmp y,#$%0.2x", op0);break; + case 0xae:sprintf(s, "pop a");break; + case 0xaf:sprintf(s, "mov (x)+,a");break; + case 0xb0:sprintf(s, "bcs $%0.4x", __disas_spc700_relb(op0, 2));break; + case 0xb1:sprintf(s, "tcall 11");break; + case 0xb2:sprintf(s, "clr5 $%0.2x", op0);break; + case 0xb3:sprintf(s, "bbc5 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0xb4:sprintf(s, "sbc a,$%0.2x+x", op0);break; + case 0xb5:sprintf(s, "sbc a,$%0.4x+x", opw);break; + case 0xb6:sprintf(s, "sbc a,$%0.4x+y", opw);break; + case 0xb7:sprintf(s, "sbc a,($%0.2x)+y", op0);break; + case 0xb8:sprintf(s, "sbc $%0.2x,#$%0.2x", op1, op0);break; + case 0xb9:sprintf(s, "sbc (x),(y)", op0);break; + case 0xba:sprintf(s, "movw ya,$%0.2x", op0);break; + case 0xbb:sprintf(s, "inc $%0.2x+x", op0);break; + case 0xbc:sprintf(s, "inc a");break; + case 0xbd:sprintf(s, "mov sp,x");break; + case 0xbe:sprintf(s, "das a");break; + case 0xbf:sprintf(s, "mov a,(x)+");break; + case 0xc0:sprintf(s, "di");break; + case 0xc1:sprintf(s, "tcall 12");break; + case 0xc2:sprintf(s, "set6 $%0.2x", op0);break; + case 0xc3:sprintf(s, "bbs6 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0xc4:sprintf(s, "mov $%0.2x,a", op0);break; + case 0xc5:sprintf(s, "mov $%0.4x,a", opw);break; + case 0xc6:sprintf(s, "mov (x),a");break; + case 0xc7:sprintf(s, "mov ($%0.2x+x),a", op0);break; + case 0xc8:sprintf(s, "cmp x,#$%0.2x", op0);break; + case 0xc9:sprintf(s, "mov $%0.4x,x", opw);break; + case 0xca:sprintf(s, "mov1 $%0.4x,%d,c", opw & 0x1fff, opw >> 13);break; + case 0xcb:sprintf(s, "mov $%0.2x,y", op0);break; + case 0xcc:sprintf(s, "asl $%0.4x", opw);break; + case 0xcd:sprintf(s, "mov x,#$%0.2x", op0);break; + case 0xce:sprintf(s, "pop x");break; + case 0xcf:sprintf(s, "mul ya");break; + case 0xd0:sprintf(s, "bne $%0.4x", __disas_spc700_relb(op0, 2));break; + case 0xd1:sprintf(s, "tcall 13");break; + case 0xd2:sprintf(s, "clr6 $%0.2x", op0);break; + case 0xd3:sprintf(s, "bbc6 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0xd4:sprintf(s, "mov $%0.2x+x,a", op0);break; + case 0xd5:sprintf(s, "mov $%0.4x+x,a", opw);break; + case 0xd6:sprintf(s, "mov $%0.4x+y,a", opw);break; + case 0xd7:sprintf(s, "mov ($%0.2x)+y,a", op0);break; + case 0xd8:sprintf(s, "mov $%0.2x,x", op0);break; + case 0xd9:sprintf(s, "mov $%0.2x+y,x", op0);break; + case 0xda:sprintf(s, "movw $%0.2x,ya", op0);break; + case 0xdb:sprintf(s, "mov $%0.2x+x,y", op0);break; + case 0xdc:sprintf(s, "dec y");break; + case 0xdd:sprintf(s, "mov a,y");break; + case 0xde:sprintf(s, "cbne $%0.2x+x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0xdf:sprintf(s, "daa a");break; + case 0xe0:sprintf(s, "clrv");break; + case 0xe1:sprintf(s, "tcall 14");break; + case 0xe2:sprintf(s, "set7 $%0.2x", op0);break; + case 0xe3:sprintf(s, "bbs7 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0xe4:sprintf(s, "mov a,$%0.2x", op0);break; + case 0xe5:sprintf(s, "mov a,$%0.4x", opw);break; + case 0xe6:sprintf(s, "mov a,(x)");break; + case 0xe7:sprintf(s, "mov a,($%0.2x+x)", op0);break; + case 0xe8:sprintf(s, "mov a,#$%0.2x", op0);break; + case 0xe9:sprintf(s, "mov x,$%0.4x", opw);break; + case 0xea:sprintf(s, "not1 $%0.4x,%d", opw & 0x1fff, opw >> 13);break; + case 0xeb:sprintf(s, "mov y,$%0.2x", op0);break; + case 0xec:sprintf(s, "mov y,$%0.4x", opw);break; + case 0xed:sprintf(s, "notc");break; + case 0xee:sprintf(s, "pop y");break; + case 0xef:sprintf(s, "sleep");break; + case 0xf0:sprintf(s, "beq $%0.4x", __disas_spc700_relb(op0, 2));break; + case 0xf1:sprintf(s, "tcall 15");break; + case 0xf2:sprintf(s, "clr7 $%0.2x", op0);break; + case 0xf3:sprintf(s, "bbc7 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break; + case 0xf4:sprintf(s, "mov a,$%0.2x+x", op0);break; + case 0xf5:sprintf(s, "mov a,$%0.4x+x", opw);break; + case 0xf6:sprintf(s, "mov a,$%0.4x+y", opw);break; + case 0xf7:sprintf(s, "mov a,($%0.2x)+y", op0);break; + case 0xf8:sprintf(s, "mov x,$%0.2x", op0);break; + case 0xf9:sprintf(s, "mov x,$%0.2x+y", op0);break; + case 0xfa:sprintf(s, "mov ($%0.2x),($%0.2x)", op1, op0);break; + case 0xfb:sprintf(s, "mov y,$%0.2x+x", op0);break; + case 0xfc:sprintf(s, "inc y");break; + case 0xfd:sprintf(s, "mov y,a");break; + case 0xfe:sprintf(s, "dbnz y,$%0.4x", __disas_spc700_relb(op0, 2));break; + case 0xff:sprintf(s, "stop");break; + } +} + +void disas_spc700_op(void) { +byte op; +byte op0, op1; +word offset; +char flags[256]; +char *s = (char*)__disas_spc700_str; +int i; + if(debug_write_status() == DEBUGWRITE_NONE)return; + +//use offset instead of spc700->regs.pc + n to avoid going above 65535 + offset = spc700->regs.pc; + op = spc700->ram[offset++]; + op0 = spc700->ram[offset++]; + op1 = spc700->ram[offset ]; + + strcpy(__disas_spc700_str, "???"); + __disas_spc700_op(op, op0, op1); + i = strlen(s); + while(i < 23) { + s[i++] = ' '; + s[i] = 0; + } + + sprintf(flags, "%c%c%c%c%c%c%c%c", + (spc700->regs.p & 0x80)?'N':'n', + (spc700->regs.p & 0x40)?'V':'v', + (spc700->regs.p & 0x20)?'P':'p', + (spc700->regs.p & 0x10)?'B':'b', + (spc700->regs.p & 0x08)?'H':'h', + (spc700->regs.p & 0x04)?'I':'i', + (spc700->regs.p & 0x02)?'Z':'z', + (spc700->regs.p & 0x01)?'C':'c'); + + dprintf(DEBUGMSG_APU, "--%0.4x %s A:%0.2x X:%0.2x Y:%0.2x SP:%0.2x YA:%0.4x %s", + spc700->regs.pc, __disas_spc700_str, + spc700->regs.a, spc700->regs.x, spc700->regs.y, spc700->regs.sp, + (spc700->regs.y << 8) | (spc700->regs.a), flags); +} diff --git a/bsnes/apu/spc700.cpp b/bsnes/apu/spc700.cpp new file mode 100644 index 00000000..f203de3e --- /dev/null +++ b/bsnes/apu/spc700.cpp @@ -0,0 +1,49 @@ +#include "../base.h" +#include "../timing/timing.h" +#include "../bridge/bridge.h" +#include "spc700_iplrom.h" +#include "spc700.h" + +extern snes_timer *snes_time; +extern debugstate debugger; +extern port_bridge *cpu_apu_bridge; +sony_spc700 *spc700; + +#include "spc700_ops.cpp" + +void sony_spc700::Reset(void) { + memset(ram, 0, 65536); + memcpy(ram + 0xffc0, spc700_iplrom, 64); + regs.pc = 0xffc0; + regs.a = regs.x = regs.y = regs.sp = 0x00; + regs.p = 0x02; + regs.dp = 0x0000; +} + +void sony_spc700::exec_op(void) { +byte op; + op = spc700->ram[spc700->regs.pc]; + spc700_optbl[op](); + debugger.apu_op_executed = true; + debugger.disas_apu_op = true; + + debug_test_bp(BPSRC_SPCRAM, BP_EXEC, spc700->regs.pc, 0); +} + +void sony_spc700::Run(void) { + if(snes_time->bridge.cpu_cycles >= snes_time->bridge.apu_cycles) { + exec_op(); + } + if(snes_time->bridge.cpu_cycles >= 65536 && snes_time->bridge.apu_cycles >= 65536) { + snes_time->bridge.cpu_cycles &= 65535; + snes_time->bridge.apu_cycles &= 65535; + } +} + +sony_spc700::sony_spc700() { + ram = (byte*)malloc(65536); +} + +sony_spc700::~sony_spc700() { + if(ram)free(ram); +} diff --git a/bsnes/apu/spc700.h b/bsnes/apu/spc700.h new file mode 100644 index 00000000..c07924e7 --- /dev/null +++ b/bsnes/apu/spc700.h @@ -0,0 +1,24 @@ +class sony_spc700 { +public: + struct { + word pc; + byte a, x, y, sp, p; + word dp; + }regs; + byte *ram; + + void Reset(void); + void Run(void); + + void exec_op(void); + word convert_address(byte mode, word addr); + byte mem_getbyte(word addr); + void mem_putbyte(word addr, byte value); + word mem_read(byte mode, byte size, word addr); + void mem_write(byte mode, byte size, word addr, word value); + byte stack_read(void); + void stack_write(byte value); + + sony_spc700(); + ~sony_spc700(); +}; diff --git a/bsnes/apu/spc700_iplrom.h b/bsnes/apu/spc700_iplrom.h new file mode 100644 index 00000000..e4b71093 --- /dev/null +++ b/bsnes/apu/spc700_iplrom.h @@ -0,0 +1,35 @@ +byte 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) +}; diff --git a/bsnes/apu/spc700_ops.cpp b/bsnes/apu/spc700_ops.cpp new file mode 100644 index 00000000..a3307d46 --- /dev/null +++ b/bsnes/apu/spc700_ops.cpp @@ -0,0 +1,194 @@ +#define spc700_setn() spc700->regs.p |= SPF_N +#define spc700_clrn() spc700->regs.p &= ~SPF_N +#define spc700_setv() spc700->regs.p |= SPF_V +#define spc700_clrv() spc700->regs.p &= ~SPF_V +#define spc700_setp() spc700->regs.p |= SPF_P;spc700->regs.dp = 0x0100 +#define spc700_clrp() spc700->regs.p &= ~SPF_P;spc700->regs.dp = 0x0000 +#define spc700_setb() spc700->regs.p |= SPF_B +#define spc700_clrb() spc700->regs.p &= ~SPF_B +#define spc700_seth() spc700->regs.p |= SPF_H +#define spc700_clrh() spc700->regs.p &= ~SPF_H +#define spc700_seti() spc700->regs.p |= SPF_I +#define spc700_clri() spc700->regs.p &= ~SPF_I +#define spc700_setz() spc700->regs.p |= SPF_Z +#define spc700_clrz() spc700->regs.p &= ~SPF_Z +#define spc700_setc() spc700->regs.p |= SPF_C +#define spc700_clrc() spc700->regs.p &= ~SPF_C +#define spc700_testn(x) if(x)spc700_setn(); else spc700_clrn() +#define spc700_testv(x) if(x)spc700_setv(); else spc700_clrv() +#define spc700_testp(x) if(x)spc700_setp(); else spc700_clrp() +#define spc700_testb(x) if(x)spc700_setb(); else spc700_clrb() +#define spc700_testh(x) if(x)spc700_seth(); else spc700_clrh() +#define spc700_testi(x) if(x)spc700_seti(); else spc700_clri() +#define spc700_testz(x) if(x)spc700_setz(); else spc700_clrz() +#define spc700_testc(x) if(x)spc700_setc(); else spc700_clrc() + +#define spc700_incpc(__n) spc700->regs.pc += __n + +#define spc700_prefetchb() \ + byte arg = spc700->ram[(spc700->regs.pc + 1) & 0xffff] + +#define spc700_prefetch2b() \ + byte arg0 = spc700->ram[(spc700->regs.pc + 1) & 0xffff]; \ + byte arg1 = spc700->ram[(spc700->regs.pc + 2) & 0xffff] + +#define spc700_prefetchw() \ + word arg = spc700->ram[(spc700->regs.pc + 1) & 0xffff] | (spc700->ram[(spc700->regs.pc + 2) & 0xffff] << 8) + +#define APUMODE_NONE 0 +#define APUMODE_DP 1 +#define APUMODE_DPX 2 +#define APUMODE_DPY 3 +#define APUMODE_IDP 4 +#define APUMODE_ADDR 5 +#define APUMODE_IX 6 +#define APUMODE_ADDRX 7 +#define APUMODE_ADDRY 8 +#define APUMODE_IDPX 9 +#define APUMODE_IDPY 10 +#define APUMODE_IADDRX 11 +#define APUMODE_IY 12 + +word sony_spc700::convert_address(byte mode, word addr) { +word r; + switch(mode) { + case APUMODE_NONE: + r = addr; + case APUMODE_DP: + r = spc700->regs.dp | (byte)addr; + break; + case APUMODE_DPX: + r = spc700->regs.dp | (byte)(addr + spc700->regs.x); + break; + case APUMODE_DPY: + r = spc700->regs.dp | (byte)(addr + spc700->regs.y); + break; + case APUMODE_IDP: + r = spc700->regs.dp | (byte)addr; + r = spc700->ram[r] | (spc700->ram[r + 1] << 8); + break; + case APUMODE_ADDR: + r = addr; + break; + case APUMODE_IX: + r = spc700->regs.dp | spc700->regs.x; + break; + case APUMODE_ADDRX: + r = addr + spc700->regs.x; + break; + case APUMODE_ADDRY: + r = addr + spc700->regs.y; + break; + case APUMODE_IDPX: + r = spc700->regs.dp | (byte)(addr + spc700->regs.x); + r = spc700->ram[r] | (spc700->ram[r + 1] << 8); + break; + case APUMODE_IDPY: + r = spc700->regs.dp | (byte)addr; + r = spc700->ram[r] | (spc700->ram[r + 1] << 8); + r += spc700->regs.y; + break; + case APUMODE_IADDRX: + r = (spc700->ram[(addr + spc700->regs.x )]) | + (spc700->ram[(addr + spc700->regs.x + 1)] << 8); + break; + case APUMODE_IY: + r = spc700->regs.dp | spc700->regs.y; + break; + } + return r; +} + +byte sony_spc700::mem_getbyte(word addr) { + if(addr >= 0x00f4 && addr <= 0x00f7) { + return cpu_apu_bridge->apu_read(addr - 0x00f4); + } else { + return spc700->ram[addr]; + } +} + +void sony_spc700::mem_putbyte(word addr, byte value) { + if(addr >= 0x00f4 && addr <= 0x00f7) { + cpu_apu_bridge->apu_write(addr - 0x00f4, value); + } else if(addr < 0xffc0) { + spc700->ram[addr] = value; + } +} + +word sony_spc700::mem_read(byte mode, byte size, word addr) { +word r; + addr = convert_address(mode, addr); + switch(size) { + case MEMSIZE_BYTE: + r = mem_getbyte(addr); + break; + case MEMSIZE_WORD: + r = mem_getbyte(addr) | (mem_getbyte(addr + 1) << 8); + break; + } + return r; +} + +void sony_spc700::mem_write(byte mode, byte size, word addr, word value) { + addr = convert_address(mode, addr); + switch(size) { + case MEMSIZE_BYTE: + mem_putbyte(addr, value); + break; + case MEMSIZE_WORD: + mem_putbyte(addr , value); + mem_putbyte(addr + 1, value >> 8); + break; + } +} + +byte sony_spc700::stack_read(void) { +word addr; + spc700->regs.sp++; + addr = 0x0100 | spc700->regs.sp; + return mem_getbyte(addr); +} + +void sony_spc700::stack_write(byte value) { +word addr; + addr = 0x0100 | spc700->regs.sp; + spc700->regs.sp--; + mem_putbyte(addr, value); +} + +#include "spc700_ops_adc.cpp" +#include "spc700_ops_and.cpp" +#include "spc700_ops_cmp.cpp" +#include "spc700_ops_eor.cpp" +#include "spc700_ops_flags.cpp" +#include "spc700_ops_incdec.cpp" +#include "spc700_ops_misc.cpp" +#include "spc700_ops_mov.cpp" +#include "spc700_ops_or.cpp" +#include "spc700_ops_pc.cpp" +#include "spc700_ops_sbc.cpp" +#include "spc700_ops_shift.cpp" +#include "spc700_ops_stack.cpp" + +vfunc spc700_optbl[256] = { + // -----------------------------x0, -----------------------------x1, -----------------------------x2, -----------------------------x3, -------- -----------------------------x4, -----------------------------x5, -----------------------------x6, -----------------------------x7, -------- -----------------------------x8, -----------------------------x9, -----------------------------xa, -----------------------------xb, -------- -----------------------------xc, -----------------------------xd, -----------------------------xe, -----------------------------xf, +/* 0x */ spc700_op_nop, spc700_op_tcall_0, spc700_op_set0_dp, spc700_op_bbc0, /* 0x */ spc700_op_or_a_dp, spc700_op_or_a_addr, spc700_op_or_a_ix, spc700_op_or_a_idpx, /* 0x */ spc700_op_or_a_const, spc700_op_or_dp_dp, spc700_op_or1_bit, spc700_op_asl_dp, /* 0x */ spc700_op_mov_addr_y, spc700_op_push_p, spc700_op_tset1_addr, spc700_op_brk, +/* 1x */ spc700_op_bpl, spc700_op_tcall_1, spc700_op_clr0_dp, spc700_op_bbs0, /* 1x */ spc700_op_or_a_dpx, spc700_op_or_a_addrx, spc700_op_or_a_addry, spc700_op_or_a_idpy, /* 1x */ spc700_op_or_dp_imm, spc700_op_or_ix_iy, spc700_op_decw_dp, spc700_op_asl_dpx, /* 1x */ spc700_op_asl_a, spc700_op_dec_x, spc700_op_cmp_x_addr, spc700_op_jmp_iaddrx, +/* 2x */ spc700_op_clrp, spc700_op_tcall_2, spc700_op_set1_dp, spc700_op_bbc1, /* 2x */ spc700_op_and_a_dp, spc700_op_and_a_addr, spc700_op_and_a_ix, spc700_op_and_a_idpx, /* 2x */ spc700_op_and_a_const, spc700_op_and_dp_dp, spc700_op_or1_notbit, spc700_op_rol_dp, /* 2x */ spc700_op_rol_addr, spc700_op_push_a, spc700_op_cbne_dp, spc700_op_bra, +/* 3x */ spc700_op_bmi, spc700_op_tcall_3, spc700_op_clr1_dp, spc700_op_bbs1, /* 3x */ spc700_op_and_a_dpx, spc700_op_and_a_addrx, spc700_op_and_a_addry, spc700_op_and_a_idpy, /* 3x */ spc700_op_and_dp_imm, spc700_op_and_ix_iy, spc700_op_incw_dp, spc700_op_rol_dpx, /* 3x */ spc700_op_rol_a, spc700_op_inc_x, spc700_op_cmp_x_dp, spc700_op_call, + +/* 4x */ spc700_op_setp, spc700_op_tcall_4, spc700_op_set2_dp, spc700_op_bbc2, /* 4x */ spc700_op_eor_a_dp, spc700_op_eor_a_addr, spc700_op_eor_a_ix, spc700_op_eor_a_idpx, /* 4x */ spc700_op_eor_a_const, spc700_op_eor_dp_dp, spc700_op_and1_bit, spc700_op_lsr_dp, /* 4x */ spc700_op_lsr_addr, spc700_op_push_x, spc700_op_tclr1_addr, spc700_op_pcall, +/* 5x */ spc700_op_bvc, spc700_op_tcall_5, spc700_op_clr2_dp, spc700_op_bbs2, /* 5x */ spc700_op_eor_a_dpx, spc700_op_eor_a_addrx, spc700_op_eor_a_addry, spc700_op_eor_a_idpy, /* 5x */ spc700_op_eor_dp_imm, spc700_op_eor_ix_iy, spc700_op_cmpw_ya_dp, spc700_op_lsr_dpx, /* 5x */ spc700_op_lsr_a, spc700_op_mov_x_a, spc700_op_cmp_y_addr, spc700_op_jmp_addr, +/* 6x */ spc700_op_clrc, spc700_op_tcall_6, spc700_op_set3_dp, spc700_op_bbc3, /* 6x */ spc700_op_cmp_a_dp, spc700_op_cmp_a_addr, spc700_op_cmp_a_ix, spc700_op_cmp_a_idpx, /* 6x */ spc700_op_cmp_a_const, spc700_op_cmp_dp_dp, spc700_op_and1_notbit, spc700_op_ror_dp, /* 6x */ spc700_op_ror_addr, spc700_op_push_y, spc700_op_dbnz_dp, spc700_op_ret, +/* 7x */ spc700_op_bvs, spc700_op_tcall_7, spc700_op_clr3_dp, spc700_op_bbs3, /* 7x */ spc700_op_cmp_a_dpx, spc700_op_cmp_a_addrx, spc700_op_cmp_a_addry, spc700_op_cmp_a_idpy, /* 7x */ spc700_op_cmp_dp_imm, spc700_op_cmp_ix_iy, spc700_op_addw_ya_dp, spc700_op_ror_dpx, /* 7x */ spc700_op_ror_a, spc700_op_mov_a_x, spc700_op_cmp_y_dp, spc700_op_reti, + +/* 8x */ spc700_op_setc, spc700_op_tcall_8, spc700_op_set4_dp, spc700_op_bbc4, /* 8x */ spc700_op_adc_a_dp, spc700_op_adc_a_addr, spc700_op_adc_a_ix, spc700_op_adc_a_idpx, /* 8x */ spc700_op_adc_a_const, spc700_op_adc_dp_dp, spc700_op_eor1_bit, spc700_op_dec_dp, /* 8x */ spc700_op_dec_addr, spc700_op_mov_y_const, spc700_op_pop_p, spc700_op_mov_dp_imm, +/* 9x */ spc700_op_bcc, spc700_op_tcall_9, spc700_op_clr4_dp, spc700_op_bbs4, /* 9x */ spc700_op_adc_a_dpx, spc700_op_adc_a_addrx, spc700_op_adc_a_addry, spc700_op_adc_a_idpy, /* 9x */ spc700_op_adc_dp_imm, spc700_op_adc_ix_iy, spc700_op_subw_ya_dp, spc700_op_dec_dpx, /* 9x */ spc700_op_dec_a, spc700_op_mov_x_sp, spc700_op_div_ya_x, spc700_op_xcn_a, +/* ax */ spc700_op_ei, spc700_op_tcall_10, spc700_op_set5_dp, spc700_op_bbc5, /* ax */ spc700_op_sbc_a_dp, spc700_op_sbc_a_addr, spc700_op_sbc_a_ix, spc700_op_sbc_a_idpx, /* ax */ spc700_op_sbc_a_const, spc700_op_sbc_dp_dp, spc700_op_mov1_c_bit, spc700_op_inc_dp, /* ax */ spc700_op_inc_addr, spc700_op_cmp_y_const, spc700_op_pop_a, spc700_op_mov_ixinc_a, +/* bx */ spc700_op_bcs, spc700_op_tcall_11, spc700_op_clr5_dp, spc700_op_bbs5, /* bx */ spc700_op_sbc_a_dpx, spc700_op_sbc_a_addrx, spc700_op_sbc_a_addry, spc700_op_sbc_a_idpy, /* bx */ spc700_op_sbc_dp_imm, spc700_op_sbc_ix_iy, spc700_op_mov_ya_dp, spc700_op_inc_dpx, /* bx */ spc700_op_inc_a, spc700_op_mov_sp_x, spc700_op_das_a, spc700_op_mov_a_ixinc, + +/* cx */ spc700_op_di, spc700_op_tcall_12, spc700_op_set6_dp, spc700_op_bbc6, /* cx */ spc700_op_mov_dp_a, spc700_op_mov_addr_a, spc700_op_mov_ix_a, spc700_op_mov_idpx_a, /* cx */ spc700_op_cmp_x_const, spc700_op_mov_addr_x, spc700_op_mov1_bit_c, spc700_op_mov_dp_y, /* cx */ spc700_op_asl_addr, spc700_op_mov_x_const, spc700_op_pop_x, spc700_op_mul_ya, +/* dx */ spc700_op_bne, spc700_op_tcall_13, spc700_op_clr6_dp, spc700_op_bbs6, /* dx */ spc700_op_mov_dpx_a, spc700_op_mov_addrx_a, spc700_op_mov_addry_a, spc700_op_mov_idpy_a, /* dx */ spc700_op_mov_dp_x, spc700_op_mov_dpy_x, spc700_op_mov_dp_ya, spc700_op_mov_dpx_y, /* dx */ spc700_op_dec_y, spc700_op_mov_a_y, spc700_op_cbne_dpx, spc700_op_daa_a, +/* ex */ spc700_op_clrv, spc700_op_tcall_14, spc700_op_set7_dp, spc700_op_bbc7, /* ex */ spc700_op_mov_a_dp, spc700_op_mov_a_addr, spc700_op_mov_a_ix, spc700_op_mov_a_idpx, /* ex */ spc700_op_mov_a_const, spc700_op_mov_x_addr, spc700_op_not1_bit, spc700_op_mov_y_dp, /* ex */ spc700_op_mov_y_addr, spc700_op_notc, spc700_op_pop_y, spc700_op_sleep, +/* fx */ spc700_op_beq, spc700_op_tcall_15, spc700_op_clr7_dp, spc700_op_bbs7, /* fx */ spc700_op_mov_a_dpx, spc700_op_mov_a_addrx, spc700_op_mov_a_addry, spc700_op_mov_a_idpy, /* fx */ spc700_op_mov_x_dp, spc700_op_mov_x_dpy, spc700_op_mov_dp_dp, spc700_op_mov_y_dpx, /* fx */ spc700_op_inc_y, spc700_op_mov_y_a, spc700_op_dbnz_y, spc700_op_stop +}; diff --git a/bsnes/apu/spc700_ops_adc.cpp b/bsnes/apu/spc700_ops_adc.cpp new file mode 100644 index 00000000..e403903e --- /dev/null +++ b/bsnes/apu/spc700_ops_adc.cpp @@ -0,0 +1,114 @@ +byte spc700_op_adc(byte x, byte y) { +word r = x + y + (spc700->regs.p & SPF_C); + spc700_testn(r & 0x80); + spc700_testv((~(x ^ y) & (y ^ (byte)r) & 0x80)); + spc700_testh((x ^ y ^ (byte)r) & 0x10); + spc700_testz((byte)r == 0); + spc700_testc(r >= 0x100); + return (byte)r; +} + +void spc700_op_adc_a_const(void) { +spc700_prefetchb(); + spc700->regs.a = spc700_op_adc(spc700->regs.a, arg); + spc700_incpc(2); + add_apu_cycles(2); +} + +void spc700_op_adc_a_ix(void) { + spc700->regs.a = spc700_op_adc(spc700->regs.a, spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0)); + spc700_incpc(1); + add_apu_cycles(3); +} + +void spc700_op_adc_a_dp(void) { +spc700_prefetchb(); + spc700->regs.a = spc700_op_adc(spc700->regs.a, spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg)); + spc700_incpc(2); + add_apu_cycles(3); +} + +void spc700_op_adc_a_dpx(void) { +spc700_prefetchb(); + spc700->regs.a = spc700_op_adc(spc700->regs.a, spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg)); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_adc_a_addr(void) { +spc700_prefetchw(); + spc700->regs.a = spc700_op_adc(spc700->regs.a, spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg)); + spc700_incpc(3); + add_apu_cycles(4); +} + +void spc700_op_adc_a_addrx(void) { +spc700_prefetchw(); + spc700->regs.a = spc700_op_adc(spc700->regs.a, spc700->mem_read(APUMODE_ADDRX, MEMSIZE_BYTE, arg)); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_adc_a_addry(void) { +spc700_prefetchw(); + spc700->regs.a += spc700->mem_read(APUMODE_ADDRY, MEMSIZE_BYTE, arg); + spc700->regs.a += (spc700->regs.p & PF_C); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_adc_a_idpx(void) { +spc700_prefetchb(); +word i; + spc700->regs.a = spc700_op_adc(spc700->regs.a, spc700->mem_read(APUMODE_IDPX, MEMSIZE_BYTE, arg)); + spc700_incpc(2); + add_apu_cycles(6); +} + +void spc700_op_adc_a_idpy(void) { +spc700_prefetchb(); + spc700->regs.a = spc700_op_adc(spc700->regs.a, spc700->mem_read(APUMODE_IDPY, MEMSIZE_BYTE, arg)); + spc700_incpc(2); + add_apu_cycles(6); +} + +void spc700_op_adc_ix_iy(void) { +byte x = spc700_op_adc(spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0), spc700->mem_read(APUMODE_IY, MEMSIZE_BYTE, 0)); + spc700->mem_write(APUMODE_IX, MEMSIZE_BYTE, 0, x); + spc700_incpc(1); + add_apu_cycles(5); +} + +void spc700_op_adc_dp_dp(void) { +spc700_prefetch2b(); +byte x = spc700_op_adc(spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1), spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0)); + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x); + spc700_incpc(3); + add_apu_cycles(6); +} + +void spc700_op_adc_dp_imm(void) { +spc700_prefetch2b(); +byte x = spc700_op_adc(spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1), arg0); + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_addw_ya_dp(void) { +spc700_prefetchb(); +word ya = (spc700->regs.y << 8) | spc700->regs.a; +word dp = spc700->mem_read(APUMODE_DP, MEMSIZE_WORD, arg); +ulong r = ya + dp; + spc700_testn(r & 0x8000); + spc700_testv(~(ya ^ dp) & (dp ^ (word)r) & 0x8000); + spc700_testh((ya ^ dp ^ (word)r) & 0x1000); + spc700_testz((word)r == 0); + spc700_testc(r >= 0x10000); + spc700->regs.a = r; + spc700->regs.y = r >> 8; + spc700_incpc(2); + add_apu_cycles(5); +} diff --git a/bsnes/apu/spc700_ops_and.cpp b/bsnes/apu/spc700_ops_and.cpp new file mode 100644 index 00000000..08600be2 --- /dev/null +++ b/bsnes/apu/spc700_ops_and.cpp @@ -0,0 +1,147 @@ +void spc700_op_and_a_const(void) { +spc700_prefetchb(); + spc700->regs.a &= arg; + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(2); +} + +void spc700_op_and_a_ix(void) { + spc700->regs.a &= spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(1); + add_apu_cycles(3); +} + +void spc700_op_and_a_dp(void) { +spc700_prefetchb(); + spc700->regs.a &= spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(3); +} + +void spc700_op_and_a_dpx(void) { +spc700_prefetchb(); + spc700->regs.a &= spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_and_a_addr(void) { +spc700_prefetchw(); + spc700->regs.a &= spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(3); + add_apu_cycles(4); +} + +void spc700_op_and_a_addrx(void) { +spc700_prefetchw(); + spc700->regs.a &= spc700->mem_read(APUMODE_ADDRX, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_and_a_addry(void) { +spc700_prefetchw(); + spc700->regs.a &= spc700->mem_read(APUMODE_ADDRY, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_and_a_idpx(void) { +spc700_prefetchb(); +word i; + spc700->regs.a &= spc700->mem_read(APUMODE_IDPX, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(6); +} + +void spc700_op_and_a_idpy(void) { +spc700_prefetchb(); +word i; + spc700->regs.a &= spc700->mem_read(APUMODE_IDPY, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(6); +} + +void spc700_op_and_ix_iy(void) { +word i; +byte x; + x = spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0); + x &= spc700->mem_read(APUMODE_IY, MEMSIZE_BYTE, 0); + spc700->mem_write(APUMODE_IX, MEMSIZE_BYTE, 0, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(1); + add_apu_cycles(5); +} + +void spc700_op_and_dp_dp(void) { +spc700_prefetch2b(); +byte x; + x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1); + x &= spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0); + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(3); + add_apu_cycles(6); +} + +void spc700_op_and_dp_imm(void) { +spc700_prefetch2b(); +byte x; + x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1); + x &= arg0; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_and1_bit(void) { +spc700_prefetchw(); +word addr = arg & 0x1fff; +byte bit = arg >> 13; +byte x; + if(spc700->regs.p & SPF_C) { + x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, addr); + if(!(x & (1 << bit))) { + spc700_clrc(); + } + } + spc700_incpc(3); + add_apu_cycles(4); +} + +void spc700_op_and1_notbit(void) { +spc700_prefetchw(); +word addr = arg & 0x1fff; +byte bit = arg >> 13; +byte x; + if(spc700->regs.p & SPF_C) { + x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, addr); + if(x & (1 << bit)) { + spc700_clrc(); + } + } + spc700_incpc(3); + add_apu_cycles(4); +} diff --git a/bsnes/apu/spc700_ops_cmp.cpp b/bsnes/apu/spc700_ops_cmp.cpp new file mode 100644 index 00000000..43c52ec3 --- /dev/null +++ b/bsnes/apu/spc700_ops_cmp.cpp @@ -0,0 +1,142 @@ +void spc700_op_cmp(byte x, byte y) { +short r = (short)x - (short)y; + spc700_testn(r & 0x80); + spc700_testz((byte)r == 0); + spc700_testc(r >= 0); +} + +void spc700_op_cmp_a_const(void) { +spc700_prefetchb(); + spc700_op_cmp(spc700->regs.a, arg); + spc700_incpc(2); + add_apu_cycles(2); +} + +void spc700_op_cmp_a_ix(void) { + spc700_op_cmp(spc700->regs.a, spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0)); + spc700_incpc(1); + add_apu_cycles(3); +} + +void spc700_op_cmp_a_dp(void) { +spc700_prefetchb(); + spc700_op_cmp(spc700->regs.a, spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg)); + spc700_incpc(2); + add_apu_cycles(3); +} + +void spc700_op_cmp_a_dpx(void) { +spc700_prefetchb(); + spc700_op_cmp(spc700->regs.a, spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg)); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_cmp_a_addr(void) { +spc700_prefetchw(); + spc700_op_cmp(spc700->regs.a, spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg)); + spc700_incpc(3); + add_apu_cycles(4); +} + +void spc700_op_cmp_a_addrx(void) { +spc700_prefetchw(); + spc700_op_cmp(spc700->regs.a, spc700->mem_read(APUMODE_ADDRX, MEMSIZE_BYTE, arg)); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_cmp_a_addry(void) { +spc700_prefetchw(); + spc700_op_cmp(spc700->regs.a, spc700->mem_read(APUMODE_ADDRY, MEMSIZE_BYTE, arg)); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_cmp_a_idpx(void) { +spc700_prefetchb(); + spc700_op_cmp(spc700->regs.a, spc700->mem_read(APUMODE_IDPX, MEMSIZE_BYTE, arg)); + spc700_incpc(2); + add_apu_cycles(6); +} + +void spc700_op_cmp_a_idpy(void) { +spc700_prefetchb(); + spc700_op_cmp(spc700->regs.a, spc700->mem_read(APUMODE_IDPY, MEMSIZE_BYTE, arg)); + spc700_incpc(2); + add_apu_cycles(6); +} + +void spc700_op_cmp_ix_iy(void) { + spc700_op_cmp(spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0), spc700->mem_read(APUMODE_IY, MEMSIZE_BYTE, 0)); + spc700_incpc(1); + add_apu_cycles(5); +} + +void spc700_op_cmp_dp_dp(void) { +spc700_prefetch2b(); + spc700_op_cmp(spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1), spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0)); + spc700_incpc(3); + add_apu_cycles(6); +} + +void spc700_op_cmp_dp_imm(void) { +spc700_prefetch2b(); + spc700_op_cmp(spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1), arg0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_cmp_x_const(void) { +spc700_prefetchb(); + spc700_op_cmp(spc700->regs.x, arg); + spc700_incpc(2); + add_apu_cycles(2); +} + +void spc700_op_cmp_x_dp(void) { +spc700_prefetchb(); + spc700_op_cmp(spc700->regs.x, spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg)); + spc700_incpc(2); + add_apu_cycles(3); +} + +void spc700_op_cmp_x_addr(void) { +spc700_prefetchw(); + spc700_op_cmp(spc700->regs.x, spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg)); + spc700_incpc(3); + add_apu_cycles(4); +} + +void spc700_op_cmp_y_const(void) { +spc700_prefetchb(); + spc700_op_cmp(spc700->regs.y, arg); + spc700_incpc(2); + add_apu_cycles(2); +} + +void spc700_op_cmp_y_dp(void) { +spc700_prefetchb(); + spc700_op_cmp(spc700->regs.y, spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg)); + spc700_incpc(2); + add_apu_cycles(3); +} + +void spc700_op_cmp_y_addr(void) { +spc700_prefetchw(); + spc700_op_cmp(spc700->regs.y, spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg)); + spc700_incpc(3); + add_apu_cycles(4); +} + +void spc700_op_cmpw_ya_dp(void) { +spc700_prefetchb(); +word ya = ((spc700->regs.y << 8) | spc700->regs.a); +word dp = spc700->mem_read(APUMODE_DP, MEMSIZE_WORD, arg); +long r = (long)ya - (long)dp; + spc700_testn(r & 0x8000); + spc700_testz((word)r == 0); + spc700_testc(r >= 0); + spc700_incpc(2); + add_apu_cycles(5); +} diff --git a/bsnes/apu/spc700_ops_eor.cpp b/bsnes/apu/spc700_ops_eor.cpp new file mode 100644 index 00000000..a4e42377 --- /dev/null +++ b/bsnes/apu/spc700_ops_eor.cpp @@ -0,0 +1,148 @@ +void spc700_op_eor_a_const(void) { +spc700_prefetchb(); + spc700->regs.a ^= arg; + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(2); +} + +void spc700_op_eor_a_ix(void) { + spc700->regs.a ^= spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(1); + add_apu_cycles(3); +} + +void spc700_op_eor_a_dp(void) { +spc700_prefetchb(); + spc700->regs.a ^= spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(3); +} + +void spc700_op_eor_a_dpx(void) { +spc700_prefetchb(); + spc700->regs.a ^= spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_eor_a_addr(void) { +spc700_prefetchw(); + spc700->regs.a ^= spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(3); + add_apu_cycles(4); +} + +void spc700_op_eor_a_addrx(void) { +spc700_prefetchw(); + spc700->regs.a ^= spc700->mem_read(APUMODE_ADDRX, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_eor_a_addry(void) { +spc700_prefetchw(); + spc700->regs.a ^= spc700->mem_read(APUMODE_ADDRY, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_eor_a_idpx(void) { +spc700_prefetchb(); +word i; + spc700->regs.a ^= spc700->mem_read(APUMODE_IDPX, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(6); +} + +void spc700_op_eor_a_idpy(void) { +spc700_prefetchb(); +word i; + spc700->regs.a ^= spc700->mem_read(APUMODE_IDPY, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(6); +} + +void spc700_op_eor_ix_iy(void) { +word i; +byte x; + x = spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0); + x ^= spc700->mem_read(APUMODE_IY, MEMSIZE_BYTE, 0); + spc700->mem_write(APUMODE_IX, MEMSIZE_BYTE, 0, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(1); + add_apu_cycles(5); +} + +void spc700_op_eor_dp_dp(void) { +spc700_prefetch2b(); +byte x; + x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1); + x ^= spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0); + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(3); + add_apu_cycles(6); +} + +void spc700_op_eor_dp_imm(void) { +spc700_prefetch2b(); +byte x; + x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1); + x ^= arg0; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_eor1_bit(void) { +spc700_prefetchw(); +word addr = arg & 0x1fff; +byte bit = arg >> 13; +byte x; + x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, addr); + if(spc700->regs.p & SPF_C) { + if(x & (1 << bit)) { + spc700_clrc(); + } + } else { + if(x & (1 << bit)) { + spc700_setc(); + } + } + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_not1_bit(void) { +spc700_prefetchw(); +word addr = arg & 0x1fff; +byte bit = arg >> 13; +byte x; + x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, addr); + x ^= (1 << bit); + spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, addr, x); + spc700_incpc(3); + add_apu_cycles(5); +} diff --git a/bsnes/apu/spc700_ops_flags.cpp b/bsnes/apu/spc700_ops_flags.cpp new file mode 100644 index 00000000..b2c2db06 --- /dev/null +++ b/bsnes/apu/spc700_ops_flags.cpp @@ -0,0 +1,48 @@ +void spc700_op_clrc(void) { + spc700_clrc(); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_setc(void) { + spc700_setc(); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_notc(void) { + spc700->regs.p ^= SPF_C; + spc700_incpc(1); + add_apu_cycles(3); +} + +void spc700_op_clrv(void) { + spc700_clrv(); + spc700_clrh(); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_clrp(void) { + spc700_clrp(); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_setp(void) { + spc700_setp(); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_di(void) { + spc700_clri(); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_ei(void) { + spc700_seti(); + spc700_incpc(1); + add_apu_cycles(2); +} diff --git a/bsnes/apu/spc700_ops_incdec.cpp b/bsnes/apu/spc700_ops_incdec.cpp new file mode 100644 index 00000000..271a1ee5 --- /dev/null +++ b/bsnes/apu/spc700_ops_incdec.cpp @@ -0,0 +1,135 @@ +void spc700_op_inc_a(void) { + spc700->regs.a++; + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_inc_x(void) { + spc700->regs.x++; + spc700_testn(spc700->regs.x & 0x80); + spc700_testz(spc700->regs.x == 0); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_inc_y(void) { + spc700->regs.y++; + spc700_testn(spc700->regs.y & 0x80); + spc700_testz(spc700->regs.y == 0); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_inc_dp(void) { +spc700_prefetchb(); +byte r; + r = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg) + 1; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, r); + spc700_testn(r & 0x80); + spc700_testz(r == 0); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_inc_dpx(void) { +spc700_prefetchb(); +byte r; + r = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg) + 1; + spc700->mem_write(APUMODE_DPX, MEMSIZE_BYTE, arg, r); + spc700_testn(r & 0x80); + spc700_testz(r == 0); + spc700_incpc(2); + add_apu_cycles(5); +} + +void spc700_op_inc_addr(void) { +spc700_prefetchw(); +byte r; + r = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg) + 1; + spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, r); + spc700_testn(r & 0x80); + spc700_testz(r == 0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_dec_a(void) { + spc700->regs.a--; + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_dec_x(void) { + spc700->regs.x--; + spc700_testn(spc700->regs.x & 0x80); + spc700_testz(spc700->regs.x == 0); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_dec_y(void) { + spc700->regs.y--; + spc700_testn(spc700->regs.y & 0x80); + spc700_testz(spc700->regs.y == 0); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_dec_dp(void) { +spc700_prefetchb(); +byte r; + r = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg) - 1; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, r); + spc700_testn(r & 0x80); + spc700_testz(r == 0); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_dec_dpx(void) { +spc700_prefetchb(); +byte r; + r = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg) - 1; + spc700->mem_write(APUMODE_DPX, MEMSIZE_BYTE, arg, r); + spc700_testn(r & 0x80); + spc700_testz(r == 0); + spc700_incpc(2); + add_apu_cycles(5); +} + +void spc700_op_dec_addr(void) { +spc700_prefetchw(); +byte r; + r = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg) - 1; + spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, r); + spc700_testn(r & 0x80); + spc700_testz(r == 0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_incw_dp(void) { +spc700_prefetchb(); +word r; + r = spc700->mem_read(APUMODE_DP, MEMSIZE_WORD, arg) + 1; + spc700->mem_write(APUMODE_DP, MEMSIZE_WORD, arg, r); + spc700_testn(r & 0x8000); + spc700_testz(r == 0); + spc700_incpc(2); + add_apu_cycles(6); +} + +void spc700_op_decw_dp(void) { +spc700_prefetchb(); +word r; + r = spc700->mem_read(APUMODE_DP, MEMSIZE_WORD, arg) - 1; + spc700->mem_write(APUMODE_DP, MEMSIZE_WORD, arg, r); + spc700_testn(r & 0x8000); + spc700_testz(r == 0); + spc700_incpc(2); + add_apu_cycles(6); +} diff --git a/bsnes/apu/spc700_ops_misc.cpp b/bsnes/apu/spc700_ops_misc.cpp new file mode 100644 index 00000000..02a0a9a0 --- /dev/null +++ b/bsnes/apu/spc700_ops_misc.cpp @@ -0,0 +1,241 @@ +void spc700_op_nop(void) { + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_sleep(void) { + add_apu_cycles(3); +} + +void spc700_op_stop(void) { + add_apu_cycles(3); +} + +void spc700_op_xcn_a(void) { + spc700->regs.a = (spc700->regs.a >> 4) | (spc700->regs.a << 4); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(1); + add_apu_cycles(5); +} + +void spc700_op_daa_a(void) { +int a = spc700->regs.a; + if(((a ) & 15) > 9)a += 6; + if(((a >> 4) & 15) > 9)a += 6 << 4; + spc700->regs.a = a; + spc700_testn(a & 0x80); + spc700_testz(a == 0); + spc700_testc(a >= 0x0100); + spc700_incpc(1); + add_apu_cycles(3); +} + +void spc700_op_das_a(void) { +int a = spc700->regs.a; + if(((a ) & 15) > 9)a -= 6; + if(((a >> 4) & 15) > 9)a -= 6 << 4; + spc700->regs.a = a; + spc700_testn(a & 0x80); + spc700_testz(a == 0); + spc700_testc(a < 0); + spc700_incpc(1); + add_apu_cycles(3); +} + +void spc700_op_set0_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + x |= 0x01; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_clr0_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + x &= ~0x01; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_set1_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + x |= 0x02; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_clr1_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + x &= ~0x02; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_set2_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + x |= 0x04; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_clr2_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + x &= ~0x04; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_set3_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + x |= 0x08; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_clr3_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + x &= ~0x08; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_set4_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + x |= 0x10; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_clr4_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + x &= ~0x10; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_set5_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + x |= 0x20; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_clr5_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + x &= ~0x20; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_set6_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + x |= 0x40; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_clr6_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + x &= ~0x40; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_set7_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + x |= 0x80; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_clr7_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + x &= ~0x80; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_tset1_addr(void) { +spc700_prefetchw(); +byte x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg); + x |= spc700->regs.a; + spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(3); + add_apu_cycles(6); +} + +void spc700_op_tclr1_addr(void) { +spc700_prefetchw(); +byte x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg); + x &= ~spc700->regs.a; + spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(3); + add_apu_cycles(6); +} + +void spc700_op_mul_ya(void) { +word ya; + ya = spc700->regs.y * spc700->regs.a; + spc700->regs.a = ya; + spc700->regs.y = ya >> 8; + spc700_testn(ya & 0x8000); + spc700_testz(ya == 0); + spc700_incpc(1); + add_apu_cycles(9); +} + +/* + v/h flags not set, may have result backwards + (a and y may need to be swapped) +*/ +void spc700_op_div_ya_x(void) { +word ya = (spc700->regs.y << 8) | spc700->regs.a; + if(spc700->regs.x == 0) { + spc700->regs.a = 0; + spc700->regs.y = 0; + } else { + spc700->regs.a = ya / spc700->regs.x; + spc700->regs.y = ya % spc700->regs.x; + } + ya = (spc700->regs.y << 8) | spc700->regs.a; + spc700_testn(ya & 0x8000); + spc700_testz(ya == 0); + spc700_incpc(1); + add_apu_cycles(12); +} diff --git a/bsnes/apu/spc700_ops_mov.cpp b/bsnes/apu/spc700_ops_mov.cpp new file mode 100644 index 00000000..c3f8ed48 --- /dev/null +++ b/bsnes/apu/spc700_ops_mov.cpp @@ -0,0 +1,377 @@ +void spc700_op_mov_a_x(void) { + spc700->regs.a = spc700->regs.x; + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_mov_a_y(void) { + spc700->regs.a = spc700->regs.y; + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_mov_x_a(void) { + spc700->regs.x = spc700->regs.a; + spc700_testn(spc700->regs.x & 0x80); + spc700_testz(spc700->regs.x == 0); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_mov_y_a(void) { + spc700->regs.y = spc700->regs.a; + spc700_testn(spc700->regs.y & 0x80); + spc700_testz(spc700->regs.y == 0); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_mov_x_sp(void) { + spc700->regs.x = spc700->regs.sp; + spc700_testn(spc700->regs.x & 0x80); + spc700_testz(spc700->regs.x == 0); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_mov_sp_x(void) { + spc700->regs.sp = spc700->regs.x; + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_mov_dp_dp(void) { +spc700_prefetch2b(); +byte x; + x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0); + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_mov_dp_imm(void) { +spc700_prefetch2b(); + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, arg0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_mov_a_const(void) { +spc700_prefetchb(); + spc700->regs.a = arg; + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(2); +} + +void spc700_op_mov_x_const(void) { +spc700_prefetchb(); + spc700->regs.x = arg; + spc700_testn(spc700->regs.x & 0x80); + spc700_testz(spc700->regs.x == 0); + spc700_incpc(2); + add_apu_cycles(2); +} + +void spc700_op_mov_y_const(void) { +spc700_prefetchb(); + spc700->regs.y = arg; + spc700_testn(spc700->regs.y & 0x80); + spc700_testz(spc700->regs.y == 0); + spc700_incpc(2); + add_apu_cycles(2); +} + +void spc700_op_mov_ix_a(void) { + spc700->mem_write(APUMODE_IX, MEMSIZE_BYTE, 0, spc700->regs.a); + spc700_incpc(1); + add_apu_cycles(4); +} + +void spc700_op_mov_ixinc_a(void) { + spc700->mem_write(APUMODE_IX, MEMSIZE_BYTE, 0, spc700->regs.a); + spc700->regs.x++; + spc700_incpc(1); + add_apu_cycles(4); +} + +void spc700_op_mov_dp_a(void) { +spc700_prefetchb(); + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, spc700->regs.a); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_mov_dpx_a(void) { +spc700_prefetchb(); + spc700->mem_write(APUMODE_DPX, MEMSIZE_BYTE, arg, spc700->regs.a); + spc700_incpc(2); + add_apu_cycles(5); +} + +void spc700_op_mov_addr_a(void) { +spc700_prefetchw(); + spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, spc700->regs.a); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_mov_addrx_a(void) { +spc700_prefetchw(); + spc700->mem_write(APUMODE_ADDRX, MEMSIZE_BYTE, arg, spc700->regs.a); + spc700_incpc(3); + add_apu_cycles(6); +} + +void spc700_op_mov_addry_a(void) { +spc700_prefetchw(); + spc700->mem_write(APUMODE_ADDRY, MEMSIZE_BYTE, arg, spc700->regs.a); + spc700_incpc(3); + add_apu_cycles(6); +} + +void spc700_op_mov_idpx_a(void) { +spc700_prefetchb(); +word i; + spc700->mem_write(APUMODE_IDPX, MEMSIZE_BYTE, arg, spc700->regs.a); + spc700_incpc(2); + add_apu_cycles(7); +} + +void spc700_op_mov_idpy_a(void) { +spc700_prefetchb(); +word i; + spc700->mem_write(APUMODE_IDPY, MEMSIZE_BYTE, arg, spc700->regs.a); + spc700_incpc(2); + add_apu_cycles(7); +} + +void spc700_op_mov_dp_x(void) { +spc700_prefetchb(); + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, spc700->regs.x); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_mov_dpy_x(void) { +spc700_prefetchb(); + spc700->mem_write(APUMODE_DPY, MEMSIZE_BYTE, arg, spc700->regs.x); + spc700_incpc(2); + add_apu_cycles(5); +} + +void spc700_op_mov_addr_x(void) { +spc700_prefetchw(); + spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, spc700->regs.x); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_mov_dp_y(void) { +spc700_prefetchb(); + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, spc700->regs.y); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_mov_dpx_y(void) { +spc700_prefetchb(); + spc700->mem_write(APUMODE_DPX, MEMSIZE_BYTE, arg, spc700->regs.y); + spc700_incpc(2); + add_apu_cycles(5); +} + +void spc700_op_mov_addr_y(void) { +spc700_prefetchw(); + spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, spc700->regs.y); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_mov_a_ix(void) { + spc700->regs.a = spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(1); + add_apu_cycles(3); +} + +void spc700_op_mov_a_ixinc(void) { + spc700->regs.a = spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0); + spc700->regs.x++; + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(1); + add_apu_cycles(4); +} + +void spc700_op_mov_a_dp(void) { +spc700_prefetchb(); + spc700->regs.a = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(3); +} + +void spc700_op_mov_a_dpx(void) { +spc700_prefetchb(); + spc700->regs.a = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_mov_a_addr(void) { +spc700_prefetchw(); + spc700->regs.a = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(3); + add_apu_cycles(4); +} + +void spc700_op_mov_a_addrx(void) { +spc700_prefetchw(); + spc700->regs.a = spc700->mem_read(APUMODE_ADDRX, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_mov_a_addry(void) { +spc700_prefetchw(); + spc700->regs.a = spc700->mem_read(APUMODE_ADDRY, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_mov_a_idpx(void) { +spc700_prefetchb(); +word i; + spc700->regs.a = spc700->mem_read(APUMODE_IDPX, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(6); +} + +void spc700_op_mov_a_idpy(void) { +spc700_prefetchb(); +word i; + spc700->regs.a = spc700->mem_read(APUMODE_IDPY, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(6); +} + +void spc700_op_mov_x_dp(void) { +spc700_prefetchb(); + spc700->regs.x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.x & 0x80); + spc700_testz(spc700->regs.x == 0); + spc700_incpc(2); + add_apu_cycles(3); +} + +void spc700_op_mov_x_dpy(void) { +spc700_prefetchb(); + spc700->regs.x = spc700->mem_read(APUMODE_DPY, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.x & 0x80); + spc700_testz(spc700->regs.x == 0); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_mov_x_addr(void) { +spc700_prefetchw(); + spc700->regs.x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.x & 0x80); + spc700_testz(spc700->regs.x == 0); + spc700_incpc(3); + add_apu_cycles(4); +} + +void spc700_op_mov_y_dp(void) { +spc700_prefetchb(); + spc700->regs.y = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.y & 0x80); + spc700_testz(spc700->regs.y == 0); + spc700_incpc(2); + add_apu_cycles(3); +} + +void spc700_op_mov_y_dpx(void) { +spc700_prefetchb(); + spc700->regs.y = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.y & 0x80); + spc700_testz(spc700->regs.y == 0); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_mov_y_addr(void) { +spc700_prefetchw(); + spc700->regs.y = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.y & 0x80); + spc700_testz(spc700->regs.y == 0); + spc700_incpc(3); + add_apu_cycles(4); +} + +void spc700_op_mov_ya_dp(void) { +spc700_prefetchb(); +word ya; + ya = spc700->mem_read(APUMODE_DP, MEMSIZE_WORD, arg); + spc700->regs.a = ya; + spc700->regs.y = ya >> 8; + spc700_testn(ya & 0x8000); + spc700_testz(ya == 0); + spc700_incpc(2); + add_apu_cycles(5); +} + +void spc700_op_mov_dp_ya(void) { +spc700_prefetchb(); +word ya = (spc700->regs.y << 8) | spc700->regs.a; + spc700->mem_write(APUMODE_DP, MEMSIZE_WORD, arg, ya); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_mov1_c_bit(void) { +spc700_prefetchw(); +word addr = arg & 0x1fff; +byte bit = arg >> 13; +byte x; + x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, addr); + spc700_testc(x & (1 << bit)); + spc700_incpc(3); + add_apu_cycles(4); +} + +void spc700_op_mov1_bit_c(void) { +spc700_prefetchw(); +word addr = arg & 0x1fff; +byte bit = arg >> 13; +byte x; + x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, addr); + if(spc700->regs.p & SPF_C) { + x |= (1 << bit); + } else { + x &= ~(1 << bit); + } + spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, addr, x); + spc700_incpc(3); + add_apu_cycles(5); +} diff --git a/bsnes/apu/spc700_ops_or.cpp b/bsnes/apu/spc700_ops_or.cpp new file mode 100644 index 00000000..22b89192 --- /dev/null +++ b/bsnes/apu/spc700_ops_or.cpp @@ -0,0 +1,147 @@ +void spc700_op_or_a_const(void) { +spc700_prefetchb(); + spc700->regs.a |= arg; + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(2); +} + +void spc700_op_or_a_ix(void) { + spc700->regs.a |= spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(1); + add_apu_cycles(3); +} + +void spc700_op_or_a_dp(void) { +spc700_prefetchb(); + spc700->regs.a |= spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(3); +} + +void spc700_op_or_a_dpx(void) { +spc700_prefetchb(); + spc700->regs.a |= spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_or_a_addr(void) { +spc700_prefetchw(); + spc700->regs.a |= spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(3); + add_apu_cycles(4); +} + +void spc700_op_or_a_addrx(void) { +spc700_prefetchw(); + spc700->regs.a |= spc700->mem_read(APUMODE_ADDRX, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_or_a_addry(void) { +spc700_prefetchw(); + spc700->regs.a |= spc700->mem_read(APUMODE_ADDRY, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_or_a_idpx(void) { +spc700_prefetchb(); +word i; + spc700->regs.a |= spc700->mem_read(APUMODE_IDPX, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(6); +} + +void spc700_op_or_a_idpy(void) { +spc700_prefetchb(); +word i; + spc700->regs.a |= spc700->mem_read(APUMODE_IDPY, MEMSIZE_BYTE, arg); + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(2); + add_apu_cycles(6); +} + +void spc700_op_or_ix_iy(void) { +word i; +byte x; + x = spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0); + x |= spc700->mem_read(APUMODE_IY, MEMSIZE_BYTE, 0); + spc700->mem_write(APUMODE_IX, MEMSIZE_BYTE, 0, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(1); + add_apu_cycles(5); +} + +void spc700_op_or_dp_dp(void) { +spc700_prefetch2b(); +byte x; + x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1); + x |= spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0); + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(3); + add_apu_cycles(6); +} + +void spc700_op_or_dp_imm(void) { +spc700_prefetch2b(); +byte x; + x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1); + x |= arg0; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_or1_bit(void) { +spc700_prefetchw(); +word addr = arg & 0x1fff; +byte bit = arg >> 13; +byte x; + if(!(spc700->regs.p & SPF_C)) { + x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, addr); + if(x & (1 << bit)) { + spc700_setc(); + } + } + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_or1_notbit(void) { +spc700_prefetchw(); +word addr = arg & 0x1fff; +byte bit = arg >> 13; +byte x; + if(!(spc700->regs.p & SPF_C)) { + x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, addr); + if(!(x & (1 << bit))) { + spc700_setc(); + } + } + spc700_incpc(3); + add_apu_cycles(5); +} diff --git a/bsnes/apu/spc700_ops_pc.cpp b/bsnes/apu/spc700_ops_pc.cpp new file mode 100644 index 00000000..c422f7af --- /dev/null +++ b/bsnes/apu/spc700_ops_pc.cpp @@ -0,0 +1,342 @@ +void spc700_op_bra(void) { +spc700_prefetchb(); + spc700->regs.pc += (signed char)arg; + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_bcc(void) { +spc700_prefetchb(); + if(!(spc700->regs.p & SPF_C)) { + spc700->regs.pc += (signed char)arg; + add_apu_cycles(4); + } else { + add_apu_cycles(2); + } + spc700_incpc(2); +} + +void spc700_op_bcs(void) { +spc700_prefetchb(); + if((spc700->regs.p & SPF_C)) { + spc700->regs.pc += (signed char)arg; + add_apu_cycles(4); + } else { + add_apu_cycles(2); + } + spc700_incpc(2); +} + +void spc700_op_beq(void) { +spc700_prefetchb(); + if((spc700->regs.p & SPF_Z)) { + spc700->regs.pc += (signed char)arg; + add_apu_cycles(4); + } else { + add_apu_cycles(2); + } + spc700_incpc(2); +} + +void spc700_op_bmi(void) { +spc700_prefetchb(); + if((spc700->regs.p & SPF_N)) { + spc700->regs.pc += (signed char)arg; + add_apu_cycles(4); + } else { + add_apu_cycles(2); + } + spc700_incpc(2); +} + +void spc700_op_bne(void) { +spc700_prefetchb(); + if(!(spc700->regs.p & SPF_Z)) { + spc700->regs.pc += (signed char)arg; + add_apu_cycles(4); + } else { + add_apu_cycles(2); + } + spc700_incpc(2); +} + +void spc700_op_bpl(void) { +spc700_prefetchb(); + if(!(spc700->regs.p & SPF_N)) { + spc700->regs.pc += (signed char)arg; + add_apu_cycles(4); + } else { + add_apu_cycles(2); + } + spc700_incpc(2); +} + +void spc700_op_bvc(void) { +spc700_prefetchb(); + if(!(spc700->regs.p & SPF_V)) { + spc700->regs.pc += (signed char)arg; + add_apu_cycles(4); + } else { + add_apu_cycles(2); + } + spc700_incpc(2); +} + +void spc700_op_bvs(void) { +spc700_prefetchb(); + if((spc700->regs.p & SPF_V)) { + spc700->regs.pc += (signed char)arg; + add_apu_cycles(4); + } else { + add_apu_cycles(2); + } + spc700_incpc(2); +} + +#define spc700_op_bbc(__n) \ + void spc700_op_bbc##__n##(void) { \ + spc700_prefetch2b(); \ + byte r; \ + r = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0); \ + if(!(r & (1 << __n))) { \ + spc700->regs.pc += (signed char)arg1; \ + add_apu_cycles(7); \ + } else { \ + add_apu_cycles(5); \ + } \ + spc700_incpc(3); \ + } + +#define spc700_op_bbs(__n) \ + void spc700_op_bbs##__n##(void) { \ + spc700_prefetch2b(); \ + byte r; \ + r = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0); \ + if(r & (1 << __n)) { \ + spc700->regs.pc += (signed char)arg1; \ + add_apu_cycles(7); \ + } else { \ + add_apu_cycles(5); \ + } \ + spc700_incpc(3); \ + } + +spc700_op_bbc(0) +spc700_op_bbc(1) +spc700_op_bbc(2) +spc700_op_bbc(3) +spc700_op_bbc(4) +spc700_op_bbc(5) +spc700_op_bbc(6) +spc700_op_bbc(7) + +spc700_op_bbs(0) +spc700_op_bbs(1) +spc700_op_bbs(2) +spc700_op_bbs(3) +spc700_op_bbs(4) +spc700_op_bbs(5) +spc700_op_bbs(6) +spc700_op_bbs(7) + +void spc700_op_cbne_dp(void) { +spc700_prefetch2b(); +byte r; + r = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0); + if(r != spc700->regs.a) { + spc700->regs.pc += (signed char)arg1; + add_apu_cycles(7); + } else { + add_apu_cycles(5); + } + spc700_incpc(3); +} + +void spc700_op_cbne_dpx(void) { +spc700_prefetch2b(); +byte r; + r = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg0); + if(r != spc700->regs.a) { + spc700->regs.pc += (signed char)arg1; + add_apu_cycles(8); + } else { + add_apu_cycles(6); + } + spc700_incpc(3); +} + +void spc700_op_dbnz_dp(void) { +spc700_prefetch2b(); +byte r; + r = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0) - 1; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg0, r); + if(r != 0) { + spc700->regs.pc += (signed char)arg1; + add_apu_cycles(7); + } else { + add_apu_cycles(5); + } + spc700_incpc(3); +} + +void spc700_op_dbnz_y(void) { +spc700_prefetchb(); + spc700->regs.y--; + if(spc700->regs.y != 0) { + spc700->regs.pc += (signed char)arg; + add_apu_cycles(6); + } else { + add_apu_cycles(4); + } + spc700_incpc(2); +} + +void spc700_op_jmp_addr(void) { +spc700_prefetchw(); + spc700->regs.pc = arg; + add_apu_cycles(3); +} + +void spc700_op_jmp_iaddrx(void) { +spc700_prefetchw(); + spc700->regs.pc = spc700->mem_read(APUMODE_IADDRX, MEMSIZE_WORD, arg); + add_apu_cycles(3); +} + +void spc700_op_call(void) { +spc700_prefetchw(); +word r = spc700->regs.pc + 3; + spc700_incpc(3); + spc700->stack_write(r); + spc700->stack_write(r >> 8); + spc700->regs.pc = arg; + add_apu_cycles(8); +} + +void spc700_op_pcall(void) { +spc700_prefetchb(); +word r = spc700->regs.pc + 2; + spc700->stack_write(r); + spc700->stack_write(r >> 8); + spc700->regs.pc = 0xff00 | arg; + add_apu_cycles(6); +} + +void spc700_op_tcall_0(void) { + dprintf("* spc700 opcode tcall 0 not implemented"); + spc700_incpc(1); + add_apu_cycles(8); +} + +void spc700_op_tcall_1(void) { + dprintf("* spc700 opcode tcall 1 not implemented"); + spc700_incpc(1); + add_apu_cycles(8); +} + +void spc700_op_tcall_2(void) { + dprintf("* spc700 opcode tcall 2 not implemented"); + spc700_incpc(1); + add_apu_cycles(8); +} + +void spc700_op_tcall_3(void) { + dprintf("* spc700 opcode tcall 3 not implemented"); + spc700_incpc(1); + add_apu_cycles(8); +} + +void spc700_op_tcall_4(void) { + dprintf("* spc700 opcode tcall 4 not implemented"); + spc700_incpc(1); + add_apu_cycles(8); +} + +void spc700_op_tcall_5(void) { + dprintf("* spc700 opcode tcall 5 not implemented"); + spc700_incpc(1); + add_apu_cycles(8); +} + +void spc700_op_tcall_6(void) { + dprintf("* spc700 opcode tcall 6 not implemented"); + spc700_incpc(1); + add_apu_cycles(8); +} + +void spc700_op_tcall_7(void) { + dprintf("* spc700 opcode tcall 7 not implemented"); + spc700_incpc(1); + add_apu_cycles(8); +} + +void spc700_op_tcall_8(void) { + dprintf("* spc700 opcode tcall 8 not implemented"); + spc700_incpc(1); + add_apu_cycles(8); +} + +void spc700_op_tcall_9(void) { + dprintf("* spc700 opcode tcall 9 not implemented"); + spc700_incpc(1); + add_apu_cycles(8); +} + +void spc700_op_tcall_10(void) { + dprintf("* spc700 opcode tcall 10 not implemented"); + spc700_incpc(1); + add_apu_cycles(8); +} + +void spc700_op_tcall_11(void) { + dprintf("* spc700 opcode tcall 11 not implemented"); + spc700_incpc(1); + add_apu_cycles(8); +} + +void spc700_op_tcall_12(void) { + dprintf("* spc700 opcode tcall 12 not implemented"); + spc700_incpc(1); + add_apu_cycles(8); +} + +void spc700_op_tcall_13(void) { + dprintf("* spc700 opcode tcall 13 not implemented"); + spc700_incpc(1); + add_apu_cycles(8); +} + +void spc700_op_tcall_14(void) { + dprintf("* spc700 opcode tcall 14 not implemented"); + spc700_incpc(1); + add_apu_cycles(8); +} + +void spc700_op_tcall_15(void) { + dprintf("* spc700 opcode tcall 15 not implemented"); + spc700_incpc(1); + add_apu_cycles(8); +} + +void spc700_op_brk(void) { + dprintf("* spc700 opcode brk not implemented"); + spc700_incpc(1); + add_apu_cycles(8); +} + +void spc700_op_ret(void) { +word r; + r = spc700->stack_read(); + r |= spc700->stack_read() << 8; + spc700->regs.pc = r; + add_apu_cycles(5); +} + +void spc700_op_reti(void) { +word r; + spc700->regs.p = spc700->stack_read(); + r = spc700->stack_read(); + r |= spc700->stack_read() << 8; + spc700->regs.pc = r; + add_apu_cycles(6); +} diff --git a/bsnes/apu/spc700_ops_sbc.cpp b/bsnes/apu/spc700_ops_sbc.cpp new file mode 100644 index 00000000..cd726a19 --- /dev/null +++ b/bsnes/apu/spc700_ops_sbc.cpp @@ -0,0 +1,111 @@ +byte spc700_op_sbc(byte x, byte y) { +short r = (short)x - (short)y - (short)(!(spc700->regs.p & SPF_C)); + spc700_testn(r & 0x80); + spc700_testv(((x ^ y) & 0x80) && ((x ^ (byte)r) & 0x80)); + spc700_testh(((x ^ y ^ (byte)r) & 0x10) == 0); + spc700_testz((byte)r == 0); + spc700_testc(r >= 0); + return (byte)r; +} + +void spc700_op_sbc_a_const(void) { +spc700_prefetchb(); + spc700->regs.a = spc700_op_sbc(spc700->regs.a, arg); + spc700_incpc(2); + add_apu_cycles(2); +} + +void spc700_op_sbc_a_ix(void) { + spc700->regs.a = spc700_op_sbc(spc700->regs.a, spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0)); + spc700_incpc(1); + add_apu_cycles(3); +} + +void spc700_op_sbc_a_dp(void) { +spc700_prefetchb(); + spc700->regs.a = spc700_op_sbc(spc700->regs.a, spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg)); + spc700_incpc(2); + add_apu_cycles(3); +} + +void spc700_op_sbc_a_dpx(void) { +spc700_prefetchb(); + spc700->regs.a = spc700_op_sbc(spc700->regs.a, spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg)); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_sbc_a_addr(void) { +spc700_prefetchw(); + spc700->regs.a = spc700_op_sbc(spc700->regs.a, spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg)); + spc700_incpc(3); + add_apu_cycles(4); +} + +void spc700_op_sbc_a_addrx(void) { +spc700_prefetchw(); + spc700->regs.a = spc700_op_sbc(spc700->regs.a, spc700->mem_read(APUMODE_ADDRX, MEMSIZE_BYTE, arg)); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_sbc_a_addry(void) { +spc700_prefetchw(); + spc700->regs.a = spc700_op_sbc(spc700->regs.a, spc700->mem_read(APUMODE_ADDRY, MEMSIZE_BYTE, arg)); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_sbc_a_idpx(void) { +spc700_prefetchb(); + spc700->regs.a = spc700_op_sbc(spc700->regs.a, spc700->mem_read(APUMODE_IDPX, MEMSIZE_BYTE, arg)); + spc700_incpc(2); + add_apu_cycles(6); +} + +void spc700_op_sbc_a_idpy(void) { +spc700_prefetchb(); +word i; + spc700->regs.a = spc700_op_sbc(spc700->regs.a, spc700->mem_read(APUMODE_IDPY, MEMSIZE_BYTE, arg)); + spc700_incpc(2); + add_apu_cycles(6); +} + +void spc700_op_sbc_ix_iy(void) { +byte x = spc700_op_sbc(spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0), spc700->mem_read(APUMODE_IY, MEMSIZE_BYTE, 0)); + spc700->mem_write(APUMODE_IX, MEMSIZE_BYTE, 0, x); + spc700_incpc(1); + add_apu_cycles(5); +} + +void spc700_op_sbc_dp_dp(void) { +spc700_prefetch2b(); +byte x = spc700_op_sbc(spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1), spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0)); + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x); + spc700_incpc(3); + add_apu_cycles(6); +} + +void spc700_op_sbc_dp_imm(void) { +spc700_prefetch2b(); +byte x = spc700_op_sbc(spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1), arg0); + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_subw_ya_dp(void) { +spc700_prefetchb(); +word ya = (spc700->regs.y << 8) | spc700->regs.a; +word dp = spc700->mem_read(APUMODE_DP, MEMSIZE_WORD, arg); +long r = (long)ya - (long)dp; + spc700_testn(r & 0x8000); + spc700_testv(((ya ^ dp) & 0x8000) && ((ya ^ (word)r) & 0x8000)); + spc700_testh(((ya ^ dp ^ (word)r) & 0x1000) == 0); + spc700_testz((word)r == 0); + spc700_testc(r >= 0); + spc700->regs.a = r; + spc700->regs.y = r >> 8; + spc700_incpc(2); + add_apu_cycles(5); +} diff --git a/bsnes/apu/spc700_ops_shift.cpp b/bsnes/apu/spc700_ops_shift.cpp new file mode 100644 index 00000000..fb46fac6 --- /dev/null +++ b/bsnes/apu/spc700_ops_shift.cpp @@ -0,0 +1,195 @@ +void spc700_op_asl_a(void) { + spc700_testc(spc700->regs.a & 0x80); + spc700->regs.a <<= 1; + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_asl_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + spc700_testc(x & 0x80); + x <<= 1; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_asl_dpx(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg); + spc700_testc(x & 0x80); + x <<= 1; + spc700->mem_write(APUMODE_DPX, MEMSIZE_BYTE, arg, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(2); + add_apu_cycles(5); +} + +void spc700_op_asl_addr(void) { +spc700_prefetchw(); +byte x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg); + spc700_testc(x & 0x80); + x <<= 1; + spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_lsr_a(void) { + spc700_testc(spc700->regs.a & 0x01); + spc700->regs.a >>= 1; + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_lsr_dp(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + spc700_testc(x & 0x01); + x >>= 1; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_lsr_dpx(void) { +spc700_prefetchb(); +byte x = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg); + spc700_testc(x & 0x01); + x >>= 1; + spc700->mem_write(APUMODE_DPX, MEMSIZE_BYTE, arg, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(2); + add_apu_cycles(5); +} + +void spc700_op_lsr_addr(void) { +spc700_prefetchw(); +byte x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg); + spc700_testc(x & 0x01); + x >>= 1; + spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_rol_a(void) { +byte c = (spc700->regs.p & SPF_C)?0x80:0x00; + spc700_testc(spc700->regs.a & 0x80); + spc700->regs.a <<= 1; + spc700->regs.a |= c; + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_rol_dp(void) { +spc700_prefetchb(); +byte c = (spc700->regs.p & SPF_C)?0x80:0x00; +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + spc700_testc(x & 0x80); + x <<= 1; + x |= c; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_rol_dpx(void) { +spc700_prefetchb(); +byte c = (spc700->regs.p & SPF_C)?0x80:0x00; +byte x = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg); + spc700_testc(x & 0x80); + x <<= 1; + x |= c; + spc700->mem_write(APUMODE_DPX, MEMSIZE_BYTE, arg, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(2); + add_apu_cycles(5); +} + +void spc700_op_rol_addr(void) { +spc700_prefetchw(); +byte c = (spc700->regs.p & SPF_C)?0x80:0x00; +byte x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg); + spc700_testc(x & 0x80); + x <<= 1; + x |= c; + spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(3); + add_apu_cycles(5); +} + +void spc700_op_ror_a(void) { +byte c = (spc700->regs.p & SPF_C)?0x01:0x00; + spc700_testc(spc700->regs.a & 0x01); + spc700->regs.a >>= 1; + spc700->regs.a |= c; + spc700_testn(spc700->regs.a & 0x80); + spc700_testz(spc700->regs.a == 0); + spc700_incpc(1); + add_apu_cycles(2); +} + +void spc700_op_ror_dp(void) { +spc700_prefetchb(); +byte c = (spc700->regs.p & SPF_C)?0x01:0x00; +byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg); + spc700_testc(x & 0x01); + x >>= 1; + x |= c; + spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(2); + add_apu_cycles(4); +} + +void spc700_op_ror_dpx(void) { +spc700_prefetchb(); +byte c = (spc700->regs.p & SPF_C)?0x01:0x00; +byte x = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg); + spc700_testc(x & 0x01); + x >>= 1; + x |= c; + spc700->mem_write(APUMODE_DPX, MEMSIZE_BYTE, arg, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(2); + add_apu_cycles(5); +} + +void spc700_op_ror_addr(void) { +spc700_prefetchw(); +byte c = (spc700->regs.p & SPF_C)?0x01:0x00; +byte x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg); + spc700_testc(x & 0x01); + x >>= 1; + x |= c; + spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, x); + spc700_testn(x & 0x80); + spc700_testz(x == 0); + spc700_incpc(3); + add_apu_cycles(5); +} diff --git a/bsnes/apu/spc700_ops_stack.cpp b/bsnes/apu/spc700_ops_stack.cpp new file mode 100644 index 00000000..b397a0e5 --- /dev/null +++ b/bsnes/apu/spc700_ops_stack.cpp @@ -0,0 +1,48 @@ +void spc700_op_push_a(void) { + spc700->stack_write(spc700->regs.a); + spc700_incpc(1); + add_apu_cycles(4); +} + +void spc700_op_push_x(void) { + spc700->stack_write(spc700->regs.x); + spc700_incpc(1); + add_apu_cycles(4); +} + +void spc700_op_push_y(void) { + spc700->stack_write(spc700->regs.y); + spc700_incpc(1); + add_apu_cycles(4); +} + +void spc700_op_push_p(void) { + spc700->stack_write(spc700->regs.p); + spc700_incpc(1); + add_apu_cycles(4); +} + +void spc700_op_pop_a(void) { + spc700->regs.a = spc700->stack_read(); + spc700_incpc(1); + add_apu_cycles(4); +} + +void spc700_op_pop_x(void) { + spc700->regs.x = spc700->stack_read(); + spc700_incpc(1); + add_apu_cycles(4); +} + +void spc700_op_pop_y(void) { + spc700->regs.y = spc700->stack_read(); + spc700_incpc(1); + add_apu_cycles(4); +} + +void spc700_op_pop_p(void) { + spc700->regs.p = spc700->stack_read(); + spc700_incpc(1); + add_apu_cycles(4); + spc700->regs.dp = (spc700->regs.p & SPF_P)?0x0100:0x0000; +} diff --git a/bsnes/base.h b/bsnes/base.h index 32dbfd6a..7a3403f8 100644 --- a/bsnes/base.h +++ b/bsnes/base.h @@ -1,4 +1,4 @@ -//#define PUBLIC_DOMAIN +#define NO_SPC700 #include #include @@ -11,14 +11,18 @@ typedef unsigned short word; typedef unsigned long ulong; typedef void (*vfunc)(void); -#define SH_2 1 -#define SH_4 2 -#define SH_8 3 -#define SH_16 4 -#define SH_32 5 -#define SH_64 6 -#define SH_128 7 -#define SH_256 8 +#define SH_2 1 +#define SH_4 2 +#define SH_8 3 +#define SH_16 4 +#define SH_32 5 +#define SH_64 6 +#define SH_128 7 +#define SH_256 8 +#define SH_512 9 +#define SH_1024 10 +#define SH_2048 11 +#define SH_4096 12 /************************* *** general functions *** @@ -46,8 +50,9 @@ typedef struct { *****************/ typedef struct { - char rom_name[4096], sram_name[4096]; + bool rom_loaded; ulong sram_save_tick_count; + char rom_name[4096], sram_name[4096]; }emustate; /*********************** @@ -57,9 +62,12 @@ typedef struct { void video_setmode(bool fullscreen, word width, word height); void video_setsnesmode(void); +#define LINE_DOUBLEWIDTH 1 +#define LINE_DOUBLEHEIGHT 2 + //global export: render typedef struct { - word width, height; + word display_width, display_height; word snes_width, snes_height; bool fullscreen; bool show_menu; @@ -68,18 +76,30 @@ typedef struct { byte frame_count; bool bg1_enabled[3], bg2_enabled[3], bg3_enabled[3], bg4_enabled[3], oam_enabled[5]; + + byte line[239]; }videostate; /*************************** *** debugging functions *** **************************/ -#define DEBUGMODE_NOROM 0 -#define DEBUGMODE_DISABLED 1 -#define DEBUGMODE_WAIT 2 -#define DEBUGMODE_RUN 3 -#define DEBUGMODE_STEP 4 -#define DEBUGMODE_PROCEED 5 +#define DEBUGMSG_INFO 0 +#define DEBUGMSG_CPU 1 +#define DEBUGMSG_APU 2 + +#define DEBUGWRITE_NONE 0 +#define DEBUGWRITE_CONSOLE 1 +#define DEBUGWRITE_TRACE 2 + +enum { + DEBUGMODE_DISABLED = 0, + DEBUGMODE_WAIT, + DEBUGMODE_RUN, + DEBUGMODE_CPUSTEP, + DEBUGMODE_APUSTEP, + DEBUGMODE_PROCEED +}; #define DEBUG_BGENABLED_ALL 0 #define DEBUG_BGENABLED_PRI0 1 @@ -87,21 +107,62 @@ typedef struct { #define DEBUG_BGENABLED_PRI2 3 #define DEBUG_BGENABLED_PRI3 4 -void debug_set_state(byte state); +#define BP_OFF 0 +#define BP_READ 1 +#define BP_WRITE 2 +#define BP_EXEC 4 +#define BP_VAL 8 + +#define BPSRC_MEM 0 +#define BPSRC_VRAM 1 +#define BPSRC_CGRAM 2 +#define BPSRC_OAM 3 +#define BPSRC_SPCRAM 4 + +void debug_test_breakpoint(byte source, byte flag, ulong offset, byte value); #define debug_get_state() debugger.mode -void dprintf(char *s, ...); -void debug_refresh_mem(void); -void debug_refresh_bp(void); -void debug_update_cycles(void); +#define debugger_enabled() ((debugger.mode == DEBUGMODE_DISABLED)?false:true) +#define debug_test_bp(__source, __flag, __offset, __value) \ + if(debug_get_state() != DEBUGMODE_DISABLED) { \ + debug_test_breakpoint(__source, __flag, __offset, __value); \ + } +void debug_set_state(byte state); +void dprintf(char *s, ...); +void dprintf(ulong msg_type, char *s, ...); +void debug_refresh_mem(void); +void debug_refresh_bp(void); +void debug_update_status(void); +ulong debug_write_status(void); typedef struct { byte mode; - bool trace_enabled; - ulong mem_ptr; //position of wram ptr for debug window - bool disas_op; + ulong mem_ptr; //position of wram ptr for debug window + bool disas_cpu_op, disas_apu_op; bool refresh_mem; bool refresh_bp; + bool refresh_status; + + bool cpu_op_executed; + bool apu_op_executed; + + bool output_cpu_instrs; + bool output_apu_instrs; + bool output_debug_info; + bool trace_enabled; + bool trace_output_enabled; + + bool lock_up, lock_down, lock_left, lock_right; + bool lock_a, lock_b, lock_x, lock_y; + bool lock_l, lock_r, lock_select, lock_start; + + struct { + ulong offset; + byte flags; + byte source; + byte value; + ulong hit_count; + }bp_list[16]; FILE *trace_fp; }debugstate; @@ -147,10 +208,10 @@ typedef struct { bool display_disable; //$2100 bit 7 byte display_brightness; //$2100 bits 0-3 - byte visible_scanlines; //$2133 bit 2 (NTSC/PAL mode) -- value = 224 or 240 - byte toggle_visible_scanlines; //do not allow change midframe - - bool interlace; + bool overscan; + byte visible_scanlines; + bool sprite_halve; + bool interlace, toggle_interlace; byte interlace_frame; //0 or 1, used to alternate between scanlines rendered bool bg_enabled[5]; @@ -173,6 +234,9 @@ typedef struct { bool virq_triggered; //prevent recursive calling bool hirq_triggered; //prevent recursive calling word vram_write_pos; //holds value at $2116 + word vram_write_buffer; + word vram_read_buffer; + word vram_remap_mode; word vram_inc_size; //amount to increment vram_write_pos by byte vram_inc_reg; //increment on 2118 (0) or 2119 (1) word cgram_write_pos; //holds value at $2121 (multiplied by 2) @@ -183,14 +247,11 @@ typedef struct { word bg_vscroll_pos[4]; word m7hofs, m7vofs; - byte mul_a, mul_b; - word div_a; - byte div_b; - word r_4214, r_4216; - - word smul_a; - byte smul_b; - ulong smul_r; + byte mul_a, mul_b; + word div_a; + byte div_b; + word r_4214, r_4216; + ulong r_2134; bool bg_window1_enabled[5]; bool bg_window2_enabled[5]; @@ -213,7 +274,6 @@ typedef struct { bool bg_color_enabled[6]; byte color_r, color_g, color_b; - byte toggle_active_hdma_channels; byte active_hdma_channels; word hdma_scanlines_remaining[8]; word hdma_index_pointer[8]; @@ -230,16 +290,30 @@ typedef struct { word m7a, m7b, m7c, m7d, m7x, m7y; + byte mode7_repeat; + bool mode7_extbg; bool mode7_vflip, mode7_hflip; + + byte io4201; + bool counter_latched; + + byte mmio_mem_43xx[0x80]; }ppustate; /********************* *** cpu functions *** ********************/ +#define CPUSTATE_RUN 0 +#define CPUSTATE_DMA 1 +#define CPUSTATE_STP 2 + #define MEMSPEED_SLOWROM 0 #define MEMSPEED_FASTROM 1 +void add_apu_cycles(int n); + +//g65816 cpu flags #define PF_N 0x80 #define PF_V 0x40 #define PF_M 0x20 @@ -249,16 +323,24 @@ typedef struct { #define PF_Z 0x02 #define PF_C 0x01 -#define BP_OFF 0 -#define BP_READ 1 -#define BP_WRITE 2 -#define BP_EXEC 4 -#define BP_VAL 8 +//spc700 cpu flags +#define SPF_N 0x80 +#define SPF_V 0x40 +#define SPF_P 0x20 +#define SPF_B 0x10 +#define SPF_H 0x08 +#define SPF_I 0x04 +#define SPF_Z 0x02 +#define SPF_C 0x01 /************************ *** memory functions *** ***********************/ +#define MEMSPEED_FAST 6 +#define MEMSPEED_SLOW 8 +#define MEMSPEED_XSLOW 12 + #define MEMMAP_HIROM 0x01 #define MEMMAP_LOROM 0x02 @@ -289,7 +371,14 @@ enum { MEMMODE_ADDR_PC, //addr MEMMODE_IADDR_PC, //(addr) MEMMODE_IADDRX_PC, //(addr,x) - MEMMODE_ILADDR_PC //[addr] + MEMMODE_ILADDR_PC, //[addr] +//opcode memory access types + OPMODE_DBR, + OPMODE_PBR, + OPMODE_LONG, + OPMODE_DP, + OPMODE_SP, + OPMODE_ADDR }; #define MEMSIZE_BYTE 1 @@ -302,17 +391,19 @@ enum { //main.cpp void InitSNES(void); -extern vfunc RunSNES; -void RunSNES_NoDebug(void); -void RunSNES_Debug(void); +void RunSNES(void); +void ResetSNES(void); //cpu/g65816_ops_stack.cpp -ulong g65816_stackread(byte size); -void g65816_stackwrite(byte size, ulong value); +//ulong g65816_stackread(byte size); +//void g65816_stackwrite(byte size, ulong value); //cpu/d65816.cpp void disas_g65816_op(void); +//apu/dspc700.cpp +void disas_spc700_op(void); + //ppu/mmio.cpp byte mmio_read(word addr); void mmio_write(word addr, byte value); @@ -323,6 +414,7 @@ void ppu_update_scanline(void); byte oam_read(word addr); void oam_write(word addr, byte value); void PPUInit(byte first_time); +void ppu_update_dma(void); //win/render.cpp void UpdateDisplay(void); diff --git a/bsnes/bridge/bridge.cpp b/bsnes/bridge/bridge.cpp new file mode 100644 index 00000000..bf490b36 --- /dev/null +++ b/bsnes/bridge/bridge.cpp @@ -0,0 +1,26 @@ +#include "../base.h" +#include "bridge.h" +port_bridge *cpu_apu_bridge; + +port_bridge::port_bridge() { + cputoapu_port[0] = cputoapu_port[1] = + cputoapu_port[2] = cputoapu_port[3] = + aputocpu_port[0] = aputocpu_port[1] = + aputocpu_port[2] = aputocpu_port[3] = 0; +} + +byte port_bridge::cpu_read(byte port) { + return aputocpu_port[port & 3]; +} + +byte port_bridge::apu_read(byte port) { + return cputoapu_port[port & 3]; +} + +void port_bridge::cpu_write(byte port, byte value) { + cputoapu_port[port & 3] = value; +} + +void port_bridge::apu_write(byte port, byte value) { + aputocpu_port[port & 3] = value; +} diff --git a/bsnes/bridge/bridge.h b/bsnes/bridge/bridge.h new file mode 100644 index 00000000..2690ebaa --- /dev/null +++ b/bsnes/bridge/bridge.h @@ -0,0 +1,11 @@ +class port_bridge { +public: + byte cputoapu_port[4]; //holds values written to CPU at $2140-$2143 + byte aputocpu_port[4]; //holds values written to APU at $f4-$f7 + + port_bridge(); + byte cpu_read(byte port); + byte apu_read(byte port); + void cpu_write(byte port, byte value); + void apu_write(byte port, byte value); +}; diff --git a/bsnes/bsnes.exe b/bsnes/bsnes.exe index 551d2a4a9a340a95fe3d19ca462e13ae619e0f61..614ef29b58d3717b7f8b8807786494780c5efd66 100644 GIT binary patch literal 258048 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
    =K^E;8 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 Zyz7OR4kiEfzN6CZ#D8%K{68Uq{{`=S++6?w literal 233472 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 diff --git a/bsnes/cpu/d65816.cpp b/bsnes/cpu/d65816.cpp index 35f12cf2..2077055e 100644 --- a/bsnes/cpu/d65816.cpp +++ b/bsnes/cpu/d65816.cpp @@ -1,6 +1,7 @@ #include "../base.h" #include "g65816.h" -extern g65816 *gx816; +extern g65816 *gx816; +extern debugstate debugger; ulong _disas_relb(byte addr) { return gx816->regs.pc + (signed char)(addr + 2); @@ -298,11 +299,14 @@ char *s = (char*)__disas_op_str; } void disas_g65816_op(void) { -byte op = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc, MEMACCESS_DEBUGGER); -byte op0 = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc + 1, MEMACCESS_DEBUGGER), - op1 = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc + 2, MEMACCESS_DEBUGGER), - op2 = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc + 3, MEMACCESS_DEBUGGER); +byte op, op0, op1, op2; char str0[256], str1[256], str2[256]; + if(debug_write_status() == DEBUGWRITE_NONE)return; + + op = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc, MEMACCESS_DEBUGGER); + op0 = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc + 1, MEMACCESS_DEBUGGER); + op1 = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc + 2, MEMACCESS_DEBUGGER); + op2 = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc + 3, MEMACCESS_DEBUGGER); strcpy(__disas_op_str, "??? "); __disas_op(op, op0, op1, op2); @@ -329,9 +333,7 @@ char str0[256], str1[256], str2[256]; (gx816->regs.p & 0x01)?'C':'c'); } - dprintf("%0.6x %s A:%0.4x X:%0.4x Y:%0.4x S:%0.4x D:%0.4x DB:%0.2x %s", gx816->regs.pc, __disas_op_str, + dprintf(DEBUGMSG_CPU, "%0.6x %s A:%0.4x X:%0.4x Y:%0.4x S:%0.4x D:%0.4x DB:%0.2x %s", gx816->regs.pc, __disas_op_str, gx816->regs.a.w, gx816->regs.x, gx816->regs.y, gx816->regs.s, gx816->regs.d, gx816->regs.db, str1); - - debug_update_cycles(); } diff --git a/bsnes/cpu/g65816.cpp b/bsnes/cpu/g65816.cpp index 9d117b50..99f95e55 100644 --- a/bsnes/cpu/g65816.cpp +++ b/bsnes/cpu/g65816.cpp @@ -2,11 +2,11 @@ #include "../timing/timing.h" #include "g65816.h" -extern emustate emu_state; -extern debugstate debugger; -extern ppustate ppu; +extern emustate emu_state; +extern debugstate debugger; +extern ppustate ppu; extern snes_timer *snes_time; -g65816 *gx816; +g65816 *gx816; #include "g65816_ops.cpp" @@ -31,12 +31,12 @@ int i; if((fsize & 0x000fff) == 0x000200)header_offset = 512; fseek(fp, 0x7fdc + header_offset, SEEK_SET); - cksum = fgetc(fp) | fgetc(fp) << 8; + cksum = fgetc(fp) | fgetc(fp) << 8; icksum = fgetc(fp) | fgetc(fp) << 8; if(cksum + icksum == 0xffff)map = MEMMAP_LOROM; fseek(fp, 0xffdc + header_offset, SEEK_SET); - cksum = fgetc(fp) | fgetc(fp) << 8; + cksum = fgetc(fp) | fgetc(fp) << 8; icksum = fgetc(fp) | fgetc(fp) << 8; if(cksum + icksum == 0xffff)map = MEMMAP_HIROM; @@ -65,7 +65,7 @@ int i; //pbr is loaded with 00, and 16-bit pc is loaded with reset vector at 0xfffc //upon power on and at first reset - regs.pc = mem_read(MEMMODE_LONG, MEMSIZE_WORD, 0x00fffc); + regs.pc = mem_read(MEMMODE_LONG, MEMSIZE_WORD, 0x00fffc); fclose(fp); @@ -114,12 +114,13 @@ void g65816::PowerOn(byte first_time) { regs.e = true; snes_time->master_cycles = 0; memory_speed = MEMSPEED_SLOWROM; - toggle_memory_speed = MEMSPEED_SLOWROM; wai_interrupt_occurred = false; InitializeWRAM(0x00); PPUInit(first_time); UpdateDisplay(); + snes_time->set_speed_map(MEMSPEED_SLOWROM); + cpu_state = CPUSTATE_RUN; } void g65816::Reset(void) { @@ -133,74 +134,68 @@ void g65816::Reset(void) { regs.pc = mem_read(MEMMODE_LONG, MEMSIZE_WORD, 0x00fffc); snes_time->master_cycles = 0; memory_speed = MEMSPEED_SLOWROM; - toggle_memory_speed = MEMSPEED_SLOWROM; wai_interrupt_occurred = false; PPUInit(0); //0 blocks reallocating memory for vram, cgram, etc. UpdateDisplay(); - - if(debug_get_state() == DEBUGMODE_WAIT)disas_g65816_op(); + snes_time->set_speed_map(MEMSPEED_SLOWROM); + cpu_state = CPUSTATE_RUN; } +/*********** + *** IRQ *** + *********** +cycles: + [1] pbr,pc ; io + [2] pbr,pc ; io + [3] 0,s ; pbr + [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 g65816::InvokeIRQ(word addr) { - wai_interrupt_occurred = true; - snes_time->add_cpu_pcycles(1); - if(gx816->regs.e == true) { - snes_time->add_cpu_scycles(3); - g65816_stackwrite(MEMSIZE_WORD, gx816->regs.pc); - g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.p); - } else { - snes_time->add_cpu_scycles(4); - g65816_stackwrite(MEMSIZE_LONG, gx816->regs.pc); - g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.p); - } - snes_time->add_cpu_mcycles(2, addr); - snes_time->add_cpu_icycles(1); - gx816->regs.pc = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, addr); - gx816->regs.p |= PF_I; + snes_time->add_cpu_icycles(2); //1,2 [i/o] + gx816->stack_write(gx816->regs.pc >> 16); //3 [write pbr] + gx816->stack_write(gx816->regs.pc >> 8); //4 [write pch] + gx816->stack_write(gx816->regs.pc); //5 [write pcl] + gx816->stack_write(gx816->regs.p); //6 [write p] + gx816->op.r.p.l = gx816->op_read(OPMODE_ADDR, addr); //7 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_ADDR, addr + 1); //8 [read high] + gx816->regs.pc = gx816->op.r.w; + gx816->regs.p |= PF_I; + wai_interrupt_occurred = true; snes_time->update_timer(); } -void g65816::Run(void) { +void g65816::exec_op(void) { FILE *fp; byte op; -word h; int i; static ulong sram_save_tick = 0; - op = mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc); - if(regs.e == true)g65816_optbl_e[op](); - else switch((regs.p & 0x30)) { - case 0x30:g65816_optbl_MX[op]();break; - case 0x20:g65816_optbl_Mx[op]();break; - case 0x10:g65816_optbl_mX[op]();break; - case 0x00:g65816_optbl_mx[op]();break; - } - - h = snes_time->hscan_pos; - snes_time->update_timer(); - if(snes_time->hscan_pos >= WRAM_REFRESH_DOT_POS && h < WRAM_REFRESH_DOT_POS) { - snes_time->add_cpu_cycles(40); + if(cpu_state == CPUSTATE_RUN || cpu_state == CPUSTATE_STP) { + op = mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc); + if(regs.e == true)g65816_optbl_e[op](); + else switch((regs.p & 0x30)) { + case 0x30:g65816_optbl_MX[op]();break; + case 0x20:g65816_optbl_Mx[op]();break; + case 0x10:g65816_optbl_mX[op]();break; + case 0x00:g65816_optbl_mx[op]();break; + } + debugger.cpu_op_executed = true; + debugger.disas_cpu_op = true; + snes_time->update_timer(); + } else if(cpu_state == CPUSTATE_DMA) { + ppu_update_dma(); snes_time->update_timer(); } + + snes_time->update_timer_events(); ppu_update_scanline(); - memory_speed = toggle_memory_speed; - - if(debug_get_state() == DEBUGMODE_DISABLED)return; - - for(i=0;i<16;i++) { - if(gx816->bp_list[i].flags & BP_EXEC) { - if(gx816->bp_list[i].offset == gx816->regs.pc) { - dprintf("* breakpoint %d hit -- exec access", i); - gx816->bp_list[i].hit_count++; - debug_set_state(DEBUGMODE_WAIT); - disas_g65816_op(); - debugger.refresh_bp = true; - } - } - } - //see if we need to backup sram to a file yet... if(sram_size != 0) { sram_save_tick++; @@ -211,20 +206,31 @@ static ulong sram_save_tick = 0; fclose(fp); } } + + debug_test_bp(BPSRC_MEM, BP_EXEC, gx816->regs.pc, 0); +} + +void g65816::Run(void) { + if(snes_time->bridge.apu_cycles >= snes_time->bridge.cpu_cycles) { + exec_op(); + } + if(snes_time->bridge.cpu_cycles >= 65536 && snes_time->bridge.apu_cycles >= 65536) { + snes_time->bridge.cpu_cycles &= 65535; + snes_time->bridge.apu_cycles &= 65535; + } } g65816::g65816() { +int i; rom = (byte*)malloc(0x600000); wram = (byte*)malloc(0x020000); sram = (byte*)malloc(0x0e0000); - for(int i=0;i<16;i++) { - bp_list[i].offset = 0; - bp_list[i].flags = BP_OFF; - bp_list[i].value = 0; - bp_list[i].hit_count = 0; - } nmi_enabled = false; nmi_pin = 0; + + op.dp = op.sp = 0x00; + op.r.l = 0x000000; + op.aa.l = 0x000000; } g65816::~g65816() { diff --git a/bsnes/cpu/g65816.h b/bsnes/cpu/g65816.h index f1e83a1b..accc6956 100644 --- a/bsnes/cpu/g65816.h +++ b/bsnes/cpu/g65816.h @@ -8,8 +8,9 @@ class g65816 { public: //cpu declarations + byte cpu_state; struct { - ulong pc, dc; + ulong pc; union { byte b; word w; @@ -19,9 +20,23 @@ public: byte db, p; bool e; }regs; + struct { + byte dp, sp; + union { + byte b; + word w; + ulong l; + struct { byte l, h, b; }p; + }r; + union { + word w; + ulong l; + struct { byte l, h, b; }p; + }aa; + ulong addr, iaddr; + bool c2, c4; + }op; byte memory_speed; - byte toggle_memory_speed; - bool index_bank_crossed; byte nmi_pin; bool nmi_enabled; @@ -32,13 +47,6 @@ public: byte *wram, *sram, *rom; ulong map; ulong sram_size; -//debug declarations - struct { - ulong offset; - byte flags; - byte value; - ulong hit_count; - }bp_list[16]; //cpu functions (cpu/g65816.cpp) void Run(void); @@ -48,19 +56,29 @@ public: void InvokeIRQ(word addr); //memory functions (mem/memory.cpp) + void exec_op(void); void InitializeROM(byte memory_map); void InitializeWRAM(byte value); ulong mirror_offset(ulong offset); ulong convert_offset(byte read_mode, ulong addr, bool mirror = true); - ulong adjust_base_offset(byte read_mode, ulong addr); - ulong read_indirect_address(byte read_mode, ulong addr); - ulong get_dc(byte read_mode, ulong addr); +//ulong adjust_base_offset(byte read_mode, ulong addr); +//ulong read_indirect_address(byte read_mode, ulong addr); +//ulong get_dc(byte read_mode, ulong addr); + byte mem_getbyte_direct(ulong addr, byte access_mode = MEMACCESS_NORMAL); byte mem_getbyte(ulong addr, byte access_mode = MEMACCESS_NORMAL); void mem_putbyte_direct(ulong addr, byte value, byte access_mode = MEMACCESS_NORMAL); void mem_putbyte(ulong addr, byte value, byte access_mode = MEMACCESS_NORMAL); ulong mem_read(byte read_mode, byte read_size, ulong addr, byte access_mode = MEMACCESS_NORMAL); void mem_write(byte write_mode, byte write_size, ulong addr, ulong value, byte access_mode = MEMACCESS_NORMAL); + + ulong read_operand(byte size); + byte op_read(byte mode, ulong addr); + void op_write(byte mode, ulong addr, byte value); + byte stack_read(void); + void stack_write(byte value); + void op_cond(byte c, ulong n0 = 0, ulong n1 = 0); + ulong rom_read(ulong addr, byte read_size); void rom_write(ulong addr, ulong v, byte write_size); diff --git a/bsnes/cpu/g65816_ops.cpp b/bsnes/cpu/g65816_ops.cpp index 02e036da..211e09a3 100644 --- a/bsnes/cpu/g65816_ops.cpp +++ b/bsnes/cpu/g65816_ops.cpp @@ -21,14 +21,15 @@ #define g65816_testz(x) if(x)g65816_setz(); else g65816_clrz() #define g65816_testc(x) if(x)g65816_setc(); else g65816_clrc() -//read opcode argument -#define g65816_prefetch(__size) ulong arg = gx816->mem_read(MEMMODE_NONE, __size, gx816->regs.pc + 1, MEMACCESS_CPU) -//get destination address, do not mirror -#define g65816_getaddr(__mode) ulong dest_addr = gx816->get_dc(__mode, arg) -//get indirect destination address + destination address, do not mirror -#define g65816_getiaddr(__mode) ulong base_addr = gx816->adjust_base_offset(__mode, arg);ulong dest_addr = gx816->read_indirect_address(__mode, base_addr) //increment program counter, wrap around pbr -#define g65816_incpc(__n) gx816->regs.pc = (gx816->regs.pc & 0xff0000) | ((gx816->regs.pc + __n) & 0xffff) +#define g65816_incpc(__n) gx816->regs.pc = (gx816->regs.pc & 0xff0000) | (word)(gx816->regs.pc + __n) + +/* + vpa = 1, vda = 1 -> add_cpu_pcycles (opcode fetch) + vpa = 1, vda = 0 -> add_cpu_pcycles (operand fetch) + vpa = 0, vda = 1 -> add_cpu_dcycles (memory fetch) + vpa = 0, vda = 0 -> add_cpu_icycles (internal operation) +*/ //opcode functions #include "g65816_ops_adc.cpp" @@ -47,7 +48,7 @@ vfunc g65816_optbl_e[256] = { // g65816_optbl_e, g65816_optbl_e, g65816_optbl_e, // ----------------------x0, ----------------------x1, ----------------------x2, ----------------------x3, -------- ----------------------x4, ----------------------x5, ----------------------x6, ----------------------x7, -------- ----------------------x8, ----------------------x9, ----------------------xa, ----------------------xb, -------- ----------------------xc, ----------------------xd, ----------------------xe, ----------------------xf, -/* 0x */ g65816_op_brke, g65816_op_ora_idpxb, g65816_op_cope, g65816_op_ora_srb, /* 0x */ g65816_op_tsb_dpb, g65816_op_ora_dpb, g65816_op_asl_dpb, g65816_op_ora_ildpb, /* 0x */ g65816_op_php, g65816_op_ora_constb, g65816_op_aslb, g65816_op_phd, /* 0x */ g65816_op_tsb_addrb, g65816_op_ora_addrb, g65816_op_asl_addrb, g65816_op_ora_longb, +/* 0x */ g65816_op_brk, g65816_op_ora_idpxb, g65816_op_cop, g65816_op_ora_srb, /* 0x */ g65816_op_tsb_dpb, g65816_op_ora_dpb, g65816_op_asl_dpb, g65816_op_ora_ildpb, /* 0x */ g65816_op_php, g65816_op_ora_constb, g65816_op_aslb, g65816_op_phd, /* 0x */ g65816_op_tsb_addrb, g65816_op_ora_addrb, g65816_op_asl_addrb, g65816_op_ora_longb, /* 1x */ g65816_op_bpl, g65816_op_ora_idpyb, g65816_op_ora_idpb, g65816_op_ora_isryb, /* 1x */ g65816_op_trb_dpb, g65816_op_ora_dpxb, g65816_op_asl_dpxb, g65816_op_ora_ildpyb, /* 1x */ g65816_op_clc, g65816_op_ora_addryb, g65816_op_incb, g65816_op_tcse, /* 1x */ g65816_op_trb_addrb, g65816_op_ora_addrxb, g65816_op_asl_addrxb, g65816_op_ora_longxb, /* 2x */ g65816_op_jsr_addr, g65816_op_and_idpxb, g65816_op_jsr_long, g65816_op_and_srb, /* 2x */ g65816_op_bit_dpb, g65816_op_and_dpb, g65816_op_rol_dpb, g65816_op_and_ildpb, /* 2x */ g65816_op_plp, g65816_op_and_constb, g65816_op_rolb, g65816_op_pld, /* 2x */ g65816_op_bit_addrb, g65816_op_and_addrb, g65816_op_rol_addrb, g65816_op_and_longb, /* 3x */ g65816_op_bmi, g65816_op_and_idpyb, g65816_op_and_idpb, g65816_op_and_isryb, /* 3x */ g65816_op_bit_dpxb, g65816_op_and_dpxb, g65816_op_rol_dpxb, g65816_op_and_ildpyb, /* 3x */ g65816_op_sec, g65816_op_and_addryb, g65816_op_decb, g65816_op_tsce, /* 3x */ g65816_op_bit_addrxb, g65816_op_and_addrxb, g65816_op_rol_addrxb, g65816_op_and_longxb, @@ -70,7 +71,7 @@ vfunc g65816_optbl_e[256] = { // vfunc g65816_optbl_MX[256] = { // g65816_optbl_MX, g65816_optbl_MX, g65816_optbl_MX, // ----------------------x0, ----------------------x1, ----------------------x2, ----------------------x3, -------- ----------------------x4, ----------------------x5, ----------------------x6, ----------------------x7, -------- ----------------------x8, ----------------------x9, ----------------------xa, ----------------------xb, -------- ----------------------xc, ----------------------xd, ----------------------xe, ----------------------xf, -/* 0x */ g65816_op_brkn, g65816_op_ora_idpxb, g65816_op_copn, g65816_op_ora_srb, /* 0x */ g65816_op_tsb_dpb, g65816_op_ora_dpb, g65816_op_asl_dpb, g65816_op_ora_ildpb, /* 0x */ g65816_op_php, g65816_op_ora_constb, g65816_op_aslb, g65816_op_phd, /* 0x */ g65816_op_tsb_addrb, g65816_op_ora_addrb, g65816_op_asl_addrb, g65816_op_ora_longb, +/* 0x */ g65816_op_brk, g65816_op_ora_idpxb, g65816_op_cop, g65816_op_ora_srb, /* 0x */ g65816_op_tsb_dpb, g65816_op_ora_dpb, g65816_op_asl_dpb, g65816_op_ora_ildpb, /* 0x */ g65816_op_php, g65816_op_ora_constb, g65816_op_aslb, g65816_op_phd, /* 0x */ g65816_op_tsb_addrb, g65816_op_ora_addrb, g65816_op_asl_addrb, g65816_op_ora_longb, /* 1x */ g65816_op_bpl, g65816_op_ora_idpyb, g65816_op_ora_idpb, g65816_op_ora_isryb, /* 1x */ g65816_op_trb_dpb, g65816_op_ora_dpxb, g65816_op_asl_dpxb, g65816_op_ora_ildpyb, /* 1x */ g65816_op_clc, g65816_op_ora_addryb, g65816_op_incb, g65816_op_tcsn, /* 1x */ g65816_op_trb_addrb, g65816_op_ora_addrxb, g65816_op_asl_addrxb, g65816_op_ora_longxb, /* 2x */ g65816_op_jsr_addr, g65816_op_and_idpxb, g65816_op_jsr_long, g65816_op_and_srb, /* 2x */ g65816_op_bit_dpb, g65816_op_and_dpb, g65816_op_rol_dpb, g65816_op_and_ildpb, /* 2x */ g65816_op_plp, g65816_op_and_constb, g65816_op_rolb, g65816_op_pld, /* 2x */ g65816_op_bit_addrb, g65816_op_and_addrb, g65816_op_rol_addrb, g65816_op_and_longb, /* 3x */ g65816_op_bmi, g65816_op_and_idpyb, g65816_op_and_idpb, g65816_op_and_isryb, /* 3x */ g65816_op_bit_dpxb, g65816_op_and_dpxb, g65816_op_rol_dpxb, g65816_op_and_ildpyb, /* 3x */ g65816_op_sec, g65816_op_and_addryb, g65816_op_decb, g65816_op_tscn, /* 3x */ g65816_op_bit_addrxb, g65816_op_and_addrxb, g65816_op_rol_addrxb, g65816_op_and_longxb, @@ -93,7 +94,7 @@ vfunc g65816_optbl_MX[256] = { // vfunc g65816_optbl_Mx[256] = { // g65816_optbl_Mx, g65816_optbl_Mx, g65816_optbl_Mx, // ----------------------x0, ----------------------x1, ----------------------x2, ----------------------x3, -------- ----------------------x4, ----------------------x5, ----------------------x6, ----------------------x7, -------- ----------------------x8, ----------------------x9, ----------------------xa, ----------------------xb, -------- ----------------------xc, ----------------------xd, ----------------------xe, ----------------------xf, -/* 0x */ g65816_op_brkn, g65816_op_ora_idpxb, g65816_op_copn, g65816_op_ora_srb, /* 0x */ g65816_op_tsb_dpb, g65816_op_ora_dpb, g65816_op_asl_dpb, g65816_op_ora_ildpb, /* 0x */ g65816_op_php, g65816_op_ora_constb, g65816_op_aslb, g65816_op_phd, /* 0x */ g65816_op_tsb_addrb, g65816_op_ora_addrb, g65816_op_asl_addrb, g65816_op_ora_longb, +/* 0x */ g65816_op_brk, g65816_op_ora_idpxb, g65816_op_cop, g65816_op_ora_srb, /* 0x */ g65816_op_tsb_dpb, g65816_op_ora_dpb, g65816_op_asl_dpb, g65816_op_ora_ildpb, /* 0x */ g65816_op_php, g65816_op_ora_constb, g65816_op_aslb, g65816_op_phd, /* 0x */ g65816_op_tsb_addrb, g65816_op_ora_addrb, g65816_op_asl_addrb, g65816_op_ora_longb, /* 1x */ g65816_op_bpl, g65816_op_ora_idpyb, g65816_op_ora_idpb, g65816_op_ora_isryb, /* 1x */ g65816_op_trb_dpb, g65816_op_ora_dpxb, g65816_op_asl_dpxb, g65816_op_ora_ildpyb, /* 1x */ g65816_op_clc, g65816_op_ora_addryb, g65816_op_incb, g65816_op_tcsn, /* 1x */ g65816_op_trb_addrb, g65816_op_ora_addrxb, g65816_op_asl_addrxb, g65816_op_ora_longxb, /* 2x */ g65816_op_jsr_addr, g65816_op_and_idpxb, g65816_op_jsr_long, g65816_op_and_srb, /* 2x */ g65816_op_bit_dpb, g65816_op_and_dpb, g65816_op_rol_dpb, g65816_op_and_ildpb, /* 2x */ g65816_op_plp, g65816_op_and_constb, g65816_op_rolb, g65816_op_pld, /* 2x */ g65816_op_bit_addrb, g65816_op_and_addrb, g65816_op_rol_addrb, g65816_op_and_longb, /* 3x */ g65816_op_bmi, g65816_op_and_idpyb, g65816_op_and_idpb, g65816_op_and_isryb, /* 3x */ g65816_op_bit_dpxb, g65816_op_and_dpxb, g65816_op_rol_dpxb, g65816_op_and_ildpyb, /* 3x */ g65816_op_sec, g65816_op_and_addryb, g65816_op_decb, g65816_op_tscn, /* 3x */ g65816_op_bit_addrxb, g65816_op_and_addrxb, g65816_op_rol_addrxb, g65816_op_and_longxb, @@ -116,7 +117,7 @@ vfunc g65816_optbl_Mx[256] = { // vfunc g65816_optbl_mX[256] = { // g65816_optbl_mX, g65816_optbl_mX, g65816_optbl_mX, // ----------------------x0, ----------------------x1, ----------------------x2, ----------------------x3, -------- ----------------------x4, ----------------------x5, ----------------------x6, ----------------------x7, -------- ----------------------x8, ----------------------x9, ----------------------xa, ----------------------xb, -------- ----------------------xc, ----------------------xd, ----------------------xe, ----------------------xf, -/* 0x */ g65816_op_brkn, g65816_op_ora_idpxw, g65816_op_copn, g65816_op_ora_srw, /* 0x */ g65816_op_tsb_dpw, g65816_op_ora_dpw, g65816_op_asl_dpw, g65816_op_ora_ildpw, /* 0x */ g65816_op_php, g65816_op_ora_constw, g65816_op_aslw, g65816_op_phd, /* 0x */ g65816_op_tsb_addrw, g65816_op_ora_addrw, g65816_op_asl_addrw, g65816_op_ora_longw, +/* 0x */ g65816_op_brk, g65816_op_ora_idpxw, g65816_op_cop, g65816_op_ora_srw, /* 0x */ g65816_op_tsb_dpw, g65816_op_ora_dpw, g65816_op_asl_dpw, g65816_op_ora_ildpw, /* 0x */ g65816_op_php, g65816_op_ora_constw, g65816_op_aslw, g65816_op_phd, /* 0x */ g65816_op_tsb_addrw, g65816_op_ora_addrw, g65816_op_asl_addrw, g65816_op_ora_longw, /* 1x */ g65816_op_bpl, g65816_op_ora_idpyw, g65816_op_ora_idpw, g65816_op_ora_isryw, /* 1x */ g65816_op_trb_dpw, g65816_op_ora_dpxw, g65816_op_asl_dpxw, g65816_op_ora_ildpyw, /* 1x */ g65816_op_clc, g65816_op_ora_addryw, g65816_op_incw, g65816_op_tcsn, /* 1x */ g65816_op_trb_addrw, g65816_op_ora_addrxw, g65816_op_asl_addrxw, g65816_op_ora_longxw, /* 2x */ g65816_op_jsr_addr, g65816_op_and_idpxw, g65816_op_jsr_long, g65816_op_and_srw, /* 2x */ g65816_op_bit_dpw, g65816_op_and_dpw, g65816_op_rol_dpw, g65816_op_and_ildpw, /* 2x */ g65816_op_plp, g65816_op_and_constw, g65816_op_rolw, g65816_op_pld, /* 2x */ g65816_op_bit_addrw, g65816_op_and_addrw, g65816_op_rol_addrw, g65816_op_and_longw, /* 3x */ g65816_op_bmi, g65816_op_and_idpyw, g65816_op_and_idpw, g65816_op_and_isryw, /* 3x */ g65816_op_bit_dpxw, g65816_op_and_dpxw, g65816_op_rol_dpxw, g65816_op_and_ildpyw, /* 3x */ g65816_op_sec, g65816_op_and_addryw, g65816_op_decw, g65816_op_tscn, /* 3x */ g65816_op_bit_addrxw, g65816_op_and_addrxw, g65816_op_rol_addrxw, g65816_op_and_longxw, @@ -139,7 +140,7 @@ vfunc g65816_optbl_mX[256] = { // vfunc g65816_optbl_mx[256] = { // g65816_optbl_mx, g65816_optbl_mx, g65816_optbl_mx, // ----------------------x0, ----------------------x1, ----------------------x2, ----------------------x3, -------- ----------------------x4, ----------------------x5, ----------------------x6, ----------------------x7, -------- ----------------------x8, ----------------------x9, ----------------------xa, ----------------------xb, -------- ----------------------xc, ----------------------xd, ----------------------xe, ----------------------xf, -/* 0x */ g65816_op_brkn, g65816_op_ora_idpxw, g65816_op_copn, g65816_op_ora_srw, /* 0x */ g65816_op_tsb_dpw, g65816_op_ora_dpw, g65816_op_asl_dpw, g65816_op_ora_ildpw, /* 0x */ g65816_op_php, g65816_op_ora_constw, g65816_op_aslw, g65816_op_phd, /* 0x */ g65816_op_tsb_addrw, g65816_op_ora_addrw, g65816_op_asl_addrw, g65816_op_ora_longw, +/* 0x */ g65816_op_brk, g65816_op_ora_idpxw, g65816_op_cop, g65816_op_ora_srw, /* 0x */ g65816_op_tsb_dpw, g65816_op_ora_dpw, g65816_op_asl_dpw, g65816_op_ora_ildpw, /* 0x */ g65816_op_php, g65816_op_ora_constw, g65816_op_aslw, g65816_op_phd, /* 0x */ g65816_op_tsb_addrw, g65816_op_ora_addrw, g65816_op_asl_addrw, g65816_op_ora_longw, /* 1x */ g65816_op_bpl, g65816_op_ora_idpyw, g65816_op_ora_idpw, g65816_op_ora_isryw, /* 1x */ g65816_op_trb_dpw, g65816_op_ora_dpxw, g65816_op_asl_dpxw, g65816_op_ora_ildpyw, /* 1x */ g65816_op_clc, g65816_op_ora_addryw, g65816_op_incw, g65816_op_tcsn, /* 1x */ g65816_op_trb_addrw, g65816_op_ora_addrxw, g65816_op_asl_addrxw, g65816_op_ora_longxw, /* 2x */ g65816_op_jsr_addr, g65816_op_and_idpxw, g65816_op_jsr_long, g65816_op_and_srw, /* 2x */ g65816_op_bit_dpw, g65816_op_and_dpw, g65816_op_rol_dpw, g65816_op_and_ildpw, /* 2x */ g65816_op_plp, g65816_op_and_constw, g65816_op_rolw, g65816_op_pld, /* 2x */ g65816_op_bit_addrw, g65816_op_and_addrw, g65816_op_rol_addrw, g65816_op_and_longw, /* 3x */ g65816_op_bmi, g65816_op_and_idpyw, g65816_op_and_idpw, g65816_op_and_isryw, /* 3x */ g65816_op_bit_dpxw, g65816_op_and_dpxw, g65816_op_rol_dpxw, g65816_op_and_ildpyw, /* 3x */ g65816_op_sec, g65816_op_and_addryw, g65816_op_decw, g65816_op_tscn, /* 3x */ g65816_op_bit_addrxw, g65816_op_and_addrxw, g65816_op_rol_addrxw, g65816_op_and_longxw, diff --git a/bsnes/cpu/g65816_ops_adc.cpp b/bsnes/cpu/g65816_ops_adc.cpp index 06134a76..5ad972e3 100644 --- a/bsnes/cpu/g65816_ops_adc.cpp +++ b/bsnes/cpu/g65816_ops_adc.cpp @@ -1,345 +1,526 @@ -#define bcd_add_adjust_byte() \ - if(gx816->regs.p & PF_D) { \ - if(((r ) & 15) > 9)r += 6; \ - if(((r >> 4) & 15) > 9)r += 6 << 4; \ +void g65816_flags_adc_b(void) { +int r = gx816->regs.a.b + gx816->op.r.b + (gx816->regs.p & PF_C); +//bcd + if(gx816->regs.p & PF_D) { + if(((r ) & 15) > 9)r += 6; + if(((r >> 4) & 15) > 9)r += 6 << 4; } -#define bcd_add_adjust_word() \ - if(gx816->regs.p & PF_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; \ - } - -#define g65816_if_adc_b() \ -byte c = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); \ -int r = gx816->regs.a.b + c + (gx816->regs.p & PF_C); \ - bcd_add_adjust_byte() \ - g65816_testn(r & 0x80); \ - g65816_testv(~(gx816->regs.a.b ^ c) & (gx816->regs.a.b ^ (byte)r) & 0x80); \ - g65816_testz((byte)r == 0); \ - g65816_testc(r > 0xff); \ - gx816->regs.a.b = r - -#define g65816_if_adc_w() \ -word c = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); \ -int r = gx816->regs.a.w + c + (gx816->regs.p & PF_C); \ - bcd_add_adjust_word() \ - g65816_testn(r & 0x8000); \ - g65816_testv(~(gx816->regs.a.w ^ c) & (gx816->regs.a.w ^ (word)r) & 0x8000); \ - g65816_testz((word)r == 0); \ - g65816_testc(r > 0xffff); \ - gx816->regs.a.w = r - -void g65816_op_adc_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - g65816_if_adc_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); -} - -void g65816_op_adc_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - g65816_if_adc_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); -} - -void g65816_op_adc_addrxb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - g65816_if_adc_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_adc_addrxw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - g65816_if_adc_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_adc_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - g65816_if_adc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_adc_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - g65816_if_adc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_adc_idpb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDP); - g65816_if_adc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_adc_idpw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDP); - g65816_if_adc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_adc_ildpb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDP); - g65816_if_adc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_adc_ildpw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDP); - g65816_if_adc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_adc_longb(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONG); - g65816_if_adc_b(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(1, dest_addr); -} - -void g65816_op_adc_longw(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONG); - g65816_if_adc_w(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(2, dest_addr); -} - -void g65816_op_adc_longxb(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONGX); - g65816_if_adc_b(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(1, dest_addr); -} - -void g65816_op_adc_longxw(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONGX); - g65816_if_adc_w(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(2, dest_addr); -} - -void g65816_op_adc_addryb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - g65816_if_adc_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_adc_addryw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - g65816_if_adc_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_adc_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - g65816_if_adc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_adc_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - g65816_if_adc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_adc_idpxb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPX); - g65816_if_adc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_adc_idpxw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPX); - g65816_if_adc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_adc_idpyb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPY); - g65816_if_adc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2 | TIMING_CONDITION4); -} - -void g65816_op_adc_idpyw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPY); - g65816_if_adc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2 | TIMING_CONDITION4); -} - -void g65816_op_adc_ildpyb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDPY); - g65816_if_adc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_adc_ildpyw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDPY); - g65816_if_adc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_adc_srb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_SR); - g65816_if_adc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(1); -} - -void g65816_op_adc_srw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_SR); - g65816_if_adc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(1); -} - -void g65816_op_adc_isryb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_ISRY); - g65816_if_adc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(2); -} - -void g65816_op_adc_isryw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_ISRY); - g65816_if_adc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2); -} - -void g65816_op_adc_constb(void) { -g65816_prefetch(1); -int r = gx816->regs.a.b + arg + (gx816->regs.p & PF_C); - bcd_add_adjust_byte() g65816_testn(r & 0x80); - g65816_testv(~(gx816->regs.a.b ^ arg) & (gx816->regs.a.b ^ (byte)r) & 0x80); + g65816_testv(~(gx816->regs.a.b ^ gx816->op.r.b) & (gx816->regs.a.b ^ (byte)r) & 0x80); g65816_testz((byte)r == 0); g65816_testc(r > 0xff); gx816->regs.a.b = r; - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); } -void g65816_op_adc_constw(void) { -g65816_prefetch(2); -int r = gx816->regs.a.w + arg + (gx816->regs.p & PF_C); - bcd_add_adjust_word() +void g65816_flags_adc_w(void) { +int r = gx816->regs.a.w + gx816->op.r.w + (gx816->regs.p & PF_C); +//bcd + if(gx816->regs.p & PF_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; + } + g65816_testn(r & 0x8000); - g65816_testv(~(gx816->regs.a.w ^ arg) & (gx816->regs.a.w ^ (word)r) & 0x8000); + g65816_testv(~(gx816->regs.a.w ^ gx816->op.r.w) & (gx816->regs.a.w ^ (word)r) & 0x8000); g65816_testz((word)r == 0); g65816_testc(r > 0xffff); gx816->regs.a.w = r; - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); +} + +/************************ + *** 0x69: adc #const *** + ************************ +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; idl + [2a] pbr,pc+2 ; idh [1] +*/ + +void g65816_op_adc_constb(void) { + gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch] + + g65816_flags_adc_b(); + g65816_incpc(2); +} + +void g65816_op_adc_constw(void) { + gx816->op.r.w = gx816->read_operand(2); //1,2,2a [op fetch] + + g65816_flags_adc_w(); + g65816_incpc(3); +} + +/********************** + *** 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 g65816_op_adc_addrb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + + g65816_flags_adc_b(); + g65816_incpc(3); +} + +void g65816_op_adc_addrw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + + g65816_flags_adc_w(); + g65816_incpc(3); +} + +/************************ + *** 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 g65816_op_adc_addrxb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read] + + g65816_flags_adc_b(); + g65816_incpc(3); +} + +void g65816_op_adc_addrxw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //4a [read high] + + g65816_flags_adc_w(); + g65816_incpc(3); +} + +/******************** + *** 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 g65816_op_adc_dpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + + g65816_flags_adc_b(); + g65816_incpc(2); +} + +void g65816_op_adc_dpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + + g65816_flags_adc_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_adc_idpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read] + + g65816_flags_adc_b(); + g65816_incpc(2); +} + +void g65816_op_adc_idpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //5a [read high] + + g65816_flags_adc_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_adc_ildpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read] + + g65816_flags_adc_b(); + g65816_incpc(2); +} + +void g65816_op_adc_ildpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //6a [read high] + + g65816_flags_adc_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_adc_longb(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read] + + g65816_flags_adc_b(); + g65816_incpc(4); +} + +void g65816_op_adc_longw(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read] + gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //5a [read] + + g65816_flags_adc_w(); + g65816_incpc(4); +} + +/************************ + *** 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 g65816_op_adc_longxb(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read] + + g65816_flags_adc_b(); + g65816_incpc(4); +} + +void g65816_op_adc_longxw(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read] + gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x + 1); //5a [read] + + g65816_flags_adc_w(); + g65816_incpc(4); +} + +/************************ + *** 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 g65816_op_adc_addryb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read] + + g65816_flags_adc_b(); + g65816_incpc(3); +} + +void g65816_op_adc_addryw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //4a [read high] + + g65816_flags_adc_w(); + g65816_incpc(3); +} + +/********************** + *** 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 g65816_op_adc_dpxb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read] + + g65816_flags_adc_b(); + g65816_incpc(2); +} + +void g65816_op_adc_dpxw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high] + + g65816_flags_adc_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_adc_idpxb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read] + + g65816_flags_adc_b(); + g65816_incpc(2); +} + +void g65816_op_adc_idpxw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //6 [read high] + + g65816_flags_adc_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_adc_idpyb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read] + + g65816_flags_adc_b(); + g65816_incpc(2); +} + +void g65816_op_adc_idpyw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //5a [read high] + + g65816_flags_adc_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_adc_ildpyb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read] + + g65816_flags_adc_b(); + g65816_incpc(2); +} + +void g65816_op_adc_ildpyw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y + 1); //6a [read high] + + g65816_flags_adc_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_adc_srb(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read] + + g65816_flags_adc_b(); + g65816_incpc(2); +} + +void g65816_op_adc_srw(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //4a [read high] + + g65816_flags_adc_w(); + g65816_incpc(2); +} + +/************************** + *** 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 g65816_op_adc_isryb(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read] + + g65816_flags_adc_b(); + g65816_incpc(2); +} + +void g65816_op_adc_isryw(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //7a [read high] + + g65816_flags_adc_w(); + g65816_incpc(2); } diff --git a/bsnes/cpu/g65816_ops_and.cpp b/bsnes/cpu/g65816_ops_and.cpp index 4ea42256..90734f0c 100644 --- a/bsnes/cpu/g65816_ops_and.cpp +++ b/bsnes/cpu/g65816_ops_and.cpp @@ -1,335 +1,504 @@ -#define g65816_flags_and_b() g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0) -#define g65816_flags_and_w() g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0) - -#define g65816_inst_and_b() gx816->regs.a.b &= gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr) -#define g65816_inst_and_w() gx816->regs.a.w &= gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr) - -void g65816_op_and_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - g65816_inst_and_b(); - g65816_flags_and_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); +void g65816_flags_and_b() { + g65816_testn(gx816->regs.a.b & 0x80); + g65816_testz(gx816->regs.a.b == 0); } -void g65816_op_and_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - g65816_inst_and_w(); - g65816_flags_and_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); +void g65816_flags_and_w() { + g65816_testn(gx816->regs.a.w & 0x8000); + g65816_testz(gx816->regs.a.w == 0); } -void g65816_op_and_addrxb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - g65816_inst_and_b(); - g65816_flags_and_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_and_addrxw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - g65816_inst_and_w(); - g65816_flags_and_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_and_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - g65816_inst_and_b(); - g65816_flags_and_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_and_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - g65816_inst_and_w(); - g65816_flags_and_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_and_idpb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDP); - g65816_inst_and_b(); - g65816_flags_and_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_and_idpw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDP); - g65816_inst_and_w(); - g65816_flags_and_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_and_ildpb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDP); - g65816_inst_and_b(); - g65816_flags_and_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_and_ildpw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDP); - g65816_inst_and_w(); - g65816_flags_and_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_and_longb(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONG); - g65816_inst_and_b(); - g65816_flags_and_b(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(1, dest_addr); -} - -void g65816_op_and_longw(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONG); - g65816_inst_and_w(); - g65816_flags_and_w(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(2, dest_addr); -} - -void g65816_op_and_longxb(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONGX); - g65816_inst_and_b(); - g65816_flags_and_b(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(1, dest_addr); -} - -void g65816_op_and_longxw(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONGX); - g65816_inst_and_w(); - g65816_flags_and_w(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(2, dest_addr); -} - -void g65816_op_and_addryb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - g65816_inst_and_b(); - g65816_flags_and_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_and_addryw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - g65816_inst_and_w(); - g65816_flags_and_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_and_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - g65816_inst_and_b(); - g65816_flags_and_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_and_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - g65816_inst_and_w(); - g65816_flags_and_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_and_idpxb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPX); - g65816_inst_and_b(); - g65816_flags_and_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_and_idpxw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPX); - g65816_inst_and_w(); - g65816_flags_and_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_and_idpyb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPY); - g65816_inst_and_b(); - g65816_flags_and_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2 | TIMING_CONDITION4); -} - -void g65816_op_and_idpyw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPY); - g65816_inst_and_w(); - g65816_flags_and_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2 | TIMING_CONDITION4); -} - -void g65816_op_and_ildpyb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDPY); - g65816_inst_and_b(); - g65816_flags_and_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_and_ildpyw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDPY); - g65816_inst_and_w(); - g65816_flags_and_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_and_srb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_SR); - g65816_inst_and_b(); - g65816_flags_and_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(1); -} - -void g65816_op_and_srw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_SR); - g65816_inst_and_w(); - g65816_flags_and_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(1); -} - -void g65816_op_and_isryb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_ISRY); - g65816_inst_and_b(); - g65816_flags_and_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(2); -} - -void g65816_op_and_isryw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_ISRY); - g65816_inst_and_w(); - g65816_flags_and_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2); -} +/************************ + *** 0x29: and #const *** + ************************ +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; idl + [2a] pbr,pc+2 ; idh [1] +*/ void g65816_op_and_constb(void) { -g65816_prefetch(1); - gx816->regs.a.b &= arg; + gx816->regs.a.b &= gx816->read_operand(1); //1,2 [op fetch] + g65816_flags_and_b(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); } void g65816_op_and_constw(void) { -g65816_prefetch(2); - gx816->regs.a.w &= arg; + gx816->regs.a.w &= gx816->read_operand(2); //1,2,2a [op fetch] + g65816_flags_and_w(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); +} + +/********************** + *** 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 g65816_op_and_addrb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->regs.a.b &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + + g65816_flags_and_b(); + g65816_incpc(3); +} + +void g65816_op_and_addrw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->regs.a.p.l &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->regs.a.p.h &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + + g65816_flags_and_w(); + g65816_incpc(3); +} + +/************************ + *** 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 g65816_op_and_addrxb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->regs.a.b &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read] + + g65816_flags_and_b(); + g65816_incpc(3); +} + +void g65816_op_and_addrxw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->regs.a.p.l &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read low] + gx816->regs.a.p.h &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //4a [read high] + + g65816_flags_and_w(); + g65816_incpc(3); +} + +/******************** + *** 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 g65816_op_and_dpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->regs.a.b &= gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + + g65816_flags_and_b(); + g65816_incpc(2); +} + +void g65816_op_and_dpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->regs.a.p.l &= gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->regs.a.p.h &= gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + + g65816_flags_and_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_and_idpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->regs.a.b &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read] + + g65816_flags_and_b(); + g65816_incpc(2); +} + +void g65816_op_and_idpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->regs.a.p.l &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read low] + gx816->regs.a.p.h &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //5a [read high] + + g65816_flags_and_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_and_ildpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->regs.a.b &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read] + + g65816_flags_and_b(); + g65816_incpc(2); +} + +void g65816_op_and_ildpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->regs.a.p.l &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read low] + gx816->regs.a.p.h &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //6a [read high] + + g65816_flags_and_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_and_longb(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->regs.a.b &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read] + + g65816_flags_and_b(); + g65816_incpc(4); +} + +void g65816_op_and_longw(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->regs.a.p.l &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read] + gx816->regs.a.p.h &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //5a [read] + + g65816_flags_and_w(); + g65816_incpc(4); +} + +/************************ + *** 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 g65816_op_and_longxb(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->regs.a.b &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read] + + g65816_flags_and_b(); + g65816_incpc(4); +} + +void g65816_op_and_longxw(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->regs.a.p.l &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read] + gx816->regs.a.p.h &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x + 1); //5a [read] + + g65816_flags_and_w(); + g65816_incpc(4); +} + +/************************ + *** 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 g65816_op_and_addryb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0] + gx816->regs.a.b &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read] + + g65816_flags_and_b(); + g65816_incpc(3); +} + +void g65816_op_and_addryw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0] + gx816->regs.a.p.l &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read low] + gx816->regs.a.p.h &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //4a [read high] + + g65816_flags_and_w(); + g65816_incpc(3); +} + +/********************** + *** 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 g65816_op_and_dpxb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.a.b &= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read] + + g65816_flags_and_b(); + g65816_incpc(2); +} + +void g65816_op_and_dpxw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.a.p.l &= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low] + gx816->regs.a.p.h &= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high] + + g65816_flags_and_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_and_idpxb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah] + gx816->regs.a.b &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read] + + g65816_flags_and_b(); + g65816_incpc(2); +} + +void g65816_op_and_idpxw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah] + gx816->regs.a.p.l &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read low] + gx816->regs.a.p.h &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //6 [read high] + + g65816_flags_and_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_and_idpyb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0] + gx816->regs.a.b &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read] + + g65816_flags_and_b(); + g65816_incpc(2); +} + +void g65816_op_and_idpyw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0] + gx816->regs.a.p.l &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read low] + gx816->regs.a.p.h &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //5a [read high] + + g65816_flags_and_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_and_ildpyb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->regs.a.b &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read] + + g65816_flags_and_b(); + g65816_incpc(2); +} + +void g65816_op_and_ildpyw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->regs.a.p.l &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read low] + gx816->regs.a.p.h &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y + 1); //6a [read high] + + g65816_flags_and_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_and_srb(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.a.b &= gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read] + + g65816_flags_and_b(); + g65816_incpc(2); +} + +void g65816_op_and_srw(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.a.p.l &= gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read low] + gx816->regs.a.p.h &= gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //4a [read high] + + g65816_flags_and_w(); + g65816_incpc(2); +} + +/************************** + *** 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 g65816_op_and_isryb(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->regs.a.b &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read] + + g65816_flags_and_b(); + g65816_incpc(2); +} + +void g65816_op_and_isryw(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->regs.a.p.l &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read low] + gx816->regs.a.p.h &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //7a [read high] + + g65816_flags_and_w(); + g65816_incpc(2); } diff --git a/bsnes/cpu/g65816_ops_cmp.cpp b/bsnes/cpu/g65816_ops_cmp.cpp index 9eabc22a..33e2bc14 100644 --- a/bsnes/cpu/g65816_ops_cmp.cpp +++ b/bsnes/cpu/g65816_ops_cmp.cpp @@ -1,321 +1,508 @@ -#define g65816_flags_cmp_b() \ -byte c = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); \ -int r = gx816->regs.a.b - c; \ - g65816_testn(r & 0x80); \ - g65816_testz((byte)r == 0); \ - g65816_testc(r >= 0) - -#define g65816_flags_cmp_w() \ -word c = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); \ -int r = gx816->regs.a.w - c; \ - g65816_testn(r & 0x8000); \ - g65816_testz((word)r == 0); \ - g65816_testc(r >= 0) - -void g65816_op_cmp_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - g65816_flags_cmp_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); -} - -void g65816_op_cmp_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - g65816_flags_cmp_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); -} - -void g65816_op_cmp_addrxb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - g65816_flags_cmp_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_cmp_addrxw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - g65816_flags_cmp_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_cmp_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - g65816_flags_cmp_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_cmp_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - g65816_flags_cmp_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_cmp_idpb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDP); - g65816_flags_cmp_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_cmp_idpw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDP); - g65816_flags_cmp_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_cmp_ildpb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDP); - g65816_flags_cmp_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_cmp_ildpw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDP); - g65816_flags_cmp_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_cmp_longb(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONG); - g65816_flags_cmp_b(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(1, dest_addr); -} - -void g65816_op_cmp_longw(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONG); - g65816_flags_cmp_w(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(2, dest_addr); -} - -void g65816_op_cmp_longxb(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONGX); - g65816_flags_cmp_b(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(1, dest_addr); -} - -void g65816_op_cmp_longxw(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONGX); - g65816_flags_cmp_w(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(2, dest_addr); -} - -void g65816_op_cmp_addryb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - g65816_flags_cmp_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_cmp_addryw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - g65816_flags_cmp_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_cmp_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - g65816_flags_cmp_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_cmp_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - g65816_flags_cmp_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_cmp_idpxb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPX); - g65816_flags_cmp_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_cmp_idpxw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPX); - g65816_flags_cmp_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_cmp_idpyb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPY); - g65816_flags_cmp_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2 | TIMING_CONDITION4); -} - -void g65816_op_cmp_idpyw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPY); - g65816_flags_cmp_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2 | TIMING_CONDITION4); -} - -void g65816_op_cmp_ildpyb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDPY); - g65816_flags_cmp_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_cmp_ildpyw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDPY); - g65816_flags_cmp_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_cmp_srb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_SR); - g65816_flags_cmp_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(1); -} - -void g65816_op_cmp_srw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_SR); - g65816_flags_cmp_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(1); -} - -void g65816_op_cmp_isryb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_ISRY); - g65816_flags_cmp_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(2); -} - -void g65816_op_cmp_isryw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_ISRY); - g65816_flags_cmp_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2); -} - -void g65816_op_cmp_constb(void) { -g65816_prefetch(1); -int r; - r = gx816->regs.a.b - arg; +void g65816_flags_cmp_b() { +int r = gx816->regs.a.b - gx816->op.r.b; g65816_testn(r & 0x80); g65816_testz((byte)r == 0); g65816_testc(r >= 0); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); } -void g65816_op_cmp_constw(void) { -g65816_prefetch(2); -int r; - r = gx816->regs.a.w - arg; +void g65816_flags_cmp_w() { +int r = gx816->regs.a.w - gx816->op.r.w; g65816_testn(r & 0x8000); g65816_testz((word)r == 0); g65816_testc(r >= 0); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); +} + +/************************ + *** 0xc9: cmp #const *** + ************************ +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; idl + [2a] pbr,pc+2 ; idh [1] +*/ + +void g65816_op_cmp_constb(void) { + gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch] + + g65816_flags_cmp_b(); + g65816_incpc(2); +} + +void g65816_op_cmp_constw(void) { + gx816->op.r.w = gx816->read_operand(2); //1,2,2a [op fetch] + + g65816_flags_cmp_w(); + g65816_incpc(3); +} + +/********************** + *** 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 g65816_op_cmp_addrb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + + g65816_flags_cmp_b(); + g65816_incpc(3); +} + +void g65816_op_cmp_addrw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + + g65816_flags_cmp_w(); + g65816_incpc(3); +} + +/************************ + *** 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 g65816_op_cmp_addrxb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read] + + g65816_flags_cmp_b(); + g65816_incpc(3); +} + +void g65816_op_cmp_addrxw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //4a [read high] + + g65816_flags_cmp_w(); + g65816_incpc(3); +} + +/******************** + *** 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 g65816_op_cmp_dpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + + g65816_flags_cmp_b(); + g65816_incpc(2); +} + +void g65816_op_cmp_dpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + + g65816_flags_cmp_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_cmp_idpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read] + + g65816_flags_cmp_b(); + g65816_incpc(2); +} + +void g65816_op_cmp_idpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //5a [read high] + + g65816_flags_cmp_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_cmp_ildpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read] + + g65816_flags_cmp_b(); + g65816_incpc(2); +} + +void g65816_op_cmp_ildpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //6a [read high] + + g65816_flags_cmp_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_cmp_longb(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read] + + g65816_flags_cmp_b(); + g65816_incpc(4); +} + +void g65816_op_cmp_longw(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read] + gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //5a [read] + + g65816_flags_cmp_w(); + g65816_incpc(4); +} + +/************************ + *** 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 g65816_op_cmp_longxb(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read] + + g65816_flags_cmp_b(); + g65816_incpc(4); +} + +void g65816_op_cmp_longxw(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read] + gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x + 1); //5a [read] + + g65816_flags_cmp_w(); + g65816_incpc(4); +} + +/************************ + *** 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 g65816_op_cmp_addryb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read] + + g65816_flags_cmp_b(); + g65816_incpc(3); +} + +void g65816_op_cmp_addryw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //4a [read high] + + g65816_flags_cmp_w(); + g65816_incpc(3); +} + +/********************** + *** 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 g65816_op_cmp_dpxb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read] + + g65816_flags_cmp_b(); + g65816_incpc(2); +} + +void g65816_op_cmp_dpxw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high] + + g65816_flags_cmp_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_cmp_idpxb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read] + + g65816_flags_cmp_b(); + g65816_incpc(2); +} + +void g65816_op_cmp_idpxw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //6 [read high] + + g65816_flags_cmp_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_cmp_idpyb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read] + + g65816_flags_cmp_b(); + g65816_incpc(2); +} + +void g65816_op_cmp_idpyw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //5a [read high] + + g65816_flags_cmp_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_cmp_ildpyb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read] + + g65816_flags_cmp_b(); + g65816_incpc(2); +} + +void g65816_op_cmp_ildpyw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y + 1); //6a [read high] + + g65816_flags_cmp_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_cmp_srb(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read] + + g65816_flags_cmp_b(); + g65816_incpc(2); +} + +void g65816_op_cmp_srw(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //4a [read high] + + g65816_flags_cmp_w(); + g65816_incpc(2); +} + +/************************** + *** 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 g65816_op_cmp_isryb(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read] + + g65816_flags_cmp_b(); + g65816_incpc(2); +} + +void g65816_op_cmp_isryw(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //7a [read high] + + g65816_flags_cmp_w(); + g65816_incpc(2); } diff --git a/bsnes/cpu/g65816_ops_eor.cpp b/bsnes/cpu/g65816_ops_eor.cpp index 80932ee4..c60f28a6 100644 --- a/bsnes/cpu/g65816_ops_eor.cpp +++ b/bsnes/cpu/g65816_ops_eor.cpp @@ -1,335 +1,504 @@ -#define g65816_flags_eor_b() g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0) -#define g65816_flags_eor_w() g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0) - -#define g65816_inst_eor_b() gx816->regs.a.b ^= gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr) -#define g65816_inst_eor_w() gx816->regs.a.w ^= gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr) - -void g65816_op_eor_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - g65816_inst_eor_b(); - g65816_flags_eor_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); +void g65816_flags_eor_b() { + g65816_testn(gx816->regs.a.b & 0x80); + g65816_testz(gx816->regs.a.b == 0); } -void g65816_op_eor_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - g65816_inst_eor_w(); - g65816_flags_eor_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); +void g65816_flags_eor_w() { + g65816_testn(gx816->regs.a.w & 0x8000); + g65816_testz(gx816->regs.a.w == 0); } -void g65816_op_eor_addrxb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - g65816_inst_eor_b(); - g65816_flags_eor_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_eor_addrxw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - g65816_inst_eor_w(); - g65816_flags_eor_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_eor_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - g65816_inst_eor_b(); - g65816_flags_eor_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_eor_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - g65816_inst_eor_w(); - g65816_flags_eor_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_eor_idpb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDP); - g65816_inst_eor_b(); - g65816_flags_eor_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_eor_idpw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDP); - g65816_inst_eor_w(); - g65816_flags_eor_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_eor_ildpb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDP); - g65816_inst_eor_b(); - g65816_flags_eor_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_eor_ildpw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDP); - g65816_inst_eor_w(); - g65816_flags_eor_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_eor_longb(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONG); - g65816_inst_eor_b(); - g65816_flags_eor_b(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(1, dest_addr); -} - -void g65816_op_eor_longw(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONG); - g65816_inst_eor_w(); - g65816_flags_eor_w(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(2, dest_addr); -} - -void g65816_op_eor_longxb(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONGX); - g65816_inst_eor_b(); - g65816_flags_eor_b(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(1, dest_addr); -} - -void g65816_op_eor_longxw(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONGX); - g65816_inst_eor_w(); - g65816_flags_eor_w(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(2, dest_addr); -} - -void g65816_op_eor_addryb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - g65816_inst_eor_b(); - g65816_flags_eor_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_eor_addryw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - g65816_inst_eor_w(); - g65816_flags_eor_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_eor_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - g65816_inst_eor_b(); - g65816_flags_eor_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_eor_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - g65816_inst_eor_w(); - g65816_flags_eor_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_eor_idpxb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPX); - g65816_inst_eor_b(); - g65816_flags_eor_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_eor_idpxw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPX); - g65816_inst_eor_w(); - g65816_flags_eor_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_eor_idpyb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPY); - g65816_inst_eor_b(); - g65816_flags_eor_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2 | TIMING_CONDITION4); -} - -void g65816_op_eor_idpyw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPY); - g65816_inst_eor_w(); - g65816_flags_eor_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2 | TIMING_CONDITION4); -} - -void g65816_op_eor_ildpyb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDPY); - g65816_inst_eor_b(); - g65816_flags_eor_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_eor_ildpyw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDPY); - g65816_inst_eor_w(); - g65816_flags_eor_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_eor_srb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_SR); - g65816_inst_eor_b(); - g65816_flags_eor_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(1); -} - -void g65816_op_eor_srw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_SR); - g65816_inst_eor_w(); - g65816_flags_eor_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(1); -} - -void g65816_op_eor_isryb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_ISRY); - g65816_inst_eor_b(); - g65816_flags_eor_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(2); -} - -void g65816_op_eor_isryw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_ISRY); - g65816_inst_eor_w(); - g65816_flags_eor_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2); -} +/************************ + *** 0x49: eor #const *** + ************************ +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; idl + [2a] pbr,pc+2 ; idh [1] +*/ void g65816_op_eor_constb(void) { -g65816_prefetch(1); - gx816->regs.a.b ^= arg; + gx816->regs.a.b ^= gx816->read_operand(1); //1,2 [op fetch] + g65816_flags_eor_b(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); } void g65816_op_eor_constw(void) { -g65816_prefetch(2); - gx816->regs.a.w ^= arg; + gx816->regs.a.w ^= gx816->read_operand(2); //1,2,2a [op fetch] + g65816_flags_eor_w(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); +} + +/********************** + *** 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 g65816_op_eor_addrb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->regs.a.b ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + + g65816_flags_eor_b(); + g65816_incpc(3); +} + +void g65816_op_eor_addrw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + + g65816_flags_eor_w(); + g65816_incpc(3); +} + +/************************ + *** 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 g65816_op_eor_addrxb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->regs.a.b ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read] + + g65816_flags_eor_b(); + g65816_incpc(3); +} + +void g65816_op_eor_addrxw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read low] + gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //4a [read high] + + g65816_flags_eor_w(); + g65816_incpc(3); +} + +/******************** + *** 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 g65816_op_eor_dpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->regs.a.b ^= gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + + g65816_flags_eor_b(); + g65816_incpc(2); +} + +void g65816_op_eor_dpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + + g65816_flags_eor_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_eor_idpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->regs.a.b ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read] + + g65816_flags_eor_b(); + g65816_incpc(2); +} + +void g65816_op_eor_idpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read low] + gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //5a [read high] + + g65816_flags_eor_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_eor_ildpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->regs.a.b ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read] + + g65816_flags_eor_b(); + g65816_incpc(2); +} + +void g65816_op_eor_ildpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->regs.a.p.l ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read low] + gx816->regs.a.p.h ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //6a [read high] + + g65816_flags_eor_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_eor_longb(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->regs.a.b ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read] + + g65816_flags_eor_b(); + g65816_incpc(4); +} + +void g65816_op_eor_longw(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->regs.a.p.l ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read] + gx816->regs.a.p.h ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //5a [read] + + g65816_flags_eor_w(); + g65816_incpc(4); +} + +/************************ + *** 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 g65816_op_eor_longxb(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->regs.a.b ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read] + + g65816_flags_eor_b(); + g65816_incpc(4); +} + +void g65816_op_eor_longxw(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->regs.a.p.l ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read] + gx816->regs.a.p.h ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x + 1); //5a [read] + + g65816_flags_eor_w(); + g65816_incpc(4); +} + +/************************ + *** 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 g65816_op_eor_addryb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0] + gx816->regs.a.b ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read] + + g65816_flags_eor_b(); + g65816_incpc(3); +} + +void g65816_op_eor_addryw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0] + gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read low] + gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //4a [read high] + + g65816_flags_eor_w(); + g65816_incpc(3); +} + +/********************** + *** 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 g65816_op_eor_dpxb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.a.b ^= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read] + + g65816_flags_eor_b(); + g65816_incpc(2); +} + +void g65816_op_eor_dpxw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low] + gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high] + + g65816_flags_eor_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_eor_idpxb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah] + gx816->regs.a.b ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read] + + g65816_flags_eor_b(); + g65816_incpc(2); +} + +void g65816_op_eor_idpxw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah] + gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read low] + gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //6 [read high] + + g65816_flags_eor_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_eor_idpyb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0] + gx816->regs.a.b ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read] + + g65816_flags_eor_b(); + g65816_incpc(2); +} + +void g65816_op_eor_idpyw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0] + gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read low] + gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //5a [read high] + + g65816_flags_eor_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_eor_ildpyb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->regs.a.b ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read] + + g65816_flags_eor_b(); + g65816_incpc(2); +} + +void g65816_op_eor_ildpyw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->regs.a.p.l ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read low] + gx816->regs.a.p.h ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y + 1); //6a [read high] + + g65816_flags_eor_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_eor_srb(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.a.b ^= gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read] + + g65816_flags_eor_b(); + g65816_incpc(2); +} + +void g65816_op_eor_srw(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.a.p.l ^= gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read low] + gx816->regs.a.p.h ^= gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //4a [read high] + + g65816_flags_eor_w(); + g65816_incpc(2); +} + +/************************** + *** 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 g65816_op_eor_isryb(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->regs.a.b ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read] + + g65816_flags_eor_b(); + g65816_incpc(2); +} + +void g65816_op_eor_isryw(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read low] + gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //7a [read high] + + g65816_flags_eor_w(); + g65816_incpc(2); } diff --git a/bsnes/cpu/g65816_ops_incdec.cpp b/bsnes/cpu/g65816_ops_incdec.cpp index 5abaa9c7..a9a26722 100644 --- a/bsnes/cpu/g65816_ops_incdec.cpp +++ b/bsnes/cpu/g65816_ops_incdec.cpp @@ -1,355 +1,511 @@ -/*********** - *** inc *** - **********/ +/***************** + *** 0x1a: inc *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ void g65816_op_incb(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + gx816->regs.a.b++; g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_incw(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + gx816->regs.a.w++; g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/********************** + *** 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 g65816_op_inc_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - m++; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); - g65816_testn(m & 0x80); - g65816_testz(m == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + snes_time->add_cpu_icycles(1); //5 [i/o] + gx816->op.r.b++; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.b); //6 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1); } void g65816_op_inc_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - m++; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); - g65816_testn(m & 0x8000); - g65816_testz(m == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + snes_time->add_cpu_icycles(1); //5 [i/o] + gx816->op.r.w++; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->op.r.p.h); //6a [write high] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.p.l); //6 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(1); } +/************************ + *** 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 g65816_op_inc_addrxb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - m++; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); - g65816_testn(m & 0x80); - g65816_testz(m == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->op.r.b++; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.b); //7 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2); } void g65816_op_inc_addrxw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - m++; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); - g65816_testn(m & 0x8000); - g65816_testz(m == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //5a [read high] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->op.r.w++; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1, gx816->op.r.p.h); //7a [write high] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.p.l); //7 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(2); } +/******************** + *** 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 g65816_op_inc_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - m++; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); - g65816_testn(m & 0x80); - g65816_testz(m == 0); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->op.r.b++; + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.b); //5 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_REGD); } void g65816_op_inc_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - m++; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); - g65816_testn(m & 0x8000); - g65816_testz(m == 0); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->op.r.w++; + gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->op.r.p.h); //5a [write high] + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.p.l); //5 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_REGD); } +/********************** + *** 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 g65816_op_inc_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - m++; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); - g65816_testn(m & 0x80); - g65816_testz(m == 0); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read] + snes_time->add_cpu_icycles(1); //5 [i/o] + gx816->op.r.b++; + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.b); //6 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2, TIMING_REGD); } void g65816_op_inc_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - m++; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); - g65816_testn(m & 0x8000); - g65816_testz(m == 0); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high] + snes_time->add_cpu_icycles(1); //5 [i/o] + gx816->op.r.w++; + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1, gx816->op.r.p.h); //6a [write high] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.p.l); //6 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(2, TIMING_REGD); } -/*********** - *** inx *** - **********/ +/***************** + *** 0xe8: inx *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ void g65816_op_inxb(void) { - gx816->regs.x = (gx816->regs.x + 1) & 0xff; + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + + gx816->regs.x++; + gx816->regs.x &= 0xff; g65816_testn(gx816->regs.x & 0x80); - g65816_testz((gx816->regs.x & 0xff) == 0); + g65816_testz(gx816->regs.x == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_inxw(void) { - gx816->regs.x += 1; + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + + gx816->regs.x++; g65816_testn(gx816->regs.x & 0x8000); g65816_testz(gx816->regs.x == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } -/*********** - *** iny *** - **********/ +/***************** + *** 0xc8: iny *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ void g65816_op_inyb(void) { - gx816->regs.y = (gx816->regs.y + 1) & 0xff; + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + + gx816->regs.y++; + gx816->regs.y &= 0xff; g65816_testn(gx816->regs.y & 0x80); - g65816_testz((gx816->regs.y & 0xff) == 0); + g65816_testz(gx816->regs.y == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_inyw(void) { - gx816->regs.y += 1; + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + + gx816->regs.y++; g65816_testn(gx816->regs.y & 0x8000); g65816_testz(gx816->regs.y == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } -/*********** - *** dec *** - **********/ +/***************** + *** 0x3a: dec *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ void g65816_op_decb(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + gx816->regs.a.b--; g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_decw(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + gx816->regs.a.w--; g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/********************** + *** 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 g65816_op_dec_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - m--; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); - g65816_testn(m & 0x80); - g65816_testz(m == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + snes_time->add_cpu_icycles(1); //5 [i/o] + gx816->op.r.b--; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.b); //6 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1); } void g65816_op_dec_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - m--; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); - g65816_testn(m & 0x8000); - g65816_testz(m == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + snes_time->add_cpu_icycles(1); //5 [i/o] + gx816->op.r.w--; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->op.r.p.h); //6a [write high] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.p.l); //6 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(1); } +/************************ + *** 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 g65816_op_dec_addrxb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - m--; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); - g65816_testn(m & 0x80); - g65816_testz(m == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->op.r.b--; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.b); //7 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2); } void g65816_op_dec_addrxw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - m--; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); - g65816_testn(m & 0x8000); - g65816_testz(m == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //5a [read high] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->op.r.w--; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1, gx816->op.r.p.h); //7a [write high] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.p.l); //7 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(2); } +/******************** + *** 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 g65816_op_dec_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - m--; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); - g65816_testn(m & 0x80); - g65816_testz(m == 0); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->op.r.b--; + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.b); //5 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_REGD); } void g65816_op_dec_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - m--; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); - g65816_testn(m & 0x8000); - g65816_testz(m == 0); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->op.r.w--; + gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->op.r.p.h); //5a [write high] + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.p.l); //5 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_REGD); } +/********************** + *** 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 g65816_op_dec_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - m--; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); - g65816_testn(m & 0x80); - g65816_testz(m == 0); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read] + snes_time->add_cpu_icycles(1); //5 [i/o] + gx816->op.r.b--; + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.b); //6 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2, TIMING_REGD); } void g65816_op_dec_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - m--; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); - g65816_testn(m & 0x8000); - g65816_testz(m == 0); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high] + snes_time->add_cpu_icycles(1); //5 [i/o] + gx816->op.r.w--; + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1, gx816->op.r.p.h); //6a [write high] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.p.l); //6 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(2, TIMING_REGD); } -/*********** - *** dex *** - **********/ +/***************** + *** 0xca: dex *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ void g65816_op_dexb(void) { - gx816->regs.x = (gx816->regs.x - 1) & 0xff; + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + + gx816->regs.x--; + gx816->regs.x &= 0xff; g65816_testn(gx816->regs.x & 0x80); - g65816_testz((gx816->regs.x & 0xff) == 0); + g65816_testz(gx816->regs.x == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_dexw(void) { - gx816->regs.x -= 1; + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + + gx816->regs.x--; g65816_testn(gx816->regs.x & 0x8000); g65816_testz(gx816->regs.x == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } -/*********** - *** dey *** - **********/ +/***************** + *** 0x88: dey *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ void g65816_op_deyb(void) { - gx816->regs.y = (gx816->regs.y - 1) & 0xff; + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + + gx816->regs.y--; + gx816->regs.y &= 0xff; g65816_testn(gx816->regs.y & 0x80); - g65816_testz((gx816->regs.y & 0xff) == 0); + g65816_testz(gx816->regs.y == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_deyw(void) { - gx816->regs.y -= 1; + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + + gx816->regs.y--; g65816_testn(gx816->regs.y & 0x8000); g65816_testz(gx816->regs.y == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } diff --git a/bsnes/cpu/g65816_ops_lda.cpp b/bsnes/cpu/g65816_ops_lda.cpp index 289285cd..bacc7fdd 100644 --- a/bsnes/cpu/g65816_ops_lda.cpp +++ b/bsnes/cpu/g65816_ops_lda.cpp @@ -1,335 +1,504 @@ -#define g65816_flags_lda_b() g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0) -#define g65816_flags_lda_w() g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0) - -#define g65816_set_lda_b() gx816->regs.a.b = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr) -#define g65816_set_lda_w() gx816->regs.a.w = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr) - -void g65816_op_lda_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - g65816_set_lda_b(); - g65816_flags_lda_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); +void g65816_flags_lda_b(void) { + g65816_testn(gx816->regs.a.b & 0x80); + g65816_testz(gx816->regs.a.b == 0); } -void g65816_op_lda_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - g65816_set_lda_w(); - g65816_flags_lda_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); +void g65816_flags_lda_w(void) { + g65816_testn(gx816->regs.a.w & 0x8000); + g65816_testz(gx816->regs.a.w == 0); } -void g65816_op_lda_addrxb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - g65816_set_lda_b(); - g65816_flags_lda_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_lda_addrxw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - g65816_set_lda_w(); - g65816_flags_lda_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_lda_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - g65816_set_lda_b(); - g65816_flags_lda_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_lda_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - g65816_set_lda_w(); - g65816_flags_lda_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_lda_idpb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDP); - g65816_set_lda_b(); - g65816_flags_lda_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_lda_idpw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDP); - g65816_set_lda_w(); - g65816_flags_lda_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_lda_ildpb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDP); - g65816_set_lda_b(); - g65816_flags_lda_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_lda_ildpw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDP); - g65816_set_lda_w(); - g65816_flags_lda_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_lda_longb(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONG); - g65816_set_lda_b(); - g65816_flags_lda_b(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(1, dest_addr); -} - -void g65816_op_lda_longw(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONG); - g65816_set_lda_w(); - g65816_flags_lda_w(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(2, dest_addr); -} - -void g65816_op_lda_longxb(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONGX); - g65816_set_lda_b(); - g65816_flags_lda_b(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(1, dest_addr); -} - -void g65816_op_lda_longxw(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONGX); - g65816_set_lda_w(); - g65816_flags_lda_w(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(2, dest_addr); -} - -void g65816_op_lda_addryb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - g65816_set_lda_b(); - g65816_flags_lda_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_lda_addryw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - g65816_set_lda_w(); - g65816_flags_lda_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_lda_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - g65816_set_lda_b(); - g65816_flags_lda_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_lda_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - g65816_set_lda_w(); - g65816_flags_lda_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_lda_idpxb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPX); - g65816_set_lda_b(); - g65816_flags_lda_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_lda_idpxw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPX); - g65816_set_lda_w(); - g65816_flags_lda_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_lda_idpyb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPY); - g65816_set_lda_b(); - g65816_flags_lda_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2 | TIMING_CONDITION4); -} - -void g65816_op_lda_idpyw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPY); - g65816_set_lda_w(); - g65816_flags_lda_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2 | TIMING_CONDITION4); -} - -void g65816_op_lda_ildpyb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDPY); - g65816_set_lda_b(); - g65816_flags_lda_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_lda_ildpyw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDPY); - g65816_set_lda_w(); - g65816_flags_lda_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_lda_srb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_SR); - g65816_set_lda_b(); - g65816_flags_lda_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(1); -} - -void g65816_op_lda_srw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_SR); - g65816_set_lda_w(); - g65816_flags_lda_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(1); -} - -void g65816_op_lda_isryb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_ISRY); - g65816_set_lda_b(); - g65816_flags_lda_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(2); -} - -void g65816_op_lda_isryw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_ISRY); - g65816_set_lda_w(); - g65816_flags_lda_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2); -} +/************************ + *** 0xa9: lda #const *** + ************************ +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; idl + [2a] pbr,pc+2 ; idh [1] +*/ void g65816_op_lda_constb(void) { -g65816_prefetch(1); - gx816->regs.a.b = arg; + gx816->regs.a.b = gx816->read_operand(1); //1,2 [op fetch] + g65816_flags_lda_b(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); } void g65816_op_lda_constw(void) { -g65816_prefetch(2); - gx816->regs.a.w = arg; + gx816->regs.a.w = gx816->read_operand(2); //1,2,2a [op fetch] + g65816_flags_lda_w(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); +} + +/********************** + *** 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 g65816_op_lda_addrb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->regs.a.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + + g65816_flags_lda_b(); + g65816_incpc(3); +} + +void g65816_op_lda_addrw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->regs.a.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->regs.a.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + + g65816_flags_lda_w(); + g65816_incpc(3); +} + +/************************ + *** 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 g65816_op_lda_addrxb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->regs.a.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read] + + g65816_flags_lda_b(); + g65816_incpc(3); +} + +void g65816_op_lda_addrxw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->regs.a.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read low] + gx816->regs.a.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //4a [read high] + + g65816_flags_lda_w(); + g65816_incpc(3); +} + +/******************** + *** 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 g65816_op_lda_dpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->regs.a.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + + g65816_flags_lda_b(); + g65816_incpc(2); +} + +void g65816_op_lda_dpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->regs.a.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->regs.a.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + + g65816_flags_lda_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_lda_idpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->regs.a.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read] + + g65816_flags_lda_b(); + g65816_incpc(2); +} + +void g65816_op_lda_idpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->regs.a.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read low] + gx816->regs.a.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //5a [read high] + + g65816_flags_lda_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_lda_ildpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->regs.a.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read] + + g65816_flags_lda_b(); + g65816_incpc(2); +} + +void g65816_op_lda_ildpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->regs.a.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read low] + gx816->regs.a.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //6a [read high] + + g65816_flags_lda_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_lda_longb(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->regs.a.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read] + + g65816_flags_lda_b(); + g65816_incpc(4); +} + +void g65816_op_lda_longw(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->regs.a.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read] + gx816->regs.a.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //5a [read] + + g65816_flags_lda_w(); + g65816_incpc(4); +} + +/************************ + *** 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 g65816_op_lda_longxb(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->regs.a.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read] + + g65816_flags_lda_b(); + g65816_incpc(4); +} + +void g65816_op_lda_longxw(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->regs.a.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read] + gx816->regs.a.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x + 1); //5a [read] + + g65816_flags_lda_w(); + g65816_incpc(4); +} + +/************************ + *** 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 g65816_op_lda_addryb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0] + gx816->regs.a.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read] + + g65816_flags_lda_b(); + g65816_incpc(3); +} + +void g65816_op_lda_addryw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0] + gx816->regs.a.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read low] + gx816->regs.a.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //4a [read high] + + g65816_flags_lda_w(); + g65816_incpc(3); +} + +/********************** + *** 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 g65816_op_lda_dpxb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.a.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read] + + g65816_flags_lda_b(); + g65816_incpc(2); +} + +void g65816_op_lda_dpxw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.a.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low] + gx816->regs.a.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high] + + g65816_flags_lda_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_lda_idpxb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah] + gx816->regs.a.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read] + + g65816_flags_lda_b(); + g65816_incpc(2); +} + +void g65816_op_lda_idpxw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah] + gx816->regs.a.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read low] + gx816->regs.a.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //6 [read high] + + g65816_flags_lda_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_lda_idpyb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0] + gx816->regs.a.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read] + + g65816_flags_lda_b(); + g65816_incpc(2); +} + +void g65816_op_lda_idpyw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0] + gx816->regs.a.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read low] + gx816->regs.a.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //5a [read high] + + g65816_flags_lda_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_lda_ildpyb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->regs.a.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read] + + g65816_flags_lda_b(); + g65816_incpc(2); +} + +void g65816_op_lda_ildpyw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->regs.a.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read low] + gx816->regs.a.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y + 1); //6a [read high] + + g65816_flags_lda_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_lda_srb(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.a.b = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read] + + g65816_flags_lda_b(); + g65816_incpc(2); +} + +void g65816_op_lda_srw(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.a.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read low] + gx816->regs.a.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //4a [read high] + + g65816_flags_lda_w(); + g65816_incpc(2); +} + +/************************** + *** 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 g65816_op_lda_isryb(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->regs.a.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read] + + g65816_flags_lda_b(); + g65816_incpc(2); +} + +void g65816_op_lda_isryw(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->regs.a.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read low] + gx816->regs.a.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //7a [read high] + + g65816_flags_lda_w(); + g65816_incpc(2); } diff --git a/bsnes/cpu/g65816_ops_misc.cpp b/bsnes/cpu/g65816_ops_misc.cpp index 6737a35f..d8d8b2d4 100644 --- a/bsnes/cpu/g65816_ops_misc.cpp +++ b/bsnes/cpu/g65816_ops_misc.cpp @@ -1,1294 +1,1692 @@ -/*********** - *** bit *** - **********/ +void g65816_flags_bit_b(void) { + g65816_testn(gx816->op.r.b & 0x80); + g65816_testv(gx816->op.r.b & 0x40); + g65816_testz((gx816->op.r.b & gx816->regs.a.b) == 0); +} + +void g65816_flags_bit_w(void) { + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testv(gx816->op.r.w & 0x4000); + g65816_testz((gx816->op.r.w & gx816->regs.a.w) == 0); +} + +/************************ + *** 0x89: bit #const *** + ************************ +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; idl + [2a] pbr,pc+2 ; idh [1] +*/ void g65816_op_bit_constb(void) { -g65816_prefetch(1); - g65816_testn(arg & 0x80); - g65816_testv(arg & 0x40); - g65816_testz((arg & gx816->regs.a.b) == 0); + gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch] + g65816_flags_bit_b(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); } void g65816_op_bit_constw(void) { -g65816_prefetch(2); - g65816_testn(arg & 0x8000); - g65816_testv(arg & 0x4000); - g65816_testz((arg & gx816->regs.a.w) == 0); + gx816->op.r.w = gx816->read_operand(2); //1,2,2a [op fetch] + g65816_flags_bit_w(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); } +/********************** + *** 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 g65816_op_bit_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - arg = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testn(arg & 0x80); - g65816_testv(arg & 0x40); - g65816_testz((arg & gx816->regs.a.b) == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + g65816_flags_bit_b(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); } void g65816_op_bit_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - arg = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testn(arg & 0x8000); - g65816_testv(arg & 0x4000); - g65816_testz((arg & gx816->regs.a.w) == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + g65816_flags_bit_w(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); } +/************************ + *** 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 g65816_op_bit_addrxb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - arg = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testn(arg & 0x80); - g65816_testv(arg & 0x40); - g65816_testz((arg & gx816->regs.a.b) == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read] + g65816_flags_bit_b(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); } void g65816_op_bit_addrxw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - arg = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testn(arg & 0x8000); - g65816_testv(arg & 0x4000); - g65816_testz((arg & gx816->regs.a.w) == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //4a [read high] + g65816_flags_bit_w(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); } +/******************** + *** 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 g65816_op_bit_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - arg = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testn(arg & 0x80); - g65816_testv(arg & 0x40); - g65816_testz((arg & gx816->regs.a.b) == 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + g65816_flags_bit_b(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } void g65816_op_bit_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - arg = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testn(arg & 0x8000); - g65816_testv(arg & 0x4000); - g65816_testz((arg & gx816->regs.a.w) == 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + g65816_flags_bit_w(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } +/********************** + *** 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 g65816_op_bit_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - arg = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testn(arg & 0x80); - g65816_testv(arg & 0x40); - g65816_testz((arg & gx816->regs.a.b) == 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read] + g65816_flags_bit_b(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); } void g65816_op_bit_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - arg = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testn(arg & 0x8000); - g65816_testv(arg & 0x4000); - g65816_testz((arg & gx816->regs.a.w) == 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high] + g65816_flags_bit_w(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); } -/*********** - *** cpx *** - **********/ - -void g65816_op_cpx_constb(void) { -g65816_prefetch(1); -int r = gx816->regs.x - arg; +void g65816_flags_cpx_b(void) { +int r = gx816->regs.x - gx816->op.r.b; g65816_testn(r & 0x80); g65816_testz((byte)r == 0); g65816_testc(r >= 0); +} + +void g65816_flags_cpx_w(void) { +int r = gx816->regs.x - gx816->op.r.w; + g65816_testn(r & 0x8000); + g65816_testz((word)r == 0); + g65816_testc(r >= 0); +} + +/************************ + *** 0xe0: cpx #const *** + ************************ +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; idl + [2a] pbr,pc+2 ; idh [1] +*/ + +void g65816_op_cpx_constb(void) { + gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch] + g65816_flags_cpx_b(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); } void g65816_op_cpx_constw(void) { -g65816_prefetch(2); -int r = gx816->regs.x - arg; - g65816_testn(r & 0x8000); - g65816_testz((word)r == 0); - g65816_testc(r >= 0); + gx816->op.r.w = gx816->read_operand(2); //1,2,2a [op fetch] + g65816_flags_cpx_w(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); } +/********************** + *** 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 g65816_op_cpx_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -int r = gx816->regs.x - gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testn(r & 0x80); - g65816_testz((byte)r == 0); - g65816_testc(r >= 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + g65816_flags_cpx_b(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); } void g65816_op_cpx_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -int r = gx816->regs.x - gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testn(r & 0x8000); - g65816_testz((word)r == 0); - g65816_testc(r >= 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + g65816_flags_cpx_w(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); } +/******************** + *** 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 g65816_op_cpx_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -int r = gx816->regs.x - gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testn(r & 0x80); - g65816_testz((byte)r == 0); - g65816_testc(r >= 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + g65816_flags_cpx_b(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } void g65816_op_cpx_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -int r = gx816->regs.x - gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testn(r & 0x8000); - g65816_testz((word)r == 0); - g65816_testc(r >= 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + g65816_flags_cpx_w(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } -/*********** - *** cpy *** - **********/ - -void g65816_op_cpy_constb(void) { -g65816_prefetch(1); -int r = gx816->regs.y - arg; +void g65816_flags_cpy_b(void) { +int r = gx816->regs.y - gx816->op.r.b; g65816_testn(r & 0x80); g65816_testz((byte)r == 0); g65816_testc(r >= 0); +} + +void g65816_flags_cpy_w(void) { +int r = gx816->regs.y - gx816->op.r.w; + g65816_testn(r & 0x8000); + g65816_testz((word)r == 0); + g65816_testc(r >= 0); +} + +/************************ + *** 0xc0: cpy #const *** + ************************ +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; idl + [2a] pbr,pc+2 ; idh [1] +*/ + +void g65816_op_cpy_constb(void) { + gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch] + g65816_flags_cpy_b(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); } void g65816_op_cpy_constw(void) { -g65816_prefetch(2); -int r = gx816->regs.y - arg; - g65816_testn(r & 0x8000); - g65816_testz((word)r == 0); - g65816_testc(r >= 0); + gx816->op.r.w = gx816->read_operand(2); //1,2,2a [op fetch] + g65816_flags_cpy_w(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); } +/********************** + *** 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 g65816_op_cpy_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -int r = gx816->regs.y - gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testn(r & 0x80); - g65816_testz((byte)r == 0); - g65816_testc(r >= 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + g65816_flags_cpy_b(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); } void g65816_op_cpy_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -int r = gx816->regs.y - gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testn(r & 0x8000); - g65816_testz((word)r == 0); - g65816_testc(r >= 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + g65816_flags_cpy_w(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); } +/******************** + *** 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 g65816_op_cpy_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -int r = gx816->regs.y - gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testn(r & 0x80); - g65816_testz((byte)r == 0); - g65816_testc(r >= 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + g65816_flags_cpy_b(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } void g65816_op_cpy_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -int r = gx816->regs.y - gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testn(r & 0x8000); - g65816_testz((word)r == 0); - g65816_testc(r >= 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + g65816_flags_cpy_w(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } -/*********** - *** ldx *** - **********/ - -void g65816_op_ldx_constb(void) { -g65816_prefetch(1); - gx816->regs.x = arg; +void g65816_flags_ldx_b(void) { g65816_testn(gx816->regs.x & 0x80); g65816_testz(gx816->regs.x == 0); +} + +void g65816_flags_ldx_w(void) { + g65816_testn(gx816->regs.x & 0x8000); + g65816_testz(gx816->regs.x == 0); +} + +/************************ + *** 0xa2: ldx #const *** + ************************ +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; idl + [2a] pbr,pc+2 ; idh [1] +*/ + +void g65816_op_ldx_constb(void) { + gx816->regs.x = gx816->read_operand(1); //1,2 [op fetch] + g65816_flags_ldx_b(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); } void g65816_op_ldx_constw(void) { -g65816_prefetch(2); - gx816->regs.x = arg; - g65816_testn(gx816->regs.x & 0x8000); - g65816_testz(gx816->regs.x == 0); + gx816->regs.x = gx816->read_operand(2); //1,2,2a [op fetch] + g65816_flags_ldx_w(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); } +/********************** + *** 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 g65816_op_ldx_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - gx816->regs.x = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testn(gx816->regs.x & 0x80); - g65816_testz(gx816->regs.x == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->regs.x = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + g65816_flags_ldx_b(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); } void g65816_op_ldx_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - gx816->regs.x = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testn(gx816->regs.x & 0x8000); - g65816_testz(gx816->regs.x == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->regs.x = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->regs.x |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1) << 8; //4a [read high] + g65816_flags_ldx_w(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); } +/************************ + *** 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 g65816_op_ldx_addryb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - gx816->regs.x = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testn(gx816->regs.x & 0x80); - g65816_testz(gx816->regs.x == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0] + gx816->regs.x = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read] + g65816_flags_ldx_b(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); } void g65816_op_ldx_addryw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - gx816->regs.x = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testn(gx816->regs.x & 0x8000); - g65816_testz(gx816->regs.x == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0] + gx816->regs.x = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read low] + gx816->regs.x |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1) << 8; //4a [read high] + g65816_flags_ldx_w(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); } +/******************** + *** 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 g65816_op_ldx_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - gx816->regs.x = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testn(gx816->regs.x & 0x80); - g65816_testz(gx816->regs.x == 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->regs.x = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + g65816_flags_ldx_b(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } void g65816_op_ldx_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - gx816->regs.x = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testn(gx816->regs.x & 0x8000); - g65816_testz(gx816->regs.x == 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->regs.x = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->regs.x |= gx816->op_read(OPMODE_DP, gx816->op.dp + 1) << 8; //3a [read high] + g65816_flags_ldx_w(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } +/********************** + *** 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 g65816_op_ldx_dpyb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPY); - gx816->regs.x = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testn(gx816->regs.x & 0x80); - g65816_testz(gx816->regs.x == 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.x = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.y); //4 [read] + g65816_flags_ldx_b(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); } void g65816_op_ldx_dpyw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPY); - gx816->regs.x = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testn(gx816->regs.x & 0x8000); - g65816_testz(gx816->regs.x == 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.x = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.y); //4 [read low] + gx816->regs.x |= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.y + 1) << 8; //4a [read high] + g65816_flags_ldx_w(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); } -/*********** - *** ldy *** - **********/ - -void g65816_op_ldy_constb(void) { -g65816_prefetch(1); - gx816->regs.y = (gx816->regs.y & 0xff00) | arg; +void g65816_flags_ldy_b(void) { g65816_testn(gx816->regs.y & 0x80); g65816_testz(gx816->regs.y == 0); +} + +void g65816_flags_ldy_w(void) { + g65816_testn(gx816->regs.y & 0x8000); + g65816_testz(gx816->regs.y == 0); +} + +/************************ + *** 0xa0: ldy #const *** + ************************ +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; idl + [2a] pbr,pc+2 ; idh [1] +*/ + +void g65816_op_ldy_constb(void) { + gx816->regs.y = gx816->read_operand(1); //1,2 [op fetch] + g65816_flags_ldy_b(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); } void g65816_op_ldy_constw(void) { -g65816_prefetch(2); - gx816->regs.y = arg; - g65816_testn(gx816->regs.y & 0x8000); - g65816_testz(gx816->regs.y == 0); + gx816->regs.y = gx816->read_operand(2); //1,2,2a [op fetch] + g65816_flags_ldy_w(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); } +/********************** + *** 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 g65816_op_ldy_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - gx816->regs.y = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testn(gx816->regs.y & 0x80); - g65816_testz(gx816->regs.y == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->regs.y = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + g65816_flags_ldy_b(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); } void g65816_op_ldy_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - gx816->regs.y = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testn(gx816->regs.y & 0x8000); - g65816_testz(gx816->regs.y == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->regs.y = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->regs.y |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1) << 8; //4a [read high] + g65816_flags_ldy_w(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); } +/************************ + *** 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 g65816_op_ldy_addrxb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - gx816->regs.y = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testn(gx816->regs.y & 0x80); - g65816_testz(gx816->regs.y == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->regs.y = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read] + g65816_flags_ldy_b(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); } void g65816_op_ldy_addrxw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - gx816->regs.y = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testn(gx816->regs.y & 0x8000); - g65816_testz(gx816->regs.y == 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->regs.y = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read low] + gx816->regs.y |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1) << 8; //4a [read high] + g65816_flags_ldy_w(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); } +/******************** + *** 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 g65816_op_ldy_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - gx816->regs.y = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testn(gx816->regs.y & 0x80); - g65816_testz(gx816->regs.y == 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->regs.y = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + g65816_flags_ldy_b(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } void g65816_op_ldy_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - gx816->regs.y = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testn(gx816->regs.y & 0x8000); - g65816_testz(gx816->regs.y == 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->regs.y = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->regs.y |= gx816->op_read(OPMODE_DP, gx816->op.dp + 1) << 8; //3a [read high] + g65816_flags_ldy_w(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } +/********************** + *** 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 g65816_op_ldy_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - gx816->regs.y = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testn(gx816->regs.y & 0x80); - g65816_testz(gx816->regs.y == 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.y = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read] + g65816_flags_ldy_b(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); } void g65816_op_ldy_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - gx816->regs.y = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testn(gx816->regs.y & 0x8000); - g65816_testz(gx816->regs.y == 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.y = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low] + gx816->regs.y |= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1) << 8; //4a [read high] + g65816_flags_ldy_w(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); } -/*********** - *** stx *** - **********/ +/********************** + *** 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 g65816_op_stx_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, gx816->regs.x); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.x); //4 [write] g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); } void g65816_op_stx_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, gx816->regs.x); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.x); //4 [write low] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->regs.x >> 8); //4a [write high] g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); } +/******************** + *** 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 g65816_op_stx_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, gx816->regs.x); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->regs.x); //3 [write] g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } void g65816_op_stx_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, gx816->regs.x); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->regs.x); //3 [write low] + gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->regs.x >> 8); //3a [write high] g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } +/********************** + *** 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 g65816_op_stx_dpyb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPY); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, gx816->regs.x); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.y, gx816->regs.x); //4 [write] g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); } void g65816_op_stx_dpyw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPY); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, gx816->regs.x); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.y, gx816->regs.x); //4 [write low] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.y + 1, gx816->regs.x >> 8); //4a [write high] g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); } -/*********** - *** sty *** - **********/ +/********************** + *** 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 g65816_op_sty_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, gx816->regs.y); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.y); //4 [write] g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); } void g65816_op_sty_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, gx816->regs.y); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.y); //4 [write low] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->regs.y >> 8); //4a [write high] g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); } +/******************** + *** 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 g65816_op_sty_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, gx816->regs.y); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->regs.y); //3 [write] g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } void g65816_op_sty_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, gx816->regs.y); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->regs.y); //3 [write low] + gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->regs.y >> 8); //3a [write high] g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } +/********************** + *** 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 g65816_op_sty_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, gx816->regs.y); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->regs.y); //4 [write] g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); } void g65816_op_sty_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, gx816->regs.y); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->regs.y); //4 [write low] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1, gx816->regs.y >> 8); //4a [write high] g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); } -/*********** - *** stz *** - **********/ +/********************** + *** 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 g65816_op_stz_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, 0); //4 [write] g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); } void g65816_op_stz_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, 0); //4 [write low] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, 0); //4a [write high] g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); } +/************************ + *** 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 g65816_op_stz_addrxb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //3a [write i/o] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, 0); //4 [write] g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); } void g65816_op_stz_addrxw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, 0); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //3a [write i/o] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, 0); //4 [write low] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1, 0); //4a [write high] g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); } +/******************** + *** 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 g65816_op_stz_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op_write(OPMODE_DP, gx816->op.dp, 0); //3 [write] g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } void g65816_op_stz_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op_write(OPMODE_DP, gx816->op.dp, 0); //3 [write low] + gx816->op_write(OPMODE_DP, gx816->op.dp + 1, 0); //3a [write high] g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } +/********************** + *** 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 g65816_op_stz_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, 0); //4 [write] g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); } void g65816_op_stz_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, 0); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, 0); //4 [write low] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1, 0); //4a [write high] g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); } -/*********** - *** xba *** - **********/ +/***************** + *** 0xeb: xba *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io + [3] pbr,pc+1 ; io +*/ void g65816_op_xba(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(2); //2,3 [i/o] gx816->regs.a.p.l ^= gx816->regs.a.p.h; gx816->regs.a.p.h ^= gx816->regs.a.p.l; gx816->regs.a.p.l ^= gx816->regs.a.p.h; g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(2); } -/*********** - *** trb *** - **********/ +/********************** + *** 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 g65816_op_trb_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testz((m & gx816->regs.a.b) == 0); - m &= ~gx816->regs.a.b; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testz((gx816->op.r.b & gx816->regs.a.b) == 0); + gx816->op.r.b &= ~gx816->regs.a.b; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.b); //6 [write] g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1); } void g65816_op_trb_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testz((m & gx816->regs.a.w) == 0); - m &= ~gx816->regs.a.w; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testz((gx816->op.r.w & gx816->regs.a.w) == 0); + gx816->op.r.w &= ~gx816->regs.a.w; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->op.r.p.h); //6a [write high] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.p.l); //6 [write low] g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(1); } +/******************** + *** 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 g65816_op_trb_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testz((m & gx816->regs.a.b) == 0); - m &= ~gx816->regs.a.b; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + snes_time->add_cpu_icycles(1); //4 [i/o] + g65816_testz((gx816->op.r.b & gx816->regs.a.b) == 0); + gx816->op.r.b &= ~gx816->regs.a.b; + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.b); //5 [write] g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_REGD); } void g65816_op_trb_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testz((m & gx816->regs.a.w) == 0); - m &= ~gx816->regs.a.w; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + snes_time->add_cpu_icycles(1); //4 [i/o] + g65816_testz((gx816->op.r.w & gx816->regs.a.w) == 0); + gx816->op.r.w &= ~gx816->regs.a.w; + gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->op.r.p.h); //5a [write high] + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.p.l); //5 [write low] g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_REGD); } -/*********** - *** tsb *** - **********/ +/********************** + *** 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 g65816_op_tsb_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testz((m & gx816->regs.a.b) == 0); - m |= gx816->regs.a.b; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testz((gx816->op.r.b & gx816->regs.a.b) == 0); + gx816->op.r.b |= gx816->regs.a.b; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.b); //6 [write] g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1); } void g65816_op_tsb_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testz((m & gx816->regs.a.w) == 0); - m |= gx816->regs.a.w; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testz((gx816->op.r.w & gx816->regs.a.w) == 0); + gx816->op.r.w |= gx816->regs.a.w; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->op.r.p.h); //6a [write high] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.p.l); //6 [write low] g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(1); } +/******************** + *** 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 g65816_op_tsb_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testz((m & gx816->regs.a.b) == 0); - m |= gx816->regs.a.b; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + snes_time->add_cpu_icycles(1); //4 [i/o] + g65816_testz((gx816->op.r.b & gx816->regs.a.b) == 0); + gx816->op.r.b |= gx816->regs.a.b; + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.b); //5 [write] g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_REGD); } void g65816_op_tsb_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testz((m & gx816->regs.a.w) == 0); - m |= gx816->regs.a.w; - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + snes_time->add_cpu_icycles(1); //4 [i/o] + g65816_testz((gx816->op.r.w & gx816->regs.a.w) == 0); + gx816->op.r.w |= gx816->regs.a.w; + gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->op.r.p.h); //5a [write high] + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.p.l); //5 [write low] g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_REGD); } -/*********** - *** mvn *** - **********/ +/************************** + *** 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 g65816_op_mvn(void) { -g65816_prefetch(2); ulong sp, dp; -byte m; - if(gx816->regs.a.w != 0xffff) { - gx816->regs.a.w--; - dp = (arg) & 0xff; - sp = (arg >> 8) & 0xff; - dp = (dp << 16) | gx816->regs.y; - sp = (sp << 16) | gx816->regs.x; - m = gx816->mem_read(MEMMODE_LONG, MEMSIZE_BYTE, sp); - gx816->mem_write(MEMMODE_LONG, MEMSIZE_BYTE, dp, m); - gx816->regs.x++; - gx816->regs.y++; - if(gx816->regs.e == true || (gx816->regs.e == false && (gx816->regs.p & PF_X))) { - gx816->regs.x &= 0xff; - gx816->regs.y &= 0xff; - } + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->regs.a.w--; + dp = (gx816->op.aa.p.l << 16) | gx816->regs.y; + sp = (gx816->op.aa.p.h << 16) | gx816->regs.x; + gx816->op.r.b = gx816->op_read(OPMODE_LONG, sp); //4 [src data] + gx816->op_write(OPMODE_LONG, dp, gx816->op.r.b); //5 [dest data] + gx816->regs.x++; + gx816->regs.y++; + if(gx816->regs.e == true || (gx816->regs.p & PF_X)) { + gx816->regs.x &= 0xff; + gx816->regs.y &= 0xff; } if(gx816->regs.a.w == 0xffff) { g65816_incpc(3); } - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, sp); - snes_time->add_cpu_mcycles(1, dp); - snes_time->add_cpu_icycles(2); + snes_time->add_cpu_icycles(2); //6,7 [i/o] } -/*********** - *** mvp *** - **********/ +/************************** + *** 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 g65816_op_mvp(void) { -g65816_prefetch(2); ulong sp, dp; -byte m; - if(gx816->regs.a.w != 0xffff) { - gx816->regs.a.w--; - dp = (arg) & 0xff; - sp = (arg >> 8) & 0xff; - dp = (dp << 16) | gx816->regs.y; - sp = (sp << 16) | gx816->regs.x; - m = gx816->mem_read(MEMMODE_LONG, MEMSIZE_BYTE, sp); - gx816->mem_write(MEMMODE_LONG, MEMSIZE_BYTE, dp, m); - gx816->regs.x--; - gx816->regs.y--; - if(gx816->regs.e == true || (gx816->regs.e == false && (gx816->regs.p & PF_X))) { - gx816->regs.x &= 0xff; - gx816->regs.y &= 0xff; - } + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->regs.a.w--; + dp = (gx816->op.aa.p.l << 16) | gx816->regs.y; + sp = (gx816->op.aa.p.h << 16) | gx816->regs.x; + gx816->op.r.b = gx816->op_read(OPMODE_LONG, sp); //4 [src data] + gx816->op_write(OPMODE_LONG, dp, gx816->op.r.b); //5 [dest data] + gx816->regs.x--; + gx816->regs.y--; + if(gx816->regs.e == true || (gx816->regs.p & PF_X)) { + gx816->regs.x &= 0xff; + gx816->regs.y &= 0xff; } if(gx816->regs.a.w == 0xffff) { g65816_incpc(3); } - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, sp); - snes_time->add_cpu_mcycles(1, dp); - snes_time->add_cpu_icycles(2); + snes_time->add_cpu_icycles(2); //6,7 [i/o] } -/*********** - *** brk *** - **********/ +/************************ + *** 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 g65816_op_brke(void) { - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(3); - snes_time->add_cpu_mcycles(2, 0x00ffe6); - g65816_incpc(2); - g65816_stackwrite(MEMSIZE_WORD, gx816->regs.pc); - g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.p); +void g65816_op_brk(void) { + snes_time->add_cpu_pcycles(2); //1,2 [op fetch] + gx816->stack_write(gx816->regs.pc >> 16); //3 [pbr] + gx816->stack_write(gx816->regs.pc >> 8); //4 [pch] + gx816->stack_write(gx816->regs.pc); //5 [pcl] + gx816->stack_write(gx816->regs.p); //6 [p] + gx816->op.aa.p.l = gx816->op_read(OPMODE_LONG, 0xffe6); //7 [aavl] + gx816->op.aa.p.h = gx816->op_read(OPMODE_LONG, 0xffe7); //8 [aavh] + gx816->regs.pc = gx816->op.aa.w; g65816_seti(); g65816_clrd(); - gx816->regs.pc = gx816->mem_read(MEMMODE_LONG, MEMSIZE_WORD, 0x00ffe6); } -void g65816_op_brkn(void) { - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(4); - snes_time->add_cpu_mcycles(2, 0x00ffe6); - g65816_incpc(2); - g65816_stackwrite(MEMSIZE_LONG, gx816->regs.pc); - g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.p); +/************************ + *** 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 g65816_op_cop(void) { + snes_time->add_cpu_pcycles(2); //1,2 [op fetch] + gx816->stack_write(gx816->regs.pc >> 16); //3 [pbr] + gx816->stack_write(gx816->regs.pc >> 8); //4 [pch] + gx816->stack_write(gx816->regs.pc); //5 [pcl] + gx816->stack_write(gx816->regs.p); //6 [p] + gx816->op.aa.p.l = gx816->op_read(OPMODE_LONG, 0xfff4); //7 [aavl] + gx816->op.aa.p.h = gx816->op_read(OPMODE_LONG, 0xfff5); //8 [aavh] + gx816->regs.pc = gx816->op.aa.w; g65816_seti(); g65816_clrd(); - gx816->regs.pc = gx816->mem_read(MEMMODE_LONG, MEMSIZE_WORD, 0x00ffe6); } -/*********** - *** cop *** - **********/ - -void g65816_op_cope(void) { - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(3); - snes_time->add_cpu_mcycles(2, 0x00fff4); - g65816_incpc(2); - g65816_stackwrite(MEMSIZE_WORD, gx816->regs.pc); - g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.p); - g65816_seti(); - g65816_clrd(); - gx816->regs.pc = gx816->mem_read(MEMMODE_LONG, MEMSIZE_WORD, 0x00fff4); -} - -void g65816_op_copn(void) { - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(4); - snes_time->add_cpu_mcycles(2, 0x00fff4); - g65816_incpc(2); - g65816_stackwrite(MEMSIZE_LONG, gx816->regs.pc); - g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.p); - g65816_seti(); - g65816_clrd(); - gx816->regs.pc = gx816->mem_read(MEMMODE_LONG, MEMSIZE_WORD, 0x00fff4); -} - -/*********** - *** stp *** - **********/ +/***************** + *** 0xdb: stp *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io + [3] pbr,pc+1 ; io +*/ void g65816_op_stp(void) { - g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(2); - dprintf("* stp not implemented"); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(2); //2,3 [i/o] + gx816->cpu_state = CPUSTATE_STP; } -/*********** - *** wai *** - **********/ +/***************** + *** 0xcb: wai *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io + [3] pbr,pc+1 ; io +*/ void g65816_op_wai(void) { byte i = 0; + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(2); //2,3 [i/o] if(gx816->nmi_enabled == true)i = 1; if((ppu.vcounter_enabled == true || ppu.hcounter_enabled == true) && !(gx816->regs.p & PF_I))i = 1; if(gx816->wai_interrupt_occurred == true || i == 0) { gx816->wai_interrupt_occurred = false; g65816_incpc(1); } - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(2); } -/*********** - *** xce *** - **********/ +/***************** + *** 0xfb: xce *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ void g65816_op_xce(void) { bool t = gx816->regs.e; - if(gx816->regs.p & PF_C)gx816->regs.e = true; - else gx816->regs.e = false; + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + if(gx816->regs.p & PF_C) { + gx816->regs.e = true; + } else { + gx816->regs.e = false; + } g65816_setm(); g65816_setx(); - if(t == true)g65816_setc(); - else g65816_clrc(); - - if(gx816->regs.e == true)gx816->regs.s = 0x0100 | (gx816->regs.s & 0xff); - + g65816_testc(t == true); + if(gx816->regs.e == true) { + gx816->regs.s = 0x0100 | (gx816->regs.s & 0xff); + gx816->regs.x &= 0xff; + gx816->regs.y &= 0xff; + } g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } -/*********** - *** nop *** - **********/ +/***************** + *** 0xea: nop *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ void g65816_op_nop(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } -/*********** - *** wdm *** - **********/ +/***************** + *** 0x42: wdm *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ void g65816_op_wdm(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] g65816_incpc(2); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } -/***************************** - *** clear/set bit opcodes *** - ****************************/ +/***************** + *** 0x18: clc *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ void g65816_op_clc(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] g65816_clrc(); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/***************** + *** 0xd8: cld *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ + void g65816_op_cld(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] g65816_clrd(); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/***************** + *** 0x58: cli *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ + void g65816_op_cli(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] g65816_clri(); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/***************** + *** 0xb8: clv *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ + void g65816_op_clv(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] g65816_clrv(); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/***************** + *** 0x38: sec *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ + void g65816_op_sec(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] g65816_setc(); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/***************** + *** 0xf8: sed *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ + void g65816_op_sed(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] g65816_setd(); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/***************** + *** 0x78: sei *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ + void g65816_op_sei(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] g65816_seti(); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/************************ + *** 0xc2: rep #const *** + ************************ +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; idl + [2a] pbr,pc+1 ; idl +*/ + void g65816_op_rep(void) { -g65816_prefetch(1); - gx816->regs.p &= ~arg; + gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //2a [i/o] + gx816->regs.p &= ~gx816->op.r.b; g65816_incpc(2); - snes_time->add_cpu_pcycles(3); - - if(gx816->regs.e == true)gx816->regs.p |= 0x30; + if(gx816->regs.e == true) { + gx816->regs.p |= 0x30; + } } +/************************ + *** 0xe2: sep #const *** + ************************ +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; idl + [2a] pbr,pc+1 ; idl +*/ + void g65816_op_sep(void) { -g65816_prefetch(1); - gx816->regs.p |= arg; - if(arg & 0x10) { + gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //2a [i/o] + gx816->regs.p |= gx816->op.r.b; + if(gx816->regs.p & 0x10) { gx816->regs.x &= 0xff; gx816->regs.y &= 0xff; } g65816_incpc(2); - snes_time->add_cpu_pcycles(3); } -/************************ - *** transfer opcodes *** - ***********************/ +/***************** + *** 0xaa: tax *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ void g65816_op_taxb(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.x = gx816->regs.a.b; g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_taxw(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.x = gx816->regs.a.w; g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/***************** + *** 0xa8: tay *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ + void g65816_op_tayb(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.y = gx816->regs.a.b; g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_tayw(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.y = gx816->regs.a.w; g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/***************** + *** 0x5b: tcd *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ + void g65816_op_tcd(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.d = gx816->regs.a.w; g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/***************** + *** 0x1b: tcs *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ + void g65816_op_tcse(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.s = 0x0100 | gx816->regs.a.b; g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_tcsn(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.s = gx816->regs.a.w; g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/***************** + *** 0x7b: tdc *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ + void g65816_tdc(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.a.w = gx816->regs.d; g65816_testn(gx816->regs.d & 0x8000); g65816_testz(gx816->regs.d == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/***************** + *** 0x3b: tsc *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ + void g65816_op_tsce(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.a.w = gx816->regs.s; g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_tscn(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.a.w = gx816->regs.s; g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/***************** + *** 0xba: tsx *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ + void g65816_op_tsxb(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.x = gx816->regs.s & 0xff; g65816_testn(gx816->regs.s & 0x80); g65816_testz((gx816->regs.s & 0xff) == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_tsxw(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.x = gx816->regs.s; g65816_testn(gx816->regs.s & 0x8000); g65816_testz(gx816->regs.s == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/***************** + *** 0x8a: txa *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ + void g65816_op_txab(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.a.b = gx816->regs.x; g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_txaw(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.a.w = gx816->regs.x; g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/***************** + *** 0x9a: txs *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ + void g65816_op_txsb(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.s = gx816->regs.x; g65816_testn(gx816->regs.x & 0x80); g65816_testz((gx816->regs.x & 0xff) == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_txsw(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.s = gx816->regs.x; g65816_testn(gx816->regs.x & 0x8000); g65816_testz(gx816->regs.x == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/***************** + *** 0x9b: txy *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ + void g65816_op_txyb(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.y = gx816->regs.x; g65816_testn(gx816->regs.x & 0x80); g65816_testz((gx816->regs.x & 0xff) == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_txyw(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.y = gx816->regs.x; g65816_testn(gx816->regs.x & 0x8000); g65816_testz(gx816->regs.x == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/***************** + *** 0x98: tya *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ + void g65816_op_tyab(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.a.b = gx816->regs.y; g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_tyaw(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.a.w = gx816->regs.y; g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/***************** + *** 0xbb: tyx *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ + void g65816_op_tyxb(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.x = gx816->regs.y; g65816_testn(gx816->regs.y & 0x80); g65816_testz((gx816->regs.y & 0xff) == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_tyxw(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] gx816->regs.x = gx816->regs.y; g65816_testn(gx816->regs.y & 0x8000); g65816_testz(gx816->regs.y == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } diff --git a/bsnes/cpu/g65816_ops_ora.cpp b/bsnes/cpu/g65816_ops_ora.cpp index f6aa2d75..7134d999 100644 --- a/bsnes/cpu/g65816_ops_ora.cpp +++ b/bsnes/cpu/g65816_ops_ora.cpp @@ -1,335 +1,504 @@ -#define g65816_flags_ora_b() g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0) -#define g65816_flags_ora_w() g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0) - -#define g65816_inst_ora_b() gx816->regs.a.b |= gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr) -#define g65816_inst_ora_w() gx816->regs.a.w |= gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr) - -void g65816_op_ora_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - g65816_inst_ora_b(); - g65816_flags_ora_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); +void g65816_flags_ora_b() { + g65816_testn(gx816->regs.a.b & 0x80); + g65816_testz(gx816->regs.a.b == 0); } -void g65816_op_ora_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - g65816_inst_ora_w(); - g65816_flags_ora_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); +void g65816_flags_ora_w() { + g65816_testn(gx816->regs.a.w & 0x8000); + g65816_testz(gx816->regs.a.w == 0); } -void g65816_op_ora_addrxb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - g65816_inst_ora_b(); - g65816_flags_ora_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_ora_addrxw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - g65816_inst_ora_w(); - g65816_flags_ora_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_ora_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - g65816_inst_ora_b(); - g65816_flags_ora_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_ora_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - g65816_inst_ora_w(); - g65816_flags_ora_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_ora_idpb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDP); - g65816_inst_ora_b(); - g65816_flags_ora_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_ora_idpw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDP); - g65816_inst_ora_w(); - g65816_flags_ora_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_ora_ildpb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDP); - g65816_inst_ora_b(); - g65816_flags_ora_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_ora_ildpw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDP); - g65816_inst_ora_w(); - g65816_flags_ora_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_ora_longb(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONG); - g65816_inst_ora_b(); - g65816_flags_ora_b(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(1, dest_addr); -} - -void g65816_op_ora_longw(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONG); - g65816_inst_ora_w(); - g65816_flags_ora_w(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(2, dest_addr); -} - -void g65816_op_ora_longxb(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONGX); - g65816_inst_ora_b(); - g65816_flags_ora_b(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(1, dest_addr); -} - -void g65816_op_ora_longxw(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONGX); - g65816_inst_ora_w(); - g65816_flags_ora_w(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(2, dest_addr); -} - -void g65816_op_ora_addryb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - g65816_inst_ora_b(); - g65816_flags_ora_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_ora_addryw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - g65816_inst_ora_w(); - g65816_flags_ora_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_ora_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - g65816_inst_ora_b(); - g65816_flags_ora_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_ora_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - g65816_inst_ora_w(); - g65816_flags_ora_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_ora_idpxb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPX); - g65816_inst_ora_b(); - g65816_flags_ora_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_ora_idpxw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPX); - g65816_inst_ora_w(); - g65816_flags_ora_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_ora_idpyb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPY); - g65816_inst_ora_b(); - g65816_flags_ora_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2 | TIMING_CONDITION4); -} - -void g65816_op_ora_idpyw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPY); - g65816_inst_ora_w(); - g65816_flags_ora_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2 | TIMING_CONDITION4); -} - -void g65816_op_ora_ildpyb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDPY); - g65816_inst_ora_b(); - g65816_flags_ora_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_ora_ildpyw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDPY); - g65816_inst_ora_w(); - g65816_flags_ora_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_ora_srb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_SR); - g65816_inst_ora_b(); - g65816_flags_ora_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(1); -} - -void g65816_op_ora_srw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_SR); - g65816_inst_ora_w(); - g65816_flags_ora_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(1); -} - -void g65816_op_ora_isryb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_ISRY); - g65816_inst_ora_b(); - g65816_flags_ora_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(2); -} - -void g65816_op_ora_isryw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_ISRY); - g65816_inst_ora_w(); - g65816_flags_ora_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2); -} +/************************ + *** 0x09: ora #const *** + ************************ +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; idl + [2a] pbr,pc+2 ; idh [1] +*/ void g65816_op_ora_constb(void) { -g65816_prefetch(1); - gx816->regs.a.b |= arg; + gx816->regs.a.b |= gx816->read_operand(1); //1,2 [op fetch] + g65816_flags_ora_b(); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); } void g65816_op_ora_constw(void) { -g65816_prefetch(2); - gx816->regs.a.w |= arg; + gx816->regs.a.w |= gx816->read_operand(2); //1,2,2a [op fetch] + g65816_flags_ora_w(); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); +} + +/********************** + *** 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 g65816_op_ora_addrb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->regs.a.b |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + + g65816_flags_ora_b(); + g65816_incpc(3); +} + +void g65816_op_ora_addrw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->regs.a.p.l |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->regs.a.p.h |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + + g65816_flags_ora_w(); + g65816_incpc(3); +} + +/************************ + *** 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 g65816_op_ora_addrxb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->regs.a.b |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read] + + g65816_flags_ora_b(); + g65816_incpc(3); +} + +void g65816_op_ora_addrxw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->regs.a.p.l |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read low] + gx816->regs.a.p.h |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //4a [read high] + + g65816_flags_ora_w(); + g65816_incpc(3); +} + +/******************** + *** 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 g65816_op_ora_dpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->regs.a.b |= gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + + g65816_flags_ora_b(); + g65816_incpc(2); +} + +void g65816_op_ora_dpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->regs.a.p.l |= gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->regs.a.p.h |= gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + + g65816_flags_ora_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_ora_idpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->regs.a.b |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read] + + g65816_flags_ora_b(); + g65816_incpc(2); +} + +void g65816_op_ora_idpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->regs.a.p.l |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read low] + gx816->regs.a.p.h |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //5a [read high] + + g65816_flags_ora_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_ora_ildpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->regs.a.b |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read] + + g65816_flags_ora_b(); + g65816_incpc(2); +} + +void g65816_op_ora_ildpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->regs.a.p.l |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read low] + gx816->regs.a.p.h |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //6a [read high] + + g65816_flags_ora_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_ora_longb(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->regs.a.b |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read] + + g65816_flags_ora_b(); + g65816_incpc(4); +} + +void g65816_op_ora_longw(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->regs.a.p.l |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read] + gx816->regs.a.p.h |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //5a [read] + + g65816_flags_ora_w(); + g65816_incpc(4); +} + +/************************ + *** 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 g65816_op_ora_longxb(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->regs.a.b |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read] + + g65816_flags_ora_b(); + g65816_incpc(4); +} + +void g65816_op_ora_longxw(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->regs.a.p.l |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read] + gx816->regs.a.p.h |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x + 1); //5a [read] + + g65816_flags_ora_w(); + g65816_incpc(4); +} + +/************************ + *** 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 g65816_op_ora_addryb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0] + gx816->regs.a.b |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read] + + g65816_flags_ora_b(); + g65816_incpc(3); +} + +void g65816_op_ora_addryw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0] + gx816->regs.a.p.l |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read low] + gx816->regs.a.p.h |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //4a [read high] + + g65816_flags_ora_w(); + g65816_incpc(3); +} + +/********************** + *** 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 g65816_op_ora_dpxb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.a.b |= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read] + + g65816_flags_ora_b(); + g65816_incpc(2); +} + +void g65816_op_ora_dpxw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.a.p.l |= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low] + gx816->regs.a.p.h |= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high] + + g65816_flags_ora_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_ora_idpxb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah] + gx816->regs.a.b |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read] + + g65816_flags_ora_b(); + g65816_incpc(2); +} + +void g65816_op_ora_idpxw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah] + gx816->regs.a.p.l |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read low] + gx816->regs.a.p.h |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //6 [read high] + + g65816_flags_ora_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_ora_idpyb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0] + gx816->regs.a.b |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read] + + g65816_flags_ora_b(); + g65816_incpc(2); +} + +void g65816_op_ora_idpyw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0] + gx816->regs.a.p.l |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read low] + gx816->regs.a.p.h |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //5a [read high] + + g65816_flags_ora_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_ora_ildpyb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->regs.a.b |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read] + + g65816_flags_ora_b(); + g65816_incpc(2); +} + +void g65816_op_ora_ildpyw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->regs.a.p.l |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read low] + gx816->regs.a.p.h |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y + 1); //6a [read high] + + g65816_flags_ora_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_ora_srb(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.a.b |= gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read] + + g65816_flags_ora_b(); + g65816_incpc(2); +} + +void g65816_op_ora_srw(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->regs.a.p.l |= gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read low] + gx816->regs.a.p.h |= gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //4a [read high] + + g65816_flags_ora_w(); + g65816_incpc(2); +} + +/************************** + *** 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 g65816_op_ora_isryb(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->regs.a.b |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read] + + g65816_flags_ora_b(); + g65816_incpc(2); +} + +void g65816_op_ora_isryw(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->regs.a.p.l |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read low] + gx816->regs.a.p.h |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //7a [read high] + + g65816_flags_ora_w(); + g65816_incpc(2); } diff --git a/bsnes/cpu/g65816_ops_pc.cpp b/bsnes/cpu/g65816_ops_pc.cpp index efa52755..f527fdab 100644 --- a/bsnes/cpu/g65816_ops_pc.cpp +++ b/bsnes/cpu/g65816_ops_pc.cpp @@ -1,223 +1,497 @@ -/*********** - *** jmp *** - **********/ +/********************** + *** 0x4c: jmp addr *** + ********************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; new pcl + [3] pbr,pc+2 ; new pch +*/ void g65816_op_jmp_addr(void) { -g65816_prefetch(2); - snes_time->add_cpu_pcycles(3); - gx816->regs.pc = (gx816->regs.pc & 0xff0000) | arg; + gx816->op.r.w = gx816->read_operand(2); //1-3 [op fetch] + + gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->op.r.w; } +/********************** + *** 0x5c: jml 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 g65816_op_jmp_long(void) { -g65816_prefetch(3); - snes_time->add_cpu_pcycles(4); - gx816->regs.pc = arg; + gx816->regs.pc = gx816->read_operand(3); //1-4 [op fetch] } +/************************ + *** 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 g65816_op_jmp_iaddr(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_IADDR_PC); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_ADDR, gx816->op.aa.w); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_ADDR, gx816->op.aa.w + 1); //5 [read high] + + gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->op.r.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 g65816_op_jmp_iaddrx(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_IADDRX_PC); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1); - gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_PBR, gx816->op.aa.w + gx816->regs.x); //5 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_PBR, gx816->op.aa.w + gx816->regs.x + 1); //6 [read high] + + gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->op.r.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 g65816_op_jmp_iladdr(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ILADDR_PC); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(3, dest_addr); - gx816->regs.pc = gx816->mem_read(MEMMODE_NONE, MEMSIZE_LONG, dest_addr); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_ADDR, gx816->op.aa.w); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_ADDR, gx816->op.aa.w + 1); //5 [read high] + gx816->op.r.p.b = gx816->op_read(OPMODE_ADDR, gx816->op.aa.w + 2); //6 [read bank] + + gx816->regs.pc = gx816->op.r.l; } -/*********** - *** jsr *** - **********/ - -//Note: The address pushed onto the stack is one byte less than the operand size. -//Upon returning, the address counter is incremented one more to move to the next -//instruction. The third/fourth cycles store the pc address on the stack, before -//the second operand byte is read in. +/********************** + *** 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 g65816_op_jsr_addr(void) { -g65816_prefetch(2); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(1); - g65816_stackwrite(MEMSIZE_WORD, gx816->regs.pc + 2); - gx816->regs.pc = (gx816->regs.pc & 0xff0000) | arg; + gx816->op.r.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->regs.pc += 2; + gx816->stack_write(gx816->regs.pc >> 8); //5 [write high] + gx816->stack_write(gx816->regs.pc); //6 [write low] + + gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->op.r.w; } +/********************** + *** 0x22: jsl 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 g65816_op_jsr_long(void) { -g65816_prefetch(3); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_scycles(3); - snes_time->add_cpu_icycles(1); - g65816_stackwrite(MEMSIZE_LONG, gx816->regs.pc + 3); - gx816->regs.pc = arg; + gx816->op.r.l = gx816->read_operand(3); //1-3,6 [op fetch] + gx816->regs.pc += 3; + gx816->stack_write(gx816->regs.pc >> 16); //4 [write bank] + snes_time->add_cpu_icycles(1); //5 [i/o] + gx816->stack_write(gx816->regs.pc >> 8); //7 [write high] + gx816->stack_write(gx816->regs.pc); //8 [write low] + + gx816->regs.pc = gx816->op.r.l; } +/************************** + *** 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 g65816_op_jsr_iaddrx(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_IADDRX_PC); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(1); - g65816_stackwrite(MEMSIZE_WORD, gx816->regs.pc + 2); - gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->mem_read(MEMMODE_IADDRX_PC, MEMSIZE_WORD, arg); - snes_time->add_cpu_pcycles(2); + gx816->op.aa.w = gx816->read_operand(2); //1,2,5 [op fetch] + gx816->regs.pc += 2; + gx816->stack_write(gx816->regs.pc >> 8); //3 [write high] + gx816->stack_write(gx816->regs.pc); //4 [write low] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_PBR, gx816->op.aa.w + gx816->regs.x); //7 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_PBR, gx816->op.aa.w + gx816->regs.x + 1); //8 [read high] + + gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->op.r.w; } -/*********** - *** ret *** - **********/ +/***************** + *** 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 g65816_op_rtie(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(3); - gx816->regs.p = g65816_stackread(MEMSIZE_BYTE); - gx816->regs.pc = (gx816->regs.pc & 0xff0000) | g65816_stackread(MEMSIZE_WORD); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(2); //2,3 [i/o] + gx816->regs.p = gx816->stack_read(); //4 [read p] + gx816->op.r.p.l = gx816->stack_read(); //5 [read pcl] + gx816->op.r.p.h = gx816->stack_read(); //6 [read pch] + + gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->op.r.w; if(gx816->regs.p & PF_X) { gx816->regs.x &= 0xff; gx816->regs.y &= 0xff; } gx816->regs.p &= ~ PF_I; - snes_time->add_cpu_icycles(2); } void g65816_op_rtin(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(4); - gx816->regs.p = g65816_stackread(MEMSIZE_BYTE); - gx816->regs.pc = g65816_stackread(MEMSIZE_LONG); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(2); //2,3 [i/o] + gx816->regs.p = gx816->stack_read(); //4 [read p] + gx816->op.r.p.l = gx816->stack_read(); //5 [read pcl] + gx816->op.r.p.h = gx816->stack_read(); //6 [read pch] + gx816->op.r.p.b = gx816->stack_read(); //7 [read pbr] + + gx816->regs.pc = gx816->op.r.l; if(gx816->regs.p & PF_X) { gx816->regs.x &= 0xff; gx816->regs.y &= 0xff; } - snes_time->add_cpu_icycles(2); + gx816->regs.p &= ~ PF_I; } +/***************** + *** 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 g65816_op_rts(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(3); - gx816->regs.pc = ((gx816->regs.pc & 0xff0000) | g65816_stackread(MEMSIZE_WORD)) + 1; + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(2); //2,3 [i/o] + gx816->op.r.p.l = gx816->stack_read(); //4 [read low] + gx816->op.r.p.h = gx816->stack_read(); //5 [read high] + snes_time->add_cpu_icycles(1); //6 [i/o] + + gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->op.r.w; + g65816_incpc(1); } +/***************** + *** 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 g65816_op_rtl(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(3); - snes_time->add_cpu_icycles(2); - gx816->regs.pc = g65816_stackread(MEMSIZE_LONG) + 1; + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(2); //2,3 [i/o] + gx816->op.r.p.l = gx816->stack_read(); //4 [read low] + gx816->op.r.p.h = gx816->stack_read(); //5 [read high] + gx816->op.r.p.b = gx816->stack_read(); //6 [read bank] + + gx816->regs.pc = gx816->op.r.l; + g65816_incpc(1); } -/*********** - *** bra *** - **********/ - -//Need to add condition (5) to cycle counts: if e=1, add one (i)cycle if page boundary crossed +/********************** + *** 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 g65816_op_bra(void) { -g65816_prefetch(1); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_icycles(1); - gx816->regs.pc += (signed char)(arg + 2); +word r; + gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //2a [i/o] + r = gx816->regs.pc + (signed char)gx816->op.r.b; + if(gx816->regs.e == true) { + if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) { + snes_time->add_cpu_icycles(1); //2b [i/o] + } + } + gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r; + g65816_incpc(2); } +/********************* + *** 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 g65816_op_brl(void) { -g65816_prefetch(2); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_icycles(1); - gx816->regs.pc += (signed short)(arg + 3); +word r; + gx816->op.r.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //4 [i/o] + r = gx816->regs.pc + (signed short)gx816->op.r.w; + gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r; + g65816_incpc(3); } +/********************** + *** 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 g65816_op_bcc(void) { -g65816_prefetch(1); - snes_time->add_cpu_pcycles(2); +word r; + gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch] if(!(gx816->regs.p & PF_C)) { - snes_time->add_cpu_icycles(1); - gx816->regs.pc += (signed char)(arg + 2); - } else { - g65816_incpc(2); + snes_time->add_cpu_icycles(1); //2a [i/o] + r = gx816->regs.pc + (signed char)gx816->op.r.b; + if(gx816->regs.e == true) { + if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) { + snes_time->add_cpu_icycles(1); //2b [i/o] + } + } + gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r; } + g65816_incpc(2); } +/********************** + *** 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 g65816_op_bcs(void) { -g65816_prefetch(1); - snes_time->add_cpu_pcycles(2); +word r; + gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch] if(gx816->regs.p & PF_C) { - snes_time->add_cpu_icycles(1); - gx816->regs.pc += (signed char)(arg + 2); - } else { - g65816_incpc(2); + snes_time->add_cpu_icycles(1); //2a [i/o] + r = gx816->regs.pc + (signed char)gx816->op.r.b; + if(gx816->regs.e == true) { + if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) { + snes_time->add_cpu_icycles(1); //2b [i/o] + } + } + gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r; } + g65816_incpc(2); } +/********************** + *** 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 g65816_op_bne(void) { -g65816_prefetch(1); - snes_time->add_cpu_pcycles(2); +word r; + gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch] if(!(gx816->regs.p & PF_Z)) { - snes_time->add_cpu_icycles(1); - gx816->regs.pc += (signed char)(arg + 2); - } else { - g65816_incpc(2); + snes_time->add_cpu_icycles(1); //2a [i/o] + r = gx816->regs.pc + (signed char)gx816->op.r.b; + if(gx816->regs.e == true) { + if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) { + snes_time->add_cpu_icycles(1); //2b [i/o] + } + } + gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r; } + g65816_incpc(2); } +/********************** + *** 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 g65816_op_beq(void) { -g65816_prefetch(1); - snes_time->add_cpu_pcycles(2); +word r; + gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch] if(gx816->regs.p & PF_Z) { - snes_time->add_cpu_icycles(1); - gx816->regs.pc += (signed char)(arg + 2); - } else { - g65816_incpc(2); + snes_time->add_cpu_icycles(1); //2a [i/o] + r = gx816->regs.pc + (signed char)gx816->op.r.b; + if(gx816->regs.e == true) { + if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) { + snes_time->add_cpu_icycles(1); //2b [i/o] + } + } + gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r; } + g65816_incpc(2); } +/********************** + *** 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 g65816_op_bpl(void) { -g65816_prefetch(1); - snes_time->add_cpu_pcycles(2); +word r; + gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch] if(!(gx816->regs.p & PF_N)) { - snes_time->add_cpu_icycles(1); - gx816->regs.pc += (signed char)(arg + 2); - } else { - g65816_incpc(2); + snes_time->add_cpu_icycles(1); //2a [i/o] + r = gx816->regs.pc + (signed char)gx816->op.r.b; + if(gx816->regs.e == true) { + if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) { + snes_time->add_cpu_icycles(1); //2b [i/o] + } + } + gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r; } + g65816_incpc(2); } +/********************** + *** 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 g65816_op_bmi(void) { -g65816_prefetch(1); - snes_time->add_cpu_pcycles(2); +word r; + gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch] if(gx816->regs.p & PF_N) { - snes_time->add_cpu_icycles(1); - gx816->regs.pc += (signed char)(arg + 2); - } else { - g65816_incpc(2); + snes_time->add_cpu_icycles(1); //2a [i/o] + r = gx816->regs.pc + (signed char)gx816->op.r.b; + if(gx816->regs.e == true) { + if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) { + snes_time->add_cpu_icycles(1); //2b [i/o] + } + } + gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r; } + g65816_incpc(2); } +/********************** + *** 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 g65816_op_bvc(void) { -g65816_prefetch(1); - snes_time->add_cpu_pcycles(2); +word r; + gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch] if(!(gx816->regs.p & PF_V)) { - snes_time->add_cpu_icycles(1); - gx816->regs.pc += (signed char)(arg + 2); - } else { - g65816_incpc(2); + snes_time->add_cpu_icycles(1); //2a [i/o] + r = gx816->regs.pc + (signed char)gx816->op.r.b; + if(gx816->regs.e == true) { + if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) { + snes_time->add_cpu_icycles(1); //2b [i/o] + } + } + gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r; } + g65816_incpc(2); } +/********************** + *** 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 g65816_op_bvs(void) { -g65816_prefetch(1); - snes_time->add_cpu_pcycles(2); +word r; + gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch] if(gx816->regs.p & PF_V) { - snes_time->add_cpu_icycles(1); - gx816->regs.pc += (signed char)(arg + 2); - } else { - g65816_incpc(2); + snes_time->add_cpu_icycles(1); //2a [i/o] + r = gx816->regs.pc + (signed char)gx816->op.r.b; + if(gx816->regs.e == true) { + if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) { + snes_time->add_cpu_icycles(1); //2b [i/o] + } + } + gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r; } + g65816_incpc(2); } diff --git a/bsnes/cpu/g65816_ops_sbc.cpp b/bsnes/cpu/g65816_ops_sbc.cpp index f5f3c076..1f467f3a 100644 --- a/bsnes/cpu/g65816_ops_sbc.cpp +++ b/bsnes/cpu/g65816_ops_sbc.cpp @@ -1,345 +1,526 @@ -#define bcd_sub_adjust_byte() \ - if(gx816->regs.p & PF_D) { \ - if(((r ) & 15) > 9)r -= 6; \ - if(((r >> 4) & 15) > 9)r -= 6 << 4; \ +void g65816_flags_sbc_b() { +int r = gx816->regs.a.b - gx816->op.r.b - !(gx816->regs.p & PF_C); +//bcd + if(gx816->regs.p & PF_D) { + if(((r ) & 15) > 9)r -= 6; + if(((r >> 4) & 15) > 9)r -= 6 << 4; } -#define bcd_sub_adjust_word() \ - if(gx816->regs.p & PF_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; \ - } - -#define g65816_if_sbc_b() \ -byte c = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); \ -int r = gx816->regs.a.b - c - !(gx816->regs.p & PF_C); \ - bcd_sub_adjust_byte() \ - g65816_testn(r & 0x80); \ - g65816_testv((gx816->regs.a.b ^ c) & (gx816->regs.a.b ^ (byte)r) & 0x80); \ - g65816_testz((byte)r == 0); \ - g65816_testc(r >= 0); \ - gx816->regs.a.b = r - -#define g65816_if_sbc_w() \ -word c = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); \ -int r = gx816->regs.a.w - c - !(gx816->regs.p & PF_C); \ - bcd_sub_adjust_word() \ - g65816_testn(r & 0x8000); \ - g65816_testv((gx816->regs.a.w ^ c) & (gx816->regs.a.w ^ (word)r) & 0x8000); \ - g65816_testz((word)r == 0); \ - g65816_testc(r >= 0); \ - gx816->regs.a.w = r - -void g65816_op_sbc_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - g65816_if_sbc_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); -} - -void g65816_op_sbc_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - g65816_if_sbc_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); -} - -void g65816_op_sbc_addrxb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - g65816_if_sbc_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_sbc_addrxw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - g65816_if_sbc_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_sbc_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - g65816_if_sbc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_sbc_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - g65816_if_sbc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_sbc_idpb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDP); - g65816_if_sbc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_sbc_idpw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDP); - g65816_if_sbc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_sbc_ildpb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDP); - g65816_if_sbc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_sbc_ildpw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDP); - g65816_if_sbc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_sbc_longb(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONG); - g65816_if_sbc_b(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(1, dest_addr); -} - -void g65816_op_sbc_longw(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONG); - g65816_if_sbc_w(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(2, dest_addr); -} - -void g65816_op_sbc_longxb(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONGX); - g65816_if_sbc_b(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(1, dest_addr); -} - -void g65816_op_sbc_longxw(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONGX); - g65816_if_sbc_w(); - g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(2, dest_addr); -} - -void g65816_op_sbc_addryb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - g65816_if_sbc_b(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_sbc_addryw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - g65816_if_sbc_w(); - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); -} - -void g65816_op_sbc_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - g65816_if_sbc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_sbc_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - g65816_if_sbc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_sbc_idpxb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPX); - g65816_if_sbc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_sbc_idpxw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPX); - g65816_if_sbc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); -} - -void g65816_op_sbc_idpyb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPY); - g65816_if_sbc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2 | TIMING_CONDITION4); -} - -void g65816_op_sbc_idpyw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPY); - g65816_if_sbc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2 | TIMING_CONDITION4); -} - -void g65816_op_sbc_ildpyb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDPY); - g65816_if_sbc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_sbc_ildpyw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDPY); - g65816_if_sbc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); -} - -void g65816_op_sbc_srb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_SR); - g65816_if_sbc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(1); -} - -void g65816_op_sbc_srw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_SR); - g65816_if_sbc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(1); -} - -void g65816_op_sbc_isryb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_ISRY); - g65816_if_sbc_b(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(2); -} - -void g65816_op_sbc_isryw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_ISRY); - g65816_if_sbc_w(); - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2); -} - -void g65816_op_sbc_constb(void) { -g65816_prefetch(1); -int r = gx816->regs.a.b - arg - !(gx816->regs.p & PF_C); - bcd_sub_adjust_byte() g65816_testn(r & 0x80); - g65816_testv((gx816->regs.a.b ^ arg) & (gx816->regs.a.b ^ (byte)r) & 0x80); + g65816_testv((gx816->regs.a.b ^ gx816->op.r.b) & (gx816->regs.a.b ^ (byte)r) & 0x80); g65816_testz((byte)r == 0); g65816_testc(r >= 0); gx816->regs.a.b = r; - g65816_incpc(2); - snes_time->add_cpu_pcycles(2); } -void g65816_op_sbc_constw(void) { -g65816_prefetch(2); -int r = gx816->regs.a.w - arg - !(gx816->regs.p & PF_C); - bcd_sub_adjust_word() +void g65816_flags_sbc_w() { +int r = gx816->regs.a.w - gx816->op.r.w - !(gx816->regs.p & PF_C); +//bcd + if(gx816->regs.p & PF_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; + } + g65816_testn(r & 0x8000); - g65816_testv((gx816->regs.a.w ^ arg) & (gx816->regs.a.w ^ (word)r) & 0x8000); + g65816_testv((gx816->regs.a.w ^ gx816->op.r.w) & (gx816->regs.a.w ^ (word)r) & 0x8000); g65816_testz((word)r == 0); g65816_testc(r >= 0); gx816->regs.a.w = r; - g65816_incpc(3); - snes_time->add_cpu_pcycles(3); +} + +/************************ + *** 0xe9: sbc #const *** + ************************ +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; idl + [2a] pbr,pc+2 ; idh [1] +*/ + +void g65816_op_sbc_constb(void) { + gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch] + + g65816_flags_sbc_b(); + g65816_incpc(2); +} + +void g65816_op_sbc_constw(void) { + gx816->op.r.w = gx816->read_operand(2); //1,2,2a [op fetch] + + g65816_flags_sbc_w(); + g65816_incpc(3); +} + +/********************** + *** 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 g65816_op_sbc_addrb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + + g65816_flags_sbc_b(); + g65816_incpc(3); +} + +void g65816_op_sbc_addrw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + + g65816_flags_sbc_w(); + g65816_incpc(3); +} + +/************************ + *** 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 g65816_op_sbc_addrxb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read] + + g65816_flags_sbc_b(); + g65816_incpc(3); +} + +void g65816_op_sbc_addrxw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //4a [read high] + + g65816_flags_sbc_w(); + g65816_incpc(3); +} + +/******************** + *** 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 g65816_op_sbc_dpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + + g65816_flags_sbc_b(); + g65816_incpc(2); +} + +void g65816_op_sbc_dpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + + g65816_flags_sbc_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_sbc_idpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read] + + g65816_flags_sbc_b(); + g65816_incpc(2); +} + +void g65816_op_sbc_idpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //5a [read high] + + g65816_flags_sbc_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_sbc_ildpb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read] + + g65816_flags_sbc_b(); + g65816_incpc(2); +} + +void g65816_op_sbc_ildpw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //6a [read high] + + g65816_flags_sbc_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_sbc_longb(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read] + + g65816_flags_sbc_b(); + g65816_incpc(4); +} + +void g65816_op_sbc_longw(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read] + gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //5a [read] + + g65816_flags_sbc_w(); + g65816_incpc(4); +} + +/************************ + *** 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 g65816_op_sbc_longxb(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read] + + g65816_flags_sbc_b(); + g65816_incpc(4); +} + +void g65816_op_sbc_longxw(void) { + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read] + gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x + 1); //5a [read] + + g65816_flags_sbc_w(); + g65816_incpc(4); +} + +/************************ + *** 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 g65816_op_sbc_addryb(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read] + + g65816_flags_sbc_b(); + g65816_incpc(3); +} + +void g65816_op_sbc_addryw(void) { + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //4a [read high] + + g65816_flags_sbc_w(); + g65816_incpc(3); +} + +/********************** + *** 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 g65816_op_sbc_dpxb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read] + + g65816_flags_sbc_b(); + g65816_incpc(2); +} + +void g65816_op_sbc_dpxw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high] + + g65816_flags_sbc_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_sbc_idpxb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read] + + g65816_flags_sbc_b(); + g65816_incpc(2); +} + +void g65816_op_sbc_idpxw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //6 [read high] + + g65816_flags_sbc_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_sbc_idpyb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read] + + g65816_flags_sbc_b(); + g65816_incpc(2); +} + +void g65816_op_sbc_idpyw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //5a [read high] + + g65816_flags_sbc_w(); + g65816_incpc(2); +} + +/************************ + *** 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 g65816_op_sbc_ildpyb(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read] + + g65816_flags_sbc_b(); + g65816_incpc(2); +} + +void g65816_op_sbc_ildpyw(void) { + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y + 1); //6a [read high] + + g65816_flags_sbc_w(); + g65816_incpc(2); +} + +/********************** + *** 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 g65816_op_sbc_srb(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read] + + g65816_flags_sbc_b(); + g65816_incpc(2); +} + +void g65816_op_sbc_srw(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //4a [read high] + + g65816_flags_sbc_w(); + g65816_incpc(2); +} + +/************************** + *** 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 g65816_op_sbc_isryb(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read] + + g65816_flags_sbc_b(); + g65816_incpc(2); +} + +void g65816_op_sbc_isryw(void) { + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //7a [read high] + + g65816_flags_sbc_w(); + g65816_incpc(2); } diff --git a/bsnes/cpu/g65816_ops_shift.cpp b/bsnes/cpu/g65816_ops_shift.cpp index 2e61d5f8..a71f06ec 100644 --- a/bsnes/cpu/g65816_ops_shift.cpp +++ b/bsnes/cpu/g65816_ops_shift.cpp @@ -1,595 +1,873 @@ -/********** -*** asl *** -**********/ +/***************** + *** 0x0a: asl *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ void g65816_op_aslb(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + g65816_testc(gx816->regs.a.b & 0x80); gx816->regs.a.b <<= 1; g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_aslw(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + g65816_testc(gx816->regs.a.w & 0x8000); gx816->regs.a.w <<= 1; g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/********************** + *** 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 g65816_op_asl_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testc(m & 0x80); - m <<= 1; - g65816_testn(m & 0x80); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testc(gx816->op.r.b & 0x80); + gx816->op.r.b <<= 1; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.b); //6 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1); } void g65816_op_asl_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testc(m & 0x8000); - m <<= 1; - g65816_testn(m & 0x8000); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testc(gx816->op.r.w & 0x8000); + gx816->op.r.w <<= 1; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->op.r.p.h); //6a [write high] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.p.l); //6 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(1); } +/************************ + *** 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 g65816_op_asl_addrxb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testc(m & 0x80); - m <<= 1; - g65816_testn(m & 0x80); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read] + snes_time->add_cpu_icycles(1); //6 [i/o] + g65816_testc(gx816->op.r.b & 0x80); + gx816->op.r.b <<= 1; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.b); //7 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2); } void g65816_op_asl_addrxw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testc(m & 0x8000); - m <<= 1; - g65816_testn(m & 0x8000); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //5a [read high] + snes_time->add_cpu_icycles(1); //6 [i/o] + g65816_testc(gx816->op.r.w & 0x8000); + gx816->op.r.w <<= 1; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1, gx816->op.r.p.h); //7a [write high] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.p.l); //7 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(2); } +/******************** + *** 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 g65816_op_asl_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testc(m & 0x80); - m <<= 1; - g65816_testn(m & 0x80); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + snes_time->add_cpu_icycles(1); //4 [i/o] + g65816_testc(gx816->op.r.b & 0x80); + gx816->op.r.b <<= 1; + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.b); //5 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_REGD); } void g65816_op_asl_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testc(m & 0x8000); - m <<= 1; - g65816_testn(m & 0x8000); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + snes_time->add_cpu_icycles(1); //4 [i/o] + g65816_testc(gx816->op.r.w & 0x8000); + gx816->op.r.w <<= 1; + gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->op.r.p.h); //5a [write high] + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.p.l); //5 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_REGD); } +/********************** + *** 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 g65816_op_asl_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testc(m & 0x80); - m <<= 1; - g65816_testn(m & 0x80); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testc(gx816->op.r.b & 0x80); + gx816->op.r.b <<= 1; + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.b); //6 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2, TIMING_REGD); } void g65816_op_asl_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testc(m & 0x8000); - m <<= 1; - g65816_testn(m & 0x8000); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testc(gx816->op.r.w & 0x8000); + gx816->op.r.w <<= 1; + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1, gx816->op.r.p.h); //6a [write high] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.p.l); //6 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(2, TIMING_REGD); } -/********** -*** lsr *** -**********/ +/***************** + *** 0x4a: lsr *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ void g65816_op_lsrb(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + g65816_testc(gx816->regs.a.b & 0x01); gx816->regs.a.b >>= 1; g65816_clrn(); g65816_testz(gx816->regs.a.b == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_lsrw(void) { + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + g65816_testc(gx816->regs.a.w & 0x0001); gx816->regs.a.w >>= 1; g65816_clrn(); g65816_testz(gx816->regs.a.w == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } + +/********************** + *** 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 g65816_op_lsr_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testc(m & 0x01); - m >>= 1; + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testc(gx816->op.r.b & 0x01); + gx816->op.r.b >>= 1; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.b); //6 [write] + g65816_clrn(); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1); } void g65816_op_lsr_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testc(m & 0x0001); - m >>= 1; + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testc(gx816->op.r.w & 0x0001); + gx816->op.r.w >>= 1; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->op.r.p.h); //6a [write high] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.p.l); //6 [write low] + g65816_clrn(); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(1); } +/************************ + *** 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 g65816_op_lsr_addrxb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testc(m & 0x01); - m >>= 1; + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read] + snes_time->add_cpu_icycles(1); //6 [i/o] + g65816_testc(gx816->op.r.b & 0x01); + gx816->op.r.b >>= 1; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.b); //7 [write] + g65816_clrn(); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2); } void g65816_op_lsr_addrxw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testc(m & 0x0001); - m >>= 1; + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //5a [read high] + snes_time->add_cpu_icycles(1); //6 [i/o] + g65816_testc(gx816->op.r.w & 0x0001); + gx816->op.r.w >>= 1; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1, gx816->op.r.p.h); //7a [write high] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.p.l); //7 [write low] + g65816_clrn(); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(2); } +/******************** + *** 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 g65816_op_lsr_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testc(m & 0x01); - m >>= 1; + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + snes_time->add_cpu_icycles(1); //4 [i/o] + g65816_testc(gx816->op.r.b & 0x01); + gx816->op.r.b >>= 1; + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.b); //5 [write] + g65816_clrn(); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_REGD); } void g65816_op_lsr_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testc(m & 0x0001); - m >>= 1; + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + snes_time->add_cpu_icycles(1); //4 [i/o] + g65816_testc(gx816->op.r.w & 0x0001); + gx816->op.r.w >>= 1; + gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->op.r.p.h); //5a [write high] + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.p.l); //5 [write low] + g65816_clrn(); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_REGD); } +/********************** + *** 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 g65816_op_lsr_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testc(m & 0x01); - m >>= 1; + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testc(gx816->op.r.b & 0x80); + gx816->op.r.b >>= 1; + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.b); //6 [write] + g65816_clrn(); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2, TIMING_REGD); } void g65816_op_lsr_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testc(m & 0x0001); - m >>= 1; + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testc(gx816->op.r.w & 0x001); + gx816->op.r.w >>= 1; + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1, gx816->op.r.p.h); //6a [write high] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.p.l); //6 [write low] + g65816_clrn(); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(2, TIMING_REGD); } -/********** -*** rol *** -**********/ +/***************** + *** 0x2a: rol *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ void g65816_op_rolb(void) { -byte c = gx816->regs.p & PF_C; +byte c = (gx816->regs.p & PF_C)?0x01:0x00; + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + g65816_testc(gx816->regs.a.b & 0x80); - gx816->regs.a.b = (gx816->regs.a.b << 1) | c; + gx816->regs.a.b <<= 1; + gx816->regs.a.b |= c; g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_rolw(void) { -byte c = gx816->regs.p & PF_C; +word c = (gx816->regs.p & PF_C)?0x0001:0x0000; + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + g65816_testc(gx816->regs.a.w & 0x8000); - gx816->regs.a.w = (gx816->regs.a.w << 1) | c; + gx816->regs.a.w <<= 1; + gx816->regs.a.w |= c; g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } +/********************** + *** 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 g65816_op_rol_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -byte c = gx816->regs.p & PF_C; -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testc(m & 0x80); - m = (m << 1) | c; - g65816_testn(m & 0x80); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); +byte c = (gx816->regs.p & PF_C)?0x01:0x00; + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testc(gx816->op.r.b & 0x80); + gx816->op.r.b <<= 1; + gx816->op.r.b |= c; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.b); //6 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1); } void g65816_op_rol_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); -byte c = gx816->regs.p & PF_C; -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testc(m & 0x8000); - m = (m << 1) | c; - g65816_testn(m & 0x8000); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); +word c = (gx816->regs.p & PF_C)?0x0001:0x0000; + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testc(gx816->op.r.w & 0x8000); + gx816->op.r.w <<= 1; + gx816->op.r.w |= c; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->op.r.p.h); //6a [write high] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.p.l); //6 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(1); } +/************************ + *** 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 g65816_op_rol_addrxb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); -byte c = gx816->regs.p & PF_C; -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testc(m & 0x80); - m = (m << 1) | c; - g65816_testn(m & 0x80); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); +byte c = (gx816->regs.p & PF_C)?0x01:0x00; + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read] + snes_time->add_cpu_icycles(1); //6 [i/o] + g65816_testc(gx816->op.r.b & 0x80); + gx816->op.r.b <<= 1; + gx816->op.r.b |= c; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.b); //7 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2); } void g65816_op_rol_addrxw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); -byte c = gx816->regs.p & PF_C; -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testc(m & 0x8000); - m = (m << 1) | c; - g65816_testn(m & 0x8000); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); +word c = (gx816->regs.p & PF_C)?0x0001:0x0000; + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //5a [read high] + snes_time->add_cpu_icycles(1); //6 [i/o] + g65816_testc(gx816->op.r.w & 0x8000); + gx816->op.r.w <<= 1; + gx816->op.r.w |= c; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1, gx816->op.r.p.h); //7a [write high] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.p.l); //7 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(2); } +/******************** + *** 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 g65816_op_rol_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -byte c = gx816->regs.p & PF_C; -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testc(m & 0x80); - m = (m << 1) | c; - g65816_testn(m & 0x80); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); +byte c = (gx816->regs.p & PF_C)?0x01:0x00; + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + snes_time->add_cpu_icycles(1); //4 [i/o] + g65816_testc(gx816->op.r.b & 0x80); + gx816->op.r.b <<= 1; + gx816->op.r.b |= c; + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.b); //5 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_REGD); } void g65816_op_rol_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); -byte c = gx816->regs.p & PF_C; -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testc(m & 0x8000); - m = (m << 1) | c; - g65816_testn(m & 0x8000); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); +word c = (gx816->regs.p & PF_C)?0x0001:0x0000; + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + snes_time->add_cpu_icycles(1); //4 [i/o] + g65816_testc(gx816->op.r.w & 0x8000); + gx816->op.r.w <<= 1; + gx816->op.r.w |= c; + gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->op.r.p.h); //5a [write high] + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.p.l); //5 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_REGD); } +/********************** + *** 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 g65816_op_rol_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); -byte c = gx816->regs.p & PF_C; -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testc(m & 0x80); - m = (m << 1) | c; - g65816_testn(m & 0x80); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); +byte c = (gx816->regs.p & PF_C)?0x01:0x00; + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testc(gx816->op.r.b & 0x80); + gx816->op.r.b <<= 1; + gx816->op.r.b |= c; + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.b); //6 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2, TIMING_REGD); } void g65816_op_rol_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); -byte c = gx816->regs.p & PF_C; -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, arg); - g65816_testc(m & 0x8000); - m = (m << 1) | c; - g65816_testn(m & 0x8000); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, arg, m); +word c = (gx816->regs.p & PF_C)?0x0001:0x0000; + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testc(gx816->op.r.w & 0x8000); + gx816->op.r.w <<= 1; + gx816->op.r.w |= c; + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1, gx816->op.r.p.h); //6a [write high] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.p.l); //6 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(2, TIMING_REGD); } -/********** -*** ror *** -**********/ +/***************** + *** 0x6a: ror *** + ***************** +cycles: + [1] pbr,pc ; opcode + [2] pbr,pc+1 ; io +*/ void g65816_op_rorb(void) { byte c = (gx816->regs.p & PF_C)?0x80:0x00; + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + g65816_testc(gx816->regs.a.b & 0x01); - gx816->regs.a.b = (gx816->regs.a.b >> 1) | c; + gx816->regs.a.b >>= 1; + gx816->regs.a.b |= c; g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_rorw(void) { word c = (gx816->regs.p & PF_C)?0x8000:0x0000; + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + g65816_testc(gx816->regs.a.w & 0x0001); - gx816->regs.a.w = (gx816->regs.a.w >> 1) | c; + gx816->regs.a.w >>= 1; + gx816->regs.a.w |= c; g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0); g65816_incpc(1); - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_icycles(1); } + +/********************** + *** 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 g65816_op_ror_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); byte c = (gx816->regs.p & PF_C)?0x80:0x00; -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testc(m & 0x01); - m = (m >> 1) | c; - g65816_testn(m & 0x80); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testc(gx816->op.r.b & 0x01); + gx816->op.r.b >>= 1; + gx816->op.r.b |= c; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.b); //6 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1); } void g65816_op_ror_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); word c = (gx816->regs.p & PF_C)?0x8000:0x0000; -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testc(m & 0x0001); - m = (m >> 1) | c; - g65816_testn(m & 0x8000); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testc(gx816->op.r.w & 0x0001); + gx816->op.r.w >>= 1; + gx816->op.r.w |= c; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->op.r.p.h); //6a [write high] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.p.l); //6 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(1); } +/************************ + *** 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 g65816_op_ror_addrxb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); byte c = (gx816->regs.p & PF_C)?0x80:0x00; -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testc(m & 0x01); - m = (m >> 1) | c; - g65816_testn(m & 0x80); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read] + snes_time->add_cpu_icycles(1); //6 [i/o] + g65816_testc(gx816->op.r.b & 0x01); + gx816->op.r.b >>= 1; + gx816->op.r.b |= c; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.b); //7 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2); } void g65816_op_ror_addrxw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); word c = (gx816->regs.p & PF_C)?0x8000:0x0000; -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testc(m & 0x0001); - m = (m >> 1) | c; - g65816_testn(m & 0x8000); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //4 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //5a [read high] + snes_time->add_cpu_icycles(1); //6 [i/o] + g65816_testc(gx816->op.r.w & 0x0001); + gx816->op.r.w >>= 1; + gx816->op.r.w |= c; + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1, gx816->op.r.p.h); //7a [write high] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.p.l); //7 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(2); } +/******************** + *** 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 g65816_op_ror_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); byte c = (gx816->regs.p & PF_C)?0x80:0x00; -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testc(m & 0x01); - m = (m >> 1) | c; - g65816_testn(m & 0x80); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read] + snes_time->add_cpu_icycles(1); //4 [i/o] + g65816_testc(gx816->op.r.b & 0x01); + gx816->op.r.b >>= 1; + gx816->op.r.b |= c; + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.b); //5 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_REGD); } void g65816_op_ror_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); word c = (gx816->regs.p & PF_C)?0x8000:0x0000; -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testc(m & 0x0001); - m = (m >> 1) | c; - g65816_testn(m & 0x8000); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high] + snes_time->add_cpu_icycles(1); //4 [i/o] + g65816_testc(gx816->op.r.w & 0x0001); + gx816->op.r.w >>= 1; + gx816->op.r.w |= c; + gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->op.r.p.h); //5a [write high] + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.p.l); //5 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_REGD); } +/********************** + *** 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 g65816_op_ror_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); byte c = (gx816->regs.p & PF_C)?0x80:0x00; -byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); - g65816_testc(m & 0x01); - m = (m >> 1) | c; - g65816_testn(m & 0x80); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testc(gx816->op.r.b & 0x80); + gx816->op.r.b >>= 1; + gx816->op.r.b |= c; + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.b); //6 [write] + + g65816_testn(gx816->op.r.b & 0x80); + g65816_testz(gx816->op.r.b == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2, TIMING_REGD); } void g65816_op_ror_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); word c = (gx816->regs.p & PF_C)?0x8000:0x0000; -word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); - g65816_testc(m & 0x0001); - m = (m >> 1) | c; - g65816_testn(m & 0x8000); - g65816_testz(m == 0); - gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); + gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low] + gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high] + snes_time->add_cpu_icycles(1); //5 [i/o] + g65816_testc(gx816->op.r.w & 0x001); + gx816->op.r.w >>= 1; + gx816->op.r.w |= c; + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1, gx816->op.r.p.h); //6a [write high] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.p.l); //6 [write low] + + g65816_testn(gx816->op.r.w & 0x8000); + g65816_testz(gx816->op.r.w == 0); g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(4, dest_addr); - snes_time->add_cpu_icycles(2, TIMING_REGD); } diff --git a/bsnes/cpu/g65816_ops_sta.cpp b/bsnes/cpu/g65816_ops_sta.cpp index 5f2069cc..96b7846b 100644 --- a/bsnes/cpu/g65816_ops_sta.cpp +++ b/bsnes/cpu/g65816_ops_sta.cpp @@ -1,288 +1,443 @@ -#define g65816_sta_data_b() gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, gx816->regs.a.b) -#define g65816_sta_data_w() gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, gx816->regs.a.w) +/********************** + *** 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 g65816_op_sta_addrb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - g65816_sta_data_b(); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.a.b); //4 [write] + g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); } void g65816_op_sta_addrw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDR); - g65816_sta_data_w(); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.a.p.l); //4 [write low] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->regs.a.p.h); //4a [write high] + g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); } +/************************ + *** 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 g65816_op_sta_addrxb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - g65816_sta_data_b(); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //3a [write i/o] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->regs.a.b); //4 [write] + g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); } void g65816_op_sta_addrxw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRX); - g65816_sta_data_w(); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //3a [write i/o] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->regs.a.p.l); //4 [write low] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1, gx816->regs.a.p.h); //4a [write high] + g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); } +/******************** + *** 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 g65816_op_sta_dpb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - g65816_sta_data_b(); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->regs.a.b); //3 [write] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } void g65816_op_sta_dpw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - g65816_sta_data_w(); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->regs.a.p.l); //3 [write low] + gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->regs.a.p.h); //3a [write high] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } +/********************** + *** 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 g65816_op_sta_idpb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDP); - g65816_sta_data_b(); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.a.b); //5 [write] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } void g65816_op_sta_idpw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDP); - g65816_sta_data_w(); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.a.p.l); //5 [write low] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->regs.a.p.h); //5a [write high] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } +/********************** + *** 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 g65816_op_sta_ildpb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDP); - g65816_sta_data_b(); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->op_write(OPMODE_LONG, gx816->op.aa.l, gx816->regs.a.b); //6 [write] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } void g65816_op_sta_ildpw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDP); - g65816_sta_data_w(); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->op_write(OPMODE_LONG, gx816->op.aa.l, gx816->regs.a.p.l); //6 [write low] + gx816->op_write(OPMODE_LONG, gx816->op.aa.l + 1, gx816->regs.a.p.h); //6a [write high] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } +/********************** + *** 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 g65816_op_sta_longb(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONG); - g65816_sta_data_b(); + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->op_write(OPMODE_LONG, gx816->op.aa.l, gx816->regs.a.b); //5 [write] + g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(1, dest_addr); } void g65816_op_sta_longw(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONG); - g65816_sta_data_w(); + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->op_write(OPMODE_LONG, gx816->op.aa.l, gx816->regs.a.p.l); //5 [write] + gx816->op_write(OPMODE_LONG, gx816->op.aa.l + 1, gx816->regs.a.p.h); //5a [write] + g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(2, dest_addr); } +/************************ + *** 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 g65816_op_sta_longxb(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONGX); - g65816_sta_data_b(); + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->op_write(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x, gx816->regs.a.b); //5 [write] + g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(1, dest_addr); } void g65816_op_sta_longxw(void) { -g65816_prefetch(3); -g65816_getaddr(MEMMODE_LONGX); - g65816_sta_data_w(); + gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch] + gx816->op_write(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x, gx816->regs.a.p.l); //5 [write] + gx816->op_write(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x + 1, gx816->regs.a.p.h); //5a [write] + g65816_incpc(4); - snes_time->add_cpu_pcycles(4); - snes_time->add_cpu_mcycles(2, dest_addr); } +/************************ + *** 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 g65816_op_sta_addryb(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - g65816_sta_data_b(); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //3a [write i/o] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y, gx816->regs.a.b); //4 [write] + g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); } void g65816_op_sta_addryw(void) { -g65816_prefetch(2); -g65816_getaddr(MEMMODE_ADDRY); - g65816_sta_data_w(); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //3a [write i/o] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y, gx816->regs.a.p.l); //4 [write low] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1, gx816->regs.a.p.h); //4a [write high] + g65816_incpc(3); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION4); } +/********************** + *** 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 g65816_op_sta_dpxb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - g65816_sta_data_b(); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->regs.a.b); //4 [write] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); } void g65816_op_sta_dpxw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DPX); - g65816_sta_data_w(); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->regs.a.p.l); //4 [write low] + gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1, gx816->regs.a.p.h); //4a [write high] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); } +/************************ + *** 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 g65816_op_sta_idpxb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPX); - g65816_sta_data_b(); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.a.b); //6 [write] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); } void g65816_op_sta_idpxw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPX); - g65816_sta_data_w(); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.a.p.l); //6 [write low] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->regs.a.p.h); //6 [write high] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(1, TIMING_CONDITION2); } +/************************ + *** 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 g65816_op_sta_idpyb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPY); - g65816_sta_data_b(); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + snes_time->add_cpu_icycles(1); //4a [write i/o] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y, gx816->regs.a.b); //5 [write] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2 | TIMING_CONDITION4); } void g65816_op_sta_idpyw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_IDPY); - g65816_sta_data_w(); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + snes_time->add_cpu_icycles(1); //4a [write i/o] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y, gx816->regs.a.p.l); //5 [write low] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1, gx816->regs.a.p.h); //5a [write high] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2 | TIMING_CONDITION4); } +/************************ + *** 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 g65816_op_sta_ildpyb(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDPY); - g65816_sta_data_b(); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->op_write(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y, gx816->regs.a.b); //6 [write] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } void g65816_op_sta_ildpyw(void) { -g65816_prefetch(1); -g65816_getiaddr(MEMMODE_ILDPY); - g65816_sta_data_w(); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [dl!=0] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah] + gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab] + gx816->op_write(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y, gx816->regs.a.p.l); //6 [write low] + gx816->op_write(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y + 1, gx816->regs.a.p.h); //6a [write high] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(3, base_addr); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(0, TIMING_CONDITION2); } +/********************** + *** 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 g65816_op_sta_srb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_SR); - g65816_sta_data_b(); + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op_write(OPMODE_SP, gx816->op.sp, gx816->regs.a.b); //4 [write] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(1); } void g65816_op_sta_srw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_SR); - g65816_sta_data_w(); + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op_write(OPMODE_SP, gx816->op.sp, gx816->regs.a.p.l); //4 [write low] + gx816->op_write(OPMODE_SP, gx816->op.sp + 1, gx816->regs.a.p.h); //4a [write high] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(1); } +/************************** + *** 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 g65816_op_sta_isryb(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_ISRY); - g65816_sta_data_b(); + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y, gx816->regs.a.b); //7 [write] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_mcycles(1, dest_addr); - snes_time->add_cpu_icycles(2); } void g65816_op_sta_isryw(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_ISRY); - g65816_sta_data_w(); + gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch] + snes_time->add_cpu_icycles(1); //3 [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah] + snes_time->add_cpu_icycles(1); //6 [i/o] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y, gx816->regs.a.p.l); //7 [write low] + gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1, gx816->regs.a.p.h); //7a [write high] + g65816_incpc(2); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_icycles(2); } diff --git a/bsnes/cpu/g65816_ops_stack.cpp b/bsnes/cpu/g65816_ops_stack.cpp index a126db5c..efa412a0 100644 --- a/bsnes/cpu/g65816_ops_stack.cpp +++ b/bsnes/cpu/g65816_ops_stack.cpp @@ -1,243 +1,357 @@ -ulong g65816_stackread(byte size) { -ulong r = 0; - if(size == MEMSIZE_BYTE) { - gx816->regs.s++; - r = gx816->mem_read(MEMMODE_LONG, MEMSIZE_BYTE, gx816->regs.s); - } else if(size == MEMSIZE_WORD) { - gx816->regs.s++; - r = gx816->mem_read(MEMMODE_LONG, MEMSIZE_BYTE, gx816->regs.s); - gx816->regs.s++; - r |= gx816->mem_read(MEMMODE_LONG, MEMSIZE_BYTE, gx816->regs.s) << 8; - } else if(size == MEMSIZE_LONG) { - gx816->regs.s++; - r = gx816->mem_read(MEMMODE_LONG, MEMSIZE_BYTE, gx816->regs.s); - gx816->regs.s++; - r |= gx816->mem_read(MEMMODE_LONG, MEMSIZE_BYTE, gx816->regs.s) << 8; - gx816->regs.s++; - r |= gx816->mem_read(MEMMODE_LONG, MEMSIZE_BYTE, gx816->regs.s) << 16; - } - if(gx816->regs.e == true) { - gx816->regs.s = 0x0100 | (gx816->regs.s & 0xff); - } - return r; -} - -void g65816_stackwrite(byte size, ulong value) { - if(size == MEMSIZE_BYTE) { - gx816->mem_write(MEMMODE_LONG, MEMSIZE_BYTE, gx816->regs.s, value); - gx816->regs.s--; - } else if(size == MEMSIZE_WORD) { - gx816->mem_write(MEMMODE_LONG, MEMSIZE_BYTE, gx816->regs.s, value >> 8); - gx816->regs.s--; - gx816->mem_write(MEMMODE_LONG, MEMSIZE_BYTE, gx816->regs.s, value); - gx816->regs.s--; - } else if(size == MEMSIZE_LONG) { - gx816->mem_write(MEMMODE_LONG, MEMSIZE_BYTE, gx816->regs.s, value >> 16); - gx816->regs.s--; - gx816->mem_write(MEMMODE_LONG, MEMSIZE_BYTE, gx816->regs.s, value >> 8); - gx816->regs.s--; - gx816->mem_write(MEMMODE_LONG, MEMSIZE_BYTE, gx816->regs.s, value); - gx816->regs.s--; - } - if(gx816->regs.e == true) { - gx816->regs.s = 0x0100 | (gx816->regs.s & 0xff); - } -} +/***************** + *** 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 g65816_op_phab(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(1); - g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.a.b); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + gx816->stack_write(gx816->regs.a.b); //3 [reg low] g65816_incpc(1); } void g65816_op_phaw(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(1); - g65816_stackwrite(MEMSIZE_WORD, gx816->regs.a.w); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + gx816->stack_write(gx816->regs.a.p.h); //3a [reg high] + gx816->stack_write(gx816->regs.a.p.l); //3 [reg low] g65816_incpc(1); } +/***************** + *** 0x8b: phb *** + ***************** +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; io + [3a] 0,s ; reg high [1] + [3 ] 0,s-1 ; reg low +*/ + void g65816_op_phb(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(1); - g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.db); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + gx816->stack_write(gx816->regs.db); //3 [reg low] g65816_incpc(1); } +/***************** + *** 0x0b: phd *** + ***************** +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; io + [3a] 0,s ; reg high [1] + [3 ] 0,s-1 ; reg low +*/ + void g65816_op_phd(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(1); - g65816_stackwrite(MEMSIZE_WORD, gx816->regs.d); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + gx816->stack_write(gx816->regs.d >> 8); //3a [reg high] + gx816->stack_write(gx816->regs.d); //3 [reg low] g65816_incpc(1); } +/***************** + *** 0x4b: phk *** + ***************** +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; io + [3a] 0,s ; reg high [1] + [3 ] 0,s-1 ; reg low +*/ + void g65816_op_phk(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(1); - g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.pc >> 16); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + gx816->stack_write(gx816->regs.pc >> 16); //3 [reg low] g65816_incpc(1); } +/***************** + *** 0x08: php *** + ***************** +cycles: + [1 ] pbr,pc ; opcode + [2 ] pbr,pc+1 ; io + [3a] 0,s ; reg high [1] + [3 ] 0,s-1 ; reg low +*/ + void g65816_op_php(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(1); - g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.p); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + gx816->stack_write(gx816->regs.p); //3 [reg low] g65816_incpc(1); } +/***************** + *** 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 g65816_op_phxb(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(1); - g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.x); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + gx816->stack_write(gx816->regs.x); //3 [reg low] g65816_incpc(1); } void g65816_op_phxw(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(1); - g65816_stackwrite(MEMSIZE_WORD, gx816->regs.x); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + gx816->stack_write(gx816->regs.x >> 8); //3a [reg high] + gx816->stack_write(gx816->regs.x); //3 [reg low] g65816_incpc(1); } +/***************** + *** 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 g65816_op_phyb(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(1); - g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.y); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + gx816->stack_write(gx816->regs.y); //3 [reg low] g65816_incpc(1); } void g65816_op_phyw(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(1); - g65816_stackwrite(MEMSIZE_WORD, gx816->regs.y); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(1); //2 [i/o] + gx816->stack_write(gx816->regs.y >> 8); //3a [reg high] + gx816->stack_write(gx816->regs.y); //3 [reg low] g65816_incpc(1); } +/***************** + *** 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 g65816_op_plab(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(2); - gx816->regs.a.b = g65816_stackread(MEMSIZE_BYTE); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(2); //2,3 [i/o] + gx816->regs.a.b = gx816->stack_read(); //4 [reg low] g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0); g65816_incpc(1); } void g65816_op_plaw(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(2); - gx816->regs.a.w = g65816_stackread(MEMSIZE_WORD); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(2); //2,3 [i/o] + gx816->regs.a.p.l = gx816->stack_read(); //4 [reg low] + gx816->regs.a.p.h = gx816->stack_read(); //4a [reg high] g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0); g65816_incpc(1); } +/***************** + *** 0xab: plb *** + ***************** +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 g65816_op_plb(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(2); - gx816->regs.db = g65816_stackread(MEMSIZE_BYTE); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(2); //2,3 [i/o] + gx816->regs.db = gx816->stack_read(); //4 [reg low] g65816_testn(gx816->regs.db & 0x80); g65816_testz(gx816->regs.db == 0); g65816_incpc(1); } +/***************** + *** 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 [1] +*/ + void g65816_op_pld(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(2); - gx816->regs.d = g65816_stackread(MEMSIZE_WORD); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(2); //2,3 [i/o] + gx816->regs.d = gx816->stack_read(); //4 [reg low] + gx816->regs.d |= gx816->stack_read() << 8; //4a [reg high] g65816_testn(gx816->regs.d & 0x8000); g65816_testz(gx816->regs.d == 0); g65816_incpc(1); } +/***************** + *** 0x28: plp *** + ***************** +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 g65816_op_plp(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(2); - gx816->regs.p = g65816_stackread(MEMSIZE_BYTE); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(2); //2,3 [i/o] + gx816->regs.p = gx816->stack_read(); //4 [reg low] g65816_incpc(1); if(gx816->regs.e == true)gx816->regs.p |= 0x30; if(gx816->regs.p & PF_X) { gx816->regs.x &= 0xff; gx816->regs.y &= 0xff; } } +/***************** + *** 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 g65816_op_plxb(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(2); - gx816->regs.x = g65816_stackread(MEMSIZE_BYTE); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(2); //2,3 [i/o] + gx816->regs.x = gx816->stack_read(); //4 [reg low] g65816_testn(gx816->regs.x & 0x80); - g65816_testz((gx816->regs.x & 0xff) == 0); + g65816_testz(gx816->regs.x == 0); g65816_incpc(1); } void g65816_op_plxw(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(2); - gx816->regs.x = g65816_stackread(MEMSIZE_WORD); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(2); //2,3 [i/o] + gx816->regs.x = gx816->stack_read(); //4 [reg low] + gx816->regs.x |= gx816->stack_read() << 8; //4a [reg high] g65816_testn(gx816->regs.x & 0x8000); g65816_testz(gx816->regs.x == 0); g65816_incpc(1); } +/***************** + *** 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 g65816_op_plyb(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(1); - snes_time->add_cpu_icycles(2); - gx816->regs.y = g65816_stackread(MEMSIZE_BYTE); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(2); //2,3 [i/o] + gx816->regs.y = gx816->stack_read(); //4 [reg low] g65816_testn(gx816->regs.y & 0x80); - g65816_testz((gx816->regs.y & 0xff) == 0); + g65816_testz(gx816->regs.y == 0); g65816_incpc(1); } void g65816_op_plyw(void) { - snes_time->add_cpu_pcycles(1); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(2); - gx816->regs.y = g65816_stackread(MEMSIZE_WORD); + snes_time->add_cpu_pcycles(1); //1 [op fetch] + snes_time->add_cpu_icycles(2); //2,3 [i/o] + gx816->regs.y = gx816->stack_read(); //4 [reg low] + gx816->regs.y |= gx816->stack_read() << 8; //4a [reg high] g65816_testn(gx816->regs.y & 0x8000); g65816_testz(gx816->regs.y == 0); g65816_incpc(1); } +/********************** + *** 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 g65816_op_pea(void) { -g65816_prefetch(2); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_scycles(2); - g65816_stackwrite(MEMSIZE_WORD, arg); + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + gx816->stack_write(gx816->op.aa.p.h); //4 [write high] + gx816->stack_write(gx816->op.aa.p.l); //5 [write low] g65816_incpc(3); } +/********************** + *** 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 g65816_op_pei(void) { -g65816_prefetch(1); -g65816_getaddr(MEMMODE_DP); - snes_time->add_cpu_pcycles(2); - snes_time->add_cpu_mcycles(2, dest_addr); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(0, TIMING_REGD); - g65816_stackwrite(MEMSIZE_WORD, gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr)); + gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch] + gx816->op_cond(2); //2a [i/o] + gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read aal] + gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [read aah] + gx816->stack_write(gx816->op.aa.p.h); //5 [write aah] + gx816->stack_write(gx816->op.aa.p.l); //6 [write aal] g65816_incpc(2); } +/********************** + *** 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 g65816_op_per(void) { -g65816_prefetch(2); - snes_time->add_cpu_pcycles(3); - snes_time->add_cpu_scycles(2); - snes_time->add_cpu_icycles(1); - g65816_stackwrite(MEMSIZE_WORD, gx816->regs.pc + arg + 3); +word r; + gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch] + snes_time->add_cpu_icycles(1); //4 [i/o] + r = (gx816->regs.pc + (signed short)gx816->op.aa.w + 3); + gx816->stack_write(r >> 8); //5 [write pch] + gx816->stack_write(r); //6 [write pcl] g65816_incpc(3); } diff --git a/bsnes/d65816.obj b/bsnes/d65816.obj deleted file mode 100644 index e685f195330d2ed1a8336e19d86349ce0f003c91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84902 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 Cvyn3Z diff --git a/bsnes/demo.srm b/bsnes/demo.srm deleted file mode 100644 index 6d17cf9d15fb9f4a2358a2d079f3b8c755d005fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8192 zcmeIu0Sy2E0K%a6Pi+o2h(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM GyblZ@00031 diff --git a/bsnes/demo_mode1.smc b/bsnes/demo_mode1.smc deleted file mode 100644 index 687d174918c33fc9b9041a9f4a10bf4eafb354c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131584 zcmeIvF-sgl6ae72rxL+Hwuu}z-dI~$rxLgEN2Ce}X;knmEClxt>}j2HyA9+w2zG*n zbs!+Aw6;{Z%tjkQwAb&=vb=e3-oktvA>OmV*Qks4e1CT*K!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB=EFA@FUyvo#*=Z;kgyd%N4ChgciT&qNdv)5qwur@Oup z^>jMCJ1e{6CQ?^4bE&JF&waLN`L|GzJuJA61jT8`!CI*+xNdM}J=5gYwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM GyblZ@00031 diff --git a/bsnes/demo_mode4.smc b/bsnes/demo_mode4.smc deleted file mode 100644 index a1811a01b430b754b4e4e89581eff3a90f25b4be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131584 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 XKoB4Z5CjMU1Ob8oL4Y9eKS1C&3TxDT diff --git a/bsnes/demo_mode4.srm b/bsnes/demo_mode4.srm deleted file mode 100644 index 6d17cf9d15fb9f4a2358a2d079f3b8c755d005fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8192 zcmeIu0Sy2E0K%a6Pi+o2h(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM GyblZ@00031 diff --git a/bsnes/g65816.obj b/bsnes/g65816.obj deleted file mode 100644 index f333479d5eda2636e8723eb7bbdf85a2892678cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 289767 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 F{|E3XASD0* diff --git a/bsnes/gui.obj b/bsnes/gui.obj deleted file mode 100644 index 6d84676e8f835ccecc732b7478f6bbf5a09b5b86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67128 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�+sXzuLl2-Mr{RF{*Q%IY>#jS+^f`?^`@_~_)Nz;layg?=>4 z&f7U$U+!$yEw($F60Xq3ea z-JRlxx>aY_CG52YFZTOOe1lzCMrlz&sgJ)d z>H<$MESgi{qeDPHfJ`{4X1)%o^%D0URqR!l&jY05@h9;&Oyq>55c9l9S+K*B&R^FfzX%1bEqK) zM!k83p|?R=CBE_^^!3^gGEj_S&69Qtuz|I3`Nd1nb6nAymX}v9DM7Glx<6N*(DqDR z5{~4UOnc|Ti5hB#uAOi=CxbPvB^XzfTaJE8{~#WQ*zl(Ei+C!z`QpGi($Y~+$)1r) zSB7?7AHcf4Y1ek^RgnvAycNFuA}qqGpI6Gx#IG%38t)&}!~1i}b8JMe-<2I%y2YUy z4w9t$^U?U{yU?kH#W}^kGY9eJ6c+jx4CbL7SGjn8Uw&y}u@9lJq$TN@+UeL0-4ub@ z8i-U7CNCURXpUs&S5y@E@M_=eOxvy$N9LRY42qP%y;4}}%d03T@yYvqF^C)FmC*U- z=jR(SUJmR^7_^H}rEKloB6p~zzT&b1GtWr=qU0_X3sHwV`#h39ek)aoROQ4rB|_p4$)<5 zMri@ujL5J-xU;3BnL7n$eyWZ8(a#w?N4H${<1A@VB&6f6ZpCkE L=Bizx4D0^_*Jd7x diff --git a/bsnes/libstr.obj b/bsnes/libstr.obj deleted file mode 100644 index 7518ffe95403f512c4c65b98d52b0e450fbf9962..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38996 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 vJ$Oa_$ZRun(); - gx816->Run(); - gx816->Run(); - gx816->Run(); - gx816->Run(); - gx816->Run(); - gx816->Run(); - gx816->Run(); +void debug_test_breakpoint_hit(byte source, byte flag, ulong offset, byte value, int i) { + dprintf("* breakpoint %d hit", i); + debugger.bp_list[i].hit_count++; + debugger.refresh_bp = true; + debug_set_state(DEBUGMODE_WAIT); + if(source == BPSRC_SPCRAM) { + disas_spc700_op(); + } else { + disas_g65816_op(); } } -void RunSNES_Debug(void) { - if(debug_get_state() == DEBUGMODE_NOROM)return; +void debug_test_breakpoint(byte source, byte flag, ulong offset, byte value) { +int i; + if(debug_get_state() == DEBUGMODE_DISABLED)return; + + for(i=0;i<16;i++) { + if(debugger.bp_list[i].source != source)continue; + if(debugger.bp_list[i].flags & flag) { + if(debugger.bp_list[i].offset == offset) { + if(debugger.bp_list[i].flags & BP_VAL) { + if(debugger.bp_list[i].value == value) { + debug_test_breakpoint_hit(source, flag, offset, value, i); + } + } else { + debug_test_breakpoint_hit(source, flag, offset, value, i); + } + } + } + } +} + +ulong debug_write_status(void) { + if(debugger_enabled() == false)return DEBUGWRITE_NONE; + + if(debug_get_state() == DEBUGMODE_RUN) { + if(debugger.trace_enabled == false)return DEBUGWRITE_NONE; + if(debugger.trace_output_enabled == true) { + return DEBUGWRITE_CONSOLE | DEBUGWRITE_TRACE; + } + return DEBUGWRITE_TRACE; + } + + return DEBUGWRITE_CONSOLE; +} + +void init_debugstate(void) { + debugger.mode = DEBUGMODE_DISABLED; + + debugger.mem_ptr = 0x7e0000; + debugger.disas_cpu_op = true; + debugger.disas_apu_op = true; + debugger.refresh_mem = true; + debugger.refresh_bp = true; + debugger.refresh_status = true; + + debugger.cpu_op_executed = false; + debugger.apu_op_executed = false; + + debugger.output_cpu_instrs = true; + debugger.output_apu_instrs = true; + debugger.output_debug_info = true; + debugger.trace_enabled = false; + debugger.trace_output_enabled = false; + + debugger.lock_up = debugger.lock_down = debugger.lock_left = debugger.lock_right = false; + debugger.lock_a = debugger.lock_b = debugger.lock_x = debugger.lock_y = false; + debugger.lock_l = debugger.lock_r = debugger.lock_select = debugger.lock_start = false; +} + +void RunSNES(void) { + if(emu_state.rom_loaded == false)return; + + if(debugger_enabled() == false) { + gx816->Run(); + spc700->Run(); + return; + } if(debug_get_state() == DEBUGMODE_RUN) { gx816->Run(); + spc700->Run(); if(debugger.trace_enabled == true) { - disas_g65816_op(); + if(debugger.disas_cpu_op == true) { + disas_g65816_op(); + debugger.disas_cpu_op = false; + } + if(debugger.disas_apu_op == true) { + disas_spc700_op(); + debugger.disas_apu_op = false; + } } } else { - if(debugger.disas_op == true) { + if(debugger.disas_cpu_op == true) { disas_g65816_op(); - debugger.disas_op = false; + debugger.disas_cpu_op = false; + } + if(debugger.disas_apu_op == true) { + disas_spc700_op(); + debugger.disas_apu_op = false; } if(debugger.refresh_mem == true) { debug_refresh_mem(); @@ -47,30 +124,68 @@ void RunSNES_Debug(void) { debug_refresh_bp(); debugger.refresh_bp = false; } + if(debugger.refresh_status == true) { + debug_update_status(); + debugger.refresh_status = false; + } if(debug_get_state() == DEBUGMODE_WAIT)return; - if(debug_get_state() == DEBUGMODE_STEP) { + if(debug_get_state() == DEBUGMODE_CPUSTEP) { gx816->Run(); - disas_g65816_op(); - debug_set_state(DEBUGMODE_WAIT); + spc700->Run(); + if(debugger.cpu_op_executed == true) { + debug_set_state(DEBUGMODE_WAIT); + } + } + + if(debug_get_state() == DEBUGMODE_APUSTEP) { + gx816->Run(); + spc700->Run(); + if(debugger.apu_op_executed == true) { + debug_set_state(DEBUGMODE_WAIT); + } } } + debug_update_status(); } +extern vfunc spc700_optbl[256]; + void InitSNES(void) { +int i, z; snes_time = new snes_timer(); gx816 = new g65816(); gx816->PowerOn(1); + spc700 = new sony_spc700(); + spc700->Reset(); + snes_time->reset_clock(); + cpu_apu_bridge = new port_bridge(); if(*emu_state.rom_name == 0) { - debug_set_state(DEBUGMODE_NOROM); + emu_state.rom_loaded = false; } else { gx816->LoadROM(); + emu_state.rom_loaded = true; } + for(i=0;i<16;i++) { + debugger.bp_list[i].offset = 0; + debugger.bp_list[i].flags = BP_OFF; + debugger.bp_list[i].source = BPSRC_MEM; + debugger.bp_list[i].value = 0; + debugger.bp_list[i].hit_count = 0; + } +} - if(debug_get_state() == DEBUGMODE_DISABLED) { - RunSNES = RunSNES_NoDebug; - } else { - RunSNES = RunSNES_Debug; +void ResetSNES(void) { +int i; + gx816->Reset(); + spc700->Reset(); + snes_time->reset_clock(); + for(i=0;i<16;i++) { + debugger.bp_list[i].offset = 0; + debugger.bp_list[i].flags = BP_OFF; + debugger.bp_list[i].source = BPSRC_MEM; + debugger.bp_list[i].value = 0; + debugger.bp_list[i].hit_count = 0; } } @@ -91,7 +206,9 @@ char fn[MAX_PATH]; emu_state.sram_name[strlen(emu_state.sram_name) - 4] = 0; } strcat(emu_state.sram_name, ".srm"); -//located in win/gui.cpp - __winmain(); + + init_debugstate(); + __winmain(); //located in win/gui.cpp + return 0; } diff --git a/bsnes/main.h b/bsnes/main.h index 21446257..9d92669a 100644 --- a/bsnes/main.h +++ b/bsnes/main.h @@ -5,26 +5,17 @@ void __winmain(void); to emu_state.sram_name */ emustate emu_state = { - "", "", //rom name, sram name - 1000000 //sram save tick count *1 -}; - -debugstate debugger = { - DEBUGMODE_DISABLED, //default debug mode - false, //trace enabled - 0x7e0000, //debugger memory start pos - true, //debugger disassemble op - true, //debugger refresh mem - true, //debugger refresh breakpoints - 0 //tracelog file pointer + false, //rom loaded + 20000000, //sram save tick count *1 + "", "" //rom name, sram name }; videostate render = { - 512, 448, //resolution + 512, 448, //display resolution 256, 224, //snes internal resolution false, //fullscreen true, //show menu - 1, //frame skip + 0, //frame skip 0, //frame count { true, true, true }, //bg1 enable { true, true, true }, //bg2 enable diff --git a/bsnes/main.obj b/bsnes/main.obj deleted file mode 100644 index e04557fb60faf02d8cc6218513191e03c8ce5b33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11653 zcmeHNUu;uV82@ftx^4_tvC&~fD-=P&W}|Z=8R;!s(UScsOvaxmrCTqf%i7Mi7l@)6 z4uaZ%Bfc2KghYrjF}_KBP$`V)Kwlun#F!9`FXBi{0JES8^ZU-Z_uSi6@WmIC^Cjop z@BGepzCXWvdi(NqD)sP9?9<57WdO~&R!Tv(Qj=Jm%Lm!2vaN#o>(>VZ>lkR@ zZ!HEmhJ%Dsea`D$JKNtl;wRCjB|ugH_u;sczw2n@Si;Qi>aQMcjvIFO-o@X##{l|p zklZQ1CfwM8HsedVT|GW{ew94WLEMAy%Py)H`TGZ6=Aqp}!`6)ZWJ=qa)Q5}1>HgKa zo=yc(@&7B>8C%<4Vb#;w(H-fE_WJF4NL?}@8ITM}1|$QL0m*=5Kr$d1kPJu$BmDnL+DW+G z;{po`tVLkY2rMkH4uP!~SdYLq32d9dP=NuOxG)Nd*BUrM$boXhf&KVwbLtChOpUG~ zLq$(tC8N5aA^%-fKIJ+@AaQ$+IY zz9WBpm)cz(#NmS#;smkAvDE^L2rY)%0vtXduDF*zp>0Qv-jfef0vi(AUex$|dlfbQ z-d;zIM|%^s2XOds0KCm+Yq}rR8W{4h3dhd74wj4elqT8g1G1W``0%si zpnJ+SVwc+yr_?OvgJ*H(Y;>abD8n}3OfTOJFW}7C7(|WR4Ws7A;e(fO_TX^C9-Ql$ z_6p8)8{KeFV8kiqv!Ctl8Z!TyOty$eg^?`Vh6GD15fw0DK}vCt?Je)f{kt_bZH)adKwhG~I$ zF^A>2@~JxWqb7h)^lWR-n}di`A+O}`^dA>ixPUNwboyC2m2sS@QPI~v{hk&5Lqtg2BKj8` zz}bxceHHS16;ey#nb0YFhBb&<8D5?|_@lcjL;6VY4Cxc{e)Ex>l_A|D5|7AdWkoF7 zTVI6?R3W-Rh(nTh1Y%bDQ3YbJf_@HG6%En($30b5&|jZZq2^2a)cxT1^;=b(HaypX z8SC7vSXOK1T;_+~BFV(lFOHfS1AJ$kBAZH{DW;VnE})KOcnwd4^IA5gWxUhCM>e=4zXfL{pw??*X*@k`$DAAqkpq^S) z-AWq_R|i|4TGiaDsv9Cvh7Imz%TPShXKvX%RGw!!B??;6Oa=W$RdmcZ^4iY4R@jy3 z9}y8NH!@nr+DR9Zg#-_o$XO?1*>sWDV~OQtsVbX6rD&+XCjJ=qGJB@=Ek3&9#y zs=JWY3W;JmgDg{>Vu|knYYjKq0rO0FC9)QeY>8ogiOuP37k(Ml=2i$N5_{5F`c8^c Z!ijb@(bUo%jmFe)3x0CLfk;G!zXAShNMry2 diff --git a/bsnes/mem/memory.cpp b/bsnes/mem/memory.cpp index 5d2072dc..07035c6d 100644 --- a/bsnes/mem/memory.cpp +++ b/bsnes/mem/memory.cpp @@ -1,8 +1,10 @@ #include "../base.h" #include "../cpu/g65816.h" -extern g65816 *gx816; -extern emustate emu_state; -extern debugstate debugger; +#include "../timing/timing.h" +extern g65816 *gx816; +extern emustate emu_state; +extern debugstate debugger; +extern snes_timer *snes_time; void g65816::InitializeROM(byte memory_map) { memset(rom, 0, 0x600000); @@ -71,37 +73,35 @@ ulong g65816::convert_offset(byte read_mode, ulong addr, bool mirror) { byte db; switch(read_mode) { case MEMMODE_DP: - addr = (regs.d + (addr & 0xff)) & 0xffff; + addr = (regs.d + (addr & 0xffff)) & 0xffff; break; case MEMMODE_DPX: - addr = (regs.d + regs.x + (addr & 0xff)) & 0xffff; + addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff; break; case MEMMODE_DPY: - addr = (regs.d + regs.y + (addr & 0xff)) & 0xffff; + addr = (regs.d + regs.y + (addr & 0xffff)) & 0xffff; break; case MEMMODE_IDP: - addr = (regs.d + (addr & 0xff)) & 0xffff; + addr = (regs.d + (addr & 0xffff)) & 0xffff; addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr); addr |= (regs.db << 16); break; case MEMMODE_IDPX: - addr = (regs.d + regs.x + (addr & 0xff)) & 0xffff; + addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff; addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr); addr |= (regs.db << 16); break; case MEMMODE_IDPY: - addr = (regs.d + (addr & 0xff)) & 0xffff; + addr = (regs.d + (addr & 0xffff)) & 0xffff; addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr); addr += (regs.db << 16) + regs.y; - if((addr >> 16) != regs.db)index_bank_crossed = true; - else index_bank_crossed = false; break; case MEMMODE_ILDP: - addr = (regs.d + (addr & 0xff)); + addr = (regs.d + (addr & 0xffff)); addr = mem_read(MEMMODE_LONG, MEMSIZE_LONG, addr); break; case MEMMODE_ILDPY: - addr = (regs.d + (addr & 0xff)); + addr = (regs.d + (addr & 0xffff)); addr = mem_read(MEMMODE_LONG, MEMSIZE_LONG, addr); addr += regs.y; break; @@ -116,14 +116,10 @@ byte db; case MEMMODE_ADDRX: addr = (regs.db << 16) + (addr & 0xffff); addr += regs.x; - if((addr >> 16) != regs.db)index_bank_crossed = true; - else index_bank_crossed = false; break; case MEMMODE_ADDRY: addr = (regs.db << 16) + (addr & 0xffff); addr += regs.y; - if((addr >> 16) != regs.db)index_bank_crossed = true; - else index_bank_crossed = false; break; case MEMMODE_IADDRX: addr += regs.x; @@ -155,6 +151,25 @@ byte db; addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr); addr += (regs.db << 16) + regs.y; break; + + case OPMODE_ADDR: + addr &= 0xffff; + break; + case OPMODE_LONG: + addr &= 0xffffff; + break; + case OPMODE_DBR: + addr = (regs.db << 16) + addr; + break; + case OPMODE_PBR: + addr = (regs.pc & 0xff0000) | (addr & 0xffff); + break; + case OPMODE_DP: + addr = (regs.d + (addr & 0xffff)) & 0xffff; + break; + case OPMODE_SP: + addr = (regs.s + (addr & 0xffff)) & 0xffff; + break; } if(mirror == true) { @@ -164,129 +179,13 @@ byte db; } } -ulong g65816::adjust_base_offset(byte read_mode, ulong addr) { -byte db; - switch(read_mode) { - case MEMMODE_DP: - addr = (regs.d + (addr & 0xff)) & 0xffff; - break; - case MEMMODE_DPX: - addr = (regs.d + regs.x + (addr & 0xff)) & 0xffff; - break; - case MEMMODE_DPY: - addr = (regs.d + regs.y + (addr & 0xff)) & 0xffff; - break; - case MEMMODE_IDP: - addr = (regs.d + (addr & 0xff)) & 0xffff; - break; - case MEMMODE_IDPX: - addr = (regs.d + regs.x + (addr & 0xff)) & 0xffff; - break; - case MEMMODE_IDPY: - addr = (regs.d + (addr & 0xff)) & 0xffff; - break; - case MEMMODE_ILDP: - addr = (regs.d + (addr & 0xff)); - break; - case MEMMODE_ILDPY: - addr = (regs.d + (addr & 0xff)); - break; - case MEMMODE_ADDR: - addr = addr & 0xffff; - addr |= (regs.db << 16); - break; - case MEMMODE_ADDR_PC: - addr = addr & 0xffff; - addr |= (regs.pc & 0xff0000); - break; - case MEMMODE_ADDRX: - addr = (regs.db << 16) | (addr & 0xffff); - addr += regs.x; - if((addr >> 16) != regs.db)index_bank_crossed = true; - else index_bank_crossed = false; - break; - case MEMMODE_ADDRY: - addr = (regs.db << 16) + (addr & 0xffff); - addr += regs.y; - if((addr >> 16) != regs.db)index_bank_crossed = true; - else index_bank_crossed = false; - break; - case MEMMODE_IADDRX: - addr += regs.x; - addr &= 0xffff; - break; - case MEMMODE_ILADDR: - addr &= 0xffff; - break; - case MEMMODE_IADDR_PC: - addr |= (regs.pc & 0xff0000); - break; - case MEMMODE_IADDRX_PC: - addr += regs.x; - addr |= (regs.pc & 0xff0000); - break; - case MEMMODE_ILADDR_PC: - break; - case MEMMODE_LONG: - break; - case MEMMODE_LONGX: - addr += regs.x; - break; - case MEMMODE_SR: - addr = (regs.s + (addr & 0xff)) & 0xffff; - break; - case MEMMODE_ISRY: - addr = (regs.s + (addr & 0xff)) & 0xffff; - break; - } - return addr; -} - -ulong g65816::read_indirect_address(byte read_mode, ulong addr) { -byte db; - switch(read_mode) { - case MEMMODE_IDP: - addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr); - addr |= (regs.db << 16); - break; - case MEMMODE_IDPX: - addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr); - addr |= (regs.db << 16); - break; - case MEMMODE_IDPY: - addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr); - addr += (regs.db << 16) + regs.y; - if((addr >> 16) != regs.db)index_bank_crossed = true; - else index_bank_crossed = false; - break; - case MEMMODE_ILDP: - addr = mem_read(MEMMODE_LONG, MEMSIZE_LONG, addr); - break; - case MEMMODE_ILDPY: - addr = mem_read(MEMMODE_LONG, MEMSIZE_LONG, addr); - addr += regs.y; - break; - case MEMMODE_IADDRX: - addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, (addr & 0x00ffff)); - addr |= (regs.pc & 0xff0000); - break; - case MEMMODE_ILADDR: - addr = mem_read(MEMMODE_LONG, MEMSIZE_LONG, addr); - break; - case MEMMODE_ISRY: - addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr); - addr += (regs.db << 16) + regs.y; - break; - default: - dprintf("* Error: Invalid read_mode for g65816::read_indirect_address [%d]", read_mode); - break; - } - return addr; -} - -ulong g65816::get_dc(byte read_mode, ulong addr) { - regs.dc = convert_offset(read_mode, addr, false); - return regs.dc; +ulong g65816::read_operand(byte size) { +ulong r; + r = gx816->mem_read(MEMMODE_NONE, size, gx816->regs.pc + 1); +//add size + 1 cycles. the extra cycle is for the actual opcode +//byte itself being read in by the main cpu emulation routine. + snes_time->add_cpu_pcycles(size + 1); + return r; } byte g65816::mem_getbyte_direct(ulong addr, byte access_mode) { @@ -295,7 +194,11 @@ word a; db = (addr >> 16) & 0xff; a = (addr & 0xffff); if(db == 0x00 && a >= 0x2000 && a <= 0x5fff) { - return mmio_read(addr); + if(access_mode == MEMACCESS_DEBUGGER) { + return 0x00; + } else { + return mmio_read(addr); + } } if(db == 0x7e || db == 0x7f) { @@ -324,30 +227,9 @@ byte r; r = mem_getbyte_direct(addr, access_mode); if(debug_get_state() == DEBUGMODE_DISABLED)return r; - if(access_mode == MEMACCESS_DEBUGGER)return r; //don't report breakpoint hits from debugger - for(i=0;i<16;i++) { - if(bp_list[i].flags & BP_READ) { - if(bp_list[i].offset == addr) { - if(bp_list[i].flags & BP_VAL) { - if(bp_list[i].value == r) { - dprintf("* breakpoint %d hit -- read match access [%0.2x]", i, r); - bp_list[i].hit_count++; - debugger.refresh_bp = true; - debug_set_state(DEBUGMODE_WAIT); - disas_g65816_op(); - } - } else { - dprintf("* breakpoint %d hit -- read access", i); - bp_list[i].hit_count++; - debugger.refresh_bp = true; - debug_set_state(DEBUGMODE_WAIT); - disas_g65816_op(); - } - } - } - } + debug_test_bp(BPSRC_MEM, BP_READ, addr, r); return r; } @@ -392,30 +274,9 @@ int i; mem_putbyte_direct(addr, value, access_mode); if(debug_get_state() == DEBUGMODE_DISABLED)return; - if(access_mode == MEMACCESS_DEBUGGER)return; //don't report breakpoint hits from debugger - for(i=0;i<16;i++) { - if(bp_list[i].flags & BP_WRITE) { - if(bp_list[i].offset == addr) { - if(bp_list[i].flags & BP_VAL) { - if(bp_list[i].value == value) { - dprintf("* breakpoint %d hit -- write match access [%0.2x]", i, value); - bp_list[i].hit_count++; - debugger.refresh_bp = true; - debug_set_state(DEBUGMODE_WAIT); - disas_g65816_op(); - } - } else { - dprintf("* breakpoint %d hit -- write access", i); - bp_list[i].hit_count++; - debugger.refresh_bp = true; - debug_set_state(DEBUGMODE_WAIT); - disas_g65816_op(); - } - } - } - } + debug_test_bp(BPSRC_MEM, BP_WRITE, addr, value); } ulong g65816::mem_read(byte read_mode, byte read_size, ulong addr, byte access_mode) { @@ -424,16 +285,16 @@ ulong r; switch(read_size) { case MEMSIZE_BYTE: - r = mem_getbyte(addr, access_mode); + r = mem_getbyte(addr, access_mode); break; case MEMSIZE_WORD: - r = mem_getbyte(addr, access_mode) | - mem_getbyte(addr + 1, access_mode)<<8; + r = mem_getbyte(addr, access_mode) | + mem_getbyte(addr+1, access_mode)<<8; break; case MEMSIZE_LONG: - r = mem_getbyte(addr, access_mode) | - mem_getbyte(addr + 1, access_mode)<<8 | - mem_getbyte(addr + 2, access_mode)<<16; + r = mem_getbyte(addr, access_mode) | + mem_getbyte(addr+1, access_mode)<<8 | + mem_getbyte(addr+2, access_mode)<<16; break; } @@ -461,6 +322,63 @@ void g65816::mem_write(byte write_mode, byte write_size, ulong addr, ulong value debugger.refresh_mem = true; } +/* + todo: move address mirroring into mem_getbyte + in case there are different memory speeds depending + on pre-mirrored addresses. +*/ +byte g65816::op_read(byte mode, ulong addr) { +byte r; + addr = convert_offset(mode, addr); + r = mem_getbyte(addr); + snes_time->add_cpu_mcycles(1, addr); + return r; +} + +void g65816::op_write(byte mode, ulong addr, byte value) { + mem_putbyte(convert_offset(mode, addr), value); + snes_time->add_cpu_mcycles(1, addr); +} + +byte g65816::stack_read(void) { +byte r; + gx816->regs.s++; + if(gx816->regs.e == true) { + gx816->regs.s = 0x0100 | (gx816->regs.s & 0xff); + } + r = mem_getbyte(convert_offset(OPMODE_SP, 0)); + snes_time->add_cpu_mcycles(1, gx816->regs.s); + return r; +} + +void g65816::stack_write(byte value) { + mem_putbyte(convert_offset(OPMODE_SP, 0), value); + gx816->regs.s--; + if(gx816->regs.e == true) { + gx816->regs.s = 0x0100 | (gx816->regs.s & 0xff); + } + snes_time->add_cpu_mcycles(1, gx816->regs.s); +} + +/* + note: case 4 (write) condition is handled directly + in the opcode, since it is always true. +*/ +void g65816::op_cond(byte c, ulong n0, ulong n1) { + switch(c) { + case 2: //dl != 0 + if((regs.d & 0xff) != 0x00) { + snes_time->add_cpu_icycles(1); + } + break; + case 4: //read across page boundaries, write, or x=0 + if((n0 & 0xff00) != (n1 & 0xff00) || !(gx816->regs.p & PF_X)) { + snes_time->add_cpu_icycles(1); + } + break; + } +} + ulong g65816::rom_read(ulong addr, byte read_size) { ulong r; if(map == MEMMAP_LOROM) { diff --git a/bsnes/memory.obj b/bsnes/memory.obj deleted file mode 100644 index ca0afd4a5a1f84a4d8c01fb8254184649984b321..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11196 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 diff --git a/bsnes/mmio.obj b/bsnes/mmio.obj deleted file mode 100644 index 090d59ad6bd3c0ee262caf61a8b43c743a65bf79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81207 zcmeFa349b));3<9?sNhqbbt<^5NRN|u?Pf4Rtc-9pkY^02wRH?f{+#*ap)KVoo=Ey z;=+te0`4o0`v&Pm!lI5Wu7eBcC`;U(K|m${=bTe@t2&i#qO*MO`~AQBOWk_v+;g9M z?tbf5RcDlAkmJqso*jJA7n-))sj=%ebK$HR1=r4!D@{8U;L9Gym40rVp>>Us`bkIcvzQkQQ7a-+j<| zy8(O$pmU@Fd`Z94w4OM~C9-b>bSCP0@#=%}n-87U4dA;EI?ptKZzFWRZUA4>*=W-^ z$i=hIhp@KL8DPD<3!T?=J+ppe$LDU)>zONDhM${(@wuLHHy?TnblrIAW`N}P&{>&3G#7x8a|PNlAw$iCyyX*wJc;NtP+Bdj%amgstk?Ar>R z_fNn_?d4PGjMY~lwCstO-|f)(o30nnz98cN9Xd151%PXcBOc$kq%)GV;^#Mru*T2{ z>w1aoOF9p20SCEw_N_)(Tj)Hd>m{@U*@pVVQJm}ngq3E^1DPFxz zzDU!q!a*(`-v)#Qpwo#uC|o*@czh2+=XqT(9$y{;qR?qJmg%&%3HZ(!r)hn0kc-E+ z7hyx8({Vg$X_^N|Jo{dR&Nf{y9-j~KcSGj~T`wsCU&;hcYlVYcJidH{wTDiju9t%A zc=m09&U+`|%SHTs&}lyr04^CvJic+znW5{&vyZB49&}!90N*#zscisXqe+@}2@Z0J z?2AC>&$?bb`?`bUe(1cT>p5{9FTX!P$9XZO8oxe#2up`fS6wer{SJoCm}~+xe(3yo0=^*f=(rU94F|b29MWE5$8nl3j_Nw3M=stto-!Hbhl5cB+dKmy*BOLMi(Msstq3gxVFY%Q_r`hGi zmYDA<=v=Ss#pBBbM=^9Z>w0cn$Ft8d1?l1-mx!+obSCS1iTLh-&Vwi5%RpLBK__a_ zi)Y{K(Ai_rtM7h+#Sbk?gXOONJ zkB{p2JY7c^zN4j33`beIRc7=nS14n)B&j)!s z=nT^Jl5icb{f&dp3|%h~-#qA)>Uv2D_{yR4l&+VE?`7!h(e;uN@O=ZFT3s&@U!xhC zb_Nb|iTDOWXSA*tkB{2RBmx!+rI=7sFkH)J%L+5o}&xz}J`8^1oqbK0=A-;1K z?gMa;OT;%AI%9Obc=`2#V={EEZvfv~=sbJ^zSZD+8ahM$0C0)!^PYlERM(4VUoJRa zhfb3#h%NDWdM3WIyra`A%*GmRxy!zM;ozG6d=R^Fjpp!lu04`B`X%C$qx?Vi{ zsJ--u&Q%TITLzt*Pr&B`-&*Lr*Z{saq4QA#`1V65bY5?DU=%ic) z!{8F}b%IWBT`y672SI0Q1Nd%$PH6-9?tsqo4d8nRI-j3_FBf_I20CZWrQ9aIPo4&y zYjnMM`OO8#_0V~_0eoLU=a&=k`M{Sl59>M{#{?NHV*NbPL4;&Mq6KDWm33S#r zfNwo?sv5xe9(49MfbTo#G`pH|n>fFnpwnB|OO)S1(3#o*zD3X}Y5-p;bRKU2Ulck! zPr#RfJnn%`O#}F9q2rm)#gcG*ISD#_b-hIGWi)gyZvfvF&{^34zCT0f(G&1dexHTT zW{Y0D@$W6@d}7h7Z+%7c(Lv~(L<2QkqVei%=$xzTC2B8YpmU9`m#F-Tp>taU`0j3zD($JvgpO*I}194EPCIxBU(M11c-Xa5QKsD8hL zjw4{E8?XGDK&OpGufFmlzE05TZPAOzHwZcxS@h!ZT>_meEqd|z7D1=Tq8E>^6gqcX z^y2Y72%YCGdiC+;BEM1SIIflQOSJww13G&4@v^1B;4=}U#LQ3AdzptD%li^u0f{6grI>w1aG zZxeLhIssn>_&(5e0NKSWzk|>_+5kT14F*$Uz828ysO!ed?*;^Ph0aHR5U$2J#j|hl zGVGV&AQz9X3;~m&^HY%362336vJlS~aFC0~w-+6@96E(7MK4kP?txB?t{0Cl0|V4Q zp_3dIzAT*L<@dCRrk#z0Ts*!V2p9~VW~HK+h%e_RjFmXZ#pC-H0i&TaaJA^2hEqKI zs&2u&kAqx1zA^-S1f3gh6}>h%#p8>t!Co8=a`E_9BjA4M^uAs667dbaL(|6LAQz7> z9|OSU(0TQ4(evRH&%R&oK|jA&^y2ZAA-ENEp4asfji)J4ZbcE`;__jFY+r^s^FCJ7 z+T#?@z9tV~y@7*VTt2kFPSDx>kmxnVDIVXLhc#^)4s!AMD!_LYbUHsKdLwa)$M@3{ zm>ZrHy?A_i;LC*0tfxe8Kmxv3pVqWDagdA0NB!eH=sftW=yk^_o_#By$9RB)Tq3@5 z=v?!n=q2JC^D@d02f28Bdl7IIbS`*R^b+xP-h_D-2f28BL4*y5&SqUN4cGDVJFo(M z9S6C1e0d0)RDtrtK@Qy|F5hPrcwYqvxp;ivBJ7t6%+pcQ(zKIt#Ix_aO7K*%T3kLK z+DjAYblxm_LlW?9+JgBK2f29mbw|Jl&}pq`Zy@aPjP0jq#-!bjsfnJ(`BOJ{HD)m_XxL>D!`X__-Om zx%IvGdK>ia*LCBiOa1am=q!6z*m7`+*A8xYA8F$t7mqJD1$`Gf?|mYA>v4+5*ZT|9 z2@Y}wU)Pzl{L=z+3+7%qz2B(wh79#t1s9DPcH!XB!^im?Nl7jg*omDZ$>~aVr=&J& z+$1f%sVAdZ^A_IBmaST!baI=vS*Nr+k$Zts=(+1fx?2e4IYJqskwQCX==hqj(_sE1~twWXSu zfL3KFn#z%ZM8nz`8y#9s#Sf201`^kcS`Y(+y2zCa1Rw zr&ghAH6IQyzct<*$gQyYQm&EVNLn#f zbKyR%wpMGhy+kf4D<-FDKQy(j(p#Bh=iSbxgY?o19@-;JGFF!J&Z!((xDWDH4eL3GKtx#_XxXc#o!L571L5u zS=<5_riHC>Mb5BrB(QKyWaA=~b8U`R+AA3SA}O+hnnvCn$DF1INRAdbK07Tm3M20(T4o7uq-zH*Zz58E?M+m$Q`k;I7vXU8 zDnzWMR&gN?uhyG=W4yQlG+ymIC7Y;FzCwP5<|}lqLI9e6b4}&IBf@CNtmT0GBeTP@ z(@+Zj$W4@2zjNyt&L;AoAti&}lp!Tn^qNb0)EsTBSzb~gzqT~Y>BQ`T9bmw8&UqIg zDIpq5q|``7TF^0mzzd- z1*suxt>XfPhjzDI-Ff)sc%og7sv8gV+n%Qq@IwL#0nmK0T zQX4}a94ZjzYTBhZ65ERB-8NebM$B>8gn@S@183G3Av0ct2IPh6O!AitB;`(ZCiye# z>Ld9t#d>+TgetG*>WIhCpRhCS|wYr zWVpH4^=S1fd{s*Jrjh|@?~w;*w5Kb96St=Xb!4v!&vLG#BwGhV9XV~n6V#ENzTnI` z^-yQlNBw_M9bL_JG%j*kcIw1QIkknK(Q0U;3*HN;MlJHz?!CoT1&ebk{E-oi)vR?KW;Iv+L7~ryAw%`dNj~c7or(g~!s`j2+ zc>F#{Jger`*49p)GMPIEZeaAbNbAMxaJaQz@RzVW7e0;OUY^ltRP$<6;Ll_<4?eX_ zFVEYQf3LO*{$d<%?H2e2ETfS^+WVQldGoHEKXq}hp53RPenvmvgsZQ*dj8_8eZxi% z_7yCgcJ(6vtcAXU>lV!F=j%ji;JY#QxhG(r#j_3^DOwo!2Y~1=@n4)b*UcB6jYS`WTCam6V&m*2OwJj?jut z(lFP5bQd6VJ(b>tIK0}~N)JGzS&|%5qE?_4;jpe~bW?`2DLjQcc_F5^jX6n%DUq9~ zs&aOPZ*PjTb1PQc$jTfo`e{a!?S{5#_zKci<6m=Ji0!8UNnMz>cY{o9@2x_~ZqcK0 zQ1VFgpyUk(?lzK5$k}TPZUQ1IZuBN+KDjlz8uCLnR zT2__-e7{C#Bb`!Ul;x;w*ThJ4jAa$XiRS5xVPg^Ofi@CEH%q}P*DM~&C0Xp{Z`>r$ zw62qMPv;P7S+quwPylTJd2og;e+1U^9I2kfwoEJ?5Hu`ty-K+jQ>08#5+d^tHVUJ) zb;9DAi|S3vqz#ay-X2J7J57aB>yywvDilB)LLMBfC5aq!_4psDah6+$VUD`ZfD0aoS0KB-$P1?nmwf>QWmS}PEta<1BumrRp=lkllj=_ z(-R>lXXNBA;NMo>*3$m<~ORB4=1t4*VO-SIlZa>B>F&uPa{~lf-JXUta*3 z*`CMaiky*?2Y~;T@--T{S8wD)#&Qc2F}kL72!F0LwW8O$a|`-c>VtZu^p#;ik~3;U zl5ZNtB$P%m38fjvtjnu$Mb0RJM}hyPx-|OF?cDYKdI^Zs7@Uj(FzUU#rC0q-y^2Qd zf2FP^ZoCqa(8)+cN@NC*l!(mh)ca^QmrwvLNFJO~N*jQGTRSlZl)5dYs4}Vkwvz1B z2T-H6sKx#2U*B%baq=AGKw8EKAjv7+!%8_!Qla@ObdCxI;581NjS_hl_&2s2qe$ws z991H9+KwuaxUI)5p3v8X8Epw$6qvHbQ<(E&+@;*4<2&_GW>-i3qtrJgy9e=go7^l%eMtC zphdMbFl+_!=10sW7S+~JEUK-SuE0dg<-bT}Wv*v^F7qeVl9XV3Ai8q%KAWJSD)c;s zsD08p$gBC`-@zyVznsx>_%x1rwOipo%V-_^KQej>KFy5{Fy+0e%6?EGzjL)|LFo_)Gbp5s@5fh$>0jgd;^8H-WdYyoLK~ag92@f$O-m zEuRC|l=j+G+T{jX9%Iihr-Byl!?g&nk+JiqZ;YySZ*hgc#2HAdUfG3GnL6e2$yNS= zLCwE~*D3hfp+?obesR>K2+*)u==IkQ*JR8=EAiJh;dpxAp`k^J|73+uRp@LWsjyt2 zi*UGk6I7PTR5=oNHjwBoRERc>L>303(x59m;$)u-i3MA5Ez4Y#Rph%#vYJNA4^T-3 zwbHf>0@sxec&@Yy->^jYn?-eVD&i+7sugvMY9+0Wxu{lB*Q26h5WlFfun)V6xzAMu zni&f$Rg$=stw)$tpU_#K&{dDHo-Pzyaa43t_Ou8UL`zRW{eYzGsZ&Y4jRKN-yHx32 zrSt*{(e0$frH&`{Mx9Dzbi*ngG72Oe@?D^E)~JCm9g_OMvn*=~B;BhGPyx%}X=mb! z98N^7y@BII{l!yU2rYk+i+c?A$OY&<2z?2isFU0{{+Ietef{Tj*eLbTLm`@wMRoy@ zl;wCJshi7zq;9B2L~p6mTcOa+3f%)__Nm8lMb0S8oxmyDgb1GgOpN?fdekJdOL>Z^ zOQIOLH&HRlUcrFpxbV=u=4g>b9m^$MvPre-UHUi_w{sbL4HFKKojeYuF$o5vs!}gH z*ll_T%dA(0_Vw!zNQxKWj2GaF6HsrbGp$_R0+vhNbX2H|LW6*$UPl5+z0yKU>Xnw| z5_hIT1wazR>~kxXY_-z69Z2fBT*;nPdbBQ(3GX!(x(i6AzK@iQ`ld{Rhn38Q1|!p< z2T1J80+NaGbR|0*Nc!*qAhG*g6$(1-B3zNfiHb?1F+qBB&YqmwS3S7gNaMNMEL@)4 z1ec!WWeD+?QwIF~t31nZAu!OP1;#{1A04MAz|g%kjF0n|Ov&H|Z& zpU;6;!(TTKUX?i>oPec}09r12aE2|^FRf+isyO5{QuHG%lsOANnPV{~ z8|KhJ63Uzbf8BI=W-U@7wuD41YO7F=LVXoFMQswH>|cK;E>&r}a3Lw1BPB$f8#*%;&U7artvF{}_OkGS za5~ZWOZcSN(jaRH+gZ$3P85+$G6C-?xttZevJItWgt?xudD6xoNvA6EJ2@R}%1{m@ zQMvDq?1&z6Rl6EHBI(3Km&wrsZkA-GLQ?I@aOn0?Uc|Z-h0KxQR3+=GP(OuofoQyT z^QuwMG$jMTb1-p~3b|hO<*{^_=7`N@@TlY8na%q0X!h4LV3(ADIR_3@GFkyi&c-T4 z?NMX^8cnI>j6C+Oo5#{Lye~*McVSnv2Gt@}O?@_-vvoGo6Pr6L)JGuz^?;KwxpQn* zjnW)-%sNrASJi9P$zT^-61Ntzf_l8w4P~qN-7(kBz5exdcUZN$F??YpU7DfDQHhWn z$#Ejwkg1E{$$dG+Lmv^~&+SwT9fM6qrX*+xr@7*7rDSG#LZn`*G*TSRDWcm^GLkU8 zE)ew(Mgbx$?8-p@6Wb*<@|}vkkwQL&0QhB9IvZ{*r&CUs)yZ_jf=#uNE>KhD`6GF5 zOg*`PJuB4Uf^1 zbGD(%9VMf5kzo;3E~#UbrToqHxDTm_rKc%G3HQK(M3tMy7HlvENvcjb3Z`1MIzMa1 z)=2%DSFt9|IT12}ZaQ!`bADT6!Jdr!3}gLF<76naH~e+|;90WfM$C(FxcOf=NM5?& zS`g(!5CA_Kr!yGXEdWTtP3!M)MxR69=|o{oqW<+H(o->e3Ne{%)X&L5lU)En&3+D= z{g}6ePs-wk&VIjVw(>qW)iI4k1|6Vo5#1k|w$aE)j>5?;1BkVaiA&P0WUCu$+j7Mw z^D7qXgHNh5Yl2eDAP>&4poHUyet2-3>cMRsy&Q+%Ke?h)5L!llsH~+n0r&+AIvegL zNjH5B1RHW`bWYk(QJqYeieWXsQ7*uf&83ZsDxLkeFH73s@E0y~YmS9UX}SKKZBxUq`}==~{d-&oDHrA_ zN2Mv_5b=&CPaIX1cBkY8t)JVwlUCHYVdR@`tU*hm65ZQ0lz9_?e|;D}v70kq2S_BB zrz-@YUato|ySr677%IAwXdQXstvmN&AT0wVURngvJmBUZWTqKL)~aTUqV)kegLj>U zHyf>8SZQR@EX+-CDZEq{!fVctq}+}?ID_{==EdAn2BE+3sFoCtEGn6`R{D*;xt! z@GEz8Hr!Ke71d27{XPi!?rM%!xJ}dkpyjDuKm7xMNG9n}Nn@2z!WUf7G;)|0NdKp~ zaRLsncBTqFTOk1Jt4(yNJ;%0`Qxf#9RW>a$fty6Jmd4jmBu8pc($g~g5=0u!%H$}V z+{^Xlj2IorB*LP5Q=3E$QdPcYPJG}nYqJwk!Wrxp%+7Nkms`92% ztk|%v;n;Byv*tS5#|@=l2;XSSW<4jKE4B;U_-q%(xA69f7@2yL?U87RGNgssr~H5G zFX=r5+Eeh@JIh~QjlfR$ScfN2x(HWdJwj2c!s&FaSIE{flJ#<6{2{4mkaaX-$|qrh zXvd325cvd3N;3!7f^rq2yJgYKQ?kpI%&%luDH(vafIK*40Dt(TRPv3sjBFoRw-q88 zNZ3FaI}8d{=Gv7;GqID(Q;>P52$AL^502?^emf?GSn?4>&h3a+`@&|XKzCP?YXFT> zA!qP@kbsx&4t^`|#|e1P{}*^aOTatoU*J6;yy*OXY-vQX%a{2uiiw))4h-xM0i!W< z^KG&tL?a!I_b=dN^bx86l1o{ey{HYQu*=j;MQ`0a3|s!4OzLt~Q3)|xp??_?{RXOm$~ z^gxE9LW_vUM!Z(nj@fuo_X^}XMKYji0og;&Xp`A04)*rZuhJ=Ic*nX|aq>L59fS94 zKvrvD&}y19gtNIqH0PM42Z0i?YR{_3)Gtf4Ocw*$+NOY~dKk(ym|N2VEAo%h46byh| zG$>T|l$NE?D99{zH$||xfgHzQ zPLZMqQuTNcTH+Wj!iYA6u?9|t2000z#Z_{{SBU;cXNbp522Ktxr0MD zvLYL*(4`9HD@1o8W~tA?6*;aZoX6O6_CCaQbM`4@q4eDpV$0b_9QK|Hi^{AS4Ap#Y0?YwlkFZ4@g7l zKfqu2y-7}kJe=8EIwDM3JgwsdbyEmHqY;gq(F+PJ7Gz_4CJ70yI}C+T`cLrnx}}x6 zu#qnafImp5v%z+qg^k_=u)ZVkCGHSi^`>V*Y*7Ji5W55iw}0G^(#Wbfbfj=&!h z*!CSK|1JD_Z2N`-zlOi=D|r72+loxvq$}P!`I*!Ih0;GBlYT2)NnKNJIf}gevWv0@luOKD6-MSR9&TQAGpcteq&7MOgN4?x3dnZfWeGy-PR0fh34plc3HD zovjefxe|JjLX#D`LZL+pEmJ6>&>ae`SLg|a=*B_P0MKZ$Yjt;U9hA|N5_}Ed#KRc< z#k_(0w1tiQ13%Lildz29gwrXnJN7n?hWX*RASxU}6?@gE%tvb(E+R#Lj*bZRDI8#NL^)I3k!p>ndi$5^u=&*PqA&7v<;@u@-UNIDfMy*T5IRLO6X@ZN4Ue!T@Z zoZc}2E&$hH?6tP0UfL-5Q-$Zo$*@qi`GPOf2KFD_#k@sn{81ET>)-Ljv+`dE(?XD^Myj|q4yT8iW z*7>8zq3Bo1;fN13k@urD$#@j%V{Pc{t`V*1fyPC9+jagZdZ@8z7Jb?-au8p-A3*q_ z&Xw3GTFnHN2gAhk>+J}y>KtQ1$oWvV zzNyi@$xSv-AwPQgWPBnYTj$i?rR`jx(0GMrDfB!L4VP|hpF*_g6&bywA?ON)Zcqqn z+In1}foK>Rymb8>x0W$zD{0bJB9&+o`V#=XU1UhRIEHpH6VYSaMPuwELl_#LjqlvY zNt>9UH;P-402)Om!s$nHP&Vl_AsOuu4I=Vgczfi??yrmXw~K6#WYNqOIk5YioNXv_ z)O_dTDD3dfKJY|-ihL)HDZCx6VD~qX?c8#{372y4QLw)i`5?RI-)T~c)dTf_{p$YKjwvg(`!ri53WRlg7riyDeI2TlAK;b;I;E zp`6T-rMG6ZlXDa@Tg)6K3n_FjkhF=73egRq$Y=>H?aqU;7ew!WNhs|)3!*m%1R;V( z&s_0GqZGHIm$?rG92Ny85n7@0qNWp=Vmy!z}bhh7w7gkXX4yFJS?LJaLbN*|qhP4%h@RUH zSLGUvxr&hyGcsaEM$E{F85uDnBZJXrF!~fDBW7g8jEtC(5i>GkMn(o>hQXMj7#T4m zBW7g8jEtC(5i>F}7*h?#RK>`M85uDnBW7g8jEtC(k-_LP7+s2y5i>GkMn=rYh#46% zBO`+`$zV)UjEtC(5i>GkMn=rYC>PUutA`jGln#T^p(q(KB_pO}#FUJfl2PtMd?Gr0 zOdEOYqT+3y;_P2)Yvm=YsZ&B}XUZIa-k&XRMPh72UwD&TYKkLV4~%IFu#@~UHa zd=GSo9vEb^0W-p*dNc!W+jAFn2yX6wQO&(lHTO!kH;6n`riLs#-J|u_hx! z6V)%8RD+_)hP-)%ZMJmlZ5o}ZOLd)aq)4gEE8Ywn_?Ck1K^(B}J&qq`0c2uymOeOqCRiE|UVNlI&wuk_~y$mZbBr+RFA6 z55{*i<&?W>*Xb(HmU*Zvf@t^H&AY)eS7c*cZ^^R0KoU9;NJ4j_EF^S4kc6gS3Xssv zKoSZ9?Hydv$^?;lPN|TUNjNhf!f`w+$ZJPAdnSgnE{8DEI|F|7vu4hZ@pbm3Kx;fR zh-CheLcXVmhSPvby$fp^DS7nM#?I|IwY)OL`*&%co5GmJCPWVM&l2K!zz7Fk9rvuv zhg5%YJUEc{2ONQJmLCGcvcKJ&Wb^03(wGoGu`<+OGFm%GZ-JLnyYNTwk^y?P3ZeB4 zESp#xd`VW-J!4rrhDX$fFZ?BMjC^{J-;arnzZIm+OeDWxd6pL&{t&{;$X>itXrpc! z9&sE$OK7p%tH*Z1?%`U^JpCQeZQ%=#gZup0(2HVC%?`TjcCb$9MRF79hgUPsEvil~+MLw?h-cL@^tj9MGf{Zo5t)c_mL_O< z`a~<{*U?7Y{63PjsMe4PGWR)pDjD6!O6d6t%?6_VCAW41{O!zFq(W~3`U*0yMyn`V z<;b^Q!b01|g8r`bXhT`_=!*ym%~5C&knqtPs683X@gYKFp zjnjVyihsb!vpk4!%#y7mKjPjE?HMhhdiirS&N)JNQ7*L5^5@_i-}m9CKRv}4P$b+` zLIYh|3$3CTdoZj_#&1G;iZ=iUe{uyz1ea#Fu2?h(OJMKBIj-1rsk?-67b~eos;5q= zUe3R@fMkQ5?3y5WG@=YlV~RSKS5q>Zq_4G&RC5C?bp?YjkV(k}jjEZ>S(712;LCE6 zILPv;p*ty&DWMR2Bof?2MdSz+=qWi4keth?Am3^ytm7=Np@P%Gt2mL;HGIO>Sqk!z zlmtG!`FJ`)DG|EGY8-qe2&h#oY#w`$<*ZI}8o!`s=?t{5AT6w&LfwEq1EKtcnzZam zkO`Wi&^~oM5-o6deim| z-?HRv!>BrUg)=;U1*(5VQgmNx6WmFLy(<`ncSjG2?$p@=ne;s(K1Tf1k+Ua! zB=Q3~S6aTXEZ7dD1YSA7go?^DmcCMo>%rM@9!>LL26hHseH-^^Dll|-6kVT@=1MRXM z>*y|x@F~EwcSiW6>=fRn%Bd(Tg(!M30}Tx2QgkE*Pl{6^@~nITzCP#SJ+QMkq^_fa zTStwvYWXft@hX5iLYr1#PBrbDYZ=wa6fXl211)T#f?*=c6|G#-^2BKQs^rp_Kx2c? zVxVo#K%eV{#zJ_Pz3qrE^MF#0>t`-~0%y~pTFpm!Oe__S|vMGhy(u57hsXxFL^(to|Q9!g(yuI-8e=>G{ub|%^jZNb8yzp$+Vc0(XVo$p8mDo zp1W$A_p7`XG-Tc)7p`%KFfP27j99)WoJD2?GWu0f6iOUXDiEcLqR=&>RMgTPRkhjF>9xj{uUS!;!S3UyIvfI_1bnhJD) z+vjqi{ft6DUoct)^f{x|K!0Zh1GF``B8N$Z5zSlNj#Ke1!p{gm19gY9ej&6cfa<}7 z|C2M|+TfU6RrVu?2Qtcz2snR({*7F+(0GqbypQaVmZ!A-Zs<-i){PtT;#v zXv+T#r&H6Z=|dEIfy(H;hj6-TzY_BfX)cRzMoiidM9i1N=~SZqqKlq_6*N2&#oajD z6VE{6W~1GP78tcO+HE!1b_-`x!pm|0rMFpb=9V_g%{->fLYE%G7aemhKBG4KHbAX$ zlpAYJRtFt;d+MM`&nVh!jSGD`HTY9f0AG~hdU92SCdL>??KcGyX&2^d=`?&Mh6~DZ{ z8)FG?X_V0vnzKt5%3)gDY0*Q@K zSor=WoJFg&$dSVRN0woI z{F$qCz;!v>ig#h(BExgj9oRXT5IIovc?ur6U}qTn`)&C-GJ0T2q_T5#WKB{e>f8c( z>*!vWb2C24bS8(v=&Y1Y9=>FobccrL;w$_?4qAjcDj8gr@_zW?r$`#DRtqx6Ybc56m zHxMK2j7b(o?BVE)jF^$puVQpr7_n2NGcsaEM!$+N)xwDVD4mfJGcx*Bj2RY2?0V^p zjF^$puVVCB7_qmeGcsaEM!$+N*TR^q7#T4mqXsg1N~_SGs09TrtU<-fh*=pCt7rLY zL^*hUz3s5UEDdgl|IXY>U-4OT>Qgyo^c!pB-`{Hf{Vn_7-~0ZpBgCLzH;QG%jA9tU zu$$+_*xPnQZvQBDR=u883y;Z$UeRmx`Zx`aGP`9cM0<2{$I(%t9tw?6Xf%+-r5Rab z%u;B+3SF#ZB}!JNWIGk2^|A2LN<|R;f`%~Dego|hcs05s64VOUg057EcKJj`FSQ7o zs?bjgjmAEigx;&rcM1)~+$Ev6DYRdqzL+s36ozV3aD|BEcvk!o7GTAh?uUTh(JDyo zlT7n=VClFp{w)B$h24bNQvYWsW$A!LuethF1;+X#y=elL30Wp-fB$b6dUJN=d==j5 zj~sBmlk=57@^$}1OWR`uWGANf$ktL<GXV~_>5RyezrPPyQgwKV4 zz~I{X`Of{}!apDoPaBhVevU_&NjvxZu_{R_9bQ{HsW#9m=PP~3z02r_pa(O%?EJh2 z|E~c{WvXCP-0^_Fa3GqOR^bSol2ajX>tM@%^ajXw?(JCVtm;^a_-$)Wt{ZBGMfm5s zutek!HjTAgWI!p^k?|Qe7Ixk7;?cRNl>sQN(>*s;qViC0y|Clulc>9oA#@nttBHP^ zjFl0YK0Z6Qq#%1_O$HWmxv0Cgh%pR%)!h**8#lf8P(eg~C_3(3Jia#jSzKr^pf#Oq zhDJ8;K9aMo=tw)yJ<;%?0kcp1f6S?V1Oqwrb-^-sUkJA5I|Qi?kd`6F$| zM5-dYx!faLqX(MeJ5dy7AFOwWWzUQrN-x50;6abS{|@9k&r?i~1h5C_qn|m#I1)VO z3UrRVTlA@?=vXRBV!%>IE{dT~@vZ_-(bDVzsY_FmsY+`cxuU-`yO%3)8dOe~I7_kY z$td0i?PH|-E$NbowV{>`Lq=scL$yq}k?h}n2-zEj#qkcw0;L%o(AW{kf^vQya+*I@ zK3;~N53-S%0cu>hz*}Z`PbNF%@Z9X?;rF4KS6mUgEW1U47u%z!zd(0mMW3bM)f~ub zQV@Q6(cY9&?+&2x@&p_gNRHCzgVl0c(HAKkt8;ZtGB64sfiTyVM2qRnq$<*!ssHOS zvWDiOg6u9(>pr~W*IZ?DBGu6&PSjKXBY}YteyTfI&loK3zkTT+Yffd`(LWG(fW$oz z_RhfuE?S|#|FJ;w;QoJI`UO9Ql*d@8DR2L+sKo)ERkQJEU!D<60 z)EtLfqj{_)qX2w)vb79IVwf}9T}t+x^A>kx3(Nem{%z@3?U+$4^#oUSNjD>X0+4LRV3XR3ei7M#LtX_ZxxV> z5&cV4C!;k$NsN#o?M_@#$w9z#fCC^!D}MnZ+{Ye%Em$BAPciS+*48BR4`N04rbLgV zM7EZ{1T9i&N{@zjL@KRHkxbf_9S7YB6QO;$IykAoLk;Qs$h(Exnaz#ngSv_IrcI>i zrzz26DL+gk+K_C&<$tNN8HgbQliIGf# zf>Y<8Fy0%o&ef6kxp)4!8$*&0x!h7%bF>`@esY!$XkAXX{`F_k^W>K3r>RaJtjk9x zRQn>;SsmHoFCPLef8>2XQlb)p4M!qdq(sv6D=s}WcCWvD1Z!iy_?)#-F5gC~4Q;tH zv|FQZW^~>fiDFns?fkf-lZLEx<$N4*I-~yLJq4+SZ|TLfpNh%z2|Kp zt4XG-iTWc-jAu0RWn;W?{^UF~LUsc%M`d_c&A^_kj0Z7aPST19+17X>0`YVnywIinJA${6{2r`%r)gLxI#xF$GxZt_o6a-*fVZ|#q`7)i^rCIvS^eFG@YZ(ahi{7`(#mHq)-~=I21ox%zGRtp*~qO69=02$vTP7 zja7)NPZlK+$n2BViq7fd>LEoS*+zkO&SrhGPNu*{Cq{v#RSslXqJb_n3lJMn97c01cpXyZ9abx6H^vYJsy+BiEW%%l}AnQ5c+6wgBO^~q`r1yAuMz;m1i z_2jDmda-hC{O>3^YBW@8s0>wNdSk114{OULeBvS^Cl(RqR?(2 ziTk0F{avB&ROm4!OF|(?y7a@&!t7NtS_w!fJ)0Ni?n*{`%o0iyjfB###fglXuOL5= zFb9;3Rtyp&qGa@3Qeu>;P4k+|3ki}G}N{SslO zFH9uv!wNkMBymxx+D2UI4*A2w_1KY`hF^W8rl$rnr2N{kn8)z?yOlnK#~m~^Yi|j21{e3hR@Wre(T6d>lnSC07+|}sL*sEY0b1pC83KH zx*ka4E>|*Igoxf9KoYl1$sSVZ85K%*L=t1OLRd)Z%ydU2p`R#p5J;H6S2A-9O-6A@ zD6O+3?#T*KI}@Af7Xl@8D3HXUTLY2NeU+fgfg}d4(L_c!`+^p$(4dmhvpWf;F;tlE zQnLFL+Mq&TR5E(=N#fEQ9g^;DCEKIW=Rm^zwUQlHh{jL}Z44xQ%@t|`B+S`L)~-StR&=>jCJsjotVRp|LjX0F06hfG=%?RZPvs}=ga3N2Eyh(c?CBwbpCN!8aG7N7)VlUrBFK+db*OCYp?#0i7mADlDOtr zaG~p)-|iu0nJ_CF%Y_$yO+|8c3MeDp|Qg zkE>969>>if6!hE-q-LDYslt`#KGgqom+9}aMEt3xS6+D8?X1thsTRmr+3)K7&DRk8~dnxsPW zm29>`bbl$#02;ME-EoPWAtgdv6skme>X~k7ZdH_#0yeQxUI{X$x))K$&tV4@dX_?F z4k6Mgm%3vsyNQ*nAfp|5b(a)a@M}k7-guEElBakr`1G;0g}%*g+3NU%jE{k9|CO=P zl3t)|{Iu%X;GIm%P1^`{GGtP+9f72!pRQ!R6&k2QX-9&dXn3{Q79%YAN^cgB$QCL@ zs}MLf2Kw~LY65~l6QST2d&B7@ z3THNke>~c6dx)^%)~2VQ&G7S5!^@ov$O{@VlI;J|(`4?hHNp^DKes!WAm zb~)l`!6j`Rfs;ZPw~=pxgV(in1RBpiRIBHODROG*=`KHGm6ZA)^OQb?$bGWNv;y2N zkfHLfdvM@oz>YvG$!$(WbbsR)H5lYP_QRu7Cszq$McK{J!e>*9uh74hVmW(;(tqY+ zHPTJ!)Bps4+S7YabA@Q&kU77-LR}TgQK*kX)Q=%}6dD8c1rD!viIUNrPfz{5 z{Hxp-;mWPieYwQFQ6Y2Ar~C4u9OF+av4S z?Qm=bwXQ(IXTC8p7&5WNoc$*#J(~R`Mgb6wSze9q z#znRgXfV>i8xBCUhws&H0ou%#(rTV|#k|@*O7;K{-CujPN0sbpAX=$=`TuuH+zQBO zj+gfqMfN6SG|PFlT`KP1fM`zfYM&_CejplIyxNya_79+3$lTfyph1j&20Dik4G;qv zxqt>RN(JiAC=I9|qYNPWWdJwI0sOeq9iu)7!T*}3qQTpUG%Yj%sxFDGU)*{9828U3jIN$h(h-$^oT;# zFD34)3RNn!1xWf9?V*X@hYB51$n2s2P%&sXO=3`A6+|m_K|X~#0ZAH&s&&Sd?zpX; zCv6SCQN%CS_y=l93!6pwM+5O{Sa^9VHR-BICaw1PO+EbktE$zsN|kgvC`7Dhkq2ia zLjQvUEjflgQ^@d*M=DYXt;(>ZKtfI>lxBHH#7vD=!jdkfayEHzoDrPqe~!pElX%q$ z%Ycak9Fsi7%V5le*;+6~+9IkD|1X20acko_oj)3uOCQMAr<$RfPg_rU=g^|pyzA+f zoiB2}+UNzI4Gkj{zfE0wgQLVfoPK?}Hqz4b-@p^M=yxB^k7l7EAma@@$rbZ zbc_5>M@}t$({uSAyvUQY4R6n7e3*_ggzW;HIs{KJq4GdnDK5GBGVg5AoRY!jSZ#u|A2_r$Qfhut9qF>{x#81Hh<6CUL8tg9_aUA(Wp_28URYUNW&$&gl8OT<~ zNAG)9b-=ZlK@%tbC-7bezU=tn(a1m-U*>8WU8K@Q5FTAnfxj5yiw%2AvZ%axLAGux zP)XLs@T-$~VN#uZIW9b*tbCk8S<~QSokyzz{6k9`u96+0tTh~V8~eN>EXlf)G)l6l z$ChN>M;G#+Fq1%XmxPtcDU4Gn%g_E*?9XL?0sHgWr|tGo);#vVWdA$%-)8><_CIF- zGxiU|FvM!L9jI{UOn2;I4Z{dd@>LJQsb75jf<{}cAVhwm@B1pl7oB%Dsg(XA+& zlv{X|EM58}cuxmd?{LUJX@+5|C|*`6`!}(FGyAWwPva7bVk2Kv$VH``UXxQbPNA%= z@Jq7ZU`%@mp)6WKg!miWP!_GvLs>tve}sLs2}q8y{}cN^v;PbG$JwVghmZMTs((F= zXQ8YV_EXuXy@*g2E!43_hM#lzC3->Qhet#A(DsAB*!EcfA$ARz&UctmD4CWoiC@6a-vO2P|#BcoQBBhCD@HC8r(x! z^k!U$-(#GD-$SyDTe9|S10^30FaJM28NJR_vR*(U>#Jl#m29Mvja4$bxA)=jYSbGf z?o6O|ETbkWvH*~eW$Tpe5rv{alQCZ6e_}Z_?Q$UeFCvA`RcH;+$;|R6AYp!3A=*h5 z8Qq!+qBWHudNW1PhYEeF&;fkdxoNSheCHNv|gb{ z6xyH={lbjIeMKSqXh39J75b|}Z!1K^ALJHla&>DsQq)?ec z4=D7QLVr={1%);$^qNB3722WDy9#}z(B}#rR)}8Om2ydT87NJm77CrDP&Dbz)w z9EJKRG+3dL3SFeoM1?L_Xr@9}DRhlOixq0d?x{f-FtkEQ@u#69d+D0$)L08*+#guk z9uxP?k0QjgybONw8z0x!79F|3vy#SrY=eX##BZfl`aTef|_;n{}x!xs1IbB7)`wVe~Ib;=Xf=ggGT@R#;ctR zGzm5A)kXo)-o00&T@#v%z1l>ep^PR2jb)S%bQz;rK+_n_0rE4VCD>Jr3V^PJ1z!An zKI7hv?#?d4;nvnFL~SmGWlt;gGSFje-(DaZjb(@ADMp7NyNT1FRn47@Xaz%WA9*z= zeEKggUd;IgK7(dj^UF`}K6az=DVPNSGxKGLSvy@%LAhCO5ECbpsN{O3^b1smEv4R`9N1OqUWqMqPn$bfUaQl z0+654D?qatRRGZ#?ABfbn!yM~pl!t!IsK$fM~L+E$X48PpsN=irOx5GnZ|t2a+()P z3$;&bYX=q~nr9{b7H*yHj!y_u-CHX0~kA`lOTF zw9PuDov(d|j@g|~J?-=}&g|T!Yqzty_vo3^=ilgh_5Pi)_4l7CYRO-!?ozb>&b6_m z;xj#YqPqvT)(_|{M#F&i;_zy;8$fSDc(r_>b&O~e>On?JfgWQN2BKXWuSOeQHH;pB zk4YJ_XW+Y7uM&t>-Cm7$py zcvVB|7B?e$$Eyh=T7}RP5HEf*RnzGCl2=;-pY|WT+6wq*FY2=KcA5w{wziX@aHhP5&nEe^pKI{cvc0U_5r-SuKX4y=ha@q^*=nXtP4+El! z#;Y9zq8)axmWpNEaz-tI7O|!HFDkqi$A1wAD&bK2vuQN&o zqPumsmIkzqQ3lXfMqZ#Tj9LR#GinR8nUN2O?)mY%mOxdEP6wirb8B6IqKvu&RWRxW zw24t4Alf-_YXg8@Wt0o_3Zr2_FEbhm^b(^{Krb@N1ET#0lpoOZj4lRxj?ra6&oasf zqWW}eGl8CFG#iL^G2Gf*pr;ru0NTK)0O(0ZOMsqWv=r!ZMnNFj3&B_IK#wvC0X@QK z70|kx>EAEsT}`t!A_o=w?Pipqm&i2P$P00$Rmr6;OoHY9Q*HZfy-v z38OoKiW%Jnw46~HP!Xg1fNo^;5Ktkb$AGA>yR{8K%NRWaw1UwKK$0VL5-o>rf#J}# z+1&u06s?>8%DJ<2$#F~*S2z|d2%I%<-j(ya%~(LsJm7L?%%8WQ+m$oj9h=}&e)_F} zZZj9ono)2qM?@#b9r3BG3HGMbX%d3#HhmEd3hXFNr=wSzei?H@ht+x_gmu6?tzeoS z4g(Quc8s=haXLUMh2xMMod?uI@!*2LP3^8rMCW=)&x(<(fuviE=k>aQ>?~T$+Z+KMshnz;3!6t)~#UHk^;V#-8QGA zyB>DO#kuF3cjYhYv0R#uV$Ga2J#a<#2#ScNk5bKmud86!j$~G5G#uz`fZrTPu$)#6 zhBoc;lXGjtJayi*xpU{w5D`nPX;G7lP0MXdi)+!54^6US*hfRIFw>%S2Dwxlb0bJ& znNw}dC`Rb`;1f;$ySH9qGSj;m8{3#st!1G5tF(18vi_#IbUaPZewm?V{UF^_Qo);8UN$wCUZb%_S%?fKRwoFuZ_7S>-gYP z8C)A`KHOvu>&z`}%&j<<(RcjkPPw+Fjkz`J1mROln&as`$Yj1(XKu~R2-cq0C7P1Z zQyas@_S};oHuKe})6&1Swxv$b?wpR*@G12^m+#nMrhZ6gK3S!eL_-?8x}!uJNX@iJ z{1Psh`i^@iH2M!8}lB zKE=k|j$;|MgA2R`M3z}cHXp8?j(qrbn=jFseKzLy9Lvh=voUvIoxSj>&-|l*&-+cA z13GgD8*@jFWo7PQW6oxsz3_>-NB;LWn#{BkA(w4q?gXh>&cF11?}2O^GtJsE&QojI zxcd;c&K*GHXcb8ARAweb>sxWsTFjaHG>Dy!ZhGjRm+r?ZL2qo@+j=b05g9$z5=T7b z&Q=oAv9=bP=gnM@?y0t1oDrk5ukUK?92vQopfjIgE1xrCViEHhHs;Q(lMA0(OK#t_ zr6%*0I&)_ma~F06w*FZS)hlCUddQ+||ZRB^+BCU2V*C4<(~975qv4 z&cyP?C=LFpA4t!#F?Y8ypJik2!8*C{sWdi^p=S{W^A_Fa9yaEl9Lri7J#5Uh`{8ut z!Kal+$#qNio6KM7%sDpZUN+_&8*^{g$%jwtjCVH-u#`p%$_89-8}siVjV&*Ra%mZx9{cX$xStkgeRxpDm9KF z+L$qYLMI5HY`*&Xv$3`103x?jXC7o@&P8Y}^B^1ZVAfd;pKNxgx46k<{!wQhY-1i0 z!`$l0g}H-m%tKj+%%l;!d&i$YH<`1jxxfw8naxpj7^F@I^ytTLHf>dbjI<}n=0sKIxl^Ec+%n8&hCK769t-}5I-xhNWTXX?yjnVCfA=n~DA z);NU5*6CPVTH{$K7d~|__jMos-c0Laoq4>Cc>>2Wa)AqNyp5UOBaj({n6G(w3AVG1 zT+G#(C)$`NaV#tIL>n`@iiP=(TaR36G6!|$i*3xf)vQw*7u%RIL_()K`8dKwi=!s< z8lCx48}nov^QAWC%UH(;pIXbZ%17QdnIF=bFS9XU&ateeahZ*I3hVgb6Z2g^kNVJL zenn@VVq>1lv8>EfY|QzrGt z{=3dR-NrnFV_BJ}+n8svPIsMo!mz&tP39vy^GqA_EF1Go8?!%#dDOT0KbXvEv@C%0 z+nBF_)a-+8Q|DFqZOpS-CkUVB(_%_wHDlQ9Gqr*!d<27Ib;B z5-bcy#7a;kv}!P7<@D)|MGcjfNUXbj=uWViW?*vPRW192)DvCx((NIg*jW!lwk4;e zJKL6148G9u!KZq^IcLQlGpAE@=BsRFI2XER8R9~_%Emm8b$sxNdFJe*4kq(Loq3*( z`D%`3ZBg@V%=1}i0sKZdZYsHKsmZ)TXP$3kCjD5O=i8XCiD7aCe}>$@#&EGy5EI&+bYdAW*ZSW#qSE>=3kJaTHZvuX2Wow?Y?yh6n? zn2T-9D_JKOK9$Dj>tC^~Jg?T7SK63E9Lw5MR@#_LSjPvS#=0ZnR?|(JZ`7GfY|LSf zWo0h0F-KU(2cMYRtWNpKWWHTzj@X!2aV#ry#Kv68IzITs{LYeb|1g;!(V0ta%r|i? zD|4xh`DWJf!6)W7-aDza$-Gf#zS+jSnqyg+Z?-Yt5~H(c+0W;i%)4~vTWrjKjERK{ z{8tEC0bBPxZ)F`HdU=C!QToqQawhyUEw zWNxQ3ueC8_5U<0$*2es2*71>#*T_x zk$=gcB0vWax%oPCxs7=pLSt<%w=u70om}|T())HD^t8!*qt3kE#(W>gvf8}f#(Y2P z_~28kduiO59FzHWo%wzn^8*~q%6z|#`9ap{t}|EMZ~?lzQ5uiv%n#a_AF?q&Xk&hu zb$mMWjr;M7^on_-&it^A`4JoQ!#3teW0-U1ZnNy|?9!PZwJ|?tV}8`e{5b0@fKRQi zZNEGeo>3ZK=**AXn4hpQKW<}wl68FWX&yXxV@I+L*DyQHS|e8}laC@xdqNoL-OPWHA3pXWnFEu7GZ=&6{k@QP%On zC*~c|36}emCv@hhjk%IzS<5+UW3FNyAADk7G42t|>Z?*`uCg(|#<8r-RW|0$tmA`E z%uDyJ#4U&eh}^q6^JW_}hJZSyvDwDFg>`)JiTTV$OJIn>d`M^BVq@OQv8*<4u`zE` zI>h|g!^bg@7|h3Y=503S?JAa`yUoV@I_vo06LV_m`aF}lSsFxeuiKd4fHbykyl!KD zlXZOXi8=7jsbfs$Y@PW{8}nZ|mbEnAv@v4g)I$4_Q_PD|P1gY|QW5 znBTK8e-NYd<-JR=pf*b5&pPu5Hs-&@#KML4!T;CT`36T-onbr+BBG@bC{jcqKqvyG z?w`9!Xp!AWB7`7D#{lJnm(6Aa(PTH>-4G~hspI%(I(3|mOr5s2d}wQHEn2l!9aF5j8un$-f_v4;%6UL4H%Uva9ZZARlDp{DOT5_dK68)x`5nn$VUYEJ=TiIM+EsOi}}u; zb;;K3qb2(T^*30G2|11{2xI+A;_Pom;t=fy3up>c3e=$ z@EvV08}cWD{3-VGIrxbnpHwlP=iSeYvF6|rLp~|Up9%6wK|ZBop2BM_zJB!F?F$3X zrw#d(Ab+k}O~k9$zf*#ITE%qWmCl1dee(H+AbQdlAz?c$$OPosI4#IA6+?L*hp*xJ z3%3R2d4?Q|)uGz$zh@i8$eqgkf3?kfF*>5pG|(qaA3!X%Qu%3UKz_c@m4yB@To98+RyVPjbQ*u9!j+_c(nZk9K@Pvh zVjSdohNU?12EIfb`AV+9;Yv$!;!WuL^}b?zrcc6h&r^lxX)0zTPBC@xyyeKB z{~CDyx$!(rdA7+H2=X*Ro~~kcfl6odM?Sysu7JGPkf#gsg@Qa?kg3i_$9CZ|Z#Kwp z&VKCKfV|(3XDD+0>XiDck0h-zXhnI3f{f9>dt@od{4`5RE?I*5nP4eSB86FS8;+@4 z+1Z#WJkJoGXKBwM(!%E6Lcei?q_$JW^Q>5Sm8cWsS%N%U#XJS_O3)tN_UmH-`O6da z5oQbW96_Ef$a7Up2gpl-x#7?y#em#k$a4j`UXbSs@;ntos{;~WbL#1{UJl4t8}d9s z{)!;a6Xf}fy!!s(O#!)V$nypHB0-)n$O}}=FkZ>?oTU#p2jn{qd4V7=6yybhyhz3D z0F`cG|9E!`4gg7QyA63!ELMjLs@5A$d7?97Y)kjDu zGUjs1!3uc@EvS{6-6=W~y~-7=^Dl4(tLT$l!D{>vS1{jy!4<3%maagC|9;OkLB>jkoQj3V!V%<@ zAg47MRB~QfTKjxJ{+=PH1-U_x(}LWnVzP!@cl5X00`fhE+$hLRjC|A1W1lq&@)8w8 z|LXXSppSoc=c57ncZR$~lgq(JcE7G#(V2?2CvIxrp!-bk_L^1{qepPqD0)m?x2Ia_ zqe$AqdH#kX)0DtBYFi>aFI6$L9-<6uZo5C%6GXpjj_DyCLy zl+(1fyu}q{<3+9@8+({S*XqCG3bJt*SJ3etTtPPaxPlQ}Zz)bH4uwAX?>U5mjP0?M zRN8?;&v^7=pdg1cxq^O8q|!-vPI3jF>$w8Y=W_*~&*2I@ ze~P8ZJ37el{2o`}XCGJK`9-cE&wIH7&yO&L?xg71EWxo7@O(E{;F&&qY{kIy^<07H zB3IyfBUj-0Dz3nD3s>NoK2L5P3!X1xN*tc)X^ufm9G>Zu^Oge7pJQ%W3Opa<3Ov8b z6?lG$EAadrSK#?EuE6tsT!H7G*os4U9CvU9o_BBsp37W;=WedR^IERJGu<=#J#}au zqqCW%z%!jwECrrtas{3zGNlQgM{xz7Kf;O@aGK!x5Le*&6|TVZU$_F#d$H-^`Roc;3Plc;3tvc&0N^(2GWR#t*t}1)i5#3RVF4q38K{t)Rfq>-fo; zR_yad23h0hi)HG3F=-OcikWmBB9j@7lpi)$JPW=|P)ps-wBJ8IZnQHNQDP3?&nZE@G^2B?dw={f({;%BJWo zAxpV_t+{k<1em>JsN7pExC5oi=8<;vnH`(E`*Us;*AEp~a;w`03T~zM+Xc6p>*_0b z7BknDwhiRE6L{aLzjZ6sTowC`nXXN46%TnaPCA-Z$1?fBa=B2fx|IR4LycW`uvpCX z7my;fq(kR7=ZeJwx#?)`gy6r|WNL)oj(9ZB2U_c6QfdZzw-)-`JXpF1p~F&0zORrg z^FZW#{RW-e-ePan?~n&F`_(89IjOC2JwzBIj1LVxiAWKR8yAyNVk$~>qQrER*bpT) zTB1tsz+kmR-YmVp(65VhQ$xBb0nC-nt?jM&kNUA`tCEn-wcc(sPDH7e@&kh*l&Z9> z7Yr6U->zYzvP{P4Kw_UsT;x8JzsP+ijgk9IHff(3pk&;iSnzDHXtnH zF3-C0XVO7ayl=zTs!S@A?krwcEDaSi>6XizGijPY*_sTdxr-FJ z`E97LO14rgR8U6!G}kFJ?c~H4RmrdQ-y#O7_79fVd8QU>iqg8`=DI4SzCoHwSYXtE z1^ar7-M#e0q|iP#wd0IH%Zs6hqHNYkQHe8RCEPP%CC`YJJR?@>j995NVmW8Taw1qO zQ5Ki=mMhhDdg;@PxnE!%*%d7-!}XPqtS=&|0z-Xu4q$~XkkV`_VNI!wry~WmA|sZU ziq+oYU}>-t71d^{W@L^R@xM8WP0Ob);AA3hO?F>1D;bsDmfr3{$*mNsGy(cc-KwV5 z0_;bdC61y!Eon^)UsLB>U8bIvvX%u;i<{Na=Ea+Wr1)`5A~c*}y&?4Dtfj=)BK#$+ zUhDPcifqTKRV~?ioafV-bf&ZSYEES_JJr3s&j#a>yMm-Iyvv!RzYCaJ|aXgK8H zv!UU9Koj|ZCh`F-oDbrOk%bnnsIr5CrsD=yNK#4SlFCsaA(ionRK~-pq`0V(4WGd% zzp7*G5KST{$wX7cVVfcj+Z1uwgvg0~MQYV%RJDh5M_03Ya$6Tg(DZqiX~~Fwh_Rql zMeyPgJUwQ7Wzd5b(jxMbh{{XUa40Pp4jLgf;kl${aUfCQiGxBD2Za_sD7Ceg6g@qm zg%=8{(6Bj3VRMi|=BQz45+mtJ;SHMb22FT_7WPIwF=?TRNefL(T4)gknv7VElM#iI zj3|^;MB$|(CQvFoW@RTHmA%jurG$o--65}`u0(y>UZw7`)cR(xf_Zh+pmA)z{3Z>jc71=PnJauZv_sz!y18n#+}nihel_Txd^K+!VdZv!FSI^mz_D1%%lFt<>S$>7I6}ObG zE3{p8CA&jZ<)ur$rMEKBm)qty@GlGfOG0Ei3?=xoD{y+6b*wduSJYP>tQ5M<`Hu7Ts_S3ds{{NOsoUCW diff --git a/bsnes/ppu/mmio.cpp b/bsnes/ppu/mmio.cpp index 4a515a37..3d3a549a 100644 --- a/bsnes/ppu/mmio.cpp +++ b/bsnes/ppu/mmio.cpp @@ -1,14 +1,18 @@ #include "../base.h" #include "../timing/timing.h" #include "../cpu/g65816.h" -extern g65816 *gx816; -extern snes_timer *snes_time; -extern videostate render; +#include "../bridge/bridge.h" -ppustate ppu; +extern g65816 *gx816; +extern snes_timer *snes_time; +extern videostate render; +extern debugstate debugger; +extern port_bridge *cpu_apu_bridge; +ppustate ppu; #include "ppu_cache.cpp" +#include "ppu_spc.cpp" #include "ppu_dma.cpp" #include "ppu_screen.cpp" #include "ppu_vram.cpp" @@ -27,21 +31,29 @@ ppustate ppu; #include "ppu.cpp" byte mmio_read(word addr) { -static word counter = 0; + snes_time->update_timer(); + + if((snes_time->hscan_pos >= 274 || snes_time->vscan_pos >= (ppu.visible_scanlines + 1)) || ppu.display_disable == true) { + switch(addr) { + case 0x2139:return mmio_r2139(); + case 0x213a:return mmio_r213a(); + case 0x213b:return mmio_r213b(); + } + } + switch(addr) { case 0x2134:return mmio_r2134(); case 0x2135:return mmio_r2135(); case 0x2136:return mmio_r2136(); case 0x2137:return mmio_r2137(); case 0x2138:return mmio_r2138(); - case 0x2139:return mmio_r2139(); - case 0x213a:return mmio_r213a(); - case 0x213b:return mmio_r213b(); case 0x213c:return mmio_r213c(); case 0x213d:return mmio_r213d(); case 0x213e:return mmio_r213e(); case 0x213f:return mmio_r213f(); + } + switch(addr) { case 0x2140:case 0x2141:case 0x2142:case 0x2143: case 0x2144:case 0x2145:case 0x2146:case 0x2147: case 0x2148:case 0x2149:case 0x214a:case 0x214b: @@ -58,14 +70,11 @@ static word counter = 0; case 0x2174:case 0x2175:case 0x2176:case 0x2177: case 0x2178:case 0x2179:case 0x217a:case 0x217b: case 0x217c:case 0x217d:case 0x217e:case 0x217f: - byte x; - x = rand() & 3; - if(x == 0)return gx816->regs.a.b; - if(x == 1)return gx816->regs.x; - if(x == 2)return gx816->regs.y; - if(x == 3) { counter++; return counter >> 1; } + return mmio_rspc((addr & 3)); break; + case 0x2180:return mmio_r2180(); + case 0x21c2:return mmio_r21c2(); case 0x21c3:return mmio_r21c3(); @@ -87,10 +96,28 @@ static word counter = 0; */ break; } + + if(addr >= 0x4300 && addr <= 0x437f) { + if((addr & 0xf) == 0x8)return mmio_r43x8((addr >> 4) & 7); + if((addr & 0xf) == 0x9)return mmio_r43x9((addr >> 4) & 7); + if((addr & 0xf) == 0xa)return mmio_r43xa((addr >> 4) & 7); + return ppu.mmio_mem_43xx[addr & 0x7f]; + } + return 0x00; } void mmio_write(word addr, byte value) { + snes_time->update_timer(); + + if((snes_time->hscan_pos >= 274 || snes_time->vscan_pos >= (ppu.visible_scanlines + 1)) || ppu.display_disable == true) { + switch(addr) { + case 0x2118:mmio_w2118(value);break; + case 0x2119:mmio_w2119(value);break; + case 0x2122:mmio_w2122(value);break; + } + } + switch(addr) { case 0x2100:mmio_w2100(value);break; case 0x2101:mmio_w2101(value);break; @@ -116,8 +143,6 @@ void mmio_write(word addr, byte value) { case 0x2115:mmio_w2115(value);break; case 0x2116:mmio_w2116(value);break; case 0x2117:mmio_w2117(value);break; - case 0x2118:mmio_w2118(value);break; - case 0x2119:mmio_w2119(value);break; case 0x211a:mmio_w211a(value);break; case 0x211b:mmio_w211b(value);break; case 0x211c:mmio_w211c(value);break; @@ -126,7 +151,6 @@ void mmio_write(word addr, byte value) { case 0x211f:mmio_w211f(value);break; case 0x2120:mmio_w2120(value);break; case 0x2121:mmio_w2121(value);break; - case 0x2122:mmio_w2122(value);break; case 0x2123:mmio_w2123(value);break; case 0x2124:mmio_w2124(value);break; case 0x2125:mmio_w2125(value);break; @@ -144,12 +168,23 @@ void mmio_write(word addr, byte value) { case 0x2131:mmio_w2131(value);break; case 0x2132:mmio_w2132(value);break; case 0x2133:mmio_w2133(value);break; + } + + if(addr >= 0x2140 && addr <= 0x217f) { + mmio_wspc(addr & 3, value); + } + + switch(addr) { case 0x2180:mmio_w2180(value);break; case 0x2181:mmio_w2181(value);break; case 0x2182:mmio_w2182(value);break; case 0x2183:mmio_w2183(value);break; + } + + switch(addr) { case 0x4016:mmio_w4016(value);break; case 0x4200:mmio_w4200(value);break; + case 0x4201:mmio_w4201(value);break; case 0x4202:mmio_w4202(value);break; case 0x4203:mmio_w4203(value);break; case 0x4204:mmio_w4204(value);break; @@ -165,34 +200,61 @@ void mmio_write(word addr, byte value) { case 0x4300:case 0x4310:case 0x4320:case 0x4330: case 0x4340:case 0x4350:case 0x4360:case 0x4370: - mmio_w43x0((addr >> 4) & 7, value);break; + mmio_w43x0((addr >> 4) & 7, value); + break; case 0x4301:case 0x4311:case 0x4321:case 0x4331: case 0x4341:case 0x4351:case 0x4361:case 0x4371: - mmio_w43x1((addr >> 4) & 7, value);break; + mmio_w43x1((addr >> 4) & 7, value); + break; case 0x4302:case 0x4312:case 0x4322:case 0x4332: case 0x4342:case 0x4352:case 0x4362:case 0x4372: - mmio_w43x2((addr >> 4) & 7, value);break; + mmio_w43x2((addr >> 4) & 7, value); + break; case 0x4303:case 0x4313:case 0x4323:case 0x4333: case 0x4343:case 0x4353:case 0x4363:case 0x4373: - mmio_w43x3((addr >> 4) & 7, value);break; + mmio_w43x3((addr >> 4) & 7, value); + break; case 0x4304:case 0x4314:case 0x4324:case 0x4334: case 0x4344:case 0x4354:case 0x4364:case 0x4374: - mmio_w43x4((addr >> 4) & 7, value);break; + mmio_w43x4((addr >> 4) & 7, value); + break; case 0x4305:case 0x4315:case 0x4325:case 0x4335: case 0x4345:case 0x4355:case 0x4365:case 0x4375: - mmio_w43x5((addr >> 4) & 7, value);break; + mmio_w43x5((addr >> 4) & 7, value); + break; case 0x4306:case 0x4316:case 0x4326:case 0x4336: case 0x4346:case 0x4356:case 0x4366:case 0x4376: - mmio_w43x6((addr >> 4) & 7, value);break; + mmio_w43x6((addr >> 4) & 7, value); + break; case 0x4307:case 0x4317:case 0x4327:case 0x4337: case 0x4347:case 0x4357:case 0x4367:case 0x4377: - mmio_w43x7((addr >> 4) & 7, value);break; + mmio_w43x7((addr >> 4) & 7, value); + break; + + case 0x4308:case 0x4318:case 0x4328:case 0x4338: + case 0x4348:case 0x4358:case 0x4368:case 0x4378: + mmio_w43x8((addr >> 4) & 7, value); + break; + + case 0x4309:case 0x4319:case 0x4329:case 0x4339: + case 0x4349:case 0x4359:case 0x4369:case 0x4379: + mmio_w43x9((addr >> 4) & 7, value); + break; + + case 0x430a:case 0x431a:case 0x432a:case 0x433a: + case 0x434a:case 0x435a:case 0x436a:case 0x437a: + mmio_w43xa((addr >> 4) & 7, value); + break; + } + + if(addr >= 0x4300 && addr <= 0x437f) { + ppu.mmio_mem_43xx[addr & 0x7f] = value; } } diff --git a/bsnes/ppu/ppu.cpp b/bsnes/ppu/ppu.cpp index a2745ecf..88f8ddb5 100644 --- a/bsnes/ppu/ppu.cpp +++ b/bsnes/ppu/ppu.cpp @@ -3,206 +3,129 @@ #include "ppu_render.cpp" -/********************** - *** priority table *** - ********************************* - *** p = $2105 bit 3 *** - *** o = tile priority bit *** - *** s = sprite priority (0-3) *** - ********************************* - *** p = 0 : p = 1 *** - *** bg4(o = 0) : bg4(o = 0) *** - *** bg3(o = 0) : bg3(o = 0) *** - *** oam(s = 0) : oam(s = 0) *** - *** bg4(o = 1) : bg4(o = 1) *** - *** bg3(o = 1) : oam(s = 1) *** - *** oam(s = 1) : bg2(o = 0) *** - *** bg2(o = 0) : bg1(o = 0) *** - *** bg1(o = 0) : oam(s = 2) *** - *** oam(s = 2) : bg2(o = 1) *** - *** bg2(o = 1) : bg1(o = 1) *** - *** bg1(o = 1) : oam(s = 3) *** - *** oam(s = 3) : bg3(o = 1) *** - ********************************/ - -#define debug_ppu_render_line_bg(bgnum, depth, bg, pri) \ - if(render.##bgnum##_enabled[DEBUG_BGENABLED_ALL] == true) { \ - if(render.##bgnum##_enabled[DEBUG_BGENABLED_PRI##pri##] == true) { \ - ppu_render_line_bg(depth, bg, pri); \ - } \ - } -#define debug_ppu_render_line_oam(bgnum, pri) \ - if(render.##bgnum##_enabled[DEBUG_BGENABLED_ALL] == true) { \ - if(render.##bgnum##_enabled[DEBUG_BGENABLED_PRI##pri##] == true) { \ - ppu_render_line_oam(pri); \ - } \ - } +byte layer_bg_lookup_mode0[12] = { + BG4, BG3, OAM, BG4, BG3, OAM, BG2, BG1, OAM, BG2, BG1, OAM +}; void ppu_render_line_mode0(void) { - if(ppu.bg_priority_mode == 0) { - debug_ppu_render_line_bg (bg4, COLORDEPTH_4, BG4, 0); - debug_ppu_render_line_bg (bg3, COLORDEPTH_4, BG3, 0); - debug_ppu_render_line_oam(oam, 0); - debug_ppu_render_line_bg (bg4, COLORDEPTH_4, BG4, 1); - debug_ppu_render_line_bg (bg3, COLORDEPTH_4, BG3, 1); - debug_ppu_render_line_oam(oam, 1); - debug_ppu_render_line_bg (bg2, COLORDEPTH_4, BG2, 0); - debug_ppu_render_line_bg (bg1, COLORDEPTH_4, BG1, 0); - debug_ppu_render_line_oam(oam, 2); - debug_ppu_render_line_bg (bg2, COLORDEPTH_4, BG2, 1); - debug_ppu_render_line_bg (bg1, COLORDEPTH_4, BG1, 1); - debug_ppu_render_line_oam(oam, 3); - } else { - debug_ppu_render_line_bg (bg4, COLORDEPTH_4, BG4, 0); - debug_ppu_render_line_bg (bg3, COLORDEPTH_4, BG3, 0); - debug_ppu_render_line_oam(oam, 0); - debug_ppu_render_line_bg (bg4, COLORDEPTH_4, BG4, 1); - debug_ppu_render_line_oam(oam, 1); - debug_ppu_render_line_bg (bg2, COLORDEPTH_4, BG2, 0); - debug_ppu_render_line_bg (bg1, COLORDEPTH_4, BG1, 0); - debug_ppu_render_line_oam(oam, 2); - debug_ppu_render_line_bg (bg2, COLORDEPTH_4, BG2, 1); - debug_ppu_render_line_bg (bg1, COLORDEPTH_4, BG1, 1); - debug_ppu_render_line_oam(oam, 3); - debug_ppu_render_line_bg (bg3, COLORDEPTH_4, BG3, 1); - } + ppu_render_line_bg (7, 10, COLORDEPTH_4, BG1); + ppu_render_line_bg (6, 9, COLORDEPTH_4, BG2); + ppu_render_line_bg (1, 4, COLORDEPTH_4, BG3); + ppu_render_line_bg (0, 3, COLORDEPTH_4, BG4); + ppu_render_line_oam(2, 5, 8, 11); + ppu_set_layer_pixels(12, layer_bg_lookup_mode0); } +byte layer_bg_lookup_mode1_pri0[10] = { + BG3, OAM, BG3, OAM, BG2, BG1, OAM, BG2, BG1, OAM +}; + +byte layer_bg_lookup_mode1_pri1[10] = { + BG3, OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM, BG3 +}; + void ppu_render_line_mode1(void) { - if(ppu.bg_priority_mode == 0) { - debug_ppu_render_line_bg (bg3, COLORDEPTH_4, BG3, 0); - debug_ppu_render_line_oam(oam, 0); - debug_ppu_render_line_bg (bg3, COLORDEPTH_4, BG3, 1); - debug_ppu_render_line_oam(oam, 1); - debug_ppu_render_line_bg (bg2, COLORDEPTH_16, BG2, 0); - debug_ppu_render_line_bg (bg1, COLORDEPTH_16, BG1, 0); - debug_ppu_render_line_oam(oam, 2); - debug_ppu_render_line_bg (bg2, COLORDEPTH_16, BG2, 1); - debug_ppu_render_line_bg (bg1, COLORDEPTH_16, BG1, 1); - debug_ppu_render_line_oam(oam, 3); - } else { - debug_ppu_render_line_bg (bg3, COLORDEPTH_4, BG3, 0); - debug_ppu_render_line_oam(oam, 0); - debug_ppu_render_line_oam(oam, 1); - debug_ppu_render_line_bg (bg2, COLORDEPTH_16, BG2, 0); - debug_ppu_render_line_bg (bg1, COLORDEPTH_16, BG1, 0) - debug_ppu_render_line_oam(oam, 2); - debug_ppu_render_line_bg (bg2, COLORDEPTH_16, BG2, 1); - debug_ppu_render_line_bg (bg1, COLORDEPTH_16, BG1, 1) - debug_ppu_render_line_oam(oam, 3); - debug_ppu_render_line_bg (bg3, COLORDEPTH_4, BG3, 1); + switch(ppu.bg_priority_mode) { + case 0: + ppu_render_line_bg (5, 8, COLORDEPTH_16, BG1); + ppu_render_line_bg (4, 7, COLORDEPTH_16, BG2); + ppu_render_line_bg (0, 2, COLORDEPTH_4, BG3); + ppu_render_line_oam(1, 3, 6, 9); + ppu_set_layer_pixels(10, layer_bg_lookup_mode1_pri0); + break; + case 1: + ppu_render_line_bg (4, 7, COLORDEPTH_16, BG1); + ppu_render_line_bg (3, 6, COLORDEPTH_16, BG2); + ppu_render_line_bg (0, 9, COLORDEPTH_4, BG3); + ppu_render_line_oam(1, 2, 5, 8); + ppu_set_layer_pixels(10, layer_bg_lookup_mode1_pri1); + break; } } +byte layer_bg_lookup_mode2[8] = { + OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM +}; + void ppu_render_line_mode2(void) { - if(ppu.bg_priority_mode == 0) { - debug_ppu_render_line_oam(oam, 0); - debug_ppu_render_line_oam(oam, 1); - debug_ppu_render_line_bg (bg2, COLORDEPTH_16, BG2, 0); - debug_ppu_render_line_bg (bg1, COLORDEPTH_16, BG1, 0); - debug_ppu_render_line_oam(oam, 2); - debug_ppu_render_line_bg (bg2, COLORDEPTH_16, BG2, 1); - debug_ppu_render_line_bg (bg1, COLORDEPTH_16, BG1, 1); - debug_ppu_render_line_oam(oam, 3); - } else { - debug_ppu_render_line_oam(oam, 0); - debug_ppu_render_line_oam(oam, 1); - debug_ppu_render_line_bg (bg2, COLORDEPTH_16, BG2, 0); - debug_ppu_render_line_bg (bg1, COLORDEPTH_16, BG1, 0) - debug_ppu_render_line_oam(oam, 2); - debug_ppu_render_line_bg (bg2, COLORDEPTH_16, BG2, 1); - debug_ppu_render_line_bg (bg1, COLORDEPTH_16, BG1, 1) - debug_ppu_render_line_oam(oam, 3); - } + ppu_render_line_bg (3, 6, COLORDEPTH_16, BG1); + ppu_render_line_bg (2, 5, COLORDEPTH_16, BG2); + ppu_render_line_oam(0, 1, 4, 7); + ppu_set_layer_pixels(8, layer_bg_lookup_mode2); } +byte layer_bg_lookup_mode3[8] = { + OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM +}; + void ppu_render_line_mode3(void) { - if(ppu.bg_priority_mode == 0) { - debug_ppu_render_line_oam(oam, 0); - debug_ppu_render_line_oam(oam, 1); - debug_ppu_render_line_bg(bg2, COLORDEPTH_16, BG2, 0); - debug_ppu_render_line_bg(bg1, COLORDEPTH_256, BG1, 0); - debug_ppu_render_line_oam(oam, 2); - debug_ppu_render_line_bg(bg2, COLORDEPTH_16, BG2, 1); - debug_ppu_render_line_bg(bg1, COLORDEPTH_256, BG1, 1); - debug_ppu_render_line_oam(oam, 3); - } else { - debug_ppu_render_line_oam(oam, 0); - debug_ppu_render_line_oam(oam, 1); - debug_ppu_render_line_bg(bg2, COLORDEPTH_16, BG2, 0); - debug_ppu_render_line_bg(bg1, COLORDEPTH_256, BG1, 0); - debug_ppu_render_line_oam(oam, 2); - debug_ppu_render_line_bg(bg2, COLORDEPTH_16, BG2, 1); - debug_ppu_render_line_bg(bg1, COLORDEPTH_256, BG1, 1); - debug_ppu_render_line_oam(oam, 3); - } + ppu_render_line_bg (3, 6, COLORDEPTH_256, BG1); + ppu_render_line_bg (2, 5, COLORDEPTH_16, BG2); + ppu_render_line_oam(0, 1, 4, 7); + ppu_set_layer_pixels(8, layer_bg_lookup_mode3); } +byte layer_bg_lookup_mode4[8] = { + OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM +}; + void ppu_render_line_mode4(void) { - if(ppu.bg_priority_mode == 0) { - debug_ppu_render_line_oam(oam, 0); - debug_ppu_render_line_oam(oam, 1); - debug_ppu_render_line_bg(bg2, COLORDEPTH_4, BG2, 0); - debug_ppu_render_line_bg(bg1, COLORDEPTH_256, BG1, 0); - debug_ppu_render_line_oam(oam, 2); - debug_ppu_render_line_bg(bg2, COLORDEPTH_4, BG2, 1); - debug_ppu_render_line_bg(bg1, COLORDEPTH_256, BG1, 1); - debug_ppu_render_line_oam(oam, 3); - } else { - debug_ppu_render_line_oam(oam, 0); - debug_ppu_render_line_oam(oam, 1); - debug_ppu_render_line_bg(bg2, COLORDEPTH_4, BG2, 0); - debug_ppu_render_line_bg(bg1, COLORDEPTH_256, BG1, 0); - debug_ppu_render_line_oam(oam, 2); - debug_ppu_render_line_bg(bg2, COLORDEPTH_4, BG2, 1); - debug_ppu_render_line_bg(bg1, COLORDEPTH_256, BG1, 1); - debug_ppu_render_line_oam(oam, 3); - } + ppu_render_line_bg (3, 6, COLORDEPTH_256, BG1); + ppu_render_line_bg (2, 5, COLORDEPTH_4, BG2); + ppu_render_line_oam(0, 1, 4, 7); + ppu_set_layer_pixels(8, layer_bg_lookup_mode4); } +byte layer_bg_lookup_mode5[8] = { + OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM +}; + void ppu_render_line_mode5(void) { - debug_ppu_render_line_bg(bg2, COLORDEPTH_4, BG2, 0); - debug_ppu_render_line_bg(bg1, COLORDEPTH_16, BG1, 0); - debug_ppu_render_line_bg(bg2, COLORDEPTH_4, BG2, 0); - debug_ppu_render_line_bg(bg1, COLORDEPTH_16, BG1, 1); + ppu_render_line_bg (3, 6, COLORDEPTH_16, BG1); + ppu_render_line_bg (2, 5, COLORDEPTH_4, BG2); + ppu_render_line_oam(0, 1, 4, 7); + ppu_set_layer_pixels(8, layer_bg_lookup_mode5); } +byte layer_bg_lookup_mode6[6] = { + OAM, OAM, BG1, OAM, BG1, OAM +}; + void ppu_render_line_mode6(void) { - debug_ppu_render_line_bg(bg1, COLORDEPTH_16, BG1, 0); - debug_ppu_render_line_bg(bg1, COLORDEPTH_16, BG1, 1); + ppu_render_line_bg (2, 4, COLORDEPTH_16, BG1); + ppu_render_line_oam(0, 1, 3, 5); + ppu_set_layer_pixels(8, layer_bg_lookup_mode6); } +byte layer_bg_lookup_mode7[5] = { + OAM, BG1, OAM, OAM, OAM +}; + +byte layer_bg_lookup_mode7_extbg[6] = { + BG2, OAM, OAM, BG2, OAM, OAM +}; + void ppu_render_line_mode7(void) { - if(ppu.bg_priority_mode == 0) { - debug_ppu_render_line_oam(oam, 0); - debug_ppu_render_line_oam(oam, 1); - ppu_render_line_m7(); - debug_ppu_render_line_oam(oam, 2); - debug_ppu_render_line_oam(oam, 3); + if(ppu.mode7_extbg == false) { + ppu_render_line_m7 (1, 0, 0); //bg2 priorities are ignored + ppu_render_line_oam(0, 2, 3, 4); + ppu_set_layer_pixels(5, layer_bg_lookup_mode7); } else { - debug_ppu_render_line_oam(oam, 0); - debug_ppu_render_line_oam(oam, 1); - ppu_render_line_m7(); - debug_ppu_render_line_oam(oam, 2); - debug_ppu_render_line_oam(oam, 3); + ppu_render_line_m7 (0, 0, 3); //bg1 priority is ignored + ppu_render_line_oam(1, 2, 4, 5); + ppu_set_layer_pixels(6, layer_bg_lookup_mode7_extbg); } } void ppu_render_scanline(void) { int x, y; + ppu.vline_pos = snes_time->vscan_pos; ppu.hirq_triggered = false; - ppu.vline_pos++; - if(ppu.vline_pos > 261)ppu.vline_pos = 0; //new screen initialize if(ppu.vline_pos == 0) { + hdma_initialize(); ppu.virq_triggered = false; - ppu.active_hdma_channels = ppu.toggle_active_hdma_channels; - if(ppu.visible_scanlines != ppu.toggle_visible_scanlines) { - ppu.visible_scanlines = ppu.toggle_visible_scanlines; - video_setsnesmode(); - video_setmode(false, 512, ppu.visible_scanlines * 2); - } gx816->nmi_pin = 1; } @@ -215,7 +138,6 @@ int x, y; if(render.frame_count >= render.frame_skip) { render.frame_count = 0; } - ppu.interlace_frame ^= 1; } //automatic joypad read @@ -223,20 +145,12 @@ int x, y; UpdateJoypad(); } -//nmi - if(ppu.vline_pos == (ppu.visible_scanlines + 8) && gx816->nmi_pin == 1) { - gx816->nmi_pin = 0; - if(gx816->nmi_enabled == true) { - gx816->InvokeIRQ(0xffea); - } - } - - UpdateHDMA(); //found in ppu_dma.cpp y = ppu.vline_pos; - if(y < ppu.visible_scanlines && (render.frame_skip == 0 || render.frame_count == 0)) { + if(y > 0 && y < ppu.visible_scanlines && (render.frame_skip == 0 || render.frame_count == 0)) { if(ppu.display_disable == true) { - memset(ppu.screen + y * 512, 0, 1024); + memset(ppu.screen + (y << 1) * 512, 0, 2048); } else { + ppu_clear_layer_cache(); ppu_clear_pixel_cache(); switch(ppu.bg_mode) { case 0:ppu_render_line_mode0();break; @@ -254,17 +168,26 @@ int x, y; } void ppu_update_scanline(void) { +static bool hdma_triggered = false; +word current_vscan_pos; //starting a new screen? - if(ppu.vline_pos > snes_time->vscan_pos) { - while(ppu.vline_pos != 0) { - ppu_render_scanline(); - } + if(snes_time->vscan_wrapped == true) { + snes_time->vscan_wrapped = false; } - while(snes_time->vscan_pos > ppu.vline_pos) { + if(snes_time->hscan_wrapped == true) { + snes_time->hscan_wrapped = false; + hdma_triggered = false; ppu_render_scanline(); } + if(snes_time->hscan_pos >= 278 && hdma_triggered == false) { + hdma_update(); + hdma_triggered = true; + } + + if(gx816->cpu_state == CPUSTATE_STP)return; + if(!(gx816->regs.p & PF_I)) { if(ppu.vcounter_enabled == true && ppu.hcounter_enabled == true) { if(snes_time->vscan_pos == ppu.virq_pos && ppu.virq_triggered == false) { @@ -292,13 +215,17 @@ void ppu_update_scanline(void) { } byte oam_read(word addr) { +byte r; addr &= 1023; if(addr >= 512) { addr &= 31; - return ppu.oam[addr + 512]; + r = ppu.oam[addr + 512]; + debug_test_bp(BPSRC_OAM, BP_READ, addr + 512, r); } else { - return ppu.oam[addr]; + r = ppu.oam[addr]; + debug_test_bp(BPSRC_OAM, BP_READ, addr, r); } + return r; } void oam_write(word addr, byte value) { @@ -306,8 +233,10 @@ void oam_write(word addr, byte value) { if(addr >= 512) { addr &= 31; ppu.oam[addr + 512] = value; + debug_test_bp(BPSRC_OAM, BP_WRITE, addr + 512, value); } else { ppu.oam[addr] = value; + debug_test_bp(BPSRC_OAM, BP_WRITE, addr, value); } } @@ -317,7 +246,7 @@ byte r, g, b; double m; word *ptr; if(first_time == 1) { - ppu.screen = (word*)malloc(512 * 480 * 2); + ppu.screen = (word*)malloc(512 * 478 * 2); ppu.vram = (byte*)malloc(0x10000); ppu.cgram = (byte*)malloc(512); ppu.oam = (byte*)malloc(544); @@ -349,32 +278,35 @@ word *ptr; } } } - ppu_clear_pixel_cache(); - memset(ppu.screen, 0, 512 * 480 * 2); + ppu_clear_tiledata_cache(); + memset(ppu.screen, 0, 512 * 478 * 2); memset(ppu.vram, 0, 0x10000); memset(ppu.cgram, 0, 512); memset(ppu.oam, 0, 544); - ppu.ppu_cycles = 0; - ppu.ppu_prev_cycles = 0; - ppu.display_disable = true; - ppu.display_brightness = 15; - ppu.visible_scanlines = 224; - ppu.toggle_visible_scanlines = 224; + ppu.ppu_cycles = 0; + ppu.ppu_prev_cycles = 0; + ppu.display_disable = true; + ppu.display_brightness = 15; - ppu.interlace = false; - ppu.interlace_frame = 0; - ppu.hline_pos = 0; - ppu.vline_pos = 261; - ppu.irq_triggered = false; - ppu.virq_triggered = false; - ppu.hirq_triggered = false; - ppu.vram_write_pos = 0; - ppu.cgram_write_pos = 0; - ppu.wram_write_pos = 0; - ppu.vram_inc_size = 2; - ppu.vram_inc_reg = 0; - ppu.oam_write_pos = 0; - ppu.oam_tiledata_loc = 0; +//ppu.interlace/ppu.interlace_frame initialized in timing/timing.cpp + ppu.overscan = false; + ppu.visible_scanlines = 224; + ppu.sprite_halve = false; + ppu.hline_pos = 0; + ppu.vline_pos = 0; + ppu.irq_triggered = false; + ppu.virq_triggered = false; + ppu.hirq_triggered = false; + ppu.vram_write_pos = 0; + ppu.vram_read_buffer = 0; + ppu.vram_write_buffer = 0; + ppu.cgram_write_pos = 0; + ppu.wram_write_pos = 0; + ppu.vram_remap_mode = 0; + ppu.vram_inc_size = 2; + ppu.vram_inc_reg = 0; + ppu.oam_write_pos = 0; + ppu.oam_tiledata_loc = 0; ppu.bg_enabled[OAM] = false; ppu.ss_bg_enabled[OAM] = false; @@ -417,10 +349,7 @@ word *ptr; ppu.div_b = 0; ppu.r_4214 = 0; ppu.r_4216 = 0; - - ppu.smul_a = 0; - ppu.smul_b = 0; - ppu.smul_r = 0; + ppu.r_2134 = 0; ppu.window1_left = 0; ppu.window1_right = 0; @@ -444,14 +373,14 @@ word *ptr; ppu.color_g = 0; ppu.color_b = 0; - ppu.toggle_active_hdma_channels = 0; - ppu.active_hdma_channels = 0; + ppu.active_hdma_channels = 0; for(i=0;i<8;i++) { memset(&dma_channel[i], 0, sizeof(dmachannel)); ppu.hdma_completed[i] = false; ppu.hdma_scanlines_remaining[i] = 0; ppu.hdma_index_pointer[i] = 0; } + hdma_initialize(); ppu.vcounter_enabled = false; ppu.hcounter_enabled = false; @@ -471,6 +400,13 @@ word *ptr; ppu.m7hofs = ppu.m7vofs = 0x0000; - ppu.mode7_hflip = false; - ppu.mode7_vflip = false; + ppu.mode7_repeat = 0; + ppu.mode7_extbg = false; + ppu.mode7_hflip = false; + ppu.mode7_vflip = false; + + ppu.io4201 = 0xff; + ppu.counter_latched = false; + + memset(ppu.mmio_mem_43xx, 0, 0x80); } diff --git a/bsnes/ppu/ppu_cache.cpp b/bsnes/ppu/ppu_cache.cpp index 591db059..113d865a 100644 --- a/bsnes/ppu/ppu_cache.cpp +++ b/bsnes/ppu/ppu_cache.cpp @@ -13,6 +13,8 @@ struct { byte blend_type; }ppu_pixel_cache[512]; +byte ppu_layer_cache[512 * 12]; + #define TILE_2BIT 0 #define TILE_4BIT 1 #define TILE_8BIT 2 @@ -23,7 +25,7 @@ byte *ppu_bg_tiledata_state[3]; //this should be reset once every scanline void ppu_clear_pixel_cache(void) { int i; - for(i=0;i<512;i++) { + for(i=0;i2118 23->2118 45->2118 67->2118 89->2118) - 001: 2 regs 1 write (01->2118 23->2119 45->2118 67->2119 89->2118) - 010: 1 reg 2 writes (01->2118 23->2118 45->2118 67->2118 89->2118) - 011: 2 regs 2 writes (01->2118 23->2118 45->2119 67->2119 89->2118) - 100: 4 regs 1 write (01->2118 23->2119 45->211a 67->211b 89->2118) - 101-111: unknown */ void mmio_w43x0(byte c, byte value) { dma_channel[c].transfer_mode = (value & 0x80)?DMATRANSFER_MMIOTOCPU:DMATRANSFER_CPUTOMMIO; - dma_channel[c].index_mode = (value & 0x40)?DMAINDEX_INDIRECT:DMAINDEX_ABSOLUTE; - dma_channel[c].write_dir = (value & 0x10)?DMAWRITE_DEC:DMAWRITE_INC; + dma_channel[c].indirect = (value & 0x40)?true:false; + dma_channel[c].write_dir = (value & 0x10)?-1:1; dma_channel[c].fixed_address = (value & 0x08)?true:false; dma_channel[c].transfer_type = (value & 0x07); } @@ -61,7 +65,7 @@ void mmio_w43x0(byte c, byte value) { b: $2100 | b = destination register - limited to $21xx regs only */ void mmio_w43x1(byte c, byte value) { - dma_channel[c].dest_addr = 0x2100 | value; + dma_channel[c].dest_addr = value; } /* @@ -96,390 +100,293 @@ void mmio_w43x6(byte c, byte value) { $43x7 : HDMA indirect bank address */ void mmio_w43x7(byte c, byte value) { - dma_channel[c].indirect_bank_address = value; + dma_channel[c].indirect_bank = value; } -void dma_cputommio(byte c, byte a) { -byte x; - x = gx816->mem_read(MEMMODE_LONG, MEMSIZE_BYTE, dma_channel[c].src_addr); - mmio_write(dma_channel[c].dest_addr + a, x); - if(dma_channel[c].fixed_address == false) { - if(dma_channel[c].write_dir == DMAWRITE_INC)dma_channel[c].src_addr++; - if(dma_channel[c].write_dir == DMAWRITE_DEC)dma_channel[c].src_addr--; - } - dma_channel[c].transfer_size--; +void dma_mmio_write(byte reg, byte value) { + mmio_write(0x2100 | reg, value); } -void dma_mmiotocpu(byte c, byte a) { +byte dma_mmio_read(byte reg) { + return mmio_read(0x2100 | reg); +} + +word dma_cputommio(byte c, byte a) { byte x; - x = mmio_read(dma_channel[c].dest_addr + a); - gx816->mem_write(MEMMODE_LONG, MEMSIZE_BYTE, dma_channel[c].src_addr, x); + x = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dma_channel[c].src_addr); + dma_mmio_write(dma_channel[c].dest_addr + a, x); if(dma_channel[c].fixed_address == false) { - if(dma_channel[c].write_dir == DMAWRITE_INC)dma_channel[c].src_addr++; - if(dma_channel[c].write_dir == DMAWRITE_DEC)dma_channel[c].src_addr--; + dma_channel[c].src_addr = (dma_channel[c].src_addr & 0xff0000) | ((dma_channel[c].src_addr + dma_channel[c].write_dir) & 0xffff); } - dma_channel[c].transfer_size--; + snes_time->add_cpu_cycles(1, 8); + return --dma_channel[c].transfer_size; +} + +word dma_mmiotocpu(byte c, byte a) { +byte x; + x = dma_mmio_read(dma_channel[c].dest_addr + a); + gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dma_channel[c].src_addr, x); + if(dma_channel[c].fixed_address == false) { + dma_channel[c].src_addr = (dma_channel[c].src_addr & 0xff0000) | ((dma_channel[c].src_addr + dma_channel[c].write_dir) & 0xffff); + } + snes_time->add_cpu_cycles(1, 8); + return --dma_channel[c].transfer_size; } void dma_transfer_type0(byte c) { if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) { - while(1) { - dma_cputommio(c, 0); if(dma_channel[c].transfer_size == 0)break; - } + if(dma_cputommio(c, 0) == 0)return; } else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) { - while(1) { - dma_mmiotocpu(c, 0); if(dma_channel[c].transfer_size == 0)break; - } + if(dma_mmiotocpu(c, 0) == 0)return; } } void dma_transfer_type1(byte c) { if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) { - while(1) { - dma_cputommio(c, 0); if(dma_channel[c].transfer_size == 0)break; - dma_cputommio(c, 1); if(dma_channel[c].transfer_size == 0)break; - } + if(dma_cputommio(c, 0) == 0)return; + if(dma_cputommio(c, 1) == 0)return; } else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) { - while(1) { - dma_mmiotocpu(c, 0); if(dma_channel[c].transfer_size == 0)break; - dma_mmiotocpu(c, 1); if(dma_channel[c].transfer_size == 0)break; - } + if(dma_mmiotocpu(c, 0) == 0)return; + if(dma_mmiotocpu(c, 1) == 0)return; } } void dma_transfer_type2(byte c) { if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) { - while(1) { - dma_cputommio(c, 0); if(dma_channel[c].transfer_size == 0)break; - } + if(dma_cputommio(c, 0) == 0)return; } else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) { - while(1) { - dma_mmiotocpu(c, 0); if(dma_channel[c].transfer_size == 0)break; - } + if(dma_mmiotocpu(c, 0) == 0)return; } } void dma_transfer_type3(byte c) { if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) { - while(1) { - dma_cputommio(c, 0); if(dma_channel[c].transfer_size == 0)break; - dma_cputommio(c, 0); if(dma_channel[c].transfer_size == 0)break; - dma_cputommio(c, 1); if(dma_channel[c].transfer_size == 0)break; - dma_cputommio(c, 1); if(dma_channel[c].transfer_size == 0)break; - } + if(dma_cputommio(c, 0) == 0)return; + if(dma_cputommio(c, 0) == 0)return; + if(dma_cputommio(c, 1) == 0)return; + if(dma_cputommio(c, 1) == 0)return; } else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) { - while(1) { - dma_mmiotocpu(c, 0); if(dma_channel[c].transfer_size == 0)break; - dma_mmiotocpu(c, 0); if(dma_channel[c].transfer_size == 0)break; - dma_mmiotocpu(c, 1); if(dma_channel[c].transfer_size == 0)break; - dma_mmiotocpu(c, 1); if(dma_channel[c].transfer_size == 0)break; - } + if(dma_mmiotocpu(c, 0) == 0)return; + if(dma_mmiotocpu(c, 0) == 0)return; + if(dma_mmiotocpu(c, 1) == 0)return; + if(dma_mmiotocpu(c, 1) == 0)return; } } void dma_transfer_type4(byte c) { if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) { - while(1) { - dma_cputommio(c, 0); if(dma_channel[c].transfer_size == 0)break; - dma_cputommio(c, 1); if(dma_channel[c].transfer_size == 0)break; - dma_cputommio(c, 2); if(dma_channel[c].transfer_size == 0)break; - dma_cputommio(c, 3); if(dma_channel[c].transfer_size == 0)break; - } + if(dma_cputommio(c, 0) == 0)return; + if(dma_cputommio(c, 1) == 0)return; + if(dma_cputommio(c, 2) == 0)return; + if(dma_cputommio(c, 3) == 0)return; } else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) { - while(1) { - dma_mmiotocpu(c, 0); if(dma_channel[c].transfer_size == 0)break; - dma_mmiotocpu(c, 1); if(dma_channel[c].transfer_size == 0)break; - dma_mmiotocpu(c, 2); if(dma_channel[c].transfer_size == 0)break; - dma_mmiotocpu(c, 3); if(dma_channel[c].transfer_size == 0)break; - } + if(dma_mmiotocpu(c, 0) == 0)return; + if(dma_mmiotocpu(c, 1) == 0)return; + if(dma_mmiotocpu(c, 2) == 0)return; + if(dma_mmiotocpu(c, 3) == 0)return; } } +void dma_transfer_type5(byte c) { + if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) { + if(dma_cputommio(c, 0) == 0)return; + if(dma_cputommio(c, 1) == 0)return; + if(dma_cputommio(c, 0) == 0)return; + if(dma_cputommio(c, 1) == 0)return; + } else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) { + if(dma_mmiotocpu(c, 0) == 0)return; + if(dma_mmiotocpu(c, 1) == 0)return; + if(dma_mmiotocpu(c, 0) == 0)return; + if(dma_mmiotocpu(c, 1) == 0)return; + } +} + +/* + This function is called consecutively until all DMA transfers are completed. + Rather than transfer all of the DMA data immediately, control is returned to + the main loop after each DMA transfer so that the APU, PPU, renderer, etc. + can keep in sync. Otherwise, a transfer of 65536 bytes could prevent the renderer + from drawing all scanlines, for example. + Each DMA channel must be completed incrementally. The entire transfer from channel 0 + must complete before any data is transferred for channel 1, etc. +*/ +void ppu_update_dma(void) { +int i, z; + z = 0; + for(i=0;i<8;i++) { + if(dma_channel[i].active == false)continue; + switch(dma_channel[i].transfer_type) { + case 0:dma_transfer_type0(i);break; + case 1:dma_transfer_type1(i);break; + case 2:dma_transfer_type2(i);break; + case 3:dma_transfer_type3(i);break; + case 4:dma_transfer_type4(i);break; + case 5:dma_transfer_type5(i);break; + case 6:dma_transfer_type2(i);break; //6 is the same as 2 + case 7:dma_transfer_type3(i);break; //7 is the same as 3 + } + if(dma_channel[i].transfer_size == 0) { + dma_channel[i].active = false; + } + return; + } + gx816->cpu_state = CPUSTATE_RUN; +} + /* $420b : DMA enable $420c : HDMA enable - each bit corresponds to the respecting DMA channel (7,6,5,4,3,2,1,0) - setting a bit in this register will perform the DMA transfer. multiple - transfers can be done at once. requires one cycle per byte transferred - hdma bits are sticky (they are not cleared automatically after write) + Each bit corresponds to the respecting DMA channel (7,6,5,4,3,2,1,0) + Setting a bit in this register will perform the DMA transfer. Multiple + transfers can be done at once. Requires one cycle per byte transferred. */ void mmio_w420b(byte value) { int i; + ppu.active_hdma_channels &= ~value; for(i=0;i<8;i++) { if(value & (1 << i)) { - snes_time->add_cpu_cycles(dma_channel[i].transfer_size * 6); - if (dma_channel[i].transfer_type == 0)dma_transfer_type0(i); - else if(dma_channel[i].transfer_type == 1)dma_transfer_type1(i); - else if(dma_channel[i].transfer_type == 2)dma_transfer_type2(i); - else if(dma_channel[i].transfer_type == 3)dma_transfer_type3(i); - else if(dma_channel[i].transfer_type == 4)dma_transfer_type4(i); - else dprintf("* mmio_w420b(): Unknown DMA transfer type: %d", dma_channel[i].transfer_type); + dma_channel[i].active = true; + gx816->cpu_state = CPUSTATE_DMA; } } } void mmio_w420c(byte value) { -//don't actually enable hdma channels until the start of the next frame - ppu.toggle_active_hdma_channels = value; + ppu.active_hdma_channels = value; } -byte hdma_read_absolute(byte c) { -ulong x; - x = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dma_channel[c].src_addr + ppu.hdma_index_pointer[c]); - ppu.hdma_index_pointer[c]++; - return x; -} +byte hdma_transfer_lentbl[8] = { 1, 2, 2, 4, 4, 4, 2, 4 }; -byte hdma_read_indirect(byte c) { -ulong x; - x = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dma_channel[c].src_addr + ppu.hdma_index_pointer[c]); - x += dma_channel[c].hdma_indirect_pointer; - x = (dma_channel[c].indirect_bank_address << 16) | (x & 0xffff); - x = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, x); - dma_channel[c].hdma_indirect_pointer++; - return x; -} - -void hdma_transfer_type0_absolute(byte c) { - mmio_write(dma_channel[c].dest_addr, hdma_read_absolute(c)); -} - -void hdma_transfer_type0_indirect(byte c) { - mmio_write(dma_channel[c].dest_addr, hdma_read_indirect(c)); - if(dma_channel[c].hdma_mode == HDMAMODE_NORMAL)dma_channel[c].hdma_indirect_pointer -= 1; -} - -void hdma_transfer_type1_absolute(byte c) { - mmio_write(dma_channel[c].dest_addr, hdma_read_absolute(c)); - mmio_write(dma_channel[c].dest_addr + 1, hdma_read_absolute(c)); -} - -void hdma_transfer_type1_indirect(byte c) { - mmio_write(dma_channel[c].dest_addr, hdma_read_indirect(c)); - mmio_write(dma_channel[c].dest_addr + 1, hdma_read_indirect(c)); - if(dma_channel[c].hdma_mode == HDMAMODE_NORMAL)dma_channel[c].hdma_indirect_pointer -= 2; -} - -void hdma_transfer_type2_absolute(byte c) { - mmio_write(dma_channel[c].dest_addr, hdma_read_absolute(c)); - mmio_write(dma_channel[c].dest_addr, hdma_read_absolute(c)); -} - -void hdma_transfer_type2_indirect(byte c) { - mmio_write(dma_channel[c].dest_addr, hdma_read_indirect(c)); - mmio_write(dma_channel[c].dest_addr, hdma_read_indirect(c)); - if(dma_channel[c].hdma_mode == HDMAMODE_NORMAL)dma_channel[c].hdma_indirect_pointer -= 2; -} - -void hdma_transfer_type3_absolute(byte c) { - mmio_write(dma_channel[c].dest_addr, hdma_read_absolute(c)); - mmio_write(dma_channel[c].dest_addr, hdma_read_absolute(c)); - mmio_write(dma_channel[c].dest_addr + 1, hdma_read_absolute(c)); - mmio_write(dma_channel[c].dest_addr + 1, hdma_read_absolute(c)); -} - -void hdma_transfer_type3_indirect(byte c) { - mmio_write(dma_channel[c].dest_addr, hdma_read_indirect(c)); - mmio_write(dma_channel[c].dest_addr, hdma_read_indirect(c)); - mmio_write(dma_channel[c].dest_addr + 1, hdma_read_indirect(c)); - mmio_write(dma_channel[c].dest_addr + 1, hdma_read_indirect(c)); - if(dma_channel[c].hdma_mode == HDMAMODE_NORMAL)dma_channel[c].hdma_indirect_pointer -= 4; -} - -void hdma_transfer_type4_absolute(byte c) { - mmio_write(dma_channel[c].dest_addr, hdma_read_absolute(c)); - mmio_write(dma_channel[c].dest_addr + 1, hdma_read_absolute(c)); - mmio_write(dma_channel[c].dest_addr + 2, hdma_read_absolute(c)); - mmio_write(dma_channel[c].dest_addr + 3, hdma_read_absolute(c)); -} - -void hdma_transfer_type4_indirect(byte c) { - mmio_write(dma_channel[c].dest_addr, hdma_read_indirect(c)); - mmio_write(dma_channel[c].dest_addr + 1, hdma_read_indirect(c)); - mmio_write(dma_channel[c].dest_addr + 2, hdma_read_indirect(c)); - mmio_write(dma_channel[c].dest_addr + 3, hdma_read_indirect(c)); - if(dma_channel[c].hdma_mode == HDMAMODE_NORMAL)dma_channel[c].hdma_indirect_pointer -= 4; -} - -byte hdma_transfer_type_size_table[8] = { 1, 2, 2, 4, 4, 0, 0, 0 }; - -void HDMAFirstWrite(byte c) { - if(dma_channel[c].hdma_mode == HDMAMODE_NORMAL && ppu.hdma_scanlines_remaining[c] == 0x00) { - return; - } - if(dma_channel[c].hdma_mode == HDMAMODE_CONTINUOUS && ppu.hdma_scanlines_remaining[c] == 0x80) { - return; - } - - if(dma_channel[c].index_mode == DMAINDEX_ABSOLUTE) { - if (dma_channel[c].transfer_type == 0)hdma_transfer_type0_absolute(c); - else if(dma_channel[c].transfer_type == 1)hdma_transfer_type1_absolute(c); - else if(dma_channel[c].transfer_type == 2)hdma_transfer_type2_absolute(c); - else if(dma_channel[c].transfer_type == 3)hdma_transfer_type3_absolute(c); - else if(dma_channel[c].transfer_type == 4)hdma_transfer_type4_absolute(c); - else dprintf("* mmio_w420c(): Unknown HDMA transfer type: %d", dma_channel[c].transfer_type); - } else { //indirect - if (dma_channel[c].transfer_type == 0)hdma_transfer_type0_indirect(c); - else if(dma_channel[c].transfer_type == 1)hdma_transfer_type1_indirect(c); - else if(dma_channel[c].transfer_type == 2)hdma_transfer_type2_indirect(c); - else if(dma_channel[c].transfer_type == 3)hdma_transfer_type3_indirect(c); - else if(dma_channel[c].transfer_type == 4)hdma_transfer_type4_indirect(c); - else dprintf("* mmio_w420c(): Unknown HDMA transfer type: %d", dma_channel[c].transfer_type); +void hdma_write_byte(byte i, byte l, byte x) { + switch(dma_channel[i].transfer_type) { + case 0: + dma_mmio_write(dma_channel[i].dest_addr, x); + break; + case 1: + dma_mmio_write(dma_channel[i].dest_addr + l, x); + break; + case 2: + dma_mmio_write(dma_channel[i].dest_addr, x); + break; + case 3: + dma_mmio_write(dma_channel[i].dest_addr + (l >> 1), x); + break; + case 4: + dma_mmio_write(dma_channel[i].dest_addr + l, x); + break; + case 5: + dma_mmio_write(dma_channel[i].dest_addr + (l & 1), x); + break; + case 6: + dma_mmio_write(dma_channel[i].dest_addr, x); + break; + case 7: + dma_mmio_write(dma_channel[i].dest_addr + (l >> 1), x); + break; } } -void UpdateHDMAAbsoluteNormal(byte c) { - if(ppu.hdma_scanlines_remaining[c] == 0x00) { - ppu.hdma_scanlines_remaining[c] = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dma_channel[c].src_addr + ppu.hdma_index_pointer[c]); +void hdma_update(void) { +int i, l; +byte x, channels_active = 0; + if(snes_time->vscan_pos > ppu.visible_scanlines)return; + for(i=0;i<8;i++) { + if(dma_channel[i].completed == true)continue; + snes_time->add_cpu_cycles(1, 8); + channels_active++; + if(dma_channel[i].line_counter == 0) { + dma_channel[i].line_counter = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dma_channel[i].address++); + dma_channel[i].r43x8 = dma_channel[i].address; + if(dma_channel[i].line_counter == 0) { + dma_channel[i].completed = true; + continue; + } - if(ppu.hdma_scanlines_remaining[c] == 0) { - ppu.hdma_completed[c] = true; - return; - } - - dma_channel[c].hdma_indirect_pointer = 0; - if(ppu.hdma_scanlines_remaining[c] > 0x80) { - dma_channel[c].hdma_mode = HDMAMODE_CONTINUOUS; - } else { - dma_channel[c].hdma_mode = HDMAMODE_NORMAL; - } - - ppu.hdma_index_pointer[c]++; - HDMAFirstWrite(c); - } - - ppu.hdma_scanlines_remaining[c]--; -} - -void UpdateHDMAAbsoluteContinuous(byte c) { - if(ppu.hdma_scanlines_remaining[c] == 0x80) { - ppu.hdma_scanlines_remaining[c] = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dma_channel[c].src_addr + ppu.hdma_index_pointer[c]); - - if(ppu.hdma_scanlines_remaining[c] == 0) { - ppu.hdma_completed[c] = true; - return; - } - - dma_channel[c].hdma_indirect_pointer = 0; - if(ppu.hdma_scanlines_remaining[c] > 0x80) { - dma_channel[c].hdma_mode = HDMAMODE_CONTINUOUS; - } else { - dma_channel[c].hdma_mode = HDMAMODE_NORMAL; - } - - ppu.hdma_index_pointer[c]++; - HDMAFirstWrite(c); - ppu.hdma_scanlines_remaining[c]--; - } else { - if (dma_channel[c].transfer_type == 0)hdma_transfer_type0_absolute(c); - else if(dma_channel[c].transfer_type == 1)hdma_transfer_type1_absolute(c); - else if(dma_channel[c].transfer_type == 2)hdma_transfer_type2_absolute(c); - else if(dma_channel[c].transfer_type == 3)hdma_transfer_type3_absolute(c); - else if(dma_channel[c].transfer_type == 4)hdma_transfer_type4_absolute(c); - else dprintf("* mmio_w420c(): Unknown HDMA transfer type: %d", dma_channel[c].transfer_type); - - ppu.hdma_scanlines_remaining[c]--; - } -} - -void UpdateHDMAIndirectNormal(byte c) { - if(ppu.hdma_scanlines_remaining[c] == 0x00) { - ppu.hdma_index_pointer[c] += 2; - ppu.hdma_scanlines_remaining[c] = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dma_channel[c].src_addr + ppu.hdma_index_pointer[c]); - - if(ppu.hdma_scanlines_remaining[c] == 0) { - ppu.hdma_completed[c] = true; - return; - } - - dma_channel[c].hdma_indirect_pointer = 0; - if(ppu.hdma_scanlines_remaining[c] > 0x80) { - dma_channel[c].hdma_mode = HDMAMODE_CONTINUOUS; - } else { - dma_channel[c].hdma_mode = HDMAMODE_NORMAL; - } - - ppu.hdma_index_pointer[c]++; - HDMAFirstWrite(c); - } - - ppu.hdma_scanlines_remaining[c]--; -} - -void UpdateHDMAIndirectContinuous(byte c) { - if(ppu.hdma_scanlines_remaining[c] == 0x80) { - ppu.hdma_index_pointer[c] += 2; - ppu.hdma_scanlines_remaining[c] = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dma_channel[c].src_addr + ppu.hdma_index_pointer[c]); - - if(ppu.hdma_scanlines_remaining[c] == 0) { - ppu.hdma_completed[c] = true; - return; - } - - dma_channel[c].hdma_indirect_pointer = 0; - if(ppu.hdma_scanlines_remaining[c] > 0x80) { - dma_channel[c].hdma_mode = HDMAMODE_CONTINUOUS; - } else { - dma_channel[c].hdma_mode = HDMAMODE_NORMAL; - } - ppu.hdma_index_pointer[c]++; - HDMAFirstWrite(c); - ppu.hdma_scanlines_remaining[c]--; - } else { - if (dma_channel[c].transfer_type == 0)hdma_transfer_type0_indirect(c); - else if(dma_channel[c].transfer_type == 1)hdma_transfer_type1_indirect(c); - else if(dma_channel[c].transfer_type == 2)hdma_transfer_type2_indirect(c); - else if(dma_channel[c].transfer_type == 3)hdma_transfer_type3_indirect(c); - else if(dma_channel[c].transfer_type == 4)hdma_transfer_type4_indirect(c); - else dprintf("* mmio_w420c(): Unknown HDMA transfer type: %d", dma_channel[c].transfer_type); - - ppu.hdma_scanlines_remaining[c]--; - } -} - -void UpdateHDMA(void) { -int c; - for(c=0;c<8;c++) { - if(ppu.active_hdma_channels & (1 << c)) { - if(ppu.vline_pos == 0)continue; - if(ppu.vline_pos == 1) { - ppu.hdma_completed[c] = false; - ppu.hdma_index_pointer[c] = 0; - ppu.hdma_scanlines_remaining[c] = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dma_channel[c].src_addr); - ppu.hdma_index_pointer[c]++; - - if(ppu.hdma_scanlines_remaining[c] == 0) { - ppu.hdma_completed[c] = true; - continue; - } - - dma_channel[c].hdma_indirect_pointer = 0; - if(ppu.hdma_scanlines_remaining[c] > 0x80) { - dma_channel[c].hdma_mode = HDMAMODE_CONTINUOUS; - } else { - dma_channel[c].hdma_mode = HDMAMODE_NORMAL; - } - - HDMAFirstWrite(c); - ppu.hdma_scanlines_remaining[c]--; + if(dma_channel[i].line_counter > 0x80) { + dma_channel[i].repeat = true; + dma_channel[i].line_counter -= 0x80; } else { - if(ppu.hdma_completed[c] == true)continue; + dma_channel[i].repeat = false; + } - if(dma_channel[c].index_mode == DMAINDEX_ABSOLUTE) { - if(dma_channel[c].hdma_mode == HDMAMODE_NORMAL) { - UpdateHDMAAbsoluteNormal(c); - } else { - UpdateHDMAAbsoluteContinuous(c); - } - } else { //indirect - if(dma_channel[c].hdma_mode == HDMAMODE_NORMAL) { - UpdateHDMAIndirectNormal(c); - } else { - UpdateHDMAIndirectContinuous(c); - } - } + dma_channel[i].first_line = true; + if(dma_channel[i].indirect == false) { + dma_channel[i].iaddress = dma_channel[i].address; + } else { + dma_channel[i].iaddress = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dma_channel[i].address); + dma_channel[i].iaddress |= (dma_channel[i].indirect_bank << 16); + dma_channel[i].address += 2; + snes_time->add_cpu_cycles(1, 16); } } + + dma_channel[i].line_counter--; + if(dma_channel[i].first_line == false && dma_channel[i].repeat == false)continue; + dma_channel[i].first_line = false; + + if(dma_channel[i].indirect == false) { + dma_channel[i].iaddress = dma_channel[i].address; + } + + for(l=0;lmem_read(MEMMODE_NONE, MEMSIZE_BYTE, dma_channel[i].iaddress++); + if(dma_channel[i].indirect == false) { + dma_channel[i].address++; + } + hdma_write_byte(i, l, x); + snes_time->add_cpu_cycles(1, 8); + } + } + if(channels_active != 0) { + snes_time->add_cpu_cycles(1, 18); } } + +void hdma_initialize(void) { +int i, active_channels = 0; + for(i=0;i<8;i++) { + if((ppu.active_hdma_channels & (1 << i)) == 0) { + dma_channel[i].completed = true; + continue; + } + active_channels++; + dma_channel[i].first_line = true; + dma_channel[i].repeat = false; + dma_channel[i].line_counter = 0; + dma_channel[i].address = dma_channel[i].src_addr; + dma_channel[i].completed = false; + if(dma_channel[i].indirect == false) { + snes_time->add_cpu_cycles(1, 8); + } else { + snes_time->add_cpu_cycles(1, 24); + } + } + if(active_channels != 0) { + snes_time->add_cpu_cycles(1, 18); + } +} + +byte mmio_r43x8(byte c) { + return (dma_channel[c].r43x8); +} + +byte mmio_r43x9(byte c) { + return (dma_channel[c].r43x8 >> 8); +} + +byte mmio_r43xa(byte c) { + return (dma_channel[c].line_counter + 1); +} + +void mmio_w43x8(byte c, byte x) { + dma_channel[c].address = (dma_channel[c].address & 0xff00) | x; +} + +void mmio_w43x9(byte c, byte x) { + dma_channel[c].address = (dma_channel[c].address & 0x00ff) | (x << 8); +} + +void mmio_w43xa(byte c, byte x) { + dma_channel[c].line_counter = x; +} diff --git a/bsnes/ppu/ppu_mode7.cpp b/bsnes/ppu/ppu_mode7.cpp index 302eed08..c9b44940 100644 --- a/bsnes/ppu/ppu_mode7.cpp +++ b/bsnes/ppu/ppu_mode7.cpp @@ -11,64 +11,49 @@ x: horizontal screen flip */ void mmio_w211a(byte value) { - ppu.mode7_vflip = (value & 0x02)?true:false; - ppu.mode7_hflip = (value & 0x01)?true:false; + ppu.mode7_repeat = (value >> 6) & 3; + ppu.mode7_vflip = (value & 0x02)?true:false; + ppu.mode7_hflip = (value & 0x01)?true:false; } -byte m7_latch = 0x00; - /* $211b : m7a / 16-bit source operand for signed multiplication */ void mmio_w211b(byte value) { -static byte latch = 0; - ppu.m7a = (value << 8) | m7_latch; - m7_latch = value; - - if(!latch) { ppu.smul_a = (ppu.smul_a & 0xff00) | value; } - else { ppu.smul_a = (ppu.smul_a & 0x00ff) | (value << 8); } - - latch ^= 1; + ppu.m7a = (value << 8) | (ppu.m7a >> 8); } /* $211c : m7b / 8-bit source operand for signed multiplication */ void mmio_w211c(byte value) { - ppu.m7b = (value << 8) | m7_latch; - m7_latch = value; - - ppu.smul_b = value; + ppu.m7b = (value << 8) | (ppu.m7b >> 8); } /* $211d : m7c */ void mmio_w211d(byte value) { - ppu.m7c = (value << 8) | m7_latch; - m7_latch = value; + ppu.m7c = (value << 8) | (ppu.m7c >> 8); } /* $211e : m7d */ void mmio_w211e(byte value) { - ppu.m7d = (value << 8) | m7_latch; - m7_latch = value; + ppu.m7d = (value << 8) | (ppu.m7d >> 8); } /* $211f : m7x */ void mmio_w211f(byte value) { - ppu.m7x = (value << 8) | m7_latch; - m7_latch = value; + ppu.m7x = (value << 8) | (ppu.m7x >> 8); } /* $2120 : m7y */ void mmio_w2120(byte value) { - ppu.m7y = (value << 8) | m7_latch; - m7_latch = value; + ppu.m7y = (value << 8) | (ppu.m7y >> 8); } diff --git a/bsnes/ppu/ppu_muldiv.cpp b/bsnes/ppu/ppu_muldiv.cpp index 731be27b..3f82876d 100644 --- a/bsnes/ppu/ppu_muldiv.cpp +++ b/bsnes/ppu/ppu_muldiv.cpp @@ -1,19 +1,16 @@ byte mmio_r2134(void) { -ulong r; - r = (signed short)ppu.smul_a * (signed char)ppu.smul_b; - return r & 0xff; +ulong r = ((signed short)ppu.m7a * (signed char)(ppu.m7b >> 8)); + return (r); } byte mmio_r2135(void) { -ulong r; - r = (signed short)ppu.smul_a * (signed char)ppu.smul_b; - return (r >> 8) & 0xff; +ulong r = ((signed short)ppu.m7a * (signed char)(ppu.m7b >> 8)); + return (r >> 8); } byte mmio_r2136(void) { -ulong r; - r = (signed short)ppu.smul_a * (signed char)ppu.smul_b; - return (r >> 16) & 0xff; +ulong r = ((signed short)ppu.m7a * (signed char)(ppu.m7b >> 8)); + return (r >> 16); } void mmio_w4202(byte value) { diff --git a/bsnes/ppu/ppu_palette.cpp b/bsnes/ppu/ppu_palette.cpp index f8f3b142..9a78568a 100644 --- a/bsnes/ppu/ppu_palette.cpp +++ b/bsnes/ppu/ppu_palette.cpp @@ -5,7 +5,6 @@ multiply value by 2 to get actual offset into ppu.cgram */ void mmio_w2121(byte value) { -//if(ppu.vline_pos < 224 && ppu.display_disable == false)return; ppu.cgram_write_pos = value << 1; } @@ -14,9 +13,11 @@ void mmio_w2121(byte value) { writes to cgram using cgram_write_pos * 2 as an index */ -void mmio_w2122(byte val) { -//if(ppu.vline_pos < 224 && ppu.display_disable == false)return; - ppu.cgram[ppu.cgram_write_pos] = val; +void mmio_w2122(byte value) { + ppu.cgram[ppu.cgram_write_pos] = value; + + debug_test_bp(BPSRC_CGRAM, BP_WRITE, ppu.cgram_write_pos, value); + ppu.cgram_write_pos++; ppu.cgram_write_pos &= 0x01ff; } @@ -28,8 +29,10 @@ void mmio_w2122(byte val) { */ byte mmio_r213b(void) { byte r; -//if(ppu.vline_pos < 224 && ppu.display_disable == false)return; r = ppu.cgram[ppu.cgram_write_pos]; + + debug_test_bp(BPSRC_CGRAM, BP_READ, ppu.cgram_write_pos, r); + ppu.cgram_write_pos++; ppu.cgram_write_pos &= 0x01ff; return r; diff --git a/bsnes/ppu/ppu_render.cpp b/bsnes/ppu/ppu_render.cpp index 648760ee..904ddc2d 100644 --- a/bsnes/ppu/ppu_render.cpp +++ b/bsnes/ppu/ppu_render.cpp @@ -1,36 +1,51 @@ -byte ppu_addsub_adjust_buffer[96] = { +byte ppu_addsub_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 }; +byte ppu_addsub_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 +}; + #define ppu_pal_pixel(__i) \ (*((word*)ppu.cgram + __i)) word ppu_addsub_pixels(byte x, byte cdest_index, byte cdest_bg, byte csrc_index, byte csrc_bg) { int r, g, b; -byte hd = 0, hs = 0; word cdest = ppu_pal_pixel(cdest_index); word csrc = ppu_pal_pixel(csrc_index); +word res; //oam palettes 0-3 are not affected by color add/sub if(cdest_bg == OAM) { if(cdest_index < 192) { return cdest; } } - if(ppu.bg_color_enabled[cdest_bg] == true) { - hd = hs = ppu.color_halve; - } switch(ppu.color_mode) { case COLORMODE_ADD: - r = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest ) & 31) >> hd) + ( ((csrc ) & 31) >> hs) )); - g = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest >> 5) & 31) >> hd) + ( ((csrc >> 5) & 31) >> hs) )); - b = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest >> 10) & 31) >> hd) + ( ((csrc >> 10) & 31) >> hs) )); + if(ppu.bg_color_enabled[cdest_bg] == true && ppu.color_halve == 1) { + r = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1; + g = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )) >> 1; + b = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )) >> 1; + } else { + r = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )); + g = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )); + b = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )); + } break; case COLORMODE_SUB: - r = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest ) & 31) >> hd) - ( ((csrc ) & 31) >> hs) )); - g = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest >> 5) & 31) >> hd) - ( ((csrc >> 5) & 31) >> hs) )); - b = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest >> 10) & 31) >> hd) - ( ((csrc >> 10) & 31) >> hs) )); + if(ppu.bg_color_enabled[cdest_bg] == true && ppu.color_halve == 1) { + r = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1; + g = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )) >> 1; + b = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )) >> 1; + } else { + r = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest ) & 31) - ((csrc ) & 31) )); + g = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest >> 5) & 31) - ((csrc >> 5) & 31) )); + b = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest >> 10) & 31) - ((csrc >> 10) & 31) )); + } break; } return ((r) | (g << 5) | (b << 10)); @@ -38,27 +53,37 @@ word csrc = ppu_pal_pixel(csrc_index); word ppu_addsub_pixel(byte x, byte cdest_index, byte cdest_bg) { int r, g, b; -byte hd = 0; word cdest = ppu_pal_pixel(cdest_index); +word csrc = (ppu.color_r) | (ppu.color_g << 5) | (ppu.color_b << 10); +word res; //only oam palettes 4-7 are affected by color add/sub if(cdest_bg == OAM) { if(cdest_index < 192) { return cdest; } } - if(ppu.bg_color_enabled[cdest_bg] == true) { - hd = ppu.color_halve; - } switch(ppu.color_mode) { case COLORMODE_ADD: - r = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest ) & 31) >> hd) + (ppu.color_r >> hd) )); - g = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest >> 5) & 31) >> hd) + (ppu.color_g >> hd) )); - b = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest >> 10) & 31) >> hd) + (ppu.color_b >> hd) )); + if(ppu.bg_color_enabled[cdest_bg] == true && ppu.color_halve == 1 && ppu.addsub_mode == 0) { + r = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1; + g = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )) >> 1; + b = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )) >> 1; + } else { + r = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )); + g = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )); + b = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )); + } break; case COLORMODE_SUB: - r = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest ) & 31) >> hd) - (ppu.color_r >> hd) )); - g = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest >> 5) & 31) >> hd) - (ppu.color_g >> hd) )); - b = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest >> 10) & 31) >> hd) - (ppu.color_b >> hd) )); + if(ppu.bg_color_enabled[cdest_bg] == true && ppu.color_halve == 1 && ppu.addsub_mode == 0) { + r = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1; + g = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )) >> 1; + b = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )) >> 1; + } else { + r = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest ) & 31) - ((csrc ) & 31) )); + g = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest >> 5) & 31) - ((csrc >> 5) & 31) )); + b = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest >> 10) & 31) - ((csrc >> 10) & 31) )); + } break; } return ((r) | (g << 5) | (b << 10)); @@ -165,43 +190,42 @@ byte *dest; #define PPU_MAIN 0 #define PPU_SUB 1 -bool windows_not_obstructing(byte layer, byte bg, byte x); -bool color_windows_not_obstructing(byte x, byte color_mask_type); - -//light table is mirrored twice so that the high bit (bit 15) in the color -//is ignored, and does not cause color to reach into next light table. -#define ppu_write_pixel() \ - *(ptr + x) = *(light_table + cx) +bool windows_not_obstructing(byte layer, byte bg, word x); +bool color_windows_not_obstructing(word x, byte color_mask_type); void ppu_render_line_to_screen(void) { -int x; -word *ptr, *light_table; +int x, x1; +word *ptr, *ptri, *light_table, *light_tablei; word c, cx, cy; word screen_width = render.snes_width; - ptr = (word*)ppu.screen; - light_table = (word*)ppu.light_table + (ppu.display_brightness * 65536); - if(ppu.interlace == true) { - ptr += ((ppu.vline_pos * 2) + ppu.interlace_frame) * 512; + + if(ppu.interlace == false) { + ptr = (word*)ppu.screen + ((ppu.vline_pos << 1) ) * 512; + ptri = (word*)ppu.screen + ((ppu.vline_pos << 1) + 1) * 512; } else { - ptr += ppu.vline_pos * 512; + ptr = (word*)ppu.screen + ((ppu.vline_pos << 1) + ppu.interlace_frame) * 512; } - for(x=0;x> 2)]; - if ((sprite_num & 3) == 0) { size = (b & 0x02)?1:0; x = (b & 0x01)?0x100:0; } - else if((sprite_num & 3) == 1) { size = (b & 0x08)?1:0; x = (b & 0x04)?0x100:0; } - else if((sprite_num & 3) == 2) { size = (b & 0x20)?1:0; x = (b & 0x10)?0x100:0; } - else if((sprite_num & 3) == 3) { size = (b & 0x80)?1:0; x = (b & 0x40)?0x100:0; } + switch(sprite_num & 3) { + case 0: size = (b & 0x02)?1:0; x = (b & 0x01)?0x100:0; break; + case 1: size = (b & 0x08)?1:0; x = (b & 0x04)?0x100:0; break; + case 2: size = (b & 0x20)?1:0; x = (b & 0x10)?0x100:0; break; + case 3: size = (b & 0x80)?1:0; 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) & 0xff; + current_sprite.y = ((t >> 8) + 1) & 0xff; current_sprite.v_flip = (t & 0x80000000)?1:0; current_sprite.h_flip = (t & 0x40000000)?1:0; current_sprite.palette = (t >> 25) & 7; @@ -339,44 +391,57 @@ word x; } } -bool windows_not_obstructing(byte layer, byte bg, byte x) { +bool windows_not_obstructing(byte layer, byte bg, word x) { byte w1_mask, w2_mask; //1 = masked, 0 = not masked +word window1_left, window1_right, window2_left, window2_right; if(layer == PPU_MAIN) { if(ppu.bg_windowing_enabled[bg] == false)return true; } else if(layer == PPU_SUB) { if(ppu.ss_bg_windowing_enabled[bg] == false)return true; } + window1_left = ppu.window1_left; + window1_right = ppu.window1_right; + window2_left = ppu.window2_left; + window2_right = ppu.window2_right; + + if(ppu.bg_mode == 5 || ppu.bg_mode == 6) { + window1_left <<= 1; + window1_right <<= 1; + window2_left <<= 1; + window2_right <<= 1; + } + if(ppu.bg_window1_enabled[bg] == true && ppu.bg_window2_enabled[bg] == false) { if(ppu.bg_window1_clipmode[bg] == CLIPMODE_IN) { - if(x >= ppu.window1_left && x <= ppu.window1_right)return false; + if(x >= window1_left && x <= window1_right)return false; return true; } else { - if(x <= ppu.window1_left || x >= ppu.window1_right)return false; + if(x < window1_left || x > window1_right)return false; return true; } } else if(ppu.bg_window2_enabled[bg] == true && ppu.bg_window1_enabled[bg] == false) { if(ppu.bg_window2_clipmode[bg] == CLIPMODE_IN) { - if(x >= ppu.window2_left && x <= ppu.window2_right)return false; + if(x >= window2_left && x <= window2_right)return false; return true; } else { - if(x <= ppu.window2_left || x >= ppu.window2_right)return false; + if(x < window2_left || x > window2_right)return false; return true; } } else if(ppu.bg_window1_enabled[bg] == true && ppu.bg_window2_enabled[bg] == true) { if(ppu.bg_window1_clipmode[bg] == CLIPMODE_IN) { - if(x >= ppu.window1_left && x <= ppu.window1_right)w1_mask = 1; + if(x >= window1_left && x <= window1_right)w1_mask = 1; else w1_mask = 0; } else { - if(x <= ppu.window1_left || x >= ppu.window1_right)w1_mask = 1; + if(x < window1_left || x > window1_right)w1_mask = 1; else w1_mask = 0; } if(ppu.bg_window2_clipmode[bg] == CLIPMODE_IN) { - if(x >= ppu.window2_left && x <= ppu.window2_right)w2_mask = 1; + if(x >= window2_left && x <= window2_right)w2_mask = 1; else w2_mask = 0; } else { - if(x <= ppu.window2_left || x >= ppu.window2_right)w2_mask = 1; + if(x < window2_left || x > window2_right)w2_mask = 1; else w2_mask = 0; } @@ -398,67 +463,80 @@ byte w1_mask, w2_mask; //1 = masked, 0 = not masked return true; } -bool color_windows_not_obstructing(byte x, byte color_mask_type) { +bool color_windows_not_obstructing(word x, byte color_mask_type) { byte w1_mask, w2_mask; //1 = masked, 0 = not masked byte color_mask; bool r; +word window1_left, window1_right, window2_left, window2_right; if(color_mask_type == PPU_MAIN)color_mask = ppu.color_mask; else color_mask = ppu.ss_color_mask; if(color_mask == 0)return false; if(color_mask == 3)return true; + window1_left = ppu.window1_left; + window1_right = ppu.window1_right; + window2_left = ppu.window2_left; + window2_right = ppu.window2_right; + + if(ppu.bg_mode == 5 || ppu.bg_mode == 6) { + window1_left <<= 1; + window1_right <<= 1; + window2_left <<= 1; + window2_right <<= 1; + } + if(ppu.color_window1_enabled == false && ppu.color_window2_enabled == false) { r = true; } else if(ppu.color_window1_enabled == true && ppu.color_window2_enabled == false) { if(ppu.color_window1_clipmode == CLIPMODE_IN) { - if(x >= ppu.window1_left && x <= ppu.window1_right)r = false; - else r = true; + if(x >= window1_left && x <= window1_right)r = false; + else r = true; } else { - if(x <= ppu.window1_left || x >= ppu.window1_right)r = false; - else r = true; + if(x < window1_left || x > window1_right)r = false; + else r = true; } } else if(ppu.color_window1_enabled == false && ppu.color_window2_enabled == true) { if(ppu.color_window2_clipmode == CLIPMODE_IN) { - if(x >= ppu.window2_left && x <= ppu.window2_right)r = false; - else r = true; + if(x >= window2_left && x <= window2_right)r = false; + else r = true; } else { - if(x <= ppu.window2_left || x >= ppu.window2_right)r = false; - else r = true; + if(x < window2_left || x > window2_right)r = false; + else r = true; } } else if(ppu.color_window1_enabled == true && ppu.color_window2_enabled == true) { if(ppu.color_window1_clipmode == CLIPMODE_IN) { - if(x >= ppu.window1_left && x <= ppu.window1_right)w1_mask = 1; + if(x >= window1_left && x <= window1_right)w1_mask = 1; else w1_mask = 0; } else { - if(x <= ppu.window1_left || x >= ppu.window1_right)w1_mask = 1; + if(x < window1_left || x > window1_right)w1_mask = 1; else w1_mask = 0; } if(ppu.color_window2_clipmode == CLIPMODE_IN) { - if(x >= ppu.window2_left && x <= ppu.window2_right)w2_mask = 1; + if(x >= window2_left && x <= window2_right)w2_mask = 1; else w2_mask = 0; } else { - if(x <= ppu.window2_left || x >= ppu.window2_right)w2_mask = 1; + if(x < window2_left || x > window2_right)w2_mask = 1; else w2_mask = 0; } switch(ppu.color_window_mask) { case WINDOWMASK_OR: if((w1_mask | w2_mask) == 1)r = false; - else r = true; + else r = true; break; case WINDOWMASK_AND: if((w1_mask & w2_mask) == 1)r = false; - else r = true; + else r = true; break; case WINDOWMASK_XOR: if((w1_mask ^ w2_mask) == 1)r = false; - else r = true; + else r = true; break; case WINDOWMASK_XNOR: if((w1_mask ^ w2_mask) == 0)r = false; - else r = true; + else r = true; break; } } @@ -480,21 +558,8 @@ bool r; correct y tile, y / 8 * 1 row (16 tiles) must be used. */ -#define ppu_render_oam_tile_line(__m) \ - x &= 511; \ - if(x < 256) { \ - col = 0; \ - if(d0 & __m)col += 1; \ - if(d1 & __m)col += 2; \ - if(d2 & __m)col += 4; \ - if(d3 & __m)col += 8; \ - if(col) { \ - col += pal_index; \ - col += 128; \ - ppu_set_pixel(OAM, x, col); \ - } \ - } \ - x++ +#define OAM_PRI_NONE 4 +byte ppu_oam_line_pal[512], ppu_oam_line_pri[512]; void ppu_render_oam_sprite(void) { word pos, col, chr, tiledata_inc; @@ -505,14 +570,27 @@ int tile_width; tile_width = current_sprite.width >> SH_8; //e.x. 16x16 sprite = 2x2 tiles - y = ppu.vline_pos; - x = current_sprite.x; - if(current_sprite.v_flip) { - y = (current_sprite.height - 1) - (ppu.vline_pos - current_sprite.y); + if(ppu.interlace == true && (ppu.bg_mode == 5 || ppu.bg_mode == 6)) { + y = (ppu.vline_pos << SH_2) + ppu.interlace_frame; } else { - y = ppu.vline_pos - current_sprite.y; + y = ppu.vline_pos; + } + + x = current_sprite.x; + if(render.snes_width == 512) { + x <<= SH_2; + } + + if(current_sprite.v_flip) { + y = ((current_sprite.height - 1) - (ppu.vline_pos - current_sprite.y)); + } else { + y = (ppu.vline_pos - current_sprite.y); } y &= 255; + if(ppu.sprite_halve == true) { + y <<= 1; + y += ppu.interlace_frame; + } chr = current_sprite.character; tiledata_inc = (chr & 0x100)?(ppu.oam_name_sel << 13):0; //*1 @@ -526,43 +604,78 @@ int tile_width; d1 = ppu.vram[pos + 1]; d2 = ppu.vram[pos + 16]; d3 = ppu.vram[pos + 17]; - if(current_sprite.h_flip) { - ppu_render_oam_tile_line(0x01); - ppu_render_oam_tile_line(0x02); - ppu_render_oam_tile_line(0x04); - ppu_render_oam_tile_line(0x08); - ppu_render_oam_tile_line(0x10); - ppu_render_oam_tile_line(0x20); - ppu_render_oam_tile_line(0x40); - ppu_render_oam_tile_line(0x80); - } else { - ppu_render_oam_tile_line(0x80); - ppu_render_oam_tile_line(0x40); - ppu_render_oam_tile_line(0x20); - ppu_render_oam_tile_line(0x10); - ppu_render_oam_tile_line(0x08); - ppu_render_oam_tile_line(0x04); - ppu_render_oam_tile_line(0x02); - ppu_render_oam_tile_line(0x01); + for(z=0;z<8;z++) { + if(current_sprite.h_flip) { + mask = 0x01 << z; + } else { + mask = 0x80 >> z; + } + x &= 511; + if(x < render.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(ppu_oam_line_pri[x] == OAM_PRI_NONE) { + ppu_oam_line_pal[x] = col; + ppu_oam_line_pri[x] = current_sprite.priority; + } + if(render.snes_width == 512) { + if(ppu_oam_line_pri[x + 1] == OAM_PRI_NONE) { + ppu_oam_line_pal[x + 1] = col; + ppu_oam_line_pri[x + 1] = current_sprite.priority; + } + } + } + } + x++; + if(render.snes_width == 512) { + x++; + } } } } -void ppu_render_line_oam(byte priority) { -int s; +/* + +*/ + +void ppu_render_line_oam(byte layer_pos_pri0, byte layer_pos_pri1, byte layer_pos_pri2, byte layer_pos_pri3) { +int i, s; +byte layer_pos; if(ppu.bg_enabled[OAM] != true && ppu.ss_bg_enabled[OAM] != true)return; - s = 128; - while(s--) { + memset(ppu_oam_line_pri, OAM_PRI_NONE, 512); + for(s=0;s<128;s++) { ppu_set_sprite_attributes(s); - if(current_sprite.priority == priority) { -//if the sprite is within screen boundaries... render the current line from the sprite + if(ppu.sprite_halve == false) { if(ppu.vline_pos >= current_sprite.y && ppu.vline_pos < (current_sprite.y + current_sprite.height)) { ppu_render_oam_sprite(); -//or if the sprite is so close to the bottom of the screen that the bottom of it actually wraps back around to the top... } else if((current_sprite.y + current_sprite.height) >= 256 && ppu.vline_pos < ((current_sprite.y + current_sprite.height) & 255)) { ppu_render_oam_sprite(); } + } else { + if(ppu.vline_pos >= current_sprite.y && ppu.vline_pos < (current_sprite.y + (current_sprite.height >> 1))) { + ppu_render_oam_sprite(); + } else if((current_sprite.y + current_sprite.height) >= 256 && ppu.vline_pos < ((current_sprite.y + (current_sprite.height >> 1)) & 255)) { + ppu_render_oam_sprite(); + } + } + } + + for(i=0;i> tile_size) > 31)?32*32*2:0; - break; - case 2: - map_index = ((bg_y >> tile_size) > 31)?32*32*2:0; - break; - case 3: - map_index = ((bg_x >> tile_size) > 31)?32*32*2:0; - map_index += ((bg_y >> tile_size) > 31)?32*32*2*2:0; - break; + if(ppu.bg_mode == 2 || ppu.bg_mode == 4 || ppu.bg_mode == 6) { + if(ppu.bg_mode == 6) { + tile_x = (mosaic_table[screen_x + (hscroll & 15)] >> SH_16); + } else { + tile_x = (mosaic_table[screen_x + (hscroll & 7)] >> SH_8); + } + hoffset = hscroll; + voffset = vscroll; + if(tile_x != 0) { + tile_x = (tile_x - 1) & 31; + if(ppu.bg_mode == 4) { + pos = ppu.bg_tilemap_loc[BG3] + (tile_x << SH_2); + t = *((word*)ppu.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 = ppu.bg_tilemap_loc[BG3] + (tile_x << SH_2); + t = *((word*)ppu.vram + (pos >> SH_2)); + if(t & opt_valid_bit) { + hoffset = ((t & 0x1ff8) | (hscroll & 7)) & screen_width_mask; + } + pos = ppu.bg_tilemap_loc[BG3] + 64 + (tile_x << SH_2); + t = *((word*)ppu.vram + (pos >> SH_2)); + if(t & opt_valid_bit) { + voffset = (t & 0x1fff) & screen_height_mask; + } + } + } + mosaic_x = mosaic_table[(screen_x + hoffset) & screen_width_mask ]; + mosaic_y = mosaic_table[(screen_y + voffset) & screen_height_mask]; } - mosaic_x = mosaic_table[bg_x]; + switch(ppu.bg_tilemap_size[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); @@ -685,69 +847,55 @@ word *mosaic_table; t = *((word*)ppu.vram + (pos >> SH_2)); mirror_y = (t & 0x8000)?1:0; mirror_x = (t & 0x4000)?1:0; - if(((t >> 13) & 1) == priority) { - tile_num = t & 0x03ff; - if(tile_width == SH_16) { - if((mosaic_x & 15) >= 8)tile_num++; - if(mirror_x) { - if((mosaic_x & 15) >= 8)tile_num--; - else tile_num++; - } - tile_num &= 0x03ff; - } - if(tile_height == SH_16) { - if((mosaic_y & 15) >= 8)tile_num += 16; - if(mirror_y) { - if((mosaic_y & 15) >= 8)tile_num -= 16; - else tile_num += 16; - } - tile_num &= 0x03ff; - } - tile_num += (ppu.bg_tiledata_loc[bg] >> tiledata_size); - if(bg_tiledata_state[tile_num] == 1) { - ppu_render_bg_tile(color_depth, bg, tile_num); - } + if((t & 0x2000) == 0) { + layer_pos = layer_pos_pri0; + } else { + layer_pos = layer_pos_pri1; + } - pal_index = ((t >> 10) & 7) * pal_size; + 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 += (ppu.bg_tiledata_loc[bg] >> tiledata_size); - if(mirror_y) { ypos = (7 - (mosaic_y & 7)); } - else { ypos = ( (mosaic_y & 7)); } + if(bg_tiledata_state[tile_num] == 1) { + ppu_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. - while(1) { - if(mirror_x) { xpos = (7 - (mosaic_x & 7)); } - else { xpos = ( (mosaic_x & 7)); } - col = *(bg_tiledata + (tile_num << SH_64) + (ypos << SH_8) + (xpos)); - if(col) { - ppu_set_pixel(bg, screen_x, col + pal_index); - } - - bg_x++; - bg_x &= screen_width_mask; - mosaic_x = mosaic_table[bg_x]; - - if(base_xpos != ((mosaic_x >> SH_8) & 31))break; - screen_x++; - if(screen_x >= render.snes_width)break; + tile_ptr = (byte*)bg_tiledata + (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) { + ppu_set_layer_pixel(screen_x, col + pal_index); } - } else { - while(1) { - bg_x++; - bg_x &= screen_width_mask; - mosaic_x = mosaic_table[bg_x]; - if(base_xpos != ((mosaic_x >> SH_8) & 31))break; - screen_x++; - if(screen_x >= render.snes_width)break; - } + bg_x++; + bg_x &= screen_width_mask; + mosaic_x = mosaic_table[bg_x]; + + if(base_xpos != ((mosaic_x >> SH_8) & 31))break; + screen_x++; + if(screen_x >= render.snes_width)break; } } } -#ifdef PUBLIC_DOMAIN - #include "ppu_render_mode7f.cpp" -#else - #include "ppu_render_mode7i.cpp" -#endif +#include "ppu_render_mode7.cpp" diff --git a/bsnes/ppu/ppu_render_mode7.cpp b/bsnes/ppu/ppu_render_mode7.cpp new file mode 100644 index 00000000..8b8d02d5 --- /dev/null +++ b/bsnes/ppu/ppu_render_mode7.cpp @@ -0,0 +1,121 @@ +/* + The algorithm in this file was derived from the snes9x source code. + The snes9x source code is not public domain. If you wish to use this + code, you must abide by the terms of the snes9x license. If you do not + wish to abide by the snes9x licensing terms, please define the precompiler + variable PUBLIC_DOMAIN so that ppu_render_mode7f.cpp is used instead of + this file. You must also remove this file from any work that you release + that does not follow the snes9x license. + See license.txt for more info on the license of this software and snes9x. +*/ + +#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 ppu_render_line_m7(byte layer_pos_bg1, byte layer_pos_bg2_pri0, byte 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; +byte layer_pos; + hoffset = (CAST_WORDTOINT(ppu.m7hofs) << 7) >> 7; + voffset = (CAST_WORDTOINT(ppu.m7vofs) << 7) >> 7; + + centerx = (CAST_WORDTOINT(ppu.m7x) << 7) >> 7; + centery = (CAST_WORDTOINT(ppu.m7y) << 7) >> 7; + + if(ppu.mode7_vflip == true) { + yy = 223 - ppu.vline_pos; + } else { + yy = ppu.vline_pos; + } + yy += CLIP_10BIT_SIGNED(voffset - centery); + + m7b = CAST_WORDTOINT(ppu.m7b) * yy + (centerx << 8); + m7d = CAST_WORDTOINT(ppu.m7d) * yy + (centery << 8); + + step_m7a = CAST_WORDTOINT(ppu.m7a); + step_m7c = CAST_WORDTOINT(ppu.m7c); + + xx = CLIP_10BIT_SIGNED(hoffset - centerx); + + m7a = CAST_WORDTOINT(ppu.m7a) * xx; + m7c = CAST_WORDTOINT(ppu.m7c) * xx; + + for(x=0;x<256;x++) { + px = ((m7a + m7b) >> 8); + py = ((m7c + m7d) >> 8); + + switch(ppu.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 = ppu.vram[(ty * 128 + tx) << 1]; + palette = ppu.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 = ppu.vram[(ty * 128 + tx) << 1]; + palette = ppu.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 = ppu.vram[(ty * 128 + tx) << 1]; + palette = ppu.vram[(((tile << SH_64) + ((py & 7) << SH_8) + (px & 7)) << 1) + 1]; + } + break; + } + + if(ppu.mode7_extbg == false) { + if(palette) { + layer_pos = layer_pos_bg1; + if(ppu.mode7_hflip == true) { + ppu_set_layer_pixel(255 - x, palette); + } else { + ppu_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(ppu.mode7_hflip == true) { + ppu_set_layer_pixel(255 - x, palette); + } else { + ppu_set_layer_pixel(x, palette); + } + } + } + + m7a += step_m7a; + m7c += step_m7c; + } +} diff --git a/bsnes/ppu/ppu_render_mode7f.cpp b/bsnes/ppu/ppu_render_mode7f.cpp deleted file mode 100644 index 3fd66357..00000000 --- a/bsnes/ppu/ppu_render_mode7f.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - This mode7 code was derived from my own research, assisted by - information in the public domain. It is therefore redistributed - to the public domain. This code is infinitesimally less accurate - than ppu_render_mode7i.cpp, but nearly twice as slow. - However, this file contains no licensing restrictions. - Please define the precompiler variable PUBLIC_DOMAIN to use this - code instead of mode7i. -*/ - -/* - *1 - converts 16-bit word value to float within the range -128/127. decimal - has range of 256 with steps of 0.00390625 - *2 - (int)float will turn anything from -0.999 to 0.999 to 0. this code will - check to see if the number is negative, and if the decimal place (.xxx) - is zero or not. If value is positive or the decimal place ends on .000, - the number is converted directly to an int. otherwise, one is subtracted - to make up for the rounding error of 1 mentioned above. - result is masked by 1023 (width / height of map is 1024) to prevent - negative values from causing an error with the division in the tile - calculation below. - *3 - mode7 vram consists of 32k of data. there are two 16k regions interleaved - in bytes. the low byte is the tile number, and the high byte is tile data. - the tile data directly indexes into the palette. the map is 128*128, and - there are 256 possible characters. each character is 64 bytes in length. -*/ -void ppu_render_line_m7(void) { -int x, y, sx, sy; -byte tile, palette; -float x_stepx, x_stepy, y_stepx, y_stepy; -float centerx, centery, scrollx, scrolly, startx, starty; - y = (ppu.mode7_vflip == true)?223 - ppu.vline_pos:ppu.vline_pos; - -//*1 - x_stepx = (float)((signed short)ppu.m7a) / 256.0; - x_stepy = (float)((signed short)ppu.m7b) / 256.0; - y_stepx = (float)((signed short)ppu.m7c) / 256.0; - y_stepy = (float)((signed short)ppu.m7d) / 256.0; - - centerx = (float)(1.0 - x_stepx) * (signed short)ppu.m7x - x_stepy * (signed short)ppu.m7y; - centery = (float)(1.0 - y_stepy) * (signed short)ppu.m7y - y_stepx * (signed short)ppu.m7x; - - scrollx = (float)((signed short)ppu.m7hofs); - scrolly = (float)((signed short)ppu.m7vofs); - - startx = centerx + ((scrollx) * x_stepx) + ((scrolly + y) * x_stepy); - starty = centery + ((scrollx) * y_stepx) + ((scrolly + y) * y_stepy); - - for(x=0;x<256;x++) { -//*2 - if(startx < 0.0 && (int)(startx * 32768) & 32767) { - sx = (int)(startx - 1) & 1023; - } else { - sx = (int)startx & 1023; - } - if(starty < 0.0 && (int)(starty * 32768) & 32767) { - sy = (int)(starty - 1) & 1023; - } else { - sy = (int)starty & 1023; - } -//*3 - tile = ppu.vram[(((sy / 8) & 127) * 128 + ((sx / 8) & 127)) << 1]; - palette = ppu.vram[((tile * 64 + (sy & 7) * 8 + (sx & 7)) << 1) + 1]; - if(palette) { - if(ppu.mode7_hflip == true) { - ppu_set_pixel(BG1, 255 - x, palette); - } else { - ppu_set_pixel(BG1, x, palette); - } - } - startx += x_stepx; - starty += y_stepx; - } -} diff --git a/bsnes/ppu/ppu_render_mode7i.cpp b/bsnes/ppu/ppu_render_mode7i.cpp deleted file mode 100644 index 6fc9dffe..00000000 --- a/bsnes/ppu/ppu_render_mode7i.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - The algorithm in this file was derived from the snes9x source code. - The snes9x source code is not public domain. If you wish to use this - code, you must abide by the terms of the snes9x license. If you do not - wish to abide by the snes9x licensing terms, please define the precompiler - variable PUBLIC_DOMAIN so that ppu_render_mode7f.cpp is used instead of - this file. You must also remove this file from any work that you release - that does not follow the snes9x license. - See license.txt for more info on the license of this software and snes9x. -*/ - -#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 ppu_render_line_m7(void) { -int x; -int step_m7a, step_m7c, m7a, m7b, m7c, m7d; -int hoffset, voffset; -int centerx, centery; -int xx, yy; -int px, py; -int tile, palette; - hoffset = (CAST_WORDTOINT(ppu.m7hofs) << 7) >> 7; - voffset = (CAST_WORDTOINT(ppu.m7vofs) << 7) >> 7; - - centerx = (CAST_WORDTOINT(ppu.m7x) << 7) >> 7; - centery = (CAST_WORDTOINT(ppu.m7y) << 7) >> 7; - - if(ppu.mode7_vflip == true) { - yy = 223 - ppu.vline_pos; - } else { - yy = ppu.vline_pos; - } - yy += CLIP_10BIT_SIGNED(voffset - centery); - - m7b = CAST_WORDTOINT(ppu.m7b) * yy + (centerx << 8); - m7d = CAST_WORDTOINT(ppu.m7d) * yy + (centery << 8); - - step_m7a = CAST_WORDTOINT(ppu.m7a); - step_m7c = CAST_WORDTOINT(ppu.m7c); - - xx = CLIP_10BIT_SIGNED(hoffset - centerx); - - m7a = CAST_WORDTOINT(ppu.m7a) * xx; - m7c = CAST_WORDTOINT(ppu.m7c) * xx; - - for(x=0;x<256;x++) { - px = ((m7a + m7b) >> 8) & 1023; - py = ((m7c + m7d) >> 8) & 1023; - - tile = ppu.vram[(((py / 8) & 127) * 128 + ((px / 8) & 127)) << 1]; - palette = ppu.vram[((tile * 64 + (py & 7) * 8 + (px & 7)) << 1) + 1]; - - if(ppu.mode7_hflip == true) { - ppu_set_pixel(BG1, 255 - x, palette); - } else { - ppu_set_pixel(BG1, x, palette); - } - - m7a += step_m7a; - m7c += step_m7c; - } -} diff --git a/bsnes/ppu/ppu_screen.cpp b/bsnes/ppu/ppu_screen.cpp index 9b6c7990..75db08bd 100644 --- a/bsnes/ppu/ppu_screen.cpp +++ b/bsnes/ppu/ppu_screen.cpp @@ -24,13 +24,17 @@ void mmio_w2100(byte value) { m: screen mode */ void mmio_w2105(byte value) { +static byte prev_mode = 0x00; ppu.bg_tile_size[BG4] = (value & 0x80)?1:0; ppu.bg_tile_size[BG3] = (value & 0x40)?1:0; ppu.bg_tile_size[BG2] = (value & 0x20)?1:0; ppu.bg_tile_size[BG1] = (value & 0x10)?1:0; ppu.bg_priority_mode = (value & 0x08)?1:0; ppu.bg_mode = (value & 0x07); - video_setsnesmode(); + if(prev_mode != ppu.bg_mode) { + video_setsnesmode(); + prev_mode = ppu.bg_mode; + } } /* @@ -80,13 +84,18 @@ void mmio_w212d(byte value) { /* $2133 : screen mode settings - ?????h?i + ?m???ohi - h: snes height (0 = 224, 1 = 240) - i: interlace (0 = off, 1 = on) + m: mode7 extbg (0 = off, 1 = on) + o: overscan (0 = off, 1 = on) + h: sprite halve (0 = off, 1 = on) + i: interlace (0 = off, 1 = on) */ void mmio_w2133(byte value) { - ppu.toggle_visible_scanlines = (value & 0x04)?240:224; - ppu.interlace = (value & 0x01)?true:false; + ppu.mode7_extbg = (value & 0x40)?true:false; + ppu.overscan = (value & 0x04)?true:false; + ppu.visible_scanlines = (value & 0x04)?239:224; + ppu.sprite_halve = (value & 0x02)?true:false; + ppu.toggle_interlace = (value & 0x01)?true:false; video_setsnesmode(); } diff --git a/bsnes/ppu/ppu_scroll.cpp b/bsnes/ppu/ppu_scroll.cpp index c5345950..fd7908b5 100644 --- a/bsnes/ppu/ppu_scroll.cpp +++ b/bsnes/ppu/ppu_scroll.cpp @@ -11,14 +11,12 @@ */ void mmio_w210d(byte value) { ppu.bg_hscroll_pos[BG1] = (value << 8) | (ppu.bg_hscroll_pos[BG1] >> 8); - ppu.m7hofs = (value << 8) | m7_latch; - m7_latch = value; + ppu.m7hofs = (value << 8) | (ppu.m7hofs >> 8); } void mmio_w210e(byte value) { ppu.bg_vscroll_pos[BG1] = (value << 8) | (ppu.bg_vscroll_pos[BG1] >> 8); - ppu.m7vofs = (value << 8) | m7_latch; - m7_latch = value; + ppu.m7vofs = (value << 8) | (ppu.m7vofs >> 8); } void mmio_w210f(byte value) { diff --git a/bsnes/ppu/ppu_spc.cpp b/bsnes/ppu/ppu_spc.cpp new file mode 100644 index 00000000..7d4a7e5e --- /dev/null +++ b/bsnes/ppu/ppu_spc.cpp @@ -0,0 +1,34 @@ +byte mmio_rspc(byte port) { +#ifndef NO_SPC700 + return cpu_apu_bridge->cpu_read(port); +#else +static byte t = 0, counter = 0; +byte x; + if(rand() & 1) { + x = rand() & 7; + if(x == 0) { + if(!(port & 1))t = gx816->regs.a.w; + else t = gx816->regs.a.w >> 8; + } + else if(x == 1) { + if(!(port & 1))t = gx816->regs.x; + else t = gx816->regs.x >> 8; + } + else if(x == 2) { + if(!(port & 1))t = gx816->regs.y; + else t = gx816->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; +#endif +} + +void mmio_wspc(byte port, byte value) { +#ifndef NO_SPC700 + cpu_apu_bridge->cpu_write(port, value); +#endif +} diff --git a/bsnes/ppu/ppu_timing.cpp b/bsnes/ppu/ppu_timing.cpp index 31169975..59a36077 100644 --- a/bsnes/ppu/ppu_timing.cpp +++ b/bsnes/ppu/ppu_timing.cpp @@ -1,13 +1,19 @@ /* - $213d : vertical latch position + $2137 : counter latch - returns the current scanline. must read from - $2137 before reading from this register. + reading from this register will latch the x/y + counter positions, but only if bit 7 of $4201 + is set. the default state of this register is + $ff on snes power on/reset. */ byte mmio_r2137(void) { - ppu.latch_toggle = 0; - ppu.latch_vpos = snes_time->vscan_pos; - ppu.latch_hpos = snes_time->hscan_pos; + if(ppu.io4201 & 0x80) { + snes_time->set_scan_pos(snes_time->master_cycles, false); + ppu.latch_toggle = 0; + ppu.latch_vpos = snes_time->vscan_pos; + ppu.latch_hpos = snes_time->hscan_pos; + ppu.counter_latched = true; + } return 0x00; } @@ -29,27 +35,54 @@ word r; /* $213e : ppu1 status register + trm-vvvv - trm0vvvv t: time over (?) r: range over (?) m: master/slave mode select (?) - v: version # (returns 1) + -: open bus (?) + v: PPU1 (5c77) version number [1] */ byte mmio_r213e(void) { - return 0x01; +byte r = 0x00; + r |= 0x01; //ppu1 version # + return r; } /* $213f : ppu2 status register - fl0mvvvv - f: field # (?) - l: external signal applied (should be 0) + ilcmvvvv + + i: interlace frame (0=even, 1=odd) + l: counter latched + c: open bus complement m: ntsc/pal mode (0=ntsc, 1=pal) - v: version # (returns 0) + v: PPU2 (5c78) version number [3] + +notes: + bit 6 (l): counter is latched by reading $2137, + or a 1->0 transition of $4201 bit 7. + + bit 5 (c): this is not implemented correctly. basically, + my copier (super ufo 8.3j) breaks the snes open bus. + as a result, 0x00 is always returned instead of the + open bus values. since this is the complement of that + value, 1 is always returned. I am emulating what my + copier returns until I can get a copier that supports + open bus correctly. */ byte mmio_r213f(void) { - return 0x00; +byte r = 0x00; + r |= ppu.interlace_frame << 7; + if(!(ppu.io4201 & 0x80)) { + r |= 1 << 6; + } else if(ppu.counter_latched == true) { + r |= 1 << 6; + ppu.counter_latched = false; + } + r |= 1 << 5; + r |= 0x03; //ppu2 version # + return r; } /* @@ -72,6 +105,36 @@ void mmio_w4200(byte value) { ppu.auto_joypad_read = (value & 0x01)?true:false; } +/* + $4201 : programmable i/o port + l??????? + + l: counter latch + + upon power on/reset, this value is set to 0xff. + clearing bit 7 will result in the x/y dot position + being set in $213c/$213d. the counters cannot be + latched again by writing a 0 to bit 7 until a 1 is + written to this bit first. reading $2137 while bit 7 + is cleared will not latch the counters. + + examples (+ = counter latched, - = counter not latched): + $00->$4201+ + $80->$4201- + $00->$4201+ $00->$4201- $80->$4201- $00->$4201+ + $2137->a+ $00->$4201+ $2137->a- +*/ +void mmio_w4201(byte value) { + if((ppu.io4201 & 0x80) && !(value & 0x80)) { + snes_time->set_scan_pos(snes_time->master_cycles + 4, false); + ppu.latch_toggle = 0; + ppu.latch_vpos = snes_time->vscan_pos; + ppu.latch_hpos = snes_time->hscan_pos; + ppu.counter_latched = true; + } + ppu.io4201 = value; +} + /* $4207/$4208 : horizontal counter position @@ -106,18 +169,25 @@ void mmio_w420a(byte value) { 1 = FastROM */ void mmio_w420d(byte value) { - gx816->toggle_memory_speed = (value) & 0x01; + gx816->memory_speed = (value) & 0x01; + snes_time->set_speed_map(gx816->memory_speed); } /* $4210 : nmi status - n------- + n---vvvv - n: outside nmi (0=no, 1=yes) + n: nmi occurred (0=no, 1=yes) + -: open bus (?) + v: CPU (5a22) version number [2] + + value is set/cleared regardless of whether or not + NMIs are enabled in $4200 bit 7. */ byte mmio_r4210(void) { -byte r; - r = (gx816->nmi_pin ^ 1)?0x80:0x00; +byte r = 0x00; + r |= (gx816->nmi_pin ^ 1)?0x80:0x00; + r |= 0x02; //cpu version # gx816->nmi_pin = 1; return r; } @@ -130,8 +200,8 @@ byte r; ?: unknown, always return 1? */ byte mmio_r4211(void) { -byte r; - r = 0x40; +byte r = 0x00; + r |= 0x40; if(ppu.irq_triggered == true)r |= 0x80; ppu.irq_triggered = false; return r; @@ -153,8 +223,16 @@ byte r; if(snes_time->vscan_pos >= (ppu.visible_scanlines + 1) && snes_time->vscan_pos <= (ppu.visible_scanlines + 3))r |= 0x01; //set when the SNES is in hblank/vblank - if(snes_time->hscan_pos >= 256)r |= 0x40; - if(snes_time->vscan_pos >= ppu.visible_scanlines)r |= 0x80; + if(snes_time->hcycle_pos <= 4 || snes_time->hcycle_pos >= 1098)r |= 0x40; + if(snes_time->vscan_pos == 0 || snes_time->vscan_pos >= (ppu.visible_scanlines + 1)) { + if(snes_time->vscan_pos == 0) { + if(snes_time->hcycle_pos < 2)r |= 0x80; + } else if(snes_time->vscan_pos == (ppu.visible_scanlines + 1)) { + if(snes_time->hcycle_pos >= 2)r |= 0x80; + } else { + r |= 0x80; + } + } return r; } diff --git a/bsnes/ppu/ppu_vram.cpp b/bsnes/ppu/ppu_vram.cpp index 5ce65a35..b4708a51 100644 --- a/bsnes/ppu/ppu_vram.cpp +++ b/bsnes/ppu/ppu_vram.cpp @@ -40,24 +40,28 @@ void mmio_w210c(byte value) { /* $2115 : vram write counter - i---ggrr + i---mmrr i: 0 = increment on $2118/$2139 1 = increment on $2119/$213a - g: graphic increment + m: address remapping + 00 = no remapping + 01 = aaaaaaaaBBBccccc -> aaaaaaaacccccBBB + 10 = aaaaaaaBBBcccccc -> aaaaaaaccccccBBB + 11 = aaaaaaBBBccccccc -> aaaaaacccccccBBB r: increment rate - 00 = increment by 2 - 01 = increment by 64 + 00 = increment by 1 + 01 = increment by 32 10 = increment by 128 - 11 = increment by 256 + 11 = increment by 128 */ void mmio_w2115(byte value) { -if(value & 0x0c)dprintf("$2115 = %0.2x", value); - ppu.vram_inc_reg = (value & 0x80)?1:0; + ppu.vram_inc_reg = (value & 0x80)?1:0; + ppu.vram_remap_mode = (value >> 2) & 3; switch(value & 3) { case 0x00:ppu.vram_inc_size = 1;break; case 0x01:ppu.vram_inc_size = 32;break; - case 0x02:ppu.vram_inc_size = 64;break; + case 0x02:ppu.vram_inc_size = 128;break; case 0x03:ppu.vram_inc_size = 128;break; } } @@ -69,10 +73,31 @@ if(value & 0x0c)dprintf("$2115 = %0.2x", value); this value is doubled to get true write position (0000-ffff) */ void mmio_w2116(byte value) { - ppu.vram_write_pos = ((ppu.vram_write_pos & 0xff00) | value) & 0x7fff; + ppu.vram_write_pos = ((ppu.vram_write_pos & 0xff00) | value); } void mmio_w2117(byte value) { - ppu.vram_write_pos = ((value << 8) | (ppu.vram_write_pos & 0xff)) & 0x7fff; + ppu.vram_write_pos = ((value << 8) | (ppu.vram_write_pos & 0xff)); +} + +word mmio_vram_remap(void) { +word addr, t; + addr = (ppu.vram_write_pos << 1); + switch(ppu.vram_remap_mode) { + case 0: + break; + case 1: + t = (addr >> 5) & 7; + addr = (addr & 0xff00) | ((addr & 0x001f) << 3) | t; + break; + case 2: + t = (addr >> 6) & 7; + addr = (addr & 0xfe00) | ((addr & 0x003f) << 3) | t; + break; + case 3: + t = (addr >> 7) & 7; + addr = (addr & 0xfc00) | ((addr & 0x007f) << 3) | t; + } + return addr; } /* @@ -82,50 +107,60 @@ void mmio_w2117(byte value) { the settings of $2115 (vram_inc_size / vram_inc_reg) */ void mmio_w2118(byte value) { -word w = ppu.vram_write_pos * 2; +word w; + w = mmio_vram_remap(); ppu.vram[w] = value; if(ppu.vram_inc_reg == 0) { ppu.vram_write_pos += ppu.vram_inc_size; - ppu.vram_write_pos &= 0x7fff; } ppu_bg_tiledata_state[TILE_2BIT][(w >> 4)] = 1; ppu_bg_tiledata_state[TILE_4BIT][(w >> 5)] = 1; ppu_bg_tiledata_state[TILE_8BIT][(w >> 6)] = 1; + + debug_test_bp(BPSRC_VRAM, BP_WRITE, w, value); } void mmio_w2119(byte value) { -word w = ppu.vram_write_pos * 2 + 1; +word w; + w = mmio_vram_remap() + 1; ppu.vram[w] = value; if(ppu.vram_inc_reg == 1) { ppu.vram_write_pos += ppu.vram_inc_size; - ppu.vram_write_pos &= 0x7fff; } ppu_bg_tiledata_state[TILE_2BIT][(w >> 4)] = 1; ppu_bg_tiledata_state[TILE_4BIT][(w >> 5)] = 1; ppu_bg_tiledata_state[TILE_8BIT][(w >> 6)] = 1; + + debug_test_bp(BPSRC_VRAM, BP_WRITE, w, value); } /* $2139/$213a : vram read */ byte mmio_r2139(void) { -word w = ppu.vram_write_pos * 2; byte r; - r = ppu.vram[w]; +word w; + w = mmio_vram_remap(); + r = ppu.vram_read_buffer; if(ppu.vram_inc_reg == 0) { + ppu.vram_read_buffer = *((word*)ppu.vram + (w >> 1)); ppu.vram_write_pos += ppu.vram_inc_size; - ppu.vram_write_pos &= 0x7fff; } + + debug_test_bp(BPSRC_VRAM, BP_READ, w, r); return r; } byte mmio_r213a(void) { -word w = ppu.vram_write_pos * 2 + 1; byte r; - r = ppu.vram[w]; +word w; + w = mmio_vram_remap() + 1; + r = ppu.vram_read_buffer >> 8; if(ppu.vram_inc_reg == 1) { + ppu.vram_read_buffer = *((word*)ppu.vram + (w >> 1)); ppu.vram_write_pos += ppu.vram_inc_size; - ppu.vram_write_pos &= 0x7fff; } + + debug_test_bp(BPSRC_VRAM, BP_READ, w, r); return r; } diff --git a/bsnes/ppu/ppu_wram.cpp b/bsnes/ppu/ppu_wram.cpp index 87f59f23..af47708d 100644 --- a/bsnes/ppu/ppu_wram.cpp +++ b/bsnes/ppu/ppu_wram.cpp @@ -1,11 +1,19 @@ /* - $2180 : wram write + $2180 : wram read/write write byte to wram write pointer ($2181-$2183), then increment pointer. always stays within 7e0000-7fffff, high 7 bits of 24-bit offset ignored. */ +byte mmio_r2180(void) { +byte r; + r = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, 0x7e0000 | ppu.wram_write_pos); + ppu.wram_write_pos++; + ppu.wram_write_pos &= 0x01ffff; + return r; +} + void mmio_w2180(byte value) { - gx816->mem_write(MEMMODE_LONG, MEMSIZE_BYTE, 0x7e0000 | ppu.wram_write_pos, value); + gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, 0x7e0000 | ppu.wram_write_pos, value); ppu.wram_write_pos++; ppu.wram_write_pos &= 0x01ffff; } diff --git a/bsnes/timing.obj b/bsnes/timing.obj deleted file mode 100644 index 450d6b3d0804783094608f43206c4e62ad2cfdd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3162 zcma)-?`vCC7{|{|(j@(rAGQ;z%A$sfFO1#dY86Iq>L#13+ES=lt_Ps4p8K40 zzUT8i=iGD79TK|P^^;el-7d!ZnPQ=2E|rkxQ)-pnn$()H%t}=YxNyffw)%$3w}~WML}!f+i*18_+GPS^@PFKHp#?FMy6EXfCP=*r031 zTZLvr)ivYwVf-dEwiY{EX6YWh0CIW{nokV6rt^hn!=T%B z{lME)HE_8#J-^Ju(L5I9ix#KI=A`9c`qxFLe?o~Is)*LK-lm&8aXp4B4@1O~FG3P-& z3Qfn3W{_)Q-sP_qP2BtT7u>7Yz2`5((|E<2nCmRo-qIr!YsFl?Si80`yGvvzMV`+$ zjY|Eo`BC)8c~%B4+KRbn(O+K(e}oL!1@VFE4-b}uci$I(Pnj#y$ za5mV1BrXd}KS~_~FZL8%NUKBq!$Gg=x=nHw7d=c8#Ok_(3nXWCu*+8vMA@T+rGe!j_~Gob-c1=gO4L+-15h+G0R%J4TOo-&HGbC=FW?TmJ&kxX^F5P*Q9 z{&b~(Nhc4Wg{*~>$xBk9nmHDoTRj#@S}d{XLbVHhC@I$C?3ryn)*@QST$WkTm1rir zEMz(%I{BBY6IXQd2ZV*STF7({o5`&fay!=qP-2PLmh1h0b@EqeA#1mg>54X!+bv|; z-&lE+WS81k|I^7^N+Zrd<2R+-%1rLGkmvSJ+eiN4O8}L^2smWDBt@AD?d=dYTW_MEU)QW}1mis7x~zrK-hiDl(z= SA{Da92`R;wHD{R{R`7qD{x!+~ diff --git a/bsnes/timing/timing.cpp b/bsnes/timing/timing.cpp index 60449829..5508de23 100644 --- a/bsnes/timing/timing.cpp +++ b/bsnes/timing/timing.cpp @@ -1,103 +1,370 @@ #include "../base.h" #include "../cpu/g65816.h" -extern g65816 *gx816; #include "timing.h" -snes_timer::snes_timer() { - master_cycles = 0; - vscan_pos = 0; - hscan_pos = 0; +extern g65816 *gx816; +extern ppustate ppu; +extern debugstate debugger; +snes_timer *snes_time; + +/* + apu_cycles is incremented to keep in sync with master_cycles. + (n << 5) is only a guess that one apu cycle is equivalent to + 32 cpu cycles. +*/ +void add_apu_cycles(int n) { + snes_time->apu_cycles += n; + snes_time->bridge.apu_cycles += (n << 5); } -#define MEMSPEED_FAST 6 -#define MEMSPEED_SLOW 8 -#define MEMSPEED_XSLOW 12 -ulong snes_timer::get_master_cycle_count(ulong offset) { -byte db; -word addr; - db = (offset >> 16) & 0xff; - addr = (offset) & 0xffff; - if(db >= 0x00 && db <= 0x3f) { - if (addr >= 0x0000 && addr <= 0x1fff)return MEMSPEED_SLOW; - else if(addr >= 0x2000 && addr <= 0x3fff)return MEMSPEED_FAST; - else if(addr >= 0x4000 && addr <= 0x41ff)return MEMSPEED_XSLOW; - else if(addr >= 0x4200 && addr <= 0x5fff)return MEMSPEED_FAST; - else if(addr >= 0x6000 && addr <= 0xffff)return MEMSPEED_SLOW; - } else if(db >= 0x40 && db <= 0x7f) { - return MEMSPEED_SLOW; - } else if(db >= 0x80 && db <= 0xbf) { - if (addr >= 0x0000 && addr <= 0x1fff)return MEMSPEED_SLOW; - else if(addr >= 0x2000 && addr <= 0x3fff)return MEMSPEED_FAST; - else if(addr >= 0x4000 && addr <= 0x41ff)return MEMSPEED_XSLOW; - else if(addr >= 0x4200 && addr <= 0x5fff)return MEMSPEED_FAST; - else if(addr >= 0x6000 && addr <= 0x7fff)return MEMSPEED_SLOW; - else if(addr >= 0x8000 && addr <= 0xffff) { - if(gx816->memory_speed == MEMSPEED_SLOWROM) { - return MEMSPEED_SLOW; - } else { //gx816->memory_speed == MEMSPEED_FASTROM - return MEMSPEED_FAST; +void snes_timer::add_cpu_cycles(byte count, byte speed) { +ulong cycles = count * speed; + master_cycles += cycles; + bridge.cpu_cycles += cycles; +} + +void snes_timer::add_cpu_pcycles(byte count) { +ulong speed = mem_speed_map[(gx816->regs.pc & 0xffffff) >> 9]; +ulong cycles = count * speed; + master_cycles += cycles; + bridge.cpu_cycles += cycles; +} + +void snes_timer::add_cpu_mcycles(byte count, ulong addr) { +ulong speed = mem_speed_map[(addr & 0xffffff) >> 9]; +ulong cycles = count * speed; + master_cycles += cycles; + bridge.cpu_cycles += cycles; +} + +void snes_timer::add_cpu_scycles(byte count) { +ulong cycles = (count << 3); //count * 8 + master_cycles += cycles; + bridge.cpu_cycles += cycles; +} + +void snes_timer::add_cpu_icycles(byte count) { +ulong cycles = (count << 2) + (count << 1); //count * 6 + master_cycles += cycles; + bridge.cpu_cycles += cycles; +} + +void snes_timer::set_speed_map(byte speed) { + if(speed == MEMSPEED_SLOWROM) { + mem_speed_map = sm_slowrom; + } else { //speed == MEMSPEED_FASTROM + mem_speed_map = sm_fastrom; + } +} + +void snes_timer::build_speed_map(void) { +int i; +byte db; +word addr; +ulong z; + sm_slowrom = (byte*)malloc(0x8000); + sm_fastrom = (byte*)malloc(0x8000); + for(i=0;i<0x8000;i++) { + z = (i << 9); + db = (z >> 16); + addr = (z & 0xffff); + if(db >= 0x00 && db <= 0x3f) { + if (addr >= 0x0000 && addr <= 0x1fff) { + sm_slowrom[i] = MEMSPEED_SLOW; + sm_fastrom[i] = MEMSPEED_SLOW; } - } - } else if(db >= 0xc0 && db <= 0xff) { - if(gx816->memory_speed == MEMSPEED_SLOWROM) { - return MEMSPEED_SLOW; - } else { //gx816->memory_speed == MEMSPEED_FASTROM - return MEMSPEED_FAST; + else if(addr >= 0x2000 && addr <= 0x3fff) { + sm_slowrom[i] = MEMSPEED_FAST; + sm_fastrom[i] = MEMSPEED_FAST; + } + else if(addr >= 0x4000 && addr <= 0x41ff) { + sm_slowrom[i] = MEMSPEED_XSLOW; + sm_fastrom[i] = MEMSPEED_XSLOW; + } + else if(addr >= 0x4200 && addr <= 0x5fff) { + sm_slowrom[i] = MEMSPEED_FAST; + sm_fastrom[i] = MEMSPEED_FAST; + } + else { //(addr >= 0x6000 && addr <= 0xffff) + sm_slowrom[i] = MEMSPEED_SLOW; + sm_fastrom[i] = MEMSPEED_SLOW; + } + } else if(db >= 0x40 && db <= 0x7f) { + sm_slowrom[i] = MEMSPEED_SLOW; + sm_fastrom[i] = MEMSPEED_SLOW; + } else if(db >= 0x80 && db <= 0xbf) { + if (addr >= 0x0000 && addr <= 0x1fff) { + sm_slowrom[i] = MEMSPEED_SLOW; + sm_fastrom[i] = MEMSPEED_SLOW; + } + else if(addr >= 0x2000 && addr <= 0x3fff) { + sm_slowrom[i] = MEMSPEED_FAST; + sm_fastrom[i] = MEMSPEED_FAST; + } + else if(addr >= 0x4000 && addr <= 0x41ff) { + sm_slowrom[i] = MEMSPEED_XSLOW; + sm_fastrom[i] = MEMSPEED_XSLOW; + } + else if(addr >= 0x4200 && addr <= 0x5fff) { + sm_slowrom[i] = MEMSPEED_FAST; + sm_fastrom[i] = MEMSPEED_FAST; + } + else if(addr >= 0x6000 && addr <= 0x7fff) { + sm_slowrom[i] = MEMSPEED_SLOW; + sm_fastrom[i] = MEMSPEED_SLOW; + } + else { //(addr >= 0x8000 && addr <= 0xffff) + sm_slowrom[i] = MEMSPEED_SLOW; + sm_fastrom[i] = MEMSPEED_FAST; + } + } else { //(db >= 0xc0 && db <= 0xff) + sm_slowrom[i] = MEMSPEED_SLOW; + sm_fastrom[i] = MEMSPEED_FAST; } } - return MEMSPEED_FAST; //this should never be hit } /* - vpa = 1, vda = 1 -> add_cpu_pcycles (opcode fetch) - vpa = 1, vda = 0 -> add_cpu_pcycles (operand fetch) - vpa = 0, vda = 1 -> add_cpu_dcycles (memory fetch) - vpa = 0, vda = 0 -> add_cpu_icycles (internal operation) + 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 } + + latch_table_a is used for interlace-even, interlace-odd, and + non-interlace-even frames. this is done to conserve memory. + interlace-even frames have one extra scanline, but the + cycle-to-x/y positions are still identical. + latch_table_b is used for non-interlace-odd, because these + frames have one scanline that is 4 master cycles shorter than + the others. this would offset all x/y positions from (322,240) + and onward without a separate table. + + both tables are one scanline longer than the snes allows so that + if the x/y positions are refreshed and the cycle position used + goes beyond the end of the frame, it won't access an invalid + memory address. the routine will then see that the y position + is higher than the current frame allows, and it will reset the + y position at that time. */ -void snes_timer::add_cpu_pcycles(ulong n) { -ulong speed; - speed = get_master_cycle_count(gx816->regs.pc); - master_cycles += n * speed; -} +void snes_timer::build_dot_map(void) { +int x, y, cycle; +int ptr; + latch_table_a = (latch_pos*)malloc(264 * (1364 / 2) * sizeof(latch_pos)); + latch_table_b = (latch_pos*)malloc(263 * (1364 / 2) * sizeof(latch_pos)); -void snes_timer::add_cpu_scycles(ulong n) { -ulong speed; - speed = get_master_cycle_count(gx816->regs.s); - master_cycles += n * speed; -} - -void snes_timer::add_cpu_mcycles(ulong n, ulong addr) { -ulong speed; - speed = get_master_cycle_count(addr); - master_cycles += n * speed; -} - -void snes_timer::add_cpu_icycles(ulong n) { - master_cycles += n * MEMSPEED_FAST; -} - -void snes_timer::add_cpu_icycles(ulong n, ulong flags) { - if(flags & TIMING_BANKCROSS) { - if(gx816->index_bank_crossed == true)n++; + ptr = 0; + for(y=0;y<264;y++) { + for(x=cycle=0;x<340;x++) { + latch_table_a[ptr].cx = cycle; + latch_table_a[ptr].x = x; + latch_table_a[ptr].y = y; + ptr++; + cycle += 2; + latch_table_a[ptr].cx = cycle; + latch_table_a[ptr].x = x; + latch_table_a[ptr].y = y; + ptr++; + cycle += 2; + if(x == 322 || x == 326) { + latch_table_a[ptr].cx = cycle; + latch_table_a[ptr].x = x; + latch_table_a[ptr].y = y; + ptr++; + cycle += 2; + } + } } -//regs.dl != 0x00 - if(flags & TIMING_CONDITION2) { - if((gx816->regs.d & 0xff) != 0x00)n++; + + ptr = 0; + for(y=0;y<263;y++) { + for(x=cycle=0;x<340;x++) { + latch_table_b[ptr].cx = cycle; + latch_table_b[ptr].x = x; + latch_table_b[ptr].y = y; + ptr++; + cycle += 2; + latch_table_b[ptr].cx = cycle; + latch_table_b[ptr].x = x; + latch_table_b[ptr].y = y; + ptr++; + cycle += 2; + if(y != 240 && (x == 322 || x == 326)) { + latch_table_b[ptr].cx = cycle; + latch_table_b[ptr].x = x; + latch_table_b[ptr].y = y; + ptr++; + cycle += 2; + } + } } -//add 1 cycle for indexing across page boundaries, or write, or x=0 - if(flags & TIMING_CONDITION4) { - if(gx816->index_bank_crossed == true || !(gx816->regs.p & PF_X))n++; - } - master_cycles += n * MEMSPEED_FAST; } -void snes_timer::add_cpu_cycles(ulong n) { - master_cycles += n; +void snes_timer::reset_clock(void) { + mem_speed_map = sm_slowrom; + +//upon SNES reset, starts at scanline 0 non-interlace + frame_cycles = 262 * 1364; + frame_lines = 262; + line_cycles = 1364; + ppu.interlace = false; + ppu.toggle_interlace = false; + ppu.interlace_frame = 0; + latch_table = latch_table_a; + + vscan_pos = 0; + hscan_pos = 0; + hcycle_pos = 0; + + dram_refresh_pos = 538; + dram_refreshed = false; + + nmi_triggered = false; + + apu_cycles = 0; + bridge.cpu_cycles = 0; + bridge.apu_cycles = 0; + +/* + Initial latch values for $213c/$213d + 0035:0000 (53.0 -> 212) [lda $2137] + 0038:0000 (56.5 -> 226) [nop : lda $2137] +*/ + master_cycles = 188; + prev_master_cycles = 0; + update_timer(); +} + +snes_timer::snes_timer() { + build_speed_map(); + build_dot_map(); +} + +snes_timer::~snes_timer() { + if(mem_speed_map)free(mem_speed_map); + if(latch_table_a)free(latch_table_a); + if(latch_table_b)free(latch_table_b); +} + +/* + 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. +*/ +void snes_timer::inc_vscan_pos(void) { + if(vscan_pos >= frame_lines) { + master_cycles -= frame_cycles; + vscan_pos = 0; + nmi_triggered = false; + + ppu.interlace = ppu.toggle_interlace; + ppu.interlace_frame ^= 1; + if(ppu.interlace == true) { + if(ppu.interlace_frame == 0) { + frame_cycles = 263 * 1364; + frame_lines = 263; + } else { + frame_cycles = 262 * 1364; + frame_lines = 262; + } + latch_table = latch_table_a; + } else { //ppu.interlace == false + if(ppu.interlace_frame == 0) { + frame_cycles = 262 * 1364; + frame_lines = 262; + latch_table = latch_table_a; + } else { + frame_cycles = (262 * 1364) - 4; + frame_lines = 262; + latch_table = latch_table_b; + } + } + vscan_wrapped = true; + } + + if(ppu.interlace == false && ppu.interlace_frame == 1 && vscan_pos == 240) { + line_cycles = 1360; + } else { + line_cycles = 1364; + } + + hscan_wrapped = true; + dram_refreshed = false; +} + +void snes_timer::update_dram_refresh_pos(void) { + if(ppu.interlace == false && ppu.interlace_frame == 1 && vscan_pos == 240) { + //dram refresh position doesn't change + } else { + if(dram_refresh_pos == 534) { + dram_refresh_pos = 538; + } else { + dram_refresh_pos = 534; + } + } +} + +/* + this routine is *not* designed to seek to any scan position passed to it. + it is intended that cycle_pos is no more than 40 master cycles above the + previous cycle_pos given to this routine. the routine has two purposes, + one is to actually update the screen x/y positions and trigger system + events; the other is to allow the 4 master cycle difference between latching + the x/y counters from reading $2137 and writing $4201. + the former passes update_frame_info as true, as the changes should be permanent. + the latter passes update_frame_info as false, as the real cycle counter will + not be incremented at that time (that is handled within the opcodes themselves). + + the cycle_pos passed is divided by 2 because the smallest possible cpu clock + frequency is 2 master cycles, and this allows the latch tables to consume only + half as much memory. +*/ +void snes_timer::set_scan_pos(ulong cycle_pos, bool update_frame_info) { +int y; + y = vscan_pos; + cycle_pos >>= 1; + vscan_pos = latch_table[cycle_pos].y; + hscan_pos = latch_table[cycle_pos].x; + hcycle_pos = latch_table[cycle_pos].cx; + if(update_frame_info == true) { + if(vscan_pos > y) { + inc_vscan_pos(); + } + } else { + if(vscan_pos >= frame_lines) { + vscan_pos -= frame_lines; + } + } + + if(dram_refreshed == false && hcycle_pos >= dram_refresh_pos) { + if(update_frame_info == true) { + add_cpu_cycles(1, 40); + dram_refreshed = true; + update_dram_refresh_pos(); + } + hcycle_pos += 40; + hscan_pos += 10; + } } void snes_timer::update_timer(void) { - vscan_pos = (master_cycles / CYCLES_PER_SCANLINE) % 262; - hscan_pos = (master_cycles % CYCLES_PER_SCANLINE) / 4; + set_scan_pos(master_cycles, true); } -snes_timer *snes_time; +void snes_timer::update_timer_events(void) { + if(gx816->cpu_state == CPUSTATE_STP)return; + + if(snes_time->vscan_pos == (ppu.visible_scanlines + 1) && snes_time->hcycle_pos >= 12 && nmi_triggered == false) { + nmi_triggered = true; + gx816->nmi_pin = 0; + if(gx816->nmi_enabled == true) { + gx816->InvokeIRQ(0xffea); + } + } +} diff --git a/bsnes/timing/timing.h b/bsnes/timing/timing.h index b3dfb6d7..37a7c9e5 100644 --- a/bsnes/timing/timing.h +++ b/bsnes/timing/timing.h @@ -1,23 +1,43 @@ -#define CYCLES_PER_SCANLINE 1360 -#define WRAM_REFRESH_DOT_POS 132 - +//mask table (powers of 2) #define TIMING_NONE 0x00 -#define TIMING_BANKCROSS 0x01 -#define TIMING_REGD 0x02 -#define TIMING_CONDITION2 0x02 -#define TIMING_CONDITION4 0x04 +#define TIMING_CONDITION2 0x01 //DL != 0 +#define TIMING_CONDITION4 0x02 //crossed page boundary or p.x = 0 + +typedef struct { + word cx, x, y; +}latch_pos; class snes_timer { public: -ulong master_cycles; -word vscan_pos, hscan_pos; +ulong apu_cycles; +ulong master_cycles, prev_master_cycles; +struct { + ulong cpu_cycles, apu_cycles; +}bridge; +word hcycle_pos, vscan_pos, hscan_pos; +bool vscan_wrapped, hscan_wrapped; +bool dram_refreshed, nmi_triggered; +byte *mem_speed_map, *sm_slowrom, *sm_fastrom; +ulong frame_cycles, frame_lines, line_cycles; +word dram_refresh_pos; +latch_pos *latch_table_a, *latch_table_b, *latch_table; + + void add_cpu_cycles (byte count, byte speed); + void add_cpu_pcycles(byte count); + void add_cpu_mcycles(byte count, ulong addr); + void add_cpu_scycles(byte count); + void add_cpu_icycles(byte count); + ulong get_master_cycle_count(ulong offset); - void add_cpu_pcycles(ulong n); - void add_cpu_scycles(ulong n); - void add_cpu_mcycles(ulong n, ulong addr); - void add_cpu_icycles(ulong n); - void add_cpu_icycles(ulong n, ulong flags); - void add_cpu_cycles(ulong n); + void build_speed_map(void); + void build_dot_map(void); + void reset_clock(void); + void inc_vscan_pos(void); + void set_scan_pos(ulong cycle_pos, bool update_frame_info); + void set_speed_map(byte speed); + void update_dram_refresh_pos(void); void update_timer(void); + void update_timer_events(void); snes_timer(); + ~snes_timer(); }; diff --git a/bsnes/win/gui.cpp b/bsnes/win/gui.cpp index 7d0f8f7e..cabc86a8 100644 --- a/bsnes/win/gui.cpp +++ b/bsnes/win/gui.cpp @@ -2,19 +2,22 @@ #include "../timing/timing.h" extern snes_timer *snes_time; #include "../cpu/g65816.h" -extern g65816 *gx816; -extern emustate emu_state; -extern debugstate debugger; -extern videostate render; -extern ppustate ppu; +#include "../apu/spc700.h" +extern g65816 *gx816; +extern sony_spc700 *spc700; +extern emustate emu_state; +extern debugstate debugger; +extern videostate render; +extern ppustate ppu; #include -#define BSNES_TITLE "bsnes v0.0.002 ir9" +#define BSNES_TITLE "bsnes v0.0.005a" enum { MENU_FILE_LOAD = 100, MENU_FILE_RESET, MENU_FILE_EXIT, + MENU_SETTINGS_VIDEOMODE_256x224w, MENU_SETTINGS_VIDEOMODE_512x448w, MENU_SETTINGS_VIDEOMODE_640x480f, MENU_SETTINGS_FRAMESKIP_OFF, @@ -54,9 +57,9 @@ extern joypad_state joypad1; void UpdateJoypad(void) { joypad1.up = KeyState(KEY_UP ); - joypad1.down = KeyState(KEY_DOWN ); + joypad1.down = (joypad1.up)?0:KeyState(KEY_DOWN); joypad1.left = KeyState(KEY_LEFT ); - joypad1.right = KeyState(KEY_RIGHT); + joypad1.right = (joypad1.left)?0:KeyState(KEY_RIGHT); joypad1.select = KeyState(KEY_SHIFT); joypad1.start = KeyState(KEY_ENTER); joypad1.y = KeyState(KEY_A ); @@ -65,6 +68,20 @@ void UpdateJoypad(void) { joypad1.a = KeyState(KEY_X ); joypad1.l = KeyState(KEY_D ); joypad1.r = KeyState(KEY_C ); + + if(debugger_enabled() == false)return; + if(debugger.lock_up == true)joypad1.up = 1; + if(debugger.lock_down == true)joypad1.down = 1; + if(debugger.lock_left == true)joypad1.left = 1; + if(debugger.lock_right == true)joypad1.right = 1; + if(debugger.lock_a == true)joypad1.a = 1; + if(debugger.lock_b == true)joypad1.b = 1; + if(debugger.lock_x == true)joypad1.x = 1; + if(debugger.lock_y == true)joypad1.y = 1; + if(debugger.lock_l == true)joypad1.l = 1; + if(debugger.lock_r == true)joypad1.r = 1; + if(debugger.lock_select == true)joypad1.select = 1; + if(debugger.lock_start == true)joypad1.start = 1; } void alert(char *s, ...) { @@ -126,6 +143,7 @@ HMENU hsubmenu, hbranchmenu; hsubmenu = CreatePopupMenu(); hbranchmenu = CreatePopupMenu(); + AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_256x224w, "256x224 Windowed"); AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_512x448w, "512x448 Windowed"); AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_640x480f, "640x480 Fullscreen"); AppendMenu(hsubmenu, MF_STRING | MF_POPUP, (unsigned int)hbranchmenu, "&Video Mode"); @@ -179,7 +197,7 @@ void SetMainWindowPos(bool update_style) { SetWindowLong(hwndMain, GWL_STYLE, WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX); SetWindowLong(hwndMain, GWL_EXSTYLE, 0); } - FixWindowSize(hwndMain, render.width, render.height); + FixWindowSize(hwndMain, render.display_width, render.display_height); } } @@ -253,7 +271,7 @@ bool result; PostQuitMessage(0); break; case WM_PAINT: - UpdateDisplay_NoRender(); + DrawScene(); break; case WM_KEYDOWN: switch(wparam) { @@ -273,30 +291,40 @@ bool result; strcpy(fn, ""); result = GUIOpenFile(fn); if(result == true) { + emu_state.rom_loaded = true; strcpy(emu_state.rom_name, fn); fn[strlen(fn) - 4] = 0; strcat(fn, ".srm"); strcpy(emu_state.sram_name, fn); gx816->PowerOn(0); gx816->LoadROM(); - if(debug_get_state() == DEBUGMODE_NOROM) { - debug_set_state(DEBUGMODE_DISABLED); + ResetSNES(); + if(debugger_enabled() == true) { + debug_set_state(DEBUGMODE_WAIT); } } break; case MENU_FILE_RESET: - gx816->Reset(); + ResetSNES(); break; case MENU_FILE_EXIT: PostQuitMessage(0); break; + case MENU_SETTINGS_VIDEOMODE_256x224w: + video_setmode(false, 256, 224); + CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_256x224w, MF_CHECKED); + CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_512x448w, MF_UNCHECKED); + CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_640x480f, MF_UNCHECKED); + break; case MENU_SETTINGS_VIDEOMODE_512x448w: video_setmode(false, 512, 448); + CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_256x224w, MF_UNCHECKED); CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_512x448w, MF_CHECKED); CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_640x480f, MF_UNCHECKED); break; case MENU_SETTINGS_VIDEOMODE_640x480f: video_setmode(true, 512, 448); + CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_256x224w, MF_UNCHECKED); CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_512x448w, MF_UNCHECKED); CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_640x480f, MF_CHECKED); break; @@ -316,9 +344,7 @@ bool result; CheckMenuItem(hmenuMain, MENU_SETTINGS_FRAMESKIP_OFF + render.frame_skip, MF_CHECKED); break; case MENU_SETTINGS_DEBUGGER: - if(debug_get_state() == DEBUGMODE_NOROM)break; - - if(debug_get_state() == DEBUGMODE_DISABLED) { + if(debugger_enabled() == false) { CheckMenuItem(hmenuMain, MENU_SETTINGS_DEBUGGER, MF_CHECKED); EnableDebugger(0); } else { @@ -358,23 +384,23 @@ long height; void EnableDebugger(byte first_time) { debug_set_state(DEBUGMODE_WAIT); - hwndDCPU = NewWindow(wndprocDCPU, "bsnes_cpu", "g65816 cpu debugger", null, DCPU_WIDTH, DCPU_HEIGHT); + hwndDCPU = NewWindow(wndprocDCPU, "bsnes_cpu", "console", null, DCPU_WIDTH, DCPU_HEIGHT); CreateDCPU(); - FixWindowSize(hwndDCPU, DCPU_WIDTH, DCPU_HEIGHT, 0, 1024 - 320); + FixWindowSize(hwndDCPU, DCPU_WIDTH, DCPU_HEIGHT, 0, 1024 - 410); - hwndDMEM = NewWindow(wndprocDMEM, "bsnes_mem", "g65816 memory editor -- snes memory mode", null, 495, 238); + hwndDMEM = NewWindow(wndprocDMEM, "bsnes_mem", "memory editor", null, DMEM_WIDTH, DMEM_HEIGHT); CreateDMEM(); - FixWindowSize(hwndDMEM, 495, 238, 316, 441); + FixWindowSize(hwndDMEM, DMEM_WIDTH, DMEM_HEIGHT, 386, 321); - hwndDBP = NewWindow(wndprocDBP, "bsnes_bp", "g65816 breakpoint editor", null, 310, 238); + hwndDBP = NewWindow(wndprocDBP, "bsnes_bp", "breakpoint editor", null, DBP_WIDTH, DBP_HEIGHT); CreateDBP(); - FixWindowSize(hwndDBP, 310, 238, 0, 441); + FixWindowSize(hwndDBP, DBP_WIDTH, DBP_HEIGHT, 0, 346); hwndDBGToggle = NewWindow(wndprocDBGToggle, "bsnes_bgtoggle", "ppu bg toggle", null, 275, 90); CreateDBGToggle(); - FixWindowSize(hwndDBGToggle, 275, 90, 0, 326); + FixWindowSize(hwndDBGToggle, 275, 90, 0, 231); - FixWindowSize(hwndMain, 256, 224, 681, 1024 - 320); + FixWindowSize(hwndMain, 256, 223, 871, 1024 - 410); ShowWindow(hwndDCPU, SW_NORMAL); ShowWindow(hwndDMEM, SW_NORMAL); @@ -385,7 +411,7 @@ void EnableDebugger(byte first_time) { if(first_time == 0) { debug_refresh_mem(); debug_refresh_bp(); - debug_update_cycles(); + debug_update_status(); dprintf("* Debugger Enabled"); UpdateDisplay(); } @@ -411,11 +437,10 @@ MSG msg; if(debug_get_state() == DEBUGMODE_WAIT) { EnableDebugger(1); } - video_setmode(render.fullscreen, render.width, render.height); + video_setmode(render.fullscreen, render.display_width, render.display_height); InitDisplay(); CreateColorTable(); - SelectRenderer(); InitSNES(); diff --git a/bsnes/win/gui_bp.cpp b/bsnes/win/gui_bp.cpp index d488ea9c..c0ca3624 100644 --- a/bsnes/win/gui_bp.cpp +++ b/bsnes/win/gui_bp.cpp @@ -1,3 +1,6 @@ +#define DBP_WIDTH 380 +#define DBP_HEIGHT 243 + #define DBP_LIST 100 #define DBP_ADDBP 101 #define DBP_REMBP 102 @@ -10,34 +13,51 @@ #define DBP_BPX 109 #define DBP_BPV 110 #define DBP_BPVAL 111 +#define DBP_STATIC2 112 +#define DBP_SRCMEM 113 +#define DBP_SRCVRAM 114 +#define DBP_SRCCGRAM 115 +#define DBP_SRCOAM 116 +#define DBP_SRCSPCRAM 117 +#define DBP_SRCMODE 118 HWND hwndDBP; +byte debug_bp_src; void debug_refresh_bp(void) { -char str[64*16], t[64]; - if(debug_get_state() == DEBUGMODE_DISABLED)return; +char str[128*16], t[128]; + if(debugger_enabled() == false)return; strcpy(str, ""); for(int i=0;i<16;i++) { sprintf(t, "%0.2d: ", i); strcat(str, t); - if(gx816->bp_list[i].flags == BP_OFF) { - strcat(str, "------ ---- -- (Disabled)"); + if(debugger.bp_list[i].flags == BP_OFF) { + strcat(str, "------ ---- -- ------ (Disabled)"); } else { - sprintf(t, "%0.6x %c%c%c%c ", gx816->bp_list[i].offset, - (gx816->bp_list[i].flags & BP_READ )?'R':'r', - (gx816->bp_list[i].flags & BP_WRITE)?'W':'w', - (gx816->bp_list[i].flags & BP_EXEC )?'X':'x', - (gx816->bp_list[i].flags & BP_VAL )?'V':'v'); + sprintf(t, "%0.6x %c%c%c%c ", debugger.bp_list[i].offset, + (debugger.bp_list[i].flags & BP_READ )?'R':'r', + (debugger.bp_list[i].flags & BP_WRITE)?'W':'w', + (debugger.bp_list[i].flags & BP_EXEC )?'X':'x', + (debugger.bp_list[i].flags & BP_VAL )?'V':'v'); strcat(str, t); - if(gx816->bp_list[i].flags & BP_VAL) { - sprintf(t, "%0.2x ", gx816->bp_list[i].value); + if(debugger.bp_list[i].flags & BP_VAL) { + sprintf(t, "%0.2x ", debugger.bp_list[i].value); strcat(str, t); } else strcat(str, "-- "); - sprintf(t, "%10d", gx816->bp_list[i].hit_count); + + switch(debugger.bp_list[i].source) { + case BPSRC_MEM: strcat(str, "DRAM ");break; + case BPSRC_VRAM: strcat(str, "VRAM ");break; + case BPSRC_CGRAM: strcat(str, "CGRAM ");break; + case BPSRC_OAM: strcat(str, "OAM ");break; + case BPSRC_SPCRAM:strcat(str, "SPCRAM ");break; + } + + sprintf(t, "%10d", debugger.bp_list[i].hit_count); strcat(str, t); } - if(i != 15)strcat(str, "\n"); + if(i != 15)strcat(str, "\r\n"); } SetDlgItemText(hwndDBP, DBP_LIST, str); @@ -46,56 +66,91 @@ char str[64*16], t[64]; long __stdcall wndprocDBP(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { char str[256]; ulong num, offset, val, flags; -int i; +int i, pos; if(msg == WM_DESTROY || msg == WM_CLOSE)return 0; //don't allow debugger to be closed (yet) if(msg == WM_COMMAND) { switch(LOWORD(wparam)) { + case DBP_BPNUM: + if(HIWORD(wparam) == CBN_SELCHANGE) { + num = SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_GETCURSEL, 0, 0); + sprintf(str, "%0.6x", debugger.bp_list[num].offset); + SetDlgItemText(hwndDBP, DBP_BPOFFSET, str); + sprintf(str, "%0.2x", debugger.bp_list[num].value); + SetDlgItemText(hwndDBP, DBP_BPVAL, str); + switch(debugger.bp_list[num].source) { + case BPSRC_MEM: pos = 0; break; + case BPSRC_VRAM: pos = 1; break; + case BPSRC_CGRAM: pos = 2; break; + case BPSRC_OAM: pos = 3; break; + case BPSRC_SPCRAM: pos = 4; break; + } + SendDlgItemMessage(hwndDBP, DBP_SRCMODE, CB_SETCURSEL, (WPARAM)pos, 0); + SendDlgItemMessage(hwndDBP, DBP_BPR, BM_SETCHECK, (debugger.bp_list[num].flags & BP_READ )?1:0, 0); + SendDlgItemMessage(hwndDBP, DBP_BPW, BM_SETCHECK, (debugger.bp_list[num].flags & BP_WRITE)?1:0, 0); + SendDlgItemMessage(hwndDBP, DBP_BPX, BM_SETCHECK, (debugger.bp_list[num].flags & BP_EXEC )?1:0, 0); + SendDlgItemMessage(hwndDBP, DBP_BPV, BM_SETCHECK, (debugger.bp_list[num].flags & BP_VAL )?1:0, 0); + } + break; case DBP_ADDBP: - GetDlgItemText(hwndDBP, DBP_BPNUM, str, 255); - num = strdec(str); + num = SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_GETCURSEL, 0, 0); GetDlgItemText(hwndDBP, DBP_BPOFFSET, str, 255); offset = strhex(str) & 0xffffff; GetDlgItemText(hwndDBP, DBP_BPVAL, str, 255); val = strhex(str); flags = 0; - if(SendMessage(GetDlgItem(hwndDBP, DBP_BPR), BM_GETCHECK, 0, 0))flags |= BP_READ; - if(SendMessage(GetDlgItem(hwndDBP, DBP_BPW), BM_GETCHECK, 0, 0))flags |= BP_WRITE; - if(SendMessage(GetDlgItem(hwndDBP, DBP_BPX), BM_GETCHECK, 0, 0))flags |= BP_EXEC; - if(SendMessage(GetDlgItem(hwndDBP, DBP_BPV), BM_GETCHECK, 0, 0))flags |= BP_VAL; + if(SendDlgItemMessage(hwndDBP, DBP_BPR, BM_GETCHECK, 0, 0))flags |= BP_READ; + if(SendDlgItemMessage(hwndDBP, DBP_BPW, BM_GETCHECK, 0, 0))flags |= BP_WRITE; + if(SendDlgItemMessage(hwndDBP, DBP_BPX, BM_GETCHECK, 0, 0))flags |= BP_EXEC; + if(SendDlgItemMessage(hwndDBP, DBP_BPV, BM_GETCHECK, 0, 0))flags |= BP_VAL; - if(num > 15)dprintf("Invalid breakpoint #: %d -- 0-15 valid", num); - else { - gx816->bp_list[num].offset = offset; - gx816->bp_list[num].flags = flags; - if(gx816->bp_list[num].flags & BP_VAL)gx816->bp_list[num].value = val; - else gx816->bp_list[num].value = 0; - gx816->bp_list[num].hit_count = 0; + debugger.bp_list[num].offset = offset; + debugger.bp_list[num].flags = flags; + debugger.bp_list[num].source = debug_bp_src; + if(debugger.bp_list[num].flags & BP_VAL) { + debugger.bp_list[num].value = val; + } else { + debugger.bp_list[num].value = 0; } + debugger.bp_list[num].hit_count = 0; debugger.refresh_bp = true; break; case DBP_REMBP: - GetDlgItemText(hwndDBP, DBP_BPNUM, str, 255); - num = strdec(str); - if(num > 15)dprintf("Invalid breakpoint #: %d -- 0-15 valid", num); - else { - gx816->bp_list[num].offset = 0; - gx816->bp_list[num].flags = BP_OFF; - gx816->bp_list[num].value = 0; - gx816->bp_list[num].hit_count = 0; - } + num = SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_GETCURSEL, 0, 0); + debugger.bp_list[num].offset = 0; + debugger.bp_list[num].flags = BP_OFF; + debugger.bp_list[num].source = BPSRC_MEM; + debugger.bp_list[num].value = 0; + debugger.bp_list[num].hit_count = 0; debugger.refresh_bp = true; break; case DBP_CLRBP: for(i=0;i<16;i++) { - gx816->bp_list[i].offset = 0; - gx816->bp_list[i].flags = BP_OFF; - gx816->bp_list[i].value = 0; - gx816->bp_list[i].hit_count = 0; + debugger.bp_list[i].offset = 0; + debugger.bp_list[i].flags = BP_OFF; + debugger.bp_list[i].source = BPSRC_MEM; + debugger.bp_list[i].value = 0; + debugger.bp_list[i].hit_count = 0; } debugger.refresh_bp = true; break; + case DBP_SRCMODE: + if(HIWORD(wparam) == CBN_SELCHANGE) { + pos = SendDlgItemMessage(hwndDBP, DBP_SRCMODE, CB_GETCURSEL, 0, 0); + if(pos == 0) { + debug_bp_src = BPSRC_MEM; + } else if(pos == 1) { + debug_bp_src = BPSRC_VRAM; + } else if(pos == 2) { + debug_bp_src = BPSRC_CGRAM; + } else if(pos == 3) { + debug_bp_src = BPSRC_OAM; + } else if(pos == 4) { + debug_bp_src = BPSRC_SPCRAM; + } + } + break; } } @@ -103,29 +158,70 @@ int i; } void CreateDBP(void) { - CreateWindowEx(WS_EX_STATICEDGE, "STATIC", "", WS_CHILD|WS_VISIBLE, 5, 5, 205, 228, hwndDBP, (HMENU)DBP_LIST, GetModuleHandle(0), 0); - CreateWindow("STATIC", "BP #: Offset:", WS_CHILD|WS_VISIBLE, 215, 5, 90, 15, hwndDBP, (HMENU)DBP_STATIC1, GetModuleHandle(0), 0); - CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "00", WS_CHILD|WS_VISIBLE, 215, 20, 30, 23, hwndDBP, (HMENU)DBP_BPNUM, GetModuleHandle(0), 0); - CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "000000", WS_CHILD|WS_VISIBLE, 245, 20, 60, 23, hwndDBP, (HMENU)DBP_BPOFFSET, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "R", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 215, 44, 30, 18, hwndDBP, (HMENU)DBP_BPR, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "W", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 245, 44, 30, 18, hwndDBP, (HMENU)DBP_BPW, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "X", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 275, 44, 30, 18, hwndDBP, (HMENU)DBP_BPX, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "V", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 215, 65, 30, 18, hwndDBP, (HMENU)DBP_BPV, GetModuleHandle(0), 0); - CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "00", WS_CHILD|WS_VISIBLE, 245, 62, 60, 23, hwndDBP, (HMENU)DBP_BPVAL, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Set BP", WS_CHILD|WS_VISIBLE, 215, 88, 90, 20, hwndDBP, (HMENU)DBP_ADDBP, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Clear BP", WS_CHILD|WS_VISIBLE, 215, 108, 90, 20, hwndDBP, (HMENU)DBP_REMBP, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Clear All BPs", WS_CHILD|WS_VISIBLE, 215, 128, 90, 20, hwndDBP, (HMENU)DBP_CLRBP, GetModuleHandle(0), 0); + CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", + WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_READONLY, + 5, 5, 260, 233, hwndDBP, (HMENU)DBP_LIST, GetModuleHandle(0), 0); - SendDlgItemMessage(hwndDBP, DBP_LIST, WM_SETFONT, (WPARAM)hFontFixed, TRUE); - SendDlgItemMessage(hwndDBP, DBP_STATIC1, WM_SETFONT, (WPARAM)hFont, TRUE); - SendDlgItemMessage(hwndDBP, DBP_BPNUM, WM_SETFONT, (WPARAM)hFontFixed, TRUE); - SendDlgItemMessage(hwndDBP, DBP_BPOFFSET, WM_SETFONT, (WPARAM)hFontFixed, TRUE); - SendDlgItemMessage(hwndDBP, DBP_BPR, WM_SETFONT, (WPARAM)hFontFixed, TRUE); - SendDlgItemMessage(hwndDBP, DBP_BPW, WM_SETFONT, (WPARAM)hFontFixed, TRUE); - SendDlgItemMessage(hwndDBP, DBP_BPX, WM_SETFONT, (WPARAM)hFontFixed, TRUE); - SendDlgItemMessage(hwndDBP, DBP_BPV, WM_SETFONT, (WPARAM)hFontFixed, TRUE); - SendDlgItemMessage(hwndDBP, DBP_BPVAL, WM_SETFONT, (WPARAM)hFontFixed, TRUE); - SendDlgItemMessage(hwndDBP, DBP_ADDBP, WM_SETFONT, (WPARAM)hFont, TRUE); - SendDlgItemMessage(hwndDBP, DBP_REMBP, WM_SETFONT, (WPARAM)hFont, TRUE); - SendDlgItemMessage(hwndDBP, DBP_CLRBP, WM_SETFONT, (WPARAM)hFont, TRUE); + CreateWindow("STATIC", "BP #: Offset:", WS_CHILD|WS_VISIBLE, 270, 5, 90, 15, hwndDBP, (HMENU)DBP_STATIC1, GetModuleHandle(0), 0); + + CreateWindow("COMBOBOX", "", + WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST|CBS_HASSTRINGS, + 270, 20, 45, 300, hwndDBP, (HMENU)DBP_BPNUM, GetModuleHandle(0), 0); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"00"); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"01"); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"02"); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"03"); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"04"); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"05"); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"06"); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"07"); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"08"); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"09"); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"10"); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"11"); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"12"); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"13"); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"14"); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"15"); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_SETCURSEL, 0, 0); + + CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "000000", WS_CHILD|WS_VISIBLE, 315, 20, 60, 23, hwndDBP, (HMENU)DBP_BPOFFSET, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "R", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 270, 44, 30, 18, hwndDBP, (HMENU)DBP_BPR, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "W", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 300, 44, 30, 18, hwndDBP, (HMENU)DBP_BPW, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "X", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 330, 44, 30, 18, hwndDBP, (HMENU)DBP_BPX, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "V", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 270, 65, 30, 18, hwndDBP, (HMENU)DBP_BPV, GetModuleHandle(0), 0); + CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "00", WS_CHILD|WS_VISIBLE, 300, 62, 30, 23, hwndDBP, (HMENU)DBP_BPVAL, GetModuleHandle(0), 0); + + CreateWindow("STATIC", "Source:", WS_CHILD|WS_VISIBLE, 270, 85, 90, 15, hwndDBP, (HMENU)DBP_STATIC2, GetModuleHandle(0), 0); + CreateWindow("COMBOBOX", "", + WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST|CBS_HASSTRINGS, + 270, 100, 105, 200, hwndDBP, (HMENU)DBP_SRCMODE, GetModuleHandle(0), 0); + SendDlgItemMessage(hwndDBP, DBP_SRCMODE, CB_ADDSTRING, 0, (LPARAM)"DRAM"); + SendDlgItemMessage(hwndDBP, DBP_SRCMODE, CB_ADDSTRING, 0, (LPARAM)"VRAM"); + SendDlgItemMessage(hwndDBP, DBP_SRCMODE, CB_ADDSTRING, 0, (LPARAM)"CGRAM"); + SendDlgItemMessage(hwndDBP, DBP_SRCMODE, CB_ADDSTRING, 0, (LPARAM)"OAM"); + SendDlgItemMessage(hwndDBP, DBP_SRCMODE, CB_ADDSTRING, 0, (LPARAM)"SPCRAM"); + SendDlgItemMessage(hwndDBP, DBP_SRCMODE, CB_SETCURSEL, 0, 0); + + CreateWindow("BUTTON", "Set BP", WS_CHILD|WS_VISIBLE, 270, 125, 105, 20, hwndDBP, (HMENU)DBP_ADDBP, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Clear BP", WS_CHILD|WS_VISIBLE, 270, 145, 105, 20, hwndDBP, (HMENU)DBP_REMBP, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Clear All BPs", WS_CHILD|WS_VISIBLE, 270, 165, 105, 20, hwndDBP, (HMENU)DBP_CLRBP, GetModuleHandle(0), 0); + + SendDlgItemMessage(hwndDBP, DBP_LIST, WM_SETFONT, (WPARAM)hFontFixed, TRUE); + SendDlgItemMessage(hwndDBP, DBP_STATIC1, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDBP, DBP_BPNUM, WM_SETFONT, (WPARAM)hFontFixed, TRUE); + SendDlgItemMessage(hwndDBP, DBP_BPOFFSET, WM_SETFONT, (WPARAM)hFontFixed, TRUE); + SendDlgItemMessage(hwndDBP, DBP_BPR, WM_SETFONT, (WPARAM)hFontFixed, TRUE); + SendDlgItemMessage(hwndDBP, DBP_BPW, WM_SETFONT, (WPARAM)hFontFixed, TRUE); + SendDlgItemMessage(hwndDBP, DBP_BPX, WM_SETFONT, (WPARAM)hFontFixed, TRUE); + SendDlgItemMessage(hwndDBP, DBP_BPV, WM_SETFONT, (WPARAM)hFontFixed, TRUE); + SendDlgItemMessage(hwndDBP, DBP_BPVAL, WM_SETFONT, (WPARAM)hFontFixed, TRUE); + SendDlgItemMessage(hwndDBP, DBP_SRCMODE, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDBP, DBP_STATIC2, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDBP, DBP_ADDBP, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDBP, DBP_REMBP, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDBP, DBP_CLRBP, WM_SETFONT, (WPARAM)hFont, TRUE); + + SendDlgItemMessage(hwndDBP, DBP_SRCMEM, BM_SETCHECK, 1, 0); + debug_bp_src = BPSRC_MEM; } diff --git a/bsnes/win/gui_cpu.cpp b/bsnes/win/gui_cpu.cpp index d1d30917..f03879c1 100644 --- a/bsnes/win/gui_cpu.cpp +++ b/bsnes/win/gui_cpu.cpp @@ -1,176 +1,203 @@ -#define DCPU_WIDTH 675 -#define DCPU_HEIGHT 295 +#define DCPU_WIDTH 865 +#define DCPU_HEIGHT 385 -#define DCPU_DISAS 100 -#define DCPU_RUN 101 -#define DCPU_STEP 102 -#define DCPU_PROCEED 103 -#define DCPU_INFO 104 -#define DCPU_TRACE 105 -#define DCPU_CYCLES 106 +enum { + DCPU_DISAS = 100, + DCPU_CPUGROUP, + DCPU_CPUSTEP, + DCPU_CPUPROCEED, + DCPU_CPUSKIP, + DCPU_CPUTRACENUM, + DCPU_CPUTRACE, + DCPU_CPUDISABLE, + DCPU_APUGROUP, + DCPU_APUSTEP, + DCPU_APUPROCEED, + DCPU_APUSKIP, + DCPU_APUTRACENUM, + DCPU_APUTRACE, + DCPU_APUDISABLE, + DCPU_SYSGROUP, + DCPU_SYSRUN, + DCPU_SYSRUNTOFRAME, + DCPU_SYSRUNTOVBLANK, + DCPU_SYSRUNTONMI, + DCPU_SYSRUNTOIRQ, + DCPU_SYSRUNTOINT, + DCPU_CFGGROUP, + DCPU_CFGCPUOUT, + DCPU_CFGAPUOUT, + DCPU_CFGDBGOUT, + DCPU_CFGTRACE, + DCPU_CFGTRACEPRINT, + DCPU_CFGREGTYPE, + DCPU_CFGREGNUM, + DCPU_CFGREGVAL, + DCPU_CFGREGSET, + DCPU_CFGLOCK, + DCPU_CFGLOCKUP, + DCPU_CFGLOCKDOWN, + DCPU_CFGLOCKLEFT, + DCPU_CFGLOCKRIGHT, + DCPU_CFGLOCKA, + DCPU_CFGLOCKB, + DCPU_CFGLOCKX, + DCPU_CFGLOCKY, + DCPU_CFGLOCKL, + DCPU_CFGLOCKR, + DCPU_CFGLOCKSELECT, + DCPU_CFGLOCKSTART, + DCPU_STATUS +}; HWND hwndDCPU; +#define DEBUG_CONSOLE_LINES 250 +char dcpu_disas_mem[DEBUG_CONSOLE_LINES][256]; -char dcpu_disas_mem[20][256]; +void debug_update_console(void) { +int i; +char str[256 * DEBUG_CONSOLE_LINES]; + if(debug_write_status() == DEBUGWRITE_NONE)return; + + strcpy(str, ""); + for(i=0;ivscan_pos, snes_time->hcycle_pos, snes_time->hscan_pos, snes_time->master_cycles, + (gx816->nmi_enabled == true)?" Enabled":"Disabled", + (ppu.vcounter_enabled == true)?" Enabled":"Disabled", + (ppu.hcounter_enabled == true)?" Enabled":"Disabled", + ppu.virq_pos, ppu.hirq_pos, + gx816->regs.pc, gx816->regs.a.w, gx816->regs.x, gx816->regs.y, + gx816->regs.s, gx816->regs.d, gx816->regs.db, + spc700->regs.pc, spc700->regs.a, spc700->regs.x, spc700->regs.y, + spc700->regs.sp, (spc700->regs.y << 8) | spc700->regs.a); + SetDlgItemText(hwndDCPU, DCPU_STATUS, str); +} + +void debug_write(ulong msg_type, char *s) { +int i; + if(debugger_enabled() == false)return; + + switch(msg_type) { + case DEBUGMSG_INFO: + if(debugger.output_debug_info == false)return; + break; + case DEBUGMSG_CPU: + if(debugger.output_cpu_instrs == false)return; + break; + case DEBUGMSG_APU: + if(debugger.output_apu_instrs == false)return; + break; + } + + if(debugger.trace_enabled == true) { + fprintf(debugger.trace_fp, "%s\r\n", s); + } + + if(debug_write_status() & DEBUGWRITE_CONSOLE) { + for(i=0;imaster_cycles); - SetDlgItemText(hwndDCPU, DCPU_CYCLES, str); + va_start(args, s); + vsprintf(str, s, args); + va_end(args); + + debug_write(msg_type, str); } void debug_set_state(byte state) { debugger.mode = state; if(hwndDCPU && state != DEBUGMODE_DISABLED) { - if(state == DEBUGMODE_WAIT || state == DEBUGMODE_STEP) { - SetDlgItemText(hwndDCPU, DCPU_RUN, "Run"); - } else { - SetDlgItemText(hwndDCPU, DCPU_RUN, "Stop"); + if(state == DEBUGMODE_WAIT) { + SetDlgItemText(hwndDCPU, DCPU_SYSRUN, "Run"); + } else if(state == DEBUGMODE_RUN) { + SetDlgItemText(hwndDCPU, DCPU_SYSRUN, "Stop"); } } - - if(state == DEBUGMODE_DISABLED) { - RunSNES = RunSNES_NoDebug; - } else { - RunSNES = RunSNES_Debug; - } } long __stdcall wndprocDCPU(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { FILE *fp; +int state; if(msg == WM_DESTROY || msg == WM_CLOSE)return 0; //don't allow debugger to be closed (yet) if(msg == WM_COMMAND) { switch(LOWORD(wparam)) { - case DCPU_RUN: - if(debug_get_state() != DEBUGMODE_RUN) { - debug_set_state(DEBUGMODE_RUN); - SetDlgItemText(hwndDCPU, DCPU_RUN, "Stop"); - } else { - debug_set_state(DEBUGMODE_WAIT); - disas_g65816_op(); - SetDlgItemText(hwndDCPU, DCPU_RUN, "Run"); - } - break; - case DCPU_STEP: + case DCPU_SYSRUN: if(debug_get_state() == DEBUGMODE_WAIT) { - debug_set_state(DEBUGMODE_STEP); + debug_set_state(DEBUGMODE_RUN); + } else if(debug_get_state() == DEBUGMODE_RUN) { + debug_set_state(DEBUGMODE_WAIT); + debug_update_console(); + debug_update_status(); } break; - case DCPU_PROCEED: - fp = fopen("data.bin", "wb"); - fwrite(ppu.vram, 0x10000, 1, fp); - fwrite(gx816->wram, 0x20000, 1, fp); - fwrite(ppu.cgram, 512, 1, fp); - fwrite(ppu.oam, 544, 1, fp); - fclose(fp); + case DCPU_CPUSTEP: + if(debug_get_state() == DEBUGMODE_WAIT) { + debug_set_state(DEBUGMODE_CPUSTEP); + } + debugger.cpu_op_executed = false; break; - case DCPU_INFO: - fp = fopen("data.txt", "w"); - fprintf(fp, - "Memory speed: %s\n" - "Mode: %d\n" - "BGs On: %d%d%d%d%d\n" - "Sub BGs On: %d%d%d%d%d\n" - "Tilemap Loc: %0.4x,%0.4x,%0.4x,%0.4x\n" - "Tiledata Loc: %0.4x,%0.4x,%0.4x,%0.4x,%0.4x\n" - "Tilemap Size: %d,%d,%d,%d\n" - "Tile Size: %d,%d,%d,%d\n" - "BG Priority Mode: %d\n" - "OAM Base Size: %d\nOAM Name Sel: %d\nBG Enabled: %d\nBG Brightness: %d\n" - "Window 1 Left: %d\nWindow 1 Right: %d\nWindow 2 Left: %d\nWindow 2 Right: %d\n" - "Window 1 Enabled: %d%d%d%d%d\nWindow 2 Enabled: %d%d%d%d%d\n" - "Window 1 Clipmode: %s,%s,%s,%s,%s\nWindow 2 Clipmode: %s,%s,%s,%s,%s\n" - "BG Windowing Enabled: %d%d%d%d%d\nSub BG Windowing Enabled: %d%d%d%d%d\n" - "BG Window Mask: %d,%d,%d,%d,%d\n" - "Color Windows Enabled: %d%d\nColor Window Clipmodes: %d,%d\n" - "Color Window Mask: %d\nColor Mask: %d\nSub Color Mask: %d\nAddsub Mode: %d\nColor Mode: %d\nColor Halve: %d\n" - "BG Color Enabled: %d%d%d%d%d%d\n" - "RGB Color Settings: %d,%d,%d\nVIRQ Counter Enabled: %s\nHIRQ Counter Enabled: %s\n" - "VIRQ Pos: %d\nHIRQ Pos: %d\n" - "Mode 7 Screen Flip: x: %s, y: %s\n" - "m7a: %0.4x (%f) m7b: %0.4x (%f) m7c: %0.4x (%f) m7d: %0.4x (%f)\n" - "m7x: %0.4x m7y: %0.4x\n", - (gx816->memory_speed == 1)?"FastROM":"SlowROM", ppu.bg_mode, - (ppu.bg_enabled[0] == true)?1:0, (ppu.bg_enabled[1] == true)?1:0, - (ppu.bg_enabled[2] == true)?1:0, (ppu.bg_enabled[3] == true)?1:0, (ppu.bg_enabled[4] == true)?1:0, - (ppu.ss_bg_enabled[0] == true)?1:0, (ppu.ss_bg_enabled[1] == true)?1:0, - (ppu.ss_bg_enabled[2] == true)?1:0, (ppu.ss_bg_enabled[3] == true)?1:0, (ppu.ss_bg_enabled[4] == true)?1:0, - ppu.bg_tilemap_loc[0], ppu.bg_tilemap_loc[1], ppu.bg_tilemap_loc[2], ppu.bg_tilemap_loc[3], - ppu.bg_tiledata_loc[0], ppu.bg_tiledata_loc[1], ppu.bg_tiledata_loc[2], ppu.bg_tiledata_loc[3], ppu.oam_tiledata_loc, - ppu.bg_tilemap_size[0], ppu.bg_tilemap_size[1], ppu.bg_tilemap_size[2], ppu.bg_tilemap_size[3], - ppu.bg_tile_size[0], ppu.bg_tile_size[1], ppu.bg_tile_size[2], ppu.bg_tile_size[3], ppu.bg_priority_mode, - ppu.oam_base_size, ppu.oam_name_sel, (ppu.display_disable == true)?0:1, ppu.display_brightness, - ppu.window1_left, ppu.window1_right, ppu.window2_left, ppu.window2_right, - (ppu.bg_window1_enabled[BG1] == true)?1:0, (ppu.bg_window1_enabled[BG2] == true)?1:0, - (ppu.bg_window1_enabled[BG3] == true)?1:0, (ppu.bg_window1_enabled[BG4] == true)?1:0, - (ppu.bg_window1_enabled[OAM] == true)?1:0, - (ppu.bg_window2_enabled[BG1] == true)?1:0, (ppu.bg_window2_enabled[BG2] == true)?1:0, - (ppu.bg_window2_enabled[BG3] == true)?1:0, (ppu.bg_window2_enabled[BG4] == true)?1:0, - (ppu.bg_window2_enabled[OAM] == true)?1:0, - (ppu.bg_window1_clipmode[BG1] == 1)?"in":"out", (ppu.bg_window1_clipmode[BG2] == 1)?"in":"out", - (ppu.bg_window1_clipmode[BG3] == 1)?"in":"out", (ppu.bg_window1_clipmode[BG4] == 1)?"in":"out", - (ppu.bg_window1_clipmode[OAM] == 1)?"in":"out", - (ppu.bg_window2_clipmode[BG1] == 1)?"in":"out", (ppu.bg_window2_clipmode[BG2] == 1)?"in":"out", - (ppu.bg_window2_clipmode[BG3] == 1)?"in":"out", (ppu.bg_window2_clipmode[BG4] == 1)?"in":"out", - (ppu.bg_window2_clipmode[BG4] == 1)?"in":"out", - (ppu.bg_windowing_enabled[BG1] == true)?1:0, (ppu.bg_windowing_enabled[BG2] == true)?1:0, - (ppu.bg_windowing_enabled[BG3] == true)?1:0, (ppu.bg_windowing_enabled[BG4] == true)?1:0, - (ppu.bg_windowing_enabled[OAM] == true)?1:0, - (ppu.ss_bg_windowing_enabled[BG1] == true)?1:0, (ppu.ss_bg_windowing_enabled[BG2] == true)?1:0, - (ppu.ss_bg_windowing_enabled[BG3] == true)?1:0, (ppu.ss_bg_windowing_enabled[BG4] == true)?1:0, - (ppu.ss_bg_windowing_enabled[OAM] == true)?1:0, - ppu.bg_window_mask[BG1], ppu.bg_window_mask[BG2], - ppu.bg_window_mask[BG3], ppu.bg_window_mask[BG4], ppu.bg_window_mask[OAM], - (ppu.color_window1_enabled == true)?1:0, (ppu.color_window2_enabled == true)?1:0, - ppu.color_window1_clipmode, ppu.color_window2_clipmode, ppu.color_window_mask, - ppu.color_mask, ppu.ss_color_mask, ppu.addsub_mode, ppu.color_mode, ppu.color_halve, - (ppu.bg_color_enabled[BG1] == true)?1:0, (ppu.bg_color_enabled[BG2] == true)?1:0, - (ppu.bg_color_enabled[BG3] == true)?1:0, (ppu.bg_color_enabled[BG4] == true)?1:0, - (ppu.bg_color_enabled[OAM] == true)?1:0, (ppu.bg_color_enabled[BACK] == true)?1:0, - ppu.color_r, ppu.color_g, ppu.color_b, - (ppu.vcounter_enabled == true)?"Yes":"No", (ppu.hcounter_enabled == true)?"Yes":"No", - ppu.virq_pos, ppu.hirq_pos, - (ppu.mode7_vflip == true)?"Yes":"No", (ppu.mode7_hflip == true)?"Yes":"No", - ppu.m7a, (float)ppu.m7a / 256, ppu.m7b, (float)ppu.m7b / 256, - ppu.m7c, (float)ppu.m7c / 256, ppu.m7d, (float)ppu.m7d / 256, - ppu.m7x, ppu.m7y - ); - fclose(fp); + case DCPU_APUSTEP: + if(debug_get_state() == DEBUGMODE_WAIT) { + debug_set_state(DEBUGMODE_APUSTEP); + } + debugger.apu_op_executed = false; break; - case DCPU_TRACE: - if(debugger.trace_enabled == true) { + case DCPU_CFGCPUOUT: + state = SendDlgItemMessage(hwndDCPU, DCPU_CFGCPUOUT, BM_GETCHECK, 0, 0); + debugger.output_cpu_instrs = (state == 1)?true:false; + break; + case DCPU_CFGAPUOUT: + state = SendDlgItemMessage(hwndDCPU, DCPU_CFGAPUOUT, BM_GETCHECK, 0, 0); + debugger.output_apu_instrs = (state == 1)?true:false; + break; + case DCPU_CFGDBGOUT: + state = SendDlgItemMessage(hwndDCPU, DCPU_CFGDBGOUT, BM_GETCHECK, 0, 0); + debugger.output_debug_info = (state == 1)?true:false; + break; + case DCPU_CFGTRACE: + state = SendDlgItemMessage(hwndDCPU, DCPU_CFGTRACE, BM_GETCHECK, 0, 0); + if(state == 0) { fclose(debugger.trace_fp); debugger.trace_enabled = false; } else { @@ -178,6 +205,66 @@ FILE *fp; debugger.trace_enabled = true; } break; + case DCPU_CFGTRACEPRINT: + state = SendDlgItemMessage(hwndDCPU, DCPU_CFGTRACEPRINT, BM_GETCHECK, 0, 0); + debugger.trace_output_enabled = (state == 1)?true:false; + break; + case DCPU_CFGLOCKUP: + state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKUP, BM_GETCHECK, 0, 0); + debugger.lock_up = (state == 1)?true:false; + debugger.lock_down = false; + SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKDOWN, BM_SETCHECK, 0, 0); + break; + case DCPU_CFGLOCKDOWN: + state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKDOWN, BM_GETCHECK, 0, 0); + debugger.lock_down = (state == 1)?true:false; + debugger.lock_up = false; + SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKUP, BM_SETCHECK, 0, 0); + break; + case DCPU_CFGLOCKLEFT: + state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKLEFT, BM_GETCHECK, 0, 0); + debugger.lock_left = (state == 1)?true:false; + debugger.lock_right = false; + SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKRIGHT, BM_SETCHECK, 0, 0); + break; + case DCPU_CFGLOCKRIGHT: + state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKRIGHT, BM_GETCHECK, 0, 0); + debugger.lock_right = (state == 1)?true:false; + debugger.lock_left = false; + SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKLEFT, BM_SETCHECK, 0, 0); + break; + case DCPU_CFGLOCKA: + state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKA, BM_GETCHECK, 0, 0); + debugger.lock_a = (state == 1)?true:false; + break; + case DCPU_CFGLOCKB: + state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKB, BM_GETCHECK, 0, 0); + debugger.lock_b = (state == 1)?true:false; + break; + case DCPU_CFGLOCKX: + state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKX, BM_GETCHECK, 0, 0); + debugger.lock_x = (state == 1)?true:false; + break; + case DCPU_CFGLOCKY: + state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKY, BM_GETCHECK, 0, 0); + debugger.lock_y = (state == 1)?true:false; + break; + case DCPU_CFGLOCKL: + state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKL, BM_GETCHECK, 0, 0); + debugger.lock_l = (state == 1)?true:false; + break; + case DCPU_CFGLOCKR: + state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKR, BM_GETCHECK, 0, 0); + debugger.lock_r = (state == 1)?true:false; + break; + case DCPU_CFGLOCKSELECT: + state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKSELECT, BM_GETCHECK, 0, 0); + debugger.lock_select = (state == 1)?true:false; + break; + case DCPU_CFGLOCKSTART: + state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKSTART, BM_GETCHECK, 0, 0); + debugger.lock_start = (state == 1)?true:false; + break; } } @@ -187,22 +274,136 @@ FILE *fp; void CreateDCPU(void) { int i; for(i=0;i<20;i++)strcpy(dcpu_disas_mem[i], ""); - CreateWindowEx(WS_EX_STATICEDGE, "STATIC", "", WS_CHILD|WS_VISIBLE, 5, 5, 580, 285, hwndDCPU, (HMENU)DCPU_DISAS, GetModuleHandle(0), 0); + CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", + WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_READONLY, 5, 5, 600, 290, + hwndDCPU, (HMENU)DCPU_DISAS, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Run", WS_CHILD|WS_VISIBLE, 590, 5, 80, 20, hwndDCPU, (HMENU)DCPU_RUN, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Step", WS_CHILD|WS_VISIBLE, 590, 25, 80, 20, hwndDCPU, (HMENU)DCPU_STEP, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Export Mem", WS_CHILD|WS_VISIBLE, 590, 45, 80, 20, hwndDCPU, (HMENU)DCPU_PROCEED, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Info", WS_CHILD|WS_VISIBLE, 590, 65, 80, 20, hwndDCPU, (HMENU)DCPU_INFO, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Trace", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 590, 85, 80, 20, hwndDCPU, (HMENU)DCPU_TRACE, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "cpu (wdc 65816)", WS_CHILD|WS_VISIBLE|BS_GROUPBOX, 610, 5, 250, 60, hwndDCPU, (HMENU)DCPU_CPUGROUP, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Step", WS_CHILD|WS_VISIBLE, 615, 20, 80, 20, hwndDCPU, (HMENU)DCPU_CPUSTEP, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Proceed", WS_CHILD|WS_VISIBLE|WS_DISABLED, 695, 20, 80, 20, hwndDCPU, (HMENU)DCPU_CPUPROCEED, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Skip", WS_CHILD|WS_VISIBLE|WS_DISABLED, 775, 20, 80, 20, hwndDCPU, (HMENU)DCPU_CPUSKIP, GetModuleHandle(0), 0); + CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "0", + WS_CHILD|WS_VISIBLE|ES_RIGHT|WS_DISABLED, 615, 40, 80, 20, hwndDCPU, (HMENU)DCPU_CPUTRACENUM, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Trace", WS_CHILD|WS_VISIBLE|WS_DISABLED, 695, 40, 80, 20, hwndDCPU, (HMENU)DCPU_CPUTRACE, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Disable", WS_CHILD|WS_VISIBLE|WS_DISABLED, 775, 40, 80, 20, hwndDCPU, (HMENU)DCPU_CPUDISABLE, GetModuleHandle(0), 0); - CreateWindow("STATIC", "Scanline: 0\nCycles: 0", WS_CHILD|WS_VISIBLE, 590, 260, 80, 30, hwndDCPU, (HMENU)DCPU_CYCLES, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "apu (sony spc700)", WS_CHILD|WS_VISIBLE|BS_GROUPBOX, 610, 70, 250, 60, hwndDCPU, (HMENU)DCPU_APUGROUP, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Step", WS_CHILD|WS_VISIBLE, 615, 85, 80, 20, hwndDCPU, (HMENU)DCPU_APUSTEP, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Proceed", WS_CHILD|WS_VISIBLE|WS_DISABLED, 695, 85, 80, 20, hwndDCPU, (HMENU)DCPU_APUPROCEED, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Skip", WS_CHILD|WS_VISIBLE|WS_DISABLED, 775, 85, 80, 20, hwndDCPU, (HMENU)DCPU_APUSKIP, GetModuleHandle(0), 0); + CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "0", + WS_CHILD|WS_VISIBLE|ES_RIGHT|WS_DISABLED, 615, 105, 80, 20, hwndDCPU, (HMENU)DCPU_APUTRACENUM, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Trace", WS_CHILD|WS_VISIBLE|WS_DISABLED, 695, 105, 80, 20, hwndDCPU, (HMENU)DCPU_APUTRACE, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Disable", WS_CHILD|WS_VISIBLE|WS_DISABLED, 775, 105, 80, 20, hwndDCPU, (HMENU)DCPU_APUDISABLE, GetModuleHandle(0), 0); - SendDlgItemMessage(hwndDCPU, DCPU_DISAS, WM_SETFONT, (WPARAM)hFontFixed, TRUE); - SendDlgItemMessage(hwndDCPU, DCPU_RUN, WM_SETFONT, (WPARAM)hFont, TRUE); - SendDlgItemMessage(hwndDCPU, DCPU_STEP, WM_SETFONT, (WPARAM)hFont, TRUE); - SendDlgItemMessage(hwndDCPU, DCPU_PROCEED, WM_SETFONT, (WPARAM)hFont, TRUE); - SendDlgItemMessage(hwndDCPU, DCPU_INFO, WM_SETFONT, (WPARAM)hFont, TRUE); - SendDlgItemMessage(hwndDCPU, DCPU_TRACE, WM_SETFONT, (WPARAM)hFont, TRUE); - SendDlgItemMessage(hwndDCPU, DCPU_CYCLES, WM_SETFONT, (WPARAM)hFont, TRUE); + CreateWindow("BUTTON", "System", WS_CHILD|WS_VISIBLE|BS_GROUPBOX, 610, 135, 250, 60, hwndDCPU, (HMENU)DCPU_SYSGROUP, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Run", WS_CHILD|WS_VISIBLE, 615, 150, 80, 20, hwndDCPU, (HMENU)DCPU_SYSRUN, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "To Frame", WS_CHILD|WS_VISIBLE|WS_DISABLED, 695, 150, 80, 20, hwndDCPU, (HMENU)DCPU_SYSRUNTOFRAME, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "To VBlank", WS_CHILD|WS_VISIBLE|WS_DISABLED, 775, 150, 80, 20, hwndDCPU, (HMENU)DCPU_SYSRUNTOVBLANK, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "To NMI", WS_CHILD|WS_VISIBLE|WS_DISABLED, 615, 170, 80, 20, hwndDCPU, (HMENU)DCPU_SYSRUNTONMI, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "To IRQ", WS_CHILD|WS_VISIBLE|WS_DISABLED, 695, 170, 80, 20, hwndDCPU, (HMENU)DCPU_SYSRUNTOIRQ, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "To Interrupt", WS_CHILD|WS_VISIBLE|WS_DISABLED, 775, 170, 80, 20, hwndDCPU, (HMENU)DCPU_SYSRUNTOINT, GetModuleHandle(0), 0); + + CreateWindow("BUTTON", "Settings", WS_CHILD|WS_VISIBLE|BS_GROUPBOX, 610, 200, 250, 180, hwndDCPU, (HMENU)DCPU_CFGGROUP, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Output CPU instructions to console", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, + 615, 215, 240, 15, hwndDCPU, (HMENU)DCPU_CFGCPUOUT, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Output APU instructions to console", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, + 615, 230, 240, 15, hwndDCPU, (HMENU)DCPU_CFGAPUOUT, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Output debug info to console", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, + 615, 245, 240, 15, hwndDCPU, (HMENU)DCPU_CFGDBGOUT, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Trace output to file (very slow)", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, + 615, 260, 240, 15, hwndDCPU, (HMENU)DCPU_CFGTRACE, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Print debug info while tracing (very slow)", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, + 615, 275, 240, 15, hwndDCPU, (HMENU)DCPU_CFGTRACEPRINT, GetModuleHandle(0), 0); + CreateWindow("COMBOBOX", "", WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST|CBS_HASSTRINGS|WS_DISABLED, + 615, 290, 60, 200, hwndDCPU, (HMENU)DCPU_CFGREGTYPE, GetModuleHandle(0), 0); + CreateWindow("COMBOBOX", "", WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST|CBS_HASSTRINGS|WS_DISABLED, + 675, 290, 60, 200, hwndDCPU, (HMENU)DCPU_CFGREGNUM, GetModuleHandle(0), 0); + CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "000000", WS_CHILD|WS_VISIBLE|ES_RIGHT|WS_DISABLED, + 735, 290, 60, 20, hwndDCPU, (HMENU)DCPU_CFGREGVAL, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Set Reg", WS_CHILD|WS_VISIBLE|WS_DISABLED, + 795, 290, 60, 20, hwndDCPU, (HMENU)DCPU_CFGREGSET, GetModuleHandle(0), 0); + CreateWindow("STATIC", "Lock Joypad Buttons Down:", WS_CHILD|WS_VISIBLE, 615, 315, 240, 15, hwndDCPU, (HMENU)DCPU_CFGLOCK, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Up", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, + 615, 330, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKUP, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Down", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, + 675, 330, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKDOWN, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Left", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, + 735, 330, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKLEFT, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Right", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, + 795, 330, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKRIGHT, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "A", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, + 615, 345, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKA, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "B", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, + 675, 345, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKB, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "X", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, + 735, 345, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKX, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Y", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, + 795, 345, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKY, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "L", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, + 615, 360, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKL, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "R", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, + 675, 360, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKR, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Select", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, + 735, 360, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKSELECT, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Start", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, + 795, 360, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKSTART, GetModuleHandle(0), 0); + + CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", + WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_READONLY, 5, 300, 600, 80, + hwndDCPU, (HMENU)DCPU_STATUS, GetModuleHandle(0), 0); + + SendDlgItemMessage(hwndDCPU, DCPU_DISAS, WM_SETFONT, (WPARAM)hFontFixed, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CPUGROUP, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CPUSTEP, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CPUPROCEED, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CPUSKIP, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CPUTRACENUM, WM_SETFONT, (WPARAM)hFontFixed, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CPUTRACE, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CPUDISABLE, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_APUGROUP, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_APUSTEP, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_APUPROCEED, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_APUSKIP, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_APUTRACENUM, WM_SETFONT, (WPARAM)hFontFixed, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_APUTRACE, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_APUDISABLE, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_SYSGROUP, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_SYSRUN, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_SYSRUNTOFRAME, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_SYSRUNTOVBLANK, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_SYSRUNTONMI, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_SYSRUNTOIRQ, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_SYSRUNTOINT, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGGROUP, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGCPUOUT, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGAPUOUT, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGDBGOUT, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGTRACE, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGTRACEPRINT, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGREGTYPE, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGREGNUM, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGREGVAL, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGREGSET, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCK, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKUP, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKDOWN, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKLEFT, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKRIGHT, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKA, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKB, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKX, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKY, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKL, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKR, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKSELECT, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKSTART, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDCPU, DCPU_STATUS, WM_SETFONT, (WPARAM)hFontFixed, TRUE); + + SendDlgItemMessage(hwndDCPU, DCPU_CFGCPUOUT, BM_SETCHECK, (WPARAM)(debugger.output_cpu_instrs == true)?1:0, 0); + SendDlgItemMessage(hwndDCPU, DCPU_CFGAPUOUT, BM_SETCHECK, (WPARAM)(debugger.output_apu_instrs == true)?1:0, 0); + SendDlgItemMessage(hwndDCPU, DCPU_CFGDBGOUT, BM_SETCHECK, (WPARAM)(debugger.output_debug_info == true)?1:0, 0); + SendDlgItemMessage(hwndDCPU, DCPU_CFGTRACE, BM_SETCHECK, (WPARAM)(debugger.trace_enabled == true)?1:0, 0); + SendDlgItemMessage(hwndDCPU, DCPU_CFGTRACEPRINT, BM_SETCHECK, (WPARAM)(debugger.trace_output_enabled == true)?1:0, 0); } diff --git a/bsnes/win/gui_mem.cpp b/bsnes/win/gui_mem.cpp index ba68a08a..83e19b90 100644 --- a/bsnes/win/gui_mem.cpp +++ b/bsnes/win/gui_mem.cpp @@ -1,3 +1,6 @@ +#define DMEM_WIDTH 500 +#define DMEM_HEIGHT 268 + #define DMEM_VIEW 100 #define DMEM_EDITWRAM 101 #define DMEM_UP40 102 @@ -12,17 +15,23 @@ #define DMEM_TOROM 111 #define DMEM_TOVRAM 112 #define DMEM_TOCGRAM 113 -#define DMEM_TOOAM 114 -#define DMEM_TOOFFSET 115 -#define DMEM_EDITLOC 116 -#define DMEM_EDITVAL 117 -#define DMEM_STATIC1 118 -#define DMEM_STATIC2 119 +#define DMEM_TOSRAM 114 +#define DMEM_TOSPCRAM 115 +#define DMEM_TOOAM 116 +#define DMEM_TOOFFSET 117 +#define DMEM_EDITLOC 118 +#define DMEM_EDITVAL 119 +#define DMEM_STATIC1 120 +#define DMEM_STATIC2 121 +#define DMEM_VIEWMODE 122 +#define DMEM_GOTOADDR 123 +#define DMEM_GOTO 124 -#define DMEMMODE_WRAM 0 -#define DMEMMODE_VRAM 1 -#define DMEMMODE_CGRAM 2 -#define DMEMMODE_OAM 3 +#define DMEMMODE_WRAM 0 +#define DMEMMODE_VRAM 1 +#define DMEMMODE_CGRAM 2 +#define DMEMMODE_OAM 3 +#define DMEMMODE_SPCRAM 4 ulong dmem_mode = DMEMMODE_WRAM; HWND hwndDMEM; @@ -31,7 +40,7 @@ void debug_refresh_mem(void) { char str[64*16], t[16]; ulong ptr; int x, y; - if(debug_get_state() == DEBUGMODE_DISABLED)return; + if(debugger_enabled() == false)return; ptr = debugger.mem_ptr; strcpy(str, ""); @@ -47,7 +56,7 @@ int x, y; strcat(str, t); if(x != 15)strcat(str, " "); } - if(y != 15)strcat(str, "\n"); + if(y != 15)strcat(str, "\r\n"); } } else if(dmem_mode == DMEMMODE_VRAM) { ptr &= 0xffff; @@ -60,7 +69,7 @@ int x, y; strcat(str, t); if(x != 15)strcat(str, " "); } - if(y != 15)strcat(str, "\n"); + if(y != 15)strcat(str, "\r\n"); } } else if(dmem_mode == DMEMMODE_CGRAM) { ptr &= 0x01ff; @@ -73,7 +82,7 @@ int x, y; strcat(str, t); if(x != 15)strcat(str, " "); } - if(y != 15)strcat(str, "\n"); + if(y != 15)strcat(str, "\r\n"); } } else if(dmem_mode == DMEMMODE_OAM) { ptr &= 0x03ff; @@ -86,7 +95,20 @@ int x, y; strcat(str, t); if(x != 15)strcat(str, " "); } - if(y != 15)strcat(str, "\n"); + if(y != 15)strcat(str, "\r\n"); + } + } else if(dmem_mode == DMEMMODE_SPCRAM) { + ptr &= 0xffff; + for(y=0;y<16;y++) { + sprintf(t, "--%0.4x: ", ptr); + strcat(str, t); + for(x=0;x<16;x++) { + sprintf(t, "%0.2x", spc700->ram[ptr++]); + ptr &= 0xffff; + strcat(str, t); + if(x != 15)strcat(str, " "); + } + if(y != 15)strcat(str, "\r\n"); } } @@ -94,16 +116,23 @@ int x, y; } void __mask_mem_ptr(void) { - if(dmem_mode == DMEMMODE_WRAM )debugger.mem_ptr &= 0xffffff; - if(dmem_mode == DMEMMODE_VRAM )debugger.mem_ptr &= 0x00ffff; - if(dmem_mode == DMEMMODE_CGRAM)debugger.mem_ptr &= 0x0001ff; - if(dmem_mode == DMEMMODE_OAM )debugger.mem_ptr &= 0x0003ff; + if(dmem_mode == DMEMMODE_WRAM )debugger.mem_ptr &= 0xffffff; + if(dmem_mode == DMEMMODE_VRAM )debugger.mem_ptr &= 0x00ffff; + if(dmem_mode == DMEMMODE_CGRAM )debugger.mem_ptr &= 0x0001ff; + if(dmem_mode == DMEMMODE_OAM )debugger.mem_ptr &= 0x0003ff; + if(dmem_mode == DMEMMODE_SPCRAM)debugger.mem_ptr &= 0x00ffff; } long __stdcall wndprocDMEM(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { char str[256]; ulong pos, val; - if(msg == WM_DESTROY || msg == WM_CLOSE)return 0; //don't allow debugger to be closed (yet) + if(msg == WM_DESTROY || msg == WM_CLOSE) { + return 0; //don't allow debugger to be closed (yet) + } + + if(emu_state.rom_loaded == false) { + return DefWindowProc(hwnd, msg, wparam, lparam); + } if(msg == WM_COMMAND) { switch(LOWORD(wparam)) { @@ -120,6 +149,8 @@ ulong pos, val; ppu.cgram[pos & 0x01ff] = val; } else if(dmem_mode == DMEMMODE_OAM) { oam_write(pos, val); + } else if(dmem_mode == DMEMMODE_SPCRAM) { + spc700->ram[pos & 0xffff] = val; } debug_refresh_mem(); break; @@ -163,39 +194,38 @@ ulong pos, val; debug_refresh_mem(); __mask_mem_ptr(); break; - case DMEM_TOWRAM: - dmem_mode = DMEMMODE_WRAM; - debugger.mem_ptr = 0x7e0000; - SetWindowText(hwndDMEM, "g65816 memory editor -- snes memory mode"); - debug_refresh_mem(); + case DMEM_VIEWMODE: + if(HIWORD(wparam) == CBN_SELCHANGE) { + pos = SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_GETCURSEL, 0, 0); + if(pos == 0) { + dmem_mode = DMEMMODE_WRAM; + debugger.mem_ptr = 0x7e0000; + } else if(pos == 1) { + dmem_mode = DMEMMODE_WRAM; + if (gx816->map == MEMMAP_LOROM)debugger.mem_ptr = 0x008000; + else if(gx816->map == MEMMAP_HIROM)debugger.mem_ptr = 0xc00000; + } else if(pos == 2) { + dmem_mode = DMEMMODE_WRAM; + if (gx816->map == MEMMAP_LOROM)debugger.mem_ptr = 0x306000; + else if(gx816->map == MEMMAP_HIROM)debugger.mem_ptr = 0x700000; + } else if(pos == 3) { + dmem_mode = DMEMMODE_VRAM; + debugger.mem_ptr = 0x0000; + } else if(pos == 4) { + dmem_mode = DMEMMODE_CGRAM; + debugger.mem_ptr = 0x0000; + } else if(pos == 5) { + dmem_mode = DMEMMODE_OAM; + debugger.mem_ptr = 0x0000; + } else if(pos == 6) { + dmem_mode = DMEMMODE_SPCRAM; + debugger.mem_ptr = 0x0000; + } + debug_refresh_mem(); + } break; - case DMEM_TOROM: - dmem_mode = DMEMMODE_WRAM; - if(gx816->map == MEMMAP_LOROM)debugger.mem_ptr = 0x008000; - else if(gx816->map == MEMMAP_HIROM)debugger.mem_ptr = 0xc00000; - SetWindowText(hwndDMEM, "g65816 memory editor -- snes memory mode"); - debug_refresh_mem(); - break; - case DMEM_TOVRAM: - dmem_mode = DMEMMODE_VRAM; - debugger.mem_ptr = 0x0000; - SetWindowText(hwndDMEM, "g65816 memory editor -- ppu vram mode"); - debug_refresh_mem(); - break; - case DMEM_TOCGRAM: - dmem_mode = DMEMMODE_CGRAM; - debugger.mem_ptr = 0x0000; - SetWindowText(hwndDMEM, "g65816 memory editor -- ppu cgram mode"); - debug_refresh_mem(); - break; - case DMEM_TOOAM: - dmem_mode = DMEMMODE_OAM; - debugger.mem_ptr = 0x0000; - SetWindowText(hwndDMEM, "g65816 memory editor -- ppu oam mode"); - debug_refresh_mem(); - break; - case DMEM_TOOFFSET: - GetDlgItemText(hwndDMEM, DMEM_EDITLOC, str, 255); + case DMEM_GOTO: + GetDlgItemText(hwndDMEM, DMEM_GOTOADDR, str, 255); debugger.mem_ptr = strhex(str); __mask_mem_ptr(); debug_refresh_mem(); @@ -207,30 +237,43 @@ ulong pos, val; } void CreateDMEM(void) { - CreateWindowEx(WS_EX_STATICEDGE, "STATIC", "", WS_CHILD|WS_VISIBLE, 5, 5, 390, 228, hwndDMEM, (HMENU)DMEM_VIEW, GetModuleHandle(0), 0); - CreateWindow("STATIC", "Offset: Val:", WS_CHILD|WS_VISIBLE, 400, 5, 100, 15, hwndDMEM, (HMENU)DMEM_STATIC1, GetModuleHandle(0), 0); - CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "000000", WS_CHILD|WS_VISIBLE, 400, 20, 60, 23, hwndDMEM, (HMENU)DMEM_EDITLOC, GetModuleHandle(0), 0); - CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "00", WS_CHILD|WS_VISIBLE, 460, 20, 30, 23, hwndDMEM, (HMENU)DMEM_EDITVAL, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Edit Memory", WS_CHILD|WS_VISIBLE, 400, 45, 90, 20, hwndDMEM, (HMENU)DMEM_EDITWRAM, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "-40", WS_CHILD|WS_VISIBLE, 400, 70, 45, 20, hwndDMEM, (HMENU)DMEM_UP40, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "+40", WS_CHILD|WS_VISIBLE, 445, 70, 45, 20, hwndDMEM, (HMENU)DMEM_DOWN40, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "-400", WS_CHILD|WS_VISIBLE, 400, 90, 45, 20, hwndDMEM, (HMENU)DMEM_UP400, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "+400", WS_CHILD|WS_VISIBLE, 445, 90, 45, 20, hwndDMEM, (HMENU)DMEM_DOWN400, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "-4000", WS_CHILD|WS_VISIBLE, 400, 110, 45, 20, hwndDMEM, (HMENU)DMEM_UP4000, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "+4000", WS_CHILD|WS_VISIBLE, 445, 110, 45, 20, hwndDMEM, (HMENU)DMEM_DOWN4000, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "-40000", WS_CHILD|WS_VISIBLE, 400, 130, 45, 20, hwndDMEM, (HMENU)DMEM_UP40000, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "+40000", WS_CHILD|WS_VISIBLE, 445, 130, 45, 20, hwndDMEM, (HMENU)DMEM_DOWN40000, GetModuleHandle(0), 0); - CreateWindow("STATIC", "Seek To:", WS_CHILD|WS_VISIBLE, 400, 155, 100, 15, hwndDMEM, (HMENU)DMEM_STATIC2, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "WRAM", WS_CHILD|WS_VISIBLE, 400, 173, 45, 20, hwndDMEM, (HMENU)DMEM_TOWRAM, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "ROM", WS_CHILD|WS_VISIBLE, 445, 173, 45, 20, hwndDMEM, (HMENU)DMEM_TOROM, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "VRAM", WS_CHILD|WS_VISIBLE, 400, 193, 45, 20, hwndDMEM, (HMENU)DMEM_TOVRAM, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "CGRAM", WS_CHILD|WS_VISIBLE, 445, 193, 45, 20, hwndDMEM, (HMENU)DMEM_TOCGRAM, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "OAM", WS_CHILD|WS_VISIBLE, 400, 213, 45, 20, hwndDMEM, (HMENU)DMEM_TOOAM, GetModuleHandle(0), 0); - CreateWindow("BUTTON", "Offset", WS_CHILD|WS_VISIBLE, 445, 213, 45, 20, hwndDMEM, (HMENU)DMEM_TOOFFSET, GetModuleHandle(0), 0); + CreateWindow("COMBOBOX", "", + WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST|CBS_HASSTRINGS, + 5, 5, 200, 200, hwndDMEM, (HMENU)DMEM_VIEWMODE, GetModuleHandle(0), 0); + CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "000000", WS_CHILD|WS_VISIBLE, 210, 5, 60, 21, hwndDMEM, (HMENU)DMEM_GOTOADDR, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Goto", WS_CHILD|WS_VISIBLE, 270, 5, 50, 20, hwndDMEM, (HMENU)DMEM_GOTO, GetModuleHandle(0), 0); + CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", + WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_READONLY, + 5, 30, 395, 233, hwndDMEM, (HMENU)DMEM_VIEW, GetModuleHandle(0), 0); + + CreateWindow("STATIC", "Offset: Val:", WS_CHILD|WS_VISIBLE, 405, 15, 100, 15, hwndDMEM, (HMENU)DMEM_STATIC1, GetModuleHandle(0), 0); + CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "000000", WS_CHILD|WS_VISIBLE, 405, 30, 60, 23, hwndDMEM, (HMENU)DMEM_EDITLOC, GetModuleHandle(0), 0); + CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "00", WS_CHILD|WS_VISIBLE, 465, 30, 30, 23, hwndDMEM, (HMENU)DMEM_EDITVAL, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "Edit Memory", WS_CHILD|WS_VISIBLE, 405, 55, 90, 20, hwndDMEM, (HMENU)DMEM_EDITWRAM, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "-40", WS_CHILD|WS_VISIBLE, 405, 80, 45, 20, hwndDMEM, (HMENU)DMEM_UP40, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "+40", WS_CHILD|WS_VISIBLE, 450, 80, 45, 20, hwndDMEM, (HMENU)DMEM_DOWN40, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "-400", WS_CHILD|WS_VISIBLE, 405, 100, 45, 20, hwndDMEM, (HMENU)DMEM_UP400, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "+400", WS_CHILD|WS_VISIBLE, 450, 100, 45, 20, hwndDMEM, (HMENU)DMEM_DOWN400, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "-4000", WS_CHILD|WS_VISIBLE, 405, 120, 45, 20, hwndDMEM, (HMENU)DMEM_UP4000, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "+4000", WS_CHILD|WS_VISIBLE, 450, 120, 45, 20, hwndDMEM, (HMENU)DMEM_DOWN4000, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "-40000", WS_CHILD|WS_VISIBLE, 405, 140, 45, 20, hwndDMEM, (HMENU)DMEM_UP40000, GetModuleHandle(0), 0); + CreateWindow("BUTTON", "+40000", WS_CHILD|WS_VISIBLE, 450, 140, 45, 20, hwndDMEM, (HMENU)DMEM_DOWN40000, GetModuleHandle(0), 0); + + SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_ADDSTRING, 0, (LPARAM)"DRAM [7e0000-7fffff]"); + SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_ADDSTRING, 0, (LPARAM)"ROM [008000/c00000]"); + SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_ADDSTRING, 0, (LPARAM)"SRAM [306000/700000]"); + SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_ADDSTRING, 0, (LPARAM)"VRAM [0000-ffff]"); + SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_ADDSTRING, 0, (LPARAM)"CGRAM [0000-01ff]"); + SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_ADDSTRING, 0, (LPARAM)"OAM [0000-03ff]"); + SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_ADDSTRING, 0, (LPARAM)"SPCRAM [0000-ffff]"); + SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_SETCURSEL, 0, 0); + + SendDlgItemMessage(hwndDMEM, DMEM_GOTOADDR, WM_SETFONT, (WPARAM)hFontFixed, TRUE); SendDlgItemMessage(hwndDMEM, DMEM_VIEW, WM_SETFONT, (WPARAM)hFontFixed, TRUE); SendDlgItemMessage(hwndDMEM, DMEM_EDITLOC, WM_SETFONT, (WPARAM)hFontFixed, TRUE); SendDlgItemMessage(hwndDMEM, DMEM_EDITVAL, WM_SETFONT, (WPARAM)hFontFixed, TRUE); + SendDlgItemMessage(hwndDMEM, DMEM_GOTO, WM_SETFONT, (WPARAM)hFont, TRUE); SendDlgItemMessage(hwndDMEM, DMEM_STATIC1, WM_SETFONT, (WPARAM)hFont, TRUE); SendDlgItemMessage(hwndDMEM, DMEM_EDITWRAM, WM_SETFONT, (WPARAM)hFont, TRUE); SendDlgItemMessage(hwndDMEM, DMEM_UP40, WM_SETFONT, (WPARAM)hFont, TRUE); @@ -241,12 +284,5 @@ void CreateDMEM(void) { SendDlgItemMessage(hwndDMEM, DMEM_DOWN4000, WM_SETFONT, (WPARAM)hFont, TRUE); SendDlgItemMessage(hwndDMEM, DMEM_UP40000, WM_SETFONT, (WPARAM)hFont, TRUE); SendDlgItemMessage(hwndDMEM, DMEM_DOWN40000, WM_SETFONT, (WPARAM)hFont, TRUE); - SendDlgItemMessage(hwndDMEM, DMEM_STATIC2, WM_SETFONT, (WPARAM)hFont, TRUE); - SendDlgItemMessage(hwndDMEM, DMEM_TOWRAM, WM_SETFONT, (WPARAM)hFont, TRUE); - SendDlgItemMessage(hwndDMEM, DMEM_TOROM, WM_SETFONT, (WPARAM)hFont, TRUE); - SendDlgItemMessage(hwndDMEM, DMEM_TOVRAM, WM_SETFONT, (WPARAM)hFont, TRUE); - SendDlgItemMessage(hwndDMEM, DMEM_TOCGRAM, WM_SETFONT, (WPARAM)hFont, TRUE); - SendDlgItemMessage(hwndDMEM, DMEM_TOOAM, WM_SETFONT, (WPARAM)hFont, TRUE); - SendDlgItemMessage(hwndDMEM, DMEM_TOOFFSET, WM_SETFONT, (WPARAM)hFont, TRUE); + SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, WM_SETFONT, (WPARAM)hFontFixed, TRUE); } - diff --git a/bsnes/win/render.cpp b/bsnes/win/render.cpp index d3bff380..c5598d60 100644 --- a/bsnes/win/render.cpp +++ b/bsnes/win/render.cpp @@ -46,7 +46,7 @@ void CreateDDraw_Win(void) { ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; ddsd.dwWidth = 512; - ddsd.dwHeight = 480; + ddsd.dwHeight = 478; lpdd->CreateSurface(&ddsd, &lpddsb, 0); } @@ -63,12 +63,16 @@ void CreateDDraw_Full(void) { ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; lpdd->CreateSurface(&ddsd, &lpdds, 0); + lpdd->CreateClipper(0, &lpddc, 0); + lpddc->SetHWnd(0, hwndMain); + lpdds->SetClipper(lpddc); + memset(&ddsd, 0, sizeof(DDSURFACEDESC)); ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; ddsd.dwWidth = 512; - ddsd.dwHeight = 480; + ddsd.dwHeight = 478; lpdd->CreateSurface(&ddsd, &lpddsb, 0); } @@ -101,15 +105,19 @@ int i, r, g, b; vfunc RenderScene; +#include "render_modes.cpp" + //sets up color table and sets render proc void CreateColorTable(void) { lpdds->GetSurfaceDesc(&ddsd); switch(ddsd.ddpfPixelFormat.dwRGBBitCount) { case 16: InitColorTable16(); + RenderScene = RenderScene16; break; case 32: InitColorTable24(); + RenderScene = RenderScene32; break; default: alert("Error: Bit depth [%d] unsupported (supported depths: 16, 32)", ddsd.ddpfPixelFormat.dwRGBBitCount); @@ -118,113 +126,50 @@ void CreateColorTable(void) { } } -#include "render_modes.cpp" +void DrawScene(void) { +RECT rsrc, rdest; +POINT p; +HRESULT hr; + p.x = p.y = 0; + if(render.fullscreen == true) { + SetRect(&rdest, 0, 0, 512, 448); + OffsetRect(&rdest, (640 - 512) / 2, (480 - 448) / 2); + } else { + ClientToScreen(hwndMain, &p); + GetClientRect(hwndMain, &rdest); + OffsetRect(&rdest, p.x, p.y); + } -void SelectRenderer(void) { - lpdds->GetSurfaceDesc(&ddsd); - switch(ddsd.ddpfPixelFormat.dwRGBBitCount) { - case 16: - if (render.snes_width == 512 && render.snes_height == 480) { - RenderScene = RenderScene16_512x480; - } else if(render.snes_width == 512 && render.snes_height == 448) { - RenderScene = RenderScene16_512x448; - } else if(render.snes_width == 512 && render.snes_height == 240) { - RenderScene = RenderScene16_512x240; - } else if(render.snes_width == 512 && render.snes_height == 224) { - RenderScene = RenderScene16_512x224; - } else if(render.snes_width == 256 && render.snes_height == 480) { - RenderScene = RenderScene16_256x480; - } else if(render.snes_width == 256 && render.snes_height == 448) { - RenderScene = RenderScene16_256x448; - } else if(render.snes_width == 256 && render.snes_height == 240) { - RenderScene = RenderScene16_256x240; - } else if(render.snes_width == 256 && render.snes_height == 224) { - RenderScene = RenderScene16_256x224; - } else { - alert("Error: Unsupported SNES Resolution: %dx%d", render.snes_width, render.snes_height); - } - break; - case 32: - if (render.snes_width == 512 && render.snes_height == 480) { - RenderScene = RenderScene32_512x480; - } else if(render.snes_width == 512 && render.snes_height == 448) { - RenderScene = RenderScene32_512x448; - } else if(render.snes_width == 512 && render.snes_height == 240) { - RenderScene = RenderScene32_512x240; - } else if(render.snes_width == 512 && render.snes_height == 224) { - RenderScene = RenderScene32_512x224; - } else if(render.snes_width == 256 && render.snes_height == 480) { - RenderScene = RenderScene32_256x480; - } else if(render.snes_width == 256 && render.snes_height == 448) { - RenderScene = RenderScene32_256x448; - } else if(render.snes_width == 256 && render.snes_height == 240) { - RenderScene = RenderScene32_256x240; - } else if(render.snes_width == 256 && render.snes_height == 224) { - RenderScene = RenderScene32_256x224; - } else { - alert("Error: Unsupported SNES Resolution: %dx%d", render.snes_width, render.snes_height); - } - break; - default: - alert("Error: Bit depth [%d] unsupported (supported depths: 16, 32)", ddsd.ddpfPixelFormat.dwRGBBitCount); - exit(0); - break; + if(ppu.overscan == false) { + SetRect(&rsrc, 0, 2, 512, 448); + } else { + SetRect(&rsrc, 0, 2 + 15, 512, 448 + 15); + } + + hr = lpdds->Blt(&rdest, lpddsb, &rsrc, DDBLT_WAIT, 0); + if(hr == DDERR_SURFACELOST) { + lpdds->Restore(); + lpddsb->Restore(); } } void UpdateDisplay(void) { -RECT rsrc, rdest; -POINT p; -HRESULT hr; RenderScene(); - - p.x = p.y = 0; - if(render.fullscreen == true) { - SetRect(&rdest, 0, 0, 512, 448); - OffsetRect(&rdest, (640 - 512) / 2, (480 - 448) / 2); - } else { - ClientToScreen(hwndMain, &p); - GetClientRect(hwndMain, &rdest); - OffsetRect(&rdest, p.x, p.y); - } - - SetRect(&rsrc, 0, 0, render.snes_width, render.snes_height); - - hr = lpdds->Blt(&rdest, lpddsb, &rsrc, DDBLT_WAIT, 0); - if(hr == DDERR_SURFACELOST) { - lpdds->Restore(); - lpddsb->Restore(); - } -} - -void UpdateDisplay_NoRender(void) { -RECT rsrc, rdest; -POINT p; -HRESULT hr; - p.x = p.y = 0; - if(render.fullscreen == true) { - SetRect(&rdest, 0, 0, 512, 448); - OffsetRect(&rdest, (640 - 512) / 2, (480 - 448) / 2); - } else { - ClientToScreen(hwndMain, &p); - GetClientRect(hwndMain, &rdest); - OffsetRect(&rdest, p.x, p.y); - } - - SetRect(&rsrc, 0, 0, render.snes_width, render.snes_height); - - hr = lpdds->Blt(&rdest, lpddsb, &rsrc, DDBLT_WAIT, 0); - if(hr == DDERR_SURFACELOST) { - lpdds->Restore(); - lpddsb->Restore(); - } + DrawScene(); } void video_setmode(bool fullscreen, word width, word height) { bool prev_mode = render.fullscreen; - render.fullscreen = fullscreen; - render.width = width; - render.height = height; + if(debug_get_state() != DEBUGMODE_DISABLED)return; + render.fullscreen = fullscreen; + render.display_width = width; + render.display_height = height; + +//remove top scanline that is not rendered + if (height == 224)height = 223; + else if(height == 239)height = 238; + else if(height == 448)height = 446; + else if(height == 478)height = 476; FixWindowSize(hwndMain, width, height); ShowWindow(hwndMain, SW_NORMAL); @@ -242,6 +187,7 @@ bool prev_mode = render.fullscreen; FixWindowSize(hwndMain, width, height); ShowWindow(hwndMain, SW_NORMAL); } + CreateColorTable(); } } @@ -251,19 +197,17 @@ void video_setsnesmode(void) { } else { render.snes_width = 256; } - if(ppu.interlace == true) { - if(ppu.visible_scanlines == 240) { - render.snes_height = 480; + if(ppu.interlace == false) { + if(ppu.overscan == false) { + render.snes_height = 224; } else { - render.snes_height = 448; + render.snes_height = 239; } } else { - if(ppu.visible_scanlines == 240) { - render.snes_height = 240; + if(ppu.overscan == false) { + render.snes_height = 448; } else { - render.snes_height = 224; + render.snes_height = 478; } } - - SelectRenderer(); } diff --git a/bsnes/win/render_modes.cpp b/bsnes/win/render_modes.cpp index 40980dcb..79076e41 100644 --- a/bsnes/win/render_modes.cpp +++ b/bsnes/win/render_modes.cpp @@ -1,303 +1,84 @@ -void RenderScene16_256x224(void) { -word *screen; -word *src; -word pitch; +void RenderScene16(void) { HRESULT hr; -int x, y; hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); if(hr != DD_OK)return; - pitch = ddsd.lPitch >> 1; - for(y=0;y<224;y++) { - screen = (word*)ddsd.lpSurface + (pitch * y); - src = (word*)ppu.screen + y * 512; - for(x=0;x<256;x++) { - *screen++ = render_color_lookup[*src++]; - } + __asm { + mov edi,ddsd.lpSurface + mov edx,ddsd.lPitch + add edi,edx + add edi,edx + sub edx,1024 + mov esi,ppu.screen + add esi,2048 + mov ebx,478-2 + xor eax,eax + loop_y: + mov ecx,512 + loop_x: + lodsw + mov eax,dword ptr[render_color_lookup+eax*4] + stosw + dec ecx + jnz loop_x + add edi,edx + dec ebx + jnz loop_y } - lpddsb->Unlock(0); -} - -void RenderScene32_256x224(void) { -ulong *screen; -word *src; +/* +word *screen, *src; word pitch; -HRESULT hr; -int x, y; - hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); - if(hr != DD_OK)return; - pitch = ddsd.lPitch >> 2; - for(y=0;y<224;y++) { - screen = (ulong*)ddsd.lpSurface + (pitch * y); - src = (word*)ppu.screen + y * 512; - for(x=0;x<256;x++) { - *screen++ = render_color_lookup[*src++]; - } - } - lpddsb->Unlock(0); -} - -void RenderScene16_256x240(void) { -word *screen; -word *src; -word pitch; -HRESULT hr; -int x, y; - hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); - if(hr != DD_OK)return; - pitch = ddsd.lPitch >> 1; - for(y=0;y<240;y++) { - screen = (word*)ddsd.lpSurface + (pitch * y); - src = (word*)ppu.screen + y * 512; - for(x=0;x<256;x++) { - *screen++ = render_color_lookup[*src++]; - } - } - lpddsb->Unlock(0); -} - -void RenderScene32_256x240(void) { -ulong *screen; -word *src; -word pitch; -HRESULT hr; -int x, y; - hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); - if(hr != DD_OK)return; - pitch = ddsd.lPitch >> 2; - for(y=0;y<240;y++) { - screen = (ulong*)ddsd.lpSurface + (pitch * y); - src = (word*)ppu.screen + y * 512; - for(x=0;x<256;x++) { - *screen++ = render_color_lookup[*src++]; - } - } - lpddsb->Unlock(0); -} - -void RenderScene16_256x448(void) { -word *screen; -word *src; -word pitch; -HRESULT hr; -int x, y; - hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); - if(hr != DD_OK)return; - pitch = ddsd.lPitch >> 1; - for(y=0;y<448;y++) { - screen = (word*)ddsd.lpSurface + (pitch * y); - src = (word*)ppu.screen + y * 512; - for(x=0;x<256;x++) { - *screen++ = render_color_lookup[*src++]; - } - } - lpddsb->Unlock(0); -} - -void RenderScene32_256x448(void) { -ulong *screen; -word *src; -word pitch; -HRESULT hr; -int x, y; - hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); - if(hr != DD_OK)return; - pitch = ddsd.lPitch >> 2; - for(y=0;y<448;y++) { - screen = (ulong*)ddsd.lpSurface + (pitch * y); - src = (word*)ppu.screen + y * 512; - for(x=0;x<256;x++) { - *screen++ = render_color_lookup[*src++]; - } - } - lpddsb->Unlock(0); -} - -void RenderScene16_256x480(void) { -word *screen; -word *src; -word pitch; -HRESULT hr; -int x, y; - hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); - if(hr != DD_OK)return; - pitch = ddsd.lPitch >> 1; - for(y=0;y<480;y++) { - screen = (word*)ddsd.lpSurface + (pitch * y); - src = (word*)ppu.screen + y * 512; - for(x=0;x<256;x++) { - *screen++ = render_color_lookup[*src++]; - } - } - lpddsb->Unlock(0); -} - -void RenderScene32_256x480(void) { -ulong *screen; -word *src; -word pitch; -HRESULT hr; -int x, y; - hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); - if(hr != DD_OK)return; - pitch = ddsd.lPitch >> 2; - for(y=0;y<480;y++) { - screen = (ulong*)ddsd.lpSurface + (pitch * y); - src = (word*)ppu.screen + y * 512; - for(x=0;x<256;x++) { - *screen++ = render_color_lookup[*src++]; - } - } - lpddsb->Unlock(0); -} - -void RenderScene16_512x224(void) { -word *screen; -word *src; -word pitch; -HRESULT hr; -int x, y; - hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); - if(hr != DD_OK)return; - pitch = ddsd.lPitch >> 1; - for(y=0;y<224;y++) { +int x, y; + pitch = ddsd.lPitch >> 1; + for(y=2;y<478;y++) { screen = (word*)ddsd.lpSurface + (pitch * y); src = (word*)ppu.screen + y * 512; for(x=0;x<512;x++) { *screen++ = render_color_lookup[*src++]; } } +*/ lpddsb->Unlock(0); } -void RenderScene32_512x224(void) { -ulong *screen; -word *src; -word pitch; +void RenderScene32(void) { HRESULT hr; -int x, y; hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); if(hr != DD_OK)return; - pitch = ddsd.lPitch >> 2; - for(y=0;y<224;y++) { - screen = (ulong*)ddsd.lpSurface + (pitch * y); - src = (word*)ppu.screen + y * 512; - for(x=0;x<512;x++) { - *screen++ = render_color_lookup[*src++]; - } - } - lpddsb->Unlock(0); -} - -void RenderScene16_512x240(void) { -word *screen; -word *src; -word pitch; -HRESULT hr; -int x, y; - hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); - if(hr != DD_OK)return; - pitch = ddsd.lPitch >> 1; - for(y=0;y<240;y++) { - screen = (word*)ddsd.lpSurface + (pitch * y); - src = (word*)ppu.screen + y * 512; - for(x=0;x<512;x++) { - *screen++ = render_color_lookup[*src++]; - } - } - lpddsb->Unlock(0); -} - -void RenderScene32_512x240(void) { -ulong *screen; -word *src; -word pitch; -HRESULT hr; -int x, y; - hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); - if(hr != DD_OK)return; - pitch = ddsd.lPitch >> 2; - for(y=0;y<240;y++) { - screen = (ulong*)ddsd.lpSurface + (pitch * y); - src = (word*)ppu.screen + y * 512; - for(x=0;x<512;x++) { - *screen++ = render_color_lookup[*src++]; - } - } - lpddsb->Unlock(0); -} - -void RenderScene16_512x448(void) { -word *screen; -word *src; -word pitch; -HRESULT hr; -int x, y; - hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); - if(hr != DD_OK)return; - pitch = ddsd.lPitch >> 1; - for(y=0;y<448;y++) { - screen = (word*)ddsd.lpSurface + (pitch * y); - src = (word*)ppu.screen + y * 512; - for(x=0;x<512;x++) { - *screen++ = render_color_lookup[*src++]; - } - } - lpddsb->Unlock(0); -} - -void RenderScene32_512x448(void) { -ulong *screen; -word *src; -word pitch; -HRESULT hr; -int x, y; - hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); - if(hr != DD_OK)return; - pitch = ddsd.lPitch >> 2; - for(y=0;y<448;y++) { - screen = (ulong*)ddsd.lpSurface + (pitch * y); - src = (word*)ppu.screen + y * 512; - for(x=0;x<512;x++) { - *screen++ = render_color_lookup[*src++]; - } - } - lpddsb->Unlock(0); -} - -void RenderScene16_512x480(void) { -word *screen; -word *src; -word pitch; -HRESULT hr; -int x, y; - hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); - if(hr != DD_OK)return; - pitch = ddsd.lPitch >> 1; - for(y=0;y<480;y++) { - screen = (word*)ddsd.lpSurface + (pitch * y); - src = (word*)ppu.screen + y * 512; - for(x=0;x<512;x++) { - *screen++ = render_color_lookup[*src++]; - } - } - lpddsb->Unlock(0); -} - -void RenderScene32_512x480(void) { -ulong *screen; -word *src; -word pitch; -HRESULT hr; -int x, y; - hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); - if(hr != DD_OK)return; - pitch = ddsd.lPitch >> 2; - for(y=0;y<480;y++) { + __asm { + mov edi,ddsd.lpSurface + mov edx,ddsd.lPitch + add edi,edx + add edi,edx + sub edx,2048 + mov esi,ppu.screen + add esi,2048 + mov ebx,478-2 + loop_y: + mov ecx,512 + loop_x: + lodsw + and eax,0xffff + mov eax,dword ptr[render_color_lookup+eax*4] + stosd + dec ecx + jnz loop_x + add edi,edx + dec ebx + jnz loop_y + } +/* +ulong *screen; +word *src; +word pitch; +int x, y; + pitch = ddsd.lPitch >> 2; + for(y=2;y<478;y++) { screen = (ulong*)ddsd.lpSurface + (pitch * y); src = (word*)ppu.screen + y * 512; for(x=0;x<512;x++) { *screen++ = render_color_lookup[*src++]; } } +*/ lpddsb->Unlock(0); }