void sys_string_acquire(sys_strings_t *strings, int index, const char *name, int max_len) { sys_string_t *str = strings->strings + index; if (index < 0 || index >= SYS_STRINGS_MAX) { fprintf(stderr, "[SYSSTR] Error: Attempt to acquire string #%d\n", index); BREAKPOINT(); } if (str->name && (strcmp(name, str->name) || (str->max_size != max_len))) { fprintf(stderr, "[SYSSTR] Error: Attempt to re-acquire existing string #%d;" "was '%s', tried to claim as '%s'\n", index, str->name, name); BREAKPOINT(); } str->name = strdup(name); str->max_size = max_len; str->value = (char*)sci_malloc(max_len + 1); str->value[0] = 0; /* Set to empty string */ }
static sci_module_t * _sci_try_open_module(char *filename, char *path, char *struct_name, void **handle) { char *fullname = sci_malloc(strlen(path) + strlen(DIR_SEPARATOR_STR) + strlen(filename)); sci_module_t *module; fprintf(stderr,"Trying module %s at %s\n", filename, path); strcpy(fullname, path); strcat(fullname, DIR_SEPARATOR_STR); strcat(fullname, filename); fprintf(stderr,"Total name is %s\n", fullname); *handle = dlopen(fullname, RTLD_NOW); fprintf(stderr,"Could not open because: %s\n", dlerror()); free(fullname); if (!*handle) return NULL; module = (sci_module_t *) dlsym(*handle, struct_name); if (!module) fprintf(stderr,"%s: Failed to find symbol '%s'.\n", fullname, struct_name); return module; }
static exe_handle_t * lzexe_open(const char *filename) { exe_handle_t *handle; guint8 head[0x20]; guint8 size[2]; off_t fpos; FILE *f = sci_fopen(filename, "rb"); if (!f) return NULL; /* Read exe header plus possible lzexe signature. */ if (fread(head, 1, 0x20, f) != 0x20) return NULL; /* Verify "MZ" signature, header size == 2 paragraphs and number of ** overlays == 0. */ if (UINT16(head) != 0x5a4d || UINT16(head + 8) != 2 || UINT16(head + 0x1a) != 0) return NULL; /* Verify that first relocation item offset is 0x1c. */ if (UINT16(head + 0x18) != 0x1c) return NULL; /* Look for lzexe signature. */ if (memcmp(head + 0x1c, "LZ09", 4) && memcmp(head + 0x1c, "LZ91", 4)) { return NULL; } /* Calculate code segment offset in exe file. */ fpos = (UINT16(head + 0x16) + UINT16(head + 8)) << 4; /* Seek to offset 8 of info table at start of code segment. */ if (fseek(f, fpos + 8, SEEK_SET) == -1) return NULL; /* Read size of compressed data in paragraphs. */ if (fread(size, 1, 2, f) != 2) return NULL; /* Move file pointer to start of compressed data. */ fpos -= UINT16(size) << 4; if (fseek(f, fpos, SEEK_SET) == -1) return NULL; handle = (exe_handle_t*)sci_malloc(sizeof(exe_handle_t)); if (!lzexe_init(handle, f)) { sci_free(handle); return NULL; } return handle; }
static int mix_init(sfx_pcm_mixer_t *self, sfx_pcm_device_t *device) { self->dev = device; self->private_bits /* = P */ = sci_malloc(sizeof(struct mixer_private)); P->outbuf = P->writebuf = NULL; P->lastbuf_len = 0; P->compbuf_l = (gint32*)sci_malloc(sizeof(gint32) * device->buf_size); P->compbuf_r = (gint32*)sci_malloc(sizeof(gint32) * device->buf_size); P->played_this_second = 0; P->paused = 0; #ifdef DEBUG sciprintf("[soft-mixer] Initialised device %s v%s (%d Hz, %d/%x)\n", device->name, device->version, device->conf.rate, device->conf.stereo, device->conf.format); #endif return SFX_OK; }
void _scir_add_altsource(resource_t *res, int file, unsigned int file_offset) { resource_source_t *rsrc = (resource_source_t*)sci_malloc(sizeof(resource_source_t)); rsrc->next = res->alt_sources; rsrc->file = file; rsrc->file_offset = file_offset; res->alt_sources = rsrc; }
int main(int argc, char **argv) { int fd1, fd2; unsigned char *patch001; unsigned char *patch004; unsigned int length001, length004; if (argc < 2) return -1; if ((fd1 = open(argv[1], O_RDONLY)) < 0) return -1; if ((fd2 = open(argv[2], O_RDONLY)) < 0) { close(fd1); return -1; } patch001 = (unsigned char *)sci_malloc(65536); length001 = read(fd1, patch001, 65536); close(fd1); patch004 = (unsigned char *)sci_malloc(65536); length004 = read(fd2, patch004, 65536); close(fd2); if (patch001[0] == 0x89 && patch001[1] == 0x00) if (patch004[0] == 0x89 && patch004[1] == 0x00) analyze(patch001 + 2, length001 - 2, patch004 + 2, length004 - 2); else analyze(patch001 + 2, length001 - 2, patch004, length004); else if (patch004[0] == 0x89 && patch004[1] == 0x00) analyze(patch001, length001, patch004 + 2, length004 - 2); else analyze(patch001, length001, patch004, length004); free(patch001); free(patch004); return 0; }
static object* object_new() { object* obj = (object*)sci_malloc(sizeof(object)); if (obj == 0) return 0; obj->parent = 0; FLEXARRAY_INIT(object*, obj->children); obj->name = 0; obj->selector_count = 0; obj->selector_numbers = 0; obj->methods = 0; obj->method_count = 0; return obj; }
static void _scir_load_from_patch_file(int fh, resource_t *res, char *filename) { int really_read; res->data = (unsigned char*)sci_malloc(res->size); really_read = read(fh, res->data, res->size); if (really_read < res->size) { sciprintf("Error: Read %d bytes from %s but expected %d!\n", really_read, filename, res->size); exit(1); } res->status = SCI_STATUS_ALLOCATED; }
void sys_strings_restore(sys_strings_t *new_strings, sys_strings_t *old_strings) { int i; /* First, pad memory */ for (i = 0; i < SYS_STRINGS_MAX; i++) { sys_string_t *s = new_strings->strings + i; char *data = s->value; if (data) { s->value = (char *)sci_malloc(s->max_size + 1); strcpy(s->value, data); sci_free(data); } } sys_string_set(new_strings, SYS_STRING_SAVEDIR, old_strings->strings[SYS_STRING_SAVEDIR].value); }
static void antialiase_simple(gfx_pixmap_t *pixmap, int mask[], int shift_const, gfx_mode_t *mode) { int x, y, c; int bytespp = mode->bytespp; int line_size = bytespp * pixmap->xl; char *lastline[2]; char *lastline_p = NULL; char *data_p = (char *) pixmap->data; lastline[0] = (char*)sci_malloc(line_size); lastline[1] = (char*)sci_malloc(line_size); for (y = 0; y < pixmap->yl; y++) { int visimode = (y > 0 && y+1 < pixmap->yl)? 1 : 0; unsigned long last_pixel; memcpy(lastline[y & 1], data_p, line_size); lastline_p = lastline[(y & 1)^1]; for (x = 0; x < pixmap->xl; x++) { unsigned long result = 0; if (x == 1) visimode++; else if (x+1 == pixmap->xl) visimode--; for (c = 0; c < 3; c++) { unsigned long accum = 0; unsigned long reader = 0; int y_mode; /* Yes, bad compilers will read three times as often as neccessary. ** This optimization is straightforward to detect (common subexpression ** elemination), so I prefer to write the stuff semi-legibly... */ for (y_mode = 0; y_mode < 2; y_mode++) if ((y_mode == 0 && y > 0) || (y_mode == 1 && y+1 < pixmap->yl)) { char *src = (y_mode)? data_p + line_size : lastline_p; if (x > 0) { memcpy(&reader, src - bytespp, bytespp); accum += ((reader >> shift_const) & mask[c]) << 0; } memcpy(&reader, src, bytespp); accum += ((reader >> shift_const) & mask[c]) << 1; if (x+1 < pixmap->xl) { memcpy(&reader, src + bytespp, bytespp); accum += ((reader >> shift_const) & mask[c]) << 0; } } if (x > 0) accum += ((last_pixel >> shift_const) & mask[c]) << 1; memcpy(&reader, data_p, bytespp); if (c == 2) last_pixel = reader; accum += ((reader >> shift_const) & mask[c]) << 2; if (x+1 < pixmap->xl) { memcpy(&reader, data_p + bytespp, bytespp); accum += ((reader >> shift_const) & mask[c]) << 1; }
void * sci_find_module(char *path, char *name, char *type, char *struct_prefix, char *file_suffix, int magic, int version, void **handle) { char *module_name = sci_malloc(strlen(type) + strlen(DIR_SEPARATOR_STR) + strlen(name) + strlen(file_suffix) + strlen(MODULE_NAME_SUFFIX) + 1); char *struct_name = sci_malloc(strlen(struct_prefix) + strlen(name) + 1); char *dir_end; char *path_pos = path; char path_separator = PATH_SEPARATOR_STR[0]; sci_module_t *module = NULL; strcpy(module_name, type); strcat(module_name, DIR_SEPARATOR_STR); strcat(module_name, name); strcat(module_name, file_suffix); strcat(module_name, MODULE_NAME_SUFFIX); strcpy(struct_name, struct_prefix); strcat(struct_name, name); do { dir_end = strchr(path_pos, path_separator); if (dir_end) *dir_end = 0; module = _sci_try_open_module(module_name, path_pos, struct_name, handle); if (module) { if (module->class_magic != magic) { fprintf(stderr, "%s at %s is not a %s module, skipping...\n", module_name, path_pos, type); dlclose(*handle); module = NULL; } else if (module->class_version != version) { fprintf(stderr, "%s at %s has %s module version %d," " expected %d- skipping...\n", module_name, path_pos, type, module->class_version, version); dlclose(*handle); module = NULL; } } if (dir_end) { *dir_end = path_separator; path_pos = dir_end + 1; } } while (!module && dir_end); if (!module) { *handle = NULL; fprintf(stderr,"%s module '%s' not found in path '%s'.\n", type, name, path); } else { if (dir_end) *dir_end = 0; printf("Using %s driver '%s', version %s, from '%s'.\n", type, module->module_name, module->module_version, path_pos); if (dir_end) *dir_end = path_separator; } free(module_name); free(struct_name); return (void *) module; }
resource_mgr_t * scir_new_resource_manager(char *dir, int version, char allow_patches, int max_memory) { int resource_error = 0; resource_mgr_t *mgr = (resource_mgr_t*)sci_malloc(sizeof(resource_mgr_t)); char *caller_cwd = sci_getcwd(); int resmap_version = version; if (chdir(dir)) { sciprintf("Resmgr: Directory '%s' is invalid!\n", dir); free(caller_cwd); return NULL; } mgr->max_memory = max_memory; mgr->memory_locked = 0; mgr->memory_lru = 0; mgr->resource_path = dir; mgr->resources = NULL; if (version <= SCI_VERSION_01_VGA_ODD /* || version == SCI_VERSION_AUTODETECT -- subsumed by the above line */) { resource_error = sci0_read_resource_map(dir, &mgr->resources, &mgr->resources_nr, &resmap_version); if (resource_error >= SCI_ERROR_CRITICAL) { sciprintf("Resmgr: Error while loading resource map: %s\n", sci_error_types[resource_error]); if (resource_error == SCI_ERROR_RESMAP_NOT_FOUND) sciprintf("Running SCI games without a resource map is not supported ATM\n"); sci_free(mgr); chdir(caller_cwd); free(caller_cwd); return NULL; } if (resource_error == SCI_ERROR_RESMAP_NOT_FOUND) { /* fixme: Try reading w/o resource.map */ resource_error = SCI_ERROR_NO_RESOURCE_FILES_FOUND; } if (resource_error == SCI_ERROR_NO_RESOURCE_FILES_FOUND) { /* Initialize empty resource manager */ _scir_init_trivial(mgr); resource_error = 0; } } if ((version == SCI_VERSION_1_EARLY)|| (version == SCI_VERSION_1_LATE)|| (version == SCI_VERSION_1_1)|| ((resmap_version == SCI_VERSION_AUTODETECT)&&(version == SCI_VERSION_AUTODETECT))) { resource_error = sci1_read_resource_map(dir, &mgr->resources, &mgr->resources_nr, &resmap_version); if (resource_error >= SCI_ERROR_CRITICAL) { sciprintf("Resmgr: Error while loading resource map: %s\n", sci_error_types[resource_error]); if (resource_error == SCI_ERROR_RESMAP_NOT_FOUND) sciprintf("Running SCI games without a resource map is not supported ATM\n"); sci_free(mgr); chdir(caller_cwd); free(caller_cwd); return NULL; } if (resource_error == SCI_ERROR_RESMAP_NOT_FOUND) { /* fixme: Try reading w/o resource.map */ resource_error = SCI_ERROR_NO_RESOURCE_FILES_FOUND; } if (resource_error == SCI_ERROR_NO_RESOURCE_FILES_FOUND) { /* Initialize empty resource manager */ _scir_init_trivial(mgr); resource_error = 0; } resmap_version = SCI_VERSION_1; } if (!mgr->resources || !mgr->resources_nr) { if (mgr->resources) { free(mgr->resources); mgr->resources = NULL; } sciprintf("Resmgr: Could not retreive a resource list!\n"); sci_free(mgr); chdir(caller_cwd); free(caller_cwd); return NULL; } mgr->lru_first = NULL; mgr->lru_last = NULL; mgr->allow_patches = allow_patches; qsort(mgr->resources, mgr->resources_nr, sizeof(resource_t), resourcecmp); /* Sort resources */ if (version == SCI_VERSION_AUTODETECT) switch (resmap_version) { case SCI_VERSION_0: if (scir_test_resource(mgr, sci_vocab, VOCAB_RESOURCE_SCI0_MAIN_VOCAB)) { version = sci_test_view_type(mgr); if (version == SCI_VERSION_01_VGA) { sciprintf("Resmgr: Detected KQ5 or similar\n"); } else { sciprintf("Resmgr: Detected SCI0\n"); version = SCI_VERSION_0; } } else if (scir_test_resource(mgr, sci_vocab, VOCAB_RESOURCE_SCI1_MAIN_VOCAB)) { version = sci_test_view_type(mgr); if (version == SCI_VERSION_01_VGA) { sciprintf("Resmgr: Detected KQ5 or similar\n"); } else { if (scir_test_resource(mgr, sci_vocab, 912)) { sciprintf("Resmgr: Running KQ1 or similar, using SCI0 resource encoding\n"); version = SCI_VERSION_0; } else { version = SCI_VERSION_01; sciprintf("Resmgr: Detected SCI01\n"); } } } else { version = sci_test_view_type(mgr); if (version == SCI_VERSION_01_VGA) { sciprintf("Resmgr: Detected KQ5 or similar\n"); } else { sciprintf("Resmgr: Warning: Could not find vocabulary; assuming SCI0 w/o parser\n"); version = SCI_VERSION_0; } } break; case SCI_VERSION_01_VGA_ODD: version = resmap_version; sciprintf("Resmgr: Detected Jones/CD or similar\n"); break; case SCI_VERSION_1: { resource_t *res = scir_test_resource(mgr, sci_script, 0); mgr->sci_version = version = SCI_VERSION_1_EARLY; _scir_load_resource(mgr, res, 1); if (res->status == SCI_STATUS_NOMALLOC) mgr->sci_version = version = SCI_VERSION_1_LATE; /* No need to handle SCI 1.1 here - it was done in resource_map.c */ break; } default: sciprintf("Resmgr: Warning: While autodetecting: Couldn't" " determine SCI version!\n"); } if (!resource_error) { if (version <= SCI_VERSION_01) sci0_read_resource_patches(dir, &mgr->resources, &mgr->resources_nr); else sci1_read_resource_patches(dir, &mgr->resources, &mgr->resources_nr); qsort(mgr->resources, mgr->resources_nr, sizeof(resource_t), resourcecmp); /* Sort resources */ } mgr->sci_version = version; chdir(caller_cwd); free(caller_cwd); return mgr; }
static void _scir_init_trivial(resource_mgr_t *mgr) { mgr->resources_nr = 0; mgr->resources = (resource_t*)sci_malloc(1); }
static void mix_subscribe(sfx_pcm_mixer_t *self, sfx_pcm_feed_t *feed) { sfx_pcm_feed_state_t *fs; ACQUIRE_LOCK(); if (!self->feeds) { self->feeds_allocd = 2; self->feeds = (sfx_pcm_feed_state_t*)sci_malloc(sizeof(sfx_pcm_feed_state_t) * self->feeds_allocd); } else if (self->feeds_allocd == self->feeds_nr) { self->feeds_allocd += 2; self->feeds = (sfx_pcm_feed_state_t*)sci_realloc(self->feeds, sizeof(sfx_pcm_feed_state_t) * self->feeds_allocd); } fs = self->feeds + self->feeds_nr++; fs->feed = feed; feed->frame_size = SFX_PCM_FRAME_SIZE(feed->conf); /* fs->buf_size = (self->dev->buf_size * (feed->conf.rate + self->dev->conf.rate - 1)) / self->dev->conf.rate; */ /* For the sake of people without 64 bit CPUs: */ fs->buf_size = 2 + /* Additional safety */ (self->dev->buf_size * (1 + (feed->conf.rate / self->dev->conf.rate))); fprintf(stderr, " ---> %d/%d/%d/%d = %d\n", self->dev->buf_size, feed->conf.rate, self->dev->conf.rate, feed->frame_size, fs->buf_size); fs->buf = (byte*)sci_malloc(fs->buf_size * feed->frame_size); fprintf(stderr, " ---> --> %d for %p at %p\n", fs->buf_size * feed->frame_size, (void *)fs, (void *)fs->buf); {int i; for (i = 0; i < fs->buf_size * feed->frame_size; i++) fs->buf[i] = 0xa5; } fs->scount = urat(0, 1); fs->spd = urat(feed->conf.rate, self->dev->conf.rate); fs->scount.den = fs->spd.den; fs->ch_old.left = 0; fs->ch_old.right = 0; fs->ch_new.left = 0; fs->ch_new.right = 0; fs->mode = SFX_PCM_FEED_MODE_ALIVE; /* If the feed can't provide us with timestamps, we don't need to wait for it to do so */ fs->pending_review = (feed->get_timestamp)? 1 : 0; fs->frame_bufstart = 0; #ifdef DEBUG sciprintf("[soft-mixer] Subscribed %s-%x (%d Hz, %d/%x) at %d+%d/%d, buffer size %d\n", feed->debug_name, feed->debug_nr, feed->conf.rate, feed->conf.stereo, feed->conf.format, fs->spd.val, fs->spd.nom, fs->spd.den, fs->buf_size); #endif RELEASE_LOCK(); }
static object* read_object(resource_mgr_t *resmgr, int script, int positions[1000]) { resource_t* r = scir_find_resource(resmgr, sci_script, script, 0); unsigned char* raw; int pos; object* obj; printf("Searching for object in script %03d\n", script); if (r == 0) return 0; /*Skip to the next object*/ #ifdef SCRIPT_DEBUG printf("pre skip: pos=%#x\n", positions[script]); #endif pos = find_frame(r, 1, positions[script]); #ifdef SCRIPT_DEBUG printf("post skip: pos=%#x\n", pos); #endif if (pos == -1) return 0; else positions[script] = pos + get_length(r->data + pos); #ifdef SCRIPT_DEBUG printf("post post: pos=%#x (len=%#x)\n", positions[script], get_length(r->data + pos)); #endif /*Construct the object*/ obj = object_new(); raw = r->data + pos; /*Fill in the name*/ if (get_selector_count(raw) < 4) obj->name = "<anonymous>"; else { if (get_selector_value(raw, 3)) obj->name = (char *) r->data + get_selector_value(raw, 3); else obj->name = "<null>"; } /*Fill in the class*/ if (get_selector_count(raw) == 0) obj->parent = object_root; else { int parent_id = get_selector_value(raw, 1); if (parent_id >= fobjects.used) { free(obj); return 0; } if (parent_id < 1) obj->parent = object_root; else obj->parent = fobjects.data[parent_id]; } /*Add the object to the class*/ if (!obj->parent) { free(obj); return 0; } if (add_child(obj->parent, obj)) { free(obj); return 0; } if (add_object(obj)) { free(obj); return 0; } /*FIXME: decode selectors here*/ obj->method_count = get_method_count(raw); obj->methods = (script_method**)sci_malloc(obj->method_count * sizeof(script_method)); if (obj->methods == 0) { free(obj); return 0; } else { int i; for (i = 0; i < obj->method_count; i++) { int number = get_method_number(raw, i); int position = get_method_location(raw, i); if ((obj->methods[i] = decode_method(r->data + position)) == 0) { obj->method_count = i - 1; break; } obj->methods[i]->number = number; } } return obj; }
static script_method* decode_method(byte* data) { script_method* m; int done = 0; int pos = 0; static int count = 0; count++; if ((m = (script_method*)sci_malloc(sizeof(script_method))) == 0) return 0; FLEXARRAY_INIT(script_opcode, *m); while (!done) { int op = data[pos] >> 1; int size = 2 - (data[pos] & 1); int* args[3]; int arg; int old_pos; FLEXARRAY_ADD_SPACE(script_opcode, *m, 1, return 0); old_pos = pos; m->data[m->used-1].pos = pos; m->data[m->used-1].opcode = op; /*Copy the adresses of the args to an array for convenience*/ args[0] = &m->data[m->used-1].arg1; args[1] = &m->data[m->used-1].arg2; args[2] = &m->data[m->used-1].arg3; /*Skip past the opcode*/ pos++; for (arg = 0; arg < 4; arg++) { switch (formats[op][arg]) { case Script_Invalid: { /*Can't happen(tm)*/ int i; printf("Invalid opcode %02X at %04X in method %d\n", op, pos, count); for (i = m->used - 9; i < m->used - 1; i++) { printf("%s[%02X] ", opcodes[m->data[i].opcode].name, m->data[i].opcode); dump(data + m->data[i].pos, m->data[i].size); } printf("Dump from %04X-%04X\n", pos - 16, pos + 16); dump(data + pos - 16, 32); } break; case Script_None: { /*No more args*/ arg = 4; } break; case Script_Byte: /*Just a one byte arg*/ case Script_SByte: { *args[arg] = data[pos++]; } break; case Script_Word: { /*A two byte arg*/ *args[arg] = getInt16(data + pos); pos += 2; } break; case Script_SWord: { /*A signed two-byte arg*/ int t = getInt16(data + pos); if (t&0x8000) *args[arg] = -(t & 0x7FFF); else *args[arg] = t; pos += 2; } break; case Script_Variable: /*Size of arg depends on LSB in opcode*/ case Script_SVariable: case Script_SRelative: case Script_Property: case Script_Global: case Script_Local: case Script_Temp: case Script_Param: { if (size == 1) *args[arg] = data[pos++]; else { *args[arg] = getInt16(data + pos); pos += 2; } } break; case Script_End: { /*Special tag for ret*/ done = 1; arg = 4; } break; default: { /*Can't happen(tm)*/ printf("Unknown argument format %d for op %02X\n", formats[op][arg], op); } break; } } fflush(stdout); if (m->used) m->data[m->used-1].size = pos - old_pos; } return m; }