📄 pgbcpu.java
字号:
/**
* this source file released under the GNU Public Licence.
* see the accompanying copyright.txt for more information
* Copyright (C) 2000-2001 Ben Mazur
* modified by retroK, XTale and baka0815 2004 http://aepgb.aep-emu.de/
*/
/**
* PgbCpu keeps the state of the CPU registers and executes
* the current opcode.
*
* It is a closed-box type of architecture for performance
* purposes. Sorry for all the private final methods...
*
* The exec() method executes the current opcode and
* increases the program counter. exec() also calls the
* memory cycle() function and processes any resulting
* interrupts.
*/
public final class PgbCpu {
private final int HALTON = -1;//0x0150;
final static int Z_FLAG = 0x80; /* 1: Result is zero */
final static int N_FLAG = 0x40; /* 1: Subtraction occured */
final static int H_FLAG = 0x20; /* 1: Halfcarry/Halfborrow */
final static int C_FLAG = 0x10; /* 1: Carry/Borrow occured */
PgbMemory mem;
// registers
private PgbRegister BC;
private PgbRegister DE;
private PgbRegister HL;
private PgbRegisterW SP;
private PgbRegisterW PC;
private PgbRegisterB AF;
private boolean ime; // interrupt master enable
// by retroK
SoundChip soundChip;
public PgbCpu(PgbMemory mem) {
this.mem = mem;
//initOpcodes();
}
public void reset() {
AF = new PgbRegisterB(0x0180);
if(PgbSettings.system == PgbSettings.SYS_GBP) {
AF = new PgbRegisterB(0xFF80);
}
if(PgbSettings.system == PgbSettings.SYS_GBC) {
AF = new PgbRegisterB(0x1180);
}
BC = new PgbRegisterB(0x0013);
DE = new PgbRegisterB(0x00D8);
HL = new PgbRegisterW(0x014D);
SP = new PgbRegisterW(0xFFFE);
PC = new PgbRegisterW(0x0100);
ime = false;
PgbSettings.clockspeed = 4.194304;
}
public final void exec(int cte) {
int cv;
/*
// debug halt
if(PgbSettings.DEBUG) {
if(PC.data == HALTON) {
PgbSettings.paused = true;
System.out.println("PC hit HALTON:" + Integer.toHexString(HALTON));
}
}
*/
/*
if(PgbSettings.debuglevel == 5) {
System.out.print("op:" + Integer.toHexString(opcode) + " pc:" + Integer.toHexString(PC.getR() - 1) + " af:" + Integer.toHexString(AF.getR()) + " bc:" + Integer.toHexString(BC.getR()) + " de:" + Integer.toHexString(DE.getR()) + " hl:" + Integer.toHexString(HL.getR()) + " sp:" + Integer.toHexString(SP.getR()) + " ");
System.out.println("LCD y:" + Integer.toHexString(mem.video.ly) + " IF:" + Integer.toBinaryString(mem.IF));
}
*/
while(cte > 0) {
// process interrupts
if(ime && (mem.IF & mem.IE) != 0) {
interrupt(mem.IF & mem.IE);
}
int memread = (int)(mem.read(PC.data++) & 0xFF);
cv = 4;
//System.out.println("memread: 0x" + Integer.toHexString(memread));
switch (memread) {
case 0x00: // NOP
cv = 4;
break;
case 0x01: // LD BC,nnnn
BC.setR(readWord());
cv = 20;
break;
case 0x02: // LD (BC),A
mem.write(BC.getR(), AF.getH());
cv = 8;
break;
case 0x03: // INC BC
incR(BC);
cv = 8;
break;
case 0x04: // INC B
incH(BC);
cv = 4;
break;
case 0x05: // DEC B
decH(BC);
cv = 4;
break;
case 0x06: // LD B,nn
BC.setH(readByte());
cv = 8;
break;
case 0x07: // RLCA
rlcH(AF);
setZ(false);
cv = 4;
break;
case 0x08: // LD (nnnn),SP
mem.writeWord(readWord(), SP.getR());
cv = 20;
break;
case 0x09: // LD (nnnn),SP
addR(HL, BC);
cv = 12;
break;
case 0x0A: // LD A,(BC)
AF.setH(BC.getI(mem));
cv = 8;
break;
case 0x0B: // DEC BC
decR(BC);
cv = 8;
break;
case 0x0C: // INC C
incL(BC);
cv = 4;
break;
case 0x0D: // DEC C
decL(BC);
cv = 4;
break;
case 0x0E: // LD C,nn
BC.setL(readByte());
cv = 8;
break;
case 0x0F: // RRCA
rrcH(AF);
setZ(false);
cv = 4;
break;
case 0x10: // STOP
readByte();
if(PgbSettings.system == PgbSettings.SYS_GBC) {
// change speed
if((mem.gbcGetSpeed() & 0x01) == 0x01) {
PgbSettings.clockspeed = 8.388;
mem.gbcSetSpeed((byte)0x80);
} else {
PgbSettings.clockspeed = 4.194;
mem.gbcSetSpeed((byte)0x00);
}
//System.out.println("speed change : " + PgbSettings.clockspeed);
} else {
unsupported(0x10);
}
cv = 4;
break;
case 0x11: // LD DE,nnnn
DE.setR(readWord());
cv = 12;
break;
case 0x12: // LD (DE),A
DE.setI(AF.getH(), mem);
cv = 8;
break;
case 0x13: // INC DE
incR(DE);
cv = 8;
break;
case 0x14: // INC D
incH(DE);
cv = 4;
break;
case 0x15: // DEC D
decH(DE);
cv = 4;
break;
case 0x16: // LD D,nn
DE.setH(readByte());
cv = 8;
break;
case 0x17: // RLA
rlH(AF);
setZ(false);
cv = 4;
break;
case 0x18: // JR disp
jr(readByte());
cv = 12;
break;
case 0x19: // ADD HL,DE
addR(HL, DE);
cv = 16;
break;
case 0x1A: // LD A,(DE)
AF.setH(DE.getI(mem));
cv = 8;
break;
case 0x1B: // DEC DE
decR(DE);
cv = 8;
break;
case 0x1C: // INC E
incL(DE);
cv = 4;
break;
case 0x1D: // DEC E
decL(DE);
cv = 4;
break;
case 0x1E: // LD E,nn
DE.setL(readByte());
cv = 8;
break;
case 0x1F: // RRA
rrH(AF);
setZ(false);
cv = 4;
break;
case 0x20: // JR NZ,disp
if(!getZ()) {
jr(readByte());
cv = 12;
} else {
readByte(); // and NOP it!
cv = 8;
}
break;
case 0x21: // LD HL,nnnn
HL.setR(readWord());
cv = 12;
break;
case 0x22: // LDI (HL),A
HL.setI(AF.getH(), mem);
incR(HL);
cv = 16;
break;
case 0x23: // INC HL
incR(HL);
cv = 8;
break;
case 0x24: // INC H
incH(HL);
cv = 4;
break;
case 0x25: // DEC H
decH(HL);
cv = 4;
break;
case 0x26: // LD H,nn
HL.setH(readByte());
cv = 8;
break;
case 0x27: // DAA
daa();
cv = 4;
break;
case 0x28: // JR Z,disp
if(getZ()) {
jr(readByte());
cv = 12;
} else {
readByte(); // and NOP it!
cv = 8;
}
break;
case 0x29: // ADD HL,HL
addR(HL, HL);
cv = 12;
break;
case 0x2A: // LDI A,(HL)
AF.setH(HL.getI(mem));
incR(HL);
cv = 16;
break;
case 0x2B: // DEC HL
decR(HL);
cv = 8;
break;
case 0x2C: // INC L
incL(HL);
cv = 4;
break;
case 0x2D: // DEC L
decL(HL);
cv = 4;
break;
case 0x2E: // LD L,nn
HL.setL(readByte());
cv = 8;
break;
case 0x2F: // CPL
cpl();
cv = 4;
break;
case 0x30: // JR NC,disp
if(!getC()) {
jr(readByte());
cv = 12;
} else {
readByte(); // and NOP it!
cv = 8;
}
break;
case 0x31: // LD SP,nnnn
SP.setR(readWord());
cv = 12;
break;
case 0x32: // LDD (HL),A
HL.setI(AF.getH(), mem);
decR(HL);
cv = 16;
break;
case 0x33: // INC SP
incR(SP);
cv = 8;
break;
case 0x34: // INC (HL)
incI(HL);
cv = 12;
break;
case 0x35: // DEC (HL)
decI(HL);
cv = 12;
break;
case 0x36: // LD (HL),nn
HL.setI(readByte(), mem);
cv = 12;
break;
case 0x37: // SCF
setC(true);
cv = 4;
break;
case 0x38: // JR C,disp
if(getC()) {
jr(readByte());
cv = 12;
} else {
readByte(); // and NOP it!
cv = 8;
}
break;
case 0x39: // ADD HL,SP
addR(HL, SP);
cv = 12;
break;
case 0x3A: // LDD A,(HL)
AF.setH(HL.getI(mem));
decR(HL);
cv = 16;
break;
case 0x3B: // DEC SP
decR(SP);
cv = 8;
break;
case 0x3C: // INC A
incH(AF);
cv = 4;
break;
case 0x3D: // DEC A
decH(AF);
cv = 4;
break;
case 0x3E: // LD A,nn
AF.setH(readByte());
cv = 8;
break;
case 0x3F: // CCF
setC(!getC());
cv = 4;
break;
case 0x40: // LD B,B
//XXX senseless (B -> B)
//BC.setH(BC.getH());
cv = 4;
break;
case 0x41: // LD B,C
BC.setH(BC.getL());
cv = 4;
break;
case 0x42: // LD B,D
BC.setH(DE.getH());
cv = 4;
break;
case 0x43: // LD B,E
BC.setH(DE.getL());
cv = 4;
break;
case 0x44: // LD B,H
BC.setH(HL.getH());
cv = 4;
break;
case 0x45: // LD B,L
BC.setH(HL.getL());
cv = 4;
break;
case 0x46: // LD B,(HL)
BC.setH(HL.getI(mem));
cv = 8;
break;
case 0x47: // LD B,A
BC.setH(AF.getH());
cv = 4;
break;
case 0x48: // LD C,B
BC.setL(BC.getH());
cv = 4;
break;
case 0x49: // LD C,C
//XXX senseless (C -> C)
//BC.setL(BC.getL());
cv = 4;
break;
case 0x4A: // LD C,D
BC.setL(DE.getH());
cv = 4;
break;
case 0x4B: // LD C,E
BC.setL(DE.getL());
cv = 4;
break;
case 0x4C: // LD C,H
BC.setL(HL.getH());
cv = 4;
break;
case 0x4D: // LD C,L
BC.setL(HL.getL());
cv = 4;
break;
case 0x4E: // LD C,(HL)
BC.setL(HL.getI(mem));
cv = 8;
break;
case 0x4F: // LD C,A
BC.setL(AF.getH());
cv = 4;
break;
case 0x50: // LD D,B
DE.setH(BC.getH());
cv = 4;
break;
case 0x51: // LD D,C
DE.setH(BC.getL());
cv = 4;
break;
case 0x52: // LD D,D
//XXX senseless (D -> D)
//DE.setH(DE.getH());
cv = 4;
break;
case 0x53: // LD D,E
DE.setH(DE.getL());
cv = 4;
break;
case 0x54: // LD D,H
DE.setH(HL.getH());
cv = 4;
break;
case 0x55: // LD D,L
DE.setH(HL.getL());
cv = 4;
break;
case 0x56: // LD D,(HL)
DE.setH(HL.getI(mem));
cv = 8;
break;
case 0x57: // LD D,A
DE.setH(AF.getH());
cv = 4;
break;
case 0x58: // LD E,B
DE.setL(BC.getH());
cv = 4;
break;
case 0x59: // LD E,C
DE.setL(BC.getL());
cv = 4;
break;
case 0x5A: // LD E,D
DE.setL(DE.getH());
cv = 4;
break;
case 0x5B: // LD E,E
//XXX senseless (E -> E)
//DE.setL(DE.getL());
cv = 4;
break;
case 0x5C: // LD E,H
DE.setL(HL.getH());
cv = 4;
break;
case 0x5D: // LD E,L
DE.setL(HL.getL());
cv = 4;
break;
case 0x5E: // LD E,(HL)
DE.setL(HL.getI(mem));
cv = 8;
break;
case 0x5F: // LD E,A
DE.setL(AF.getH());
cv = 4;
break;
case 0x60: // LD H,B
HL.setH(BC.getH());
cv = 4;
break;
case 0x61: // LD H,C
HL.setH(BC.getL());
cv = 4;
break;
case 0x62: // LD H,D
HL.setH(DE.getH());
cv = 4;
break;
case 0x63: // LD H,E
HL.setH(DE.getL());
cv = 4;
break;
case 0x64: // LD H,H
//XXX senseless (H -> H)
//HL.setH(HL.getH());
cv = 4;
break;
case 0x65: // LD H,L
HL.setH(HL.getL());
cv = 4;
break;
case 0x66: // LD H,(HL)
HL.setH(HL.getI(mem));
cv = 8;
break;
case 0x67: // LD H,A
HL.setH(AF.getH());
cv = 4;
break;
case 0x68: // LD L,B
HL.setL(BC.getH());
cv = 4;
break;
case 0x69: // LD L,C
HL.setL(BC.getL());
cv = 4;
break;
case 0x6A: // LD L,D
HL.setL(DE.getH());
cv = 4;
break;
case 0x6B: // LD L,E
HL.setL(DE.getL());
cv = 4;
break;
case 0x6C: // LD L,H
HL.setL(HL.getH());
cv = 4;
break;
case 0x6D: // LD L,L
//XXX senseless (L -> L)
//HL.setL(HL.getL());
cv = 4;
break;
case 0x6E: // LD L,(HL)
HL.setL(HL.getI(mem));
cv = 8;
break;
case 0x6F: // LD L,A
HL.setL(AF.getH());
cv = 4;
break;
case 0x70: // LD (HL),B
mem.write(HL.getR(), BC.getH());
cv = 8;
break;
case 0x71: // LD (HL),C
mem.write(HL.getR(), BC.getL());
cv = 8;
break;
case 0x72: // LD (HL),D
mem.write(HL.getR(), DE.getH());
cv = 8;
break;
case 0x73: // LD (HL),E
mem.write(HL.getR(), DE.getL());
cv = 8;
break;
case 0x74: // LD (HL),H
mem.write(HL.getR(), HL.getH());
cv = 8;
break;
case 0x75: // LD (HL),L
mem.write(HL.getR(), HL.getL());
cv = 8;
break;
case 0x76: // HALT
if(ime) {
//decR(PC);
//System.out.println("cpu HALTed.");
mem.recalcCyclesLeft();
cv = mem.cyclesLeft;
} else {
//System.out.println("cpu not HALTed because IME=" + ime + " and IE=" + mem.IE);
cv = 4;
}
break;
case 0x77: // LD (HL),A
mem.write(HL.getR(), AF.getH());
cv = 8;
break;
case 0x78: // LD A,B
AF.setH(BC.getH());
cv = 4;
break;
case 0x79: // LD A,C
AF.setH(BC.getL());
cv = 4;
break;
case 0x7A: // LD A,D
AF.setH(DE.getH());
cv = 4;
break;
case 0x7B: // LD A,E
AF.setH(DE.getL());
cv = 4;
break;
case 0x7C: // LD A,H
AF.setH(HL.getH());
cv = 4;
break;
case 0x7D: // LD A,L
AF.setH(HL.getL());
cv = 4;
break;
case 0x7E: // LD A,(HL)
AF.setH(HL.getI(mem));
cv = 8;
break;
case 0x7F: // LD A,A
//XXX senseless (A -> A)
//AF.setH(AF.getH());
cv = 4;
break;
case 0x80: // ADD A,B
add(BC.getH());
cv = 4;
break;
case 0x81: // ADD A,C
add(BC.getL());
cv = 4;
break;
case 0x82: // ADD A,D
add(DE.getH());
cv = 4;
break;
case 0x83: // ADD A,E
add(DE.getL());
cv = 4;
break;
case 0x84: // ADD A,H
add(HL.getH());
cv = 4;
break;
case 0x85: // ADD A,L
add(HL.getL());
cv = 4;
break;
case 0x86: // ADD A,(HL)
add(HL.getI(mem));
cv = 8;
break;
case 0x87: // ADD A,A
add(AF.getH());
cv = 4;
break;
case 0x88: // ADC A,B
adc(BC.getH());
cv = 4;
break;
case 0x89: // ADC A,C
adc(BC.getL());
cv = 4;
break;
case 0x8A: // ADC A,D
adc(DE.getH());
cv = 4;
break;
case 0x8B: // ADC A,E
adc(DE.getL());
cv = 4;
break;
case 0x8C: // ADC A,H
adc(HL.getH());
cv = 4;
break;
case 0x8D: // ADC A,L
adc(HL.getL());
cv = 4;
break;
case 0x8E: // ADC A,(HL)
adc(HL.getI(mem));
cv = 8;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -