wip cleanup

This commit is contained in:
Matteias Collet 2022-11-26 21:38:23 +00:00 committed by GitHub
parent 6c197981f6
commit 455384c501
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 232 additions and 356 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*.o
out

View file

@ -3,7 +3,6 @@
{
"name": "Linux",
"compilerPath": "${DEVKITPPC}/bin/powerpc-eabi-cpp",
"cppStandard": "c++11",
"includePath": [
"${workspaceFolder}/include/**",
"${DEVKITPPC}/include/**",
@ -15,7 +14,12 @@
"browse": {
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
},
"cStandard": "c99",
"configurationProvider": "ms-vscode.makefile-tools",
"defines": [
"VERSION=2"
]
}
],
"version": 4

9
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,9 @@
{
"files.associations": {
"*.h": "c",
"*.c": "c"
},
"editor.autoIndent": "full",
"editor.tabSize": 2,
"editor.formatOnSave": true
}

52
Makefile Normal file
View 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)

View file

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

View file

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

View file

@ -1,4 +0,0 @@
$$ = 0;
/* TCardManager::cmdLoop() */
$C2$onReadOptionBlock = 0x801069f4;

5
example/.gitignore vendored
View file

@ -1,5 +0,0 @@
*.o
*.out
*.bin
*.gci
*.map

View file

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

View file

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

View file

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

View file

@ -1,4 +0,0 @@
.macro li32 reg val
lis \reg, \val@h
ori \reg, \reg, \val@l
.endm

View file

@ -1,3 +0,0 @@
int f(int x) {
return x*x;
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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