Full Code of andreasjhkarlsson/gbdk-n for AI

master 2592ba475a06 cached
87 files
333.4 KB
168.3k tokens
58 symbols
1 requests
Download .txt
Showing preview only (355K chars total). Download the full file or copy to clipboard to get everything.
Repository: andreasjhkarlsson/gbdk-n
Branch: master
Commit: 2592ba475a06
Files: 87
Total size: 333.4 KB

Directory structure:
gitextract_01138mzq/

├── .gitignore
├── Make.bat
├── Makefile
├── README.md
├── bin/
│   ├── gbdk-n-assemble.bat
│   ├── gbdk-n-assemble.sh
│   ├── gbdk-n-compile.bat
│   ├── gbdk-n-compile.sh
│   ├── gbdk-n-link.bat
│   ├── gbdk-n-link.sh
│   ├── gbdk-n-make-rom.bat
│   └── gbdk-n-make-rom.sh
├── examples/
│   ├── galaxy/
│   │   ├── Make.bat
│   │   ├── Makefile
│   │   └── galaxy.c
│   ├── paint/
│   │   ├── Make.bat
│   │   ├── Makefile
│   │   └── paint.c
│   ├── space/
│   │   ├── Make.bat
│   │   ├── Makefile
│   │   └── space.s
│   └── thumby/
│       ├── Make.bat
│       ├── Makefile
│       └── thumby.c
├── include/
│   ├── asm/
│   │   ├── gbz80/
│   │   │   ├── provides.h
│   │   │   ├── stdarg.h
│   │   │   └── types.h
│   │   ├── types.h
│   │   └── z80/
│   │       ├── provides.h
│   │       ├── stdarg.h
│   │       └── types.h
│   └── gb/
│       ├── cgb.h
│       ├── console.h
│       ├── drawing.h
│       ├── font.h
│       ├── gb.h
│       ├── hardware.h
│       ├── malloc.h
│       ├── rand.h
│       ├── sample.h
│       └── sgb.h
└── libc/
    ├── arand.s
    ├── cgb.s
    ├── cpy_data.s
    ├── crt0.s
    ├── delay.s
    ├── digits.c
    ├── drawing.s
    ├── f_ibm_sh.s
    ├── f_italic.s
    ├── f_min.s
    ├── f_spect.s
    ├── font.s
    ├── get_bk_t.s
    ├── get_data.s
    ├── get_prop.s
    ├── get_spr.s
    ├── get_wi_t.s
    ├── get_xy_t.s
    ├── global.s
    ├── gprint.c
    ├── gprintf.c
    ├── gprintln.c
    ├── gprintn.c
    ├── hiramcpy.s
    ├── ibmfixed.s
    ├── init_tt.s
    ├── input.s
    ├── mv_bkg.s
    ├── mv_spr.s
    ├── mv_win.s
    ├── pad.s
    ├── rand.s
    ├── sample.s
    ├── scroll_b.s
    ├── scroll_s.s
    ├── scroll_w.s
    ├── serial.s
    ├── set_bk_t.s
    ├── set_data.s
    ├── set_prop.s
    ├── set_spr.s
    ├── set_wi_t.s
    ├── set_xy_t.s
    ├── sfr.s
    ├── sgb.s
    └── stubs.rasm

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
lib/*
obj/*


================================================
FILE: Make.bat
================================================
echo off

set SRCDIR=libc
set OBJDIR=obj
set LIBDIR=lib

set CC=bin\gbdk-n-compile.bat
set CA=bin\gbdk-n-assemble.bat

:: Build examples
if "%1"=="examples" (
	cd examples
	echo Building: galaxy && cd galaxy && call Make.bat
	echo. && echo Building: paint && cd ../paint && call Make.bat
	echo. && echo Building: space && cd ../space && call Make.bat
	echo. && echo Building: thumby && cd ../thumby && call Make.bat
	cd ..\..
	goto end
)

:: Clean libc + examples
if "%1"=="clean" (
	echo Cleaning: libc

	if exist %OBJDIR% rd /s/q %OBJDIR%
	if exist %LIBDIR% rd /s/q %LIBDIR%
	
	cd examples
	echo Cleaning: galaxy && cd galaxy && call Make.bat clean
	echo Cleaning: paint && cd ..\paint && call Make.bat clean
	echo Cleaning: space && cd ..\space && call Make.bat clean
	echo Cleaning: thumby && cd ..\thumby && call Make.bat clean
	cd ..\..
	echo.
	goto end
)

:: Build libc sources
if not exist %OBJDIR% md %OBJDIR%

echo Building gb.lib && echo.

for %%A in (%SRCDIR%\*.c) do (
	if exist %OBJDIR%\%%~nA.rel del %OBJDIR%\%%~nA.rel
	echo Compiling: %%~nxA && call %CC% %SRCDIR%\%%~nA.c -o %OBJDIR%\%%~nA.rel
	if not exist %OBJDIR%\%%~nA.rel echo. && echo Build failed! && echo. && pause && goto end
)
for %%A in (%SRCDIR%\*.s) do (
	if exist %OBJDIR%\%%~nA.rel del %OBJDIR%\%%~nA.rel
	echo Assembling: %%~nxA && call %CA% %OBJDIR%\%%~nA.rel %SRCDIR%\%%~nA.s
	if not exist %OBJDIR%\%%~nA.rel echo. && echo Build failed! && echo. && pause && goto end
)

if not exist %LIBDIR% md %LIBDIR%
if exist %LIBDIR%\crt0.rel del %LIBDIR%\crt0.rel
copy /b/v/y %OBJDIR%\crt0.rel %LIBDIR%\crt0.rel

:: Write list of inputs for the library
if exist %LIBDIR%\gb.lib del %LIBDIR%\gb.lib
for %%A in (%OBJDIR%\*.rel) do (
	sdar -qv %LIBDIR%\gb.lib %%A
)

echo.
if not exist %LIBDIR%\gb.lib (
	echo Build failed!
) else (
	echo Build succeeded!
)
echo.

:end

================================================
FILE: Makefile
================================================
SRCDIR=./libc
OBJDIR=./obj
LIBDIR=./lib

CC=bin/gbdk-n-compile.sh
CA=bin/gbdk-n-assemble.sh

.PHONY: lib
lib: $(LIBDIR)/gb.lib $(LIBDIR)/crt0.rel

$(LIBDIR)/gb.lib: $(LIBDIR)/crt0.rel
	sdar -qv $(LIBDIR)/gb.lib $(OBJDIR)/*.rel

$(LIBDIR)/crt0.rel:
	chmod u+x bin/*
	mkdir -p $(OBJDIR)
	$(CC) $(SRCDIR)/digits.c -o $(OBJDIR)/digits.rel
	$(CC) $(SRCDIR)/gprint.c -o $(OBJDIR)/gprint.rel
	$(CC) $(SRCDIR)/gprintf.c -o $(OBJDIR)/gprintf.rel
	$(CC) $(SRCDIR)/gprintln.c -o $(OBJDIR)/gprintln.rel
	$(CC) $(SRCDIR)/gprintn.c -o $(OBJDIR)/gprintn.rel

	$(CA) $(OBJDIR)/arand.rel $(SRCDIR)/arand.s
	$(CA) $(OBJDIR)/cgb.rel $(SRCDIR)/cgb.s
	$(CA) $(OBJDIR)/cpy_data.rel $(SRCDIR)/cpy_data.s
	$(CA) $(OBJDIR)/delay.rel $(SRCDIR)/delay.s
	$(CA) $(OBJDIR)/drawing.rel $(SRCDIR)/drawing.s
	$(CA) $(OBJDIR)/f_ibm_sh.rel $(SRCDIR)/f_ibm_sh.s
	$(CA) $(OBJDIR)/f_italic.rel $(SRCDIR)/f_italic.s
	$(CA) $(OBJDIR)/f_min.rel $(SRCDIR)/f_min.s
	$(CA) $(OBJDIR)/font.rel $(SRCDIR)/font.s
	$(CA) $(OBJDIR)/f_spect.rel $(SRCDIR)/f_spect.s
	$(CA) $(OBJDIR)/get_bk_t.rel $(SRCDIR)/get_bk_t.s
	$(CA) $(OBJDIR)/get_data.rel $(SRCDIR)/get_data.s
	$(CA) $(OBJDIR)/get_prop.rel $(SRCDIR)/get_prop.s
	$(CA) $(OBJDIR)/get_spr.rel $(SRCDIR)/get_spr.s
	$(CA) $(OBJDIR)/get_wi_t.rel $(SRCDIR)/get_wi_t.s
	$(CA) $(OBJDIR)/get_xy_t.rel $(SRCDIR)/get_xy_t.s
	$(CA) $(OBJDIR)/global.rel $(SRCDIR)/global.s
	$(CA) $(OBJDIR)/hiramcpy.rel $(SRCDIR)/hiramcpy.s
	$(CA) $(OBJDIR)/ibmfixed.rel $(SRCDIR)/ibmfixed.s
	$(CA) $(OBJDIR)/init_tt.rel $(SRCDIR)/init_tt.s
	$(CA) $(OBJDIR)/input.rel $(SRCDIR)/input.s
	$(CA) $(OBJDIR)/mv_bkg.rel $(SRCDIR)/mv_bkg.s
	$(CA) $(OBJDIR)/mv_spr.rel $(SRCDIR)/mv_spr.s
	$(CA) $(OBJDIR)/mv_win.rel $(SRCDIR)/mv_win.s
	$(CA) $(OBJDIR)/pad.rel $(SRCDIR)/pad.s
	$(CA) $(OBJDIR)/rand.rel $(SRCDIR)/rand.s
	$(CA) $(OBJDIR)/sample.rel $(SRCDIR)/sample.s
	$(CA) $(OBJDIR)/scroll_b.rel $(SRCDIR)/scroll_b.s
	$(CA) $(OBJDIR)/scroll_s.rel $(SRCDIR)/scroll_s.s
	$(CA) $(OBJDIR)/scroll_w.rel $(SRCDIR)/scroll_w.s
	$(CA) $(OBJDIR)/serial.rel $(SRCDIR)/serial.s
	$(CA) $(OBJDIR)/set_bk_t.rel $(SRCDIR)/set_bk_t.s
	$(CA) $(OBJDIR)/set_data.rel $(SRCDIR)/set_data.s
	$(CA) $(OBJDIR)/set_prop.rel $(SRCDIR)/set_prop.s
	$(CA) $(OBJDIR)/set_spr.rel $(SRCDIR)/set_spr.s
	$(CA) $(OBJDIR)/set_wi_t.rel $(SRCDIR)/set_wi_t.s
	$(CA) $(OBJDIR)/set_xy_t.rel $(SRCDIR)/set_xy_t.s
	$(CA) $(OBJDIR)/sfr.rel $(SRCDIR)/sfr.s
	$(CA) $(OBJDIR)/sgb.rel $(SRCDIR)/sgb.s
	$(CA) $(OBJDIR)/crt0.rel $(SRCDIR)/crt0.s

	mkdir -p $(LIBDIR)
	cp $(OBJDIR)/crt0.rel $(LIBDIR)/


.PHONY: examples
examples: lib
	$(MAKE) -C examples/galaxy
	$(MAKE) -C examples/space
	$(MAKE) -C examples/thumby
	$(MAKE) -C examples/paint

.PHONY: clean
clean:
	rm -rf $(OBJDIR)/*
	rm -rf $(LIBDIR)/*
	$(MAKE) -C examples/galaxy clean
	$(MAKE) -C examples/space clean
	$(MAKE) -C examples/thumby clean
	$(MAKE) -C examples/paint clean


================================================
FILE: README.md
================================================
# gbdk-n

#### Background

The Gameboy Development Kit (GBDK) is an SDK for developing applications/games for the gameboy platform. The library bundles a custom version of the Small Device C Compiler (SDCC), libraries & examples.

The latest update of GBDK was a long time ago (mid 2002). Since then the SDCC compiler has gotten native support for compiling and linking fully functional gameboy roms. 

However GBDK is still useful since it contains libraries for developing applications for the gameboy family. This project aims to update the libraries to be compatible with new versions of SDCC and provide helpers for building roms.

The GBDK libraries are copied from the latest source release on sourceforge: http://sourceforge.net/projects/gbdk/files/gbdk/2.96/

#### Usage

##### Building the library:
`$ make`

##### Building the examples:
`$ make examples`

##### Building custom ROMs:
NOTE: All commands listed below are simply wrappers to SDCC, see the SDCC documentation for flags and general usage.

* Compile / assemble .c files and .asm files into .rel files using the gbdk-n-compile.sh and gbdk-n-assemble.sh commands respectively.
* Link together one or more .rel files into an .ihx file using the gbdk-n-link.sh command.
* Create a ready to use .gb rom file from the .ihx file with the gbdk-n-make-rom.sh command.

For exact commands, please see the Makefiles for the example programs.


================================================
FILE: bin/gbdk-n-assemble.bat
================================================
set GBDK_DIR=%~dp0..

sdasgb -plosgff -I"libc" %*


================================================
FILE: bin/gbdk-n-assemble.sh
================================================
#!/bin/sh

GBDK_DIR="$( cd "$( dirname "$0" )" && pwd )/.."

set -x

sdasgb -plosgff -I"libc" "$@"


================================================
FILE: bin/gbdk-n-compile.bat
================================================
set GBDK_DIR=%~dp0..

sdcc -mgbz80 --no-std-crt0 -I "%GBDK_DIR%\include" -I "%GBDK_DIR%\include\asm" -c %*

================================================
FILE: bin/gbdk-n-compile.sh
================================================
#!/bin/sh

GBDK_DIR="$( cd "$( dirname "$0" )" && pwd )/.."

set -x
  
sdcc -mgbz80 --no-std-crt0 -I "$GBDK_DIR/include" -I "$GBDK_DIR/include/asm" -c "$@"


================================================
FILE: bin/gbdk-n-link.bat
================================================
set GBDK_DIR=%~dp0..
  
sdcc -mgbz80 --no-std-crt0 --data-loc 0xc0a0 -L "%GBDK_DIR%\lib" "%GBDK_DIR%\lib\crt0.rel" gb.lib -o a.ihx %*


================================================
FILE: bin/gbdk-n-link.sh
================================================
#!/bin/sh

GBDK_DIR="$( cd "$( dirname "$0" )" && pwd )/.."

set -x
  
sdcc -mgbz80 --no-std-crt0 --data-loc 0xc0a0 -L "$GBDK_DIR/lib" "$GBDK_DIR/lib/crt0.rel" gb.lib -o a.ihx "$@"


================================================
FILE: bin/gbdk-n-make-rom.bat
================================================
makebin -Z %*


================================================
FILE: bin/gbdk-n-make-rom.sh
================================================
#!/bin/sh

set -x

makebin -Z "$@"


================================================
FILE: examples/galaxy/Make.bat
================================================
echo off
set BIN=..\..\bin
set OBJ=obj

if "%1"=="clean" (
	if exist %OBJ% rd /s/q %OBJ%
	if exist galaxy.gb del galaxy.gb
	goto end
)

if not exist %OBJ% mkdir %OBJ%
call %BIN%\gbdk-n-compile.bat galaxy.c -o %OBJ%\galaxy.rel
call %BIN%\gbdk-n-link.bat %OBJ%\galaxy.rel -o %OBJ%\galaxy.ihx
call %BIN%\gbdk-n-make-rom.bat %OBJ%\galaxy.ihx galaxy.gb

:end


================================================
FILE: examples/galaxy/Makefile
================================================
BIN=../../bin
OBJ=./obj



build:
	mkdir -p $(OBJ)
	$(BIN)/gbdk-n-compile.sh galaxy.c -o $(OBJ)/galaxy.rel
	$(BIN)/gbdk-n-link.sh $(OBJ)/galaxy.rel -o $(OBJ)/galaxy.ihx
	$(BIN)/gbdk-n-make-rom.sh $(OBJ)/galaxy.ihx galaxy.gb

clean:
	rm -rf $(OBJ)
	rm -f galaxy.gb


================================================
FILE: examples/galaxy/galaxy.c
================================================
/*
 * C version of the 'space' assembly demo.
 *
 * Little demo illustrating how to use the graphical possibilities
 *  of the GB (background, window and animated sprite)
 * I have used fixed-point values for both the position and
 *  speed of objects to get smooth movements
 * 
 * OBJ data             : 0x8000 -> 0x8FFF (unsigned)
 * Window data          : 0x8800 -> 0x97FF (unsigned)
 * Background data      : 0x8800 -> 0x97FF (signed)
 * 
 * Tiled 0xFC -> 0xFF are standard tiles (all black -> all white)
 * 
 * Keys:
 * Arrow keys           : Change the speed (and direction) of the sprite
 * Arrow keys + A       : Change the speed (and direction) of the window
 * Arrow keys + B       : Change the speed (and direction) of the background
 * START                : Open/close the door
 * SELECT               : Basic fading effect
 * 
 * Note that the window is kept in the lower right part of the screen
 * since it can't be made transparent
 */

#include <gb/gb.h>

const unsigned char std_data[] = {

  /* Basic tiles (0xFC to 0xFF) */
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,
  0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};

const unsigned char earth_data[] = {

  /* Tile 0x00 */
  0x07,0x07,0x18,0x1F,0x32,0x2D,0x71,0x4E,0x70,0x4F,0xF8,0x87,0xF8,0x87,0xF8,0x87,
  0xFC,0x83,0xFE,0x81,0x7F,0x40,0x7F,0x40,0x3F,0x20,0x1F,0x18,0x07,0x07,0x00,0x00,
  0xC0,0xC0,0xF0,0x30,0x78,0x88,0x3C,0xC4,0x5C,0xA4,0x9E,0x62,0x3E,0xC2,0x3E,0xC2,
  0x5E,0xA2,0x7E,0x82,0x0C,0xF4,0x0C,0xF4,0x98,0x68,0xB0,0x70,0xC0,0xC0,0x00,0x00,
  0x07,0x07,0x1F,0x18,0x2F,0x30,0x4F,0x70,0x6F,0x50,0x9F,0xE0,0x9F,0xE0,0xBF,0xC0,
  0xFF,0x80,0xB7,0xC8,0x63,0x5C,0x43,0x7C,0x3F,0x20,0x1F,0x18,0x07,0x07,0x00,0x00,
  0xC0,0xC0,0xB0,0x70,0x18,0xE8,0x0C,0xF4,0x0C,0xF4,0x82,0x7E,0x82,0x7E,0x86,0x7A,
  0xC6,0x3A,0xE6,0x1A,0xF4,0x0C,0xFC,0x04,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00,

  /* Tile 0x08 */
  0x07,0x07,0x1E,0x19,0x20,0x3F,0x40,0x7F,0x42,0x7D,0x81,0xFE,0x81,0xFE,0x83,0xFC,
  0xD7,0xA8,0xBB,0xC4,0x6E,0x51,0x7C,0x43,0x3F,0x20,0x1F,0x18,0x07,0x07,0x00,0x00,
  0xC0,0xC0,0x70,0xB0,0xE8,0x18,0xF4,0x0C,0xF4,0x0C,0xFE,0x02,0xFE,0x02,0xFE,0x02,
  0xFE,0x02,0x7E,0x82,0x3C,0xC4,0x3C,0xC4,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00,
  0x07,0x07,0x1B,0x1C,0x20,0x3F,0x40,0x7F,0x40,0x7F,0xE0,0x9F,0x90,0xEF,0x89,0xF6,
  0x8D,0xF2,0x9F,0xE0,0x5E,0x61,0x6F,0x50,0x3F,0x20,0x1F,0x18,0x07,0x07,0x00,0x00,
  0xC0,0xC0,0xB0,0x70,0x28,0xD8,0x04,0xFC,0x2C,0xD4,0x1E,0xE2,0x1E,0xE2,0x3E,0xC2,
  0x7E,0x82,0xB6,0x4A,0xE4,0x1C,0xC4,0x3C,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00,

  /* Tile 0x10 */
  0x07,0x07,0x18,0x1F,0x20,0x3F,0x40,0x7F,0x40,0x7F,0xEE,0x91,0xF1,0x8E,0xE0,0x9F,
  0xE0,0x9F,0xF1,0x8E,0x71,0x4E,0x72,0x4D,0x3F,0x20,0x1F,0x18,0x07,0x07,0x00,0x00,
  0xC0,0xC0,0xF0,0x30,0x08,0xF8,0x04,0xFC,0x04,0xFC,0x02,0xFE,0x02,0xFE,0x92,0x6E,
  0xD6,0x2A,0xFE,0x02,0xEC,0x14,0xFC,0x04,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00,
  0x07,0x07,0x1D,0x1A,0x36,0x29,0x5C,0x63,0x6C,0x53,0xCE,0xB1,0x9F,0xE0,0x9E,0xE1,
  0xAE,0xD1,0xBF,0xC0,0x47,0x78,0x47,0x78,0x2F,0x30,0x1F,0x18,0x07,0x07,0x00,0x00,
  0xC0,0xC0,0x70,0xB0,0x08,0xF8,0x04,0xFC,0x04,0xFC,0xE2,0x1E,0x32,0xCE,0x0E,0xF2,
  0x0E,0xF2,0x1E,0xE2,0x1C,0xE4,0x2C,0xD4,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00,

  /* Tile 0x18 */
  0x07,0x07,0x1E,0x19,0x33,0x2C,0x49,0x76,0x42,0x7D,0xC4,0xBB,0xC1,0xBE,0xC1,0xBE,
  0xE2,0x9D,0xF3,0x8C,0x78,0x47,0x78,0x47,0x3C,0x23,0x1C,0x1B,0x07,0x07,0x00,0x00,
  0xC0,0xC0,0x70,0xB0,0x68,0x98,0xC4,0x3C,0xC4,0x3C,0xEE,0x12,0xF2,0x0E,0xE2,0x1E,
  0xE2,0x1E,0xF2,0x0E,0x7C,0x84,0x7C,0x84,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00
};

const unsigned char frame_data[] = {

  /* Tile 0x00 */
  0xFF,0x00,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,
  0xFF,0x00,0x01,0xFE,0x03,0xFC,0x07,0xF8,0x0F,0xF0,0x1F,0xE0,0x3F,0xC0,0x7F,0x80,
  0xFF,0x00,0xFE,0x01,0xFC,0x03,0xF8,0x07,0xF0,0x0F,0xE0,0x1F,0xC0,0x3F,0x80,0x7F,
  0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
  0xFF,0x00,0xFF,0x01,0xFD,0x03,0xF9,0x07,0xF1,0x0F,0xE1,0x1F,0xC1,0x3F,0x81,0x7F,
  0x80,0x7F,0x81,0x7E,0x83,0x7C,0x87,0x78,0x8F,0x70,0x9F,0x60,0xBF,0x40,0xFF,0x00,
  0xFF,0x70,0xFF,0x98,0xEF,0xB8,0xCF,0xF8,0xFF,0x70,0xFF,0x00,0xFF,0x00,0xFF,0x01,
  0xFF,0x00,0xFE,0x01,0xFC,0x03,0xF8,0x07,0xF0,0x0F,0xE0,0x1F,0xC0,0x3F,0xFF,0xFF,

  /* Tile 0x08 */
  0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,
  0x00,0xFF,0x01,0xFE,0x03,0xFC,0x07,0xF8,0x0F,0xF0,0x1F,0xE0,0x3F,0xC0,0xFF,0xFF,
  0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,
  0xFF,0x0E,0xFF,0x13,0xFD,0x17,0xF9,0x1F,0xFE,0x0F,0xE0,0x1F,0xC0,0x3F,0x80,0xFF,
  0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,
  0xFF,0x01,0xFF,0x01,0xFD,0x03,0xF9,0x07,0xF1,0x0F,0xE1,0x1F,0xC1,0x3F,0x81,0x7F,
  0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,
  0x01,0xFF,0x01,0xFF,0x03,0xFD,0x07,0xF9,0x0F,0xF1,0x1F,0xE1,0x3F,0xC1,0x7F,0x81,

  /* Tile 0x10 */
  0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,
  0x01,0xFF,0x01,0xFE,0x03,0xFC,0x77,0xF8,0xFF,0x98,0xEF,0xB8,0xCF,0xF8,0x7F,0xF0,
  0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x0E,0xFF,0x13,0xFD,0x17,0xF9,0x1F,0xFF,0x0E,
  0x80,0x7F,0x81,0x7E,0x83,0x7C,0x87,0x78,0x8F,0x70,0x9F,0x60,0xBF,0x40,0xFF,0x7F,
  0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0xFF,0xFF,

  /* Door1 */

  /* Tile 0x15 */
  0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,
  0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,
  0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,

  /* Door2 */

  /* Tile 0x18 */
  0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,
  0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,
  0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,
  0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,

  /* Door3 */

  /* Tile 0x1C */
  0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,
  0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,
  0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,
  0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,

  /* Door4 */

  /* Tile 0x20 */
  0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};

const unsigned char bkg_data[] = {

  /* Tile 0x00 */
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xF7,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xDF,0xFF,0xEF,0xFF,0xFF,0xF7,0xFF,0xFB,0xFF,0xFD,0xFF,0xFE,0xFE,0xFF,

  /* Tile 0x08 */
  0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7D,0xFE,0x7C,0x39,
  0xFF,0xFF,0xF7,0xFF,0xEF,0xFF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF,0xFD,
  0xBB,0x01,0xC7,0x83,0xC7,0x83,0xC7,0x83,0xBB,0x01,0x7C,0x39,0x7D,0xFE,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,
  0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFB,0xAF,0x77,0x27,0x8F,0xDF,0x8F,0x27,0x8F,

  /* Tile 0x10 */
  0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFB,0xFF,0xF7,0xEF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xBF,0xFF,0xDF,0xEF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFE,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xAF,0x77,0xFF,0xFB,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,

  /* Tile 0x18 */
  0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0x7D,0xFE,0x7C,0x39,
  0xFF,0xFF,0xF7,0xFF,0xEF,0xFF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0x7F,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFD,

  /* Tile 0x20 */
  0xFF,0xFF,0xDF,0xFF,0xEF,0xFF,0xFF,0xF7,0xFF,0xFB,0xFE,0xFD,0xFD,0xFE,0xFE,0xFF,
  0xAB,0x11,0xC7,0x83,0x83,0xC7,0xC7,0x83,0xAB,0x11,0x7C,0x39,0x7D,0xFE,0xFE,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFB,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0x7F,
  0xFB,0xFF,0xFF,0xFD,0xFE,0xFE,0xFE,0xFF,0xFE,0xFE,0xFF,0xFD,0xFB,0xFF,0xFF,0xFF,
  0xEF,0xFF,0xFF,0xDF,0x3F,0xBF,0x3F,0x7F,0x3F,0xBF,0xFF,0xDF,0xEF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFB,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFD,0xFE,0xFE,0xFD,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,

  /* Tile 0x28 */
  0xF7,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};

/*
 * Image size: 0x40 x 0x40
 * Number of tiles (total - unique): 0x40 - 0x2D
 */

const unsigned char bkg_tiles[] = {
  0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC,
  0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A,
  0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC,
  0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14,
  0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC,
  0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20,
  0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26,
  0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11
};

/*
 * Image size: 0x10 x 0x70
 * Number of tiles (total - unique): 0x1C - 0x1C
 */

const unsigned char earth_tiles[] = {
  0x00,0x02,
  0x04,0x06,
  0x08,0x0A,
  0x0C,0x0E,
  0x10,0x12,
  0x14,0x16,
  0x18,0x1A
};

/*
 * Image size: 0x80 x 0x50
 * Number of tiles (total - unique): 0xA0 - 0x15
 */

const unsigned char frame_tiles[] = {
  0x80,0x81,0xFD,0x82,0x83,0x81,0xFD,0x82,0x83,0x81,0xFD,0x82,0x83,0x81,0xFD,0x84,
  0x85,0x86,0x87,0x88,0x89,0x8A,0x87,0x88,0x89,0x8A,0x87,0x88,0x89,0x8A,0x8B,0x8C,
  0xFD,0x8D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x8F,
  0x82,0x8C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x85,0x90,
  0x8E,0x8F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x8D,
  0x85,0x90,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x82,0x8C,
  0xFD,0x8D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x8F,
  0x82,0x8C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x85,0x90,
  0x8E,0x91,0xFD,0x82,0x83,0x81,0xFD,0x82,0x83,0x81,0xFD,0x82,0x83,0x81,0x92,0x8D,
  0x93,0x8A,0x87,0x88,0x89,0x8A,0x87,0x88,0x89,0x8A,0x87,0x88,0x89,0x8A,0x87,0x94
};

/*
 * Image size: 0x60 x 0x30
 * Number of tiles (total - unique): 0x48 - 0x03
 */

const unsigned char door1_tiles[] = {
  0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,
  0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,
  0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,
  0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,
  0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,
  0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,

  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
};

/*
 * Image size: 0x60 x 0x30
 * Number of tiles (total - unique): 0x48 - 0x04
 */

const unsigned char door2_tiles[] = {
  0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,
  0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,
  0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,
  0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,
  0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,
  0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,

  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
};

/*
 * Image size: 0x60 x 0x30
 * Number of tiles (total - unique): 0x48 - 0x04
 */

const unsigned char door3_tiles[] = {
  0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,
  0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,
  0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,
  0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,
  0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,
  0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,

  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
};

/*
 * Image size: 0x60 x 0x30
 * Number of tiles (total - unique): 0x48 - 0x01
 */

const unsigned char door4_tiles[] = {
  0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,
  0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,
  0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,
  0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,
  0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,
  0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,

  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
  0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
};

/* Should really be const, but sdcc doesnt yet support it. */
const unsigned char * const film[] = {
  &door1_tiles[0x0C*0],
  &door2_tiles[0x0C*0],
  &door3_tiles[0x0C*0],
  &door4_tiles[0x0C*0],
  &door1_tiles[0x0C*1],
  &door2_tiles[0x0C*1],
  &door3_tiles[0x0C*1],
  &door4_tiles[0x0C*1],
  &door1_tiles[0x0C*2],
  &door2_tiles[0x0C*2],
  &door3_tiles[0x0C*2],
  &door4_tiles[0x0C*2],
  &door1_tiles[0x0C*3],
  &door2_tiles[0x0C*3],
  &door3_tiles[0x0C*3],
  &door4_tiles[0x0C*3],
  &door1_tiles[0x0C*4],
  &door2_tiles[0x0C*4],
  &door3_tiles[0x0C*4],
  &door4_tiles[0x0C*4],
  &door1_tiles[0x0C*5],
  &door2_tiles[0x0C*5],
  &door3_tiles[0x0C*5],
  &door4_tiles[0x0C*5],
  &door1_tiles[0x0C*6]
};

#define NBDFRAMES 0x18                  /* Nb frames for the door */
#define NBSFRAMES 0x07                  /* Nb frames for the sprite */
#define WINSZX    0x80                  /* Size of the picture in the window */
#define WINSZY    0x50
#define MINWINX   (MAXWNDPOSX-WINSZX+1) /* Bounds of the window origin */
#define MINWINY   (MAXWNDPOSY-WINSZY+1)
#define MAXWINX   MAXWNDPOSX
#define MAXWINY   MAXWNDPOSY
#define FADESTEP  0x10                  /* Nb steps for the fading effect */
#define STARTFADE (0x06*FADESTEP)       /* Initial value for the fading effect */

#define CLOSED  0x00
#define OPENING 0x01
#define OPENED  0x02
#define CLOSING 0x03

static UBYTE time;  /* Global "time" value (counter) */
UBYTE doorstate;    /* State of the door (OPENED, CLOSED...) */
UBYTE doorpos;      /* Current position in the door animation */
static UBYTE color; /* Current color for fading effect */
UBYTE sframe;       /* Current frame of the sprite */
fixed bposx, bposy; /* Background position (fixed point) */
fixed bspx, bspy;   /* Background speed (fixed point) */
fixed wposx, wposy; /* Window position (fixed point) */
fixed wspx, wspy;   /* Window speed (fixed point) */
fixed sposx, sposy; /* Sprite position (fixed point) */
fixed sspx, sspy;   /* Sprite speed (fixed point) */

void fade();
void scroll();
void door();
void animate_sprite();
void tile_sprite();
void place_sprite();

/* Fade the screen (off and on) */
void fade()
{
  if(color == 0)
    return;
  switch(color)
    {
    case STARTFADE:
    case STARTFADE-4*FADESTEP:
      BGP_REG = 0xF9U;
      break;
    case STARTFADE-FADESTEP:
    case STARTFADE-3*FADESTEP:
      BGP_REG = 0xFEU;
      break;
    case STARTFADE-2*FADESTEP:
      BGP_REG = 0xFFU;
      break;
    case STARTFADE-5*FADESTEP:
      BGP_REG = 0xE4U;
      break;
    }
  color--;
}

/* Scroll the background, the window and the sprite */
void scroll()
{
  /* Update background */
  bposx.w += bspx.w;
  bposy.w += bspy.w;
  SCX_REG = bposx.b.h;
  SCY_REG = bposy.b.h;

  /* Update window */
  wposx.w += wspx.w ;
  wposy.w += wspy.w ;
  /* X position */
  if(wposx.b.h >= MAXWINX) {
    wposx.b.h = MAXWINX;
    /* Invert speed */
    wspx.w = -(WORD)wspx.w;
  } else if(wposx.b.h <= MINWINX) {
    wposx.b.h = MINWINX;
    /* Invert speed */
    wspx.w = -(WORD)wspx.w;
  }
  WX_REG = wposx.b.h;
  /* Y position */
  if(wposy.b.h >= MAXWINY) {
    wposy.b.h = MAXWINY;
    /* Invert speed */
    wspy.w = -(WORD)wspy.w;
  } else if(wposy.b.h <= MINWINY) {
    wposy.b.h = MINWINY;
    /* Invert speed */
    wspy.w = -(WORD)wspy.w;
  }
  WY_REG = wposy.b.h;

  /* Update sprite */
  sposx.w += sspx.w;
  sposy.w += sspy.w;
  place_sprite();
}

/* Open and close the door */
void door()
{
  if(doorstate == OPENING) {
    doorpos++;
    /* Draw the door in the window */
    set_win_tiles(2, 2, 12, 6, film[doorpos]);
    if(doorpos == NBDFRAMES)
      doorstate = OPENED;
  } else if(doorstate == CLOSING) {
    doorpos--;
    /* Draw the door in the window */
    set_win_tiles(2, 2, 12, 6, film[doorpos]);
    if(doorpos == 0)
      doorstate = CLOSED;
  }
}

/* Animate sprite */
void animate_sprite()
{
  if((time&0x07) == 0) {
    sframe++;
    if(sframe == NBSFRAMES)
      sframe = 0;
    tile_sprite();
  }
}

/* Set sprite tiles */
void tile_sprite()
{
  UBYTE s;

  s = sframe<<1;
  set_sprite_tile(0, earth_tiles[s]);
  set_sprite_tile(1, earth_tiles[s+1]);
}

/* Place sprite */
void place_sprite()
{
  move_sprite(0, sposx.b.h, sposy.b.h);
  move_sprite(1, sposx.b.h+8, sposy.b.h);
}

