📄 cpu.cpp
字号:
"XOR <%b", 2, 3,
"SHR <%b", 2, 5,
"XOR [<%b]", 2, 6,
// 0x48
"PSH A", 1, 3, // PHA
"XOR %#", 2, 2,
"SHR A", 1, 2,
"PSH PBR", 1, 3, // PHK
"JMP %w", 3, 3,
"XOR %w", 3, 4,
"SHR %w", 3, 6,
"XOR %L", 4, 5,
// 0x50
"BVC @%b", 2, 2,
"XOR (<%b),Y", 2, 5,
"XOR (<%b)", 2, 5,
"XOR (<%b,s),Y", 2, 7,
"MVN XYA %w", 3, 7,
"XOR <%b,X", 2, 4,
"SHR <%b,X", 2, 6,
"XOR [<%b],Y", 2, 6,
// 0x58
"CLI", 1, 2,
"XOR %w,Y", 3, 4,
"PSH Y", 1, 3, // PHY
"TAD", 1, 2,
"JML %L", 4, 4,
"XOR %w,X", 3, 4,
"SHR %w,X", 3, 7,
"XOR %L,X", 4, 5,
// 0x60
"RTS", 1, 6,
"ADC (<%b,X)", 2, 6,
"PSH @%w", 3, 6, // PER
"ADC <%b,s", 2, 4,
"CLR <%b", 2, 3,
"ADC <%b", 2, 3,
"ROR <%b", 2, 5,
"ADC [<%b]", 2, 6,
// 0x68
"PUL A", 1, 4, // PLA
"ADC %#", 2, 2,
"ROR A", 1, 2,
"RTL", 1, 6,
"JMP (%w)", 3, 5,
"ADC %w", 3, 4,
"ROR %w", 3, 6,
"ADC %L", 4, 5,
// 0x70
"BVS @%b", 2, 2,
"ADC (<%b),Y", 2, 5,
"ADC (<%b)", 2, 5,
"ADC (<%b,s),Y", 2, 7,
"CLR <%b,X", 2, 4,
"ADC <%b,X", 2, 4,
"ROR <%b,X", 2, 6,
"ADC [<%b],Y", 2, 6,
// 0x78
"SEI", 1, 2,
"ADC %w,Y", 3, 4,
"PUL Y", 1, 4, // PLY
"TDA", 1, 2,
"JMP (%w,X)", 3, 6,
"ADC %w,X", 3,4,
"ROR %w,X", 3,7,
"ADC %L,X",4,5,
// 0x80
"BRA @%b", 2, 2,
"STA (<%b,X)", 2, 6,
"BRL @%w", 3, 3,
"STA <%b,S", 2, 4,
"STY <%b", 2, 3,
"STA <%b", 2, 3,
"STX <%b", 2, 3,
"STA [<%b]", 2, 6,
// 0x88
"DEY", 1, 2,
"BIT %#", 2, 2,
"TXA", 1, 2,
"PSH DBR", 1, 3, // PHB
"STY %w", 3, 4,
"STA %w", 3, 4,
"STX %w", 3, 4,
"STA %L", 4, 5,
// 0x90
"BCC @%b", 2, 2,
"STA (<%b),Y", 2, 6,
"STA (<%b)", 2, 5,
"STA (<%b,s),Y", 2, 7,
"STY <%b,X", 2, 4,
"STA <%b,X", 2, 4,
"STX <%b,Y", 2, 4,
"STA [<%b],Y", 2, 6,
// 0x98
"TYA", 1, 2,
"STA %w,Y", 3, 5,
"TXS", 1, 2,
"TXY", 1, 2,
"CLR %w", 3, 4,
"STA %w,X", 3, 5,
"CLR %w,X", 3, 5,
"STA %L,X", 4, 5,
// 0xA0
"LDY %#i", 2, 2,
"LDA (<%b,X)", 2, 6,
"LDX %#i", 2, 2,
"LDA <%b,S", 2, 4,
"LDY <%b", 2, 3,
"LDA <%b", 2, 3,
"LDX <%b", 2, 3,
"LDA [<%b]", 2, 6,
// 0xA8
"TAY", 1, 2,
"LDA %#", 2, 2,
"TAX", 1, 2,
"PUL DBR", 1, 4, // PLB
"LDY %w", 3, 4,
"LDA %w", 3, 4,
"LDX %w", 3, 4,
"LDA %L", 4, 5,
// 0xB0
"BCS @%b", 2, 2,
"LDA (<%b),Y", 2, 5,
"LDA (<%b)", 2, 5,
"LDA (<%b,S),Y", 2, 7,
"LDY <%b,X", 2, 4,
"LDA <%b,X", 2, 4,
"LDX <%b,Y", 2, 4,
"LDA [<%b],Y", 2, 6,
// 0xB8
"CLV", 1, 2,
"LDA %w,Y", 3, 4,
"TSX", 1, 2,
"TYX", 1, 2,
"LDY %w,X", 3, 4,
"LDA %w,X", 3, 4,
"LDX %w,Y", 3, 4,
"LDA %L,X",4, 5,
// 0xC0
"CPY %#i", 2, 2,
"CMP (<%b,X)", 2, 6,
"CLP %#b", 2, 3,
"CMP <%b,S", 2, 4,
"CPY <%b", 2, 3,
"CMP <%b", 2, 3,
"DEC <%b", 2, 5,
"CMP [<%b]", 2,6,
// 0xC8
"INY", 1, 2,
"CMP %#", 2, 2,
"DEX", 1, 2,
"WAI", 1, 3,
"CPY %w", 3, 4,
"CMP %w", 3, 4,
"DEC %w", 3, 6,
"CMP %L", 4, 5,
// 0xD0
"BNE @%b", 2, 2,
"CMP (<%b),Y", 2, 5,
"CMP (<%b)", 2, 5,
"CMP (<%b,S),Y", 2, 7,
"PSH %b", 2, 6, // PEI
"CMP <%b,X", 2, 4,
"DEC <%b,X", 2, 6,
"CMP [<%b],Y", 2, 6,
// 0xD8
"CLD", 1, 2,
"CMP %w,Y", 3, 4,
"PSH X", 1, 3, // PHX
"HLT", 1, 3, // STP
"JML (%w)", 3, 6,
"CMP %w,X", 3, 4,
"DEC %w,X", 3, 7,
"CMP %L,X", 4, 5,
// 0xE0
"CPX %#i", 2, 2,
"SBC (<%b,X)", 2, 6,
"SEP %#b", 2, 3,
"SBC <%b,s", 2, 4,
"CPX <%b", 2, 3,
"SBC <%b", 2, 3,
"INC <%b", 2, 5,
"SBC [<%b]", 2, 6,
// 0xE8
"INX", 1, 2,
"SBC %#", 2, 2,
"NOP", 1, 2,
"SWA", 1, 3,
"CPX %w", 3, 4,
"SBC %w", 3, 4,
"INC %w", 3, 6,
"SBC %L", 4, 5,
// 0xF0
"BEQ @%b", 2, 2,
"SBC (<%b),Y", 2, 5,
"SBC (<%b)", 2, 5,
"SBC (<%b,S),Y", 2, 7,
"PSH %#w", 3, 5, // PEA
"SBC <%b,X", 2, 4,
"INC <%b,X", 2, 6,
"SBC [<%b],Y", 2, 6,
// 0xF8
"SED", 1, 2,
"SBC %w,Y", 3, 4,
"PUL X", 1, 4, // PLX
"XCE", 1, 2,
"JSR (%w,X)", 3, 6,
"SBC %w,X", 3, 4,
"INC %w,X", 3, 7,
"SBC %L,X", 4, 5
};
// ADDRESSING MODES - several categories, one mode from each category can be combined
// None of the instructions can use all combinations, and certain combinations are
// never used with any instruction.
// Used to calculate memory address:
// Absolute: Argument is two bytes and specifies a memory location
// + Long: Argument is three bytes instead opcode $addr
// Direct: Argument is one byte; memory address formed by adding D.
// Bank is always 0, unless indirect addressing is also used, in
// which case the bank is the program bank. opcode <$addr
// Stack Relative: Argument is one byte, which is added to the stack pointer
// to find the final address. opcode $addr,S
// Indexed addressing:
// Indexed: Memory location argument is added to X or Y to get the final
// memory location. opcode $addr,X or Y
// Note that certain indexed addressing modes only work with the X register
// or only with the Y register.
//
// Note! The above addressing mode specifiers are used only to specify the
// size of the argument and how it is used. The specifiers DO NOT SPECIFY
// anything about the actual memory location being referenced.
// For example, suppose the Absolute Indexed mode is used. This means that
// the argument to the opcode is 16 bits and will be added to an index
// register. It does not, however, mean that the value at the calculated
// memory location will be a 16-bit value. The size of the value at the memory
// location is determined by either:
// a. whether the processor is in 16-bit mode (and whether E=0), or
// b. if indirect addressing is used, whether the Long Indirect mode is used.
//
// Indirect addressing:
// Indirect: Uses indirection (pointers). In other words, after the memory
// location is found and the contents are loaded, the contents are used as
// a SECOND memory location and the value at the second memory location is
// used in the operation. opcode ($addr)
// + Direct Long: Normally, the pointer found at the specified location
// will be two bytes. If Direct Indirect Long is used, the pointer
// at the memory address found will be a three-byte long address.
// opcode [$addr]
// Indexed Indirect (preindexed; (arg,x)) vs. Indirect Indexed (postindexed;
// (arg),x): remember, these two are different!
// There is also two more modes, which are never used with any other specifiers:
// Implied: Opcode has no arguments (The "accumulator" addressing mode is like
// an implied mode and it means it acts on the accumulator only.)
// Immediate: The argument specifies an actual constant value to be used,
// rather than a memory address. [opcode #$XX or #$XXXX]
// some immediate addressing modes always have a 8-bit argument (CLP, SEP);
// others have an 8/16 bit argument depending on the status of the M bit;
// others have an 8/16 bit argument depending on the status of the X bit.
// (When the programmer writes a immediate addressing instruction he must make
// sure the assembler knows what size to make it!)
#define AA_ROM (byte *)0x1
#define AA_HIROM (byte *)0x2
//#define AA_LOROM_x40 (byte *)0x3
#define AA_NOTHING (byte *)0x4
// Placeholder in the addressarea array, needed since the rom variable is initialized to NULL
/*struct addressarea { // old mem map based on Duncanthrax's doc
// this is a representation of the SNES memory map. It's used by the getstartaddresses()
// function to build the address mapping table, *startaddr[].
byte b1, b2;
word a1, a2;
byte *start;
boolean continuous;
} loromarea [] = {
{ 0x00, 0x3F, 0x0000, 0x1FFF, ram, },
{ 0x00, 0x3F, 0x2000, 0x5FFF, registers, },
{ 0x00, 0x3F, 0x6000, 0x7FFF, expram, },
{ 0x00, 0x3F, 0x8000, 0xFFFF, AA_ROM, true },
{ 0x40, 0x7C, 0x0000, 0x7FFF, AA_ROM, true },
{ 0x40, 0x7C, 0x8000, 0xFFFF, AA_ROM, true },
{ 0x7D, 0x7D, 0x0000, 0xFFFF, sram, },
{ 0x7E, 0x7F, 0x0000, 0xFFFF, ram, true },
{ 0x80, 0xBF, 0x0000, 0x1FFF, ram, },
{ 0x80, 0xBF, 0x2000, 0x5FFF, registers, },
{ 0x80, 0xBF, 0x6000, 0x7FFF, expram, },
{ 0x80, 0xBF, 0x8000, 0xFFFF, AA_ROM, true },
{ 0xC0, 0xFC, 0x0000, 0x7FFF, AA_ROM, true },
{ 0xC0, 0xFC, 0x8000, 0xFFFF, AA_ROM, true },
{ 0xFD, 0xFD, 0x0000, 0xFFFF, sram, },
{ 0xFE, 0xFF, 0x0000, 0xFFFF, ram, true },
{ 0 }
}, hiromarea [] = {
{ 0x00, 0x3F, 0x0000, 0x1FFF, ram, },
{ 0x00, 0x3F, 0x2000, 0x5FFF, registers, },
{ 0x00, 0x3F, 0x6000, 0x7FFF, sram, },
{ 0x00, 0x3F, 0x8000, 0xFFFF, AA_ROM, true },
{ 0x40, 0x7D, 0x0000, 0xFFFF, AA_ROM, true },
{ 0x7E, 0x7F, 0x0000, 0xFFFF, ram, true },
{ 0x80, 0xBF, 0x0000, 0x1FFF, ram, },
{ 0x80, 0xBF, 0x2000, 0x5FFF, registers, },
{ 0x80, 0xBF, 0x6000, 0x7FFF, sram, },
{ 0x80, 0xBF, 0x8000, 0xFFFF, AA_ROM, true },
{ 0xC0, 0xFF, 0x0000, 0xFFFF, AA_ROM, true },
{ 0 }
};*/
struct addressarea {
// this is a representation of the SNES memory map. It's used by the getstartaddresses()
// function to build the address mapping table, *startaddr[].
byte b1, b2;
word a1, a2;
byte *start;
boolean continuous;
word spacing;
} loromarea [] = {
{ 0x00, 0x3F, 0x0000, 0x1FFF, ram, },
{ 0x00, 0x3F, 0x2000, 0x5FFF, registers, },
{ 0x00, 0x3F, 0x6000, 0x7FFF, expram, },
{ 0x00, 0x6F, 0x8000, 0xFFFF, AA_ROM, true },
{ 0x40, 0x6F, 0x0000, 0x7FFF, AA_NOTHING },
{ 0x70, 0x77, 0x0000, 0xFFFF, sram },
{ 0x78, 0x7D, 0x0000, 0xFFFF, AA_NOTHING },
{ 0x7E, 0x7F, 0x0000, 0xFFFF, ram, true },
{ 0x80, 0xBF, 0x0000, 0x1FFF, ram, },
{ 0x80, 0xBF, 0x2000, 0x5FFF, registers, },
{ 0x80, 0xBF, 0x6000, 0x7FFF, expram, },
{ 0x80, 0xEF, 0x8000, 0xFFFF, AA_ROM, true },
{ 0xC0, 0xEF, 0x0000, 0x7FFF, AA_NOTHING },
{ 0xF0, 0xF7, 0x0000, 0xFFFF, sram },
{ 0xF8, 0xFD, 0x0000, 0xFFFF, AA_NOTHING },
{ 0xFE, 0xFF, 0x0000, 0xFFFF, ram, true },
{ 0 }
}, hiromarea [] = {
{ 0x00, 0x3F, 0x0000, 0x1FFF, ram, },
{ 0x00, 0x3F, 0x2000, 0x5FFF, registers, },
{ 0x00, 0x2F, 0x6000, 0x7FFF, expram, },
{ 0x30, 0x3F, 0x6000, 0x7FFF, sram, true },
{ 0x00, 0x3F, 0x8000, 0xFFFF, AA_HIROM, true, 0x8000 },
{ 0x40, 0x6F, 0x0000, 0xFFFF, AA_ROM, true },
{ 0x70, 0x77, 0x0000, 0xFFFF, sram },
{ 0x78, 0x7D, 0x0000, 0xFFFF, AA_NOTHING },
{ 0x7E, 0x7F, 0x0000, 0xFFFF, ram, true },
{ 0x80, 0xBF, 0x0000, 0x1FFF, ram, },
{ 0x80, 0xBF, 0x2000, 0x5FFF, registers, },
{ 0x80, 0xAF, 0x6000, 0x7FFF, expram, },
{ 0xB0, 0xBF, 0x6000, 0x7FFF, sram, true },
{ 0x80, 0xBF, 0x8000, 0xFFFF, AA_HIROM, true, 0x8000 },
{ 0xC0, 0xFF, 0x0000, 0xFFFF, AA_ROM, true },
{ 0 }
};
void getstartaddresses (boolean hirom)
{
int x, i;
int b, a; // bank, address
struct addressarea *aa;
if (hirom) aa = hiromarea;
else aa = loromarea;
for (x = 0; aa[x].start != NULL; x++) {
if (aa[x].start == AA_ROM)
aa[x].start = rom;
if (aa[x].start == AA_HIROM)
aa[x].start = rom + 0x8000;
//if (aa[x].start == AA_ROM_x40)
// aa[x].start = rom + 0x40*0x8000;
if (aa[x].start == AA_NOTHING)
aa[x].start = expram;
}
for (i = 0; i <= 0x7FF; i++) {
// Get bank and address
b = (i >> 3);
a = (i & 7) << 13;
// Find which of the address areas that bb.aaaa is part of
for (x = 0; aa[x].start != NULL; x++) {
if (b >= aa[x].b1 && b <= aa[x].b2 && a >= aa[x].a1 && a <= aa[x].a2)
break;
}
startaddr [i] = (aa[x].start + (a - aa[x].a1));
if (aa[x].continuous)
startaddr [i] += (b - aa[x].b1) * (aa[x].a2 - aa[x].a1 + 1 + aa[x].spacing);
assert (aa[x].start != NULL);
// Map that address to the array specified by start.
//debug0 ("Mapping memory: %X.%X->%P[%X]", b, a, aa[x].start, startaddr [i]-aa[x].start);
}
}
void resetsystem (boolean warmreset)
{
int x;
if (!romloaded) return;
getstartaddresses (ishirom());
if (warmreset) {
//reg.S = (reg.S & 0xFF) | 0x100;
reg.S = 0x1FF;
//*(byte*)SNESMEM(reg.S) = (byte)(reg.PC >> 16); (*(word*)®.S)--;
//*(word*)SNESMEM(reg.S-1) = (word)reg.PC; (*(word*)®.S) -= 2;
//*(byte*)SNESMEM(reg.S) = (byte)(reg.P); (*(word*)®.S)--;
} else {
reg.S = 0x1FF;
dealloc_autobacktrack();
if (autobacktrack)
alloc_autobacktrack(backtracknum);
}
reg.D_dummy = 0x0000;
reg.P_dummy = 0x34; //|= 0x34; // 0011 0100
//reg.P &= ~BCD;
reg.A_dummy = 0;
reg.X_dummy = 0; //&= 0xFF;
reg.Y_dummy = 0; //&= 0xFF;
reg.E_dummy = true;
reg.PC = curheader.resetvector; //| (curheader.fastrom ? 0x800000 : 0);
debug0 ("reg.PC = %LX", reg.PC);
reg.DBR_dummy1 = reg.DBR_dummy2 = reg.DBR = reg.DBR_dummy3 = 0;
romrunning = false;
total_frames = 0;
debug_instr = 0;
memset (ram, 0, sizeof (ram));
memset (registers, 0, sizeof (registers));
memset (expram, 0, sizeof (expram));
memset (vram, 0, sizeof (vram));
memset (oam, 0, sizeof (oam));
memset (cgram, 0, sizeof (cgram));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -