wip cleanup
This commit is contained in:
parent
6c197981f6
commit
455384c501
27 changed files with 232 additions and 356 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
*.o
|
||||||
|
out
|
8
.vscode/c_cpp_properties.json
vendored
8
.vscode/c_cpp_properties.json
vendored
|
@ -3,7 +3,6 @@
|
||||||
{
|
{
|
||||||
"name": "Linux",
|
"name": "Linux",
|
||||||
"compilerPath": "${DEVKITPPC}/bin/powerpc-eabi-cpp",
|
"compilerPath": "${DEVKITPPC}/bin/powerpc-eabi-cpp",
|
||||||
"cppStandard": "c++11",
|
|
||||||
"includePath": [
|
"includePath": [
|
||||||
"${workspaceFolder}/include/**",
|
"${workspaceFolder}/include/**",
|
||||||
"${DEVKITPPC}/include/**",
|
"${DEVKITPPC}/include/**",
|
||||||
|
@ -15,7 +14,12 @@
|
||||||
"browse": {
|
"browse": {
|
||||||
"limitSymbolsToIncludedHeaders": true,
|
"limitSymbolsToIncludedHeaders": true,
|
||||||
"databaseFilename": ""
|
"databaseFilename": ""
|
||||||
}
|
},
|
||||||
|
"cStandard": "c99",
|
||||||
|
"configurationProvider": "ms-vscode.makefile-tools",
|
||||||
|
"defines": [
|
||||||
|
"VERSION=2"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version": 4
|
"version": 4
|
||||||
|
|
9
.vscode/settings.json
vendored
Normal file
9
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"*.h": "c",
|
||||||
|
"*.c": "c"
|
||||||
|
},
|
||||||
|
"editor.autoIndent": "full",
|
||||||
|
"editor.tabSize": 2,
|
||||||
|
"editor.formatOnSave": true
|
||||||
|
}
|
52
Makefile
Normal file
52
Makefile
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
CC := powerpc-eabi-gcc
|
||||||
|
CFLAGS := -D VERSION=${VERSION} -Os -I. -Wa,-mregnames,-mgekko -Wall -fno-asynchronous-unwind-tables -fno-unwind-tables
|
||||||
|
|
||||||
|
AS := powerpc-eabi-as
|
||||||
|
ASFLAGS := -mregnames -mgekko
|
||||||
|
|
||||||
|
OD := powerpc-eabi-objdump
|
||||||
|
ODFLAGS := -EB -D -b binary -m powerpc:750 -M gekko --full-content
|
||||||
|
|
||||||
|
LD := powerpc-eabi-ld
|
||||||
|
|
||||||
|
OBJCOPY := powerpc-eabi-objcopy
|
||||||
|
PYTHON := python3
|
||||||
|
|
||||||
|
SRC_DIR := source
|
||||||
|
INC_DIR := include
|
||||||
|
OUT_DIR := out
|
||||||
|
OBJ_DIR := obj
|
||||||
|
|
||||||
|
LD_FILE := sms.ld
|
||||||
|
OUT_MAP := main.map
|
||||||
|
|
||||||
|
OUT_MAIN := main.out
|
||||||
|
OUT_BIN := main.bin
|
||||||
|
OUT_ASM := main.asm
|
||||||
|
|
||||||
|
SRC_FILES := $(wildcard source/*.c)
|
||||||
|
OBJ_FILES := $(SRC_FILES:.c=.o)
|
||||||
|
|
||||||
|
OBJS := main.o card.o
|
||||||
|
blockCount := 7
|
||||||
|
|
||||||
|
all: $(OUT_DIR)/$(OUT_BIN) $(OUT_DIR)/$(OUT_ASM)
|
||||||
|
|
||||||
|
$(OUT_DIR)/$(OUT_ASM): $(OUT_DIR)/$(OUT_BIN)
|
||||||
|
$(OD) $(ODFLAGS) $(OUT_DIR)/${OUT_BIN} > $(OUT_DIR)/$(OUT_ASM)
|
||||||
|
|
||||||
|
$(OUT_DIR)/$(OUT_BIN): $(OUT_DIR)/$(OUT_MAIN)
|
||||||
|
$(OBJCOPY) -O binary $< $@
|
||||||
|
|
||||||
|
$(OUT_DIR)/$(OUT_MAIN): $(OBJ_FILES) $(LD_FILE) $(OUT_DIR)
|
||||||
|
$(LD) -o $@ -T $(LD_FILE) -Map $(OUT_DIR)/$(OUT_MAP) -r $(OBJ_FILES)
|
||||||
|
|
||||||
|
$(OBJ_FILES): $(SRC_FILES)
|
||||||
|
$(CC) $(CFLAGS) -I $(INC_DIR) -o $@ -c $(@:.o=.c)
|
||||||
|
|
||||||
|
$(OUT_DIR):
|
||||||
|
mkdir -p $@
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
$(RM) -rv $(OUT_DIR) $(OBJ_FILES)
|
|
@ -1,80 +0,0 @@
|
||||||
.file "ReadFile.c"
|
|
||||||
.machine ppc
|
|
||||||
.section ".text"
|
|
||||||
.globl onReadOptionBlock
|
|
||||||
.type onReadOptionBlock, @function
|
|
||||||
onReadOptionBlock:
|
|
||||||
.LFB0:
|
|
||||||
stwu 1,-32(1)
|
|
||||||
#mflr 0
|
|
||||||
stmw 27,12(1)
|
|
||||||
lis 29,0x817f
|
|
||||||
ori 29,29,0xe800
|
|
||||||
lis 28,0xabcd
|
|
||||||
lwz 9,0(29)
|
|
||||||
ori 28,28,0x1234
|
|
||||||
#stw 0,36(1)
|
|
||||||
mr 30,3
|
|
||||||
cmpw 0,9,28
|
|
||||||
mr 31,4
|
|
||||||
beq- 0,.L3
|
|
||||||
lis 9,mount_@ha
|
|
||||||
li 4,1
|
|
||||||
la 9,mount_@l(9)
|
|
||||||
mtctr 9
|
|
||||||
bctrl
|
|
||||||
cmpwi 0,3,0
|
|
||||||
bne- 0,.L3
|
|
||||||
lis 9,CARDOpen@ha
|
|
||||||
la 9,CARDOpen@l(9)
|
|
||||||
lwz 3,0(30)
|
|
||||||
mr 5,31
|
|
||||||
bl .LC0
|
|
||||||
.string "gct"
|
|
||||||
.section ".text"
|
|
||||||
.align 2
|
|
||||||
.LC0: mflr 4
|
|
||||||
mtctr 9
|
|
||||||
bctrl
|
|
||||||
cmpwi 0,3,0
|
|
||||||
bne- 0,.L3
|
|
||||||
lis 27,0x817f
|
|
||||||
lis 9,CARDRead@ha
|
|
||||||
la 9,CARDRead@l(9)
|
|
||||||
ori 27,27,0xa800
|
|
||||||
li 6,0
|
|
||||||
li 5,16384
|
|
||||||
mr 4,27
|
|
||||||
mr 3,31
|
|
||||||
mtctr 9
|
|
||||||
bctrl
|
|
||||||
cmpwi 0,3,0
|
|
||||||
bne- 0,.L5
|
|
||||||
lwz 9,0(27)
|
|
||||||
xoris 10,9,0xff2f
|
|
||||||
cmpwi 0,10,-16162
|
|
||||||
bne 0,.L5
|
|
||||||
lis 10,0x817f
|
|
||||||
ori 10,10,0xa804
|
|
||||||
lwz 10,0(10)
|
|
||||||
cmpw 0,10,9
|
|
||||||
bne+ 0,.L5
|
|
||||||
stw 28,0(29)
|
|
||||||
.L5:
|
|
||||||
lis 9,CARDClose@ha
|
|
||||||
mr 3,31
|
|
||||||
la 9,CARDClose@l(9)
|
|
||||||
mtctr 9
|
|
||||||
bctrl
|
|
||||||
.L3:
|
|
||||||
lis 9,open_@ha
|
|
||||||
mr 4,31
|
|
||||||
la 9,open_@l(9)
|
|
||||||
mr 3,30
|
|
||||||
mtctr 9
|
|
||||||
bctrl
|
|
||||||
lmw 27,12(1)
|
|
||||||
addi 1,1,32
|
|
||||||
.LFE0:
|
|
||||||
.size onReadOptionBlock, .-onReadOptionBlock
|
|
||||||
.ident "GCC: (devkitPPC release 41) 12.1.0"
|
|
68
ReadFile.c
68
ReadFile.c
|
@ -1,68 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char pad[20];
|
|
||||||
} CARDFileInfo;
|
|
||||||
typedef struct {
|
|
||||||
int slot;
|
|
||||||
} TCardManager;
|
|
||||||
|
|
||||||
/** For NTSC-J 1.0:
|
|
||||||
*
|
|
||||||
* mount_ 80107b50
|
|
||||||
* open_ 801072f4
|
|
||||||
* CARDOpen 800a3cac
|
|
||||||
* CARDRead 800a4640
|
|
||||||
* CARDClose 800a3e24
|
|
||||||
*
|
|
||||||
* onReadOptionBlock 801069f4
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef int bool;
|
|
||||||
int mount_(TCardManager *this, bool);
|
|
||||||
int open_(TCardManager *this, CARDFileInfo*);
|
|
||||||
int CARDOpen(int slot, const char *fileName, CARDFileInfo*);
|
|
||||||
int CARDRead(CARDFileInfo *fileInfo, void *buf, unsigned long size, unsigned long offset);
|
|
||||||
int CARDClose(CARDFileInfo *fileInfo);
|
|
||||||
|
|
||||||
#define fileName "gct"
|
|
||||||
#define dst ((void*)0x817FA800)
|
|
||||||
#define size 0x4000 // 2 blocks
|
|
||||||
#define magicAddr (dst+size)
|
|
||||||
#define magic 0xabcd1234
|
|
||||||
int onReadOptionBlock(TCardManager *this, CARDFileInfo *fileInfo) {
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
// if magic is correct -> already loaded -> do not load again
|
|
||||||
if (*(unsigned int*)(magicAddr) == magic) goto orig;
|
|
||||||
|
|
||||||
// mount
|
|
||||||
if ((rc = mount_(this, 1))) goto orig;
|
|
||||||
|
|
||||||
// open file
|
|
||||||
if ((rc = CARDOpen(this->slot, fileName, fileInfo))) {
|
|
||||||
// TODO error handling
|
|
||||||
// if (rc == -4) // file not exists
|
|
||||||
goto orig;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read file to memory
|
|
||||||
if ((rc = CARDRead(fileInfo, dst, size, 0))) {
|
|
||||||
// should not fail if (dst, size) is properly set
|
|
||||||
} else {
|
|
||||||
// everything is good => apply gecko code
|
|
||||||
// TODO entry
|
|
||||||
// ((void(*)())0x817f4000)();
|
|
||||||
if (*(uint32_t*)(dst) == 0x00d0c0de && *(uint32_t*)(dst+4) == 0x00d0c0de) {
|
|
||||||
// is gct
|
|
||||||
*(uint32_t*)(magicAddr) = magic; // set magic to enable gecko code
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// close file
|
|
||||||
CARDClose(fileInfo);
|
|
||||||
|
|
||||||
orig:
|
|
||||||
// original function call
|
|
||||||
return open_(this, fileInfo);
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
$$ = 0;
|
|
||||||
|
|
||||||
/* TCardManager::cmdLoop() */
|
|
||||||
$C2$onReadOptionBlock = 0x801069f4;
|
|
5
example/.gitignore
vendored
5
example/.gitignore
vendored
|
@ -1,5 +0,0 @@
|
||||||
*.o
|
|
||||||
*.out
|
|
||||||
*.bin
|
|
||||||
*.gci
|
|
||||||
*.map
|
|
|
@ -1,31 +0,0 @@
|
||||||
CC = powerpc-eabi-gcc
|
|
||||||
AS = powerpc-eabi-as
|
|
||||||
LD = powerpc-eabi-ld
|
|
||||||
OBJCOPY = powerpc-eabi-objcopy
|
|
||||||
CFLAGS = -Os -I. -Wa,-mregnames,-mgekko -Wall -fno-asynchronous-unwind-tables -fno-unwind-tables
|
|
||||||
ASFLAGS = -mregnames -mgekko
|
|
||||||
PYTHON = python3
|
|
||||||
|
|
||||||
OBJS = _start.o gameLoop.o qfsync.o
|
|
||||||
LDFILE = sms.ld
|
|
||||||
MAPOUT = gci.map
|
|
||||||
|
|
||||||
GCI = 01-GMSJ-gct.gci
|
|
||||||
OBJOUT = a.out
|
|
||||||
OBJBIN = a.bin
|
|
||||||
blockCount = 7
|
|
||||||
|
|
||||||
all: $(GCI)
|
|
||||||
|
|
||||||
$(GCI): $(OBJBIN)
|
|
||||||
$(PYTHON) make-gci.py $(blockCount) $< $@
|
|
||||||
|
|
||||||
$(OBJOUT): $(OBJS) | $(LDFILE)
|
|
||||||
$(LD) -o $@ -T $(LDFILE) -Map $(MAPOUT) $^
|
|
||||||
$(OBJBIN): $(OBJOUT)
|
|
||||||
$(OBJCOPY) -O binary $^ $@
|
|
||||||
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
clean:
|
|
||||||
rm -f *.gci*.out *.bin *.o *.map
|
|
|
@ -1,38 +0,0 @@
|
||||||
.include "./macros.s"
|
|
||||||
|
|
||||||
.macro .rwbl src dst
|
|
||||||
li32 r3, \src
|
|
||||||
li32 r4, \dst
|
|
||||||
bl replace_with_bl
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.globl _start
|
|
||||||
_start: # right after gci loaded into RAM
|
|
||||||
mflr r11 # need to make sure r11 is not destroyed
|
|
||||||
|
|
||||||
## replace original instruction @src with `bl dst`
|
|
||||||
## TODO version
|
|
||||||
.rwbl 0x800f9a10, _gameLoop
|
|
||||||
.rwbl 0x800ecde0, _getQFSync
|
|
||||||
|
|
||||||
## return
|
|
||||||
mtlr r11
|
|
||||||
blr
|
|
||||||
|
|
||||||
/**
|
|
||||||
* r3 = address of original code
|
|
||||||
* r4 = address of practice code function
|
|
||||||
*/
|
|
||||||
replace_with_bl:
|
|
||||||
## bl from r3 to r4
|
|
||||||
sub r4, r4, r3
|
|
||||||
rlwinm r4, r4, 0, 6, 29
|
|
||||||
oris r4, r4, 0x4800
|
|
||||||
ori r4, r4, 0x1
|
|
||||||
stw r4, 0(r3)
|
|
||||||
## invalidate cache
|
|
||||||
dcbst 0, r3
|
|
||||||
sync
|
|
||||||
icbi 0, r3
|
|
||||||
isync
|
|
||||||
blr
|
|
|
@ -1,18 +0,0 @@
|
||||||
#include <sms.h>
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t qfsync : 2;
|
|
||||||
} CodeConfig;
|
|
||||||
extern CodeConfig config;
|
|
||||||
|
|
||||||
void _gameLoop(void *gamePad) {
|
|
||||||
// original function
|
|
||||||
TMarioGamePad_read(gamePad);
|
|
||||||
|
|
||||||
// check the controller input
|
|
||||||
uint16_t btn = JUTGamePad_mPadStatus.button;
|
|
||||||
config.qfsync =
|
|
||||||
btn == (PRESS_B | PRESS_DL) ? 2 : // 4x
|
|
||||||
btn == (PRESS_B | PRESS_DR) ? 3 : // 8x
|
|
||||||
0; // 1x
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
.macro li32 reg val
|
|
||||||
lis \reg, \val@h
|
|
||||||
ori \reg, \reg, \val@l
|
|
||||||
.endm
|
|
|
@ -1,3 +0,0 @@
|
||||||
int f(int x) {
|
|
||||||
return x*x;
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
.globl _getQFSync
|
|
||||||
_getQFSync:
|
|
||||||
lis r12, 0x8180
|
|
||||||
lwz r12, -0x4000(r12)
|
|
||||||
rlwinm. r12, r12, 2, 0x3
|
|
||||||
li r3, 600
|
|
||||||
slw r3, r3, r12
|
|
||||||
blr
|
|
|
@ -1,34 +0,0 @@
|
||||||
#ifndef SMS_H
|
|
||||||
#define SMS_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
void TMarioGamePad_read(void*);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t button;
|
|
||||||
int8_t stickX;
|
|
||||||
int8_t stickY;
|
|
||||||
int8_t substickX;
|
|
||||||
int8_t substickY;
|
|
||||||
uint8_t triggerLeft;
|
|
||||||
uint8_t triggerRight;
|
|
||||||
uint8_t analogA;
|
|
||||||
uint8_t analogB;
|
|
||||||
int8_t err;
|
|
||||||
} PADStatus;
|
|
||||||
extern PADStatus JUTGamePad_mPadStatus;
|
|
||||||
#define PRESS_START 0x1000
|
|
||||||
#define PRESS_Y 0x0800
|
|
||||||
#define PRESS_X 0x0400
|
|
||||||
#define PRESS_B 0x0200
|
|
||||||
#define PRESS_A 0x0100
|
|
||||||
#define PRESS_L 0x0040
|
|
||||||
#define PRESS_R 0x0020
|
|
||||||
#define PRESS_Z 0x0010
|
|
||||||
#define PRESS_DU 0x0008
|
|
||||||
#define PRESS_DD 0x0004
|
|
||||||
#define PRESS_DR 0x0002
|
|
||||||
#define PRESS_DL 0x0001
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,14 +0,0 @@
|
||||||
SECTIONS {
|
|
||||||
. = 0x817F0000;
|
|
||||||
.init : { _start.o }
|
|
||||||
.text : { *(.text) }
|
|
||||||
.rodata : { *(.rodata) }
|
|
||||||
.data : { *(.data) }
|
|
||||||
.bss : { *(.bss) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** TODO version */
|
|
||||||
TMarioGamePad_read = 0x800fba58;
|
|
||||||
JUTGamePad_mPadStatus = 0x80400d50;
|
|
||||||
|
|
||||||
config = 0x817fc000;
|
|
|
@ -1,10 +0,0 @@
|
||||||
.set dst, 0x817fa800
|
|
||||||
|
|
||||||
## backup r15 (pointer to current gecko instruction) at dst-4
|
|
||||||
add r0, r15, r4
|
|
||||||
lis r3, dst-4@ha
|
|
||||||
stwu r0, dst-4@l(r3)
|
|
||||||
## update r15 = dst + 8(header) - r4(this C0 code size)
|
|
||||||
addi r15, r3, 4+8
|
|
||||||
sub r15, r15, r4
|
|
||||||
blr
|
|
29
gecko-jump.s
29
gecko-jump.s
|
@ -1,29 +0,0 @@
|
||||||
.set gpApplication, 0x803e6000 # TODO version
|
|
||||||
.set dst, 0x817fb000
|
|
||||||
|
|
||||||
## TODO prevent softlock: check app state >= 4
|
|
||||||
lis r5, gpApplication+8@ha
|
|
||||||
lbz r5, gpApplication+8@l(r5)
|
|
||||||
cmplwi r5, 4
|
|
||||||
bltlr
|
|
||||||
## r5 = 00D0C0DE
|
|
||||||
lis r5, 0x00D0
|
|
||||||
ori r5, r5, 0xC0DE
|
|
||||||
## check if code is loaded (check header)
|
|
||||||
lis r3, dst@ha
|
|
||||||
### first 00D0C0DE
|
|
||||||
### r3 = &dst
|
|
||||||
lwzu r0, dst@l(r3)
|
|
||||||
cmplw r0, r5
|
|
||||||
bnelr
|
|
||||||
### second 00D0C0DE
|
|
||||||
lwz r0, 4(r3)
|
|
||||||
cmplw r0, r5
|
|
||||||
bnelr
|
|
||||||
## backup r15 (pointer to current gecko instruction) at dst-4
|
|
||||||
add r0, r15, r4
|
|
||||||
stw r0, -4(r3)
|
|
||||||
## update r15 = dst + 8(header) - r4(this C0 code size)
|
|
||||||
addi r15, r3, 8
|
|
||||||
sub r15, r15, r4
|
|
||||||
blr
|
|
|
@ -1,8 +0,0 @@
|
||||||
.set dst, 0x817fa800
|
|
||||||
|
|
||||||
## restore r15 (pointer to current gecko instruction) from dst-4
|
|
||||||
lis r3, dst-4@ha
|
|
||||||
lwz r15, dst-4@l(r3)
|
|
||||||
## update r15 = restored r15 - r4(this C0 code size)
|
|
||||||
sub r15, r15, r4
|
|
||||||
blr
|
|
11
include/card.h
Normal file
11
include/card.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
|
||||||
|
#include "gcn.h"
|
||||||
|
#include "sms.h"
|
||||||
|
|
||||||
|
#ifndef __CARD_H__
|
||||||
|
#define __CARD_H__
|
||||||
|
|
||||||
|
bool loadCard(TCardManager *cm, CARDFileInfo *fileInfo, char *fileName, u32 *dst);
|
||||||
|
|
||||||
|
#endif
|
33
include/gcn.h
Normal file
33
include/gcn.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
#ifndef __GCN_H__
|
||||||
|
#define __GCN_H__
|
||||||
|
|
||||||
|
#define CARD_SLOT_A 0
|
||||||
|
#define CARD_SLOT_B 1
|
||||||
|
|
||||||
|
#define MEM1_START 0x8000000
|
||||||
|
#define MEM1_END 0x81800000
|
||||||
|
|
||||||
|
typedef struct CARDFileInfo
|
||||||
|
{
|
||||||
|
s32 chan;
|
||||||
|
s32 fileNo;
|
||||||
|
|
||||||
|
s32 offset;
|
||||||
|
s32 length;
|
||||||
|
u16 iBlock;
|
||||||
|
} CARDFileInfo;
|
||||||
|
|
||||||
|
// typedef void (*CARDCallback)(s32 chan, s32 result);
|
||||||
|
|
||||||
|
s32 CARDOpen(s32 slot, const char *fileName, CARDFileInfo *fileInfo);
|
||||||
|
s32 CARDRead(CARDFileInfo *fileInfo, void *addr, s32 length, s32 offset);
|
||||||
|
s32 CARDClose(CARDFileInfo *fileInfo);
|
||||||
|
// s32 CARDProbeEx(s32 chan, s32 *memSize, s32 *sectorSize);
|
||||||
|
// s32 CARDMount(s32 chan, void *workArea, CARDCallback detachCallback);
|
||||||
|
s32 CARDUnmount(s32 chan);
|
||||||
|
|
||||||
|
#endif
|
26
include/sms.h
Normal file
26
include/sms.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef __SMS_H__
|
||||||
|
#define __SMS_H__
|
||||||
|
|
||||||
|
/** For NTSC-J 1.0:
|
||||||
|
*
|
||||||
|
* mount_ 80107b50
|
||||||
|
* open_ 801072f4
|
||||||
|
* CARDOpen 800a3cac
|
||||||
|
* CARDRead 800a4640
|
||||||
|
* CARDClose 800a3e24
|
||||||
|
*
|
||||||
|
* onReadOptionBlock 801069f4
|
||||||
|
*/
|
||||||
|
|
||||||
|
// static void *gpApplication = (void *)0x803e9700;
|
||||||
|
// static void *gpCardManager = (void *)0x8040a2b4;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int slot;
|
||||||
|
} TCardManager;
|
||||||
|
|
||||||
|
int mount_(TCardManager *this, bool);
|
||||||
|
int open_(TCardManager *this, CARDFileInfo *fileInfo);
|
||||||
|
|
||||||
|
#endif
|
15
include/typedefs.h
Normal file
15
include/typedefs.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef __TYPEDEF_H__
|
||||||
|
#define __TYPEDEF_H__
|
||||||
|
|
||||||
|
typedef int bool;
|
||||||
|
|
||||||
|
typedef unsigned long long u64;
|
||||||
|
typedef signed long long s64;
|
||||||
|
typedef unsigned int u32;
|
||||||
|
typedef signed int s32;
|
||||||
|
typedef unsigned short u16;
|
||||||
|
typedef signed short s16;
|
||||||
|
typedef unsigned char u8;
|
||||||
|
typedef signed char s8;
|
||||||
|
|
||||||
|
#endif
|
14
sms.ld
Normal file
14
sms.ld
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
mount_ = 0x80107b50;
|
||||||
|
open_ = 0x801072f4;
|
||||||
|
CARDOpen = 0x800a3cac;
|
||||||
|
CARDRead = 0x800a4640;
|
||||||
|
CARDClose = 0x800a3e24;
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
/* . = 0x817fa000; */
|
||||||
|
.text : { *(.text) }
|
||||||
|
.rodata : { *(.rodata) }
|
||||||
|
.data : { *(.data) }
|
||||||
|
.bss : { *(.bss) }
|
||||||
|
.sdata : { *(.sdata) }
|
||||||
|
}
|
25
source/card.c
Normal file
25
source/card.c
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#include "gcn.h"
|
||||||
|
#include "sms.h"
|
||||||
|
|
||||||
|
bool loadCard(TCardManager *cm, CARDFileInfo *fileInfo, char *fileName, u32 *dst)
|
||||||
|
{
|
||||||
|
// Mount the card
|
||||||
|
if (!mount_(cm, 1))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// Open the card
|
||||||
|
if (!CARDOpen(cm->slot, fileName, fileInfo))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// Too many codes
|
||||||
|
if (fileInfo->length > (MEM1_END - (u32)dst))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// Read codes into destination address
|
||||||
|
if (CARDRead(fileInfo, dst, fileInfo->length, 0))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// Done
|
||||||
|
CARDClose(fileInfo);
|
||||||
|
return 0;
|
||||||
|
}
|
39
source/main.c
Normal file
39
source/main.c
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#include "gcn.h"
|
||||||
|
#include "card.h"
|
||||||
|
|
||||||
|
#if VERSION == 1
|
||||||
|
#define FILENAME "GCT_GMSE01"
|
||||||
|
#elif VERSION == 2
|
||||||
|
#define FILENAME "GCT_GMSJ01"
|
||||||
|
#elif VERSION == 3
|
||||||
|
#define FILENAME "GCT_GMSP01"
|
||||||
|
#elif VERSION == 4
|
||||||
|
#define FILENAME "GCT_GMSJ0A"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Memory space reserved for Gecko codes to store their state
|
||||||
|
// data, based on the current usage
|
||||||
|
// See: https://github.com/BitPatty/gctGenerator/blob/375ba5eb73e50894d4e765fdfddbe004e3b4949d/Readme.md#reserved-memory
|
||||||
|
// Range: 0x817F0000 - 0x817F1000
|
||||||
|
#define ADDR_GECKO_HEAP_START 0x817F0000
|
||||||
|
#define ADDR_GECKO_HEAP_SIZE 0x00001000
|
||||||
|
#define ADDR_GECKO_HEAP_END (ADDR_GECKO_HEAP_START + ADDR_GECKO_HEAP_SIZE)
|
||||||
|
#define PTR_FLG_LOADED (bool *)ADDR_GECKO_HEAP_END
|
||||||
|
#define GECKO_CODE_START (ADDR_GECKO_HEAP_END + sizeof(*PTR_FLG_LOADED))
|
||||||
|
|
||||||
|
void loadCodes(TCardManager *cm, CARDFileInfo *fileInfo)
|
||||||
|
{
|
||||||
|
*PTR_FLG_LOADED = -1;
|
||||||
|
|
||||||
|
if (loadCard(cm, fileInfo, FILENAME, (void *)GECKO_CODE_START))
|
||||||
|
*PTR_FLG_LOADED = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// int onReadOptionBlock(TCardManager *this, CARDFileInfo *fileInfo)
|
||||||
|
// {
|
||||||
|
// if (*PTR_FLG_LOADED)
|
||||||
|
// return open_(this, fileInfo);
|
||||||
|
|
||||||
|
// loadCodes(this, fileInfo);
|
||||||
|
// return open_(this, fileInfo);
|
||||||
|
// }
|
Loading…
Reference in a new issue