void main()
{
  UBYTE i, j;

  disable_interrupts();
  DISPLAY_OFF;
  LCDC_REG = 0x67;
  /*
   * LCD        = Off
   * WindowBank = 0x9C00
   * Window     = On
   * BG Chr     = 0x8800
   * BG Bank    = 0x9800
   * OBJ        = 8x16
   * OBJ        = On
   * BG         = On
   */

  doorstate = CLOSED;

  /* Set palettes */
  BGP_REG = OBP0_REG = OBP1_REG = 0xE4U;

  /* Initialize the background */
  set_bkg_data(0xFC, 0x04, std_data);
  set_bkg_data(0x00, 0x2D, bkg_data);
  /*
   * Draw the background
   *
   * Width  = 0x100 = 0x20 * 8
   * Height = 0x100 = 0x20 * 8
   */
  for(i = 0; i < 32; i+=8)
    for(j = 0; j < 32; j+=8)
      set_bkg_tiles(i, j, 8, 8, bkg_tiles);
  bposx.w = 0;
  SCX_REG = 0;
  bposy.w = 0;
  SCY_REG = 0;
  bspx.w = 0xFF00;
  bspy.w = 0x0080;

  /* Initialize the window */
  set_win_data(0x80, 0x21, frame_data);
  /*
   * Draw the frame in the window
   *
   * Width  = 0x80 = 0x10 * 8
   * Height = 0x50 = 0x0A * 8
   */
  set_win_tiles(0, 0, 16, 10, frame_tiles);
  /*
   * Draw the door in the window
   *
   * Width  = 0x60 = 0x20 * 12
   * Height = 0x30 = 0x20 * 6
   */
  set_win_tiles(2, 2, 12, 6, door1_tiles);
  wposx.b.h = MAXWNDPOSX;
  wposx.b.l = 0;
  WX_REG = MAXWNDPOSX;
  wposy.b.h = MAXWNDPOSY;
  wposy.b.l = 0;
  WY_REG = MAXWNDPOSY;
  wspx.w = 0xFF80;
  wspy.w = 0xFFC0;

  /* Initialize the sprite */
  set_sprite_data(0x00, 0x1C, earth_data);
  set_sprite_prop(0, 0x00);
  set_sprite_prop(1, 0x00);
  sframe = 0;
  sposx.w  = 0x1000;
  sposy.w  = 0x1000;
  sspx.w  = 0x0040;
  sspy.w  = 0x0040;
  tile_sprite();
  place_sprite();

  DISPLAY_ON;
  enable_interrupts();

  while(1) {
    /* Skip four VBLs (slow down animation) */
    for(i = 0; i < 4; i++)
      wait_vbl_done();
    time++;
    fade();
    door();
    scroll();
    animate_sprite();
    i = joypad();
    if(i & J_B) {
      if(i & J_UP)
	bspy.w -= 0x0010;
      if(i & J_DOWN)
	bspy.w += 0x0010;
      if(i & J_LEFT)
	bspx.w -= 0x0010;
      if(i & J_RIGHT)
	bspx.w += 0x0010;
    } else if(i & J_A) {
      if(i & J_UP)
	wspy.w -= 0x0010;
      if(i & J_DOWN)
	wspy.w += 0x0010;
      if(i & J_LEFT)
	wspx.w -= 0x0010;
      if(i & J_RIGHT)
	wspx.w += 0x0010;
    } else {
      if(i & J_SELECT)
	color = STARTFADE;
      if(i & J_START)
	if(doorstate == CLOSED) {
	  doorstate = OPENING;
	  doorpos = 0;
	} else if(doorstate == OPENED) {
	  doorstate = CLOSING;
	  doorpos = NBDFRAMES;
	}
      if(i & J_UP)
	sspy.w -= 0x0010;
      if(i & J_DOWN)
	sspy.w += 0x0010;
      if(i & J_LEFT)
	sspx.w -= 0x0010;
      if(i & J_RIGHT)
	sspx.w += 0x0010;
    }
  }
}


================================================
FILE: examples/paint/Make.bat
================================================
echo off
set BIN=..\..\bin
set OBJ=obj

if "%1"=="clean" (
	if exist %OBJ% rd /s/q %OBJ%
	if exist paint.gb del paint.gb
	goto end
)

if not exist %OBJ% mkdir %OBJ%
call %BIN%\gbdk-n-compile.bat paint.c -o %OBJ%\paint.rel
call %BIN%\gbdk-n-link.bat %OBJ%\paint.rel -o %OBJ%\paint.ihx
call %BIN%\gbdk-n-make-rom.bat %OBJ%\paint.ihx paint.gb

:end


================================================
FILE: examples/paint/Makefile
================================================
BIN=../../bin
OBJ=./obj



build:
	mkdir -p $(OBJ)
	$(BIN)/gbdk-n-compile.sh paint.c -o $(OBJ)/paint.rel
	$(BIN)/gbdk-n-link.sh $(OBJ)/paint.rel -o $(OBJ)/paint.ihx
	$(BIN)/gbdk-n-make-rom.sh $(OBJ)/paint.ihx paint.gb

clean:
	rm -rf $(OBJ)
	rm -f paint.gb


================================================
FILE: examples/paint/paint.c
================================================
#include <gb/gb.h>
#include <gb/drawing.h>

#define NB_TOOLS 18
#define NB_DATA_TILES 48

#define ARROW 0
#define PEN 1
#define BRUSH 2
#define FILL 3
#define ERASER 4
#define CROSS 5

#define UNSELECTED 0
#define SELECTED 1

#define FIRST_TOOL 0
#define LAST_TOOL 9
#define FIRST_COLOR 10
#define LAST_COLOR 13
#define FIRST_MODE 14
#define LAST_MODE 17

#define NULL 0

typedef struct icon_info_
{
  UBYTE data_idx; /* Index of data in the data array */
  UBYTE x, y, w, h; /* Position and size (in tiles) */
  UBYTE up, down, left, right; /* Index of next icons (for cursor movements) */
  UBYTE cursor; /* Cursor associated with icon */
} icon_info;

typedef struct cursor_info_
{
  UBYTE data_idx; /* Index of data in the data array */
  UBYTE w, h; /* Size (in tiles) */
  UBYTE hot_x, hot_y; /* Position of hot point, relatice to top-left of sprite (in pixels) */
} cursor_info;

const icon_info icons[] =
{
  /* Pen */
  { 0, 0, 0, 2, 2, 10, 2, 1, 1, 1 }, /* 0 */
  /* Brush */
  { 4, 2, 0, 2, 2, 14, 3, 0, 0, 2 }, /* 1 */
  /* Fill */
  { 8, 0, 2, 2, 2, 0, 4, 3, 3, 3 }, /* 2 */
  /* Eraser */
  { 12, 2, 2, 2, 2, 1, 5, 2, 2, 4 }, /* 3 */
  /* Line */
  { 16, 0, 4, 2, 2, 2, 6, 5, 5, 5 }, /* 4 */
  /* Line */
  { 20, 2, 4, 2, 2, 3, 7, 4, 4, 5 }, /* 5 */
  /* Rectangle */
  { 24, 0, 6, 2, 2, 4, 8, 7, 7, 5 }, /* 6 */
  /* Oval */
  { 28, 2, 6, 2, 2, 5, 9, 6, 6, 5 }, /* 7 */
  /* Filled rectangle */
  { 32, 0, 8, 2, 2, 6, 10, 9, 9, 5 }, /* 8 */
  /* Filled oval */
  { 36, 2, 8, 2, 2, 7, 14, 8, 8, 5 }, /* 9 */
  /* Color */
  { 40, 0, 10, 1, 1, 8, 11, 16, 12, 0 }, /* 10 */
  { 41, 0, 11, 1, 1, 10, 0, 17, 13, 0 }, /* 11 */
  { 42, 1, 10, 1, 1, 8, 13, 10, 14, 0 }, /* 12 */
  { 43, 1, 11, 1, 1, 12, 0, 11, 15, 0 }, /* 13 */
  /* Mode */
  { 44, 2, 10, 1, 1, 9, 15, 12, 16, 0 }, /* 14 */
  { 45, 2, 11, 1, 1, 14, 1, 13, 17, 0 }, /* 15 */
  { 46, 3, 10, 1, 1, 9, 17, 14, 10, 0 }, /* 16 */
  { 47, 3, 11, 1, 1, 16, 1, 15, 11, 0 } /* 17 */
};

const unsigned char data[NB_DATA_TILES][0x10] =
{
  /* Pen */
  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x01 },
  { 0x7E,0x02,0x7D,0x05,0x7B,0x0A,0x77,0x14,0x7F,0x18,0x7F,0x27,0x7F,0x00,0x00,0x7F },
  { 0x00,0x00,0xFE,0x01,0xFE,0x0D,0xF6,0x15,0xEE,0x29,0xDE,0x51,0xBE,0xA1,0x7E,0x41 },
  { 0xFE,0x81,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0xFD,0xFE,0x01,0x00,0xFF },
  /* Brush */
  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x01 },
  { 0x7E,0x02,0x7D,0x0D,0x7F,0x1E,0x7F,0x1E,0x7F,0x1D,0x7F,0x11,0x7F,0x00,0x00,0x7F },
  { 0x00,0x00,0xFE,0x01,0xFE,0x0D,0xF6,0x15,0xEE,0x29,0xDE,0x51,0xBE,0xA1,0x7E,0x41 },
  { 0xFE,0x81,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0xFD,0xFE,0xFD,0xFE,0x01,0x00,0xFF },
  /* Fill */
  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x01,0x7F,0x02,0x7E,0x0C,0x7D,0x18,0x7E,0x1D },
  { 0x7F,0x1B,0x7F,0x19,0x7F,0x18,0x7F,0x08,0x7F,0x08,0x7F,0x08,0x7F,0x00,0x00,0x7F },
  { 0x00,0x00,0xFE,0x01,0xFE,0x81,0xFE,0x41,0x7E,0x21,0xBE,0x71,0x5E,0xE9,0xAE,0xC5 },
  { 0x5E,0x89,0xBE,0x11,0xFE,0xA1,0xFE,0x41,0xFE,0x01,0xFE,0x01,0xFE,0x01,0x00,0xFF },
  /* Eraser */
  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x01,0x7E,0x02,0x7C,0x04 },
  { 0x78,0x08,0x7F,0x1F,0x71,0x11,0x7F,0x1F,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x00,0x7F },
  { 0x00,0x00,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0xF9,0x1E,0x19,0x2E,0x29,0x5E,0x51 },
  { 0xBE,0xA1,0x7E,0x41,0xFE,0x81,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0x00,0xFF },
  /* Line */
  { 0x00,0x00,0x7F,0x00,0x7F,0x20,0x7F,0x10,0x7F,0x08,0x7F,0x04,0x7F,0x02,0x7F,0x01 },
  { 0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x00,0x7F },
  { 0x00,0x00,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01 },
  { 0xFE,0x81,0xFE,0x41,0xFE,0x21,0xFE,0x11,0xFE,0x09,0xFE,0x05,0xFE,0x01,0x00,0xFF },
  /* Arc */
  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x1E,0x7F,0x01,0x7F,0x00,0x7F,0x00,0x7F,0x00 },
  { 0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x00,0x7F },
  { 0x00,0x00,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x81,0xFE,0x41,0xFE,0x21,0xFE,0x11 },
  { 0xFE,0x11,0xFE,0x09,0xFE,0x09,0xFE,0x09,0xFE,0x09,0xFE,0x01,0xFE,0x01,0x00,0xFF },
  /* Rectangle */
  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x3F,0x7F,0x20,0x7F,0x20,0x7F,0x20,0x7F,0x20 },
  { 0x7F,0x20,0x7F,0x20,0x7F,0x20,0x7F,0x20,0x7F,0x3F,0x7F,0x00,0x7F,0x00,0x00,0x7F },
  { 0x00,0x00,0xFE,0x01,0xFE,0x01,0xFE,0xFD,0xFE,0x05,0xFE,0x05,0xFE,0x05,0xFE,0x05 },
  { 0xFE,0x05,0xFE,0x05,0xFE,0x05,0xFE,0x05,0xFE,0xFD,0xFE,0x01,0xFE,0x01,0x00,0xFF },
  /* Oval */
  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x03,0x7F,0x0C,0x7F,0x10,0x7F,0x20,0x7F,0x20 },
  { 0x7F,0x20,0x7F,0x20,0x7F,0x10,0x7F,0x0C,0x7F,0x03,0x7F,0x00,0x7F,0x00,0x00,0x7F },
  { 0x00,0x00,0xFE,0x01,0xFE,0x01,0xFE,0xC1,0xFE,0x31,0xFE,0x09,0xFE,0x05,0xFE,0x05 },
  { 0xFE,0x05,0xFE,0x05,0xFE,0x09,0xFE,0x31,0xFE,0xC1,0xFE,0x01,0xFE,0x01,0x00,0xFF },
  /* Filled rectangle */
  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x3F,0x6A,0x3F,0x75,0x3F,0x6A,0x3F,0x75,0x3F },
  { 0x6A,0x3F,0x75,0x3F,0x6A,0x3F,0x75,0x3F,0x7F,0x3F,0x7F,0x00,0x7F,0x00,0x00,0x7F },
  { 0x00,0x00,0xFE,0x01,0xFE,0x01,0xFE,0xFD,0xAE,0xFD,0x56,0xFD,0xAE,0xFD,0x56,0xFD },
  { 0xAE,0xFD,0x56,0xFD,0xAE,0xFD,0x56,0xFD,0xFE,0xFD,0xFE,0x01,0xFE,0x01,0x00,0xFF },
  /* Filled oval */
  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x03,0x7E,0x0F,0x75,0x1F,0x6A,0x3F,0x75,0x3F },
  { 0x6A,0x3F,0x75,0x3F,0x7A,0x1F,0x7D,0x0F,0x7F,0x03,0x7F,0x00,0x7F,0x00,0x00,0x7F },
  { 0x00,0x00,0xFE,0x01,0xFE,0x01,0xFE,0xC1,0xBE,0xF1,0x5E,0xF9,0xAE,0xFD,0x56,0xFD },
  { 0xAE,0xFD,0x56,0xFD,0xAE,0xF9,0x7E,0xF1,0xFE,0xC1,0xFE,0x01,0xFE,0x01,0x00,0xFF },
  /* Color */
  { 0x00,0x00,0x7F,0x7F,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 },
  { 0x40,0x7F,0x40,0x7F,0x40,0x7F,0x40,0x7F,0x40,0x7F,0x40,0x7F,0x7F,0x7F,0x00,0x7F },
  { 0x00,0x00,0xFE,0xFF,0xFE,0x03,0xFE,0x03,0xFE,0x03,0xFE,0x03,0xFE,0x03,0xFE,0x03 },
  { 0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0x00,0xFF },
  /* Mode */
  { 0x00,0x00,0x7F,0x00,0x7F,0x0C,0x7F,0x10,0x7F,0x08,0x7F,0x04,0x7F,0x18,0x7F,0x00 },
  { 0x7F,0x00,0x7F,0x08,0x7F,0x14,0x7F,0x14,0x7F,0x14,0x7F,0x08,0x7F,0x00,0x00,0x7F },
  { 0x00,0x01,0xFE,0x01,0xFE,0x29,0xFE,0x29,0xFE,0x11,0xFE,0x29,0xFE,0x29,0xFE,0x01 },
  { 0xFE,0x01,0xFE,0x11,0xFE,0x29,0xFE,0x39,0xFE,0x29,0xFE,0x29,0xFE,0x01,0x00,0xFF }
};

const unsigned char selected_data[NB_DATA_TILES][0x10] =
{
  /* Pen */
  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFE },
  { 0x81,0xFD,0x82,0xFA,0x84,0xF5,0x88,0xEB,0x80,0xE7,0x80,0xD8,0x80,0xFF,0xFF,0x80 },
  { 0xFF,0xFF,0x01,0xFE,0x01,0xF2,0x09,0xEA,0x11,0xD6,0x21,0xAE,0x41,0x5E,0x81,0xBE },
  { 0x01,0x7E,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0x02,0x01,0xFE,0xFF,0x00 },
  /* Brush */
  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFE },
  { 0x81,0xFD,0x82,0xF2,0x80,0xE1,0x80,0xE1,0x80,0xE2,0x80,0xEE,0x80,0xFF,0xFF,0x80 },
  { 0xFF,0xFF,0x01,0xFE,0x01,0xF2,0x09,0xEA,0x11,0xD6,0x21,0xAE,0x41,0x5E,0x81,0xBE },
  { 0x01,0x7E,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0x02,0x01,0x02,0x01,0xFE,0xFF,0x00 },
  /* Fill */
  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFE,0x80,0xFD,0x81,0xF3,0x82,0xE7,0x81,0xE2 },
  { 0x80,0xE4,0x80,0xE7,0x80,0xE7,0x80,0xF7,0x80,0xF7,0x80,0xF7,0x80,0xFF,0xFF,0x80 },
  { 0xFF,0xFF,0x01,0xFE,0x01,0x7E,0x01,0xBE,0x81,0xDE,0x41,0x8E,0xA1,0x16,0x51,0x3A },
  { 0xA1,0x76,0x41,0xEE,0x01,0x5E,0x01,0xBE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0xFF,0x00 },
  /* Eraser */
  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFE,0x81,0xFD,0x83,0xFB },
  { 0x87,0xF7,0x80,0xE0,0x8E,0xEE,0x80,0xE0,0x80,0xFF,0x80,0xFF,0x80,0xFF,0xFF,0x80 },
  { 0xFF,0xFF,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0x06,0xE1,0xE6,0xD1,0xD6,0xA1,0xAE },
  { 0x41,0x5E,0x81,0xBE,0x01,0x7E,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0xFF,0x00 },
  /* Line */
  { 0xFF,0xFF,0x80,0xFF,0x80,0xDF,0x80,0xEF,0x80,0xF7,0x80,0xFB,0x80,0xFD,0x80,0xFE },
  { 0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0xFF,0x80 },
  { 0xFF,0xFF,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE },
  { 0x01,0x7E,0x01,0xBE,0x01,0xDE,0x01,0xEE,0x01,0xF6,0x01,0xFA,0x01,0xFE,0xFF,0x00 },
  /* Arc */
  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xE1,0x80,0xFE,0x80,0xFF,0x80,0xFF,0x80,0xFF },
  { 0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0xFF,0x80 },
  { 0xFF,0xFF,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0x7E,0x01,0xBE,0x01,0xDE,0x01,0xEE },
  { 0x01,0xEE,0x01,0xF6,0x01,0xF6,0x01,0xF6,0x01,0xF6,0x01,0xFE,0x01,0xFE,0xFF,0x00 },
  /* Rectangle */
  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xC0,0x80,0xDF,0x80,0xDF,0x80,0xDF,0x80,0xDF },
  { 0x80,0xDF,0x80,0xDF,0x80,0xDF,0x80,0xDF,0x80,0xC0,0x80,0xFF,0x80,0xFF,0xFF,0x80 },
  { 0xFF,0xFF,0x01,0xFE,0x01,0xFE,0x01,0x02,0x01,0xFA,0x01,0xFA,0x01,0xFA,0x01,0xFA },
  { 0x01,0xFA,0x01,0xFA,0x01,0xFA,0x01,0xFA,0x01,0x02,0x01,0xFE,0x01,0xFE,0xFF,0x00 },
  /* Oval */
  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFC,0x80,0xF3,0x80,0xEF,0x80,0xDF,0x80,0xDF },
  { 0x80,0xDF,0x80,0xDF,0x80,0xEF,0x80,0xF3,0x80,0xFC,0x80,0xFF,0x80,0xFF,0xFF,0x80 },
  { 0xFF,0xFF,0x01,0xFE,0x01,0xFE,0x01,0x3E,0x01,0xCE,0x01,0xF6,0x01,0xFA,0x01,0xFA },
  { 0x01,0xFA,0x01,0xFA,0x01,0xF6,0x01,0xCE,0x01,0x3E,0x01,0xFE,0x01,0xFE,0xFF,0x00 },
  /* Filled rectangle */
  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xC0,0x9F,0xC0,0x9F,0xC0,0x9F,0xC0,0x9F,0xC0 },
  { 0x9F,0xC0,0x9F,0xC0,0x9F,0xC0,0x9F,0xC0,0x80,0xC0,0x80,0xFF,0x80,0xFF,0xFF,0x80 },
  { 0xFF,0xFF,0x01,0xFE,0x01,0xFE,0x01,0x02,0xF9,0x02,0xF9,0x02,0xF9,0x02,0xF9,0x02 },
  { 0xF9,0x02,0xF9,0x02,0xF9,0x02,0xF9,0x02,0x01,0x02,0x01,0xFE,0x01,0xFE,0xFF,0x00 },
  /* Filled oval */
  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFC,0x83,0xF0,0x8F,0xE0,0x9F,0xC0,0x9F,0xC0 },
  { 0x9F,0xC0,0x9F,0xC0,0x8F,0xE0,0x83,0xF0,0x80,0xFC,0x80,0xFF,0x80,0xFF,0xFF,0x80 },
  { 0xFF,0xFF,0x01,0xFE,0x01,0xFE,0x01,0x3E,0xC1,0x0E,0xF1,0x06,0xF9,0x02,0xF9,0x02 },
  { 0xF9,0x02,0xF9,0x02,0xF1,0x06,0xC1,0x0E,0x01,0x3E,0x01,0xFE,0x01,0xFE,0xFF,0x00 },
  /* Color */
  { 0x00,0x00,0x7F,0x7F,0x61,0x61,0x52,0x52,0x4C,0x4C,0x4C,0x4C,0x52,0x52,0x61,0x61 },
  { 0x40,0x5E,0x40,0x6D,0x40,0x73,0x40,0x73,0x40,0x6D,0x40,0x5E,0x7F,0x7F,0x00,0x7F },
  { 0x00,0x00,0xFE,0xFF,0xFE,0x87,0xFE,0x4B,0xFE,0x33,0xFE,0x33,0xFE,0x4B,0xFE,0x87 },
  { 0x7A,0x7B,0xB6,0xB7,0xCE,0xCF,0xCE,0xCF,0xB6,0xB7,0x7A,0x7B,0xFE,0xFF,0x00,0xFF },
  /* Mode */
  { 0x00,0x00,0x7F,0x7F,0x73,0x73,0x6F,0x6F,0x77,0x77,0x7B,0x7B,0x67,0x67,0x7F,0x7F },
  { 0x7F,0x7F,0x77,0x77,0x6B,0x6B,0x6B,0x6B,0x6B,0x6B,0x77,0x77,0x7F,0x7F,0x00,0x7F },
  { 0x00,0x01,0xFE,0xFF,0xD6,0xD7,0xD6,0xD7,0xEE,0xEF,0xD6,0xD7,0xD6,0xD7,0xFE,0xFF },
  { 0xFE,0xFF,0xEE,0xEF,0xD6,0xD7,0xC6,0xC7,0xD6,0xD7,0xD6,0xD7,0xFE,0xFF,0x00,0xFF }
};

const cursor_info cursors[] =
{
  /* Arrow */
  { 0, 1, 1, 0, 0 },
  /* Pen */
  { 1, 2, 2, 0, 15 },
  /* Brush */
  { 5, 2, 2, 0, 15 },
  /* Fill */
  { 9, 2, 2, 2, 15 },
  /* Eraser */
  { 13, 2, 2, 0, 15 },
  /* Cross */
  { 17, 2, 2, 5, 10 }
};

const unsigned char cursors_data[][0x10] = {
  /* Arrow */
  { 0xFF,0x00,0xFF,0x7E,0xFF,0x7C,0xFE,0x78,0xFF,0x7C,0xFF,0x6E,0xFF,0x46,0xEF,0x00 },
  /* Pen */
  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x07,0x01 },
  { 0x0F,0x02,0x1F,0x05,0x3F,0x0A,0x7F,0x14,0x7E,0x28,0xFC,0x30,0xF8,0x40,0x60,0x00 },
  { 0x00,0x00,0x00,0x00,0x3C,0x00,0x7C,0x18,0xFC,0x28,0xFC,0x50,0xF8,0xA0,0xF0,0x40 },
  { 0xE0,0x80,0xC0,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
  /* Brush */
  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x07,0x01,0x0F,0x02 },
  { 0x1F,0x05,0x7F,0x0A,0xFF,0x34,0xFE,0x78,0xFC,0x78,0xFC,0x70,0xF8,0x40,0x60,0x00 },
  { 0x00,0x00,0x00,0x00,0x78,0x00,0xF8,0x30,0xF8,0x50,0xF8,0xA0,0xF0,0x40,0xE0,0x80 },
  { 0xC0,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
  /* Fill */
  { 0x00,0x00,0x00,0x00,0x07,0x00,0x0F,0x02,0x1F,0x05,0x7F,0x08,0xFE,0x31,0xFD,0x63 },
  { 0xFA,0x77,0xFD,0x6E,0xFF,0x64,0xFF,0x62,0xF7,0x21,0x73,0x20,0x70,0x20,0x50,0x00 },
  { 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xC0,0x00,0xE0,0x80,0xF0,0xC0,0x78,0xA0 },
  { 0xF8,0x10,0xF8,0x20,0xF0,0x40,0xE0,0x80,0xC0,0x00,0x80,0x00,0x00,0x00,0x00,0x00 },
  /* Eraser */
  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x0F,0x03 },
  { 0x1F,0x04,0x3F,0x08,0x7F,0x11,0xFF,0x22,0xFF,0x7D,0xFF,0x46,0xFF,0x7C,0x7E,0x00 },
  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0xF0,0xE0 },
  { 0xF0,0x60,0xF0,0xA0,0xF0,0x40,0xE0,0x80,0xC0,0x00,0x80,0x00,0x00,0x00,0x00,0x00 },
  /* Cross */
  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x04,0x0E,0x04 },
  { 0x0E,0x04,0xFF,0x04,0xFB,0x7B,0xFF,0x04,0x0E,0x04,0x0E,0x04,0x0E,0x04,0x0E,0x00 },
  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
  { 0x00,0x00,0xE0,0x00,0xE0,0xC0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
};

unsigned char data_buffer[NB_DATA_TILES][0x10];

const UBYTE colors[] = { WHITE, DKGREY, LTGREY, BLACK };
const UBYTE modes[] = { SOLID, OR, XOR, AND };

UBYTE current_tool;
UBYTE current_color;
UBYTE current_mode;
UBYTE current_cursor;
UBYTE menu_cursor_pos;

UBYTE cursor_x;
UBYTE cursor_y;

void set_cursor()
{
    UBYTE x, y, i;

    i = 0;
    for(x = 0; x < cursors[current_cursor].w; x++)
	for(y = 0; y < cursors[current_cursor].h; y++) {
	    set_sprite_data(i,
			    1,
			    cursors_data[cursors[current_cursor].data_idx+i]);
	    set_sprite_tile(i, i);
	    set_sprite_prop(i, 0x10);
	    i++;
	}
    /* Hide unused sprites */
    for(; i < 4; i++) {
	move_sprite(i, 0, 0);
    }
}

void move_cursor()
{
  UBYTE x, y;

  for(x = 0; x < cursors[current_cursor].w; x++)
    for(y = 0; y < cursors[current_cursor].h; y++)
      move_sprite((x<<1)+y,
		  cursor_x+8 - cursors[current_cursor].hot_x + (x<<3),
		  cursor_y+16 - cursors[current_cursor].hot_y + (y<<3));
}

void move_menu_cursor()
{
  move_sprite(0,
	      ((icons[menu_cursor_pos].x+icons[menu_cursor_pos].w)<<3) + 4,
	      ((icons[menu_cursor_pos].y+icons[menu_cursor_pos].h)<<3) + 12);
}

void set_icon(UBYTE icon, UBYTE selected)
{
    UBYTE x, y;

    for(x = 0; x < icons[icon].w; x++)
	for(y = 0; y < icons[icon].h; y++) {
	    UWORD index = icons[icon].data_idx+((UWORD)x<<1)+y;
	    switch_data(icons[icon].x + x,
			icons[icon].y + y,
			selected ? selected_data[index] : data[index],
			data_buffer[index]);
	}
}

void change_icon(UBYTE icon, UBYTE selected)
{
  UBYTE x, y;

  for(x = 0; x < icons[icon].w; x++)
    for(y = 0; y < icons[icon].h; y++)
      switch_data(icons[icon].x + x,
		  icons[icon].y + y,
		  (selected ?
		   selected_data[icons[icon].data_idx+((UWORD)x<<1)+y] :
		   data[icons[icon].data_idx+((UWORD)x<<1)+y]),
		  NULL);
}

void reset_icon(UBYTE icon)
{
  UBYTE x, y;

  for(x = 0; x < icons[icon].w; x++)
    for(y = 0; y < icons[icon].h; y++)
      switch_data(icons[icon].x + x,
		  icons[icon].y + y,
		  data_buffer[icons[icon].data_idx+(x<<1)+y],
		  NULL);
}

void splash()
{
  UBYTE x, y;

  cursor_x = 40;
  cursor_y = 50;
  current_cursor = PEN;
  set_cursor();
  move_cursor();
  SHOW_SPRITES;

  for(; cursor_x < 120; cursor_x++) {
    wait_vbl_done();
    move_cursor();
    plot(cursor_x, cursor_y, BLACK, SOLID);
  }
  for(; cursor_y < 94; cursor_y++) {
    wait_vbl_done();
    move_cursor();
    plot(cursor_x, cursor_y, BLACK, SOLID);
  }
  for(; cursor_x > 40; cursor_x--) {
    wait_vbl_done();
    move_cursor();
    plot(cursor_x, cursor_y, BLACK, SOLID);
  }
  for(; cursor_y > 50; cursor_y--) {
    wait_vbl_done();
    move_cursor();
    plot(cursor_x, cursor_y, BLACK, SOLID);
  }
  cursor_x = 160/2;
  cursor_y = 144/2;
  current_cursor = FILL;
  set_cursor();
  move_cursor();

  for(y = 51; y < 94; y++)
    for(x = 41; x < 120; x++)
      plot(x, y, LTGREY, SOLID);

  // HIDE_SPRITES;
}

void menu()
{
  UBYTE i, key;
  UBYTE slowdown;
  UBYTE cursor;

  slowdown = 50;

  for(i = 0; i < NB_TOOLS; i++)
    set_icon(i,
	     i == FIRST_TOOL + current_tool ||
	     i == FIRST_COLOR + current_color ||
	     i == FIRST_MODE + current_mode);

  cursor = current_cursor;
  current_cursor = ARROW;
  set_cursor();
  move_menu_cursor();
  SHOW_SPRITES;
  waitpadup();
  do {
    wait_vbl_done();
    key = joypad();
    if(key & (J_UP|J_DOWN|J_LEFT|J_RIGHT)) {
      if(key & J_UP)
	menu_cursor_pos = icons[menu_cursor_pos].up;
      if(key & J_DOWN)
	menu_cursor_pos = icons[menu_cursor_pos].down;
      if(key & J_LEFT)
	menu_cursor_pos = icons[menu_cursor_pos].left;
      if(key & J_RIGHT)
	menu_cursor_pos = icons[menu_cursor_pos].right;
      move_menu_cursor();
      while(slowdown && key == joypad()) {
	wait_vbl_done();
	slowdown--;
      }
      slowdown = 10;
    } else
      slowdown = 50;
    if(key & J_A) {
      if( /* menu_cursor_pos >= FIRST_TOOL && */ menu_cursor_pos <= LAST_TOOL) {
	if(menu_cursor_pos != /* FIRST_TOOL + */ current_tool) {
	  change_icon(/* FIRST_TOOL + */ current_tool, UNSELECTED);
	  current_tool = menu_cursor_pos /* - FIRST_TOOL */;
	  change_icon(/* FIRST_TOOL + */ current_tool, SELECTED);
	  cursor = icons[/* FIRST_TOOL + */ current_tool].cursor;
	}
      } else if(menu_cursor_pos >= FIRST_COLOR && menu_cursor_pos <= LAST_COLOR) {
	if(menu_cursor_pos != FIRST_COLOR + current_color) {
	  change_icon(FIRST_COLOR + current_color, UNSELECTED);
	  current_color = menu_cursor_pos - FIRST_COLOR;
	  change_icon(FIRST_COLOR + current_color, SELECTED);
	}
      } else if(menu_cursor_pos >= FIRST_MODE && menu_cursor_pos <= LAST_MODE) {
	if(menu_cursor_pos != FIRST_MODE + current_mode) {
	  change_icon(FIRST_MODE + current_mode, UNSELECTED);
	  current_mode = menu_cursor_pos - FIRST_MODE;
	  change_icon(FIRST_MODE + current_mode, SELECTED);
	}
      }
    }
  } while(key != J_SELECT);
  waitpadup();
  for(i = 0; i < NB_TOOLS; i++)
    reset_icon(i);
  HIDE_SPRITES;
  current_cursor = cursor;
}

void run()
{
  UBYTE key;
  UBYTE slowdown;
  UBYTE drawn, erased;

  slowdown = 10;
  drawn = erased = 0;

  set_cursor();
  move_cursor();
  SHOW_SPRITES;

  while(1) {
    wait_vbl_done();
    key = joypad();
    if(key & (J_UP|J_DOWN|J_LEFT|J_RIGHT)) {
      if(key & J_UP && cursor_y > 0)
	cursor_y--;
      if(key & J_DOWN && cursor_y < 143)
	cursor_y++;
      if(key & J_LEFT && cursor_x > 0)
	cursor_x--;
      if(key & J_RIGHT && cursor_x < 159)
	cursor_x++;
      move_cursor();
      while(slowdown && key == joypad()) {
	wait_vbl_done();
	slowdown--;
      }
      slowdown = 1;
      drawn = erased = 0;
    } else
      slowdown = 10;
    if(key & J_SELECT) {
      HIDE_SPRITES;
      menu();
      set_cursor();
      move_cursor();
      SHOW_SPRITES;
    }
    if((key & (J_A|J_B)) == J_A) {
      if(!drawn) {
	drawn++;
	plot(cursor_x, cursor_y, colors[current_color], modes[current_mode]);
      }
    } else
      drawn = 0;
    if((key & (J_A|J_B)) == J_B) {
      if(!erased) {
	erased++;
	plot(cursor_x, cursor_y, WHITE, SOLID);
      }
    } else
      erased = 0;
  }
}

void main()
{
  /* Initialize sprite palette */
  OBP1_REG = 0xE0U;

  splash();

  current_tool = 0;
  current_color = BLACK;
  current_mode = SOLID;
  current_cursor = PEN;
  menu_cursor_pos = 0;
  cursor_x = 160/2;
  cursor_y = 144/2;

  run();
}


================================================
FILE: examples/space/Make.bat
================================================
echo off
set BIN=..\..\bin
set OBJ=obj

if "%1"=="clean" (
	if exist %OBJ% rd /s/q %OBJ%
	if exist space.gb del space.gb
	goto end
)

if not exist %OBJ% mkdir %OBJ%
call %BIN%\gbdk-n-assemble.bat %OBJ%\space.rel space.s 
call %BIN%\gbdk-n-link.bat %OBJ%\space.rel -o %OBJ%\space.ihx
call %BIN%\gbdk-n-make-rom.bat %OBJ%\space.ihx space.gb

:end


================================================
FILE: examples/space/Makefile
================================================
BIN=../../bin
OBJ=./obj

build:
	mkdir -p $(OBJ)
	$(BIN)/gbdk-n-assemble.sh $(OBJ)/space.rel space.s
	$(BIN)/gbdk-n-link.sh $(OBJ)/space.rel -o $(OBJ)/space.ihx
	$(BIN)/gbdk-n-make-rom.sh $(OBJ)/space.ihx space.gb

clean:
	rm -rf $(OBJ)
	rm -f space.gb


================================================
FILE: examples/space/space.s
================================================
	;; Little demo illustrating how to use the graphical possibilities
	;;  of the GB (background, window and animated sprite)
	;; I have used fixed-point values for both the position and
	;;  speed of objects to get smooth movements
	;; 
	;; OBJ data		: 0x8000 -> 0x8FFF (unsigned)
	;; Window data		: 0x8800 -> 0x97FF (signed)
	;; Background data	: 0x8800 -> 0x97FF (signed)
	;; 
	;; Tiled 0xFC -> 0xFF are standard tiles (all black -> all white)
	;; 
	;; Keys:
	;; Arrow keys		: Change the speed (and direction) of the sprite
	;; Arrow keys + A	: Change the speed (and direction) of the window
	;; Arrow keys + B	: Change the speed (and direction) of the background
	;; START		: Open/close the door
	;; SELECT		: Basic fading effect
	;; 
	;; Note that the window is kept in the lower right part of the screen
	;; since it can't be made transparent

	.include	"../../libc/global.s"

	.globl	.init_vram
	.globl	.copy_vram
	.globl	.init_wtt
	.globl	.init_btt
	.globl	.set_xy_wtt
	.globl	.mv_sprite
	.globl	.set_sprite_prop
	.globl	.set_sprite_tile
	.globl	.jpad

	.NBDFRAMES	= .endfilm-.film	; Nb frames for the door
	.NBSFRAMES	= 0x07			; Nb frames for the sprite
	.WINSZX		= 0x80			; Size of the picture in the window
	.WINSZY		= 0x50
	.MINWINX	= .MAXWNDPOSX-.WINSZX+1 ; Bounds of the window origin
	.MINWINY	= .MAXWNDPOSY-.WINSZY+1
	.MAXWINX	= .MAXWNDPOSX
	.MAXWINY	= .MAXWNDPOSY
	.FADESTEP	= 0x10			; Nb steps for the fading effect
	.STARTFADE	= 0x06*.FADESTEP	; Initial value for the fading effect

	.CLOSED		= 0x00
	.OPENING	= 0x01
	.OPENED		= 0x02
	.CLOSING	= 0x03

	.module	Space

	.area	_BSS

.time:				; Global "time" value (counter)
	.ds	0x01

.doorstate:			; State of the door (OPENED, CLOSED...)
	.ds	0x01
.doorpos:			; Current position in the door animation
	.ds	0x01

.color:				; Current color for fading effect
	.ds	0x01

.sframe:			; Current frame of the sprite
	.ds	0x01

.bposx:				; Background position (fixed point)
	.ds	0x02
.bposy:
	.ds	0x02
.bspx:				; Background speed (fixed point)
	.ds	0x02
.bspy:
	.ds	0x02

.wposx:				; Window position (fixed point)
	.ds	0x02
.wposy:
	.ds	0x02
.wspx:				; Window speed (fixed point)
	.ds	0x02
