2900 lines
		
	
	
		
			No EOL
		
	
	
		
			152 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			2900 lines
		
	
	
		
			No EOL
		
	
	
		
			152 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<html><head>
 | 
						||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
 | 
						||
  <title>Specifications</title>
 | 
						||
  <meta name="GENERATOR" content="nocash XED2HTM converter">
 | 
						||
</head><body link="#0033cc" alink="#0033cc" bgcolor="#ffffff" text="#000000" vlink="#0033cc">
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="pandocs"></a><font size="+2"> Pan Docs</font></td></tr></tbody></table><br>
 | 
						||
<b>Overview<br>
 | 
						||
</b><a href="#aboutthepandocs">About the Pan Docs</a><br>
 | 
						||
<a href="#gameboytechnicaldata">Game Boy Technical Data</a><br>
 | 
						||
<a href="#memorymap">Memory Map</a><br>
 | 
						||
<br>
 | 
						||
<b>I/O Ports<br>
 | 
						||
</b><a href="#videodisplay">Video Display</a><br>
 | 
						||
<a href="#soundcontroller">Sound Controller</a><br>
 | 
						||
<a href="#joypadinput">Joypad Input</a><br>
 | 
						||
<a href="#serialdatatransferlinkcable">Serial Data Transfer (Link Cable)</a><br>
 | 
						||
<a href="#timeranddividerregisters">Timer and Divider Registers</a><br>
 | 
						||
<a href="#interrupts">Interrupts</a><br>
 | 
						||
<a href="#cgbregisters">CGB Registers</a><br>
 | 
						||
<a href="#sgbfunctions">SGB Functions</a><br>
 | 
						||
<br>
 | 
						||
<b>CPU Specifications<br>
 | 
						||
</b><a href="#cpuregistersandflags">CPU Registers and Flags</a><br>
 | 
						||
<a href="#cpuinstructionset">CPU Instruction Set</a><br>
 | 
						||
<a href="#cpucomparisionwithz80">CPU Comparision with Z80</a><br>
 | 
						||
<br>
 | 
						||
<b>Cartridges<br>
 | 
						||
</b><a href="#thecartridgeheader">The Cartridge Header</a><br>
 | 
						||
<a href="#memorybankcontrollers">Memory Bank Controllers</a><br>
 | 
						||
<a href="#gamegeniesharkcheats">Gamegenie/Shark Cheats</a><br>
 | 
						||
<br>
 | 
						||
<b>Other<br>
 | 
						||
</b><a href="#powerupsequence">Power Up Sequence</a><br>
 | 
						||
<a href="#reducingpowerconsumption">Reducing Power Consumption</a><br>
 | 
						||
<a href="#spriterambug">Sprite RAM Bug</a><br>
 | 
						||
<a href="#externalconnectors">External Connectors</a><br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="aboutthepandocs"></a><font size="+2"> About the Pan Docs</font></td></tr></tbody></table><br>
 | 
						||
<table><tbody><tr><td><pre> =================================================================
 | 
						||
       Everything You Always Wanted To Know About GAMEBOY *
 | 
						||
 =================================================================
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<table><tbody><tr><td><pre>                     * but were afraid to ask
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<table><tbody><tr><td><pre>        Pan of -ATX- Document Updated by contributions from:
 | 
						||
     Marat Fayzullin, Pascal Felber, Paul Robson, Martin Korth
 | 
						||
             CPU, SGB, CGB, AUX specs by Martin Korth
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<table><tbody><tr><td><pre>                  Last updated 10/2001 by nocash
 | 
						||
               Previously updated 4-Mar-98 by kOOPa
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>Forward<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Available Document Formats<br>
 | 
						||
</b>The present version of this document is available in Text and Html format:<br>
 | 
						||
<table><tbody><tr><td><pre>  http://www.work.de/nocash/pandocs.txt
 | 
						||
  http://www.work.de/nocash/pandocs.htm
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="gameboytechnicaldata"></a><font size="+2"> Game Boy Technical Data</font></td></tr></tbody></table><br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="memorymap"></a><font size="+2"> Memory Map</font></td></tr></tbody></table><br>
 | 
						||
The gameboy is having a 16bit address bus, that is used to address ROM, 
 | 
						||
RAM, and I/O registers.<br>
 | 
						||
<br>
 | 
						||
<b>General Memory Map<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>Jump Vectors in First ROM Bank<br>
 | 
						||
</b>The following addresses are supposed to be used as jump vectors:<br>
 | 
						||
<table><tbody><tr><td><pre>  0000,0008,0010,0018,0020,0028,0030,0038   for RST commands
 | 
						||
  0040,0048,0050,0058,0060                  for Interrupts
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>Cartridge Header in First ROM Bank<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>External Memory and Hardware<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="videodisplay"></a><font size="+2"> Video Display</font></td></tr></tbody></table><br>
 | 
						||
<b>Video I/O Registers<br>
 | 
						||
</b><a href="#lcdcontrolregister">LCD Control Register</a><br>
 | 
						||
<a href="#lcdstatusregister">LCD Status Register</a><br>
 | 
						||
<a href="#lcdinterrupts">LCD Interrupts</a><br>
 | 
						||
<a href="#lcdpositionandscrolling">LCD Position and Scrolling</a><br>
 | 
						||
<a href="#lcdmonochromepalettes">LCD Monochrome Palettes</a><br>
 | 
						||
<a href="#lcdcolorpalettescgbonly">LCD Color Palettes (CGB only)</a><br>
 | 
						||
<a href="#lcdvrambankcgbonly">LCD VRAM Bank (CGB only)</a><br>
 | 
						||
<a href="#lcdoamdmatransfers">LCD OAM DMA Transfers</a><br>
 | 
						||
<a href="#lcdvramdmatransferscgbonly">LCD VRAM DMA Transfers (CGB only)</a><br>
 | 
						||
<br>
 | 
						||
<b>Video Memory<br>
 | 
						||
</b><a href="#vramtiledata">VRAM Tile Data</a><br>
 | 
						||
<a href="#vrambackgroundmaps">VRAM Background Maps</a><br>
 | 
						||
<a href="#vramspriteattributetableoam">VRAM Sprite Attribute Table (OAM)</a><br>
 | 
						||
<a href="#accessingvramandoam">Accessing VRAM and OAM</a><br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="lcdcontrolregister"></a><font size="+2"> LCD Control Register</font></td></tr></tbody></table><br>
 | 
						||
<b>FF40 - LCDC - LCD Control (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>LCDC.7 - LCD Display Enable<br>
 | 
						||
</b>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.<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
--- LCDC.0 has different Meanings depending on Gameboy Type ---<br>
 | 
						||
<br>
 | 
						||
<b>LCDC.0 - 1) Monochrome Gameboy and SGB: BG Display<br>
 | 
						||
</b>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).<br>
 | 
						||
<br>
 | 
						||
<b>LCDC.0 - 2) CGB in CGB Mode: BG and Window Master Priority<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>LCDC.0 - 3) CGB in Non CGB Mode: BG and Window Display<br>
 | 
						||
</b>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).<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="lcdstatusregister"></a><font size="+2"> LCD Status Register</font></td></tr></tbody></table><br>
 | 
						||
<b>FF41 - STAT - LCDC Status   (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
The two lower STAT bits show the current status of the LCD controller.<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<table><tbody><tr><td><pre>  Mode 2: The LCD controller is reading from OAM memory.
 | 
						||
          The CPU <cannot> access OAM memory (FE00h-FE9Fh)
 | 
						||
          during this period.
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<table><tbody><tr><td><pre>  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.
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
The following are typical when the display is enabled:<br>
 | 
						||
<table><tbody><tr><td><pre>  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_____
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
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.)<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="lcdinterrupts"></a><font size="+2"> LCD Interrupts</font></td></tr></tbody></table><br>
 | 
						||
<b>INT 40 - V-Blank Interrupt<br>
 | 
						||
</b>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).<br>
 | 
						||
During this period video hardware is not using video ram so it may be 
 | 
						||
freely accessed. This period lasts approximately 1.1 milliseconds.<br>
 | 
						||
<br>
 | 
						||
<b>INT 48 - LCDC Status Interrupt<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="lcdpositionandscrolling"></a><font size="+2"> LCD Position and Scrolling</font></td></tr></tbody></table><br>
 | 
						||
<b>FF42 - SCY - Scroll Y   (R/W)<br>
 | 
						||
FF43 - SCX - Scroll X   (R/W)<br>
 | 
						||
</b>Specifies the position in the 256x256 pixels BG map (32x32 tiles) which 
 | 
						||
is to be displayed at the upper/left LCD display position.<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>FF44 - LY - LCDC Y-Coordinate (R)<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>FF45 - LYC - LY Compare  (R/W)<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>FF4A - WY - Window Y Position (R/W)<br>
 | 
						||
