Update to bsnes v038r05 release.

[No changelog available]
This commit is contained in:
byuu 2009-01-02 20:13:50 +00:00
parent 6cacb2517a
commit 02ca0f1e69
69 changed files with 1446 additions and 1558 deletions

BIN
bsnes.exe Normal file

Binary file not shown.

BIN
demo_irqtest.smc Normal file

Binary file not shown.

BIN
demo_nmitest.smc Normal file

Binary file not shown.

BIN
irq.smc Normal file

Binary file not shown.

BIN
nmi.smc Normal file

Binary file not shown.

View File

@ -1,4 +1,4 @@
#define BSNES_VERSION "0.038"
#define BSNES_VERSION "0.038.05"
#define BSNES_TITLE "bsnes v" BSNES_VERSION
#define BUSCORE sBus

View File

@ -74,7 +74,7 @@ bool Cheat::encode(string &str, unsigned addr, uint8 data, type_t type) {
char t[16];
if(type == ProActionReplay) {
sprintf(t, "%0.6x:%0.2x", addr, data);
sprintf(t, "%.6x:%.2x", addr, data);
str = t;
return true;
} else if(type == GameGenie) {
@ -91,7 +91,7 @@ bool Cheat::encode(string &str, unsigned addr, uint8 data, type_t type) {
(!!(r & 0x080000) << 5) | (!!(r & 0x040000) << 4) |
(!!(r & 0x020000) << 3) | (!!(r & 0x010000) << 2) |
(!!(r & 0x000800) << 1) | (!!(r & 0x000400) << 0);
sprintf(t, "%0.2x%0.2x-%0.4x", data, addr >> 16, addr & 0xffff);
sprintf(t, "%.2x%.2x-%.4x", data, addr >> 16, addr & 0xffff);
strtr(t, "0123456789abcdef", "df4709156bc8a23e");
str = t;
return true;

View File

@ -102,4 +102,9 @@ integral_setting SMP::ntsc_clock_rate(config(), "smp.ntsc_clock_rate",
integral_setting SMP::pal_clock_rate(config(), "smp.pal_clock_rate",
"PAL S-SMP clock rate (in hz)", integral_setting::decimal, 32041 * 768);
integral_setting Temp::alu_mul_delay(config(), "temp.alu_mul_delay",
"", integral_setting::decimal, 32);
integral_setting Temp::alu_div_delay(config(), "temp.alu_div_delay",
"", integral_setting::decimal, 64);
} //namespace config

View File

@ -31,4 +31,8 @@ extern struct SMP {
static integral_setting ntsc_clock_rate, pal_clock_rate;
} smp;
extern struct Temp {
static integral_setting alu_mul_delay, alu_div_delay;
} temp;
};

View File

@ -17,7 +17,6 @@ public:
regs_t regs;
virtual void scanline() = 0;
virtual void frame() = 0;
virtual void power() = 0;
virtual void reset() = 0;

View File

@ -2,22 +2,22 @@
uint8 CPU::dreadb(uint32 addr) {
if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) {
//$[00-3f|80-bf]:[2000-5fff]
//do not read MMIO registers within debugger
//$[00-3f|80-bf]:[2000-5fff]
//do not read MMIO registers within debugger
return 0x00;
}
return bus.read(addr);
}
uint16 CPU::dreadw(uint32 addr) {
uint16 r;
uint16 r;
r = dreadb((addr + 0) & 0xffffff) << 0;
r |= dreadb((addr + 1) & 0xffffff) << 8;
return r;
}
uint32 CPU::dreadl(uint32 addr) {
uint32 r;
uint32 r;
r = dreadb((addr + 0) & 0xffffff) << 0;
r |= dreadb((addr + 1) & 0xffffff) << 8;
r |= dreadb((addr + 2) & 0xffffff) << 16;
@ -25,87 +25,89 @@ uint32 r;
}
uint32 CPU::decode(uint8 offset_type, uint32 addr) {
uint32 r = 0;
uint32 r = 0;
switch(offset_type) {
case OPTYPE_DP:
r = (regs.d + (addr & 0xffff)) & 0xffff;
break;
case OPTYPE_DPX:
r = (regs.d + regs.x + (addr & 0xffff)) & 0xffff;
break;
case OPTYPE_DPY:
r = (regs.d + regs.y + (addr & 0xffff)) & 0xffff;
break;
case OPTYPE_IDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr);
break;
case OPTYPE_IDPX:
addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr);
break;
case OPTYPE_IDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr) + regs.y;
break;
case OPTYPE_ILDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = dreadl(addr);
break;
case OPTYPE_ILDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = dreadl(addr) + regs.y;
break;
case OPTYPE_ADDR:
r = (regs.db << 16) + (addr & 0xffff);
break;
case OPTYPE_ADDR_PC:
r = (regs.pc.b << 16) + (addr & 0xffff);
break;
case OPTYPE_ADDRX:
r = (regs.db << 16) + (addr & 0xffff) + regs.x;
break;
case OPTYPE_ADDRY:
r = (regs.db << 16) + (addr & 0xffff) + regs.y;
break;
case OPTYPE_IADDR_PC:
r = (regs.pc.b << 16) + (addr & 0xffff);
break;
case OPTYPE_IADDRX:
r = (regs.pc.b << 16) + ((addr + regs.x) & 0xffff);
break;
case OPTYPE_ILADDR:
r = addr;
break;
case OPTYPE_LONG:
r = addr;
break;
case OPTYPE_LONGX:
r = (addr + regs.x);
break;
case OPTYPE_SR:
r = (regs.s + (addr & 0xff)) & 0xffff;
break;
case OPTYPE_ISRY:
addr = (regs.s + (addr & 0xff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr) + regs.y;
break;
case OPTYPE_RELB:
r = (regs.pc.b << 16) + ((regs.pc.w + 2) & 0xffff);
r += int8(addr);
break;
case OPTYPE_RELW:
r = (regs.pc.b << 16) + ((regs.pc.w + 3) & 0xffff);
r += int16(addr);
break;
case OPTYPE_DP:
r = (regs.d + (addr & 0xffff)) & 0xffff;
break;
case OPTYPE_DPX:
r = (regs.d + regs.x + (addr & 0xffff)) & 0xffff;
break;
case OPTYPE_DPY:
r = (regs.d + regs.y + (addr & 0xffff)) & 0xffff;
break;
case OPTYPE_IDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr);
break;
case OPTYPE_IDPX:
addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr);
break;
case OPTYPE_IDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr) + regs.y;
break;
case OPTYPE_ILDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = dreadl(addr);
break;
case OPTYPE_ILDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = dreadl(addr) + regs.y;
break;
case OPTYPE_ADDR:
r = (regs.db << 16) + (addr & 0xffff);
break;
case OPTYPE_ADDR_PC:
r = (regs.pc.b << 16) + (addr & 0xffff);
break;
case OPTYPE_ADDRX:
r = (regs.db << 16) + (addr & 0xffff) + regs.x;
break;
case OPTYPE_ADDRY:
r = (regs.db << 16) + (addr & 0xffff) + regs.y;
break;
case OPTYPE_IADDR_PC:
r = (regs.pc.b << 16) + (addr & 0xffff);
break;
case OPTYPE_IADDRX:
r = (regs.pc.b << 16) + ((addr + regs.x) & 0xffff);
break;
case OPTYPE_ILADDR:
r = addr;
break;
case OPTYPE_LONG:
r = addr;
break;
case OPTYPE_LONGX:
r = (addr + regs.x);
break;
case OPTYPE_SR:
r = (regs.s + (addr & 0xff)) & 0xffff;
break;
case OPTYPE_ISRY:
addr = (regs.s + (addr & 0xff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr) + regs.y;
break;
case OPTYPE_RELB:
r = (regs.pc.b << 16) + ((regs.pc.w + 2) & 0xffff);
r += int8(addr);
break;
case OPTYPE_RELW:
r = (regs.pc.b << 16) + ((regs.pc.w + 3) & 0xffff);
r += int16(addr);
break;
}
return(r & 0xffffff);
}
void CPU::disassemble_opcode(char *output) {
static reg24_t pc;
char t[256];
char *s = output;
static reg24_t pc;
char t[256];
char *s = output;
if(in_opcode() == true) {
strcpy(s, "?????? <CPU within opcode>");
@ -113,367 +115,369 @@ char *s = output;
}
pc.d = regs.pc.d;
sprintf(s, "%0.6x ", uint32(pc.d));
sprintf(s, "%.6x ", (uint32)pc.d);
uint8 op = dreadb(pc.d); pc.w++;
uint8 op0 = dreadb(pc.d); pc.w++;
uint8 op1 = dreadb(pc.d); pc.w++;
uint8 op2 = dreadb(pc.d);
uint8 op = dreadb(pc.d); pc.w++;
uint8 op0 = dreadb(pc.d); pc.w++;
uint8 op1 = dreadb(pc.d); pc.w++;
uint8 op2 = dreadb(pc.d);
#define op8 ((op0))
#define op16 ((op0) | (op1 << 8))
#define op24 ((op0) | (op1 << 8) | (op2 << 16))
#define a8 (regs.e || regs.p.m)
#define x8 (regs.e || regs.p.x)
#define op8 ((op0))
#define op16 ((op0) | (op1 << 8))
#define op24 ((op0) | (op1 << 8) | (op2 << 16))
#define a8 (regs.e || regs.p.m)
#define x8 (regs.e || regs.p.x)
switch(op) {
case 0x00: sprintf(t, "brk #$%0.2x ", op8); break;
case 0x01: sprintf(t, "ora ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x02: sprintf(t, "cop #$%0.2x ", op8); break;
case 0x03: sprintf(t, "ora $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x04: sprintf(t, "tsb $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x05: sprintf(t, "ora $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x06: sprintf(t, "asl $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x07: sprintf(t, "ora [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x08: sprintf(t, "php "); break;
case 0x09: if(a8)sprintf(t, "ora #$%0.2x ", op8);
else sprintf(t, "ora #$%0.4x ", op16); break;
case 0x0a: sprintf(t, "asl a "); break;
case 0x0b: sprintf(t, "phd "); break;
case 0x0c: sprintf(t, "tsb $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0d: sprintf(t, "ora $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0e: sprintf(t, "asl $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0f: sprintf(t, "ora $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x10: sprintf(t, "bpl $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x11: sprintf(t, "ora ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x12: sprintf(t, "ora ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x13: sprintf(t, "ora ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x14: sprintf(t, "trb $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x15: sprintf(t, "ora $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x16: sprintf(t, "asl $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x17: sprintf(t, "ora [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x18: sprintf(t, "clc "); break;
case 0x19: sprintf(t, "ora $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x1a: sprintf(t, "inc "); break;
case 0x1b: sprintf(t, "tcs "); break;
case 0x1c: sprintf(t, "trb $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x1d: sprintf(t, "ora $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x1e: sprintf(t, "asl $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x1f: sprintf(t, "ora $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x20: sprintf(t, "jsr $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
case 0x21: sprintf(t, "and ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x22: sprintf(t, "jsl $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x23: sprintf(t, "and $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x24: sprintf(t, "bit $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x25: sprintf(t, "and $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x26: sprintf(t, "rol $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x27: sprintf(t, "and [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x28: sprintf(t, "plp "); break;
case 0x29: if(a8)sprintf(t, "and #$%0.2x ", op8);
else sprintf(t, "and #$%0.4x ", op16); break;
case 0x2a: sprintf(t, "rol a "); break;
case 0x2b: sprintf(t, "pld "); break;
case 0x2c: sprintf(t, "bit $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2d: sprintf(t, "and $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2e: sprintf(t, "rol $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2f: sprintf(t, "and $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x30: sprintf(t, "bmi $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x31: sprintf(t, "and ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x32: sprintf(t, "and ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x33: sprintf(t, "and ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x34: sprintf(t, "bit $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x35: sprintf(t, "and $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x36: sprintf(t, "rol $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x37: sprintf(t, "and [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x38: sprintf(t, "sec "); break;
case 0x39: sprintf(t, "and $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x3a: sprintf(t, "dec "); break;
case 0x3b: sprintf(t, "tsc "); break;
case 0x3c: sprintf(t, "bit $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3d: sprintf(t, "and $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3e: sprintf(t, "rol $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3f: sprintf(t, "and $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x40: sprintf(t, "rti "); break;
case 0x41: sprintf(t, "eor ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x42: sprintf(t, "wdm "); break;
case 0x43: sprintf(t, "eor $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x44: sprintf(t, "mvp $%0.2x,$%0.2x ", op1, op8); break;
case 0x45: sprintf(t, "eor $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x46: sprintf(t, "lsr $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x47: sprintf(t, "eor [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x48: sprintf(t, "pha "); break;
case 0x49: if(a8)sprintf(t, "eor #$%0.2x ", op8);
else sprintf(t, "eor #$%0.4x ", op16); break;
case 0x4a: sprintf(t, "lsr a "); break;
case 0x4b: sprintf(t, "phk "); break;
case 0x4c: sprintf(t, "jmp $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
case 0x4d: sprintf(t, "eor $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x4e: sprintf(t, "lsr $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x4f: sprintf(t, "eor $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x50: sprintf(t, "bvc $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x51: sprintf(t, "eor ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x52: sprintf(t, "eor ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x53: sprintf(t, "eor ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x54: sprintf(t, "mvn $%0.2x,$%0.2x ", op1, op8); break;
case 0x55: sprintf(t, "eor $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x56: sprintf(t, "lsr $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x57: sprintf(t, "eor [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x58: sprintf(t, "cli "); break;
case 0x59: sprintf(t, "eor $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x5a: sprintf(t, "phy "); break;
case 0x5b: sprintf(t, "tcd "); break;
case 0x5c: sprintf(t, "jml $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x5d: sprintf(t, "eor $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x5e: sprintf(t, "lsr $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x5f: sprintf(t, "eor $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x60: sprintf(t, "rts "); break;
case 0x61: sprintf(t, "adc ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x62: sprintf(t, "per $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x63: sprintf(t, "adc $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x64: sprintf(t, "stz $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x65: sprintf(t, "adc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x66: sprintf(t, "ror $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x67: sprintf(t, "adc [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x68: sprintf(t, "pla "); break;
case 0x69: if(a8)sprintf(t, "adc #$%0.2x ", op8);
else sprintf(t, "adc #$%0.4x ", op16); break;
case 0x6a: sprintf(t, "ror a "); break;
case 0x6b: sprintf(t, "rtl "); break;
case 0x6c: sprintf(t, "jmp ($%0.4x) [$%0.6x]", op16, decode(OPTYPE_IADDR_PC, op16)); break;
case 0x6d: sprintf(t, "adc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x6e: sprintf(t, "ror $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x6f: sprintf(t, "adc $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x70: sprintf(t, "bvs $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x71: sprintf(t, "adc ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x72: sprintf(t, "adc ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x73: sprintf(t, "adc ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x74: sprintf(t, "stz $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x75: sprintf(t, "adc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x76: sprintf(t, "ror $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x77: sprintf(t, "adc [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x78: sprintf(t, "sei "); break;
case 0x79: sprintf(t, "adc $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x7a: sprintf(t, "ply "); break;
case 0x7b: sprintf(t, "tdc "); break;
case 0x7c: sprintf(t, "jmp ($%0.4x,x) [$%0.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
case 0x7d: sprintf(t, "adc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x7e: sprintf(t, "ror $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x7f: sprintf(t, "adc $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x80: sprintf(t, "bra $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x81: sprintf(t, "sta ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x82: sprintf(t, "brl $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELW, op16)), decode(OPTYPE_RELW, op16)); break;
case 0x83: sprintf(t, "sta $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x84: sprintf(t, "sty $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x85: sprintf(t, "sta $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x86: sprintf(t, "stx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x87: sprintf(t, "sta [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x88: sprintf(t, "dey "); break;
case 0x89: if(a8)sprintf(t, "bit #$%0.2x ", op8);
else sprintf(t, "bit #$%0.4x ", op16); break;
case 0x8a: sprintf(t, "txa "); break;
case 0x8b: sprintf(t, "phb "); break;
case 0x8c: sprintf(t, "sty $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8d: sprintf(t, "sta $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8e: sprintf(t, "stx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8f: sprintf(t, "sta $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x90: sprintf(t, "bcc $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x91: sprintf(t, "sta ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x92: sprintf(t, "sta ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x93: sprintf(t, "sta ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x94: sprintf(t, "sty $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x95: sprintf(t, "sta $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x96: sprintf(t, "stx $%0.2x,y [$%0.6x]", op8, decode(OPTYPE_DPY, op8)); break;
case 0x97: sprintf(t, "sta [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x98: sprintf(t, "tya "); break;
case 0x99: sprintf(t, "sta $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x9a: sprintf(t, "txs "); break;
case 0x9b: sprintf(t, "txy "); break;
case 0x9c: sprintf(t, "stz $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x9d: sprintf(t, "sta $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x9e: sprintf(t, "stz $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x9f: sprintf(t, "sta $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xa0: if(x8)sprintf(t, "ldy #$%0.2x ", op8);
else sprintf(t, "ldy #$%0.4x ", op16); break;
case 0xa1: sprintf(t, "lda ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xa2: if(x8)sprintf(t, "ldx #$%0.2x ", op8);
else sprintf(t, "ldx #$%0.4x ", op16); break;
case 0xa3: sprintf(t, "lda $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xa4: sprintf(t, "ldy $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa5: sprintf(t, "lda $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa6: sprintf(t, "ldx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa7: sprintf(t, "lda [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xa8: sprintf(t, "tay "); break;
case 0xa9: if(a8)sprintf(t, "lda #$%0.2x ", op8);
else sprintf(t, "lda #$%0.4x ", op16); break;
case 0xaa: sprintf(t, "tax "); break;
case 0xab: sprintf(t, "plb "); break;
case 0xac: sprintf(t, "ldy $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xad: sprintf(t, "lda $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xae: sprintf(t, "ldx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xaf: sprintf(t, "lda $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xb0: sprintf(t, "bcs $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xb1: sprintf(t, "lda ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xb2: sprintf(t, "lda ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xb3: sprintf(t, "lda ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xb4: sprintf(t, "ldy $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xb5: sprintf(t, "lda $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xb6: sprintf(t, "ldx $%0.2x,y [$%0.6x]", op8, decode(OPTYPE_DPY, op8)); break;
case 0xb7: sprintf(t, "lda [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xb8: sprintf(t, "clv "); break;
case 0xb9: sprintf(t, "lda $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xba: sprintf(t, "tsx "); break;
case 0xbb: sprintf(t, "tyx "); break;
case 0xbc: sprintf(t, "ldy $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xbd: sprintf(t, "lda $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xbe: sprintf(t, "ldx $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xbf: sprintf(t, "lda $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xc0: if(x8)sprintf(t, "cpy #$%0.2x ", op8);
else sprintf(t, "cpy #$%0.4x ", op16); break;
case 0xc1: sprintf(t, "cmp ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xc2: sprintf(t, "rep #$%0.2x ", op8); break;
case 0xc3: sprintf(t, "cmp $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xc4: sprintf(t, "cpy $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc5: sprintf(t, "cmp $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc6: sprintf(t, "dec $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc7: sprintf(t, "cmp [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xc8: sprintf(t, "iny "); break;
case 0xc9: if(a8)sprintf(t, "cmp #$%0.2x ", op8);
else sprintf(t, "cmp #$%0.4x ", op16); break;
case 0xca: sprintf(t, "dex "); break;
case 0xcb: sprintf(t, "wai "); break;
case 0xcc: sprintf(t, "cpy $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xcd: sprintf(t, "cmp $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xce: sprintf(t, "dec $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xcf: sprintf(t, "cmp $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xd0: sprintf(t, "bne $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xd1: sprintf(t, "cmp ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xd2: sprintf(t, "cmp ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xd3: sprintf(t, "cmp ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xd4: sprintf(t, "pei ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xd5: sprintf(t, "cmp $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xd6: sprintf(t, "dec $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xd7: sprintf(t, "cmp [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xd8: sprintf(t, "cld "); break;
case 0xd9: sprintf(t, "cmp $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xda: sprintf(t, "phx "); break;
case 0xdb: sprintf(t, "stp "); break;
case 0xdc: sprintf(t, "jmp [$%0.4x] [$%0.6x]", op16, decode(OPTYPE_ILADDR, op16)); break;
case 0xdd: sprintf(t, "cmp $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xde: sprintf(t, "dec $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xdf: sprintf(t, "cmp $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xe0: if(x8)sprintf(t, "cpx #$%0.2x ", op8);
else sprintf(t, "cpx #$%0.4x ", op16); break;
case 0xe1: sprintf(t, "sbc ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xe2: sprintf(t, "sep #$%0.2x ", op8); break;
case 0xe3: sprintf(t, "sbc $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xe4: sprintf(t, "cpx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe5: sprintf(t, "sbc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe6: sprintf(t, "inc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe7: sprintf(t, "sbc [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xe8: sprintf(t, "inx "); break;
case 0xe9: if(a8)sprintf(t, "sbc #$%0.2x ", op8);
else sprintf(t, "sbc #$%0.4x ", op16); break;
case 0xea: sprintf(t, "nop "); break;
case 0xeb: sprintf(t, "xba "); break;
case 0xec: sprintf(t, "cpx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xed: sprintf(t, "sbc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xee: sprintf(t, "inc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xef: sprintf(t, "sbc $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xf0: sprintf(t, "beq $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xf1: sprintf(t, "sbc ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xf2: sprintf(t, "sbc ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xf3: sprintf(t, "sbc ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xf4: sprintf(t, "pea $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xf5: sprintf(t, "sbc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xf6: sprintf(t, "inc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xf7: sprintf(t, "sbc [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xf8: sprintf(t, "sed "); break;
case 0xf9: sprintf(t, "sbc $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xfa: sprintf(t, "plx "); break;
case 0xfb: sprintf(t, "xce "); break;
case 0xfc: sprintf(t, "jsr ($%0.4x,x) [$%0.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
case 0xfd: sprintf(t, "sbc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xfe: sprintf(t, "inc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xff: sprintf(t, "sbc $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x00: sprintf(t, "brk #$%.2x ", op8); break;
case 0x01: sprintf(t, "ora ($%.2x,x) [$%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x02: sprintf(t, "cop #$%.2x ", op8); break;
case 0x03: sprintf(t, "ora $%.2x,s [$%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x04: sprintf(t, "tsb $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x05: sprintf(t, "ora $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x06: sprintf(t, "asl $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x07: sprintf(t, "ora [$%.2x] [$%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x08: sprintf(t, "php "); break;
case 0x09: if(a8)sprintf(t, "ora #$%.2x ", op8);
else sprintf(t, "ora #$%.4x ", op16); break;
case 0x0a: sprintf(t, "asl a "); break;
case 0x0b: sprintf(t, "phd "); break;
case 0x0c: sprintf(t, "tsb $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0d: sprintf(t, "ora $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0e: sprintf(t, "asl $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0f: sprintf(t, "ora $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x10: sprintf(t, "bpl $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x11: sprintf(t, "ora ($%.2x),y [$%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x12: sprintf(t, "ora ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x13: sprintf(t, "ora ($%.2x,s),y [$%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x14: sprintf(t, "trb $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x15: sprintf(t, "ora $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x16: sprintf(t, "asl $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x17: sprintf(t, "ora [$%.2x],y [$%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x18: sprintf(t, "clc "); break;
case 0x19: sprintf(t, "ora $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x1a: sprintf(t, "inc "); break;
case 0x1b: sprintf(t, "tcs "); break;
case 0x1c: sprintf(t, "trb $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x1d: sprintf(t, "ora $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x1e: sprintf(t, "asl $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x1f: sprintf(t, "ora $%.6x,x [$%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x20: sprintf(t, "jsr $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
case 0x21: sprintf(t, "and ($%.2x,x) [$%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x22: sprintf(t, "jsl $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x23: sprintf(t, "and $%.2x,s [$%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x24: sprintf(t, "bit $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x25: sprintf(t, "and $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x26: sprintf(t, "rol $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x27: sprintf(t, "and [$%.2x] [$%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x28: sprintf(t, "plp "); break;
case 0x29: if(a8)sprintf(t, "and #$%.2x ", op8);
else sprintf(t, "and #$%.4x ", op16); break;
case 0x2a: sprintf(t, "rol a "); break;
case 0x2b: sprintf(t, "pld "); break;
case 0x2c: sprintf(t, "bit $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2d: sprintf(t, "and $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2e: sprintf(t, "rol $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2f: sprintf(t, "and $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x30: sprintf(t, "bmi $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x31: sprintf(t, "and ($%.2x),y [$%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x32: sprintf(t, "and ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x33: sprintf(t, "and ($%.2x,s),y [$%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x34: sprintf(t, "bit $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x35: sprintf(t, "and $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x36: sprintf(t, "rol $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x37: sprintf(t, "and [$%.2x],y [$%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x38: sprintf(t, "sec "); break;
case 0x39: sprintf(t, "and $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x3a: sprintf(t, "dec "); break;
case 0x3b: sprintf(t, "tsc "); break;
case 0x3c: sprintf(t, "bit $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3d: sprintf(t, "and $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3e: sprintf(t, "rol $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3f: sprintf(t, "and $%.6x,x [$%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x40: sprintf(t, "rti "); break;
case 0x41: sprintf(t, "eor ($%.2x,x) [$%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x42: sprintf(t, "wdm "); break;
case 0x43: sprintf(t, "eor $%.2x,s [$%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x44: sprintf(t, "mvp $%.2x,$%.2x ", op1, op8); break;
case 0x45: sprintf(t, "eor $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x46: sprintf(t, "lsr $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x47: sprintf(t, "eor [$%.2x] [$%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x48: sprintf(t, "pha "); break;
case 0x49: if(a8)sprintf(t, "eor #$%.2x ", op8);
else sprintf(t, "eor #$%.4x ", op16); break;
case 0x4a: sprintf(t, "lsr a "); break;
case 0x4b: sprintf(t, "phk "); break;
case 0x4c: sprintf(t, "jmp $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
case 0x4d: sprintf(t, "eor $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x4e: sprintf(t, "lsr $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x4f: sprintf(t, "eor $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x50: sprintf(t, "bvc $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x51: sprintf(t, "eor ($%.2x),y [$%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x52: sprintf(t, "eor ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x53: sprintf(t, "eor ($%.2x,s),y [$%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x54: sprintf(t, "mvn $%.2x,$%.2x ", op1, op8); break;
case 0x55: sprintf(t, "eor $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x56: sprintf(t, "lsr $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x57: sprintf(t, "eor [$%.2x],y [$%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x58: sprintf(t, "cli "); break;
case 0x59: sprintf(t, "eor $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x5a: sprintf(t, "phy "); break;
case 0x5b: sprintf(t, "tcd "); break;
case 0x5c: sprintf(t, "jml $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x5d: sprintf(t, "eor $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x5e: sprintf(t, "lsr $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x5f: sprintf(t, "eor $%.6x,x [$%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x60: sprintf(t, "rts "); break;
case 0x61: sprintf(t, "adc ($%.2x,x) [$%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x62: sprintf(t, "per $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x63: sprintf(t, "adc $%.2x,s [$%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x64: sprintf(t, "stz $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x65: sprintf(t, "adc $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x66: sprintf(t, "ror $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x67: sprintf(t, "adc [$%.2x] [$%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x68: sprintf(t, "pla "); break;
case 0x69: if(a8)sprintf(t, "adc #$%.2x ", op8);
else sprintf(t, "adc #$%.4x ", op16); break;
case 0x6a: sprintf(t, "ror a "); break;
case 0x6b: sprintf(t, "rtl "); break;
case 0x6c: sprintf(t, "jmp ($%.4x) [$%.6x]", op16, decode(OPTYPE_IADDR_PC, op16)); break;
case 0x6d: sprintf(t, "adc $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x6e: sprintf(t, "ror $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x6f: sprintf(t, "adc $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x70: sprintf(t, "bvs $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x71: sprintf(t, "adc ($%.2x),y [$%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x72: sprintf(t, "adc ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x73: sprintf(t, "adc ($%.2x,s),y [$%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x74: sprintf(t, "stz $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x75: sprintf(t, "adc $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x76: sprintf(t, "ror $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x77: sprintf(t, "adc [$%.2x],y [$%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x78: sprintf(t, "sei "); break;
case 0x79: sprintf(t, "adc $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x7a: sprintf(t, "ply "); break;
case 0x7b: sprintf(t, "tdc "); break;
case 0x7c: sprintf(t, "jmp ($%.4x,x) [$%.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
case 0x7d: sprintf(t, "adc $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x7e: sprintf(t, "ror $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x7f: sprintf(t, "adc $%.6x,x [$%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x80: sprintf(t, "bra $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x81: sprintf(t, "sta ($%.2x,x) [$%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x82: sprintf(t, "brl $%.4x [$%.6x]", uint16(decode(OPTYPE_RELW, op16)), decode(OPTYPE_RELW, op16)); break;
case 0x83: sprintf(t, "sta $%.2x,s [$%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x84: sprintf(t, "sty $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x85: sprintf(t, "sta $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x86: sprintf(t, "stx $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x87: sprintf(t, "sta [$%.2x] [$%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x88: sprintf(t, "dey "); break;
case 0x89: if(a8)sprintf(t, "bit #$%.2x ", op8);
else sprintf(t, "bit #$%.4x ", op16); break;
case 0x8a: sprintf(t, "txa "); break;
case 0x8b: sprintf(t, "phb "); break;
case 0x8c: sprintf(t, "sty $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8d: sprintf(t, "sta $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8e: sprintf(t, "stx $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8f: sprintf(t, "sta $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x90: sprintf(t, "bcc $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x91: sprintf(t, "sta ($%.2x),y [$%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x92: sprintf(t, "sta ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x93: sprintf(t, "sta ($%.2x,s),y [$%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x94: sprintf(t, "sty $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x95: sprintf(t, "sta $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x96: sprintf(t, "stx $%.2x,y [$%.6x]", op8, decode(OPTYPE_DPY, op8)); break;
case 0x97: sprintf(t, "sta [$%.2x],y [$%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x98: sprintf(t, "tya "); break;
case 0x99: sprintf(t, "sta $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x9a: sprintf(t, "txs "); break;
case 0x9b: sprintf(t, "txy "); break;
case 0x9c: sprintf(t, "stz $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x9d: sprintf(t, "sta $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x9e: sprintf(t, "stz $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x9f: sprintf(t, "sta $%.6x,x [$%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xa0: if(x8)sprintf(t, "ldy #$%.2x ", op8);
else sprintf(t, "ldy #$%.4x ", op16); break;
case 0xa1: sprintf(t, "lda ($%.2x,x) [$%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xa2: if(x8)sprintf(t, "ldx #$%.2x ", op8);
else sprintf(t, "ldx #$%.4x ", op16); break;
case 0xa3: sprintf(t, "lda $%.2x,s [$%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xa4: sprintf(t, "ldy $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa5: sprintf(t, "lda $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa6: sprintf(t, "ldx $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa7: sprintf(t, "lda [$%.2x] [$%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xa8: sprintf(t, "tay "); break;
case 0xa9: if(a8)sprintf(t, "lda #$%.2x ", op8);
else sprintf(t, "lda #$%.4x ", op16); break;
case 0xaa: sprintf(t, "tax "); break;
case 0xab: sprintf(t, "plb "); break;
case 0xac: sprintf(t, "ldy $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xad: sprintf(t, "lda $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xae: sprintf(t, "ldx $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xaf: sprintf(t, "lda $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xb0: sprintf(t, "bcs $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xb1: sprintf(t, "lda ($%.2x),y [$%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xb2: sprintf(t, "lda ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xb3: sprintf(t, "lda ($%.2x,s),y [$%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xb4: sprintf(t, "ldy $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xb5: sprintf(t, "lda $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xb6: sprintf(t, "ldx $%.2x,y [$%.6x]", op8, decode(OPTYPE_DPY, op8)); break;
case 0xb7: sprintf(t, "lda [$%.2x],y [$%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xb8: sprintf(t, "clv "); break;
case 0xb9: sprintf(t, "lda $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xba: sprintf(t, "tsx "); break;
case 0xbb: sprintf(t, "tyx "); break;
case 0xbc: sprintf(t, "ldy $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xbd: sprintf(t, "lda $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xbe: sprintf(t, "ldx $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xbf: sprintf(t, "lda $%.6x,x [$%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xc0: if(x8)sprintf(t, "cpy #$%.2x ", op8);
else sprintf(t, "cpy #$%.4x ", op16); break;
case 0xc1: sprintf(t, "cmp ($%.2x,x) [$%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xc2: sprintf(t, "rep #$%.2x ", op8); break;
case 0xc3: sprintf(t, "cmp $%.2x,s [$%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xc4: sprintf(t, "cpy $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc5: sprintf(t, "cmp $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc6: sprintf(t, "dec $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc7: sprintf(t, "cmp [$%.2x] [$%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xc8: sprintf(t, "iny "); break;
case 0xc9: if(a8)sprintf(t, "cmp #$%.2x ", op8);
else sprintf(t, "cmp #$%.4x ", op16); break;
case 0xca: sprintf(t, "dex "); break;
case 0xcb: sprintf(t, "wai "); break;
case 0xcc: sprintf(t, "cpy $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xcd: sprintf(t, "cmp $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xce: sprintf(t, "dec $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xcf: sprintf(t, "cmp $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xd0: sprintf(t, "bne $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xd1: sprintf(t, "cmp ($%.2x),y [$%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xd2: sprintf(t, "cmp ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xd3: sprintf(t, "cmp ($%.2x,s),y [$%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xd4: sprintf(t, "pei ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xd5: sprintf(t, "cmp $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xd6: sprintf(t, "dec $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xd7: sprintf(t, "cmp [$%.2x],y [$%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xd8: sprintf(t, "cld "); break;
case 0xd9: sprintf(t, "cmp $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xda: sprintf(t, "phx "); break;
case 0xdb: sprintf(t, "stp "); break;
case 0xdc: sprintf(t, "jmp [$%.4x] [$%.6x]", op16, decode(OPTYPE_ILADDR, op16)); break;
case 0xdd: sprintf(t, "cmp $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xde: sprintf(t, "dec $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xdf: sprintf(t, "cmp $%.6x,x [$%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xe0: if(x8)sprintf(t, "cpx #$%.2x ", op8);
else sprintf(t, "cpx #$%.4x ", op16); break;
case 0xe1: sprintf(t, "sbc ($%.2x,x) [$%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xe2: sprintf(t, "sep #$%.2x ", op8); break;
case 0xe3: sprintf(t, "sbc $%.2x,s [$%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xe4: sprintf(t, "cpx $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe5: sprintf(t, "sbc $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe6: sprintf(t, "inc $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe7: sprintf(t, "sbc [$%.2x] [$%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xe8: sprintf(t, "inx "); break;
case 0xe9: if(a8)sprintf(t, "sbc #$%.2x ", op8);
else sprintf(t, "sbc #$%.4x ", op16); break;
case 0xea: sprintf(t, "nop "); break;
case 0xeb: sprintf(t, "xba "); break;
case 0xec: sprintf(t, "cpx $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xed: sprintf(t, "sbc $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xee: sprintf(t, "inc $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xef: sprintf(t, "sbc $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xf0: sprintf(t, "beq $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xf1: sprintf(t, "sbc ($%.2x),y [$%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xf2: sprintf(t, "sbc ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xf3: sprintf(t, "sbc ($%.2x,s),y [$%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xf4: sprintf(t, "pea $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xf5: sprintf(t, "sbc $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xf6: sprintf(t, "inc $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xf7: sprintf(t, "sbc [$%.2x],y [$%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xf8: sprintf(t, "sed "); break;
case 0xf9: sprintf(t, "sbc $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xfa: sprintf(t, "plx "); break;
case 0xfb: sprintf(t, "xce "); break;
case 0xfc: sprintf(t, "jsr ($%.4x,x) [$%.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
case 0xfd: sprintf(t, "sbc $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xfe: sprintf(t, "inc $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xff: sprintf(t, "sbc $%.6x,x [$%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
}
#undef op8
#undef op16
#undef op24
#undef a8
#undef x8
#undef op8
#undef op16
#undef op24
#undef a8
#undef x8
strcat(s, t);
strcat(s, " ");
sprintf(t, "A:%0.4x X:%0.4x Y:%0.4x S:%0.4x D:%0.4x DB:%0.2x ",
sprintf(t, "A:%.4x X:%.4x Y:%.4x S:%.4x D:%.4x DB:%.2x ",
regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d.w, regs.db);
strcat(s, t);
if(regs.e) {
sprintf(t, "%c%c%c%c%c%c%c%c",
(regs.p.n) ? 'N' : 'n', (regs.p.v) ? 'V' : 'v',
(regs.p.m) ? '1' : '0', (regs.p.x) ? 'B' : 'b',
(regs.p.d) ? 'D' : 'd', (regs.p.i) ? 'I' : 'i',
(regs.p.z) ? 'Z' : 'z', (regs.p.c) ? 'C' : 'c');
regs.p.n ? 'N' : 'n', regs.p.v ? 'V' : 'v',
regs.p.m ? '1' : '0', regs.p.x ? 'B' : 'b',
regs.p.d ? 'D' : 'd', regs.p.i ? 'I' : 'i',
regs.p.z ? 'Z' : 'z', regs.p.c ? 'C' : 'c');
} else {
sprintf(t, "%c%c%c%c%c%c%c%c",
(regs.p.n) ? 'N' : 'n', (regs.p.v) ? 'V' : 'v',
(regs.p.m) ? 'M' : 'm', (regs.p.x) ? 'X' : 'x',
(regs.p.d) ? 'D' : 'd', (regs.p.i) ? 'I' : 'i',
(regs.p.z) ? 'Z' : 'z', (regs.p.c) ? 'C' : 'c');
regs.p.n ? 'N' : 'n', regs.p.v ? 'V' : 'v',
regs.p.m ? 'M' : 'm', regs.p.x ? 'X' : 'x',
regs.p.d ? 'D' : 'd', regs.p.i ? 'I' : 'i',
regs.p.z ? 'Z' : 'z', regs.p.c ? 'C' : 'c');
}
strcat(s, t);
strcat(s, " ");
sprintf(t, "V:%3d H:%4d", ppucounter.vcounter(), ppucounter.hcounter());
sprintf(t, "V:%3d H:%4d", ppu.vcounter(), ppu.hcounter());
strcat(s, t);
}
/*****
* opcode_length() retrieves the length of the next opcode
* to be executed. It is used by the debugger to step over,
* disable and proceed cpu opcodes.
*
* 5 and 6 are special cases, 5 is used for #consts based on
* the A register size, 6 for the X/Y register size. the
* rest are literal sizes. There's no need to test for
* emulation mode, as regs.p.m/regs.p.x should *always* be
* set in emulation mode.
*****/
//opcode_length() retrieves the length of the next opcode
//to be executed. It is used by the debugger to step over,
//disable and proceed cpu opcodes.
//
//5 and 6 are special cases, 5 is used for #consts based on
//the A register size, 6 for the X/Y register size. the
//rest are literal sizes. There's no need to test for
//emulation mode, as regs.p.m/regs.p.x should *always* be
//set in emulation mode.
uint8 CPU::opcode_length() {
uint8 op, len;
static uint8 op_len_tbl[256] = {
//0,1,2,3, 4,5,6,7, 8,9,a,b, c,d,e,f
uint8 op, len;
static uint8 op_len_tbl[256] = {
//0,1,2,3, 4,5,6,7, 8,9,a,b, c,d,e,f
2,2,2,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x0n
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0x1n
3,2,4,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x2n
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0x3n
2,2,2,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x0n
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0x1n
3,2,4,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x2n
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0x3n
1,2,2,2, 3,2,2,2, 1,5,1,1, 3,3,3,4, //0x4n
2,2,2,2, 3,2,2,2, 1,3,1,1, 4,3,3,4, //0x5n
1,2,3,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x6n
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0x7n
1,2,2,2, 3,2,2,2, 1,5,1,1, 3,3,3,4, //0x4n
2,2,2,2, 3,2,2,2, 1,3,1,1, 4,3,3,4, //0x5n
1,2,3,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x6n
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0x7n
2,2,3,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x8n
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0x9n
6,2,6,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0xan
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0xbn
2,2,3,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x8n
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0x9n
6,2,6,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0xan
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0xbn
6,2,2,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0xcn
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0xdn
6,2,2,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0xen
2,2,2,2, 3,2,2,2, 1,3,1,1, 3,3,3,4 //0xfn
};
6,2,2,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0xcn
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0xdn
6,2,2,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0xen
2,2,2,2, 3,2,2,2, 1,3,1,1, 3,3,3,4 //0xfn
};
if(in_opcode() == true) {
return 0;
}
op = dreadb(regs.pc.d);
len = op_len_tbl[op];
if(len == 5)return (regs.e || regs.p.m) ? 2 : 3;
if(len == 6)return (regs.e || regs.p.x) ? 2 : 3;
if(len == 5) return (regs.e || regs.p.m) ? 2 : 3;
if(len == 6) return (regs.e || regs.p.x) ? 2 : 3;
return len;
}
#endif //ifdef CPU_CPP
#endif //ifdef CPU_CPP

View File

@ -0,0 +1,88 @@
#ifdef SCPU_CPP
//delta queue scheduler is used to time multiple events with the following properties:
//O(1) test (tick)
//O(log n) insert (enqueue)
//O(log n) remove (dequeue)
//
//notes:
//implementation uses binary min-heap array;
//tick() uses 2's-complement signed math to avoid overflow errors;
//enqueue() takes relative timestamps, which are converted to absolute times internally.
class deltaqueue {
enum { queuesize = 64 }; //maximum number of events that can be queued at the same time.
public:
alwaysinline void tick(unsigned ticks) {
counter += ticks;
while(heapsize) {
if((signed)(counter - heap[0].counter) < 0) break; //if(counter < heap[0].counter) break;
unsigned event = heap[0].event;
dequeue();
cpu.queue_event(event);
}
}
void enqueue(unsigned event, unsigned ticks) {
unsigned child = heapsize++;
heap[child].event = event;
heap[child].counter = counter + ticks;
while(child) {
unsigned parent = (child - 1) >> 1;
if(heap[child].counter >= heap[parent].counter) break;
swap(parent, child);
child = parent;
}
}
void dequeue() {
heap[0].counter = heap[--heapsize].counter;
heap[0].event = heap[heapsize].event;
heap[heapsize].counter = ~0;
unsigned parent = 0;
while(true) {
unsigned child = (parent << 1) + 1;
if(heap[child + 1].counter < heap[child].counter) child++;
if(heap[parent].counter <= heap[child].counter) break;
swap(parent, child);
parent = child;
}
}
void reset() {
counter = 0;
heapsize = 0;
for(unsigned i = 0; i < queuesize << 1; i++) heap[i].counter = ~0;
}
deltaqueue() {
reset();
}
public:
unsigned counter;
unsigned heapsize;
struct {
unsigned counter;
unsigned event;
} heap[queuesize << 1];
void swap(unsigned x, unsigned y) {
unsigned counter = heap[x].counter;
unsigned event = heap[x].event;
heap[x].counter = heap[y].counter;
heap[x].event = heap[y].event;
heap[y].counter = counter;
heap[y].event = event;
}
};
#endif //ifdef SCPU_CPP

View File

@ -121,7 +121,8 @@ void sCPU::dma_run() {
channel[i].dma_enabled = false;
}
counter.set(counter.irq_delay, 2);
status.irq_lock = true;
delta.enqueue(EventIrqLockRelease, 2);
}
/*****
@ -203,7 +204,8 @@ void sCPU::hdma_run() {
}
}
counter.set(counter.irq_delay, 2);
status.irq_lock = true;
delta.enqueue(EventIrqLockRelease, 2);
}
void sCPU::hdma_init_reset() {
@ -224,7 +226,8 @@ void sCPU::hdma_init() {
hdma_update(i);
}
counter.set(counter.irq_delay, 2);
status.irq_lock = true;
delta.enqueue(EventIrqLockRelease, 2);
}
/*****

View File

@ -91,7 +91,9 @@ void sCPU::mmio_w4202(uint8 data) {
void sCPU::mmio_w4203(uint8 data) {
status.mul_b = data;
status.r4216 = status.mul_a * status.mul_b;
//counter.set(counter.hw_math, 48);
status.alu_lock = true;
delta.enqueue(EventAluLockRelease, temp_.alu_mul_delay);
}
//WRDIVL
@ -109,7 +111,9 @@ void sCPU::mmio_w4206(uint8 data) {
status.div_b = data;
status.r4214 = (status.div_b) ? status.div_a / status.div_b : 0xffff;
status.r4216 = (status.div_b) ? status.div_a % status.div_b : status.div_a;
//counter.set(counter.hw_math, 96);
status.alu_lock = true;
delta.enqueue(EventAluLockRelease, temp_.alu_div_delay);
}
//HTIMEL
@ -190,13 +194,13 @@ uint8 sCPU::mmio_r4212() {
uint16 vs = ppu.overscan() == false ? 225 : 240;
//auto joypad polling
if(ppucounter.vcounter() >= vs && ppucounter.vcounter() <= (vs + 2))r |= 0x01;
if(ppu.vcounter() >= vs && ppu.vcounter() <= (vs + 2))r |= 0x01;
//hblank
if(ppucounter.hcounter() <= 2 || ppucounter.hcounter() >= 1096)r |= 0x40;
if(ppu.hcounter() <= 2 || ppu.hcounter() >= 1096)r |= 0x40;
//vblank
if(ppucounter.vcounter() >= vs)r |= 0x80;
if(ppu.vcounter() >= vs)r |= 0x80;
return r;
}
@ -208,25 +212,25 @@ uint8 sCPU::mmio_r4213() {
//RDDIVL
uint8 sCPU::mmio_r4214() {
if(counter.hw_math) { return 0x00; }
if(status.alu_lock) return 0;
return status.r4214;
}
//RDDIVH
uint8 sCPU::mmio_r4215() {
if(counter.hw_math) { return 0x00; }
if(status.alu_lock) return 0;
return status.r4214 >> 8;
}
//RDMPYL
uint8 sCPU::mmio_r4216() {
if(counter.hw_math) { return 0x00; }
if(status.alu_lock) return 0;
return status.r4216;
}
//RDMPYH
uint8 sCPU::mmio_r4217() {
if(counter.hw_math) { return 0x00; }
if(status.alu_lock) return 0;
return status.r4216 >> 8;
}

View File

@ -1,6 +1,9 @@
#include <../base.hpp>
#define SCPU_CPP
#include "deltaqueue.cpp"
deltaqueue delta;
#include "core/core.cpp"
#include "dma/dma.cpp"
#include "memory/memory.cpp"
@ -35,7 +38,7 @@ void sCPU::reset() {
event.wai = false;
event.irq = false;
event.irq_vector = 0xfffc; //reset vector address
event.irq_vector = 0xfffc; //reset vector address
mmio_reset();
dma_reset();

View File

@ -12,31 +12,15 @@ public:
bool wai;
bool irq;
uint16 irq_vector;
unsigned cycle_edge;
} event;
enum DmaState { DmaInactive, DmaRun, DmaCpuSync };
struct {
unsigned nmi_hold;
unsigned irq_hold;
unsigned nmi_fire;
unsigned irq_fire;
unsigned irq_delay;
unsigned hw_math;
alwaysinline void set(uint &ctr, uint clocks) {
if(clocks >= ctr) { ctr = clocks; }
}
alwaysinline void sub(uint &ctr, uint clocks) {
if(ctr >= clocks) {
ctr -= clocks;
} else {
ctr = 0;
}
}
} counter;
enum DMA_State { DMA_Inactive, DMA_Run, DMA_CPUsync };
unsigned alu_mul_delay;
unsigned alu_div_delay;
} temp_;
struct {
//core
@ -47,34 +31,30 @@ public:
unsigned line_clocks;
//timing
bool dram_refreshed;
uint16 dram_refresh_position;
bool hdmainit_triggered;
uint16 hdmainit_trigger_position;
bool hdma_triggered;
uint16 irq_delay;
bool irq_lock;
bool alu_lock;
unsigned dram_refresh_position;
bool nmi_valid;
bool nmi_line;
bool nmi_transition;
bool nmi_pending;
unsigned nmi_hold;
uint16 virq_trigger_pos, hirq_trigger_pos;
bool irq_valid;
bool irq_line;
bool irq_transition;
bool irq_pending;
unsigned irq_hold;
//dma
unsigned dma_counter;
unsigned dma_clocks;
bool dma_pending;
bool hdma_pending;
bool hdma_mode; //0 = init, 1 = run
DMA_State dma_state;
bool hdma_mode; //0 = init, 1 = run
DmaState dma_state;
//mmio

View File

@ -0,0 +1,27 @@
#ifdef SCPU_CPP
void sCPU::queue_event(unsigned id) {
switch(id) {
case EventIrqLockRelease: {
status.irq_lock = false;
} break;
case EventAluLockRelease: {
status.alu_lock = false;
} break;
case EventDramRefresh: {
add_clocks(40);
} break;
case EventHdmaInit: {
event.cycle_edge |= EventFlagHdmaInit;
} break;
case EventHdmaRun: {
event.cycle_edge |= EventFlagHdmaRun;
} break;
}
}
#endif //ifdef SCPU_CPP

View File

@ -21,21 +21,21 @@ alwaysinline void sCPU::poll_interrupts() {
uint16_t vpos, hpos;
//NMI hold
if(counter.nmi_hold) {
counter.nmi_hold -= 2;
if(counter.nmi_hold == 0) {
if(status.nmi_hold) {
status.nmi_hold -= 2;
if(status.nmi_hold == 0) {
if(status.nmi_enabled == true) status.nmi_transition = true;
}
}
//NMI test
vpos = ppucounter.vcounter(2);
hpos = ppucounter.hcounter(2);
vpos = ppu.vcounter(2);
hpos = ppu.hcounter(2);
bool nmi_valid = (vpos >= (!ppu.overscan() ? 225 : 240));
if(status.nmi_valid == false && nmi_valid == true) {
//0->1 edge sensitive transition
status.nmi_line = true;
counter.nmi_hold = 4;
status.nmi_hold = 4;
} else if(status.nmi_valid == true && nmi_valid == false) {
//1->0 edge sensitive transition
status.nmi_line = false;
@ -43,14 +43,14 @@ alwaysinline void sCPU::poll_interrupts() {
status.nmi_valid = nmi_valid;
//IRQ hold
if(counter.irq_hold) counter.irq_hold -= 2;
if(status.irq_line == true && counter.irq_hold == 0) {
if(status.irq_hold) status.irq_hold -= 2;
if(status.irq_line == true && status.irq_hold == 0) {
if(status.virq_enabled == true || status.hirq_enabled == true) status.irq_transition = true;
}
//IRQ test
vpos = ppucounter.vcounter(10);
hpos = ppucounter.hcounter(10);
vpos = ppu.vcounter(10);
hpos = ppu.hcounter(10);
bool irq_valid = (status.virq_enabled == true || status.hirq_enabled == true);
if(irq_valid == true) {
if(status.virq_enabled == true && vpos != status.virq_trigger_pos) irq_valid = false;
@ -59,7 +59,7 @@ alwaysinline void sCPU::poll_interrupts() {
if(status.irq_valid == false && irq_valid == true) {
//0->1 edge sensitive transition
status.irq_line = true;
counter.irq_hold = 4;
status.irq_hold = 4;
}
status.irq_valid = irq_valid;
}
@ -88,7 +88,8 @@ void sCPU::nmitimen_update(uint8 data) {
}
update_interrupts();
counter.set(counter.irq_delay, 2);
status.irq_lock = true;
delta.enqueue(EventIrqLockRelease, 2);
}
void sCPU::hvtime_update(uint16 addr) {
@ -97,7 +98,7 @@ void sCPU::hvtime_update(uint16 addr) {
bool sCPU::rdnmi() {
bool result = status.nmi_line;
if(counter.nmi_hold == 0) {
if(status.nmi_hold == 0) {
status.nmi_line = false;
}
return result;
@ -105,7 +106,7 @@ bool sCPU::rdnmi() {
bool sCPU::timeup() {
bool result = status.irq_line;
if(counter.irq_hold == 0) {
if(status.irq_hold == 0) {
status.irq_line = false;
status.irq_transition = false;
}

View File

@ -1,24 +1,18 @@
#ifdef SCPU_CPP
#include "event.cpp"
#include "irq.cpp"
#include "joypad.cpp"
unsigned sCPU::dma_counter() {
return (status.dma_counter + ppucounter.hcounter()) & 7;
return (status.dma_counter + ppu.hcounter()) & 7;
}
void sCPU::add_clocks(unsigned clocks) {
if(status.dram_refreshed == false) {
if(ppucounter.hcounter() + clocks >= status.dram_refresh_position) {
status.dram_refreshed = true;
clocks += 40;
}
}
counter.sub(counter.irq_delay, clocks);
delta.tick(clocks);
unsigned ticks = clocks >> 1;
while(ticks--) {
ppucounter.tick();
ppu.tick();
snes.input.tick();
poll_interrupts();
}
@ -28,62 +22,59 @@ void sCPU::add_clocks(unsigned clocks) {
void sCPU::scanline() {
status.dma_counter = (status.dma_counter + status.line_clocks) & 7;
status.line_clocks = ppucounter.lineclocks();
if(ppucounter.vcounter() == 0) frame();
status.line_clocks = ppu.lineclocks();
if(ppu.vcounter() == 0) {
//hdma init triggers once every frame
delta.enqueue(EventHdmaInit, cpu_version == 1 ? 12 + 8 - dma_counter() : 12 + dma_counter());
}
//dram refresh occurs once every scanline
status.dram_refreshed = false;
if(cpu_version == 2) status.dram_refresh_position = 530 + 8 - dma_counter();
delta.enqueue(EventDramRefresh, status.dram_refresh_position);
//hdma triggers once every visible scanline
status.hdma_triggered = (ppucounter.vcounter() <= (ppu.overscan() == false ? 224 : 239)) ? false : true;
if(ppu.vcounter() <= (ppu.overscan() == false ? 224 : 239)) {
delta.enqueue(EventHdmaRun, 1104);
}
update_interrupts();
if(status.auto_joypad_poll == true && ppucounter.vcounter() == (ppu.overscan() == false ? 227 : 242)) {
if(status.auto_joypad_poll == true && ppu.vcounter() == (ppu.overscan() == false ? 227 : 242)) {
snes.input.poll();
run_auto_joypad_poll();
}
}
void sCPU::frame() {
status.hdmainit_triggered = false;
if(cpu_version == 1) {
status.hdmainit_trigger_position = 12 + 8 - dma_counter();
} else {
status.hdmainit_trigger_position = 12 + dma_counter();
}
}
//used for H/DMA bus synchronization
void sCPU::precycle_edge() {
if(status.dma_state == DMA_CPUsync) {
if(status.dma_state == DmaCpuSync) {
add_clocks(status.clock_count - (status.dma_clocks % status.clock_count));
status.dma_state = DMA_Inactive;
status.dma_state = DmaInactive;
}
}
//used to test for H/DMA, which can trigger on the edge of every opcode cycle.
void sCPU::cycle_edge() {
if(status.hdmainit_triggered == false) {
if(ppucounter.hcounter() >= status.hdmainit_trigger_position || ppucounter.vcounter()) {
status.hdmainit_triggered = true;
hdma_init_reset();
if(hdma_enabled_channels()) {
status.hdma_pending = true;
status.hdma_mode = 0;
}
}
}
while(event.cycle_edge) {
switch(event.cycle_edge & -event.cycle_edge) { //switch on lowest bit (flag) set
case EventFlagHdmaInit: {
hdma_init_reset();
if(hdma_enabled_channels()) {
status.hdma_pending = true;
status.hdma_mode = 0;
}
} break;
if(status.hdma_triggered == false) {
if(ppucounter.hcounter() >= 1104) {
status.hdma_triggered = true;
if(hdma_active_channels()) {
status.hdma_pending = true;
status.hdma_mode = 1;
}
case EventFlagHdmaRun: {
if(hdma_active_channels()) {
status.hdma_pending = true;
status.hdma_mode = 1;
}
} break;
}
event.cycle_edge &= event.cycle_edge - 1; //clear lowest bit set
}
//H/DMA pending && DMA inactive?
@ -94,30 +85,30 @@ void sCPU::cycle_edge() {
//.. Run one bus CPU cycle
//.. CPU sync
if(status.dma_state == DMA_Run) {
if(status.dma_state == DmaRun) {
if(status.hdma_pending) {
status.hdma_pending = false;
if(hdma_enabled_channels()) {
dma_add_clocks(8 - dma_counter()); //DMA sync
dma_add_clocks(8 - dma_counter()); //DMA sync
status.hdma_mode == 0 ? hdma_init() : hdma_run();
if(!dma_enabled_channels()) status.dma_state = DMA_CPUsync;
if(!dma_enabled_channels()) status.dma_state = DmaCpuSync;
}
}
if(status.dma_pending) {
status.dma_pending = false;
if(dma_enabled_channels()) {
dma_add_clocks(8 - dma_counter()); //DMA sync
dma_add_clocks(8 - dma_counter()); //DMA sync
dma_run();
status.dma_state = DMA_CPUsync;
status.dma_state = DmaCpuSync;
}
}
}
if(status.dma_state == DMA_Inactive) {
if(status.dma_state == DmaInactive) {
if(status.dma_pending || status.hdma_pending) {
status.dma_clocks = 0;
status.dma_state = DMA_Run;
status.dma_state = DmaRun;
}
}
}
@ -125,10 +116,10 @@ void sCPU::cycle_edge() {
//used to test for NMI/IRQ, which can trigger on the edge of every opcode.
//test one cycle early to simulate two-stage pipeline of x816 CPU.
//
//status.irq_delay is used to simulate hardware delay before interrupts can
//status.irq_lock is used to simulate hardware delay before interrupts can
//trigger during certain events (immediately after DMA, writes to $4200, etc)
void sCPU::last_cycle() {
if(counter.irq_delay) return;
if(status.irq_lock) return;
status.nmi_pending |= nmi_test();
status.irq_pending |= irq_test();
@ -140,36 +131,29 @@ void sCPU::timing_power() {
}
void sCPU::timing_reset() {
counter.nmi_hold = 0;
counter.irq_hold = 0;
delta.reset();
counter.nmi_fire = 0;
counter.irq_fire = 0;
counter.irq_delay = 0;
counter.hw_math = 0;
temp_.alu_mul_delay = config::temp.alu_mul_delay;
temp_.alu_div_delay = config::temp.alu_div_delay;
status.clock_count = 0;
status.line_clocks = ppucounter.lineclocks();
status.line_clocks = ppu.lineclocks();
status.dram_refreshed = false;
status.irq_lock = false;
status.alu_lock = false;
status.dram_refresh_position = (cpu_version == 1) ? 530 : 538;
status.hdmainit_triggered = false;
status.hdmainit_trigger_position = 0;
status.hdma_triggered = false;
status.irq_delay = 0;
status.nmi_valid = false;
status.nmi_line = false;
status.nmi_transition = false;
status.nmi_pending = false;
status.nmi_hold = 0;
status.irq_valid = false;
status.irq_line = false;
status.irq_transition = false;
status.irq_pending = false;
status.irq_hold = 0;
update_interrupts();
@ -178,7 +162,9 @@ void sCPU::timing_reset() {
status.dma_pending = false;
status.hdma_pending = false;
status.hdma_mode = 0;
status.dma_state = DMA_Inactive;
status.dma_state = DmaInactive;
event.cycle_edge = 0;
}
#undef ntsc_color_burst_phase_shift_scanline

View File

@ -1,12 +1,24 @@
enum {
EventNone,
EventIrqLockRelease,
EventAluLockRelease,
EventDramRefresh,
EventHdmaInit,
EventHdmaRun,
//cycle edge
EventFlagHdmaInit = 1 << 0,
EventFlagHdmaRun = 1 << 1,
};
//timing.cpp
unsigned dma_counter();
void add_clocks(unsigned clocks);
void scanline();
void frame();
void precycle_edge();
void cycle_edge();
alwaysinline void precycle_edge();
alwaysinline void cycle_edge();
void last_cycle();
void timing_power();
@ -25,3 +37,6 @@
//joypad.cpp
void run_auto_joypad_poll();
//event.cpp
void queue_event(unsigned); //deltaqueue callback function

View File

@ -1,9 +1,9 @@
Colortable colortable;
void Colortable::set_format(Format format_) { format = format_; }
void Colortable::set_contrast(int32_t contrast_) { contrast = contrast_; }
void Colortable::set_brightness(int32_t brightness_) { brightness = brightness_; }
void Colortable::set_gamma(int32_t gamma_) { gamma = gamma_; }
void Colortable::set_contrast(signed contrast_) { contrast = contrast_; }
void Colortable::set_brightness(signed brightness_) { brightness = brightness_; }
void Colortable::set_gamma(signed gamma_) { gamma = gamma_; }
void Colortable::enable_gamma_ramp(bool value) { gamma_ramp = value; }
void Colortable::enable_sepia(bool value) { sepia = value; }
@ -11,18 +11,18 @@ void Colortable::enable_grayscale(bool value) { grayscale = value; }
void Colortable::enable_invert(bool value) { invert = value; }
void Colortable::update() {
int32_t l, r, g, b;
double kr = 0.2126, kb = 0.0722, kg = (1.0 - kr - kb); //luminance
uint32_t col;
for(unsigned i = 0; i < 32768; i++) {
//bgr555->rgb888
col = ((i & 0x001f) << 19) | ((i & 0x001c) << 14)
| ((i & 0x03e0) << 6) | ((i & 0x0380) << 1)
| ((i & 0x7c00) >> 7) | ((i & 0x7000) >> 12);
double kr = 0.2126, kb = 0.0722, kg = (1.0 - kr - kb); //luminance weights
r = (col >> 16) & 0xff;
g = (col >> 8) & 0xff;
b = (col ) & 0xff;
for(unsigned i = 0; i < 32768; i++) {
unsigned color //bgr555->rgb888 conversion
= ((i & 0x001f) << 19) | ((i & 0x001c) << 14)
| ((i & 0x03e0) << 6) | ((i & 0x0380) << 1)
| ((i & 0x7c00) >> 7) | ((i & 0x7000) >> 12);
signed l;
signed r = (color >> 16) & 0xff;
signed g = (color >> 8) & 0xff;
signed b = (color ) & 0xff;
if(gamma_ramp == true) {
r = gamma_ramp_table[r >> 3];
@ -30,17 +30,31 @@ void Colortable::update() {
b = gamma_ramp_table[b >> 3];
}
contrast_adjust(r); brightness_adjust(r); gamma_adjust(r);
contrast_adjust(g); brightness_adjust(g); gamma_adjust(g);
contrast_adjust(b); brightness_adjust(b); gamma_adjust(b);
if(contrast != 0) {
r = contrast_adjust(r);
g = contrast_adjust(g);
b = contrast_adjust(b);
}
if(brightness != 0) {
r = brightness_adjust(r);
g = brightness_adjust(g);
b = brightness_adjust(b);
}
if(gamma != 100) {
r = gamma_adjust(r);
g = gamma_adjust(g);
b = gamma_adjust(b);
}
if(sepia == true) {
l = (int32_t)((double)r * kr + (double)g * kg + (double)b * kb);
l = (signed)((double)r * kr + (double)g * kg + (double)b * kb);
l = max(0, min(255, l));
r = (int32_t)((double)l * (1.0 + 0.300));
g = (int32_t)((double)l * (1.0 - 0.055));
b = (int32_t)((double)l * (1.0 - 0.225));
r = (signed)((double)l * (1.0 + 0.300));
g = (signed)((double)l * (1.0 - 0.055));
b = (signed)((double)l * (1.0 - 0.225));
r = max(0, min(255, r));
g = max(0, min(255, g));
@ -48,7 +62,7 @@ void Colortable::update() {
}
if(grayscale == true) {
l = (int32_t)((double)r * kr + (double)g * kg + (double)b * kb);
l = (signed)((double)r * kr + (double)g * kg + (double)b * kb);
l = max(0, min(255, l));
r = g = b = l;
}
@ -79,7 +93,7 @@ void Colortable::update() {
} break;
default: {
table[i] = -1U;
table[i] = ~0;
} break;
}
}
@ -90,14 +104,17 @@ Colortable::Colortable() {
contrast = 0;
brightness = 0;
gamma = 100;
gamma_ramp = false;
sepia = false;
grayscale = false;
invert = false;
}
Colortable::~Colortable() {
delete[] table;
}
/* internal */
const uint8_t Colortable::gamma_ramp_table[32] = {
0x00, 0x01, 0x03, 0x06, 0x0a, 0x0f, 0x15, 0x1c,
0x24, 0x2d, 0x37, 0x42, 0x4e, 0x5b, 0x69, 0x78,
@ -105,19 +122,17 @@ const uint8_t Colortable::gamma_ramp_table[32] = {
0xc8, 0xd0, 0xd8, 0xe0, 0xe8, 0xf0, 0xf8, 0xff,
};
void Colortable::contrast_adjust(int32_t &input) {
double lmin = 0.0 - (double)contrast;
double lmax = 255.0 + (double)contrast;
int32_t result = (int32_t)(lmin + (double)input * ((lmax - lmin) / 256.0));
input = max(0, min(255, result));
uint8_t Colortable::contrast_adjust(uint8_t input) {
signed result = input - contrast + (2 * contrast * input + 127) / 255;
return max(0, min(255, result));
}
void Colortable::brightness_adjust(int32_t &input) {
int32_t result = input + brightness;
input = max(0, min(255, result));
uint8_t Colortable::brightness_adjust(uint8_t input) {
signed result = input + brightness;
return max(0, min(255, result));
}
void Colortable::gamma_adjust(int32_t &input) {
int32_t result = (int32_t)(pow(((double)(input + 1) / 256.0), (double)gamma / 100.0) * 256.0);
input = max(0, min(255, result));
uint8_t Colortable::gamma_adjust(uint8_t input) {
signed result = (signed)(pow(((double)input / 255.0), (double)gamma / 100.0) * 255.0 + 0.5);
return max(0, min(255, result));
}

View File

@ -9,9 +9,9 @@ public:
const inline uint32_t operator[](uint16_t index) const { return table[index]; }
void set_format(Format);
void set_contrast(int32_t);
void set_brightness(int32_t);
void set_gamma(int32_t);
void set_contrast(signed);
void set_brightness(signed);
void set_gamma(signed);
void enable_gamma_ramp(bool);
void enable_sepia(bool);
void enable_grayscale(bool);
@ -26,9 +26,9 @@ private:
uint32_t *table;
Format format;
int32_t contrast;
int32_t brightness;
int32_t gamma;
signed contrast;
signed brightness;
signed gamma;
bool gamma_ramp;
bool sepia;
@ -36,9 +36,9 @@ private:
bool invert;
static const uint8_t gamma_ramp_table[32];
void contrast_adjust(int32_t &input);
void brightness_adjust(int32_t &input);
void gamma_adjust(int32_t &input);
uint8_t contrast_adjust(uint8_t input);
uint8_t brightness_adjust(uint8_t input);
uint8_t gamma_adjust(uint8_t input);
};
extern Colortable colortable;

View File

@ -198,7 +198,7 @@ private:
buffer_offset = file_offset & ~buffer_mask;
fseek(fp, buffer_offset, SEEK_SET);
unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask);
if(length) fread(buffer, 1, length, fp);
if(length) unsigned unused = fread(buffer, 1, length, fp);
}
}
@ -209,7 +209,7 @@ private:
if(buffer_dirty == false) return; //buffer unmodified since read
fseek(fp, buffer_offset, SEEK_SET);
unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask);
if(length) fwrite(buffer, 1, length, fp);
if(length) unsigned unused = fwrite(buffer, 1, length, fp);
buffer_offset = -1; //invalidate buffer
buffer_dirty = false;
}

View File

@ -107,20 +107,20 @@ static const char* input_find(uint16_t key) {
static char buffer[64];
for(unsigned j = 0; j < 16; j++) {
if(key == joypad<>::index(j, joypad<>::up)) { sprintf(buffer, "joypad%0.2d.up", j); return buffer; }
if(key == joypad<>::index(j, joypad<>::down)) { sprintf(buffer, "joypad%0.2d.down", j); return buffer; }
if(key == joypad<>::index(j, joypad<>::left)) { sprintf(buffer, "joypad%0.2d.left", j); return buffer; }
if(key == joypad<>::index(j, joypad<>::right)) { sprintf(buffer, "joypad%0.2d.right", j); return buffer; }
if(key == joypad<>::index(j, joypad<>::up)) { sprintf(buffer, "joypad%.2d.up", j); return buffer; }
if(key == joypad<>::index(j, joypad<>::down)) { sprintf(buffer, "joypad%.2d.down", j); return buffer; }
if(key == joypad<>::index(j, joypad<>::left)) { sprintf(buffer, "joypad%.2d.left", j); return buffer; }
if(key == joypad<>::index(j, joypad<>::right)) { sprintf(buffer, "joypad%.2d.right", j); return buffer; }
if(key >= joypad<>::index(j, joypad<>::axis + 0)
&& key < joypad<>::index(j, joypad<>::axis + joypad<>::axes)) {
sprintf(buffer, "joypad%0.2d.axis%0.2d", j, key - joypad<>::index(j, joypad<>::axis));
sprintf(buffer, "joypad%.2d.axis%.2d", j, key - joypad<>::index(j, joypad<>::axis));
return buffer;
}
if(key >= joypad<>::index(j, joypad<>::button + 0)
&& key < joypad<>::index(j, joypad<>::button + joypad<>::buttons)) {
sprintf(buffer, "joypad%0.2d.button%0.2d", j, key - joypad<>::index(j, joypad<>::button));
sprintf(buffer, "joypad%.2d.button%.2d", j, key - joypad<>::index(j, joypad<>::button));
return buffer;
}
}

View File

@ -69,6 +69,7 @@ public:
string& operator=(const char *str);
string& operator=(const string &str);
string& operator<<(int num);
string& operator<<(double num);
string& operator<<(const char *str);
string& operator<<(const string& str);
@ -89,7 +90,7 @@ public:
typedef vector<string> lstring;
} //namespace nall
} //namespace nall
size_t count(nall::lstring&);
int find(nall::lstring &str, const char *key);
@ -117,4 +118,4 @@ nall::string& ltrim_once(nall::string &str, const char *key = " ");
nall::string& rtrim_once(nall::string &str, const char *key = " ");
nall::string& trim_once (nall::string &str, const char *key = " ");
#endif //ifndef NALL_STRING_HPP
#endif //ifndef NALL_STRING_HPP

View File

@ -68,6 +68,12 @@ string& string::operator<<(int num) {
return *this;
}
string& string::operator<<(double num) {
string temp(num);
strcat(*this, temp);
return *this;
}
string& string::operator<<(const char *str) {
strcat(*this, str);
return *this;
@ -208,13 +214,13 @@ bool fread(nall::string &str, const char *filename) {
#else
FILE *fp = _wfopen(nall::utf16(filename), L"rb");
#endif
if(!fp)return false;
if(!fp) return false;
fseek(fp, 0, SEEK_END);
size_t size = ftell(fp);
rewind(fp);
char *fdata = (char*)malloc(size + 1);
fread(fdata, 1, size, fp);
unsigned unused = fread(fdata, 1, size, fp);
fclose(fp);
fdata[size] = 0;
strcpy(str, fdata);
@ -223,4 +229,4 @@ bool fread(nall::string &str, const char *filename) {
return true;
}
#endif //ifdef NALL_STRING_CPP
#endif //ifdef NALL_STRING_CPP

View File

@ -96,4 +96,4 @@ bool striend(const char *str, const char *key) {
return true;
}
#endif //ifdef NALL_STRING_CPP
#endif //ifdef NALL_STRING_CPP

View File

@ -24,7 +24,7 @@ char* strtr(char *dest, const char *before, const char *after) {
if(!dest || !before || !after) return dest;
int sl = strlen(dest), bsl = strlen(before), asl = strlen(after);
if(bsl != asl || bsl == 0) return dest; //patterns must be the same length for 1:1 replace
if(bsl != asl || bsl == 0) return dest; //patterns must be the same length for 1:1 replace
for(unsigned i = 0; i < sl; i++) {
for(unsigned l = 0; l < bsl; l++) {
if(dest[i] == before[l]) {
@ -62,7 +62,7 @@ uintmax_t strhex(const char *str) {
if(x >= '0' && x <= '9') x -= '0';
else if(x >= 'A' && x <= 'F') x -= 'A' - 10;
else if(x >= 'a' && x <= 'f') x -= 'a' - 10;
else break; //stop at first invalid character
else break; //stop at first invalid character
result = result * 16 + x;
}
@ -83,7 +83,7 @@ intmax_t strdec(const char *str) {
while(*str) {
uint8_t x = *str++;
if(x >= '0' && x <= '9') x -= '0';
else break; //stop at first invalid character
else break; //stop at first invalid character
result = result * 10 + x;
}
@ -101,7 +101,7 @@ uintmax_t strbin(const char *str) {
while(*str) {
uint8_t x = *str++;
if(x == '0' || x == '1') x -= '0';
else break; //stop at first invalid character
else break; //stop at first invalid character
result = result * 2 + x;
}
@ -122,8 +122,8 @@ double strdouble(const char *str) {
while(*str) {
uint8_t x = *str++;
if(x >= '0' && x <= '9') x -= '0';
else if(x == '.') break; //break loop and read fractional part
else return (double)result_integral; //invalid value, assume no fractional part
else if(x == '.') break; //break loop and read fractional part
else return (double)result_integral; //invalid value, assume no fractional part
result_integral = result_integral * 10 + x;
}
@ -131,7 +131,7 @@ double strdouble(const char *str) {
while(*str) {
uint8_t x = *str++;
if(x >= '0' && x <= '9') x -= '0';
else break; //stop at first invalid character
else break; //stop at first invalid character
result_fractional = result_fractional * 10 + x;
}
@ -144,7 +144,7 @@ double strdouble(const char *str) {
}
size_t strhex(char *str, uintmax_t value, size_t length /* = 0 */) {
if(!length) length -= 1U; //"infinite" length
if(length == 0) length -= 1U; //"infinite" length
size_t initial_length = length;
//count number of digits in value
@ -153,23 +153,23 @@ size_t strhex(char *str, uintmax_t value, size_t length /* = 0 */) {
while(digits_integral_ /= 16) digits_integral++;
int digits = digits_integral;
if(!str) return digits + 1; //only computing required length?
if(!str) return digits + 1; //only computing required length?
length = nall::min(digits, length - 1);
str += length; //seek to end of target string
*str = 0; //set null terminator
str += length; //seek to end of target string
*str = 0; //set null terminator
while(length--) {
uint8_t x = value % 16;
value /= 16;
*--str = x < 10 ? (x + '0') : (x + 'a' - 10); //iterate backwards to write string
*--str = x < 10 ? (x + '0') : (x + 'a' - 10); //iterate backwards to write string
}
return nall::min(initial_length, digits + 1);
}
size_t strdec(char *str, intmax_t value_, size_t length /* = 0 */) {
if(!length) length = -1U; //"infinite" length
if(length == 0) length = -1U; //"infinite" length
size_t initial_length = length;
bool negate = value_ < 0;
@ -181,15 +181,15 @@ size_t strdec(char *str, intmax_t value_, size_t length /* = 0 */) {
while(digits_integral_ /= 10) digits_integral++;
int digits = (negate ? 1 : 0) + digits_integral;
if(!str) return digits + 1; //only computing required length?
if(!str) return digits + 1; //only computing required length?
length = nall::min(digits, length - 1);
str += length; //seek to end of target string
*str = 0; //set null terminator
str += length; //seek to end of target string
*str = 0; //set null terminator
while(length && digits_integral--) {
uint8_t x = '0' + (value % 10);
value /= 10;
*--str = x; //iterate backwards to write string
*--str = x; //iterate backwards to write string
length--;
}
@ -201,7 +201,7 @@ size_t strdec(char *str, intmax_t value_, size_t length /* = 0 */) {
}
size_t strbin(char *str, uintmax_t value, size_t length /* = 0 */) {
if(!length) length = -1U; //"infinite" length
if(length == 0) length = -1U; //"infinite" length
size_t initial_length = length;
//count number of digits in value
@ -210,79 +210,46 @@ size_t strbin(char *str, uintmax_t value, size_t length /* = 0 */) {
while(digits_integral_ /= 2) digits_integral++;
int digits = digits_integral;
if(!str) return digits + 1; //only computing required length?
if(!str) return digits + 1; //only computing required length?
length = nall::min(digits, length - 1);
str += length; //seek to end of target string
*str = 0; //set null terminator
str += length; //seek to end of target string
*str = 0; //set null terminator
while(length--) {
uint8_t x = '0' + (value % 2);
value /= 2;
*--str = x; //iterate backwards to write string
*--str = x; //iterate backwards to write string
}
return nall::min(initial_length, digits + 1);
}
//using sprintf is certainly not the most ideal method to convert
//a double to a string ... but attempting to parse a double by
//hand, digit-by-digit, results in subtle rounding errors.
//
//note: length parameter is currently ignored.
//it remains for consistency and possible future support.
size_t strdouble(char *str, double value, size_t length /* = 0 */) {
if(!length) length = -1U; //"infinite" length
size_t initial_length = length;
char buffer[256];
sprintf(buffer, "%f", value);
double fractional, integral;
fractional = modf(value, &integral);
uintmax_t value_integral = (uintmax_t)integral;
uintmax_t value_fractional = 0;
//convert fractional portion to integral number (eg 0.275 -> 275)
//six nibbles of precision, one nibble for rounding
for(int i = 0; i < 7; i++) {
fractional *= 10.0;
value_fractional = value_fractional * 10 + ((uintmax_t)fractional % 10);
//remove excess 0's in fraction (2.500000 -> 2.5)
for(char *p = buffer; *p; p++) {
if(*p == '.') {
char *p = buffer + strlen(buffer) - 1;
while(*p == '0') {
if(*(p - 1) != '.') *p = 0; //... but not for eg 1.0 -> 1.
p--;
}
break;
}
}
//use seventh nibble to round fraction
value_fractional = (uintmax_t)((double)value_fractional / 10.0 + 0.5);
//cull fractional zero nibbles (eg 275000 -> 275)
while(value_fractional && !(value_fractional % 10)) value_fractional /= 10;
//count number of digits in integral value
int digits_integral = 1;
uintmax_t digits_integral_ = value_integral;
while(digits_integral_ /= 10) digits_integral++;
//count number of digits in fractional value
int digits_fractional = 1;
uintmax_t digits_fractional_ = value_fractional;
while(digits_fractional_ /= 10) digits_fractional++;
int digits = digits_integral + 1 + digits_fractional; //integral '.' fractional
if(!str) return digits + 1; //only computing required length?
length = nall::min(digits, length - 1);
str += length; //seek to end of target string
*str = 0; //set null terminator
while(length && digits_fractional--) {
uint8_t x = '0' + (value_fractional % 10);
value_fractional /= 10;
*--str = x; //iterate backwards to write string
length--;
}
if(length) {
*--str = '.';
length--;
}
while(length-- && digits_integral--) {
uint8_t x = '0' + (value_integral % 10);
value_integral /= 10;
*--str = x; //interate backwards to write string
}
return nall::min(initial_length, digits + 1);
length = strlen(buffer);
if(str) strcpy(str, buffer);
return length + 1;
}
#endif //ifdef NALL_STRING_CPP
#endif //ifdef NALL_STRING_CPP

View File

@ -68,4 +68,4 @@ bool match(const char *p, const char *s) {
}
}
#endif //ifdef NALL_STRING_CPP
#endif //ifdef NALL_STRING_CPP

View File

@ -156,4 +156,4 @@ bool strmath(const char *s, int &result) {
}
}
#endif //ifdef NALL_STRING_CPP
#endif //ifdef NALL_STRING_CPP

View File

@ -87,4 +87,4 @@ nall::string &qreplace(nall::string &str, const char *key, const char *token) {
return str;
}
#endif //ifdef NALL_STRING_CPP
#endif //ifdef NALL_STRING_CPP

View File

@ -48,4 +48,4 @@ void qsplit(nall::lstring &dest, const char *key, const char *src, size_t limit)
strcpy(dest[split_count++], src + lp);
}
#endif //ifdef NALL_STRING_CPP
#endif //ifdef NALL_STRING_CPP

View File

@ -44,4 +44,4 @@ size_t strlcat(char *dest, const char *src, size_t length) {
return dlength + (s - src); //return length of resulting string, sans null terminator
}
#endif //ifdef NALL_STRING_CPP
#endif //ifdef NALL_STRING_CPP

View File

@ -32,4 +32,4 @@ char* trim_once(char *str, const char *key) {
return ltrim_once(rtrim_once(str, key), key);
}
#endif //ifdef NALL_STRING_CPP
#endif //ifdef NALL_STRING_CPP

View File

@ -61,7 +61,7 @@ public:
void sample(uint16_t sl, uint16_t sr) {
uint32_t sample = sl + (sr << 16);
write(device.fd, &sample, 4);
unsigned unused = write(device.fd, &sample, 4);
}
bool init() {

View File

@ -2,8 +2,7 @@
//SDL input driver
//================
//Keyboard and mouse are controlled directly via Xlib,
//as SDL cannot capture input from windows it does not
//create itself.
//as SDL cannot capture input from windows it does not create itself.
//SDL is used only to handle joysticks.
#include <SDL/SDL.h>
@ -20,14 +19,15 @@ using namespace nall;
class pInputSDL {
public:
#include "xlibkeys.hpp"
InputSDL &self;
Display *display;
Window rootwindow;
unsigned screenwidth, screenheight;
unsigned relativex, relativey;
bool mouseacquired;
Cursor InvisibleCursor;
SDL_Joystick *gamepad[joypad<>::count];
bool mouseacquired;
struct {
//mouse device settings
@ -111,130 +111,14 @@ public:
//Keyboard
//========
#define key(n) (bool)(state[n >> 3] & (1 << (n & 7)))
{
char state[32];
XQueryKeymap(display, state);
char state[32];
XQueryKeymap(display, state);
table[keyboard::escape] = key(0x09);
table[keyboard::f1 ] = key(0x43);
table[keyboard::f2 ] = key(0x44);
table[keyboard::f3 ] = key(0x45);
table[keyboard::f4 ] = key(0x46);
table[keyboard::f5 ] = key(0x47);
table[keyboard::f6 ] = key(0x48);
table[keyboard::f7 ] = key(0x49);
table[keyboard::f8 ] = key(0x4a);
table[keyboard::f9 ] = key(0x4b);
table[keyboard::f10] = key(0x4c);
table[keyboard::f11] = key(0x5f);
table[keyboard::f12] = key(0x60);
table[keyboard::print_screen] = key(0x6f);
table[keyboard::scroll_lock ] = key(0x4e);
table[keyboard::pause ] = key(0x6e);
table[keyboard::tilde] = key(0x31);
table[keyboard::num_0] = key(0x0a);
table[keyboard::num_1] = key(0x0b);
table[keyboard::num_2] = key(0x0c);
table[keyboard::num_3] = key(0x0d);
table[keyboard::num_4] = key(0x0e);
table[keyboard::num_5] = key(0x0f);
table[keyboard::num_6] = key(0x10);
table[keyboard::num_7] = key(0x11);
table[keyboard::num_8] = key(0x12);
table[keyboard::num_9] = key(0x13);
table[keyboard::dash ] = key(0x14);
table[keyboard::equal ] = key(0x15);
table[keyboard::backspace] = key(0x16);
table[keyboard::insert ] = key(0x6a);
table[keyboard::delete_ ] = key(0x6b);
table[keyboard::home ] = key(0x61);
table[keyboard::end ] = key(0x67);
table[keyboard::page_up ] = key(0x63);
table[keyboard::page_down] = key(0x69);
table[keyboard::a] = key(0x26);
table[keyboard::b] = key(0x38);
table[keyboard::c] = key(0x36);
table[keyboard::d] = key(0x28);
table[keyboard::e] = key(0x1a);
table[keyboard::f] = key(0x29);
table[keyboard::g] = key(0x2a);
table[keyboard::h] = key(0x2b);
table[keyboard::i] = key(0x1f);
table[keyboard::j] = key(0x2c);
table[keyboard::k] = key(0x2d);
table[keyboard::l] = key(0x2e);
table[keyboard::m] = key(0x3a);
table[keyboard::n] = key(0x39);
table[keyboard::o] = key(0x20);
table[keyboard::p] = key(0x21);
table[keyboard::q] = key(0x18);
table[keyboard::r] = key(0x1b);
table[keyboard::s] = key(0x27);
table[keyboard::t] = key(0x1c);
table[keyboard::u] = key(0x1e);
table[keyboard::v] = key(0x37);
table[keyboard::w] = key(0x19);
table[keyboard::x] = key(0x35);
table[keyboard::y] = key(0x1d);
table[keyboard::z] = key(0x34);
table[keyboard::lbracket ] = key(0x22);
table[keyboard::rbracket ] = key(0x23);
table[keyboard::backslash ] = key(0x33);
table[keyboard::semicolon ] = key(0x2f);
table[keyboard::apostrophe] = key(0x30);
table[keyboard::comma ] = key(0x3b);
table[keyboard::period ] = key(0x3c);
table[keyboard::slash ] = key(0x3d);
table[keyboard::pad_0] = key(0x5a);
table[keyboard::pad_1] = key(0x57);
table[keyboard::pad_2] = key(0x58);
table[keyboard::pad_3] = key(0x59);
table[keyboard::pad_4] = key(0x53);
table[keyboard::pad_5] = key(0x54);
table[keyboard::pad_6] = key(0x55);
table[keyboard::pad_7] = key(0x4f);
table[keyboard::pad_8] = key(0x50);
table[keyboard::pad_9] = key(0x51);
table[keyboard::add ] = key(0x56);
table[keyboard::subtract] = key(0x52);
table[keyboard::multiply] = key(0x3f);
table[keyboard::divide ] = key(0x70);
table[keyboard::enter ] = key(0x6c);
table[keyboard::num_lock ] = key(0x4d);
table[keyboard::caps_lock] = key(0x42);
table[keyboard::up ] = key(0x62);
table[keyboard::down ] = key(0x68);
table[keyboard::left ] = key(0x64);
table[keyboard::right] = key(0x66);
table[keyboard::tab ] = key(0x17);
table[keyboard::return_ ] = key(0x24);
table[keyboard::spacebar] = key(0x41);
table[keyboard::lctrl ] = key(0x25);
table[keyboard::rctrl ] = key(0x6d);
table[keyboard::lalt ] = key(0x40);
table[keyboard::ralt ] = key(0x71);
table[keyboard::lshift] = key(0x32);
table[keyboard::rshift] = key(0x3e);
table[keyboard::lsuper] = key(0x73);
table[keyboard::rsuper] = key(0x74);
table[keyboard::menu ] = key(0x75);
for(unsigned i = 0; i < keyboard::limit; i++) {
uint8_t code = keycode[i];
if(code == 0) continue; //unmapped
table[i] = (bool)(state[code >> 3] & (1 << (code & 7)));
}
#undef key
//=====
//Mouse
@ -315,6 +199,7 @@ public:
}
bool init() {
init_keycodes();
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
SDL_JoystickEventState(SDL_IGNORE);

View File

@ -3,7 +3,7 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
namespace ruby {
#include "x.hpp"
@ -12,6 +12,7 @@ class pInputX {
public:
InputX &self;
Display *display;
#include "xlibkeys.hpp"
bool cap(Input::Setting setting) {
if(setting == Input::KeyboardSupport) return true;
@ -29,133 +30,20 @@ public:
bool poll(int16_t *table) {
memset(table, 0, input_limit * sizeof(int16_t));
#define key(n) (bool)(state[n >> 3] & (1 << (n & 7)))
char state[32];
XQueryKeymap(display, state);
table[keyboard::escape] = key(0x09);
table[keyboard::f1 ] = key(0x43);
table[keyboard::f2 ] = key(0x44);
table[keyboard::f3 ] = key(0x45);
table[keyboard::f4 ] = key(0x46);
table[keyboard::f5 ] = key(0x47);
table[keyboard::f6 ] = key(0x48);
table[keyboard::f7 ] = key(0x49);
table[keyboard::f8 ] = key(0x4a);
table[keyboard::f9 ] = key(0x4b);
table[keyboard::f10] = key(0x4c);
table[keyboard::f11] = key(0x5f);
table[keyboard::f12] = key(0x60);
table[keyboard::print_screen] = key(0x6f);
table[keyboard::scroll_lock ] = key(0x4e);
table[keyboard::pause ] = key(0x6e);
table[keyboard::tilde] = key(0x31);
table[keyboard::num_0] = key(0x0a);
table[keyboard::num_1] = key(0x0b);
table[keyboard::num_2] = key(0x0c);
table[keyboard::num_3] = key(0x0d);
table[keyboard::num_4] = key(0x0e);
table[keyboard::num_5] = key(0x0f);
table[keyboard::num_6] = key(0x10);
table[keyboard::num_7] = key(0x11);
table[keyboard::num_8] = key(0x12);
table[keyboard::num_9] = key(0x13);
table[keyboard::dash ] = key(0x14);
table[keyboard::equal ] = key(0x15);
table[keyboard::backspace] = key(0x16);
table[keyboard::insert ] = key(0x6a);
table[keyboard::delete_ ] = key(0x6b);
table[keyboard::home ] = key(0x61);
table[keyboard::end ] = key(0x67);
table[keyboard::page_up ] = key(0x63);
table[keyboard::page_down] = key(0x69);
table[keyboard::a] = key(0x26);
table[keyboard::b] = key(0x38);
table[keyboard::c] = key(0x36);
table[keyboard::d] = key(0x28);
table[keyboard::e] = key(0x1a);
table[keyboard::f] = key(0x29);
table[keyboard::g] = key(0x2a);
table[keyboard::h] = key(0x2b);
table[keyboard::i] = key(0x1f);
table[keyboard::j] = key(0x2c);
table[keyboard::k] = key(0x2d);
table[keyboard::l] = key(0x2e);
table[keyboard::m] = key(0x3a);
table[keyboard::n] = key(0x39);
table[keyboard::o] = key(0x20);
table[keyboard::p] = key(0x21);
table[keyboard::q] = key(0x18);
table[keyboard::r] = key(0x1b);
table[keyboard::s] = key(0x27);
table[keyboard::t] = key(0x1c);
table[keyboard::u] = key(0x1e);
table[keyboard::v] = key(0x37);
table[keyboard::w] = key(0x19);
table[keyboard::x] = key(0x35);
table[keyboard::y] = key(0x1d);
table[keyboard::z] = key(0x34);
table[keyboard::lbracket ] = key(0x22);
table[keyboard::rbracket ] = key(0x23);
table[keyboard::backslash ] = key(0x33);
table[keyboard::semicolon ] = key(0x2f);
table[keyboard::apostrophe] = key(0x30);
table[keyboard::comma ] = key(0x3b);
table[keyboard::period ] = key(0x3c);
table[keyboard::slash ] = key(0x3d);
table[keyboard::pad_0] = key(0x5a);
table[keyboard::pad_1] = key(0x57);
table[keyboard::pad_2] = key(0x58);
table[keyboard::pad_3] = key(0x59);
table[keyboard::pad_4] = key(0x53);
table[keyboard::pad_5] = key(0x54);
table[keyboard::pad_6] = key(0x55);
table[keyboard::pad_7] = key(0x4f);
table[keyboard::pad_8] = key(0x50);
table[keyboard::pad_9] = key(0x51);
table[keyboard::add ] = key(0x56);
table[keyboard::subtract] = key(0x52);
table[keyboard::multiply] = key(0x3f);
table[keyboard::divide ] = key(0x70);
table[keyboard::enter ] = key(0x6c);
table[keyboard::num_lock ] = key(0x4d);
table[keyboard::caps_lock] = key(0x42);
table[keyboard::up ] = key(0x62);
table[keyboard::down ] = key(0x68);
table[keyboard::left ] = key(0x64);
table[keyboard::right] = key(0x66);
table[keyboard::tab ] = key(0x17);
table[keyboard::return_ ] = key(0x24);
table[keyboard::spacebar] = key(0x41);
table[keyboard::lctrl ] = key(0x25);
table[keyboard::rctrl ] = key(0x6d);
table[keyboard::lalt ] = key(0x40);
table[keyboard::ralt ] = key(0x71);
table[keyboard::lshift] = key(0x32);
table[keyboard::rshift] = key(0x3e);
table[keyboard::lsuper] = key(0x73);
table[keyboard::rsuper] = key(0x74);
table[keyboard::menu ] = key(0x75);
#undef key
for(unsigned i = 0; i < keyboard::limit; i++) {
uint8_t code = keycode[i];
if(code == 0) continue; //unmapped
table[i] = (bool)(state[code >> 3] & (1 << (code & 7)));
}
return true;
}
bool init() {
init_keycodes();
display = XOpenDisplay(0);
return true;
}

View File

@ -0,0 +1,138 @@
//shared keycode lookup table + initialization routine:
//#include inside a class interface to use
//Xlib keycodes for each key can vary between platforms, so this header file
//will lookup keycodes from static keysyms, and map them to nall/input.hpp's
//keyboard identifiers.
//
//this allows input capture routine to iterate quickly over all keycodes and
//map their states to ruby's input state table.
uint8_t keycode[256];
bool init_keycodes() {
Display *display = XOpenDisplay(0);
memset(&keycode, 0, sizeof keycode);
#define assign(x, y) keycode[x] = XKeysymToKeycode(display, y)
assign(keyboard::escape, XK_Escape);
assign(keyboard::f1, XK_F1);
assign(keyboard::f2, XK_F2);
assign(keyboard::f3, XK_F3);
assign(keyboard::f4, XK_F4);
assign(keyboard::f5, XK_F5);
assign(keyboard::f6, XK_F6);
assign(keyboard::f7, XK_F7);
assign(keyboard::f8, XK_F8);
assign(keyboard::f9, XK_F9);
assign(keyboard::f10, XK_F10);
assign(keyboard::f11, XK_F11);
assign(keyboard::f12, XK_F12);
//assign(keyboard::print_screen, XK_???);
assign(keyboard::scroll_lock, XK_Scroll_Lock);
assign(keyboard::pause, XK_Pause);
assign(keyboard::tilde, XK_asciitilde);
assign(keyboard::num_0, XK_0);
assign(keyboard::num_1, XK_1);
assign(keyboard::num_2, XK_2);
assign(keyboard::num_3, XK_3);
assign(keyboard::num_4, XK_4);
assign(keyboard::num_5, XK_5);
assign(keyboard::num_6, XK_6);
assign(keyboard::num_7, XK_7);
assign(keyboard::num_8, XK_8);
assign(keyboard::num_9, XK_9);
assign(keyboard::dash, XK_minus);
assign(keyboard::equal, XK_equal);
assign(keyboard::backspace, XK_BackSpace);
assign(keyboard::insert, XK_Insert);
assign(keyboard::delete_, XK_Delete);
assign(keyboard::home, XK_Home);
assign(keyboard::end, XK_End);
assign(keyboard::page_up, XK_Prior);
assign(keyboard::page_down, XK_Next);
assign(keyboard::a, XK_A);
assign(keyboard::b, XK_B);
assign(keyboard::c, XK_C);
assign(keyboard::d, XK_D);
assign(keyboard::e, XK_E);
assign(keyboard::f, XK_F);
assign(keyboard::g, XK_G);
assign(keyboard::h, XK_H);
assign(keyboard::i, XK_I);
assign(keyboard::j, XK_J);
assign(keyboard::k, XK_K);
assign(keyboard::l, XK_L);
assign(keyboard::m, XK_M);
assign(keyboard::n, XK_N);
assign(keyboard::o, XK_O);
assign(keyboard::p, XK_P);
assign(keyboard::q, XK_Q);
assign(keyboard::r, XK_R);
assign(keyboard::s, XK_S);
assign(keyboard::t, XK_T);
assign(keyboard::u, XK_U);
assign(keyboard::v, XK_V);
assign(keyboard::w, XK_W);
assign(keyboard::x, XK_X);
assign(keyboard::y, XK_Y);
assign(keyboard::z, XK_Z);
assign(keyboard::lbracket, XK_bracketleft);
assign(keyboard::rbracket, XK_bracketright);
assign(keyboard::backslash, XK_backslash);
assign(keyboard::semicolon, XK_semicolon);
assign(keyboard::apostrophe, XK_apostrophe);
assign(keyboard::comma, XK_comma);
assign(keyboard::period, XK_period);
assign(keyboard::slash, XK_slash);
assign(keyboard::pad_0, XK_KP_0);
assign(keyboard::pad_1, XK_KP_1);
assign(keyboard::pad_2, XK_KP_2);
assign(keyboard::pad_3, XK_KP_3);
assign(keyboard::pad_4, XK_KP_4);
assign(keyboard::pad_5, XK_KP_5);
assign(keyboard::pad_6, XK_KP_6);
assign(keyboard::pad_7, XK_KP_7);
assign(keyboard::pad_8, XK_KP_8);
assign(keyboard::pad_9, XK_KP_9);
assign(keyboard::add, XK_KP_Add);
assign(keyboard::subtract, XK_KP_Subtract);
assign(keyboard::multiply, XK_KP_Multiply);
assign(keyboard::divide, XK_KP_Divide);
assign(keyboard::enter, XK_KP_Enter);
//assign(keyboard::num_lock, XK_???);
//assign(keyboard::caps_lock, XK_???);
assign(keyboard::up, XK_Up);
assign(keyboard::down, XK_Down);
assign(keyboard::left, XK_Left);
assign(keyboard::right, XK_Right);
assign(keyboard::tab, XK_Tab);
assign(keyboard::return_, XK_Return);
assign(keyboard::spacebar, XK_space);
assign(keyboard::lctrl, XK_Control_L);
assign(keyboard::rctrl, XK_Control_R);
assign(keyboard::lalt, XK_Alt_L);
assign(keyboard::ralt, XK_Alt_R);
assign(keyboard::lshift, XK_Shift_L);
assign(keyboard::rshift, XK_Shift_R);
assign(keyboard::lsuper, XK_Super_L);
assign(keyboard::rsuper, XK_Super_R);
assign(keyboard::menu, XK_Menu);
#undef assign
XCloseDisplay(display);
}

View File

@ -8,11 +8,11 @@ void bPPU::enter() {
loop:
//H = 0 (initialize)
scanline();
if(ppucounter.vcounter() == 0) frame();
if(ivcounter() == 0) frame();
add_clocks(10);
//H = 10 (OAM address reset)
if(ppucounter.vcounter() == (!overscan() ? 225 : 240)) {
if(ivcounter() == (!overscan() ? 225 : 240)) {
if(regs.display_disabled == false) {
regs.oam_addr = regs.oam_baseaddr << 1;
regs.oam_firstsprite = (regs.oam_priority == false) ? 0 : (regs.oam_addr >> 2) & 127;
@ -28,19 +28,19 @@ void bPPU::enter() {
cache.oam_basesize = regs.oam_basesize;
cache.oam_nameselect = regs.oam_nameselect;
cache.oam_tdaddr = regs.oam_tdaddr;
add_clocks(ppucounter.ppulineclocks() - 1152); //seek to start of next scanline
add_clocks(ilineclocks() - 1152); //seek to start of next scanline
goto loop;
}
void bPPU::add_clocks(unsigned clocks) {
ppucounter.tock(clocks);
tock(clocks);
scheduler.addclocks_ppu(clocks);
}
void bPPU::scanline() {
snes.scanline();
line.y = ppucounter.ppuvcounter();
line.y = ivcounter();
if(line.y == 0) {
//RTO flag reset
@ -78,7 +78,7 @@ void bPPU::frame() {
PPU::frame();
snes.frame();
if(ppucounter.ppufield() == 0) {
if(ifield() == 0) {
display.interlace = regs.interlace;
regs.scanlines = (regs.overscan == false) ? 224 : 239;
}

View File

@ -1,8 +1,8 @@
#ifdef BPPU_CPP
void bPPU::latch_counters() {
regs.hcounter = ppucounter.hdot();
regs.vcounter = ppucounter.vcounter();
regs.hcounter = hdot();
regs.vcounter = vcounter();
regs.counters_latched = true;
}
@ -28,10 +28,10 @@ uint8 bPPU::vram_mmio_read(uint16 addr) {
if(regs.display_disabled == true) {
data = memory::vram[addr];
} else {
uint16 v = ppucounter.vcounter();
uint16 h = ppucounter.hcounter();
uint16 v = vcounter();
uint16 h = hcounter();
uint16 ls = ((snes.region() == SNES::NTSC ? 525 : 625) >> 1) - 1;
if(interlace() && !ppucounter.field()) ls++;
if(interlace() && !field()) ls++;
if(v == ls && h == 1362) {
data = 0x00;
@ -55,8 +55,8 @@ void bPPU::vram_mmio_write(uint16 addr, uint8 data) {
if(regs.display_disabled == true) {
memory::vram[addr] = data;
} else {
uint16 v = ppucounter.vcounter();
uint16 h = ppucounter.hcounter();
uint16 v = vcounter();
uint16 h = hcounter();
if(v == 0) {
if(h <= 4) {
memory::vram[addr] = data;
@ -100,7 +100,7 @@ uint8 bPPU::oam_mmio_read(uint16 addr) {
if(regs.display_disabled == true) {
data = memory::oam[addr];
} else {
if(ppucounter.vcounter() < (!overscan() ? 225 : 240)) {
if(vcounter() < (!overscan() ? 225 : 240)) {
data = memory::oam[0x0218];
} else {
data = memory::oam[addr];
@ -117,7 +117,7 @@ void bPPU::oam_mmio_write(uint16 addr, uint8 data) {
if(regs.display_disabled == true) {
memory::oam[addr] = data;
} else {
if(ppucounter.vcounter() < (!overscan() ? 225 : 240)) {
if(vcounter() < (!overscan() ? 225 : 240)) {
memory::oam[0x0218] = data;
} else {
memory::oam[addr] = data;
@ -138,8 +138,8 @@ uint8 bPPU::cgram_mmio_read(uint16 addr) {
if(regs.display_disabled == true) {
data = memory::cgram[addr];
} else {
uint16 v = ppucounter.vcounter();
uint16 h = ppucounter.hcounter();
uint16 v = vcounter();
uint16 h = hcounter();
if(v < (!overscan() ? 225 : 240) && h >= 72 && h < 1096) {
data = memory::cgram[0x01ff] & 0x7f;
} else {
@ -158,8 +158,8 @@ void bPPU::cgram_mmio_write(uint16 addr, uint8 data) {
if(regs.display_disabled == true) {
memory::cgram[addr] = data;
} else {
uint16 v = ppucounter.vcounter();
uint16 h = ppucounter.hcounter();
uint16 v = vcounter();
uint16 h = hcounter();
if(v < (!overscan() ? 225 : 240) && h >= 72 && h < 1096) {
memory::cgram[0x01ff] = data & 0x7f;
} else {
@ -170,7 +170,7 @@ void bPPU::cgram_mmio_write(uint16 addr, uint8 data) {
//INIDISP
void bPPU::mmio_w2100(uint8 value) {
if(regs.display_disabled == true && ppucounter.vcounter() == (!overscan() ? 225 : 240)) {
if(regs.display_disabled == true && vcounter() == (!overscan() ? 225 : 240)) {
regs.oam_addr = regs.oam_baseaddr << 1;
regs.oam_firstsprite = (regs.oam_priority == false) ? 0 : (regs.oam_addr >> 2) & 127;
}
@ -723,7 +723,7 @@ uint8 r = 0x00;
regs.latch_hcounter = 0;
regs.latch_vcounter = 0;
r |= ppucounter.field() << 7;
r |= field() << 7;
if(!(cpu.pio() & 0x80)) {
r |= 0x40;
} else if(regs.counters_latched == true) {

View File

@ -14,16 +14,16 @@ enum { COLORDEPTH_4 = 0, COLORDEPTH_16 = 1, COLORDEPTH_256 = 2 };
enum { TILE_2BIT = 0, TILE_4BIT = 1, TILE_8BIT = 2 };
struct _pixel {
//bgr555 color data for main/subscreen pixels: 0x0000 = transparent / use palette color # 0
//needs to be bgr555 instead of palette index for direct color mode ($2130 bit 0) to work
uint16 src_main, src_sub;
//indicates source of palette # for main/subscreen (BG1-4, OAM, or back)
uint8 bg_main, bg_sub;
//color_exemption -- true when bg == OAM && palette index >= 192, disables color add/sub effects
uint8 ce_main, ce_sub;
//priority level of src_n. to set src_n,
//the priority of the pixel must be >pri_n
uint8 pri_main, pri_sub;
//bgr555 color data for main/subscreen pixels: 0x0000 = transparent / use palette color # 0
//needs to be bgr555 instead of palette index for direct color mode ($2130 bit 0) to work
uint16 src_main, src_sub;
//indicates source of palette # for main/subscreen (BG1-4, OAM, or back)
uint8 bg_main, bg_sub;
//color_exemption -- true when bg == OAM && palette index >= 192, disables color add/sub effects
uint8 ce_main, ce_sub;
//priority level of src_n. to set src_n,
//the priority of the pixel must be >pri_n
uint8 pri_main, pri_sub;
} pixel_cache[256];
uint8 *bg_tiledata[3];

View File

@ -11,14 +11,14 @@ void bPPU::update_bg_info() {
bg_info[bg].mx = (bg_info[bg].th == 4) ? (width << 1) : width;
bg_info[bg].my = bg_info[bg].mx;
if(regs.bg_scsize[bg] & 0x01)bg_info[bg].mx <<= 1;
if(regs.bg_scsize[bg] & 0x02)bg_info[bg].my <<= 1;
if(regs.bg_scsize[bg] & 0x01) bg_info[bg].mx <<= 1;
if(regs.bg_scsize[bg] & 0x02) bg_info[bg].my <<= 1;
bg_info[bg].mx--;
bg_info[bg].my--;
bg_info[bg].scy = (regs.bg_scsize[bg] & 0x02) ? (32 << 5) : 0;
bg_info[bg].scx = (regs.bg_scsize[bg] & 0x01) ? (32 << 5) : 0;
if(regs.bg_scsize[bg] == 3)bg_info[bg].scy <<= 1;
if(regs.bg_scsize[bg] == 3) bg_info[bg].scy <<= 1;
}
}
@ -90,7 +90,7 @@ void bPPU::render_line_bg(uint8 bg, uint8 color_depth, uint8 pri0_pos, uint8 pri
if(hires) {
hscroll <<= 1;
if(regs.interlace) y = (y << 1) + ppucounter.field();
if(regs.interlace) y = (y << 1) + ifield();
}
uint16 *mtable = mosaic_table[(regs.mosaic_enabled[bg]) ? regs.mosaic_size : 0];

View File

@ -106,9 +106,11 @@ void bPPU::render_bg_tile(uint8 color_depth, uint16 tile_num) {
void bPPU::flush_pixel_cache() {
uint16 main = get_palette(0);
uint16 sub = (regs.pseudo_hires || regs.bg_mode == 5 || regs.bg_mode == 6) ? main : regs.color_rgb;
uint32 i = 255;
uint16 sub = (regs.pseudo_hires || regs.bg_mode == 5 || regs.bg_mode == 6)
? main
: regs.color_rgb;
unsigned i = 255;
do {
pixel_cache[i].src_main = main;
pixel_cache[i].src_sub = sub;

View File

@ -86,7 +86,7 @@ inline uint16 bPPU::get_pixel_swap(uint32 x) {
inline void bPPU::render_line_output() {
uint16 *ptr = (uint16*)output + (line.y * 1024) +
((interlace() && ppucounter.field()) ? 512 : 0);
((interlace() && ifield()) ? 512 : 0);
uint16 *luma_b = light_table_b [regs.display_brightness];
uint16 *luma_gr = light_table_gr[regs.display_brightness];
uint16 curr, prev;
@ -132,7 +132,7 @@ inline void bPPU::render_line_output() {
inline void bPPU::render_line_clear() {
uint16 *ptr = (uint16*)output + (line.y * 1024) +
((interlace() && ppucounter.field()) ? 512 : 0);
((interlace() && ifield()) ? 512 : 0);
uint16 width = (!regs.pseudo_hires && regs.bg_mode != 5 && regs.bg_mode != 6) ? 256 : 512;
memset(ptr, 0, width * 2 * sizeof(uint16));
}

View File

@ -80,7 +80,7 @@ void bPPU::load_oam_tiles() {
}
if(regs.oam_interlace == true) {
y = (spr->vflip == false) ? (y + ppucounter.field()) : (y - ppucounter.field());
y = (spr->vflip == false) ? (y + ifield()) : (y - ifield());
}
x &= 511;

View File

@ -27,8 +27,8 @@ uint16 PPUcounter::lineclocks() {
return 1364;
}
uint16 PPUcounter::ppulineclocks() {
if(region() == 0 && interlace() == false && ppuvcounter() == 240 && status.field == 1) return 1360;
uint16 PPUcounter::ilineclocks() {
if(region() == 0 && interlace() == false && ivcounter() == 240 && status.field == 1) return 1360;
return 1364;
}

View File

@ -31,20 +31,23 @@ public:
history.ppudiff -= clocks;
}
//timing information relative to S-CPU
alwaysinline bool field () { return status.field; }
alwaysinline uint16 vcounter() { return status.vcounter; }
alwaysinline uint16 hcounter() { return status.hcounter; }
uint16 hdot();
uint16 lineclocks();
//timing history information relative to S-CPU
alwaysinline bool field (unsigned offset) { return history.field [(history.index - (offset >> 1)) & 2047]; }
alwaysinline uint16 vcounter(unsigned offset) { return history.vcounter[(history.index - (offset >> 1)) & 2047]; }
alwaysinline uint16 hcounter(unsigned offset) { return history.hcounter[(history.index - (offset >> 1)) & 2047]; }
alwaysinline bool ppufield() { return history.field [(history.index - (history.ppudiff >> 1)) & 2047]; }
alwaysinline uint16 ppuvcounter() { return history.vcounter[(history.index - (history.ppudiff >> 1)) & 2047]; }
alwaysinline uint16 ppuhcounter() { return history.hcounter[(history.index - (history.ppudiff >> 1)) & 2047]; }
uint16 ppulineclocks();
//timing information relative to S-PPU
alwaysinline bool ifield() { return history.field [(history.index - (history.ppudiff >> 1)) & 2047]; }
alwaysinline uint16 ivcounter() { return history.vcounter[(history.index - (history.ppudiff >> 1)) & 2047]; }
alwaysinline uint16 ihcounter() { return history.hcounter[(history.index - (history.ppudiff >> 1)) & 2047]; }
uint16 ilineclocks();
void reset();
@ -68,5 +71,3 @@ private:
signed ppudiff;
} history;
};
extern PPUcounter ppucounter;

View File

@ -28,6 +28,7 @@ void PPU::power() {
}
void PPU::reset() {
PPUcounter::reset();
memset(output, 0, 512 * 480 * sizeof(uint16));
}

View File

@ -1,18 +1,18 @@
class PPU : public MMIO {
#include "counter.hpp"
class PPU : public PPUcounter, public MMIO {
public:
virtual void enter() = 0;
uint16 *output;
//this struct should be read-only to
//functions outside of this class
struct {
bool render_output;
bool render_output;
bool frame_executed;
bool frames_updated;
uint32 frames_rendered;
uint32 frames_executed;
bool frame_executed;
bool frames_updated;
unsigned frames_rendered;
unsigned frames_executed;
} status;
//PPU1 version number
@ -40,5 +40,3 @@ public:
PPU();
virtual ~PPU();
};
#include "counter.hpp"

View File

@ -5,14 +5,14 @@
bool SMP::in_opcode() { return false; }
uint16 SMP::__relb(int8 offset, int op_len) {
uint16 pc = regs.pc + op_len;
uint16 pc = regs.pc + op_len;
return pc + offset;
}
void SMP::disassemble_opcode(char *output) {
char *s, t[512];
uint8 op, op0, op1;
uint16 opw, opdp0, opdp1;
char *s, t[512];
uint8 op, op0, op1;
uint16 opw, opdp0, opdp1;
s = output;
if(in_opcode() == true) {
@ -20,7 +20,7 @@ uint16 opw, opdp0, opdp1;
return;
}
sprintf(s, "..%0.4x ", regs.pc);
sprintf(s, "..%.4x ", regs.pc);
op = ram_read(regs.pc);
op0 = ram_read(regs.pc + 1);
@ -30,281 +30,283 @@ uint16 opw, opdp0, opdp1;
opdp1 = ((regs.p.p)?0x100:0x000) + op1;
strcpy(t, " ");
switch(op) {
case 0x00: sprintf(t, "nop"); break;
case 0x01: sprintf(t, "tcall 0"); break;
case 0x02: sprintf(t, "set0 $%0.3x", opdp0); break;
case 0x03: sprintf(t, "bbs0 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x04: sprintf(t, "or a,$%0.3x", opdp0); break;
case 0x05: sprintf(t, "or a,$%0.4x", opw); break;
case 0x06: sprintf(t, "or a,(x)"); break;
case 0x07: sprintf(t, "or a,($%0.3x+x)", opdp0); break;
case 0x08: sprintf(t, "or a,#$%0.2x", op0); break;
case 0x09: sprintf(t, "or $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x0a: sprintf(t, "or1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x0b: sprintf(t, "asl $%0.3x", opdp0); break;
case 0x0c: sprintf(t, "asl $%0.4x", opw); break;
case 0x0d: sprintf(t, "push p"); break;
case 0x0e: sprintf(t, "tset $%0.4x,a", opw); break;
case 0x0f: sprintf(t, "brk"); break;
case 0x10: sprintf(t, "bpl $%0.4x", __relb(op0, 2)); break;
case 0x11: sprintf(t, "tcall 1"); break;
case 0x12: sprintf(t, "clr0 $%0.3x", opdp0); break;
case 0x13: sprintf(t, "bbc0 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x14: sprintf(t, "or a,$%0.3x+x", opdp0); break;
case 0x15: sprintf(t, "or a,$%0.4x+x", opw); break;
case 0x16: sprintf(t, "or a,$%0.4x+y", opw); break;
case 0x17: sprintf(t, "or a,($%0.3x)+y", opdp0); break;
case 0x18: sprintf(t, "or $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x19: sprintf(t, "or (x),(y)"); break;
case 0x1a: sprintf(t, "decw $%0.3x", opdp0); break;
case 0x1b: sprintf(t, "asl $%0.3x+x", opdp0); break;
case 0x1c: sprintf(t, "asl a"); break;
case 0x1d: sprintf(t, "dec x"); break;
case 0x1e: sprintf(t, "cmp x,$%0.4x", opw); break;
case 0x1f: sprintf(t, "jmp ($%0.4x+x)", opw); break;
case 0x20: sprintf(t, "clrp"); break;
case 0x21: sprintf(t, "tcall 2"); break;
case 0x22: sprintf(t, "set1 $%0.3x", opdp0); break;
case 0x23: sprintf(t, "bbs1 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x24: sprintf(t, "and a,$%0.3x", opdp0); break;
case 0x25: sprintf(t, "and a,$%0.4x", opw); break;
case 0x26: sprintf(t, "and a,(x)"); break;
case 0x27: sprintf(t, "and a,($%0.3x+x)", opdp0); break;
case 0x28: sprintf(t, "and a,#$%0.2x", op0); break;
case 0x29: sprintf(t, "and $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x2a: sprintf(t, "or1 c,!$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x2b: sprintf(t, "rol $%0.3x", opdp0); break;
case 0x2c: sprintf(t, "rol $%0.4x", opw); break;
case 0x2d: sprintf(t, "push a"); break;
case 0x2e: sprintf(t, "cbne $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x2f: sprintf(t, "bra $%0.4x", __relb(op0, 2)); break;
case 0x30: sprintf(t, "bmi $%0.4x", __relb(op0, 2)); break;
case 0x31: sprintf(t, "tcall 3"); break;
case 0x32: sprintf(t, "clr1 $%0.3x", opdp0); break;
case 0x33: sprintf(t, "bbc1 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x34: sprintf(t, "and a,$%0.3x+x", opdp0); break;
case 0x35: sprintf(t, "and a,$%0.4x+x", opw); break;
case 0x36: sprintf(t, "and a,$%0.4x+y", opw); break;
case 0x37: sprintf(t, "and a,($%0.3x)+y", opdp0); break;
case 0x38: sprintf(t, "and $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x39: sprintf(t, "and (x),(y)"); break;
case 0x3a: sprintf(t, "incw $%0.3x", opdp0); break;
case 0x3b: sprintf(t, "rol $%0.3x+x", opdp0); break;
case 0x3c: sprintf(t, "rol a"); break;
case 0x3d: sprintf(t, "inc x"); break;
case 0x3e: sprintf(t, "cmp x,$%0.3x", opdp0); break;
case 0x3f: sprintf(t, "call $%0.4x", opw); break;
case 0x40: sprintf(t, "setp"); break;
case 0x41: sprintf(t, "tcall 4"); break;
case 0x42: sprintf(t, "set2 $%0.3x", opdp0); break;
case 0x43: sprintf(t, "bbs2 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x44: sprintf(t, "eor a,$%0.3x", opdp0); break;
case 0x45: sprintf(t, "eor a,$%0.4x", opw); break;
case 0x46: sprintf(t, "eor a,(x)"); break;
case 0x47: sprintf(t, "eor a,($%0.3x+x)", opdp0); break;
case 0x48: sprintf(t, "eor a,#$%0.2x", op0); break;
case 0x49: sprintf(t, "eor $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x4a: sprintf(t, "and1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x4b: sprintf(t, "lsr $%0.3x", opdp0); break;
case 0x4c: sprintf(t, "lsr $%0.4x", opw); break;
case 0x4d: sprintf(t, "push x"); break;
case 0x4e: sprintf(t, "tclr $%0.4x,a", opw); break;
case 0x4f: sprintf(t, "pcall $ff%0.2x", op0); break;
case 0x50: sprintf(t, "bvc $%0.4x", __relb(op0, 2)); break;
case 0x51: sprintf(t, "tcall 5"); break;
case 0x52: sprintf(t, "clr2 $%0.3x", opdp0); break;
case 0x53: sprintf(t, "bbc2 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x54: sprintf(t, "eor a,$%0.3x+x", opdp0); break;
case 0x55: sprintf(t, "eor a,$%0.4x+x", opw); break;
case 0x56: sprintf(t, "eor a,$%0.4x+y", opw); break;
case 0x57: sprintf(t, "eor a,($%0.3x)+y", opdp0); break;
case 0x58: sprintf(t, "eor $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x59: sprintf(t, "eor (x),(y)"); break;
case 0x5a: sprintf(t, "cmpw ya,$%0.3x", opdp0); break;
case 0x5b: sprintf(t, "lsr $%0.3x+x", opdp0); break;
case 0x5c: sprintf(t, "lsr a"); break;
case 0x5d: sprintf(t, "mov x,a"); break;
case 0x5e: sprintf(t, "cmp y,$%0.4x", opw); break;
case 0x5f: sprintf(t, "jmp $%0.4x", opw); break;
case 0x60: sprintf(t, "clrc"); break;
case 0x61: sprintf(t, "tcall 6"); break;
case 0x62: sprintf(t, "set3 $%0.3x", opdp0); break;
case 0x63: sprintf(t, "bbs3 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x64: sprintf(t, "cmp a,$%0.3x", opdp0); break;
case 0x65: sprintf(t, "cmp a,$%0.4x", opw); break;
case 0x66: sprintf(t, "cmp a,(x)"); break;
case 0x67: sprintf(t, "cmp a,($%0.3x+x)", opdp0); break;
case 0x68: sprintf(t, "cmp a,#$%0.2x", op0); break;
case 0x69: sprintf(t, "cmp $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x6a: sprintf(t, "and1 c,!$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x6b: sprintf(t, "ror $%0.3x", opdp0); break;
case 0x6c: sprintf(t, "ror $%0.4x", opw); break;
case 0x6d: sprintf(t, "push y"); break;
case 0x6e: sprintf(t, "dbnz $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x6f: sprintf(t, "ret"); break;
case 0x70: sprintf(t, "bvs $%0.4x", __relb(op0, 2)); break;
case 0x71: sprintf(t, "tcall 7"); break;
case 0x72: sprintf(t, "clr3 $%0.3x", opdp0); break;
case 0x73: sprintf(t, "bbc3 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x74: sprintf(t, "cmp a,$%0.3x+x", opdp0); break;
case 0x75: sprintf(t, "cmp a,$%0.4x+x", opw); break;
case 0x76: sprintf(t, "cmp a,$%0.4x+y", opw); break;
case 0x77: sprintf(t, "cmp a,($%0.3x)+y", opdp0); break;
case 0x78: sprintf(t, "cmp $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x79: sprintf(t, "cmp (x),(y)"); break;
case 0x7a: sprintf(t, "addw ya,$%0.3x", opdp0); break;
case 0x7b: sprintf(t, "ror $%0.3x+x", opdp0); break;
case 0x7c: sprintf(t, "ror a"); break;
case 0x7d: sprintf(t, "mov a,x"); break;
case 0x7e: sprintf(t, "cmp y,$%0.3x", opdp0); break;
case 0x7f: sprintf(t, "reti"); break;
case 0x80: sprintf(t, "setc"); break;
case 0x81: sprintf(t, "tcall 8"); break;
case 0x82: sprintf(t, "set4 $%0.3x", opdp0); break;
case 0x83: sprintf(t, "bbs4 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x84: sprintf(t, "adc a,$%0.3x", opdp0); break;
case 0x85: sprintf(t, "adc a,$%0.4x", opw); break;
case 0x86: sprintf(t, "adc a,(x)"); break;
case 0x87: sprintf(t, "adc a,($%0.3x+x)", opdp0); break;
case 0x88: sprintf(t, "adc a,#$%0.2x", op0); break;
case 0x89: sprintf(t, "adc $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x8a: sprintf(t, "eor1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x8b: sprintf(t, "dec $%0.3x", opdp0); break;
case 0x8c: sprintf(t, "dec $%0.4x", opw); break;
case 0x8d: sprintf(t, "mov y,#$%0.2x", op0); break;
case 0x8e: sprintf(t, "pop p"); break;
case 0x8f: sprintf(t, "mov $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x90: sprintf(t, "bcc $%0.4x", __relb(op0, 2)); break;
case 0x91: sprintf(t, "tcall 9"); break;
case 0x92: sprintf(t, "clr4 $%0.3x", opdp0); break;
case 0x93: sprintf(t, "bbc4 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x94: sprintf(t, "adc a,$%0.3x+x", opdp0); break;
case 0x95: sprintf(t, "adc a,$%0.4x+x", opw); break;
case 0x96: sprintf(t, "adc a,$%0.4x+y", opw); break;
case 0x97: sprintf(t, "adc a,($%0.3x)+y", opdp0); break;
case 0x98: sprintf(t, "adc $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x99: sprintf(t, "adc (x),(y)"); break;
case 0x9a: sprintf(t, "subw ya,$%0.3x", opdp0); break;
case 0x9b: sprintf(t, "dec $%0.3x+x", opdp0); break;
case 0x9c: sprintf(t, "dec a"); break;
case 0x9d: sprintf(t, "mov x,sp"); break;
case 0x9e: sprintf(t, "div ya,x"); break;
case 0x9f: sprintf(t, "xcn a"); break;
case 0xa0: sprintf(t, "ei"); break;
case 0xa1: sprintf(t, "tcall 10"); break;
case 0xa2: sprintf(t, "set5 $%0.3x", opdp0); break;
case 0xa3: sprintf(t, "bbs5 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xa4: sprintf(t, "sbc a,$%0.3x", opdp0); break;
case 0xa5: sprintf(t, "sbc a,$%0.4x", opw); break;
case 0xa6: sprintf(t, "sbc a,(x)"); break;
case 0xa7: sprintf(t, "sbc a,($%0.3x+x)", opdp0); break;
case 0xa8: sprintf(t, "sbc a,#$%0.2x", op0); break;
case 0xa9: sprintf(t, "sbc $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0xaa: sprintf(t, "mov1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0xab: sprintf(t, "inc $%0.3x", opdp0); break;
case 0xac: sprintf(t, "inc $%0.4x", opw); break;
case 0xad: sprintf(t, "cmp y,#$%0.2x", op0); break;
case 0xae: sprintf(t, "pop a"); break;
case 0xaf: sprintf(t, "mov (x)+,a"); break;
case 0xb0: sprintf(t, "bcs $%0.4x", __relb(op0, 2)); break;
case 0xb1: sprintf(t, "tcall 11"); break;
case 0xb2: sprintf(t, "clr5 $%0.3x", opdp0); break;
case 0xb3: sprintf(t, "bbc5 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xb4: sprintf(t, "sbc a,$%0.3x+x", opdp0); break;
case 0xb5: sprintf(t, "sbc a,$%0.4x+x", opw); break;
case 0xb6: sprintf(t, "sbc a,$%0.4x+y", opw); break;
case 0xb7: sprintf(t, "sbc a,($%0.3x)+y", opdp0); break;
case 0xb8: sprintf(t, "sbc $%0.3x,#$%0.2x", opdp1, op0); break;
case 0xb9: sprintf(t, "sbc (x),(y)"); break;
case 0xba: sprintf(t, "movw ya,$%0.3x", opdp0); break;
case 0xbb: sprintf(t, "inc $%0.3x+x", opdp0); break;
case 0xbc: sprintf(t, "inc a"); break;
case 0xbd: sprintf(t, "mov sp,x"); break;
case 0xbe: sprintf(t, "das a"); break;
case 0xbf: sprintf(t, "mov a,(x)+"); break;
case 0xc0: sprintf(t, "di"); break;
case 0xc1: sprintf(t, "tcall 12"); break;
case 0xc2: sprintf(t, "set6 $%0.3x", opdp0); break;
case 0xc3: sprintf(t, "bbs6 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xc4: sprintf(t, "mov $%0.3x,a", opdp0); break;
case 0xc5: sprintf(t, "mov $%0.4x,a", opw); break;
case 0xc6: sprintf(t, "mov (x),a"); break;
case 0xc7: sprintf(t, "mov ($%0.3x+x),a", opdp0); break;
case 0xc8: sprintf(t, "cmp x,#$%0.2x", op0); break;
case 0xc9: sprintf(t, "mov $%0.4x,x", opw); break;
case 0xca: sprintf(t, "mov1 $%0.4x:%d,c", opw & 0x1fff, opw >> 13); break;
case 0xcb: sprintf(t, "mov $%0.3x,y", opdp0); break;
case 0xcc: sprintf(t, "mov $%0.4x,y", opw); break;
case 0xcd: sprintf(t, "mov x,#$%0.2x", op0); break;
case 0xce: sprintf(t, "pop x"); break;
case 0xcf: sprintf(t, "mul ya"); break;
case 0xd0: sprintf(t, "bne $%0.4x", __relb(op0, 2)); break;
case 0xd1: sprintf(t, "tcall 13"); break;
case 0xd2: sprintf(t, "clr6 $%0.3x", opdp0); break;
case 0xd3: sprintf(t, "bbc6 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xd4: sprintf(t, "mov $%0.3x+x,a", opdp0); break;
case 0xd5: sprintf(t, "mov $%0.4x+x,a", opw); break;
case 0xd6: sprintf(t, "mov $%0.4x+y,a", opw); break;
case 0xd7: sprintf(t, "mov ($%0.3x)+y,a", opdp0); break;
case 0xd8: sprintf(t, "mov $%0.3x,x", opdp0); break;
case 0xd9: sprintf(t, "mov $%0.3x+y,x", opdp0); break;
case 0xda: sprintf(t, "movw $%0.3x,ya", opdp0); break;
case 0xdb: sprintf(t, "mov $%0.3x+x,y", opdp0); break;
case 0xdc: sprintf(t, "dec y"); break;
case 0xdd: sprintf(t, "mov a,y"); break;
case 0xde: sprintf(t, "cbne $%0.3x+x,$%0.4x", opdp0, __relb(op1, 3));break;
case 0xdf: sprintf(t, "daa a"); break;
case 0xe0: sprintf(t, "clrv"); break;
case 0xe1: sprintf(t, "tcall 14"); break;
case 0xe2: sprintf(t, "set7 $%0.3x", opdp0); break;
case 0xe3: sprintf(t, "bbs7 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xe4: sprintf(t, "mov a,$%0.3x", opdp0); break;
case 0xe5: sprintf(t, "mov a,$%0.4x", opw); break;
case 0xe6: sprintf(t, "mov a,(x)"); break;
case 0xe7: sprintf(t, "mov a,($%0.3x+x)", opdp0); break;
case 0xe8: sprintf(t, "mov a,#$%0.2x", op0); break;
case 0xe9: sprintf(t, "mov x,$%0.4x", opw); break;
case 0xea: sprintf(t, "not1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0xeb: sprintf(t, "mov y,$%0.3x", opdp0); break;
case 0xec: sprintf(t, "mov y,$%0.4x", opw); break;
case 0xed: sprintf(t, "notc"); break;
case 0xee: sprintf(t, "pop y"); break;
case 0xef: sprintf(t, "sleep"); break;
case 0xf0: sprintf(t, "beq $%0.4x", __relb(op0, 2)); break;
case 0xf1: sprintf(t, "tcall 15"); break;
case 0xf2: sprintf(t, "clr7 $%0.3x", opdp0); break;
case 0xf3: sprintf(t, "bbc7 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xf4: sprintf(t, "mov a,$%0.3x+x", opdp0); break;
case 0xf5: sprintf(t, "mov a,$%0.4x+x", opw); break;
case 0xf6: sprintf(t, "mov a,$%0.4x+y", opw); break;
case 0xf7: sprintf(t, "mov a,($%0.3x)+y", opdp0); break;
case 0xf8: sprintf(t, "mov x,$%0.3x", opdp0); break;
case 0xf9: sprintf(t, "mov x,$%0.3x+y", opdp0); break;
case 0xfa: sprintf(t, "mov $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0xfb: sprintf(t, "mov y,$%0.3x+x", opdp0); break;
case 0xfc: sprintf(t, "inc y"); break;
case 0xfd: sprintf(t, "mov y,a"); break;
case 0xfe: sprintf(t, "dbnz y,$%0.4x", __relb(op0, 2)); break;
case 0xff: sprintf(t, "stop"); break;
case 0x00: sprintf(t, "nop"); break;
case 0x01: sprintf(t, "tcall 0"); break;
case 0x02: sprintf(t, "set0 $%.3x", opdp0); break;
case 0x03: sprintf(t, "bbs0 $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0x04: sprintf(t, "or a,$%.3x", opdp0); break;
case 0x05: sprintf(t, "or a,$%.4x", opw); break;
case 0x06: sprintf(t, "or a,(x)"); break;
case 0x07: sprintf(t, "or a,($%.3x+x)", opdp0); break;
case 0x08: sprintf(t, "or a,#$%.2x", op0); break;
case 0x09: sprintf(t, "or $%.3x,$%.3x", opdp1, opdp0); break;
case 0x0a: sprintf(t, "or1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x0b: sprintf(t, "asl $%.3x", opdp0); break;
case 0x0c: sprintf(t, "asl $%.4x", opw); break;
case 0x0d: sprintf(t, "push p"); break;
case 0x0e: sprintf(t, "tset $%.4x,a", opw); break;
case 0x0f: sprintf(t, "brk"); break;
case 0x10: sprintf(t, "bpl $%.4x", __relb(op0, 2)); break;
case 0x11: sprintf(t, "tcall 1"); break;
case 0x12: sprintf(t, "clr0 $%.3x", opdp0); break;
case 0x13: sprintf(t, "bbc0 $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0x14: sprintf(t, "or a,$%.3x+x", opdp0); break;
case 0x15: sprintf(t, "or a,$%.4x+x", opw); break;
case 0x16: sprintf(t, "or a,$%.4x+y", opw); break;
case 0x17: sprintf(t, "or a,($%.3x)+y", opdp0); break;
case 0x18: sprintf(t, "or $%.3x,#$%.2x", opdp1, op0); break;
case 0x19: sprintf(t, "or (x),(y)"); break;
case 0x1a: sprintf(t, "decw $%.3x", opdp0); break;
case 0x1b: sprintf(t, "asl $%.3x+x", opdp0); break;
case 0x1c: sprintf(t, "asl a"); break;
case 0x1d: sprintf(t, "dec x"); break;
case 0x1e: sprintf(t, "cmp x,$%.4x", opw); break;
case 0x1f: sprintf(t, "jmp ($%.4x+x)", opw); break;
case 0x20: sprintf(t, "clrp"); break;
case 0x21: sprintf(t, "tcall 2"); break;
case 0x22: sprintf(t, "set1 $%.3x", opdp0); break;
case 0x23: sprintf(t, "bbs1 $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0x24: sprintf(t, "and a,$%.3x", opdp0); break;
case 0x25: sprintf(t, "and a,$%.4x", opw); break;
case 0x26: sprintf(t, "and a,(x)"); break;
case 0x27: sprintf(t, "and a,($%.3x+x)", opdp0); break;
case 0x28: sprintf(t, "and a,#$%.2x", op0); break;
case 0x29: sprintf(t, "and $%.3x,$%.3x", opdp1, opdp0); break;
case 0x2a: sprintf(t, "or1 c,!$%.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x2b: sprintf(t, "rol $%.3x", opdp0); break;
case 0x2c: sprintf(t, "rol $%.4x", opw); break;
case 0x2d: sprintf(t, "push a"); break;
case 0x2e: sprintf(t, "cbne $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0x2f: sprintf(t, "bra $%.4x", __relb(op0, 2)); break;
case 0x30: sprintf(t, "bmi $%.4x", __relb(op0, 2)); break;
case 0x31: sprintf(t, "tcall 3"); break;
case 0x32: sprintf(t, "clr1 $%.3x", opdp0); break;
case 0x33: sprintf(t, "bbc1 $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0x34: sprintf(t, "and a,$%.3x+x", opdp0); break;
case 0x35: sprintf(t, "and a,$%.4x+x", opw); break;
case 0x36: sprintf(t, "and a,$%.4x+y", opw); break;
case 0x37: sprintf(t, "and a,($%.3x)+y", opdp0); break;
case 0x38: sprintf(t, "and $%.3x,#$%.2x", opdp1, op0); break;
case 0x39: sprintf(t, "and (x),(y)"); break;
case 0x3a: sprintf(t, "incw $%.3x", opdp0); break;
case 0x3b: sprintf(t, "rol $%.3x+x", opdp0); break;
case 0x3c: sprintf(t, "rol a"); break;
case 0x3d: sprintf(t, "inc x"); break;
case 0x3e: sprintf(t, "cmp x,$%.3x", opdp0); break;
case 0x3f: sprintf(t, "call $%.4x", opw); break;
case 0x40: sprintf(t, "setp"); break;
case 0x41: sprintf(t, "tcall 4"); break;
case 0x42: sprintf(t, "set2 $%.3x", opdp0); break;
case 0x43: sprintf(t, "bbs2 $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0x44: sprintf(t, "eor a,$%.3x", opdp0); break;
case 0x45: sprintf(t, "eor a,$%.4x", opw); break;
case 0x46: sprintf(t, "eor a,(x)"); break;
case 0x47: sprintf(t, "eor a,($%.3x+x)", opdp0); break;
case 0x48: sprintf(t, "eor a,#$%.2x", op0); break;
case 0x49: sprintf(t, "eor $%.3x,$%.3x", opdp1, opdp0); break;
case 0x4a: sprintf(t, "and1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x4b: sprintf(t, "lsr $%.3x", opdp0); break;
case 0x4c: sprintf(t, "lsr $%.4x", opw); break;
case 0x4d: sprintf(t, "push x"); break;
case 0x4e: sprintf(t, "tclr $%.4x,a", opw); break;
case 0x4f: sprintf(t, "pcall $ff%.2x", op0); break;
case 0x50: sprintf(t, "bvc $%.4x", __relb(op0, 2)); break;
case 0x51: sprintf(t, "tcall 5"); break;
case 0x52: sprintf(t, "clr2 $%.3x", opdp0); break;
case 0x53: sprintf(t, "bbc2 $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0x54: sprintf(t, "eor a,$%.3x+x", opdp0); break;
case 0x55: sprintf(t, "eor a,$%.4x+x", opw); break;
case 0x56: sprintf(t, "eor a,$%.4x+y", opw); break;
case 0x57: sprintf(t, "eor a,($%.3x)+y", opdp0); break;
case 0x58: sprintf(t, "eor $%.3x,#$%.2x", opdp1, op0); break;
case 0x59: sprintf(t, "eor (x),(y)"); break;
case 0x5a: sprintf(t, "cmpw ya,$%.3x", opdp0); break;
case 0x5b: sprintf(t, "lsr $%.3x+x", opdp0); break;
case 0x5c: sprintf(t, "lsr a"); break;
case 0x5d: sprintf(t, "mov x,a"); break;
case 0x5e: sprintf(t, "cmp y,$%.4x", opw); break;
case 0x5f: sprintf(t, "jmp $%.4x", opw); break;
case 0x60: sprintf(t, "clrc"); break;
case 0x61: sprintf(t, "tcall 6"); break;
case 0x62: sprintf(t, "set3 $%.3x", opdp0); break;
case 0x63: sprintf(t, "bbs3 $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0x64: sprintf(t, "cmp a,$%.3x", opdp0); break;
case 0x65: sprintf(t, "cmp a,$%.4x", opw); break;
case 0x66: sprintf(t, "cmp a,(x)"); break;
case 0x67: sprintf(t, "cmp a,($%.3x+x)", opdp0); break;
case 0x68: sprintf(t, "cmp a,#$%.2x", op0); break;
case 0x69: sprintf(t, "cmp $%.3x,$%.3x", opdp1, opdp0); break;
case 0x6a: sprintf(t, "and1 c,!$%.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x6b: sprintf(t, "ror $%.3x", opdp0); break;
case 0x6c: sprintf(t, "ror $%.4x", opw); break;
case 0x6d: sprintf(t, "push y"); break;
case 0x6e: sprintf(t, "dbnz $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0x6f: sprintf(t, "ret"); break;
case 0x70: sprintf(t, "bvs $%.4x", __relb(op0, 2)); break;
case 0x71: sprintf(t, "tcall 7"); break;
case 0x72: sprintf(t, "clr3 $%.3x", opdp0); break;
case 0x73: sprintf(t, "bbc3 $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0x74: sprintf(t, "cmp a,$%.3x+x", opdp0); break;
case 0x75: sprintf(t, "cmp a,$%.4x+x", opw); break;
case 0x76: sprintf(t, "cmp a,$%.4x+y", opw); break;
case 0x77: sprintf(t, "cmp a,($%.3x)+y", opdp0); break;
case 0x78: sprintf(t, "cmp $%.3x,#$%.2x", opdp1, op0); break;
case 0x79: sprintf(t, "cmp (x),(y)"); break;
case 0x7a: sprintf(t, "addw ya,$%.3x", opdp0); break;
case 0x7b: sprintf(t, "ror $%.3x+x", opdp0); break;
case 0x7c: sprintf(t, "ror a"); break;
case 0x7d: sprintf(t, "mov a,x"); break;
case 0x7e: sprintf(t, "cmp y,$%.3x", opdp0); break;
case 0x7f: sprintf(t, "reti"); break;
case 0x80: sprintf(t, "setc"); break;
case 0x81: sprintf(t, "tcall 8"); break;
case 0x82: sprintf(t, "set4 $%.3x", opdp0); break;
case 0x83: sprintf(t, "bbs4 $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0x84: sprintf(t, "adc a,$%.3x", opdp0); break;
case 0x85: sprintf(t, "adc a,$%.4x", opw); break;
case 0x86: sprintf(t, "adc a,(x)"); break;
case 0x87: sprintf(t, "adc a,($%.3x+x)", opdp0); break;
case 0x88: sprintf(t, "adc a,#$%.2x", op0); break;
case 0x89: sprintf(t, "adc $%.3x,$%.3x", opdp1, opdp0); break;
case 0x8a: sprintf(t, "eor1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x8b: sprintf(t, "dec $%.3x", opdp0); break;
case 0x8c: sprintf(t, "dec $%.4x", opw); break;
case 0x8d: sprintf(t, "mov y,#$%.2x", op0); break;
case 0x8e: sprintf(t, "pop p"); break;
case 0x8f: sprintf(t, "mov $%.3x,#$%.2x", opdp1, op0); break;
case 0x90: sprintf(t, "bcc $%.4x", __relb(op0, 2)); break;
case 0x91: sprintf(t, "tcall 9"); break;
case 0x92: sprintf(t, "clr4 $%.3x", opdp0); break;
case 0x93: sprintf(t, "bbc4 $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0x94: sprintf(t, "adc a,$%.3x+x", opdp0); break;
case 0x95: sprintf(t, "adc a,$%.4x+x", opw); break;
case 0x96: sprintf(t, "adc a,$%.4x+y", opw); break;
case 0x97: sprintf(t, "adc a,($%.3x)+y", opdp0); break;
case 0x98: sprintf(t, "adc $%.3x,#$%.2x", opdp1, op0); break;
case 0x99: sprintf(t, "adc (x),(y)"); break;
case 0x9a: sprintf(t, "subw ya,$%.3x", opdp0); break;
case 0x9b: sprintf(t, "dec $%.3x+x", opdp0); break;
case 0x9c: sprintf(t, "dec a"); break;
case 0x9d: sprintf(t, "mov x,sp"); break;
case 0x9e: sprintf(t, "div ya,x"); break;
case 0x9f: sprintf(t, "xcn a"); break;
case 0xa0: sprintf(t, "ei"); break;
case 0xa1: sprintf(t, "tcall 10"); break;
case 0xa2: sprintf(t, "set5 $%.3x", opdp0); break;
case 0xa3: sprintf(t, "bbs5 $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0xa4: sprintf(t, "sbc a,$%.3x", opdp0); break;
case 0xa5: sprintf(t, "sbc a,$%.4x", opw); break;
case 0xa6: sprintf(t, "sbc a,(x)"); break;
case 0xa7: sprintf(t, "sbc a,($%.3x+x)", opdp0); break;
case 0xa8: sprintf(t, "sbc a,#$%.2x", op0); break;
case 0xa9: sprintf(t, "sbc $%.3x,$%.3x", opdp1, opdp0); break;
case 0xaa: sprintf(t, "mov1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0xab: sprintf(t, "inc $%.3x", opdp0); break;
case 0xac: sprintf(t, "inc $%.4x", opw); break;
case 0xad: sprintf(t, "cmp y,#$%.2x", op0); break;
case 0xae: sprintf(t, "pop a"); break;
case 0xaf: sprintf(t, "mov (x)+,a"); break;
case 0xb0: sprintf(t, "bcs $%.4x", __relb(op0, 2)); break;
case 0xb1: sprintf(t, "tcall 11"); break;
case 0xb2: sprintf(t, "clr5 $%.3x", opdp0); break;
case 0xb3: sprintf(t, "bbc5 $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0xb4: sprintf(t, "sbc a,$%.3x+x", opdp0); break;
case 0xb5: sprintf(t, "sbc a,$%.4x+x", opw); break;
case 0xb6: sprintf(t, "sbc a,$%.4x+y", opw); break;
case 0xb7: sprintf(t, "sbc a,($%.3x)+y", opdp0); break;
case 0xb8: sprintf(t, "sbc $%.3x,#$%.2x", opdp1, op0); break;
case 0xb9: sprintf(t, "sbc (x),(y)"); break;
case 0xba: sprintf(t, "movw ya,$%.3x", opdp0); break;
case 0xbb: sprintf(t, "inc $%.3x+x", opdp0); break;
case 0xbc: sprintf(t, "inc a"); break;
case 0xbd: sprintf(t, "mov sp,x"); break;
case 0xbe: sprintf(t, "das a"); break;
case 0xbf: sprintf(t, "mov a,(x)+"); break;
case 0xc0: sprintf(t, "di"); break;
case 0xc1: sprintf(t, "tcall 12"); break;
case 0xc2: sprintf(t, "set6 $%.3x", opdp0); break;
case 0xc3: sprintf(t, "bbs6 $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0xc4: sprintf(t, "mov $%.3x,a", opdp0); break;
case 0xc5: sprintf(t, "mov $%.4x,a", opw); break;
case 0xc6: sprintf(t, "mov (x),a"); break;
case 0xc7: sprintf(t, "mov ($%.3x+x),a", opdp0); break;
case 0xc8: sprintf(t, "cmp x,#$%.2x", op0); break;
case 0xc9: sprintf(t, "mov $%.4x,x", opw); break;
case 0xca: sprintf(t, "mov1 $%.4x:%d,c", opw & 0x1fff, opw >> 13); break;
case 0xcb: sprintf(t, "mov $%.3x,y", opdp0); break;
case 0xcc: sprintf(t, "mov $%.4x,y", opw); break;
case 0xcd: sprintf(t, "mov x,#$%.2x", op0); break;
case 0xce: sprintf(t, "pop x"); break;
case 0xcf: sprintf(t, "mul ya"); break;
case 0xd0: sprintf(t, "bne $%.4x", __relb(op0, 2)); break;
case 0xd1: sprintf(t, "tcall 13"); break;
case 0xd2: sprintf(t, "clr6 $%.3x", opdp0); break;
case 0xd3: sprintf(t, "bbc6 $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0xd4: sprintf(t, "mov $%.3x+x,a", opdp0); break;
case 0xd5: sprintf(t, "mov $%.4x+x,a", opw); break;
case 0xd6: sprintf(t, "mov $%.4x+y,a", opw); break;
case 0xd7: sprintf(t, "mov ($%.3x)+y,a", opdp0); break;
case 0xd8: sprintf(t, "mov $%.3x,x", opdp0); break;
case 0xd9: sprintf(t, "mov $%.3x+y,x", opdp0); break;
case 0xda: sprintf(t, "movw $%.3x,ya", opdp0); break;
case 0xdb: sprintf(t, "mov $%.3x+x,y", opdp0); break;
case 0xdc: sprintf(t, "dec y"); break;
case 0xdd: sprintf(t, "mov a,y"); break;
case 0xde: sprintf(t, "cbne $%.3x+x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0xdf: sprintf(t, "daa a"); break;
case 0xe0: sprintf(t, "clrv"); break;
case 0xe1: sprintf(t, "tcall 14"); break;
case 0xe2: sprintf(t, "set7 $%.3x", opdp0); break;
case 0xe3: sprintf(t, "bbs7 $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0xe4: sprintf(t, "mov a,$%.3x", opdp0); break;
case 0xe5: sprintf(t, "mov a,$%.4x", opw); break;
case 0xe6: sprintf(t, "mov a,(x)"); break;
case 0xe7: sprintf(t, "mov a,($%.3x+x)", opdp0); break;
case 0xe8: sprintf(t, "mov a,#$%.2x", op0); break;
case 0xe9: sprintf(t, "mov x,$%.4x", opw); break;
case 0xea: sprintf(t, "not1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0xeb: sprintf(t, "mov y,$%.3x", opdp0); break;
case 0xec: sprintf(t, "mov y,$%.4x", opw); break;
case 0xed: sprintf(t, "notc"); break;
case 0xee: sprintf(t, "pop y"); break;
case 0xef: sprintf(t, "sleep"); break;
case 0xf0: sprintf(t, "beq $%.4x", __relb(op0, 2)); break;
case 0xf1: sprintf(t, "tcall 15"); break;
case 0xf2: sprintf(t, "clr7 $%.3x", opdp0); break;
case 0xf3: sprintf(t, "bbc7 $%.3x,$%.4x", opdp0, __relb(op1, 3)); break;
case 0xf4: sprintf(t, "mov a,$%.3x+x", opdp0); break;
case 0xf5: sprintf(t, "mov a,$%.4x+x", opw); break;
case 0xf6: sprintf(t, "mov a,$%.4x+y", opw); break;
case 0xf7: sprintf(t, "mov a,($%.3x)+y", opdp0); break;
case 0xf8: sprintf(t, "mov x,$%.3x", opdp0); break;
case 0xf9: sprintf(t, "mov x,$%.3x+y", opdp0); break;
case 0xfa: sprintf(t, "mov $%.3x,$%.3x", opdp1, opdp0); break;
case 0xfb: sprintf(t, "mov y,$%.3x+x", opdp0); break;
case 0xfc: sprintf(t, "inc y"); break;
case 0xfd: sprintf(t, "mov y,a"); break;
case 0xfe: sprintf(t, "dbnz y,$%.4x", __relb(op0, 2)); break;
case 0xff: sprintf(t, "stop"); break;
}
t[strlen(t)] = ' ';
strcat(s, t);
sprintf(t, "A:%0.2x X:%0.2x Y:%0.2x SP:01%0.2x YA:%0.4x ",
sprintf(t, "A:%.2x X:%.2x Y:%.2x SP:01%.2x YA:%.4x ",
regs.a, regs.x, regs.y, regs.sp, regs.ya);
strcat(s, t);
sprintf(t, "%c%c%c%c%c%c%c%c",
(regs.p.n) ? 'N' : 'n',
(regs.p.v) ? 'V' : 'v',
(regs.p.p) ? 'P' : 'p',
(regs.p.b) ? 'B' : 'b',
(regs.p.h) ? 'H' : 'h',
(regs.p.i) ? 'I' : 'i',
(regs.p.z) ? 'Z' : 'z',
(regs.p.c) ? 'C' : 'c');
regs.p.n ? 'N' : 'n',
regs.p.v ? 'V' : 'v',
regs.p.p ? 'P' : 'p',
regs.p.b ? 'B' : 'b',
regs.p.h ? 'H' : 'h',
regs.p.i ? 'I' : 'i',
regs.p.z ? 'Z' : 'z',
regs.p.c ? 'C' : 'c');
strcat(s, t);
}
#endif //ifdef SMP_CPP
#endif //ifdef SMP_CPP

View File

@ -68,8 +68,8 @@ public:
alwaysinline void tick() {
//only test if Super Scope or Justifier is connected
if(iobit) {
if(ppucounter.vcounter() == latchy //test Y cursor position
&& ppucounter.hcounter() == latchx << 2 //test X cursor position (cycles == pixels << 2)
if(ppu.vcounter() == latchy //test Y cursor position
&& ppu.hcounter() == latchx << 2 //test X cursor position (cycles == pixels << 2)
&& latchy < (ppu.overscan() ? 240 : 225) //verify Y is not offscreen
&& latchx < 256 //verify X is not offscreen
) ppu.latch_counters();

View File

@ -1,13 +1,12 @@
#include <../base.hpp>
#define SNES_CPP
SNES snes;
BUSCORE bus;
CPUCORE cpu;
SMPCORE smp;
DSPCORE dsp;
PPUCORE ppu;
PPUcounter ppucounter;
SNES snes;
BUSCORE bus;
CPUCORE cpu;
SMPCORE smp;
DSPCORE dsp;
PPUCORE ppu;
BSXBase bsxbase;
BSXCart bsxcart;
@ -72,7 +71,6 @@ void SNES::power() {
scheduler.init();
ppucounter.reset();
cpu.power();
smp.power();
dsp.power();
@ -101,7 +99,7 @@ void SNES::power() {
for(unsigned i = 0x4200; i <= 0x421f; i++) memory::mmio.map(i, cpu);
for(unsigned i = 0x4300; i <= 0x437f; i++) memory::mmio.map(i, cpu);
if(expansion() == ExpansionBSX) { bsxbase.enable(); }
if(expansion() == ExpansionBSX) bsxbase.enable();
if(cartridge.info.bsxcart) bsxcart.enable();
if(cartridge.info.bsxflash) bsxflash.enable();
@ -125,14 +123,13 @@ void SNES::power() {
void SNES::reset() {
scheduler.init();
ppucounter.reset();
cpu.reset();
smp.reset();
dsp.reset();
ppu.reset();
bus.reset();
if(expansion() == ExpansionBSX) { bsxbase.reset(); }
if(expansion() == ExpansionBSX) bsxbase.reset();
if(cartridge.info.bsxcart) bsxcart.reset();
if(cartridge.info.bsxflash) bsxflash.reset();
@ -156,7 +153,7 @@ void SNES::reset() {
void SNES::scanline() {
video.scanline();
if(ppucounter.vcounter() == 241) {
if(ppu.vcounter() == 241) {
input.update();
video.update();
scheduler.exit();

View File

@ -77,12 +77,12 @@ void SNES::Video::update() {
}
void SNES::Video::scanline() {
unsigned y = ppucounter.vcounter();
unsigned y = ppu.vcounter();
if(y >= 240) return;
unsigned width = (ppu.hires() == false ? 256 : 512);
pline_width[y] = width;
iline_width[y * 2 + (int)ppucounter.field()] = width;
iline_width[y * 2 + (int)ppu.field()] = width;
frame_hires |= ppu.hires();
frame_interlace |= ppu.interlace();

View File

@ -205,8 +205,8 @@ void MainWindow::setup() {
menu_system_sep4.create();
menu_system_exit.create(translate["{{system}}Exit"]);
//menu_system.attach(menu_system_sep4);
//menu_system.attach(menu_system_exit);
menu_system.attach(menu_system_sep4);
menu_system.attach(menu_system_exit);
attach(menu_settings.create(translate["{{menu}}Settings"]));
menu_settings.attach(menu_settings_videomode.create(translate["Video Mode"]));

View File

@ -43,7 +43,7 @@ integral_setting System::contrast(config(), "system.colorfilter.contrast",
integral_setting System::brightness(config(), "system.colorfilter.brightness",
"Brightness", integral_setting::decimal, 0);
integral_setting System::gamma(config(), "system.colorfilter.gamma",
"Gamma", integral_setting::decimal, 80);
"Gamma", integral_setting::decimal, 100);
struct Video {
static integral_setting mode;
@ -59,6 +59,7 @@ struct Video {
} fullscreen;
static integral_setting aspect_ntsc_x, aspect_ntsc_y, aspect_pal_x, aspect_pal_y;
static integral_setting frameskip;
static integral_setting start_in_fullscreen_mode;
} video;
//0 = windowed, 1 = fullscreen, 2 = exclusive (not implemented yet)
@ -107,6 +108,9 @@ integral_setting Video::aspect_pal_x (config(), "video.aspect_pal_x", "", integ
integral_setting Video::aspect_pal_y (config(), "video.aspect_pal_y", "", integral_setting::decimal, 23);
integral_setting Video::frameskip("video.frameskip", "Video frameskip", integral_setting::decimal, 0);
integral_setting Video::start_in_fullscreen_mode(config(), "video.start_in_fullscreen_mode",
"If true, bsnes will start in fullscreen mode, rather than windowed mode.",
integral_setting::boolean, false);
struct Audio {
static integral_setting output_frequency, input_frequency;

View File

@ -24,27 +24,28 @@ using namespace libhiro;
void get_paths(const char *image) {
char temp[PATH_MAX] = "";
realpath(image, temp);
if(strlen(temp) != 0) {
for(int i = strlen(temp) - 1; i >= 0; i--) {
if(temp[i] == '\\') temp[i] = '/';
}
if(realpath(image, temp)) {
//remove program name
for(int i = strlen(temp) - 1; i >= 0; i--) {
if(temp[i] == '/') {
for(signed i = strlen(temp) - 1; i >= 0; i--) {
if(temp[i] == '/' || temp[i] == '\\') {
temp[i] = 0;
break;
}
}
if(strend(temp, "/") == false) strcat(temp, "/");
config::path.base = temp;
} else {
config::path.base = "";
}
if(strend(temp, "/") == false) strcat(temp, "/");
config::path.base = temp;
userpath(temp);
if(strend(temp, "/") == false) strcat(temp, "/");
config::path.user = temp;
if(userpath(temp)) {
if(strend(temp, "/") == false) strcat(temp, "/");
config::path.user = temp;
} else {
config::path.user = "";
}
}
void set_config_filenames() {

View File

@ -1,5 +1,5 @@
uintptr_t AudioSettingsWindow::volume_change(event_t) {
config::audio.volume = 10 + svolume.get_position();
config::audio.volume = 25 + cvolume.get_selection() * 25;
audio.set(Audio::Volume, config::audio.volume);
sync_ui();
@ -7,18 +7,19 @@ uintptr_t AudioSettingsWindow::volume_change(event_t) {
}
uintptr_t AudioSettingsWindow::latency_change(event_t) {
config::audio.latency = 25 + slatency.get_position() * 5;
config::audio.latency = 20 + clatency.get_selection() * 20;
audio.set(Audio::Latency, config::audio.latency);
sync_ui();
return true;
}
uintptr_t AudioSettingsWindow::output_change(event_t) {
switch(soutput.get_position()) {
uintptr_t AudioSettingsWindow::frequency_change(event_t) {
switch(cfrequency.get_selection()) {
case 0: config::audio.output_frequency = 32000; break;
case 1: config::audio.output_frequency = 44100; break; default:
case 2: config::audio.output_frequency = 48000; break;
case 3: config::audio.output_frequency = 96000; break;
}
audio.set(Audio::Frequency, config::audio.output_frequency);
@ -28,49 +29,8 @@ uintptr_t AudioSettingsWindow::output_change(event_t) {
return true;
}
uintptr_t AudioSettingsWindow::input_change(event_t) {
config::audio.input_frequency = sinput.get_position() + 32000 - 200;
event::update_emulation_speed(config::system.emulation_speed);
sync_ui();
return true;
}
uintptr_t AudioSettingsWindow::volume_tick(event_t) {
char t[256];
evolume.get_text(t, sizeof t);
config::audio.volume = strdec(t);
audio.set(Audio::Volume, config::audio.volume);
sync_ui();
return true;
}
uintptr_t AudioSettingsWindow::latency_tick(event_t) {
char t[256];
elatency.get_text(t, sizeof t);
config::audio.latency = strdec(t);
audio.set(Audio::Latency, config::audio.latency);
sync_ui();
return true;
}
uintptr_t AudioSettingsWindow::output_tick(event_t) {
char t[256];
eoutput.get_text(t, sizeof t);
config::audio.output_frequency = strdec(t);
audio.set(Audio::Frequency, config::audio.output_frequency);
event::update_emulation_speed(config::system.emulation_speed);
sync_ui();
return true;
}
uintptr_t AudioSettingsWindow::input_tick(event_t) {
char t[256];
einput.get_text(t, sizeof t);
config::audio.input_frequency = strdec(t);
uintptr_t AudioSettingsWindow::skew_change(event_t) {
config::audio.input_frequency = sskew.get_position() + 32000 - 200;
event::update_emulation_speed(config::system.emulation_speed);
sync_ui();
@ -78,133 +38,87 @@ uintptr_t AudioSettingsWindow::input_tick(event_t) {
}
void AudioSettingsWindow::sync_ui() {
lvolume.set_text(string()
<< translate["Volume:"] << " "
<< (int)config::audio.volume << "%"
);
cvolume.set_selection((config::audio.volume - 25) / 25);
llatency.set_text(string()
<< translate["Latency:"] << " "
<< (int)config::audio.latency << "ms"
);
unsigned position;
if(config::audio.output_frequency <= 32000) position = 0;
else if(config::audio.output_frequency <= 44100) position = 1;
else if(config::audio.output_frequency <= 48000) position = 2;
else position = 3;
cfrequency.set_selection(position);
loutput.set_text(string()
<< translate["Frequency:"] << " "
<< (int)config::audio.output_frequency << "hz"
);
clatency.set_selection((config::audio.latency - 20) / 20);
if(config::advanced.enable == false) {
int input_freq = config::audio.input_frequency - 32000;
string adjust;
if(input_freq > 0) adjust << "+";
adjust << input_freq << "hz";
linput.set_text(string()
<< translate["Frequency adjust:"] << " "
<< adjust
);
} else {
linput.set_text(string() << translate["Frequency adjust:"] << " " << (int)config::audio.input_frequency << "hz");
}
if(config::advanced.enable == false) {
svolume.set_position(config::audio.volume - 10);
slatency.set_position((config::audio.latency - 25) / 5);
unsigned position;
if(config::audio.output_frequency <= 32000) position = 0;
else if(config::audio.output_frequency <= 44100) position = 1;
else position = 2;
soutput.set_position(position);
sinput.set_position(config::audio.input_frequency - 32000 + 200);
} else {
evolume.set_text(string() << (int)config::audio.volume);
elatency.set_text(string() << (int)config::audio.latency);
eoutput.set_text(string() << (int)config::audio.output_frequency);
einput.set_text(string() << (int)config::audio.input_frequency);
}
lskew.set_text(string() << translate["{{audio}}Frequency adjust:"] << " " << (int)config::audio.input_frequency << "hz");
sskew.set_position(config::audio.input_frequency - 32000 + 200);
}
void AudioSettingsWindow::setup() {
create(0, 451, 370);
lvolume.create(0, 223, 18);
svolume.create(0, 451, 30, 91);
evolume.create(0, 118, 25);
bvolume.create(0, 100, 25, translate["{{audio}}Set"]);
lvolume.create(0, 147, 18, translate["{{audio}}Volume:"]);
cvolume.create(0, 147, 25);
cvolume.add_item( "25%");
cvolume.add_item( "50%");
cvolume.add_item( "75%");
cvolume.add_item("100%");
if(config::advanced.enable == true) {
cvolume.add_item("125%");
cvolume.add_item("150%");
cvolume.add_item("175%");
cvolume.add_item("200%");
}
llatency.create(0, 223, 18);
slatency.create(0, 451, 30, 26);
elatency.create(0, 118, 25);
blatency.create(0, 100, 25, translate["{{audio}}Set"]);
lfrequency.create(0, 147, 18, translate["{{audio}}Frequency:"]);
cfrequency.create(0, 147, 25);
cfrequency.add_item("32Khz");
cfrequency.add_item("44.1Khz");
cfrequency.add_item("48Khz");
if(config::advanced.enable == true) {
cfrequency.add_item("96Khz");
}
loutput.create(0, 223, 18);
soutput.create(0, 451, 30, 3);
eoutput.create(0, 118, 25);
boutput.create(0, 100, 25, translate["{{audio}}Set"]);
llatency.create(0, 147, 18, translate["{{audio}}Latency:"]);
clatency.create(0, 147, 25);
clatency.add_item( "20ms");
clatency.add_item( "40ms");
clatency.add_item( "60ms");
clatency.add_item( "80ms");
clatency.add_item("100ms");
clatency.add_item("120ms");
if(config::advanced.enable == true) {
clatency.add_item("140ms");
clatency.add_item("160ms");
}
linput.create(0, 223, 18);
sinput.create(0, 451, 30, 401);
einput.create(0, 118, 25);
binput.create(0, 100, 25, translate["{{audio}}Set"]);
lskew.create(0, 451, 18, translate["{{audio}}Frequency adjust:"]);
sskew.create(0, 451, 30, 401);
note.create(0, 475, 54, string()
note.create(0, 451, 54, string()
<< translate["{{audio}}Frequency adjust is used to improve video sync timing."] << "\n"
<< translate["{{audio}}Lower value to clean audio output."] << "\n"
<< translate["{{audio}}Raise value to smooth video output."]
);
unsigned y = 0;
if(config::advanced.enable == false) {
attach(lvolume, 0, y); y += 18;
attach(svolume, 0, y); y += 30;
if(audio.cap(Audio::Latency) == true) {
attach(llatency, 0, y); y += 18;
attach(slatency, 0, y); y += 30;
}
if(audio.cap(Audio::Frequency) == true) {
attach(loutput, 0, y); y += 18;
attach(soutput, 0, y); y += 30;
}
attach(linput, 0, y); y += 18;
attach(sinput, 0, y); y += 30;
} else {
attach(lvolume, 0, y);
attach(llatency, 228, y); y += 18;
attach(evolume, 0, y);
attach(bvolume, 123, y);
attach(elatency, 228, y);
attach(blatency, 351, y); y += 25 + 5;
attach(lvolume, 0, y);
attach(lfrequency, 152, y);
attach(llatency, 304, y); y += 18;
attach(loutput, 0, y);
attach(linput, 228, y); y += 18;
attach(cvolume, 0, y);
attach(cfrequency, 152, y);
attach(clatency, 304, y); y += 30;
attach(eoutput, 0, y);
attach(boutput, 123, y);
attach(einput, 228, y);
attach(binput, 351, y); y += 25 + 5;
attach(lskew, 0, y); y += 18;
attach(sskew, 0, y); y += 30;
if(audio.cap(Audio::Latency) == false) {
elatency.disable();
blatency.disable();
}
attach(note, 0, y);
if(audio.cap(Audio::Frequency) == false) {
eoutput.disable();
boutput.disable();
}
}
attach(note, 0, y);
svolume.on_change = bind(&AudioSettingsWindow::volume_change, this);
slatency.on_change = bind(&AudioSettingsWindow::latency_change, this);
soutput.on_change = bind(&AudioSettingsWindow::output_change, this);
sinput.on_change = bind(&AudioSettingsWindow::input_change, this);
bvolume.on_tick = bind(&AudioSettingsWindow::volume_tick, this);
blatency.on_tick = bind(&AudioSettingsWindow::latency_tick, this);
boutput.on_tick = bind(&AudioSettingsWindow::output_tick, this);
binput.on_tick = bind(&AudioSettingsWindow::input_tick, this);
cvolume.on_change = bind(&AudioSettingsWindow::volume_change, this);
cfrequency.on_change = bind(&AudioSettingsWindow::frequency_change, this);
clatency.on_change = bind(&AudioSettingsWindow::latency_change, this);
sskew.on_change = bind(&AudioSettingsWindow::skew_change, this);
sync_ui();
}

View File

@ -1,36 +1,19 @@
class AudioSettingsWindow : public Window {
public:
Label lvolume;
Slider svolume;
Editbox evolume;
Button bvolume;
Label llatency;
Slider slatency;
Editbox elatency;
Button blatency;
Label loutput;
Slider soutput;
Editbox eoutput;
Button boutput;
Label linput;
Slider sinput;
Editbox einput;
Button binput;
Label note;
Label lvolume;
Combobox cvolume;
Label lfrequency;
Combobox cfrequency;
Label llatency;
Combobox clatency;
Label lskew;
Slider sskew;
Label note;
uintptr_t volume_change(event_t);
uintptr_t latency_change(event_t);
uintptr_t output_change(event_t);
uintptr_t input_change(event_t);
uintptr_t volume_tick(event_t);
uintptr_t latency_tick(event_t);
uintptr_t output_tick(event_t);
uintptr_t input_tick(event_t);
uintptr_t frequency_change(event_t);
uintptr_t skew_change(event_t);
void sync_ui();
void setup();

View File

@ -1,54 +1,57 @@
void VideoSettingsWindow::setup() {
create(0, 451, 370);
lcontrast.create (0, 451, 18);
contrast.create (0, 451, 30, 192);
lbrightness.create (0, 451, 18);
brightness.create (0, 451, 30, 192);
lgamma.create (0, 451, 18);
gamma.create (0, 451, 30, 191);
gamma_ramp.create (0, 223, 18, translate["Gamma ramp"]);
sepia.create (0, 223, 18, translate["Sepia"]);
grayscale.create (0, 223, 18, translate["Grayscale"]);
invert.create (0, 223, 18, translate["Invert colors"]);
preset_optimal.create (0, 223, 25, translate["Optimal Preset"]);
preset_standard.create(0, 223, 25, translate["Standard Preset"]);
lcontrast.create (0, 451, 18);
contrast.create (0, 451, 30, 191);
lbrightness.create(0, 451, 18);
brightness.create (0, 451, 30, 191);
lgamma.create (0, 451, 18);
gamma.create (0, 451, 30, 191);
gamma_ramp.create (0, 223, 18, translate["Gamma ramp"]);
sepia.create (0, 223, 18, translate["Sepia"]);
grayscale.create (0, 223, 18, translate["Grayscale"]);
invert.create (0, 223, 18, translate["Invert colors"]);
sync_ui();
uint y = 0;
attach(lcontrast, 0, y); y += 18;
attach(contrast, 0, y); y += 30;
attach(lbrightness, 0, y); y += 18;
attach(brightness, 0, y); y += 30;
attach(lgamma, 0, y); y += 18;
attach(gamma, 0, y); y += 30;
attach(gamma_ramp, 0, y);
attach(sepia, 228, y); y += 18;
attach(grayscale, 0, y);
attach(invert, 228, y); y += 18 + 5;
attach(preset_optimal, 0, y);
attach(preset_standard, 228, y); y += 25;
unsigned y = 0;
attach(lcontrast, 0, y); y += 18;
attach(contrast, 0, y); y += 30;
attach(lbrightness, 0, y); y += 18;
attach(brightness, 0, y); y += 30;
attach(lgamma, 0, y); y += 18;
attach(gamma, 0, y); y += 30;
contrast.on_change = bind(&VideoSettingsWindow::contrast_change, this);
brightness.on_change = bind(&VideoSettingsWindow::brightness_change, this);
gamma.on_change = bind(&VideoSettingsWindow::gamma_change, this);
gamma_ramp.on_tick = bind(&VideoSettingsWindow::gammaramp_tick, this);
sepia.on_tick = bind(&VideoSettingsWindow::sepia_tick, this);
grayscale.on_tick = bind(&VideoSettingsWindow::grayscale_tick, this);
invert.on_tick = bind(&VideoSettingsWindow::invert_tick, this);
preset_optimal.on_tick = bind(&VideoSettingsWindow::optimal_tick, this);
preset_standard.on_tick = bind(&VideoSettingsWindow::standard_tick, this);
attach(gamma_ramp, 0, y);
attach(sepia, 228, y); y += 18;
attach(grayscale, 0, y);
attach(invert, 228, y); y += 18 + 5;
contrast.on_change = bind(&VideoSettingsWindow::contrast_change, this);
brightness.on_change = bind(&VideoSettingsWindow::brightness_change, this);
gamma.on_change = bind(&VideoSettingsWindow::gamma_change, this);
gamma_ramp.on_tick = bind(&VideoSettingsWindow::gammaramp_tick, this);
sepia.on_tick = bind(&VideoSettingsWindow::sepia_tick, this);
grayscale.on_tick = bind(&VideoSettingsWindow::grayscale_tick, this);
invert.on_tick = bind(&VideoSettingsWindow::invert_tick, this);
}
//update all UI controls to match config file values ...
void VideoSettingsWindow::sync_ui() {
ui_lock = true; //supress event messages while syncing UI elements, prevents infinite recursion
contrast.set_position(config::system.contrast + 96);
lcontrast.set_text(string() << translate["Contrast"] << ": " << (int)config::system.contrast);
brightness.set_position(config::system.brightness + 96);
lbrightness.set_text(string() << translate["Brightness"] << ": " << (int)config::system.brightness);
gamma.set_position(config::system.gamma - 10);
lgamma.set_text(string() << translate["Gamma"] << ": " << (int)config::system.gamma); //TODO: print gamma as "%0.2f" / 100.0
contrast.set_position(config::system.contrast + 95);
lcontrast.set_text(string()
<< translate["Contrast adjust"] << ": "
<< ((int)config::system.contrast > 0 ? "+" : "")
<< (int)config::system.contrast << "%");
brightness.set_position(config::system.brightness + 95);
lbrightness.set_text(string()
<< translate["Brightness adjust"] << ": "
<< ((int)config::system.brightness > 0 ? "+" : "")
<< (int)config::system.brightness << "%");
gamma.set_position(config::system.gamma - 5);
lgamma.set_text(string()
<< translate["Gamma adjust"] << ": "
<< ((int)config::system.gamma > 100 ? "+" : "")
<< (int)(config::system.gamma - 100) << "%");
gamma_ramp.check(config::system.gamma_ramp);
sepia.check(config::system.sepia);
grayscale.check(config::system.grayscale);
@ -62,36 +65,34 @@ void VideoSettingsWindow::sync_ui() {
libfilter::colortable.enable_grayscale(config::system.grayscale);
libfilter::colortable.enable_invert(config::system.invert);
libfilter::colortable.update();
ui_lock = false;
}
uintptr_t VideoSettingsWindow::contrast_change(event_t) {
if(!ui_lock && config::system.contrast != contrast.get_position() - 96) {
config::system.contrast = contrast.get_position() - 96;
if(config::system.contrast != contrast.get_position() - 95) {
config::system.contrast = contrast.get_position() - 95;
sync_ui();
}
return true;
}
uintptr_t VideoSettingsWindow::brightness_change(event_t) {
if(!ui_lock && config::system.brightness != brightness.get_position() - 96) {
config::system.brightness = brightness.get_position() - 96;
if(config::system.brightness != brightness.get_position() - 95) {
config::system.brightness = brightness.get_position() - 95;
sync_ui();
}
return true;
}
uintptr_t VideoSettingsWindow::gamma_change(event_t) {
if(!ui_lock && config::system.gamma != gamma.get_position() + 10) {
config::system.gamma = gamma.get_position() + 10;
if(config::system.gamma != gamma.get_position() + 5) {
config::system.gamma = gamma.get_position() + 5;
sync_ui();
}
return true;
}
uintptr_t VideoSettingsWindow::gammaramp_tick(event_t) {
if(!ui_lock && config::system.gamma_ramp != gamma_ramp.checked()) {
if(config::system.gamma_ramp != gamma_ramp.checked()) {
config::system.gamma_ramp = gamma_ramp.checked();
sync_ui();
}
@ -99,7 +100,7 @@ uintptr_t VideoSettingsWindow::gammaramp_tick(event_t) {
}
uintptr_t VideoSettingsWindow::sepia_tick(event_t) {
if(!ui_lock && config::system.sepia != sepia.checked()) {
if(config::system.sepia != sepia.checked()) {
config::system.sepia = sepia.checked();
sync_ui();
}
@ -107,7 +108,7 @@ uintptr_t VideoSettingsWindow::sepia_tick(event_t) {
}
uintptr_t VideoSettingsWindow::grayscale_tick(event_t) {
if(!ui_lock && config::system.grayscale != grayscale.checked()) {
if(config::system.grayscale != grayscale.checked()) {
config::system.grayscale = grayscale.checked();
sync_ui();
}
@ -115,37 +116,9 @@ uintptr_t VideoSettingsWindow::grayscale_tick(event_t) {
}
uintptr_t VideoSettingsWindow::invert_tick(event_t) {
if(!ui_lock && config::system.invert != invert.checked()) {
if(config::system.invert != invert.checked()) {
config::system.invert = invert.checked();
sync_ui();
}
return true;
}
uintptr_t VideoSettingsWindow::optimal_tick(event_t) {
config::system.contrast = 0;
config::system.brightness = 0;
config::system.gamma = 80;
config::system.gamma_ramp = true;
config::system.sepia = false;
config::system.grayscale = false;
config::system.invert = false;
sync_ui();
return true;
}
uintptr_t VideoSettingsWindow::standard_tick(event_t) {
config::system.contrast = 0;
config::system.brightness = 0;
config::system.gamma = 100;
config::system.gamma_ramp = false;
config::system.sepia = false;
config::system.grayscale = false;
config::system.invert = false;
sync_ui();
return true;
}
VideoSettingsWindow::VideoSettingsWindow() {
ui_lock = false;
}

View File

@ -12,13 +12,9 @@ public:
Checkbox grayscale;
Checkbox invert;
Button preset_optimal;
Button preset_standard;
void setup();
void sync_ui();
bool ui_lock;
uintptr_t contrast_change(event_t);
uintptr_t brightness_change(event_t);
uintptr_t gamma_change(event_t);
@ -26,8 +22,4 @@ public:
uintptr_t sepia_tick(event_t);
uintptr_t grayscale_tick(event_t);
uintptr_t invert_tick(event_t);
uintptr_t optimal_tick(event_t);
uintptr_t standard_tick(event_t);
VideoSettingsWindow();
} window_video_settings;

View File

@ -47,6 +47,7 @@ void ui_init() {
window_advanced.setup();
window_settings.setup();
config::video.mode = (config::video.start_in_fullscreen_mode == false) ? 0 : 1;
event::update_opacity();
event::update_video_settings(); //call first time to resize main window and update menubar

BIN
test_hdma.smc Normal file

Binary file not shown.

BIN
test_hdmasync.smc Normal file

Binary file not shown.

BIN
test_hdmatiming.smc Normal file

Binary file not shown.

BIN
test_irq.smc Normal file

Binary file not shown.

BIN
test_irq4200.smc Normal file

Binary file not shown.

BIN
test_irq4209.smc Normal file

Binary file not shown.

BIN
test_irqb.smc Normal file

Binary file not shown.

BIN
test_nmi.smc Normal file

Binary file not shown.