.wspy:
	.ds	0x02

.sposx:				; Sprite position (fixed point)
	.ds	0x02
.sposy:
	.ds	0x02
.sspx:				; Sprite speed (fixed point)
	.ds	0x02
.sspy:
	.ds	0x02

	.area	_CODE

_main::
	DI			; Disable interrupts
	;; Turn the screen off
	CALL	.display_off

	XOR	A
	LD	(.time),A
	LD	(.color),A

	LD	A,#0b11100100
	LDH	(.BGP),A
	LDH	(.OBP0),A

	; Initialize tiles
	LD	HL,#0x8000
	LD	DE,#0x1000
	LD	B,#0x00
	CALL	.init_vram	; Init the tile set at 0x8000 with 0x00
	LD	B,#0xFF
	CALL	.init_btt	; Init the tiles tables with 0xFF
	CALL	.init_wtt

	LD	BC,#.tp0	; Move tiles (standard tiles)
	LD	HL,#0x9000-(.endtp0-.tp0)
	LD	DE,#.endtp0-.tp0
	CALL	.copy_vram

	LD	BC,#.tp1	; Move tiles (earth)
	LD	HL,#0x8000
	LD	DE,#.endtp1-.tp1
	CALL	.copy_vram

	LD	BC,#.tp2	; Move tiles (door)
	LD	HL,#0x8800
	LD	DE,#.endtp2-.tp2
	CALL	.copy_vram

	LD	BC,#.tp3	; Move tiles (background)
	LD	HL,#0x9000
	LD	DE,#.endtp3-.tp3
	CALL	.copy_vram

	;; Draw the background
	LD	BC,#.bkg_tiles
	LD	HL,#0x9800
	LD	DE,#0x0400	; One whole GB Screen
	CALL	.copy_vram

	;; Draw the frame in the window
	LD	BC,#.frame_tiles
	LD	DE,#0x0000/8	; Place image at (0x00,0x00)
	LD	HL,#0x8050/8	; Image size is 0x80 x 0x50
	CALL	.set_xy_wtt

	;; Draw the door in the window
	LD	BC,#.door1_tiles
	LD	DE,#0x1010/8	; Place image at (0x10,0x10)
	LD	HL,#0x6030/8	; Image size is 0x60 x 0x30
	CALL	.set_xy_wtt
	LD	A,#.CLOSED
	LD	(.doorstate),A

	; Initialize background
	XOR	A
	LD	(.bposx),A
	LDH	(.SCX),A
	LD	(.bposx+1),A
	LD	(.bposy),A
	LDH	(.SCY),A
	LD	(.bposy+1),A
	LD	A,#-0x01
	LD	(.bspx),A
	XOR	A
	LD	(.bspx+1),A
	XOR	A
	LD	(.bspy),A
	LD	A,#0x80
	LD	(.bspy+1),A

	; Initialize window
	LD	A,#.MAXWNDPOSX
	LD	(.wposx),A
	LDH	(.WX),A
	XOR	A
	LD	(.wposx+1),A
	LD	A,#.MAXWNDPOSY
	LD	(.wposy),A
	LDH	(.WY),A
	XOR	A
	LD	(.wposy+1),A
	LD	A,#-0x01
	LD	(.wspx),A
	LD	A,#0x80
	LD	(.wspx+1),A
	LD	A,#-0x01
	LD	(.wspy),A
	LD	A,#0xC0
	LD	(.wspy+1),A

	; Initialize sprite
	XOR	A
	LD	(.sframe),A
	LD	C,#0x00		; Sprite 0x00
	LD	D,#0x00		; Default sprite properties
	CALL	.set_sprite_prop
	LD	C,#0x01		; Sprite 0x01
	LD	D,#0x00		; Default sprite properties
	CALL	.set_sprite_prop

	LD	A,#0x10
	LD	(.sposx),A
	XOR	A
	LD	(.sposx+1),A
	LD	A,#0x10
	LD	(.sposy),A
	XOR	A
	LD	(.sposy+1),A
	XOR	A
	LD	(.sspx),A
	LD	A,#0x40
	LD	(.sspx+1),A
	XOR	A
	LD	(.sspy),A
	LD	A,#0x40
	LD	(.sspy+1),A
	CALL	.tile_sprite	; Set sprite tiles
	CALL	.place_sprite	; Place sprites

	LD	A,#0b11100111	; LCD		= On
				; WindowBank	= 0x9C00
				; Window	= On
				; BG Chr	= 0x8800
				; BG Bank	= 0x9800
				; OBJ		= 8x16
				; OBJ		= On
				; BG		= On
	LDH	(.LCDC),A
	EI			; Enable interrupts
1$:
	LD	A,(.time)
	INC	A
	LD	(.time),A

	LD	B,#0x04		; Skip four VBLs (slow down animation)
2$:
	CALL	.wait_vbl_done
	DEC	B
	JR	NZ,2$

	CALL	.fade
	CALL	.door
	CALL	.scroll
	CALL	.animate_sprite

	CALL	.jpad
	LD	D,A

	AND	#.B		; Is B pressed ?
	JP	NZ,10$

	LD	A,D
	AND	#.A		; Is A pressed ?
	JP	NZ,20$

	LD	A,D
	AND	#.SELECT	; Is SELECT pressed ?
	JR	Z,3$
	LD	A,#.STARTFADE
	LD	(.color),A
3$:
	LD	A,D
	AND	#.START		; Is START pressed ?
	JR	Z,5$
	LD	A,(.doorstate)
	CP	#.CLOSED
	JR	NZ,4$
	LD	A,#.OPENING
	LD	(.doorstate),A
	XOR	A
	LD	(.doorpos),A
	JR	5$
4$:
	CP	#.OPENED
	JR	NZ,5$
	LD	A,#.CLOSING
	LD	(.doorstate),A
	LD	A,#.NBDFRAMES
	LD	(.doorpos),A
5$:
	LD	A,D
	AND	#.UP		; Is UP pressed ?
	JR	Z,6$
	LD	BC,#0x0010
	LD	A,(.sspy)	; Load speed into HL
	LD	H,A
	LD	A,(.sspy+1)
	LD	L,A
	LD	A,L		; Substract BC from HL
	SUB	C
	LD	(.sspy+1),A
	LD	A,H
	SBC	B
	LD	(.sspy),A	; Store new speed
	JR	7$
6$:
	LD	A,D
	AND	#.DOWN		; Is DOWN pressed ?
	JR	Z,7$
	LD	BC,#0x0010
	LD	A,(.sspy)	; Load speed into HL
	LD	H,A
	LD	A,(.sspy+1)
	LD	L,A
	ADD	HL,BC		; Add them
	LD	A,H		; Store new speed
	LD	(.sspy),A
	LD	A,L
	LD	(.sspy+1),A
7$:
	LD	A,D
	AND	#.LEFT		; Is LEFT pressed ?
	JR	Z,8$
	LD	BC,#0x0010
	LD	A,(.sspx)	; Load speed into HL
	LD	H,A
	LD	A,(.sspx+1)
	LD	L,A
	LD	A,L		; Substract BC from HL
	SUB	C
	LD	(.sspx+1),A
	LD	A,H
	SBC	B
	LD	(.sspx),A	; Store new speed
	JP	1$
8$:
	LD	A,D
	AND	#.RIGHT		; Is RIGHT pressed ?
	JP	Z,1$
	LD	BC,#0x0010
	LD	A,(.sspx)	; Load speed into HL
	LD	H,A
	LD	A,(.sspx+1)
	LD	L,A
	ADD	HL,BC		; Add them
	LD	A,H		; Store new speed
	LD	(.sspx),A
	LD	A,L
	LD	(.sspx+1),A
	JP	1$

10$:
	LD	A,D
	AND	#.UP		; Is UP pressed ?
	JP	Z,11$
	LD	BC,#0x0010
	LD	A,(.bspy)	; Load speed into HL
	LD	H,A
	LD	A,(.bspy+1)
	LD	L,A
	LD	A,L		; Substract BC from HL
	SUB	C
	LD	(.bspy+1),A
	LD	A,H
	SBC	B
	LD	(.bspy),A	; Store new speed
	JR	12$
11$:
	LD	A,D
	AND	#.DOWN		; Is DOWN pressed ?
	JP	Z,12$
	LD	BC,#0x0010
	LD	A,(.bspy)	; Load speed into HL
	LD	H,A
	LD	A,(.bspy+1)
	LD	L,A
	ADD	HL,BC		; Add them
	LD	A,H		; Store new speed
	LD	(.bspy),A
	LD	A,L
	LD	(.bspy+1),A
12$:
	LD	A,D
	AND	#.LEFT		; Is LEFT pressed ?
	JP	Z,13$
	LD	BC,#0x0010
	LD	A,(.bspx)	; Load speed into HL
	LD	H,A
	LD	A,(.bspx+1)
	LD	L,A
	LD	A,L		; Substract BC from HL
	SUB	C
	LD	(.bspx+1),A
	LD	A,H
	SBC	B
	LD	(.bspx),A	; Store new speed
	JP	1$
13$:
	LD	A,D
	AND	#.RIGHT		; Is RIGHT pressed ?
	JP	Z,1$
	LD	BC,#0x0010
	LD	A,(.bspx)	; Load speed into HL
	LD	H,A
	LD	A,(.bspx+1)
	LD	L,A
	ADD	HL,BC		; Add them
	LD	A,H		; Store new speed
	LD	(.bspx),A
	LD	A,L
	LD	(.bspx+1),A
	JP	1$

20$:
	LD	A,D
	AND	#.UP		; Is UP pressed ?
	JP	Z,21$
	LD	BC,#0x0010
	LD	A,(.wspy)	; Load speed into HL
	LD	H,A
	LD	A,(.wspy+1)
	LD	L,A
	LD	A,L		; Substract BC from HL
	SUB	C
	LD	(.wspy+1),A
	LD	A,H
	SBC	B
	LD	(.wspy),A	; Store new speed
	JR	22$
21$:
	LD	A,D
	AND	#.DOWN		; Is DOWN pressed ?
	JP	Z,22$
	LD	BC,#0x0010
	LD	A,(.wspy)	; Load speed into HL
	LD	H,A
	LD	A,(.wspy+1)
	LD	L,A
	ADD	HL,BC		; Add them
	LD	A,H		; Store new speed
	LD	(.wspy),A
	LD	A,L
	LD	(.wspy+1),A
22$:
	LD	A,D
	AND	#.LEFT		; Is LEFT pressed ?
	JP	Z,23$
	LD	BC,#0x0010
	LD	A,(.wspx)	; Load speed into HL
	LD	H,A
	LD	A,(.wspx+1)
	LD	L,A
	LD	A,L		; Substract BC from HL
	SUB	C
	LD	(.wspx+1),A
	LD	A,H
	SBC	B
	LD	(.wspx),A	; Store new speed
	JP	1$
23$:
	LD	A,D
	AND	#.RIGHT		; Is RIGHT pressed ?
	JP	Z,1$
	LD	BC,#0x0010
	LD	A,(.wspx)	; Load speed into HL
	LD	H,A
	LD	A,(.wspx+1)
	LD	L,A
	ADD	HL,BC		; Add them
	LD	A,H		; Store new speed
	LD	(.wspx),A
	LD	A,L
	LD	(.wspx+1),A
	JP	1$

	RET

	;; Fade the screen (off and on)
.fade:

	LD	A,(.color)	; Load color into A
	CP	#0x00
	RET	Z
	CP	#.STARTFADE
	JR	NZ,1$
	LD	A,#0b11111001
	JR	6$
1$:
	CP	#.STARTFADE-.FADESTEP
	JR	NZ,2$
	LD	A,#0b11111110
	JR	6$
2$:
	CP	#.STARTFADE-0x02*.FADESTEP
	JR	NZ,3$
	LD	A,#0b11111111
	JR	6$
3$:
	CP	#.STARTFADE-0x03*.FADESTEP
	JR	NZ,4$
	LD	A,#0b11111110
	JR	6$
4$:
	CP	#.STARTFADE-0x04*.FADESTEP
	JR	NZ,5$
	LD	A,#0b11111001
	JR	6$
5$:
	CP	#.STARTFADE-0x05*.FADESTEP
	JR	NZ,7$
	LD	A,#0b11100100
6$:
	LDH	(.BGP),A
7$:
	LD	A,(.color)
	DEC	A
	LD	(.color),A
	RET

	;; Scroll the background, the window and the sprite
.scroll:

	;; Update background
	LD	A,(.bposx)	; Load background position into HL
	LD	H,A
	LD	A,(.bposx+1)
	LD	L,A
	LD	A,(.bspx)	; Load background speed into BC
	LD	B,A
	LD	A,(.bspx+1)
	LD	C,A
	ADD	HL,BC		; Add them
	LD	A,L		; Store new background position
	LD	(.bposx+1),A
	LD	A,H
	LD	(.bposx),A
	LDH	(.SCX),A	; Update position

	LD	A,(.bposy)	; Load background position into HL
	LD	H,A
	LD	A,(.bposy+1)
	LD	L,A
	LD	A,(.bspy)	; Load background speed into BC
	LD	B,A
	LD	A,(.bspy+1)
	LD	C,A
	ADD	HL,BC		; Add them
	LD	A,L		; Store new background position
	LD	(.bposy+1),A
	LD	A,H
	LD	(.bposy),A
	LDH	(.SCY),A	; Update position

	;; Update window
	LD	A,(.wspx)	; Load window speed into BC
	LD	B,A
	LD	A,(.wspx+1)
	LD	C,A
	LD	A,(.wposx)	; Load window position into HL
	LD	H,A
	LD	A,(.wposx+1)
	LD	L,A
	ADD	HL,BC		; Add them
	LD	A,L		; Store new window position
	LD	(.wposx+1),A
	LD	A,H
	LD	(.wposx),A

	;; X position
	LD	A,(.wposx)	; Check window position
	LD	H,#0x00		; We must use 16 bit registers since the
	LD	L,A		;  window is not less than 0x80 pixels
	LD	BC,#.MAXWINX
	LD	A,L		; Substract BC from HL
	SUB	C
	LD	A,H
	SBC	B
	AND	#0x80
	JR	NZ,1$		; Maximum value ?
	LD	A,#.MAXWINX
	LD	(.wposx),A	; Correct window position
	LD	A,(.wspx+1)	; Load window speed into BC
	LD	C,A
	LD	A,(.wspx)
	LD	B,A
	AND	#0x80		; Speed is already negative ?
	JR	NZ,3$
	JR	2$
1$:
	LD	A,(.wposx)	; Check window position
	LD	H,#0x00		; We must use 16 bit registers since the
	LD	L,A		;  window is not less than 0x80 pixels
	LD	BC,#.MINWINX+1
	LD	A,L		; Substract BC from HL
	SUB	C
	LD	A,H
	SBC	B
	AND	#0x80
	JR	Z,3$		; Minimum value ?
	LD	A,#.MINWINX
	LD	(.wposx),A	; Correct window position
	LD	A,(.wspx+1)	; Load window speed into BC
	LD	C,A
	LD	A,(.wspx)
	LD	B,A
	AND	#0x80		; Speed is already positive ?
	JR	Z,3$
2$:
	LD	HL,#0x00	; Invert speed
	LD	A,L		; Substract BC from HL
	SUB	C
	LD	(.wspx+1),A
	LD	A,H
	SBC	B
	LD	(.wspx),A	; Store new speed
3$:
	LD	A,(.wposx)
	LDH	(.WX),A		; Update position

	LD	A,(.wspy)	; Load window speed into BC
	LD	B,A
	LD	A,(.wspy+1)
	LD	C,A
	LD	A,(.wposy)	; Load window position into HL
	LD	H,A
	LD	A,(.wposy+1)
	LD	L,A
	ADD	HL,BC		; Add them
	LD	A,L		; Store new window position
	LD	(.wposy+1),A
	LD	A,H
	LD	(.wposy),A

	;; Y position
	LD	A,(.wposy)	; Check window position
	LD	H,#0x00		; We must use 16 bit registers since the
	LD	L,A		;  window is not less than 0x80 pixels
	LD	BC,#.MAXWINY
	LD	A,L		; Substract BC from HL
	SUB	C
	LD	A,H
	SBC	B
	AND	#0x80
	JR	NZ,4$		; Maximum value ?
	LD	A,#.MAXWINY
	LD	(.wposy),A	; Correct window position
	LD	A,(.wspy+1)	; Load window speed into BC
	LD	C,A
	LD	A,(.wspy)
	LD	B,A
	AND	#0x80		; Speed is already negative ?
	JR	NZ,6$
	JR	5$
4$:
	LD	A,(.wposy)	; Check window position
	LD	H,#0x00		; We must use 16 bit registers since the
	LD	L,A		;  window is not less than 0x80 pixels
	LD	BC,#.MINWINY+1
	LD	A,L		; Substract BC from HL
	SUB	C
	LD	A,H
	SBC	B
	AND	#0x80
	JR	Z,6$		; Minimum value ?
	LD	A,#.MINWINY
	LD	(.wposy),A	; Correct window position
	LD	A,(.wspy+1)	; Load window speed into BC
	LD	C,A
	LD	A,(.wspy)
	LD	B,A
	AND	#0x80		; Speed is already positive ?
	JR	Z,6$
5$:
	LD	HL,#0x00	; Invert speed
	LD	A,L		; Substract BC from HL
	SUB	C
	LD	(.wspy+1),A
	LD	A,H
	SBC	B
	LD	(.wspy),A	; Store new speed
6$:
	LD	A,(.wposy)
	LDH	(.WY),A		; Update position

	;; Update sprite
	LD	A,(.sposx)	; Load sprite position into HL
	LD	H,A
	LD	A,(.sposx+1)
	LD	L,A
	LD	A,(.sspx)	; Load sprite speed into BC
	LD	B,A
	LD	A,(.sspx+1)
	LD	C,A
	ADD	HL,BC		; Add them
	LD	A,L		; Store new sprite position
	LD	(.sposx+1),A
	LD	A,H
	LD	(.sposx),A

	LD	A,(.sposy)	; Load sprite position into HL
	LD	H,A
	LD	A,(.sposy+1)
	LD	L,A
	LD	A,(.sspy)	; Load sprite speed into BC
	LD	B,A
	LD	A,(.sspy+1)
	LD	C,A
	ADD	HL,BC		; Add them
	LD	A,L		; Store new sprite position
	LD	(.sposy+1),A
	LD	A,H
	LD	(.sposy),A
	CALL	.place_sprite	; Update position

	RET

	;; Open and close the door
.door:
	LD	A,(.doorstate)
	CP	#.OPENING
	JP	Z,.open_door
	CP	#.CLOSING
	JP	Z,.close_door
	RET

.open_door:
	LD	A,(.doorpos)
	LD	HL,#.film+0x02
	LD	B,#0x00
	LD	C,A
	ADD	HL,BC
	LD	C,(HL)
	INC	HL
	LD	B,(HL)
	LD	DE,#0x1010/8	; Place image at (0x10,0x10)
	LD	HL,#0x6030/8	; Image size is 0x60 x 0x30
	CALL	.set_xy_wtt

	LD	A,(.doorpos)
	ADD	A,#0x02
	LD	(.doorpos),A
	CP	#.NBDFRAMES
	RET	NZ
	LD	A,#.OPENED
	LD	(.doorstate),A
	RET

.close_door:
	LD	A,(.doorpos)
	LD	HL,#.film-0x02
	LD	B,#0x00
	LD	C,A
	ADD	HL,BC
	LD	C,(HL)
	INC	HL
	LD	B,(HL)
	LD	DE,#0x1010/8	; Place image at (0x10,0x10)
	LD	HL,#0x6030/8	; Image size is 0x60 x 0x30
	CALL	.set_xy_wtt

	LD	A,(.doorpos)
	SUB	A,#0x02
	LD	(.doorpos),A
	RET	NZ
	LD	A,#.CLOSED
	LD	(.doorstate),A
	RET

	;; Animate sprite
.animate_sprite:
	LD	A,(.time)
	AND	#0x07
	RET	NZ

	LD	A,(.sframe)
	INC	A
	CP	#.NBSFRAMES
	JR	NZ,1$
	XOR	A
1$:
	LD	(.sframe),A

	CALL	.tile_sprite
	RET

	;; Set sprite tiles
.tile_sprite:
	LD	A,(.sframe)
	LD	HL,#.earth_tiles
	RLCA
	LD	B,#0x00
	LD	C,A
	ADD	HL,BC
	LD	C,#0x00		; Sprite 0x00
	LD	A,(HL+)
	LD	D,A
	PUSH	HL
	CALL	.set_sprite_tile
	POP	HL

	LD	C,#0x01		; Sprite 0x01
	LD	A,(HL+)
	LD	D,A
	CALL	.set_sprite_tile

	RET

	;; Place sprite
.place_sprite:
	LD	C,#0x00		; Sprite 0x00
	LD	A,(.sposx)
	LD	D,A
	LD	A,(.sposy)
	LD	E,A
	PUSH	DE		; Store position
	CALL	.mv_sprite

	LD	C,#0x01		; Sprite 0x01
	POP	DE		; Restore position
	LD	A,#0x08
	ADD	A,D
	LD	D,A
	CALL	.mv_sprite

	RET

	.area	_LIT

.tp0:

.std_data:

	; Basic tiles (0xFC to 0xFF)

	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00
	.byte	0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF
	.byte	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

.endtp0:

.tp1:

.earth_data:

	; Tile 0x00
	.byte	0x07,0x07,0x18,0x1F,0x32,0x2D,0x71,0x4E,0x70,0x4F,0xF8,0x87,0xF8,0x87,0xF8,0x87
	.byte	0xFC,0x83,0xFE,0x81,0x7F,0x40,0x7F,0x40,0x3F,0x20,0x1F,0x18,0x07,0x07,0x00,0x00
	.byte	0xC0,0xC0,0xF0,0x30,0x78,0x88,0x3C,0xC4,0x5C,0xA4,0x9E,0x62,0x3E,0xC2,0x3E,0xC2
	.byte	0x5E,0xA2,0x7E,0x82,0x0C,0xF4,0x0C,0xF4,0x98,0x68,0xB0,0x70,0xC0,0xC0,0x00,0x00
	.byte	0x07,0x07,0x1F,0x18,0x2F,0x30,0x4F,0x70,0x6F,0x50,0x9F,0xE0,0x9F,0xE0,0xBF,0xC0
	.byte	0xFF,0x80,0xB7,0xC8,0x63,0x5C,0x43,0x7C,0x3F,0x20,0x1F,0x18,0x07,0x07,0x00,0x00
	.byte	0xC0,0xC0,0xB0,0x70,0x18,0xE8,0x0C,0xF4,0x0C,0xF4,0x82,0x7E,0x82,0x7E,0x86,0x7A
	.byte	0xC6,0x3A,0xE6,0x1A,0xF4,0x0C,0xFC,0x04,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00

	; Tile 0x08
	.byte	0x07,0x07,0x1E,0x19,0x20,0x3F,0x40,0x7F,0x42,0x7D,0x81,0xFE,0x81,0xFE,0x83,0xFC
	.byte	0xD7,0xA8,0xBB,0xC4,0x6E,0x51,0x7C,0x43,0x3F,0x20,0x1F,0x18,0x07,0x07,0x00,0x00
	.byte	0xC0,0xC0,0x70,0xB0,0xE8,0x18,0xF4,0x0C,0xF4,0x0C,0xFE,0x02,0xFE,0x02,0xFE,0x02
	.byte	0xFE,0x02,0x7E,0x82,0x3C,0xC4,0x3C,0xC4,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00
	.byte	0x07,0x07,0x1B,0x1C,0x20,0x3F,0x40,0x7F,0x40,0x7F,0xE0,0x9F,0x90,0xEF,0x89,0xF6
	.byte	0x8D,0xF2,0x9F,0xE0,0x5E,0x61,0x6F,0x50,0x3F,0x20,0x1F,0x18,0x07,0x07,0x00,0x00
	.byte	0xC0,0xC0,0xB0,0x70,0x28,0xD8,0x04,0xFC,0x2C,0xD4,0x1E,0xE2,0x1E,0xE2,0x3E,0xC2
	.byte	0x7E,0x82,0xB6,0x4A,0xE4,0x1C,0xC4,0x3C,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00

	; Tile 0x10
	.byte	0x07,0x07,0x18,0x1F,0x20,0x3F,0x40,0x7F,0x40,0x7F,0xEE,0x91,0xF1,0x8E,0xE0,0x9F
	.byte	0xE0,0x9F,0xF1,0x8E,0x71,0x4E,0x72,0x4D,0x3F,0x20,0x1F,0x18,0x07,0x07,0x00,0x00
	.byte	0xC0,0xC0,0xF0,0x30,0x08,0xF8,0x04,0xFC,0x04,0xFC,0x02,0xFE,0x02,0xFE,0x92,0x6E
	.byte	0xD6,0x2A,0xFE,0x02,0xEC,0x14,0xFC,0x04,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00
	.byte	0x07,0x07,0x1D,0x1A,0x36,0x29,0x5C,0x63,0x6C,0x53,0xCE,0xB1,0x9F,0xE0,0x9E,0xE1
	.byte	0xAE,0xD1,0xBF,0xC0,0x47,0x78,0x47,0x78,0x2F,0x30,0x1F,0x18,0x07,0x07,0x00,0x00
	.byte	0xC0,0xC0,0x70,0xB0,0x08,0xF8,0x04,0xFC,0x04,0xFC,0xE2,0x1E,0x32,0xCE,0x0E,0xF2
	.byte	0x0E,0xF2,0x1E,0xE2,0x1C,0xE4,0x2C,0xD4,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00

	; Tile 0x18
	.byte	0x07,0x07,0x1E,0x19,0x33,0x2C,0x49,0x76,0x42,0x7D,0xC4,0xBB,0xC1,0xBE,0xC1,0xBE
	.byte	0xE2,0x9D,0xF3,0x8C,0x78,0x47,0x78,0x47,0x3C,0x23,0x1C,0x1B,0x07,0x07,0x00,0x00
	.byte	0xC0,0xC0,0x70,0xB0,0x68,0x98,0xC4,0x3C,0xC4,0x3C,0xEE,0x12,0xF2,0x0E,0xE2,0x1E
	.byte	0xE2,0x1E,0xF2,0x0E,0x7C,0x84,0x7C,0x84,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00

.endtp1:

.tp2:

.frame_data:

	; Tile 0x00
	.byte	0xFF,0x00,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F
	.byte	0xFF,0x00,0x01,0xFE,0x03,0xFC,0x07,0xF8,0x0F,0xF0,0x1F,0xE0,0x3F,0xC0,0x7F,0x80
	.byte	0xFF,0x00,0xFE,0x01,0xFC,0x03,0xF8,0x07,0xF0,0x0F,0xE0,0x1F,0xC0,0x3F,0x80,0x7F
	.byte	0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF
	.byte	0xFF,0x00,0xFF,0x01,0xFD,0x03,0xF9,0x07,0xF1,0x0F,0xE1,0x1F,0xC1,0x3F,0x81,0x7F
	.byte	0x80,0x7F,0x81,0x7E,0x83,0x7C,0x87,0x78,0x8F,0x70,0x9F,0x60,0xBF,0x40,0xFF,0x00
	.byte	0xFF,0x70,0xFF,0x98,0xEF,0xB8,0xCF,0xF8,0xFF,0x70,0xFF,0x00,0xFF,0x00,0xFF,0x01
	.byte	0xFF,0x00,0xFE,0x01,0xFC,0x03,0xF8,0x07,0xF0,0x0F,0xE0,0x1F,0xC0,0x3F,0xFF,0xFF

	; Tile 0x08
	.byte	0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF
	.byte	0x00,0xFF,0x01,0xFE,0x03,0xFC,0x07,0xF8,0x0F,0xF0,0x1F,0xE0,0x3F,0xC0,0xFF,0xFF
	.byte	0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF
	.byte	0xFF,0x0E,0xFF,0x13,0xFD,0x17,0xF9,0x1F,0xFE,0x0F,0xE0,0x1F,0xC0,0x3F,0x80,0xFF
	.byte	0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF
	.byte	0xFF,0x01,0xFF,0x01,0xFD,0x03,0xF9,0x07,0xF1,0x0F,0xE1,0x1F,0xC1,0x3F,0x81,0x7F
	.byte	0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F
	.byte	0x01,0xFF,0x01,0xFF,0x03,0xFD,0x07,0xF9,0x0F,0xF1,0x1F,0xE1,0x3F,0xC1,0x7F,0x81

	; Tile 0x10
	.byte	0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01
	.byte	0x01,0xFF,0x01,0xFE,0x03,0xFC,0x77,0xF8,0xFF,0x98,0xEF,0xB8,0xCF,0xF8,0x7F,0xF0
	.byte	0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x0E,0xFF,0x13,0xFD,0x17,0xF9,0x1F,0xFF,0x0E
	.byte	0x80,0x7F,0x81,0x7E,0x83,0x7C,0x87,0x78,0x8F,0x70,0x9F,0x60,0xBF,0x40,0xFF,0x7F
	.byte	0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0xFF,0xFF

.door1_data:

	; Tile 0x15
	.byte	0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF
	.byte	0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF
	.byte	0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF

.door2_data:

	; Tile 0x18
	.byte	0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF
	.byte	0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF
	.byte	0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF
	.byte	0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF

.door3_data:

	; Tile 0x1C
	.byte	0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF
	.byte	0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF
	.byte	0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF
	.byte	0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF

.door4_data:

	; Tile 0x20
	.byte	0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF

.endtp2:

.tp3:

.bkg_data:

	; Tile 0x00
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xF7,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xDF,0xFF,0xEF,0xFF,0xFF,0xF7,0xFF,0xFB,0xFF,0xFD,0xFF,0xFE,0xFE,0xFF

	; Tile 0x08
	.byte	0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7D,0xFE,0x7C,0x39
	.byte	0xFF,0xFF,0xF7,0xFF,0xEF,0xFF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF,0xFD
	.byte	0xBB,0x01,0xC7,0x83,0xC7,0x83,0xC7,0x83,0xBB,0x01,0x7C,0x39,0x7D,0xFE,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F
	.byte	0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFB,0xAF,0x77,0x27,0x8F,0xDF,0x8F,0x27,0x8F

	; Tile 0x10
	.byte	0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFB,0xFF,0xF7,0xEF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xBF,0xFF,0xDF,0xEF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFE,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xAF,0x77,0xFF,0xFB,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF

	; Tile 0x18
	.byte	0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0x7D,0xFE,0x7C,0x39
	.byte	0xFF,0xFF,0xF7,0xFF,0xEF,0xFF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0x7F,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFD

	; Tile 0x20
	.byte	0xFF,0xFF,0xDF,0xFF,0xEF,0xFF,0xFF,0xF7,0xFF,0xFB,0xFE,0xFD,0xFD,0xFE,0xFE,0xFF
	.byte	0xAB,0x11,0xC7,0x83,0x83,0xC7,0xC7,0x83,0xAB,0x11,0x7C,0x39,0x7D,0xFE,0xFE,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFB,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0x7F
	.byte	0xFB,0xFF,0xFF,0xFD,0xFE,0xFE,0xFE,0xFF,0xFE,0xFE,0xFF,0xFD,0xFB,0xFF,0xFF,0xFF
	.byte	0xEF,0xFF,0xFF,0xDF,0x3F,0xBF,0x3F,0x7F,0x3F,0xBF,0xFF,0xDF,0xEF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFB,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFD,0xFE,0xFE,0xFD
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF

	; Tile 0x28
	.byte	0xF7,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
	.byte	0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF

.endtp3:

	; Image size: 0x40 x 0x40
	; Number of tiles (total - unique): 0x40 - 0x2D

.bkg_tiles:

	.byte	0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC
	.byte	0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC
	.byte	0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC
	.byte	0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC

	.byte	0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A
	.byte	0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A
	.byte	0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A
	.byte	0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A

	.byte	0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC
	.byte	0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC
	.byte	0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC
	.byte	0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC

	.byte	0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14
	.byte	0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14
	.byte	0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14
	.byte	0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14

	.byte	0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC
	.byte	0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC
	.byte	0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC
	.byte	0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC

	.byte	0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20
	.byte	0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20
	.byte	0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20
	.byte	0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20

	.byte	0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26
	.byte	0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26
	.byte	0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26
	.byte	0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26

	.byte	0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11
	.byte	0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11
	.byte	0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11
	.byte	0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11

	.byte	0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC
	.byte	0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC
	.byte	0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC
	.byte	0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC

	.byte	0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A
	.byte	0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A
	.byte	0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A
	.byte	0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A

	.byte	0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC
	.byte	0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC
	.byte	0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC
	.byte	0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC

	.byte	0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14
	.byte	0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14
	.byte	0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14
	.byte	0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14

	.byte	0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC
	.byte	0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC
	.byte	0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC
	.byte	0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC

	.byte	0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20
	.byte	0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20
	.byte	0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20
	.byte	0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20

	.byte	0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26
	.byte	0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26
	.byte	0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26
	.byte	0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26

	.byte	0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11
	.byte	0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11
	.byte	0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11
	.byte	0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11

	.byte	0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC
	.byte	0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC
	.byte	0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC
	.byte	0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC

	.byte	0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A
	.byte	0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A
	.byte	0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A
	.byte	0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A

	.byte	0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC
	.byte	0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC
	.byte	0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC
	.byte	0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC

	.byte	0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14
	.byte	0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14
	.byte	0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14
	.byte	0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14

	.byte	0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC
	.byte	0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC
	.byte	0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC
	.byte	0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC

	.byte	0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20
	.byte	0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20
	.byte	0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20
	.byte	0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20

	.byte	0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26
	.byte	0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26
	.byte	0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26
	.byte	0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26

	.byte	0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11
	.byte	0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11
	.byte	0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11
	.byte	0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11

	.byte	0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC
	.byte	0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC
	.byte	0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC
	.byte	0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC

	.byte	0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A
	.byte	0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A
	.byte	0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A
	.byte	0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A

	.byte	0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC
	.byte	0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC
	.byte	0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC
	.byte	0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC

	.byte	0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14
	.byte	0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14
	.byte	0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14
	.byte	0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14

	.byte	0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC
	.byte	0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC
	.byte	0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC
	.byte	0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC

	.byte	0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20
	.byte	0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20
	.byte	0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20
	.byte	0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20

	.byte	0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26
	.byte	0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26
	.byte	0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26
	.byte	0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26

	.byte	0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11
	.byte	0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11
	.byte	0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11
	.byte	0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11

	; Image size: 0x10 x 0x70
	; Number of tiles (total - unique): 0x1C - 0x1C

.earth_tiles:

	.byte	0x00,0x02
	.byte	0x04,0x06
	.byte	0x08,0x0A
	.byte	0x0C,0x0E
	.byte	0x10,0x12
	.byte	0x14,0x16
	.byte	0x18,0x1A

	; Image size: 0x80 x 0x50
	; Number of tiles (total - unique): 0xA0 - 0x15

.frame_tiles:

	.byte	0x80,0x81,0xFD,0x82,0x83,0x81,0xFD,0x82,0x83,0x81,0xFD,0x82,0x83,0x81,0xFD,0x84
	.byte	0x85,0x86,0x87,0x88,0x89,0x8A,0x87,0x88,0x89,0x8A,0x87,0x88,0x89,0x8A,0x8B,0x8C
	.byte	0xFD,0x8D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x8F
	.byte	0x82,0x8C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x85,0x90
	.byte	0x8E,0x8F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x8D
	.byte	0x85,0x90,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x82,0x8C
	.byte	0xFD,0x8D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x8F
	.byte	0x82,0x8C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x85,0x90
	.byte	0x8E,0x91,0xFD,0x82,0x83,0x81,0xFD,0x82,0x83,0x81,0xFD,0x82,0x83,0x81,0x92,0x8D
	.byte	0x93,0x8A,0x87,0x88,0x89,0x8A,0x87,0x88,0x89,0x8A,0x87,0x88,0x89,0x8A,0x87,0x94

	; Image size: 0x60 x 0x30
	; Number of tiles (total - unique): 0x48 - 0x03

.door1_tiles:

	.byte	0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95
	.byte	0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96
	.byte	0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97
	.byte	0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95
	.byte	0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96
	.byte	0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97

	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC

	; Image size: 0x60 x 0x30
	; Number of tiles (total - unique): 0x48 - 0x04

.door2_tiles:

	.byte	0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98
	.byte	0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99
	.byte	0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A
	.byte	0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98
	.byte	0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99
	.byte	0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B

	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC

	; Image size: 0x60 x 0x30
	; Number of tiles (total - unique): 0x48 - 0x04

.door3_tiles:

	.byte	0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C
	.byte	0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D
	.byte	0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E
	.byte	0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C
	.byte	0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D
	.byte	0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F

	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC

	; Image size: 0x60 x 0x30
	; Number of tiles (total - unique): 0x48 - 0x01

