home *** CD-ROM | disk | FTP | other *** search
- /* ScummC
- * Copyright (C) 2006 Alban Bedel
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
- /**
- * @file scvm_res.c
- * @ingroup scvm
- * @brief SCVM ressources management
- */
-
- #include "config.h"
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <inttypes.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
-
- #include "scc_fd.h"
- #include "scc_util.h"
- #include "scc_cost.h"
- #include "scc_char.h"
- #include "scc_codec.h"
- #include "scc_box.h"
-
- #include "scvm_res.h"
- #include "scvm_thread.h"
- #include "scvm.h"
-
- scc_fd_t* scvm_open_file(scvm_t* vm,unsigned num) {
- if(num >= vm->num_file) {
- scc_log(LOG_ERR,"Invalid file number %d\n",num);
- return NULL;
- }
- if(!vm->file[num]) {
- int l = strlen(vm->path) + strlen(vm->basename) + 32;
- char name[l+1];
- sprintf(name,"%s/%s.%03d",vm->path,vm->basename,num);
- vm->file[num] = new_scc_fd(name,O_RDONLY,vm->file_key);
- if(!vm->file[num])
- scc_log(LOG_ERR,"Failed to open %s: %s\n",name,strerror(errno));
- }
- return vm->file[num];
- }
-
- void scvm_close_file(scvm_t* vm,unsigned num) {
- if(num >= vm->num_file) {
- scc_log(LOG_ERR,"Invalid file number %d\n",num);
- return;
- }
- if(vm->file[num]) {
- scc_fd_close(vm->file[num]);
- vm->file[num] = NULL;
- }
- }
-
-
- void scvm_res_init(scvm_res_type_t* res, char* name, unsigned num,
- scvm_res_load_f load, scvm_res_nuke_f nuke) {
- res->name = strdup(name);
- res->load = load;
- res->nuke = nuke;
- res->num = num;
- if(num > 0) res->idx = calloc(num,sizeof(scvm_res_t));
- }
-
- int scvm_res_load_index(scvm_t* vm, scvm_res_type_t* res,scc_fd_t* fd,
- uint32_t ref_type) {
- int i,num;
- uint32_t type, len;
-
- type = scc_fd_r32(fd);
- len = scc_fd_r32be(fd);
- if(type != ref_type || len < 8+2 ||
- (num = scc_fd_r16le(fd))*5+2+8 != len ||
- num != res->num) {
- scc_log(LOG_ERR,"Invalid index file, bad %c%c%c%c block.\n",UNMKID(ref_type));
- return 0;
- }
-
- for(i = 0 ; i < res->num ; i++) {
- res->idx[i].room = scc_fd_r8(fd);
- if(res->idx[i].room >= vm->res[SCVM_RES_ROOM].num) {
- scc_log(LOG_WARN,"Invalid room number in index: %d.\n",res->idx[i].room);
- res->idx[i].room = 0;
- continue;
- }
- res->idx[i].file = vm->res[SCVM_RES_ROOM].idx[res->idx[i].room].file;
- }
- for(i = 0 ; i < res->num ; i++)
- res->idx[i].offset = scc_fd_r32le(fd) +
- vm->res[SCVM_RES_ROOM].idx[res->idx[i].room].offset;
- return 1;
- }
-
- int scvm_lock_res(scvm_t* vm, unsigned type, unsigned num) {
- // check type and num
- if(type >= SCVM_RES_MAX) {
- scc_log(LOG_ERR,"Invalid resource type: %d\n",type);
- return 0;
- }
- if(num >= vm->res[type].num) {
- scc_log(LOG_ERR,"Invalid %s number: %d\n",vm->res[type].name,num);
- return 0;
- }
- vm->res[type].idx[num].flags |= SCVM_RES_LOCKED;
- return 1;
- }
-
- int scvm_unlock_res(scvm_t* vm, unsigned type, unsigned num) {
- // check type and num
- if(type >= SCVM_RES_MAX) {
- scc_log(LOG_ERR,"Invalid resource type: %d\n",type);
- return 0;
- }
- if(num >= vm->res[type].num) {
- scc_log(LOG_ERR,"Invalid %s number: %d\n",vm->res[type].name,num);
- return 0;
- }
- vm->res[type].idx[num].flags &= ~SCVM_RES_LOCKED;
- return 1;
- }
-
-
- void* scvm_load_res(scvm_t* vm, unsigned type, unsigned num) {
- // check type and num
- if(type >= SCVM_RES_MAX) {
- scc_log(LOG_ERR,"Invalid resource type: %d\n",type);
- return NULL;
- }
- if(num >= vm->res[type].num) {
- scc_log(LOG_ERR,"Invalid %s number: %d\n",vm->res[type].name,num);
- return NULL;
- }
- if(!vm->res[type].load && !vm->res[type].idx[num].data) {
- scc_log(LOG_ERR,"The %s loader is missing. Implement it!\n",
- vm->res[type].name);
- return NULL;
- }
- // load if needed
- if(!vm->res[type].idx[num].data) {
- scc_fd_t* fd = scvm_open_file(vm,vm->res[type].idx[num].file);
- unsigned offset = vm->res[type].idx[num].offset;
- if(!fd) return NULL;
- if(scc_fd_seek(fd,offset,SEEK_SET) != offset) {
- scc_log(LOG_ERR,"Failed to seek to %d in %s.\n",offset,fd->filename);
- scvm_close_file(vm,vm->res[type].idx[num].file);
- return NULL;
- }
- vm->res[type].idx[num].data = vm->res[type].load(vm,fd,num);
- if(!vm->res[type].idx[num].data)
- scc_log(LOG_ERR,"Failed to load %s %d\n",vm->res[type].name,num);
- }
- return vm->res[type].idx[num].data;
- }
-
- void* scvm_load_script(scvm_t* vm,scc_fd_t* fd, unsigned num) {
- uint32_t type,len;
- scvm_script_t* scrp;
-
- type = scc_fd_r32(fd);
- len = scc_fd_r32be(fd);
- if(type != MKID('S','C','R','P') || len < 8) {
- scc_log(LOG_ERR,"Bad script block %d: %c%c%c%c %d\n",num,
- UNMKID(type),len);
- return NULL;
- }
- scrp = malloc(sizeof(scvm_script_t)+len-8);
- scrp->id = num;
- scrp->size = len-8;
- if(scrp->size > 0) {
- int total = 0, r;
- while(total < scrp->size) {
- r = scc_fd_read(fd,scrp->code+total,scrp->size-total);
- if(r < 0) {
- scc_log(LOG_ERR,"Error loading script %d: %s\n",num,strerror(errno));
- free(scrp);
- return NULL;
- }
- total += r;
- }
- }
- return scrp;
- }
-
- int scvm_load_image(unsigned width, unsigned height, unsigned num_zplane,
- scvm_image_t* img,scc_fd_t* fd) {
- int i;
- uint32_t type = scc_fd_r32(fd);
- uint32_t size = scc_fd_r32be(fd);
- if(type != MKID('S','M','A','P') ||
- size < 8+(width/8)*4) return 0;
- else {
- uint8_t smap[size-8];
- if(scc_fd_read(fd,smap,size-8) != size-8)
- return 0;
- img->data = calloc(1,width*height);
- if(!(i = scc_decode_image(img->data,width,
- width,height,
- smap,size-8,-1)))
- return 0;
- img->have_trans = i-1;
- }
- if(!num_zplane) return 1;
- img->zplane = calloc(num_zplane+1,sizeof(uint8_t*));
- for(i = 1 ; i <= num_zplane ; i++) {
- char buf[8];
- sprintf(buf,"%02x",i);
- type = scc_fd_r32(fd);
- size = scc_fd_r32be(fd);
- if(type != MKID('Z','P',buf[0],buf[1]) ||
- size < 8+(width/8)*4) return 0;
- else {
- uint8_t zmap[size-8];
- uint8_t zbit[width/8*height];
- int j;
- if(scc_fd_read(fd,zmap,size-8) != size-8)
- return 0;
- if(!scc_decode_zbuf(zbit,width/8,
- width,height,
- zmap,size-8,0))
- return 0;
- img->zplane[i] = malloc(width*height);
- for(j = 0 ; j < width*height ; j++)
- img->zplane[i][j] = (zbit[j/8] & (1<<(7-(j%8))) ? 1 : 0);
- //img->zplane[i][j] = ((zbit[j>>3] << (j&7)) & 0x80) >> 7;
- }
- }
- return 1;
- }
-
- scvm_object_t* scvm_load_obim(scvm_t* vm, scvm_room_t* room, scc_fd_t* fd) {
- uint32_t type = scc_fd_r32(fd);
- uint32_t size = scc_fd_r32be(fd);
- scvm_object_t* obj;
- unsigned id;
- int i;
- if(type != MKID('I','M','H','D') ||
- size < 8+20) return NULL;
-
- id = scc_fd_r16le(fd);
- if(id >= vm->num_object) return NULL;
- if(vm->res[SCVM_RES_OBJECT].idx[id].data)
- obj = vm->res[SCVM_RES_OBJECT].idx[id].data;
- else {
- obj = calloc(1,sizeof(scvm_object_t));
- obj->id = id;
- obj->pdata = &vm->object_pdata[id];
- vm->res[SCVM_RES_OBJECT].idx[id].data = obj;
- }
- // already loaded
- if(obj->loaded & SCVM_OBJ_OBIM) return obj;
- obj->loaded |= SCVM_OBJ_OBIM;
-
- obj->num_image = scc_fd_r16le(fd);
- obj->num_zplane = scc_fd_r16le(fd);
- scc_fd_r16le(fd); // unknown
- obj->x = scc_fd_r16le(fd);
- obj->y = scc_fd_r16le(fd);
- obj->width = scc_fd_r16le(fd);
- obj->height = scc_fd_r16le(fd);
- obj->num_hotspot = scc_fd_r16le(fd);
- if(obj->num_hotspot > 0) {
- obj->hotspot = malloc(2*sizeof(int)*obj->num_hotspot);
- for(i = 0 ; i < obj->num_hotspot ; i++) {
- obj->hotspot[2*i] = scc_fd_r16le(fd);
- obj->hotspot[2*i+1] = scc_fd_r16le(fd);
- }
- }
-
- // load the images
- if(!obj->num_image) return obj;
-
- obj->image = calloc(sizeof(scvm_image_t),obj->num_image+1);
- for(i = 1 ; i <= obj->num_image ; i++) {
- type = scc_fd_r32le(fd);
- size = scc_fd_r32be(fd);
- if((type & 0xFFFF) != ('I'|'M'<<8) ||
- size < 8) return 0;
- if(!scvm_load_image(obj->width,obj->height,obj->num_zplane,
- &obj->image[i],fd)) return NULL;
- }
-
- return obj;
- }
-
- scvm_object_t* scvm_load_obcd(scvm_t* vm, scvm_room_t* room, scc_fd_t* fd) {
- uint32_t type = scc_fd_r32(fd);
- uint32_t size = scc_fd_r32be(fd);
- scvm_object_t* obj;
- unsigned id;
-
- if(type != MKID('C','D','H','D') ||
- size < 8+17) return NULL;
-
- id = scc_fd_r16le(fd);
- if(id >= vm->num_object) return NULL;
- if(vm->res[SCVM_RES_OBJECT].idx[id].data)
- obj = vm->res[SCVM_RES_OBJECT].idx[id].data;
- else {
- obj = calloc(1,sizeof(scvm_object_t));
- obj->id = id;
- obj->pdata = &vm->object_pdata[id];
- vm->res[SCVM_RES_OBJECT].idx[id].data = obj;
- }
- // already loaded
- if(obj->loaded & SCVM_OBJ_OBCD) return obj;
- obj->loaded |= SCVM_OBJ_OBCD;
-
- if(!(obj->loaded & SCVM_OBJ_OBIM)) {
- obj->x = scc_fd_r16le(fd);
- obj->y = scc_fd_r16le(fd);
- obj->width = scc_fd_r16le(fd);
- obj->height = scc_fd_r16le(fd);
- } else
- scc_fd_seek(fd,8,SEEK_CUR);
- obj->flags = scc_fd_r8(fd);
- // hack, the real pointer get resolved when all
- // object are loaded.
- obj->parent = (scvm_object_t*)((intptr_t)scc_fd_r8(fd));
- scc_fd_r32(fd); // unknown
- obj->actor_dir = scc_fd_r8(fd);
-
- type = scc_fd_r32(fd);
- size = scc_fd_r32be(fd);
-
- if(type == MKID('V','E','R','B')) {
- unsigned entries[0x200];
- unsigned num_entries = 0,verb;
- if(size < 8+1) return NULL;
- size -= 8;
- while(1) {
- verb = entries[2*num_entries] = scc_fd_r8(fd);
- size--;
- if(!verb) break;
- entries[2*num_entries+1] = scc_fd_r16le(fd);
- size -= 2;
- num_entries++;
- }
- if(num_entries) {
- obj->verb_entries = malloc(2*num_entries*sizeof(unsigned));
- obj->num_verb_entries = num_entries;
- memcpy(obj->verb_entries,entries,2*num_entries*sizeof(unsigned));
- }
- if(size > 0) {
- obj->script = malloc(sizeof(scvm_script_t)+size);
- if(scc_fd_read(fd,obj->script->code,size) != size)
- return 0;
- obj->script->id = obj->id | 0x10000;
- obj->script->size = size;
- }
-
- type = scc_fd_r32(fd);
- size = scc_fd_r32be(fd);
- }
-
- if(type == MKID('O','B','N','A') &&
- !obj->pdata->name) {
- if(size < 8+1) return 0;
- size -= 8;
- obj->pdata->name = malloc(size);
- if(scc_fd_read(fd,obj->pdata->name,size));
- // it should be 0 terminated but make sure it is
- obj->pdata->name[size-1] = 0;
- }
-
- return obj;
- }
-
- void* scvm_load_room(scvm_t* vm,scc_fd_t* fd, unsigned num) {
- uint32_t type,size,block_size,sub_block_size;
- unsigned len = 8,num_obim = 0, num_obcd = 0, num_lscr = 0;
- int i,j;
- scvm_room_t* room;
- off_t next_block;
- scvm_object_t *objlist[vm->num_local_object],*obj;
-
- memset(objlist,0,sizeof(scvm_object_t*)*vm->num_local_object);
-
- type = scc_fd_r32(fd);
- size = scc_fd_r32be(fd);
- if(type != MKID('R','O','O','M') || size < 16) {
- scc_log(LOG_ERR,"Bad ROOM block %d: %c%c%c%c %d\n",num,
- UNMKID(type),size);
- return NULL;
- }
- room = calloc(1,sizeof(scvm_room_t));
- room->id = num;
- while(len < size) {
- type = scc_fd_r32(fd);
- block_size = scc_fd_r32be(fd);
- next_block = scc_fd_pos(fd)-8+block_size;
- len += block_size;
- switch(type) {
- case MKID('R','M','H','D'):
- if(block_size != 6+8) goto bad_block;
- room->width = scc_fd_r16le(fd);
- room->height = scc_fd_r16le(fd);
- room->num_object = scc_fd_r16le(fd);
- break;
-
- case MKID('C','Y','C','L'):
- if(block_size < 1+8) goto bad_block;
- room->num_cycle = 17;
- room->cycle = calloc(room->num_cycle,sizeof(scvm_cycle_t));
- while(1) {
- unsigned freq,id = scc_fd_r8(fd);
- if(!id) break;
- if(id >= room->num_cycle) goto bad_block;
- room->cycle[id].id = id;
- scc_fd_r16(fd); // unknown
- freq = scc_fd_r16be(fd);
- room->cycle[id].delay = freq ? 0x4000/freq : 0;
- room->cycle[id].flags = scc_fd_r16be(fd);
- room->cycle[id].start = scc_fd_r8(fd);
- room->cycle[id].end = scc_fd_r8(fd);
- }
- break;
-
- case MKID('T','R','N','S'):
- if(block_size != 2+8) goto bad_block;
- room->trans = scc_fd_r16le(fd);
- break;
-
- case MKID('P','A','L','S'):
- if(block_size < 16) goto bad_block;
- type = scc_fd_r32(fd);
- sub_block_size = scc_fd_r32be(fd);
- if(type != MKID('W','R','A','P') ||
- sub_block_size != block_size-8) goto bad_block;
- type = scc_fd_r32(fd);
- sub_block_size = scc_fd_r32be(fd);
- if(type != MKID('O','F','F','S') || sub_block_size<8) goto bad_block;
- else {
- off_t base_ptr = scc_fd_pos(fd)-8;
- int npal = (sub_block_size-8)/4;
- off_t offset[npal];
- for(i = 0 ; i < npal ; i++)
- offset[i] = base_ptr + scc_fd_r32le(fd);
- room->num_palette = npal;
- room->palette = malloc(npal*sizeof(scvm_palette_t));
- for(i = 0 ; i < npal ; i++) {
- int c;
- scc_fd_seek(fd,offset[i],SEEK_SET);
- type = scc_fd_r32(fd);
- sub_block_size = scc_fd_r32be(fd);
- if(type != MKID('A','P','A','L') ||
- sub_block_size-8!= SCVM_PALETTE_SIZE*3) goto bad_block;
- for(c = 0 ; c < SCVM_PALETTE_SIZE ; c++) {
- room->palette[i][c].r = scc_fd_r8(fd);
- room->palette[i][c].g = scc_fd_r8(fd);
- room->palette[i][c].b = scc_fd_r8(fd);
- }
- }
- }
- break;
-
- case MKID('R','M','I','M'):
- if(block_size < 8+8+2+8+8+(room->width/8)*4) goto bad_block;
- type = scc_fd_r32(fd);
- sub_block_size = scc_fd_r32be(fd);
- if(type != MKID('R','M','I','H') ||
- sub_block_size != 8+2) goto bad_block;
- room->num_zplane = scc_fd_r16le(fd);
- type = scc_fd_r32(fd);
- sub_block_size = scc_fd_r32be(fd);
- if(type != MKID('I','M','0','0') ||
- sub_block_size < 8+8) goto bad_block;
- if(!scvm_load_image(room->width,room->height,room->num_zplane,
- &room->image,fd))
- goto bad_block;
- break;
-
- case MKID('O','B','I','M'):
- if(num_obim >= vm->num_local_object) {
- scc_log(LOG_ERR,"Too many objects in room.\n");
- goto bad_block;
- }
- if(block_size < 8+8+20 ||
- !(obj = scvm_load_obim(vm,room,fd))) goto bad_block;
- if(!objlist[num_obim])
- objlist[num_obim] = obj;
- else if(objlist[num_obim] != obj) {
- scc_log(LOG_ERR,"OBIM and OBCD are badly ordered.\n");
- goto bad_block;
- }
- num_obim++;
- break;
-
- case MKID('O','B','C','D'):
- if(num_obcd >= vm->num_local_object) {
- scc_log(LOG_ERR,"Too many objects in room.\n");
- goto bad_block;
- }
- if(block_size < 8+8+17 ||
- !(obj = scvm_load_obcd(vm,room,fd))) goto bad_block;
- if(!objlist[num_obcd])
- objlist[num_obcd] = obj;
- else if(objlist[num_obcd] != obj) {
- scc_log(LOG_ERR,"OBIM and OBCD are badly ordered.\n");
- goto bad_block;
- }
- num_obcd++;
- break;
-
- case MKID('E','X','C','D'):
- if(block_size <= 8) {
- scc_log(LOG_WARN,"Ignoring empty EXCD.\n");
- break;
- }
- block_size -= 8;
- room->exit = malloc(sizeof(scvm_script_t)+block_size);
- room->exit->id = 0x1ECD0000;
- room->exit->size = block_size;
- if(scc_fd_read(fd,room->exit->code,block_size) != block_size)
- goto bad_block;
- break;
-
- case MKID('E','N','C','D'):
- if(block_size <= 8) {
- scc_log(LOG_WARN,"Ignoring empty ENCD.\n");
- break;
- }
- block_size -= 8;
- room->entry = malloc(sizeof(scvm_script_t)+block_size);
- room->entry->id = 0x0ECD0000;
- room->entry->size = block_size;
- if(scc_fd_read(fd,room->entry->code,block_size) != block_size)
- goto bad_block;
- break;
-
- case MKID('N','L','S','C'):
- if(block_size != 8+2)
- goto bad_block;
- room->num_script = scc_fd_r16le(fd);
- if(room->num_script)
- room->script = calloc(room->num_script,sizeof(scvm_script_t*));
- break;
-
- case MKID('L','S','C','R'):
- if(num_lscr >= room->num_script) {
- scc_log(LOG_ERR,"Too many local scripts in room.\n");
- goto bad_block;
- }
- if(block_size <= 8+1) {
- scc_log(LOG_WARN,"Ignoring empty LSCR.\n");
- break;
- }
- block_size -= 8+1;
- i = scc_fd_r8(fd);
- if(i < 200 || i-200 >= room->num_script)
- goto bad_block;
- i -= 200;
- room->script[i] = malloc(sizeof(scvm_script_t)+block_size);
- room->script[i]->id = i+200;
- room->script[i]->size = block_size;
- if(scc_fd_read(fd,room->script[i]->code,block_size) != block_size)
- goto bad_block;
- num_lscr++;
- break;
-
- case MKID('B','O','X','D'):
- if(room->box) break;
- if(block_size < 8+2) goto bad_block;
- room->num_box = scc_fd_r16le(fd);
- if(!room->num_box) break;
- if(block_size != 8+2+(4*2*2+1+1+2)*room->num_box) goto bad_block;
- room->box = calloc(room->num_box,sizeof(scc_box_t));
- for(i = 0 ; i < room->num_box ; i++) {
- if(i+1 < room->num_box)
- room->box[i].next = &room->box[i+1];
- room->box[i].id = i;
- room->box[i].npts = 4;
- for(j = 0 ; j < 4 ; j++) {
- room->box[i].pts[j].x = scc_fd_r16le(fd);
- room->box[i].pts[j].y = scc_fd_r16le(fd);
- }
- room->box[i].mask = scc_fd_r8(fd);
- room->box[i].flags = scc_fd_r8(fd);
- room->box[i].scale = scc_fd_r16le(fd);
- }
- // Compute the matrix
- scc_box_get_matrix(room->box+1,&room->boxm);
- break;
-
- default:
- scc_log(LOG_WARN,"Unhandled room block: %c%c%c%c %d\n",
- UNMKID(type),block_size);
- }
- scc_fd_seek(fd,next_block,SEEK_SET);
- }
-
- if(num_lscr < room->num_script)
- scc_log(LOG_WARN,"Room %d is missing some local scripts?\n",num);
-
- // Resolve the object parent
- for(i=0 ; i < num_obim ; i++) {
- uint8_t num = (uint8_t)((uintptr_t)objlist[i]->parent);
- if(!num) continue;
- if(num > num_obim) {
- scc_log(LOG_WARN,"Object %d has an invalid parent.\n",obj->id);
- continue;
- }
- objlist[i]->parent = objlist[num-1];
- }
- if(num_obcd > num_obim) num_obim = num_obcd;
- room->num_object = num_obim;
- room->object = malloc(num_obim*sizeof(scvm_object_t*));
- for(i=0 ; i < num_obim ; i++)
- room->object[i] = objlist[i];
-
- return room;
-
- bad_block:
- scc_log(LOG_ERR,"Bad ROOM subblock %d: %c%c%c%c %d\n",num,
- UNMKID(type),block_size);
- free(room);
- return NULL;
- }
-
- void* scvm_load_costume(scvm_t* vm,scc_fd_t* fd, unsigned num) {
- uint32_t size,fmt;
- scc_cost_t* cost;
- fmt = scc_fd_r32(fd);
- size = scc_fd_r32be(fd);
-
- if(fmt != MKID('C','O','S','T') || size < 8+32 ) { // put the right size here
- scc_log(LOG_ERR,"Bad COST block %d: %c%c%c%c %d\n",num,
- UNMKID(fmt),size);
- return NULL;
- }
- cost = scc_parse_cost(fd,size-8);
- if(cost) cost->id = num;
- return cost;
- }
-
-
- void* scvm_load_charset(scvm_t* vm,scc_fd_t* fd, unsigned num) {
- uint32_t size,fmt;
- scc_charmap_t* ch;
- // read the scumm block header
- fmt = scc_fd_r32(fd);
- size = scc_fd_r32be(fd);
-
- if(fmt != MKID('C','H','A','R') || size < 8+25 ) {
- scc_log(LOG_ERR,"Bad CHAR block %d: %c%c%c%c %d\n",num,
- UNMKID(fmt),size);
- return NULL;
- }
- ch = scc_parse_charmap(fd,size-8);
- if(ch) ch->id = num;
- return ch;
- }
-