Merge pull request #39 from ProjectRevoTPP/decompile_hal_libc_tower

decompile hal_libc and gb_tower
This commit is contained in:
Revo
2022-10-28 23:00:43 -04:00
committed by GitHub
7 changed files with 912 additions and 2 deletions

View File

@@ -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
gb_tower.c Normal file
View File

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

9
include/hal_libc.h Normal file
View File

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

View File

@@ -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
src/gb_tower.c Normal file
View File

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

64
src/hal_libc.c Normal file
View File

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

View File

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