.door4_tiles:

	.byte	0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95
	.byte	0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96
	.byte	0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97
	.byte	0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95
	.byte	0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96
	.byte	0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0

	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
	.byte	0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC

.film:
	.word	.door1_tiles+0x0C*0
	.word	.door2_tiles+0x0C*0
	.word	.door3_tiles+0x0C*0
	.word	.door4_tiles+0x0C*0
	.word	.door1_tiles+0x0C*1
	.word	.door2_tiles+0x0C*1
	.word	.door3_tiles+0x0C*1
	.word	.door4_tiles+0x0C*1
	.word	.door1_tiles+0x0C*2
	.word	.door2_tiles+0x0C*2
	.word	.door3_tiles+0x0C*2
	.word	.door4_tiles+0x0C*2
	.word	.door1_tiles+0x0C*3
	.word	.door2_tiles+0x0C*3
	.word	.door3_tiles+0x0C*3
	.word	.door4_tiles+0x0C*3
	.word	.door1_tiles+0x0C*4
	.word	.door2_tiles+0x0C*4
	.word	.door3_tiles+0x0C*4
	.word	.door4_tiles+0x0C*4
	.word	.door1_tiles+0x0C*5
	.word	.door2_tiles+0x0C*5
	.word	.door3_tiles+0x0C*5
	.word	.door4_tiles+0x0C*5
.endfilm:
	.word	.door1_tiles+0x0C*6


================================================
FILE: examples/thumby/Make.bat
================================================
echo off
set BIN=..\..\bin
set OBJ=obj

if "%1"=="clean" (
	if exist %OBJ% rd /s/q %OBJ%
	if exist thumby.gb del thumby.gb
	goto end
)

if not exist %OBJ% mkdir %OBJ%
call %BIN%\gbdk-n-compile.bat thumby.c -o %OBJ%\thumby.rel
call %BIN%\gbdk-n-link.bat %OBJ%\thumby.rel -o %OBJ%\thumby.ihx
call %BIN%\gbdk-n-make-rom.bat %OBJ%\thumby.ihx thumby.gb

:end


================================================
FILE: examples/thumby/Makefile
================================================
BIN=../../bin
OBJ=./obj

build:
	mkdir -p $(OBJ)
	$(BIN)/gbdk-n-compile.sh thumby.c -o $(OBJ)/thumby.rel
	$(BIN)/gbdk-n-link.sh $(OBJ)/thumby.rel -o $(OBJ)/thumby.ihx
	$(BIN)/gbdk-n-make-rom.sh $(OBJ)/thumby.ihx thumby.gb

clean:
	rm -rf $(OBJ)
	rm -f thumby.gb


================================================
FILE: examples/thumby/thumby.c
================================================
#include <gb/gb.h>

/*
 * Game Boy Development Kit Demonstration program
 * Creates a rectangle on screen
 * which can be moved around with the game pad
 *
 */

unsigned char backgroundcharacters[] = {
	0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
	0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0xFF,0xF0,

	0x80,0xFF,0x7F,0xE0,0x9F,0xE0,0xFF,0xF0,
	0xFF,0xF9,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,

	0xFF,0xFF,0xFF,0xCF,0xFF,0x87,0xFF,0xCF,
	0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,

	0x1F,0xFF,0xEF,0x7F,0x9F,0x7F,0xFF,0xFF,
	0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF
}; 

unsigned char spritetiles[] = {
	255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0
};

unsigned char bgmap[] = {
	0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,
	1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3
}; 

void main()
{
	UBYTE counter,x,y;
	x=40;
	y=17;

	disable_interrupts();
	DISPLAY_OFF;

	// load background
	set_bkg_data(0,4,backgroundcharacters);
	for(counter=0;counter<=16;counter+=2)
		set_bkg_tiles( 0, counter, 20, 2, bgmap);

	// load sprite
	SPRITES_8x8;
	set_sprite_data(0, 1, spritetiles);
	set_sprite_tile(0,0);
	move_sprite(0,x,y);

	SHOW_BKG;
	SHOW_SPRITES; 
	DISPLAY_ON;
	enable_interrupts();

	while(1) {
	/* Skip four VBLs (slow down animation) */
		for(counter = 0; counter < 4; counter++){
			wait_vbl_done();
		}
		counter = joypad();

		if(counter & J_UP)
			y--;
		if(counter & J_DOWN)
			y++;
		if(counter & J_LEFT)
			x--;
		if(counter & J_RIGHT)
			x++;

		move_sprite(0,x,y);
	}
}


================================================
FILE: include/asm/gbz80/provides.h
================================================
#define USE_C_MEMCPY	1
#define USE_C_STRCPY	1
#define USE_C_STRCMP	1



================================================
FILE: include/asm/gbz80/stdarg.h
================================================
#ifndef ASM_GBZ80_STDARG_INCLUDE
#define ASM_GBZ80_STDARG_INCLUDE

/* sdcc pushes right to left with the real sizes, not cast up
   to an int.
   so printf(int, char, long)
   results in push long, push char, push int
   On the z80 the stack grows down, so the things seem to be in
   the correct order.
 */

typedef unsigned char * va_list;
#define va_start(list, last)	list = (unsigned char *)&last + sizeof(last)
#define va_arg(list, type)	*((type *)((list += sizeof(type)) - sizeof(type)))

#define va_end(list)

#endif


================================================
FILE: include/asm/gbz80/types.h
================================================
/** @file asm/gbz80/types.h
    Types definitions for the gb.
*/
#ifndef ASM_GBZ80_TYPES_INCLUDE
#define ASM_GBZ80_TYPES_INCLUDE

#if SDCC_PORT!=gbz80
#error gbz80 only.
#endif

#define NONBANKED	__nonbanked
#define BANKED		__banked

/** Signed eight bit.
 */
typedef signed char   	INT8;
/** Unsigned eight bit.
 */
typedef unsigned char 	UINT8;
/** Signed sixteen bit.
 */
typedef int           	INT16;
/** Unsigned sixteen bit.
 */
typedef unsigned int  	UINT16;
/** Signed 32 bit.
 */
typedef long          	INT32;
/** Unsigned 32 bit.
 */
typedef unsigned long 	UINT32;

#ifndef __SIZE_T_DEFINED
#define __SIZE_T_DEFINED
typedef unsigned int  	size_t;
#endif

/** Returned from clock
    @see clock
*/
typedef UINT16		clock_t;

#endif


================================================
FILE: include/asm/types.h
================================================
/** @file asm/types.h
    Shared types definitions.
*/
#ifndef ASM_TYPES_INCLUDE
#define ASM_TYPES_INCLUDE

#if SDCC_PORT == gbz80
#include <asm/gbz80/types.h>
#elif SDCC_PORT == z80
#include <asm/z80/types.h>
#else
#error Unrecognised port
#endif

#ifndef NONBANKED
#define NONBANKED
#endif

#ifndef BANKED
#define BANKED
#endif

/** TRUE or FALSE.
 */
typedef INT8		BOOLEAN;

#if BYTE_IS_UNSIGNED

typedef UINT8		BYTE;
typedef UINT16		WORD;
typedef UINT32		DWORD;

#else

/** Signed 8 bit.
 */
typedef INT8         	BYTE;
/** Unsigned 8 bit.
 */
typedef UINT8        	UBYTE;
/** Signed 16 bit */
typedef INT16      	WORD;
/** Unsigned 16 bit */
typedef UINT16       	UWORD;
/** Signed 32 bit */
typedef INT32       	LWORD;
/** Unsigned 32 bit */
typedef UINT32      	ULWORD;
/** Signed 32 bit */
typedef INT32	   	DWORD;
/** Unsigned 32 bit */
typedef UINT32	   	UDWORD;

/** Useful definition for fixed point values */
typedef union _fixed {
  struct {
    UBYTE l;
    UBYTE h;
  } b;
  UWORD w;
} fixed;

#endif

#endif


================================================
FILE: include/asm/z80/provides.h
================================================
#undef USE_C_MEMCPY
#undef USE_C_STRCPY
#undef USE_C_STRCMP


================================================
FILE: include/asm/z80/stdarg.h
================================================
#ifndef ASM_Z80_STDARG_INCLUDE
#define ASM_Z80_STDARG_INCLUDE

/* sdcc pushes right to left with the real sizes, not cast up
   to an int.
   so printf(int, char, long)
   results in push long, push char, push int
   On the z80 the stack grows down, so the things seem to be in
   the correct order.
 */

typedef char * va_list;
#define va_start(list, last)	list = (char *)&last + sizeof(last)
#ifdef STDIO_INCLUDE
#define va_arg(list, type)	*(type *)list; list + sizeof(type)
#else
#define va_arg(list, type)	(list + sizeof(type), *(type *)(list - sizeof(type)))
#endif

#endif


================================================
FILE: include/asm/z80/types.h
================================================
#ifndef ASM_Z80_TYPES_INCLUDE
#define ASM_Z80_TYPES_INCLUDE

#if SDCC_PORT!=z80
#error z80 only.
#endif

typedef char          	INT8;
typedef unsigned char 	UINT8;
typedef int           	INT16;
typedef unsigned int  	UINT16;
typedef long          	INT32;
typedef unsigned long 	UINT32;

typedef int	      	size_t;
typedef UINT16		clock_t;

#endif


================================================
FILE: include/gb/cgb.h
================================================
/** @file gb/cgb.h
    Support for Color GameBoy.
*/

#ifndef _CGB_H
#define _CGB_H

/** Macro to create a palette entry out of the color components.
 */
#define RGB(r, g, b) \
  ((((UINT16)(b) & 0x1f) << 10) | (((UINT16)(g) & 0x1f) << 5) | (((UINT16)(r) & 0x1f) << 0))

/** Common colors based on the EGA default palette.
 */
#define RGB_RED        RGB(31,  0,  0)
#define RGB_DARKRED    RGB(15,  0,  0)
#define RGB_GREEN      RGB( 0, 31,  0)
#define RGB_DARKGREEN  RGB( 0, 15,  0)
#define RGB_BLUE       RGB( 0,  0, 31)
#define RGB_DARKBLUE   RGB( 0,  0, 15)
#define RGB_YELLOW     RGB(31, 31,  0)
#define RGB_DARKYELLOW RGB(21, 21,  0)
#define RGB_CYAN       RGB( 0, 31, 31)
#define RGB_AQUA       RGB(28,  5, 22)
#define RGB_PINK       RGB(11,  0, 31)
#define RGB_PURPLE     RGB(21,  0, 21)
#define RGB_BLACK      RGB( 0,  0,  0)
#define RGB_DARKGRAY   RGB(10, 10, 10)
#define RGB_LIGHTGRAY  RGB(21, 21, 21)
#define RGB_WHITE      RGB(31, 31, 31)

#define RGB_LIGHTFLESH RGB(30, 20, 15)
#define RGB_BROWN      RGB(10, 10,  0)
#define RGB_ORANGE     RGB(30, 20,  0)
#define RGB_TEAL       RGB(15, 15,  0)

/** Set bkg palette(s).
 */
void
set_bkg_palette(UINT8 first_palette,
                UINT8 nb_palettes,
                UINT16 *rgb_data) NONBANKED;

/** Set sprite palette(s).
 */
void
set_sprite_palette(UINT8 first_palette,
                   UINT8 nb_palettes,
                   UINT16 *rgb_data) NONBANKED;

/** Set a bkg palette entry.
 */
void
set_bkg_palette_entry(UINT8 palette,
                      UINT8 entry,
                      UINT16 rgb_data);

/** Set a sprite palette entry.
 */
void
set_sprite_palette_entry(UINT8 palette,
                         UINT8 entry,
                         UINT16 rgb_data);

/** Set CPU speed to slow operation.
    Make sure interrupts are disabled before call.

    @see cpu_fast
 */
void cpu_slow(void);

/** Set CPU speed to fast operation.
    Make sure interrupts are disabled before call.

    @see cpu_slow
*/
void cpu_fast(void);

/** Set defaults compatible with normal GameBoy.
 */
void cgb_compatibility(void);

#endif /* _CGB_H */


================================================
FILE: include/gb/console.h
================================================
/** @file gb/console.h
    Console functions that work like Turbo C's.
    Note that the font is 8x8, making the screen 20x18 characters.
*/
#ifndef _CONSOLE_H
#define _CONSOLE_H

#include <types.h>

/** Move the cursor to an absolute position.
 */
void
gotoxy(UINT8 x,
	   UINT8 y);

/** Get the current X position of the cursor.
 */
UINT8
posx(void);

/** Get the current Y position of the cursor.
 */
UINT8
posy(void);

/** Writes out a single character at the current cursor
    position.
    Does not update the cursor or interpret the character.
*/
void
setchar(char c);

#endif /* _CONSOLE_H */


================================================
FILE: include/gb/drawing.h
================================================
/** @file gb/drawing.h
    All Points Addressable (APA) mode drawing library.

    Drawing routines originally by Pascal Felber
    Legendary overhall by Jon Fuge <jonny@q-continuum.demon.co.uk>
    Commenting by Michael Hope

    Note that the standard text printf() and putchar() cannot be used
    in APA mode - use gprintf() and wrtchr() instead.
*/
#ifndef __DRAWING_H
#define __DRAWING_H

/** Size of the screen in pixels */
#define GRAPHICS_WIDTH	160
#define GRAPHICS_HEIGHT 144

/** Possible drawing modes */
#if ORIGINAL
	#define	SOLID	0x10		/* Overwrites the existing pixels */
	#define	OR	0x20		/* Performs a logical OR */
	#define	XOR	0x40		/* Performs a logical XOR */
	#define	AND	0x80		/* Performs a logical AND */
#else
	#define	SOLID	0x00		/* Overwrites the existing pixels */
	#define	OR	0x01		/* Performs a logical OR */
	#define	XOR	0x02		/* Performs a logical XOR */
	#define	AND	0x03		/* Performs a logical AND */
#endif

/** Possible drawing colours */
#define	WHITE	0
#define	LTGREY	1
#define	DKGREY	2
#define	BLACK	3

/** Possible fill styles for box() and circle() */
#define	M_NOFILL	0
#define	M_FILL		1

/** Possible values for signed_value in gprintln() and gprintn() */
#define SIGNED   1
#define UNSIGNED 0

#include <types.h>

/** Print the string 'str' with no interpretation */
void
	gprint(char *str) NONBANKED;

/** Print the long number 'number' in radix 'radix'.  signed_value should
   be set to SIGNED or UNSIGNED depending on whether the number is signed
   or not */
void
	gprintln(INT16 number, INT8 radix, INT8 signed_value);

/** Print the number 'number' as in 'gprintln' */
void	
	gprintn(INT8 number, INT8 radix, INT8 signed_value);

/** Print the formatted string 'fmt' with arguments '...' */
INT8	
	gprintf(char *fmt,...) NONBANKED;

/** Old style plot - try plot_point() */
void
	plot(UINT8 x, UINT8 y, UINT8 colour, UINT8 mode);

/** Plot a point in the current drawing mode and colour at (x,y) */
void	
	plot_point(UINT8 x, UINT8 y);

/** I (MLH) have no idea what switch_data does... */
void
	switch_data(UINT8 x, UINT8 y, unsigned char *src, unsigned char *dst) NONBANKED;

/** Ditto */
void	
	draw_image(unsigned char *data) NONBANKED;

/** Draw a line in the current drawing mode and colour from (x1,y1) to (x2,y2) */
void	
	line(UINT8 x1, UINT8 y1, UINT8 x2, UINT8 y2);

/** Draw a box (rectangle) with corners (x1,y1) and (x2,y2) using fill mode
   'style' (one of NOFILL or FILL */
void	
	box(UINT8 x1, UINT8 y1, UINT8 x2, UINT8 y2, UINT8 style);

/** Draw a circle with centre at (x,y) and radius 'radius'.  'style' sets
   the fill mode */
void	
	circle(UINT8 x, UINT8 y, UINT8 radius, UINT8 style);

/** Returns the current colour of the pixel at (x,y) */
UINT8	
	getpix(UINT8 x, UINT8 y);

/** Prints the character 'chr' in the default font at the current position */
void	
	wrtchr(char chr);

/** Sets the current text position to (x,y).  Note that x and y have units
   of cells (8 pixels) */
void
	gotogxy(UINT8 x, UINT8 y);

/** Set the current foreground colour (for pixels), background colour, and
   draw mode */
void	color(UINT8 forecolor, UINT8 backcolor, UINT8 mode);

#endif /* __DRAWING_H */


================================================
FILE: include/gb/font.h
================================================
/** @file gb/font.h
    Multiple font support for the GameBoy
    Michael Hope, 1999
    michaelh@earthling.net
*/
#ifndef __FONT_H
#define __FONT_H

#include <gb/gb.h>

/** Various flags in the font header.
 */
#define	FONT_256ENCODING	0
#define	FONT_128ENCODING	1
#define	FONT_NOENCODING		2

#define	FONT_COMPRESSED		4

/* See gb.h/M_NO_SCROLL and gb.h/M_NO_INTERP */

/** font_t is a handle to a font loaded by font_load() */
typedef UINT16 font_t;

/** The default fonts */
extern UINT8 font_spect[], font_italic[], font_ibm[], font_min[];

/** Backwards compatible font */
extern UINT8 font_ibm_fixed[];

/** Init the font system.
    Should be called first.
 */
void	font_init(void) NONBANKED;

/** Load the font 'font'.
    Sets the current font to the newly loaded font.
 */
font_t	font_load( void *font ) NONBANKED;

/** Set the current font to 'font_handle', which was returned 
    from an earlier font_load().  
    @return		The previously used font handle.
*/
font_t	font_set( font_t font_handle ) NONBANKED;

/* Use mode() and color() to set the font modes and colours */

/** Internal representation of a font.  
    What a font_t really is */
typedef struct sfont_handle mfont_handle;
typedef struct sfont_handle *pmfont_handle;

struct sfont_handle {
    UINT8 first_tile;		/* First tile used */
    void *font;			/* Pointer to the base of the font */
};

#endif /* __FONT_H */


================================================
FILE: include/gb/gb.h
================================================
/** @file gb/gb.h
    Gameboy specific functions.
*/
#ifndef _GB_H
#define _GB_H

#include <types.h>
#include <gb/hardware.h>
#include <gb/sgb.h>
#include <gb/cgb.h>

/** Joypad bits.
    A logical OR of these is used in the wait_pad and joypad
    functions.  For example, to see if the B button is pressed
    try

    UINT8 keys;
    keys = joypad();
    if (keys & J_B) {
    	...
    }

    @see joypad
 */
#define	J_START      0x80U
#define	J_SELECT     0x40U
#define	J_B          0x20U
#define	J_A          0x10U
#define	J_DOWN       0x08U
#define	J_UP         0x04U
#define	J_LEFT       0x02U
#define	J_RIGHT      0x01U

/** Screen modes.
    Normally used by internal functions only.
 */
#define	M_DRAWING    0x01U
#define	M_TEXT_OUT   0x02U
#define	M_TEXT_INOUT 0x03U
/** Set this in addition to the others to disable scrolling 
    If scrolling is disabled, the cursor returns to (0,0) */
#define M_NO_SCROLL  0x04U
/** Set this to disable \n interpretation */
#define M_NO_INTERP  0x08U

/** If this is set, sprite colours come from OBJ1PAL.  Else
    they come from OBJ0PAL.
*/
#define S_PALETTE    0x10U
/** If set the sprite will be flipped horizontally.
 */
#define S_FLIPX      0x20U
/** If set the sprite will be flipped vertically.
 */
#define S_FLIPY      0x40U
/** If this bit is clear, then the sprite will be displayed
    ontop of the background and window.
*/
#define S_PRIORITY   0x80U

/* Interrupt flags */
/** Vertical blank interrupt.
    Occurs at the start of the vertical blank.  During this
    period the video ram may be freely accessed.
 */
#define VBL_IFLAG    0x01U
/** Interrupt when triggered by the STAT register.
    See the Pan doc.
*/
#define LCD_IFLAG    0x02U
/** Interrupt when the timer TIMA overflows.
 */
#define TIM_IFLAG    0x04U
/** Occurs when the serial transfer has completed.
 */
#define SIO_IFLAG    0x08U
/** Occurs on a transition of the keypad.
 */
#define JOY_IFLAG    0x10U

/* Limits */
/** Width of the visible screen in pixels.
 */
#define SCREENWIDTH  0xA0U
/** Height of the visible screen in pixels.
 */
#define SCREENHEIGHT 0x90U
#define MINWNDPOSX   0x07U
#define MINWNDPOSY   0x00U
#define MAXWNDPOSX   0xA6U
#define MAXWNDPOSY   0x8FU

/* ************************************************************ */

/** Interrupt handlers
 */
typedef void (*int_handler)(void) NONBANKED;

/** The remove functions will remove any interrupt
   handler.  A handler of NULL will cause bad things
   to happen.
*/
void
remove_VBL(int_handler h) NONBANKED;

void
remove_LCD(int_handler h) NONBANKED;

void
remove_TIM(int_handler h) NONBANKED;

void
remove_SIO(int_handler h) NONBANKED;

void
remove_JOY(int_handler h) NONBANKED;

/** Adds a V-blank interrupt handler.
    The handler 'h' will be called whenever a V-blank
    interrupt occurs.  Up to 4 handlers may be added,
    with the last added being called last.  If the remove_VBL
    function is to be called, only three may be added.
    @see remove_VBL
*/
void
add_VBL(int_handler h) NONBANKED;

/** Adds a LCD interrupt handler.
    Called when the LCD interrupt occurs, which is normally
    when LY_REG == LYC_REG.

    From pan/k0Pa:
    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.

    @see add_VBL
*/
void
add_LCD(int_handler h) NONBANKED;

/** Adds a timer interrupt handler.

    From pan/k0Pa:
    This interrupt occurs when the TIMA register ($FF05)
    changes from $FF to $00.

    @see add_VBL
*/    
void
add_TIM(int_handler h) NONBANKED;

/** Adds a serial transmit complete interrupt handler.

    From pan/k0Pa:
    This interrupt occurs when a serial transfer has
    completed on the game link port.
    
    @see send_byte, receive_byte, add_VBL
*/
void
add_SIO(int_handler h) NONBANKED;

/** Adds a pad tranisition interrupt handler.
    
    From pan/k0Pa:
    This interrupt occurs on a transition of any of the
    keypad input lines from high to low. Due to the fact
    that keypad "bounce" is virtually always present,
    software should expect this interrupt to occur one
    or more times for every button press and one or more
    times for every button release.

    @see joypad
*/
void
add_JOY(int_handler h) NONBANKED;

/* ************************************************************ */

/** Set the current mode - one of M_* defined above */
void
	mode(UINT8 m) NONBANKED;

/** Returns the current mode */
UINT8
	get_mode(void) NONBANKED;

/** GB type (GB, PGB, CGB) */
extern UINT8 _cpu;

/** Original GB or Super GB */
#define DMG_TYPE 0x01 
/** Pocket GB or Super GB 2 */
#define MGB_TYPE 0xFF
/** Color GB */
#define CGB_TYPE 0x11 

/** Time in VBL periods (60Hz) */
extern UINT16 sys_time;	

/* ************************************************************ */

/** Send byte in _io_out to the serial port */
void
send_byte(void);

/** Receive byte from the serial port in _io_in */
void
receive_byte(void);

/** An OR of IO_* */
extern UINT8 _io_status;
/** Byte just read. */
extern UINT8 _io_in;
/** Write the byte to send here before calling send_byte()
    @see send_byte
*/
extern UINT8 _io_out;

/* Status codes */
/** IO is completed */
#define IO_IDLE		0x00U		
/** Sending data */
#define IO_SENDING	0x01U		
/** Receiving data */
#define IO_RECEIVING	0x02U		
/** Error */
#define IO_ERROR	0x04U		

/* ************************************************************ */

/* Multiple banks */

/** Switches the upper 16k bank of the 32k rom to bank rombank 
    using the MBC1 controller. 
    By default the upper 16k bank is 1. Make sure the rom you compile 
    has more than just bank 0 and bank 1, a 32k rom. This is done by 
    feeding lcc.exe the following switches:

    -Wl-yt# where # is the type of cartridge. 1 for ROM+MBC1.

    -Wl-yo# where # is the number of rom banks. 2,4,8,16,32.
*/
#define SWITCH_ROM_MBC1(b) \
  *(unsigned char *)0x2000 = (b)

#define SWITCH_RAM_MBC1(b) \
  *(unsigned char *)0x4000 = (b)

#define ENABLE_RAM_MBC1 \
  *(unsigned char *)0x0000 = 0x0A

#define DISABLE_RAM_MBC1 \
  *(unsigned char *)0x0000 = 0x00

#define SWITCH_16_8_MODE_MBC1 \
  *(unsigned char *)0x6000 = 0x00

#define SWITCH_4_32_MODE_MBC1 \
  *(unsigned char *)0x6000 = 0x01

/* Note the order used here.  Writing the other way around
 * on a MBC1 always selects bank 0 (d'oh)
 */
/** MBC5 */
#define SWITCH_ROM_MBC5(b) \
  *(unsigned char *)0x3000 = (UINT16)(b)>>8; \
  *(unsigned char *)0x2000 = (UINT8)(b)

#define SWITCH_RAM_MBC5(b) \
  *(unsigned char *)0x4000 = (b)

#define ENABLE_RAM_MBC5 \
  *(unsigned char *)0x0000 = 0x0A

#define DISABLE_RAM_MBC5 \
  *(unsigned char *)0x0000 = 0x00

/* ************************************************************ */

/** Delays the given number of milliseconds.
    Uses no timers or interrupts, and can be called with 
    interrupts disabled (why nobody knows :)
 */
void
delay(UINT16 d) NONBANKED;

/* ************************************************************ */

/** Reads and returns the current state of the joypad.
    Follows Nintendo's guidelines for reading the pad.
    Return value is an OR of J_*
    @see J_START
*/
UINT8
joypad(void) NONBANKED;

/** Waits until all the keys given in mask are pressed.
    Normally only used for checking one key, but it will
    support many, even J_LEFT at the same time as J_RIGHT :)
    @see joypad, J_START
*/
UINT8
waitpad(UINT8 mask) NONBANKED;

/** Waits for the pad and all buttons to be released.
*/
void
waitpadup(void) NONBANKED;

/* ************************************************************ */

/** Enables unmasked interrupts
    @see disable_interrupts
*/
void
enable_interrupts(void) NONBANKED;

/** Disables interrupts.
    This function may be called as many times as you like;
    however the first call to enable_interrupts will re-enable
    them.
    @see enable_interrupts
*/
void
disable_interrupts(void) NONBANKED;

/** Clears any pending interrupts and sets the interrupt mask
    register IO to flags.
    @see VBL_IFLAG
    @param flags	A logical OR of *_IFLAGS
*/
void
set_interrupts(UINT8 flags) NONBANKED;

/** Performs a warm reset by reloading the CPU value
    then jumping to the start of crt0 (0x0150)
*/
void
reset(void) NONBANKED;

/** Waits for the vertical blank interrupt (VBL) to finish.  
    This can be used to sync animation with the screen 
    re-draw.  If VBL interrupt is disabled, this function will
    never return.  If the screen is off this function returns
    immediatly.
*/
void
wait_vbl_done(void) NONBANKED;

/** Turns the display off.
    Waits until the VBL interrupt before turning the display
    off.
    @see DISPLAY_ON
*/
void
display_off(void) NONBANKED;

/* ************************************************************ */

/** Copies data from somewhere in the lower address space
    to part of hi-ram.
    @param dst		Offset in high ram (0xFF00 and above)
    			to copy to.
    @param src		Area to copy from
    @param n		Number of bytes to copy.
*/
void
hiramcpy(UINT8 dst,
	 const void *src,
	 UINT8 n) NONBANKED;

/* ************************************************************ */

/** Turns the display back on.
    @see display_off, DISPLAY_OFF
*/
#define DISPLAY_ON \
  LCDC_REG|=0x80U

/** Turns the display off immediatly.
    @see display_off, DISPLAY_ON
*/
#define DISPLAY_OFF \
  display_off();

/** Turns on the background layer.
    Sets bit 0 of the LCDC register to 1.
*/
#define SHOW_BKG \
  LCDC_REG|=0x01U

/** Turns off the background layer.
    Sets bit 0 of the LCDC register to 0.
*/
#define HIDE_BKG \
  LCDC_REG&=0xFEU

/** Turns on the window layer
    Sets bit 5 of the LCDC register to 1.
*/
#define SHOW_WIN \
  LCDC_REG|=0x20U

/** Turns off the window layer.
    Clears bit 5 of the LCDC register to 0.
*/
#define HIDE_WIN \
  LCDC_REG&=0xDFU

/** Turns on the sprites layer.
    Sets bit 1 of the LCDC register to 1.
*/
#define SHOW_SPRITES \
  LCDC_REG|=0x02U

/** Turns off the sprites layer.
    Clears bit 1 of the LCDC register to 0.
*/
#define HIDE_SPRITES \
  LCDC_REG&=0xFDU

/** Sets sprite size to 8x16 pixels, two tiles one above the other.
    Sets bit 2 of the LCDC register to 1.
*/
#define SPRITES_8x16 \
  LCDC_REG|=0x04U

/** Sets sprite size to 8x8 pixels, one tile.
    Clears bit 2 of the LCDC register to 0.
*/
#define SPRITES_8x8 \
  LCDC_REG&=0xFBU

/* ************************************************************ */

/** Sets the tile patterns in the Background Tile Pattern table.
    Starting with the tile pattern x and carrying on for n number of
    tile patterns.Taking the values starting from the pointer
    data. Note that patterns 128-255 overlap with patterns 128-255
    of the sprite Tile Pattern table.  

    GBC: Depending on the VBK_REG this determines which bank of
    Background tile patterns are written to. VBK_REG=0 indicates the
    first bank, and VBK_REG=1 indicates the second.

    @param first_tile	Range 0 - 255
    @param nb_tiles	Range 0 - 255
*/
void
set_bkg_data(UINT8 first_tile,
	     UINT8 nb_tiles,
	     unsigned char *data) NONBANKED;

/** Sets the tiles in the background tile table.
    Starting at position x,y in tiles and writing across for w tiles
    and down for h tiles. Taking the values starting from the pointer
    data.

    For the GBC, also see the pan/k00Pa section on VBK_REG.

    @param x		Range 0 - 31
    @param y		Range 0 - 31
    @param w		Range 0 - 31
    @param h		Range 0 - 31
    @param data		Pointer to an unsigned char. Usually the 
    			first element in an array.
*/
void
set_bkg_tiles(UINT8 x,
	      UINT8 y,
	      UINT8 w,
	      UINT8 h,
	      unsigned char *tiles) NONBANKED;

void
get_bkg_tiles(UINT8 x,
	      UINT8 y,
	      UINT8 w,
	      UINT8 h,
	      unsigned char *tiles) NONBANKED;

/** Moves the background layer to the position specified in x and y in pixels.
    Where 0,0 is the top left corner of the GB screen. You'll notice the screen
    wraps around in all 4 directions, and is always under the window layer.
*/
void
move_bkg(UINT8 x,
	 UINT8 y) NONBANKED;

/** Moves the background relative to it's current position.

    @see move_bkg
*/
void
scroll_bkg(INT8 x,
	   INT8 y) NONBANKED;

/* ************************************************************ */

/** Sets the window tile data.
    This is the same as set_bkg_data, as both the window layer and background
    layer share the same Tile Patterns.
    @see set_bkg_data
*/
void
set_win_data(UINT8 first_tile,
	     UINT8 nb_tiles,
	     unsigned char *data) NONBANKED;

/** Sets the tiles in the win tile table. 
    Starting at position x,y in
    tiles and writing across for w tiles and down for h tiles. Taking the
    values starting from the pointer data. Note that patterns 128-255 overlap
    with patterns 128-255 of the sprite Tile Pattern table.
	
    GBC only.
    Depending on the VBK_REG this determines if you're setting the tile numbers
    VBK_REG=0; or the attributes for those tiles VBK_REG=1;. The bits in the
    attributes are defined as:
    Bit 7 - 	Priority flag. When this is set, it puts the tile above the sprites
    		with colour 0 being transparent. 0: below sprites, 1: above sprites
		Note SHOW_BKG needs to be set for these priorities to take place.
    Bit 6 - 	Vertical flip. Dictates which way up the tile is drawn vertically.
    		0: normal, 1: upside down.
    Bit 5 - 	Horizontal flip. Dictates which way up the tile is drawn
    		horizontally. 0: normal, 1:back to front.
    Bit 4 - 	Not used.
    Bit 3 - 	Character Bank specification. Dictates from which bank of
    		Background Tile Patterns the tile is taken. 0: Bank 0, 1: Bank 1
    Bit 2 - 	See bit 0.
    Bit 1 - 	See bit 0. 
    Bit 0 - 	Bits 0-2 indicate which of the 7 BKG colour palettes the tile is
		assigned.

    @param x		Range 0 - 31
    @param y		Range 0 - 31
    @param w		Range 0 - 31
    @param h		Range 0 - 31
*/
void
set_win_tiles(UINT8 x,
	      UINT8 y,
	      UINT8 w,
	      UINT8 h,
	      unsigned char *tiles) NONBANKED;

void
get_win_tiles(UINT8 x,
	      UINT8 y,
	      UINT8 w,
	      UINT8 h,
	      unsigned char *tiles) NONBANKED;

/** Moves the window layer to the position specified in x and y in pixels.
    Where 7,0 is the top left corner of the GB screen. The window is locked to
    the bottom right corner, and is always over the background layer.
    @see SHOW_WIN, HIDE_WIN
*/
void
move_win(UINT8 x,
	 UINT8 y) NONBANKED;

/** Move the window relative to its current position.
    @see move_win
*/
void
scroll_win(INT8 x,
	   INT8 y) NONBANKED;

/* ************************************************************ */

/** Sets the tile patterns in the Sprite Tile Pattern table.
    Starting with the tile pattern x and carrying on for n number of
    tile patterns.Taking the values starting from the pointer
    data. Note that patterns 128-255 overlap with patterns 128-255 of
    the Background Tile Pattern table.
    
    GBC only.
    Depending on the VBK_REG this determines which bank of Background tile
    patterns are written to. VBK_REG=0 indicates the first bank, and VBK_REG=1
    indicates the second.
*/
void
set_sprite_data(UINT8 first_tile,
		UINT8 nb_tiles,
		unsigned char *data) NONBANKED;

void
get_sprite_data(UINT8 first_tile,
		UINT8 nb_tiles,
		unsigned char *data) NONBANKED;

/** Sets sprite n to display tile number t, from the sprite tile data. 
    If the GB is in 8x16 sprite mode then it will display the next
    tile, t+1, below the first tile.
    @param nb		Sprite number, range 0 - 39
*/
void
set_sprite_tile(UINT8 nb,
		UINT8 tile) NONBANKED;

UINT8
get_sprite_tile(UINT8 nb) NONBANKED;

/** Sets the property of sprite n to those defined in p.
    Where the bits in p represent:
    Bit 7 - 	Priority flag. When this is set the sprites appear behind the
		background and window layer. 0: infront, 1: behind.
    Bit 6 - 	GBC only. Vertical flip. Dictates which way up the sprite is drawn
		vertically. 0: normal, 1:upside down.
    Bit 5 - 	GBC only. Horizontal flip. Dictates which way up the sprite is
    drawn horizontally. 0: normal, 1:back to front.
    Bit 4 - 	DMG only. Assigns either one of the two b/w palettes to the sprite.
		0: OBJ palette 0, 1: OBJ palette 1.
    Bit 3 -	GBC only. Dictates from which bank of Sprite Tile Patterns the tile
		is taken. 0: Bank 0, 1: Bank 1
    Bit 2 -	See bit 0.
    Bit 1 -	See bit 0. 
    Bit 0 - 	GBC only. Bits 0-2 indicate which of the 7 OBJ colour palettes the
		sprite is assigned.
    
    @param nb		Sprite number, range 0 - 39
*/
void
set_sprite_prop(UINT8 nb,
		UINT8 prop) NONBANKED;

UINT8
get_sprite_prop(UINT8 nb) NONBANKED;

/** Moves the given sprite to the given position on the
    screen.
    Dont forget that the top left visible pixel on the screen
    is at (8,16).  To put sprite 0 at the top left, use
    move_sprite(0, 8, 16);
*/
void
move_sprite(UINT8 nb,
	    UINT8 x,
	    UINT8 y) NONBANKED;

/** Moves the given sprite relative to its current position.
 */
void
scroll_sprite(INT8 nb,
	      INT8 x,
	      INT8 y) NONBANKED;

/* ************************************************************ */

void
set_data(unsigned char *vram_addr,
	 unsigned char *data,
	 UINT16 len) NONBANKED;

