Added a ton of information

Added assembler and compiler
Build: OK (run `make`)
This commit is contained in:
Ogre 2023-08-30 01:41:21 +02:00
parent 1928aa31f3
commit b7c264fe1e
26 changed files with 4816 additions and 0 deletions

1021
splat.yaml Normal file

File diff suppressed because it is too large Load Diff

13
src/19DD0.c Normal file
View File

@ -0,0 +1,13 @@
#include "common.h"
#include <PR/os.h>
extern s32 FP_800A9E84;
void __set_fp_800A9E84(s32 arg0) {
s32 mask;
mask = osSetIntMask(OS_IM_NONE);
FP_800A9E84 = arg0;
osSetIntMask(mask);
}

28
src/1A050.c Normal file
View File

@ -0,0 +1,28 @@
#include "common.h"
#include <PR/os.h>
OSPiHandle* CART_HANDLE;
OSMesgQueue MQ_800BE030;
OSMesg OSMESG_800BE048[0x32];
INCLUDE_ASM(const s32, "1A050", func_80089C50);
INCLUDE_ASM(const s32, "1A050", __init_controllers);
INCLUDE_ASM(const s32, "1A050", func_80089CF8);
INCLUDE_ASM(const s32, "1A050", func_80089D5C);
INCLUDE_ASM(const s32, "1A050", __start_controller_thread);
INCLUDE_ASM(const s32, "1A050", __controller_thread_80089D9C);
void initialise(void) {
osCreatePiManager(OS_PRIORITY_PIMGR, &MQ_800BE030, OSMESG_800BE048, sizeof(OSMESG_800BE048) / sizeof(OSMesg));
CART_HANDLE = osCartRomInit();
}
INCLUDE_ASM(const s32, "1A050", romCopy);
INCLUDE_ASM(const s32, "1A050", func_8008A040);

47
src/1A660.c Normal file
View File

@ -0,0 +1,47 @@
#include "common.h"
#include <PR/os.h>
extern void func_8008A354();
extern void func_8008A37C();
extern u32 D_800C4B30;
extern OSMesgQueue MQ_CONTROLLER;
INCLUDE_ASM(const s32, "1A660", func_8008A260);
INCLUDE_ASM(const s32, "1A660", func_8008A334);
INCLUDE_ASM(const s32, "1A660", __start_copy_global_controller_data);
INCLUDE_ASM(const s32, "1A660", __end_copy_global_controller_data);
// INCLUDE_ASM(const s32, "1A660", __read_controller);
s32 __read_controller(OSContPad* data, u32 arg1) {
s32 res;
res = osContStartReadData(&MQ_CONTROLLER);
if(res != 0)
return res;
osRecvMesg(&MQ_CONTROLLER, NULL, OS_MESG_BLOCK);
if (!(arg1 & D_800C4B30)) {
func_8008A354();
osContGetReadData(data);
func_8008A37C();
return 0;
}
return 0;
}
INCLUDE_ASM(const s32, "1A660", __real_read_controller);
INCLUDE_ASM(const s32, "1A660", __calls_read_controller_0);
INCLUDE_ASM(const s32, "1A660", __calls_read_controller_1);
INCLUDE_ASM(const s32, "1A660", __calls_read_controller_2);

18
src/boot.c Normal file
View File

@ -0,0 +1,18 @@
#include "common.h"
#include <PR/os.h>
void idle(void* arg);
// static OSThread IDLE_THREAD;
// static char SP_THREAD_IDLE[OS_PIM_STACKSIZE];
// void boot(void) {
// osInitialize();
// osCreateThread(&IDLE_THREAD, 1, idle, NULL, &SP_THREAD_IDLE, 0xA);
// osStartThread(&IDLE_THREAD);
// }
INCLUDE_ASM(const s32, "boot", boot);
INCLUDE_ASM(const s32, "boot", idle);

32
src/character.c Normal file
View File

@ -0,0 +1,32 @@
#ifndef __CHARACTER_H__
#define __CHARACTER_H__
#include <PR/os.h>
typedef struct {
// Possible data still undiscovered:
// - Element
// - Gender
// - Alignment
// - Held items (four u16's)
/* 0x00 */ s8 name[0x10];
/* 0x10 */ u16 portrait;
/* 0x12 */ u8 class;
/* 0x13 */ u8 level;
/* 0x14 */ u8 field_0x14[0x2];
/* 0x16 */ u16 max_hp;
/* 0x18 */ u16 cur_hp;
/* 0x1A */ u8 field_0x1a[0x2];
/* 0x1C */ u16 strength;
/* 0x1E */ u16 vitality;
/* 0x20 */ u16 intelligence;
/* 0x22 */ u16 mem;
/* 0x24 */ u16 agility;
/* 0x26 */ u16 dexterity;
/* 0x28 */ u8 field_0x28[0x10];
} CharacterSlot;
// const int __size = sizeof(CharacterSlot);
#endif __CHARACTER_H__

6
src/common.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef __COMMON_H__
#define __COMMON_H__
#include "include_asm.h"
#endif

338
src/ctx.h Normal file
View File