FF4B - WX - Window X Position minus 7 (R/W)<br>
 | 
						||
</b>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.)<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="lcdmonochromepalettes"></a><font size="+2"> LCD Monochrome Palettes</font></td></tr></tbody></table><br>
 | 
						||
<b>FF47 - BGP - BG Palette Data  (R/W) - Non CGB Mode Only<br>
 | 
						||
</b>This register assigns gray shades to the color numbers of the BG and 
 | 
						||
Window tiles.<br>
 | 
						||
<table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table>The four possible gray shades are:<br>
 | 
						||
<table><tbody><tr><td><pre>  0  White
 | 
						||
  1  Light gray
 | 
						||
  2  Dark gray
 | 
						||
  3  Black
 | 
						||
</pre></td></tr></tbody></table>In CGB Mode the Color Palettes are taken from CGB Palette Memory 
 | 
						||
instead.<br>
 | 
						||
<br>
 | 
						||
<b>FF48 - OBP0 - Object Palette 0 Data (R/W) - Non CGB Mode Only<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>FF49 - OBP1 - Object Palette 1 Data (R/W) - Non CGB Mode Only<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="lcdcolorpalettescgbonly"></a><font size="+2"> LCD Color Palettes (CGB only)</font></td></tr></tbody></table><br>
 | 
						||
<b>FF68 - BCPS/BGPI - CGB Mode Only - Background Palette Index<br>
 | 
						||
</b>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.<br>
 | 
						||
<table><tbody><tr><td><pre>  Bit 0-5   Index (00-3F)
 | 
						||
  Bit 7     Auto Increment  (0=Disabled, 1=Increment after Writing)
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>FF69 - BCPD/BGPD - CGB Mode Only - Background Palette Data<br>
 | 
						||
</b>This register allows to read/write data to the CGBs Background Palette 
 | 
						||
Memory, addressed through Register FF68.<br>
 | 
						||
Each color is defined by two bytes (Bit 0-7 in first byte).<br>
 | 
						||
<table><tbody><tr><td><pre>  Bit 0-4   Red Intensity   (00-1F)
 | 
						||
  Bit 5-9   Green Intensity (00-1F)
 | 
						||
  Bit 10-14 Blue Intensity  (00-1F)
 | 
						||
</pre></td></tr></tbody></table>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).<br>
 | 
						||
Note: Initially all background colors are initialized as white.<br>
 | 
						||
<br>
 | 
						||
<b>FF6A - OCPS/OBPI - CGB Mode Only - Sprite Palette Index<br>
 | 
						||
FF6B - OCPD/OBPD - CGB Mode Only - Sprite Palette Data<br>
 | 
						||
</b>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.<br>
 | 
						||
Note: Initially all sprite colors are uninitialized.<br>
 | 
						||
<br>
 | 
						||
<b>RGB Translation by CGBs<br>
 | 
						||
</b>When developing graphics on PCs, note that the RGB values will have 
 | 
						||
different appearance on CGB displays as on VGA monitors:<br>
 | 
						||
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.<br>
 | 
						||
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.<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>RGB Translation by GBAs<br>
 | 
						||
</b>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.<br>
 | 
						||
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.<br>
 | 
						||
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.<br>
 | 
						||
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?<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="lcdvrambankcgbonly"></a><font size="+2"> LCD VRAM Bank (CGB only)</font></td></tr></tbody></table><br>
 | 
						||
<b>FF4F - VBK - CGB Mode Only - VRAM Bank<br>
 | 
						||
</b>This 1bit register selects the current Video Memory (VRAM) Bank.<br>
 | 
						||
<table><tbody><tr><td><pre>  Bit 0 - VRAM Bank (0-1)
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="lcdoamdmatransfers"></a><font size="+2"> LCD OAM DMA Transfers</font></td></tr></tbody></table><br>
 | 
						||
<b>FF46 - DMA - DMA Transfer and Start Address (W)<br>
 | 
						||
</b>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:<br>
 | 
						||
<table><tbody><tr><td><pre>  Source:      XX00-XX9F   ;XX in range from 00-F1h
 | 
						||
  Destination: FE00-FE9F
 | 
						||
</pre></td></tr></tbody></table>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:<br>
 | 
						||
<table><tbody><tr><td><pre>   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
 | 
						||
</pre></td></tr></tbody></table>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).<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="lcdvramdmatransferscgbonly"></a><font size="+2"> LCD VRAM DMA Transfers (CGB only)</font></td></tr></tbody></table><br>
 | 
						||
<b>FF51 - HDMA1 - CGB Mode Only - New DMA Source, High<br>
 | 
						||
FF52 - HDMA2 - CGB Mode Only - New DMA Source, Low<br>
 | 
						||
FF53 - HDMA3 - CGB Mode Only - New DMA Destination, High<br>
 | 
						||
FF54 - HDMA4 - CGB Mode Only - New DMA Destination, Low<br>
 | 
						||
FF55 - HDMA5 - CGB Mode Only - New DMA Length/Mode/Start<br>
 | 
						||
</b>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).<br>
 | 
						||
<br>
 | 
						||
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:<br>
 | 
						||
<br>
 | 
						||
<b>Bit7=0 - General Purpose DMA<br>
 | 
						||
</b>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.<br>
 | 
						||
The execution of the program continues when the transfer has been 
 | 
						||
completed, and FF55 then contains a value if FFh.<br>
 | 
						||
<br>
 | 
						||
<b>Bit7=1 - H-Blank DMA<br>
 | 
						||
</b>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.<br>
 | 
						||
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!<br>
 | 
						||
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".<br>
 | 
						||
<br>
 | 
						||
<b>Confirming if the DMA Transfer is Active<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Transfer Timings<br>
 | 
						||
</b>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.<br>
 | 
						||
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).<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="vramtiledata"></a><font size="+2"> VRAM Tile Data</font></td></tr></tbody></table><br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
Each Tile occupies 16 bytes, where each 2 bytes represent a line:<br>
 | 
						||
<table><tbody><tr><td><pre>  Byte 0-1  First Line (Upper 8 pixels)
 | 
						||
  Byte 2-3  Next Line
 | 
						||
  etc.
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
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).<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="vrambackgroundmaps"></a><font size="+2"> VRAM Background Maps</font></td></tr></tbody></table><br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>BG Map Tile Numbers<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>BG Map Attributes (CGB Mode only)<br>
 | 
						||
</b>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):<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>Normal Background (BG)<br>
 | 
						||
</b>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.)<br>
 | 
						||
<br>
 | 
						||
<b>The Window<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
Both background and window can be disabled or enabled separately via 
 | 
						||
bits in the LCDC register.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="vramspriteattributetableoam"></a><font size="+2"> VRAM Sprite Attribute Table (OAM)</font></td></tr></tbody></table><br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
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:<br>
 | 
						||
<br>
 | 
						||
<b>Byte0 - Y Position<br>
 | 
						||
</b>Specifies the sprites vertical position on the screen (minus 16).<br>
 | 
						||
An offscreen value (for example, Y=0 or Y>=160) hides the sprite.<br>
 | 
						||
<br>
 | 
						||
<b>Byte1 - X Position<br>
 | 
						||
</b>Specifies the sprites horizontal position on the screen (minus 8).<br>
 | 
						||
An offscreen value (X=0 or X>=168) hides the sprite, but the sprite<br>
 | 
						||
still affects the priority ordering - a better way to hide a sprite is 
 | 
						||
to set its Y-coordinate offscreen.<br>
 | 
						||
<br>
 | 
						||
<b>Byte2 - Tile/Pattern Number<br>
 | 
						||
</b>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.<br>
 | 
						||
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".<br>
 | 
						||
<br>
 | 
						||
<b>Byte3 - Attributes/Flags:<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>Sprite Priorities and Conflicts<br>
 | 
						||
</b>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.<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>Writing Data to OAM Memory<br>
 | 
						||
</b>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).<br>
 | 
						||
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).<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="accessingvramandoam"></a><font size="+2"> Accessing VRAM and OAM</font></td></tr></tbody></table><br>
 | 
						||
<b>CAUTION<br>
 | 
						||
</b>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).<br>
 | 
						||
<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>VRAM (memory at 8000h-9FFFh) is accessable during Mode 0-2<br>
 | 
						||
</b><table><tbody><tr><td><pre>  Mode 0 - H-Blank Period,
 | 
						||
  Mode 1 - V-Blank Period, and
 | 
						||
  Mode 2 - Searching OAM Period
 | 
						||
</pre></td></tr></tbody></table>A typical procedure that waits for accessibility of VRAM would be:<br>
 | 
						||
