Port over berry fix program
This commit is contained in:
@@ -84,10 +84,12 @@ clean: tidy
|
|||||||
rm -f sound/direct_sound_samples/*.bin
|
rm -f sound/direct_sound_samples/*.bin
|
||||||
rm -f $(SONG_OBJS)
|
rm -f $(SONG_OBJS)
|
||||||
find . \( -iname '*.1bpp' -o -iname '*.4bpp' -o -iname '*.8bpp' -o -iname '*.gbapal' -o -iname '*.lz' -o -iname '*.latfont' -o -iname '*.hwjpnfont' -o -iname '*.fwjpnfont' \) -exec rm {} +
|
find . \( -iname '*.1bpp' -o -iname '*.4bpp' -o -iname '*.8bpp' -o -iname '*.gbapal' -o -iname '*.lz' -o -iname '*.latfont' -o -iname '*.hwjpnfont' -o -iname '*.fwjpnfont' \) -exec rm {} +
|
||||||
|
@$(MAKE) -C berry_fix clean
|
||||||
|
|
||||||
tidy:
|
tidy:
|
||||||
rm -f $(ROM) $(ELF) $(MAP)
|
rm -f $(ROM) $(ELF) $(MAP)
|
||||||
rm -r build/*
|
rm -r build/*
|
||||||
|
@$(MAKE) -C berry_fix tidy
|
||||||
|
|
||||||
include graphics_file_rules.mk
|
include graphics_file_rules.mk
|
||||||
|
|
||||||
@@ -169,3 +171,6 @@ $(ELF): $(OBJ_DIR)/ld_script.ld $(OBJS)
|
|||||||
$(ROM): $(ELF)
|
$(ROM): $(ELF)
|
||||||
$(OBJCOPY) -O binary $< $@
|
$(OBJCOPY) -O binary $< $@
|
||||||
$(FIX) $@ -p -t"$(TITLE)" -c$(GAME_CODE) -m$(MAKER_CODE) -r$(REVISION) --silent
|
$(FIX) $@ -p -t"$(TITLE)" -c$(GAME_CODE) -m$(MAKER_CODE) -r$(REVISION) --silent
|
||||||
|
|
||||||
|
berry_fix/berry_fix.gba:
|
||||||
|
@$(MAKE) -C berry_fix
|
||||||
|
|||||||
@@ -0,0 +1,160 @@
|
|||||||
|
include $(DEVKITARM)/base_tools
|
||||||
|
export CPP := $(PREFIX)cpp
|
||||||
|
export LD := $(PREFIX)ld
|
||||||
|
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
EXE := .exe
|
||||||
|
else
|
||||||
|
EXE :=
|
||||||
|
endif
|
||||||
|
|
||||||
|
GAME_CODE := AGBJ
|
||||||
|
MAKER_CODE := 01
|
||||||
|
REVISION := 0
|
||||||
|
|
||||||
|
SHELL := /bin/bash -o pipefail
|
||||||
|
|
||||||
|
CPPFLAGS := -I ../tools/agbcc/include -I ../tools/agbcc -iquote include -nostdinc -undef
|
||||||
|
|
||||||
|
ROM := berry_fix.gba
|
||||||
|
OBJ_DIR := build
|
||||||
|
CC1 := ../tools/agbcc/bin/agbcc$(EXE)
|
||||||
|
override CFLAGS += -mthumb-interwork -Wimplicit -Wparentheses -Werror -O2 -fhex-asm
|
||||||
|
|
||||||
|
|
||||||
|
ELF = $(ROM:.gba=.elf)
|
||||||
|
MAP = $(ROM:.gba=.map)
|
||||||
|
|
||||||
|
C_SUBDIR = src
|
||||||
|
ASM_SUBDIR = asm
|
||||||
|
DATA_ASM_SUBDIR = data
|
||||||
|
|
||||||
|
C_BUILDDIR = $(OBJ_DIR)/$(C_SUBDIR)
|
||||||
|
ASM_BUILDDIR = $(OBJ_DIR)/$(ASM_SUBDIR)
|
||||||
|
DATA_ASM_BUILDDIR = $(OBJ_DIR)/$(DATA_ASM_SUBDIR)
|
||||||
|
|
||||||
|
ASFLAGS := -mcpu=arm7tdmi
|
||||||
|
|
||||||
|
LDFLAGS = -Map ../$(MAP)
|
||||||
|
|
||||||
|
SHA1 := $(shell { command -v sha1sum || command -v shasum; } 2>/dev/null) -c
|
||||||
|
GFX := ../tools/gbagfx/gbagfx$(EXE)
|
||||||
|
AIF := ../tools/aif2pcm/aif2pcm$(EXE)
|
||||||
|
MID := ../tools/mid2agb/mid2agb$(EXE)
|
||||||
|
SCANINC := ../tools/scaninc/scaninc$(EXE)
|
||||||
|
PREPROC := ../tools/preproc/preproc$(EXE)
|
||||||
|
RAMSCRGEN := ../tools/ramscrgen/ramscrgen$(EXE)
|
||||||
|
FIX := ../tools/gbafix/gbafix$(EXE)
|
||||||
|
|
||||||
|
# Clear the default suffixes
|
||||||
|
.SUFFIXES:
|
||||||
|
# Don't delete intermediate files
|
||||||
|
.SECONDARY:
|
||||||
|
# Delete files that weren't built properly
|
||||||
|
.DELETE_ON_ERROR:
|
||||||
|
|
||||||
|
# Secondary expansion is required for dependency variables in object rules.
|
||||||
|
.SECONDEXPANSION:
|
||||||
|
|
||||||
|
.PHONY: rom clean compare tidy
|
||||||
|
|
||||||
|
C_SRCS := $(wildcard $(C_SUBDIR)/*.c $(C_SUBDIR)/*/*.c $(C_SUBDIR)/*/*/*.c)
|
||||||
|
C_OBJS := $(patsubst $(C_SUBDIR)/%.c,$(C_BUILDDIR)/%.o,$(C_SRCS))
|
||||||
|
|
||||||
|
ASM_SRCS := $(wildcard $(ASM_SUBDIR)/*.s)
|
||||||
|
ASM_OBJS := $(patsubst $(ASM_SUBDIR)/%.s,$(ASM_BUILDDIR)/%.o,$(ASM_SRCS))
|
||||||
|
|
||||||
|
DATA_ASM_SRCS := $(wildcard $(DATA_ASM_SUBDIR)/*.s)
|
||||||
|
DATA_ASM_OBJS := $(patsubst $(DATA_ASM_SUBDIR)/%.s,$(DATA_ASM_BUILDDIR)/%.o,$(DATA_ASM_SRCS))
|
||||||
|
|
||||||
|
SONG_SRCS := $(wildcard $(SONG_SUBDIR)/*.s)
|
||||||
|
SONG_OBJS := $(patsubst $(SONG_SUBDIR)/%.s,$(SONG_BUILDDIR)/%.o,$(SONG_SRCS))
|
||||||
|
|
||||||
|
MID_SRCS := $(wildcard $(MID_SUBDIR)/*.mid)
|
||||||
|
MID_OBJS := $(patsubst $(MID_SUBDIR)/%.mid,$(MID_BUILDDIR)/%.o,$(MID_SRCS))
|
||||||
|
|
||||||
|
OBJS := $(C_OBJS) $(ASM_OBJS) $(DATA_ASM_OBJS) $(SONG_OBJS) $(MID_OBJS)
|
||||||
|
# OBJS_REL := $(patsubst $(OBJ_DIR)/%,%,$(OBJS))
|
||||||
|
|
||||||
|
SUBDIRS := $(sort $(dir $(OBJS)))
|
||||||
|
|
||||||
|
$(shell mkdir -p $(SUBDIRS))
|
||||||
|
|
||||||
|
rom: $(ROM)
|
||||||
|
|
||||||
|
# For contributors to make sure a change didn't affect the contents of the ROM.
|
||||||
|
compare: $(ROM)
|
||||||
|
@$(SHA1) rom.sha1
|
||||||
|
|
||||||
|
clean: tidy
|
||||||
|
rm -f sound/direct_sound_samples/*.bin
|
||||||
|
rm -f $(SONG_OBJS) $(MID_OBJS) $(MID_SUBDIR)/*.s
|
||||||
|
find . \( -iname '*.1bpp' -o -iname '*.4bpp' -o -iname '*.8bpp' -o -iname '*.gbapal' -o -iname '*.lz' -o -iname '*.latfont' -o -iname '*.hwjpnfont' -o -iname '*.fwjpnfont' \) -exec rm {} +
|
||||||
|
make -C payload clean
|
||||||
|
|
||||||
|
tidy:
|
||||||
|
rm -f $(ROM) $(ELF) $(MAP)
|
||||||
|
rm -r build/*
|
||||||
|
make -C payload tidy
|
||||||
|
|
||||||
|
%.s: ;
|
||||||
|
%.png: ;
|
||||||
|
%.pal: ;
|
||||||
|
%.aif: ;
|
||||||
|
|
||||||
|
%.1bpp: %.png ; $(GFX) $< $@
|
||||||
|
%.4bpp: %.png ; $(GFX) $< $@
|
||||||
|
%.8bpp: %.png ; $(GFX) $< $@
|
||||||
|
%.gbapal: %.pal ; $(GFX) $< $@
|
||||||
|
%.gbapal: %.png ; $(GFX) $< $@
|
||||||
|
%.lz: % ; $(GFX) $< $@
|
||||||
|
%.rl: % ; $(GFX) $< $@
|
||||||
|
|
||||||
|
|
||||||
|
ifeq ($(NODEP),1)
|
||||||
|
$(C_BUILDDIR)/%.o: c_dep :=
|
||||||
|
else
|
||||||
|
$(C_BUILDDIR)/%.o: c_dep = $(shell $(SCANINC) -I include $(C_SUBDIR)/$*.c)
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(C_BUILDDIR)/%.o : $(C_SUBDIR)/%.c $$(c_dep)
|
||||||
|
@$(CPP) $(CPPFLAGS) $< -o $(C_BUILDDIR)/$*.i
|
||||||
|
@$(PREPROC) $(C_BUILDDIR)/$*.i charmap.txt | $(CC1) $(CFLAGS) -o $(C_BUILDDIR)/$*.s
|
||||||
|
$(AS) $(ASFLAGS) -o $@ $(C_BUILDDIR)/$*.s
|
||||||
|
|
||||||
|
ifeq ($(NODEP),1)
|
||||||
|
$(ASM_BUILDDIR)/%.o: asm_dep :=
|
||||||
|
else
|
||||||
|
$(ASM_BUILDDIR)/%.o: asm_dep = $(shell $(SCANINC) $(ASM_SUBDIR)/$*.s)
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(ASM_BUILDDIR)/%.o: $(ASM_SUBDIR)/%.s $$(asm_dep)
|
||||||
|
$(AS) $(ASFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
ifeq ($(NODEP),1)
|
||||||
|
$(DATA_ASM_BUILDDIR)/%.o: data_dep :=
|
||||||
|
else
|
||||||
|
$(DATA_ASM_BUILDDIR)/%.o: data_dep = $(shell $(SCANINC) $(DATA_ASM_SUBDIR)/$*.s)
|
||||||
|
endif
|
||||||
|
|
||||||
|
payload: data/payload.gba.lz
|
||||||
|
|
||||||
|
payload/payload.gba:
|
||||||
|
$(MAKE) -C payload/
|
||||||
|
|
||||||
|
data/payload.gba.lz: payload/payload.gba
|
||||||
|
$(GFX) $< $@ -search 1
|
||||||
|
|
||||||
|
$(DATA_ASM_BUILDDIR)/%.o: $(DATA_ASM_SUBDIR)/%.s $$(data_dep)
|
||||||
|
$(PREPROC) $< charmap.txt | $(CPP) -I include | $(AS) $(ASFLAGS) -o $@
|
||||||
|
|
||||||
|
$(SONG_BUILDDIR)/%.o: $(SONG_SUBDIR)/%.s
|
||||||
|
$(AS) $(ASFLAGS) -I sound -o $@ $<
|
||||||
|
|
||||||
|
$(ELF): ld_script.txt $(OBJS)
|
||||||
|
cd $(OBJ_DIR) && $(LD) $(LDFLAGS) -T ../ld_script.txt -o ../$@
|
||||||
|
|
||||||
|
$(ROM): $(ELF)
|
||||||
|
$(OBJCOPY) -O binary $< $@
|
||||||
|
$(FIX) $@ -c$(GAME_CODE) -m$(MAKER_CODE) -r$(REVISION) --silent
|
||||||
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
.global BerryFixMBHeaderNintendoLogo
|
||||||
|
BerryFixMBHeaderNintendoLogo:
|
||||||
|
.space 156
|
||||||
|
|
||||||
|
BerryFixMBHeaderGameTitle:
|
||||||
|
.space 12
|
||||||
|
|
||||||
|
.global BerryFixMBHeaderGameCode
|
||||||
|
BerryFixMBHeaderGameCode:
|
||||||
|
.space 4
|
||||||
|
|
||||||
|
BerryFixMBHeaderMakerCode:
|
||||||
|
.space 2
|
||||||
|
|
||||||
|
BerryFixMBHeaderMagic:
|
||||||
|
.byte 0
|
||||||
|
|
||||||
|
BerryFixMBHeaderMainUnitCode:
|
||||||
|
.byte 0
|
||||||
|
|
||||||
|
BerryFixMBHeaderDeviceType:
|
||||||
|
.byte 0
|
||||||
|
|
||||||
|
BerryFixMBHeaderReserved1:
|
||||||
|
.space 7
|
||||||
|
|
||||||
|
.global BerryFixMBHeaderSoftwareVersion
|
||||||
|
BerryFixMBHeaderSoftwareVersion:
|
||||||
|
.byte 0
|
||||||
|
|
||||||
|
BerryFixMBHeaderChecksum:
|
||||||
|
.byte 0
|
||||||
|
|
||||||
|
BerryFixMBHeaderReserved2:
|
||||||
|
.space 2
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
.include "asm/macros/asm.inc"
|
||||||
|
.include "asm/macros/function.inc"
|
||||||
|
.include "constants/gba_constants.inc"
|
||||||
|
|
||||||
|
.set SIO_ERROR, 0x0040
|
||||||
|
.set SIO_MULTI_BUSY, 0x0080
|
||||||
|
|
||||||
|
.set EWRAM_ORIG, 0x02000000
|
||||||
|
.set gCode, 0x02010000
|
||||||
|
.set PROG_ORIG, 0x00008000
|
||||||
|
|
||||||
|
.syntax unified
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
arm_func_start _start
|
||||||
|
_start: @ 0
|
||||||
|
b _entry
|
||||||
|
arm_func_end _start
|
||||||
|
|
||||||
|
.include "asm/berry_fix_header.inc"
|
||||||
|
|
||||||
|
@ C0
|
||||||
|
.word 0
|
||||||
|
|
||||||
|
.global _GPIOPortData
|
||||||
|
_GPIOPortData: @ C4
|
||||||
|
.2byte 0
|
||||||
|
|
||||||
|
.global _GPIOPortDirection
|
||||||
|
_GPIOPortDirection: @ C6
|
||||||
|
.2byte 0
|
||||||
|
|
||||||
|
.global _GPIOPortReadEnable
|
||||||
|
_GPIOPortReadEnable: @ C8
|
||||||
|
.2byte 0
|
||||||
|
|
||||||
|
@ CA
|
||||||
|
.2byte 0
|
||||||
|
|
||||||
|
@ CC
|
||||||
|
.space 0x34
|
||||||
|
|
||||||
|
arm_func_start _entry
|
||||||
|
_entry: @ 100
|
||||||
|
b _send
|
||||||
|
arm_func_end _entry
|
||||||
|
|
||||||
|
.space 0x1C
|
||||||
|
|
||||||
|
arm_func_start _recv
|
||||||
|
_recv:
|
||||||
|
@ Waits until link cable is no longer busy.
|
||||||
|
@ Returns nz if an error has occurred
|
||||||
|
@ Otherwise, returns the received short in r1.
|
||||||
|
@ Preserves r0
|
||||||
|
_120:
|
||||||
|
ldrh r1, [r0, 0x8] @ SIOCNT
|
||||||
|
tst r1, SIO_MULTI_BUSY
|
||||||
|
beq _120
|
||||||
|
_12c:
|
||||||
|
ldrh r1, [r0, 0x8] @ SIOCNT
|
||||||
|
tst r1, SIO_MULTI_BUSY
|
||||||
|
bne _12c
|
||||||
|
ldrh r1, [r0, 0x8] @ SIOCNT
|
||||||
|
tst r1, SIO_ERROR
|
||||||
|
bxne lr
|
||||||
|
ldrh r1, [r0] @ SIOMULTI0
|
||||||
|
bx lr
|
||||||
|
arm_func_end _recv
|
||||||
|
|
||||||
|
arm_func_start _send
|
||||||
|
_send: @ 14c
|
||||||
|
ldr r0, =REG_SIOMULTI0
|
||||||
|
_150:
|
||||||
|
bl _recv
|
||||||
|
bne _150
|
||||||
|
mov r2, 0
|
||||||
|
strh r2, [r0, 0xa] @ SIOMLT_SEND
|
||||||
|
cmp r1, 0
|
||||||
|
bne _150
|
||||||
|
mov r2, 0x8000
|
||||||
|
_16c:
|
||||||
|
mov r1, 0
|
||||||
|
_170:
|
||||||
|
strh r1, [r0, 0xa] @ SIOMLT_SEND
|
||||||
|
bl _recv
|
||||||
|
bne _150
|
||||||
|
cmp r1, r2
|
||||||
|
bne _16c
|
||||||
|
lsr r2, 5
|
||||||
|
cmp r1, 0
|
||||||
|
bne _170
|
||||||
|
ldr r3, =BerryFixMBHeaderGameCode
|
||||||
|
ldrh r2, [r3]
|
||||||
|
strh r2, [r0, 0xa] @ SIOMLT_SEND
|
||||||
|
bl _recv
|
||||||
|
_1a0:
|
||||||
|
bne _1a0
|
||||||
|
cmp r1, r2
|
||||||
|
bne _1a0
|
||||||
|
ldrh r2, [r3, 0x2]
|
||||||
|
strh r2, [r0, 0xa] @ SIOMLT_SEND
|
||||||
|
bl _recv
|
||||||
|
bne _1a0
|
||||||
|
cmp r1, r2
|
||||||
|
bne _1a0
|
||||||
|
mov r1, 0
|
||||||
|
strh r1, [r0, 0xa] @ SIOMLT_SEND
|
||||||
|
ldr r0, =_data_2f0
|
||||||
|
ldr r1, =gCode
|
||||||
|
swi 0x11 << 16
|
||||||
|
ldr lr, =gCode
|
||||||
|
bx lr
|
||||||
|
.pool
|
||||||
|
arm_func_end _send
|
||||||
|
@ 1f0
|
||||||
|
|
||||||
|
.align 2, 0 @ don't pad with nop
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
.macro inc x
|
||||||
|
.set \x, \x + 1
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro enum_start x=0
|
||||||
|
.set __enum__, \x
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro enum constant
|
||||||
|
.equiv \constant, __enum__
|
||||||
|
inc __enum__
|
||||||
|
.endm
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
.macro arm_func_start name
|
||||||
|
.align 2, 0
|
||||||
|
.global \name
|
||||||
|
.arm
|
||||||
|
.type \name, %function
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro arm_func_end name
|
||||||
|
.size \name, .-\name
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro thumb_func_start name
|
||||||
|
.align 2, 0
|
||||||
|
.global \name
|
||||||
|
.thumb
|
||||||
|
.thumb_func
|
||||||
|
.type \name, %function
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro non_word_aligned_thumb_func_start name
|
||||||
|
.global \name
|
||||||
|
.thumb
|
||||||
|
.thumb_func
|
||||||
|
.type \name, %function
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro thumb_func_end name
|
||||||
|
.size \name, .-\name
|
||||||
|
.endm
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
OBJDUMP="$DEVKITARM/bin/arm-none-eabi-objdump -D -bbinary -marmv4t -Mforce-thumb"
|
||||||
|
OPTIONS="--start-address=$(($1)) --stop-address=$(($1 + $2))"
|
||||||
|
$OBJDUMP $OPTIONS baserom.gba > baserom.dump
|
||||||
|
$OBJDUMP $OPTIONS berry_fix.gba > berry_fix.dump
|
||||||
|
diff -c baserom.dump berry_fix.dump
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
make -C tools/gbagfx CXX=${1:-g++}
|
||||||
|
make -C tools/scaninc CXX=${1:-g++}
|
||||||
|
make -C tools/preproc CXX=${1:-g++}
|
||||||
|
make -C tools/bin2c CXX=${1:-g++}
|
||||||
|
make -C tools/rsfont CXX=${1:-g++}
|
||||||
|
make -C tools/aif2pcm CXX=${1:-g++}
|
||||||
|
make -C tools/ramscrgen CXX=${1:-g++}
|
||||||
|
make -C tools/gbafix CXX=${1:-g++}
|
||||||
|
make -C tools/mid2agb CXX=${1:-g++}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,490 @@
|
|||||||
|
.set PSR_USR_MODE, 0x00000010
|
||||||
|
.set PSR_FIQ_MODE, 0x00000011
|
||||||
|
.set PSR_IRQ_MODE, 0x00000012
|
||||||
|
.set PSR_SVC_MODE, 0x00000013
|
||||||
|
.set PSR_ABT_MODE, 0x00000017
|
||||||
|
.set PSR_UND_MODE, 0x0000001b
|
||||||
|
.set PSR_SYS_MODE, 0x0000001f
|
||||||
|
.set PSR_MODE_MASK, 0x0000001f
|
||||||
|
.set PSR_T_BIT, 0x00000020
|
||||||
|
.set PSR_F_BIT, 0x00000040
|
||||||
|
.set PSR_I_BIT, 0x00000080
|
||||||
|
|
||||||
|
.set EWRAM_START, 0x02000000
|
||||||
|
.set EWRAM_END, EWRAM_START + 0x40000
|
||||||
|
.set IWRAM_START, 0x03000000
|
||||||
|
.set IWRAM_END, IWRAM_START + 0x8000
|
||||||
|
|
||||||
|
.set PLTT, 0x5000000
|
||||||
|
.set BG_PLTT, PLTT
|
||||||
|
.set OBJ_PLTT, PLTT + 0x200
|
||||||
|
|
||||||
|
.set VRAM, 0x6000000
|
||||||
|
.set BG_VRAM, VRAM
|
||||||
|
.set OBJ_VRAM0, VRAM + 0x10000 @ text-mode BG
|
||||||
|
.set OBJ_VRAM1, VRAM + 0x14000 @ bitmap-mode BG
|
||||||
|
|
||||||
|
.set OAM, 0x7000000
|
||||||
|
|
||||||
|
.set SOUND_INFO_PTR, 0x3007FF0
|
||||||
|
.set INTR_CHECK, 0x3007FF8
|
||||||
|
.set INTR_VECTOR, 0x3007FFC
|
||||||
|
|
||||||
|
.set INTR_FLAG_VBLANK, 1 << 0
|
||||||
|
.set INTR_FLAG_HBLANK, 1 << 1
|
||||||
|
.set INTR_FLAG_VCOUNT, 1 << 2
|
||||||
|
.set INTR_FLAG_TIMER0, 1 << 3
|
||||||
|
.set INTR_FLAG_TIMER1, 1 << 4
|
||||||
|
.set INTR_FLAG_TIMER2, 1 << 5
|
||||||
|
.set INTR_FLAG_TIMER3, 1 << 6
|
||||||
|
.set INTR_FLAG_SERIAL, 1 << 7
|
||||||
|
.set INTR_FLAG_DMA0, 1 << 8
|
||||||
|
.set INTR_FLAG_DMA1, 1 << 9
|
||||||
|
.set INTR_FLAG_DMA2, 1 << 10
|
||||||
|
.set INTR_FLAG_DMA3, 1 << 11
|
||||||
|
.set INTR_FLAG_KEYPAD, 1 << 12
|
||||||
|
.set INTR_FLAG_GAMEPAK, 1 << 13
|
||||||
|
|
||||||
|
.set VCOUNT_VBLANK, 160
|
||||||
|
.set TOTAL_SCANLINES, 228
|
||||||
|
|
||||||
|
.set REG_BASE, 0x4000000 @ I/O register base address
|
||||||
|
|
||||||
|
@ I/O register offsets
|
||||||
|
.set OFFSET_REG_DISPCNT, 0x0
|
||||||
|
.set OFFSET_REG_DISPSTAT, 0x4
|
||||||
|
.set OFFSET_REG_VCOUNT, 0x6
|
||||||
|
.set OFFSET_REG_BG0CNT, 0x8
|
||||||
|
.set OFFSET_REG_BG1CNT, 0xa
|
||||||
|
.set OFFSET_REG_BG2CNT, 0xc
|
||||||
|
.set OFFSET_REG_BG3CNT, 0xe
|
||||||
|
.set OFFSET_REG_BG0HOFS, 0x10
|
||||||
|
.set OFFSET_REG_BG0VOFS, 0x12
|
||||||
|
.set OFFSET_REG_BG1HOFS, 0x14
|
||||||
|
.set OFFSET_REG_BG1VOFS, 0x16
|
||||||
|
.set OFFSET_REG_BG2HOFS, 0x18
|
||||||
|
.set OFFSET_REG_BG2VOFS, 0x1a
|
||||||
|
.set OFFSET_REG_BG3HOFS, 0x1c
|
||||||
|
.set OFFSET_REG_BG3VOFS, 0x1e
|
||||||
|
.set OFFSET_REG_BG2PA, 0x20
|
||||||
|
.set OFFSET_REG_BG2PB, 0x22
|
||||||
|
.set OFFSET_REG_BG2PC, 0x24
|
||||||
|
.set OFFSET_REG_BG2PD, 0x26
|
||||||
|
.set OFFSET_REG_BG2X_L, 0x28
|
||||||
|
.set OFFSET_REG_BG2X_H, 0x2a
|
||||||
|
.set OFFSET_REG_BG2Y_L, 0x2c
|
||||||
|
.set OFFSET_REG_BG2Y_H, 0x2e
|
||||||
|
.set OFFSET_REG_BG3PA, 0x30
|
||||||
|
.set OFFSET_REG_BG3PB, 0x32
|
||||||
|
.set OFFSET_REG_BG3PC, 0x34
|
||||||
|
.set OFFSET_REG_BG3PD, 0x36
|
||||||
|
.set OFFSET_REG_BG3X_L, 0x38
|
||||||
|
.set OFFSET_REG_BG3X_H, 0x3a
|
||||||
|
.set OFFSET_REG_BG3Y_L, 0x3c
|
||||||
|
.set OFFSET_REG_BG3Y_H, 0x3e
|
||||||
|
.set OFFSET_REG_WIN0H, 0x40
|
||||||
|
.set OFFSET_REG_WIN1H, 0x42
|
||||||
|
.set OFFSET_REG_WIN0V, 0x44
|
||||||
|
.set OFFSET_REG_WIN1V, 0x46
|
||||||
|
.set OFFSET_REG_WININ, 0x48
|
||||||
|
.set OFFSET_REG_WINOUT, 0x4a
|
||||||
|
.set OFFSET_REG_MOSAIC, 0x4c
|
||||||
|
.set OFFSET_REG_BLDCNT, 0x50
|
||||||
|
.set OFFSET_REG_BLDALPHA, 0x52
|
||||||
|
.set OFFSET_REG_BLDY, 0x54
|
||||||
|
|
||||||
|
.set OFFSET_REG_SOUND1CNT, 0x60
|
||||||
|
.set OFFSET_REG_SOUND1CNT_L, 0x60
|
||||||
|
.set OFFSET_REG_NR10, 0x60
|
||||||
|
.set OFFSET_REG_SOUND1CNT_H, 0x62
|
||||||
|
.set OFFSET_REG_NR11, 0x62
|
||||||
|
.set OFFSET_REG_NR12, 0x63
|
||||||
|
.set OFFSET_REG_SOUND1CNT_X, 0x64
|
||||||
|
.set OFFSET_REG_NR13, 0x64
|
||||||
|
.set OFFSET_REG_NR14, 0x65
|
||||||
|
.set OFFSET_REG_SOUND2CNT, 0x68
|
||||||
|
.set OFFSET_REG_SOUND2CNT_L, 0x68
|
||||||
|
.set OFFSET_REG_NR21, 0x68
|
||||||
|
.set OFFSET_REG_NR22, 0x69
|
||||||
|
.set OFFSET_REG_SOUND2CNT_H, 0x6c
|
||||||
|
.set OFFSET_REG_NR23, 0x6c
|
||||||
|
.set OFFSET_REG_NR24, 0x6d
|
||||||
|
.set OFFSET_REG_SOUND3CNT, 0x70
|
||||||
|
.set OFFSET_REG_SOUND3CNT_L, 0x70
|
||||||
|
.set OFFSET_REG_NR30, 0x70
|
||||||
|
.set OFFSET_REG_SOUND3CNT_H, 0x72
|
||||||
|
.set OFFSET_REG_NR31, 0x72
|
||||||
|
.set OFFSET_REG_NR32, 0x73
|
||||||
|
.set OFFSET_REG_SOUND3CNT_X, 0x74
|
||||||
|
.set OFFSET_REG_NR33, 0x74
|
||||||
|
.set OFFSET_REG_NR34, 0x75
|
||||||
|
.set OFFSET_REG_SOUND4CNT, 0x78
|
||||||
|
.set OFFSET_REG_SOUND4CNT_L, 0x78
|
||||||
|
.set OFFSET_REG_NR41, 0x78
|
||||||
|
.set OFFSET_REG_NR42, 0x79
|
||||||
|
.set OFFSET_REG_SOUND4CNT_H, 0x7c
|
||||||
|
.set OFFSET_REG_NR43, 0x7c
|
||||||
|
.set OFFSET_REG_NR44, 0x7d
|
||||||
|
.set OFFSET_REG_SOUNDCNT, 0x80
|
||||||
|
.set OFFSET_REG_SOUNDCNT_L, 0x80
|
||||||
|
.set OFFSET_REG_NR50, 0x80
|
||||||
|
.set OFFSET_REG_NR51, 0x81
|
||||||
|
.set OFFSET_REG_SOUNDCNT_H, 0x82
|
||||||
|
.set OFFSET_REG_SOUNDCNT_X, 0x84
|
||||||
|
.set OFFSET_REG_NR52, 0x84
|
||||||
|
.set OFFSET_REG_SOUNDBIAS, 0x88
|
||||||
|
.set OFFSET_REG_WAVE_RAM, 0x90
|
||||||
|
.set OFFSET_REG_WAVE_RAM0, 0x90
|
||||||
|
.set OFFSET_REG_WAVE_RAM0_L, 0x90
|
||||||
|
.set OFFSET_REG_WAVE_RAM0_H, 0x92
|
||||||
|
.set OFFSET_REG_WAVE_RAM1, 0x94
|
||||||
|
.set OFFSET_REG_WAVE_RAM1_L, 0x94
|
||||||
|
.set OFFSET_REG_WAVE_RAM1_H, 0x96
|
||||||
|
.set OFFSET_REG_WAVE_RAM2, 0x98
|
||||||
|
.set OFFSET_REG_WAVE_RAM2_L, 0x98
|
||||||
|
.set OFFSET_REG_WAVE_RAM2_H, 0x9a
|
||||||
|
.set OFFSET_REG_WAVE_RAM3, 0x9c
|
||||||
|
.set OFFSET_REG_WAVE_RAM3_L, 0x9c
|
||||||
|
.set OFFSET_REG_WAVE_RAM3_H, 0x9e
|
||||||
|
.set OFFSET_REG_FIFO, 0xa0
|
||||||
|
.set OFFSET_REG_FIFO_A, 0xa0
|
||||||
|
.set OFFSET_REG_FIFO_A_L, 0xa0
|
||||||
|
.set OFFSET_REG_FIFO_A_H, 0xa2
|
||||||
|
.set OFFSET_REG_FIFO_B, 0xa4
|
||||||
|
.set OFFSET_REG_FIFO_B_L, 0xa4
|
||||||
|
.set OFFSET_REG_FIFO_B_H, 0xa6
|
||||||
|
|
||||||
|
.set OFFSET_REG_DMA0, 0xb0
|
||||||
|
.set OFFSET_REG_DMA0SAD, 0xb0
|
||||||
|
.set OFFSET_REG_DMA0SAD_L, 0xb0
|
||||||
|
.set OFFSET_REG_DMA0SAD_H, 0xb2
|
||||||
|
.set OFFSET_REG_DMA0DAD, 0xb4
|
||||||
|
.set OFFSET_REG_DMA0DAD_L, 0xb4
|
||||||
|
.set OFFSET_REG_DMA0DAD_H, 0xb6
|
||||||
|
.set OFFSET_REG_DMA0CNT, 0xb8
|
||||||
|
.set OFFSET_REG_DMA0CNT_L, 0xb8
|
||||||
|
.set OFFSET_REG_DMA0CNT_H, 0xba
|
||||||
|
.set OFFSET_REG_DMA1, 0xbc
|
||||||
|
.set OFFSET_REG_DMA1SAD, 0xbc
|
||||||
|
.set OFFSET_REG_DMA1SAD_L, 0xbc
|
||||||
|
.set OFFSET_REG_DMA1SAD_H, 0xbe
|
||||||
|
.set OFFSET_REG_DMA1DAD, 0xc0
|
||||||
|
.set OFFSET_REG_DMA1DAD_L, 0xc0
|
||||||
|
.set OFFSET_REG_DMA1DAD_H, 0xc2
|
||||||
|
.set OFFSET_REG_DMA1CNT, 0xc4
|
||||||
|
.set OFFSET_REG_DMA1CNT_L, 0xc4
|
||||||
|
.set OFFSET_REG_DMA1CNT_H, 0xc6
|
||||||
|
.set OFFSET_REG_DMA2, 0xc8
|
||||||
|
.set OFFSET_REG_DMA2SAD, 0xc8
|
||||||
|
.set OFFSET_REG_DMA2SAD_L, 0xc8
|
||||||
|
.set OFFSET_REG_DMA2SAD_H, 0xca
|
||||||
|
.set OFFSET_REG_DMA2DAD, 0xcc
|
||||||
|
.set OFFSET_REG_DMA2DAD_L, 0xcc
|
||||||
|
.set OFFSET_REG_DMA2DAD_H, 0xce
|
||||||
|
.set OFFSET_REG_DMA2CNT, 0xd0
|
||||||
|
.set OFFSET_REG_DMA2CNT_L, 0xd0
|
||||||
|
.set OFFSET_REG_DMA2CNT_H, 0xd2
|
||||||
|
.set OFFSET_REG_DMA3, 0xd4
|
||||||
|
.set OFFSET_REG_DMA3SAD, 0xd4
|
||||||
|
.set OFFSET_REG_DMA3SAD_L, 0xd4
|
||||||
|
.set OFFSET_REG_DMA3SAD_H, 0xd6
|
||||||
|
.set OFFSET_REG_DMA3DAD, 0xd8
|
||||||
|
.set OFFSET_REG_DMA3DAD_L, 0xd8
|
||||||
|
.set OFFSET_REG_DMA3DAD_H, 0xda
|
||||||
|
.set OFFSET_REG_DMA3CNT, 0xdc
|
||||||
|
.set OFFSET_REG_DMA3CNT_L, 0xdc
|
||||||
|
.set OFFSET_REG_DMA3CNT_H, 0xde
|
||||||
|
|
||||||
|
.set OFFSET_REG_TM0CNT, 0x100
|
||||||
|
.set OFFSET_REG_TM0CNT_L, 0x100
|
||||||
|
.set OFFSET_REG_TM0CNT_H, 0x102
|
||||||
|
.set OFFSET_REG_TM1CNT, 0x104
|
||||||
|
.set OFFSET_REG_TM1CNT_L, 0x104
|
||||||
|
.set OFFSET_REG_TM1CNT_H, 0x106
|
||||||
|
.set OFFSET_REG_TM2CNT, 0x108
|
||||||
|
.set OFFSET_REG_TM2CNT_L, 0x108
|
||||||
|
.set OFFSET_REG_TM2CNT_H, 0x10a
|
||||||
|
.set OFFSET_REG_TM3CNT, 0x10c
|
||||||
|
.set OFFSET_REG_TM3CNT_L, 0x10c
|
||||||
|
.set OFFSET_REG_TM3CNT_H, 0x10e
|
||||||
|
|
||||||
|
.set OFFSET_REG_SIOCNT, 0x128
|
||||||
|
.set OFFSET_REG_SIODATA8, 0x12a
|
||||||
|
.set OFFSET_REG_SIODATA32, 0x120
|
||||||
|
.set OFFSET_REG_SIOMLT_SEND, 0x12a
|
||||||
|
.set OFFSET_REG_SIOMLT_RECV, 0x120
|
||||||
|
.set OFFSET_REG_SIOMULTI0, 0x120
|
||||||
|
.set OFFSET_REG_SIOMULTI1, 0x122
|
||||||
|
.set OFFSET_REG_SIOMULTI2, 0x124
|
||||||
|
.set OFFSET_REG_SIOMULTI3, 0x126
|
||||||
|
|
||||||
|
.set OFFSET_REG_KEYINPUT, 0x130
|
||||||
|
.set OFFSET_REG_KEYCNT, 0x132
|
||||||
|
|
||||||
|
.set OFFSET_REG_RCNT, 0x134
|
||||||
|
|
||||||
|
.set OFFSET_REG_JOYCNT, 0x140
|
||||||
|
.set OFFSET_REG_JOYSTAT, 0x158
|
||||||
|
.set OFFSET_REG_JOY_RECV, 0x150
|
||||||
|
.set OFFSET_REG_JOY_RECV_L, 0x150
|
||||||
|
.set OFFSET_REG_JOY_RECV_H, 0x152
|
||||||
|
.set OFFSET_REG_JOY_TRANS, 0x154
|
||||||
|
.set OFFSET_REG_JOY_TRANS_L, 0x154
|
||||||
|
.set OFFSET_REG_JOY_TRANS_H, 0x156
|
||||||
|
|
||||||
|
.set OFFSET_REG_IME, 0x208
|
||||||
|
.set OFFSET_REG_IE, 0x200
|
||||||
|
.set OFFSET_REG_IF, 0x202
|
||||||
|
|
||||||
|
.set OFFSET_REG_WAITCNT, 0x204
|
||||||
|
|
||||||
|
@ I/O register addresses
|
||||||
|
.set REG_DISPCNT, REG_BASE + OFFSET_REG_DISPCNT
|
||||||
|
.set REG_DISPSTAT, REG_BASE + OFFSET_REG_DISPSTAT
|
||||||
|
.set REG_VCOUNT, REG_BASE + OFFSET_REG_VCOUNT
|
||||||
|
.set REG_BG0CNT, REG_BASE + OFFSET_REG_BG0CNT
|
||||||
|
.set REG_BG1CNT, REG_BASE + OFFSET_REG_BG1CNT
|
||||||
|
.set REG_BG2CNT, REG_BASE + OFFSET_REG_BG2CNT
|
||||||
|
.set REG_BG3CNT, REG_BASE + OFFSET_REG_BG3CNT
|
||||||
|
.set REG_BG0HOFS, REG_BASE + OFFSET_REG_BG0HOFS
|
||||||
|
.set REG_BG0VOFS, REG_BASE + OFFSET_REG_BG0VOFS
|
||||||
|
.set REG_BG1HOFS, REG_BASE + OFFSET_REG_BG1HOFS
|
||||||
|
.set REG_BG1VOFS, REG_BASE + OFFSET_REG_BG1VOFS
|
||||||
|
.set REG_BG2HOFS, REG_BASE + OFFSET_REG_BG2HOFS
|
||||||
|
.set REG_BG2VOFS, REG_BASE + OFFSET_REG_BG2VOFS
|
||||||
|
.set REG_BG3HOFS, REG_BASE + OFFSET_REG_BG3HOFS
|
||||||
|
.set REG_BG3VOFS, REG_BASE + OFFSET_REG_BG3VOFS
|
||||||
|
.set REG_BG2PA, REG_BASE + OFFSET_REG_BG2PA
|
||||||
|
.set REG_BG2PB, REG_BASE + OFFSET_REG_BG2PB
|
||||||
|
.set REG_BG2PC, REG_BASE + OFFSET_REG_BG2PC
|
||||||
|
.set REG_BG2PD, REG_BASE + OFFSET_REG_BG2PD
|
||||||
|
.set REG_BG2X_L, REG_BASE + OFFSET_REG_BG2X_L
|
||||||
|
.set REG_BG2X_H, REG_BASE + OFFSET_REG_BG2X_H
|
||||||
|
.set REG_BG2Y_L, REG_BASE + OFFSET_REG_BG2Y_L
|
||||||
|
.set REG_BG2Y_H, REG_BASE + OFFSET_REG_BG2Y_H
|
||||||
|
.set REG_BG3PA, REG_BASE + OFFSET_REG_BG3PA
|
||||||
|
.set REG_BG3PB, REG_BASE + OFFSET_REG_BG3PB
|
||||||
|
.set REG_BG3PC, REG_BASE + OFFSET_REG_BG3PC
|
||||||
|
.set REG_BG3PD, REG_BASE + OFFSET_REG_BG3PD
|
||||||
|
.set REG_BG3X_L, REG_BASE + OFFSET_REG_BG3X_L
|
||||||
|
.set REG_BG3X_H, REG_BASE + OFFSET_REG_BG3X_H
|
||||||
|
.set REG_BG3Y_L, REG_BASE + OFFSET_REG_BG3Y_L
|
||||||
|
.set REG_BG3Y_H, REG_BASE + OFFSET_REG_BG3Y_H
|
||||||
|
.set REG_WIN0H, REG_BASE + OFFSET_REG_WIN0H
|
||||||
|
.set REG_WIN1H, REG_BASE + OFFSET_REG_WIN1H
|
||||||
|
.set REG_WIN0V, REG_BASE + OFFSET_REG_WIN0V
|
||||||
|
.set REG_WIN1V, REG_BASE + OFFSET_REG_WIN1V
|
||||||
|
.set REG_WININ, REG_BASE + OFFSET_REG_WININ
|
||||||
|
.set REG_WINOUT, REG_BASE + OFFSET_REG_WINOUT
|
||||||
|
.set REG_MOSAIC, REG_BASE + OFFSET_REG_MOSAIC
|
||||||
|
.set REG_BLDCNT, REG_BASE + OFFSET_REG_BLDCNT
|
||||||
|
.set REG_BLDALPHA, REG_BASE + OFFSET_REG_BLDALPHA
|
||||||
|
.set REG_BLDY, REG_BASE + OFFSET_REG_BLDY
|
||||||
|
|
||||||
|
.set REG_SOUND1CNT, REG_BASE + OFFSET_REG_SOUND1CNT
|
||||||
|
.set REG_SOUND1CNT_L, REG_BASE + OFFSET_REG_SOUND1CNT_L
|
||||||
|
.set REG_NR10, REG_BASE + OFFSET_REG_NR10
|
||||||
|
.set REG_SOUND1CNT_H, REG_BASE + OFFSET_REG_SOUND1CNT_H
|
||||||
|
.set REG_NR11, REG_BASE + OFFSET_REG_NR11
|
||||||
|
.set REG_NR12, REG_BASE + OFFSET_REG_NR12
|
||||||
|
.set REG_SOUND1CNT_X, REG_BASE + OFFSET_REG_SOUND1CNT_X
|
||||||
|
.set REG_NR13, REG_BASE + OFFSET_REG_NR13
|
||||||
|
.set REG_NR14, REG_BASE + OFFSET_REG_NR14
|
||||||
|
.set REG_SOUND2CNT, REG_BASE + OFFSET_REG_SOUND2CNT
|
||||||
|
.set REG_SOUND2CNT_L, REG_BASE + OFFSET_REG_SOUND2CNT_L
|
||||||
|
.set REG_NR21, REG_BASE + OFFSET_REG_NR21
|
||||||
|
.set REG_NR22, REG_BASE + OFFSET_REG_NR22
|
||||||
|
.set REG_SOUND2CNT_H, REG_BASE + OFFSET_REG_SOUND2CNT_H
|
||||||
|
.set REG_NR23, REG_BASE + OFFSET_REG_NR23
|
||||||
|
.set REG_NR24, REG_BASE + OFFSET_REG_NR24
|
||||||
|
.set REG_SOUND3CNT, REG_BASE + OFFSET_REG_SOUND3CNT
|
||||||
|
.set REG_SOUND3CNT_L, REG_BASE + OFFSET_REG_SOUND3CNT_L
|
||||||
|
.set REG_NR30, REG_BASE + OFFSET_REG_NR30
|
||||||
|
.set REG_SOUND3CNT_H, REG_BASE + OFFSET_REG_SOUND3CNT_H
|
||||||
|
.set REG_NR31, REG_BASE + OFFSET_REG_NR31
|
||||||
|
.set REG_NR32, REG_BASE + OFFSET_REG_NR32
|
||||||
|
.set REG_SOUND3CNT_X, REG_BASE + OFFSET_REG_SOUND3CNT_X
|
||||||
|
.set REG_NR33, REG_BASE + OFFSET_REG_NR33
|
||||||
|
.set REG_NR34, REG_BASE + OFFSET_REG_NR34
|
||||||
|
.set REG_SOUND4CNT, REG_BASE + OFFSET_REG_SOUND4CNT
|
||||||
|
.set REG_SOUND4CNT_L, REG_BASE + OFFSET_REG_SOUND4CNT_L
|
||||||
|
.set REG_NR41, REG_BASE + OFFSET_REG_NR41
|
||||||
|
.set REG_NR42, REG_BASE + OFFSET_REG_NR42
|
||||||
|
.set REG_SOUND4CNT_H, REG_BASE + OFFSET_REG_SOUND4CNT_H
|
||||||
|
.set REG_NR43, REG_BASE + OFFSET_REG_NR43
|
||||||
|
.set REG_NR44, REG_BASE + OFFSET_REG_NR44
|
||||||
|
.set REG_SOUNDCNT, REG_BASE + OFFSET_REG_SOUNDCNT
|
||||||
|
.set REG_SOUNDCNT_L, REG_BASE + OFFSET_REG_SOUNDCNT_L
|
||||||
|
.set REG_NR50, REG_BASE + OFFSET_REG_NR50
|
||||||
|
.set REG_NR51, REG_BASE + OFFSET_REG_NR51
|
||||||
|
.set REG_SOUNDCNT_H, REG_BASE + OFFSET_REG_SOUNDCNT_H
|
||||||
|
.set REG_SOUNDCNT_X, REG_BASE + OFFSET_REG_SOUNDCNT_X
|
||||||
|
.set REG_NR52, REG_BASE + OFFSET_REG_NR52
|
||||||
|
.set REG_SOUNDBIAS, REG_BASE + OFFSET_REG_SOUNDBIAS
|
||||||
|
.set REG_WAVE_RAM, REG_BASE + OFFSET_REG_WAVE_RAM
|
||||||
|
.set REG_WAVE_RAM0, REG_BASE + OFFSET_REG_WAVE_RAM0
|
||||||
|
.set REG_WAVE_RAM0_L, REG_BASE + OFFSET_REG_WAVE_RAM0_L
|
||||||
|
.set REG_WAVE_RAM0_H, REG_BASE + OFFSET_REG_WAVE_RAM0_H
|
||||||
|
.set REG_WAVE_RAM1, REG_BASE + OFFSET_REG_WAVE_RAM1
|
||||||
|
.set REG_WAVE_RAM1_L, REG_BASE + OFFSET_REG_WAVE_RAM1_L
|
||||||
|
.set REG_WAVE_RAM1_H, REG_BASE + OFFSET_REG_WAVE_RAM1_H
|
||||||
|
.set REG_WAVE_RAM2, REG_BASE + OFFSET_REG_WAVE_RAM2
|
||||||
|
.set REG_WAVE_RAM2_L, REG_BASE + OFFSET_REG_WAVE_RAM2_L
|
||||||
|
.set REG_WAVE_RAM2_H, REG_BASE + OFFSET_REG_WAVE_RAM2_H
|
||||||
|
.set REG_WAVE_RAM3, REG_BASE + OFFSET_REG_WAVE_RAM3
|
||||||
|
.set REG_WAVE_RAM3_L, REG_BASE + OFFSET_REG_WAVE_RAM3_L
|
||||||
|
.set REG_WAVE_RAM3_H, REG_BASE + OFFSET_REG_WAVE_RAM3_H
|
||||||
|
.set REG_FIFO, REG_BASE + OFFSET_REG_FIFO
|
||||||
|
.set REG_FIFO_A, REG_BASE + OFFSET_REG_FIFO_A
|
||||||
|
.set REG_FIFO_A_L, REG_BASE + OFFSET_REG_FIFO_A_L
|
||||||
|
.set REG_FIFO_A_H, REG_BASE + OFFSET_REG_FIFO_A_H
|
||||||
|
.set REG_FIFO_B, REG_BASE + OFFSET_REG_FIFO_B
|
||||||
|
.set REG_FIFO_B_L, REG_BASE + OFFSET_REG_FIFO_B_L
|
||||||
|
.set REG_FIFO_B_H, REG_BASE + OFFSET_REG_FIFO_B_H
|
||||||
|
|
||||||
|
.set REG_DMA0, REG_BASE + OFFSET_REG_DMA0
|
||||||
|
.set REG_DMA0SAD, REG_BASE + OFFSET_REG_DMA0SAD
|
||||||
|
.set REG_DMA0SAD_L, REG_BASE + OFFSET_REG_DMA0SAD_L
|
||||||
|
.set REG_DMA0SAD_H, REG_BASE + OFFSET_REG_DMA0SAD_H
|
||||||
|
.set REG_DMA0DAD, REG_BASE + OFFSET_REG_DMA0DAD
|
||||||
|
.set REG_DMA0DAD_L, REG_BASE + OFFSET_REG_DMA0DAD_L
|
||||||
|
.set REG_DMA0DAD_H, REG_BASE + OFFSET_REG_DMA0DAD_H
|
||||||
|
.set REG_DMA0CNT, REG_BASE + OFFSET_REG_DMA0CNT
|
||||||
|
.set REG_DMA0CNT_L, REG_BASE + OFFSET_REG_DMA0CNT_L
|
||||||
|
.set REG_DMA0CNT_H, REG_BASE + OFFSET_REG_DMA0CNT_H
|
||||||
|
.set REG_DMA1, REG_BASE + OFFSET_REG_DMA1
|
||||||
|
.set REG_DMA1SAD, REG_BASE + OFFSET_REG_DMA1SAD
|
||||||
|
.set REG_DMA1SAD_L, REG_BASE + OFFSET_REG_DMA1SAD_L
|
||||||
|
.set REG_DMA1SAD_H, REG_BASE + OFFSET_REG_DMA1SAD_H
|
||||||
|
.set REG_DMA1DAD, REG_BASE + OFFSET_REG_DMA1DAD
|
||||||
|
.set REG_DMA1DAD_L, REG_BASE + OFFSET_REG_DMA1DAD_L
|
||||||
|
.set REG_DMA1DAD_H, REG_BASE + OFFSET_REG_DMA1DAD_H
|
||||||
|
.set REG_DMA1CNT, REG_BASE + OFFSET_REG_DMA1CNT
|
||||||
|
.set REG_DMA1CNT_L, REG_BASE + OFFSET_REG_DMA1CNT_L
|
||||||
|
.set REG_DMA1CNT_H, REG_BASE + OFFSET_REG_DMA1CNT_H
|
||||||
|
.set REG_DMA2, REG_BASE + OFFSET_REG_DMA2
|
||||||
|
.set REG_DMA2SAD, REG_BASE + OFFSET_REG_DMA2SAD
|
||||||
|
.set REG_DMA2SAD_L, REG_BASE + OFFSET_REG_DMA2SAD_L
|
||||||
|
.set REG_DMA2SAD_H, REG_BASE + OFFSET_REG_DMA2SAD_H
|
||||||
|
.set REG_DMA2DAD, REG_BASE + OFFSET_REG_DMA2DAD
|
||||||
|
.set REG_DMA2DAD_L, REG_BASE + OFFSET_REG_DMA2DAD_L
|
||||||
|
.set REG_DMA2DAD_H, REG_BASE + OFFSET_REG_DMA2DAD_H
|
||||||
|
.set REG_DMA2CNT, REG_BASE + OFFSET_REG_DMA2CNT
|
||||||
|
.set REG_DMA2CNT_L, REG_BASE + OFFSET_REG_DMA2CNT_L
|
||||||
|
.set REG_DMA2CNT_H, REG_BASE + OFFSET_REG_DMA2CNT_H
|
||||||
|
.set REG_DMA3, REG_BASE + OFFSET_REG_DMA3
|
||||||
|
.set REG_DMA3SAD, REG_BASE + OFFSET_REG_DMA3SAD
|
||||||
|
.set REG_DMA3SAD_L, REG_BASE + OFFSET_REG_DMA3SAD_L
|
||||||
|
.set REG_DMA3SAD_H, REG_BASE + OFFSET_REG_DMA3SAD_H
|
||||||
|
.set REG_DMA3DAD, REG_BASE + OFFSET_REG_DMA3DAD
|
||||||
|
.set REG_DMA3DAD_L, REG_BASE + OFFSET_REG_DMA3DAD_L
|
||||||
|
.set REG_DMA3DAD_H, REG_BASE + OFFSET_REG_DMA3DAD_H
|
||||||
|
.set REG_DMA3CNT, REG_BASE + OFFSET_REG_DMA3CNT
|
||||||
|
.set REG_DMA3CNT_L, REG_BASE + OFFSET_REG_DMA3CNT_L
|
||||||
|
.set REG_DMA3CNT_H, REG_BASE + OFFSET_REG_DMA3CNT_H
|
||||||
|
|
||||||
|
.set REG_TM0CNT, REG_BASE + OFFSET_REG_TM0CNT
|
||||||
|
.set REG_TM0CNT_L, REG_BASE + OFFSET_REG_TM0CNT_L
|
||||||
|
.set REG_TM0CNT_H, REG_BASE + OFFSET_REG_TM0CNT_H
|
||||||
|
.set REG_TM1CNT, REG_BASE + OFFSET_REG_TM1CNT
|
||||||
|
.set REG_TM1CNT_L, REG_BASE + OFFSET_REG_TM1CNT_L
|
||||||
|
.set REG_TM1CNT_H, REG_BASE + OFFSET_REG_TM1CNT_H
|
||||||
|
.set REG_TM2CNT, REG_BASE + OFFSET_REG_TM2CNT
|
||||||
|
.set REG_TM2CNT_L, REG_BASE + OFFSET_REG_TM2CNT_L
|
||||||
|
.set REG_TM2CNT_H, REG_BASE + OFFSET_REG_TM2CNT_H
|
||||||
|
.set REG_TM3CNT, REG_BASE + OFFSET_REG_TM3CNT
|
||||||
|
.set REG_TM3CNT_L, REG_BASE + OFFSET_REG_TM3CNT_L
|
||||||
|
.set REG_TM3CNT_H, REG_BASE + OFFSET_REG_TM3CNT_H
|
||||||
|
|
||||||
|
.set REG_SIOCNT, REG_BASE + OFFSET_REG_SIOCNT
|
||||||
|
.set REG_SIODATA8, REG_BASE + OFFSET_REG_SIODATA8
|
||||||
|
.set REG_SIODATA32, REG_BASE + OFFSET_REG_SIODATA32
|
||||||
|
.set REG_SIOMLT_SEND, REG_BASE + OFFSET_REG_SIOMLT_SEND
|
||||||
|
.set REG_SIOMLT_RECV, REG_BASE + OFFSET_REG_SIOMLT_RECV
|
||||||
|
.set REG_SIOMULTI0, REG_BASE + OFFSET_REG_SIOMULTI0
|
||||||
|
.set REG_SIOMULTI1, REG_BASE + OFFSET_REG_SIOMULTI1
|
||||||
|
.set REG_SIOMULTI2, REG_BASE + OFFSET_REG_SIOMULTI2
|
||||||
|
.set REG_SIOMULTI3, REG_BASE + OFFSET_REG_SIOMULTI3
|
||||||
|
|
||||||
|
.set REG_KEYINPUT, REG_BASE + OFFSET_REG_KEYINPUT
|
||||||
|
.set REG_KEYCNT, REG_BASE + OFFSET_REG_KEYCNT
|
||||||
|
|
||||||
|
.set REG_RCNT, REG_BASE + OFFSET_REG_RCNT
|
||||||
|
|
||||||
|
.set REG_JOYCNT, REG_BASE + OFFSET_REG_JOYCNT
|
||||||
|
.set REG_JOYSTAT, REG_BASE + OFFSET_REG_JOYSTAT
|
||||||
|
.set REG_JOY_RECV, REG_BASE + OFFSET_REG_JOY_RECV
|
||||||
|
.set REG_JOY_RECV_L, REG_BASE + OFFSET_REG_JOY_RECV_L
|
||||||
|
.set REG_JOY_RECV_H, REG_BASE + OFFSET_REG_JOY_RECV_H
|
||||||
|
.set REG_JOY_TRANS, REG_BASE + OFFSET_REG_JOY_TRANS
|
||||||
|
.set REG_JOY_TRANS_L, REG_BASE + OFFSET_REG_JOY_TRANS_L
|
||||||
|
.set REG_JOY_TRANS_H, REG_BASE + OFFSET_REG_JOY_TRANS_H
|
||||||
|
|
||||||
|
.set REG_IME, REG_BASE + OFFSET_REG_IME
|
||||||
|
.set REG_IE, REG_BASE + OFFSET_REG_IE
|
||||||
|
.set REG_IF, REG_BASE + OFFSET_REG_IF
|
||||||
|
|
||||||
|
.set REG_WAITCNT, REG_BASE + OFFSET_REG_WAITCNT
|
||||||
|
|
||||||
|
@ DMA register constants
|
||||||
|
|
||||||
|
.set DMA_DEST_INC, 0x0000
|
||||||
|
.set DMA_DEST_DEC, 0x0020
|
||||||
|
.set DMA_DEST_FIXED, 0x0040
|
||||||
|
.set DMA_DEST_RELOAD, 0x0060
|
||||||
|
.set DMA_SRC_INC, 0x0000
|
||||||
|
.set DMA_SRC_DEC, 0x0080
|
||||||
|
.set DMA_SRC_FIXED, 0x0100
|
||||||
|
.set DMA_REPEAT, 0x0200
|
||||||
|
.set DMA_16BIT, 0x0000
|
||||||
|
.set DMA_32BIT, 0x0400
|
||||||
|
.set DMA_DREQ_ON, 0x0800
|
||||||
|
.set DMA_START_NOW, 0x0000
|
||||||
|
.set DMA_START_VBLANK, 0x1000
|
||||||
|
.set DMA_START_HBLANK, 0x2000
|
||||||
|
.set DMA_START_SPECIAL, 0x3000
|
||||||
|
.set DMA_INTR_ENABLE, 0x4000
|
||||||
|
.set DMA_ENABLE, 0x8000
|
||||||
|
|
||||||
|
@ OAM attribute constants
|
||||||
|
|
||||||
|
.set OAM_OBJ_NORMAL, 0x00000000
|
||||||
|
.set OAM_OBJ_BLEND, 0x00000400
|
||||||
|
.set OAM_OBJ_WINDOW, 0x00000800
|
||||||
|
|
||||||
|
.set OAM_AFFINE_NONE, 0x00000000
|
||||||
|
.set OAM_AFFINE_NORMAL_SIZE, 0x00000100
|
||||||
|
.set OAM_OBJ_DISABLED, 0x00000200
|
||||||
|
.set OAM_AFFINE_DOUBLE_SIZE, 0x00000300
|
||||||
|
|
||||||
|
.set OAM_MOSAIC_OFF, 0x00000000
|
||||||
|
.set OAM_MOSAIC_ON, 0x00001000
|
||||||
|
|
||||||
|
.set OAM_4BPP, 0x00000000
|
||||||
|
.set OAM_8BPP, 0x00002000
|
||||||
|
|
||||||
|
.set OAM_H_FLIP, 0x10000000
|
||||||
|
.set OAM_V_FLIP, 0x20000000
|
||||||
|
|
||||||
|
.set OAM_SQUARE, 0x00000000
|
||||||
|
.set OAM_H_RECTANGLE, 0x00004000
|
||||||
|
.set OAM_V_RECTANGLE, 0x00008000
|
||||||
|
.set OAM_SIZE_0, 0x00000000
|
||||||
|
.set OAM_SIZE_1, 0x40000000
|
||||||
|
.set OAM_SIZE_2, 0x80000000
|
||||||
|
.set OAM_SIZE_3, 0xc0000000
|
||||||
|
|
||||||
|
.set OAM_SIZE_8x8, OAM_SIZE_0 | OAM_SQUARE
|
||||||
|
.set OAM_SIZE_16x16, OAM_SIZE_1 | OAM_SQUARE
|
||||||
|
.set OAM_SIZE_32x32, OAM_SIZE_2 | OAM_SQUARE
|
||||||
|
.set OAM_SIZE_64x64, OAM_SIZE_3 | OAM_SQUARE
|
||||||
|
|
||||||
|
.set OAM_SIZE_16x8, OAM_SIZE_0 | OAM_H_RECTANGLE
|
||||||
|
.set OAM_SIZE_32x8, OAM_SIZE_1 | OAM_H_RECTANGLE
|
||||||
|
.set OAM_SIZE_32x16, OAM_SIZE_2 | OAM_H_RECTANGLE
|
||||||
|
.set OAM_SIZE_64x32, OAM_SIZE_3 | OAM_H_RECTANGLE
|
||||||
|
|
||||||
|
.set OAM_SIZE_8x16, OAM_SIZE_0 | OAM_V_RECTANGLE
|
||||||
|
.set OAM_SIZE_8x32, OAM_SIZE_1 | OAM_V_RECTANGLE
|
||||||
|
.set OAM_SIZE_16x32, OAM_SIZE_2 | OAM_V_RECTANGLE
|
||||||
|
.set OAM_SIZE_32x64, OAM_SIZE_3 | OAM_V_RECTANGLE
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
.section .rodata
|
||||||
|
|
||||||
|
_data_2f0::
|
||||||
|
.incbin "data/payload.gba.lz"
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/<EWRAM>/ {
|
||||||
|
r sym_ewram.ld
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
/<BSS>/ {
|
||||||
|
r sym_bss.ld
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
/<COMMON>/ {
|
||||||
|
r sym_common.ld
|
||||||
|
d
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = 0x2000000;
|
||||||
|
|
||||||
|
.text :
|
||||||
|
ALIGN(4)
|
||||||
|
{
|
||||||
|
asm/loader.o(.text);
|
||||||
|
} =0
|
||||||
|
|
||||||
|
. += 0x100;
|
||||||
|
.rodata :
|
||||||
|
ALIGN(4)
|
||||||
|
{
|
||||||
|
data/data.o(.rodata);
|
||||||
|
} =0
|
||||||
|
|
||||||
|
. = 0x2010000;
|
||||||
|
|
||||||
|
ewram (NOLOAD) :
|
||||||
|
ALIGN(4)
|
||||||
|
{
|
||||||
|
gCode = .;
|
||||||
|
}
|
||||||
|
|
||||||
|
/DISCARD/ :
|
||||||
|
{
|
||||||
|
*(*);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
include $(DEVKITARM)/base_tools
|
||||||
|
export CPP := $(PREFIX)cpp
|
||||||
|
export LD := $(PREFIX)ld
|
||||||
|
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
EXE := .exe
|
||||||
|
else
|
||||||
|
EXE :=
|
||||||
|
endif
|
||||||
|
|
||||||
|
SHELL := /bin/bash -o pipefail
|
||||||
|
|
||||||
|
CPPFLAGS := -I ../../tools/agbcc/include -I ../../tools/agbcc -iquote include -nostdinc -undef
|
||||||
|
|
||||||
|
ROM := payload.gba
|
||||||
|
OBJ_DIR := build
|
||||||
|
CC1 := ../../tools/agbcc/bin/agbcc$(EXE)
|
||||||
|
override CFLAGS += -mthumb-interwork -Wimplicit -Wparentheses -Werror -O2 -fhex-asm
|
||||||
|
|
||||||
|
|
||||||
|
ELF = $(ROM:.gba=.elf)
|
||||||
|
MAP = $(ROM:.gba=.map)
|
||||||
|
|
||||||
|
C_SUBDIR = src
|
||||||
|
ASM_SUBDIR = asm
|
||||||
|
DATA_ASM_SUBDIR = data
|
||||||
|
|
||||||
|
C_BUILDDIR = $(OBJ_DIR)/$(C_SUBDIR)
|
||||||
|
ASM_BUILDDIR = $(OBJ_DIR)/$(ASM_SUBDIR)
|
||||||
|
DATA_ASM_BUILDDIR = $(OBJ_DIR)/$(DATA_ASM_SUBDIR)
|
||||||
|
|
||||||
|
ASFLAGS := -mcpu=arm7tdmi
|
||||||
|
|
||||||
|
LDFLAGS = -Map ../$(MAP)
|
||||||
|
|
||||||
|
LIB := -L ../../../tools/agbcc/lib -lagb_flash -lsiirtc -lagbsyscall -lgcc
|
||||||
|
|
||||||
|
SHA1 := $(shell { command -v sha1sum || command -v shasum; } 2>/dev/null) -c
|
||||||
|
GFX := ../../tools/gbagfx/gbagfx$(EXE)
|
||||||
|
AIF := ../../tools/aif2pcm/aif2pcm$(EXE)
|
||||||
|
MID := ../../tools/mid2agb/mid2agb$(EXE)
|
||||||
|
SCANINC := ../../tools/scaninc/scaninc$(EXE)
|
||||||
|
PREPROC := ../../tools/preproc/preproc$(EXE)
|
||||||
|
RAMSCRGEN := ../../tools/ramscrgen/ramscrgen$(EXE)
|
||||||
|
FIX := ../../tools/gbafix/gbafix$(EXE)
|
||||||
|
|
||||||
|
# Clear the default suffixes
|
||||||
|
.SUFFIXES:
|
||||||
|
# Don't delete intermediate files
|
||||||
|
.SECONDARY:
|
||||||
|
# Delete files that weren't built properly
|
||||||
|
.DELETE_ON_ERROR:
|
||||||
|
|
||||||
|
# Secondary expansion is required for dependency variables in object rules.
|
||||||
|
.SECONDEXPANSION:
|
||||||
|
|
||||||
|
.PHONY: rom clean compare tidy
|
||||||
|
|
||||||
|
C_SRCS := $(wildcard $(C_SUBDIR)/*.c $(C_SUBDIR)/*/*.c $(C_SUBDIR)/*/*/*.c)
|
||||||
|
C_OBJS := $(patsubst $(C_SUBDIR)/%.c,$(C_BUILDDIR)/%.o,$(C_SRCS))
|
||||||
|
|
||||||
|
ASM_SRCS := $(wildcard $(ASM_SUBDIR)/*.s)
|
||||||
|
ASM_OBJS := $(patsubst $(ASM_SUBDIR)/%.s,$(ASM_BUILDDIR)/%.o,$(ASM_SRCS))
|
||||||
|
|
||||||
|
DATA_ASM_SRCS := $(wildcard $(DATA_ASM_SUBDIR)/*.s)
|
||||||
|
DATA_ASM_OBJS := $(patsubst $(DATA_ASM_SUBDIR)/%.s,$(DATA_ASM_BUILDDIR)/%.o,$(DATA_ASM_SRCS))
|
||||||
|
|
||||||
|
SONG_SRCS := $(wildcard $(SONG_SUBDIR)/*.s)
|
||||||
|
SONG_OBJS := $(patsubst $(SONG_SUBDIR)/%.s,$(SONG_BUILDDIR)/%.o,$(SONG_SRCS))
|
||||||
|
|
||||||
|
MID_SRCS := $(wildcard $(MID_SUBDIR)/*.mid)
|
||||||
|
MID_OBJS := $(patsubst $(MID_SUBDIR)/%.mid,$(MID_BUILDDIR)/%.o,$(MID_SRCS))
|
||||||
|
|
||||||
|
OBJS := $(C_OBJS) $(ASM_OBJS) $(DATA_ASM_OBJS) $(SONG_OBJS) $(MID_OBJS)
|
||||||
|
# OBJS_REL := $(patsubst $(OBJ_DIR)/%,%,$(OBJS))
|
||||||
|
|
||||||
|
SUBDIRS := $(sort $(dir $(OBJS)))
|
||||||
|
|
||||||
|
$(shell mkdir -p $(SUBDIRS))
|
||||||
|
|
||||||
|
rom: $(ROM)
|
||||||
|
|
||||||
|
# For contributors to make sure a change didn't affect the contents of the ROM.
|
||||||
|
compare: $(ROM)
|
||||||
|
@$(SHA1) rom.sha1
|
||||||
|
|
||||||
|
clean: tidy
|
||||||
|
rm -f sound/direct_sound_samples/*.bin
|
||||||
|
rm -f $(SONG_OBJS) $(MID_OBJS) $(MID_SUBDIR)/*.s
|
||||||
|
find . \( -iname '*.1bpp' -o -iname '*.4bpp' -o -iname '*.8bpp' -o -iname '*.gbapal' -o -iname '*.lz' -o -iname '*.latfont' -o -iname '*.hwjpnfont' -o -iname '*.fwjpnfont' \) -exec rm {} +
|
||||||
|
|
||||||
|
tidy:
|
||||||
|
rm -f $(ROM) $(ELF) $(MAP)
|
||||||
|
rm -r build/*
|
||||||
|
|
||||||
|
%.s: ;
|
||||||
|
%.png: ;
|
||||||
|
%.pal: ;
|
||||||
|
%.aif: ;
|
||||||
|
|
||||||
|
%.1bpp: %.png ; $(GFX) $< $@
|
||||||
|
%.4bpp: %.png ; $(GFX) $< $@
|
||||||
|
%.8bpp: %.png ; $(GFX) $< $@
|
||||||
|
%.gbapal: %.pal ; $(GFX) $< $@
|
||||||
|
%.gbapal: %.png ; $(GFX) $< $@
|
||||||
|
%.lz: % ; $(GFX) $< $@
|
||||||
|
%.rl: % ; $(GFX) $< $@
|
||||||
|
|
||||||
|
|
||||||
|
ifeq ($(NODEP),1)
|
||||||
|
$(C_BUILDDIR)/%.o: c_dep :=
|
||||||
|
else
|
||||||
|
$(C_BUILDDIR)/%.o: c_dep = $(shell $(SCANINC) -I include $(C_SUBDIR)/$*.c)
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(C_BUILDDIR)/%.o : $(C_SUBDIR)/%.c $$(c_dep)
|
||||||
|
@$(CPP) $(CPPFLAGS) $< -o $(C_BUILDDIR)/$*.i
|
||||||
|
@$(PREPROC) $(C_BUILDDIR)/$*.i charmap.txt | $(CC1) $(CFLAGS) -o $(C_BUILDDIR)/$*.s
|
||||||
|
$(AS) $(ASFLAGS) -o $@ $(C_BUILDDIR)/$*.s
|
||||||
|
|
||||||
|
ifeq ($(NODEP),1)
|
||||||
|
$(ASM_BUILDDIR)/%.o: asm_dep :=
|
||||||
|
else
|
||||||
|
$(ASM_BUILDDIR)/%.o: asm_dep = $(shell $(SCANINC) $(ASM_SUBDIR)/$*.s)
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(ASM_BUILDDIR)/%.o: $(ASM_SUBDIR)/%.s $$(asm_dep)
|
||||||
|
$(AS) $(ASFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
ifeq ($(NODEP),1)
|
||||||
|
$(DATA_ASM_BUILDDIR)/%.o: data_dep :=
|
||||||
|
else
|
||||||
|
$(DATA_ASM_BUILDDIR)/%.o: data_dep = $(shell $(SCANINC) $(DATA_ASM_SUBDIR)/$*.s)
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(DATA_ASM_BUILDDIR)/%.o: $(DATA_ASM_SUBDIR)/%.s $$(data_dep)
|
||||||
|
$(PREPROC) $< charmap.txt | $(CPP) -I include | $(AS) $(ASFLAGS) -o $@
|
||||||
|
|
||||||
|
$(SONG_BUILDDIR)/%.o: $(SONG_SUBDIR)/%.s
|
||||||
|
$(AS) $(ASFLAGS) -I sound -o $@ $<
|
||||||
|
|
||||||
|
$(OBJ_DIR)/sym_bss.ld: sym_bss.txt
|
||||||
|
$(RAMSCRGEN) .bss $< ENGLISH > $@
|
||||||
|
|
||||||
|
$(OBJ_DIR)/sym_common.ld: sym_common.txt $(C_OBJS) $(wildcard common_syms/*.txt)
|
||||||
|
$(RAMSCRGEN) COMMON $< ENGLISH -c $(C_BUILDDIR),common_syms,../../tools/agbcc/lib > $@
|
||||||
|
|
||||||
|
$(OBJ_DIR)/sym_ewram.ld: sym_ewram.txt
|
||||||
|
$(RAMSCRGEN) ewram_data $< ENGLISH > $@
|
||||||
|
|
||||||
|
$(OBJ_DIR)/ld_script.ld: ld_script.txt $(OBJ_DIR)/sym_bss.ld $(OBJ_DIR)/sym_common.ld $(OBJ_DIR)/sym_ewram.ld
|
||||||
|
cd $(OBJ_DIR) && sed -f ../../ld_script.sed ../$< | sed "s#tools/#../tools/#g" > ld_script.ld
|
||||||
|
|
||||||
|
$(ELF): $(OBJ_DIR)/ld_script.ld $(OBJS)
|
||||||
|
cd $(OBJ_DIR) && $(LD) $(LDFLAGS) -T ld_script.ld -o ../$@ $(LIB)
|
||||||
|
|
||||||
|
$(ROM): $(ELF)
|
||||||
|
$(OBJCOPY) -O binary $< $@
|
||||||
|
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
.include "asm/macros/asm.inc"
|
||||||
|
.include "asm/macros/function.inc"
|
||||||
|
.include "constants/gba_constants.inc"
|
||||||
|
|
||||||
|
.syntax unified
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
.arm
|
||||||
|
.align 2, 0
|
||||||
|
.global Init
|
||||||
|
Init:
|
||||||
|
mov r0, PSR_IRQ_MODE
|
||||||
|
msr cpsr_cf, r0
|
||||||
|
ldr sp, sp_irq
|
||||||
|
mov r0, PSR_SYS_MODE
|
||||||
|
msr cpsr_cf, r0
|
||||||
|
ldr sp, sp_sys
|
||||||
|
ldr r1, =INTR_VECTOR
|
||||||
|
ldr r0, =IntrMain
|
||||||
|
str r0, [r1]
|
||||||
|
ldr r1, =AgbMain + 1
|
||||||
|
mov lr, pc
|
||||||
|
bx r1
|
||||||
|
b Init
|
||||||
|
|
||||||
|
.align 2, 0
|
||||||
|
sp_sys: .word IWRAM_END - 0x100
|
||||||
|
sp_irq: .word IWRAM_END - 0x60
|
||||||
|
|
||||||
|
.pool
|
||||||
|
.size Init, .-Init
|
||||||
|
|
||||||
|
.arm
|
||||||
|
.align 2, 0
|
||||||
|
.global IntrMain
|
||||||
|
IntrMain: @ 0x2010048
|
||||||
|
mov ip, REG_BASE
|
||||||
|
add r3, ip, OFFSET_REG_IE
|
||||||
|
ldr r2, [r3]
|
||||||
|
and r1, r2, r2, lsr #16
|
||||||
|
mov r2, #0
|
||||||
|
ands r0, r1, #0x2000
|
||||||
|
strbne r0, [r3, #-0x17c]
|
||||||
|
_02010064:
|
||||||
|
bne _02010064
|
||||||
|
ands r0, r1, #0xc0
|
||||||
|
bne _020100DC
|
||||||
|
add r2, r2, #4
|
||||||
|
ands r0, r1, #1
|
||||||
|
strhne r0, [ip, #-8]
|
||||||
|
bne _020100DC
|
||||||
|
add r2, r2, #4
|
||||||
|
ands r0, r1, #2
|
||||||
|
bne _020100DC
|
||||||
|
add r2, r2, #4
|
||||||
|
ands r0, r1, #4
|
||||||
|
bne _020100DC
|
||||||
|
add r2, r2, #4
|
||||||
|
ands r0, r1, #0x100
|
||||||
|
bne _020100DC
|
||||||
|
add r2, r2, #4
|
||||||
|
ands r0, r1, #0x200
|
||||||
|
bne _020100DC
|
||||||
|
add r2, r2, #4
|
||||||
|
ands r0, r1, #0x400
|
||||||
|
bne _020100DC
|
||||||
|
add r2, r2, #4
|
||||||
|
ands r0, r1, #0x800
|
||||||
|
bne _020100DC
|
||||||
|
add r2, r2, #4
|
||||||
|
ands r0, r1, #0x1000
|
||||||
|
bne _020100DC
|
||||||
|
add r2, r2, #4
|
||||||
|
ands r0, r1, #8
|
||||||
|
_020100DC:
|
||||||
|
strh r0, [r3, #2]
|
||||||
|
ldr r1, =gIntrTable
|
||||||
|
add r1, r1, r2
|
||||||
|
ldr r0, [r1]
|
||||||
|
bx r0
|
||||||
|
.pool
|
||||||
|
.size IntrMain, .-IntrMain
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
.macro inc x
|
||||||
|
.set \x, \x + 1
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro enum_start x=0
|
||||||
|
.set __enum__, \x
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro enum constant
|
||||||
|
.equiv \constant, __enum__
|
||||||
|
inc __enum__
|
||||||
|
.endm
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
.macro arm_func_start name
|
||||||
|
.align 2, 0
|
||||||
|
.global \name
|
||||||
|
.arm
|
||||||
|
.type \name, %function
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro arm_func_end name
|
||||||
|
.size \name, .-\name
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro thumb_func_start name
|
||||||
|
.align 2, 0
|
||||||
|
.global \name
|
||||||
|
.thumb
|
||||||
|
.thumb_func
|
||||||
|
.type \name, %function
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro non_word_aligned_thumb_func_start name
|
||||||
|
.global \name
|
||||||
|
.thumb
|
||||||
|
.thumb_func
|
||||||
|
.type \name, %function
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro thumb_func_end name
|
||||||
|
.size \name, .-\name
|
||||||
|
.endm
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
OBJDUMP="$DEVKITARM/bin/arm-none-eabi-objdump -D -bbinary -marmv4t -Mforce-thumb"
|
||||||
|
OPTIONS="--start-address=$(($1)) --stop-address=$(($1 + $2))"
|
||||||
|
$OBJDUMP $OPTIONS baserom.gba > baserom.dump
|
||||||
|
$OBJDUMP $OPTIONS payload.gba > payload.dump
|
||||||
|
diff baserom.dump payload.dump
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
|||||||
|
gFlashTimeoutFlag
|
||||||
|
PollFlashStatus
|
||||||
|
WaitForFlashWrite
|
||||||
|
ProgramFlashSector
|
||||||
|
gFlash
|
||||||
|
ProgramFlashByte
|
||||||
|
gFlashNumRemainingBytes
|
||||||
|
EraseFlashChip
|
||||||
|
EraseFlashSector
|
||||||
|
gFlashMaxTime
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
gIntrTable
|
||||||
|
gHeldKeys
|
||||||
|
gNewKeys
|
||||||
|
gIntrVector
|
||||||
|
gUpdateSuccessful
|
||||||
|
gUnknown_3001194
|
||||||
|
gUnknown_30011A0
|
||||||
|
gMainCallbackState
|
||||||
|
gGameVersion
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
gTimeSinceBerryUpdate
|
||||||
|
gRtcUTCTime
|
||||||
@@ -0,0 +1,490 @@
|
|||||||
|
.set PSR_USR_MODE, 0x00000010
|
||||||
|
.set PSR_FIQ_MODE, 0x00000011
|
||||||
|
.set PSR_IRQ_MODE, 0x00000012
|
||||||
|
.set PSR_SVC_MODE, 0x00000013
|
||||||
|
.set PSR_ABT_MODE, 0x00000017
|
||||||
|
.set PSR_UND_MODE, 0x0000001b
|
||||||
|
.set PSR_SYS_MODE, 0x0000001f
|
||||||
|
.set PSR_MODE_MASK, 0x0000001f
|
||||||
|
.set PSR_T_BIT, 0x00000020
|
||||||
|
.set PSR_F_BIT, 0x00000040
|
||||||
|
.set PSR_I_BIT, 0x00000080
|
||||||
|
|
||||||
|
.set EWRAM_START, 0x02000000
|
||||||
|
.set EWRAM_END, EWRAM_START + 0x40000
|
||||||
|
.set IWRAM_START, 0x03000000
|
||||||
|
.set IWRAM_END, IWRAM_START + 0x8000
|
||||||
|
|
||||||
|
.set PLTT, 0x5000000
|
||||||
|
.set BG_PLTT, PLTT
|
||||||
|
.set OBJ_PLTT, PLTT + 0x200
|
||||||
|
|
||||||
|
.set VRAM, 0x6000000
|
||||||
|
.set BG_VRAM, VRAM
|
||||||
|
.set OBJ_VRAM0, VRAM + 0x10000 @ text-mode BG
|
||||||
|
.set OBJ_VRAM1, VRAM + 0x14000 @ bitmap-mode BG
|
||||||
|
|
||||||
|
.set OAM, 0x7000000
|
||||||
|
|
||||||
|
.set SOUND_INFO_PTR, 0x3007FF0
|
||||||
|
.set INTR_CHECK, 0x3007FF8
|
||||||
|
.set INTR_VECTOR, 0x3007FFC
|
||||||
|
|
||||||
|
.set INTR_FLAG_VBLANK, 1 << 0
|
||||||
|
.set INTR_FLAG_HBLANK, 1 << 1
|
||||||
|
.set INTR_FLAG_VCOUNT, 1 << 2
|
||||||
|
.set INTR_FLAG_TIMER0, 1 << 3
|
||||||
|
.set INTR_FLAG_TIMER1, 1 << 4
|
||||||
|
.set INTR_FLAG_TIMER2, 1 << 5
|
||||||
|
.set INTR_FLAG_TIMER3, 1 << 6
|
||||||
|
.set INTR_FLAG_SERIAL, 1 << 7
|
||||||
|
.set INTR_FLAG_DMA0, 1 << 8
|
||||||
|
.set INTR_FLAG_DMA1, 1 << 9
|
||||||
|
.set INTR_FLAG_DMA2, 1 << 10
|
||||||
|
.set INTR_FLAG_DMA3, 1 << 11
|
||||||
|
.set INTR_FLAG_KEYPAD, 1 << 12
|
||||||
|
.set INTR_FLAG_GAMEPAK, 1 << 13
|
||||||
|
|
||||||
|
.set VCOUNT_VBLANK, 160
|
||||||
|
.set TOTAL_SCANLINES, 228
|
||||||
|
|
||||||
|
.set REG_BASE, 0x4000000 @ I/O register base address
|
||||||
|
|
||||||
|
@ I/O register offsets
|
||||||
|
.set OFFSET_REG_DISPCNT, 0x0
|
||||||
|
.set OFFSET_REG_DISPSTAT, 0x4
|
||||||
|
.set OFFSET_REG_VCOUNT, 0x6
|
||||||
|
.set OFFSET_REG_BG0CNT, 0x8
|
||||||
|
.set OFFSET_REG_BG1CNT, 0xa
|
||||||
|
.set OFFSET_REG_BG2CNT, 0xc
|
||||||
|
.set OFFSET_REG_BG3CNT, 0xe
|
||||||
|
.set OFFSET_REG_BG0HOFS, 0x10
|
||||||
|
.set OFFSET_REG_BG0VOFS, 0x12
|
||||||
|
.set OFFSET_REG_BG1HOFS, 0x14
|
||||||
|
.set OFFSET_REG_BG1VOFS, 0x16
|
||||||
|
.set OFFSET_REG_BG2HOFS, 0x18
|
||||||
|
.set OFFSET_REG_BG2VOFS, 0x1a
|
||||||
|
.set OFFSET_REG_BG3HOFS, 0x1c
|
||||||
|
.set OFFSET_REG_BG3VOFS, 0x1e
|
||||||
|
.set OFFSET_REG_BG2PA, 0x20
|
||||||
|
.set OFFSET_REG_BG2PB, 0x22
|
||||||
|
.set OFFSET_REG_BG2PC, 0x24
|
||||||
|
.set OFFSET_REG_BG2PD, 0x26
|
||||||
|
.set OFFSET_REG_BG2X_L, 0x28
|
||||||
|
.set OFFSET_REG_BG2X_H, 0x2a
|
||||||
|
.set OFFSET_REG_BG2Y_L, 0x2c
|
||||||
|
.set OFFSET_REG_BG2Y_H, 0x2e
|
||||||
|
.set OFFSET_REG_BG3PA, 0x30
|
||||||
|
.set OFFSET_REG_BG3PB, 0x32
|
||||||
|
.set OFFSET_REG_BG3PC, 0x34
|
||||||
|
.set OFFSET_REG_BG3PD, 0x36
|
||||||
|
.set OFFSET_REG_BG3X_L, 0x38
|
||||||
|
.set OFFSET_REG_BG3X_H, 0x3a
|
||||||
|
.set OFFSET_REG_BG3Y_L, 0x3c
|
||||||
|
.set OFFSET_REG_BG3Y_H, 0x3e
|
||||||
|
.set OFFSET_REG_WIN0H, 0x40
|
||||||
|
.set OFFSET_REG_WIN1H, 0x42
|
||||||
|
.set OFFSET_REG_WIN0V, 0x44
|
||||||
|
.set OFFSET_REG_WIN1V, 0x46
|
||||||
|
.set OFFSET_REG_WININ, 0x48
|
||||||
|
.set OFFSET_REG_WINOUT, 0x4a
|
||||||
|
.set OFFSET_REG_MOSAIC, 0x4c
|
||||||
|
.set OFFSET_REG_BLDCNT, 0x50
|
||||||
|
.set OFFSET_REG_BLDALPHA, 0x52
|
||||||
|
.set OFFSET_REG_BLDY, 0x54
|
||||||
|
|
||||||
|
.set OFFSET_REG_SOUND1CNT, 0x60
|
||||||
|
.set OFFSET_REG_SOUND1CNT_L, 0x60
|
||||||
|
.set OFFSET_REG_NR10, 0x60
|
||||||
|
.set OFFSET_REG_SOUND1CNT_H, 0x62
|
||||||
|
.set OFFSET_REG_NR11, 0x62
|
||||||
|
.set OFFSET_REG_NR12, 0x63
|
||||||
|
.set OFFSET_REG_SOUND1CNT_X, 0x64
|
||||||
|
.set OFFSET_REG_NR13, 0x64
|
||||||
|
.set OFFSET_REG_NR14, 0x65
|
||||||
|
.set OFFSET_REG_SOUND2CNT, 0x68
|
||||||
|
.set OFFSET_REG_SOUND2CNT_L, 0x68
|
||||||
|
.set OFFSET_REG_NR21, 0x68
|
||||||
|
.set OFFSET_REG_NR22, 0x69
|
||||||
|
.set OFFSET_REG_SOUND2CNT_H, 0x6c
|
||||||
|
.set OFFSET_REG_NR23, 0x6c
|
||||||
|
.set OFFSET_REG_NR24, 0x6d
|
||||||
|
.set OFFSET_REG_SOUND3CNT, 0x70
|
||||||
|
.set OFFSET_REG_SOUND3CNT_L, 0x70
|
||||||
|
.set OFFSET_REG_NR30, 0x70
|
||||||
|
.set OFFSET_REG_SOUND3CNT_H, 0x72
|
||||||
|
.set OFFSET_REG_NR31, 0x72
|
||||||
|
.set OFFSET_REG_NR32, 0x73
|
||||||
|
.set OFFSET_REG_SOUND3CNT_X, 0x74
|
||||||
|
.set OFFSET_REG_NR33, 0x74
|
||||||
|
.set OFFSET_REG_NR34, 0x75
|
||||||
|
.set OFFSET_REG_SOUND4CNT, 0x78
|
||||||
|
.set OFFSET_REG_SOUND4CNT_L, 0x78
|
||||||
|
.set OFFSET_REG_NR41, 0x78
|
||||||
|
.set OFFSET_REG_NR42, 0x79
|
||||||
|
.set OFFSET_REG_SOUND4CNT_H, 0x7c
|
||||||
|
.set OFFSET_REG_NR43, 0x7c
|
||||||
|
.set OFFSET_REG_NR44, 0x7d
|
||||||
|
.set OFFSET_REG_SOUNDCNT, 0x80
|
||||||
|
.set OFFSET_REG_SOUNDCNT_L, 0x80
|
||||||
|
.set OFFSET_REG_NR50, 0x80
|
||||||
|
.set OFFSET_REG_NR51, 0x81
|
||||||
|
.set OFFSET_REG_SOUNDCNT_H, 0x82
|
||||||
|
.set OFFSET_REG_SOUNDCNT_X, 0x84
|
||||||
|
.set OFFSET_REG_NR52, 0x84
|
||||||
|
.set OFFSET_REG_SOUNDBIAS, 0x88
|
||||||
|
.set OFFSET_REG_WAVE_RAM, 0x90
|
||||||
|
.set OFFSET_REG_WAVE_RAM0, 0x90
|
||||||
|
.set OFFSET_REG_WAVE_RAM0_L, 0x90
|
||||||
|
.set OFFSET_REG_WAVE_RAM0_H, 0x92
|
||||||
|
.set OFFSET_REG_WAVE_RAM1, 0x94
|
||||||
|
.set OFFSET_REG_WAVE_RAM1_L, 0x94
|
||||||
|
.set OFFSET_REG_WAVE_RAM1_H, 0x96
|
||||||
|
.set OFFSET_REG_WAVE_RAM2, 0x98
|
||||||
|
.set OFFSET_REG_WAVE_RAM2_L, 0x98
|
||||||
|
.set OFFSET_REG_WAVE_RAM2_H, 0x9a
|
||||||
|
.set OFFSET_REG_WAVE_RAM3, 0x9c
|
||||||
|
.set OFFSET_REG_WAVE_RAM3_L, 0x9c
|
||||||
|
.set OFFSET_REG_WAVE_RAM3_H, 0x9e
|
||||||
|
.set OFFSET_REG_FIFO, 0xa0
|
||||||
|
.set OFFSET_REG_FIFO_A, 0xa0
|
||||||
|
.set OFFSET_REG_FIFO_A_L, 0xa0
|
||||||
|
.set OFFSET_REG_FIFO_A_H, 0xa2
|
||||||
|
.set OFFSET_REG_FIFO_B, 0xa4
|
||||||
|
.set OFFSET_REG_FIFO_B_L, 0xa4
|
||||||
|
.set OFFSET_REG_FIFO_B_H, 0xa6
|
||||||
|
|
||||||
|
.set OFFSET_REG_DMA0, 0xb0
|
||||||
|
.set OFFSET_REG_DMA0SAD, 0xb0
|
||||||
|
.set OFFSET_REG_DMA0SAD_L, 0xb0
|
||||||
|
.set OFFSET_REG_DMA0SAD_H, 0xb2
|
||||||
|
.set OFFSET_REG_DMA0DAD, 0xb4
|
||||||
|
.set OFFSET_REG_DMA0DAD_L, 0xb4
|
||||||
|
.set OFFSET_REG_DMA0DAD_H, 0xb6
|
||||||
|
.set OFFSET_REG_DMA0CNT, 0xb8
|
||||||
|
.set OFFSET_REG_DMA0CNT_L, 0xb8
|
||||||
|
.set OFFSET_REG_DMA0CNT_H, 0xba
|
||||||
|
.set OFFSET_REG_DMA1, 0xbc
|
||||||
|
.set OFFSET_REG_DMA1SAD, 0xbc
|
||||||
|
.set OFFSET_REG_DMA1SAD_L, 0xbc
|
||||||
|
.set OFFSET_REG_DMA1SAD_H, 0xbe
|
||||||
|
.set OFFSET_REG_DMA1DAD, 0xc0
|
||||||
|
.set OFFSET_REG_DMA1DAD_L, 0xc0
|
||||||
|
.set OFFSET_REG_DMA1DAD_H, 0xc2
|
||||||
|
.set OFFSET_REG_DMA1CNT, 0xc4
|
||||||
|
.set OFFSET_REG_DMA1CNT_L, 0xc4
|
||||||
|
.set OFFSET_REG_DMA1CNT_H, 0xc6
|
||||||
|
.set OFFSET_REG_DMA2, 0xc8
|
||||||
|
.set OFFSET_REG_DMA2SAD, 0xc8
|
||||||
|
.set OFFSET_REG_DMA2SAD_L, 0xc8
|
||||||
|
.set OFFSET_REG_DMA2SAD_H, 0xca
|
||||||
|
.set OFFSET_REG_DMA2DAD, 0xcc
|
||||||
|
.set OFFSET_REG_DMA2DAD_L, 0xcc
|
||||||
|
.set OFFSET_REG_DMA2DAD_H, 0xce
|
||||||
|
.set OFFSET_REG_DMA2CNT, 0xd0
|
||||||
|
.set OFFSET_REG_DMA2CNT_L, 0xd0
|
||||||
|
.set OFFSET_REG_DMA2CNT_H, 0xd2
|
||||||
|
.set OFFSET_REG_DMA3, 0xd4
|
||||||
|
.set OFFSET_REG_DMA3SAD, 0xd4
|
||||||
|
.set OFFSET_REG_DMA3SAD_L, 0xd4
|
||||||
|
.set OFFSET_REG_DMA3SAD_H, 0xd6
|
||||||
|
.set OFFSET_REG_DMA3DAD, 0xd8
|
||||||
|
.set OFFSET_REG_DMA3DAD_L, 0xd8
|
||||||
|
.set OFFSET_REG_DMA3DAD_H, 0xda
|
||||||
|
.set OFFSET_REG_DMA3CNT, 0xdc
|
||||||
|
.set OFFSET_REG_DMA3CNT_L, 0xdc
|
||||||
|
.set OFFSET_REG_DMA3CNT_H, 0xde
|
||||||
|
|
||||||
|
.set OFFSET_REG_TM0CNT, 0x100
|
||||||
|
.set OFFSET_REG_TM0CNT_L, 0x100
|
||||||
|
.set OFFSET_REG_TM0CNT_H, 0x102
|
||||||
|
.set OFFSET_REG_TM1CNT, 0x104
|
||||||
|
.set OFFSET_REG_TM1CNT_L, 0x104
|
||||||
|
.set OFFSET_REG_TM1CNT_H, 0x106
|
||||||
|
.set OFFSET_REG_TM2CNT, 0x108
|
||||||
|
.set OFFSET_REG_TM2CNT_L, 0x108
|
||||||
|
.set OFFSET_REG_TM2CNT_H, 0x10a
|
||||||
|
.set OFFSET_REG_TM3CNT, 0x10c
|
||||||
|
.set OFFSET_REG_TM3CNT_L, 0x10c
|
||||||
|
.set OFFSET_REG_TM3CNT_H, 0x10e
|
||||||
|
|
||||||
|
.set OFFSET_REG_SIOCNT, 0x128
|
||||||
|
.set OFFSET_REG_SIODATA8, 0x12a
|
||||||
|
.set OFFSET_REG_SIODATA32, 0x120
|
||||||
|
.set OFFSET_REG_SIOMLT_SEND, 0x12a
|
||||||
|
.set OFFSET_REG_SIOMLT_RECV, 0x120
|
||||||
|
.set OFFSET_REG_SIOMULTI0, 0x120
|
||||||
|
.set OFFSET_REG_SIOMULTI1, 0x122
|
||||||
|
.set OFFSET_REG_SIOMULTI2, 0x124
|
||||||
|
.set OFFSET_REG_SIOMULTI3, 0x126
|
||||||
|
|
||||||
|
.set OFFSET_REG_KEYINPUT, 0x130
|
||||||
|
.set OFFSET_REG_KEYCNT, 0x132
|
||||||
|
|
||||||
|
.set OFFSET_REG_RCNT, 0x134
|
||||||
|
|
||||||
|
.set OFFSET_REG_JOYCNT, 0x140
|
||||||
|
.set OFFSET_REG_JOYSTAT, 0x158
|
||||||
|
.set OFFSET_REG_JOY_RECV, 0x150
|
||||||
|
.set OFFSET_REG_JOY_RECV_L, 0x150
|
||||||
|
.set OFFSET_REG_JOY_RECV_H, 0x152
|
||||||
|
.set OFFSET_REG_JOY_TRANS, 0x154
|
||||||
|
.set OFFSET_REG_JOY_TRANS_L, 0x154
|
||||||
|
.set OFFSET_REG_JOY_TRANS_H, 0x156
|
||||||
|
|
||||||
|
.set OFFSET_REG_IME, 0x208
|
||||||
|
.set OFFSET_REG_IE, 0x200
|
||||||
|
.set OFFSET_REG_IF, 0x202
|
||||||
|
|
||||||
|
.set OFFSET_REG_WAITCNT, 0x204
|
||||||
|
|
||||||
|
@ I/O register addresses
|
||||||
|
.set REG_DISPCNT, REG_BASE + OFFSET_REG_DISPCNT
|
||||||
|
.set REG_DISPSTAT, REG_BASE + OFFSET_REG_DISPSTAT
|
||||||
|
.set REG_VCOUNT, REG_BASE + OFFSET_REG_VCOUNT
|
||||||
|
.set REG_BG0CNT, REG_BASE + OFFSET_REG_BG0CNT
|
||||||
|
.set REG_BG1CNT, REG_BASE + OFFSET_REG_BG1CNT
|
||||||
|
.set REG_BG2CNT, REG_BASE + OFFSET_REG_BG2CNT
|
||||||
|
.set REG_BG3CNT, REG_BASE + OFFSET_REG_BG3CNT
|
||||||
|
.set REG_BG0HOFS, REG_BASE + OFFSET_REG_BG0HOFS
|
||||||
|
.set REG_BG0VOFS, REG_BASE + OFFSET_REG_BG0VOFS
|
||||||
|
.set REG_BG1HOFS, REG_BASE + OFFSET_REG_BG1HOFS
|
||||||
|
.set REG_BG1VOFS, REG_BASE + OFFSET_REG_BG1VOFS
|
||||||
|
.set REG_BG2HOFS, REG_BASE + OFFSET_REG_BG2HOFS
|
||||||
|
.set REG_BG2VOFS, REG_BASE + OFFSET_REG_BG2VOFS
|
||||||
|
.set REG_BG3HOFS, REG_BASE + OFFSET_REG_BG3HOFS
|
||||||
|
.set REG_BG3VOFS, REG_BASE + OFFSET_REG_BG3VOFS
|
||||||
|
.set REG_BG2PA, REG_BASE + OFFSET_REG_BG2PA
|
||||||
|
.set REG_BG2PB, REG_BASE + OFFSET_REG_BG2PB
|
||||||
|
.set REG_BG2PC, REG_BASE + OFFSET_REG_BG2PC
|
||||||
|
.set REG_BG2PD, REG_BASE + OFFSET_REG_BG2PD
|
||||||
|
.set REG_BG2X_L, REG_BASE + OFFSET_REG_BG2X_L
|
||||||
|
.set REG_BG2X_H, REG_BASE + OFFSET_REG_BG2X_H
|
||||||
|
.set REG_BG2Y_L, REG_BASE + OFFSET_REG_BG2Y_L
|
||||||
|
.set REG_BG2Y_H, REG_BASE + OFFSET_REG_BG2Y_H
|
||||||
|
.set REG_BG3PA, REG_BASE + OFFSET_REG_BG3PA
|
||||||
|
.set REG_BG3PB, REG_BASE + OFFSET_REG_BG3PB
|
||||||
|
.set REG_BG3PC, REG_BASE + OFFSET_REG_BG3PC
|
||||||
|
.set REG_BG3PD, REG_BASE + OFFSET_REG_BG3PD
|
||||||
|
.set REG_BG3X_L, REG_BASE + OFFSET_REG_BG3X_L
|
||||||
|
.set REG_BG3X_H, REG_BASE + OFFSET_REG_BG3X_H
|
||||||
|
.set REG_BG3Y_L, REG_BASE + OFFSET_REG_BG3Y_L
|
||||||
|
.set REG_BG3Y_H, REG_BASE + OFFSET_REG_BG3Y_H
|
||||||
|
.set REG_WIN0H, REG_BASE + OFFSET_REG_WIN0H
|
||||||
|
.set REG_WIN1H, REG_BASE + OFFSET_REG_WIN1H
|
||||||
|
.set REG_WIN0V, REG_BASE + OFFSET_REG_WIN0V
|
||||||
|
.set REG_WIN1V, REG_BASE + OFFSET_REG_WIN1V
|
||||||
|
.set REG_WININ, REG_BASE + OFFSET_REG_WININ
|
||||||
|
.set REG_WINOUT, REG_BASE + OFFSET_REG_WINOUT
|
||||||
|
.set REG_MOSAIC, REG_BASE + OFFSET_REG_MOSAIC
|
||||||
|
.set REG_BLDCNT, REG_BASE + OFFSET_REG_BLDCNT
|
||||||
|
.set REG_BLDALPHA, REG_BASE + OFFSET_REG_BLDALPHA
|
||||||
|
.set REG_BLDY, REG_BASE + OFFSET_REG_BLDY
|
||||||
|
|
||||||
|
.set REG_SOUND1CNT, REG_BASE + OFFSET_REG_SOUND1CNT
|
||||||
|
.set REG_SOUND1CNT_L, REG_BASE + OFFSET_REG_SOUND1CNT_L
|
||||||
|
.set REG_NR10, REG_BASE + OFFSET_REG_NR10
|
||||||
|
.set REG_SOUND1CNT_H, REG_BASE + OFFSET_REG_SOUND1CNT_H
|
||||||
|
.set REG_NR11, REG_BASE + OFFSET_REG_NR11
|
||||||
|
.set REG_NR12, REG_BASE + OFFSET_REG_NR12
|
||||||
|
.set REG_SOUND1CNT_X, REG_BASE + OFFSET_REG_SOUND1CNT_X
|
||||||
|
.set REG_NR13, REG_BASE + OFFSET_REG_NR13
|
||||||
|
.set REG_NR14, REG_BASE + OFFSET_REG_NR14
|
||||||
|
.set REG_SOUND2CNT, REG_BASE + OFFSET_REG_SOUND2CNT
|
||||||
|
.set REG_SOUND2CNT_L, REG_BASE + OFFSET_REG_SOUND2CNT_L
|
||||||
|
.set REG_NR21, REG_BASE + OFFSET_REG_NR21
|
||||||
|
.set REG_NR22, REG_BASE + OFFSET_REG_NR22
|
||||||
|
.set REG_SOUND2CNT_H, REG_BASE + OFFSET_REG_SOUND2CNT_H
|
||||||
|
.set REG_NR23, REG_BASE + OFFSET_REG_NR23
|
||||||
|
.set REG_NR24, REG_BASE + OFFSET_REG_NR24
|
||||||
|
.set REG_SOUND3CNT, REG_BASE + OFFSET_REG_SOUND3CNT
|
||||||
|
.set REG_SOUND3CNT_L, REG_BASE + OFFSET_REG_SOUND3CNT_L
|
||||||
|
.set REG_NR30, REG_BASE + OFFSET_REG_NR30
|
||||||
|
.set REG_SOUND3CNT_H, REG_BASE + OFFSET_REG_SOUND3CNT_H
|
||||||
|
.set REG_NR31, REG_BASE + OFFSET_REG_NR31
|
||||||
|
.set REG_NR32, REG_BASE + OFFSET_REG_NR32
|
||||||
|
.set REG_SOUND3CNT_X, REG_BASE + OFFSET_REG_SOUND3CNT_X
|
||||||
|
.set REG_NR33, REG_BASE + OFFSET_REG_NR33
|
||||||
|
.set REG_NR34, REG_BASE + OFFSET_REG_NR34
|
||||||
|
.set REG_SOUND4CNT, REG_BASE + OFFSET_REG_SOUND4CNT
|
||||||
|
.set REG_SOUND4CNT_L, REG_BASE + OFFSET_REG_SOUND4CNT_L
|
||||||
|
.set REG_NR41, REG_BASE + OFFSET_REG_NR41
|
||||||
|
.set REG_NR42, REG_BASE + OFFSET_REG_NR42
|
||||||
|
.set REG_SOUND4CNT_H, REG_BASE + OFFSET_REG_SOUND4CNT_H
|
||||||
|
.set REG_NR43, REG_BASE + OFFSET_REG_NR43
|
||||||
|
.set REG_NR44, REG_BASE + OFFSET_REG_NR44
|
||||||
|
.set REG_SOUNDCNT, REG_BASE + OFFSET_REG_SOUNDCNT
|
||||||
|
.set REG_SOUNDCNT_L, REG_BASE + OFFSET_REG_SOUNDCNT_L
|
||||||
|
.set REG_NR50, REG_BASE + OFFSET_REG_NR50
|
||||||
|
.set REG_NR51, REG_BASE + OFFSET_REG_NR51
|
||||||
|
.set REG_SOUNDCNT_H, REG_BASE + OFFSET_REG_SOUNDCNT_H
|
||||||
|
.set REG_SOUNDCNT_X, REG_BASE + OFFSET_REG_SOUNDCNT_X
|
||||||
|
.set REG_NR52, REG_BASE + OFFSET_REG_NR52
|
||||||
|
.set REG_SOUNDBIAS, REG_BASE + OFFSET_REG_SOUNDBIAS
|
||||||
|
.set REG_WAVE_RAM, REG_BASE + OFFSET_REG_WAVE_RAM
|
||||||
|
.set REG_WAVE_RAM0, REG_BASE + OFFSET_REG_WAVE_RAM0
|
||||||
|
.set REG_WAVE_RAM0_L, REG_BASE + OFFSET_REG_WAVE_RAM0_L
|
||||||
|
.set REG_WAVE_RAM0_H, REG_BASE + OFFSET_REG_WAVE_RAM0_H
|
||||||
|
.set REG_WAVE_RAM1, REG_BASE + OFFSET_REG_WAVE_RAM1
|
||||||
|
.set REG_WAVE_RAM1_L, REG_BASE + OFFSET_REG_WAVE_RAM1_L
|
||||||
|
.set REG_WAVE_RAM1_H, REG_BASE + OFFSET_REG_WAVE_RAM1_H
|
||||||
|
.set REG_WAVE_RAM2, REG_BASE + OFFSET_REG_WAVE_RAM2
|
||||||
|
.set REG_WAVE_RAM2_L, REG_BASE + OFFSET_REG_WAVE_RAM2_L
|
||||||
|
.set REG_WAVE_RAM2_H, REG_BASE + OFFSET_REG_WAVE_RAM2_H
|
||||||
|
.set REG_WAVE_RAM3, REG_BASE + OFFSET_REG_WAVE_RAM3
|
||||||
|
.set REG_WAVE_RAM3_L, REG_BASE + OFFSET_REG_WAVE_RAM3_L
|
||||||
|
.set REG_WAVE_RAM3_H, REG_BASE + OFFSET_REG_WAVE_RAM3_H
|
||||||
|
.set REG_FIFO, REG_BASE + OFFSET_REG_FIFO
|
||||||
|
.set REG_FIFO_A, REG_BASE + OFFSET_REG_FIFO_A
|
||||||
|
.set REG_FIFO_A_L, REG_BASE + OFFSET_REG_FIFO_A_L
|
||||||
|
.set REG_FIFO_A_H, REG_BASE + OFFSET_REG_FIFO_A_H
|
||||||
|
.set REG_FIFO_B, REG_BASE + OFFSET_REG_FIFO_B
|
||||||
|
.set REG_FIFO_B_L, REG_BASE + OFFSET_REG_FIFO_B_L
|
||||||
|
.set REG_FIFO_B_H, REG_BASE + OFFSET_REG_FIFO_B_H
|
||||||
|
|
||||||
|
.set REG_DMA0, REG_BASE + OFFSET_REG_DMA0
|
||||||
|
.set REG_DMA0SAD, REG_BASE + OFFSET_REG_DMA0SAD
|
||||||
|
.set REG_DMA0SAD_L, REG_BASE + OFFSET_REG_DMA0SAD_L
|
||||||
|
.set REG_DMA0SAD_H, REG_BASE + OFFSET_REG_DMA0SAD_H
|
||||||
|
.set REG_DMA0DAD, REG_BASE + OFFSET_REG_DMA0DAD
|
||||||
|
.set REG_DMA0DAD_L, REG_BASE + OFFSET_REG_DMA0DAD_L
|
||||||
|
.set REG_DMA0DAD_H, REG_BASE + OFFSET_REG_DMA0DAD_H
|
||||||
|
.set REG_DMA0CNT, REG_BASE + OFFSET_REG_DMA0CNT
|
||||||
|
.set REG_DMA0CNT_L, REG_BASE + OFFSET_REG_DMA0CNT_L
|
||||||
|
.set REG_DMA0CNT_H, REG_BASE + OFFSET_REG_DMA0CNT_H
|
||||||
|
.set REG_DMA1, REG_BASE + OFFSET_REG_DMA1
|
||||||
|
.set REG_DMA1SAD, REG_BASE + OFFSET_REG_DMA1SAD
|
||||||
|
.set REG_DMA1SAD_L, REG_BASE + OFFSET_REG_DMA1SAD_L
|
||||||
|
.set REG_DMA1SAD_H, REG_BASE + OFFSET_REG_DMA1SAD_H
|
||||||
|
.set REG_DMA1DAD, REG_BASE + OFFSET_REG_DMA1DAD
|
||||||
|
.set REG_DMA1DAD_L, REG_BASE + OFFSET_REG_DMA1DAD_L
|
||||||
|
.set REG_DMA1DAD_H, REG_BASE + OFFSET_REG_DMA1DAD_H
|
||||||
|
.set REG_DMA1CNT, REG_BASE + OFFSET_REG_DMA1CNT
|
||||||
|
.set REG_DMA1CNT_L, REG_BASE + OFFSET_REG_DMA1CNT_L
|
||||||
|
.set REG_DMA1CNT_H, REG_BASE + OFFSET_REG_DMA1CNT_H
|
||||||
|
.set REG_DMA2, REG_BASE + OFFSET_REG_DMA2
|
||||||
|
.set REG_DMA2SAD, REG_BASE + OFFSET_REG_DMA2SAD
|
||||||
|
.set REG_DMA2SAD_L, REG_BASE + OFFSET_REG_DMA2SAD_L
|
||||||
|
.set REG_DMA2SAD_H, REG_BASE + OFFSET_REG_DMA2SAD_H
|
||||||
|
.set REG_DMA2DAD, REG_BASE + OFFSET_REG_DMA2DAD
|
||||||
|
.set REG_DMA2DAD_L, REG_BASE + OFFSET_REG_DMA2DAD_L
|
||||||
|
.set REG_DMA2DAD_H, REG_BASE + OFFSET_REG_DMA2DAD_H
|
||||||
|
.set REG_DMA2CNT, REG_BASE + OFFSET_REG_DMA2CNT
|
||||||
|
.set REG_DMA2CNT_L, REG_BASE + OFFSET_REG_DMA2CNT_L
|
||||||
|
.set REG_DMA2CNT_H, REG_BASE + OFFSET_REG_DMA2CNT_H
|
||||||
|
.set REG_DMA3, REG_BASE + OFFSET_REG_DMA3
|
||||||
|
.set REG_DMA3SAD, REG_BASE + OFFSET_REG_DMA3SAD
|
||||||
|
.set REG_DMA3SAD_L, REG_BASE + OFFSET_REG_DMA3SAD_L
|
||||||
|
.set REG_DMA3SAD_H, REG_BASE + OFFSET_REG_DMA3SAD_H
|
||||||
|
.set REG_DMA3DAD, REG_BASE + OFFSET_REG_DMA3DAD
|
||||||
|
.set REG_DMA3DAD_L, REG_BASE + OFFSET_REG_DMA3DAD_L
|
||||||
|
.set REG_DMA3DAD_H, REG_BASE + OFFSET_REG_DMA3DAD_H
|
||||||
|
.set REG_DMA3CNT, REG_BASE + OFFSET_REG_DMA3CNT
|
||||||
|
.set REG_DMA3CNT_L, REG_BASE + OFFSET_REG_DMA3CNT_L
|
||||||
|
.set REG_DMA3CNT_H, REG_BASE + OFFSET_REG_DMA3CNT_H
|
||||||
|
|
||||||
|
.set REG_TM0CNT, REG_BASE + OFFSET_REG_TM0CNT
|
||||||
|
.set REG_TM0CNT_L, REG_BASE + OFFSET_REG_TM0CNT_L
|
||||||
|
.set REG_TM0CNT_H, REG_BASE + OFFSET_REG_TM0CNT_H
|
||||||
|
.set REG_TM1CNT, REG_BASE + OFFSET_REG_TM1CNT
|
||||||
|
.set REG_TM1CNT_L, REG_BASE + OFFSET_REG_TM1CNT_L
|
||||||
|
.set REG_TM1CNT_H, REG_BASE + OFFSET_REG_TM1CNT_H
|
||||||
|
.set REG_TM2CNT, REG_BASE + OFFSET_REG_TM2CNT
|
||||||
|
.set REG_TM2CNT_L, REG_BASE + OFFSET_REG_TM2CNT_L
|
||||||
|
.set REG_TM2CNT_H, REG_BASE + OFFSET_REG_TM2CNT_H
|
||||||
|
.set REG_TM3CNT, REG_BASE + OFFSET_REG_TM3CNT
|
||||||
|
.set REG_TM3CNT_L, REG_BASE + OFFSET_REG_TM3CNT_L
|
||||||
|
.set REG_TM3CNT_H, REG_BASE + OFFSET_REG_TM3CNT_H
|
||||||
|
|
||||||
|
.set REG_SIOCNT, REG_BASE + OFFSET_REG_SIOCNT
|
||||||
|
.set REG_SIODATA8, REG_BASE + OFFSET_REG_SIODATA8
|
||||||
|
.set REG_SIODATA32, REG_BASE + OFFSET_REG_SIODATA32
|
||||||
|
.set REG_SIOMLT_SEND, REG_BASE + OFFSET_REG_SIOMLT_SEND
|
||||||
|
.set REG_SIOMLT_RECV, REG_BASE + OFFSET_REG_SIOMLT_RECV
|
||||||
|
.set REG_SIOMULTI0, REG_BASE + OFFSET_REG_SIOMULTI0
|
||||||
|
.set REG_SIOMULTI1, REG_BASE + OFFSET_REG_SIOMULTI1
|
||||||
|
.set REG_SIOMULTI2, REG_BASE + OFFSET_REG_SIOMULTI2
|
||||||
|
.set REG_SIOMULTI3, REG_BASE + OFFSET_REG_SIOMULTI3
|
||||||
|
|
||||||
|
.set REG_KEYINPUT, REG_BASE + OFFSET_REG_KEYINPUT
|
||||||
|
.set REG_KEYCNT, REG_BASE + OFFSET_REG_KEYCNT
|
||||||
|
|
||||||
|
.set REG_RCNT, REG_BASE + OFFSET_REG_RCNT
|
||||||
|
|
||||||
|
.set REG_JOYCNT, REG_BASE + OFFSET_REG_JOYCNT
|
||||||
|
.set REG_JOYSTAT, REG_BASE + OFFSET_REG_JOYSTAT
|
||||||
|
.set REG_JOY_RECV, REG_BASE + OFFSET_REG_JOY_RECV
|
||||||
|
.set REG_JOY_RECV_L, REG_BASE + OFFSET_REG_JOY_RECV_L
|
||||||
|
.set REG_JOY_RECV_H, REG_BASE + OFFSET_REG_JOY_RECV_H
|
||||||
|
.set REG_JOY_TRANS, REG_BASE + OFFSET_REG_JOY_TRANS
|
||||||
|
.set REG_JOY_TRANS_L, REG_BASE + OFFSET_REG_JOY_TRANS_L
|
||||||
|
.set REG_JOY_TRANS_H, REG_BASE + OFFSET_REG_JOY_TRANS_H
|
||||||
|
|
||||||
|
.set REG_IME, REG_BASE + OFFSET_REG_IME
|
||||||
|
.set REG_IE, REG_BASE + OFFSET_REG_IE
|
||||||
|
.set REG_IF, REG_BASE + OFFSET_REG_IF
|
||||||
|
|
||||||
|
.set REG_WAITCNT, REG_BASE + OFFSET_REG_WAITCNT
|
||||||
|
|
||||||
|
@ DMA register constants
|
||||||
|
|
||||||
|
.set DMA_DEST_INC, 0x0000
|
||||||
|
.set DMA_DEST_DEC, 0x0020
|
||||||
|
.set DMA_DEST_FIXED, 0x0040
|
||||||
|
.set DMA_DEST_RELOAD, 0x0060
|
||||||
|
.set DMA_SRC_INC, 0x0000
|
||||||
|
.set DMA_SRC_DEC, 0x0080
|
||||||
|
.set DMA_SRC_FIXED, 0x0100
|
||||||
|
.set DMA_REPEAT, 0x0200
|
||||||
|
.set DMA_16BIT, 0x0000
|
||||||
|
.set DMA_32BIT, 0x0400
|
||||||
|
.set DMA_DREQ_ON, 0x0800
|
||||||
|
.set DMA_START_NOW, 0x0000
|
||||||
|
.set DMA_START_VBLANK, 0x1000
|
||||||
|
.set DMA_START_HBLANK, 0x2000
|
||||||
|
.set DMA_START_SPECIAL, 0x3000
|
||||||
|
.set DMA_INTR_ENABLE, 0x4000
|
||||||
|
.set DMA_ENABLE, 0x8000
|
||||||
|
|
||||||
|
@ OAM attribute constants
|
||||||
|
|
||||||
|
.set OAM_OBJ_NORMAL, 0x00000000
|
||||||
|
.set OAM_OBJ_BLEND, 0x00000400
|
||||||
|
.set OAM_OBJ_WINDOW, 0x00000800
|
||||||
|
|
||||||
|
.set OAM_AFFINE_NONE, 0x00000000
|
||||||
|
.set OAM_AFFINE_NORMAL_SIZE, 0x00000100
|
||||||
|
.set OAM_OBJ_DISABLED, 0x00000200
|
||||||
|
.set OAM_AFFINE_DOUBLE_SIZE, 0x00000300
|
||||||
|
|
||||||
|
.set OAM_MOSAIC_OFF, 0x00000000
|
||||||
|
.set OAM_MOSAIC_ON, 0x00001000
|
||||||
|
|
||||||
|
.set OAM_4BPP, 0x00000000
|
||||||
|
.set OAM_8BPP, 0x00002000
|
||||||
|
|
||||||
|
.set OAM_H_FLIP, 0x10000000
|
||||||
|
.set OAM_V_FLIP, 0x20000000
|
||||||
|
|
||||||
|
.set OAM_SQUARE, 0x00000000
|
||||||
|
.set OAM_H_RECTANGLE, 0x00004000
|
||||||
|
.set OAM_V_RECTANGLE, 0x00008000
|
||||||
|
.set OAM_SIZE_0, 0x00000000
|
||||||
|
.set OAM_SIZE_1, 0x40000000
|
||||||
|
.set OAM_SIZE_2, 0x80000000
|
||||||
|
.set OAM_SIZE_3, 0xc0000000
|
||||||
|
|
||||||
|
.set OAM_SIZE_8x8, OAM_SIZE_0 | OAM_SQUARE
|
||||||
|
.set OAM_SIZE_16x16, OAM_SIZE_1 | OAM_SQUARE
|
||||||
|
.set OAM_SIZE_32x32, OAM_SIZE_2 | OAM_SQUARE
|
||||||
|
.set OAM_SIZE_64x64, OAM_SIZE_3 | OAM_SQUARE
|
||||||
|
|
||||||
|
.set OAM_SIZE_16x8, OAM_SIZE_0 | OAM_H_RECTANGLE
|
||||||
|
.set OAM_SIZE_32x8, OAM_SIZE_1 | OAM_H_RECTANGLE
|
||||||
|
.set OAM_SIZE_32x16, OAM_SIZE_2 | OAM_H_RECTANGLE
|
||||||
|
.set OAM_SIZE_64x32, OAM_SIZE_3 | OAM_H_RECTANGLE
|
||||||
|
|
||||||
|
.set OAM_SIZE_8x16, OAM_SIZE_0 | OAM_V_RECTANGLE
|
||||||
|
.set OAM_SIZE_8x32, OAM_SIZE_1 | OAM_V_RECTANGLE
|
||||||
|
.set OAM_SIZE_16x32, OAM_SIZE_2 | OAM_V_RECTANGLE
|
||||||
|
.set OAM_SIZE_32x64, OAM_SIZE_3 | OAM_V_RECTANGLE
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 166 B |
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
Binary file not shown.
@@ -0,0 +1,56 @@
|
|||||||
|
#ifndef GUARD_CONSTANTS_GAME_STAT_H
|
||||||
|
#define GUARD_CONSTANTS_GAME_STAT_H
|
||||||
|
|
||||||
|
#define GAME_STAT_SAVED_GAME 0
|
||||||
|
#define GAME_STAT_FIRST_HOF_PLAY_TIME 1
|
||||||
|
#define GAME_STAT_STARTED_TRENDS 2
|
||||||
|
#define GAME_STAT_PLANTED_BERRIES 3
|
||||||
|
#define GAME_STAT_TRADED_BIKES 4
|
||||||
|
#define GAME_STAT_STEPS 5
|
||||||
|
#define GAME_STAT_GOT_INTERVIEWED 6
|
||||||
|
#define GAME_STAT_TOTAL_BATTLES 7
|
||||||
|
#define GAME_STAT_WILD_BATTLES 8
|
||||||
|
#define GAME_STAT_TRAINER_BATTLES 9
|
||||||
|
#define GAME_STAT_ENTERED_HOF 10
|
||||||
|
#define GAME_STAT_POKEMON_CAPTURES 11
|
||||||
|
#define GAME_STAT_FISHING_CAPTURES 12
|
||||||
|
#define GAME_STAT_HATCHED_EGGS 13
|
||||||
|
#define GAME_STAT_EVOLVED_POKEMON 14
|
||||||
|
#define GAME_STAT_USED_POKECENTER 15
|
||||||
|
#define GAME_STAT_RESTED_AT_HOME 16
|
||||||
|
#define GAME_STAT_ENTERED_SAFARI_ZONE 17
|
||||||
|
#define GAME_STAT_USED_CUT 18
|
||||||
|
#define GAME_STAT_USED_ROCK_SMASH 19
|
||||||
|
#define GAME_STAT_MOVED_SECRET_BASE 20
|
||||||
|
#define GAME_STAT_POKEMON_TRADES 21
|
||||||
|
#define GAME_STAT_UNKNOWN_22 22
|
||||||
|
#define GAME_STAT_LINK_BATTLE_WINS 23
|
||||||
|
#define GAME_STAT_LINK_BATTLE_LOSSES 24
|
||||||
|
#define GAME_STAT_LINK_BATTLE_DRAWS 25
|
||||||
|
#define GAME_STAT_USED_SPLASH 26
|
||||||
|
#define GAME_STAT_USED_STRUGGLE 27
|
||||||
|
#define GAME_STAT_SLOT_JACKPOTS 28
|
||||||
|
#define GAME_STAT_CONSECUTIVE_ROULETTE_WINS 29
|
||||||
|
#define GAME_STAT_ENTERED_BATTLE_TOWER 30
|
||||||
|
#define GAME_STAT_UNKNOWN_31 31
|
||||||
|
#define GAME_STAT_BATTLE_TOWER_BEST_STREAK 32
|
||||||
|
#define GAME_STAT_POKEBLOCKS 33
|
||||||
|
#define GAME_STAT_POKEBLOCKS_WITH_FRIENDS 34
|
||||||
|
#define GAME_STAT_WON_LINK_CONTEST 35
|
||||||
|
#define GAME_STAT_ENTERED_CONTEST 36
|
||||||
|
#define GAME_STAT_WON_CONTEST 37
|
||||||
|
#define GAME_STAT_SHOPPED 38
|
||||||
|
#define GAME_STAT_USED_ITEMFINDER 39
|
||||||
|
#define GAME_STAT_GOT_RAINED_ON 40
|
||||||
|
#define GAME_STAT_CHECKED_POKEDEX 41
|
||||||
|
#define GAME_STAT_RECEIVED_RIBBONS 42
|
||||||
|
#define GAME_STAT_JUMPED_DOWN_LEDGES 43
|
||||||
|
#define GAME_STAT_WATCHED_TV 44
|
||||||
|
#define GAME_STAT_CHECKED_CLOCK 45
|
||||||
|
#define GAME_STAT_WON_POKEMON_LOTTERY 46
|
||||||
|
#define GAME_STAT_USED_DAYCARE 47
|
||||||
|
#define GAME_STAT_RODE_CABLE_CAR 48
|
||||||
|
#define GAME_STAT_ENTERED_HOT_SPRINGS 49
|
||||||
|
#define NUM_GAME_STATS 50
|
||||||
|
|
||||||
|
#endif // GUARD_CONSTANTS_GAME_STAT_H
|
||||||
@@ -0,0 +1,196 @@
|
|||||||
|
#ifndef GUARD_CONSTANTS_VARS_H
|
||||||
|
#define GUARD_CONSTANTS_VARS_H
|
||||||
|
|
||||||
|
#define VAR_0x3F20 0x3F20
|
||||||
|
|
||||||
|
#define VARS_START 0x4000
|
||||||
|
|
||||||
|
// temporary vars
|
||||||
|
// The first 0x10 vars are are temporary--they are cleared every time a map is loaded.
|
||||||
|
#define VAR_TEMP_0 0x4000
|
||||||
|
#define VAR_TEMP_1 0x4001
|
||||||
|
#define VAR_TEMP_2 0x4002
|
||||||
|
#define VAR_TEMP_3 0x4003
|
||||||
|
#define VAR_TEMP_4 0x4004
|
||||||
|
#define VAR_TEMP_5 0x4005
|
||||||
|
#define VAR_TEMP_6 0x4006
|
||||||
|
#define VAR_TEMP_7 0x4007
|
||||||
|
#define VAR_TEMP_8 0x4008
|
||||||
|
#define VAR_TEMP_9 0x4009
|
||||||
|
#define VAR_TEMP_A 0x400A
|
||||||
|
#define VAR_TEMP_B 0x400B
|
||||||
|
#define VAR_TEMP_C 0x400C
|
||||||
|
#define VAR_TEMP_D 0x400D
|
||||||
|
#define VAR_TEMP_E 0x400E
|
||||||
|
#define VAR_TEMP_F 0x400F
|
||||||
|
|
||||||
|
// object gfx id vars
|
||||||
|
// These 0x10 vars are used to dynamically control a event object's sprite.
|
||||||
|
// For example, the rival's sprite id is dynamically set based on the player's gender.
|
||||||
|
// See VarGetEventObjectGraphicsId().
|
||||||
|
#define VAR_OBJ_GFX_ID_0 0x4010
|
||||||
|
#define VAR_OBJ_GFX_ID_1 0x4011
|
||||||
|
#define VAR_OBJ_GFX_ID_2 0x4012
|
||||||
|
#define VAR_OBJ_GFX_ID_3 0x4013
|
||||||
|
#define VAR_OBJ_GFX_ID_4 0x4014
|
||||||
|
#define VAR_OBJ_GFX_ID_5 0x4015
|
||||||
|
#define VAR_OBJ_GFX_ID_6 0x4016
|
||||||
|
#define VAR_OBJ_GFX_ID_7 0x4017
|
||||||
|
#define VAR_OBJ_GFX_ID_8 0x4018
|
||||||
|
#define VAR_OBJ_GFX_ID_9 0x4019
|
||||||
|
#define VAR_OBJ_GFX_ID_A 0x401A
|
||||||
|
#define VAR_OBJ_GFX_ID_B 0x401B
|
||||||
|
#define VAR_OBJ_GFX_ID_C 0x401C
|
||||||
|
#define VAR_OBJ_GFX_ID_D 0x401D
|
||||||
|
#define VAR_OBJ_GFX_ID_E 0x401E
|
||||||
|
#define VAR_OBJ_GFX_ID_F 0x401F
|
||||||
|
|
||||||
|
// general purpose vars
|
||||||
|
#define VAR_RECYCLE_GOODS 0x4020
|
||||||
|
#define VAR_REPEL_STEP_COUNT 0x4021
|
||||||
|
#define VAR_ICE_STEP_COUNT 0x4022
|
||||||
|
#define VAR_STARTER_MON 0x4023 // 0=Treecko, 1=Torchic, 2=Mudkip
|
||||||
|
#define VAR_MIRAGE_RND_H 0x4024
|
||||||
|
#define VAR_MIRAGE_RND_L 0x4025
|
||||||
|
#define VAR_SECRET_BASE_MAP 0x4026
|
||||||
|
#define VAR_CYCLING_ROAD_RECORD_COLLISIONS 0x4027
|
||||||
|
#define VAR_CYCLING_ROAD_RECORD_TIME_L 0x4028
|
||||||
|
#define VAR_CYCLING_ROAD_RECORD_TIME_H 0x4029
|
||||||
|
#define VAR_HAPPINESS_STEP_COUNTER 0x402A
|
||||||
|
#define VAR_POISON_STEP_COUNTER 0x402B
|
||||||
|
#define VAR_RESET_RTC_ENABLE 0x402C
|
||||||
|
#define VAR_ENIGMA_BERRY_AVAILABLE 0x402D
|
||||||
|
|
||||||
|
#define VAR_DAYS 0x4040
|
||||||
|
#define VAR_FANCLUB_UNKNOWN_1 0x4041 // TODO: document these two fanclub vars
|
||||||
|
#define VAR_FANCLUB_UNKNOWN_2 0x4042
|
||||||
|
#define VAR_DEPT_STORE_FLOOR 0x4043
|
||||||
|
#define VAR_TRICK_HOUSE_ROOMS_COMPLETED 0x4044
|
||||||
|
#define VAR_LOTTERY_PRIZE 0x4045
|
||||||
|
#define VAR_NATIONAL_DEX 0x4046
|
||||||
|
#define VAR_SHROOMISH_SIZE_RECORD 0x4047
|
||||||
|
#define VAR_ASH_GATHER_COUNT 0x4048
|
||||||
|
#define VAR_BIRCH_STATE 0x4049
|
||||||
|
#define VAR_CRUISE_STEP_COUNT 0x404A
|
||||||
|
#define VAR_LOTTERY_RND_L 0x404B
|
||||||
|
#define VAR_LOTTERY_RND_H 0x404C
|
||||||
|
|
||||||
|
#define VAR_BARBOACH_SIZE_RECORD 0x404F
|
||||||
|
#define VAR_LITTLEROOT_STATE 0x4050
|
||||||
|
#define VAR_ROUTE102_ACCESSIBLE 0x4051
|
||||||
|
|
||||||
|
#define VAR_LAVARIDGE_RIVAL_STATE 0x4053
|
||||||
|
#define VAR_CURRENT_SECRET_BASE 0x4054
|
||||||
|
|
||||||
|
#define VAR_PETALBURG_STATE 0x4057
|
||||||
|
#define VAR_SLATEPORT_STATE 0x4058
|
||||||
|
|
||||||
|
#define VAR_RUSTBORO_STATE 0x405A
|
||||||
|
|
||||||
|
#define VAR_SOOTOPOLIS_STATE 0x405E
|
||||||
|
|
||||||
|
#define VAR_ROUTE101_STATE 0x4060
|
||||||
|
|
||||||
|
#define VAR_ROUTE103_STATE 0x4062
|
||||||
|
|
||||||
|
#define VAR_ROUTE110_STATE 0x4069
|
||||||
|
|
||||||
|
#define VAR_ROUTE116_STATE 0x406F
|
||||||
|
|
||||||
|
#define VAR_ROUTE118_STATE 0x4071
|
||||||
|
#define VAR_ROUTE119_STATE 0x4072
|
||||||
|
|
||||||
|
#define VAR_ROUTE121_STATE 0x4074
|
||||||
|
#define VAR_ROUTE128_STATE 0x407B
|
||||||
|
|
||||||
|
#define VAR_LITTLEROOT_HOUSES_STATE 0x4082 // TODO: needs more investigation
|
||||||
|
|
||||||
|
#define VAR_BIRCH_LAB_STATE 0x4084
|
||||||
|
#define VAR_PETALBURG_GYM_STATE 0x4085
|
||||||
|
#define VAR_LINK_CONTEST_ROOM_STATE 0x4086
|
||||||
|
#define VAR_CABLE_CLUB_STATE 0x4087
|
||||||
|
#define VAR_CONTEST_LOCATION 0x4088
|
||||||
|
#define VAR_0x4089 0x4089 // TODO: related to decorations
|
||||||
|
#define VAR_CONTEST_PRIZE_PICKUP 0x408A
|
||||||
|
|
||||||
|
#define VAR_LITTLEROOT_HOUSES_STATE_2 0x408C // TODO: needs more investigation
|
||||||
|
#define VAR_LITTLEROOT_RIVAL_STATE 0x408D
|
||||||
|
#define VAR_BOARD_BRINEY_BOAT_ROUTE104_STATE 0x408E
|
||||||
|
#define VAR_DEVON_CORP_3F_STATE 0x408F
|
||||||
|
#define VAR_BRINEY_HOUSE_STATE 0x4090
|
||||||
|
|
||||||
|
#define VAR_LITTLEROOT_INTRO_STATE 0x4092
|
||||||
|
#define VAR_MAUVILLE_GYM_STATE 0x4093
|
||||||
|
#define VAR_LILYCOVE_MUSEUM_2F_STATE 0x4094
|
||||||
|
#define VAR_LILYCOVE_FAN_CLUB_STATE 0x4095
|
||||||
|
#define VAR_BRINEY_LOCATION 0x4096
|
||||||
|
#define VAR_0x4097 0x4097 // TODO: related to creating new secret base
|
||||||
|
#define VAR_PETALBURG_WOODS_STATE 0x4098
|
||||||
|
#define VAR_LILYCOVE_CONTEST_LOBBY_STATE 0x4099
|
||||||
|
#define VAR_RUSTURF_TUNNEL_STATE 0x409a
|
||||||
|
#define VAR_CAVE_OF_ORIGIN_B4F_STATE 0x409B
|
||||||
|
#define VAR_ELITE_4_STATE 0x409C
|
||||||
|
|
||||||
|
#define VAR_SLATEPORT_HARBOR_STATE 0x40A0
|
||||||
|
|
||||||
|
#define VAR_SEAFLOOR_CAVERN_STATE 0x40A2
|
||||||
|
#define VAR_CABLE_CAR_STATION_STATE 0x40A3
|
||||||
|
#define VAR_SAFARI_ZONE_STATE 0x40A4
|
||||||
|
#define VAR_TRICK_HOUSE_ENTRANCE_STATE 0x40A5
|
||||||
|
#define VAR_TRICK_HOUSE_ENTRANCE_STATE_2 0x40A6
|
||||||
|
#define VAR_TRICK_HOUSE_ENTRANCE_STATE_3 0x40A7
|
||||||
|
|
||||||
|
#define VAR_CYCLING_CHALLENGE_STATE 0x40A9
|
||||||
|
#define VAR_SLATEPORT_MUSEUM_1F_STATE 0x40AA
|
||||||
|
#define VAR_TRICK_HOUSE_PUZZLE_1_STATE 0x40AB
|
||||||
|
#define VAR_TRICK_HOUSE_PUZZLE_2_STATE 0x40AC
|
||||||
|
#define VAR_TRICK_HOUSE_PUZZLE_3_STATE 0x40AD
|
||||||
|
#define VAR_TRICK_HOUSE_PUZZLE_4_STATE 0x40AE
|
||||||
|
#define VAR_TRICK_HOUSE_PUZZLE_5_STATE 0x40AF
|
||||||
|
#define VAR_TRICK_HOUSE_PUZZLE_6_STATE 0x40B0
|
||||||
|
#define VAR_TRICK_HOUSE_PUZZLE_7_STATE 0x40B1
|
||||||
|
#define VAR_TRICK_HOUSE_PUZZLE_8_STATE 0x40B2
|
||||||
|
#define VAR_WEATHER_INSTITUTE_STATE 0x40B3
|
||||||
|
#define VAR_PORTHOLE_STATE 0x40B4
|
||||||
|
#define VAR_TRICK_HOUSE_STATE 0x40B5 // TODO: needs some further investigation
|
||||||
|
#define VAR_TRICK_HOUSE_PUZZLE_7_STATE_2 0x40B6
|
||||||
|
#define VAR_SLATEPORT_FAN_CLUB_STATE 0x40B7
|
||||||
|
|
||||||
|
#define VAR_MT_PYRE_STATE 0x40B9
|
||||||
|
#define VAR_NEW_MAUVILLE_STATE 0x40BA
|
||||||
|
|
||||||
|
#define VAR_BRAVO_TRAINER_BATTLE_TOWER_ON 0x40BC
|
||||||
|
#define VAR_JAGGED_PASS_ASH_WEATHER 0x40BD
|
||||||
|
#define VAR_GLASS_WORKSHOP_STATE 0x40BE
|
||||||
|
#define VAR_METEOR_FALLS_STATE 0x40BF
|
||||||
|
#define VAR_GAME_CORNER_STATE 0x40C0
|
||||||
|
#define VAR_TRICK_HOUSE_PRIZE_PICKUP 0x40C1
|
||||||
|
#define VAR_PACIFIDLOG_TM_RECEIVED_DAY 0x40C2
|
||||||
|
#define VAR_VICTORY_ROAD_1F_STATE 0x40C3
|
||||||
|
#define VAR_FOSSIL_RESURRECTION_STATE 0x40C4
|
||||||
|
#define VAR_WHICH_FOSSIL_REVIVED 0x40C5
|
||||||
|
#define VAR_STEVENS_HOUSE_STATE 0x40C6
|
||||||
|
#define VAR_OLDALE_STATE 0x40C7
|
||||||
|
|
||||||
|
// special vars
|
||||||
|
// They are commonly used as parameters to commands, or return values from commands.
|
||||||
|
#define VAR_SPECIAL_0 0x8000
|
||||||
|
#define VAR_SPECIAL_1 0x8001
|
||||||
|
#define VAR_SPECIAL_2 0x8002
|
||||||
|
#define VAR_SPECIAL_3 0x8003
|
||||||
|
#define VAR_SPECIAL_4 0x8004
|
||||||
|
#define VAR_SPECIAL_5 0x8005
|
||||||
|
#define VAR_SPECIAL_6 0x8006
|
||||||
|
#define VAR_SPECIAL_7 0x8007
|
||||||
|
#define VAR_SPECIAL_8 0x8008
|
||||||
|
#define VAR_SPECIAL_9 0x8009
|
||||||
|
#define VAR_SPECIAL_A 0x800A
|
||||||
|
#define VAR_SPECIAL_B 0x800B
|
||||||
|
#define FACING 0x800C
|
||||||
|
#define RESULT 0x800D
|
||||||
|
#define ITEM_ID 0x800E
|
||||||
|
#define LAST_TALKED 0x800F
|
||||||
|
#define CONTEST_RANK 0x8010
|
||||||
|
#define CONTEST_CATEGORY 0x8011
|
||||||
|
|
||||||
|
#endif // GUARD_CONSTANTS_VARS_H
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#ifndef GUARD_FLASH_H
|
||||||
|
#define GUARD_FLASH_H
|
||||||
|
|
||||||
|
#include <gba/gba.h>
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SECTOR_DAMAGED,
|
||||||
|
SECTOR_OK,
|
||||||
|
SECTOR_CHECK, // unused
|
||||||
|
};
|
||||||
|
|
||||||
|
enum MsgBoxUpdateMessage
|
||||||
|
{
|
||||||
|
MSGBOX_WILL_NOW_UPDATE = 0,
|
||||||
|
MSGBOX_HAS_BEEN_UPDATED,
|
||||||
|
MSGBOX_UNABLE_TO_UPDATE,
|
||||||
|
MSGBOX_NO_NEED_TO_UPDATE,
|
||||||
|
MSGBOX_UPDATING
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SaveSector
|
||||||
|
{
|
||||||
|
u8 data[0xFF4];
|
||||||
|
u16 id;
|
||||||
|
u16 checksum;
|
||||||
|
u32 signature;
|
||||||
|
u32 counter;
|
||||||
|
}; // size is 0x1000
|
||||||
|
|
||||||
|
// headless save section?
|
||||||
|
struct UnkSaveSection
|
||||||
|
{
|
||||||
|
u8 data[0xFF4];
|
||||||
|
u32 signature;
|
||||||
|
}; // size is 0xFF8
|
||||||
|
|
||||||
|
#define eSaveSection ((struct SaveSector *)0x2020000)
|
||||||
|
|
||||||
|
#define NUM_SECTORS_PER_SAVE_SLOT 14 // Number of sectors occupied by a save slot
|
||||||
|
#define FILE_SIGNATURE 0x08012025
|
||||||
|
|
||||||
|
#define SAVE_STATUS_EMPTY 0
|
||||||
|
#define SAVE_STATUS_OK 1
|
||||||
|
#define SAVE_STATUS_NO_FLASH 4
|
||||||
|
#define SAVE_STATUS_ERROR 0xFF
|
||||||
|
|
||||||
|
bool32 flash_maincb_ident_is_valid(void);
|
||||||
|
bool8 flash_maincb_read_save(u32);
|
||||||
|
void msg_load_gfx(void);
|
||||||
|
void msg_display(enum MsgBoxUpdateMessage);
|
||||||
|
bool32 flash_maincb_check_need_reset_pacifidlog_tm(void);
|
||||||
|
bool32 flash_maincb_reset_pacifidlog_tm(void);
|
||||||
|
|
||||||
|
#endif //GUARD_FLASH_H
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
#ifndef GUARD_GLOBAL_BERRY_H
|
||||||
|
#define GUARD_GLOBAL_BERRY_H
|
||||||
|
|
||||||
|
struct Berry
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 name[7];
|
||||||
|
/*0x07*/ u8 firmness;
|
||||||
|
/*0x08*/ u16 size;
|
||||||
|
/*0x0A*/ u8 maxYield;
|
||||||
|
/*0x0B*/ u8 minYield;
|
||||||
|
/*0x0C*/ const u8 *description1;
|
||||||
|
/*0x10*/ const u8 *description2;
|
||||||
|
/*0x14*/ u8 stageDuration;
|
||||||
|
/*0x15*/ u8 spicy;
|
||||||
|
/*0x16*/ u8 dry;
|
||||||
|
/*0x17*/ u8 sweet;
|
||||||
|
/*0x18*/ u8 bitter;
|
||||||
|
/*0x19*/ u8 sour;
|
||||||
|
/*0x1A*/ u8 smoothness;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EnigmaBerry
|
||||||
|
{
|
||||||
|
/*0x000*/ struct Berry berry;
|
||||||
|
/*0x01B*/ u8 pic[(6 * 6) * TILE_SIZE_4BPP];
|
||||||
|
/*0x49C*/ u16 palette[16];
|
||||||
|
/*0x4BC*/ u8 description1[45];
|
||||||
|
/*0x4E9*/ u8 description2[45];
|
||||||
|
/*0x516*/ u8 itemEffect[18];
|
||||||
|
/*0x528*/ u8 holdEffect;
|
||||||
|
/*0x529*/ u8 holdEffectParam;
|
||||||
|
/*0x52C*/ u32 checksum;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BattleEnigmaBerry
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 name[7];
|
||||||
|
/*0x07*/ u8 holdEffect;
|
||||||
|
/*0x08*/ u8 itemEffect[18];
|
||||||
|
/*0x1A*/ u8 holdEffectParam;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BerryTree
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 berry;
|
||||||
|
/*0x01*/ u8 stage:7;
|
||||||
|
/*
|
||||||
|
A berry sparkle is a state that a berry tree
|
||||||
|
can be in after growing within the player's
|
||||||
|
viewport.
|
||||||
|
*/
|
||||||
|
/*0x01*/ bool8 growthSparkle:1;
|
||||||
|
/*0x02*/ u16 minutesUntilNextStage;
|
||||||
|
/*0x04*/ u8 berryYield;
|
||||||
|
/*0x05*/ u8 regrowthCount:4;
|
||||||
|
/*0x05*/ u8 watered1:1;
|
||||||
|
/*0x05*/ u8 watered2:1;
|
||||||
|
/*0x05*/ u8 watered3:1;
|
||||||
|
/*0x05*/ u8 watered4:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GUARD_GLOBAL_BERRY_H
|
||||||
@@ -0,0 +1,317 @@
|
|||||||
|
#ifndef GUARD_GLOBAL_FIELDMAP_H
|
||||||
|
#define GUARD_GLOBAL_FIELDMAP_H
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CONNECTION_SOUTH = 1,
|
||||||
|
CONNECTION_NORTH,
|
||||||
|
CONNECTION_WEST,
|
||||||
|
CONNECTION_EAST,
|
||||||
|
CONNECTION_DIVE,
|
||||||
|
CONNECTION_EMERGE
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*TilesetCB)(void);
|
||||||
|
|
||||||
|
struct Tileset
|
||||||
|
{
|
||||||
|
/*0x00*/ bool8 isCompressed;
|
||||||
|
/*0x01*/ bool8 isSecondary;
|
||||||
|
/*0x04*/ void *tiles;
|
||||||
|
/*0x08*/ void *palettes;
|
||||||
|
/*0x0c*/ void *metatiles;
|
||||||
|
/*0x10*/ void *metatileAttributes;
|
||||||
|
/*0x14*/ TilesetCB callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MapLayout
|
||||||
|
{
|
||||||
|
/*0x00*/ s32 width;
|
||||||
|
/*0x04*/ s32 height;
|
||||||
|
/*0x08*/ u16 *border;
|
||||||
|
/*0x0c*/ u16 *map;
|
||||||
|
/*0x10*/ struct Tileset *primaryTileset;
|
||||||
|
/*0x14*/ struct Tileset *secondaryTileset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BackupMapLayout
|
||||||
|
{
|
||||||
|
s32 width;
|
||||||
|
s32 height;
|
||||||
|
u16 *map;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventObjectTemplate
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 localId;
|
||||||
|
/*0x01*/ u8 graphicsId;
|
||||||
|
/*0x02*/ u8 unk2;
|
||||||
|
/*0x04*/ s16 x;
|
||||||
|
/*0x06*/ s16 y;
|
||||||
|
/*0x08*/ u8 elevation;
|
||||||
|
/*0x09*/ u8 movementType;
|
||||||
|
/*0x0A*/ u8 movementRangeX:4;
|
||||||
|
u8 movementRangeY:4;
|
||||||
|
/*0x0C*/ u16 trainerType;
|
||||||
|
/*0x0E*/ u16 trainerRange_berryTreeId;
|
||||||
|
/*0x10*/ u8 *script;
|
||||||
|
/*0x14*/ u16 flagId;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WarpEvent
|
||||||
|
{
|
||||||
|
s16 x, y;
|
||||||
|
u8 elevation;
|
||||||
|
u8 warpId;
|
||||||
|
u8 mapNum;
|
||||||
|
u8 mapGroup;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CoordEvent
|
||||||
|
{
|
||||||
|
s16 x, y;
|
||||||
|
u8 elevation;
|
||||||
|
u16 trigger;
|
||||||
|
u16 index;
|
||||||
|
u8 filler_A[0x2];
|
||||||
|
u8 *script;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BgEvent
|
||||||
|
{
|
||||||
|
/*0x00*/u16 x;
|
||||||
|
/*0x02*/u16 y;
|
||||||
|
/*0x04*/u8 elevation;
|
||||||
|
/*0x05*/u8 kind;
|
||||||
|
/*0x08*/union { // carried over from diego's FR/LG work, seems to be the same struct
|
||||||
|
// in gen 3, "kind" (0x3 in BgEvent struct) determines the method to read the union.
|
||||||
|
u8 *script;
|
||||||
|
|
||||||
|
// hidden item type
|
||||||
|
struct {
|
||||||
|
u16 item;
|
||||||
|
u16 hiddenItemId; // flag offset to determine flag lookup
|
||||||
|
} hiddenItem;
|
||||||
|
|
||||||
|
// secret base type
|
||||||
|
u32 secretBaseId;
|
||||||
|
|
||||||
|
} bgUnion;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MapEvents
|
||||||
|
{
|
||||||
|
u8 eventObjectCount;
|
||||||
|
u8 warpCount;
|
||||||
|
u8 coordEventCount;
|
||||||
|
u8 bgEventCount;
|
||||||
|
|
||||||
|
struct EventObjectTemplate *eventObjects;
|
||||||
|
struct WarpEvent *warps;
|
||||||
|
struct CoordEvent *coordEvents;
|
||||||
|
struct BgEvent *bgEvents;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MapConnection
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 direction;
|
||||||
|
/*0x01*/ u32 offset;
|
||||||
|
/*0x05*/ u8 mapGroup;
|
||||||
|
/*0x06*/ u8 mapNum;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MapConnections
|
||||||
|
{
|
||||||
|
s32 count;
|
||||||
|
struct MapConnection *connections;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MapHeader
|
||||||
|
{
|
||||||
|
/* 0x00 */ struct MapLayout *mapLayout;
|
||||||
|
/* 0x04 */ struct MapEvents *events;
|
||||||
|
/* 0x08 */ u8 *mapScripts;
|
||||||
|
/* 0x0C */ struct MapConnections *connections;
|
||||||
|
/* 0x10 */ u16 music;
|
||||||
|
/* 0x12 */ u16 mapLayoutId;
|
||||||
|
/* 0x14 */ u8 regionMapSectionId;
|
||||||
|
/* 0x15 */ u8 cave;
|
||||||
|
/* 0x16 */ u8 weather;
|
||||||
|
/* 0x17 */ u8 mapType;
|
||||||
|
/* 0x18 */ u8 filler_18;
|
||||||
|
/* 0x19 */ u8 escapeRope;
|
||||||
|
/* 0x1A */ u8 flags;
|
||||||
|
/* 0x1B */ u8 battleType;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventObject
|
||||||
|
{
|
||||||
|
/*0x00*/ u32 active:1;
|
||||||
|
u32 singleMovementActive:1;
|
||||||
|
u32 triggerGroundEffectsOnMove:1;
|
||||||
|
u32 triggerGroundEffectsOnStop:1;
|
||||||
|
u32 disableCoveringGroundEffects:1; // disables ground effects that cover parts of the object's sprite
|
||||||
|
u32 landingJump:1;
|
||||||
|
u32 heldMovementActive:1;
|
||||||
|
u32 heldMovementFinished:1;
|
||||||
|
/*0x01*/ u32 frozen:1;
|
||||||
|
u32 facingDirectionLocked:1;
|
||||||
|
u32 disableAnim:1; // used to disable forced movement sliding animations (like on ice)
|
||||||
|
u32 enableAnim:1;
|
||||||
|
u32 inanimate:1;
|
||||||
|
u32 invisible:1;
|
||||||
|
u32 offScreen:1;
|
||||||
|
u32 trackedByCamera:1; // only set for the player object
|
||||||
|
/*0x02*/ u32 isPlayer:1;
|
||||||
|
u32 hasReflection:1;
|
||||||
|
u32 inShortGrass:1;
|
||||||
|
u32 inShallowFlowingWater:1;
|
||||||
|
u32 inSandPile:1;
|
||||||
|
u32 inHotSprings:1;
|
||||||
|
u32 hasShadow:1;
|
||||||
|
u32 spriteAnimPausedBackup:1;
|
||||||
|
/*0x03*/ u32 spriteAffineAnimPausedBackup:1;
|
||||||
|
u32 disableJumpLandingGroundEffect:1;
|
||||||
|
u32 fixedPriority:1;
|
||||||
|
/*0x04*/ u8 spriteId;
|
||||||
|
/*0x05*/ u8 graphicsId;
|
||||||
|
/*0x06*/ u8 movementType;
|
||||||
|
/*0x07*/ u8 trainerType;
|
||||||
|
/*0x08*/ u8 localId;
|
||||||
|
/*0x09*/ u8 mapNum;
|
||||||
|
/*0x0A*/ u8 mapGroup;
|
||||||
|
/*0x0B*/ u8 currentElevation:4;
|
||||||
|
u8 previousElevation:4;
|
||||||
|
/*0x0C*/ struct Coords16 initialCoords;
|
||||||
|
/*0x10*/ struct Coords16 currentCoords;
|
||||||
|
/*0x14*/ struct Coords16 previousCoords;
|
||||||
|
/*0x18*/ u8 facingDirection:4;
|
||||||
|
/*0x18*/ u8 movementDirection:4;
|
||||||
|
/*0x19*/ union __attribute__((packed)) {
|
||||||
|
u8 as_byte;
|
||||||
|
struct __attribute__((packed)) {
|
||||||
|
u16 x:4;
|
||||||
|
u16 y:4;
|
||||||
|
} as_nybbles;
|
||||||
|
} range;
|
||||||
|
/*0x1A*/ u8 fieldEffectSpriteId;
|
||||||
|
/*0x1B*/ u8 warpArrowSpriteId;
|
||||||
|
/*0x1C*/ u8 movementActionId;
|
||||||
|
/*0x1D*/ u8 trainerRange_berryTreeId;
|
||||||
|
/*0x1E*/ u8 currentMetatileBehavior;
|
||||||
|
/*0x1F*/ u8 previousMetatileBehavior;
|
||||||
|
/*0x20*/ u8 previousMovementDirection;
|
||||||
|
/*0x21*/ u8 directionSequenceIndex;
|
||||||
|
/*0x22*/ u8 playerCopyableMovement; // used as an index to gCopyPlayerMovementFuncs for the "copy player" movement types
|
||||||
|
/*size = 0x24*/
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventObjectGraphicsInfo
|
||||||
|
{
|
||||||
|
/*0x00*/ u16 tileTag;
|
||||||
|
/*0x02*/ u16 paletteTag;
|
||||||
|
/*0x04*/ u16 bridgeReflectionPaletteTag;
|
||||||
|
/*0x06*/ u16 size;
|
||||||
|
/*0x08*/ s16 width;
|
||||||
|
/*0x0A*/ s16 height;
|
||||||
|
/*0x0C*/ u8 paletteSlot:4;
|
||||||
|
u8 shadowSize:2;
|
||||||
|
u8 inanimate:1;
|
||||||
|
u8 disableReflectionPaletteLoad:1;
|
||||||
|
/*0x0D*/ u8 tracks;
|
||||||
|
/*0x10*/ const struct OamData *oam;
|
||||||
|
/*0x14*/ const struct SubspriteTable *subspriteTables;
|
||||||
|
/*0x18*/ const union AnimCmd *const *anims;
|
||||||
|
/*0x1C*/ const struct SpriteFrameImage *images;
|
||||||
|
/*0x20*/ const union AffineAnimCmd *const *affineAnims;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PLAYER_AVATAR_FLAG_ON_FOOT (1 << 0)
|
||||||
|
#define PLAYER_AVATAR_FLAG_MACH_BIKE (1 << 1)
|
||||||
|
#define PLAYER_AVATAR_FLAG_ACRO_BIKE (1 << 2)
|
||||||
|
#define PLAYER_AVATAR_FLAG_SURFING (1 << 3)
|
||||||
|
#define PLAYER_AVATAR_FLAG_UNDERWATER (1 << 4)
|
||||||
|
#define PLAYER_AVATAR_FLAG_5 (1 << 5)
|
||||||
|
#define PLAYER_AVATAR_FLAG_6 (1 << 6)
|
||||||
|
#define PLAYER_AVATAR_FLAG_DASH (1 << 7)
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ACRO_BIKE_NORMAL,
|
||||||
|
ACRO_BIKE_TURNING,
|
||||||
|
ACRO_BIKE_WHEELIE_STANDING,
|
||||||
|
ACRO_BIKE_BUNNY_HOP,
|
||||||
|
ACRO_BIKE_WHEELIE_MOVING,
|
||||||
|
ACRO_BIKE_STATE5,
|
||||||
|
ACRO_BIKE_STATE6,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
DIR_NONE,
|
||||||
|
DIR_SOUTH,
|
||||||
|
DIR_NORTH,
|
||||||
|
DIR_WEST,
|
||||||
|
DIR_EAST,
|
||||||
|
DIR_SOUTHWEST,
|
||||||
|
DIR_SOUTHEAST,
|
||||||
|
DIR_NORTHWEST,
|
||||||
|
DIR_NORTHEAST,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
COLLISION_LEDGE_JUMP = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
// player running states
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
NOT_MOVING,
|
||||||
|
TURN_DIRECTION, // not the same as turning! turns your avatar without moving. also known as a turn frame in some circles
|
||||||
|
MOVING,
|
||||||
|
};
|
||||||
|
|
||||||
|
// player tile transition states
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
T_NOT_MOVING,
|
||||||
|
T_TILE_TRANSITION,
|
||||||
|
T_TILE_CENTER, // player is on a frame in which they are centered on a tile during which the player either stops or keeps their momentum and keeps going, changing direction if necessary.
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PlayerAvatar /* 0x202E858 */
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 flags;
|
||||||
|
/*0x01*/ u8 unk1; // used to be named bike, but its definitely not that. seems to be some transition flags
|
||||||
|
/*0x02*/ u8 runningState; // this is a static running state. 00 is not moving, 01 is turn direction, 02 is moving.
|
||||||
|
/*0x03*/ u8 tileTransitionState; // this is a transition running state: 00 is not moving, 01 is transition between tiles, 02 means you are on the frame in which you have centered on a tile but are about to keep moving, even if changing directions. 2 is also used for a ledge hop, since you are transitioning.
|
||||||
|
/*0x04*/ u8 spriteId;
|
||||||
|
/*0x05*/ u8 eventObjectId;
|
||||||
|
/*0x06*/ bool8 preventStep;
|
||||||
|
/*0x07*/ u8 gender;
|
||||||
|
/*0x08*/ u8 acroBikeState; // 00 is normal, 01 is turning, 02 is standing wheelie, 03 is hopping wheelie
|
||||||
|
/*0x09*/ u8 newDirBackup; // during bike movement, the new direction as opposed to player's direction is backed up here.
|
||||||
|
/*0x0A*/ u8 bikeFrameCounter; // on the mach bike, when this value is 1, the bike is moving but not accelerating yet for 1 tile. on the acro bike, this acts as a timer for acro bike.
|
||||||
|
/*0x0B*/ u8 bikeSpeed;
|
||||||
|
// acro bike only
|
||||||
|
/*0x0C*/ u32 directionHistory; // up/down/left/right history is stored in each nybble, but using the field directions and not the io inputs.
|
||||||
|
/*0x10*/ u32 abStartSelectHistory; // same as above but for A + B + start + select only
|
||||||
|
// these two are timer history arrays which [0] is the active timer for acro bike. every element is backed up to the next element upon update.
|
||||||
|
/*0x14*/ u8 dirTimerHistory[8];
|
||||||
|
/*0x1C*/ u8 abStartSelectTimerHistory[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Camera
|
||||||
|
{
|
||||||
|
bool8 active:1;
|
||||||
|
s32 x;
|
||||||
|
s32 y;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct EventObject gEventObjects[];
|
||||||
|
extern u8 gSelectedEventObject;
|
||||||
|
extern struct MapHeader gMapHeader;
|
||||||
|
extern struct PlayerAvatar gPlayerAvatar;
|
||||||
|
|
||||||
|
#endif // GUARD_GLOBAL_FIELDMAP_H
|
||||||
@@ -0,0 +1,875 @@
|
|||||||
|
#ifndef GUARD_GLOBAL_H
|
||||||
|
#define GUARD_GLOBAL_H
|
||||||
|
|
||||||
|
#include <gba/gba.h>
|
||||||
|
|
||||||
|
// global.h from pokemon ruby
|
||||||
|
|
||||||
|
// IDE support
|
||||||
|
#if defined(__APPLE__) || defined(__CYGWIN__)
|
||||||
|
#define _(x) x
|
||||||
|
#define __(x) x
|
||||||
|
#define INCBIN(x) {0}
|
||||||
|
#define INCBIN_U8 INCBIN
|
||||||
|
#define INCBIN_U16 INCBIN
|
||||||
|
#define INCBIN_U32 INCBIN
|
||||||
|
#define INCBIN_S8 INCBIN
|
||||||
|
#define INCBIN_S16 INCBIN
|
||||||
|
#define INCBIN_S32 INCBIN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Prevent cross-jump optimization.
|
||||||
|
#define BLOCK_CROSS_JUMP asm("");
|
||||||
|
|
||||||
|
// to help in decompiling
|
||||||
|
#define asm_comment(x) asm volatile("@ -- " x " -- ")
|
||||||
|
|
||||||
|
#define asm_unified(x) asm(".syntax unified\n" x "\n.syntax divided\n")
|
||||||
|
|
||||||
|
#define ARRAY_COUNT(array) (sizeof(array) / sizeof((array)[0]))
|
||||||
|
|
||||||
|
|
||||||
|
#define POKEMON_SLOTS_NUMBER 412
|
||||||
|
#define POKEMON_NAME_LENGTH 10
|
||||||
|
#define OT_NAME_LENGTH 7
|
||||||
|
|
||||||
|
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
#define max(a, b) ((a) >= (b) ? (a) : (b))
|
||||||
|
|
||||||
|
// why does GF hate 2d arrays
|
||||||
|
#define MULTI_DIM_ARR(x, dim, y) ((x) * dim + (y))
|
||||||
|
|
||||||
|
// dim access enums
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
B_8 = 1,
|
||||||
|
B_16 = 2,
|
||||||
|
B_32 = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
// There are many quirks in the source code which have overarching behavioral differences from
|
||||||
|
// a number of other files. For example, diploma.c seems to declare rodata before each use while
|
||||||
|
// other files declare out of order and must be at the beginning. There are also a number of
|
||||||
|
// macros which differ from one file to the next due to the method of obtaining the result, such
|
||||||
|
// as these below. Because of this, there is a theory (Two Team Theory) that states that these
|
||||||
|
// programming projects had more than 1 "programming team" which utilized different macros for
|
||||||
|
// each of the files that were worked on.
|
||||||
|
#define T1_READ_8(ptr) ((ptr)[0])
|
||||||
|
#define T1_READ_16(ptr) ((ptr)[0] | ((ptr)[1] << 8))
|
||||||
|
#define T1_READ_32(ptr) ((ptr)[0] | ((ptr)[1] << 8) | ((ptr)[2] << 16) | ((ptr)[3] << 24))
|
||||||
|
#define T1_READ_PTR(ptr) (u8*) T1_READ_32(ptr)
|
||||||
|
|
||||||
|
// T2_READ_8 is a duplicate to remain consistent with each group.
|
||||||
|
#define T2_READ_8(ptr) ((ptr)[0])
|
||||||
|
#define T2_READ_16(ptr) ((ptr)[0] + ((ptr)[1] << 8))
|
||||||
|
#define T2_READ_32(ptr) ((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24))
|
||||||
|
#define T2_READ_PTR(ptr) (void*) T2_READ_32(ptr)
|
||||||
|
|
||||||
|
// Credits to Made (dolphin emoji)
|
||||||
|
#define S16TOPOSFLOAT(val) \
|
||||||
|
({ \
|
||||||
|
s16 v = (val); \
|
||||||
|
float f = (float)v; \
|
||||||
|
if(v < 0) f += 65536.0f; \
|
||||||
|
f; \
|
||||||
|
})
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
VERSION_SAPPHIRE = 1,
|
||||||
|
VERSION_RUBY = 2,
|
||||||
|
VERSION_EMERALD = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LanguageId
|
||||||
|
{
|
||||||
|
LANGUAGE_JAPANESE = 1,
|
||||||
|
LANGUAGE_ENGLISH = 2,
|
||||||
|
LANGUAGE_GERMAN = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
// capacities of various saveblock objects
|
||||||
|
#define DAYCARE_MON_COUNT 2
|
||||||
|
#define POKEBLOCKS_COUNT 40
|
||||||
|
#define PARTY_SIZE 6
|
||||||
|
#define EVENT_OBJECTS_COUNT 16
|
||||||
|
#define BERRY_TREES_COUNT 128
|
||||||
|
#define FLAGS_COUNT 288
|
||||||
|
#define VARS_COUNT 256
|
||||||
|
#define MAIL_COUNT 16
|
||||||
|
#define SECRET_BASES_COUNT 20
|
||||||
|
#define TV_SHOWS_COUNT 25
|
||||||
|
#define POKE_NEWS_COUNT 16
|
||||||
|
#define PC_ITEMS_COUNT 50
|
||||||
|
#define BAG_ITEMS_COUNT 20
|
||||||
|
#define BAG_KEYITEMS_COUNT 20
|
||||||
|
#define BAG_POKEBALLS_COUNT 16
|
||||||
|
#define BAG_TMHM_COUNT 64
|
||||||
|
#define BAG_BERRIES_COUNT 46
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
MALE,
|
||||||
|
FEMALE
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
OPTIONS_BUTTON_MODE_NORMAL,
|
||||||
|
OPTIONS_BUTTON_MODE_LR,
|
||||||
|
OPTIONS_BUTTON_MODE_L_EQUALS_A
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
OPTIONS_TEXT_SPEED_SLOW,
|
||||||
|
OPTIONS_TEXT_SPEED_MID,
|
||||||
|
OPTIONS_TEXT_SPEED_FAST
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
OPTIONS_SOUND_MONO,
|
||||||
|
OPTIONS_SOUND_STEREO
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
OPTIONS_BATTLE_STYLE_SHIFT,
|
||||||
|
OPTIONS_BATTLE_STYLE_SET
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
BAG_ITEMS = 1,
|
||||||
|
BAG_POKEBALLS,
|
||||||
|
BAG_TMsHMs,
|
||||||
|
BAG_BERRIES,
|
||||||
|
BAG_KEYITEMS
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Coords16
|
||||||
|
{
|
||||||
|
s16 x;
|
||||||
|
s16 y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UCoords16
|
||||||
|
{
|
||||||
|
u16 x;
|
||||||
|
u16 y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SecretBaseRecord
|
||||||
|
{
|
||||||
|
/*0x1A08*/ u8 secretBaseId;
|
||||||
|
/*0x1A09*/ u8 sbr_field_1_0:4;
|
||||||
|
/*0x1A09*/ u8 gender:1;
|
||||||
|
/*0x1A09*/ u8 sbr_field_1_5:1;
|
||||||
|
/*0x1A09*/ u8 sbr_field_1_6:2;
|
||||||
|
/*0x1A0A*/ u8 playerName[OT_NAME_LENGTH];
|
||||||
|
/*0x1A11*/ u8 trainerId[4]; // byte 0 is used for determining trainer class
|
||||||
|
/*0x1A16*/ u16 sbr_field_e;
|
||||||
|
/*0x1A18*/ u8 sbr_field_10;
|
||||||
|
/*0x1A19*/ u8 sbr_field_11;
|
||||||
|
/*0x1A1A*/ u8 decorations[16];
|
||||||
|
/*0x1A2A*/ u8 decorationPos[16];
|
||||||
|
/*0x1A3C*/ u32 partyPersonality[6];
|
||||||
|
/*0x1A54*/ u16 partyMoves[6 * 4];
|
||||||
|
/*0x1A84*/ u16 partySpecies[6];
|
||||||
|
/*0x1A90*/ u16 partyHeldItems[6];
|
||||||
|
/*0x1A9C*/ u8 partyLevels[6];
|
||||||
|
/*0x1AA2*/ u8 partyEVs[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "constants/game_stat.h"
|
||||||
|
#include "global.fieldmap.h"
|
||||||
|
#include "global.berry.h"
|
||||||
|
#include "pokemon.h"
|
||||||
|
|
||||||
|
struct WarpData
|
||||||
|
{
|
||||||
|
s8 mapGroup;
|
||||||
|
s8 mapNum;
|
||||||
|
s8 warpId;
|
||||||
|
s16 x, y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ItemSlot
|
||||||
|
{
|
||||||
|
u16 itemId;
|
||||||
|
u16 quantity;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Pokeblock
|
||||||
|
{
|
||||||
|
u8 color;
|
||||||
|
u8 spicy;
|
||||||
|
u8 dry;
|
||||||
|
u8 sweet;
|
||||||
|
u8 bitter;
|
||||||
|
u8 sour;
|
||||||
|
u8 feel;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Roamer
|
||||||
|
{
|
||||||
|
/*0x00*/ u32 ivs;
|
||||||
|
/*0x04*/ u32 personality;
|
||||||
|
/*0x08*/ u16 species;
|
||||||
|
/*0x0A*/ u16 hp;
|
||||||
|
/*0x0C*/ u8 level;
|
||||||
|
/*0x0D*/ u8 status;
|
||||||
|
/*0x0E*/ u8 cool;
|
||||||
|
/*0x0F*/ u8 beauty;
|
||||||
|
/*0x10*/ u8 cute;
|
||||||
|
/*0x11*/ u8 smart;
|
||||||
|
/*0x12*/ u8 tough;
|
||||||
|
/*0x13*/ bool8 active;
|
||||||
|
/*0x14*/ u8 filler[0x8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RamScriptData
|
||||||
|
{
|
||||||
|
u8 magic;
|
||||||
|
u8 mapGroup;
|
||||||
|
u8 mapNum;
|
||||||
|
u8 objectId;
|
||||||
|
u8 script[995];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RamScript
|
||||||
|
{
|
||||||
|
u32 checksum;
|
||||||
|
struct RamScriptData data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EasyChatPair
|
||||||
|
{
|
||||||
|
u16 unk0_0:7;
|
||||||
|
u16 unk0_7:7;
|
||||||
|
u16 unk1_6:1;
|
||||||
|
u16 unk2;
|
||||||
|
u16 words[2];
|
||||||
|
}; /*size = 0x8*/
|
||||||
|
|
||||||
|
struct TVShowCommon
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 kind;
|
||||||
|
/*0x01*/ bool8 active;
|
||||||
|
/*0x02*/ u8 pad02[20];
|
||||||
|
/*0x16*/ u16 var16[3];
|
||||||
|
/*0x1C*/ u8 srcTrainerId3Lo;
|
||||||
|
/*0x1D*/ u8 srcTrainerId3Hi;
|
||||||
|
/*0x1E*/ u8 srcTrainerId2Lo;
|
||||||
|
/*0x1F*/ u8 srcTrainerId2Hi;
|
||||||
|
/*0x20*/ u8 srcTrainerIdLo;
|
||||||
|
/*0x21*/ u8 srcTrainerIdHi;
|
||||||
|
/*0x22*/ u8 trainerIdLo;
|
||||||
|
/*0x23*/ u8 trainerIdHi;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TVShowFanClubLetter
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 kind;
|
||||||
|
/*0x01*/ bool8 active;
|
||||||
|
/*0x02*/ u16 species;
|
||||||
|
/*0x04*/ u16 pad04[6];
|
||||||
|
/*0x10*/ u8 playerName[8];
|
||||||
|
/*0x18*/ u8 language;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TVShowRecentHappenings
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 kind;
|
||||||
|
/*0x01*/ bool8 active;
|
||||||
|
/*0x02*/ u16 var02;
|
||||||
|
/*0x04*/ u16 var04[6];
|
||||||
|
/*0x10*/ u8 playerName[8];
|
||||||
|
/*0x18*/ u8 language;
|
||||||
|
/*0x19*/ u8 pad19[10];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TVShowFanclubOpinions
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 kind;
|
||||||
|
/*0x01*/ bool8 active;
|
||||||
|
/*0x02*/ u16 var02;
|
||||||
|
/*0x04*/ u8 var04A:4;
|
||||||
|
/*0x04*/ u8 var04B:4;
|
||||||
|
/*0x05*/ u8 playerName[8];
|
||||||
|
/*0x0D*/ u8 language;
|
||||||
|
/*0x0E*/ u8 var0E;
|
||||||
|
/*0x0F*/ u8 var0F;
|
||||||
|
/*0x10*/ u8 var10[8];
|
||||||
|
/*0x18*/ u16 var18[2];
|
||||||
|
/*0x1C*/ u16 var1C[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TVShowUnknownType04
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 kind;
|
||||||
|
/*0x01*/ bool8 active;
|
||||||
|
/*0x02*/ u8 pad02[4];
|
||||||
|
/*0x06*/ u16 var06;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TVShowNameRaterShow
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 kind;
|
||||||
|
/*0x01*/ bool8 active;
|
||||||
|
/*0x02*/ u16 species;
|
||||||
|
/*0x04*/ u8 pokemonName[11];
|
||||||
|
/*0x0F*/ u8 trainerName[11];
|
||||||
|
/*0x1A*/ u8 random;
|
||||||
|
/*0x1B*/ u8 random2;
|
||||||
|
/*0x1C*/ u16 var1C;
|
||||||
|
/*0x1E*/ u8 language;
|
||||||
|
/*0x1F*/ u8 pokemonNameLanguage;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TVShowBravoTrainerPokemonProfiles
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 kind;
|
||||||
|
/*0x01*/ bool8 active;
|
||||||
|
/*0x02*/ u16 species;
|
||||||
|
/*0x04*/ u16 var04[2];
|
||||||
|
/*0x08*/ u8 pokemonNickname[11];
|
||||||
|
/*0x13*/ u8 contestCategory:3;
|
||||||
|
/*0x13*/ u8 contestRank:2;
|
||||||
|
/*0x13*/ u8 contestResult:2;
|
||||||
|
/*0x13*/ u8 var13_7:1;
|
||||||
|
/*0x14*/ u16 var14;
|
||||||
|
/*0x16*/ u8 playerName[8];
|
||||||
|
/*0x1E*/ u8 language;
|
||||||
|
/*0x1F*/ u8 var1f;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TVShowBravoTrainerBattleTowerSpotlight
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 kind;
|
||||||
|
/*0x01*/ bool8 active;
|
||||||
|
/*0x02*/ u8 trainerName[8];
|
||||||
|
/*0x0A*/ u16 species;
|
||||||
|
/*0x0C*/ u8 enemyTrainerName[8];
|
||||||
|
/*0x14*/ u16 defeatedSpecies;
|
||||||
|
/*0x16*/ u16 var16;
|
||||||
|
/*0x18*/ u16 var18[1];
|
||||||
|
/*0x1A*/ u8 btLevel;
|
||||||
|
/*0x1B*/ u8 var1b;
|
||||||
|
/*0x1C*/ u8 var1c;
|
||||||
|
/*0x1D*/ u8 language;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TVShowPokemonToday
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 kind;
|
||||||
|
/*0x01*/ bool8 active;
|
||||||
|
/*0x02*/ u8 language;
|
||||||
|
/*0x03*/ u8 language2;
|
||||||
|
/*0x04*/ u8 nickname[11];
|
||||||
|
/*0x0F*/ u8 ball;
|
||||||
|
/*0x10*/ u16 species;
|
||||||
|
/*0x12*/ u8 var12;
|
||||||
|
/*0x13*/ u8 playerName[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TVShowSmartShopper
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 kind;
|
||||||
|
/*0x01*/ bool8 active;
|
||||||
|
/*0x02*/ u8 priceReduced;
|
||||||
|
/*0x03*/ u8 language;
|
||||||
|
/*0x04*/ u8 pad04[2];
|
||||||
|
/*0x06*/ u16 itemIds[3];
|
||||||
|
/*0x0C*/ u16 itemAmounts[3];
|
||||||
|
/*0x12*/ u8 shopLocation;
|
||||||
|
/*0x13*/ u8 playerName[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TVShowPokemonTodayFailed
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 kind;
|
||||||
|
/*0x01*/ bool8 active;
|
||||||
|
/*0x02*/ u8 language;
|
||||||
|
/*0x03*/ u8 pad03[9];
|
||||||
|
/*0x0c*/ u16 species;
|
||||||
|
/*0x0e*/ u16 species2;
|
||||||
|
/*0x10*/ u8 var10;
|
||||||
|
/*0x11*/ u8 var11;
|
||||||
|
/*0x12*/ u8 var12;
|
||||||
|
/*0x13*/ u8 playerName[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TVShowPokemonAngler
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 kind;
|
||||||
|
/*0x01*/ bool8 active;
|
||||||
|
/*0x02*/ u8 var02;
|
||||||
|
/*0x03*/ u8 var03;
|
||||||
|
/*0x04*/ u16 var04;
|
||||||
|
/*0x06*/ u8 language;
|
||||||
|
u8 pad07[12];
|
||||||
|
/*0x13*/ u8 playerName[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TVShowWorldOfMasters
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 kind;
|
||||||
|
/*0x01*/ bool8 active;
|
||||||
|
/*0x02*/ u16 var02;
|
||||||
|
/*0x04*/ u16 var04;
|
||||||
|
/*0x06*/ u16 var06;
|
||||||
|
/*0x08*/ u16 var08;
|
||||||
|
/*0x0a*/ u8 var0a;
|
||||||
|
/*0x0b*/ u8 language;
|
||||||
|
u8 pad0c[7];
|
||||||
|
/*0x13*/ u8 playerName[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TVShowMassOutbreak
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 kind;
|
||||||
|
/*0x01*/ bool8 active;
|
||||||
|
/*0x02*/ u8 var02;
|
||||||
|
/*0x03*/ u8 var03;
|
||||||
|
/*0x04*/ u16 moves[4];
|
||||||
|
/*0x0C*/ u16 species;
|
||||||
|
/*0x0E*/ u16 var0E;
|
||||||
|
/*0x10*/ u8 locationMapNum;
|
||||||
|
/*0x11*/ u8 locationMapGroup;
|
||||||
|
/*0x12*/ u8 var12;
|
||||||
|
/*0x13*/ u8 probability;
|
||||||
|
/*0x14*/ u8 level;
|
||||||
|
/*0x15*/ u8 var15;
|
||||||
|
/*0x16*/ u16 daysLeft;
|
||||||
|
/*0x18*/ u8 language;
|
||||||
|
u8 pad19[11];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union TVShow
|
||||||
|
{
|
||||||
|
struct TVShowCommon common;
|
||||||
|
struct TVShowFanClubLetter fanclubLetter;
|
||||||
|
struct TVShowRecentHappenings recentHappenings;
|
||||||
|
struct TVShowFanclubOpinions fanclubOpinions;
|
||||||
|
struct TVShowUnknownType04 unkShow04;
|
||||||
|
struct TVShowNameRaterShow nameRaterShow;
|
||||||
|
struct TVShowBravoTrainerPokemonProfiles bravoTrainer;
|
||||||
|
struct TVShowBravoTrainerBattleTowerSpotlight bravoTrainerTower;
|
||||||
|
struct TVShowPokemonToday pokemonToday;
|
||||||
|
struct TVShowSmartShopper smartshopperShow;
|
||||||
|
struct TVShowPokemonTodayFailed pokemonTodayFailed;
|
||||||
|
struct TVShowPokemonAngler pokemonAngler;
|
||||||
|
struct TVShowWorldOfMasters worldOfMasters;
|
||||||
|
struct TVShowMassOutbreak massOutbreak;
|
||||||
|
} TVShow;
|
||||||
|
|
||||||
|
struct MailStruct
|
||||||
|
{
|
||||||
|
/*0x00*/ u16 words[9];
|
||||||
|
/*0x12*/ u8 playerName[8];
|
||||||
|
/*0x1A*/ u8 trainerId[4];
|
||||||
|
/*0x1E*/ u16 species;
|
||||||
|
/*0x20*/ u16 itemId;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Mauville Pokemon Center men
|
||||||
|
|
||||||
|
struct MauvilleManCommon
|
||||||
|
{
|
||||||
|
u8 id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MauvilleManBard
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 id;
|
||||||
|
/*0x02*/ u16 songLyrics[6];
|
||||||
|
/*0x0E*/ u16 temporaryLyrics[6];
|
||||||
|
/*0x1A*/ u8 playerName[8];
|
||||||
|
/*0x22*/ u8 filler_2DB6[0x3];
|
||||||
|
/*0x25*/ u8 playerTrainerId[4];
|
||||||
|
/*0x29*/ bool8 hasChangedSong;
|
||||||
|
}; /*size = 0x2C*/
|
||||||
|
|
||||||
|
struct MauvilleManHipster
|
||||||
|
{
|
||||||
|
u8 id;
|
||||||
|
bool8 alreadySpoken;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MauvilleManTrader
|
||||||
|
{
|
||||||
|
u8 id;
|
||||||
|
u8 unk1[4];
|
||||||
|
u8 unk5[4][11];
|
||||||
|
bool8 alreadyTraded;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MauvilleManStoryteller
|
||||||
|
{
|
||||||
|
u8 id;
|
||||||
|
bool8 alreadyRecorded;
|
||||||
|
u8 filler2[2];
|
||||||
|
u8 gameStatIDs[4];
|
||||||
|
u8 trainerNames[4][7];
|
||||||
|
u8 statValues[4][4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MauvilleManGiddy
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 id;
|
||||||
|
/*0x01*/ u8 taleCounter;
|
||||||
|
/*0x02*/ u8 questionNum;
|
||||||
|
/*0x04*/ u16 randomWords[10];
|
||||||
|
/*0x18*/ u8 questionList[12];
|
||||||
|
}; /*size = 0x2C*/
|
||||||
|
|
||||||
|
|
||||||
|
union MauvilleMan
|
||||||
|
{
|
||||||
|
struct MauvilleManCommon common;
|
||||||
|
struct MauvilleManBard bard;
|
||||||
|
struct MauvilleManHipster hipster;
|
||||||
|
struct MauvilleManTrader trader;
|
||||||
|
struct MauvilleManStoryteller storyteller;
|
||||||
|
struct MauvilleManGiddy giddy;
|
||||||
|
u8 filler[0x40]; // needed to pad out the struct
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PokeNews
|
||||||
|
{
|
||||||
|
u8 kind;
|
||||||
|
u8 state;
|
||||||
|
u16 days;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GabbyAndTyData
|
||||||
|
{
|
||||||
|
/*2b10*/ u16 mon1;
|
||||||
|
/*2b12*/ u16 mon2;
|
||||||
|
/*2b14*/ u16 lastMove;
|
||||||
|
/*2b16*/ u16 quote;
|
||||||
|
/*2b18*/ u8 mapnum;
|
||||||
|
/*2b19*/ u8 battleNum;
|
||||||
|
/*2b1a*/ u8 valA_0:1;
|
||||||
|
/*2b1a*/ u8 valA_1:1;
|
||||||
|
/*2b1a*/ u8 valA_2:1;
|
||||||
|
/*2b1a*/ u8 valA_3:1;
|
||||||
|
/*2b1a*/ u8 valA_4:1;
|
||||||
|
/*2b1a*/ u8 valA_5:3;
|
||||||
|
/*2b1b*/ u8 valB_0:1;
|
||||||
|
/*2b1b*/ u8 valB_1:1;
|
||||||
|
/*2b1b*/ u8 valB_2:1;
|
||||||
|
/*2b1b*/ u8 valB_3:1;
|
||||||
|
/*2b1b*/ u8 valB_4:1;
|
||||||
|
/*2b1b*/ u8 valB_5:3;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DayCareMail
|
||||||
|
{
|
||||||
|
/*0x00*/ struct MailStruct message;
|
||||||
|
/*0x24*/ u8 names[19];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DayCareStepCountersEtc {
|
||||||
|
u32 steps[DAYCARE_MON_COUNT];
|
||||||
|
u16 pendingEggPersonality;
|
||||||
|
u8 eggCycleStepsRemaining;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RecordMixingDayCareMail
|
||||||
|
{
|
||||||
|
struct DayCareMail mail[DAYCARE_MON_COUNT];
|
||||||
|
u32 numDaycareMons;
|
||||||
|
u16 itemsHeld[DAYCARE_MON_COUNT]; // marks whether or not each daycare mon is currently holding an item.
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DayCareMisc
|
||||||
|
{
|
||||||
|
struct DayCareMail mail[DAYCARE_MON_COUNT];
|
||||||
|
struct DayCareStepCountersEtc countersEtc;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DayCare {
|
||||||
|
struct BoxPokemon mons[DAYCARE_MON_COUNT];
|
||||||
|
struct DayCareMisc misc;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LinkBattleRecord
|
||||||
|
{
|
||||||
|
u8 name[8];
|
||||||
|
u16 trainerId;
|
||||||
|
u16 wins;
|
||||||
|
u16 losses;
|
||||||
|
u16 draws;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RecordMixingGiftData
|
||||||
|
{
|
||||||
|
u8 unk0;
|
||||||
|
u8 quantity;
|
||||||
|
u16 itemId;
|
||||||
|
u8 filler4[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RecordMixingGift
|
||||||
|
{
|
||||||
|
int checksum;
|
||||||
|
struct RecordMixingGiftData data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ContestWinner
|
||||||
|
{
|
||||||
|
/*0x00*/ u32 personality; // personality
|
||||||
|
/*0x04*/ u32 otId; // otId
|
||||||
|
/*0x08*/ u16 species; // species
|
||||||
|
/*0x0A*/ u8 contestCategory;
|
||||||
|
/*0x0B*/ u8 nickname[11];
|
||||||
|
/*0x16*/ u8 trainerName[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
// there should be enough flags for all 412 slots
|
||||||
|
// each slot takes up 8 flags
|
||||||
|
// if the value is not divisible by 8, we need to account for the reminder as well
|
||||||
|
#define DEX_FLAGS_NO ((POKEMON_SLOTS_NUMBER / 8) + ((POKEMON_SLOTS_NUMBER % 8) ? 1 : 0))
|
||||||
|
|
||||||
|
struct SaveBlock1 /* 0x02025734 */
|
||||||
|
{
|
||||||
|
/*0x00*/ struct Coords16 pos;
|
||||||
|
/*0x04*/ struct WarpData location;
|
||||||
|
/*0x0C*/ struct WarpData warp1;
|
||||||
|
/*0x14*/ struct WarpData warp2;
|
||||||
|
/*0x1C*/ struct WarpData lastHealLocation;
|
||||||
|
/*0x24*/ struct WarpData warp4;
|
||||||
|
/*0x2C*/ u16 savedMusic;
|
||||||
|
/*0x2E*/ u8 weather;
|
||||||
|
/*0x2F*/ u8 weatherCycleStage;
|
||||||
|
/*0x30*/ u8 flashLevel; // flash level on current map, 0 being normal and 4 being the darkest
|
||||||
|
/*0x32*/ u16 mapLayoutId;
|
||||||
|
/*0x34*/ u16 mapView[0x100];
|
||||||
|
/*0x234*/ u8 playerPartyCount;
|
||||||
|
/*0x238*/ struct Pokemon playerParty[6];
|
||||||
|
/*0x490*/ u32 money;
|
||||||
|
/*0x494*/ u16 coins;
|
||||||
|
/*0x496*/ u16 registeredItem; // registered for use with SELECT button
|
||||||
|
/*0x498*/ struct ItemSlot pcItems[PC_ITEMS_COUNT];
|
||||||
|
/*0x560*/ struct ItemSlot bagPocket_Items[BAG_ITEMS_COUNT];
|
||||||
|
/*0x5B0*/ struct ItemSlot bagPocket_KeyItems[BAG_KEYITEMS_COUNT];
|
||||||
|
/*0x600*/ struct ItemSlot bagPocket_PokeBalls[BAG_POKEBALLS_COUNT];
|
||||||
|
/*0x640*/ struct ItemSlot bagPocket_TMHM[BAG_TMHM_COUNT];
|
||||||
|
/*0x740*/ struct ItemSlot bagPocket_Berries[BAG_BERRIES_COUNT];
|
||||||
|
/*0x7F8*/ struct Pokeblock pokeblocks[POKEBLOCKS_COUNT];
|
||||||
|
/*0x938*/ u8 dexSeen2[DEX_FLAGS_NO];
|
||||||
|
/*0x96C*/ u16 berryBlenderRecords[3];
|
||||||
|
/*0x972*/ u8 filler_972[0x6];
|
||||||
|
/*0x978*/ u16 trainerRematchStepCounter;
|
||||||
|
/*0x97A*/ u8 trainerRematches[100];
|
||||||
|
/*0x9E0*/ struct EventObject eventObjects[EVENT_OBJECTS_COUNT];
|
||||||
|
/*0xC20*/ struct EventObjectTemplate eventObjectTemplates[64];
|
||||||
|
/*0x1220*/ u8 flags[FLAGS_COUNT];
|
||||||
|
/*0x1340*/ u16 vars[VARS_COUNT];
|
||||||
|
/*0x1540*/ u32 gameStats[NUM_GAME_STATS];
|
||||||
|
/*0x1608*/ struct BerryTree berryTrees[BERRY_TREES_COUNT];
|
||||||
|
/*0x1A08*/ struct SecretBaseRecord secretBases[SECRET_BASES_COUNT];
|
||||||
|
/*0x2688*/ u8 playerRoomDecor[12];
|
||||||
|
/*0x2694*/ u8 playerRoomDecorPos[12];
|
||||||
|
/*0x26A0*/ u8 decorDesk[10];
|
||||||
|
/*0x26AA*/ u8 decorChair[10];
|
||||||
|
/*0x26B4*/ u8 decorPlant[10];
|
||||||
|
/*0x26BE*/ u8 decorOrnament[30];
|
||||||
|
/*0x26DC*/ u8 decorMat[30];
|
||||||
|
/*0x26FA*/ u8 decorPoster[10];
|
||||||
|
/*0x2704*/ u8 decorDoll[40];
|
||||||
|
/*0x272C*/ u8 decorCushion[10];
|
||||||
|
/*0x2736*/ u8 padding_2736[2];
|
||||||
|
/*0x2738*/ TVShow tvShows[TV_SHOWS_COUNT];
|
||||||
|
/*0x2ABC*/ struct PokeNews pokeNews[POKE_NEWS_COUNT];
|
||||||
|
/*0x2AFC*/ u16 outbreakPokemonSpecies;
|
||||||
|
/*0x2AFE*/ u8 outbreakLocationMapNum;
|
||||||
|
/*0x2AFF*/ u8 outbreakLocationMapGroup;
|
||||||
|
/*0x2B00*/ u8 outbreakPokemonLevel;
|
||||||
|
/*0x2B01*/ u8 outbreakUnk1;
|
||||||
|
/*0x2B02*/ u16 outbreakUnk2;
|
||||||
|
/*0x2B04*/ u16 outbreakPokemonMoves[4];
|
||||||
|
/*0x2B0C*/ u8 outbreakUnk4;
|
||||||
|
/*0x2B0D*/ u8 outbreakPokemonProbability;
|
||||||
|
/*0x2B0E*/ u16 outbreakUnk5;
|
||||||
|
/*0x2B10*/ struct GabbyAndTyData gabbyAndTyData;
|
||||||
|
/*0x2B1C*/ struct {
|
||||||
|
/*0x2B1C*/ u16 unk2B1C[6];
|
||||||
|
/*0x2B28*/ u16 unk2B28[6];
|
||||||
|
/*0x2B34*/ u16 unk2B34[6];
|
||||||
|
/*0x2B40*/ u16 unk2B40[6];
|
||||||
|
} easyChats;
|
||||||
|
/*0x2B4C*/ struct MailStruct mail[MAIL_COUNT];
|
||||||
|
/*0x2D8C*/ u8 unk2D8C[4]; // What is this? Apparently it's supposed to be 64 bytes in size.
|
||||||
|
/*0x2D90*/ u8 filler_2D90[0x4];
|
||||||
|
/*0x2D94*/ union MauvilleMan mauvilleMan;
|
||||||
|
/*0x2DD4*/ struct EasyChatPair easyChatPairs[5]; //Dewford trend [0] and some other stuff
|
||||||
|
/*0x2DFC*/ struct ContestWinner contestWinners[8];
|
||||||
|
/*0x2EFC*/ struct ContestWinner museumPortraits[5];
|
||||||
|
/*0x2F9C*/ struct DayCare daycare;
|
||||||
|
/*0x30B8*/ struct LinkBattleRecord linkBattleRecords[5];
|
||||||
|
struct {
|
||||||
|
/*0x3108*/ u8 unknown1[8];
|
||||||
|
/*0x3110*/ u8 giftRibbons[11];
|
||||||
|
/*0x311B*/ u8 unknown2[8];
|
||||||
|
/*0x3123*/ u32 currentPokeCoupons;
|
||||||
|
/*0x3127*/ u32 totalEarnedPokeCoupons;
|
||||||
|
/*0x312B*/ u8 unknown3[6];
|
||||||
|
/*0x3131*/ u8 receivedWishmakerJirachi;
|
||||||
|
/*0x3132*/ u8 unknown4[18];
|
||||||
|
} __attribute__((packed)) externalReservedData;
|
||||||
|
/*0x3144*/ struct Roamer roamer;
|
||||||
|
/*0x3160*/ struct EnigmaBerry enigmaBerry;
|
||||||
|
/*0x3690*/ struct RamScript ramScript;
|
||||||
|
/*0x3A7C*/ struct RecordMixingGift recordMixingGift;
|
||||||
|
/*0x3A8C*/ u8 dexSeen3[DEX_FLAGS_NO];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct SaveBlock1 gSaveBlock1;
|
||||||
|
|
||||||
|
struct Time
|
||||||
|
{
|
||||||
|
/*0x00*/ s16 days;
|
||||||
|
/*0x02*/ s8 hours;
|
||||||
|
/*0x03*/ s8 minutes;
|
||||||
|
/*0x04*/ s8 seconds;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Pokedex
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 order;
|
||||||
|
/*0x01*/ u8 unknown1;
|
||||||
|
/*0x02*/ u8 nationalMagic; // must equal 0xDA in order to have National mode
|
||||||
|
/*0x03*/ u8 unknown2;
|
||||||
|
/*0x04*/ u32 unownPersonality; // set when you first see Unown
|
||||||
|
/*0x08*/ u32 spindaPersonality; // set when you first see Spinda
|
||||||
|
/*0x0C*/ u32 unknown3;
|
||||||
|
/*0x10*/ u8 owned[DEX_FLAGS_NO];
|
||||||
|
/*0x44*/ u8 seen[DEX_FLAGS_NO];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BattleTowerTrainer
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 trainerClass;
|
||||||
|
/*0x01*/ u8 name[8];
|
||||||
|
/*0x09*/ u8 teamFlags;
|
||||||
|
u8 filler0A[2];
|
||||||
|
/*0x0C*/ u16 greeting[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BattleTowerRecord // record mixing
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 battleTowerLevelType; // 0 = level 50, 1 = level 100
|
||||||
|
/*0x01*/ u8 trainerClass;
|
||||||
|
/*0x02*/ u16 winStreak;
|
||||||
|
/*0x04*/ u8 name[8];
|
||||||
|
/*0x0C*/ u8 trainerId[4];
|
||||||
|
/*0x10*/ u16 greeting[6];
|
||||||
|
/*0x1C*/ struct BattleTowerPokemon party[3];
|
||||||
|
/*0xA0*/ u32 checksum;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BattleTowerEReaderTrainer
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 unk0;
|
||||||
|
/*0x01*/ u8 trainerClass;
|
||||||
|
/*0x02*/ u16 winStreak;
|
||||||
|
/*0x04*/ u8 name[8];
|
||||||
|
/*0x0C*/ u8 trainerId[4];
|
||||||
|
/*0x10*/ u16 greeting[6];
|
||||||
|
/*0x1C*/ u16 farewellPlayerLost[6];
|
||||||
|
/*0x28*/ u16 farewellPlayerWon[6];
|
||||||
|
/*0x34*/ struct BattleTowerPokemon party[3];
|
||||||
|
/*0xB8*/ u32 checksum;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BattleTowerData
|
||||||
|
{
|
||||||
|
/*0x0000, 0x00A8*/ struct BattleTowerRecord playerRecord;
|
||||||
|
/*0x00A4, 0x014C*/ struct BattleTowerRecord records[5]; // from record mixing
|
||||||
|
/*0x03D8, 0x0480*/ u16 firstMonSpecies; // species of the first pokemon in the player's battle tower party
|
||||||
|
/*0x03DA, 0x0482*/ u16 defeatedBySpecies; // species of the pokemon that defated the player
|
||||||
|
/*0x03DC, 0x0484*/ u8 defeatedByTrainerName[8];
|
||||||
|
/*0x03E4, 0x048C*/ u8 firstMonNickname[POKEMON_NAME_LENGTH]; // nickname of the first pokemon in the player's battle tower party
|
||||||
|
/*0x03F0, 0x0498*/ struct BattleTowerEReaderTrainer ereaderTrainer;
|
||||||
|
/*0x04AC, 0x0554*/ u8 battleTowerLevelType:1; // 0 = level 50; 1 = level 100
|
||||||
|
/*0x04AC, 0x0554*/ u8 unk_554:1;
|
||||||
|
/*0x04AD, 0x0555*/ u8 battleOutcome;
|
||||||
|
/*0x04AE, 0x0556*/ u8 var_4AE[2];
|
||||||
|
/*0x04B0, 0x0558*/ u16 curChallengeBattleNum[2]; // 1-based index of battle in the current challenge. (challenges consist of 7 battles)
|
||||||
|
/*0x04B4, 0x055C*/ u16 curStreakChallengesNum[2]; // 1-based index of the current challenge in the current streak.
|
||||||
|
/*0x04B8, 0x0560*/ u16 recordWinStreaks[2];
|
||||||
|
/*0x04BC, 0x0564*/ u8 battleTowerTrainerId; // index for gBattleTowerTrainers table
|
||||||
|
/*0x04BD, 0x0565*/ u8 selectedPartyMons[0x3]; // indices of the 3 selected player party mons.
|
||||||
|
/*0x04C0, 0x0568*/ u16 prizeItem;
|
||||||
|
/*0x04C2, 0x056A*/ u8 battledTrainerIds[6];
|
||||||
|
/*0x04C8, 0x0570*/ u16 totalBattleTowerWins;
|
||||||
|
/*0x04CA, 0x0572*/ u16 bestBattleTowerWinStreak;
|
||||||
|
/*0x04CC, 0x0574*/ u16 currentWinStreaks[2];
|
||||||
|
/*0x04D0, 0x0578*/ u8 lastStreakLevelType; // 0 = level 50, 1 = level 100. level type of the last streak. Used by tv to report the level mode.
|
||||||
|
/*0x04D1, 0x0579*/ u8 filler_4D1[0x317];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SaveBlock2 /* 0x02024EA4 */
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 playerName[8];
|
||||||
|
/*0x08*/ u8 playerGender; // MALE, FEMALE
|
||||||
|
/*0x09*/ u8 specialSaveWarp;
|
||||||
|
/*0x0A*/ u8 playerTrainerId[4];
|
||||||
|
/*0x0E*/ u16 playTimeHours;
|
||||||
|
/*0x10*/ u8 playTimeMinutes;
|
||||||
|
/*0x11*/ u8 playTimeSeconds;
|
||||||
|
/*0x12*/ u8 playTimeVBlanks;
|
||||||
|
/*0x13*/ u8 optionsButtonMode; // OPTIONS_BUTTON_MODE_[NORMAL/LR/L_EQUALS_A]
|
||||||
|
/*0x14*/ u16 optionsTextSpeed:3; // OPTIONS_TEXT_SPEED_[SLOW/MID/FAST]
|
||||||
|
u16 optionsWindowFrameType:5; // Specifies one of the 20 decorative borders for text boxes
|
||||||
|
u16 optionsSound:1; // OPTIONS_SOUND_[MONO/STEREO]
|
||||||
|
u16 optionsBattleStyle:1; // OPTIONS_BATTLE_STYLE_[SHIFT/SET]
|
||||||
|
u16 optionsBattleSceneOff:1; // whether battle animations are disabled
|
||||||
|
u16 regionMapZoom:1; // whether the map is zoomed in
|
||||||
|
/*0x18*/ struct Pokedex pokedex;
|
||||||
|
/*0x90*/ u8 filler_90[0x8];
|
||||||
|
/*0x98*/ struct Time localTimeOffset;
|
||||||
|
/*0xA0*/ struct Time lastBerryTreeUpdate;
|
||||||
|
/*0xA8*/ struct BattleTowerData battleTower;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MapPosition
|
||||||
|
{
|
||||||
|
s16 x;
|
||||||
|
s16 y;
|
||||||
|
s8 height;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UnkStruct_8054FF8
|
||||||
|
{
|
||||||
|
u8 a;
|
||||||
|
u8 b;
|
||||||
|
u8 c;
|
||||||
|
u8 d;
|
||||||
|
struct MapPosition sub;
|
||||||
|
u16 field_C;
|
||||||
|
};
|
||||||
|
|
||||||
|
// wasnt defined so I had to define it
|
||||||
|
struct HallOfFame
|
||||||
|
{
|
||||||
|
u8 filler[0x1F00];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct SaveBlock2 gSaveBlock2;
|
||||||
|
|
||||||
|
#define RomHeaderGameTitle ((const char *)0x080000A0)
|
||||||
|
#define RomHeaderGameCode ((const char *)0x080000AC)
|
||||||
|
#define RomHeaderMakerCode ((const char *)0x080000B0)
|
||||||
|
#define RomHeaderMagic ((const u8 *) 0x080000B2)
|
||||||
|
#define RomHeaderSoftwareVersion ((const u8 *) 0x080000BC)
|
||||||
|
|
||||||
|
#define LocalTimeOffset ((struct Time *)0x02028098)
|
||||||
|
#define LastBerryTreeUpdate ((struct Time *)0x020280A0)
|
||||||
|
|
||||||
|
#endif //GUARD_GLOBAL_H
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#ifndef GUARD_MAIN_H
|
||||||
|
#define GUARD_MAIN_H
|
||||||
|
|
||||||
|
#include <gba/gba.h>
|
||||||
|
|
||||||
|
enum RomHeaderValidationResult
|
||||||
|
{
|
||||||
|
SAPPHIRE_UPDATABLE = 2,
|
||||||
|
RUBY_UPDATABLE,
|
||||||
|
SAPPHIRE_NONEED,
|
||||||
|
RUBY_NONEED,
|
||||||
|
INVALID
|
||||||
|
};
|
||||||
|
|
||||||
|
enum MainCallbackState
|
||||||
|
{
|
||||||
|
MAINCB_INIT = 0,
|
||||||
|
MAINCB_CHECK_RTC,
|
||||||
|
MAINCB_CHECK_FLASH,
|
||||||
|
MAINCB_READ_SAVE,
|
||||||
|
MAINCB_CHECK_TIME,
|
||||||
|
MAINCB_FIX_DATE,
|
||||||
|
MAINCB_NO_NEED_TO_FIX,
|
||||||
|
MAINCB_YEAR_MAKES_NO_SENSE,
|
||||||
|
MAINCB_FINISHED,
|
||||||
|
MAINCB_CHECK_PACIFIDLOG_TM,
|
||||||
|
MAINCB_FIX_PACIFIDLOG_TM,
|
||||||
|
MAINCB_ERROR
|
||||||
|
};
|
||||||
|
|
||||||
|
extern IntrFunc gIntrTable[];
|
||||||
|
extern u16 gHeldKeys;
|
||||||
|
extern u16 gNewKeys;
|
||||||
|
extern u8 gIntrVector[];
|
||||||
|
extern u32 gUpdateSuccessful;
|
||||||
|
extern u32 gUnknown_3001194;
|
||||||
|
extern u32 gUnknown_30011A0[];
|
||||||
|
extern u32 gMainCallbackState;
|
||||||
|
extern u32 gGameVersion;
|
||||||
|
|
||||||
|
extern u8 gSharedMem[0x8000];
|
||||||
|
|
||||||
|
extern const IntrFunc gIntrFuncPointers[];
|
||||||
|
|
||||||
|
#endif //GUARD_MAIN_H
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
#ifndef GUARD_POKEMON_H
|
||||||
|
#define GUARD_POKEMON_H
|
||||||
|
|
||||||
|
struct PokemonSubstruct0
|
||||||
|
{
|
||||||
|
u16 species;
|
||||||
|
u16 heldItem;
|
||||||
|
u32 experience;
|
||||||
|
u8 ppBonuses;
|
||||||
|
u8 friendship;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PokemonSubstruct1
|
||||||
|
{
|
||||||
|
u16 moves[4];
|
||||||
|
u8 pp[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PokemonSubstruct2
|
||||||
|
{
|
||||||
|
u8 hpEV;
|
||||||
|
u8 attackEV;
|
||||||
|
u8 defenseEV;
|
||||||
|
u8 speedEV;
|
||||||
|
u8 spAttackEV;
|
||||||
|
u8 spDefenseEV;
|
||||||
|
u8 cool;
|
||||||
|
u8 beauty;
|
||||||
|
u8 cute;
|
||||||
|
u8 smart;
|
||||||
|
u8 tough;
|
||||||
|
u8 sheen;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PokemonSubstruct3
|
||||||
|
{
|
||||||
|
/*0x00*/ u8 pokerus;
|
||||||
|
/*0x01*/ u8 metLocation;
|
||||||
|
|
||||||
|
/*0x02*/ u16 metLevel:7;
|
||||||
|
/*0x02*/ u16 metGame:4;
|
||||||
|
/*0x03*/ u16 pokeball:4;
|
||||||
|
/*0x03*/ u16 otGender:1;
|
||||||
|
|
||||||
|
/*0x04*/ u32 hpIV:5;
|
||||||
|
/*0x04*/ u32 attackIV:5;
|
||||||
|
/*0x05*/ u32 defenseIV:5;
|
||||||
|
/*0x05*/ u32 speedIV:5;
|
||||||
|
/*0x05*/ u32 spAttackIV:5;
|
||||||
|
/*0x06*/ u32 spDefenseIV:5;
|
||||||
|
/*0x07*/ u32 isEgg:1;
|
||||||
|
/*0x07*/ u32 altAbility:1;
|
||||||
|
|
||||||
|
/*0x08*/ u32 coolRibbon:3;
|
||||||
|
/*0x08*/ u32 beautyRibbon:3;
|
||||||
|
/*0x08*/ u32 cuteRibbon:3;
|
||||||
|
/*0x09*/ u32 smartRibbon:3;
|
||||||
|
/*0x09*/ u32 toughRibbon:3;
|
||||||
|
/*0x09*/ u32 championRibbon:1;
|
||||||
|
/*0x0A*/ u32 winningRibbon:1;
|
||||||
|
/*0x0A*/ u32 victoryRibbon:1;
|
||||||
|
/*0x0A*/ u32 artistRibbon:1;
|
||||||
|
/*0x0A*/ u32 effortRibbon:1;
|
||||||
|
/*0x0A*/ u32 giftRibbon1:1;
|
||||||
|
/*0x0A*/ u32 giftRibbon2:1;
|
||||||
|
/*0x0A*/ u32 giftRibbon3:1;
|
||||||
|
/*0x0A*/ u32 giftRibbon4:1;
|
||||||
|
/*0x0B*/ u32 giftRibbon5:1;
|
||||||
|
/*0x0B*/ u32 giftRibbon6:1;
|
||||||
|
/*0x0B*/ u32 giftRibbon7:1;
|
||||||
|
/*0x0B*/ u32 fatefulEncounter:5; // unused in Ruby/Sapphire, but the high bit must be set for Mew/Deoxys to obey in FR/LG/Emerald
|
||||||
|
};
|
||||||
|
|
||||||
|
union PokemonSubstruct
|
||||||
|
{
|
||||||
|
struct PokemonSubstruct0 type0;
|
||||||
|
struct PokemonSubstruct1 type1;
|
||||||
|
struct PokemonSubstruct2 type2;
|
||||||
|
struct PokemonSubstruct3 type3;
|
||||||
|
u16 raw[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BoxPokemon
|
||||||
|
{
|
||||||
|
/*0x00*/ u32 personality;
|
||||||
|
/*0x04*/ u32 otId;
|
||||||
|
/*0x08*/ u8 nickname[POKEMON_NAME_LENGTH];
|
||||||
|
/*0x12*/ u8 language;
|
||||||
|
/*0x13*/ u8 isBadEgg:1;
|
||||||
|
u8 hasSpecies:1;
|
||||||
|
u8 isEgg:1;
|
||||||
|
/*0x14*/ u8 otName[OT_NAME_LENGTH];
|
||||||
|
/*0x1B*/ u8 markings;
|
||||||
|
/*0x1C*/ u16 checksum;
|
||||||
|
/*0x1E*/ u16 unknown;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
u32 raw[12];
|
||||||
|
union PokemonSubstruct substructs[4];
|
||||||
|
} secure;
|
||||||
|
}; /*size = 0x50*/
|
||||||
|
|
||||||
|
struct Pokemon
|
||||||
|
{
|
||||||
|
/*0x00*/ struct BoxPokemon box;
|
||||||
|
/*0x50*/ u32 status;
|
||||||
|
/*0x54*/ u8 level;
|
||||||
|
/*0x55*/ u8 mail;
|
||||||
|
/*0x56*/ u16 hp;
|
||||||
|
/*0x58*/ u16 maxHP;
|
||||||
|
/*0x5A*/ u16 attack;
|
||||||
|
/*0x5C*/ u16 defense;
|
||||||
|
/*0x5E*/ u16 speed;
|
||||||
|
/*0x60*/ u16 spAttack;
|
||||||
|
/*0x62*/ u16 spDefense;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BattleTowerPokemon
|
||||||
|
{
|
||||||
|
/*0x00*/u16 species;
|
||||||
|
/*0x02*/u16 heldItem;
|
||||||
|
/*0x04*/u16 moves[4];
|
||||||
|
/*0x0C*/u8 level;
|
||||||
|
/*0x0D*/u8 ppBonuses;
|
||||||
|
/*0x0E*/u8 hpEV;
|
||||||
|
/*0x0F*/u8 attackEV;
|
||||||
|
/*0x10*/u8 defenseEV;
|
||||||
|
/*0x11*/u8 speedEV;
|
||||||
|
/*0x12*/u8 spAttackEV;
|
||||||
|
/*0x13*/u8 spDefenseEV;
|
||||||
|
/*0x14*/u32 otId;
|
||||||
|
/*0x18*/u32 hpIV:5;
|
||||||
|
/*0x18*/u32 attackIV:5;
|
||||||
|
/*0x19*/u32 defenseIV:5;
|
||||||
|
/*0x19*/u32 speedIV:5;
|
||||||
|
/*0x1A*/u32 spAttackIV:5;
|
||||||
|
/*0x1A*/u32 spDefenseIV:5;
|
||||||
|
/*0x1B*/u32 gap:1;
|
||||||
|
/*0x1B*/u32 altAbility:1;
|
||||||
|
/*0x1C*/u32 personality;
|
||||||
|
/*0x20*/u8 nickname[POKEMON_NAME_LENGTH + 1];
|
||||||
|
/*0x2B*/u8 friendship;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PokemonStorage
|
||||||
|
{
|
||||||
|
/*0x0000*/ u8 currentBox;
|
||||||
|
/*0x0004*/ struct BoxPokemon boxes[14][30];
|
||||||
|
/*0x8344*/ u8 boxNames[14][9];
|
||||||
|
/*0x83c2*/ u8 wallpaper[14];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GUARD_POKEMON_H
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef GUARD_RTC_H
|
||||||
|
#define GUARD_RTC_H
|
||||||
|
|
||||||
|
#include <gba/gba.h>
|
||||||
|
#include <siirtc.h>
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
|
extern struct Time gTimeSinceBerryUpdate;
|
||||||
|
extern struct Time gRtcUTCTime;
|
||||||
|
|
||||||
|
bool32 rtc_maincb_is_rtc_working(void);
|
||||||
|
bool32 rtc_maincb_is_time_since_last_berry_update_positive(u8 *);
|
||||||
|
void rtc_maincb_fix_date(void);
|
||||||
|
|
||||||
|
#endif //GUARD_RTC_H
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/<EWRAM>/ {
|
||||||
|
r sym_ewram.ld
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
/<BSS>/ {
|
||||||
|
r sym_bss.ld
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
/<COMMON>/ {
|
||||||
|
r sym_common.ld
|
||||||
|
d
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
ENTRY(Init)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = 0x2010000;
|
||||||
|
|
||||||
|
.text :
|
||||||
|
ALIGN(4)
|
||||||
|
{
|
||||||
|
asm/crt0.o(.text);
|
||||||
|
src/main.o(.text);
|
||||||
|
src/rtc.o(.text);
|
||||||
|
src/flash.o(.text);
|
||||||
|
} =0
|
||||||
|
|
||||||
|
lib_text :
|
||||||
|
ALIGN(4)
|
||||||
|
{
|
||||||
|
*libagb_flash.a:agb_flash.o(.text);
|
||||||
|
*libagb_flash.a:agb_flash_1m.o(.text);
|
||||||
|
*libagb_flash.a:agb_flash_mx.o(.text);
|
||||||
|
*libagbsyscall.a:ArcTan2.o(.text);
|
||||||
|
*libagbsyscall.a:BgAffineSet.o(.text);
|
||||||
|
*libagbsyscall.a:CpuFastSet.o(.text);
|
||||||
|
*libagbsyscall.a:CpuSet.o(.text);
|
||||||
|
*libagbsyscall.a:Div.o(.text);
|
||||||
|
*libagbsyscall.a:Mod.o(.text);
|
||||||
|
*libagbsyscall.a:LZ77UnCompVram.o(.text);
|
||||||
|
*libagbsyscall.a:LZ77UnCompWram.o(.text);
|
||||||
|
*libagbsyscall.a:MultiBoot.o(.text);
|
||||||
|
*libagbsyscall.a:ObjAffineSet.o(.text);
|
||||||
|
*libagbsyscall.a:RLUnCompVram.o(.text);
|
||||||
|
*libagbsyscall.a:RLUnCompWram.o(.text);
|
||||||
|
*libagbsyscall.a:RegisterRamReset.o(.text);
|
||||||
|
*libagbsyscall.a:SoftReset.o(.text);
|
||||||
|
*libagbsyscall.a:Sqrt.o(.text);
|
||||||
|
*libagbsyscall.a:VBlankIntrWait.o(.text);
|
||||||
|
*libsiirtc.a:siirtc.o(.text);
|
||||||
|
*libgcc.a:_call_via_rX.o(.text);
|
||||||
|
*libgcc.a:_modsi3.o(.text);
|
||||||
|
*libgcc.a:_umodsi3.o(.text);
|
||||||
|
*libgcc.a:_dvmd_tls.o(.text);
|
||||||
|
} =0
|
||||||
|
|
||||||
|
.rodata :
|
||||||
|
ALIGN(4)
|
||||||
|
{
|
||||||
|
src/main.o(.rodata);
|
||||||
|
src/rtc.o(.rodata);
|
||||||
|
src/flash.o(.rodata);
|
||||||
|
} =0
|
||||||
|
|
||||||
|
lib_rodata :
|
||||||
|
ALIGN(4)
|
||||||
|
{
|
||||||
|
*libagb_flash.a:agb_flash.o(.rodata);
|
||||||
|
*libagb_flash.a:agb_flash_1m.o(.rodata);
|
||||||
|
*libagb_flash.a:agb_flash_mx.o(.rodata);
|
||||||
|
*libagb_flash.a:agb_flash_le.o(.rodata);
|
||||||
|
*libsiirtc.a:siirtc.o(.rodata);
|
||||||
|
}
|
||||||
|
|
||||||
|
. = 0x2020000;
|
||||||
|
|
||||||
|
ewram (NOLOAD) :
|
||||||
|
ALIGN(4)
|
||||||
|
{
|
||||||
|
<EWRAM>
|
||||||
|
}
|
||||||
|
|
||||||
|
. = 0x3001000;
|
||||||
|
|
||||||
|
iwram (NOLOAD) :
|
||||||
|
ALIGN(4)
|
||||||
|
{
|
||||||
|
<BSS>
|
||||||
|
. = 0x40;
|
||||||
|
<COMMON>
|
||||||
|
end = .;
|
||||||
|
}
|
||||||
|
|
||||||
|
. = 0x8000000;
|
||||||
|
|
||||||
|
RS_Rom (NOLOAD) :
|
||||||
|
ALIGN(4)
|
||||||
|
{
|
||||||
|
_start = .;
|
||||||
|
. += 4;
|
||||||
|
RomHeaderNintendoLogo = .;
|
||||||
|
. += 156;
|
||||||
|
RS_RomHeader = .;
|
||||||
|
RomHeaderGameTitle = .;
|
||||||
|
. += 12;
|
||||||
|
RomHeaderGameCode = .;
|
||||||
|
. += 4;
|
||||||
|
RomHeaderMakerCode = .;
|
||||||
|
. += 2;
|
||||||
|
RomHeaderMagic = .;
|
||||||
|
. += 1;
|
||||||
|
RomHeaderMainUnitCode = .;
|
||||||
|
. += 1;
|
||||||
|
RomHeaderDeviceType = .;
|
||||||
|
. += 1;
|
||||||
|
RomHeaderReserved1 = .;
|
||||||
|
. += 7;
|
||||||
|
RomHeaderSoftwareVersion = .;
|
||||||
|
. += 1;
|
||||||
|
RomHeaderChecksum = .;
|
||||||
|
. += 1;
|
||||||
|
RomHeaderReserved2 = .;
|
||||||
|
. += 6;
|
||||||
|
GPIOPortData = .;
|
||||||
|
. += 2;
|
||||||
|
GPIOPortDirection = .;
|
||||||
|
. += 2;
|
||||||
|
GPIOPortReadEnable = .;
|
||||||
|
} =0
|
||||||
|
|
||||||
|
/DISCARD/ :
|
||||||
|
{
|
||||||
|
*(*);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
866991e2b5a8de02d12f53abe0ee9af03a2b6e01 payload.gba
|
||||||
@@ -0,0 +1,752 @@
|
|||||||
|
#include <gba/gba.h>
|
||||||
|
#include <agb_flash.h>
|
||||||
|
#include "constants/vars.h"
|
||||||
|
#include "global.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "flash.h"
|
||||||
|
#include "rtc.h"
|
||||||
|
|
||||||
|
struct SaveBlockChunk
|
||||||
|
{
|
||||||
|
u8 * data;
|
||||||
|
u16 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
u8 WriteSaveBlockChunks(u16 a0, const struct SaveBlockChunk * a1);
|
||||||
|
u8 WriteSingleChunk(u16 a0, const struct SaveBlockChunk * a1);
|
||||||
|
u8 TryWriteSector(u8, u8 *);
|
||||||
|
u8 EraseCurrentChunk(u16 a0, const struct SaveBlockChunk * a1);
|
||||||
|
u8 TryReadAllSaveSectorsCurrentSlot(u16 a0, const struct SaveBlockChunk * a1);
|
||||||
|
u8 ReadAllSaveSectorsCurrentSlot(u16 a0, const struct SaveBlockChunk * a1);
|
||||||
|
u8 GetSaveValidStatus(const struct SaveBlockChunk * a1);
|
||||||
|
u32 DoReadFlashWholeSection(u8 a0, struct SaveSector * a1);
|
||||||
|
u16 CalculateChecksum(const void *, u16);
|
||||||
|
|
||||||
|
u16 gFirstSaveSector;
|
||||||
|
u32 gPrevSaveCounter;
|
||||||
|
u16 gLastKnownGoodSector;
|
||||||
|
u32 gDamagedSaveSectors;
|
||||||
|
u32 gSaveCounter;
|
||||||
|
struct SaveSector * gFastSaveSection;
|
||||||
|
u16 gCurSaveChunk;
|
||||||
|
bool32 gFlashIdentIsValid;
|
||||||
|
|
||||||
|
EWRAM_DATA struct SaveBlock2 gSaveBlock2 = {};
|
||||||
|
EWRAM_DATA struct SaveBlock1 gSaveBlock1 = {};
|
||||||
|
EWRAM_DATA struct PokemonStorage gPokemonStorage = {};
|
||||||
|
|
||||||
|
// Each 4 KiB flash sector contains 3968 bytes of actual data followed by a 128 byte footer
|
||||||
|
#define SECTOR_DATA_SIZE 3968
|
||||||
|
#define SECTOR_FOOTER_SIZE 128
|
||||||
|
|
||||||
|
#define SAVEBLOCK_CHUNK(structure, chunkNum) \
|
||||||
|
{ \
|
||||||
|
(u8 *)&structure + chunkNum * SECTOR_DATA_SIZE, \
|
||||||
|
min(sizeof(structure) - chunkNum * SECTOR_DATA_SIZE, SECTOR_DATA_SIZE) \
|
||||||
|
} \
|
||||||
|
|
||||||
|
static const struct SaveBlockChunk sSaveBlockChunks[] =
|
||||||
|
{
|
||||||
|
SAVEBLOCK_CHUNK(gSaveBlock2, 0),
|
||||||
|
|
||||||
|
SAVEBLOCK_CHUNK(gSaveBlock1, 0),
|
||||||
|
SAVEBLOCK_CHUNK(gSaveBlock1, 1),
|
||||||
|
SAVEBLOCK_CHUNK(gSaveBlock1, 2),
|
||||||
|
SAVEBLOCK_CHUNK(gSaveBlock1, 3),
|
||||||
|
|
||||||
|
SAVEBLOCK_CHUNK(gPokemonStorage, 0),
|
||||||
|
SAVEBLOCK_CHUNK(gPokemonStorage, 1),
|
||||||
|
SAVEBLOCK_CHUNK(gPokemonStorage, 2),
|
||||||
|
SAVEBLOCK_CHUNK(gPokemonStorage, 3),
|
||||||
|
SAVEBLOCK_CHUNK(gPokemonStorage, 4),
|
||||||
|
SAVEBLOCK_CHUNK(gPokemonStorage, 5),
|
||||||
|
SAVEBLOCK_CHUNK(gPokemonStorage, 6),
|
||||||
|
SAVEBLOCK_CHUNK(gPokemonStorage, 7),
|
||||||
|
SAVEBLOCK_CHUNK(gPokemonStorage, 8),
|
||||||
|
};
|
||||||
|
|
||||||
|
const u16 gInfoMessagesPal[] = INCBIN_U16("graphics/msg_box.gbapal");
|
||||||
|
const u8 gInfoMessagesTilemap[] = INCBIN_U8("graphics/msg_box.tilemap.lz");
|
||||||
|
const u8 gInfoMessagesGfx[] = INCBIN_U8("graphics/msg_box.4bpp.lz");
|
||||||
|
|
||||||
|
bool32 flash_maincb_ident_is_valid(void)
|
||||||
|
{
|
||||||
|
gFlashIdentIsValid = TRUE;
|
||||||
|
if (!IdentifyFlash())
|
||||||
|
{
|
||||||
|
SetFlashTimerIntr(0, &((IntrFunc *)gIntrFuncPointers)[9]);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
gFlashIdentIsValid = FALSE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Call_ReadFlash(u16 sectorNum, ptrdiff_t offset, void * dest, size_t size)
|
||||||
|
{
|
||||||
|
ReadFlash(sectorNum, offset, dest, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 Call_WriteSaveBlockChunks(u16 a0, const struct SaveBlockChunk * a1)
|
||||||
|
{
|
||||||
|
return WriteSaveBlockChunks(a0, a1);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 Call_TryReadAllSaveSectorsCurrentSlot(u16 a0, const struct SaveBlockChunk * a1)
|
||||||
|
{
|
||||||
|
return TryReadAllSaveSectorsCurrentSlot(a0, a1);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 * GetDamagedSaveSectorsPtr(void)
|
||||||
|
{
|
||||||
|
return &gDamagedSaveSectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 flash_write_save_block_chunks(u8 a0)
|
||||||
|
{
|
||||||
|
u8 i;
|
||||||
|
|
||||||
|
switch (a0)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
Call_WriteSaveBlockChunks(0xFFFF, sSaveBlockChunks);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
Call_WriteSaveBlockChunks(i, sSaveBlockChunks);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Call_WriteSaveBlockChunks(0, sSaveBlockChunks);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 flash_write_save_block_chunks_check_damage(u8 a0)
|
||||||
|
{
|
||||||
|
flash_write_save_block_chunks(a0);
|
||||||
|
if (*GetDamagedSaveSectorsPtr() == 0)
|
||||||
|
return 1;
|
||||||
|
return 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 flash_maincb_read_save(u32 unused)
|
||||||
|
{
|
||||||
|
return Call_TryReadAllSaveSectorsCurrentSlot(0xFFFF, sSaveBlockChunks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void msg_load_gfx(void)
|
||||||
|
{
|
||||||
|
REG_DISPCNT = 0;
|
||||||
|
REG_BG0HOFS = 0;
|
||||||
|
REG_BG0VOFS = 0;
|
||||||
|
REG_BLDCNT = 0;
|
||||||
|
LZ77UnCompVram(gInfoMessagesGfx, (void *)BG_VRAM);
|
||||||
|
LZ77UnCompVram(gInfoMessagesTilemap, (void *)BG_SCREEN_ADDR(28));
|
||||||
|
CpuCopy16(gInfoMessagesPal, (void *)BG_PLTT, 0x200);
|
||||||
|
REG_BG0CNT = BGCNT_SCREENBASE(28) | BGCNT_TXT512x512;
|
||||||
|
REG_DISPCNT = DISPCNT_BG0_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
void msg_display(enum MsgBoxUpdateMessage a0)
|
||||||
|
{
|
||||||
|
switch (a0)
|
||||||
|
{
|
||||||
|
case MSGBOX_WILL_NOW_UPDATE:
|
||||||
|
REG_BG0HOFS = 0;
|
||||||
|
REG_BG0VOFS = 0;
|
||||||
|
break;
|
||||||
|
case MSGBOX_HAS_BEEN_UPDATED:
|
||||||
|
REG_BG0HOFS = 0x100;
|
||||||
|
REG_BG0VOFS = 0;
|
||||||
|
break;
|
||||||
|
case MSGBOX_UNABLE_TO_UPDATE:
|
||||||
|
REG_BG0HOFS = 0x100;
|
||||||
|
REG_BG0VOFS = 0xB0;
|
||||||
|
break;
|
||||||
|
case MSGBOX_NO_NEED_TO_UPDATE:
|
||||||
|
REG_BG0HOFS = 0;
|
||||||
|
REG_BG0VOFS = 0xB0;
|
||||||
|
break;
|
||||||
|
case MSGBOX_UPDATING:
|
||||||
|
REG_BG0HOFS = 0;
|
||||||
|
REG_BG0VOFS = 0x160;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Save_EraseAllData(void)
|
||||||
|
{
|
||||||
|
u16 i;
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
EraseFlashSector(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Save_ResetSaveCounters(void)
|
||||||
|
{
|
||||||
|
gSaveCounter = 0;
|
||||||
|
gFirstSaveSector = 0;
|
||||||
|
gDamagedSaveSectors = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool32 SetSectorDamagedStatus(u8 op, u8 sectorNum)
|
||||||
|
{
|
||||||
|
bool32 retVal = FALSE;
|
||||||
|
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case SECTOR_DAMAGED:
|
||||||
|
gDamagedSaveSectors |= (1 << sectorNum);
|
||||||
|
break;
|
||||||
|
case SECTOR_OK:
|
||||||
|
gDamagedSaveSectors &= ~(1 << sectorNum);
|
||||||
|
break;
|
||||||
|
case SECTOR_CHECK: // unused
|
||||||
|
if (gDamagedSaveSectors & (1 << sectorNum))
|
||||||
|
retVal = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 WriteSaveBlockChunks(u16 chunkId, const struct SaveBlockChunk *chunks)
|
||||||
|
{
|
||||||
|
u32 retVal;
|
||||||
|
u16 i;
|
||||||
|
|
||||||
|
gFastSaveSection = eSaveSection;
|
||||||
|
|
||||||
|
if (chunkId != 0xFFFF) // write single chunk
|
||||||
|
{
|
||||||
|
retVal = WriteSingleChunk(chunkId, chunks);
|
||||||
|
}
|
||||||
|
else // write all chunks
|
||||||
|
{
|
||||||
|
gLastKnownGoodSector = gFirstSaveSector;
|
||||||
|
gPrevSaveCounter = gSaveCounter;
|
||||||
|
gFirstSaveSector++;
|
||||||
|
gFirstSaveSector %= NUM_SECTORS_PER_SAVE_SLOT;
|
||||||
|
gSaveCounter++;
|
||||||
|
retVal = SAVE_STATUS_OK;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_SECTORS_PER_SAVE_SLOT; i++)
|
||||||
|
WriteSingleChunk(i, chunks);
|
||||||
|
|
||||||
|
// Check for any bad sectors
|
||||||
|
if (gDamagedSaveSectors != 0) // skip the damaged sector.
|
||||||
|
{
|
||||||
|
retVal = SAVE_STATUS_ERROR;
|
||||||
|
gFirstSaveSector = gLastKnownGoodSector;
|
||||||
|
gSaveCounter = gPrevSaveCounter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 WriteSingleChunk(u16 chunkId, const struct SaveBlockChunk * chunks)
|
||||||
|
{
|
||||||
|
u16 i;
|
||||||
|
u16 sectorNum;
|
||||||
|
u8 *chunkData;
|
||||||
|
u16 chunkSize;
|
||||||
|
|
||||||
|
// select sector number
|
||||||
|
sectorNum = chunkId + gFirstSaveSector;
|
||||||
|
sectorNum %= NUM_SECTORS_PER_SAVE_SLOT;
|
||||||
|
// select save slot
|
||||||
|
sectorNum += NUM_SECTORS_PER_SAVE_SLOT * (gSaveCounter % 2);
|
||||||
|
|
||||||
|
chunkData = chunks[chunkId].data;
|
||||||
|
chunkSize = chunks[chunkId].size;
|
||||||
|
|
||||||
|
// clear save section.
|
||||||
|
for (i = 0; i < sizeof(struct SaveSector); i++)
|
||||||
|
((u8 *)gFastSaveSection)[i] = 0;
|
||||||
|
|
||||||
|
gFastSaveSection->id = chunkId;
|
||||||
|
gFastSaveSection->signature = FILE_SIGNATURE;
|
||||||
|
gFastSaveSection->counter = gSaveCounter;
|
||||||
|
for (i = 0; i < chunkSize; i++)
|
||||||
|
gFastSaveSection->data[i] = chunkData[i];
|
||||||
|
gFastSaveSection->checksum = CalculateChecksum(chunkData, chunkSize);
|
||||||
|
|
||||||
|
return TryWriteSector(sectorNum, gFastSaveSection->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 HandleWriteSectorNBytes(u8 sectorNum, u8 *data, u16 size)
|
||||||
|
{
|
||||||
|
u16 i;
|
||||||
|
struct SaveSector *section = eSaveSection;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(struct SaveSector); i++)
|
||||||
|
((char *)section)[i] = 0;
|
||||||
|
|
||||||
|
section->signature = FILE_SIGNATURE;
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
section->data[i] = data[i];
|
||||||
|
section->id = CalculateChecksum(data, size); // though this appears to be incorrect, it might be some sector checksum instead of a whole save checksum and only appears to be relevent to HOF data, if used.
|
||||||
|
|
||||||
|
return TryWriteSector(sectorNum, section->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 TryWriteSector(u8 sectorNum, u8 *data)
|
||||||
|
{
|
||||||
|
if (ProgramFlashSectorAndVerify(sectorNum, data) != 0) // is damaged?
|
||||||
|
{
|
||||||
|
SetSectorDamagedStatus(SECTOR_DAMAGED, sectorNum); // set damaged sector bits.
|
||||||
|
return SAVE_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetSectorDamagedStatus(SECTOR_OK, sectorNum); // unset damaged sector bits. it's safe now.
|
||||||
|
return SAVE_STATUS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 RestoreSaveBackupVarsAndIncrement(const struct SaveBlockChunk *chunk) // chunk is unused
|
||||||
|
{
|
||||||
|
gFastSaveSection = eSaveSection;
|
||||||
|
gLastKnownGoodSector = gFirstSaveSector;
|
||||||
|
gPrevSaveCounter = gSaveCounter;
|
||||||
|
gFirstSaveSector++;
|
||||||
|
gFirstSaveSector %= NUM_SECTORS_PER_SAVE_SLOT;
|
||||||
|
gSaveCounter++;
|
||||||
|
gCurSaveChunk = 0;
|
||||||
|
gDamagedSaveSectors = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 RestoreSaveBackupVars(const struct SaveBlockChunk *chunk)
|
||||||
|
{
|
||||||
|
gFastSaveSection = eSaveSection;
|
||||||
|
gLastKnownGoodSector = gFirstSaveSector;
|
||||||
|
gPrevSaveCounter = gSaveCounter;
|
||||||
|
gCurSaveChunk = 0;
|
||||||
|
gDamagedSaveSectors = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 WriteSingleChunkAndIncrement(u16 a1, const struct SaveBlockChunk * chunk)
|
||||||
|
{
|
||||||
|
u8 retVal;
|
||||||
|
|
||||||
|
if (gCurSaveChunk < a1 - 1)
|
||||||
|
{
|
||||||
|
retVal = SAVE_STATUS_OK;
|
||||||
|
WriteSingleChunk(gCurSaveChunk, chunk);
|
||||||
|
gCurSaveChunk++;
|
||||||
|
if (gDamagedSaveSectors)
|
||||||
|
{
|
||||||
|
retVal = SAVE_STATUS_ERROR;
|
||||||
|
gFirstSaveSector = gLastKnownGoodSector;
|
||||||
|
gSaveCounter = gPrevSaveCounter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retVal = SAVE_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 ErasePreviousChunk(u16 a1, const struct SaveBlockChunk *chunk)
|
||||||
|
{
|
||||||
|
u8 retVal = SAVE_STATUS_OK;
|
||||||
|
|
||||||
|
EraseCurrentChunk(a1 - 1, chunk);
|
||||||
|
|
||||||
|
if (gDamagedSaveSectors)
|
||||||
|
{
|
||||||
|
retVal = SAVE_STATUS_ERROR;
|
||||||
|
gFirstSaveSector = gLastKnownGoodSector;
|
||||||
|
gSaveCounter = gPrevSaveCounter;
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 EraseCurrentChunk(u16 chunkId, const struct SaveBlockChunk *chunks)
|
||||||
|
{
|
||||||
|
u16 i;
|
||||||
|
u16 sector;
|
||||||
|
u8 *data;
|
||||||
|
u16 size;
|
||||||
|
u8 status;
|
||||||
|
|
||||||
|
// select sector number
|
||||||
|
sector = chunkId + gFirstSaveSector;
|
||||||
|
sector %= NUM_SECTORS_PER_SAVE_SLOT;
|
||||||
|
// select save slot
|
||||||
|
sector += NUM_SECTORS_PER_SAVE_SLOT * (gSaveCounter % 2);
|
||||||
|
|
||||||
|
data = chunks[chunkId].data;
|
||||||
|
size = chunks[chunkId].size;
|
||||||
|
|
||||||
|
// clear temp save section.
|
||||||
|
for (i = 0; i < sizeof(struct SaveSector); i++)
|
||||||
|
((char *)gFastSaveSection)[i] = 0;
|
||||||
|
|
||||||
|
gFastSaveSection->id = chunkId;
|
||||||
|
gFastSaveSection->signature = FILE_SIGNATURE;
|
||||||
|
gFastSaveSection->counter = gSaveCounter;
|
||||||
|
|
||||||
|
// set temp section's data.
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
gFastSaveSection->data[i] = data[i];
|
||||||
|
|
||||||
|
// calculate checksum.
|
||||||
|
gFastSaveSection->checksum = CalculateChecksum(data, size);
|
||||||
|
|
||||||
|
EraseFlashSector(sector);
|
||||||
|
|
||||||
|
status = SAVE_STATUS_OK;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(struct UnkSaveSection); i++)
|
||||||
|
{
|
||||||
|
if (ProgramFlashByte(sector, i, gFastSaveSection->data[i]))
|
||||||
|
{
|
||||||
|
status = SAVE_STATUS_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == SAVE_STATUS_ERROR)
|
||||||
|
{
|
||||||
|
SetSectorDamagedStatus(SECTOR_DAMAGED, sector);
|
||||||
|
return SAVE_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = SAVE_STATUS_OK;
|
||||||
|
|
||||||
|
for (i = 0; i < 7; i++)
|
||||||
|
{
|
||||||
|
if (ProgramFlashByte(sector, 0xFF9 + i, ((u8 *)gFastSaveSection)[0xFF9 + i]))
|
||||||
|
{
|
||||||
|
status = SAVE_STATUS_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == SAVE_STATUS_ERROR)
|
||||||
|
{
|
||||||
|
SetSectorDamagedStatus(SECTOR_DAMAGED, sector);
|
||||||
|
return SAVE_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetSectorDamagedStatus(SECTOR_OK, sector);
|
||||||
|
return SAVE_STATUS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 WriteSomeFlashByteToPrevSector(u16 a1, const struct SaveBlockChunk *chunk)
|
||||||
|
{
|
||||||
|
u16 sector;
|
||||||
|
|
||||||
|
// select sector number
|
||||||
|
sector = a1 + gFirstSaveSector - 1;
|
||||||
|
sector %= NUM_SECTORS_PER_SAVE_SLOT;
|
||||||
|
// select save slot
|
||||||
|
sector += NUM_SECTORS_PER_SAVE_SLOT * (gSaveCounter % 2);
|
||||||
|
|
||||||
|
if (ProgramFlashByte(sector, sizeof(struct UnkSaveSection), ((u8 *)gFastSaveSection)[sizeof(struct UnkSaveSection)]))
|
||||||
|
{
|
||||||
|
// sector is damaged, so enable the bit in gDamagedSaveSectors and restore the last written sector and save counter.
|
||||||
|
SetSectorDamagedStatus(SECTOR_DAMAGED, sector);
|
||||||
|
gFirstSaveSector = gLastKnownGoodSector;
|
||||||
|
gSaveCounter = gPrevSaveCounter;
|
||||||
|
return SAVE_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetSectorDamagedStatus(SECTOR_OK, sector);
|
||||||
|
return SAVE_STATUS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 WriteSomeFlashByte0x25ToPrevSector(u16 a1, const struct SaveBlockChunk *chunk)
|
||||||
|
{
|
||||||
|
u16 sector;
|
||||||
|
|
||||||
|
sector = a1 + gFirstSaveSector - 1;
|
||||||
|
sector %= NUM_SECTORS_PER_SAVE_SLOT;
|
||||||
|
sector += NUM_SECTORS_PER_SAVE_SLOT * (gSaveCounter % 2);
|
||||||
|
|
||||||
|
if (ProgramFlashByte(sector, sizeof(struct UnkSaveSection), 0x25))
|
||||||
|
{
|
||||||
|
// sector is damaged, so enable the bit in gDamagedSaveSectors and restore the last written sector and save counter.
|
||||||
|
SetSectorDamagedStatus(SECTOR_DAMAGED, sector);
|
||||||
|
gFirstSaveSector = gLastKnownGoodSector;
|
||||||
|
gSaveCounter = gPrevSaveCounter;
|
||||||
|
return SAVE_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetSectorDamagedStatus(SECTOR_OK, sector);
|
||||||
|
return SAVE_STATUS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 TryReadAllSaveSectorsCurrentSlot(u16 a1, const struct SaveBlockChunk *chunk)
|
||||||
|
{
|
||||||
|
u8 retVal;
|
||||||
|
gFastSaveSection = eSaveSection;
|
||||||
|
if (a1 != 0xFFFF)
|
||||||
|
{
|
||||||
|
retVal = SAVE_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retVal = GetSaveValidStatus(chunk);
|
||||||
|
ReadAllSaveSectorsCurrentSlot(0xFFFF, chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 ReadAllSaveSectorsCurrentSlot(u16 a1, const struct SaveBlockChunk *chunks)
|
||||||
|
{
|
||||||
|
u16 i;
|
||||||
|
u16 checksum;
|
||||||
|
u16 sector = NUM_SECTORS_PER_SAVE_SLOT * (gSaveCounter % 2);
|
||||||
|
u16 id;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_SECTORS_PER_SAVE_SLOT; i++)
|
||||||
|
{
|
||||||
|
DoReadFlashWholeSection(i + sector, gFastSaveSection);
|
||||||
|
id = gFastSaveSection->id;
|
||||||
|
if (id == 0)
|
||||||
|
gFirstSaveSector = i;
|
||||||
|
checksum = CalculateChecksum(gFastSaveSection->data, chunks[id].size);
|
||||||
|
if (gFastSaveSection->signature == FILE_SIGNATURE
|
||||||
|
&& gFastSaveSection->checksum == checksum)
|
||||||
|
{
|
||||||
|
u16 j;
|
||||||
|
for (j = 0; j < chunks[id].size; j++)
|
||||||
|
chunks[id].data[j] = gFastSaveSection->data[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 GetSaveValidStatus(const struct SaveBlockChunk *chunks)
|
||||||
|
{
|
||||||
|
u16 sector;
|
||||||
|
bool8 signatureValid;
|
||||||
|
u16 checksum;
|
||||||
|
u32 slot1saveCounter = 0;
|
||||||
|
u32 slot2saveCounter = 0;
|
||||||
|
u8 slot1Status;
|
||||||
|
u8 slot2Status;
|
||||||
|
u32 validSectors;
|
||||||
|
const u32 ALL_SECTORS = (1 << NUM_SECTORS_PER_SAVE_SLOT) - 1; // bitmask of all saveblock sectors
|
||||||
|
|
||||||
|
// check save slot 1.
|
||||||
|
validSectors = 0;
|
||||||
|
signatureValid = FALSE;
|
||||||
|
for (sector = 0; sector < NUM_SECTORS_PER_SAVE_SLOT; sector++)
|
||||||
|
{
|
||||||
|
DoReadFlashWholeSection(sector, gFastSaveSection);
|
||||||
|
if (gFastSaveSection->signature == FILE_SIGNATURE)
|
||||||
|
{
|
||||||
|
signatureValid = TRUE;
|
||||||
|
checksum = CalculateChecksum(gFastSaveSection->data, chunks[gFastSaveSection->id].size);
|
||||||
|
if (gFastSaveSection->checksum == checksum)
|
||||||
|
{
|
||||||
|
slot1saveCounter = gFastSaveSection->counter;
|
||||||
|
validSectors |= 1 << gFastSaveSection->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signatureValid)
|
||||||
|
{
|
||||||
|
if (validSectors == ALL_SECTORS)
|
||||||
|
slot1Status = SAVE_STATUS_OK;
|
||||||
|
else
|
||||||
|
slot1Status = SAVE_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slot1Status = SAVE_STATUS_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check save slot 2.
|
||||||
|
validSectors = 0;
|
||||||
|
signatureValid = FALSE;
|
||||||
|
for (sector = 0; sector < NUM_SECTORS_PER_SAVE_SLOT; sector++)
|
||||||
|
{
|
||||||
|
DoReadFlashWholeSection(NUM_SECTORS_PER_SAVE_SLOT + sector, gFastSaveSection);
|
||||||
|
if (gFastSaveSection->signature == FILE_SIGNATURE)
|
||||||
|
{
|
||||||
|
signatureValid = TRUE;
|
||||||
|
checksum = CalculateChecksum(gFastSaveSection->data, chunks[gFastSaveSection->id].size);
|
||||||
|
if (gFastSaveSection->checksum == checksum)
|
||||||
|
{
|
||||||
|
slot2saveCounter = gFastSaveSection->counter;
|
||||||
|
validSectors |= 1 << gFastSaveSection->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signatureValid)
|
||||||
|
{
|
||||||
|
if (validSectors == ALL_SECTORS)
|
||||||
|
slot2Status = SAVE_STATUS_OK;
|
||||||
|
else
|
||||||
|
slot2Status = SAVE_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slot2Status = SAVE_STATUS_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slot1Status == SAVE_STATUS_OK && slot2Status == SAVE_STATUS_OK)
|
||||||
|
{
|
||||||
|
// Choose counter of the most recent save file
|
||||||
|
if ((slot1saveCounter == -1 && slot2saveCounter == 0) || (slot1saveCounter == 0 && slot2saveCounter == -1))
|
||||||
|
{
|
||||||
|
if ((unsigned)(slot1saveCounter + 1) < (unsigned)(slot2saveCounter + 1))
|
||||||
|
gSaveCounter = slot2saveCounter;
|
||||||
|
else
|
||||||
|
gSaveCounter = slot1saveCounter;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (slot1saveCounter < slot2saveCounter)
|
||||||
|
gSaveCounter = slot2saveCounter;
|
||||||
|
else
|
||||||
|
gSaveCounter = slot1saveCounter;
|
||||||
|
}
|
||||||
|
return SAVE_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slot1Status == SAVE_STATUS_OK)
|
||||||
|
{
|
||||||
|
gSaveCounter = slot1saveCounter;
|
||||||
|
if (slot2Status == SAVE_STATUS_ERROR)
|
||||||
|
return SAVE_STATUS_ERROR;
|
||||||
|
else
|
||||||
|
return SAVE_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slot2Status == SAVE_STATUS_OK)
|
||||||
|
{
|
||||||
|
gSaveCounter = slot2saveCounter;
|
||||||
|
if (slot1Status == SAVE_STATUS_ERROR)
|
||||||
|
return SAVE_STATUS_ERROR;
|
||||||
|
else
|
||||||
|
return SAVE_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slot1Status == SAVE_STATUS_EMPTY && slot2Status == SAVE_STATUS_EMPTY)
|
||||||
|
{
|
||||||
|
gSaveCounter = 0;
|
||||||
|
gFirstSaveSector = 0;
|
||||||
|
return SAVE_STATUS_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
gSaveCounter = 0;
|
||||||
|
gFirstSaveSector = 0;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 ReadSomeUnknownSectorAndVerify(u8 sector, u8 *data, u16 size)
|
||||||
|
{
|
||||||
|
u16 i;
|
||||||
|
struct SaveSector *section = eSaveSection;
|
||||||
|
|
||||||
|
DoReadFlashWholeSection(sector, section);
|
||||||
|
if (section->signature == FILE_SIGNATURE)
|
||||||
|
{
|
||||||
|
u16 checksum = CalculateChecksum(section->data, size);
|
||||||
|
if (section->id == checksum)
|
||||||
|
{
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
data[i] = section->data[i];
|
||||||
|
return SAVE_STATUS_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return SAVE_STATUS_EMPTY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 DoReadFlashWholeSection(u8 sector, struct SaveSector *section)
|
||||||
|
{
|
||||||
|
ReadFlash(sector, 0, section->data, sizeof(struct SaveSector));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 CalculateChecksum(const void *data, u16 size)
|
||||||
|
{
|
||||||
|
u16 i;
|
||||||
|
u32 checksum = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < (size / 4); i++)
|
||||||
|
{
|
||||||
|
checksum += *((u32 *)data);
|
||||||
|
data += sizeof(u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((checksum >> 16) + checksum);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nullsub_0201182C()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void nullsub_02011830()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void nullsub_02011834()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 * get_var_addr(u16 a0)
|
||||||
|
{
|
||||||
|
if (a0 < VARS_START)
|
||||||
|
return NULL;
|
||||||
|
if (a0 < VAR_SPECIAL_0)
|
||||||
|
return &gSaveBlock1.vars[a0 - VARS_START];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool32 flash_maincb_check_need_reset_pacifidlog_tm(void)
|
||||||
|
{
|
||||||
|
u8 sp0;
|
||||||
|
u16 * data = get_var_addr(VAR_PACIFIDLOG_TM_RECEIVED_DAY);
|
||||||
|
rtc_maincb_is_time_since_last_berry_update_positive(&sp0);
|
||||||
|
if (*data <= gRtcUTCTime.days)
|
||||||
|
return TRUE;
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool32 flash_maincb_reset_pacifidlog_tm(void)
|
||||||
|
{
|
||||||
|
u8 sp0;
|
||||||
|
if (flash_maincb_check_need_reset_pacifidlog_tm() == TRUE)
|
||||||
|
return TRUE;
|
||||||
|
rtc_maincb_is_time_since_last_berry_update_positive(&sp0);
|
||||||
|
if (gRtcUTCTime.days < 0)
|
||||||
|
return FALSE;
|
||||||
|
*get_var_addr(VAR_PACIFIDLOG_TM_RECEIVED_DAY) = 1;
|
||||||
|
if (flash_write_save_block_chunks_check_damage(0) != TRUE)
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
@@ -0,0 +1,289 @@
|
|||||||
|
#include <gba/gba.h>
|
||||||
|
#include "global.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "rtc.h"
|
||||||
|
#include "flash.h"
|
||||||
|
|
||||||
|
static s32 gInitialWaitTimer;
|
||||||
|
IntrFunc gIntrTable[16];
|
||||||
|
u16 gHeldKeys;
|
||||||
|
u16 gNewKeys;
|
||||||
|
u8 gIntrVector[0x100];
|
||||||
|
u32 gUpdateSuccessful;
|
||||||
|
u32 gUnknown_3001194;
|
||||||
|
u32 gUnknown_30011A0[0x19];
|
||||||
|
u32 gMainCallbackState;
|
||||||
|
u32 gGameVersion;
|
||||||
|
|
||||||
|
EWRAM_DATA u8 gSharedMem[0x8000] = {};
|
||||||
|
|
||||||
|
void IntrMain(void);
|
||||||
|
void ReadKeys(void);
|
||||||
|
void dummy_intr_0(void);
|
||||||
|
void dummy_intr_1(void);
|
||||||
|
void main_callback(u32 *, void *, void *);
|
||||||
|
|
||||||
|
|
||||||
|
const char gBerryFixGameCode[] = "AGBJ";
|
||||||
|
const IntrFunc gIntrFuncPointers[] = {
|
||||||
|
dummy_intr_0,
|
||||||
|
dummy_intr_1,
|
||||||
|
dummy_intr_0,
|
||||||
|
dummy_intr_0,
|
||||||
|
dummy_intr_0,
|
||||||
|
dummy_intr_0,
|
||||||
|
dummy_intr_0,
|
||||||
|
dummy_intr_0,
|
||||||
|
dummy_intr_0,
|
||||||
|
dummy_intr_0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
const char gVersionData[][2] = {
|
||||||
|
{'J', 1},
|
||||||
|
{'E', 2},
|
||||||
|
{'D', 1},
|
||||||
|
{'F', 1},
|
||||||
|
{'I', 1},
|
||||||
|
{'S', 1}
|
||||||
|
};
|
||||||
|
const char gRubyTitleAndCode[] = "POKEMON RUBYAXV";
|
||||||
|
const char gSapphireTitleAndCode[] = "POKEMON SAPPAXP";
|
||||||
|
const u16 sDebugPals[20] = {
|
||||||
|
RGB(00, 00, 00),
|
||||||
|
RGB(31, 00, 00),
|
||||||
|
RGB(00, 31, 00),
|
||||||
|
RGB(00, 00, 31)
|
||||||
|
};
|
||||||
|
const u16 sDebugDigitsGfx[] = INCBIN_U16("graphics/debug_digits.4bpp");
|
||||||
|
|
||||||
|
void AgbMain(void)
|
||||||
|
{
|
||||||
|
RegisterRamReset(0x1E);
|
||||||
|
DmaCopy32(3, gIntrFuncPointers, gIntrTable, sizeof gIntrFuncPointers);
|
||||||
|
DmaCopy32(3, IntrMain, gIntrVector, sizeof(gIntrVector));
|
||||||
|
INTR_VECTOR = gIntrVector;
|
||||||
|
REG_IE = INTR_FLAG_VBLANK;
|
||||||
|
if (*RomHeaderMagic == 0x96 && *(u32 *)RomHeaderGameCode == *(u32 *)gBerryFixGameCode)
|
||||||
|
REG_IE |= INTR_FLAG_GAMEPAK;
|
||||||
|
REG_DISPSTAT = DISPSTAT_VBLANK_INTR;
|
||||||
|
REG_IME = INTR_FLAG_VBLANK;
|
||||||
|
msg_load_gfx();
|
||||||
|
gMainCallbackState = MAINCB_INIT;
|
||||||
|
gUnknown_3001194 = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
VBlankIntrWait();
|
||||||
|
ReadKeys();
|
||||||
|
main_callback(&gMainCallbackState, gUnknown_30011A0, gSharedMem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dummy_intr_1(void)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void dummy_intr_0(void)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void ReadKeys(void)
|
||||||
|
{
|
||||||
|
u16 keyInput = REG_KEYINPUT ^ KEYS_MASK;
|
||||||
|
gNewKeys = keyInput & ~gHeldKeys;
|
||||||
|
gHeldKeys = keyInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fill_palette(const u8 * src, u16 * dest, u8 value)
|
||||||
|
{
|
||||||
|
s32 i;
|
||||||
|
for (i = 0; src[i] != 0; i++)
|
||||||
|
dest[i] = src[i] | value << 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool32 berry_fix_memcmp(const char * src1, const char * src2, size_t size)
|
||||||
|
{
|
||||||
|
s32 i;
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
if (src1[i] != src2[i])
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 validate_rom_header_internal(void)
|
||||||
|
{
|
||||||
|
char languageCode = *(RomHeaderGameCode + 3);
|
||||||
|
s32 softwareVersion = *RomHeaderSoftwareVersion;
|
||||||
|
s32 shouldUpdate = -1;
|
||||||
|
s32 i;
|
||||||
|
for (i = 0; i < ARRAY_COUNT(gVersionData); i++)
|
||||||
|
{
|
||||||
|
if (languageCode == gVersionData[i][0])
|
||||||
|
{
|
||||||
|
if (softwareVersion >= gVersionData[i][1])
|
||||||
|
{
|
||||||
|
shouldUpdate = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shouldUpdate = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shouldUpdate != -1)
|
||||||
|
{
|
||||||
|
if (berry_fix_memcmp(RomHeaderGameTitle, gRubyTitleAndCode, 15) == TRUE)
|
||||||
|
{
|
||||||
|
if (shouldUpdate == 0)
|
||||||
|
return RUBY_NONEED;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gGameVersion = VERSION_RUBY;
|
||||||
|
return RUBY_UPDATABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (berry_fix_memcmp(RomHeaderGameTitle, gSapphireTitleAndCode, 15) == TRUE)
|
||||||
|
{
|
||||||
|
if (shouldUpdate == 0)
|
||||||
|
return SAPPHIRE_NONEED;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gGameVersion = VERSION_SAPPHIRE;
|
||||||
|
return SAPPHIRE_UPDATABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 validate_rom_header(void)
|
||||||
|
{
|
||||||
|
if (*RomHeaderMakerCode == '0' && *(RomHeaderMakerCode + 1) == '1' && *RomHeaderMagic == 0x96)
|
||||||
|
return validate_rom_header_internal();
|
||||||
|
else
|
||||||
|
return INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main_callback(u32 * state, void * unused1, void * unused2)
|
||||||
|
{
|
||||||
|
u8 year;
|
||||||
|
switch (*state)
|
||||||
|
{
|
||||||
|
case MAINCB_INIT:
|
||||||
|
msg_display(MSGBOX_WILL_NOW_UPDATE);
|
||||||
|
if (++gInitialWaitTimer >= 180)
|
||||||
|
{
|
||||||
|
gInitialWaitTimer = 0;
|
||||||
|
gUpdateSuccessful = 0;
|
||||||
|
switch (validate_rom_header())
|
||||||
|
{
|
||||||
|
case SAPPHIRE_UPDATABLE:
|
||||||
|
case RUBY_UPDATABLE: // Should Update Ruby
|
||||||
|
++(*state); // MAINCB_CHECK_RTC
|
||||||
|
break;
|
||||||
|
case INVALID: // Invalid header
|
||||||
|
*state = MAINCB_ERROR;
|
||||||
|
break;
|
||||||
|
case SAPPHIRE_NONEED: // Should not update Sapphire
|
||||||
|
case RUBY_NONEED: // Should not update Ruby
|
||||||
|
*state = MAINCB_NO_NEED_TO_FIX;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MAINCB_CHECK_RTC:
|
||||||
|
if (!rtc_maincb_is_rtc_working())
|
||||||
|
*state = MAINCB_ERROR;
|
||||||
|
else
|
||||||
|
++(*state); // MAINCB_CHECK_FLASH
|
||||||
|
break;
|
||||||
|
case MAINCB_CHECK_FLASH:
|
||||||
|
if (flash_maincb_ident_is_valid() == TRUE)
|
||||||
|
++(*state); // MAINCB_READ_SAVE
|
||||||
|
else
|
||||||
|
*state = MAINCB_ERROR;
|
||||||
|
break;
|
||||||
|
case MAINCB_READ_SAVE:
|
||||||
|
if (flash_maincb_read_save(0) == SAVE_STATUS_OK)
|
||||||
|
++(*state); // MAINCB_CHECK_TIME
|
||||||
|
else
|
||||||
|
*state = MAINCB_ERROR;
|
||||||
|
break;
|
||||||
|
case MAINCB_CHECK_TIME:
|
||||||
|
if (rtc_maincb_is_time_since_last_berry_update_positive(&year) == TRUE)
|
||||||
|
{
|
||||||
|
if (year == 0)
|
||||||
|
++(*state); // MAINCB_FIX_DATE
|
||||||
|
else
|
||||||
|
*state = MAINCB_CHECK_PACIFIDLOG_TM;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (year != 1)
|
||||||
|
*state = MAINCB_YEAR_MAKES_NO_SENSE;
|
||||||
|
else
|
||||||
|
++(*state); // MAINCB_FIX_DATE
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MAINCB_FIX_DATE:
|
||||||
|
rtc_maincb_fix_date();
|
||||||
|
gUpdateSuccessful |= 1;
|
||||||
|
*state = MAINCB_CHECK_PACIFIDLOG_TM;
|
||||||
|
break;
|
||||||
|
case MAINCB_CHECK_PACIFIDLOG_TM:
|
||||||
|
if (flash_maincb_check_need_reset_pacifidlog_tm() == TRUE)
|
||||||
|
*state = MAINCB_FINISHED;
|
||||||
|
else
|
||||||
|
*state = MAINCB_FIX_PACIFIDLOG_TM;
|
||||||
|
break;
|
||||||
|
case MAINCB_FIX_PACIFIDLOG_TM:
|
||||||
|
msg_display(MSGBOX_UPDATING);
|
||||||
|
if (flash_maincb_reset_pacifidlog_tm() == TRUE)
|
||||||
|
{
|
||||||
|
gUpdateSuccessful |= 1;
|
||||||
|
*state = MAINCB_FINISHED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*state = MAINCB_ERROR;
|
||||||
|
break;
|
||||||
|
case MAINCB_FINISHED:
|
||||||
|
if (gUpdateSuccessful == 0)
|
||||||
|
*state = MAINCB_NO_NEED_TO_FIX;
|
||||||
|
else
|
||||||
|
msg_display(MSGBOX_HAS_BEEN_UPDATED);
|
||||||
|
break;
|
||||||
|
case MAINCB_NO_NEED_TO_FIX:
|
||||||
|
msg_display(MSGBOX_NO_NEED_TO_UPDATE);
|
||||||
|
break;
|
||||||
|
case MAINCB_YEAR_MAKES_NO_SENSE:
|
||||||
|
msg_display(MSGBOX_UNABLE_TO_UPDATE);
|
||||||
|
break;
|
||||||
|
case MAINCB_ERROR:
|
||||||
|
msg_display(MSGBOX_UNABLE_TO_UPDATE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBG_LoadDigitsPal(void)
|
||||||
|
{
|
||||||
|
const u16 * src;
|
||||||
|
s32 i;
|
||||||
|
register vu16 * dest asm("r3") = (vu16 *)BG_PLTT + 1;
|
||||||
|
DmaFill16(3, RGB(31, 31, 31), (vu16 *)BG_PLTT, BG_PLTT_SIZE);
|
||||||
|
src = sDebugPals;
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
*dest = *src;
|
||||||
|
dest += 16;
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBG_LoadDigits(void)
|
||||||
|
{
|
||||||
|
DmaFill16(3, 0x1111, (void *)VRAM + 0x8420, 0x1800);
|
||||||
|
DmaCopy32(3, sDebugDigitsGfx, (void *)VRAM + 0x8600, 0x200);
|
||||||
|
DBG_LoadDigitsPal();
|
||||||
|
}
|
||||||
@@ -0,0 +1,346 @@
|
|||||||
|
#include <gba/gba.h>
|
||||||
|
#include <siirtc.h>
|
||||||
|
#include "global.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
struct Time gTimeSinceBerryUpdate;
|
||||||
|
struct Time gRtcUTCTime;
|
||||||
|
|
||||||
|
static u16 sRtcProbeStatus;
|
||||||
|
static struct SiiRtcInfo sRtcInfoBuffer;
|
||||||
|
static u8 sRtcProbeCode;
|
||||||
|
static u16 sImeBak;
|
||||||
|
static struct SiiRtcInfo sRtcInfoWork;
|
||||||
|
|
||||||
|
const struct SiiRtcInfo sDefaultRTC = {
|
||||||
|
.year = 0, // 2000
|
||||||
|
.month = 1, // January
|
||||||
|
.day = 1, // 01
|
||||||
|
.dayOfWeek = 0,
|
||||||
|
.hour = 0,
|
||||||
|
.minute = 0,
|
||||||
|
.second = 0,
|
||||||
|
.status = 0,
|
||||||
|
.alarmHour = 0,
|
||||||
|
.alarmMinute = 0
|
||||||
|
};
|
||||||
|
const s32 sDaysPerMonth[] = {
|
||||||
|
31,
|
||||||
|
28,
|
||||||
|
31,
|
||||||
|
30,
|
||||||
|
31,
|
||||||
|
30,
|
||||||
|
31,
|
||||||
|
31,
|
||||||
|
30,
|
||||||
|
31,
|
||||||
|
30,
|
||||||
|
31
|
||||||
|
};
|
||||||
|
|
||||||
|
void rtc_get_status_and_datetime(struct SiiRtcInfo *);
|
||||||
|
u16 rtc_validate_datetime(struct SiiRtcInfo *);
|
||||||
|
|
||||||
|
|
||||||
|
void rtc_intr_disable(void)
|
||||||
|
{
|
||||||
|
sImeBak = REG_IME;
|
||||||
|
REG_IME = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_intr_enable(void)
|
||||||
|
{
|
||||||
|
REG_IME = sImeBak;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 bcd_to_hex(u8 a0)
|
||||||
|
{
|
||||||
|
if (a0 >= 0xa0 || (a0 & 0xF) >= 10)
|
||||||
|
return 0xFF;
|
||||||
|
return ((a0 >> 4) & 0xF) * 10 + (a0 & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool8 is_leap_year(u8 year)
|
||||||
|
{
|
||||||
|
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 rtc_count_days_parameterized(u8 year, u8 month, u8 day)
|
||||||
|
{
|
||||||
|
u16 numDays = 0;
|
||||||
|
s32 i;
|
||||||
|
for (i = year - 1; i > 0; i--)
|
||||||
|
{
|
||||||
|
numDays += 365;
|
||||||
|
if (is_leap_year(i) == TRUE)
|
||||||
|
numDays++;
|
||||||
|
}
|
||||||
|
for (i = 0; i < month - 1; i++)
|
||||||
|
numDays += sDaysPerMonth[i];
|
||||||
|
if (month > MONTH_FEB && is_leap_year(year) == TRUE)
|
||||||
|
numDays++;
|
||||||
|
numDays += day;
|
||||||
|
return numDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 rtc_count_days_from_info(struct SiiRtcInfo *info)
|
||||||
|
{
|
||||||
|
return rtc_count_days_parameterized(bcd_to_hex(info->year), bcd_to_hex(info->month), bcd_to_hex(info->day));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rtc_probe_status(void)
|
||||||
|
{
|
||||||
|
sRtcProbeStatus = 0;
|
||||||
|
rtc_intr_disable();
|
||||||
|
SiiRtcUnprotect();
|
||||||
|
sRtcProbeCode = SiiRtcProbe();
|
||||||
|
rtc_intr_enable();
|
||||||
|
if ((sRtcProbeCode & 0xF) != 1)
|
||||||
|
sRtcProbeStatus = 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (sRtcProbeCode & 0xF0)
|
||||||
|
sRtcProbeStatus = 2;
|
||||||
|
else
|
||||||
|
sRtcProbeStatus = 0;
|
||||||
|
rtc_get_status_and_datetime(&sRtcInfoBuffer);
|
||||||
|
sRtcProbeStatus = rtc_validate_datetime(&sRtcInfoBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 rtc_get_probe_status(void)
|
||||||
|
{
|
||||||
|
return sRtcProbeStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sub_020106EC(struct SiiRtcInfo * info)
|
||||||
|
{
|
||||||
|
if (sRtcProbeStatus & 0xFF0)
|
||||||
|
*info = sDefaultRTC;
|
||||||
|
else
|
||||||
|
rtc_get_status_and_datetime(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_get_datetime(struct SiiRtcInfo * info)
|
||||||
|
{
|
||||||
|
rtc_intr_disable();
|
||||||
|
SiiRtcGetDateTime(info);
|
||||||
|
rtc_intr_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_get_status(struct SiiRtcInfo * info)
|
||||||
|
{
|
||||||
|
rtc_intr_disable();
|
||||||
|
SiiRtcGetStatus(info);
|
||||||
|
rtc_intr_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_get_status_and_datetime(struct SiiRtcInfo * info)
|
||||||
|
{
|
||||||
|
rtc_get_status(info);
|
||||||
|
rtc_get_datetime(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 rtc_validate_datetime(struct SiiRtcInfo * info)
|
||||||
|
{
|
||||||
|
s32 year, month, day;
|
||||||
|
u16 r4 = (info->status & SIIRTCINFO_POWER) ? 0x20 : 0;
|
||||||
|
if (!(info->status & SIIRTCINFO_24HOUR))
|
||||||
|
r4 |= 0x10;
|
||||||
|
year = bcd_to_hex(info->year);
|
||||||
|
if (year == 0xFF)
|
||||||
|
r4 |= 0x40;
|
||||||
|
month = bcd_to_hex(info->month);
|
||||||
|
if (month == 0xFF || month == 0 || month > 12)
|
||||||
|
r4 |= 0x80;
|
||||||
|
day = bcd_to_hex(info->day);
|
||||||
|
if (day == 0xFF)
|
||||||
|
r4 |= 0x100;
|
||||||
|
if (month == MONTH_FEB)
|
||||||
|
{
|
||||||
|
if (day > is_leap_year(year) + sDaysPerMonth[1])
|
||||||
|
r4 |= 0x100;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (day > sDaysPerMonth[month - 1])
|
||||||
|
r4 |= 0x100;
|
||||||
|
}
|
||||||
|
day = bcd_to_hex(info->hour);
|
||||||
|
if (day > 24)
|
||||||
|
r4 |= 0x200;
|
||||||
|
day = bcd_to_hex(info->minute);
|
||||||
|
if (day > 60)
|
||||||
|
r4 |= 0x400;
|
||||||
|
day = bcd_to_hex(info->second);
|
||||||
|
if (day > 60)
|
||||||
|
r4 |= 0x800;
|
||||||
|
return r4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_reset(void)
|
||||||
|
{
|
||||||
|
rtc_intr_disable();
|
||||||
|
SiiRtcReset();
|
||||||
|
rtc_intr_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_sub_time_from_datetime(struct SiiRtcInfo * datetime, struct Time * dest, struct Time * timediff)
|
||||||
|
{
|
||||||
|
u16 r4 = rtc_count_days_from_info(datetime);
|
||||||
|
dest->seconds = bcd_to_hex(datetime->second) - timediff->seconds;
|
||||||
|
dest->minutes = bcd_to_hex(datetime->minute) - timediff->minutes;
|
||||||
|
dest->hours = bcd_to_hex(datetime->hour) - timediff->hours;
|
||||||
|
dest->days = r4 - timediff->days;
|
||||||
|
if (dest->seconds < 0)
|
||||||
|
{
|
||||||
|
dest->seconds += 60;
|
||||||
|
dest->minutes--;
|
||||||
|
}
|
||||||
|
if (dest->minutes < 0)
|
||||||
|
{
|
||||||
|
dest->minutes += 60;
|
||||||
|
dest->hours--;
|
||||||
|
}
|
||||||
|
if (dest->hours < 0)
|
||||||
|
{
|
||||||
|
dest->hours += 24;
|
||||||
|
dest->days--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_sub_time_from_time(struct Time * dest, struct Time * diff, struct Time * src)
|
||||||
|
{
|
||||||
|
dest->seconds = src->seconds - diff->seconds;
|
||||||
|
dest->minutes = src->minutes - diff->minutes;
|
||||||
|
dest->hours = src->hours - diff->hours;
|
||||||
|
dest->days = src->days - diff->days;
|
||||||
|
if (dest->seconds < 0)
|
||||||
|
{
|
||||||
|
dest->seconds += 60;
|
||||||
|
dest->minutes--;
|
||||||
|
}
|
||||||
|
if (dest->minutes < 0)
|
||||||
|
{
|
||||||
|
dest->minutes += 60;
|
||||||
|
dest->hours--;
|
||||||
|
}
|
||||||
|
if (dest->hours < 0)
|
||||||
|
{
|
||||||
|
dest->hours += 24;
|
||||||
|
dest->days--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool32 rtc_maincb_is_rtc_working(void)
|
||||||
|
{
|
||||||
|
rtc_probe_status();
|
||||||
|
if (rtc_get_probe_status() & 0xFF0)
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_set_datetime(struct SiiRtcInfo * info)
|
||||||
|
{
|
||||||
|
vu16 imeBak = REG_IME;
|
||||||
|
REG_IME = 0;
|
||||||
|
SiiRtcSetDateTime(info);
|
||||||
|
REG_IME = imeBak;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool32 rtc_maincb_is_time_since_last_berry_update_positive(u8 * a0)
|
||||||
|
{
|
||||||
|
rtc_get_status_and_datetime(&sRtcInfoWork);
|
||||||
|
*a0 = bcd_to_hex(sRtcInfoWork.year);
|
||||||
|
rtc_sub_time_from_datetime(&sRtcInfoWork, &gRtcUTCTime, LocalTimeOffset);
|
||||||
|
rtc_sub_time_from_time(&gTimeSinceBerryUpdate, LastBerryTreeUpdate, &gRtcUTCTime);
|
||||||
|
if (gTimeSinceBerryUpdate.days * 1440 + gTimeSinceBerryUpdate.hours * 60 + gTimeSinceBerryUpdate.minutes >= 0)
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 hex_to_bcd(u8 a0)
|
||||||
|
{
|
||||||
|
u32 r4;
|
||||||
|
if (a0 > 99)
|
||||||
|
return 0xFF;
|
||||||
|
r4 = Div(a0, 10) << 4;
|
||||||
|
r4 |= Mod(a0, 10);
|
||||||
|
return r4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sii_rtc_inc(u8 * a0)
|
||||||
|
{
|
||||||
|
*a0 = hex_to_bcd(bcd_to_hex(*a0) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sii_rtc_inc_month(struct SiiRtcInfo * a0)
|
||||||
|
{
|
||||||
|
sii_rtc_inc(&a0->month);
|
||||||
|
if (bcd_to_hex(a0->month) > 12)
|
||||||
|
{
|
||||||
|
sii_rtc_inc(&a0->year);
|
||||||
|
a0->month = MONTH_JAN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sii_rtc_inc_day(struct SiiRtcInfo * a0)
|
||||||
|
{
|
||||||
|
sii_rtc_inc(&a0->day);
|
||||||
|
if (bcd_to_hex(a0->day) > sDaysPerMonth[bcd_to_hex(a0->month) - 1])
|
||||||
|
{
|
||||||
|
if (!is_leap_year(bcd_to_hex(a0->year)) || bcd_to_hex(a0->month) != MONTH_FEB || bcd_to_hex(a0->day) != 29)
|
||||||
|
{
|
||||||
|
a0->day = 1;
|
||||||
|
sii_rtc_inc_month(a0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool32 rtc_is_past_feb_28_2000(struct SiiRtcInfo * a0)
|
||||||
|
{
|
||||||
|
if (bcd_to_hex(a0->year) == 0)
|
||||||
|
{
|
||||||
|
if (bcd_to_hex(a0->month) == MONTH_JAN)
|
||||||
|
return FALSE;
|
||||||
|
if (bcd_to_hex(a0->month) > MONTH_FEB)
|
||||||
|
return TRUE;
|
||||||
|
if (bcd_to_hex(a0->day) == 29)
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (bcd_to_hex(a0->year) == 1)
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_maincb_fix_date(void)
|
||||||
|
{
|
||||||
|
rtc_get_status_and_datetime(&sRtcInfoWork);
|
||||||
|
if (bcd_to_hex(sRtcInfoWork.year) == 0 || bcd_to_hex(sRtcInfoWork.year) == 1)
|
||||||
|
{
|
||||||
|
if (bcd_to_hex(sRtcInfoWork.year) == 1)
|
||||||
|
{
|
||||||
|
sRtcInfoWork.year = 2;
|
||||||
|
sRtcInfoWork.month = MONTH_JAN;
|
||||||
|
sRtcInfoWork.day = 2;
|
||||||
|
rtc_set_datetime(&sRtcInfoWork);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (rtc_is_past_feb_28_2000(&sRtcInfoWork) == TRUE)
|
||||||
|
{
|
||||||
|
sii_rtc_inc_day(&sRtcInfoWork);
|
||||||
|
sii_rtc_inc(&sRtcInfoWork.year);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sii_rtc_inc(&sRtcInfoWork.year);
|
||||||
|
}
|
||||||
|
rtc_set_datetime(&sRtcInfoWork);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.include "src/main.o"
|
||||||
|
.include "src/rtc.o"
|
||||||
|
.include "src/flash.o"
|
||||||
|
.include "*libagb_flash.a:agb_flash.o"
|
||||||
|
.include "*libsiirtc.a:siirtc.o"
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
.include "main.o"
|
||||||
|
.include "rtc.o"
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
gFirstSaveSector: @ 0x03001220
|
||||||
|
.space 0x4
|
||||||
|
|
||||||
|
gPrevSaveCounter: @ 0x03001224
|
||||||
|
.space 0x4
|
||||||
|
|
||||||
|
gLastKnownGoodSector: @ 0x03001228
|
||||||
|
.space 0x4
|
||||||
|
|
||||||
|
gDamagedSaveSectors: @ 0x0300122C
|
||||||
|
.space 0x4
|
||||||
|
|
||||||
|
gSaveCounter: @ 0x03001230
|
||||||
|
.space 0x4
|
||||||
|
|
||||||
|
gFastSaveSection: @ 0x03001234
|
||||||
|
.space 0x4
|
||||||
|
|
||||||
|
gCurSaveChunk:
|
||||||
|
.space 0x4
|
||||||
|
|
||||||
|
gFlashIdentIsValid: @ 0x0300123C
|
||||||
|
.space 0x4
|
||||||
|
|
||||||
|
.include "*libagb_flash.a:agb_flash.o"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
.include "src/main.o"
|
||||||
|
.include "src/rtc.o"
|
||||||
|
.include "src/flash.o"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
2eb0a94a913bebfb4cb59ceb57f3f965da55ef6d berry_fix.gba
|
||||||
Binary file not shown.
@@ -1,5 +1,5 @@
|
|||||||
.section .rodata
|
.section .rodata
|
||||||
|
|
||||||
gMultiBootProgram_BerryGlitchFix_Start:: @ 86FFC6C
|
gMultiBootProgram_BerryGlitchFix_Start:: @ 86FFC6C
|
||||||
.incbin "data/berry_fix.mb"
|
.incbin "berry_fix/berry_fix.gba"
|
||||||
gMultiBootProgram_BerryGlitchFix_End::
|
gMultiBootProgram_BerryGlitchFix_End::
|
||||||
|
|||||||
Reference in New Issue
Block a user