@ -0,0 +1,338 @@
typedef unsigned char u8; /* unsigned 8-bit */
typedef unsigned short u16; /* unsigned 16-bit */
typedef unsigned long u32; /* unsigned 32-bit */
typedef unsigned long long u64; /* unsigned 64-bit */
typedef signed char s8; /* signed 8-bit */
typedef short s16; /* signed 16-bit */
typedef long s32; /* signed 32-bit */
typedef long long s64; /* signed 64-bit */
typedef volatile unsigned char vu8; /* unsigned 8-bit */
typedef volatile unsigned short vu16; /* unsigned 16-bit */
typedef volatile unsigned long vu32; /* unsigned 32-bit */
typedef volatile unsigned long long vu64; /* unsigned 64-bit */
typedef volatile signed char vs8; /* signed 8-bit */
typedef volatile short vs16; /* signed 16-bit */
typedef volatile long vs32; /* signed 32-bit */
typedef volatile long long vs64; /* signed 64-bit */
typedef float f32; /* single prec floating point */
typedef double f64; /* double prec floating point */
typedef unsigned long size_t;
#define NULL 0
#define true 1
#define false 0
/* Flags to turn blocking on/off when sending/receiving message */
#define OS_MESG_NOBLOCK 0
#define OS_MESG_BLOCK 1
/* Recommended thread priorities for the system threads */
#define OS_PRIORITY_MAX 255
#define OS_PRIORITY_VIMGR 254
#define OS_PRIORITY_RMON 250
#define OS_PRIORITY_RMONSPIN 200
#define OS_PRIORITY_PIMGR 150
#define OS_PRIORITY_SIMGR 140
#define OS_PRIORITY_APPMAX 127
#define OS_PRIORITY_IDLE 0 /* Must be 0 */
typedef s32 OSPri;
typedef s32 OSId;
typedef union { struct { f32 f_odd; f32 f_even; } f; f64 d; } __OSfp;
typedef struct {
u64 at, v0, v1, a0, a1, a2, a3;
u64 t0, t1, t2, t3, t4, t5, t6, t7;
u64 s0, s1, s2, s3, s4, s5, s6, s7;
u64 t8, t9, gp, sp, s8, ra;
u64 lo, hi;
u32 sr, pc, cause, badvaddr, rcp;
u32 fpcsr;
__OSfp fp0, fp2, fp4, fp6, fp8, fp10, fp12, fp14;
__OSfp fp16, fp18, fp20, fp22, fp24, fp26, fp28, fp30;
} __OSThreadContext;
typedef struct OSThread_s {
struct OSThread_s *next; /* run/mesg queue link */
OSPri priority; /* run/mesg queue priority */
struct OSThread_s **queue; /* queue thread is on */
struct OSThread_s *tlnext; /* all threads queue link */
u16 state; /* OS_STATE_* */
u16 flags; /* flags for rmon */
OSId id; /* id for debugging */
int fp; /* thread has used fp unit */
__OSThreadContext context; /* register/interrupt mask */
} OSThread;
/*
* Structure for message
*/
typedef void* OSMesg;
typedef struct {
u16 button;
s8 stick_x; /* -80 <= stick_x <= 80 */
s8 stick_y; /* -80 <= stick_y <= 80 */
u8 errno;
} OSContPad;
/*
* Structure for message queue
*/
typedef struct OSMesgQueue_s {
OSThread *mtqueue; /* Queue to store threads blocked
on empty mailboxes (receive) */
OSThread *fullqueue; /* Queue to store threads blocked
on full mailboxes (send) */
s32 validCount; /* Contains number of valid message */
s32 first; /* Points to first valid message */
s32 msgCount; /* Contains total # of messages */
OSMesg *msg; /* Points to message buffer array */
} OSMesgQueue;
/*
* OSTranxInfo is set up for Leo Disk DMA. This info will be maintained
* by exception handler. This is how the PIMGR and the ISR communicate.
*/
typedef struct {
u32 errStatus; /* error status */
void *dramAddr; /* RDRAM buffer address (DMA) */
void *C2Addr; /* C2 buffer address */
u32 sectorSize; /* size of transfering sector */
u32 C1ErrNum; /* total # of C1 errors */
u32 C1ErrSector[4]; /* error sectors */
} __OSBlockInfo;
typedef struct {
u32 cmdType; /* for disk only */
u16 transferMode; /* Block, Track, or sector? */
u16 blockNum; /* which block is transfering */
s32 sectorNum; /* which sector is transfering */
u32 devAddr; /* Device buffer address */
u32 bmCtlShadow; /* asic bm_ctl(510) register shadow ram */
u32 seqCtlShadow; /* asic seq_ctl(518) register shadow ram */
__OSBlockInfo block[2]; /* bolck transfer info */
} __OSTranxInfo;
typedef struct OSPiHandle_s {
struct OSPiHandle_s *next; /* point to next handle on the table */
u8 type; /* DEVICE_TYPE_BULK for disk */
u8 latency; /* domain latency */
u8 pageSize; /* domain page size */
u8 relDuration; /* domain release duration */
u8 pulse; /* domain pulse width */
u8 domain; /* which domain */
u32 baseAddress; /* Domain address */
u32 speed; /* for roms only */
/* The following are "private" elements" */
__OSTranxInfo transferInfo; /* for disk only */
} OSPiHandle;
/*
* Structure for I/O message block
*/
typedef struct {
u16 type; /* Message type */
u8 pri; /* Message priority (High or Normal) */
u8 status; /* Return status */
OSMesgQueue *retQueue; /* Return message queue to notify I/O
* completion */
} OSIoMesgHdr;
typedef struct {
OSIoMesgHdr hdr; /* Message header */
void * dramAddr; /* RDRAM buffer address (DMA) */
u32 devAddr; /* Device buffer address (DMA) */
u32 size; /* DMA transfer size in bytes */
OSPiHandle *piHandle; /* PI device handle */
} OSIoMesg;
/*
* Structure for device manager block
*/
typedef struct {
s32 active; /* Status flag */
OSThread *thread; /* Calling thread */
OSMesgQueue *cmdQueue; /* Command queue */
OSMesgQueue *evtQueue; /* Event queue */
OSMesgQueue *acsQueue; /* Access queue */
/* Raw DMA routine */
s32 (*dma)(s32, u32, void *, u32);
s32 (*edma)(OSPiHandle *, s32, u32, void *, u32);
} OSDevMgr;
#define OS_SC_STACKSIZE 0x2000
#define OS_SC_RETRACE_MSG 1
#define OS_SC_DONE_MSG 2
#define OS_SC_RDP_DONE_MSG 3
#define OS_SC_PRE_NMI_MSG 4
#define OS_SC_LAST_MSG 4 /* this should have highest number */
#define OS_SC_MAX_MESGS 8
typedef struct {
short type;
char misc[30];
} OSScMsg;
typedef struct {
u32 type;
u32 flags;
u64 *ucode_boot;
u32 ucode_boot_size;
u64 *ucode;
u32 ucode_size;
u64 *ucode_data;
u32 ucode_data_size;
u64 *dram_stack;
u32 dram_stack_size;
u64 *output_buff;
u64 *output_buff_size;
u64 *data_ptr;
u32 data_size;
u64 *yield_data_ptr;
u32 yield_data_size;
} OSTask_t;
typedef union {
OSTask_t t;
long long int force_structure_alignment;
} OSTask;
typedef struct OSScTask_s {
struct OSScTask_s *next; /* note: this must be first */
u32 state;
u32 flags;
void *framebuffer; /* used by graphics tasks */
OSTask list;
OSMesgQueue *msgQ;
OSMesg msg;
} OSScTask; /* non FINALROM code */
/*
* OSScTask flags:
*/
#define OS_SC_NEEDS_RDP 0x0001 /* uses the RDP */
#define OS_SC_NEEDS_RSP 0x0002 /* uses the RSP */
#define OS_SC_DRAM_DLIST 0x0004 /* SP & DP communicate through DRAM */
#define OS_SC_PARALLEL_TASK 0x0010 /* must be first gfx task on list */
#define OS_SC_LAST_TASK 0x0020 /* last task in queue for frame */
#define OS_SC_SWAPBUFFER 0x0040 /* swapbuffers when gfx task done */
#define OS_SC_RCP_MASK 0x0003 /* mask for needs bits */
#define OS_SC_TYPE_MASK 0x0007 /* complete type mask */
/*
* OSScClient:
*
* Data structure used by threads that wish to communicate to the
* scheduling thread
*
*/
typedef struct SCClient_s {
struct SCClient_s *next; /* next client in the list */
OSMesgQueue *msgQ; /* where to send the frame msg */
} OSScClient;
typedef struct {
OSScMsg retraceMsg;
OSScMsg prenmiMsg;
OSMesgQueue interruptQ;
OSMesg intBuf[8];
OSMesgQueue cmdQ;
OSMesg cmdMsgBuf[8];
OSThread thread;
OSScClient *clientList;
OSScTask *audioListHead;
OSScTask *gfxListHead;
OSScTask *audioListTail;
OSScTask *gfxListTail;
OSScTask *curRSPTask;
OSScTask *curRDPTask;
u32 frameCount;
s32 doAudio;
} OSSched;
/* Buttons */
#define CONT_A 0x8000
#define CONT_B 0x4000
#define CONT_G 0x2000
#define CONT_START 0x1000
#define CONT_UP 0x0800
#define CONT_DOWN 0x0400
#define CONT_LEFT 0x0200
#define CONT_RIGHT 0x0100
#define CONT_L 0x0020
#define CONT_R 0x0010
#define CONT_E 0x0008
#define CONT_D 0x0004
#define CONT_C 0x0002
#define CONT_F 0x0001
/* Nintendo's official button names */
#define A_BUTTON CONT_A
#define B_BUTTON CONT_B
#define L_TRIG CONT_L
#define R_TRIG CONT_R
#define Z_TRIG CONT_G
#define START_BUTTON CONT_START
#define U_JPAD CONT_UP
#define L_JPAD CONT_LEFT
#define R_JPAD CONT_RIGHT
#define D_JPAD CONT_DOWN
#define U_CBUTTONS CONT_E
#define L_CBUTTONS CONT_C
#define R_CBUTTONS CONT_F
#define D_CBUTTONS CONT_D
extern void osContGetReadData(OSContPad* data);
extern s32 osContStartReadData(OSMesgQueue *mq);
extern s32 osRecvMesg(OSMesgQueue *mq, OSMesg *msg, s32 flags);
extern void osCreateThread(OSThread *t, OSId id, void (*entry)(void *), void *arg, void *sp, OSPri p);
extern void osSetThreadPri(OSThread *t, OSPri pri);
extern void osStartThread(OSThread *t);
extern void osCreateScheduler(OSSched *s, void *stack, OSPri priority, u8 mode, u8 retraceCount);
extern void osCreateMesgQueue(OSMesgQueue *mq, OSMesg *msg, s32 count);
extern void osSendMesg(OSMesgQueue *mq, OSMesg msg, s32 flag);
extern void osJamMesg(OSMesgQueue *mq, OSMesg msg, s32 flag);
extern s32 osRecvMesg(OSMesgQueue *mq, OSMesg *msg, s32 flag);
extern void osInvalDCache(void *vaddr, s32 nbytes);
extern OSPiHandle* CART_HANDLE;
extern s32 osEPiStartDma(OSPiHandle *pihandle, OSIoMesg *mb, s32 direction);
extern s32 osEPiWriteIo(OSPiHandle *pihandle, u32 devAddr, u32 data);
extern s32 osEPiReadIo(OSPiHandle *pihandle, u32 devAddr, u32 *data);
extern void osInitialize(void);
extern void MusFxBankSetPtrBank(void *ifxbank, void *ipbank);
extern void MusSetMasterVolume(unsigned long flags, int volume);
extern void MusFxBankInitialize(void *fxbank);
extern void osViSetSpecialFeatures(u32 func);
extern void boot(void* arg);
extern void idle(void* arg);
extern void main_(void* arg);
extern void romCopy(u8* src, u8* dst, u32 len);
extern void __calls_romCopy_8009DA50(u8* src, u8* dst, u32 len);

259
src/mus.c Normal file
View File