<table><tbody><tr><td><pre>  ld   hl,0FF41h    ;-STAT Register
 | 
						||
 @@wait:            ;\
 | 
						||
  bit  1,(hl)       ; Wait until Mode is 0 or 1
 | 
						||
  jr   nz,@@wait    ;/
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
In CGB Mode an alternate method to write data to VRAM is to use the HDMA 
 | 
						||
Function (FF51-FF55).<br>
 | 
						||
<br>
 | 
						||
<b>OAM (memory at FE00h-FE9Fh) is accessable during Mode 0-1<br>
 | 
						||
</b><table><tbody><tr><td><pre>  Mode 0 - H-Blank Period, and
 | 
						||
  Mode 1 - V-Blank Period
 | 
						||
</pre></td></tr></tbody></table>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:<br>
 | 
						||
<table><tbody><tr><td><pre>  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   ;/
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>Note<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="soundcontroller"></a><font size="+2"> Sound Controller</font></td></tr></tbody></table><br>
 | 
						||
<a href="#soundoverview">Sound Overview</a><br>
 | 
						||
<a href="#soundchannel1tonesweep">Sound Channel 1 - Tone & Sweep</a><br>
 | 
						||
<a href="#soundchannel2tone">Sound Channel 2 - Tone</a><br>
 | 
						||
<a href="#soundchannel3waveoutput">Sound Channel 3 - Wave Output</a><br>
 | 
						||
<a href="#soundchannel4noise">Sound Channel 4 - Noise</a><br>
 | 
						||
<a href="#soundcontrolregisters">Sound Control Registers</a><br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="soundoverview"></a><font size="+2"> Sound Overview</font></td></tr></tbody></table><br>
 | 
						||
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:<br>
 | 
						||
<br>
 | 
						||
<table><tbody><tr><td><pre>   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.
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
These four sounds can be controlled independantly and then mixed 
 | 
						||
separately for each of the output terminals.<br>
 | 
						||
<br>
 | 
						||
Sound registers may be set at all times while producing sound.<br>
 | 
						||
<br>
 | 
						||
(Sounds will have a 2.4% higher frequency on Super GB.)<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="soundchannel1tonesweep"></a><font size="+2"> Sound Channel 1 - Tone & Sweep</font></td></tr></tbody></table><br>
 | 
						||
