Use RGBDS 0.4.0 and make boilerplate minimal

This commit is contained in:
ISSOtm
2020-04-25 19:13:38 +02:00
parent 3f6309cdce
commit 4c9dd12d91
32 changed files with 156 additions and 3035 deletions

View File

@@ -1,4 +0,0 @@
INCLUDE "constants/hardware.inc"
INCLUDE "constants/enums.asm"
INCLUDE "constants/misc.asm"

View File

@@ -1,68 +0,0 @@
set_enum_value: MACRO
enum_value = \1
ENDM
enum_start: MACRO
IF _NARG == 0
set_enum_value 0
ELSE
set_enum_value \1
ENDC
ENDM
enum_elem: MACRO
IF _NARG >= 2
set_enum_value \2
ENDC
\1 = enum_value
set_enum_value enum_value+1
ENDM
; SGB packet types
enum_start
enum_elem PAL01
enum_elem PAL23
enum_elem PAL12
enum_elem PAL03
enum_elem ATTR_BLK
enum_elem ATTR_LIN
enum_elem ATTR_DIV
enum_elem ATTR_CHR
enum_elem SOUND ; $08
enum_elem SOU_TRN
enum_elem PAL_SET
enum_elem PAL_TRN
enum_elem ATRC_EN
enum_elem TEST_EN
enum_elem ICON_EN
enum_elem DATA_SND
enum_elem DATA_TRN ; $10
enum_elem MLT_REQ
enum_elem JUMP
enum_elem CHR_TRN
enum_elem PCT_TRN
enum_elem ATTR_TRN
enum_elem ATTR_SET
enum_elem MASK_EN
enum_elem OBJ_TRN ; $18
; Error IDs
enum_start
enum_elem ERROR_JUMP_HL
enum_elem ERROR_JUMP_DE
enum_elem ERROR_NULL_EXEC
enum_elem ERROR_RST38
enum_elem ERROR_UNKNOWN
; Directions
enum_start
enum_elem DIR_UP
enum_elem DIR_DOWN
enum_elem DIR_LEFT
enum_elem DIR_RIGHT

View File