void
get_data(unsigned char *data,
	 unsigned char *vram_addr,
	 UINT16 len) NONBANKED;

void
set_tiles(UINT8 x,
	  UINT8 y,
	  UINT8 w,
	  UINT8 h,
	  unsigned char *vram_addr,
	  unsigned char *tiles) NONBANKED;

void
get_tiles(UINT8 x,
	  UINT8 y,
	  UINT8 w,
	  UINT8 h,
	  unsigned char *tiles,
	  unsigned char *vram_addr) NONBANKED;

#endif /* _GB_H */


================================================
FILE: include/gb/hardware.h
================================================
/** @file gb/hardware.h
    Defines that let the GB's hardware registers be accessed
    from C.  See the Pan doc for what to set them to.
*/
#ifndef _HARDWARE_H
#define _HARDWARE_H

#include <types.h>

#if USE_SFR_FOR_REG
#error SFR is unteseted and disabled in 2.96

#define __REG	extern volatile sfr UINT8

__REG P1_REG		; /* Joystick: 1.1.P15.P14.P13.P12.P11.P10 */
__REG SB_REG		; /* Serial IO data buffer */
__REG SC_REG		; /* Serial IO control register */
__REG DIV_REG		; /* Divider register */
__REG TIMA_REG		; /* Timer counter */
__REG TMA_REG		; /* Timer modulo */
__REG TAC_REG		; /* Timer control */
__REG IF_REG		; /* Interrupt flags: 0.0.0.JOY.SIO.TIM.LCD.VBL */
__REG NR10_REG		; /* Sound register */
__REG NR11_REG		; /* Sound register */
__REG NR12_REG		; /* Sound register */
__REG NR13_REG		; /* Sound register */
__REG NR14_REG		; /* Sound register */
__REG NR21_REG		; /* Sound register */
__REG NR22_REG		; /* Sound register */
__REG NR23_REG		; /* Sound register */
__REG NR24_REG		; /* Sound register */
__REG NR30_REG		; /* Sound register */
__REG NR31_REG		; /* Sound register */
__REG NR32_REG		; /* Sound register */
__REG NR33_REG		; /* Sound register */
__REG NR34_REG		; /* Sound register */
__REG NR41_REG		; /* Sound register */
__REG NR42_REG		; /* Sound register */
__REG NR43_REG		; /* Sound register */
__REG NR44_REG		; /* Sound register */
__REG NR50_REG		; /* Sound register */
__REG NR51_REG		; /* Sound register */
__REG NR52_REG		; /* Sound register */
__REG LCDC_REG		; /* LCD control */
__REG STAT_REG		; /* LCD status */
__REG SCY_REG		; /* Scroll Y */
__REG SCX_REG		; /* Scroll X */
__REG LY_REG		; /* LCDC Y-coordinate */
__REG LYC_REG		; /* LY compare */
__REG DMA_REG		; /* DMA transfer */
__REG BGP_REG		; /* BG palette data */
__REG OBP0_REG		; /* OBJ palette 0 data */
__REG OBP1_REG		; /* OBJ palette 1 data */
__REG WY_REG		; /* Window Y coordinate */
__REG WX_REG		; /* Window X coordinate */
__REG KEY1_REG		; /* CPU speed */
__REG VBK_REG		; /* VRAM bank */
__REG HDMA1_REG		; /* DMA control 1 */
__REG HDMA2_REG		; /* DMA control 2 */
__REG HDMA3_REG		; /* DMA control 3 */
__REG HDMA4_REG		; /* DMA control 4 */
__REG HDMA5_REG		; /* DMA control 5 */
__REG RP_REG		; /* IR port */
__REG BCPS_REG		; /* BG color palette specification */
__REG BCPD_REG		; /* BG color palette data */
__REG OCPS_REG		; /* OBJ color palette specification */
__REG OCPD_REG		; /* OBJ color palette data */
__REG SVBK_REG		; /* WRAM bank */
__REG IE_REG		; /* Interrupt enable */

#else

#define __REG	volatile UINT8 *

#define P1_REG		(*(__REG)0xFF00)	/* Joystick: 1.1.P15.P14.P13.P12.P11.P10 */
#define SB_REG		(*(__REG)0xFF01)	/* Serial IO data buffer */
#define SC_REG		(*(__REG)0xFF02)	/* Serial IO control register */
#define DIV_REG		(*(__REG)0xFF04)	/* Divider register */
#define TIMA_REG	(*(__REG)0xFF05)	/* Timer counter */
#define TMA_REG		(*(__REG)0xFF06)	/* Timer modulo */
#define TAC_REG		(*(__REG)0xFF07)	/* Timer control */
#define IF_REG		(*(__REG)0xFF0F)	/* Interrupt flags: 0.0.0.JOY.SIO.TIM.LCD.VBL */
#define NR10_REG	(*(__REG)0xFF10)	/* Sound register */
#define NR11_REG	(*(__REG)0xFF11)	/* Sound register */
#define NR12_REG	(*(__REG)0xFF12)	/* Sound register */
#define NR13_REG	(*(__REG)0xFF13)	/* Sound register */
#define NR14_REG	(*(__REG)0xFF14)	/* Sound register */
#define NR21_REG	(*(__REG)0xFF16)	/* Sound register */
#define NR22_REG	(*(__REG)0xFF17)	/* Sound register */
#define NR23_REG	(*(__REG)0xFF18)	/* Sound register */
#define NR24_REG	(*(__REG)0xFF19)	/* Sound register */
#define NR30_REG	(*(__REG)0xFF1A)	/* Sound register */
#define NR31_REG	(*(__REG)0xFF1B)	/* Sound register */
#define NR32_REG	(*(__REG)0xFF1C)	/* Sound register */
#define NR33_REG	(*(__REG)0xFF1D)	/* Sound register */
#define NR34_REG	(*(__REG)0xFF1E)	/* Sound register */
#define NR41_REG	(*(__REG)0xFF20)	/* Sound register */
#define NR42_REG	(*(__REG)0xFF21)	/* Sound register */
#define NR43_REG	(*(__REG)0xFF22)	/* Sound register */
#define NR44_REG	(*(__REG)0xFF23)	/* Sound register */
#define NR50_REG	(*(__REG)0xFF24)	/* Sound register */
#define NR51_REG	(*(__REG)0xFF25)	/* Sound register */
#define NR52_REG	(*(__REG)0xFF26)	/* Sound register */
#define LCDC_REG	(*(__REG)0xFF40)	/* LCD control */
#define STAT_REG	(*(__REG)0xFF41)	/* LCD status */
#define SCY_REG		(*(__REG)0xFF42)	/* Scroll Y */
#define SCX_REG		(*(__REG)0xFF43)	/* Scroll X */
#define LY_REG		(*(__REG)0xFF44)	/* LCDC Y-coordinate */
#define LYC_REG		(*(__REG)0xFF45)	/* LY compare */
#define DMA_REG		(*(__REG)0xFF46)	/* DMA transfer */
#define BGP_REG		(*(__REG)0xFF47)	/* BG palette data */
#define OBP0_REG	(*(__REG)0xFF48)	/* OBJ palette 0 data */
#define OBP1_REG	(*(__REG)0xFF49)	/* OBJ palette 1 data */
#define WY_REG		(*(__REG)0xFF4A)	/* Window Y coordinate */
#define WX_REG		(*(__REG)0xFF4B)	/* Window X coordinate */
#define KEY1_REG	(*(__REG)0xFF4D)	/* CPU speed */
#define VBK_REG		(*(__REG)0xFF4F)	/* VRAM bank */
#define HDMA1_REG	(*(__REG)0xFF51)	/* DMA control 1 */
#define HDMA2_REG	(*(__REG)0xFF52)	/* DMA control 2 */
#define HDMA3_REG	(*(__REG)0xFF53)	/* DMA control 3 */
#define HDMA4_REG	(*(__REG)0xFF54)	/* DMA control 4 */
#define HDMA5_REG	(*(__REG)0xFF55)	/* DMA control 5 */
#define RP_REG		(*(__REG)0xFF56)	/* IR port */
#define BCPS_REG	(*(__REG)0xFF68)	/* BG color palette specification */
#define BCPD_REG	(*(__REG)0xFF69)	/* BG color palette data */
#define OCPS_REG	(*(__REG)0xFF6A)	/* OBJ color palette specification */
#define OCPD_REG	(*(__REG)0xFF6B)	/* OBJ color palette data */
#define SVBK_REG	(*(__REG)0xFF70)	/* WRAM bank */
#define IE_REG		(*(__REG)0xFFFF)	/* Interrupt enable */

#endif

#endif /* _HARDWARE_H */


================================================
FILE: include/gb/malloc.h
================================================
/** @file gb/malloc.h

    Header for a simple implementation of malloc().  This library
    may currently be broken.
*/
#ifndef __SYS_MALLOC_H
#define __SYS_MALLOC_H

#include <types.h>

/* The various constants */
/** The malloc hunk flags
    Note:  Cound have used a negative size a'la TI
*/
#define MALLOC_FREE	1
#define MALLOC_USED	2

/** Magic number of a header.  Gives us some chance of 
    surviving if the list is corrupted*/
#define MALLOC_MAGIC	123

/* malloc hunk header definition */
typedef struct smalloc_hunk	mmalloc_hunk;
typedef struct smalloc_hunk *	pmmalloc_hunk;

struct smalloc_hunk {
    UBYTE 		magic;		/* Magic number - indicates valid hunk header */
    pmmalloc_hunk	next;		/* Pointer to the next hunk */
    UWORD 		size;		/* Size in bytes of this region */
    int 		status;		/* One of MALLOC_FREE or MALLOC_USED */
};

/** Start of free memory, as defined by the linker */
extern UBYTE malloc_heap_start;

/** First hunk */
extern pmmalloc_hunk malloc_first;

/** Garbage collect (join free hunks) */
void malloc_gc(void) NONBANKED;
/** debug message logger */
void debug( char *routine, char *msg ) NONBANKED;

#endif	/* __SYS_MALLOC_H */


================================================
FILE: include/gb/rand.h
================================================
/** @file rand.h
    Random generator using the linear congruential method

    @author	Luc Van den Borre
*/
#ifndef RAND_INCLUDE
#define RAND_INCLUDE

#include <types.h>

/** Initalise the random number generator.
    seed needs to be different each time, else the same sequence will be 
    generated.  A good source is the DIV register.
*/
void
initrand(UINT16 seed) NONBANKED; /* Non-banked as called from asm in arand.s */

/** Returns a random value.
 */
INT8
_rand(void);

/** Returns a random word.
 */
UINT16
_randw(void);

/** Random generator using the linear lagged additive method
    Note that 'initarand()' calls 'initrand()' with the same seed value, and
    uses 'rand()' to initialize the random generator.

    @author	Luc Van den Borre
*/
void
initarand(UINT16 seed);

/** Generates a random number using the linear lagged additive method.
 */
INT8
arand(void);

#endif


================================================
FILE: include/gb/sample.h
================================================
/** @file gb/sample.h
    Playback raw sound sample with length len from start at 8192Hz rate.
    len defines the length of the sample in samples/32 or bytes/16.
    The format of the data is unsigned 4-bit samples,
    2 samples per byte, upper 4-bits played before lower 4 bits.

    Adaption for GBDK by Lars Malmborg.
    Original code by Jeff Frohwein.
*/
#ifndef _SAMPLE_H
#define _SAMPLE_H

/** Play the given, appropriatly formatted sample.
 */
void
play_sample(UINT8 *start, UINT16 len) NONBANKED;

#endif /* _SAMPLE_H */


================================================
FILE: include/gb/sgb.h
================================================
/** @file gb/sgb.h
    Super Gameboy definitions.
*/
#ifndef _SGB_H
#define _SGB_H

/** Return a non-null value if running on Super GameBoy */
UINT8
sgb_check(void);

#endif /* _SGB_H */


================================================
FILE: libc/arand.s
================================================
;/***************************************************************************
; *                                                                         *
; * Module  : arand.s                                                       *
; *                                                                         *
; * Purpose : A random number generator using the lagged additive method    *
; *                                                                         *
; * Version : 1, January 11 1998                                            *
; *                                                                         *
; * Author  : Luc Van den Borre ( Homepage : NOC.BASE.ORG )                 *
; *                                                                         *
; **************************************************************************/

	;; BANKED: checked
	.include	"global.s"

	.globl	.initrand
	.globl	_rand

	.area	_BSS
.randarr:
	.ds	55
.raxj:
	.ds	0x01
.raxk:
	.ds	0x01

	.area	_CODE

	;; arand() operates on an array of 55 arbitrary values (here : bytes).
	;; It adds two values of the array together, replaces one of the values
	;; with the result, and returns the result.
	;; At start, the indices into the array refer to the 55th and 24th element.
	;; After each call, each index is decreased, and looped around if necessary.
	;; This kind of works, but the values produces are less good than those by
	;; rand(), mainly because it operates on bytes instead of words.
	;; Ref : D. E. Knuth, "The Art of Computer Programming" , Volume 2
	;;
	;; Exit conditions
	;;   DE = Random number (byte!)
	;;
	;; Registers used:
	;;   all
	;;
_arand::			; Banked
	PUSH	BC
	LD	D,#0
	LD	HL,#.randarr-1
	LD	A,(.raxj)
	LD	E,A
	DEC	A		; Decrease the pointer
	JR	NZ,1$
	LD	A,#55
1$:
	LD	(.raxj),A
	ADD	HL,DE
	LD	B,(HL)

	LD	HL,#.randarr-1	; Ooh...
	LD	A,(.raxk)
	LD	E,A
	DEC	A		; Decrease the pointer
	JR	NZ,2$
	LD	A,#55
2$:
	LD	(.raxk),A
	ADD	HL,DE
	LD	A,(HL)

	ADD	A,B
	LD	(HL),A		; Store new value

	POP	BC

	LD	D,#0
	LD	E,A

	RET

	;; _initarand calls the _rand function to fill the array with random values
	;; Note that this also sets the seed value of the _rand function first,
	;; like _initrand
	;;
	;; Exit conditions
	;;   None
	;;
	;; Registers used:
	;;   all
	;;
_initarand::			; Banked
	LDA	HL,.BANKOV(SP)
	CALL	.initrand

	PUSH	BC
	LD	A,#55
	LD	HL,#.randarr
1$:
	DEC	A
	LD	(.raxj),A
	LD	B,H
	LD	C,L
	CALL	_rand
	LD	H,B
	LD	L,C

	LD	(HL),D
	INC	HL
	LD	(HL),E
	INC	HL
	
	LD	A,(.raxj)
	CP	#0
	JR	NZ,1$

	LD	A,#24		; Now the array has been filled,set the pointers
	LD	(.raxj),A
	LD	A,#55
	LD	(.raxk),A

	POP	BC
	RET


================================================
FILE: libc/cgb.s
================================================
	.include "global.s"

	.title	"CGB support"
	.module	CGB

	;; BANKED: checked, imperfect
	.area	_BASE

_set_bkg_palette::		; Non-banked
	PUSH	BC
	PUSH	DE

	LDA	HL,9(SP)	; Skip return address and registers
	LD	B,(HL)		; BC = rgb_data
	DEC	HL
	LD	C,(HL)
	DEC	HL
	LD	D,(HL)		; D = nb_palettes
	DEC	HL
	LD	E,(HL)		; E = first_palette

	LD	A,D		; A = nb_palettes
	ADD	E
	ADD	A		; A *= 8
	ADD	A
	ADD	A
	LD	D,A

        LD      A,E		; E = first_palette
	ADD	A		; A *= 8
	ADD	A
	ADD	A
	LD	E,A		; A = first BCPS data
1$:
	LDH	A,(.STAT)
	AND	#0x02
	JR	NZ,1$

	LD	A,E
	LDH	(.BCPS),A
	LD	A,(BC)
	LDH	(.BCPD),A
	INC	BC		; next rgb_data
	INC	E		; next BCPS
	LD	A,E
	CP	A,D
	JR	NZ,1$

	POP	DE
	POP	BC
	RET

_set_sprite_palette::		; Non-banked
	PUSH	BC
	PUSH	DE

	LDA	HL,9(SP)	; Skip return address and registers
	LD	B,(HL)		; BC = rgb_data
	DEC	HL
	LD	C,(HL)
	DEC	HL
	LD	D,(HL)		; D = nb_palettes
	DEC	HL
	LD	E,(HL)		; E = first_palette

	LD	A,D		; A = nb_palettes
	ADD	E
	ADD	A		; A *= 8
	ADD	A
	ADD	A
	LD	D,A

        LD      A,E		; E = first_palette
	ADD	A		; A *= 8
	ADD	A
	ADD	A
	LD	E,A		; A = first BCPS data
1$:
	LDH	A,(.STAT)
	AND	#0x02
	JR	NZ,1$

	LD	A,E
	LDH	(.OCPS),A
	LD	A,(BC)
	LDH	(.OCPD),A
	INC	BC		; next rgb_data
	INC	E		; next BCPS
	LD	A,E
	CP	A,D
	JR	NZ,1$

	POP	DE
	POP	BC
	RET

	.area	_CODE
_set_bkg_palette_entry::	; Banked
	PUSH	BC
	PUSH	DE

	LDA	HL,.BANKOV+4+3(SP); Skip return address and registers
	LD	B,(HL)		; BC = rgb_data
	DEC	HL
	LD	C,(HL)
	DEC	HL
	LD	D,(HL)		; D = pal_entry
	DEC	HL
	LD	E,(HL)		; E = first_palette

        LD      A,E		; E = first_palette
	ADD	A		; A *= 8
	ADD	A
	ADD	A
	ADD	D		; A += 2 * pal_entry
	ADD	D
	LD	E,A		; A = first BCPS data

1$:
	LDH	A,(.STAT)
	AND	#0x02
	JR	NZ,1$

	LD	A,E
	LDH	(.BCPS),A
	LD	A,C
	LDH	(.BCPD),A
	INC	E		; next BCPS

	LD	A,E
	LDH	(.BCPS),A
	LD	A,B
	LDH	(.BCPD),A

	POP	DE
	POP	BC
	RET

_set_sprite_palette_entry::
	PUSH	BC
	PUSH	DE

	LDA	HL,.BANKOV+4+3(SP); Skip return address and registers
	LD	B,(HL)		; BC = rgb_data
	DEC	HL
	LD	C,(HL)
	DEC	HL
	LD	D,(HL)		; D = pal_entry
	DEC	HL
	LD	E,(HL)		; E = first_palette

        LD      A,E		; E = first_palette
	ADD	A		; A *= 8
	ADD	A
	ADD	A
	ADD	D		; A += 2 * pal_entry
	ADD	D
	LD	E,A		; A = first BCPS data

1$:
	LDH	A,(.STAT)
	AND	#0x02
	JR	NZ,1$

	LD	A,E
	LDH	(.OCPS),A
	LD	A,C
	LDH	(.OCPD),A
	INC	E		; next BCPS

	LD	A,E
	LDH	(.OCPS),A
	LD	A,B
	LDH	(.OCPD),A

	POP	DE
	POP	BC
	RET

	.area	_CODE
_cpu_slow::			; Banked
	LDH	A,(.KEY1)
	AND	#0x80		; Is GBC in double speed mode?
	RET	Z		; No, already in single speed

shift_speed:
	LDH	A,(.IE)
	PUSH	AF

	XOR	A		; A = 0
	LDH	(.IE),A		; Disable interrupts
	LDH	(.IF),A

	LD	A,#0x30
	LDH	(.P1),A

	LD	A,#0x01
	LDH	(.KEY1),A

	STOP

	POP	AF
	LDH	(.IE),A

	RET

_cpu_fast::			; Banked
	LDH	A,(.KEY1)
	AND	#0x80		; Is GBC in double speed mode?
	RET	NZ		; Yes, exit
        JR	shift_speed


_cgb_compatibility::		; Banked

	LD	A,#0x80
	LDH	(.BCPS),A	; Set default bkg palette
	LD	A,#0xff		; White
	LDH	(.BCPD),A
	LD	A,#0x7f
	LDH	(.BCPD),A
	LD	A,#0xb5		; Light gray
	LDH	(.BCPD),A
	LD	A,#0x56
	LDH	(.BCPD),A
	LD	A,#0x4a		; Dark gray
	LDH	(.BCPD),A
	LD	A,#0x29
	LDH	(.BCPD),A
	LD	A,#0x00		; Black
	LDH	(.BCPD),A
	LD	A,#0x00
	LDH	(.BCPD),A

	LD	A,#0x80
	LDH	(.OCPS),A	; Set default sprite palette
	LD	A,#0xff		; White
	LDH	(.OCPD),A
	LD	A,#0x7f
	LDH	(.OCPD),A
	LD	A,#0xb5		; Light gray
	LDH	(.OCPD),A
	LD	A,#0x56
	LDH	(.OCPD),A
	LD	A,#0x4a		; Dark gray
	LDH	(.OCPD),A
	LD	A,#0x29
	LDH	(.OCPD),A
	LD	A,#0x00		; Black
	LDH	(.OCPD),A
	LD	A,#0x00
	LDH	(.OCPD),A

	RET


================================================
FILE: libc/cpy_data.s
================================================
	.include	"global.s"

	;; BANKED: checked
	.area	_BASE
	;; Copy part (size = DE) of the VRAM from (BC) to (HL)
.copy_vram::
1$:
	LDH	A,(.STAT)
	AND	#0x02
	JR	NZ,1$

	LD	A,(BC)
	LD	(HL+),A
	INC	BC
	DEC	DE
	LD	A,D
	OR	E
	JR	NZ,1$
	RET

_set_data::
_get_data::
	PUSH	BC

	LDA	HL,9(SP)	; Skip return address and registers
	LD	D,(HL)		; DE = len
	DEC	HL
	LD	E,(HL)
	DEC	HL
	LD	B,(HL)		; BC = src
	DEC	HL
	LD	C,(HL)
	DEC	HL
	LD	A,(HL-)		; HL = dst
	LD	L,(HL)
	LD	H,A

	CALL	.copy_vram

	POP	BC
	RET


================================================
FILE: libc/crt0.s
================================================
	.include	"global.s"

	;; ****************************************
	;; Beginning of module
	;; BANKED: checked
	.title	"Runtime"
	.module	Runtime
	.area	_HEADER (ABS)

	;; Standard header for the GB
	.org	0x00
	RET			; Empty function (default for interrupts)

	.org	0x10
	.byte	0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01
	.byte	0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80

	;; Interrupt vectors
	.org	0x40		; VBL
.int_VBL:
	PUSH	HL
	LD	HL,#.int_0x40
	JP	.int

	.org	0x48		; LCD
.int_LCD:
	PUSH	HL
	LD	HL,#.int_0x48
	JP	.int

	.org	0x50		; TIM
.int_TIM:
	PUSH	HL
	LD	HL,#.int_0x50
	JP	.int

	.org	0x58		; SIO
.int_SIO:
	PUSH	HL
	LD	HL,#.int_0x58
	JP	.int

	.org	0x60		; JOY
.int_JOY:
	PUSH	HL
	LD	HL,#.int_0x60
	JP	.int

.int:
	PUSH	AF
	PUSH	BC
	PUSH	DE
1$:
	LD	A,(HL+)
	OR	(HL)
	JR	Z,2$
	PUSH	HL
	LD	A,(HL-)
	LD	L,(HL)
	LD	H,A
	CALL	3$
	POP	HL
	INC	HL
	JR	1$
2$:
	POP	DE
	POP	BC
	POP	AF
	POP	HL
	RETI

3$:
	JP	(HL)

	;; GameBoy Header

	;; DO NOT CHANGE...
	.org	0x100
.header:
	NOP
	JP	0x150
	.byte	0xCE,0xED,0x66,0x66
	.byte	0xCC,0x0D,0x00,0x0B
	.byte	0x03,0x73,0x00,0x83
	.byte	0x00,0x0C,0x00,0x0D
	.byte	0x00,0x08,0x11,0x1F
	.byte	0x88,0x89,0x00,0x0E
	.byte	0xDC,0xCC,0x6E,0xE6
	.byte	0xDD,0xDD,0xD9,0x99
	.byte	0xBB,0xBB,0x67,0x63
	.byte	0x6E,0x0E,0xEC,0xCC
	.byte	0xDD,0xDC,0x99,0x9F
	.byte	0xBB,0xB9,0x33,0x3E

	;; Title of the game
	.org	0x134
	.asciz	"Title"

	.org	0x144
	.byte	0,0,0

	;; Cartridge type is ROM only
	.org	0x147
	.byte	0

	;; ROM size is 32kB
	.org	0x148
	.byte	0

	;; RAM size is 0kB
	.org	0x149
	.byte	0

	;; Maker ID
	.org	0x14A
	.byte	0x00,0x00

	;; Version number
	.org	0x14C
	.byte	0x01

	;; Complement check
	.org	0x14D
	.byte	0x00

	;; Checksum
	.org	0x14E
	.byte	0x00,0x00

	;; ****************************************
	.org	0x150
.code_start:
	;; Beginning of the code
	DI			; Disable interrupts
	LD	D,A		; Store CPU type in D
	XOR	A
	;; Initialize the stack
	LD	SP,#.STACK
	;; Clear from 0xC000 to 0xDFFF
	LD	HL,#0xDFFF
	LD	C,#0x20
	LD	B,#0x00
1$:
	LD	(HL-),A
	DEC	B
	JR	NZ,1$
	DEC	C
	JR	NZ,1$
	;; Clear from 0xFE00 to 0xFEFF
	LD	HL,#0xFEFF
	LD	B,#0x00
2$:
	LD	(HL-),A
	DEC	B
	JR	NZ,2$
	;; Clear from 0xFF80 to 0xFFFF
	LD	HL,#0xFFFF
	LD	B,#0x80
3$:
	LD	(HL-),A
	DEC	B
	JR	NZ,3$
; 	LD	(.mode),A	; Clearing (.mode) is performed when clearing RAM
	;; Store CPU type
	LD	A,D
	LD	(__cpu),A

	;; Turn the screen off
	CALL	.display_off

	;; Initialize the display
	XOR	A
	LDH	(.SCY),A
	LDH	(.SCX),A
	LDH	(.STAT),A
	LDH	(.WY),A
	LD	A,#0x07
	LDH	(.WX),A

	;; Copy refresh_OAM routine to HIRAM
	LD	BC,#.refresh_OAM
	LD	HL,#.start_refresh_OAM
	LD	B,#.end_refresh_OAM-.start_refresh_OAM
4$:
	LD	A,(HL+)
	LDH	(C),A
	INC	C
	DEC	B
	JR	NZ,4$

	;; Install interrupt routines
	LD	BC,#.vbl
	CALL	.add_VBL
	LD	BC,#.serial_IO
	CALL	.add_SIO

	;; Standard color palettes
	LD	A,#0b11100100	; Grey 3 = 11 (Black)
				; Grey 2 = 10 (Dark grey)
				; Grey 1 = 01 (Light grey)
				; Grey 0 = 00 (Transparent)
	LDH	(.BGP),A
	LDH	(.OBP0),A
	LD	A,#0b00011011
	LDH	(.OBP1),A

	;; Turn the screen on
	LD	A,#0b11000000	; LCD		= On
				; WindowBank	= 0x9C00
				; Window	= Off
				; BG Chr	= 0x8800
				; BG Bank	= 0x9800
				; OBJ		= 8x8
				; OBJ		= Off
				; BG		= Off
	LDH	(.LCDC),A
	XOR	A
	LDH	(.IF),A
	LD	A,#0b00001001	; Pin P10-P13	=   Off
				; Serial I/O	=   On
				; Timer Ovfl	=   Off
				; LCDC		=   Off
				; V-Blank	=   On
	LDH	(.IE),A

	XOR	A
	LDH	(.NR52),A	; Turn sound off
	LDH	(.SC),A		; Use external clock
	LD	A,#.DT_IDLE
	LDH	(.SB),A		; Send IDLE byte
	LD	A,#0x80
	LDH	(.SC),A		; Use external clock

	XOR	A		; Erase the malloc list
;	LD	(_malloc_heap_start+0),A
;	LD	(_malloc_heap_start+1),A
;	LD	(.sys_time+0),A	; Zero the system clock
;	LD	(.sys_time+1),A	

	call	gsinit

;	CALL	.init		

	EI			; Enable interrupts

	;; Call the main function
	CALL	banked_call
	.dw	_main
	.if __RGBDS__
	.dw	BANK(_main)
	.else
	.dw	1
	.endif
_exit::	
99$:
	HALT
	JR	99$		; Wait forever

	.org	.MODE_TABLE
	;; Jump table for modes
	RET

	;; ****************************************

	;; Ordering of segments for the linker
	;; Code that really needs to be in bank 0
	.area	_HOME
	;; Similar to _HOME
	.area	_BASE
	;; Code
	.area	_CODE
	;; Constant data
	.area	_LIT
	;; Constant data used to init _DATA
	.area	_GSINIT
	.area	_GSINITTAIL
	.area	_GSFINAL
	;; Initialised in ram data
	.area	_DATA
	;; Uninitialised ram data
	.area	_BSS
	;; For malloc
	.area	_HEAP

	.area	_BSS
__cpu::
	.ds	0x01		; GB type (GB, PGB, CGB)
.mode::
	.ds	0x01		; Current mode
__io_out::
	.ds	0x01		; Byte to send
__io_in::
	.ds	0x01		; Received byte
__io_status::
	.ds	0x01		; Status of serial IO
.vbl_done::
	.ds	0x01		; Is VBL interrupt finished?
__current_bank::
	.ds	0x01		; Current MBC1 style bank.
.sys_time::
_sys_time::
	.ds	0x02		; System time in VBL units
.int_0x40::
	.blkw	0x08
.int_0x48::
	.blkw	0x08
.int_0x50::
	.blkw	0x08
.int_0x58::
	.blkw	0x08
.int_0x60::
	.blkw	0x08

	;; Runtime library
	.area	_GSINIT
gsinit::
	.area	_GSINITTAIL
	ret
	
	.area	_HOME
	;; Call the initialization function for the mode specified in HL
.set_mode::
	LD	A,L
	LD	(.mode),A

	;; AND to get rid of the extra flags
	AND	#0x03
	LD	L,A
	LD	BC,#.MODE_TABLE
	SLA	L		; Multiply mode by 4
	SLA	L
	ADD	HL,BC
	JP	(HL)		; Jump to initialization routine

	;; Add interrupt routine in BC to the interrupt list
.remove_VBL::
	LD	HL,#.int_0x40
	JP	.remove_int
.remove_LCD::
	LD	HL,#.int_0x48
	JP	.remove_int
.remove_TIM::
	LD	HL,#.int_0x50
	JP	.remove_int
.remove_SIO::
	LD	HL,#.int_0x58
	JP	.remove_int
.remove_JOY::
	LD	HL,#.int_0x60
	JP	.remove_int
.add_VBL::
	LD	HL,#.int_0x40
	JP	.add_int
.add_LCD::
	LD	HL,#.int_0x48
	JP	.add_int
.add_TIM::
	LD	HL,#.int_0x50
	JP	.add_int
.add_SIO::
	LD	HL,#.int_0x58
	JP	.add_int
.add_JOY::
	LD	HL,#.int_0x60
	JP	.add_int

	;; Remove interrupt BC from interrupt list HL if it exists
	;; Abort if a 0000 is found (end of list)
	;; Will only remove last int on list
.remove_int::
1$:
	LD	A,(HL+)
	LD	E,A
	LD	D,(HL)
	OR	D
	RET	Z		; No interrupt found

	LD	A,E
	CP	C
	JR	NZ,1$
	LD	A,D
	CP	B
	JR	NZ,1$

	XOR	A
	LD	(HL-),A
	LD	(HL),A
	INC	A		; Clear Z flag

	;; Now do a memcpy from here until the end of the list
	LD	D,H
	LD	E,L
	DEC	DE

	INC	HL
2$:
	LD	A,(HL+)
	LD	(DE),A
	LD	B,A
	INC	DE
	LD	A,(HL+)
	LD	(DE),A
	INC	DE
	OR	B
	RET	Z
	JR	2$
	
	;; Add interrupt routine in BC to the interrupt list in HL
.add_int::
1$:
	LD	A,(HL+)
	OR	(HL)
	JR	Z,2$
	INC	HL
	JR	1$
2$:
	LD	(HL),B
	DEC	HL
	LD	(HL),C
	RET

	
	;; VBlank interrupt
.vbl:
	LD	HL,#.sys_time
	INC	(HL)
	JR	NZ,2$
	INC	HL
	INC	(HL)
2$:	
	CALL	.refresh_OAM

	LD	A,#0x01
	LD	(.vbl_done),A
	RET

	;; Wait for VBL interrupt to be finished
.wait_vbl_done::
_wait_vbl_done::
	;; Check if the screen is on
	LDH	A,(.LCDC)
	ADD	A
	RET	NC		; Return if screen is off
	XOR	A
	DI
	LD	(.vbl_done),A	; Clear any previous sets of vbl_done
	EI
1$:
	HALT			; Wait for any interrupt
	NOP			; HALT sometimes skips the next instruction
	LD	A,(.vbl_done)	; Was it a VBlank interrupt?
	;; Warning: we may lose a VBlank interrupt, if it occurs now
	OR	A
	JR	Z,1$		; No: back to sleep!

	XOR	A
	LD	(.vbl_done),A
	RET

.display_off::
_display_off::
	;; Check if the screen is on
	LDH	A,(.LCDC)
	ADD	A
	RET	NC		; Return if screen is off
1$:				; We wait for the *NEXT* VBL 
	LDH	A,(.LY)
	CP	#0x92		; Smaller than or equal to 0x91?
	JR	NC,1$		; Loop until smaller than or equal to 0x91
2$:
	LDH	A,(.LY)
	CP	#0x91		; Bigger than 0x90?
	JR	C,2$		; Loop until bigger than 0x90

	LDH	A,(.LCDC)
	AND	#0b01111111
	LDH	(.LCDC),A	; Turn off screen
	RET

	;; Copy OAM data to OAM RAM
.start_refresh_OAM:
	LD	A,#>.OAM
	LDH	(.DMA),A	; Put A into DMA registers
	LD	A,#0x28		; We need to wait 160 ns
1$:
	DEC	A
	JR	NZ,1$
	RET
.end_refresh_OAM:

	;; Serial interrupt
.serial_IO::
	LD	A,(__io_status) ; Get status

	CP	#.IO_RECEIVING
	JR	NZ,10$

	;; Receiving data
	LDH	A,(.SB)		; Get data byte
	LD	(__io_in),A	; Store it
	LD	A,#.IO_IDLE
	JR	11$

10$:

	CP	#.IO_SENDING
	JR	NZ,99$

	;; Sending data
	LDH	A,(.SB)		; Get data byte
	CP	#.DT_RECEIVING
	JR	Z,11$
	LD	A,#.IO_ERROR
	JR	12$
11$:
	LD	A,#.IO_IDLE
12$:
	LD	(__io_status),A ; Store status

	XOR	A
	LDH	(.SC),A		; Use external clock
	LD	A,#.DT_IDLE
	LDH	(.SB),A		; Reply with IDLE byte
99$:
	LD	A,#0x80
	LDH	(.SC),A		; Enable transfer with external clock
	RET

_mode::
	LDA	HL,2(SP)	; Skip return address
	LD	L,(HL)
	LD	H,#0x00
	CALL	.set_mode
	RET

_get_mode::
	LD	HL,#.mode
	LD	E,(HL)
	RET
	
_enable_interrupts::
	EI
	RET

_disable_interrupts::
	DI
	RET

.reset::
_reset::
	LD	A,(__cpu)
	JP	.code_start

_set_interrupts::
	DI
	LDA	HL,2(SP)	; Skip return address
	XOR	A
	LDH	(.IF),A		; Clear pending interrupts
	LD	A,(HL)
	LDH	(.IE),A
	EI			; Enable interrupts
	RET

_remove_VBL::
	PUSH	BC
	LDA	HL,4(SP)	; Skip return address and registers
	LD	C,(HL)
	INC	HL
	LD	B,(HL)
	CALL	.remove_VBL
	POP	BC
	RET

_remove_LCD::
	PUSH	BC
	LDA	HL,4(SP)	; Skip return address and registers
	LD	C,(HL)
	INC	HL
	LD	B,(HL)
	CALL	.remove_LCD
	POP	BC
	RET

_remove_TIM::
	PUSH	BC
	LDA	HL,4(SP)	; Skip return address and registers
	LD	C,(HL)
	INC	HL
	LD	B,(HL)
	CALL	.remove_TIM
	POP	BC
	RET

_remove_SIO::
	PUSH	BC
	LDA	HL,4(SP)	; Skip return address and registers
	LD	C,(HL)
	INC	HL
	LD	B,(HL)
	CALL	.remove_SIO
	POP	BC
	RET

