mirror of
https://github.com/dborth/vbagx.git
synced 2024-12-27 11:11:50 +01:00
1461 lines
34 KiB
C++
1461 lines
34 KiB
C++
// -*- C++ -*-
|
|
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
|
|
// Copyright (C) 1999-2003 Forgotten
|
|
// Copyright (C) 2005-2006 Forgotten and the VBA development team
|
|
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2, or(at your option)
|
|
// any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software Foundation,
|
|
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
case 0x00:
|
|
// NOP
|
|
break;
|
|
case 0x01:
|
|
// LD BC, NNNN
|
|
BC.B.B0=gbReadOpcode(PC.W++);
|
|
BC.B.B1=gbReadOpcode(PC.W++);
|
|
break;
|
|
case 0x02:
|
|
// LD (BC),A
|
|
gbWriteMemory(BC.W,AF.B.B1);
|
|
break;
|
|
case 0x03:
|
|
// INC BC
|
|
BC.W++;
|
|
break;
|
|
case 0x04:
|
|
// INC B
|
|
BC.B.B1++;
|
|
AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[BC.B.B1]| (BC.B.B1&0x0F? 0:H_FLAG);
|
|
break;
|
|
case 0x05:
|
|
// DEC B
|
|
BC.B.B1--;
|
|
AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[BC.B.B1]|
|
|
((BC.B.B1&0x0F)==0x0F? H_FLAG:0);
|
|
break;
|
|
case 0x06:
|
|
// LD B, NN
|
|
BC.B.B1=gbReadOpcode(PC.W++);
|
|
break;
|
|
case 0x07:
|
|
// RLCA
|
|
tempValue=AF.B.B1&0x80? C_FLAG:0;
|
|
AF.B.B1=(AF.B.B1<<1)|(AF.B.B1>>7);
|
|
AF.B.B0=tempValue;
|
|
break;
|
|
case 0x08:
|
|
// LD (NNNN), SP
|
|
tempRegister.B.B0=gbReadOpcode(PC.W++);
|
|
tempRegister.B.B1=gbReadOpcode(PC.W++);
|
|
gbWriteMemory(tempRegister.W++,SP.B.B0);
|
|
gbWriteMemory(tempRegister.W,SP.B.B1);
|
|
break;
|
|
case 0x09:
|
|
// ADD HL,BC
|
|
tempRegister.W=(HL.W+BC.W)&0xFFFF;
|
|
AF.B.B0= (AF.B.B0 & Z_FLAG)| ((HL.W^BC.W^tempRegister.W)&0x1000? H_FLAG:0)|
|
|
(((long)HL.W+(long)BC.W)&0x10000? C_FLAG:0);
|
|
HL.W=tempRegister.W;
|
|
break;
|
|
case 0x0a:
|
|
// LD A,(BC)
|
|
AF.B.B1=gbReadMemory(BC.W);
|
|
break;
|
|
case 0x0b:
|
|
// DEC BC
|
|
BC.W--;
|
|
break;
|
|
case 0x0c:
|
|
// INC C
|
|
BC.B.B0++;
|
|
AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[BC.B.B0]| (BC.B.B0&0x0F? 0:H_FLAG);
|
|
break;
|
|
case 0x0d:
|
|
// DEC C
|
|
BC.B.B0--;
|
|
AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[BC.B.B0]|
|
|
((BC.B.B0&0x0F)==0x0F? H_FLAG:0);
|
|
break;
|
|
case 0x0e:
|
|
// LD C, NN
|
|
BC.B.B0=gbReadOpcode(PC.W++);
|
|
break;
|
|
case 0x0f:
|
|
// RRCA
|
|
tempValue=AF.B.B1&0x01;
|
|
AF.B.B1=(AF.B.B1>>1)|(tempValue? 0x80:0);
|
|
AF.B.B0=(tempValue<<4);
|
|
break;
|
|
case 0x10:
|
|
// STOP
|
|
opcode = gbReadOpcode(PC.W++);
|
|
if(gbCgbMode) {
|
|
if(gbMemory[0xff4d] & 1) {
|
|
|
|
gbSpeedSwitch();
|
|
//clockTicks += 228*144-(gbSpeed ? 62 : 63);
|
|
|
|
if(gbSpeed == 0)
|
|
gbMemory[0xff4d] = 0x00;
|
|
else
|
|
gbMemory[0xff4d] = 0x80;
|
|
}
|
|
}
|
|
break;
|
|
case 0x11:
|
|
// LD DE, NNNN
|
|
DE.B.B0=gbReadOpcode(PC.W++);
|
|
DE.B.B1=gbReadOpcode(PC.W++);
|
|
break;
|
|
case 0x12:
|
|
// LD (DE),A
|
|
gbWriteMemory(DE.W,AF.B.B1);
|
|
break;
|
|
case 0x13:
|
|
// INC DE
|
|
DE.W++;
|
|
break;
|
|
case 0x14:
|
|
// INC D
|
|
DE.B.B1++;
|
|
AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[DE.B.B1]| (DE.B.B1&0x0F? 0:H_FLAG);
|
|
break;
|
|
case 0x15:
|
|
// DEC D
|
|
DE.B.B1--;
|
|
AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[DE.B.B1]|
|
|
((DE.B.B1&0x0F)==0x0F? H_FLAG:0);
|
|
break;
|
|
case 0x16:
|
|
// LD D,NN
|
|
DE.B.B1=gbReadOpcode(PC.W++);
|
|
break;
|
|
case 0x17:
|
|
// RLA
|
|
tempValue=AF.B.B1&0x80? C_FLAG:0;
|
|
AF.B.B1=(AF.B.B1<<1)|((AF.B.B0&C_FLAG)>>4);
|
|
AF.B.B0=tempValue;
|
|
break;
|
|
case 0x18:
|
|
// JR NN
|
|
PC.W+=(s8)gbReadOpcode(PC.W)+1;
|
|
break;
|
|
case 0x19:
|
|
// ADD HL,DE
|
|
tempRegister.W=(HL.W+DE.W)&0xFFFF;
|
|
AF.B.B0= (AF.B.B0 & Z_FLAG)| ((HL.W^DE.W^tempRegister.W)&0x1000? H_FLAG:0)|
|
|
(((long)HL.W+(long)DE.W)&0x10000? C_FLAG:0);
|
|
HL.W=tempRegister.W;
|
|
break;
|
|
case 0x1a:
|
|
// LD A,(DE)
|
|
AF.B.B1=gbReadMemory(DE.W);
|
|
break;
|
|
case 0x1b:
|
|
// DEC DE
|
|
DE.W--;
|
|
break;
|
|
case 0x1c:
|
|
// INC E
|
|
DE.B.B0++;
|
|
AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[DE.B.B0]| (DE.B.B0&0x0F? 0:H_FLAG);
|
|
break;
|
|
case 0x1d:
|
|
// DEC E
|
|
DE.B.B0--;
|
|
AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[DE.B.B0]|
|
|
((DE.B.B0&0x0F)==0x0F? H_FLAG:0);
|
|
break;
|
|
case 0x1e:
|
|
// LD E,NN
|
|
DE.B.B0=gbReadOpcode(PC.W++);
|
|
break;
|
|
case 0x1f:
|
|
// RRA
|
|
tempValue=AF.B.B1&0x01;
|
|
AF.B.B1=(AF.B.B1>>1)|(AF.B.B0&C_FLAG? 0x80:0);
|
|
AF.B.B0=(tempValue<<4);
|
|
break;
|
|
case 0x20:
|
|
// JR NZ,NN
|
|
if(AF.B.B0&Z_FLAG)
|
|
PC.W++;
|
|
else {
|
|
PC.W+=(s8)gbReadOpcode(PC.W)+1;
|
|
clockTicks++;
|
|
}
|
|
break;
|
|
case 0x21:
|
|
// LD HL,NNNN
|
|
HL.B.B0=gbReadOpcode(PC.W++);
|
|
HL.B.B1=gbReadOpcode(PC.W++);
|
|
break;
|
|
case 0x22:
|
|
// LDI (HL),A
|
|
gbWriteMemory(HL.W++,AF.B.B1);
|
|
break;
|
|
case 0x23:
|
|
// INC HL
|
|
HL.W++;
|
|
break;
|
|
case 0x24:
|
|
// INC H
|
|
HL.B.B1++;
|
|
AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[HL.B.B1]| (HL.B.B1&0x0F? 0:H_FLAG);
|
|
break;
|
|
case 0x25:
|
|
// DEC H
|
|
HL.B.B1--;
|
|
AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[HL.B.B1]|
|
|
((HL.B.B1&0x0F)==0x0F? H_FLAG:0);
|
|
break;
|
|
case 0x26:
|
|
// LD H,NN
|
|
HL.B.B1=gbReadOpcode(PC.W++);
|
|
break;
|
|
case 0x27:
|
|
// DAA
|
|
tempRegister.W=AF.B.B1;
|
|
if(AF.B.B0&C_FLAG) tempRegister.W|=256;
|
|
if(AF.B.B0&H_FLAG) tempRegister.W|=512;
|
|
if(AF.B.B0&N_FLAG) tempRegister.W|=1024;
|
|
AF.W=DAATable[tempRegister.W];
|
|
break;
|
|
case 0x28:
|
|
// JR Z,NN
|
|
if(AF.B.B0&Z_FLAG) {
|
|
PC.W+=(s8)gbReadOpcode(PC.W)+1;
|
|
clockTicks++;
|
|
} else
|
|
PC.W++;
|
|
break;
|
|
case 0x29:
|
|
// ADD HL,HL
|
|
tempRegister.W=(HL.W+HL.W)&0xFFFF; AF.B.B0= (AF.B.B0 & Z_FLAG)|
|
|
((HL.W^HL.W^tempRegister.W)&0x1000? H_FLAG:0)|
|
|
(((long)HL.W+(long)HL.W)&0x10000? C_FLAG:0);
|
|
HL.W=tempRegister.W;
|
|
break;
|
|
case 0x2a:
|
|
// LDI A,(HL)
|
|
AF.B.B1 = gbReadMemory(HL.W++);
|
|
break;
|
|
case 0x2b:
|
|
// DEC HL
|
|
HL.W--;
|
|
break;
|
|
case 0x2c:
|
|
// INC L
|
|
HL.B.B0++;
|
|
AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[HL.B.B0]| (HL.B.B0&0x0F? 0:H_FLAG);
|
|
break;
|
|
case 0x2d:
|
|
// DEC L
|
|
HL.B.B0--;
|
|
AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[HL.B.B0]|
|
|
((HL.B.B0&0x0F)==0x0F? H_FLAG:0);
|
|
break;
|
|
case 0x2e:
|
|
// LD L,NN
|
|
HL.B.B0=gbReadOpcode(PC.W++);
|
|
break;
|
|
case 0x2f:
|
|
// CPL
|
|
AF.B.B1 ^= 255;
|
|
AF.B.B0|=N_FLAG|H_FLAG;
|
|
break;
|
|
case 0x30:
|
|
// JR NC,NN
|
|
if(AF.B.B0&C_FLAG)
|
|
PC.W++;
|
|
else {
|
|
PC.W+=(s8)gbReadOpcode(PC.W)+1;
|
|
clockTicks++;
|
|
}
|
|
break;
|
|
case 0x31:
|
|
// LD SP,NNNN
|
|
SP.B.B0=gbReadOpcode(PC.W++);
|
|
SP.B.B1=gbReadOpcode(PC.W++);
|
|
break;
|
|
case 0x32:
|
|
// LDD (HL),A
|
|
gbWriteMemory(HL.W--,AF.B.B1);
|
|
break;
|
|
case 0x33:
|
|
// INC SP
|
|
SP.W++;
|
|
break;
|
|
case 0x34:
|
|
// INC (HL)
|
|
tempValue=gbReadMemory(HL.W)+1;
|
|
AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[tempValue]| (tempValue&0x0F? 0:H_FLAG);
|
|
gbWriteMemory(HL.W,tempValue);
|
|
break;
|
|
case 0x35:
|
|
// DEC (HL)
|
|
tempValue=gbReadMemory(HL.W)-1;
|
|
AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[tempValue]|
|
|
((tempValue&0x0F)==0x0F? H_FLAG:0);gbWriteMemory(HL.W,tempValue);
|
|
break;
|
|
case 0x36:
|
|
// LD (HL),NN
|
|
gbWriteMemory(HL.W,gbReadOpcode(PC.W++));
|
|
break;
|
|
case 0x37:
|
|
// SCF
|
|
AF.B.B0 = AF.B.B0 & Z_FLAG | C_FLAG;
|
|
break;
|
|
case 0x38:
|
|
// JR C,NN
|
|
if(AF.B.B0&C_FLAG) {
|
|
PC.W+=(s8)gbReadOpcode(PC.W)+1;
|
|
clockTicks ++;
|
|
} else
|
|
PC.W++;
|
|
break;
|
|
case 0x39:
|
|
// ADD HL,SP
|
|
tempRegister.W=(HL.W+SP.W)&0xFFFF;
|
|
AF.B.B0= (AF.B.B0 & Z_FLAG)| ((HL.W^SP.W^tempRegister.W)&0x1000? H_FLAG:0)|
|
|
(((long)HL.W+(long)SP.W)&0x10000? C_FLAG:0);
|
|
HL.W=tempRegister.W;
|
|
break;
|
|
case 0x3a:
|
|
// LDD A,(HL)
|
|
AF.B.B1 = gbReadMemory(HL.W--);
|
|
break;
|
|
case 0x3b:
|
|
// DEC SP
|
|
SP.W--;
|
|
break;
|
|
case 0x3c:
|
|
// INC A
|
|
AF.B.B1++;
|
|
AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[AF.B.B1]| (AF.B.B1&0x0F? 0:H_FLAG);
|
|
break;
|
|
case 0x3d:
|
|
// DEC A
|
|
AF.B.B1--;
|
|
AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[AF.B.B1]|
|
|
((AF.B.B1&0x0F)==0x0F? H_FLAG:0);
|
|
break;
|
|
case 0x3e:
|
|
// LD A,NN
|
|
AF.B.B1=gbReadOpcode(PC.W++);
|
|
break;
|
|
case 0x3f:
|
|
// CCF
|
|
AF.B.B0^=C_FLAG;AF.B.B0&=~(N_FLAG|H_FLAG);
|
|
break;
|
|
case 0x40:
|
|
// LD B,B
|
|
BC.B.B1=BC.B.B1;
|
|
break;
|
|
case 0x41:
|
|
// LD B,C
|
|
BC.B.B1=BC.B.B0;
|
|
break;
|
|
case 0x42:
|
|
// LD B,D
|
|
BC.B.B1=DE.B.B1;
|
|
break;
|
|
case 0x43:
|
|
// LD B,E
|
|
BC.B.B1=DE.B.B0;
|
|
break;
|
|
case 0x44:
|
|
// LD B,H
|
|
BC.B.B1=HL.B.B1;
|
|
break;
|
|
case 0x45:
|
|
// LD B,L
|
|
BC.B.B1=HL.B.B0;
|
|
break;
|
|
case 0x46:
|
|
// LD B,(HL)
|
|
BC.B.B1=gbReadMemory(HL.W);
|
|
break;
|
|
case 0x47:
|
|
// LD B,A
|
|
BC.B.B1=AF.B.B1;
|
|
break;
|
|
case 0x48:
|
|
// LD C,B
|
|
BC.B.B0=BC.B.B1;
|
|
break;
|
|
case 0x49:
|
|
// LD C,C
|
|
BC.B.B0=BC.B.B0;
|
|
break;
|
|
case 0x4a:
|
|
// LD C,D
|
|
BC.B.B0=DE.B.B1;
|
|
break;
|
|
case 0x4b:
|
|
// LD C,E
|
|
BC.B.B0=DE.B.B0;
|
|
break;
|
|
case 0x4c:
|
|
// LD C,H
|
|
BC.B.B0=HL.B.B1;
|
|
break;
|
|
case 0x4d:
|
|
// LD C,L
|
|
BC.B.B0=HL.B.B0;
|
|
break;
|
|
case 0x4e:
|
|
// LD C,(HL)
|
|
BC.B.B0=gbReadMemory(HL.W);
|
|
break;
|
|
case 0x4f:
|
|
// LD C,A
|
|
BC.B.B0=AF.B.B1;
|
|
break;
|
|
case 0x50:
|
|
// LD D,B
|
|
DE.B.B1=BC.B.B1;
|
|
break;
|
|
case 0x51:
|
|
// LD D,C
|
|
DE.B.B1=BC.B.B0;
|
|
break;
|
|
case 0x52:
|
|
// LD D,D
|
|
DE.B.B1=DE.B.B1;
|
|
break;
|
|
case 0x53:
|
|
// LD D,E
|
|
DE.B.B1=DE.B.B0;
|
|
break;
|
|
case 0x54:
|
|
// LD D,H
|
|
DE.B.B1=HL.B.B1;
|
|
break;
|
|
case 0x55:
|
|
// LD D,L
|
|
DE.B.B1=HL.B.B0;
|
|
break;
|
|
case 0x56:
|
|
// LD D,(HL)
|
|
DE.B.B1=gbReadMemory(HL.W);
|
|
break;
|
|
case 0x57:
|
|
// LD D,A
|
|
DE.B.B1=AF.B.B1;
|
|
break;
|
|
case 0x58:
|
|
// LD E,B
|
|
DE.B.B0=BC.B.B1;
|
|
break;
|
|
case 0x59:
|
|
// LD E,C
|
|
DE.B.B0=BC.B.B0;
|
|
break;
|
|
case 0x5a:
|
|
// LD E,D
|
|
DE.B.B0=DE.B.B1;
|
|
break;
|
|
case 0x5b:
|
|
// LD E,E
|
|
DE.B.B0=DE.B.B0;
|
|
break;
|
|
case 0x5c:
|
|
// LD E,H
|
|
DE.B.B0=HL.B.B1;
|
|
break;
|
|
case 0x5d:
|
|
// LD E,L
|
|
DE.B.B0=HL.B.B0;
|
|
break;
|
|
case 0x5e:
|
|
// LD E,(HL)
|
|
DE.B.B0=gbReadMemory(HL.W);
|
|
break;
|
|
case 0x5f:
|
|
// LD E,A
|
|
DE.B.B0=AF.B.B1;
|
|
break;
|
|
case 0x60:
|
|
// LD H,B
|
|
HL.B.B1=BC.B.B1;
|
|
break;
|
|
case 0x61:
|
|
// LD H,C
|
|
HL.B.B1=BC.B.B0;
|
|
break;
|
|
case 0x62:
|
|
// LD H,D
|
|
HL.B.B1=DE.B.B1;
|
|
break;
|
|
case 0x63:
|
|
// LD H,E
|
|
HL.B.B1=DE.B.B0;
|
|
break;
|
|
case 0x64:
|
|
// LD H,H
|
|
HL.B.B1=HL.B.B1;
|
|
break;
|
|
case 0x65:
|
|
// LD H,L
|
|
HL.B.B1=HL.B.B0;
|
|
break;
|
|
case 0x66:
|
|
// LD H,(HL)
|
|
HL.B.B1=gbReadMemory(HL.W);
|
|
break;
|
|
case 0x67:
|
|
// LD H,A
|
|
HL.B.B1=AF.B.B1;
|
|
break;
|
|
case 0x68:
|
|
// LD L,B
|
|
HL.B.B0=BC.B.B1;
|
|
break;
|
|
case 0x69:
|
|
// LD L,C
|
|
HL.B.B0=BC.B.B0;
|
|
break;
|
|
case 0x6a:
|
|
// LD L,D
|
|
HL.B.B0=DE.B.B1;
|
|
break;
|
|
case 0x6b:
|
|
// LD L,E
|
|
HL.B.B0=DE.B.B0;
|
|
break;
|
|
case 0x6c:
|
|
// LD L,H
|
|
HL.B.B0=HL.B.B1;
|
|
break;
|
|
case 0x6d:
|
|
// LD L,L
|
|
HL.B.B0=HL.B.B0;
|
|
break;
|
|
case 0x6e:
|
|
// LD L,(HL)
|
|
HL.B.B0=gbReadMemory(HL.W);
|
|
break;
|
|
case 0x6f:
|
|
// LD L,A
|
|
HL.B.B0=AF.B.B1;
|
|
break;
|
|
case 0x70:
|
|
// LD (HL),B
|
|
gbWriteMemory(HL.W,BC.B.B1);
|
|
break;
|
|
case 0x71:
|
|
// LD (HL),C
|
|
gbWriteMemory(HL.W,BC.B.B0);
|
|
break;
|
|
case 0x72:
|
|
// LD (HL),D
|
|
gbWriteMemory(HL.W,DE.B.B1);
|
|
break;
|
|
case 0x73:
|
|
// LD (HL),E
|
|
gbWriteMemory(HL.W,DE.B.B0);
|
|
break;
|
|
case 0x74:
|
|
// LD (HL),H
|
|
gbWriteMemory(HL.W,HL.B.B1);
|
|
break;
|
|
case 0x75:
|
|
// LD (HL),L
|
|
gbWriteMemory(HL.W,HL.B.B0);
|
|
break;
|
|
case 0x76:
|
|
// HALT
|
|
// If an EI is pending, the interrupts are triggered before Halt state !!
|
|
// Fix Torpedo Range's intro.
|
|
if (IFF & 0x40)
|
|
{
|
|
IFF &= ~0x70;
|
|
IFF |=1;
|
|
PC.W--;
|
|
}
|
|
else
|
|
{
|
|
// if (IE & IF) and interrupts are disabeld,
|
|
// Halt is cancelled.
|
|
if ((register_IE & register_IF & 0x1f) && !(IFF & 1))
|
|
{
|
|
IFF|=2;
|
|
}
|
|
else
|
|
IFF |= 0x80;
|
|
}
|
|
break;
|
|
case 0x77:
|
|
// LD (HL),A
|
|
gbWriteMemory(HL.W,AF.B.B1);
|
|
break;
|
|
case 0x78:
|
|
// LD A,B
|
|
AF.B.B1=BC.B.B1;
|
|
break;
|
|
case 0x79:
|
|
// LD A,C
|
|
AF.B.B1=BC.B.B0;
|
|
break;
|
|
case 0x7a:
|
|
// LD A,D
|
|
AF.B.B1=DE.B.B1;
|
|
break;
|
|
case 0x7b:
|
|
// LD A,E
|
|
AF.B.B1=DE.B.B0;
|
|
break;
|
|
case 0x7c:
|
|
// LD A,H
|
|
AF.B.B1=HL.B.B1;
|
|
break;
|
|
case 0x7d:
|
|
// LD A,L
|
|
AF.B.B1=HL.B.B0;
|
|
break;
|
|
case 0x7e:
|
|
// LD A,(HL)
|
|
AF.B.B1=gbReadMemory(HL.W);
|
|
break;
|
|
case 0x7f:
|
|
// LD A,A
|
|
AF.B.B1=AF.B.B1;
|
|
break;
|
|
case 0x80:
|
|
// ADD B
|
|
tempRegister.W=AF.B.B1+BC.B.B1;
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^BC.B.B1^tempRegister.B.B0)&0x10 ? H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x81:
|
|
// ADD C
|
|
tempRegister.W=AF.B.B1+BC.B.B0;
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^BC.B.B0^tempRegister.B.B0)&0x10 ? H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x82:
|
|
// ADD D
|
|
tempRegister.W=AF.B.B1+DE.B.B1;
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^DE.B.B1^tempRegister.B.B0)&0x10 ? H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x83:
|
|
// ADD E
|
|
tempRegister.W=AF.B.B1+DE.B.B0;
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^DE.B.B0^tempRegister.B.B0)&0x10 ? H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x84:
|
|
// ADD H
|
|
tempRegister.W=AF.B.B1+HL.B.B1;
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^HL.B.B1^tempRegister.B.B0)&0x10 ? H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x85:
|
|
// ADD L
|
|
tempRegister.W=AF.B.B1+HL.B.B0;
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^HL.B.B0^tempRegister.B.B0)&0x10 ? H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x86:
|
|
// ADD (HL)
|
|
tempValue=gbReadMemory(HL.W);
|
|
tempRegister.W=AF.B.B1+tempValue;
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^tempValue^tempRegister.B.B0)&0x10 ? H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x87:
|
|
// ADD A
|
|
tempRegister.W=AF.B.B1+AF.B.B1;
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^AF.B.B1^tempRegister.B.B0)&0x10 ? H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x88:
|
|
// ADC B:
|
|
tempRegister.W=AF.B.B1+BC.B.B1+(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^BC.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x89:
|
|
// ADC C
|
|
tempRegister.W=AF.B.B1+BC.B.B0+(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^BC.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x8a:
|
|
// ADC D
|
|
tempRegister.W=AF.B.B1+DE.B.B1+(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^DE.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x8b:
|
|
// ADC E
|
|
tempRegister.W=AF.B.B1+DE.B.B0+(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^DE.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x8c:
|
|
// ADC H
|
|
tempRegister.W=AF.B.B1+HL.B.B1+(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^HL.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x8d:
|
|
// ADC L
|
|
tempRegister.W=AF.B.B1+HL.B.B0+(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^HL.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x8e:
|
|
// ADC (HL)
|
|
tempValue=gbReadMemory(HL.W);
|
|
tempRegister.W=AF.B.B1+tempValue+(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x8f:
|
|
// ADC A
|
|
tempRegister.W=AF.B.B1+AF.B.B1+(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^AF.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x90:
|
|
// SUB B
|
|
tempRegister.W=AF.B.B1-BC.B.B1;
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^BC.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x91:
|
|
// SUB C
|
|
tempRegister.W=AF.B.B1-BC.B.B0;
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^BC.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x92:
|
|
// SUB D
|
|
tempRegister.W=AF.B.B1-DE.B.B1;
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^DE.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x93:
|
|
// SUB E
|
|
tempRegister.W=AF.B.B1-DE.B.B0;
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^DE.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x94:
|
|
// SUB H
|
|
tempRegister.W=AF.B.B1-HL.B.B1;
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^HL.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x95:
|
|
// SUB L
|
|
tempRegister.W=AF.B.B1-HL.B.B0;
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^HL.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x96:
|
|
// SUB (HL)
|
|
tempValue=gbReadMemory(HL.W);
|
|
tempRegister.W=AF.B.B1-tempValue;
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x97:
|
|
// SUB A
|
|
AF.B.B1=0;
|
|
AF.B.B0=N_FLAG|Z_FLAG;
|
|
break;
|
|
case 0x98:
|
|
// SBC B
|
|
tempRegister.W=AF.B.B1-BC.B.B1-(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^BC.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x99:
|
|
// SBC C
|
|
tempRegister.W=AF.B.B1-BC.B.B0-(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^BC.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x9a:
|
|
// SBC D
|
|
tempRegister.W=AF.B.B1-DE.B.B1-(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^DE.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x9b:
|
|
// SBC E
|
|
tempRegister.W=AF.B.B1-DE.B.B0-(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^DE.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x9c:
|
|
// SBC H
|
|
tempRegister.W=AF.B.B1-HL.B.B1-(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^HL.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x9d:
|
|
// SBC L
|
|
tempRegister.W=AF.B.B1-HL.B.B0-(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^HL.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x9e:
|
|
// SBC (HL)
|
|
tempValue=gbReadMemory(HL.W);
|
|
tempRegister.W=AF.B.B1-tempValue-(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0x9f:
|
|
// SBC A
|
|
tempRegister.W=AF.B.B1-AF.B.B1-(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^AF.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0xa0:
|
|
// AND B
|
|
AF.B.B1&=BC.B.B1;
|
|
AF.B.B0=H_FLAG|ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xa1:
|
|
// AND C
|
|
AF.B.B1&=BC.B.B0;
|
|
AF.B.B0=H_FLAG|ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xa2:
|
|
// AND_D
|
|
AF.B.B1&=DE.B.B1;
|
|
AF.B.B0=H_FLAG|ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xa3:
|
|
// AND E
|
|
AF.B.B1&=DE.B.B0;
|
|
AF.B.B0=H_FLAG|ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xa4:
|
|
// AND H
|
|
AF.B.B1&=HL.B.B1;
|
|
AF.B.B0=H_FLAG|ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xa5:
|
|
// AND L
|
|
AF.B.B1&=HL.B.B0;
|
|
AF.B.B0=H_FLAG|ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xa6:
|
|
// AND (HL)
|
|
tempValue=gbReadMemory(HL.W);
|
|
AF.B.B1&=tempValue;
|
|
AF.B.B0=H_FLAG|ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xa7:
|
|
// AND A
|
|
AF.B.B1&=AF.B.B1;
|
|
AF.B.B0=H_FLAG|ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xa8:
|
|
// XOR B
|
|
AF.B.B1^=BC.B.B1;
|
|
AF.B.B0=ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xa9:
|
|
// XOR C
|
|
AF.B.B1^=BC.B.B0;
|
|
AF.B.B0=ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xaa:
|
|
// XOR D
|
|
AF.B.B1^=DE.B.B1;
|
|
AF.B.B0=ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xab:
|
|
// XOR E
|
|
AF.B.B1^=DE.B.B0;
|
|
AF.B.B0=ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xac:
|
|
// XOR H
|
|
AF.B.B1^=HL.B.B1;
|
|
AF.B.B0=ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xad:
|
|
// XOR L
|
|
AF.B.B1^=HL.B.B0;
|
|
AF.B.B0=ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xae:
|
|
// XOR (HL)
|
|
tempValue=gbReadMemory(HL.W);
|
|
AF.B.B1^=tempValue;
|
|
AF.B.B0=ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xaf:
|
|
// XOR A
|
|
AF.B.B1=0;
|
|
AF.B.B0=Z_FLAG;
|
|
break;
|
|
case 0xb0:
|
|
// OR B
|
|
AF.B.B1|=BC.B.B1;
|
|
AF.B.B0=ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xb1:
|
|
// OR C
|
|
AF.B.B1|=BC.B.B0;
|
|
AF.B.B0=ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xb2:
|
|
// OR D
|
|
AF.B.B1|=DE.B.B1;
|
|
AF.B.B0=ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xb3:
|
|
// OR E
|
|
AF.B.B1|=DE.B.B0;
|
|
AF.B.B0=ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xb4:
|
|
// OR H
|
|
AF.B.B1|=HL.B.B1;
|
|
AF.B.B0=ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xb5:
|
|
// OR L
|
|
AF.B.B1|=HL.B.B0;
|
|
AF.B.B0=ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xb6:
|
|
// OR (HL)
|
|
tempValue=gbReadMemory(HL.W);
|
|
AF.B.B1|=tempValue;
|
|
AF.B.B0=ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xb7:
|
|
// OR A
|
|
AF.B.B1|=AF.B.B1;
|
|
AF.B.B0=ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xb8:
|
|
// CP B:
|
|
tempRegister.W=AF.B.B1-BC.B.B1;
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^BC.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
break;
|
|
case 0xb9:
|
|
// CP C
|
|
tempRegister.W=AF.B.B1-BC.B.B0;
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^BC.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
break;
|
|
case 0xba:
|
|
// CP D
|
|
tempRegister.W=AF.B.B1-DE.B.B1;
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^DE.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
break;
|
|
case 0xbb:
|
|
// CP E
|
|
tempRegister.W=AF.B.B1-DE.B.B0;
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^DE.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
break;
|
|
case 0xbc:
|
|
// CP H
|
|
tempRegister.W=AF.B.B1-HL.B.B1;
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^HL.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
break;
|
|
case 0xbd:
|
|
// CP L
|
|
tempRegister.W=AF.B.B1-HL.B.B0;
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^HL.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
break;
|
|
case 0xbe:
|
|
// CP (HL)
|
|
tempValue=gbReadMemory(HL.W);
|
|
tempRegister.W=AF.B.B1-tempValue;
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
break;
|
|
case 0xbf:
|
|
// CP A
|
|
AF.B.B0=N_FLAG|Z_FLAG;
|
|
break;
|
|
case 0xc0:
|
|
// RET NZ
|
|
if(!(AF.B.B0&Z_FLAG)) {
|
|
PC.B.B0=gbReadMemory(SP.W++);
|
|
PC.B.B1=gbReadMemory(SP.W++);
|
|
clockTicks += 3;
|
|
}
|
|
break;
|
|
case 0xc1:
|
|
// POP BC
|
|
BC.B.B0=gbReadMemory(SP.W++);
|
|
BC.B.B1=gbReadMemory(SP.W++);
|
|
break;
|
|
case 0xc2:
|
|
// JP NZ,NNNN
|
|
if(AF.B.B0&Z_FLAG)
|
|
PC.W+=2;
|
|
else {
|
|
tempRegister.B.B0=gbReadOpcode(PC.W++);
|
|
tempRegister.B.B1=gbReadOpcode(PC.W);
|
|
PC.W=tempRegister.W;
|
|
clockTicks++;
|
|
}
|
|
break;
|
|
case 0xc3:
|
|
// JP NNNN
|
|
tempRegister.B.B0=gbReadOpcode(PC.W++);
|
|
tempRegister.B.B1=gbReadOpcode(PC.W);
|
|
PC.W=tempRegister.W;
|
|
break;
|
|
case 0xc4:
|
|
// CALL NZ,NNNN
|
|
if(AF.B.B0&Z_FLAG)
|
|
PC.W+=2;
|
|
else {
|
|
tempRegister.B.B0=gbReadOpcode(PC.W++);
|
|
tempRegister.B.B1=gbReadOpcode(PC.W++);
|
|
gbWriteMemory(--SP.W,PC.B.B1);
|
|
gbWriteMemory(--SP.W,PC.B.B0);
|
|
PC.W=tempRegister.W;
|
|
clockTicks += 3;
|
|
}
|
|
break;
|
|
case 0xc5:
|
|
// PUSH BC
|
|
gbWriteMemory(--SP.W,BC.B.B1);
|
|
gbWriteMemory(--SP.W,BC.B.B0);
|
|
break;
|
|
case 0xc6:
|
|
// ADD NN
|
|
tempValue=gbReadOpcode(PC.W++);
|
|
tempRegister.W=AF.B.B1+tempValue;
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^tempValue^tempRegister.B.B0)&0x10 ? H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0xc7:
|
|
// RST 00
|
|
gbWriteMemory(--SP.W,PC.B.B1);
|
|
gbWriteMemory(--SP.W,PC.B.B0);
|
|
PC.W=0x0000;
|
|
break;
|
|
case 0xc8:
|
|
// RET Z
|
|
if(AF.B.B0&Z_FLAG) {
|
|
PC.B.B0=gbReadMemory(SP.W++);
|
|
PC.B.B1=gbReadMemory(SP.W++);
|
|
clockTicks += 3;
|
|
}
|
|
break;
|
|
case 0xc9:
|
|
// RET
|
|
PC.B.B0=gbReadMemory(SP.W++);
|
|
PC.B.B1=gbReadMemory(SP.W++);
|
|
break;
|
|
case 0xca:
|
|
// JP Z,NNNN
|
|
if(AF.B.B0&Z_FLAG) {
|
|
tempRegister.B.B0=gbReadOpcode(PC.W++);
|
|
tempRegister.B.B1=gbReadOpcode(PC.W);
|
|
PC.W=tempRegister.W;
|
|
clockTicks++;
|
|
} else
|
|
PC.W+=2;
|
|
break;
|
|
// CB done outside
|
|
case 0xcc:
|
|
// CALL Z,NNNN
|
|
if(AF.B.B0&Z_FLAG) {
|
|
tempRegister.B.B0=gbReadOpcode(PC.W++);
|
|
tempRegister.B.B1=gbReadOpcode(PC.W++);
|
|
gbWriteMemory(--SP.W,PC.B.B1);
|
|
gbWriteMemory(--SP.W,PC.B.B0);
|
|
PC.W=tempRegister.W;
|
|
clockTicks += 3;
|
|
} else
|
|
PC.W+=2;
|
|
break;
|
|
case 0xcd:
|
|
// CALL NNNN
|
|
tempRegister.B.B0=gbReadOpcode(PC.W++);
|
|
tempRegister.B.B1=gbReadOpcode(PC.W++);
|
|
gbWriteMemory(--SP.W,PC.B.B1);
|
|
gbWriteMemory(--SP.W,PC.B.B0);
|
|
PC.W=tempRegister.W;
|
|
break;
|
|
case 0xce:
|
|
// ADC NN
|
|
tempValue=gbReadOpcode(PC.W++);
|
|
tempRegister.W=AF.B.B1+tempValue+(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0xcf:
|
|
// RST 08
|
|
gbWriteMemory(--SP.W,PC.B.B1);
|
|
gbWriteMemory(--SP.W,PC.B.B0);
|
|
PC.W=0x0008;
|
|
break;
|
|
case 0xd0:
|
|
// RET NC
|
|
if(!(AF.B.B0&C_FLAG)) {
|
|
PC.B.B0=gbReadMemory(SP.W++);
|
|
PC.B.B1=gbReadMemory(SP.W++);
|
|
clockTicks += 3;
|
|
}
|
|
break;
|
|
case 0xd1:
|
|
// POP DE
|
|
DE.B.B0=gbReadMemory(SP.W++);
|
|
DE.B.B1=gbReadMemory(SP.W++);
|
|
break;
|
|
case 0xd2:
|
|
// JP NC,NNNN
|
|
if(AF.B.B0&C_FLAG)
|
|
PC.W+=2;
|
|
else {
|
|
tempRegister.B.B0=gbReadOpcode(PC.W++);
|
|
tempRegister.B.B1=gbReadOpcode(PC.W);
|
|
PC.W=tempRegister.W;
|
|
clockTicks++;
|
|
}
|
|
break;
|
|
// D3 illegal
|
|
case 0xd3:
|
|
PC.W--;
|
|
IFF = 0;
|
|
break;
|
|
case 0xd4:
|
|
// CALL NC,NNNN
|
|
if(AF.B.B0&C_FLAG)
|
|
PC.W+=2;
|
|
else {
|
|
tempRegister.B.B0=gbReadOpcode(PC.W++);
|
|
tempRegister.B.B1=gbReadOpcode(PC.W++);
|
|
gbWriteMemory(--SP.W,PC.B.B1);
|
|
gbWriteMemory(--SP.W,PC.B.B0);
|
|
PC.W=tempRegister.W;
|
|
clockTicks += 3;
|
|
}
|
|
break;
|
|
case 0xd5:
|
|
// PUSH DE
|
|
gbWriteMemory(--SP.W,DE.B.B1);
|
|
gbWriteMemory(--SP.W,DE.B.B0);
|
|
break;
|
|
case 0xd6:
|
|
// SUB NN
|
|
tempValue=gbReadOpcode(PC.W++);
|
|
tempRegister.W=AF.B.B1-tempValue;
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0xd7:
|
|
// RST 10
|
|
gbWriteMemory(--SP.W,PC.B.B1);
|
|
gbWriteMemory(--SP.W,PC.B.B0);
|
|
PC.W=0x0010;
|
|
break;
|
|
case 0xd8:
|
|
// RET C
|
|
if(AF.B.B0&C_FLAG) {
|
|
PC.B.B0=gbReadMemory(SP.W++);
|
|
PC.B.B1=gbReadMemory(SP.W++);
|
|
clockTicks += 3;
|
|
}
|
|
break;
|
|
case 0xd9:
|
|
// RETI
|
|
PC.B.B0=gbReadMemory(SP.W++);
|
|
PC.B.B1=gbReadMemory(SP.W++);
|
|
IFF |= 0x01;
|
|
break;
|
|
case 0xda:
|
|
// JP C,NNNN
|
|
if(AF.B.B0&C_FLAG) {
|
|
tempRegister.B.B0=gbReadOpcode(PC.W++);
|
|
tempRegister.B.B1=gbReadOpcode(PC.W);
|
|
PC.W=tempRegister.W;
|
|
clockTicks++;
|
|
} else
|
|
PC.W+=2;
|
|
break;
|
|
// DB illegal
|
|
case 0xdb:
|
|
PC.W--;
|
|
IFF = 0;
|
|
break;
|
|
case 0xdc:
|
|
// CALL C,NNNN
|
|
if(AF.B.B0&C_FLAG) {
|
|
tempRegister.B.B0=gbReadOpcode(PC.W++);
|
|
tempRegister.B.B1=gbReadOpcode(PC.W++);
|
|
gbWriteMemory(--SP.W,PC.B.B1);
|
|
gbWriteMemory(--SP.W,PC.B.B0);
|
|
PC.W=tempRegister.W;
|
|
clockTicks += 3;
|
|
} else
|
|
PC.W+=2;
|
|
break;
|
|
// DD illegal
|
|
case 0xdd:
|
|
PC.W--;
|
|
IFF = 0;
|
|
break;
|
|
case 0xde:
|
|
// SBC NN
|
|
tempValue=gbReadOpcode(PC.W++);
|
|
tempRegister.W=AF.B.B1-tempValue-(AF.B.B0&C_FLAG ? 1 : 0);
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
AF.B.B1=tempRegister.B.B0;
|
|
break;
|
|
case 0xdf:
|
|
// RST 18
|
|
gbWriteMemory(--SP.W,PC.B.B1);
|
|
gbWriteMemory(--SP.W,PC.B.B0);
|
|
PC.W=0x0018;
|
|
break;
|
|
case 0xe0:
|
|
// LD (FF00+NN),A
|
|
gbWriteMemory(0xff00 + gbReadOpcode(PC.W++),AF.B.B1);
|
|
break;
|
|
case 0xe1:
|
|
// POP HL
|
|
HL.B.B0=gbReadMemory(SP.W++);
|
|
HL.B.B1=gbReadMemory(SP.W++);
|
|
break;
|
|
case 0xe2:
|
|
// LD (FF00+C),A
|
|
gbWriteMemory(0xff00 + BC.B.B0,AF.B.B1);
|
|
break;
|
|
// E3 illegal
|
|
// E4 illegal
|
|
case 0xe3:
|
|
case 0xe4:
|
|
PC.W--;
|
|
IFF = 0;
|
|
break;
|
|
case 0xe5:
|
|
// PUSH HL
|
|
gbWriteMemory(--SP.W,HL.B.B1);
|
|
gbWriteMemory(--SP.W,HL.B.B0);
|
|
break;
|
|
case 0xe6:
|
|
// AND NN
|
|
tempValue=gbReadOpcode(PC.W++);
|
|
AF.B.B1&=tempValue;
|
|
AF.B.B0=H_FLAG|ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xe7:
|
|
// RST 20
|
|
gbWriteMemory(--SP.W,PC.B.B1);
|
|
gbWriteMemory(--SP.W,PC.B.B0);
|
|
PC.W=0x0020;
|
|
break;
|
|
case 0xe8:
|
|
// ADD SP,NN
|
|
offset = (s8)gbReadOpcode(PC.W++);
|
|
|
|
if(offset >= 0) {
|
|
tempRegister.W = SP.W + offset;
|
|
AF.B.B0 = (SP.W > tempRegister.W ? C_FLAG : 0) |
|
|
((SP.W^offset^tempRegister.W)&0x1000? H_FLAG:0);
|
|
SP.W = tempRegister.W;
|
|
} else {
|
|
tempRegister.W = SP.W + offset;
|
|
AF.B.B0 = (SP.W < tempRegister.W ? C_FLAG : 0) |
|
|
((SP.W^offset^tempRegister.W)&0x1000?H_FLAG:0);
|
|
SP.W = tempRegister.W;
|
|
}
|
|
break;
|
|
case 0xe9:
|
|
// LD PC,HL
|
|
PC.W=HL.W;
|
|
break;
|
|
case 0xea:
|
|
// LD (NNNN),A
|
|
tempRegister.B.B0=gbReadOpcode(PC.W++);
|
|
tempRegister.B.B1=gbReadOpcode(PC.W++);
|
|
gbWriteMemory(tempRegister.W,AF.B.B1);
|
|
break;
|
|
// EB illegal
|
|
// EC illegal
|
|
// ED illegal
|
|
case 0xeb:
|
|
case 0xec:
|
|
case 0xed:
|
|
PC.W--;
|
|
IFF = 0;
|
|
break;
|
|
case 0xee:
|
|
// XOR NN
|
|
tempValue=gbReadOpcode(PC.W++);
|
|
AF.B.B1^=tempValue;
|
|
AF.B.B0=ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xef:
|
|
// RST 28
|
|
gbWriteMemory(--SP.W,PC.B.B1);
|
|
gbWriteMemory(--SP.W,PC.B.B0);
|
|
PC.W=0x0028;
|
|
break;
|
|
case 0xf0:
|
|
// LD A,(FF00+NN)
|
|
AF.B.B1 = gbReadMemory(0xff00+gbReadOpcode(PC.W++));
|
|
break;
|
|
case 0xf1:
|
|
// POP AF
|
|
AF.B.B0=gbReadMemory(SP.W++);
|
|
AF.B.B1=gbReadMemory(SP.W++);
|
|
break;
|
|
case 0xf2:
|
|
// LD A,(FF00+C)
|
|
AF.B.B1 = gbReadMemory(0xff00+BC.B.B0);
|
|
break;
|
|
case 0xf3:
|
|
// DI
|
|
// IFF&=0xFE;
|
|
IFF|=0x08;
|
|
break;
|
|
// F4 illegal
|
|
case 0xf4:
|
|
PC.W--;
|
|
IFF = 0;
|
|
break;
|
|
case 0xf5:
|
|
// PUSH AF
|
|
gbWriteMemory(--SP.W,AF.B.B1);
|
|
gbWriteMemory(--SP.W,AF.B.B0);
|
|
break;
|
|
case 0xf6:
|
|
// OR NN
|
|
tempValue=gbReadOpcode(PC.W++);
|
|
AF.B.B1|=tempValue;
|
|
AF.B.B0=ZeroTable[AF.B.B1];
|
|
break;
|
|
case 0xf7:
|
|
// RST 30
|
|
gbWriteMemory(--SP.W,PC.B.B1);
|
|
gbWriteMemory(--SP.W,PC.B.B0);
|
|
PC.W=0x0030;
|
|
break;
|
|
case 0xf8:
|
|
// LD HL,SP+NN
|
|
offset = (s8)gbReadOpcode(PC.W++);
|
|
if(offset >= 0) {
|
|
tempRegister.W = SP.W + offset;
|
|
AF.B.B0 = (SP.W > tempRegister.W ? C_FLAG : 0) |
|
|
((SP.W^offset^tempRegister.W)&0x1000? H_FLAG:0);
|
|
HL.W = tempRegister.W;
|
|
} else {
|
|
tempRegister.W = SP.W + offset;
|
|
AF.B.B0 = (SP.W < tempRegister.W ? C_FLAG : 0) |
|
|
((SP.W^offset^tempRegister.W)&0x1000?H_FLAG:0);
|
|
HL.W = tempRegister.W;
|
|
}
|
|
break;
|
|
case 0xf9:
|
|
// LD SP,HL
|
|
SP.W=HL.W;
|
|
break;
|
|
case 0xfa:
|
|
// LD A,(NNNN)
|
|
tempRegister.B.B0=gbReadOpcode(PC.W++);
|
|
tempRegister.B.B1=gbReadOpcode(PC.W++);
|
|
AF.B.B1=gbReadMemory(tempRegister.W);
|
|
break;
|
|
case 0xfb:
|
|
// EI
|
|
if (!(IFF & 0x30))
|
|
// If an EI is executed right before HALT,
|
|
// the interrupts are triggered before the Halt state !!
|
|
// Fix Torpedo Range Intro.
|
|
// IFF |= 0x10 : 1 ticks before the EI enables the interrupts
|
|
// IFF |= 0x40 : marks that an EI is being executed.
|
|
IFF|=0x50;
|
|
break;
|
|
// FC illegal (FC = breakpoint)
|
|
case 0xfc:
|
|
breakpoint = true;
|
|
break;
|
|
// FD illegal
|
|
case 0xfd:
|
|
PC.W--;
|
|
IFF = 0;
|
|
break;
|
|
case 0xfe:
|
|
// CP NN
|
|
tempValue=gbReadOpcode(PC.W++);
|
|
tempRegister.W=AF.B.B1-tempValue;
|
|
AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]|
|
|
((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0);
|
|
break;
|
|
case 0xff:
|
|
// RST 38
|
|
gbWriteMemory(--SP.W,PC.B.B1);
|
|
gbWriteMemory(--SP.W,PC.B.B0);
|
|
PC.W=0x0038;
|
|
break;
|
|
default:
|
|
if (gbSystemMessage == false)
|
|
{
|
|
systemMessage(0, N_("Unknown opcode %02x at %04x"),
|
|
gbReadOpcode(PC.W-1),PC.W-1);
|
|
gbSystemMessage =true;
|
|
}
|
|
return;
|