pso_gc_tools/quests.h
Gered 27b2956e0e remove quest number validation check
plus, it was written wrong anyway, heh. but, quest numbers can indeed
be zero, so this was not a proper validation check anyway.
2021-03-26 17:56:53 -04:00

123 lines
4.7 KiB
C

#ifndef QUESTS_H_INCLUDED
#define QUESTS_H_INCLUDED
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "defs.h"
#define QUESTBIN_ERROR_OBJECT_CODE_OFFSET 1
#define QUESTBIN_ERROR_LARGER_BIN_SIZE 2
#define QUESTBIN_ERROR_SMALLER_BIN_SIZE 4
#define QUESTBIN_ERROR_NAME 8
#define QUESTBIN_ERROR_EPISODE 16
#define QUESTDAT_ERROR_TYPE 1
#define QUESTDAT_ERROR_TABLE_BODY_SIZE 2
#define QUESTDAT_ERROR_PREMATURE_EOF 4
#define PACKET_ID_QUEST_INFO_ONLINE 0x44
#define PACKET_ID_QUEST_INFO_DOWNLOAD 0xa6
#define PACKET_ID_QUEST_CHUNK_ONLINE 0x13
#define PACKET_ID_QUEST_CHUNK_DOWNLOAD 0xa7
#define QUEST_FILENAME_MAX_LENGTH 16
// decompressed quest .bin file header
typedef struct _PACKED_ {
uint32_t object_code_offset;
uint32_t function_offset_table_offset;
uint32_t bin_size;
uint32_t xffffffff; // always 0xffffffff ?
uint8_t download; // must be '1' to be usable as an offline quest (played from memory card)
// have seen some projects define this field as language. "newserv" just calls it unknown? i've seen multiple
// values present for english language quests ...
uint8_t unknown;
// "newserv" has these like this here, as quest_number and episode separately. most other projects that parse
// .bin files treat quest_number as a 16-bit number. in general, i think the "episode" field as a separate byte
// is *probably* better when dealing with non-custom quests. however, some custom quests (which are mostly of
// dubious quality anyway) clearly were created using a tool which had quest_number as a 16-bit value ...
// ... so .... i dunno! i guess i'll just leave it like this ...
union {
struct {
uint8_t quest_number_byte;
uint8_t episode;
};
struct {
uint16_t quest_number_word;
};
};
// some sources say these strings are all UTF-16LE, but i'm not sure that is really the case for gamecube data?
// for gamecube-format quest .bin files, it instead looks like SHIFT-JIS probably ... ?
char name[32];
char short_description[128];
char long_description[288];
} QUEST_BIN_HEADER;
// decompressed quest .dat file table header
typedef struct _PACKED_ {
uint32_t type;
uint32_t table_size;
uint32_t area;
uint32_t table_body_size;
} QUEST_DAT_TABLE_HEADER;
// .qst file header, for either the embedded bin or dat quest data (there should be two of these per .qst file).
typedef struct _PACKED_ {
// 0xA6 = download to memcard, 0x44 = download for online play
// (quest file data chunks must then be encoded accordingly. 0xA6 = use 0xA7, and 0x44 = use 0x13)
uint8_t pkt_id;
// khyller sets .dat header value to 0xC9, .bin header value to 0x88
// newserv sets both to 0x00
// sylverant appears to set it differently per quest, the logic/reasoning behind it is unknown to me
// ... so, this value is probably unimportant?
uint8_t pkt_flags;
uint16_t pkt_size;
char name[32];
uint16_t unused;
// khyller sets .dat header value to 0x02, .bin header value to 0x00
// newserv sets both to 0x02
// sylverant sets both to 0x00
// ... and so, this value is also probably unimportant?
uint16_t flags;
char filename[QUEST_FILENAME_MAX_LENGTH];
uint32_t size;
} QST_HEADER;
// .qst raw .bin/.dat file data packet. the original .bin/.dat file data is broken down into as many of these structs
// as is necessary to fit into the resulting .qst file
typedef struct _PACKED_ {
uint8_t pkt_id;
uint8_t pkt_flags;
uint16_t pkt_size;
char filename[QUEST_FILENAME_MAX_LENGTH];
uint8_t data[1024];
uint32_t size;
} QST_DATA_CHUNK;
// for download/offline .qst files only. the raw .bin/.dat file data needs to be prefixed with one of these structs
// before being turned into QST_DATA_CHUNKs. only one of these is needed per each .bin/.dat file.
typedef struct _PACKED_ {
uint32_t decompressed_size;
uint32_t crypt_key;
} DOWNLOAD_QUEST_CHUNKS_HEADER;
int generate_qst_header(const char *src_file, size_t src_file_size, const QUEST_BIN_HEADER *bin_header, QST_HEADER *out_header);
int generate_qst_data_chunk(const char *base_filename, uint8_t counter, const uint8_t *src, uint32_t size, QST_DATA_CHUNK *out_chunk);
int validate_quest_bin(const QUEST_BIN_HEADER *header, uint32_t length, bool print_errors);
int validate_quest_dat(const uint8_t *data, uint32_t length, bool print_errors);
int handle_quest_bin_validation_issues(int bin_validation_result, QUEST_BIN_HEADER *bin_header, uint8_t **decompressed_bin_data, size_t *decompressed_bin_length);
int handle_quest_dat_validation_issues(int dat_validation_result, uint8_t **decompressed_dat_data, size_t *decompressed_dat_length);
void print_quick_quest_info(QUEST_BIN_HEADER *bin_header, size_t compressed_bin_size, size_t compressed_dat_size);
#endif