Skip to content

Instantly share code, notes, and snippets.

@agrif
Created April 9, 2013 02:13
Show Gist options
  • Select an option

  • Save agrif/5342381 to your computer and use it in GitHub Desktop.

Select an option

Save agrif/5342381 to your computer and use it in GitHub Desktop.
;;; useful addresses
INT_VBLANK: equ 0x0040
INT_LCDC: equ 0x0048
INT_TIMER: equ 0x0050
INT_SERIAL: equ 0x0058
INT_P1THRU4: equ 0x0060
ROM_HEADER: equ 0x0100
;;; 15 ascii bytes
ROM_TITLE: equ ROM_HEADER + 0x034
;;; 2 bytes
ROM_MANUFACTURER: equ ROM_HEADER + 0x044
ROM_HEADER_END: equ ROM_HEADER + 0x050
VRAM: equ 0x8000
SCRN0: equ 0x9800
;;; figure out what to call these later
rSTAT: equ 0xFF41
rBGP: equ 0xff47
rLCDC: equ 0xff40
rSCX: equ 0xff43
rSCY: equ 0xff42
rLY: equ 0xff44
LCDCF_OFF: equ 0b00000000
LCDCF_ON: equ 0b10000000
LCDCF_WIN9800: equ 0b00000000
LCDCF_WIN9C00: equ 0b01000000
LCDCF_WINOFF: equ 0b00000000
LCDCF_WINON: equ 0b00100000
LCDCF_BG8800: equ 0b00000000
LCDCF_BG8000: equ 0b00010000
LCDCF_BG9800: equ 0b00000000
LCDCF_BG9C00: equ 0b00001000
LCDCF_OBJ8: equ 0b00000000
LCDCF_OBJ16: equ 0b00000100
LCDCF_OBJOFF: equ 0b00000000
LCDCF_OBJON: equ 0b00000010
LCDCF_BGOFF: equ 0b00000000
LCDCF_BGON: equ 0b00000001
STATF_BUSY: equ 0b00000010
SCRN_VX_B: equ 0x20
SCRN_VY_B: equ 0x20
;;; org and seek all in one
section: macro address
seek address
org address
endm
;;; Helper to select 16k ROM page
;;; correctly sets org to 0x4000 for pages >= 1
;;; and 0x0000 for page 0
rompage: macro page
seek 0x4000 * page
if page == 0
org 0x0000
else
org 0x4000
endif
endm
;;; Game Boy Color Flag
COLOR_ON: equ 0x80
COLOR_OFF: equ 0x00
;;; Super Game Boy Flag
SGB_ON: equ 0x03
SGB_OFF: equ 0x00
;;; Cartridge Type
CART_ROM: equ 0x00
CART_ROM_MBC1: equ 0x01
CART_ROM_MBC1_RAM: equ 0x02
CART_ROM_MBC1_RAM_BAT: equ 0x03
CART_ROM_MBC2: equ 0x05
CART_ROM_MBC2_BAT: equ 0x06
CART_ROM_RAM: equ 0x08
CART_ROM_RAM_BATTERY: equ 0x09
CART_ROM_MMMO1: equ 0x0b
CART_ROM_MMMO1_SRAM: equ 0x0c
CART_ROM_MMMO1_SRAM_BAT: equ 0x0d
CART_ROM_MBC3_TIMER_BAT: equ 0x0f
CART_ROM_MBC3_TIMER_RAM_BAT: equ 0x10
CART_ROM_MBC3: equ 0x11
CART_ROM_MBC3_RAM: equ 0x12
CART_ROM_MBC3_RAM_BAT: equ 0x13
CART_ROM_MBC5: equ 0x19
CART_ROM_MBC5_RAM: equ 0x1a
CART_ROM_MBC5_RAM_BAT: equ 0x1b
CART_ROM_MBC5_RUMBLE: equ 0x1c
CART_ROM_MBC5_RUMBLE_SRAM: equ 0x1d
CART_ROM_MBC5_RUMBLE_SRAM_BAT: equ 0x1e
CART_POCKET_CAMERA: equ 0x1f
CART_BANDAI_TAMA5: equ 0xfd
CART_HUDSON_HuC_3: equ 0xfe
CART_HUDSON_HuC_1: equ 0xff
;;; ROM size (in bytes)
;;; upper 16kB (0x4000) can be paged
;;; on all but MBC5, paging in page 0 actually pages in page 1
ROM_32K: equ 0x00 ; 32kB, 256kbit, 2 pages
ROM_64K: equ 0x01 ; 64kB, 512kbit, 4 pages
ROM_128K: equ 0x02 ; 128kB, 1Mbit, 8 pages
ROM_256K: equ 0x03 ; 256kB, 2Mbit, 16 pages
ROM_512K: equ 0x04 ; 512kB, 4Mbit, 32 pages
ROM_1M: equ 0x05 ; 1MB, 8Mbit, 64 pages
ROM_2M: equ 0x06 ; 2MB, 16Mbit, 128 pages
ROM_1_1M: equ 0x52 ; 1.1MB, 9Mbit, 72 pages
ROM_1_2M: equ 0x53 ; 1.2MB, 10Mbit, 80 pages
ROM_1_5M: equ 0x54 ; 1.5MB, 12Mbit, 96 pages
;;; RAM size (in bytes)
;;; 8kB can be found at 0xA000, and can be paged
RAM_NONE: equ 0x00 ; no RAM
RAM_2K: equ 0x01 ; 2kB, 16kbit, 1 page
RAM_8K: equ 0x02 ; 8kB, 64kbit, 1 page
RAM_32K: equ 0x03 ; 32kB, 256kbit, 4 pages
RAM_128K: equ 0x04 ; 128kB, 1Mbit, 16 pages
;;; Region Code
REGION_JAPAN: equ 0x00
REGION_OTHER: equ 0x01
rom_header: macro jump_target, color, sgb, cartridge, romsize, ramsize, region
section ROM_HEADER
nop ; 0x00
jp jump_target ; 0xc3 + xx xx
;; nintendo logo
db 0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B
db 0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D
db 0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E
db 0xDC, 0xCC, 0x6E, 0xE6, 0xDD, 0xDD, 0xD9, 0x99
db 0xBB, 0xBB, 0x67, 0x63, 0x6E, 0x0E, 0xEC, 0xCC
db 0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E
;; title, 15 ascii bytes
seek ROM_TITLE + 0xf
;; color compatibility
db color
;; manufacturer, 2 bytes
seek ROM_MANUFACTURER + 0x2
;; super game boy
db sgb
;; cartridge type
db cartridge
;; ROM size
db romsize
;; RAM size
db ramsize
;; region code
db region
;; old manufacturer code
;; this can be something other than 0x33 - nintendo / extended, but
;; it must be this for super game boy to work, so
db 0x33
;; mask rom version, usually 0
db 0x00
;; checksums, must be filled in later
;; complement checksum is computed by adding up everything from
;; the title to the mask rom version, & 0xff, then subtracting that
;; from 0xe7
db 0x00 ; complement checksum
db 0x00, 0x00 ; whole cart checksum
;; move our pointer ahead to pad out our output file
;; to agree with the given rom size
if romsize <= ROM_2M ; 2 * 2^rom pages
seek 0x4000 << (romsize + 1)
else
if romsize == ROM_1_1M ; 72 pages
seek 0x4000 * 72
endif
if romsize == ROM_1_2M ; 80 pages
seek 0x4000 * 80
endif
if romsize == ROM_1_5M ; 96 pages
seek 0x4000 * 96
endif
endif
;; and finally return our pointer to where it was
seek ROM_HEADER_END
org ROM_HEADER_END
endm
include "gboy-phantasm.inc"
section INT_VBLANK
reti
section INT_LCDC
reti
section INT_TIMER
reti
section INT_SERIAL
reti
section INT_P1THRU4
reti
section ROM_TITLE
db "Hello, world!"
section ROM_MANUFACTURER
db "AG"
rom_header begin, COLOR_OFF, SGB_OFF, CART_ROM, ROM_32K, RAM_NONE, REGION_OTHER
include "memory.asm"
include "fonts/PressStart2P.inc"
title: db "Hello,"
titleend:
subtitle: db "#overviewer!"
subtitleend:
begin:
;; disable interrupts and set up stack
di
ld sp, 0xffff
init:
;; set background palette to 11 / 10 / 01 / 00
ld a, 0b11100100
ld (rBGP), a
;; set x/y scroll registers to 0
ld a, 0
ld (rSCX), a
ld (rSCY), a
;; turn off the lcd
call stoplcd
;; write to VRAM
;; for mem_CopyMono, hl is source, de is dest, bc is length
ld hl, PressStart2P
ld de, VRAM
ld bc, PressStart2Pend - PressStart2P
call mem_CopyMono
;; turn the LCD on
ld a, LCDCF_ON|LCDCF_BG8000|LCDCF_BG9800|LCDCF_BGON|LCDCF_OBJ16|LCDCF_OBJOFF
ld (rLCDC), a
;; clear screen (0x20 - ascii space)
ld a, 0x20
ld hl, SCRN0
ld bc, SCRN_VX_B * SCRN_VY_B
call mem_SetVRAM
;; set our title
ld hl, title
ld de, SCRN0 + 7 + (SCRN_VY_B * 7)
ld bc, titleend - title
call mem_CopyVRAM
ld hl, subtitle
ld de, SCRN0 + 4 + (SCRN_VY_B * 8)
ld bc, subtitleend - subtitle
call mem_CopyVRAM
.wait:
;; do nothing, nicely
halt
nop
jr .wait
stoplcd:
ld a, (rLCDC)
rlca ; put high bit of LCDC into carry
ret nc ; screen is off => exit
.wait:
ld a, (rLY)
cp 145 ; are we at line 145 yet?
jr nz, .wait ; no, keep waiting
ld a, (rLCDC) ; yes!
res 7, a ; reset bit 7 of LCDC
ld (rLCDC), a
ret
;;; copy a monochrome font
;;; hl - source, de - dest, bc - bytecount
mem_CopyMono:
inc b
inc c
jr .skip
.loop:
ld a, (hli)
ld (de), a
inc de
ld (de), a
inc de
.skip:
dec c
jr nz, .loop
dec b
jr nz, .loop
ret
lcdwait: macro
ld a, (rSTAT) ; <---+
and STATF_BUSY ; |
jr nz, $ - 5 ; ----+
endm
;;; set a memory region in VRAM
;;; a - value, hl - dest, bc - bytecount
mem_SetVRAM:
inc b
inc c
jr .skip
.loop:
push af
di
lcdwait
pop af
ld (hli), a
ei
.skip:
dec c
jr nz, .loop
dec b
jr nz, .loop
ret
;;; copy a memory to or from VRAM
;;; hl - source, de - dest, bc - bytecount
mem_CopyVRAM:
inc b
inc c
jr .skip
.loop:
di
lcdwait
ld a, (hli)
ld (de), a
ei
inc de
.skip:
dec c
jr nz, .loop
dec b
jr nz, .loop
ret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment