package com.pixelutilitys.arcade.emulators.AEPgb;
/**
* 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 = 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;
case 0x8F: // ADC A,A
adc(AF.getH());
cv = 4;
break;
case 0x90: // SUB B
sub(BC.getH());
cv = 4;
break;
case 0x91: // SUB C
sub(BC.getL());
cv = 4;
break;
case 0x92: // SUB D
sub(DE.getH());
cv = 4;
break;
case 0x93: // SUB E
sub(DE.getL());
cv = 4;
break;
case 0x94: // SUB H
sub(HL.getH());
cv = 4;
break;
case 0x95: // SUB L
sub(HL.getL());
cv = 4;
break;
case 0x96: // SUB (HL)
sub(HL.getI(mem));
cv = 8;
break;
case 0x97: // SUB A
sub(AF.getH());
cv = 4;
break;
case 0x98: // SBC A,B
sbc(BC.getH());
cv = 4;
break;
case 0x99: // SBC A,C
sbc(BC.getL());
cv = 4;
break;
case 0x9A: // SBC A,D
sbc(DE.getH());
cv = 4;
break;
case 0x9B: // SBC A,E
sbc(DE.getL());
cv = 4;
break;
case 0x9C: // SBC A,H
sbc(HL.getH());
cv = 4;
break;
case 0x9D: // SBC A,L
sbc(HL.getL());
cv = 4;
break;
case 0x9E: // SBC A,(HL)
sbc(HL.getI(mem));
cv = 8;
break;
case 0x9F: // SBC A,A
sbc(AF.getH());
cv = 4;
break;
case 0xA0: // AND B
and(BC.getH());
cv = 4;
break;
case 0xA1: // AND C
and(BC.getL());
cv = 4;
break;
case 0xA2: // AND D
and(DE.getH());
cv = 4;
break;
case 0xA3: // AND E
and(DE.getL());
cv = 4;
break;
case 0xA4: // AND H
and(HL.getH());
cv = 4;
break;
case 0xA5: // AND L
and(HL.getL());
cv = 4;
break;
case 0xA6: // AND (HL)
and(HL.getI(mem));
cv = 8;
break;
case 0xA7: // AND A
and(AF.getH());
cv = 4;
break;
case 0xA8: // XOR B
xor(BC.getH());
cv = 4;
break;
case 0xA9: // XOR C
xor(BC.getL());
cv = 4;
break;
case 0xAA: // XOR D
xor(DE.getH());
cv = 4;
break;
case 0xAB: // XOR E
xor(DE.getL());
cv = 4;
break;
case 0xAC: // XOR H
xor(HL.getH());
cv = 4;
break;
case 0xAD: // XOR L
xor(HL.getL());
cv = 4;
break;
case 0xAE: // XOR (HL)
xor(HL.getI(mem));
cv = 8;
break;
case 0xAF: // XOR A
xor(AF.getH());
cv = 4;
break;
case 0xB0: // OR B
or(BC.getH());
cv = 4;
break;
case 0xB1: // OR C
or(BC.getL());
cv = 4;
break;
case 0xB2: // OR D
or(DE.getH());
cv = 4;
break;
case 0xB3: // OR E
or(DE.getL());
cv = 4;
break;
case 0xB4: // OR H
or(HL.getH());
cv = 4;
break;
case 0xB5: // OR L
or(HL.getL());
cv = 4;
break;
case 0xB6: // OR (HL)
or(HL.getI(mem));
cv = 8;
break;
case 0xB7: // OR A
or(AF.getH());
cv = 4;
break;
case 0xB8: // CP B
cp(BC.getH());
cv = 4;
break;
case 0xB9: // CP C
cp(BC.getL());
cv = 4;
break;
case 0xBA: // CP D
cp(DE.getH());
cv = 4;
break;
case 0xBB: // CP E
cp(DE.getL());
cv = 4;
break;
case 0xBC: // CP H
cp(HL.getH());
cv = 4;
break;
case 0xBD: // CP L
cp(HL.getL());
cv = 4;
break;
case 0xBE: // CP (HL)
cp(HL.getI(mem));
cv = 8;
break;
case 0xBF: // CP A
cp(AF.getH());
cv = 4;
break;
case 0xC0: // RET NZ
if(!getZ()) {
ret();
cv = 20;
} else {
cv = 8;
}
break;
case 0xC1: // POP BC
pop(BC);
cv = 12;
break;
case 0xC2: // JP NZ,nnnn
if(!getZ()) {
jp(readWord());
cv = 16;
} else {
readWord();
cv = 12;
}
break;
case 0xC3: // JP nnnn
jp(readWord());
cv = 16;
break;
case 0xC4: // CALL NZ,nnnn
if(!getZ()) {
call(readWord());
cv = 24;
} else {
readWord();
cv = 12;
}
break;
case 0xC5: // PUSH BC
push(BC);
cv = 16;
break;
case 0xC6: // ADD A,nn
add(readByte());
cv = 8;
break;
case 0xC7: // RST 0H
rst(0x0);
cv = 16;
break;
case 0xC8: // RET Z
if(getZ()) {
ret();
cv = 20;
} else {
cv = 8;
}
break;
case 0xC9: // RET
ret();
cv = 16;
break;
case 0xCA: // JP Z,nnnn
if(getZ()) {
jp(readWord());
cv = 16;
} else {
readWord();
cv = 12;
}
break;
case 0xCB: // -- special --
int b = readByte();
if (PgbSettings.DEBUG)
System.out.println("0xCB, executing SubOpCode 0x" + Integer.toHexString(b));
//cv = cbcodes[b].exec();
switch(b) {
case 0x00: // RLC B
rlcH(BC);
cv = 8;
break;
case 0x01: // RLC C
rlcL(BC);
cv = 8;
break;
case 0x02: // RLC D
rlcH(DE);
cv = 8;
break;
case 0x03: // RLC E
rlcL(DE);
cv = 8;
break;
case 0x04: // RLC H
rlcH(HL);
cv = 8;
break;
case 0x05: // RLC L
rlcL(HL);
cv = 8;
break;
case 0x06: // RLC (HL)
rlcI(HL.getR());
cv = 16;
break;
case 0x07: // RLC A
rlcH(AF);
cv = 8;
break;
case 0x08: // RRC B
rrcH(BC);
cv = 8;
break;
case 0x09: // RRC C
rrcL(BC);
cv = 8;
break;
case 0x0A: // RRC D
rrcH(DE);
cv = 8;
break;
case 0x0B: // RRC E
rrcL(DE);
cv = 8;
break;
case 0x0C: // RRC H
rrcH(HL);
cv = 8;
break;
case 0x0D: // RRC L
rrcL(HL);
cv = 8;
break;
case 0x0E: // RRC (HL)
rrcI(HL.getR());
cv = 16;
break;
case 0x0F: // RRC A
rrcH(AF);
cv = 8;
break;
case 0x10: // RL B
rlH(BC);
cv = 8;
break;
case 0x11: // RL C
rlL(BC);
cv = 8;
break;
case 0x12: // RL D
rlH(DE);
cv = 8;
break;
case 0x13: // RL E
rlL(DE);
cv = 8;
break;
case 0x14: // RL H
rlH(HL);
cv = 8;
break;
case 0x15: // RL L
rlL(HL);
cv = 8;
break;
case 0x16: // RL (HL)
rlI(HL.getR());
cv = 16;
break;
case 0x17: // RL A
rlH(AF);
cv = 8;
break;
case 0x18: // RR B
rrH(BC);
cv = 8;
break;
case 0x19: // RR C
rrL(BC);
cv = 8;
break;
case 0x1A: // RR D
rrH(DE);
cv = 8;
break;
case 0x1B: // RR E
rrL(DE);
cv = 8;
break;
case 0x1C: // RR H
rrH(HL);
cv = 8;
break;
case 0x1D: // RR L
rrL(HL);
cv = 8;
break;
case 0x1E: // RR (HL)
rrI(HL.getR());
cv = 16;
break;
case 0x1F: // RR A
rrH(AF);
cv = 8;
break;
case 0x20: // SLA B
slaH(BC);
cv = 8;
break;
case 0x21: // SLA C
slaL(BC);
cv = 8;
break;
case 0x22: // SLA D
slaH(DE);
cv = 8;
break;
case 0x23: // SLA E
slaL(DE);
cv = 8;
break;
case 0x24: // SLA H
slaH(HL);
cv = 8;
break;
case 0x25: // SLA L
slaL(HL);
cv = 8;
break;
case 0x26: // SLA (HL)
slaI(HL.getR());
cv = 16;
break;
case 0x27: // SLA A
slaH(AF);
cv = 8;
break;
case 0x28: // SRA B
sraH(BC);
cv = 8;
break;
case 0x29: // SRA C
sraL(BC);
cv = 8;
break;
case 0x2A: // SRA D
sraH(DE);
cv = 8;
break;
case 0x2B: // SRA E
sraL(DE);
cv = 8;
break;
case 0x2C: // SRA H
sraH(HL);
cv = 8;
break;
case 0x2D: // SRA L
sraL(HL);
cv = 8;
break;
case 0x2E: // SRA (HL)
sraI(HL.getR());
cv = 16;
break;
case 0x2F: // SRA A
sraH(AF);
cv = 8;
break;
case 0x30: // SWAP B
swapH(BC);
cv = 8;
break;
case 0x31: // SWAP C
swapL(BC);
cv = 8;
break;
case 0x32: // SWAP D
swapH(DE);
cv = 8;
break;
case 0x33: // SWAP E
swapL(DE);
cv = 8;
break;
case 0x34: // SWAP H
swapH(HL);
cv = 8;
break;
case 0x35: // SWAP L
swapL(HL);
cv = 8;
break;
case 0x36: // SWAP (HL)
swapI(HL.getR());
cv = 16;
break;
case 0x37: // SWAP A
swapH(AF);
cv = 8;
break;
case 0x38: // SRL B
srlH(BC);
cv = 8;
break;
case 0x39: // SRL C
srlL(BC);
cv = 8;
break;
case 0x3A: // SRL D
srlH(DE);
cv = 8;
break;
case 0x3B: // SRL E
srlL(DE);
cv = 8;
break;
case 0x3C: // SRL H
srlH(HL);
cv = 8;
break;
case 0x3D: // SRL L
srlL(HL);
cv = 8;
break;
case 0x3E: // SRL (HL)
srlI(HL.getR());
cv = 16;
break;
case 0x3F: // SRL A
srlH(AF);
cv = 8;
break;
case 0x40: // BIT 0,B
bit(0, BC.getH());
cv = 8;
break;
case 0x41: // BIT 0,C
bit(0, BC.getL());
cv = 8;
break;
case 0x42: // BIT 0,D
bit(0, DE.getH());
cv = 8;
break;
case 0x43: // BIT 0,E
bit(0, DE.getL());
cv = 8;
break;
case 0x44: // BIT 0,H
bit(0, HL.getH());
cv = 8;
break;
case 0x45: // BIT 0,L
bit(0, HL.getL());
cv = 8;
break;
case 0x46: // BIT 0,(HL)
bit(0, HL.getI(mem));
cv = 16;
break;
case 0x47: // BIT 0,A
bit(0, AF.getH());
cv = 8;
break;
case 0x48: // BIT 1,B
bit(1, BC.getH());
cv = 8;
break;
case 0x49: // BIT 1,C
bit(1, BC.getL());
cv = 8;
break;
case 0x4A: // BIT 1,D
bit(1, DE.getH());
cv = 8;
break;
case 0x4B: // BIT 1,E
bit(1, DE.getL());
cv = 8;
break;
case 0x4C: // BIT 1,H
bit(1, HL.getH());
cv = 8;
break;
case 0x4D: // BIT 1,L
bit(1, HL.getL());
cv = 8;
break;
case 0x4E: // BIT 1,(HL)
bit(1, HL.getI(mem));
cv = 16;
break;
case 0x4F: // BIT 1,A
bit(1, AF.getH());
cv = 8;
break;
case 0x50: // BIT 2,B
bit(2, BC.getH());
cv = 8;
break;
case 0x51: // BIT 2,C
bit(2, BC.getL());
cv = 8;
break;
case 0x52: // BIT 2,D
bit(2, DE.getH());
cv = 8;
break;
case 0x53: // BIT 2,E
bit(2, DE.getL());
cv = 8;
break;
case 0x54: // BIT 2,H
bit(2, HL.getH());
cv = 8;
break;
case 0x55: // BIT 2,L
bit(2, HL.getL());
cv = 8;
break;
case 0x56: // BIT 2,(HL)
bit(2, HL.getI(mem));
cv = 16;
break;
case 0x57: // BIT 2,A
bit(2, AF.getH());
cv = 8;
break;
case 0x58: // BIT 3,B
bit(3, BC.getH());
cv = 8;
break;
case 0x59: // BIT 3,C
bit(3, BC.getL());
cv = 8;
break;
case 0x5A: // BIT 3,D
bit(3, DE.getH());
cv = 8;
break;
case 0x5B: // BIT 3,E
bit(3, DE.getL());
cv = 8;
break;
case 0x5C: // BIT 3,H
bit(3, HL.getH());
cv = 8;
break;
case 0x5D: // BIT 3,L
bit(3, HL.getL());
cv = 8;
break;
case 0x5E: // BIT 3,(HL)
bit(3, HL.getI(mem));
cv = 16;
break;
case 0x5F: // BIT 3,A
bit(3, AF.getH());
cv = 8;
break;
case 0x60: // BIT 4,B
bit(4, BC.getH());
cv = 8;
break;
case 0x61: // BIT 4,C
bit(4, BC.getL());
cv = 8;
break;
case 0x62: // BIT 4,D
bit(4, DE.getH());
cv = 8;
break;
case 0x63: // BIT 4,E
bit(4, DE.getL());
cv = 8;
break;
case 0x64: // BIT 4,H
bit(4, HL.getH());
cv = 8;
break;
case 0x65: // BIT 4,L
bit(4, HL.getL());
cv = 8;
break;
case 0x66: // BIT 4,(HL)
bit(4, HL.getI(mem));
cv = 16;
break;
case 0x67: // BIT 4,A
bit(4, AF.getH());
cv = 8;
break;
case 0x68: // BIT 5,B
bit(5, BC.getH());
cv = 8;
break;
case 0x69: // BIT 5,C
bit(5, BC.getL());
cv = 8;
break;
case 0x6A: // BIT 5,D
bit(5, DE.getH());
cv = 8;
break;
case 0x6B: // BIT 5,E
bit(5, DE.getL());
cv = 8;
break;
case 0x6C: // BIT 5,H
bit(5, HL.getH());
cv = 8;
break;
case 0x6D: // BIT 5,L
bit(5, HL.getL());
cv = 8;
break;
case 0x6E: // BIT 5,(HL)
bit(5, HL.getI(mem));
cv = 16;
break;
case 0x6F: // BIT 5,A
bit(5, AF.getH());
cv = 8;
break;
case 0x70: // BIT 6,B
bit(6, BC.getH());
cv = 8;
break;
case 0x71: // BIT 6,C
bit(6, BC.getL());
cv = 8;
break;
case 0x72: // BIT 6,D
bit(6, DE.getH());
cv = 8;
break;
case 0x73: // BIT 6,E
bit(6, DE.getL());
cv = 8;
break;
case 0x74: // BIT 6,H
bit(6, HL.getH());
cv = 8;
break;
case 0x75: // BIT 6,L
bit(6, HL.getL());
cv = 8;
break;
case 0x76: // BIT 6,(HL)
bit(6, HL.getI(mem));
cv = 16;
break;
case 0x77: // BIT 6,A
bit(6, AF.getH());
cv = 8;
break;
case 0x78: // BIT 7,B
bit(7, BC.getH());
cv = 8;
break;
case 0x79: // BIT 7,C
bit(7, BC.getL());
cv = 8;
break;
case 0x7A: // BIT 7,D
bit(7, DE.getH());
cv = 8;
break;
case 0x7B: // BIT 7,E
bit(7, DE.getL());
cv = 8;
break;
case 0x7C: // BIT 7,H
bit(7, HL.getH());
cv = 8;
break;
case 0x7D: // BIT 7,L
bit(7, HL.getL());
cv = 8;
break;
case 0x7E: // BIT 7,(HL)
bit(7, HL.getI(mem));
cv = 16;
break;
case 0x7F: // BIT 7,A
bit(7, AF.getH());
cv = 8;
break;
case 0x80: // RES 0,B
resH(0, BC);
cv = 8;
break;
case 0x81: // RES 0,C
resL(0, BC);
cv = 8;
break;
case 0x82: // RES 0,D
resH(0, DE);
cv = 8;
break;
case 0x83: // RES 0,E
resL(0, DE);
cv = 8;
break;
case 0x84: // RES 0,H
resH(0, HL);
cv = 8;
break;
case 0x85: // RES 0,L
resL(0, HL);
cv = 8;
break;
case 0x86: // RES 0,(HL)
resI(0, HL.getR());
cv = 16;
break;
case 0x87: // RES 0,A
resH(0, AF);
cv = 8;
break;
case 0x88: // RES 1,B
resH(1, BC);
cv = 8;
break;
case 0x89: // RES 1,C
resL(1, BC);
cv = 8;
break;
case 0x8A: // RES 1,D
resH(1, DE);
cv = 8;
break;
case 0x8B: // RES 1,E
resL(1, DE);
cv = 8;
break;
case 0x8C: // RES 1,H
resH(1, HL);
cv = 8;
break;
case 0x8D: // RES 1,L
resL(1, HL);
cv = 8;
break;
case 0x8E: // RES 1,(HL)
resI(1, HL.getR());
cv = 16;
break;
case 0x8F: // RES 1,A
resH(1, AF);
cv = 8;
break;
case 0x90: // RES 2,B
resH(2, BC);
cv = 8;
break;
case 0x91: // RES 2,C
resL(2, BC);
cv = 8;
break;
case 0x92: // RES 2,D
resH(2, DE);
cv = 8;
break;
case 0x93: // RES 2,E
resL(2, DE);
cv = 8;
break;
case 0x94: // RES 2,H
resH(2, HL);
cv = 8;
break;
case 0x95: // RES 2,L
resL(2, HL);
cv = 8;
break;
case 0x96: // RES 2,(HL)
resI(2, HL.getR());
cv = 16;
break;
case 0x97: // RES 2,A
resH(2, AF);
cv = 8;
break;
case 0x98: // RES 3,B
resH(3, BC);
cv = 8;
break;
case 0x99: // RES 3,C
resL(3, BC);
cv = 8;
break;
case 0x9A: // RES 3,D
resH(3, DE);
cv = 8;
break;
case 0x9B: // RES 3,E
resL(3, DE);
cv = 8;
break;
case 0x9C: // RES 3,H
resH(3, HL);
cv = 8;
break;
case 0x9D: // RES 3,L
resL(3, HL);
cv = 8;
break;
case 0x9E: // RES 3,(HL)
resI(3, HL.getR());
cv = 16;
break;
case 0x9F: // RES 3,A
resH(3, AF);
cv = 8;
break;
case 0xA0: // RES 4,B
resH(4, BC);
cv = 8;
break;
case 0xA1: // RES 4,C
resL(4, BC);
cv = 8;
break;
case 0xA2: // RES 4,D
resH(4, DE);
cv = 8;
break;
case 0xA3: // RES 4,E
resL(4, DE);
cv = 8;
break;
case 0xA4: // RES 4,H
resH(4, HL);
cv = 8;
break;
case 0xA5: // RES 4,L
resL(4, HL);
cv = 8;
break;
case 0xA6: // RES 4,(HL)
resI(4, HL.getR());
cv = 16;
break;
case 0xA7: // RES 4,A
resH(4, AF);
cv = 8;
break;
case 0xA8: // RES 5,B
resH(5, BC);
cv = 8;
break;
case 0xA9: // RES 5,C
resL(5, BC);
cv = 8;
break;
case 0xAA: // RES 5,D
resH(5, DE);
cv = 8;
break;
case 0xAB: // RES 5,E
resL(5, DE);
cv = 8;
break;
case 0xAC: // RES 5,H
resH(5, HL);
cv = 8;
break;
case 0xAD: // RES 5,L
resL(5, HL);
cv = 8;
break;
case 0xAE: // RES 5,(HL)
resI(5, HL.getR());
cv = 16;
break;
case 0xAF: // RES 5,A
resH(5, AF);
cv = 8;
break;
case 0xB0: // RES 6,B
resH(6, BC);
cv = 8;
break;
case 0xB1: // RES 6,C
resL(6, BC);
cv = 8;
break;
case 0xB2: // RES 6,D
resH(6, DE);
cv = 8;
break;
case 0xB3: // RES 6,E
resL(6, DE);
cv = 8;
break;
case 0xB4: // RES 6,H
resH(6, HL);
cv = 8;
break;
case 0xB5: // RES 6,L
resL(6, HL);
cv = 8;
break;
case 0xB6: // RES 6,(HL)
resI(6, HL.getR());
cv = 16;
break;
case 0xB7: // RES 6,A
resH(6, AF);
cv = 8;
break;
case 0xB8: // RES 7,B
resH(7, BC);
cv = 8;
break;
case 0xB9: // RES 7,C
resL(7, BC);
cv = 8;
break;
case 0xBA: // RES 7,D
resH(7, DE);
cv = 8;
break;
case 0xBB: // RES 7,E
resL(7, DE);
cv = 8;
break;
case 0xBC: // RES 7,H
resH(7, HL);
cv = 8;
break;
case 0xBD: // RES 7,L
resL(7, HL);
cv = 8;
break;
case 0xBE: // RES 7,(HL)
resI(7, HL.getR());
cv = 16;
break;
case 0xBF: // RES 7,A
resH(7, AF);
cv = 8;
break;
case 0xC0: // SET 0,B
setH(0, BC);
cv = 8;
break;
case 0xC1: // SET 0,C
setL(0, BC);
cv = 8;
break;
case 0xC2: // SET 0,D
setH(0, DE);
cv = 8;
break;
case 0xC3: // SET 0,E
setL(0, DE);
cv = 8;
break;
case 0xC4: // SET 0,H
setH(0, HL);
cv = 8;
break;
case 0xC5: // SET 0,L
setL(0, HL);
cv = 8;
break;
case 0xC6: // SET 0,(HL)
setI(0, HL.getR());
cv = 16;
break;
case 0xC7: // SET 0,A
setH(0, AF);
cv = 8;
break;
case 0xC8: // SET 1,B
setH(1, BC);
cv = 8;
break;
case 0xC9: // SET 1,C
setL(1, BC);
cv = 8;
break;
case 0xCA: // SET 1,D
setH(1, DE);
cv = 8;
break;
case 0xCB: // SET 1,E
setL(1, DE);
cv = 8;
break;
case 0xCC: // SET 1,H
setH(1, HL);
cv = 8;
break;
case 0xCD: // SET 1,L
setL(1, HL);
cv = 8;
break;
case 0xCE: // SET 1,(HL)
setI(1, HL.getR());
cv = 8;
break;
case 0xCF: // SET 1,A
setH(1, AF);
cv = 8;
break;
case 0xD0: // SET 2,B
setH(2, BC);
cv = 8;
break;
case 0xD1: // SET 2,C
setL(2, BC);
cv = 8;
break;
case 0xD2: // SET 2,D
setH(2, DE);
cv = 8;
break;
case 0xD3: // SET 2,E
setL(2, DE);
cv = 8;
break;
case 0xD4: // SET 2,H
setH(2, HL);
cv = 8;
break;
case 0xD5: // SET 2,L
setL(2, HL);
cv = 8;
break;
case 0xD6: // SET 2,(HL)
setI(2, HL.getR());
cv = 16;
break;
case 0xD7: // SET 2,A
setH(2, AF);
cv = 8;
break;
case 0xD8: // SET 3,B
setH(3, BC);
cv = 8;
break;
case 0xD9: // SET 3,C
setL(3, BC);
cv = 8;
break;
case 0xDA: // SET 3,D
setH(3, DE);
cv = 8;
break;
case 0xDB: // SET 3,E
setL(3, DE);
cv = 8;
break;
case 0xDC: // SET 3,H
setH(3, HL);
cv = 8;
break;
case 0xDD: // SET 3,L
setL(3, HL);
cv = 8;
break;
case 0xDE: // SET 3,(HL)
setI(3, HL.getR());
cv = 16;
break;
case 0xDF: // SET 3,A
setH(3, AF);
cv = 8;
break;
case 0xE0: // SET 4,B
setH(4, BC);
cv = 8;
break;
case 0xE1: // SET 4,C
setL(4, BC);
cv = 8;
break;
case 0xE2: // SET 4,D
setH(4, DE);
cv = 8;
break;
case 0xE3: // SET 4,E
setL(4, DE);
cv = 8;
break;
case 0xE4: // SET 4,H
setH(4, HL);
cv = 8;
break;
case 0xE5: // SET 4,L
setL(4, HL);
cv = 8;
break;
case 0xE6: // SET 4,(HL)
setI(4, HL.getR());
cv = 16;
break;
case 0xE7: // SET 4,A
setH(4, AF);
cv = 8;
break;
case 0xE8: // SET 5,B
setH(5, BC);
cv = 8;
break;
case 0xE9: // SET 5,C
setL(5, BC);
cv = 8;
break;
case 0xEA: // SET 5,D
setH(5, DE);
cv = 8;
break;
case 0xEB: // SET 5,E
setL(5, DE);
cv = 8;
break;
case 0xEC: // SET 5,H
setH(5, HL);
cv = 8;
break;
case 0xED: // SET 5,L
setL(5, HL);
cv = 8;
break;
case 0xEE: // SET 5,(HL)
setI(5, HL.getR());
cv = 16;
break;
case 0xEF: // SET 5,A
setH(5, AF);
cv = 8;
break;
case 0xF0: // SET 6,B
setH(6, BC);
cv = 8;
break;
case 0xF1: // SET 6,C
setL(6, BC);
cv = 8;
break;
case 0xF2: // SET 6,D
setH(6, DE);
cv = 8;
break;
case 0xF3: // SET 6,E
setL(6, DE);
cv = 8;
break;
case 0xF4: // SET 6,H
setH(6, HL);
cv = 8;
break;
case 0xF5: // SET 6,L
setL(6, HL);
cv = 8;
break;
case 0xF6: // SET 6,(HL)
setI(6, HL.getR());
cv = 16;
break;
case 0xF7: // SET 6,A
setH(6, AF);
cv = 8;
break;
case 0xF8: // SET 7,B
setH(7, BC);
cv = 8;
break;
case 0xF9: // SET 7,C
setL(7, BC);
cv = 8;
break;
case 0xFA: // SET 7,D
setH(7, DE);
cv = 8;
break;
case 0xFB: // SET 7,E
setL(7, DE);
cv = 8;
break;
case 0xFC: // SET 7,H
setH(7, HL);
cv = 8;
break;
case 0xFD: // SET 7,L
setL(7, HL);
cv = 8;
break;
case 0xFE: // SET 7,(HL)
setI(7, HL.getR());
cv = 16;
break;
case 0xFF: // SET 7,A
setH(7, AF);
cv = 8;
break;
default:
//cv = cbcodes[b].exec();
unsupportedCB(b);
cv = 4;
}
break;
case 0xCC: // CALL Z,nnnn
if(getZ()) {
call(readWord());
cv = 24;
} else {
readWord();
cv = 12;
}
break;
case 0xCD: // CALL nnnn
call(readWord());
cv = 24;
break;
case 0xCE: // ADC A,nn
adc(readByte());
cv = 8;
break;
case 0xCF: // RST 8H
rst(0x8);
cv = 16;
break;
case 0xD0: // RET NC
if(!getC()) {
ret();
cv = 20;
} else {
cv = 8;
}
break;
case 0xD1: // POP DE
pop(DE);
cv = 10;
break;
case 0xD2: // JP NC,nnnn
if(!getC()) {
jp(readWord());
cv = 20;
} else {
readWord();
cv = 8;
}
break;
case 0xD3: // -
unsupported(0xD3);
cv = 4;
break;
case 0xD4: // CALL NC,nnnn
if(!getC()) {
call(readWord());
cv = 24;
} else {
readWord();
cv = 12;
}
break;
case 0xD5: // PUSH DE
push(DE);
cv = 16;
break;
case 0xD6: // SUB nn
sub(readByte());
cv = 8;
break;
case 0xD7: // RST 10h
rst(0x10);
cv = 16;
break;
case 0xD8: // RET C
if(getC()) {
ret();
cv = 20;
} else {
cv = 8;
}
break;
case 0xD9: // RETI
ret();
ei();
cv = 16;
break;
case 0xDA: // JP C,nnnn
if(getC()) {
jp(readWord());
cv = 16;
} else {
readWord();
cv = 12;
}
break;
case 0xDB: // -
unsupported(0xDB);
cv = 4;
break;
case 0xDC: // CALL C,nnnn
if(getC()) {
call(readWord());
cv = 24;
} else {
readWord();
cv = 12;
}
break;
case 0xDD: // -
unsupported(0xDD);
cv = 4;
break;
case 0xDE: // SBC A,nn
sbc(readByte());
cv = 8;
break;
case 0xDF: // RST 18h
rst(0x18);
cv = 16;
break;
case 0xE0: // LD ($FF00+nn),A
mem.write(0xFF00 + readByte(), AF.getH());
cv = 12;
break;
case 0xE1: // POP HL
pop(HL);
cv = 12;
break;
case 0xE2: // LD ($FF00+C),A
mem.write(0xFF00 + BC.getL(), AF.getH());
cv = 8;
break;
case 0xE3: // -
unsupported(0xE3);
cv = 4;
break;
case 0xE4: // -
unsupported(0xE4);
cv = 4;
break;
case 0xE5: // PUSH HL
push(HL);
cv = 16;
break;
case 0xE6: // AND nn
and(readByte());
cv = 8;
break;
case 0xE7: // RST 20h
rst(0x20);
cv = 16;
break;
case 0xE8: // ADD SP,dd
SP.setR(SP.getR() + (byte)readByte());
setZ(false);
cv = 16;
break;
case 0xE9: // JP (HL)
jp(HL.getR());
cv = 4;
break;
case 0xEA: // LD (nnnn),A
mem.write(readWord(), AF.getH());
cv = 16;
break;
case 0xEB: // -
unsupported(0xEB);
cv = 4;
break;
case 0xEC: // -
unsupported(0xEC);
cv = 4;
break;
case 0xED: // -
unsupported(0xED);
cv = 4;
break;
case 0xEE: // XOR nn
xor(readByte());
cv = 8;
break;
case 0xEF: // RST 28h
rst(0x28);
cv = 16;
break;
case 0xF0: // LD A,($FF00+nn)
AF.setH(mem.read(0xFF00 + readByte()));
cv = 12;
break;
case 0xF1: // POP AF
pop(AF);
cv = 12;
break;
case 0xF2: // LD A,(C) [same as LD A,($FF00+C)]
AF.setH(mem.read(0xFF00 + BC.getL()));
cv = 8;
break;
case 0xF3: // DI
di();
cv = 4;
break;
case 0xF4: // -
unsupported(0xF4);
cv = 4;
break;
case 0xF5: // PUSH AF
push(AF);
cv = 16;
break;
case 0xF6: // OR nn
or(readByte());
cv = 8;
break;
case 0xF7: // RST 30h
rst(0x30);
cv = 16;
break;
case 0xF8: // LD HL,SP+dd
HL.setR(SP.getR() + (byte)readByte());
cv = 12;
break;
case 0xF9: // LD SP,HL
SP.setR(HL.getR());
cv = 8;
break;
case 0xFA: // LD A,(nnnn)
AF.setH(mem.read(readWord()));
cv = 16;
break;
case 0xFB: // EI
ei();
cv = 4;
break;
case 0xFC: // -
unsupported(0xFC);
cv = 4;
break;
case 0xFD: // -
unsupported(0xFD); //XXX was ei()
cv = 4;
break;
case 0xFE: // CP nn
cp(readByte());
cv = 8;
break;
case 0xFF: // RST 38h
rst(0x38);
cv = 16;
break;
default:
//System.out.println("Code: 0x" + Integer.toHexString(memread));
unsupported(memread);
cv = 4;
}
// cycle all hardware and set the interrupt flag
mem.cycle(cv);
// loop
cte -= cv;
}
}
private void interrupt(int i) {
if((i & PgbMemory.INT_VBLANK) == PgbMemory.INT_VBLANK) {
// vBlank
mem.IF &= ~PgbMemory.INT_VBLANK;
di();
rst(0x0040);
}
else if((i & PgbMemory.INT_LCD) == PgbMemory.INT_LCD) {
// LCD
mem.IF &= ~PgbMemory.INT_LCD;
di();
rst(0x0048);
}
else if((i & PgbMemory.INT_TIMER) == PgbMemory.INT_TIMER) {
// timer overflow
mem.IF &= ~PgbMemory.INT_TIMER;
di();
rst(0x0050);
}
else if((i & PgbMemory.INT_SERIAL) == PgbMemory.INT_SERIAL) {
// serial
mem.IF &= ~PgbMemory.INT_SERIAL;
di();
rst(0x0058);
}
else if((i & PgbMemory.INT_JOYPAD) == PgbMemory.INT_JOYPAD) {
// joypad
mem.IF &= ~PgbMemory.INT_JOYPAD;
di();
rst(0x0060);
}
}
/**
* interrupts
*/
private void di() {
//System.out.println("Interrupts DISabled.");
ime = false;
}
private void ei() {
//System.out.println("Interrupts ENabled.");
ime = true;
}
/**
* 8-bit acumulator arithmetic functions
*/
/**
* add
* @param val
*/
private void add(int val) {
int res = AF.getH() + val;
setC(res != (res &= 0xFF));
setZ(res);
setN(false);
AF.setH(res);
}
/**
* add with carrier
* @param val
*/
private void adc(int val) {
int res = AF.getH() + val + (getC() ? 1 : 0);
setC(res != (res &= 0xFF));
setZ(res);
setN(false);
AF.setH(res);
}
/**
* substract
* @param val
*/
private void sub(int val) {
int res = AF.getH() - val;
setC(res != (res &= 0xFF));
setZ(res);
setN(true);
AF.setH(res);
}
/**
* substract with carrier
* @param val
*/
private void sbc(int val) {
int res = AF.getH() - val - (getC() ? 1 : 0);
setC(res != (res &= 0xFF));
setZ(res);
setN(true);
AF.setH(res);
}
/**
* logical and
* @param val
*/
private void and(int val) {
int res = AF.getH() & val;
setC(false);
setZ(res);
setN(false);
AF.setH(res);
}
/**
* or
* @param val
*/
private void or(int val) {
int res = AF.getH() | val;
setC(false);
setZ(res);
setN(false);
AF.setH(res);
}
/**
* exclusive or
* @param val
*/
private void xor(int val) {
int res = AF.getH() ^ val;
setC(false);
setZ(res);
setN(false);
AF.setH(res);
}
/**
* compare
* @param val
*/
private void cp(int val) {
setC(AF.getH() < val);
setZ(AF.getH() == val);
setN(true);
}
/**
* 8-bit register arithmetic functions
*/
/**
* increase higher
* @param reg
*/
private void incH(PgbRegister reg) {
int res = (reg.getH() + 1);
res &= 0xFF;
setZ(res);
setN(false);
reg.setH(res);
}
/**
* increase lower
* @param reg
*/
private void incL(PgbRegister reg) {
int res = (reg.getL() + 1);
res &= 0xFF;
setZ(res);
setN(false);
reg.setL(res);
}
/**
* increase memory location (?)
* @param reg
*/
private void incI(PgbRegister reg) {
int res = reg.getI(mem) + 1;
res &= 0xFF;
setZ(res);
setN(false);
reg.setI(res, mem);
}
/**
* decrease higher
* @param reg
*/
private void decH(PgbRegister reg) {
int res = reg.getH() - 1;
res &= 0xFF;
setZ(res);
setN(true);
reg.setH(res);
}
/**
* decrease lower
* @param reg
*/
private void decL(PgbRegister reg) {
int res = reg.getL() - 1;
res &= 0xFF;
setZ(res);
setN(true);
reg.setL(res);
}
/**
* decrease memory location(?)
* @param reg
*/
private void decI(PgbRegister reg) {
int res = reg.getI(mem) - 1;
res &= 0xFF;
setZ(res);
setN(true);
reg.setI(res, mem);
}
/**
* 16-bit register opcode functions
*/
/**
* increase register
* @param reg
*/
private void incR(PgbRegister reg) {
reg.setR(reg.getR() + 1 & 0xFFFF);
}
/**
* decrease register
* @param reg
*/
private void decR(PgbRegister reg) {
reg.setR(reg.getR() - 1 & 0xFFFF);
}
/**
* add register reg1 to register reg0
* @param reg0
* @param reg1
*/
private void addR(PgbRegister reg0, PgbRegister reg1) {
int res = reg0.getR() + reg1.getR();
setC(res != (res &= 0xFFFF));
reg0.setR(res);
}
/**
* stack
*/
private void pop(PgbRegister reg) {
reg.setL(mem.read(SP.data++));
reg.setH(mem.read(SP.data++));
}
private void push(PgbRegister reg) {
// arggh. some roms push with SP == 0x0000,
// totally ruining the elegance of this expression
mem.write(--SP.data & 0xFFFF, reg.getH());
SP.data &= 0xFFFF;
mem.write(--SP.data, reg.getL());
}
/**
* jumping around...
*/
private void jp(int address) {
PC.setR(address);
}
private void jr(int offset) {
PC.setR(PC.getR() + (byte)offset);
}
private void call(int address) {
push(PC);
PC.setR(address);
}
private void rst(int address) {
push(PC);
PC.setR(address);
}
private void ret() {
pop(PC);
}
/**
* bitwise operators
*/
private void bit(int bit, int val) {
int res = val & 1 << bit;
setZ(res);
setN(false);
}
private void resH(int bit, PgbRegister reg) {
int res = reg.getH() & ~(1 << bit);
reg.setH(res);
}
private void resL(int bit, PgbRegister reg) {
int res = reg.getL() & ~(1 << bit);
reg.setL(res);
}
private void resI(int bit, int address) {
int res = unsign(mem.read(address)) & ~(1 << bit);
mem.write(address, res);
}
private void setH(int bit, PgbRegister reg) {
int res = reg.getH() | 1 << bit;
reg.setH(res);
}
private void setL(int bit, PgbRegister reg) {
int res = reg.getL() | 1 << bit;
reg.setL(res);
}
private void setI(int bit, int address) {
int res = unsign(mem.read(address)) | 1 << bit;
mem.write(address, res);
}
/**
* rotates and shifts
*/
private void rrcH(PgbRegister reg) {
int res = reg.getH();
setC((res & 0x01) == 1);
res = (res >> 1) | ((res & 0x01) << 7);
setZ(res);
setN(false);
reg.setH(res);
}
private void rrcL(PgbRegister reg) {
int res = reg.getL();
setC((res & 0x01) == 1);
res = (res >> 1) | ((res & 0x01) << 7);
setZ(res);
setN(false);
reg.setL(res);
}
private void rrcI(int address) {
int res = unsign(mem.read(address));
setC((res & 0x01) == 1);
res = (res >> 1) | ((res & 0x01) << 7);
setZ(res);
setN(false);
mem.write(address, res);
}
private void rrH(PgbRegister reg) {
int res = reg.getH();
res = (res >> 1) | (getC() ? 0x80 : 0);
setC((reg.getH() & 0x01) == 1);
setZ(res);
setN(false);
reg.setH(res);
}
private void rrL(PgbRegister reg) {
int res = reg.getL();
res = (res >> 1) | (getC() ? 0x80 : 0);
setC((reg.getL() & 0x01) == 1);
setZ(res);
setN(false);
reg.setL(res);
}
private void rrI(int address) {
int res = unsign(mem.read(address));
res = (res >> 1) | (getC() ? 0x80 : 0);
setC((unsign(mem.read(address)) & 0x01) == 1);
setZ(res);
setN(false);
mem.write(address, res);
}
private void rlcH(PgbRegister reg) {
int res = reg.getH();
res = (res << 1) | (res >> 7);
setC(res != (res &= 0xFF));
setZ(res);
setN(false);
reg.setH(res);
}
private void rlcL(PgbRegister reg) {
int res = reg.getL();
res = (res << 1) | (res >> 7);
setC(res != (res &= 0xFF));
setZ(res);
setN(false);
reg.setL(res);
}
private void rlcI(int address) {
int res = unsign(mem.read(address));
res = (res << 1) | (res >> 7);
setC(res != (res &= 0xFF));
setZ(res);
setN(false);
mem.write(address, res);
}
private void rlH(PgbRegister reg) {
int res = (reg.getH() << 1) | (getC() ? 1 : 0);
setC(res != (res &= 0xFF));
setZ(res);
setN(false);
reg.setH(res);
}
private void rlL(PgbRegister reg) {
int res = (reg.getL() << 1) | (getC() ? 1 : 0);
setC(res != (res &= 0xFF));
setZ(res);
setN(false);
reg.setL(res);
}
private void rlI(int address) {
int res = (unsign(mem.read(address)) << 1) | (getC() ? 1 : 0);
setC(res != (res &= 0xFF));
setZ(res);
setN(false);
mem.write(address, res);
}
private void sraH(PgbRegister reg) {
int res = reg.getH();
setC((res & 1) == 1);
res = (res >> 1) | (res & 0x80);
setZ(res);
setN(false);
reg.setH(res);
}
private void sraL(PgbRegister reg) {
int res = reg.getL();
setC((res & 1) == 1);
res = (res >> 1) | (res & 0x80);
setZ(res);
setN(false);
reg.setL(res);
}
private void sraI(int address) {
int res = unsign(mem.read(address));
setC((res & 1) == 1);
res = (res >> 1) | (res & 0x80);
setZ(res);
setN(false);
mem.write(address, res);
}
private void slaH(PgbRegister reg) {
int res = reg.getH() << 1;
setC(res != (res &= 0xFF));
setZ(res);
setN(false);
reg.setH(res);
}
private void slaL(PgbRegister reg) {
int res = reg.getL() << 1;
setC(res != (res &= 0xFF));
setZ(res);
setN(false);
reg.setL(res);
}
private void slaI(int address) {
int res = unsign(mem.read(address));
res *= 2;
setC(res != (res &= 0xFF));
setZ(res);
setN(false);
mem.write(address, res);
}
private void srlH(PgbRegister reg) {
int res = reg.getH();
setC((res & 1) == 1);
res >>= 1;
setZ(res);
setN(false);
reg.setH(res);
}
private void srlL(PgbRegister reg) {
int res = reg.getL();
setC((res & 1) == 1);
res >>= 1;
setZ(res);
setN(false);
reg.setL(res);
}
private void srlI(int address) {
int res = unsign(mem.read(address));
setC((res & 1) == 1);
res >>= 1;
setZ(res);
setN(false);
mem.write(address, res);
}
/**
* misc operations
*/
private void cpl() {
int res = ~AF.getH() & 0xFF;
setN(true);
AF.setH(res);
}
private void daa() {
int res = AF.getH();
if(getN()) {
if(res / 16 > 9) {
res -= 0x60;
}
if((res & 15) > 9) {
res -= 0x06;
}
} else {
if(res / 16 > 9) {
res += 0x60;
}
if((res & 15) > 9) {
res += 0x06;
}
}
setC(res != (res &= 0xFF));
setZ(res);
AF.setH(res);
}
private void swapH(PgbRegister reg) {
int res = ((reg.getH() << 4) & 0xF0) | (reg.getH() >> 4);
setC(false);
setZ(res);
setN(false);
reg.setH(res);
}
private void swapL(PgbRegister reg) {
int res = ((reg.getL() << 4) & 0xF0) | (reg.getL() >> 4);
setC(false);
setZ(res);
setN(false);
reg.setL(res);
}
private void swapI(int address) {
int res = ((unsign(mem.read(address)) << 4) & 0xF0) | (unsign(mem.read(address)) >> 4);
setC(false);
setZ(res);
setN(false);
mem.write(address, res);
}
/**
* flaggies?
*/
private void setZ(boolean zval) {
AF.lo &= ~Z_FLAG;
if(zval) {
AF.lo |= Z_FLAG;
}
}
private void setZ(int zval) {
AF.lo &= ~Z_FLAG;
if(zval == 0) {
AF.lo |= Z_FLAG;
}
}
private void setN(boolean nval) {
AF.lo &= ~N_FLAG;
if(nval) {
AF.lo |= N_FLAG;
}
}
private void setH(boolean hval) {
AF.lo &= ~H_FLAG;
if(hval) {
AF.lo |= H_FLAG;
}
}
private void setC(boolean cval) {
AF.lo &= ~C_FLAG;
if(cval) {
AF.lo |= C_FLAG;
}
}
private boolean getZ() {
return (AF.getL() & Z_FLAG) == Z_FLAG;
}
private boolean getN() {
return (AF.getL() & N_FLAG) == N_FLAG;
}
private boolean getH() {
return (AF.getL() & H_FLAG) == H_FLAG;
}
private boolean getC() {
return (AF.getL() & C_FLAG) == C_FLAG;
}
/**
* reads
*/
private int readWord() {
return unsign(mem.read(PC.data++)) | unsign(mem.read(PC.data++)) << 8;
}
private int readByte() {
return unsign(mem.read(PC.data++));
}
/**
* status displays
*/
private void unsupportedCB(int cb) {
System.out.println("unsupported CB code: " + Integer.toHexString(cb));
//PgbSettings.paused = true;
}
private void unsupported(int op) {
System.out.println(Integer.toHexString(PC.data - 1) + " unsupported opcode: " + Integer.toHexString(op));
//PgbSettings.paused = true;;
}
/**
* unsign a byte
*/
private int unsign(byte b) {
return b & 0xFF;
}
}