<b>FF10 - NR10 - Channel 1 Sweep register (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>Sweep Time:<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
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:<br>
 | 
						||
<table><tbody><tr><td><pre>  X(t) = X(t-1) +/- X(t-1)/2^n
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>FF11 - NR11 - Channel 1 Sound length/Wave pattern duty (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  Bit 7-6 - Wave Pattern Duty (Read/Write)
 | 
						||
  Bit 5-0 - Sound length data (Write Only) (t1: 0-63)
 | 
						||
</pre></td></tr></tbody></table>Wave Duty:<br>
 | 
						||
<table><tbody><tr><td><pre>  00: 12.5% ( _-------_-------_------- )
 | 
						||
  01: 25%   ( __------__------__------ )
 | 
						||
  10: 50%   ( ____----____----____---- ) (normal)
 | 
						||
  11: 75%   ( ______--______--______-- )
 | 
						||
</pre></td></tr></tbody></table>Sound Length = (64-t1)*(1/256) seconds<br>
 | 
						||
The Length value is used only if Bit 6 in NR14 is set.<br>
 | 
						||
<br>
 | 
						||
<b>FF12 - NR12 - Channel 1 Volume Envelope (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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.)
 | 
						||
</pre></td></tr></tbody></table>Length of 1 step = n*(1/64) seconds<br>
 | 
						||
<br>
 | 
						||
<b>FF13 - NR13 - Channel 1 Frequency lo (Write Only)<br>
 | 
						||
</b><br>
 | 
						||
Lower 8 bits of 11 bit frequency (x).<br>
 | 
						||
Next 3 bit are in NR14 ($FF14)<br>
 | 
						||
<br>
 | 
						||
<b>FF14 - NR14 - Channel 1 Frequency hi (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>Frequency = 131072/(2048-x) Hz<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="soundchannel2tone"></a><font size="+2"> Sound Channel 2 - Tone</font></td></tr></tbody></table><br>
 | 
						||
This sound channel works exactly as channel 1, except that it doesn't 
 | 
						||
have a Tone Envelope/Sweep Register.<br>
 | 
						||
<br>
 | 
						||
<b>FF16 - NR21 - Channel 2 Sound Length/Wave Pattern Duty (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  Bit 7-6 - Wave Pattern Duty (Read/Write)
 | 
						||
  Bit 5-0 - Sound length data (Write Only) (t1: 0-63)
 | 
						||
</pre></td></tr></tbody></table>Wave Duty:<br>
 | 
						||
<table><tbody><tr><td><pre>  00: 12.5% ( _-------_-------_------- )
 | 
						||
  01: 25%   ( __------__------__------ )
 | 
						||
  10: 50%   ( ____----____----____---- ) (normal)
 | 
						||
  11: 75%   ( ______--______--______-- )
 | 
						||
</pre></td></tr></tbody></table>Sound Length = (64-t1)*(1/256) seconds<br>
 | 
						||
The Length value is used only if Bit 6 in NR24 is set.<br>
 | 
						||
<br>
 | 
						||
<b>FF17 - NR22 - Channel 2 Volume Envelope (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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.)
 | 
						||
</pre></td></tr></tbody></table>Length of 1 step = n*(1/64) seconds<br>
 | 
						||
<br>
 | 
						||
<b>FF18 - NR23 - Channel 2 Frequency lo data (W)<br>
 | 
						||
</b>Frequency's lower 8 bits of 11 bit data (x).<br>
 | 
						||
Next 3 bits are in NR24 ($FF19).<br>
 | 
						||
<br>
 | 
						||
<b>FF19 - NR24 - Channel 2 Frequency hi data (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>Frequency = 131072/(2048-x) Hz<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="soundchannel3waveoutput"></a><font size="+2"> Sound Channel 3 - Wave Output</font></td></tr></tbody></table><br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>FF1A - NR30 - Channel 3 Sound on/off (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  Bit 7 - Sound Channel 3 Off  (0=Stop, 1=Playback)  (Read/Write)
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>FF1B - NR31 - Channel 3 Sound Length<br>
 | 
						||
</b><table><tbody><tr><td><pre>  Bit 7-0 - Sound length (t1: 0 - 255)
 | 
						||
</pre></td></tr></tbody></table>Sound Length = (256-t1)*(1/256) seconds<br>
 | 
						||
This value is used only if Bit 6 in NR34 is set.<br>
 | 
						||
<br>
 | 
						||
<b>FF1C - NR32 - Channel 3 Select output level (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  Bit 6-5 - Select output level (Read/Write)
 | 
						||
</pre></td></tr></tbody></table>Possible Output levels are:<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>FF1D - NR33 - Channel 3 Frequency's lower data (W)<br>
 | 
						||
</b>Lower 8 bits of an 11 bit frequency (x).<br>
 | 
						||
<br>
 | 
						||
<b>FF1E - NR34 - Channel 3 Frequency's higher data (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>Frequency  =  4194304/(64*(2048-x)) Hz  =  65536/(2048-x) Hz<br>
 | 
						||
<br>
 | 
						||
<b>FF30-FF3F - Wave Pattern RAM<br>
 | 
						||
</b>Contents - Waveform storage for arbitrary sound data<br>
 | 
						||
<br>
 | 
						||
This storage area holds 32 4-bit samples  that are played back upper 4 
 | 
						||
bits first.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="soundchannel4noise"></a><font size="+2"> Sound Channel 4 - Noise</font></td></tr></tbody></table><br>
 | 
						||
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'.<br>
 | 
						||
<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>FF20 - NR41 - Channel 4 Sound Length (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  Bit 5-0 - Sound length data (t1: 0-63)
 | 
						||
</pre></td></tr></tbody></table>Sound Length = (64-t1)*(1/256) seconds<br>
 | 
						||
The Length value is used only if Bit 6 in NR44 is set.<br>
 | 
						||
<br>
 | 
						||
<b>FF21 - NR42 - Channel 4 Volume Envelope (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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.)
 | 
						||
</pre></td></tr></tbody></table>Length of 1 step = n*(1/64) seconds<br>
 | 
						||
<br>
 | 
						||
<b>FF22 - NR43 - Channel 4 Polynomial Counter (R/W)<br>
 | 
						||
</b>The amplitude is randomly switched between high and low at the given 
 | 
						||
frequency. A higher frequency will make the noise to appear 'softer'.<br>
 | 
						||
When Bit 3 is set, the output will become more regular, and some 
 | 
						||
frequencies will sound more like Tone than Noise.<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>Frequency = 524288 Hz / r / 2^(s+1)     ;For r=0 assume r=0.5 instead<br>
 | 
						||
<br>
 | 
						||
<b>FF23 - NR44 - Channel 4 Counter/consecutive; Inital (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  Bit 7   - Initial (1=Restart Sound)     (Write Only)
 | 
						||
  Bit 6   - Counter/consecutive selection (Read/Write)
 | 
						||
            (1=Stop output when length in NR41 expires)
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="soundcontrolregisters"></a><font size="+2"> Sound Control Registers</font></td></tr></tbody></table><br>
 | 
						||
<b>FF24 - NR50 - Channel control / ON-OFF / Volume (R/W)<br>
 | 
						||
</b>The volume bits specify the "Master Volume" for Left/Right sound output.<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>FF25 - NR51 - Selection of Sound output terminal (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>FF26 - NR52 - Sound on/off<br>
 | 
						||
</b>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.<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="joypadinput"></a><font size="+2"> Joypad Input</font></td></tr></tbody></table><br>
 | 
						||
<b>FF00 - P1/JOYP - Joypad (R/W)<br>
 | 
						||
</b>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.<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>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).<br>
 | 
						||
<br>
 | 
						||
<b>Usage in SGB software<br>
 | 
						||
</b>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.<br>
 | 
						||
See SGB description for details.<br>
 | 
						||
<br>
 | 
						||
<b>INT 60 - Joypad Interrupt<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Using the Joypad Interrupt<br>
 | 
						||
</b>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.<br>
 | 
						||
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).<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="serialdatatransferlinkcable"></a><font size="+2"> Serial Data Transfer (Link Cable)</font></td></tr></tbody></table><br>
 | 
						||
<b>FF01 - SB - Serial transfer data (R/W)<br>
 | 
						||
</b>8 Bits of data to be read/written<br>
 | 
						||
<br>
 | 
						||
<b>FF02 - SC - Serial Transfer Control  (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>Internal Clock<br>
 | 
						||
</b>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:<br>
 | 
						||
<table><tbody><tr><td><pre>    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
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>External Clock<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Timeouts<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Delays and Synchronization<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>INT 58 - Serial Interrupt<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>XXXXXX...<br>
 | 
						||
</b><br>
 | 
						||
Transmitting and receiving serial data is done simultaneously. The 
 | 
						||
received data is automatically stored in SB.<br>
 | 
						||
<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
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.<br>
 | 
						||
The most significant bit is shifted in and out first.<br>
 | 
						||
<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
The state of the last bit shifted out determines the state of the output 
 | 
						||
line until another transfer takes place.<br>
 | 
						||
<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
The following code causes $75 to be shifted out the serial port and a 
 | 
						||
byte to be shifted into $FF01:<br>
 | 
						||
<br>
 | 
						||
<table><tbody><tr><td><pre>    ld   a,$75
 | 
						||
    ld  ($FF01),a
 | 
						||
    ld   a,$81
 | 
						||
    ld  ($FF02),a
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="timeranddividerregisters"></a><font size="+2"> Timer and Divider Registers</font></td></tr></tbody></table><br>
 | 
						||
<b>FF04 - DIV - Divider Register (R/W)<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>FF05 - TIMA - Timer counter (R/W)<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>FF06 - TMA - Timer Modulo (R/W)<br>
 | 
						||
</b>When the TIMA overflows, this data will be loaded.<br>
 | 
						||
<br>
 | 
						||
<b>FF07 - TAC - Timer Control (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>INT 50 - Timer Interrupt<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Note<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="interrupts"></a><font size="+2"> Interrupts</font></td></tr></tbody></table><br>
 | 
						||
<b>IME - Interrupt Master Enable Flag (Write Only)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  0 - Disable all Interrupts
 | 
						||
  1 - Enable all Interrupts that are enabled in IE Register (FFFF)
 | 
						||
</pre></td></tr></tbody></table>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:<br>
 | 
						||
<table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table>Whereas <INT> means the operation which is automatically executed by the 
 | 
						||
CPU when it executes an interrupt.<br>
 | 
						||
<br>
 | 
						||
<b>FFFF - IE - Interrupt Enable (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>FF0F - IF - Interrupt Flag (R/W)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>Interrupt Requests<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Interrupt Execution<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Manually Requesting/Discarding Interrupts<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Interrupt Priorities<br>
 | 
						||
</b>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:<br>
 | 
						||
<table><tbody><tr><td><pre>  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.
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>Nested Interrupts<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="cgbregisters"></a><font size="+2"> CGB Registers</font></td></tr></tbody></table><br>
 | 
						||
<b>Forward<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Unlocking CGB functions<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Detecting CGB (and GBA) functions<br>
 | 
						||
</b>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).<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>FF4D - KEY1 - CGB Mode Only - Prepare Speed Switch<br>
 | 
						||
</b><table><tbody><tr><td><pre>  Bit 7: Current Speed     (0=Normal, 1=Double) (Read Only)
 | 
						||
  Bit 0: Prepare Speed Switch (0=No, 1=Prepare) (Read/Write)
 | 
						||
</pre></td></tr></tbody></table>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:<br>
 | 
						||
<table><tbody><tr><td><pre>  IF KEY1_BIT7 <> DESIRED_SPEED THEN
 | 
						||
    IE=00H       ;(FFFF)=00h
 | 
						||
    JOYP=30H     ;(FF00)=30h
 | 
						||
    KEY1=01H     ;(FF4D)=01h
 | 
						||
    STOP         ;STOP
 | 
						||
  ENDIF
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
In Double Speed Mode the following will operate twice as fast as normal:<br>
 | 
						||
<table><tbody><tr><td><pre>  The CPU (2.10 MHz, 1 Cycle = approx. 0.5us)
 | 
						||
  Timer and Divider Registers
 | 
						||
  Serial Port (Link Cable)
 | 
						||
  DMA Transfer to OAM
 | 
						||
</pre></td></tr></tbody></table>And the following will keep operating as usual:<br>
 | 
						||
<table><tbody><tr><td><pre>  LCD Video Controller
 | 
						||
  HDMA Transfer to VRAM
 | 
						||
  All Sound Timings and Frequencies
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>FF56 - RP - CGB Mode Only - Infrared Communications Port<br>
 | 
						||
</b>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.<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
Even though being generally CGB compatible, the GBA does not include an 
 | 
						||
infra-red port.<br>
 | 
						||
<br>
 | 
						||
<b>FF70 - SVBK - CGB Mode Only - WRAM Bank<br>
 | 
						||
</b>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.<br>
 | 
						||
<table><tbody><tr><td><pre>  Bit 0-2  Select WRAM Bank (Read/Write)
 | 
						||
</pre></td></tr></tbody></table>Writing a value of 01h-07h will select Bank 1-7, writing a value of 00h 
 | 
						||
will select Bank 1 either.<br>
 | 
						||
<br>
 | 
						||
<b>FF6C - Undocumented (FEh) - Bit 0   (Read/Write) - CGB Mode Only<br>
 | 
						||
FF72 - Undocumented (00h) - Bit 0-7 (Read/Write)<br>
 | 
						||
FF73 - Undocumented (00h) - Bit 0-7 (Read/Write)<br>
 | 
						||
FF74 - Undocumented (00h) - Bit 0-7 (Read/Write) - CGB Mode Only<br>
 | 
						||
FF75 - Undocumented (8Fh) - Bit 4-6 (Read/Write)<br>
 | 
						||
FF76 - Undocumented (00h) - Always 00h (Read Only)<br>
 | 
						||
FF77 - Undocumented (00h) - Always 00h (Read Only)<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="sgbfunctions"></a><font size="+2"> SGB Functions</font></td></tr></tbody></table><br>
 | 
						||
<b>General Information<br>
 | 
						||
</b><a href="#sgbdescription">SGB Description</a><br>
 | 
						||
<a href="#sgbunlockinganddetectingsgbfunctions">SGB Unlocking and Detecting SGB Functions</a><br>
 | 
						||
<a href="#sgbcommandpackettransfers">SGB Command Packet Transfers</a><br>
 | 
						||
<a href="#sgbvramtransfers">SGB VRAM Transfers</a><br>
 | 
						||
<a href="#sgbcommandsummary">SGB Command Summary</a><br>
 | 
						||
<a href="#sgbcolorpalettesoverview">SGB Color Palettes Overview</a><br>
 | 
						||
<br>
 | 
						||
<b>SGB Commands<br>
 | 
						||
</b><a href="#sgbpalettecommands">SGB Palette Commands</a><br>
 | 
						||
<a href="#sgbcolorattributecommands">SGB Color Attribute Commands</a><br>
 | 
						||
<a href="#sgbsoundfunctions">SGB Sound Functions</a><br>
 | 
						||
<a href="#sgbsystemcontrolcommands">SGB System Control Commands</a><br>
 | 
						||
<a href="#sgbmultiplayercommand">SGB Multiplayer Command</a><br>
 | 
						||
<a href="#sgbborderandobjcommands">SGB Border and OBJ Commands</a><br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="sgbdescription"></a><font size="+2"> SGB Description</font></td></tr></tbody></table><br>
 | 
						||
<b>General Description<br>
 | 
						||
</b>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).<br>
 | 
						||
<br>
 | 
						||
<b>More Technical Description<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Normal Monochrome Games<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
Games that have been designed to support SGB functions may also access 
 | 
						||
the following additional features:<br>
 | 
						||
<br>
 | 
						||
<b>Colorized Game Screen<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>SNES Foreground Sprites<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>The SGB Border<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Multiple Joypads<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Sound Functions<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Taking Control of the SNES CPU<br>
 | 
						||
</b>Finally, it is possible to write program code or data into SNES memory, 
 | 
						||
and to execute such program code by using the SNES CPU.<br>
 | 
						||
<br>
 | 
						||
<b>SGB System Clock<br>
 | 
						||
</b>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.<br>
 | 
						||
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.<br>
 | 
						||
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 ???<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="sgbunlockinganddetectingsgbfunctions"></a><font size="+2"> SGB Unlocking and Detecting SGB Functions</font></td></tr></tbody></table><br>
 | 
						||
<b>Cartridge Header<br>
 | 
						||
</b>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:<br>
 | 
						||
<table><tbody><tr><td><pre>  146h - SGB Flag - Must be set to 03h for SGB games
 | 
						||
  14Bh - Old Licensee Code - Must be set 33h for SGB games
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>Detecting SGB hardware<br>
 | 
						||
</b>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).<br>
 | 
						||
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.<br>
 | 
						||
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. <br>
 | 
						||
<br>
 | 
						||
<b>Separating between SGB and SGB2<br>
 | 
						||
</b>It is also possible to separate between SGB and SGB2 models by examining 
 | 
						||
the inital value of the accumulator (A-register) directly after startup.<br>
 | 
						||
<table><tbody><tr><td><pre>  01h  SGB or Normal Gameboy (DMG)
 | 
						||
  FFh  SGB2 or Pocket Gameboy
 | 
						||
  11h  CGB or GBA
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
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 ???<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="sgbcommandpackettransfers"></a><font size="+2"> SGB Command Packet Transfers</font></td></tr></tbody></table><br>
 | 
						||
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).<br>
 | 
						||
<br>
 | 
						||
<b>Transferring Bits<br>
 | 
						||
</b>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:<br>
 | 
						||
<table><tbody><tr><td><pre>       RESET 0   0   1   1   0   1   0
 | 
						||
  P14  --_---_---_-----------_-------_--...
 | 
						||
  P15  --_-----------_---_-------_------...
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
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).<br>
 | 
						||
<br>
 | 
						||
<b>Transferring Packets<br>
 | 
						||
</b>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:<br>
 | 
						||
<table><tbody><tr><td><pre>   1 PULSE Reset
 | 
						||
   1 BYTE  Command Code*8+Length
 | 
						||
  15 BYTES Parameter Data
 | 
						||
   1 BIT   Stop Bit (0)
 | 
						||
</pre></td></tr></tbody></table>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:<br>
 | 
						||
<table><tbody><tr><td><pre>   1 PULSE Reset
 | 
						||
  16 BYTES Parameter Data
 | 
						||
   1 BIT   Stop Bit (0)
 | 
						||
</pre></td></tr></tbody></table>By using all 7 packets, up to 111 data bytes (15+16*6) may be sent.<br>
 | 
						||
Unused bytes at the end of the last packet must be set to zero.<br>
 | 
						||
A 60ms (4 frames) delay should be invoked between each packet transfer.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="sgbvramtransfers"></a><font size="+2"> SGB VRAM Transfers</font></td></tr></tbody></table><br>
 | 
						||
<b>Overview<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Transfer Data<br>
 | 
						||
</b>Normally, transfer data should be stored at 8000h-8FFFh in gameboy VRAM,<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>Preparing the Display<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Transfer Time<br>
 | 
						||
</b>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).<br>
 | 
						||
<br>
 | 
						||
<b>Avoiding Screen Garbage<br>
 | 
						||
</b>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.<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="sgbcommandsummary"></a><font size="+2"> SGB Command Summary</font></td></tr></tbody></table><br>
 | 
						||
<b>SGB System Command Table<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="sgbcolorpalettesoverview"></a><font size="+2"> SGB Color Palettes Overview</font></td></tr></tbody></table><br>
 | 
						||
<b>Available SNES Palettes<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Color 0 Restriction<br>
 | 
						||
</b>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).<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>Translation of Grayshades into Colors<br>
 | 
						||
</b>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:<br>
 | 
						||
<table><tbody><tr><td><pre>  White       -->  Color 0
 | 
						||
  Light Gray  -->  Color 1
 | 
						||
  Dark Gray   -->  Color 2
 | 
						||
  Black       -->  Color 3
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>Using Gameboy BGP/OBP Registers<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>System Color Palette Memory<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="sgbpalettecommands"></a><font size="+2"> SGB Palette Commands</font></td></tr></tbody></table><br>
 | 
						||
<b>SGB Command 00h - PAL01<br>
 | 
						||
</b>Transmit color data for SGB palette 0, color 0-3, and for SGB palette 1, 
 | 
						||
color 1-3 (without separate color 0).<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>The value transferred as color 0 will be applied for all eight palettes.<br>
 | 
						||
<br>
 | 
						||
<b>SGB Command 01h - PAL23<br>
 | 
						||
</b>Same as above PAL01, but for Palettes 2 and 3 respectively.<br>
 | 
						||
<br>
 | 
						||
<b>SGB Command 02h - PAL03<br>
 | 
						||
</b>Same as above PAL01, but for Palettes 0 and 3 respectively.<br>
 | 
						||
<br>
 | 
						||
<b>SGB Command 03h - PAL12<br>
 | 
						||
</b>Same as above PAL01, but for Palettes 1 and 2 respectively.<br>
 | 
						||
<br>
 | 
						||
<b>SGB Command 0Ah - PAL_SET<br>
 | 
						||
</b>Used to copy pre-defined palette data from SGB system color palette to 
 | 
						||
actual SGB palette.<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>SGB Command 0Bh - PAL_TRN<br>
 | 
						||
</b>Used to initialize SGB system color palettes in SNES RAM.<br>
 | 
						||
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).<br>
 | 
						||
<table><tbody><tr><td><pre>  Byte  Content
 | 
						||
  0     Command*8+Length (fixed length=1)
 | 
						||
  1-F   Not used (zero)
 | 
						||
</pre></td></tr></tbody></table>The palette data is sent by VRAM-Transfer (4 KBytes).<br>
 | 
						||
<table><tbody><tr><td><pre>  000-FFF  Data for System Color Palette 0-511
 | 
						||
</pre></td></tr></tbody></table>Each Palette consists of four 16bit-color definitions (8 bytes).<br>
 | 
						||
Note: The data is stored at 3000h-3FFFh in SNES memory.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="sgbcolorattributecommands"></a><font size="+2"> SGB Color Attribute Commands</font></td></tr></tbody></table><br>
 | 
						||
<b>SGB Command 04h - ATTR_BLK<br>
 | 
						||
</b>Used to specify color attributes for the inside or outside of one or 
 | 
						||
more rectangular screen regions.<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>SGB Command 05h - ATTR_LIN<br>
 | 
						||
</b>Used to specify color attributes of one or more horizontal or vertical 
 | 
						||
character lines.<br>
 | 
						||
<table><tbody><tr><td><pre>  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.
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>SGB Command 06h - ATTR_DIV<br>
 | 
						||
</b>Used to split the screen into two halfes, and to assign separate color 
 | 
						||
attributes to each half, and to the division line between them.<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>SGB Command 07h - ATTR_CHR<br>
 | 
						||
</b>Used to specify color attributes for separate characters.<br>
 | 
						||
<table><tbody><tr><td><pre>  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.
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>SGB Command 15h - ATTR_TRN<br>
 | 
						||
</b>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.<br>
 | 
						||
<table><tbody><tr><td><pre>  Byte  Content
 | 
						||
  0     Command*8+Length (fixed length=1)
 | 
						||
  1-F   Not used (zero)
 | 
						||
</pre></td></tr></tbody></table>The ATF data is sent by VRAM-Transfer (4 KBytes).<br>
 | 
						||
<table><tbody><tr><td><pre>  000-FD1  Data for ATF0 through ATF44 (4050 bytes)
 | 
						||
  FD2-FFF  Not used
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>SGB Command 16h - ATTR_SET<br>
 | 
						||
</b>Used to transfer attributes from Attribute File (ATF) to gameboy window.<br>
 | 
						||
<table><tbody><tr><td><pre>  Byte  Content
 | 
						||
  0     Command*8+Length (fixed length=1)
 | 
						||
  1     Attribute File Number (00-2Ch), Bit 6=Cancel Mask
 | 
						||
  2-F   Not used (zero)
 | 
						||
</pre></td></tr></tbody></table>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).<br>
 | 
						||
Note: The same functions may be (optionally) also included in PAL_SET 
 | 
						||
commands, as described in the chapter about Color Palette Commands.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="sgbsoundfunctions"></a><font size="+2"> SGB Sound Functions</font></td></tr></tbody></table><br>
 | 
						||
<b>SGB Command 08h - SOUND<br>
 | 
						||
</b>Used to start/stop internal sound effect, start/stop sound using 
 | 
						||
internal tone data.<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>See Sound Effect Tables below for a list of available pre-defined effects.<br>
 | 
						||
"Notes"<br>
 | 
						||
1) Mute is only active when both bits D2 and D3 are 1.<br>
 | 
						||
2) When the volume is set for either Sound Effect A or Sound Effect B, 
 | 
						||
