Update to bsnes v005a release.

[No changelog available]
This commit is contained in:
byuu 2005-02-06 04:04:32 +00:00
parent 8751bc433f
commit 6f7cf1bd31
82 changed files with 12410 additions and 6248 deletions

View File

@ -1,6 +1,6 @@
CC = cl CC = cl
CFLAGS = /nologo /O2 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 LIBS = kernel32.lib user32.lib gdi32.lib comdlg32.lib ddraw.lib
all: $(OBJS) all: $(OBJS)
@ -21,12 +21,21 @@ g65816.obj: cpu/g65816*.cpp cpu/g65816.h
d65816.obj: cpu/d65816.cpp d65816.obj: cpu/d65816.cpp
$(CC) $(CFLAGS) /c 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 memory.obj: mem/memory.cpp
$(CC) $(CFLAGS) /c mem/memory.cpp $(CC) $(CFLAGS) /c mem/memory.cpp
mmio.obj: ppu/mmio.cpp ppu/ppu*.cpp mmio.obj: ppu/mmio.cpp ppu/ppu*.cpp
$(CC) $(CFLAGS) /c ppu/mmio.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 gui.obj: win/gui*.cpp win/render*.cpp
$(CC) $(CFLAGS) /c win/gui.cpp $(CC) $(CFLAGS) /c win/gui.cpp

314
bsnes/apu/dspc700.cpp Normal file
View File

@ -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);
}

49
bsnes/apu/spc700.cpp Normal file
View File

@ -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);
}

24
bsnes/apu/spc700.h Normal file
View File

@ -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();
};

35
bsnes/apu/spc700_iplrom.h Normal file
View File

@ -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)
};

194
bsnes/apu/spc700_ops.cpp Normal file
View File

@ -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
};

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

147
bsnes/apu/spc700_ops_or.cpp Normal file
View File

@ -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);
}

342
bsnes/apu/spc700_ops_pc.cpp Normal file
View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -1,4 +1,4 @@
//#define PUBLIC_DOMAIN #define NO_SPC700
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -11,14 +11,18 @@ typedef unsigned short word;
typedef unsigned long ulong; typedef unsigned long ulong;
typedef void (*vfunc)(void); typedef void (*vfunc)(void);
#define SH_2 1 #define SH_2 1
#define SH_4 2 #define SH_4 2
#define SH_8 3 #define SH_8 3
#define SH_16 4 #define SH_16 4
#define SH_32 5 #define SH_32 5
#define SH_64 6 #define SH_64 6
#define SH_128 7 #define SH_128 7
#define SH_256 8 #define SH_256 8
#define SH_512 9
#define SH_1024 10
#define SH_2048 11
#define SH_4096 12
/************************* /*************************
*** general functions *** *** general functions ***
@ -46,8 +50,9 @@ typedef struct {
*****************/ *****************/
typedef struct { typedef struct {
char rom_name[4096], sram_name[4096]; bool rom_loaded;
ulong sram_save_tick_count; ulong sram_save_tick_count;
char rom_name[4096], sram_name[4096];
}emustate; }emustate;
/*********************** /***********************
@ -57,9 +62,12 @@ typedef struct {
void video_setmode(bool fullscreen, word width, word height); void video_setmode(bool fullscreen, word width, word height);
void video_setsnesmode(void); void video_setsnesmode(void);
#define LINE_DOUBLEWIDTH 1
#define LINE_DOUBLEHEIGHT 2
//global export: render //global export: render
typedef struct { typedef struct {
word width, height; word display_width, display_height;
word snes_width, snes_height; word snes_width, snes_height;
bool fullscreen; bool fullscreen;
bool show_menu; bool show_menu;
@ -68,18 +76,30 @@ typedef struct {
byte frame_count; byte frame_count;
bool bg1_enabled[3], bg2_enabled[3], bg3_enabled[3], bg4_enabled[3], oam_enabled[5]; bool bg1_enabled[3], bg2_enabled[3], bg3_enabled[3], bg4_enabled[3], oam_enabled[5];
byte line[239];
}videostate; }videostate;
/*************************** /***************************
*** debugging functions *** *** debugging functions ***
**************************/ **************************/
#define DEBUGMODE_NOROM 0 #define DEBUGMSG_INFO 0
#define DEBUGMODE_DISABLED 1 #define DEBUGMSG_CPU 1
#define DEBUGMODE_WAIT 2 #define DEBUGMSG_APU 2
#define DEBUGMODE_RUN 3
#define DEBUGMODE_STEP 4 #define DEBUGWRITE_NONE 0
#define DEBUGMODE_PROCEED 5 #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_ALL 0
#define DEBUG_BGENABLED_PRI0 1 #define DEBUG_BGENABLED_PRI0 1
@ -87,21 +107,62 @@ typedef struct {
#define DEBUG_BGENABLED_PRI2 3 #define DEBUG_BGENABLED_PRI2 3
#define DEBUG_BGENABLED_PRI3 4 #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 #define debug_get_state() debugger.mode
void dprintf(char *s, ...); #define debugger_enabled() ((debugger.mode == DEBUGMODE_DISABLED)?false:true)
void debug_refresh_mem(void); #define debug_test_bp(__source, __flag, __offset, __value) \
void debug_refresh_bp(void); if(debug_get_state() != DEBUGMODE_DISABLED) { \
void debug_update_cycles(void); 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 { typedef struct {
byte mode; byte mode;
bool trace_enabled; ulong mem_ptr; //position of wram ptr for debug window
ulong mem_ptr; //position of wram ptr for debug window bool disas_cpu_op, disas_apu_op;
bool disas_op;
bool refresh_mem; bool refresh_mem;
bool refresh_bp; 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; FILE *trace_fp;
}debugstate; }debugstate;
@ -147,10 +208,10 @@ typedef struct {
bool display_disable; //$2100 bit 7 bool display_disable; //$2100 bit 7
byte display_brightness; //$2100 bits 0-3 byte display_brightness; //$2100 bits 0-3
byte visible_scanlines; //$2133 bit 2 (NTSC/PAL mode) -- value = 224 or 240 bool overscan;
byte toggle_visible_scanlines; //do not allow change midframe byte visible_scanlines;
bool sprite_halve;
bool interlace; bool interlace, toggle_interlace;
byte interlace_frame; //0 or 1, used to alternate between scanlines rendered byte interlace_frame; //0 or 1, used to alternate between scanlines rendered
bool bg_enabled[5]; bool bg_enabled[5];
@ -173,6 +234,9 @@ typedef struct {
bool virq_triggered; //prevent recursive calling bool virq_triggered; //prevent recursive calling
bool hirq_triggered; //prevent recursive calling bool hirq_triggered; //prevent recursive calling
word vram_write_pos; //holds value at $2116 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 word vram_inc_size; //amount to increment vram_write_pos by
byte vram_inc_reg; //increment on 2118 (0) or 2119 (1) byte vram_inc_reg; //increment on 2118 (0) or 2119 (1)
word cgram_write_pos; //holds value at $2121 (multiplied by 2) word cgram_write_pos; //holds value at $2121 (multiplied by 2)
@ -183,14 +247,11 @@ typedef struct {
word bg_vscroll_pos[4]; word bg_vscroll_pos[4];
word m7hofs, m7vofs; word m7hofs, m7vofs;
byte mul_a, mul_b; byte mul_a, mul_b;
word div_a; word div_a;
byte div_b; byte div_b;
word r_4214, r_4216; word r_4214, r_4216;
ulong r_2134;
word smul_a;
byte smul_b;
ulong smul_r;
bool bg_window1_enabled[5]; bool bg_window1_enabled[5];
bool bg_window2_enabled[5]; bool bg_window2_enabled[5];
@ -213,7 +274,6 @@ typedef struct {
bool bg_color_enabled[6]; bool bg_color_enabled[6];
byte color_r, color_g, color_b; byte color_r, color_g, color_b;
byte toggle_active_hdma_channels;
byte active_hdma_channels; byte active_hdma_channels;
word hdma_scanlines_remaining[8]; word hdma_scanlines_remaining[8];
word hdma_index_pointer[8]; word hdma_index_pointer[8];
@ -230,16 +290,30 @@ typedef struct {
word m7a, m7b, m7c, m7d, m7x, m7y; word m7a, m7b, m7c, m7d, m7x, m7y;
byte mode7_repeat;
bool mode7_extbg;
bool mode7_vflip, mode7_hflip; bool mode7_vflip, mode7_hflip;
byte io4201;
bool counter_latched;
byte mmio_mem_43xx[0x80];
}ppustate; }ppustate;
/********************* /*********************
*** cpu functions *** *** cpu functions ***
********************/ ********************/
#define CPUSTATE_RUN 0
#define CPUSTATE_DMA 1
#define CPUSTATE_STP 2
#define MEMSPEED_SLOWROM 0 #define MEMSPEED_SLOWROM 0
#define MEMSPEED_FASTROM 1 #define MEMSPEED_FASTROM 1
void add_apu_cycles(int n);
//g65816 cpu flags
#define PF_N 0x80 #define PF_N 0x80
#define PF_V 0x40 #define PF_V 0x40
#define PF_M 0x20 #define PF_M 0x20
@ -249,16 +323,24 @@ typedef struct {
#define PF_Z 0x02 #define PF_Z 0x02
#define PF_C 0x01 #define PF_C 0x01
#define BP_OFF 0 //spc700 cpu flags
#define BP_READ 1 #define SPF_N 0x80
#define BP_WRITE 2 #define SPF_V 0x40
#define BP_EXEC 4 #define SPF_P 0x20
#define BP_VAL 8 #define SPF_B 0x10
#define SPF_H 0x08
#define SPF_I 0x04
#define SPF_Z 0x02
#define SPF_C 0x01
/************************ /************************
*** memory functions *** *** memory functions ***
***********************/ ***********************/
#define MEMSPEED_FAST 6
#define MEMSPEED_SLOW 8
#define MEMSPEED_XSLOW 12
#define MEMMAP_HIROM 0x01 #define MEMMAP_HIROM 0x01
#define MEMMAP_LOROM 0x02 #define MEMMAP_LOROM 0x02
@ -289,7 +371,14 @@ enum {
MEMMODE_ADDR_PC, //addr MEMMODE_ADDR_PC, //addr
MEMMODE_IADDR_PC, //(addr) MEMMODE_IADDR_PC, //(addr)
MEMMODE_IADDRX_PC, //(addr,x) 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 #define MEMSIZE_BYTE 1
@ -302,17 +391,19 @@ enum {
//main.cpp //main.cpp
void InitSNES(void); void InitSNES(void);
extern vfunc RunSNES; void RunSNES(void);
void RunSNES_NoDebug(void); void ResetSNES(void);
void RunSNES_Debug(void);
//cpu/g65816_ops_stack.cpp //cpu/g65816_ops_stack.cpp
ulong g65816_stackread(byte size); //ulong g65816_stackread(byte size);
void g65816_stackwrite(byte size, ulong value); //void g65816_stackwrite(byte size, ulong value);
//cpu/d65816.cpp //cpu/d65816.cpp
void disas_g65816_op(void); void disas_g65816_op(void);
//apu/dspc700.cpp
void disas_spc700_op(void);
//ppu/mmio.cpp //ppu/mmio.cpp
byte mmio_read(word addr); byte mmio_read(word addr);
void mmio_write(word addr, byte value); void mmio_write(word addr, byte value);
@ -323,6 +414,7 @@ void ppu_update_scanline(void);
byte oam_read(word addr); byte oam_read(word addr);
void oam_write(word addr, byte value); void oam_write(word addr, byte value);
void PPUInit(byte first_time); void PPUInit(byte first_time);
void ppu_update_dma(void);
//win/render.cpp //win/render.cpp
void UpdateDisplay(void); void UpdateDisplay(void);

26
bsnes/bridge/bridge.cpp Normal file
View File

@ -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;
}

11
bsnes/bridge/bridge.h Normal file
View File

@ -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);
};

Binary file not shown.

View File

@ -1,6 +1,7 @@
#include "../base.h" #include "../base.h"
#include "g65816.h" #include "g65816.h"
extern g65816 *gx816; extern g65816 *gx816;
extern debugstate debugger;
ulong _disas_relb(byte addr) { ulong _disas_relb(byte addr) {
return gx816->regs.pc + (signed char)(addr + 2); return gx816->regs.pc + (signed char)(addr + 2);
@ -298,11 +299,14 @@ char *s = (char*)__disas_op_str;
} }
void disas_g65816_op(void) { void disas_g65816_op(void) {
byte op = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc, MEMACCESS_DEBUGGER); byte op, op0, op1, op2;
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);
char str0[256], str1[256], str2[256]; 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, "??? "); strcpy(__disas_op_str, "??? ");
__disas_op(op, op0, op1, op2); __disas_op(op, op0, op1, op2);
@ -329,9 +333,7 @@ char str0[256], str1[256], str2[256];
(gx816->regs.p & 0x01)?'C':'c'); (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.a.w, gx816->regs.x, gx816->regs.y, gx816->regs.s,
gx816->regs.d, gx816->regs.db, str1); gx816->regs.d, gx816->regs.db, str1);
debug_update_cycles();
} }

View File

@ -2,11 +2,11 @@
#include "../timing/timing.h" #include "../timing/timing.h"
#include "g65816.h" #include "g65816.h"
extern emustate emu_state; extern emustate emu_state;
extern debugstate debugger; extern debugstate debugger;
extern ppustate ppu; extern ppustate ppu;
extern snes_timer *snes_time; extern snes_timer *snes_time;
g65816 *gx816; g65816 *gx816;
#include "g65816_ops.cpp" #include "g65816_ops.cpp"
@ -31,12 +31,12 @@ int i;
if((fsize & 0x000fff) == 0x000200)header_offset = 512; if((fsize & 0x000fff) == 0x000200)header_offset = 512;
fseek(fp, 0x7fdc + header_offset, SEEK_SET); 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; icksum = fgetc(fp) | fgetc(fp) << 8;
if(cksum + icksum == 0xffff)map = MEMMAP_LOROM; if(cksum + icksum == 0xffff)map = MEMMAP_LOROM;
fseek(fp, 0xffdc + header_offset, SEEK_SET); 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; icksum = fgetc(fp) | fgetc(fp) << 8;
if(cksum + icksum == 0xffff)map = MEMMAP_HIROM; 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 //pbr is loaded with 00, and 16-bit pc is loaded with reset vector at 0xfffc
//upon power on and at first reset //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); fclose(fp);
@ -114,12 +114,13 @@ void g65816::PowerOn(byte first_time) {
regs.e = true; regs.e = true;
snes_time->master_cycles = 0; snes_time->master_cycles = 0;
memory_speed = MEMSPEED_SLOWROM; memory_speed = MEMSPEED_SLOWROM;
toggle_memory_speed = MEMSPEED_SLOWROM;
wai_interrupt_occurred = false; wai_interrupt_occurred = false;
InitializeWRAM(0x00); InitializeWRAM(0x00);
PPUInit(first_time); PPUInit(first_time);
UpdateDisplay(); UpdateDisplay();
snes_time->set_speed_map(MEMSPEED_SLOWROM);
cpu_state = CPUSTATE_RUN;
} }
void g65816::Reset(void) { void g65816::Reset(void) {
@ -133,74 +134,68 @@ void g65816::Reset(void) {
regs.pc = mem_read(MEMMODE_LONG, MEMSIZE_WORD, 0x00fffc); regs.pc = mem_read(MEMMODE_LONG, MEMSIZE_WORD, 0x00fffc);
snes_time->master_cycles = 0; snes_time->master_cycles = 0;
memory_speed = MEMSPEED_SLOWROM; memory_speed = MEMSPEED_SLOWROM;
toggle_memory_speed = MEMSPEED_SLOWROM;
wai_interrupt_occurred = false; wai_interrupt_occurred = false;
PPUInit(0); //0 blocks reallocating memory for vram, cgram, etc. PPUInit(0); //0 blocks reallocating memory for vram, cgram, etc.
UpdateDisplay(); UpdateDisplay();
snes_time->set_speed_map(MEMSPEED_SLOWROM);
if(debug_get_state() == DEBUGMODE_WAIT)disas_g65816_op(); 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) { void g65816::InvokeIRQ(word addr) {
wai_interrupt_occurred = true; snes_time->add_cpu_icycles(2); //1,2 [i/o]
snes_time->add_cpu_pcycles(1); gx816->stack_write(gx816->regs.pc >> 16); //3 [write pbr]
if(gx816->regs.e == true) { gx816->stack_write(gx816->regs.pc >> 8); //4 [write pch]
snes_time->add_cpu_scycles(3); gx816->stack_write(gx816->regs.pc); //5 [write pcl]
g65816_stackwrite(MEMSIZE_WORD, gx816->regs.pc); gx816->stack_write(gx816->regs.p); //6 [write p]
g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.p); gx816->op.r.p.l = gx816->op_read(OPMODE_ADDR, addr); //7 [read low]
} else { gx816->op.r.p.h = gx816->op_read(OPMODE_ADDR, addr + 1); //8 [read high]
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;
gx816->regs.pc = gx816->op.r.w;
gx816->regs.p |= PF_I;
wai_interrupt_occurred = true;
snes_time->update_timer(); snes_time->update_timer();
} }
void g65816::Run(void) { void g65816::exec_op(void) {
FILE *fp; FILE *fp;
byte op; byte op;
word h;
int i; int i;
static ulong sram_save_tick = 0; static ulong sram_save_tick = 0;
op = mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc); if(cpu_state == CPUSTATE_RUN || cpu_state == CPUSTATE_STP) {
if(regs.e == true)g65816_optbl_e[op](); op = mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc);
else switch((regs.p & 0x30)) { if(regs.e == true)g65816_optbl_e[op]();
case 0x30:g65816_optbl_MX[op]();break; else switch((regs.p & 0x30)) {
case 0x20:g65816_optbl_Mx[op]();break; case 0x30:g65816_optbl_MX[op]();break;
case 0x10:g65816_optbl_mX[op]();break; case 0x20:g65816_optbl_Mx[op]();break;
case 0x00:g65816_optbl_mx[op]();break; case 0x10:g65816_optbl_mX[op]();break;
} case 0x00:g65816_optbl_mx[op]();break;
}
h = snes_time->hscan_pos; debugger.cpu_op_executed = true;
snes_time->update_timer(); debugger.disas_cpu_op = true;
if(snes_time->hscan_pos >= WRAM_REFRESH_DOT_POS && h < WRAM_REFRESH_DOT_POS) { snes_time->update_timer();
snes_time->add_cpu_cycles(40); } else if(cpu_state == CPUSTATE_DMA) {
ppu_update_dma();
snes_time->update_timer(); snes_time->update_timer();
} }
snes_time->update_timer_events();
ppu_update_scanline(); 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... //see if we need to backup sram to a file yet...
if(sram_size != 0) { if(sram_size != 0) {
sram_save_tick++; sram_save_tick++;
@ -211,20 +206,31 @@ static ulong sram_save_tick = 0;
fclose(fp); 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() { g65816::g65816() {
int i;
rom = (byte*)malloc(0x600000); rom = (byte*)malloc(0x600000);
wram = (byte*)malloc(0x020000); wram = (byte*)malloc(0x020000);
sram = (byte*)malloc(0x0e0000); 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_enabled = false;
nmi_pin = 0; nmi_pin = 0;
op.dp = op.sp = 0x00;
op.r.l = 0x000000;
op.aa.l = 0x000000;
} }
g65816::~g65816() { g65816::~g65816() {

View File

@ -8,8 +8,9 @@
class g65816 { class g65816 {
public: public:
//cpu declarations //cpu declarations
byte cpu_state;
struct { struct {
ulong pc, dc; ulong pc;
union { union {
byte b; byte b;
word w; word w;
@ -19,9 +20,23 @@ public:
byte db, p; byte db, p;
bool e; bool e;
}regs; }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 memory_speed;
byte toggle_memory_speed;
bool index_bank_crossed;
byte nmi_pin; byte nmi_pin;
bool nmi_enabled; bool nmi_enabled;
@ -32,13 +47,6 @@ public:
byte *wram, *sram, *rom; byte *wram, *sram, *rom;
ulong map; ulong map;
ulong sram_size; ulong sram_size;
//debug declarations
struct {
ulong offset;
byte flags;
byte value;
ulong hit_count;
}bp_list[16];
//cpu functions (cpu/g65816.cpp) //cpu functions (cpu/g65816.cpp)
void Run(void); void Run(void);
@ -48,19 +56,29 @@ public:
void InvokeIRQ(word addr); void InvokeIRQ(word addr);
//memory functions (mem/memory.cpp) //memory functions (mem/memory.cpp)
void exec_op(void);
void InitializeROM(byte memory_map); void InitializeROM(byte memory_map);
void InitializeWRAM(byte value); void InitializeWRAM(byte value);
ulong mirror_offset(ulong offset); ulong mirror_offset(ulong offset);
ulong convert_offset(byte read_mode, ulong addr, bool mirror = true); ulong convert_offset(byte read_mode, ulong addr, bool mirror = true);
ulong adjust_base_offset(byte read_mode, ulong addr); //ulong adjust_base_offset(byte read_mode, ulong addr);
ulong read_indirect_address(byte read_mode, ulong addr); //ulong read_indirect_address(byte read_mode, ulong addr);
ulong get_dc(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_direct(ulong addr, byte access_mode = MEMACCESS_NORMAL);
byte mem_getbyte(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_direct(ulong addr, byte value, byte access_mode = MEMACCESS_NORMAL);
void mem_putbyte(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); 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); 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); ulong rom_read(ulong addr, byte read_size);
void rom_write(ulong addr, ulong v, byte write_size); void rom_write(ulong addr, ulong v, byte write_size);

View File

@ -21,14 +21,15 @@
#define g65816_testz(x) if(x)g65816_setz(); else g65816_clrz() #define g65816_testz(x) if(x)g65816_setz(); else g65816_clrz()
#define g65816_testc(x) if(x)g65816_setc(); else g65816_clrc() #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 //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 //opcode functions
#include "g65816_ops_adc.cpp" #include "g65816_ops_adc.cpp"
@ -47,7 +48,7 @@
vfunc g65816_optbl_e[256] = { // g65816_optbl_e, g65816_optbl_e, g65816_optbl_e, 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, // ----------------------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, /* 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, /* 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, /* 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, 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, // ----------------------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, /* 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, /* 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, /* 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, 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, // ----------------------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, /* 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, /* 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, /* 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, 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, // ----------------------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, /* 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, /* 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, /* 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, 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, // ----------------------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, /* 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, /* 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, /* 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,

View File

@ -1,345 +1,526 @@
#define bcd_add_adjust_byte() \ void g65816_flags_adc_b(void) {
if(gx816->regs.p & PF_D) { \ int r = gx816->regs.a.b + gx816->op.r.b + (gx816->regs.p & PF_C);
if(((r ) & 15) > 9)r += 6; \ //bcd
if(((r >> 4) & 15) > 9)r += 6 << 4; \ 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_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_testz((byte)r == 0);
g65816_testc(r > 0xff); g65816_testc(r > 0xff);
gx816->regs.a.b = r; gx816->regs.a.b = r;
g65816_incpc(2);
snes_time->add_cpu_pcycles(2);
} }
void g65816_op_adc_constw(void) { void g65816_flags_adc_w(void) {
g65816_prefetch(2); int r = gx816->regs.a.w + gx816->op.r.w + (gx816->regs.p & PF_C);
int r = gx816->regs.a.w + arg + (gx816->regs.p & PF_C); //bcd
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;
}
g65816_testn(r & 0x8000); 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_testz((word)r == 0);
g65816_testc(r > 0xffff); g65816_testc(r > 0xffff);
gx816->regs.a.w = r; 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);
} }

View File

@ -1,335 +1,504 @@
#define g65816_flags_and_b() g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0) void g65816_flags_and_b() {
#define g65816_flags_and_w() g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0) g65816_testn(gx816->regs.a.b & 0x80);
g65816_testz(gx816->regs.a.b == 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_op_and_addrw(void) { void g65816_flags_and_w() {
g65816_prefetch(2); g65816_testn(gx816->regs.a.w & 0x8000);
g65816_getaddr(MEMMODE_ADDR); g65816_testz(gx816->regs.a.w == 0);
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_op_and_addrxb(void) { /************************
g65816_prefetch(2); *** 0x29: and #const ***
g65816_getaddr(MEMMODE_ADDRX); ************************
g65816_inst_and_b(); cycles:
g65816_flags_and_b(); [1 ] pbr,pc ; opcode
g65816_incpc(3); [2 ] pbr,pc+1 ; idl
snes_time->add_cpu_pcycles(3); [2a] pbr,pc+2 ; idh [1]
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);
}
void g65816_op_and_constb(void) { void g65816_op_and_constb(void) {
g65816_prefetch(1); gx816->regs.a.b &= gx816->read_operand(1); //1,2 [op fetch]
gx816->regs.a.b &= arg;
g65816_flags_and_b(); g65816_flags_and_b();
g65816_incpc(2); g65816_incpc(2);
snes_time->add_cpu_pcycles(2);
} }
void g65816_op_and_constw(void) { void g65816_op_and_constw(void) {
g65816_prefetch(2); gx816->regs.a.w &= gx816->read_operand(2); //1,2,2a [op fetch]
gx816->regs.a.w &= arg;
g65816_flags_and_w(); g65816_flags_and_w();
g65816_incpc(3); 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);
} }

View File

@ -1,321 +1,508 @@
#define g65816_flags_cmp_b() \ void g65816_flags_cmp_b() {
byte c = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); \ int r = gx816->regs.a.b - gx816->op.r.b;
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;
g65816_testn(r & 0x80); g65816_testn(r & 0x80);
g65816_testz((byte)r == 0); g65816_testz((byte)r == 0);
g65816_testc(r >= 0); g65816_testc(r >= 0);
g65816_incpc(2);
snes_time->add_cpu_pcycles(2);
} }
void g65816_op_cmp_constw(void) { void g65816_flags_cmp_w() {
g65816_prefetch(2); int r = gx816->regs.a.w - gx816->op.r.w;
int r;
r = gx816->regs.a.w - arg;
g65816_testn(r & 0x8000); g65816_testn(r & 0x8000);
g65816_testz((word)r == 0); g65816_testz((word)r == 0);
g65816_testc(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);
} }

View File

@ -1,335 +1,504 @@
#define g65816_flags_eor_b() g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0) void g65816_flags_eor_b() {
#define g65816_flags_eor_w() g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0) g65816_testn(gx816->regs.a.b & 0x80);
g65816_testz(gx816->regs.a.b == 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_op_eor_addrw(void) { void g65816_flags_eor_w() {
g65816_prefetch(2); g65816_testn(gx816->regs.a.w & 0x8000);
g65816_getaddr(MEMMODE_ADDR); g65816_testz(gx816->regs.a.w == 0);
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_op_eor_addrxb(void) { /************************
g65816_prefetch(2); *** 0x49: eor #const ***
g65816_getaddr(MEMMODE_ADDRX); ************************
g65816_inst_eor_b(); cycles:
g65816_flags_eor_b(); [1 ] pbr,pc ; opcode
g65816_incpc(3); [2 ] pbr,pc+1 ; idl
snes_time->add_cpu_pcycles(3); [2a] pbr,pc+2 ; idh [1]
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);
}
void g65816_op_eor_constb(void) { void g65816_op_eor_constb(void) {
g65816_prefetch(1); gx816->regs.a.b ^= gx816->read_operand(1); //1,2 [op fetch]
gx816->regs.a.b ^= arg;
g65816_flags_eor_b(); g65816_flags_eor_b();
g65816_incpc(2); g65816_incpc(2);
snes_time->add_cpu_pcycles(2);
} }
void g65816_op_eor_constw(void) { void g65816_op_eor_constw(void) {
g65816_prefetch(2); gx816->regs.a.w ^= gx816->read_operand(2); //1,2,2a [op fetch]
gx816->regs.a.w ^= arg;
g65816_flags_eor_w(); g65816_flags_eor_w();
g65816_incpc(3); 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);
} }

View File

@ -1,355 +1,511 @@
/*********** /*****************
*** inc *** *** 0x1a: inc ***
**********/ *****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void g65816_op_incb(void) { 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++; gx816->regs.a.b++;
g65816_testn(gx816->regs.a.b & 0x80); g65816_testn(gx816->regs.a.b & 0x80);
g65816_testz(gx816->regs.a.b == 0); g65816_testz(gx816->regs.a.b == 0);
g65816_incpc(1); g65816_incpc(1);
snes_time->add_cpu_pcycles(1);
snes_time->add_cpu_icycles(1);
} }
void g65816_op_incw(void) { 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++; gx816->regs.a.w++;
g65816_testn(gx816->regs.a.w & 0x8000); g65816_testn(gx816->regs.a.w & 0x8000);
g65816_testz(gx816->regs.a.w == 0); g65816_testz(gx816->regs.a.w == 0);
g65816_incpc(1); 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) { void g65816_op_inc_addrb(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
g65816_getaddr(MEMMODE_ADDR); gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read]
byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); snes_time->add_cpu_icycles(1); //5 [i/o]
m++; gx816->op.r.b++;
gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.b); //6 [write]
g65816_testn(m & 0x80);
g65816_testz(m == 0); g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(3); 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) { void g65816_op_inc_addrw(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
g65816_getaddr(MEMMODE_ADDR); gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low]
word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high]
m++; snes_time->add_cpu_icycles(1); //5 [i/o]
gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); gx816->op.r.w++;
g65816_testn(m & 0x8000); gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->op.r.p.h); //6a [write high]
g65816_testz(m == 0); 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); 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) { void g65816_op_inc_addrxb(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
g65816_getaddr(MEMMODE_ADDRX); snes_time->add_cpu_icycles(1); //4 [i/o]
byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read]
m++; snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); gx816->op.r.b++;
g65816_testn(m & 0x80); gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.b); //7 [write]
g65816_testz(m == 0);
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(3); 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) { void g65816_op_inc_addrxw(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
g65816_getaddr(MEMMODE_ADDRX); snes_time->add_cpu_icycles(1); //4 [i/o]
word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read low]
m++; gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //5a [read high]
gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); snes_time->add_cpu_icycles(1); //6 [i/o]
g65816_testn(m & 0x8000); gx816->op.r.w++;
g65816_testz(m == 0); 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); 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) { void g65816_op_inc_dpb(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
g65816_getaddr(MEMMODE_DP); gx816->op_cond(2); //2a [dl!=0]
byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read]
m++; snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); gx816->op.r.b++;
g65816_testn(m & 0x80); gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.b); //5 [write]
g65816_testz(m == 0);
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(2); 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) { void g65816_op_inc_dpw(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
g65816_getaddr(MEMMODE_DP); gx816->op_cond(2); //2a [dl!=0]
word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low]
m++; gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high]
gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); snes_time->add_cpu_icycles(1); //4 [i/o]
g65816_testn(m & 0x8000); gx816->op.r.w++;
g65816_testz(m == 0); 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); 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) { void g65816_op_inc_dpxb(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
g65816_getaddr(MEMMODE_DPX); gx816->op_cond(2); //2a [dl!=0]
byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); snes_time->add_cpu_icycles(1); //3 [i/o]
m++; gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read]
gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testn(m & 0x80); gx816->op.r.b++;
g65816_testz(m == 0); 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); 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) { void g65816_op_inc_dpxw(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
g65816_getaddr(MEMMODE_DPX); gx816->op_cond(2); //2a [dl!=0]
word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); snes_time->add_cpu_icycles(1); //3 [i/o]
m++; gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low]
gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high]
g65816_testn(m & 0x8000); snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testz(m == 0); 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); 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) { 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_testn(gx816->regs.x & 0x80);
g65816_testz((gx816->regs.x & 0xff) == 0); g65816_testz(gx816->regs.x == 0);
g65816_incpc(1); g65816_incpc(1);
snes_time->add_cpu_pcycles(1);
snes_time->add_cpu_icycles(1);
} }
void g65816_op_inxw(void) { 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_testn(gx816->regs.x & 0x8000);
g65816_testz(gx816->regs.x == 0); g65816_testz(gx816->regs.x == 0);
g65816_incpc(1); 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) { 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_testn(gx816->regs.y & 0x80);
g65816_testz((gx816->regs.y & 0xff) == 0); g65816_testz(gx816->regs.y == 0);
g65816_incpc(1); g65816_incpc(1);
snes_time->add_cpu_pcycles(1);
snes_time->add_cpu_icycles(1);
} }
void g65816_op_inyw(void) { 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_testn(gx816->regs.y & 0x8000);
g65816_testz(gx816->regs.y == 0); g65816_testz(gx816->regs.y == 0);
g65816_incpc(1); 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) { 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--; gx816->regs.a.b--;
g65816_testn(gx816->regs.a.b & 0x80); g65816_testn(gx816->regs.a.b & 0x80);
g65816_testz(gx816->regs.a.b == 0); g65816_testz(gx816->regs.a.b == 0);
g65816_incpc(1); g65816_incpc(1);
snes_time->add_cpu_pcycles(1);
snes_time->add_cpu_icycles(1);
} }
void g65816_op_decw(void) { 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--; gx816->regs.a.w--;
g65816_testn(gx816->regs.a.w & 0x8000); g65816_testn(gx816->regs.a.w & 0x8000);
g65816_testz(gx816->regs.a.w == 0); g65816_testz(gx816->regs.a.w == 0);
g65816_incpc(1); 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) { void g65816_op_dec_addrb(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
g65816_getaddr(MEMMODE_ADDR); gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read]
byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); snes_time->add_cpu_icycles(1); //5 [i/o]
m--; gx816->op.r.b--;
gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.b); //6 [write]
g65816_testn(m & 0x80);
g65816_testz(m == 0); g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(3); 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) { void g65816_op_dec_addrw(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
g65816_getaddr(MEMMODE_ADDR); gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low]
word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high]
m--; snes_time->add_cpu_icycles(1); //5 [i/o]
gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); gx816->op.r.w--;
g65816_testn(m & 0x8000); gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->op.r.p.h); //6a [write high]
g65816_testz(m == 0); 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); 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) { void g65816_op_dec_addrxb(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
g65816_getaddr(MEMMODE_ADDRX); snes_time->add_cpu_icycles(1); //4 [i/o]
byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read]
m--; snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); gx816->op.r.b--;
g65816_testn(m & 0x80); gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.b); //7 [write]
g65816_testz(m == 0);
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(3); 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) { void g65816_op_dec_addrxw(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
g65816_getaddr(MEMMODE_ADDRX); snes_time->add_cpu_icycles(1); //4 [i/o]
word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read low]
m--; gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //5a [read high]
gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); snes_time->add_cpu_icycles(1); //6 [i/o]
g65816_testn(m & 0x8000); gx816->op.r.w--;
g65816_testz(m == 0); 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); 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) { void g65816_op_dec_dpb(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
g65816_getaddr(MEMMODE_DP); gx816->op_cond(2); //2a [dl!=0]
byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read]
m--; snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); gx816->op.r.b--;
g65816_testn(m & 0x80); gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.b); //5 [write]
g65816_testz(m == 0);
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(2); 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) { void g65816_op_dec_dpw(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
g65816_getaddr(MEMMODE_DP); gx816->op_cond(2); //2a [dl!=0]
word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low]
m--; gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high]
gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); snes_time->add_cpu_icycles(1); //4 [i/o]
g65816_testn(m & 0x8000); gx816->op.r.w--;
g65816_testz(m == 0); 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); 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) { void g65816_op_dec_dpxb(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
g65816_getaddr(MEMMODE_DPX); gx816->op_cond(2); //2a [dl!=0]
byte m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr); snes_time->add_cpu_icycles(1); //3 [i/o]
m--; gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read]
gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dest_addr, m); snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testn(m & 0x80); gx816->op.r.b--;
g65816_testz(m == 0); 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); 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) { void g65816_op_dec_dpxw(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
g65816_getaddr(MEMMODE_DPX); gx816->op_cond(2); //2a [dl!=0]
word m = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); snes_time->add_cpu_icycles(1); //3 [i/o]
m--; gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low]
gx816->mem_write(MEMMODE_NONE, MEMSIZE_WORD, dest_addr, m); gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high]
g65816_testn(m & 0x8000); snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testz(m == 0); 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); 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) { 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_testn(gx816->regs.x & 0x80);
g65816_testz((gx816->regs.x & 0xff) == 0); g65816_testz(gx816->regs.x == 0);
g65816_incpc(1); g65816_incpc(1);
snes_time->add_cpu_pcycles(1);
snes_time->add_cpu_icycles(1);
} }
void g65816_op_dexw(void) { 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_testn(gx816->regs.x & 0x8000);
g65816_testz(gx816->regs.x == 0); g65816_testz(gx816->regs.x == 0);
g65816_incpc(1); 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) { 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_testn(gx816->regs.y & 0x80);
g65816_testz((gx816->regs.y & 0xff) == 0); g65816_testz(gx816->regs.y == 0);
g65816_incpc(1); g65816_incpc(1);
snes_time->add_cpu_pcycles(1);
snes_time->add_cpu_icycles(1);
} }
void g65816_op_deyw(void) { 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_testn(gx816->regs.y & 0x8000);
g65816_testz(gx816->regs.y == 0); g65816_testz(gx816->regs.y == 0);
g65816_incpc(1); g65816_incpc(1);
snes_time->add_cpu_pcycles(1);
snes_time->add_cpu_icycles(1);
} }

