From bf648f4218ea34b1ad037ea07ac36853fe883941 Mon Sep 17 00:00:00 2001 From: yenatch Date: Thu, 25 Sep 2014 22:31:54 -0700 Subject: [PATCH] Organize the source and add some bankswitch macros. --- Makefile | 11 +++-- main.asm | 18 -------- src/code/header.asm | 14 ++++++ src/code/rst.asm | 97 ++++++++++++++++++++++++++++++++++++++ src/constants.asm | 8 ++++ src/gbhw.asm | 110 ++++++++++++++++++++++++++++++++++++++++++++ src/hram.asm | 4 ++ src/macros.asm | 9 ++++ src/main.asm | 22 +++++++++ 9 files changed, 270 insertions(+), 23 deletions(-) delete mode 100644 main.asm create mode 100644 src/code/header.asm create mode 100644 src/code/rst.asm create mode 100644 src/constants.asm create mode 100644 src/gbhw.asm create mode 100644 src/hram.asm create mode 100644 src/macros.asm create mode 100644 src/main.asm diff --git a/Makefile b/Makefile index 6eb1e34..2d14739 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ PYTHON = python .PHONY: all clean .SECONDEXPANSION: + # For now, we only need to build one rom (game.gbc). all: game.gbc @: @@ -14,16 +15,16 @@ clean: ; @rm -f game.{gbc,sym,map} # Objects are assembled from source. -# main.o is built from main.asm. -obj := main.o +# src/main.o is built from src/main.asm. +obj := src/main.o %.asm: ; $(obj): $$*.asm - @rgbasm -o $@ $< + rgbasm -i src/ -o $@ $< # Then we link them to create a playable image. # This also spits out game.sym, which lets you use labels in bgb. # Generating a mapfile is required thanks to a bug in rgblink. game.gbc: $(obj) - @rgblink -n $*.sym -m $*.map -o $@ $^ - @rgbfix -v $@ + rgblink -n $*.sym -m $*.map -o $@ $^ + rgbfix -v $@ diff --git a/main.asm b/main.asm deleted file mode 100644 index cd9c2d9..0000000 --- a/main.asm +++ /dev/null @@ -1,18 +0,0 @@ -; The source code found here is assembled into main.o. - -; If it starts to take a long time to build, it's a good idea -; to split your code and data up into new objects in the makefile. - -section "Entry", rom0 [$100] -; This is the entry point to the program. - nop - jr Start - -section "Main", rom0 [$150] -Start: -; There should be some code here. In the meantime, loop forever. -; Disable interrupts and halt to conserve battery. - di -.loop - halt - jr .loop diff --git a/src/code/header.asm b/src/code/header.asm new file mode 100644 index 0000000..b4ce032 --- /dev/null +++ b/src/code/header.asm @@ -0,0 +1,14 @@ +section "Entry", rom0 [$100] + + ; This is the entry point to the program. + + nop + jp Start + + +section "Header", rom0 [$104] + + ; The header is created by rgbfix. + ; The space here is allocated as a placeholder. + + ds $150 - $104 diff --git a/src/code/rst.asm b/src/code/rst.asm new file mode 100644 index 0000000..19b5334 --- /dev/null +++ b/src/code/rst.asm @@ -0,0 +1,97 @@ +; rst vectors are single-byte calls. + +; Here, they're used as pseudoinstructions for bank management. +; This is not the only way the rst instructions can be used. + + +section "rst Bankswitch", rom0 [Bankswitch] + jp rst_Bankswitch + +section "rst FarCall", rom0 [FarCall] + jp rst_FarCall + + +section "Bankswitch", rom0 + +rst_Bankswitch: + ld [hTemp], a + ld a, l + ld [hTemp + 1], a + ld a, h + ld [hTemp + 2], a + + pop hl + ld a, [hli] + push hl + + ld [hRomBank], a + ld [MBC3RomBank], a + + ld hl, hTemp + 2 + ld a, [hld] + ld l, [hl] + ld h, a + ld a, [hTemp] + ret + + +BankswitchHome: + ld [hRomBank], a + ld [MBC3RomBank], a + ret + + +section "FarCall", rom0 + +rst_FarCall: + push af + ld [hTemp], a + ld a, l + ld [hTemp + 1], a + ld a, h + ld [hTemp + 2], a + pop af + + ; Grab the return address. + pop hl + ld a, $c3 ; jp + ld [hCodeTemp + 0], a + ld a, [hli] + ld [hCodeTemp + 1], a + ld a, [hli] + ld [hCodeTemp + 2], a + ld a, [hli] + rst Bankswitch + ; Put it back, skipping past the arguments. + push hl + + ld a, [hRomBank] + push af + + ld hl, hTemp + 2 + ld a, [hld] + ld l, [hl] + ld h, a + ld a, [hTemp] + + call hCodeTemp + + push af + ld a, b + ld [hTemp], a + ld a, c + ld [hTemp + 1], a + pop af + + pop bc + + push af + ld a, b + rst Bankswitch + ld a, [hTemp] + ld b, a + ld a, [hTemp + 1] + ld c, a + pop af + + ret diff --git a/src/constants.asm b/src/constants.asm new file mode 100644 index 0000000..5e58031 --- /dev/null +++ b/src/constants.asm @@ -0,0 +1,8 @@ +; rst vector addresses are defined here. +Bankswitch equ 0 +FarCall equ 8 + +include "gbhw.asm" +include "macros.asm" + +include "hram.asm" diff --git a/src/gbhw.asm b/src/gbhw.asm new file mode 100644 index 0000000..3284e48 --- /dev/null +++ b/src/gbhw.asm @@ -0,0 +1,110 @@ +; Graciously aped from http://nocash.emubase.de/pandocs.htm. + +; MBC3 +MBC3SRamEnable EQU $0000 +MBC3RomBank EQU $2000 +MBC3SRamBank EQU $4000 +MBC3LatchClock EQU $6000 +MBC3RTC EQU $a000 + +SRAM_DISABLE EQU $00 +SRAM_ENABLE EQU $0a + +RTC_S EQU $08 ; Seconds 0-59 (0-3Bh) +RTC_M EQU $09 ; Minutes 0-59 (0-3Bh) +RTC_H EQU $0a ; Hours 0-23 (0-17h) +RTC_DL EQU $0b ; Lower 8 bits of Day Counter (0-FFh) +RTC_DH EQU $0c ; Upper 1 bit of Day Counter, Carry Bit, Halt Flag + ; Bit 0 Most significant bit of Day Counter (Bit 8) + ; Bit 6 Halt (0=Active, 1=Stop Timer) + ; Bit 7 Day Counter Carry Bit (1=Counter Overflow) + + +; interrupt flags +VBLANK EQU 0 +LCD_STAT EQU 1 +TIMER EQU 2 +SERIAL EQU 3 +JOYPAD EQU 4 + +; OAM attribute flags +OAM_PALETTE EQU %111 +OAM_TILE_BANK EQU 3 +OAM_OBP_NUM EQU 4 ; Non CGB Mode Only +OAM_X_FLIP EQU 5 +OAM_Y_FLIP EQU 6 +OAM_PRIORITY EQU 7 ; 0: OBJ above BG, 1: OBJ behind BG (colors 1-3) + + +; Hardware registers +rJOYP EQU $ff00 ; Joypad (R/W) +rSB EQU $ff01 ; Serial transfer data (R/W) +rSC EQU $ff02 ; Serial Transfer Control (R/W) +rSC_ON EQU 7 +rSC_CGB EQU 1 +rSC_CLOCK EQU 0 +rDIV EQU $ff04 ; Divider Register (R/W) +rTIMA EQU $ff05 ; Timer counter (R/W) +rTMA EQU $ff06 ; Timer Modulo (R/W) +rTAC EQU $ff07 ; Timer Control (R/W) +rTAC_ON EQU 2 +rTAC_4096_HZ EQU 0 +rTAC_262144_HZ EQU 1 +rTAC_65536_HZ EQU 2 +rTAC_16384_HZ EQU 3 +rIF EQU $ff0f ; Interrupt Flag (R/W) +rNR10 EQU $ff10 ; Channel 1 Sweep register (R/W) +rNR11 EQU $ff11 ; Channel 1 Sound length/Wave pattern duty (R/W) +rNR12 EQU $ff12 ; Channel 1 Volume Envelope (R/W) +rNR13 EQU $ff13 ; Channel 1 Frequency lo (Write Only) +rNR14 EQU $ff14 ; Channel 1 Frequency hi (R/W) +rNR21 EQU $ff16 ; Channel 2 Sound Length/Wave Pattern Duty (R/W) +rNR22 EQU $ff17 ; Channel 2 Volume Envelope (R/W) +rNR23 EQU $ff18 ; Channel 2 Frequency lo data (W) +rNR24 EQU $ff19 ; Channel 2 Frequency hi data (R/W) +rNR30 EQU $ff1a ; Channel 3 Sound on/off (R/W) +rNR31 EQU $ff1b ; Channel 3 Sound Length +rNR32 EQU $ff1c ; Channel 3 Select output level (R/W) +rNR33 EQU $ff1d ; Channel 3 Frequency's lower data (W) +rNR34 EQU $ff1e ; Channel 3 Frequency's higher data (R/W) +rNR41 EQU $ff20 ; Channel 4 Sound Length (R/W) +rNR42 EQU $ff21 ; Channel 4 Volume Envelope (R/W) +rNR43 EQU $ff22 ; Channel 4 Polynomial Counter (R/W) +rNR44 EQU $ff23 ; Channel 4 Counter/consecutive; Inital (R/W) +rNR50 EQU $ff24 ; Channel control / ON-OFF / Volume (R/W) +rNR51 EQU $ff25 ; Selection of Sound output terminal (R/W) +rNR52 EQU $ff26 ; Sound on/off +rLCDC EQU $ff40 ; LCD Control (R/W) +rSTAT EQU $ff41 ; LCDC Status (R/W) +rSCY EQU $ff42 ; Scroll Y (R/W) +rSCX EQU $ff43 ; Scroll X (R/W) +rLY EQU $ff44 ; LCDC Y-Coordinate (R) +rLYC EQU $ff45 ; LY Compare (R/W) +rDMA EQU $ff46 ; DMA Transfer and Start Address (W) +rBGP EQU $ff47 ; BG Palette Data (R/W) - Non CGB Mode Only +rOBP0 EQU $ff48 ; Object Palette 0 Data (R/W) - Non CGB Mode Only +rOBP1 EQU $ff49 ; Object Palette 1 Data (R/W) - Non CGB Mode Only +rWY EQU $ff4a ; Window Y Position (R/W) +rWX EQU $ff4b ; Window X Position minus 7 (R/W) +rKEY1 EQU $ff4d ; CGB Mode Only - Prepare Speed Switch +rVBK EQU $ff4f ; CGB Mode Only - VRAM Bank +rHDMA1 EQU $ff51 ; CGB Mode Only - New DMA Source, High +rHDMA2 EQU $ff52 ; CGB Mode Only - New DMA Source, Low +rHDMA3 EQU $ff53 ; CGB Mode Only - New DMA Destination, High +rHDMA4 EQU $ff54 ; CGB Mode Only - New DMA Destination, Low +rHDMA5 EQU $ff55 ; CGB Mode Only - New DMA Length/Mode/Start +rRP EQU $ff56 ; CGB Mode Only - Infrared Communications Port +rBGPI EQU $ff68 ; CGB Mode Only - Background Palette Index +rBGPD EQU $ff69 ; CGB Mode Only - Background Palette Data +rOBPI EQU $ff6a ; CGB Mode Only - Sprite Palette Index +rOBPD EQU $ff6b ; CGB Mode Only - Sprite Palette Data +rUNKN1 EQU $ff6c ; (FEh) Bit 0 (Read/Write) - CGB Mode Only +rSVBK EQU $ff70 ; CGB Mode Only - WRAM Bank +rUNKN2 EQU $ff72 ; (00h) - Bit 0-7 (Read/Write) +rUNKN3 EQU $ff73 ; (00h) - Bit 0-7 (Read/Write) +rUNKN4 EQU $ff74 ; (00h) - Bit 0-7 (Read/Write) - CGB Mode Only +rUNKN5 EQU $ff75 ; (8Fh) - Bit 4-6 (Read/Write) +rUNKN6 EQU $ff76 ; (00h) - Always 00h (Read Only) +rUNKN7 EQU $ff77 ; (00h) - Always 00h (Read Only) +rIE EQU $ffff ; Interrupt Enable (R/W) + diff --git a/src/hram.asm b/src/hram.asm new file mode 100644 index 0000000..766e881 --- /dev/null +++ b/src/hram.asm @@ -0,0 +1,4 @@ + +hRomBank equ $ff80 +hTemp equ $ff81 +hCodeTemp equ $ff82 diff --git a/src/macros.asm b/src/macros.asm new file mode 100644 index 0000000..f268d43 --- /dev/null +++ b/src/macros.asm @@ -0,0 +1,9 @@ +farcall: macro + rst FarCall + db bank(\1) + dw \1 +endm + +RGB: macro + db (\1) + (\2) << 5 + (\3) << 10 +endm diff --git a/src/main.asm b/src/main.asm new file mode 100644 index 0000000..6e29c0e --- /dev/null +++ b/src/main.asm @@ -0,0 +1,22 @@ +; The source code found here assembles to main.o. + +; If it starts to take a long time to build, it's a good idea +; to split your code and data up into new objects in the makefile. + + +include "constants.asm" + +include "code/rst.asm" +include "code/header.asm" + + +section "Main", rom0 + +Start: + ; There should be some code here. In the meantime, loop forever. + ; Disable interrupts and halt to conserve battery. + + di +.loop + halt + jr .loop