diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/Dev Documentation/GBCPUman.pdf b/Dev Documentation/GBCPUman.pdf new file mode 100644 index 0000000..7cf38e1 Binary files /dev/null and b/Dev Documentation/GBCPUman.pdf differ diff --git a/Dev Documentation/GameBoy Opcodes Summary.htm b/Dev Documentation/GameBoy Opcodes Summary.htm new file mode 100644 index 0000000..c5ffde3 --- /dev/null +++ b/Dev Documentation/GameBoy Opcodes Summary.htm @@ -0,0 +1,355 @@ + +GameBoy Opcodes Summary +

GameBoy Opcode Summary

+

The GameBoy has instructions & registers similiar to the 8080, 8085, & +Z80 microprocessors. The internal 8-bit registers are A, B, C, D, E, F, H, & +L. Theses registers may be used in pairs for 16-bit operations as AF, BC, DE, & +HL. The two remaining 16-bit registers are the program counter (PC) and the +stack pointer (SP).

+

The F register holds the cpu flags. The operation of these flags is +identical to their Z80 relative. The lower four bits of this register always +read zero even if written with a one.

+ + +
Flag +Register
76543210
ZNHC0000
+

The GameBoy CPU is based on a subset of the Z80 microprocessor. A summary of +these commands is given below.

+ + +
MnemonicSymbolic +OperationCommentsCPU ClocksFlags - Z,N,H,C
+

8-Bit Loads

+ + +
LD r,sr + ss=r,n,(HL)r=4, +n=8, (HL)=8
LD d,rd + rd=r,(HL)r=4, (HL)=8
LD d,nd + nr=8, (HL)=12
LD +A,(ss)A + (ss)ss=BC,DE,HL,nn[BC,DE,HL]=8, +nn=16
LD (dd),A(dd) + Add=BC,DE,HL,nn
LD +A,(C)A + ($FF00+C)-8
LD (C),A($FF00+C) + A8
LDD A,(HL)A + (HL), HL + HL - 18
LDD (HL),A(HL) + A, HL + HL - 18
LDI A,(HL)A + (HL), HL + HL + 18
LDI (HL),A(HL) + A, HL + HL + 18
LDH (n),A($FF00+n) + A12
LDH A,(n)A + ($FF00+n)12
+

16-Bit Loads

+ + + +
LD dd,nndd + nndd=BC,DE,HL,SP12----
LD (nn),SP(nn) + SP +-20
LD SP,HL +SP + HL8
LD HL,(SP+e)HL + (SP+e)1200**
PUSH ss + (SP-1) +ssh, (SP-2) +ssl, SPSP-2 +ss=BC,DE,HL,AF16----
POP dd +ddl + (SP), ddh + (SP+1), SPSP+2 +dd=BC,DE,HL,AF +12
+

8-Bit ALU

+ + + + + + + +
ADD A,sA + A + s +CY is the carry flag. s=r,n,(HL)r=4, n=8, (HL)=8*0**
ADC A,sA + A + s + CY +
SUB sA + A - s +*1**
SBC A,sA + A - s - CY +
AND sA + A + s*010
OR sA + A + s +*000
XOR sA + A + s +
CP sA - s*1**
INC ss + s + 1 +s=r,(HL)r=4, (HL)=12*0*-
DEC ss + s - 1 +*1*-
+

16-Bit Arithmetic

+ + +
ADD HL,ssHL + HL + ss +ss=BC,DE,HL,SP8-0**
ADD SP,eSP + SP + e +1600**
INC ssss + ss + 1 +8----
DEC +ssss + ss - 1 +8
+

Miscellaneous

+ + + + + + +
SWAP sSwap nibbles. s=r,(HL)r=8, (HL)=16*000
DAAConverts +A into packed BCD.-4*-0*
CPLA + /A4-11-
CCF + CY /CY +CY is the carry flag.4-00*
SCFCY + 14-001
NOPNo operation.-4----
HALTHalt CPU until an interrupt occurs.4
STOP +Halt CPU.4
DIDisable Interrupts.4
EIEnable Interrupts. +4
+

Rotates & Shifts

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RLCA4000*
RLA
RRCA
RRA
RLC ss=A,r,(HL)r=8,(HL)=16*00*
RL s
RRC s
RR s
SLA ss=r,(HL)r=8, +(HL)=16
SRA s
SRL s
+

Bit Opcodes

+ + + +
BIT b,sZ + /sbZ is zero flag. s=r,(HL)r=8, +(HL)=12*01-
SET b,ssb + 1r=8, (HL)=16----
RES b,ssb + 0
+

Jumps

+ + + + + +
JP nnPC + nn-16
JP cc,nnIf cc is true, PC + nn, else +continue.If cc is true, 16 else 12.
JP (HL)PC + HL4
JR ePC + PC + e +12
JR cc,eif cc is true, PC + PC + e, +else continue.If cc is true, 12 else 8.
+

Calls

+ + +
CALL nn(SP-1) + PCh, +(SP-2) +PCl, PC +nn, SPSP-2 +-24
CALL cc,nnIf condition cc is false continue, else same as CALL nn.If cc is true, 24 else 12.
+

Restarts

+ + +
RST f(SP-1) + PCh, +(SP-2) +PCl, PCh +0, PCl f, +SPSP-2 +- +16
+

Returns

+ + + +
RETpcl + (SP), pch + (SP+1), SPSP+2 +-16
RET ccIf cc is true, RET else continue.If cc is +true, 20 else 8.
RETIReturn +then enable interrupts.16
+

Terminology

+ + + +
-Flag is not +affected by this operation.
*Flag is affected according to result of operation.
bA bit number in any 8-bit register or +memory location.
CCarry +flag.
cc +Flag condition code: C,NC,NZ,Z
dAny 8-bit destination register or memory +location.
ddAny 16-bit +destination register or memory location.
e8-bit signed 2's complement displacement.
f8 special call locations in page zero. +
HHalf-carry flag.
NSubtraction flag.
NCNot carry flag
NZNot zero flag.
nAny 8-bit binary number.
nnAny 16-bit binary number.
rAny 8-bit register. (A,B,C,D,E,H, or L)
sAny 8-bit source register or +memory location.
sbA bit +in a specific 8-bit register or memory location.
ssAny 16-bit source register or memory location.
ZZero Flag.
+ diff --git a/Dev Documentation/Gameboy (LR35902) OPCODES.htm b/Dev Documentation/Gameboy (LR35902) OPCODES.htm new file mode 100644 index 0000000..eacfc22 --- /dev/null +++ b/Dev Documentation/Gameboy (LR35902) OPCODES.htm @@ -0,0 +1,218 @@ + + + + + Gameboy (LR35902) OPCODES + + + + + +Gameboy CPU (LR35902) instruction set +

+ + + + + + + + + + + + + + + + + + + +
  x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xA  xB  xC  xD  xE  xF 
 0x NOP
1  4
- - - -
LD BC,d16
3  12
- - - -
LD (BC),A
1  8
- - - -
INC BC
1  8
- - - -
INC B
1  4
Z 0 H -
DEC B
1  4
Z 1 H -
LD B,d8
2  8
- - - -
RLCA
1  4
0 0 0 C
LD (a16),SP
3  20
- - - -
ADD HL,BC
1  8
- 0 H C
LD A,(BC)
1  8
- - - -
DEC BC
1  8
- - - -
INC C
1  4
Z 0 H -
DEC C
1  4
Z 1 H -
LD C,d8
2  8
- - - -
RRCA
1  4
0 0 0 C
 1x STOP 0
2  4
- - - -
LD DE,d16
3  12
- - - -
LD (DE),A
1  8
- - - -
INC DE
1  8
- - - -
INC D
1  4
Z 0 H -
DEC D
1  4
Z 1 H -
LD D,d8
2  8
- - - -
RLA
1  4
0 0 0 C
JR r8
2  12
- - - -
ADD HL,DE
1  8
- 0 H C
LD A,(DE)
1  8
- - - -
DEC DE
1  8
- - - -
INC E
1  4
Z 0 H -
DEC E
1  4
Z 1 H -
LD E,d8
2  8
- - - -
RRA
1  4
0 0 0 C
 2x JR NZ,r8
2  12/8
- - - -
LD HL,d16
3  12
- - - -
LD (HL+),A
1  8
- - - -
INC HL
1  8
- - - -
INC H
1  4
Z 0 H -
DEC H
1  4
Z 1 H -
LD H,d8
2  8
- - - -
DAA
1  4
Z - 0 C
JR Z,r8
2  12/8
- - - -
ADD HL,HL
1  8
- 0 H C
LD A,(HL+)
1  8
- - - -
DEC HL
1  8
- - - -
INC L
1  4
Z 0 H -
DEC L
1  4
Z 1 H -
LD L,d8
2  8
- - - -
CPL
1  4
- 1 1 -
 3x JR NC,r8
2  12/8
- - - -
LD SP,d16
3  12
- - - -
LD (HL-),A
1  8
- - - -
INC SP
1  8
- - - -
INC (HL)
1  12
Z 0 H -
DEC (HL)
1  12
Z 1 H -
LD (HL),d8
2  12
- - - -
SCF
1  4
- 0 0 1
JR C,r8
2  12/8
- - - -
ADD HL,SP
1  8
- 0 H C
LD A,(HL-)
1  8
- - - -
DEC SP
1  8
- - - -
INC A
1  4
Z 0 H -
DEC A
1  4
Z 1 H -
LD A,d8
2  8
- - - -
CCF
1  4
- 0 0 C
 4x LD B,B
1  4
- - - -
LD B,C
1  4
- - - -
LD B,D
1  4
- - - -
LD B,E
1  4
- - - -
LD B,H
1  4
- - - -
LD B,L
1  4
- - - -
LD B,(HL)
1  8
- - - -
LD B,A
1  4
- - - -
LD C,B
1  4
- - - -
LD C,C
1  4
- - - -
LD C,D
1  4
- - - -
LD C,E
1  4
- - - -
LD C,H
1  4
- - - -
LD C,L
1  4
- - - -
LD C,(HL)
1  8
- - - -
LD C,A
1  4
- - - -
 5x LD D,B
1  4
- - - -
LD D,C
1  4
- - - -
LD D,D
1  4
- - - -
LD D,E
1  4
- - - -
LD D,H
1  4
- - - -
LD D,L
1  4
- - - -
LD D,(HL)
1  8
- - - -
LD D,A
1  4
- - - -
LD E,B
1  4
- - - -
LD E,C
1  4
- - - -
LD E,D
1  4
- - - -
LD E,E
1  4
- - - -
LD E,H
1  4
- - - -
LD E,L
1  4
- - - -
LD E,(HL)
1  8
- - - -
LD E,A
1  4
- - - -
 6x LD H,B
1  4
- - - -
LD H,C
1  4
- - - -
LD H,D
1  4
- - - -
LD H,E
1  4
- - - -
LD H,H
1  4
- - - -
LD H,L
1  4
- - - -
LD H,(HL)
1  8
- - - -
LD H,A
1  4
- - - -
LD L,B
1  4
- - - -
LD L,C
1  4
- - - -
LD L,D
1  4
- - - -
LD L,E
1  4
- - - -
LD L,H
1  4
- - - -
LD L,L
1  4
- - - -
LD L,(HL)
1  8
- - - -
LD L,A
1  4
- - - -
 7x LD (HL),B
1  8
- - - -
LD (HL),C
1  8
- - - -
LD (HL),D
1  8
- - - -
LD (HL),E
1  8
- - - -
LD (HL),H
1  8
- - - -
LD (HL),L
1  8
- - - -
HALT
1  4
- - - -
LD (HL),A
1  8
- - - -
LD A,B
1  4
- - - -
LD A,C
1  4
- - - -
LD A,D
1  4
- - - -
LD A,E
1  4
- - - -
LD A,H
1  4
- - - -
LD A,L
1  4
- - - -
LD A,(HL)
1  8
- - - -
LD A,A
1  4
- - - -
 8x ADD A,B
1  4
Z 0 H C
ADD A,C
1  4
Z 0 H C
ADD A,D
1  4
Z 0 H C
ADD A,E
1  4
Z 0 H C
ADD A,H
1  4
Z 0 H C
ADD A,L
1  4
Z 0 H C
ADD A,(HL)
1  8
Z 0 H C
ADD A,A
1  4
Z 0 H C
ADC A,B
1  4
Z 0 H C
ADC A,C
1  4
Z 0 H C
ADC A,D
1  4
Z 0 H C
ADC A,E
1  4
Z 0 H C
ADC A,H
1  4
Z 0 H C
ADC A,L
1  4
Z 0 H C
ADC A,(HL)
1  8
Z 0 H C
ADC A,A
1  4
Z 0 H C
 9x SUB B
1  4
Z 1 H C
SUB C
1  4
Z 1 H C
SUB D
1  4
Z 1 H C
SUB E
1  4
Z 1 H C
SUB H
1  4
Z 1 H C
SUB L
1  4
Z 1 H C
SUB (HL)
1  8
Z 1 H C
SUB A
1  4
Z 1 H C
SBC A,B
1  4
Z 1 H C
SBC A,C
1  4
Z 1 H C
SBC A,D
1  4
Z 1 H C
SBC A,E
1  4
Z 1 H C
SBC A,H
1  4
Z 1 H C
SBC A,L
1  4
Z 1 H C
SBC A,(HL)
1  8
Z 1 H C
SBC A,A
1  4
Z 1 H C
 Ax AND B
1  4
Z 0 1 0
AND C
1  4
Z 0 1 0
AND D
1  4
Z 0 1 0
AND E
1  4
Z 0 1 0
AND H
1  4
Z 0 1 0
AND L
1  4
Z 0 1 0
AND (HL)
1  8
Z 0 1 0
AND A
1  4
Z 0 1 0
XOR B
1  4
Z 0 0 0
XOR C
1  4
Z 0 0 0
XOR D
1  4
Z 0 0 0
XOR E
1  4
Z 0 0 0
XOR H
1  4
Z 0 0 0
XOR L
1  4
Z 0 0 0
XOR (HL)
1  8
Z 0 0 0
XOR A
1  4
Z 0 0 0
 Bx OR B
1  4
Z 0 0 0
OR C
1  4
Z 0 0 0
OR D
1  4
Z 0 0 0
OR E
1  4
Z 0 0 0
OR H
1  4
Z 0 0 0
OR L
1  4
Z 0 0 0
OR (HL)
1  8
Z 0 0 0
OR A
1  4
Z 0 0 0
CP B
1  4
Z 1 H C
CP C
1  4
Z 1 H C
CP D
1  4
Z 1 H C
CP E
1  4
Z 1 H C
CP H
1  4
Z 1 H C
CP L
1  4
Z 1 H C
CP (HL)
1  8
Z 1 H C
CP A
1  4
Z 1 H C
 Cx RET NZ
1  20/8
- - - -
POP BC
1  12
- - - -
JP NZ,a16
3  16/12
- - - -
JP a16
3  16
- - - -
CALL NZ,a16
3  24/12
- - - -
PUSH BC
1  16
- - - -
ADD A,d8
2  8
Z 0 H C
RST 00H
1  16
- - - -
RET Z
1  20/8
- - - -
RET
1  16
- - - -
JP Z,a16
3  16/12
- - - -
PREFIX CB
1  4
- - - -
CALL Z,a16
3  24/12
- - - -
CALL a16
3  24
- - - -
ADC A,d8
2  8
Z 0 H C
RST 08H
1  16
- - - -
 Dx RET NC
1  20/8
- - - -
POP DE
1  12
- - - -
JP NC,a16
3  16/12
- - - -
 CALL NC,a16
3  24/12
- - - -
PUSH DE
1  16
- - - -
SUB d8
2  8
Z 1 H C
RST 10H
1  16
- - - -
RET C
1  20/8
- - - -
RETI
1  16
- - - -
JP C,a16
3  16/12
- - - -
 CALL C,a16
3  24/12
- - - -
 SBC A,d8
2  8
Z 1 H C
RST 18H
1  16
- - - -
 Ex LDH (a8),A
2  12
- - - -
POP HL
1  12
- - - -
LD (C),A
2  8
- - - -
  PUSH HL
1  16
- - - -
AND d8
2  8
Z 0 1 0
RST 20H
1  16
- - - -
ADD SP,r8
2  16
0 0 H C
JP (HL)
1  4
- - - -
LD (a16),A
3  16
- - - -
   XOR d8
2  8
Z 0 0 0
RST 28H
1  16
- - - -
 Fx LDH A,(a8)
2  12
- - - -
POP AF
1  12
Z N H C
LD A,(C)
2  8
- - - -
DI
1  4
- - - -
 PUSH AF
1  16
- - - -
OR d8
2  8
Z 0 0 0
RST 30H
1  16
- - - -
LD HL,SP+r8
2  12
0 0 H C
LD SP,HL
1  8
- - - -
LD A,(a16)
3  16
- - - -
EI
1  4
- - - -
  CP d8
2  8
Z 1 H C
RST 38H
1  16
- - - -
+

+ +Prefix CB +

+ + + + + + + + + + + + + + + + + + + + +
  x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xA  xB  xC  xD  xE  xF 
 0x RLC B
2  8
Z 0 0 C
RLC C
2  8
Z 0 0 C
RLC D
2  8
Z 0 0 C
RLC E
2  8
Z 0 0 C
RLC H
2  8
Z 0 0 C
RLC L
2  8
Z 0 0 C
RLC (HL)
2  16
Z 0 0 C
RLC A
2  8
Z 0 0 C
RRC B
2  8
Z 0 0 C
RRC C
2  8
Z 0 0 C
RRC D
2  8
Z 0 0 C
RRC E
2  8
Z 0 0 C
RRC H
2  8
Z 0 0 C
RRC L
2  8
Z 0 0 C
RRC (HL)
2  16
Z 0 0 C
RRC A
2  8
Z 0 0 C
 1x RL B
2  8
Z 0 0 C
RL C
2  8
Z 0 0 C
RL D
2  8
Z 0 0 C
RL E
2  8
Z 0 0 C
RL H
2  8
Z 0 0 C
RL L
2  8
Z 0 0 C
RL (HL)
2  16
Z 0 0 C
RL A
2  8
Z 0 0 C
RR B
2  8
Z 0 0 C
RR C
2  8
Z 0 0 C
RR D
2  8
Z 0 0 C
RR E
2  8
Z 0 0 C
RR H
2  8
Z 0 0 C
RR L
2  8
Z 0 0 C
RR (HL)
2  16
Z 0 0 C
RR A
2  8
Z 0 0 C
 2x SLA B
2  8
Z 0 0 C
SLA C
2  8
Z 0 0 C
SLA D
2  8
Z 0 0 C
SLA E
2  8
Z 0 0 C
SLA H
2  8
Z 0 0 C
SLA L
2  8
Z 0 0 C
SLA (HL)
2  16
Z 0 0 C
SLA A
2  8
Z 0 0 C
SRA B
2  8
Z 0 0 0
SRA C
2  8
Z 0 0 0
SRA D
2  8
Z 0 0 0
SRA E
2  8
Z 0 0 0
SRA H
2  8
Z 0 0 0
SRA L
2  8
Z 0 0 0
SRA (HL)
2  16
Z 0 0 0
SRA A
2  8
Z 0 0 0
 3x SWAP B
2  8
Z 0 0 0
SWAP C
2  8
Z 0 0 0
SWAP D
2  8
Z 0 0 0
SWAP E
2  8
Z 0 0 0
SWAP H
2  8
Z 0 0 0
SWAP L
2  8
Z 0 0 0
SWAP (HL)
2  16
Z 0 0 0
SWAP A
2  8
Z 0 0 0
SRL B
2  8
Z 0 0 C
SRL C
2  8
Z 0 0 C
SRL D
2  8
Z 0 0 C
SRL E
2  8
Z 0 0 C
SRL H
2  8
Z 0 0 C
SRL L
2  8
Z 0 0 C
SRL (HL)
2  16
Z 0 0 C
SRL A
2  8
Z 0 0 C
 4x BIT 0,B
2  8
Z 0 1 -
BIT 0,C
2  8
Z 0 1 -
BIT 0,D
2  8
Z 0 1 -
BIT 0,E
2  8
Z 0 1 -
BIT 0,H
2  8
Z 0 1 -
BIT 0,L
2  8
Z 0 1 -
BIT 0,(HL)
2  16
Z 0 1 -
BIT 0,A
2  8
Z 0 1 -
BIT 1,B
2  8
Z 0 1 -
BIT 1,C
2  8
Z 0 1 -
BIT 1,D
2  8
Z 0 1 -
BIT 1,E
2  8
Z 0 1 -
BIT 1,H
2  8
Z 0 1 -
BIT 1,L
2  8
Z 0 1 -
BIT 1,(HL)
2  16
Z 0 1 -
BIT 1,A
2  8
Z 0 1 -
 5x BIT 2,B
2  8
Z 0 1 -
BIT 2,C
2  8
Z 0 1 -
BIT 2,D
2  8
Z 0 1 -
BIT 2,E
2  8
Z 0 1 -
BIT 2,H
2  8
Z 0 1 -
BIT 2,L
2  8
Z 0 1 -
BIT 2,(HL)
2  16
Z 0 1 -
BIT 2,A
2  8
Z 0 1 -
BIT 3,B
2  8
Z 0 1 -
BIT 3,C
2  8
Z 0 1 -
BIT 3,D
2  8
Z 0 1 -
BIT 3,E
2  8
Z 0 1 -
BIT 3,H
2  8
Z 0 1 -
BIT 3,L
2  8
Z 0 1 -
BIT 3,(HL)
2  16
Z 0 1 -
BIT 3,A
2  8
Z 0 1 -
 6x BIT 4,B
2  8
Z 0 1 -
BIT 4,C
2  8
Z 0 1 -
BIT 4,D
2  8
Z 0 1 -
BIT 4,E
2  8
Z 0 1 -
BIT 4,H
2  8
Z 0 1 -
BIT 4,L
2  8
Z 0 1 -
BIT 4,(HL)
2  16
Z 0 1 -
BIT 4,A
2  8
Z 0 1 -
BIT 5,B
2  8
Z 0 1 -
BIT 5,C
2  8
Z 0 1 -
BIT 5,D
2  8
Z 0 1 -
BIT 5,E
2  8
Z 0 1 -
BIT 5,H
2  8
Z 0 1 -
BIT 5,L
2  8
Z 0 1 -
BIT 5,(HL)
2  16
Z 0 1 -
BIT 5,A
2  8
Z 0 1 -
 7x BIT 6,B
2  8
Z 0 1 -
BIT 6,C
2  8
Z 0 1 -
BIT 6,D
2  8
Z 0 1 -
BIT 6,E
2  8
Z 0 1 -
BIT 6,H
2  8
Z 0 1 -
BIT 6,L
2  8
Z 0 1 -
BIT 6,(HL)
2  16
Z 0 1 -
BIT 6,A
2  8
Z 0 1 -
BIT 7,B
2  8
Z 0 1 -
BIT 7,C
2  8
Z 0 1 -
BIT 7,D
2  8
Z 0 1 -
BIT 7,E
2  8
Z 0 1 -
BIT 7,H
2  8
Z 0 1 -
BIT 7,L
2  8
Z 0 1 -
BIT 7,(HL)
2  16
Z 0 1 -
BIT 7,A
2  8
Z 0 1 -
 8x RES 0,B
2  8
- - - -
RES 0,C
2  8
- - - -
RES 0,D
2  8
- - - -
RES 0,E
2  8
- - - -
RES 0,H
2  8
- - - -
RES 0,L
2  8
- - - -
RES 0,(HL)
2  16
- - - -
RES 0,A
2  8
- - - -
RES 1,B
2  8
- - - -
RES 1,C
2  8
- - - -
RES 1,D
2  8
- - - -
RES 1,E
2  8
- - - -
RES 1,H
2  8
- - - -
RES 1,L
2  8
- - - -
RES 1,(HL)
2  16
- - - -
RES 1,A
2  8
- - - -
 9x RES 2,B
2  8
- - - -
RES 2,C
2  8
- - - -
RES 2,D
2  8
- - - -
RES 2,E
2  8
- - - -
RES 2,H
2  8
- - - -
RES 2,L
2  8
- - - -
RES 2,(HL)
2  16
- - - -
RES 2,A
2  8
- - - -
RES 3,B
2  8
- - - -
RES 3,C
2  8
- - - -
RES 3,D
2  8
- - - -
RES 3,E
2  8
- - - -
RES 3,H
2  8
- - - -
RES 3,L
2  8
- - - -
RES 3,(HL)
2  16
- - - -
RES 3,A
2  8
- - - -
 Ax RES 4,B
2  8
- - - -
RES 4,C
2  8
- - - -
RES 4,D
2  8
- - - -
RES 4,E
2  8
- - - -
RES 4,H
2  8
- - - -
RES 4,L
2  8
- - - -
RES 4,(HL)
2  16
- - - -
RES 4,A
2  8
- - - -
RES 5,B
2  8
- - - -
RES 5,C
2  8
- - - -
RES 5,D
2  8
- - - -
RES 5,E
2  8
- - - -
RES 5,H
2  8
- - - -
RES 5,L
2  8
- - - -
RES 5,(HL)
2  16
- - - -
RES 5,A
2  8
- - - -
 Bx RES 6,B
2  8
- - - -
RES 6,C
2  8
- - - -
RES 6,D
2  8
- - - -
RES 6,E
2  8
- - - -
RES 6,H
2  8
- - - -
RES 6,L
2  8
- - - -
RES 6,(HL)
2  16
- - - -
RES 6,A
2  8
- - - -
RES 7,B
2  8
- - - -
RES 7,C
2  8
- - - -
RES 7,D
2  8
- - - -
RES 7,E
2  8
- - - -
RES 7,H
2  8
- - - -
RES 7,L
2  8
- - - -
RES 7,(HL)
2  16
- - - -
RES 7,A
2  8
- - - -
 Cx SET 0,B
2  8
- - - -
SET 0,C
2  8
- - - -
SET 0,D
2  8
- - - -
SET 0,E
2  8
- - - -
SET 0,H
2  8
- - - -
SET 0,L
2  8
- - - -
SET 0,(HL)
2  16
- - - -
SET 0,A
2  8
- - - -
SET 1,B
2  8
- - - -
SET 1,C
2  8
- - - -
SET 1,D
2  8
- - - -
SET 1,E
2  8
- - - -
SET 1,H
2  8
- - - -
SET 1,L
2  8
- - - -
SET 1,(HL)
2  16
- - - -
SET 1,A
2  8
- - - -
 Dx SET 2,B
2  8
- - - -
SET 2,C
2  8
- - - -
SET 2,D
2  8
- - - -
SET 2,E
2  8
- - - -
SET 2,H
2  8
- - - -
SET 2,L
2  8
- - - -
SET 2,(HL)
2  16
- - - -
SET 2,A
2  8
- - - -
SET 3,B
2  8
- - - -
SET 3,C
2  8
- - - -
SET 3,D
2  8
- - - -
SET 3,E
2  8
- - - -
SET 3,H
2  8
- - - -
SET 3,L
2  8
- - - -
SET 3,(HL)
2  16
- - - -
SET 3,A
2  8
- - - -
 Ex SET 4,B
2  8
- - - -
SET 4,C
2  8
- - - -
SET 4,D
2  8
- - - -
SET 4,E
2  8
- - - -
SET 4,H
2  8
- - - -
SET 4,L
2  8
- - - -
SET 4,(HL)
2  16
- - - -
SET 4,A
2  8
- - - -
SET 5,B
2  8
- - - -
SET 5,C
2  8
- - - -
SET 5,D
2  8
- - - -
SET 5,E
2  8
- - - -
SET 5,H
2  8
- - - -
SET 5,L
2  8
- - - -
SET 5,(HL)
2  16
- - - -
SET 5,A
2  8
- - - -
 Fx SET 6,B
2  8
- - - -
SET 6,C
2  8
- - - -
SET 6,D
2  8
- - - -
SET 6,E
2  8
- - - -
SET 6,H
2  8
- - - -
SET 6,L
2  8
- - - -
SET 6,(HL)
2  16
- - - -
SET 6,A
2  8
- - - -
SET 7,B
2  8
- - - -
SET 7,C
2  8
- - - -
SET 7,D
2  8
- - - -
SET 7,E
2  8
- - - -
SET 7,H
2  8
- - - -
SET 7,L
2  8
- - - -
SET 7,(HL)
2  16
- - - -
SET 7,A
2  8
- - - -
+

+ + + + + + + + + +
+ + + + + + + + +
       Misc/control instructions
       Jumps/calls
       8bit load/store/move instructions
       16bit load/store/move instructions
       8bit arithmetic/logical instructions
       16bit arithmetic/logical instructions
       8bit rotations/shifts and bit instructions
+
  + + + + + + + + +
 
Length in bytes →
 
 INS reg
2  8
Z N H C
 ← Instruction mnemonic
← Duration in cycles
← Flags affected
+
  + Duration of conditional calls and returns is different when action is taken or not. This is indicated by two numbers separated by "/". The higher number (on the left side of "/") means duration of instruction when action is taken, the lower number (on the right side of "/") means duration of instruction when action is not taken. +
+
+ + +
+Instruction STOP has according to manuals opcode 10 00 and thus is 2 bytes long. Anyhow it seems there is no reason for it so some assemblers code it simply as one byte instruction 10.
+Flags affected are always shown in Z H N C order. If flag is marked by "0" it means it is reset after the instruction. If it is marked by "1" it is set. If it is marked by "-" it is not changed. If it is marked by "Z", "N", "H" or "C" corresponding flag is affected as expected by its function.
+
+ +d8  means immediate 8 bit data
+d16 means immediate 16 bit data
+a8  means 8 bit unsigned data, which are added to $FF00 in certain instructions (replacement for missing IN and OUT instructions)
+a16 means 16 bit address
+r8  means 8 bit signed data, which are added to program counter
+
+LD A,(C) has alternative mnemonic LD A,($FF00+C)
+LD C,(A) has alternative mnemonic LD ($FF00+C),A
+LDH A,(a8) has alternative mnemonic LD A,($FF00+a8)
+LDH (a8),A has alternative mnemonic LD ($FF00+a8),A
+LD A,(HL+) has alternative mnemonic LD A,(HLI) or LDI A,(HL)
+LD (HL+),A has alternative mnemonic LD (HLI),A or LDI (HL),A
+LD A,(HL-) has alternative mnemonic LD A,(HLD) or LDD A,(HL)
+LD (HL-),A has alternative mnemonic LD (HLD),A or LDD (HL),A
+LD HL,SP+r8 has alternative mnemonic LDHL SP,r8 +
+

+Registers +