mute is turned off.<br>
 | 
						||
3) When Mute on/off has been executed, the sound fades out/fades in.<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>SGB Command 09h - SOU_TRN<br>
 | 
						||
</b>Used to transfer sound code or data to SNES Audio Processing Unit memory 
 | 
						||
(APU-RAM).<br>
 | 
						||
<table><tbody><tr><td><pre>  Byte  Content
 | 
						||
  0     Command*8+Length (fixed length=1)
 | 
						||
  1-F   Not used (zero)
 | 
						||
</pre></td></tr></tbody></table>The sound code/data is sent by VRAM-Transfer (4 KBytes).<br>
 | 
						||
<table><tbody><tr><td><pre>  000      One (or two ???) 16bit expression(s ???) indicating the
 | 
						||
           transfer destination address and transfer length.
 | 
						||
  ...-...  Transfer Data
 | 
						||
  ...-FFF  Remaining bytes not used
 | 
						||
</pre></td></tr></tbody></table>Possible destinations in APU-RAM are:<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>SGB Sound Effect A/B Tables<br>
 | 
						||
</b>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.<br>
 | 
						||
Effect A and B may be simultaneously reproduced.<br>
 | 
						||
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).<br>
 | 
						||
<br>
 | 
						||
<b>Sound Effect A Flag Table<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table>Sound effect A is used for formanto sounds (percussion sounds).<br>
 | 
						||
