Files
gbdk-2020/gbdk-lib/libc/targets/sm83/gb/global.s
2023-06-05 02:16:43 +03:00

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