mirror of
https://github.com/jiangzhengwenjz/katam.git
synced 2024-11-23 05:00:01 +00:00
decompile libraries (#6)
This commit is contained in:
parent
cbd9351e32
commit
cac5bd8be6
2
.gitignore
vendored
2
.gitignore
vendored
@ -48,7 +48,7 @@ tools/agbcc
|
||||
tools/binutils
|
||||
types_*.taghl
|
||||
*.zip
|
||||
!.travis/calcrom/calcrom.pl
|
||||
!calcrom.pl
|
||||
!sound/programmable_wave_samples/*.pcm
|
||||
_Deparsed_XSubs.pm
|
||||
*.py
|
||||
|
28
INSTALL.md
28
INSTALL.md
@ -1,3 +1,5 @@
|
||||
First, you must put a Kirby & the Amazing Mirror (U) ROM (with SHA1: `274b102b6d940f46861a92b4e65f89a51815c12c`) in the root directory of the repository and name it `baserom.gba`.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
| Linux | macOS | Windows 10 (build 18917+) | Windows 10 (1709+) | Windows 8, 8.1, and 10 (1507, 1511, 1607, 1703)
|
||||
@ -15,18 +17,24 @@ Make sure that the `build-essential`, `git`, and `libpng-dev` packages are insta
|
||||
|
||||
In the case of Cygwin, [include](https://cygwin.com/cygwin-ug-net/setup-net.html#setup-packages) the `make`, `git`, `gcc-core`, `gcc-g++`, and `libpng-devel` packages.
|
||||
|
||||
Install the **devkitARM** toolchain of [devkitPro](https://devkitpro.org/wiki/Getting_Started) and add its environment variables. For Windows versions without the Linux subsystem, the devkitPro [graphical installer](https://github.com/devkitPro/installer/releases) includes a preconfigured MSYS2 environment, thus the steps below are not required.
|
||||
|
||||
sudo (dkp-)pacman -S gba-dev
|
||||
export DEVKITPRO=/opt/devkitpro
|
||||
echo "export DEVKITPRO=$DEVKITPRO" >> ~/.bashrc
|
||||
export DEVKITARM=$DEVKITPRO/devkitARM
|
||||
echo "export DEVKITARM=$DEVKITARM" >> ~/.bashrc
|
||||
|
||||
## Installation
|
||||
|
||||
To set up the repository:
|
||||
|
||||
git clone https://github.com/jiangzhengwenjz/kirbyamazingmirror
|
||||
git clone https://github.com/luckytyphlosion/agbcc -b new_layout_with_libs
|
||||
git clone https://github.com/jiangzhengwenjz/agbcc -b new_newlib_pret
|
||||
|
||||
cd ./agbcc
|
||||
make
|
||||
make install prefix=../kirbyamazingmirror
|
||||
make install-sdk prefix=../kirbyamazingmirror
|
||||
sh build.sh
|
||||
sh install.sh ../kirbyamazingmirror
|
||||
|
||||
cd ../kirbyamazingmirror
|
||||
|
||||
@ -43,3 +51,15 @@ If only `.c` or `.s` files were changed, turn off the dependency scanning tempor
|
||||
make -j$(nproc) NODEP=1
|
||||
|
||||
**Note:** If the build command is not recognized on Linux, including the Linux environment used within Windows, run `nproc` and replace `$(nproc)` with the returned value (e.g.: `make -j4`). Because `nproc` is not available on macOS, the alternative is `sysctl -n hw.ncpu`.
|
||||
|
||||
### Note for Mac users
|
||||
|
||||
The BSD make that comes with Mac XCode can be buggy, so obtain GNU make and sed using [Homebrew](https://brew.sh):
|
||||
|
||||
brew install make gnu-sed
|
||||
|
||||
When compiling agbcc, substitute the `build.sh` line for
|
||||
|
||||
gsed 's/^make/gmake/g' build.sh | sh
|
||||
|
||||
Finally, use `gmake` instead of `make` to compile the ROM(s).
|
||||
|
18
Makefile
18
Makefile
@ -1,9 +1,9 @@
|
||||
include $(DEVKITARM)/base_tools
|
||||
|
||||
COMPARE ?= 0
|
||||
|
||||
AS := tools/binutils/bin/arm-none-eabi-as
|
||||
CPP := $(CC) -E
|
||||
LD := tools/binutils/bin/arm-none-eabi-ld
|
||||
OBJCOPY := tools/binutils/bin/arm-none-eabi-objcopy
|
||||
LD := $(DEVKITARM)/bin/arm-none-eabi-ld
|
||||
|
||||
GAME_VERSION := AMAZINGMIRROR
|
||||
REVISION := 0
|
||||
@ -48,7 +48,7 @@ CPPFLAGS := -I tools/agbcc -I tools/agbcc/include -iquote include -nostdinc -und
|
||||
|
||||
LDFLAGS = -Map ../../$(MAP)
|
||||
|
||||
LIB := #-L ../../tools/agbcc/lib -lgcc -lc
|
||||
LIB := -L ../../tools/agbcc/lib -lgcc -lc
|
||||
|
||||
SHA1 := $(shell { command -v sha1sum || command -v shasum; } 2>/dev/null) -c
|
||||
GFX := tools/gbagfx/gbagfx
|
||||
@ -157,6 +157,12 @@ sound/%.bin: sound/%.aif ; $(AIF) $< $@
|
||||
sound/songs/%.s: sound/songs/%.mid
|
||||
cd $(@D) && ../../$(MID) $(<F)
|
||||
|
||||
$(C_BUILDDIR)/m4a.o: CC1 := tools/agbcc/bin/old_agbcc
|
||||
$(C_BUILDDIR)/powf_error_handler.o: CC1 := tools/agbcc/bin/old_agbcc
|
||||
$(C_BUILDDIR)/powf_error_handler.o: override CFLAGS := -Wimplicit -Wparentheses -Werror -O2 -fhex-asm
|
||||
$(C_BUILDDIR)/agb_sram.o: CFLAGS := -mthumb-interwork -Wimplicit -Wparentheses -Werror -O1
|
||||
$(C_BUILDDIR)/agb_sram.o: CC1 := tools/agbcc/bin/old_agbcc
|
||||
|
||||
ifeq ($(NODEP),1)
|
||||
$(C_BUILDDIR)/%.o: c_dep :=
|
||||
else
|
||||
@ -170,7 +176,7 @@ 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
|
||||
@echo -e "\t.text\n\t.align\t2, 0\n" >> $(C_BUILDDIR)/$*.s
|
||||
@echo -e "\t.text\n\t.align\t2, 0 @ Don't pad with nop\n" >> $(C_BUILDDIR)/$*.s
|
||||
$(AS) $(ASFLAGS) -o $@ $(C_BUILDDIR)/$*.s
|
||||
|
||||
ifeq ($(NODEP),1)
|
||||
@ -195,7 +201,7 @@ $(SONG_BUILDDIR)/%.o: $(SONG_SUBDIR)/%.s
|
||||
$(AS) $(ASFLAGS) -I sound -o $@ $<
|
||||
|
||||
$(ELF): $(OBJS) linker.ld
|
||||
cd $(OBJ_DIR) && ../../$(LD) $(LDFLAGS) -T ../../linker.ld -o ../../$@ $(LIB)
|
||||
cd $(OBJ_DIR) && $(LD) $(LDFLAGS) -T ../../linker.ld -o ../../$@ $(LIB)
|
||||
$(FIX) $@ -t"$(TITLE)" -c$(GAME_CODE) -m$(MAKER_CODE) -r$(REVISION) --silent
|
||||
|
||||
$(ROM): $(ELF)
|
||||
|
227
asm/agb_flash.s
227
asm/agb_flash.s
@ -1,227 +0,0 @@
|
||||
.include "asm/macros.inc"
|
||||
.include "constants/constants.inc"
|
||||
|
||||
.syntax unified
|
||||
|
||||
.text
|
||||
|
||||
thumb_func_start sub_08159158
|
||||
sub_08159158: @ 0x08159158
|
||||
push {r4, lr}
|
||||
adds r4, r0, #0
|
||||
subs r3, r2, #1
|
||||
cmp r2, #0
|
||||
beq _08159174
|
||||
movs r2, #1
|
||||
rsbs r2, r2, #0
|
||||
_08159166:
|
||||
ldrb r0, [r4]
|
||||
strb r0, [r1]
|
||||
adds r4, #1
|
||||
adds r1, #1
|
||||
subs r3, #1
|
||||
cmp r3, r2
|
||||
bne _08159166
|
||||
_08159174:
|
||||
pop {r4}
|
||||
pop {r0}
|
||||
bx r0
|
||||
.align 2, 0
|
||||
|
||||
thumb_func_start sub_0815917C
|
||||
sub_0815917C: @ 0x0815917C
|
||||
push {r4, r5, r6, lr}
|
||||
sub sp, #0x80
|
||||
adds r4, r0, #0
|
||||
adds r5, r1, #0
|
||||
adds r6, r2, #0
|
||||
ldr r2, _081591A8 @ =0x04000204
|
||||
ldrh r0, [r2]
|
||||
ldr r1, _081591AC @ =0x0000FFFC
|
||||
ands r0, r1
|
||||
movs r1, #3
|
||||
orrs r0, r1
|
||||
strh r0, [r2]
|
||||
ldr r3, _081591B0 @ =sub_08159158
|
||||
movs r0, #1
|
||||
bics r3, r0
|
||||
mov r2, sp
|
||||
ldr r0, _081591B4 @ =sub_0815917C
|
||||
ldr r1, _081591B0 @ =sub_08159158
|
||||
subs r0, r0, r1
|
||||
lsls r0, r0, #0xf
|
||||
b _081591C4
|
||||
.align 2, 0
|
||||
_081591A8: .4byte 0x04000204
|
||||
_081591AC: .4byte 0x0000FFFC
|
||||
_081591B0: .4byte sub_08159158
|
||||
_081591B4: .4byte sub_0815917C
|
||||
_081591B8:
|
||||
ldrh r0, [r3]
|
||||
strh r0, [r2]
|
||||
adds r3, #2
|
||||
adds r2, #2
|
||||
subs r0, r1, #1
|
||||
lsls r0, r0, #0x10
|
||||
_081591C4:
|
||||
lsrs r1, r0, #0x10
|
||||
cmp r1, #0
|
||||
bne _081591B8
|
||||
mov r3, sp
|
||||
adds r3, #1
|
||||
adds r0, r4, #0
|
||||
adds r1, r5, #0
|
||||
adds r2, r6, #0
|
||||
bl _call_via_r3
|
||||
add sp, #0x80
|
||||
pop {r4, r5, r6}
|
||||
pop {r0}
|
||||
bx r0
|
||||
|
||||
thumb_func_start sub_081591E0
|
||||
sub_081591E0: @ 0x081591E0
|
||||
push {r4, r5, lr}
|
||||
adds r5, r0, #0
|
||||
adds r4, r1, #0
|
||||
adds r3, r2, #0
|
||||
ldr r2, _08159218 @ =0x04000204
|
||||
ldrh r0, [r2]
|
||||
ldr r1, _0815921C @ =0x0000FFFC
|
||||
ands r0, r1
|
||||
movs r1, #3
|
||||
orrs r0, r1
|
||||
strh r0, [r2]
|
||||
subs r3, #1
|
||||
movs r0, #1
|
||||
rsbs r0, r0, #0
|
||||
cmp r3, r0
|
||||
beq _08159210
|
||||
adds r1, r0, #0
|
||||
_08159202:
|
||||
ldrb r0, [r5]
|
||||
strb r0, [r4]
|
||||
adds r5, #1
|
||||
adds r4, #1
|
||||
subs r3, #1
|
||||
cmp r3, r1
|
||||
bne _08159202
|
||||
_08159210:
|
||||
pop {r4, r5}
|
||||
pop {r0}
|
||||
bx r0
|
||||
.align 2, 0
|
||||
_08159218: .4byte 0x04000204
|
||||
_0815921C: .4byte 0x0000FFFC
|
||||
|
||||
thumb_func_start sub_08159220
|
||||
sub_08159220: @ 0x08159220
|
||||
push {r4, r5, lr}
|
||||
adds r5, r0, #0
|
||||
adds r3, r1, #0
|
||||
subs r4, r2, #1
|
||||
cmp r2, #0
|
||||
beq _08159246
|
||||
movs r2, #1
|
||||
rsbs r2, r2, #0
|
||||
_08159230:
|
||||
ldrb r1, [r3]
|
||||
ldrb r0, [r5]
|
||||
adds r5, #1
|
||||
adds r3, #1
|
||||
cmp r1, r0
|
||||
beq _08159240
|
||||
subs r0, r3, #1
|
||||
b _08159248
|
||||
_08159240:
|
||||
subs r4, #1
|
||||
cmp r4, r2
|
||||
bne _08159230
|
||||
_08159246:
|
||||
movs r0, #0
|
||||
_08159248:
|
||||
pop {r4, r5}
|
||||
pop {r1}
|
||||
bx r1
|
||||
.align 2, 0
|
||||
|
||||
thumb_func_start sub_08159250
|
||||
sub_08159250: @ 0x08159250
|
||||
push {r4, r5, r6, lr}
|
||||
sub sp, #0xc0
|
||||
adds r4, r0, #0
|
||||
adds r5, r1, #0
|
||||
adds r6, r2, #0
|
||||
ldr r2, _0815927C @ =0x04000204
|
||||
ldrh r0, [r2]
|
||||
ldr r1, _08159280 @ =0x0000FFFC
|
||||
ands r0, r1
|
||||
movs r1, #3
|
||||
orrs r0, r1
|
||||
strh r0, [r2]
|
||||
ldr r3, _08159284 @ =sub_08159220
|
||||
movs r0, #1
|
||||
bics r3, r0
|
||||
mov r2, sp
|
||||
ldr r0, _08159288 @ =sub_08159250
|
||||
ldr r1, _08159284 @ =sub_08159220
|
||||
subs r0, r0, r1
|
||||
lsls r0, r0, #0xf
|
||||
b _08159298
|
||||
.align 2, 0
|
||||
_0815927C: .4byte 0x04000204
|
||||
_08159280: .4byte 0x0000FFFC
|
||||
_08159284: .4byte sub_08159220
|
||||
_08159288: .4byte sub_08159250
|
||||
_0815928C:
|
||||
ldrh r0, [r3]
|
||||
strh r0, [r2]
|
||||
adds r3, #2
|
||||
adds r2, #2
|
||||
subs r0, r1, #1
|
||||
lsls r0, r0, #0x10
|
||||
_08159298:
|
||||
lsrs r1, r0, #0x10
|
||||
cmp r1, #0
|
||||
bne _0815928C
|
||||
mov r3, sp
|
||||
adds r3, #1
|
||||
adds r0, r4, #0
|
||||
adds r1, r5, #0
|
||||
adds r2, r6, #0
|
||||
bl _call_via_r3
|
||||
add sp, #0xc0
|
||||
pop {r4, r5, r6}
|
||||
pop {r1}
|
||||
bx r1
|
||||
|
||||
thumb_func_start sub_081592B4
|
||||
sub_081592B4: @ 0x081592B4
|
||||
push {r4, r5, r6, r7, lr}
|
||||
adds r6, r0, #0
|
||||
adds r5, r1, #0
|
||||
adds r4, r2, #0
|
||||
movs r7, #0
|
||||
b _081592C6
|
||||
_081592C0:
|
||||
adds r0, r7, #1
|
||||
lsls r0, r0, #0x18
|
||||
lsrs r7, r0, #0x18
|
||||
_081592C6:
|
||||
cmp r7, #2
|
||||
bhi _081592E4
|
||||
adds r0, r6, #0
|
||||
adds r1, r5, #0
|
||||
adds r2, r4, #0
|
||||
bl sub_081591E0
|
||||
adds r0, r6, #0
|
||||
adds r1, r5, #0
|
||||
adds r2, r4, #0
|
||||
bl sub_08159250
|
||||
adds r3, r0, #0
|
||||
cmp r3, #0
|
||||
bne _081592C0
|
||||
_081592E4:
|
||||
adds r0, r3, #0
|
||||
pop {r4, r5, r6, r7}
|
||||
pop {r1}
|
||||
bx r1
|
60
asm/code.s
60
asm/code.s
@ -22388,7 +22388,7 @@ _0800AA6C:
|
||||
mov r0, sp
|
||||
adds r1, r5, #0
|
||||
movs r2, #8
|
||||
bl sub_081592B4
|
||||
bl WriteSramEx
|
||||
cmp r0, #0
|
||||
bne _0800AA58
|
||||
adds r5, #8
|
||||
@ -22418,7 +22418,7 @@ _0800AA9E:
|
||||
_0800AAB0:
|
||||
adds r0, r1, #0
|
||||
adds r1, r5, #0
|
||||
bl sub_081592B4
|
||||
bl WriteSramEx
|
||||
cmp r0, #0
|
||||
bne _0800AA58
|
||||
ldr r0, [r4, #4]
|
||||
@ -22515,7 +22515,7 @@ _0800AB58:
|
||||
adds r0, r5, #0
|
||||
mov r1, sp
|
||||
movs r2, #8
|
||||
bl sub_0815917C
|
||||
bl ReadSram
|
||||
adds r5, #8
|
||||
cmp r7, #0
|
||||
beq _0800AB72
|
||||
@ -22542,7 +22542,7 @@ _0800AB7E:
|
||||
adds r6, r0, #0
|
||||
_0800AB90:
|
||||
adds r0, r5, #0
|
||||
bl sub_0815917C
|
||||
bl ReadSram
|
||||
ldr r0, [r4, #4]
|
||||
adds r5, r5, r0
|
||||
adds r4, #8
|
||||
@ -55836,14 +55836,14 @@ _0801A66A:
|
||||
ldr r6, _0801A6B8 @ =gUnk_03002490
|
||||
ldrb r2, [r2]
|
||||
adds r1, r6, #0
|
||||
bl sub_08157308
|
||||
bl MultiSioMain
|
||||
str r0, [r4]
|
||||
adds r4, r5, #0
|
||||
adds r4, #0xa4
|
||||
ldr r0, [r4]
|
||||
cmp r0, #0
|
||||
bne _0801A690
|
||||
bl sub_081576A0
|
||||
bl MultiSioStart
|
||||
movs r0, #1
|
||||
str r0, [r4]
|
||||
_0801A690:
|
||||
@ -55906,12 +55906,12 @@ _0801A6E6:
|
||||
adds r0, r0, r2
|
||||
ldr r4, [r0]
|
||||
_0801A6FC:
|
||||
bl sub_081576BC
|
||||
bl MultiSioStop
|
||||
ldr r2, _0801A730 @ =0x04000208
|
||||
movs r0, #0
|
||||
strh r0, [r2]
|
||||
ldr r1, _0801A734 @ =gUnk_030017B0
|
||||
ldr r0, _0801A738 @ =sub_08158038
|
||||
ldr r1, _0801A734 @ =gIntrTable
|
||||
ldr r0, _0801A738 @ =Sio32MultiLoadIntr
|
||||
str r0, [r1]
|
||||
movs r0, #1
|
||||
strh r0, [r2]
|
||||
@ -55920,7 +55920,7 @@ _0801A6FC:
|
||||
movs r1, #0x80
|
||||
ands r0, r1
|
||||
adds r1, r4, #0
|
||||
bl sub_08158100
|
||||
bl Sio32MultiLoadInit
|
||||
ldr r0, _0801A740 @ =sub_0801A8C4
|
||||
str r0, [r5, #0x14]
|
||||
pop {r4, r5}
|
||||
@ -55930,8 +55930,8 @@ _0801A6FC:
|
||||
_0801A728: .4byte gUnk_082DE308
|
||||
_0801A72C: .4byte gUnk_08D60A80
|
||||
_0801A730: .4byte 0x04000208
|
||||
_0801A734: .4byte gUnk_030017B0
|
||||
_0801A738: .4byte sub_08158038
|
||||
_0801A734: .4byte gIntrTable
|
||||
_0801A738: .4byte Sio32MultiLoadIntr
|
||||
_0801A73C: .4byte gUnk_03002554
|
||||
_0801A740: .4byte sub_0801A8C4
|
||||
|
||||
@ -56126,7 +56126,7 @@ sub_0801A884: @ 0x0801A884
|
||||
bl sub_0801E754
|
||||
adds r0, r4, #0
|
||||
bl sub_0801A908
|
||||
bl sub_081576A0
|
||||
bl MultiSioStart
|
||||
ldr r0, _0801A8C0 @ =sub_0801A618
|
||||
str r0, [r4, #0x14]
|
||||
_0801A8B4:
|
||||
@ -56145,7 +56145,7 @@ sub_0801A8C4: @ 0x0801A8C4
|
||||
movs r0, #0
|
||||
str r0, [sp]
|
||||
mov r0, sp
|
||||
bl sub_08157E54
|
||||
bl Sio32MultiLoadMain
|
||||
cmp r0, #0
|
||||
beq _0801A8DC
|
||||
ldr r0, _0801A8E4 @ =sub_0801AA40
|
||||
@ -56181,8 +56181,8 @@ sub_0801A908: @ 0x0801A908
|
||||
ldr r2, _0801A940 @ =0x04000208
|
||||
movs r6, #0
|
||||
strh r6, [r2]
|
||||
ldr r1, _0801A944 @ =gUnk_030017B0
|
||||
ldr r0, _0801A948 @ =gUnk_030068E0
|
||||
ldr r1, _0801A944 @ =gIntrTable
|
||||
ldr r0, _0801A948 @ =gMultiSioIntrFuncBuf
|
||||
str r0, [r1]
|
||||
movs r0, #1
|
||||
strh r0, [r2]
|
||||
@ -56192,7 +56192,7 @@ sub_0801A908: @ 0x0801A908
|
||||
lsls r1, r1, #4
|
||||
ands r0, r1
|
||||
lsrs r0, r0, #8
|
||||
bl sub_08157210
|
||||
bl MultiSioInit
|
||||
adds r0, r4, #0
|
||||
adds r0, #0xa8
|
||||
movs r1, #0
|
||||
@ -56205,8 +56205,8 @@ sub_0801A908: @ 0x0801A908
|
||||
bx r0
|
||||
.align 2, 0
|
||||
_0801A940: .4byte 0x04000208
|
||||
_0801A944: .4byte gUnk_030017B0
|
||||
_0801A948: .4byte gUnk_030068E0
|
||||
_0801A944: .4byte gIntrTable
|
||||
_0801A948: .4byte gMultiSioIntrFuncBuf
|
||||
_0801A94C: .4byte gUnk_03002554
|
||||
|
||||
thumb_func_start sub_0801A950
|
||||
@ -101110,7 +101110,7 @@ sub_0803024C: @ 0x0803024C
|
||||
ldr r0, _080302D4 @ =0x0400012A
|
||||
strh r3, [r0]
|
||||
ldr r2, _080302D8 @ =gUnk_03000470
|
||||
ldr r1, _080302DC @ =gUnk_030017B0
|
||||
ldr r1, _080302DC @ =gIntrTable
|
||||
ldr r0, [r1, #0x1c]
|
||||
str r0, [r2]
|
||||
ldr r2, _080302E0 @ =gUnk_03000484
|
||||
@ -101139,7 +101139,7 @@ _080302CC: .4byte 0x04000128
|
||||
_080302D0: .4byte 0x00004003
|
||||
_080302D4: .4byte 0x0400012A
|
||||
_080302D8: .4byte gUnk_03000470
|
||||
_080302DC: .4byte gUnk_030017B0
|
||||
_080302DC: .4byte gIntrTable
|
||||
_080302E0: .4byte gUnk_03000484
|
||||
_080302E4: .4byte sub_08030898
|
||||
_080302E8: .4byte 0x04000200
|
||||
@ -102251,7 +102251,7 @@ sub_08030B38: @ 0x08030B38
|
||||
ldr r2, _08030B9C @ =0x00008F52
|
||||
adds r0, r2, #0
|
||||
strh r0, [r1]
|
||||
ldr r1, _08030BA0 @ =gUnk_030017B0
|
||||
ldr r1, _08030BA0 @ =gIntrTable
|
||||
ldr r0, _08030BA4 @ =gUnk_03000470
|
||||
ldr r0, [r0]
|
||||
str r0, [r1, #0x1c]
|
||||
@ -102281,7 +102281,7 @@ _08030B90: .4byte 0x04000128
|
||||
_08030B94: .4byte 0x0000BFFF
|
||||
_08030B98: .4byte 0x0400012A
|
||||
_08030B9C: .4byte 0x00008F52
|
||||
_08030BA0: .4byte gUnk_030017B0
|
||||
_08030BA0: .4byte gIntrTable
|
||||
_08030BA4: .4byte gUnk_03000470
|
||||
_08030BA8: .4byte gUnk_03000484
|
||||
_08030BAC: .4byte gUnk_03000490
|
||||
@ -102324,7 +102324,7 @@ sub_08030BB8: @ 0x08030BB8
|
||||
mov r1, r8
|
||||
strb r1, [r0]
|
||||
adds r0, r5, #0
|
||||
bl sub_08157DDC
|
||||
bl MultiBootInit
|
||||
add sp, #4
|
||||
pop {r3, r4}
|
||||
mov r8, r3
|
||||
@ -102429,7 +102429,7 @@ sub_08030C94: @ 0x08030C94
|
||||
adds r1, r4, #0
|
||||
bl CpuSet
|
||||
strh r5, [r4, #4]
|
||||
bl sub_081576A0
|
||||
bl MultiSioStart
|
||||
ldr r0, _08030D0C @ =sub_0803149C
|
||||
str r5, [sp]
|
||||
movs r1, #0x20
|
||||
@ -106963,14 +106963,14 @@ _08032F98:
|
||||
str r4, [r3]
|
||||
strb r4, [r5]
|
||||
movs r0, #0
|
||||
bl sub_08157210
|
||||
bl MultiSioInit
|
||||
bl sub_08031BFC
|
||||
bl m4aMPlayAllStop
|
||||
ldr r0, _08032FFC @ =0x04000208
|
||||
strh r4, [r0]
|
||||
movs r2, #0
|
||||
ldr r4, _08033000 @ =gUnk_030017B0
|
||||
ldr r3, _08033004 @ =gUnk_08D5FD9C
|
||||
ldr r4, _08033000 @ =gIntrTable
|
||||
ldr r3, _08033004 @ =gIntrTableTemplate
|
||||
_08032FB6:
|
||||
lsls r0, r2, #2
|
||||
adds r1, r0, r4
|
||||
@ -107000,8 +107000,8 @@ _08032FF0: .4byte 0x85000014
|
||||
_08032FF4: .4byte gUnk_03002554
|
||||
_08032FF8: .4byte gUnk_03002558
|
||||
_08032FFC: .4byte 0x04000208
|
||||
_08033000: .4byte gUnk_030017B0
|
||||
_08033004: .4byte gUnk_08D5FD9C
|
||||
_08033000: .4byte gIntrTable
|
||||
_08033004: .4byte gIntrTableTemplate
|
||||
|
||||
thumb_func_start sub_08033008
|
||||
sub_08033008: @ 0x08033008
|
||||
|
2489
asm/code_0815158C.s
2489
asm/code_0815158C.s
File diff suppressed because it is too large
Load Diff
9543
asm/code_08152A18.s
Normal file
9543
asm/code_08152A18.s
Normal file
File diff suppressed because it is too large
Load Diff
@ -5,429 +5,6 @@
|
||||
|
||||
.text
|
||||
|
||||
thumb_func_start sub_08157E54
|
||||
sub_08157E54: @ 0x08157E54
|
||||
push {r4, r5, r6, r7, lr}
|
||||
adds r2, r0, #0
|
||||
ldr r0, _08157E70 @ =gUnk_03006C90
|
||||
ldrb r1, [r0, #1]
|
||||
adds r5, r0, #0
|
||||
cmp r1, #4
|
||||
bls _08157E64
|
||||
b _0815802A
|
||||
_08157E64:
|
||||
lsls r0, r1, #2
|
||||
ldr r1, _08157E74 @ =_08157E78
|
||||
adds r0, r0, r1
|
||||
ldr r0, [r0]
|
||||
mov pc, r0
|
||||
.align 2, 0
|
||||
_08157E70: .4byte gUnk_03006C90
|
||||
_08157E74: .4byte _08157E78
|
||||
_08157E78: @ jump table
|
||||
.4byte _08157E8C @ case 0
|
||||
.4byte _08157EA4 @ case 1
|
||||
.4byte _08157F40 @ case 2
|
||||
.4byte _08157FB2 @ case 3
|
||||
.4byte _08158020 @ case 4
|
||||
_08157E8C:
|
||||
ldr r0, [r5]
|
||||
ldr r1, _08157EA0 @ =0x00FF00FF
|
||||
ands r0, r1
|
||||
cmp r0, #0
|
||||
bne _08157E98
|
||||
b _0815802A
|
||||
_08157E98:
|
||||
movs r0, #1
|
||||
strb r0, [r5, #1]
|
||||
b _0815802A
|
||||
.align 2, 0
|
||||
_08157EA0: .4byte 0x00FF00FF
|
||||
_08157EA4:
|
||||
ldrb r0, [r5]
|
||||
cmp r0, #1
|
||||
bne _08157EB4
|
||||
ldrb r0, [r5, #2]
|
||||
cmp r0, #5
|
||||
bhi _08157EB2
|
||||
b _0815802A
|
||||
_08157EB2:
|
||||
b _08157EBE
|
||||
_08157EB4:
|
||||
ldr r1, _08157EF4 @ =0x04000128
|
||||
movs r2, #0x80
|
||||
lsls r2, r2, #5
|
||||
adds r0, r2, #0
|
||||
strh r0, [r1]
|
||||
_08157EBE:
|
||||
ldr r0, _08157EF8 @ =0x04000120
|
||||
movs r6, #0
|
||||
str r6, [r0]
|
||||
ldr r1, _08157EFC @ =0x04000202
|
||||
movs r0, #0xc0
|
||||
strh r0, [r1]
|
||||
ldrb r4, [r5]
|
||||
cmp r4, #1
|
||||
bne _08157F0C
|
||||
ldr r2, _08157EF4 @ =0x04000128
|
||||
ldrh r0, [r2]
|
||||
movs r1, #0x80
|
||||
orrs r0, r1
|
||||
strh r0, [r2]
|
||||
ldr r1, _08157F00 @ =0x0400010C
|
||||
ldr r0, _08157F04 @ =0x00C0F318
|
||||
str r0, [r1]
|
||||
ldr r3, _08157F08 @ =0x04000208
|
||||
strh r6, [r3]
|
||||
adds r2, #0xd8
|
||||
ldrh r0, [r2]
|
||||
movs r1, #0x40
|
||||
orrs r0, r1
|
||||
strh r0, [r2]
|
||||
strh r4, [r3]
|
||||
b _08157F2C
|
||||
.align 2, 0
|
||||
_08157EF4: .4byte 0x04000128
|
||||
_08157EF8: .4byte 0x04000120
|
||||
_08157EFC: .4byte 0x04000202
|
||||
_08157F00: .4byte 0x0400010C
|
||||
_08157F04: .4byte 0x00C0F318
|
||||
_08157F08: .4byte 0x04000208
|
||||
_08157F0C:
|
||||
ldr r2, _08157F38 @ =0x04000128
|
||||
ldrh r0, [r2]
|
||||
movs r3, #0x81
|
||||
lsls r3, r3, #7
|
||||
adds r1, r3, #0
|
||||
orrs r0, r1
|
||||
strh r0, [r2]
|
||||
ldr r3, _08157F3C @ =0x04000208
|
||||
strh r6, [r3]
|
||||
adds r2, #0xd8
|
||||
ldrh r0, [r2]
|
||||
movs r1, #0x80
|
||||
orrs r0, r1
|
||||
strh r0, [r2]
|
||||
movs r0, #1
|
||||
strh r0, [r3]
|
||||
_08157F2C:
|
||||
movs r0, #0
|
||||
strb r0, [r5, #2]
|
||||
movs r0, #2
|
||||
strb r0, [r5, #1]
|
||||
b _0815802A
|
||||
.align 2, 0
|
||||
_08157F38: .4byte 0x04000128
|
||||
_08157F3C: .4byte 0x04000208
|
||||
_08157F40:
|
||||
ldr r6, [r5, #8]
|
||||
adds r4, r6, #0
|
||||
movs r0, #0x80
|
||||
lsls r0, r0, #6
|
||||
cmp r6, r0
|
||||
ble _08157F50
|
||||
adds r4, r0, #0
|
||||
b _08157F56
|
||||
_08157F50:
|
||||
cmp r6, #0
|
||||
bge _08157F56
|
||||
movs r4, #0
|
||||
_08157F56:
|
||||
cmp r2, #0
|
||||
beq _08157F5C
|
||||
str r4, [r2]
|
||||
_08157F5C:
|
||||
ldrb r0, [r5]
|
||||
cmp r0, #1
|
||||
beq _08157F9E
|
||||
ldr r0, [r5, #0x14]
|
||||
cmp r0, r4
|
||||
bge _08157F82
|
||||
adds r3, r5, #0
|
||||
ldr r7, [r5, #4]
|
||||
_08157F6C:
|
||||
ldr r2, [r3, #0x14]
|
||||
lsls r0, r2, #2
|
||||
adds r0, r0, r7
|
||||
ldr r1, [r3, #0x10]
|
||||
ldr r0, [r0]
|
||||
adds r1, r1, r0
|
||||
str r1, [r3, #0x10]
|
||||
adds r2, #1
|
||||
str r2, [r3, #0x14]
|
||||
cmp r2, r4
|
||||
blt _08157F6C
|
||||
_08157F82:
|
||||
movs r0, #0x80
|
||||
lsls r0, r0, #6
|
||||
cmp r6, r0
|
||||
ble _08157FA6
|
||||
ldr r0, [r5, #0xc]
|
||||
ldr r1, [r5, #0x10]
|
||||
adds r0, r0, r1
|
||||
str r0, [r5, #0xc]
|
||||
movs r1, #1
|
||||
rsbs r1, r1, #0
|
||||
cmp r0, r1
|
||||
bne _08157F9E
|
||||
movs r0, #1
|
||||
strb r0, [r5, #3]
|
||||
_08157F9E:
|
||||
movs r0, #0x80
|
||||
lsls r0, r0, #6
|
||||
cmp r6, r0
|
||||
bgt _08157FAC
|
||||
_08157FA6:
|
||||
ldrb r0, [r5, #2]
|
||||
cmp r0, #0x8c
|
||||
bne _0815802A
|
||||
_08157FAC:
|
||||
movs r0, #3
|
||||
strb r0, [r5, #1]
|
||||
b _0815802A
|
||||
_08157FB2:
|
||||
ldr r3, _08158004 @ =0x04000208
|
||||
movs r4, #0
|
||||
strh r4, [r3]
|
||||
ldr r2, _08158008 @ =0x04000200
|
||||
ldrh r1, [r2]
|
||||
ldr r0, _0815800C @ =0x0000FF3F
|
||||
ands r0, r1
|
||||
strh r0, [r2]
|
||||
movs r0, #1
|
||||
strh r0, [r3]
|
||||
ldr r1, _08158010 @ =0x04000128
|
||||
movs r2, #0x80
|
||||
lsls r2, r2, #5
|
||||
adds r0, r2, #0
|
||||
strh r0, [r1]
|
||||
movs r0, #0x80
|
||||
lsls r0, r0, #6
|
||||
str r0, [r1]
|
||||
adds r0, #3
|
||||
str r0, [r1]
|
||||
ldr r2, _08158014 @ =0x04000120
|
||||
movs r0, #0
|
||||
movs r1, #0
|
||||
str r0, [r2]
|
||||
str r1, [r2, #4]
|
||||
ldrb r0, [r5]
|
||||
cmp r0, #0
|
||||
beq _08157FF0
|
||||
ldr r1, _08158018 @ =0x0400010C
|
||||
movs r0, #0
|
||||
str r0, [r1]
|
||||
_08157FF0:
|
||||
ldr r0, _0815801C @ =0x04000202
|
||||
movs r1, #0xc0
|
||||
strh r1, [r0]
|
||||
ldrb r0, [r5]
|
||||
cmp r0, #0
|
||||
beq _08158026
|
||||
strb r4, [r5, #2]
|
||||
movs r0, #4
|
||||
strb r0, [r5, #1]
|
||||
b _0815802A
|
||||
.align 2, 0
|
||||
_08158004: .4byte 0x04000208
|
||||
_08158008: .4byte 0x04000200
|
||||
_0815800C: .4byte 0x0000FF3F
|
||||
_08158010: .4byte 0x04000128
|
||||
_08158014: .4byte 0x04000120
|
||||
_08158018: .4byte 0x0400010C
|
||||
_0815801C: .4byte 0x04000202
|
||||
_08158020:
|
||||
ldrb r0, [r5, #2]
|
||||
cmp r0, #2
|
||||
bls _0815802A
|
||||
_08158026:
|
||||
movs r0, #1
|
||||
b _08158032
|
||||
_0815802A:
|
||||
ldrb r0, [r5, #2]
|
||||
adds r0, #1
|
||||
strb r0, [r5, #2]
|
||||
movs r0, #0
|
||||
_08158032:
|
||||
pop {r4, r5, r6, r7}
|
||||
pop {r1}
|
||||
bx r1
|
||||
|
||||
thumb_func_start sub_08158038
|
||||
sub_08158038: @ 0x08158038
|
||||
push {r4, r5, lr}
|
||||
ldr r2, _0815805C @ =0x04000120
|
||||
ldr r3, [r2]
|
||||
ldr r5, _08158060 @ =gUnk_03006C90
|
||||
ldrb r0, [r5]
|
||||
adds r4, r5, #0
|
||||
cmp r0, #1
|
||||
beq _08158068
|
||||
ldr r0, _08158064 @ =0x04000128
|
||||
ldrh r1, [r0]
|
||||
movs r2, #0x80
|
||||
orrs r1, r2
|
||||
strh r1, [r0]
|
||||
ldr r2, [r4, #8]
|
||||
cmp r2, #0
|
||||
bge _081580B4
|
||||
b _081580A2
|
||||
.align 2, 0
|
||||
_0815805C: .4byte 0x04000120
|
||||
_08158060: .4byte gUnk_03006C90
|
||||
_08158064: .4byte 0x04000128
|
||||
_08158068:
|
||||
ldr r1, _0815807C @ =0x0400010E
|
||||
movs r0, #0
|
||||
strh r0, [r1]
|
||||
ldr r1, [r4, #8]
|
||||
cmp r1, #0
|
||||
bge _08158084
|
||||
ldr r0, _08158080 @ =0xFEFEFEFE
|
||||
str r0, [r2]
|
||||
b _081580CA
|
||||
.align 2, 0
|
||||
_0815807C: .4byte 0x0400010E
|
||||
_08158080: .4byte 0xFEFEFEFE
|
||||
_08158084:
|
||||
ldr r0, _08158098 @ =0x00001FFF
|
||||
cmp r1, r0
|
||||
bgt _0815809C
|
||||
ldr r0, [r4, #4]
|
||||
lsls r1, r1, #2
|
||||
adds r1, r1, r0
|
||||
ldr r0, [r1]
|
||||
str r0, [r2]
|
||||
b _081580CA
|
||||
.align 2, 0
|
||||
_08158098: .4byte 0x00001FFF
|
||||
_0815809C:
|
||||
ldr r0, [r4, #0xc]
|
||||
str r0, [r2]
|
||||
b _081580CA
|
||||
_081580A2:
|
||||
ldr r0, _081580B0 @ =0xFEFEFEFE
|
||||
cmp r3, r0
|
||||
beq _081580CA
|
||||
subs r0, r2, #1
|
||||
str r0, [r5, #8]
|
||||
b _081580CA
|
||||
.align 2, 0
|
||||
_081580B0: .4byte 0xFEFEFEFE
|
||||
_081580B4:
|
||||
ldr r0, _081580C4 @ =0x00001FFF
|
||||
cmp r2, r0
|
||||
bgt _081580C8
|
||||
ldr r1, [r4, #4]
|
||||
lsls r0, r2, #2
|
||||
adds r0, r0, r1
|
||||
str r3, [r0]
|
||||
b _081580CA
|
||||
.align 2, 0
|
||||
_081580C4: .4byte 0x00001FFF
|
||||
_081580C8:
|
||||
str r3, [r4, #0xc]
|
||||
_081580CA:
|
||||
ldr r1, [r4, #8]
|
||||
ldr r0, _081580F4 @ =0x00002002
|
||||
cmp r1, r0
|
||||
bgt _081580EC
|
||||
adds r0, r1, #1
|
||||
str r0, [r4, #8]
|
||||
ldrb r0, [r4]
|
||||
cmp r0, #1
|
||||
bne _081580EC
|
||||
ldr r2, _081580F8 @ =0x04000128
|
||||
ldrh r0, [r2]
|
||||
movs r1, #0x80
|
||||
orrs r0, r1
|
||||
strh r0, [r2]
|
||||
ldr r1, _081580FC @ =0x0400010E
|
||||
movs r0, #0xc0
|
||||
strh r0, [r1]
|
||||
_081580EC:
|
||||
pop {r4, r5}
|
||||
pop {r0}
|
||||
bx r0
|
||||
.align 2, 0
|
||||
_081580F4: .4byte 0x00002002
|
||||
_081580F8: .4byte 0x04000128
|
||||
_081580FC: .4byte 0x0400010E
|
||||
|
||||
thumb_func_start sub_08158100
|
||||
sub_08158100: @ 0x08158100
|
||||
push {r4, r5, r6, r7, lr}
|
||||
mov r7, r8
|
||||
push {r7}
|
||||
sub sp, #4
|
||||
adds r5, r0, #0
|
||||
adds r7, r1, #0
|
||||
movs r6, #0
|
||||
ldr r3, _0815817C @ =0x04000208
|
||||
strh r6, [r3]
|
||||
ldr r2, _08158180 @ =0x04000200
|
||||
ldrh r1, [r2]
|
||||
ldr r0, _08158184 @ =0x0000FF3F
|
||||
ands r0, r1
|
||||
strh r0, [r2]
|
||||
movs r0, #1
|
||||
mov r8, r0
|
||||
strh r0, [r3]
|
||||
str r6, [sp]
|
||||
ldr r4, _08158188 @ =gUnk_03006C90
|
||||
ldr r2, _0815818C @ =0x05000006
|
||||
mov r0, sp
|
||||
adds r1, r4, #0
|
||||
bl CpuSet
|
||||
ldr r1, _08158190 @ =0x04000128
|
||||
ldr r0, _08158194 @ =0x00002003
|
||||
str r0, [r1]
|
||||
str r7, [r4, #4]
|
||||
movs r0, #1
|
||||
rsbs r0, r0, #0
|
||||
str r0, [r4, #8]
|
||||
cmp r5, #0
|
||||
beq _0815816E
|
||||
ldr r0, _08158198 @ =0x0400010C
|
||||
str r6, [r0]
|
||||
mov r2, r8
|
||||
strb r2, [r4]
|
||||
adds r1, r7, #0
|
||||
movs r2, #0x80
|
||||
lsls r2, r2, #6
|
||||
_08158150:
|
||||
ldm r1!, {r0}
|
||||
adds r6, r6, r0
|
||||
subs r2, #1
|
||||
cmp r2, #0
|
||||
bne _08158150
|
||||
mvns r0, r6
|
||||
str r0, [r4, #0xc]
|
||||
ldr r1, _08158190 @ =0x04000128
|
||||
movs r2, #0x80
|
||||
lsls r2, r2, #5
|
||||
adds r0, r2, #0
|
||||
strh r0, [r1]
|
||||
adds r2, #1
|
||||
adds r0, r2, #0
|
||||
strh r0, [r1]
|
||||
_0815816E:
|
||||
add sp, #4
|
||||
pop {r3}
|
||||
mov r8, r3
|
||||
pop {r4, r5, r6, r7}
|
||||
pop {r0}
|
||||
bx r0
|
||||
.align 2, 0
|
||||
_0815817C: .4byte 0x04000208
|
||||
_08158180: .4byte 0x04000200
|
||||
_08158184: .4byte 0x0000FF3F
|
||||
_08158188: .4byte gUnk_03006C90
|
||||
_0815818C: .4byte 0x05000006
|
||||
_08158190: .4byte 0x04000128
|
||||
_08158194: .4byte 0x00002003
|
||||
_08158198: .4byte 0x0400010C
|
||||
|
||||
thumb_func_start sub_0815819C
|
||||
sub_0815819C: @ 0x0815819C
|
||||
ldr r1, _081581A4 @ =gUnk_03006CB0
|
||||
@ -901,30 +478,30 @@ _081584FE:
|
||||
movs r1, #0
|
||||
ldrsh r4, [r7, r1]
|
||||
adds r0, r4, #0
|
||||
bl __floatsidf
|
||||
bl __floatsisf
|
||||
adds r6, r0, #0
|
||||
mov r8, r5
|
||||
cmp r4, #0
|
||||
bge _08158520
|
||||
ldr r1, _08158558 @ =0x47800000
|
||||
bl __adddf3
|
||||
bl __addsf3
|
||||
adds r6, r0, #0
|
||||
_08158520:
|
||||
mov r2, sl
|
||||
movs r0, #0
|
||||
ldrsb r0, [r2, r0]
|
||||
bl __floatsidf
|
||||
bl __floatsisf
|
||||
adds r4, r0, #0
|
||||
ldr r1, _0815855C @ =0x41800000
|
||||
bl __adddf3
|
||||
bl __addsf3
|
||||
ldr r1, _08158560 @ =0x3D800000
|
||||
bl __muldf3
|
||||
bl __mulsf3
|
||||
adds r1, r0, #0
|
||||
adds r0, r6, #0
|
||||
bl __muldf3
|
||||
bl __mulsf3
|
||||
adds r1, r4, #0
|
||||
bl __subdf3
|
||||
bl __fixdfsi
|
||||
bl __subsf3
|
||||
bl __fixsfsi
|
||||
cmp r0, #0
|
||||
bge _08158564
|
||||
movs r0, #0
|
||||
@ -946,23 +523,23 @@ _0815856A:
|
||||
adds r6, r1, r0
|
||||
ldrh r0, [r6]
|
||||
lsrs r0, r0, #5
|
||||
bl __floatsidf
|
||||
bl __floatsisf
|
||||
adds r5, r0, #0
|
||||
mov r2, sl
|
||||
movs r0, #1
|
||||
ldrsb r0, [r2, r0]
|
||||
bl __floatsidf
|
||||
bl __floatsisf
|
||||
adds r4, r0, #0
|
||||
ldr r1, _081585B0 @ =0x41800000
|
||||
bl __adddf3
|
||||
bl __addsf3
|
||||
ldr r1, _081585B4 @ =0x3D800000
|
||||
bl __muldf3
|
||||
bl __mulsf3
|
||||
adds r1, r0, #0
|
||||
adds r0, r5, #0
|
||||
bl __muldf3
|
||||
bl __mulsf3
|
||||
adds r1, r4, #0
|
||||
bl __subdf3
|
||||
bl __fixdfsi
|
||||
bl __subsf3
|
||||
bl __fixsfsi
|
||||
cmp r0, #0
|
||||
bge _081585B8
|
||||
movs r0, #0
|
||||
@ -990,23 +567,23 @@ _081585CC:
|
||||
adds r6, r1, r0
|
||||
ldrh r0, [r6]
|
||||
lsrs r0, r0, #0xa
|
||||
bl __floatsidf
|
||||
bl __floatsisf
|
||||
adds r5, r0, #0
|
||||
mov r2, sl
|
||||
movs r0, #2
|
||||
ldrsb r0, [r2, r0]
|
||||
bl __floatsidf
|
||||
bl __floatsisf
|
||||
adds r4, r0, #0
|
||||
ldr r1, _08158614 @ =0x41800000
|
||||
bl __adddf3
|
||||
bl __addsf3
|
||||
ldr r1, _08158618 @ =0x3D800000
|
||||
bl __muldf3
|
||||
bl __mulsf3
|
||||
adds r1, r0, #0
|
||||
adds r0, r5, #0
|
||||
bl __muldf3
|
||||
bl __mulsf3
|
||||
adds r1, r4, #0
|
||||
bl __subdf3
|
||||
bl __fixdfsi
|
||||
bl __subsf3
|
||||
bl __fixsfsi
|
||||
cmp r0, #0
|
||||
bge _0815861C
|
||||
movs r0, #0
|
||||
@ -1068,20 +645,20 @@ _0815866A:
|
||||
movs r0, #0
|
||||
ldrsh r4, [r6, r0]
|
||||
adds r0, r4, #0
|
||||
bl __floatsidf
|
||||
bl __floatsisf
|
||||
cmp r4, #0
|
||||
bge _08158686
|
||||
ldr r1, _081586B0 @ =0x47800000
|
||||
bl __adddf3
|
||||
bl __addsf3
|
||||
_08158686:
|
||||
adds r1, r7, #0
|
||||
bl __divdf3
|
||||
bl __divsf3
|
||||
mov r2, r8
|
||||
ldr r1, [r2]
|
||||
bl sub_08159350
|
||||
bl powferrorhandler
|
||||
adds r1, r7, #0
|
||||
bl __muldf3
|
||||
bl __fixdfsi
|
||||
bl __mulsf3
|
||||
bl __fixsfsi
|
||||
cmp r0, #0
|
||||
bge _081586B4
|
||||
movs r0, #0
|
||||
@ -1100,15 +677,15 @@ _081586BA:
|
||||
adds r4, r5, r0
|
||||
ldrh r0, [r4]
|
||||
lsrs r0, r0, #5
|
||||
bl __floatsidf
|
||||
bl __floatsisf
|
||||
adds r1, r7, #0
|
||||
bl __divdf3
|
||||
bl __divsf3
|
||||
mov r2, r8
|
||||
ldr r1, [r2, #4]
|
||||
bl sub_08159350
|
||||
bl powferrorhandler
|
||||
adds r1, r7, #0
|
||||
bl __muldf3
|
||||
bl __fixdfsi
|
||||
bl __mulsf3
|
||||
bl __fixsfsi
|
||||
cmp r0, #0
|
||||
bge _081586EC
|
||||
movs r0, #0
|
||||
@ -1129,15 +706,15 @@ _081586F8:
|
||||
adds r5, r5, r0
|
||||
ldrh r0, [r5]
|
||||
lsrs r0, r0, #0xa
|
||||
bl __floatsidf
|
||||
bl __floatsisf
|
||||
adds r1, r7, #0
|
||||
bl __divdf3
|
||||
bl __divsf3
|
||||
mov r2, r8
|
||||
ldr r1, [r2, #8]
|
||||
bl sub_08159350
|
||||
bl powferrorhandler
|
||||
adds r1, r7, #0
|
||||
bl __muldf3
|
||||
bl __fixdfsi
|
||||
bl __mulsf3
|
||||
bl __fixsfsi
|
||||
cmp r0, #0
|
||||
bge _0815872C
|
||||
movs r0, #0
|
||||
@ -1455,7 +1032,7 @@ sub_08158934: @ 0x08158934
|
||||
ldr r0, _08158988 @ =gUnk_03002558
|
||||
strb r2, [r0]
|
||||
movs r0, #0
|
||||
bl sub_08157210
|
||||
bl MultiSioInit
|
||||
add sp, #4
|
||||
pop {r0}
|
||||
bx r0
|
||||
@ -1489,12 +1066,12 @@ sub_0815898C: @ 0x0815898C
|
||||
movs r2, #1
|
||||
strh r2, [r3]
|
||||
strh r4, [r3]
|
||||
ldr r1, _081589DC @ =gUnk_030017B0
|
||||
ldr r0, _081589E0 @ =gUnk_030068E0
|
||||
ldr r1, _081589DC @ =gIntrTable
|
||||
ldr r0, _081589E0 @ =gMultiSioIntrFuncBuf
|
||||
str r0, [r1]
|
||||
strh r2, [r3]
|
||||
movs r0, #0
|
||||
bl sub_08157210
|
||||
bl MultiSioInit
|
||||
_081589C0:
|
||||
ldr r1, _081589E4 @ =gUnk_03002558
|
||||
movs r0, #1
|
||||
@ -1507,8 +1084,8 @@ _081589CC: .4byte gUnk_03002440
|
||||
_081589D0: .4byte 0x04000208
|
||||
_081589D4: .4byte 0x04000200
|
||||
_081589D8: .4byte 0x0000FFBF
|
||||
_081589DC: .4byte gUnk_030017B0
|
||||
_081589E0: .4byte gUnk_030068E0
|
||||
_081589DC: .4byte gIntrTable
|
||||
_081589E0: .4byte gMultiSioIntrFuncBuf
|
||||
_081589E4: .4byte gUnk_03002558
|
||||
|
||||
thumb_func_start sub_081589E8
|
||||
@ -1522,9 +1099,9 @@ sub_081589E8: @ 0x081589E8
|
||||
ldr r1, _08158A24 @ =0xFFEFFFFF
|
||||
ands r0, r1
|
||||
str r0, [r4]
|
||||
bl sub_081576BC
|
||||
bl MultiSioStop
|
||||
movs r0, #0
|
||||
bl sub_08157210
|
||||
bl MultiSioInit
|
||||
ldr r0, [r4]
|
||||
movs r1, #0x80
|
||||
lsls r1, r1, #0xc
|
||||
@ -1741,12 +1318,12 @@ _08158BD0:
|
||||
cmp r0, #3
|
||||
bhi _08158BE4
|
||||
lsls r0, r0, #1
|
||||
ldr r1, _08158BE0 @ =gUnk_08D60898
|
||||
ldr r1, _08158BE0 @ =gAgbSramLibVer
|
||||
adds r0, r0, r1
|
||||
ldrh r0, [r0]
|
||||
b _08158BE8
|
||||
.align 2, 0
|
||||
_08158BE0: .4byte gUnk_08D60898
|
||||
_08158BE0: .4byte gAgbSramLibVer
|
||||
_08158BE4:
|
||||
movs r0, #0x80
|
||||
lsls r0, r0, #8
|
||||
@ -2112,8 +1689,8 @@ _08158E9A:
|
||||
.align 2, 0
|
||||
_08158EA4: .4byte 0x10000010
|
||||
|
||||
thumb_func_start sub_08158EA8
|
||||
sub_08158EA8: @ 0x08158EA8
|
||||
thumb_func_start Timer3Intr
|
||||
Timer3Intr: @ 0x08158EA8
|
||||
push {r4, r5, lr}
|
||||
ldr r3, _08158EE8 @ =0x04000208
|
||||
movs r4, #0
|
@ -1,108 +0,0 @@
|
||||
.include "asm/macros.inc"
|
||||
.include "constants/constants.inc"
|
||||
|
||||
.syntax unified
|
||||
|
||||
.text
|
||||
|
||||
arm_func_start sub_08158F14
|
||||
sub_08158F14: @ 0x08158F14
|
||||
push {r4, r5, r6, r7, r8, sb, sl, fp}
|
||||
mov ip, #0x4000000
|
||||
ldr fp, _08158F50 @ =gUnk_03006A60
|
||||
add sl, fp, #0x40
|
||||
mov sb, #1
|
||||
mov r8, #0
|
||||
strb r8, [ip, #0x208]
|
||||
ldm sl, {r0, r1, r2, r3, r4, r5, r6, r7}
|
||||
stm sl!, {r4, r5, r6, r7}
|
||||
stm sl!, {r0, r1, r2, r3}
|
||||
ldr r0, [fp, #4]
|
||||
str r8, [fp, #4]
|
||||
strb sb, [ip, #0x208]
|
||||
pop {r4, r5, r6, r7, r8, sb, sl, fp}
|
||||
bx lr
|
||||
.align 2, 0
|
||||
_08158F50: .4byte gUnk_03006A60
|
||||
|
||||
arm_func_start sub_08158F54
|
||||
sub_08158F54: @ 0x08158F54
|
||||
mov ip, #0x4000000
|
||||
add ip, ip, #0x120
|
||||
ldm ip, {r0, r1}
|
||||
push {r7, r8, sb, sl, fp}
|
||||
ldr fp, _0815906C @ =gUnk_03006A60
|
||||
mov sb, #0xfe
|
||||
add sb, sb, #0xfe00
|
||||
ldrh r3, [ip, #8]
|
||||
and r3, r3, #0x40
|
||||
strb r3, [fp, #9]
|
||||
ldr sl, [fp, #0x14]
|
||||
adds r3, sl, #1
|
||||
blt _08158FB0
|
||||
bne _08158FA4
|
||||
strh sb, [ip, #0xa]
|
||||
add r8, fp, #0x28
|
||||
ldm r8, {r2, r3}
|
||||
mov r7, r2
|
||||
stm r8, {r3, r7}
|
||||
b _08158FB0
|
||||
_08158FA4:
|
||||
ldr r3, [fp, #0x2c]
|
||||
ldr r2, [r3, sl, lsl #1]
|
||||
strh r2, [ip, #0xa]
|
||||
_08158FB0:
|
||||
cmp sl, #0xd
|
||||
addlt sl, sl, #1
|
||||
strlt sl, [fp, #0x14]
|
||||
push {r0, r1, r5, r6}
|
||||
mov r6, #3
|
||||
_08158FC4:
|
||||
add r8, fp, #0x18
|
||||
add r8, r8, r6, lsl #2
|
||||
ldr sl, [r8]
|
||||
lsl r3, r6, #1
|
||||
ldrh r5, [sp, r3]
|
||||
cmp r5, sb
|
||||
bne _08158FF4
|
||||
cmp sl, #0xb
|
||||
ble _08158FF4
|
||||
mov r0, #1
|
||||
sub sl, r0, #2
|
||||
b _08159020
|
||||
_08158FF4:
|
||||
ldr r0, [r8, #0x18]
|
||||
lsl r3, sl, #1
|
||||
strh r5, [r0, r3]
|
||||
cmp sl, #0xb
|
||||
bne _08159020
|
||||
ldr r1, [r8, #0x28]
|
||||
str r0, [r8, #0x28]
|
||||
str r1, [r8, #0x18]
|
||||
add r3, fp, #4
|
||||
mov r0, #1
|
||||
strb r0, [r3, r6]
|
||||
_08159020:
|
||||
cmp sl, #0xd
|
||||
addlt sl, sl, #1
|
||||
str sl, [r8]
|
||||
subs r6, r6, #1
|
||||
bge _08158FC4
|
||||
ldrb r0, [fp]
|
||||
cmp r0, #0
|
||||
beq _08159060
|
||||
ldr r7, _08159070 @ =0x0400010E
|
||||
mov r0, #0
|
||||
strh r0, [r7]
|
||||
ldrh r0, [ip, #8]
|
||||
orr r0, r0, #0x80
|
||||
strh r0, [ip, #8]
|
||||
mov r0, #0xc0
|
||||
strh r0, [r7]
|
||||
_08159060:
|
||||
add sp, sp, #8
|
||||
pop {r5, r6, r7, r8, sb, sl, fp}
|
||||
bx lr
|
||||
.align 2, 0
|
||||
_0815906C: .4byte gUnk_03006A60
|
||||
_08159070: .4byte 0x0400010E
|
1784
asm/code_08159350.s
1784
asm/code_08159350.s
File diff suppressed because it is too large
Load Diff
57
asm/crt0.s
57
asm/crt0.s
@ -10,82 +10,81 @@ __start:
|
||||
arm_func_start sub_08000000
|
||||
sub_08000000: @ 0x08000000
|
||||
b _080000C0
|
||||
_08000004:
|
||||
|
||||
.include "asm/rom_header.inc"
|
||||
|
||||
_080000C0:
|
||||
mov r0, #0x12
|
||||
mov r0, #PSR_IRQ_MODE
|
||||
msr cpsr_fc, r0
|
||||
ldr sp, _080000F8 @ =gUnk_03007FA0
|
||||
mov r0, #0x1f
|
||||
ldr sp, sp_irq
|
||||
mov r0, #PSR_SYS_MODE
|
||||
msr cpsr_fc, r0
|
||||
ldr sp, _080000F4 @ =gUnk_03007E80
|
||||
ldr r1, _080001C0 @ =gUnk_03007FFC
|
||||
add r0, pc, #0x18 @ =sub_080000FC
|
||||
ldr sp, sp_usr
|
||||
ldr r1, _080001C0 @ =INTR_VECTOR
|
||||
add r0, pc, #0x18 @ =IntrMain
|
||||
str r0, [r1]
|
||||
ldr r1, _080001C4 @ =sub_08152A04
|
||||
ldr r1, _080001C4 @ =AgbMain
|
||||
mov lr, pc
|
||||
bx r1
|
||||
_080000F0:
|
||||
b _080000C0
|
||||
_080000F4: .4byte gUnk_03007E80
|
||||
_080000F8: .4byte gUnk_03007FA0
|
||||
sp_usr: .4byte IWRAM_END - 0x180
|
||||
sp_irq: .4byte IWRAM_END - 0x60
|
||||
|
||||
arm_func_start sub_080000FC
|
||||
sub_080000FC: @ 0x080000FC
|
||||
arm_func_start IntrMain
|
||||
IntrMain: @ 0x080000FC
|
||||
mov r3, #0x4000000
|
||||
add r3, r3, #0x200
|
||||
ldr r2, [r3]
|
||||
and r1, r2, r2, lsr #16
|
||||
mov r2, #0
|
||||
ands r0, r1, #0x2000
|
||||
ands r0, r1, #INTR_FLAG_GAMEPAK
|
||||
strbne r0, [r3, #-0x17c]
|
||||
_08000118:
|
||||
bne _08000118
|
||||
ands r0, r1, #0xc0
|
||||
ands r0, r1, #INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL
|
||||
bne _080001AC
|
||||
add r2, r2, #4
|
||||
ands r0, r1, #1
|
||||
ands r0, r1, #INTR_FLAG_VBLANK
|
||||
bne _080001AC
|
||||
add r2, r2, #4
|
||||
ands r0, r1, #2
|
||||
ands r0, r1, #INTR_FLAG_HBLANK
|
||||
bne _080001AC
|
||||
add r2, r2, #4
|
||||
ands r0, r1, #4
|
||||
ands r0, r1, #INTR_FLAG_VCOUNT
|
||||
bne _080001AC
|
||||
add r2, r2, #4
|
||||
ands r0, r1, #8
|
||||
ands r0, r1, #INTR_FLAG_TIMER0
|
||||
bne _080001AC
|
||||
add r2, r2, #4
|
||||
ands r0, r1, #0x10
|
||||
ands r0, r1, #INTR_FLAG_TIMER1
|
||||
bne _080001AC
|
||||
add r2, r2, #4
|
||||
ands r0, r1, #0x20
|
||||
ands r0, r1, #INTR_FLAG_TIMER2
|
||||
bne _080001AC
|
||||
add r2, r2, #4
|
||||
ands r0, r1, #0x40
|
||||
ands r0, r1, #INTR_FLAG_TIMER3
|
||||
bne _080001AC
|
||||
add r2, r2, #4
|
||||
ands r0, r1, #0x100
|
||||
ands r0, r1, #INTR_FLAG_DMA0
|
||||
bne _080001AC
|
||||
add r2, r2, #4
|
||||
ands r0, r1, #0x200
|
||||
ands r0, r1, #INTR_FLAG_DMA1
|
||||
bne _080001AC
|
||||
add r2, r2, #4
|
||||
ands r0, r1, #0x400
|
||||
ands r0, r1, #INTR_FLAG_DMA2
|
||||
bne _080001AC
|
||||
add r2, r2, #4
|
||||
ands r0, r1, #0x800
|
||||
ands r0, r1, #INTR_FLAG_DMA3
|
||||
bne _080001AC
|
||||
add r2, r2, #4
|
||||
_080001AC:
|
||||
strh r0, [r3, #2]
|
||||
ldr r1, _080001C8 @ =gUnk_030017B0
|
||||
ldr r1, _080001C8 @ =gIntrTable
|
||||
add r1, r1, r2
|
||||
ldr r0, [r1]
|
||||
bx r0
|
||||
.align 2, 0
|
||||
_080001C0: .4byte gUnk_03007FFC
|
||||
_080001C4: .4byte sub_08152A04
|
||||
_080001C8: .4byte gUnk_030017B0
|
||||
_080001C0: .4byte INTR_VECTOR
|
||||
_080001C4: .4byte AgbMain
|
||||
_080001C8: .4byte gIntrTable
|
||||
|
@ -73,15 +73,15 @@ SoftReset: @ 0x0815931C
|
||||
_0815932C: .4byte 0x04000208
|
||||
_08159330: .4byte gUnk_03007F00
|
||||
|
||||
thumb_func_start SoundBiasLevel000
|
||||
SoundBiasLevel000: @ 0x08159334
|
||||
thumb_func_start SoundBiasReset
|
||||
SoundBiasReset: @ 0x08159334
|
||||
movs r0, #0
|
||||
svc #0x19
|
||||
bx lr
|
||||
.align 2, 0
|
||||
|
||||
thumb_func_start SoundBiasLevel200
|
||||
SoundBiasLevel200: @ 0x0815933C
|
||||
thumb_func_start SoundBiasSet
|
||||
SoundBiasSet: @ 0x0815933C
|
||||
movs r0, #1
|
||||
svc #0x19
|
||||
bx lr
|
||||
|
113
asm/libc.s
113
asm/libc.s
@ -1,113 +0,0 @@
|
||||
.include "asm/macros.inc"
|
||||
.include "constants/constants.inc"
|
||||
|
||||
.syntax unified
|
||||
|
||||
.text
|
||||
|
||||
thumb_func_start memcpy
|
||||
memcpy: @ 0x0815BD24
|
||||
push {r4, r5, lr}
|
||||
adds r5, r0, #0
|
||||
adds r4, r5, #0
|
||||
adds r3, r1, #0
|
||||
cmp r2, #0xf
|
||||
bls _0815BD64
|
||||
adds r0, r3, #0
|
||||
orrs r0, r5
|
||||
movs r1, #3
|
||||
ands r0, r1
|
||||
cmp r0, #0
|
||||
bne _0815BD64
|
||||
adds r1, r5, #0
|
||||
_0815BD3E:
|
||||
ldm r3!, {r0}
|
||||
stm r1!, {r0}
|
||||
ldm r3!, {r0}
|
||||
stm r1!, {r0}
|
||||
ldm r3!, {r0}
|
||||
stm r1!, {r0}
|
||||
ldm r3!, {r0}
|
||||
stm r1!, {r0}
|
||||
subs r2, #0x10
|
||||
cmp r2, #0xf
|
||||
bhi _0815BD3E
|
||||
cmp r2, #3
|
||||
bls _0815BD62
|
||||
_0815BD58:
|
||||
ldm r3!, {r0}
|
||||
stm r1!, {r0}
|
||||
subs r2, #4
|
||||
cmp r2, #3
|
||||
bhi _0815BD58
|
||||
_0815BD62:
|
||||
adds r4, r1, #0
|
||||
_0815BD64:
|
||||
subs r2, #1
|
||||
movs r0, #1
|
||||
rsbs r0, r0, #0
|
||||
cmp r2, r0
|
||||
beq _0815BD7E
|
||||
adds r1, r0, #0
|
||||
_0815BD70:
|
||||
ldrb r0, [r3]
|
||||
strb r0, [r4]
|
||||
adds r3, #1
|
||||
adds r4, #1
|
||||
subs r2, #1
|
||||
cmp r2, r1
|
||||
bne _0815BD70
|
||||
_0815BD7E:
|
||||
adds r0, r5, #0
|
||||
pop {r4, r5, pc}
|
||||
.align 2, 0
|
||||
|
||||
thumb_func_start memset
|
||||
memset: @ 0x0815BD84
|
||||
push {r4, r5, lr}
|
||||
adds r5, r0, #0
|
||||
adds r4, r1, #0
|
||||
adds r3, r5, #0
|
||||
cmp r2, #3
|
||||
bls _0815BDCA
|
||||
movs r0, #3
|
||||
ands r0, r5
|
||||
cmp r0, #0
|
||||
bne _0815BDCA
|
||||
adds r1, r5, #0
|
||||
movs r0, #0xff
|
||||
ands r4, r0
|
||||
lsls r3, r4, #8
|
||||
orrs r3, r4
|
||||
lsls r0, r3, #0x10
|
||||
orrs r3, r0
|
||||
cmp r2, #0xf
|
||||
bls _0815BDBE
|
||||
_0815BDAA:
|
||||
stm r1!, {r3}
|
||||
stm r1!, {r3}
|
||||
stm r1!, {r3}
|
||||
stm r1!, {r3}
|
||||
subs r2, #0x10
|
||||
cmp r2, #0xf
|
||||
bhi _0815BDAA
|
||||
b _0815BDBE
|
||||
_0815BDBA:
|
||||
stm r1!, {r3}
|
||||
subs r2, #4
|
||||
_0815BDBE:
|
||||
cmp r2, #3
|
||||
bhi _0815BDBA
|
||||
adds r3, r1, #0
|
||||
b _0815BDCA
|
||||
_0815BDC6:
|
||||
strb r4, [r3]
|
||||
adds r3, #1
|
||||
_0815BDCA:
|
||||
adds r0, r2, #0
|
||||
subs r2, #1
|
||||
cmp r0, #0
|
||||
bne _0815BDC6
|
||||
adds r0, r5, #0
|
||||
pop {r4, r5, pc}
|
||||
.align 2, 0
|
3875
asm/libgcc.s
3875
asm/libgcc.s
File diff suppressed because it is too large
Load Diff
2950
asm/libm4a_2.s
2950
asm/libm4a_2.s
File diff suppressed because it is too large
Load Diff
12411
asm/main.s
12411
asm/main.s
File diff suppressed because it is too large
Load Diff
220
asm/multi_sio_asm.s
Normal file
220
asm/multi_sio_asm.s
Normal file
@ -0,0 +1,220 @@
|
||||
.include "asm/macros.inc"
|
||||
.include "constants/constants.inc"
|
||||
|
||||
.syntax unified
|
||||
|
||||
.text
|
||||
|
||||
.ifdef MULTI_SIO_DI_FUNC_FAST
|
||||
|
||||
@--------------------------------------------------------------------
|
||||
@- Update Receive Data/Check Buffer Routine -
|
||||
@--------------------------------------------------------------------
|
||||
|
||||
arm_func_start MultiSioRecvBufChange
|
||||
MultiSioRecvBufChange: @ 0x08158F14
|
||||
stmfd sp!, {r4-r11}
|
||||
|
||||
mov r12, #REG_BASE @ r12: REG_BASE
|
||||
ldr r11, =gMultiSioArea @ r11: &gMultiSioArea
|
||||
add r10, r11, #OFS_MS_LAST_RECV_BUF_P @ r10: &gMultiSioArea.lastRecvBufp[0]
|
||||
mov r9, #1 @ r9: 1
|
||||
mov r8, #0 @ r8: 0
|
||||
|
||||
|
||||
@ *(vu8 *)REG_ADDR_IME = 0 Disable Interrupt (29 Clocks)
|
||||
|
||||
strb r8, [r12, #OFFSET_REG_IME]
|
||||
|
||||
@ gMultiSioArea.recvCheckBufp[i] <--> gMultiSioArea.lastRecvBufp[i] Update Receive Buffer
|
||||
|
||||
ldmia r10, {r0-r7}
|
||||
stmia r10!, {r4-r7}
|
||||
stmia r10!, {r0-r3}
|
||||
|
||||
@ syncRecvFlagBak[i] = gMultiSioArea.syncRecvFlag[i]
|
||||
@ gMultiSioArea.syncRecvFlag[i] = 0
|
||||
|
||||
ldr r0, [r11, #OFS_MS_SYNC_RECV_FLAG]
|
||||
str r8, [r11, #OFS_MS_SYNC_RECV_FLAG]
|
||||
|
||||
@ *(vu8 *)REG_IME = 1 Enable Interrupt
|
||||
|
||||
strb r9, [r12, #OFFSET_REG_IME]
|
||||
|
||||
@ return gMultiSioArea.syncRecvFlag[i]
|
||||
|
||||
ldmfd sp!, {r4-r11}
|
||||
bx lr
|
||||
.ltorg
|
||||
arm_func_end MultiSioRecvBufChange
|
||||
|
||||
@--------------------------------------------------------------------
|
||||
@- Multi-play Interrupt Routine -
|
||||
@--------------------------------------------------------------------
|
||||
|
||||
arm_func_start MultiSioIntr
|
||||
MultiSioIntr: @ 0x08158F54
|
||||
@ Save Receive Data
|
||||
@ *(u64 *)recvTmp = *(u64 *)REG_ADDR_SIOMLT_RECV
|
||||
|
||||
mov r12, #REG_BASE @ r12: REG_SIOMLT_RECV
|
||||
add r12, r12, #OFFSET_REG_SIOMLT_RECV
|
||||
ldmia r12, {r0-r1}
|
||||
|
||||
@ Save Register to Stack
|
||||
|
||||
stmfd sp!, {r7-r11}
|
||||
|
||||
ldr r11, =gMultiSioArea @ r11: &gMultiSioArea
|
||||
mov r9, #MULTI_SIO_SYNC_DATA & 0x00ff @ r9: MULTI_SIO_SYNC_DATA
|
||||
add r9, r9, #MULTI_SIO_SYNC_DATA & 0xff00
|
||||
|
||||
/* FIXME: What does these mean? */
|
||||
ldrh r3, [r12, #8]
|
||||
and r3, r3, #0x40
|
||||
@ hardError
|
||||
strb r3, [r11, #9]
|
||||
|
||||
@ Send Data Processing
|
||||
|
||||
@ if (gMultiSioArea.sendBufCounter == -1) {
|
||||
|
||||
ldr r10, [r11, #OFS_MS_SEND_BUF_COUNTER] @ r10: gMultiSioArea.sendBufCounter
|
||||
adds r3, r10, #1
|
||||
blt 3f
|
||||
bne 2f
|
||||
|
||||
@ REG_SIOCNT->data = MULTI_SIO_SYNC_DATA Set Synchronization Data
|
||||
|
||||
strh r9, [r12, #REG_SIOMLT_SEND - REG_SIOMLT_RECV]
|
||||
|
||||
@ gMultiSioArea.currentSendBufp <--> gMultiSioArea.nextSendBufp Change Send Buffer
|
||||
|
||||
add r8, r11, #OFS_MS_NEXT_SEND_BUF_P
|
||||
ldmia r8, {r2,r3}
|
||||
mov r7, r2
|
||||
stmia r8, {r3,r7}
|
||||
b 3f
|
||||
2:
|
||||
@ } else if (gMultiSioArea.sendBufCounter >= 0) {
|
||||
@ REG_SIOCNT->data = gMultiSioArea.currentSendBufp[gMultiSioArea.sendBufCounter]
|
||||
@ Set Send Data
|
||||
|
||||
ldr r3, [r11, #OFS_MS_CURRENT_SEND_BUF_P]
|
||||
ldr r2, [r3, r10, lsl #1]
|
||||
strh r2, [r12, #REG_SIOMLT_SEND - REG_SIOMLT_RECV]
|
||||
3:
|
||||
@ }
|
||||
|
||||
@ if (gMultiSioArea.sendBufCounter < sizeof(struct MultiSioPacket) / 2 - 1)
|
||||
@ gMultiSioArea.sendBufCounter++;
|
||||
|
||||
cmp r10, #MULTI_SIO_PACKET_SIZE / 2 - 1
|
||||
addlt r10, r10, #1
|
||||
strlt r10, [r11, #OFS_MS_SEND_BUF_COUNTER]
|
||||
|
||||
@ Save Receive Data & Register to Stack
|
||||
|
||||
stmfd sp!, {r0-r1, r5-r6}
|
||||
|
||||
|
||||
@ Receive Data Processing (Max. Approx. 160 Clocks/Included in Wait Period)
|
||||
|
||||
@ for (i = 0; i < MULTI_SIO_PLAYERS_MAX; i++) {
|
||||
|
||||
mov r6, #MULTI_SIO_PLAYERS_MAX - 1 @ r6: i
|
||||
4:
|
||||
add r8, r11, #OFS_MS_RECV_BUF_COUNTER @ r8: &gMultiSioArea.recvBufCounter[i]
|
||||
add r8, r8, r6, lsl #2
|
||||
ldr r10, [r8, #0] @ r10: gMultiSioArea.recvBufCounter[i]
|
||||
mov r3, r6, lsl #1 @ r5: RecvTmp[i]
|
||||
ldrh r5, [sp, r3]
|
||||
|
||||
@ if ( recvTmp[i] == MULTI_SIO_SYNC_DATA
|
||||
@ && gMultiSioArea.recvBufCounter[i] > sizeof(struct MultiSioPacket) / 2 - 3) {
|
||||
|
||||
cmp r5, r9
|
||||
bne 6f
|
||||
cmp r10, #MULTI_SIO_PACKET_SIZE / 2 - 3
|
||||
ble 6f
|
||||
|
||||
@ gMultiSioArea.recvBufCounter[i] = -1
|
||||
|
||||
mov r0, #1
|
||||
sub r10, r0, #2
|
||||
|
||||
b 7f
|
||||
6:
|
||||
@ } else {
|
||||
@ gMultiSioArea.currentRecvBufp[i][gMultiSioArea.recvBufCounter[i]] = recvTmp[i]
|
||||
@ Store Receive Data
|
||||
|
||||
ldr r0, [r8, #OFS_MS_CURRENT_RECV_BUF_P - OFS_MS_RECV_BUF_COUNTER]
|
||||
mov r3, r10, lsl #1
|
||||
strh r5, [r0, r3]
|
||||
|
||||
@ if (gMultiSioArea.recvBufCounter[i] == sizeof(struct MultiSioPacket) / 2 - 3)
|
||||
|
||||
cmp r10, #MULTI_SIO_PACKET_SIZE / 2 - 3
|
||||
bne 7f
|
||||
|
||||
@ gMultiSioArea.currentRecvBufp[i] <--> gMultiSioArea.lastRecvBufp[i] Change Receive Buffer
|
||||
|
||||
ldr r1, [r8, #OFS_MS_LAST_RECV_BUF_P - OFS_MS_RECV_BUF_COUNTER]
|
||||
str r0, [r8, #OFS_MS_LAST_RECV_BUF_P - OFS_MS_RECV_BUF_COUNTER]
|
||||
str r1, [r8, #OFS_MS_CURRENT_RECV_BUF_P - OFS_MS_RECV_BUF_COUNTER]
|
||||
|
||||
@ gMultiSioArea.syncRecvFlag[i] = 1; Receive Completion Flag
|
||||
|
||||
add r3, r11, #OFS_MS_SYNC_RECV_FLAG
|
||||
mov r0, #1
|
||||
strb r0, [r3, r6]
|
||||
7:
|
||||
@ }
|
||||
|
||||
@ if (gMultiSioArea.recvBufCounter[i] < sizeof(struct MultiSioPacket) / 2 - 1)
|
||||
@ gMultiSioArea.recvBufCounter[i]++;
|
||||
|
||||
cmp r10, #MULTI_SIO_PACKET_SIZE / 2 - 1
|
||||
addlt r10, r10, #1
|
||||
str r10, [r8, #0]
|
||||
|
||||
subs r6, r6, #1
|
||||
bge 4b
|
||||
|
||||
@ }
|
||||
|
||||
|
||||
@ Start Master Send
|
||||
|
||||
@ if (gMultiSioArea.type == SIO_MULTI_PARENT)
|
||||
|
||||
ldrb r0, [r11,#OFS_MS_TYPE]
|
||||
cmp r0, #0
|
||||
beq 11f
|
||||
|
||||
@ *(vu16 *)REG_ADDR_MULTI_SIO_TIMER_H = 0; Stop Timer
|
||||
|
||||
ldr r7, =REG_MULTI_SIO_TIMER_H @ r7: REG_MULTI_SIO_TIMER_H
|
||||
mov r0, #0
|
||||
strh r0, [r7, #0]
|
||||
|
||||
@ REG_SIOCNT |= SIO_ENABLE; Restart Send
|
||||
|
||||
ldrh r0, [r12, #REG_SIOCNT - REG_SIOMLT_RECV]
|
||||
orr r0, r0, #SIO_ENABLE
|
||||
strh r0, [r12, #REG_SIOCNT - REG_SIOMLT_RECV]
|
||||
|
||||
@ *(vu16 *)REG_ADDR_MULTI_SIO_TIMER_H Restart Timer
|
||||
@ = (TIMER_1CLK | TIMER_INTR_ENABLE | TIMER_ENABLE);
|
||||
|
||||
mov r0, #0xC0
|
||||
strh r0, [r7, #0]
|
||||
11:
|
||||
add sp, sp, #8
|
||||
ldmfd sp!, {r5-r11}
|
||||
bx lr
|
||||
arm_func_end MultiSioIntr
|
||||
|
||||
.endif
|
1008
asm/multiboot.s
1008
asm/multiboot.s
File diff suppressed because it is too large
Load Diff
10
asmdiff.sh
Normal file
10
asmdiff.sh
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
buildname=kirbyamazingmirror
|
||||
baserom=baserom
|
||||
|
||||
OBJDUMP="$DEVKITARM/bin/arm-none-eabi-objdump -D -bbinary -marmv4t -Mforce-thumb"
|
||||
OPTIONS="--start-address=$(($1)) --stop-address=$(($1 + $2))"
|
||||
$OBJDUMP $OPTIONS ${baserom}.gba > ${baserom}.dump || exit 1
|
||||
$OBJDUMP $OPTIONS ${buildname}.gba > ${buildname}.dump
|
||||
diff -u ${baserom}.dump ${buildname}.dump
|
142
calcrom.pl
Normal file
142
calcrom.pl
Normal file
@ -0,0 +1,142 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use IPC::Cmd qw[ run ];
|
||||
|
||||
(@ARGV == 1)
|
||||
or die "ERROR: no map file specified.\n";
|
||||
open(my $file, $ARGV[0])
|
||||
or die "ERROR: could not open file '$ARGV[0]'.\n";
|
||||
|
||||
my $src = 0;
|
||||
my $asm = 0;
|
||||
my $srcdata = 0;
|
||||
my $data = 0;
|
||||
while (my $line = <$file>)
|
||||
{
|
||||
if ($line =~ /^ \.(\w+)\s+0x[0-9a-f]+\s+(0x[0-9a-f]+) (\w+)\/.+\.o/)
|
||||
{
|
||||
my $section = $1;
|
||||
my $size = hex($2);
|
||||
my $dir = $3;
|
||||
if ($size & 3)
|
||||
{
|
||||
$size += 4 - ($size % 3);
|
||||
}
|
||||
|
||||
if ($section =~ /text/)
|
||||
{
|
||||
if ($dir eq 'src')
|
||||
{
|
||||
$src += $size;
|
||||
}
|
||||
elsif ($dir eq 'asm')
|
||||
{
|
||||
$asm += $size;
|
||||
}
|
||||
}
|
||||
elsif ($section =~ /rodata/)
|
||||
{
|
||||
if ($dir eq 'src')
|
||||
{
|
||||
$srcdata += $size;
|
||||
}
|
||||
elsif ($dir eq 'data')
|
||||
{
|
||||
$data += $size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Note that the grep filters out all branch labels. It also requires a minimum
|
||||
# line length of 5, to filter out a ton of generated symbols (like AcCn). No
|
||||
# settings to nm seem to remove these symbols. Finally, nm prints out a separate
|
||||
# entry for whenever a name appears in a file, not just where it's defined. uniq
|
||||
# removes all the duplicate entries.
|
||||
#
|
||||
#
|
||||
# You'd expect this to take a while, because of uniq. It runs in under a second,
|
||||
# though. Uniq is pretty fast!
|
||||
my $base_cmd = "nm kirbyamazingmirror.elf | awk '{print \$3}' | grep '^[^_].\\{4\\}' | uniq";
|
||||
|
||||
# This looks for Unk_, unk_, or sub_, followed by just numbers. Note that
|
||||
# it matches even if stuff precedes the unk, like sUnk/gUnk.
|
||||
my $undoc_cmd = "grep '[Uu]nk_[0-9a-fA-F]*\\|sub_[0-9a-fA-F]*'";
|
||||
|
||||
# This looks for every symbol with an address at the end of it. Some things are
|
||||
# given a name based on their type / location, but still have an unknown purpose.
|
||||
# For example, FooMap_EventScript_FFFFFFF.
|
||||
|
||||
my $count_cmd = "wc -l";
|
||||
|
||||
# It sucks that we have to run this three times, but I can't figure out how to get
|
||||
# stdin working for subcommands in perl while still having a timeout. It's decently
|
||||
# fast anyway.
|
||||
my $total_syms_as_string;
|
||||
(run (
|
||||
command => "$base_cmd | $count_cmd",
|
||||
buffer => \$total_syms_as_string,
|
||||
timeout => 60
|
||||
))
|
||||
or die "ERROR: Error while getting all symbols: $?";
|
||||
|
||||
my $undocumented_as_string;
|
||||
(run (
|
||||
command => "$base_cmd | $undoc_cmd | $count_cmd",
|
||||
buffer => \$undocumented_as_string,
|
||||
timeout => 60
|
||||
))
|
||||
or die "ERROR: Error while filtering for undocumented symbols: $?";
|
||||
|
||||
# Performing addition on a string converts it to a number. Any string that fails
|
||||
# to convert to a number becomes 0. So if our converted number is 0, but our string
|
||||
# is nonzero, then the conversion was an error.
|
||||
my $undocumented = $undocumented_as_string + 0;
|
||||
(($undocumented != 0) and ($undocumented_as_string ne "0"))
|
||||
or die "ERROR: Cannot convert string to num: '$undocumented_as_string'";
|
||||
|
||||
my $total_syms = $total_syms_as_string + 0;
|
||||
(($total_syms != 0) and ($total_syms_as_string ne "0"))
|
||||
or die "ERROR: Cannot convert string to num: '$total_syms_as_string'";
|
||||
|
||||
($total_syms != 0)
|
||||
or die "ERROR: No symbols found.";
|
||||
|
||||
my $total = $src + $asm;
|
||||
my $srcPct = sprintf("%.4f", 100 * $src / $total);
|
||||
my $asmPct = sprintf("%.4f", 100 * $asm / $total);
|
||||
|
||||
my $documented = $total_syms - ($undocumented);
|
||||
my $docPct = sprintf("%.4f", 100 * $documented / $total_syms);
|
||||
my $undocPct = sprintf("%.4f", 100 * $undocumented / $total_syms);
|
||||
|
||||
print "$total total bytes of code\n";
|
||||
print "$src bytes of code in src ($srcPct%)\n";
|
||||
print "$asm bytes of code in asm ($asmPct%)\n";
|
||||
print "\n";
|
||||
print "$total_syms total symbols\n";
|
||||
print "$documented symbols documented ($docPct%)\n";
|
||||
print "$undocumented symbols undocumented ($undocPct%)\n";
|
||||
|
||||
my $foundLines = `git grep '\.incbin "baserom\.gba"' data/`;
|
||||
my @allLines = split('\n', $foundLines);
|
||||
my $incbinTotal = 0;
|
||||
my $incbinNum = 0;
|
||||
foreach my $line (@allLines)
|
||||
{
|
||||
if ($line =~ /\.incbin\s+"baserom\.gba",\s*0x\w+,\s*(.+?)\s*(\@.*)?$/)
|
||||
{
|
||||
my $size = hex($1);
|
||||
$incbinTotal += $size;
|
||||
$incbinNum++;
|
||||
}
|
||||
}
|
||||
print "\n";
|
||||
my $dataTotal = $srcdata + $data;
|
||||
my $srcDataPct = sprintf("%.4f", 100 * $srcdata / $dataTotal);
|
||||
my $dataPct = sprintf("%.4f", 100 * $data / $dataTotal);
|
||||
my $incbinTotalPct = sprintf("%.4f", 100 * $incbinTotal / $dataTotal);
|
||||
print "$dataTotal total bytes of data\n";
|
||||
print "$srcdata bytes of data in src ($srcDataPct%)\n";
|
||||
print "$data bytes of data in data ($dataPct%)\n";
|
||||
print "$incbinNum baserom incbins with a combined $incbinTotal bytes ($incbinTotalPct%)\n";
|
@ -1,2 +1,3 @@
|
||||
.include "constants/gba_constants.inc"
|
||||
.include "constants/misc_constants.inc"
|
||||
.include "constants/multi_sio_constants.inc"
|
||||
|
@ -10,9 +10,9 @@
|
||||
.set PSR_F_BIT, 0x00000040
|
||||
.set PSR_I_BIT, 0x00000080
|
||||
|
||||
.set EWRAM_START, gUnk_02000000
|
||||
.set EWRAM_START, 0x2000000
|
||||
.set EWRAM_END, EWRAM_START + 0x40000
|
||||
.set IWRAM_START, 0x03000000
|
||||
.set IWRAM_START, 0x3000000
|
||||
.set IWRAM_END, IWRAM_START + 0x8000
|
||||
|
||||
.set PLTT, 0x5000000
|
||||
@ -488,3 +488,7 @@
|
||||
.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
|
||||
|
||||
@ SIO constants
|
||||
|
||||
.set SIO_ENABLE, 0x80
|
||||
|
64
constants/multi_sio_constants.inc
Normal file
64
constants/multi_sio_constants.inc
Normal file
@ -0,0 +1,64 @@
|
||||
@ Optimize the following settings based on the software specifications
|
||||
|
||||
MULTI_SIO_BLOCK_SIZE = 20 @ Communication Data Block Size (Max. 24 Bytes)
|
||||
|
||||
MULTI_SIO_PLAYERS_MAX = 4 @ Maximum Number of Players
|
||||
|
||||
MULTI_SIO_SYNC_DATA = 0xfefe @ Synchronized Data (0x0000/0xfffa~0xffff prohibited)
|
||||
|
||||
@ Comment out if no space in CPU internal Work RAM
|
||||
MULTI_SIO_DI_FUNC_FAST: @ SIO Interrupt Prohibit Function High Speed Flag (CPU Internal RAM Execution)
|
||||
|
||||
|
||||
MULTI_SIO_TIMER_NO = 3 @ Timer No.
|
||||
MULTI_SIO_TIMER_INTR_FLAG = (INTR_FLAG_TIMER0 << MULTI_SIO_TIMER_NO)
|
||||
@ Timer Interrupt Flag
|
||||
REG_MULTI_SIO_TIMER = (REG_TM0CNT + MULTI_SIO_TIMER_NO * 4)
|
||||
REG_MULTI_SIO_TIMER_L = REG_MULTI_SIO_TIMER
|
||||
REG_MULTI_SIO_TIMER_H = (REG_MULTI_SIO_TIMER + 2)
|
||||
@ Timer Register
|
||||
|
||||
|
||||
@ Multi-play Communication Packet Structure Offset
|
||||
|
||||
OFS_MSP_FRAME_COUNTER = 0 @ Frame Counter
|
||||
OFS_MSP_RECV_ERROR_FLAGS = 1 @ Receive Error Flag
|
||||
OFS_MSP_CHECK_SUM = 2 @ Checksum
|
||||
OFS_MSP_DATA = 4 @ Communication Data
|
||||
OFS_MSP_OVERRUN_CATCH = (OFS_MSP_DATA + MULTI_SIO_BLOCK_SIZE)
|
||||
@ Overrun Protect Area
|
||||
|
||||
MULTI_SIO_PACKET_SIZE = (OFS_MSP_OVERRUN_CATCH + 4)
|
||||
@ Structure Size
|
||||
|
||||
|
||||
@ Multi-play Communication Work Area Structure Offset
|
||||
|
||||
OFS_MS_TYPE = 0 @ Connection (Master/Slave)
|
||||
OFS_MS_STATE = 1 @ Communication Function State
|
||||
OFS_MS_CONNECTED_FLAG = 2 @ Connection History Flag
|
||||
OFS_MS_RECV_SUCCESS_FLAGS = 3 @ Receive Success Flag
|
||||
|
||||
OFS_MS_SYNC_RECV_FLAG = 4 @ Synchronized Data Receive Confirmation Flag
|
||||
OFS_MS_SYNC_RECV_ADJUST_COUNTER = 8 @ Synchronization Adjustment Counter
|
||||
|
||||
OFS_MS_SEND_BUF_COUNTER_INIT = 10 @ Send Buffer Counter Initialization
|
||||
|
||||
OFS_MS_SYNC_SEND_FRAME_COUNTER = 11 @ Send Frame Counter
|
||||
OFS_MS_SYNC_RECV_FRAME_COUNTER = 12 @ Receive Frame Counter
|
||||
|
||||
OFS_MS_SEND_BUF_COUNTER = 20 @ Send Buffer Counter
|
||||
OFS_MS_RECV_BUF_COUNTER = 24 @ Receive Buffer Counter
|
||||
|
||||
OFS_MS_NEXT_SEND_BUF_P = 40 @ Send Buffer Pointer
|
||||
OFS_MS_CURRENT_SEND_BUF_P = 44
|
||||
OFS_MS_CURRENT_RECV_BUF_P = 48 @ Receive Buffer Pointer
|
||||
OFS_MS_LAST_RECV_BUF_P = 64
|
||||
OFS_MS_RECV_CHECK_BUF_P = 80
|
||||
|
||||
OFS_MS_SEND_BUF = 96 @ Send Buffer (Double Buffer)
|
||||
OFS_MS_RECV_BUF = (OFS_MS_SEND_BUF + MULTI_SIO_PACKET_SIZE * 2)
|
||||
@ Receive Buffer (Triple Buffer)
|
||||
|
||||
MULTI_SIO_AREA_SIZE = (OFS_MS_RECV_BUF + MULTI_SIO_PACKET_SIZE * 3 * MULTI_SIO_PLAYERS_MAX)
|
||||
@ Structure Size
|
1412
data/data_1.s
1412
data/data_1.s
File diff suppressed because it is too large
Load Diff
1385
data/data_2.s
Normal file
1385
data/data_2.s
Normal file
File diff suppressed because it is too large
Load Diff
7
data/data_3.s
Normal file
7
data/data_3.s
Normal file
@ -0,0 +1,7 @@
|
||||
.include "asm/macros.inc"
|
||||
.include "constants/constants.inc"
|
||||
|
||||
.section .rodata
|
||||
|
||||
gUnk_08D6096C:: @ 08D6096C
|
||||
.incbin "baserom.gba", 0xD6096C, 0x0000010
|
@ -4,7 +4,10 @@
|
||||
.section .rodata
|
||||
|
||||
gUnk_08D72194:: @ 08D72194
|
||||
.incbin "baserom.gba", 0xD72194, 0x01C0F10
|
||||
.incbin "baserom.gba", 0xD72194, 0x01C0C00
|
||||
|
||||
gUnk_08F330A4:: @ 08F330A4
|
||||
.incbin "baserom.gba", 0xF330A4, 0x0000004
|
||||
gUnk_08F32D94:: @ 08F32D94
|
||||
.incbin "baserom.gba", 0xF32D94, 0x0000008
|
||||
|
||||
gUnk_08F32D9C:: @ 08F32D9C
|
||||
.incbin "baserom.gba", 0xF32D9C, 0x000001C
|
||||
|
100
include/agb_sram.h
Normal file
100
include/agb_sram.h
Normal file
@ -0,0 +1,100 @@
|
||||
#ifndef GUARD_AGB_SRAM_H
|
||||
#define GUARD_AGB_SRAM_H
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#define SRAM 0x0E000000
|
||||
|
||||
#ifndef __SRAM_DEBUG
|
||||
#define SRAM_ADR 0x0e000000 // SRAM Start Address
|
||||
#define SRAM_SIZE_256K 0x00008000 // 256KSRAM
|
||||
#define SRAM_SIZE_512K 0x00010000 // 512KSRAM
|
||||
#else
|
||||
#define SRAM_ADR 0x02018000
|
||||
#define SRAM_SIZE_256K 0x00000400
|
||||
#define SRAM_SIZE_512K 0x00000800
|
||||
#endif
|
||||
#define SRAM_RETRY_MAX 3 // Maximum retry number for the
|
||||
// WriteSramEx function
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
The function group in this header file was also used in the old version.
|
||||
The static variable area of the main unit WRAM is not used, but please
|
||||
note that compared to the function group AgbSramFast.h, access to
|
||||
SRAM is slower.
|
||||
--------------------------------------------------------------------*/
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Read Data */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern void ReadSram(const u8 *src,u8 *dst,u32 size) ;
|
||||
|
||||
/* From the SRAM address specified by the argument, read "size"
|
||||
byte of data to area starting from "dst" address in Work.
|
||||
<Arguments>
|
||||
const u8 *src : Read source SRAM address (Address on AGB memory map)
|
||||
u8 *dst : Address of work area where read data is stored
|
||||
(Address on AGB memory map)
|
||||
u32 size : Read size in bytes
|
||||
<Return Values>
|
||||
None
|
||||
*/
|
||||
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Write Data */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern void WriteSram(const u8 *src,u8 *dst,u32 size) ;
|
||||
|
||||
/* From the work area address specified by the argument, write "size"
|
||||
byte data to area starting from 'dst' address in SRAM.
|
||||
<Arguments>
|
||||
const u8 *src : Write source work area address
|
||||
u8 *dst : Write destination SRAM address
|
||||
(Address on AGB memory map)
|
||||
u32 size : Write size in bytes
|
||||
<Return Values>
|
||||
None
|
||||
*/
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Verify Data */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern u32 VerifySram(const u8 *src,u8 *tgt,u32 size) ;
|
||||
|
||||
/* Verify "size" byte of data from "src" address in the work area
|
||||
and "tgt" address in SRAM.
|
||||
If verify ends normally this function returns 0, if a verify error
|
||||
occurs and the address where the error occurred is returned.
|
||||
<Arguments>
|
||||
const u8 *src : Pointer to verify source work area address (original data)
|
||||
u8 *tgt : Pointer to verify target SRAM address
|
||||
(write destination data, address on AGB memory map)
|
||||
u32 size : Verify size in bytes
|
||||
<Return Values>
|
||||
u32 errorAdr : Normal end => 0
|
||||
Verify error => Error address on device side
|
||||
*/
|
||||
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Write data & Verify */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern u32 WriteSramEx(const u8 *src, u8 *dst, u32 size) ;
|
||||
|
||||
/* This function writes internally using WriteSram and then verifies using VerifySram.
|
||||
In case of an error, it retries a maximum of SRAM_RETRY_MAX times (defined by AgbSram.h).
|
||||
|
||||
<Argument>
|
||||
const u8 *src : Work area address of write source
|
||||
u8 *dst : SRAM address of write destination (address on AGB memory map)
|
||||
u32 size : Write size in number of bytes
|
||||
<Return value>
|
||||
u32 errorAdr : Normal end => 0
|
||||
Verify error => Error address on device side
|
||||
*/
|
||||
|
||||
#endif // GUARD_AGB_SRAM_H
|
@ -14,6 +14,9 @@
|
||||
#define EWRAM_DATA __attribute__((section("ewram_data")))
|
||||
#endif
|
||||
|
||||
#define NAKED __attribute__((naked))
|
||||
#define UNUSED __attribute__((unused))
|
||||
|
||||
#define ALIGNED(n) __attribute__((aligned(n)))
|
||||
|
||||
#define SOUND_INFO_PTR (*(struct SoundInfo **)0x3007FF0)
|
||||
@ -86,7 +89,6 @@
|
||||
#define RGB_CYAN RGB(0, 31, 31)
|
||||
#define RGB_WHITEALPHA (RGB_WHITE | 0x8000)
|
||||
|
||||
#define NAKED __attribute__((naked))
|
||||
#define UNUSED __attribute__((unused))
|
||||
#define SYSTEM_CLOCK (16 * 1024 * 1024) // System Clock
|
||||
|
||||
#endif // GUARD_GBA_DEFINES
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "defines.h"
|
||||
#include "io_reg.h"
|
||||
#include "types.h"
|
||||
#include "multiboot.h"
|
||||
#include "multi_boot.h"
|
||||
#include "syscall.h"
|
||||
#include "macro.h"
|
||||
#include "isagbprint.h"
|
||||
|
@ -667,20 +667,40 @@
|
||||
#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_SCK_OUT 0x0000 // Select external clock
|
||||
#define SIO_SCK_IN 0x0001 // Select internal clock
|
||||
#define SIO_IN_SCK_256K 0x0000 // Select internal clock 256KHz
|
||||
#define SIO_IN_SCK_2M 0x0002 // Select 2MHz
|
||||
#define SIO_ACK_RECV 0x0004 // Request transfer
|
||||
#define SIO_ACK_SEND 0x0008 // Enable transfer
|
||||
#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_MULTI_CONNECT 0x0004 // Connecting multi-play communication
|
||||
#define SIO_MULTI_DISCONNECT 0x0000 // Disconnect
|
||||
#define SIO_MULTI_PARENT 0x0008 // Multi-play communication Connect master
|
||||
#define SIO_MULTI_CHILD 0x0000 // Connect slave
|
||||
#define SIO_MULTI_SI 0x0004 // Multi-play communication SI terminal
|
||||
#define SIO_MULTI_SD 0x0008 // SD terminal
|
||||
#define SIO_MULTI_BUSY 0x0080 // Multi-play communicating
|
||||
#define SIO_CTS_ENABLE 0x0004 // Enable UART send enable signal
|
||||
#define SIO_UART_7BIT 0x0000 // UART communication data length 7 bit
|
||||
#define SIO_UART_8BIT 0x0080 // 8 bit
|
||||
|
||||
#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_PARITY_ENABLE 0x0200 // Enable parity
|
||||
#define SIO_PARITY_EVEN 0x0000 // Even parity
|
||||
#define SIO_PARITY_ODD 0x0008 // Odd parity
|
||||
#define SIO_TRANS_ENABLE 0x0400 // Enable transmitter
|
||||
#define SIO_TRANS_DATA_FULL 0x0010 // Transmitted data full
|
||||
#define SIO_RECV_ENABLE 0x0800 // Enable receiver
|
||||
#define SIO_RECV_DATA_EMPTY 0x0020 // No data received
|
||||
#define SIO_IF_ENABLE 0x4000 // Enable interrupt request
|
||||
|
||||
#define SIO_MULTI_SI_SHIFT 2
|
||||
#define SIO_MULTI_SI_MASK 0x1
|
||||
|
@ -100,7 +100,7 @@ struct CgbChannel
|
||||
u8 le;
|
||||
u8 sw;
|
||||
u32 fr;
|
||||
u32 * wp;
|
||||
u32 *wp;
|
||||
u32 cp;
|
||||
u32 tp;
|
||||
u32 pp;
|
||||
@ -182,8 +182,8 @@ struct SoundInfo
|
||||
void (*CgbOscOff)(u8);
|
||||
u32 (*MidiKeyToCgbFreq)(u8, u8, u8);
|
||||
u32 MPlayJumpTable;
|
||||
u32 plynote;
|
||||
u32 ExtVolPit;
|
||||
void *plynote;
|
||||
void (*ExtVolPit)(void);
|
||||
u8 gap2[16];
|
||||
struct SoundChannel chans[MAX_DIRECTSOUND_CHANNELS];
|
||||
s8 pcmBuffer[PCM_DMA_BUF_SIZE * 2];
|
||||
@ -199,38 +199,6 @@ struct SongHeader
|
||||
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
|
||||
@ -334,21 +302,10 @@ struct Song
|
||||
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[];
|
||||
@ -357,6 +314,7 @@ typedef void (*XcmdFunc)(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
||||
extern const XcmdFunc gXcmdTable[];
|
||||
|
||||
extern struct CgbChannel gCgbChans[];
|
||||
extern const u8 gCgb3Vol[];
|
||||
|
||||
extern const u8 gScaleTable[];
|
||||
extern const u32 gFreqTable[];
|
||||
@ -366,10 +324,6 @@ 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[];
|
||||
|
||||
@ -398,7 +352,7 @@ void MPlayOpen(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track
|
||||
void CgbSound(void);
|
||||
void CgbOscOff(u8);
|
||||
u32 MidiKeyToCgbFreq(u8, u8, u8);
|
||||
void DummyFunc(void);
|
||||
void nullsub_141(void);
|
||||
void MPlayJumpTableCopy(void **mplayJumpTable);
|
||||
void SampleFreqSet(u32 freq);
|
||||
void m4aSoundVSyncOn(void);
|
||||
@ -412,18 +366,6 @@ 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);
|
||||
int 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 *);
|
||||
|
106
include/gba/multi_boot.h
Normal file
106
include/gba/multi_boot.h
Normal file
@ -0,0 +1,106 @@
|
||||
#ifndef GUARD_GBA_MULTI_BOOT_H
|
||||
#define GUARD_GBA_MULTI_BOOT_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]; // Can be rewritten within system call.
|
||||
// Used with library also.
|
||||
u8 handshake_data; // Handshake data from client
|
||||
u8 padding;
|
||||
u16 handshake_timeout; // Handshake timeout check counter
|
||||
u8 probe_count; // If not 0, during client recognition or
|
||||
// boot program transfer
|
||||
u8 client_data[MULTIBOOT_NCHILD]; // Handshake data from client
|
||||
u8 palette_data; // Palette's flashing parameter during load
|
||||
// for client
|
||||
u8 response_bit; // When high probability that slave
|
||||
// connected, 4P-2P: d3-d1 is 1.
|
||||
u8 client_bit; // For slave distinguished as client,
|
||||
// 4P-2P: d3-d1 is 1.
|
||||
u8 reserved1; // Reserved
|
||||
const u8 *boot_srcp; // Boot program start (after header)
|
||||
const u8 *boot_endp; // Boot program end pointer
|
||||
const u8 *masterp; // Pointer to header referenced and output
|
||||
// by master
|
||||
u8 *reserved2[MULTIBOOT_NCHILD]; // Reserved
|
||||
u32 system_work2[4]; // Can be rewritten within system call.
|
||||
u8 sendflag; // If SC7=1 and during send, not 0
|
||||
u8 probe_target_bit; // If target recognized with client,
|
||||
// 4P-2P: d3-d1 is 1.
|
||||
u8 check_wait; // Wait frame until recoginition with client
|
||||
u8 server_type; // client recognize method 0= Low Speed
|
||||
// 1= High Speed
|
||||
};
|
||||
|
||||
/* Error Code
|
||||
* If value returned by MultiBootMain() is not 0, an error listed
|
||||
* below has occurred. However, there is no need to have separate error
|
||||
* messages for all error code types.
|
||||
* "Communication Error. Please check connection. Retry with START."
|
||||
* "Turn off power, check connection, and turn on again."
|
||||
* "Slave is not connected."
|
||||
* "Cannot recognize the slave."
|
||||
* ,etc. Messages easy for the player to understand are good.
|
||||
* NO_PROBE_TARGET: When recognizing client all machines returned
|
||||
* abnormal data and there is no target.
|
||||
* NO_DLREADY: client did not return a download preparations
|
||||
* possible message.
|
||||
* BOOT_FAILURE: MultiBoot() system call returned an error.
|
||||
* HANDSHAKE_FAILURE: Failed to do handshake with master which should
|
||||
* occur immediately after boot of slave.
|
||||
* (Slave may be in infinite loop, request that power be turned off
|
||||
* and on again.)
|
||||
*/
|
||||
#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
|
||||
|
||||
/* After an error, or when a value other than 0xffff is returned,
|
||||
* the avoid chattering wait(frames) until redo connection check.
|
||||
* The client timeout is about 11 frames so use value sufficiently
|
||||
* longer than this.
|
||||
* Usually during this time the MASTER_INFO is sent, but when there
|
||||
* is a system call error, nothing is sent at this time and it waits.
|
||||
* Then, during this time period MASTER_INFO is sent.
|
||||
*/
|
||||
#define MULTIBOOT_CONNECTION_CHECK_WAIT 15
|
||||
|
||||
/* Recognition of Slave
|
||||
* Value set in MultiBootParam structure member server_type
|
||||
* MULTIBOOT_SERVER_TYPE_NORMAL: Slow speed recognition mode
|
||||
* The MultiBootMain() function communicates 2 bytes with one call.
|
||||
* Therefore, processing returns from MultiBootMain() function
|
||||
* in short time.
|
||||
* MULTIBOOT_SERVER_TYPE_QUICK: High speed recognition mode
|
||||
* In MultiBootMain() function as many consecutive communications
|
||||
* are done as possible.
|
||||
* Therefore, processing may not return from MultiBootMain() for
|
||||
* several dozen frames.
|
||||
* During this time, there is no problem if processing for sound and
|
||||
* display cannot be done. If processing for sound and display is
|
||||
* done with timer interrupt processing, you can use.
|
||||
*/
|
||||
#define MULTIBOOT_SERVER_TYPE_NORMAL 0
|
||||
#define MULTIBOOT_SERVER_TYPE_QUICK 1
|
||||
|
||||
/* Timeout for slave's final start up check 400 frames */
|
||||
#define MULTIBOOT_HANDSHAKE_TIMEOUT 400
|
||||
|
||||
#endif // GUARD_GBA_MULTI_BOOT_H
|
@ -1,55 +0,0 @@
|
||||
#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];
|
||||
u8 handshake_data;
|
||||
u8 padding;
|
||||
u16 handshake_timeout;
|
||||
u8 probe_count;
|
||||
u8 client_data[MULTIBOOT_NCHILD];
|
||||
u8 palette_data;
|
||||
u8 response_bit;
|
||||
u8 client_bit;
|
||||
u8 reserved1;
|
||||
const u8 *boot_srcp;
|
||||
const u8 *boot_endp;
|
||||
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
|
@ -142,6 +142,31 @@ struct ObjAffineSrcData
|
||||
u16 rotation;
|
||||
};
|
||||
|
||||
// Normal SIO Control Structure
|
||||
struct SioNormalCnt
|
||||
{
|
||||
u16 sck_I_O:1; // Clock I/O Select
|
||||
u16 sck:1; // Internal Clock Select
|
||||
u16 ackRecv:1; // Transfer Enable Flag Receive
|
||||
u16 ackSend:1; // Transfer Enable Flag Send
|
||||
u16 unused_6_4:3;
|
||||
u16 enable:1; // SIO Enable
|
||||
u16 unused_11_8:4;
|
||||
u16 mode:2; // Communication Mode Select
|
||||
u16 ifEnable:1; // Interrupt Request Enable
|
||||
u16 unused_15:1;
|
||||
u8 data; // Data
|
||||
u8 unused_31_24;
|
||||
};
|
||||
|
||||
#define ST_SIO_8BIT_MODE 0 // Normal 8-bit communication mode
|
||||
#define ST_SIO_32BIT_MODE 1 // Normal 32-bit communication mode
|
||||
|
||||
#define ST_SIO_SCK_OUT 0 // Select external clock
|
||||
#define ST_SIO_SCK_IN 1 // Select internal clock
|
||||
#define ST_SIO_IN_SCK_256K 0 // Select internal clock 256KHz
|
||||
#define ST_SIO_IN_SCK_2M 1 // Select 2MHz
|
||||
|
||||
// Multi-player SIO Control Structure
|
||||
struct SioMultiCnt
|
||||
{
|
||||
@ -153,17 +178,91 @@ struct SioMultiCnt
|
||||
u16 enable:1; // SIO enable
|
||||
u16 unused_11_8:4;
|
||||
u16 mode:2; // communication mode (should equal 2)
|
||||
u16 intrEnable:1; // IRQ enable
|
||||
u16 ifEnable:1; // IRQ enable
|
||||
u16 unused_15:1;
|
||||
u16 data; // data
|
||||
};
|
||||
|
||||
#define ST_SIO_MULTI_MODE 2 // Multi-player communication mode
|
||||
#define ST_SIO_MULTI_MODE 2 // Multi-play 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
|
||||
#define ST_SIO_9600_BPS 0 // Baud rate 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
|
||||
#define ST_SIO_MULTI_PARENT 1 // Multi-play communication Connect master
|
||||
#define ST_SIO_MULTI_CHILD 0 // Connect slave
|
||||
|
||||
// UART - SIO Control Structure
|
||||
struct SioUartCnt
|
||||
{
|
||||
u16 baudRate:2; // Baud Rate
|
||||
u16 ctsEnable:1; // Send Signal Enable
|
||||
u16 paritySelect:1; // Parity Even/Odd
|
||||
u16 transDataFull:1; // Transmit Data Full
|
||||
u16 recvDataEmpty:1; // Receive Data Empty
|
||||
u16 error:1; // Error Detect
|
||||
u16 length:1; // Data Length
|
||||
u16 fifoEnable:1; // FIFO Enable
|
||||
u16 parityEnable:1; // Parity Enable
|
||||
u16 transEnable:1; // Transmitter Enable
|
||||
u16 recvEnable:1; // Receiver Enable
|
||||
u16 mode:2; // Communication Mode Select
|
||||
u16 ifEnable:1; // Interrupt Request Enable
|
||||
u16 unused_15:1;
|
||||
u8 data; // Data
|
||||
u8 unused_31_24;
|
||||
};
|
||||
|
||||
#define ST_SIO_UART_MODE 3 // UART communication mode
|
||||
|
||||
#define ST_SIO_UART_7BIT 0 // UART communication data length 7 bits
|
||||
#define ST_SIO_UART_8BIT 1 // 8 bits
|
||||
#define ST_SIO_PARITY_EVEN 0 // Even parity
|
||||
#define ST_SIO_PARITY_ODD 1 // Odd parity
|
||||
|
||||
// JOY Bus Communication Control Structure
|
||||
struct JoyCnt
|
||||
{
|
||||
u8 ifReset:1; // JOY Bus Reset Interrupt Request
|
||||
u8 ifRecv:1; // JOY Bus Received Interrupt Request
|
||||
u8 ifSend:1; // JOY Bus Sent Interrupt Request
|
||||
u8 unused_5_3:3;
|
||||
u8 ifEnable:1; // Interrupt Request Enable
|
||||
u8 unused_7:1;
|
||||
};
|
||||
|
||||
// JOY Bus Communication Status Structure
|
||||
struct JoyStat
|
||||
{
|
||||
u8 unused_0:1;
|
||||
u8 recv:1; // Receive Status
|
||||
u8 unused_2:1;
|
||||
u8 send:1; // Send Status
|
||||
u8 flags:2; // General Flag
|
||||
u8 unused_7_6:2;
|
||||
};
|
||||
|
||||
// General Input/Output Control Structure
|
||||
struct RCnt
|
||||
{
|
||||
u8 sc:1; // Data
|
||||
u8 sd:1;
|
||||
u8 si:1;
|
||||
u8 so:1;
|
||||
u8 sc_i_o:1; // I/O Select
|
||||
u8 sd_i_o:1;
|
||||
u8 si_i_o:1;
|
||||
u8 so_i_o:1;
|
||||
u8 ifEnable:1; // Interrupt Request Enable
|
||||
u8 unused_13_9:5;
|
||||
u8 sioModeMaster:2; // SIO Mode Master
|
||||
};
|
||||
|
||||
#define ST_R_SIO_MASTER_MODE 0 // SIO master mode
|
||||
#define ST_R_DIRECT_MODE 2 // General input/output communication mode
|
||||
#define ST_R_JOY_MODE 3 // JOY communication mode
|
||||
|
||||
#define ST_R_IN 0 // Select input
|
||||
#define ST_R_OUT 1 // Select output
|
||||
|
||||
#endif // GUARD_GBA_TYPES_H
|
||||
|
99
include/multi_boot.h
Normal file
99
include/multi_boot.h
Normal file
@ -0,0 +1,99 @@
|
||||
#ifndef GUARD_MULTI_BOOT_H
|
||||
#define GUARD_MULTI_BOOT_H
|
||||
|
||||
#include "global.h"
|
||||
|
||||
/* From MASTER_INFO to MASTER_START_DL are upper values.
|
||||
* From MASTER_REQUEST_CRC to MASTER_VERIFY_CRC are lower values (Upper=0)
|
||||
*/
|
||||
#define MULTIBOOT_MASTER_INFO 0x62
|
||||
#define MULTIBOOT_CLIENT_INFO 0x72
|
||||
#define MULTIBOOT_MASTER_START_PROBE 0x61
|
||||
#define MULTIBOOT_MASTER_REQUEST_DLREADY 0x63
|
||||
#define MULTIBOOT_CLIENT_DLREADY 0x73
|
||||
#define MULTIBOOT_MASTER_START_DL 0x64
|
||||
#define MULTIBOOT_MASTER_REQUEST_CRC 0x65
|
||||
#define MULTIBOOT_CLIENT_CALC_CRC 0x74
|
||||
#define MULTIBOOT_CLIENT_CRCREADY 0x75
|
||||
#define MULTIBOOT_MASTER_VERIFY_CRC 0x66
|
||||
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Initialize Multi-play Boot */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern void MultiBootInit(struct MultiBootParam *mp);
|
||||
|
||||
//* Sets serial communication mode as multi-play mode.
|
||||
//* Basically, SIO_INTR_FLAG of IE is cleared, however it is acceptable to use SIO interrupt.
|
||||
//
|
||||
//* does not set mp -> masterp.
|
||||
// Make sure to set up before calling this initialization function.
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Multi-play Boot Main */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern s32 MultiBootMain(struct MultiBootParam *mp);
|
||||
|
||||
//* Basically, call it once per frame.
|
||||
// However, if there is a wait long enough, it is acceptable to call it multiple times per frame.
|
||||
// The safe length of wait time depends on the application.
|
||||
// (It is necessary to make the wait longer than the time it takes to process the interrupts of long period of time,
|
||||
// including V-Blank interrupts.)
|
||||
//
|
||||
//* Returns 0 in normal completion.
|
||||
//
|
||||
//* Returns 0 when transfer ends (successfully) and a value of MultiBootCheckComplete() other than 0.
|
||||
//
|
||||
//* Once it is in the transfer end status, it simply returns 0 immediately.
|
||||
// In order to cancel this status, call MultiBootInit().
|
||||
// It is acceptable to call MultiBootStartProbe() or MultiBootStartMaster(), however, they are internally
|
||||
// calling MultiBootInit().
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Starts Client Recognition */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern void MultiBootStartProbe(struct MultiBootParam *mp);
|
||||
|
||||
// After calling this, the client's recognition processing is done with // MultiBootMain().
|
||||
// Call after verifying mp -> probe_count is 0.
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Starts Transfer from Master Server */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern void MultiBootStartMaster(struct MultiBootParam *mp, const u8 *srcp, s32 length, u8 palette_color, s8 palette_speed);
|
||||
|
||||
//* Among the units connected by multi-play communication cable, only those units with game pak inserted
|
||||
// can become master server.
|
||||
//
|
||||
// srcp Pointer for the program that you want to boot
|
||||
// (requires 4-byte alignment)
|
||||
// For clients, it is downloaded immediately after the header.
|
||||
// length Transfer byte count of program.
|
||||
// MULTIBOOT_SEND_SIZE_MIN (0x100) bytes or more and
|
||||
// MULTIBOOT_SEND_SIZE_MAX (0x40000) bytes or less.
|
||||
// "palette_color" and "palette_speed" are palette flash parameters of client while loading.
|
||||
// palette_color uses 0 to 6 to specify the basic palettes (7 types)
|
||||
// With "palette_speed", it flashes in reversal order from -4 to -1 (-4 being the fastest) and it flashes in normal
|
||||
// from +1 to +4 (+4 being the fastest)
|
||||
// Palette is fixed (no flash) at 0.
|
||||
// Do not specify any values other than listed above.
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Check Transfer Completion */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern s32 MultiBootCheckComplete(struct MultiBootParam *mp);
|
||||
|
||||
//* Check if transfer has completed.
|
||||
//
|
||||
//* Returns a value other than 0 if transfer has completed (successfully).
|
||||
// Returns 0 if it is still recognizing, has not started transfer, or transfer has failed.
|
||||
//
|
||||
//* Calling any one of MultiBootInit(), MultiBootStartProbe() or MultiBootStartMaster()
|
||||
// cancels the transfer completion status.
|
||||
|
||||
#endif // GUARD_MULTI_BOOT_H
|
264
include/multi_sio.h
Normal file
264
include/multi_sio.h
Normal file
@ -0,0 +1,264 @@
|
||||
#ifndef GUARD_MULTI_SIO_H
|
||||
#define GUARD_MULTI_SIO_H
|
||||
|
||||
#include "global.h"
|
||||
|
||||
// Optimize the following settings based on the software specifications
|
||||
|
||||
#define MULTI_SIO_BLOCK_SIZE 20 // Communication Data Block Size (Max. 24 Bytes)
|
||||
|
||||
#define MULTI_SIO_PLAYERS_MAX 4 // Maximum Number of Players
|
||||
|
||||
#define MULTI_SIO_SYNC_DATA 0xfefe // Synchronized Data (0x0000/0xfffa~0xffff prohibited)
|
||||
|
||||
// Comment out if no space in CPU internal Work RAM
|
||||
#define MULTI_SIO_DI_FUNC_FAST // SIO Interrupt Prohibit Function High Speed Flag (CPU Internal RAM Execution)
|
||||
|
||||
|
||||
// Update if maximum delay for communication interrupt is larger than following.
|
||||
#define MULTI_SIO_INTR_DELAY_MAX 2000 // Communication Interrupt Allowed Delay Clocks
|
||||
|
||||
#ifdef MULTI_SIO_DI_FUNC_FAST
|
||||
#define MULTI_SIO_INTR_CLOCK_MAX 400 // Communication Interrupt Processing Maximum Clocks
|
||||
#else
|
||||
#define MULTI_SIO_INTR_CLOCK_MAX 1000
|
||||
#endif
|
||||
|
||||
#define MULTI_SIO_1P_SEND_CLOCKS 3000 // Communication Time for 1 unit
|
||||
|
||||
#if MULTI_SIO_PLAYERS_MAX == 4
|
||||
#define MULTI_SIO_START_BIT_WAIT 0 // Start Bit Wait Time
|
||||
#else
|
||||
#define MULTI_SIO_START_BIT_WAIT 512
|
||||
#endif
|
||||
|
||||
// During development set NDEBUG to undefined and value below to 0,
|
||||
// define with last check and confirm operation with changed to 600.
|
||||
// (Even if increase setting the communication interval increases, but
|
||||
// processing doesn't slow).
|
||||
//#define NDEBUG // Can define with Makefile (MakefileDemo)
|
||||
#ifdef NDEBUG
|
||||
#define MULTI_SIO_INTR_MARGIN 600 // Communication Interrupt Error Guarantee Value
|
||||
#else
|
||||
#define MULTI_SIO_INTR_MARGIN 0
|
||||
#endif
|
||||
|
||||
|
||||
#define MULTI_SIO_BAUD_RATE 115200 // Baud Rate
|
||||
#define MULTI_SIO_BAUD_RATE_NO SIO_115200_BPS // Baud Rate No.
|
||||
|
||||
|
||||
#define MULTI_SIO_TIMER_NO 3 // Timer No.
|
||||
#define MULTI_SIO_TIMER_INTR_FLAG (INTR_FLAG_TIMER0 << MULTI_SIO_TIMER_NO)
|
||||
|
||||
#define REG_MULTI_SIO_TIMER (*(vu32 *)(REG_ADDR_TMCNT + (MULTI_SIO_TIMER_NO * 4)))
|
||||
#define REG_MULTI_SIO_TIMER_L (*(vu16 *)(REG_ADDR_TMCNT_L + (MULTI_SIO_TIMER_NO * 4)))
|
||||
#define REG_MULTI_SIO_TIMER_H (*(vu16 *)(REG_ADDR_TMCNT_H + (MULTI_SIO_TIMER_NO * 4)))
|
||||
// Timer Register
|
||||
|
||||
// Timer count number is calculated from communication data block size.
|
||||
#define MULTI_SIO_TIMER_COUNT_TMP (SYSTEM_CLOCK / 60 / ((2 + 4 + MULTI_SIO_BLOCK_SIZE + 6) / (16 / 8)))
|
||||
// Timer Count Temporary Value
|
||||
#define MULTI_SIO_TIMER_COUNT_MIN ( MULTI_SIO_1P_SEND_CLOCKS * MULTI_SIO_PLAYERS_MAX \
|
||||
+ MULTI_SIO_START_BIT_WAIT + MULTI_SIO_INTR_MARGIN \
|
||||
+ MULTI_SIO_INTR_DELAY_MAX + MULTI_SIO_INTR_CLOCK_MAX)
|
||||
// Timer Count Minimum Value
|
||||
#define MULTI_SIO_TIMER_COUNT_MAX 0x10000 // Timer Count Maximum Value
|
||||
#define MULTI_SIO_TIMER_COUNT (MULTI_SIO_TIMER_COUNT_MAX - MULTI_SIO_TIMER_COUNT_TMP)
|
||||
// Timer Count
|
||||
// Timer Count Setting Error
|
||||
#if MULTI_SIO_TIMER_COUNT_TMP < MULTI_SIO_TIMER_COUNT_MIN
|
||||
#error MULTI_SIO_TIMER_COUNT is too short,
|
||||
#error because MULTI_SIO_BLOCK_SIZE or MULTI_SIO_INTR_DELAY_MAX is too large.
|
||||
#elif MULTI_SIO_TIMER_COUNT_TMP > MULTI_SIO_TIMER_COUNT_MAX
|
||||
#error MULTI_SIO_TIMER_COUNT is too long.
|
||||
#endif
|
||||
|
||||
// Multi-play Communication Packet Structure
|
||||
struct MultiSioPacket
|
||||
{
|
||||
u8 frameCounter; // Frame Counter
|
||||
u8 recvErrorFlags:4; // Receive Error Flag
|
||||
u8 loadRequest:1; // Load Request
|
||||
u8 downloadSuccessFlag:1; // Download Success Flag
|
||||
u8 loadSuccessFlag:1; // Load Success
|
||||
u8 reserved_0:1; // Reserved
|
||||
u16 checkSum; // Checksum
|
||||
u16 data[MULTI_SIO_BLOCK_SIZE / 2]; // Communication Data
|
||||
u16 overrunCatch[2]; // Overrun Protect Area
|
||||
};
|
||||
|
||||
// Multi-play Communication Work Area Structure
|
||||
struct MultiSioArea
|
||||
{
|
||||
u8 type; // Connection (Master/Slave)
|
||||
u8 state; // Communication Function State
|
||||
u8 connectedFlags; // Connection History Flag
|
||||
u8 recvSuccessFlags; // Receive Success Flag
|
||||
|
||||
u8 syncRecvFlag[4]; // Receive Confirmation Flag
|
||||
|
||||
u8 downloadSuccessFlags:4; // Download Success Flag
|
||||
u8 loadEnable:1; // Enable Load
|
||||
u8 loadRequest:1; // Load Request
|
||||
u8 loadSuccessFlag:1; // Load Success
|
||||
u8 startFlag:1; // Communication Start Flag
|
||||
|
||||
u8 hardError; // Hard error
|
||||
u8 recvFlagsAvailableCounter; // Receiving success flag validation counter
|
||||
|
||||
u8 sendFrameCounter; // Send Frame Counter
|
||||
u8 recvFrameCounter[4][2]; // Receive Frame Counter
|
||||
|
||||
s32 sendBufCounter; // Send Buffer Counter
|
||||
s32 recvBufCounter[4]; // Receive Buffer Counter
|
||||
|
||||
u16 *nextSendBufp; // Send Buffer Pointer
|
||||
u16 *currentSendBufp;
|
||||
u16 *currentRecvBufp[4]; // Receive Buffer Pointer
|
||||
u16 *lastRecvBufp[4];
|
||||
u16 *recvCheckBufp[4];
|
||||
|
||||
struct MultiSioPacket sendBuf[2]; // Send Buffer (Double Buffer)
|
||||
struct MultiSioPacket recvBuf[MULTI_SIO_PLAYERS_MAX][3];
|
||||
// Receive Buffer (Triple Buffer)
|
||||
};
|
||||
|
||||
extern u32 gMultiSioRecvFuncBuf[0x40 / 4]; // Receive Data/Check Buffer Change Routine RAM Execution Buffer
|
||||
extern u32 gMultiSioIntrFuncBuf[0x180 / 4]; // Interrupt Routine RAM Execution Buffer
|
||||
|
||||
extern struct MultiSioArea gMultiSioArea; // Multi-play Communication Work Area
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Multi-play Communication Initialization */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern void MultiSioInit(u32 connectedFlags);
|
||||
|
||||
//* Set serial communication mode to multi-play mode.
|
||||
//* Initialize register and buffer.
|
||||
//* Arguments:
|
||||
// u32 connectedFlags Set appropriate flag if a unit recognized as connected
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Start Multi-play Communication */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
void MultiSioStart(void);
|
||||
|
||||
//* If following master recognition set flag to start send.
|
||||
//* If slave or prior to master recognition do nothing.
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Stop Multi-play Communication */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
void MultiSioStop(void);
|
||||
|
||||
//* Stop Communication
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Multi-play Communication Main */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern u32 MultiSioMain(void *sendp, void *recvp, u32 loadRequest);
|
||||
|
||||
//* First determine if master or slave. If master recognized, initialize
|
||||
// timer.
|
||||
//* Call MultiSioSendDataSet() and set send data.
|
||||
//* Call MultiSioRecvDataCheck() and check if normal receive done,
|
||||
// and copy receive data to Recvp.
|
||||
//
|
||||
//* Set so called with as close a timing as possible within 1 frame.
|
||||
//* Safer not to send data that matches flag data (SIO_SYNC_DATA) prior
|
||||
// to connection determination.
|
||||
//
|
||||
//* Arguments:
|
||||
// void *sendp User Send Buffer Pointer
|
||||
// void *recvp User Receive Buffer Pointer
|
||||
// u32 loadRequest Load Request
|
||||
|
||||
//* Return Value:
|
||||
|
||||
#define MULTI_SIO_RECV_ID_MASK 0x000f // Receive Success Flag
|
||||
#define MULTI_SIO_CONNECTED_ID_MASK 0x0f00 // Connection History Flag
|
||||
|
||||
#define MULTI_SIO_RECV_ID0 0x0001 // Receive Success Flag Master
|
||||
#define MULTI_SIO_RECV_ID1 0x0002 // Slave 1
|
||||
#define MULTI_SIO_RECV_ID2 0x0004 // Slave 2
|
||||
#define MULTI_SIO_RECV_ID3 0x0008 // Slave 3
|
||||
#define MULTI_SIO_LD_ENABLE 0x0010 // Enable Load
|
||||
#define MULTI_SIO_LD_REQUEST 0x0020 // Load Request
|
||||
#define MULTI_SIO_LD_SUCCESS 0x0040 // Load Success
|
||||
#define MULTI_SIO_TYPE 0x0080 // Connection (Master/Slave)
|
||||
#define MULTI_SIO_PARENT 0x0080 // Master Connection
|
||||
#define MULTI_SIO_CHILD 0x0000 // Slave Connection
|
||||
#define MULTI_SIO_CONNECTED_ID0 0x0100 // Connection History Flag Master
|
||||
#define MULTI_SIO_CONNECTED_ID1 0x0200 // Slave 1
|
||||
#define MULTI_SIO_CONNECTED_ID2 0x0400 // Slave 2
|
||||
#define MULTI_SIO_CONNECTED_ID3 0x0800 // Slave 3
|
||||
#define MULTI_SIO_UNK_x1000 0x1000
|
||||
#define MULTI_SIO_UNK_x2000 0x2000
|
||||
|
||||
|
||||
// Return Value Structure
|
||||
struct MultiSioReturn
|
||||
{
|
||||
u32 recvSuccessFlags:4; // Receive Success Flag
|
||||
u32 loadEnable:1; // Enable Load
|
||||
u32 loadRequest:1; // Load Request
|
||||
u32 loadSuccessFlag:1; // Load Success
|
||||
u32 type:1; // Connection (Master/Slave)
|
||||
u32 connectedFlags:4; // Connection History Flag
|
||||
u32 multisioreturn_unk00_0c:1;
|
||||
u32 multisioreturn_unk00_0d:1;
|
||||
};
|
||||
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Multi-play Communication Interrupt */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern void MultiSioIntr(void);
|
||||
|
||||
//* During communication interrupt, store receive data from each unit
|
||||
// in each receive buffer and set the send buffer data to the register.
|
||||
//* If master, reset timer and restart send.
|
||||
//
|
||||
//* Program so slave is called with communication interrupt and master
|
||||
// is called with timer interrupt.
|
||||
//* Adjust setting so 1 packet (Except for OverRunCatch[]) can be
|
||||
// transfered with 1 frame.
|
||||
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Set Send Data */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern void MultiSioSendDataSet(void *sendp, u32 loadReq);
|
||||
|
||||
//* Set the user send buffer data to send buffer.
|
||||
//
|
||||
//* Called from MultiSioMain().
|
||||
//* Not necessary to call directly.
|
||||
//
|
||||
//* Arguments:
|
||||
// void *sendp User Send Buffer Pointer
|
||||
// u32 loadReq Load Request
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Check Receive Data */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern u32 MultiSioRecvDataCheck(void *recvp);
|
||||
|
||||
//* Check if receive done normally. If normal, copy the receive data
|
||||
// to the user receive buffer.
|
||||
//
|
||||
//* Called from MultiSioMain().
|
||||
//* Do not need to call directly.
|
||||
//
|
||||
//* Arguments:
|
||||
// void *recvp User Receive Buffer Pointer
|
||||
|
||||
#endif // GUARD_MULTI_SIO_H
|
@ -1,17 +0,0 @@
|
||||
#ifndef GUARD_MULTIBOOT_H
|
||||
#define GUARD_MULTIBOOT_H
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#define MULTIBOOT_MASTER_INFO 0x62
|
||||
#define MULTIBOOT_CLIENT_INFO 0x72
|
||||
#define MULTIBOOT_MASTER_START_PROBE 0x61
|
||||
#define MULTIBOOT_MASTER_REQUEST_DLREADY 0x63
|
||||
#define MULTIBOOT_CLIENT_DLREADY 0x73
|
||||
#define MULTIBOOT_MASTER_START_DL 0x64
|
||||
#define MULTIBOOT_MASTER_REQUEST_CRC 0x65
|
||||
#define MULTIBOOT_CLIENT_CALC_CRC 0x74
|
||||
#define MULTIBOOT_CLIENT_CRCREADY 0x75
|
||||
#define MULTIBOOT_MASTER_VERIFY_CRC 0x66
|
||||
|
||||
#endif // GUARD_MULTIBOOT_H
|
141
include/sio32_multi_load.h
Normal file
141
include/sio32_multi_load.h
Normal file
@ -0,0 +1,141 @@
|
||||
#ifndef GUARD_SIO32_MULTI_LOAD_H
|
||||
#define GUARD_SIO32_MULTI_LOAD_H
|
||||
|
||||
#include "multi_sio.h"
|
||||
|
||||
// Optimize the following settings based on the software specifications
|
||||
|
||||
#define SIO32ML_BLOCK_SIZE 0x8000 // Communication Data Block Size
|
||||
|
||||
// Update if maximum delay for communication interrupt is larger than following.
|
||||
#define SIO32ML_INTR_DELAY_MAX 1000 // Communication Interrupt Allowed Delay Clocks
|
||||
|
||||
#define SIO32ML_INTR_CLOCK_MAX 256 // Communication Interrupt Processing Maximum Clocks
|
||||
|
||||
#define SIO32ML_SYNC_DATA 0xfefefefe // Synchronized Data (0x00000000and 0xffffffff prohibited)
|
||||
|
||||
#define SIO32ML_SYSTEM_CLOCK (16 * 1024 * 1024)// System Clock
|
||||
#define SIO32ML_SHIFT_CLOCK (256 * 1024) // Shift Clock
|
||||
#define SIO32ML_LINE_CLOCKS 1232 // Line Clocks
|
||||
|
||||
// Comment out if no space in CPU internal Work RAM
|
||||
#ifdef MULTI_SIO_DI_FUNC_FAST
|
||||
// #define SIO32ML_DI_FUNC_FAST // SIO Interrupt Prohibit Function High Speed Flag (CPU Internal RAM Execution)
|
||||
#endif
|
||||
|
||||
#define SIO32ML_TIMER_NO 3 // Timer No.
|
||||
#define SIO32ML_TIMER_INTR_FLAG (INTR_FLAG_TIMER0 << SIO32ML_TIMER_NO)
|
||||
// Timer Interrupt Flag
|
||||
|
||||
#define REG_SIO32ML_TIMER (*(vu32 *)(REG_ADDR_TMCNT + (SIO32ML_TIMER_NO * 4)))
|
||||
#define REG_SIO32ML_TIMER_L (*(vu16 *)(REG_ADDR_TMCNT_L + (SIO32ML_TIMER_NO * 4)))
|
||||
#define REG_SIO32ML_TIMER_H (*(vu16 *)(REG_ADDR_TMCNT_H + (SIO32ML_TIMER_NO * 4)))
|
||||
// Timer Register
|
||||
|
||||
// Timer count temporary value is calculated from communication data block size.
|
||||
#define SIO32ML_TIMER_COUNT_TMP (SIO32ML_SYSTEM_CLOCK / SIO32ML_SHIFT_CLOCK * 32 \
|
||||
+ SIO32ML_INTR_DELAY_MAX + SIO32ML_INTR_CLOCK_MAX)
|
||||
// Timer Count Temporary Value
|
||||
#define SIO32ML_TIMER_COUNT_MAX 0x10000 // Timer Count Maximum Value
|
||||
#define SIO32ML_TIMER_COUNT ((SIO32ML_TIMER_COUNT_TMP > SIO32ML_TIMER_COUNT_MAX) \
|
||||
? SIO32ML_TIMER_COUNT_MAX - SIO32ML_TIMER_COUNT_MAX \
|
||||
: SIO32ML_TIMER_COUNT_MAX - SIO32ML_TIMER_COUNT_TMP)
|
||||
// Timer Count
|
||||
|
||||
// Load timeout frames is calculated from above values.
|
||||
#define SIO32ML_MODE_WAIT_FRAMES 6 // SIO Mode Switch Wait Frames
|
||||
#define SIO32ML_LD_TIMEOUT_FRAMES (((SIO32ML_TIMER_COUNT_MAX - SIO32ML_TIMER_COUNT \
|
||||
+ SIO32ML_INTR_DELAY_MAX + SIO32ML_INTR_CLOCK_MAX) \
|
||||
* (SIO32ML_BLOCK_SIZE / 4)) / (SIO32ML_LINE_CLOCKS * 228) \
|
||||
+ SIO32ML_MODE_WAIT_FRAMES + 2)
|
||||
// Load timeout frames
|
||||
|
||||
|
||||
// 32bit Serial Communication Multi-load Work Area Structure
|
||||
struct Sio32MultiLoadArea
|
||||
{
|
||||
u8 type; // Connection (Master/Slave)
|
||||
u8 state; // Communication Function State
|
||||
u8 frameCounter; // Frame Counter
|
||||
u8 downloadSuccessFlag; // Download Success Flag
|
||||
|
||||
u32 *datap; // Data Pointer
|
||||
s32 dataCounter; // Data Counter
|
||||
|
||||
u32 checkSum; // Checksum
|
||||
u32 checkSumTmp;
|
||||
s32 checkSumCounter; // Checksum Counter
|
||||
};
|
||||
|
||||
extern struct Sio32MultiLoadArea gSio32MultiLoadArea; // 32bit Serial Communication Multi-load Work Area
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* 32bit Serial Communication Multi-load Intialization */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern void Sio32MultiLoadInit(u32 type, void *datap);
|
||||
|
||||
//* Initialize register and buffer.
|
||||
//* To avoid problem with shift clock synchronization set master to 256Kbps
|
||||
// 32 bit serial communication mode first.
|
||||
//
|
||||
//* 2Mbps communication with a cable is not guaranteed so do not set up.
|
||||
//* Set already connection already determined with multi-play communication
|
||||
// to Type.
|
||||
//* Do not pass VRAM address to Datap during display.
|
||||
// May fail with checksum of stored data.
|
||||
// Copy to VRAM after storing to work RAM once.
|
||||
// After this, possible overwrite program data to work RAM.
|
||||
//
|
||||
//* Arguments:
|
||||
// u32 type Connection (Master = Not 0/ Slave = 0)
|
||||
// void *datap Data Pointer (Master = Send Data/ Slave= Receive Buffer)
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* 32bit Serial Communication Multi-load Main */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern u32 Sio32MultiLoadMain(u32 *progressCounterp);
|
||||
|
||||
//* After 1 frame wait, set the slave to 256Kbps 32bit serial communication
|
||||
// mode. Also, until the slave's SIO mode is determined the waits and then
|
||||
// communication is started.
|
||||
//* Slave successively calculates receive data checksum, and checks when
|
||||
// receive complete.
|
||||
//* If receive is not completed at time when should be, end receive forcibly.
|
||||
//* After communication ends prohibit communication interrupts, and return
|
||||
// to multi-play communication mode.
|
||||
//
|
||||
//* Arguments:
|
||||
// u32 *progressCounterp Progress Counter Pointer
|
||||
// (Disabled when 0 specified)
|
||||
//* Return Value:
|
||||
// During communication = 0/ End = Not 0
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* 32bit Serial Communication Multi-load Interrupt Routine */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern void Sio32MultiLoadIntr(void);
|
||||
|
||||
//* Master does only send and slave only receive.
|
||||
//* Master resets timer during send.
|
||||
//* Slave stores receive data in order to receive buffer during
|
||||
// communication interrupt.
|
||||
// Lastly it stores checksum to work area.
|
||||
//
|
||||
//* Program so slave is called with communication interrupt and master
|
||||
// is called with timer interrupt.
|
||||
//* Data is passed with pipeline operation so delayed with slave with
|
||||
// large ID and then received. Therefore at a minimum need to send
|
||||
// two (8 Bytes) extra times.
|
||||
//
|
||||
//* Example:
|
||||
// ID 0 1 2 3
|
||||
// Data 0 -> 0 -> 0 -> 0
|
||||
// 1 -> 0 -> 0 -> 0
|
||||
// 2 -> 1 -> 0 -> 0
|
||||
// 3 -> 2 -> 1 -> 0
|
||||
// 4 -> 3 -> 2 -> 1
|
||||
|
||||
#endif // GUARD_SIO32_MULTI_LOAD_H
|
83
linker.ld
83
linker.ld
@ -1,5 +1,6 @@
|
||||
gNumMusicPlayers = 4;
|
||||
gMaxLines = 0;
|
||||
gUnk_02000000 = 0x2000000;
|
||||
|
||||
ENTRY(__start)
|
||||
|
||||
@ -11,7 +12,6 @@ MEMORY {
|
||||
|
||||
SECTIONS {
|
||||
ewram (NOLOAD) : ALIGN(4) {
|
||||
. = 0x00000000; gUnk_02000000 = .;
|
||||
. = 0x00000140; gUnk_02000140 = .;
|
||||
. = 0x00000F40; gUnk_02000F40 = .;
|
||||
. = 0x00008300; gUnk_02008300 = .;
|
||||
@ -116,15 +116,18 @@ SECTIONS {
|
||||
. = 0x00000008; gUnk_03000008 = .;
|
||||
. = 0x0000000C; gUnk_0300000C = .;
|
||||
. = 0x00000010; gUnk_03000010 = .;
|
||||
. = 0x00000014; gUnk_03000014 = .;
|
||||
. = 0x00000014; src/multi_boot.o(.bss);
|
||||
. = ALIGN(16);
|
||||
. = 0x00000020; gUnk_03000020 = .;
|
||||
. = 0x0000002C; gUnk_0300002C = .;
|
||||
. = 0x00000030; gUnk_03000030 = .;
|
||||
. = 0x00000034; gUnk_03000034 = .;
|
||||
. = 0x00000038; gUnk_03000038 = .;
|
||||
. = 0x00000050; gUnk_03000050 = .;
|
||||
. += 4; . = ALIGN(4);
|
||||
*libgcc.a:dp-bit.o(.bss);
|
||||
. = ALIGN(4);
|
||||
*libgcc.a:fp-bit.o(.bss);
|
||||
. = ALIGN(4);
|
||||
. = 0x00000060; SoundMainRAM_Buffer = .;
|
||||
. = 0x00000061; gUnk_03000061 = .;
|
||||
. = 0x00000470; gUnk_03000470 = .;
|
||||
. = 0x00000478; gUnk_03000478 = .;
|
||||
. = 0x00000480; gUnk_03000480 = .;
|
||||
@ -151,7 +154,7 @@ SECTIONS {
|
||||
. = 0x00001760; gMPlayMemAccArea = .;
|
||||
. = 0x00001760; gUnk_03001760 = .;
|
||||
. = 0x00001770; gUnk_03001770 = .;
|
||||
. = 0x000017B0; gUnk_030017B0 = .;
|
||||
. = 0x000017B0; gIntrTable = .;
|
||||
. = 0x000017F0; gUnk_030017F0 = .;
|
||||
. = 0x000019F0; gUnk_030019F0 = .;
|
||||
. = 0x000023F0; gUnk_030023F0 = .;
|
||||
@ -258,42 +261,72 @@ SECTIONS {
|
||||
. = 0x000068D0; gUnk_030068D0 = .;
|
||||
. = 0x000068D4; gUnk_030068D4 = .;
|
||||
. = 0x000068D8; gUnk_030068D8 = .;
|
||||
. = 0x000068E0; gUnk_030068E0 = .;
|
||||
. = 0x00006A60; gUnk_03006A60 = .;
|
||||
. = 0x00006C50; gUnk_03006C50 = .;
|
||||
. = 0x00006C90; gUnk_03006C90 = .;
|
||||
. = 0x000068E0; gMultiSioIntrFuncBuf = .;
|
||||
. = 0x00006A60; gMultiSioArea = .;
|
||||
. = 0x00006C50; gMultiSioRecvFuncBuf = .;
|
||||
. = 0x00006C90; gSio32MultiLoadArea = .;
|
||||
. = 0x00006CB0; gUnk_03006CB0 = .;
|
||||
. = 0x00006CBC; gUnk_03006CBC = .;
|
||||
. = 0x00006CC0; gUnk_03006CC0 = .;
|
||||
. = 0x00006CC4; gUnk_03006CC4 = .;
|
||||
. = 0x00007E80; gUnk_03007E80 = .;
|
||||
. = 0x00007F00; gUnk_03007F00 = .;
|
||||
. = 0x00007FA0; gUnk_03007FA0 = .;
|
||||
. = 0x00007FF0; SOUND_INFO_PTR = .;
|
||||
. = 0x00007FF8; gUnk_03007FF8 = .;
|
||||
. = 0x00007FFC; gUnk_03007FFC = .;
|
||||
. = 0x00008000;
|
||||
} >iwram
|
||||
|
||||
rom : ALIGN(4) {
|
||||
asm/crt0.o(.text);
|
||||
asm/code.o(.text);
|
||||
asm/libm4a_1.o(.text);
|
||||
asm/libm4a_2.o(.text);
|
||||
asm/code_0815158C.o(.text);
|
||||
asm/m4a_asm.o(.text);
|
||||
src/m4a.o(.text);
|
||||
asm/main.o(.text);
|
||||
asm/multiboot.o(.text);
|
||||
asm/code_08157E54.o(.text);
|
||||
asm/code_08158F14.o(.text);
|
||||
asm/code_08152A18.o(.text);
|
||||
src/multi_sio.o(.text);
|
||||
src/multi_boot.o(.text);
|
||||
src/sio32_multi_load.o(.text);
|
||||
asm/code_0815819C.o(.text);
|
||||
asm/multi_sio_asm.o(.text);
|
||||
asm/code_08159074.o(.text);
|
||||
asm/agb_flash.o(.text); /* TODO: is it? */
|
||||
src/agb_sram.o(.text);
|
||||
asm/libagbsyscall.o(.text);
|
||||
asm/code_08159350.o(.text);
|
||||
asm/libgcc.o(.text);
|
||||
asm/libc.o(.text);
|
||||
src/powf_error_handler.o(.text);
|
||||
*libc.a:ef_pow.o(.text);
|
||||
*libc.a:ef_sqrt.o(.text);
|
||||
*libc.a:s_matherr.o(.text);
|
||||
*libc.a:s_rint.o(.text);
|
||||
*libc.a:sf_fabs.o(.text);
|
||||
*libc.a:sf_finite.o(.text);
|
||||
*libc.a:sf_isnan.o(.text);
|
||||
*libc.a:sf_scalbn.o(.text);
|
||||
*libc.a:sf_copysign.o(.text);
|
||||
*libgcc.a:_call_via_rX.o(.text);
|
||||
*libgcc.a:_divsi3.o(.text);
|
||||
*libgcc.a:_dvmd_tls.o(.text);
|
||||
*libgcc.a:_modsi3.o(.text);
|
||||
*libgcc.a:_udivsi3.o(.text);
|
||||
*libgcc.a:_umodsi3.o(.text);
|
||||
*libgcc.a:dp-bit.o(.text);
|
||||
*libgcc.a:fp-bit.o(.text);
|
||||
*libgcc.a:_lshrdi3.o(.text);
|
||||
*libgcc.a:_muldi3.o(.text);
|
||||
*libgcc.a:_negdi2.o(.text);
|
||||
*libc.a:errno.o(.text);
|
||||
*libc.a:memcpy.o(.text);
|
||||
*libc.a:memset.o(.text);
|
||||
data/data_1.o(.rodata);
|
||||
src/multi_sio.o(.rodata);
|
||||
src/sio32_multi_load.o(.rodata);
|
||||
src/agb_sram.o(.rodata);
|
||||
src/powf_error_handler.o(.rodata);
|
||||
*libc.a:ef_pow.o(.rodata);
|
||||
*libc.a:ef_sqrt.o(.rodata);
|
||||
src/powf_error_handler.o(.data);
|
||||
*libc.a:s_rint.o(.rodata);
|
||||
data/data_3.o(.rodata);
|
||||
*libc.a:impure.o(.rodata);
|
||||
data/data_2.o(.rodata);
|
||||
/* stuff below are mislinked into the binary? */
|
||||
data/data_unk.o(.rodata);
|
||||
*libc.a:impure.o(.data);
|
||||
} >rom
|
||||
|
||||
/* DWARF 2 sections */
|
||||
|
80
src/agb_sram.c
Normal file
80
src/agb_sram.c
Normal file
@ -0,0 +1,80 @@
|
||||
#include "agb_sram.h"
|
||||
|
||||
const char gAgbSramLibVer[] = "NINTENDOSRAM_V113";
|
||||
|
||||
static void ReadSram_Core(const u8 *src, u8 *dest, u32 size)
|
||||
{
|
||||
while (--size != -1)
|
||||
*dest++ = *src++;
|
||||
}
|
||||
|
||||
void ReadSram(const u8 *src, u8 *dest, u32 size)
|
||||
{
|
||||
const u16 *s;
|
||||
u16 *d;
|
||||
u16 readSramFast_Work[64];
|
||||
u16 size_;
|
||||
|
||||
REG_WAITCNT = (REG_WAITCNT & ~3) | 3;
|
||||
s = (void *)((uintptr_t)ReadSram_Core);
|
||||
s = (void *)((uintptr_t)s & ~1);
|
||||
d = readSramFast_Work;
|
||||
size_ = ((uintptr_t)ReadSram - (uintptr_t)ReadSram_Core) / 2;
|
||||
while (size_ != 0)
|
||||
{
|
||||
*d++ = *s++;
|
||||
--size_;
|
||||
}
|
||||
((void (*)(const u8 *, u8 *, u32))readSramFast_Work + 1)(src, dest, size);
|
||||
}
|
||||
|
||||
void WriteSram(const u8 *src, u8 *dest, u32 size)
|
||||
{
|
||||
REG_WAITCNT = (REG_WAITCNT & ~3) | 3;
|
||||
while (--size != -1)
|
||||
*dest++ = *src++;
|
||||
}
|
||||
|
||||
static u32 VerifySram_Core(const u8 *src, u8 *dest, u32 size)
|
||||
{
|
||||
while (--size != -1)
|
||||
if (*dest++ != *src++)
|
||||
return (u32)(dest - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 VerifySram(const u8 *src, u8 *dest, u32 size)
|
||||
{
|
||||
const u16 *s;
|
||||
u16 *d;
|
||||
u16 verifySramFast_Work[96];
|
||||
u16 size_;
|
||||
|
||||
REG_WAITCNT = (REG_WAITCNT & ~3) | 3;
|
||||
s = (void *)((uintptr_t)VerifySram_Core);
|
||||
s = (void *)((uintptr_t)s & ~1);
|
||||
d = verifySramFast_Work;
|
||||
size_ = ((uintptr_t)VerifySram - (uintptr_t)VerifySram_Core) / 2;
|
||||
while (size_ != 0)
|
||||
{
|
||||
*d++ = *s++;
|
||||
--size_;
|
||||
}
|
||||
return ((u32 (*)(const u8 *, u8 *, u32))verifySramFast_Work + 1)(src, dest, size);
|
||||
}
|
||||
|
||||
u32 WriteSramEx(const u8 *src, u8 *dest, u32 size)
|
||||
{
|
||||
u8 i;
|
||||
u32 errorAddr;
|
||||
|
||||
// try writing and verifying the data 3 times
|
||||
for (i = 0; i < SRAM_RETRY_MAX; ++i)
|
||||
{
|
||||
WriteSram(src, dest, size);
|
||||
errorAddr = VerifySram(src, dest, size);
|
||||
if (errorAddr == 0)
|
||||
break;
|
||||
}
|
||||
return errorAddr;
|
||||
}
|
637
src/multi_boot.c
Normal file
637
src/multi_boot.c
Normal file
@ -0,0 +1,637 @@
|
||||
#include "multi_boot.h"
|
||||
|
||||
static s32 MultiBootSend(struct MultiBootParam *mp, u16 data);
|
||||
static s32 MultiBootHandShake(struct MultiBootParam *mp);
|
||||
static void MultiBootWaitSendDone(void);
|
||||
|
||||
static u16 sMultiBootRequiredData[MULTIBOOT_NCHILD];
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Multi-play Boot Main */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
s32 MultiBootMain(struct MultiBootParam *mp)
|
||||
{
|
||||
s32 i, j, k;
|
||||
|
||||
if (MultiBootCheckComplete(mp))
|
||||
/* Transfer is complete so no other processing done */
|
||||
return 0;
|
||||
if (mp->check_wait > MULTIBOOT_CONNECTION_CHECK_WAIT)
|
||||
{
|
||||
/* After system call error, do not send anything,
|
||||
* and wait for client to have timeout error.
|
||||
*/
|
||||
--mp->check_wait;
|
||||
return 0;
|
||||
}
|
||||
output_burst:
|
||||
if (mp->sendflag)
|
||||
{
|
||||
mp->sendflag = 0;
|
||||
/* There is a problem if SC7, SC6 is on at this point.
|
||||
* There may be a problem with the connection(connected to JOY) and
|
||||
* communication does not have timeout error.
|
||||
* When the connection ID is not 00 or there is a problem with the SD or SI terminals an error occurs.
|
||||
*/
|
||||
i = REG_SIOCNT & (SIO_MULTI_BUSY | SIO_ERROR | SIO_ID | SIO_MULTI_SD | SIO_MULTI_SI);
|
||||
if (i != SIO_MULTI_SD)
|
||||
{
|
||||
mp->client_bit = 0;
|
||||
mp->probe_count = 0;
|
||||
mp->response_bit = 0;
|
||||
mp->check_wait = MULTIBOOT_CONNECTION_CHECK_WAIT;
|
||||
mp->sendflag = 0;
|
||||
mp->handshake_timeout = 0;
|
||||
return i ^ SIO_MULTI_SD;
|
||||
}
|
||||
}
|
||||
if (mp->probe_count >= 0xe0)
|
||||
{
|
||||
/* Check(handshake) to see if all slaves booted properly. */
|
||||
i = MultiBootHandShake(mp);
|
||||
if (i)
|
||||
return i;
|
||||
/* If Low speed recognition mode, handshake also 2bytes communication, call
|
||||
* If High speed recognition mode, handshake also high speed communication.
|
||||
*/
|
||||
if (mp->probe_count > 0xe1
|
||||
&& MultiBootCheckComplete(mp) == 0)
|
||||
{
|
||||
MultiBootWaitSendDone();
|
||||
goto output_burst;
|
||||
}
|
||||
/* Timeout check */
|
||||
if (MultiBootCheckComplete(mp) == 0)
|
||||
{
|
||||
if (mp->handshake_timeout == 0)
|
||||
{
|
||||
mp->client_bit = 0;
|
||||
mp->probe_count = 0;
|
||||
mp->response_bit = 0;
|
||||
mp->check_wait = MULTIBOOT_CONNECTION_CHECK_WAIT;
|
||||
mp->sendflag = 0;
|
||||
mp->handshake_timeout = 0;
|
||||
return MULTIBOOT_ERROR_HANDSHAKE_FAILURE;
|
||||
}
|
||||
--mp->handshake_timeout;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
switch (mp->probe_count)
|
||||
{
|
||||
case 0:
|
||||
/* client not doing recognition
|
||||
* Value should be CLIENT_INFO 000 0 ccc 0
|
||||
* First, check if some kind of response(other than 0xffff)
|
||||
* from machine.
|
||||
*/
|
||||
k = 0x0e;
|
||||
for (i = MULTIBOOT_NCHILD; i != 0; --i)
|
||||
{
|
||||
if (*(vu16 *)(REG_ADDR_SIOMULTI0 + i * 2) != 0xffff)
|
||||
{ // braces are required to match on my machine, but works fine on SBird's CE :/
|
||||
break;
|
||||
}
|
||||
k >>= 1;
|
||||
}
|
||||
k &= 0x0e; /* 4P-2P: d3-d1 is 1 */
|
||||
mp->response_bit = k;
|
||||
/* Machine recognized as client,
|
||||
* must be CLIENT_INFO 000 0 ccc 0.
|
||||
*/
|
||||
for (i = MULTIBOOT_NCHILD; i != 0; --i)
|
||||
{
|
||||
j = *(vu16 *)(REG_ADDR_SIOMULTI0 + i * 2);
|
||||
if (mp->client_bit & (1 << i))
|
||||
{
|
||||
if (j != ((MULTIBOOT_CLIENT_INFO << 8) | (1 << i)))
|
||||
{
|
||||
/* Need to do recognition processing again */
|
||||
k = 0;
|
||||
mp->response_bit = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
mp->client_bit &= k;
|
||||
if (k == 0)
|
||||
/* From client, until at least one returns value other than
|
||||
* 0xffff, maintain fixed time until redo of recognition processing
|
||||
*/
|
||||
mp->check_wait = MULTIBOOT_CONNECTION_CHECK_WAIT;
|
||||
if (mp->check_wait)
|
||||
{
|
||||
--mp->check_wait;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If machine with response and client status do not match up,
|
||||
* do recognition processing again.
|
||||
*/
|
||||
if (mp->response_bit != mp->client_bit)
|
||||
{
|
||||
MultiBootStartProbe(mp);
|
||||
goto case_1;
|
||||
}
|
||||
}
|
||||
output_master_info:
|
||||
/* Output MASTER_INFO 000 0 ccc 0. */
|
||||
return MultiBootSend(mp, (MULTIBOOT_MASTER_INFO << 8) | mp->client_bit);
|
||||
case 1:
|
||||
case_1:
|
||||
/* Start recognition.
|
||||
* Those where in data is CLIENT_INFO 000 0 ccc 0
|
||||
* are recognized.
|
||||
*/
|
||||
mp->probe_target_bit = 0;
|
||||
for (i = MULTIBOOT_NCHILD; i != 0; --i)
|
||||
{
|
||||
j = *(vu16 *)(REG_ADDR_SIOMULTI0 + i * 2);
|
||||
if ((j >> 8) == MULTIBOOT_CLIENT_INFO)
|
||||
{
|
||||
/* Check validity of 000 0 ccc 0.
|
||||
* If 4P, 0x08
|
||||
* If 3P, 0x04
|
||||
* If 2P, 0x02
|
||||
* If not so, invalid.
|
||||
*/
|
||||
sMultiBootRequiredData[i - 1] = j; /* During processing next time must be same value */
|
||||
j &= 0xff;
|
||||
if (j == (1 << i))
|
||||
mp->probe_target_bit |= j;
|
||||
}
|
||||
}
|
||||
|
||||
if (mp->response_bit != mp->probe_target_bit)
|
||||
goto output_master_info;
|
||||
/* Send MASTER_START_PROBE 000 0 ccc 0.
|
||||
* Here the recognized bits are 000, ccc.
|
||||
* If not possible that 000 or ccc, not recognized by master.
|
||||
*/
|
||||
mp->probe_count = 2;
|
||||
return MultiBootSend(mp, (MULTIBOOT_MASTER_START_PROBE << 8) | mp->probe_target_bit);
|
||||
case 2:
|
||||
/* Must be CLIENT_INFO 000 0 ccc 0.
|
||||
* Output header +0, +1 bytes.
|
||||
*/
|
||||
for (i = MULTIBOOT_NCHILD; i != 0; --i)
|
||||
{
|
||||
if (mp->probe_target_bit & (1 << i))
|
||||
{
|
||||
j = *(vu16 *)(REG_ADDR_SIOMULTI0 + i * 2);
|
||||
if (j != sMultiBootRequiredData[i - 1])
|
||||
/* Problem with client recognition */
|
||||
mp->probe_target_bit ^= 1 << i;
|
||||
}
|
||||
}
|
||||
goto output_header;
|
||||
case 0xd0:
|
||||
/* Request for start of master server.
|
||||
* If CLIENT_INFO 000 0 ccc 0, not ready
|
||||
* to download client.
|
||||
* If all clients CLIENT_DLREADY, call system
|
||||
* call and transfer boot program.
|
||||
*/
|
||||
k = 1; /* Okay to go to download start? */
|
||||
for (i = MULTIBOOT_NCHILD; i != 0; --i)
|
||||
{
|
||||
j = *(vu16 *)(REG_ADDR_SIOMULTI0 + i * 2);
|
||||
/* handshake data from client
|
||||
* Regardless of recognition, save for all machines
|
||||
*/
|
||||
mp->client_data[i - 1] = j;
|
||||
if (mp->probe_target_bit & (1 << i))
|
||||
{
|
||||
if ((j >> 8) != MULTIBOOT_CLIENT_INFO
|
||||
&& (j >> 8) != MULTIBOOT_CLIENT_DLREADY)
|
||||
{
|
||||
mp->client_bit = 0;
|
||||
mp->probe_count = 0;
|
||||
mp->response_bit = 0;
|
||||
mp->check_wait = MULTIBOOT_CONNECTION_CHECK_WAIT;
|
||||
mp->sendflag = 0;
|
||||
mp->handshake_timeout = 0;
|
||||
return MULTIBOOT_ERROR_NO_DLREADY; /* No response saying ready to do download */
|
||||
}
|
||||
if (j == sMultiBootRequiredData[i - 1])
|
||||
/* CLIENT_INFO 000 0 ccc 0
|
||||
* Was at least one machine not ready for download,
|
||||
* so not start download yet.
|
||||
*/
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
if (k == 0)
|
||||
/* Not start download yet.
|
||||
* Send request for download preparation
|
||||
*/
|
||||
return MultiBootSend(mp, (MULTIBOOT_MASTER_REQUEST_DLREADY << 8) | mp->palette_data);
|
||||
/* All machines ready to download */
|
||||
mp->probe_count = 0xd1;
|
||||
k = 0x11;
|
||||
for (i = MULTIBOOT_NCHILD; i != 0; --i)
|
||||
/* handshake data */
|
||||
k += mp->client_data[i - 1];
|
||||
mp->handshake_data = k;
|
||||
return MultiBootSend(mp, (MULTIBOOT_MASTER_START_DL << 8) | (k & 0xff));
|
||||
case 0xd1:
|
||||
/* Send MASTER_START_DL
|
||||
* Should be CLIENT_DLREADY.
|
||||
*/
|
||||
for (i = MULTIBOOT_NCHILD; i != 0; --i)
|
||||
{
|
||||
j = *(vu16 *)(REG_ADDR_SIOMULTI0 + i * 2);
|
||||
if (mp->probe_target_bit & (1 << i))
|
||||
{
|
||||
if ((j >> 8) != MULTIBOOT_CLIENT_DLREADY)
|
||||
{
|
||||
mp->client_bit = 0;
|
||||
mp->probe_count = 0;
|
||||
mp->response_bit = 0;
|
||||
mp->check_wait = MULTIBOOT_CONNECTION_CHECK_WAIT;
|
||||
mp->sendflag = 0;
|
||||
mp->handshake_timeout = 0;
|
||||
return MULTIBOOT_ERROR_NO_DLREADY; /* No response saying ready to do download */
|
||||
}
|
||||
}
|
||||
}
|
||||
i = MultiBoot(mp);
|
||||
if (i == 0)
|
||||
{
|
||||
/* complete
|
||||
* Make mp -> probe_count into 0xe0(request for handshake start).
|
||||
*/
|
||||
mp->probe_count = 0xe0;
|
||||
mp->handshake_timeout = MULTIBOOT_HANDSHAKE_TIMEOUT;
|
||||
return 0;
|
||||
}
|
||||
mp->client_bit = 0;
|
||||
mp->probe_count = 0;
|
||||
mp->response_bit = 0;
|
||||
mp->check_wait = MULTIBOOT_CONNECTION_CHECK_WAIT;
|
||||
mp->sendflag = 0;
|
||||
mp->handshake_timeout = 0;
|
||||
/* With system call failure, possible that client still in
|
||||
* receive data status.
|
||||
* Therefore, until retry, do not send anything including MASTER_INFO,
|
||||
* during time for "Client has timeout error".
|
||||
*/
|
||||
mp->check_wait = MULTIBOOT_CONNECTION_CHECK_WAIT * 2;
|
||||
return MULTIBOOT_ERROR_BOOT_FAILURE; /* Transfer failed */
|
||||
default:
|
||||
/* 4-...: Doing recognition processing
|
||||
* 4 -> +0,1 byte
|
||||
* 6 -> +2,3
|
||||
* 8 -> +4,5
|
||||
* :
|
||||
* 0xc2 -> +0xbe, 0xbf byte
|
||||
* Output header data.
|
||||
*/
|
||||
|
||||
/* When client is being recognized,
|
||||
* value is MASTER_START_PROBE - 1, ..-2, ..., 0
|
||||
* 0x61 - 1, 0x5f
|
||||
* lower bytes are 000 0 ccc 0
|
||||
*/
|
||||
for (i = MULTIBOOT_NCHILD; i != 0; --i)
|
||||
{
|
||||
if (mp->probe_target_bit & (1 << i))
|
||||
{
|
||||
j = *(vu16 *)(REG_ADDR_SIOMULTI0 + i * 2);
|
||||
if ((j >> 8) != (MULTIBOOT_MASTER_START_PROBE + 1 - (mp->probe_count >> 1))
|
||||
|| ((j & 0xff) != (1 << i)))
|
||||
/* Problem with client recognition */
|
||||
mp->probe_target_bit ^= 1 << i;
|
||||
}
|
||||
}
|
||||
if (mp->probe_count == 0xc4)
|
||||
{
|
||||
/* From recognized, those leftover last are
|
||||
* qualified as client.
|
||||
*/
|
||||
mp->client_bit = mp->probe_target_bit & 0x0e;
|
||||
mp->probe_count = 0;
|
||||
goto output_master_info;
|
||||
}
|
||||
output_header:
|
||||
/* If no target, ends with error in middle. */
|
||||
if (mp->probe_target_bit == 0)
|
||||
{
|
||||
mp->client_bit = 0;
|
||||
mp->probe_count = 0;
|
||||
mp->response_bit = 0;
|
||||
mp->check_wait = MULTIBOOT_CONNECTION_CHECK_WAIT;
|
||||
mp->sendflag = 0;
|
||||
mp->handshake_timeout = 0;
|
||||
return MULTIBOOT_ERROR_NO_PROBE_TARGET; /* No recognized target */
|
||||
}
|
||||
mp->probe_count += 2;
|
||||
if (mp->probe_count == 0xc4)
|
||||
/* When getting final data, send MASTER_INFO 000 0 ccc 0.
|
||||
* If do not problem with timing.
|
||||
*/
|
||||
goto output_master_info;
|
||||
i = MultiBootSend(mp,
|
||||
(mp->masterp[mp->probe_count - 4 + 1] << 8)
|
||||
| mp->masterp[mp->probe_count - 4]);
|
||||
if (i)
|
||||
return i;
|
||||
/* If Low speed recognition mode, for each frame of call, 2 bytes of
|
||||
* communication.
|
||||
* If High speed recognition mode,
|
||||
* (time to end of communication + sufficient time for slave
|
||||
* interrupt processing)
|
||||
* Wait, continued communication.
|
||||
*/
|
||||
if (mp->server_type == MULTIBOOT_SERVER_TYPE_QUICK)
|
||||
{
|
||||
MultiBootWaitSendDone();
|
||||
goto output_burst;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* never comes here */
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Send Data */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* If connection has problem, non-0
|
||||
*/
|
||||
static s32 MultiBootSend(struct MultiBootParam *mp, u16 data)
|
||||
{
|
||||
s32 i;
|
||||
|
||||
/* If SC7 is on, problem has occurred.
|
||||
* There may be a problem with the connection(connected to JOY) and
|
||||
* communication does not have timeout error.
|
||||
* (reconnect cable) May be first communication so no check for
|
||||
* SC6, connection ID.
|
||||
*/
|
||||
i = REG_SIOCNT & (SIO_MULTI_BUSY | SIO_MULTI_SD | SIO_MULTI_SI);
|
||||
if (i != SIO_MULTI_SD)
|
||||
{
|
||||
mp->client_bit = 0;
|
||||
mp->probe_count = 0;
|
||||
mp->response_bit = 0;
|
||||
mp->check_wait = MULTIBOOT_CONNECTION_CHECK_WAIT;
|
||||
mp->sendflag = 0;
|
||||
mp->handshake_timeout = 0;
|
||||
return i ^ SIO_MULTI_SD;
|
||||
}
|
||||
REG_SIODATA8 = data;
|
||||
REG_SIOCNT |= SIO_START;
|
||||
mp->sendflag = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Start recognition of client */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
void MultiBootStartProbe(struct MultiBootParam *mp)
|
||||
{
|
||||
if (mp->probe_count != 0)
|
||||
{
|
||||
mp->client_bit = 0;
|
||||
mp->probe_count = 0;
|
||||
mp->response_bit = 0;
|
||||
mp->check_wait = MULTIBOOT_CONNECTION_CHECK_WAIT;
|
||||
mp->sendflag = 0;
|
||||
mp->handshake_timeout = 0;
|
||||
return;
|
||||
}
|
||||
mp->check_wait = 0;
|
||||
mp->client_bit = 0;
|
||||
mp->probe_count = 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Start send from master server */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
void MultiBootStartMaster(struct MultiBootParam *mp, const u8 *srcp, s32 length, u8 palette_color, s8 palette_speed)
|
||||
{
|
||||
s32 i;
|
||||
|
||||
if (mp->probe_count != 0
|
||||
|| mp->client_bit == 0
|
||||
|| mp->check_wait != 0)
|
||||
{
|
||||
/* Recognition processing, cannot do processing */
|
||||
mp->client_bit = 0;
|
||||
mp->probe_count = 0;
|
||||
mp->response_bit = 0;
|
||||
mp->check_wait = MULTIBOOT_CONNECTION_CHECK_WAIT;
|
||||
mp->sendflag = 0;
|
||||
mp->handshake_timeout = 0;
|
||||
return;
|
||||
}
|
||||
mp->boot_srcp = srcp;
|
||||
length = (length + 15) & ~15; /* 16 byte units */
|
||||
if (length < MULTIBOOT_SEND_SIZE_MIN || length > MULTIBOOT_SEND_SIZE_MAX)
|
||||
{
|
||||
/* More than number or transfer bytes */
|
||||
mp->client_bit = 0;
|
||||
mp->probe_count = 0;
|
||||
mp->response_bit = 0;
|
||||
mp->check_wait = MULTIBOOT_CONNECTION_CHECK_WAIT;
|
||||
mp->sendflag = 0;
|
||||
mp->handshake_timeout = 0;
|
||||
return;
|
||||
}
|
||||
mp->boot_endp = srcp + length;
|
||||
switch (palette_speed)
|
||||
{
|
||||
case -4:
|
||||
case -3:
|
||||
case -2:
|
||||
case -1:
|
||||
i = (palette_color << 3) | (3 - palette_speed);
|
||||
break;
|
||||
case 0:
|
||||
i = 0x38 | palette_color;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
i = (palette_color << 3) | (palette_speed - 1);
|
||||
break;
|
||||
}
|
||||
mp->palette_data = ((i & 0x3f) << 1) | 0x81;
|
||||
mp->probe_count = 0xd0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Handshake (final confirmation of boot) */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
static s32 MultiBootHandShake(struct MultiBootParam *mp)
|
||||
{
|
||||
s32 i, j;
|
||||
|
||||
#define send_data (mp->system_work[0])
|
||||
#define must_data (mp->system_work[1])
|
||||
switch (mp->probe_count)
|
||||
{
|
||||
case 0xe0:
|
||||
case_0xe0:
|
||||
/* Master sends 0x0000. */
|
||||
mp->probe_count = 0xe1;
|
||||
must_data = 0x0000;
|
||||
send_data = 0x100000; /* Right before next send >>5 */
|
||||
return MultiBootSend(mp, 0x0000);
|
||||
default:
|
||||
/* 0xe1-0xe6
|
||||
* If expected data does not come, do again from case_0xe0.
|
||||
* 0xe1: After master sends 0x0000. All slaves must be 0x0000.
|
||||
* 0xe2: After master sends 0x8000. All slaves must be 0x0000.
|
||||
* 0xe3: 0x0400 0x8000
|
||||
* 0xe4: 0x0020 0x0400
|
||||
* 0xe5: 0x0001 0x0020
|
||||
* 0xe6: 0x0000 0x0001
|
||||
*/
|
||||
for (i = MULTIBOOT_NCHILD; i != 0; --i)
|
||||
{
|
||||
j = *(vu16 *)(REG_ADDR_SIOMULTI0 + i * 2);
|
||||
if ((mp->client_bit & (1 << i))
|
||||
&& j != must_data)
|
||||
/* Expected data still hasn't come from all slaves. */
|
||||
goto case_0xe0;
|
||||
}
|
||||
++mp->probe_count;
|
||||
must_data = send_data & 0xffff;
|
||||
if (send_data == 0x0000)
|
||||
{
|
||||
/* This time send initial code low. */
|
||||
must_data = mp->masterp[0xac] | (mp->masterp[0xad] << 8);
|
||||
send_data = must_data << 5; /* right before sending >>5 */
|
||||
}
|
||||
send_data >>= 5;
|
||||
output_common:
|
||||
return MultiBootSend(mp, send_data);
|
||||
case 0xe7: /* Master sent initial code, low. All slaves must be same. */
|
||||
case 0xe8: /* Master sent initial code, high. All slaves must be same. */
|
||||
for (i = MULTIBOOT_NCHILD; i != 0; --i)
|
||||
{
|
||||
j = *(vu16 *)(REG_ADDR_SIOMULTI0 + i * 2);
|
||||
if ((mp->client_bit & (1 << i)) && j != must_data)
|
||||
{
|
||||
/* Desired data did not come from all slaves.
|
||||
* If reach this point and have error, stop(infinite loop) slave,
|
||||
* and no retry by master.
|
||||
* On master's screen display,
|
||||
* "Communicsation failure. Turn off power and check connection.
|
||||
* Turn on power again."
|
||||
*/
|
||||
mp->client_bit = 0;
|
||||
mp->probe_count = 0;
|
||||
mp->response_bit = 0;
|
||||
mp->check_wait = MULTIBOOT_CONNECTION_CHECK_WAIT;
|
||||
mp->sendflag = 0;
|
||||
mp->handshake_timeout = 0;
|
||||
return MULTIBOOT_ERROR_HANDSHAKE_FAILURE;
|
||||
}
|
||||
}
|
||||
++mp->probe_count;
|
||||
if (mp->probe_count == 0xe9)
|
||||
/* Handshake Success! */
|
||||
return 0;
|
||||
/* This time send the initial code, high. */
|
||||
send_data = mp->masterp[0xae] | (mp->masterp[0xaf] << 8);
|
||||
must_data = send_data;
|
||||
goto output_common;
|
||||
}
|
||||
#undef send_data
|
||||
#undef must_data
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Multi-play Boot Initialization */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
void MultiBootInit(struct MultiBootParam *mp)
|
||||
{
|
||||
mp->client_bit = 0;
|
||||
mp->probe_count = 0;
|
||||
mp->response_bit = 0;
|
||||
mp->check_wait = MULTIBOOT_CONNECTION_CHECK_WAIT;
|
||||
mp->sendflag = 0;
|
||||
mp->handshake_timeout = 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Check transfer completion */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
s32 MultiBootCheckComplete(struct MultiBootParam *mp)
|
||||
{
|
||||
if (mp->probe_count == 0xe9)
|
||||
/* Transfer complete status */
|
||||
return 1;
|
||||
/* middle of recognition, haven't started transfer, or transfer failure */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Wait Cycle */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
static inline void MultiBootWaitCycles(u32 cycles)
|
||||
{
|
||||
/* Depending on if this is in CPU internal working, CPU external
|
||||
* working, ROM, the CPU cycles used for one of this function's wait
|
||||
* loops is different.
|
||||
* CPU External Working (0x02XXXXXX) ... 12 cycles/loop
|
||||
* ROM (0x08XXXXXX) ... 13 cycles/loop
|
||||
* (Have prefetch Setup maximum speed)
|
||||
* CPU Internal Working (0x03XXXXXX) ... 4 cycles/loop
|
||||
* If address area other than above, temporarily use 4 cycles/loop.
|
||||
* If set up lower cycles/loop than actual,
|
||||
* can get specified cycle number wait.
|
||||
*
|
||||
* Use AGB system clock 16.78MHz as hint for argument, cycles.
|
||||
* If use 0x1000000 (16777216) with cycles approximately 1 second wait.
|
||||
* (If V blank interrupt is processed during this, actual wait is longer)
|
||||
*/
|
||||
asm("mov r2, pc");
|
||||
asm("lsr r2, #24");
|
||||
asm("mov r1, #12");
|
||||
asm("cmp r2, #0x02");
|
||||
asm("beq MultiBootWaitCyclesLoop");
|
||||
asm("mov r1, #13");
|
||||
asm("cmp r2, #0x08");
|
||||
asm("beq MultiBootWaitCyclesLoop");
|
||||
asm("mov r1, #4");
|
||||
asm("MultiBootWaitCyclesLoop:");
|
||||
asm("sub r0, r1");
|
||||
asm("bgt MultiBootWaitCyclesLoop");
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Check if communication completed within fixed time */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
static void MultiBootWaitSendDone(void)
|
||||
{
|
||||
s32 i;
|
||||
|
||||
/* If cannot detect communication end within fixed time(1 frame),
|
||||
* remove loop.
|
||||
* Even if fast this loop takes 9 cycles/loop,
|
||||
* (ldr=3, and=1, branch skip=1, i++=1, branch=3)
|
||||
* try loop for 1 frame.
|
||||
* Number of times do loop is,
|
||||
* 0x1000000 (16.78MHz=cycles/sec) / 60 (frames/sec) / 9 (cycles/loop)
|
||||
* = approximately 31069 (loops/frame)
|
||||
*/
|
||||
for (i = 0; i < 31069; ++i)
|
||||
if ((REG_SIOCNT & SIO_START) == 0)
|
||||
break;
|
||||
/* Sufficient time for slave's interrupt processing */
|
||||
MultiBootWaitCycles(600);
|
||||
}
|
279
src/multi_sio.c
Normal file
279
src/multi_sio.c
Normal file
@ -0,0 +1,279 @@
|
||||
#include "sio32_multi_load.h"
|
||||
|
||||
static const u8 sMultiSioLibVer[] = "MultiSio4Sio32Load020820";
|
||||
|
||||
// COMMON
|
||||
// struct MultiSioArea gMultiSioArea; // Multi-play Communication Work Area
|
||||
|
||||
#ifdef MULTI_SIO_DI_FUNC_FAST
|
||||
// u32 gMultiSioRecvFuncBuf[0x40 / 4]; // Receive Data/Check Buffer Change Routine RAM Execution Buffer
|
||||
// u32 gMultiSioIntrFuncBuf[0x180 / 4]; // Interrupt Routine RAM Execution Buffer
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Multi-play Communication Initialization */
|
||||
/*------------------------------------------------------------------*/
|
||||
extern u32 MultiSioRecvBufChange(void);
|
||||
|
||||
void MultiSioInit(u32 connectedFlags)
|
||||
{
|
||||
s32 i;
|
||||
|
||||
REG_IME = 0;
|
||||
REG_IE &= ~(INTR_FLAG_SERIAL // Disable SIO & Timer Interrupt
|
||||
| MULTI_SIO_TIMER_INTR_FLAG);
|
||||
REG_IME = 1;
|
||||
REG_RCNT = ST_R_SIO_MASTER_MODE;
|
||||
*(vu32 *)REG_ADDR_SIOCNT = SIO_MULTI_MODE;
|
||||
REG_SIOCNT |= SIO_IF_ENABLE | MULTI_SIO_BAUD_RATE_NO;
|
||||
CpuFill32(0, &gMultiSioArea, sizeof(struct MultiSioArea)); // Clear Multi-play Communication Work Area
|
||||
#ifdef MULTI_SIO_DI_FUNC_FAST // Copy Function
|
||||
CpuCopy32(MultiSioRecvBufChange, gMultiSioRecvFuncBuf, sizeof(gMultiSioRecvFuncBuf));
|
||||
CpuCopy32(MultiSioIntr, gMultiSioIntrFuncBuf, sizeof(gMultiSioIntrFuncBuf));
|
||||
#endif
|
||||
gMultiSioArea.connectedFlags = connectedFlags;
|
||||
gMultiSioArea.sendBufCounter = -1;
|
||||
gMultiSioArea.nextSendBufp = (u16 *)&gMultiSioArea.sendBuf[0]; // Set Send Buffer Pointer
|
||||
gMultiSioArea.currentSendBufp = (u16 *)&gMultiSioArea.sendBuf[1];
|
||||
for (i = 0; i < 4; ++i)
|
||||
{ // Set Receive Buffer Pointer
|
||||
gMultiSioArea.currentRecvBufp[i] = (u16 *)&gMultiSioArea.recvBuf[i][0];
|
||||
gMultiSioArea.lastRecvBufp[i] = (u16 *)&gMultiSioArea.recvBuf[i][1];
|
||||
gMultiSioArea.recvCheckBufp[i] = (u16 *)&gMultiSioArea.recvBuf[i][2];
|
||||
}
|
||||
REG_IME = 0;
|
||||
REG_IE |= INTR_FLAG_SERIAL; // Enable SIO Interrupt
|
||||
REG_IME = 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Multi-play Communication Main */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
u32 MultiSioMain(void *sendp, void *recvp, u32 loadRequest)
|
||||
{
|
||||
struct SioMultiCnt sioCntBak;
|
||||
UNUSED s32 i, ii; // declared in SDK
|
||||
|
||||
sioCntBak = *(struct SioMultiCnt *)REG_ADDR_SIOCNT; // Check Connection
|
||||
switch (gMultiSioArea.state)
|
||||
{
|
||||
case 0:
|
||||
if (!sioCntBak.id)
|
||||
{
|
||||
if (!sioCntBak.sd || sioCntBak.enable)
|
||||
break;
|
||||
if (!sioCntBak.si && gMultiSioArea.sendBufCounter == -1)
|
||||
{
|
||||
REG_IME = 0;
|
||||
REG_IE &= ~INTR_FLAG_SERIAL; // Disable SIO Interrupt
|
||||
REG_IE |= MULTI_SIO_TIMER_INTR_FLAG; // Enable Timer Interrupt
|
||||
REG_IME = 1;
|
||||
((struct SioMultiCnt *)REG_ADDR_SIOCNT)->ifEnable = 0; // Reset SIO-IFE
|
||||
REG_IF = INTR_FLAG_SERIAL | MULTI_SIO_TIMER_INTR_FLAG;
|
||||
REG_MULTI_SIO_TIMER = MULTI_SIO_TIMER_COUNT; // Timer Initialization
|
||||
gMultiSioArea.type = SIO_MULTI_PARENT;
|
||||
((struct SioMultiCnt *)REG_ADDR_SIOCNT)->enable = 1; // Start Send
|
||||
}
|
||||
}
|
||||
gMultiSioArea.state = 1;
|
||||
// fallthrough
|
||||
case 1:
|
||||
if (gMultiSioArea.connectedFlags && !gMultiSioArea.loadSuccessFlag)
|
||||
{
|
||||
if (gMultiSioArea.recvFlagsAvailableCounter < 8) // Waiting period to stabilize communication in initialization
|
||||
++gMultiSioArea.recvFlagsAvailableCounter;
|
||||
else
|
||||
gMultiSioArea.state = 2;
|
||||
}
|
||||
// fallthrough
|
||||
case 2:
|
||||
MultiSioRecvDataCheck(recvp); // Check Receive Data
|
||||
MultiSioSendDataSet(sendp, loadRequest); // Set Send Data
|
||||
break;
|
||||
}
|
||||
++gMultiSioArea.sendFrameCounter;
|
||||
return gMultiSioArea.recvSuccessFlags
|
||||
| gMultiSioArea.loadEnable << 4
|
||||
| gMultiSioArea.loadRequest << 5
|
||||
| gMultiSioArea.loadSuccessFlag << 6
|
||||
| (gMultiSioArea.type == SIO_MULTI_PARENT) << 7
|
||||
| gMultiSioArea.connectedFlags << 8
|
||||
| (gMultiSioArea.hardError != 0) << 12
|
||||
| (sioCntBak.id >= MULTI_SIO_PLAYERS_MAX) << 13
|
||||
| (gMultiSioArea.recvFlagsAvailableCounter >> 3) << 15;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Set Send Data */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
void MultiSioSendDataSet(void *sendp, u32 loadRequest)
|
||||
{
|
||||
s32 checkSum = 0;
|
||||
s32 i;
|
||||
|
||||
((struct MultiSioPacket *)gMultiSioArea.nextSendBufp)->loadRequest = loadRequest;
|
||||
((struct MultiSioPacket *)gMultiSioArea.nextSendBufp)->downloadSuccessFlag = gSio32MultiLoadArea.downloadSuccessFlag;
|
||||
((struct MultiSioPacket *)gMultiSioArea.nextSendBufp)->loadSuccessFlag = gMultiSioArea.loadSuccessFlag;
|
||||
((struct MultiSioPacket *)gMultiSioArea.nextSendBufp)->frameCounter = (u8)gMultiSioArea.sendFrameCounter;
|
||||
((struct MultiSioPacket *)gMultiSioArea.nextSendBufp)->recvErrorFlags = gMultiSioArea.connectedFlags ^ gMultiSioArea.recvSuccessFlags;
|
||||
((struct MultiSioPacket *)gMultiSioArea.nextSendBufp)->checkSum = 0;
|
||||
CpuCopy32(sendp, &gMultiSioArea.nextSendBufp[2], MULTI_SIO_BLOCK_SIZE); // Set Send Data
|
||||
for (i = 0; i < sizeof(struct MultiSioPacket) / 2 - 2; ++i) // Calculate Checksum Send Data
|
||||
checkSum += gMultiSioArea.nextSendBufp[i];
|
||||
((struct MultiSioPacket *)gMultiSioArea.nextSendBufp)->checkSum = ~checkSum - 14;
|
||||
if (gMultiSioArea.type)
|
||||
REG_MULTI_SIO_TIMER_H = 0; // Stop Timer
|
||||
gMultiSioArea.sendBufCounter = -1;
|
||||
if (gMultiSioArea.type && gMultiSioArea.startFlag)
|
||||
REG_MULTI_SIO_TIMER_H = TIMER_1CLK | TIMER_INTR_ENABLE | TIMER_ENABLE; // Start Timer
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Check Receive Data */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
u32 MultiSioRecvDataCheck(void *recvp)
|
||||
{
|
||||
u32 (*multiSioRecvBufChangeOnRam)(void) = (u32 (*)(void))gMultiSioRecvFuncBuf;
|
||||
s32 checkSum;
|
||||
vu32 recvCheck = 0;
|
||||
u8 syncRecvFlagBak[4];
|
||||
u8 counterDiff;
|
||||
u16 *bufpTmp;
|
||||
s32 i, ii;
|
||||
|
||||
#ifdef MULTI_SIO_DI_FUNC_FAST // Update Receive Data/Check Buffer
|
||||
*(u32 *)syncRecvFlagBak = multiSioRecvBufChangeOnRam();
|
||||
#else
|
||||
REG_IME = 0; // Disable Interrupt (Approx. 80 Clocks)
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
bufpTmp = gMultiSioArea.recvCheckBufp[i]; // Update Receive Data/Check Buffer
|
||||
gMultiSioArea.recvCheckBufp[i] = gMultiSioArea.lastRecvBufp[i];
|
||||
gMultiSioArea.lastRecvBufp[i] = bufpTmp;
|
||||
}
|
||||
REG_IME = 1; // Enable Interrupt
|
||||
#endif
|
||||
gMultiSioArea.recvSuccessFlags = 0;
|
||||
gMultiSioArea.loadSuccessFlag = 0;
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
checkSum = 0; // Calculate Checksum Receive Data
|
||||
for (ii = 0; ii < sizeof(struct MultiSioPacket) / 2 - 2; ++ii)
|
||||
checkSum += gMultiSioArea.recvCheckBufp[i][ii];
|
||||
if (syncRecvFlagBak[i]) // Receive Success Confirmation
|
||||
if ((s16)checkSum == -15)
|
||||
{
|
||||
gMultiSioArea.recvSuccessFlags |= 1 << i;
|
||||
gMultiSioArea.downloadSuccessFlags |= ((struct MultiSioPacket *)gMultiSioArea.recvCheckBufp[i])->downloadSuccessFlag << i;
|
||||
CpuCopy32(&((u8 *)gMultiSioArea.recvCheckBufp[i])[4], &((u8 *)recvp)[i * MULTI_SIO_BLOCK_SIZE], MULTI_SIO_BLOCK_SIZE);
|
||||
}
|
||||
CpuFill32(0, &((u8 *)gMultiSioArea.recvCheckBufp[i])[4], MULTI_SIO_BLOCK_SIZE);
|
||||
}
|
||||
gMultiSioArea.connectedFlags |= gMultiSioArea.recvSuccessFlags; // Set Connect Complete Flag
|
||||
if (gMultiSioArea.recvSuccessFlags & 1)
|
||||
{
|
||||
if (gMultiSioArea.type == SIO_MULTI_PARENT)
|
||||
{
|
||||
if (gMultiSioArea.recvSuccessFlags & 0x3) // Enable Load
|
||||
if (gMultiSioArea.recvSuccessFlags == gMultiSioArea.connectedFlags)
|
||||
gMultiSioArea.loadEnable = 1;
|
||||
if ((gMultiSioArea.downloadSuccessFlags & 0xe) == (gMultiSioArea.connectedFlags & 0xe)) // Check Load
|
||||
gMultiSioArea.loadSuccessFlag = 1;
|
||||
}
|
||||
else
|
||||
gMultiSioArea.loadSuccessFlag = ((struct MultiSioPacket *)gMultiSioArea.recvCheckBufp[0])->loadSuccessFlag;
|
||||
gMultiSioArea.loadRequest = ((struct MultiSioPacket *)gMultiSioArea.recvCheckBufp[0])->loadRequest; // Request Load
|
||||
}
|
||||
return gMultiSioArea.recvSuccessFlags;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Start Multi-play Communication */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
void MultiSioStart(void)
|
||||
{
|
||||
if (gMultiSioArea.type)
|
||||
gMultiSioArea.startFlag = 1; // Set Start Flag
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Stop Multi-play Communication */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
void MultiSioStop(void)
|
||||
{
|
||||
REG_IME = 0;
|
||||
REG_IE &= ~(INTR_FLAG_SERIAL | MULTI_SIO_TIMER_INTR_FLAG); // Disable SIO & Timer Interrupt
|
||||
REG_IME = 1;
|
||||
REG_SIOCNT = SIO_MULTI_MODE | MULTI_SIO_BAUD_RATE_NO; // Stop SIO
|
||||
REG_MULTI_SIO_TIMER = MULTI_SIO_TIMER_COUNT; // Stop Timer
|
||||
REG_IF = INTR_FLAG_SERIAL | MULTI_SIO_TIMER_INTR_FLAG; // Reset IF
|
||||
gMultiSioArea.startFlag = 0; // Reset Start Flag
|
||||
}
|
||||
|
||||
/*==================================================================*/
|
||||
/* Multi-play Communication Interrupt Routine */
|
||||
/*==================================================================*/
|
||||
|
||||
#ifndef MULTI_SIO_DI_FUNC_FAST
|
||||
void MultiSioIntr(void)
|
||||
{
|
||||
u16 recvTmp[4];
|
||||
u16 *bufpTmp;
|
||||
s32 i;
|
||||
UNUSED s32 ii; // declared in SDK
|
||||
|
||||
// Save Receive Data
|
||||
*(u64 *)recvTmp = *(u64 *)REG_ADDR_SIOMLT_RECV;
|
||||
// Detect hard error
|
||||
gMultiSioArea.hardError = ((struct SioMultiCnt *)REG_ADDR_SIOCNT)->error;
|
||||
// Send Data Processing
|
||||
if (gMultiSioArea.sendBufCounter == -1)
|
||||
{ // Set Synchronized Data
|
||||
((struct SioMultiCnt *)REG_ADDR_SIOCNT)->data = MULTI_SIO_SYNC_DATA;
|
||||
bufpTmp = gMultiSioArea.currentSendBufp; // Change Send Buffer
|
||||
gMultiSioArea.currentSendBufp = gMultiSioArea.nextSendBufp;
|
||||
gMultiSioArea.nextSendBufp = bufpTmp;
|
||||
}
|
||||
else if (gMultiSioArea.sendBufCounter >= 0)
|
||||
{ // Set Send Data
|
||||
((struct SioMultiCnt *)REG_ADDR_SIOCNT)->data = gMultiSioArea.currentSendBufp[gMultiSioArea.sendBufCounter];
|
||||
}
|
||||
if (gMultiSioArea.sendBufCounter < (s32)(sizeof(struct MultiSioPacket) / 2 - 1))
|
||||
++gMultiSioArea.sendBufCounter;
|
||||
// Receive Data Processing (Max. Approx. 350 Clocks/Included in wait period)
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
if (recvTmp[i] == MULTI_SIO_SYNC_DATA
|
||||
&& gMultiSioArea.recvBufCounter[i] > (s32)(sizeof(struct MultiSioPacket) / 2 - 3))
|
||||
{
|
||||
gMultiSioArea.recvBufCounter[i] = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
gMultiSioArea.currentRecvBufp[i][gMultiSioArea.recvBufCounter[i]] = recvTmp[i];
|
||||
// Store Receive Data
|
||||
if (gMultiSioArea.recvBufCounter[i] == (s32)(sizeof(struct MultiSioPacket) / 2 - 3))
|
||||
{
|
||||
bufpTmp = gMultiSioArea.lastRecvBufp[i]; // Change Receive Buffer
|
||||
gMultiSioArea.lastRecvBufp[i] = gMultiSioArea.currentRecvBufp[i];
|
||||
gMultiSioArea.currentRecvBufp[i] = bufpTmp;
|
||||
gMultiSioArea.syncRecvFlag[i] = 1; // Receive Complete Flag
|
||||
}
|
||||
}
|
||||
if (gMultiSioArea.recvBufCounter[i] < (s32)(sizeof(struct MultiSioPacket) / 2 - 1))
|
||||
++gMultiSioArea.recvBufCounter[i];
|
||||
}
|
||||
// Start Master Send
|
||||
if (gMultiSioArea.type == SIO_MULTI_PARENT)
|
||||
{
|
||||
REG_MULTI_SIO_TIMER_H = 0; // Stop Timer
|
||||
REG_SIOCNT |= SIO_ENABLE; // Restart Send
|
||||
REG_MULTI_SIO_TIMER_H = TIMER_1CLK | TIMER_INTR_ENABLE | TIMER_ENABLE; // Restart Timer
|
||||
}
|
||||
}
|
||||
#endif
|
215
src/powf_error_handler.c
Normal file
215
src/powf_error_handler.c
Normal file
@ -0,0 +1,215 @@
|
||||
#include "global.h"
|
||||
|
||||
// lib function but doesn't match any known signature.
|
||||
|
||||
// fdlibm.h
|
||||
#define HUGE ((float)3.40282346638528860e+38)
|
||||
|
||||
// math.h
|
||||
union __dmath {
|
||||
__uint32_t i[2];
|
||||
double d;
|
||||
};
|
||||
|
||||
#define DOMAIN 1
|
||||
#define SING 2
|
||||
#define OVERFLOW 3
|
||||
#define UNDERFLOW 4
|
||||
#define TLOSS 5
|
||||
#define PLOSS 6
|
||||
|
||||
extern const union __dmath __infinity;
|
||||
|
||||
#define HUGE_VAL (__infinity.d)
|
||||
|
||||
struct exception
|
||||
{
|
||||
int type;
|
||||
const char *name;
|
||||
double arg1;
|
||||
double arg2;
|
||||
double retval;
|
||||
int err;
|
||||
};
|
||||
|
||||
float __ieee754_powf (float, float);
|
||||
int isnanf(float x);
|
||||
int matherr(struct exception *exc);
|
||||
int finitef(float x);
|
||||
double rint(double x);
|
||||
|
||||
// sys/errno.h
|
||||
#define EDOM 33 /* Math arg out of domain of func */
|
||||
#define ERANGE 34 /* Math result not representable */
|
||||
int *__errno(void);
|
||||
|
||||
// mislinked data section - -
|
||||
union __dmath gUnk_08D60950 = { .i = {0x7ff00000, 0} }; // infinity
|
||||
s32 gUnk_08D60958 = 1;
|
||||
|
||||
static const char gUnk_08D608BC[] = "powf";
|
||||
|
||||
f32 powferrorhandler(f32 x, f32 y)
|
||||
{
|
||||
struct exception e;
|
||||
union __dmath sp24;
|
||||
f32 r4 = __ieee754_powf(x, y);
|
||||
s32 r9 = gUnk_08D60958;
|
||||
|
||||
if (r9 == -1)
|
||||
return r4;
|
||||
if (isnanf(y) != 0)
|
||||
return r4;
|
||||
if (isnanf(x) != 0)
|
||||
{
|
||||
if (y == 0.0f)
|
||||
{
|
||||
e.type = DOMAIN;
|
||||
e.name = gUnk_08D608BC;
|
||||
e.err = 0;
|
||||
e.arg1 = x;
|
||||
e.arg2 = y;
|
||||
e.retval = x;
|
||||
if (r9 == 2)
|
||||
e.retval = 1.0;
|
||||
else
|
||||
{
|
||||
if (matherr(&e) == 0)
|
||||
*__errno() = EDOM;
|
||||
}
|
||||
if (e.err != 0)
|
||||
*__errno() = e.err;
|
||||
return e.retval;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x == 0.0f)
|
||||
{
|
||||
if (y == 0.0f)
|
||||
{
|
||||
e.type = DOMAIN;
|
||||
e.name = gUnk_08D608BC;
|
||||
e.err = 0;
|
||||
e.arg1 = x;
|
||||
e.arg2 = y;
|
||||
e.retval = 0.0;
|
||||
if (r9 != 0)
|
||||
e.retval = 1.0;
|
||||
else
|
||||
{
|
||||
if (matherr(&e) == 0)
|
||||
*__errno() = EDOM;
|
||||
}
|
||||
if (e.err != 0)
|
||||
*__errno() = e.err;
|
||||
return e.retval;
|
||||
}
|
||||
else
|
||||
{
|
||||
// _08159468
|
||||
if (finitef(y) == 0)
|
||||
return r4;
|
||||
if (y < 0.0f)
|
||||
{
|
||||
e.type = DOMAIN;
|
||||
e.name = gUnk_08D608BC;
|
||||
e.err = 0;
|
||||
e.arg1 = x;
|
||||
e.arg2 = y;
|
||||
if (r9 == 0)
|
||||
e.retval = 0.0;
|
||||
else
|
||||
e.retval = -gUnk_08D60950.d;
|
||||
if (gUnk_08D60958 == 2 || matherr(&e) == 0)
|
||||
*__errno() = EDOM;
|
||||
if (e.err != 0)
|
||||
*__errno() = e.err;
|
||||
return e.retval;
|
||||
}
|
||||
else
|
||||
return r4;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (finitef(r4) == 0 && finitef(x) != 0 && finitef(y) != 0)
|
||||
{
|
||||
if (isnanf(r4) != 0)
|
||||
{
|
||||
e.type = 1;
|
||||
e.name = gUnk_08D608BC;
|
||||
e.err = 0;
|
||||
e.arg1 = x;
|
||||
e.arg2 = y;
|
||||
if (r9 == 0)
|
||||
e.retval = 0.0;
|
||||
else
|
||||
{
|
||||
union __d_math_2
|
||||
{
|
||||
f64 d;
|
||||
s64 i;
|
||||
};
|
||||
e.retval = ((union __d_math_2)((s64)0xFFFFFFFF7FFFFFFF)).d;
|
||||
}
|
||||
if (gUnk_08D60958 == 2 || matherr(&e) == 0)
|
||||
*__errno() = EDOM;
|
||||
if (e.err != 0)
|
||||
*__errno() = e.err;
|
||||
return e.retval;
|
||||
}
|
||||
else
|
||||
{
|
||||
e.type = OVERFLOW;
|
||||
e.name = gUnk_08D608BC;
|
||||
e.err = 0;
|
||||
e.arg1 = x;
|
||||
e.arg2 = y;
|
||||
if (r9 == 0)
|
||||
{
|
||||
e.retval = HUGE;
|
||||
y *= 5e-1;
|
||||
if (x < 0.0)
|
||||
{
|
||||
if(rint(y) != y)
|
||||
e.retval = -HUGE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sp24 = gUnk_08D60950;
|
||||
e.retval = sp24.d;
|
||||
y *= 5e-1;
|
||||
if (x < 0.0)
|
||||
{
|
||||
if(rint(y) != y)
|
||||
e.retval = -sp24.d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (r4 == 0.0f && finitef(x) != 0 && finitef(y) != 0)
|
||||
{
|
||||
e.type = UNDERFLOW;
|
||||
e.name = gUnk_08D608BC;
|
||||
e.err = 0;
|
||||
e.arg1 = x;
|
||||
e.arg2 = y;
|
||||
e.retval = 0.0;
|
||||
}
|
||||
else
|
||||
return r4;
|
||||
}
|
||||
if (gUnk_08D60958 == 2 || matherr(&e) == 0)
|
||||
*__errno() = ERANGE;
|
||||
if (e.err != 0)
|
||||
*__errno() = e.err;
|
||||
return e.retval;
|
||||
}
|
||||
}
|
||||
return r4;
|
||||
}
|
176
src/sio32_multi_load.c
Normal file
176
src/sio32_multi_load.c
Normal file
@ -0,0 +1,176 @@
|
||||
#include "sio32_multi_load.h"
|
||||
|
||||
static const u8 sMultiSioLibVer[] = "Sio32MultiLoad010214";
|
||||
|
||||
// COMMON
|
||||
// struct Sio32MultiLoadArea gSio32MultiLoadArea; // 32bit serial communication multi-load work area
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* 32bit serial communication multi-load main */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
u32 Sio32MultiLoadMain(u32 *progressCounterp)
|
||||
{
|
||||
s32 dataCounter, dataCounterBak;
|
||||
UNUSED s32 i, ii; // declared in SDK
|
||||
|
||||
switch (gSio32MultiLoadArea.state)
|
||||
{
|
||||
case 0:
|
||||
if (gSio32MultiLoadArea.type || gSio32MultiLoadArea.frameCounter) // Slave SIO Mode switch delay wait
|
||||
gSio32MultiLoadArea.state = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (gSio32MultiLoadArea.type == SIO_SCK_IN)
|
||||
{
|
||||
if (gSio32MultiLoadArea.frameCounter < SIO32ML_MODE_WAIT_FRAMES) // Master wait
|
||||
break;
|
||||
}
|
||||
else // Slave
|
||||
REG_SIOCNT = SIO_32BIT_MODE; // Switches to SIO mode
|
||||
REG_SIODATA32 = 0; // Clears data registery
|
||||
REG_IF = INTR_FLAG_SERIAL | SIO32ML_TIMER_INTR_FLAG; // Resets IF
|
||||
if (gSio32MultiLoadArea.type == SIO_SCK_IN)
|
||||
{ // Sets Master
|
||||
REG_SIOCNT |= SIO_ENABLE; // Starts communication
|
||||
REG_SIO32ML_TIMER = SIO32ML_TIMER_COUNT | ((TIMER_1CLK | TIMER_INTR_ENABLE | TIMER_ENABLE) << 16); // Starts timer
|
||||
REG_IME = 0;
|
||||
REG_IE |= SIO32ML_TIMER_INTR_FLAG; // Enables timer interrupt
|
||||
REG_IME = 1;
|
||||
}
|
||||
else
|
||||
{ // Sets Slave
|
||||
REG_SIOCNT |= SIO_IF_ENABLE | SIO_ENABLE; // Starts communication
|
||||
REG_IME = 0;
|
||||
REG_IE |= INTR_FLAG_SERIAL; // Enables SIO interrupt
|
||||
REG_IME = 1;
|
||||
}
|
||||
gSio32MultiLoadArea.frameCounter = 0;
|
||||
gSio32MultiLoadArea.state = 2;
|
||||
break;
|
||||
case 2:
|
||||
dataCounter = gSio32MultiLoadArea.dataCounter;
|
||||
dataCounterBak = dataCounter;
|
||||
if (dataCounter > SIO32ML_BLOCK_SIZE / 4)
|
||||
dataCounter = SIO32ML_BLOCK_SIZE / 4;
|
||||
else if (dataCounter < 0)
|
||||
dataCounter = 0;
|
||||
if (progressCounterp)
|
||||
*progressCounterp = dataCounter; // Set progress counter
|
||||
if (gSio32MultiLoadArea.type != SIO_SCK_IN)
|
||||
{ // Slave
|
||||
while (gSio32MultiLoadArea.checkSumCounter < dataCounter) // Receiving data sum check
|
||||
gSio32MultiLoadArea.checkSumTmp += ((s32 *)gSio32MultiLoadArea.datap)[gSio32MultiLoadArea.checkSumCounter++];
|
||||
if (dataCounterBak > SIO32ML_BLOCK_SIZE / 4)
|
||||
if ((gSio32MultiLoadArea.checkSum += gSio32MultiLoadArea.checkSumTmp) == -1)
|
||||
gSio32MultiLoadArea.downloadSuccessFlag = 1; // Succeeds download
|
||||
}
|
||||
if (dataCounterBak > SIO32ML_BLOCK_SIZE / 4 // Complete communication
|
||||
|| gSio32MultiLoadArea.frameCounter == 0x8C) // SIO32ML_LD_TIMEOUT_FRAMES in SDK doesn't match
|
||||
gSio32MultiLoadArea.state = 3; // Load time out
|
||||
break;
|
||||
case 3:
|
||||
REG_IME = 0;
|
||||
REG_IE &= ~(INTR_FLAG_SERIAL | SIO32ML_TIMER_INTR_FLAG); // Disables SIO and timer interrupt
|
||||
REG_IME = 1;
|
||||
REG_SIOCNT = SIO_32BIT_MODE; // Stops SIO32
|
||||
*(vu32 *)REG_ADDR_SIOCNT = SIO_MULTI_MODE; // Switches to SIO mode
|
||||
*(vu32 *)REG_ADDR_SIOCNT = SIO_MULTI_MODE | MULTI_SIO_BAUD_RATE_NO;
|
||||
*(vu64 *)REG_ADDR_SIODATA32 = 0; // Clears data register
|
||||
if (gSio32MultiLoadArea.type) // Master
|
||||
REG_SIO32ML_TIMER = 0; // Resets timer
|
||||
REG_IF = INTR_FLAG_SERIAL | SIO32ML_TIMER_INTR_FLAG; // Resets IF
|
||||
if (!gSio32MultiLoadArea.type)
|
||||
return 1; // Slave comes back first
|
||||
gSio32MultiLoadArea.frameCounter = 0;
|
||||
gSio32MultiLoadArea.state = 4;
|
||||
break;
|
||||
case 4:
|
||||
if (gSio32MultiLoadArea.frameCounter >= 3) // Master comes back later
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
++gSio32MultiLoadArea.frameCounter;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==================================================================*/
|
||||
/* 32bit Serial Communication Multi-load Interrupt Routine */
|
||||
/*==================================================================*/
|
||||
|
||||
void Sio32MultiLoadIntr(void)
|
||||
{
|
||||
u32 recvTmp;
|
||||
u32 *bufpTmp;
|
||||
|
||||
// Saves received data
|
||||
recvTmp = REG_SIODATA32;
|
||||
// Slave prepares to receive
|
||||
if (gSio32MultiLoadArea.type != SIO_SCK_IN)
|
||||
REG_SIOCNT |= SIO_ENABLE;
|
||||
if (gSio32MultiLoadArea.type == SIO_SCK_IN)
|
||||
{
|
||||
REG_SIO32ML_TIMER_H = 0; // Stops timer
|
||||
// Process sending data
|
||||
if (gSio32MultiLoadArea.dataCounter < 0) // Sets synchronous data
|
||||
REG_SIODATA32 = SIO32ML_SYNC_DATA;
|
||||
else if (gSio32MultiLoadArea.dataCounter < SIO32ML_BLOCK_SIZE / 4) // Sets sending data
|
||||
REG_SIODATA32 = gSio32MultiLoadArea.datap[gSio32MultiLoadArea.dataCounter];
|
||||
else
|
||||
REG_SIODATA32 = gSio32MultiLoadArea.checkSum; // Sets check sum
|
||||
}
|
||||
else
|
||||
{
|
||||
// Process receiving data
|
||||
if (gSio32MultiLoadArea.dataCounter < 0)
|
||||
{ // Checks synchronous data
|
||||
if (recvTmp != SIO32ML_SYNC_DATA)
|
||||
--gSio32MultiLoadArea.dataCounter;
|
||||
}
|
||||
else if (gSio32MultiLoadArea.dataCounter < SIO32ML_BLOCK_SIZE / 4) // Saves receiving data
|
||||
gSio32MultiLoadArea.datap[gSio32MultiLoadArea.dataCounter] = recvTmp;
|
||||
else
|
||||
gSio32MultiLoadArea.checkSum = recvTmp; // Saves check sum
|
||||
}
|
||||
if (gSio32MultiLoadArea.dataCounter < SIO32ML_BLOCK_SIZE / 4 + 3)
|
||||
{
|
||||
++gSio32MultiLoadArea.dataCounter;
|
||||
// Master starts to sending
|
||||
if (gSio32MultiLoadArea.type == SIO_SCK_IN)
|
||||
{
|
||||
REG_SIOCNT |= SIO_ENABLE; // Restarts sending
|
||||
REG_SIO32ML_TIMER_H = TIMER_1CLK | TIMER_INTR_ENABLE | TIMER_ENABLE; // Restarts timer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* 32bit Serial communication multi-load initialization */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
void Sio32MultiLoadInit(u32 type, void *datap)
|
||||
{
|
||||
s32 checkSum = 0;
|
||||
UNUSED s32 i; // declared in SDK
|
||||
|
||||
REG_IME = 0;
|
||||
REG_IE &= ~(INTR_FLAG_SERIAL | SIO32ML_TIMER_INTR_FLAG); // Disables SIO and timer interrupt
|
||||
REG_IME = 1;
|
||||
CpuFill32(0, &gSio32MultiLoadArea, sizeof(gSio32MultiLoadArea)); // Clears 32bit serial communication work area
|
||||
#ifdef SIO32ML_DI_FUNC_FAST // Copies function
|
||||
CpuCopy32(Sio32MultiLoadIntr, gMultiSioIntrFuncBuf, sizeof(gMultiSioIntrFuncBuf));
|
||||
#endif
|
||||
*(vu32 *)REG_ADDR_SIOCNT = SIO_MULTI_MODE | MULTI_SIO_BAUD_RATE_NO; // Stops multi-play communication
|
||||
gSio32MultiLoadArea.datap = datap; // Sets data pointer
|
||||
gSio32MultiLoadArea.dataCounter = -1;
|
||||
if (type)
|
||||
{ // Sets Master
|
||||
REG_SIO32ML_TIMER = 0; // Resets timer
|
||||
gSio32MultiLoadArea.type = SIO_SCK_IN;
|
||||
for (i = 0; i < SIO32ML_BLOCK_SIZE / 4; ++i) // Calculates sending data check sum
|
||||
checkSum += ((s32 *)datap)[i];
|
||||
gSio32MultiLoadArea.checkSum = ~checkSum;
|
||||
REG_SIOCNT = SIO_32BIT_MODE; // Switches to SIO mode (preceding code)
|
||||
REG_SIOCNT = SIO_32BIT_MODE | SIO_SCK_IN | SIO_IN_SCK_256K;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user