int load_module_info (struct prx *p) { struct prx_modinfo *info; uint32 offset; p->modinfo = NULL; if (p->phnum > 0) offset = p->programs[0].paddr & 0x7FFFFFFF; else { error (__FILE__ ": can't find module info for PRX"); return 0; } info = (struct prx_modinfo *) xmalloc (sizeof (struct prx_modinfo)); p->modinfo = info; info->attributes = read_uint16_le (&p->data[offset]); info->version = read_uint16_le (&p->data[offset+2]); info->name = (const char *) &p->data[offset+4]; info->gp = read_uint32_le (&p->data[offset+32]); info->expvaddr = read_uint32_le (&p->data[offset+36]); info->expvaddrbtm = read_uint32_le (&p->data[offset+40]); info->impvaddr = read_uint32_le (&p->data[offset+44]); info->impvaddrbtm = read_uint32_le (&p->data[offset+48]); info->imports = NULL; info->exports = NULL; if (!check_module_info (p)) return 0; if (!load_module_imports (p)) return 0; if (!load_module_exports (p)) return 0; return 1; }
static void parse_stat(const char *p, const char *end, ml_art **art) { int header = read_sint32_le(&p, end); int width = read_sint16_le(&p, end); int height = read_sint16_le(&p, end); const char *line_start_offsets[512]; const char *start = p + height * 2; //printf("%d %d\n", width, height); assert(height <= sizeof(line_start_offsets)/sizeof(line_start_offsets[0])); for (int i = 0; i < height; i++) { line_start_offsets[i] = start + 2 * read_uint16_le(&p, end); } int art_size = sizeof(ml_art) + 2 * width * height; *art = (ml_art *)malloc(art_size); (*art)->width = width; (*art)->height = height; uint16_t *target_data = (*art)->data; memset(target_data, 0, 2 * width * height); for (int i = 0; i < height; i++) { uint16_t *w = target_data + i * width; p = line_start_offsets[i]; while (true) { int skip = read_sint16_le(&p, end); int length = read_sint16_le(&p, end); if (skip == 0 && length == 0) { break; } w += skip; for (int j = 0; j < length; j++) { *w = read_uint16_le(&p, end); // set alpha... if (*w) { *w |= 0x8000; } w += 1; } } } }
static void parse_cliloc(const char *p, const char *end) { int a = read_uint32_le(&p, end); int b = read_uint16_le(&p, end); const char *start = p; // first go through it one pass to count the number of strings and total string size int string_count = 0; int total_string_size = 0; while(p < end) { read_uint32_le(&p, end); read_uint8(&p, end); int length = read_uint16_le(&p, end); p += length; if (length > 0) { string_count += 1; total_string_size += length + 1; // include null terminator } } // rewind p = start; cliloc_entry_count = string_count; cliloc_entries = (ml_cliloc_entry *)malloc(sizeof(ml_cliloc_entry) * string_count); int next_index = 0; while(p < end) { int id = read_sint32_le(&p, end); read_uint8(&p, end); int length = read_uint16_le(&p, end); if (length > 0) { ml_cliloc_entry *entry = &cliloc_entries[next_index]; entry->id = id; char *s = (char *)malloc(length+1); s[length-1] = '\0'; read_ascii_fixed(&p, end, s, length); entry->s = s; next_index += 1; } } for (int i = 0; i < string_count; i++) { ml_cliloc_entry *entry = &cliloc_entries[i]; //printf("%d, %d: %s\n", i, entry->id, entry->s); } }
static void parse_tiledata(const char *p, const char *end) { int remaining_bytes = (int)(end - p); int block_count = (remaining_bytes-512*32*(8+2+20)) / (4 + 32*(8+1+1+4+2+2+2+1+20)); item_data_entry_count = 32*block_count; tile_datas = (ml_tile_data_entry *)malloc(512*32*sizeof(ml_tile_data_entry)); item_datas = (ml_item_data_entry *)malloc(item_data_entry_count * sizeof(ml_item_data_entry)); // 512*4 + 512*32*(8+2+20) bytes // first, 512 land data for (int i = 0; i < 512*32; i++) { // every 32 entries have a header of unknown use if (i % 32 == 0) { read_uint32_le(&p, end); } ml_tile_data_entry *tile_data = &tile_datas[i]; tile_data->flags = read_uint64_le(&p, end); tile_data->texture = read_uint16_le(&p, end); // hmm can this be used instead of the rotation of land gfx? read_ascii_fixed(&p, end, tile_data->name, 20); //printf("%d: %08llx %d %s\n", i, (unsigned long long)flags, texture, name); } int i = 0; while (p < end) { // every 32 entries have a header of unknown use if (i % 32 == 0) { read_uint32_le(&p, end); } ml_item_data_entry *item_data = &item_datas[i]; item_data->flags = read_uint64_le(&p, end); item_data->weight = read_uint8(&p, end); item_data->quality = read_uint8(&p, end); item_data->quantity = read_uint32_le(&p, end); item_data->animation = read_uint16_le(&p, end); read_uint16_le(&p, end); read_uint16_le(&p, end); item_data->height = read_uint8(&p, end); read_ascii_fixed(&p, end, item_data->name, 20); //printf("%d: %08llx %d %s\n", i, (unsigned long long)flags, animation, name); i += 1; } }
static int load_module_exports (struct prx *p) { uint32 i = 0, offset; struct prx_modinfo *info = p->modinfo; if (!info->expvaddr) return 1; info->exports = (struct prx_export *) xmalloc (info->numexports * sizeof (struct prx_export)); memset (info->exports, 0, info->numexports * sizeof (struct prx_export)); offset = prx_translate (p, info->expvaddr); for (i = 0; i < info->numexports; i++) { struct prx_export *exp = &info->exports[i]; exp->namevaddr = read_uint32_le (&p->data[offset]); exp->flags = read_uint32_le (&p->data[offset+4]); exp->size = p->data[offset+8]; exp->nvars = p->data[offset+9]; exp->nfuncs = read_uint16_le (&p->data[offset+10]); exp->expvaddr = read_uint32_le (&p->data[offset+12]); if (!check_module_export (p, i)) return 0; if (exp->namevaddr) exp->name = (const char *) &p->data[prx_translate (p, exp->namevaddr)]; else exp->name = "syslib"; if (!load_module_export (p, exp)) return 0; offset += exp->size << 2; } return 1; }
static int load_module_imports (struct prx *p) { uint32 i = 0, offset; struct prx_modinfo *info = p->modinfo; if (!info->impvaddr) return 1; info->imports = (struct prx_import *) xmalloc (info->numimports * sizeof (struct prx_import)); memset (info->imports, 0, info->numimports * sizeof (struct prx_import)); offset = prx_translate (p, info->impvaddr); for (i = 0; i < info->numimports; i++) { struct prx_import *imp = &info->imports[i]; imp->namevaddr = read_uint32_le (&p->data[offset]); imp->flags = read_uint32_le (&p->data[offset+4]); imp->size = p->data[offset+8]; imp->nvars = p->data[offset+9]; imp->nfuncs = read_uint16_le (&p->data[offset+10]); imp->nidsvaddr = read_uint32_le (&p->data[offset+12]); imp->funcsvaddr = read_uint32_le (&p->data[offset+16]); if (imp->nvars) imp->varsvaddr = read_uint32_le (&p->data[offset+20]); if (!check_module_import (p, i)) return 0; if (imp->namevaddr) imp->name = (const char *) &p->data[prx_translate (p, imp->namevaddr)]; else imp->name = NULL; if (!load_module_import (p, imp)) return 0; offset += imp->size << 2; } return 1; }
static void parse_gump(const char *p, const char *end, int width, int height, ml_gump **g) { int line_start_offsets[512]; assert(height < sizeof(line_start_offsets)/sizeof(line_start_offsets[0])); const char *start = p; for (int i = 0; i < height; i++) { line_start_offsets[i] = read_uint32_le(&p, end); //printf("%d %d\n", i, line_start_offsets[i]); } int gump_size = sizeof(ml_gump) + 2 * width * height; *g = (ml_gump *)malloc(gump_size); (*g)->width = width; (*g)->height = height; uint16_t *target_data = (*g)->data; memset(target_data, 0, 2 * width * height); for (int i = 0; i < height; i++) { uint16_t *w = target_data + i * width; p = start + line_start_offsets[i] * 4; int accum_length = 0; while (accum_length < width) { uint16_t color = read_uint16_le(&p, end); int length = read_uint16_le(&p, end); for (int j = 0; j < length; j++) { *w = color; // set alpha... if (*w) { *w |= 0x8000; } w += 1; } accum_length += length; } } }
static void parse_hues(const char *p, const char *end) { hues = (ml_hue *)malloc(sizeof(ml_hue)*8*375); for (int i = 0; i < 8*375; i++) { // every eighth hue is prepended by an unknown header if (i % 8 == 0) { read_uint32_le(&p, end); } ml_hue *hue = &hues[i]; for (int j = 0; j < 32; j++) { hue->colors[j] = read_uint16_le(&p, end); } hue->start_color = read_uint16_le(&p, end); hue->end_color = read_uint16_le(&p, end); read_ascii_fixed(&p, end, hue->name, 20); //printf("%d: %s %04x %04x\n", i, name, start_color, end_color); } }
static void parse_land_block(const char *p, const char *end, ml_land_block **mb) { int header = read_sint32_le(&p, end); *mb = (ml_land_block *)malloc(sizeof(ml_land_block)); for (int i = 0; i < 8*8; i++) { int tile_id = read_uint16_le(&p, end); int z = read_sint8(&p, end); (*mb)->tiles[i].tile_id = tile_id; (*mb)->tiles[i].z = z; } }
static void parse_multi(const char *p, const char *end, ml_multi **m) { int num_bytes = (int)(end - p); int item_count = num_bytes / 16; int multi_size = sizeof(ml_multi) + item_count * sizeof((*m)->items[0]); *m = (ml_multi *)malloc(multi_size); (*m)->item_count = item_count; for (int i = 0; i < item_count; i++) { (*m)->items[i].item_id = read_uint16_le(&p, end); (*m)->items[i].x = read_sint16_le(&p, end); (*m)->items[i].y = read_sint16_le(&p, end); (*m)->items[i].z = read_sint16_le(&p, end); (*m)->items[i].visible = read_uint32_le(&p, end); read_uint32_le(&p, end); } }
static void parse_statics_block(const char *p, const char *end, ml_statics_block **sb) { long size = end - p; int statics_count = size / 7; int statics_block_size = sizeof(ml_statics_block) + statics_count * sizeof((*sb)->statics[0]); *sb = (ml_statics_block *)malloc(statics_block_size); (*sb)->statics_count = statics_count; for (int i = 0; i < 8*8; i++) { (*sb)->roof_heights[i] = -1; } //printf("statics_count. %d\n", statics_count); for (int i = 0; i < statics_count; i++) { int tile_id = read_sint16_le(&p, end); int dx = read_uint8(&p, end); int dy = read_uint8(&p, end); int z = read_sint8(&p, end); read_uint16_le(&p, end); // unknown (*sb)->statics[i].tile_id = tile_id; (*sb)->statics[i].dx = dx; (*sb)->statics[i].dy = dy; (*sb)->statics[i].z = z; ml_item_data_entry *item_data = ml_get_item_data(tile_id); if (item_data->flags & 0x10000000) { // is roof! if ((*sb)->roof_heights[dx+dy*8] == -1 || z > (*sb)->roof_heights[dx+dy*8]) // higher than existing roof? { (*sb)->roof_heights[dx+dy*8] = z; } } //printf("%d %d %d %d\n", tile_id, dx, dy, z); } }
static void parse_anim(const char *p, const char *end, ml_anim **animation) { //printf("parsing... offset: %d, length: %d\n", offset, length); //p += offset; uint16_t palette[0x100]; int frame_count; int frame_start_offsets[64]; int total_frames_size; for (int i = 0; i < 0x100; i++) { palette[i] = read_uint16_le(&p, end); // set alpha if (palette[i]) { palette[i] |= 0x8000; } //printf("palette %d %d\n", i, palette[i]); } const char *payload_start = p; frame_count = read_sint32_le(&p, end); assert(frame_count <= sizeof(frame_start_offsets)/sizeof(frame_start_offsets[0])); for (int i = 0; i < frame_count; i++) { frame_start_offsets[i] = read_sint32_le(&p, end); //printf("offset %d %d\n", i, frame_start_offsets[i]); } total_frames_size = 0; for (int i = 0; i < frame_count; i++) { if (frame_start_offsets[i] != 0) { p = payload_start + frame_start_offsets[i] + 4; int width = read_sint16_le(&p, end); int height = read_sint16_le(&p, end); total_frames_size += 2 * width * height; } } //printf("frames size: %d\n", total_frames_size); int anim_meta_data_size = sizeof(ml_anim) + frame_count * sizeof((*animation)->frames[0]); int anim_size = anim_meta_data_size + total_frames_size; //printf("this animation is %d bytes\n", anim_size); *animation = (ml_anim *)malloc(anim_size); ml_anim *anim = *animation; anim->frame_count = frame_count; char *frame_data_start = ((char *)anim) + anim_meta_data_size; int offset_accum = 0; for (int i = 0; i < frame_count; i++) { //printf("frame %d of %d\n", i, frame_count); p = payload_start + frame_start_offsets[i]; int center_x = 0; int center_y = 0; int width = 0; int height = 0; if (frame_start_offsets[i] != 0) { center_x = read_sint16_le(&p, end); center_y = read_sint16_le(&p, end); width = read_sint16_le(&p, end); height = read_sint16_le(&p, end); } anim->frames[i].center_x = center_x; anim->frames[i].center_y = center_y; anim->frames[i].width = width; anim->frames[i].height = height; anim->frames[i].data = (uint16_t *)(frame_data_start + offset_accum); offset_accum += 2 * width * height; uint16_t *target_data = anim->frames[i].data; memset(target_data, 0, 2 * width * height); //printf("%d %d %d %d\n", center_x, center_y, width, height); if (frame_start_offsets[i] != 0) { while (true) { uint32_t header = read_uint32_le(&p, end); //printf("header %08x\n", header); if (header == 0x7FFF7FFFul) { // finished... break; } int offset_x = ((header >> 22) ^ 0x200) - 0x200; int offset_y = (((header >> 12) & 0x3ff) ^ 0x200) - 0x200; int run = header & 0xfff; int start_x = center_x + offset_x; int start_y = center_y + height + offset_y; uint16_t *w = (uint16_t *)&target_data[start_x + start_y * width]; uint16_t *wend = w + width * height; //printf("%d %d\n", width, height); //printf("%d %d %d\n", start_x, start_y, run); for (int j = 0; j < run; j++) { assert(w < wend); *w = palette[read_uint8(&p, end)]; w += 1; } //printf("%d %d %d\n", start_x, start_y, run); } } } // when we are done we should have written every byte we allocated assert(anim_meta_data_size + offset_accum == anim_size); //printf("read %d\n", (int)((p - payload_start) + 0x200)); }