@ -0,0 +1,259 @@
#include "common.h"
#include <PR/os.h>
extern void* musCurrentPtrBank;
void func_8008350C();
INCLUDE_ASM(const s32, "mus", func_800810F0);
INCLUDE_ASM(const s32, "mus", func_8008123C);
INCLUDE_ASM(const s32, "mus", MusSetMasterVolume);
INCLUDE_ASM(const s32, "mus", MusStartSong);
INCLUDE_ASM(const s32, "mus", func_80081520);
INCLUDE_ASM(const s32, "mus", func_80081770);
INCLUDE_ASM(const s32, "mus", func_800817F0);
INCLUDE_ASM(const s32, "mus", func_80081908);
INCLUDE_ASM(const s32, "mus", __dma_load_loop_check);
INCLUDE_ASM(const s32, "mus", func_80081A54);
INCLUDE_ASM(const s32, "mus", func_80081B08);
INCLUDE_ASM(const s32, "mus", func_80081B60);
INCLUDE_ASM(const s32, "mus", func_80081BC0);
INCLUDE_ASM(const s32, "mus", func_80081C30);
INCLUDE_ASM(const s32, "mus", func_80081CA0);
INCLUDE_ASM(const s32, "mus", func_80081D2C);
void __something_music(void* arg0) {
func_8008350C();
if (musCurrentPtrBank == 0) {
musCurrentPtrBank = arg0;
}
}
// INCLUDE_ASM(const s32, "mus", func_80081DF0);
extern void* D_800B1828;
void* func_80081DF0(void* arg0) {
if ((arg0 != NULL) && ((*(s32*)(arg0 + 0x10)) < 0)) {
D_800B1828 = arg0;
}
return D_800B1828;
}
INCLUDE_ASM(const s32, "mus", MusPtrBankSetCurrent);
// void MusPtrBankSetCurrent(void* arg0) {
// if ((arg0 != NULL) && (arg0->unk10 < 0)) {
// D_800B182C = arg0;
// }
// }
INCLUDE_ASM(const s32, "mus", func_80081E3C);
INCLUDE_ASM(const s32, "mus", func_80081E48);
INCLUDE_ASM(const s32, "mus", MusHandlePause);
INCLUDE_ASM(const s32, "mus", MusHandleUnpause);
INCLUDE_ASM(const s32, "mus", MusSetFxType);
INCLUDE_ASM(const s32, "mus", func_80081F20);
INCLUDE_ASM(const s32, "mus", MusFxBankInitialize);
INCLUDE_ASM(const s32, "mus", MusFxBankNumberOfEffects);
INCLUDE_ASM(const s32, "mus", func_80082008);
INCLUDE_ASM(const s32, "mus", func_80082014);
INCLUDE_ASM(const s32, "mus", func_80082020);
INCLUDE_ASM(const s32, "mus", MusFxBankSetPtrBank);
INCLUDE_ASM(const s32, "mus", MusFxBankGetPtrBank);
INCLUDE_ASM(const s32, "mus", func_8008203C);
INCLUDE_ASM(const s32, "mus", func_80082048);
INCLUDE_ASM(const s32, "mus", func_800820AC);
INCLUDE_ASM(const s32, "mus", func_80082124);
INCLUDE_ASM(const s32, "mus", func_80082130);
INCLUDE_ASM(const s32, "mus", func_80082194);
INCLUDE_ASM(const s32, "mus", func_80082214);
INCLUDE_ASM(const s32, "mus", func_800822AC);
INCLUDE_ASM(const s32, "mus", func_8008259C);
INCLUDE_ASM(const s32, "mus", func_80082AE8);
INCLUDE_ASM(const s32, "mus", func_80082B64);
INCLUDE_ASM(const s32, "mus", func_80082CB8);
INCLUDE_ASM(const s32, "mus", func_80082DC4);
INCLUDE_ASM(const s32, "mus", func_80082E34);
INCLUDE_ASM(const s32, "mus", __MusIntInitSweep);
INCLUDE_ASM(const s32, "mus", func_8008302C);
INCLUDE_ASM(const s32, "mus", func_800830E4);
INCLUDE_ASM(const s32, "mus", func_8008313C);
INCLUDE_ASM(const s32, "mus", func_800831A0);
INCLUDE_ASM(const s32, "mus", func_80083264);
INCLUDE_ASM(const s32, "mus", func_80083378);
INCLUDE_ASM(const s32, "mus", func_8008350C);
INCLUDE_ASM(const s32, "mus", func_800836A4);
INCLUDE_ASM(const s32, "mus", func_80083738);
INCLUDE_ASM(const s32, "mus", func_80083874);
INCLUDE_ASM(const s32, "mus", func_80083A3C);
INCLUDE_ASM(const s32, "mus", func_80083A74);
INCLUDE_ASM(const s32, "mus", func_80083B24);
INCLUDE_ASM(const s32, "mus", func_80083CCC);
INCLUDE_ASM(const s32, "mus", func_80083F38);
INCLUDE_ASM(const s32, "mus", func_80083F8C);
INCLUDE_ASM(const s32, "mus", func_80083FAC);
INCLUDE_ASM(const s32, "mus", func_80083FDC);
INCLUDE_ASM(const s32, "mus", func_80083FFC);
INCLUDE_ASM(const s32, "mus", func_80084008);
INCLUDE_ASM(const s32, "mus", func_80084130);
INCLUDE_ASM(const s32, "mus", func_80084214);
INCLUDE_ASM(const s32, "mus", func_80084228);
INCLUDE_ASM(const s32, "mus", func_8008424C);
INCLUDE_ASM(const s32, "mus", func_800842BC);
INCLUDE_ASM(const s32, "mus", func_80084330);
INCLUDE_ASM(const s32, "mus", func_80084340);
INCLUDE_ASM(const s32, "mus", func_80084370);
INCLUDE_ASM(const s32, "mus", func_80084380);
INCLUDE_ASM(const s32, "mus", func_80084390);
INCLUDE_ASM(const s32, "mus", func_800843A0);
INCLUDE_ASM(const s32, "mus", func_800843F8);
INCLUDE_ASM(const s32, "mus", func_80084408);
INCLUDE_ASM(const s32, "mus", func_80084414);
INCLUDE_ASM(const s32, "mus", func_80084424);
INCLUDE_ASM(const s32, "mus", func_80084430);
INCLUDE_ASM(const s32, "mus", func_8008449C);
INCLUDE_ASM(const s32, "mus", func_80084538);
INCLUDE_ASM(const s32, "mus", func_80084560);
INCLUDE_ASM(const s32, "mus", func_8008456C);
INCLUDE_ASM(const s32, "mus", func_8008457C);
INCLUDE_ASM(const s32, "mus", func_80084588);
INCLUDE_ASM(const s32, "mus", func_8008459C);
INCLUDE_ASM(const s32, "mus", func_800845B0);
INCLUDE_ASM(const s32, "mus", func_800845B8);
INCLUDE_ASM(const s32, "mus", func_80084600);
INCLUDE_ASM(const s32, "mus", func_8008460C);
INCLUDE_ASM(const s32, "mus", func_80084614);
INCLUDE_ASM(const s32, "mus", func_80084684);
INCLUDE_ASM(const s32, "mus", func_80084694);
INCLUDE_ASM(const s32, "mus", func_800846E4);
INCLUDE_ASM(const s32, "mus", func_80084734);
INCLUDE_ASM(const s32, "mus", func_80084784);
INCLUDE_ASM(const s32, "mus", func_80084794);
INCLUDE_ASM(const s32, "mus", func_80084864);
INCLUDE_ASM(const s32, "mus", func_800848A0);
INCLUDE_ASM(const s32, "mus", func_800848B0);
INCLUDE_ASM(const s32, "mus", func_800848F4);
INCLUDE_ASM(const s32, "mus", func_80084964);
INCLUDE_ASM(const s32, "mus", func_80084970);
INCLUDE_ASM(const s32, "mus", func_800849D8);
INCLUDE_ASM(const s32, "mus", func_80084C48);
INCLUDE_ASM(const s32, "mus", func_80084C98);
INCLUDE_ASM(const s32, "mus", func_80084DE0);
INCLUDE_ASM(const s32, "mus", func_800850C0);
INCLUDE_ASM(const s32, "mus", func_800850D8);
INCLUDE_ASM(const s32, "mus", func_8008511C);
INCLUDE_ASM(const s32, "mus", func_80085160);

View File

@ -0,0 +1,75 @@
#include "common.h"
#include <PR/os.h>
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800E9C20);
// extern u8 D_2B8BA0;
// extern u8 D_2BF250;
// extern u8 D_423FF0;
// extern u8 D_429CD0;
// extern u8 D_4E3140;
// extern u8 D_4F0FB0;
// extern u8 D_80104710;
// extern u8 D_8010A760;
// extern u8 D_80164770;
// extern void romCopy(u8* src, u8* dst, u32 len);
// extern void __something_music(u8*, u8*);
// extern void MusFxBankInitialize(u8*);
// extern void MusFxBankSetPtrBank(u8*, u8*);
// void func_800E9C20(void) {
// romCopy(&D_2B8BA0, &D_80164770, &D_2BF250 - &D_2B8BA0);
// romCopy(&D_423FF0, &D_80104710, &D_429CD0 - &D_423FF0);
// romCopy(&D_4E3140, &D_8010A760, &D_4F0FB0 - &D_4E3140);
// __something_music(&D_80164770, &D_2BF250);
// __something_music(&D_80104710, &D_429CD0);
// MusFxBankInitialize(&D_8010A760);
// MusFxBankSetPtrBank(&D_8010A760, &D_80104710);
// }
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800E9CEC);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800E9E34);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA0E4);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA1C8);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA3BC);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA3E4);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA488);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA568);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA604);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA6B0);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA6C8);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA714);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA76C);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA7AC);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA7E4);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA838);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA850);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA86C);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA884);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA89C);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA8B4);
INCLUDE_ASM(const s32, "overlays/overlay0/3F1B0", func_800EA8CC);

337
symbol_addrs.txt Normal file
View File

