mirror of
https://github.com/gbdk-2020/gbdk-2020.git
synced 2026-02-20 00:32:21 +01:00
522 lines
16 KiB
ArmAsm
522 lines
16 KiB
ArmAsm
_VRAM = 0x8000 ; $8000->$9FFF
|
|
_VRAM8000 = 0x8000
|
|
_VRAM8800 = 0x8800
|
|
_VRAM9000 = 0x9000
|
|
_SCRN0 = 0x9800 ; $9800->$9BFF
|
|
_SCRN1 = 0x9C00 ; $9C00->$9FFF
|
|
_SRAM = 0xA000 ; $A000->$BFFF
|
|
_RAM = 0xC000 ; $C000->$CFFF / $C000->$DFFF
|
|
_RAMBANK = 0xD000 ; $D000->$DFFF
|
|
_OAMRAM = 0xFE00 ; $FE00->$FE9F
|
|
_IO = 0xFF00 ; $FF00->$FF7F,$FFFF
|
|
_AUD3WAVERAM = 0xFF30 ; $FF30->$FF3F
|
|
_HRAM = 0xFF80 ; $FF80->$FFFE
|
|
|
|
;; MBC Equates
|
|
|
|
rRAMG = 0x0000 ; $0000->$1fff
|
|
rROMB0 = 0x2000 ; $2000->$2fff
|
|
rROMB1 = 0x3000 ; $3000->$3fff - If more than 256 ROM banks are present.
|
|
rRAMB = 0x4000 ; $4000->$5fff - Bit 3 enables rumble (if present)
|
|
|
|
;; Keypad
|
|
.UP = 0x04
|
|
.DOWN = 0x08
|
|
.LEFT = 0x02
|
|
.RIGHT = 0x01
|
|
.A = 0x10
|
|
.B = 0x20
|
|
.SELECT = 0x40
|
|
.START = 0x80
|
|
|
|
.P14 = 0x10
|
|
.P15 = 0x20
|
|
|
|
;; Screen dimensions
|
|
.MAXCURSPOSX = 0x13 ; In tiles
|
|
.MAXCURSPOSY = 0x11
|
|
|
|
.SCREENWIDTH = 0xA0
|
|
.SCREENHEIGHT = 0x90
|
|
.MINWNDPOSX = 0x07
|
|
.MINWNDPOSY = 0x00
|
|
.MAXWNDPOSX = 0xA6
|
|
.MAXWNDPOSY = 0x8F
|
|
|
|
;; Hardware registers
|
|
|
|
.P1 = 0x00 ; Joystick: 1.1.P15.P14.P13.P12.P11.P10
|
|
rP1 = 0xFF00
|
|
|
|
P1F_5 = 0b00100000 ; P15 out port, set to 0 to get buttons
|
|
P1F_4 = 0b00010000 ; P14 out port, set to 0 to get dpad
|
|
P1F_3 = 0b00001000 ; P13 in port
|
|
P1F_2 = 0b00000100 ; P12 in port
|
|
P1F_1 = 0b00000010 ; P11 in port
|
|
P1F_0 = 0b00000001 ; P10 in port
|
|
|
|
P1F_GET_DPAD = 0b00100000
|
|
P1F_GET_BTN = 0b00010000
|
|
P1F_GET_NONE = 0b00110000
|
|
|
|
.SB = 0x01 ; Serial IO data buffer
|
|
rSB = 0xFF01
|
|
|
|
.SC = 0x02 ; Serial IO control register
|
|
rSC = 0xFF02
|
|
|
|
.DIV = 0x04 ; Divider register
|
|
rDIV = 0xFF04
|
|
|
|
.TIMA = 0x05 ; Timer counter
|
|
rTIMA = 0xFF05
|
|
|
|
.TMA = 0x06 ; Timer modulo
|
|
rTMA = 0xFF06
|
|
|
|
.TAC = 0x07 ; Timer control
|
|
rTAC = 0xFF07
|
|
|
|
TACF_START = 0b00000100
|
|
TACF_STOP = 0b00000000
|
|
TACF_4KHZ = 0b00000000
|
|
TACF_16KHZ = 0b00000011
|
|
TACF_65KHZ = 0b00000010
|
|
TACF_262KHZ = 0b00000001
|
|
|
|
.IF = 0x0F ; Interrupt flags: 0.0.0.JST.SIO.TIM.LCD.VBL
|
|
rIF = 0xFF0F
|
|
|
|
.NR10 = 0x10 ; Sound register
|
|
rNR10 = 0xFF10
|
|
rAUD1SWEEP = 0xFF10
|
|
|
|
AUD1SWEEP_UP = 0b00000000
|
|
AUD1SWEEP_DOWN = 0b00001000
|
|
|
|
.NR11 = 0x11 ; Sound register
|
|
rNR11 = 0xFF11
|
|
rAUD1LEN = 0xFF11
|
|
|
|
.NR12 = 0x12 ; Sound register
|
|
rNR12 = 0xFF12
|
|
rAUD1ENV = 0xFF12
|
|
|
|
.NR13 = 0x13 ; Sound register
|
|
rNR13 = 0xFF13
|
|
rAUD1LOW = 0xFF13
|
|
|
|
.NR14 = 0x14 ; Sound register
|
|
rNR14 = 0xFF14
|
|
rAUD1HIGH = 0xFF14
|
|
|
|
.NR21 = 0x16 ; Sound register
|
|
rNR21 = 0xFF16
|
|
rAUD2LEN = 0xFF16
|
|
|
|
.NR22 = 0x17 ; Sound register
|
|
rNR22 = 0xFF17
|
|
rAUD2ENV = 0xFF17
|
|
|
|
.NR23 = 0x18 ; Sound register
|
|
rNR23 = 0xFF18
|
|
rAUD2LOW = 0xFF18
|
|
|
|
.NR24 = 0x19 ; Sound register
|
|
rNR24 = 0xFF19
|
|
rAUD2HIGH = 0xFF19
|
|
|
|
.NR30 = 0x1A ; Sound register
|
|
rNR30 = 0xFF1A
|
|
rAUD3ENA = 0xFF1A
|
|
|
|
.NR31 = 0x1B ; Sound register
|
|
rNR31 = 0xFF1B
|
|
rAUD3LEN = 0xFF1B
|
|
|
|
.NR32 = 0x1C ; Sound register
|
|
rNR32 = 0xFF1C
|
|
rAUD3LEVEL = 0xFF1C
|
|
|
|
.NR33 = 0x1D ; Sound register
|
|
rNR33 = 0xFF1D
|
|
rAUD3LOW = 0xFF1D
|
|
|
|
.NR34 = 0x1E ; Sound register
|
|
rNR34 = 0xFF1E
|
|
rAUD3HIGH = 0xFF1E
|
|
|
|
.NR41 = 0x20 ; Sound register
|
|
rNR41 = 0xFF20
|
|
rAUD4LEN = 0xFF20
|
|
|
|
.NR42 = 0x21 ; Sound register
|
|
rNR42 = 0xFF21
|
|
rAUD4ENV = 0xFF21
|
|
|
|
.NR43 = 0x22 ; Sound register
|
|
rNR43 = 0xFF22
|
|
rAUD4POLY = 0xFF22
|
|
|
|
.NR44 = 0x23 ; Sound register
|
|
rNR44 = 0xFF23
|
|
rAUD4GO = 0xFF23
|
|
|
|
.NR50 = 0x24 ; Sound register
|
|
rNR50 = 0xFF24
|
|
rAUDVOL = 0xFF24
|
|
|
|
AUDVOL_VIN_LEFT = 0b10000000 ; SO2
|
|
AUDVOL_VIN_RIGHT = 0b00001000 ; SO1
|
|
|
|
.NR51 = 0x25 ; Sound register
|
|
rNR51 = 0xFF25
|
|
rAUDTERM = 0xFF25
|
|
|
|
AUDTERM_4_LEFT = 0b10000000
|
|
AUDTERM_3_LEFT = 0b01000000
|
|
AUDTERM_2_LEFT = 0b00100000
|
|
AUDTERM_1_LEFT = 0b00010000
|
|
AUDTERM_4_RIGHT = 0b00001000
|
|
AUDTERM_3_RIGHT = 0b00000100
|
|
AUDTERM_2_RIGHT = 0b00000010
|
|
AUDTERM_1_RIGHT = 0b00000001
|
|
|
|
.NR52 = 0x26 ; Sound register
|
|
rNR52 = 0xFF26
|
|
rAUDENA = 0xFF26
|
|
|
|
AUDENA_ON = 0b10000000
|
|
AUDENA_OFF = 0b00000000 ; sets all audio regs to 0!
|
|
|
|
.LCDC = 0x40 ; LCD control
|
|
rLCDC = 0xFF40
|
|
|
|
LCDCF_OFF = 0b00000000 ; LCD Control Operation
|
|
LCDCF_ON = 0b10000000 ; LCD Control Operation
|
|
LCDCF_WIN9800 = 0b00000000 ; Window Tile Map Display Select
|
|
LCDCF_WIN9C00 = 0b01000000 ; Window Tile Map Display Select
|
|
LCDCF_WINOFF = 0b00000000 ; Window Display
|
|
LCDCF_WINON = 0b00100000 ; Window Display
|
|
LCDCF_BG8800 = 0b00000000 ; BG & Window Tile Data Select
|
|
LCDCF_BG8000 = 0b00010000 ; BG & Window Tile Data Select
|
|
LCDCF_BG9800 = 0b00000000 ; BG Tile Map Display Select
|
|
LCDCF_BG9C00 = 0b00001000 ; BG Tile Map Display Select
|
|
LCDCF_OBJ8 = 0b00000000 ; OBJ Construction
|
|
LCDCF_OBJ16 = 0b00000100 ; OBJ Construction
|
|
LCDCF_OBJOFF = 0b00000000 ; OBJ Display
|
|
LCDCF_OBJON = 0b00000010 ; OBJ Display
|
|
LCDCF_BGOFF = 0b00000000 ; BG Display
|
|
LCDCF_BGON = 0b00000001 ; BG Display
|
|
LCDCF_B_ON = 7
|
|
LCDCF_B_WIN9C00 = 6
|
|
LCDCF_B_WINON = 5
|
|
LCDCF_B_BG8000 = 4
|
|
LCDCF_B_BG9C00 = 3
|
|
LCDCF_B_OBJ16 = 2
|
|
LCDCF_B_OBJON = 1
|
|
LCDCF_B_BGON = 0
|
|
|
|
.STAT = 0x41 ; LCD status
|
|
rSTAT = 0xFF41
|
|
|
|
STATF_LYC = 0b01000000 ; LYC=LY Coincidence (Selectable)
|
|
STATF_MODE10 = 0b00100000 ; Mode 10
|
|
STATF_MODE01 = 0b00010000 ; Mode 01 (V-Blank)
|
|
STATF_MODE00 = 0b00001000 ; Mode 00 (H-Blank)
|
|
STATF_LYCF = 0b00000100 ; Coincidence Flag
|
|
STATF_HBL = 0b00000000 ; H-Blank
|
|
STATF_VBL = 0b00000001 ; V-Blank
|
|
STATF_OAM = 0b00000010 ; OAM-RAM is used by system
|
|
STATF_LCD = 0b00000011 ; Both OAM and VRAM used by system
|
|
STATF_BUSY = 0b00000010 ; When set, VRAM access is unsafe
|
|
STATF_B_LYC = 6
|
|
STATF_B_MODE10 = 5
|
|
STATF_B_MODE01 = 4
|
|
STATF_B_MODE00 = 3
|
|
STATF_B_LYCF = 2
|
|
STATF_B_VBL = 0
|
|
STATF_B_OAM = 1
|
|
STATF_B_BUSY = 1
|
|
|
|
.SCY = 0x42 ; Scroll Y
|
|
rSCY = 0xFF42
|
|
|
|
.SCX = 0x43 ; Scroll X
|
|
rSCX = 0xFF43
|
|
|
|
.LY = 0x44 ; LCDC Y-coordinate
|
|
rLY = 0xFF44
|
|
|
|
.LYC = 0x45 ; LY compare
|
|
rLYC = 0xFF45
|
|
|
|
.DMA = 0x46 ; DMA transfer
|
|
rDMA = 0xFF46
|
|
|
|
.BGP = 0x47 ; BG palette data
|
|
rBGP = 0xFF47
|
|
|
|
.OBP0 = 0x48 ; OBJ palette 0 data
|
|
rOBP0 = 0xFF48
|
|
|
|
.OBP1 = 0x49 ; OBJ palette 1 data
|
|
rOBP1 = 0xFF49
|
|
|
|
.WY = 0x4A ; Window Y coordinate
|
|
rWY = 0xFF4A
|
|
|
|
.WX = 0x4B ; Window X coordinate
|
|
rWX = 0xFF4B
|
|
|
|
.KEY1 = 0x4D ; CPU speed
|
|
rKEY1 = 0xFF4D
|
|
rSPD = 0xFF4D
|
|
|
|
KEY1F_DBLSPEED = 0b10000000 ; 0=Normal Speed, 1=Double Speed (R)
|
|
KEY1F_PREPARE = 0b00000001 ; 0=No, 1=Prepare (R/W)
|
|
|
|
.VBK = 0x4F ; VRAM bank
|
|
rVBK = 0xFF4F
|
|
|
|
.HDMA1 = 0x51 ; DMA control 1
|
|
rHDMA1 = 0xFF51
|
|
|
|
.HDMA2 = 0x52 ; DMA control 2
|
|
rHDMA2 = 0xFF52
|
|
|
|
.HDMA3 = 0x53 ; DMA control 3
|
|
rHDMA3 = 0xFF53
|
|
|
|
.HDMA4 = 0x54 ; DMA control 4
|
|
rHDMA4 = 0xFF54
|
|
|
|
.HDMA5 = 0x55 ; DMA control 5
|
|
rHDMA5 = 0xFF55
|
|
|
|
HDMA5F_MODE_GP = 0b00000000 ; General Purpose DMA (W)
|
|
HDMA5F_MODE_HBL = 0b10000000 ; HBlank DMA (W)
|
|
|
|
HDMA5F_BUSY = 0b10000000 ; 0=Busy (DMA still in progress), 1=Transfer complete (R)
|
|
|
|
.RP = 0x56 ; IR port
|
|
rRP = 0xFF56
|
|
|
|
RPF_ENREAD = 0b11000000
|
|
RPF_DATAIN = 0b00000010 ; 0=Receiving IR Signal, 1=Normal
|
|
RPF_WRITE_HI = 0b00000001
|
|
RPF_WRITE_LO = 0b00000000
|
|
|
|
.BCPS = 0x68 ; BG color palette specification
|
|
rBCPS = 0xFF68
|
|
|
|
BCPSF_AUTOINC = 0b10000000 ; Auto Increment (0=Disabled, 1=Increment after Writing)
|
|
|
|
.BCPD = 0x69 ; BG color palette data
|
|
rBCPD = 0xFF69
|
|
|
|
.OCPS = 0x6A ; OBJ color palette specification
|
|
rOCPS = 0xFF6A
|
|
|
|
OCPSF_AUTOINC = 0b10000000 ; Auto Increment (0=Disabled, 1=Increment after Writing)
|
|
|
|
.OCPD = 0x6B ; OBJ color palette data
|
|
rOCPD = 0xFF6B
|
|
|
|
.SVBK = 0x70 ; WRAM bank
|
|
rSVBK = 0xFF70
|
|
rSMBK = 0xFF70
|
|
|
|
rPCM12 = 0xFF76
|
|
|
|
rPCM34 = 0xFF77
|
|
|
|
.IE = 0xFF ; Interrupt enable
|
|
rIE = 0xFFFF
|
|
|
|
.VBL_IFLAG = 0x01
|
|
.LCD_IFLAG = 0x02
|
|
.TIM_IFLAG = 0x04
|
|
.SIO_IFLAG = 0x08
|
|
.JOY_IFLAG = 0x10
|
|
|
|
IEF_HILO = 0b00010000 ; Transition from High to Low of Pin number P10-P13
|
|
IEF_SERIAL = 0b00001000 ; Serial I/O transfer end
|
|
IEF_TIMER = 0b00000100 ; Timer Overflow
|
|
IEF_STAT = 0b00000010 ; STAT
|
|
IEF_VBLANK = 0b00000001 ; V-Blank
|
|
|
|
;; Flags common to multiple sound channels
|
|
|
|
AUDLEN_DUTY_12_5 = 0b00000000 ; 12.5%
|
|
AUDLEN_DUTY_25 = 0b01000000 ; 25%
|
|
AUDLEN_DUTY_50 = 0b10000000 ; 50%
|
|
AUDLEN_DUTY_75 = 0b11000000 ; 75%
|
|
|
|
AUDENV_UP = 0b00001000
|
|
AUDENV_DOWN = 0b00000000
|
|
|
|
AUDHIGH_RESTART = 0b10000000
|
|
AUDHIGH_LENGTH_ON = 0b01000000
|
|
AUDHIGH_LENGTH_OFF = 0b00000000
|
|
|
|
;; OAM related constants
|
|
|
|
OAM_COUNT = 40 ; number of OAM entries in OAM RAM
|
|
|
|
OAMF_PRI = 0b10000000 ; Priority
|
|
OAMF_YFLIP = 0b01000000 ; Y flip
|
|
OAMF_XFLIP = 0b00100000 ; X flip
|
|
OAMF_PAL0 = 0b00000000 ; Palette number; 0,1 (DMG)
|
|
OAMF_PAL1 = 0b00010000 ; Palette number; 0,1 (DMG)
|
|
OAMF_BANK0 = 0b00000000 ; Bank number; 0,1 (GBC)
|
|
OAMF_BANK1 = 0b00001000 ; Bank number; 0,1 (GBC)
|
|
|
|
OAMF_PALMASK = 0b00000111 ; Palette (GBC)
|
|
|
|
OAMB_PRI = 7 ; Priority
|
|
OAMB_YFLIP = 6 ; Y flip
|
|
OAMB_XFLIP = 5 ; X flip
|
|
OAMB_PAL1 = 4 ; Palette number; 0,1 (DMG)
|
|
OAMB_BANK1 = 3 ; Bank number; 0,1 (GBC)
|
|
|
|
;; SGB packets
|
|
.PAL_01 = 0x00
|
|
.PAL_23 = 0x01
|
|
.PAL_03 = 0x02
|
|
.PAL_12 = 0x03
|
|
.ATTR_BLK = 0x04
|
|
.ATTR_LIN = 0x05
|
|
.ATTR_DIV = 0x06
|
|
.ATTR_CHR = 0x07
|
|
.SOUND = 0x08
|
|
.SOU_TRN = 0x09
|
|
.PAL_SET = 0x0A
|
|
.PAL_TRN = 0x0B
|
|
.ATRC_EN = 0x0C
|
|
.TEST_EN = 0x0D
|
|
.ICON_EN = 0x0E
|
|
.DATA_SND = 0x0F
|
|
.DATA_TRN = 0x10
|
|
.MLT_REQ = 0x11
|
|
.JUMP = 0x12
|
|
.CHR_TRN = 0x13
|
|
.PCT_TRN = 0x14
|
|
.ATTR_TRN = 0x15
|
|
.ATTR_SET = 0x16
|
|
.MASK_EN = 0x17
|
|
.OBJ_TRN = 0x18
|
|
|
|
;; CPU detection
|
|
.DMG_TYPE = 0x01 ; Original GB or Super GB
|
|
.MGB_TYPE = 0xFF ; Pocket GB or Super GB 2
|
|
.CGB_TYPE = 0x11 ; Color GB
|
|
|
|
;; GBDK library screen modes
|
|
|
|
.G_MODE = 0x01 ; Graphic mode
|
|
.T_MODE = 0x02 ; Text mode (bit 2)
|
|
.T_MODE_OUT = 0x02 ; Text mode output only
|
|
.T_MODE_INOUT = 0x03 ; Text mode with input
|
|
.M_NO_SCROLL = 0x04 ; Disables scrolling of the screen in text mode
|
|
.M_NO_INTERP = 0x08 ; Disables special character interpretation
|
|
|
|
;; Status codes for IO
|
|
.IO_IDLE = 0x00
|
|
.IO_SENDING = 0x01
|
|
.IO_RECEIVING = 0x02
|
|
.IO_ERROR = 0x04
|
|
|
|
;; Type of IO data
|
|
.DT_IDLE = 0x66
|
|
.DT_RECEIVING = 0x55
|
|
|
|
;; Table of routines for modes
|
|
.MODE_TABLE = 0x00F0
|
|
|
|
;; C related
|
|
;; Overheap of a banked call. Used for parameters
|
|
;; = ret + real ret + bank
|
|
|
|
.BANKOV = 6
|
|
|
|
.globl __current_bank
|
|
.globl __shadow_OAM_base
|
|
|
|
;; Global variables
|
|
.globl .mode
|
|
|
|
.globl __cpu
|
|
.globl __is_GBA
|
|
|
|
;; Global routines
|
|
.globl .reset
|
|
|
|
.globl .display_off
|
|
|
|
.globl .wait_vbl_done
|
|
|
|
.INT_CALL_CHAIN_SIZE = 3
|
|
|
|
;; Interrupt routines
|
|
.globl .add_VBL
|
|
; .globl .add_LCD ;; don't link LCD.o by default
|
|
; .globl .add_TIM ;; don't link TIM.o by default
|
|
; .globl .add_SIO ;; don't link serial.o by default
|
|
; .globl .add_JOY ;; don't link JOY.o by default
|
|
|
|
;; Symbols defined at link time
|
|
.globl .STACK
|
|
.globl _shadow_OAM
|
|
.globl .refresh_OAM
|
|
|
|
;; Main user routine
|
|
.globl _main
|
|
|
|
;; Macro definitions
|
|
|
|
.macro WAIT_STAT ?lbl
|
|
lbl: LDH A, (.STAT)
|
|
AND #STATF_BUSY ; Check if in LCD modes 0 or 1
|
|
JR NZ, lbl
|
|
.endm
|
|
|
|
.macro ADD_A_REG16 regH regL
|
|
ADD regL
|
|
LD regL, A
|
|
ADC regH
|
|
SUB regL
|
|
LD regH, A
|
|
.endm
|
|
|
|
.macro SIGNED_ADD_A_REG16 regH regL ?lbl
|
|
; If A is negative, we need to subtract 1 from upper byte of 16-bit value
|
|
BIT 7, A ; set z if a signed bit is 0
|
|
JR Z, lbl ; if z is set jump to positive
|
|
dec regH ; if negative decrement upper byte
|
|
lbl:
|
|
ADD_A_REG16 regH, regL
|
|
.endm
|
|
|
|
.macro SIGNED_SUB_A_REG16 regH regL ?lbl
|
|
; negate A then add to 16-bit value
|
|
CPL
|
|
INC A
|
|
SIGNED_ADD_A_REG16 regH, regL
|
|
.endm
|
|
|
|
.macro MUL_DE_BY_A_RET_HL ?lbl1 ?lbl2
|
|
; Multiply DE by A, return result in HL; preserves: BC
|
|
LD HL, #0
|
|
lbl1:
|
|
SRL A
|
|
JR NC, lbl2
|
|
ADD HL, DE
|
|
lbl2:
|
|
SLA E
|
|
RL D
|
|
OR A
|
|
JR NZ, lbl1
|
|
.endm
|
|
|