_remove_JOY::
	PUSH	BC
	LDA	HL,4(SP)	; Skip return address and registers
	LD	C,(HL)
	INC	HL
	LD	B,(HL)
	CALL	.remove_JOY
	POP	BC
	RET
	
_add_VBL::
	PUSH	BC
	LDA	HL,4(SP)	; Skip return address and registers
	LD	C,(HL)
	INC	HL
	LD	B,(HL)
	CALL	.add_VBL
	POP	BC
	RET

_add_LCD::
	PUSH	BC
	LDA	HL,4(SP)	; Skip return address and registers
	LD	C,(HL)
	INC	HL
	LD	B,(HL)
	CALL	.add_LCD
	POP	BC
	RET

_add_TIM::
	PUSH	BC
	LDA	HL,4(SP)	; Skip return address and registers
	LD	C,(HL)
	INC	HL
	LD	B,(HL)
	CALL	.add_TIM
	POP	BC
	RET

_add_SIO::
	PUSH	BC
	LDA	HL,4(SP)	; Skip return address and registers
	LD	C,(HL)
	INC	HL
	LD	B,(HL)
	CALL	.add_SIO
	POP	BC
	RET

_add_JOY::
	PUSH	BC
	LDA	HL,4(SP)	; Skip return address and registers
	LD	C,(HL)
	INC	HL
	LD	B,(HL)
	CALL	.add_JOY
	POP	BC
	RET

_clock::
	ld	hl,#.sys_time
	di
	ld	a,(hl+)
	ei
	;; Interrupts are disabled for the next instruction...
	ld	d,(hl)
	ld	e,a
	ret

__printTStates::
	ret

	;; Performs a long call.
	;; Basically:
	;;   call banked_call
	;;   .dw low
	;;   .dw bank
	;;   remainder of the code
	;; Total m-cycles:
	;;	3+4+4 + 2+2+2+2+2+2 + 4+4+ 3+4+1+1+1
	;;      = 41 for the call
	;;	3+3+4+4+1
	;;	= 15 for the ret
banked_call::
	pop	hl		; Get the return address
	ld	a,(__current_bank)
	push	af		; Push the current bank onto the stack
	ld	e,(hl)		; Fetch the call address
	inc	hl
	ld	d,(hl)
	inc	hl
	ld	a,(hl+)		; ...and page
	inc	hl		; Yes this should be here
	push	hl		; Push the real return address
	ld	(__current_bank),a
	ld	(.MBC1_ROM_PAGE),a	; Perform the switch
	ld	hl,#banked_ret	; Push the fake return address
	push	hl
	ld	l,e
	ld	h,d
	jp	(hl)

banked_ret::
	pop	hl		; Get the return address
	pop	af		; Pop the old bank
	ld	(.MBC1_ROM_PAGE),a
	ld	(__current_bank),a
	jp	(hl)
		
	.area	_HEAP
_malloc_heap_start::


================================================
FILE: libc/delay.s
================================================
	.include	"global.s"

	;; BANKED:	checked, imperfect
	.area	_BASE

	;; Delay DE milliseconds
	;; 
	;; Entry conditions
	;;   DE = number of milliseconds to delay (1 to 65536, 0 = 65536)
	;; 
	;; Register used: AF, DE
	.CPMS	= 4194/4	; 4.194304 MHz
.delay::			; 6 cycles for the CALL
	PUSH	BC		; 4 cycles
	CALL	.dly		; 12 cycles to return from .dly (6+1+5)
	LD	B,#.CPMS/20-2 ; 2 cycles
				; =========
				; 24 cycles
.ldlp:
	JR	1$		; 3 cycles
1$:	JR	2$		; 3 cycles
2$:	JR	3$		; 3 cycles
3$:	JR	4$		; 3 cycles
4$:	JR	5$		; 3 cycles
5$:	DEC	B		; 1 cycles
	JP	NZ,.ldlp	; 3 cycles (if TRUE: 4 cycles)
	NOP			; 1 cycles
				; =========
				; 20 cycles
	;; Exit in 16 cycles
	POP	BC		; 3 cycles
	JR	6$		; 3 cycles
6$:	JR	7$		; 3 cycles
7$:	JR	8$		; 3 cycles
8$:	RET			; 4 cycles
				; =========
				; 16 cycles

	;; Delay all but last millisecond
.dly:
	DEC	DE		; 2 cycles
	LD	A,E		; 1 cycles
	OR	D		; 1 cycles
	RET	Z		; 2 cycles (upon return: 5 cycles)
	LD	B,#.CPMS/20-1   ; 2 cycles
				; =========
				; 8 cycles
.dlp:
	JR	1$		; 3 cycles
1$:	JR	2$		; 3 cycles
2$:	JR	3$		; 3 cycles
3$:	JR	4$		; 3 cycles
4$:	JR	5$		; 3 cycles
5$:	DEC	B		; 1 cycles
	JP	NZ,.dlp		; 3 cycles (if TRUE: 4 cycles)
	NOP			; 1 cycles
				; =========
				; 20 cycles
	;; Exit in 15 cycles
	JR	6$		; 3 cycles
6$:	JR	7$		; 3 cycles
7$:	JR	8$		; 3 cycles
8$:	JR	.dly		; 3 cycles
				; =========
				; 12 cycles

_delay::
	LDA	HL,2(SP)	; Skip return address
	LD	E,(HL)		; DE = delay
	INC	HL
	LD	D,(HL)
	CALL	.delay
	RET


================================================
FILE: libc/digits.c
================================================
#pragma bank=BASE

const char * const digits = "0123456789ABCDEF";


================================================
FILE: libc/drawing.s
================================================
;; Optimised Drawing library 
;; By Jon Fuge (jonny@q-continuum.demon.co.uk) based on original file
;; Updates
;;   990223 Michael	Removed mod_col, splitting it up into 
;;			fg_colour, bg_colour, and draw_mode
;; Note: some optimisations are available with unneded PUSH DE/POP DE's

	;; BANKED: checked
	.include        "global.s"

	.globl  .init_vram
	.globl  .copy_vram

	.M_SOLID	=	0x00
	.M_OR	=	0x01
	.M_XOR	=	0x02
	.M_AND	=	0x03

	.if	0
	.M_SOLID	=	0x10
	.M_OR	=	0x20
	.M_XOR	=	0x40
	.M_AND	=	0x80
	.endif

	;;  Format of mod_col
	;; 7 6 5 4 3 2 1 0
	;;   mode  fg  bg

	.area   _HEADER (ABS)

	.org    .MODE_TABLE+4*.G_MODE
	JP      .gmode

	.module Drawing1

	;; Data
	.area	_BSS
	;; Foreground drawing colour
.fg_colour::	
	.ds	1
	;; Background drawing colour
.bg_colour::	
	.ds	1
	;; Drawing mode (.SOILD etc)
.draw_mode:
	.ds	1
	;; Fill style
.style:	
	.ds	0x01
	;; Various varibles
.x_s:	
	.ds	2
.y_s:	
	.ds	2
.delta_x:	
	.ds	1
.delta_y:	
	.ds	1
.l_inc:	
	.ds	1
.l_d:	
	.ds	2
.dinc1:	
	.ds	2
.dinc2:	
	.ds	2
.tx:	
	.ds	1
.ty:	
	.ds	1
	
	.area   _BASE
	;; Enter graphic mode
.gmode::
	DI			; Disable interrupts

	;; Turn the screen off
	LDH	A,(.LCDC)
	BIT	7,A
	JR	Z,1$

	;; Turn the screen off
	CALL	.display_off
1$:
	LD	HL,#0x8000+0x10*0x10
	LD	DE,#0x1800-0x18*0x10
	LD	B,#0x00
	CALL	.init_vram	; Init the charset at 0x8000

	;; Install interrupt routines
	LD	BC,#.vbl
	CALL	.add_VBL
	LD	BC,#.lcd
	CALL	.add_LCD

	LD	A,#72		; Set line at which LCD interrupt occurs
	LDH	(.LYC),A

	LD	A,#0b01000100	; Set LCD interrupt to occur when LY = LCY
	LDH	(.STAT),A

	LDH	A,(.IE)
	OR	#0b00000010	; Enable LCD interrupt
	LDH	(.IE),A

	;; (9*20) = 180 tiles are used in the upper part of the screen
	;; (9*20) = 180 tiles are used in the lower part of the screen
	;; => We have 24 tiles free
	;; We keep 16 at 0x8000->0x80FF, and 8 at 0x9780->97FF

	LD	HL,#0x9800
	LD	A,#0x10		; Keep 16 tiles free
	LD	BC,#12		; 12 unused columns
	LD	E,#18		; 18 lines
2$:
	LD	D,#20		; 20 used columns
3$:
	LD	(HL+),A
	INC	A
	DEC	D
	JR	NZ,3$
	ADD	HL,BC
	DEC	E
	JR	NZ,2$

	;; Turn the screen on
	LDH	A,(.LCDC)
	OR	#0b10010001	; LCD		= On
				; BG Chr	= 0x8000
				; BG		= On
	AND	#0b11110111	; BG Bank	= 0x9800
	LDH	(.LCDC),A

	LD	A,#.G_MODE
	LD	(.mode),A

	;; Setup the default colours and draw modes
	LD	A,#.M_SOLID
	LD	(.draw_mode),A
	LD	A,#0x03		; Black
	LD	(.fg_colour),A
	LD	A,#0x00		; White
	LD	(.bg_colour),A
	
	EI			; Enable interrupts

	RET

.vbl::
	LDH	A,(.LCDC)
	OR	#0b00010000	; Set BG Chr to 0x8000
	LDH	(.LCDC),A

	LD	A,#72		; Set line at which LCD interrupt occurs
	LDH	(.LYC),A

	RET

	;; Is the STAT check required, as we are already in the HBL?
.lcd::
1$:
	LDH	A,(.STAT)
	BIT	1,A
	JR	NZ,1$

	LDH	A,(.LCDC)
	AND	#0b11101111	; Set BG Chr to 0x8800
	LDH	(.LCDC),A

	RET

	;; Draw a full-screen image at (BC)
.draw_image::
	LD      HL,#0x8000+0x10*0x10
	LD      DE,#0x1680
	CALL    .copy_vram      ; Move the charset
	RET

	;; Replace tile data at (B,C) with data at DE and store old value at HL
.switch_data::
	PUSH    DE              ; Save src
	PUSH    HL              ; Save dst
	LD      L,B
	SLA     L
	SLA     L
	SLA     L
	LD      H,#0x00
	ADD     HL,HL
	LD      D,H
	LD      E,L

	LD      HL,#.y_table
	SLA     C
	SLA     C
	SLA     C
	LD      B,#0x00
	ADD     HL,BC
	ADD     HL,BC
	LD      B,(HL)
	INC     HL
	LD      H,(HL)
	LD      L,B
	ADD     HL,DE

	LD      B,H             ; BC = src
	LD      C,L
	POP     HL              ; HL = dst
	PUSH    BC              ; Save dst
	LD      A,H
	OR      L
	JR      Z,1$
	LD      DE,#0x10
	CALL    .copy_vram
1$:
	POP     HL              ; HL = dst
	POP     BC              ; BC = src
	LD      DE,#0x10
	CALL    .copy_vram

	RET

	.area	_CODE
	;; Advance the cursor
.adv_gcurs::
	PUSH	HL
	LD	HL,#.tx	; X coordinate
	LD	A,#.MAXCURSPOSX
	CP	(HL)
	JR	Z,1$
	INC	(HL)
	JR	99$
1$:
	LD	(HL),#0x00
	LD	HL,#.ty	; Y coordinate
	LD	A,#.MAXCURSPOSY
	CP	(HL)
	JR	Z,2$
	INC	(HL)
	JR	99$
2$:
	LD	(HL),#0x00
99$:
	POP	HL
	RET

	;; Draw a circle from (B,C) with radius D
.circle::
	LD	A,B	;Store center values
	LD	(.x_s),A
	LD	A,C
	LD	(.y_s),A

	XOR	A
	LD	(.x_s+1),A 
	LD	A,D
	LD	(.y_s+1),A 
	CPL
	LD	L,A
	LD	H,#0xFF
	INC	HL
	LD	BC,#0
	ADD	HL,BC
	LD	A,L
	LD	(.l_d+1),A
	LD	A,H
	LD	(.l_d),A

cloop$:
	LD	A,(.x_s+1)
	LD	B,A
	LD	A,(.y_s+1)
	SUB	B
	RET	C

	LD	A,(.style)
	OR	A
	CALL	Z,.circplot

	LD	A,(.l_d)
	BIT	7,A
	JR	Z,ycirc$

	LD	A,(.style)
	OR	A
	CALL	NZ,.horlin
	LD	A,(.x_s+1)
	INC	A
	LD	(.x_s+1),A
	LD	A,(.l_d)
	LD	B,A
	LD	A,(.l_d+1)
	LD	C,A
	LD	H,#0
	LD	A,(.x_s+1)
	LD	L,A
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,BC
	LD	BC,#6
	ADD	HL,BC
	LD	A,H
	LD	(.l_d),A
	LD	A,L
	LD	(.l_d+1),A
	JR	cloop$
ycirc$:	
	LD	A,(.style)
	OR	A
	CALL	NZ,.verlin
	LD	A,(.x_s+1)
	INC	A
	LD	(.x_s+1),A
	LD	B,#0
	LD	A,(.x_s+1)
	LD	C,A
	LD	H,#0xFF
	LD	A,(.y_s+1)
	CPL
	LD	L,A
	INC	HL
	ADD	HL,BC
	LD	A,(.l_d)
	LD	B,A
	LD	A,(.l_d+1)
	LD	C,A
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,BC
	LD	BC,#10
	ADD	HL,BC
	LD	A,H
	LD	(.l_d),A
	LD	A,L
	LD	(.l_d+1),A
	LD	A,(.y_s+1)
	DEC	A
	LD	(.y_s+1),A
	JP	cloop$

.horlin::
	LD	A,(.x_s)
	LD	B,A
	LD	A,(.y_s)
	LD	C,A
	LD	A,(.x_s+1)
	LD	D,A
	LD	A,(.y_s+1)
	LD	E,A
	PUSH	BC
	PUSH	DE
	LD	A,B
	SUB	E
	LD	H,A
	LD	A,B
	ADD	E
	LD	B,A
	LD	A,C
	ADD	D
	LD	C,A
	LD	D,H
	LD	E,C
	CALL	.line
	POP	DE
	POP	BC
	LD	A,D
	OR	A
	RET	Z
	PUSH	BC
	PUSH	DE
	LD	A,B
	SUB	E
	LD	H,A
	LD	A,B
	ADD	E
	LD	B,A
	LD	A,C
	SUB	D
	LD	C,A
	LD	D,H
	LD	E,C
	CALL	.line
	POP	DE
	POP	BC
	RET

.verlin::
	LD	A,(.x_s)
	LD	B,A
	LD	A,(.y_s)
	LD	C,A
	LD	A,(.x_s+1)
	LD	D,A
	LD	A,(.y_s+1)
	LD	E,A
	PUSH	BC
	PUSH	DE
	LD	A,B
	SUB	E
	LD	H,A
	LD	A,B
	ADD	E
	LD	B,A
	LD	A,C
	ADD	D
	LD	C,A
	LD	D,H
	LD	E,C
	CALL	.line
	POP	DE
	POP	BC
	PUSH	BC
	PUSH	DE
	LD	A,B
	SUB	E
	LD	H,A
	LD	A,B
	ADD	E
	LD	B,A
	LD	A,C
	SUB	D
	LD	C,A
	LD	D,H
	LD	E,C
	CALL	.line
	POP	DE
	POP	BC
	LD	A,D
	SUB	E
	RET	Z
	PUSH	BC
	PUSH	DE
	LD	A,B
	SUB	D
	LD	H,A
	LD	A,B
	ADD	D
	LD	B,A
	LD	A,C
	SUB	E
	LD	C,A
	LD	D,H
	LD	E,C
	CALL	.line
	POP	DE
	POP	BC
	PUSH	BC
	PUSH	DE
	LD	A,B
	SUB	D
	LD	H,A
	LD	A,B
	ADD	D
	LD	B,A
	LD	A,C
	ADD	E
	LD	C,A
	LD	D,H
	LD	E,C
	CALL	.line
	POP	DE
	POP	BC
	RET

.circplot::
	LD	A,(.x_s)
	LD	B,A
	LD	A,(.y_s)
	LD	C,A
	LD	A,(.x_s+1)
	LD	D,A
	LD	A,(.y_s+1)
	LD	E,A
	PUSH	BC
	PUSH	DE
	LD	A,B
	ADD	D
	LD	B,A
	LD	A,C
	SUB	E
	LD	C,A
	CALL	.plot
	POP	DE
	POP	BC
	PUSH	BC
	PUSH	DE
	LD	A,B
	SUB	E
	LD	B,A
	LD	A,C
	SUB	D
	LD	C,A
	CALL	.plot
	POP	DE
	POP	BC
	PUSH	BC
	PUSH	DE
	LD	A,B
	SUB	D
	LD	B,A
	LD	A,C
	ADD	E
	LD	C,A
	CALL	.plot
	POP	DE
	POP	BC
	PUSH	BC
	PUSH	DE
	LD	A,B
	ADD	E
	LD	B,A
	LD	A,C
	ADD	D
	LD	C,A
	CALL	.plot
	POP	DE
	POP	BC
	
	LD	A,D
	OR	A
	RET	Z
	SUB	E
	RET	Z

	PUSH	BC
	PUSH	DE
	LD	A,B
	SUB	D
	LD	B,A
	LD	A,C
	SUB	E
	LD	C,A
	CALL	.plot
	POP	DE
	POP	BC
	PUSH	BC
	PUSH	DE
	LD	A,B
	SUB	E
	LD	B,A
	LD	A,C
	ADD	D
	LD	C,A
	CALL	.plot
	POP	DE
	POP	BC
	PUSH	BC
	PUSH	DE
	LD	A,B
	ADD	D
	LD	B,A
	LD	A,C
	ADD	E
	LD	C,A
	CALL	.plot
	POP	DE
	POP	BC
	PUSH	BC
	PUSH	DE
	LD	A,B
	ADD	E
	LD	B,A
	LD	A,C
	SUB	D
	LD	C,A
	CALL	.plot
	POP	DE
	POP	BC
	RET

	;; Draw a box between (B,C) and (D,E)
.box::
	LD	A,(.x_s)
	LD	B,A
	LD	A,(.x_s+1)
	LD	C,A
	SUB	B
	JR	NC,ychk$
	LD	A,C
	LD	(.x_s),A
	LD	A,B
	LD	(.x_s+1),A
ychk$:
	LD	A,(.y_s)
	LD	B,A
	LD	A,(.y_s+1)
	LD	C,A
	SUB	B
	JR	NC,dbox$
	LD	A,C
	LD	(.y_s),A
	LD	A,B
	LD	(.y_s+1),A
dbox$:
	LD	A,(.x_s)
	LD	B,A
	LD	D,A
	LD	A,(.y_s)
	LD	C,A
	LD	A,(.y_s+1)
	LD	E,A
	CALL	.line
	LD	A,(.x_s+1)
	LD	B,A
	LD	D,A
	LD	A,(.y_s)
	LD	C,A
	LD	A,(.y_s+1)
	LD	E,A
	CALL	.line
	LD	A,(.x_s)
	INC	A
	LD	(.x_s),A
	LD	A,(.x_s+1)
	DEC	A
	LD	(.x_s+1),A
	LD	A,(.x_s)
	LD	B,A
	LD	A,(.x_s+1)
	LD	D,A
	LD	A,(.y_s)
	LD	C,A
	LD	E,A
	CALL	.line
	LD	A,(.x_s)
	LD	B,A
	LD	A,(.x_s+1)
	LD	D,A
	LD	A,(.y_s+1)
	LD	C,A
	LD	E,A
	CALL	.line
	LD	A,(.style)
	OR	A
	RET	Z
	LD	A,(.x_s)
	LD	B,A
	LD	A,(.x_s+1)
	SUB	B
	RET	C
	LD	A,(.y_s)
	INC	A
	LD	(.y_s),A
	LD	A,(.y_s+1)
	DEC	A
	LD	(.y_s+1),A
	LD	A,(.y_s)
	LD	B,A
	LD	A,(.y_s+1)
	SUB	B
	RET	C

	.if	0
	LD	A,(.mod_col)	;Swap fore + back colours.
	LD	D,A
	AND	#0xF0
	LD	C,A		;Preserve Style
	LD	A,D
	AND	#0x0C
	RRCA
	RRCA
	OR	C		;Foreground->background + style
	LD	C,A
	LD	A,D
	AND	#0x03
	RLCA
	RLCA
	OR	C
	LD	(.mod_col),A
	.else
	LD	A,(.fg_colour)
	LD	C,A
	LD	A,(.bg_colour)
	LD	(.fg_colour),A
	LD	A,C
	LD	(.bg_colour),A
	.endif 
filllp$:
	LD	A,(.x_s)
	LD	B,A
	LD	A,(.x_s+1)
	LD	D,A
	LD	A,(.y_s)
	LD	C,A
	LD	E,A
	CALL	.line
	LD	A,(.y_s+1)
	LD	B,A
	LD	A,(.y_s)
	CP	B
	JR	Z,swap$
	INC	A
	LD	(.y_s),A
	JR	filllp$
swap$:	
	.if	0
	LD	A,(.mod_col)	;Swap fore + back colours.
	LD	D,A
	AND	#0xF0
	LD	C,A		;Preserve Style
	LD	A,D
	AND	#0x0C
	RRCA
	RRCA
	OR	C		;Foreground->background + style
	LD	C,A
	LD	A,D
	AND	#0x03
	RLCA
	RLCA
	OR	C
	LD	(.mod_col),A
	.else
	LD	A,(.fg_colour)
	LD	C,A
	LD	A,(.bg_colour)
	LD	(.fg_colour),A
	LD	A,C
	LD	(.bg_colour),A
	.endif
	RET

	;; Draw a line between (B,C) and (D,E)
.line::
	LD	A,C	;Calculate Delta Y
	SUB	E
	JR	NC,s1$
	CPL
	INC	A
s1$:	LD	(.delta_y),A
	LD	H,A

	LD	A,B	;Calculate Delta X
	SUB	D
	JR	NC,s2$
	CPL
	INC	A
s2$:	LD	(.delta_x),A

	SUB	H
	JP	C,y1

	;; Use Delta X

	LD	A,B
	SUB	D
	JP	NC,x2$

	LD	A,C
	SUB	E
	JR	Z,x3$
	LD	A,#0x00
	JR	NC,x3$
	LD	A,#0xFF
	JR	x3$

x2$:
	LD	A,E
	SUB	C
	JR	Z,x2a$
	LD	A,#0x00
	JR	NC,x2a$
	LD	A,#0xFF

x2a$:
	LD	B,D
	LD	C,E	;BC holds start X,Y
x3$:
	LD	(.l_inc),A	;Store Y increment
	LD	HL,#.y_table
	LD	D,#0x00
	LD	E,C
	ADD	HL,DE
	ADD	HL,DE
	LD	A,(HL+)
	LD	H,(HL)
	LD	L,A

	LD	A,B
	AND	#0xf8
	LD	E,A
	ADD	HL,DE
	ADD	HL,DE

	LD	A,(.delta_y)
	OR	A
	JP	Z,.xonly

	;;	Got to do it the hard way.

	;	Calculate (2*deltay) -> dinc1

	PUSH	HL
	LD	H,#0x00
	LD	L,A
	ADD	HL,HL
	LD	A,H
	LD	(.dinc1),A
	LD	A,L
	LD	(.dinc1+1),A

	;	Calculate (2*deltay)-deltax -> d


	LD	D,H
	LD	E,L
	LD	A,(.delta_x)
	CPL
	LD	L,A
	LD	H,#0xFF
	INC	HL
dx1$:
	ADD	HL,DE
	LD	A,H
	LD	(.l_d),A
	LD	A,L
	LD	(.l_d+1),A

	;	Calculate (deltay-deltax)*2 -> dinc2

	LD	A,(.delta_x)
	CPL
	LD	L,A
	LD	H,#0xFF
	INC	HL
	LD	A,(.delta_y)
	LD	D,#0x00
	LD	E,A
	ADD	HL,DE
	ADD	HL,HL

	LD	A,H
	LD	(.dinc2),A
	LD	A,L
	LD	(.dinc2+1),A

	POP	HL

	.if	0
	LD	A,(.mod_col)
	LD	D,A
	.endif
	
	LD	A,(.delta_x)
	LD	E,A

	LD	A,B
	AND	#7
	ADD	#0x10	; Table of bits is located at 0x0010
	LD	C,A
	LD	B,#0x00
	LD	A,(BC)	; Get start bit
	LD	B,A
	LD	C,A

xloop$:
	RRC	C
	LD	A,(.l_d)
	BIT	7,A
	JR	Z,ychg$
	PUSH	DE
	BIT	7,C
	JR	Z,nbit$
	LD	A,B
	CPL
	LD	C,A
	CALL	.wrbyte
	DEC	HL
	LD	C,#0x80
	LD	B,C
nbit$:
	LD	A,(.l_d+1)
	LD	D,A
	LD	A,(.dinc1+1)
	ADD	D
	LD	(.l_d+1),A
	LD	A,(.l_d)
	LD	D,A
	LD	A,(.dinc1)
	ADC	D
	LD	(.l_d),A
	POP	DE
	JR	nchg$
ychg$:
	PUSH	DE
	PUSH	BC
	LD	A,B
	CPL
	LD	C,A
	CALL	.wrbyte
	LD	A,(.l_inc)
	OR	A
	JR	Z,ydown$
	INC	HL
	LD	A,L
	AND	#0x0F
	JR	NZ,bound$
	LD	DE,#0x0130
	ADD	HL,DE	;Correct screen address
	JR	bound$
ydown$:
	DEC	HL
	DEC	HL
	DEC	HL
	LD	A,L
	AND	#0x0F
	XOR	#0x0E
	JR	NZ,bound$
	LD	DE,#0xFED0
	ADD	HL,DE	;Correct screen address
bound$:
	LD	A,(.l_d+1)
	LD	D,A
	LD	A,(.dinc2+1)
	ADD	D
	LD	(.l_d+1),A
	LD	A,(.l_d)
	LD	D,A
	LD	A,(.dinc2)
	ADC	D
	LD	(.l_d),A
	POP	BC
	LD	B,C
	POP	DE
nchg$:
	BIT	7,C
	JR	Z,nadj$
	PUSH	DE
	LD	DE,#0x0010
	ADD	HL,DE	;Correct screen address
	POP	DE
	LD	B,C
nadj$:
	LD	A,B
	OR	C
	LD	B,A
	DEC	E
	JP	NZ,xloop$
	LD	A,B
	CPL
	LD	C,A
	JP	.wrbyte

.xonly::
	;; Draw accelerated horizontal line
	.if	0
	;; xxx needed?
	LD	A,(.mod_col)	
	LD	D,A
	.endif

	LD	A,(.delta_x)
	LD	E,A
	INC	E

	LD	A,B	;check X
	AND	#7	;just look at bottom 3 bits
	JR	Z,2$
	PUSH	HL
	ADD	#0x10	;Table of bits is located at 0x0010
	LD	L,A
	LD	H,#0x00
	LD	C,(HL)
	POP	HL
	XOR	A	;Clear A
1$:	RRCA		;Shift data right 1
	OR	C
	DEC	E
	JR	Z,3$
	BIT	0,A
	JR	Z,1$
	JR	3$
2$:
	LD	A,E
	DEC	A
	AND	#0xF8
	JR	Z,4$
	JR	8$
3$:
	LD	B,A
	CPL
	LD	C,A
	PUSH	DE
	CALL	.wrbyte
	LD	DE,#0x0F
	ADD	HL,DE	;Correct screen address
	POP	DE

8$:	LD	A,E
	OR	A
	RET	Z
	AND	#0xF8
	JR	Z,4$

	XOR	A
	LD	C,A
	CPL
	LD	B,A

	PUSH	DE
	CALL	.wrbyte
	LD	DE,#0x0F
	ADD	HL,DE	;Correct screen address
	POP	DE
	LD	A,E
	SUB	#8
	RET	Z
	LD	E,A
	JR	8$

4$:	LD	A,#0x80
5$:	DEC	E
	JR	Z,6$
	SRA	A
	JR	5$
6$:	LD	B,A
	CPL
	LD	C,A
	JP	.wrbyte

	;; Use Delta Y
y1:
	LD	A,C
	SUB	E
	JP	NC,y2$

	LD	A,B
	SUB	D
	JR	Z,y3$
	LD	A,#0x00
	JR	NC,y3$
	LD	A,#0xFF
	JR	y3$

y2$:
	LD	A,C
	SUB	E
	JR	Z,y2a$
	LD	A,#0x00
	JR	NC,y2a$
	LD	A,#0xFF

y2a$:
	LD	B,D
	LD	C,E	;BC holds start X,Y

y3$:
	LD	(.l_inc),A	;Store X increment
	LD	HL,#.y_table
	LD	D,#0x00
	LD	E,C
	ADD	HL,DE
	ADD	HL,DE
	LD	A,(HL+)
	LD	H,(HL)
	LD	L,A

	LD	A,B
	AND	#0xf8
	LD	E,A
	ADD	HL,DE
	ADD	HL,DE

	.if	0
	;; Trashed by later instructions
	LD	A,(.mod_col)
	LD	D,A
	.endif
	
	LD	A,(.delta_y)
	LD	E,A
	INC	E

	LD	A,(.delta_x)
	OR	A
	JP	Z,.yonly

	;;	Got to do it the hard way.

	;	Calculate (2*deltax) -> dinc1

	PUSH	HL
	LD	H,#0x00
	LD	L,A
	ADD	HL,HL
	LD	A,H
	LD	(.dinc1),A
	LD	A,L
	LD	(.dinc1+1),A

	;	Calculate (2*deltax)-deltay -> d


	LD	D,H
	LD	E,L
	LD	A,(.delta_y)
	CPL
	LD	L,A
	LD	H,#0xFF
	INC	HL
dy1$:
	ADD	HL,DE
	LD	A,H
	LD	(.l_d),A
	LD	A,L
	LD	(.l_d+1),A

	;	Calculate (deltax-deltay)*2 -> dinc2

	LD	A,(.delta_y)
	CPL
	LD	L,A
	LD	H,#0xFF
	INC	HL
	LD	A,(.delta_x)
	LD	D,#0x00
	LD	E,A
	ADD	HL,DE
	ADD	HL,HL

	LD	A,H
	LD	(.dinc2),A
	LD	A,L
	LD	(.dinc2+1),A

	POP	HL

	.if	0
	;; xxx Not used?
	LD	A,(.mod_col)
	LD	D,A
	.endif

	LD	A,(.delta_y)
	LD	E,A

	LD	A,B
	AND	#7
	ADD	#0x10	; Table of bits is located at 0x0010
	LD	C,A
	LD	B,#0x00
	LD	A,(BC)	; Get start bit
	LD	B,A
	LD	C,A

yloop$:
	PUSH	DE
	PUSH	BC
	LD	A,B
	CPL
	LD	C,A
	CALL	.wrbyte
	INC	HL
	LD	A,L
	AND	#0x0F
	JR	NZ,nybound$
	LD	DE,#0x0130
	ADD	HL,DE	;Correct screen address
nybound$:
	POP	BC
	LD	A,(.l_d)
	BIT	7,A
	JR	Z,xchg$
	LD	A,(.l_d+1)
	LD	D,A
	LD	A,(.dinc1+1)
	ADD	D
	LD	(.l_d+1),A
	LD	A,(.l_d)
	LD	D,A
	LD	A,(.dinc1)
	ADC	D
	LD	(.l_d),A
	JR	nchgy$
xchg$:
	LD	A,(.l_inc)
	OR	A
	JR	NZ,yright$
	RLC	B
	BIT	0,B
	JR	Z,boundy$
	LD	DE,#0xFFF0
	ADD	HL,DE	;Correct screen address
	JR	boundy$
yright$:
	RRC	B
	BIT	7,B
	JR	Z,boundy$
	LD	DE,#0x0010
	ADD	HL,DE	;Correct screen address
boundy$:
	LD	A,(.l_d+1)
	LD	D,A
	LD	A,(.dinc2+1)
	ADD	D
	LD	(.l_d+1),A
	LD	A,(.l_d)
	LD	D,A
	LD	A,(.dinc2)
	ADC	D
	LD	(.l_d),A
nchgy$:
	POP	DE
	DEC	E
	JR	NZ,yloop$
	LD	A,B
	CPL
	LD	C,A
	JP	.wrbyte

.yonly::
	;; Draw accelerated vertical line
	LD	A,B	;check X
	AND	#7	;just look at bottom 3 bits
	PUSH	HL
	ADD	#0x10	;Table of bits is located at 0x0010
	LD	L,A
	LD	H,#0x00
	LD	A,(HL)	;Get mask bit
	POP	HL
	LD	B,A
	CPL
	LD	C,A

1$:	PUSH	DE
	CALL	.wrbyte
	INC	HL	;Correct screen address
	LD	A,L
	AND	#0x0F
	JR	NZ,2$
	LD	DE,#0x0130
	ADD	HL,DE
2$:	POP	DE
	DEC	E
	RET	Z
	JR	1$

	;; Draw a point at (B,C) with mode and color D
.plot::

	LD	HL,#.y_table
	LD	D,#0x00
	LD	E,C
	ADD	HL,DE
	ADD	HL,DE
	LD	A,(HL+)
	LD	H,(HL)
	LD	L,A

	LD	A,B
	AND	#0xf8
	LD	E,A
	ADD	HL,DE
	ADD	HL,DE

	LD	A,B

	AND     #7
	ADD     #0x10		; Table of bits is located at 0x0010
	LD      C,A
	LD      B,#0x00
	LD      A,(BC)
	LD      B,A
	CPL
	LD      C,A

.wrbyte::
	.if	0
	LD	A,(.mod_col)	; Restore color and mode
	LD	D,A

	BIT	5,D
	JR	NZ,10$
	BIT	6,D
	JR	NZ,20$
	BIT	7,D
	JR	NZ,30$
	.else
	LD	A,(.fg_colour)
	LD	D,A
	LD	A,(.draw_mode)
	CP	#.M_OR
	JR	Z,10$
	CP	#.M_XOR
	JR	Z,20$
	CP	#.M_AND
	JR	Z,30$		
	.endif

	; Fall through to SOLID by default
1$:
	;; Solid
	LD	E,B
	.if	0
	BIT	2,D
	.else
	BIT	0,D
	.endif
	JR	NZ,2$
	PUSH	BC
	LD	B,#0x00
2$:
	.if	0
	BIT	3,D
	.else
	BIT	1,D
	.endif
	JR	NZ,3$
	LD	E,#0x00
3$:
	LDH	A,(.STAT)
	BIT	1,A
	JR	NZ,3$

	LD	A,(HL)
	AND	C
	OR	B
	LD	(HL+),A

	LD	A,(HL)
	AND	C
	OR	E
	LD	(HL),A
	LD	A,B
	OR	A
	RET	NZ
	POP	BC
	RET

10$:
	;; Or
	LD      C,B
	.if	0
	BIT     2,D
	.else
	BIT	0,D
	.endif
	JR      NZ,11$
	LD      B,#0x00
11$:
	.if	0
	BIT     3,D
	.else
	BIT	1,D
	.endif
	JR      NZ,12$
	LD      C,#0x00
12$:
	LDH     A,(.STAT)
	BIT     1,A
	JR      NZ,12$

	LD      A,(HL)
	OR      B
	LD      (HL+),A

	LD      A,(HL)
	OR      C
	LD      (HL),A
	RET

20$:
	;; Xor
	LD      C,B
	.if	0
	BIT     2,D
	.else
	BIT	0,D
	.endif
	JR      NZ,21$
	LD      B,#0x00
21$:
	.if	0
	BIT     3,D
	.else
	BIT	1,D
	.endif
	JR      NZ,22$
	LD      C,#0x00
22$:
	LDH     A,(.STAT)
	BIT     1,A
	JR      NZ,22$

	LD      A,(HL)
	XOR     B
	LD      (HL+),A

	LD      A,(HL)
	XOR     C
	LD      (HL),A
	RET

30$:
	;; And
	LD      B,C
	.if	0
	BIT     2,D
	.else
	BIT	0,D
	.endif
	JR      Z,31$
	LD      B,#0xFF
31$:
	.if	0
	BIT     3,D
	.else
	BIT	1,D
	.endif
	JR      Z,32$
	LD      C,#0xFF
32$:
	LDH     A,(.STAT)
	BIT     1,A
	JR      NZ,32$

	LD      A,(HL)
	AND     B
	LD      (HL+),A

	LD      A,(HL)
	AND     C
	LD      (HL),A
	RET

	;; Get color of pixel at point (B,C) returns in A