<br>
 | 
						||
<b>Sound Effect B Flag Table<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table>Sound effect B is mainly used for looping sounds (sustained sounds).<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="sgbsystemcontrolcommands"></a><font size="+2"> SGB System Control Commands</font></td></tr></tbody></table><br>
 | 
						||
<b>SGB Command 17h - MASK_EN<br>
 | 
						||
</b>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).<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>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).<br>
 | 
						||
The Cancel Mask function may be also invoked (optionally) by completion 
 | 
						||
of PAL_SET and ATTR_SET commands.<br>
 | 
						||
<br>
 | 
						||
<b>SGB Command 0Ch - ATRC_EN<br>
 | 
						||
</b>Used to enable/disable Attraction mode. It is totally unclear what an 
 | 
						||
attraction mode is ???, but it is enabled by default.<br>
 | 
						||
<table><tbody><tr><td><pre>  Byte  Content
 | 
						||
  0     Command*8+Length    (fixed length=1)
 | 
						||
  1     Attraction Disable  (0=Enable, 1=Disable)
 | 
						||
  2-F   Not used (zero)
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>SGB Command 0Dh - TEST_EN<br>
 | 
						||
</b>Used to enable/disable test mode for "SGB-CPU variable clock speed 
 | 
						||
function". This function is disabled by default.<br>
 | 
						||
<table><tbody><tr><td><pre>  Byte  Content
 | 
						||
  0     Command*8+Length    (fixed length=1)
 | 
						||
  1     Test Mode Enable    (0=Disable, 1=Enable)
 | 
						||
  2-F   Not used (zero)
 | 
						||
</pre></td></tr></tbody></table>Maybe intended to determine whether SNES operates at 50Hz or 60Hz 
 | 
						||
display refresh rate ??? Possibly result can be read-out from joypad 
 | 
						||
register ???<br>
 | 
						||
<br>
 | 
						||
<b>SGB Command 0Eh - ICON_EN<br>
 | 
						||
</b>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).<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>SGB Command 0Fh - DATA_SND<br>
 | 
						||
</b>Used to write one or more bytes directly into SNES Work RAM.<br>
 | 
						||
<table><tbody><tr><td><pre>  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.
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
Free Addresses in SNES memory are Bank 0 1800h-1FFFh, Bank 7Fh 
 | 
						||
0000h-FFFFh.<br>
 | 
						||
<br>
 | 
						||
<b>SGB Command 10h - DATA_TRN<br>
 | 
						||
</b>Used to transfer binary code or data directly into SNES RAM.<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>The data is sent by VRAM-Transfer (4 KBytes).<br>
 | 
						||
<table><tbody><tr><td><pre>  000-FFF  Data
 | 
						||
</pre></td></tr></tbody></table>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 ???<br>
 | 
						||
<br>
 | 
						||
<b>SGB Command 12h - JUMP<br>
 | 
						||
</b>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.<br>
 | 
						||
<table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table>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 ???<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="sgbmultiplayercommand"></a><font size="+2"> SGB Multiplayer Command</font></td></tr></tbody></table><br>
 | 
						||
<b>SGB Command 11h - MLT_REQ<br>
 | 
						||
</b>Used to request multiplayer mode (ie. input from more than one joypad).<br>
 | 
						||
Because this function provides feedback from the SGB/SNES to the gameboy 
 | 
						||
program, it is also used to detect SGB hardware.<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>Reading Multiple Controllers (Joypads)<br>
 | 
						||
</b>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:<br>
 | 
						||
<table><tbody><tr><td><pre>  0Fh  Joypad 1
 | 
						||
  0Eh  Joypad 2
 | 
						||
  0Dh  Joypad 3
 | 
						||
  0Ch  Joypad 4
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="sgbborderandobjcommands"></a><font size="+2"> SGB Border and OBJ Commands</font></td></tr></tbody></table><br>
 | 
						||
<b>SGB Command 13h - CHR_TRN<br>
 | 
						||
</b>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).<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>The tile data is sent by VRAM-Transfer (4 KBytes).<br>
 | 
						||
<table><tbody><tr><td><pre>  000-FFF  Bitmap data for 128 Tiles
 | 
						||
</pre></td></tr></tbody></table>Each tile occupies 16bytes (8x8 pixels, 16 colors each).<br>
 | 
						||
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 ???<br>
 | 
						||
<br>
 | 
						||
<b>SGB Command 14h - PCT_TRN<br>
 | 
						||
</b>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.<br>
 | 
						||
<table><tbody><tr><td><pre>  Byte  Content
 | 
						||
  0     Command*8+Length    (fixed length=1)
 | 
						||
  1-F   Not used (zero)
 | 
						||
</pre></td></tr></tbody></table>The map data is sent by VRAM-Transfer (4 KBytes).<br>
 | 
						||
<table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table>Each BG Map Entry consists of a 16bit value as such:<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>SGB Command 18h - OBJ_TRN<br>
 | 
						||
</b>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.<br>
 | 
						||
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 ???<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>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:<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>The format of SNES OAM Entries is:<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>The format of SNES OAM MSB Entries is:<br>
 | 
						||
<table><tbody><tr><td><pre>  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).
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="cpuregistersandflags"></a><font size="+2"> CPU Registers and Flags</font></td></tr></tbody></table><br>
 | 
						||
<b>Registers<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table>As shown above, most registers can be accessed either as one 16bit 
 | 
						||
register, or as two separate 8bit registers.<br>
 | 
						||
<br>
 | 
						||
<b>The Flag Register (lower 8bit of AF register)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>Conatins the result from the recent instruction which has affected 
 | 
						||
flags.<br>
 | 
						||
<br>
 | 
						||
<b>The Zero Flag (Z)<br>
 | 
						||
</b>This bit becomes set (1) if the result of an operation has been zero 
 | 
						||
(0). Used for conditional jumps.<br>
 | 
						||
<br>
 | 
						||
<b>The Carry Flag (C, or Cy)<br>
 | 
						||
</b>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.<br>
 | 
						||
Used for conditional jumps, and for instructions such like ADC, SBC, RL, 
 | 
						||
RLA, etc.<br>
 | 
						||
<br>
 | 
						||