+ + + + + + +
+ + + + + + +
15  . . .  87  . . .  0
A (accumulator)F (flags)
BC
DE
HL
+
+ + + + +
15  . . .  0
SP (stack pointer)
PC (program counter)
+
  +Flag register (F) bits:

+ + + + + + + + + + + + + + + + + + + + + +
76543210
ZNHC0000
+
+Z - Zero Flag
+N - Subtract Flag
+H - Half Carry Flag
+C - Carry Flag
+0 - Not used, always zero
+
+ + + + + diff --git a/Dev Documentation/Pandocs.htm b/Dev Documentation/Pandocs.htm new file mode 100644 index 0000000..1112377 --- /dev/null +++ b/Dev Documentation/Pandocs.htm @@ -0,0 +1,2899 @@ + + Specifications + + +
 Pan Docs

+Overview
+
About the Pan Docs
+Game Boy Technical Data
+Memory Map
+
+I/O Ports
+
Video Display
+Sound Controller
+Joypad Input
+Serial Data Transfer (Link Cable)
+Timer and Divider Registers
+Interrupts
+CGB Registers
+SGB Functions
+
+CPU Specifications
+
CPU Registers and Flags
+CPU Instruction Set
+CPU Comparision with Z80
+
+Cartridges
+
The Cartridge Header
+Memory Bank Controllers
+Gamegenie/Shark Cheats
+
+Other
+
Power Up Sequence
+Reducing Power Consumption
+Sprite RAM Bug
+External Connectors
+
+
+
 About the Pan Docs

+
 =================================================================
+       Everything You Always Wanted To Know About GAMEBOY *
+ =================================================================
+

+
                     * but were afraid to ask
+

+
        Pan of -ATX- Document Updated by contributions from:
+     Marat Fayzullin, Pascal Felber, Paul Robson, Martin Korth
+             CPU, SGB, CGB, AUX specs by Martin Korth
+

+
                  Last updated 10/2001 by nocash
+               Previously updated 4-Mar-98 by kOOPa
+

+Forward
+
The following was typed up for informational purposes regarding the +inner workings on the hand-held game machine known as GameBoy, +manufactured and designed by Nintendo Co., LTD. This info is presented +to inform a user on how their Game Boy works and what makes it "tick". +GameBoy is copyrighted by Nintendo Co., LTD. Any reference to +copyrighted material is not presented for monetary gain, but for +educational purposes and higher learning.
+
+Available Document Formats
+
The present version of this document is available in Text and Html format:
+
  http://www.work.de/nocash/pandocs.txt
+  http://www.work.de/nocash/pandocs.htm
+
Also, a copy of this document is included in the manual of newer +versions of the no$gmb debugger, because of recent piracy attacks (many +thanks and best wishes go to hell) I have currently no intention to +publish any such or further no$gmb updates though.
+
+
+
 Game Boy Technical Data

+
  CPU          - 8-bit (Similar to the Z80 processor)
+  Clock Speed  - 4.194304MHz (4.295454MHz for SGB, max. 8.4MHz for CGB)
+  Work RAM     - 8K Byte (32K Byte for CGB)
+  Video RAM    - 8K Byte (16K Byte for CGB)
+  Screen Size  - 2.6"
+  Resolution   - 160x144 (20x18 tiles)
+  Max sprites  - Max 40 per screen, 10 per line
+  Sprite sizes - 8x8 or 8x16
+  Palettes     - 1x4 BG, 2x3 OBJ (for CGB: 8x4 BG, 8x3 OBJ)
+  Colors       - 4 grayshades (32768 colors for CGB)
+  Horiz Sync   - 9198 KHz (9420 KHz for SGB)
+  Vert Sync    - 59.73 Hz (61.17 Hz for SGB)
+  Sound        - 4 channels with stereo sound
+  Power        - DC6V 0.7W (DC3V 0.7W for GB Pocket, DC3V 0.6W for CGB)
+

+
+
 Memory Map

+The gameboy is having a 16bit address bus, that is used to address ROM, +RAM, and I/O registers.
+
+General Memory Map
+
  0000-3FFF   16KB ROM Bank 00     (in cartridge, fixed at bank 00)
+  4000-7FFF   16KB ROM Bank 01..NN (in cartridge, switchable bank number)
+  8000-9FFF   8KB Video RAM (VRAM) (switchable bank 0-1 in CGB Mode)
+  A000-BFFF   8KB External RAM     (in cartridge, switchable bank, if any)
+  C000-CFFF   4KB Work RAM Bank 0 (WRAM)
+  D000-DFFF   4KB Work RAM Bank 1 (WRAM)  (switchable bank 1-7 in CGB Mode)
+  E000-FDFF   Same as C000-DDFF (ECHO)    (typically not used)
+  FE00-FE9F   Sprite Attribute Table (OAM)
+  FEA0-FEFF   Not Usable
+  FF00-FF7F   I/O Ports
+  FF80-FFFE   High RAM (HRAM)
+  FFFF        Interrupt Enable Register
+

+Jump Vectors in First ROM Bank
+
The following addresses are supposed to be used as jump vectors:
+
  0000,0008,0010,0018,0020,0028,0030,0038   for RST commands
+  0040,0048,0050,0058,0060                  for Interrupts
+
However, the memory may be used for any other purpose in case that your +program doesn't use any (or only some) RST commands or Interrupts. RST +commands are 1-byte opcodes that work similiar to CALL opcodes, except +that the destination address is fixed.
+
+Cartridge Header in First ROM Bank
+
The memory at 0100-014F contains the cartridge header. This area +contains information about the program, its entry point, checksums, +information about the used MBC chip, the ROM and RAM sizes, etc. Most of +the bytes in this area are required to be specified correctly. For more +information read the chapter about The Cartridge Header.
+
+External Memory and Hardware
+
The areas from 0000-7FFF and A000-BFFF may be used to connect external +hardware. The first area is typically used to address ROM (read only, of +course), cartridges with Memory Bank Controllers (MBCs) are additionally +using this area to output data (write only) to the MBC chip. The second +area is often used to address external RAM, or to address other external +hardware (Real Time Clock, etc). External memory is often battery +buffered, and may hold saved game positions and high scrore tables +(etc.) even when the gameboy is turned of, or when the cartridge is +removed. For specific information read the chapter about Memory Bank +Controllers.
+
+
+
 Video Display

+Video I/O Registers
+
LCD Control Register
+LCD Status Register
+LCD Interrupts
+LCD Position and Scrolling
+LCD Monochrome Palettes
+LCD Color Palettes (CGB only)
+LCD VRAM Bank (CGB only)
+LCD OAM DMA Transfers
+LCD VRAM DMA Transfers (CGB only)
+
+Video Memory
+
VRAM Tile Data
+VRAM Background Maps
+VRAM Sprite Attribute Table (OAM)
+Accessing VRAM and OAM
+
+
+
 LCD Control Register

+FF40 - LCDC - LCD Control (R/W)
+
  Bit 7 - LCD Display Enable             (0=Off, 1=On)
+  Bit 6 - Window Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF)
+  Bit 5 - Window Display Enable          (0=Off, 1=On)
+  Bit 4 - BG & Window Tile Data Select   (0=8800-97FF, 1=8000-8FFF)
+  Bit 3 - BG Tile Map Display Select     (0=9800-9BFF, 1=9C00-9FFF)
+  Bit 2 - OBJ (Sprite) Size              (0=8x8, 1=8x16)
+  Bit 1 - OBJ (Sprite) Display Enable    (0=Off, 1=On)
+  Bit 0 - BG Display (for CGB see below) (0=Off, 1=On)
+

+LCDC.7 - LCD Display Enable
+
CAUTION: Stopping LCD operation (Bit 7 from 1 to 0) may be performed +during V-Blank ONLY, disabeling the display outside of the V-Blank +period may damage the hardware. This appears to be a serious issue, +Nintendo is reported to reject any games that do not follow this rule.
+V-blank can be confirmed when the value of LY is greater than or equal +to 144. When the display is disabled the screen is blank (white), and +VRAM and OAM can be accessed freely.
+
+--- LCDC.0 has different Meanings depending on Gameboy Type ---
+
+LCDC.0 - 1) Monochrome Gameboy and SGB: BG Display
+
When Bit 0 is cleared, the background becomes blank (white). Window and +Sprites may still be displayed (if enabled in Bit 1 and/or Bit 5).
+
+LCDC.0 - 2) CGB in CGB Mode: BG and Window Master Priority
+
When Bit 0 is cleared, the background and window lose their priority - +the sprites will be always displayed on top of background and window, +independently of the priority flags in OAM and BG Map attributes.
+
+LCDC.0 - 3) CGB in Non CGB Mode: BG and Window Display
+
When Bit 0 is cleared, both background and window become blank (white), +ie. the Window Display Bit (Bit 5) is ignored in that case. Only Sprites +may still be displayed (if enabled in Bit 1).
+This is a possible compatibility problem - any monochrome games (if any) +that disable the background, but still want to display the window +wouldn't work properly on CGBs.
+
+
+
 LCD Status Register

+FF41 - STAT - LCDC Status (R/W)
+
  Bit 6 - LYC=LY Coincidence Interrupt (1=Enable) (Read/Write)
+  Bit 5 - Mode 2 OAM Interrupt         (1=Enable) (Read/Write)
+  Bit 4 - Mode 1 V-Blank Interrupt     (1=Enable) (Read/Write)
+  Bit 3 - Mode 0 H-Blank Interrupt     (1=Enable) (Read/Write)
+  Bit 2 - Coincidence Flag  (0:LYC<>LY, 1:LYC=LY) (Read Only)
+  Bit 1-0 - Mode Flag       (Mode 0-3, see below) (Read Only)
+            0: During H-Blank
+            1: During V-Blank
+            2: During Searching OAM-RAM
+            3: During Transfering Data to LCD Driver
+

+The two lower STAT bits show the current status of the LCD controller.
+
  Mode 0: The LCD controller is in the H-Blank period and
+          the CPU can access both the display RAM (8000h-9FFFh)
+          and OAM (FE00h-FE9Fh)
+

+
  Mode 1: The LCD contoller is in the V-Blank period (or the
+          display is disabled) and the CPU can access both the
+          display RAM (8000h-9FFFh) and OAM (FE00h-FE9Fh)
+

+
  Mode 2: The LCD controller is reading from OAM memory.
+          The CPU <cannot> access OAM memory (FE00h-FE9Fh)
+          during this period.
+

+
  Mode 3: The LCD controller is reading from both OAM and VRAM,
+          The CPU <cannot> access OAM and VRAM during this period.
+          CGB Mode: Cannot access Palette Data (FF69,FF6B) either.
+

+The following are typical when the display is enabled:
+
  Mode 2  2_____2_____2_____2_____2_____2___________________2____
+  Mode 3  _33____33____33____33____33____33__________________3___
+  Mode 0  ___000___000___000___000___000___000________________000
+  Mode 1  ____________________________________11111111111111_____
+

+The Mode Flag goes through the values 0, 2, and 3 at a cycle of about +109uS. 0 is present about 48.6uS, 2 about 19uS, and 3 about 41uS. This +is interrupted every 16.6ms by the VBlank (1). The mode flag stays set +at 1 for about 1.08 ms.
+
+Mode 0 is present between 201-207 clks, 2 about 77-83 clks, and 3 about +169-175 clks. A complete cycle through these states takes 456 clks. +VBlank lasts 4560 clks. A complete screen refresh occurs every 70224 +clks.)
+
+
+
 LCD Interrupts

+INT 40 - V-Blank Interrupt
+
The V-Blank interrupt occurs ca. 59.7 times a second on a regular GB and +ca. 61.1 times a second on a Super GB (SGB). This interrupt occurs at +the beginning of the V-Blank period (LY=144).
+During this period video hardware is not using video ram so it may be +freely accessed. This period lasts approximately 1.1 milliseconds.
+
+INT 48 - LCDC Status Interrupt
+
There are various reasons for this interrupt to occur as described by +the STAT register ($FF40). One very popular reason is to indicate to the +user when the video hardware is about to redraw a given LCD line. This +can be useful for dynamically controlling the SCX/SCY registers +($FF43/$FF42) to perform special video effects.
+
+
+
 LCD Position and Scrolling

+FF42 - SCY - Scroll Y (R/W)
+FF43 - SCX - Scroll X (R/W)
+
Specifies the position in the 256x256 pixels BG map (32x32 tiles) which +is to be displayed at the upper/left LCD display position.
+Values in range from 0-255 may be used for X/Y each, the video +controller automatically wraps back to the upper (left) position in BG +map when drawing exceeds the lower (right) border of the BG map area.
+
+FF44 - LY - LCDC Y-Coordinate (R)
+
The LY indicates the vertical line to which the present data is +transferred to the LCD Driver. The LY can take on any value between 0 +through 153. The values between 144 and 153 indicate the V-Blank period. +Writing will reset the counter.
+
+FF45 - LYC - LY Compare (R/W)
+
The gameboy permanently compares the value of the LYC and LY registers. +When both values are identical, the coincident bit in the STAT register +becomes set, and (if enabled) a STAT interrupt is requested.
+
+FF4A - WY - Window Y Position (R/W)
+FF4B - WX - Window X Position minus 7 (R/W)
+
Specifies the upper/left positions of the Window area. (The window is an +alternate background area which can be displayed above of the normal +background. OBJs (sprites) may be still displayed above or behinf the +window, just as for normal BG.)
+The window becomes visible (if enabled) when positions are set in range +WX=0..166, WY=0..143. A postion of WX=7, WY=0 locates the window at +upper left, it is then completly covering normal background.
+
+
+
 LCD Monochrome Palettes

+FF47 - BGP - BG Palette Data (R/W) - Non CGB Mode Only
+
This register assigns gray shades to the color numbers of the BG and +Window tiles.
+
  Bit 7-6 - Shade for Color Number 3
+  Bit 5-4 - Shade for Color Number 2
+  Bit 3-2 - Shade for Color Number 1
+  Bit 1-0 - Shade for Color Number 0
+
The four possible gray shades are:
+
  0  White
+  1  Light gray
+  2  Dark gray
+  3  Black
+
In CGB Mode the Color Palettes are taken from CGB Palette Memory +instead.
+
+FF48 - OBP0 - Object Palette 0 Data (R/W) - Non CGB Mode Only
+
This register assigns gray shades for sprite palette 0. It works exactly +as BGP (FF47), except that the lower two bits aren't used because sprite +data 00 is transparent.
+
+FF49 - OBP1 - Object Palette 1 Data (R/W) - Non CGB Mode Only
+
This register assigns gray shades for sprite palette 1. It works exactly +as BGP (FF47), except that the lower two bits aren't used because sprite +data 00 is transparent.
+
+
+
 LCD Color Palettes (CGB only)

+FF68 - BCPS/BGPI - CGB Mode Only - Background Palette Index
+
This register is used to address a byte in the CGBs Background Palette +Memory. Each two byte in that memory define a color value. The first 8 +bytes define Color 0-3 of Palette 0 (BGP0), and so on for BGP1-7.
+
  Bit 0-5   Index (00-3F)
+  Bit 7     Auto Increment  (0=Disabled, 1=Increment after Writing)
+
Data can be read/written to/from the specified index address through +Register FF69. When the Auto Increment Bit is set then the index is +automatically incremented after each <write> to FF69. Auto Increment has +no effect when <reading> from FF69, so the index must be manually +incremented in that case.
+
+FF69 - BCPD/BGPD - CGB Mode Only - Background Palette Data
+
This register allows to read/write data to the CGBs Background Palette +Memory, addressed through Register FF68.
+Each color is defined by two bytes (Bit 0-7 in first byte).
+
  Bit 0-4   Red Intensity   (00-1F)
+  Bit 5-9   Green Intensity (00-1F)
+  Bit 10-14 Blue Intensity  (00-1F)
+
Much like VRAM, Data in Palette Memory cannot be read/written during the +time when the LCD Controller is reading from it. (That is when the STAT +register indicates Mode 3).
+Note: Initially all background colors are initialized as white.
+
+FF6A - OCPS/OBPI - CGB Mode Only - Sprite Palette Index
+FF6B - OCPD/OBPD - CGB Mode Only - Sprite Palette Data
+
These registers are used to initialize the Sprite Palettes OBP0-7, +identically as described above for Background Palettes. Note that four +colors may be defined for each OBP Palettes - but only Color 1-3 of each +Sprite Palette can be displayed, Color 0 is always transparent, and can +be initialized to a don't care value.
+Note: Initially all sprite colors are uninitialized.
+
+RGB Translation by CGBs
+
When developing graphics on PCs, note that the RGB values will have +different appearance on CGB displays as on VGA monitors:
+The highest intensity will produce Light Gray color rather than White. +The intensities are not linear; the values 10h-1Fh will all appear very +bright, while medium and darker colors are ranged at 00h-0Fh.
+The CGB display will mix colors quite oddly, increasing intensity of +only one R,G,B color will also influence the other two R,G,B colors.
+For example, a color setting of 03EFh (Blue=0, Green=1Fh, Red=0Fh) will +appear as Neon Green on VGA displays, but on the CGB it'll produce a +decently washed out Yellow.
+
+RGB Translation by GBAs
+
Even though GBA is described to be compatible to CGB games, most CGB +games are completely unplayable on GBAs because most colors are +invisible (black). Of course, colors such like Black and White will +appear the same on both CGB and GBA, but medium intensities are arranged +completely different.
+Intensities in range 00h..0Fh are invisible/black (unless eventually +under best sunlight circumstances, and when gazing at the screen under +obscure viewing angles), unfortunately, these intensities are regulary +used by most existing CGB games for medium and darker colors.
+Newer CGB games may avoid this effect by changing palette data when +detecting GBA hardware. A relative simple method would be using the +formula GBA=CGB/2+10h for each R,G,B intensity, probably the result +won't be perfect, and (once colors became visible) it may turn out that +the color mixing is different also, anyways, it'd be still ways better +than no conversion.
+Asides, this translation method should have been VERY easy to implement +in GBA hardware directly, even though Nintendo obviously failed to do +so. How did they say, This seal is your assurance for excellence in +workmanship and so on?
+
+
+
 LCD VRAM Bank (CGB only)

+FF4F - VBK - CGB Mode Only - VRAM Bank
+
This 1bit register selects the current Video Memory (VRAM) Bank.
+
  Bit 0 - VRAM Bank (0-1)
+
Bank 0 contains 192 Tiles, and two background maps, just as for +monochrome games. Bank 1 contains another 192 Tiles, and color attribute +maps for the background maps in bank 0.
+
+
+
 LCD OAM DMA Transfers

+FF46 - DMA - DMA Transfer and Start Address (W)
+
Writing to this register launches a DMA transfer from ROM or RAM to OAM +memory (sprite attribute table). The written value specifies the +transfer source address divided by 100h, ie. source & destination are:
+
  Source:      XX00-XX9F   ;XX in range from 00-F1h
+  Destination: FE00-FE9F
+
It takes 160 microseconds until the transfer has completed (80 +microseconds in CGB Double Speed Mode), during this time the CPU can +access only HRAM (memory at FF80-FFFE). For this reason, the programmer +must copy a short procedure into HRAM, and use this procedure to start +the transfer from inside HRAM, and wait until the transfer has finished:
+
   ld  (0FF46h),a ;start DMA transfer, a=start address/100h
+   ld  a,28h      ;delay...
+  wait:           ;total 5x40 cycles, approx 200ms
+   dec a          ;1 cycle
+   jr  nz,wait    ;4 cycles
+
Most programs are executing this procedure from inside of their VBlank +procedure, but it is possible to execute it during display redraw also, +allowing to display more than 40 sprites on the screen (ie. for example +40 sprites in upper half, and other 40 sprites in lower half of the +screen).
+
+
+
 LCD VRAM DMA Transfers (CGB only)

+FF51 - HDMA1 - CGB Mode Only - New DMA Source, High
+FF52 - HDMA2 - CGB Mode Only - New DMA Source, Low
+FF53 - HDMA3 - CGB Mode Only - New DMA Destination, High
+FF54 - HDMA4 - CGB Mode Only - New DMA Destination, Low
+FF55 - HDMA5 - CGB Mode Only - New DMA Length/Mode/Start
+
These registers are used to initiate a DMA transfer from ROM or RAM to +VRAM. The Source Start Address may be located at 0000-7FF0 or A000-DFF0, +the lower four bits of the address are ignored (treated as zero). The +Destination Start Address may be located at 8000-9FF0, the lower four +bits of the address are ignored (treated as zero), the upper 3 bits are +ignored either (destination is always in VRAM).
+
+Writing to FF55 starts the transfer, the lower 7 bits of FF55 specify +the Transfer Length (divided by 10h, minus 1). Ie. lengths of 10h-800h +bytes can be defined by the values 00h-7Fh. And the upper bit of FF55 +indicates the Transfer Mode:
+
+Bit7=0 - General Purpose DMA
+
When using this transfer method, all data is transferred at once. The +execution of the program is halted until the transfer has completed. +Note that the General Purpose DMA blindly attempts to copy the data, +even if the LCD controller is currently accessing VRAM. So General +Purpose DMA should be used only if the Display is disabled, or during +V-Blank, or (for rather short blocks) during H-Blank.
+The execution of the program continues when the transfer has been +completed, and FF55 then contains a value if FFh.
+
+Bit7=1 - H-Blank DMA
+
The H-Blank DMA transfers 10h bytes of data during each H-Blank, ie. at +LY=0-143, no data is transferred during V-Blank (LY=144-153), but the +transfer will then continue at LY=00. The execution of the program is +halted during the separate transfers, but the program execution +continues during the 'spaces' between each data block.
+Note that the program may not change the Destination VRAM bank (FF4F), +or the Source ROM/RAM bank (in case data is transferred from bankable +memory) until the transfer has completed!
+Reading from Register FF55 returns the remaining length (divided by 10h, +minus 1), a value of 0FFh indicates that the transfer has completed. It +is also possible to terminate an active H-Blank transfer by writing zero +to Bit 7 of FF55. In that case reading from FF55 may return any value +for the lower 7 bits, but Bit 7 will be read as "1".
+
+Confirming if the DMA Transfer is Active
+
Reading Bit 7 of FF55 can be used to confirm if the DMA transfer is +active (1=Not Active, 0=Active). This works under any circumstances - +after completion of General Purpose, or H-Blank Transfer, and after +manually terminating a H-Blank Transfer.
+
+Transfer Timings
+
In both Normal Speed and Double Speed Mode it takes about 8us to +transfer a block of 10h bytes. That are 8 cycles in Normal Speed Mode, +and 16 'fast' cycles in Double Speed Mode.
+Older MBC controllers (like MBC1-4) and slower ROMs are not guaranteed +to support General Purpose or H-Blank DMA, that's because there are +always 2 bytes transferred per microsecond (even if the itself program +runs it Normal Speed Mode).
+
+
+
 VRAM Tile Data

+Tile Data is stored in VRAM at addresses 8000h-97FFh, this area defines +the Bitmaps for 192 Tiles. In CGB Mode 384 Tiles can be defined, because +memory at 0:8000h-97FFh and at 1:8000h-97FFh is used.
+
+Each tile is sized 8x8 pixels and has a color depth of 4 colors/gray +shades. Tiles can be displayed as part of the Background/Window map, +and/or as OAM tiles (foreground sprites). Note that foreground sprites +may have only 3 colors, because color 0 is transparent.
+
+As it was said before, there are two Tile Pattern Tables at $8000-8FFF +and at $8800-97FF. The first one can be used for sprites and the +background. Its tiles are numbered from 0 to 255. The second table can +be used for the background and the window display and its tiles are +numbered from -128 to 127.
+
+Each Tile occupies 16 bytes, where each 2 bytes represent a line:
+
  Byte 0-1  First Line (Upper 8 pixels)
+  Byte 2-3  Next Line
+  etc.
+
For each line, the first byte defines the least significant bits of the +color numbers for each pixel, and the second byte defines the upper bits +of the color numbers. In either case, Bit 7 is the leftmost pixel, and +Bit 0 the rightmost.
+
+So, each pixel is having a color number in range from 0-3. The color +numbers are translated into real colors (or gray shades) depending on +the current palettes. The palettes are defined through registers +FF47-FF49 (Non CGB Mode), and FF68-FF6B (CGB Mode).
+
+
+
 VRAM Background Maps