.getpix::
	LD	HL,#.y_table
	LD	D,#0x00
	LD	E,C
	ADD	HL,DE
	ADD	HL,DE
	LD	A,(HL+)
	LD	H,(HL)
	LD	L,A

	LD	A,B
	AND	#0xf8
	LD	E,A
	ADD	HL,DE
	ADD	HL,DE

	LD	A,B

	AND     #7
	ADD     #0x10		; Table of bits is located at 0x0010
	LD      C,A
	LD      B,#0x00
	LD      A,(BC)
	LD      C,A

gp$:
	LDH	A,(.STAT)
	BIT	1,A
	JR	NZ,gp$

	LD	A,(HL+)
	LD	D,A
	LD	A,(HL+)
	LD	E,A
	LD	B,#0
	LD	A,D
	AND	C
	JR	Z,npix$
	SET	0,B
npix$:	LD	A,E
	AND	C
	JR	Z,end$
	SET	1,B
end$:	LD	E,B
	RET

	;; Write character C
.wrtchr::
	LD	HL,#.y_table
	LD	D,#0x00
	LD	A,(.ty)
	RLCA
	RLCA
	RLCA
	LD	E,A
	ADD	HL,DE
	ADD	HL,DE
	LD	B,(HL)
	INC	HL
	LD	H,(HL)
	LD	L,B

	LD	A,(.tx)
	RLCA
	RLCA
	RLCA
	LD	E,A
	ADD	HL,DE
	ADD	HL,DE

	LD	A,C
	LD	B,H
	LD	C,L

	LD	H,D
	LD	L,A
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL

	.if	0
	LD	DE,#.tp1
	.else
	.globl	_font_ibm_fixed_tiles

	LD	DE,#_font_ibm_fixed_tiles
	.endif
	
	ADD	HL,DE

	LD	D,H
	LD	E,L
	LD	H,B
	LD	L,C

	.if	0
	LD	A,(.mod_col)
	LD	C,A
	.else
	LD	A,(.fg_colour)
	LD	C,A
	.endif
chrloop$:
	LD	A,(DE)
	INC	DE
	PUSH	DE

	.if	1
	PUSH	HL
	LD	HL,#.bg_colour
	LD	L,(HL)
	.endif

	LD	B,A
	XOR	A
	.if	0
	BIT	0,C
	.else
	BIT	0,L
	.endif
	JR	Z,a0$
	CPL
a0$:	OR	B
	.if	0
	BIT	2,C
	.else
	BIT	0,C
	.endif
	JR	NZ,a1$
	XOR	B
a1$:	LD	D,A
	XOR	A
	.if	0
	BIT	1,C
	.else
	BIT	1,L
	.endif
	JR	Z,b0$
	CPL
b0$:	OR	B
	.if	0
	BIT	3,C
	.else
	BIT	1,C
	.endif
	JR	NZ,b1$
	XOR	B
b1$:	
	LD	E,A
	.if	1
	POP	HL
	.endif
chrwait$:
	LDH	A,(.STAT)
	BIT	1,A
	JR	NZ,chrwait$

	LD	A,D
	LD	(HL+),A
	LD	A,E
	LD	(HL+),A
	POP	DE
	LD	A,L
	AND	#0x0F
	JR	NZ,chrloop$
	RET

	.area	_CODE
_gotogxy::			; Banked
	LDA	HL,.BANKOV(SP)	; Skip return address
	LD	A,(HL+)		; A = x
	LD	(.tx),A
	LD	A,(HL+)		; A = y
	LD	(.ty),A

	RET

_wrtchr::			; Banked
	PUSH    BC

	LD	A,(.mode)
	CP	#.G_MODE
	CALL	NZ,.gmode

	LDA	HL,.BANKOV+2(SP)	; Skip return address and registers
	LD	A,(HL)
	LD	C,A	; C = Char to print

	CALL	.wrtchr
	CALL	.adv_gcurs

	POP	BC
	RET

_getpix::			; Banked
	PUSH    BC

	LDA	HL,.BANKOV+2(SP)	; Skip return address and registers
	LD	A,(HL+)	; B = x
	LD	B,A
	LD	A,(HL+)	; C = y
	LD	C,A

	CALL	.getpix

	POP	BC
	RET

_color::			; Banked
	LDA	HL,.BANKOV(SP)	; Skip return address and registers
	LD	A,(HL+)	; A = Foreground
	LD	(.fg_colour),a
	LD	A,(HL+)
	LD	(.bg_colour),a
	LD	A,(HL)
	LD	(.draw_mode),a
	RET

_circle::			; Banked
	PUSH    BC

	LD	A,(.mode)
	CP	#.G_MODE
	CALL	NZ,.gmode

	LDA	HL,.BANKOV+2(SP)	; Skip return address and registers
	LD	A,(HL+)	; B = x
	LD	B,A
	LD	A,(HL+)	; C = y
	LD	C,A
	LD	A,(HL+)	; D = Radius
	LD	D,A
	LD	A,(HL)
	LD	(.style),A

	CALL	.circle

	POP	BC
	RET

_box::				; Banked
	PUSH    BC

	LD      A,(.mode)
	CP      #.G_MODE
	CALL	NZ,.gmode

	LDA	HL,.BANKOV+2(SP)	; Skip return address and registers
	LD	A,(HL+)	; B = x1
	LD	(.x_s),A
	LD	A,(HL+)	; C = y1
	LD	(.y_s),A
	LD	A,(HL+)	; D = x2
	LD	(.x_s+1),A
	LD	A,(HL+)	; E = y2
	LD	(.y_s+1),A
	LD	A,(HL)
	LD	(.style),A
	CALL	.box
	POP	BC
	RET

_line::				; Banked
	PUSH    BC

	LD      A,(.mode)
	CP      #.G_MODE
	CALL	NZ,.gmode

	LDA	HL,.BANKOV+2(SP)	; Skip return address and registers
	LD	A,(HL+)	; B = x1
	LD	B,A
	LD	A,(HL+)	; C = y1
	LD	C,A
	LD	A,(HL+)	; D = x2
	LD	D,A
	LD	A,(HL+)	; E = y2
	LD	E,A

	CALL	.line

	POP     BC
	RET

_plot_point::			; Banked
	PUSH    BC

	LD	A,(.mode)
	CP	#.G_MODE
	CALL	NZ,.gmode

	LDA	HL,.BANKOV+2(SP)	; Skip return address and registers
	LD	A,(HL+)	; B = x
	LD	B,A
	LD	A,(HL+)	; C = y
	LD	C,A

	CALL	.plot

	POP	BC
	RET

	;; Old, compatible version of plot()
_plot::				; Banked
	PUSH    BC

	LD	A,(.mode)
	CP	#.G_MODE
	CALL	NZ,.gmode

	LDA	HL,.BANKOV+2(SP)	; Skip return address and registers
	LD	A,(HL+)		; B = x
	LD	B,A
	LD	A,(HL+)		; C = y
	LD	C,A
	LD	A,(HL+)		; colour
	LD	(.fg_colour),A
	LD	A,(HL+)		; mode
	LD	(.draw_mode),A
	
	CALL	.plot

	POP	BC
	RET

	.area	_BASE
_switch_data::			; Non Banked as pointer
	PUSH    BC

	LD	A,(.mode)
	CP	#.G_MODE
	CALL	NZ,.gmode

	LDA	HL,4(SP)	; Skip return address and registers
	LD	A,(HL+)	; B = x
	LD	B,A
	LD	A,(HL+)	; C = y
	LD	C,A
	LD	A,(HL+)	; DE = src
	LD	E,A
	LD	A,(HL+)
	LD	D,A
	LD	A,(HL+)	; HL = dst
	LD	H,(HL)
	LD	L,A

	CALL    .switch_data

	POP     BC
	RET


_draw_image::			; Non banked as pointer
	PUSH    BC

	LD	A,(.mode)
	CP	#.G_MODE
	CALL	NZ,.gmode

	LDA	HL,4(SP)	; Skip return address and registers
	LD	A,(HL+)	; HL = data
	LD	C,A
	LD	B,(HL)

	CALL	.draw_image

	POP	BC
	RET

	.area	_BASE
.y_table::
	.word   0x8100,0x8102,0x8104,0x8106,0x8108,0x810A,0x810C,0x810E
	.word   0x8240,0x8242,0x8244,0x8246,0x8248,0x824A,0x824C,0x824E
	.word   0x8380,0x8382,0x8384,0x8386,0x8388,0x838A,0x838C,0x838E
	.word   0x84C0,0x84C2,0x84C4,0x84C6,0x84C8,0x84CA,0x84CC,0x84CE
	.word   0x8600,0x8602,0x8604,0x8606,0x8608,0x860A,0x860C,0x860E
	.word   0x8740,0x8742,0x8744,0x8746,0x8748,0x874A,0x874C,0x874E
	.word   0x8880,0x8882,0x8884,0x8886,0x8888,0x888A,0x888C,0x888E
	.word   0x89C0,0x89C2,0x89C4,0x89C6,0x89C8,0x89CA,0x89CC,0x89CE
	.word   0x8B00,0x8B02,0x8B04,0x8B06,0x8B08,0x8B0A,0x8B0C,0x8B0E
	.word   0x8C40,0x8C42,0x8C44,0x8C46,0x8C48,0x8C4A,0x8C4C,0x8C4E
	.word   0x8D80,0x8D82,0x8D84,0x8D86,0x8D88,0x8D8A,0x8D8C,0x8D8E
	.word   0x8EC0,0x8EC2,0x8EC4,0x8EC6,0x8EC8,0x8ECA,0x8ECC,0x8ECE
	.word   0x9000,0x9002,0x9004,0x9006,0x9008,0x900A,0x900C,0x900E
	.word   0x9140,0x9142,0x9144,0x9146,0x9148,0x914A,0x914C,0x914E
	.word   0x9280,0x9282,0x9284,0x9286,0x9288,0x928A,0x928C,0x928E
	.word   0x93C0,0x93C2,0x93C4,0x93C6,0x93C8,0x93CA,0x93CC,0x93CE
	.word   0x9500,0x9502,0x9504,0x9506,0x9508,0x950A,0x950C,0x950E
	.word   0x9640,0x9642,0x9644,0x9646,0x9648,0x964A,0x964C,0x964E


================================================
FILE: libc/f_ibm_sh.s
================================================
; ibm_fixed.ms - fixed width IBM font
	;; BANKED:	checked, imperfect
	.area	_BASE

	; 898 bytes giving ' '-'0'-'@'-'A'-'Z'-'???'-'a'-'z'-127
_font_ibm::
	.byte	1+4		; 128 character encoding
	.byte	128-32		; Tiles required

	.byte	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0		; All map to space
	.byte	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	.byte	0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15	; 0x20
	.byte	16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
	.byte	32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47 ; 0x40
	.byte	48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63
	.byte	64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79 ; 0x60
	.byte	80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95
	
	.byte	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
	.byte	0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x00
	.byte	0x66,0x66,0x44,0x00,0x00,0x00,0x00,0x00
	.byte	0x00,0x24,0x7E,0x24,0x24,0x7E,0x24,0x00
	.byte	0x14,0x3E,0x55,0x3C,0x1E,0x55,0x3E,0x14
	.byte	0x62,0x66,0x0C,0x18,0x30,0x66,0x46,0x00
	.byte	0x78,0xCC,0x61,0xCE,0xCC,0xCC,0x78,0x00
	.byte	0x18,0x18,0x10,0x00,0x00,0x00,0x00,0x00
	.byte	0x04,0x08,0x18,0x18,0x18,0x18,0x08,0x04
	.byte	0x20,0x10,0x18,0x18,0x18,0x18,0x10,0x20
	.byte	0x00,0x54,0x38,0xFE,0x38,0x54,0x00,0x00
	.byte	0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00
	.byte	0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x20
	.byte	0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x00
	.byte	0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00
	.byte	0x03,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00
	.byte	0x3C,0x66,0x6E,0x76,0x66,0x66,0x3C,0x00
	.byte	0x18,0x38,0x18,0x18,0x18,0x18,0x18,0x00
	.byte	0x3C,0x66,0x0E,0x1C,0x38,0x70,0x7E,0x00
	.byte	0x7E,0x0C,0x18,0x3C,0x06,0x46,0x3C,0x00
	.byte	0x0C,0x1C,0x2C,0x4C,0x7E,0x0C,0x0C,0x00
	.byte	0x7E,0x60,0x7C,0x06,0x06,0x46,0x3C,0x00
	.byte	0x1C,0x20,0x60,0x7C,0x66,0x66,0x3C,0x00
	.byte	0x7E,0x06,0x0E,0x1C,0x18,0x18,0x18,0x00
	.byte	0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00
	.byte	0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00
	.byte	0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00
	.byte	0x00,0x18,0x18,0x00,0x18,0x18,0x10,0x00
	.byte	0x06,0x0C,0x18,0x30,0x18,0x0C,0x06,0x00
	.byte	0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00
	.byte	0x60,0x30,0x18,0x0C,0x18,0x30,0x60,0x00
	.byte	0x3C,0x46,0x06,0x0C,0x18,0x18,0x00,0x18
	.byte	0x3C,0x66,0x6E,0x6A,0x6E,0x60,0x3C,0x00
	.byte	0x3C,0x66,0x66,0x7E,0x66,0x66,0x66,0x00
	.byte	0x7C,0x66,0x66,0x7C,0x66,0x66,0x7C,0x00
	.byte	0x3C,0x62,0x60,0x60,0x60,0x62,0x3C,0x00
	.byte	0x7C,0x66,0x66,0x66,0x66,0x66,0x7C,0x00
	.byte	0x7E,0x60,0x60,0x7C,0x60,0x60,0x7E,0x00
	.byte	0x7E,0x60,0x60,0x7C,0x60,0x60,0x60,0x00
	.byte	0x3C,0x62,0x60,0x6E,0x66,0x66,0x3E,0x00
	.byte	0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00
	.byte	0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00
	.byte	0x06,0x06,0x06,0x06,0x06,0x46,0x3C,0x00
	.byte	0x66,0x6C,0x78,0x70,0x78,0x6C,0x66,0x00
	.byte	0x60,0x60,0x60,0x60,0x60,0x60,0x7C,0x00
	.byte	0xFC,0xD6,0xD6,0xD6,0xD6,0xC6,0xC6,0x00
	.byte	0x62,0x72,0x7A,0x5E,0x4E,0x46,0x42,0x00
	.byte	0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x00
	.byte	0x7C,0x66,0x66,0x7C,0x60,0x60,0x60,0x00
	.byte	0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x06
	.byte	0x7C,0x66,0x66,0x7C,0x66,0x66,0x66,0x00
	.byte	0x3C,0x62,0x70,0x3C,0x0E,0x46,0x3C,0x00
	.byte	0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00
	.byte	0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x00
	.byte	0x66,0x66,0x66,0x66,0x66,0x64,0x78,0x00
	.byte	0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFC,0x00
	.byte	0x66,0x66,0x66,0x3C,0x66,0x66,0x66,0x00
	.byte	0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00
	.byte	0x7E,0x0E,0x1C,0x38,0x70,0x60,0x7E,0x00
	.byte	0x1E,0x18,0x18,0x18,0x18,0x18,0x1E,0x00
	.byte	0x40,0x60,0x30,0x18,0x0C,0x06,0x02,0x00
	.byte	0x78,0x18,0x18,0x18,0x18,0x18,0x78,0x00
	.byte	0x10,0x38,0x6C,0x00,0x00,0x00,0x00,0x00
	.byte	0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00
	.byte	0x00,0xC0,0xC0,0x60,0x00,0x00,0x00,0x00
	.byte	0x00,0x3C,0x46,0x3E,0x66,0x66,0x3E,0x00
	.byte	0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x00
	.byte	0x00,0x3C,0x62,0x60,0x60,0x62,0x3C,0x00
	.byte	0x06,0x3E,0x66,0x66,0x66,0x66,0x3E,0x00
	.byte	0x00,0x3C,0x66,0x7E,0x60,0x62,0x3C,0x00
	.byte	0x1E,0x30,0x7C,0x30,0x30,0x30,0x30,0x00
	.byte	0x00,0x3E,0x66,0x66,0x66,0x3E,0x46,0x3C
	.byte	0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x00
	.byte	0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00
	.byte	0x00,0x08,0x18,0x18,0x18,0x18,0x58,0x30
	.byte	0x60,0x64,0x68,0x70,0x78,0x6C,0x66,0x00
	.byte	0x18,0x18,0x18,0x18,0x18,0x18,0x0C,0x00
	.byte	0x00,0xFC,0xD6,0xD6,0xD6,0xD6,0xC6,0x00
	.byte	0x00,0x7C,0x66,0x66,0x66,0x66,0x66,0x00
	.byte	0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x00
	.byte	0x00,0x7C,0x66,0x66,0x66,0x7C,0x60,0x60
	.byte	0x00,0x3E,0x66,0x66,0x66,0x66,0x3E,0x06
	.byte	0x00,0x6C,0x70,0x60,0x60,0x60,0x60,0x00
	.byte	0x00,0x3C,0x72,0x38,0x1C,0x4E,0x3C,0x00
	.byte	0x18,0x3C,0x18,0x18,0x18,0x18,0x0C,0x00
	.byte	0x00,0x66,0x66,0x66,0x66,0x66,0x3E,0x00
	.byte	0x00,0x66,0x66,0x66,0x66,0x64,0x78,0x00
	.byte	0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFC,0x00
	.byte	0x00,0x66,0x66,0x3C,0x66,0x66,0x66,0x00
	.byte	0x00,0x66,0x66,0x66,0x26,0x1E,0x46,0x3C
	.byte	0x00,0x7E,0x0E,0x1C,0x38,0x70,0x7E,0x00
	.byte	0x0E,0x18,0x18,0x30,0x18,0x18,0x0E,0x00
	.byte	0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18
	.byte	0x70,0x18,0x18,0x0C,0x18,0x18,0x70,0x00
	.byte	0x00,0x60,0xF2,0x9E,0x0C,0x00,0x00,0x00
	.byte	0x10,0x10,0x28,0x28,0x44,0x44,0x82,0xFE


================================================
FILE: libc/f_italic.s
================================================
; font: italic
	;; BANKED:	checked,imperfect
	.area	_BASE
_font_italic::
	.db	1+4	; 128 char encoding, compressed
	.db	93	; Number of tiles

; Encoding table

	.db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
	.db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
	.db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
	.db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
	.db 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07
	.db 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F
	.db 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17
	.db 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F
	.db 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27
	.db 0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F
	.db 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37
	.db 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x00
	.db 0x00,0x3F,0x40,0x41,0x42,0x43,0x44,0x45
	.db 0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D
	.db 0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,0x55
	.db 0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x00
; Tile data
; Default character (space)
	.db	0b00000000
	.db	0b00000000
	.db	0b00000000
	.db	0b00000000
	.db	0b00000000
	.db	0b00000000
	.db	0b00000000
	.db	0b00000000

; Character: ! (21)
	.db	0b00000000	;         
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b00000000	;         
	.db	0b00100000	;   o     

; Character: " (22)
	.db	0b00000000	;         
	.db	0b00100100	;   o  o  
	.db	0b00100100	;   o  o  
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         

; Character: # (23)
	.db	0b00000000	;         
	.db	0b00100100	;   o  o  
	.db	0b01111110	;  oooooo 
	.db	0b00100100	;   o  o  
	.db	0b00100100	;   o  o  
	.db	0b01111110	;  oooooo 
	.db	0b00100100	;   o  o  
	.db	0b00000000	;         

; Character: $ (24)
	.db	0b00000000	;         
	.db	0b00001000	;     o   
	.db	0b00111110	;   ooooo 
	.db	0b00101000	;   o o   
	.db	0b00111110	;   ooooo 
	.db	0b00001010	;     o o 
	.db	0b00111110	;   ooooo 
	.db	0b00001000	;     o   

; Character: % (25)
	.db	0b00000000	;         
	.db	0b01100010	;  oo   o 
	.db	0b01100100	;  oo  o  
	.db	0b00001000	;     o   
	.db	0b00010000	;    o    
	.db	0b00100110	;   o  oo 
	.db	0b01000110	;  o   oo 
	.db	0b00000000	;         

; Character: & (26)
	.db	0b00000000	;         
	.db	0b00010000	;    o    
	.db	0b00101000	;   o o   
	.db	0b00010000	;    o    
	.db	0b00101010	;   o o o 
	.db	0b01000100	;  o   o  
	.db	0b00111010	;   ooo o 
	.db	0b00000000	;         

; Character: ' (27)
	.db	0b00000000	;         
	.db	0b00001000	;     o   
	.db	0b00010000	;    o    
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         

; Character: ( (28)
	.db	0b00000000	;         
	.db	0b00000100	;      o  
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00000100	;      o  
	.db	0b00000000	;         

; Character: ) (29)
	.db	0b00000000	;         
	.db	0b00100000	;   o     
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b00100000	;   o     
	.db	0b00000000	;         

; Character: * (2A)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00100100	;   o  o  
	.db	0b00011000	;    oo   
	.db	0b01111110	;  oooooo 
	.db	0b00011000	;    oo   
	.db	0b00100100	;   o  o  
	.db	0b00000000	;         

; Character: + (2B)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00111110	;   ooooo 
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00000000	;         

; Character: , (2C)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00010000	;    o    

; Character: - (2D)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00111110	;   ooooo 
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         

; Character: . (2E)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00011000	;    oo   
	.db	0b00011000	;    oo   
	.db	0b00000000	;         

; Character: / (2F)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000010	;       o 
	.db	0b00000100	;      o  
	.db	0b00001000	;     o   
	.db	0b00010000	;    o    
	.db	0b00100000	;   o     
	.db	0b00000000	;         

; Character: 0 (30)
	.db	0b00000000	;         
	.db	0b00011100	;    ooo  
	.db	0b00100110	;   o  oo 
	.db	0b01001010	;  o  o o 
	.db	0b01010100	;  o o o  
	.db	0b10100100	; o o  o  
	.db	0b11001000	; oo  o   
	.db	0b01110000	;  ooo    

; Character: 1 (31)
	.db	0b00000000	;         
	.db	0b00011000	;    oo   
	.db	0b00101000	;   o o   
	.db	0b00001000	;     o   
	.db	0b00010000	;    o    
	.db	0b00100000	;   o     
	.db	0b00100000	;   o     
	.db	0b11111000	; ooooo   

; Character: 2 (32)
	.db	0b00000000	;         
	.db	0b00111100	;   oooo  
	.db	0b01000010	;  o    o 
	.db	0b00000100	;      o  
	.db	0b00011000	;    oo   
	.db	0b01100000	;  oo     
	.db	0b10000000	; o       
	.db	0b11111100	; oooooo  

; Character: 3 (33)
	.db	0b00000000	;         
	.db	0b00111100	;   oooo  
	.db	0b01000010	;  o    o 
	.db	0b00000010	;       o 
	.db	0b00001100	;     oo  
	.db	0b00000010	;       o 
	.db	0b10000100	; o    o  
	.db	0b01111000	;  oooo   

; Character: 4 (34)
	.db	0b00000000	;         
	.db	0b00001100	;     oo  
	.db	0b00110100	;   oo o  
	.db	0b01000100	;  o   o  
	.db	0b10001000	; o   o   
	.db	0b11111110	; ooooooo 
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    

; Character: 5 (35)
	.db	0b00000000	;         
	.db	0b00111110	;   ooooo 
	.db	0b00100000	;   o     
	.db	0b01000000	;  o      
	.db	0b01111000	;  oooo   
	.db	0b00000100	;      o  
	.db	0b10000100	; o    o  
	.db	0b01111000	;  oooo   

; Character: 6 (36)
	.db	0b00000000	;         
	.db	0b00011100	;    ooo  
	.db	0b00100010	;   o   o 
	.db	0b01000000	;  o      
	.db	0b01111000	;  oooo   
	.db	0b10000100	; o    o  
	.db	0b10000100	; o    o  
	.db	0b01111000	;  oooo   

; Character: 7 (37)
	.db	0b00000000	;         
	.db	0b00111110	;   ooooo 
	.db	0b00000010	;       o 
	.db	0b00000100	;      o  
	.db	0b00001000	;     o   
	.db	0b00010000	;    o    
	.db	0b00100000	;   o     
	.db	0b00100000	;   o     

; Character: 8 (38)
	.db	0b00000000	;         
	.db	0b00111100	;   oooo  
	.db	0b01000010	;  o    o 
	.db	0b00111100	;   oooo  
	.db	0b01000010	;  o    o 
	.db	0b10000100	; o    o  
	.db	0b10000100	; o    o  
	.db	0b01111000	;  oooo   

; Character: 9 (39)
	.db	0b00000000	;         
	.db	0b00111100	;   oooo  
	.db	0b01000010	;  o    o 
	.db	0b01000010	;  o    o 
	.db	0b00111100	;   oooo  
	.db	0b00000100	;      o  
	.db	0b00001000	;     o   
	.db	0b11110000	; oooo    

; Character: : (3A)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00001000	;     o   
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00010000	;    o    
	.db	0b00000000	;         

; Character: ; (3B)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00010000	;    o    
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b00100000	;   o     

; Character: < (3C)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000100	;      o  
	.db	0b00001000	;     o   
	.db	0b00010000	;    o    
	.db	0b00001000	;     o   
	.db	0b00000100	;      o  
	.db	0b00000000	;         

; Character: = (3D)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00111110	;   ooooo 
	.db	0b00000000	;         
	.db	0b01111100	;  ooooo  
	.db	0b00000000	;         
	.db	0b00000000	;         

; Character: > (3E)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00010000	;    o    
	.db	0b00001000	;     o   
	.db	0b00000100	;      o  
	.db	0b00001000	;     o   
	.db	0b00010000	;    o    
	.db	0b00000000	;         

; Character: ? (3F)
	.db	0b00000000	;         
	.db	0b00111100	;   oooo  
	.db	0b01000010	;  o    o 
	.db	0b00000010	;       o 
	.db	0b00001100	;     oo  
	.db	0b00010000	;    o    
	.db	0b00000000	;         
	.db	0b00110000	;   oo    

; Character: @ (40)
	.db	0b00000000	;         
	.db	0b00111100	;   oooo  
	.db	0b01001010	;  o  o o 
	.db	0b01010110	;  o o oo 
	.db	0b01011110	;  o oooo 
	.db	0b01000000	;  o      
	.db	0b00111100	;   oooo  
	.db	0b00000000	;         

; Character: A (41)
	.db	0b00000000	;         
	.db	0b00011100	;    ooo  
	.db	0b00100010	;   o   o 
	.db	0b00100010	;   o   o 
	.db	0b01111100	;  ooooo  
	.db	0b01000100	;  o   o  
	.db	0b10001000	; o   o   
	.db	0b10001000	; o   o   

; Character: B (42)
	.db	0b00000000	;         
	.db	0b00111100	;   oooo  
	.db	0b00100010	;   o   o 
	.db	0b00111100	;   oooo  
	.db	0b01000010	;  o    o 
	.db	0b01000010	;  o    o 
	.db	0b10000100	; o    o  
	.db	0b11111000	; ooooo   

; Character: C (43)
	.db	0b00000000	;         
	.db	0b00011100	;    ooo  
	.db	0b00100010	;   o   o 
	.db	0b01000000	;  o      
	.db	0b01000000	;  o      
	.db	0b10000000	; o       
	.db	0b10000100	; o    o  
	.db	0b01111000	;  oooo   

; Character: D (44)
	.db	0b00000000	;         
	.db	0b00111000	;   ooo   
	.db	0b00100100	;   o  o  
	.db	0b00100010	;   o   o 
	.db	0b01000010	;  o    o 
	.db	0b01000100	;  o   o  
	.db	0b10001000	; o   o   
	.db	0b11110000	; oooo    

; Character: E (45)
	.db	0b00000000	;         
	.db	0b00111110	;   ooooo 
	.db	0b00100000	;   o     
	.db	0b01000000	;  o      
	.db	0b01111000	;  oooo   
	.db	0b01000000	;  o      
	.db	0b10000000	; o       
	.db	0b11111000	; ooooo   

; Character: F (46)
	.db	0b00000000	;         
	.db	0b00111110	;   ooooo 
	.db	0b00100000	;   o     
	.db	0b01000000	;  o      
	.db	0b01111000	;  oooo   
	.db	0b01000000	;  o      
	.db	0b10000000	; o       
	.db	0b10000000	; o       

; Character: G (47)
	.db	0b00000000	;         
	.db	0b00011100	;    ooo  
	.db	0b00100010	;   o   o 
	.db	0b01000000	;  o      
	.db	0b01000000	;  o      
	.db	0b10001110	; o   ooo 
	.db	0b10000100	; o    o  
	.db	0b01111000	;  oooo   

; Character: H (48)
	.db	0b00000000	;         
	.db	0b00100010	;   o   o 
	.db	0b00100010	;   o   o 
	.db	0b01000100	;  o   o  
	.db	0b01111100	;  ooooo  
	.db	0b01000100	;  o   o  
	.db	0b10001000	; o   o   
	.db	0b10001000	; o   o   

; Character: I (49)
	.db	0b00000000	;         
	.db	0b00111110	;   ooooo 
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00010000	;    o    
	.db	0b00100000	;   o     
	.db	0b00100000	;   o     
	.db	0b11111000	; ooooo   

; Character: J (4A)
	.db	0b00000000	;         
	.db	0b00000010	;       o 
	.db	0b00000010	;       o 
	.db	0b00000100	;      o  
	.db	0b00000100	;      o  
	.db	0b10001000	; o   o   
	.db	0b10001000	; o   o   
	.db	0b01110000	;  ooo    

; Character: K (4B)
	.db	0b00000000	;         
	.db	0b00100010	;   o   o 
	.db	0b00100100	;   o  o  
	.db	0b01001000	;  o  o   
	.db	0b01110000	;  ooo    
	.db	0b01001000	;  o  o   
	.db	0b10001000	; o   o   
	.db	0b10000100	; o    o  

; Character: L (4C)
	.db	0b00000000	;         
	.db	0b00100000	;   o     
	.db	0b00100000	;   o     
	.db	0b01000000	;  o      
	.db	0b01000000	;  o      
	.db	0b01000000	;  o      
	.db	0b10000000	; o       
	.db	0b11111100	; oooooo  

; Character: M (4D)
	.db	0b00000000	;         
	.db	0b00110110	;   oo oo 
	.db	0b00101010	;   o o o 
	.db	0b01010100	;  o o o  
	.db	0b01010100	;  o o o  
	.db	0b01000100	;  o   o  
	.db	0b10001000	; o   o   
	.db	0b10001000	; o   o   

; Character: N (4E)
	.db	0b00000000	;         
	.db	0b00100010	;   o   o 
	.db	0b00110010	;   oo  o 
	.db	0b01010100	;  o o o  
	.db	0b01010100	;  o o o  
	.db	0b01010100	;  o o o  
	.db	0b10011000	; o  oo   
	.db	0b10001000	; o   o   

; Character: O (4F)
	.db	0b00000000	;         
	.db	0b00011100	;    ooo  
	.db	0b00100010	;   o   o 
	.db	0b01000010	;  o    o 
	.db	0b01000100	;  o   o  
	.db	0b10000100	; o    o  
	.db	0b10001000	; o   o   
	.db	0b01110000	;  ooo    

; Character: P (50)
	.db	0b00000000	;         
	.db	0b00111100	;   oooo  
	.db	0b00100010	;   o   o 
	.db	0b01000010	;  o    o 
	.db	0b01111100	;  ooooo  
	.db	0b01000000	;  o      
	.db	0b10000000	; o       
	.db	0b10000000	; o       

; Character: Q (51)
	.db	0b00000000	;         
	.db	0b00011100	;    ooo  
	.db	0b00100010	;   o   o 
	.db	0b01000010	;  o    o 
	.db	0b01000100	;  o   o  
	.db	0b10010100	; o  o o  
	.db	0b10001000	; o   o   
	.db	0b01110100	;  ooo o  

; Character: R (52)
	.db	0b00000000	;         
	.db	0b00111100	;   oooo  
	.db	0b00100010	;   o   o 
	.db	0b01000010	;  o    o 
	.db	0b01111100	;  ooooo  
	.db	0b01001000	;  o  o   
	.db	0b10000100	; o    o  
	.db	0b10000100	; o    o  

; Character: S (53)
	.db	0b00000000	;         
	.db	0b00011110	;    oooo 
	.db	0b00100000	;   o     
	.db	0b00100000	;   o     
	.db	0b00011000	;    oo   
	.db	0b00000100	;      o  
	.db	0b10000100	; o    o  
	.db	0b01111000	;  oooo   

; Character: T (54)
	.db	0b00000000	;         
	.db	0b11111110	; ooooooo 
	.db	0b00010000	;    o    
	.db	0b00100000	;   o     
	.db	0b00100000	;   o     
	.db	0b00100000	;   o     
	.db	0b01000000	;  o      
	.db	0b01000000	;  o      

; Character: U (55)
	.db	0b00000000	;         
	.db	0b00100010	;   o   o 
	.db	0b00100010	;   o   o 
	.db	0b01000100	;  o   o  
	.db	0b01000100	;  o   o  
	.db	0b10001000	; o   o   
	.db	0b10001000	; o   o   
	.db	0b01110000	;  ooo    

; Character: V (56)
	.db	0b00000000	;         
	.db	0b01000010	;  o    o 
	.db	0b01000010	;  o    o 
	.db	0b01000100	;  o   o  
	.db	0b01000100	;  o   o  
	.db	0b10001000	; o   o   
	.db	0b10010000	; o  o    
	.db	0b11100000	; ooo     

; Character: W (57)
	.db	0b00000000	;         
	.db	0b00100010	;   o   o 
	.db	0b00100010	;   o   o 
	.db	0b01000100	;  o   o  
	.db	0b01010100	;  o o o  
	.db	0b10101000	; o o o   
	.db	0b10101000	; o o o   
	.db	0b01010000	;  o o    

; Character: X (58)
	.db	0b00000000	;         
	.db	0b01000010	;  o    o 
	.db	0b00100100	;   o  o  
	.db	0b00101000	;   o o   
	.db	0b00010000	;    o    
	.db	0b00101000	;   o o   
	.db	0b01001000	;  o  o   
	.db	0b10000100	; o    o  

; Character: Y (59)
	.db	0b00000000	;         
	.db	0b01000010	;  o    o 
	.db	0b00100100	;   o  o  
	.db	0b00101000	;   o o   
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b00100000	;   o     
	.db	0b00100000	;   o     

; Character: Z (5A)
	.db	0b00000000	;         
	.db	0b01111110	;  oooooo 
	.db	0b00000100	;      o  
	.db	0b00001000	;     o   
	.db	0b00010000	;    o    
	.db	0b00100000	;   o     
	.db	0b01000000	;  o      
	.db	0b11111100	; oooooo  

; Character: [ (5B)
	.db	0b00000000	;         
	.db	0b00001110	;     ooo 
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00001110	;     ooo 
	.db	0b00000000	;         

; Character: \ (5C)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b01000000	;  o      
	.db	0b00100000	;   o     
	.db	0b00010000	;    o    
	.db	0b00001000	;     o   
	.db	0b00000100	;      o  
	.db	0b00000000	;         

; Character: ] (5D)
	.db	0b00000000	;         
	.db	0b01110000	;  ooo    
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b01110000	;  ooo    
	.db	0b00000000	;         

; Character: ^ (5E)
	.db	0b00000000	;         
	.db	0b00010000	;    o    
	.db	0b00111000	;   ooo   
	.db	0b01010100	;  o o o  
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b00000000	;         

; Character: a (61)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00011100	;    ooo  
	.db	0b00000010	;       o 
	.db	0b00111110	;   ooooo 
	.db	0b01000100	;  o   o  
	.db	0b00111100	;   oooo  

; Character: b (62)
	.db	0b00000000	;         
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b00100000	;   o     
	.db	0b00111100	;   oooo  
	.db	0b00100010	;   o   o 
	.db	0b01000100	;  o   o  
	.db	0b01111000	;  oooo   

; Character: c (63)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00011110	;    oooo 
	.db	0b00100000	;   o     
	.db	0b01000000	;  o      
	.db	0b01000000	;  o      
	.db	0b00111100	;   oooo  

; Character: d (64)
	.db	0b00000000	;         
	.db	0b00000010	;       o 
	.db	0b00000010	;       o 
	.db	0b00000100	;      o  
	.db	0b00111100	;   oooo  
	.db	0b01000100	;  o   o  
	.db	0b01001000	;  o  o   
	.db	0b00111000	;   ooo   

; Character: e (65)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00011100	;    ooo  
	.db	0b00100010	;   o   o 
	.db	0b01111100	;  ooooo  
	.db	0b01000000	;  o      
	.db	0b00111000	;   ooo   