<b>The BCD Flags (N, H)<br>
 | 
						||
</b>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.<br>
 | 
						||
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.<br>
 | 
						||
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).<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="cpuinstructionset"></a><font size="+2"> CPU Instruction Set</font></td></tr></tbody></table><br>
 | 
						||
Tables below specify the mnemonic, opcode bytes, clock cycles, affected 
 | 
						||
flags (ordered as znhc), and explanatation.<br>
 | 
						||
The timings assume a CPU clock frequency of 4.194304 MHz (or 8.4<br>
 | 
						||
MHz for CGB in double speed mode), as all gameboy timings are divideable<br>
 | 
						||
by 4, many people specify timings and clock frequency divided by 4.<br>
 | 
						||
<br>
 | 
						||
<b>GMB 8bit-Loadcommands<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>GMB 16bit-Loadcommands<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>GMB 8bit-Arithmetic/logical Commands<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>GMB 16bit-Arithmetic/logical Commands<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>GMB Rotate- und Shift-Commands<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>GMB Singlebit Operation Commands<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>GMB CPU-Controlcommands<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>GMB Jumpcommands<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="cpucomparisionwithz80"></a><font size="+2"> CPU Comparision with Z80</font></td></tr></tbody></table><br>
 | 
						||
<b>Comparision with 8080<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>Comparision with Z80<br>
 | 
						||
</b>Any DD-, ED-, and FD-prefixed instructions are missing, that means no 
 | 
						||
IX-, IY-registers, no block commands, and some other missing commands.<br>
 | 
						||
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.<br>
 | 
						||
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.<br>
 | 
						||
The sign and parity/overflow flags have been removed.<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>Moved, Removed, and Added Opcodes<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>Note: The unused (-) opcodes will lock-up the gameboy CPU when used.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="thecartridgeheader"></a><font size="+2"> The Cartridge Header</font></td></tr></tbody></table><br>
 | 
						||
An internal information area is located at 0100-014F in<br>
 | 
						||
each cartridge. It contains the following values:<br>
 | 
						||
<br>
 | 
						||
<b>0100-0103 - Entry Point<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>0104-0133 - Nintendo Logo<br>
 | 
						||
</b>These bytes define the bitmap of the Nintendo logo that is displayed 
 | 
						||
when the gameboy gets turned on. The hexdump of this bitmap is:<br>
 | 
						||
<table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>0134-0143 - Title<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>013F-0142 - Manufacturer Code<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>0143 - CGB Flag<br>
 | 
						||
</b>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:<br>
 | 
						||
<table><tbody><tr><td><pre>  80h - Game supports CGB functions, but works on old gameboys also.
 | 
						||
  C0h - Game works on CGB only (physically the same as 80h).
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>0144-0145 - New Licensee Code<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>0146 - SGB Flag<br>
 | 
						||
</b>Specifies whether the game supports SGB functions, common values are:<br>
 | 
						||
<table><tbody><tr><td><pre>  00h = No SGB functions (Normal Gameboy or CGB only game)
 | 
						||
  03h = Game supports SGB functions
 | 
						||
</pre></td></tr></tbody></table>The SGB disables its SGB functions if this byte is set to another value 
 | 
						||
than 03h.<br>
 | 
						||
<br>
 | 
						||
<b>0147 - Cartridge Type<br>
 | 
						||
</b>Specifies which Memory Bank Controller (if any) is used in the 
 | 
						||
cartridge, and if further external hardware exists in the cartridge.<br>
 | 
						||
<table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>0148 - ROM Size<br>
 | 
						||
</b>Specifies the ROM Size of the cartridge. Typically calculated as "32KB 
 | 
						||
shl N".<br>
 | 
						||
<table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>0149 - RAM Size<br>
 | 
						||
</b>Specifies the size of the external RAM in the cartridge (if any).<br>
 | 
						||
<table><tbody><tr><td><pre>  00h - None
 | 
						||
  01h - 2 KBytes
 | 
						||
  02h - 8 Kbytes
 | 
						||
  03h - 32 KBytes (4 banks of 8KBytes each)
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>014A - Destination Code<br>
 | 
						||
</b>Specifies if this version of the game is supposed to be sold in japan, 
 | 
						||
or anywhere else. Only two values are defined.<br>
 | 
						||
<table><tbody><tr><td><pre>  00h - Japanese
 | 
						||
  01h - Non-Japanese
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>014B - Old Licensee Code<br>
 | 
						||
</b>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.<br>
 | 
						||
(Super GameBoy functions won't work if <> $33.)<br>
 | 
						||
<br>
 | 
						||
<b>014C - Mask ROM Version number<br>
 | 
						||
</b>Specifies the version number of the game. That is usually 00h.<br>
 | 
						||
<br>
 | 
						||
<b>014D - Header Checksum<br>
 | 
						||
</b>Contains an 8 bit checksum across the cartridge header bytes 0134-014C. 
 | 
						||
The checksum is calculated as follows:<br>
 | 
						||
<table><tbody><tr><td><pre>  x=0:FOR i=0134h TO 014Ch:x=x-MEM[i]-1:NEXT
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>014E-014F - Global Checksum<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="memorybankcontrollers"></a><font size="+2"> Memory Bank Controllers</font></td></tr></tbody></table><br>
 | 
						||
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:<br>
 | 
						||
<br>
 | 
						||
<a href="#none32kbyteromonly">None (32KByte ROM only)</a><br>
 | 
						||
<a href="#mbc1max2mbyteromandor32kbyteram">MBC1 (max 2MByte ROM and/or 32KByte RAM)</a><br>
 | 
						||
<a href="#mbc2max256kbyteromand512x4bitsram">MBC2 (max 256KByte ROM and 512x4 bits RAM)</a><br>
 | 
						||
<a href="#mbc3max2mbyteromandor32kbyteramandtimer">MBC3 (max 2MByte ROM and/or 32KByte RAM and Timer)</a><br>
 | 
						||
<a href="#huc1mbcwithinfraredcontroller">HuC1 (MBC with Infrared Controller)</a><br>
 | 
						||
<br>
 | 
						||
<a href="#mbctimingissues">MBC Timing Issues</a><br>
 | 
						||
<br>
 | 
						||
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.)<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="none32kbyteromonly"></a><font size="+2"> None (32KByte ROM only)</font></td></tr></tbody></table><br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="mbc1max2mbyteromandor32kbyteram"></a><font size="+2"> MBC1 (max 2MByte ROM and/or 32KByte RAM)</font></td></tr></tbody></table><br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
Note that the memory in range 0000-7FFF is used for both reading from 
 | 
						||
ROM, and for writing to the MBCs Control Registers.<br>
 | 
						||
<br>
 | 
						||
<b>0000-3FFF - ROM Bank 00 (Read Only)<br>
 | 
						||
</b>This area always contains the first 16KBytes of the cartridge ROM.<br>
 | 
						||
<br>
 | 
						||
<b>4000-7FFF - ROM Bank 01-7F (Read Only)<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>A000-BFFF - RAM Bank 00-03, if any (Read/Write)<br>
 | 
						||
</b>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).<br>
 | 
						||
<br>
 | 
						||
<b>0000-1FFF - RAM Enable (Write Only)<br>
 | 
						||
</b>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:<br>
 | 
						||
<table><tbody><tr><td><pre>  00h  Disable RAM (default)
 | 
						||
  0Ah  Enable RAM
 | 
						||
</pre></td></tr></tbody></table>Practically any value with 0Ah in the lower 4 bits enables RAM, and any 
 | 
						||
other value disables RAM.<br>
 | 
						||
<br>
 | 
						||
<b>2000-3FFF - ROM Bank Number (Write Only)<br>
 | 
						||
</b>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.<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>4000-5FFF - RAM Bank Number - or - Upper Bits of ROM Bank Number (Write Only)<brbr>
 | 
						||
</brbr></b>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.)<br>
 | 
						||
<br>
 | 
						||
<b>6000-7FFF - ROM/RAM Mode Select (Write Only)<br>
 | 
						||
</b>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.<br>
 | 
						||
<table><tbody><tr><td><pre>  00h = ROM Banking Mode (up to 8KByte RAM, 2MByte ROM) (default)
 | 
						||
  01h = RAM Banking Mode (up to 32KByte RAM, 512KByte ROM)
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="mbc2max256kbyteromand512x4bitsram"></a><font size="+2"> MBC2 (max 256KByte ROM and 512x4 bits RAM)</font></td></tr></tbody></table><br>
 | 
						||
<b>0000-3FFF - ROM Bank 00 (Read Only)<br>
 | 
						||
</b>Same as for MBC1.<br>
 | 
						||
<br>
 | 
						||
<b>4000-7FFF - ROM Bank 01-0F (Read Only)<br>
 | 
						||