@@ -1,838 +0,0 @@
;*
;* Gameboy Hardware definitions
;*
;* Based on Jones' hardware.inc
;* And based on Carsten Sorensen's ideas.
;*
;* Rev 1.1 - 15-Jul-97 : Added define check
;* Rev 1.2 - 18-Jul-97 : Added revision check macro
;* Rev 1.3 - 19-Jul-97 : Modified for RGBASM V1.05
;* Rev 1.4 - 27-Jul-97 : Modified for new subroutine prefixes
;* Rev 1.5 - 15-Aug-97 : Added _HRAM, PAD, CART defines
;* : and Nintendo Logo
;* Rev 1.6 - 30-Nov-97 : Added rDIV, rTIMA, rTMA, & rTAC
;* Rev 1.7 - 31-Jan-98 : Added _SCRN0, _SCRN1
;* Rev 1.8 - 15-Feb-98 : Added rSB, rSC
;* Rev 1.9 - 16-Feb-98 : Converted I/O registers to $FFXX format
;* Rev 2.0 - : Added GBC registers
;* Rev 2.1 - : Added MBC5 & cart RAM enable/disable defines
;* Rev 2.2 - : Fixed NR42,NR43, & NR44 equates
;* Rev 2.3 - : Fixed incorrect _HRAM equate
;* Rev 2.4 - 27-Apr-13 : Added some cart defines (AntonioND)
;* Rev 2.5 - 03-May-15 : Fixed format (AntonioND)
;* Rev 2.6 - 09-Apr-16 : Added GBC OAM and cart defines (AntonioND)
;* Rev 2.7 - 19-Jan-19 : Added rPCMXX (ISSOtm)
;* Rev 2.8 - 03-Feb-19 : Added audio registers flags (Álvaro Cuesta)
; If all of these are already defined, don't do it again.
IF !DEF(HARDWARE_INC)
HARDWARE_INC SET 1
rev_Check_hardware_inc : MACRO
;NOTE: REVISION NUMBER CHANGES MUST BE ADDED
;TO SECOND PARAMETER IN FOLLOWING LINE.
IF \1 > 2.8 ;PUT REVISION NUMBER HERE
WARN "Version \1 or later of 'hardware.inc' is required."
ENDC
ENDM
_HW EQU $FF00
_VRAM EQU $8000 ; $8000->$9FFF
_SCRN0 EQU $9800 ; $9800->$9BFF
_SCRN1 EQU $9C00 ; $9C00->$9FFF
_SRAM EQU $A000 ; $A000->$BFFF
_RAM EQU $C000 ; $C000->$DFFF
_OAMRAM EQU $FE00 ; $FE00->$FE9F
_AUD3WAVERAM EQU $FF30 ; $FF30->$FF3F
_HRAM EQU $FF80 ; $FF80->$FFFE
; *** MBC5 Equates ***
rRAMG EQU $0000 ; $0000->$1fff
rROMB0 EQU $2000 ; $2000->$2fff
rROMB1 EQU $3000 ; $3000->$3fff - If more than 256 ROM banks are present.
rRAMB EQU $4000 ; $4000->$5fff - Bit 3 enables rumble (if present)
; --
; -- OAM flags
; --
OAMF_PRI EQU %10000000 ; Priority
OAMF_YFLIP EQU %01000000 ; Y flip
OAMF_XFLIP EQU %00100000 ; X flip
OAMF_PAL0 EQU %00000000 ; Palette number; 0,1 (DMG)
OAMF_PAL1 EQU %00010000 ; Palette number; 0,1 (DMG)
OAMF_BANK0 EQU %00000000 ; Bank number; 0,1 (GBC)
OAMF_BANK1 EQU %00001000 ; Bank number; 0,1 (GBC)
OAMF_PALMASK EQU %00000111 ; Palette (GBC)
OAMB_PRI EQU 7 ; Priority
OAMB_YFLIP EQU 6 ; Y flip
OAMB_XFLIP EQU 5 ; X flip
OAMB_PAL1 EQU 4 ; Palette number; 0,1 (DMG)
OAMB_BANK1 EQU 3 ; Bank number; 0,1 (GBC)
;***************************************************************************
;*
;* Custom registers
;*
;***************************************************************************
; --
; -- P1 ($FF00)
; -- Register for reading joy pad info. (R/W)
; --
rP1 EQU $FF00
P1F_5 EQU %00100000 ; P15 out port
P1F_4 EQU %00010000 ; P14 out port
P1F_3 EQU %00001000 ; P13 in port
P1F_2 EQU %00000100 ; P12 in port
P1F_1 EQU %00000010 ; P11 in port
P1F_0 EQU %00000001 ; P10 in port
; --
; -- SB ($FF01)
; -- Serial Transfer Data (R/W)
; --
rSB EQU $FF01
; --
; -- SC ($FF02)
; -- Serial I/O Control (R/W)
; --
rSC EQU $FF02
; --
; -- DIV ($FF04)
; -- Divider register (R/W)
; --
rDIV EQU $FF04
; --
; -- TIMA ($FF05)
; -- Timer counter (R/W)
; --
rTIMA EQU $FF05
; --
; -- TMA ($FF06)
; -- Timer modulo (R/W)
; --
rTMA EQU $FF06
; --
; -- TAC ($FF07)
; -- Timer control (R/W)
; --
rTAC EQU $FF07
TACF_START EQU %00000100
TACF_STOP EQU %00000000
TACF_4KHZ EQU %00000000
TACF_16KHZ EQU %00000011
TACF_65KHZ EQU %00000010
TACF_262KHZ EQU %00000001
; --
; -- IF ($FF0F)
; -- Interrupt Flag (R/W)
; --
rIF EQU $FF0F
; --
; -- LCDC ($FF40)
; -- LCD Control (R/W)
; --
rLCDC EQU $FF40
LCDCF_OFF EQU %00000000 ; LCD Control Operation
LCDCF_ON EQU %10000000 ; LCD Control Operation
LCDCF_WIN9800 EQU %00000000 ; Window Tile Map Display Select
LCDCF_WIN9C00 EQU %01000000 ; Window Tile Map Display Select
LCDCF_WINOFF EQU %00000000 ; Window Display
LCDCF_WINON EQU %00100000 ; Window Display
LCDCF_BG8800 EQU %00000000 ; BG & Window Tile Data Select
LCDCF_BG8000 EQU %00010000 ; BG & Window Tile Data Select
LCDCF_BG9800 EQU %00000000 ; BG Tile Map Display Select
LCDCF_BG9C00 EQU %00001000 ; BG Tile Map Display Select
LCDCF_OBJ8 EQU %00000000 ; OBJ Construction
LCDCF_OBJ16 EQU %00000100 ; OBJ Construction
LCDCF_OBJOFF EQU %00000000 ; OBJ Display
LCDCF_OBJON EQU %00000010 ; OBJ Display
LCDCF_BGOFF EQU %00000000 ; BG Display
LCDCF_BGON EQU %00000001 ; BG Display
; "Window Character Data Select" follows BG
; --
; -- STAT ($FF41)
; -- LCDC Status (R/W)
; --
rSTAT EQU $FF41
STATF_LYC EQU %01000000 ; LYCEQULY Coincidence (Selectable)
STATF_MODE10 EQU %00100000 ; Mode 10
STATF_MODE01 EQU %00010000 ; Mode 01 (V-Blank)
STATF_MODE00 EQU %00001000 ; Mode 00 (H-Blank)
STATF_LYCF EQU %00000100 ; Coincidence Flag
STATF_HB EQU %00000000 ; H-Blank
STATF_VB EQU %00000001 ; V-Blank
STATF_OAM EQU %00000010 ; OAM-RAM is used by system
STATF_LCD EQU %00000011 ; Both OAM and VRAM used by system
STATF_BUSY EQU %00000010 ; When set, VRAM access is unsafe
; --
; -- SCY ($FF42)
; -- Scroll Y (R/W)
; --
rSCY EQU $FF42
; --
; -- SCY ($FF43)
; -- Scroll X (R/W)
; --
rSCX EQU $FF43
; --
; -- LY ($FF44)
; -- LCDC Y-Coordinate (R)
; --
; -- Values range from 0->153. 144->153 is the VBlank period.
; --
rLY EQU $FF44
; --
; -- LYC ($FF45)
; -- LY Compare (R/W)
; --
; -- When LYEQUEQULYC, STATF_LYCF will be set in STAT
; --
rLYC EQU $FF45
; --
; -- DMA ($FF46)
; -- DMA Transfer and Start Address (W)
; --
rDMA EQU $FF46
; --
; -- BGP ($FF47)
; -- BG Palette Data (W)
; --
; -- Bit 7-6 - Intensity for %11
; -- Bit 5-4 - Intensity for %10
; -- Bit 3-2 - Intensity for %01
; -- Bit 1-0 - Intensity for %00
; --
rBGP EQU $FF47
; --
; -- OBP0 ($FF48)
; -- Object Palette 0 Data (W)
; --
; -- See BGP for info
; --
rOBP0 EQU $FF48
; --
; -- OBP1 ($FF49)
; -- Object Palette 1 Data (W)
; --
; -- See BGP for info
; --
rOBP1 EQU $FF49
; --
; -- WY ($FF4A)
; -- Window Y Position (R/W)
; --
; -- 0 <EQU WY <EQU 143
; --
rWY EQU $FF4A
; --
; -- WX ($FF4B)
; -- Window X Position (R/W)
; --
; -- 7 <EQU WX <EQU 166
; --
rWX EQU $FF4B
; --
; -- KEY 1 ($FF4D)
; -- Select CPU Speed (R/W)
; --
rKEY1 EQU $FF4D
; --
; -- VBK ($FF4F)
; -- Select Video RAM Bank (R/W)
; --
rVBK EQU $FF4F
; --
; -- HDMA1 ($FF51)
; -- Horizontal Blanking, General Purpose DMA (W)
; --
rHDMA1 EQU $FF51
; --
; -- HDMA2 ($FF52)
; -- Horizontal Blanking, General Purpose DMA (W)
; --
rHDMA2 EQU $FF52
; --
; -- HDMA3 ($FF53)
; -- Horizontal Blanking, General Purpose DMA (W)
; --
rHDMA3 EQU $FF53
; --
; -- HDMA4 ($FF54)
; -- Horizontal Blanking, General Purpose DMA (W)
; --
rHDMA4 EQU $FF54
; --
; -- HDMA5 ($FF55)
; -- Horizontal Blanking, General Purpose DMA (R/W)
; --
rHDMA5 EQU $FF55
; --
; -- RP ($FF56)
; -- Infrared Communications Port (R/W)
; --
rRP EQU $FF56
; --
; -- BCPS ($FF68)
; -- Background Color Palette Specification (R/W)
; --
rBCPS EQU $FF68
; --
; -- BCPD ($FF69)
; -- Background Color Palette Data (R/W)
; --
rBCPD EQU $FF69
; --
; -- BCPS ($FF6A)
; -- Object Color Palette Specification (R/W)
; --
rOCPS EQU $FF6A
; --
; -- BCPD ($FF6B)
; -- Object Color Palette Data (R/W)
; --
rOCPD EQU $FF6B
; --
; -- SVBK ($FF4F)
; -- Select Main RAM Bank (R/W)
; --
rSVBK EQU $FF70
; --
; -- IE ($FFFF)
; -- Interrupt Enable (R/W)
; --
rIE EQU $FFFF
IEF_HILO EQU %00010000 ; Transition from High to Low of Pin number P10-P13
IEF_SERIAL EQU %00001000 ; Serial I/O transfer end
IEF_TIMER EQU %00000100 ; Timer Overflow
IEF_LCDC EQU %00000010 ; LCDC (see STAT)
IEF_VBLANK EQU %00000001 ; V-Blank
;***************************************************************************
;*
;* Sound control registers
;*
;***************************************************************************
; --
; -- AUDVOL/NR50 ($FF24)
; -- Channel control / ON-OFF / Volume (R/W)
; --
; -- Bit 7 - Vin->SO2 ON/OFF (Vin??)
; -- Bit 6-4 - SO2 output level (volume) (# 0-7)
; -- Bit 3 - Vin->SO1 ON/OFF (Vin??)
; -- Bit 2-0 - SO1 output level (volume) (# 0-7)
; --
rNR50 EQU $FF24
rAUDVOL EQU rNR50
AUDVOL_VIN_LEFT EQU %10000000 ; SO2
AUDVOL_VIN_RIGHT EQU %00001000 ; SO1
; --
; -- AUDTERM/NR51 ($FF25)
; -- Selection of Sound output terminal (R/W)
; --
; -- Bit 7 - Output sound 4 to SO2 terminal
; -- Bit 6 - Output sound 3 to SO2 terminal
; -- Bit 5 - Output sound 2 to SO2 terminal
; -- Bit 4 - Output sound 1 to SO2 terminal
; -- Bit 3 - Output sound 4 to SO1 terminal
; -- Bit 2 - Output sound 3 to SO1 terminal
; -- Bit 1 - Output sound 2 to SO1 terminal
; -- Bit 0 - Output sound 0 to SO1 terminal
; --
rNR51 EQU $FF25
rAUDTERM EQU rNR51
; SO2
AUDTERM_4_LEFT EQU %10000000
AUDTERM_3_LEFT EQU %01000000
AUDTERM_2_LEFT EQU %00100000
AUDTERM_1_LEFT EQU %00010000
; SO1
AUDTERM_4_RIGHT EQU %00001000
AUDTERM_3_RIGHT EQU %00000100
AUDTERM_2_RIGHT EQU %00000010
AUDTERM_1_RIGHT EQU %00000001
; --
; -- AUDENA/NR52 ($FF26)
; -- Sound on/off (R/W)
; --
; -- Bit 7 - All sound on/off (sets all audio regs to 0!)
; -- Bit 3 - Sound 4 ON flag (doesn't work!)
; -- Bit 2 - Sound 3 ON flag (doesn't work!)
; -- Bit 1 - Sound 2 ON flag (doesn't work!)
; -- Bit 0 - Sound 1 ON flag (doesn't work!)
; --
rNR52 EQU $FF26
rAUDENA EQU rNR52
AUDENA_ON EQU %10000000
AUDENA_OFF EQU %00000000 ; sets all audio regs to 0!
;***************************************************************************
;*
;* SoundChannel #1 registers
;*
;***************************************************************************
; --
; -- AUD1SWEEP/NR10 ($FF10)
; -- Sweep register (R/W)
; --
; -- Bit 6-4 - Sweep Time
; -- Bit 3 - Sweep Increase/Decrease
; -- 0: Addition (frequency increases???)
; -- 1: Subtraction (frequency increases???)
; -- Bit 2-0 - Number of sweep shift (# 0-7)
; -- Sweep Time: (n*7.8ms)
; --
rNR10 EQU $FF10
rAUD1SWEEP EQU rNR10
AUD1SWEEP_UP EQU %00000000
AUD1SWEEP_DOWN EQU %00001000
; --
; -- AUD1LEN/NR11 ($FF11)
; -- Sound length/Wave pattern duty (R/W)
; --
; -- Bit 7-6 - Wave Pattern Duty (00:12.5% 01:25% 10:50% 11:75%)
; -- Bit 5-0 - Sound length data (# 0-63)
; --
rNR11 EQU $FF11
rAUD1LEN EQU rNR11
; --
; -- AUD1ENV/NR12 ($FF12)
; -- Envelope (R/W)
; --
; -- Bit 7-4 - Initial value of envelope
; -- Bit 3 - Envelope UP/DOWN
; -- 0: Decrease
; -- 1: Range of increase
; -- Bit 2-0 - Number of envelope sweep (# 0-7)
; --
rNR12 EQU $FF12
rAUD1ENV EQU rNR12
; --
; -- AUD1LOW/NR13 ($FF13)
; -- Frequency lo (W)
; --
rNR13 EQU $FF13
rAUD1LOW EQU rNR13
; --
; -- AUD1HIGH/NR14 ($FF14)
; -- Frequency hi (W)
; --
; -- Bit 7 - Initial (when set, sound restarts)
; -- Bit 6 - Counter/consecutive selection
; -- Bit 2-0 - Frequency's higher 3 bits
; --
rNR14 EQU $FF14
rAUD1HIGH EQU rNR14
;***************************************************************************
;*
;* SoundChannel #2 registers
;*
;***************************************************************************
; --
; -- AUD2LEN/NR21 ($FF16)
; -- Sound Length; Wave Pattern Duty (R/W)
; --
; -- see AUD1LEN for info
; --
rNR21 EQU $FF16
rAUD2LEN EQU rNR21
; --
; -- AUD2ENV/NR22 ($FF17)
; -- Envelope (R/W)
; --
; -- see AUD1ENV for info
; --
rNR22 EQU $FF17
rAUD2ENV EQU rNR22
; --
; -- AUD2LOW/NR23 ($FF18)
; -- Frequency lo (W)
; --
rNR23 EQU $FF18
rAUD2LOW EQU rNR23
; --
; -- AUD2HIGH/NR24 ($FF19)
; -- Frequency hi (W)
; --
; -- see AUD1HIGH for info
; --
rNR24 EQU $FF19
rAUD2HIGH EQU rNR24
;***************************************************************************
;*
;* SoundChannel #3 registers
;*
;***************************************************************************
; --
; -- AUD3ENA/NR30 ($FF1A)
; -- Sound on/off (R/W)
; --
; -- Bit 7 - Sound ON/OFF (1EQUON,0EQUOFF)
; --
rNR30 EQU $FF1A
rAUD3ENA EQU rNR30
; --
; -- AUD3LEN/NR31 ($FF1B)
; -- Sound length (R/W)
; --
; -- Bit 7-0 - Sound length
; --
rNR31 EQU $FF1B
rAUD3LEN EQU rNR31
; --
; -- AUD3LEVEL/NR32 ($FF1C)
; -- Select output level
; --
; -- Bit 6-5 - Select output level
; -- 00: 0/1 (mute)
; -- 01: 1/1
; -- 10: 1/2
; -- 11: 1/4
; --
rNR32 EQU $FF1C
rAUD3LEVEL EQU rNR32
; --
; -- AUD3LOW/NR33 ($FF1D)
; -- Frequency lo (W)
; --
; -- see AUD1LOW for info
; --
rNR33 EQU $FF1D
rAUD3LOW EQU rNR33
; --
; -- AUD3HIGH/NR34 ($FF1E)
; -- Frequency hi (W)
; --
; -- see AUD1HIGH for info
; --
rNR34 EQU $FF1E
rAUD3HIGH EQU rNR34
; --
; -- AUD4LEN/NR41 ($FF20)
; -- Sound length (R/W)
; --
; -- Bit 5-0 - Sound length data (# 0-63)
; --
rNR41 EQU $FF20
rAUD4LEN EQU rNR41
; --
; -- AUD4ENV/NR42 ($FF21)
; -- Envelope (R/W)
; --
; -- see AUD1ENV for info
; --
rNR42 EQU $FF21
rAUD4ENV EQU rNR42
; --
; -- AUD4POLY/NR43 ($FF22)
; -- Polynomial counter (R/W)
; --
; -- Bit 7-4 - Selection of the shift clock frequency of the (scf)
; -- polynomial counter (0000-1101)
; -- freqEQUdrf*1/2^scf (not sure)
; -- Bit 3 - Selection of the polynomial counter's step
; -- 0: 15 steps
; -- 1: 7 steps
; -- Bit 2-0 - Selection of the dividing ratio of frequencies (drf)
; -- 000: f/4 001: f/8 010: f/16 011: f/24
; -- 100: f/32 101: f/40 110: f/48 111: f/56 (fEQU4.194304 Mhz)
; --
rNR43 EQU $FF22
rAUD4POLY EQU rNR43
; --
; -- AUD4GO/NR44 ($FF23)
; -- (has wrong name and value (ff30) in Dr.Pan's doc!)
; --
; -- Bit 7 - Inital
; -- Bit 6 - Counter/consecutive selection
; --
rNR44 EQU $FF23
rAUD4GO EQU rNR44 ; silly name!
; --
; -- PCM12 ($FF76)
; -- Sound channel 1&2 PCM amplitude (R)
; --
; -- Bit 7-4 - Copy of sound channel 2's PCM amplitude
; -- Bit 3-0 - Copy of sound channel 1's PCM amplitude
; --
rPCM12 EQU $FF76
; --
; -- PCM34 ($FF77)
; -- Sound channel 3&4 PCM amplitude (R)
; --
; -- Bit 7-4 - Copy of sound channel 4's PCM amplitude
; -- Bit 3-0 - Copy of sound channel 3's PCM amplitude
; --
rPCM34 EQU $FF77
;***************************************************************************
;*
;* Flags common to multiple sound channels
;*
;***************************************************************************
; --
; -- Square wave duty cycle
; --
; -- Can be used with AUD1LEN and AUD2LEN
; -- See AUD1LEN for more info
; --
AUDLEN_DUTY_12_5 EQU %00000000 ; 12.5%
AUDLEN_DUTY_25 EQU %01000000 ; 25%
AUDLEN_DUTY_50 EQU %10000000 ; 50%
AUDLEN_DUTY_75 EQU %11000000 ; 75%
; --
; -- Audio envelope flags
; --
; -- Can be used with AUD1ENV, AUD2ENV, AUD4ENV
; -- See AUD1ENV for more info
; --
AUDENV_UP EQU %00001000
AUDENV_DOWN EQU %00000000
; --
; -- Audio trigger flags
; --
; -- Can be used with AUD1HIGH, AUD2HIGH, AUD3HIGH
; -- See AUD1HIGH for more info
; --
AUDHIGH_RESTART EQU %10000000
AUDHIGH_LENGTH_ON EQU %01000000
AUDHIGH_LENGTH_OFF EQU %00000000
;***************************************************************************
;*
;* Cart related
;*
;***************************************************************************
CART_COMPATIBLE_DMG EQU $00
CART_COMPATIBLE_DMG_GBC EQU $80
CART_COMPATIBLE_GBC EQU $C0
CART_ROM EQU $00
CART_ROM_MBC1 EQU $01
CART_ROM_MBC1_RAM EQU $02
CART_ROM_MBC1_RAM_BAT EQU $03
CART_ROM_MBC2 EQU $05
CART_ROM_MBC2_BAT EQU $06
CART_ROM_RAM EQU $08
CART_ROM_RAM_BAT EQU $09
CART_ROM_MBC3_BAT_RTC EQU $0F
CART_ROM_MBC3_RAM_BAT_RTC EQU $10
CART_ROM_MBC3 EQU $11
CART_ROM_MBC3_RAM EQU $12
CART_ROM_MBC3_RAM_BAT EQU $13
CART_ROM_MBC5 EQU $19
CART_ROM_MBC5_BAT EQU $1A
CART_ROM_MBC5_RAM_BAT EQU $1B
CART_ROM_MBC5_RUMBLE EQU $1C
CART_ROM_MBC5_RAM_RUMBLE EQU $1D
CART_ROM_MBC5_RAM_BAT_RUMBLE EQU $1E
CART_ROM_MBC7_RAM_BAT_GYRO EQU $22
CART_ROM_POCKET_CAMERA EQU $FC
CART_ROM_256K EQU 0 ; 2 banks
CART_ROM_512K EQU 1 ; 4 banks
CART_ROM_1M EQU 2 ; 8 banks
CART_ROM_2M EQU 3 ; 16 banks
CART_ROM_4M EQU 4 ; 32 banks
CART_ROM_8M EQU 5 ; 64 banks
CART_ROM_16M EQU 6 ; 128 banks
CART_ROM_32M EQU 7 ; 256 banks
CART_ROM_64M EQU 8 ; 512 banks
CART_RAM_NONE EQU 0
CART_RAM_16K EQU 1 ; 1 incomplete bank
CART_RAM_64K EQU 2 ; 1 bank
CART_RAM_256K EQU 3 ; 4 banks
CART_RAM_1M EQU 4 ; 16 banks
CART_RAM_ENABLE EQU $0A
CART_RAM_DISABLE EQU $00
;***************************************************************************
;*
;* Keypad related
;*
;***************************************************************************
PADF_DOWN EQU $80
PADF_UP EQU $40
PADF_LEFT EQU $20
PADF_RIGHT EQU $10
PADF_START EQU $08
PADF_SELECT EQU $04
PADF_B EQU $02
PADF_A EQU $01
PADB_DOWN EQU $7
PADB_UP EQU $6
PADB_LEFT EQU $5
PADB_RIGHT EQU $4
PADB_START EQU $3
PADB_SELECT EQU $2
PADB_B EQU $1
PADB_A EQU $0
;***************************************************************************
;*
;* Screen related
;*
;***************************************************************************
SCRN_X EQU 160 ; Width of screen in pixels
SCRN_Y EQU 144 ; Height of screen in pixels
SCRN_X_B EQU 20 ; Width of screen in bytes
SCRN_Y_B EQU 18 ; Height of screen in bytes
SCRN_VX EQU 256 ; Virtual width of screen in pixels
SCRN_VY EQU 256 ; Virtual height of screen in pixels
SCRN_VX_B EQU 32 ; Virtual width of screen in bytes
SCRN_VY_B EQU 32 ; Virtual height of screen in bytes
;*
;* Nintendo scrolling logo
;* (Code won't work on a real GameBoy)
;* (if next lines are altered.)
NINTENDO_LOGO : MACRO
DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D
DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99
DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E
ENDM
ENDC ;HARDWARE_INC

View File

@@ -1,23 +0,0 @@
; RST labels
null_exec equ $00
memcpy_small equ $08
memset_small equ $10
memset equ $18
bankswitch equ $20
call_hl equ $28
wait_vblank equ $30
rst38_err equ $38
; Seconds-to-frames converter
; "wait 30 seconds" is nice RGBDS magic :D
second EQUS "* 60"
seconds EQUS "* 60"
frames EQUS "" ; lol
STACK_SIZE = $40
SGB_PACKET_SIZE = 16

View File

@@ -1,6 +0,0 @@
INCLUDE "constants.asm"
INCLUDE "macros.asm"
INCLUDE "engine/init.asm"
INCLUDE "engine/error_handler.asm"

View File

@@ -1,746 +0,0 @@
SECTION "Error handler trampoline", ROM0
handle_error: MACRO
; Make sure we're not interrupted
di
; Save current value of A
ld [wErrorA], a
ld a, \1 ; Preserve flags, don't "xor a"!
; Will generate an extra, unnecessary "jr", but eh.
jr ErrorHandler
ENDM
HLJumpingError::
handle_error ERROR_JUMP_HL
DEJumpingError::
handle_error ERROR_JUMP_DE
NullExecError::
handle_error ERROR_NULL_EXEC
Rst38Error::
handle_error ERROR_RST38
; Perform minimal init, and jump to error handler in ROMX
ErrorHandler:
ld [wErrorType], a
ld a, BANK(_ErrorHandler)
ld [rROMB0], a
xor a ; Ensure the error handler WILL be called, even if we end up with 512 banks
ld [rROMB1], a
jp _ErrorHandler
SECTION "Error handler", ROMX
; Note: `call` is BANNED in this section of code!!
_ErrorHandler:
ld [wErrorSP], sp
ld sp, wErrorSP
push hl
push de
push bc
ld a, [wErrorA]
push af
xor a
ldh [rNR52], a
ldh a, [rLCDC]
bit 7, a
jr z, .lcdOff
.waitVBlank
ld a, [rLY]
cp SCRN_Y
jr c, .waitVBlank
xor a
ld [rLCDC], a
.lcdOff
; Load palette
ld a, $F4
ld [rBGP], a
xor a
ldh [rSCY], a
ldh [rSCX], a
ld hl, _SCRN0
ld bc, SCRN_VX_B * SCRN_Y_B
.clearVRAM
xor a
ld [hli], a
dec bc
ld a, b
or c
jr nz, .clearVRAM
; Copy monospace font
ld hl, vBlankTile
ld de, ErrorFont
ld bc, $800
.copyFont
ld a, [de]
inc de
ld [hli], a
dec bc
ld a, b
or c
jr nz, .copyFont
; Oh noes!!
; ld hl, _SCRN0
; ld de, ErrorUwu
.copyUwU
ld a, [de]
inc de
ld [hli], a
and a
jr nz, .copyUwU
ld a, LCDCF_ON | LCDCF_BGON
ld [rLCDC], a
lb bc, 180, LOW(rLY)
.delayBetweenUwUs
ld a, [$ff00+c]
cp SCRN_Y + 1
jr nz, .delayBetweenUwUs
.waitUwUBlank
ld a, [$ff00+c]
cp SCRN_Y
jr nz, .waitUwUBlank
dec b
jr nz, .delayBetweenUwUs
ldcoord hl, 8, 0, _SCRN0
.copySeriousUwU
ldh a, [rSTAT]
and STATF_BUSY
jr nz, .copySeriousUwU
ld a, [de]
ld [hli], a
inc de
and a
jr nz, .copySeriousUwU
; But can you do it in 0.5x A presses?
lb bc, 1, LOW(rP1)
ld a, $10 ; Select buttons
ld [$ff00+c], a
.waitAPress
REPT 6
ld a, [$ff00+c]
ENDR
xor b
rra
jr nc, .waitAPress
dec b ; No, you can't.
jr z, .waitAPress
ErrorDumpScreen:
ldh a, [rLY]
sub SCRN_Y
jr nz, ErrorDumpScreen
ldh [rLCDC], a
ld hl, _SCRN0
ld bc, SCRN_VX_B * SCRN_Y_B
.clearSCRN0
xor a
ld [hli], a
dec bc
ld a, b
or c
jr nz, .clearSCRN0
ld a, [wErrorType]
ld c, a
; We can start using wErrorType for the drawing status purpose
xor a
ld [wErrorDrawStatus], a
ld a, c
cp ERROR_UNKNOWN
jr c, .errorTypeOK
ld a, ERROR_UNKNOWN
.errorTypeOK
add a, a
add a, LOW(ErrorStrings)
ld l, a
adc a, HIGH(ErrorStrings)
sub l
ld h, a
ld a, [hli]
ld d, [hl]
ld e, a
ldcoord hl, 3, 1, _SCRN0
jp StrcpyNoTerm
PrintedErrorStr:
ld a, c
cp ERROR_UNKNOWN
jp nc, PrintHex
PrintedErrorCode:
ld hl, wErrorDrawStatus
inc [hl]
pop bc
; From now on, there is 1 free stack slot, which means we can `call`!!
ld de, AFStr
ldcoord hl, 4, 1, _SCRN0
call StrcpyNoTerm
ld a, b
call PrintHex
ld a, c
call PrintHex
ldcoord hl, 0, 1, _SCRN0
ld de, SendNudesStr
call Strcpy
ld l, $21 ; ld hl, $9821
call Strcpy
ldcoord hl, 5, 1, _SCRN0
ld de, BCStr
call StrcpyNoTerm
pop bc
ld a, b
call PrintHex
ld a, c
call PrintHex
inc hl
; ld de, DEStr
call StrcpyNoTerm
pop bc
ld a, b
call PrintHex
ld a, c
call PrintHex
ldcoord hl, 14, 1, _SCRN0
ld de, MemRegs
.printMemReg
ld a, [de]
and a
jr z, .doneWithMemRegs
call StrcpyNoTerm
ld a, [de]
inc de
ld c, a
ld a, [de]
inc de
ld b, a
ld a, [bc]
call PrintHex
inc hl
jr .printMemReg
.doneWithMemRegs
ldcoord hl, 15, 1, _SCRN0
ld de, BankStr
call StrcpyNoTerm
ldh a, [hCurROMBank]
call PrintHex
ldcoord hl, 16, 1, _SCRN0
ld de, BuildDate
call Strcpy
; Now, we need to do the hex dumps. Boi are we in for some trouble!
ldcoord hl, 6, 1, _SCRN0
ld de, HLStr
call StrcpyNoTerm
; We first need to get the two registers (both at once to increase efficiency)
pop bc ; hl
pop de ; sp
; Move SP back by 2 entries (we need to preserve those for dump printing)
add sp, -4
ld a, b
call PrintHex
ld a, c
call PrintHex
ld b, d
ld c, e
ldcoord hl, 10, 1, _SCRN0
ld de, SPstr
call StrcpyNoTerm
ld a, b
call PrintHex
ld a, c
call PrintHex
ldcoord hl, 6, 10, _SCRN0
ld de, ViewStr
call StrcpyNoTerm
ldcoord hl, 10, 10, _SCRN0
ld de, ViewStr
call StrcpyNoTerm
ld a, 2
ld [wErrorWhichDump], a
.printOneDump
call PrintDump
ld hl, wErrorWhichDump
dec [hl]
jr nz, .printOneDump
ldcoord hl, 8, 0, _SCRN0
ld [hl], $1F
ld l, $80 ; ld hl, $9980
ld [hl], $1F
ld a, 4
ldh [rSCX], a
ld a, $FF
ldh [rSCY], a
; ld a, $FF
ld [wErrorHeldButtons], a
ld a, 30
ld [wErrorFramesTillUnlock], a
ld a, LCDCF_ON | LCDCF_BGON
ldh [rLCDC], a
; From now on, we'll be using the upper byte of the AF stack slot to save keys
; Thus, we're only allowed 2 stack slots (bc and de)
ErrorLoop:
; Wait till next frame
ld a, [rLY]
cp SCRN_Y + 1
jr c, ErrorLoop
; Wait until right before VBlank, to account for the overhead
.waitVBlank
ld a, [rLY]
cp SCRN_Y
jr nz, .waitVBlank
ld c, LOW(rP1)
ld a, $20 ; Select D-pad
ld [$ff00+c], a
REPT 6
ld a, [$ff00+c]
ENDR
or $F0 ; Set 4 upper bits (give them consistency)
ld b, a
; Filter impossible D-pad combinations
and $0C ; Filter only Down and Up
ld a, b
jr nz, .notUpAndDown
or $0C ; If both are pressed, "unpress" them
ld b, a
.notUpAndDown
and $03 ; Filter only Left and Right
jr nz, .notLeftAndRight
ld a, b
or $03 ; If both are pressed, "unpress" them
ld b, a
.notLeftAndRight
swap b ; Put D-pad buttons in upper nibble
ld a, $10 ; Select buttons
ld [$ff00+c], a
REPT 6
ld a, [$ff00+c]
ENDR
or $F0 ; Set 4 upper bits
and b ; Mix with D-pad bits (use AND because pressed=0)
ld b, a
ld a, [wErrorHeldButtons]
cpl
or b
ld e, a ; Pressed buttons
ld a, b
ld [wErrorHeldButtons], a
; Release joypad
ld a, $30
ld [$ff00+c], a
ld hl, wErrorFramesTillUnlock
ld a, [hl]
and a
jr z, .dumpsUnlocked
ld a, b ; Get back held buttons
and 3 ; Get only A and B
jr nz, ErrorLoop ; Decrement only if both are held
dec [hl]
jr ErrorLoop
.dumpsUnlocked
ld hl, wErrorWhichDump
bit 1, e ; Check if B was pressed
jr z, .changeDumps
; Prevent any dump-related operation if none have been chosen yet
ld a, [hl]
and a
jr z, ErrorLoop
; Select dump to act upon
ld hl, wErrorHL
dec a
jr z, .usingHLDump
ld hl, wErrorSP
.usingHLDump
bit 0, b
lb bc, 1, 8
jr nz, .moveSmall
lb bc, $10, 1
.moveSmall
ld a, [hl]
bit 7, e
jr z, .moveDown
bit 6, e
jr z, .moveUp
inc hl ; The next 2 target the high byte only
ld a, [hl]
bit 5, e
jr z, .moveLeft
bit 4, e
jp nz, ErrorLoop
.moveRight
add a, b
db $0E
.moveLeft
sub a, b
ld [hl], a
jr .redrawDump
.moveDown
add a, c
ld [hli], a
jr nc, .redrawDump
inc [hl]
jr .redrawDump
.moveUp
sub c
ld [hli], a
jp nc, .redrawDump
dec [hl]
.redrawDump
call PrintDump
; Unfortunately, PrintDump uses 3 stack slots, which overwrites the held keys and the lock frames
; We can get around that, though
ld hl, wErrorFramesTillUnlock
xor a ; Set no remaining frames (obv)
ld [hld], a
; Set all buttons as held (avoid spurious presses)
ld [hl], a
jp ErrorLoop
.changeDumps
ld a, [hl]
dec a ; Check if on HL dump
jr z, .toSPDump
ld [hl], 1 ; Switch to HL dump (from SP dump & no dump yet)
db $21
.toSPDump
ld [hl], 2
; Toggle cursors
ld a, $1F
jr z, .emptyHLCursor
ld a, $7F
.emptyHLCursor
ld [$9900], a
xor $1F ^ $7F
ld [$9980], a
jp ErrorLoop
PrintHex:
ld b, a
and $F0
swap a
cp 10
jr c, .highIsDigit
add a, "A" - "0" - 10
.highIsDigit
add a, "0"
ld [hli], a
ld a, b
and $0F
cp 10
jr c, .lowIsDigit
add a, "A" - "0" - 10
.lowIsDigit
add a, "0"
ld [hli], a
ld a, [wErrorDrawStatus]
and a
jp z, PrintedErrorCode
ret
StrcpyNoTerm:
ld a, [de]
inc de
and a
jr z, .return
ld [hli], a
jr StrcpyNoTerm
.return
ld a, [wErrorDrawStatus]
and a
jp z, PrintedErrorStr
ret
PrintDump:
ldcoord hl, 6, 15, _SCRN0
ld bc, wErrorHL
ld a, [wErrorWhichDump]
dec a
jr z, .dumpHL
ldcoord hl, 10, 15, _SCRN0
ld bc, wErrorSP
.dumpHL
ld a, [bc]
ld e, a
inc bc
ld a, [bc]
ld d, a
call PrintHex
ld a, e
call PrintHex
inc hl
ld a, e
sub 4 * 2
ld e, a
ld a, d
sbc 0
ld d, a
ld b, 3
.printNextRow
ld a, b
ld bc, $20 - 20
add hl, bc
ld c, 4
ld b, a
dec a ; Dirty hack: when the LCD is on, VBlank expires slightly too early, so only 2 rows can be drawn correctly
jr nz, .printOneWord
; If the LCD is off, no worries
ldh a, [rLCDC]
add a, a
jr nc, .printOneWord
; Wait till VBlank again
.waitVBlank
ldh a, [rLY]
cp $90
jr nz, .waitVBlank
.printOneWord
inc hl
push bc ; B is trashed by PrintHex, so we need to save it anyways; but we also free c for storage
ld a, [de]
inc de
ld c, a ; Save low byte for later
ld a, [de]
inc de
call PrintHex
ld a, c
call PrintHex
pop bc
dec c
jr nz, .printOneWord
dec b
jr nz, .printNextRow
ret
SendNudesStr:
dstr "Pls send us a pic"
dstr "of this screen! =)"
ErrorStrings:
dw .hlJumpErrorStr
dw .deJumpErrorStr
dw .nullExecErrorStr
dw .rst38ErrorStr
dw .unknownErrorStr
.hlJumpErrorStr
dstr "Bad hl jump"
.deJumpErrorStr
dstr "Bad de jump"
.nullExecErrorStr
dstr "Null exec"
.rst38ErrorStr
dstr "rst 38 error"
.unknownErrorStr
dstr "Unk err $"
AFStr:
dstr "AF:"
BCStr:
dstr "BC:"
DEStr:
dstr "DE:"
HLStr:
dstr "HL:"
SPstr:
dstr "SP:"
ViewStr:
dstr "View:"
MemRegs:
dstr "STAT:"
dw rSTAT
dstr "IE:"
dw rIE
db 0
BankStr:
dstr "Bank:"
ErrorFont:
REPT " " - 1
dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000
ENDR
dw $0000, $0000, $0800, $0C00, $0800, $0000, $0000, $0000 ; Empty arrow
dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 ; Space
; Symbols 1
dw $8000, $8000, $8000, $8000, $8000, $0000, $8000, $0000
dw $0000, $6C00, $6C00, $4800, $0000, $0000, $0000, $0000
dw $4800, $FC00, $4800, $4800, $4800, $FC00, $4800, $0000
dw $1000, $7C00, $9000, $7800, $1400, $F800, $1000, $0000
dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 ; %, empty slot for now
dw $6000, $9000, $5000, $6000, $9400, $9800, $6C00, $0000
dw $0000, $3800, $3800, $0800, $1000, $0000, $0000, $0000
dw $1800, $2000, $2000, $2000, $2000, $2000, $1800, $0000
dw $1800, $0400, $0400, $0400, $0400, $0400, $1800, $0000
dw $0000, $1000, $5400, $3800, $5400, $1000, $0000, $0000
dw $0000, $1000, $1000, $7C00, $1000, $1000, $0000, $0000
dw $0000, $0000, $0000, $0000, $3000, $3000, $6000, $0000
dw $0000, $0000, $0000, $7C00, $0000, $0000, $0000, $0000
dw $0000, $0000, $0000, $0000, $0000, $6000, $6000, $0000
dw $0000, $0400, $0800, $1000, $2000, $4000, $8000, $0000
dw $3000, $5800, $CC00, $CC00, $CC00, $6800, $3000, $0000
dw $3000, $7000, $F000, $3000, $3000, $3000, $FC00, $0000
dw $7800, $CC00, $1800, $3000, $6000, $C000, $FC00, $0000
dw $7800, $8C00, $0C00, $3800, $0C00, $8C00, $7800, $0000
dw $3800, $5800, $9800, $FC00, $1800, $1800, $1800, $0000
dw $FC00, $C000, $C000, $7800, $0C00, $CC00, $7800, $0000
dw $7800, $CC00, $C000, $F800, $CC00, $CC00, $7800, $0000
dw $FC00, $0C00, $0C00, $1800, $1800, $3000, $3000, $0000
dw $7800, $CC00, $CC00, $7800, $CC00, $CC00, $7800, $0000
dw $7800, $CC00, $CC00, $7C00, $0C00, $CC00, $7800, $0000
dw $0000, $C000, $C000, $0000, $C000, $C000, $0000, $0000
dw $0000, $C000, $C000, $0000, $C000, $4000, $8000, $0000
dw $0400, $1800, $6000, $8000, $6000, $1800, $0400, $0000
dw $0000, $0000, $FC00, $0000, $FC00, $0000, $0000, $0000
dw $8000, $6000, $1800, $0400, $1800, $6000, $8000, $0000
dw $7800, $CC00, $1800, $3000, $2000, $0000, $2000, $0000
dw $0000, $2000, $7000, $F800, $F800, $F800, $0000, $0000 ; "Up" arrow, not ASCII but otherwise unused :P
; Uppercase
dw $3000, $4800, $8400, $8400, $FC00, $8400, $8400, $0000
dw $F800, $8400, $8400, $F800, $8400, $8400, $F800, $0000
dw $3C00, $4000, $8000, $8000, $8000, $4000, $3C00, $0000
dw $F000, $8800, $8400, $8400, $8400, $8800, $F000, $0000
dw $FC00, $8000, $8000, $FC00, $8000, $8000, $FC00, $0000
dw $FC00, $8000, $8000, $FC00, $8000, $8000, $8000, $0000
dw $7C00, $8000, $8000, $BC00, $8400, $8400, $7800, $0000
dw $8400, $8400, $8400, $FC00, $8400, $8400, $8400, $0000
dw $7C00, $1000, $1000, $1000, $1000, $1000, $7C00, $0000
dw $0400, $0400, $0400, $0400, $0400, $0400, $F800, $0000
dw $8400, $8800, $9000, $A000, $E000, $9000, $8C00, $0000
dw $8000, $8000, $8000, $8000, $8000, $8000, $FC00, $0000
dw $8400, $CC00, $B400, $8400, $8400, $8400, $8400, $0000
dw $8400, $C400, $A400, $9400, $8C00, $8400, $8400, $0000
dw $7800, $8400, $8400, $8400, $8400, $8400, $7800, $0000
dw $F800, $8400, $8400, $F800, $8000, $8000, $8000, $0000
dw $7800, $8400, $8400, $8400, $A400, $9800, $6C00, $0000
dw $F800, $8400, $8400, $F800, $9000, $8800, $8400, $0000
dw $7C00, $8000, $8000, $7800, $0400, $8400, $7800, $0000
dw $7C00, $1000, $1000, $1000, $1000, $1000, $1000, $0000
dw $8400, $8400, $8400, $8400, $8400, $8400, $7800, $0000
dw $8400, $8400, $8400, $8400, $8400, $4800, $3000, $0000
dw $8400, $8400, $8400, $8400, $B400, $CC00, $8400, $0000
dw $8400, $8400, $4800, $3000, $4800, $8400, $8400, $0000
dw $4400, $4400, $4400, $2800, $1000, $1000, $1000, $0000
dw $FC00, $0400, $0800, $1000, $2000, $4000, $FC00, $0000
; Symbols 2
dw $3800, $2000, $2000, $2000, $2000, $2000, $3800, $0000
dw $0000, $8000, $4000, $2000, $1000, $0800, $0400, $0000
dw $1C00, $0400, $0400, $0400, $0400, $0400, $1C00, $0000
dw $1000, $2800, $0000, $0000, $0000, $0000, $0000, $0000
dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $FF00
dw $C000, $6000, $0000, $0000, $0000, $0000, $0000, $0000
; Lowercase
dw $0000, $0000, $7800, $0400, $7C00, $8400, $7800, $0000
dw $8000, $8000, $8000, $F800, $8400, $8400, $7800, $0000
dw $0000, $0000, $7C00, $8000, $8000, $8000, $7C00, $0000
dw $0400, $0400, $0400, $7C00, $8400, $8400, $7800, $0000
dw $0000, $0000, $7800, $8400, $F800, $8000, $7C00, $0000
dw $0000, $3C00, $4000, $FC00, $4000, $4000, $4000, $0000
dw $0000, $0000, $7800, $8400, $7C00, $0400, $F800, $0000
dw $8000, $8000, $F800, $8400, $8400, $8400, $8400, $0000
dw $0000, $1000, $0000, $1000, $1000, $1000, $1000, $0000
dw $0000, $1000, $0000, $1000, $1000, $1000, $E000, $0000
dw $8000, $8000, $8400, $9800, $E000, $9800, $8400, $0000
dw $1000, $1000, $1000, $1000, $1000, $1000, $1000, $0000
dw $0000, $0000, $6800, $9400, $9400, $9400, $9400, $0000
dw $0000, $0000, $7800, $8400, $8400, $8400, $8400, $0000
dw $0000, $0000, $7800, $8400, $8400, $8400, $7800, $0000
dw $0000, $0000, $7800, $8400, $8400, $F800, $8000, $0000
dw $0000, $0000, $7800, $8400, $8400, $7C00, $0400, $0000
dw $0000, $0000, $BC00, $C000, $8000, $8000, $8000, $0000
dw $0000, $0000, $7C00, $8000, $7800, $0400, $F800, $0000
dw $0000, $4000, $F800, $4000, $4000, $4000, $3C00, $0000
dw $0000, $0000, $8400, $8400, $8400, $8400, $7800, $0000
dw $0000, $0000, $8400, $8400, $4800, $4800, $3000, $0000
dw $0000, $0000, $8400, $8400, $8400, $A400, $5800, $0000
dw $0000, $0000, $8C00, $5000, $2000, $5000, $8C00, $0000
dw $0000, $0000, $8400, $8400, $7C00, $0400, $F800, $0000
dw $0000, $0000, $FC00, $0800, $3000, $4000, $FC00, $0000
; Symbols 3
dw $1800, $2000, $2000, $4000, $2000, $2000, $1800, $0000
dw $1000, $1000, $1000, $1000, $1000, $1000, $1000, $0000
dw $3000, $0800, $0800, $0400, $0800, $0800, $3000, $0000
dw $0000, $0000, $4800, $A800, $9000, $0000, $0000, $0000
dw $0000, $0800, $0C00, $0E00, $0C00, $0800, $0000, $0000 ; Left arrow
ErrorUwu:
db "OOPSIE WOOPSIE!! Uwu "
db " We made a fucky "
db " wucky!! A wittle "
db " fucko boingo! The "
db "code monkeys at our "
db " headquarters are "
db "working VEWY HAWD to "
db " fix this! ",0
db " "
db "More seriously, I'm "
db "sorry, but the game "
db "has encountered a "
db "fatal error blah "
db "blah blah, tl;dr it "
db "has crashed. "
db "To allow us to fix "
db "it, please be a "
db "peach and press A =3",0

View File

@@ -1,8 +0,0 @@
SECTION "Init code", ROMX
Init::
ret

21
src/header.asm Normal file
View File

@@ -0,0 +1,21 @@
SECTION "Header", ROM0[$100]
; This is your ROM's entry point
; You have 4 bytes of code to do... something
di
jp EntryPoint
; Make sure to allocate some space for the header, so no important
; code gets put there and later overwritten by RGBFIX.
; RGBFIX is designed to operate over a zero-filled header, so make
; sure to put zeros regardless of the padding value. (This feature
; was introduced in RGBDS 0.4.0, but the -MG etc flags were also
; introduced in that version.)
ds $150 - @, 0
SECTION "Entry point", ROM0
EntryPoint:
; Here is where the fun begins, happy coding :)
jr @

View File

@@ -1,10 +0,0 @@
INCLUDE "constants.asm"
INCLUDE "macros.asm"
INCLUDE "home/vectors.asm"
INCLUDE "home/header.asm"
INCLUDE "home/utils.asm"
INCLUDE "home/sgb.asm"
INCLUDE "home/unpb16.asm"

View File

@@ -1,104 +0,0 @@
NB_ROM_BANKS = 2
SECTION "Header", ROM0[$100]
EntryPoint::
ld b, $60
jr LogoFade
dbr 0, $150 - $104
; Header ends here
LogoFade:
xor a
ldh [rAUDENA], a
.fadeLogo
ld c, 7 ; Number of frames between each logo fade step
.logoWait
ld a, [rLY]
cp a, SCRN_Y
jr nc, .logoWait
.waitVBlank
ld a, [rLY]
cp a, SCRN_Y
jr c, .waitVBlank
dec c
jr nz, .logoWait
; Shift all colors (fading the logo progressively)
ld a, b
rra
rra
and $FC ; Ensures a proper rotation and sets Z for final check
ldh [rBGP], a
ld b, a
jr nz, .fadeLogo ; End if the palette is fully blank (flag set from `and $FC`)
; xor a
ldh [rDIV], a
Reset::
di
ld sp, wStackBottom
xor a
ldh [rAUDENA], a
.waitVBlank
ld a, [rLY]
cp SCRN_Y
jr c, .waitVBlank
xor a
ldh [rLCDC], a
; Perform some init
; xor a
ldh [rAUDENA], a
; Init HRAM
; Also clears IE, but we're gonna overwrite it just after
ld c, LOW(hClearStart)
.clearHRAM
xor a
ld [$ff00+c], a
inc c
jr nz, .clearHRAM
; Copy OAM DMA routine
ld hl, OAMDMA
lb bc, OAMDMAEnd - OAMDMA, LOW(hOAMDMA)
.copyOAMDMA
ld a, [hli]
ld [$ff00+c], a
inc c
dec b
jr nz, .copyOAMDMA
ld a, LCDCF_ON | LCDCF_BGON
ldh [hLCDC], a
ldh [rLCDC], a
ld a, IEF_VBLANK
ldh [rIE], a
xor a
ei ; Delayed until the next instruction: perfectly safe!
ldh [rIF], a
; Init code goes here
SECTION "OAM DMA routine", ROM0
OAMDMA:
ldh [rDMA], a
ld a, $28
.wait
dec a
jr nz, .wait
ret
OAMDMAEnd:

View File

@@ -1,130 +0,0 @@
SECTION "SGB routines", ROM0
; Sends SGB packets to the SGB, assuming we're running on one.
; @param hl Pointer to the packet data to be sent (can send any number of packets btw)
; @return hl Points to the end of the packet data
; @return de Zero
; @return bc Zero
; @return a Zero
SendPackets::
ld a, [hl] ; Length
and %111
ret z
ld c, a
.sendPacket
call SendPacketNoDelay
call SGBDelay ; Let the ICD chip rest a bit
dec c
jr nz, .sendPacket
ret
; Sends a SGB packet to the SGB to freeze the screen, assuming we're running on one.
; Does not perform any delay after sending the packet.
; Use only if you're not going to send another SGB packet in the next few frames.
; You're likely to perform some decompression or smth after this
; @param hl Pointer to the packet data to be sent.
; @return hl Points to the end of the packet data
; @return b Zero
; @return d Zero
; @return a $30
; @destroy e
FreezeSGBScreen::
ld hl, FreezeScreenPacket
; Sends a SGB packet to the SGB, assuming it's running on one.
; Does not perform any delay after sending the packet.
; Unsuitable to send multi-packet packets.
; Use only if you're not going to send another SGB packet in the next four frames.
; Assumes the joypad won't be polled by interrupts during this time, but since the VBlank handler doesn't poll except when waited for, this is fine.
; @param hl Pointer to the packet data to be sent.
; @return hl Points to the end of the packet data
; @return b Zero
; @return d Zero
; @return a $30
; @destroy e
SendPacketNoDelay::
; Packet transmission begins by sending $00 then $30
xor a
ldh [rP1], a
ld a, $30
ldh [rP1], a
ld b, SGB_PACKET_SIZE
.sendByte
ld d, 8 ; 8 bits in a byte
ld a, [hli] ; Read byte to send
ld e, a
.sendBit
ld a, $10 ; 1 bits are sent with $10
rr e ; Rotate d and get its lower bit, two birds in one stone!
jr c, .bitSet
add a, a ; 0 bits are sent with $20
.bitSet
ldh [rP1], a
ld a, $30 ; Terminate pulse
ldh [rP1], a
dec d
jr nz, .sendBit
dec b
jr nz, .sendByte
; Packets are terminated by a "STOP" 0 bit
ld a, $20
ldh [rP1], a
ld a, $30
ldh [rP1], a
ret
SGBDelay::
ld de, 7000 ; Magic value, apparently
.loop
nop
nop
nop
dec de
ld a, d
or e
jr nz, .loop
ret
FreezeScreenPacket:
sgb_packet MASK_EN, 1, 1
; Fill the $9C00 tilemap with a pattern suitable for SGB _TRN
; Also sets up the rendering parameters for the transfer
; Finally, assumes the LCD is **off**
; @return hl
FillScreenWithSGBMap::
xor a
ldh [hSCY], a
ldh [hSCX], a
ld b, a ; ld b, 0
ld hl, $9C00
.writeRow
ld c, SCRN_X_B
.writeTile
ld a, b
ld [hli], a
inc b
jr z, .done
dec c
jr nz, .writeTile
ld a, l
add a, SCRN_VX_B - SCRN_X_B
ld l, a
jr nc, .writeRow
inc h
jr .writeRow
.done
ld a, %11100100
ldh [hBGP], a
SetupSGBLCDC::
ld a, LCDCF_ON | LCDCF_WINOFF | LCDCF_BG8000 | LCDCF_BG9C00 | LCDCF_OBJOFF | LCDCF_BGON
ldh [rLCDC], a
ldh [hLCDC], a
ret

View File

@@ -1,89 +0,0 @@
;
; PB16 decompression for Game Boy
; Copyright 2018 Damian Yerrick
;
; This software is provided 'as-is', without any express or implied
; warranty. In no event will the authors be held liable for any damages
; arising from the use of this software.
;
; Permission is granted to anyone to use this software for any purpose,
; including commercial applications, and to alter it and redistribute it
; freely, subject to the following restrictions:
;
; 1. The origin of this software must not be misrepresented; you must not
; claim that you wrote the original software. If you use this software
; in a product, an acknowledgment in the product documentation would be
; appreciated but is not required.
; 2. Altered source versions must be plainly marked as such, and must not be
; misrepresented as being the original software.
; 3. This notice may not be removed or altered from any source distribution.
;
; This software has been modified by Eldred Habert (ISSOtm):
; - Removal of .inc file
; - Removal of variable allocation
section "pb16", ROM0
; The PB16 format is a starting point toward efficient RLE image
; codecs on Game Boy and Super NES.
;
; 0: Load a literal byte
; 1: Repeat from 2 bytes ago
pb16_unpack_packet:
; Read first bit of control byte. Treat B as a ring counter with
; a 1 bit as the sentinel. Once the 1 bit reaches carry, B will
; become 0, meaning the 8-byte packet is complete.
ld a,[de]
inc de
scf
rla
ld b,a
.byteloop:
; If the bit from the control byte is clear, plane 0 is is literal
jr nc,.p0_is_literal
ldh a,[pb16_byte0]
jr .have_p0
.p0_is_literal:
ld a,[de]
inc de
ldh [pb16_byte0],a
.have_p0:
ld [hl+],a
; Read next bit. If it's clear, plane 1 is is literal.
ld a,c
sla b
jr c,.have_p1
.p1_is_copy:
ld a,[de]
inc de
ld c,a
.have_p1:
ld [hl+],a
; Read next bit of control byte
sla b
jr nz,.byteloop
ret
;;
; Unpacks 2*B packets from DE to HL, producing 8 bytes per packet.
; About 127 cycles (2 scanlines) per 8-byte packet; filling CHR RAM
; thus takes (6144/8)*127 = about 97536 cycles or 93 ms
pb16_unpack_block::
; Prefill with zeroes
xor a
ldh [pb16_byte0],a
ld c,a
.packetloop:
push bc
call pb16_unpack_packet
call pb16_unpack_packet
ld a,c
pop bc
ld c,a
dec b
jr nz,.packetloop
ret

View File

@@ -1,192 +0,0 @@
; Since all these functions are independent, declare each of them in individual sections
; Lets the linker place them more liberally. Hooray!
f: MACRO
PURGE \1
SECTION "Utility function \1", ROM0
\1::
ENDM
SECTION "Dummy section", ROM0 ; To have the first `Memcpy` declare properly
; Copies bc bytes of data from de to hl
Memcpy::
f Memcpy
ld a, [de]
ld [hli], a
inc de
dec bc
ld a, b
or c
jr nz, Memcpy
ret
; Copies a null-terminated string from de to hl, including the terminating NUL
Strcpy::
f Strcpy
ld a, [de]
ld [hli], a
inc de
and a
jr nz, Strcpy
ret
; Copies c bytes of data from de to hl in a LCD-safe manner
LCDMemcpySmall::
f LCDMemcpySmall
ldh a, [rSTAT]
and STATF_BUSY
jr nz, LCDMemcpySmall
ld a, [de]
ld [hli], a
inc de
dec c
jr nz, LCDMemcpySmall
ret
; Copies bc bytes of data from de to hl in a LCD-safe manner
LCDMemcpy::
f LCDMemcpy
ldh a, [rSTAT]
and STATF_BUSY
jr nz, LCDMemcpy
ld a, [de]
ld [hli], a
inc de
dec bc
ld a, b
or c
jr nz, LCDMemcpy
ret
; Sets c bytes of data at hl with the value in a
LCDMemsetSmall::
f LCDMemsetSmall
ld b, a
; Sets c bytes of data at hl with the value in b
LCDMemsetSmallFromB::
; No f (...) because there's the slide-in above
.loop
ldh a, [rSTAT]
and STATF_BUSY
jr nz, .loop
ld a, b
ld [hli], a
dec c
jr nz, .loop
ret
; Sets bc bytes of data at hl with the value in a
LCDMemset::
f LCDMemset
ld d, a
; Sets bc bytes of data at hl with the value in d
LCDMemsetFromD::
; No f (...) because of the slide-in above
.loop
ldh a, [rSTAT]
and STATF_BUSY
jr nz, .loop
ld a, d
ld [hli], a
dec bc
ld a, b
or c
jr nz, .loop
ret
; Opens SRAM at some bank
; @param a The bank's number
; @return a CART_RAM_ENABLE, ie. $0A
GetSRAMBank::
f GetSRAMBank
ld [rRAMB], a
ld a, CART_RAM_ENABLE
ld [rRAMG], a
ret
; Closes SRAM
; @return hl = rRAMB (I know, it sounds stupid)
CloseSRAM::
f CloseSRAM
; Implementation note: MUST preserve the Z flag to avoid breaking the call to `PrintSRAMFailure`
ld hl, rRAMG
ld [hl], l ; ld [hl], 0
ld h, HIGH(rRAMB)
ld [hl], l ; Avoid unintentional unlocks corrupting saved data, switch to bank 0 (which is scratch)
ret
; Gets the Nth struct in an array of 'em
; @param hl Array base
; @param bc Size of a struct
; @param a ID of the desired struct
; @return hl Pointer to the struct's base
; @destroys a
GetNthStruct::
f GetNthStruct
and a
ret z
.next
add hl, bc
dec a
jr nz, .next
ret
; Copies tiles into VRAM, using an unrolled loop to go faster
; @param hl Destination (pointer)
; @param de Source
; @param c Number of tiles
; @return hl, de Pointer to end of blocks
; @return c 0
; @destroys a
Tilecpy::
f Tilecpy
REPT $10 / 2
wait_vram
ld a, [de]
ld [hli], a
inc de
ld a, [de]
ld [hli], a
inc de
ENDR
dec c
jr nz, Tilecpy
ret
; Copies a tilemap to VRAM, assuming the LCD is off
; @param hl Destination
; @param de Source
; @return hl, de Pointer to end of blocks
; @return bc Zero
; @return a Equal to h
Mapcpy::
f Mapcpy
ld b, SCRN_Y_B
.copyRow
ld c, SCRN_X_B
.copyTile
ld a, [de]
ld [hli], a
inc de
dec c
jr nz, .copyTile
ld a, l
add a, SCRN_VX_B - SCRN_X_B
ld l, a
adc a, h
sub l
ld h, a
dec b
jr nz, .copyRow
ret
PURGE f

View File

@@ -1,226 +0,0 @@
SECTION "rst00", ROM0[$0000]
; Please do not call
; Traps execution errors (mostly to $FFFF / $0000)
rst00:
; Pad, in case we come from FFFF and read a 2-byte operand
nop
nop
jp NullExecError
SECTION "rst08", ROM0[$0008]
; Please call using `rst memcpy_small`
; Copies c bytes of data from de to hl
MemcpySmall:
ld a, [de]
ld [hli], a
inc de
dec c
jr nz, MemcpySmall
EmptyFunc::
ret
SECTION "rst10", ROM0[$0010]
; Please call using `rst memset_small`
; Sets c bytes at hl with the value in a
MemsetSmall:
ld [hli], a
dec c
jr nz, MemsetSmall
ret
SECTION "rst18", ROM0[$0017]
; Please do not call. Use `rst memset`, or, if absolutely needed, `call rst18`.
; Sets bc bytes at hl with the value in d
Memset:
ld a, d
; Please call using `rst memset`
; Sets bc bytes at hl with the value in a
rst18:
ld d, a
ld [hli], a
dec bc
ld a, b
or c
jr nz, Memset
ret
SECTION "rst20", ROM0[$0020]
; Please call using `rst bankswitch`
; Properly switches to a ROM bank
; @param a The ROM bank to switch to
; NOTE: only switches the lower 8 bytes, the upper bit (for 512 banks) is not considered
ROMbankswitch:
ldh [hCurROMBank], a
ld [rROMB0], a
ret
SECTION "rst28", ROM0[$0028]
; Please call using `rst call_hl`
; Jumps to hl. Use as a placeholder for `call hl`!
; Will error out if the target is in RAM
CallHL:
bit 7, h ; Prevent jumping into RAM (doesn't protec against returning to it, but hey :D)
jr nz, .err
jp hl
.err
jp HLJumpingError
SECTION "rst30", ROM0[$0030]
; Please call using `rst wait_vblank`
; Waits for the VBlank interrupt
; Note: if the interrupt occurs without being waited for, it will skip performing some actions
WaitVBlank:
xor a
ldh [hVBlankFlag], a
.waitVBlank
halt
jr z, .waitVBlank
ret
SECTION "rst38", ROM0[$0038]
; Please do not call
; Traps execution of the $FF byte (which serves as padding of the ROM)
rst38:
jp Rst38Error
SECTION "Interrupt vectors", ROM0[$0040]
transfer_reg: MACRO
ldh a, [h\1]
ldh [r\1], a
ENDM
; VBlank
push af
transfer_reg LCDC
jp VBlankHandler
; LCD
reti
ds 7
; Timer
reti
ds 7
; Serial
reti
; Fit in a 7-byte function, too!
; Jumps immediately to de, no questions asked (except RAM targets?).
CallDE::
push de
bit 7, d
ret z
jp DEJumpingError
; Joypad
reti
SECTION "VBlank handler", ROM0
VBlankHandler:
push bc
; ============= Here are things that need to be updated, even on lag frames ==============
; Update IO from HRAM shadow
transfer_reg SCY
transfer_reg SCX
transfer_reg WY
transfer_reg WX
; Update OAM if needed
; Do this last so it will go through even without time
; This will simply cause sprites to not be displayed on the top few scanlines, but that's not as bad as palettes not loading at all, huh?
ldh a, [hOAMBufferHigh]
and a
jr z, .dontUpdateOAM
ld b, a
; Reset OAM buffer high vect
xor a
ldh [hOAMBufferHigh], a
; Perform DMA as specified
ld a, b
call hOAMDMA
.dontUpdateOAM
; ============== In case of lag, don't update further, to avoid breaking stuff ===============
ldh a, [hVBlankFlag]
and a
jr nz, .lagFrame
; Poll joypad and update regs
ld c, LOW(rP1)
ld a, $20 ; Select D-pad
ld [$ff00+c], a
REPT 6
ld a, [$ff00+c]
ENDR
or $F0 ; Set 4 upper bits (give them consistency)
ld b, a
; Filter impossible D-pad combinations
and $0C ; Filter only Down and Up
ld a, b
jr nz, .notUpAndDown
or $0C ; If both are pressed, "unpress" them
ld b, a
.notUpAndDown
and $03 ; Filter only Left and Right
jr nz, .notLeftAndRight
ld a, b
or $03 ; If both are pressed, "unpress" them
ld b, a
.notLeftAndRight
swap b ; Put D-pad buttons in upper nibble
ld a, $10 ; Select buttons
ld [$ff00+c], a
REPT 6
ld a, [$ff00+c]
ENDR
; On SsAB held, soft-reset
and $0F
jp z, Reset
or $F0 ; Set 4 upper bits
xor b ; Mix with D-pad bits, and invert all bits (such that pressed=1) thanks to "or $F0"
ld b, a
ldh a, [hHeldButtons]
cpl
and b
ldh [hPressedButtons], a
ld a, b
ldh [hHeldButtons], a
; Release joypad
ld a, $30
ld [$ff00+c], a
pop bc
pop af
; The main code was waiting for VBlank, so tell it it's OK by resetting Z
xor a
inc a ; Clear Z
ldh [hVBlankFlag], a ; Mark VBlank as ACK'd
reti
.lagFrame
pop bc
pop af
reti

View File

@@ -1,5 +0,0 @@
INCLUDE "macros/structs.asm"
INCLUDE "macros/struct_decls.asm"
INCLUDE "macros/pseudo_instr.asm"
INCLUDE "macros/misc.asm"

View File

@@ -1,127 +0,0 @@
; dbr value, nb_times
; Writes nb_times consecutive bytes with value.
dbr: MACRO
REPT \2
db \1
ENDR
ENDM
; dwr value, nb_times
; Writes nb_times consecutive words with value.
dwr: MACRO
REPT \2
dw \1
ENDR
ENDM
; db's everything given to it, and terminates with a NUL
; For strings, obviously.
dstr: MACRO
REPT _NARG
db \1
shift
ENDR
db 0
ENDM
; Places a sprite's data, but with screen coords instead of OAM coords
dspr: MACRO
db LOW(\1 + 16)
db LOW(\2 + 8)
db \3
db \4
ENDM
; dwcoord y, x, base
dwcoord: MACRO
dw (\1) * SCRN_VX_B + (\2) + (\3)
ENDM
; dptr symbol
; Places a symbol's bank and ptr
;
; dptr symbol_b, symbol_p
; Places a symbol's bank and another's ptr
; Useful for expressions: `dptr Label, Label+1`
dptr: MACRO
db BANK(\1)
IF _NARG < 2
dw \1
ELSE
dw \2
ENDC
ENDM
lda: MACRO
IF \1 == 0
xor a
ELSE
ld a, \1
ENDC
ENDM
lb: MACRO
ld \1, ((\2) << 8) | (\3)
ENDM
ln: MACRO
REGISTER\@ = \1
VALUE\@ = 0
INDEX\@ = 1
REPT _NARG
shift
INDEX\@ = INDEX\@ + 1
IF \1 > $0F
FAIL "Argument {INDEX} to `ln` must be a 4-bit value!"
ENDC
VALUE\@ = VALUE\@ << 8 | \1
ENDR
ld REGISTER\@, VALUE\@
PURGE REGISTER\@
PURGE VALUE\@
PURGE INDEX\@
ENDM
; ldcoord reg16, y, x, base
ldcoord: MACRO
IF "\1" == "bc"
db $01
ELIF "\1" == "de"
db $11
ELIF "\1" == "hl"
db $21
ELIF "\1" == "sp"
db $31
ELSE
FAIL "Invalid 1st operand to ldcoord, \1 is not a 16-bit register"
ENDC
dwcoord \2, \3, \4
ENDM
; sgb_packet packet_type, nb_packets,
sgb_packet: MACRO
SGBPacket:
db (\1 << 3) | (\2)
NB_REPT = _NARG + (-2)
REPT NB_REPT
SHIFT
db \2
ENDR
PURGE NB_REPT
SGBPacketEnd:
PACKET_SIZE = SGBPacketEnd - SGBPacket
IF PACKET_SIZE != SGB_PACKET_SIZE
dbr 0, SGB_PACKET_SIZE - PACKET_SIZE
ENDC
PURGE SGBPacket
PURGE SGBPacketEnd
PURGE PACKET_SIZE
ENDM

View File

@@ -1,16 +0,0 @@
wait: MACRO
ld c, \1
.delay\@
rst wait_vblank
dec c
jr nz, .delay\@
ENDM
wait_vram: MACRO
.waitVRAM\@
ldh a, [rSTAT]
and STATF_BUSY
jr nz, .waitVRAM\@
ENDM

View File

@@ -1,156 +0,0 @@
; MIT License
;
; Copyright (c) 2018 Eldred Habert
; Originally hosted at https://github.com/ISSOtm/rgbds-structs
;
; Permission is hereby granted, free of charge, to any person obtaining a copy
; of this software and associated documentation files (the "Software"), to deal
; in the Software without restriction, including without limitation the rights
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
; copies of the Software, and to permit persons to whom the Software is
; furnished to do so, subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in all
; copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
; SOFTWARE.
; struct struct_name
; Begins a struct declaration
struct: MACRO
IF DEF(NB_FIELDS)
FAIL "Please close struct definitions using `end_struct`"
ENDC
STRUCT_NAME equs "\1"
NB_FIELDS = 0
RSRESET
ENDM
; end_struct
; Ends a struct declaration
end_struct: MACRO
; Set nb of fields
STRUCT_NB_FIELDS equs "{STRUCT_NAME}_nb_fields"
STRUCT_NB_FIELDS = NB_FIELDS
PURGE STRUCT_NB_FIELDS
; Set size of struct
STRUCT_SIZEOF equs "sizeof_{STRUCT_NAME}"
STRUCT_SIZEOF RB 0
PURGE STRUCT_SIZEOF
PURGE NB_FIELDS
PURGE STRUCT_NAME
ENDM
; field_name_from_id field_id
; For internal use, please do not use externally
field_name_from_id: MACRO
FIELD_ID_STR equs "{\1}"
STRUCT_FIELD equs STRCAT("{STRUCT_NAME}_field", STRSUB("{FIELD_ID_STR}", 2, STRLEN("{FIELD_ID_STR}") - 1))
STRUCT_FIELD_NAME equs "{STRUCT_FIELD}_name"
STRUCT_FIELD_SIZE equs "{STRUCT_FIELD}_size"
ENDM
; new_field nb_elems, rs_type, field_name
; For internal use, please do not use externally
new_field: MACRO
IF !DEF(STRUCT_NAME) || !DEF(NB_FIELDS)
FAIL "Please start defining a struct, using `define_struct`"
ENDC
field_name_from_id NB_FIELDS
; Set field name
STRUCT_FIELD_NAME equs "\"\3\""
PURGE STRUCT_FIELD_NAME
; Set field offset
STRUCT_FIELD \2 (\1)
; Alias this in a human-comprehensive manner
STRUCT_FIELD_NAME equs "{STRUCT_NAME}_\3"
STRUCT_FIELD_NAME = STRUCT_FIELD
; Calculate field size
CURRENT_RS RB 0
STRUCT_FIELD_SIZE = CURRENT_RS - STRUCT_FIELD
PURGE FIELD_ID_STR
PURGE STRUCT_FIELD
PURGE STRUCT_FIELD_NAME
PURGE STRUCT_FIELD_SIZE
PURGE CURRENT_RS
NB_FIELDS = NB_FIELDS + 1
ENDM
; bytes nb_bytes, field_name
; Defines a field of N bytes
bytes: MACRO
new_field \1, RB, \2
ENDM
; words nb_words, field_name
; Defines a field of N*2 bytes
words: MACRO
new_field \1, RW, \2
ENDM
; longs nb_longs, field_name
; Defines a field of N*4 bytes
longs: MACRO
new_field \1, RL, \2
ENDM
; dstruct struct_type, var_name
; Allocates space for a struct in memory (primarily RAM)
dstruct: MACRO
NB_FIELDS equs "\1_nb_fields"
IF !DEF(NB_FIELDS)
FAIL "Struct \1 isn't defined!"
ENDC
STRUCT_NAME equs "\1" ; Target this struct for `field_name_from_id`
\2:: ; Declare the struct's root
FIELD_ID = 0
REPT NB_FIELDS
field_name_from_id FIELD_ID
FIELD_NAME equs STRCAT("\2_", STRUCT_FIELD_NAME)
FIELD_NAME::
ds STRUCT_FIELD_SIZE
; Clean up vars for next iteration
PURGE FIELD_ID_STR
PURGE STRUCT_FIELD
PURGE STRUCT_FIELD_NAME
PURGE STRUCT_FIELD_SIZE
PURGE FIELD_NAME
FIELD_ID = FIELD_ID + 1
ENDR
; Define variable's properties from struct's
\2_nb_fields = NB_FIELDS
sizeof_\2 = sizeof_\1
; Clean up
PURGE NB_FIELDS
PURGE STRUCT_NAME
PURGE FIELD_ID
ENDM

View File

@@ -1,7 +0,0 @@
INCLUDE "constants.asm"
INCLUDE "macros.asm"
INCLUDE "memory/vram.asm"
INCLUDE "memory/sram.asm"
INCLUDE "memory/wram.asm"
INCLUDE "memory/hram.asm"

View File

@@ -1,57 +0,0 @@
SECTION "HRAM", HRAM
; The OAM DMA routine
hOAMDMA::
ds 8 ; OAMDMAEnd - OAMDMA
; Currently-loaded ROM bank, useful to save back (eg. during ints)
hCurROMBank::
db
; Used by the PB16 decompressor
pb16_byte0::
db
; Place variables that need to be zero-cleared on init (and soft-reset) below
hClearStart::
; Used to let VBlank know it need to ACK
; NOTE: VBlank doesn't preserve AF **on purpose** when this is set
; Thus, make sure to wait for Z set before continuing
hVBlankFlag::
db
; Values transferred to hw regs on VBlank
hLCDC::
db
hSCY::
db
hSCX::
db
hWY::
db
hWX::
db
hBGP::
db
hOBP0::
db
hOBP1::
db
; Joypad regs
hHeldButtons::
db
hPressedButtons::
db
; High byte of the shadow OAM buffer to be transferred
; Reset by the VBlank handler to signal transfer completion
hOAMBufferHigh::
db

View File

View File

@@ -1,20 +0,0 @@
SECTION "VRAM", VRAM[$8000]
ds $1000
; $9000
vBlankTile::
ds $10
ds $7F0
; $9800
ds SCRN_VX_B * SCRN_VY_B ; $400
; $9C00
ds SCRN_VX_B * SCRN_VY_B ; $400

View File

@@ -1,40 +0,0 @@
SECTION "Error handler memory", WRAM0
; ID of the error that occurred
wErrorType::
; Once the ID has been used, this is re-used as a status, to route calls because stack space is available
wErrorDrawStatus::
; The status is also used to determine which dump to print
wErrorWhichDump::
db
wErrorRegs::
; Value of A when the handler is called
; Re-used as part of the reg dump
wErrorA::
; Re-used to hold last frame's keys
wErrorHeldButtons::
db ; a
; Re-used to hold the number of frames till the debugger is unlocked
wErrorFramesTillUnlock::
db ; f
dw ; bc
dw ; de
wErrorHL::
dw
wErrorSP::
dw
SECTION "Shadow OAM", WRAM0,ALIGN[8]
wShadowOAM::
ds $A0
SECTION "Stack", WRAM0[$E000 - STACK_SIZE]
wStackTop::
ds STACK_SIZE
wStackBottom::