+The gameboy contains two 32x32 tile background maps in VRAM at addresses +9800h-9BFFh and 9C00h-9FFFh. Each can be used either to display "normal" +background, or "window" background.
+
+BG Map Tile Numbers
+
An area of VRAM known as Background Tile Map contains the numbers of +tiles to be displayed. It is organized as 32 rows of 32 bytes each. Each +byte contains a number of a tile to be displayed. Tile patterns are +taken from the Tile Data Table located either at $8000-8FFF or +$8800-97FF. In the first case, patterns are numbered with unsigned +numbers from 0 to 255 (i.e. pattern #0 lies at address $8000). In the +second case, patterns have signed numbers from -128 to 127 (i.e. pattern +#0 lies at address $9000). The Tile Data Table address for the +background can be selected via LCDC register.
+
+BG Map Attributes (CGB Mode only)
+
In CGB Mode, an additional map of 32x32 bytes is stored in VRAM Bank 1 +(each byte defines attributes for the corresponding tile-number map +entry in VRAM Bank 0):
+
  Bit 0-2  Background Palette number  (BGP0-7)
+  Bit 3    Tile VRAM Bank number      (0=Bank 0, 1=Bank 1)
+  Bit 4    Not used
+  Bit 5    Horizontal Flip            (0=Normal, 1=Mirror horizontally)
+  Bit 6    Vertical Flip              (0=Normal, 1=Mirror vertically)
+  Bit 7    BG-to-OAM Priority         (0=Use OAM priority bit, 1=BG Priority)
+
When Bit 7 is set, the corresponding BG tile will have priority above +all OBJs (regardless of the priority bits in OAM memory). There's also +an Master Priority flag in LCDC register Bit 0 which overrides all other +priority bits when cleared.
+
+As one background tile has a size of 8x8 pixels, the BG maps may hold a +picture of 256x256 pixels, an area of 160x144 pixels of this picture can +be displayed on the LCD screen.
+
+Normal Background (BG)
+
The SCY and SCX registers can be used to scroll the background, allowing +to select the origin of the visible 160x144 pixel area within the total +256x256 pixel background map. Background wraps around the screen (i.e. +when part of it goes off the screen, it appears on the opposite side.)
+
+The Window
+
Besides background, there is also a "window" overlaying the background. +The window is not scrollable i.e. it is always displayed starting from +its left upper corner. The location of a window on the screen can be +adjusted via WX and WY registers. Screen coordinates of the top left +corner of a window are WX-7,WY. The tiles for the window are stored in +the Tile Data Table. Both the Background and the window share the same +Tile Data Table.
+
+Both background and window can be disabled or enabled separately via +bits in the LCDC register.
+
+
+
 VRAM Sprite Attribute Table (OAM)

+GameBoy video controller can display up to 40 sprites either in 8x8 or +in 8x16 pixels. Because of a limitation of hardware, only ten sprites +can be displayed per scan line. Sprite patterns have the same format as +BG tiles, but they are taken from the Sprite Pattern Table located at +$8000-8FFF and have unsigned numbering.
+
+Sprite attributes reside in the Sprite Attribute Table (OAM - Object +Attribute Memory) at $FE00-FE9F. Each of the 40 entries consists of four +bytes with the following meanings:
+
+Byte0 - Y Position
+
Specifies the sprites vertical position on the screen (minus 16).
+An offscreen value (for example, Y=0 or Y>=160) hides the sprite.
+
+Byte1 - X Position
+
Specifies the sprites horizontal position on the screen (minus 8).
+An offscreen value (X=0 or X>=168) hides the sprite, but the sprite
+still affects the priority ordering - a better way to hide a sprite is +to set its Y-coordinate offscreen.
+
+Byte2 - Tile/Pattern Number
+
Specifies the sprites Tile Number (00-FF). This (unsigned) value selects +a tile from memory at 8000h-8FFFh. In CGB Mode this could be either in +VRAM Bank 0 or 1, depending on Bit 3 of the following byte.
+In 8x16 mode, the lower bit of the tile number is ignored. Ie. the upper +8x8 tile is "NN AND FEh", and the lower 8x8 tile is "NN OR 01h".
+
+Byte3 - Attributes/Flags:
+
  Bit7   OBJ-to-BG Priority (0=OBJ Above BG, 1=OBJ Behind BG color 1-3)
+         (Used for both BG and Window. BG color 0 is always behind OBJ)
+  Bit6   Y flip          (0=Normal, 1=Vertically mirrored)
+  Bit5   X flip          (0=Normal, 1=Horizontally mirrored)
+  Bit4   Palette number  **Non CGB Mode Only** (0=OBP0, 1=OBP1)
+  Bit3   Tile VRAM-Bank  **CGB Mode Only**     (0=Bank 0, 1=Bank 1)
+  Bit2-0 Palette number  **CGB Mode Only**     (OBP0-7)
+

+Sprite Priorities and Conflicts
+
When sprites with different x coordinate values overlap, the one with +the smaller x coordinate (closer to the left) will have priority and +appear above any others. This applies in Non CGB Mode only.
+When sprites with the same x coordinate values overlap, they have +priority according to table ordering. (i.e. $FE00 - highest, $FE04 - +next highest, etc.) In CGB Mode priorities are always assigned like +this.
+
+Only 10 sprites can be displayed on any one line. When this limit is +exceeded, the lower priority sprites (priorities listed above) won't be +displayed. To keep unused sprites from affecting onscreen sprites set +their Y coordinate to Y=0 or Y=>144+16. Just setting the X coordinate to +X=0 or X=>160+8 on a sprite will hide it but it will still affect other +sprites sharing the same lines.
+
+Writing Data to OAM Memory
+
The recommened method is to write the data to normal RAM first, and to +copy that RAM to OAM by using the DMA transfer function, initiated +through DMA register (FF46).
+Beside for that, it is also possible to write data directly to the OAM +area by using normal LD commands, this works only during the H-Blank and +V-Blank periods. The current state of the LCD controller can be read out +from the STAT register (FF41).
+
+
+
 Accessing VRAM and OAM

+CAUTION
+
When the LCD Controller is drawing the screen it is directly reading +from Video Memory (VRAM) and from the Sprite Attribute Table (OAM). +During these periods the Gameboy CPU may not access the VRAM and OAM. +That means, any attempts to write to VRAM/OAM are ignored (the data +remains unchanged). And any attempts to read from VRAM/OAM will return +undefined data (typically a value of FFh).
+
+For this reason the program should verify if VRAM/OAM is accessable +before actually reading or writing to it. This is usually done by +reading the Mode Bits from the STAT Register (FF41). When doing this (as +described in the examples below) you should take care that no interrupts +occur between the wait loops and the following memory access - the +memory is guaranted to be accessable only for a few cycles directly +after the wait loops have completed.
+
+VRAM (memory at 8000h-9FFFh) is accessable during Mode 0-2
+
  Mode 0 - H-Blank Period,
+  Mode 1 - V-Blank Period, and
+  Mode 2 - Searching OAM Period
+
A typical procedure that waits for accessibility of VRAM would be:
+
  ld   hl,0FF41h    ;-STAT Register
+ @@wait:            ;\
+  bit  1,(hl)       ; Wait until Mode is 0 or 1
+  jr   nz,@@wait    ;/
+
Even if the procedure gets executed at the <end> of Mode 0 or 1, it is +still proof to assume that VRAM can be accessed for a few more cycles +because in either case the following period is Mode 2 which allows +access to VRAM either.
+In CGB Mode an alternate method to write data to VRAM is to use the HDMA +Function (FF51-FF55).
+
+OAM (memory at FE00h-FE9Fh) is accessable during Mode 0-1
+
  Mode 0 - H-Blank Period, and
+  Mode 1 - V-Blank Period
+
Beside for that, OAM can be accessed at any time by using the DMA +Function (FF46). When directly reading or writing to OAM, a typical +procedure that waits for accessibilty or OAM Memory would be:
+
  ld   hl,0FF41h    ;-STAT Register
+ @@wait1:           ;\
+  bit  1,(hl)       ; Wait until Mode is -NOT- 0 or 1
+  jr   z,@@wait1    ;/
+ @@wait2:           ;\
+  bit  1,(hl)       ; Wait until Mode 0 or 1 -BEGINS-
+  jr   nz,@@wait2   ;/
+
The two wait loops ensure that Mode 0 or 1 will last for a few clock +cycles after completion of the procedure. In V-Blank period it might be +recommended to skip the whole procedure - and in most cases using the +above mentioned DMA function would be more recommended anyways.
+
+Note
+
When the display is disabled, both VRAM and OAM are accessable at any +time. The downside is that the screen is blank (white) during this +period, so that disabling the display would be recommended only during +initialization.
+
+
+
 Sound Controller

+Sound Overview
+Sound Channel 1 - Tone & Sweep
+Sound Channel 2 - Tone
+Sound Channel 3 - Wave Output
+Sound Channel 4 - Noise
+Sound Control Registers
+
+
+
 Sound Overview

+There are two sound channels connected to the output terminals SO1 and +SO2. There is also a input terminal Vin connected to the cartridge. It +can be routed to either of both output terminals. GameBoy circuitry +allows producing sound in four different ways:
+
+
   Quadrangular wave patterns with sweep and envelope functions.
+   Quadrangular wave patterns with envelope functions.
+   Voluntary wave patterns from wave RAM.
+   White noise with an envelope function.
+

+These four sounds can be controlled independantly and then mixed +separately for each of the output terminals.
+
+Sound registers may be set at all times while producing sound.
+
+(Sounds will have a 2.4% higher frequency on Super GB.)
+
+
+
 Sound Channel 1 - Tone & Sweep

+FF10 - NR10 - Channel 1 Sweep register (R/W)
+
  Bit 6-4 - Sweep Time
+  Bit 3   - Sweep Increase/Decrease
+             0: Addition    (frequency increases)
+             1: Subtraction (frequency decreases)
+  Bit 2-0 - Number of sweep shift (n: 0-7)
+
Sweep Time:
+
  000: sweep off - no freq change
+  001: 7.8 ms  (1/128Hz)
+  010: 15.6 ms (2/128Hz)
+  011: 23.4 ms (3/128Hz)
+  100: 31.3 ms (4/128Hz)
+  101: 39.1 ms (5/128Hz)
+  110: 46.9 ms (6/128Hz)
+  111: 54.7 ms (7/128Hz)
+

+The change of frequency (NR13,NR14) at each shift is calculated by the +following formula where X(0) is initial freq & X(t-1) is last freq:
+
  X(t) = X(t-1) +/- X(t-1)/2^n
+

+FF11 - NR11 - Channel 1 Sound length/Wave pattern duty (R/W)
+
  Bit 7-6 - Wave Pattern Duty (Read/Write)
+  Bit 5-0 - Sound length data (Write Only) (t1: 0-63)
+
Wave Duty:
+
  00: 12.5% ( _-------_-------_------- )
+  01: 25%   ( __------__------__------ )
+  10: 50%   ( ____----____----____---- ) (normal)
+  11: 75%   ( ______--______--______-- )
+
Sound Length = (64-t1)*(1/256) seconds
+The Length value is used only if Bit 6 in NR14 is set.
+
+FF12 - NR12 - Channel 1 Volume Envelope (R/W)
+
  Bit 7-4 - Initial Volume of envelope (0-0Fh) (0=No Sound)
+  Bit 3   - Envelope Direction (0=Decrease, 1=Increase)
+  Bit 2-0 - Number of envelope sweep (n: 0-7)
+            (If zero, stop envelope operation.)
+
Length of 1 step = n*(1/64) seconds
+
+FF13 - NR13 - Channel 1 Frequency lo (Write Only)
+

+Lower 8 bits of 11 bit frequency (x).
+Next 3 bit are in NR14 ($FF14)
+
+FF14 - NR14 - Channel 1 Frequency hi (R/W)
+
  Bit 7   - Initial (1=Restart Sound)     (Write Only)
+  Bit 6   - Counter/consecutive selection (Read/Write)
+            (1=Stop output when length in NR11 expires)
+  Bit 2-0 - Frequency's higher 3 bits (x) (Write Only)
+
Frequency = 131072/(2048-x) Hz
+
+
+
 Sound Channel 2 - Tone

+This sound channel works exactly as channel 1, except that it doesn't +have a Tone Envelope/Sweep Register.
+
+FF16 - NR21 - Channel 2 Sound Length/Wave Pattern Duty (R/W)
+
  Bit 7-6 - Wave Pattern Duty (Read/Write)
+  Bit 5-0 - Sound length data (Write Only) (t1: 0-63)
+
Wave Duty:
+
  00: 12.5% ( _-------_-------_------- )
+  01: 25%   ( __------__------__------ )
+  10: 50%   ( ____----____----____---- ) (normal)
+  11: 75%   ( ______--______--______-- )
+
Sound Length = (64-t1)*(1/256) seconds
+The Length value is used only if Bit 6 in NR24 is set.
+
+FF17 - NR22 - Channel 2 Volume Envelope (R/W)
+
  Bit 7-4 - Initial Volume of envelope (0-0Fh) (0=No Sound)
+  Bit 3   - Envelope Direction (0=Decrease, 1=Increase)
+  Bit 2-0 - Number of envelope sweep (n: 0-7)
+            (If zero, stop envelope operation.)
+
Length of 1 step = n*(1/64) seconds
+
+FF18 - NR23 - Channel 2 Frequency lo data (W)
+
Frequency's lower 8 bits of 11 bit data (x).
+Next 3 bits are in NR24 ($FF19).
+
+FF19 - NR24 - Channel 2 Frequency hi data (R/W)
+
  Bit 7   - Initial (1=Restart Sound)     (Write Only)
+  Bit 6   - Counter/consecutive selection (Read/Write)
+            (1=Stop output when length in NR21 expires)
+  Bit 2-0 - Frequency's higher 3 bits (x) (Write Only)
+
Frequency = 131072/(2048-x) Hz
+
+
+
 Sound Channel 3 - Wave Output

+This channel can be used to output digital sound, the length of the +sample buffer (Wave RAM) is limited to 32 digits. This sound channel can +be also used to output normal tones when initializing the Wave RAM by a +square wave. This channel doesn't have a volume envelope register.
+
+FF1A - NR30 - Channel 3 Sound on/off (R/W)
+
  Bit 7 - Sound Channel 3 Off  (0=Stop, 1=Playback)  (Read/Write)
+

+FF1B - NR31 - Channel 3 Sound Length
+
  Bit 7-0 - Sound length (t1: 0 - 255)
+
Sound Length = (256-t1)*(1/256) seconds
+This value is used only if Bit 6 in NR34 is set.
+
+FF1C - NR32 - Channel 3 Select output level (R/W)
+
  Bit 6-5 - Select output level (Read/Write)
+
Possible Output levels are:
+
  0: Mute (No sound)
+  1: 100% Volume (Produce Wave Pattern RAM Data as it is)
+  2:  50% Volume (Produce Wave Pattern RAM data shifted once to the right)
+  3:  25% Volume (Produce Wave Pattern RAM data shifted twice to the right)
+

+FF1D - NR33 - Channel 3 Frequency's lower data (W)
+
Lower 8 bits of an 11 bit frequency (x).
+
+FF1E - NR34 - Channel 3 Frequency's higher data (R/W)
+
  Bit 7   - Initial (1=Restart Sound)     (Write Only)
+  Bit 6   - Counter/consecutive selection (Read/Write)
+            (1=Stop output when length in NR31 expires)
+  Bit 2-0 - Frequency's higher 3 bits (x) (Write Only)
+
Frequency = 4194304/(64*(2048-x)) Hz = 65536/(2048-x) Hz
+
+FF30-FF3F - Wave Pattern RAM
+
Contents - Waveform storage for arbitrary sound data
+
+This storage area holds 32 4-bit samples that are played back upper 4 +bits first.
+
+
+
 Sound Channel 4 - Noise

+This channel is used to output white noise. This is done by randomly +switching the amplitude between high and low at a given frequency. +Depending on the frequency the noise will appear 'harder' or 'softer'.
+
+It is also possible to influence the function of the random generator, +so the that the output becomes more regular, resulting in a limited +ability to output Tone instead of Noise.
+
+FF20 - NR41 - Channel 4 Sound Length (R/W)
+
  Bit 5-0 - Sound length data (t1: 0-63)
+
Sound Length = (64-t1)*(1/256) seconds
+The Length value is used only if Bit 6 in NR44 is set.
+
+FF21 - NR42 - Channel 4 Volume Envelope (R/W)
+
  Bit 7-4 - Initial Volume of envelope (0-0Fh) (0=No Sound)
+  Bit 3   - Envelope Direction (0=Decrease, 1=Increase)
+  Bit 2-0 - Number of envelope sweep (n: 0-7)
+            (If zero, stop envelope operation.)
+
Length of 1 step = n*(1/64) seconds
+
+FF22 - NR43 - Channel 4 Polynomial Counter (R/W)
+
The amplitude is randomly switched between high and low at the given +frequency. A higher frequency will make the noise to appear 'softer'.
+When Bit 3 is set, the output will become more regular, and some +frequencies will sound more like Tone than Noise.
+
  Bit 7-4 - Shift Clock Frequency (s)
+  Bit 3   - Counter Step/Width (0=15 bits, 1=7 bits)
+  Bit 2-0 - Dividing Ratio of Frequencies (r)
+
Frequency = 524288 Hz / r / 2^(s+1) ;For r=0 assume r=0.5 instead
+
+FF23 - NR44 - Channel 4 Counter/consecutive; Inital (R/W)
+
  Bit 7   - Initial (1=Restart Sound)     (Write Only)
+  Bit 6   - Counter/consecutive selection (Read/Write)
+            (1=Stop output when length in NR41 expires)
+

+
+
 Sound Control Registers

+FF24 - NR50 - Channel control / ON-OFF / Volume (R/W)
+
The volume bits specify the "Master Volume" for Left/Right sound output.
+
  Bit 7   - Output Vin to SO2 terminal (1=Enable)
+  Bit 6-4 - SO2 output level (volume)  (0-7)
+  Bit 3   - Output Vin to SO1 terminal (1=Enable)
+  Bit 2-0 - SO1 output level (volume)  (0-7)
+
The Vin signal is received from the game cartridge bus, allowing +external hardware in the cartridge to supply a fifth sound channel, +additionally to the gameboys internal four channels. As far as I know +this feature isn't used by any existing games.
+
+FF25 - NR51 - Selection of Sound output terminal (R/W)
+
  Bit 7 - Output sound 4 to SO2 terminal
+  Bit 6 - Output sound 3 to SO2 terminal
+  Bit 5 - Output sound 2 to SO2 terminal
+  Bit 4 - Output sound 1 to SO2 terminal
+  Bit 3 - Output sound 4 to SO1 terminal
+  Bit 2 - Output sound 3 to SO1 terminal
+  Bit 1 - Output sound 2 to SO1 terminal
+  Bit 0 - Output sound 1 to SO1 terminal
+

+FF26 - NR52 - Sound on/off
+
If your GB programs don't use sound then write 00h to this register to +save 16% or more on GB power consumption. Disabeling the sound +controller by clearing Bit 7 destroys the contents of all sound +registers. Also, it is not possible to access any sound registers +(execpt FF26) while the sound controller is disabled.
+
  Bit 7 - All sound on/off  (0: stop all sound circuits) (Read/Write)
+  Bit 3 - Sound 4 ON flag (Read Only)
+  Bit 2 - Sound 3 ON flag (Read Only)
+  Bit 1 - Sound 2 ON flag (Read Only)
+  Bit 0 - Sound 1 ON flag (Read Only)
+
Bits 0-3 of this register are read only status bits, writing to these +bits does NOT enable/disable sound. The flags get set when sound output +is restarted by setting the Initial flag (Bit 7 in NR14-NR44), the flag +remains set until the sound length has expired (if enabled). A volume +envelopes which has decreased to zero volume will NOT cause the sound +flag to go off.
+
+
+
 Joypad Input

+FF00 - P1/JOYP - Joypad (R/W)
+
The eight gameboy buttons/direction keys are arranged in form of a 2x4 +matrix. Select either button or direction keys by writing to this +register, then read-out bit 0-3.
+
  Bit 7 - Not used
+  Bit 6 - Not used
+  Bit 5 - P15 Select Button Keys      (0=Select)
+  Bit 4 - P14 Select Direction Keys   (0=Select)
+  Bit 3 - P13 Input Down  or Start    (0=Pressed) (Read Only)
+  Bit 2 - P12 Input Up    or Select   (0=Pressed) (Read Only)
+  Bit 1 - P11 Input Left  or Button B (0=Pressed) (Read Only)
+  Bit 0 - P10 Input Right or Button A (0=Pressed) (Read Only)
+
Note: Most programs are repeatedly reading from this port several times +(the first reads used as short delay, allowing the inputs to stabilize, +and only the value from the last read actually used).
+
+Usage in SGB software
+
Beside for normal joypad input, SGB games mis-use the joypad register to +output SGB command packets to the SNES, also, SGB programs may read out +gamepad states from up to four different joypads which can be connected +to the SNES.
+See SGB description for details.
+
+INT 60 - Joypad Interrupt
+
Joypad interrupt is requested when any of the above Input lines changes +from High to Low. Generally this should happen when a key becomes +pressed (provided that the button/direction key is enabled by above +Bit4/5), however, because of switch bounce, one or more High to Low +transitions are usually produced both when pressing or releasing a key.
+
+Using the Joypad Interrupt
+
It's more or less useless for programmers, even when selecting both +buttons and direction keys simultaneously it still cannot recognize all +keystrokes, because in that case a bit might be already held low by a +button key, and pressing the corresponding direction key would thus +cause no difference. The only meaningful purpose of the keystroke +interrupt would be to terminate STOP (low power) standby state.
+Also, the joypad interrupt does not appear to work with CGB and GBA +hardware (the STOP function can be still terminated by joypad keystrokes +though).
+
+
+
 Serial Data Transfer (Link Cable)

+FF01 - SB - Serial transfer data (R/W)
+
8 Bits of data to be read/written
+
+FF02 - SC - Serial Transfer Control (R/W)
+
  Bit 7 - Transfer Start Flag (0=No Transfer, 1=Start)
+  Bit 1 - Clock Speed (0=Normal, 1=Fast) ** CGB Mode Only **
+  Bit 0 - Shift Clock (0=External Clock, 1=Internal Clock)
+
The clock signal specifies the rate at which the eight data bits in SB +(FF01) are transferred. When the gameboy is communicating with another +gameboy (or other computer) then either one must supply internal clock, +and the other one must use external clock.
+
+Internal Clock
+
In Non-CGB Mode the gameboy supplies an internal clock of 8192Hz only +(allowing to transfer about 1 KByte per second). In CGB Mode four +internal clock rates are available, depending on Bit 1 of the SC +register, and on whether the CGB Double Speed Mode is used:
+
    8192Hz -  1KB/s - Bit 1 cleared, Normal
+   16384Hz -  2KB/s - Bit 1 cleared, Double Speed Mode
+  262144Hz - 32KB/s - Bit 1 set,     Normal
+  524288Hz - 64KB/s - Bit 1 set,     Double Speed Mode
+

+External Clock
+
The external clock is typically supplied by another gameboy, but might +be supplied by another computer (for example if connected to a PCs +parallel port), in that case the external clock may have any speed. Even +the old/monochrome gameboy is reported to recognizes external clocks of +up to 500KHz. And there is no limitiation into the other direction - +even when suppling an external clock speed of "1 bit per month", then +the gameboy will still eagerly wait for the next bit(s) to be +transferred. It isn't required that the clock pulses are sent at an +regular interval either.
+
+Timeouts
+
When using external clock then the transfer will not complete until the +last bit is received. In case that the second gameboy isn't supplying a +clock signal, if it gets turned off, or if there is no second gameboy +connected at all) then transfer will never complete. For this reason the +transfer procedure should use a timeout counter, and abort the +communication if no response has been received during the timeout +interval.
+
+Delays and Synchronization
+
The gameboy that is using internal clock should always execute a small +delay between each transfer, in order to ensure that the opponent +gameboy has enough time to prepare itself for the next transfer, ie. the +gameboy with external clock must have set its transfer start bit before +the gameboy with internal clock starts the transfer. Alternately, the +two gameboys could switch between internal and external clock for each +transferred byte to ensure synchronization.
+
+Transfer is initiated by setting the Transfer Start Flag. This bit is +automatically set to 0 at the end of Transfer. Reading this bit can be +used to determine if the transfer is still active.
+
+INT 58 - Serial Interrupt
+
When the transfer has completed (ie. after sending/receiving 8 bits, if +any) then an interrupt is requested by setting Bit 3 of the IF Register +(FF0F). When that interrupt is enabled, then the Serial Interrupt vector +at 0058 is called.
+
+XXXXXX...
+

+Transmitting and receiving serial data is done simultaneously. The +received data is automatically stored in SB.
+
+The serial I/O port on the Gameboy is a very simple setup and is crude +compared to standard RS-232 (IBM-PC) or RS-485 (Macintosh) serial ports. +There are no start or stop bits.
+
+During a transfer, a byte is shifted in at the same time that a byte is +shifted out. The rate of the shift is determined by whether the clock +source is internal or external.
+The most significant bit is shifted in and out first.
+
+When the internal clock is selected, it drives the clock pin on the game +link port and it stays high when not used. During a transfer it will go +low eight times to clock in/out each bit.
+
+The state of the last bit shifted out determines the state of the output +line until another transfer takes place.
+
+If a serial transfer with internal clock is performed and no external +GameBoy is present, a value of $FF will be received in the transfer.
+
+The following code causes $75 to be shifted out the serial port and a +byte to be shifted into $FF01:
+
+
    ld   a,$75
+    ld  ($FF01),a
+    ld   a,$81
+    ld  ($FF02),a
+

+
+
 Timer and Divider Registers

+FF04 - DIV - Divider Register (R/W)
+
This register is incremented at rate of 16384Hz (~16779Hz on SGB). In +CGB Double Speed Mode it is incremented twice as fast, ie. at 32768Hz. +Writing any value to this register resets it to 00h.
+
+FF05 - TIMA - Timer counter (R/W)
+
This timer is incremented by a clock frequency specified by the TAC +register ($FF07). When the value overflows (gets bigger than FFh) then +it will be reset to the value specified in TMA (FF06), and an interrupt +will be requested, as described below.
+
+FF06 - TMA - Timer Modulo (R/W)
+
When the TIMA overflows, this data will be loaded.
+
+FF07 - TAC - Timer Control (R/W)
+
  Bit 2    - Timer Stop  (0=Stop, 1=Start)
+  Bits 1-0 - Input Clock Select
+             00:   4096 Hz    (~4194 Hz SGB)
+             01: 262144 Hz  (~268400 Hz SGB)
+             10:  65536 Hz   (~67110 Hz SGB)
+             11:  16384 Hz   (~16780 Hz SGB)
+

+INT 50 - Timer Interrupt
+
Each time when the timer overflows (ie. when TIMA gets bigger than FFh), +then an interrupt is requested by setting Bit 2 in the IF Register +(FF0F). When that interrupt is enabled, then the CPU will execute it by +calling the timer interrupt vector at 0050h.
+
+Note
+
The above described Timer is the built-in timer in the gameboy. It has +nothing to do with the MBC3s battery buffered Real Time Clock - that's a +completely different thing, described in the chapter about Memory +Banking Controllers.
+
+
+
 Interrupts

+IME - Interrupt Master Enable Flag (Write Only)
+
  0 - Disable all Interrupts
+  1 - Enable all Interrupts that are enabled in IE Register (FFFF)
+
The IME flag is used to disable all interrupts, overriding any enabled +bits in the IE Register. It isn't possible to access the IME flag by +using a I/O address, instead IME is accessed directly from the CPU, by +the following opcodes/operations:
+
  EI     ;Enable Interrupts  (ie. IME=1)
+  DI     ;Disable Interrupts (ie. IME=0)
+  RETI   ;Enable Ints & Return (same as the opcode combination EI, RET)
+  <INT>  ;Disable Ints & Call to Interrupt Vector
+
Whereas <INT> means the operation which is automatically executed by the +CPU when it executes an interrupt.
+
+FFFF - IE - Interrupt Enable (R/W)
+
  Bit 0: V-Blank  Interrupt Enable  (INT 40h)  (1=Enable)
+  Bit 1: LCD STAT Interrupt Enable  (INT 48h)  (1=Enable)
+  Bit 2: Timer    Interrupt Enable  (INT 50h)  (1=Enable)
+  Bit 3: Serial   Interrupt Enable  (INT 58h)  (1=Enable)
+  Bit 4: Joypad   Interrupt Enable  (INT 60h)  (1=Enable)
+

+FF0F - IF - Interrupt Flag (R/W)
+
  Bit 0: V-Blank  Interrupt Request (INT 40h)  (1=Request)
+  Bit 1: LCD STAT Interrupt Request (INT 48h)  (1=Request)
+  Bit 2: Timer    Interrupt Request (INT 50h)  (1=Request)
+  Bit 3: Serial   Interrupt Request (INT 58h)  (1=Request)
+  Bit 4: Joypad   Interrupt Request (INT 60h)  (1=Request)
+
When an interrupt signal changes from low to high, then the +corresponding bit in the IF register becomes set. For example, Bit 0 +becomes set when the LCD controller enters into the V-Blank period.
+
+Interrupt Requests
+
Any set bits in the IF register are only <requesting> an interrupt to be +executed. The actual <execution> happens only if both the IME flag, and +the corresponding bit in the IE register are set, otherwise the +interrupt 'waits' until both IME and IE allow its execution.
+
+Interrupt Execution
+
When an interrupt gets executed, the corresponding bit in the IF +register becomes automatically reset by the CPU, and the IME flag +becomes cleared (disabeling any further interrupts until the program +re-enables the interrupts, typically by using the RETI instruction), and +the corresponding Interrupt Vector (that are the addresses in range +0040h-0060h, as shown in IE and IF register decriptions above) becomes +called.
+
+Manually Requesting/Discarding Interrupts
+
As the CPU automatically sets and cleares the bits in the IF register it +is usually not required to write to the IF register. However, the user +may still do that in order to manually request (or discard) interrupts. +As for real interrupts, a manually requested interrupt isn't executed +unless/until IME and IE allow its execution.
+
+Interrupt Priorities
+
In the following three situations it might happen that more than 1 bit +in the IF register are set, requesting more than one interrupt at once:
+
  1) More than one interrupt signal changed from Low
+     to High at the same time.
+  2) Several interrupts have been requested during a
+     time in which IME/IE didn't allow these interrupts
+     to be executed directly.
+  3) The user has written a value with several "1" bits
+     (for example 1Fh) to the IF register.
+
Provided that IME and IE allow the execution of more than one of the +requested interrupts, then the interrupt with the highest priority +becomes executed first. The priorities are ordered as the bits in the IE +and IF registers, Bit 0 (V-Blank) having the highest priority, and Bit 4 +(Joypad) having the lowest priority.
+
+Nested Interrupts
+
The CPU automatically disables all other interrupts by setting IME=0 +when it executes an interrupt. Usually IME remains zero until the +interrupt procedure returns (and sets IME=1 by the RETI instruction). +However, if you want any other interrupts of lower or higher (or same) +priority to be allowed to be executed from inside of the interrupt +procedure, then you can place an EI instruction into the interrupt +procedure.
+
+
+
 CGB Registers

+Forward
+
This chapter describes only CGB (Color Gameboy) registers that didn't +fit into normal categories - most CGB registers are described in the +chapter about Video Display (Color Palettes, VRAM Bank, VRAM DMA +Transfers, and changed meaning of Bit 0 of LCDC Control register). Also, +a changed bit is noted in the chapter about the Serial/Link port.
+
+Unlocking CGB functions
+
When using any CGB registers (including those in the Video/Link +chapters), you must first unlock CGB features by changing byte 0143h in +the cartridge header. Typically use a value of 80h for games which +support both CGB and monochrome gameboys, and C0h for games which work +on CGBs only. Otherwise, the CGB will operate in monochrome "Non CGB" +compatibility mode.
+
+Detecting CGB (and GBA) functions
+
CGB hardware can be detected by examing the CPU accumulator (A-register) +directly after startup. A value of 11h indicates CGB (or GBA) hardware, +if so, CGB functions can be used (if unlocked, see above).
+When A=11h, you may also examine Bit 0 of the CPUs B-Register to +separate between CGB (bit cleared) and GBA (bit set), by that detection +it is possible to use 'repaired' color palette data matching for GBA +displays.
+
+FF4D - KEY1 - CGB Mode Only - Prepare Speed Switch
+
  Bit 7: Current Speed     (0=Normal, 1=Double) (Read Only)
+  Bit 0: Prepare Speed Switch (0=No, 1=Prepare) (Read/Write)
+
This register is used to prepare the gameboy to switch between CGB +Double Speed Mode and Normal Speed Mode. The actual speed switch is +performed by executing a STOP command after Bit 0 has been set. After +that Bit 0 will be cleared automatically, and the gameboy will operate +at the 'other' speed. The recommended speed switching procedure in +pseudo code would be:
+
  IF KEY1_BIT7 <> DESIRED_SPEED THEN
+    IE=00H       ;(FFFF)=00h
+    JOYP=30H     ;(FF00)=30h
+    KEY1=01H     ;(FF4D)=01h
+    STOP         ;STOP
+  ENDIF
+
The CGB is operating in Normal Speed Mode when it is turned on. Note +that using the Double Speed Mode increases the power consumption, it +would be recommended to use Single Speed whenever possible. However, the +display will flicker (white) for a moment during speed switches, so this +cannot be done permanentely.
+In Double Speed Mode the following will operate twice as fast as normal:
+
  The CPU (2.10 MHz, 1 Cycle = approx. 0.5us)
+  Timer and Divider Registers
+  Serial Port (Link Cable)
+  DMA Transfer to OAM
+
And the following will keep operating as usual:
+
  LCD Video Controller
+  HDMA Transfer to VRAM
+  All Sound Timings and Frequencies
+