@ -0,0 +1,337 @@
maybe_boot_01 = 0x800851C0;
__CONTROLLER_0_BUTTON = 0x800E8700;
__menu_handle_input = 0x8019B8AC; // type:func
__MENU_TIMER = 0x801BA540; // type:u32
__inc_menu_timer = 0x8019BCEC; // type:func rom:0x1D21EC
__calls_inc_menu_timer = 0x80177A38; // rom:0x4D938
__MENU_INDEX = 0x801BA94C;
musCurrentPtrBank = 0x800B182C;
osViModeTable = 0x800AA7E0;
osViSetMode = 0x800955C0;
osViSetEvent = 0x80095560;
osCreateScheduler = 0x80088C50;
osViBlack = 0x80089BE4;
osViSetSpecialFeatures = 0x80095610;
__init_controllers = 0x80089C60;
MusFxBankInitialize = 0x80081F7C;
osGetCause = 0x8009A6D0;
osGetSR = 0x8009A6F0;
osSetCompare = 0x8009A700;
osSetFpcCsr = 0x8009A710;
osSetSR = 0x8009A720;
osUnmapTLBAll = 0x8009AB00;
osMapTLBRdb = 0x8009AAA0;
__something_music = 0x80081DB4;
__real_read_controller = 0x8008A42C;
__calls_romCopy_8009DA50 = 0x8009DA50;
__calls_romCopy_8009DAF4 = 0x8009DAF4;
__calls_romCopy_8009DBB8 = 0x8009DBB8;
__calls_romCopy_8009DD38 = 0x8009DD38;
__calls_romCopy_8009DE40 = 0x8009DE40;
__calls_romCopy_8009DF48 = 0x8009DF48;
__start_thread_800BE1C0 = 0x8008B0B0;
__start_thread_800B9C88 = 0x80089660;
magnitude = 0x8009C780;
main_ = 0x80071EB0;
__dma_load_loop = 0x80089A30;
__dma_load_loop_check = 0x800819D4;
__MUS_MEM_800B18A4 = 0x800B18A4; // size:0x58
__MUS_MEM_800B186C = 0x800B186C;
__MUS_MEM_800B1870 = 0x800B1870;
__MUS_MEM_800B1868 = 0x800B1868;
MQ_CONTROLLER = 0x800E9B88;
MQ_800E7988 = 0x800E7988;
MQ_800C4A00 = 0x800C4A00;
MQ_800E9BF0 = 0x800E9BF0;
MQ_800C4C28 = 0x800C4C28;
MQ_800C35A0 = 0x800C35A0;
MQ_800AF320 = 0x800AF320;
MQ_800B1880 = 0x800B1880;
MQ_800E79C8 = 0x800E79C8;
MQ_800C49E8 = 0x800C49E8;
MQ_800BE030 = 0x800BE030;
MQ_800E8B84 = 0x800E8B84;
MQ_800B9C40 = 0x800B9C40;
MQ_800E8B4C = 0x800E8B4C;
OSMESG_800BE190 = 0x800BE190;
OSMESG_800BE194 = 0x800BE194;
OSMESG_800BE1A0 = 0x800BE1A0;
OSMESG_800B1870 = 0x800B1870;
OSMESG_800B17D0 = 0x800B17D0;
OSMESG_800B17E0 = 0x800B17E0;
OSMESG_800BE048 = 0x800BE048;
OSMESG_800B9C58 = 0x800B9C58;
OSMESG_800B9C80 = 0x800B9C80;
SP_THREAD_IDLE = 0x800B17A0;
SP_THREAD_FIRST_DMA_LOAD = 0x800C6D60;
SP_THREAD_800BE1C0 = 0x800C2370;
SP_THREAD_800B9C88 = 0x800BBE40;
THREAD_CONTROLLER = 0x800BBE80;
THREAD_FIRST_DMA_LOAD = 0x800AF5F0;
THREAD_800B7A90 = 0x800B7A90;
THREAD_800BE1C0 = 0x800BE1C0;
THREAD_800B9C88 = 0x800B9C88;
__thread_8007AC30 = 0x8007AC30;
__thread_8008AFE0 = 0x8008AFE0;
__thread_80093EE8 = 0x80093EE8;
__thread_80088F08 = 0x80088F08;
__thread_80089200 = 0x80089200;
__thread_800893C0 = 0x800893C0;
__thread_80089540 = 0x80089540;
__scMain = 0x80089358;
FP_800A9E84 = 0x800A9E84;
__set_fp_800A9E84 = 0x800899D0;
romCopy = 0x80089F80;
CART_HANDLE = 0x800E7A20;
__CART_HANDLE_800B1898 = 0x800B1898;
__GLOBAL_CONTROLLER_DATA = 0x0800C4BF0; // size:0x18
__GLOBAL_CONTROLLER_DATA_COPY = 0x0800AEE78; // size:0x18
__start_controller_thread = 0x80089D7C;
__calls_copy_controller_data = 0x8007297C;
__copy_global_controller_data = 0x8008A600;
__start_copy_global_controller_data = 0x8008A354;
__end_copy_global_controller_data = 0x8008A37C;
__read_controller = 0x8008A3A4;
__calls_read_controller_0 = 0x8008A47C;
__calls_read_controller_1 = 0x8008A508;
__calls_read_controller_2 = 0x8008A528;
__CRC_ERROR = 0x800AE2A0;
__FILE_WRITE_ERROR = 0x800AE348;
__FILE_READ_ERROR = 0x800AE378;
__logs_read_error = 0x8007C590;
__file_read = 0x8007F570;
___FILE_WRITE_ERROR = 0x800AE38C;
__file_write = 0x08007F5D8;
__ERROR_BAD_TABLE = 0x800AE338;
__VIRTUAL_MEMORY_EXHAUSTED = 0x800AE35C;
__some_logging = 0x80093540;
__virtual_mem_alloc = 0x80070F30;
__controller_thread_80089D9C = 0x80089D9C;
__Mus_thread_80085908 = 0x80085908;
THREAD_IDLE = 0x800AF440;
idle = 0x8007F8E4;
initialise = 0x80089F40;
boot = 0x8007F880;
entry = 0x80070C00;
guRotateRPYF = 0x80092A90;
CHARACTER_SLOT_MAGNUS = 0x80193BF8; // size:0x38
CHARACTER_SLOT_01 = 0x80193C30; // size:0x38
CHARACTER_SLOT_02 = 0x80193C68; // size:0x38
PERSPECTIVE_MATRIX_00 = 0x801969b0;
PERSPECTIVE_MATRIX_01 = 0x800C4BE4;
AddHeap = 0x80070D20;
HIsAllocatedPointer = 0x800714D4;
can_log_crc_error = 0x8007B88C;
proutSprintf = 0x80093508;
osSyncPrintf = 0x80093540;
rmonPrintf = 0x80093554;
bzero = 0x80093380;
strchr = 0x80093420;
strlen = 0x80093460;
memcpy = 0x80093484;
_bcmp = 0x80092F50;
_bcopy = 0x80093060;
MusHandlePause = 0x80081EA4;
MusHandleUnpause = 0x80081EC8;
MusSetFxType = 0x80081EF0;
MusFxBankNumberOfEffects = 0x80082000;
MusFxBankSetPtrBank = 0x8008202C;
MusFxBankGetPtrBank = 0x80082034;
MusSetMasterVolume = 0x800814C4;
MusStartSong = 0x800814F0;
MusPtrBankSetCurrent = 0x80081E18;
__MusIntInitSweep = 0x80083010;
__MusIntMemMalloc = 0x80085ADC;
alSynAllocFX = 0x8008FF70;
alFxNew = 0x8008C694;
alFxParam = 0x8008EEA4;
alMainBusParam = 0x8008E850;
alInit = 0x8008F7A0;
alUnlink = 0x8008F81C;
alClose = 0x8008F7CC;
alLink = 0x8008F7FC;
alGlobals = 0x800AA710;
alSynNew = 0x8008F920;
alCopy = 0x8008F8E0;
alSavePull = 0x8008F6D0;
alSaveParam = 0x8008F778;
alSynDelete = 0x8008FF60;
sqrtf = 0x800907E0;
sinf = 0x80092DB0;
cosf = 0x800907F0;
guOrthoF = 0x800920A0;
guOrtho = 0x800921D0;
guPerspectiveF = 0x80092320;
guPerspective = 0x800924D0;
guPositionF = 0x800926A0;
guPosition = 0x80092878;
guRotateRPY = 0x80092C18;
guMtxF2L = 0x800988A0;
guMtxL2F = 0x80098920;
guMtxCatF = 0x800989A0;
guMtxCatL = 0x80098340;
guMtxXFML = 0x800983C0;
guMtxXFMF = 0x80098450;
guNormalize = 0x80098BC0;
guMtxIdent = 0x800987E0;
guMtxIdentF = 0x80098840;
guRotateF = 0x80098500;
guRotate = 0x80098660;
guScaleF = 0x80098B60;
guTranslateF = 0x80098D00;
guLookAtF = 0x80090940;
guLookAt = 0x80090CC0;
guLookAtHiliteF = 0x80091050;
guLookAtHilite = 0x800919D4;
guLookAtReflectF = 0x80091AB0;
guLookAtReflect = 0x80092028;
CartRomHandle = 0x800C4C54;
osTvType = 0x80000300; // type:s32
osRomBase = 0x80000308; // type:s32
osInitialize = 0x80098050;
osInvalICache = 0x800900C0;
osGetCount = 0x8009A6E0;
osCreateViManager = 0x80095220;
osCreateMesgQueue = 0x80093570;
osVirtualToPhysical = 0x80090780;
osContGetReadData = 0x80090318;
osContGetQuery = 0x80090270;
osGetTime = 0x80094C90;
osSetTimer = 0x80094D40;
osYieldThread = 0x80094C40;
osGetThreadPri = 0x80094930;
osSetThreadPri = 0x80094950;
osWritebackDCache = 0x80090140;
osWritebackDCacheAll = 0x800901C0;
osSetIntMask = 0x8008B820;
osCartRomInit = 0x8008BD30;
osStartThread = 0x80094A20;
osJamMesg = 0x800935A0;
osRecvMesg = 0x800936E0;
osSendMesg = 0x80093810;
osSetEventMesg = 0x80093940;
osContStartQuery = 0x800901F0;
osContInit = 0x80090470;
osContStartReadData = 0x80090290;
osCreateThread = 0x80094860;
osCreatePiManager = 0x8008B8C0;
osInvalDCache = 0x80090010;
osDestroyThread = 0x8009A9C0;
__osDevMgrMain = 0x8008BEB0;
__osPackReadData = 0x800903B4;
__osProbeTLB = 0x800950E0;
__osEnqueueAndYield = 0x800993DC;
__osDisableInt = 0x800996D0;
__osRestoreInt = 0x80099740;
__osPopThread = 0x8009952C;
__osThreadTail = 0x800AA790;
__osContLastCmd = 0x800E79A8;
__osPackRequestData = 0x800906C0;
__osContPifRam = 0x800C4A20; // size:0x40
__osContGetInitData = 0x8009060C;
__osViGetCurrentContext = 0x8009AC60;
__osViSwapContext = 0x80095820;
__osTimerInterrupt = 0x80094E34;
__osViIntrCount = 0x800C4BA8;
__osDequeueThread = 0x80094C00;
__osRunningThread = 0x800AA7A0;
__osDispatchThread = 0x8009953C;
__osActiveQueue = 0x800AA79C;
__osTimerServicesInit = 0x80094DE0;
__osSiAccessQueue = 0x800E9BC8;
__osViInit = 0x8009AB50;
__osBaseCounter = 0x800C4814;
__osCurrentTime = 0x800C4C40;
__osContinitialized = 0x800AA720;
__osMaxControllers = 0x800C4C1C;
__osSiCreateAccessQueue = 0x80094770;
__osEepromTimerQ = 0x800E99D0;
__osEepromTimerMsg = 0x800E79B8;
piAccessBuf = 0x800C3550;
piEventQueue = 0x800C3530;
piEventBuf = 0x800C3548;
piThread = 0x800C2380;
osPiStartDma = 0x8008C360;
osEPiStartDma = 0x8008BC40;
osPiGetCmdQueue = 0x800998C0;
__osPiCreateAccessQueue = 0x8008C270;
__osPiRelAccess = 0x8008C330;
__osPiGetAccess = 0x8008C2C4;
__osPiAccessQueueEnabled = 0x800AA440;
__osPiAccessQueue = 0x800C4CC8;
__osPiDevMgr = 0x800AA400; // size:0x1C
siAccessBuf = 0x800C35A0;
__osSiRawStartDma = 0x800946C0;
__osSiRawStartDma = 0x800946C0;
__osSiRelAccess = 0x80094830;
__osSiGetAccess = 0x800947C4;
__osSiAccessQueueEnabled = 0x800AA780;
__osSpGetStatus = 0x800939F0;
viMgrMain = 0x800953C0;
viEventQueue = 0x800C4770;
viEventBuf = 0x800C4788;
viRetraceMsg = 0x800C47A0; // size:0x18
viCounterMsg = 0x800C47B8; // size:0x18
__osViDevMgr = 0x800AA7C0; // size:0x1C

