Initial commit
This commit is contained in:
97
devtools/sci/musicplayer.cpp
Normal file
97
devtools/sci/musicplayer.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <sfx_iterator_internal.h>
|
||||
#include <sfx_engine.h>
|
||||
#include <sfx_core.h>
|
||||
#include <resource.h>
|
||||
|
||||
#define DUMMY_SOUND_HANDLE 0xdeadbeef
|
||||
|
||||
static song_iterator_t *
|
||||
build_iterator(resource_mgr_t *resmgr, int song_nr, int type, songit_id_t id) {
|
||||
resource_t *song = scir_find_resource(resmgr, sci_sound, song_nr, 0);
|
||||
|
||||
if (!song)
|
||||
return NULL;
|
||||
|
||||
return songit_new(song->data, song->size, type, id);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
resource_mgr_t *resmgr;
|
||||
sfx_state_t sound;
|
||||
int res_version = SCI_VERSION_AUTODETECT;
|
||||
int sound_nr;
|
||||
song_handle_t dummy1;
|
||||
int dummy2;
|
||||
int arg;
|
||||
int it_type = SCI_SONG_ITERATOR_TYPE_SCI0;
|
||||
song_iterator_t *base, *ff;
|
||||
|
||||
printf("FreeSCI %s music player Copyright (C) 1999-2007\n", VERSION);
|
||||
printf(" Dmitry Jemerov, Christopher T. Lansdown, Sergey Lapin, Rickard Lind,\n"
|
||||
" Carl Muckenhoupt, Christoph Reichenbach, Magnus Reftel, Lars Skovlund,\n"
|
||||
" Rink Springer, Petr Vyhnak, Solomon Peachy, Matt Hargett, Alex Angas\n"
|
||||
" Walter van Niftrik, Rainer Canavan, Ruediger Hanke, Hugues Valois\n"
|
||||
"This program is free software. You can copy and/or modify it freely\n"
|
||||
"according to the terms of the GNU general public license, v2.0\n"
|
||||
"or any later version, at your option.\n"
|
||||
"It comes with ABSOLUTELY NO WARRANTY.\n");
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "Syntax: %s <resource dir> <sound number> [<sound number> ...]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(resmgr = scir_new_resource_manager(argv[1], res_version,
|
||||
0, 1024 * 128))) {
|
||||
fprintf(stderr, "Could not find any resources; quitting.\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (resmgr->sci_version >= SCI_VERSION_01)
|
||||
it_type = SCI_SONG_ITERATOR_TYPE_SCI1;
|
||||
|
||||
sfx_init(&sound, resmgr, 0);
|
||||
sfx_set_volume(&sound, 127);
|
||||
|
||||
arg = 2 - 1;
|
||||
while (++arg < argc) {
|
||||
sound_nr = atoi(argv[arg]);
|
||||
base = ff = build_iterator(resmgr, sound_nr, it_type,
|
||||
DUMMY_SOUND_HANDLE);
|
||||
printf("Playing resource %d...\n", sound_nr);
|
||||
if (sfx_add_song(&sound, ff,
|
||||
0, DUMMY_SOUND_HANDLE, sound_nr)) {
|
||||
fprintf(stderr, "Could not start sound resource. Does it exist?\n");
|
||||
return 2;
|
||||
}
|
||||
sfx_song_set_status(&sound, DUMMY_SOUND_HANDLE, SOUND_STATUS_PLAYING);
|
||||
while (sfx_poll(&sound, &dummy1, &dummy2) != SI_FINISHED) {}
|
||||
}
|
||||
sfx_exit(&sound);
|
||||
scir_free_resource_manager(resmgr);
|
||||
return 0;
|
||||
}
|
||||
983
devtools/sci/scidisasm.cpp
Normal file
983
devtools/sci/scidisasm.cpp
Normal file
@@ -0,0 +1,983 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#define MALLOC_DEBUG
|
||||
|
||||
#include <sciresource.h>
|
||||
#include <engine.h>
|
||||
#include <console.h>
|
||||
#include <versions.h>
|
||||
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif /* HAVE_GETOPT_H */
|
||||
|
||||
static int hexdump = 0;
|
||||
static int opcode_size = 0;
|
||||
static int verbose = 0;
|
||||
|
||||
static resource_mgr_t *resmgr;
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static struct option options[] = {
|
||||
{"version", no_argument, 0, 256},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"hexdump", no_argument, &hexdump, 1},
|
||||
{"opcode-size", no_argument, &opcode_size, 1},
|
||||
{"verbose", no_argument, &verbose, 1},
|
||||
{"gamedir", required_argument, 0, 'd'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
#endif /* HAVE_GETOPT_LONG */
|
||||
|
||||
#define SCI_ASSUME_VERSION SCI_VERSION_FTU_NEW_SCRIPT_HEADER
|
||||
|
||||
typedef struct name_s {
|
||||
int offset;
|
||||
char *name;
|
||||
int class_no;
|
||||
struct name_s *next;
|
||||
} name_t;
|
||||
|
||||
typedef struct area_s {
|
||||
int start_offset;
|
||||
int end_offset;
|
||||
void *data;
|
||||
struct area_s *next;
|
||||
} area_t;
|
||||
|
||||
enum area_type { area_said, area_string, area_object, area_last };
|
||||
|
||||
typedef struct script_state_s {
|
||||
int script_no;
|
||||
name_t *names;
|
||||
area_t *areas [area_last];
|
||||
|
||||
struct script_state_s *next;
|
||||
} script_state_t;
|
||||
|
||||
typedef struct disasm_state_s {
|
||||
char **snames;
|
||||
int selector_count;
|
||||
opcode *opcodes;
|
||||
int kernel_names_nr;
|
||||
char **kernel_names;
|
||||
word_t **words;
|
||||
int word_count;
|
||||
|
||||
char **class_names;
|
||||
int *class_selector_count;
|
||||
short **class_selectors;
|
||||
int class_count;
|
||||
int old_header;
|
||||
|
||||
script_state_t *scripts;
|
||||
} disasm_state_t;
|
||||
|
||||
void
|
||||
disassemble_script(disasm_state_t *d, int res_no, int pass_no);
|
||||
|
||||
script_state_t *
|
||||
find_script_state(disasm_state_t *d, int script_no);
|
||||
|
||||
void
|
||||
script_free_names(script_state_t *s);
|
||||
|
||||
void
|
||||
script_add_name(script_state_t *s, int aoffset, char *aname, int aclass_no);
|
||||
|
||||
char *
|
||||
script_find_name(script_state_t *s, int offset, int *class_no);
|
||||
|
||||
void
|
||||
script_add_area(script_state_t *s, int start_offset, int end_offset, int type, void *data);
|
||||
|
||||
void
|
||||
script_free_areas(script_state_t *s);
|
||||
|
||||
int
|
||||
script_get_area_type(script_state_t *s, int offset, void **pdata);
|
||||
|
||||
void
|
||||
disasm_init(disasm_state_t *d);
|
||||
|
||||
void
|
||||
disasm_free_state(disasm_state_t *d);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int i;
|
||||
char outfilename [256];
|
||||
int optindex = 0;
|
||||
int c;
|
||||
disasm_state_t disasm_state;
|
||||
char *gamedir = NULL;
|
||||
int res_version = SCI_VERSION_AUTODETECT;
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
while ((c = getopt_long(argc, argv, "vhxr:d:", options, &optindex)) > -1) {
|
||||
#else /* !HAVE_GETOPT_H */
|
||||
while ((c = getopt(argc, argv, "vhxr:d:")) > -1) {
|
||||
#endif /* !HAVE_GETOPT_H */
|
||||
|
||||
switch (c) {
|
||||
case 256:
|
||||
printf("scidisasm ("PACKAGE") "VERSION"\n");
|
||||
printf("This program is copyright (C) 1999 Christoph Reichenbach.\n"
|
||||
"It comes WITHOUT WARRANTY of any kind.\n"
|
||||
"This is free software, released under the GNU General Public License.\n");
|
||||
exit(0);
|
||||
|
||||
case 'h':
|
||||
printf("Usage: scidisasm\n"
|
||||
"\nAvailable options:\n"
|
||||
" --version Prints the version number\n"
|
||||
" --help -h Displays this help message\n"
|
||||
" --gamedir <dir> -d<dir> Read game resources from dir\n"
|
||||
" --hexdump -x Hex dump all script resources\n"
|
||||
" --verbose Print additional disassembly information\n"
|
||||
" --opcode-size Print opcode size postfixes\n");
|
||||
exit(0);
|
||||
|
||||
case 'd':
|
||||
if (gamedir) sci_free(gamedir);
|
||||
gamedir = sci_strdup(optarg);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
res_version = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 0: /* getopt_long already did this for us */
|
||||
case '?':
|
||||
/* getopt_long already printed an error message. */
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (gamedir)
|
||||
if (chdir(gamedir)) {
|
||||
printf("Error changing to game directory '%s'\n", gamedir);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Loading resources...\n");
|
||||
if (!(resmgr = scir_new_resource_manager(sci_getcwd(), res_version,
|
||||
1, 1024 * 128))) {
|
||||
fprintf(stderr, "Could not find any resources; quitting.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
disasm_init(&disasm_state);
|
||||
|
||||
script_adjust_opcode_formats(resmgr->sci_version);
|
||||
|
||||
printf("Performing first pass...\n");
|
||||
for (i = 0; i < resmgr->resources_nr; i++)
|
||||
if (resmgr->resources[i].type == sci_script)
|
||||
disassemble_script(&disasm_state,
|
||||
resmgr->resources[i].number, 1);
|
||||
|
||||
printf("Performing second pass...\n");
|
||||
for (i = 0; i < resmgr->resources_nr; i++)
|
||||
if (resmgr->resources[i].type == sci_script) {
|
||||
sprintf(outfilename, "%03d.script",
|
||||
resmgr->resources[i].number);
|
||||
open_console_file(outfilename);
|
||||
disassemble_script(&disasm_state,
|
||||
resmgr->resources[i].number, 2);
|
||||
}
|
||||
|
||||
close_console_file();
|
||||
disasm_free_state(&disasm_state);
|
||||
|
||||
free(resmgr->resource_path);
|
||||
scir_free_resource_manager(resmgr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- General operations on disasm_state_t ------------------------------- */
|
||||
|
||||
void
|
||||
disasm_init(disasm_state_t *d) {
|
||||
d->snames = vocabulary_get_snames(resmgr, &d->selector_count, SCI_ASSUME_VERSION);
|
||||
d->opcodes = vocabulary_get_opcodes(resmgr);
|
||||
d->kernel_names = vocabulary_get_knames(resmgr, &d->kernel_names_nr);
|
||||
d->words = vocab_get_words(resmgr, &d->word_count);
|
||||
d->scripts = NULL;
|
||||
d->old_header = 0;
|
||||
|
||||
d->class_count = vocabulary_get_class_count(resmgr);
|
||||
d->class_names = (char **) sci_malloc(d->class_count * sizeof(char *));
|
||||
memset(d->class_names, 0, d->class_count * sizeof(char *));
|
||||
d->class_selector_count = (int *) sci_malloc(d->class_count * sizeof(int));
|
||||
memset(d->class_selector_count, 0, d->class_count * sizeof(int));
|
||||
d->class_selectors = (short **) sci_malloc(d->class_count * sizeof(short *));
|
||||
memset(d->class_selectors, 0, d->class_count * sizeof(short *));
|
||||
}
|
||||
|
||||
void
|
||||
disasm_free_state(disasm_state_t *d) {
|
||||
script_state_t *s, *next_script;
|
||||
int i;
|
||||
|
||||
s = d->scripts;
|
||||
while (s) {
|
||||
next_script = s->next;
|
||||
script_free_names(s);
|
||||
script_free_areas(s);
|
||||
s = next_script;
|
||||
}
|
||||
|
||||
for (i = 0; i < d->class_count; i++) {
|
||||
if (d->class_names [i]) sci_free(d->class_names [i]);
|
||||
if (d->class_selectors [i]) sci_free(d->class_selectors [i]);
|
||||
}
|
||||
|
||||
free(d->class_names);
|
||||
free(d->class_selectors);
|
||||
free(d->class_selector_count);
|
||||
|
||||
vocabulary_free_snames(d->snames);
|
||||
vocabulary_free_opcodes(d->opcodes);
|
||||
vocabulary_free_knames(d->kernel_names);
|
||||
vocab_free_words(d->words, d->word_count);
|
||||
}
|
||||
|
||||
script_state_t *
|
||||
find_script_state(disasm_state_t *d, int script_no) {
|
||||
script_state_t *s;
|
||||
|
||||
for (s = d->scripts; s; s = s->next)
|
||||
if (s->script_no == script_no) return s;
|
||||
|
||||
s = (script_state_t *) sci_malloc(sizeof(script_state_t));
|
||||
memset(s, 0, sizeof(script_state_t));
|
||||
s->script_no = script_no;
|
||||
s->next = d->scripts;
|
||||
|
||||
d->scripts = s;
|
||||
return s;
|
||||
}
|
||||
|
||||
/* -- Name table operations ---------------------------------------------- */
|
||||
|
||||
void
|
||||
script_free_names(script_state_t *s) {
|
||||
name_t *p = s->names, *next_name;
|
||||
|
||||
while (p) {
|
||||
next_name = p->next;
|
||||
free(p->name);
|
||||
free(p);
|
||||
p = next_name;
|
||||
}
|
||||
|
||||
s->names = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
script_add_name(script_state_t *s, int aoffset, char *aname, int aclass_no) {
|
||||
name_t *p;
|
||||
char *name = script_find_name(s, aoffset, NULL);
|
||||
if (name) return;
|
||||
|
||||
p = (name_t *) sci_malloc(sizeof(name_t));
|
||||
p->offset = aoffset;
|
||||
p->name = sci_strdup(aname);
|
||||
p->class_no = aclass_no;
|
||||
p->next = s->names;
|
||||
s->names = p;
|
||||
}
|
||||
|
||||
char *
|
||||
script_find_name(script_state_t *s, int offset, int *aclass_no) {
|
||||
name_t *p;
|
||||
|
||||
for (p = s->names; p; p = p->next)
|
||||
if (p->offset == offset) {
|
||||
if (aclass_no && p->class_no != -2) *aclass_no = p->class_no;
|
||||
return p->name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* -- Area table operations ---------------------------------------------- */
|
||||
|
||||
void
|
||||
script_add_area(script_state_t *s, int start_offset, int end_offset, int type, void *data) {
|
||||
area_t *area;
|
||||
|
||||
area = (area_t *) sci_malloc(sizeof(area_t));
|
||||
area->start_offset = start_offset;
|
||||
area->end_offset = end_offset;
|
||||
area->data = data;
|
||||
area->next = s->areas [type];
|
||||
|
||||
s->areas [type] = area;
|
||||
}
|
||||
|
||||
void
|
||||
script_free_areas(script_state_t *s) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < area_last; i++) {
|
||||
area_t *area = s->areas [i], *next_area;
|
||||
while (area) {
|
||||
next_area = area->next;
|
||||
free(area);
|
||||
area = next_area;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
script_get_area_type(script_state_t *s, int offset, void **pdata) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < area_last; i++) {
|
||||
area_t *area = s->areas [i];
|
||||
while (area) {
|
||||
if (area->start_offset <= offset && area->end_offset >= offset) {
|
||||
if (pdata != NULL) *pdata = area->data;
|
||||
return i;
|
||||
}
|
||||
area = area->next;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *
|
||||
get_selector_name(disasm_state_t *d, int selector) {
|
||||
static char selector_name [256];
|
||||
|
||||
if (d->snames && selector >= 0 && selector < d->selector_count)
|
||||
return d->snames [selector];
|
||||
else {
|
||||
sprintf(selector_name, "unknown_sel_%X", selector);
|
||||
return selector_name;
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
get_class_name(disasm_state_t *d, int class_no) {
|
||||
static char class_name [256];
|
||||
|
||||
if (class_no == -1)
|
||||
return "<none>";
|
||||
else if (class_no >= 0 && class_no < d->class_count && d->class_names [class_no])
|
||||
return d->class_names [class_no];
|
||||
else {
|
||||
sprintf(class_name, "class_%d", class_no);
|
||||
return class_name;
|
||||
}
|
||||
}
|
||||
|
||||
/* -- Code to dump individual script block types ------------------------- */
|
||||
|
||||
static void
|
||||
script_dump_object(disasm_state_t *d, script_state_t *s,
|
||||
unsigned char *data, int seeker, int objsize, int pass_no) {
|
||||
int selectors, overloads, selectorsize;
|
||||
int species = getInt16(data + 8 + seeker);
|
||||
int superclass = getInt16(data + 10 + seeker);
|
||||
int namepos = getInt16(data + 14 + seeker);
|
||||
int i = 0;
|
||||
short sel;
|
||||
const char *name;
|
||||
char buf [256];
|
||||
short *sels;
|
||||
|
||||
selectors = (selectorsize = getInt16(data + seeker + 6));
|
||||
name = namepos ? ((const char *)data + namepos) : "<unknown>";
|
||||
|
||||
if (pass_no == 1)
|
||||
script_add_area(s, seeker, seeker + objsize - 1, area_object, strdup(name));
|
||||
|
||||
if (pass_no == 2) {
|
||||
sciprintf(".object\n");
|
||||
sciprintf("Name: %s\n", name);
|
||||
sciprintf("Superclass: %s [%x]\n", get_class_name(d, superclass), superclass);
|
||||
sciprintf("Species: %s [%x]\n", get_class_name(d, species), species);
|
||||
|
||||
sciprintf("-info-:%x\n", getInt16(data + 12 + seeker) & 0xffff);
|
||||
|
||||
sciprintf("Function area offset: %x\n", getInt16(data + seeker + 4));
|
||||
sciprintf("Selectors [%x]:\n", selectors);
|
||||
}
|
||||
|
||||
seeker += 8;
|
||||
|
||||
if (species < d->class_count)
|
||||
sels = d->class_selectors [species];
|
||||
else
|
||||
sels = NULL;
|
||||
|
||||
while (selectors--) {
|
||||
if (pass_no == 2) {
|
||||
sel = getInt16(data + seeker) & 0xffff;
|
||||
if (sels && (sels [i] >= 0) && (sels[i] < d->selector_count)) {
|
||||
sciprintf(" [#%03x] %s = 0x%x\n", i, d->snames [sels [i]], sel);
|
||||
i++;
|
||||
} else
|
||||
sciprintf(" [#%03x] <unknown> = 0x%x\n", i++, sel);
|
||||
}
|
||||
|
||||
seeker += 2;
|
||||
}
|
||||
|
||||
selectors = overloads = getInt16(data + seeker);
|
||||
|
||||
if (pass_no == 2)
|
||||
sciprintf("Overloaded functions: %x\n", overloads);
|
||||
|
||||
seeker += 2;
|
||||
|
||||
while (overloads--) {
|
||||
word selector = getInt16(data + (seeker)) & 0xffff;
|
||||
if (d->old_header) selector >>= 1;
|
||||
|
||||
if (pass_no == 1) {
|
||||
sprintf(buf, "%s::%s", name, get_selector_name(d, selector));
|
||||
script_add_name(s, getInt16(data + seeker + selectors*2 + 2), buf, species);
|
||||
} else {
|
||||
sciprintf(" [%03x] %s: @", selector, get_selector_name(d, selector));
|
||||
sciprintf("%04x\n", getInt16(data + seeker + selectors*2 + 2));
|
||||
}
|
||||
|
||||
seeker += 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
script_dump_class(disasm_state_t *d, script_state_t *s,
|
||||
unsigned char *data, int seeker, int objsize, int pass_no) {
|
||||
word selectors, overloads, selectorsize;
|
||||
int species = getInt16(data + 8 + seeker);
|
||||
int superclass = getInt16(data + 10 + seeker);
|
||||
int namepos = getInt16(data + 14 + seeker);
|
||||
const char *name;
|
||||
char buf [256];
|
||||
int i;
|
||||
|
||||
name = namepos ? ((const char *)data + namepos) : "<unknown>";
|
||||
selectors = (selectorsize = getInt16(data + seeker + 6));
|
||||
|
||||
if (pass_no == 1) {
|
||||
if (species >= 0 && species < d->class_count) {
|
||||
if (!namepos) {
|
||||
sprintf(buf, "class_%d", species);
|
||||
d->class_names [species] = sci_strdup(buf);
|
||||
} else
|
||||
d->class_names [species] = sci_strdup(name);
|
||||
|
||||
d->class_selector_count [species] = selectors;
|
||||
d->class_selectors [species] = (short *) sci_malloc(sizeof(short) * selectors);
|
||||
}
|
||||
}
|
||||
|
||||
if (pass_no == 2) {
|
||||
sciprintf(".class\n");
|
||||
sciprintf("Name: %s\n", name);
|
||||
sciprintf("Superclass: %s [%x]\n", get_class_name(d, superclass), superclass);
|
||||
sciprintf("Species: %x\n", species);
|
||||
sciprintf("-info-:%x\n", getInt16(data + 12 + seeker) & 0xffff);
|
||||
|
||||
sciprintf("Function area offset: %x\n", getInt16(data + seeker + 4));
|
||||
sciprintf("Selectors [%x]:\n", selectors);
|
||||
}
|
||||
|
||||
seeker += 8;
|
||||
selectorsize <<= 1;
|
||||
|
||||
for (i = 0; i < selectors; i++) {
|
||||
word selector = 0xffff & getInt16(data + (seeker) + selectorsize);
|
||||
if (d->old_header) selector >>= 1;
|
||||
|
||||
if (pass_no == 1) {
|
||||
if (species >= 0 && species < d->class_count)
|
||||
d->class_selectors [species][i] = selector;
|
||||
} else
|
||||
sciprintf(" [%03x] %s = 0x%x\n", selector, get_selector_name(d, selector),
|
||||
getInt16(data + seeker) & 0xffff);
|
||||
|
||||
seeker += 2;
|
||||
}
|
||||
|
||||
seeker += selectorsize;
|
||||
|
||||
selectors = overloads = getInt16(data + seeker);
|
||||
|
||||
sciprintf("Overloaded functions: %x\n", overloads);
|
||||
|
||||
seeker += 2;
|
||||
|
||||
while (overloads--) {
|
||||
word selector = getInt16(data + (seeker)) & 0xffff;
|
||||
if (d->old_header) selector >>= 1;
|
||||
|
||||
if (pass_no == 1) {
|
||||
sprintf(buf, "%s::%s", name, get_selector_name(d, selector));
|
||||
script_add_name(s, getInt16(data + seeker + selectors*2 + 2) & 0xffff, buf, species);
|
||||
} else {
|
||||
sciprintf(" [%03x] %s: @", selector & 0xffff, get_selector_name(d, selector));
|
||||
sciprintf("%04x\n", getInt16(data + seeker + selectors*2 + 2) & 0xffff);
|
||||
}
|
||||
|
||||
seeker += 2;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
script_dump_said_string(disasm_state_t *d, unsigned char *data, int seeker) {
|
||||
while (1) {
|
||||
unsigned short nextitem = (unsigned char) data [seeker++];
|
||||
if (nextitem == 0xFF) return seeker;
|
||||
|
||||
if (nextitem >= 0xF0) {
|
||||
switch (nextitem) {
|
||||
case 0xf0:
|
||||
sciprintf(", ");
|
||||
break;
|
||||
case 0xf1:
|
||||
sciprintf("& ");
|
||||
break;
|
||||
case 0xf2:
|
||||
sciprintf("/ ");
|
||||
break;
|
||||
case 0xf3:
|
||||
sciprintf("( ");
|
||||
break;
|
||||
case 0xf4:
|
||||
sciprintf(") ");
|
||||
break;
|
||||
case 0xf5:
|
||||
sciprintf("[ ");
|
||||
break;
|
||||
case 0xf6:
|
||||
sciprintf("] ");
|
||||
break;
|
||||
case 0xf7:
|
||||
sciprintf("# ");
|
||||
break;
|
||||
case 0xf8:
|
||||
sciprintf("< ");
|
||||
break;
|
||||
case 0xf9:
|
||||
sciprintf("> ");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
nextitem = nextitem << 8 | (unsigned char) data [seeker++];
|
||||
sciprintf("%s ", vocab_get_any_group_word(nextitem, d->words, d->word_count));
|
||||
if (verbose)
|
||||
sciprintf("[%03x] ", nextitem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
script_dump_said(disasm_state_t *d, script_state_t *s,
|
||||
unsigned char *data, int seeker, int objsize, int pass_no) {
|
||||
int _seeker = seeker + objsize - 4;
|
||||
|
||||
if (pass_no == 1) {
|
||||
script_add_area(s, seeker, seeker + objsize - 1, area_said, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
sciprintf(".said\n");
|
||||
|
||||
while (seeker < _seeker - 1) {
|
||||
sciprintf("%04x: ", seeker);
|
||||
seeker = script_dump_said_string(d, data, seeker);
|
||||
sciprintf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
script_dump_synonyms(disasm_state_t *d, script_state_t *s,
|
||||
unsigned char *data, int seeker, int objsize, int pass_no) {
|
||||
int _seeker = seeker + objsize - 4;
|
||||
|
||||
sciprintf("Synonyms:\n");
|
||||
while (seeker < _seeker) {
|
||||
int search = getInt16(data + seeker);
|
||||
int replace = getInt16(data + seeker + 2);
|
||||
seeker += 4;
|
||||
if (search < 0) break;
|
||||
sciprintf("%s[%03x] ==> %s[%03x]\n",
|
||||
vocab_get_any_group_word(search, d->words, d->word_count), search,
|
||||
vocab_get_any_group_word(replace, d->words, d->word_count), replace);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
script_dump_strings(disasm_state_t *d, script_state_t *s,
|
||||
unsigned char *data, int seeker, int objsize, int pass_no) {
|
||||
int endptr = seeker + objsize - 4;
|
||||
|
||||
if (pass_no == 1) {
|
||||
script_add_area(s, seeker, seeker + objsize - 1, area_string, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
sciprintf(".strings\n");
|
||||
while (data [seeker] && seeker < endptr) {
|
||||
sciprintf("%04x: %s\n", seeker, data + seeker);
|
||||
seeker += strlen((char *) data + seeker) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
script_dump_exports(disasm_state_t *d, script_state_t *s,
|
||||
unsigned char *data, int seeker, int objsize, int pass_no) {
|
||||
byte *pexport = (byte *)(data + seeker);
|
||||
word export_count = getUInt16(pexport);
|
||||
int i;
|
||||
char buf [256];
|
||||
|
||||
pexport += 2;
|
||||
|
||||
if (pass_no == 2) sciprintf(".exports\n");
|
||||
|
||||
for (i = 0; i < export_count; i++) {
|
||||
if (pass_no == 1) {
|
||||
guint16 offset = getUInt16(pexport);
|
||||
sprintf(buf, "exp_%02X", i);
|
||||
script_add_name(s, offset, buf, -1);
|
||||
} else
|
||||
sciprintf("%02X: %04X\n", i, *pexport);
|
||||
pexport += 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* -- The disassembly code ----------------------------------------------- */
|
||||
|
||||
static void
|
||||
script_disassemble_code(disasm_state_t *d, script_state_t *s,
|
||||
unsigned char *data, int seeker, int objsize, int pass_no) {
|
||||
int endptr = seeker + objsize - 4;
|
||||
int i = 0;
|
||||
int cur_class = -1;
|
||||
word dest;
|
||||
void *area_data;
|
||||
char buf [256];
|
||||
char *dest_name;
|
||||
|
||||
if (pass_no == 2) sciprintf(".code\n");
|
||||
|
||||
while (seeker < endptr - 1) {
|
||||
unsigned char opsize = data [seeker];
|
||||
unsigned char opcode = opsize >> 1;
|
||||
word param_value;
|
||||
char *name;
|
||||
|
||||
opsize &= 1; /* byte if true, word if false */
|
||||
|
||||
if (pass_no == 2) {
|
||||
name = script_find_name(s, seeker, &cur_class);
|
||||
if (name) sciprintf(" %s:\n", name);
|
||||
sciprintf("%04X: ", seeker);
|
||||
sciprintf("%s", d->opcodes[opcode].name);
|
||||
if (opcode_size && formats[opcode][0])
|
||||
sciprintf(".%c", opsize ? 'b' : 'w');
|
||||
sciprintf("\t");
|
||||
}
|
||||
|
||||
seeker++;
|
||||
|
||||
for (i = 0; formats[opcode][i]; i++)
|
||||
|
||||
switch (formats[opcode][i]) {
|
||||
|
||||
case Script_Invalid:
|
||||
if (pass_no == 2) sciprintf("-Invalid operation-");
|
||||
break;
|
||||
|
||||
case Script_SByte:
|
||||
case Script_Byte:
|
||||
if (pass_no == 2) sciprintf(" %02x", data[seeker]);
|
||||
seeker++;
|
||||
break;
|
||||
|
||||
case Script_Word:
|
||||
case Script_SWord:
|
||||
if (pass_no == 2)
|
||||
sciprintf(" %04x", 0xffff & (data[seeker] | (data[seeker+1] << 8)));
|
||||
seeker += 2;
|
||||
break;
|
||||
|
||||
case Script_SVariable:
|
||||
case Script_Variable:
|
||||
case Script_Global:
|
||||
case Script_Local:
|
||||
case Script_Temp:
|
||||
case Script_Param:
|
||||
case Script_SRelative:
|
||||
case Script_Property:
|
||||
case Script_Offset:
|
||||
if (opsize)
|
||||
param_value = data [seeker++];
|
||||
else {
|
||||
param_value = 0xffff & (data[seeker] | (data[seeker+1] << 8));
|
||||
seeker += 2;
|
||||
}
|
||||
|
||||
if (pass_no == 1) {
|
||||
if (opcode == op_jmp || opcode == op_bt || opcode == op_bnt) {
|
||||
dest = seeker + (short) param_value;
|
||||
sprintf(buf, "lbl_%04X", dest);
|
||||
script_add_name(s, dest, buf, -2);
|
||||
}
|
||||
} else if (pass_no == 2)
|
||||
switch (formats[opcode][i]) {
|
||||
|
||||
case Script_SVariable:
|
||||
case Script_Variable:
|
||||
if (opcode == op_callk) {
|
||||
sciprintf(" #%s", (param_value < d->kernel_names_nr)
|
||||
? d->kernel_names[param_value] : "<invalid>");
|
||||
if (verbose) sciprintf("[%x]", param_value);
|
||||
} else if (opcode == op_class || (opcode == op_super && i == 0)) {
|
||||
sciprintf(" %s", (d->class_names && param_value < d->class_count)
|
||||
? d->class_names[param_value] : "<invalid>");
|
||||
if (verbose) sciprintf("[%x]", param_value);
|
||||
} else sciprintf(opsize ? " %02x" : " %04x", param_value);
|
||||
|
||||
if (opcode == op_pushi && param_value > 0 && param_value < d->selector_count)
|
||||
sciprintf("\t\t; selector <%s>", d->snames [param_value]);
|
||||
|
||||
break;
|
||||
|
||||
case Script_Global:
|
||||
sciprintf(" global_%d", param_value);
|
||||
break;
|
||||
|
||||
case Script_Local:
|
||||
sciprintf(" local_%d", param_value);
|
||||
break;
|
||||
|
||||
case Script_Temp:
|
||||
sciprintf(" temp_%d", param_value);
|
||||
break;
|
||||
|
||||
case Script_Param:
|
||||
sciprintf(" param_%d", param_value);
|
||||
break;
|
||||
|
||||
case Script_Offset:
|
||||
dest = (short) param_value;
|
||||
dest_name = script_find_name(s, dest, NULL);
|
||||
if (dest_name)
|
||||
sciprintf(" %s", dest_name);
|
||||
else
|
||||
sciprintf(" %04x", dest);
|
||||
|
||||
if (verbose)
|
||||
sciprintf(opsize ? " [%02x] " : " [%04x] ", param_value);
|
||||
|
||||
if (opcode == op_lofsa || opcode == op_lofss) {
|
||||
int atype = script_get_area_type(s, dest, &area_data);
|
||||
if (atype == area_string) {
|
||||
strncpy(buf, (char *) &data [dest], sizeof(buf) - 1);
|
||||
buf [sizeof(buf)-1] = 0;
|
||||
if (strlen(buf) > 40) {
|
||||
buf [40] = 0;
|
||||
strcat(buf, "...");
|
||||
}
|
||||
sciprintf("\t\t; \"%s\"", buf);
|
||||
} else if (atype == area_said) {
|
||||
sciprintf("\t\t; said \"");
|
||||
script_dump_said_string(d, data, dest);
|
||||
sciprintf("\"\n");
|
||||
} else if (atype == area_object)
|
||||
sciprintf("\t\t; object <%s>", area_data);
|
||||
}
|
||||
break;
|
||||
|
||||
case Script_SRelative:
|
||||
dest = seeker + (short) param_value;
|
||||
dest_name = script_find_name(s, dest, NULL);
|
||||
if (dest_name)
|
||||
sciprintf(" %s", dest_name);
|
||||
else
|
||||
sciprintf(" %04x", dest);
|
||||
|
||||
if (verbose)
|
||||
sciprintf(opsize ? " [%02x] " : " [%04x] ", param_value);
|
||||
|
||||
if (opcode == op_lofsa || opcode == op_lofss) {
|
||||
int atype = script_get_area_type(s, dest, &area_data);
|
||||
if (atype == area_string) {
|
||||
strncpy(buf, (char *) &data [dest], sizeof(buf) - 1);
|
||||
buf [sizeof(buf)-1] = 0;
|
||||
if (strlen(buf) > 40) {
|
||||
buf [40] = 0;
|
||||
strcat(buf, "...");
|
||||
}
|
||||
sciprintf("\t\t; \"%s\"", buf);
|
||||
} else if (atype == area_said) {
|
||||
sciprintf("\t\t; said \"");
|
||||
script_dump_said_string(d, data, dest);
|
||||
sciprintf("\"\n");
|
||||
} else if (atype == area_object)
|
||||
sciprintf("\t\t; object <%s>", area_data);
|
||||
}
|
||||
break;
|
||||
|
||||
case Script_Property:
|
||||
if (cur_class != -1 && param_value / 2 < d->class_selector_count [cur_class]) {
|
||||
sciprintf(" %s", get_selector_name(d, d->class_selectors [cur_class][param_value/2]));
|
||||
if (verbose) sciprintf("[%x]", param_value);
|
||||
} else
|
||||
sciprintf(opsize ? " %02x" : " %04x", param_value);
|
||||
|
||||
break;
|
||||
|
||||
case Script_End:
|
||||
if (pass_no == 2) sciprintf("\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
sciprintf("Unexpected opcode format %d\n", (formats[opcode][i]));
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (pass_no == 2) sciprintf("\n");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
disassemble_script_pass(disasm_state_t *d, script_state_t *s,
|
||||
resource_t *script, int pass_no) {
|
||||
int _seeker = 0;
|
||||
word id = getInt16(script->data);
|
||||
|
||||
if (id > 15) {
|
||||
if (pass_no == 2) sciprintf("; Old script header detected\n");
|
||||
d->old_header = 1;
|
||||
}
|
||||
|
||||
if (d->old_header) _seeker = 2;
|
||||
|
||||
while (_seeker < script->size) {
|
||||
int objtype = getInt16(script->data + _seeker);
|
||||
int objsize;
|
||||
int seeker = _seeker + 4;
|
||||
|
||||
if (!objtype) return;
|
||||
|
||||
if (pass_no == 2)
|
||||
sciprintf("\n");
|
||||
|
||||
objsize = getInt16(script->data + _seeker + 2);
|
||||
|
||||
if (pass_no == 2) {
|
||||
sciprintf("; Obj type #%x, offset 0x%x, size 0x%x:\n", objtype, _seeker, objsize);
|
||||
if (hexdump) sci_hexdump(script->data + seeker, objsize - 4, seeker);
|
||||
}
|
||||
|
||||
_seeker += objsize;
|
||||
|
||||
switch (objtype) {
|
||||
case sci_obj_object:
|
||||
script_dump_object(d, s, script->data, seeker, objsize, pass_no);
|
||||
break;
|
||||
|
||||
case sci_obj_code:
|
||||
script_disassemble_code(d, s, script->data, seeker, objsize, pass_no);
|
||||
break;
|
||||
|
||||
case sci_obj_synonyms:
|
||||
script_dump_synonyms(d, s, script->data, seeker, objsize, pass_no);
|
||||
break;
|
||||
|
||||
case sci_obj_said:
|
||||
script_dump_said(d, s, script->data, seeker, objsize, pass_no);
|
||||
break;
|
||||
|
||||
case sci_obj_strings:
|
||||
script_dump_strings(d, s, script->data, seeker, objsize, pass_no);
|
||||
break;
|
||||
|
||||
case sci_obj_class:
|
||||
script_dump_class(d, s, script->data, seeker, objsize, pass_no);
|
||||
break;
|
||||
|
||||
case sci_obj_exports:
|
||||
script_dump_exports(d, s, script->data, seeker, objsize, pass_no);
|
||||
break;
|
||||
|
||||
case sci_obj_pointers:
|
||||
if (pass_no == 2) {
|
||||
sciprintf("Pointers\n");
|
||||
sci_hexdump(script->data + seeker, objsize - 4, seeker);
|
||||
};
|
||||
break;
|
||||
|
||||
case sci_obj_preload_text:
|
||||
if (pass_no == 2) {
|
||||
sciprintf("The script has a preloaded text resource\n");
|
||||
};
|
||||
break;
|
||||
|
||||
case sci_obj_localvars:
|
||||
if (pass_no == 2) {
|
||||
sciprintf("Local vars\n");
|
||||
sci_hexdump(script->data + seeker, objsize - 4, seeker);
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
sciprintf("Unsupported %d!\n", objtype);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sciprintf("Script ends without terminator\n");
|
||||
}
|
||||
|
||||
void
|
||||
disassemble_script(disasm_state_t *d, int res_no, int pass_no) {
|
||||
resource_t *script = scir_find_resource(resmgr, sci_script, res_no, 0);
|
||||
script_state_t *s = find_script_state(d, res_no);
|
||||
|
||||
if (!script) {
|
||||
sciprintf("Script not found!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
disassemble_script_pass(d, s, script, pass_no);
|
||||
}
|
||||
45
devtools/sci/scifx/lsl2.scifx
Normal file
45
devtools/sci/scifx/lsl2.scifx
Normal file
@@ -0,0 +1,45 @@
|
||||
# LSL2 per-resource palette configuration
|
||||
# Copyright (C) 2006 Matt Hargett
|
||||
|
||||
gameid = LSL2;
|
||||
|
||||
#ego
|
||||
view(507,155,161,163,170,197,198,431,432,145..159,131..141,191,104,244,215,217,219,100,101,110,111,112,113,192,193,604,704..706,717,718,818,819,822,823,824,831,832,833,834,835) *= 1.25;
|
||||
pic(28,99) *= 1.25;
|
||||
view(218)(3) *= 1.25;
|
||||
view(218)(0..2) *= 0.9;
|
||||
view(820)(0,1) *= 0.9;
|
||||
view(227,224,206,208,209,220) *= 0.9;
|
||||
view(221,254,252) *= 0.7;
|
||||
view(820)(2..4) *= 1.2;
|
||||
view(816)(5)(0) *= 1.2;
|
||||
view(516,509,501..504,401..403,408,409,411,413,414,417,418,419,430,310,302,303,120..124,232,223,208,710,716,714) *=1.1;
|
||||
view(434..438,311,313,316,319,321,323,324,306..309,248,245,246,233..235,237,226,229,222,203,204,205,600,525,524,523,522,520,602,605,608,707..708) *=1.2;
|
||||
view(305)(4) *= 1.1;
|
||||
view(305)(0..3) *= 0.6;
|
||||
view(661)(0,1,3..5) *= 1.2;
|
||||
view(661)(2) *= 0.7;
|
||||
view(711,712,713,60) *= (0.9, 1.0, 1.0);
|
||||
view(816)(0..4) *= 0.9;
|
||||
view(506,508,500,252,803,804,433) *= 0.6;
|
||||
view(513)(0..5) *= 0.5;
|
||||
view(240..243,701,722) *= 0.8;
|
||||
view(700)(1) *= (0.6, 0.9, 1.0);
|
||||
view(610,611) *= (0.9, 1.0, 1.1);
|
||||
view(607)(1) *= 0.8;
|
||||
view(253,228,247,300,326) *= 0.8;
|
||||
view(412) *= 1.3;
|
||||
pic(96) *= 1.1;
|
||||
|
||||
pic(92,93,18,20..26,134,40,50,76..82,181) *= 0.9;
|
||||
pic(114..118,125,11..17,19,43,70..74,44,86,101..104,32,33,35,36,95) *= 0.85;
|
||||
#titles
|
||||
view(800,801) *= 1.5;
|
||||
pic(10,90,91) *= 0.4;
|
||||
|
||||
#misc effects
|
||||
view(702) *= (1.1, 1.0, 1.0);
|
||||
view(519) *= 0.8;
|
||||
|
||||
view(200)(0) *= 0.7;
|
||||
view(201,202) *= 0.8;
|
||||
232
devtools/sci/scifx/scifx_to_cpp.py
Normal file
232
devtools/sci/scifx/scifx_to_cpp.py
Normal file
@@ -0,0 +1,232 @@
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
from typing import List, Tuple, Any
|
||||
|
||||
def Chunker(seq: List[Any], size: int) -> List[List[Any]]:
|
||||
return (seq[pos:pos + size] for pos in range(0, len(seq), size))
|
||||
|
||||
def ModToIndex(mods: List[Tuple[int]], m: int):
|
||||
try:
|
||||
return mods.index(m)
|
||||
except ValueError:
|
||||
mods.append(m)
|
||||
return len(mods)-1
|
||||
|
||||
def PrintMods(gid: str, mods: List[Tuple[int]]):
|
||||
L = [ "\t{ " + ", ".join( [ "%4d" % (round(128 * (val - 1)),) for val in m ] ) + " }" for m in mods ]
|
||||
print("static const PaletteMod paletteMods" + gid + "[] = {")
|
||||
print( ",\n".join(L) )
|
||||
print("};")
|
||||
|
||||
def PrintPic(gid: str, pics: List[List[int]], comments: List[str]):
|
||||
print("static const PicMod picMods" + gid + "[] = {")
|
||||
|
||||
for comment in comments:
|
||||
print("\t// " + comment)
|
||||
|
||||
for chunk in Chunker(pics, 5):
|
||||
t = ""
|
||||
for pic in chunk:
|
||||
t = t + "{ " + str(pic[0]).rjust(3, ' ') + ", " + str(pic[1]).rjust(2, ' ') + " }, "
|
||||
print("\t" + t)
|
||||
|
||||
print("};")
|
||||
|
||||
def PrintView(gid: str, views: List[List[int]], comments: List[str]):
|
||||
print("static const ViewMod viewMods" + gid + "[] = {")
|
||||
|
||||
for comment in comments:
|
||||
print("\t// " + comment)
|
||||
|
||||
for chunk in Chunker(views, 5):
|
||||
t = ""
|
||||
for view in chunk:
|
||||
t = t + "{ " + str(view[0]).rjust(3, ' ') + ", " + str(view[1]).rjust(2, ' ') + ", " + str(view[2]).rjust(2, ' ') + ", " + str(view[3]).rjust(2, ' ') + " }, "
|
||||
print("\t" + t)
|
||||
|
||||
print("};")
|
||||
|
||||
def ParseList(l: str) -> Tuple[str, List[str]]:
|
||||
assert(l[0] == '(')
|
||||
e = l.find(")")
|
||||
L = l[1:e].split(",")
|
||||
tests = []
|
||||
for t in L:
|
||||
t = t.strip()
|
||||
ell = t.find('..')
|
||||
if ell >= 0:
|
||||
start = int(t[0:ell])
|
||||
end = int(t[ell+2:])
|
||||
# interval
|
||||
for x in range(start, end + 1):
|
||||
tests.append(str(x))
|
||||
else:
|
||||
tests.append(t)
|
||||
return l[e+1:], tests
|
||||
|
||||
def ParseTriple(l: str) -> List[str]:
|
||||
assert(l[0] == '(')
|
||||
e = l.find(")")
|
||||
L = l[1:e].split(",")
|
||||
assert(len(L) == 3)
|
||||
return L
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python scifx_to_header.py [scifx files] > scifx.cpp")
|
||||
sys.exit(-1)
|
||||
|
||||
print("""
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// NB: This file is AUTO-GENERATED by devtools/sci/scifx/scifx_to_cpp.py
|
||||
// from devtools/sci/scifx/*.scifx
|
||||
|
||||
#include "sci/graphics/helpers.h"
|
||||
#include "sci/graphics/screen.h"
|
||||
|
||||
namespace Sci {
|
||||
""")
|
||||
input_files = sys.argv[1:]
|
||||
gids = []
|
||||
|
||||
for F in input_files:
|
||||
comments = []
|
||||
pics = []
|
||||
views = []
|
||||
mods = [(1.,1.,1.)]
|
||||
gid = ""
|
||||
|
||||
for l in open(F, "r").readlines():
|
||||
l = l.strip()
|
||||
if len(l) == 0:
|
||||
continue
|
||||
if l[0] == '#':
|
||||
comment = l[1:].strip()
|
||||
# Only add the top comments (before the game ID is set)
|
||||
if (gid == ""):
|
||||
comments.append(comment)
|
||||
continue
|
||||
if l[0:6] == "gameid":
|
||||
assert(gid == "")
|
||||
l = l[6:].strip()
|
||||
l = l.strip()
|
||||
assert(l[0] == "=")
|
||||
assert(l[-1] == ";")
|
||||
l = l[1:-1].strip()
|
||||
gid = l
|
||||
continue
|
||||
if l[0:4] == "view":
|
||||
ruletype = "view"
|
||||
l = l[4:]
|
||||
elif l[0:3] == "pic":
|
||||
ruletype = "pic"
|
||||
l = l[3:]
|
||||
else:
|
||||
assert(False)
|
||||
|
||||
ids = []
|
||||
loops = [-1]
|
||||
cels = [-1]
|
||||
l,ids = ParseList(l)
|
||||
if l[0] == "(":
|
||||
l,loops = ParseList(l)
|
||||
if l[0] == "(":
|
||||
l,cels = ParseList(l)
|
||||
l = l.strip()
|
||||
assert(l[0:2] == "*=")
|
||||
assert(l[-1] == ";")
|
||||
l = l[2:-1].strip()
|
||||
if l[0] == "(":
|
||||
val = ParseTriple(l)
|
||||
val = (float(v) for v in val)
|
||||
else:
|
||||
val = (float(l), float(l), float(l))
|
||||
if ruletype == "pic":
|
||||
for pic in ids:
|
||||
pics.append([pic, ModToIndex(mods, val)])
|
||||
elif ruletype == "view":
|
||||
for view in ids:
|
||||
for loop in loops:
|
||||
for cel in cels:
|
||||
views.append([view, loop, cel, ModToIndex(mods, val)])
|
||||
|
||||
if gid == "":
|
||||
raise ValueError("No gameid specified")
|
||||
|
||||
gids.append(gid)
|
||||
|
||||
PrintMods(gid, mods)
|
||||
print()
|
||||
PrintPic(gid, pics, comments)
|
||||
print()
|
||||
PrintView(gid, views, comments)
|
||||
print()
|
||||
|
||||
print("static const SciFxMod mods[] = {")
|
||||
for gid in gids:
|
||||
print("\t{{ gid_{0}, paletteMods{0}, ARRAYSIZE(paletteMods{0}), picMods{0}, ARRAYSIZE(picMods{0}), viewMods{0}, ARRAYSIZE(viewMods{0}) }},".format(gid));
|
||||
print("};")
|
||||
|
||||
print("""
|
||||
void setupCustomPaletteMods(GfxScreen *screen) {
|
||||
for (int i = 0; i < ARRAYSIZE(mods); i++) {
|
||||
if (mods[i].gameId == g_sci->getGameId()) {
|
||||
screen->setPaletteMods(mods[i].paletteMods, mods[i].paletteModsSize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void doCustomViewPalette(GfxScreen *screen, GuiResourceId view, int16 loop, int16 cel) {
|
||||
for (int i = 0; i < ARRAYSIZE(mods); i++) {
|
||||
SciFxMod mod = mods[i];
|
||||
if (mod.gameId == g_sci->getGameId()) {
|
||||
for (int j = 0; j < mod.viewModsSize; j++) {
|
||||
ViewMod m = mod.viewMods[j];
|
||||
if (m.id == view && (m.loop == -1 || m.loop == loop) && (m.cel == -1 || m.cel == cel)) {
|
||||
screen->setCurPaletteMapValue(m.multiplier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void doCustomPicPalette(GfxScreen *screen, GuiResourceId pic) {
|
||||
for (int i = 0; i < ARRAYSIZE(mods); i++) {
|
||||
SciFxMod mod = mods[i];
|
||||
if (mod.gameId == g_sci->getGameId()) {
|
||||
for (int j = 0; j < mod.picModsSize; j++) {
|
||||
PicMod m = mod.picMods[j];
|
||||
if (m.id == pic) {
|
||||
screen->setCurPaletteMapValue(m.multiplier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}""")
|
||||
83
devtools/sci/scifx/sq3.scifx
Normal file
83
devtools/sci/scifx/sq3.scifx
Normal file
@@ -0,0 +1,83 @@
|
||||
# SQ3 per-resource palette configuration
|
||||
# Copyright (C) 2006 Matt Hargett
|
||||
|
||||
gameid = SQ3;
|
||||
|
||||
# ego
|
||||
view(0,8,11,12,14,68,17,22..26,32,35, 751, 289, 288, 261, 260, 257, 213, 199, 193, 192, 138, 137, 134, 109, 110, 113, 114, 117, 122, 123,100, 99, 97, 95, 89, 88, 87, 85, 84, 82, 76, 68, 63, 104 ) *= 1.25 ;
|
||||
view(136) *= 1.15;
|
||||
view(106)(4,5,9) *= 1.25;
|
||||
view(105)(0,1) *= 1.25;
|
||||
# ego on garbage lifter -- lighten but not so as to make the lifter be obviously weird
|
||||
view(13)(0)(2) *= 1.15 ;
|
||||
view(31) *= 1.15;
|
||||
view(15)(3)(0) *= 1.25 ;
|
||||
view(16,19)(0) *= 1.25;
|
||||
view(57)(5..6) *= 1.25 ;
|
||||
view(21)(1) *= 1.25 ;
|
||||
# ego's shadow
|
||||
view(7,18) *= 0.5;
|
||||
view(6..8,18) *= 0.9;
|
||||
view(901) *= 1.25;
|
||||
view(751) *= 1.25;
|
||||
view(750)(1) *= 1.25;
|
||||
view(92)(4) *= 1.25;
|
||||
view(83)(0) *= 1.25;
|
||||
view(83)(1)(2) *=1.15;
|
||||
view(83)(2)(2) *=1.15;
|
||||
view(78)(3) *= 1.25;
|
||||
view(64)(2,3) *= 1.25;
|
||||
# ego's hands controlling robot
|
||||
pic(96) *= 1.15;
|
||||
# peeking at scumsoft
|
||||
pic(81,82) *= 1.15;
|
||||
#lifted by robot
|
||||
pic(430) *= 1.15;
|
||||
|
||||
# computer controls
|
||||
view(40,41,42,149,146,141,151,152) *= 0.8;
|
||||
view(70,2) *= 0.9;
|
||||
pic(17,18,162..164,170,180,191,300) *= 0.75;
|
||||
|
||||
# title screen
|
||||
view(900) *= 0.9;
|
||||
pic(1) *= 0.9 ;
|
||||
pic(926) *= 0.9;
|
||||
|
||||
# humans(?)
|
||||
view(593,93,103,131..133,210,130,115) *= 1.2;
|
||||
pic(117) *=1.15;
|
||||
view(116)(1..2) *= 1.2;
|
||||
|
||||
#ships, planets, and robots
|
||||
view(39) *= 0.9;
|
||||
view(1) *= 0.75;
|
||||
pic(205..209,112..115) *= 0.9;
|
||||
pic(60..72) *= 0.9;
|
||||
pic(153) *= 0.8;
|
||||
view(96) *= 0.9;
|
||||
pic(690) *= 0.9;
|
||||
view(77)(0..2) *= 0.7;
|
||||
view(259) *= 1.15;
|
||||
|
||||
|
||||
# in the garbage scow
|
||||
pic(1..20) *= 0.75 ;
|
||||
pic(157) *= 0.6;
|
||||
view(20)(0) *= 0.5;
|
||||
# rats
|
||||
view(15)(0,1) *= 0.6;
|
||||
view(34) *= 0.6;
|
||||
|
||||
# guys from andromeda
|
||||
view(128) *= 0.9;
|
||||
view(601, 602) *= 0.9;
|
||||
|
||||
# misc text bubbles, effects, etc
|
||||
view(94) *= 1.1;
|
||||
view(91, 73) *= 1.5;
|
||||
view(57)(3,4) *= 1.5;
|
||||
view(15)(4) *= 1.5;
|
||||
view(64)(0) *= 1.5;
|
||||
view(71)(8) *= 1.5;
|
||||
view(10)(6) *= 1.5;
|
||||
204
devtools/sci/scipack.cpp
Normal file
204
devtools/sci/scipack.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sciresource.h>
|
||||
#include <resource.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define COPY_BLOCK_SIZE 512
|
||||
|
||||
unsigned short *resource_ids = NULL;
|
||||
|
||||
void
|
||||
help() {
|
||||
printf("Usage:\n\tscipack <file_0> ... <file_n>\n"
|
||||
"\nBuilds an uncompressed SCI0 resource.000 and a resource.map\n");
|
||||
}
|
||||
|
||||
int /* Returns resource ID on success, -1 on error */
|
||||
test_file(char *filename) {
|
||||
char *dot = strchr(filename, '.');
|
||||
char *endptr;
|
||||
FILE *f;
|
||||
int res_type, res_index;
|
||||
|
||||
if (!dot) {
|
||||
fprintf(stderr, "Must contain a period");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*dot = 0;
|
||||
|
||||
for (res_type = 0; res_type < sci_invalid_resource
|
||||
&& scumm_stricmp(filename, sci_resource_types[res_type]); res_type++);
|
||||
|
||||
*dot = '.';
|
||||
|
||||
if (res_type == sci_invalid_resource) {
|
||||
fprintf(stderr, "Invalid resource type");
|
||||
return -1;
|
||||
}
|
||||
|
||||
++dot;
|
||||
res_index = strtol(dot, &endptr, 10);
|
||||
|
||||
if (!*dot || *endptr) {
|
||||
fprintf(stderr, "Invalid resource index");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (res_index < 0) {
|
||||
fprintf(stderr, "Negative resource index");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (res_index >= 1000) {
|
||||
fprintf(stderr, "Resource index too large");
|
||||
return -1;
|
||||
}
|
||||
|
||||
f = fopen(filename, "r");
|
||||
if (!f) {
|
||||
perror("While asserting file");
|
||||
return -1;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
return (res_type << 11) | res_index;
|
||||
}
|
||||
|
||||
int
|
||||
build_file_ids(int count, char **names) {
|
||||
int i;
|
||||
int error = 0;
|
||||
|
||||
resource_ids = (unsigned short*) malloc(sizeof(unsigned short) * count);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
int id = test_file(names[i]);
|
||||
if (id < 0) {
|
||||
error = -1;
|
||||
fprintf(stderr, ": %s\n", names[i]);
|
||||
} else resource_ids[i] = id;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
write_uint16(int fd, unsigned int uint) {
|
||||
unsigned char upper = (uint >> 8) & 0xff;
|
||||
unsigned char lower = (uint) & 0xff;
|
||||
|
||||
if ((write(fd, &upper, 1) < 1)
|
||||
|| (write(fd, &lower, 1) < 1)) {
|
||||
perror("While writing");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
write_files(int count, char **names) {
|
||||
int resource_000, resource_map;
|
||||
int i;
|
||||
|
||||
resource_000 = creat("resource.000", 0644);
|
||||
if (resource_000 < 0) {
|
||||
perror("While creating 'resource.000'");
|
||||
return -1;
|
||||
}
|
||||
|
||||
resource_map = creat("resource.map", 0644);
|
||||
if (resource_map < 0) {
|
||||
perror("While creating 'resource.map'");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
int fd = open(names[i], O_RDONLY);
|
||||
struct stat fdstat;
|
||||
int fdsize;
|
||||
unsigned char buf[512];
|
||||
int j;
|
||||
long offset = lseek(resource_000, SEEK_CUR, 0);
|
||||
int top_offset = (offset >> 16) & 0xffff;
|
||||
int bot_offset = offset & 0xffff;
|
||||
|
||||
if (fd < 0) {
|
||||
perror(names[i]);
|
||||
return -1;
|
||||
}
|
||||
fstat(fd, &fdstat);
|
||||
fdsize = fdstat.st_size;
|
||||
|
||||
write_uint16(resource_000, resource_ids[i]);
|
||||
write_uint16(resource_000, fdsize);
|
||||
write_uint16(resource_000, fdsize);
|
||||
write_uint16(resource_000, 0);
|
||||
|
||||
do {
|
||||
j = read(fd, buf, COPY_BLOCK_SIZE);
|
||||
write(resource_000, buf, j);
|
||||
} while (j == COPY_BLOCK_SIZE);
|
||||
close(fd);
|
||||
|
||||
write_uint16(resource_map, resource_ids[i]);
|
||||
write_uint16(resource_map, bot_offset);
|
||||
write_uint16(resource_map, top_offset);
|
||||
}
|
||||
|
||||
/* Terminate resource 000 */
|
||||
write_uint16(resource_000, 0);
|
||||
|
||||
/* Terminate resource map */
|
||||
write_uint16(resource_map, 0xffff);
|
||||
write_uint16(resource_map, 0xffff);
|
||||
|
||||
close(resource_000);
|
||||
close(resource_map);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
printf("scipack.c Copyright (C) 2002 Christoph Reichenbach\n"
|
||||
"This program is FREE SOFTWARE. You may copy it and/or re-distribute it\n"
|
||||
"according to the terms of the GNU General Public License. See LICENSING\n"
|
||||
"for details.\n");
|
||||
|
||||
if (argc < 1)
|
||||
help();
|
||||
|
||||
if (build_file_ids(argc - 1, argv + 1))
|
||||
return -1;
|
||||
|
||||
if (write_files(argc - 1, argv + 1))
|
||||
return -1;
|
||||
free(resource_ids);
|
||||
}
|
||||
131
devtools/sci/scitrace.asm
Normal file
131
devtools/sci/scitrace.asm
Normal file
@@ -0,0 +1,131 @@
|
||||
; ScummVM - Graphic Adventure Engine
|
||||
;
|
||||
; ScummVM is the legal property of its developers, whose names
|
||||
; are too numerous to list here. Please refer to the COPYRIGHT
|
||||
; file distributed with this source distribution.
|
||||
;
|
||||
; 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
;
|
||||
;---------------------------------------------------------------------------
|
||||
;
|
||||
; SCITRACE
|
||||
; TSR for logging specific calls inside sierra sci
|
||||
; Written by M. Kiewitz
|
||||
;
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
; Simply replace 51h 51h 51h 51h in sierra sci with
|
||||
; CDh 90h 90h 90h. This code will then log copyrect calls to scitrace.bin
|
||||
|
||||
.286
|
||||
|
||||
code_seg segment public
|
||||
assume cs:code_seg, ds:nothing, es:nothing
|
||||
org 00100h
|
||||
|
||||
scitrace: jmp install_my_prog
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
filename: db 'SCITRACE.BIN', 0
|
||||
|
||||
inthandler: push ax
|
||||
push bx
|
||||
push cx
|
||||
push dx
|
||||
push ds
|
||||
push cs
|
||||
pop ds
|
||||
mov ah, 3Dh
|
||||
mov al, 1
|
||||
mov dx, offset filename
|
||||
xor cl, cl
|
||||
int 21h
|
||||
pop ds
|
||||
jc int_error
|
||||
mov bx, ax
|
||||
mov ax, 4202h
|
||||
xor cx, cx
|
||||
xor dx, dx
|
||||
int 21h
|
||||
mov dx, si
|
||||
mov ah, 40h
|
||||
mov cx, 8
|
||||
int 21h
|
||||
mov ah, 3Eh
|
||||
int 21h
|
||||
int_error: pop dx
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
movsw
|
||||
movsw
|
||||
movsw
|
||||
movsw
|
||||
iret
|
||||
|
||||
end_of_tsr:
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
titlestr: db 'SCITRACE - written by M. Kiewitz',13,10,'$'
|
||||
errorfile: db 'error creating file',13,10,'$'
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
install_my_prog:
|
||||
push cs
|
||||
pop ds
|
||||
mov ah, 09h
|
||||
mov dx, offset titlestr
|
||||
int 21h
|
||||
|
||||
mov ah, 3Ch
|
||||
mov cx, 0
|
||||
mov dx, offset filename
|
||||
int 21h
|
||||
jnc valid_open
|
||||
mov ah, 09h
|
||||
mov dx, offset errorfile
|
||||
int 21h
|
||||
mov ax, 6200h
|
||||
int 21h
|
||||
mov es, bx
|
||||
mov ax, 4C00h
|
||||
int 21h
|
||||
|
||||
valid_open: mov bx, ax
|
||||
mov ah, 3Eh
|
||||
int 21h
|
||||
|
||||
NowInstallTSR:
|
||||
mov ax, 2590h
|
||||
mov dx, offset inthandler
|
||||
int 21h ; int 90h pointer <- ds:dx
|
||||
|
||||
mov ax, ds:[002ch] ; get envt segment
|
||||
mov es, ax
|
||||
mov ax, 4900h
|
||||
int 21h
|
||||
|
||||
mov dx, offset end_of_tsr
|
||||
add dx, 15
|
||||
shr dx, 4
|
||||
mov ax, 3100h
|
||||
int 21h
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
code_seg ends
|
||||
end scitrace
|
||||
Reference in New Issue
Block a user