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 551d2a4a..614ef29b 100644 Binary files a/bsnes/bsnes.exe and b/bsnes/bsnes.exe differ 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 e685f195..00000000 Binary files a/bsnes/d65816.obj and /dev/null differ diff --git a/bsnes/demo.smc b/bsnes/demo.smc deleted file mode 100644 index 4abad79c..00000000 Binary files a/bsnes/demo.smc and /dev/null differ diff --git a/bsnes/demo.srm b/bsnes/demo.srm deleted file mode 100644 index 6d17cf9d..00000000 Binary files a/bsnes/demo.srm and /dev/null differ diff --git a/bsnes/demo_mode1.smc b/bsnes/demo_mode1.smc deleted file mode 100644 index 687d1749..00000000 Binary files a/bsnes/demo_mode1.smc and /dev/null differ diff --git a/bsnes/demo_mode1.srm b/bsnes/demo_mode1.srm deleted file mode 100644 index 6d17cf9d..00000000 Binary files a/bsnes/demo_mode1.srm and /dev/null differ diff --git a/bsnes/demo_mode4.smc b/bsnes/demo_mode4.smc deleted file mode 100644 index a1811a01..00000000 Binary files a/bsnes/demo_mode4.smc and /dev/null differ diff --git a/bsnes/demo_mode4.srm b/bsnes/demo_mode4.srm deleted file mode 100644 index 6d17cf9d..00000000 Binary files a/bsnes/demo_mode4.srm and /dev/null differ diff --git a/bsnes/g65816.obj b/bsnes/g65816.obj deleted file mode 100644 index f333479d..00000000 Binary files a/bsnes/g65816.obj and /dev/null differ diff --git a/bsnes/gui.obj b/bsnes/gui.obj deleted file mode 100644 index 6d84676e..00000000 Binary files a/bsnes/gui.obj and /dev/null differ diff --git a/bsnes/libstr.obj b/bsnes/libstr.obj deleted file mode 100644 index 7518ffe9..00000000 Binary files a/bsnes/libstr.obj and /dev/null differ diff --git a/bsnes/main.cpp b/bsnes/main.cpp index b01c7881..d21abf20 100644 --- a/bsnes/main.cpp +++ b/bsnes/main.cpp @@ -1,43 +1,120 @@ /* bsnes - project started 10/14/2004 - author byuu */ + project started: 10/14/2004 + author: byuu */ #include "base.h" #include "main.h" #include "timing/timing.h" #include "cpu/g65816.h" -extern snes_timer *snes_time; -extern g65816 *gx816; -extern ppustate ppu; +#include "apu/spc700.h" +#include "bridge/bridge.h" +extern snes_timer *snes_time; +extern g65816 *gx816; +extern sony_spc700 *spc700; +extern ppustate ppu; +extern port_bridge *cpu_apu_bridge; +debugstate debugger; -vfunc RunSNES; - -void RunSNES_NoDebug(void) { -byte l = 64; - while(l--) { - gx816->Run(); - 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 e04557fb..00000000 Binary files a/bsnes/main.obj and /dev/null differ 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 ca0afd4a..00000000 Binary files a/bsnes/memory.obj and /dev/null differ diff --git a/bsnes/mmio.obj b/bsnes/mmio.obj deleted file mode 100644 index 090d59ad..00000000 Binary files a/bsnes/mmio.obj and /dev/null differ 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 450d6b3d..00000000 Binary files a/bsnes/timing.obj and /dev/null differ 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); }