; Character: f (66)
	.db	0b00000000	;         
	.db	0b00001110	;     ooo 
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b00111000	;   ooo   
	.db	0b00100000	;   o     
	.db	0b01000000	;  o      
	.db	0b01000000	;  o      

; Character: g (67)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00011110	;    oooo 
	.db	0b00100010	;   o   o 
	.db	0b01000100	;  o   o  
	.db	0b00111100	;   oooo  
	.db	0b00000100	;      o  
	.db	0b01111000	;  oooo   

; Character: h (68)
	.db	0b00000000	;         
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b00100000	;   o     
	.db	0b00111100	;   oooo  
	.db	0b00100010	;   o   o 
	.db	0b01000100	;  o   o  
	.db	0b01000100	;  o   o  

; Character: i (69)
	.db	0b00000000	;         
	.db	0b00001000	;     o   
	.db	0b00000000	;         
	.db	0b00011000	;    oo   
	.db	0b00001000	;     o   
	.db	0b00010000	;    o    
	.db	0b00100000	;   o     
	.db	0b01110000	;  ooo    

; Character: j (6A)
	.db	0b00000000	;         
	.db	0b00000100	;      o  
	.db	0b00000000	;         
	.db	0b00000100	;      o  
	.db	0b00000100	;      o  
	.db	0b01001000	;  o  o   
	.db	0b01001000	;  o  o   
	.db	0b00110000	;   oo    

; Character: k (6B)
	.db	0b00000000	;         
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b00100000	;   o     
	.db	0b00100100	;   o  o  
	.db	0b00111000	;   ooo   
	.db	0b01000100	;  o   o  
	.db	0b01000100	;  o   o  

; Character: l (6C)
	.db	0b00000000	;         
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b00100000	;   o     
	.db	0b00100000	;   o     
	.db	0b00011000	;    oo   

; Character: m (6D)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00110100	;   oo o  
	.db	0b00101010	;   o o o 
	.db	0b00101010	;   o o o 
	.db	0b01010100	;  o o o  
	.db	0b01010100	;  o o o  

; Character: n (6E)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00111100	;   oooo  
	.db	0b00100010	;   o   o 
	.db	0b00100010	;   o   o 
	.db	0b01000100	;  o   o  
	.db	0b01000100	;  o   o  

; Character: o (6F)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00011100	;    ooo  
	.db	0b00100010	;   o   o 
	.db	0b00100010	;   o   o 
	.db	0b01000100	;  o   o  
	.db	0b01000100	;  o   o  
	.db	0b00111000	;   ooo   

; Character: p (70)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00011100	;    ooo  
	.db	0b00010010	;    o  o 
	.db	0b00100010	;   o   o 
	.db	0b00111100	;   oooo  
	.db	0b01000000	;  o      
	.db	0b01000000	;  o      

; Character: q (71)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00011110	;    oooo 
	.db	0b00100010	;   o   o 
	.db	0b00100100	;   o  o  
	.db	0b00011100	;    ooo  
	.db	0b00001000	;     o   
	.db	0b00001100	;     oo  

; Character: r (72)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00001110	;     ooo 
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b00100000	;   o     
	.db	0b00100000	;   o     

; Character: s (73)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00011110	;    oooo 
	.db	0b00100000	;   o     
	.db	0b00011000	;    oo   
	.db	0b00000100	;      o  
	.db	0b01111000	;  oooo   

; Character: t (74)
	.db	0b00000000	;         
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00011100	;    ooo  
	.db	0b00001000	;     o   
	.db	0b00010000	;    o    
	.db	0b00010000	;    o    
	.db	0b00100000	;   o     

; Character: u (75)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00100010	;   o   o 
	.db	0b00100010	;   o   o 
	.db	0b01000100	;  o   o  
	.db	0b01000100	;  o   o  
	.db	0b00111000	;   ooo   

; Character: v (76)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00100010	;   o   o 
	.db	0b00100010	;   o   o 
	.db	0b01000100	;  o   o  
	.db	0b01001000	;  o  o   
	.db	0b00110000	;   oo    

; Character: w (77)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00100010	;   o   o 
	.db	0b00101010	;   o o o 
	.db	0b01010100	;  o o o  
	.db	0b01010100	;  o o o  
	.db	0b00101000	;   o o   

; Character: x (78)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00100100	;   o  o  
	.db	0b00101000	;   o o   
	.db	0b00011000	;    oo   
	.db	0b00100100	;   o  o  
	.db	0b01000100	;  o   o  

; Character: y (79)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00100010	;   o   o 
	.db	0b00100010	;   o   o 
	.db	0b00011100	;    ooo  
	.db	0b00000100	;      o  
	.db	0b01111000	;  oooo   

; Character: z (7A)
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00000000	;         
	.db	0b00111110	;   ooooo 
	.db	0b00000100	;      o  
	.db	0b00011000	;    oo   
	.db	0b00100000	;   o     
	.db	0b01111100	;  ooooo  

; Character: { (7B)
	.db	0b00000000	;         
	.db	0b00001110	;     ooo 
	.db	0b00001000	;     o   
	.db	0b00110000	;   oo    
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00001110	;     ooo 
	.db	0b00000000	;         

; Character: | (7C)
	.db	0b00000000	;         
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00001000	;     o   
	.db	0b00000000	;         

; Character: } (7D)
	.db	0b00000000	;         
	.db	0b01110000	;  ooo    
	.db	0b00010000	;    o    
	.db	0b00001100	;     oo  
	.db	0b00
Download .txt
gitextract_01138mzq/

├── .gitignore
├── Make.bat
├── Makefile
├── README.md
├── bin/
│   ├── gbdk-n-assemble.bat
│   ├── gbdk-n-assemble.sh
│   ├── gbdk-n-compile.bat
│   ├── gbdk-n-compile.sh
│   ├── gbdk-n-link.bat
│   ├── gbdk-n-link.sh
│   ├── gbdk-n-make-rom.bat
│   └── gbdk-n-make-rom.sh
├── examples/
│   ├── galaxy/
│   │   ├── Make.bat
│   │   ├── Makefile
│   │   └── galaxy.c
│   ├── paint/
│   │   ├── Make.bat
│   │   ├── Makefile
│   │   └── paint.c
│   ├── space/
│   │   ├── Make.bat
│   │   ├── Makefile
│   │   └── space.s
│   └── thumby/
│       ├── Make.bat
│       ├── Makefile
│       └── thumby.c
├── include/
│   ├── asm/
│   │   ├── gbz80/
│   │   │   ├── provides.h
│   │   │   ├── stdarg.h
│   │   │   └── types.h
│   │   ├── types.h
│   │   └── z80/
│   │       ├── provides.h
│   │       ├── stdarg.h
│   │       └── types.h
│   └── gb/
│       ├── cgb.h
│       ├── console.h
│       ├── drawing.h
│       ├── font.h
│       ├── gb.h
│       ├── hardware.h
│       ├── malloc.h
│       ├── rand.h
│       ├── sample.h
│       └── sgb.h
└── libc/
    ├── arand.s
    ├── cgb.s
    ├── cpy_data.s
    ├── crt0.s
    ├── delay.s
    ├── digits.c
    ├── drawing.s
    ├── f_ibm_sh.s
    ├── f_italic.s
    ├── f_min.s
    ├── f_spect.s
    ├── font.s
    ├── get_bk_t.s
    ├── get_data.s
    ├── get_prop.s
    ├── get_spr.s
    ├── get_wi_t.s
    ├── get_xy_t.s
    ├── global.s
    ├── gprint.c
    ├── gprintf.c
    ├── gprintln.c
    ├── gprintn.c
    ├── hiramcpy.s
    ├── ibmfixed.s
    ├── init_tt.s
    ├── input.s
    ├── mv_bkg.s
    ├── mv_spr.s
    ├── mv_win.s
    ├── pad.s
    ├── rand.s
    ├── sample.s
    ├── scroll_b.s
    ├── scroll_s.s
    ├── scroll_w.s
    ├── serial.s
    ├── set_bk_t.s
    ├── set_data.s
    ├── set_prop.s
    ├── set_spr.s
    ├── set_wi_t.s
    ├── set_xy_t.s
    ├── sfr.s
    ├── sgb.s
    └── stubs.rasm
Download .txt
SYMBOL INDEX (58 symbols across 12 files)

FILE: examples/galaxy/galaxy.c
  function fade (line 389) | void fade()
  function scroll (line 414) | void scroll()
  function door (line 455) | void door()
  function animate_sprite (line 473) | void animate_sprite()
  function tile_sprite (line 484) | void tile_sprite()
  function place_sprite (line 494) | void place_sprite()
  function main (line 500) | void main()

FILE: examples/paint/paint.c
  type icon_info (line 26) | typedef struct icon_info_
  type cursor_info (line 34) | typedef struct cursor_info_
  function set_cursor (line 263) | void set_cursor()
  function move_cursor (line 283) | void move_cursor()
  function move_menu_cursor (line 294) | void move_menu_cursor()
  function set_icon (line 301) | void set_icon(UBYTE icon, UBYTE selected)
  function change_icon (line 315) | void change_icon(UBYTE icon, UBYTE selected)
  function reset_icon (line 329) | void reset_icon(UBYTE icon)
  function splash (line 341) | void splash()
  function menu (line 385) | void menu()
  function run (line 455) | void run()
  function main (line 513) | void main()

FILE: examples/thumby/thumby.c
  function main (line 33) | void main()

FILE: include/asm/gbz80/types.h
  type INT8 (line 16) | typedef signed char   	INT8;
  type UINT8 (line 19) | typedef unsigned char 	UINT8;
  type INT16 (line 22) | typedef int           	INT16;
  type UINT16 (line 25) | typedef unsigned int  	UINT16;
  type INT32 (line 28) | typedef long          	INT32;
  type UINT32 (line 31) | typedef unsigned long 	UINT32;
  type UINT16 (line 41) | typedef UINT16		clock_t;

FILE: include/asm/types.h
  type INT8 (line 25) | typedef INT8		BOOLEAN;
  type UINT8 (line 29) | typedef UINT8		BYTE;
  type UINT16 (line 30) | typedef UINT16		WORD;
  type UINT32 (line 31) | typedef UINT32		DWORD;
  type INT8 (line 37) | typedef INT8         	BYTE;
  type UINT8 (line 40) | typedef UINT8        	UBYTE;
  type INT16 (line 42) | typedef INT16      	WORD;
  type UINT16 (line 44) | typedef UINT16       	UWORD;
  type INT32 (line 46) | typedef INT32       	LWORD;
  type UINT32 (line 48) | typedef UINT32      	ULWORD;
  type INT32 (line 50) | typedef INT32	   	DWORD;
  type UINT32 (line 52) | typedef UINT32	   	UDWORD;
  type fixed (line 55) | typedef union _fixed {

FILE: include/asm/z80/types.h
  type INT8 (line 8) | typedef char          	INT8;
  type UINT8 (line 9) | typedef unsigned char 	UINT8;
  type INT16 (line 10) | typedef int           	INT16;
  type UINT16 (line 11) | typedef unsigned int  	UINT16;
  type INT32 (line 12) | typedef long          	INT32;
  type UINT32 (line 13) | typedef unsigned long 	UINT32;
  type UINT16 (line 16) | typedef UINT16		clock_t;

FILE: include/gb/font.h
  type UINT16 (line 22) | typedef UINT16 font_t;
  type mfont_handle (line 50) | typedef struct sfont_handle mfont_handle;
  type sfont_handle (line 51) | struct sfont_handle
  type sfont_handle (line 53) | struct sfont_handle {

FILE: include/gb/malloc.h
  type mmalloc_hunk (line 23) | typedef struct smalloc_hunk	mmalloc_hunk;
  type smalloc_hunk (line 24) | struct smalloc_hunk
  type smalloc_hunk (line 26) | struct smalloc_hunk {

FILE: libc/gprint.c
  function gprint (line 3) | void gprint(char *str) NONBANKED

FILE: libc/gprintf.c
  function INT8 (line 4) | INT8 gprintf(char *fmt, ...) NONBANKED

FILE: libc/gprintln.c
  function gprintln (line 7) | void gprintln(INT16 number, INT8 radix, INT8 signed_value)

FILE: libc/gprintn.c
  function gprintn (line 7) | void gprintn(BYTE number, BYTE radix, BYTE signed_value)
Condensed preview — 87 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (383K chars).
[
  {
    "path": ".gitignore",
    "chars": 12,
    "preview": "lib/*\nobj/*\n"
  },
  {
    "path": "Make.bat",
    "chars": 1839,
    "preview": "echo off\n\nset SRCDIR=libc\nset OBJDIR=obj\nset LIBDIR=lib\n\nset CC=bin\\gbdk-n-compile.bat\nset CA=bin\\gbdk-n-assemble.bat\n\n:"
  },
  {
    "path": "Makefile",
    "chars": 2856,
    "preview": "SRCDIR=./libc\nOBJDIR=./obj\nLIBDIR=./lib\n\nCC=bin/gbdk-n-compile.sh\nCA=bin/gbdk-n-assemble.sh\n\n.PHONY: lib\nlib: $(LIBDIR)/"
  },
  {
    "path": "README.md",
    "chars": 1404,
    "preview": "# gbdk-n\n\n#### Background\n\nThe Gameboy Development Kit (GBDK) is an SDK for developing applications/games for the gamebo"
  },
  {
    "path": "bin/gbdk-n-assemble.bat",
    "chars": 50,
    "preview": "set GBDK_DIR=%~dp0..\n\nsdasgb -plosgff -I\"libc\" %*\n"
  },
  {
    "path": "bin/gbdk-n-assemble.sh",
    "chars": 99,
    "preview": "#!/bin/sh\n\nGBDK_DIR=\"$( cd \"$( dirname \"$0\" )\" && pwd )/..\"\n\nset -x\n\nsdasgb -plosgff -I\"libc\" \"$@\"\n"
  },
  {
    "path": "bin/gbdk-n-compile.bat",
    "chars": 106,
    "preview": "set GBDK_DIR=%~dp0..\n\nsdcc -mgbz80 --no-std-crt0 -I \"%GBDK_DIR%\\include\" -I \"%GBDK_DIR%\\include\\asm\" -c %*"
  },
  {
    "path": "bin/gbdk-n-compile.sh",
    "chars": 156,
    "preview": "#!/bin/sh\n\nGBDK_DIR=\"$( cd \"$( dirname \"$0\" )\" && pwd )/..\"\n\nset -x\n  \nsdcc -mgbz80 --no-std-crt0 -I \"$GBDK_DIR/include\""
  },
  {
    "path": "bin/gbdk-n-link.bat",
    "chars": 134,
    "preview": "set GBDK_DIR=%~dp0..\n  \nsdcc -mgbz80 --no-std-crt0 --data-loc 0xc0a0 -L \"%GBDK_DIR%\\lib\" \"%GBDK_DIR%\\lib\\crt0.rel\" gb.li"
  },
  {
    "path": "bin/gbdk-n-link.sh",
    "chars": 181,
    "preview": "#!/bin/sh\n\nGBDK_DIR=\"$( cd \"$( dirname \"$0\" )\" && pwd )/..\"\n\nset -x\n  \nsdcc -mgbz80 --no-std-crt0 --data-loc 0xc0a0 -L \""
  },
  {
    "path": "bin/gbdk-n-make-rom.bat",
    "chars": 14,
    "preview": "makebin -Z %*\n"
  },
  {
    "path": "bin/gbdk-n-make-rom.sh",
    "chars": 35,
    "preview": "#!/bin/sh\n\nset -x\n\nmakebin -Z \"$@\"\n"
  },
  {
    "path": "examples/galaxy/Make.bat",
    "chars": 354,
    "preview": "echo off\nset BIN=..\\..\\bin\nset OBJ=obj\n\nif \"%1\"==\"clean\" (\n\tif exist %OBJ% rd /s/q %OBJ%\n\tif exist galaxy.gb del galaxy."
  },
  {
    "path": "examples/galaxy/Makefile",
    "chars": 264,
    "preview": "BIN=../../bin\nOBJ=./obj\n\n\n\nbuild:\n\tmkdir -p $(OBJ)\n\t$(BIN)/gbdk-n-compile.sh galaxy.c -o $(OBJ)/galaxy.rel\n\t$(BIN)/gbdk-"
  },
  {
    "path": "examples/galaxy/galaxy.c",
    "chars": 22503,
    "preview": "/*\n * C version of the 'space' assembly demo.\n *\n * Little demo illustrating how to use the graphical possibilities\n *  "
  },
  {
    "path": "examples/paint/Make.bat",
    "chars": 346,
    "preview": "echo off\nset BIN=..\\..\\bin\nset OBJ=obj\n\nif \"%1\"==\"clean\" (\n\tif exist %OBJ% rd /s/q %OBJ%\n\tif exist paint.gb del paint.gb"
  },
  {
    "path": "examples/paint/Makefile",
    "chars": 257,
    "preview": "BIN=../../bin\nOBJ=./obj\n\n\n\nbuild:\n\tmkdir -p $(OBJ)\n\t$(BIN)/gbdk-n-compile.sh paint.c -o $(OBJ)/paint.rel\n\t$(BIN)/gbdk-n-"
  },
  {
    "path": "examples/paint/paint.c",
    "chars": 19322,
    "preview": "#include <gb/gb.h>\n#include <gb/drawing.h>\n\n#define NB_TOOLS 18\n#define NB_DATA_TILES 48\n\n#define ARROW 0\n#define PEN 1\n"
  },
  {
    "path": "examples/space/Make.bat",
    "chars": 345,
    "preview": "echo off\nset BIN=..\\..\\bin\nset OBJ=obj\n\nif \"%1\"==\"clean\" (\n\tif exist %OBJ% rd /s/q %OBJ%\n\tif exist space.gb del space.gb"
  },
  {
    "path": "examples/space/Makefile",
    "chars": 253,
    "preview": "BIN=../../bin\nOBJ=./obj\n\nbuild:\n\tmkdir -p $(OBJ)\n\t$(BIN)/gbdk-n-assemble.sh $(OBJ)/space.rel space.s\n\t$(BIN)/gbdk-n-link"
  },
  {
    "path": "examples/space/space.s",
    "chars": 35637,
    "preview": "\t;; Little demo illustrating how to use the graphical possibilities\n\t;;  of the GB (background, window and animated spri"
  },
  {
    "path": "examples/thumby/Make.bat",
    "chars": 354,
    "preview": "echo off\nset BIN=..\\..\\bin\nset OBJ=obj\n\nif \"%1\"==\"clean\" (\n\tif exist %OBJ% rd /s/q %OBJ%\n\tif exist thumby.gb del thumby."
  },
  {
    "path": "examples/thumby/Makefile",
    "chars": 262,
    "preview": "BIN=../../bin\nOBJ=./obj\n\nbuild:\n\tmkdir -p $(OBJ)\n\t$(BIN)/gbdk-n-compile.sh thumby.c -o $(OBJ)/thumby.rel\n\t$(BIN)/gbdk-n-"
  },
  {
    "path": "examples/thumby/thumby.c",
    "chars": 1449,
    "preview": "#include <gb/gb.h>\n\n/*\n * Game Boy Development Kit Demonstration program\n * Creates a rectangle on screen\n * which can b"
  },
  {
    "path": "include/asm/gbz80/provides.h",
    "chars": 70,
    "preview": "#define USE_C_MEMCPY\t1\n#define USE_C_STRCPY\t1\n#define USE_C_STRCMP\t1\n\n"
  },
  {
    "path": "include/asm/gbz80/stdarg.h",
    "chars": 524,
    "preview": "#ifndef ASM_GBZ80_STDARG_INCLUDE\n#define ASM_GBZ80_STDARG_INCLUDE\n\n/* sdcc pushes right to left with the real sizes, not"
  },
  {
    "path": "include/asm/gbz80/types.h",
    "chars": 740,
    "preview": "/** @file asm/gbz80/types.h\n    Types definitions for the gb.\n*/\n#ifndef ASM_GBZ80_TYPES_INCLUDE\n#define ASM_GBZ80_TYPES"
  },
  {
    "path": "include/asm/types.h",
    "chars": 1025,
    "preview": "/** @file asm/types.h\n    Shared types definitions.\n*/\n#ifndef ASM_TYPES_INCLUDE\n#define ASM_TYPES_INCLUDE\n\n#if SDCC_POR"
  },
  {
    "path": "include/asm/z80/provides.h",
    "chars": 60,
    "preview": "#undef USE_C_MEMCPY\n#undef USE_C_STRCPY\n#undef USE_C_STRCMP\n"
  },
  {
    "path": "include/asm/z80/stdarg.h",
    "chars": 579,
    "preview": "#ifndef ASM_Z80_STDARG_INCLUDE\n#define ASM_Z80_STDARG_INCLUDE\n\n/* sdcc pushes right to left with the real sizes, not cas"
  },
  {
    "path": "include/asm/z80/types.h",
    "chars": 347,
    "preview": "#ifndef ASM_Z80_TYPES_INCLUDE\n#define ASM_Z80_TYPES_INCLUDE\n\n#if SDCC_PORT!=z80\n#error z80 only.\n#endif\n\ntypedef char   "
  },
  {
    "path": "include/gb/cgb.h",
    "chars": 2106,
    "preview": "/** @file gb/cgb.h\n    Support for Color GameBoy.\n*/\n\n#ifndef _CGB_H\n#define _CGB_H\n\n/** Macro to create a palette entry"
  },
  {
    "path": "include/gb/console.h",
    "chars": 602,
    "preview": "/** @file gb/console.h\n    Console functions that work like Turbo C's.\n    Note that the font is 8x8, making the screen "
  },
  {
    "path": "include/gb/drawing.h",
    "chars": 3169,
    "preview": "/** @file gb/drawing.h\n    All Points Addressable (APA) mode drawing library.\n\n    Drawing routines originally by Pascal"
  },
  {
    "path": "include/gb/font.h",
    "chars": 1395,
    "preview": "/** @file gb/font.h\n    Multiple font support for the GameBoy\n    Michael Hope, 1999\n    michaelh@earthling.net\n*/\n#ifnd"
  },
  {
    "path": "include/gb/gb.h",
    "chars": 17765,
    "preview": "/** @file gb/gb.h\n    Gameboy specific functions.\n*/\n#ifndef _GB_H\n#define _GB_H\n\n#include <types.h>\n#include <gb/hardwa"
  },
  {
    "path": "include/gb/hardware.h",
    "chars": 5704,
    "preview": "/** @file gb/hardware.h\n    Defines that let the GB's hardware registers be accessed\n    from C.  See the Pan doc for wh"
  },
  {
    "path": "include/gb/malloc.h",
    "chars": 1173,
    "preview": "/** @file gb/malloc.h\n\n    Header for a simple implementation of malloc().  This library\n    may currently be broken.\n*/"
  },
  {
    "path": "include/gb/rand.h",
    "chars": 890,
    "preview": "/** @file rand.h\n    Random generator using the linear congruential method\n\n    @author\tLuc Van den Borre\n*/\n#ifndef RAN"
  },
  {
    "path": "include/gb/sample.h",
    "chars": 532,
    "preview": "/** @file gb/sample.h\n    Playback raw sound sample with length len from start at 8192Hz rate.\n    len defines the lengt"
  },
  {
    "path": "include/gb/sgb.h",
    "chars": 187,
    "preview": "/** @file gb/sgb.h\n    Super Gameboy definitions.\n*/\n#ifndef _SGB_H\n#define _SGB_H\n\n/** Return a non-null value if runni"
  },
  {
    "path": "libc/arand.s",
    "chars": 2642,
    "preview": ";/***************************************************************************\n; *                                       "
  },
  {
    "path": "libc/cgb.s",
    "chars": 3517,
    "preview": "\t.include \"global.s\"\n\n\t.title\t\"CGB support\"\n\t.module\tCGB\n\n\t;; BANKED: checked, imperfect\n\t.area\t_BASE\n\n_set_bkg_palette:"
  },
  {
    "path": "libc/cpy_data.s",
    "chars": 493,
    "preview": "\t.include\t\"global.s\"\n\n\t;; BANKED: checked\n\t.area\t_BASE\n\t;; Copy part (size = DE) of the VRAM from (BC) to (HL)\n.copy_vra"
  },
  {
    "path": "libc/crt0.s",
    "chars": 10947,
    "preview": "\t.include\t\"global.s\"\n\n\t;; ****************************************\n\t;; Beginning of module\n\t;; BANKED: checked\n\t.title\t\""
  },
  {
    "path": "libc/delay.s",
    "chars": 1488,
    "preview": "\t.include\t\"global.s\"\n\n\t;; BANKED:\tchecked, imperfect\n\t.area\t_BASE\n\n\t;; Delay DE milliseconds\n\t;; \n\t;; Entry conditions\n\t"
  },
  {
    "path": "libc/digits.c",
    "chars": 67,
    "preview": "#pragma bank=BASE\n\nconst char * const digits = \"0123456789ABCDEF\";\n"
  },
  {
    "path": "libc/drawing.s",
    "chars": 21754,
    "preview": ";; Optimised Drawing library \n;; By Jon Fuge (jonny@q-continuum.demon.co.uk) based on original file\n;; Updates\n;;   9902"
  },
  {
    "path": "libc/f_ibm_sh.s",
    "chars": 5176,
    "preview": "; ibm_fixed.ms - fixed width IBM font\n\t;; BANKED:\tchecked, imperfect\n\t.area\t_BASE\n\n\t; 898 bytes giving ' '-'0'-'@'-'A'-'"
  },
  {
    "path": "libc/f_italic.s",
    "chars": 22852,
    "preview": "; font: italic\n\t;; BANKED:\tchecked,imperfect\n\t.area\t_BASE\n_font_italic::\n\t.db\t1+4\t; 128 char encoding, compressed\n\t.db\t9"
  },
  {
    "path": "libc/f_min.s",
    "chars": 9295,
    "preview": "; font_min.s\n\t\n;\tText font\n;\tMichael Hope, 1998\n;\tmichaelh@earthling.net\n;\tDistrubuted under the Artistic License - see "
  },
  {
    "path": "libc/f_spect.s",
    "chars": 22884,
    "preview": "; font_spect.ms\n;\tText font\n;\tMichael Hope, 1998\n;\tmichaelh@earthling.net\n;\tDistrubuted under the Artistic License - see"
  },
  {
    "path": "libc/font.s",
    "chars": 11270,
    "preview": "; font.ms\n;\n;\tMichael Hope, 1999\n;\tmichaelh@earthling.net\n;\tDistrubuted under the Artistic License - see www.opensource."
  },
  {
    "path": "libc/get_bk_t.s",
    "chars": 358,
    "preview": "\t.include\t\"global.s\"\n\n\t.globl\t.get_xy_btt\n\t;; BANKED:\tchecked\n\t.area\t_BASE\n\n_get_bkg_tiles::\n\tPUSH\tBC\n\n\tLDA\tHL,4(SP)\t; S"
  },
  {
    "path": "libc/get_data.s",
    "chars": 1624,
    "preview": "\t.include\t\"global.s\"\n\n\t.globl\t.copy_vram\n\n\t;; BANKED:\tchecked\n\t.area\t_BASE\n\n_get_bkg_data::\n_get_win_data::\n\tLDH\tA,(.LCD"
  },
  {
    "path": "libc/get_prop.s",
    "chars": 418,
    "preview": "\t.include\t\"global.s\"\n\t;; BANKED:\tchecked, imperfect\n\t.area\t_BASE\n\n\t;; Get properties of sprite number C\n.get_sprite_prop"
  },
  {
    "path": "libc/get_spr.s",
    "chars": 409,
    "preview": "\t.include\t\"global.s\"\n\n\t;; BANKED:\tchecked, imperfect\n\t.area\t_BASE\n\n\t;; Get tile of sprite number C\n.get_sprite_tile::\n\tL"
  },
  {
    "path": "libc/get_wi_t.s",
    "chars": 369,
    "preview": "\t.include\t\"global.s\"\n\n\t.globl\t.get_xy_wtt\n\t;; BANKED:\tchecked, imperfect\n\t.area\t_BASE\n\n_get_win_tiles::\n\tPUSH\tBC\n\n\tLDA\tH"
  },
  {
    "path": "libc/get_xy_t.s",
    "chars": 1608,
    "preview": "\t.include        \"global.s\"\n\n\t;; BANKED:\tchecked\n\t.area\t_BASE\n\n\t;; Store window tile table into (BC) at xy = DE of size "
  },
  {
    "path": "libc/global.s",
    "chars": 3642,
    "preview": "\t.NEAR_CALLS = 1         ; <near_calls> - tag so that sed can change this\n        \n\t;; Changed by astorgb.pl to 1\n\t__RGB"
  },
  {
    "path": "libc/gprint.c",
    "chars": 95,
    "preview": "#include <gb/drawing.h>\n\nvoid gprint(char *str) NONBANKED\n{\n    while(*str)\n\twrtchr(*str++);\n}\n"
  },
  {
    "path": "libc/gprintf.c",
    "chars": 1443,
    "preview": "#include <stdarg.h>\n#include <gb/drawing.h>\n\nINT8 gprintf(char *fmt, ...) NONBANKED\n{\n  va_list ap;\n  INT8 nb = 0;\n\n  va"
  },
  {
    "path": "libc/gprintln.c",
    "chars": 373,
    "preview": "#include <gb/drawing.h>\n\n/* Print a long number in any radix */\n\nextern char *digits;\n\nvoid gprintln(INT16 number, INT8 "
  },
  {
    "path": "libc/gprintn.c",
    "chars": 360,
    "preview": "#include <gb/drawing.h>\n\n/* Print a number in any radix */\n\nextern char *digits;\n\nvoid gprintn(BYTE number, BYTE radix, "
  },
  {
    "path": "libc/hiramcpy.s",
    "chars": 482,
    "preview": "\t.include\t\"global.s\"\n\n\t;; BANKED:\tchecked\n\t.area\t_BASE\n\n\t;; Copy memory zone to HIRAM\n\t;; \n\t;; Entry conditions\n\t;;   C "
  },
  {
    "path": "libc/ibmfixed.s",
    "chars": 62510,
    "preview": "; font: font\n\t;; BANKED: checked\n\t.area\t_BASE\n\n\t.globl\tfont_load\n\t;; Perform tricks with banking to shift this font out "
  },
  {
    "path": "libc/init_tt.s",
    "chars": 641,
    "preview": "\t.include\t\"global.s\"\n\n\t;; BANKED: checked\n\t.area\t_BASE\n\n\t;; Initialize part (size = DE) of the VRAM at (HL) with B\n.init"
  },
  {
    "path": "libc/input.s",
    "chars": 9724,
    "preview": "\t.include\t\"global.s\"\n\n\t;; Note that while gets uses a pointer, the pointer had better\n\t;; be in non-banked RAM else bad "
  },
  {
    "path": "libc/mv_bkg.s",
    "chars": 165,
    "preview": "\t.include\t\"global.s\"\n\n\t;; BANKED:\tchecked\n\t.area\t_BASE\n\n_move_bkg::\n\tLDA\tHL,2(SP)\t; Skip return address\n\tLD\tA,(HL+)\n\tLDH"
  },
  {
    "path": "libc/mv_spr.s",
    "chars": 458,
    "preview": "\t.include\t\"global.s\"\n\n\t;; BANKED:\tchecked\n\t.area\t_BASE\n\n\t;; Move sprite number C at XY = DE\n.mv_sprite::\n\tLD\tHL,#.OAM\t; "
  },
  {
    "path": "libc/mv_win.s",
    "chars": 159,
    "preview": "\t.include\t\"global.s\"\n\n\t;; BANKED:\tchecked\n\t.area\t_BASE\n\n_move_win::\n\tLDA\tHL,2(SP)\t; Skip return address\n\tLD\tA,(HL+)\n\tLDH"
  },
  {
    "path": "libc/pad.s",
    "chars": 1298,
    "preview": "\t.include\t\"global.s\"\n\n\t;; BANKED:\tchecked\n\t.area\t_BASE\n\n\t;; Wait until all buttons have been released\n.padup::\n_waitpadu"
  },
  {
    "path": "libc/rand.s",
    "chars": 4059,
    "preview": ";/***************************************************************************\n; *                                       "
  },
  {
    "path": "libc/sample.s",
    "chars": 1711,
    "preview": "\t.include \"global.s\"\n\n\t;; BANKED:\tchecked\n\t.title \"Sound sample player\"\n\t.module Sample\n\n\t.area\t_BASE\n\t.AUD3WAVERAM = 0x"
  },
  {
    "path": "libc/scroll_b.s",
    "chars": 304,
    "preview": "\t.include\t\"global.s\"\n\n\t;; BANKED:\tchecked, imperfect\n\t.area\t_BASE\n\n_scroll_bkg::\n\tLDA\tHL,2(SP)\t; Skip return address\n\tXO"
  },
  {
    "path": "libc/scroll_s.s",
    "chars": 499,
    "preview": "\t.include\t\"global.s\"\n\n\t;; BANKED:\tchecked, imperfect\n\t.area\t_BASE\n\n\t;; Move sprite number C at XY = DE\n.scroll_sprite::\n"
  },
  {
    "path": "libc/scroll_w.s",
    "chars": 302,
    "preview": "\t.include\t\"global.s\"\n\n\t;; BANKED:\tchecked, imperfect\n\t.area\t_BASE\n\n_scroll_win::\n\tLDA\tHL,2(SP)\t; Skip return address\n\tXO"
  },
  {
    "path": "libc/serial.s",
    "chars": 637,
    "preview": "\t.include\t\"global.s\"\n\n\t;; BANKED:\tchecked\n\t.area\t_CODE\n\n\t;; Send byte in __io_out to the serial port\n.send_byte:\n_send_b"
  },
  {
    "path": "libc/set_bk_t.s",
    "chars": 358,
    "preview": "\t.include\t\"global.s\"\n\n\t.globl\t.set_xy_btt\n\t;; BANKED:\tchecked\n\t.area\t_BASE\n\n_set_bkg_tiles::\n\tPUSH\tBC\n\n\tLDA\tHL,4(SP)\t; S"
  },
  {
    "path": "libc/set_data.s",
    "chars": 1612,
    "preview": "\t.include\t\"global.s\"\n\n\t.globl\t.copy_vram\n\n\t;; BANKED:\tchecked\n\t.area\t_BASE\n\n_set_bkg_data::\n_set_win_data::\n\tLDH\tA,(.LCD"
  },
  {
    "path": "libc/set_prop.s",
    "chars": 455,
    "preview": "\t.include\t\"global.s\"\n\n\t;; BANKED:\tchecked, imperfect\n\t.area\t_BASE\n\n\t;; Set properties of sprite number C to D\n.set_sprit"
  },
  {
    "path": "libc/set_spr.s",
    "chars": 442,
    "preview": "\t.include\t\"global.s\"\n\n\t;; BANKED:\tchecked, imperfect\n\t.area\t_BASE\n\n\t;; Set sprite number C to tile D\n.set_sprite_tile::\n"
  },
  {
    "path": "libc/set_wi_t.s",
    "chars": 370,
    "preview": "\t.include\t\"global.s\"\n\n\t.globl\t.set_xy_wtt\n\n\t;; BANKED:\tchecked, imperfect\n\t.area\t_BASE\n\n_set_win_tiles::\n\tPUSH\tBC\n\n\tLDA\t"
  },
  {
    "path": "libc/set_xy_t.s",
    "chars": 1585,
    "preview": "\t.include\t\"global.s\"\n\n\t;; BANKED:\tchecked, imperfect\n\t.area\t_BASE\n\n\t;; Set window tile table from BC at XY = DE of size "
  },
  {
    "path": "libc/sfr.s",
    "chars": 2947,
    "preview": "\t.area\t_SFR (ABS)\n\n\t.org\t0xFF00\n_P1_REG::\t; Joystick: 1.1.P15.P14.P13.P12.P11.P10 */ \n\t.ds\t1\n\t.org\t0xFF01\n_SB_REG::\t; Se"
  },
  {
    "path": "libc/sgb.s",
    "chars": 2297,
    "preview": "\t.include        \"global.s\"\n\n\t.PAL_01\t\t= 0x00\n\t.PAL_23\t\t= 0x01\n\t.PAL_03\t\t= 0x02\n\t.PAL_12\t\t= 0x03\n\t.ATTR_BLK\t= 0x04\n\t.ATT"
  },
  {
    "path": "libc/stubs.rasm",
    "chars": 176,
    "preview": "\tGLOBAL \tSTACK\n\tGLOBAL \tOAM\n\tGLOBAL\trefresh_OAM\n\n\tSECTION \"stubs_1\", BSS[$C000]\nOAM:\n\tDS\t$A0\n\tSECTION \"stubs_2\", HRAM[$F"
  }
]

About this extraction

This page contains the full source code of the andreasjhkarlsson/gbdk-n GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 87 files (333.4 KB), approximately 168.3k tokens, and a symbol index with 58 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!