;****************************************************************************** ; Game Boy hardware constant definitions ; https://github.com/gbdev/hardware.inc ;****************************************************************************** ; To the extent possible under law, the authors of this work have ; waived all copyright and related or neighboring rights to the work. ; See https://creativecommons.org/publicdomain/zero/1.0/ for details. ; SPDX-License-Identifier: CC0-1.0 ; If this file was already included, don't do it again if !def(HARDWARE_INC) ; Check for the minimum supported RGBDS version if !def(__RGBDS_MAJOR__) || !def(__RGBDS_MINOR__) || !def(__RGBDS_PATCH__) fail "This version of 'hardware.inc' requires RGBDS version 0.5.0 or later" endc if __RGBDS_MAJOR__ == 0 && __RGBDS_MINOR__ < 5 fail "This version of 'hardware.inc' requires RGBDS version 0.5.0 or later." endc ; Define the include guard and the current hardware.inc version ; (do this after the RGBDS version check since the `def` syntax depends on it) def HARDWARE_INC equ 1 def HARDWARE_INC_VERSION equs "5.3.0" ; Usage: rev_Check_hardware_inc <min_ver> ; Examples: ; rev_Check_hardware_inc 1.2.3 ; rev_Check_hardware_inc 1.2 (equivalent to 1.2.0) ; rev_Check_hardware_inc 1 (equivalent to 1.0.0) MACRO rev_Check_hardware_inc if _NARG == 1 ; Actual invocation by the user def hw_inc_cur_ver\@ equs strrpl("{HARDWARE_INC_VERSION}", ".", ",") def hw_inc_min_ver\@ equs strrpl("\1", ".", ",") rev_Check_hardware_inc {hw_inc_cur_ver\@}, {hw_inc_min_ver\@}, 0, 0 purge hw_inc_cur_ver\@, hw_inc_min_ver\@ else ; Recursive invocation if \1 != \4 || (\2 < \5 || (\2 == \5 && \3 < \6)) fail "Version \1.\2.\3 of 'hardware.inc' is incompatible with requested version \4.\5.\6" endc endc ENDM ;****************************************************************************** ; Memory-mapped registers ($FFxx range) ;****************************************************************************** ; -- JOYP / P1 ($FF00) -------------------------------------------------------- ; Joypad face buttons def rJOYP equ $FF00 def B_JOYP_GET_BUTTONS equ 5 ; 0 = reading buttons [r/w] def B_JOYP_GET_CTRL_PAD equ 4 ; 0 = reading Control Pad [r/w] def JOYP_GET equ %00_11_0000 ; select which inputs to read from the lower nybble def JOYP_GET_BUTTONS equ %00_01_0000 ; reading A/B/Select/Start buttons def JOYP_GET_CTRL_PAD equ %00_10_0000 ; reading Control Pad directions def JOYP_GET_NONE equ %00_11_0000 ; reading nothing def B_JOYP_START equ 3 ; 0 = Start is pressed (if reading buttons) [ro] def B_JOYP_SELECT equ 2 ; 0 = Select is pressed (if reading buttons) [ro] def B_JOYP_B equ 1 ; 0 = B is pressed (if reading buttons) [ro] def B_JOYP_A equ 0 ; 0 = A is pressed (if reading buttons) [ro] def B_JOYP_DOWN equ 3 ; 0 = Down is pressed (if reading Control Pad) [ro] def B_JOYP_UP equ 2 ; 0 = Up is pressed (if reading Control Pad) [ro] def B_JOYP_LEFT equ 1 ; 0 = Left is pressed (if reading Control Pad) [ro] def B_JOYP_RIGHT equ 0 ; 0 = Right is pressed (if reading Control Pad) [ro] def JOYP_INPUTS equ %0000_1111 ; bits equal to 0 indicate pressed (when reading inputs) def JOYP_START equ 1 << B_JOYP_START def JOYP_SELECT equ 1 << B_JOYP_SELECT def JOYP_B equ 1 << B_JOYP_B def JOYP_A equ 1 << B_JOYP_A def JOYP_DOWN equ 1 << B_JOYP_DOWN def JOYP_UP equ 1 << B_JOYP_UP def JOYP_LEFT equ 1 << B_JOYP_LEFT def JOYP_RIGHT equ 1 << B_JOYP_RIGHT ; SGB command packet transfer uses for JOYP bits def B_JOYP_SGB_ONE equ 5 ; 0 = sending 1 bit def B_JOYP_SGB_ZERO equ 4 ; 0 = sending 0 bit def JOYP_SGB_START equ %00_00_0000 ; start SGB packet transfer def JOYP_SGB_ONE equ %00_01_0000 ; send 1 bit def JOYP_SGB_ZERO equ %00_10_0000 ; send 0 bit def JOYP_SGB_FINISH equ %00_11_0000 ; finish SGB packet transfer ; Combined input byte, with Control Pad in high nybble (conventional order) def B_PAD_DOWN equ 7 def B_PAD_UP equ 6 def B_PAD_LEFT equ 5 def B_PAD_RIGHT equ 4 def B_PAD_START equ 3 def B_PAD_SELECT equ 2 def B_PAD_B equ 1 def B_PAD_A equ 0 def PAD_CTRL_PAD equ %1111_0000 def PAD_BUTTONS equ %0000_1111 def PAD_DOWN equ 1 << B_PAD_DOWN def PAD_UP equ 1 << B_PAD_UP def PAD_LEFT equ 1 << B_PAD_LEFT def PAD_RIGHT equ 1 << B_PAD_RIGHT def PAD_START equ 1 << B_PAD_START def PAD_SELECT equ 1 << B_PAD_SELECT def PAD_B equ 1 << B_PAD_B def PAD_A equ 1 << B_PAD_A ; Combined input byte, with Control Pad in low nybble (swapped order) def B_PAD_SWAP_START equ 7 def B_PAD_SWAP_SELECT equ 6 def B_PAD_SWAP_B equ 5 def B_PAD_SWAP_A equ 4 def B_PAD_SWAP_DOWN equ 3 def B_PAD_SWAP_UP equ 2 def B_PAD_SWAP_LEFT equ 1 def B_PAD_SWAP_RIGHT equ 0 def PAD_SWAP_CTRL_PAD equ %0000_1111 def PAD_SWAP_BUTTONS equ %1111_0000 def PAD_SWAP_START equ 1 << B_PAD_SWAP_START def PAD_SWAP_SELECT equ 1 << B_PAD_SWAP_SELECT def PAD_SWAP_B equ 1 << B_PAD_SWAP_B def PAD_SWAP_A equ 1 << B_PAD_SWAP_A def PAD_SWAP_DOWN equ 1 << B_PAD_SWAP_DOWN def PAD_SWAP_UP equ 1 << B_PAD_SWAP_UP def PAD_SWAP_LEFT equ 1 << B_PAD_SWAP_LEFT def PAD_SWAP_RIGHT equ 1 << B_PAD_SWAP_RIGHT ; -- SB ($FF01) --------------------------------------------------------------- ; Serial transfer data [r/w] def rSB equ $FF01 ; -- SC ($FF02) --------------------------------------------------------------- ; Serial transfer control def rSC equ $FF02 def B_SC_START equ 7 ; reading 1 = transfer in progress, writing 1 = start transfer [r/w] def B_SC_SPEED equ 1 ; (CGB only) 1 = use faster internal clock [r/w] def B_SC_SOURCE equ 0 ; 0 = use external clock ("slave"), 1 = use internal clock ("master") [r/w] def SC_START equ 1 << B_SC_START def SC_SPEED equ 1 << B_SC_SPEED def SC_SLOW equ 0 << B_SC_SPEED def SC_FAST equ 1 << B_SC_SPEED def SC_SOURCE equ 1 << B_SC_SOURCE def SC_EXTERNAL equ 0 << B_SC_SOURCE def SC_INTERNAL equ 1 << B_SC_SOURCE ; -- $FF03 is unused ---------------------------------------------------------- ; -- DIV ($FF04) -------------------------------------------------------------- ; Divider register [r/w] def rDIV equ $FF04 ; -- TIMA ($FF05) ------------------------------------------------------------- ; Timer counter [r/w] def rTIMA equ $FF05 ; -- TMA ($FF06) -------------------------------------------------------------- ; Timer modulo [r/w] def rTMA equ $FF06 ; -- TAC ($FF07) -------------------------------------------------------------- ; Timer control def rTAC equ $FF07 def B_TAC_START equ 2 ; enable incrementing TIMA [r/w] def TAC_STOP equ 0 << B_TAC_START def TAC_START equ 1 << B_TAC_START def TAC_CLOCK equ %000000_11 ; the frequency at which TIMA increments [r/w] def TAC_4KHZ equ %000000_00 ; every 256 M-cycles = ~4 KHz on DMG def TAC_262KHZ equ %000000_01 ; every 4 M-cycles = ~262 KHz on DMG def TAC_65KHZ equ %000000_10 ; every 16 M-cycles = ~65 KHz on DMG def TAC_16KHZ equ %000000_11 ; every 64 M-cycles = ~16 KHz on DMG ; -- $FF08-$FF0E are unused --------------------------------------------------- ; -- IF ($FF0F) --------------------------------------------------------------- ; Pending interrupts def rIF equ $FF0F def B_IF_JOYPAD equ 4 ; 1 = joypad interrupt is pending [r/w] def B_IF_SERIAL equ 3 ; 1 = serial interrupt is pending [r/w] def B_IF_TIMER equ 2 ; 1 = timer interrupt is pending [r/w] def B_IF_STAT equ 1 ; 1 = STAT interrupt is pending [r/w] def B_IF_VBLANK equ 0 ; 1 = VBlank interrupt is pending [r/w] def IF_JOYPAD equ 1 << B_IF_JOYPAD def IF_SERIAL equ 1 << B_IF_SERIAL def IF_TIMER equ 1 << B_IF_TIMER def IF_STAT equ 1 << B_IF_STAT def IF_VBLANK equ 1 << B_IF_VBLANK ; -- AUD1SWEEP / NR10 ($FF10) ------------------------------------------------- ; Audio channel 1 sweep def rAUD1SWEEP equ $FF10 def AUD1SWEEP_TIME equ %0_111_0000 ; how long between sweep iterations ; (in 128 Hz ticks, ~7.8 ms apart) [r/w] def B_AUD1SWEEP_DIR equ 3 ; sweep direction [r/w] def AUD1SWEEP_DIR equ 1 << B_AUD1SWEEP_DIR def AUD1SWEEP_UP equ 0 << B_AUD1SWEEP_DIR def AUD1SWEEP_DOWN equ 1 << B_AUD1SWEEP_DIR def AUD1SWEEP_SHIFT equ %00000_111 ; how much the period increases/decreases per iteration [r/w] ; -- AUD1LEN / NR11 ($FF11) --------------------------------------------------- ; Audio channel 1 length timer and duty cycle def rAUD1LEN equ $FF11 def AUD1LEN_DUTY equ %11_000000 ; ratio of time spent high vs. time spent low [r/w] def AUD1LEN_DUTY_12_5 equ %00_000000 ; 12.5% def AUD1LEN_DUTY_25 equ %01_000000 ; 25% def AUD1LEN_DUTY_50 equ %10_000000 ; 50% def AUD1LEN_DUTY_75 equ %11_000000 ; 75% def AUD1LEN_TIMER equ %00_111111 ; initial length timer (0-63) [wo] ; -- AUD1ENV / NR12 ($FF12) --------------------------------------------------- ; Audio channel 1 volume and envelope def rAUD1ENV equ $FF12 def AUD1ENV_INIT_VOLUME equ %1111_0000 ; initial volume [r/w] def B_AUD1ENV_DIR equ 3 ; direction of volume envelope [r/w] def AUD1ENV_DIR equ 1 << B_AUD1ENV_DIR def AUD1ENV_DOWN equ 0 << B_AUD1ENV_DIR def AUD1ENV_UP equ 1 << B_AUD1ENV_DIR def AUD1ENV_PACE equ %00000_111 ; how long between envelope iterations ; (in 64 Hz ticks, ~15.6 ms apart) [r/w] ; -- AUD1LOW / NR13 ($FF13) --------------------------------------------------- ; Audio channel 1 period (low 8 bits) [wo] def rAUD1LOW equ $FF13 ; -- AUD1HIGH / NR14 ($FF14) -------------------------------------------------- ; Audio channel 1 period (high 3 bits) and control def rAUD1HIGH equ $FF14 def B_AUD1HIGH_RESTART equ 7 ; 1 = restart the channel [wo] def B_AUD1HIGH_LEN_ENABLE equ 6 ; 1 = reset the channel after the length timer expires [r/w] def AUD1HIGH_RESTART equ 1 << B_AUD1HIGH_RESTART def AUD1HIGH_LENGTH_OFF equ 0 << B_AUD1HIGH_LEN_ENABLE def AUD1HIGH_LENGTH_ON equ 1 << B_AUD1HIGH_LEN_ENABLE def AUD1HIGH_PERIOD_HIGH equ %00000_111 ; upper 3 bits of the channel's period [r/w] ; -- $FF15 is unused ---------------------------------------------------------- ; -- AUD2LEN / NR21 ($FF16) --------------------------------------------------- ; Audio channel 2 length timer and duty cycle def rAUD2LEN equ $FF16 def AUD2LEN_DUTY equ %11_000000 ; ratio of time spent high vs. time spent low [r/w] def AUD2LEN_DUTY_12_5 equ %00_000000 ; 12.5% def AUD2LEN_DUTY_25 equ %01_000000 ; 25% def AUD2LEN_DUTY_50 equ %10_000000 ; 50% def AUD2LEN_DUTY_75 equ %11_000000 ; 75% def AUD2LEN_TIMER equ %00_111111 ; initial length timer (0-63) [wo] ; -- AUD2ENV / NR22 ($FF17) --------------------------------------------------- ; Audio channel 2 volume and envelope def rAUD2ENV equ $FF17 def AUD2ENV_INIT_VOLUME equ %1111_0000 ; initial volume [r/w] def B_AUD2ENV_DIR equ 3 ; direction of volume envelope [r/w] def AUD2ENV_DIR equ 1 << B_AUD2ENV_DIR def AUD2ENV_DOWN equ 0 << B_AUD2ENV_DIR def AUD2ENV_UP equ 1 << B_AUD2ENV_DIR def AUD2ENV_PACE equ %00000_111 ; how long between envelope iterations ; (in 64 Hz ticks, ~15.6 ms apart) [r/w] ; -- AUD2LOW / NR23 ($FF18) --------------------------------------------------- ; Audio channel 2 period (low 8 bits) [wo] def rAUD2LOW equ $FF18 ; -- AUD2HIGH / NR24 ($FF19) -------------------------------------------------- ; Audio channel 2 period (high 3 bits) and control def rAUD2HIGH equ $FF19 def B_AUD2HIGH_RESTART equ 7 ; 1 = restart the channel [wo] def B_AUD2HIGH_LEN_ENABLE equ 6 ; 1 = reset the channel after the length timer expires [r/w] def AUD2HIGH_RESTART equ 1 << B_AUD2HIGH_RESTART def AUD2HIGH_LENGTH_OFF equ 0 << B_AUD2HIGH_LEN_ENABLE def AUD2HIGH_LENGTH_ON equ 1 << B_AUD2HIGH_LEN_ENABLE def AUD2HIGH_PERIOD_HIGH equ %00000_111 ; upper 3 bits of the channel's period [r/w] ; -- AUD3ENA / NR30 ($FF1A) --------------------------------------------------- ; Audio channel 3 enable def rAUD3ENA equ $FF1A def B_AUD3ENA_ENABLE equ 7 ; 1 = channel is active [r/w] def AUD3ENA_OFF equ 0 << B_AUD3ENA_ENABLE def AUD3ENA_ON equ 1 << B_AUD3ENA_ENABLE ; -- AUD3LEN / NR31 ($FF1B) --------------------------------------------------- ; Audio channel 3 length timer [wo] def rAUD3LEN equ $FF1B ; -- AUD3LEVEL / NR32 ($FF1C) ------------------------------------------------- ; Audio channel 3 volume def rAUD3LEVEL equ $FF1C def AUD3LEVEL_VOLUME equ %0_11_00000 ; volume level [r/w] def AUD3LEVEL_MUTE equ %0_00_00000 ; 0% (muted) def AUD3LEVEL_100 equ %0_01_00000 ; 100% def AUD3LEVEL_50 equ %0_10_00000 ; 50% def AUD3LEVEL_25 equ %0_11_00000 ; 25% ; -- AUD3LOW / NR33 ($FF1D) --------------------------------------------------- ; Audio channel 3 period (low 8 bits) [wo] def rAUD3LOW equ $FF1D ; -- AUD3HIGH / NR34 ($FF1E) -------------------------------------------------- ; Audio channel 3 period (high 3 bits) and control def rAUD3HIGH equ $FF1E def B_AUD3HIGH_RESTART equ 7 ; 1 = restart the channel [wo] def B_AUD3HIGH_LEN_ENABLE equ 6 ; 1 = reset the channel after the length timer expires [r/w] def AUD3HIGH_RESTART equ 1 << B_AUD3HIGH_RESTART def AUD3HIGH_LENGTH_OFF equ 0 << B_AUD3HIGH_LEN_ENABLE def AUD3HIGH_LENGTH_ON equ 1 << B_AUD3HIGH_LEN_ENABLE def AUD3HIGH_PERIOD_HIGH equ %00000_111 ; upper 3 bits of the channel's period [r/w] ; -- $FF1F is unused ---------------------------------------------------------- ; -- AUD4LEN / NR41 ($FF20) --------------------------------------------------- ; Audio channel 4 length timer def rAUD4LEN equ $FF20 def AUD4LEN_TIMER equ %00_111111 ; initial length timer (0-63) [wo] ; -- AUD4ENV / NR42 ($FF21) --------------------------------------------------- ; Audio channel 4 volume and envelope def rAUD4ENV equ $FF21 def AUD4ENV_INIT_VOLUME equ %1111_0000 ; initial volume [r/w] def B_AUD4ENV_DIR equ 3 ; direction of volume envelope [r/w] def AUD4ENV_DIR equ 1 << B_AUD4ENV_DIR def AUD4ENV_DOWN equ 0 << B_AUD4ENV_DIR def AUD4ENV_UP equ 1 << B_AUD4ENV_DIR def AUD4ENV_PACE equ %00000_111 ; how long between envelope iterations ; (in 64 Hz ticks, ~15.6 ms apart) [r/w] ; -- AUD4POLY / NR43 ($FF22) -------------------------------------------------- ; Audio channel 4 period and randomness def rAUD4POLY equ $FF22 def AUD4POLY_SHIFT equ %1111_0000 ; coarse control of the channel's period [r/w] def B_AUD4POLY_WIDTH equ 3 ; controls the noise generator (LFSR)'s step width [r/w] def AUD4POLY_15STEP equ 0 << B_AUD4POLY_WIDTH def AUD4POLY_7STEP equ 1 << B_AUD4POLY_WIDTH def AUD4POLY_DIV equ %00000_111 ; fine control of the channel's period [r/w] ; -- AUD4GO / NR44 ($FF23) ---------------------------------------------------- ; Audio channel 4 control def rAUD4GO equ $FF23 def B_AUD4GO_RESTART equ 7 ; 1 = restart the channel [wo] def B_AUD4GO_LEN_ENABLE equ 6 ; 1 = reset the channel after the length timer expires [r/w] def AUD4GO_RESTART equ 1 << B_AUD4GO_RESTART def AUD4GO_LENGTH_OFF equ 0 << B_AUD4GO_LEN_ENABLE def AUD4GO_LENGTH_ON equ 1 << B_AUD4GO_LEN_ENABLE ; -- AUDVOL / NR50 ($FF24) ---------------------------------------------------- ; Audio master volume and VIN mixer def rAUDVOL equ $FF24 def B_AUDVOL_VIN_LEFT equ 7 ; 1 = output VIN to left ear (SO2, speaker 2) [r/w] def AUDVOL_VIN_LEFT equ 1 << B_AUDVOL_VIN_LEFT def AUDVOL_LEFT equ %0_111_0000 ; 0 = barely audible, 7 = full volume [r/w] def B_AUDVOL_VIN_RIGHT equ 3 ; 1 = output VIN to right ear (SO1, speaker 1) [r/w] def AUDVOL_VIN_RIGHT equ 1 << B_AUDVOL_VIN_RIGHT def AUDVOL_RIGHT equ %00000_111 ; 0 = barely audible, 7 = full volume [r/w] ; -- AUDTERM / NR51 ($FF25) --------------------------------------------------- ; Audio channel mixer def rAUDTERM equ $FF25 def B_AUDTERM_4_LEFT equ 7 ; 1 = output channel 4 to left ear [r/w] def B_AUDTERM_3_LEFT equ 6 ; 1 = output channel 3 to left ear [r/w] def B_AUDTERM_2_LEFT equ 5 ; 1 = output channel 2 to left ear [r/w] def B_AUDTERM_1_LEFT equ 4 ; 1 = output channel 1 to left ear [r/w] def B_AUDTERM_4_RIGHT equ 3 ; 1 = output channel 4 to right ear [r/w] def B_AUDTERM_3_RIGHT equ 2 ; 1 = output channel 3 to right ear [r/w] def B_AUDTERM_2_RIGHT equ 1 ; 1 = output channel 2 to right ear [r/w] def B_AUDTERM_1_RIGHT equ 0 ; 1 = output channel 1 to right ear [r/w] def AUDTERM_4_LEFT equ 1 << B_AUDTERM_4_LEFT def AUDTERM_3_LEFT equ 1 << B_AUDTERM_3_LEFT def AUDTERM_2_LEFT equ 1 << B_AUDTERM_2_LEFT def AUDTERM_1_LEFT equ 1 << B_AUDTERM_1_LEFT def AUDTERM_4_RIGHT equ 1 << B_AUDTERM_4_RIGHT def AUDTERM_3_RIGHT equ 1 << B_AUDTERM_3_RIGHT def AUDTERM_2_RIGHT equ 1 << B_AUDTERM_2_RIGHT def AUDTERM_1_RIGHT equ 1 << B_AUDTERM_1_RIGHT ; -- AUDENA / NR52 ($FF26) ---------------------------------------------------- ; Audio master enable def rAUDENA equ $FF26 def B_AUDENA_ENABLE equ 7 ; 0 = disable the APU (resets all audio registers to 0!) [r/w] def B_AUDENA_ENABLE_CH4 equ 3 ; 1 = channel 4 is running [ro] def B_AUDENA_ENABLE_CH3 equ 2 ; 1 = channel 3 is running [ro] def B_AUDENA_ENABLE_CH2 equ 1 ; 1 = channel 2 is running [ro] def B_AUDENA_ENABLE_CH1 equ 0 ; 1 = channel 1 is running [ro] def AUDENA_OFF equ 0 << B_AUDENA_ENABLE def AUDENA_ON equ 1 << B_AUDENA_ENABLE def AUDENA_CH4_OFF equ 0 << B_AUDENA_ENABLE_CH4 def AUDENA_CH4_ON equ 1 << B_AUDENA_ENABLE_CH4 def AUDENA_CH3_OFF equ 0 << B_AUDENA_ENABLE_CH3 def AUDENA_CH3_ON equ 1 << B_AUDENA_ENABLE_CH3 def AUDENA_CH2_OFF equ 0 << B_AUDENA_ENABLE_CH2 def AUDENA_CH2_ON equ 1 << B_AUDENA_ENABLE_CH2 def AUDENA_CH1_OFF equ 0 << B_AUDENA_ENABLE_CH1 def AUDENA_CH1_ON equ 1 << B_AUDENA_ENABLE_CH1 ; -- $FF27-$FF2F are unused --------------------------------------------------- ; -- AUD3WAVE ($FF30-$FF3F) --------------------------------------------------- ; Audio channel 3 wave pattern RAM [r/w] def rAUD3WAVE_0 equ $FF30 def rAUD3WAVE_1 equ $FF31 def rAUD3WAVE_2 equ $FF32 def rAUD3WAVE_3 equ $FF33 def rAUD3WAVE_4 equ $FF34 def rAUD3WAVE_5 equ $FF35 def rAUD3WAVE_6 equ $FF36 def rAUD3WAVE_7 equ $FF37 def rAUD3WAVE_8 equ $FF38 def rAUD3WAVE_9 equ $FF39 def rAUD3WAVE_A equ $FF3A def rAUD3WAVE_B equ $FF3B def rAUD3WAVE_C equ $FF3C def rAUD3WAVE_D equ $FF3D def rAUD3WAVE_E equ $FF3E def rAUD3WAVE_F equ $FF3F ; -- LCDC ($FF40) ------------------------------------------------------------- ; PPU graphics control def rLCDC equ $FF40 def B_LCDC_ENABLE equ 7 ; whether the PPU (and LCD) are turned on [r/w] def B_LCDC_WIN_MAP equ 6 ; which tilemap the Window reads from [r/w] def B_LCDC_WINDOW equ 5 ; whether the Window is enabled [r/w] def B_LCDC_BLOCKS equ 4 ; which "tile blocks" the BG and Window use [r/w] def B_LCDC_BG_MAP equ 3 ; which tilemap the BG reads from [r/w] def B_LCDC_OBJ_SIZE equ 2 ; how many pixels tall each OBJ is [r/w] def B_LCDC_OBJS equ 1 ; whether OBJs are enabled [r/w] def B_LCDC_BG equ 0 ; (DMG only) whether the BG is enabled [r/w] def B_LCDC_PRIO equ 0 ; (CGB only) whether OBJ priority bits are enabled [r/w] def LCDC_ENABLE equ 1 << B_LCDC_ENABLE def LCDC_OFF equ 0 << B_LCDC_ENABLE def LCDC_ON equ 1 << B_LCDC_ENABLE def LCDC_WIN_MAP equ 1 << B_LCDC_WIN_MAP def LCDC_WIN_9800 equ 0 << B_LCDC_WIN_MAP def LCDC_WIN_9C00 equ 1 << B_LCDC_WIN_MAP def LCDC_WINDOW equ 1 << B_LCDC_WINDOW def LCDC_WIN_OFF equ 0 << B_LCDC_WINDOW def LCDC_WIN_ON equ 1 << B_LCDC_WINDOW def LCDC_BLOCKS equ 1 << B_LCDC_BLOCKS def LCDC_BLOCK21 equ 0 << B_LCDC_BLOCKS def LCDC_BLOCK01 equ 1 << B_LCDC_BLOCKS def LCDC_BG_MAP equ 1 << B_LCDC_BG_MAP def LCDC_BG_9800 equ 0 << B_LCDC_BG_MAP def LCDC_BG_9C00 equ 1 << B_LCDC_BG_MAP def LCDC_OBJ_SIZE equ 1 << B_LCDC_OBJ_SIZE def LCDC_OBJ_8 equ 0 << B_LCDC_OBJ_SIZE def LCDC_OBJ_16 equ 1 << B_LCDC_OBJ_SIZE def LCDC_OBJS equ 1 << B_LCDC_OBJS def LCDC_OBJ_OFF equ 0 << B_LCDC_OBJS def LCDC_OBJ_ON equ 1 << B_LCDC_OBJS def LCDC_BG equ 1 << B_LCDC_BG def LCDC_BG_OFF equ 0 << B_LCDC_BG def LCDC_BG_ON equ 1 << B_LCDC_BG def LCDC_PRIO equ 1 << B_LCDC_PRIO def LCDC_PRIO_OFF equ 0 << B_LCDC_PRIO def LCDC_PRIO_ON equ 1 << B_LCDC_PRIO ; -- STAT ($FF41) ------------------------------------------------------------- ; Graphics status and interrupt control def rSTAT equ $FF41 def B_STAT_LYC equ 6 ; 1 = LY match triggers the STAT interrupt [r/w] def B_STAT_MODE_2 equ 5 ; 1 = OAM Scan triggers the PPU interrupt [r/w] def B_STAT_MODE_1 equ 4 ; 1 = VBlank triggers the PPU interrupt [r/w] def B_STAT_MODE_0 equ 3 ; 1 = HBlank triggers the PPU interrupt [r/w] def B_STAT_LYCF equ 2 ; 1 = LY is currently equal to LYC [ro] def B_STAT_BUSY equ 1 ; 1 = the PPU is currently accessing VRAM [ro] def STAT_LYC equ 1 << B_STAT_LYC def STAT_MODE_2 equ 1 << B_STAT_MODE_2 def STAT_MODE_1 equ 1 << B_STAT_MODE_1 def STAT_MODE_0 equ 1 << B_STAT_MODE_0 def STAT_LYCF equ 1 << B_STAT_LYCF def STAT_BUSY equ 1 << B_STAT_BUSY def STAT_MODE equ %000000_11 ; PPU's current status [ro] def STAT_HBLANK equ %000000_00 ; waiting after a line's rendering (HBlank) def STAT_VBLANK equ %000000_01 ; waiting between frames (VBlank) def STAT_OAM equ %000000_10 ; checking which OBJs will be rendered on this line (OAM scan) def STAT_LCD equ %000000_11 ; pushing pixels to the LCD ; -- SCY ($FF42) -------------------------------------------------------------- ; Background Y scroll offset (in pixels) [r/w] def rSCY equ $FF42 ; -- SCX ($FF43) -------------------------------------------------------------- ; Background X scroll offset (in pixels) [r/w] def rSCX equ $FF43 ; -- LY ($FF44) --------------------------------------------------------------- ; Y coordinate of the line currently processed by the PPU (0-153) [ro] def rLY equ $FF44 def LY_VBLANK equ 144 ; 144-153 is the VBlank period ; -- LYC ($FF45) -------------------------------------------------------------- ; Value that LY is constantly compared to [r/w] def rLYC equ $FF45 ; -- DMA ($FF46) -------------------------------------------------------------- ; OAM DMA start address (high 8 bits) and start [wo] def rDMA equ $FF46 ; -- BGP ($FF47) -------------------------------------------------------------- ; (DMG only) Background color mapping [r/w] def rBGP equ $FF47 def BGP_SGB_TRANSFER equ %11_10_01_00 ; set BGP to this value before SGB VRAM transfer ; -- OBP0 ($FF48) ------------------------------------------------------------- ; (DMG only) OBJ color mapping #0 [r/w] def rOBP0 equ $FF48 ; -- OBP1 ($FF49) ------------------------------------------------------------- ; (DMG only) OBJ color mapping #1 [r/w] def rOBP1 equ $FF49 ; -- WY ($FF4A) --------------------------------------------------------------- ; Y coordinate of the Window's top-left pixel (0-143) [r/w] def rWY equ $FF4A ; -- WX ($FF4B) --------------------------------------------------------------- ; X coordinate of the Window's top-left pixel, plus 7 (7-166) [r/w] def rWX equ $FF4B def WX_OFS equ 7 ; subtract this to get the actual Window X coordinate ; -- SYS / KEY0 ($FF4C) ------------------------------------------------------- ; (CGB boot ROM only) CPU mode select def rSYS equ $FF4C ; This is known as the "CPU mode register" in Fig. 11 of this patent: ; https://patents.google.com/patent/US6322447B1/en?oq=US6322447bi ; "OBJ priority mode designating register" in the same patent ; Credit to @mattcurrie for this finding! def SYS_MODE equ %0000_11_00 ; current system mode [r/w] def SYS_CGB equ %0000_00_00 ; CGB mode def SYS_DMG equ %0000_01_00 ; DMG compatibility mode def SYS_PGB1 equ %0000_10_00 ; LCD is driven externally, CPU is stopped def SYS_PGB2 equ %0000_11_00 ; LCD is driven externally, CPU is running ; -- SPD / KEY1 ($FF4D) ------------------------------------------------------- ; (CGB only) Double-speed mode control def rSPD equ $FF4D def B_SPD_DOUBLE equ 7 ; current clock speed [ro] def B_SPD_PREPARE equ 0 ; 1 = next `stop` instruction will switch clock speeds [r/w] def SPD_SINGLE equ 0 << B_SPD_DOUBLE def SPD_DOUBLE equ 1 << B_SPD_DOUBLE def SPD_PREPARE equ 1 << B_SPD_PREPARE ; -- $FF4E is unused ---------------------------------------------------------- ; -- VBK ($FF4F) -------------------------------------------------------------- ; (CGB only) VRAM bank number (0 or 1) def rVBK equ $FF4F def VBK_BANK equ %0000000_1 ; mapped VRAM bank [r/w] ; -- BANK ($FF50) ------------------------------------------------------------- ; (boot ROM only) Boot ROM mapping control def rBANK equ $FF50 def B_BANK_ON equ 0 ; whether the boot ROM is mapped [wo] def BANK_ON equ 0 << B_BANK_ON def BANK_OFF equ 1 << B_BANK_ON ; -- VDMA_SRC_HIGH / HDMA1 ($FF51) -------------------------------------------- ; (CGB only) VRAM DMA source address (high 8 bits) [wo] def rVDMA_SRC_HIGH equ $FF51 ; -- VDMA_SRC_LOW / HDMA2 ($FF52) --------------------------------------------- ; (CGB only) VRAM DMA source address (low 8 bits) [wo] def rVDMA_SRC_LOW equ $FF52 ; -- VDMA_DEST_HIGH / HDMA3 ($FF53) ------------------------------------------- ; (CGB only) VRAM DMA destination address (high 8 bits) [wo] def rVDMA_DEST_HIGH equ $FF53 ; -- VDMA_DEST_LOW / HDMA4 ($FF54) -------------------------------------------- ; (CGB only) VRAM DMA destination address (low 8 bits) [wo] def rVDMA_DEST_LOW equ $FF54 ; -- VDMA_LEN / HDMA5 ($FF55) ------------------------------------------------- ; (CGB only) VRAM DMA length, mode, and start def rVDMA_LEN equ $FF55 def B_VDMA_LEN_MODE equ 7 ; on write: VRAM DMA mode [wo] def VDMA_LEN_MODE equ 1 << B_VDMA_LEN_MODE def VDMA_LEN_MODE_GENERAL equ 0 << B_VDMA_LEN_MODE ; GDMA (general-purpose) def VDMA_LEN_MODE_HBLANK equ 1 << B_VDMA_LEN_MODE ; HDMA (HBlank) def B_VDMA_LEN_BUSY equ 7 ; on read: is a VRAM DMA active? def VDMA_LEN_BUSY equ 1 << B_VDMA_LEN_BUSY def VDMA_LEN_NO equ 0 << B_VDMA_LEN_BUSY def VDMA_LEN_YES equ 1 << B_VDMA_LEN_BUSY def VDMA_LEN_SIZE equ %0_1111111 ; how many 16-byte blocks (minus 1) to transfer [r/w] ; -- RP ($FF56) --------------------------------------------------------------- ; (CGB only) Infrared communications port def rRP equ $FF56 def RP_READ equ %11_000000 ; whether the IR read is enabled [r/w] def RP_DISABLE equ %00_000000 def RP_ENABLE equ %11_000000 def B_RP_DATA_IN equ 1 ; 0 = IR light is being received [ro] def B_RP_LED_ON equ 0 ; 1 = IR light is being sent [r/w] def RP_DATA_IN equ 1 << B_RP_DATA_IN def RP_LED_ON equ 1 << B_RP_LED_ON def RP_WRITE_LOW equ 0 << B_RP_LED_ON def RP_WRITE_HIGH equ 1 << B_RP_LED_ON ; -- $FF57-$FF67 are unused --------------------------------------------------- ; -- BGPI / BCPS ($FF68) ------------------------------------------------------ ; (CGB only) Background palette I/O index def rBGPI equ $FF68 def B_BGPI_AUTOINC equ 7 ; whether the index field is incremented after each write to BCPD [r/w] def BGPI_AUTOINC equ 1 << B_BGPI_AUTOINC def BGPI_INDEX equ %00_111111 ; the index within Palette RAM accessed via BCPD [r/w] ; -- BGPD / BCPD ($FF69) ------------------------------------------------------ ; (CGB only) Background palette I/O access [r/w] def rBGPD equ $FF69 ; -- OBPI / OCPS ($FF6A) ------------------------------------------------------ ; (CGB only) OBJ palette I/O index def rOBPI equ $FF6A def B_OBPI_AUTOINC equ 7 ; whether the index field is incremented after each write to OBPD [r/w] def OBPI_AUTOINC equ 1 << B_OBPI_AUTOINC def OBPI_INDEX equ %00_111111 ; the index within Palette RAM accessed via OBPD [r/w] ; -- OBPD / OCPD ($FF6B) ------------------------------------------------------ ; (CGB only) OBJ palette I/O access [r/w] def rOBPD equ $FF6B ; -- OPRI ($FF6C) ------------------------------------------------------------- ; (CGB boot ROM only) OBJ draw priority mode def rOPRI equ $FF6C def B_OPRI_PRIORITY equ 0 ; which drawing priority is used for OBJs [r/w] def OPRI_PRIORITY equ 1 << B_OPRI_PRIORITY def OPRI_OAM equ 0 << B_OPRI_PRIORITY ; CGB mode default: earliest OBJ in OAM wins def OPRI_COORD equ 1 << B_OPRI_PRIORITY ; DMG mode default: leftmost OBJ wins ; -- $FF6D-$FF6F are unused --------------------------------------------------- ; -- WBK / SVBK ($FF70) ------------------------------------------------------- ; (CGB only) WRAM bank number def rWBK equ $FF70 def WBK_BANK equ %00000_111 ; mapped WRAM bank (0-7) [r/w] ; -- $FF71-$FF75 are unused --------------------------------------------------- ; -- PCM12 ($FF76) ------------------------------------------------------------ ; Audio channels 1 and 2 output def rPCM12 equ $FF76 def PCM12_CH2 equ %1111_0000 ; audio channel 2 output [ro] def PCM12_CH1 equ %0000_1111 ; audio channel 1 output [ro] ; -- PCM34 ($FF77) ------------------------------------------------------------ ; Audio channels 3 and 4 output def rPCM34 equ $FF77 def PCM34_CH4 equ %1111_0000 ; audio channel 4 output [ro] def PCM34_CH3 equ %0000_1111 ; audio channel 3 output [ro] ; -- $FF78-$FF7F are unused --------------------------------------------------- ; -- IE ($FFFF) --------------------------------------------------------------- ; Interrupt enable def rIE equ $FFFF def B_IE_JOYPAD equ 4 ; 1 = joypad interrupt is enabled [r/w] def B_IE_SERIAL equ 3 ; 1 = serial interrupt is enabled [r/w] def B_IE_TIMER equ 2 ; 1 = timer interrupt is enabled [r/w] def B_IE_STAT equ 1 ; 1 = STAT interrupt is enabled [r/w] def B_IE_VBLANK equ 0 ; 1 = VBlank interrupt is enabled [r/w] def IE_JOYPAD equ 1 << B_IE_JOYPAD def IE_SERIAL equ 1 << B_IE_SERIAL def IE_TIMER equ 1 << B_IE_TIMER def IE_STAT equ 1 << B_IE_STAT def IE_VBLANK equ 1 << B_IE_VBLANK ;****************************************************************************** ; Cartridge registers (MBC) ;****************************************************************************** ; Note that these "registers" are each actually accessible at an entire address range; ; however, one address for each of these ranges is considered the "canonical" one, and ; these addresses are what's provided here. ; ** Common to most MBCs ****************************************************** ; -- RAMG ($0000-$1FFF) ------------------------------------------------------- ; Whether SRAM can be accessed [wo] def rRAMG equ $0000 ; Common values (not for HuC1 or HuC-3) def RAMG_SRAM_DISABLE equ $00 def RAMG_SRAM_ENABLE equ $0A ; some MBCs accept any value whose low nybble is $A ; (HuC-3 only) switch SRAM to map cartridge RAM, RTC, or IR def RAMG_CART_RAM_RO equ $00 ; select cartridge RAM [ro] def RAMG_CART_RAM equ $0A ; select cartridge RAM [r/w] def RAMG_RTC_IN equ $0B ; select RTC command/argument [wo] def RAMG_RTC_IN_CMD equ %0_111_0000 ; command def RAMG_RTC_IN_ARG equ %0_000_1111 ; argument def RAMG_RTC_OUT equ $0C ; select RTC command/response [ro] def RAMG_RTC_OUT_CMD equ %0_111_0000 ; command def RAMG_RTC_OUT_RESULT equ %0_000_1111 ; result def RAMG_RTC_SEMAPHORE equ $0D ; select RTC semaphore [r/w] def RAMG_IR equ $0E ; (HuC1 and HuC-3 only) select IR [r/w] ; -- ROMB ($2000-$3FFF) ------------------------------------------------------- ; ROM bank number (not for MBC5 or MBC6) [wo] def rROMB equ $2000 ; -- RAMB ($4000-$5FFF) ------------------------------------------------------- ; SRAM bank number (not for MBC2, MBC6, or MBC7) [wo] def rRAMB equ $4000 ; (MBC3 only) Special RAM bank numbers that actually map values into RTCREG def RAMB_RTC_S equ $08 ; seconds counter (0-59) def RAMB_RTC_M equ $09 ; minutes counter (0-59) def RAMB_RTC_H equ $0A ; hours counter (0-23) def RAMB_RTC_DL equ $0B ; days counter, low byte (0-255) def RAMB_RTC_DH equ $0C ; days counter, high bit and other flags def B_RAMB_RTC_DH_CARRY equ 7 ; 1 = days counter overflowed [wo] def B_RAMB_RTC_DH_HALT equ 6 ; 0 = run timer, 1 = stop timer [wo] def B_RAMB_RTC_DH_HIGH equ 0 ; days counter, high bit (bit 8) [wo] def RAMB_RTC_DH_CARRY equ 1 << B_RAMB_RTC_DH_CARRY def RAMB_RTC_DH_HALT equ 1 << B_RAMB_RTC_DH_HALT def RAMB_RTC_DH_HIGH equ 1 << B_RAMB_RTC_DH_HIGH def B_RAMB_RUMBLE equ 3 ; (MBC5 and MBC7 only) enable the rumble motor (if any) def RAMB_RUMBLE equ 1 << B_RAMB_RUMBLE def RAMB_RUMBLE_OFF equ 0 << B_RAMB_RUMBLE def RAMB_RUMBLE_ON equ 1 << B_RAMB_RUMBLE ; ** MBC1 and MMM01 only ****************************************************** ; -- BMODE ($6000-$7FFF) ------------------------------------------------------ ; Banking mode select [wo] def rBMODE equ $6000 def BMODE_SIMPLE equ $00 ; locks ROMB and RAMB to bank 0 def BMODE_ADVANCED equ $01 ; allows bank-switching with RAMB ; ** MBC2 only **************************************************************** ; -- ROM2B ($0000-$3FFF with bit 8 set) --------------------------------------- ; ROM bank number [wo] def rROM2B equ $2100 ; ** MBC3 only **************************************************************** ; -- RTCLATCH ($6000-$7FFF) --------------------------------------------------- ; RTC latch clock data [wo] def rRTCLATCH equ $6000 ; Write $00 then $01 to latch the current time into RTCREG def RTCLATCH_START equ $00 def RTCLATCH_FINISH equ $01 ; -- RTCREG ($A000-$BFFF) ----------------------------------------------------- ; RTC register [r/w] def rRTCREG equ $A000 ; ** MBC5 only **************************************************************** ; -- ROMB0 ($2000-$2FFF) ------------------------------------------------------ ; ROM bank number low byte (bits 0-7) [wo] def rROMB0 equ $2000 ; -- ROMB1 ($3000-$3FFF) ------------------------------------------------------ ; ROM bank number high bit (bit 8) [wo] def rROMB1 equ $3000 ; ** MBC6 only **************************************************************** ; -- RAMBA ($0400-$07FF) ------------------------------------------------------ ; RAM bank A number [wo] def rRAMBA equ $0400 ; -- RAMBB ($0800-$0BFF) ------------------------------------------------------ ; RAM bank B number [wo] def rRAMBB equ $0800 ; -- FLASH ($0C00-$0FFF) ------------------------------------------------------ ; Whether the flash chip can be accessed [wo] def rFLASH equ $0C00 ; -- FMODE ($1000) ------------------------------------------------------------ ; Write mode select for the flash chip def rFMODE equ $1000 ; -- ROMBA ($2000-$27FF) ------------------------------------------------------ ; ROM/Flash bank A number [wo] def rROMBA equ $2000 ; -- FLASHA ($2800-$2FFF) ----------------------------------------------------- ; ROM/Flash bank A select [wo] def rFLASHA equ $2800 ; -- ROMBB ($3000-$37FF) ------------------------------------------------------ ; ROM/Flash bank B number [wo] def rROMBB equ $3000 ; -- FLASHB ($3800-$3FFF) ----------------------------------------------------- ; ROM/Flash bank B select [wo] def rFLASHB equ $3800 ; ** MBC7 only **************************************************************** ; -- RAMREG ($4000-$5FFF) ----------------------------------------------------- ; Enable RAM register access [wo] def rRAMREG equ $4000 def RAMREG_ENABLE equ $40 ; -- ACCLATCH0 ($Ax0x) -------------------------------------------------------- ; Latch accelerometer start [wo] def rACCLATCH0 equ $A000 ; Write $55 to ACCLATCH0 to erase the latched data def ACCLATCH0_START equ $55 ; -- ACCLATCH1 ($Ax1x) -------------------------------------------------------- ; Latch accelerometer finish [wo] def rACCLATCH1 equ $A010 ; Write $AA to ACCLATCH1 to latch the accelerometer and update ACCEL* def ACCLATCH1_FINISH equ $AA ; -- ACCELX0 ($Ax2x) ---------------------------------------------------------- ; Accelerometer X value low byte [ro] def rACCELX0 equ $A020 ; -- ACCELX1 ($Ax3x) ---------------------------------------------------------- ; Accelerometer X value high byte [ro] def rACCELX1 equ $A030 ; -- ACCELY0 ($Ax4x) ---------------------------------------------------------- ; Accelerometer Y value low byte [ro] def rACCELY0 equ $A040 ; -- ACCELY1 ($Ax5x) ---------------------------------------------------------- ; Accelerometer Y value high byte [ro] def rACCELY1 equ $A050 ; -- EEPROM ($Ax8x) ----------------------------------------------------------- ; EEPROM access [r/w] def rEEPROM equ $A080 ; ** HuC1 only **************************************************************** ; -- IRREG ($A000-$BFFF) ------------------------------------------------------ ; IR register [r/w] def rIRREG equ $A000 ; whether the IR transmitter sees light def IR_LED_OFF equ $C0 def IR_LED_ON equ $C1 ;****************************************************************************** ; Screen-related constants ;****************************************************************************** def SCREEN_WIDTH_PX equ 160 ; width of screen in pixels def SCREEN_HEIGHT_PX equ 144 ; height of screen in pixels def SCREEN_WIDTH equ 20 ; width of screen in bytes def SCREEN_HEIGHT equ 18 ; height of screen in bytes def SCREEN_AREA equ SCREEN_WIDTH * SCREEN_HEIGHT ; size of screen in bytes def TILEMAP_WIDTH_PX equ 256 ; width of tilemap in pixels def TILEMAP_HEIGHT_PX equ 256 ; height of tilemap in pixels def TILEMAP_WIDTH equ 32 ; width of tilemap in bytes def TILEMAP_HEIGHT equ 32 ; height of tilemap in bytes def TILEMAP_AREA equ TILEMAP_WIDTH * TILEMAP_HEIGHT ; size of tilemap in bytes def TILE_WIDTH equ 8 ; width of tile in pixels def TILE_HEIGHT equ 8 ; height of tile in pixels def TILE_SIZE equ 16 ; size of tile in bytes (2 bits/pixel) def COLOR_SIZE equ 2 ; size of color in bytes (little-endian BGR555) def PAL_COLORS equ 4 ; colors per palette def PAL_SIZE equ COLOR_SIZE * PAL_COLORS ; size of palette in bytes def COLOR_CH_WIDTH equ 5 ; bits per RGB color channel def COLOR_CH_MAX equ (1 << COLOR_CH_WIDTH) - 1 def B_COLOR_RED equ COLOR_CH_WIDTH * 0 ; bits 4-0 def B_COLOR_GREEN equ COLOR_CH_WIDTH * 1 ; bits 9-5 def B_COLOR_BLUE equ COLOR_CH_WIDTH * 2 ; bits 14-10 def COLOR_RED equ %000_11111 ; for the low byte def COLOR_GREEN_LOW equ %111_00000 ; for the low byte def COLOR_GREEN_HIGH equ %0_00000_11 ; for the high byte def COLOR_BLUE equ %0_11111_00 ; for the high byte ; (DMG only) grayscale shade indexes for BGP, OBP0, and OBP1 def SHADE_WHITE equ %00 def SHADE_LIGHT equ %01 def SHADE_DARK equ %10 def SHADE_BLACK equ %11 ; Tilemaps the BG or Window can read from (controlled by LCDC) def TILEMAP0 equ $9800 ; $9800-$9BFF def TILEMAP1 equ $9C00 ; $9C00-$9FFF ; (CGB only) BG tile attribute fields def B_BG_PRIO equ 7 ; whether the BG tile colors 1-3 are drawn above OBJs def B_BG_YFLIP equ 6 ; whether the whole BG tile is flipped vertically def B_BG_XFLIP equ 5 ; whether the whole BG tile is flipped horizontally def B_BG_BANK1 equ 3 ; which VRAM bank the BG tile is taken from def BG_PALETTE equ %00000_111 ; which palette the BG tile uses def BG_PRIO equ 1 << B_BG_PRIO def BG_YFLIP equ 1 << B_BG_YFLIP def BG_XFLIP equ 1 << B_BG_XFLIP def BG_BANK0 equ 0 << B_BG_BANK1 def BG_BANK1 equ 1 << B_BG_BANK1 ;****************************************************************************** ; OBJ-related constants ;****************************************************************************** ; OAM attribute field offsets rsreset def OAMA_Y rb ; 0 def OAM_Y_OFS equ 16 ; subtract 16 from what's written to OAM to get the real Y position def OAMA_X rb ; 1 def OAM_X_OFS equ 8 ; subtract 8 from what's written to OAM to get the real X position def OAMA_TILEID rb ; 2 def OAMA_FLAGS rb ; 3 def B_OAM_PRIO equ 7 ; whether the OBJ is drawn below BG colors 1-3 def B_OAM_YFLIP equ 6 ; whether the whole OBJ is flipped vertically def B_OAM_XFLIP equ 5 ; whether the whole OBJ is flipped horizontally def B_OAM_PAL1 equ 4 ; (DMG only) which of the two palettes the OBJ uses def B_OAM_BANK1 equ 3 ; (CGB only) which VRAM bank the OBJ takes its tile(s) from def OAM_PALETTE equ %00000_111 ; (CGB only) which palette the OBJ uses def OAM_PRIO equ 1 << B_OAM_PRIO def OAM_YFLIP equ 1 << B_OAM_YFLIP def OAM_XFLIP equ 1 << B_OAM_XFLIP def OAM_PAL0 equ 0 << B_OAM_PAL1 def OAM_PAL1 equ 1 << B_OAM_PAL1 def OAM_BANK0 equ 0 << B_OAM_BANK1 def OAM_BANK1 equ 1 << B_OAM_BANK1 def OBJ_SIZE rb 0 ; size of OBJ in bytes = 4 def OAM_COUNT equ 40 ; how many OBJs there are room for in OAM def OAM_SIZE equ OBJ_SIZE * OAM_COUNT ;****************************************************************************** ; Audio channel RAM addresses ;****************************************************************************** def AUD1RAM equ $FF10 ; $FF10-$FF14 def AUD2RAM equ $FF15 ; $FF15-$FF19 def AUD3RAM equ $FF1A ; $FF1A-$FF1E def AUD4RAM equ $FF1F ; $FF1F-$FF23 def AUDRAM_SIZE equ 5 ; size of each audio channel RAM in bytes def _AUD3WAVERAM equ $FF30 ; $FF30-$FF3F def AUD3WAVE_SIZE equ 16 ; size of wave pattern RAM in bytes ;****************************************************************************** ; Interrupt vector addresses ;****************************************************************************** def INT_HANDLER_VBLANK equ $0040 ; VBlank interrupt handler address def INT_HANDLER_STAT equ $0048 ; STAT interrupt handler address def INT_HANDLER_TIMER equ $0050 ; timer interrupt handler address def INT_HANDLER_SERIAL equ $0058 ; serial interrupt handler address def INT_HANDLER_JOYPAD equ $0060 ; joypad interrupt handler address ;****************************************************************************** ; Boot-up register values ;****************************************************************************** ; Register A = CPU type def BOOTUP_A_DMG equ $01 def BOOTUP_A_CGB equ $11 ; CGB or AGB def BOOTUP_A_MGB equ $FF def BOOTUP_A_SGB equ BOOTUP_A_DMG def BOOTUP_A_SGB2 equ BOOTUP_A_MGB ; Register B = CPU qualifier (if A is BOOTUP_A_CGB) def B_BOOTUP_B_AGB equ 0 def BOOTUP_B_CGB equ 0 << B_BOOTUP_B_AGB def BOOTUP_B_AGB equ 1 << B_BOOTUP_B_AGB ; Register C = CPU qualifier def BOOTUP_C_DMG equ $13 def BOOTUP_C_SGB equ $14 def BOOTUP_C_CGB equ $00 ; CGB or AGB ; Register D = color qualifier def BOOTUP_D_MONO equ $00 ; DMG, MGB, SGB, or CGB or AGB in DMG mode def BOOTUP_D_COLOR equ $FF ; CGB or AGB ; Register E = CPU qualifier (distinguishes DMG variants) def BOOTUP_E_DMG0 equ $C1 def BOOTUP_E_DMG equ $C8 def BOOTUP_E_SGB equ $00 def BOOTUP_E_CGB_DMGMODE equ $08 ; CGB or AGB in DMG mode def BOOTUP_E_CGB equ $56 ; CGB or AGB ;****************************************************************************** ; Aliases ;****************************************************************************** ; Prefer the standard names to these aliases, which may be official but are ; less directly meaningful or human-readable. def rP1 equ rJOYP def rNR10 equ rAUD1SWEEP def rNR11 equ rAUD1LEN def rNR12 equ rAUD1ENV def rNR13 equ rAUD1LOW def rNR14 equ rAUD1HIGH def rNR21 equ rAUD2LEN def rNR22 equ rAUD2ENV def rNR23 equ rAUD2LOW def rNR24 equ rAUD2HIGH def rNR30 equ rAUD3ENA def rNR31 equ rAUD3LEN def rNR32 equ rAUD3LEVEL def rNR33 equ rAUD3LOW def rNR34 equ rAUD3HIGH def rNR41 equ rAUD4LEN def rNR42 equ rAUD4ENV def rNR43 equ rAUD4POLY def rNR44 equ rAUD4GO def rNR50 equ rAUDVOL def rNR51 equ rAUDTERM def rNR52 equ rAUDENA def rKEY0 equ rSYS def rKEY1 equ rSPD def rHDMA1 equ rVDMA_SRC_HIGH def rHDMA2 equ rVDMA_SRC_LOW def rHDMA3 equ rVDMA_DEST_HIGH def rHDMA4 equ rVDMA_DEST_LOW def rHDMA5 equ rVDMA_LEN def rBCPS equ rBGPI def rBCPD equ rBGPD def rOCPS equ rOBPI def rOCPD equ rOBPD def rSVBK equ rWBK endc ; HARDWARE_INC