271
tools/data_structure.py Normal file
View File

@ -0,0 +1,271 @@
import struct
from collections import namedtuple
CLASS_NAME = {
0x01: "Soldier",
0x02: "Fighter",
0x03: "Lycanthrope",
0x04: "Amazon",
0x05: "Knight",
0x06: "Berserker",
0x07: "Fencer",
0x08: "Phalanx",
0x09: "BeastTamer",
0x0A: "DollMaster",
0x0B: "Ninja",
0x0C: "Wizard",
0x0D: "Archer",
0x0E: "DragonTamer",
0x0F: "Valkyrie",
0x10: "Witch",
0x11: "Sorceress",
0x12: "Cleric",
0x13: "Paladin",
0x14: "Dragoon",
0x15: "BlackKnight",
0x16: "SwordMaster",
0x17: "Cataphract",
0x18: "BeastMaster",
0x19: "Enchanter",
0x1A: "NinjaMaster",
0x1B: "Archmage",
0x1C: "Diana",
0x1D: "DragonMaster",
0x1E: "Freya",
0x1F: "Siren",
0x20: "Priest",
0x21: "Princess",
0x22: "Centurion",
0x23: "Centurion",
0x24: "AngelKnight",
0x25: "Seraph",
0x26: "Lich",
0x27: "Hawkman",
0x28: "Vultan",
0x29: "Raven",
0x2A: "Werewolf",
0x2B: "Vampire",
0x2C: "Vampire",
0x2D: "Zombie",
0x2E: "Zombie",
0x2F: "Skeleton",
0x30: "Ghost",
0x31: "Gorgon",
0x32: "Pumpkinhead",
0x33: "Faerie",
0x34: "Gremlin",
0x35: "Goblin",
0x36: "Saturos",
0x37: "Ogre",
0x38: "YoungDragon",
0x39: "ThunderDragon",
0x3A: "RedDragon",
0x3B: "EarthDragon",
0x3C: "BlueDragon",
0x3D: "PlatinumDragon",
0x3E: "BlackDragon",
0x3F: "Quetzalcoatl",
0x40: "Flarebrass",
0x41: "AhziDahaka",
0x42: "Hydra",
0x43: "Bahamut",
0x44: "Tiamat",
0x45: "Wyrm",
0x46: "Wyvern",
0x47: "Griffin",
0x48: "Opinincus",
0x49: "Cockatrice",
0x4A: "Sphinx",
0x4B: "Hellhound",
0x4C: "Cerberus",
0x4D: "Giant",
0x4E: "Golem",
0x4F: "StoneGolem",
0x50: "BaldrGolem",
0x51: "Gladiator",
0x52: "Vanguard",
0x53: "General",
0x54: "Gladiator",
0x55: "Warrior",
0x56: "BlazeKnight",
0x57: "RuneKnight",
0x58: "Lord",
0x59: "General",
0x5A: "BeastMaster",
0x5B: "Priest",
0x5C: "Warlock",
0x5D: "Grappler",
0x5E: "Centurion",
0x5F: "Lycanthrope",
0x60: "Werewolf",
0x61: "Solidblade",
0x62: "Overlord",
0x63: "DarkPrince",
0x64: "SpecialClass",
0x65: "FlailMonarch",
0x66: "DeathTemplar",
0x67: "TempleCommander",
0x68: "TempleCommander",
0x69: "TempleCommander",
0x6A: "TempleCommander",
0x6B: "TempleCommander",
0x6C: "Vanity",
0x6D: "Vanity",
0x6E: "Vanity",
0x6F: "SuperiorKnight",
0x70: "SuperiorKnight",
0x71: "Gatekeeper",
0x72: "Grappler",
0x73: "KnightTemplar",
0x74: "Daemon",
0x75: "Phalanx",
0x76: "Berserker",
0x77: "Cleric",
0x78: "Archer",
0x79: "Hawkman",
0x7A: "Siren",
0x7B: "Enchanter",
0x7C: "BlackKnight",
0x7D: "SpecialClass",
0x7E: "SpecialClass",
0x7F: "SpecialClass",
0x80: "SpecialClass",
0x81: "SpecialClass",
0x82: "Barkeep",
0x83: "ElderlyMan",
0x84: "Commoner",
0x85: "Commoner",
0x86: "Danika",
0x87: "Danika_01",
0x88: "Danika_02",
0x89: "Archer",
0x8A: "Berserker",
0x8B: "BeastTamer",
0x8C: "Valkyrie",
0x8D: "Wizard",
0x8E: "Phalanx",
0x8F: "Berserker",
0x90: "Knight",
0x91: "NinjaMaster",
0x92: "DollMaster",
0x93: "KnightTemplar",
0x94: "Archmage",
0x95: "Priest",
0x96: "BlackKnight",
0x97: "DragonMaster",
0x98: "Siren",
0x99: "Saturos",
0x9A: "SwordMaster",
0x9B: "KnightTemplar",
0x9C: "Dragoon",
0x9D: "Gorgon",
0x9E: "Lich",
0x9F: "Daemon",
0xA0: "Plaladin",
0xA1: "Danika",
0xA2: "Paladin",
0xA3: "Witch",
0xA4: "DeathBahamut",
}
pattern = """4D61676E 75730000 00000000 00000000
00515104 00000059 00590132 0041003D
003C003C 003F003F 37000000 00000000
00000002 01000000 41726E6F 6C640000
00000000 00000000 00020203 00000053
00370332 003A003B 00370039 0031003B
37000000 00000000 00000000 02000000
4D612764 6F670000 00000000 00000000
00020203 00000051 00510432 003A003C
00360039 0031003B 37000000 00000000
00000000 03000000 486F6C6C 79000000
00000000 00000000 00040403 01000049
00490132 003D0033 003A003B 003D0042
37000000 00000000 00000000 04000000
4A65616E 6E650000 00000000 00000000
00040403 01000049 00490432 00390033
003B003D 003C0040 37000000 00000000
00000000 05000000 446F726F 74687900
00000000 00000000 00111103 0100004C
004C0123 003B0032 003C003D 003B0042
37000000 00000000 00000002 06000000
41737261 00000000 00000000 00000000
00020203 00000054 00540332 003C0039
00350039 0031003C 37000000 00000000
00000000 07000000 436C7964 65000000
00000000 00000000 00020203 00000052
00520332 003C003A 0038003A 0032003B
37000000 00000000 00000000 08000000
42727961 6E000000 00000000 00000000
00020203 00000051 00510232 003C0038
00350039 0031003A 38000000 00000000
00000000 09000000 4976616E 00000000
00000000 00000000 000A0A03 0000004F
004F0332 003D003A 0037003A 0033003C
36000000 00000000 00000002 0A000000
48616E6E 61000000 00000000 00000000
00040403 0100004B 004B0232 003D0034
0039003C 003A0042 36000000 00000000
00000000 0B000000 44696F00 00000000
00000000 00000000 00545404 00000054
0054012A 003E003B 00310035 00300036
32000000 00000000 00000002 0C000000
50697474 00000000 00000000 00000000
00020203 00000051 00510432 003B0037
002F0034 002D0034 32000000 00000000
00000000 0D000000 41627261 68616D00
00000000 00000000 00020203 00000050
00500432 00390037 002E0035 002F0034
32000000 00000000 00000000 0E000000
56617564 76696C6C 65000000 00000000
00020203 00000050 00500332 003B0039
002D0033 002F0033 32000000 00000000
00000000 0F000000 53657261 66696E61
00000000 00000000 00040403 0100004A
004A0432 003A0030 00330036 00360039
32000000 00000000 00000000 10000000
4B726973 00000000 00000000 00000000
00111103 01000049 00490323 003D0032
003B003A 003C0042 37000000 00000000
00000002 11000000 5A696567 6C657200
00000000 00000000 00080803 00000054
00540332 003D003B 00360038 0033003A
37000000 00000000 00000002 12000000
4F6D6567 61000000 00000000 00000000
004E4E03 02000071 00710332 004B005B
002C002D 002A0039 36000000 00000000
00000000 13000000"""
data = bytes.fromhex(pattern)
while len(data) > 0:
name = data[:0x10].decode("utf-8")
(portrait,) = struct.unpack_from('>h', data[0x10:])
(clazz,) = struct.unpack_from('>b', data[0x12:])
(level,) = struct.unpack_from('>b', data[0x13:])
(max_hp,) = struct.unpack_from('>h', data[0x16:])
(cur_hp,) = struct.unpack_from('>h', data[0x18:])
(strr,) = struct.unpack_from('>h', data[0x1C:])
(vit,) = struct.unpack_from('>h', data[0x1E:])
(intt,) = struct.unpack_from('>h', data[0x20:])
(mem,) = struct.unpack_from('>h', data[0x22:])
(agi,) = struct.unpack_from('>h', data[0x24:])
(dex,) = struct.unpack_from('>h', data[0x26:])
print(f"name= {name}")
print(f"portrait= {portrait}")
print(f"class= {CLASS_NAME[clazz]} ({clazz})")
print(f"max_health= {max_hp}")
print(f"current_health= {cur_hp}")
print(f"level= {level}")
print(f"str= {strr}")
print(f"vit= {vit}")
print(f"int= {intt}")
print(f"mem= {agi}")
print(f"agi= {agi}")
print(f"dex= {dex}")
print(f"rest= {data[0x26:0x38].hex()}")
print(" ")
data = data[0x38:]

Binary file not shown.

44
tools/splat_ext/lha.py Normal file
View File

@ -0,0 +1,44 @@
from pathlib import Path
from typing import Optional
from segtypes.n64.segment import N64Segment
from segtypes.n64.rgba16 import N64SegRgba16
from segtypes.n64.i4 import N64SegI4
from util import options, log
import lhafile
import sys
sys.path.append(str(options.opts.base_path / "tools"))
class N64SegLha(N64Segment):
def __init__(self, rom_start, rom_end, type, name, vram_start, args, yaml):
super().__init__(rom_start, rom_end, type, name, vram_start, args=args, yaml=yaml),
log.write(f"LHA decompression initialised with {self.name}")
def out_path(self) -> Optional[Path]:
return options.opts.asset_path / self.dir / f"{self.name}"
def split(self, rom_bytes):
data_bytes = rom_bytes[self.rom_start:self.rom_end]
path = self.out_path()
path.parent.mkdir(parents=True, exist_ok=True)
with path.open("wb") as f:
f.write(data_bytes)
f.close()
# Create Lhafile instance from filename
archive = lhafile.Lhafile(str(path))
# Print each file informaion in archive file.
for info in archive.infolist():
print(info.filename)
log.write(f"LHA decompression got {len(data_bytes)}")
log.write(data_bytes)

View File

@ -0,0 +1,30 @@
Copyright (c) 2010 Hidekazu Ohnishi.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its contributors
may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,2 @@
include COPYING.txt
include MANIFEST.in

View File

@ -0,0 +1,19 @@
Metadata-Version: 1.0
Name: lhafile
Version: 0.1
Summary: LHA(.lzh) file extract interface
Home-page: http://trac.neotitans.net/wiki/lhafile
Author: Hidekazu Ohnishi
Author-email: the-o@neotitans.net
License: BSD
Download-URL: http://trac.neotitans.net/wiki/lhafile
Description: Extract LHA(.lzh) file extension.
Its interface is likely zipfile extension is included in regular
python distribution.
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Envrionment :: Other Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS IndependentProgramming Language :: Python
Classifier: Topic :: Software Development

View File

@ -0,0 +1,5 @@
Readme for lhafile
Lhafile is extension that extract lha file(.lzh).
Its interface is likey zipfile module which is include regular python distribution.

View File

@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
from lhafile import *

View File

@ -0,0 +1,337 @@
# -*- coding:utf-8 -*-
# Copyright (c) 2010 Hidekazu Ohnishi.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# * Neither the name of the author nor the names of its contributors
# may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Lhafile, extension extract lzh file.
Its interface is likey zipfile module is include in regular python environment.
"""
import cStringIO
import datetime
import os
import os.path
import struct
import sys
import lzhlib
crc16 = lzhlib.crc16
def is_lhafile(filename):
try:
Lhafile(filename)
except:
return False
return True
class BadLhafile(Exception):
pass
class LhaInfo(object):
__slots__ = (
'orig_filename',
'filename',
'directory',
'date_time',
'compress_type',
'comment',
'extra',
'create_system',
'create_version',
'extract_version',
'reserved',
'flag_bits',
'volume',
'internal_attr',
'external_attr',
'header_offset',
'file_offset',
'CRC',
'compress_size',
'file_size',
)
def __init__(self):
self.orig_filename = None
self.filename = None
self.directory = None
self.date_time = None
self.compress_type = None
self.comment = None
self.extra = None
self.create_system = None
self.create_version = None
self.extract_version = None
self.reserved = None
self.flag_bits = None
self.volume = None
self.internal_attr = None
self.external_attr = None
self.header_offset = None
self.file_offset = None
self.CRC = None
self.compress_size = None
self.file_size = None
def __str__(self):
return '%s %s %08X %d %04X' % (self.filename, self.file_size,
self.file_offset, self.compress_size, self.CRC)
def __getstate__(self):
return (self.orig_filename, self.filename, self.directory, self.date_time,
self.compress_type, self.comment, self.extra, self.create_system,
self.create_version, self.extract_version, self.reserved,
self.flag_bits, self.volume, self.internal_attr, self.external_attr,
self.header_offset, self.file_offset, self.CRC, self.compress_size,
self.file_size)
def __setstate__(self, state):
(self.orig_filename, self.filename, self.directory, self.date_time,
self.compress_type, self.comment, self.extra, self.create_system,
self.create_version, self.extract_version, self.reserved,
self.flag_bits, self.volume, self.internal_attr, self.external_attr,
self.header_offset, self.file_offset, self.CRC, self.compress_size,
self.file_size) = state
class Lhafile:
"""
"""
SUPPORTED_COMPRESS_TYPE = ('-lhd-', '-lh0-', '-lh5-', '-lh6-', '-lh7-');
def __init__(self, file, mode="r", compression=None, callback=None, args=None):
""" Open the LZH file """
self.filelist = []
self.NameToInfo = {}
self.mode = key = mode.replace('b', '')[0]
if isinstance(file, basestring):
self._fileParsed = 0
self.filename = file
modeDict = {'r' : 'rb'}
self.fp = open(file, modeDict[mode])
else:
self._fileParsed = 1
self.fp = file
self.filename = getattr(file, 'name', None)
# Get file size
initial_pos = self.fp.tell()
self.fp.seek(0, 2)
self.filesize = self.fp.tell()
self.fp.seek(initial_pos, 0)
if key == 'r':
self._GetContents(callback=callback,args=args)
else:
if not self._fileParsed:
self.fp.close()
self.fp = None
raise RuntimeError, 'Mode must be "r"'
def _GetContents(self, callback=None, args=None):
try:
info = self._RealGetContent()
while info:
if not info.compress_type in Lhafile.SUPPORTED_COMPRESS_TYPE:
raise RuntimeError, "Unsupported file is contained %s" % (info.compress_type,)
if callback:
callback(args, self.fp.tell(), self.filesize, info)
self.filelist.append(info)
self.NameToInfo[info.filename] = info
info = self._RealGetContent()
except BadLhafile, e:
raise
if not self._fileParsed:
self.fp.close()
self.fp = None
def _RealGetContent(self):
fp = self.fp
filesize = self.filesize
initial_pos = fp.tell()
is_read = lambda x: fp.tell() + (x) < filesize
if fp.tell() == filesize - 1:
return None
if not is_read(26):
raise BadLhafile, "Header is broken"
# Check OS level
os_level = ord(fp.read(21)[20])
fp.seek(-21, 1)
if not os_level in (0, 1, 2):
raise BadLhafile, "this file level is out of support range %d" % os_level
if os_level in (0, 1):
header_size, checksum, signature, skip_size, \
file_size, modify_time, reserved , os_level, \
filename_length = struct.unpack('<BB5sII4sBBB', fp.read(22))
if is_read(filename_length + 2):
filename, crc = struct.unpack('<%dsH' % filename_length, fp.read(filename_length + 2))
if os_level == 0:
ext_header_size = 0
pass
elif os_level == 1:
extra_data_size = header_size - (5+4+4+2+2+1+1+1+filename_length+2+1+2)
os_identifier, extra_data, ext_header_size \
= struct.unpack('<c%dsH' % extra_data_size, fp.read(1 + extra_data_size + 2))
sum_ext_header_size = 0
directory = None
comment = None
compress_size = skip_size - sum_ext_header_size
elif os_level == 2:
header = fp.read(26)
all_header_size, signature, compress_size, file_size, \
modify_time, reserved, os_level, crc, os_identifier, \
ext_header_size = struct.unpack('<H5sIIIBBHBH', header)
sum_ext_header_size = 0
directory = None
comment = None
while ext_header_size != 0:
sum_ext_header_size += ext_header_size
if not is_read(ext_header_size):
raise BadLhafile, "File is broken"
(ext,) = struct.unpack('<B', fp.read(1))
if ext == 0x00:
# Common header
dummy, ext_header_size \
= struct.unpack('<%dsH' % (ext_header_size - 3), fp.read(ext_header_size-1))
elif ext == 0x01:
# Filename header
filename, ext_header_size \
= struct.unpack('<%dsH' % (ext_header_size - 3), fp.read(ext_header_size-1))
elif ext == 0x02:
# Directory name header
directory, ext_header_size \
= struct.unpack('<%dsH' % (ext_header_size - 3), fp.read(ext_header_size-1))
elif ext == 0x3F:
# Comment header
comment, ext_header_size \
= struct.unpack('<%dsH' % (ext_header_size - 3), fp.read(ext_header_size-1))
elif ext == 0x40:
# Attribute Header
if not ext_header_size == 5:
raise BadLhafile, "file is broken"
attr, ext_header_size \
= struct.unpack('<HH', fp.read(4))
else:
# Skip the other
dummy, ext_header_size \
= struct.unpack('<%dsH' % (ext_header_size - 3), fp.read(ext_header_size-1))
# skip to next header
file_offset = fp.tell()
if os_level in (0, 1):
compress_size = skip_size - sum_ext_header_size
if not is_read(compress_size):
raise BadLhafile, "Compress data is too short"
fp.seek(compress_size, 1)
# modify_time
if os_level in (0, 1):
year = (ord(modify_time[3]) >> 1) + 1980
month = ((ord(modify_time[3]) << 8 | ord(modify_time[2])) >> 5) & 0x0F
day = ord(modify_time[2]) & 0x1F
hour = ord(modify_time[1]) >> 3
minute = ((ord(modify_time[1]) << 8 | ord(modify_time[0])) >> 5) & 0x2F
second = (ord(modify_time[0]) & 0x1F) * 2
date_time = datetime.datetime(year, month, day, hour, minute, second)
create_time = date_time
elif os_level in (2,):
dummy_date = datetime.datetime(1970,1,1)
date_time = dummy_date.fromtimestamp(modify_time)
create_time = date_time
info = LhaInfo()
if directory is None:
# for lhaplus archive
sjisname = unicode(filename, 'cp932')
if '\\' in sjisname:
sjispath = [s.encode('cp932') for s in sjisname.split(u'\\')]
filename = os.sep.join(sjispath)
directory = os.sep.join(sjispath[:-1])
else:
directory = os.sep.join(directory.split('\xff'))
filename = os.path.join(directory, filename)
info.directory = directory
info.filename = filename
info.compress_size = compress_size
info.file_size = file_size
info.CRC = crc
info.header_offset = initial_pos
info.file_offset = file_offset
info.external_attr = None
info.internal_attr = None
info.reserved = 0
info.comment = comment
info.compress_type = signature
info.date_time = date_time
return info
def lhaname(self):
return self.filename
def namelist(self):
if self.filelist:
return [d.filename for d in self.filelist \
if d.compress_type in Lhafile.SUPPORTED_COMPRESS_TYPE]
return None
def infolist(self):
return self.filelist
def read(self, name):
"""Return file bytes (as a string) for 'name'. """
if not self.fp:
raise RuntimeError, \
"Attempt to read LZH archive that was already closed"
info = self.NameToInfo[name]
if info.compress_type in Lhafile.SUPPORTED_COMPRESS_TYPE:
self.fp.seek(info.file_offset)
fin = cStringIO.StringIO(self.fp.read(info.compress_size))
fout = cStringIO.StringIO()
try:
session = lzhlib.LZHDecodeSession(fin, fout, info)
while session.do_next() == False:
pass
outsize = session.output_pos
crc = session.crc16
except Exception, e:
raise e
if outsize != info.file_size:
raise BadLhafile, "%s output_size is not matched %d/%d %s" % \
(name, outsize, info.file_size, info.compress_type)
if crc != info.CRC:
raise BadLhafile, "crc is not matched"
fout.seek(0)
bytes = fout.read()
elif info.commpress_type == '-lhd-':
raise RuntimeError, \
"name is directory"
else:
raise RuntimeError, \
"Unsupport format"
return bytes

View File

@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
from lhafile import *

View File

@ -0,0 +1,337 @@
# -*- coding:utf-8 -*-
# Copyright (c) 2010 Hidekazu Ohnishi.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# * Neither the name of the author nor the names of its contributors
# may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Lhafile, extension extract lzh file.
Its interface is likey zipfile module is include in regular python environment.
"""
import cStringIO
import datetime
import os
import os.path
import struct
import sys
import lzhlib
crc16 = lzhlib.crc16
def is_lhafile(filename):
try:
Lhafile(filename)
except:
return False
return True
class BadLhafile(Exception):
pass
class LhaInfo(object):
__slots__ = (
'orig_filename',
'filename',
'directory',
'date_time',
'compress_type',
'comment',
'extra',
'create_system',
'create_version',
'extract_version',
'reserved',
'flag_bits',
'volume',
'internal_attr',
'external_attr',
'header_offset',
'file_offset',
'CRC',
'compress_size',
'file_size',
)
def __init__(self):
self.orig_filename = None
self.filename = None
self.directory = None
self.date_time = None
self.compress_type = None
self.comment = None
self.extra = None
self.create_system = None
self.create_version = None
self.extract_version = None
self.reserved = None
self.flag_bits = None
self.volume = None
self.internal_attr = None
self.external_attr = None
self.header_offset = None
self.file_offset = None
self.CRC = None
self.compress_size = None
self.file_size = None
def __str__(self):
return '%s %s %08X %d %04X' % (self.filename, self.file_size,
self.file_offset, self.compress_size, self.CRC)
def __getstate__(self):
return (self.orig_filename, self.filename, self.directory, self.date_time,
self.compress_type, self.comment, self.extra, self.create_system,
self.create_version, self.extract_version, self.reserved,
self.flag_bits, self.volume, self.internal_attr, self.external_attr,
self.header_offset, self.file_offset, self.CRC, self.compress_size,
self.file_size)
def __setstate__(self, state):
(self.orig_filename, self.filename, self.directory, self.date_time,
self.compress_type, self.comment, self.extra, self.create_system,
self.create_version, self.extract_version, self.reserved,
self.flag_bits, self.volume, self.internal_attr, self.external_attr,
self.header_offset, self.file_offset, self.CRC, self.compress_size,
self.file_size) = state
class Lhafile:
"""
"""
SUPPORTED_COMPRESS_TYPE = ('-lhd-', '-lh0-', '-lh5-', '-lh6-', '-lh7-');
def __init__(self, file, mode="r", compression=None, callback=None, args=None):
""" Open the LZH file """
self.filelist = []
self.NameToInfo = {}
self.mode = key = mode.replace('b', '')[0]
if isinstance(file, basestring):
self._fileParsed = 0
self.filename = file
modeDict = {'r' : 'rb'}
self.fp = open(file, modeDict[mode])
else:
self._fileParsed = 1
self.fp = file
self.filename = getattr(file, 'name', None)
# Get file size
initial_pos = self.fp.tell()
self.fp.seek(0, 2)
self.filesize = self.fp.tell()
self.fp.seek(initial_pos, 0)
if key == 'r':
self._GetContents(callback=callback,args=args)
else:
if not self._fileParsed:
self.fp.close()
self.fp = None
raise RuntimeError, 'Mode must be "r"'
def _GetContents(self, callback=None, args=None):
try:
info = self._RealGetContent()
while info:
if not info.compress_type in Lhafile.SUPPORTED_COMPRESS_TYPE:
raise RuntimeError, "Unsupported file is contained %s" % (info.compress_type,)
if callback:
callback(args, self.fp.tell(), self.filesize, info)
self.filelist.append(info)
self.NameToInfo[info.filename] = info
info = self._RealGetContent()
except BadLhafile, e:
raise
if not self._fileParsed:
self.fp.close()
self.fp = None
def _RealGetContent(self):
fp = self.fp
filesize = self.filesize
initial_pos = fp.tell()
is_read = lambda x: fp.tell() + (x) < filesize
if fp.tell() == filesize - 1:
return None
if not is_read(26):
raise BadLhafile, "Header is broken"
# Check OS level
os_level = ord(fp.read(21)[20])
fp.seek(-21, 1)
if not os_level in (0, 1, 2):
raise BadLhafile, "this file level is out of support range %d" % os_level
if os_level in (0, 1):
header_size, checksum, signature, skip_size, \
file_size, modify_time, reserved , os_level, \
filename_length = struct.unpack('<BB5sII4sBBB', fp.read(22))
if is_read(filename_length + 2):
filename, crc = struct.unpack('<%dsH' % filename_length, fp.read(filename_length + 2))
if os_level == 0:
ext_header_size = 0
pass
elif os_level == 1:
extra_data_size = header_size - (5+4+4+2+2+1+1+1+filename_length+2+1+2)
os_identifier, extra_data, ext_header_size \
= struct.unpack('<c%dsH' % extra_data_size, fp.read(1 + extra_data_size + 2))
sum_ext_header_size = 0
directory = None
comment = None
compress_size = skip_size - sum_ext_header_size
elif os_level == 2:
header = fp.read(26)
all_header_size, signature, compress_size, file_size, \
modify_time, reserved, os_level, crc, os_identifier, \
ext_header_size = struct.unpack('<H5sIIIBBHBH', header)
sum_ext_header_size = 0
directory = None
comment = None
while ext_header_size != 0:
sum_ext_header_size += ext_header_size
if not is_read(ext_header_size):
raise BadLhafile, "File is broken"
(ext,) = struct.unpack('<B', fp.read(1))
if ext == 0x00:
# Common header
dummy, ext_header_size \
= struct.unpack('<%dsH' % (ext_header_size - 3), fp.read(ext_header_size-1))
elif ext == 0x01:
# Filename header
filename, ext_header_size \
= struct.unpack('<%dsH' % (ext_header_size - 3), fp.read(ext_header_size-1))
elif ext == 0x02:
# Directory name header
directory, ext_header_size \
= struct.unpack('<%dsH' % (ext_header_size - 3), fp.read(ext_header_size-1))
elif ext == 0x3F:
# Comment header
comment, ext_header_size \
= struct.unpack('<%dsH' % (ext_header_size - 3), fp.read(ext_header_size-1))
elif ext == 0x40:
# Attribute Header
if not ext_header_size == 5:
raise BadLhafile, "file is broken"
attr, ext_header_size \
= struct.unpack('<HH', fp.read(4))
else:
# Skip the other
dummy, ext_header_size \
= struct.unpack('<%dsH' % (ext_header_size - 3), fp.read(ext_header_size-1))
# skip to next header
file_offset = fp.tell()
if os_level in (0, 1):
compress_size = skip_size - sum_ext_header_size
if not is_read(compress_size):
raise BadLhafile, "Compress data is too short"
fp.seek(compress_size, 1)
# modify_time
if os_level in (0, 1):
year = (ord(modify_time[3]) >> 1) + 1980
month = ((ord(modify_time[3]) << 8 | ord(modify_time[2])) >> 5) & 0x0F
day = ord(modify_time[2]) & 0x1F
hour = ord(modify_time[1]) >> 3
minute = ((ord(modify_time[1]) << 8 | ord(modify_time[0])) >> 5) & 0x2F
second = (ord(modify_time[0]) & 0x1F) * 2
date_time = datetime.datetime(year, month, day, hour, minute, second)
create_time = date_time
elif os_level in (2,):
dummy_date = datetime.datetime(1970,1,1)
date_time = dummy_date.fromtimestamp(modify_time)
create_time = date_time
info = LhaInfo()
if directory is None:
# for lhaplus archive
sjisname = unicode(filename, 'cp932')
if '\\' in sjisname:
sjispath = [s.encode('cp932') for s in sjisname.split(u'\\')]
filename = os.sep.join(sjispath)
directory = os.sep.join(sjispath[:-1])
else:
directory = os.sep.join(directory.split('\xff'))
filename = os.path.join(directory, filename)
info.directory = directory
info.filename = filename
info.compress_size = compress_size
info.file_size = file_size
info.CRC = crc
info.header_offset = initial_pos
info.file_offset = file_offset
info.external_attr = None
info.internal_attr = None
info.reserved = 0
info.comment = comment
info.compress_type = signature
info.date_time = date_time
return info
def lhaname(self):
return self.filename
def namelist(self):
if self.filelist:
return [d.filename for d in self.filelist \
if d.compress_type in Lhafile.SUPPORTED_COMPRESS_TYPE]
return None
def infolist(self):
return self.filelist
def read(self, name):
"""Return file bytes (as a string) for 'name'. """
if not self.fp:
raise RuntimeError, \
"Attempt to read LZH archive that was already closed"
info = self.NameToInfo[name]
if info.compress_type in Lhafile.SUPPORTED_COMPRESS_TYPE:
self.fp.seek(info.file_offset)
fin = cStringIO.StringIO(self.fp.read(info.compress_size))
fout = cStringIO.StringIO()
try:
session = lzhlib.LZHDecodeSession(fin, fout, info)
while session.do_next() == False:
pass
outsize = session.output_pos
crc = session.crc16
except Exception, e:
raise e
if outsize != info.file_size:
raise BadLhafile, "%s output_size is not matched %d/%d %s" % \
(name, outsize, info.file_size, info.compress_type)
if crc != info.CRC:
raise BadLhafile, "crc is not matched"
fout.seek(0)
bytes = fout.read()
elif info.commpress_type == '-lhd-':
raise RuntimeError, \
"name is directory"
else:
raise RuntimeError, \
"Unsupport format"
return bytes

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2010 Hidekazu Ohnishi
#
# This software is released under the terms of the BSD license.
# For more information see the COPYING.txt file in this directory.
from distutils.core import setup, Extension
lzhlib = Extension('lzhlib',
define_macros=[('MAJOR_VERSION', '0'),
('MINOR_VERSION', '1')],
sources=['lhafile/lzhlib.c'])
setup(name="lhafile",
packages=['lhafile'],
version='0.1',
description="LHA(.lzh) file extract interface",
long_description="""Extract LHA(.lzh) file extension.
Its interface is likely zipfile extension is included in regular
python distribution.""",
author='Hidekazu Ohnishi',
author_email='the-o@neotitans.net',
url='http://trac.neotitans.net/wiki/lhafile',
download_url='http://trac.neotitans.net/wiki/lhafile',
license='BSD',
keywords = [],
classifiers = [
'Development Status :: 4 - Beta',
'Envrionment :: Other Environment',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent'
'Programming Language :: Python',
'Topic :: Software Development'],
ext_modules=[lzhlib])

107
undefined_funcs.txt Normal file
View File

@ -0,0 +1,107 @@
func_840010BC = 0x840010BC;
func_8008A37C = 0x8008A37C;
func_8008A354 = 0x8008A354;
func_8023A05C = 0x8023A05C;
func_8023A150 = 0x8023A150;
func_8023A0F0 = 0x8023A0F0;
func_8023A608 = 0x8023A608;
func_8023A7A0 = 0x8023A7A0;
func_8023A7A0 = 0x8023A7A0;
func_8023A884 = 0x8023A884;
func_8023A884 = 0x8023A884;
func_8023A8A8 = 0x8023A8A8;
func_8023B4A0 = 0x8023B4A0;
func_8023B894 = 0x8023B894;
func_8023B928 = 0x8023B928;
func_8023B928 = 0x8023B928;
func_8023BBF0 = 0x8023BBF0;
func_8023BB78 = 0x8023BB78;
func_8023BBCC = 0x8023BBCC;
func_8023BD3C = 0x8023BD3C;
func_8023BCC8 = 0x8023BCC8;
func_8023BD1C = 0x8023BD1C;
func_8023BDB0 = 0x8023BDB0;
func_8023BF00 = 0x8023BF00;
func_8023C030 = 0x8023C030;
func_8023C1E8 = 0x8023C1E8;
func_8023C2E0 = 0x8023C2E0;
func_8023C304 = 0x8023C304;
func_8023C70C = 0x8023C70C;
func_8023D304 = 0x8023D304;
func_8023D7A0 = 0x8023D7A0;
func_8023D908 = 0x8023D908;
func_8023D90C = 0x8023D90C;
func_8023D90C = 0x8023D90C;
func_8023E4E8 = 0x8023E4E8;
func_8023DD90 = 0x8023DD90;
func_8023DE84 = 0x8023DE84;
func_8023E154 = 0x8023E154;
func_8023E7A4 = 0x8023E7A4;
func_8023E990 = 0x8023E990;
func_8023EAC8 = 0x8023EAC8;
func_8023EBF8 = 0x8023EBF8;
func_8023EDB8 = 0x8023EDB8;
func_8023EDB8 = 0x8023EDB8;
func_8023EEA0 = 0x8023EEA0;
func_8023F3E8 = 0x8023F3E8;
func_8023F3E8 = 0x8023F3E8;
func_8023F48C = 0x8023F48C;
func_8023F48C = 0x8023F48C;
func_8023F958 = 0x8023F958;
func_8023FA6C = 0x8023FA6C;
func_8023FC98 = 0x8023FC98;
func_8023FC98 = 0x8023FC98;
func_8023FC94 = 0x8023FC94;
func_8023FC98 = 0x8023FC98;
func_8023FC98 = 0x8023FC98;
func_8023FF34 = 0x8023FF34;
func_80240004 = 0x80240004;
func_80240144 = 0x80240144;
func_80240168 = 0x80240168;
func_80240180 = 0x80240180;
func_80240238 = 0x80240238;
func_80240474 = 0x80240474;
func_802406AC = 0x802406AC;
func_80240860 = 0x80240860;
func_802408E4 = 0x802408E4;
func_80240958 = 0x80240958;
func_802409BC = 0x802409BC;
func_80240C68 = 0x80240C68;
func_80240F18 = 0x80240F18;
func_80240EE4 = 0x80240EE4;
func_80240EF0 = 0x80240EF0;
func_80240F84 = 0x80240F84;
func_802415D4 = 0x802415D4;
func_80241698 = 0x80241698;
func_8024169C = 0x8024169C;
func_80241724 = 0x80241724;
func_80241744 = 0x80241744;
func_80241AE4 = 0x80241AE4;
func_80241BF0 = 0x80241BF0;
func_80241DE0 = 0x80241DE0;
func_80242010 = 0x80242010;
func_80242010 = 0x80242010;
func_80242404 = 0x80242404;
func_80242404 = 0x80242404;
func_80242400 = 0x80242400;
func_80242400 = 0x80242400;
func_80242400 = 0x80242400;
func_802424C4 = 0x802424C4;
func_802424C4 = 0x802424C4;
func_802424C0 = 0x802424C0;
func_802424C0 = 0x802424C0;
func_802424C0 = 0x802424C0;
func_80242E44 = 0x80242E44;
func_80242F14 = 0x80242F14;
func_8024304C = 0x8024304C;
func_80243048 = 0x80243048;
func_80243034 = 0x80243034;
func_8024339C = 0x8024339C;
func_80243424 = 0x80243424;
func_802434B4 = 0x802434B4;
func_80243510 = 0x80243510;
func_80243600 = 0x80243600;
func_8024366C = 0x8024366C;
func_802439E0 = 0x802439E0;
func_80243B94 = 0x80243B94;

39
undefined_syms.txt Normal file
View File

@ -0,0 +1,39 @@
D_800AEC70 = 0x800AEC70;
D_800AEC78 = 0x800AEC78;
D_800AEC80 = 0x800AEC80;
D_800AEC88 = 0x800AEC88;
D_800AEC90 = 0x800AEC90;
D_800AEC98 = 0x800AEC98;
D_800AECA0 = 0x800AECA0;
D_800AECA8 = 0x800AECA8;
D_800AECB0 = 0x800AECB0;
D_800AECC0 = 0x800AECC0;
D_800AECC8 = 0x800AECC8;
D_800AECD0 = 0x800AECD0;
D_800AECD8 = 0x800AECD8;
D_800AECE0 = 0x800AECE0;
D_800AECE8 = 0x800AECE8;
D_800AECF0 = 0x800AECF0;
D_800AECF8 = 0x800AECF8;
D_800AED00 = 0x800AED00;
D_800AED08 = 0x800AED08;
D_800AED10 = 0x800AED10;
D_800AED18 = 0x800AED18;
D_800AED20 = 0x800AED20;
D_800AED28 = 0x800AED28;
D_800AED30 = 0x800AED30;
D_800AED38 = 0x800AED38;
D_800AED40 = 0x800AED40;
D_800AED44 = 0x800AED44;
D_800AED48 = 0x800AED48;
D_800AED50 = 0x800AED50;
D_800AED58 = 0x800AED58;
D_800AED60 = 0x800AED60;
D_800EB8F4 = 0x800EB8F4;
D_800EB970 = 0x800EB970;
D_800EB9F4 = 0x800EB9F4;
D_800A8210 = 0x800A8210;
D_80187020 = 0x80187020;
D_80187030 = 0x80187030;
D_8018F1A0 = 0x8018F1A0;
D_8018FC18 = 0x8018FC18;