ACXLoader: implement GetDataString

Strings are embedded in the rows, making them variable length. So we now
deserialize the whole ACX file in ACXLoader.Load and store them such
that they can be indexed by row/col in constant time.
This commit is contained in:
Nunuhara Cabbage
2020-08-02 14:28:23 -07:00
parent 3d70c81404
commit 4afd54bb89
2 changed files with 77 additions and 20 deletions
+66 -19
View File
@@ -26,17 +26,50 @@
#include "vm/page.h"
#include "xsystem4.h"
union acx_value {
int32_t i;
struct string *s;
};
struct acx_file {
int compressed_size;
int size;
int nr_columns;
int nr_lines;
uint8_t *data_raw;
uint8_t *data;
int32_t *column_types;
union acx_value *lines;
};
static struct acx_file acx;
static void acx_read(uint8_t *data_raw)
{
acx.nr_columns = LittleEndian_getDW(data_raw, 0);
acx.nr_lines = LittleEndian_getDW(data_raw, 4 + acx.nr_columns * 4);
uint8_t *data = data_raw + (8 + acx.nr_columns * 4);
acx.column_types = xcalloc(acx.nr_columns, sizeof(int32_t));
for (int i = 0; i < acx.nr_columns; i++) {
acx.column_types[i] = LittleEndian_getDW(data_raw, 4 + 4*i);
}
int ptr = 0;
acx.lines = xcalloc(acx.nr_lines * acx.nr_columns, sizeof(union acx_value));
for (int line = 0; line < acx.nr_lines; line++) {
for (int col = 0; col < acx.nr_columns; col++) {
if (acx.column_types[col] == 2) {
int old_ptr = ptr;
while (data[ptr])
ptr++;
acx.lines[line*acx.nr_columns + col].s = make_string((char*)data+old_ptr, ptr-old_ptr);
ptr++;
} else {
acx.lines[line*acx.nr_columns + col].i = LittleEndian_getDW(data, ptr);
ptr += 4;
}
}
}
}
//bool Load(string pIFileName)
bool ACXLoader_Load(struct string *filename)
{
@@ -68,28 +101,35 @@ bool ACXLoader_Load(struct string *filename)
return false;
}
acx.compressed_size = LittleEndian_getDW(buf, 8);
acx.size = LittleEndian_getDW(buf, 12);
acx.data_raw = xmalloc(acx.size);
int compressed_size = LittleEndian_getDW(buf, 8);
unsigned long size = LittleEndian_getDW(buf, 12);
uint8_t *data_raw = xmalloc(size);
unsigned long size = acx.size;
if (Z_OK != uncompress(acx.data_raw, &size, buf+16, len-16)) {
if (Z_OK != uncompress(data_raw, &size, buf+16, compressed_size)) {
WARNING("ACXLoader.Load: uncompress failed");
free(buf);
free(data_raw);
return false;
}
acx.nr_columns = LittleEndian_getDW(acx.data_raw, 0);
acx.nr_lines = LittleEndian_getDW(acx.data_raw, 4 + acx.nr_columns * 4);
acx.data = acx.data_raw + (8 + acx.nr_columns * 4);
acx_read(data_raw);
free(buf);
free(data_raw);
return true;
}
void ACXLoader_Release(void)
{
free(acx.data_raw);
for (int col = 0; col < acx.nr_columns; col++) {
if (acx.column_types[col] != 2)
continue;
for (int line = 0; line < acx.nr_lines; line++) {
free_string(acx.lines[line*acx.nr_columns+col].s);
}
}
free(acx.lines);
free(acx.column_types);
memset(&acx, 0, sizeof(struct acx_file));
}
@@ -105,17 +145,21 @@ int ACXLoader_GetNumofColumn(void)
bool ACXLoader_GetDataInt(int line, int col, int *ptr)
{
if (line < 0 || line >= acx.nr_lines || col < 0 || col >= acx.nr_columns)
return false;
uint8_t *data = acx.data + (line * acx.nr_columns * 4) + (col * 4);
*ptr = LittleEndian_getDW(data, 0);
*ptr = acx.lines[line*acx.nr_columns + col].i;
return true;
}
HLL_UNIMPLEMENTED(bool, ACXLoader, GetDataString, int line, int col, struct string *data);
bool ACXLoader_GetDataString(int line, int col, struct string **ptr)
{
if (line < 0 || line >= acx.nr_lines || col < 0 || col >= acx.nr_columns)
return false;
*ptr = string_ref(acx.lines[line*acx.nr_columns + col].s);
return true;
}
bool ACXLoader_GetDataStruct(int line, struct page **page)
{
@@ -124,9 +168,12 @@ bool ACXLoader_GetDataStruct(int line, struct page **page)
if (line >= acx.nr_lines)
return false;
uint8_t *data = acx.data + (line * acx.nr_columns * 4);
for (int i = 0; i < acx.nr_columns; i++) {
s[i].i = LittleEndian_getDW(data, i*4);
if (acx.column_types[i] == 2) {
s[i].i = vm_string_ref(acx.lines[line*acx.nr_columns + i].s);
} else {
s[i].i = acx.lines[line*acx.nr_columns + i].i;
}
}
return true;
+11 -1
View File
@@ -14,6 +14,7 @@
* along with this program; if not, see <http://gnu.org/licenses/>.
*/
#include "system4/string.h"
#include "hll.h"
HLL_WARN_UNIMPLEMENTED( , void, Confirm2, Init, void *imainsystem);
@@ -21,8 +22,17 @@ HLL_WARN_UNIMPLEMENTED(1, int, Confirm2, ExistKeyFile, struct string *filename,
HLL_UNIMPLEMENTED(int, Confirm2, CheckProtectFile, struct string *filename, int keynum);
HLL_UNIMPLEMENTED(int, Confirm2, CreateKeyFile, struct string *filename, int keynum);
void Confirm2_ExistKeyFile2(possibly_unused struct string *pIFileName, possibly_unused int nKeyNum, struct string **pIResult)
{
// XXX: this is the magic value for Yokubori Saboten
// need to check if this works for other games
*pIResult = make_string("moke-", 5);
}
HLL_LIBRARY(Confirm2,
HLL_EXPORT(Init, Confirm2_Init),
HLL_EXPORT(ExistKeyFile, Confirm2_ExistKeyFile),
HLL_EXPORT(CheckProtectFile, Confirm2_CheckProtectFile),
HLL_EXPORT(CreateKeyFile, Confirm2_CreateKeyFile));
HLL_EXPORT(CreateKeyFile, Confirm2_CreateKeyFile),
HLL_EXPORT(ExistKeyFile2, Confirm2_ExistKeyFile2));