+FF56 - RP - CGB Mode Only - Infrared Communications Port
+
This register allows to input and output data through the CGBs built-in +Infrared Port. When reading data, bit 6 and 7 must be set (and obviously +Bit 0 must be cleared - if you don't want to receive your own gameboys +IR signal). After sending or receiving data you should reset the +register to 00h to reduce battery power consumption again.
+
  Bit 0:   Write Data   (0=LED Off, 1=LED On)             (Read/Write)
+  Bit 1:   Read Data    (0=Receiving IR Signal, 1=Normal) (Read Only)
+  Bit 6-7: Data Read Enable (0=Disable, 3=Enable)         (Read/Write)
+
Note that the receiver will adapt itself to the normal level of IR +pollution in the air, so if you would send a LED ON signal for a longer +period, then the receiver would treat that as normal (=OFF) after a +while. For example, a Philips TV Remote Control sends a series of 32 LED +ON/OFF pulses (length 10us ON, 17.5us OFF each) instead of a permanent +880us LED ON signal.
+Even though being generally CGB compatible, the GBA does not include an +infra-red port.
+
+FF70 - SVBK - CGB Mode Only - WRAM Bank
+
In CGB Mode 32 KBytes internal RAM are available. This memory is divided +into 8 banks of 4 KBytes each. Bank 0 is always available in memory at +C000-CFFF, Bank 1-7 can be selected into the address space at D000-DFFF.
+
  Bit 0-2  Select WRAM Bank (Read/Write)
+
Writing a value of 01h-07h will select Bank 1-7, writing a value of 00h +will select Bank 1 either.
+
+FF6C - Undocumented (FEh) - Bit 0 (Read/Write) - CGB Mode Only
+FF72 - Undocumented (00h) - Bit 0-7 (Read/Write)
+FF73 - Undocumented (00h) - Bit 0-7 (Read/Write)
+FF74 - Undocumented (00h) - Bit 0-7 (Read/Write) - CGB Mode Only
+FF75 - Undocumented (8Fh) - Bit 4-6 (Read/Write)
+FF76 - Undocumented (00h) - Always 00h (Read Only)
+FF77 - Undocumented (00h) - Always 00h (Read Only)
+
These are undocumented CGB Registers. The numbers in brackets () +indicate the initial values. Purpose of these registers is unknown (if +any). Registers FF6C and FF74 are always FFh if the CGB is in Non CGB +Mode.
+
+
+
 SGB Functions

+General Information
+
SGB Description
+SGB Unlocking and Detecting SGB Functions
+SGB Command Packet Transfers
+SGB VRAM Transfers
+SGB Command Summary
+SGB Color Palettes Overview
+
+SGB Commands
+
SGB Palette Commands
+SGB Color Attribute Commands
+SGB Sound Functions
+SGB System Control Commands
+SGB Multiplayer Command
+SGB Border and OBJ Commands
+
+
+
 SGB Description

+General Description
+
Basically, the SGB (Super Gameboy) is an adapter cartridge that allows +to play gameboy games on a SNES (Super Nintendo Entertainment System) +gaming console. In detail, you plug the gameboy cartridge into the SGB +cartridge, then plug the SGB cartridge into the SNES, and then connect +the SNES to your TV Set. In result, games can be played and viewed on +the TV Set, and are controlled by using the SNES joypad(s).
+
+More Technical Description
+
The SGB cartridge just contains a normal gameboy CPU and normal gameboy +video controller. Normally the video signal from this controller would +be sent to the LCD screen, however, in this special case the SNES read +out the video signal and displays it on the TV set by using a special +SNES BIOS ROM which is located in the SGB cartridge. Also, normal +gameboy sound output is forwared to the SNES and output to the TV Set, +vice versa, joypad input is forwared from the SNES controller(s) to the +gameboy joypad inputs.
+
+Normal Monochrome Games
+
Any gameboy games which have been designed for normal monochrome +handheld gameboys will work with the SGB hardware as well. The SGB will +apply a four color palette to these games by replacing the normal four +grayshades. The 160x144 pixel gamescreen is displayed in the middle of +the 256x224 pixel SNES screen (the unused area is filled by a screen +border bitmap). The user may access built-in menues, allowing to change +color palette data, to select between several pre-defined borders, etc.
+
+Games that have been designed to support SGB functions may also access +the following additional features:
+
+Colorized Game Screen
+
There's limited ability to colorize the gamescreen by assigning custom +color palettes to each 20x18 display characters, however, this works +mainly for static display data such like title screens or status bars, +the 20x18 color attribute map is non-scrollable, and it is not possible +to assign separate colors to moveable foreground sprites (OBJs), so that +animated screen regions will be typically restricted to using a single +palette of four colors only.
+
+SNES Foreground Sprites
+
Up to 24 foreground sprites (OBJs) of 8x8 or 16x16 pixels, 16 colors can +be displayed. When replacing (or just overlaying) the normal gameboy +OBJs by SNES OBJs it'd be thus possible to display OBJs with other +colors than normal background area. This method doesn't appear to be +very popular, even though it appears to be quite easy to implement, +however, the bottommost character line of the gamescreen will be masked +out because this area is used to transfer OAM data to the SNES.
+
+The SGB Border
+
The possibly most popular and most impressive feature is to replace the +default SGB screen border by a custom bitmap which is stored in the game +cartridge.
+
+Multiple Joypads
+
Up to four joypads can be conected to the SNES, and SGB software may +read-out each of these joypads separately, allowing up to four players +to play the same game simultaneously. Unlike for multiplayer handheld +games, this requires only one game cartridge and only one SGB/SNES, and +no link cables are required, the downside is that all players must share +the same display screen.
+
+Sound Functions
+
Beside for normal gameboy sound, a number of digital sound effects is +pre-defined in the SNES BIOS, these effects may be accessed quite +easily. Programmers whom are familiar with SNES sounds may also access +the SNES sound chip, or use the SNES MIDI engine directly in order to +produce other sound effects or music.
+
+Taking Control of the SNES CPU
+
Finally, it is possible to write program code or data into SNES memory, +and to execute such program code by using the SNES CPU.
+
+SGB System Clock
+
Because the SGB is synchronized to the SNES CPU, the gameboy system +clock is directly chained to the SNES system clock. In result, the +gameboy CPU, video controller, timers, and sound frequencies will be all +operated approx 2.4% faster as by normal gameboys.
+Basically, this should be no problem, and the game will just run a +little bit faster. However sensitive musicians may notice that sound +frequencies are a bit too high, programs that support SGB functions may +avoid this effect by reducing frequencies of gameboy sounds when having +detected SGB hardware.
+Also, I think that I've heard that SNES models which use a 50Hz display +refresh rate (rather than 60Hz) are resulting in respectively slower +SGB/gameboy timings ???
+
+
+
 SGB Unlocking and Detecting SGB Functions

+Cartridge Header
+
SGB games are required to have a cartridge header with Nintendo and +proper checksum just as normal gameboy games. Also, two special entries +must be set in order to unlock SGB functions:
+
  146h - SGB Flag - Must be set to 03h for SGB games
+  14Bh - Old Licensee Code - Must be set 33h for SGB games
+
When these entries aren't set, the game will still work just like all +'monochrome' gameboy games, but it cannot access any of the special SGB +functions.
+
+Detecting SGB hardware
+
The recommended detection method is to send a MLT_REQ command which +enables two (or four) joypads. A normal handheld gameboy will ignore +this command, a SGB will now return incrementing joypad IDs each time +when deselecting keyboard lines (see MLT_REQ description for details).
+Now read-out joypad state/IDs several times, and if the ID-numbers are +changing, then it is a SGB (a normal gameboy would typically always +return 0Fh as ID). Finally, when not intending to use more than one +joypad, send another MLT_REQ command in order to re-disable the +multi-controller mode.
+Detection works regardless of whether and how many joypads are +physically connected to the SNES. However, detection works only when +having unlocked SGB functions in the cartridge header, as described +above.
+
+Separating between SGB and SGB2
+
It is also possible to separate between SGB and SGB2 models by examining +the inital value of the accumulator (A-register) directly after startup.
+
  01h  SGB or Normal Gameboy (DMG)
+  FFh  SGB2 or Pocket Gameboy
+  11h  CGB or GBA
+
Because values 01h and FFh are shared for both handhelds and SGBs, it is +still required to use the above MLT_REQ detection procedure. As far as I +know the SGB2 doesn't have any extra features which'd require separate +SGB2 detection except for curiosity purposes, for example, the game +"Tetris DX" chooses to display an alternate SGB border on SGB2s.
+
+Reportedly, some SGB models include link ports (just like handheld +gameboy) (my own SGB does not have such an port), possibly this feature +is available in SGB2-type models only ???
+
+
+
 SGB Command Packet Transfers

+Command packets (aka Register Files) are transferred from the gameboy to +the SNES by using P14 and P15 output lines of the JOYPAD register +(FF00h), these lines are normally used to select the two rows in the +gameboy keyboard matrix (which still works).
+
+Transferring Bits
+
A command packet transfer must be initiated by setting both P14 and P15 +to LOW, this will reset and start the SNES packet receiving program. +Data is then transferred (LSB first), setting P14=LOW will indicate a +"0" bit, and setting P15=LOW will indicate a "1" bit. For example:
+
       RESET 0   0   1   1   0   1   0
+  P14  --_---_---_-----------_-------_--...
+  P15  --_-----------_---_-------_------...
+
Data and reset pulses must be kept LOW for at least 5us. P14 and P15 +must be kept both HIGH for at least 15us between any pulses.
+Obviously, it'd be no good idea to access the JOYPAD register during the +transfer, for example, in case that your VBlank interrupt procedure +reads-out joypad states each frame, be sure to disable that interrupt +during the transfer (or disable only the joypad procedure by using a +software flag).
+
+Transferring Packets
+
Each packet is invoked by a RESET pulse, then 128 bits of data are +transferred (16 bytes, LSB of first byte first), and finally, a "0"-bit +must be transferred as stop bit. The structure of normal packets is:
+
   1 PULSE Reset
+   1 BYTE  Command Code*8+Length
+  15 BYTES Parameter Data
+   1 BIT   Stop Bit (0)
+
The above 'Length' indicates the total number of packets (1-7, including +the first packet) which will be sent, ie. if more than 15 parameter +bytes are used, then further packet(s) will follow, as such:
+
   1 PULSE Reset
+  16 BYTES Parameter Data
+   1 BIT   Stop Bit (0)
+
By using all 7 packets, up to 111 data bytes (15+16*6) may be sent.
+Unused bytes at the end of the last packet must be set to zero.
+A 60ms (4 frames) delay should be invoked between each packet transfer.
+
+
+
 SGB VRAM Transfers

+Overview
+
Beside for the packet transfer method, larger data blocks of 4KBytes can +be transferred by using the video signal. These transfers are invoked by +first sending one of the commands with the ending _TRN (by using normal +packet transfer), the 4K data block is then read-out by the SNES from +gameboy display memory during the next frame.
+
+Transfer Data
+
Normally, transfer data should be stored at 8000h-8FFFh in gameboy VRAM,
+even though the SNES receives the data in from display scanlines, it +will automatically re-produce the same ordering of bits and bytes, as +being originally stored at 8000h-8FFFh in gameboy memory.
+
+Preparing the Display
+
The above method works only when recursing the following things: BG Map +must display unsigned characters 00h-FFh on the screen; 00h..13h in +first line, 14h..27h in next line, etc. The gameboy display must be +enabled, the display may not be scrolled, OBJ sprites should not overlap +the background tiles, the BGP palette register must be set to E4h.
+
+Transfer Time
+
Note that the transfer data should be prepared in VRAM <before> sending +the transfer command packet. The actual transfer starts at the beginning +of the next frame after the command has been sent, and the transfer ends +at the end of the 5th frame after the command has been sent (not +counting the frame in which the command has been sent).
+
+Avoiding Screen Garbage
+
The display will contain 'garbage' during the transfer, this dirt-effect +can be avoided by freezing the screen (in the state which has been +displayed before the transfer) by using the MASK_EN command.
+Of course, this works only when actually executing the game on a SGB +(and not on normal handheld gameboys), it'd be thus required to detect +the presence of SGB hardware before blindly sending VRAM data.
+
+
+
 SGB Command Summary

+SGB System Command Table
+
  Code Name      Expl.
+  00   PAL01     Set SGB Palette 0,1 Data
+  01   PAL23     Set SGB Palette 2,3 Data
+  02   PAL03     Set SGB Palette 0,3 Data
+  03   PAL12     Set SGB Palette 1,2 Data
+  04   ATTR_BLK  "Block" Area Designation Mode
+  05   ATTR_LIN  "Line" Area Designation Mode
+  06   ATTR_DIV  "Divide" Area Designation Mode
+  07   ATTR_CHR  "1CHR" Area Designation Mode
+  08   SOUND     Sound On/Off
+  09   SOU_TRN   Transfer Sound PRG/DATA
+  0A   PAL_SET   Set SGB Palette Indirect
+  0B   PAL_TRN   Set System Color Palette Data
+  0C   ATRC_EN   Enable/disable Attraction Mode
+  0D   TEST_EN   Speed Function
+  0E   ICON_EN   SGB Function
+  0F   DATA_SND  SUPER NES WRAM Transfer 1
+  10   DATA_TRN  SUPER NES WRAM Transfer 2
+  11   MLT_REG   Controller 2 Request
+  12   JUMP      Set SNES Program Counter
+  13   CHR_TRN   Transfer Character Font Data
+  14   PCT_TRN   Set Screen Data Color Data
+  15   ATTR_TRN  Set Attribute from ATF
+  16   ATTR_SET  Set Data to ATF
+  17   MASK_EN   Game Boy Window Mask
+  18   OBJ_TRN   Super NES OBJ Mode
+

+
+
 SGB Color Palettes Overview

+Available SNES Palettes
+
The SGB/SNES provides 8 palettes of 16 colors each, each color may be +defined out of a selection of 34768 colors (15 bit). Palettes 0-3 are +used to colorize the gamescreen, only the first four colors of each of +these palettes are used. Palettes 4-7 are used for the SGB Border, all +16 colors of each of these palettes may be used.
+
+Color 0 Restriction
+
Color 0 of each of the eight palettes is transparent, causing the +backdrop color to be displayed instead. The backdrop color is typically +defined by the most recently color being assigned to Color 0 (regardless +of the palette number being used for that operation).
+Effectively, gamescreen palettes can have only three custom colors each, +and SGB border palettes only 15 colors each, additionally, color 0 can +be used for for all palettes, which will then all share the same color +though.
+
+Translation of Grayshades into Colors
+
Because the SGB/SNES reads out the gameboy video controllers display +signal, it translates the different grayshades from the signal into SNES +colors as such:
+
  White       -->  Color 0
+  Light Gray  -->  Color 1
+  Dark Gray   -->  Color 2
+  Black       -->  Color 3
+
Note that gameboy colors 0-3 are assigned to user-selectable grayshades +by the gameboys BGP, OBP1, and OBP2 registers. There is thus no fixed +relationship between gameboy colors 0-3 and SNES colors 0-3.
+
+Using Gameboy BGP/OBP Registers
+
A direct translation of color 0-3 into color 0-3 may be produced by +setting BGP/OBP registers to a value of 0E4h each. However, in case that +your program uses black background for example, then you may internally +assign background as "White" at the gameboy side by BGP/OBP registers +(which is then interpreted as SNES color 0, which is shared for all SNES +palettes). The advantage is that you may define Color 0 as Black at the +SNES side, and may assign custom colors for Colors 1-3 of each SNES +palette.
+
+System Color Palette Memory
+
Beside for the actually visible palettes, up to 512 palettes of 4 colors +each may be defined in SNES RAM. Basically, this is completely +irrelevant because the palettes are just stored in RAM whithout any +relationship to the displayed picture, anyways, these pre-defined colors +may be transferred to actually visible palettes slightly faster as when +transferring palette data by separate command packets.
+
+
+
 SGB Palette Commands

+SGB Command 00h - PAL01
+
Transmit color data for SGB palette 0, color 0-3, and for SGB palette 1, +color 1-3 (without separate color 0).
+
  Byte  Content
+  0     Command*8+Length (fixed length=01h)
+  1-E   Color Data for 7 colors of 2 bytes (16bit) each:
+          Bit 0-4   - Red Intensity   (0-31)
+          Bit 5-9   - Green Intensity (0-31)
+          Bit 10-14 - Blue Intensity  (0-31)
+          Bit 15    - Not used (zero)
+  F     Not used (00h)
+
The value transferred as color 0 will be applied for all eight palettes.
+
+SGB Command 01h - PAL23
+
Same as above PAL01, but for Palettes 2 and 3 respectively.
+
+SGB Command 02h - PAL03
+
Same as above PAL01, but for Palettes 0 and 3 respectively.
+
+SGB Command 03h - PAL12
+
Same as above PAL01, but for Palettes 1 and 2 respectively.
+
+SGB Command 0Ah - PAL_SET
+
Used to copy pre-defined palette data from SGB system color palette to +actual SGB palette.
+
  Byte  Content
+  0     Command*8+Length (fixed length=1)
+  1-2   System Palette number for SGB Color Palette 0 (0-511)
+  3-4   System Palette number for SGB Color Palette 1 (0-511)
+  5-6   System Palette number for SGB Color Palette 2 (0-511)
+  7-8   System Palette number for SGB Color Palette 3 (0-511)
+  9     Attribute File
+          Bit 0-5 - Attribute File Number (00h-2Ch) (Used only if Bit7=1)
+          Bit 6   - Cancel Mask           (0=No change, 1=Yes)
+          Bit 7   - Use Attribute File    (0=No, 1=Apply above ATF Number)
+  A-F   Not used (zero)
+
Before using this function, System Palette data should be initialized by +PAL_TRN command, and (when used) Attribute File data should be +initialized by ATTR_TRN.
+
+SGB Command 0Bh - PAL_TRN
+
Used to initialize SGB system color palettes in SNES RAM.
+System color palette memory contains 512 pre-defined palettes, these +palettes do not directly affect the display, however, the PAL_SET +command may be later used to transfer four of these 'logical' palettes +to actual visible 'physical' SGB palettes. Also, the OBJ_TRN function +will use groups of 4 System Color Palettes (4*4 colors) for SNES OBJ +palettes (16 colors).
+
  Byte  Content
+  0     Command*8+Length (fixed length=1)
+  1-F   Not used (zero)
+
The palette data is sent by VRAM-Transfer (4 KBytes).
+
  000-FFF  Data for System Color Palette 0-511
+
Each Palette consists of four 16bit-color definitions (8 bytes).
+Note: The data is stored at 3000h-3FFFh in SNES memory.
+
+
+
 SGB Color Attribute Commands

+SGB Command 04h - ATTR_BLK
+
Used to specify color attributes for the inside or outside of one or +more rectangular screen regions.
+
  Byte  Content
+  0     Command*8+Length (length=1..7)
+  1     Number of Data Sets (01h..12h)
+  2-7   Data Set #1
+          Byte 0 - Control Code (0-7)
+            Bit 0 - Change Colors inside of surrounded area     (1=Yes)
+            Bit 1 - Change Colors of surrounding character line (1=Yes)
+            Bit 2 - Change Colors outside of surrounded area    (1=Yes)
+            Bit 3-7 - Not used (zero)
+            Exception: When changing only the Inside or Outside, then the
+            Surrounding line becomes automatically changed to same color.
+          Byte 1 - Color Palette Designation
+            Bit 0-1 - Palette Number for inside of surrounded area
+            Bit 2-3 - Palette Number for surrounding character line
+            Bit 4-5 - Palette Number for outside of surrounded area
+            Bit 6-7 - Not used (zero)
+          Data Set Byte 2 - Coordinate X1 (left)
+          Data Set Byte 3 - Coordinate Y1 (upper)
+          Data Set Byte 4 - Coordinate X2 (right)
+          Data Set Byte 5 - Coordinate Y2 (lower)
+            Specifies the coordinates of the surrounding rectangle.
+  8-D   Data Set #2 (if any)
+  E-F   Data Set #3 (continued at 0-3 in next packet) (if any)
+
When sending three or more data sets, data is continued in further +packet(s). Unused bytes at the end of the last packet should be set to +zero. The format of the separate Data Sets is described below.
+
+SGB Command 05h - ATTR_LIN
+
Used to specify color attributes of one or more horizontal or vertical +character lines.
+
  Byte  Content
+  0     Command*8+Length (length=1..7)
+  1     Number of Data Sets (01h..6Eh) (one byte each)
+  2     Data Set #1
+          Bit 0-4 - Line Number    (X- or Y-coordinate, depending on bit 7)
+          Bit 5-6 - Palette Number (0-3)
+          Bit 7   - H/V Mode Bit   (0=Vertical line, 1=Horizontal Line)
+  3     Data Set #2 (if any)
+  4     Data Set #3 (if any)
+  etc.
+
When sending 15 or more data sets, data is continued in further +packet(s). Unused bytes at the end of the last packet should be set to +zero. The format of the separate Data Sets (one byte each) is described +below.
+The length of each line reaches from one end of the screen to the other +end. In case that some lines overlap each other, then lines from +lastmost data sets will overwrite lines from previous data sets.
+
+SGB Command 06h - ATTR_DIV
+
Used to split the screen into two halfes, and to assign separate color +attributes to each half, and to the division line between them.
+
  Byte  Content
+  0     Command*8+Length   (fixed length=1)
+  1     Color Palette Numbers and H/V Mode Bit
+          Bit 0-1  Palette Number below/right of division line
+          Bit 2-3  Palette Number above/left of division line
+          Bit 4-5  Palette Number for division line
+          Bit 6    H/V Mode Bit  (0=split left/right, 1=split above/below)
+  2     X- or Y-Coordinate (depending on H/V bit)
+  3-F   Not used (zero)
+

+SGB Command 07h - ATTR_CHR
+
Used to specify color attributes for separate characters.
+
  Byte  Content
+  0     Command*8+Length (length=1..6)
+  1     Beginning X-Coordinate
+  2     Beginning Y-Coordinate
+  3-4   Number of Data Sets (1-360)
+  5     Writing Style   (0=Left to Right, 1=Top to Bottom)
+  6     Data Sets 1-4   (Set 1 in MSBs, Set 4 in LSBs)
+  7     Data Sets 5-8   (if any)
+  8     Data Sets 9-12  (if any)
+  etc.
+
When sending 41 or more data sets, data is continued in further +packet(s). Unused bytes at the end of the last packet should be set to +zero. Each data set consists of two bits, indicating the palette number +for one character.
+Depending on the writing style, data sets are written from left to +right, or from top to bottom. In either case the function wraps to the +next row/column when reaching the end of the screen.
+
+SGB Command 15h - ATTR_TRN
+
Used to initialize Attribute Files (ATFs) in SNES RAM. Each ATF consists +of 20x18 color attributes for the gameboy screen. This function does not +directly affect display attributes. Instead, one of the defined ATFs may +be copied to actual display memory at a later time by using ATTR_SET or +PAL_SET functions.
+
  Byte  Content
+  0     Command*8+Length (fixed length=1)
+  1-F   Not used (zero)
+
The ATF data is sent by VRAM-Transfer (4 KBytes).
+
  000-FD1  Data for ATF0 through ATF44 (4050 bytes)
+  FD2-FFF  Not used
+
Each ATF consists of 90 bytes, that are 5 bytes (20x2bits) for each of +the 18 character lines of the gameboy window. The two most significant +bits of the first byte define the color attribute (0-3) for the first +character of the first line, the next two bits the next character, and +so on.
+
+SGB Command 16h - ATTR_SET
+
Used to transfer attributes from Attribute File (ATF) to gameboy window.
+
  Byte  Content
+  0     Command*8+Length (fixed length=1)
+  1     Attribute File Number (00-2Ch), Bit 6=Cancel Mask
+  2-F   Not used (zero)
+
When above Bit 6 is set, the gameboy screen becomes re-enabled after the +transfer (in case it has been disabled/frozen by MASK_EN command).
+Note: The same functions may be (optionally) also included in PAL_SET +commands, as described in the chapter about Color Palette Commands.
+
+
+
 SGB Sound Functions

+SGB Command 08h - SOUND
+
Used to start/stop internal sound effect, start/stop sound using +internal tone data.
+
  Byte  Content
+  0     Command*8+Length (fixed length=1)
+  1     Sound Effect A (Port 1) Decrescendo 8bit Sound Code
+  2     Sound Effect B (Port 2) Sustain     8bit Sound Code
+  3     Sound Effect Attributes
+          Bit 0-1 - Sound Effect A Pitch  (0..3=Low..High)
+          Bit 2-3 - Sound Effect A Volume (0..2=High..Low, 3=Mute on)
+          Bit 4-5 - Sound Effect B Pitch  (0..3=Low..High)
+          Bit 6-7 - Sound Effect B Volume (0..2=High..Low, 3=Not used)
+  4     Music Score Code (must be zero if not used)
+  5-F   Not used (zero)
+
See Sound Effect Tables below for a list of available pre-defined effects.
+"Notes"
+1) Mute is only active when both bits D2 and D3 are 1.
+2) When the volume is set for either Sound Effect A or Sound Effect B, +mute is turned off.
+3) When Mute on/off has been executed, the sound fades out/fades in.
+4) Mute on/off operates on the (BGM) which is reproduced by Sound Effect +A, Sound Effect B, and the Super NES APU. A "mute off" flag does not +exist by itself. When mute flag is set, volume and pitch of Sound Effect +A (port 1) and Sound Effect B (port 2) must be set.
+
+SGB Command 09h - SOU_TRN
+
Used to transfer sound code or data to SNES Audio Processing Unit memory +(APU-RAM).
+
  Byte  Content
+  0     Command*8+Length (fixed length=1)
+  1-F   Not used (zero)
+
The sound code/data is sent by VRAM-Transfer (4 KBytes).
+
  000      One (or two ???) 16bit expression(s ???) indicating the
+           transfer destination address and transfer length.
+  ...-...  Transfer Data
+  ...-FFF  Remaining bytes not used
+
Possible destinations in APU-RAM are:
+
  0400h-2AFFh  APU-RAM Program Area (9.75KBytes)
+  2B00h-4AFFh  APU-RAM Sound Score Area (8Kbytes)
+  4DB0h-EEFFh  APU-RAM Sampling Data Area (40.25 Kbytes)
+
This function may be used to take control of the SNES sound chip, and/or +to access the SNES MIDI engine. In either case it requires deeper +knowledge of SNES sound programming.
+
+SGB Sound Effect A/B Tables
+
Below lists the digital sound effects that are pre-defined in the +SGB/SNES BIOS, and which can be used with the SGB "SOUND" Command.
+Effect A and B may be simultaneously reproduced.
+The P-column indicates the recommended Pitch value, the V-column +indicates the numbers of Voices used. Sound Effect A uses voices 6,7. +Sound Effect B uses voices 0,1,4,5. Effects that use less voices will +use only the upper voices (eg. 4,5 for Effect B with only two voices).
+
+Sound Effect A Flag Table
+
  Code Description             P V     Code Description             P V
+  00  Dummy flag, re-trigger   - 2     18  Fast Jump                3 1
+  80  Effect A, stop/silent    - 2     19  Jet (rocket) takeoff     0 1
+  01  Nintendo                 3 1     1A  Jet (rocket) landing     0 1
+  02  Game Over                3 2     1B  Cup breaking             2 2
+  03  Drop                     3 1     1C  Glass breaking           1 2
+  04  OK ... A                 3 2     1D  Level UP                 2 2
+  05  OK ... B                 3 2     1E  Insert air               1 1
+  06  Select...A               3 2     1F  Sword swing              1 1
+  07  Select...B               3 1     20  Water falling            2 1
+  08  Select...C               2 2     21  Fire                     1 1
+  09  Mistake...Buzzer         2 1     22  Wall collapsing          1 2
+  0A  Catch Item               2 2     23  Cancel                   1 2
+  0B  Gate squeaks 1 time      2 2     24  Walking                  1 2
+  0C  Explosion...small        1 2     25  Blocking strike          1 2
+  0D  Explosion...medium       1 2     26  Picture floats on & off  3 2
+  0E  Explosion...large        1 2     27  Fade in                  0 2
+  0F  Attacked...A             3 1     28  Fade out                 0 2
+  10  Attacked...B             3 2     29  Window being opened      1 2
+  11  Hit (punch)...A          0 2     2A  Window being closed      0 2
+  12  Hit (punch)...B          0 2     2B  Big Laser                3 2
+  13  Breath in air            3 2     2C  Stone gate closes/opens  0 2
+  14  Rocket Projectile...A    3 2     2D  Teleportation            3 1
+  15  Rocket Projectile...B    3 2     2E  Lightning                0 2
+  16  Escaping Bubble          2 1     2F  Earthquake               0 2
+  17  Jump                     3 1     30  Small Laser              2 2
+
Sound effect A is used for formanto sounds (percussion sounds).
+
+Sound Effect B Flag Table
+
  Code Description             P V     Code Description             P V
+  00  Dummy flag, re-trigger   - 4     0D  Waterfall                2 2
+  80  Effect B, stop/silent    - 4     0E  Small character running  3 1
+  01  Applause...small group   2 1     0F  Horse running            3 1
+  02  Applause...medium group  2 2     10  Warning sound            1 1
+  03  Applause...large group   2 4     11  Approaching car          0 1
+  04  Wind                     1 2     12  Jet flying               1 1
+  05  Rain                     1 1     13  UFO flying               2 1
+  06  Storm                    1 3     14  Electromagnetic waves    0 1
+  07  Storm with wind/thunder  2 4     15  Score UP                 3 1
+  08  Lightning                0 2     16  Fire                     2 1
+  09  Earthquake               0 2     17  Camera shutter, formanto 3 4
+  0A  Avalanche                0 2     18  Write, formanto          0 1
+  0B  Wave                     0 1     19  Show up title, formanto  0 1
+  0C  River                    3 2
+
Sound effect B is mainly used for looping sounds (sustained sounds).
+
+
+
 SGB System Control Commands

