/* Sarien - A Sierra AGI resource interpreter engine * Copyright (C) 1999-2001 Stuart George and Claudio Matsuoka * * $Id: agi_v2.c,v 1.38 2001/09/06 18:52:14 cmatsuoka Exp $ * * 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; see docs/COPYING for further details. */ #ifndef PALMOS #include #include #include "sarien.h" #include "agi.h" static int agi_v2_init (void); static int agi_v2_deinit (void); static int agi_v2_detect_game (char *); static int agi_v2_load_resource (int, int); static int agi_v2_unload_resource (int, int); static int agi_v2_load_objects(char *); static int agi_v2_load_words(char *); struct agi_loader agi_v2 = { 2, 0, agi_v2_init, agi_v2_deinit, agi_v2_detect_game, agi_v2_load_resource, agi_v2_unload_resource, agi_v2_load_objects, agi_v2_load_words }; static int agi_v2_detect_game (char *gn) { strncpy (game.dir, gn, MAX_PATH); _D (_D_WARN "game.dir = %s", game.dir); if ( !file_isthere (fixpath (NO_GAMEDIR, LOGDIR)) || !file_isthere (fixpath (NO_GAMEDIR, PICDIR)) || !file_isthere (fixpath (NO_GAMEDIR, SNDDIR)) || !file_isthere (fixpath (NO_GAMEDIR, VIEWDIR))) { return err_InvalidAGIFile; } agi_v2.int_version = 0x2917; /* setup for 2.917 */ #ifdef __MPW__ return err_OK; #else return v2id_game (); #endif } static int agi_v2_load_dir (struct agi_dir *agid, char *fname) { FILE *fp; UINT8 *mem; UINT32 flen; unsigned int i; char *path; path = fixpath (NO_GAMEDIR, fname); report ("Loading directory: %s\n", path); if ((fp = fopen (path, "rb")) == NULL) { return err_BadFileOpen; } fseek (fp, 0, SEEK_END); flen = ftell (fp); fseek (fp, 0, SEEK_SET); if ((mem = malloc (flen + 32)) == NULL) { fclose (fp); return err_NotEnoughMemory; } fread (mem, 1, flen, fp); /* set all directory resources to gone */ for (i = 0; i < MAX_DIRS; i++) { agid[i].volume = 0xff; agid[i].offset = _EMPTY; } /* build directory entries */ for (i = 0; i < flen; i += 3) { agid[i / 3].volume = hilo_getbyte (mem + i) >> 4; agid[i / 3].offset = hilo_getpword (mem + i) & (UINT32)_EMPTY; } free (mem); fclose (fp); return err_OK; } static int agi_v2_init () { int ec = err_OK; /* load directory files */ ec = agi_v2_load_dir (game.dir_logic, LOGDIR); if (ec == err_OK) ec = agi_v2_load_dir (game.dir_pic, PICDIR); if (ec == err_OK) ec = agi_v2_load_dir (game.dir_view, VIEWDIR); if (ec == err_OK) ec = agi_v2_load_dir (game.dir_sound, SNDDIR); return ec; } static int agi_v2_deinit () { int ec = err_OK; #if 0 /* unload words */ agi_v2_unload_words (); /* unload objects */ agi_v2_unload_objects (); #endif return ec; } #if 0 static int agi_v2_load_objects (UINT8 *fname) { return load_objects (fname); } static int agi_v2_load_words (UINT8* fname) { return load_words (fname); } static int agi_v2_unload_objects () { unload_objects (); return err_OK; } static int agi_v2_unload_words () { unload_words (); return err_OK; } #endif static int agi_v2_unload_resource (int t, int n) { /* _D ("unload resource"); */ switch (t) { case rLOGIC: unload_logic (n); break; case rPICTURE: unload_picture (n); break; case rVIEW: unload_view (n); break; case rSOUND: unload_sound (n); break; } return err_OK; } /* * This function does noting but load a raw resource into memory, * if further decoding is required, it must be done by another * routine. NULL is returned if unsucsessfull. */ static UINT8* agi_v2_load_vol_res (struct agi_dir *agid) { UINT8 *data = NULL; char x[MAX_PATH], *path; FILE *fp; unsigned int sig; sprintf (x, "vol.%i", agid->volume); path = fixpath (NO_GAMEDIR, x); _D ("path = %s", path); if (agid->offset != _EMPTY && (fp = fopen (path, "rb")) != NULL) { _D ("loading resource at offset %d", agid->offset); if (fseek (fp, agid->offset, SEEK_SET) < 0) { agid->offset = _EMPTY; return NULL; } fread (&x, 1, 5, fp); if ((sig = hilo_getword ((UINT8*)x)) == 0x1234) { agid->len = lohi_getword ((UINT8*)x + 3); data = calloc (1, agid->len + 32); if (data != NULL) { fread (data, 1, agid->len, fp); } else { abort (); } } else { #if 0 /* FIXME: call some panic handler instead of * deiniting directly */ deinit_video_mode (); #endif report ("Error: bad signature %04x\n", sig); /* fprintf (stderr, "ACK! BAD RESOURCE!!!\n"); */ return 0; } fclose (fp); } else { /* we have a bad volume resource */ /* set that resource to NA */ agid->offset = _EMPTY; } return data; } /* * Loads a resource into memory, a raw resource is loaded in * with above routine, then further decoded here. */ int agi_v2_load_resource (int t, int n) { int ec = err_OK; UINT8 *data = NULL; _D (_D_WARN "(t = %d, n = %d)", t, n); if (n > MAX_DIRS) return err_BadResource; switch (t) { case rLOGIC: if (~game.dir_logic[n].flags & RES_LOADED) { /*report ("load logic #%d\n", n);*/ _D (_D_WARN "loading logic resource %d", n); agi_v2.unload_resource (rLOGIC, n); /* load raw resource into data */ data = agi_v2_load_vol_res (&game.dir_logic[n]); game.logics[n].data = data; ec = data ? decode_logic (n) : err_BadResource; game.logics[n].sIP = 2; } /* if logic was cached, we get here */ /* reset code pointers incase it was cached */ game.logics[n].cIP = game.logics[n].sIP; break; case rPICTURE: /* if picture is currently NOT loaded *OR* cacheing is off, * unload the resource (caching == off) and reload it */ _D (_D_WARN "loading picture resource %d", n); if (game.dir_pic[n].flags & RES_LOADED) break; /* if loaded but not cached, unload it */ /* if cached but not loaded, etc */ agi_v2.unload_resource (rPICTURE, n); data = agi_v2_load_vol_res (&game.dir_pic[n]); if (data != NULL) { game.pictures[n].rdata = data; game.dir_pic[n].flags |= RES_LOADED; } else { ec = err_BadResource; } break; case rSOUND: _D (_D_WARN "loading sound resource %d", n); if (game.dir_sound[n].flags & RES_LOADED) break; data = agi_v2_load_vol_res (&game.dir_sound[n]); if (data != NULL) { game.sounds[n].rdata = data; game.dir_sound[n].flags |= RES_LOADED; decode_sound (n); } else { ec = err_BadResource; } break; case rVIEW: /* Load a VIEW resource into memory... * Since VIEWS alter the view table ALL the time * can we cache the view? or must we reload it all * the time? */ if (game.dir_view[n].flags & RES_LOADED) break; _D (_D_WARN "loading view resource %d", n); agi_v2.unload_resource (rVIEW, n); data = agi_v2_load_vol_res (&game.dir_view[n]); if (data) { game.views[n].rdata = data; game.dir_view[n].flags |= RES_LOADED; ec = decode_view (n); } else { ec=err_BadResource; } break; default: ec = err_BadResource; break; } return ec; } static int agi_v2_load_objects(char *fname) { return load_objects(fname); } static int agi_v2_load_words(char *fname) { return load_words(fname); } #endif /* PALMOS */