import from github

This commit is contained in:
2022-05-19 17:14:13 +00:00
parent 5247c34f50
commit ab32b30591
12612 changed files with 1905035 additions and 83 deletions

203
berry_fix/Makefile Normal file
View File

@ -0,0 +1,203 @@
TOOLCHAIN := $(DEVKITARM)
COMPARE ?= 0
# don't use dkP's base_tools anymore
# because the redefinition of $(CC) conflicts
# with when we want to use $(CC) to preprocess files
# thus, manually create the variables for the bin
# files, or use arm-none-eabi binaries on the system
# if dkP is not installed on this system
ifneq (,$(TOOLCHAIN))
ifneq ($(wildcard $(TOOLCHAIN)/bin),)
export PATH := $(TOOLCHAIN)/bin:$(PATH)
endif
endif
PREFIX := arm-none-eabi-
OBJCOPY := $(PREFIX)objcopy
AS := $(PREFIX)as
LD := $(PREFIX)ld
# note: the makefile must be set up so MODERNCC is never called
# if MODERN=0
MODERNCC := $(PREFIX)gcc
ifeq ($(OS),Windows_NT)
EXE := .exe
else
EXE :=
endif
# use arm-none-eabi-cpp for macOS
# as macOS's default compiler is clang
# and clang's preprocessor will warn on \u
# when preprocessing asm files, expecting a unicode literal
# we can't unconditionally use arm-none-eabi-cpp
# as installations which install binutils-arm-none-eabi
# don't come with it
ifneq ($(MODERN),1)
ifeq ($(shell uname -s),Darwin)
CPP := $(PREFIX)cpp
else
CPP := $(CC) -E
endif
else
CPP := $(PREFIX)cpp
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: all rom clean compare tidy payload
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))
all: payload rom
@:
rom: $(ROM)
ifeq ($(COMPARE),1)
@$(SHA1) rom.sha1
endif
# For contributors to make sure a change didn't affect the contents of the ROM.
compare: ; @$(MAKE) COMPARE=1
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:
@$(MAKE) -C payload COMPARE=$(COMPARE) TOOLCHAIN=$(TOOLCHAIN) MODERN=$(MODERN)
payload/payload.gba: 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

View File

@ -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

119
berry_fix/asm/loader.s Normal file
View File

@ -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

1067
berry_fix/charmap.txt Normal file
View File

@ -0,0 +1,1067 @@
' ' = 00
'À' = 01
'Á' = 02
'Â' = 03
'Ç' = 04
'È' = 05
'É' = 06
'Ê' = 07
'Ë' = 08
'Ì' = 09
'Î' = 0B
'Ï' = 0C
'Ò' = 0D
'Ó' = 0E
'Ô' = 0F
'Œ' = 10
'Ù' = 11
'Ú' = 12
'Û' = 13
'Ñ' = 14
'ß' = 15
'à' = 16
'á' = 17
'ç' = 19
'è' = 1A
'é' = 1B
'ê' = 1C
'ë' = 1D
'ì' = 1E
'î' = 20
'ï' = 21
'ò' = 22
'ó' = 23
'ô' = 24
'œ' = 25
'ù' = 26
'ú' = 27
'û' = 28
'ñ' = 29
'º' = 2A
'ª' = 2B
SUPER_ER = 2C
'&' = 2D
'+' = 2E
LV = 34
'=' = 35
';' = 36
'¿' = 51
'¡' = 52
PK = 53
PKMN = 53 54
POKEBLOCK = 55 56 57 58 59
'Í' = 5A
'%' = 5B
'(' = 5C
')' = 5D
'â' = 68
'í' = 6F
UNK_SPACER = 77
UP_ARROW = 79
DOWN_ARROW = 7A
LEFT_ARROW = 7B
RIGHT_ARROW = 7C
'0' = A1
'1' = A2
'2' = A3
'3' = A4
'4' = A5
'5' = A6
'6' = A7
'7' = A8
'8' = A9
'9' = AA
'!' = AB
'?' = AC
'.' = AD
'-' = AE
'·' = AF
'…' = B0
'“' = B1
'”' = B2
'' = B3
'' = B4
'♂' = B5
'♀' = B6
'¥' = B7
',' = B8
'×' = B9
'/' = BA
'A' = BB
'B' = BC
'C' = BD
'D' = BE
'E' = BF
'F' = C0
'G' = C1
'H' = C2
'I' = C3
'J' = C4
'K' = C5
'L' = C6
'M' = C7
'N' = C8
'O' = C9
'P' = CA
'Q' = CB
'R' = CC
'S' = CD
'T' = CE
'U' = CF
'V' = D0
'W' = D1
'X' = D2
'Y' = D3
'Z' = D4
'a' = D5
'b' = D6
'c' = D7
'd' = D8
'e' = D9
'f' = DA
'g' = DB
'h' = DC
'i' = DD
'j' = DE
'k' = DF
'l' = E0
'm' = E1
'n' = E2
'o' = E3
'p' = E4
'q' = E5
'r' = E6
's' = E7
't' = E8
'u' = E9
'v' = EA
'w' = EB
'x' = EC
'y' = ED
'z' = EE
'▶' = EF
':' = F0
'Ä' = F1
'Ö' = F2
'Ü' = F3
'ä' = F4
'ö' = F5
'ü' = F6
TALL_PLUS = FC 0C FB
'$' = FF
@ Hiragana
'あ' = 01
'い' = 02
'う' = 03
'え' = 04
'お' = 05
'か' = 06
'き' = 07
'く' = 08
'け' = 09
'こ' = 0A
'さ' = 0B
'し' = 0C
'す' = 0D
'せ' = 0E
'そ' = 0F
'た' = 10
'ち' = 11
'つ' = 12
'て' = 13
'と' = 14
'な' = 15
'に' = 16
'ぬ' = 17
'ね' = 18
'の' = 19
'は' = 1A
'ひ' = 1B
'ふ' = 1C
'へ' = 1D
'ほ' = 1E
'ま' = 1F
'み' = 20
'む' = 21
'め' = 22
'も' = 23
'や' = 24
'ゆ' = 25
'よ' = 26
'ら' = 27
'り' = 28
'る' = 29
'れ' = 2A
'ろ' = 2B
'わ' = 2C
'を' = 2D
'ん' = 2E
'ぁ' = 2F
'ぃ' = 30
'ぅ' = 31
'ぇ' = 32
'ぉ' = 33
'ゃ' = 34
'ゅ' = 35
'ょ' = 36
'が' = 37
'ぎ' = 38
'ぐ' = 39
'げ' = 3A
'ご' = 3B
'ざ' = 3C
'じ' = 3D
'ず' = 3E
'ぜ' = 3F
'ぞ' = 40
'だ' = 41
'ぢ' = 42
'づ' = 43
'で' = 44
'ど' = 45
'ば' = 46
'び' = 47
'ぶ' = 48
'べ' = 49
'ぼ' = 4A
'ぱ' = 4B
'ぴ' = 4C
'ぷ' = 4D
'ぺ' = 4E
'ぽ' = 4F
'っ' = 50
@ Katakana
'ア' = 51
'イ' = 52
'ウ' = 53
'エ' = 54
'オ' = 55
'カ' = 56
'キ' = 57
'ク' = 58
'ケ' = 59
'コ' = 5A
'サ' = 5B
'シ' = 5C
'ス' = 5D
'セ' = 5E
'ソ' = 5F
'タ' = 60
'チ' = 61
'ツ' = 62
'テ' = 63
'ト' = 64
'ナ' = 65
'ニ' = 66
'ヌ' = 67
'ネ' = 68
'' = 69
'ハ' = 6A
'ヒ' = 6B
'フ' = 6C
'ヘ' = 6D
'ホ' = 6E
'マ' = 6F
'ミ' = 70
'ム' = 71
'メ' = 72
'モ' = 73
'ヤ' = 74
'ユ' = 75
'ヨ' = 76
'ラ' = 77
'リ' = 78
'ル' = 79
'レ' = 7A
'ロ' = 7B
'ワ' = 7C
'ヲ' = 7D
'ン' = 7E
'ァ' = 7F
'ィ' = 80
'ゥ' = 81
'ェ' = 82
'ォ' = 83
'ャ' = 84
'ュ' = 85
'ョ' = 86
'ガ' = 87
'ギ' = 88
'グ' = 89
'ゲ' = 8A
'ゴ' = 8B
'ザ' = 8C
'ジ' = 8D
'ズ' = 8E
'ゼ' = 8F
'ゾ' = 90
'ダ' = 91
'ヂ' = 92
'ヅ' = 93
'デ' = 94
'ド' = 95
'バ' = 96
'ビ' = 97
'ブ' = 98
'ベ' = 99
'ボ' = 9A
'パ' = 9B
'ピ' = 9C
'プ' = 9D
'ペ' = 9E
'ポ' = 9F
'ッ' = A0
@ Japanese punctuation
' ' = 00
'' = AB
'' = AC
'。' = AD
'ー' = AE
'⋯' = B0
STRING = FD
@ string placeholders
PLAYER = FD 01
STR_VAR_1 = FD 02
STR_VAR_2 = FD 03
STR_VAR_3 = FD 04
KUN = FD 05
RIVAL = FD 06
@ version-dependent strings (originally made for Ruby/Sapphire differences)
@ Emerald uses the Sapphire strings (except for VERSION).
VERSION = FD 07 @ "EMERALD"
AQUA = FD 08
MAGMA = FD 09
ARCHIE = FD 0A
MAXIE = FD 0B
KYOGRE = FD 0C
GROUDON = FD 0D
@ battle string placeholders
B_BUFF1 = FD 00
B_BUFF2 = FD 01
B_COPY_VAR_1 = FD 02
B_COPY_VAR_2 = FD 03
B_COPY_VAR_3 = FD 04
B_PLAYER_MON1_NAME = FD 05
B_OPPONENT_MON1_NAME = FD 06
B_PLAYER_MON2_NAME = FD 07
B_OPPONENT_MON2_NAME = FD 08
B_LINK_PLAYER_MON1_NAME = FD 09
B_LINK_OPPONENT_MON1_NAME = FD 0A
B_LINK_PLAYER_MON2_NAME = FD 0B
B_LINK_OPPONENT_MON2_NAME = FD 0C
B_ATK_NAME_WITH_PREFIX_MON1 = FD 0D
B_ATK_PARTNER_NAME = FD 0E
B_ATK_NAME_WITH_PREFIX = FD 0F
B_DEF_NAME_WITH_PREFIX = FD 10
B_EFF_NAME_WITH_PREFIX = FD 11 @ EFF = short for gEffectBattler
B_ACTIVE_NAME_WITH_PREFIX = FD 12
B_SCR_ACTIVE_NAME_WITH_PREFIX = FD 13
B_CURRENT_MOVE = FD 14
B_LAST_MOVE = FD 15
B_LAST_ITEM = FD 16
B_LAST_ABILITY = FD 17
B_ATK_ABILITY = FD 18
B_DEF_ABILITY = FD 19
B_SCR_ACTIVE_ABILITY = FD 1A
B_EFF_ABILITY = FD 1B
B_TRAINER1_CLASS = FD 1C
B_TRAINER1_NAME = FD 1D
B_LINK_PLAYER_NAME = FD 1E
B_LINK_PARTNER_NAME = FD 1F
B_LINK_OPPONENT1_NAME = FD 20
B_LINK_OPPONENT2_NAME = FD 21
B_LINK_SCR_TRAINER_NAME = FD 22
B_PLAYER_NAME = FD 23
B_TRAINER1_LOSE_TEXT = FD 24
B_TRAINER1_WIN_TEXT = FD 25
B_26 = FD 26
B_PC_CREATOR_NAME = FD 27
B_ATK_PREFIX1 = FD 28
B_DEF_PREFIX1 = FD 29
B_ATK_PREFIX2 = FD 2A
B_DEF_PREFIX2 = FD 2B
B_ATK_PREFIX3 = FD 2C
B_DEF_PREFIX3 = FD 2D
B_TRAINER2_CLASS = FD 2E
B_TRAINER2_NAME = FD 2F
B_TRAINER2_LOSE_TEXT = FD 30
B_TRAINER2_WIN_TEXT = FD 31
B_PARTNER_CLASS = FD 32
B_PARTNER_NAME = FD 33
B_BUFF3 = FD 34
@ indicates the end of a town/city name (before " TOWN" or " CITY")
NAME_END = FC 00
@ special 0xF7 character
SPECIAL_F7 = F7
@ more text functions
COLOR = FC 01 @ use a color listed below right after
HIGHLIGHT = FC 02 @ same as fc 01
SHADOW = FC 03 @ same as fc 01
COLOR_HIGHLIGHT_SHADOW = FC 04 @ takes 3 bytes
PALETTE = FC 05 @ used in credits
SIZE = FC 06 @ note that anything other than "SMALL" is invalid
UNKNOWN_7 = FC 07
PAUSE = FC 08 @ manually print the wait byte after this, havent mapped them
PAUSE_UNTIL_PRESS = FC 09
WAIT_SE = FC 0A
PLAY_BGM = FC 0B
ESCAPE = FC 0C
SHIFT_TEXT = FC 0D
UNKNOWN_E = FC 0E
UNKNOWN_F = FC 0F
PLAY_SE = FC 10
CLEAR = FC 11
SKIP = FC 12
CLEAR_TO = FC 13
UNKNOWN_14 = FC 14
JPN = FC 15
ENG = FC 16
PAUSE_MUSIC = FC 17
RESUME_MUSIC = FC 18
@ colors
TRANSPARENT = 00
WHITE = 01
DARK_GRAY = 02
LIGHT_GRAY = 03
RED = 04
LIGHT_RED = 05
GREEN = 06
LIGHT_GREEN = 07
BLUE = 08
LIGHT_BLUE = 09
@ these next colors can be set to anything arbitrary at runtime
@ usually though they'll have the textbox border colors as described below
DYNAMIC_COLOR1 = 0A @ white
DYNAMIC_COLOR2 = 0B @ white with a tinge of green
DYNAMIC_COLOR3 = 0C @ white 2
DYNAMIC_COLOR4 = 0D @ aquamarine
DYNAMIC_COLOR5 = 0E @ blue-green
DYNAMIC_COLOR6 = 0F @ cerulean
@ sound and music
MUS_DUMMY = 00 00
SE_USE_ITEM = 01 00
SE_PC_LOGIN = 02 00
SE_PC_OFF = 03 00
SE_PC_ON = 04 00
SE_SELECT = 05 00
SE_WIN_OPEN = 06 00
SE_WALL_HIT = 07 00
SE_DOOR = 08 00
SE_EXIT = 09 00
SE_LEDGE = 0A 00
SE_BIKE_BELL = 0B 00
SE_NOT_EFFECTIVE = 0C 00
SE_EFFECTIVE = 0D 00
SE_SUPER_EFFECTIVE = 0E 00
SE_BALL_OPEN = 0F 00
SE_FAINT = 10 00
SE_FLEE = 11 00
SE_SLIDING_DOOR = 12 00
SE_SHIP = 13 00
SE_BANG = 14 00
SE_PIN = 15 00
SE_BOO = 16 00
SE_BALL = 17 00
SE_CONTEST_PLACE = 18 00
SE_A = 19 00
SE_I = 1A 00
SE_U = 1B 00
SE_E = 1C 00
SE_O = 1D 00
SE_N = 1E 00
SE_SUCCESS = 1F 00
SE_FAILURE = 20 00
SE_EXP = 21 00
SE_BIKE_HOP = 22 00
SE_SWITCH = 23 00
SE_CLICK = 24 00
SE_FU_ZAKU = 25 00
SE_CONTEST_CONDITION_LOSE = 26 00
SE_LAVARIDGE_FALL_WARP = 27 00
SE_ICE_STAIRS = 28 00
SE_ICE_BREAK = 29 00
SE_ICE_CRACK = 2A 00
SE_FALL = 2B 00
SE_UNLOCK = 2C 00
SE_WARP_IN = 2D 00
SE_WARP_OUT = 2E 00
SE_REPEL = 2F 00
SE_ROTATING_GATE = 30 00
SE_TRUCK_MOVE = 31 00
SE_TRUCK_STOP = 32 00
SE_TRUCK_UNLOAD = 33 00
SE_TRUCK_DOOR = 34 00
SE_BERRY_BLENDER = 35 00
SE_CARD = 36 00
SE_SAVE = 37 00
SE_BALL_BOUNCE_1 = 38 00
SE_BALL_BOUNCE_2 = 39 00
SE_BALL_BOUNCE_3 = 3A 00
SE_BALL_BOUNCE_4 = 3B 00
SE_BALL_TRADE = 3C 00
SE_BALL_THROW = 3D 00
SE_NOTE_C = 3E 00
SE_NOTE_D = 3F 00
SE_NOTE_E = 40 00
SE_NOTE_F = 41 00
SE_NOTE_G = 42 00
SE_NOTE_A = 43 00
SE_NOTE_B = 44 00
SE_NOTE_C_HIGH = 45 00
SE_PUDDLE = 46 00
SE_BRIDGE_WALK = 47 00
SE_ITEMFINDER = 48 00
SE_DING_DONG = 49 00
SE_BALLOON_RED = 4A 00
SE_BALLOON_BLUE = 4B 00
SE_BALLOON_YELLOW = 4C 00
SE_BREAKABLE_DOOR = 4D 00
SE_MUD_BALL = 4E 00
SE_FIELD_POISON = 4F 00
SE_ESCALATOR = 50 00
SE_THUNDERSTORM = 51 00
SE_THUNDERSTORM_STOP = 52 00
SE_DOWNPOUR = 53 00
SE_DOWNPOUR_STOP = 54 00
SE_RAIN = 55 00
SE_RAIN_STOP = 56 00
SE_THUNDER = 57 00
SE_THUNDER2 = 58 00
SE_ELEVATOR = 59 00
SE_LOW_HEALTH = 5A 00
SE_EXP_MAX = 5B 00
SE_ROULETTE_BALL = 5C 00
SE_ROULETTE_BALL2 = 5D 00
SE_TAILLOW_WING_FLAP = 5E 00
SE_SHOP = 5F 00
SE_CONTEST_HEART = 60 00
SE_CONTEST_CURTAIN_RISE = 61 00
SE_CONTEST_CURTAIN_FALL = 62 00
SE_CONTEST_ICON_CHANGE = 63 00
SE_CONTEST_ICON_CLEAR = 64 00
SE_CONTEST_MONS_TURN = 65 00
SE_SHINY = 66 00
SE_INTRO_BLAST = 67 00
SE_MUGSHOT = 68 00
SE_APPLAUSE = 69 00
SE_VEND = 6A 00
SE_ORB = 6B 00
SE_DEX_SCROLL = 6C 00
SE_DEX_PAGE = 6D 00
SE_POKENAV_ON = 6E 00
SE_POKENAV_OFF = 6F 00
SE_DEX_SEARCH = 70 00
SE_EGG_HATCH = 71 00
SE_BALL_TRAY_ENTER = 72 00
SE_BALL_TRAY_BALL = 73 00
SE_BALL_TRAY_EXIT = 74 00
SE_GLASS_FLUTE = 75 00
SE_M_THUNDERBOLT = 76 00
SE_M_THUNDERBOLT2 = 77 00
SE_M_HARDEN = 78 00
SE_M_NIGHTMARE = 79 00
SE_M_VITAL_THROW = 7A 00
SE_M_VITAL_THROW2 = 7B 00
SE_M_BUBBLE = 7C 00
SE_M_BUBBLE2 = 7D 00
SE_M_BUBBLE3 = 7E 00
SE_M_RAIN_DANCE = 7F 00
SE_M_CUT = 80 00
SE_M_STRING_SHOT = 81 00
SE_M_STRING_SHOT2 = 82 00
SE_M_ROCK_THROW = 83 00
SE_M_GUST = 84 00
SE_M_GUST2 = 85 00
SE_M_DOUBLE_SLAP = 86 00
SE_M_DOUBLE_TEAM = 87 00
SE_M_RAZOR_WIND = 88 00
SE_M_ICY_WIND = 89 00
SE_M_THUNDER_WAVE = 8A 00
SE_M_COMET_PUNCH = 8B 00
SE_M_MEGA_KICK = 8C 00
SE_M_MEGA_KICK2 = 8D 00
SE_M_CRABHAMMER = 8E 00
SE_M_JUMP_KICK = 8F 00
SE_M_FLAME_WHEEL = 90 00
SE_M_FLAME_WHEEL2 = 91 00
SE_M_FLAMETHROWER = 92 00
SE_M_FIRE_PUNCH = 93 00
SE_M_TOXIC = 94 00
SE_M_SACRED_FIRE = 95 00
SE_M_SACRED_FIRE2 = 96 00
SE_M_EMBER = 97 00
SE_M_TAKE_DOWN = 98 00
SE_M_BLIZZARD = 99 00
SE_M_BLIZZARD2 = 9A 00
SE_M_SCRATCH = 9B 00
SE_M_VICEGRIP = 9C 00
SE_M_WING_ATTACK = 9D 00
SE_M_FLY = 9E 00
SE_M_SAND_ATTACK = 9F 00
SE_M_RAZOR_WIND2 = A0 00
SE_M_BITE = A1 00
SE_M_HEADBUTT = A2 00
SE_M_SURF = A3 00
SE_M_HYDRO_PUMP = A4 00
SE_M_WHIRLPOOL = A5 00
SE_M_HORN_ATTACK = A6 00
SE_M_TAIL_WHIP = A7 00
SE_M_MIST = A8 00
SE_M_POISON_POWDER = A9 00
SE_M_BIND = AA 00
SE_M_DRAGON_RAGE = AB 00
SE_M_SING = AC 00
SE_M_PERISH_SONG = AD 00
SE_M_PAY_DAY = AE 00
SE_M_DIG = AF 00
SE_M_DIZZY_PUNCH = B0 00
SE_M_SELF_DESTRUCT = B1 00
SE_M_EXPLOSION = B2 00
SE_M_ABSORB_2 = B3 00
SE_M_ABSORB = B4 00
SE_M_SCREECH = B5 00
SE_M_BUBBLE_BEAM = B6 00
SE_M_BUBBLE_BEAM2 = B7 00
SE_M_SUPERSONIC = B8 00
SE_M_BELLY_DRUM = B9 00
SE_M_METRONOME = BA 00
SE_M_BONEMERANG = BB 00
SE_M_LICK = BC 00
SE_M_PSYBEAM = BD 00
SE_M_FAINT_ATTACK = BE 00
SE_M_SWORDS_DANCE = BF 00
SE_M_LEER = C0 00
SE_M_SWAGGER = C1 00
SE_M_SWAGGER2 = C2 00
SE_M_HEAL_BELL = C3 00
SE_M_CONFUSE_RAY = C4 00
SE_M_SNORE = C5 00
SE_M_BRICK_BREAK = C6 00
SE_M_GIGA_DRAIN = C7 00
SE_M_PSYBEAM2 = C8 00
SE_M_SOLAR_BEAM = C9 00
SE_M_PETAL_DANCE = CA 00
SE_M_TELEPORT = CB 00
SE_M_MINIMIZE = CC 00
SE_M_SKETCH = CD 00
SE_M_SWIFT = CE 00
SE_M_REFLECT = CF 00
SE_M_BARRIER = D0 00
SE_M_DETECT = D1 00
SE_M_LOCK_ON = D2 00
SE_M_MOONLIGHT = D3 00
SE_M_CHARM = D4 00
SE_M_CHARGE = D5 00
SE_M_STRENGTH = D6 00
SE_M_HYPER_BEAM = D7 00
SE_M_WATERFALL = D8 00
SE_M_REVERSAL = D9 00
SE_M_ACID_ARMOR = DA 00
SE_M_SANDSTORM = DB 00
SE_M_TRI_ATTACK = DC 00
SE_M_TRI_ATTACK2 = DD 00
SE_M_ENCORE = DE 00
SE_M_ENCORE2 = DF 00
SE_M_BATON_PASS = E0 00
SE_M_MILK_DRINK = E1 00
SE_M_ATTRACT = E2 00
SE_M_ATTRACT2 = E3 00
SE_M_MORNING_SUN = E4 00
SE_M_FLATTER = E5 00
SE_M_SAND_TOMB = E6 00
SE_M_GRASSWHISTLE = E7 00
SE_M_SPIT_UP = E8 00
SE_M_DIVE = E9 00
SE_M_EARTHQUAKE = EA 00
SE_M_TWISTER = EB 00
SE_M_SWEET_SCENT = EC 00
SE_M_YAWN = ED 00
SE_M_SKY_UPPERCUT = EE 00
SE_M_STAT_INCREASE = EF 00
SE_M_HEAT_WAVE = F0 00
SE_M_UPROAR = F1 00
SE_M_HAIL = F2 00
SE_M_COSMIC_POWER = F3 00
SE_M_TEETER_DANCE = F4 00
SE_M_STAT_DECREASE = F5 00
SE_M_HAZE = F6 00
SE_M_HYPER_BEAM2 = F7 00
SE_RG_DOOR = F8 00
SE_RG_CARD_FLIP = F9 00
SE_RG_CARD_FLIPPING = FA 00
SE_RG_CARD_OPEN = FB 00
SE_RG_BAG_CURSOR = FC 00
SE_RG_BAG_POCKET = FD 00
SE_RG_BALL_CLICK = FE 00
SE_RG_SHOP = FF 00
SE_RG_SS_ANNE_HORN = 00 01
SE_RG_HELP_OPEN = 01 01
SE_RG_HELP_CLOSE = 02 01
SE_RG_HELP_ERROR = 03 01
SE_RG_DEOXYS_MOVE = 04 01
SE_RG_POKE_JUMP_SUCCESS = 05 01
SE_RG_POKE_JUMP_FAILURE = 06 01
SE_POKENAV_CALL = 07 01
SE_POKENAV_HANG_UP = 08 01
SE_ARENA_TIMEUP1 = 09 01
SE_ARENA_TIMEUP2 = 0A 01
SE_PIKE_CURTAIN_CLOSE = 0B 01
SE_PIKE_CURTAIN_OPEN = 0C 01
SE_SUDOWOODO_SHAKE = 0D 01
MUS_LITTLEROOT_TEST = 5E 01
MUS_GSC_ROUTE38 = 5F 01
MUS_CAUGHT = 60 01
MUS_VICTORY_WILD = 61 01
MUS_VICTORY_GYM_LEADER = 62 01
MUS_VICTORY_LEAGUE = 63 01
MUS_C_COMM_CENTER = 64 01
MUS_GSC_PEWTER = 65 01
MUS_C_VS_LEGEND_BEAST = 66 01
MUS_ROUTE101 = 67 01
MUS_ROUTE110 = 68 01
MUS_ROUTE120 = 69 01
MUS_PETALBURG = 6A 01
MUS_OLDALE = 6B 01
MUS_GYM = 6C 01
MUS_SURF = 6D 01
MUS_PETALBURG_WOODS = 6E 01
MUS_LEVEL_UP = 6F 01
MUS_HEAL = 70 01
MUS_OBTAIN_BADGE = 71 01
MUS_OBTAIN_ITEM = 72 01
MUS_EVOLVED = 73 01
MUS_OBTAIN_TMHM = 74 01
MUS_LILYCOVE_MUSEUM = 75 01
MUS_ROUTE122 = 76 01
MUS_OCEANIC_MUSEUM = 77 01
MUS_EVOLUTION_INTRO = 78 01
MUS_EVOLUTION = 79 01
MUS_MOVE_DELETED = 7A 01
MUS_ENCOUNTER_GIRL = 7B 01
MUS_ENCOUNTER_MALE = 7C 01
MUS_ABANDONED_SHIP = 7D 01
MUS_FORTREE = 7E 01
MUS_BIRCH_LAB = 7F 01
MUS_B_TOWER_RS = 80 01
MUS_ENCOUNTER_SWIMMER = 81 01
MUS_CAVE_OF_ORIGIN = 82 01
MUS_OBTAIN_BERRY = 83 01
MUS_AWAKEN_LEGEND = 84 01
MUS_SLOTS_JACKPOT = 85 01
MUS_SLOTS_WIN = 86 01
MUS_TOO_BAD = 87 01
MUS_ROULETTE = 88 01
MUS_LINK_CONTEST_P1 = 89 01
MUS_LINK_CONTEST_P2 = 8A 01
MUS_LINK_CONTEST_P3 = 8B 01
MUS_LINK_CONTEST_P4 = 8C 01
MUS_ENCOUNTER_RICH = 8D 01
MUS_VERDANTURF = 8E 01
MUS_RUSTBORO = 8F 01
MUS_POKE_CENTER = 90 01
MUS_ROUTE104 = 91 01
MUS_ROUTE119 = 92 01
MUS_CYCLING = 93 01
MUS_POKE_MART = 94 01
MUS_LITTLEROOT = 95 01
MUS_MT_CHIMNEY = 96 01
MUS_ENCOUNTER_FEMALE = 97 01
MUS_LILYCOVE = 98 01
MUS_ROUTE111 = 99 01
MUS_HELP = 9A 01
MUS_UNDERWATER = 9B 01
MUS_VICTORY_TRAINER = 9C 01
MUS_TITLE = 9D 01
MUS_INTRO = 9E 01
MUS_ENCOUNTER_MAY = 9F 01
MUS_ENCOUNTER_INTENSE = A0 01
MUS_ENCOUNTER_COOL = A1 01
MUS_ROUTE113 = A2 01
MUS_ENCOUNTER_AQUA = A3 01
MUS_FOLLOW_ME = A4 01
MUS_ENCOUNTER_BRENDAN = A5 01
MUS_EVER_GRANDE = A6 01
MUS_ENCOUNTER_SUSPICIOUS = A7 01
MUS_VICTORY_AQUA_MAGMA = A8 01
MUS_CABLE_CAR = A9 01
MUS_GAME_CORNER = AA 01
MUS_DEWFORD = AB 01
MUS_SAFARI_ZONE = AC 01
MUS_VICTORY_ROAD = AD 01
MUS_AQUA_MAGMA_HIDEOUT = AE 01
MUS_SAILING = AF 01
MUS_MT_PYRE = B0 01
MUS_SLATEPORT = B1 01
MUS_MT_PYRE_EXTERIOR = B2 01
MUS_SCHOOL = B3 01
MUS_HALL_OF_FAME = B4 01
MUS_FALLARBOR = B5 01
MUS_SEALED_CHAMBER = B6 01
MUS_CONTEST_WINNER = B7 01
MUS_CONTEST = B8 01
MUS_ENCOUNTER_MAGMA = B9 01
MUS_INTRO_BATTLE = BA 01
MUS_ABNORMAL_WEATHER = BB 01
MUS_WEATHER_GROUDON = BC 01
MUS_SOOTOPOLIS = BD 01
MUS_CONTEST_RESULTS = BE 01
MUS_HALL_OF_FAME_ROOM = BF 01
MUS_TRICK_HOUSE = C0 01
MUS_ENCOUNTER_TWINS = C1 01
MUS_ENCOUNTER_ELITE_FOUR = C2 01
MUS_ENCOUNTER_HIKER = C3 01
MUS_CONTEST_LOBBY = C4 01
MUS_ENCOUNTER_INTERVIEWER = C5 01
MUS_ENCOUNTER_CHAMPION = C6 01
MUS_CREDITS = C7 01
MUS_END = C8 01
MUS_B_FRONTIER = C9 01
MUS_B_ARENA = CA 01
MUS_OBTAIN_B_POINTS = CB 01
MUS_REGISTER_MATCH_CALL = CC 01
MUS_B_PYRAMID = CD 01
MUS_B_PYRAMID_TOP = CE 01
MUS_B_PALACE = CF 01
MUS_RAYQUAZA_APPEARS = D0 01
MUS_B_TOWER = D1 01
MUS_OBTAIN_SYMBOL = D2 01
MUS_B_DOME = D3 01
MUS_B_PIKE = D4 01
MUS_B_FACTORY = D5 01
MUS_VS_RAYQUAZA = D6 01
MUS_VS_FRONTIER_BRAIN = D7 01
MUS_VS_MEW = D8 01
MUS_B_DOME_LOBBY = D9 01
MUS_VS_WILD = DA 01
MUS_VS_AQUA_MAGMA = DB 01
MUS_VS_TRAINER = DC 01
MUS_VS_GYM_LEADER = DD 01
MUS_VS_CHAMPION = DE 01
MUS_VS_REGI = DF 01
MUS_VS_KYOGRE_GROUDON = E0 01
MUS_VS_RIVAL = E1 01
MUS_VS_ELITE_FOUR = E2 01
MUS_VS_AQUA_MAGMA_LEADER = E3 01
MUS_RG_FOLLOW_ME = E4 01
MUS_RG_GAME_CORNER = E5 01
MUS_RG_ROCKET_HIDEOUT = E6 01
MUS_RG_GYM = E7 01
MUS_RG_JIGGLYPUFF = E8 01
MUS_RG_INTRO_FIGHT = E9 01
MUS_RG_TITLE = EA 01
MUS_RG_CINNABAR = EB 01
MUS_RG_LAVENDER = EC 01
MUS_RG_HEAL = ED 01
MUS_RG_CYCLING = EE 01
MUS_RG_ENCOUNTER_ROCKET = EF 01
MUS_RG_ENCOUNTER_GIRL = F0 01
MUS_RG_ENCOUNTER_BOY = F1 01
MUS_RG_HALL_OF_FAME = F2 01
MUS_RG_VIRIDIAN_FOREST = F3 01
MUS_RG_MT_MOON = F4 01
MUS_RG_POKE_MANSION = F5 01
MUS_RG_CREDITS = F6 01
MUS_RG_ROUTE1 = F7 01
MUS_RG_ROUTE24 = F8 01
MUS_RG_ROUTE3 = F9 01
MUS_RG_ROUTE11 = FA 01
MUS_RG_VICTORY_ROAD = FB 01
MUS_RG_VS_GYM_LEADER = FC 01
MUS_RG_VS_TRAINER = FD 01
MUS_RG_VS_WILD = FE 01
MUS_RG_VS_CHAMPION = FF 01
MUS_RG_PALLET = 00 02
MUS_RG_OAK_LAB = 01 02
MUS_RG_OAK = 02 02
MUS_RG_POKE_CENTER = 03 02
MUS_RG_SS_ANNE = 04 02
MUS_RG_SURF = 05 02
MUS_RG_POKE_TOWER = 06 02
MUS_RG_SILPH = 07 02
MUS_RG_FUCHSIA = 08 02
MUS_RG_CELADON = 09 02
MUS_RG_VICTORY_TRAINER = 0A 02
MUS_RG_VICTORY_WILD = 0B 02
MUS_RG_VICTORY_GYM_LEADER = 0C 02
MUS_RG_VERMILLION = 0D 02
MUS_RG_PEWTER = 0E 02
MUS_RG_ENCOUNTER_RIVAL = 0F 02
MUS_RG_RIVAL_EXIT = 10 02
MUS_RG_DEX_RATING = 11 02
MUS_RG_OBTAIN_KEY_ITEM = 12 02
MUS_RG_CAUGHT_INTRO = 13 02
MUS_RG_PHOTO = 14 02
MUS_RG_GAME_FREAK = 15 02
MUS_RG_CAUGHT = 16 02
MUS_RG_NEW_GAME_INSTRUCT = 17 02
MUS_RG_NEW_GAME_INTRO = 18 02
MUS_RG_NEW_GAME_EXIT = 19 02
MUS_RG_POKE_JUMP = 1A 02
MUS_RG_UNION_ROOM = 1B 02
MUS_RG_NET_CENTER = 1C 02
MUS_RG_MYSTERY_GIFT = 1D 02
MUS_RG_BERRY_PICK = 1E 02
MUS_RG_SEVII_CAVE = 1F 02
MUS_RG_TEACHY_TV_SHOW = 20 02
MUS_RG_SEVII_ROUTE = 21 02
MUS_RG_SEVII_DUNGEON = 22 02
MUS_RG_SEVII_123 = 23 02
MUS_RG_SEVII_45 = 24 02
MUS_RG_SEVII_67 = 25 02
MUS_RG_POKE_FLUTE = 26 02
MUS_RG_VS_DEOXYS = 27 02
MUS_RG_VS_MEWTWO = 28 02
MUS_RG_VS_LEGEND = 29 02
MUS_RG_ENCOUNTER_GYM_LEADER = 2A 02
MUS_RG_ENCOUNTER_DEOXYS = 2B 02
MUS_RG_TRAINER_TOWER = 2C 02
MUS_RG_SLOW_PALLET = 2D 02
MUS_RG_TEACHY_TV_MENU = 2E 02
PH_TRAP_BLEND = 2F 02
PH_TRAP_HELD = 30 02
PH_TRAP_SOLO = 31 02
PH_FACE_BLEND = 32 02
PH_FACE_HELD = 33 02
PH_FACE_SOLO = 34 02
PH_CLOTH_BLEND = 35 02
PH_CLOTH_HELD = 36 02
PH_CLOTH_SOLO = 37 02
PH_DRESS_BLEND = 38 02
PH_DRESS_HELD = 39 02
PH_DRESS_SOLO = 3A 02
PH_FLEECE_BLEND = 3B 02
PH_FLEECE_HELD = 3C 02
PH_FLEECE_SOLO = 3D 02
PH_KIT_BLEND = 3E 02
PH_KIT_HELD = 3F 02
PH_KIT_SOLO = 40 02
PH_PRICE_BLEND = 41 02
PH_PRICE_HELD = 42 02
PH_PRICE_SOLO = 43 02
PH_LOT_BLEND = 44 02
PH_LOT_HELD = 45 02
PH_LOT_SOLO = 46 02
PH_GOAT_BLEND = 47 02
PH_GOAT_HELD = 48 02
PH_GOAT_SOLO = 49 02
PH_THOUGHT_BLEND = 4A 02
PH_THOUGHT_HELD = 4B 02
PH_THOUGHT_SOLO = 4C 02
PH_CHOICE_BLEND = 4D 02
PH_CHOICE_HELD = 4E 02
PH_CHOICE_SOLO = 4F 02
PH_MOUTH_BLEND = 50 02
PH_MOUTH_HELD = 51 02
PH_MOUTH_SOLO = 52 02
PH_FOOT_BLEND = 53 02
PH_FOOT_HELD = 54 02
PH_FOOT_SOLO = 55 02
PH_GOOSE_BLEND = 56 02
PH_GOOSE_HELD = 57 02
PH_GOOSE_SOLO = 58 02
PH_STRUT_BLEND = 59 02
PH_STRUT_HELD = 5A 02
PH_STRUT_SOLO = 5B 02
PH_CURE_BLEND = 5C 02
PH_CURE_HELD = 5D 02
PH_CURE_SOLO = 5E 02
PH_NURSE_BLEND = 5F 02
PH_NURSE_HELD = 60 02
PH_NURSE_SOLO = 61 02
A_BUTTON = F8 00
B_BUTTON = F8 01
DPAD_UPDOWN = F8 0A
DPAD_NONE = F8 0C
UP_ARROW_2 = F9 00
DOWN_ARROW_2 = F9 01
LEFT_ARROW_2 = F9 02
RIGHT_ARROW_2 = F9 03
PLUS = F9 04
LV_2 = F9 05
PP = F9 06
ID = F9 07
NO = F9 08
UNDERSCORE = F9 09
CIRCLE_1 = F9 0A
CIRCLE_2 = F9 0B
CIRCLE_3 = F9 0C
CIRCLE_4 = F9 0D
CIRCLE_5 = F9 0E
CIRCLE_6 = F9 0F
CIRCLE_7 = F9 10
CIRCLE_8 = F9 11
CIRCLE_9 = F9 12
ROUND_LEFT_PAREN = F9 13
ROUND_RIGHT_PAREN = F9 14
CIRCLE_DOT = F9 15
TRIANGLE = F9 16
BIG_MULT_X = F9 17
EMOJI_UNDERSCORE = F9 D0
EMOJI_PIPE = F9 D1
EMOJI_HIGHBAR = F9 D2
EMOJI_TILDE = F9 D3
EMOJI_LEFT_PAREN = F9 D4
EMOJI_RIGHT_PAREN = F9 D5
EMOJI_UNION = F9 D6 @ ⊂
EMOJI_GREATER_THAN = F9 D7
EMOJI_LEFT_EYE = F9 D8
EMOJI_RIGHT_EYE = F9 D9
EMOJI_AT = F9 DA
EMOJI_SEMICOLON = F9 DB
EMOJI_PLUS = F9 DC
EMOJI_MINUS = F9 DD
EMOJI_EQUALS = F9 DE
EMOJI_SPIRAL = F9 DF
EMOJI_TONGUE = F9 E0
EMOJI_TRIANGLE_OUTLINE = F9 E1
EMOJI_ACUTE = F9 E2
EMOJI_GRAVE = F9 E3
EMOJI_CIRCLE = F9 E4
EMOJI_TRIANGLE = F9 E5
EMOJI_SQUARE = F9 E6
EMOJI_HEART = F9 E7
EMOJI_MOON = F9 E8
EMOJI_NOTE = F9 E9
EMOJI_BALL = F9 EA
EMOJI_BOLT = F9 EB
EMOJI_LEAF = F9 EC
EMOJI_FIRE = F9 ED
EMOJI_WATER = F9 EE
EMOJI_LEFT_FIST = F9 EF
EMOJI_RIGHT_FIST = F9 F0
EMOJI_BIGWHEEL = F9 F1
EMOJI_SMALLWHEEL = F9 F2
EMOJI_SPHERE = F9 F3
EMOJI_IRRITATED = F9 F4
EMOJI_MISCHIEVOUS = F9 F5
EMOJI_HAPPY = F9 F6
EMOJI_ANGRY = F9 F7
EMOJI_SURPRISED = F9 F8
EMOJI_BIGSMILE = F9 F9
EMOJI_EVIL = F9 FA
EMOJI_TIRED = F9 FB
EMOJI_NEUTRAL = F9 FC
EMOJI_SHOCKED = F9 FD
EMOJI_BIGANGER = F9 FE
'\l' = FA @ scroll up window text
'\p' = FB @ new paragraph
'\n' = FE @ new line