+SGB Command 17h - MASK_EN
+
Used to mask the gameboy window, among others this can be used to freeze +the gameboy screen before transferring data through VRAM (the SNES then +keeps displaying the gameboy screen, even though VRAM doesn't contain +meaningful display information during the transfer).
+
  Byte  Content
+  0     Command*8+Length (fixed length=1)
+  1     Gameboy Screen Mask (0-3)
+          0  Cancel Mask   (Display activated)
+          1  Freeze Screen (Keep displaying current picture)
+          2  Blank Screen  (Black)
+          3  Blank Screen  (Color 0)
+  2-F   Not used (zero)
+
Freezing works only if the SNES has stored a picture, ie. if necessary +wait one or two frames before freezing (rather than freezing directly +after having displayed the picture).
+The Cancel Mask function may be also invoked (optionally) by completion +of PAL_SET and ATTR_SET commands.
+
+SGB Command 0Ch - ATRC_EN
+
Used to enable/disable Attraction mode. It is totally unclear what an +attraction mode is ???, but it is enabled by default.
+
  Byte  Content
+  0     Command*8+Length    (fixed length=1)
+  1     Attraction Disable  (0=Enable, 1=Disable)
+  2-F   Not used (zero)
+

+SGB Command 0Dh - TEST_EN
+
Used to enable/disable test mode for "SGB-CPU variable clock speed +function". This function is disabled by default.
+
  Byte  Content
+  0     Command*8+Length    (fixed length=1)
+  1     Test Mode Enable    (0=Disable, 1=Enable)
+  2-F   Not used (zero)
+
Maybe intended to determine whether SNES operates at 50Hz or 60Hz +display refresh rate ??? Possibly result can be read-out from joypad +register ???
+
+SGB Command 0Eh - ICON_EN
+
Used to enable/disable ICON function. Possibly meant to enable/disable +SGB/SNES popup menues which might otherwise activated during gameboy +game play. By default all functions are enabled (0).
+
  Byte  Content
+  0     Command*8+Length    (fixed length=1)
+  1     Disable Bits
+          Bit 0 - Use of SGB-Built-in Color Palettes    (1=Disable)
+          Bit 1 - Controller Set-up Screen    (0=Enable, 1=Disable)
+          Bit 2 - SGB Register File Transfer (0=Receive, 1=Disable)
+          Bit 3-6 - Not used (zero)
+  2-F   Not used (zero)
+
Above Bit 2 will suppress all further packets/commands when set, this +might be useful when starting a monochrome game from inside of the +SGB-menu of a multi-gamepak which contains a collection of different +games.
+
+SGB Command 0Fh - DATA_SND
+
Used to write one or more bytes directly into SNES Work RAM.
+
  Byte  Content
+  0     Command*8+Length    (fixed length=1)
+  1     SNES Destination Address, low
+  2     SNES Destination Address, high
+  3     SNES Destination Address, bank number
+  4     Number of bytes to write (01h-0Bh)
+  5     Data Byte #1
+  6     Data Byte #2 (if any)
+  7     Data Byte #3 (if any)
+  etc.
+
Unused bytes at the end of the packet should be set to zero, this +function is restricted to a single packet, so that not more than 11 +bytes can be defined at once.
+Free Addresses in SNES memory are Bank 0 1800h-1FFFh, Bank 7Fh +0000h-FFFFh.
+
+SGB Command 10h - DATA_TRN
+
Used to transfer binary code or data directly into SNES RAM.
+
  Byte  Content
+  0     Command*8+Length    (fixed length=1)
+  1     SNES Destination Address, low
+  2     SNES Destination Address, high
+  3     SNES Destination Address, bank number
+  4-F   Not used (zero)
+
The data is sent by VRAM-Transfer (4 KBytes).
+
  000-FFF  Data
+
Free Addresses in SNES memory are Bank 0 1800h-1FFFh, Bank 7Fh +0000h-FFFFh. The transfer length is fixed at 4KBytes ???, so that directly +writing to the free 2KBytes at 0:1800h would be a not so good idea ???
+
+SGB Command 12h - JUMP
+
Used to set the SNES program counter to a specified address. Optionally, +it may be used to set a new address for the SNES NMI handler, the NMI +handler remains unchanged if all bytes 4-6 are zero.
+
  Byte  Content
+  0     Command*8+Length    (fixed length=1)
+  1     SNES Program Counter, low
+  2     SNES Program Counter, high
+  3     SNES Program Counter, bank number
+  4     SNES NMI Handler, low
+  5     SNES NMI Handler, high
+  6     SNES NMI Handler, bank number
+  7-F   Not used, zero
+
Note: The game "Space Invaders 94" uses this function when selecting +"Arcade mode" to execute SNES program code which has been previously +transferred from the SGB to the SNES. The type of the CPU which is used +in the SNES is unknown ???
+
+
+
 SGB Multiplayer Command

+SGB Command 11h - MLT_REQ
+
Used to request multiplayer mode (ie. input from more than one joypad).
+Because this function provides feedback from the SGB/SNES to the gameboy +program, it is also used to detect SGB hardware.
+
  Byte  Content
+  0     Command*8+Length    (fixed length=1)
+  1     Multiplayer Control (0-3) (Bit0=Enable, Bit1=Two/Four Players)
+          0 = One player
+          1 = Two players
+          3 = Four players
+  2-F   Not used (zero)
+
In one player mode, the second joypad (if any) is used for the SGB +system program. In two player mode, both joypads are used for the game. +Because SNES have only two joypad sockets, four player mode requires an +external "Multiplayer 5" adapter.
+
+Reading Multiple Controllers (Joypads)
+
When having enabled multiple controllers by MLT_REQ, data for each +joypad can be read out through JOYPAD register (FF00) as follows: First +set P14 and P15 both HIGH (deselect both Buttons and Cursor keys), you +can now read the lower 4bits of FF00 which indicate the joypad ID for +the following joypad input:
+
  0Fh  Joypad 1
+  0Eh  Joypad 2
+  0Dh  Joypad 3
+  0Ch  Joypad 4
+
Next, set P14 and P15 low (one after each other) to select Buttons and +Cursor lines, and read-out joypad state as normally. When completed, set +P14 and P15 back HIGH, this automatically increments the joypad number +(or restarts counting once reached the lastmost joypad). Repeat the +procedure until you have read-out states for all two (or four) joypads.
+
+
+
 SGB Border and OBJ Commands

+SGB Command 13h - CHR_TRN
+
Used to transfer tile data (characters) to SNES Tile memory in VRAM. This +normally used to define BG tiles for the SGB Border (see PCT_TRN), but +might be also used to define moveable SNES foreground sprites (see +OBJ_TRN).
+
  Byte  Content
+  0     Command*8+Length    (fixed length=1)
+  1     Tile Transfer Destination
+          Bit 0   - Tile Numbers   (0=Tiles 00h-7Fh, 1=Tiles 80h-FFh)
+          Bit 1   - Tile Type      (0=BG Tiles, 1=OBJ Tiles)
+          Bit 2-7 - Not used (zero)
+  2-F   Not used (zero)
+
The tile data is sent by VRAM-Transfer (4 KBytes).
+
  000-FFF  Bitmap data for 128 Tiles
+
Each tile occupies 16bytes (8x8 pixels, 16 colors each).
+When intending to transfer more than 128 tiles, call this function twice +(once for tiles 00h-7Fh, and once for tiles 80h-FFh). Note: The BG/OBJ +Bit seems to have no effect and writes to the same VRAM addresses for +both BG and OBJ ???
+
+SGB Command 14h - PCT_TRN
+
Used to transfer tile map data and palette data to SNES BG Map memory in +VRAM to be used for the SGB border. The actual tiles must be separately +transferred by using the CHR_TRN function.
+
  Byte  Content
+  0     Command*8+Length    (fixed length=1)
+  1-F   Not used (zero)
+
The map data is sent by VRAM-Transfer (4 KBytes).
+
  000-7FF  BG Map 32x32 Entries of 16bit each (2048 bytes)
+  800-87F  BG Palette Data (Palettes 4-7, each 16 colors of 16bits each)
+  880-FFF  Not used, don't care
+
Each BG Map Entry consists of a 16bit value as such:
+
  Bit 0-9   - Character Number (use only 00h-FFh, upper 2 bits zero)
+  Bit 10-12 - Palette Number   (use only 4-7, officially use only 4-6)
+  Bit 13    - BG Priority      (use only 0)
+  Bit 14    - X-Flip           (0=Normal, 1=Mirror horizontally)
+  Bit 15    - Y-Flip           (0=Normal, 1=Mirror vertically)
+
Even though 32x32 map entries are transferred, only upper 32x28 are +actually used (256x224 pixels, SNES screen size). The 20x18 entries in +the center of the 32x28 area should be set to 0000h as transparent space +for the gameboy window to be displayed inside. Reportedly, +non-transparent border data will cover the gameboy window.
+
+SGB Command 18h - OBJ_TRN
+
Used to transfer OBJ attributes to SNES OAM memory. Unlike all other +functions with the ending _TRN, this function does not use the usual +one-shot 4KBytes VRAM transfer method.
+Instead, when enabled (below execute bit set), data is permanently (each +frame) read out from the lower character line of the gameboy screen. To +suppress garbage on the display, the lower line is masked, and only the +upper 20x17 characters of the gameboy window are used - the masking +method is unknwon - frozen, black, or recommended to be covered by the +SGB border, or else ??? Also, when the function is enabled, "system +attract mode is not performed" - whatever that means ???
+
  Byte  Content
+  0     Command*8+Length (fixed length=1)
+  1     Control Bits
+          Bit 0   - SNES OBJ Mode enable (0=Cancel, 1=Enable)
+          Bit 1   - Change OBJ Color     (0=No, 1=Use definitions below)
+          Bit 2-7 - Not used (zero)
+  2-3   System Color Palette Number for OBJ Palette 4 (0-511)
+  4-5   System Color Palette Number for OBJ Palette 5 (0-511)
+  6-7   System Color Palette Number for OBJ Palette 6 (0-511)
+  8-9   System Color Palette Number for OBJ Palette 7 (0-511)
+          These color entries are ignored if above Control Bit 1 is zero.
+          Because each OBJ palette consists of 16 colors, four system
+          palette entries (of 4 colors each) are transferred into each
+          OBJ palette. The system palette numbers are not required to be
+          aligned to a multiple of four, and will wrap to palette number
+          0 when exceeding 511. For example, a value of 511 would copy
+          system palettes 511, 0, 1, 2 to the SNES OBJ palette.
+  A-F   Not used (zero)
+
The recommended method is to "display" gameboy BG tiles F9h..FFh from +left to right as first 7 characters of the bottom-most character line of +the gameboy screen. As for normal 4KByte VRAM transfers, this area +should not be scrolled, should not be overlapped by gameboy OBJs, and +the gameboy BGP palette register should be set up properly. By following +that method, SNES OAM data can be defined in the 70h bytes of the +gameboy BG tile memory at following addresses:
+
  8F90-8FEF  SNES OAM, 24 Entries of 4 bytes each (96 bytes)
+  8FF0-8FF5  SNES OAM MSBs, 24 Entries of 2 bits each (6 bytes)
+  8FF6-8FFF  Not used, don't care (10 bytes)
+
The format of SNES OAM Entries is:
+
  Byte 0  OBJ X-Position (0-511, MSB is separately stored, see below)
+  Byte 1  OBJ Y-Position (0-255)
+  Byte 2-3  Attributes (16bit)
+    Bit 0-8    Tile Number     (use only 00h-FFh, upper bit zero)
+    Bit 9-11   Palette Number  (use only 4-7)
+    Bit 12-13  OBJ Priority    (use only 3)
+    Bit 14     X-Flip          (0=Normal, 1=Mirror horizontally)
+    Bit 15     Y-Flip          (0=Normal, 1=Mirror vertically)
+
The format of SNES OAM MSB Entries is:
+
  Actually, the format is unknown ??? However, 2 bits are used per entry:
+  One bit is the most significant bit of the OBJ X-Position.
+  The other bit specifies the OBJ size (8x8 or 16x16 pixels).
+

+
+
 CPU Registers and Flags

+Registers
+
  16bit Hi   Lo   Name/Function
+  AF    A    -    Accumulator & Flags
+  BC    B    C    BC
+  DE    D    E    DE
+  HL    H    L    HL
+  SP    -    -    Stack Pointer
+  PC    -    -    Program Counter/Pointer
+
As shown above, most registers can be accessed either as one 16bit +register, or as two separate 8bit registers.
+
+The Flag Register (lower 8bit of AF register)
+
  Bit  Name  Set Clr  Expl.
+  7    zf    Z   NZ   Zero Flag
+  6    n     -   -    Add/Sub-Flag (BCD)
+  5    h     -   -    Half Carry Flag (BCD)
+  4    cy    C   NC   Carry Flag
+  3-0  -     -   -    Not used (always zero)
+
Conatins the result from the recent instruction which has affected +flags.
+
+The Zero Flag (Z)
+
This bit becomes set (1) if the result of an operation has been zero +(0). Used for conditional jumps.
+
+The Carry Flag (C, or Cy)
+
Becomes set when the result of an addition became bigger than FFh (8bit) +or FFFFh (16bit). Or when the result of a subtraction or comparision +became less than zero (much as for Z80 and 80x86 CPUs, but unlike as for +65XX and ARM CPUs). Also the flag becomes set when a rotate/shift +operation has shifted-out a "1"-bit.
+Used for conditional jumps, and for instructions such like ADC, SBC, RL, +RLA, etc.
+
+The BCD Flags (N, H)
+
These flags are (rarely) used for the DAA instruction only, N Indicates +whether the previous instruction has been an addition or subtraction, +and H indicates carry for lower 4bits of the result, also for DAA, the C +flag must indicate carry for upper 8bits.
+After adding/subtracting two BCD numbers, DAA is intended to convert the +result into BCD format; BCD numbers are ranged from 00h to 99h rather +than 00h to FFh.
+Because C and H flags must contain carry-outs for each digit, DAA cannot +be used for 16bit operations (which have 4 digits), or for INC/DEC +operations (which do not affect C-flag).
+
+
+
 CPU Instruction Set

+Tables below specify the mnemonic, opcode bytes, clock cycles, affected +flags (ordered as znhc), and explanatation.
+The timings assume a CPU clock frequency of 4.194304 MHz (or 8.4
+MHz for CGB in double speed mode), as all gameboy timings are divideable
+by 4, many people specify timings and clock frequency divided by 4.
+
+GMB 8bit-Loadcommands
+
  ld   r,r         xx         4 ---- r=r
+  ld   r,n         xx nn      8 ---- r=n
+  ld   r,(HL)      xx         8 ---- r=(HL)
+  ld   (HL),r      7x         8 ---- (HL)=r
+  ld   (HL),n      36 nn     12 ----
+  ld   A,(BC)      0A         8 ----
+  ld   A,(DE)      1A         8 ----
+  ld   A,(nn)      FA        16 ----
+  ld   (BC),A      02         8 ----
+  ld   (DE),A      12         8 ----
+  ld   (nn),A      EA        16 ----
+  ld   A,(FF00+n)  F0 nn     12 ---- read from io-port n (memory FF00+n)
+  ld   (FF00+n),A  E0 nn     12 ---- write to io-port n (memory FF00+n)
+  ld   A,(FF00+C)  F2         8 ---- read from io-port C (memory FF00+C)
+  ld   (FF00+C),A  E2         8 ---- write to io-port C (memory FF00+C)
+  ldi  (HL),A      22         8 ---- (HL)=A, HL=HL+1
+  ldi  A,(HL)      2A         8 ---- A=(HL), HL=HL+1
+  ldd  (HL),A      32         8 ---- (HL)=A, HL=HL-1
+  ldd  A,(HL)      3A         8 ---- A=(HL), HL=HL-1
+

+GMB 16bit-Loadcommands
+
  ld   rr,nn       x1 nn nn  12 ---- rr=nn (rr may be BC,DE,HL or SP)
+  ld   SP,HL       F9         8 ---- SP=HL
+  push rr          x5        16 ---- SP=SP-2  (SP)=rr   (rr may be BC,DE,HL,AF)
+  pop  rr          x1        12 (AF) rr=(SP)  SP=SP+2   (rr may be BC,DE,HL,AF)
+

+GMB 8bit-Arithmetic/logical Commands
+
  add  A,r         8x         4 z0hc A=A+r
+  add  A,n         C6 nn      8 z0hc A=A+n
+  add  A,(HL)      86         8 z0hc A=A+(HL)
+  adc  A,r         8x         4 z0hc A=A+r+cy
+  adc  A,n         CE nn      8 z0hc A=A+n+cy
+  adc  A,(HL)      8E         8 z0hc A=A+(HL)+cy
+  sub  r           9x         4 z1hc A=A-r
+  sub  n           D6 nn      8 z1hc A=A-n
+  sub  (HL)        96         8 z1hc A=A-(HL)
+  sbc  A,r         9x         4 z1hc A=A-r-cy
+  sbc  A,n         DE nn      8 z1hc A=A-n-cy
+  sbc  A,(HL)      9E         8 z1hc A=A-(HL)-cy
+  and  r           Ax         4 z010 A=A & r
+  and  n           E6 nn      8 z010 A=A & n
+  and  (HL)        A6         8 z010 A=A & (HL)
+  xor  r           Ax         4 z000
+  xor  n           EE nn      8 z000
+  xor  (HL)        AE         8 z000
+  or   r           Bx         4 z000 A=A | r
+  or   n           F6 nn      8 z000 A=A | n
+  or   (HL)        B6         8 z000 A=A | (HL)
+  cp   r           Bx         4 z1hc compare A-r
+  cp   n           FE nn      8 z1hc compare A-n
+  cp   (HL)        BE         8 z1hc compare A-(HL)
+  inc  r           xx         4 z0h- r=r+1
+  inc  (HL)        34        12 z0h- (HL)=(HL)+1
+  dec  r           xx         4 z1h- r=r-1
+  dec  (HL)        35        12 z1h- (HL)=(HL)-1
+  daa              27         4 z-0x decimal adjust akku
+  cpl              2F         4 -11- A = A xor FF
+

+GMB 16bit-Arithmetic/logical Commands
+
  add  HL,rr     x9           8 -0hc HL = HL+rr     ;rr may be BC,DE,HL,SP
+  inc  rr        x3           8 ---- rr = rr+1      ;rr may be BC,DE,HL,SP
+  dec  rr        xB           8 ---- rr = rr-1      ;rr may be BC,DE,HL,SP
+  add  SP,dd     E8          16 00hc SP = SP +/- dd ;dd is 8bit signed number
+  ld   HL,SP+dd  F8          12 00hc HL = SP +/- dd ;dd is 8bit signed number
+

+GMB Rotate- und Shift-Commands
+
  rlca           07           4 000c rotate akku left
+  rla            17           4 000c rotate akku left through carry
+  rrca           0F           4 000c rotate akku right
+  rra            1F           4 000c rotate akku right through carry
+  rlc  r         CB 0x        8 z00c rotate left
+  rlc  (HL)      CB 06       16 z00c rotate left
+  rl   r         CB 1x        8 z00c rotate left through carry
+  rl   (HL)      CB 16       16 z00c rotate left through carry
+  rrc  r         CB 0x        8 z00c rotate right
+  rrc  (HL)      CB 0E       16 z00c rotate right
+  rr   r         CB 1x        8 z00c rotate right through carry
+  rr   (HL)      CB 1E       16 z00c rotate right through carry
+  sla  r         CB 2x        8 z00c shift left arithmetic (b0=0)
+  sla  (HL)      CB 26       16 z00c shift left arithmetic (b0=0)
+  swap r         CB 3x        8 z000 exchange low/hi-nibble
+  swap (HL)      CB 36       16 z000 exchange low/hi-nibble
+  sra  r         CB 2x        8 z00c shift right arithmetic (b7=b7)
+  sra  (HL)      CB 2E       16 z00c shift right arithmetic (b7=b7)
+  srl  r         CB 3x        8 z00c shift right logical (b7=0)
+  srl  (HL)      CB 3E       16 z00c shift right logical (b7=0)
+

+GMB Singlebit Operation Commands
+
  bit  n,r       CB xx        8 z01- test bit n
+  bit  n,(HL)    CB xx       12 z01- test bit n
+  set  n,r       CB xx        8 ---- set bit n
+  set  n,(HL)    CB xx       16 ---- set bit n
+  res  n,r       CB xx        8 ---- reset bit n
+  res  n,(HL)    CB xx       16 ---- reset bit n
+

+GMB CPU-Controlcommands
+
  ccf            3F           4 -00c cy=cy xor 1
+  scf            37           4 -001 cy=1
+  nop            00           4 ---- no operation
+  halt           76         N*4 ---- halt until interrupt occurs (low power)
+  stop           10 00        ? ---- low power standby mode (VERY low power)
+  di             F3           4 ---- disable interrupts, IME=0
+  ei             FB           4 ---- enable interrupts, IME=1
+

+GMB Jumpcommands
+
  jp   nn        C3 nn nn    16 ---- jump to nn, PC=nn
+  jp   HL        E9           4 ---- jump to HL, PC=HL
+  jp   f,nn      xx nn nn 16;12 ---- conditional jump if nz,z,nc,c
+  jr   PC+dd     18 dd       12 ---- relative jump to nn (PC=PC+/-7bit)
+  jr   f,PC+dd   xx dd     12;8 ---- conditional relative jump if nz,z,nc,c
+  call nn        CD nn nn    24 ---- call to nn, SP=SP-2, (SP)=PC, PC=nn
+  call f,nn      xx nn nn 24;12 ---- conditional call if nz,z,nc,c
+  ret            C9          16 ---- return, PC=(SP), SP=SP+2
+  ret  f         xx        20;8 ---- conditional return if nz,z,nc,c
+  reti           D9          16 ---- return and enable interrupts (IME=1)
+  rst  n         xx          16 ---- call to 00,08,10,18,20,28,30,38
+

+
+
 CPU Comparision with Z80

+Comparision with 8080
+
Basically, the gameboy CPU works more like an older 8080 CPU rather than +like a more powerful Z80 CPU. It is, however, supporting CB-prefixed +instructions. Also, all known gameboy assemblers using the more obvious +Z80-style syntax, rather than the chaotic 8080-style syntax.
+
+Comparision with Z80
+
Any DD-, ED-, and FD-prefixed instructions are missing, that means no +IX-, IY-registers, no block commands, and some other missing commands.
+All exchange instructions have been removed (including total absence of +second register set), 16bit memory accesses are mostly missing, and +16bit arithmetic functions are heavily cut-down.
+The gameboy has no IN/OUT instructions, instead I/O ports are accessed +directly by normal LD instructions, or by special LD (FF00+n) opcodes.
+The sign and parity/overflow flags have been removed.
+The gameboy operates approximately as fast as a 4MHz Z80 (8MHz in CGB +double speed mode), execution time of all instructions has been rounded +up to a multiple of 4 cycles though.
+
+Moved, Removed, and Added Opcodes
+
  Opcode  Z80             GMB
+  ---------------------------------------
+  08      EX   AF,AF      LD   (nn),SP
+  10      DJNZ PC+dd      STOP
+  22      LD   (nn),HL    LDI  (HL),A
+  2A      LD   HL,(nn)    LDI  A,(HL)
+  32      LD   (nn),A     LDD  (HL),A
+  3A      LD   A,(nn)     LDD  A,(HL)
+  D3      OUT  (n),A      -
+  D9      EXX             RETI
+  DB      IN   A,(n)      -
+  DD      <IX>            -
+  E0      RET  PO         LD   (FF00+n),A
+  E2      JP   PO,nn      LD   (FF00+C),A
+  E3      EX   (SP),HL    -
+  E4      CALL P0,nn      -
+  E8      RET  PE         ADD  SP,dd
+  EA      JP   PE,nn      LD   (nn),A
+  EB      EX   DE,HL      -
+  EC      CALL PE,nn      -
+  ED      <pref>          -
+  F0      RET  P          LD   A,(FF00+n)
+  F2      JP   P,nn       LD   A,(FF00+C)
+  F4      CALL P,nn       -
+  F8      RET  M          LD   HL,SP+dd
+  FA      JP   M,nn       LD   A,(nn)
+  FC      CALL M,nn       -
+  FD      <IY>            -
+  CB3X    SLL  r/(HL)     SWAP r/(HL)
+
Note: The unused (-) opcodes will lock-up the gameboy CPU when used.
+
+
+
 The Cartridge Header

+An internal information area is located at 0100-014F in
+each cartridge. It contains the following values:
+
+0100-0103 - Entry Point
+
After displaying the Nintendo Logo, the built-in boot procedure jumps to +this address (100h), which should then jump to the actual main program +in the cartridge. Usually this 4 byte area contains a NOP instruction, +followed by a JP 0150h instruction. But not always.
+
+0104-0133 - Nintendo Logo
+
These bytes define the bitmap of the Nintendo logo that is displayed +when the gameboy gets turned on. The hexdump of this bitmap is:
+
  CE ED 66 66 CC 0D 00 0B 03 73 00 83 00 0C 00 0D
+  00 08 11 1F 88 89 00 0E DC CC 6E E6 DD DD D9 99
+  BB BB 67 63 6E 0E EC CC DD DC 99 9F BB B9 33 3E
+
The gameboys boot procedure verifies the content of this bitmap (after +it has displayed it), and LOCKS ITSELF UP if these bytes are incorrect. +A CGB verifies only the first 18h bytes of the bitmap, but others (for +example a pocket gameboy) verify all 30h bytes.
+
+0134-0143 - Title
+
Title of the game in UPPER CASE ASCII. If it is less than 16 characters +then the remaining bytes are filled with 00's. When inventing the CGB, +Nintendo has reduced the length of this area to 15 characters, and some +months later they had the fantastic idea to reduce it to 11 characters +only. The new meaning of the ex-title bytes is described below.
+
+013F-0142 - Manufacturer Code
+
In older cartridges this area has been part of the Title (see above), in +newer cartridges this area contains an 4 character uppercase +manufacturer code. Purpose and Deeper Meaning unknown.
+
+0143 - CGB Flag
+
In older cartridges this byte has been part of the Title (see above). In +CGB cartridges the upper bit is used to enable CGB functions. This is +required, otherwise the CGB switches itself into Non-CGB-Mode. Typical +values are:
+
  80h - Game supports CGB functions, but works on old gameboys also.
+  C0h - Game works on CGB only (physically the same as 80h).
+
Values with Bit 7 set, and either Bit 2 or 3 set, will switch the +gameboy into a special non-CGB-mode with uninitialized palettes. Purpose +unknown, eventually this has been supposed to be used to colorize +monochrome games that include fixed palette data at a special location +in ROM.
+
+0144-0145 - New Licensee Code
+
Specifies a two character ASCII licensee code, indicating the company or +publisher of the game. These two bytes are used in newer games only +(games that have been released after the SGB has been invented). Older +games are using the header entry at 014B instead.
+
+0146 - SGB Flag
+
Specifies whether the game supports SGB functions, common values are:
+
  00h = No SGB functions (Normal Gameboy or CGB only game)
+  03h = Game supports SGB functions
+
The SGB disables its SGB functions if this byte is set to another value +than 03h.
+
+0147 - Cartridge Type
+
Specifies which Memory Bank Controller (if any) is used in the +cartridge, and if further external hardware exists in the cartridge.
+
  00h  ROM ONLY                 13h  MBC3+RAM+BATTERY
+  01h  MBC1                     15h  MBC4
+  02h  MBC1+RAM                 16h  MBC4+RAM
+  03h  MBC1+RAM+BATTERY         17h  MBC4+RAM+BATTERY
+  05h  MBC2                     19h  MBC5
+  06h  MBC2+BATTERY             1Ah  MBC5+RAM
+  08h  ROM+RAM                  1Bh  MBC5+RAM+BATTERY
+  09h  ROM+RAM+BATTERY          1Ch  MBC5+RUMBLE
+  0Bh  MMM01                    1Dh  MBC5+RUMBLE+RAM
+  0Ch  MMM01+RAM                1Eh  MBC5+RUMBLE+RAM+BATTERY
+  0Dh  MMM01+RAM+BATTERY        FCh  POCKET CAMERA
+  0Fh  MBC3+TIMER+BATTERY       FDh  BANDAI TAMA5
+  10h  MBC3+TIMER+RAM+BATTERY   FEh  HuC3
+  11h  MBC3                     FFh  HuC1+RAM+BATTERY
+  12h  MBC3+RAM
+

+0148 - ROM Size
+
Specifies the ROM Size of the cartridge. Typically calculated as "32KB +shl N".
+
  00h -  32KByte (no ROM banking)
+  01h -  64KByte (4 banks)
+  02h - 128KByte (8 banks)
+  03h - 256KByte (16 banks)
+  04h - 512KByte (32 banks)
+  05h -   1MByte (64 banks)  - only 63 banks used by MBC1
+  06h -   2MByte (128 banks) - only 125 banks used by MBC1
+  07h -   4MByte (256 banks)
+  52h - 1.1MByte (72 banks)
+  53h - 1.2MByte (80 banks)
+  54h - 1.5MByte (96 banks)
+

+0149 - RAM Size
+
Specifies the size of the external RAM in the cartridge (if any).
+
  00h - None
+  01h - 2 KBytes
+  02h - 8 Kbytes
+  03h - 32 KBytes (4 banks of 8KBytes each)
+
When using a MBC2 chip 00h must be specified in this entry, even though +the MBC2 includes a built-in RAM of 512 x 4 bits.
+
+014A - Destination Code
+
Specifies if this version of the game is supposed to be sold in japan, +or anywhere else. Only two values are defined.
+
  00h - Japanese
+  01h - Non-Japanese
+

+014B - Old Licensee Code
+
Specifies the games company/publisher code in range 00-FFh. A value of +33h signalizes that the New License Code in header bytes 0144-0145 is +used instead.
+(Super GameBoy functions won't work if <> $33.)
+
+014C - Mask ROM Version number
+
Specifies the version number of the game. That is usually 00h.
+
+014D - Header Checksum
+
Contains an 8 bit checksum across the cartridge header bytes 0134-014C. +The checksum is calculated as follows:
+
  x=0:FOR i=0134h TO 014Ch:x=x-MEM[i]-1:NEXT
+
The lower 8 bits of the result must be the same than the value in this +entry. The GAME WON'T WORK if this checksum is incorrect.
+
+014E-014F - Global Checksum
+
Contains a 16 bit checksum (upper byte first) across the whole cartridge +ROM. Produced by adding all bytes of the cartridge (except for the two +checksum bytes). The Gameboy doesn't verify this checksum.
+
+
+
 Memory Bank Controllers

+As the gameboys 16 bit address bus offers only limited space for ROM and +RAM addressing, many games are using Memory Bank Controllers (MBCs) to +expand the available address space by bank switching. These MBC chips +are located in the game cartridge (ie. not in the gameboy itself), +several different MBC types are available:
+
+None (32KByte ROM only)
+MBC1 (max 2MByte ROM and/or 32KByte RAM)
+MBC2 (max 256KByte ROM and 512x4 bits RAM)
+MBC3 (max 2MByte ROM and/or 32KByte RAM and Timer)
+HuC1 (MBC with Infrared Controller)
+
+MBC Timing Issues
+
+In each cartridge, the required (or preferred) MBC type should be +specified in byte at 0147h of the ROM. (As described in the chapter +about The Cartridge Header.)
+
+
+
 None (32KByte ROM only)

+Small games of not more than 32KBytes ROM do not require a MBC chip for +ROM banking. The ROM is directly mapped to memory at 0000-7FFFh. +Optionally up to 8KByte of RAM could be connected at A000-BFFF, even +though that could require a tiny MBC-like circuit, but no real MBC chip.
+
+
+
 MBC1 (max 2MByte ROM and/or 32KByte RAM)

+This is the first MBC chip for the gameboy. Any newer MBC chips are +working similiar, so that is relative easy to upgrade a program from one +MBC chip to another - or even to make it compatible to several different +types of MBCs.
+
+Note that the memory in range 0000-7FFF is used for both reading from +ROM, and for writing to the MBCs Control Registers.
+
+0000-3FFF - ROM Bank 00 (Read Only)
+
This area always contains the first 16KBytes of the cartridge ROM.
+
+4000-7FFF - ROM Bank 01-7F (Read Only)
+
This area may contain any of the further 16KByte banks of the ROM, +allowing to address up to 125 ROM Banks (almost 2MByte). As described +below, bank numbers 20h, 40h, and 60h cannot be used, resulting in the +odd amount of 125 banks.
+
+A000-BFFF - RAM Bank 00-03, if any (Read/Write)
+
This area is used to address external RAM in the cartridge (if any). +External RAM is often battery buffered, allowing to store game positions +or high score tables, even if the gameboy is turned off, or if the +cartridge is removed from the gameboy. Available RAM sizes are: 2KByte +(at A000-A7FF), 8KByte (at A000-BFFF), and 32KByte (in form of four 8K +banks at A000-BFFF).
+
+0000-1FFF - RAM Enable (Write Only)
+
Before external RAM can be read or written, it must be enabled by +writing to this address space. It is recommended to disable external RAM +after accessing it, in order to protect its contents from damage during +power down of the gameboy. Usually the following values are used:
+
  00h  Disable RAM (default)
+  0Ah  Enable RAM
+
Practically any value with 0Ah in the lower 4 bits enables RAM, and any +other value disables RAM.
+
+2000-3FFF - ROM Bank Number (Write Only)
+
Writing to this address space selects the lower 5 bits of the ROM Bank +Number (in range 01-1Fh). When 00h is written, the MBC translates that +to bank 01h also. That doesn't harm so far, because ROM Bank 00h can be +always directly accessed by reading from 0000-3FFF.
+But (when using the register below to specify the upper ROM Bank bits), +the same happens for Bank 20h, 40h, and 60h. Any attempt to address +these ROM Banks will select Bank 21h, 41h, and 61h instead.
+
+4000-5FFF - RAM Bank Number - or - Upper Bits of ROM Bank Number (Write Only) +This 2bit register can be used to select a RAM Bank in range from +00-03h, or to specify the upper two bits (Bit 5-6) of the ROM Bank +number, depending on the current ROM/RAM Mode. (See below.)
+
+6000-7FFF - ROM/RAM Mode Select (Write Only)
+
This 1bit Register selects whether the two bits of the above register +should be used as upper two bits of the ROM Bank, or as RAM Bank Number.
+
  00h = ROM Banking Mode (up to 8KByte RAM, 2MByte ROM) (default)
+  01h = RAM Banking Mode (up to 32KByte RAM, 512KByte ROM)
+
The program may freely switch between both modes, the only limitiation +is that only RAM Bank 00h can be used during Mode 0, and only ROM Banks +00-1Fh can be used during Mode 1.
+
+
+
 MBC2 (max 256KByte ROM and 512x4 bits RAM)

+0000-3FFF - ROM Bank 00 (Read Only)
+
Same as for MBC1.
+
+4000-7FFF - ROM Bank 01-0F (Read Only)
+
Same as for MBC1, but only a total of 16 ROM banks is supported.
+
+A000-A1FF - 512x4bits RAM, built-in into the MBC2 chip (Read/Write)
+
The MBC2 doesn't support external RAM, instead it includes 512x4 bits of +built-in RAM (in the MBC2 chip itself). It still requires an external +battery to save data during power-off though.
+As the data consists of 4bit values, only the lower 4 bits of the +"bytes" in this memory area are used.
+
+0000-1FFF - RAM Enable (Write Only)
+
The least significant bit of the upper address byte must be zero to +enable/disable cart RAM. For example the following addresses can be used +to enable/disable cart RAM: 0000-00FF, 0200-02FF, 0400-04FF, ..., +1E00-1EFF.
+The suggested address range to use for MBC2 ram enable/disable is +0000-00FF.
+
+2000-3FFF - ROM Bank Number (Write Only)
+
Writing a value (XXXXBBBB - X = Don't cares, B = bank select bits) into +2000-3FFF area will select an appropriate ROM bank at 4000-7FFF.
+
+The least significant bit of the upper address byte must be one to +select a ROM bank. For example the following addresses can be used to +select a ROM bank: 2100-21FF, 2300-23FF, 2500-25FF, ..., 3F00-3FFF.
+The suggested address range to use for MBC2 rom bank selection is +2100-21FF.
+
+
+
 MBC3 (max 2MByte ROM and/or 32KByte RAM and Timer)

+Beside for the ability to access up to 2MB ROM (128 banks), and 32KB RAM +(4 banks), the MBC3 also includes a built-in Real Time Clock (RTC). The +RTC requires an external 32.768 kHz Quartz Oscillator, and an external +battery (if it should continue to tick when the gameboy is turned off).
+
+0000-3FFF - ROM Bank 00 (Read Only)
+
Same as for MBC1.
+
+4000-7FFF - ROM Bank 01-7F (Read Only)
+
Same as for MBC1, except that accessing banks 20h, 40h, and 60h is +supported now.
+
+A000-BFFF - RAM Bank 00-03, if any (Read/Write)
+A000-BFFF - RTC Register 08-0C (Read/Write)
+
Depending on the current Bank Number/RTC Register selection (see below), +this memory space is used to access an 8KByte external RAM Bank, or a +single RTC Register.
+
+0000-1FFF - RAM and Timer Enable (Write Only)
+
Mostly the same as for MBC1, a value of 0Ah will enable reading and +writing to external RAM - and to the RTC Registers! A value of 00h will +disable either.
+
+2000-3FFF - ROM Bank Number (Write Only)
+
Same as for MBC1, except that the whole 7 bits of the RAM Bank Number +are written directly to this address. As for the MBC1, writing a value +of 00h, will select Bank 01h instead. All other values 01-7Fh select the +corresponding ROM Banks.
+
+4000-5FFF - RAM Bank Number - or - RTC Register Select (Write Only)
+
As for the MBC1s RAM Banking Mode, writing a value in range for 00h-03h +maps the corresponding external RAM Bank (if any) into memory at +A000-BFFF.
+When writing a value of 08h-0Ch, this will map the corresponding RTC +register into memory at A000-BFFF. That register could then be +read/written by accessing any address in that area, typically that is +done by using address A000.
+
+6000-7FFF - Latch Clock Data (Write Only)
+
When writing 00h, and then 01h to this register, the current time +becomes latched into the RTC registers. The latched data will not change +until it becomes latched again, by repeating the write 00h->01h +procedure.
+This is supposed for <reading> from the RTC registers. It is proof to +read the latched (frozen) time from the RTC registers, while the clock +itself continues to tick in background.
+
+The Clock Counter Registers
+
  08h  RTC S   Seconds   0-59 (0-3Bh)
+  09h  RTC M   Minutes   0-59 (0-3Bh)
+  0Ah  RTC H   Hours     0-23 (0-17h)
+  0Bh  RTC DL  Lower 8 bits of Day Counter (0-FFh)
+  0Ch  RTC DH  Upper 1 bit of Day Counter, Carry Bit, Halt Flag
+        Bit 0  Most significant bit of Day Counter (Bit 8)
+        Bit 6  Halt (0=Active, 1=Stop Timer)
+        Bit 7  Day Counter Carry Bit (1=Counter Overflow)
+
The Halt Flag is supposed to be set before <writing> to the RTC +Registers.
+
+The Day Counter
+
The total 9 bits of the Day Counter allow to count days in range from +0-511 (0-1FFh). The Day Counter Carry Bit becomes set when this value +overflows. In that case the Carry Bit remains set until the program does +reset it.
+Note that you can store an offset to the Day Counter in battery RAM. For +example, every time you read a non-zero Day Counter, add this Counter to +the offset in RAM, and reset the Counter to zero. This method allows to +count any number of days, making your program Year-10000-Proof, provided +that the cartridge gets used at least every 511 days.
+
+Delays
+
When accessing the RTC Registers it is recommended to execute a 4ms +delay (4 Cycles in Normal Speed Mode) between the separate accesses.
+
+
+
 HuC1 (MBC with Infrared Controller)

+This controller (made by Hudson Soft) appears to be very similar to an +MBC1 with the main difference being that it supports infrared LED input +/ output. (Similiar to the infrared port that has been later invented in +CGBs.)
+
+The Japanese cart "Fighting Phoenix" (internal cart name: SUPER B DAMAN) +is known to contain this chip.
+
+
+
 MBC Timing Issues

+Using MBCs with CGB Double Speed Mode
+
The MBC5 has been designed to support CGB Double Speed Mode.
+There have been rumours that older MBCs (like MBC1-3) wouldn't be fast +enough in that mode. If so, it might be nethertheless possible to use +Double Speed during periods which use only code and data which is +located in internal RAM.
+However, despite of the above, my own good old selfmade MBC1-EPROM card +appears to work stable and fine even in Double Speed Mode though.
+
+
+
 Gamegenie/Shark Cheats

+Game Shark and Gamegenie are external cartridge adapters that can be +plugged between the gameboy and the actual game cartridge. Hexadecimal +codes can be then entered for specific games, typically providing things +like Infinite Sex, 255 Cigarettes, or Starting directly in Wonderland +Level PRO, etc.
+
+Gamegenie (ROM patches)
+
Gamegenie codes consist of nine-digit hex numbers, formatted as +ABC-DEF-GHI, the meaning of the separate digits is:
+
  AB    New data
+  FCDE  Memory address, XORed by 0F000h
+  GI    Old data, XORed by 0BAh and rotated left by two
+  H     Don't know, maybe checksum and/or else
+
The address should be located in ROM area 0000h-7FFFh, the adapter +permanently compares address/old data with address/data being read by +the game, and replaces that data by new data if necessary. That method +(more or less) prohibits unwanted patching of wrong memory banks. +Eventually it is also possible to patch external RAM ?
+Newer devices reportedly allow to specify only the first six digits +(optionally). As far as I rememeber, around three or four codes can be +used simultaneously.
+
+Game Shark (RAM patches)
+
Game Shark codes consist of eight-digit hex numbers, formatted as +ABCDEFGH, the meaning of the separate digits is:
+
  AB    External RAM bank number
+  CD    New Data
+  GHEF  Memory Address (internal or external RAM, A000-DFFF)
+
As far as I understand, patching is implement by hooking the original +VBlank interrupt handler, and re-writing RAM values each frame. The +downside is that this method steals some CPU time, also, it cannot be +used to patch program code in ROM.
+As far as I rememeber, somewhat 10-25 codes can be used simultaneously.
+
+
+
 Power Up Sequence

+When the GameBoy is powered up, a 256 byte program starting at memory +location 0 is executed. This program is located in a ROM inside the +GameBoy. The first thing the program does is read the cartridge +locations from $104 to $133 and place this graphic of a Nintendo logo on +the screen at the top. This image is then scrolled until it is in the +middle of the screen. Two musical notes are then played on the internal +speaker. Again, the cartridge locations $104 to $133 are read but this +time they are compared with a table in the internal rom. If any byte +fails to compare, then the GameBoy stops comparing bytes and simply +halts all operations. If all locations compare the same, then the +GameBoy starts adding all of the bytes in the cartridge from $134 to +$14d. A value of 25 decimal is added to this total. If the least +significant byte of the result is a not a zero, then the GameBoy will +stop doing anything. If it is a zero, then the internal ROM is disabled +and cartridge program execution begins at location $100 with the +following register values:
+
+
   AF=$01B0
+   BC=$0013
+   DE=$00D8
+   HL=$014D
+   Stack Pointer=$FFFE
+   [$FF05] = $00   ; TIMA
+   [$FF06] = $00   ; TMA
+   [$FF07] = $00   ; TAC
+   [$FF10] = $80   ; NR10
+   [$FF11] = $BF   ; NR11
+   [$FF12] = $F3   ; NR12
+   [$FF14] = $BF   ; NR14
+   [$FF16] = $3F   ; NR21
+   [$FF17] = $00   ; NR22
+   [$FF19] = $BF   ; NR24
+   [$FF1A] = $7F   ; NR30
+   [$FF1B] = $FF   ; NR31
+   [$FF1C] = $9F   ; NR32
+   [$FF1E] = $BF   ; NR33
+   [$FF20] = $FF   ; NR41
+   [$FF21] = $00   ; NR42
+   [$FF22] = $00   ; NR43
+   [$FF23] = $BF   ; NR30
+   [$FF24] = $77   ; NR50
+   [$FF25] = $F3   ; NR51
+   [$FF26] = $F1-GB, $F0-SGB ; NR52
+   [$FF40] = $91   ; LCDC
+   [$FF42] = $00   ; SCY
+   [$FF43] = $00   ; SCX
+   [$FF45] = $00   ; LYC
+   [$FF47] = $FC   ; BGP
+   [$FF48] = $FF   ; OBP0
+   [$FF49] = $FF   ; OBP1
+   [$FF4A] = $00   ; WY
+   [$FF4B] = $00   ; WX
+   [$FFFF] = $00   ; IE
+

+It is not a good idea to assume the above values will always exist. A +later version GameBoy could contain different values than these at +reset. Always set these registers on reset rather than assume they are +as above.
+
+Please note that GameBoy internal RAM on power up contains random data. +All of the GameBoy emulators tend to set all RAM to value $00 on entry.
+
+Cart RAM the first time it is accessed on a real GameBoy contains random +data. It will only contain known data if the GameBoy code initializes it +to some value.
+
+
+
 Reducing Power Consumption

+The following can be used to recude the power consumption of the +gameboy, and to extend the life of the batteries.
+
+PWR Using the HALT Instruction
+PWR Using the STOP Instruction
+PWR Disabeling the Sound Controller
+PWR Not using CGB Double Speed Mode
+PWR Using the Skills
+
+
+
 PWR Using the HALT Instruction

+It is recommended that the HALT instruction be used whenever possible to +reduce power consumption & extend the life of the batteries. This +command stops the system clock reducing the power consumption of both +the CPU and ROM.
+
+The CPU will remain suspended until an interrupt occurs at which point +the interrupt is serviced and then the instruction immediately following +the HALT is executed.
+
+Depending on how much CPU time is required by a game, the HALT +instruction can extend battery life anywhere from 5 to 50% or possibly +more.
+
+When waiting for a vblank event, this would be a BAD example:
+
  @@wait:
+   ld   a,(0FF44h)      ;LY
+   cp   a,144
+   jr   nz,@@wait
+

+A better example would be a procedure as shown below. In this case the +vblank interrupt must be enabled, and your vblank interrupt procedure +must set vblank_flag to a non-zero value.
+
   ld   hl,vblank_flag  ;hl=pointer to vblank_flag
+   xor  a               ;a=0
+  @@wait:               ;wait...
+   halt                 ;suspend CPU - wait for ANY interrupt
+   cp   a,(hl)          ;vblank flag still zero?
+   jr   z,@@wait        ;wait more if zero
+   ld   (hl),a          ;set vblank_flag back to zero
+
The vblank_flag is used to determine whether the HALT period has been +terminated by a vblank interrupt, or by another interrupt. In case that +your program has all other interrupts disabled, then it would be proof +to replace the above procedure by a single HALT instruction.
+
+
+
 PWR Using the STOP Instruction

+The STOP instruction is intended to switch the gameboy into VERY low +power standby mode. For example, a program may use this feature when it +hasn't sensed keyboard input for a longer period (assuming that somebody +forgot to turn off the gameboy).
+
+Before invoking STOP, it might be required to disable Sound and Video +manually (as well as IR-link port in CGB). Much like HALT, the STOP +state is terminated by interrupt events - in this case this would be +commonly a joypad interrupt. The joypad register might be required to be +prepared for STOP either.
+
+
+
 PWR Disabeling the Sound Controller

+If your programs doesn't use sound at all (or during some periods) then +write 00h to register FF26 to save 16% or more on GB power consumption.
+Sound can be turned back on by writing 80h to the same register, all +sound registers must be then re-initialized.
+When the gameboy becomes turned on, sound is enabled by default, and +must be turned off manually when not used.
+
+
+
 PWR Not using CGB Double Speed Mode

+Because CGB Double Speed mode consumes more power, it'd be recommended +to use normal speed when possible.
+There's limited ability to switch between both speeds, for example, a +game might use normal speed in the title screen, and double speed in the +game, or vice versa.
+However, during speed switch the display collapses for a short moment, +so that it'd be no good idea to alter speeds within active game or title +screen periods.
+
+
+
 PWR Using the Skills

+Most of the above power saving methods will produce best results when +using efficient and tight assembler code which requires as less CPU +power as possible. Thus, experienced old-school programmers will +(hopefully) produce lower power consumption, as than HLL-programming +teenagers, for example.
+
+
+
 Sprite RAM Bug

+There is a flaw in the GameBoy hardware that causes trash to be written +to OAM RAM if the following commands are used while their 16-bit content +is in the range of $FE00 to $FEFF:
+
  inc rr        dec rr          ;rr = bc,de, or hl
+  ldi a,(hl)    ldd a,(hl)
+  ldi (hl),a    ldd (hl),a
+
Only sprites 1 & 2 ($FE00 & $FE04) are not affected by these +instructions.
+
+
+
 External Connectors

+Cartridge Slot
+
  Pin   Name    Expl.
+  1     VDD     Power Supply +5V DC
+  2     PHI     System Clock
+  3     /WR     Write
+  4     /RD     Read
+  5     /CS     Chip Select
+  6-21  A0-A15  Address Lines
+  22-29 D0-D7   Data Lines
+  30    /RES    Reset signal
+  31    VIN     External Sound Input
+  32    GND     Ground
+

+Link Port
+
Pin numbers are arranged as 2,4,6 in upper row, 1,3,5 un lower row; +outside view of gameboy socket; flat side of socket upside.
+Colors as used in most or all standard link cables, because SIN and SOUT +are crossed, colors Red and Orange are exchanged at one cable end.
+
  Pin Name Color  Expl.
+  1   VCC  -      +5V DC
+  2   SOUT red    Data Out
+  3   SIN  orange Data In
+  4   P14  -      Not used
+  5   SCK  green  Shift Clock
+  6   GND  blue   Ground
+
Note: The original gameboy used larger plugs (unlike pocket gameboys and +newer), linking between older/newer gameboys is possible by using cables +with one large and one small plug though.
+
+Stereo Sound Connector (3.5mm, female)
+
  Pin     Expl.
+  Tip     Sound Left
+  Middle  Sound Right
+  Base    Ground
+

+External Power Supply
+
...
+
+
+
+
 END
+ \ No newline at end of file diff --git a/Dev Documentation/Ultimate Game Boy Talk.url b/Dev Documentation/Ultimate Game Boy Talk.url new file mode 100644 index 0000000..0b417b6 --- /dev/null +++ b/Dev Documentation/Ultimate Game Boy Talk.url @@ -0,0 +1,5 @@ +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 +[InternetShortcut] +IDList= +URL=https://www.youtube.com/watch?v=HyzD8pNlpwI diff --git a/Dev Documentation/gbctr.pdf b/Dev Documentation/gbctr.pdf new file mode 100644 index 0000000..37148cf Binary files /dev/null and b/Dev Documentation/gbctr.pdf differ diff --git a/Dev Documentation/gbspec.txt b/Dev Documentation/gbspec.txt new file mode 100644 index 0000000..443e1c2 --- /dev/null +++ b/Dev Documentation/gbspec.txt @@ -0,0 +1,1792 @@ +============================================================================ + Everything You Always Wanted To Know About GAMEBOY * +============================================================================ + + * but were afraid to ask + + + Pan of -ATX- Document Updated by contributions from: + Marat Fayzullin, Pascal Felber, Paul Robson, Martin Korth + + Last update 12-Mar-98 by kOOPa + + Forward: The following was typed up for informational purposes regarding + the inner workings on the hand-held game machine known as + GameBoy, manufactured and designed by Nintendo Co., LTD. + This info is presented to inform a user on how their Game Boy + works and what makes it "tick". GameBoy is copyrighted by + Nintendo Co., LTD. Any reference to copyrighted material is + not presented for monetary gain, but for educational purposes + and higher learning. + +Terms +----- + + GB = Original GameBoy + GBP = GameBoy Pocket/GameBoy Light + GBC = GameBoy Color + SGB = Super GameBoy + + +Game Boy Specs +-------------- + + CPU: 8-bit (Similar to the Z80 processor.) + Main RAM: 8K Byte + Video RAM: 8K Byte + Screen Size 2.6" + Resolution: 160x144 (20x18 tiles) + Max # of sprites: 40 + Max # sprites/line: 10 + Max sprite size: 8x16 + Min sprite size: 8x8 + Clock Speed: 4.194304 MHz (4.295454 SGB, 4.194/8.388MHz GBC) + Horiz Sync: 9198 KHz (9420 KHz for SGB) + Vert Sync: 59.73 Hz (61.17 Hz for SGB) + Sound: 4 channels with stereo sound + Power: DC6V 0.7W (DC3V 0.7W for GB Pocket) + + +Processor +--------- + + The GameBoy uses a computer chip similar to an Intel 8080. + It contains all of the instructions of an 8080 except there + are no exchange instructions. In many ways the processor is + more similar to the Zilog Z80 processor. Compared to the + Z80, some instructions have been added and some have been + taken away. + + The following are added instructions: + + ADD SP,nn ;nn = signed byte + LDI (HL),A ;Write A to (HL) and increment HL + LDD (HL),A ;Write A to (HL) and decrement HL + LDI A,(HL) ;Write (HL) to A and increment HL + LDD A,(HL) ;Write (HL) to A and decrement HL + LD A,($FF00+nn) + LD A,($FF00+C) + LD ($FF00+nn),A + LD ($FF00+C),A + LD (nnnn),SP + LD HL,SP+nn ;nn = signed byte + STOP ;Stop processor & screen until button press + SWAP r ;Swap high & low nibbles of r + + The following instructions have been removed: + + Any command that uses the IX or IY registers. + All IN/OUT instructions. + All exchange instructions. + All commands prefixed by ED (except remapped RETI). + All conditional jumps/calls/rets on parity/overflow and sign flag. + + The following instructions have different opcodes: + + LD A,[nnnn] + LD [nnnn],A + RETI + + +General Memory Map* Hardware Write Registers +------------------ ------------------------ + + Interrupt Enable Register + --------------------------- FFFF + Internal RAM + --------------------------- FF80 + Empty but unusable for I/O + --------------------------- FF4C + I/O ports + --------------------------- FF00 + Empty but unusable for I/O + --------------------------- FEA0 + Sprite Attrib Memory (OAM) + --------------------------- FE00 + Echo of 8kB Internal RAM + --------------------------- E000 + 8kB Internal RAM + --------------------------- C000 ------------------------- + 8kB switchable RAM bank / MBC1 ROM/RAM Select + --------------------------- A000 / ------------------------ + 8kB Video RAM / / RAM Bank Select + --------------------------- 8000 --/ / ----------------------- + 16kB switchable ROM bank 6000 ----/ / ROM Bank Select + --------------------------- 4000 ------/ ---------------------- + 16kB ROM bank #0 2000 --------/ RAM Bank enable + --------------------------- 0000 ------------------------------- + + * NOTE: b = bit, B = byte + + +Echo of 8kB Internal RAM +------------------------ + + The addresses E000-FE00 appear to access the internal RAM +the same as C000-DE00. (i.e. If you write a byte to address +E000 it will appear at C000 and E000. Similarly, writing a +byte to C000 will appear at C000 and E000.) + + +User I/O +-------- + + There are no empty spaces in the memory map for +implementing input ports except the switchable RAM bank +area (not an option on the Super Smart Card since it's +RAM bank is always enabled). + + An output only port may be implemented anywhere between +A000-FDFF. If implemented in a RAM area care should be +taken to use an area of RAM not used for anything else. +(FE00 and above can't be used because the CPU doesn't +generate an external /WR for these locations.) + + If you have a cart with an MBC1, a ROM 4Mbit or smaller, +and a RAM 8Kbyte or smaller (or no RAM) then you can use +pins 6 & 7 of the MBC1 for 2 digital output pins for +whatever purpose you wish. To use them you must first +put the MBC1 into 4MbitROM/32KbyteRAM mode by writing +01 to 6000. The two least significant bits you write +to 4000 will then be output to these pins. + + +Reserved Memory Locations +------------------------- + +0000 Restart $00 Address (RST $00 calls this address.) + +0008 Restart $08 Address (RST $08 calls this address.) + +0010 Restart $10 Address (RST $10 calls this address.) + +0018 Restart $18 Address (RST $18 calls this address.) + +0020 Restart $20 Address (RST $20 calls this address.) + +0028 Restart $28 Address (RST $28 calls this address.) + +0030 Restart $30 Address (RST $30 calls this address.) + +0038 Restart $38 Address (RST $38 calls this address.) + +0040 Vertical Blank Interrupt Start Address + +0048 LCDC Status Interrupt Start Address + +0050 Timer Overflow Interrupt Start Address + +0058 Serial Transfer Completion Interrupt Start Address + +0060 High-to-Low of P10-P13 Interrupt Start Address + +An internal information area is located at 0100-014F in +each cartridge. It contains the following values: + +0100-0103 This is the begin code execution point in a + cart. Usually there is a NOP and a JP + instruction here but not always. + +0104-0133 Scrolling Nintendo graphic: + CE ED 66 66 CC 0D 00 0B 03 73 00 83 00 0C 00 0D + 00 08 11 1F 88 89 00 0E DC CC 6E E6 DD DD D9 99 + BB BB 67 63 6E 0E EC CC DD DC 99 9F BB B9 33 3E + ( PROGRAM WON'T RUN IF CHANGED!!!) + +0134-0142 Title of the game in UPPER CASE ASCII. If it + is less than 16 characters then the remaining + bytes are filled with 00's. + +0143 $80 = Color GB, $00 or other = not Color GB + +0144 Ascii hex digit, high nibble of licensee code (new). +0145 Ascii hex digit, low nibble of licensee code (new). + (These are normally $00 if [$014B] <> $33.) + +0146 GB/SGB Indicator (00 = GameBoy, 03 = Super GameBoy functions) + (Super GameBoy functions won't work if <> $03.) + +0147 Cartridge type: + 0 - ROM ONLY 12 - ROM+MBC3+RAM + 1 - ROM+MBC1 13 - ROM+MBC3+RAM+BATT + 2 - ROM+MBC1+RAM 19 - ROM+MBC5 + 3 - ROM+MBC1+RAM+BATT 1A - ROM+MBC5+RAM + 5 - ROM+MBC2 1B - ROM+MBC5+RAM+BATT + 6 - ROM+MBC2+BATTERY 1C - ROM+MBC5+RUMBLE + 8 - ROM+RAM 1D - ROM+MBC5+RUMBLE+SRAM + 9 - ROM+RAM+BATTERY 1E - ROM+MBC5+RUMBLE+SRAM+BATT + B - ROM+MMM01 1F - Pocket Camera + C - ROM+MMM01+SRAM FD - Bandai TAMA5 + D - ROM+MMM01+SRAM+BATT FE - Hudson HuC-3 + F - ROM+MBC3+TIMER+BATT FF - Hudson HuC-1 + 10 - ROM+MBC3+TIMER+RAM+BATT + 11 - ROM+MBC3 + +0148 ROM size: + 0 - 256Kbit = 32KByte = 2 banks + 1 - 512Kbit = 64KByte = 4 banks + 2 - 1Mbit = 128KByte = 8 banks + 3 - 2Mbit = 256KByte = 16 banks + 4 - 4Mbit = 512KByte = 32 banks + 5 - 8Mbit = 1MByte = 64 banks + 6 - 16Mbit = 2MByte = 128 banks + $52 - 9Mbit = 1.1MByte = 72 banks + $53 - 10Mbit = 1.2MByte = 80 banks + $54 - 12Mbit = 1.5MByte = 96 banks + +0149 RAM size: + 0 - None + 1 - 16kBit = 2kB = 1 bank + 2 - 64kBit = 8kB = 1 bank + 3 - 256kBit = 32kB = 4 banks + 4 - 1MBit =128kB =16 banks + +014A Destination code: + 0 - Japanese + 1 - Non-Japanese + +014B Licensee code (old): + 33 - Check 0144/0145 for Licensee code. + 79 - Accolade + A4 - Konami + (Super GameBoy function won't work if <> $33.) + +014C Mask ROM Version number (Usually $00) + +014D Complement check + (PROGRAM WON'T RUN ON GB IF NOT CORRECT!!!) + (It will run on Super GB, however, if incorrect.) + +014E-014F Checksum (higher byte first) produced by + adding all bytes of a cartridge except for two + checksum bytes and taking two lower bytes of + the result. (GameBoy ignores this value.) + + +Cartridge Types +--------------- + +The following define the byte at cart location 0147: + + ROM ONLY + This is a 32kB (256kb) ROM and occupies 0000-7FFF. + + MBC1 (Memory Bank Controller 1) + MBC1 has two different maximum memory modes: + 16Mbit ROM/8KByte RAM or 4Mbit ROM/32KByte RAM. + + The MBC1 defaults to 16Mbit ROM/8KByte RAM mode + on power up. Writing a value (XXXXXXXS - X = Don't + care, S = Memory model select) into 6000-7FFF area + will select the memory model to use. S = 0 selects + 16/8 mode. S = 1 selects 4/32 mode. + + Writing a value (XXXBBBBB - X = Don't cares, B = + bank select bits) into 2000-3FFF area will select an + appropriate ROM bank at 4000-7FFF. Values of 0 and 1 + do the same thing and point to ROM bank 1. Rom bank 0 + is not accessible from 4000-7FFF and can only be read + from 0000-3FFF. + + If memory model is set to 4/32: + Writing a value (XXXXXXBB - X = Don't care, B = + bank select bits) into 4000-5FFF area will select an + appropriate RAM bank at A000-C000. Before you can + read or write to a RAM bank you have to enable it by + writing a XXXX1010 into 0000-1FFF area*. To disable + RAM bank operations write any value but XXXX1010 + into 0000-1FFF area. Disabling a RAM bank probably + protects that bank from false writes during power + down of the GameBoy. (NOTE: Nintendo suggests values + $0A to enable and $00 to disable RAM bank!!) + + If memory model is set to 16/8 mode: + Writing a value (XXXXXXBB - X = Don't care, B = + bank select bits) into 4000-5FFF area will set the + two most significant ROM address lines. + + * NOTE: The Super Smart Card doesn't require this + operation because it's RAM bank is ALWAYS enabled. + Include this operation anyway to allow your code + to work with both. + + MBC2 (Memory Bank Controller 2): + This memory controller works much like the MBC1 + controller with the following exceptions: + + MBC2 will work with ROM sizes up to 2Mbit. + + Writing a value (XXXXBBBB - X = Don't cares, B = + bank select bits) into 2000-3FFF area will select an + appropriate ROM bank at 4000-7FFF. + + RAM switching is not provided. Unlike the MBC1 which + uses external RAM, MBC2 has 512 x 4 bits of RAM which + is in the controller itself. It still requires an + external battery to save data during power-off though. + + The least significant bit of the upper address byte + must be zero to enable/disable cart RAM. For example + the following addresses can be used to enable/disable + cart RAM: + 0000-00FF, 0200-02FF, 0400-04FF, ..., 1E00-1EFF. + The suggested address range to use for MBC2 ram + enable/disable is 0000-00FF. + + The least significant bit of the upper address byte + must be one to select a ROM bank. For example the + following addresses can be used to select a ROM bank: + 2100-21FF, 2300-23FF, 2500-25FF, ..., 3F00-3FFF. + The suggested address range to use for MBC2 rom + bank selection is 2100-21FF. + + MBC3 (Memory Bank Controller 3): + This controller is similar to MBC1 except it accesses + all 16mbits of ROM without requiring any writes to the + 4000-5FFF area. + Writing a value (XBBBBBBB - X = Don't care, B = + bank select bits) into 2000-3FFF area will select an + appropriate ROM bank at 4000-7FFF. + + Also, this MBC has a built-in battery-backed Real + Time Clock (RTC) not found in any other MBC. Some + MBC3 carts do not support it (WarioLand II non-color + version) but some do (Harvest Moon/Japanese version.) + + MBC5 (Memory Bank Controller 5): + This controller is the first MBC that is guaranteed + to run in GameBoy Color double-speed mode but it + appears the other MBC's run fine in GBC double-speed + mode as well. + + It is similar to the MBC3 (but no RTC) but can + access up to 64mbits of ROM and up to 1mbit of RAM. + The lower 8 bits of the 9-bit rom bank select is + written to the 2000-2FFF area while the upper bit + is written to the least significant bit of the + 3000-3FFF area. + + Writing a value (XXXXBBBB - X = Don't care, B = + bank select bits) into 4000-5FFF area will select an + appropriate RAM bank at A000-BFFF if the cart + contains RAM. Ram sizes are 64kbit,256kbit, & 1mbit. + + Also, this is the first MBC that allows rom bank 0 + to appear in the 4000-7FFF range by writing $000 + to the rom bank select. + + Rumble Carts: + Rumble carts use an MBC5 memory bank controller. + Rumble carts can only have up to 256kbits of RAM. + The highest RAM address line that allows 1mbit of + RAM on MBC5 non-rumble carts is used as the motor + on/off for the rumble cart. + + Writing a value (XXXXMBBB - X = Don't care, M = + motor, B = bank select bits) into 4000-5FFF area + will select an appropriate RAM bank at A000-BFFF + if the cart contains RAM. RAM sizes are 64kbit or + 256kbits. To turn the rumble motor on set M = 1, + M = 0 turns it off. + + HuC1 (Memory Bank / Infrared Controller): + This controller made by Hudson Soft appears to be + very similar to an MBC1 with the main difference + being that it supports infrared LED input / output. + The Japanese cart "Fighting Phoenix" (internal cart + name: SUPER B DAMAN) is known to contain this chip. + + + +Power Up Sequence +----------------- + + When the GameBoy is powered up, a 256 byte program + starting at memory location 0 is executed. This program + is located in a ROM inside the GameBoy. The first thing + the program does is read the cartridge locations from + $104 to $133 and place this graphic of a Nintendo logo + on the screen at the top. This image is then scrolled + until it is in the middle of the screen. Two musical + notes are then played on the internal speaker. Again, + the cartridge locations $104 to $133 are read but this + time they are compared with a table in the internal rom. + If any byte fails to compare, then the GameBoy stops + comparing bytes and simply halts all operations. + + GB & GB Pocket: + Next, the GameBoy starts adding all of the bytes + in the cartridge from $134 to $14d. A value of 25 + decimal is added to this total. If the least + significant byte of the result is a not a zero, + then the GameBoy will stop doing anything. + + Super GB: + Even though the GB & GBP check the memory locations + from $134 to $14d, the SGB doesn't. + + If the above checks pass then the internal ROM is + disabled and cartridge program execution begins at + location $100 with the following register values: + + AF=$01-GB/SGB, $FF-GBP, $11-GBC + F =$B0 + BC=$0013 + DE=$00D8 + HL=$014D + Stack Pointer=$FFFE + [$FF05] = $00 ; TIMA + [$FF06] = $00 ; TMA + [$FF07] = $00 ; TAC + [$FF10] = $80 ; NR10 + [$FF11] = $BF ; NR11 + [$FF12] = $F3 ; NR12 + [$FF14] = $BF ; NR14 + [$FF16] = $3F ; NR21 + [$FF17] = $00 ; NR22 + [$FF19] = $BF ; NR24 + [$FF1A] = $7F ; NR30 + [$FF1B] = $FF ; NR31 + [$FF1C] = $9F ; NR32 + [$FF1E] = $BF ; NR33 + [$FF20] = $FF ; NR41 + [$FF21] = $00 ; NR42 + [$FF22] = $00 ; NR43 + [$FF23] = $BF ; NR30 + [$FF24] = $77 ; NR50 + [$FF25] = $F3 ; NR51 + [$FF26] = $F1-GB, $F0-SGB ; NR52 + [$FF40] = $91 ; LCDC + [$FF42] = $00 ; SCY + [$FF43] = $00 ; SCX + [$FF45] = $00 ; LYC + [$FF47] = $FC ; BGP + [$FF48] = $FF ; OBP0 + [$FF49] = $FF ; OBP1 + [$FF4A] = $00 ; WY + [$FF4B] = $00 ; WX + [$FFFF] = $00 ; IE + + It is not a good idea to assume the above values +will always exist. A later version GameBoy could +contain different values than these at reset. +Always set these registers on reset rather than +assume they are as above. + + Please note that GameBoy internal RAM on power up +contains random data. All of the GameBoy emulators +tend to set all RAM to value $00 on entry. + + Cart RAM the first time it is accessed on a real +GameBoy contains random data. It will only contain +known data if the GameBoy code initializes it to +some value. + +Stop Mode +--------- + + The STOP command halts the GameBoy processor + and screen until any button is pressed. The GB + and GBP screen goes white with a single dark + horizontal line. The GBC screen goes black. + + +Low-Power Mode +-------------- + + It is recommended that the HALT instruction be used + whenever possible to reduce power consumption & extend + the life of the batteries. This command stops the + system clock reducing the power consumption of both + the CPU and ROM. + + The CPU will remain suspended until an interrupt + occurs at which point the interrupt is serviced and + then the instruction immediately following the HALT + is executed. If interrupts are disabled (DI) then + halt doesn't suspend operation but it does cause + the program counter to stop counting for one + instruction on the GB,GBP, and SGB as mentioned below. + + Depending on how much CPU time is required by a game, + the HALT instruction can extend battery life anywhere + from 5 to 50% or possibly more. + + WARNING: The instruction immediately following the + HALT instruction is "skipped" when interrupts are + disabled (DI) on the GB,GBP, and SGB. As a result, + always put a NOP after the HALT instruction. This + instruction skipping doesn't occur when interrupts + are enabled (EI). + This "skipping" does not seem to occur on the + GameBoy Color even in regular GB mode. ($143=$00) + + EXAMPLES from Martin Korth who documented this problem: + (assuming interrupts disabled for all examples) + +1) This code causes the 'a' register to be incremented TWICE. + 76 halt + 3C inc a + +2) The next example is a bit more difficult. The following code + 76 halt + FA 34 12 ld a,(1234) + + is effectively executed as + + 76 halt + FA FA 34 ld a,(34FA) + 12 ld (de),a + +3) Finally an interesting side effect + 76 halt + 76 halt + + This combination hangs the cpu. + The first HALT causes the second HALT to be repeated, which + therefore causes the following command (=itself) to be + repeated - again and again. + Placing a NOP between the two halts would cause the NOP to + be repeated once, the second HALT wouldn't lock the cpu. + + Below is suggested code for GameBoy programs: + + ; **** Main Game Loop **** + Main: + halt ; stop system clock + ; return from halt when interrupted + nop ; (See WARNING above.) + + ld a,(VblnkFlag) + or a ; V-Blank interrupt ? + jr z,Main ; No, some other interrupt + + xor a + ld (VblnkFlag),a ; Clear V-Blank flag + + call Controls ; button inputs + call Game ; game operation + + jr Main + + ; **** V-Blank Interrupt Routine **** + Vblnk: + push af + push bc + push de + push hl + + call SpriteDma ; Do sprite updates + + ld a,1 + ld (VblnkFlag),a + + pop hl + pop de + pop bc + pop af + reti + + +Video +----- + + The main GameBoy screen buffer (background) consists + of 256x256 pixels or 32x32 tiles (8x8 pixels each). Only + 160x144 pixels can be displayed on the screen. Registers + SCROLLX and SCROLLY hold the coordinates of background to + be displayed in the left upper corner of the screen. + Background wraps around the screen (i.e. when part of it + goes off the screen, it appears on the opposite side.) + + An area of VRAM known as Background Tile Map contains + the numbers of tiles to be displayed. It is organized as + 32 rows of 32 bytes each. Each byte contains a number of + a tile to be displayed. Tile patterns are taken from the + Tile Data Table located either at $8000-8FFF or + $8800-97FF. In the first case, patterns are numbered with + unsigned numbers from 0 to 255 (i.e. pattern #0 lies at + address $8000). In the second case, patterns have signed + numbers from -128 to 127 (i.e. pattern #0 lies at address + $9000). The Tile Data Table address for the background + can be selected by setting the LCDC register. + + There are two different Background Tile Maps. One is + located from $9800-9Bff. The other from $9C00-9FFF. + Only one of these can be viewed at any one time. The + currently displayed background can be selected by + setting the LCDC register. + + Besides background, there is also a "window" overlaying + the background. The window is not scrollable i.e. it is + always displayed starting from its left upper corner. The + location of a window on the screen can be adjusted via + WNDPOSX and WNDPOSY registers. Screen coordinates of the + top left corner of a window are WNDPOSX-7,WNDPOSY. The + tile numbers for the window are stored in the Tile Data + Table. None of the windows tiles are ever transparent. + Both the Background and the window share the same Tile + Data Table. + + Both background and window can be disabled or enabled + separately via bits in the LCDC register. + + If the window is used and a scan line interrupt disables + it (either by writing to LCDC or by setting WX > 166) + and a scan line interrupt a little later on enables it + then the window will resume appearing on the screen at the + exact position of the window where it left off earlier. + This way, even if there are only 16 lines of useful graphics + in the window, you could display the first 8 lines at the + top of the screen and the next 8 lines at the bottom if + you wanted to do so. + + WX may be changed during a scan line interrupt (to either + cause a graphic distortion effect or to disable the window + (WX>166) ) but changes to WY are not dynamic and won't + be noticed until the next screen redraw. + + The tile images are stored in the Tile Pattern Tables. + Each 8x8 image occupies 16 bytes, where each 2 bytes + represent a line: + + Tile: Image: + + .33333.. .33333.. -> 01111100 -> $7C + 22...22. 01111100 -> $7C + 11...11. 22...22. -> 00000000 -> $00 + 2222222. <-- digits 11000110 -> $C6 + 33...33. represent 11...11. -> 11000110 -> $C6 + 22...22. color 00000000 -> $00 + 11...11. numbers 2222222. -> 00000000 -> $00 + ........ 11111110 -> $FE + 33...33. -> 11000110 -> $C6 + 11000110 -> $C6 + 22...22. -> 00000000 -> $00 + 11000110 -> $C6 + 11...11. -> 11000110 -> $C6 + 00000000 -> $00 + ........ -> 00000000 -> $00 + 00000000 -> $00 + + As it was said before, there are two Tile Pattern Tables + at $8000-8FFF and at $8800-97FF. The first one can be used + for sprites, the background, and the window display. Its + tiles are numbered from 0 to 255. The second table can be + used for the background and the window display and its tiles + are numbered from -128 to 127. + + +Sprites +------ + + GameBoy video controller can display up to 40 sprites + either in 8x8 or in 8x16 pixels. Because of a limitation + of hardware, only ten sprites can be displayed per scan + line. Sprite patterns have the same format as tiles, but + they are taken from the Sprite Pattern Table located at + $8000-8FFF and have unsigned numbering. Sprite + attributes reside in the Sprite Attribute Table (OAM + - Object Attribute Memory) at $FE00-FE9F. OAM is divided + into 40 4-byte blocks each of which corresponds to a sprite. + + In 8x16 sprite mode, the least significant bit of the + sprite pattern number is ignored and treated as 0. + + When sprites with different x coordinate values overlap, + the one with the smaller x coordinate (closer to the left) + will have priority and appear above any others. + + When sprites with the same x coordinate values overlap, + they have priority according to table ordering. (i.e. + $FE00 - highest, $FE04 - next highest, etc.) + + Please note that Sprite X=0, Y=0 hides a sprite. To + display a sprite use the following formulas: + + SpriteScreenPositionX(Upper left corner of sprite) = SpriteX - 8 + SpriteScreenPositionY(Upper left corner of sprite) = SpriteY - 16 + + To display a sprite in the upper left corner of the + screen set sprite X=8, Y=16. + + Only 10 sprites can be displayed on any one line. + When this limit is exceeded, the lower priority sprites + (priorities listed above) won't be displayed. To keep + unused sprites from affecting onscreen sprites set their + Y coordinate to Y=0 or Y=>144+16. Just setting the X + coordinate to X=0 or X=>160+8 on a sprite will hide it + but it will still affect other sprites sharing the same + lines. + + Blocks have the following + format: + + Byte0 Y position on the screen + Byte1 X position on the screen + Byte2 Pattern number 0-255 (Unlike some tile + numbers, sprite pattern numbers are unsigned. + LSB is ignored (treated as 0) in 8x16 mode.) + Byte3 Flags: + + Bit7 Priority + If this bit is set to 0, sprite is displayed + on top of background & window. If this bit + is set to 1, then sprite will be hidden behind + colors 1, 2, and 3 of the background & window. + (Sprite only prevails over color 0 of BG & win.) + Bit6 Y flip + Sprite pattern is flipped vertically if + this bit is set to 1. + Bit5 X flip + Sprite pattern is flipped horizontally if + this bit is set to 1. + Bit4 Palette number + Sprite colors are taken from OBJ1PAL if + this bit is set to 1 and from OBJ0PAL + otherwise. + + +Sprite RAM Bug +-------------- + + There is a flaw in the GameBoy hardware that causes + trash to be written to OAM RAM if the following commands + are used while their 16-bit content is in the range + of $FE00 to $FEFF: + + inc xx (xx = bc,de, or hl) + dec xx + + ldi a,(hl) + ldd a,(hl) + + ldi (hl),a + ldd (hl),a + + Only sprites 1 & 2 ($FE00 & $FE04) are not affected + by these instructions. + + +Sound +----- + + There are two sound channels connected to the output + terminals SO1 and SO2. There is also a input terminal Vin + connected to the cartridge. It can be routed to either of + both output terminals. GameBoy circuitry allows producing + sound in four different ways: + + Quadrangular wave patterns with sweep and envelope functions. + Quadrangular wave patterns with envelope functions. + Voluntary wave patterns from wave RAM. + White noise with an envelope function. + + These four sounds can be controlled independantly and + then mixed separately for each of the output terminals. + + Sound registers may be set at all times while producing + sound. + + When setting the initial value of the envelope and + restarting the length counter, set the initial flag to 1 + and initialize the data. + + Under the following situations the Sound ON flag is + reset and the sound output stops: + + 1. When the sound output is stopped by the length counter. + 2. When overflow occurs at the addition mode while sweep + is operating at sound 1. + + When the Sound OFF flag for sound 3 (bit 7 of NR30) is + set at 0, the cancellation of the OFF mode must be done + by setting the sound OFF flag to 1. By initializing + sound 3, it starts it's function. + + When the All Sound OFF flag (bit 7 of NR52) is set to 0, + the mode registers for sounds 1,2,3, and 4 are reset and + the sound output stops. (NOTE: The setting of each sounds + mode register must be done after the All Sound OFF mode + is cancelled. During the All Sound OFF mode, each sound + mode register cannot be set.) + + NOTE: DURING THE ALL SOUND OFF MODE, GB POWER CONSUMPTION + DROPS BY 16% OR MORE! WHILE YOUR PROGRAMS AREN'T USING + SOUND THEN SET THE ALL SOUND OFF FLAG TO 0. IT DEFAULTS + TO 1 ON RESET. + + These tend to be the two most important equations in + converting between Hertz and GB frequency registers: + (Sounds will have a 2.4% higher frequency on Super GB.) + + gb = 2048 - (131072 / Hz) + + Hz = 131072 / (2048 - gb) + + +Timer +----- + + Sometimes it's useful to have a timer that interrupts at + regular intervals for routines that require periodic or + percise updates. The timer in the GameBoy has a selectable + frequency of 4096, 16384, 65536, or 262144 Hertz. This + frequency increments the Timer Counter (TIMA). When it + overflows, it generates an interrupt. It is then loaded + with the contents of Timer Modulo (TMA). The following + are examples: + + ;This interval timer interrupts 4096 times per second + + ld a,-1 + ld ($FF06),a ;Set TMA to divide clock by 1 + ld a,4 + ld ($FF07),a ;Set clock to 4096 Hertz + + ;This interval timer interrupts 65536 times per second + + ld a,-4 + ld ($FF06),a ;Set TMA to divide clock by 4 + ld a,5 + ld ($FF07),a ;Set clock to 262144 Hertz + + +Serial I/O +---------- + + The serial I/O port on the Gameboy is a very simple setup + and is crude compared to standard RS-232 (IBM-PC) or RS-485 + (Macintosh) serial ports. There are no start or stop bits + so the programmer must be more creative when using this port. + + During a transfer, a byte is shifted in at the same time + that a byte is shifted out. The rate of the shift is deter- + mined by whether the clock source is internal or external. + If internal, the bits are shifted out at a rate of 8192Hz + (122 microseconds) per bit. The most significant bit is + shifted in and out first. + + When the internal clock is selected, it drives the clock + pin on the game link port and it stays high when not used. + During a transfer it will go low eight times to clock + in/out each bit. + + A programmer initates a serial transfer by setting bit 7 + of $FF02. This bit may be read and is automatically set + to 0 at the completion of transfer. After this bit is set, + an interrupt will then occur eight bit clocks later if the + serial interrupt is enabled. + If internal clock is selected and serial interrupt is + enabled, this interrupt occurs 122*8 microseconds later. + If external clock is selected and serial interrupt is + enabled, an interrupt will occur eight bit clocks later. + + Initiating a serial transfer with external clock will + wait forever if no external clock is present. This allows + a certain amount of synchronization with each serial port. + + The state of the last bit shifted out determines the + state of the output line until another transfer takes + place. + + If a serial transfer with internal clock is performed + and no external GameBoy is present, a value of $FF will + be received in the transfer. + + The following code causes $75 to be shifted out the + serial port and a byte to be shifted into $FF01: + + ld a,$75 + ld ($FF01),a + ld a,$81 + ld ($FF02),a + + +Interrupt Procedure +------------------- + + The IME (interrupt master enable) flag is reset by DI and + prohibits all interrupts. It is set by EI and acknowledges + the interrupt setting by the IE register. + + 1. When an interrupt is generated, the IF flag will be set. + 2. If the IME flag is set & the corresponding IE flag is + set, the following 3 steps are performed. + 3. Reset the IME flag and prevent all interrupts. + 4. The PC (program counter) is pushed onto the stack. + 5. Jump to the starting address of the interrupt. + + Resetting of the IF register, which was the cause of the + interrupt, is done by hardware. + + During the interrupt, pushing of registers to be used + should be performed by the interrupt routine. + + Once the interrupt service is in progress, all the + interrupts will be prohibited. However, if the IME flag + and the IE flag are controlled, a number of interrupt + services can be made possible by nesting. + + Return from an interrupt routine can be performed by + either RETI or RET instruction. + + The RETI instruction enables interrupts after doing a + return operation. + + If a RET is used as the final instruction in an interrupt + routine, interrupts will remain disabled unless a EI was + used in the interrupt routine or is used at a later time. + + The interrupt will be acknowledged during opcode fetch + period of each instruction. + + +Interrupt Descriptions +---------------------- + + The following interrupts only occur if they have been + enabled in the Interrupt Enable register ($FFFF) and + if the interrupts have actually been enabled using the + EI instruction. + + V-Blank - + + The V-Blank interrupt occurs ~59.7 times a second + on a regular GB and ~61.1 times a second on a Super + GB (SGB). This interrupt occurs at the beginning of + the V-Blank period. During this period video hardware + is not using video ram so it may be freely accessed. + This period lasts approximately 1.1 milliseconds. + + LCDC Status - + + There are various reasons for this interrupt to occur + as described by the STAT register ($FF40). One very + popular reason is to indicate to the user when the + video hardware is about to redraw a given LCD line. + This can be useful for dynamically controlling the SCX/ + SCY registers ($FF43/$FF42) to perform special video + effects. + + Timer Overflow - + + This interrupt occurs when the TIMA register ($FF05) + changes from $FF to $00. + + Serial Transfer Completion - + + This interrupt occurs when a serial transfer has + completed on the game link port. + + High-to-Low of P10-P13 - + + This interrupt occurs on a transition of any of the + keypad input lines from high to low. Due to the fact + that keypad "bounce"* is virtually always present, + software should expect this interrupt to occur one + or more times for every button press and one or more + times for every button release. + + * - Bounce tends to be a side effect of any button + making or breaking a connection. During these + periods, it is very common for a small amount of + oscillation between high & low states to take place. + +I/O Registers +------------- + +FF00 + Name - P1 + Contents - Register for reading joy pad info + and determining system type. (R/W) + + Bit 7 - Not used + Bit 6 - Not used + Bit 5 - P15 out port + Bit 4 - P14 out port + Bit 3 - P13 in port + Bit 2 - P12 in port + Bit 1 - P11 in port + Bit 0 - P10 in port + + This is the matrix layout for register $FF00: + + + P14 P15 + | | + P10-------O-Right----O-A + | | + P11-------O-Left-----O-B + | | + P12-------O-Up-------O-Select + | | + P13-------O-Down-----O-Start + | | + + Example code: + + Game: Ms. Pacman + Address: $3b1 + + LD A,$20 <- bit 5 = $20 + LD ($FF00),A <- select P14 by setting it low + LD A,($FF00) + LD A,($FF00) <- wait a few cycles + CPL <- complement A + AND $0F <- get only first 4 bits + SWAP A <- swap it + LD B,A <- store A in B + LD A,$10 + LD ($FF00),A <- select P15 by setting it low + LD A,($FF00) + LD A,($FF00) + LD A,($FF00) + LD A,($FF00) + LD A,($FF00) + LD A,($FF00) <- Wait a few MORE cycles + CPL <- complement (invert) + AND $0F <- get first 4 bits + OR B <- put A and B together + + LD B,A <- store A in D + LD A,($FF8B) <- read old joy data from ram + XOR B <- toggle w/current button bit + AND B <- get current button bit back + LD ($FF8C),A <- save in new Joydata storage + LD A,B <- put original value in A + LD ($FF8B),A <- store it as old joy data + + + LD A,$30 <- deselect P14 and P15 + LD ($FF00),A <- RESET Joypad + RET <- Return from Subroutine + + The button values using the above method are such: + $80 - Start $8 - Down + $40 - Select $4 - Up + $20 - B $2 - Left + $10 - A $1 - Right + + Let's say we held down A, Start, and Up. + The value returned in accumulator A would be $94 + + +FF01 + Name - SB + Contents - Serial transfer data (R/W) + + 8 Bits of data to be read/written + +FF02 + Name - SC + Contents - SIO control (R/W) + + Bit 7 - Transfer Start Flag + 0: Non transfer + 1: Start transfer + + Bit 0 - Shift Clock + 0: External Clock (500KHz Max.) + 1: Internal Clock (8192Hz) + + Transfer is initiated by setting the + Transfer Start Flag. This bit may be read + and is automatically set to 0 at the end of + Transfer. + + Transmitting and receiving serial data is + done simultaneously. The received data is + automatically stored in SB. + +FF04 + Name - DIV + Contents - Divider Register (R/W) + + This register is incremented 16384 (~16779 + on SGB) times a second. Writing any value + sets it to $00. +FF05 + Name - TIMA + Contents - Timer counter (R/W) + + This timer is incremented by a clock frequency + specified by the TAC register ($FF07). The timer + generates an interrupt when it overflows. + +FF06 + Name - TMA + Contents - Timer Modulo (R/W) + + When the TIMA overflows, this data will be loaded. + +FF07 + Name - TAC + Contents - Timer Control (R/W) + + Bit 2 - Timer Stop + 0: Stop Timer + 1: Start Timer + + Bits 1+0 - Input Clock Select + 00: 4.096 KHz (~4.194 KHz SGB) + 01: 262.144 KHz (~268.4 KHz SGB) + 10: 65.536 KHz (~67.11 KHz SGB) + 11: 16.384 KHz (~16.78 KHz SGB) + +FF0F + Name - IF + Contents - Interrupt Flag (R/W) + + Bit 4: Transition from High to Low of Pin number P10-P13 + Bit 3: Serial I/O transfer complete + Bit 2: Timer Overflow + Bit 1: LCDC (see STAT) + Bit 0: V-Blank + + The priority and jump address for the above 5 interrupts are: + + Interrupt Priority Start Address + + V-Blank 1 $0040 + LCDC Status 2 $0048 - Modes 0, 1, 2 + LYC=LY coincide (selectable) + Timer Overflow 3 $0050 + Serial Transfer 4 $0058 - when transfer is complete + Hi-Lo of P10-P13 5 $0060 + + * When more than 1 interrupts occur at the same time + only the interrupt with the highest priority can be + acknowledged. When an interrupt is used a '0' should + be stored in the IF register before the IE register + is set. + + +FF10 + Name - NR 10 + Contents - Sound Mode 1 register, Sweep register (R/W) + + Bit 6-4 - Sweep Time + Bit 3 - Sweep Increase/Decrease + 0: Addition (frequency increases) + 1: Subtraction (frequency decreases) + Bit 2-0 - Number of sweep shift (n: 0-7) + + Sweep Time: 000: sweep off - no freq change + 001: 7.8 ms (1/128Hz) + 010: 15.6 ms (2/128Hz) + 011: 23.4 ms (3/128Hz) + 100: 31.3 ms (4/128Hz) + 101: 39.1 ms (5/128Hz) + 110: 46.9 ms (6/128Hz) + 111: 54.7 ms (7/128Hz) + + The change of frequency (NR13,NR14) at each shift + is calculated by the following formula where + X(0) is initial freq & X(t-1) is last freq: + + X(t) = X(t-1) +/- X(t-1)/2^n + +FF11 + Name - NR 11 + Contents - Sound Mode 1 register, Sound length/Wave pattern duty (R/W) + + Only Bits 7-6 can be read. + + Bit 7-6 - Wave Pattern Duty + Bit 5-0 - Sound length data (t1: 0-63) + + Wave Duty: 00: 12.5% ( _--------_--------_-------- ) + 01: 25% ( __-------__-------__------- ) + 10: 50% ( ____-----____-----____----- ) (default) + 11: 75% ( ______---______---______--- ) + + Sound Length = (64-t1)*(1/256) seconds +FF12 + Name - NR 12 + Contents - Sound Mode 1 register, Envelope (R/W) + + Bit 7-4 - Initial volume of envelope + Bit 3 - Envelope UP/DOWN + 0: Attenuate + 1: Amplify + Bit 2-0 - Number of envelope sweep (n: 0-7) + (If zero, stop envelope operation.) + + Initial volume of envelope is from 0 to $F. + Zero being no sound. + + Length of 1 step = n*(1/64) seconds + +FF13 + Name - NR 13 + Contents - Sound Mode 1 register, Frequency lo (W) + + Lower 8 bits of 11 bit frequency (x). + Next 3 bit are in NR 14 ($FF14) + +FF14 + Name - NR 14 + Contents - Sound Mode 1 register, Frequency hi (R/W) + + Only Bit 6 can be read. + + Bit 7 - Initial (when set, sound restarts) + Bit 6 - Counter/consecutive selection + Bit 2-0 - Frequency's higher 3 bits (x) + + Frequency = 4194304/(32*(2048-x)) Hz + = 131072/(2048-x) Hz + + Counter/consecutive Selection + 0 = Regardless of the length data in NR11 + sound can be produced consecutively. + 1 = Sound is generated during the time period + set by the length data in NR11. After this + period the sound 1 ON flag (bit 0 of NR52) + is reset. + +FF16 + Name - NR 21 + Contents - Sound Mode 2 register, Sound Length; Wave Pattern Duty (R/W) + + Only bits 7-6 can be read. + + Bit 7-6 - Wave pattern duty + Bit 5-0 - Sound length data (t1: 0-63) + + Wave Duty: 00: 12.5% ( _--------_--------_-------- ) + 01: 25% ( __-------__-------__------- ) + 10: 50% ( ____-----____-----____----- ) (default) + 11: 75% ( ______---______---______--- ) + + Sound Length = (64-t1)*(1/256) seconds + +FF17 + Name - NR 22 + Contents - Sound Mode 2 register, envelope (R/W) + + Bit 7-4 - Initial volume of envelope + Bit 3 - Envelope UP/DOWN + 0: Attenuate + 1: Amplify + Bit 2-0 - Number of envelope sweep (n: 0-7) + (If zero, stop envelope operation.) + + Initial volume of envelope is from 0 to $F. + Zero being no sound. + + Length of 1 step = n*(1/64) seconds + +FF18 + Name - NR 23 + Contents - Sound Mode 2 register, frequency lo data (W) + + Frequency's lower 8 bits of 11 bit data (x). + Next 3 bits are in NR 14 ($FF19). + +FF19 + Name - NR 24 + Contents - Sound Mode 2 register, frequency hi data (R/W) + + Only bit 6 can be read. + + Bit 7 - Initial (when set, sound restarts) + Bit 6 - Counter/consecutive selection + Bit 2-0 - Frequency's higher 3 bits (x) + + Frequency = 4194304/(32*(2048-x)) Hz + = 131072/(2048-x) Hz + + Counter/consecutive Selection + 0 = Regardless of the length data in NR21 + sound can be produced consecutively. + 1 = Sound is generated during the time period + set by the length data in NR21. After this + period the sound 2 ON flag (bit 1 of NR52) + is reset. + +FF1A + Name - NR 30 + Contents - Sound Mode 3 register, Sound on/off (R/W) + + Only bit 7 can be read + + Bit 7 - Sound OFF + 0: Sound 3 output stop + 1: Sound 3 output OK + +FF1B + Name - NR 31 + Contents - Sound Mode 3 register, sound length (R/W) + + Bit 7-0 - Sound length (t1: 0 - 255) + + Sound Length = (256-t1)*(1/2) seconds + +FF1C + Name - NR 32 + Contents - Sound Mode 3 register, Select output level (R/W) + + Only bits 6-5 can be read + + Bit 6-5 - Select output level + 00: Mute + 01: Produce Wave Pattern RAM Data as it is + (4 bit length) + 10: Produce Wave Pattern RAM data shifted once + to the RIGHT (1/2) (4 bit length) + 11: Produce Wave Pattern RAM data shifted twice + to the RIGHT (1/4) (4 bit length) + + * - Wave Pattern RAM is located from $FF30-$FF3f. + +FF1D + Name - NR 33 + Contents - Sound Mode 3 register, frequency's lower data (W) + + Lower 8 bits of an 11 bit frequency (x). + +FF1E + Name - NR 34 + Contents - Sound Mode 3 register, frequency's higher data (R/W) + + Only bit 6 can be read. + + Bit 7 - Initial (when set, sound restarts) + Bit 6 - Counter/consecutive flag + Bit 2-0 - Frequency's higher 3 bits (x). + + Frequency = 4194304/(64*(2048-x)) Hz + = 65536/(2048-x) Hz + + Counter/consecutive Selection + 0 = Regardless of the length data in NR31 + sound can be produced consecutively. + 1 = Sound is generated during the time period + set by the length data in NR31. After this + period the sound 3 ON flag (bit 2 of NR52) + is reset. + +FF20 + Name - NR 41 + Contents - Sound Mode 4 register, sound length (R/W) + + Bit 5-0 - Sound length data (t1: 0-63) + + Sound Length = (64-t1)*(1/256) seconds + +FF21 + Name - NR 42 + Contents - Sound Mode 4 register, envelope (R/W) + + Bit 7-4 - Initial volume of envelope + Bit 3 - Envelope UP/DOWN + 0: Attenuate + 1: Amplify + Bit 2-0 - Number of envelope sweep (n: 0-7) + (If zero, stop envelope operation.) + + Initial volume of envelope is from 0 to $F. + Zero being no sound. + + Length of 1 step = n*(1/64) seconds + +FF22 + Name - NR 43 + Contents - Sound Mode 4 register, polynomial counter (R/W) + + Bit 7-4 - Selection of the shift clock frequency of the + polynomial counter + Bit 3 - Selection of the polynomial counter's step + Bit 2-0 - Selection of the dividing ratio of frequencies + + Selection of the dividing ratio of frequencies: + 000: f * 1/2^3 * 2 + 001: f * 1/2^3 * 1 + 010: f * 1/2^3 * 1/2 + 011: f * 1/2^3 * 1/3 + 100: f * 1/2^3 * 1/4 + 101: f * 1/2^3 * 1/5 + 110: f * 1/2^3 * 1/6 + 111: f * 1/2^3 * 1/7 f = 4.194304 Mhz + + Selection of the polynomial counter step: + 0: 15 steps + 1: 7 steps + + Selection of the shift clock frequency of the polynomial + counter: + + 0000: dividing ratio of frequencies * 1/2 + 0001: dividing ratio of frequencies * 1/2^2 + 0010: dividing ratio of frequencies * 1/2^3 + 0011: dividing ratio of frequencies * 1/2^4 + : : + : : + : : + 0101: dividing ratio of frequencies * 1/2^14 + 1110: prohibited code + 1111: prohibited code + +FF23 + Name - NR 44 + Contents - Sound Mode 4 register, counter/consecutive; inital (R/W) + + Only bit 6 can be read. + + Bit 7 - Initial (when set, sound restarts) + Bit 6 - Counter/consecutive selection + + Counter/consecutive Selection + 0 = Regardless of the length data in NR41 + sound can be produced consecutively. + 1 = Sound is generated during the time period + set by the length data in NR41. After this + period the sound 4 ON flag (bit 3 of NR52) + is reset. + +FF24 + Name - NR 50 + Contents - Channel control / ON-OFF / Volume (R/W) + + Bit 7 - Vin->SO2 ON/OFF + Bit 6-4 - SO2 output level (volume) (# 0-7) + Bit 3 - Vin->SO1 ON/OFF + Bit 2-0 - SO1 output level (volume) (# 0-7) + + Vin->SO1 (Vin->SO2) + + By synthesizing the sound from sound 1 + through 4, the voice input from Vin + terminal is put out. + 0: no output + 1: output OK + +FF25 + Name - NR 51 + Contents - Selection of Sound output terminal (R/W) + + Bit 7 - Output sound 4 to SO2 terminal + Bit 6 - Output sound 3 to SO2 terminal + Bit 5 - Output sound 2 to SO2 terminal + Bit 4 - Output sound 1 to SO2 terminal + Bit 3 - Output sound 4 to SO1 terminal + Bit 2 - Output sound 3 to SO1 terminal + Bit 1 - Output sound 2 to SO1 terminal + Bit 0 - Output sound 1 to SO1 terminal + +FF26 + Name - NR 52 (Value at reset: $F1-GB, $F0-SGB) + Contents - Sound on/off (R/W) + + Bit 7 - All sound on/off + 0: stop all sound circuits + 1: operate all sound circuits + Bit 3 - Sound 4 ON flag + Bit 2 - Sound 3 ON flag + Bit 1 - Sound 2 ON flag + Bit 0 - Sound 1 ON flag + + Bits 0 - 3 of this register are meant to + be status bits to be read. Writing to these + bits does NOT enable/disable sound. + + If your GB programs don't use sound then + write $00 to this register to save 16% or + more on GB power consumption. +FF30 - FF3F + Name - Wave Pattern RAM + Contents - Waveform storage for arbitrary sound data + + This storage area holds 32 4-bit samples + that are played back upper 4 bits first. + +FF40 + Name - LCDC (value $91 at reset) + Contents - LCD Control (R/W) + + Bit 7 - LCD Control Operation * + 0: Stop completely (no picture on screen) + 1: operation + + Bit 6 - Window Tile Map Display Select + 0: $9800-$9BFF + 1: $9C00-$9FFF + + Bit 5 - Window Display + 0: off + 1: on + + Bit 4 - BG & Window Tile Data Select + 0: $8800-$97FF + 1: $8000-$8FFF <- Same area as OBJ + + Bit 3 - BG Tile Map Display Select + 0: $9800-$9BFF + 1: $9C00-$9FFF + + Bit 2 - OBJ (Sprite) Size + 0: 8*8 + 1: 8*16 (width*height) + + Bit 1 - OBJ (Sprite) Display + 0: off + 1: on + + Bit 0 - BG Display + 0: off + 1: on + + * - Stopping LCD operation (bit 7 from 1 to 0) + must be performed during V-blank to work + properly. V-blank can be confirmed when the + value of LY is greater than or equal to 144. + +FF41 + Name - STAT + Contents - LCDC Status (R/W) + + Bits 6-3 - Interrupt Selection By LCDC Status + + Bit 6 - LYC=LY Coincidence (Selectable) + Bit 5 - Mode 10 + Bit 4 - Mode 01 + Bit 3 - Mode 00 + 0: Non Selection + 1: Selection + + Bit 2 - Coincidence Flag + 0: LYC not equal to LCDC LY + 1: LYC = LCDC LY + + Bit 1-0 - Mode Flag + 00: During H-Blank + 01: During V-Blank + 10: During Searching OAM-RAM + 11: During Transfering Data to LCD Driver + + STAT shows the current status of the LCD controller. + Mode 00: When the flag is 00 it is the H-Blank period + and the CPU can access the display RAM + ($8000-$9FFF). + + Mode 01: When the flag is 01 it is the V-Blank period + and the CPU can access the display RAM + ($8000-$9FFF). + + Mode 10: When the flag is 10 then the OAM is being + used ($FE00-$FE9F). The CPU cannot access + the OAM during this period + + Mode 11: When the flag is 11 both the OAM and display + RAM are being used. The CPU cannot access + either during this period. + + + The following are typical when the display is enabled: + +Mode 0 000___000___000___000___000___000___000________________ +Mode 1 _______________________________________11111111111111__ +Mode 2 ___2_____2_____2_____2_____2_____2___________________2_ +Mode 3 ____33____33____33____33____33____33__________________3 + + + The Mode Flag goes through the values 0, 2, + and 3 at a cycle of about 109uS. 0 is present + about 48.6uS, 2 about 19uS, and 3 about 41uS. This + is interrupted every 16.6ms by the VBlank (1). + The mode flag stays set at 1 for about 1.08 ms. + (Mode 0 is present between 201-207 clks, 2 about + 77-83 clks, and 3 about 169-175 clks. A complete + cycle through these states takes 456 clks. + VBlank lasts 4560 clks. A complete screen refresh + occurs every 70224 clks.) + +FF42 + Name - SCY + Contents - Scroll Y (R/W) + + 8 Bit value $00-$FF to scroll BG Y screen + position. + +FF43 + Name - SCX + Contents - Scroll X (R/W) + + 8 Bit value $00-$FF to scroll BG X screen + position. + +FF44 + Name - LY + Contents - LCDC Y-Coordinate (R) + + The LY indicates the vertical line to which + the present data is transferred to the LCD + Driver. The LY can take on any value between + 0 through 153. The values between 144 and 153 + indicate the V-Blank period. Writing will + reset the counter. + +FF45 + Name - LYC + Contents - LY Compare (R/W) + + The LYC compares itself with the LY. If the + values are the same it causes the STAT to set + the coincident flag. + +FF46 + Name - DMA + Contents - DMA Transfer and Start Address (W) + + The DMA Transfer (40*28 bit) from internal ROM or RAM + ($0000-$F19F) to the OAM (address $FE00-$FE9F) can be + performed. It takes 160 microseconds for the transfer. + + 40*28 bit = #140 or #$8C. As you can see, it only + transfers $8C bytes of data. OAM data is $A0 bytes + long, from $0-$9F. + + But if you examine the OAM data you see that 4 bits are + not in use. + + 40*32 bit = #$A0, but since 4 bits for each OAM is not + used it's 40*28 bit. + + It transfers all the OAM data to OAM RAM. + + The DMA transfer start address can be designated every + $100 from address $0000-$F100. That means $0000, $0100, + $0200, $0300.... + + As can be seen by looking at register $FF41 Sprite RAM + ($FE00 - $FE9F) is not always available. A simple routine + that many games use to write data to Sprite memory is shown + below. Since it copies data to the sprite RAM at the appro- + priate times it removes that responsibility from the main + program. + All of the memory space, except high ram ($FF80-$FFFE), + is not accessible during DMA. Because of this, the routine + below must be copied & executed in high ram. It is usually + called from a V-blank Interrupt. + + Example program: + + org $40 + jp VBlank + + org $ff80 +VBlank: + push af <- Save A reg & flags + ld a,BASE_ADRS <- transfer data from BASE_ADRS + ld ($ff46),a <- put A into DMA registers + ld a,28h <- loop length +Wait: <- We need to wait 160 microseconds. + dec a <- 4 cycles - decrease A by 1 + jr nz,Wait <- 12 cycles - branch if Not Zero to Wait + pop af <- Restore A reg & flags + reti <- Return from interrupt + + +FF47 + Name - BGP + Contents - BG & Window Palette Data (R/W) + + Bit 7-6 - Data for Dot Data 11 (Normally darkest color) + Bit 5-4 - Data for Dot Data 10 + Bit 3-2 - Data for Dot Data 01 + Bit 1-0 - Data for Dot Data 00 (Normally lightest color) + + This selects the shade of grays to use for + the background (BG) & window pixels. Since + each pixel uses 2 bits, the corresponding + shade will be selected from here. + +FF48 + Name - OBP0 + Contents - Object Palette 0 Data (R/W) + + This selects the colors for sprite palette 0. + It works exactly as BGP ($FF47) except each + each value of 0 is transparent. + +FF49 + Name - OBP1 + Contents - Object Palette 1 Data (R/W) + + This Selects the colors for sprite palette 1. + It works exactly as OBP0 ($FF48). + See BGP for details. + +FF4A + Name - WY + Contents - Window Y Position (R/W) + + 0 <= WY <= 143 + + WY must be greater than or equal to 0 and + must be less than or equal to 143 for + window to be visible. + +FF4B + Name - WX + Contents - Window X Position (R/W) + + 0 <= WX <= 166 + + WX must be greater than or equal to 0 and + must be less than or equal to 166 for + window to be visible. + + WX is offset from absolute screen coordinates + by 7. Setting the window to WX=7, WY=0 will + put the upper left corner of the window at + absolute screen coordinates 0,0. + + + Lets say WY = 70 and WX = 87. + The window would be positioned as so: + + 0 80 159 + ______________________________________ + 0 | | + | | | + | | + | Background Display | + | Here | + | | + | | + 70 | - +------------------| + | | 80,70 | + | | | + | | Window Display | + | | Here | + | | | + | | | + 143 |___________________|__________________| + + + OBJ Characters (Sprites) can still enter the + window. None of the window colors are + transparent so any background tiles under the + window are hidden. + +FFFF + Name - IE + Contents - Interrupt Enable (R/W) + + Bit 4: Transition from High to Low of Pin + number P10-P13. + Bit 3: Serial I/O transfer complete + Bit 2: Timer Overflow + Bit 1: LCDC (see STAT) + Bit 0: V-Blank + + 0: disable + 1: enable + + + + + diff --git a/MCEmuCore.CPU/Class1.cs b/MCEmuCore.CPU/Class1.cs new file mode 100644 index 0000000..8eb79cb --- /dev/null +++ b/MCEmuCore.CPU/Class1.cs @@ -0,0 +1,8 @@ +using System; + +namespace MCEmuCore.CPU +{ + public class Class1 + { + } +} diff --git a/MCEmuCore.CPU/MCEmuCore.CPU.csproj b/MCEmuCore.CPU/MCEmuCore.CPU.csproj new file mode 100644 index 0000000..c16c6d5 --- /dev/null +++ b/MCEmuCore.CPU/MCEmuCore.CPU.csproj @@ -0,0 +1,7 @@ + + + + netcoreapp2.2 + + + diff --git a/MCEmuCore.Console/MCEmuCore.Console.csproj b/MCEmuCore.Console/MCEmuCore.Console.csproj new file mode 100644 index 0000000..c52b93a --- /dev/null +++ b/MCEmuCore.Console/MCEmuCore.Console.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp2.2 + + + \ No newline at end of file diff --git a/MCEmuCore.Console/Program.cs b/MCEmuCore.Console/Program.cs new file mode 100644 index 0000000..ff2c446 --- /dev/null +++ b/MCEmuCore.Console/Program.cs @@ -0,0 +1,13 @@ +using System; + +namespace MCEmuCore.Console +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + Console.ReadLine(); + } + } +} \ No newline at end of file diff --git a/MCEmuCore.GBMonolith/Cpu.cs b/MCEmuCore.GBMonolith/Cpu.cs new file mode 100644 index 0000000..4433798 --- /dev/null +++ b/MCEmuCore.GBMonolith/Cpu.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; + +namespace MCEmuCore.GBMonolith +{ + public struct OpCode + { + public readonly byte Instruction; + public byte? Arg1; + public byte? Arg2; + } + class Cpu + { + const byte ZERO_FLAG = 0b10000000; + const byte SUB_FLAG = 0b01000000; + const byte HALF_CARRY = 0b00100000; + const byte FULL_CARRY = 0b00010000; + private readonly CpuRegisters registers; + #region OpCodes + + private readonly Dictionary> OpCodeTable; + #endregion + + public Cpu() + { + registers = new CpuRegisters(); + + OpCodeTable = new Dictionary>() + { + {0x00, (op) => { + registers.PC += 1; + return true; + } }, + {0x01, (op) => + { + // LD BC,d16 + if (op.Arg1.HasValue && op.Arg2.HasValue) + { + ushort operand = (ushort)(op.Arg2 + (op.Arg1 << 8)); + registers.BC = operand; + registers.PC += 3; + return true; + } + else + { + throw new InvalidOperationException(op, "Missing arguments for LD BC"); + } + } }, + {0x02, (op) => + { + // LD (BC), A + throw new NotImplementedException("LD (BC), A"); + } }, + {0x03, (op) => + { + registers.BC += 1; + registers.PC += 1; + return true; + } }, + {0x04, (op) => + { + // INC B + byte reg = (byte)(registers.B + 1); + registers.B = reg; + + registers.Flags.Subtract = false; + registers.Flags.Zero = reg == 0; + registers.Flags.HalfCarry = reg == 16; + + registers.PC += 1; + return true; + } } + }; + } + } + + + [Serializable] + public class InvalidOperationException : Exception + { + public OpCode OpCode { get; set; } + public InvalidOperationException() { } + public InvalidOperationException(OpCode opCode, string message) : base(message) + { + OpCode = opCode; + } + public InvalidOperationException(string message) : base(message) { } + public InvalidOperationException(string message, Exception inner) : base(message, inner) { } + protected InvalidOperationException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base(info, context) { } + } +} diff --git a/MCEmuCore.GBMonolith/CpuRegisters.cs b/MCEmuCore.GBMonolith/CpuRegisters.cs new file mode 100644 index 0000000..86d3aa5 --- /dev/null +++ b/MCEmuCore.GBMonolith/CpuRegisters.cs @@ -0,0 +1,308 @@ +using System; +using System.Collections.Generic; + +namespace MCEmuCore.GBMonolith +{ + class CpuRegisters + { + enum Register { A, B, C, D, E, H, L }; + private readonly byte[] Registers = new byte[7]; + public readonly FlagRegister Flags = new FlagRegister(); + + #region Register Accessors + public byte A + { + get + { + return Registers[(int)Register.A]; + } + set + { + Registers[(int)Register.A] = value; + } + } + public byte B + { + get + { + return Registers[(int)Register.B]; + } + set + { + Registers[(int)Register.B] = value; + } + } + public byte D + { + get + { + return Registers[(int)Register.D]; + } + set + { + Registers[(int)Register.D] = value; + } + } + public byte H + { + get + { + return Registers[(int)Register.H]; + } + set + { + Registers[(int)Register.H] = value; + } + } + public byte F + { + get + { + return Flags.Value; + } + set + { + Flags.Value = value; + } + } + public byte C + { + get + { + return Registers[(int)Register.C]; + } + set + { + Registers[(int)Register.C] = value; + } + } + public byte E + { + get + { + return Registers[(int)Register.E]; + } + set + { + Registers[(int)Register.E] = value; + } + } + public byte L + { + get + { + return Registers[(int)Register.L]; + } + set + { + Registers[(int)Register.L] = value; + } + } + #endregion + + #region Wide Register Accessors + public ushort AF + { + get + { + ushort retVal = Flags.Value; + retVal += (ushort)((Registers[(int)Register.A]) << 8); + return retVal; + } + set + { + Flags.Value = (byte)(value & 0x00FF); + Registers[(int)Register.A] = (byte)((value & 0xFF00) >> 8); + } + } + public ushort BC + { + get + { + ushort retVal = Registers[(int)Register.C]; + retVal += (ushort)((Registers[(int)Register.B]) << 8); + return retVal; + } + set + { + Registers[(int)Register.C] = (byte)(value & 0x00FF); + Registers[(int)Register.B] = (byte)((value & 0xFF00) >> 8); + } + } + public ushort DE + { + get + { + ushort retVal = Registers[(int)Register.E]; + retVal += (ushort)((Registers[(int)Register.D]) << 8); + return retVal; + } + set + { + Registers[(int)Register.E] = (byte)(value & 0x00FF); + Registers[(int)Register.D] = (byte)((value & 0xFF00) >> 8); + } + } + public ushort HL + { + get + { + ushort retVal = Registers[(int)Register.L]; + retVal += (ushort)((Registers[(int)Register.H]) << 8); + return retVal; + } + set + { + Registers[(int)Register.L] = (byte)(value & 0x00FF); + Registers[(int)Register.H] = (byte)((value & 0xFF00) >> 8); + } + } + #endregion + + public ushort SP { get; set; } + public ushort PC { get; set; } + + #region Constructors + public CpuRegisters() + { + AF = 0x01B0; + BC = 0x0013; + DE = 0x00D8; + HL = 0x014D; + } + public CpuRegisters(ushort initValue) : base() + { + AF = initValue; + BC = initValue; + DE = initValue; + HL = initValue; + } + public CpuRegisters(byte A, byte F, ushort SP, ushort PC) + { + this.A = A; + this.F = F; + this.SP = SP; + this.PC = PC; + } + public CpuRegisters(byte A, byte F, byte B, byte C, byte D, byte E, byte H, byte L, ushort SP, ushort PC) : this(A, F, SP, PC) + { + this.B = B; + this.C = C; + this.D = D; + this.E = E; + this.H = H; + this.L = L; + } + public CpuRegisters(byte A, byte F, ushort BC, ushort DE, ushort HL, ushort SP, ushort PC) : this(A, F, SP, PC) + { + this.BC = BC; + this.DE = DE; + this.HL = HL; + } + #endregion + + public Dictionary DumpRegisters() + { + return new Dictionary + { + { "A", A }, + { "F", F }, + { "B", B }, + { "C", C }, + { "D", D }, + { "E", E }, + { "H", H }, + { "L", L }, + { "AF", AF }, + { "BC", BC }, + { "DE", DE }, + { "HL", HL }, + { "PC", PC }, + { "SP", SP } + }; + } + + #region Print Functions + public void PrintSingleStatus() + { + Console.WriteLine("Register status:"); + Console.WriteLine($"A:\t{A}\tF:\t{F}"); + Console.WriteLine($"B:\t{B}\tC:\t{C}"); + Console.WriteLine($"D:\t{D}\tE:\t{E}"); + Console.WriteLine($"H:\t{H}\tL:\t{L}\r\n"); + } + public void PrintWideStatus() + { + Console.WriteLine("Wide Register status:"); + Console.WriteLine($"AF:\t{AF}"); + Console.WriteLine($"BC:\t{BC}"); + Console.WriteLine($"DE:\t{DE}"); + Console.WriteLine($"HL:\t{HL}"); + } + public void PrintFlags() + { + Console.WriteLine("Flag status:"); + Console.WriteLine($"Zero:\t\t{Flags.Zero}"); + Console.WriteLine($"Subtract:\t{Flags.Subtract}"); + Console.WriteLine($"Half Carry:\t{Flags.HalfCarry}"); + Console.WriteLine($"Carry:\t\t{Flags.Carry}"); + Console.WriteLine($"Raw Register:\t{Convert.ToString(Flags.Value, 2)}"); + } + #endregion + + public class FlagRegister + { + protected internal byte Value { get; set; } + #region Boolean Flag Properties + public bool Zero + { + get { return (Value & 0b1000_0000) != 0; } + set + { + if (value) + Value |= 0b1000_0000; + else + Value &= 0b0111_1111; + } + } + public bool Subtract + { + get { return (Value & 0b0100_0000) != 0; } + set + { + if (value) + Value |= 0b0100_0000; + else + Value &= 0b1011_1111; + } + } + public bool HalfCarry + { + get { return (Value & 0b0010_0000) != 0; } + set + { + if (value) + Value |= 0b0010_0000; + else + Value &= 0b1101_1111; + } + } + public bool Carry + { + get { return (Value & 0b0001_0000) != 0; } + set + { + if (value) + Value |= 0b0001_0000; + else + Value &= 0b1110_1111; + } + } + #endregion + public bool IsValid + { + get { return (Value & 0b0000_1111) == 0; } + } + } + } +} diff --git a/MCEmuCore.GBMonolith/MCEmuCore.GBMonolith.csproj b/MCEmuCore.GBMonolith/MCEmuCore.GBMonolith.csproj new file mode 100644 index 0000000..21dff5c --- /dev/null +++ b/MCEmuCore.GBMonolith/MCEmuCore.GBMonolith.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp2.2 + + + diff --git a/MCEmuCore.GBMonolith/Program.cs b/MCEmuCore.GBMonolith/Program.cs new file mode 100644 index 0000000..c533403 --- /dev/null +++ b/MCEmuCore.GBMonolith/Program.cs @@ -0,0 +1,60 @@ +using System; + +namespace MCEmuCore.GBMonolith +{ + class Program + { + static void Main(string[] args) + { + TestRegisters(); + } + + static void TestRegisters() + { + CpuRegisters cpuRegisters = new CpuRegisters(true); + Console.WriteLine("Initializing registers:"); + Console.WriteLine("A:\t1\tF:\t16"); + Console.WriteLine("B:\t2\tC:\t100"); + Console.WriteLine("D:\t3\tE:\t150"); + Console.WriteLine("H:\t4\tL:\t200\r\n"); + cpuRegisters.A += 1; + cpuRegisters.B += 2; + cpuRegisters.D += 3; + cpuRegisters.H += 4; + cpuRegisters.F += 16; + cpuRegisters.C += 100; + cpuRegisters.E += 150; + cpuRegisters.L += 200; + cpuRegisters.PrintSingleStatus(); + Console.WriteLine("Expected Wide Register status:"); + Console.WriteLine("BC:\t612"); + Console.WriteLine("DE:\t918"); + Console.WriteLine("HL:\t1224\r\n"); + Console.Write("Actual "); + cpuRegisters.PrintWideStatus(); + Console.WriteLine("\r\nSetting wide values:"); + Console.WriteLine("BC:\t26214"); + Console.WriteLine("DE:\t22016"); + Console.WriteLine("HL:\t153\r\n"); + cpuRegisters.BC = 26214; + cpuRegisters.DE = 22016; + cpuRegisters.HL = 153; + cpuRegisters.PrintWideStatus(); + Console.WriteLine("\r\nExpected Register status:"); + Console.WriteLine("A:\t1\tF:\t16"); + Console.WriteLine("B:\t102\tC:\t102"); + Console.WriteLine("D:\t86\tE:\t0"); + Console.WriteLine("H:\t0\tL:\t153\r\n"); + Console.Write("Actual "); + cpuRegisters.PrintSingleStatus(); + Console.WriteLine("Testing Flags:"); + cpuRegisters.PrintFlags(); + cpuRegisters.Flags.Zero = true; + cpuRegisters.Flags.Subtract = true; + cpuRegisters.Flags.HalfCarry = true; + cpuRegisters.Flags.Carry = false; + cpuRegisters.PrintFlags(); + Console.ReadLine(); + } + } +} diff --git a/MCEmuCore.GFX/Class1.cs b/MCEmuCore.GFX/Class1.cs new file mode 100644 index 0000000..b6e4648 --- /dev/null +++ b/MCEmuCore.GFX/Class1.cs @@ -0,0 +1,8 @@ +using System; + +namespace MCEmuCore.GFX +{ + public class Class1 + { + } +} diff --git a/MCEmuCore.GFX/MCEmuCore.GFX.csproj b/MCEmuCore.GFX/MCEmuCore.GFX.csproj new file mode 100644 index 0000000..c16c6d5 --- /dev/null +++ b/MCEmuCore.GFX/MCEmuCore.GFX.csproj @@ -0,0 +1,7 @@ + + + + netcoreapp2.2 + + + diff --git a/MCEmuCore.Input/Class1.cs b/MCEmuCore.Input/Class1.cs new file mode 100644 index 0000000..44a0a18 --- /dev/null +++ b/MCEmuCore.Input/Class1.cs @@ -0,0 +1,8 @@ +using System; + +namespace MCEmuCore.Input +{ + public class Class1 + { + } +} diff --git a/MCEmuCore.Input/MCEmuCore.Input.csproj b/MCEmuCore.Input/MCEmuCore.Input.csproj new file mode 100644 index 0000000..c16c6d5 --- /dev/null +++ b/MCEmuCore.Input/MCEmuCore.Input.csproj @@ -0,0 +1,7 @@ + + + + netcoreapp2.2 + + + diff --git a/MCEmuCore.Memory/Class1.cs b/MCEmuCore.Memory/Class1.cs new file mode 100644 index 0000000..6db6723 --- /dev/null +++ b/MCEmuCore.Memory/Class1.cs @@ -0,0 +1,8 @@ +using System; + +namespace MCEmuCore.Memory +{ + public class Class1 + { + } +} diff --git a/MCEmuCore.Memory/MCEmuCore.Memory.csproj b/MCEmuCore.Memory/MCEmuCore.Memory.csproj new file mode 100644 index 0000000..c16c6d5 --- /dev/null +++ b/MCEmuCore.Memory/MCEmuCore.Memory.csproj @@ -0,0 +1,7 @@ + + + + netcoreapp2.2 + + + diff --git a/MCEmuCore.System/Class1.cs b/MCEmuCore.System/Class1.cs new file mode 100644 index 0000000..8ed0db7 --- /dev/null +++ b/MCEmuCore.System/Class1.cs @@ -0,0 +1,8 @@ +using System; + +namespace MCEmuCore.System +{ + public abstract class System + { + } +} diff --git a/MCEmuCore.System/MCEmuCore.System.csproj b/MCEmuCore.System/MCEmuCore.System.csproj new file mode 100644 index 0000000..c0c22e6 --- /dev/null +++ b/MCEmuCore.System/MCEmuCore.System.csproj @@ -0,0 +1,11 @@ + + + + netcoreapp2.2 + + + + + + + diff --git a/MCEmuCore.sln b/MCEmuCore.sln new file mode 100644 index 0000000..e45d3fe --- /dev/null +++ b/MCEmuCore.sln @@ -0,0 +1,61 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.64 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MCEmuCore.Console", "MCEmuCore.Console\MCEmuCore.Console.csproj", "{8657E0E4-43DC-4AAB-BCB2-D54AD255E13E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MCEmuCore.CPU", "MCEmuCore.CPU\MCEmuCore.CPU.csproj", "{BB90BFE8-7331-4F68-A6B4-30CB57E8EB6D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MCEmuCore.System", "MCEmuCore.System\MCEmuCore.System.csproj", "{CB962918-F94B-43A0-A7CF-6822EB815BE6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MCEmuCore.Memory", "MCEmuCore.Memory\MCEmuCore.Memory.csproj", "{E29389DA-A4D2-4FD9-A132-B674DACE7C29}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MCEmuCore.GFX", "MCEmuCore.GFX\MCEmuCore.GFX.csproj", "{FADFCC95-60A7-49A0-872E-BBBABD1BA68F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MCEmuCore.Input", "MCEmuCore.Input\MCEmuCore.Input.csproj", "{C95C1D18-8BB8-4203-8520-C02160D5DA6D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MCEmuCore.GBMonolith", "MCEmuCore.GBMonolith\MCEmuCore.GBMonolith.csproj", "{C7208534-EA17-4D10-86BE-1D2A85BF1DEE}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8657E0E4-43DC-4AAB-BCB2-D54AD255E13E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8657E0E4-43DC-4AAB-BCB2-D54AD255E13E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8657E0E4-43DC-4AAB-BCB2-D54AD255E13E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8657E0E4-43DC-4AAB-BCB2-D54AD255E13E}.Release|Any CPU.Build.0 = Release|Any CPU + {BB90BFE8-7331-4F68-A6B4-30CB57E8EB6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BB90BFE8-7331-4F68-A6B4-30CB57E8EB6D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BB90BFE8-7331-4F68-A6B4-30CB57E8EB6D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BB90BFE8-7331-4F68-A6B4-30CB57E8EB6D}.Release|Any CPU.Build.0 = Release|Any CPU + {CB962918-F94B-43A0-A7CF-6822EB815BE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CB962918-F94B-43A0-A7CF-6822EB815BE6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CB962918-F94B-43A0-A7CF-6822EB815BE6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CB962918-F94B-43A0-A7CF-6822EB815BE6}.Release|Any CPU.Build.0 = Release|Any CPU + {E29389DA-A4D2-4FD9-A132-B674DACE7C29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E29389DA-A4D2-4FD9-A132-B674DACE7C29}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E29389DA-A4D2-4FD9-A132-B674DACE7C29}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E29389DA-A4D2-4FD9-A132-B674DACE7C29}.Release|Any CPU.Build.0 = Release|Any CPU + {FADFCC95-60A7-49A0-872E-BBBABD1BA68F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FADFCC95-60A7-49A0-872E-BBBABD1BA68F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FADFCC95-60A7-49A0-872E-BBBABD1BA68F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FADFCC95-60A7-49A0-872E-BBBABD1BA68F}.Release|Any CPU.Build.0 = Release|Any CPU + {C95C1D18-8BB8-4203-8520-C02160D5DA6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C95C1D18-8BB8-4203-8520-C02160D5DA6D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C95C1D18-8BB8-4203-8520-C02160D5DA6D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C95C1D18-8BB8-4203-8520-C02160D5DA6D}.Release|Any CPU.Build.0 = Release|Any CPU + {C7208534-EA17-4D10-86BE-1D2A85BF1DEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C7208534-EA17-4D10-86BE-1D2A85BF1DEE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C7208534-EA17-4D10-86BE-1D2A85BF1DEE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C7208534-EA17-4D10-86BE-1D2A85BF1DEE}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {19299914-A3FB-4FA9-9B50-CD16059FEB08} + EndGlobalSection +EndGlobal