mirror of
https://github.com/gbdk-2020/gbdk-2020.git
synced 2026-02-20 00:32:21 +01:00
megaduck support (library and definitions)
This commit is contained in:
2
Makefile
2
Makefile
@@ -11,7 +11,7 @@ PKG = gbdk
|
||||
VER = 3.00
|
||||
|
||||
PORTS=gbz80 z80
|
||||
PLATFORMS=gb ap gg sms
|
||||
PLATFORMS=gb ap duck gg sms
|
||||
|
||||
# Prefix to add to the standard tools. Usefull for a standard gcc
|
||||
# cross-compile.
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#define ANALOGUEPOCKET
|
||||
#elif defined(__TARGET_gb)
|
||||
#define GAMEBOY
|
||||
#elif defined(__TARGET_duck)
|
||||
#define MEGADUCK
|
||||
#endif
|
||||
|
||||
|
||||
@@ -458,6 +460,12 @@ __endasm; \
|
||||
*/
|
||||
#define BANKREF_EXTERN(VARNAME) extern const void __bank_ ## VARNAME;
|
||||
|
||||
/** Makes MEGADUCK MBC switch the active ROM bank
|
||||
@param b ROM bank to switch to
|
||||
*/
|
||||
#define SWITCH_ROM_MEGADUCK(b) \
|
||||
_current_bank = (b), *(uint8_t *)0x0001 = (b)
|
||||
|
||||
|
||||
/** Makes MBC1 and other compatible MBCs switch the active ROM bank
|
||||
@param b ROM bank to switch to
|
||||
@@ -465,12 +473,16 @@ __endasm; \
|
||||
#define SWITCH_ROM_MBC1(b) \
|
||||
_current_bank = (b), *(uint8_t *)0x2000 = (b)
|
||||
|
||||
/** Makes MBC1, MBC5 (4M ROMs) and other compatible MBCs switch the active ROM bank
|
||||
/** Makes default platform MBC switch the active ROM bank
|
||||
@param b ROM bank to switch to (max 255)
|
||||
|
||||
@see SWITCH_ROM_MBC1, SWITCH_ROM_MBC5
|
||||
@see SWITCH_ROM_MBC1, SWITCH_ROM_MBC5, SWITCH_ROM_MEGADUCK
|
||||
*/
|
||||
#if defined(__TARGET_duck)
|
||||
#define SWITCH_ROM SWITCH_ROM_MEGADUCK
|
||||
#else
|
||||
#define SWITCH_ROM SWITCH_ROM_MBC1
|
||||
#endif
|
||||
|
||||
/** Switches SRAM bank on MBC1 and other compaticle MBCs
|
||||
@param b SRAM bank to switch to
|
||||
|
||||
@@ -161,7 +161,7 @@ __BYTE_REG AUD3WAVE[16];
|
||||
__REG LCDC_REG; /**< LCD control */
|
||||
#define rLCDC LCDC_REG
|
||||
|
||||
#ifdef __TARGET_ap
|
||||
#if defined(__TARGET_ap)
|
||||
#define LCDCF_OFF 0b00000000
|
||||
#define LCDCF_ON 0b00000001
|
||||
#define LCDCF_WIN9800 0b00000000
|
||||
@@ -186,37 +186,62 @@ __REG LCDC_REG; /**< LCD control */
|
||||
#define LCDCF_B_OBJ16 5
|
||||
#define LCDCF_B_OBJON 6
|
||||
#define LCDCF_B_BGON 7
|
||||
#elif defined(__TARGET_duck)
|
||||
#define LCDCF_OFF 0b00000000
|
||||
#define LCDCF_ON 0b10000000
|
||||
#define LCDCF_WIN9800 0b00000000
|
||||
#define LCDCF_WIN9C00 0b00001000
|
||||
#define LCDCF_WINOFF 0b00000000
|
||||
#define LCDCF_WINON 0b00100000
|
||||
#define LCDCF_BG8800 0b00000000
|
||||
#define LCDCF_BG8000 0b00010000
|
||||
#define LCDCF_BG9800 0b00000000
|
||||
#define LCDCF_BG9C00 0b00000100
|
||||
#define LCDCF_OBJ8 0b00000000
|
||||
#define LCDCF_OBJ16 0b00000010
|
||||
#define LCDCF_OBJOFF 0b00000000
|
||||
#define LCDCF_OBJON 0b00000001
|
||||
#define LCDCF_BGOFF 0b00000000
|
||||
#define LCDCF_BGON 0b01000000
|
||||
#define LCDCF_B_ON 7
|
||||
#define LCDCF_B_WIN9C00 3
|
||||
#define LCDCF_B_WINON 5
|
||||
#define LCDCF_B_BG8000 4
|
||||
#define LCDCF_B_BG9C00 2
|
||||
#define LCDCF_B_OBJ16 1
|
||||
#define LCDCF_B_OBJON 0
|
||||
#define LCDCF_B_BGON 6
|
||||
#else
|
||||
#define LCDCF_OFF 0b00000000 /**< LCD Control: Off */
|
||||
#define LCDCF_ON 0b10000000 /**< LCD Control: On */
|
||||
#define LCDCF_WIN9800 0b00000000 /**< Window Tile Map: Use 9800 Region */
|
||||
#define LCDCF_WIN9C00 0b01000000 /**< Window Tile Map: Use 9C00 Region */
|
||||
#define LCDCF_WINOFF 0b00000000 /**< Window Display: Hidden */
|
||||
#define LCDCF_WINON 0b00100000 /**< Window Display: Visible */
|
||||
#define LCDCF_BG8800 0b00000000 /**< BG & Window Tile Data: Use 8800 Region */
|
||||
#define LCDCF_BG8000 0b00010000 /**< BG & Window Tile Data: Use 8000 Region */
|
||||
#define LCDCF_BG9800 0b00000000 /**< BG Tile Map: use 9800 Region */
|
||||
#define LCDCF_BG9C00 0b00001000 /**< BG Tile Map: use 9C00 Region */
|
||||
#define LCDCF_OBJ8 0b00000000 /**< Sprites Size: 8x8 pixels */
|
||||
#define LCDCF_OBJ16 0b00000100 /**< Sprites Size: 8x16 pixels */
|
||||
#define LCDCF_OBJOFF 0b00000000 /**< Sprites Display: Hidden */
|
||||
#define LCDCF_OBJON 0b00000010 /**< Sprites Display: Visible */
|
||||
#define LCDCF_BGOFF 0b00000000 /**< Background Display: Hidden */
|
||||
#define LCDCF_BGON 0b00000001 /**< Background Display: Visible */
|
||||
#define LCDCF_B_ON 7 /**< Bit for LCD On/Off Select */
|
||||
#define LCDCF_B_WIN9C00 6 /**< Bit for Window Tile Map Region Select */
|
||||
#define LCDCF_B_WINON 5 /**< Bit for Window Display On/Off Control */
|
||||
#define LCDCF_B_BG8000 4 /**< Bit for BG & Window Tile Data Region Select */
|
||||
#define LCDCF_B_BG9C00 3 /**< Bit for BG Tile Map Region Select */
|
||||
#define LCDCF_B_OBJ16 2 /**< Bit for Sprites Size Select */
|
||||
#define LCDCF_B_OBJON 1 /**< Bit for Sprites Display Visible/Hidden Select */
|
||||
#define LCDCF_B_BGON 0 /**< Bit for Background Display Visible/Hidden Select */
|
||||
#define LCDCF_OFF 0b00000000 /**< LCD Control: Off */
|
||||
#define LCDCF_ON 0b10000000 /**< LCD Control: On */
|
||||
#define LCDCF_WIN9800 0b00000000 /**< Window Tile Map: Use 9800 Region */
|
||||
#define LCDCF_WIN9C00 0b01000000 /**< Window Tile Map: Use 9C00 Region */
|
||||
#define LCDCF_WINOFF 0b00000000 /**< Window Display: Hidden */
|
||||
#define LCDCF_WINON 0b00100000 /**< Window Display: Visible */
|
||||
#define LCDCF_BG8800 0b00000000 /**< BG & Window Tile Data: Use 8800 Region */
|
||||
#define LCDCF_BG8000 0b00010000 /**< BG & Window Tile Data: Use 8000 Region */
|
||||
#define LCDCF_BG9800 0b00000000 /**< BG Tile Map: use 9800 Region */
|
||||
#define LCDCF_BG9C00 0b00001000 /**< BG Tile Map: use 9C00 Region */
|
||||
#define LCDCF_OBJ8 0b00000000 /**< Sprites Size: 8x8 pixels */
|
||||
#define LCDCF_OBJ16 0b00000100 /**< Sprites Size: 8x16 pixels */
|
||||
#define LCDCF_OBJOFF 0b00000000 /**< Sprites Display: Hidden */
|
||||
#define LCDCF_OBJON 0b00000010 /**< Sprites Display: Visible */
|
||||
#define LCDCF_BGOFF 0b00000000 /**< Background Display: Hidden */
|
||||
#define LCDCF_BGON 0b00000001 /**< Background Display: Visible */
|
||||
#define LCDCF_B_ON 7 /**< Bit for LCD On/Off Select */
|
||||
#define LCDCF_B_WIN9C00 6 /**< Bit for Window Tile Map Region Select */
|
||||
#define LCDCF_B_WINON 5 /**< Bit for Window Display On/Off Control */
|
||||
#define LCDCF_B_BG8000 4 /**< Bit for BG & Window Tile Data Region Select */
|
||||
#define LCDCF_B_BG9C00 3 /**< Bit for BG Tile Map Region Select */
|
||||
#define LCDCF_B_OBJ16 2 /**< Bit for Sprites Size Select */
|
||||
#define LCDCF_B_OBJON 1 /**< Bit for Sprites Display Visible/Hidden Select */
|
||||
#define LCDCF_B_BGON 0 /**< Bit for Background Display Visible/Hidden Select */
|
||||
#endif
|
||||
|
||||
__REG STAT_REG; /**< LCD status */
|
||||
#define rSTAT STAT_REG
|
||||
|
||||
#ifdef __TARGET_ap
|
||||
#if defined(__TARGET_ap)
|
||||
#define STATF_LYC 0b00000010
|
||||
#define STATF_MODE10 0b00000100
|
||||
#define STATF_MODE01 0b00001000
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __GBDK_BCD_H_INCLUDE
|
||||
#define __GBDK_BCD_H_INCLUDE
|
||||
|
||||
#if defined(__TARGET_gb) || defined(__TARGET_ap)
|
||||
#if defined(__TARGET_gb) || defined(__TARGET_ap) || defined(__TARGET_duck)
|
||||
#include <gb/bcd.h>
|
||||
#elif defined(__TARGET_sms) || defined(__TARGET_gg)
|
||||
#error Not implemented yet
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __GB_DECOMPRESS_H_INCLUDE
|
||||
#define __GB_DECOMPRESS_H_INCLUDE
|
||||
|
||||
#if defined(__TARGET_gb) || defined(__TARGET_ap)
|
||||
#if defined(__TARGET_gb) || defined(__TARGET_ap) || defined(__TARGET_duck)
|
||||
#include <gb/gbdecompress.h>
|
||||
#elif defined(__TARGET_sms) || defined(__TARGET_gg)
|
||||
#include <sms/gbdecompress.h>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PLAT_METASPRITES_H_INVCLUDE
|
||||
#define __PLAT_METASPRITES_H_INVCLUDE
|
||||
|
||||
#if defined(__TARGET_gb) || defined(__TARGET_ap)
|
||||
#if defined(__TARGET_gb) || defined(__TARGET_ap) || defined(__TARGET_duck)
|
||||
#include <gb/metasprites.h>
|
||||
#elif defined(__TARGET_sms) || defined(__TARGET_gg)
|
||||
#include <sms/metasprites.h>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PLATFORM_H_INCLUDE
|
||||
#define __PLATFORM_H_INCLUDE
|
||||
|
||||
#if defined(__TARGET_gb) || defined(__TARGET_ap)
|
||||
#if defined(__TARGET_gb) || defined(__TARGET_ap) || defined(__TARGET_duck)
|
||||
#include <gb/gb.h>
|
||||
#include <gb/cgb.h>
|
||||
#include <gb/sgb.h>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#define RLE_STOP 0
|
||||
|
||||
#if defined(__TARGET_gb) || defined(__TARGET_ap)
|
||||
#if defined(__TARGET_gb) || defined(__TARGET_ap) || defined(__TARGET_duck)
|
||||
/** Initialize the RLE decompressor with RLE data at address __data__
|
||||
|
||||
@param data Pointer to start of RLE compressed data
|
||||
|
||||
@@ -7,7 +7,7 @@ ifeq ($(PORTS),)
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORMS),)
|
||||
PLATFORMS = gb ap gg sms
|
||||
PLATFORMS = gb ap duck gg sms
|
||||
endif
|
||||
|
||||
TOPDIR = ..
|
||||
|
||||
@@ -15,7 +15,7 @@ banked_call:: ; Performs a long call.
|
||||
inc hl ; Yes this should be here
|
||||
push hl ; Push the real return address
|
||||
ldh (__current_bank),a
|
||||
ld (.MBC1_ROM_PAGE),a ; Perform the switch
|
||||
ld (.MBC_ROM_PAGE),a ; Perform the switch
|
||||
ld l,e
|
||||
ld h,d
|
||||
rst 0x20
|
||||
@@ -23,5 +23,5 @@ banked_ret::
|
||||
pop hl ; Get the return address
|
||||
pop af ; Pop the old bank
|
||||
ldh (__current_bank),a
|
||||
ld (.MBC1_ROM_PAGE),a
|
||||
ld (.MBC_ROM_PAGE),a
|
||||
jp (hl)
|
||||
|
||||
@@ -7,9 +7,9 @@ ldh a,(__current_bank)
|
||||
push af ; Push the current bank onto the stack
|
||||
ld a, e
|
||||
ldh (__current_bank),a
|
||||
ld (.MBC1_ROM_PAGE),a ; Perform the switch
|
||||
ld (.MBC_ROM_PAGE),a ; Perform the switch
|
||||
rst 0x20
|
||||
pop af ; Pop the old bank
|
||||
ldh (__current_bank),a
|
||||
ld (.MBC1_ROM_PAGE),a
|
||||
ld (.MBC_ROM_PAGE),a
|
||||
ret
|
||||
@@ -20,6 +20,7 @@
|
||||
;; MBC Equates
|
||||
|
||||
.MBC1_ROM_PAGE = 0x2000 ; Address to write to for MBC1 switching
|
||||
.MBC_ROM_PAGE = 0x2000 ; Default platform MBC rom switching address
|
||||
|
||||
rRAMG = 0x0000 ; $0000->$1fff
|
||||
rROMB0 = 0x2000 ; $2000->$2fff
|
||||
|
||||
53
gbdk-lib/libc/targets/gbz80/duck/Makefile
Normal file
53
gbdk-lib/libc/targets/gbz80/duck/Makefile
Normal file
@@ -0,0 +1,53 @@
|
||||
# GB specific Makefile
|
||||
|
||||
TOPDIR = ../../../..
|
||||
|
||||
THIS = duck
|
||||
PORT = gbz80
|
||||
|
||||
CSRC = digits.c gprint.c gprintf.c gprintln.c gprintn.c
|
||||
|
||||
ASSRC = cgb.s cgb_palettes.s cgb_compat.s \
|
||||
cpy_data.s \
|
||||
drawing.s drawing_isr.s color.s \
|
||||
f_ibm_full.s f_ibm_sh.s f_italic.s f_min.s f_spect.s \
|
||||
get_bk_t.s get_data.s get_tile.s \
|
||||
get_wi_t.s get_xy_t.s \
|
||||
get_addr.s \
|
||||
hiramcpy.s init_tt.s input.s \
|
||||
pad.s \
|
||||
serial.s set_bk_t.s set_tile.s \
|
||||
set_data.s set_prop.s set_spr.s set_wi_t.s set_xy_t.s \
|
||||
set_1bit_data.s \
|
||||
sgb.s font.s font_color.s delay.s \
|
||||
bgb_emu.s bgb_emu_printf.s \
|
||||
nowait.s far_ptr.s \
|
||||
lcd.s joy.s tim.s \
|
||||
crash_handler.s \
|
||||
___sdcc_bcall_ehl.s ___sdcc_bcall.s \
|
||||
mv_spr.s \
|
||||
pad_ex.s \
|
||||
mode.s clock.s \
|
||||
get_t.s set_t.s init_vram.s \
|
||||
fill_rect.s fill_rect_bk.s fill_rect_wi.s \
|
||||
metasprites.s metasprites_flip.s metasprites_hide.s metasprites_hide_spr.s \
|
||||
set_tile_submap.s set_win_tile_submap.s \
|
||||
gb_decompress.s gb_decompress_tiles.s \
|
||||
rle_decompress.s \
|
||||
heap.s \
|
||||
crt0.s
|
||||
|
||||
ifeq ($(ASM),asxxxx)
|
||||
ASSRC += sfr.s
|
||||
endif
|
||||
ifeq ($(ASM),rgbds)
|
||||
ASSRC += stubs.s
|
||||
endif
|
||||
|
||||
CRT0 = crt0.s
|
||||
|
||||
include $(TOPDIR)/Makefile.common
|
||||
|
||||
AS = $(AS_GBZ80)
|
||||
|
||||
include ../../../Makefile.platform
|
||||
476
gbdk-lib/libc/targets/gbz80/duck/crash_handler.s
Normal file
476
gbdk-lib/libc/targets/gbz80/duck/crash_handler.s
Normal file
@@ -0,0 +1,476 @@
|
||||
; Crash handler support
|
||||
; Original code by ISSOtm
|
||||
; Adapted by Toxa from gb-starter-kit: https://github.com/ISSOtm/gb-starter-kit
|
||||
|
||||
.include "global.s"
|
||||
|
||||
.globl _font_ibm
|
||||
|
||||
SCRN_X = 160 ; Width of screen in pixels
|
||||
SCRN_Y = 144 ; Height of screen in pixels
|
||||
SCRN_X_B = 20 ; Width of screen in bytes
|
||||
SCRN_Y_B = 18 ; Height of screen in bytes
|
||||
|
||||
SCRN_VX = 256 ; Virtual width of screen in pixels
|
||||
SCRN_VY = 256 ; Virtual height of screen in pixels
|
||||
SCRN_VX_B = 32 ; Virtual width of screen in bytes
|
||||
SCRN_VY_B = 32 ; Virtual height of screen in bytes
|
||||
|
||||
|
||||
.area _CRASH_HEADER(ABS)
|
||||
|
||||
.org 0x38
|
||||
di
|
||||
jp ___HandleCrash
|
||||
|
||||
|
||||
.area _HOME
|
||||
|
||||
___HandleCrash::
|
||||
|
||||
; We will use VRAM as scratch, since we are going to overwrite it for
|
||||
; screen output anyways. The thing is, we need to turn the LCD off
|
||||
; *without* affecting flags... fun task, eh?
|
||||
|
||||
; Note: it's assumed that this was jumped to with IME off.
|
||||
; Don't call this directly, use `rst Crash`.
|
||||
|
||||
ld (wCrashA), a ; We need to have at least one working register, so...
|
||||
ldh a, (.IE) ; We're also going to overwrite this
|
||||
ld (wCrashIE), a
|
||||
ldh a, (.LCDC)
|
||||
ld (wCrashLCDC), a
|
||||
ld a, #LCDCF_ON ; LCDCF_ON Make sure the LCD is turned on to avoid waiting infinitely
|
||||
ldh (.LCDC), a
|
||||
ld a, #IEF_VBLANK ; IEF_VBLANK
|
||||
ld (.IE), a
|
||||
ld a, #0 ; `xor a` would overwrite flags
|
||||
ld (.IF), a ; No point in backing up that register, it's always changing
|
||||
halt ; With interrupts disabled, this will exit when `IE & IF != 0`
|
||||
nop ; Handle hardware bug if it becomes true *before* starting to execute the instruction (1-cycle window)
|
||||
|
||||
; We're now in VBlank! So we can now use VRAM as scratch for some cycles
|
||||
ld a, #0
|
||||
ldh (.LCDC), a ; Turn off LCD so VRAM can always be safely accessed
|
||||
; Save regs
|
||||
ld (vCrashSP), sp
|
||||
ld sp, #vCrashSP
|
||||
push hl
|
||||
push de
|
||||
push bc
|
||||
ld a, (wCrashA)
|
||||
push af
|
||||
|
||||
; We need to have all the data in bank 0, but we can't guarantee we were there
|
||||
ldh a, (.VBK)
|
||||
ld e, a
|
||||
bit #0, a
|
||||
jr z, .bank0
|
||||
; Oh noes. We need to copy the data across banks!
|
||||
ld hl, #vCrashAF
|
||||
ld c, #(5 * 2)
|
||||
.copyAcross:
|
||||
ld b, (hl)
|
||||
xor a
|
||||
ldh (.VBK), a
|
||||
ld (hl), b
|
||||
inc l ; inc hl
|
||||
inc a ; ld a, 1
|
||||
ldh (.VBK), a
|
||||
dec c
|
||||
jr nz, .copyAcross
|
||||
.bank0:
|
||||
xor a
|
||||
ldh (.NR52), a ; Kill sound for this screen
|
||||
|
||||
ldh (.VBK), a
|
||||
ld a, e
|
||||
ld (vCrashVBK), a ; copy vCrashVBK across banks
|
||||
|
||||
ld a, #1
|
||||
ldh (.VBK), a
|
||||
ld hl, #vCrashDumpScreen
|
||||
ld b, #SCRN_Y_B
|
||||
.writeAttrRow:
|
||||
xor a
|
||||
ld c, #(SCRN_X_B + 1)
|
||||
rst #0x28 ; .MemsetSmall
|
||||
ld a, l
|
||||
add a, #(SCRN_VX_B - SCRN_X_B - 1)
|
||||
ld l, a
|
||||
dec b
|
||||
jr nz, .writeAttrRow
|
||||
xor a
|
||||
ldh (.VBK), a
|
||||
|
||||
; Load palettes
|
||||
ld a, #0x03
|
||||
ldh (.BGP), a
|
||||
ld a, #0x80
|
||||
ldh (.BCPS), a
|
||||
xor a
|
||||
ld c, #.BCPD
|
||||
ldh (c), a
|
||||
ldh (c), a
|
||||
dec a ; ld a, $FF
|
||||
ldh (c), a
|
||||
ldh (c), a
|
||||
ldh (c), a
|
||||
ldh (c), a
|
||||
ldh (c), a
|
||||
ldh (c), a
|
||||
|
||||
ld a, #(SCRN_VY - SCRN_Y)
|
||||
ldh (.SCY), a
|
||||
ld a, #(SCRN_VX - SCRN_X - 4)
|
||||
ldh (.SCX), a
|
||||
|
||||
call loadfont
|
||||
|
||||
; Copy the registers to the dump viewers
|
||||
ld hl, #vDumpHL
|
||||
ld de, #vCrashHL
|
||||
ld c, #4
|
||||
rst #0x30 ; .MemcpySmall
|
||||
|
||||
; We're now going to draw the screen, top to bottom
|
||||
ld hl, #vCrashDumpScreen
|
||||
|
||||
; First 3 lines of text
|
||||
ld de, #.header
|
||||
ld b, #3
|
||||
.writeHeaderLine:
|
||||
ld a, #0x20 ; " "
|
||||
ld (hl+), a
|
||||
ld c, #19
|
||||
rst #0x30 ; .MemcpySmall
|
||||
ld a, #0x20 ; " "
|
||||
ld (hl+), a
|
||||
ld a, l
|
||||
add a, #(SCRN_VX_B - SCRN_X_B - 1)
|
||||
ld l, a
|
||||
dec b
|
||||
jr nz, .writeHeaderLine
|
||||
|
||||
; Blank line
|
||||
ld a, #0x20 ; " "
|
||||
ld c, #(SCRN_X_B + 1)
|
||||
rst #0x28 ; .MemsetSmall
|
||||
|
||||
; AF and console model
|
||||
ld l, #<vCrashDumpScreenRow4
|
||||
ld c, #4
|
||||
rst #0x30 ; .MemcpySmall
|
||||
pop bc
|
||||
call .printHexBC
|
||||
ld c, #8
|
||||
rst #0x30 ; .MemcpySmall
|
||||
ld a, (__cpu)
|
||||
call .printHexA
|
||||
ld a, #0x20 ; " "
|
||||
ld (hl+), a
|
||||
ld (hl+), a
|
||||
ld (hl+), a
|
||||
|
||||
; BC and DE
|
||||
ld l, #<vCrashDumpScreenRow5
|
||||
ld c, #4
|
||||
rst #0x30 ; .MemcpySmall
|
||||
pop bc
|
||||
call .printHexBC
|
||||
ld c, #6
|
||||
rst #0x30 ; .MemcpySmall
|
||||
pop bc
|
||||
call .printHexBC
|
||||
ld a, #0x20
|
||||
ld (hl+), a
|
||||
ld (hl+), a
|
||||
ld (hl+), a
|
||||
|
||||
; Now, the two memory dumps
|
||||
.writeDump:
|
||||
ld a, l
|
||||
add a, #(SCRN_VX_B - SCRN_X_B - 1)
|
||||
ld l, a
|
||||
ld c, #4
|
||||
rst #0x30 ; .MemcpySmall
|
||||
pop bc
|
||||
push bc
|
||||
call .printHexBC
|
||||
ld de, #.viewStr
|
||||
ld c, #7
|
||||
rst #0x30 ; .MemcpySmall
|
||||
pop de
|
||||
call .printDump
|
||||
ld de, #.spStr
|
||||
bit #7, l
|
||||
jr z, .writeDump
|
||||
|
||||
ld de, #.hwRegsStrs
|
||||
ld l, #<vCrashDumpScreenRow14
|
||||
ld c, #6
|
||||
rst #0x30 ; .MemcpySmall
|
||||
ld a, (wCrashLCDC)
|
||||
call .printHexA
|
||||
ld c, #4
|
||||
rst #0x30 ; .MemcpySmall
|
||||
ldh a, (.KEY1)
|
||||
call .printHexA
|
||||
ld c, #4
|
||||
rst #0x30 ; .MemcpySmall
|
||||
ld a, (wCrashIE)
|
||||
call .printHexA
|
||||
ld (hl), #0x20 ; " "
|
||||
|
||||
ld l, #<vCrashDumpScreenRow15
|
||||
ld c, #7
|
||||
rst #0x30 ; .MemcpySmall
|
||||
.writeBank:
|
||||
ld a, #0x20 ; " "
|
||||
ld (hl+), a
|
||||
ld a, (de)
|
||||
inc de
|
||||
ld (hl+), a
|
||||
cp #0x20 ; " "
|
||||
jr z, .banksDone
|
||||
ld a, (de)
|
||||
inc de
|
||||
ld c, a
|
||||
ld a, (de)
|
||||
inc de
|
||||
ld b, a
|
||||
ld a, (bc)
|
||||
call .printHexA
|
||||
jr .writeBank
|
||||
.banksDone:
|
||||
|
||||
; Start displaying
|
||||
ld a, #(LCDCF_ON | LCDCF_BG9C00 | LCDCF_BGON)
|
||||
ldh (.LCDC), a
|
||||
|
||||
.loop:
|
||||
; The code never lags, and IE is equal to IEF_VBLANK
|
||||
xor a
|
||||
ldh (.IF), a
|
||||
halt
|
||||
|
||||
jr .loop
|
||||
|
||||
.printHexBC:
|
||||
call .printHexB
|
||||
ld a, c
|
||||
.printHexA:
|
||||
ld b, a
|
||||
.printHexB:
|
||||
ld a, b
|
||||
and #0xF0
|
||||
swap a
|
||||
add a, #0x30
|
||||
cp #0x3a
|
||||
jr c, 1$
|
||||
add a, #(0x41 - 0x3a)
|
||||
1$: ld (hl+), a
|
||||
ld a, b
|
||||
and #0x0F
|
||||
add a, #0x30
|
||||
cp #0x3a
|
||||
jr c, 2$
|
||||
add a, #(0x41 - 0x3a)
|
||||
2$: ld (hl+), a
|
||||
ret
|
||||
|
||||
.printDump:
|
||||
ld b, d
|
||||
ld c, e
|
||||
call .printHexBC
|
||||
ld a, #0x20 ; " "
|
||||
ld (hl+), a
|
||||
ld (hl+), a
|
||||
ld a, e
|
||||
sub #8
|
||||
ld e, a
|
||||
ld a, d
|
||||
sbc #0
|
||||
ld d, a
|
||||
.writeDumpLine:
|
||||
ld a, l
|
||||
add a, #(SCRN_VX_B - SCRN_X_B - 1)
|
||||
ld l, a
|
||||
ld a, #0x20 ; " "
|
||||
ld (hl+), a
|
||||
.writeDumpWord:
|
||||
ld a, (de)
|
||||
inc de
|
||||
call .printHexA
|
||||
ld a, (de)
|
||||
inc de
|
||||
call .printHexA
|
||||
ld a, #0x20 ; " "
|
||||
ld (hl+), a
|
||||
bit 4, l
|
||||
jr nz, .writeDumpWord
|
||||
ld a, l
|
||||
and #0x7F
|
||||
jr nz, .writeDumpLine
|
||||
ret
|
||||
|
||||
loadfont:
|
||||
xor a
|
||||
cpl
|
||||
ld hl, #0x9000
|
||||
ld c, #16
|
||||
rst #0x28 ; .MemsetSmall
|
||||
ld hl, #(0x9000 + ' ' * 16)
|
||||
ld c, #16
|
||||
rst #0x28 ; .MemsetSmall
|
||||
|
||||
ld de, #(_font_ibm + 2 + '0') ; recode table
|
||||
ld hl, #(0x9000 + '0' * 16) ; destination
|
||||
push hl
|
||||
ld c, #(16 * 3)
|
||||
1$:
|
||||
ld a, (de)
|
||||
inc de
|
||||
push de
|
||||
|
||||
swap a
|
||||
ld l, a
|
||||
and #0x0f
|
||||
ld h, a
|
||||
ld a, l
|
||||
and #0xf0
|
||||
srl h
|
||||
rra
|
||||
ld l, a
|
||||
ld de, #(_font_ibm + 2 + 128)
|
||||
add hl, de
|
||||
|
||||
ld d, h
|
||||
ld e, l
|
||||
|
||||
ldhl sp, #2
|
||||
ld a, (hl+)
|
||||
ld h, (hl)
|
||||
ld l, a
|
||||
|
||||
ld b, #8
|
||||
2$:
|
||||
ld a, (de)
|
||||
cpl
|
||||
inc de
|
||||
ld (hl+), a
|
||||
ld (hl+), a
|
||||
|
||||
dec b
|
||||
jr nz, 2$
|
||||
|
||||
ld d, h
|
||||
ld a, l
|
||||
ldhl sp, #2
|
||||
ld (hl+), a
|
||||
ld (hl), d
|
||||
|
||||
pop de
|
||||
|
||||
dec c
|
||||
jr nz, 1$
|
||||
|
||||
add sp, #2
|
||||
ret
|
||||
|
||||
.header:
|
||||
; 0123456789ABCDEFGHI 19 chars
|
||||
.ascii "KERNEL PANIC PLEASE"
|
||||
.ascii "SEND A CLEAR PIC OF"
|
||||
.ascii "THIS SCREEN TO DEVS"
|
||||
.ascii " AF:"
|
||||
.ascii " MODEL:"
|
||||
.ascii " BC:"
|
||||
.ascii " DE:"
|
||||
.ascii " HL:"
|
||||
.viewStr:
|
||||
.ascii " VIEW:"
|
||||
.spStr:
|
||||
.ascii " SP:"
|
||||
.hwRegsStrs:
|
||||
.ascii " LCDC:"
|
||||
.ascii " K1:"
|
||||
.ascii " IE:"
|
||||
.ascii " BANK:"
|
||||
.ascii "R"
|
||||
.dw __current_bank
|
||||
.ascii "V"
|
||||
.dw vCrashVBK
|
||||
.ascii "W"
|
||||
.db .SVBK, 0xff
|
||||
.ascii " "
|
||||
|
||||
|
||||
.area _DATA
|
||||
|
||||
wCrashA:
|
||||
.ds 1 ; We need at least one working register, and A allows accessing memory
|
||||
wCrashIE:
|
||||
.ds 1
|
||||
wCrashLCDC:
|
||||
.ds 1
|
||||
|
||||
|
||||
.area _CRASH_SCRATCH(ABS)
|
||||
|
||||
.org 0x9C00
|
||||
|
||||
; Put the crash dump screen at the bottom-right of the 9C00 tilemap, since that tends to be unused space
|
||||
.ds SCRN_VX_B * (SCRN_VY_B - SCRN_Y_B - 2) ; 2 rows reserved as scratch space
|
||||
|
||||
.ds SCRN_X_B ; Try not to overwrite the window area
|
||||
.ds 2 * 1 ; Free stack entries (we spill into the above by 1 entry, though :/)
|
||||
; These are the initial values of the registers
|
||||
; They are popped off the stack when printed, freeing up stack space
|
||||
|
||||
vCrashAF:
|
||||
.ds 2
|
||||
vCrashBC:
|
||||
.ds 2
|
||||
vCrashDE:
|
||||
.ds 2
|
||||
vCrashHL:
|
||||
.ds 2
|
||||
vCrashSP:
|
||||
.ds 2
|
||||
|
||||
.ds SCRN_X_B
|
||||
vHeldKeys:
|
||||
.ds 1 ; Keys held on previous frame
|
||||
vUnlockCounter:
|
||||
.ds 1 ; How many frames until dumps are "unlocked"
|
||||
vWhichDump:
|
||||
.ds 1
|
||||
vDumpHL:
|
||||
.ds 2
|
||||
vDumpSP:
|
||||
.ds 2
|
||||
vCrashVBK:
|
||||
.ds 1
|
||||
.ds 4 ; Unused
|
||||
|
||||
.ds SCRN_VX_B - SCRN_X_B - 1
|
||||
vCrashDumpScreen:
|
||||
vCrashDumpScreenRow0 = vCrashDumpScreen + 1 * SCRN_VX_B
|
||||
vCrashDumpScreenRow1 = vCrashDumpScreen + 2 * SCRN_VX_B
|
||||
vCrashDumpScreenRow2 = vCrashDumpScreen + 3 * SCRN_VX_B
|
||||
vCrashDumpScreenRow3 = vCrashDumpScreen + 4 * SCRN_VX_B
|
||||
vCrashDumpScreenRow4 = vCrashDumpScreen + 5 * SCRN_VX_B
|
||||
vCrashDumpScreenRow5 = vCrashDumpScreen + 6 * SCRN_VX_B
|
||||
vCrashDumpScreenRow6 = vCrashDumpScreen + 7 * SCRN_VX_B
|
||||
vCrashDumpScreenRow7 = vCrashDumpScreen + 8 * SCRN_VX_B
|
||||
vCrashDumpScreenRow8 = vCrashDumpScreen + 9 * SCRN_VX_B
|
||||
vCrashDumpScreenRow9 = vCrashDumpScreen + 10 * SCRN_VX_B
|
||||
vCrashDumpScreenRow10 = vCrashDumpScreen + 11 * SCRN_VX_B
|
||||
vCrashDumpScreenRow11 = vCrashDumpScreen + 12 * SCRN_VX_B
|
||||
vCrashDumpScreenRow12 = vCrashDumpScreen + 13 * SCRN_VX_B
|
||||
vCrashDumpScreenRow13 = vCrashDumpScreen + 14 * SCRN_VX_B
|
||||
vCrashDumpScreenRow14 = vCrashDumpScreen + 15 * SCRN_VX_B
|
||||
vCrashDumpScreenRow15 = vCrashDumpScreen + 16 * SCRN_VX_B
|
||||
vCrashDumpScreenRow16 = vCrashDumpScreen + 17 * SCRN_VX_B
|
||||
vCrashDumpScreenRow17 = vCrashDumpScreen + 18 * SCRN_VX_B
|
||||
476
gbdk-lib/libc/targets/gbz80/duck/crt0.s
Normal file
476
gbdk-lib/libc/targets/gbz80/duck/crt0.s
Normal file
@@ -0,0 +1,476 @@
|
||||
.include "global.s"
|
||||
|
||||
;; ****************************************
|
||||
;; Beginning of module
|
||||
;; BANKED: checked
|
||||
.title "Runtime"
|
||||
.module Runtime
|
||||
.area _HEADER (ABS)
|
||||
|
||||
;; RST vectors
|
||||
.org 0x00 ; MEGADUCK entry point/reset
|
||||
JP .code_start
|
||||
|
||||
; .org 0x08 ; --profile handler utilized by bgb_emu.h
|
||||
|
||||
; .org 0x10 ; empty
|
||||
|
||||
; .org 0x18 ; empty
|
||||
|
||||
.org 0x20 ; RST 0x20 == call HL
|
||||
.call_hl::
|
||||
JP (HL)
|
||||
|
||||
.org 0x28 ; zero up to 256 bytes in C pointed by HL
|
||||
.MemsetSmall::
|
||||
LD (HL+),A
|
||||
DEC C
|
||||
JR NZ,.MemsetSmall
|
||||
ret
|
||||
|
||||
.org 0x30 ; copy up to 256 bytes in C from DE to HL
|
||||
.MemcpySmall::
|
||||
LD A, (DE)
|
||||
LD (HL+), A
|
||||
INC DE
|
||||
DEC C
|
||||
JR NZ,.MemcpySmall
|
||||
RET
|
||||
|
||||
; .org 0x38 ; crash handler utilized by crash_handler.h
|
||||
|
||||
;; Hardware interrupt vectors
|
||||
.org 0x40 ; VBL
|
||||
.int_VBL:
|
||||
PUSH AF
|
||||
PUSH HL
|
||||
LD HL,#.int_0x40
|
||||
JP .int
|
||||
|
||||
; .org 0x48 ; LCD
|
||||
|
||||
; .org 0x50 ; TIM
|
||||
|
||||
; .org 0x58 ; SIO
|
||||
|
||||
; .org 0x60 ; JOY
|
||||
|
||||
; .org 0x70
|
||||
;; space for drawing.s bit table
|
||||
|
||||
.org 0x80
|
||||
.int::
|
||||
PUSH BC
|
||||
PUSH DE
|
||||
1$:
|
||||
LD A,(HL+)
|
||||
OR (HL)
|
||||
JR Z,.int_tail
|
||||
PUSH HL
|
||||
LD A,(HL-)
|
||||
LD L,(HL)
|
||||
LD H,A
|
||||
RST 0x20 ; .call_hl
|
||||
POP HL
|
||||
INC HL
|
||||
JR 1$
|
||||
_wait_int_handler::
|
||||
ADD SP,#4
|
||||
.int_tail:
|
||||
POP DE
|
||||
POP BC
|
||||
POP HL
|
||||
|
||||
;; we return at least at the beginning of mode 2
|
||||
WAIT_STAT
|
||||
|
||||
POP AF
|
||||
RETI
|
||||
|
||||
;; VBlank default interrupt routine
|
||||
__standard_VBL_handler::
|
||||
.std_vbl:
|
||||
LD HL,#.sys_time
|
||||
INC (HL)
|
||||
JR NZ,2$
|
||||
INC HL
|
||||
INC (HL)
|
||||
2$:
|
||||
CALL .refresh_OAM
|
||||
|
||||
LD A, #1
|
||||
LDH (.vbl_done),A
|
||||
RET
|
||||
|
||||
_refresh_OAM::
|
||||
LD HL, #((.refresh_OAM_DMA - .start_refresh_OAM) + .refresh_OAM)
|
||||
WAIT_STAT
|
||||
LD A, #>_shadow_OAM
|
||||
JP (HL)
|
||||
|
||||
.clear_WRAM:
|
||||
PUSH DE
|
||||
XOR A
|
||||
LD BC, #l__DATA
|
||||
LD HL, #s__DATA
|
||||
CALL .memset_simple
|
||||
|
||||
LD A, #>_shadow_OAM
|
||||
LDH (__shadow_OAM_base), A
|
||||
LD H, A
|
||||
XOR A
|
||||
LD L, A
|
||||
LD C, #(40 << 2) ; 40 entries 4 bytes each
|
||||
RST 0x28
|
||||
POP DE
|
||||
RET
|
||||
|
||||
.org 0x150
|
||||
|
||||
;; soft reset: falldown to .code_start
|
||||
.reset::
|
||||
_reset::
|
||||
RST 0x00
|
||||
|
||||
;; Initialization code
|
||||
.code_start::
|
||||
DI ; Disable interrupts
|
||||
LD D, #0 ; MEGADUCK is always a DMG
|
||||
LD E, B
|
||||
;; Initialize the stack
|
||||
LD SP, #.STACK
|
||||
|
||||
CALL .clear_WRAM
|
||||
|
||||
; LD (.mode),A ; Clearing (.mode) is performed when clearing RAM
|
||||
|
||||
;; Store CPU type
|
||||
LD A, D
|
||||
LD (__cpu), A
|
||||
CP #.CGB_TYPE
|
||||
JR NZ, 1$
|
||||
XOR A
|
||||
SRL E
|
||||
RLA
|
||||
LD (__is_GBA), A
|
||||
1$:
|
||||
|
||||
;; Turn the screen off
|
||||
CALL .display_off
|
||||
|
||||
XOR A
|
||||
;; Initialize the display
|
||||
LDH (.SCY),A
|
||||
LDH (.SCX),A
|
||||
LDH (.STAT),A
|
||||
LDH (.WY),A
|
||||
LD A,#0x07
|
||||
LDH (.WX),A
|
||||
|
||||
;; Copy refresh_OAM routine to HRAM
|
||||
LD DE,#.start_refresh_OAM ; source
|
||||
LD HL,#.refresh_OAM ; dest
|
||||
LD C,#(.end_refresh_OAM - .start_refresh_OAM) ; size
|
||||
RST 0x30 ; call .MemcpySmall
|
||||
|
||||
;; Clear the OAM by calling refresh_OAM
|
||||
CALL .refresh_OAM
|
||||
|
||||
;; Install interrupt routines
|
||||
LD BC,#.std_vbl
|
||||
CALL .add_VBL
|
||||
|
||||
;; Standard color palettes
|
||||
LD A,#0b11100100 ; Grey 3 = 11 (Black)
|
||||
; Grey 2 = 10 (Dark grey)
|
||||
; Grey 1 = 01 (Light grey)
|
||||
; Grey 0 = 00 (Transparent)
|
||||
LDH (.BGP),A
|
||||
LDH (.OBP0),A
|
||||
LD A,#0b00011011
|
||||
LDH (.OBP1),A
|
||||
|
||||
;; Turn the screen on
|
||||
LD A,#(LCDCF_ON | LCDCF_WIN9C00 | LCDCF_WINOFF | LCDCF_BG8800 | LCDCF_BG9800 | LCDCF_OBJ8 | LCDCF_OBJOFF | LCDCF_BGOFF)
|
||||
LDH (.LCDC),A
|
||||
XOR A
|
||||
LDH (.IF),A
|
||||
LD A,#.VBL_IFLAG ; switch on VBlank interrupt only
|
||||
LDH (.IE),A
|
||||
|
||||
LDH (__current_bank),A ; current bank is 1 at startup
|
||||
|
||||
XOR A
|
||||
|
||||
LD HL,#.sys_time
|
||||
LD (HL+),A
|
||||
LD (HL),A
|
||||
|
||||
LDH (.NR52),A ; Turn sound off
|
||||
|
||||
CALL gsinit
|
||||
|
||||
EI ; Enable interrupts
|
||||
|
||||
;; Call the main function
|
||||
CALL _main
|
||||
_exit::
|
||||
99$:
|
||||
HALT
|
||||
NOP
|
||||
JR 99$ ; Wait forever
|
||||
|
||||
_set_interrupts::
|
||||
DI
|
||||
LDA HL,2(SP) ; Skip return address
|
||||
XOR A
|
||||
LDH (.IF),A ; Clear pending interrupts
|
||||
LD A,(HL)
|
||||
EI ; Enable interrupts
|
||||
LDH (.IE),A ; interrupts are still disabled here
|
||||
RET
|
||||
|
||||
;; Copy OAM data to OAM RAM
|
||||
.start_refresh_OAM:
|
||||
LDH A,(__shadow_OAM_base)
|
||||
OR A
|
||||
RET Z
|
||||
.refresh_OAM_DMA:
|
||||
LDH (.DMA),A ; Put A into DMA registers
|
||||
LD A,#0x28 ; We need to wait 160 ns
|
||||
1$:
|
||||
DEC A
|
||||
JR NZ,1$
|
||||
RET
|
||||
.end_refresh_OAM:
|
||||
|
||||
.org .MODE_TABLE
|
||||
;; Jump table for modes
|
||||
RET
|
||||
|
||||
;; ****************************************
|
||||
|
||||
;; Ordering of segments for the linker
|
||||
;; Code that really needs to be in bank 0
|
||||
.area _HOME
|
||||
;; Similar to _HOME
|
||||
.area _BASE
|
||||
;; Code
|
||||
.area _CODE
|
||||
;; #pragma bank 0 workaround
|
||||
.area _CODE_0
|
||||
;; Constant data
|
||||
.area _LIT
|
||||
; ;; since _CODE_1 area base address is pre-defined in the linker from 0x4000,
|
||||
; ;; that moves initializer code and tables out of bank 0
|
||||
; .area _CODE_1
|
||||
;; Constant data, used to init _DATA
|
||||
.area _INITIALIZER
|
||||
;; Code, used to init _DATA
|
||||
.area _GSINIT
|
||||
.area _GSFINAL
|
||||
;; Uninitialised ram data
|
||||
.area _DATA
|
||||
.area _BSS
|
||||
;; Initialised in ram data
|
||||
.area _INITIALIZED
|
||||
;; For malloc
|
||||
.area _HEAP
|
||||
|
||||
.area _DATA
|
||||
__cpu::
|
||||
.ds 0x01 ; GB type (GB, PGB, CGB)
|
||||
__is_GBA::
|
||||
.ds 0x01 ; detect GBA
|
||||
.mode::
|
||||
.ds 0x01 ; Current mode
|
||||
.sys_time::
|
||||
_sys_time::
|
||||
.ds 0x02 ; System time in VBL units
|
||||
.int_0x40::
|
||||
.blkw 0x0A ; 4 interrupt handlers (built-in + user-defined)
|
||||
|
||||
.area _HRAM (ABS)
|
||||
|
||||
.org 0xFF90
|
||||
__current_bank:: ; Current bank
|
||||
.ds 0x01
|
||||
.vbl_done:
|
||||
.ds 0x01 ; Is VBL interrupt finished?
|
||||
__shadow_OAM_base::
|
||||
.ds 0x01
|
||||
|
||||
;; Runtime library
|
||||
.area _GSINIT
|
||||
gsinit::
|
||||
;; initialize static storage variables
|
||||
LD BC, #l__INITIALIZER
|
||||
LD HL, #s__INITIALIZER
|
||||
LD DE, #s__INITIALIZED
|
||||
call .memcpy_simple
|
||||
|
||||
.area _GSFINAL
|
||||
ret
|
||||
|
||||
.area _HOME
|
||||
|
||||
;; fills memory at HL of length BC with A, clobbers DE
|
||||
.memset_simple::
|
||||
LD E, A
|
||||
LD A, B
|
||||
OR C
|
||||
RET Z
|
||||
LD (HL), E
|
||||
DEC BC
|
||||
LD D, H
|
||||
LD E, L
|
||||
INC DE
|
||||
|
||||
;; copies BC bytes from HL into DE
|
||||
.memcpy_simple::
|
||||
LD A, B
|
||||
OR C
|
||||
RET Z
|
||||
|
||||
SRL B
|
||||
RR C
|
||||
JR NC,3$
|
||||
LD A, (HL+)
|
||||
LD (DE), A
|
||||
INC DE
|
||||
3$:
|
||||
INC B
|
||||
INC C
|
||||
JR 2$
|
||||
1$:
|
||||
LD A, (HL+)
|
||||
LD (DE), A
|
||||
INC DE
|
||||
LD A, (HL+)
|
||||
LD (DE), A
|
||||
INC DE
|
||||
2$:
|
||||
DEC C
|
||||
JR NZ,1$
|
||||
DEC B
|
||||
JR NZ,1$
|
||||
4$:
|
||||
RET
|
||||
|
||||
;; Remove interrupt routine in BC from the VBL interrupt list
|
||||
;; falldown to .remove_int
|
||||
.remove_VBL::
|
||||
LD HL,#.int_0x40
|
||||
|
||||
;; Remove interrupt BC from interrupt list HL if it exists
|
||||
;; Abort if a 0000 is found (end of list)
|
||||
.remove_int::
|
||||
1$:
|
||||
LD A,(HL+)
|
||||
LD E,A
|
||||
LD D,(HL)
|
||||
INC HL
|
||||
OR D
|
||||
RET Z ; No interrupt found
|
||||
|
||||
LD A,E
|
||||
CP C
|
||||
JR NZ,1$
|
||||
LD A,D
|
||||
CP B
|
||||
JR NZ,1$
|
||||
|
||||
LD D,H
|
||||
LD E,L
|
||||
DEC DE
|
||||
DEC DE
|
||||
|
||||
;; Now do a memcpy from here until the end of the list
|
||||
2$:
|
||||
LD A,(HL+)
|
||||
LD (DE),A
|
||||
LD B,A
|
||||
INC DE
|
||||
LD A,(HL+)
|
||||
LD (DE),A
|
||||
INC DE
|
||||
OR B
|
||||
RET Z
|
||||
JR 2$
|
||||
|
||||
;; Add interrupt routine in BC to the VBL interrupt list
|
||||
;; falldown to .add_int
|
||||
.add_VBL::
|
||||
LD HL,#.int_0x40
|
||||
|
||||
;; Add interrupt routine in BC to the interrupt list in HL
|
||||
.add_int::
|
||||
1$:
|
||||
LD A,(HL+)
|
||||
OR (HL)
|
||||
JR Z,2$
|
||||
INC HL
|
||||
JR 1$
|
||||
2$:
|
||||
LD A,B
|
||||
LD (HL-),A
|
||||
LD (HL),C
|
||||
RET
|
||||
|
||||
;; Wait for VBL interrupt to be finished
|
||||
.wait_vbl_done::
|
||||
_wait_vbl_done::
|
||||
;; Check if the screen is on
|
||||
LDH A,(.LCDC)
|
||||
AND #LCDCF_ON
|
||||
RET Z ; Return if screen is off
|
||||
XOR A
|
||||
LDH (.vbl_done),A ; Clear any previous sets of vbl_done
|
||||
1$:
|
||||
HALT ; Wait for any interrupt
|
||||
NOP ; HALT sometimes skips the next instruction
|
||||
LDH A,(.vbl_done) ; Was it a VBlank interrupt?
|
||||
;; Warning: we may lose a VBlank interrupt, if it occurs now
|
||||
OR A
|
||||
JR Z,1$ ; No: back to sleep!
|
||||
RET
|
||||
|
||||
.display_off::
|
||||
_display_off::
|
||||
;; Check if the screen is on
|
||||
LDH A,(.LCDC)
|
||||
AND #LCDCF_ON
|
||||
RET Z ; Return if screen is off
|
||||
1$: ; We wait for the *NEXT* VBL
|
||||
LDH A,(.LY)
|
||||
CP #0x92 ; Smaller than or equal to 0x91?
|
||||
JR NC,1$ ; Loop until smaller than or equal to 0x91
|
||||
2$:
|
||||
LDH A,(.LY)
|
||||
CP #0x91 ; Bigger than 0x90?
|
||||
JR C,2$ ; Loop until bigger than 0x90
|
||||
|
||||
LDH A,(.LCDC)
|
||||
AND #~LCDCF_ON
|
||||
LDH (.LCDC),A ; Turn off screen
|
||||
RET
|
||||
|
||||
_remove_VBL::
|
||||
PUSH BC
|
||||
LDA HL,4(SP) ; Skip return address and registers
|
||||
LD A,(HL+)
|
||||
LD C,A
|
||||
LD B,(HL)
|
||||
CALL .remove_VBL
|
||||
POP BC
|
||||
RET
|
||||
|
||||
_add_VBL::
|
||||
PUSH BC
|
||||
LDA HL, 4(SP) ; Skip return address and registers
|
||||
LD A,(HL+)
|
||||
LD C,A
|
||||
LD B,(HL)
|
||||
CALL .add_VBL
|
||||
POP BC
|
||||
RET
|
||||
509
gbdk-lib/libc/targets/gbz80/duck/global.s
Normal file
509
gbdk-lib/libc/targets/gbz80/duck/global.s
Normal file
@@ -0,0 +1,509 @@
|
||||
.NEAR_CALLS = 1 ; <near_calls> - tag so that sed can change this
|
||||
|
||||
;; Changed by astorgb.pl to 1
|
||||
__RGBDS__ = 0
|
||||
|
||||
_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
|
||||
|
||||
.MBC1_ROM_PAGE = 0x2000 ; Address to write to for MBC1 switching
|
||||
.MBC_ROM_PAGE = 0x0001 ; Default platform MBC rom switching address
|
||||
|
||||
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
|
||||
.START = 0x80
|
||||
.SELECT = 0x40
|
||||
.B = 0x20
|
||||
.A = 0x10
|
||||
.DOWN = 0x08
|
||||
.UP = 0x04
|
||||
.LEFT = 0x02
|
||||
.RIGHT = 0x01
|
||||
|
||||
.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 = 0x20 ; Sound register
|
||||
rNR10 = 0xFF20
|
||||
rAUD1SWEEP = 0xFF20
|
||||
|
||||
AUD1SWEEP_UP = 0b00000000
|
||||
AUD1SWEEP_DOWN = 0b00001000
|
||||
|
||||
.NR11 = 0x22 ; Sound register
|
||||
rNR11 = 0xFF22
|
||||
rAUD1LEN = 0xFF22
|
||||
|
||||
.NR12 = 0x21 ; Sound register
|
||||
rNR12 = 0xFF21
|
||||
rAUD1ENV = 0xFF21
|
||||
|
||||
.NR13 = 0x23 ; Sound register
|
||||
rNR13 = 0xFF23
|
||||
rAUD1LOW = 0xFF23
|
||||
|
||||
.NR14 = 0x24 ; Sound register
|
||||
rNR14 = 0xFF24
|
||||
rAUD1HIGH = 0xFF24
|
||||
|
||||
.NR21 = 0x26 ; Sound register
|
||||
rNR21 = 0xFF26
|
||||
rAUD2LEN = 0xFF26
|
||||
|
||||
.NR22 = 0x28 ; Sound register
|
||||
rNR22 = 0xFF28
|
||||
rAUD2ENV = 0xFF28
|
||||
|
||||
.NR23 = 0x27 ; Sound register
|
||||
rNR23 = 0xFF27
|
||||
rAUD2LOW = 0xFF27
|
||||
|
||||
.NR24 = 0x29 ; Sound register
|
||||
rNR24 = 0xFF29
|
||||
rAUD2HIGH = 0xFF29
|
||||
|
||||
.NR30 = 0x2A ; Sound register
|
||||
rNR30 = 0xFF2A
|
||||
rAUD3ENA = 0xFF2A
|
||||
|
||||
.NR31 = 0x2B ; Sound register
|
||||
rNR31 = 0xFF2B
|
||||
rAUD3LEN = 0xFF2B
|
||||
|
||||
.NR32 = 0x2C ; Sound register
|
||||
rNR32 = 0xFF2C
|
||||
rAUD3LEVEL = 0xFF2C
|
||||
|
||||
.NR33 = 0x2E ; Sound register
|
||||
rNR33 = 0xFF2E
|
||||
rAUD3LOW = 0xFF2E
|
||||
|
||||
.NR34 = 0x2D ; Sound register
|
||||
rNR34 = 0xFF2D
|
||||
rAUD3HIGH = 0xFF2D
|
||||
|
||||
.NR41 = 0x40 ; Sound register
|
||||
rNR41 = 0xFF40
|
||||
rAUD4LEN = 0xFF40
|
||||
|
||||
.NR42 = 0x42 ; Sound register
|
||||
rNR42 = 0xFF42
|
||||
rAUD4ENV = 0xFF42
|
||||
|
||||
.NR43 = 0x41 ; Sound register
|
||||
rNR43 = 0xFF41
|
||||
rAUD4POLY = 0xFF41
|
||||
|
||||
.NR44 = 0x43 ; Sound register
|
||||
rNR44 = 0xFF43
|
||||
rAUD4GO = 0xFF43
|
||||
|
||||
.NR50 = 0x44 ; Sound register
|
||||
rNR50 = 0xFF44
|
||||
rAUDVOL = 0xFF44
|
||||
|
||||
AUDVOL_VIN_LEFT = 0b10000000 ; SO2
|
||||
AUDVOL_VIN_RIGHT = 0b00001000 ; SO1
|
||||
|
||||
.NR51 = 0x46 ; Sound register
|
||||
rNR51 = 0xFF46
|
||||
rAUDTERM = 0xFF46
|
||||
|
||||
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 = 0x45 ; Sound register
|
||||
rNR52 = 0xFF45
|
||||
rAUDENA = 0xFF45
|
||||
|
||||
AUDENA_ON = 0b10000000
|
||||
AUDENA_OFF = 0b00000000 ; sets all audio regs to 0!
|
||||
|
||||
.LCDC = 0x10 ; LCD control
|
||||
rLCDC = 0xFF10
|
||||
|
||||
LCDCF_OFF = 0b00000000 ; LCD Control Operation
|
||||
LCDCF_ON = 0b10000000 ; LCD Control Operation
|
||||
LCDCF_WIN9800 = 0b00000000 ; Window Tile Map Display Select
|
||||
LCDCF_WIN9C00 = 0b00001000 ; 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 = 0b00000100 ; BG Tile Map Display Select
|
||||
LCDCF_OBJ8 = 0b00000000 ; OBJ Construction
|
||||
LCDCF_OBJ16 = 0b00000010 ; OBJ Construction
|
||||
LCDCF_OBJOFF = 0b00000000 ; OBJ Display
|
||||
LCDCF_OBJON = 0b00000001 ; OBJ Display
|
||||
LCDCF_BGOFF = 0b00000000 ; BG Display
|
||||
LCDCF_BGON = 0b01000000 ; BG Display
|
||||
LCDCF_B_ON = 7
|
||||
LCDCF_B_WIN9C00 = 3
|
||||
LCDCF_B_WINON = 5
|
||||
LCDCF_B_BG8000 = 4
|
||||
LCDCF_B_BG9C00 = 2
|
||||
LCDCF_B_OBJ16 = 1
|
||||
LCDCF_B_OBJON = 0
|
||||
LCDCF_B_BGON = 6
|
||||
|
||||
.STAT = 0x11 ; LCD status
|
||||
rSTAT = 0xFF11
|
||||
|
||||
STATF_LYC = 0b00000010 ; LYC=LY Coincidence (Selectable)
|
||||
STATF_MODE10 = 0b00000100 ; Mode 10
|
||||
STATF_MODE01 = 0b00001000 ; Mode 01 (V-Blank)
|
||||
STATF_MODE00 = 0b00010000 ; Mode 00 (H-Blank)
|
||||
STATF_LYCF = 0b00100000 ; Coincidence Flag
|
||||
STATF_HBL = 0b00000000 ; H-Blank
|
||||
STATF_VBL = 0b10000000 ; V-Blank
|
||||
STATF_OAM = 0b01000000 ; OAM-RAM is used by system
|
||||
STATF_LCD = 0b11000000 ; Both OAM and VRAM used by system
|
||||
STATF_BUSY = 0b01000000 ; When set, VRAM access is unsafe
|
||||
STATF_B_LYC = 1
|
||||
STATF_B_MODE10 = 2
|
||||
STATF_B_MODE01 = 3
|
||||
STATF_B_MODE00 = 4
|
||||
STATF_B_LYCF = 5
|
||||
STATF_B_VBL = 7
|
||||
STATF_B_OAM = 6
|
||||
STATF_B_BUSY = 6
|
||||
|
||||
.SCY = 0x12 ; Scroll Y
|
||||
rSCY = 0xFF12
|
||||
|
||||
.SCX = 0x13 ; Scroll X
|
||||
rSCX = 0xFF13
|
||||
|
||||
.LY = 0x18 ; LCDC Y-coordinate
|
||||
rLY = 0xFF18
|
||||
|
||||
.LYC = 0x19 ; LY compare
|
||||
rLYC = 0xFF19
|
||||
|
||||
.DMA = 0x1A ; DMA transfer
|
||||
rDMA = 0xFF1A
|
||||
|
||||
.BGP = 0x1B ; BG palette data
|
||||
rBGP = 0xFF1B
|
||||
|
||||
.OBP0 = 0x14 ; OBJ palette 0 data
|
||||
rOBP0 = 0xFF14
|
||||
|
||||
.OBP1 = 0x15 ; OBJ palette 1 data
|
||||
rOBP1 = 0xFF15
|
||||
|
||||
.WY = 0x16 ; Window Y coordinate
|
||||
rWY = 0xFF16
|
||||
|
||||
.WX = 0x17 ; Window X coordinate
|
||||
rWX = 0xFF17
|
||||
|
||||
.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)
|
||||
|
||||
;; 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 = 0x01E0
|
||||
|
||||
;; C related
|
||||
;; Overheap of a banked call. Used for parameters
|
||||
;; = ret + real ret + bank
|
||||
|
||||
.if .NEAR_CALLS
|
||||
.BANKOV = 2
|
||||
|
||||
.else
|
||||
.BANKOV = 6
|
||||
|
||||
.endif
|
||||
|
||||
.globl __current_bank
|
||||
.globl __shadow_OAM_base
|
||||
|
||||
;; Global variables
|
||||
.globl .mode
|
||||
|
||||
.globl __cpu
|
||||
.globl __is_GBA
|
||||
|
||||
;; Global routines
|
||||
; .globl .set_mode ;; don't link mode.o by default
|
||||
|
||||
.globl .reset
|
||||
|
||||
.globl .display_off
|
||||
|
||||
.globl .wait_vbl_done
|
||||
|
||||
;; 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 ?lbl3
|
||||
; Multiply DE by A, return result in HL; preserves: BC
|
||||
LD HL, #0
|
||||
lbl1:
|
||||
SRL A
|
||||
JR NC, lbl2
|
||||
ADD HL, DE
|
||||
lbl2:
|
||||
JR Z, lbl3
|
||||
SLA E
|
||||
RL D
|
||||
JR lbl1
|
||||
lbl3:
|
||||
.endm
|
||||
|
||||
111
gbdk-lib/libc/targets/gbz80/duck/sfr.s
Normal file
111
gbdk-lib/libc/targets/gbz80/duck/sfr.s
Normal file
@@ -0,0 +1,111 @@
|
||||
__VRAM = 0x8000
|
||||
__VRAM8000 = 0x8000
|
||||
__VRAM8800 = 0x8800
|
||||
__VRAM9000 = 0x9000
|
||||
__SCRN0 = 0x9800
|
||||
__SCRN1 = 0x9C00
|
||||
__SRAM = 0xA000
|
||||
__RAM = 0xC000
|
||||
__RAMBANK = 0xD000
|
||||
__OAMRAM = 0xFE00
|
||||
__IO = 0xFF00
|
||||
__AUD3WAVERAM = 0xFF30
|
||||
__HRAM = 0xFF80
|
||||
|
||||
.globl __VRAM, __VRAM8000, __VRAM8800, __VRAM9000, __SCRN0, __SCRN1, __SRAM, __RAM, __RAMBANK, __OAMRAM, __IO, __AUD3WAVERAM, __HRAM
|
||||
|
||||
_rRAMG = 0x0000
|
||||
_rROMB0 = 0x2000
|
||||
_rROMB1 = 0x3000
|
||||
_rRAMB = 0x4000
|
||||
|
||||
.globl _rRAMG, _rROMB0, _rROMB1, _rRAMB
|
||||
|
||||
_P1_REG = 0xFF00 ; Joystick: 1.1.P15.P14.P13.P12.P11.P10
|
||||
_SB_REG = 0xFF01 ; Serial IO data buffer
|
||||
_SC_REG = 0xFF02 ; Serial IO control register
|
||||
_DIV_REG = 0xFF04 ; Divider register
|
||||
_TIMA_REG = 0xFF05 ; Timer counter
|
||||
_TMA_REG = 0xFF06 ; Timer modulo
|
||||
_TAC_REG = 0xFF07 ; Timer control
|
||||
_IF_REG = 0xFF0F ; Interrupt flags: 0.0.0.JOY.SIO.TIM.LCD.VBL
|
||||
_LCDC_REG = 0xFF10 ; LCD control
|
||||
_STAT_REG = 0xFF11 ; LCD status
|
||||
_SCY_REG = 0xFF12 ; Scroll Y
|
||||
_SCX_REG = 0xFF13 ; Scroll X
|
||||
_OBP0_REG = 0xFF14 ; OBJ palette 0 data
|
||||
_OBP1_REG = 0xFF15 ; OBJ palette 1 data
|
||||
_WY_REG = 0xFF16 ; Window Y coordinate
|
||||
_WX_REG = 0xFF17 ; Window X coordinate
|
||||
_LY_REG = 0xFF18 ; LCDC Y-coordinate
|
||||
_LYC_REG = 0xFF19 ; LY compare
|
||||
_DMA_REG = 0xFF1A ; DMA transfer
|
||||
_BGP_REG = 0xFF1B ; BG palette data
|
||||
_NR10_REG = 0xFF20 ; Sound register
|
||||
_NR12_REG = 0xFF21 ; Sound register
|
||||
_NR11_REG = 0xFF22 ; Sound register
|
||||
_NR13_REG = 0xFF23 ; Sound register
|
||||
_NR14_REG = 0xFF24 ; Sound register
|
||||
_NR21_REG = 0xFF26 ; Sound register
|
||||
_NR23_REG = 0xFF27 ; Sound register
|
||||
_NR22_REG = 0xFF28 ; Sound register
|
||||
_NR24_REG = 0xFF29 ; Sound register
|
||||
_NR30_REG = 0xFF2A ; Sound register
|
||||
_NR31_REG = 0xFF2B ; Sound register
|
||||
_NR32_REG = 0xFF2C ; Sound register
|
||||
_NR34_REG = 0xFF2D ; Sound register
|
||||
_NR33_REG = 0xFF2E ; Sound register
|
||||
_NR41_REG = 0xFF40 ; Sound register
|
||||
_NR43_REG = 0xFF41 ; Sound register
|
||||
_NR42_REG = 0xFF42 ; Sound register
|
||||
_NR44_REG = 0xFF43 ; Sound register
|
||||
_NR50_REG = 0xFF44 ; Sound register
|
||||
_NR52_REG = 0xFF45 ; Sound register
|
||||
_NR51_REG = 0xFF46 ; Sound register
|
||||
_PCM_SAMPLE = 0xFF30 ; PCM wave pattern
|
||||
|
||||
_KEY1_REG = 0xFF4D ; CPU speed
|
||||
_VBK_REG = 0xFF4F ; VRAM bank
|
||||
_HDMA1_REG = 0xFF51 ; DMA control 1
|
||||
_HDMA2_REG = 0xFF52 ; DMA control 2
|
||||
_HDMA3_REG = 0xFF53 ; DMA control 3
|
||||
_HDMA4_REG = 0xFF54 ; DMA control 4
|
||||
_HDMA5_REG = 0xFF55 ; DMA control 5
|
||||
_RP_REG = 0xFF56 ; IR port
|
||||
_BCPS_REG = 0xFF68 ; BG color palette specification
|
||||
_BCPD_REG = 0xFF69 ; BG color palette data
|
||||
_OCPS_REG = 0xFF6A ; OBJ color palette specification
|
||||
_OCPD_REG = 0xFF6B ; OBJ color palette data
|
||||
_SVBK_REG = 0xFF70 ; WRAM bank
|
||||
_PCM12_REG = 0xFF76 ; Sound channel 1&2 PCM amplitude (R)
|
||||
_PCM34_REG = 0xFF77 ; Sound channel 3&4 PCM amplitude (R)
|
||||
_IE_REG = 0xFFFF ; Interrupt enable
|
||||
|
||||
.globl _P1_REG
|
||||
.globl _SB_REG, _SC_REG
|
||||
.globl _DIV_REG
|
||||
.globl _TIMA_REG, _TMA_REG, _TAC_REG
|
||||
.globl _IF_REG
|
||||
.globl _NR10_REG, _NR11_REG, _NR12_REG, _NR13_REG, _NR14_REG
|
||||
.globl _NR21_REG, _NR22_REG, _NR23_REG, _NR24_REG
|
||||
.globl _NR30_REG, _NR31_REG, _NR32_REG, _NR33_REG, _NR34_REG
|
||||
.globl _NR41_REG, _NR42_REG, _NR43_REG, _NR44_REG
|
||||
.globl _NR50_REG, _NR51_REG, _NR52_REG
|
||||
.globl _PCM_SAMPLE
|
||||
.globl _LCDC_REG
|
||||
.globl _STAT_REG
|
||||
.globl _SCY_REG, _SCX_REG
|
||||
.globl _LY_REG, _LYC_REG
|
||||
.globl _DMA_REG
|
||||
.globl _BGP_REG
|
||||
.globl _OBP0_REG, _OBP1_REG
|
||||
.globl _WY_REG, _WX_REG
|
||||
.globl _KEY1_REG
|
||||
.globl _VBK_REG
|
||||
.globl _HDMA1_REG, _HDMA2_REG, _HDMA3_REG, _HDMA4_REG, _HDMA5_REG
|
||||
.globl _RP_REG
|
||||
.globl _BCPS_REG, _BCPD_REG
|
||||
.globl _OCPS_REG, _OCPD_REG
|
||||
.globl _SVBK_REG
|
||||
.globl _PCM12_REG, _PCM34_REG
|
||||
.globl _IE_REG
|
||||
@@ -43,7 +43,7 @@ ___call__banked::
|
||||
ld L, A
|
||||
ld A, (#___call_banked_bank)
|
||||
ldh (#__current_bank), A
|
||||
ld (.MBC1_ROM_PAGE),A
|
||||
ld (.MBC_ROM_PAGE),A
|
||||
jp (HL)
|
||||
1$:
|
||||
pop AF
|
||||
|
||||
481
gbdk-lib/libc/targets/gbz80/gb/crash_handler.s
Normal file
481
gbdk-lib/libc/targets/gbz80/gb/crash_handler.s
Normal file
@@ -0,0 +1,481 @@
|
||||
; Crash handler support
|
||||
; Original code by ISSOtm
|
||||
; Adapted by Toxa from gb-starter-kit: https://github.com/ISSOtm/gb-starter-kit
|
||||
|
||||
.include "global.s"
|
||||
|
||||
.globl _font_ibm
|
||||
|
||||
SCRN_X = 160 ; Width of screen in pixels
|
||||
SCRN_Y = 144 ; Height of screen in pixels
|
||||
SCRN_X_B = 20 ; Width of screen in bytes
|
||||
SCRN_Y_B = 18 ; Height of screen in bytes
|
||||
|
||||
SCRN_VX = 256 ; Virtual width of screen in pixels
|
||||
SCRN_VY = 256 ; Virtual height of screen in pixels
|
||||
SCRN_VX_B = 32 ; Virtual width of screen in bytes
|
||||
SCRN_VY_B = 32 ; Virtual height of screen in bytes
|
||||
|
||||
|
||||
.area _CRASH_HEADER(ABS)
|
||||
|
||||
.org 0x00
|
||||
nop
|
||||
nop
|
||||
rst 0x38
|
||||
|
||||
.org 0x38
|
||||
di
|
||||
jp ___HandleCrash
|
||||
|
||||
|
||||
.area _HOME
|
||||
|
||||
___HandleCrash::
|
||||
|
||||
; We will use VRAM as scratch, since we are going to overwrite it for
|
||||
; screen output anyways. The thing is, we need to turn the LCD off
|
||||
; *without* affecting flags... fun task, eh?
|
||||
|
||||
; Note: it's assumed that this was jumped to with IME off.
|
||||
; Don't call this directly, use `rst Crash`.
|
||||
|
||||
ld (wCrashA), a ; We need to have at least one working register, so...
|
||||
ldh a, (.IE) ; We're also going to overwrite this
|
||||
ld (wCrashIE), a
|
||||
ldh a, (.LCDC)
|
||||
ld (wCrashLCDC), a
|
||||
ld a, #LCDCF_ON ; LCDCF_ON Make sure the LCD is turned on to avoid waiting infinitely
|
||||
ldh (.LCDC), a
|
||||
ld a, #IEF_VBLANK ; IEF_VBLANK
|
||||
ld (.IE), a
|
||||
ld a, #0 ; `xor a` would overwrite flags
|
||||
ld (.IF), a ; No point in backing up that register, it's always changing
|
||||
halt ; With interrupts disabled, this will exit when `IE & IF != 0`
|
||||
nop ; Handle hardware bug if it becomes true *before* starting to execute the instruction (1-cycle window)
|
||||
|
||||
; We're now in VBlank! So we can now use VRAM as scratch for some cycles
|
||||
ld a, #0
|
||||
ldh (.LCDC), a ; Turn off LCD so VRAM can always be safely accessed
|
||||
; Save regs
|
||||
ld (vCrashSP), sp
|
||||
ld sp, #vCrashSP
|
||||
push hl
|
||||
push de
|
||||
push bc
|
||||
ld a, (wCrashA)
|
||||
push af
|
||||
|
||||
; We need to have all the data in bank 0, but we can't guarantee we were there
|
||||
ldh a, (.VBK)
|
||||
ld e, a
|
||||
bit #0, a
|
||||
jr z, .bank0
|
||||
; Oh noes. We need to copy the data across banks!
|
||||
ld hl, #vCrashAF
|
||||
ld c, #(5 * 2)
|
||||
.copyAcross:
|
||||
ld b, (hl)
|
||||
xor a
|
||||
ldh (.VBK), a
|
||||
ld (hl), b
|
||||
inc l ; inc hl
|
||||
inc a ; ld a, 1
|
||||
ldh (.VBK), a
|
||||
dec c
|
||||
jr nz, .copyAcross
|
||||
.bank0:
|
||||
xor a
|
||||
ldh (.NR52), a ; Kill sound for this screen
|
||||
|
||||
ldh (.VBK), a
|
||||
ld a, e
|
||||
ld (vCrashVBK), a ; copy vCrashVBK across banks
|
||||
|
||||
ld a, #1
|
||||
ldh (.VBK), a
|
||||
ld hl, #vCrashDumpScreen
|
||||
ld b, #SCRN_Y_B
|
||||
.writeAttrRow:
|
||||
xor a
|
||||
ld c, #(SCRN_X_B + 1)
|
||||
rst #0x28 ; .MemsetSmall
|
||||
ld a, l
|
||||
add a, #(SCRN_VX_B - SCRN_X_B - 1)
|
||||
ld l, a
|
||||
dec b
|
||||
jr nz, .writeAttrRow
|
||||
xor a
|
||||
ldh (.VBK), a
|
||||
|
||||
; Load palettes
|
||||
ld a, #0x03
|
||||
ldh (.BGP), a
|
||||
ld a, #0x80
|
||||
ldh (.BCPS), a
|
||||
xor a
|
||||
ld c, #.BCPD
|
||||
ldh (c), a
|
||||
ldh (c), a
|
||||
dec a ; ld a, $FF
|
||||
ldh (c), a
|
||||
ldh (c), a
|
||||
ldh (c), a
|
||||
ldh (c), a
|
||||
ldh (c), a
|
||||
ldh (c), a
|
||||
|
||||
ld a, #(SCRN_VY - SCRN_Y)
|
||||
ldh (.SCY), a
|
||||
ld a, #(SCRN_VX - SCRN_X - 4)
|
||||
ldh (.SCX), a
|
||||
|
||||
call loadfont
|
||||
|
||||
; Copy the registers to the dump viewers
|
||||
ld hl, #vDumpHL
|
||||
ld de, #vCrashHL
|
||||
ld c, #4
|
||||
rst #0x30 ; .MemcpySmall
|
||||
|
||||
; We're now going to draw the screen, top to bottom
|
||||
ld hl, #vCrashDumpScreen
|
||||
|
||||
; First 3 lines of text
|
||||
ld de, #.header
|
||||
ld b, #3
|
||||
.writeHeaderLine:
|
||||
ld a, #0x20 ; " "
|
||||
ld (hl+), a
|
||||
ld c, #19
|
||||
rst #0x30 ; .MemcpySmall
|
||||
ld a, #0x20 ; " "
|
||||
ld (hl+), a
|
||||
ld a, l
|
||||
add a, #(SCRN_VX_B - SCRN_X_B - 1)
|
||||
ld l, a
|
||||
dec b
|
||||
jr nz, .writeHeaderLine
|
||||
|
||||
; Blank line
|
||||
ld a, #0x20 ; " "
|
||||
ld c, #(SCRN_X_B + 1)
|
||||
rst #0x28 ; .MemsetSmall
|
||||
|
||||
; AF and console model
|
||||
ld l, #<vCrashDumpScreenRow4
|
||||
ld c, #4
|
||||
rst #0x30 ; .MemcpySmall
|
||||
pop bc
|
||||
call .printHexBC
|
||||
ld c, #8
|
||||
rst #0x30 ; .MemcpySmall
|
||||
ld a, (__cpu)
|
||||
call .printHexA
|
||||
ld a, #0x20 ; " "
|
||||
ld (hl+), a
|
||||
ld (hl+), a
|
||||
ld (hl+), a
|
||||
|
||||
; BC and DE
|
||||
ld l, #<vCrashDumpScreenRow5
|
||||
ld c, #4
|
||||
rst #0x30 ; .MemcpySmall
|
||||
pop bc
|
||||
call .printHexBC
|
||||
ld c, #6
|
||||
rst #0x30 ; .MemcpySmall
|
||||
pop bc
|
||||
call .printHexBC
|
||||
ld a, #0x20
|
||||
ld (hl+), a
|
||||
ld (hl+), a
|
||||
ld (hl+), a
|
||||
|
||||
; Now, the two memory dumps
|
||||
.writeDump:
|
||||
ld a, l
|
||||
add a, #(SCRN_VX_B - SCRN_X_B - 1)
|
||||
ld l, a
|
||||
ld c, #4
|
||||
rst #0x30 ; .MemcpySmall
|
||||
pop bc
|
||||
push bc
|
||||
call .printHexBC
|
||||
ld de, #.viewStr
|
||||
ld c, #7
|
||||
rst #0x30 ; .MemcpySmall
|
||||
pop de
|
||||
call .printDump
|
||||
ld de, #.spStr
|
||||
bit #7, l
|
||||
jr z, .writeDump
|
||||
|
||||
ld de, #.hwRegsStrs
|
||||
ld l, #<vCrashDumpScreenRow14
|
||||
ld c, #6
|
||||
rst #0x30 ; .MemcpySmall
|
||||
ld a, (wCrashLCDC)
|
||||
call .printHexA
|
||||
ld c, #4
|
||||
rst #0x30 ; .MemcpySmall
|
||||
ldh a, (.KEY1)
|
||||
call .printHexA
|
||||
ld c, #4
|
||||
rst #0x30 ; .MemcpySmall
|
||||
ld a, (wCrashIE)
|
||||
call .printHexA
|
||||
ld (hl), #0x20 ; " "
|
||||
|
||||
ld l, #<vCrashDumpScreenRow15
|
||||
ld c, #7
|
||||
rst #0x30 ; .MemcpySmall
|
||||
.writeBank:
|
||||
ld a, #0x20 ; " "
|
||||
ld (hl+), a
|
||||
ld a, (de)
|
||||
inc de
|
||||
ld (hl+), a
|
||||
cp #0x20 ; " "
|
||||
jr z, .banksDone
|
||||
ld a, (de)
|
||||
inc de
|
||||
ld c, a
|
||||
ld a, (de)
|
||||
inc de
|
||||
ld b, a
|
||||
ld a, (bc)
|
||||
call .printHexA
|
||||
jr .writeBank
|
||||
.banksDone:
|
||||
|
||||
; Start displaying
|
||||
ld a, #(LCDCF_ON | LCDCF_BG9C00 | LCDCF_BGON)
|
||||
ldh (.LCDC), a
|
||||
|
||||
.loop:
|
||||
; The code never lags, and IE is equal to IEF_VBLANK
|
||||
xor a
|
||||
ldh (.IF), a
|
||||
halt
|
||||
|
||||
jr .loop
|
||||
|
||||
.printHexBC:
|
||||
call .printHexB
|
||||
ld a, c
|
||||
.printHexA:
|
||||
ld b, a
|
||||
.printHexB:
|
||||
ld a, b
|
||||
and #0xF0
|
||||
swap a
|
||||
add a, #0x30
|
||||
cp #0x3a
|
||||
jr c, 1$
|
||||
add a, #(0x41 - 0x3a)
|
||||
1$: ld (hl+), a
|
||||
ld a, b
|
||||
and #0x0F
|
||||
add a, #0x30
|
||||
cp #0x3a
|
||||
jr c, 2$
|
||||
add a, #(0x41 - 0x3a)
|
||||
2$: ld (hl+), a
|
||||
ret
|
||||
|
||||
.printDump:
|
||||
ld b, d
|
||||
ld c, e
|
||||
call .printHexBC
|
||||
ld a, #0x20 ; " "
|
||||
ld (hl+), a
|
||||
ld (hl+), a
|
||||
ld a, e
|
||||
sub #8
|
||||
ld e, a
|
||||
ld a, d
|
||||
sbc #0
|
||||
ld d, a
|
||||
.writeDumpLine:
|
||||
ld a, l
|
||||
add a, #(SCRN_VX_B - SCRN_X_B - 1)
|
||||
ld l, a
|
||||
ld a, #0x20 ; " "
|
||||
ld (hl+), a
|
||||
.writeDumpWord:
|
||||
ld a, (de)
|
||||
inc de
|
||||
call .printHexA
|
||||
ld a, (de)
|
||||
inc de
|
||||
call .printHexA
|
||||
ld a, #0x20 ; " "
|
||||
ld (hl+), a
|
||||
bit 4, l
|
||||
jr nz, .writeDumpWord
|
||||
ld a, l
|
||||
and #0x7F
|
||||
jr nz, .writeDumpLine
|
||||
ret
|
||||
|
||||
loadfont:
|
||||
xor a
|
||||
cpl
|
||||
ld hl, #0x9000
|
||||
ld c, #16
|
||||
rst #0x28 ; .MemsetSmall
|
||||
ld hl, #(0x9000 + ' ' * 16)
|
||||
ld c, #16
|
||||
rst #0x28 ; .MemsetSmall
|
||||
|
||||
ld de, #(_font_ibm + 2 + '0') ; recode table
|
||||
ld hl, #(0x9000 + '0' * 16) ; destination
|
||||
push hl
|
||||
ld c, #(16 * 3)
|
||||
1$:
|
||||
ld a, (de)
|
||||
inc de
|
||||
push de
|
||||
|
||||
swap a
|
||||
ld l, a
|
||||
and #0x0f
|
||||
ld h, a
|
||||
ld a, l
|
||||
and #0xf0
|
||||
srl h
|
||||
rra
|
||||
ld l, a
|
||||
ld de, #(_font_ibm + 2 + 128)
|
||||
add hl, de
|
||||
|
||||
ld d, h
|
||||
ld e, l
|
||||
|
||||
ldhl sp, #2
|
||||
ld a, (hl+)
|
||||
ld h, (hl)
|
||||
ld l, a
|
||||
|
||||
ld b, #8
|
||||
2$:
|
||||
ld a, (de)
|
||||
cpl
|
||||
inc de
|
||||
ld (hl+), a
|
||||
ld (hl+), a
|
||||
|
||||
dec b
|
||||
jr nz, 2$
|
||||
|
||||
ld d, h
|
||||
ld a, l
|
||||
ldhl sp, #2
|
||||
ld (hl+), a
|
||||
ld (hl), d
|
||||
|
||||
pop de
|
||||
|
||||
dec c
|
||||
jr nz, 1$
|
||||
|
||||
add sp, #2
|
||||
ret
|
||||
|
||||
.header:
|
||||
; 0123456789ABCDEFGHI 19 chars
|
||||
.ascii "KERNEL PANIC PLEASE"
|
||||
.ascii "SEND A CLEAR PIC OF"
|
||||
.ascii "THIS SCREEN TO DEVS"
|
||||
.ascii " AF:"
|
||||
.ascii " MODEL:"
|
||||
.ascii " BC:"
|
||||
.ascii " DE:"
|
||||
.ascii " HL:"
|
||||
.viewStr:
|
||||
.ascii " VIEW:"
|
||||
.spStr:
|
||||
.ascii " SP:"
|
||||
.hwRegsStrs:
|
||||
.ascii " LCDC:"
|
||||
.ascii " K1:"
|
||||
.ascii " IE:"
|
||||
.ascii " BANK:"
|
||||
.ascii "R"
|
||||
.dw __current_bank
|
||||
.ascii "V"
|
||||
.dw vCrashVBK
|
||||
.ascii "W"
|
||||
.db .SVBK, 0xff
|
||||
.ascii " "
|
||||
|
||||
|
||||
.area _DATA
|
||||
|
||||
wCrashA:
|
||||
.ds 1 ; We need at least one working register, and A allows accessing memory
|
||||
wCrashIE:
|
||||
.ds 1
|
||||
wCrashLCDC:
|
||||
.ds 1
|
||||
|
||||
|
||||
.area _CRASH_SCRATCH(ABS)
|
||||
|
||||
.org 0x9C00
|
||||
|
||||
; Put the crash dump screen at the bottom-right of the 9C00 tilemap, since that tends to be unused space
|
||||
.ds SCRN_VX_B * (SCRN_VY_B - SCRN_Y_B - 2) ; 2 rows reserved as scratch space
|
||||
|
||||
.ds SCRN_X_B ; Try not to overwrite the window area
|
||||
.ds 2 * 1 ; Free stack entries (we spill into the above by 1 entry, though :/)
|
||||
; These are the initial values of the registers
|
||||
; They are popped off the stack when printed, freeing up stack space
|
||||
|
||||
vCrashAF:
|
||||
.ds 2
|
||||
vCrashBC:
|
||||
.ds 2
|
||||
vCrashDE:
|
||||
.ds 2
|
||||
vCrashHL:
|
||||
.ds 2
|
||||
vCrashSP:
|
||||
.ds 2
|
||||
|
||||
.ds SCRN_X_B
|
||||
vHeldKeys:
|
||||
.ds 1 ; Keys held on previous frame
|
||||
vUnlockCounter:
|
||||
.ds 1 ; How many frames until dumps are "unlocked"
|
||||
vWhichDump:
|
||||
.ds 1
|
||||
vDumpHL:
|
||||
.ds 2
|
||||
vDumpSP:
|
||||
.ds 2
|
||||
vCrashVBK:
|
||||
.ds 1
|
||||
.ds 4 ; Unused
|
||||
|
||||
.ds SCRN_VX_B - SCRN_X_B - 1
|
||||
vCrashDumpScreen:
|
||||
vCrashDumpScreenRow0 = vCrashDumpScreen + 1 * SCRN_VX_B
|
||||
vCrashDumpScreenRow1 = vCrashDumpScreen + 2 * SCRN_VX_B
|
||||
vCrashDumpScreenRow2 = vCrashDumpScreen + 3 * SCRN_VX_B
|
||||
vCrashDumpScreenRow3 = vCrashDumpScreen + 4 * SCRN_VX_B
|
||||
vCrashDumpScreenRow4 = vCrashDumpScreen + 5 * SCRN_VX_B
|
||||
vCrashDumpScreenRow5 = vCrashDumpScreen + 6 * SCRN_VX_B
|
||||
vCrashDumpScreenRow6 = vCrashDumpScreen + 7 * SCRN_VX_B
|
||||
vCrashDumpScreenRow7 = vCrashDumpScreen + 8 * SCRN_VX_B
|
||||
vCrashDumpScreenRow8 = vCrashDumpScreen + 9 * SCRN_VX_B
|
||||
vCrashDumpScreenRow9 = vCrashDumpScreen + 10 * SCRN_VX_B
|
||||
vCrashDumpScreenRow10 = vCrashDumpScreen + 11 * SCRN_VX_B
|
||||
vCrashDumpScreenRow11 = vCrashDumpScreen + 12 * SCRN_VX_B
|
||||
vCrashDumpScreenRow12 = vCrashDumpScreen + 13 * SCRN_VX_B
|
||||
vCrashDumpScreenRow13 = vCrashDumpScreen + 14 * SCRN_VX_B
|
||||
vCrashDumpScreenRow14 = vCrashDumpScreen + 15 * SCRN_VX_B
|
||||
vCrashDumpScreenRow15 = vCrashDumpScreen + 16 * SCRN_VX_B
|
||||
vCrashDumpScreenRow16 = vCrashDumpScreen + 17 * SCRN_VX_B
|
||||
vCrashDumpScreenRow17 = vCrashDumpScreen + 18 * SCRN_VX_B
|
||||
@@ -20,6 +20,7 @@
|
||||
;; MBC Equates
|
||||
|
||||
.MBC1_ROM_PAGE = 0x2000 ; Address to write to for MBC1 switching
|
||||
.MBC_ROM_PAGE = 0x2000 ; Default platform MBC rom switching address
|
||||
|
||||
rRAMG = 0x0000 ; $0000->$1fff
|
||||
rROMB0 = 0x2000 ; $2000->$2fff
|
||||
|
||||
Reference in New Issue
Block a user