</b>Same as for MBC1, but only a total of 16 ROM banks is supported.<br>
 | 
						||
<br>
 | 
						||
<b>A000-A1FF - 512x4bits RAM, built-in into the MBC2 chip (Read/Write)<br>
 | 
						||
</b>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.<br>
 | 
						||
As the data consists of 4bit values, only the lower 4 bits of the 
 | 
						||
"bytes" in this memory area are used.<br>
 | 
						||
<br>
 | 
						||
<b>0000-1FFF - RAM Enable (Write Only)<br>
 | 
						||
</b>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.<br>
 | 
						||
The suggested address range to use for MBC2 ram enable/disable is 
 | 
						||
0000-00FF.<br>
 | 
						||
<br>
 | 
						||
<b>2000-3FFF - ROM Bank Number (Write Only)<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
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.<br>
 | 
						||
The suggested address range to use for MBC2 rom bank selection is 
 | 
						||
2100-21FF.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="mbc3max2mbyteromandor32kbyteramandtimer"></a><font size="+2"> MBC3 (max 2MByte ROM and/or 32KByte RAM and Timer)</font></td></tr></tbody></table><br>
 | 
						||
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).<br>
 | 
						||
<br>
 | 
						||
<b>0000-3FFF - ROM Bank 00 (Read Only)<br>
 | 
						||
</b>Same as for MBC1.<br>
 | 
						||
<br>
 | 
						||
<b>4000-7FFF - ROM Bank 01-7F (Read Only)<br>
 | 
						||
</b>Same as for MBC1, except that accessing banks 20h, 40h, and 60h is 
 | 
						||
supported now.<br>
 | 
						||
<br>
 | 
						||
<b>A000-BFFF - RAM Bank 00-03, if any (Read/Write)<br>
 | 
						||
A000-BFFF - RTC Register 08-0C (Read/Write)<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>0000-1FFF - RAM and Timer Enable (Write Only)<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>2000-3FFF - ROM Bank Number (Write Only)<br>
 | 
						||
</b>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.<br>
 | 
						||
<br>
 | 
						||
<b>4000-5FFF - RAM Bank Number - or - RTC Register Select (Write Only)<br>
 | 
						||
</b>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.<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>6000-7FFF - Latch Clock Data (Write Only)<br>
 | 
						||
</b>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.<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>The Clock Counter Registers<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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)
 | 
						||
</pre></td></tr></tbody></table>The Halt Flag is supposed to be set before <writing> to the RTC 
 | 
						||
Registers.<br>
 | 
						||
<br>
 | 
						||
<b>The Day Counter<br>
 | 
						||
</b>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.<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>Delays<br>
 | 
						||
</b>When accessing the RTC Registers it is recommended to execute a 4ms 
 | 
						||
delay (4 Cycles in Normal Speed Mode) between the separate accesses.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="huc1mbcwithinfraredcontroller"></a><font size="+2"> HuC1 (MBC with Infrared Controller)</font></td></tr></tbody></table><br>
 | 
						||
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.)<br>
 | 
						||
<br>
 | 
						||
The Japanese cart "Fighting Phoenix" (internal cart name: SUPER B DAMAN) 
 | 
						||
is known to contain this chip.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="mbctimingissues"></a><font size="+2"> MBC Timing Issues</font></td></tr></tbody></table><br>
 | 
						||
<b>Using MBCs with CGB Double Speed Mode<br>
 | 
						||
</b>The MBC5 has been designed to support CGB Double Speed Mode.<br>
 | 
						||
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.<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="gamegeniesharkcheats"></a><font size="+2"> Gamegenie/Shark Cheats</font></td></tr></tbody></table><br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>Gamegenie (ROM patches)<br>
 | 
						||
</b>Gamegenie codes consist of nine-digit hex numbers, formatted as 
 | 
						||
ABC-DEF-GHI, the meaning of the separate digits is:<br>
 | 
						||
<table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table>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 ?<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<b>Game Shark (RAM patches)<br>
 | 
						||
</b>Game Shark codes consist of eight-digit hex numbers, formatted as 
 | 
						||
ABCDEFGH, the meaning of the separate digits is:<br>
 | 
						||
<table><tbody><tr><td><pre>  AB    External RAM bank number
 | 
						||
  CD    New Data
 | 
						||
  GHEF  Memory Address (internal or external RAM, A000-DFFF)
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
As far as I rememeber, somewhat 10-25 codes can be used simultaneously.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="powerupsequence"></a><font size="+2"> Power Up Sequence</font></td></tr></tbody></table><br>
 | 
						||
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:<br>
 | 
						||
<br>
 | 
						||
<table><tbody><tr><td><pre>   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
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="reducingpowerconsumption"></a><font size="+2"> Reducing Power Consumption</font></td></tr></tbody></table><br>
 | 
						||
The following can be used to recude the power consumption of the 
 | 
						||
gameboy, and to extend the life of the batteries.<br>
 | 
						||
<br>
 | 
						||
<a href="#pwrusingthehaltinstruction">PWR Using the HALT Instruction</a><br>
 | 
						||
<a href="#pwrusingthestopinstruction">PWR Using the STOP Instruction</a><br>
 | 
						||
<a href="#pwrdisabelingthesoundcontroller">PWR Disabeling the Sound Controller</a><br>
 | 
						||
<a href="#pwrnotusingcgbdoublespeedmode">PWR Not using CGB Double Speed Mode</a><br>
 | 
						||
<a href="#pwrusingtheskills">PWR Using the Skills</a><br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="pwrusingthehaltinstruction"></a><font size="+2"> PWR Using the HALT Instruction</font></td></tr></tbody></table><br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
When waiting for a vblank event, this would be a BAD example:<br>
 | 
						||
<table><tbody><tr><td><pre>  @@wait:
 | 
						||
   ld   a,(0FF44h)      ;LY
 | 
						||
   cp   a,144
 | 
						||
   jr   nz,@@wait
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
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.<br>
 | 
						||
<table><tbody><tr><td><pre>   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
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="pwrusingthestopinstruction"></a><font size="+2"> PWR Using the STOP Instruction</font></td></tr></tbody></table><br>
 | 
						||
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).<br>
 | 
						||
<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="pwrdisabelingthesoundcontroller"></a><font size="+2"> PWR Disabeling the Sound Controller</font></td></tr></tbody></table><br>
 | 
						||
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.<br>
 | 
						||
Sound can be turned back on by writing 80h to the same register, all 
 | 
						||
sound registers must be then re-initialized.<br>
 | 
						||
When the gameboy becomes turned on, sound is enabled by default, and 
 | 
						||
must be turned off manually when not used.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="pwrnotusingcgbdoublespeedmode"></a><font size="+2"> PWR Not using CGB Double Speed Mode</font></td></tr></tbody></table><br>
 | 
						||
Because CGB Double Speed mode consumes more power, it'd be recommended 
 | 
						||
to use normal speed when possible.<br>
 | 
						||
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.<br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="pwrusingtheskills"></a><font size="+2"> PWR Using the Skills</font></td></tr></tbody></table><br>
 | 
						||
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.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="spriterambug"></a><font size="+2"> Sprite RAM Bug</font></td></tr></tbody></table><br>
 | 
						||
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:<br>
 | 
						||
<table><tbody><tr><td><pre>  inc rr        dec rr          ;rr = bc,de, or hl
 | 
						||
  ldi a,(hl)    ldd a,(hl)
 | 
						||
  ldi (hl),a    ldd (hl),a
 | 
						||
</pre></td></tr></tbody></table>Only sprites 1 & 2 ($FE00 & $FE04) are not affected by these 
 | 
						||
instructions.<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="externalconnectors"></a><font size="+2"> External Connectors</font></td></tr></tbody></table><br>
 | 
						||
<b>Cartridge Slot<br>
 | 
						||
</b><table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>Link Port<br>
 | 
						||
</b>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.<br>
 | 
						||
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.<br>
 | 
						||
<table><tbody><tr><td><pre>  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
 | 
						||
</pre></td></tr></tbody></table>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.<br>
 | 
						||
<br>
 | 
						||
<b>Stereo Sound Connector (3.5mm, female)<br>
 | 
						||
</b><table><tbody><tr><td><pre>  Pin     Expl.
 | 
						||
  Tip     Sound Left
 | 
						||
  Middle  Sound Right
 | 
						||
  Base    Ground
 | 
						||
</pre></td></tr></tbody></table><br>
 | 
						||
<b>External Power Supply<br>
 | 
						||
</b>...<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<br>
 | 
						||
<table width="100%"><tbody><tr bgcolor="#cccccc"><td><a name="end"></a><font size="+2"> END</font></td></tr></tbody></table>
 | 
						||
</body></html> |