4
berry_fix/data/data.s Normal file
View File

@ -0,0 +1,4 @@
.section .rodata
_data_2f0::
.incbin "data/payload.gba.lz"

14
berry_fix/ld_script.sed Normal file
View File

@ -0,0 +1,14 @@
/<EWRAM>/ {
r sym_ewram.ld
d
}
/<BSS>/ {
r sym_bss.ld
d
}
/<COMMON>/ {
r sym_common.ld
d
}

31
berry_fix/ld_script.txt Normal file
View File

@ -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/ :
{
*(*);
}
}

209
berry_fix/payload/Makefile Normal file
View File

@ -0,0 +1,209 @@
TOOLCHAIN := $(DEVKITARM)
COMPARE ?= 0
# don't use dkP's base_tools anymore
# because the redefinition of $(CC) conflicts
# with when we want to use $(CC) to preprocess files
# thus, manually create the variables for the bin
# files, or use arm-none-eabi binaries on the system
# if dkP is not installed on this system
ifneq (,$(TOOLCHAIN))
ifneq ($(wildcard $(TOOLCHAIN)/bin),)
export PATH := $(TOOLCHAIN)/bin:$(PATH)
endif
endif
PREFIX := arm-none-eabi-
OBJCOPY := $(PREFIX)objcopy
AS := $(PREFIX)as
LD := $(PREFIX)ld
# note: the makefile must be set up so MODERNCC is never called
# if MODERN=0
MODERNCC := $(PREFIX)gcc
ifeq ($(OS),Windows_NT)
EXE := .exe
else
EXE :=
endif
# use arm-none-eabi-cpp for macOS
# as macOS's default compiler is clang
# and clang's preprocessor will warn on \u
# when preprocessing asm files, expecting a unicode literal
# we can't unconditionally use arm-none-eabi-cpp
# as installations which install binutils-arm-none-eabi
# don't come with it
ifneq ($(MODERN),1)
ifeq ($(shell uname -s),Darwin)
CPP := $(PREFIX)cpp
else
CPP := $(CC) -E
endif
else
CPP := $(PREFIX)cpp
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 CC1FLAGS += -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 -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: all 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))
$(C_BUILDDIR)/siirtc.o: CC1FLAGS := -mthumb-interwork
$(C_BUILDDIR)/agb_flash.o: CC1FLAGS := -O1 -mthumb-interwork
$(C_BUILDDIR)/agb_flash_1m.o: CC1FLAGS := -O1 -mthumb-interwork
$(C_BUILDDIR)/agb_flash_mx.o: CC1FLAGS := -O1 -mthumb-interwork
$(C_BUILDDIR)/agb_flash_le.o: CC1FLAGS := -O1 -mthumb-interwork
all: rom
@:
rom: $(ROM)
ifeq ($(COMPARE),1)
@$(SHA1) rom.sha1
endif
# For contributors to make sure a change didn't affect the contents of the ROM.
compare: ; @$(MAKE) COMPARE=1
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) $(CC1FLAGS) -o $(C_BUILDDIR)/$*.s
@echo -e ".text\n\t.align\t2, 0\n" >> $(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 > $@
$(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 $< $@

View File

@ -0,0 +1,82 @@
.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

View File

@ -0,0 +1,46 @@
.include "asm/macros/function.inc"
.include "constants/gba_constants.inc"
.syntax unified
.text
thumb_func_start CpuSet
CpuSet: @ 81E3B64
svc 0xB
bx lr
thumb_func_end CpuSet
thumb_func_start Div
Div: @ 81E3B68
svc 0x6
bx lr
thumb_func_end Div
thumb_func_start Mod
Mod:
svc 0x6
adds r0, r1, 0
bx lr
thumb_func_end Mod
thumb_func_start LZ77UnCompVram
LZ77UnCompVram: @ 81E3B6C
svc 0x12
bx lr
thumb_func_end LZ77UnCompVram
thumb_func_start RegisterRamReset
RegisterRamReset: @ 81E3B80
svc 0x1
bx lr
thumb_func_end RegisterRamReset
thumb_func_start VBlankIntrWait
VBlankIntrWait: @ 81E3BA0
movs r2, 0
svc 0x5
bx lr
thumb_func_end VBlankIntrWait
.align 2, 0 @ Don't pad with nop.

View File

@ -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

View File

@ -0,0 +1,1067 @@
' ' = 00
'À' = 01
'Á' = 02
'Â' = 03
'Ç' = 04
'È' = 05
'É' = 06
'Ê' = 07
'Ë' = 08
'Ì' = 09
'Î' = 0B
'Ï' = 0C
'Ò' = 0D
'Ó' = 0E
'Ô' = 0F
'Œ' = 10
'Ù' = 11
'Ú' = 12
'Û' = 13
'Ñ' = 14
'ß' = 15
'à' = 16
'á' = 17
'ç' = 19
'è' = 1A
'é' = 1B
'ê' = 1C
'ë' = 1D
'ì' = 1E
'î' = 20
'ï' = 21
'ò' = 22
'ó' = 23
'ô' = 24
'œ' = 25
'ù' = 26
'ú' = 27
'û' = 28
'ñ' = 29
'º' = 2A
'ª' = 2B
SUPER_ER = 2C
'&' = 2D
'+' = 2E
LV = 34
'=' = 35
';' = 36
'¿' = 51
'¡' = 52
PK = 53
PKMN = 53 54
POKEBLOCK = 55 56 57 58 59
'Í' = 5A
'%' = 5B
'(' = 5C
')' = 5D
'â' = 68
'í' = 6F
UNK_SPACER = 77
UP_ARROW = 79
DOWN_ARROW = 7A
LEFT_ARROW = 7B
RIGHT_ARROW = 7C
'0' = A1
'1' = A2
'2' = A3
'3' = A4
'4' = A5
'5' = A6
'6' = A7
'7' = A8
'8' = A9
'9' = AA
'!' = AB
'?' = AC
'.' = AD
'-' = AE
'·' = AF
'…' = B0
'“' = B1
'”' = B2
'' = B3
'' = B4
'♂' = B5
'♀' = B6
'¥' = B7
',' = B8
'×' = B9
'/' = BA
'A' = BB
'B' = BC
'C' = BD
'D' = BE
'E' = BF
'F' = C0
'G' = C1
'H' = C2
'I' = C3
'J' = C4
'K' = C5
'L' = C6
'M' = C7
'N' = C8
'O' = C9
'P' = CA
'Q' = CB
'R' = CC
'S' = CD
'T' = CE
'U' = CF
'V' = D0
'W' = D1
'X' = D2
'Y' = D3
'Z' = D4
'a' = D5
'b' = D6
'c' = D7
'd' = D8
'e' = D9
'f' = DA
'g' = DB
'h' = DC
'i' = DD
'j' = DE
'k' = DF
'l' = E0
'm' = E1
'n' = E2
'o' = E3
'p' = E4
'q' = E5
'r' = E6
's' = E7
't' = E8
'u' = E9
'v' = EA
'w' = EB
'x' = EC
'y' = ED
'z' = EE
'▶' = EF
':' = F0
'Ä' = F1
'Ö' = F2
'Ü' = F3
'ä' = F4
'ö' = F5
'ü' = F6
TALL_PLUS = FC 0C FB
'$' = FF
@ Hiragana
'あ' = 01
'い' = 02
'う' = 03
'え' = 04
'お' = 05
'か' = 06
'き' = 07
'く' = 08
'け' = 09
'こ' = 0A
'さ' = 0B
'し' = 0C
'す' = 0D
'せ' = 0E
'そ' = 0F
'た' = 10
'ち' = 11
'つ' = 12
'て' = 13
'と' = 14
'な' = 15
'に' = 16
'ぬ' = 17
'ね' = 18
'の' = 19
'は' = 1A
'ひ' = 1B
'ふ' = 1C
'へ' = 1D
'ほ' = 1E
'ま' = 1F
'み' = 20
'む' = 21
'め' = 22
'も' = 23
'や' = 24
'ゆ' = 25
'よ' = 26
'ら' = 27
'り' = 28
'る' = 29
'れ' = 2A
'ろ' = 2B
'わ' = 2C
'を' = 2D
'ん' = 2E
'ぁ' = 2F
'ぃ' = 30
'ぅ' = 31
'ぇ' = 32
'ぉ' = 33
'ゃ' = 34
'ゅ' = 35
'ょ' = 36
'が' = 37
'ぎ' = 38
'ぐ' = 39
'げ' = 3A
'ご' = 3B
'ざ' = 3C
'じ' = 3D
'ず' = 3E
'ぜ' = 3F
'ぞ' = 40
'だ' = 41
'ぢ' = 42
'づ' = 43
'で' = 44
'ど' = 45
'ば' = 46
'び' = 47
'ぶ' = 48
'べ' = 49
'ぼ' = 4A
'ぱ' = 4B
'ぴ' = 4C
'ぷ' = 4D
'ぺ' = 4E
'ぽ' = 4F
'っ' = 50
@ Katakana
'ア' = 51
'イ' = 52
'ウ' = 53
'エ' = 54
'オ' = 55
'カ' = 56
'キ' = 57
'ク' = 58
'ケ' = 59
'コ' = 5A
'サ' = 5B
'シ' = 5C
'ス' = 5D
'セ' = 5E
'ソ' = 5F
'タ' = 60
'チ' = 61
'ツ' = 62
'テ' = 63
'ト' = 64
'ナ' = 65
'ニ' = 66
'ヌ' = 67
'ネ' = 68
'' = 69
'ハ' = 6A
'ヒ' = 6B
'フ' = 6C
'ヘ' = 6D
'ホ' = 6E
'マ' = 6F
'ミ' = 70
'ム' = 71
'メ' = 72
'モ' = 73
'ヤ' = 74
'ユ' = 75
'ヨ' = 76
'ラ' = 77
'リ' = 78
'ル' = 79
'レ' = 7A
'ロ' = 7B
'ワ' = 7C
'ヲ' = 7D
'ン' = 7E
'ァ' = 7F
'ィ' = 80
'ゥ' = 81
'ェ' = 82
'ォ' = 83
'ャ' = 84
'ュ' = 85
'ョ' = 86
'ガ' = 87
'ギ' = 88
'グ' = 89
'ゲ' = 8A
'ゴ' = 8B
'ザ' = 8C
'ジ' = 8D
'ズ' = 8E
'ゼ' = 8F
'ゾ' = 90
'ダ' = 91
'ヂ' = 92
'ヅ' = 93
'デ' = 94
'ド' = 95
'バ' = 96
'ビ' = 97
'ブ' = 98
'ベ' = 99
'ボ' = 9A
'パ' = 9B
'ピ' = 9C
'プ' = 9D
'ペ' = 9E
'ポ' = 9F
'ッ' = A0
@ Japanese punctuation
' ' = 00
'' = AB
'' = AC
'。' = AD
'ー' = AE
'⋯' = B0
STRING = FD
@ string placeholders
PLAYER = FD 01
STR_VAR_1 = FD 02
STR_VAR_2 = FD 03
STR_VAR_3 = FD 04
KUN = FD 05
RIVAL = FD 06
@ version-dependent strings (originally made for Ruby/Sapphire differences)
@ Emerald uses the Sapphire strings (except for VERSION).
VERSION = FD 07 @ "EMERALD"
AQUA = FD 08
MAGMA = FD 09
ARCHIE = FD 0A
MAXIE = FD 0B
KYOGRE = FD 0C
GROUDON = FD 0D
@ battle string placeholders
B_BUFF1 = FD 00
B_BUFF2 = FD 01
B_COPY_VAR_1 = FD 02
B_COPY_VAR_2 = FD 03
B_COPY_VAR_3 = FD 04
B_PLAYER_MON1_NAME = FD 05
B_OPPONENT_MON1_NAME = FD 06
B_PLAYER_MON2_NAME = FD 07
B_OPPONENT_MON2_NAME = FD 08
B_LINK_PLAYER_MON1_NAME = FD 09
B_LINK_OPPONENT_MON1_NAME = FD 0A
B_LINK_PLAYER_MON2_NAME = FD 0B
B_LINK_OPPONENT_MON2_NAME = FD 0C
B_ATK_NAME_WITH_PREFIX_MON1 = FD 0D
B_ATK_PARTNER_NAME = FD 0E
B_ATK_NAME_WITH_PREFIX = FD 0F
B_DEF_NAME_WITH_PREFIX = FD 10
B_EFF_NAME_WITH_PREFIX = FD 11 @ EFF = short for gEffectBattler
B_ACTIVE_NAME_WITH_PREFIX = FD 12
B_SCR_ACTIVE_NAME_WITH_PREFIX = FD 13
B_CURRENT_MOVE = FD 14
B_LAST_MOVE = FD 15
B_LAST_ITEM = FD 16
B_LAST_ABILITY = FD 17
B_ATK_ABILITY = FD 18
B_DEF_ABILITY = FD 19
B_SCR_ACTIVE_ABILITY = FD 1A
B_EFF_ABILITY = FD 1B
B_TRAINER1_CLASS = FD 1C
B_TRAINER1_NAME = FD 1D
B_LINK_PLAYER_NAME = FD 1E
B_LINK_PARTNER_NAME = FD 1F
B_LINK_OPPONENT1_NAME = FD 20
B_LINK_OPPONENT2_NAME = FD 21
B_LINK_SCR_TRAINER_NAME = FD 22
B_PLAYER_NAME = FD 23
B_TRAINER1_LOSE_TEXT = FD 24
B_TRAINER1_WIN_TEXT = FD 25
B_26 = FD 26
B_PC_CREATOR_NAME = FD 27
B_ATK_PREFIX1 = FD 28
B_DEF_PREFIX1 = FD 29
B_ATK_PREFIX2 = FD 2A
B_DEF_PREFIX2 = FD 2B
B_ATK_PREFIX3 = FD 2C
B_DEF_PREFIX3 = FD 2D
B_TRAINER2_CLASS = FD 2E
B_TRAINER2_NAME = FD 2F
B_TRAINER2_LOSE_TEXT = FD 30
B_TRAINER2_WIN_TEXT = FD 31
B_PARTNER_CLASS = FD 32
B_PARTNER_NAME = FD 33
B_BUFF3 = FD 34
@ indicates the end of a town/city name (before " TOWN" or " CITY")
NAME_END = FC 00
@ special 0xF7 character
SPECIAL_F7 = F7
@ more text functions
COLOR = FC 01 @ use a color listed below right after
HIGHLIGHT = FC 02 @ same as fc 01
SHADOW = FC 03 @ same as fc 01
COLOR_HIGHLIGHT_SHADOW = FC 04 @ takes 3 bytes
PALETTE = FC 05 @ used in credits
SIZE = FC 06 @ note that anything other than "SMALL" is invalid
UNKNOWN_7 = FC 07
PAUSE = FC 08 @ manually print the wait byte after this, havent mapped them
PAUSE_UNTIL_PRESS = FC 09
WAIT_SE = FC 0A
PLAY_BGM = FC 0B
ESCAPE = FC 0C
SHIFT_TEXT = FC 0D
UNKNOWN_E = FC 0E
UNKNOWN_F = FC 0F
PLAY_SE = FC 10
CLEAR = FC 11
SKIP = FC 12
CLEAR_TO = FC 13
UNKNOWN_14 = FC 14
JPN = FC 15
ENG = FC 16
PAUSE_MUSIC = FC 17
RESUME_MUSIC = FC 18
@ colors
TRANSPARENT = 00
WHITE = 01
DARK_GRAY = 02
LIGHT_GRAY = 03
RED = 04
LIGHT_RED = 05
GREEN = 06
LIGHT_GREEN = 07
BLUE = 08
LIGHT_BLUE = 09
@ these next colors can be set to anything arbitrary at runtime
@ usually though they'll have the textbox border colors as described below
DYNAMIC_COLOR1 = 0A @ white
DYNAMIC_COLOR2 = 0B @ white with a tinge of green
DYNAMIC_COLOR3 = 0C @ white 2
DYNAMIC_COLOR4 = 0D @ aquamarine
DYNAMIC_COLOR5 = 0E @ blue-green
DYNAMIC_COLOR6 = 0F @ cerulean
@ sound and music
MUS_DUMMY = 00 00
SE_USE_ITEM = 01 00
SE_PC_LOGIN = 02 00
SE_PC_OFF = 03 00
SE_PC_ON = 04 00
SE_SELECT = 05 00
SE_WIN_OPEN = 06 00
SE_WALL_HIT = 07 00
SE_DOOR = 08 00
SE_EXIT = 09 00
SE_LEDGE = 0A 00
SE_BIKE_BELL = 0B 00
SE_NOT_EFFECTIVE = 0C 00
SE_EFFECTIVE = 0D 00
SE_SUPER_EFFECTIVE = 0E 00
SE_BALL_OPEN = 0F 00
SE_FAINT = 10 00
SE_FLEE = 11 00
SE_SLIDING_DOOR = 12 00
SE_SHIP = 13 00
SE_BANG = 14 00
SE_PIN = 15 00
SE_BOO = 16 00
SE_BALL = 17 00
SE_CONTEST_PLACE = 18 00
SE_A = 19 00
SE_I = 1A 00
SE_U = 1B 00
SE_E = 1C 00
SE_O = 1D 00
SE_N = 1E 00
SE_SUCCESS = 1F 00
SE_FAILURE = 20 00
SE_EXP = 21 00
SE_BIKE_HOP = 22 00
SE_SWITCH = 23 00
SE_CLICK = 24 00
SE_FU_ZAKU = 25 00
SE_CONTEST_CONDITION_LOSE = 26 00
SE_LAVARIDGE_FALL_WARP = 27 00
SE_ICE_STAIRS = 28 00
SE_ICE_BREAK = 29 00
SE_ICE_CRACK = 2A 00
SE_FALL = 2B 00
SE_UNLOCK = 2C 00
SE_WARP_IN = 2D 00
SE_WARP_OUT = 2E 00
SE_REPEL = 2F 00
SE_ROTATING_GATE = 30 00
SE_TRUCK_MOVE = 31 00
SE_TRUCK_STOP = 32 00
SE_TRUCK_UNLOAD = 33 00
SE_TRUCK_DOOR = 34 00
SE_BERRY_BLENDER = 35 00
SE_CARD = 36 00
SE_SAVE = 37 00
SE_BALL_BOUNCE_1 = 38 00
SE_BALL_BOUNCE_2 = 39 00
SE_BALL_BOUNCE_3 = 3A 00
SE_BALL_BOUNCE_4 = 3B 00
SE_BALL_TRADE = 3C 00
SE_BALL_THROW = 3D 00
SE_NOTE_C = 3E 00
SE_NOTE_D = 3F 00
SE_NOTE_E = 40 00
SE_NOTE_F = 41 00
SE_NOTE_G = 42 00
SE_NOTE_A = 43 00
SE_NOTE_B = 44 00
SE_NOTE_C_HIGH = 45 00
SE_PUDDLE = 46 00
SE_BRIDGE_WALK = 47 00
SE_ITEMFINDER = 48 00
SE_DING_DONG = 49 00
SE_BALLOON_RED = 4A 00
SE_BALLOON_BLUE = 4B 00
SE_BALLOON_YELLOW = 4C 00
SE_BREAKABLE_DOOR = 4D 00
SE_MUD_BALL = 4E 00
SE_FIELD_POISON = 4F 00
SE_ESCALATOR = 50 00
SE_THUNDERSTORM = 51 00
SE_THUNDERSTORM_STOP = 52 00
SE_DOWNPOUR = 53 00
SE_DOWNPOUR_STOP = 54 00
SE_RAIN = 55 00
SE_RAIN_STOP = 56 00
SE_THUNDER = 57 00
SE_THUNDER2 = 58 00
SE_ELEVATOR = 59 00
SE_LOW_HEALTH = 5A 00
SE_EXP_MAX = 5B 00
SE_ROULETTE_BALL = 5C 00
SE_ROULETTE_BALL2 = 5D 00
SE_TAILLOW_WING_FLAP = 5E 00
SE_SHOP = 5F 00
SE_CONTEST_HEART = 60 00
SE_CONTEST_CURTAIN_RISE = 61 00
SE_CONTEST_CURTAIN_FALL = 62 00
SE_CONTEST_ICON_CHANGE = 63 00
SE_CONTEST_ICON_CLEAR = 64 00
SE_CONTEST_MONS_TURN = 65 00
SE_SHINY = 66 00
SE_INTRO_BLAST = 67 00
SE_MUGSHOT = 68 00
SE_APPLAUSE = 69 00
SE_VEND = 6A 00
SE_ORB = 6B 00
SE_DEX_SCROLL = 6C 00
SE_DEX_PAGE = 6D 00
SE_POKENAV_ON = 6E 00
SE_POKENAV_OFF = 6F 00
SE_DEX_SEARCH = 70 00
SE_EGG_HATCH = 71 00
SE_BALL_TRAY_ENTER = 72 00
SE_BALL_TRAY_BALL = 73 00
SE_BALL_TRAY_EXIT = 74 00
SE_GLASS_FLUTE = 75 00
SE_M_THUNDERBOLT = 76 00
SE_M_THUNDERBOLT2 = 77 00
SE_M_HARDEN = 78 00
SE_M_NIGHTMARE = 79 00
SE_M_VITAL_THROW = 7A 00
SE_M_VITAL_THROW2 = 7B 00
SE_M_BUBBLE = 7C 00
SE_M_BUBBLE2 = 7D 00
SE_M_BUBBLE3 = 7E 00
SE_M_RAIN_DANCE = 7F 00
SE_M_CUT = 80 00
SE_M_STRING_SHOT = 81 00
SE_M_STRING_SHOT2 = 82 00
SE_M_ROCK_THROW = 83 00
SE_M_GUST = 84 00
SE_M_GUST2 = 85 00
SE_M_DOUBLE_SLAP = 86 00
SE_M_DOUBLE_TEAM = 87 00
SE_M_RAZOR_WIND = 88 00
SE_M_ICY_WIND = 89 00
SE_M_THUNDER_WAVE = 8A 00
SE_M_COMET_PUNCH = 8B 00
SE_M_MEGA_KICK = 8C 00
SE_M_MEGA_KICK2 = 8D 00
SE_M_CRABHAMMER = 8E 00
SE_M_JUMP_KICK = 8F 00
SE_M_FLAME_WHEEL = 90 00
SE_M_FLAME_WHEEL2 = 91 00
SE_M_FLAMETHROWER = 92 00
SE_M_FIRE_PUNCH = 93 00
SE_M_TOXIC = 94 00
SE_M_SACRED_FIRE = 95 00
SE_M_SACRED_FIRE2 = 96 00
SE_M_EMBER = 97 00
SE_M_TAKE_DOWN = 98 00
SE_M_BLIZZARD = 99 00
SE_M_BLIZZARD2 = 9A 00
SE_M_SCRATCH = 9B 00
SE_M_VICEGRIP = 9C 00
SE_M_WING_ATTACK = 9D 00
SE_M_FLY = 9E 00
SE_M_SAND_ATTACK = 9F 00
SE_M_RAZOR_WIND2 = A0 00
SE_M_BITE = A1 00
SE_M_HEADBUTT = A2 00
SE_M_SURF = A3 00
SE_M_HYDRO_PUMP = A4 00
SE_M_WHIRLPOOL = A5 00
SE_M_HORN_ATTACK = A6 00
SE_M_TAIL_WHIP = A7 00
SE_M_MIST = A8 00
SE_M_POISON_POWDER = A9 00
SE_M_BIND = AA 00
SE_M_DRAGON_RAGE = AB 00
SE_M_SING = AC 00
SE_M_PERISH_SONG = AD 00
SE_M_PAY_DAY = AE 00
SE_M_DIG = AF 00
SE_M_DIZZY_PUNCH = B0 00
SE_M_SELF_DESTRUCT = B1 00
SE_M_EXPLOSION = B2 00
SE_M_ABSORB_2 = B3 00
SE_M_ABSORB = B4 00
SE_M_SCREECH = B5 00
SE_M_BUBBLE_BEAM = B6 00
SE_M_BUBBLE_BEAM2 = B7 00
SE_M_SUPERSONIC = B8 00
SE_M_BELLY_DRUM = B9 00
SE_M_METRONOME = BA 00
SE_M_BONEMERANG = BB 00
SE_M_LICK = BC 00
SE_M_PSYBEAM = BD 00
SE_M_FAINT_ATTACK = BE 00
SE_M_SWORDS_DANCE = BF 00
SE_M_LEER = C0 00
SE_M_SWAGGER = C1 00
SE_M_SWAGGER2 = C2 00
SE_M_HEAL_BELL = C3 00
SE_M_CONFUSE_RAY = C4 00
SE_M_SNORE = C5 00
SE_M_BRICK_BREAK = C6 00
SE_M_GIGA_DRAIN = C7 00
SE_M_PSYBEAM2 = C8 00
SE_M_SOLAR_BEAM = C9 00
SE_M_PETAL_DANCE = CA 00
SE_M_TELEPORT = CB 00
SE_M_MINIMIZE = CC 00
SE_M_SKETCH = CD 00
SE_M_SWIFT = CE 00
SE_M_REFLECT = CF 00
SE_M_BARRIER = D0 00
SE_M_DETECT = D1 00
SE_M_LOCK_ON = D2 00
SE_M_MOONLIGHT = D3 00
SE_M_CHARM = D4 00
SE_M_CHARGE = D5 00
SE_M_STRENGTH = D6 00
SE_M_HYPER_BEAM = D7 00
SE_M_WATERFALL = D8 00
SE_M_REVERSAL = D9 00
SE_M_ACID_ARMOR = DA 00
SE_M_SANDSTORM = DB 00
SE_M_TRI_ATTACK = DC 00
SE_M_TRI_ATTACK2 = DD 00
SE_M_ENCORE = DE 00
SE_M_ENCORE2 = DF 00
SE_M_BATON_PASS = E0 00
SE_M_MILK_DRINK = E1 00
SE_M_ATTRACT = E2 00
SE_M_ATTRACT2 = E3 00
SE_M_MORNING_SUN = E4 00
SE_M_FLATTER = E5 00
SE_M_SAND_TOMB = E6 00
SE_M_GRASSWHISTLE = E7 00
SE_M_SPIT_UP = E8 00
SE_M_DIVE = E9 00
SE_M_EARTHQUAKE = EA 00
SE_M_TWISTER = EB 00
SE_M_SWEET_SCENT = EC 00
SE_M_YAWN = ED 00
SE_M_SKY_UPPERCUT = EE 00
SE_M_STAT_INCREASE = EF 00
SE_M_HEAT_WAVE = F0 00
SE_M_UPROAR = F1 00
SE_M_HAIL = F2 00
SE_M_COSMIC_POWER = F3 00
SE_M_TEETER_DANCE = F4 00
SE_M_STAT_DECREASE = F5 00
SE_M_HAZE = F6 00
SE_M_HYPER_BEAM2 = F7 00
SE_RG_DOOR = F8 00
SE_RG_CARD_FLIP = F9 00
SE_RG_CARD_FLIPPING = FA 00
SE_RG_CARD_OPEN = FB 00
SE_RG_BAG_CURSOR = FC 00
SE_RG_BAG_POCKET = FD 00
SE_RG_BALL_CLICK = FE 00
SE_RG_SHOP = FF 00
SE_RG_SS_ANNE_HORN = 00 01
SE_RG_HELP_OPEN = 01 01
SE_RG_HELP_CLOSE = 02 01
SE_RG_HELP_ERROR = 03 01
SE_RG_DEOXYS_MOVE = 04 01
SE_RG_POKE_JUMP_SUCCESS = 05 01
SE_RG_POKE_JUMP_FAILURE = 06 01
SE_POKENAV_CALL = 07 01
SE_POKENAV_HANG_UP = 08 01
SE_ARENA_TIMEUP1 = 09 01
SE_ARENA_TIMEUP2 = 0A 01
SE_PIKE_CURTAIN_CLOSE = 0B 01
SE_PIKE_CURTAIN_OPEN = 0C 01
SE_SUDOWOODO_SHAKE = 0D 01
MUS_LITTLEROOT_TEST = 5E 01
MUS_GSC_ROUTE38 = 5F 01
MUS_CAUGHT = 60 01
MUS_VICTORY_WILD = 61 01
MUS_VICTORY_GYM_LEADER = 62 01
MUS_VICTORY_LEAGUE = 63 01
MUS_C_COMM_CENTER = 64 01
MUS_GSC_PEWTER = 65 01
MUS_C_VS_LEGEND_BEAST = 66 01
MUS_ROUTE101 = 67 01
MUS_ROUTE110 = 68 01
MUS_ROUTE120 = 69 01
MUS_PETALBURG = 6A 01
MUS_OLDALE = 6B 01
MUS_GYM = 6C 01
MUS_SURF = 6D 01
MUS_PETALBURG_WOODS = 6E 01
MUS_LEVEL_UP = 6F 01
MUS_HEAL = 70 01
MUS_OBTAIN_BADGE = 71 01
MUS_OBTAIN_ITEM = 72 01
MUS_EVOLVED = 73 01
MUS_OBTAIN_TMHM = 74 01
MUS_LILYCOVE_MUSEUM = 75 01
MUS_ROUTE122 = 76 01
MUS_OCEANIC_MUSEUM = 77 01
MUS_EVOLUTION_INTRO = 78 01
MUS_EVOLUTION = 79 01
MUS_MOVE_DELETED = 7A 01
MUS_ENCOUNTER_GIRL = 7B 01
MUS_ENCOUNTER_MALE = 7C 01
MUS_ABANDONED_SHIP = 7D 01
MUS_FORTREE = 7E 01
MUS_BIRCH_LAB = 7F 01
MUS_B_TOWER_RS = 80 01
MUS_ENCOUNTER_SWIMMER = 81 01
MUS_CAVE_OF_ORIGIN = 82 01
MUS_OBTAIN_BERRY = 83 01
MUS_AWAKEN_LEGEND = 84 01
MUS_SLOTS_JACKPOT = 85 01
MUS_SLOTS_WIN = 86 01
MUS_TOO_BAD = 87 01
MUS_ROULETTE = 88 01
MUS_LINK_CONTEST_P1 = 89 01
MUS_LINK_CONTEST_P2 = 8A 01
MUS_LINK_CONTEST_P3 = 8B 01
MUS_LINK_CONTEST_P4 = 8C 01
MUS_ENCOUNTER_RICH = 8D 01
MUS_VERDANTURF = 8E 01
MUS_RUSTBORO = 8F 01
MUS_POKE_CENTER = 90 01
MUS_ROUTE104 = 91 01
MUS_ROUTE119 = 92 01
MUS_CYCLING = 93 01
MUS_POKE_MART = 94 01
MUS_LITTLEROOT = 95 01
MUS_MT_CHIMNEY = 96 01
MUS_ENCOUNTER_FEMALE = 97 01
MUS_LILYCOVE = 98 01
MUS_ROUTE111 = 99 01
MUS_HELP = 9A 01
MUS_UNDERWATER = 9B 01
MUS_VICTORY_TRAINER = 9C 01
MUS_TITLE = 9D 01
MUS_INTRO = 9E 01
MUS_ENCOUNTER_MAY = 9F 01
MUS_ENCOUNTER_INTENSE = A0 01
MUS_ENCOUNTER_COOL = A1 01
MUS_ROUTE113 = A2 01
MUS_ENCOUNTER_AQUA = A3 01
MUS_FOLLOW_ME = A4 01
MUS_ENCOUNTER_BRENDAN = A5 01
MUS_EVER_GRANDE = A6 01
MUS_ENCOUNTER_SUSPICIOUS = A7 01
MUS_VICTORY_AQUA_MAGMA = A8 01
MUS_CABLE_CAR = A9 01
MUS_GAME_CORNER = AA 01
MUS_DEWFORD = AB 01
MUS_SAFARI_ZONE = AC 01
MUS_VICTORY_ROAD = AD 01
MUS_AQUA_MAGMA_HIDEOUT = AE 01
MUS_SAILING = AF 01
MUS_MT_PYRE = B0 01
MUS_SLATEPORT = B1 01
MUS_MT_PYRE_EXTERIOR = B2 01
MUS_SCHOOL = B3 01
MUS_HALL_OF_FAME = B4 01
MUS_FALLARBOR = B5 01
MUS_SEALED_CHAMBER = B6 01
MUS_CONTEST_WINNER = B7 01
MUS_CONTEST = B8 01
MUS_ENCOUNTER_MAGMA = B9 01
MUS_INTRO_BATTLE = BA 01
MUS_ABNORMAL_WEATHER = BB 01
MUS_WEATHER_GROUDON = BC 01
MUS_SOOTOPOLIS = BD 01
MUS_CONTEST_RESULTS = BE 01
MUS_HALL_OF_FAME_ROOM = BF 01
MUS_TRICK_HOUSE = C0 01
MUS_ENCOUNTER_TWINS = C1 01
MUS_ENCOUNTER_ELITE_FOUR = C2 01
MUS_ENCOUNTER_HIKER = C3 01
MUS_CONTEST_LOBBY = C4 01
MUS_ENCOUNTER_INTERVIEWER = C5 01
MUS_ENCOUNTER_CHAMPION = C6 01
MUS_CREDITS = C7 01
MUS_END = C8 01
MUS_B_FRONTIER = C9 01
MUS_B_ARENA = CA 01
MUS_OBTAIN_B_POINTS = CB 01
MUS_REGISTER_MATCH_CALL = CC 01
MUS_B_PYRAMID = CD 01
MUS_B_PYRAMID_TOP = CE 01
MUS_B_PALACE = CF 01
MUS_RAYQUAZA_APPEARS = D0 01
MUS_B_TOWER = D1 01
MUS_OBTAIN_SYMBOL = D2 01
MUS_B_DOME = D3 01
MUS_B_PIKE = D4 01
MUS_B_FACTORY = D5 01
MUS_VS_RAYQUAZA = D6 01
MUS_VS_FRONTIER_BRAIN = D7 01
MUS_VS_MEW = D8 01
MUS_B_DOME_LOBBY = D9 01
MUS_VS_WILD = DA 01
MUS_VS_AQUA_MAGMA = DB 01
MUS_VS_TRAINER = DC 01
MUS_VS_GYM_LEADER = DD 01
MUS_VS_CHAMPION = DE 01
MUS_VS_REGI = DF 01
MUS_VS_KYOGRE_GROUDON = E0 01
MUS_VS_RIVAL = E1 01
MUS_VS_ELITE_FOUR = E2 01
MUS_VS_AQUA_MAGMA_LEADER = E3 01
MUS_RG_FOLLOW_ME = E4 01
MUS_RG_GAME_CORNER = E5 01
MUS_RG_ROCKET_HIDEOUT = E6 01
MUS_RG_GYM = E7 01
MUS_RG_JIGGLYPUFF = E8 01
MUS_RG_INTRO_FIGHT = E9 01
MUS_RG_TITLE = EA 01
MUS_RG_CINNABAR = EB 01
MUS_RG_LAVENDER = EC 01
MUS_RG_HEAL = ED 01
MUS_RG_CYCLING = EE 01
MUS_RG_ENCOUNTER_ROCKET = EF 01
MUS_RG_ENCOUNTER_GIRL = F0 01
MUS_RG_ENCOUNTER_BOY = F1 01
MUS_RG_HALL_OF_FAME = F2 01
MUS_RG_VIRIDIAN_FOREST = F3 01
MUS_RG_MT_MOON = F4 01
MUS_RG_POKE_MANSION = F5 01
MUS_RG_CREDITS = F6 01
MUS_RG_ROUTE1 = F7 01
MUS_RG_ROUTE24 = F8 01
MUS_RG_ROUTE3 = F9 01
MUS_RG_ROUTE11 = FA 01
MUS_RG_VICTORY_ROAD = FB 01
MUS_RG_VS_GYM_LEADER = FC 01
MUS_RG_VS_TRAINER = FD 01
MUS_RG_VS_WILD = FE 01
MUS_RG_VS_CHAMPION = FF 01
MUS_RG_PALLET = 00 02
MUS_RG_OAK_LAB = 01 02
MUS_RG_OAK = 02 02
MUS_RG_POKE_CENTER = 03 02
MUS_RG_SS_ANNE = 04 02
MUS_RG_SURF = 05 02
MUS_RG_POKE_TOWER = 06 02
MUS_RG_SILPH = 07 02
MUS_RG_FUCHSIA = 08 02
MUS_RG_CELADON = 09 02
MUS_RG_VICTORY_TRAINER = 0A 02
MUS_RG_VICTORY_WILD = 0B 02
MUS_RG_VICTORY_GYM_LEADER = 0C 02
MUS_RG_VERMILLION = 0D 02
MUS_RG_PEWTER = 0E 02
MUS_RG_ENCOUNTER_RIVAL = 0F 02
MUS_RG_RIVAL_EXIT = 10 02
MUS_RG_DEX_RATING = 11 02
MUS_RG_OBTAIN_KEY_ITEM = 12 02
MUS_RG_CAUGHT_INTRO = 13 02
MUS_RG_PHOTO = 14 02
MUS_RG_GAME_FREAK = 15 02
MUS_RG_CAUGHT = 16 02
MUS_RG_NEW_GAME_INSTRUCT = 17 02
MUS_RG_NEW_GAME_INTRO = 18 02
MUS_RG_NEW_GAME_EXIT = 19 02
MUS_RG_POKE_JUMP = 1A 02
MUS_RG_UNION_ROOM = 1B 02
MUS_RG_NET_CENTER = 1C 02
MUS_RG_MYSTERY_GIFT = 1D 02
MUS_RG_BERRY_PICK = 1E 02
MUS_RG_SEVII_CAVE = 1F 02
MUS_RG_TEACHY_TV_SHOW = 20 02
MUS_RG_SEVII_ROUTE = 21 02
MUS_RG_SEVII_DUNGEON = 22 02
MUS_RG_SEVII_123 = 23 02
MUS_RG_SEVII_45 = 24 02
MUS_RG_SEVII_67 = 25 02
MUS_RG_POKE_FLUTE = 26 02
MUS_RG_VS_DEOXYS = 27 02
MUS_RG_VS_MEWTWO = 28 02
MUS_RG_VS_LEGEND = 29 02
MUS_RG_ENCOUNTER_GYM_LEADER = 2A 02
MUS_RG_ENCOUNTER_DEOXYS = 2B 02
MUS_RG_TRAINER_TOWER = 2C 02
MUS_RG_SLOW_PALLET = 2D 02
MUS_RG_TEACHY_TV_MENU = 2E 02
PH_TRAP_BLEND = 2F 02
PH_TRAP_HELD = 30 02
PH_TRAP_SOLO = 31 02
PH_FACE_BLEND = 32 02
PH_FACE_HELD = 33 02
PH_FACE_SOLO = 34 02
PH_CLOTH_BLEND = 35 02
PH_CLOTH_HELD = 36 02
PH_CLOTH_SOLO = 37 02
PH_DRESS_BLEND = 38 02
PH_DRESS_HELD = 39 02
PH_DRESS_SOLO = 3A 02
PH_FLEECE_BLEND = 3B 02
PH_FLEECE_HELD = 3C 02
PH_FLEECE_SOLO = 3D 02
PH_KIT_BLEND = 3E 02
PH_KIT_HELD = 3F 02
PH_KIT_SOLO = 40 02
PH_PRICE_BLEND = 41 02
PH_PRICE_HELD = 42 02
PH_PRICE_SOLO = 43 02
PH_LOT_BLEND = 44 02
PH_LOT_HELD = 45 02
PH_LOT_SOLO = 46 02
PH_GOAT_BLEND = 47 02
PH_GOAT_HELD = 48 02
PH_GOAT_SOLO = 49 02
PH_THOUGHT_BLEND = 4A 02
PH_THOUGHT_HELD = 4B 02
PH_THOUGHT_SOLO = 4C 02
PH_CHOICE_BLEND = 4D 02
PH_CHOICE_HELD = 4E 02
PH_CHOICE_SOLO = 4F 02
PH_MOUTH_BLEND = 50 02
PH_MOUTH_HELD = 51 02
PH_MOUTH_SOLO = 52 02
PH_FOOT_BLEND = 53 02
PH_FOOT_HELD = 54 02
PH_FOOT_SOLO = 55 02
PH_GOOSE_BLEND = 56 02
PH_GOOSE_HELD = 57 02
PH_GOOSE_SOLO = 58 02
PH_STRUT_BLEND = 59 02
PH_STRUT_HELD = 5A 02
PH_STRUT_SOLO = 5B 02
PH_CURE_BLEND = 5C 02
PH_CURE_HELD = 5D 02
PH_CURE_SOLO = 5E 02
PH_NURSE_BLEND = 5F 02
PH_NURSE_HELD = 60 02
PH_NURSE_SOLO = 61 02
A_BUTTON = F8 00
B_BUTTON = F8 01
DPAD_UPDOWN = F8 0A
DPAD_NONE = F8 0C
UP_ARROW_2 = F9 00
DOWN_ARROW_2 = F9 01
LEFT_ARROW_2 = F9 02
RIGHT_ARROW_2 = F9 03
PLUS = F9 04
LV_2 = F9 05
PP = F9 06
ID = F9 07
NO = F9 08
UNDERSCORE = F9 09
CIRCLE_1 = F9 0A
CIRCLE_2 = F9 0B
CIRCLE_3 = F9 0C
CIRCLE_4 = F9 0D
CIRCLE_5 = F9 0E
CIRCLE_6 = F9 0F
CIRCLE_7 = F9 10
CIRCLE_8 = F9 11
CIRCLE_9 = F9 12
ROUND_LEFT_PAREN = F9 13
ROUND_RIGHT_PAREN = F9 14
CIRCLE_DOT = F9 15
TRIANGLE = F9 16
BIG_MULT_X = F9 17
EMOJI_UNDERSCORE = F9 D0
EMOJI_PIPE = F9 D1
EMOJI_HIGHBAR = F9 D2
EMOJI_TILDE = F9 D3
EMOJI_LEFT_PAREN = F9 D4
EMOJI_RIGHT_PAREN = F9 D5
EMOJI_UNION = F9 D6 @ ⊂
EMOJI_GREATER_THAN = F9 D7
EMOJI_LEFT_EYE = F9 D8
EMOJI_RIGHT_EYE = F9 D9
EMOJI_AT = F9 DA
EMOJI_SEMICOLON = F9 DB
EMOJI_PLUS = F9 DC
EMOJI_MINUS = F9 DD
EMOJI_EQUALS = F9 DE
EMOJI_SPIRAL = F9 DF
EMOJI_TONGUE = F9 E0
EMOJI_TRIANGLE_OUTLINE = F9 E1
EMOJI_ACUTE = F9 E2
EMOJI_GRAVE = F9 E3
EMOJI_CIRCLE = F9 E4
EMOJI_TRIANGLE = F9 E5
EMOJI_SQUARE = F9 E6
EMOJI_HEART = F9 E7
EMOJI_MOON = F9 E8
EMOJI_NOTE = F9 E9
EMOJI_BALL = F9 EA
EMOJI_BOLT = F9 EB
EMOJI_LEAF = F9 EC
EMOJI_FIRE = F9 ED
EMOJI_WATER = F9 EE
EMOJI_LEFT_FIST = F9 EF
EMOJI_RIGHT_FIST = F9 F0
EMOJI_BIGWHEEL = F9 F1
EMOJI_SMALLWHEEL = F9 F2
EMOJI_SPHERE = F9 F3
EMOJI_IRRITATED = F9 F4
EMOJI_MISCHIEVOUS = F9 F5
EMOJI_HAPPY = F9 F6
EMOJI_ANGRY = F9 F7
EMOJI_SURPRISED = F9 F8
EMOJI_BIGSMILE = F9 F9
EMOJI_EVIL = F9 FA
EMOJI_TIRED = F9 FB
EMOJI_NEUTRAL = F9 FC
EMOJI_SHOCKED = F9 FD
EMOJI_BIGANGER = F9 FE
'\l' = FA @ scroll up window text
'\p' = FB @ new paragraph
'\n' = FE @ new line

View File

@ -0,0 +1,10 @@
gFlashTimeoutFlag
PollFlashStatus
WaitForFlashWrite
ProgramFlashSector
gFlash
ProgramFlashByte
gFlashNumRemainingBytes
EraseFlashChip
EraseFlashSector
gFlashMaxTime

View File

@ -0,0 +1,9 @@
gIntrTable
gHeldKeys
gNewKeys
gIntrVector
gUpdateSuccessful
gUnknown_3001194
gUnknown_30011A0
gMainCallbackState
gGameVersion

View File

@ -0,0 +1,2 @@
gTimeSinceBerryUpdate
gRtcUTCTime

View File

@ -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.

View File

@ -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

View File

@ -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_MAP_SCENE_SIX_ISLAND_POKEMON_CENTER_1F 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_VOLCANIC_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

View File

@ -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

View File

@ -0,0 +1,87 @@
#ifndef GUARD_GBA_DEFINES_H
#define GUARD_GBA_DEFINES_H
#include <stddef.h>
#define TRUE 1
#define FALSE 0
#define BSS_DATA __attribute__((section(".bss")))
#define IWRAM_DATA __attribute__((section("iwram_data")))
#define EWRAM_DATA __attribute__((section("ewram_data")))
#define UNUSED __attribute__((unused))
#define NAKED __attribute__((naked))
#define ALIGNED(n) __attribute__((aligned(n)))
#define SOUND_INFO_PTR (*(struct SoundInfo **)0x3007FF0)
#define INTR_CHECK (*(u16 *)0x3007FF8)
#define INTR_VECTOR (*(void **)0x3007FFC)
#define EWRAM_START 0x02000000
#define EWRAM_END (EWRAM_START + 0x40000)
#define IWRAM_START 0x03000000
#define IWRAM_END (IWRAM_START + 0x8000)
#define PLTT 0x5000000
#define PLTT_SIZE 0x400
#define BG_PLTT PLTT
#define BG_PLTT_SIZE 0x200
#define OBJ_PLTT (PLTT + 0x200)
#define OBJ_PLTT_SIZE 0x200
#define VRAM 0x6000000
#define VRAM_SIZE 0x18000
#define BG_VRAM VRAM
#define BG_VRAM_SIZE 0x10000
#define BG_CHAR_SIZE 0x4000
#define BG_SCREEN_SIZE 0x800
#define BG_CHAR_ADDR(n) (void *)(BG_VRAM + (0x4000 * (n)))
#define BG_SCREEN_ADDR(n) (void *)(BG_VRAM + (0x800 * (n)))
#define BG_TILE_ADDR(n) (void *)(BG_VRAM + (0x80 * (n)))
#define BG_TILE_H_FLIP(n) (0x400 + (n))
#define BG_TILE_V_FLIP(n) (0x800 + (n))
// text-mode BG
#define OBJ_VRAM0 (void *)(VRAM + 0x10000)
#define OBJ_VRAM0_SIZE 0x8000
// bitmap-mode BG
#define OBJ_VRAM1 (void *)(VRAM + 0x14000)
#define OBJ_VRAM1_SIZE 0x4000
#define OAM 0x7000000
#define OAM_SIZE 0x400
#define ROM_HEADER_SIZE 0xC0
#define DISPLAY_WIDTH 240
#define DISPLAY_HEIGHT 160
#define TILE_SIZE_4BPP 32
#define TILE_SIZE_8BPP 64
#define TILE_OFFSET_4BPP(n) ((n) * TILE_SIZE_4BPP)
#define TILE_OFFSET_8BPP(n) ((n) * TILE_SIZE_8BPP)
#define TOTAL_OBJ_TILE_COUNT 1024
#define RGB(r, g, b) ((r) | ((g) << 5) | ((b) << 10))
#define RGB2(r, g, b) (((b) << 10) | ((g) << 5) | (r))
#define _RGB(r, g, b) ((((b) & 0x1F) << 10) + (((g) & 0x1F) << 5) + ((r) & 0x1F))
#define RGB_BLACK RGB(0, 0, 0)
#define RGB_WHITE RGB(31, 31, 31)
#define RGB_RED RGB(31, 0, 0)
#define RGB_GREEN RGB(0, 31, 0)
#define RGB_BLUE RGB(0, 0, 31)
#define RGB_YELLOW RGB(31, 31, 0)
#define RGB_MAGENTA RGB(31, 0, 31)
#define RGB_CYAN RGB(0, 31, 31)
#define RGB_WHITEALPHA (RGB_WHITE | 0x8000)
#endif // GUARD_GBA_DEFINES_H

View File

@ -0,0 +1,85 @@
#ifndef GUARD_GBA_FLASH_INTERNAL_H
#define GUARD_GBA_FLASH_INTERNAL_H
#include "gba/gba.h"
#define FLASH_BASE ((u8 *)0xE000000)
#define FLASH_WRITE(addr, data) ((*(vu8 *)(FLASH_BASE + (addr))) = (data))
#define FLASH_ROM_SIZE_1M 131072 // 1 megabit ROM
#define SECTORS_PER_BANK 16
struct FlashSector
{
u32 size;
u8 shift;
u16 count;
u16 top;
};
struct FlashType {
u32 romSize;
struct FlashSector sector;
u16 wait[2]; // game pak bus read/write wait
// TODO: add support for anonymous unions/structs if possible
union {
struct {
u8 makerId;
u8 deviceId;
} separate;
u16 joined;
} ids;
};
struct FlashSetupInfo
{
u16 (*programFlashByte)(u16, u32, u8);
u16 (*programFlashSector)(u16, void *);
u16 (*eraseFlashChip)(void);
u16 (*eraseFlashSector)(u16);
u16 (*WaitForFlashWrite)(u8, u8 *, u8);
const u16 *maxTime;
struct FlashType type;
};
extern u16 gFlashNumRemainingBytes;
extern u16 (*ProgramFlashByte)(u16, u32, u8);
extern u16 (*ProgramFlashSector)(u16, void *);
extern u16 (*EraseFlashChip)(void);
extern u16 (*EraseFlashSector)(u16);
extern u16 (*WaitForFlashWrite)(u8, u8 *, u8);
extern const u16 *gFlashMaxTime;
extern const struct FlashType *gFlash;
extern u8 (*PollFlashStatus)(u8 *);
extern u8 gFlashTimeoutFlag;
extern const struct FlashSetupInfo MX29L010;
extern const struct FlashSetupInfo LE26FV10N1TS;
extern const struct FlashSetupInfo DefaultFlash;
void SwitchFlashBank(u8 bankNum);
u16 ReadFlashId(void);
void StartFlashTimer(u8 phase);
void SetReadFlash1(u16 *dest);
void StopFlashTimer(void);
u16 SetFlashTimerIntr(u8 timerNum, void (**intrFunc)(void));
u32 ProgramFlashSectorAndVerify(u16 sectorNum, u8 *src);
void ReadFlash(u16 sectorNum, u32 offset, void *dest, u32 size);
u32 ProgramFlashSectorAndVerifyNBytes(u16 sectorNum, void *dataSrc, u32 n);
u16 WaitForFlashWrite_Common(u8 phase, u8 *addr, u8 lastData);
u16 EraseFlashChip_MX(void);
u16 EraseFlashSector_MX(u16 sectorNum);
u16 ProgramFlashByte_MX(u16 sectorNum, u32 offset, u8 data);
u16 ProgramFlashSector_MX(u16 sectorNum, void *src);
// agb_flash_1m
u32 IdentifyFlash(void);
#endif // GUARD_GBA_FLASH_INTERNAL_H

View File

@ -0,0 +1,12 @@
#ifndef GUARD_GBA_GBA_H
#define GUARD_GBA_GBA_H
#include "gba/defines.h"
#include "gba/io_reg.h"
#include "gba/types.h"
#include "gba/multiboot.h"
#include "gba/syscall.h"
#include "gba/macro.h"
#include "gba/isagbprint.h"
#endif // GUARD_GBA_GBA_H

View File

@ -0,0 +1,770 @@
#ifndef GUARD_GBA_IO_REG_H
#define GUARD_GBA_IO_REG_H
#define REG_BASE 0x4000000 // I/O register base address
// I/O register offsets
#define REG_OFFSET_DISPCNT 0x0
#define REG_OFFSET_DISPSTAT 0x4
#define REG_OFFSET_VCOUNT 0x6
#define REG_OFFSET_BG0CNT 0x8
#define REG_OFFSET_BG1CNT 0xa
#define REG_OFFSET_BG2CNT 0xc
#define REG_OFFSET_BG3CNT 0xe
#define REG_OFFSET_BG0HOFS 0x10
#define REG_OFFSET_BG0VOFS 0x12
#define REG_OFFSET_BG1HOFS 0x14
#define REG_OFFSET_BG1VOFS 0x16
#define REG_OFFSET_BG2HOFS 0x18
#define REG_OFFSET_BG2VOFS 0x1a
#define REG_OFFSET_BG3HOFS 0x1c
#define REG_OFFSET_BG3VOFS 0x1e
#define REG_OFFSET_BG2PA 0x20
#define REG_OFFSET_BG2PB 0x22
#define REG_OFFSET_BG2PC 0x24
#define REG_OFFSET_BG2PD 0x26
#define REG_OFFSET_BG2X 0x28
#define REG_OFFSET_BG2X_L 0x28
#define REG_OFFSET_BG2X_H 0x2a
#define REG_OFFSET_BG2Y 0x2c
#define REG_OFFSET_BG2Y_L 0x2c
#define REG_OFFSET_BG2Y_H 0x2e
#define REG_OFFSET_BG3PA 0x30
#define REG_OFFSET_BG3PB 0x32
#define REG_OFFSET_BG3PC 0x34
#define REG_OFFSET_BG3PD 0x36
#define REG_OFFSET_BG3X 0x38
#define REG_OFFSET_BG3X_L 0x38
#define REG_OFFSET_BG3X_H 0x3a
#define REG_OFFSET_BG3Y 0x3c
#define REG_OFFSET_BG3Y_L 0x3c
#define REG_OFFSET_BG3Y_H 0x3e
#define REG_OFFSET_WIN0H 0x40
#define REG_OFFSET_WIN1H 0x42
#define REG_OFFSET_WIN0V 0x44
#define REG_OFFSET_WIN1V 0x46
#define REG_OFFSET_WININ 0x48
#define REG_OFFSET_WINOUT 0x4a
#define REG_OFFSET_MOSAIC 0x4c
#define REG_OFFSET_BLDCNT 0x50
#define REG_OFFSET_BLDALPHA 0x52
#define REG_OFFSET_BLDY 0x54
#define REG_OFFSET_SOUND1CNT_L 0x60
#define REG_OFFSET_NR10 0x60
#define REG_OFFSET_SOUND1CNT_H 0x62
#define REG_OFFSET_NR11 0x62
#define REG_OFFSET_NR12 0x63
#define REG_OFFSET_SOUND1CNT_X 0x64
#define REG_OFFSET_NR13 0x64
#define REG_OFFSET_NR14 0x65
#define REG_OFFSET_SOUND2CNT_L 0x68
#define REG_OFFSET_NR21 0x68
#define REG_OFFSET_NR22 0x69
#define REG_OFFSET_SOUND2CNT_H 0x6c
#define REG_OFFSET_NR23 0x6c
#define REG_OFFSET_NR24 0x6d
#define REG_OFFSET_SOUND3CNT_L 0x70
#define REG_OFFSET_NR30 0x70
#define REG_OFFSET_SOUND3CNT_H 0x72
#define REG_OFFSET_NR31 0x72
#define REG_OFFSET_NR32 0x73
#define REG_OFFSET_SOUND3CNT_X 0x74
#define REG_OFFSET_NR33 0x74
#define REG_OFFSET_NR34 0x75
#define REG_OFFSET_SOUND4CNT_L 0x78
#define REG_OFFSET_NR41 0x78
#define REG_OFFSET_NR42 0x79
#define REG_OFFSET_SOUND4CNT_H 0x7c
#define REG_OFFSET_NR43 0x7c
#define REG_OFFSET_NR44 0x7d
#define REG_OFFSET_SOUNDCNT_L 0x80
#define REG_OFFSET_NR50 0x80
#define REG_OFFSET_NR51 0x81
#define REG_OFFSET_SOUNDCNT_H 0x82
#define REG_OFFSET_SOUNDCNT_X 0x84
#define REG_OFFSET_NR52 0x84
#define REG_OFFSET_SOUNDBIAS 0x88
#define REG_OFFSET_SOUNDBIAS_L 0x88
#define REG_OFFSET_SOUNDBIAS_H 0x89
#define REG_OFFSET_WAVE_RAM0 0x90
#define REG_OFFSET_WAVE_RAM1 0x94
#define REG_OFFSET_WAVE_RAM2 0x98
#define REG_OFFSET_WAVE_RAM3 0x9c
#define REG_OFFSET_FIFO_A 0xa0
#define REG_OFFSET_FIFO_B 0xa4
#define REG_OFFSET_DMA0 0xb0
#define REG_OFFSET_DMA0SAD 0xb0
#define REG_OFFSET_DMA0SAD_L 0xb0
#define REG_OFFSET_DMA0SAD_H 0xb2
#define REG_OFFSET_DMA0DAD 0xb4
#define REG_OFFSET_DMA0DAD_L 0xb4
#define REG_OFFSET_DMA0DAD_H 0xb6
#define REG_OFFSET_DMA0CNT 0xb8
#define REG_OFFSET_DMA0CNT_L 0xb8
#define REG_OFFSET_DMA0CNT_H 0xba
#define REG_OFFSET_DMA1 0xbc
#define REG_OFFSET_DMA1SAD 0xbc
#define REG_OFFSET_DMA1SAD_L 0xbc
#define REG_OFFSET_DMA1SAD_H 0xbe
#define REG_OFFSET_DMA1DAD 0xc0
#define REG_OFFSET_DMA1DAD_L 0xc0
#define REG_OFFSET_DMA1DAD_H 0xc2
#define REG_OFFSET_DMA1CNT 0xc4
#define REG_OFFSET_DMA1CNT_L 0xc4
#define REG_OFFSET_DMA1CNT_H 0xc6
#define REG_OFFSET_DMA2 0xc8
#define REG_OFFSET_DMA2SAD 0xc8
#define REG_OFFSET_DMA2SAD_L 0xc8
#define REG_OFFSET_DMA2SAD_H 0xca
#define REG_OFFSET_DMA2DAD 0xcc
#define REG_OFFSET_DMA2DAD_L 0xcc
#define REG_OFFSET_DMA2DAD_H 0xce
#define REG_OFFSET_DMA2CNT 0xd0
#define REG_OFFSET_DMA2CNT_L 0xd0
#define REG_OFFSET_DMA2CNT_H 0xd2
#define REG_OFFSET_DMA3 0xd4
#define REG_OFFSET_DMA3SAD 0xd4
#define REG_OFFSET_DMA3SAD_L 0xd4
#define REG_OFFSET_DMA3SAD_H 0xd6
#define REG_OFFSET_DMA3DAD 0xd8
#define REG_OFFSET_DMA3DAD_L 0xd8
#define REG_OFFSET_DMA3DAD_H 0xda
#define REG_OFFSET_DMA3CNT 0xdc
#define REG_OFFSET_DMA3CNT_L 0xdc
#define REG_OFFSET_DMA3CNT_H 0xde
#define REG_OFFSET_TMCNT 0x100
#define REG_OFFSET_TMCNT_L 0x100
#define REG_OFFSET_TMCNT_H 0x102
#define REG_OFFSET_TM0CNT 0x100
#define REG_OFFSET_TM0CNT_L 0x100
#define REG_OFFSET_TM0CNT_H 0x102
#define REG_OFFSET_TM1CNT 0x104
#define REG_OFFSET_TM1CNT_L 0x104
#define REG_OFFSET_TM1CNT_H 0x106
#define REG_OFFSET_TM2CNT 0x108
#define REG_OFFSET_TM2CNT_L 0x108
#define REG_OFFSET_TM2CNT_H 0x10a
#define REG_OFFSET_TM3CNT 0x10c
#define REG_OFFSET_TM3CNT_L 0x10c
#define REG_OFFSET_TM3CNT_H 0x10e
#define REG_OFFSET_SIOCNT 0x128
#define REG_OFFSET_SIODATA8 0x12a
#define REG_OFFSET_SIODATA32 0x120
#define REG_OFFSET_SIOMLT_SEND 0x12a
#define REG_OFFSET_SIOMLT_RECV 0x120
#define REG_OFFSET_SIOMULTI0 0x120
#define REG_OFFSET_SIOMULTI1 0x122
#define REG_OFFSET_SIOMULTI2 0x124
#define REG_OFFSET_SIOMULTI3 0x126
#define REG_OFFSET_KEYINPUT 0x130
#define REG_OFFSET_KEYCNT 0x132
#define REG_OFFSET_RCNT 0x134
#define REG_OFFSET_JOYCNT 0x140
#define REG_OFFSET_JOYSTAT 0x158
#define REG_OFFSET_JOY_RECV 0x150
#define REG_OFFSET_JOY_RECV_L 0x150
#define REG_OFFSET_JOY_RECV_H 0x152
#define REG_OFFSET_JOY_TRANS 0x154
#define REG_OFFSET_JOY_TRANS_L 0x154
#define REG_OFFSET_JOY_TRANS_H 0x156
#define REG_OFFSET_IME 0x208
#define REG_OFFSET_IE 0x200
#define REG_OFFSET_IF 0x202
#define REG_OFFSET_WAITCNT 0x204
// I/O register addresses
#define REG_ADDR_DISPCNT (REG_BASE + REG_OFFSET_DISPCNT)
#define REG_ADDR_DISPSTAT (REG_BASE + REG_OFFSET_DISPSTAT)
#define REG_ADDR_VCOUNT (REG_BASE + REG_OFFSET_VCOUNT)
#define REG_ADDR_BG0CNT (REG_BASE + REG_OFFSET_BG0CNT)
#define REG_ADDR_BG1CNT (REG_BASE + REG_OFFSET_BG1CNT)
#define REG_ADDR_BG2CNT (REG_BASE + REG_OFFSET_BG2CNT)
#define REG_ADDR_BG3CNT (REG_BASE + REG_OFFSET_BG3CNT)
#define REG_ADDR_BG0HOFS (REG_BASE + REG_OFFSET_BG0HOFS)
#define REG_ADDR_BG0VOFS (REG_BASE + REG_OFFSET_BG0VOFS)
#define REG_ADDR_BG1HOFS (REG_BASE + REG_OFFSET_BG1HOFS)
#define REG_ADDR_BG1VOFS (REG_BASE + REG_OFFSET_BG1VOFS)
#define REG_ADDR_BG2HOFS (REG_BASE + REG_OFFSET_BG2HOFS)
#define REG_ADDR_BG2VOFS (REG_BASE + REG_OFFSET_BG2VOFS)
#define REG_ADDR_BG3HOFS (REG_BASE + REG_OFFSET_BG3HOFS)
#define REG_ADDR_BG3VOFS (REG_BASE + REG_OFFSET_BG3VOFS)
#define REG_ADDR_BG2PA (REG_BASE + REG_OFFSET_BG2PA)
#define REG_ADDR_BG2PB (REG_BASE + REG_OFFSET_BG2PB)
#define REG_ADDR_BG2PC (REG_BASE + REG_OFFSET_BG2PC)
#define REG_ADDR_BG2PD (REG_BASE + REG_OFFSET_BG2PD)
#define REG_ADDR_BG2X (REG_BASE + REG_OFFSET_BG2X)
#define REG_ADDR_BG2X_L (REG_BASE + REG_OFFSET_BG2X_L)
#define REG_ADDR_BG2X_H (REG_BASE + REG_OFFSET_BG2X_H)
#define REG_ADDR_BG2Y (REG_BASE + REG_OFFSET_BG2Y)
#define REG_ADDR_BG2Y_L (REG_BASE + REG_OFFSET_BG2Y_L)
#define REG_ADDR_BG2Y_H (REG_BASE + REG_OFFSET_BG2Y_H)
#define REG_ADDR_BG3PA (REG_BASE + REG_OFFSET_BG3PA)
#define REG_ADDR_BG3PB (REG_BASE + REG_OFFSET_BG3PB)
#define REG_ADDR_BG3PC (REG_BASE + REG_OFFSET_BG3PC)
#define REG_ADDR_BG3PD (REG_BASE + REG_OFFSET_BG3PD)
#define REG_ADDR_BG3X (REG_BASE + REG_OFFSET_BG3X)
#define REG_ADDR_BG3X_L (REG_BASE + REG_OFFSET_BG3X_L)
#define REG_ADDR_BG3X_H (REG_BASE + REG_OFFSET_BG3X_H)
#define REG_ADDR_BG3Y (REG_BASE + REG_OFFSET_BG3Y)
#define REG_ADDR_BG3Y_L (REG_BASE + REG_OFFSET_BG3Y_L)
#define REG_ADDR_BG3Y_H (REG_BASE + REG_OFFSET_BG3Y_H)
#define REG_ADDR_WIN0H (REG_BASE + REG_OFFSET_WIN0H)
#define REG_ADDR_WIN1H (REG_BASE + REG_OFFSET_WIN1H)
#define REG_ADDR_WIN0V (REG_BASE + REG_OFFSET_WIN0V)
#define REG_ADDR_WIN1V (REG_BASE + REG_OFFSET_WIN1V)
#define REG_ADDR_WININ (REG_BASE + REG_OFFSET_WININ)
#define REG_ADDR_WINOUT (REG_BASE + REG_OFFSET_WINOUT)
#define REG_ADDR_MOSAIC (REG_BASE + REG_OFFSET_MOSAIC)
#define REG_ADDR_BLDCNT (REG_BASE + REG_OFFSET_BLDCNT)
#define REG_ADDR_BLDALPHA (REG_BASE + REG_OFFSET_BLDALPHA)
#define REG_ADDR_BLDY (REG_BASE + REG_OFFSET_BLDY)
#define REG_ADDR_SOUND1CNT_L (REG_BASE + REG_OFFSET_SOUND1CNT_L)
#define REG_ADDR_NR10 (REG_BASE + REG_OFFSET_NR10)
#define REG_ADDR_SOUND1CNT_H (REG_BASE + REG_OFFSET_SOUND1CNT_H)
#define REG_ADDR_NR11 (REG_BASE + REG_OFFSET_NR11)
#define REG_ADDR_NR12 (REG_BASE + REG_OFFSET_NR12)
#define REG_ADDR_SOUND1CNT_X (REG_BASE + REG_OFFSET_SOUND1CNT_X)
#define REG_ADDR_NR13 (REG_BASE + REG_OFFSET_NR13)
#define REG_ADDR_NR14 (REG_BASE + REG_OFFSET_NR14)
#define REG_ADDR_SOUND2CNT_L (REG_BASE + REG_OFFSET_SOUND2CNT_L)
#define REG_ADDR_NR21 (REG_BASE + REG_OFFSET_NR21)
#define REG_ADDR_NR22 (REG_BASE + REG_OFFSET_NR22)
#define REG_ADDR_SOUND2CNT_H (REG_BASE + REG_OFFSET_SOUND2CNT_H)
#define REG_ADDR_NR23 (REG_BASE + REG_OFFSET_NR23)
#define REG_ADDR_NR24 (REG_BASE + REG_OFFSET_NR24)
#define REG_ADDR_SOUND3CNT_L (REG_BASE + REG_OFFSET_SOUND3CNT_L)
#define REG_ADDR_NR30 (REG_BASE + REG_OFFSET_NR30)
#define REG_ADDR_SOUND3CNT_H (REG_BASE + REG_OFFSET_SOUND3CNT_H)
#define REG_ADDR_NR31 (REG_BASE + REG_OFFSET_NR31)
#define REG_ADDR_NR32 (REG_BASE + REG_OFFSET_NR32)
#define REG_ADDR_SOUND3CNT_X (REG_BASE + REG_OFFSET_SOUND3CNT_X)
#define REG_ADDR_NR33 (REG_BASE + REG_OFFSET_NR33)
#define REG_ADDR_NR34 (REG_BASE + REG_OFFSET_NR34)
#define REG_ADDR_SOUND4CNT_L (REG_BASE + REG_OFFSET_SOUND4CNT_L)
#define REG_ADDR_NR41 (REG_BASE + REG_OFFSET_NR41)
#define REG_ADDR_NR42 (REG_BASE + REG_OFFSET_NR42)
#define REG_ADDR_SOUND4CNT_H (REG_BASE + REG_OFFSET_SOUND4CNT_H)
#define REG_ADDR_NR43 (REG_BASE + REG_OFFSET_NR43)
#define REG_ADDR_NR44 (REG_BASE + REG_OFFSET_NR44)
#define REG_ADDR_SOUNDCNT_L (REG_BASE + REG_OFFSET_SOUNDCNT_L)
#define REG_ADDR_NR50 (REG_BASE + REG_OFFSET_NR50)
#define REG_ADDR_NR51 (REG_BASE + REG_OFFSET_NR51)
#define REG_ADDR_SOUNDCNT_H (REG_BASE + REG_OFFSET_SOUNDCNT_H)
#define REG_ADDR_SOUNDCNT_X (REG_BASE + REG_OFFSET_SOUNDCNT_X)
#define REG_ADDR_NR52 (REG_BASE + REG_OFFSET_NR52)
#define REG_ADDR_SOUNDBIAS (REG_BASE + REG_OFFSET_SOUNDBIAS)
#define REG_ADDR_SOUNDBIAS_L (REG_BASE + REG_OFFSET_SOUNDBIAS_L)
#define REG_ADDR_SOUNDBIAS_H (REG_BASE + REG_OFFSET_SOUNDBIAS_H)
#define REG_ADDR_WAVE_RAM0 (REG_BASE + REG_OFFSET_WAVE_RAM0)
#define REG_ADDR_WAVE_RAM1 (REG_BASE + REG_OFFSET_WAVE_RAM1)
#define REG_ADDR_WAVE_RAM2 (REG_BASE + REG_OFFSET_WAVE_RAM2)
#define REG_ADDR_WAVE_RAM3 (REG_BASE + REG_OFFSET_WAVE_RAM3)
#define REG_ADDR_FIFO_A (REG_BASE + REG_OFFSET_FIFO_A)
#define REG_ADDR_FIFO_B (REG_BASE + REG_OFFSET_FIFO_B)
#define REG_ADDR_DMA0 (REG_BASE + REG_OFFSET_DMA0)
#define REG_ADDR_DMA0SAD (REG_BASE + REG_OFFSET_DMA0SAD)
#define REG_ADDR_DMA0DAD (REG_BASE + REG_OFFSET_DMA0DAD)
#define REG_ADDR_DMA0CNT (REG_BASE + REG_OFFSET_DMA0CNT)
#define REG_ADDR_DMA0CNT_L (REG_BASE + REG_OFFSET_DMA0CNT_L)
#define REG_ADDR_DMA0CNT_H (REG_BASE + REG_OFFSET_DMA0CNT_H)
#define REG_ADDR_DMA1 (REG_BASE + REG_OFFSET_DMA1)
#define REG_ADDR_DMA1SAD (REG_BASE + REG_OFFSET_DMA1SAD)
#define REG_ADDR_DMA1DAD (REG_BASE + REG_OFFSET_DMA1DAD)
#define REG_ADDR_DMA1CNT (REG_BASE + REG_OFFSET_DMA1CNT)
#define REG_ADDR_DMA1CNT_L (REG_BASE + REG_OFFSET_DMA1CNT_L)
#define REG_ADDR_DMA1CNT_H (REG_BASE + REG_OFFSET_DMA1CNT_H)
#define REG_ADDR_DMA2 (REG_BASE + REG_OFFSET_DMA2)
#define REG_ADDR_DMA2SAD (REG_BASE + REG_OFFSET_DMA2SAD)
#define REG_ADDR_DMA2DAD (REG_BASE + REG_OFFSET_DMA2DAD)
#define REG_ADDR_DMA2CNT (REG_BASE + REG_OFFSET_DMA2CNT)
#define REG_ADDR_DMA2CNT_L (REG_BASE + REG_OFFSET_DMA2CNT_L)
#define REG_ADDR_DMA2CNT_H (REG_BASE + REG_OFFSET_DMA2CNT_H)
#define REG_ADDR_DMA3 (REG_BASE + REG_OFFSET_DMA3)
#define REG_ADDR_DMA3SAD (REG_BASE + REG_OFFSET_DMA3SAD)
#define REG_ADDR_DMA3DAD (REG_BASE + REG_OFFSET_DMA3DAD)
#define REG_ADDR_DMA3CNT (REG_BASE + REG_OFFSET_DMA3CNT)
#define REG_ADDR_DMA3CNT_L (REG_BASE + REG_OFFSET_DMA3CNT_L)
#define REG_ADDR_DMA3CNT_H (REG_BASE + REG_OFFSET_DMA3CNT_H)
#define REG_ADDR_TMCNT (REG_BASE + REG_OFFSET_TMCNT)
#define REG_ADDR_TMCNT_L (REG_BASE + REG_OFFSET_TMCNT_L)
#define REG_ADDR_TMCNT_H (REG_BASE + REG_OFFSET_TMCNT_H)
#define REG_ADDR_TM0CNT (REG_BASE + REG_OFFSET_TM0CNT)
#define REG_ADDR_TM0CNT_L (REG_BASE + REG_OFFSET_TM0CNT_L)
#define REG_ADDR_TM0CNT_H (REG_BASE + REG_OFFSET_TM0CNT_H)
#define REG_ADDR_TM1CNT (REG_BASE + REG_OFFSET_TM1CNT)
#define REG_ADDR_TM1CNT_L (REG_BASE + REG_OFFSET_TM1CNT_L)
#define REG_ADDR_TM1CNT_H (REG_BASE + REG_OFFSET_TM1CNT_H)
#define REG_ADDR_TM2CNT (REG_BASE + REG_OFFSET_TM2CNT)
#define REG_ADDR_TM2CNT_L (REG_BASE + REG_OFFSET_TM2CNT_L)
#define REG_ADDR_TM2CNT_H (REG_BASE + REG_OFFSET_TM2CNT_H)
#define REG_ADDR_TM3CNT (REG_BASE + REG_OFFSET_TM3CNT)
#define REG_ADDR_TM3CNT_L (REG_BASE + REG_OFFSET_TM3CNT_L)
#define REG_ADDR_TM3CNT_H (REG_BASE + REG_OFFSET_TM3CNT_H)
#define REG_ADDR_SIOCNT (REG_BASE + REG_OFFSET_SIOCNT)
#define REG_ADDR_SIODATA8 (REG_BASE + REG_OFFSET_SIODATA8)
#define REG_ADDR_SIODATA32 (REG_BASE + REG_OFFSET_SIODATA32)
#define REG_ADDR_SIOMLT_SEND (REG_BASE + REG_OFFSET_SIOMLT_SEND)
#define REG_ADDR_SIOMLT_RECV (REG_BASE + REG_OFFSET_SIOMLT_RECV)
#define REG_ADDR_SIOMULTI0 (REG_BASE + REG_OFFSET_SIOMULTI0)
#define REG_ADDR_SIOMULTI1 (REG_BASE + REG_OFFSET_SIOMULTI1)
#define REG_ADDR_SIOMULTI2 (REG_BASE + REG_OFFSET_SIOMULTI2)
#define REG_ADDR_SIOMULTI3 (REG_BASE + REG_OFFSET_SIOMULTI3)
#define REG_ADDR_KEYINPUT (REG_BASE + REG_OFFSET_KEYINPUT)
#define REG_ADDR_KEYCNT (REG_BASE + REG_OFFSET_KEYCNT)
#define REG_ADDR_RCNT (REG_BASE + REG_OFFSET_RCNT)
#define REG_ADDR_JOYCNT (REG_BASE + REG_OFFSET_JOYCNT)
#define REG_ADDR_JOYSTAT (REG_BASE + REG_OFFSET_JOYSTAT)
#define REG_ADDR_JOY_RECV (REG_BASE + REG_OFFSET_JOY_RECV)
#define REG_ADDR_JOY_RECV_L (REG_BASE + REG_OFFSET_JOY_RECV_L)
#define REG_ADDR_JOY_RECV_H (REG_BASE + REG_OFFSET_JOY_RECV_H)
#define REG_ADDR_JOY_TRANS (REG_BASE + REG_OFFSET_JOY_TRANS)
#define REG_ADDR_JOY_TRANS_L (REG_BASE + REG_OFFSET_JOY_TRANS_L)
#define REG_ADDR_JOY_TRANS_H (REG_BASE + REG_OFFSET_JOY_TRANS_H)
#define REG_ADDR_IME (REG_BASE + REG_OFFSET_IME)
#define REG_ADDR_IE (REG_BASE + REG_OFFSET_IE)
#define REG_ADDR_IF (REG_BASE + REG_OFFSET_IF)
#define REG_ADDR_WAITCNT (REG_BASE + REG_OFFSET_WAITCNT)
// I/O registers
#define REG_DISPCNT (*(vu16 *)REG_ADDR_DISPCNT)
#define REG_DISPSTAT (*(vu16 *)REG_ADDR_DISPSTAT)
#define REG_VCOUNT (*(vu16 *)REG_ADDR_VCOUNT)
#define REG_BG0CNT (*(vu16 *)REG_ADDR_BG0CNT)
#define REG_BG1CNT (*(vu16 *)REG_ADDR_BG1CNT)
#define REG_BG2CNT (*(vu16 *)REG_ADDR_BG2CNT)
#define REG_BG3CNT (*(vu16 *)REG_ADDR_BG3CNT)
#define REG_BG0HOFS (*(vu16 *)REG_ADDR_BG0HOFS)
#define REG_BG0VOFS (*(vu16 *)REG_ADDR_BG0VOFS)
#define REG_BG1HOFS (*(vu16 *)REG_ADDR_BG1HOFS)
#define REG_BG1VOFS (*(vu16 *)REG_ADDR_BG1VOFS)
#define REG_BG2HOFS (*(vu16 *)REG_ADDR_BG2HOFS)
#define REG_BG2VOFS (*(vu16 *)REG_ADDR_BG2VOFS)
#define REG_BG3HOFS (*(vu16 *)REG_ADDR_BG3HOFS)
#define REG_BG3VOFS (*(vu16 *)REG_ADDR_BG3VOFS)
#define REG_BG2PA (*(vu16 *)REG_ADDR_BG2PA)
#define REG_BG2PB (*(vu16 *)REG_ADDR_BG2PB)
#define REG_BG2PC (*(vu16 *)REG_ADDR_BG2PC)
#define REG_BG2PD (*(vu16 *)REG_ADDR_BG2PD)
#define REG_BG2X (*(vu32 *)REG_ADDR_BG2X)
#define REG_BG2X_L (*(vu16 *)REG_ADDR_BG2X_L)
#define REG_BG2X_H (*(vu16 *)REG_ADDR_BG2X_H)
#define REG_BG2Y (*(vu32 *)REG_ADDR_BG2Y)
#define REG_BG2Y_L (*(vu16 *)REG_ADDR_BG2Y_L)
#define REG_BG2Y_H (*(vu16 *)REG_ADDR_BG2Y_H)
#define REG_BG3PA (*(vu16 *)REG_ADDR_BG3PA)
#define REG_BG3PB (*(vu16 *)REG_ADDR_BG3PB)
#define REG_BG3PC (*(vu16 *)REG_ADDR_BG3PC)
#define REG_BG3PD (*(vu16 *)REG_ADDR_BG3PD)
#define REG_BG3X (*(vu32 *)REG_ADDR_BG3X)
#define REG_BG3X_L (*(vu16 *)REG_ADDR_BG3X_L)
#define REG_BG3X_H (*(vu16 *)REG_ADDR_BG3X_H)
#define REG_BG3Y (*(vu32 *)REG_ADDR_BG3Y)
#define REG_BG3Y_L (*(vu16 *)REG_ADDR_BG3Y_L)
#define REG_BG3Y_H (*(vu16 *)REG_ADDR_BG3Y_H)
#define REG_WIN0H (*(vu16 *)REG_ADDR_WIN0H)
#define REG_WIN1H (*(vu16 *)REG_ADDR_WIN1H)
#define REG_WIN0V (*(vu16 *)REG_ADDR_WIN0V)
#define REG_WIN1V (*(vu16 *)REG_ADDR_WIN1V)
#define REG_WININ (*(vu16 *)REG_ADDR_WININ)
#define REG_WINOUT (*(vu16 *)REG_ADDR_WINOUT)
#define REG_MOSAIC (*(vu16 *)REG_ADDR_MOSAIC)
#define REG_BLDCNT (*(vu16 *)REG_ADDR_BLDCNT)
#define REG_BLDALPHA (*(vu16 *)REG_ADDR_BLDALPHA)
#define REG_BLDY (*(vu16 *)REG_ADDR_BLDY)
#define REG_SOUND1CNT_L (*(vu16 *)REG_ADDR_SOUND1CNT_L)
#define REG_NR10 (*(vu8 *)REG_ADDR_NR10)
#define REG_SOUND1CNT_H (*(vu16 *)REG_ADDR_SOUND1CNT_H)
#define REG_NR11 (*(vu8 *)REG_ADDR_NR11)
#define REG_NR12 (*(vu8 *)REG_ADDR_NR12)
#define REG_SOUND1CNT_X (*(vu16 *)REG_ADDR_SOUND1CNT_X)
#define REG_NR13 (*(vu8 *)REG_ADDR_NR13)
#define REG_NR14 (*(vu8 *)REG_ADDR_NR14)
#define REG_SOUND2CNT_L (*(vu16 *)REG_ADDR_SOUND2CNT_L)
#define REG_NR21 (*(vu8 *)REG_ADDR_NR21)
#define REG_NR22 (*(vu8 *)REG_ADDR_NR22)
#define REG_SOUND2CNT_H (*(vu16 *)REG_ADDR_SOUND2CNT_H)
#define REG_NR23 (*(vu8 *)REG_ADDR_NR23)
#define REG_NR24 (*(vu8 *)REG_ADDR_NR24)
#define REG_SOUND3CNT_L (*(vu16 *)REG_ADDR_SOUND3CNT_L)
#define REG_NR30 (*(vu8 *)REG_ADDR_NR30)
#define REG_SOUND3CNT_H (*(vu16 *)REG_ADDR_SOUND3CNT_H)
#define REG_NR31 (*(vu8 *)REG_ADDR_NR31)
#define REG_NR32 (*(vu8 *)REG_ADDR_NR32)
#define REG_SOUND3CNT_X (*(vu16 *)REG_ADDR_SOUND3CNT_X)
#define REG_NR33 (*(vu8 *)REG_ADDR_NR33)
#define REG_NR34 (*(vu8 *)REG_ADDR_NR34)
#define REG_SOUND4CNT_L (*(vu16 *)REG_ADDR_SOUND4CNT_L)
#define REG_NR41 (*(vu8 *)REG_ADDR_NR41)
#define REG_NR42 (*(vu8 *)REG_ADDR_NR42)
#define REG_SOUND4CNT_H (*(vu16 *)REG_ADDR_SOUND4CNT_H)
#define REG_NR43 (*(vu8 *)REG_ADDR_NR43)
#define REG_NR44 (*(vu8 *)REG_ADDR_NR44)
#define REG_SOUNDCNT_L (*(vu16 *)REG_ADDR_SOUNDCNT_L)
#define REG_NR50 (*(vu8 *)REG_ADDR_NR50)
#define REG_NR51 (*(vu8 *)REG_ADDR_NR51)
#define REG_SOUNDCNT_H (*(vu16 *)REG_ADDR_SOUNDCNT_H)
#define REG_SOUNDCNT_X (*(vu16 *)REG_ADDR_SOUNDCNT_X)
#define REG_NR52 (*(vu8 *)REG_ADDR_NR52)
#define REG_SOUNDBIAS (*(vu16 *)REG_ADDR_SOUNDBIAS)
#define REG_SOUNDBIAS_L (*(vu8 *)REG_ADDR_SOUNDBIAS_L)
#define REG_SOUNDBIAS_H (*(vu8 *)REG_ADDR_SOUNDBIAS_H)
#define REG_WAVE_RAM0 (*(vu32 *)REG_ADDR_WAVE_RAM0)
#define REG_WAVE_RAM1 (*(vu32 *)REG_ADDR_WAVE_RAM1)
#define REG_WAVE_RAM2 (*(vu32 *)REG_ADDR_WAVE_RAM2)
#define REG_WAVE_RAM3 (*(vu32 *)REG_ADDR_WAVE_RAM3)
#define REG_FIFO_A (*(vu32 *)REG_ADDR_FIFO_A)
#define REG_FIFO_B (*(vu32 *)REG_ADDR_FIFO_B)
#define REG_DMA0SAD (*(vu32 *)REG_ADDR_DMA0SAD)
#define REG_DMA0DAD (*(vu32 *)REG_ADDR_DMA0DAD)
#define REG_DMA0CNT (*(vu32 *)REG_ADDR_DMA0CNT)
#define REG_DMA0CNT_L (*(vu16 *)REG_ADDR_DMA0CNT_L)
#define REG_DMA0CNT_H (*(vu16 *)REG_ADDR_DMA0CNT_H)
#define REG_DMA1SAD (*(vu32 *)REG_ADDR_DMA1SAD)
#define REG_DMA1DAD (*(vu32 *)REG_ADDR_DMA1DAD)
#define REG_DMA1CNT (*(vu32 *)REG_ADDR_DMA1CNT)
#define REG_DMA1CNT_L (*(vu16 *)REG_ADDR_DMA1CNT_L)
#define REG_DMA1CNT_H (*(vu16 *)REG_ADDR_DMA1CNT_H)
#define REG_DMA2SAD (*(vu32 *)REG_ADDR_DMA2SAD)
#define REG_DMA2DAD (*(vu32 *)REG_ADDR_DMA2DAD)
#define REG_DMA2CNT (*(vu32 *)REG_ADDR_DMA2CNT)
#define REG_DMA2CNT_L (*(vu16 *)REG_ADDR_DMA2CNT_L)
#define REG_DMA2CNT_H (*(vu16 *)REG_ADDR_DMA2CNT_H)
#define REG_DMA3SAD (*(vu32 *)REG_ADDR_DMA3SAD)
#define REG_DMA3DAD (*(vu32 *)REG_ADDR_DMA3DAD)
#define REG_DMA3CNT (*(vu32 *)REG_ADDR_DMA3CNT)
#define REG_DMA3CNT_L (*(vu16 *)REG_ADDR_DMA3CNT_L)
#define REG_DMA3CNT_H (*(vu16 *)REG_ADDR_DMA3CNT_H)
#define REG_TMCNT(n) (*(vu16 *)(REG_ADDR_TMCNT + ((n) * 4)))
#define REG_TMCNT_L(n) (*(vu16 *)(REG_ADDR_TMCNT_L + ((n) * 4)))
#define REG_TMCNT_H(n) (*(vu16 *)(REG_ADDR_TMCNT_H + ((n) * 4)))
#define REG_TM0CNT (*(vu32 *)REG_ADDR_TM0CNT)
#define REG_TM0CNT_L (*(vu16 *)REG_ADDR_TM0CNT_L)
#define REG_TM0CNT_H (*(vu16 *)REG_ADDR_TM0CNT_H)
#define REG_TM1CNT (*(vu32 *)REG_ADDR_TM1CNT)
#define REG_TM1CNT_L (*(vu16 *)REG_ADDR_TM1CNT_L)
#define REG_TM1CNT_H (*(vu16 *)REG_ADDR_TM1CNT_H)
#define REG_TM2CNT (*(vu32 *)REG_ADDR_TM2CNT)
#define REG_TM2CNT_L (*(vu16 *)REG_ADDR_TM2CNT_L)
#define REG_TM2CNT_H (*(vu16 *)REG_ADDR_TM2CNT_H)
#define REG_TM3CNT (*(vu32 *)REG_ADDR_TM3CNT)
#define REG_TM3CNT_L (*(vu16 *)REG_ADDR_TM3CNT_L)
#define REG_TM3CNT_H (*(vu16 *)REG_ADDR_TM3CNT_H)
#define REG_SIOCNT (*(vu16 *)REG_ADDR_SIOCNT)
#define REG_SIODATA8 (*(vu16 *)REG_ADDR_SIODATA8)
#define REG_SIODATA32 (*(vu32 *)REG_ADDR_SIODATA32)
#define REG_SIOMLT_SEND (*(vu16 *)REG_ADDR_SIOMLT_SEND)
#define REG_SIOMLT_RECV (*(vu64 *)REG_ADDR_SIOMLT_RECV)
#define REG_SIOMULTI0 (*(vu16 *)REG_ADDR_SIOMULTI0)
#define REG_SIOMULTI1 (*(vu16 *)REG_ADDR_SIOMULTI1)
#define REG_SIOMULTI2 (*(vu16 *)REG_ADDR_SIOMULTI2)
#define REG_SIOMULTI3 (*(vu16 *)REG_ADDR_SIOMULTI3)
#define REG_KEYINPUT (*(vu16 *)REG_ADDR_KEYINPUT)
#define REG_KEYCNT (*(vu16 *)REG_ADDR_KEYCNT)
#define REG_RCNT (*(vu16 *)REG_ADDR_RCNT)
#define REG_IME (*(vu16 *)REG_ADDR_IME)
#define REG_IE (*(vu16 *)REG_ADDR_IE)
#define REG_IF (*(vu16 *)REG_ADDR_IF)
#define REG_WAITCNT (*(vu16 *)REG_ADDR_WAITCNT)
// I/O register fields
// DISPCNT
#define DISPCNT_MODE_0 0x0000 // BG0: text, BG1: text, BG2: text, BG3: text
#define DISPCNT_MODE_1 0x0001 // BG0: text, BG1: text, BG2: affine, BG3: off
#define DISPCNT_MODE_2 0x0002 // BG0: off, BG1: off, BG2: affine, BG3: affine
#define DISPCNT_MODE_3 0x0003 // Bitmap mode, 240x160, BGR555 color
#define DISPCNT_MODE_4 0x0004 // Bitmap mode, 240x160, 256 color palette
#define DISPCNT_MODE_5 0x0005 // Bitmap mode, 160x128, BGR555 color
#define DISPCNT_HBLANK_INTERVAL 0x0020 // Allow access to OAM during H-Blank
#define DISPCNT_OBJ_1D_MAP 0x0040
#define DISPCNT_FORCED_BLANK 0x0080
#define DISPCNT_BG0_ON 0x0100
#define DISPCNT_BG1_ON 0x0200
#define DISPCNT_BG2_ON 0x0400
#define DISPCNT_BG3_ON 0x0800
#define DISPCNT_BG_ALL_ON 0x0F00
#define DISPCNT_OBJ_ON 0x1000
#define DISPCNT_WIN0_ON 0x2000
#define DISPCNT_WIN1_ON 0x4000
#define DISPCNT_OBJWIN_ON 0x8000
// DISPSTAT
#define DISPSTAT_VBLANK 0x0001 // in V-Blank
#define DISPSTAT_HBLANK 0x0002 // in H-Blank
#define DISPSTAT_VCOUNT 0x0004 // V-Count match
#define DISPSTAT_VBLANK_INTR 0x0008 // V-Blank interrupt enabled
#define DISPSTAT_HBLANK_INTR 0x0010 // H-Blank interrupt enabled
#define DISPSTAT_VCOUNT_INTR 0x0020 // V-Count interrupt enabled
// BGCNT
#define BGCNT_PRIORITY(n) (n) // Values 0 - 3. Lower priority BGs will be drawn on top of higher priority BGs.
#define BGCNT_CHARBASE(n) ((n) << 2) // Values 0 - 3. Base block for tile pixel data.
#define BGCNT_MOSAIC 0x0040
#define BGCNT_16COLOR 0x0000 // 4 bits per pixel
#define BGCNT_256COLOR 0x0080 // 8 bits per pixel
#define BGCNT_SCREENBASE(n) ((n) << 8) // Values 0 - 31. Base block for tile map.
#define BGCNT_WRAP 0x2000 // Only affects affine BGs. Text BGs wrap by default.
#define BGCNT_TXT256x256 0x0000 // Internal screen size size of text mode BG in pixels.
#define BGCNT_TXT512x256 0x4000
#define BGCNT_TXT256x512 0x8000
#define BGCNT_TXT512x512 0xC000
#define BGCNT_AFF128x128 0x0000 // Internal screen size size of affine mode BG in pixels.
#define BGCNT_AFF256x256 0x4000
#define BGCNT_AFF512x512 0x8000
#define BGCNT_AFF1024x1024 0xC000
// WININ/OUT
#define WININ_WIN0_BG0 (1 << 0)
#define WININ_WIN0_BG1 (1 << 1)
#define WININ_WIN0_BG2 (1 << 2)
#define WININ_WIN0_BG3 (1 << 3)
#define WININ_WIN0_BG_ALL (WININ_WIN0_BG0 | WININ_WIN0_BG1 | WININ_WIN0_BG2 | WININ_WIN0_BG3)
#define WININ_WIN0_OBJ (1 << 4)
#define WININ_WIN0_CLR (1 << 5)
#define WININ_WIN1_BG0 (1 << 8)
#define WININ_WIN1_BG1 (1 << 9)
#define WININ_WIN1_BG2 (1 << 10)
#define WININ_WIN1_BG3 (1 << 11)
#define WININ_WIN1_BG_ALL (WININ_WIN1_BG0 | WININ_WIN1_BG1 | WININ_WIN1_BG2 | WININ_WIN1_BG3)
#define WININ_WIN1_OBJ (1 << 12)
#define WININ_WIN1_CLR (1 << 13)
#define WINOUT_WIN01_BG0 (1 << 0)
#define WINOUT_WIN01_BG1 (1 << 1)
#define WINOUT_WIN01_BG2 (1 << 2)
#define WINOUT_WIN01_BG3 (1 << 3)
#define WINOUT_WIN01_BG_ALL (WINOUT_WIN01_BG0 | WINOUT_WIN01_BG1 | WINOUT_WIN01_BG2 | WINOUT_WIN01_BG3)
#define WINOUT_WIN01_OBJ (1 << 4)
#define WINOUT_WIN01_CLR (1 << 5)
#define WINOUT_WINOBJ_BG0 (1 << 8)
#define WINOUT_WINOBJ_BG1 (1 << 9)
#define WINOUT_WINOBJ_BG2 (1 << 10)
#define WINOUT_WINOBJ_BG3 (1 << 11)
#define WINOUT_WINOBJ_BG_ALL (WINOUT_WINOBJ_BG0 | WINOUT_WINOBJ_BG1 | WINOUT_WINOBJ_BG2 | WINOUT_WINOBJ_BG3)
#define WINOUT_WINOBJ_OBJ (1 << 12)
#define WINOUT_WINOBJ_CLR (1 << 13)
#define WIN_RANGE(a, b) (((a) << 8) | (b))
#define WIN_RANGE2(a, b) ((b) | ((a) << 8))
// BLDCNT
// Bits 0-5 select layers for the 1st target
#define BLDCNT_TGT1_BG0 (1 << 0)
#define BLDCNT_TGT1_BG1 (1 << 1)
#define BLDCNT_TGT1_BG2 (1 << 2)
#define BLDCNT_TGT1_BG3 (1 << 3)
#define BLDCNT_TGT1_OBJ (1 << 4)
#define BLDCNT_TGT1_BD (1 << 5)
#define BLDCNT_TGT1_ALL (BLDCNT_TGT1_BG0 | BLDCNT_TGT1_BG1 | BLDCNT_TGT1_BG2 | BLDCNT_TGT1_BG3 | BLDCNT_TGT1_OBJ | BLDCNT_TGT1_BD)
// Bits 6-7 select the special effect
#define BLDCNT_EFFECT_NONE (0 << 6) // no special effect
#define BLDCNT_EFFECT_BLEND (1 << 6) // 1st+2nd targets mixed (controlled by BLDALPHA)
#define BLDCNT_EFFECT_LIGHTEN (2 << 6) // 1st target becomes whiter (controlled by BLDY)
#define BLDCNT_EFFECT_DARKEN (3 << 6) // 1st target becomes blacker (controlled by BLDY)
// Bits 8-13 select layers for the 2nd target
#define BLDCNT_TGT2_BG0 (1 << 8)
#define BLDCNT_TGT2_BG1 (1 << 9)
#define BLDCNT_TGT2_BG2 (1 << 10)
#define BLDCNT_TGT2_BG3 (1 << 11)
#define BLDCNT_TGT2_OBJ (1 << 12)
#define BLDCNT_TGT2_BD (1 << 13)
#define BLDCNT_TGT2_ALL (BLDCNT_TGT2_BG0 | BLDCNT_TGT2_BG1 | BLDCNT_TGT2_BG2 | BLDCNT_TGT2_BG3 | BLDCNT_TGT2_OBJ | BLDCNT_TGT2_BD)
// BLDALPHA
#define BLDALPHA_BLEND(target1, target2) (((target2) << 8) | (target1))
// SOUNDCNT_H
#define SOUND_CGB_MIX_QUARTER 0x0000
#define SOUND_CGB_MIX_HALF 0x0001
#define SOUND_CGB_MIX_FULL 0x0002
#define SOUND_A_MIX_HALF 0x0000
#define SOUND_A_MIX_FULL 0x0004
#define SOUND_B_MIX_HALF 0x0000
#define SOUND_B_MIX_FULL 0x0008
#define SOUND_ALL_MIX_FULL 0x000E
#define SOUND_A_RIGHT_OUTPUT 0x0100
#define SOUND_A_LEFT_OUTPUT 0x0200
#define SOUND_A_TIMER_0 0x0000
#define SOUND_A_TIMER_1 0x0400
#define SOUND_A_FIFO_RESET 0x0800
#define SOUND_B_RIGHT_OUTPUT 0x1000
#define SOUND_B_LEFT_OUTPUT 0x2000
#define SOUND_B_TIMER_0 0x0000
#define SOUND_B_TIMER_1 0x4000
#define SOUND_B_FIFO_RESET 0x8000
// SOUNDCNT_X
#define SOUND_1_ON 0x0001
#define SOUND_2_ON 0x0002
#define SOUND_3_ON 0x0004
#define SOUND_4_ON 0x0008
#define SOUND_MASTER_ENABLE 0x0080
// DMA
#define DMA_DEST_INC 0x0000
#define DMA_DEST_DEC 0x0020
#define DMA_DEST_FIXED 0x0040
#define DMA_DEST_RELOAD 0x0060
#define DMA_SRC_INC 0x0000
#define DMA_SRC_DEC 0x0080
#define DMA_SRC_FIXED 0x0100
#define DMA_REPEAT 0x0200
#define DMA_16BIT 0x0000
#define DMA_32BIT 0x0400
#define DMA_DREQ_ON 0x0800
#define DMA_START_NOW 0x0000
#define DMA_START_VBLANK 0x1000
#define DMA_START_HBLANK 0x2000
#define DMA_START_SPECIAL 0x3000
#define DMA_START_MASK 0x3000
#define DMA_INTR_ENABLE 0x4000
#define DMA_ENABLE 0x8000
// timer
#define TIMER_1CLK 0x00
#define TIMER_64CLK 0x01
#define TIMER_256CLK 0x02
#define TIMER_1024CLK 0x03
#define TIMER_INTR_ENABLE 0x40
#define TIMER_ENABLE 0x80
// serial
#define SIO_ID 0x0030 // Communication ID
#define SIO_8BIT_MODE 0x0000 // Normal 8-bit communication mode
#define SIO_32BIT_MODE 0x1000 // Normal 32-bit communication mode
#define SIO_MULTI_MODE 0x2000 // Multi-player communication mode
#define SIO_UART_MODE 0x3000 // UART communication mode
#define SIO_9600_BPS 0x0000 // baud rate 9600 bps
#define SIO_38400_BPS 0x0001 // 38400 bps
#define SIO_57600_BPS 0x0002 // 57600 bps
#define SIO_115200_BPS 0x0003 // 115200 bps
#define SIO_MULTI_SI 0x0004 // Multi-player communication SI terminal
#define SIO_MULTI_SD 0x0008 // SD terminal
#define SIO_MULTI_BUSY 0x0080
#define SIO_ERROR 0x0040 // Detect error
#define SIO_START 0x0080 // Start transfer
#define SIO_ENABLE 0x0080 // Enable SIO
#define SIO_INTR_ENABLE 0x4000
#define SIO_MULTI_SI_SHIFT 2
#define SIO_MULTI_SI_MASK 0x1
#define SIO_MULTI_DI_SHIFT 3
#define SIO_MULTI_DI_MASK 0x1
// keys
#define A_BUTTON 0x0001
#define B_BUTTON 0x0002
#define SELECT_BUTTON 0x0004
#define START_BUTTON 0x0008
#define DPAD_RIGHT 0x0010
#define DPAD_LEFT 0x0020
#define DPAD_UP 0x0040
#define DPAD_DOWN 0x0080
#define R_BUTTON 0x0100
#define L_BUTTON 0x0200
#define KEYS_MASK 0x03FF
#define KEY_INTR_ENABLE 0x0400
#define KEY_OR_INTR 0x0000
#define KEY_AND_INTR 0x8000
#define DPAD_ANY ((DPAD_RIGHT | DPAD_LEFT | DPAD_UP | DPAD_DOWN))
#define JOY_EXCL_DPAD 0x030F
// interrupt flags
#define INTR_FLAG_VBLANK (1 << 0)
#define INTR_FLAG_HBLANK (1 << 1)
#define INTR_FLAG_VCOUNT (1 << 2)
#define INTR_FLAG_TIMER0 (1 << 3)
#define INTR_FLAG_TIMER1 (1 << 4)
#define INTR_FLAG_TIMER2 (1 << 5)
#define INTR_FLAG_TIMER3 (1 << 6)
#define INTR_FLAG_SERIAL (1 << 7)
#define INTR_FLAG_DMA0 (1 << 8)
#define INTR_FLAG_DMA1 (1 << 9)
#define INTR_FLAG_DMA2 (1 << 10)
#define INTR_FLAG_DMA3 (1 << 11)
#define INTR_FLAG_KEYPAD (1 << 12)
#define INTR_FLAG_GAMEPAK (1 << 13)
// WAITCNT
#define WAITCNT_SRAM_4 (0 << 0)
#define WAITCNT_SRAM_3 (1 << 0)
#define WAITCNT_SRAM_2 (2 << 0)
#define WAITCNT_SRAM_8 (3 << 0)
#define WAITCNT_SRAM_MASK (3 << 0)
#define WAITCNT_WS0_N_4 (0 << 2)
#define WAITCNT_WS0_N_3 (1 << 2)
#define WAITCNT_WS0_N_2 (2 << 2)
#define WAITCNT_WS0_N_8 (3 << 2)
#define WAITCNT_WS0_N_MASK (3 << 2)
#define WAITCNT_WS0_S_2 (0 << 4)
#define WAITCNT_WS0_S_1 (1 << 4)
#define WAITCNT_WS1_N_4 (0 << 5)
#define WAITCNT_WS1_N_3 (1 << 5)
#define WAITCNT_WS1_N_2 (2 << 5)
#define WAITCNT_WS1_N_8 (3 << 5)
#define WAITCNT_WS1_N_MASK (3 << 5)
#define WAITCNT_WS1_S_4 (0 << 7)
#define WAITCNT_WS1_S_1 (1 << 7)
#define WAITCNT_WS2_N_4 (0 << 8)
#define WAITCNT_WS2_N_3 (1 << 8)
#define WAITCNT_WS2_N_2 (2 << 8)
#define WAITCNT_WS2_N_8 (3 << 8)
#define WAITCNT_WS2_N_MASK (3 << 8)
#define WAITCNT_WS2_S_8 (0 << 10)
#define WAITCNT_WS2_S_1 (1 << 10)
#define WAITCNT_PHI_OUT_NONE (0 << 11)
#define WAITCNT_PHI_OUT_4MHZ (1 << 11)
#define WAITCNT_PHI_OUT_8MHZ (2 << 11)
#define WAITCNT_PHI_OUT_16MHZ (3 << 11)
#define WAITCNT_PHI_OUT_MASK (3 << 11)
#define WAITCNT_PREFETCH_ENABLE (1 << 14)
#define WAITCNT_AGB (0 << 15)
#define WAITCNT_CGB (1 << 15)
#endif // GUARD_GBA_IO_REG_H

View File

@ -0,0 +1,50 @@
#ifndef GUARD_GBA_ISAGBPRINT_H
#define GUARD_GBA_ISAGBPRINT_H
#ifdef NDEBUG
#define AGBPrintInit()
#define AGBPutc(cChr)
#define AGBPrint(pBuf)
#define AGBPrintf(pBuf, ...)
#define AGBPrintFlush1Block()
#define AGBPrintFlush()
#define AGBAssert(pFile, nLine, pExpression, nStopProgram)
#else
void AGBPrintInit(void);
void AGBPutc(const char cChr);
void AGBPrint(const char *pBuf);
void AGBPrintf(const char *pBuf, ...);
void AGBPrintFlush1Block(void);
void AGBPrintFlush(void);
void AGBAssert(const char *pFile, int nLine, const char *pExpression, int nStopProgram);
#endif
#undef AGB_ASSERT
#ifdef NDEBUG
#define AGB_ASSERT(exp)
#else
#define AGB_ASSERT(exp) (exp) ? ((void*)0) : AGBAssert(__FILE__, __LINE__, #exp, 1);
#endif
#undef AGB_WARNING
#ifdef NDEBUG
#define AGB_WARNING(exp)
#else
#define AGB_WARNING(exp) (exp) ? ((void*)0) : AGBAssert(__FILE__, __LINE__, #exp, 0);
#endif
// for matching purposes
#ifdef NDEBUG
#define AGB_ASSERT_EX(exp, file, line)
#else
#define AGB_ASSERT_EX(exp, file, line) (exp) ? ((void*)0) : AGBAssert(file, line, #exp, 1);
#endif
#ifdef NDEBUG
#define AGB_WARNING_EX(exp, file, line)
#else
#define AGB_WARNING_EX(exp, file, line) (exp) ? ((void*)0) : AGBAssert(file, line, #exp, 0);
#endif
#endif // GUARD_GBA_ISAGBPRINT_H

View File

@ -0,0 +1,467 @@
#ifndef GUARD_GBA_M4A_INTERNAL_H
#define GUARD_GBA_M4A_INTERNAL_H
#include "gba/gba.h"
// ASCII encoding of 'Smsh' in reverse
// This is presumably short for SMASH, the developer of MKS4AGB.
#define ID_NUMBER 0x68736D53
#define C_V 0x40 // center value for PAN, BEND, and TUNE
#define SOUND_MODE_REVERB_VAL 0x0000007F
#define SOUND_MODE_REVERB_SET 0x00000080
#define SOUND_MODE_MAXCHN 0x00000F00
#define SOUND_MODE_MAXCHN_SHIFT 8
#define SOUND_MODE_MASVOL 0x0000F000
#define SOUND_MODE_MASVOL_SHIFT 12
#define SOUND_MODE_FREQ_05734 0x00010000
#define SOUND_MODE_FREQ_07884 0x00020000
#define SOUND_MODE_FREQ_10512 0x00030000
#define SOUND_MODE_FREQ_13379 0x00040000
#define SOUND_MODE_FREQ_15768 0x00050000
#define SOUND_MODE_FREQ_18157 0x00060000
#define SOUND_MODE_FREQ_21024 0x00070000
#define SOUND_MODE_FREQ_26758 0x00080000
#define SOUND_MODE_FREQ_31536 0x00090000
#define SOUND_MODE_FREQ_36314 0x000A0000
#define SOUND_MODE_FREQ_40137 0x000B0000
#define SOUND_MODE_FREQ_42048 0x000C0000
#define SOUND_MODE_FREQ 0x000F0000
#define SOUND_MODE_FREQ_SHIFT 16
#define SOUND_MODE_DA_BIT_9 0x00800000
#define SOUND_MODE_DA_BIT_8 0x00900000
#define SOUND_MODE_DA_BIT_7 0x00A00000
#define SOUND_MODE_DA_BIT_6 0x00B00000
#define SOUND_MODE_DA_BIT 0x00B00000
#define SOUND_MODE_DA_BIT_SHIFT 20
struct WaveData
{
u16 type;
u16 status;
u32 freq;
u32 loopStart;
u32 size; // number of samples
s8 data[1]; // samples
};
#define TONEDATA_TYPE_CGB 0x07
#define TONEDATA_TYPE_FIX 0x08
#define TONEDATA_TYPE_SPL 0x40 // key split
#define TONEDATA_TYPE_RHY 0x80 // rhythm
#define TONEDATA_P_S_PAN 0xc0
#define TONEDATA_P_S_PAM TONEDATA_P_S_PAN
struct ToneData
{
u8 type;
u8 key;
u8 length; // sound length (compatible sound)
u8 pan_sweep; // pan or sweep (compatible sound ch. 1)
struct WaveData *wav;
u8 attack;
u8 decay;
u8 sustain;
u8 release;
};
struct CgbChannel
{
u8 sf;
u8 ty;
u8 rightVolume;
u8 leftVolume;
u8 at;
u8 de;
u8 su;
u8 re;
u8 ky;
u8 ev;
u8 eg;
u8 ec;
u8 echoVolume;
u8 echoLength;
u8 d1;
u8 d2;
u8 gt;
u8 mk;
u8 ve;
u8 pr;
u8 rp;
u8 d3[3];
u8 d5;
u8 sg;
u8 n4;
u8 pan;
u8 panMask;
u8 mo;
u8 le;
u8 sw;
u32 fr;
u32 wp;
u32 cp;
u32 tp;
u32 pp;
u32 np;
u8 d4[8];
};
struct MusicPlayerTrack;
struct SoundChannel
{
u8 status;
u8 type;
u8 rightVolume;
u8 leftVolume;
u8 attack;
u8 decay;
u8 sustain;
u8 release;
u8 ky;
u8 ev;
u8 er;
u8 el;
u8 echoVolume;
u8 echoLength;
u8 d1;
u8 d2;
u8 gt;
u8 mk;
u8 ve;
u8 pr;
u8 rp;
u8 d3[3];
u32 ct;
u32 fw;
u32 freq;
struct WaveData *wav;
u32 cp;
struct MusicPlayerTrack *track;
u32 pp;
u32 np;
u32 d4;
u16 xpi;
u16 xpc;
};
#define MAX_DIRECTSOUND_CHANNELS 12
#define PCM_DMA_BUF_SIZE 1584 // size of Direct Sound buffer
struct SoundInfo
{
// This field is normally equal to ID_NUMBER but it is set to other
// values during sensitive operations for locking purposes.
// This field should be volatile but isn't. This could potentially cause
// race conditions.
u32 ident;
vu8 pcmDmaCounter;
// Direct Sound
u8 reverb;
u8 maxChans;
u8 masterVolume;
u8 freq;
u8 mode;
u8 c15;
u8 pcmDmaPeriod; // number of V-blanks per PCM DMA
u8 maxLines;
u8 gap[3];
s32 pcmSamplesPerVBlank;
s32 pcmFreq;
s32 divFreq;
struct CgbChannel *cgbChans;
u32 func;
u32 intp;
void (*CgbSound)(void);
void (*CgbOscOff)(u8);
u32 (*MidiKeyToCgbFreq)(u8, u8, u8);
u32 MPlayJumpTable;
u32 plynote;
u32 ExtVolPit;
u8 gap2[16];
struct SoundChannel chans[MAX_DIRECTSOUND_CHANNELS];
s8 pcmBuffer[PCM_DMA_BUF_SIZE * 2];
};
struct SongHeader
{
u8 trackCount;
u8 blockCount;
u8 priority;
u8 reverb;
struct ToneData *tone;
u8 *part[1];
};
struct PokemonCrySong
{
u8 trackCount;
u8 blockCount;
u8 priority;
u8 reverb;
struct ToneData *tone;
u8 *part[2];
u8 gap;
u8 part0; // 0x11
u8 tuneValue; // 0x12
u8 gotoCmd; // 0x13
u32 gotoTarget; // 0x14
u8 part1; // 0x18
u8 tuneValue2; // 0x19
u8 cont[2]; // 0x1A
u8 volCmd; // 0x1C
u8 volumeValue; // 0x1D
u8 unkCmd0D[2]; // 0x1E
u32 unkCmd0DParam; // 0x20
u8 xreleCmd[2]; // 0x24
u8 releaseValue; // 0x26
u8 panCmd;
u8 panValue; // 0x28
u8 tieCmd; // 0x29
u8 tieKeyValue; // 0x2A
u8 tieVelocityValue; // 0x2B
u8 unkCmd0C[2]; // 0x2C
u16 unkCmd0CParam; // 0x2E
u8 end[2]; // 0x30
};
#define MPT_FLG_VOLSET 0x01
#define MPT_FLG_VOLCHG 0x03
#define MPT_FLG_PITSET 0x04
#define MPT_FLG_PITCHG 0x0C
#define MPT_FLG_START 0x40
#define MPT_FLG_EXIST 0x80
struct MusicPlayerTrack
{
u8 flags;
u8 wait;
u8 patternLevel;
u8 repN;
u8 gateTime;
u8 key;
u8 velocity;
u8 runningStatus;
u8 keyM;
u8 pitM;
s8 keyShift;
s8 keyShiftX;
s8 tune;
u8 pitX;
s8 bend;
u8 bendRange;
u8 volMR;
u8 volML;
u8 vol;
u8 volX;
s8 pan;
s8 panX;
s8 modM;
u8 mod;
u8 modT;
u8 lfoSpeed;
u8 lfoSpeedC;
u8 lfoDelay;
u8 lfoDelayC;
u8 priority;
u8 echoVolume;
u8 echoLength;
struct SoundChannel *chan;
struct ToneData tone;
u8 gap[10];
u16 unk_3A;
u32 unk_3C;
u8 *cmdPtr;
u8 *patternStack[3];
};
#define MUSICPLAYER_STATUS_TRACK 0x0000ffff
#define MUSICPLAYER_STATUS_PAUSE 0x80000000
#define MAX_MUSICPLAYER_TRACKS 16
#define TEMPORARY_FADE 0x0001
#define FADE_IN 0x0002
#define FADE_VOL_MAX 64
#define FADE_VOL_SHIFT 2
struct MusicPlayerInfo
{
struct SongHeader *songHeader;
u32 status;
u8 trackCount;
u8 priority;
u8 cmd;
u8 unk_B;
u32 clock;
u8 gap[8];
u8 *memAccArea;
u16 tempoD;
u16 tempoU;
u16 tempoI;
u16 tempoC;
u16 fadeOI;
u16 fadeOC;
u16 fadeOV;
struct MusicPlayerTrack *tracks;
struct ToneData *tone;
u32 ident;
u32 func;
u32 intp;
};
struct MusicPlayer
{
struct MusicPlayerInfo *info;
struct MusicPlayerTrack *track;
u8 unk_8;
u16 unk_A;
};
struct Song
{
struct SongHeader *header;
u16 ms;
u16 me;
};
extern const struct MusicPlayer gMPlayTable[];
extern const struct Song gSongTable[];
extern u8 gMPlayMemAccArea[];
//u8 gPokemonCrySong[52];
//u8 gPokemonCrySongs[52 * MAX_POKEMON_CRIES];
#define MAX_POKEMON_CRIES 2
extern struct PokemonCrySong gPokemonCrySong;
extern struct PokemonCrySong gPokemonCrySongs[];
extern struct MusicPlayerInfo gPokemonCryMusicPlayers[];
extern struct MusicPlayerTrack gPokemonCryTracks[];
extern char SoundMainRAM[];
extern void *gMPlayJumpTable[];
typedef void (*XcmdFunc)(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
extern const XcmdFunc gXcmdTable[];
extern struct CgbChannel gCgbChans[];
extern const u8 gScaleTable[];
extern const u32 gFreqTable[];
extern const u16 gPcmSamplesPerVBlankTable[];
extern const u8 gCgbScaleTable[];
extern const s16 gCgbFreqTable[];
extern const u8 gNoiseTable[];
extern const struct PokemonCrySong gPokemonCrySongTemplate;
extern const struct ToneData voicegroup000;
extern char gNumMusicPlayers[];
extern char gMaxLines[];
#define NUM_MUSIC_PLAYERS ((u16)gNumMusicPlayers)
#define MAX_LINES ((u32)gMaxLines)
u32 umul3232H32(u32 multiplier, u32 multiplicand);
void SoundMain(void);
void SoundMainBTM(void);
void TrackStop(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track);
void MPlayMain(void);
void RealClearChain(void *x);
void MPlayContinue(struct MusicPlayerInfo *mplayInfo);
void MPlayStart(struct MusicPlayerInfo *mplayInfo, struct SongHeader *songHeader);
void m4aMPlayStop(struct MusicPlayerInfo *mplayInfo);
void FadeOutBody(struct MusicPlayerInfo *mplayInfo);
void TrkVolPitSet(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track);
void MPlayFadeOut(struct MusicPlayerInfo *mplayInfo, u16 speed);
void ClearChain(void *x);
void Clear64byte(void *addr);
void SoundInit(struct SoundInfo *soundInfo);
void MPlayExtender(struct CgbChannel *cgbChans);
void m4aSoundMode(u32 mode);
void MPlayOpen(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track, u8 a3);
void CgbSound(void);
void CgbOscOff(u8);
u32 MidiKeyToCgbFreq(u8, u8, u8);
void DummyFunc(void);
void MPlayJumpTableCopy(void **mplayJumpTable);
void SampleFreqSet(u32 freq);
void m4aSoundVSyncOn(void);
void m4aSoundVSyncOff(void);
void m4aMPlayTempoControl(struct MusicPlayerInfo *mplayInfo, u16 tempo);
void m4aMPlayVolumeControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u16 volume);
void m4aMPlayPitchControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, s16 pitch);
void m4aMPlayPanpotControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, s8 pan);
void ClearModM(struct MusicPlayerTrack *track);
void m4aMPlayModDepthSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 modDepth);
void m4aMPlayLFOSpeedSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 lfoSpeed);
struct MusicPlayerInfo *SetPokemonCryTone(struct ToneData *tone);
void SetPokemonCryVolume(u8 val);
void SetPokemonCryPanpot(s8 val);
void SetPokemonCryPitch(s16 val);
void SetPokemonCryLength(u16 val);
void SetPokemonCryRelease(u8 val);
void SetPokemonCryProgress(u32 val);
bool32 IsPokemonCryPlaying(struct MusicPlayerInfo *mplayInfo);
void SetPokemonCryChorus(s8 val);
void SetPokemonCryStereo(u32 val);
void SetPokemonCryPriority(u8 val);
// sound command handler functions
void ply_fine(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_goto(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_patt(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_pend(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_rept(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_memacc(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_prio(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_tempo(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_keysh(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_voice(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_vol(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_pan(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_bend(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_bendr(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_lfos(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_lfodl(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_mod(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_modt(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_tune(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_port(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_xcmd(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_endtie(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_note(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
// extended sound command handler functions
void ply_xxx(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_xwave(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_xtype(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_xatta(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_xdeca(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_xsust(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_xrele(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_xiecv(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_xiecl(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_xleng(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_xswee(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_xcmd_0C(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
void ply_xcmd_0D(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
#endif // GUARD_GBA_M4A_INTERNAL_H

View File

@ -0,0 +1,247 @@
#ifndef GUARD_GBA_MACRO_H
#define GUARD_GBA_MACRO_H
#define CPU_FILL(value, dest, size, bit) \
{ \
vu##bit tmp = (vu##bit)(value); \
CpuSet((void *)&tmp, \
dest, \
CPU_SET_##bit##BIT | CPU_SET_SRC_FIXED | ((size)/(bit/8) & 0x1FFFFF)); \
}
#define CpuFill16(value, dest, size) CPU_FILL(value, dest, size, 16)
#define CpuFill32(value, dest, size) CPU_FILL(value, dest, size, 32)
#define CPU_COPY(src, dest, size, bit) CpuSet(src, dest, CPU_SET_##bit##BIT | ((size)/(bit/8) & 0x1FFFFF))
#define CpuCopy16(src, dest, size) CPU_COPY(src, dest, size, 16)
#define CpuCopy32(src, dest, size) CPU_COPY(src, dest, size, 32)
#define CpuFastFill(value, dest, size) \
{ \
vu32 tmp = (vu32)(value); \
CpuFastSet((void *)&tmp, \
dest, \
CPU_FAST_SET_SRC_FIXED | ((size)/(32/8) & 0x1FFFFF)); \
}
#define CpuFastFill16(value, dest, size) CpuFastFill(((value) << 16) | (value), (dest), (size))
#define CpuFastFill8(value, dest, size) CpuFastFill(((value) << 24) | ((value) << 16) | ((value) << 8) | (value), (dest), (size))
#define CpuFastCopy(src, dest, size) CpuFastSet(src, dest, ((size)/(32/8) & 0x1FFFFF))
#define DmaSet(dmaNum, src, dest, control) \
{ \
vu32 *dmaRegs = (vu32 *)REG_ADDR_DMA##dmaNum; \
dmaRegs[0] = (vu32)(src); \
dmaRegs[1] = (vu32)(dest); \
dmaRegs[2] = (vu32)(control); \
dmaRegs[2]; \
}
#define DMA_FILL(dmaNum, value, dest, size, bit) \
{ \
vu##bit tmp = (vu##bit)(value); \
DmaSet(dmaNum, \
&tmp, \
dest, \
(DMA_ENABLE | DMA_START_NOW | DMA_##bit##BIT | DMA_SRC_FIXED | DMA_DEST_INC) << 16 \
| ((size)/(bit/8))); \
}
#define DmaFill16(dmaNum, value, dest, size) DMA_FILL(dmaNum, value, dest, size, 16)
#define DmaFill32(dmaNum, value, dest, size) DMA_FILL(dmaNum, value, dest, size, 32)
// Note that the DMA clear macros cause the DMA control value to be calculated
// at runtime rather than compile time. The size is divided by the DMA transfer
// unit size (2 or 4 bytes) and then combined with the DMA control flags using a
// bitwise OR operation.
#define DMA_CLEAR(dmaNum, dest, size, bit) \
{ \
vu##bit *_dest = (vu##bit *)(dest); \
u32 _size = size; \
DmaFill##bit(dmaNum, 0, _dest, _size); \
}
#define DmaClear16(dmaNum, dest, size) DMA_CLEAR(dmaNum, dest, size, 16)
#define DmaClear32(dmaNum, dest, size) DMA_CLEAR(dmaNum, dest, size, 32)
#define DMA_COPY(dmaNum, src, dest, size, bit) \
DmaSet(dmaNum, \
src, \
dest, \
(DMA_ENABLE | DMA_START_NOW | DMA_##bit##BIT | DMA_SRC_INC | DMA_DEST_INC) << 16 \
| ((size)/(bit/8)))
#define DmaCopy16(dmaNum, src, dest, size) DMA_COPY(dmaNum, src, dest, size, 16)
#define DmaCopy32(dmaNum, src, dest, size) DMA_COPY(dmaNum, src, dest, size, 32)
#define DmaCopyLarge(dmaNum, src, dest, size, block, bit) \
{ \
const void *_src = src; \
void *_dest = (void *)dest; \
u32 _size = size; \
while (1) \
{ \
DmaCopy##bit(dmaNum, _src, _dest, (block)); \
_src += (block); \
_dest += (block); \
_size -= (block); \
if (_size <= (block)) \
{ \
DmaCopy##bit(dmaNum, _src, _dest, _size); \
break; \
} \
} \
}
#define DmaCopyLarge16(dmaNum, src, dest, size, block) DmaCopyLarge(dmaNum, src, dest, size, block, 16)
#define DmaCopyLarge32(dmaNum, src, dest, size, block) DmaCopyLarge(dmaNum, src, dest, size, block, 32)
#define DmaFillLarge(dmaNum, value, dest, size, block, bit) \
{ \
void *_dest = (void *)dest; \
u32 _size = size; \
while (1) \
{ \
DmaFill##bit(dmaNum, value, _dest, (block)); \
_dest += (block); \
_size -= (block); \
if (_size <= (block)) \
{ \
DmaFill##bit(dmaNum, value, _dest, _size); \
break; \
} \
} \
}
#define DmaFillLarge16(dmaNum, value, dest, size, block) DmaFillLarge(dmaNum, value, dest, size, block, 16)
#define DmaFillLarge32(dmaNum, value, dest, size, block) DmaFillLarge(dmaNum, value, dest, size, block, 32)
#define DmaClearLarge(dmaNum, dest, size, block, bit) \
{ \
void *_dest = (void *)dest; \
u32 _size = size; \
while (1) \
{ \
DmaFill##bit(dmaNum, 0, _dest, (block)); \
_dest += (block); \
_size -= (block); \
if (_size <= (block)) \
{ \
DmaFill##bit(dmaNum, 0, _dest, _size); \
break; \
} \
} \
}
#define DmaClearLarge16(dmaNum, dest, size, block) DmaClearLarge(dmaNum, dest, size, block, 16)
#define DmaClearLarge32(dmaNum, dest, size, block) DmaClearLarge(dmaNum, dest, size, block, 32)
#define DmaCopyDefvars(dmaNum, src, dest, size, bit) \
{ \
const void *_src = src; \
void *_dest = (void *)(dest); \
u32 _size = size; \
DmaCopy##bit(dmaNum, _src, _dest, _size); \
}
#define DmaCopy16Defvars(dmaNum, src, dest, size) DmaCopyDefvars(dmaNum, src, dest, size, 16)
#define DmaCopy32Defvars(dmaNum, src, dest, size) DmaCopyDefvars(dmaNum, src, dest, size, 32)
#define DmaFillDefvars(dmaNum, value, dest, size, bit) \
{ \
void *_dest = (void *)dest; \
u32 _size = size; \
DmaFill##bit(dmaNum, value, _dest, _size); \
}
#define DmaFill16Defvars(dmaNum, value, dest, size) DmaFillDefvars(dmaNum, value, dest, size, 16)
#define DmaFill32Defvars(dmaNum, value, dest, size) DmaFillDefvars(dmaNum, value, dest, size, 32)
#define DmaClearDefvars(dmaNum, dest, size, bit) \
{ \
void *_dest = (void *)dest; \
u32 _size = size; \
DmaClear##bit(dmaNum, _dest, _size); \
}
#define DmaClear16Defvars(dmaNum, dest, size) DmaClearDefvars(dmaNum, dest, size, 16)
#define DmaClear32Defvars(dmaNum, dest, size) DmaClearDefvars(dmaNum, dest, size, 32)
#define DmaStop(dmaNum) \
{ \
vu16 *dmaRegs = (vu16 *)REG_ADDR_DMA##dmaNum; \
dmaRegs[5] &= ~(DMA_START_MASK | DMA_DREQ_ON | DMA_REPEAT); \
dmaRegs[5] &= ~DMA_ENABLE; \
dmaRegs[5]; \
}
#define IntrEnable(flags) \
{ \
u16 imeTemp; \
\
imeTemp = REG_IME; \
REG_IME = 0; \
REG_IE |= flags; \
REG_IME = imeTemp; \
} \
// from pokeemerald
// Maximum amount of data we will transfer in one operation
#define MAX_DMA_BLOCK_SIZE 0x1000
#define MAX_DMA_REQUESTS 128
#define DMA_REQUEST_COPY32 1
#define DMA_REQUEST_FILL32 2
#define DMA_REQUEST_COPY16 3
#define DMA_REQUEST_FILL16 4
#define Dma3CopyLarge_(src, dest, size, bit) \
{ \
const void *_src = src; \
void *_dest = (void *)dest; \
u32 _size = size; \
while (1) \
{ \
if (_size <= MAX_DMA_BLOCK_SIZE) \
{ \
DmaCopy##bit(3, _src, _dest, _size); \
break; \
} \
DmaCopy##bit(3, _src, _dest, MAX_DMA_BLOCK_SIZE); \
_src += MAX_DMA_BLOCK_SIZE; \
_dest += MAX_DMA_BLOCK_SIZE; \
_size -= MAX_DMA_BLOCK_SIZE; \
} \
}
#define Dma3CopyLarge16_(src, dest, size) Dma3CopyLarge_(src, dest, size, 16)
#define Dma3CopyLarge32_(src, dest, size) Dma3CopyLarge_(src, dest, size, 32)
#define Dma3FillLarge_(value, dest, size, bit) \
{ \
void *_dest = (void *)dest; \
u32 _size = size; \
while (1) \
{ \
if (_size <= MAX_DMA_BLOCK_SIZE) \
{ \
DmaFill##bit(3, value, _dest, _size); \
break; \
} \
DmaFill##bit(3, value, _dest, MAX_DMA_BLOCK_SIZE); \
_dest += MAX_DMA_BLOCK_SIZE; \
_size -= MAX_DMA_BLOCK_SIZE; \
} \
}
#define Dma3FillLarge16_(value, dest, size) Dma3FillLarge_(value, dest, size, 16)
#define Dma3FillLarge32_(value, dest, size) Dma3FillLarge_(value, dest, size, 32)
#endif // GUARD_GBA_MACRO_H

View File

@ -0,0 +1,55 @@
#ifndef GUARD_GBA_MULTIBOOT_H
#define GUARD_GBA_MULTIBOOT_H
#define MULTIBOOT_NCHILD 3 // Maximum number of slaves
#define MULTIBOOT_HEADER_SIZE 0xc0 // Header size
#define MULTIBOOT_SEND_SIZE_MIN 0x100 // Minimum transmission size
#define MULTIBOOT_SEND_SIZE_MAX 0x40000 // Maximum transmission size
struct MultiBootParam
{
u32 system_work[5]; // 00
u8 handshake_data; // 14
u8 padding; // 15
u16 handshake_timeout; // 16
u8 probe_count; // 18
u8 client_data[MULTIBOOT_NCHILD]; // 19
u8 palette_data; // 1c
u8 response_bit; // 1d
u8 client_bit; // 1e
u8 reserved1; // 1f
const u8 *boot_srcp; // 20
const u8 *boot_endp; // 24
const u8 *masterp;
u8 *reserved2[MULTIBOOT_NCHILD];
u32 system_work2[4];
u8 sendflag;
u8 probe_target_bit;
u8 check_wait;
u8 server_type;
};
#define MULTIBOOT_ERROR_04 0x04
#define MULTIBOOT_ERROR_08 0x08
#define MULTIBOOT_ERROR_0c 0x0c
#define MULTIBOOT_ERROR_40 0x40
#define MULTIBOOT_ERROR_44 0x44
#define MULTIBOOT_ERROR_48 0x48
#define MULTIBOOT_ERROR_4c 0x4c
#define MULTIBOOT_ERROR_80 0x80
#define MULTIBOOT_ERROR_84 0x84
#define MULTIBOOT_ERROR_88 0x88
#define MULTIBOOT_ERROR_8c 0x8c
#define MULTIBOOT_ERROR_NO_PROBE_TARGET 0x50
#define MULTIBOOT_ERROR_NO_DLREADY 0x60
#define MULTIBOOT_ERROR_BOOT_FAILURE 0x70
#define MULTIBOOT_ERROR_HANDSHAKE_FAILURE 0x71
#define MULTIBOOT_CONNECTION_CHECK_WAIT 15
#define MULTIBOOT_SERVER_TYPE_NORMAL 0
#define MULTIBOOT_SERVER_TYPE_QUICK 1
#define MULTIBOOT_HANDSHAKE_TIMEOUT 400
#endif // GUARD_GBA_MULTIBOOT_H

View File

@ -0,0 +1,57 @@
#ifndef GUARD_GBA_SYSCALL_H
#define GUARD_GBA_SYSCALL_H
#include "gba/types.h"
#define RESET_EWRAM 0x01
#define RESET_IWRAM 0x02
#define RESET_PALETTE 0x04
#define RESET_VRAM 0x08
#define RESET_OAM 0x10
#define RESET_SIO_REGS 0x20
#define RESET_SOUND_REGS 0x40
#define RESET_REGS 0x80
#define RESET_ALL 0xFF
void SoftReset(u32 resetFlags);
void RegisterRamReset(u32 resetFlags);
void VBlankIntrWait(void);
u16 Sqrt(u32 num);
u16 ArcTan2(s16 x, s16 y);
#define CPU_SET_SRC_FIXED 0x01000000
#define CPU_SET_16BIT 0x00000000
#define CPU_SET_32BIT 0x04000000
void CpuSet(const void *src, void *dest, u32 control);
#define CPU_FAST_SET_SRC_FIXED 0x01000000
void CpuFastSet(const void *src, void *dest, u32 control);
void BgAffineSet(struct BgAffineSrcData *src, struct BgAffineDstData *dest, s32 count);
void ObjAffineSet(struct ObjAffineSrcData *src, void *dest, s32 count, s32 offset);
void LZ77UnCompWram(const void *src, void *dest);
void LZ77UnCompVram(const void *src, void *dest);
void RLUnCompWram(const void *src, void *dest);
void RLUnCompVram(const void *src, void *dest);
int MultiBoot(struct MultiBootParam *mp);
void SoundBiasReset(void);
void SoundBiasSet(void);
u32 Div(u32 divisor, u32 dividend);
u32 Mod(u32 divisor, u32 dividend);
#endif // GUARD_GBA_SYSCALL_H

View File

@ -0,0 +1,146 @@
#ifndef GUARD_GBA_TYPES_H
#define GUARD_GBA_TYPES_H
#include <stdint.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
typedef volatile u8 vu8;
typedef volatile u16 vu16;
typedef volatile u32 vu32;
typedef volatile u64 vu64;
typedef volatile s8 vs8;
typedef volatile s16 vs16;
typedef volatile s32 vs32;
typedef volatile s64 vs64;
typedef float f32;
typedef double f64;
typedef u8 bool8;
typedef u16 bool16;
typedef u32 bool32;
struct BgCnt
{
u16 priority:2;
u16 charBaseBlock:2;
u16 dummy:2;
u16 mosaic:1;
u16 palettes:1;
u16 screenBaseBlock:5;
u16 areaOverflowMode:1;
u16 screenSize:2;
};
typedef volatile struct BgCnt vBgCnt;
struct PlttData
{
u16 r:5; // red
u16 g:5; // green
u16 b:5; // blue
u16 unused_15:1;
};
struct OamData
{
/*0x00*/ u32 y:8;
/*0x01*/ u32 affineMode:2; // 0x1, 0x2 -> 0x4
u32 objMode:2; // 0x4, 0x8 -> 0xC
u32 mosaic:1; // 0x10
u32 bpp:1; // 0x20
u32 shape:2; // 0x40, 0x80 -> 0xC0
/*0x02*/ u32 x:9;
u32 matrixNum:5; // bits 3/4 are h-flip/v-flip if not in affine mode
u32 size:2;
/*0x04*/ u16 tileNum:10; // 0x3FF
u16 priority:2; // 0x400, 0x800 -> 0xC00
u16 paletteNum:4;
/*0x06*/ u16 affineParam;
};
#define ST_OAM_OBJ_NORMAL 0
#define ST_OAM_OBJ_BLEND 1
#define ST_OAM_OBJ_WINDOW 2
#define ST_OAM_AFFINE_OFF 0
#define ST_OAM_AFFINE_NORMAL 1
#define ST_OAM_AFFINE_ERASE 2
#define ST_OAM_AFFINE_DOUBLE 3
#define ST_OAM_AFFINE_ON_MASK 1
#define ST_OAM_AFFINE_DOUBLE_MASK 2
#define ST_OAM_4BPP 0
#define ST_OAM_8BPP 1
#define ST_OAM_SQUARE 0
#define ST_OAM_H_RECTANGLE 1
#define ST_OAM_V_RECTANGLE 2
struct BgAffineSrcData
{
s32 texX;
s32 texY;
s16 scrX;
s16 scrY;
s16 sx;
s16 sy;
u16 alpha;
};
struct BgAffineDstData
{
s16 pa;
s16 pb;
s16 pc;
s16 pd;
s32 dx;
s32 dy;
};
struct ObjAffineSrcData
{
s16 xScale;
s16 yScale;
u16 rotation;
};
// Multi-player SIO Control Structure
struct SioMultiCnt
{
u16 baudRate:2; // baud rate
u16 si:1; // SI terminal
u16 sd:1; // SD terminal
u16 id:2; // ID
u16 error:1; // error flag
u16 enable:1; // SIO enable
u16 unused_11_8:4;
u16 mode:2; // communication mode (should equal 2)
u16 intrEnable:1; // IRQ enable
u16 unused_15:1;
u16 data; // data
};
#define ST_SIO_MULTI_MODE 2 // Multi-player communication mode
// baud rate
#define ST_SIO_9600_BPS 0 // 9600 bps
#define ST_SIO_38400_BPS 1 // 38400 bps
#define ST_SIO_57600_BPS 2 // 57600 bps
#define ST_SIO_115200_BPS 3 // 115200 bps
typedef void (*MainCallback)(void);
typedef void (*IntrCallback)(void);
typedef void (*IntrFunc)(void);
#endif // GUARD_GBA_TYPES_H

View File

@ -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

View File

@ -0,0 +1,310 @@
#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
{
u16 x, y;
u8 elevation;
u8 kind; // The "kind" field determines how to access bgUnion union below.
union {
u8 *script;
struct {
u16 item;
u16 hiddenItemId;
} hiddenItem;
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_CONTROLLABLE (1 << 5)
#define PLAYER_AVATAR_FLAG_FORCED_MOVE (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 gMapObjects[];
extern u8 gSelectedEventObject;
extern struct MapHeader gMapHeader;
extern struct PlayerAvatar gPlayerAvatar;
#endif // GUARD_GLOBAL_FIELDMAP_H

View File

@ -0,0 +1,876 @@
#ifndef GUARD_GLOBAL_H
#define GUARD_GLOBAL_H
#include "gba/gba.h"
// global.h from pokemon ruby
// IDE support
#if defined(__APPLE__) || defined(__CYGWIN__) || defined(__INTELLISENSE__)
// We define these when using certain IDEs to fool preproc
#define _(x) (x)
#define __(x) (x)
#define INCBIN(...) {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 // IDE support
// 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,54 @@
#ifndef GUARD_RTC_H
#define GUARD_RTC_H
#include "gba/gba.h"
#define SIIRTCINFO_INTFE 0x01 // frequency interrupt enable
#define SIIRTCINFO_INTME 0x02 // per-minute interrupt enable
#define SIIRTCINFO_INTAE 0x04 // alarm interrupt enable
#define SIIRTCINFO_24HOUR 0x40 // 0: 12-hour mode, 1: 24-hour mode
#define SIIRTCINFO_POWER 0x80 // power on or power failure occurred
enum
{
MONTH_JAN = 1,
MONTH_FEB,
MONTH_MAR,
MONTH_APR,
MONTH_MAY,
MONTH_JUN,
MONTH_JUL,
MONTH_AUG,
MONTH_SEP,
MONTH_OCT,
MONTH_NOV,
MONTH_DEC
};
struct SiiRtcInfo
{
u8 year;
u8 month;
u8 day;
u8 dayOfWeek;
u8 hour;
u8 minute;
u8 second;
u8 status;
u8 alarmHour;
u8 alarmMinute;
};
void SiiRtcUnprotect(void);
void SiiRtcProtect(void);
u8 SiiRtcProbe(void);
bool8 SiiRtcReset(void);
bool8 SiiRtcGetStatus(struct SiiRtcInfo *rtc);
bool8 SiiRtcSetStatus(struct SiiRtcInfo *rtc);
bool8 SiiRtcGetDateTime(struct SiiRtcInfo *rtc);
bool8 SiiRtcSetDateTime(struct SiiRtcInfo *rtc);
bool8 SiiRtcGetTime(struct SiiRtcInfo *rtc);
bool8 SiiRtcSetTime(struct SiiRtcInfo *rtc);
bool8 SiiRtcSetAlarm(struct SiiRtcInfo *rtc);
#endif // GUARD_RTC_H

View File

@ -0,0 +1,14 @@
/<EWRAM>/ {
r sym_ewram.ld
d
}
/<BSS>/ {
r sym_bss.ld
d
}
/<COMMON>/ {
r sym_common.ld
d
}

View File

@ -0,0 +1,107 @@
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)
{
src/agb_flash.o(.text);
src/agb_flash_1m.o(.text);
src/agb_flash_mx.o(.text);
asm/libagbsyscall.o(.text);
src/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)
{
src/agb_flash.o(.rodata);
src/agb_flash_1m.o(.rodata);
src/agb_flash_mx.o(.rodata);
src/agb_flash_le.o(.rodata);
src/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/ :
{
*(*);
}
}

View File

@ -0,0 +1 @@
866991e2b5a8de02d12f53abe0ee9af03a2b6e01 payload.gba

View File

@ -0,0 +1,296 @@
#include "gba/gba.h"
#include "gba/flash_internal.h"
static u8 sTimerNum;
static u16 sTimerCount;
static vu16 *sTimerReg;
static u16 sSavedIme;
u8 gFlashTimeoutFlag;
u8 (*PollFlashStatus)(u8 *);
const struct FlashType *gFlash;
u16 gFlashNumRemainingBytes;
const u16 *gFlashMaxTime;
u16 (*ProgramFlashByte)(u16, u32, u8);
u16 (*ProgramFlashSector)(u16, void *);
u16 (*EraseFlashChip)(void);
u16 (*EraseFlashSector)(u16);
u16 (*WaitForFlashWrite)(u8, u8 *, u8);
void SetReadFlash1(u16 *dest);
void SwitchFlashBank(u8 bankNum)
{
FLASH_WRITE(0x5555, 0xAA);
FLASH_WRITE(0x2AAA, 0x55);
FLASH_WRITE(0x5555, 0xB0);
FLASH_WRITE(0x0000, bankNum);
}
#define DELAY() \
do { \
vu16 i; \
for (i = 20000; i != 0; i--) \
; \
} while (0)
u16 ReadFlashId(void)
{
u16 flashId;
u16 readFlash1Buffer[0x20];
u8 (*readFlash1)(u8 *);
SetReadFlash1(readFlash1Buffer);
readFlash1 = (u8 (*)(u8 *))((s32)readFlash1Buffer + 1);
// Enter ID mode.
FLASH_WRITE(0x5555, 0xAA);
FLASH_WRITE(0x2AAA, 0x55);
FLASH_WRITE(0x5555, 0x90);
DELAY();
flashId = readFlash1(FLASH_BASE + 1) << 8;
flashId |= readFlash1(FLASH_BASE);
// Leave ID mode.
FLASH_WRITE(0x5555, 0xAA);
FLASH_WRITE(0x2AAA, 0x55);
FLASH_WRITE(0x5555, 0xF0);
FLASH_WRITE(0x5555, 0xF0);
DELAY();
return flashId;
}
void FlashTimerIntr(void)
{
if (sTimerCount != 0 && --sTimerCount == 0)
gFlashTimeoutFlag = 1;
}
u16 SetFlashTimerIntr(u8 timerNum, void (**intrFunc)(void))
{
if (timerNum >= 4)
return 1;
sTimerNum = timerNum;
sTimerReg = &REG_TMCNT(sTimerNum);
*intrFunc = FlashTimerIntr;
return 0;
}
void StartFlashTimer(u8 phase)
{
const u16 *maxTime = &gFlashMaxTime[phase * 3];
sSavedIme = REG_IME;
REG_IME = 0;
sTimerReg[1] = 0;
REG_IE |= (INTR_FLAG_TIMER0 << sTimerNum);
gFlashTimeoutFlag = 0;
sTimerCount = *maxTime++;
*sTimerReg++ = *maxTime++;
*sTimerReg-- = *maxTime++;
REG_IF = (INTR_FLAG_TIMER0 << sTimerNum);
REG_IME = 1;
}
void StopFlashTimer(void)
{
REG_IME = 0;
*sTimerReg++ = 0;
*sTimerReg-- = 0;
REG_IE &= ~(INTR_FLAG_TIMER0 << sTimerNum);
REG_IME = sSavedIme;
}
u8 ReadFlash1(u8 *addr)
{
return *addr;
}
void SetReadFlash1(u16 *dest)
{
u16 *src;
u16 i;
PollFlashStatus = (u8 (*)(u8 *))((s32)dest + 1);
src = (u16 *)ReadFlash1;
src = (u16 *)((s32)src ^ 1);
i = ((s32)SetReadFlash1 - (s32)ReadFlash1) >> 1;
while (i != 0)
{
*dest++ = *src++;
i--;
}
}
void ReadFlash_Core(u8 *src, u8 *dest, u32 size)
{
while (size-- != 0)
{
*dest++ = *src++;
}
}
void ReadFlash(u16 sectorNum, u32 offset, void *dest, u32 size)
{
u8 *src;
u16 i;
u16 readFlash_Core_Buffer[0x40];
u16 *funcSrc;
u16 *funcDest;
void (*readFlash_Core)(u8 *, u8 *, u32);
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
if (gFlash->romSize == FLASH_ROM_SIZE_1M)
{
SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
sectorNum %= SECTORS_PER_BANK;
}
funcSrc = (u16 *)ReadFlash_Core;
funcSrc = (u16 *)((s32)funcSrc ^ 1);
funcDest = readFlash_Core_Buffer;
i = ((s32)ReadFlash - (s32)ReadFlash_Core) >> 1;
while (i != 0)
{
*funcDest++ = *funcSrc++;
i--;
}
readFlash_Core = (void (*)(u8 *, u8 *, u32))((s32)readFlash_Core_Buffer + 1);
src = FLASH_BASE + (sectorNum << gFlash->sector.shift) + offset;
readFlash_Core(src, dest, size);
}
u32 VerifyFlashSector_Core(u8 *src, u8 *tgt, u32 size)
{
while (size-- != 0)
{
if (*tgt++ != *src++)
return (u32)(tgt - 1);
}
return 0;
}
u32 VerifyFlashSector(u16 sectorNum, u8 *src)
{
u16 i;
u16 verifyFlashSector_Core_Buffer[0x80];
u16 *funcSrc;
u16 *funcDest;
u8 *tgt;
u16 size;
u32 (*verifyFlashSector_Core)(u8 *, u8 *, u32);
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
if (gFlash->romSize == FLASH_ROM_SIZE_1M)
{
SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
sectorNum %= SECTORS_PER_BANK;
}
funcSrc = (u16 *)VerifyFlashSector_Core;
funcSrc = (u16 *)((s32)funcSrc ^ 1);
funcDest = verifyFlashSector_Core_Buffer;
i = ((s32)VerifyFlashSector - (s32)VerifyFlashSector_Core) >> 1;
while (i != 0)
{
*funcDest++ = *funcSrc++;
i--;
}
verifyFlashSector_Core = (u32 (*)(u8 *, u8 *, u32))((s32)verifyFlashSector_Core_Buffer + 1);
tgt = FLASH_BASE + (sectorNum << gFlash->sector.shift);
size = gFlash->sector.size;
return verifyFlashSector_Core(src, tgt, size);
}
u32 VerifyFlashSectorNBytes(u16 sectorNum, u8 *src, u32 n)
{
u16 i;
u16 verifyFlashSector_Core_Buffer[0x80];
u16 *funcSrc;
u16 *funcDest;
u8 *tgt;
u32 (*verifyFlashSector_Core)(u8 *, u8 *, u32);
if (gFlash->romSize == FLASH_ROM_SIZE_1M)
{
SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
sectorNum %= SECTORS_PER_BANK;
}
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
funcSrc = (u16 *)VerifyFlashSector_Core;
funcSrc = (u16 *)((s32)funcSrc ^ 1);
funcDest = verifyFlashSector_Core_Buffer;
i = ((s32)VerifyFlashSector - (s32)VerifyFlashSector_Core) >> 1;
while (i != 0)
{
*funcDest++ = *funcSrc++;
i--;
}
verifyFlashSector_Core = (u32 (*)(u8 *, u8 *, u32))((s32)verifyFlashSector_Core_Buffer + 1);
tgt = FLASH_BASE + (sectorNum << gFlash->sector.shift);
return verifyFlashSector_Core(src, tgt, n);
}
u32 ProgramFlashSectorAndVerify(u16 sectorNum, u8 *src)
{
u8 i;
u32 result;
for (i = 0; i < 3; i++)
{
result = ProgramFlashSector(sectorNum, src);
if (result != 0)
continue;
result = VerifyFlashSector(sectorNum, src);
if (result == 0)
break;
}
return result;
}
u32 ProgramFlashSectorAndVerifyNBytes(u16 sectorNum, void *src, u32 n)
{
u8 i;
u32 result;
for (i = 0; i < 3; i++)
{
result = ProgramFlashSector(sectorNum, src);
if (result != 0)
continue;
result = VerifyFlashSectorNBytes(sectorNum, src, n);
if (result == 0)
break;
}
return result;
}

View File

@ -0,0 +1,86 @@
#include "gba/gba.h"
#include "gba/flash_internal.h"
static const char AgbLibFlashVersion[] = "FLASH1M_V103";
const struct FlashSetupInfo * const sSetupInfos[] =
{
&MX29L010,
&LE26FV10N1TS,
&DefaultFlash
};
u32 IdentifyFlash(void)
{
u16 result;
u16 flashId;
const struct FlashSetupInfo * const *setupInfo;
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
flashId = ReadFlashId();
setupInfo = sSetupInfos;
result = 1;
for (;;)
{
if ((*setupInfo)->type.ids.separate.makerId == 0)
break;
if (flashId == (*setupInfo)->type.ids.joined)
{
result = 0;
break;
}
setupInfo++;
}
ProgramFlashByte = (*setupInfo)->programFlashByte;
ProgramFlashSector = (*setupInfo)->programFlashSector;
EraseFlashChip = (*setupInfo)->eraseFlashChip;
EraseFlashSector = (*setupInfo)->eraseFlashSector;
WaitForFlashWrite = (*setupInfo)->WaitForFlashWrite;
gFlashMaxTime = (*setupInfo)->maxTime;
gFlash = &(*setupInfo)->type;
return result;
}
u16 WaitForFlashWrite_Common(u8 phase, u8 *addr, u8 lastData)
{
u16 result = 0;
u8 status;
StartFlashTimer(phase);
while ((status = PollFlashStatus(addr)) != lastData)
{
if (status & 0x20)
{
// The write operation exceeded the flash chip's time limit.
if (PollFlashStatus(addr) == lastData)
break;
FLASH_WRITE(0x5555, 0xF0);
result = phase | 0xA000u;
break;
}
if (gFlashTimeoutFlag)
{
if (PollFlashStatus(addr) == lastData)
break;
FLASH_WRITE(0x5555, 0xF0);
result = phase | 0xC000u;
break;
}
}
StopFlashTimer();
return result;
}

View File

@ -0,0 +1,31 @@
#include "gba/gba.h"
#include "gba/flash_internal.h"
const u16 leMaxTime[] =
{
10, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
10, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
2000, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
2000, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
};
const struct FlashSetupInfo LE26FV10N1TS =
{
ProgramFlashByte_MX,
ProgramFlashSector_MX,
EraseFlashChip_MX,
EraseFlashSector_MX,
WaitForFlashWrite_Common,
leMaxTime,
{
131072, // ROM size
{
4096, // sector size
12, // bit shift to multiply by sector size (4096 == 1 << 12)
32, // number of sectors
0 // appears to be unused
},
{ 3, 1 }, // wait state setup data
{ { 0x62, 0x13 } } // ID
}
};

View File

@ -0,0 +1,193 @@
#include "gba/gba.h"
#include "gba/flash_internal.h"
const u16 mxMaxTime[] =
{
10, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
10, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
2000, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
2000, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
};
const struct FlashSetupInfo MX29L010 =
{
ProgramFlashByte_MX,
ProgramFlashSector_MX,
EraseFlashChip_MX,
EraseFlashSector_MX,
WaitForFlashWrite_Common,
mxMaxTime,
{
131072, // ROM size
{
4096, // sector size
12, // bit shift to multiply by sector size (4096 == 1 << 12)
32, // number of sectors
0 // appears to be unused
},
{ 3, 1 }, // wait state setup data
{ { 0xC2, 0x09 } } // ID
}
};
const struct FlashSetupInfo DefaultFlash =
{
ProgramFlashByte_MX,
ProgramFlashSector_MX,
EraseFlashChip_MX,
EraseFlashSector_MX,
WaitForFlashWrite_Common,
mxMaxTime,
{
131072, // ROM size
{
4096, // sector size
12, // bit shift to multiply by sector size (4096 == 1 << 12)
32, // number of sectors
0 // appears to be unused
},
{ 3, 1 }, // wait state setup data
{ { 0x00, 0x00 } } // ID of 0
}
};
u16 EraseFlashChip_MX(void)
{
u16 result;
u16 readFlash1Buffer[0x20];
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | gFlash->wait[0];
FLASH_WRITE(0x5555, 0xAA);
FLASH_WRITE(0x2AAA, 0x55);
FLASH_WRITE(0x5555, 0x80);
FLASH_WRITE(0x5555, 0xAA);
FLASH_WRITE(0x2AAA, 0x55);
FLASH_WRITE(0x5555, 0x10);
SetReadFlash1(readFlash1Buffer);
result = WaitForFlashWrite(3, FLASH_BASE, 0xFF);
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
return result;
}
u16 EraseFlashSector_MX(u16 sectorNum)
{
u16 numTries;
u16 result;
u8 *addr;
u16 readFlash1Buffer[0x20];
if (sectorNum >= gFlash->sector.count)
return 0x80FF;
SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
sectorNum %= SECTORS_PER_BANK;
numTries = 0;
try_erase:
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | gFlash->wait[0];
addr = FLASH_BASE + (sectorNum << gFlash->sector.shift);
FLASH_WRITE(0x5555, 0xAA);
FLASH_WRITE(0x2AAA, 0x55);
FLASH_WRITE(0x5555, 0x80);
FLASH_WRITE(0x5555, 0xAA);
FLASH_WRITE(0x2AAA, 0x55);
*addr = 0x30;
SetReadFlash1(readFlash1Buffer);
result = WaitForFlashWrite(2, addr, 0xFF);
if (!(result & 0xA000) || numTries > 3)
goto done;
numTries++;
goto try_erase;
done:
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
return result;
}
u16 ProgramFlashByte_MX(u16 sectorNum, u32 offset, u8 data)
{
u8 *addr;
u16 readFlash1Buffer[0x20];
if (offset >= gFlash->sector.size)
return 0x8000;
SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
sectorNum %= SECTORS_PER_BANK;
addr = FLASH_BASE + (sectorNum << gFlash->sector.shift) + offset;
SetReadFlash1(readFlash1Buffer);
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | gFlash->wait[0];
FLASH_WRITE(0x5555, 0xAA);
FLASH_WRITE(0x2AAA, 0x55);
FLASH_WRITE(0x5555, 0xA0);
*addr = data;
return WaitForFlashWrite(1, addr, data);
}
static u16 ProgramByte(u8 *src, u8 *dest)
{
FLASH_WRITE(0x5555, 0xAA);
FLASH_WRITE(0x2AAA, 0x55);
FLASH_WRITE(0x5555, 0xA0);
*dest = *src;
return WaitForFlashWrite(1, dest, *src);
}
u16 ProgramFlashSector_MX(u16 sectorNum, void *src)
{
u16 result;
u8 *dest;
u16 readFlash1Buffer[0x20];
if (sectorNum >= gFlash->sector.count)
return 0x80FF;
result = EraseFlashSector_MX(sectorNum);
if (result != 0)
return result;
SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
sectorNum %= SECTORS_PER_BANK;
SetReadFlash1(readFlash1Buffer);
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | gFlash->wait[0];
gFlashNumRemainingBytes = gFlash->sector.size;
dest = FLASH_BASE + (sectorNum << gFlash->sector.shift);
while (gFlashNumRemainingBytes > 0)
{
result = ProgramByte(src, dest);
if (result != 0)
break;
gFlashNumRemainingBytes--;
src++;
dest++;
}
return result;
}

View File

@ -0,0 +1,752 @@
#include "gba/gba.h"
#include "gba/flash_internal.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;
}

View File

@ -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();
}

346
berry_fix/payload/src/rtc.c Normal file
View File

@ -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);
}
}
}

View File

@ -0,0 +1,432 @@
// Ruby/Sapphire/Emerald cartridges contain a Seiko Instruments Inc. (SII)
// S-3511A real-time clock (RTC). This library ("SIIRTC_V001") is for
// communicating with the RTC.
#include "gba/gba.h"
#include "siirtc.h"
#define STATUS_INTFE 0x02 // frequency interrupt enable
#define STATUS_INTME 0x08 // per-minute interrupt enable
#define STATUS_INTAE 0x20 // alarm interrupt enable
#define STATUS_24HOUR 0x40 // 0: 12-hour mode, 1: 24-hour mode
#define STATUS_POWER 0x80 // power on or power failure occurred
#define TEST_MODE 0x80 // flag in the "second" byte
#define ALARM_AM 0x00
#define ALARM_PM 0x80
#define OFFSET_YEAR offsetof(struct SiiRtcInfo, year)
#define OFFSET_MONTH offsetof(struct SiiRtcInfo, month)
#define OFFSET_DAY offsetof(struct SiiRtcInfo, day)
#define OFFSET_DAY_OF_WEEK offsetof(struct SiiRtcInfo, dayOfWeek)
#define OFFSET_HOUR offsetof(struct SiiRtcInfo, hour)
#define OFFSET_MINUTE offsetof(struct SiiRtcInfo, minute)
#define OFFSET_SECOND offsetof(struct SiiRtcInfo, second)
#define OFFSET_STATUS offsetof(struct SiiRtcInfo, status)
#define OFFSET_ALARM_HOUR offsetof(struct SiiRtcInfo, alarmHour)
#define OFFSET_ALARM_MINUTE offsetof(struct SiiRtcInfo, alarmMinute)
#define INFO_BUF(info, index) (*((u8 *)(info) + (index)))
#define DATETIME_BUF(info, index) INFO_BUF(info, OFFSET_YEAR + index)
#define DATETIME_BUF_LEN (OFFSET_SECOND - OFFSET_YEAR + 1)
#define TIME_BUF(info, index) INFO_BUF(info, OFFSET_HOUR + index)
#define TIME_BUF_LEN (OFFSET_SECOND - OFFSET_HOUR + 1)
#define WR 0 // command for writing data
#define RD 1 // command for reading data
#define CMD(n) (0x60 | (n << 1))
#define CMD_RESET CMD(0)
#define CMD_STATUS CMD(1)
#define CMD_DATETIME CMD(2)
#define CMD_TIME CMD(3)
#define CMD_ALARM CMD(4)
#define GPIO_PORT_DATA (*(vu16 *)0x80000C4)
#define GPIO_PORT_DIRECTION (*(vu16 *)0x80000C6)
#define GPIO_PORT_READ_ENABLE (*(vu16 *)0x80000C8)
extern vu16 GPIOPortDirection;
static u16 sDummy; // unused variable
static bool8 sLocked;
static int WriteCommand(u8 value);
static int WriteData(u8 value);
static u8 ReadData();
static void EnableGpioPortRead();
static void DisableGpioPortRead();
static const char AgbLibRtcVersion[] = "SIIRTC_V001";
void SiiRtcUnprotect()
{
EnableGpioPortRead();
sLocked = FALSE;
}
void SiiRtcProtect()
{
DisableGpioPortRead();
sLocked = TRUE;
}
u8 SiiRtcProbe()
{
u8 errorCode;
struct SiiRtcInfo rtc;
if (!SiiRtcGetStatus(&rtc))
return 0;
errorCode = 0;
if ((rtc.status & (SIIRTCINFO_POWER | SIIRTCINFO_24HOUR)) == SIIRTCINFO_POWER
|| (rtc.status & (SIIRTCINFO_POWER | SIIRTCINFO_24HOUR)) == 0)
{
// The RTC is in 12-hour mode. Reset it and switch to 24-hour mode.
// Note that the conditions are redundant and equivalent to simply
// "(rtc.status & SIIRTCINFO_24HOUR) == 0". It's possible that this
// was also intended to handle resetting the clock after power failure
// but a mistake was made.
if (!SiiRtcReset())
return 0;
errorCode++;
}
SiiRtcGetTime(&rtc);
if (rtc.second & TEST_MODE)
{
// The RTC is in test mode. Reset it to leave test mode.
if (!SiiRtcReset())
return (errorCode << 4) & 0xF0;
errorCode++;
}
return (errorCode << 4) | 1;
}
bool8 SiiRtcReset()
{
u8 result;
struct SiiRtcInfo rtc;
if (sLocked == TRUE)
return FALSE;
sLocked = TRUE;
GPIO_PORT_DATA = 1;
GPIO_PORT_DATA = 5;
GPIO_PORT_DIRECTION = 7;
WriteCommand(CMD_RESET | WR);
GPIO_PORT_DATA = 1;
GPIO_PORT_DATA = 1;
sLocked = FALSE;
rtc.status = SIIRTCINFO_24HOUR;
result = SiiRtcSetStatus(&rtc);
return result;
}
bool8 SiiRtcGetStatus(struct SiiRtcInfo *rtc)
{
u8 statusData;
if (sLocked == TRUE)
return FALSE;
sLocked = TRUE;
GPIO_PORT_DATA = 1;
GPIO_PORT_DATA = 5;
GPIO_PORT_DIRECTION = 7;
WriteCommand(CMD_STATUS | RD);
GPIO_PORT_DIRECTION = 5;
statusData = ReadData();
rtc->status = (statusData & (STATUS_POWER | STATUS_24HOUR))
| ((statusData & STATUS_INTAE) >> 3)
| ((statusData & STATUS_INTME) >> 2)
| ((statusData & STATUS_INTFE) >> 1);
GPIO_PORT_DATA = 1;
GPIO_PORT_DATA = 1;
sLocked = FALSE;
return TRUE;
}
bool8 SiiRtcSetStatus(struct SiiRtcInfo *rtc)
{
u8 statusData;
if (sLocked == TRUE)
return FALSE;
sLocked = TRUE;
GPIO_PORT_DATA = 1;
GPIO_PORT_DATA = 5;
statusData = STATUS_24HOUR
| ((rtc->status & SIIRTCINFO_INTAE) << 3)
| ((rtc->status & SIIRTCINFO_INTME) << 2)
| ((rtc->status & SIIRTCINFO_INTFE) << 1);
GPIO_PORT_DIRECTION = 7;
WriteCommand(CMD_STATUS | WR);
WriteData(statusData);
GPIO_PORT_DATA = 1;
GPIO_PORT_DATA = 1;
sLocked = FALSE;
return TRUE;
}
bool8 SiiRtcGetDateTime(struct SiiRtcInfo *rtc)
{
u8 i;
if (sLocked == TRUE)
return FALSE;
sLocked = TRUE;
GPIO_PORT_DATA = 1;
GPIO_PORT_DATA = 5;
GPIO_PORT_DIRECTION = 7;
WriteCommand(CMD_DATETIME | RD);
GPIO_PORT_DIRECTION = 5;
for (i = 0; i < DATETIME_BUF_LEN; i++)
DATETIME_BUF(rtc, i) = ReadData();
INFO_BUF(rtc, OFFSET_HOUR) &= 0x7F;
GPIO_PORT_DATA = 1;
GPIO_PORT_DATA = 1;
sLocked = FALSE;
return TRUE;
}
bool8 SiiRtcSetDateTime(struct SiiRtcInfo *rtc)
{
u8 i;
if (sLocked == TRUE)
return FALSE;
sLocked = TRUE;
GPIO_PORT_DATA = 1;
GPIO_PORT_DATA = 5;
GPIO_PORT_DIRECTION = 7;
WriteCommand(CMD_DATETIME | WR);
for (i = 0; i < DATETIME_BUF_LEN; i++)
WriteData(DATETIME_BUF(rtc, i));
GPIO_PORT_DATA = 1;
GPIO_PORT_DATA = 1;
sLocked = FALSE;
return TRUE;
}
bool8 SiiRtcGetTime(struct SiiRtcInfo *rtc)
{
u8 i;
if (sLocked == TRUE)
return FALSE;
sLocked = TRUE;
GPIO_PORT_DATA = 1;
GPIO_PORT_DATA = 5;
GPIO_PORT_DIRECTION = 7;
WriteCommand(CMD_TIME | RD);
GPIO_PORT_DIRECTION = 5;
for (i = 0; i < TIME_BUF_LEN; i++)
TIME_BUF(rtc, i) = ReadData();
INFO_BUF(rtc, OFFSET_HOUR) &= 0x7F;
GPIO_PORT_DATA = 1;
GPIO_PORT_DATA = 1;
sLocked = FALSE;
return TRUE;
}
bool8 SiiRtcSetTime(struct SiiRtcInfo *rtc)
{
u8 i;
if (sLocked == TRUE)
return FALSE;
sLocked = TRUE;
GPIO_PORT_DATA = 1;
GPIO_PORT_DATA = 5;
GPIO_PORT_DIRECTION = 7;
WriteCommand(CMD_TIME | WR);
for (i = 0; i < TIME_BUF_LEN; i++)
WriteData(TIME_BUF(rtc, i));
GPIO_PORT_DATA = 1;
GPIO_PORT_DATA = 1;
sLocked = FALSE;
return TRUE;
}
bool8 SiiRtcSetAlarm(struct SiiRtcInfo *rtc)
{
u8 i;
u8 alarmData[2];
if (sLocked == TRUE)
return FALSE;
sLocked = TRUE;
// Decode BCD.
alarmData[0] = (rtc->alarmHour & 0xF) + 10 * ((rtc->alarmHour >> 4) & 0xF);
// The AM/PM flag must be set correctly even in 24-hour mode.
if (alarmData[0] < 12)
alarmData[0] = rtc->alarmHour | ALARM_AM;
else
alarmData[0] = rtc->alarmHour | ALARM_PM;
alarmData[1] = rtc->alarmMinute;
GPIO_PORT_DATA = 1;
GPIO_PORT_DATA = 5;
GPIOPortDirection = 7; // Why is this the only instance that uses a symbol?
WriteCommand(CMD_ALARM | WR);
for (i = 0; i < 2; i++)
WriteData(alarmData[i]);
GPIO_PORT_DATA = 1;
GPIO_PORT_DATA = 1;
sLocked = FALSE;
return TRUE;
}
static int WriteCommand(u8 value)
{
u8 i;
u8 temp;
for (i = 0; i < 8; i++)
{
temp = ((value >> (7 - i)) & 1);
GPIO_PORT_DATA = (temp << 1) | 4;
GPIO_PORT_DATA = (temp << 1) | 4;
GPIO_PORT_DATA = (temp << 1) | 4;
GPIO_PORT_DATA = (temp << 1) | 5;
}
// control reaches end of non-void function
}
static int WriteData(u8 value)
{
u8 i;
u8 temp;
for (i = 0; i < 8; i++)
{
temp = ((value >> i) & 1);
GPIO_PORT_DATA = (temp << 1) | 4;
GPIO_PORT_DATA = (temp << 1) | 4;
GPIO_PORT_DATA = (temp << 1) | 4;
GPIO_PORT_DATA = (temp << 1) | 5;
}
// control reaches end of non-void function
}
static u8 ReadData()
{
u8 i;
u8 temp;
u8 value;
for (i = 0; i < 8; i++)
{
GPIO_PORT_DATA = 4;
GPIO_PORT_DATA = 4;
GPIO_PORT_DATA = 4;
GPIO_PORT_DATA = 4;
GPIO_PORT_DATA = 4;
GPIO_PORT_DATA = 5;
temp = ((GPIO_PORT_DATA & 2) >> 1);
value = (value >> 1) | (temp << 7); // UB: accessing uninitialized var
}
return value;
}
static void EnableGpioPortRead()
{
GPIO_PORT_READ_ENABLE = 1;
}
static void DisableGpioPortRead()
{
GPIO_PORT_READ_ENABLE = 0;
}

View File

@ -0,0 +1,5 @@
.include "src/main.o"
.include "src/rtc.o"
.include "src/flash.o"
.include "src/agb_flash.o"
.include "src/siirtc.o"

View File

@ -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 "agb_flash.o"

View File

@ -0,0 +1,3 @@
.include "src/main.o"
.include "src/rtc.o"
.include "src/flash.o"

1
berry_fix/rom.sha1 Normal file
View File

@ -0,0 +1 @@
2eb0a94a913bebfb4cb59ceb57f3f965da55ef6d berry_fix.gba