Created
May 13, 2025 00:23
-
-
Save ISSOtm/2e3e8a7fa7517ac4d803438f441dcc40 to your computer and use it in GitHub Desktop.
Attempting a reformat of hardware.inc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; ***************************************************************************** | |
; Game Boy hardware constant definitions | |
; ***************************************************************************** | |
; 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.0.0" | |
; Usage: check_hardware_inc_version <min_ver> | |
; Example: check_hardware_inc_version 5.0 | |
MACRO check_hardware_inc_version | |
def hardware_inc_cur_ver\@ equs strrpl("{HARDWARE_INC_VERSION}", ".", ",") | |
def hardware_inc_min_ver\@ equs strrpl("\1", ".", ",") | |
def hardware_inc_define_check\@ equs """MACRO hardware_inc_internal_check\@ | |
if (\\1) < (\\4) || ((\1) == (\\4) && ((\\2) < (\\5) || ((\\2) == (\\5) && (\\3) < (\\6)))) | |
fail "Version \\1.\\2.\\3 of 'hardware.inc' is incompatible with minimum version \\4.\\5.\\6" | |
endc | |
\nENDM""" | |
hardware_inc_define_check\@ | |
hardware_inc_internal_check\@ {hardware_inc_cur_ver\@}, {hardware_inc_min_ver\@}, 0, 0 | |
purge hardware_inc_cur_ver\@, hardware_inc_min_ver\@, hardware_inc_define_check\@, hardware_inc_internal_check\@ | |
ENDM | |
; ----------------------------------------------------------------------------- | |
; JOYPAD ($FF00): Face buttons | |
; | |
; - Bit 5-4 = which set of four inputs to read [r/w] | |
; - Bit 3-0 = the four inputs being read (0 = pressed) [ro] | |
; ----------------------------------------------------------------------------- | |
def rJoypad equ $ff00 | |
def BIT_JOYPAD_CTRL_PAD equ 5 ; 0 = reading buttons [r/w] | |
def BIT_JOYPAD_BUTTONS equ 4 ; 0 = reading Control Pad [r/w] | |
def BIT_JOYPAD_START equ 3 ; 0 = Start is pressed (if reading buttons) [ro] | |
def BIT_JOYPAD_SELECT equ 2 ; 0 = Select is pressed (if reading buttons) [ro] | |
def BIT_JOYPAD_B equ 1 ; 0 = B is pressed (if reading buttons) [ro] | |
def BIT_JOYPAD_A equ 0 ; 0 = A is pressed (if reading buttons) [ro] | |
def BIT_JOYPAD_DOWN equ 3 ; 0 = Down is pressed (if reading Control Pad) [ro] | |
def BIT_JOYPAD_UP equ 2 ; 0 = Up is pressed (if reading Control Pad) [ro] | |
def BIT_JOYPAD_LEFT equ 1 ; 0 = Left is pressed (if reading Control Pad) [ro] | |
def BIT_JOYPAD_RIGHT equ 0 ; 0 = Right is pressed (if reading Control Pad) [ro] | |
def MASK_JOYPAD_GET equ %00_11_0000 | |
def JOYPAD_GET_BUTTONS equ %00_01_0000 ; read A/B/Select/Start buttons | |
def JOYPAD_GET_CTRL_PAD equ %00_10_0000 ; read Control Pad directions | |
def JOYPAD_GET_NONE equ %00_11_0000 ; read nothing | |
def MASK_JOYPAD_INPUTS equ %0000_1111 | |
def JOYPAD_START equ 1 << BIT_JOYPAD_START | |
def JOYPAD_SELECT equ 1 << BIT_JOYPAD_SELECT | |
def JOYPAD_B equ 1 << BIT_JOYPAD_B | |
def JOYPAD_A equ 1 << BIT_JOYPAD_A | |
def JOYPAD_DOWN equ 1 << BIT_JOYPAD_DOWN | |
def JOYPAD_UP equ 1 << BIT_JOYPAD_UP | |
def JOYPAD_LEFT equ 1 << BIT_JOYPAD_LEFT | |
def JOYPAD_RIGHT equ 1 << BIT_JOYPAD_RIGHT | |
; Combined input byte, with Control Pad in high nybble (conventional) | |
def BIT_INPUT_DOWN equ BIT_JOYPAD_DOWN + 4 | |
def BIT_INPUT_UP equ BIT_JOYPAD_UP + 4 | |
def BIT_INPUT_LEFT equ BIT_JOYPAD_LEFT + 4 | |
def BIT_INPUT_RIGHT equ BIT_JOYPAD_RIGHT + 4 | |
def BIT_INPUT_START equ BIT_JOYPAD_START | |
def BIT_INPUT_SELECT equ BIT_JOYPAD_SELECT | |
def BIT_INPUT_B equ BIT_JOYPAD_B | |
def BIT_INPUT_A equ BIT_JOYPAD_A | |
def INPUT_DOWN equ 1 << BIT_INPUT_DOWN | |
def INPUT_UP equ 1 << BIT_INPUT_UP | |
def INPUT_LEFT equ 1 << BIT_INPUT_LEFT | |
def INPUT_RIGHT equ 1 << BIT_INPUT_RIGHT | |
def INPUT_START equ 1 << BIT_INPUT_START | |
def INPUT_SELECT equ 1 << BIT_INPUT_SELECT | |
def INPUT_B equ 1 << BIT_INPUT_B | |
def INPUT_A equ 1 << BIT_INPUT_A | |
; Combined input byte, with Control Pad in low nybble (swapped) | |
def BIT_INPUT_SWAP_START equ BIT_JOYPAD_START + 4 | |
def BIT_INPUT_SWAP_SELECT equ BIT_JOYPAD_SELECT + 4 | |
def BIT_INPUT_SWAP_B equ BIT_JOYPAD_B + 4 | |
def BIT_INPUT_SWAP_A equ BIT_JOYPAD_A + 4 | |
def BIT_INPUT_SWAP_DOWN equ BIT_JOYPAD_DOWN | |
def BIT_INPUT_SWAP_UP equ BIT_JOYPAD_UP | |
def BIT_INPUT_SWAP_LEFT equ BIT_JOYPAD_LEFT | |
def BIT_INPUT_SWAP_RIGHT equ BIT_JOYPAD_RIGHT | |
def INPUT_SWAP_START equ 1 << BIT_INPUT_SWAP_START | |
def INPUT_SWAP_SELECT equ 1 << BIT_INPUT_SWAP_SELECT | |
def INPUT_SWAP_B equ 1 << BIT_INPUT_SWAP_B | |
def INPUT_SWAP_A equ 1 << BIT_INPUT_SWAP_A | |
def INPUT_SWAP_DOWN equ 1 << BIT_INPUT_SWAP_DOWN | |
def INPUT_SWAP_UP equ 1 << BIT_INPUT_SWAP_UP | |
def INPUT_SWAP_LEFT equ 1 << BIT_INPUT_SWAP_LEFT | |
def INPUT_SWAP_RIGHT equ 1 << BIT_INPUT_SWAP_RIGHT | |
; ----------------------------------------------------------------------------- | |
; SERIAL_DATA ($FF01): Serial transfer data [r/w] | |
; ----------------------------------------------------------------------------- | |
def rSerialData equ $ff01 | |
; ----------------------------------------------------------------------------- | |
; SERIAL CTL ($FF02): Serial transfer control | |
; ----------------------------------------------------------------------------- | |
def rSerialCtl equ $ff02 | |
def BIT_SERIAL_CTL_TRANSFER equ 7 ; Reading 1 = transfer in progress; writing 1 = start transfer [r/w] | |
def MASK_SERIAL_CTL_TRANSFER equ 1 << BIT_SERIAL_CTL_TRANSFER | |
def SERIAL_CTL_TRANSFER_OFF equ 0 << BIT_SERIAL_CTL_TRANSFER | |
def SERIAL_CTL_TRANSFER_ON equ 1 << BIT_SERIAL_CTL_TRANSFER | |
def BIT_SERIAL_CTL_CLOCK_SPD equ 1 ; (CGB only) 1 = use TODOx faster clock if master [r/w] | |
def MASK_SERIAL_CTL_CLOCK_SPD equ 1 << BIT_SERIAL_CTL_CLOCK_SPD | |
def SERIAL_CTL_LOW_SPD_CLK equ 0 << BIT_SERIAL_CTL_CLK_SPD | |
def SERIAL_CTL_HIGH_SPD_CLK equ 1 << BIT_SERIAL_CTL_CLK_SPD | |
def BIT_SERIAL_CTL_CLOCK_SEL equ 0 ; 0 = use external clock ("slave"), 1 = use internal clock ("master") [r/w] | |
def MASK_SERIAL_CTL_CLOCK_SEL equ 1 << BIT_SERIAL_CTL_CLOCK_SEL | |
def SERIAL_CTL_EXTERNAL_CLK equ 0 << BIT_SERIAL_CTL_CLK_SEL | |
def SERIAL_CTL_INTERNAL_CLK equ 1 << BIT_SERIAL_CTL_CLK_SEL | |
; ----------------------------------------------------------------------------- | |
; $FF03 is unused | |
; ----------------------------------------------------------------------------- | |
; ----------------------------------------------------------------------------- | |
; CYCLE_CNT ($FF04): Divider register [r/w] | |
; ----------------------------------------------------------------------------- | |
def rCycleCnt equ $ff04 | |
; ----------------------------------------------------------------------------- | |
; TIMER_CNT ($FF05): Timer counter [r/w] | |
; ----------------------------------------------------------------------------- | |
def rTimerCnt equ $ff05 | |
; ----------------------------------------------------------------------------- | |
; TIMER_MOD ($FF06): Timer modulo [r/w] | |
; ----------------------------------------------------------------------------- | |
def rTimerMod equ $ff06 | |
; ----------------------------------------------------------------------------- | |
; TIMER_CTL ($FF07): Timer control | |
; ----------------------------------------------------------------------------- | |
def rTimerCtl equ $ff07 | |
def BIT_TIMER_CTL_ENABLE equ 2 ; 1 = enable incrementing TIMER_CNT [r/w] | |
def MASK_TIMER_CTL_ENABLE equ 1 << BIT_TIMER_CTL_ENABLE | |
def TIMER_CTL_START equ 0 << BIT_TIMER_CTL_ENABLE | |
def TIMER_CTL_STOP equ 1 << BIT_TIMER_CTL_ENABLE | |
def MASK_TIMER_CTL_CLOCK_SELECT equ %000000_11 ; the frequency at which TIMER_CNT increments [r/w] | |
def TIMER_CTL_INC_256_M_CYCLES equ %000000_00 ; every 256 M-cycles = ~4 KHz on DMG | |
def TIMER_CTL_INC_4_M_CYCLES equ %000000_01 ; every 4 M-cycles = ~262 KHz on DMG | |
def TIMER_CTL_INC_16_M_CYCLES equ %000000_10 ; every 16 M-cycles = ~65 KHz on DMG | |
def TIMER_CTL_INC_64_M_CYCLES equ %000000_11 ; every 64 M-cycles = ~16 KHz on DMG | |
; ----------------------------------------------------------------------------- | |
; $FF08-$FF0E are unused | |
; ----------------------------------------------------------------------------- | |
; ----------------------------------------------------------------------------- | |
; INTR_PENDING ($FF0F): Pending interrupts | |
; ----------------------------------------------------------------------------- | |
def rIntrFlg equ $ff0f | |
def BIT_INTR_PENDING_JOYPAD equ 4 ; 1 = Joypad interrupt is pending [r/w] | |
def MASK_INTR_PENDING_JOYPAD equ 1 << BIT_INTR_PENDING_JOYPAD | |
def rINTR_PENDING_JOYPAD_OFF equ 0 << BIT_INTR_PENDING_JOYPAD | |
def rINTR_PENDING_JOYPAD_ON equ 1 << BIT_INTR_PENDING_JOYPAD | |
def BIT_INTR_PENDING_SERIAL equ 3 ; 1 = Serial interrupt is pending [r/w] | |
def MASK_INTR_PENDING_SERIAL equ 1 << BIT_INTR_PENDING_SERIAL | |
def rINTR_PENDING_SERIAL_OFF equ 0 << BIT_INTR_PENDING_SERIAL | |
def rINTR_PENDING_SERIAL_ON equ 1 << BIT_INTR_PENDING_SERIAL | |
def BIT_INTR_PENDING_TIMER equ 2 ; 1 = Timer interrupt is pending [r/w] | |
def MASK_INTR_PENDING_TIMER equ 1 << BIT_INTR_PENDING_TIMER | |
def rINTR_PENDING_TIMER_OFF equ 0 << BIT_INTR_PENDING_TIMER | |
def rINTR_PENDING_TIMER_ON equ 1 << BIT_INTR_PENDING_TIMER | |
def BIT_INTR_PENDING_LCD equ 1 ; 1 = LCD interrupt is pending [r/w] | |
def MASK_INTR_PENDING_LCD equ 1 << BIT_INTR_PENDING_LCD | |
def rINTR_PENDING_LCD_OFF equ 0 << BIT_INTR_PENDING_LCD | |
def rINTR_PENDING_LCD_ON equ 1 << BIT_INTR_PENDING_LCD | |
def BIT_INTR_PENDING_VBLANK equ 0 ; 1 = VBlank interrupt is pending [r/w] | |
def MASK_INTR_PENDING_VBLANK equ 1 << BIT_INTR_PENDING_VBLANK | |
def rINTR_PENDING_VBLANK_OFF equ 0 << BIT_INTR_PENDING_VBLANK | |
def rINTR_PENDING_VBLANK_ON equ 1 << BIT_INTR_PENDING_VBLANK | |
; ----------------------------------------------------------------------------- | |
; AUD1_SWEEP ($FF10): Audio channel 1 sweep | |
; ----------------------------------------------------------------------------- | |
def rAud1Sweep equ $ff10 | |
def MASK_AUD1_SWEEP_PACE equ %0_111_0000 ; how long between sweep iterations [r/w] | |
; (in 128 Hz ticks, ~ 7.8 ms apart) | |
def BIT_AUD1_SWEEP_DIR equ 3 ; sweep direction [r/w] | |
def MASK_AUD1_SWEEP_DIR equ 1 << BIT_AUD1_SWEEP_DIR | |
def AUD1_SWEEP_UP equ 0 << BIT_AUD1_SWEEP_DIR | |
def AUD1_SWEEP_DOWN equ 1 << BIT_AUD1_SWEEP_DIR | |
def MASK_AUD1_SWEEP_STEP equ %00000_111 ; by how much the period inc-/decreases per iteration [r/w] | |
; ----------------------------------------------------------------------------- | |
; AUD1_LEN ($FF11): Audio channel 1 length timer and duty cycle | |
; ----------------------------------------------------------------------------- | |
def rAud1Len equ $ff11 | |
def MASK_AUD1_LEN_DUTY equ %11_000000 ; ratio of time spent high vs. time spent low [r/w] | |
def AUD1_LEN_DUTY_12_5 equ %00_000000 ; 12.5% | |
def AUD1_LEN_DUTY_25 equ %01_000000 ; 25% | |
def AUD1_LEN_DUTY_50 equ %10_000000 ; 50% | |
def AUD1_LEN_DUTY_75 equ %11_000000 ; 75% | |
def MASK_AUD1_LEN_TIMER equ %00_111111 ; initial length timer [wo] | |
; ----------------------------------------------------------------------------- | |
; AUD1_ENV/NR12 ($FF12): Audio channel 1 volume and envelope | |
; ----------------------------------------------------------------------------- | |
def rAud1Env equ $ff12 | |
def MASK_AUD1_ENV_VOLUME equ %1111_0000 ; initial volume [r/w] | |
def BIT_AUD1_ENV_DIR equ 3 ; direction of volume envelope [r/w] | |
def MASK_AUD1_ENV_DIR equ 1 << BIT_AUD1_ENV_DIR | |
def AUD1_ENV_DOWN equ 0 << BIT_AUD1_ENV_DIR | |
def AUD1_ENV_UP equ 1 << BIT_AUD1_ENV_DIR | |
def MASK_AUD1_ENV_PACE equ %00000_111 ; how long between envelope iterations [r/w] | |
; (in TODO Hz ticks, ~ TODO apart) | |
; ----------------------------------------------------------------------------- | |
; TODO | |
endc ; def(HARDWARE_INC) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment