jak-project/game/overlord/isocommon.h
2020-08-22 22:30:12 -04:00

188 lines
5.6 KiB
C++

/*!
* @file isocommon.h
* Common ISO utilities.
*/
#ifndef JAK_V2_ISOCOMMON_H
#define JAK_V2_ISOCOMMON_H
#include <string>
#include "common/common_types.h"
#include "common/link_types.h"
constexpr int PRI_STACK_LENGTH = 4; // number of queued commands per priority
constexpr int N_PRIORITIES = 4; // number of priorities
constexpr u32 CMD_STATUS_READ_ERR = 8; // read encountered a problem or was canceled.
constexpr u32 CMD_STATUS_NULL_CB = 7; // status returned if you don't set a callback
constexpr u32 CMD_STATUS_FAILED_TO_OPEN = 6; // status if file couldn't be opened
constexpr u32 CMD_STATUS_FAILED_TO_QUEUE = 2; // status if we couldn't be queued
constexpr u32 CMD_STATUS_IN_PROGRESS = 0xffffffff; // status if command is running and healthy
constexpr u32 CMD_STATUS_DONE = 0; // status if command is done.
constexpr int BUFFER_PAGE_SIZE = 0xc000; // size in bytes of normal read buffer
constexpr int STR_BUFFER_DATA_SIZE = 0x6000; // size in bytes of vag read buffer
constexpr int LOAD_TO_EE_CMD_ID = 0x100; // command to load file to ee
constexpr int LOAD_TO_IOP_CMD_ID = 0x101; // command to load to iop
constexpr int LOAD_TO_EE_OFFSET_CMD_ID = 0x102; // command to load file to ee with offset.
constexpr int LOAD_DGO_CMD_ID = 0x200; // command to load DGO
constexpr int SECTOR_SIZE = 0x800; // media sector size
constexpr int MAX_ISO_FILES = 350; // maximum files on FS
constexpr int MAX_OPEN_FILES = 16; // maximum number of open files at a time.
/*!
* Record for file. There is one for each file in the FS, and pointers to each FileRecord act as
* an identifier.
* The location/size can't be counted on to be anything meaningful as it depends on the IsoFs
* implementation being used.
*/
struct FileRecord {
char name[12];
uint32_t location;
uint32_t size;
};
/*!
* Record for an open file.
*/
struct LoadStackEntry {
FileRecord* fr;
uint32_t location;
};
/*!
* Header for a ISO data buffer.
*/
struct IsoBufferHeader {
void* data; // 0
uint32_t data_size; // 1
uint32_t buffer_size;
void* next;
// follows the header.
u8* get_data() { return ((u8*)this) + sizeof(IsoBufferHeader); }
};
struct IsoMessage;
struct LoadStackEntry;
//! Callback function for data loads.
typedef u32 (*iso_callback_func)(IsoMessage* cmd, IsoBufferHeader* buffer);
/*!
* Command, common parent.
*/
struct IsoMessage {
uint32_t field_0x0; // 0x00
uint32_t field_0x4; // 0x04
uint32_t cmd_id; // 0x08
uint32_t status; // 0x0c
s32 messagebox_to_reply; // 0x10
s32 thread_id; // 0x14
uint32_t ready_for_data; // 0x18
IsoBufferHeader* callback_buffer; // 0x1c
iso_callback_func callback_function; // 0x20
LoadStackEntry* fd; // 0x24
};
/*!
* Command to load a single file.
*/
struct IsoCommandLoadSingle : public IsoMessage {
FileRecord* file_record; // 0x28
u8* dest_addr; // 0x2c
s32 length; // 0x30
s32 length_to_copy; // 0x34
u32 offset; // 0x38
u8* dst_ptr; // 0x3c
s32 bytes_done; // 0x40
};
/*!
* Command to do something.
*/
struct VagCommand : public IsoMessage {
u32 field_0x30;
u32 field_0x34;
u32 field_0x38;
u32 field_0x3c;
u32 field_0x40;
u32 field_0x44;
u32 field_0x48;
u32 field_0x4c;
// 0x6c max
};
/*!
* DGO Load State Machine states.
*/
enum class DgoState {
Init = 0,
Read_Header = 1,
Finish_Obj = 2,
Read_Last_Obj = 3,
Read_Obj_Header = 4,
Read_Obj_data = 5,
Finish_Dgo = 6
};
/*!
* Command to load a DGO.
*/
struct DgoCommand : public IsoMessage {
FileRecord* fr; // 0x28, DGO file that's open
u8* buffer1; // 0x2c, first EE buffer
u8* buffer2; // 0x30, second EE buffer
u8* buffer_heaptop; // 0x34, top of the heap
DgoHeader dgo_header; // 0x38, current DGO's header
ObjectHeader objHeader; // 0x78, current obj's header
u8* ee_destination_buffer; // 0xb8, where we are currently loading to on ee
u32 bytes_processed; // 0xbc, how many bytes processed in the current state
u32 objects_loaded; // 0xc0, completed object count
DgoState dgo_state; // 0xc4, state machine state
u32 finished_first_obj; // 0xc8, have we finished loading the first object?
u32 buffer_toggle; // 0xcc, which buffer to load into (top, buffer1, buffer2)
u8* selectedBuffer; // 0xd0, most recently completed load destination
u32 want_abort; // 0xd4, should we quit?
};
/*!
* Priority Stack entry.
*/
struct PriStackEntry {
IsoMessage* cmds[PRI_STACK_LENGTH]; // cmds at this priority
std::string names[PRI_STACK_LENGTH]; // my addition for debug
uint32_t n; // how many in this priority?
void reset();
};
/*!
* API to access files. There are debug modes + reading from an ISO filesystem.
*/
struct IsoFs {
int (*init)(u8*);
FileRecord* (*find)(const char*);
FileRecord* (*find_in)(const char*);
uint32_t (*get_length)(FileRecord*);
LoadStackEntry* (*open)(FileRecord*, int32_t);
LoadStackEntry* (*open_wad)(FileRecord*, int32_t);
void (*close)(LoadStackEntry*);
uint32_t (*begin_read)(LoadStackEntry*, void*, int32_t);
uint32_t (*sync_read)();
uint32_t (*load_sound_bank)(char*, void*);
uint32_t (*load_music)(char*, void*);
void (*poll_drive)();
};
extern IsoFs* isofs;
extern s32 iso_mbx;
void MakeISOName(char* dst, const char* src);
#endif // JAK_V2_ISOCOMMON_H