View File

@ -1,335 +1,504 @@
#define g65816_flags_lda_b() g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0) void g65816_flags_lda_b(void) {
#define g65816_flags_lda_w() g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0) g65816_testn(gx816->regs.a.b & 0x80);
g65816_testz(gx816->regs.a.b == 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_op_lda_addrw(void) { void g65816_flags_lda_w(void) {
g65816_prefetch(2); g65816_testn(gx816->regs.a.w & 0x8000);
g65816_getaddr(MEMMODE_ADDR); g65816_testz(gx816->regs.a.w == 0);
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_op_lda_addrxb(void) { /************************
g65816_prefetch(2); *** 0xa9: lda #const ***
g65816_getaddr(MEMMODE_ADDRX); ************************
g65816_set_lda_b(); cycles:
g65816_flags_lda_b(); [1 ] pbr,pc ; opcode
g65816_incpc(3); [2 ] pbr,pc+1 ; idl
snes_time->add_cpu_pcycles(3); [2a] pbr,pc+2 ; idh [1]
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);
}
void g65816_op_lda_constb(void) { void g65816_op_lda_constb(void) {
g65816_prefetch(1); gx816->regs.a.b = gx816->read_operand(1); //1,2 [op fetch]
gx816->regs.a.b = arg;
g65816_flags_lda_b(); g65816_flags_lda_b();
g65816_incpc(2); g65816_incpc(2);
snes_time->add_cpu_pcycles(2);
} }
void g65816_op_lda_constw(void) { void g65816_op_lda_constw(void) {
g65816_prefetch(2); gx816->regs.a.w = gx816->read_operand(2); //1,2,2a [op fetch]
gx816->regs.a.w = arg;
g65816_flags_lda_w(); g65816_flags_lda_w();
g65816_incpc(3); 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);
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,335 +1,504 @@
#define g65816_flags_ora_b() g65816_testn(gx816->regs.a.b & 0x80); g65816_testz(gx816->regs.a.b == 0) void g65816_flags_ora_b() {
#define g65816_flags_ora_w() g65816_testn(gx816->regs.a.w & 0x8000); g65816_testz(gx816->regs.a.w == 0) g65816_testn(gx816->regs.a.b & 0x80);
g65816_testz(gx816->regs.a.b == 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_op_ora_addrw(void) { void g65816_flags_ora_w() {
g65816_prefetch(2); g65816_testn(gx816->regs.a.w & 0x8000);
g65816_getaddr(MEMMODE_ADDR); g65816_testz(gx816->regs.a.w == 0);
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_op_ora_addrxb(void) { /************************
g65816_prefetch(2); *** 0x09: ora #const ***
g65816_getaddr(MEMMODE_ADDRX); ************************
g65816_inst_ora_b(); cycles:
g65816_flags_ora_b(); [1 ] pbr,pc ; opcode
g65816_incpc(3); [2 ] pbr,pc+1 ; idl
snes_time->add_cpu_pcycles(3); [2a] pbr,pc+2 ; idh [1]
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);
}
void g65816_op_ora_constb(void) { void g65816_op_ora_constb(void) {
g65816_prefetch(1); gx816->regs.a.b |= gx816->read_operand(1); //1,2 [op fetch]
gx816->regs.a.b |= arg;
g65816_flags_ora_b(); g65816_flags_ora_b();
g65816_incpc(2); g65816_incpc(2);
snes_time->add_cpu_pcycles(2);
} }
void g65816_op_ora_constw(void) { void g65816_op_ora_constw(void) {
g65816_prefetch(2); gx816->regs.a.w |= gx816->read_operand(2); //1,2,2a [op fetch]
gx816->regs.a.w |= arg;
g65816_flags_ora_w(); g65816_flags_ora_w();
g65816_incpc(3); 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);
} }

View File

@ -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) { void g65816_op_jmp_addr(void) {
g65816_prefetch(2); gx816->op.r.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_pcycles(3);
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | arg; 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) { void g65816_op_jmp_long(void) {
g65816_prefetch(3); gx816->regs.pc = gx816->read_operand(3); //1-4 [op fetch]
snes_time->add_cpu_pcycles(4);
gx816->regs.pc = arg;
} }
/************************
*** 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) { void g65816_op_jmp_iaddr(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
g65816_getaddr(MEMMODE_IADDR_PC); gx816->op.r.p.l = gx816->op_read(OPMODE_ADDR, gx816->op.aa.w); //4 [read low]
snes_time->add_cpu_pcycles(3); gx816->op.r.p.h = gx816->op_read(OPMODE_ADDR, gx816->op.aa.w + 1); //5 [read high]
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->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) { void g65816_op_jmp_iaddrx(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
g65816_getaddr(MEMMODE_IADDRX_PC); snes_time->add_cpu_icycles(1); //4 [i/o]
snes_time->add_cpu_pcycles(3); gx816->op.r.p.l = gx816->op_read(OPMODE_PBR, gx816->op.aa.w + gx816->regs.x); //5 [read low]
snes_time->add_cpu_mcycles(2, dest_addr); gx816->op.r.p.h = gx816->op_read(OPMODE_PBR, gx816->op.aa.w + gx816->regs.x + 1); //6 [read high]
snes_time->add_cpu_icycles(1);
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr); 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) { void g65816_op_jmp_iladdr(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
g65816_getaddr(MEMMODE_ILADDR_PC); gx816->op.r.p.l = gx816->op_read(OPMODE_ADDR, gx816->op.aa.w); //4 [read low]
snes_time->add_cpu_pcycles(3); gx816->op.r.p.h = gx816->op_read(OPMODE_ADDR, gx816->op.aa.w + 1); //5 [read high]
snes_time->add_cpu_mcycles(3, dest_addr); gx816->op.r.p.b = gx816->op_read(OPMODE_ADDR, gx816->op.aa.w + 2); //6 [read bank]
gx816->regs.pc = gx816->mem_read(MEMMODE_NONE, MEMSIZE_LONG, dest_addr);
gx816->regs.pc = gx816->op.r.l;
} }
/*********** /**********************
*** jsr *** *** 0x20: jsr addr ***
**********/ **********************
cycles:
//Note: The address pushed onto the stack is one byte less than the operand size. [1] pbr,pc ; opcode
//Upon returning, the address counter is incremented one more to move to the next [2] pbr,pc+1 ; new pcl
//instruction. The third/fourth cycles store the pc address on the stack, before [3] pbr,pc+2 ; new pch
//the second operand byte is read in. [4] pbr,pc+2 ; io
[5] 0,s ; pch
[6] 0,s-1 ; pcl
*/
void g65816_op_jsr_addr(void) { void g65816_op_jsr_addr(void) {
g65816_prefetch(2); gx816->op.r.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_pcycles(3); snes_time->add_cpu_icycles(1); //4 [i/o]
snes_time->add_cpu_scycles(2); gx816->regs.pc += 2;
snes_time->add_cpu_icycles(1); gx816->stack_write(gx816->regs.pc >> 8); //5 [write high]
g65816_stackwrite(MEMSIZE_WORD, gx816->regs.pc + 2); gx816->stack_write(gx816->regs.pc); //6 [write low]
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | arg;
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) { void g65816_op_jsr_long(void) {
g65816_prefetch(3); gx816->op.r.l = gx816->read_operand(3); //1-3,6 [op fetch]
snes_time->add_cpu_pcycles(4); gx816->regs.pc += 3;
snes_time->add_cpu_scycles(3); gx816->stack_write(gx816->regs.pc >> 16); //4 [write bank]
snes_time->add_cpu_icycles(1); snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_stackwrite(MEMSIZE_LONG, gx816->regs.pc + 3); gx816->stack_write(gx816->regs.pc >> 8); //7 [write high]
gx816->regs.pc = arg; 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) { void g65816_op_jsr_iaddrx(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1,2,5 [op fetch]
g65816_getaddr(MEMMODE_IADDRX_PC); gx816->regs.pc += 2;
snes_time->add_cpu_pcycles(3); gx816->stack_write(gx816->regs.pc >> 8); //3 [write high]
snes_time->add_cpu_scycles(2); gx816->stack_write(gx816->regs.pc); //4 [write low]
snes_time->add_cpu_icycles(1); snes_time->add_cpu_icycles(1); //6 [i/o]
g65816_stackwrite(MEMSIZE_WORD, gx816->regs.pc + 2); gx816->op.r.p.l = gx816->op_read(OPMODE_PBR, gx816->op.aa.w + gx816->regs.x); //7 [read low]
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->mem_read(MEMMODE_IADDRX_PC, MEMSIZE_WORD, arg); gx816->op.r.p.h = gx816->op_read(OPMODE_PBR, gx816->op.aa.w + gx816->regs.x + 1); //8 [read high]
snes_time->add_cpu_pcycles(2);
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) { void g65816_op_rtie(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(3); snes_time->add_cpu_icycles(2); //2,3 [i/o]
gx816->regs.p = g65816_stackread(MEMSIZE_BYTE); gx816->regs.p = gx816->stack_read(); //4 [read p]
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | g65816_stackread(MEMSIZE_WORD); 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; } if(gx816->regs.p & PF_X) { gx816->regs.x &= 0xff; gx816->regs.y &= 0xff; }
gx816->regs.p &= ~ PF_I; gx816->regs.p &= ~ PF_I;
snes_time->add_cpu_icycles(2);
} }
void g65816_op_rtin(void) { void g65816_op_rtin(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(4); snes_time->add_cpu_icycles(2); //2,3 [i/o]
gx816->regs.p = g65816_stackread(MEMSIZE_BYTE); gx816->regs.p = gx816->stack_read(); //4 [read p]
gx816->regs.pc = g65816_stackread(MEMSIZE_LONG); 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; } 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) { void g65816_op_rts(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(2); snes_time->add_cpu_icycles(2); //2,3 [i/o]
snes_time->add_cpu_icycles(3); gx816->op.r.p.l = gx816->stack_read(); //4 [read low]
gx816->regs.pc = ((gx816->regs.pc & 0xff0000) | g65816_stackread(MEMSIZE_WORD)) + 1; 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) { void g65816_op_rtl(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(3); snes_time->add_cpu_icycles(2); //2,3 [i/o]
snes_time->add_cpu_icycles(2); gx816->op.r.p.l = gx816->stack_read(); //4 [read low]
gx816->regs.pc = g65816_stackread(MEMSIZE_LONG) + 1; 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 *** *** 0x80: bra near ***
**********/ **********************
cycles:
//Need to add condition (5) to cycle counts: if e=1, add one (i)cycle if page boundary crossed [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) { void g65816_op_bra(void) {
g65816_prefetch(1); word r;
snes_time->add_cpu_pcycles(2); gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); snes_time->add_cpu_icycles(1); //2a [i/o]
gx816->regs.pc += (signed char)(arg + 2); 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) { void g65816_op_brl(void) {
g65816_prefetch(2); word r;
snes_time->add_cpu_pcycles(3); gx816->op.r.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->regs.pc += (signed short)(arg + 3); 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) { void g65816_op_bcc(void) {
g65816_prefetch(1); word r;
snes_time->add_cpu_pcycles(2); gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
if(!(gx816->regs.p & PF_C)) { if(!(gx816->regs.p & PF_C)) {
snes_time->add_cpu_icycles(1); snes_time->add_cpu_icycles(1); //2a [i/o]
gx816->regs.pc += (signed char)(arg + 2); r = gx816->regs.pc + (signed char)gx816->op.r.b;
} else { if(gx816->regs.e == true) {
g65816_incpc(2); 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) { void g65816_op_bcs(void) {
g65816_prefetch(1); word r;
snes_time->add_cpu_pcycles(2); gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
if(gx816->regs.p & PF_C) { if(gx816->regs.p & PF_C) {
snes_time->add_cpu_icycles(1); snes_time->add_cpu_icycles(1); //2a [i/o]
gx816->regs.pc += (signed char)(arg + 2); r = gx816->regs.pc + (signed char)gx816->op.r.b;
} else { if(gx816->regs.e == true) {
g65816_incpc(2); 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) { void g65816_op_bne(void) {
g65816_prefetch(1); word r;
snes_time->add_cpu_pcycles(2); gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
if(!(gx816->regs.p & PF_Z)) { if(!(gx816->regs.p & PF_Z)) {
snes_time->add_cpu_icycles(1); snes_time->add_cpu_icycles(1); //2a [i/o]
gx816->regs.pc += (signed char)(arg + 2); r = gx816->regs.pc + (signed char)gx816->op.r.b;
} else { if(gx816->regs.e == true) {
g65816_incpc(2); 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) { void g65816_op_beq(void) {
g65816_prefetch(1); word r;
snes_time->add_cpu_pcycles(2); gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
if(gx816->regs.p & PF_Z) { if(gx816->regs.p & PF_Z) {
snes_time->add_cpu_icycles(1); snes_time->add_cpu_icycles(1); //2a [i/o]
gx816->regs.pc += (signed char)(arg + 2); r = gx816->regs.pc + (signed char)gx816->op.r.b;
} else { if(gx816->regs.e == true) {
g65816_incpc(2); 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) { void g65816_op_bpl(void) {
g65816_prefetch(1); word r;
snes_time->add_cpu_pcycles(2); gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
if(!(gx816->regs.p & PF_N)) { if(!(gx816->regs.p & PF_N)) {
snes_time->add_cpu_icycles(1); snes_time->add_cpu_icycles(1); //2a [i/o]
gx816->regs.pc += (signed char)(arg + 2); r = gx816->regs.pc + (signed char)gx816->op.r.b;
} else { if(gx816->regs.e == true) {
g65816_incpc(2); 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) { void g65816_op_bmi(void) {
g65816_prefetch(1); word r;
snes_time->add_cpu_pcycles(2); gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
if(gx816->regs.p & PF_N) { if(gx816->regs.p & PF_N) {
snes_time->add_cpu_icycles(1); snes_time->add_cpu_icycles(1); //2a [i/o]
gx816->regs.pc += (signed char)(arg + 2); r = gx816->regs.pc + (signed char)gx816->op.r.b;
} else { if(gx816->regs.e == true) {
g65816_incpc(2); 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) { void g65816_op_bvc(void) {
g65816_prefetch(1); word r;
snes_time->add_cpu_pcycles(2); gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
if(!(gx816->regs.p & PF_V)) { if(!(gx816->regs.p & PF_V)) {
snes_time->add_cpu_icycles(1); snes_time->add_cpu_icycles(1); //2a [i/o]
gx816->regs.pc += (signed char)(arg + 2); r = gx816->regs.pc + (signed char)gx816->op.r.b;
} else { if(gx816->regs.e == true) {
g65816_incpc(2); 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) { void g65816_op_bvs(void) {
g65816_prefetch(1); word r;
snes_time->add_cpu_pcycles(2); gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
if(gx816->regs.p & PF_V) { if(gx816->regs.p & PF_V) {
snes_time->add_cpu_icycles(1); snes_time->add_cpu_icycles(1); //2a [i/o]
gx816->regs.pc += (signed char)(arg + 2); r = gx816->regs.pc + (signed char)gx816->op.r.b;
} else { if(gx816->regs.e == true) {
g65816_incpc(2); 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);
} }

View File

@ -1,345 +1,526 @@
#define bcd_sub_adjust_byte() \ void g65816_flags_sbc_b() {
if(gx816->regs.p & PF_D) { \ int r = gx816->regs.a.b - gx816->op.r.b - !(gx816->regs.p & PF_C);
if(((r ) & 15) > 9)r -= 6; \ //bcd
if(((r >> 4) & 15) > 9)r -= 6 << 4; \ 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_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_testz((byte)r == 0);
g65816_testc(r >= 0); g65816_testc(r >= 0);
gx816->regs.a.b = r; gx816->regs.a.b = r;
g65816_incpc(2);
snes_time->add_cpu_pcycles(2);
} }
void g65816_op_sbc_constw(void) { void g65816_flags_sbc_w() {
g65816_prefetch(2); int r = gx816->regs.a.w - gx816->op.r.w - !(gx816->regs.p & PF_C);
int r = gx816->regs.a.w - arg - !(gx816->regs.p & PF_C); //bcd
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;
}
g65816_testn(r & 0x8000); 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_testz((word)r == 0);
g65816_testc(r >= 0); g65816_testc(r >= 0);
gx816->regs.a.w = r; 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);
} }

File diff suppressed because it is too large Load Diff

View File

@ -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) { void g65816_op_sta_addrb(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
g65816_getaddr(MEMMODE_ADDR); gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.a.b); //4 [write]
g65816_sta_data_b();
g65816_incpc(3); g65816_incpc(3);
snes_time->add_cpu_pcycles(3);
snes_time->add_cpu_mcycles(1, dest_addr);
} }
void g65816_op_sta_addrw(void) { void g65816_op_sta_addrw(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
g65816_getaddr(MEMMODE_ADDR); gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.a.p.l); //4 [write low]
g65816_sta_data_w(); gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->regs.a.p.h); //4a [write high]
g65816_incpc(3); 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) { void g65816_op_sta_addrxb(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
g65816_getaddr(MEMMODE_ADDRX); snes_time->add_cpu_icycles(1); //3a [write i/o]
g65816_sta_data_b(); gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->regs.a.b); //4 [write]
g65816_incpc(3); 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) { void g65816_op_sta_addrxw(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
g65816_getaddr(MEMMODE_ADDRX); snes_time->add_cpu_icycles(1); //3a [write i/o]
g65816_sta_data_w(); 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); 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) { void g65816_op_sta_dpb(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getaddr(MEMMODE_DP); gx816->op_cond(2); //2a [dl!=0]
g65816_sta_data_b(); gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->regs.a.b); //3 [write]
g65816_incpc(2); 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) { void g65816_op_sta_dpw(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getaddr(MEMMODE_DP); gx816->op_cond(2); //2a [dl!=0]
g65816_sta_data_w(); 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); 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) { void g65816_op_sta_idpb(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getiaddr(MEMMODE_IDP); gx816->op_cond(2); //2a [dl!=0]
g65816_sta_data_b(); 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); 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) { void g65816_op_sta_idpw(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getiaddr(MEMMODE_IDP); gx816->op_cond(2); //2a [dl!=0]
g65816_sta_data_w(); 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); 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) { void g65816_op_sta_ildpb(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getiaddr(MEMMODE_ILDP); gx816->op_cond(2); //2a [dl!=0]
g65816_sta_data_b(); 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); 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) { void g65816_op_sta_ildpw(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getiaddr(MEMMODE_ILDP); gx816->op_cond(2); //2a [dl!=0]
g65816_sta_data_w(); 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); 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) { void g65816_op_sta_longb(void) {
g65816_prefetch(3); gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
g65816_getaddr(MEMMODE_LONG); gx816->op_write(OPMODE_LONG, gx816->op.aa.l, gx816->regs.a.b); //5 [write]
g65816_sta_data_b();
g65816_incpc(4); g65816_incpc(4);
snes_time->add_cpu_pcycles(4);
snes_time->add_cpu_mcycles(1, dest_addr);
} }
void g65816_op_sta_longw(void) { void g65816_op_sta_longw(void) {
g65816_prefetch(3); gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
g65816_getaddr(MEMMODE_LONG); gx816->op_write(OPMODE_LONG, gx816->op.aa.l, gx816->regs.a.p.l); //5 [write]
g65816_sta_data_w(); gx816->op_write(OPMODE_LONG, gx816->op.aa.l + 1, gx816->regs.a.p.h); //5a [write]
g65816_incpc(4); 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) { void g65816_op_sta_longxb(void) {
g65816_prefetch(3); gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
g65816_getaddr(MEMMODE_LONGX); gx816->op_write(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x, gx816->regs.a.b); //5 [write]
g65816_sta_data_b();
g65816_incpc(4); g65816_incpc(4);
snes_time->add_cpu_pcycles(4);
snes_time->add_cpu_mcycles(1, dest_addr);
} }
void g65816_op_sta_longxw(void) { void g65816_op_sta_longxw(void) {
g65816_prefetch(3); gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
g65816_getaddr(MEMMODE_LONGX); gx816->op_write(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x, gx816->regs.a.p.l); //5 [write]
g65816_sta_data_w(); gx816->op_write(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x + 1, gx816->regs.a.p.h); //5a [write]
g65816_incpc(4); 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) { void g65816_op_sta_addryb(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
g65816_getaddr(MEMMODE_ADDRY); snes_time->add_cpu_icycles(1); //3a [write i/o]
g65816_sta_data_b(); gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y, gx816->regs.a.b); //4 [write]
g65816_incpc(3); 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) { void g65816_op_sta_addryw(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
g65816_getaddr(MEMMODE_ADDRY); snes_time->add_cpu_icycles(1); //3a [write i/o]
g65816_sta_data_w(); 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); 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) { void g65816_op_sta_dpxb(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getaddr(MEMMODE_DPX); gx816->op_cond(2); //2a [dl!=0]
g65816_sta_data_b(); 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); 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) { void g65816_op_sta_dpxw(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getaddr(MEMMODE_DPX); gx816->op_cond(2); //2a [dl!=0]
g65816_sta_data_w(); 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); 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) { void g65816_op_sta_idpxb(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getiaddr(MEMMODE_IDPX); gx816->op_cond(2); //2a [dl!=0]
g65816_sta_data_b(); 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); 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) { void g65816_op_sta_idpxw(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getiaddr(MEMMODE_IDPX); gx816->op_cond(2); //2a [dl!=0]
g65816_sta_data_w(); 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); 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) { void g65816_op_sta_idpyb(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getiaddr(MEMMODE_IDPY); gx816->op_cond(2); //2a [dl!=0]
g65816_sta_data_b(); 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); 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) { void g65816_op_sta_idpyw(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getiaddr(MEMMODE_IDPY); gx816->op_cond(2); //2a [dl!=0]
g65816_sta_data_w(); 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); 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) { void g65816_op_sta_ildpyb(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getiaddr(MEMMODE_ILDPY); gx816->op_cond(2); //2a [dl!=0]
g65816_sta_data_b(); 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); 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) { void g65816_op_sta_ildpyw(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getiaddr(MEMMODE_ILDPY); gx816->op_cond(2); //2a [dl!=0]
g65816_sta_data_w(); 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); 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) { void g65816_op_sta_srb(void) {
g65816_prefetch(1); gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getaddr(MEMMODE_SR); snes_time->add_cpu_icycles(1); //3 [i/o]
g65816_sta_data_b(); gx816->op_write(OPMODE_SP, gx816->op.sp, gx816->regs.a.b); //4 [write]
g65816_incpc(2); 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) { void g65816_op_sta_srw(void) {
g65816_prefetch(1); gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getaddr(MEMMODE_SR); snes_time->add_cpu_icycles(1); //3 [i/o]
g65816_sta_data_w(); 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); 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) { void g65816_op_sta_isryb(void) {
g65816_prefetch(1); gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getaddr(MEMMODE_ISRY); snes_time->add_cpu_icycles(1); //3 [i/o]
g65816_sta_data_b(); 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); 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) { void g65816_op_sta_isryw(void) {
g65816_prefetch(1); gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getaddr(MEMMODE_ISRY); snes_time->add_cpu_icycles(1); //3 [i/o]
g65816_sta_data_w(); 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); 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);
} }

View File

@ -1,243 +1,357 @@
ulong g65816_stackread(byte size) { /*****************
ulong r = 0; *** 0x48: pha ***
if(size == MEMSIZE_BYTE) { *****************
gx816->regs.s++; cycles:
r = gx816->mem_read(MEMMODE_LONG, MEMSIZE_BYTE, gx816->regs.s); [1 ] pbr,pc ; opcode
} else if(size == MEMSIZE_WORD) { [2 ] pbr,pc+1 ; io
gx816->regs.s++; [3a] 0,s ; reg high [1]
r = gx816->mem_read(MEMMODE_LONG, MEMSIZE_BYTE, gx816->regs.s); [3 ] 0,s-1 ; reg low
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);
}
}
void g65816_op_phab(void) { void g65816_op_phab(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(1); snes_time->add_cpu_icycles(1); //2 [i/o]
snes_time->add_cpu_icycles(1); gx816->stack_write(gx816->regs.a.b); //3 [reg low]
g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.a.b);
g65816_incpc(1); g65816_incpc(1);
} }
void g65816_op_phaw(void) { void g65816_op_phaw(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(2); snes_time->add_cpu_icycles(1); //2 [i/o]
snes_time->add_cpu_icycles(1); gx816->stack_write(gx816->regs.a.p.h); //3a [reg high]
g65816_stackwrite(MEMSIZE_WORD, gx816->regs.a.w); gx816->stack_write(gx816->regs.a.p.l); //3 [reg low]
g65816_incpc(1); 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) { void g65816_op_phb(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(1); snes_time->add_cpu_icycles(1); //2 [i/o]
snes_time->add_cpu_icycles(1); gx816->stack_write(gx816->regs.db); //3 [reg low]
g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.db);
g65816_incpc(1); 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) { void g65816_op_phd(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(2); snes_time->add_cpu_icycles(1); //2 [i/o]
snes_time->add_cpu_icycles(1); gx816->stack_write(gx816->regs.d >> 8); //3a [reg high]
g65816_stackwrite(MEMSIZE_WORD, gx816->regs.d); gx816->stack_write(gx816->regs.d); //3 [reg low]
g65816_incpc(1); 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) { void g65816_op_phk(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(1); snes_time->add_cpu_icycles(1); //2 [i/o]
snes_time->add_cpu_icycles(1); gx816->stack_write(gx816->regs.pc >> 16); //3 [reg low]
g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.pc >> 16);
g65816_incpc(1); 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) { void g65816_op_php(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(1); snes_time->add_cpu_icycles(1); //2 [i/o]
snes_time->add_cpu_icycles(1); gx816->stack_write(gx816->regs.p); //3 [reg low]
g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.p);
g65816_incpc(1); 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) { void g65816_op_phxb(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(1); snes_time->add_cpu_icycles(1); //2 [i/o]
snes_time->add_cpu_icycles(1); gx816->stack_write(gx816->regs.x); //3 [reg low]
g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.x);
g65816_incpc(1); g65816_incpc(1);
} }
void g65816_op_phxw(void) { void g65816_op_phxw(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(2); snes_time->add_cpu_icycles(1); //2 [i/o]
snes_time->add_cpu_icycles(1); gx816->stack_write(gx816->regs.x >> 8); //3a [reg high]
g65816_stackwrite(MEMSIZE_WORD, gx816->regs.x); gx816->stack_write(gx816->regs.x); //3 [reg low]
g65816_incpc(1); 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) { void g65816_op_phyb(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(1); snes_time->add_cpu_icycles(1); //2 [i/o]
snes_time->add_cpu_icycles(1); gx816->stack_write(gx816->regs.y); //3 [reg low]
g65816_stackwrite(MEMSIZE_BYTE, gx816->regs.y);
g65816_incpc(1); g65816_incpc(1);
} }
void g65816_op_phyw(void) { void g65816_op_phyw(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(2); snes_time->add_cpu_icycles(1); //2 [i/o]
snes_time->add_cpu_icycles(1); gx816->stack_write(gx816->regs.y >> 8); //3a [reg high]
g65816_stackwrite(MEMSIZE_WORD, gx816->regs.y); gx816->stack_write(gx816->regs.y); //3 [reg low]
g65816_incpc(1); 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) { void g65816_op_plab(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(1); snes_time->add_cpu_icycles(2); //2,3 [i/o]
snes_time->add_cpu_icycles(2); gx816->regs.a.b = gx816->stack_read(); //4 [reg low]
gx816->regs.a.b = g65816_stackread(MEMSIZE_BYTE);
g65816_testn(gx816->regs.a.b & 0x80); g65816_testn(gx816->regs.a.b & 0x80);
g65816_testz(gx816->regs.a.b == 0); g65816_testz(gx816->regs.a.b == 0);
g65816_incpc(1); g65816_incpc(1);
} }
void g65816_op_plaw(void) { void g65816_op_plaw(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(2); snes_time->add_cpu_icycles(2); //2,3 [i/o]
snes_time->add_cpu_icycles(2); gx816->regs.a.p.l = gx816->stack_read(); //4 [reg low]
gx816->regs.a.w = g65816_stackread(MEMSIZE_WORD); gx816->regs.a.p.h = gx816->stack_read(); //4a [reg high]
g65816_testn(gx816->regs.a.w & 0x8000); g65816_testn(gx816->regs.a.w & 0x8000);
g65816_testz(gx816->regs.a.w == 0); g65816_testz(gx816->regs.a.w == 0);
g65816_incpc(1); 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) { void g65816_op_plb(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(1); snes_time->add_cpu_icycles(2); //2,3 [i/o]
snes_time->add_cpu_icycles(2); gx816->regs.db = gx816->stack_read(); //4 [reg low]
gx816->regs.db = g65816_stackread(MEMSIZE_BYTE);
g65816_testn(gx816->regs.db & 0x80); g65816_testn(gx816->regs.db & 0x80);
g65816_testz(gx816->regs.db == 0); g65816_testz(gx816->regs.db == 0);
g65816_incpc(1); 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) { void g65816_op_pld(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(2); snes_time->add_cpu_icycles(2); //2,3 [i/o]
snes_time->add_cpu_icycles(2); gx816->regs.d = gx816->stack_read(); //4 [reg low]
gx816->regs.d = g65816_stackread(MEMSIZE_WORD); gx816->regs.d |= gx816->stack_read() << 8; //4a [reg high]
g65816_testn(gx816->regs.d & 0x8000); g65816_testn(gx816->regs.d & 0x8000);
g65816_testz(gx816->regs.d == 0); g65816_testz(gx816->regs.d == 0);
g65816_incpc(1); 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) { void g65816_op_plp(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(1); snes_time->add_cpu_icycles(2); //2,3 [i/o]
snes_time->add_cpu_icycles(2); gx816->regs.p = gx816->stack_read(); //4 [reg low]
gx816->regs.p = g65816_stackread(MEMSIZE_BYTE);
g65816_incpc(1); g65816_incpc(1);
if(gx816->regs.e == true)gx816->regs.p |= 0x30; if(gx816->regs.e == true)gx816->regs.p |= 0x30;
if(gx816->regs.p & PF_X) { gx816->regs.x &= 0xff; gx816->regs.y &= 0xff; } 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) { void g65816_op_plxb(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(1); snes_time->add_cpu_icycles(2); //2,3 [i/o]
snes_time->add_cpu_icycles(2); gx816->regs.x = gx816->stack_read(); //4 [reg low]
gx816->regs.x = g65816_stackread(MEMSIZE_BYTE);
g65816_testn(gx816->regs.x & 0x80); g65816_testn(gx816->regs.x & 0x80);
g65816_testz((gx816->regs.x & 0xff) == 0); g65816_testz(gx816->regs.x == 0);
g65816_incpc(1); g65816_incpc(1);
} }
void g65816_op_plxw(void) { void g65816_op_plxw(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(2); snes_time->add_cpu_icycles(2); //2,3 [i/o]
snes_time->add_cpu_icycles(2); gx816->regs.x = gx816->stack_read(); //4 [reg low]
gx816->regs.x = g65816_stackread(MEMSIZE_WORD); gx816->regs.x |= gx816->stack_read() << 8; //4a [reg high]
g65816_testn(gx816->regs.x & 0x8000); g65816_testn(gx816->regs.x & 0x8000);
g65816_testz(gx816->regs.x == 0); g65816_testz(gx816->regs.x == 0);
g65816_incpc(1); 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) { void g65816_op_plyb(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(1); snes_time->add_cpu_icycles(2); //2,3 [i/o]
snes_time->add_cpu_icycles(2); gx816->regs.y = gx816->stack_read(); //4 [reg low]
gx816->regs.y = g65816_stackread(MEMSIZE_BYTE);
g65816_testn(gx816->regs.y & 0x80); g65816_testn(gx816->regs.y & 0x80);
g65816_testz((gx816->regs.y & 0xff) == 0); g65816_testz(gx816->regs.y == 0);
g65816_incpc(1); g65816_incpc(1);
} }
void g65816_op_plyw(void) { void g65816_op_plyw(void) {
snes_time->add_cpu_pcycles(1); snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_scycles(2); snes_time->add_cpu_icycles(2); //2,3 [i/o]
snes_time->add_cpu_icycles(2); gx816->regs.y = gx816->stack_read(); //4 [reg low]
gx816->regs.y = g65816_stackread(MEMSIZE_WORD); gx816->regs.y |= gx816->stack_read() << 8; //4a [reg high]
g65816_testn(gx816->regs.y & 0x8000); g65816_testn(gx816->regs.y & 0x8000);
g65816_testz(gx816->regs.y == 0); g65816_testz(gx816->regs.y == 0);
g65816_incpc(1); 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) { void g65816_op_pea(void) {
g65816_prefetch(2); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_pcycles(3); gx816->stack_write(gx816->op.aa.p.h); //4 [write high]
snes_time->add_cpu_scycles(2); gx816->stack_write(gx816->op.aa.p.l); //5 [write low]
g65816_stackwrite(MEMSIZE_WORD, arg);
g65816_incpc(3); 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) { void g65816_op_pei(void) {
g65816_prefetch(1); gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
g65816_getaddr(MEMMODE_DP); gx816->op_cond(2); //2a [i/o]
snes_time->add_cpu_pcycles(2); gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read aal]
snes_time->add_cpu_mcycles(2, dest_addr); gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [read aah]
snes_time->add_cpu_scycles(2); gx816->stack_write(gx816->op.aa.p.h); //5 [write aah]
snes_time->add_cpu_icycles(0, TIMING_REGD); gx816->stack_write(gx816->op.aa.p.l); //6 [write aal]
g65816_stackwrite(MEMSIZE_WORD, gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dest_addr));
g65816_incpc(2); 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) { void g65816_op_per(void) {
g65816_prefetch(2); word r;
snes_time->add_cpu_pcycles(3); gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_scycles(2); snes_time->add_cpu_icycles(1); //4 [i/o]
snes_time->add_cpu_icycles(1); r = (gx816->regs.pc + (signed short)gx816->op.aa.w + 3);
g65816_stackwrite(MEMSIZE_WORD, gx816->regs.pc + arg + 3); gx816->stack_write(r >> 8); //5 [write pch]
gx816->stack_write(r); //6 [write pcl]
g65816_incpc(3); g65816_incpc(3);
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,43 +1,120 @@
/* bsnes /* bsnes
project started 10/14/2004 project started: 10/14/2004
author byuu */ author: byuu */
#include "base.h" #include "base.h"
#include "main.h" #include "main.h"
#include "timing/timing.h" #include "timing/timing.h"
#include "cpu/g65816.h" #include "cpu/g65816.h"
extern snes_timer *snes_time; #include "apu/spc700.h"
extern g65816 *gx816; #include "bridge/bridge.h"
extern ppustate ppu; 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 debug_test_breakpoint_hit(byte source, byte flag, ulong offset, byte value, int i) {
dprintf("* breakpoint %d hit", i);
void RunSNES_NoDebug(void) { debugger.bp_list[i].hit_count++;
byte l = 64; debugger.refresh_bp = true;
while(l--) { debug_set_state(DEBUGMODE_WAIT);
gx816->Run(); if(source == BPSRC_SPCRAM) {
gx816->Run(); disas_spc700_op();
gx816->Run(); } else {
gx816->Run(); disas_g65816_op();
gx816->Run();
gx816->Run();
gx816->Run();
gx816->Run();
} }
} }
void RunSNES_Debug(void) { void debug_test_breakpoint(byte source, byte flag, ulong offset, byte value) {
if(debug_get_state() == DEBUGMODE_NOROM)return; 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) { if(debug_get_state() == DEBUGMODE_RUN) {
gx816->Run(); gx816->Run();
spc700->Run();
if(debugger.trace_enabled == true) { 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 { } else {
if(debugger.disas_op == true) { if(debugger.disas_cpu_op == true) {
disas_g65816_op(); 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) { if(debugger.refresh_mem == true) {
debug_refresh_mem(); debug_refresh_mem();
@ -47,30 +124,68 @@ void RunSNES_Debug(void) {
debug_refresh_bp(); debug_refresh_bp();
debugger.refresh_bp = false; 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_WAIT)return;
if(debug_get_state() == DEBUGMODE_STEP) { if(debug_get_state() == DEBUGMODE_CPUSTEP) {
gx816->Run(); gx816->Run();
disas_g65816_op(); spc700->Run();
debug_set_state(DEBUGMODE_WAIT); 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) { void InitSNES(void) {
int i, z;
snes_time = new snes_timer(); snes_time = new snes_timer();
gx816 = new g65816(); gx816 = new g65816();
gx816->PowerOn(1); 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) { if(*emu_state.rom_name == 0) {
debug_set_state(DEBUGMODE_NOROM); emu_state.rom_loaded = false;
} else { } else {
gx816->LoadROM(); 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) { void ResetSNES(void) {
RunSNES = RunSNES_NoDebug; int i;
} else { gx816->Reset();
RunSNES = RunSNES_Debug; 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; emu_state.sram_name[strlen(emu_state.sram_name) - 4] = 0;
} }
strcat(emu_state.sram_name, ".srm"); strcat(emu_state.sram_name, ".srm");
//located in win/gui.cpp
__winmain(); init_debugstate();
__winmain(); //located in win/gui.cpp
return 0; return 0;
} }

View File

@ -5,26 +5,17 @@ void __winmain(void);
to emu_state.sram_name to emu_state.sram_name
*/ */
emustate emu_state = { emustate emu_state = {
"", "", //rom name, sram name false, //rom loaded
1000000 //sram save tick count *1 20000000, //sram save tick count *1
}; "", "" //rom name, sram name
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
}; };
videostate render = { videostate render = {
512, 448, //resolution 512, 448, //display resolution
256, 224, //snes internal resolution 256, 224, //snes internal resolution
false, //fullscreen false, //fullscreen
true, //show menu true, //show menu
1, //frame skip 0, //frame skip
0, //frame count 0, //frame count
{ true, true, true }, //bg1 enable { true, true, true }, //bg1 enable
{ true, true, true }, //bg2 enable { true, true, true }, //bg2 enable

Binary file not shown.

View File

@ -1,8 +1,10 @@
#include "../base.h" #include "../base.h"
#include "../cpu/g65816.h" #include "../cpu/g65816.h"
extern g65816 *gx816; #include "../timing/timing.h"
extern emustate emu_state; extern g65816 *gx816;
extern debugstate debugger; extern emustate emu_state;
extern debugstate debugger;
extern snes_timer *snes_time;
void g65816::InitializeROM(byte memory_map) { void g65816::InitializeROM(byte memory_map) {
memset(rom, 0, 0x600000); memset(rom, 0, 0x600000);
@ -71,37 +73,35 @@ ulong g65816::convert_offset(byte read_mode, ulong addr, bool mirror) {
byte db; byte db;
switch(read_mode) { switch(read_mode) {
case MEMMODE_DP: case MEMMODE_DP:
addr = (regs.d + (addr & 0xff)) & 0xffff; addr = (regs.d + (addr & 0xffff)) & 0xffff;
break; break;
case MEMMODE_DPX: case MEMMODE_DPX:
addr = (regs.d + regs.x + (addr & 0xff)) & 0xffff; addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff;
break; break;
case MEMMODE_DPY: case MEMMODE_DPY:
addr = (regs.d + regs.y + (addr & 0xff)) & 0xffff; addr = (regs.d + regs.y + (addr & 0xffff)) & 0xffff;
break; break;
case MEMMODE_IDP: case MEMMODE_IDP:
addr = (regs.d + (addr & 0xff)) & 0xffff; addr = (regs.d + (addr & 0xffff)) & 0xffff;
addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr); addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr);
addr |= (regs.db << 16); addr |= (regs.db << 16);
break; break;
case MEMMODE_IDPX: 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 = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr);
addr |= (regs.db << 16); addr |= (regs.db << 16);
break; break;
case MEMMODE_IDPY: case MEMMODE_IDPY:
addr = (regs.d + (addr & 0xff)) & 0xffff; addr = (regs.d + (addr & 0xffff)) & 0xffff;
addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr); addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr);
addr += (regs.db << 16) + regs.y; addr += (regs.db << 16) + regs.y;
if((addr >> 16) != regs.db)index_bank_crossed = true;
else index_bank_crossed = false;
break; break;
case MEMMODE_ILDP: case MEMMODE_ILDP:
addr = (regs.d + (addr & 0xff)); addr = (regs.d + (addr & 0xffff));
addr = mem_read(MEMMODE_LONG, MEMSIZE_LONG, addr); addr = mem_read(MEMMODE_LONG, MEMSIZE_LONG, addr);
break; break;
case MEMMODE_ILDPY: case MEMMODE_ILDPY:
addr = (regs.d + (addr & 0xff)); addr = (regs.d + (addr & 0xffff));
addr = mem_read(MEMMODE_LONG, MEMSIZE_LONG, addr); addr = mem_read(MEMMODE_LONG, MEMSIZE_LONG, addr);
addr += regs.y; addr += regs.y;
break; break;
@ -116,14 +116,10 @@ byte db;
case MEMMODE_ADDRX: case MEMMODE_ADDRX:
addr = (regs.db << 16) + (addr & 0xffff); addr = (regs.db << 16) + (addr & 0xffff);
addr += regs.x; addr += regs.x;
if((addr >> 16) != regs.db)index_bank_crossed = true;
else index_bank_crossed = false;
break; break;
case MEMMODE_ADDRY: case MEMMODE_ADDRY:
addr = (regs.db << 16) + (addr & 0xffff); addr = (regs.db << 16) + (addr & 0xffff);
addr += regs.y; addr += regs.y;
if((addr >> 16) != regs.db)index_bank_crossed = true;
else index_bank_crossed = false;
break; break;
case MEMMODE_IADDRX: case MEMMODE_IADDRX:
addr += regs.x; addr += regs.x;
@ -155,6 +151,25 @@ byte db;
addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr); addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr);
addr += (regs.db << 16) + regs.y; addr += (regs.db << 16) + regs.y;
break; 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) { if(mirror == true) {
@ -164,129 +179,13 @@ byte db;
} }
} }
ulong g65816::adjust_base_offset(byte read_mode, ulong addr) { ulong g65816::read_operand(byte size) {
byte db; ulong r;
switch(read_mode) { r = gx816->mem_read(MEMMODE_NONE, size, gx816->regs.pc + 1);
case MEMMODE_DP: //add size + 1 cycles. the extra cycle is for the actual opcode
addr = (regs.d + (addr & 0xff)) & 0xffff; //byte itself being read in by the main cpu emulation routine.
break; snes_time->add_cpu_pcycles(size + 1);
case MEMMODE_DPX: return r;
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;
} }
byte g65816::mem_getbyte_direct(ulong addr, byte access_mode) { byte g65816::mem_getbyte_direct(ulong addr, byte access_mode) {
@ -295,7 +194,11 @@ word a;
db = (addr >> 16) & 0xff; db = (addr >> 16) & 0xff;
a = (addr & 0xffff); a = (addr & 0xffff);
if(db == 0x00 && a >= 0x2000 && a <= 0x5fff) { 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) { if(db == 0x7e || db == 0x7f) {
@ -324,30 +227,9 @@ byte r;
r = mem_getbyte_direct(addr, access_mode); r = mem_getbyte_direct(addr, access_mode);
if(debug_get_state() == DEBUGMODE_DISABLED)return r; if(debug_get_state() == DEBUGMODE_DISABLED)return r;
if(access_mode == MEMACCESS_DEBUGGER)return r; //don't report breakpoint hits from debugger if(access_mode == MEMACCESS_DEBUGGER)return r; //don't report breakpoint hits from debugger
for(i=0;i<16;i++) { debug_test_bp(BPSRC_MEM, BP_READ, addr, r);
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();
}
}
}
}
return r; return r;
} }
@ -392,30 +274,9 @@ int i;
mem_putbyte_direct(addr, value, access_mode); mem_putbyte_direct(addr, value, access_mode);
if(debug_get_state() == DEBUGMODE_DISABLED)return; if(debug_get_state() == DEBUGMODE_DISABLED)return;
if(access_mode == MEMACCESS_DEBUGGER)return; //don't report breakpoint hits from debugger if(access_mode == MEMACCESS_DEBUGGER)return; //don't report breakpoint hits from debugger
for(i=0;i<16;i++) { debug_test_bp(BPSRC_MEM, BP_WRITE, addr, value);
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();
}
}
}
}
} }
ulong g65816::mem_read(byte read_mode, byte read_size, ulong addr, byte access_mode) { ulong g65816::mem_read(byte read_mode, byte read_size, ulong addr, byte access_mode) {
@ -424,16 +285,16 @@ ulong r;
switch(read_size) { switch(read_size) {
case MEMSIZE_BYTE: case MEMSIZE_BYTE:
r = mem_getbyte(addr, access_mode); r = mem_getbyte(addr, access_mode);
break; break;
case MEMSIZE_WORD: case MEMSIZE_WORD:
r = mem_getbyte(addr, access_mode) | r = mem_getbyte(addr, access_mode) |
mem_getbyte(addr + 1, access_mode)<<8; mem_getbyte(addr+1, access_mode)<<8;
break; break;
case MEMSIZE_LONG: case MEMSIZE_LONG:
r = mem_getbyte(addr, access_mode) | r = mem_getbyte(addr, access_mode) |
mem_getbyte(addr + 1, access_mode)<<8 | mem_getbyte(addr+1, access_mode)<<8 |
mem_getbyte(addr + 2, access_mode)<<16; mem_getbyte(addr+2, access_mode)<<16;
break; break;
} }
@ -461,6 +322,63 @@ void g65816::mem_write(byte write_mode, byte write_size, ulong addr, ulong value
debugger.refresh_mem = true; 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 g65816::rom_read(ulong addr, byte read_size) {
ulong r; ulong r;
if(map == MEMMAP_LOROM) { if(map == MEMMAP_LOROM) {

Binary file not shown.

Binary file not shown.

View File

@ -1,14 +1,18 @@
#include "../base.h" #include "../base.h"
#include "../timing/timing.h" #include "../timing/timing.h"
#include "../cpu/g65816.h" #include "../cpu/g65816.h"
extern g65816 *gx816; #include "../bridge/bridge.h"
extern snes_timer *snes_time;
extern videostate render;
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_cache.cpp"
#include "ppu_spc.cpp"
#include "ppu_dma.cpp" #include "ppu_dma.cpp"
#include "ppu_screen.cpp" #include "ppu_screen.cpp"
#include "ppu_vram.cpp" #include "ppu_vram.cpp"
@ -27,21 +31,29 @@ ppustate ppu;
#include "ppu.cpp" #include "ppu.cpp"
byte mmio_read(word addr) { 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) { switch(addr) {
case 0x2134:return mmio_r2134(); case 0x2134:return mmio_r2134();
case 0x2135:return mmio_r2135(); case 0x2135:return mmio_r2135();
case 0x2136:return mmio_r2136(); case 0x2136:return mmio_r2136();
case 0x2137:return mmio_r2137(); case 0x2137:return mmio_r2137();
case 0x2138:return mmio_r2138(); 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 0x213c:return mmio_r213c();
case 0x213d:return mmio_r213d(); case 0x213d:return mmio_r213d();
case 0x213e:return mmio_r213e(); case 0x213e:return mmio_r213e();
case 0x213f:return mmio_r213f(); case 0x213f:return mmio_r213f();
}
switch(addr) {
case 0x2140:case 0x2141:case 0x2142:case 0x2143: case 0x2140:case 0x2141:case 0x2142:case 0x2143:
case 0x2144:case 0x2145:case 0x2146:case 0x2147: case 0x2144:case 0x2145:case 0x2146:case 0x2147:
case 0x2148:case 0x2149:case 0x214a:case 0x214b: 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 0x2174:case 0x2175:case 0x2176:case 0x2177:
case 0x2178:case 0x2179:case 0x217a:case 0x217b: case 0x2178:case 0x2179:case 0x217a:case 0x217b:
case 0x217c:case 0x217d:case 0x217e:case 0x217f: case 0x217c:case 0x217d:case 0x217e:case 0x217f:
byte x; return mmio_rspc((addr & 3));
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; }
break; break;
case 0x2180:return mmio_r2180();
case 0x21c2:return mmio_r21c2(); case 0x21c2:return mmio_r21c2();
case 0x21c3:return mmio_r21c3(); case 0x21c3:return mmio_r21c3();
@ -87,10 +96,28 @@ static word counter = 0;
*/ */
break; 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; return 0x00;
} }
void mmio_write(word addr, byte value) { 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) { switch(addr) {
case 0x2100:mmio_w2100(value);break; case 0x2100:mmio_w2100(value);break;
case 0x2101:mmio_w2101(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 0x2115:mmio_w2115(value);break;
case 0x2116:mmio_w2116(value);break; case 0x2116:mmio_w2116(value);break;
case 0x2117:mmio_w2117(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 0x211a:mmio_w211a(value);break;
case 0x211b:mmio_w211b(value);break; case 0x211b:mmio_w211b(value);break;
case 0x211c:mmio_w211c(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 0x211f:mmio_w211f(value);break;
case 0x2120:mmio_w2120(value);break; case 0x2120:mmio_w2120(value);break;
case 0x2121:mmio_w2121(value);break; case 0x2121:mmio_w2121(value);break;
case 0x2122:mmio_w2122(value);break;
case 0x2123:mmio_w2123(value);break; case 0x2123:mmio_w2123(value);break;
case 0x2124:mmio_w2124(value);break; case 0x2124:mmio_w2124(value);break;
case 0x2125:mmio_w2125(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 0x2131:mmio_w2131(value);break;
case 0x2132:mmio_w2132(value);break; case 0x2132:mmio_w2132(value);break;
case 0x2133:mmio_w2133(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 0x2180:mmio_w2180(value);break;
case 0x2181:mmio_w2181(value);break; case 0x2181:mmio_w2181(value);break;
case 0x2182:mmio_w2182(value);break; case 0x2182:mmio_w2182(value);break;
case 0x2183:mmio_w2183(value);break; case 0x2183:mmio_w2183(value);break;
}
switch(addr) {
case 0x4016:mmio_w4016(value);break; case 0x4016:mmio_w4016(value);break;
case 0x4200:mmio_w4200(value);break; case 0x4200:mmio_w4200(value);break;
case 0x4201:mmio_w4201(value);break;
case 0x4202:mmio_w4202(value);break; case 0x4202:mmio_w4202(value);break;
case 0x4203:mmio_w4203(value);break; case 0x4203:mmio_w4203(value);break;
case 0x4204:mmio_w4204(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 0x4300:case 0x4310:case 0x4320:case 0x4330:
case 0x4340:case 0x4350:case 0x4360:case 0x4370: 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 0x4301:case 0x4311:case 0x4321:case 0x4331:
case 0x4341:case 0x4351:case 0x4361:case 0x4371: 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 0x4302:case 0x4312:case 0x4322:case 0x4332:
case 0x4342:case 0x4352:case 0x4362:case 0x4372: 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 0x4303:case 0x4313:case 0x4323:case 0x4333:
case 0x4343:case 0x4353:case 0x4363:case 0x4373: 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 0x4304:case 0x4314:case 0x4324:case 0x4334:
case 0x4344:case 0x4354:case 0x4364:case 0x4374: 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 0x4305:case 0x4315:case 0x4325:case 0x4335:
case 0x4345:case 0x4355:case 0x4365:case 0x4375: 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 0x4306:case 0x4316:case 0x4326:case 0x4336:
case 0x4346:case 0x4356:case 0x4366:case 0x4376: 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 0x4307:case 0x4317:case 0x4327:case 0x4337:
case 0x4347:case 0x4357:case 0x4367:case 0x4377: 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;
} }
} }

View File

@ -3,206 +3,129 @@
#include "ppu_render.cpp" #include "ppu_render.cpp"
/********************** byte layer_bg_lookup_mode0[12] = {
*** priority table *** BG4, BG3, OAM, BG4, BG3, OAM, BG2, BG1, OAM, BG2, BG1, OAM
********************************* };
*** 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); \
} \
}
void ppu_render_line_mode0(void) { void ppu_render_line_mode0(void) {
if(ppu.bg_priority_mode == 0) { ppu_render_line_bg (7, 10, COLORDEPTH_4, BG1);
debug_ppu_render_line_bg (bg4, COLORDEPTH_4, BG4, 0); ppu_render_line_bg (6, 9, COLORDEPTH_4, BG2);
debug_ppu_render_line_bg (bg3, COLORDEPTH_4, BG3, 0); ppu_render_line_bg (1, 4, COLORDEPTH_4, BG3);
debug_ppu_render_line_oam(oam, 0); ppu_render_line_bg (0, 3, COLORDEPTH_4, BG4);
debug_ppu_render_line_bg (bg4, COLORDEPTH_4, BG4, 1); ppu_render_line_oam(2, 5, 8, 11);
debug_ppu_render_line_bg (bg3, COLORDEPTH_4, BG3, 1); ppu_set_layer_pixels(12, layer_bg_lookup_mode0);
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);
}
} }
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) { void ppu_render_line_mode1(void) {
if(ppu.bg_priority_mode == 0) { switch(ppu.bg_priority_mode) {
debug_ppu_render_line_bg (bg3, COLORDEPTH_4, BG3, 0); case 0:
debug_ppu_render_line_oam(oam, 0); ppu_render_line_bg (5, 8, COLORDEPTH_16, BG1);
debug_ppu_render_line_bg (bg3, COLORDEPTH_4, BG3, 1); ppu_render_line_bg (4, 7, COLORDEPTH_16, BG2);
debug_ppu_render_line_oam(oam, 1); ppu_render_line_bg (0, 2, COLORDEPTH_4, BG3);
debug_ppu_render_line_bg (bg2, COLORDEPTH_16, BG2, 0); ppu_render_line_oam(1, 3, 6, 9);
debug_ppu_render_line_bg (bg1, COLORDEPTH_16, BG1, 0); ppu_set_layer_pixels(10, layer_bg_lookup_mode1_pri0);
debug_ppu_render_line_oam(oam, 2); break;
debug_ppu_render_line_bg (bg2, COLORDEPTH_16, BG2, 1); case 1:
debug_ppu_render_line_bg (bg1, COLORDEPTH_16, BG1, 1); ppu_render_line_bg (4, 7, COLORDEPTH_16, BG1);
debug_ppu_render_line_oam(oam, 3); ppu_render_line_bg (3, 6, COLORDEPTH_16, BG2);
} else { ppu_render_line_bg (0, 9, COLORDEPTH_4, BG3);
debug_ppu_render_line_bg (bg3, COLORDEPTH_4, BG3, 0); ppu_render_line_oam(1, 2, 5, 8);
debug_ppu_render_line_oam(oam, 0); ppu_set_layer_pixels(10, layer_bg_lookup_mode1_pri1);
debug_ppu_render_line_oam(oam, 1); break;
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);
} }
} }
byte layer_bg_lookup_mode2[8] = {
OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
void ppu_render_line_mode2(void) { void ppu_render_line_mode2(void) {
if(ppu.bg_priority_mode == 0) { ppu_render_line_bg (3, 6, COLORDEPTH_16, BG1);
debug_ppu_render_line_oam(oam, 0); ppu_render_line_bg (2, 5, COLORDEPTH_16, BG2);
debug_ppu_render_line_oam(oam, 1); ppu_render_line_oam(0, 1, 4, 7);
debug_ppu_render_line_bg (bg2, COLORDEPTH_16, BG2, 0); ppu_set_layer_pixels(8, layer_bg_lookup_mode2);
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);
}
} }
byte layer_bg_lookup_mode3[8] = {
OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
void ppu_render_line_mode3(void) { void ppu_render_line_mode3(void) {
if(ppu.bg_priority_mode == 0) { ppu_render_line_bg (3, 6, COLORDEPTH_256, BG1);
debug_ppu_render_line_oam(oam, 0); ppu_render_line_bg (2, 5, COLORDEPTH_16, BG2);
debug_ppu_render_line_oam(oam, 1); ppu_render_line_oam(0, 1, 4, 7);
debug_ppu_render_line_bg(bg2, COLORDEPTH_16, BG2, 0); ppu_set_layer_pixels(8, layer_bg_lookup_mode3);
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);
}
} }
byte layer_bg_lookup_mode4[8] = {
OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
void ppu_render_line_mode4(void) { void ppu_render_line_mode4(void) {
if(ppu.bg_priority_mode == 0) { ppu_render_line_bg (3, 6, COLORDEPTH_256, BG1);
debug_ppu_render_line_oam(oam, 0); ppu_render_line_bg (2, 5, COLORDEPTH_4, BG2);
debug_ppu_render_line_oam(oam, 1); ppu_render_line_oam(0, 1, 4, 7);
debug_ppu_render_line_bg(bg2, COLORDEPTH_4, BG2, 0); ppu_set_layer_pixels(8, layer_bg_lookup_mode4);
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);
}
} }
byte layer_bg_lookup_mode5[8] = {
OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
void ppu_render_line_mode5(void) { void ppu_render_line_mode5(void) {
debug_ppu_render_line_bg(bg2, COLORDEPTH_4, BG2, 0); ppu_render_line_bg (3, 6, COLORDEPTH_16, BG1);
debug_ppu_render_line_bg(bg1, COLORDEPTH_16, BG1, 0); ppu_render_line_bg (2, 5, COLORDEPTH_4, BG2);
debug_ppu_render_line_bg(bg2, COLORDEPTH_4, BG2, 0); ppu_render_line_oam(0, 1, 4, 7);
debug_ppu_render_line_bg(bg1, COLORDEPTH_16, BG1, 1); 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) { void ppu_render_line_mode6(void) {
debug_ppu_render_line_bg(bg1, COLORDEPTH_16, BG1, 0); ppu_render_line_bg (2, 4, COLORDEPTH_16, BG1);
debug_ppu_render_line_bg(bg1, COLORDEPTH_16, BG1, 1); 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) { void ppu_render_line_mode7(void) {
if(ppu.bg_priority_mode == 0) { if(ppu.mode7_extbg == false) {
debug_ppu_render_line_oam(oam, 0); ppu_render_line_m7 (1, 0, 0); //bg2 priorities are ignored
debug_ppu_render_line_oam(oam, 1); ppu_render_line_oam(0, 2, 3, 4);
ppu_render_line_m7(); ppu_set_layer_pixels(5, layer_bg_lookup_mode7);
debug_ppu_render_line_oam(oam, 2);
debug_ppu_render_line_oam(oam, 3);
} else { } else {
debug_ppu_render_line_oam(oam, 0); ppu_render_line_m7 (0, 0, 3); //bg1 priority is ignored
debug_ppu_render_line_oam(oam, 1); ppu_render_line_oam(1, 2, 4, 5);
ppu_render_line_m7(); ppu_set_layer_pixels(6, layer_bg_lookup_mode7_extbg);
debug_ppu_render_line_oam(oam, 2);
debug_ppu_render_line_oam(oam, 3);
} }
} }
void ppu_render_scanline(void) { void ppu_render_scanline(void) {
int x, y; int x, y;
ppu.vline_pos = snes_time->vscan_pos;
ppu.hirq_triggered = false; ppu.hirq_triggered = false;
ppu.vline_pos++;
if(ppu.vline_pos > 261)ppu.vline_pos = 0;
//new screen initialize //new screen initialize
if(ppu.vline_pos == 0) { if(ppu.vline_pos == 0) {
hdma_initialize();
ppu.virq_triggered = false; 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; gx816->nmi_pin = 1;
} }
@ -215,7 +138,6 @@ int x, y;
if(render.frame_count >= render.frame_skip) { if(render.frame_count >= render.frame_skip) {
render.frame_count = 0; render.frame_count = 0;
} }
ppu.interlace_frame ^= 1;
} }
//automatic joypad read //automatic joypad read
@ -223,20 +145,12 @@ int x, y;
UpdateJoypad(); 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; 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) { if(ppu.display_disable == true) {
memset(ppu.screen + y * 512, 0, 1024); memset(ppu.screen + (y << 1) * 512, 0, 2048);
} else { } else {
ppu_clear_layer_cache();
ppu_clear_pixel_cache(); ppu_clear_pixel_cache();
switch(ppu.bg_mode) { switch(ppu.bg_mode) {
case 0:ppu_render_line_mode0();break; case 0:ppu_render_line_mode0();break;
@ -254,17 +168,26 @@ int x, y;
} }
void ppu_update_scanline(void) { void ppu_update_scanline(void) {
static bool hdma_triggered = false;
word current_vscan_pos;
//starting a new screen? //starting a new screen?
if(ppu.vline_pos > snes_time->vscan_pos) { if(snes_time->vscan_wrapped == true) {
while(ppu.vline_pos != 0) { snes_time->vscan_wrapped = false;
ppu_render_scanline();
}
} }
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(); 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(!(gx816->regs.p & PF_I)) {
if(ppu.vcounter_enabled == true && ppu.hcounter_enabled == true) { if(ppu.vcounter_enabled == true && ppu.hcounter_enabled == true) {
if(snes_time->vscan_pos == ppu.virq_pos && ppu.virq_triggered == false) { 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 oam_read(word addr) {
byte r;
addr &= 1023; addr &= 1023;
if(addr >= 512) { if(addr >= 512) {
addr &= 31; addr &= 31;
return ppu.oam[addr + 512]; r = ppu.oam[addr + 512];
debug_test_bp(BPSRC_OAM, BP_READ, addr + 512, r);
} else { } 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) { void oam_write(word addr, byte value) {
@ -306,8 +233,10 @@ void oam_write(word addr, byte value) {
if(addr >= 512) { if(addr >= 512) {
addr &= 31; addr &= 31;
ppu.oam[addr + 512] = value; ppu.oam[addr + 512] = value;
debug_test_bp(BPSRC_OAM, BP_WRITE, addr + 512, value);
} else { } else {
ppu.oam[addr] = value; ppu.oam[addr] = value;
debug_test_bp(BPSRC_OAM, BP_WRITE, addr, value);
} }
} }
@ -317,7 +246,7 @@ byte r, g, b;
double m; double m;
word *ptr; word *ptr;
if(first_time == 1) { if(first_time == 1) {
ppu.screen = (word*)malloc(512 * 480 * 2); ppu.screen = (word*)malloc(512 * 478 * 2);
ppu.vram = (byte*)malloc(0x10000); ppu.vram = (byte*)malloc(0x10000);
ppu.cgram = (byte*)malloc(512); ppu.cgram = (byte*)malloc(512);
ppu.oam = (byte*)malloc(544); ppu.oam = (byte*)malloc(544);
@ -349,32 +278,35 @@ word *ptr;
} }
} }
} }
ppu_clear_pixel_cache(); ppu_clear_tiledata_cache();
memset(ppu.screen, 0, 512 * 480 * 2); memset(ppu.screen, 0, 512 * 478 * 2);
memset(ppu.vram, 0, 0x10000); memset(ppu.vram, 0, 0x10000);
memset(ppu.cgram, 0, 512); memset(ppu.cgram, 0, 512);
memset(ppu.oam, 0, 544); memset(ppu.oam, 0, 544);
ppu.ppu_cycles = 0; ppu.ppu_cycles = 0;
ppu.ppu_prev_cycles = 0; ppu.ppu_prev_cycles = 0;
ppu.display_disable = true; ppu.display_disable = true;
ppu.display_brightness = 15; ppu.display_brightness = 15;
ppu.visible_scanlines = 224;
ppu.toggle_visible_scanlines = 224;
ppu.interlace = false; //ppu.interlace/ppu.interlace_frame initialized in timing/timing.cpp
ppu.interlace_frame = 0; ppu.overscan = false;
ppu.hline_pos = 0; ppu.visible_scanlines = 224;
ppu.vline_pos = 261; ppu.sprite_halve = false;
ppu.irq_triggered = false; ppu.hline_pos = 0;
ppu.virq_triggered = false; ppu.vline_pos = 0;
ppu.hirq_triggered = false; ppu.irq_triggered = false;
ppu.vram_write_pos = 0; ppu.virq_triggered = false;
ppu.cgram_write_pos = 0; ppu.hirq_triggered = false;
ppu.wram_write_pos = 0; ppu.vram_write_pos = 0;
ppu.vram_inc_size = 2; ppu.vram_read_buffer = 0;
ppu.vram_inc_reg = 0; ppu.vram_write_buffer = 0;
ppu.oam_write_pos = 0; ppu.cgram_write_pos = 0;
ppu.oam_tiledata_loc = 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.bg_enabled[OAM] = false;
ppu.ss_bg_enabled[OAM] = false; ppu.ss_bg_enabled[OAM] = false;
@ -417,10 +349,7 @@ word *ptr;
ppu.div_b = 0; ppu.div_b = 0;
ppu.r_4214 = 0; ppu.r_4214 = 0;
ppu.r_4216 = 0; ppu.r_4216 = 0;
ppu.r_2134 = 0;
ppu.smul_a = 0;
ppu.smul_b = 0;
ppu.smul_r = 0;
ppu.window1_left = 0; ppu.window1_left = 0;
ppu.window1_right = 0; ppu.window1_right = 0;
@ -444,14 +373,14 @@ word *ptr;
ppu.color_g = 0; ppu.color_g = 0;
ppu.color_b = 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++) { for(i=0;i<8;i++) {
memset(&dma_channel[i], 0, sizeof(dmachannel)); memset(&dma_channel[i], 0, sizeof(dmachannel));
ppu.hdma_completed[i] = false; ppu.hdma_completed[i] = false;
ppu.hdma_scanlines_remaining[i] = 0; ppu.hdma_scanlines_remaining[i] = 0;
ppu.hdma_index_pointer[i] = 0; ppu.hdma_index_pointer[i] = 0;
} }
hdma_initialize();
ppu.vcounter_enabled = false; ppu.vcounter_enabled = false;
ppu.hcounter_enabled = false; ppu.hcounter_enabled = false;
@ -471,6 +400,13 @@ word *ptr;
ppu.m7hofs = ppu.m7vofs = 0x0000; ppu.m7hofs = ppu.m7vofs = 0x0000;
ppu.mode7_hflip = false; ppu.mode7_repeat = 0;
ppu.mode7_vflip = false; 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);
} }

View File

@ -13,6 +13,8 @@ struct {
byte blend_type; byte blend_type;
}ppu_pixel_cache[512]; }ppu_pixel_cache[512];
byte ppu_layer_cache[512 * 12];
#define TILE_2BIT 0 #define TILE_2BIT 0
#define TILE_4BIT 1 #define TILE_4BIT 1
#define TILE_8BIT 2 #define TILE_8BIT 2
@ -23,7 +25,7 @@ byte *ppu_bg_tiledata_state[3];
//this should be reset once every scanline //this should be reset once every scanline
void ppu_clear_pixel_cache(void) { void ppu_clear_pixel_cache(void) {
int i; int i;
for(i=0;i<512;i++) { for(i=0;i<render.snes_width;i++) {
ppu_pixel_cache[i].color_main = ppu_pixel_cache[i].color_main =
ppu_pixel_cache[i].color_sub = 0; ppu_pixel_cache[i].color_sub = 0;
ppu_pixel_cache[i].src_main = ppu_pixel_cache[i].src_main =
@ -32,14 +34,21 @@ int i;
} }
} }
//this should be reset once every scanline
void ppu_clear_layer_cache(void) {
memset(&ppu_layer_cache, 0, render.snes_width * 12);
}
void ppu_init_tiledata_cache(void) { void ppu_init_tiledata_cache(void) {
int i;
ppu_bg_tiledata[TILE_2BIT] = (byte*)malloc(262144); ppu_bg_tiledata[TILE_2BIT] = (byte*)malloc(262144);
ppu_bg_tiledata[TILE_4BIT] = (byte*)malloc(131072); ppu_bg_tiledata[TILE_4BIT] = (byte*)malloc(131072);
ppu_bg_tiledata[TILE_8BIT] = (byte*)malloc( 65536); ppu_bg_tiledata[TILE_8BIT] = (byte*)malloc( 65536);
ppu_bg_tiledata_state[TILE_2BIT] = (byte*)malloc( 4096); ppu_bg_tiledata_state[TILE_2BIT] = (byte*)malloc( 4096);
ppu_bg_tiledata_state[TILE_4BIT] = (byte*)malloc( 2048); ppu_bg_tiledata_state[TILE_4BIT] = (byte*)malloc( 2048);
ppu_bg_tiledata_state[TILE_8BIT] = (byte*)malloc( 1024); ppu_bg_tiledata_state[TILE_8BIT] = (byte*)malloc( 1024);
}
void ppu_clear_tiledata_cache(void) {
memset(ppu_bg_tiledata[TILE_2BIT], 0, 262144); memset(ppu_bg_tiledata[TILE_2BIT], 0, 262144);
memset(ppu_bg_tiledata[TILE_4BIT], 0, 131072); memset(ppu_bg_tiledata[TILE_4BIT], 0, 131072);
memset(ppu_bg_tiledata[TILE_4BIT], 0, 65536); memset(ppu_bg_tiledata[TILE_4BIT], 0, 65536);

View File

@ -11,17 +11,27 @@
#define HDMAMODE_CONTINUOUS 1 #define HDMAMODE_CONTINUOUS 1
typedef struct { typedef struct {
bool active;
byte transfer_mode; byte transfer_mode;
byte index_mode; bool indirect;
bool fixed_address; bool fixed_address;
byte write_dir; int write_dir;
byte transfer_type; byte transfer_type;
word dest_addr; byte dest_addr;
ulong src_addr; ulong src_addr;
word transfer_size; word transfer_size;
byte indirect_bank_address; byte indirect_bank;
byte hdma_mode; byte hdma_mode;
word hdma_indirect_pointer; word hdma_indirect_pointer;
//hdma specific
bool first_line;
bool repeat;
bool completed;
byte line_counter;
ulong address, iaddress;
word r43x8;
}dmachannel; }dmachannel;
dmachannel dma_channel[8]; dmachannel dma_channel[8];
@ -31,25 +41,19 @@ dmachannel dma_channel[8];
da-ifttt da-ifttt
d: (dma only) d: (dma only)
0=read from cpu mem, write to $21?? 0=read from cpu mem, write to $21xx
1=read from $21??, write to cpu mem 1=read from $21xx, write to cpu mem
a: (hdma only) a: (hdma only)
0=absolute addressing 0=absolute addressing
1=indirect addressing 1=indirect addressing
f: 1=fixed address, 0=inc/dec address
i: 0=increment address, 1=decrement address i: 0=increment address, 1=decrement address
f: 1=fixed address, 0=inc/dec address
t: transfer type t: transfer type
000: 1 reg 1 write (01->2118 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) { void mmio_w43x0(byte c, byte value) {
dma_channel[c].transfer_mode = (value & 0x80)?DMATRANSFER_MMIOTOCPU:DMATRANSFER_CPUTOMMIO; 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].indirect = (value & 0x40)?true:false;
dma_channel[c].write_dir = (value & 0x10)?DMAWRITE_DEC:DMAWRITE_INC; dma_channel[c].write_dir = (value & 0x10)?-1:1;
dma_channel[c].fixed_address = (value & 0x08)?true:false; dma_channel[c].fixed_address = (value & 0x08)?true:false;
dma_channel[c].transfer_type = (value & 0x07); 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 b: $2100 | b = destination register - limited to $21xx regs only
*/ */
void mmio_w43x1(byte c, byte value) { 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 $43x7 : HDMA indirect bank address
*/ */
void mmio_w43x7(byte c, byte value) { 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) { void dma_mmio_write(byte reg, byte value) {
byte x; mmio_write(0x2100 | reg, value);
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_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; byte x;
x = mmio_read(dma_channel[c].dest_addr + a); x = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dma_channel[c].src_addr);
gx816->mem_write(MEMMODE_LONG, MEMSIZE_BYTE, dma_channel[c].src_addr, x); dma_mmio_write(dma_channel[c].dest_addr + a, x);
if(dma_channel[c].fixed_address == false) { if(dma_channel[c].fixed_address == false) {
if(dma_channel[c].write_dir == DMAWRITE_INC)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);
if(dma_channel[c].write_dir == DMAWRITE_DEC)dma_channel[c].src_addr--;
} }
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) { void dma_transfer_type0(byte c) {
if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) { if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) {
while(1) { if(dma_cputommio(c, 0) == 0)return;
dma_cputommio(c, 0); if(dma_channel[c].transfer_size == 0)break;
}
} else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) { } else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) {
while(1) { if(dma_mmiotocpu(c, 0) == 0)return;
dma_mmiotocpu(c, 0); if(dma_channel[c].transfer_size == 0)break;
}
} }
} }
void dma_transfer_type1(byte c) { void dma_transfer_type1(byte c) {
if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) { if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) {
while(1) { if(dma_cputommio(c, 0) == 0)return;
dma_cputommio(c, 0); if(dma_channel[c].transfer_size == 0)break; if(dma_cputommio(c, 1) == 0)return;
dma_cputommio(c, 1); if(dma_channel[c].transfer_size == 0)break;
}
} else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) { } else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) {
while(1) { if(dma_mmiotocpu(c, 0) == 0)return;
dma_mmiotocpu(c, 0); if(dma_channel[c].transfer_size == 0)break; if(dma_mmiotocpu(c, 1) == 0)return;
dma_mmiotocpu(c, 1); if(dma_channel[c].transfer_size == 0)break;
}
} }
} }
void dma_transfer_type2(byte c) { void dma_transfer_type2(byte c) {
if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) { if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) {
while(1) { if(dma_cputommio(c, 0) == 0)return;
dma_cputommio(c, 0); if(dma_channel[c].transfer_size == 0)break;
}
} else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) { } else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) {
while(1) { if(dma_mmiotocpu(c, 0) == 0)return;
dma_mmiotocpu(c, 0); if(dma_channel[c].transfer_size == 0)break;
}
} }
} }
void dma_transfer_type3(byte c) { void dma_transfer_type3(byte c) {
if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) { if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) {
while(1) { if(dma_cputommio(c, 0) == 0)return;
dma_cputommio(c, 0); if(dma_channel[c].transfer_size == 0)break; if(dma_cputommio(c, 0) == 0)return;
dma_cputommio(c, 0); if(dma_channel[c].transfer_size == 0)break; if(dma_cputommio(c, 1) == 0)return;
dma_cputommio(c, 1); if(dma_channel[c].transfer_size == 0)break; if(dma_cputommio(c, 1) == 0)return;
dma_cputommio(c, 1); if(dma_channel[c].transfer_size == 0)break;
}
} else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) { } else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) {
while(1) { if(dma_mmiotocpu(c, 0) == 0)return;
dma_mmiotocpu(c, 0); if(dma_channel[c].transfer_size == 0)break; if(dma_mmiotocpu(c, 0) == 0)return;
dma_mmiotocpu(c, 0); if(dma_channel[c].transfer_size == 0)break; if(dma_mmiotocpu(c, 1) == 0)return;
dma_mmiotocpu(c, 1); if(dma_channel[c].transfer_size == 0)break; if(dma_mmiotocpu(c, 1) == 0)return;
dma_mmiotocpu(c, 1); if(dma_channel[c].transfer_size == 0)break;
}
} }
} }
void dma_transfer_type4(byte c) { void dma_transfer_type4(byte c) {
if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) { if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) {
while(1) { if(dma_cputommio(c, 0) == 0)return;
dma_cputommio(c, 0); if(dma_channel[c].transfer_size == 0)break; if(dma_cputommio(c, 1) == 0)return;
dma_cputommio(c, 1); if(dma_channel[c].transfer_size == 0)break; if(dma_cputommio(c, 2) == 0)return;
dma_cputommio(c, 2); if(dma_channel[c].transfer_size == 0)break; if(dma_cputommio(c, 3) == 0)return;
dma_cputommio(c, 3); if(dma_channel[c].transfer_size == 0)break;
}
} else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) { } else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) {
while(1) { if(dma_mmiotocpu(c, 0) == 0)return;
dma_mmiotocpu(c, 0); if(dma_channel[c].transfer_size == 0)break; if(dma_mmiotocpu(c, 1) == 0)return;
dma_mmiotocpu(c, 1); if(dma_channel[c].transfer_size == 0)break; if(dma_mmiotocpu(c, 2) == 0)return;
dma_mmiotocpu(c, 2); if(dma_channel[c].transfer_size == 0)break; if(dma_mmiotocpu(c, 3) == 0)return;
dma_mmiotocpu(c, 3); if(dma_channel[c].transfer_size == 0)break;
}
} }
} }
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 $420b : DMA enable
$420c : HDMA enable $420c : HDMA enable
each bit corresponds to the respecting DMA channel (7,6,5,4,3,2,1,0) 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 Setting a bit in this register will perform the DMA transfer. Multiple
transfers can be done at once. requires one cycle per byte transferred transfers can be done at once. Requires one cycle per byte transferred.
hdma bits are sticky (they are not cleared automatically after write)
*/ */
void mmio_w420b(byte value) { void mmio_w420b(byte value) {
int i; int i;
ppu.active_hdma_channels &= ~value;
for(i=0;i<8;i++) { for(i=0;i<8;i++) {
if(value & (1 << i)) { if(value & (1 << i)) {
snes_time->add_cpu_cycles(dma_channel[i].transfer_size * 6); dma_channel[i].active = true;
if (dma_channel[i].transfer_type == 0)dma_transfer_type0(i); gx816->cpu_state = CPUSTATE_DMA;
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);
} }
} }
} }
void mmio_w420c(byte value) { void mmio_w420c(byte value) {
//don't actually enable hdma channels until the start of the next frame ppu.active_hdma_channels = value;
ppu.toggle_active_hdma_channels = value;
} }
byte hdma_read_absolute(byte c) { byte hdma_transfer_lentbl[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
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_read_indirect(byte c) { void hdma_write_byte(byte i, byte l, byte x) {
ulong x; switch(dma_channel[i].transfer_type) {
x = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dma_channel[c].src_addr + ppu.hdma_index_pointer[c]); case 0:
x += dma_channel[c].hdma_indirect_pointer; dma_mmio_write(dma_channel[i].dest_addr, x);
x = (dma_channel[c].indirect_bank_address << 16) | (x & 0xffff); break;
x = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, x); case 1:
dma_channel[c].hdma_indirect_pointer++; dma_mmio_write(dma_channel[i].dest_addr + l, x);
return x; break;
} case 2:
dma_mmio_write(dma_channel[i].dest_addr, x);
void hdma_transfer_type0_absolute(byte c) { break;
mmio_write(dma_channel[c].dest_addr, hdma_read_absolute(c)); case 3:
} dma_mmio_write(dma_channel[i].dest_addr + (l >> 1), x);
break;
void hdma_transfer_type0_indirect(byte c) { case 4:
mmio_write(dma_channel[c].dest_addr, hdma_read_indirect(c)); dma_mmio_write(dma_channel[i].dest_addr + l, x);
if(dma_channel[c].hdma_mode == HDMAMODE_NORMAL)dma_channel[c].hdma_indirect_pointer -= 1; break;
} case 5:
dma_mmio_write(dma_channel[i].dest_addr + (l & 1), x);
void hdma_transfer_type1_absolute(byte c) { break;
mmio_write(dma_channel[c].dest_addr, hdma_read_absolute(c)); case 6:
mmio_write(dma_channel[c].dest_addr + 1, hdma_read_absolute(c)); dma_mmio_write(dma_channel[i].dest_addr, x);
} break;
case 7:
void hdma_transfer_type1_indirect(byte c) { dma_mmio_write(dma_channel[i].dest_addr + (l >> 1), x);
mmio_write(dma_channel[c].dest_addr, hdma_read_indirect(c)); break;
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 UpdateHDMAAbsoluteNormal(byte c) { void hdma_update(void) {
if(ppu.hdma_scanlines_remaining[c] == 0x00) { int i, l;
ppu.hdma_scanlines_remaining[c] = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dma_channel[c].src_addr + ppu.hdma_index_pointer[c]); 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) { if(dma_channel[i].line_counter > 0x80) {
ppu.hdma_completed[c] = true; dma_channel[i].repeat = true;
return; dma_channel[i].line_counter -= 0x80;
}
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]--;
} else { } else {
if(ppu.hdma_completed[c] == true)continue; dma_channel[i].repeat = false;
}
if(dma_channel[c].index_mode == DMAINDEX_ABSOLUTE) { dma_channel[i].first_line = true;
if(dma_channel[c].hdma_mode == HDMAMODE_NORMAL) { if(dma_channel[i].indirect == false) {
UpdateHDMAAbsoluteNormal(c); dma_channel[i].iaddress = dma_channel[i].address;
} else { } else {
UpdateHDMAAbsoluteContinuous(c); 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);
} else { //indirect dma_channel[i].address += 2;
if(dma_channel[c].hdma_mode == HDMAMODE_NORMAL) { snes_time->add_cpu_cycles(1, 16);
UpdateHDMAIndirectNormal(c);
} else {
UpdateHDMAIndirectContinuous(c);
}
}
} }
} }
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;l<hdma_transfer_lentbl[dma_channel[i].transfer_type];l++) {
x = gx816->mem_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;
}

View File

@ -11,64 +11,49 @@
x: horizontal screen flip x: horizontal screen flip
*/ */
void mmio_w211a(byte value) { void mmio_w211a(byte value) {
ppu.mode7_vflip = (value & 0x02)?true:false; ppu.mode7_repeat = (value >> 6) & 3;
ppu.mode7_hflip = (value & 0x01)?true:false; 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 $211b : m7a / 16-bit source operand for signed multiplication
*/ */
void mmio_w211b(byte value) { void mmio_w211b(byte value) {
static byte latch = 0; ppu.m7a = (value << 8) | (ppu.m7a >> 8);
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;
} }
/* /*
$211c : m7b / 8-bit source operand for signed multiplication $211c : m7b / 8-bit source operand for signed multiplication
*/ */
void mmio_w211c(byte value) { void mmio_w211c(byte value) {
ppu.m7b = (value << 8) | m7_latch; ppu.m7b = (value << 8) | (ppu.m7b >> 8);
m7_latch = value;
ppu.smul_b = value;
} }
/* /*
$211d : m7c $211d : m7c
*/ */
void mmio_w211d(byte value) { void mmio_w211d(byte value) {
ppu.m7c = (value << 8) | m7_latch; ppu.m7c = (value << 8) | (ppu.m7c >> 8);
m7_latch = value;
} }
/* /*
$211e : m7d $211e : m7d
*/ */
void mmio_w211e(byte value) { void mmio_w211e(byte value) {
ppu.m7d = (value << 8) | m7_latch; ppu.m7d = (value << 8) | (ppu.m7d >> 8);
m7_latch = value;
} }
/* /*
$211f : m7x $211f : m7x
*/ */
void mmio_w211f(byte value) { void mmio_w211f(byte value) {
ppu.m7x = (value << 8) | m7_latch; ppu.m7x = (value << 8) | (ppu.m7x >> 8);
m7_latch = value;
} }
/* /*
$2120 : m7y $2120 : m7y
*/ */
void mmio_w2120(byte value) { void mmio_w2120(byte value) {
ppu.m7y = (value << 8) | m7_latch; ppu.m7y = (value << 8) | (ppu.m7y >> 8);
m7_latch = value;
} }

View File

@ -1,19 +1,16 @@
byte mmio_r2134(void) { byte mmio_r2134(void) {
ulong r; ulong r = ((signed short)ppu.m7a * (signed char)(ppu.m7b >> 8));
r = (signed short)ppu.smul_a * (signed char)ppu.smul_b; return (r);
return r & 0xff;
} }
byte mmio_r2135(void) { byte mmio_r2135(void) {
ulong r; ulong r = ((signed short)ppu.m7a * (signed char)(ppu.m7b >> 8));
r = (signed short)ppu.smul_a * (signed char)ppu.smul_b; return (r >> 8);
return (r >> 8) & 0xff;
} }
byte mmio_r2136(void) { byte mmio_r2136(void) {
ulong r; ulong r = ((signed short)ppu.m7a * (signed char)(ppu.m7b >> 8));
r = (signed short)ppu.smul_a * (signed char)ppu.smul_b; return (r >> 16);
return (r >> 16) & 0xff;
} }
void mmio_w4202(byte value) { void mmio_w4202(byte value) {

View File

@ -5,7 +5,6 @@
multiply value by 2 to get actual offset into ppu.cgram multiply value by 2 to get actual offset into ppu.cgram
*/ */
void mmio_w2121(byte value) { void mmio_w2121(byte value) {
//if(ppu.vline_pos < 224 && ppu.display_disable == false)return;
ppu.cgram_write_pos = value << 1; 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 writes to cgram using cgram_write_pos * 2 as an index
*/ */
void mmio_w2122(byte val) { void mmio_w2122(byte value) {
//if(ppu.vline_pos < 224 && ppu.display_disable == false)return; ppu.cgram[ppu.cgram_write_pos] = value;
ppu.cgram[ppu.cgram_write_pos] = val;
debug_test_bp(BPSRC_CGRAM, BP_WRITE, ppu.cgram_write_pos, value);
ppu.cgram_write_pos++; ppu.cgram_write_pos++;
ppu.cgram_write_pos &= 0x01ff; ppu.cgram_write_pos &= 0x01ff;
} }
@ -28,8 +29,10 @@ void mmio_w2122(byte val) {
*/ */
byte mmio_r213b(void) { byte mmio_r213b(void) {
byte r; byte r;
//if(ppu.vline_pos < 224 && ppu.display_disable == false)return;
r = ppu.cgram[ppu.cgram_write_pos]; 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++;
ppu.cgram_write_pos &= 0x01ff; ppu.cgram_write_pos &= 0x01ff;
return r; return r;

View File

@ -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, 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, 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 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) \ #define ppu_pal_pixel(__i) \
(*((word*)ppu.cgram + __i)) (*((word*)ppu.cgram + __i))
word ppu_addsub_pixels(byte x, byte cdest_index, byte cdest_bg, byte csrc_index, byte csrc_bg) { word ppu_addsub_pixels(byte x, byte cdest_index, byte cdest_bg, byte csrc_index, byte csrc_bg) {
int r, g, b; int r, g, b;
byte hd = 0, hs = 0;
word cdest = ppu_pal_pixel(cdest_index); word cdest = ppu_pal_pixel(cdest_index);
word csrc = ppu_pal_pixel(csrc_index); word csrc = ppu_pal_pixel(csrc_index);
word res;
//oam palettes 0-3 are not affected by color add/sub //oam palettes 0-3 are not affected by color add/sub
if(cdest_bg == OAM) { if(cdest_bg == OAM) {
if(cdest_index < 192) { if(cdest_index < 192) {
return cdest; return cdest;
} }
} }
if(ppu.bg_color_enabled[cdest_bg] == true) {
hd = hs = ppu.color_halve;
}
switch(ppu.color_mode) { switch(ppu.color_mode) {
case COLORMODE_ADD: case COLORMODE_ADD:
r = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest ) & 31) >> hd) + ( ((csrc ) & 31) >> hs) )); if(ppu.bg_color_enabled[cdest_bg] == true && ppu.color_halve == 1) {
g = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest >> 5) & 31) >> hd) + ( ((csrc >> 5) & 31) >> hs) )); r = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1;
b = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest >> 10) & 31) >> hd) + ( ((csrc >> 10) & 31) >> hs) )); 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; break;
case COLORMODE_SUB: case COLORMODE_SUB:
r = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest ) & 31) >> hd) - ( ((csrc ) & 31) >> hs) )); if(ppu.bg_color_enabled[cdest_bg] == true && ppu.color_halve == 1) {
g = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest >> 5) & 31) >> hd) - ( ((csrc >> 5) & 31) >> hs) )); r = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1;
b = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest >> 10) & 31) >> hd) - ( ((csrc >> 10) & 31) >> hs) )); 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; break;
} }
return ((r) | (g << 5) | (b << 10)); 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) { word ppu_addsub_pixel(byte x, byte cdest_index, byte cdest_bg) {
int r, g, b; int r, g, b;
byte hd = 0;
word cdest = ppu_pal_pixel(cdest_index); 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 //only oam palettes 4-7 are affected by color add/sub
if(cdest_bg == OAM) { if(cdest_bg == OAM) {
if(cdest_index < 192) { if(cdest_index < 192) {
return cdest; return cdest;
} }
} }
if(ppu.bg_color_enabled[cdest_bg] == true) {
hd = ppu.color_halve;
}
switch(ppu.color_mode) { switch(ppu.color_mode) {
case COLORMODE_ADD: case COLORMODE_ADD:
r = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest ) & 31) >> hd) + (ppu.color_r >> hd) )); if(ppu.bg_color_enabled[cdest_bg] == true && ppu.color_halve == 1 && ppu.addsub_mode == 0) {
g = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest >> 5) & 31) >> hd) + (ppu.color_g >> hd) )); r = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1;
b = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest >> 10) & 31) >> hd) + (ppu.color_b >> hd) )); 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; break;
case COLORMODE_SUB: case COLORMODE_SUB:
r = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest ) & 31) >> hd) - (ppu.color_r >> hd) )); if(ppu.bg_color_enabled[cdest_bg] == true && ppu.color_halve == 1 && ppu.addsub_mode == 0) {
g = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest >> 5) & 31) >> hd) - (ppu.color_g >> hd) )); r = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1;
b = *(ppu_addsub_adjust_buffer + 32 + (( ((cdest >> 10) & 31) >> hd) - (ppu.color_b >> hd) )); 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; break;
} }
return ((r) | (g << 5) | (b << 10)); return ((r) | (g << 5) | (b << 10));
@ -165,43 +190,42 @@ byte *dest;
#define PPU_MAIN 0 #define PPU_MAIN 0
#define PPU_SUB 1 #define PPU_SUB 1
bool windows_not_obstructing(byte layer, byte bg, byte x); bool windows_not_obstructing(byte layer, byte bg, word x);
bool color_windows_not_obstructing(byte x, byte color_mask_type); bool color_windows_not_obstructing(word 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)
void ppu_render_line_to_screen(void) { void ppu_render_line_to_screen(void) {
int x; int x, x1;
word *ptr, *light_table; word *ptr, *ptri, *light_table, *light_tablei;
word c, cx, cy; word c, cx, cy;
word screen_width = render.snes_width; word screen_width = render.snes_width;
ptr = (word*)ppu.screen;
light_table = (word*)ppu.light_table + (ppu.display_brightness * 65536); if(ppu.interlace == false) {
if(ppu.interlace == true) { ptr = (word*)ppu.screen + ((ppu.vline_pos << 1) ) * 512;
ptr += ((ppu.vline_pos * 2) + ppu.interlace_frame) * 512; ptri = (word*)ppu.screen + ((ppu.vline_pos << 1) + 1) * 512;
} else { } else {
ptr += ppu.vline_pos * 512; ptr = (word*)ppu.screen + ((ppu.vline_pos << 1) + ppu.interlace_frame) * 512;
} }
for(x=0;x<screen_width;x++) { light_table = (word*)ppu.light_table + (ppu.display_brightness * 65536);
for(x=x1=0;x<screen_width;x++) {
switch(ppu_pixel_cache[x].blend_type) { switch(ppu_pixel_cache[x].blend_type) {
case BLENDTYPE_BACK: case BLENDTYPE_BACK:
if(ppu.bg_color_enabled[BACK] == true && color_windows_not_obstructing(x, PPU_SUB) == false) { if(color_windows_not_obstructing(x, PPU_MAIN) == true) {
cx = 0x0000;
} else if(ppu.bg_color_enabled[BACK] == true && color_windows_not_obstructing(x, PPU_SUB) == false) {
cx = ppu_addsub_pixel(x, 0, BACK); cx = ppu_addsub_pixel(x, 0, BACK);
} else { } else {
cx = ppu_pal_pixel(0); cx = ppu_pal_pixel(0);
} }
ppu_write_pixel();
break; break;
case BLENDTYPE_MAIN: case BLENDTYPE_MAIN:
if(ppu.bg_color_enabled[ppu_pixel_cache[x].src_main] == true && color_windows_not_obstructing(x, PPU_SUB) == false) { if(ppu.bg_color_enabled[ppu_pixel_cache[x].src_main] == true && color_windows_not_obstructing(x, PPU_MAIN) == true) {
cx = 0x0000;
} else if(ppu.bg_color_enabled[ppu_pixel_cache[x].src_main] == true && color_windows_not_obstructing(x, PPU_SUB) == false) {
cx = ppu_addsub_pixel(x, ppu_pixel_cache[x].color_main, ppu_pixel_cache[x].src_main); cx = ppu_addsub_pixel(x, ppu_pixel_cache[x].color_main, ppu_pixel_cache[x].src_main);
} else { } else {
cx = ppu_pal_pixel(ppu_pixel_cache[x].color_main); cx = ppu_pal_pixel(ppu_pixel_cache[x].color_main);
} }
ppu_write_pixel();
break; break;
case BLENDTYPE_SUB: case BLENDTYPE_SUB:
if(ppu.bg_color_enabled[BACK] && color_windows_not_obstructing(x, PPU_SUB) == false) { if(ppu.bg_color_enabled[BACK] && color_windows_not_obstructing(x, PPU_SUB) == false) {
@ -209,7 +233,6 @@ word screen_width = render.snes_width;
} else { } else {
cx = ppu_pal_pixel(ppu_pixel_cache[x].color_sub); cx = ppu_pal_pixel(ppu_pixel_cache[x].color_sub);
} }
ppu_write_pixel();
break; break;
case BLENDTYPE_COMBINE: case BLENDTYPE_COMBINE:
if(color_windows_not_obstructing(x, PPU_SUB) == false) { if(color_windows_not_obstructing(x, PPU_SUB) == false) {
@ -222,9 +245,20 @@ word screen_width = render.snes_width;
} else { } else {
cx = ppu_pal_pixel(ppu_pixel_cache[x].color_main); cx = ppu_pal_pixel(ppu_pixel_cache[x].color_main);
} }
ppu_write_pixel();
break; break;
} }
if(ppu.interlace == false) {
*(ptr + (x1 )) = *(light_table + cx);
*(ptri + (x1++)) = *(light_table + cx);
if(screen_width != 256)continue;
*(ptr + (x1 )) = *(light_table + cx);
*(ptri + (x1++)) = *(light_table + cx);
} else {
*(ptr + (x1++)) = *(light_table + cx);
if(screen_width != 256)continue;
*(ptr + (x1++)) = *(light_table + cx);
}
} }
} }
@ -268,6 +302,25 @@ void ppu_set_pixel(byte bg, word x, byte pal_index) {
} }
} }
void ppu_set_layer_pixels(byte layer_count, byte *layer_bg_lookup) {
int layer, x = 0, x1;
byte pal;
do {
layer = 0;
x1 = x * 12;
do {
pal = ppu_layer_cache[x1 + layer];
if(pal) {
ppu_set_pixel(layer_bg_lookup[layer], x, pal);
}
layer++;
} while(layer < layer_count);
x++;
} while(x < render.snes_width);
}
#define ppu_set_layer_pixel(__x, __c) ppu_layer_cache[(__x) * 12 + layer_pos] = __c
struct { struct {
byte num; byte num;
byte width, height; byte width, height;
@ -282,21 +335,20 @@ void ppu_set_sprite_attributes(byte sprite_num) {
ulong t; ulong t;
byte size, b; byte size, b;
word x; word x;
t = ppu.oam[(sprite_num << 2) ] | t = *((ulong*)ppu.oam + sprite_num);
ppu.oam[(sprite_num << 2) + 1] << 8 |
ppu.oam[(sprite_num << 2) + 2] << 16 |
ppu.oam[(sprite_num << 2) + 3] << 24;
b = ppu.oam[512 + (sprite_num >> 2)]; b = ppu.oam[512 + (sprite_num >> 2)];
if ((sprite_num & 3) == 0) { size = (b & 0x02)?1:0; x = (b & 0x01)?0x100:0; } switch(sprite_num & 3) {
else if((sprite_num & 3) == 1) { size = (b & 0x08)?1:0; x = (b & 0x04)?0x100:0; } case 0: size = (b & 0x02)?1:0; x = (b & 0x01)?0x100:0; break;
else if((sprite_num & 3) == 2) { size = (b & 0x20)?1:0; x = (b & 0x10)?0x100:0; } case 1: size = (b & 0x08)?1:0; x = (b & 0x04)?0x100:0; break;
else if((sprite_num & 3) == 3) { size = (b & 0x80)?1:0; x = (b & 0x40)?0x100:0; } 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.num = sprite_num;
current_sprite.priority = (t >> 28) & 3; current_sprite.priority = (t >> 28) & 3;
current_sprite.x = x | (t & 0xff); 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.v_flip = (t & 0x80000000)?1:0;
current_sprite.h_flip = (t & 0x40000000)?1:0; current_sprite.h_flip = (t & 0x40000000)?1:0;
current_sprite.palette = (t >> 25) & 7; 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 byte w1_mask, w2_mask; //1 = masked, 0 = not masked
word window1_left, window1_right, window2_left, window2_right;
if(layer == PPU_MAIN) { if(layer == PPU_MAIN) {
if(ppu.bg_windowing_enabled[bg] == false)return true; if(ppu.bg_windowing_enabled[bg] == false)return true;
} else if(layer == PPU_SUB) { } else if(layer == PPU_SUB) {
if(ppu.ss_bg_windowing_enabled[bg] == false)return true; 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_enabled[bg] == true && ppu.bg_window2_enabled[bg] == false) {
if(ppu.bg_window1_clipmode[bg] == CLIPMODE_IN) { 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; return true;
} else { } else {
if(x <= ppu.window1_left || x >= ppu.window1_right)return false; if(x < window1_left || x > window1_right)return false;
return true; return true;
} }
} else if(ppu.bg_window2_enabled[bg] == true && ppu.bg_window1_enabled[bg] == false) { } else if(ppu.bg_window2_enabled[bg] == true && ppu.bg_window1_enabled[bg] == false) {
if(ppu.bg_window2_clipmode[bg] == CLIPMODE_IN) { 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; return true;
} else { } else {
if(x <= ppu.window2_left || x >= ppu.window2_right)return false; if(x < window2_left || x > window2_right)return false;
return true; return true;
} }
} else if(ppu.bg_window1_enabled[bg] == true && ppu.bg_window2_enabled[bg] == true) { } else if(ppu.bg_window1_enabled[bg] == true && ppu.bg_window2_enabled[bg] == true) {
if(ppu.bg_window1_clipmode[bg] == CLIPMODE_IN) { 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 w1_mask = 0;
} else { } 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; else w1_mask = 0;
} }
if(ppu.bg_window2_clipmode[bg] == CLIPMODE_IN) { 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 w2_mask = 0;
} else { } 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; else w2_mask = 0;
} }
@ -398,67 +463,80 @@ byte w1_mask, w2_mask; //1 = masked, 0 = not masked
return true; 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 w1_mask, w2_mask; //1 = masked, 0 = not masked
byte color_mask; byte color_mask;
bool r; bool r;
word window1_left, window1_right, window2_left, window2_right;
if(color_mask_type == PPU_MAIN)color_mask = ppu.color_mask; if(color_mask_type == PPU_MAIN)color_mask = ppu.color_mask;
else color_mask = ppu.ss_color_mask; else color_mask = ppu.ss_color_mask;
if(color_mask == 0)return false; if(color_mask == 0)return false;
if(color_mask == 3)return true; 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) { if(ppu.color_window1_enabled == false && ppu.color_window2_enabled == false) {
r = true; r = true;
} else if(ppu.color_window1_enabled == true && ppu.color_window2_enabled == false) { } else if(ppu.color_window1_enabled == true && ppu.color_window2_enabled == false) {
if(ppu.color_window1_clipmode == CLIPMODE_IN) { if(ppu.color_window1_clipmode == CLIPMODE_IN) {
if(x >= ppu.window1_left && x <= ppu.window1_right)r = false; if(x >= window1_left && x <= window1_right)r = false;
else r = true; else r = true;
} else { } else {
if(x <= ppu.window1_left || x >= ppu.window1_right)r = false; if(x < window1_left || x > window1_right)r = false;
else r = true; else r = true;
} }
} else if(ppu.color_window1_enabled == false && ppu.color_window2_enabled == true) { } else if(ppu.color_window1_enabled == false && ppu.color_window2_enabled == true) {
if(ppu.color_window2_clipmode == CLIPMODE_IN) { if(ppu.color_window2_clipmode == CLIPMODE_IN) {
if(x >= ppu.window2_left && x <= ppu.window2_right)r = false; if(x >= window2_left && x <= window2_right)r = false;
else r = true; else r = true;
} else { } else {
if(x <= ppu.window2_left || x >= ppu.window2_right)r = false; if(x < window2_left || x > window2_right)r = false;
else r = true; else r = true;
} }
} else if(ppu.color_window1_enabled == true && ppu.color_window2_enabled == true) { } else if(ppu.color_window1_enabled == true && ppu.color_window2_enabled == true) {
if(ppu.color_window1_clipmode == CLIPMODE_IN) { 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 w1_mask = 0;
} else { } 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; else w1_mask = 0;
} }
if(ppu.color_window2_clipmode == CLIPMODE_IN) { 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 w2_mask = 0;
} else { } 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; else w2_mask = 0;
} }
switch(ppu.color_window_mask) { switch(ppu.color_window_mask) {
case WINDOWMASK_OR: case WINDOWMASK_OR:
if((w1_mask | w2_mask) == 1)r = false; if((w1_mask | w2_mask) == 1)r = false;
else r = true; else r = true;
break; break;
case WINDOWMASK_AND: case WINDOWMASK_AND:
if((w1_mask & w2_mask) == 1)r = false; if((w1_mask & w2_mask) == 1)r = false;
else r = true; else r = true;
break; break;
case WINDOWMASK_XOR: case WINDOWMASK_XOR:
if((w1_mask ^ w2_mask) == 1)r = false; if((w1_mask ^ w2_mask) == 1)r = false;
else r = true; else r = true;
break; break;
case WINDOWMASK_XNOR: case WINDOWMASK_XNOR:
if((w1_mask ^ w2_mask) == 0)r = false; if((w1_mask ^ w2_mask) == 0)r = false;
else r = true; else r = true;
break; break;
} }
} }
@ -480,21 +558,8 @@ bool r;
correct y tile, y / 8 * 1 row (16 tiles) must be used. correct y tile, y / 8 * 1 row (16 tiles) must be used.
*/ */
#define ppu_render_oam_tile_line(__m) \ #define OAM_PRI_NONE 4
x &= 511; \ byte ppu_oam_line_pal[512], ppu_oam_line_pri[512];
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++
void ppu_render_oam_sprite(void) { void ppu_render_oam_sprite(void) {
word pos, col, chr, tiledata_inc; 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 tile_width = current_sprite.width >> SH_8; //e.x. 16x16 sprite = 2x2 tiles
y = ppu.vline_pos; if(ppu.interlace == true && (ppu.bg_mode == 5 || ppu.bg_mode == 6)) {
x = current_sprite.x; y = (ppu.vline_pos << SH_2) + ppu.interlace_frame;
if(current_sprite.v_flip) {
y = (current_sprite.height - 1) - (ppu.vline_pos - current_sprite.y);
} else { } 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; y &= 255;
if(ppu.sprite_halve == true) {
y <<= 1;
y += ppu.interlace_frame;
}
chr = current_sprite.character; chr = current_sprite.character;
tiledata_inc = (chr & 0x100)?(ppu.oam_name_sel << 13):0; //*1 tiledata_inc = (chr & 0x100)?(ppu.oam_name_sel << 13):0; //*1
@ -526,43 +604,78 @@ int tile_width;
d1 = ppu.vram[pos + 1]; d1 = ppu.vram[pos + 1];
d2 = ppu.vram[pos + 16]; d2 = ppu.vram[pos + 16];
d3 = ppu.vram[pos + 17]; d3 = ppu.vram[pos + 17];
if(current_sprite.h_flip) { for(z=0;z<8;z++) {
ppu_render_oam_tile_line(0x01); if(current_sprite.h_flip) {
ppu_render_oam_tile_line(0x02); mask = 0x01 << z;
ppu_render_oam_tile_line(0x04); } else {
ppu_render_oam_tile_line(0x08); mask = 0x80 >> z;
ppu_render_oam_tile_line(0x10); }
ppu_render_oam_tile_line(0x20); x &= 511;
ppu_render_oam_tile_line(0x40); if(x < render.snes_width) {
ppu_render_oam_tile_line(0x80); col = 0;
} else { if(d0 & mask)col += 1;
ppu_render_oam_tile_line(0x80); if(d1 & mask)col += 2;
ppu_render_oam_tile_line(0x40); if(d2 & mask)col += 4;
ppu_render_oam_tile_line(0x20); if(d3 & mask)col += 8;
ppu_render_oam_tile_line(0x10); if(col) {
ppu_render_oam_tile_line(0x08); col += pal_index;
ppu_render_oam_tile_line(0x04); col += 128;
ppu_render_oam_tile_line(0x02); if(ppu_oam_line_pri[x] == OAM_PRI_NONE) {
ppu_render_oam_tile_line(0x01); 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; if(ppu.bg_enabled[OAM] != true && ppu.ss_bg_enabled[OAM] != true)return;
s = 128; memset(ppu_oam_line_pri, OAM_PRI_NONE, 512);
while(s--) { for(s=0;s<128;s++) {
ppu_set_sprite_attributes(s); ppu_set_sprite_attributes(s);
if(current_sprite.priority == priority) { if(ppu.sprite_halve == false) {
//if the sprite is within screen boundaries... render the current line from the sprite
if(ppu.vline_pos >= current_sprite.y && ppu.vline_pos < (current_sprite.y + current_sprite.height)) { if(ppu.vline_pos >= current_sprite.y && ppu.vline_pos < (current_sprite.y + current_sprite.height)) {
ppu_render_oam_sprite(); 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)) { } else if((current_sprite.y + current_sprite.height) >= 256 && ppu.vline_pos < ((current_sprite.y + current_sprite.height) & 255)) {
ppu_render_oam_sprite(); 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<render.snes_width;i++) {
if(ppu_oam_line_pri[i] != OAM_PRI_NONE) {
switch(ppu_oam_line_pri[i]) {
case 0:layer_pos = layer_pos_pri0;break;
case 1:layer_pos = layer_pos_pri1;break;
case 2:layer_pos = layer_pos_pri2;break;
case 3:layer_pos = layer_pos_pri3;break;
}
ppu_set_layer_pixel(i, ppu_oam_line_pal[i]);
} }
} }
} }
@ -584,7 +697,7 @@ int s;
(((x tile #) mapped to tilemap boundary) * 2 (# of bytes per tilemap entry)); (((x tile #) mapped to tilemap boundary) * 2 (# of bytes per tilemap entry));
*/ */
void ppu_render_line_bg(byte color_depth, byte bg, byte priority) { void ppu_render_line_bg(byte layer_pos_pri0, byte layer_pos_pri1, byte color_depth, byte bg) {
int x, y, z, x1, y1; int x, y, z, x1, y1;
int mirror_x, mirror_y, p; int mirror_x, mirror_y, p;
int screen_x, screen_y; int screen_x, screen_y;
@ -592,14 +705,20 @@ int bg_x, bg_y;
int xpos, ypos, mosaic_x, mosaic_y; int xpos, ypos, mosaic_x, mosaic_y;
word t, base_xpos, base_pos, pos, ppos = 0; word t, base_xpos, base_pos, pos, ppos = 0;
word col; word col;
byte *src, *bg_tiledata, *bg_tiledata_state; byte *src, *bg_tiledata, *bg_tiledata_state, *tile_ptr;
byte tiledata_size; byte tiledata_size;
byte tile_size, tile_width, tile_height; byte tile_size, tile_width, tile_height, tile_x;
byte mask, pal_index, pal_size; byte mask, pal_index, pal_size;
word tile_num, screen_width, screen_height, screen_width_mask, screen_height_mask, map_index; word tile_num, screen_width, screen_height, screen_width_mask, screen_height_mask, map_index;
word *mosaic_table; word *mosaic_table;
byte layer_pos;
word opt_valid_bit, voffset, hoffset, vscroll, hscroll;
if(ppu.bg_enabled[bg] == false && ppu.ss_bg_enabled[bg] == false)return; if(ppu.bg_enabled[bg] == false && ppu.ss_bg_enabled[bg] == false)return;
if (bg == BG1)opt_valid_bit = 0x2000;
else if(bg == BG2)opt_valid_bit = 0x4000;
else opt_valid_bit = 0x0000;
switch(color_depth) { switch(color_depth) {
case COLORDEPTH_4: case COLORDEPTH_4:
pal_size = 4; pal_size = 4;
@ -629,7 +748,7 @@ word *mosaic_table;
screen_y = ppu.vline_pos; screen_y = ppu.vline_pos;
} }
//Not sure why, but modes 5 and 6 seem to force 16-width tiles. //Modes 5 and 6 seem to force 16-width tiles due to having twice the resolution.
//The tile size attribute in $2105 has no effect on tile width. //The tile size attribute in $2105 has no effect on tile width.
if(ppu.bg_mode == 5 || ppu.bg_mode == 6) { if(ppu.bg_mode == 5 || ppu.bg_mode == 6) {
tile_width = SH_16; tile_width = SH_16;
@ -647,37 +766,80 @@ word *mosaic_table;
screen_height_mask = screen_height - 1; screen_height_mask = screen_height - 1;
if(render.snes_width == 512) { if(render.snes_width == 512) {
bg_x = (ppu.bg_hscroll_pos[bg] << SH_2) & screen_width_mask; hscroll = (ppu.bg_hscroll_pos[bg] << SH_2) & screen_width_mask;
} else { } else {
bg_x = ppu.bg_hscroll_pos[bg] & screen_width_mask; hscroll = ppu.bg_hscroll_pos[bg] & screen_width_mask;
}
if(render.snes_height == 448) {
bg_y = (screen_y + ((ppu.bg_vscroll_pos[bg] << SH_2) & screen_height_mask)) & screen_height_mask;
} else {
bg_y = (screen_y + (ppu.bg_vscroll_pos[bg] & screen_height_mask)) & screen_height_mask;
} }
bg_x = hscroll;
mosaic_table = (word*)ppu.mosaic_table[ppu.mosaic_size]; if(render.snes_height == 448) {
mosaic_y = mosaic_table[bg_y]; vscroll = (ppu.bg_vscroll_pos[bg] << SH_2) & screen_height_mask;
} else {
vscroll = ppu.bg_vscroll_pos[bg] & screen_height_mask;
}
bg_y = (screen_y + vscroll) & screen_height_mask;
if(ppu.mosaic_enabled[bg] == true) {
mosaic_table = (word*)ppu.mosaic_table[ppu.mosaic_size];
} else {
mosaic_table = (word*)ppu.mosaic_table[0];
}
mosaic_x = mosaic_table[bg_x];
mosaic_y = mosaic_table[bg_y];
for(screen_x=0;screen_x<render.snes_width;screen_x++) { for(screen_x=0;screen_x<render.snes_width;screen_x++) {
switch(ppu.bg_tilemap_size[bg]) { if(ppu.bg_mode == 2 || ppu.bg_mode == 4 || ppu.bg_mode == 6) {
case 0: if(ppu.bg_mode == 6) {
map_index = 0; tile_x = (mosaic_table[screen_x + (hscroll & 15)] >> SH_16);
break; } else {
case 1: tile_x = (mosaic_table[screen_x + (hscroll & 7)] >> SH_8);
map_index = ((bg_x >> tile_size) > 31)?32*32*2:0; }
break; hoffset = hscroll;
case 2: voffset = vscroll;
map_index = ((bg_y >> tile_size) > 31)?32*32*2:0; if(tile_x != 0) {
break; tile_x = (tile_x - 1) & 31;
case 3: if(ppu.bg_mode == 4) {
map_index = ((bg_x >> tile_size) > 31)?32*32*2:0; pos = ppu.bg_tilemap_loc[BG3] + (tile_x << SH_2);
map_index += ((bg_y >> tile_size) > 31)?32*32*2*2:0; t = *((word*)ppu.vram + (pos >> SH_2));
break; 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_xpos = ((mosaic_x >> SH_8) & 31);
base_pos = (((mosaic_y >> tile_height) & 31) << SH_32) + ((mosaic_x >> tile_width) & 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)); t = *((word*)ppu.vram + (pos >> SH_2));
mirror_y = (t & 0x8000)?1:0; mirror_y = (t & 0x8000)?1:0;
mirror_x = (t & 0x4000)?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) { if((t & 0x2000) == 0) {
ppu_render_bg_tile(color_depth, bg, tile_num); 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)); } if(bg_tiledata_state[tile_num] == 1) {
else { ypos = ( (mosaic_y & 7)); } 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 //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. //unless we have rendered all of the visible tile, taking mosaic into account.
while(1) { tile_ptr = (byte*)bg_tiledata + (tile_num << SH_64) + (ypos << SH_8);
if(mirror_x) { xpos = (7 - (mosaic_x & 7)); } while(1) {
else { xpos = ( (mosaic_x & 7)); } if(mirror_x) { xpos = (7 - (mosaic_x & 7)); }
col = *(bg_tiledata + (tile_num << SH_64) + (ypos << SH_8) + (xpos)); else { xpos = ( (mosaic_x & 7)); }
if(col) { col = *(tile_ptr + xpos);
ppu_set_pixel(bg, screen_x, col + pal_index); if(col) {
} ppu_set_layer_pixel(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;
} }
} 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; bg_x++;
screen_x++; bg_x &= screen_width_mask;
if(screen_x >= render.snes_width)break; 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_mode7.cpp"
#include "ppu_render_mode7f.cpp"
#else
#include "ppu_render_mode7i.cpp"
#endif

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -24,13 +24,17 @@ void mmio_w2100(byte value) {
m: screen mode m: screen mode
*/ */
void mmio_w2105(byte value) { void mmio_w2105(byte value) {
static byte prev_mode = 0x00;
ppu.bg_tile_size[BG4] = (value & 0x80)?1:0; ppu.bg_tile_size[BG4] = (value & 0x80)?1:0;
ppu.bg_tile_size[BG3] = (value & 0x40)?1:0; ppu.bg_tile_size[BG3] = (value & 0x40)?1:0;
ppu.bg_tile_size[BG2] = (value & 0x20)?1:0; ppu.bg_tile_size[BG2] = (value & 0x20)?1:0;
ppu.bg_tile_size[BG1] = (value & 0x10)?1:0; ppu.bg_tile_size[BG1] = (value & 0x10)?1:0;
ppu.bg_priority_mode = (value & 0x08)?1:0; ppu.bg_priority_mode = (value & 0x08)?1:0;
ppu.bg_mode = (value & 0x07); 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 $2133 : screen mode settings
?????h?i ?m???ohi
h: snes height (0 = 224, 1 = 240) m: mode7 extbg (0 = off, 1 = on)
i: interlace (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) { void mmio_w2133(byte value) {
ppu.toggle_visible_scanlines = (value & 0x04)?240:224; ppu.mode7_extbg = (value & 0x40)?true:false;
ppu.interlace = (value & 0x01)?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(); video_setsnesmode();
} }

View File

@ -11,14 +11,12 @@
*/ */
void mmio_w210d(byte value) { void mmio_w210d(byte value) {
ppu.bg_hscroll_pos[BG1] = (value << 8) | (ppu.bg_hscroll_pos[BG1] >> 8); ppu.bg_hscroll_pos[BG1] = (value << 8) | (ppu.bg_hscroll_pos[BG1] >> 8);
ppu.m7hofs = (value << 8) | m7_latch; ppu.m7hofs = (value << 8) | (ppu.m7hofs >> 8);
m7_latch = value;
} }
void mmio_w210e(byte value) { void mmio_w210e(byte value) {
ppu.bg_vscroll_pos[BG1] = (value << 8) | (ppu.bg_vscroll_pos[BG1] >> 8); ppu.bg_vscroll_pos[BG1] = (value << 8) | (ppu.bg_vscroll_pos[BG1] >> 8);
ppu.m7vofs = (value << 8) | m7_latch; ppu.m7vofs = (value << 8) | (ppu.m7vofs >> 8);
m7_latch = value;
} }
void mmio_w210f(byte value) { void mmio_w210f(byte value) {

34
bsnes/ppu/ppu_spc.cpp Normal file
View File

@ -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
}

View File

@ -1,13 +1,19 @@
/* /*
$213d : vertical latch position $2137 : counter latch
returns the current scanline. must read from reading from this register will latch the x/y
$2137 before reading from this register. 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) { byte mmio_r2137(void) {
ppu.latch_toggle = 0; if(ppu.io4201 & 0x80) {
ppu.latch_vpos = snes_time->vscan_pos; snes_time->set_scan_pos(snes_time->master_cycles, false);
ppu.latch_hpos = snes_time->hscan_pos; ppu.latch_toggle = 0;
ppu.latch_vpos = snes_time->vscan_pos;
ppu.latch_hpos = snes_time->hscan_pos;
ppu.counter_latched = true;
}
return 0x00; return 0x00;
} }
@ -29,27 +35,54 @@ word r;
/* /*
$213e : ppu1 status register $213e : ppu1 status register
trm-vvvv
trm0vvvv
t: time over (?) t: time over (?)
r: range over (?) r: range over (?)
m: master/slave mode select (?) m: master/slave mode select (?)
v: version # (returns 1) -: open bus (?)
v: PPU1 (5c77) version number [1]
*/ */
byte mmio_r213e(void) { byte mmio_r213e(void) {
return 0x01; byte r = 0x00;
r |= 0x01; //ppu1 version #
return r;
} }
/* /*
$213f : ppu2 status register $213f : ppu2 status register
fl0mvvvv ilcmvvvv
f: field # (?)
l: external signal applied (should be 0) i: interlace frame (0=even, 1=odd)
l: counter latched
c: open bus complement
m: ntsc/pal mode (0=ntsc, 1=pal) 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) { 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; 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 $4207/$4208 : horizontal counter position
@ -106,18 +169,25 @@ void mmio_w420a(byte value) {
1 = FastROM 1 = FastROM
*/ */
void mmio_w420d(byte value) { 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 $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 mmio_r4210(void) {
byte r; byte r = 0x00;
r = (gx816->nmi_pin ^ 1)?0x80:0x00; r |= (gx816->nmi_pin ^ 1)?0x80:0x00;
r |= 0x02; //cpu version #
gx816->nmi_pin = 1; gx816->nmi_pin = 1;
return r; return r;
} }
@ -130,8 +200,8 @@ byte r;
?: unknown, always return 1? ?: unknown, always return 1?
*/ */
byte mmio_r4211(void) { byte mmio_r4211(void) {
byte r; byte r = 0x00;
r = 0x40; r |= 0x40;
if(ppu.irq_triggered == true)r |= 0x80; if(ppu.irq_triggered == true)r |= 0x80;
ppu.irq_triggered = false; ppu.irq_triggered = false;
return r; 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; 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 //set when the SNES is in hblank/vblank
if(snes_time->hscan_pos >= 256)r |= 0x40; if(snes_time->hcycle_pos <= 4 || snes_time->hcycle_pos >= 1098)r |= 0x40;
if(snes_time->vscan_pos >= ppu.visible_scanlines)r |= 0x80; 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; return r;
} }

View File

@ -40,24 +40,28 @@ void mmio_w210c(byte value) {
/* /*
$2115 : vram write counter $2115 : vram write counter
i---ggrr i---mmrr
i: 0 = increment on $2118/$2139 i: 0 = increment on $2118/$2139
1 = increment on $2119/$213a 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 r: increment rate
00 = increment by 2 00 = increment by 1
01 = increment by 64 01 = increment by 32
10 = increment by 128 10 = increment by 128
11 = increment by 256 11 = increment by 128
*/ */
void mmio_w2115(byte value) { 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) { switch(value & 3) {
case 0x00:ppu.vram_inc_size = 1;break; case 0x00:ppu.vram_inc_size = 1;break;
case 0x01:ppu.vram_inc_size = 32;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; 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) this value is doubled to get true write position (0000-ffff)
*/ */
void mmio_w2116(byte value) { 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) { 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) the settings of $2115 (vram_inc_size / vram_inc_reg)
*/ */
void mmio_w2118(byte value) { void mmio_w2118(byte value) {
word w = ppu.vram_write_pos * 2; word w;
w = mmio_vram_remap();
ppu.vram[w] = value; ppu.vram[w] = value;
if(ppu.vram_inc_reg == 0) { if(ppu.vram_inc_reg == 0) {
ppu.vram_write_pos += ppu.vram_inc_size; 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_2BIT][(w >> 4)] = 1;
ppu_bg_tiledata_state[TILE_4BIT][(w >> 5)] = 1; ppu_bg_tiledata_state[TILE_4BIT][(w >> 5)] = 1;
ppu_bg_tiledata_state[TILE_8BIT][(w >> 6)] = 1; ppu_bg_tiledata_state[TILE_8BIT][(w >> 6)] = 1;
debug_test_bp(BPSRC_VRAM, BP_WRITE, w, value);
} }
void mmio_w2119(byte 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; ppu.vram[w] = value;
if(ppu.vram_inc_reg == 1) { if(ppu.vram_inc_reg == 1) {
ppu.vram_write_pos += ppu.vram_inc_size; 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_2BIT][(w >> 4)] = 1;
ppu_bg_tiledata_state[TILE_4BIT][(w >> 5)] = 1; ppu_bg_tiledata_state[TILE_4BIT][(w >> 5)] = 1;
ppu_bg_tiledata_state[TILE_8BIT][(w >> 6)] = 1; ppu_bg_tiledata_state[TILE_8BIT][(w >> 6)] = 1;
debug_test_bp(BPSRC_VRAM, BP_WRITE, w, value);
} }
/* /*
$2139/$213a : vram read $2139/$213a : vram read
*/ */
byte mmio_r2139(void) { byte mmio_r2139(void) {
word w = ppu.vram_write_pos * 2;
byte r; byte r;
r = ppu.vram[w]; word w;
w = mmio_vram_remap();
r = ppu.vram_read_buffer;
if(ppu.vram_inc_reg == 0) { 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 += ppu.vram_inc_size;
ppu.vram_write_pos &= 0x7fff;
} }
debug_test_bp(BPSRC_VRAM, BP_READ, w, r);
return r; return r;
} }
byte mmio_r213a(void) { byte mmio_r213a(void) {
word w = ppu.vram_write_pos * 2 + 1;
byte r; 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) { 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 += ppu.vram_inc_size;
ppu.vram_write_pos &= 0x7fff;
} }
debug_test_bp(BPSRC_VRAM, BP_READ, w, r);
return r; return r;
} }

View File

@ -1,11 +1,19 @@
/* /*
$2180 : wram write $2180 : wram read/write
write byte to wram write pointer ($2181-$2183), then increment pointer. write byte to wram write pointer ($2181-$2183), then increment pointer.
always stays within 7e0000-7fffff, high 7 bits of 24-bit offset ignored. 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) { 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++;
ppu.wram_write_pos &= 0x01ffff; ppu.wram_write_pos &= 0x01ffff;
} }

Binary file not shown.

View File

@ -1,103 +1,370 @@
#include "../base.h" #include "../base.h"
#include "../cpu/g65816.h" #include "../cpu/g65816.h"
extern g65816 *gx816;
#include "timing.h" #include "timing.h"
snes_timer::snes_timer() { extern g65816 *gx816;
master_cycles = 0; extern ppustate ppu;
vscan_pos = 0; extern debugstate debugger;
hscan_pos = 0; 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 void snes_timer::add_cpu_cycles(byte count, byte speed) {
#define MEMSPEED_SLOW 8 ulong cycles = count * speed;
#define MEMSPEED_XSLOW 12 master_cycles += cycles;
ulong snes_timer::get_master_cycle_count(ulong offset) { bridge.cpu_cycles += cycles;
byte db; }
word addr;
db = (offset >> 16) & 0xff; void snes_timer::add_cpu_pcycles(byte count) {
addr = (offset) & 0xffff; ulong speed = mem_speed_map[(gx816->regs.pc & 0xffffff) >> 9];
if(db >= 0x00 && db <= 0x3f) { ulong cycles = count * speed;
if (addr >= 0x0000 && addr <= 0x1fff)return MEMSPEED_SLOW; master_cycles += cycles;
else if(addr >= 0x2000 && addr <= 0x3fff)return MEMSPEED_FAST; bridge.cpu_cycles += cycles;
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; void snes_timer::add_cpu_mcycles(byte count, ulong addr) {
} else if(db >= 0x40 && db <= 0x7f) { ulong speed = mem_speed_map[(addr & 0xffffff) >> 9];
return MEMSPEED_SLOW; ulong cycles = count * speed;
} else if(db >= 0x80 && db <= 0xbf) { master_cycles += cycles;
if (addr >= 0x0000 && addr <= 0x1fff)return MEMSPEED_SLOW; bridge.cpu_cycles += cycles;
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; void snes_timer::add_cpu_scycles(byte count) {
else if(addr >= 0x6000 && addr <= 0x7fff)return MEMSPEED_SLOW; ulong cycles = (count << 3); //count * 8
else if(addr >= 0x8000 && addr <= 0xffff) { master_cycles += cycles;
if(gx816->memory_speed == MEMSPEED_SLOWROM) { bridge.cpu_cycles += cycles;
return MEMSPEED_SLOW; }
} else { //gx816->memory_speed == MEMSPEED_FASTROM
return MEMSPEED_FAST; 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(addr >= 0x2000 && addr <= 0x3fff) {
} else if(db >= 0xc0 && db <= 0xff) { sm_slowrom[i] = MEMSPEED_FAST;
if(gx816->memory_speed == MEMSPEED_SLOWROM) { sm_fastrom[i] = MEMSPEED_FAST;
return MEMSPEED_SLOW; }
} else { //gx816->memory_speed == MEMSPEED_FASTROM else if(addr >= 0x4000 && addr <= 0x41ff) {
return MEMSPEED_FAST; 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) all dots are 4 cycles long, except dots 322 and 326. dots 322 and 326
vpa = 1, vda = 0 -> add_cpu_pcycles (operand fetch) are 6 cycles long. this holds true for all scanlines except scanline
vpa = 0, vda = 1 -> add_cpu_dcycles (memory fetch) 240 on non-interlace odd frames. the reason for this is because this
vpa = 0, vda = 0 -> add_cpu_icycles (internal operation) 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) { void snes_timer::build_dot_map(void) {
ulong speed; int x, y, cycle;
speed = get_master_cycle_count(gx816->regs.pc); int ptr;
master_cycles += n * speed; 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) { ptr = 0;
ulong speed; for(y=0;y<264;y++) {
speed = get_master_cycle_count(gx816->regs.s); for(x=cycle=0;x<340;x++) {
master_cycles += n * speed; latch_table_a[ptr].cx = cycle;
} latch_table_a[ptr].x = x;
latch_table_a[ptr].y = y;
void snes_timer::add_cpu_mcycles(ulong n, ulong addr) { ptr++;
ulong speed; cycle += 2;
speed = get_master_cycle_count(addr); latch_table_a[ptr].cx = cycle;
master_cycles += n * speed; latch_table_a[ptr].x = x;
} latch_table_a[ptr].y = y;
ptr++;
void snes_timer::add_cpu_icycles(ulong n) { cycle += 2;
master_cycles += n * MEMSPEED_FAST; if(x == 322 || x == 326) {
} latch_table_a[ptr].cx = cycle;
latch_table_a[ptr].x = x;
void snes_timer::add_cpu_icycles(ulong n, ulong flags) { latch_table_a[ptr].y = y;
if(flags & TIMING_BANKCROSS) { ptr++;
if(gx816->index_bank_crossed == true)n++; cycle += 2;
}
}
} }
//regs.dl != 0x00
if(flags & TIMING_CONDITION2) { ptr = 0;
if((gx816->regs.d & 0xff) != 0x00)n++; 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) { void snes_timer::reset_clock(void) {
master_cycles += n; 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) { void snes_timer::update_timer(void) {
vscan_pos = (master_cycles / CYCLES_PER_SCANLINE) % 262; set_scan_pos(master_cycles, true);
hscan_pos = (master_cycles % CYCLES_PER_SCANLINE) / 4;
} }
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);
}
}
}

View File

@ -1,23 +1,43 @@
#define CYCLES_PER_SCANLINE 1360 //mask table (powers of 2)
#define WRAM_REFRESH_DOT_POS 132
#define TIMING_NONE 0x00 #define TIMING_NONE 0x00
#define TIMING_BANKCROSS 0x01 #define TIMING_CONDITION2 0x01 //DL != 0
#define TIMING_REGD 0x02 #define TIMING_CONDITION4 0x02 //crossed page boundary or p.x = 0
#define TIMING_CONDITION2 0x02
#define TIMING_CONDITION4 0x04 typedef struct {
word cx, x, y;
}latch_pos;
class snes_timer { class snes_timer {
public: public:
ulong master_cycles; ulong apu_cycles;
word vscan_pos, hscan_pos; 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); ulong get_master_cycle_count(ulong offset);
void add_cpu_pcycles(ulong n); void build_speed_map(void);
void add_cpu_scycles(ulong n); void build_dot_map(void);
void add_cpu_mcycles(ulong n, ulong addr); void reset_clock(void);
void add_cpu_icycles(ulong n); void inc_vscan_pos(void);
void add_cpu_icycles(ulong n, ulong flags); void set_scan_pos(ulong cycle_pos, bool update_frame_info);
void add_cpu_cycles(ulong n); void set_speed_map(byte speed);
void update_dram_refresh_pos(void);
void update_timer(void); void update_timer(void);
void update_timer_events(void);
snes_timer(); snes_timer();
~snes_timer();
}; };

View File

@ -2,19 +2,22 @@
#include "../timing/timing.h" #include "../timing/timing.h"
extern snes_timer *snes_time; extern snes_timer *snes_time;
#include "../cpu/g65816.h" #include "../cpu/g65816.h"
extern g65816 *gx816; #include "../apu/spc700.h"
extern emustate emu_state; extern g65816 *gx816;
extern debugstate debugger; extern sony_spc700 *spc700;
extern videostate render; extern emustate emu_state;
extern ppustate ppu; extern debugstate debugger;
extern videostate render;
extern ppustate ppu;
#include <windows.h> #include <windows.h>
#define BSNES_TITLE "bsnes v0.0.002 ir9" #define BSNES_TITLE "bsnes v0.0.005a"
enum { enum {
MENU_FILE_LOAD = 100, MENU_FILE_LOAD = 100,
MENU_FILE_RESET, MENU_FILE_RESET,
MENU_FILE_EXIT, MENU_FILE_EXIT,
MENU_SETTINGS_VIDEOMODE_256x224w,
MENU_SETTINGS_VIDEOMODE_512x448w, MENU_SETTINGS_VIDEOMODE_512x448w,
MENU_SETTINGS_VIDEOMODE_640x480f, MENU_SETTINGS_VIDEOMODE_640x480f,
MENU_SETTINGS_FRAMESKIP_OFF, MENU_SETTINGS_FRAMESKIP_OFF,
@ -54,9 +57,9 @@ extern joypad_state joypad1;
void UpdateJoypad(void) { void UpdateJoypad(void) {
joypad1.up = KeyState(KEY_UP ); joypad1.up = KeyState(KEY_UP );
joypad1.down = KeyState(KEY_DOWN ); joypad1.down = (joypad1.up)?0:KeyState(KEY_DOWN);
joypad1.left = KeyState(KEY_LEFT ); joypad1.left = KeyState(KEY_LEFT );
joypad1.right = KeyState(KEY_RIGHT); joypad1.right = (joypad1.left)?0:KeyState(KEY_RIGHT);
joypad1.select = KeyState(KEY_SHIFT); joypad1.select = KeyState(KEY_SHIFT);
joypad1.start = KeyState(KEY_ENTER); joypad1.start = KeyState(KEY_ENTER);
joypad1.y = KeyState(KEY_A ); joypad1.y = KeyState(KEY_A );
@ -65,6 +68,20 @@ void UpdateJoypad(void) {
joypad1.a = KeyState(KEY_X ); joypad1.a = KeyState(KEY_X );
joypad1.l = KeyState(KEY_D ); joypad1.l = KeyState(KEY_D );
joypad1.r = KeyState(KEY_C ); 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, ...) { void alert(char *s, ...) {
@ -126,6 +143,7 @@ HMENU hsubmenu, hbranchmenu;
hsubmenu = CreatePopupMenu(); hsubmenu = CreatePopupMenu();
hbranchmenu = 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_512x448w, "512x448 Windowed");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_640x480f, "640x480 Fullscreen"); AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_640x480f, "640x480 Fullscreen");
AppendMenu(hsubmenu, MF_STRING | MF_POPUP, (unsigned int)hbranchmenu, "&Video Mode"); 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_STYLE, WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
SetWindowLong(hwndMain, GWL_EXSTYLE, 0); 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); PostQuitMessage(0);
break; break;
case WM_PAINT: case WM_PAINT:
UpdateDisplay_NoRender(); DrawScene();
break; break;
case WM_KEYDOWN: case WM_KEYDOWN:
switch(wparam) { switch(wparam) {
@ -273,30 +291,40 @@ bool result;
strcpy(fn, ""); strcpy(fn, "");
result = GUIOpenFile(fn); result = GUIOpenFile(fn);
if(result == true) { if(result == true) {
emu_state.rom_loaded = true;
strcpy(emu_state.rom_name, fn); strcpy(emu_state.rom_name, fn);
fn[strlen(fn) - 4] = 0; fn[strlen(fn) - 4] = 0;
strcat(fn, ".srm"); strcat(fn, ".srm");
strcpy(emu_state.sram_name, fn); strcpy(emu_state.sram_name, fn);
gx816->PowerOn(0); gx816->PowerOn(0);
gx816->LoadROM(); gx816->LoadROM();
if(debug_get_state() == DEBUGMODE_NOROM) { ResetSNES();
debug_set_state(DEBUGMODE_DISABLED); if(debugger_enabled() == true) {
debug_set_state(DEBUGMODE_WAIT);
} }
} }
break; break;
case MENU_FILE_RESET: case MENU_FILE_RESET:
gx816->Reset(); ResetSNES();
break; break;
case MENU_FILE_EXIT: case MENU_FILE_EXIT:
PostQuitMessage(0); PostQuitMessage(0);
break; 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: case MENU_SETTINGS_VIDEOMODE_512x448w:
video_setmode(false, 512, 448); 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_512x448w, MF_CHECKED);
CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_640x480f, MF_UNCHECKED); CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_640x480f, MF_UNCHECKED);
break; break;
case MENU_SETTINGS_VIDEOMODE_640x480f: case MENU_SETTINGS_VIDEOMODE_640x480f:
video_setmode(true, 512, 448); 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_512x448w, MF_UNCHECKED);
CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_640x480f, MF_CHECKED); CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_640x480f, MF_CHECKED);
break; break;
@ -316,9 +344,7 @@ bool result;
CheckMenuItem(hmenuMain, MENU_SETTINGS_FRAMESKIP_OFF + render.frame_skip, MF_CHECKED); CheckMenuItem(hmenuMain, MENU_SETTINGS_FRAMESKIP_OFF + render.frame_skip, MF_CHECKED);
break; break;
case MENU_SETTINGS_DEBUGGER: case MENU_SETTINGS_DEBUGGER:
if(debug_get_state() == DEBUGMODE_NOROM)break; if(debugger_enabled() == false) {
if(debug_get_state() == DEBUGMODE_DISABLED) {
CheckMenuItem(hmenuMain, MENU_SETTINGS_DEBUGGER, MF_CHECKED); CheckMenuItem(hmenuMain, MENU_SETTINGS_DEBUGGER, MF_CHECKED);
EnableDebugger(0); EnableDebugger(0);
} else { } else {
@ -358,23 +384,23 @@ long height;
void EnableDebugger(byte first_time) { void EnableDebugger(byte first_time) {
debug_set_state(DEBUGMODE_WAIT); 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(); 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(); 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(); 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); hwndDBGToggle = NewWindow(wndprocDBGToggle, "bsnes_bgtoggle", "ppu bg toggle", null, 275, 90);
CreateDBGToggle(); 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(hwndDCPU, SW_NORMAL);
ShowWindow(hwndDMEM, SW_NORMAL); ShowWindow(hwndDMEM, SW_NORMAL);
@ -385,7 +411,7 @@ void EnableDebugger(byte first_time) {
if(first_time == 0) { if(first_time == 0) {
debug_refresh_mem(); debug_refresh_mem();
debug_refresh_bp(); debug_refresh_bp();
debug_update_cycles(); debug_update_status();
dprintf("* Debugger Enabled"); dprintf("* Debugger Enabled");
UpdateDisplay(); UpdateDisplay();
} }
@ -411,11 +437,10 @@ MSG msg;
if(debug_get_state() == DEBUGMODE_WAIT) { if(debug_get_state() == DEBUGMODE_WAIT) {
EnableDebugger(1); EnableDebugger(1);
} }
video_setmode(render.fullscreen, render.width, render.height); video_setmode(render.fullscreen, render.display_width, render.display_height);
InitDisplay(); InitDisplay();
CreateColorTable(); CreateColorTable();
SelectRenderer();
InitSNES(); InitSNES();

View File

@ -1,3 +1,6 @@
#define DBP_WIDTH 380
#define DBP_HEIGHT 243
#define DBP_LIST 100 #define DBP_LIST 100
#define DBP_ADDBP 101 #define DBP_ADDBP 101
#define DBP_REMBP 102 #define DBP_REMBP 102
@ -10,34 +13,51 @@
#define DBP_BPX 109 #define DBP_BPX 109
#define DBP_BPV 110 #define DBP_BPV 110
#define DBP_BPVAL 111 #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; HWND hwndDBP;
byte debug_bp_src;
void debug_refresh_bp(void) { void debug_refresh_bp(void) {
char str[64*16], t[64]; char str[128*16], t[128];
if(debug_get_state() == DEBUGMODE_DISABLED)return; if(debugger_enabled() == false)return;
strcpy(str, ""); strcpy(str, "");
for(int i=0;i<16;i++) { for(int i=0;i<16;i++) {
sprintf(t, "%0.2d: ", i); sprintf(t, "%0.2d: ", i);
strcat(str, t); strcat(str, t);
if(gx816->bp_list[i].flags == BP_OFF) { if(debugger.bp_list[i].flags == BP_OFF) {
strcat(str, "------ ---- -- (Disabled)"); strcat(str, "------ ---- -- ------ (Disabled)");
} else { } else {
sprintf(t, "%0.6x %c%c%c%c ", gx816->bp_list[i].offset, sprintf(t, "%0.6x %c%c%c%c ", debugger.bp_list[i].offset,
(gx816->bp_list[i].flags & BP_READ )?'R':'r', (debugger.bp_list[i].flags & BP_READ )?'R':'r',
(gx816->bp_list[i].flags & BP_WRITE)?'W':'w', (debugger.bp_list[i].flags & BP_WRITE)?'W':'w',
(gx816->bp_list[i].flags & BP_EXEC )?'X':'x', (debugger.bp_list[i].flags & BP_EXEC )?'X':'x',
(gx816->bp_list[i].flags & BP_VAL )?'V':'v'); (debugger.bp_list[i].flags & BP_VAL )?'V':'v');
strcat(str, t); strcat(str, t);
if(gx816->bp_list[i].flags & BP_VAL) { if(debugger.bp_list[i].flags & BP_VAL) {
sprintf(t, "%0.2x ", gx816->bp_list[i].value); sprintf(t, "%0.2x ", debugger.bp_list[i].value);
strcat(str, t); strcat(str, t);
} else strcat(str, "-- "); } 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); strcat(str, t);
} }
if(i != 15)strcat(str, "\n"); if(i != 15)strcat(str, "\r\n");
} }
SetDlgItemText(hwndDBP, DBP_LIST, str); 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) { long __stdcall wndprocDBP(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
char str[256]; char str[256];
ulong num, offset, val, flags; 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_DESTROY || msg == WM_CLOSE)return 0; //don't allow debugger to be closed (yet)
if(msg == WM_COMMAND) { if(msg == WM_COMMAND) {
switch(LOWORD(wparam)) { 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: case DBP_ADDBP:
GetDlgItemText(hwndDBP, DBP_BPNUM, str, 255); num = SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_GETCURSEL, 0, 0);
num = strdec(str);
GetDlgItemText(hwndDBP, DBP_BPOFFSET, str, 255); GetDlgItemText(hwndDBP, DBP_BPOFFSET, str, 255);
offset = strhex(str) & 0xffffff; offset = strhex(str) & 0xffffff;
GetDlgItemText(hwndDBP, DBP_BPVAL, str, 255); GetDlgItemText(hwndDBP, DBP_BPVAL, str, 255);
val = strhex(str); val = strhex(str);
flags = 0; flags = 0;
if(SendMessage(GetDlgItem(hwndDBP, DBP_BPR), BM_GETCHECK, 0, 0))flags |= BP_READ; if(SendDlgItemMessage(hwndDBP, DBP_BPR, BM_GETCHECK, 0, 0))flags |= BP_READ;
if(SendMessage(GetDlgItem(hwndDBP, DBP_BPW), BM_GETCHECK, 0, 0))flags |= BP_WRITE; if(SendDlgItemMessage(hwndDBP, DBP_BPW, BM_GETCHECK, 0, 0))flags |= BP_WRITE;
if(SendMessage(GetDlgItem(hwndDBP, DBP_BPX), BM_GETCHECK, 0, 0))flags |= BP_EXEC; if(SendDlgItemMessage(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_BPV, BM_GETCHECK, 0, 0))flags |= BP_VAL;
if(num > 15)dprintf("Invalid breakpoint #: %d -- 0-15 valid", num); debugger.bp_list[num].offset = offset;
else { debugger.bp_list[num].flags = flags;
gx816->bp_list[num].offset = offset; debugger.bp_list[num].source = debug_bp_src;
gx816->bp_list[num].flags = flags; if(debugger.bp_list[num].flags & BP_VAL) {
if(gx816->bp_list[num].flags & BP_VAL)gx816->bp_list[num].value = val; debugger.bp_list[num].value = val;
else gx816->bp_list[num].value = 0; } else {
gx816->bp_list[num].hit_count = 0; debugger.bp_list[num].value = 0;
} }
debugger.bp_list[num].hit_count = 0;
debugger.refresh_bp = true; debugger.refresh_bp = true;
break; break;
case DBP_REMBP: case DBP_REMBP:
GetDlgItemText(hwndDBP, DBP_BPNUM, str, 255); num = SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_GETCURSEL, 0, 0);
num = strdec(str); debugger.bp_list[num].offset = 0;
if(num > 15)dprintf("Invalid breakpoint #: %d -- 0-15 valid", num); debugger.bp_list[num].flags = BP_OFF;
else { debugger.bp_list[num].source = BPSRC_MEM;
gx816->bp_list[num].offset = 0; debugger.bp_list[num].value = 0;
gx816->bp_list[num].flags = BP_OFF; debugger.bp_list[num].hit_count = 0;
gx816->bp_list[num].value = 0;
gx816->bp_list[num].hit_count = 0;
}
debugger.refresh_bp = true; debugger.refresh_bp = true;
break; break;
case DBP_CLRBP: case DBP_CLRBP:
for(i=0;i<16;i++) { for(i=0;i<16;i++) {
gx816->bp_list[i].offset = 0; debugger.bp_list[i].offset = 0;
gx816->bp_list[i].flags = BP_OFF; debugger.bp_list[i].flags = BP_OFF;
gx816->bp_list[i].value = 0; debugger.bp_list[i].source = BPSRC_MEM;
gx816->bp_list[i].hit_count = 0; debugger.bp_list[i].value = 0;
debugger.bp_list[i].hit_count = 0;
} }
debugger.refresh_bp = true; debugger.refresh_bp = true;
break; 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) { void CreateDBP(void) {
CreateWindowEx(WS_EX_STATICEDGE, "STATIC", "", WS_CHILD|WS_VISIBLE, 5, 5, 205, 228, hwndDBP, (HMENU)DBP_LIST, GetModuleHandle(0), 0); CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
CreateWindow("STATIC", "BP #: Offset:", WS_CHILD|WS_VISIBLE, 215, 5, 90, 15, hwndDBP, (HMENU)DBP_STATIC1, GetModuleHandle(0), 0); WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_READONLY,
CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "00", WS_CHILD|WS_VISIBLE, 215, 20, 30, 23, hwndDBP, (HMENU)DBP_BPNUM, GetModuleHandle(0), 0); 5, 5, 260, 233, hwndDBP, (HMENU)DBP_LIST, 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);
SendDlgItemMessage(hwndDBP, DBP_LIST, WM_SETFONT, (WPARAM)hFontFixed, TRUE); CreateWindow("STATIC", "BP #: Offset:", WS_CHILD|WS_VISIBLE, 270, 5, 90, 15, hwndDBP, (HMENU)DBP_STATIC1, GetModuleHandle(0), 0);
SendDlgItemMessage(hwndDBP, DBP_STATIC1, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBP, DBP_BPNUM, WM_SETFONT, (WPARAM)hFontFixed, TRUE); CreateWindow("COMBOBOX", "",
SendDlgItemMessage(hwndDBP, DBP_BPOFFSET, WM_SETFONT, (WPARAM)hFontFixed, TRUE); WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST|CBS_HASSTRINGS,
SendDlgItemMessage(hwndDBP, DBP_BPR, WM_SETFONT, (WPARAM)hFontFixed, TRUE); 270, 20, 45, 300, hwndDBP, (HMENU)DBP_BPNUM, GetModuleHandle(0), 0);
SendDlgItemMessage(hwndDBP, DBP_BPW, WM_SETFONT, (WPARAM)hFontFixed, TRUE); SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"00");
SendDlgItemMessage(hwndDBP, DBP_BPX, WM_SETFONT, (WPARAM)hFontFixed, TRUE); SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"01");
SendDlgItemMessage(hwndDBP, DBP_BPV, WM_SETFONT, (WPARAM)hFontFixed, TRUE); SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"02");
SendDlgItemMessage(hwndDBP, DBP_BPVAL, WM_SETFONT, (WPARAM)hFontFixed, TRUE); SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"03");
SendDlgItemMessage(hwndDBP, DBP_ADDBP, WM_SETFONT, (WPARAM)hFont, TRUE); SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"04");
SendDlgItemMessage(hwndDBP, DBP_REMBP, WM_SETFONT, (WPARAM)hFont, TRUE); SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"05");
SendDlgItemMessage(hwndDBP, DBP_CLRBP, WM_SETFONT, (WPARAM)hFont, TRUE); 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;
} }

View File

@ -1,176 +1,203 @@
#define DCPU_WIDTH 675 #define DCPU_WIDTH 865
#define DCPU_HEIGHT 295 #define DCPU_HEIGHT 385
#define DCPU_DISAS 100 enum {
#define DCPU_RUN 101 DCPU_DISAS = 100,
#define DCPU_STEP 102 DCPU_CPUGROUP,
#define DCPU_PROCEED 103 DCPU_CPUSTEP,
#define DCPU_INFO 104 DCPU_CPUPROCEED,
#define DCPU_TRACE 105 DCPU_CPUSKIP,
#define DCPU_CYCLES 106 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; 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;i<DEBUG_CONSOLE_LINES;i++) {
strcat(str, dcpu_disas_mem[i]);
if(i != DEBUG_CONSOLE_LINES-1)strcat(str, "\r\n");
}
SetDlgItemText(hwndDCPU, DCPU_DISAS, str);
SendDlgItemMessage(hwndDCPU, DCPU_DISAS, EM_SETSEL, 0, -1);
SendDlgItemMessage(hwndDCPU, DCPU_DISAS, EM_SCROLLCARET, 0, 0);
}
void debug_update_status(void) {
char str[4096];
if(!(debug_write_status() & DEBUGWRITE_CONSOLE))return;
sprintf(str,
"Scanline: %3d, HCycle Pos: %4d, HDot Pos: %3d, Master Cycle Pos: %10d\r\n"
"NMI: %s, VIRQ: %s, HIRQ: %s, VIRQ Pos: %3d, HIRQ Pos: %3d\r\n"
"CPU Status: { PC:%0.6x A:%0.4x X:%0.4x Y:%0.4x S:%0.4x D:%0.4x DB:%0.2x }\r\n"
"APU Status: { PC:%0.4x A:%0.2x X:%0.2x Y:%0.2x SP:%0.2x YA:%0.4x }",
snes_time->vscan_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;i<DEBUG_CONSOLE_LINES-1;i++)strcpy(dcpu_disas_mem[i], dcpu_disas_mem[i+1]);
strcpy(dcpu_disas_mem[DEBUG_CONSOLE_LINES - 1], s);
debug_update_console();
}
}
void dprintf(char *s, ...) { void dprintf(char *s, ...) {
char str[256*20]; char str[4096];
va_list args; va_list args;
int i; int i;
if(debug_get_state() == DEBUGMODE_DISABLED)return; if(debugger_enabled() == false)return;
va_start(args, s); va_start(args, s);
vsprintf(str, s, args); vsprintf(str, s, args);
va_end(args); va_end(args);
if(debugger.trace_enabled == true) { debug_write(DEBUGMSG_INFO, str);
fprintf(debugger.trace_fp, "%s\r\n", str);
}
//if(debug_get_state() != DEBUGMODE_RUN) {
for(i=0;i<19;i++)strcpy(dcpu_disas_mem[i], dcpu_disas_mem[i+1]);
strcpy(dcpu_disas_mem[19], str);
strcpy(str, "");
for(i=0;i<20;i++) {
strcat(str, dcpu_disas_mem[i]);
if(i != 20)strcat(str, "\n");
}
SetDlgItemText(hwndDCPU, DCPU_DISAS, str);
//}
} }
void debug_update_cycles(void) { void dprintf(ulong msg_type, char *s, ...) {
char str[256]; char str[4096];
if(debug_get_state() == DEBUGMODE_DISABLED || va_list args;
debug_get_state() == DEBUGMODE_RUN)return; int i;
if(debugger_enabled() == false)return;
sprintf(str, "Scanline: %d\nCC: %d", ppu.vline_pos, snes_time->master_cycles); va_start(args, s);
SetDlgItemText(hwndDCPU, DCPU_CYCLES, str); vsprintf(str, s, args);
va_end(args);
debug_write(msg_type, str);
} }
void debug_set_state(byte state) { void debug_set_state(byte state) {
debugger.mode = state; debugger.mode = state;
if(hwndDCPU && state != DEBUGMODE_DISABLED) { if(hwndDCPU && state != DEBUGMODE_DISABLED) {
if(state == DEBUGMODE_WAIT || state == DEBUGMODE_STEP) { if(state == DEBUGMODE_WAIT) {
SetDlgItemText(hwndDCPU, DCPU_RUN, "Run"); SetDlgItemText(hwndDCPU, DCPU_SYSRUN, "Run");
} else { } else if(state == DEBUGMODE_RUN) {
SetDlgItemText(hwndDCPU, DCPU_RUN, "Stop"); 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) { long __stdcall wndprocDCPU(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
FILE *fp; FILE *fp;
int state;
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(msg == WM_COMMAND) { if(msg == WM_COMMAND) {
switch(LOWORD(wparam)) { switch(LOWORD(wparam)) {
case DCPU_RUN: case DCPU_SYSRUN:
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:
if(debug_get_state() == DEBUGMODE_WAIT) { 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; break;
case DCPU_PROCEED: case DCPU_CPUSTEP:
fp = fopen("data.bin", "wb"); if(debug_get_state() == DEBUGMODE_WAIT) {
fwrite(ppu.vram, 0x10000, 1, fp); debug_set_state(DEBUGMODE_CPUSTEP);
fwrite(gx816->wram, 0x20000, 1, fp); }
fwrite(ppu.cgram, 512, 1, fp); debugger.cpu_op_executed = false;
fwrite(ppu.oam, 544, 1, fp);
fclose(fp);
break; break;
case DCPU_INFO: case DCPU_APUSTEP:
fp = fopen("data.txt", "w"); if(debug_get_state() == DEBUGMODE_WAIT) {
fprintf(fp, debug_set_state(DEBUGMODE_APUSTEP);
"Memory speed: %s\n" }
"Mode: %d\n" debugger.apu_op_executed = false;
"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);
break; break;
case DCPU_TRACE: case DCPU_CFGCPUOUT:
if(debugger.trace_enabled == true) { 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); fclose(debugger.trace_fp);
debugger.trace_enabled = false; debugger.trace_enabled = false;
} else { } else {
@ -178,6 +205,66 @@ FILE *fp;
debugger.trace_enabled = true; debugger.trace_enabled = true;
} }
break; 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) { void CreateDCPU(void) {
int i; int i;
for(i=0;i<20;i++)strcpy(dcpu_disas_mem[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", "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, 590, 25, 80, 20, hwndDCPU, (HMENU)DCPU_STEP, GetModuleHandle(0), 0); CreateWindow("BUTTON", "Step", WS_CHILD|WS_VISIBLE, 615, 20, 80, 20, hwndDCPU, (HMENU)DCPU_CPUSTEP, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Export Mem", WS_CHILD|WS_VISIBLE, 590, 45, 80, 20, hwndDCPU, (HMENU)DCPU_PROCEED, 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", "Info", WS_CHILD|WS_VISIBLE, 590, 65, 80, 20, hwndDCPU, (HMENU)DCPU_INFO, GetModuleHandle(0), 0); CreateWindow("BUTTON", "Skip", WS_CHILD|WS_VISIBLE|WS_DISABLED, 775, 20, 80, 20, hwndDCPU, (HMENU)DCPU_CPUSKIP, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Trace", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 590, 85, 80, 20, hwndDCPU, (HMENU)DCPU_TRACE, 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); CreateWindow("BUTTON", "System", WS_CHILD|WS_VISIBLE|BS_GROUPBOX, 610, 135, 250, 60, hwndDCPU, (HMENU)DCPU_SYSGROUP, GetModuleHandle(0), 0);
SendDlgItemMessage(hwndDCPU, DCPU_RUN, WM_SETFONT, (WPARAM)hFont, TRUE); CreateWindow("BUTTON", "Run", WS_CHILD|WS_VISIBLE, 615, 150, 80, 20, hwndDCPU, (HMENU)DCPU_SYSRUN, GetModuleHandle(0), 0);
SendDlgItemMessage(hwndDCPU, DCPU_STEP, WM_SETFONT, (WPARAM)hFont, TRUE); CreateWindow("BUTTON", "To Frame", WS_CHILD|WS_VISIBLE|WS_DISABLED, 695, 150, 80, 20, hwndDCPU, (HMENU)DCPU_SYSRUNTOFRAME, GetModuleHandle(0), 0);
SendDlgItemMessage(hwndDCPU, DCPU_PROCEED, WM_SETFONT, (WPARAM)hFont, TRUE); CreateWindow("BUTTON", "To VBlank", WS_CHILD|WS_VISIBLE|WS_DISABLED, 775, 150, 80, 20, hwndDCPU, (HMENU)DCPU_SYSRUNTOVBLANK, GetModuleHandle(0), 0);
SendDlgItemMessage(hwndDCPU, DCPU_INFO, WM_SETFONT, (WPARAM)hFont, TRUE); CreateWindow("BUTTON", "To NMI", WS_CHILD|WS_VISIBLE|WS_DISABLED, 615, 170, 80, 20, hwndDCPU, (HMENU)DCPU_SYSRUNTONMI, GetModuleHandle(0), 0);
SendDlgItemMessage(hwndDCPU, DCPU_TRACE, WM_SETFONT, (WPARAM)hFont, TRUE); CreateWindow("BUTTON", "To IRQ", WS_CHILD|WS_VISIBLE|WS_DISABLED, 695, 170, 80, 20, hwndDCPU, (HMENU)DCPU_SYSRUNTOIRQ, GetModuleHandle(0), 0);
SendDlgItemMessage(hwndDCPU, DCPU_CYCLES, WM_SETFONT, (WPARAM)hFont, TRUE); 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);
} }

View File

@ -1,3 +1,6 @@
#define DMEM_WIDTH 500
#define DMEM_HEIGHT 268
#define DMEM_VIEW 100 #define DMEM_VIEW 100
#define DMEM_EDITWRAM 101 #define DMEM_EDITWRAM 101
#define DMEM_UP40 102 #define DMEM_UP40 102
@ -12,17 +15,23 @@
#define DMEM_TOROM 111 #define DMEM_TOROM 111
#define DMEM_TOVRAM 112 #define DMEM_TOVRAM 112
#define DMEM_TOCGRAM 113 #define DMEM_TOCGRAM 113
#define DMEM_TOOAM 114 #define DMEM_TOSRAM 114
#define DMEM_TOOFFSET 115 #define DMEM_TOSPCRAM 115
#define DMEM_EDITLOC 116 #define DMEM_TOOAM 116
#define DMEM_EDITVAL 117 #define DMEM_TOOFFSET 117
#define DMEM_STATIC1 118 #define DMEM_EDITLOC 118
#define DMEM_STATIC2 119 #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_WRAM 0
#define DMEMMODE_VRAM 1 #define DMEMMODE_VRAM 1
#define DMEMMODE_CGRAM 2 #define DMEMMODE_CGRAM 2
#define DMEMMODE_OAM 3 #define DMEMMODE_OAM 3
#define DMEMMODE_SPCRAM 4
ulong dmem_mode = DMEMMODE_WRAM; ulong dmem_mode = DMEMMODE_WRAM;
HWND hwndDMEM; HWND hwndDMEM;
@ -31,7 +40,7 @@ void debug_refresh_mem(void) {
char str[64*16], t[16]; char str[64*16], t[16];
ulong ptr; ulong ptr;
int x, y; int x, y;
if(debug_get_state() == DEBUGMODE_DISABLED)return; if(debugger_enabled() == false)return;
ptr = debugger.mem_ptr; ptr = debugger.mem_ptr;
strcpy(str, ""); strcpy(str, "");
@ -47,7 +56,7 @@ int x, y;
strcat(str, t); strcat(str, t);
if(x != 15)strcat(str, " "); if(x != 15)strcat(str, " ");
} }
if(y != 15)strcat(str, "\n"); if(y != 15)strcat(str, "\r\n");
} }
} else if(dmem_mode == DMEMMODE_VRAM) { } else if(dmem_mode == DMEMMODE_VRAM) {
ptr &= 0xffff; ptr &= 0xffff;
@ -60,7 +69,7 @@ int x, y;
strcat(str, t); strcat(str, t);
if(x != 15)strcat(str, " "); if(x != 15)strcat(str, " ");
} }
if(y != 15)strcat(str, "\n"); if(y != 15)strcat(str, "\r\n");
} }
} else if(dmem_mode == DMEMMODE_CGRAM) { } else if(dmem_mode == DMEMMODE_CGRAM) {
ptr &= 0x01ff; ptr &= 0x01ff;
@ -73,7 +82,7 @@ int x, y;
strcat(str, t); strcat(str, t);
if(x != 15)strcat(str, " "); if(x != 15)strcat(str, " ");
} }
if(y != 15)strcat(str, "\n"); if(y != 15)strcat(str, "\r\n");
} }
} else if(dmem_mode == DMEMMODE_OAM) { } else if(dmem_mode == DMEMMODE_OAM) {
ptr &= 0x03ff; ptr &= 0x03ff;
@ -86,7 +95,20 @@ int x, y;
strcat(str, t); strcat(str, t);
if(x != 15)strcat(str, " "); 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) { void __mask_mem_ptr(void) {
if(dmem_mode == DMEMMODE_WRAM )debugger.mem_ptr &= 0xffffff; if(dmem_mode == DMEMMODE_WRAM )debugger.mem_ptr &= 0xffffff;
if(dmem_mode == DMEMMODE_VRAM )debugger.mem_ptr &= 0x00ffff; if(dmem_mode == DMEMMODE_VRAM )debugger.mem_ptr &= 0x00ffff;
if(dmem_mode == DMEMMODE_CGRAM)debugger.mem_ptr &= 0x0001ff; if(dmem_mode == DMEMMODE_CGRAM )debugger.mem_ptr &= 0x0001ff;
if(dmem_mode == DMEMMODE_OAM )debugger.mem_ptr &= 0x0003ff; 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) { long __stdcall wndprocDMEM(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
char str[256]; char str[256];
ulong pos, val; 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) { if(msg == WM_COMMAND) {
switch(LOWORD(wparam)) { switch(LOWORD(wparam)) {
@ -120,6 +149,8 @@ ulong pos, val;
ppu.cgram[pos & 0x01ff] = val; ppu.cgram[pos & 0x01ff] = val;
} else if(dmem_mode == DMEMMODE_OAM) { } else if(dmem_mode == DMEMMODE_OAM) {
oam_write(pos, val); oam_write(pos, val);
} else if(dmem_mode == DMEMMODE_SPCRAM) {
spc700->ram[pos & 0xffff] = val;
} }
debug_refresh_mem(); debug_refresh_mem();
break; break;
@ -163,39 +194,38 @@ ulong pos, val;
debug_refresh_mem(); debug_refresh_mem();
__mask_mem_ptr(); __mask_mem_ptr();
break; break;
case DMEM_TOWRAM: case DMEM_VIEWMODE:
dmem_mode = DMEMMODE_WRAM; if(HIWORD(wparam) == CBN_SELCHANGE) {
debugger.mem_ptr = 0x7e0000; pos = SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_GETCURSEL, 0, 0);
SetWindowText(hwndDMEM, "g65816 memory editor -- snes memory mode"); if(pos == 0) {
debug_refresh_mem(); 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; break;
case DMEM_TOROM: case DMEM_GOTO:
dmem_mode = DMEMMODE_WRAM; GetDlgItemText(hwndDMEM, DMEM_GOTOADDR, str, 255);
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);
debugger.mem_ptr = strhex(str); debugger.mem_ptr = strhex(str);
__mask_mem_ptr(); __mask_mem_ptr();
debug_refresh_mem(); debug_refresh_mem();
@ -207,30 +237,43 @@ ulong pos, val;
} }
void CreateDMEM(void) { void CreateDMEM(void) {
CreateWindowEx(WS_EX_STATICEDGE, "STATIC", "", WS_CHILD|WS_VISIBLE, 5, 5, 390, 228, hwndDMEM, (HMENU)DMEM_VIEW, GetModuleHandle(0), 0); CreateWindow("COMBOBOX", "",
CreateWindow("STATIC", "Offset: Val:", WS_CHILD|WS_VISIBLE, 400, 5, 100, 15, hwndDMEM, (HMENU)DMEM_STATIC1, GetModuleHandle(0), 0); WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST|CBS_HASSTRINGS,
CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "000000", WS_CHILD|WS_VISIBLE, 400, 20, 60, 23, hwndDMEM, (HMENU)DMEM_EDITLOC, GetModuleHandle(0), 0); 5, 5, 200, 200, hwndDMEM, (HMENU)DMEM_VIEWMODE, GetModuleHandle(0), 0);
CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "00", WS_CHILD|WS_VISIBLE, 460, 20, 30, 23, hwndDMEM, (HMENU)DMEM_EDITVAL, 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", "Edit Memory", WS_CHILD|WS_VISIBLE, 400, 45, 90, 20, hwndDMEM, (HMENU)DMEM_EDITWRAM, GetModuleHandle(0), 0); CreateWindow("BUTTON", "Goto", WS_CHILD|WS_VISIBLE, 270, 5, 50, 20, hwndDMEM, (HMENU)DMEM_GOTO, 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);
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_VIEW, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_EDITLOC, 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_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_STATIC1, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_EDITWRAM, WM_SETFONT, (WPARAM)hFont, TRUE); SendDlgItemMessage(hwndDMEM, DMEM_EDITWRAM, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_UP40, 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_DOWN4000, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_UP40000, 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_DOWN40000, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_STATIC2, WM_SETFONT, (WPARAM)hFont, TRUE); SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, WM_SETFONT, (WPARAM)hFontFixed, 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);
} }

View File

@ -46,7 +46,7 @@ void CreateDDraw_Win(void) {
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
ddsd.dwWidth = 512; ddsd.dwWidth = 512;
ddsd.dwHeight = 480; ddsd.dwHeight = 478;
lpdd->CreateSurface(&ddsd, &lpddsb, 0); lpdd->CreateSurface(&ddsd, &lpddsb, 0);
} }
@ -63,12 +63,16 @@ void CreateDDraw_Full(void) {
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
lpdd->CreateSurface(&ddsd, &lpdds, 0); lpdd->CreateSurface(&ddsd, &lpdds, 0);
lpdd->CreateClipper(0, &lpddc, 0);
lpddc->SetHWnd(0, hwndMain);
lpdds->SetClipper(lpddc);
memset(&ddsd, 0, sizeof(DDSURFACEDESC)); memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
ddsd.dwWidth = 512; ddsd.dwWidth = 512;
ddsd.dwHeight = 480; ddsd.dwHeight = 478;
lpdd->CreateSurface(&ddsd, &lpddsb, 0); lpdd->CreateSurface(&ddsd, &lpddsb, 0);
} }
@ -101,15 +105,19 @@ int i, r, g, b;
vfunc RenderScene; vfunc RenderScene;
#include "render_modes.cpp"
//sets up color table and sets render proc //sets up color table and sets render proc
void CreateColorTable(void) { void CreateColorTable(void) {
lpdds->GetSurfaceDesc(&ddsd); lpdds->GetSurfaceDesc(&ddsd);
switch(ddsd.ddpfPixelFormat.dwRGBBitCount) { switch(ddsd.ddpfPixelFormat.dwRGBBitCount) {
case 16: case 16:
InitColorTable16(); InitColorTable16();
RenderScene = RenderScene16;
break; break;
case 32: case 32:
InitColorTable24(); InitColorTable24();
RenderScene = RenderScene32;
break; break;
default: default:
alert("Error: Bit depth [%d] unsupported (supported depths: 16, 32)", ddsd.ddpfPixelFormat.dwRGBBitCount); 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) { if(ppu.overscan == false) {
lpdds->GetSurfaceDesc(&ddsd); SetRect(&rsrc, 0, 2, 512, 448);
switch(ddsd.ddpfPixelFormat.dwRGBBitCount) { } else {
case 16: SetRect(&rsrc, 0, 2 + 15, 512, 448 + 15);
if (render.snes_width == 512 && render.snes_height == 480) { }
RenderScene = RenderScene16_512x480;
} else if(render.snes_width == 512 && render.snes_height == 448) { hr = lpdds->Blt(&rdest, lpddsb, &rsrc, DDBLT_WAIT, 0);
RenderScene = RenderScene16_512x448; if(hr == DDERR_SURFACELOST) {
} else if(render.snes_width == 512 && render.snes_height == 240) { lpdds->Restore();
RenderScene = RenderScene16_512x240; lpddsb->Restore();
} 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;
} }
} }
void UpdateDisplay(void) { void UpdateDisplay(void) {
RECT rsrc, rdest;
POINT p;
HRESULT hr;
RenderScene(); RenderScene();
DrawScene();
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();
}
} }
void video_setmode(bool fullscreen, word width, word height) { void video_setmode(bool fullscreen, word width, word height) {
bool prev_mode = render.fullscreen; bool prev_mode = render.fullscreen;
render.fullscreen = fullscreen; if(debug_get_state() != DEBUGMODE_DISABLED)return;
render.width = width; render.fullscreen = fullscreen;
render.height = height; 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); FixWindowSize(hwndMain, width, height);
ShowWindow(hwndMain, SW_NORMAL); ShowWindow(hwndMain, SW_NORMAL);
@ -242,6 +187,7 @@ bool prev_mode = render.fullscreen;
FixWindowSize(hwndMain, width, height); FixWindowSize(hwndMain, width, height);
ShowWindow(hwndMain, SW_NORMAL); ShowWindow(hwndMain, SW_NORMAL);
} }
CreateColorTable();
} }
} }
@ -251,19 +197,17 @@ void video_setsnesmode(void) {
} else { } else {
render.snes_width = 256; render.snes_width = 256;
} }
if(ppu.interlace == true) { if(ppu.interlace == false) {
if(ppu.visible_scanlines == 240) { if(ppu.overscan == false) {
render.snes_height = 480; render.snes_height = 224;
} else { } else {
render.snes_height = 448; render.snes_height = 239;
} }
} else { } else {
if(ppu.visible_scanlines == 240) { if(ppu.overscan == false) {
render.snes_height = 240; render.snes_height = 448;
} else { } else {
render.snes_height = 224; render.snes_height = 478;
} }
} }
SelectRenderer();
} }

View File

@ -1,303 +1,84 @@
void RenderScene16_256x224(void) { void RenderScene16(void) {
word *screen;
word *src;
word pitch;
HRESULT hr; HRESULT hr;
int x, y;
hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0);
if(hr != DD_OK)return; if(hr != DD_OK)return;
pitch = ddsd.lPitch >> 1; __asm {
for(y=0;y<224;y++) { mov edi,ddsd.lpSurface
screen = (word*)ddsd.lpSurface + (pitch * y); mov edx,ddsd.lPitch
src = (word*)ppu.screen + y * 512; add edi,edx
for(x=0;x<256;x++) { add edi,edx
*screen++ = render_color_lookup[*src++]; 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); /*
} word *screen, *src;
void RenderScene32_256x224(void) {
ulong *screen;
word *src;
word pitch; word pitch;
HRESULT hr; int x, y;
int x, y; pitch = ddsd.lPitch >> 1;
hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); for(y=2;y<478;y++) {
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++) {
screen = (word*)ddsd.lpSurface + (pitch * y); screen = (word*)ddsd.lpSurface + (pitch * y);
src = (word*)ppu.screen + y * 512; src = (word*)ppu.screen + y * 512;
for(x=0;x<512;x++) { for(x=0;x<512;x++) {
*screen++ = render_color_lookup[*src++]; *screen++ = render_color_lookup[*src++];
} }
} }
*/
lpddsb->Unlock(0); lpddsb->Unlock(0);
} }
void RenderScene32_512x224(void) { void RenderScene32(void) {
ulong *screen;
word *src;
word pitch;
HRESULT hr; HRESULT hr;
int x, y;
hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0);
if(hr != DD_OK)return; if(hr != DD_OK)return;
pitch = ddsd.lPitch >> 2; __asm {
for(y=0;y<224;y++) { mov edi,ddsd.lpSurface
screen = (ulong*)ddsd.lpSurface + (pitch * y); mov edx,ddsd.lPitch
src = (word*)ppu.screen + y * 512; add edi,edx
for(x=0;x<512;x++) { add edi,edx
*screen++ = render_color_lookup[*src++]; sub edx,2048
} mov esi,ppu.screen
} add esi,2048
lpddsb->Unlock(0); mov ebx,478-2
} loop_y:
mov ecx,512
void RenderScene16_512x240(void) { loop_x:
word *screen; lodsw
word *src; and eax,0xffff
word pitch; mov eax,dword ptr[render_color_lookup+eax*4]
HRESULT hr; stosd
int x, y; dec ecx
hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); jnz loop_x
if(hr != DD_OK)return; add edi,edx
pitch = ddsd.lPitch >> 1; dec ebx
for(y=0;y<240;y++) { jnz loop_y
screen = (word*)ddsd.lpSurface + (pitch * y); }
src = (word*)ppu.screen + y * 512; /*
for(x=0;x<512;x++) { ulong *screen;
*screen++ = render_color_lookup[*src++]; word *src;
} word pitch;
} int x, y;
lpddsb->Unlock(0); pitch = ddsd.lPitch >> 2;
} for(y=2;y<478;y++) {
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++) {
screen = (ulong*)ddsd.lpSurface + (pitch * y); screen = (ulong*)ddsd.lpSurface + (pitch * y);
src = (word*)ppu.screen + y * 512; src = (word*)ppu.screen + y * 512;
for(x=0;x<512;x++) { for(x=0;x<512;x++) {
*screen++ = render_color_lookup[*src++]; *screen++ = render_color_lookup[*src++];
} }
} }
*/
lpddsb->Unlock(0); lpddsb->Unlock(0);
} }