mirror of
https://github.com/pret/pokestadium.git
synced 2026-09-27 13:41:34 -04:00
Merge pull request #39 from ProjectRevoTPP/decompile_hal_libc_tower
decompile hal_libc and gb_tower
This commit is contained in:
@@ -52,6 +52,9 @@ OBJDUMP_FLAGS := -d -r -z -Mreg-names=32
|
||||
|
||||
$(foreach dir,$(SRC_DIRS) $(ASM_DIRS) $(DATA_DIRS) $(COMPRESSED_DIRS) $(MAP_DIRS) $(BGM_DIRS),$(shell mkdir -p build/$(dir)))
|
||||
|
||||
# The reimplementations of the string functions need to treat char as signed.
|
||||
build/src/hal_libc.c.o: CFLAGS += -signed
|
||||
|
||||
# Libultra O1 files
|
||||
build/src/libultra/os/sendmesg.c.o: OPTFLAGS := -O1
|
||||
build/src/libultra/os/stopthread.c.o: OPTFLAGS := -O1
|
||||
|
||||
+443
@@ -0,0 +1,443 @@
|
||||
#include <ultra64.h>
|
||||
#include "controller.h"
|
||||
|
||||
extern s32 func_8000DAFC(void*, s32, u16, s32, s32);
|
||||
|
||||
// gb_tower.c
|
||||
// dont forget to pass -signed when compiling
|
||||
|
||||
extern OSPfs D_800A8100[];
|
||||
extern u8 D_800A82A0[];
|
||||
extern u8 D_800A82AC[];
|
||||
|
||||
extern u8 D_800A82A4;
|
||||
extern u8 D_800A82A5;
|
||||
extern u8 D_800A82A6;
|
||||
extern u8 D_800A82A7;
|
||||
extern s32 D_800A82A8;
|
||||
|
||||
// these first 4 funcs might be part of a hal_libc file or something instead of GB Tower.
|
||||
|
||||
s32 func_8000AEBC(s32 arg0, s32 arg1, u16 arg2, u16 arg3);
|
||||
s32 func_8000AF40(s32 arg0, void* arg1, u16 arg2, u16 arg3);
|
||||
|
||||
/*
|
||||
* Strcpy implementation; copy the strings terminated by 0. Return the original dest
|
||||
* pointer.
|
||||
*/
|
||||
char* HAL_Strcpy(char* dest, char* src) {
|
||||
char *newDest = dest;
|
||||
while ((*(newDest++) = *(src++)) != '\0') {
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
/*
|
||||
* Alternate strcpy implementation; return the post-increment altered dest pointer.
|
||||
*/
|
||||
char* HAL_Strcpy2(char *dest, char* src) {
|
||||
size_t c = strlen(dest); // this is completely pointless. the strlen func called
|
||||
// doesnt alter the pointer.
|
||||
while ((*(dest++) = *(src++)) != '\0') {
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
/*
|
||||
* Strcmp implementation. Compare two strings, terminated by 0. Return a 0 if success, return
|
||||
* a positive value if the 2nd string is "greater" than the 1st, and vice versa.
|
||||
*/
|
||||
size_t HAL_Strcmp(char* dest, char* src) {
|
||||
int c1 = *dest;
|
||||
int c2 = *src;
|
||||
// while the string values are the same...
|
||||
while (c1 == c2) {
|
||||
// ...once we hit a 0 terminator, we've reached the end of the strings.
|
||||
// Return a success.
|
||||
if (c1 == '\0') {
|
||||
return 0;
|
||||
}
|
||||
// Increment the strings and update the content values for comparison.
|
||||
c1 = *++dest;
|
||||
c2 = *++src;
|
||||
}
|
||||
// depending on where the mismatch occured, this subtraction operation
|
||||
// will result in the correctly expected sign for whichever string is
|
||||
// "greater".
|
||||
return c1-c2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Memset implementation. Given a value, set each byte in the given pointer to
|
||||
* this value for every byte across a given specified size. Return the original
|
||||
* pointer used.
|
||||
*/
|
||||
char* HAL_Memset(char* dest, s32 c, s32 nsize) {
|
||||
char* newDest = dest;
|
||||
|
||||
// While the size is not 0, keep decrementing. Oddly, HAL seems to have
|
||||
// xor'd the result instead of checking the logical result.
|
||||
while((nsize-- == 0) ^ 1) {
|
||||
*newDest++ = c;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
// TODO: These 0x20 sizes probably belong to a struct size or something. Use
|
||||
// that instead of assuming sizeof is the same
|
||||
s32 func_8000A630(s32 arg0, void* arg1) {
|
||||
u8 sp47;
|
||||
u8 sp24[0x20];
|
||||
s32 sp20 = 0;
|
||||
u8 padding[8];
|
||||
|
||||
if ((func_8000AF40(arg0, arg1, 0, 0x20) == 0)
|
||||
&& (func_8000AEBC(arg0, &sp24, 0, 0x20) == 0)
|
||||
&& (bcmp(&sp24, arg1, 0x20) == 0)
|
||||
&& (osGbpakGetStatus(&D_800A8100[arg0], &sp47) == 0))
|
||||
{
|
||||
sp20 = ((sp47 & 4) != 0) == 0;
|
||||
}
|
||||
return sp20;
|
||||
}
|
||||
|
||||
s32 func_8000A6D8(s32 arg0, u8* arg1) {
|
||||
s32 var_s0 = 0;
|
||||
u8 sp34[0x20];
|
||||
|
||||
if (arg1 == NULL) {
|
||||
arg1 = sp34;
|
||||
}
|
||||
HAL_Memset(arg1, 0x55, 0x20);
|
||||
if (func_8000A630(arg0, arg1) != 0) {
|
||||
HAL_Memset(arg1, 0xAA, 0x20);
|
||||
if (func_8000A630(arg0, arg1) != 0) {
|
||||
s32 i;
|
||||
for (i = 0; i < sizeof(sp34); i++) {
|
||||
arg1[i] = osGetCount();
|
||||
}
|
||||
var_s0 = func_8000A630(arg0, arg1);
|
||||
}
|
||||
}
|
||||
return var_s0;
|
||||
}
|
||||
|
||||
s32 func_8000A798(s32 arg0, u8* arg1, s32 arg2) {
|
||||
u8 status;
|
||||
OSGbpakId gbpakId;
|
||||
s32 sp28 = 0;
|
||||
|
||||
if (arg1 != NULL) {
|
||||
*arg1 = D_800A82A0[arg0];
|
||||
}
|
||||
|
||||
if (D_800A82A0[arg0] == 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (osGbpakReadId(&D_800A8100[arg0], &gbpakId, &status) != 0) {
|
||||
func_8002B274(arg0, 1);
|
||||
}
|
||||
if ((status & OS_GBPAK_RSTB_STATUS) && (osGbpakCheckConnector(&D_800A8100[arg0], &status) == 0)) {
|
||||
func_8000D970(&D_800A8100[arg0]);
|
||||
sp28 = func_8000A6D8(arg0, arg2);
|
||||
}
|
||||
D_800A82A0[arg0] = 1;
|
||||
return sp28;
|
||||
}
|
||||
|
||||
s32 func_8000A888(s32 arg0, u8 arg1) {
|
||||
u8 status;
|
||||
s32 temp_v1;
|
||||
|
||||
if (osGbpakGetStatus(&D_800A8100[arg0], &status) != 0) {
|
||||
func_8002B274(arg0, 1);
|
||||
}
|
||||
|
||||
temp_v1 = !((status & OS_GBPAK_RSTB_DETECTION) != 0);
|
||||
if (arg1 == 0) {
|
||||
osGbpakPower(&D_800A8100[arg0], 0);
|
||||
D_800A82A0[arg0] = 0;
|
||||
}
|
||||
return temp_v1;
|
||||
}
|
||||
|
||||
void func_8000A924(void) {
|
||||
s32 i;
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
if (D_800A82A4 & (1 << i)) {
|
||||
osGbpakPower(&D_800A8100[i], 0);
|
||||
D_800A82A0[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s32 func_8000A9D0(OSGbpakId* header) {
|
||||
// make sure its 0 terminated. dont want those dirty hackers abusing a Strcmp exploit
|
||||
header->game_title[15] = '\0';
|
||||
|
||||
// is the cartridge non-Japanese?
|
||||
if (header->country_code == 1) {
|
||||
// Which supported POKeMON version is this?
|
||||
if (HAL_Strcmp(header->game_title, "POKEMON RED") == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (HAL_Strcmp(header->game_title, "POKEMON GREEN") == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (HAL_Strcmp(header->game_title, "POKEMON BLUE") == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (HAL_Strcmp(header->game_title, "POKEMON YELLOW") == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// This is not a supported cartridge.
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 func_8000AA7C(void) {
|
||||
s32 i;
|
||||
s32 temp_v0;
|
||||
u8 status;
|
||||
OSGbpakId sp4C;
|
||||
|
||||
D_800A82A5 = 0;
|
||||
D_800A82A4 = 0;
|
||||
D_800A82A7 = 0;
|
||||
D_800A82A8 = 0;
|
||||
osPfsIsPlug(&gSIEventMesgQueue, &D_800A82A6);
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
if ((D_800A82A6 & (1 << i)) && ((i != 3) || (func_8000B4C4() == 0))) {
|
||||
if (osGbpakInit(&gSIEventMesgQueue, &D_800A8100[i], i) == 0) {
|
||||
D_800A82A4 |= (1 << i);
|
||||
temp_v0 = osGbpakReadId(&D_800A8100[i], &sp4C, &status);
|
||||
if (temp_v0 == 0) {
|
||||
if (!(status & 8)) {
|
||||
func_8002B274(i, 2);
|
||||
}
|
||||
if (func_8000A9D0(&sp4C) != 0) {
|
||||
if (temp_v0 == 4) {
|
||||
// what. the redundant temp_v0 functionless check is apparently needed to match.
|
||||
}
|
||||
if (osGbpakCheckConnector(&D_800A8100[i], &status) == 0) {
|
||||
func_8000D970(&D_800A8100[i]);
|
||||
D_800A82A0[i] = 1;
|
||||
D_800A82A5 |= (1 << i);
|
||||
} else {
|
||||
func_8002B274(i, 2);
|
||||
}
|
||||
} else {
|
||||
D_800A82A5 |= (1 << i);
|
||||
D_800A82A0[i] = 1;
|
||||
}
|
||||
} else {
|
||||
D_800A82A0[i] = 0;
|
||||
if (temp_v0 == 4) {
|
||||
func_8002B274(i, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (D_800A82A5 << 0x10) | D_800A82A4;
|
||||
}
|
||||
|
||||
s32 func_8000AC7C(s32 arg0) {
|
||||
u8 status;
|
||||
s32 ret = osGbpakGetStatus(&D_800A8100[arg0], &status);
|
||||
u8 filler;
|
||||
|
||||
// check the error code returned (if applicable) by the osGbpakGetStatus
|
||||
// call.
|
||||
if ((ret == PFS_ERR_NOPACK)
|
||||
|| (ret == PFS_ERR_DEVICE)
|
||||
|| (ret == PFS_ERR_CONTRFAIL)) {
|
||||
func_8002B274(arg0, 1);
|
||||
}
|
||||
return !((status & OS_GBPAK_GBCART_ON) != 0);
|
||||
}
|
||||
|
||||
s32 func_8000ACF4(s32 arg0) {
|
||||
u8 status;
|
||||
s32 ret = osGbpakGetStatus(&D_800A8100[arg0], &status);
|
||||
|
||||
if ((ret == PFS_ERR_NOPACK)
|
||||
|| (ret == PFS_ERR_DEVICE)
|
||||
|| (ret == PFS_ERR_CONTRFAIL)) {
|
||||
func_8002B274(arg0, 1);
|
||||
}
|
||||
return ((status & OS_GBPAK_GBCART_ON) != 0);
|
||||
}
|
||||
|
||||
s32 func_8000AD68(s32 arg0) {
|
||||
u8 filler[4];
|
||||
u8 status;
|
||||
OSGbpakId sp28;
|
||||
|
||||
D_800A82A0[arg0] = 0;
|
||||
if ((osGbpakInit(&gSIEventMesgQueue, &D_800A8100[arg0], arg0) == 0)
|
||||
&& (osGbpakReadId(&D_800A8100[arg0], &sp28, &status) == 0)
|
||||
&& (status & OS_GBPAK_RSTB_STATUS)
|
||||
&& (osGbpakCheckConnector(&D_800A8100[arg0], &status) == 0)) {
|
||||
|
||||
func_8000D970(&D_800A8100[arg0]);
|
||||
D_800A82A0[arg0] = 1;
|
||||
}
|
||||
|
||||
return D_800A82A0[arg0] == 1;
|
||||
}
|
||||
|
||||
s32 func_8000AE28(s32 arg0, void* arg1) {
|
||||
u8 status;
|
||||
u8 sp1C[0x20];
|
||||
s32 sp18;
|
||||
|
||||
sp18 = 0;
|
||||
if ((func_8000AEBC(arg0, &sp1C, 0, 0x20) == 0) && (bcmp(&sp1C, arg1, 0x20) == 0)
|
||||
&& (osGbpakGetStatus(&D_800A8100[arg0], &status) == 0)
|
||||
&& !(status & OS_GBPAK_RSTB_DETECTION)) {
|
||||
sp18 = 1;
|
||||
}
|
||||
return sp18;
|
||||
}
|
||||
|
||||
s32 func_8000AEBC(s32 arg0, s32 arg1, u16 arg2, u16 arg3) {
|
||||
s32 var_v1;
|
||||
|
||||
var_v1 = 1;
|
||||
if (D_800A82A5 & (1 << arg0)) {
|
||||
var_v1 = func_8000DAFC(&D_800A8100[arg0], 0, arg2, arg1, arg3);
|
||||
}
|
||||
return var_v1;
|
||||
}
|
||||
|
||||
s32 func_8000AF40(s32 arg0, void* arg1, u16 arg2, u16 arg3) {
|
||||
s32 var_v1;
|
||||
|
||||
var_v1 = 1;
|
||||
if (D_800A82A5 & (1 << arg0)) {
|
||||
var_v1 = func_8000DAFC(&D_800A8100[arg0], 1, arg2, arg1, arg3);
|
||||
}
|
||||
return var_v1;
|
||||
}
|
||||
|
||||
s32 func_8000AFC4(s32 arg0, u8 *arg1, u16 arg2, u16 arg3) {
|
||||
s32 var_v1;
|
||||
|
||||
var_v1 = 1;
|
||||
if (D_800A82A5 & (1 << arg0)) {
|
||||
var_v1 = osGbpakReadWrite(&D_800A8100[arg0], 0, arg2, arg1, arg3);
|
||||
}
|
||||
return var_v1;
|
||||
}
|
||||
|
||||
s32 func_8000B048(s32 arg0, u8 *arg1, u16 arg2, u16 arg3) {
|
||||
s32 var_v1;
|
||||
|
||||
var_v1 = 1;
|
||||
if (D_800A82A5 & (1 << arg0)) {
|
||||
var_v1 = osGbpakReadWrite(&D_800A8100[arg0], 1, arg2, arg1, arg3);
|
||||
}
|
||||
return var_v1;
|
||||
}
|
||||
|
||||
int func_8000B0CC(s32 arg0, s32 arg1) {
|
||||
u8 sp28[0x20];
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
for(i = 0; i < 0x20; i++) {
|
||||
sp28[i] = 0;
|
||||
}
|
||||
ret = func_8000B048(arg0, sp28, 0x5000U, 0x20U);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
for(i = 0; i < 0x20; i++) {
|
||||
sp28[i] = (arg1 / 32);
|
||||
}
|
||||
ret = func_8000B048(arg0, sp28, 0x4000U, 0x20U);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
for(i = 0; i < 0x20; i++) {
|
||||
sp28[i] = (arg1 % 32);
|
||||
}
|
||||
return func_8000B048(arg0, sp28, 0x2000U, 0x20U);
|
||||
}
|
||||
|
||||
s32 func_8000B1C4(s32 arg0, u8* arg1, s32 arg2, s32 arg3) {
|
||||
s32 ret = 1;
|
||||
u32 temp_s1 = (arg2 & ~0x1F);
|
||||
u32 temp_s4 = ((arg2 + arg3) + 0x1F) & ~0x1F;
|
||||
|
||||
s32 temp_s1_2;
|
||||
s32 temp_v0_4;
|
||||
u32 temp_v0_5;
|
||||
u32 var_v1_2;
|
||||
|
||||
if (temp_s1 < 0x4000U) {
|
||||
if (temp_s4 < 0x4001U) {
|
||||
var_v1_2 = temp_s4;
|
||||
} else {
|
||||
var_v1_2 = 0x4000;
|
||||
}
|
||||
temp_v0_4 = var_v1_2 - temp_s1;
|
||||
ret = func_8000AFC4(arg0, arg1, temp_s1, temp_v0_4);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
temp_s1 += temp_v0_4;
|
||||
arg1 = &arg1[temp_v0_4];
|
||||
}
|
||||
while (temp_s1 < temp_s4) {
|
||||
temp_v0_5 = (temp_s1 & ~0x3FFF) + 0x4000;
|
||||
if (temp_v0_5 >= temp_s4) {
|
||||
var_v1_2 = temp_s4;
|
||||
} else {
|
||||
var_v1_2 = temp_v0_5;
|
||||
}
|
||||
temp_s1_2 = var_v1_2 - temp_s1;
|
||||
ret = func_8000B0CC(arg0, temp_s1 >> 0xE);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = func_8000AFC4(arg0, arg1, ((temp_s1 & 0x3FFF) + 0x4000) & 0xFFFF, temp_s1_2);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
temp_s1 += temp_s1_2;
|
||||
arg1 = &arg1[temp_s1_2];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
u8 func_8000B318(u8 arg0) {
|
||||
u8 temp_v0 = D_800A82A7;
|
||||
|
||||
D_800A82A7 = arg0;
|
||||
return temp_v0;
|
||||
}
|
||||
|
||||
void func_8000B330(void) {
|
||||
u8 sp1F;
|
||||
static s32 D_800697D0 = 0; // .data
|
||||
|
||||
if (D_800A82A8 == 0) {
|
||||
if (D_800A82A7 & (1 << D_800697D0)) {
|
||||
if (osGbpakGetStatus(&D_800A8100[D_800697D0], &sp1F) == 0) {
|
||||
D_800A82AC[D_800697D0] = 0;
|
||||
} else {
|
||||
D_800A82AC[D_800697D0]++;
|
||||
if (D_800A82AC[D_800697D0] == 3) {
|
||||
D_800A82A8 = 1;
|
||||
func_8002B274(D_800697D0, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
D_800697D0 = (D_800697D0 + 1) & 3;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef _HAL_LIBC_
|
||||
#define _HAL_LIBC_
|
||||
|
||||
char* HAL_Strcpy(char* dest, char* src);
|
||||
char* HAL_Strcpy2(char *dest, char* src);
|
||||
size_t HAL_Strcmp(char* dest, char* src);
|
||||
char* HAL_Memset(char* dest, s32 c, s32 nsize);
|
||||
|
||||
#endif // _HAL_LIBC_
|
||||
+6
-1
@@ -49,7 +49,8 @@ segments:
|
||||
- [0x8EC0, c, crash_screen] # crash handler
|
||||
- [0x9D20, asm] #
|
||||
- [0xAF00, asm] # camera code
|
||||
- [0xB130, asm] # dp code for text
|
||||
- [0xB130, c, hal_libc]
|
||||
- [0xB230, c, gb_tower]
|
||||
- [0xC030, asm] # extra sprites loader
|
||||
- [0xC3D0, asm, exception_set] # exception functions
|
||||
- [0xC3F0, asm] # yay0 decoder
|
||||
@@ -323,6 +324,8 @@ segments:
|
||||
# .data is somewhere in here
|
||||
- [0x6A1B0, .data, crash_screen]
|
||||
- [0x6A3B0, bin, rom_data_6A3B0]
|
||||
- [0x6A3D0, .data, gb_tower]
|
||||
- [0x6A3E0, bin, rom_data_6A3E0]
|
||||
- [0x7A2A0, .data, libultra/os/initialize]
|
||||
- [0x7A2C0, .data, libultra/al/reverb]
|
||||
- [0x7A2E0, bin, rom_data_7A2E0]
|
||||
@@ -346,6 +349,8 @@ segments:
|
||||
- [0x7BB10, bin, rom_rodata_7BB10]
|
||||
- [0x7BBE0, .rodata, crash_screen]
|
||||
- [0x7BFA0, bin, rom_rodata_7BFA0]
|
||||
- [0x7BFC0, .rodata, gb_tower]
|
||||
- [0x7C000, bin, rom_rodata_7C000]
|
||||
- [0x7EE90, .rodata, libultra/gu/sinf]
|
||||
- [0x7EEE0, bin, rom_rodata_7EEE0]
|
||||
- [0x7EF30, .rodata, libultra/al/reverb]
|
||||
|
||||
+382
@@ -0,0 +1,382 @@
|
||||
#include <ultra64.h>
|
||||
#include "hal_libc.h"
|
||||
#include "controller.h"
|
||||
|
||||
extern s32 func_8000DAFC(void*, s32, u16, s32, s32);
|
||||
|
||||
// gb_tower.c
|
||||
// dont forget to pass -signed when compiling
|
||||
|
||||
extern OSPfs D_800A8100[];
|
||||
extern u8 D_800A82A0[];
|
||||
extern u8 D_800A82AC[];
|
||||
|
||||
extern u8 D_800A82A4;
|
||||
extern u8 D_800A82A5;
|
||||
extern u8 D_800A82A6;
|
||||
extern u8 D_800A82A7;
|
||||
extern s32 D_800A82A8;
|
||||
|
||||
// these first 4 funcs might be part of a hal_libc file or something instead of GB Tower.
|
||||
|
||||
s32 func_8000AEBC(s32 arg0, s32 arg1, u16 arg2, u16 arg3);
|
||||
s32 func_8000AF40(s32 arg0, void* arg1, u16 arg2, u16 arg3);
|
||||
|
||||
// TODO: These 0x20 sizes probably belong to a struct size or something. Use
|
||||
// that instead of assuming sizeof is the same
|
||||
s32 func_8000A630(s32 arg0, void* arg1) {
|
||||
u8 sp47;
|
||||
u8 sp24[0x20];
|
||||
s32 sp20 = 0;
|
||||
u8 padding[8];
|
||||
|
||||
if ((func_8000AF40(arg0, arg1, 0, 0x20) == 0)
|
||||
&& (func_8000AEBC(arg0, &sp24, 0, 0x20) == 0)
|
||||
&& (bcmp(&sp24, arg1, 0x20) == 0)
|
||||
&& (osGbpakGetStatus(&D_800A8100[arg0], &sp47) == 0))
|
||||
{
|
||||
sp20 = ((sp47 & 4) != 0) == 0;
|
||||
}
|
||||
return sp20;
|
||||
}
|
||||
|
||||
s32 func_8000A6D8(s32 arg0, u8* arg1) {
|
||||
s32 var_s0 = 0;
|
||||
u8 sp34[0x20];
|
||||
|
||||
if (arg1 == NULL) {
|
||||
arg1 = sp34;
|
||||
}
|
||||
HAL_Memset(arg1, 0x55, 0x20);
|
||||
if (func_8000A630(arg0, arg1) != 0) {
|
||||
HAL_Memset(arg1, 0xAA, 0x20);
|
||||
if (func_8000A630(arg0, arg1) != 0) {
|
||||
s32 i;
|
||||
for (i = 0; i < sizeof(sp34); i++) {
|
||||
arg1[i] = osGetCount();
|
||||
}
|
||||
var_s0 = func_8000A630(arg0, arg1);
|
||||
}
|
||||
}
|
||||
return var_s0;
|
||||
}
|
||||
|
||||
s32 func_8000A798(s32 arg0, u8* arg1, s32 arg2) {
|
||||
u8 status;
|
||||
OSGbpakId gbpakId;
|
||||
s32 sp28 = 0;
|
||||
|
||||
if (arg1 != NULL) {
|
||||
*arg1 = D_800A82A0[arg0];
|
||||
}
|
||||
|
||||
if (D_800A82A0[arg0] == 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (osGbpakReadId(&D_800A8100[arg0], &gbpakId, &status) != 0) {
|
||||
func_8002B274(arg0, 1);
|
||||
}
|
||||
if ((status & OS_GBPAK_RSTB_STATUS) && (osGbpakCheckConnector(&D_800A8100[arg0], &status) == 0)) {
|
||||
func_8000D970(&D_800A8100[arg0]);
|
||||
sp28 = func_8000A6D8(arg0, arg2);
|
||||
}
|
||||
D_800A82A0[arg0] = 1;
|
||||
return sp28;
|
||||
}
|
||||
|
||||
s32 func_8000A888(s32 arg0, u8 arg1) {
|
||||
u8 status;
|
||||
s32 temp_v1;
|
||||
|
||||
if (osGbpakGetStatus(&D_800A8100[arg0], &status) != 0) {
|
||||
func_8002B274(arg0, 1);
|
||||
}
|
||||
|
||||
temp_v1 = !((status & OS_GBPAK_RSTB_DETECTION) != 0);
|
||||
if (arg1 == 0) {
|
||||
osGbpakPower(&D_800A8100[arg0], 0);
|
||||
D_800A82A0[arg0] = 0;
|
||||
}
|
||||
return temp_v1;
|
||||
}
|
||||
|
||||
void func_8000A924(void) {
|
||||
s32 i;
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
if (D_800A82A4 & (1 << i)) {
|
||||
osGbpakPower(&D_800A8100[i], 0);
|
||||
D_800A82A0[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s32 func_8000A9D0(OSGbpakId* header) {
|
||||
// make sure its 0 terminated. dont want those dirty hackers abusing a Strcmp exploit
|
||||
header->game_title[15] = '\0';
|
||||
|
||||
// is the cartridge non-Japanese?
|
||||
if (header->country_code == 1) {
|
||||
// Which supported POKeMON version is this?
|
||||
if (HAL_Strcmp(header->game_title, "POKEMON RED") == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (HAL_Strcmp(header->game_title, "POKEMON GREEN") == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (HAL_Strcmp(header->game_title, "POKEMON BLUE") == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (HAL_Strcmp(header->game_title, "POKEMON YELLOW") == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// This is not a supported cartridge.
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 func_8000AA7C(void) {
|
||||
s32 i;
|
||||
s32 temp_v0;
|
||||
u8 status;
|
||||
OSGbpakId sp4C;
|
||||
|
||||
D_800A82A5 = 0;
|
||||
D_800A82A4 = 0;
|
||||
D_800A82A7 = 0;
|
||||
D_800A82A8 = 0;
|
||||
osPfsIsPlug(&gSIEventMesgQueue, &D_800A82A6);
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
if ((D_800A82A6 & (1 << i)) && ((i != 3) || (func_8000B4C4() == 0))) {
|
||||
if (osGbpakInit(&gSIEventMesgQueue, &D_800A8100[i], i) == 0) {
|
||||
D_800A82A4 |= (1 << i);
|
||||
temp_v0 = osGbpakReadId(&D_800A8100[i], &sp4C, &status);
|
||||
if (temp_v0 == 0) {
|
||||
if (!(status & 8)) {
|
||||
func_8002B274(i, 2);
|
||||
}
|
||||
if (func_8000A9D0(&sp4C) != 0) {
|
||||
if (temp_v0 == 4) {
|
||||
// what. the redundant temp_v0 functionless check is apparently needed to match.
|
||||
}
|
||||
if (osGbpakCheckConnector(&D_800A8100[i], &status) == 0) {
|
||||
func_8000D970(&D_800A8100[i]);
|
||||
D_800A82A0[i] = 1;
|
||||
D_800A82A5 |= (1 << i);
|
||||
} else {
|
||||
func_8002B274(i, 2);
|
||||
}
|
||||
} else {
|
||||
D_800A82A5 |= (1 << i);
|
||||
D_800A82A0[i] = 1;
|
||||
}
|
||||
} else {
|
||||
D_800A82A0[i] = 0;
|
||||
if (temp_v0 == 4) {
|
||||
func_8002B274(i, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (D_800A82A5 << 0x10) | D_800A82A4;
|
||||
}
|
||||
|
||||
s32 func_8000AC7C(s32 arg0) {
|
||||
u8 status;
|
||||
s32 ret = osGbpakGetStatus(&D_800A8100[arg0], &status);
|
||||
u8 filler;
|
||||
|
||||
// check the error code returned (if applicable) by the osGbpakGetStatus
|
||||
// call.
|
||||
if ((ret == PFS_ERR_NOPACK)
|
||||
|| (ret == PFS_ERR_DEVICE)
|
||||
|| (ret == PFS_ERR_CONTRFAIL)) {
|
||||
func_8002B274(arg0, 1);
|
||||
}
|
||||
return !((status & OS_GBPAK_GBCART_ON) != 0);
|
||||
}
|
||||
|
||||
s32 func_8000ACF4(s32 arg0) {
|
||||
u8 status;
|
||||
s32 ret = osGbpakGetStatus(&D_800A8100[arg0], &status);
|
||||
|
||||
if ((ret == PFS_ERR_NOPACK)
|
||||
|| (ret == PFS_ERR_DEVICE)
|
||||
|| (ret == PFS_ERR_CONTRFAIL)) {
|
||||
func_8002B274(arg0, 1);
|
||||
}
|
||||
return ((status & OS_GBPAK_GBCART_ON) != 0);
|
||||
}
|
||||
|
||||
s32 func_8000AD68(s32 arg0) {
|
||||
u8 filler[4];
|
||||
u8 status;
|
||||
OSGbpakId sp28;
|
||||
|
||||
D_800A82A0[arg0] = 0;
|
||||
if ((osGbpakInit(&gSIEventMesgQueue, &D_800A8100[arg0], arg0) == 0)
|
||||
&& (osGbpakReadId(&D_800A8100[arg0], &sp28, &status) == 0)
|
||||
&& (status & OS_GBPAK_RSTB_STATUS)
|
||||
&& (osGbpakCheckConnector(&D_800A8100[arg0], &status) == 0)) {
|
||||
|
||||
func_8000D970(&D_800A8100[arg0]);
|
||||
D_800A82A0[arg0] = 1;
|
||||
}
|
||||
|
||||
return D_800A82A0[arg0] == 1;
|
||||
}
|
||||
|
||||
s32 func_8000AE28(s32 arg0, void* arg1) {
|
||||
u8 status;
|
||||
u8 sp1C[0x20];
|
||||
s32 sp18;
|
||||
|
||||
sp18 = 0;
|
||||
if ((func_8000AEBC(arg0, &sp1C, 0, 0x20) == 0) && (bcmp(&sp1C, arg1, 0x20) == 0)
|
||||
&& (osGbpakGetStatus(&D_800A8100[arg0], &status) == 0)
|
||||
&& !(status & OS_GBPAK_RSTB_DETECTION)) {
|
||||
sp18 = 1;
|
||||
}
|
||||
return sp18;
|
||||
}
|
||||
|
||||
s32 func_8000AEBC(s32 arg0, s32 arg1, u16 arg2, u16 arg3) {
|
||||
s32 var_v1;
|
||||
|
||||
var_v1 = 1;
|
||||
if (D_800A82A5 & (1 << arg0)) {
|
||||
var_v1 = func_8000DAFC(&D_800A8100[arg0], 0, arg2, arg1, arg3);
|
||||
}
|
||||
return var_v1;
|
||||
}
|
||||
|
||||
s32 func_8000AF40(s32 arg0, void* arg1, u16 arg2, u16 arg3) {
|
||||
s32 var_v1;
|
||||
|
||||
var_v1 = 1;
|
||||
if (D_800A82A5 & (1 << arg0)) {
|
||||
var_v1 = func_8000DAFC(&D_800A8100[arg0], 1, arg2, arg1, arg3);
|
||||
}
|
||||
return var_v1;
|
||||
}
|
||||
|
||||
s32 func_8000AFC4(s32 arg0, u8 *arg1, u16 arg2, u16 arg3) {
|
||||
s32 var_v1;
|
||||
|
||||
var_v1 = 1;
|
||||
if (D_800A82A5 & (1 << arg0)) {
|
||||
var_v1 = osGbpakReadWrite(&D_800A8100[arg0], 0, arg2, arg1, arg3);
|
||||
}
|
||||
return var_v1;
|
||||
}
|
||||
|
||||
s32 func_8000B048(s32 arg0, u8 *arg1, u16 arg2, u16 arg3) {
|
||||
s32 var_v1;
|
||||
|
||||
var_v1 = 1;
|
||||
if (D_800A82A5 & (1 << arg0)) {
|
||||
var_v1 = osGbpakReadWrite(&D_800A8100[arg0], 1, arg2, arg1, arg3);
|
||||
}
|
||||
return var_v1;
|
||||
}
|
||||
|
||||
int func_8000B0CC(s32 arg0, s32 arg1) {
|
||||
u8 sp28[0x20];
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
for(i = 0; i < 0x20; i++) {
|
||||
sp28[i] = 0;
|
||||
}
|
||||
ret = func_8000B048(arg0, sp28, 0x5000U, 0x20U);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
for(i = 0; i < 0x20; i++) {
|
||||
sp28[i] = (arg1 / 32);
|
||||
}
|
||||
ret = func_8000B048(arg0, sp28, 0x4000U, 0x20U);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
for(i = 0; i < 0x20; i++) {
|
||||
sp28[i] = (arg1 % 32);
|
||||
}
|
||||
return func_8000B048(arg0, sp28, 0x2000U, 0x20U);
|
||||
}
|
||||
|
||||
s32 func_8000B1C4(s32 arg0, u8* arg1, s32 arg2, s32 arg3) {
|
||||
s32 ret = 1;
|
||||
u32 temp_s1 = (arg2 & ~0x1F);
|
||||
u32 temp_s4 = ((arg2 + arg3) + 0x1F) & ~0x1F;
|
||||
|
||||
s32 temp_s1_2;
|
||||
s32 temp_v0_4;
|
||||
u32 temp_v0_5;
|
||||
u32 var_v1_2;
|
||||
|
||||
if (temp_s1 < 0x4000U) {
|
||||
if (temp_s4 < 0x4001U) {
|
||||
var_v1_2 = temp_s4;
|
||||
} else {
|
||||
var_v1_2 = 0x4000;
|
||||
}
|
||||
temp_v0_4 = var_v1_2 - temp_s1;
|
||||
ret = func_8000AFC4(arg0, arg1, temp_s1, temp_v0_4);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
temp_s1 += temp_v0_4;
|
||||
arg1 = &arg1[temp_v0_4];
|
||||
}
|
||||
while (temp_s1 < temp_s4) {
|
||||
temp_v0_5 = (temp_s1 & ~0x3FFF) + 0x4000;
|
||||
if (temp_v0_5 >= temp_s4) {
|
||||
var_v1_2 = temp_s4;
|
||||
} else {
|
||||
var_v1_2 = temp_v0_5;
|
||||
}
|
||||
temp_s1_2 = var_v1_2 - temp_s1;
|
||||
ret = func_8000B0CC(arg0, temp_s1 >> 0xE);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = func_8000AFC4(arg0, arg1, ((temp_s1 & 0x3FFF) + 0x4000) & 0xFFFF, temp_s1_2);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
temp_s1 += temp_s1_2;
|
||||
arg1 = &arg1[temp_s1_2];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
u8 func_8000B318(u8 arg0) {
|
||||
u8 temp_v0 = D_800A82A7;
|
||||
|
||||
D_800A82A7 = arg0;
|
||||
return temp_v0;
|
||||
}
|
||||
|
||||
void func_8000B330(void) {
|
||||
u8 sp1F;
|
||||
static s32 D_800697D0 = 0; // .data
|
||||
|
||||
if (D_800A82A8 == 0) {
|
||||
if (D_800A82A7 & (1 << D_800697D0)) {
|
||||
if (osGbpakGetStatus(&D_800A8100[D_800697D0], &sp1F) == 0) {
|
||||
D_800A82AC[D_800697D0] = 0;
|
||||
} else {
|
||||
D_800A82AC[D_800697D0]++;
|
||||
if (D_800A82AC[D_800697D0] == 3) {
|
||||
D_800A82A8 = 1;
|
||||
func_8002B274(D_800697D0, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
D_800697D0 = (D_800697D0 + 1) & 3;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#include <ultra64.h>
|
||||
#include "hal_libc.h"
|
||||
|
||||
/*
|
||||
* Strcpy implementation; copy the strings terminated by 0. Return the original dest
|
||||
* pointer.
|
||||
*/
|
||||
char* HAL_Strcpy(char* dest, char* src) {
|
||||
char *newDest = dest;
|
||||
while ((*(newDest++) = *(src++)) != '\0') {
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
/*
|
||||
* Alternate strcpy implementation; return the post-increment altered dest pointer.
|
||||
*/
|
||||
char* HAL_Strcpy2(char *dest, char* src) {
|
||||
size_t c = strlen(dest); // this is completely pointless. the strlen func called
|
||||
// doesnt alter the pointer.
|
||||
while ((*(dest++) = *(src++)) != '\0') {
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
/*
|
||||
* Strcmp implementation. Compare two strings, terminated by 0. Return a 0 if success, return
|
||||
* a positive value if the 2nd string is "greater" than the 1st, and vice versa.
|
||||
*/
|
||||
size_t HAL_Strcmp(char* dest, char* src) {
|
||||
int c1 = *dest;
|
||||
int c2 = *src;
|
||||
// while the string values are the same...
|
||||
while (c1 == c2) {
|
||||
// ...once we hit a 0 terminator, we've reached the end of the strings.
|
||||
// Return a success.
|
||||
if (c1 == '\0') {
|
||||
return 0;
|
||||
}
|
||||
// Increment the strings and update the content values for comparison.
|
||||
c1 = *++dest;
|
||||
c2 = *++src;
|
||||
}
|
||||
// depending on where the mismatch occured, this subtraction operation
|
||||
// will result in the correctly expected sign for whichever string is
|
||||
// "greater".
|
||||
return c1-c2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Memset implementation. Given a value, set each byte in the given pointer to
|
||||
* this value for every byte across a given specified size. Return the original
|
||||
* pointer used.
|
||||
*/
|
||||
char* HAL_Memset(char* dest, s32 c, s32 nsize) {
|
||||
char* newDest = dest;
|
||||
|
||||
// While the size is not 0, keep decrementing. Oddly, HAL seems to have
|
||||
// xor'd the result instead of checking the logical result.
|
||||
while((nsize-- == 0) ^ 1) {
|
||||
*newDest++ = c;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
@@ -442,4 +442,8 @@ Cont_AttemptWriteEeprom = 0x80005C64;
|
||||
Cont_BlockEepromQueue = 0x80005D1C;
|
||||
Cont_NoBlockEepromQueue = 0x80005D48;
|
||||
Cont_InitEepromQueue = 0x80005D74;
|
||||
Cont_SetupControllers = 0x80005DB8;
|
||||
Cont_SetupControllers = 0x80005DB8;
|
||||
HAL_Strcpy = 0x8000A530;
|
||||
HAL_Strcpy2 = 0x8000A560;
|
||||
HAL_Strcmp = 0x8000A5B8;
|
||||
HAL_Memset = 0x8000A5FC;
|
||||
Reference in New Issue
Block a user