diff options
-rw-r--r-- | simon/simon.cpp | 4787 | ||||
-rw-r--r-- | simon/simon.h | 133 | ||||
-rw-r--r-- | simon/simondebug.cpp | 731 | ||||
-rw-r--r-- | simon/simonitems.cpp | 1371 | ||||
-rw-r--r-- | simon/simonsys.cpp | 50 | ||||
-rw-r--r-- | simon/simonverb.cpp | 423 | ||||
-rw-r--r-- | simon/simonvga.cpp | 1836 |
7 files changed, 4471 insertions, 4860 deletions
diff --git a/simon/simon.cpp b/simon/simon.cpp index e85ef2d3d8..fd32c45176 100644 --- a/simon/simon.cpp +++ b/simon/simon.cpp @@ -19,23 +19,9 @@ * */ - #include "stdafx.h" -#include "scummsys.h" -#include "system.h" -#include "../sound/mixer.h" #include "simon.h" - -#ifndef _WIN32_WCE -#include <errno.h> -#endif -#include <time.h> -#ifdef WIN32 -#include <malloc.h> -#endif -#include <sys/stat.h> - int sdl_mouse_x, sdl_mouse_y; byte *sdl_buf_3; @@ -44,85 +30,22 @@ byte *sdl_buf_attached; SimonState *g_simon; +SimonState *SimonState::create(OSystem *syst, MidiDriver *driver) { + SimonState *s = new SimonState; -static const GameSpecificSettings simon1_settings = { - 1, /* VGA_DELAY_BASE */ - 1576/4, /* TABLE_INDEX_BASE */ - 1460/4, /* TEXT_INDEX_BASE */ - 1700/4, /* NUM_GAME_OFFSETS */ - 64, /* NUM_VIDEO_OP_CODES */ - 1000000, /* VGA_MEM_SIZE */ - 50000, /* TABLES_MEM_SIZE */ - 3624, /* NUM_VOICE_RESOURCES */ - 141, /* NUM_EFFECT_RESOURCES */ - 1316/4, /* MUSIC_INDEX_BASE */ - 0, /* SOUND_INDEX_BASE */ - "SIMON.GME", /* gme_filename */ - "SIMON.WAV", /* wav_filename */ - "SIMON.VOC", /* wav_filename2 */ - "EFFECTS.VOC", /* effects_filename */ - "GAMEPC", /* gamepc_filename */ -}; - -static const GameSpecificSettings simon2_settings = { - 5, /* VGA_DELAY_BASE */ - 1580/4, /* TABLE_INDEX_BASE */ - 1500/4, /* TEXT_INDEX_BASE */ - 2116/4, /* NUM_GAME_OFFSETS */ - 75, /* NUM_VIDEO_OP_CODES */ - 2000000, /* VGA_MEM_SIZE */ - 100000, /* TABLES_MEM_SIZE */ - 12256, /* NUM_VOICE_RESOURCES */ - 0, - 1128/4, /* MUSIC_INDEX_BASE */ - 1660/4, /* SOUND_INDEX_BASE */ - "SIMON2.GME", /* gme_filename */ - "SIMON2.WAV", /* wav_filename */ - NULL, - "", - "GSPTR30", /* gamepc_filename */ -}; - -static const GameSpecificSettings simon2win_settings = { - 5, /* VGA_DELAY_BASE */ - 1580/4, /* TABLE_INDEX_BASE */ - 1500/4, /* TEXT_INDEX_BASE */ - 2116/4, /* NUM_GAME_OFFSETS */ - 75, /* NUM_VIDEO_OP_CODES */ - 2000000, /* VGA_MEM_SIZE */ - 100000, /* TABLES_MEM_SIZE */ - 12256, /* NUM_VOICE_RESOURCES */ - 0, - 1128/4, /* MUSIC_INDEX_BASE */ - 1660/4, /* SOUND_INDEX_BASE */ - "SIMON2.GME", /* gme_filename */ - "SIMON2.WAV", /* wav_filename */ - NULL, - "", - "GSPTR30", /* gamepc_filename */ -}; + s->_system = syst; -static const GameSpecificSettings simon2dos_settings = { - 5, /* VGA_DELAY_BASE */ - 1580/4, /* TABLE_INDEX_BASE */ - 1500/4, /* TEXT_INDEX_BASE */ - 2116/4, /* NUM_GAME_OFFSETS */ - 75, /* NUM_VIDEO_OP_CODES */ - 2000000, /* VGA_MEM_SIZE */ - 100000, /* TABLES_MEM_SIZE */ - 12256, /* NUM_VOICE_RESOURCES */ - 0, - 1128/4, /* MUSIC_INDEX_BASE */ - 1660/4, /* SOUND_INDEX_BASE */ - "SIMON2.GME", /* gme_filename */ - "SIMON2.WAV", /* wav_filename */ - NULL, - "", - "GAME32", /* gamepc_filename */ -}; + /* Setup midi driver */ + s->midi.set_driver(driver); + + /* Setup mixer */ + if (!s->_mixer->bind_to_system(syst)) + warning("Sound initialization failed. " + "Features of the game that depend on sound synchronization will most likely break"); + return s; -#define NUM_PALETTE_FADEOUT 32 +} void palette_fadeout(uint32 *pal_values,uint num) { byte *p = (byte*)pal_values; @@ -135,54 +58,6 @@ void palette_fadeout(uint32 *pal_values,uint num) { } while (--num); } - -uint fileReadItemID(FILE *in) { - uint32 val = fileReadBE32(in); - if (val==0xFFFFFFFF) - return 0; - return val + 2; -} - - -/* debug code */ -void SimonState::show_it(void *buf) { - _system->copy_rect((byte*)buf, 320, 0, 0, 320, 200); - _system->update_screen(); -} - -FILE *SimonState::fopen_maybe_lowercase(const char *filename) { - FILE *in; - char buf[256], dotbuf[256], *e; - const char *s = _game_path; - - strcpy(buf, s); strcat(buf, filename); - strcpy(dotbuf, buf); strcat(dotbuf, "."); // '.' appended version - // for dumb vfat drivers - - /* original filename */ - in = fopen(buf, "rb"); - if (in) return in; - - /* lowercase original filename */ - e = buf + strlen(s); do *e = tolower(*e); while(*e++); - in = fopen(buf, "rb"); - if (in) return in; - - if (strchr(buf, '.')) - return NULL; - - /* dot appended original filename */ - in = fopen(dotbuf, "rb"); - if (in) return in; - - /* lowercase dot appended */ - e = dotbuf + strlen(s); do *e = tolower(*e); while(*e++); - in = fopen(dotbuf, "rb"); - - return in; -} - - byte *SimonState::allocateItem(uint size) { byte *org = _itemheap_ptr; size = (size + 3) & ~3; @@ -317,234 +192,6 @@ void SimonState::setupLocalStringTable(byte *mem, int num) { } } -void SimonState::readGamePcText(FILE *in) { - uint text_size; - byte *text_mem; - - _text_size = text_size = fileReadBE32(in); - text_mem = (byte*)malloc(text_size); - if (text_mem == NULL) - error("Out of text memory"); - - fread(text_mem, text_size, 1, in); - - setupStringTable(text_mem, _stringtab_num); -} - -void SimonState::readItemChildren(FILE *in, Item *item, uint tmp) { - if (tmp == 1) { - uint fr1 = fileReadBE16(in); - uint fr2 = fileReadBE16(in); - uint i, size; - uint j, k; - Child1 *child; - - size = CHILD1_SIZE; - for(i=0,j=fr2; i!=6; i++, j>>=2) - if (j&3) - size += sizeof(child->array[0]); - - child = (Child1*)allocateChildBlock(item, 1, size); - child->subroutine_id = fr1; - child->fr2 = fr2; - - for(i=k=0,j=fr2; i!=6; i++, j>>=2) - if (j&3) - child->array[k++] = (uint16)fileReadItemID(in); - } else if (tmp == 2) { - uint32 fr = fileReadBE32(in); - uint i,k,size; - Child2 *child; - - size = CHILD2_SIZE; - for(i=0; i!=16; i++) - if (fr & (1<<i)) - size += sizeof(child->array[0]); - - child = (Child2*)allocateChildBlock(item, 2, size); - child->avail_props = fr; - - k = 0; - if (fr & 1) { - child->array[k++] = (uint16)fileReadBE32(in); - } - for(i=1; i!=16; i++) - if(fr & (1<<i)) - child->array[k++] = fileReadBE16(in); - - child->string_id = (uint16)fileReadBE32(in); - } else { - error("readItemChildren: invalid mode"); - } -} - - -void SimonState::readItemFromGamePc(FILE *in, Item *item) { - uint32 tmp; - - item->unk2 = fileReadBE16(in); - item->unk1 = fileReadBE16(in); - item->unk3 = fileReadBE16(in); - item->sibling = (uint16)fileReadItemID(in); - item->child = (uint16)fileReadItemID(in); - item->parent = (uint16)fileReadItemID(in); - fileReadBE16(in); - item->unk4 = fileReadBE16(in); - item->children = NULL; - - tmp = fileReadBE32(in); - while (tmp) { - tmp = fileReadBE16(in); - if (tmp != 0) - readItemChildren(in, item, tmp); - } -} - - -static const char * const opcode_arg_table_simon1win[256] = { -" ","I ","I ","I ","I ","I ","I ","II ","II ","II ","II ","B ","B ","BN ","BN ","BN ", -"BN ","BB ","BB ","BB ","BB ","II ","II ","N ","I ","I ","I ","IN ","IB ","II ","I ","I ", -"II ","II ","IBB ","BIB ","BB ","B ","BI ","IB ","B ","B ","BN ","BN ","BN ","BB ","BB ","BN ", -"BN ","BB ","BB ","BN ","BB ","BN ","B ","I ","IB ","IB ","II ","I ","I ","IN ","B ","T ", -"T ","NNNNNB ","BT ","BTS ","T "," ","B ","N ","IBN ","I ","I ","I ","NN "," "," ","IT ", -"II ","I ","B "," ","IB ","IBB ","IIB ","T "," "," ","IB ","IB ","IB ","B ","BB ","IBB ", -"NB ","N ","NBNNN ","N "," ","BNNNNNN ","B "," ","B ","B ","BB ","NNNNNIN ","N ","N ","N ","NNN ", -"NBNN ","IBNN ","IB ","IB ","IB ","IB ","N ","N ","N ","BI "," "," ","N ","I ","IBB ","NN ", -"N ","N ","Ban ","BB "," "," "," "," ","IB ","B "," ","II "," ","BI ","N ","I ", -"IB ","IB ","IB ","IB ","IB ","IB ","IB ","BI ","BB ","B ","B ","B ","B ","IBB ","IBN ","IB ", -"B ","BNBN ","BBTS ","N "," ","Ian ","B ","B ","B ","B ","T ","T ","B "," ","I "," ", -" ","BBI ","NNBB ","BBB "," "," "," "," ","N ","N "," "," ", -}; - -static const char * const opcode_arg_table_simon1dos[256] = { -" ","I ","I ","I ","I ","I ","I ","II ","II ","II ","II ","B ","B ","BN ","BN ","BN ", -"BN ","BB ","BB ","BB ","BB ","II ","II ","N ","I ","I ","I ","IN ","IB ","II ","I ","I ", -"II ","II ","IBB ","BIB ","BB ","B ","BI ","IB ","B ","B ","BN ","BN ","BN ","BB ","BB ","BN ", -"BN ","BB ","BB ","BN ","BB ","BN ","B ","I ","IB ","IB ","II ","I ","I ","IN ","B ","T ", -"T ","NNNNNB ","BT ","BT ","T "," ","B ","N ","IBN ","I ","I ","I ","NN "," "," ","IT ", -"II ","I ","B "," ","IB ","IBB ","IIB ","T "," "," ","IB ","IB ","IB ","B ","BB ","IBB ", -"NB ","N ","NBNNN ","N "," ","BNNNNNN ","B "," ","B ","B ","BB ","NNNNNIN ","N ","N ","N ","NNN ", -"NBNN ","IBNN ","IB ","IB ","IB ","IB ","N ","N ","N ","BI "," "," ","N ","I ","IBB ","NN ", -"N ","N ","Ban ","BB "," "," "," "," ","IB ","B "," ","II "," ","BI ","N ","I ", -"IB ","IB ","IB ","IB ","IB ","IB ","IB ","BI ","BB ","B ","B ","B ","B ","IBB ","IBN ","IB ", -"B ","BNBN ","BBT ","N "," ","Ian ","B ","B ","B ","B ","T ","T ","B "," ","I "," ", -" ","BBI ","NNBB ","BBB "," "," "," "," ","N ","N "," "," ", -}; - -static const char * const opcode_arg_table_simon2win[256] = { -" ","I ","I ","I ","I ","I ","I ","II ","II ","II ","II ","B ","B ","BN ","BN ","BN ", -"BN ","BB ","BB ","BB ","BB ","II ","II ","N ","I ","I ","I ","IN ","IB ","II ","I ","I ", -"II ","II ","IBB ","BIB ","BB ","B ","BI ","IB ","B ","B ","BN ","BN ","BN ","BB ","BB ","BN ", -"BN ","BB ","BB ","BN ","BB ","BN ","B ","I ","IB ","IB ","II ","I ","I ","IN ","B ","T ", -"T ","NNNNNB ","BT ","BTS ","T "," ","B ","N ","IBN ","I ","I ","I ","NN "," "," ","IT ", -"II ","I ","B "," ","IB ","IBB ","IIB ","T "," "," ","IB ","IB ","IB ","B ","BB ","IBB ", -"NB ","N ","NNBNNN ","NN "," ","BNNNNNN ","B "," ","B ","B ","BB ","NNNNNIN ","N ","N ","N ","NNN ", -"NBNN ","IBNN ","IB ","IB ","IB ","IB ","N ","N ","N ","BI "," "," ","N ","I ","IBB ","NNB ", -"N ","N ","Ban ","BB "," "," "," "," ","IB ","B "," ","II "," ","BI ","N ","I ", -"IB ","IB ","IB ","IB ","IB ","IB ","IB ","BI ","BB ","B ","B ","B ","B ","IBB ","IBN ","IB ", -"B ","BNBN ","BBTS ","N "," ","Ian ","B ","B ","B ","B ","T ","T ","B "," ","I "," ", -" ","BBI ","NNBB ","BBB "," "," "," "," ","N ","N "," "," ","BT "," ","B "}; - -static const char * const opcode_arg_table_simon2dos[256] = { -" ","I ","I ","I ","I ","I ","I ","II ","II ","II ","II ","B ","B ","BN ","BN ","BN ", -"BN ","BB ","BB ","BB ","BB ","II ","II ","N ","I ","I ","I ","IN ","IB ","II ","I ","I ", -"II ","II ","IBB ","BIB ","BB ","B ","BI ","IB ","B ","B ","BN ","BN ","BN ","BB ","BB ","BN ", -"BN ","BB ","BB ","BN ","BB ","BN ","B ","I ","IB ","IB ","II ","I ","I ","IN ","B ","T ", -"T ","NNNNNB ","BT ","BT ","T "," ","B ","N ","IBN ","I ","I ","I ","NN "," "," ","IT ", -"II ","I ","B "," ","IB ","IBB ","IIB ","T "," "," ","IB ","IB ","IB ","B ","BB ","IBB ", -"NB ","N ","NNBNNN ","NN "," ","BNNNNNN ","B "," ","B ","B ","BB ","NNNNNIN ","N ","N ","N ","NNN ", -"NBNN ","IBNN ","IB ","IB ","IB ","IB ","N ","N ","N ","BI "," "," ","N ","I ","IBB ","NNB ", -"N ","N ","Ban ","BB "," "," "," "," ","IB ","B "," ","II "," ","BI ","N ","I ", -"IB ","IB ","IB ","IB ","IB ","IB ","IB ","BI ","BB ","B ","B ","B ","B ","IBB ","IBN ","IB ", -"B ","BNBN ","BBT ","N "," ","Ian ","B ","B ","B ","B ","T ","T ","B "," ","I "," ", -" ","BBI ","NNBB ","BBB "," "," "," "," ","N ","N "," "," ","BT "," ","B "}; - - -/* read_single_opcode */ -byte *SimonState::readSingleOpcode(FILE *in, byte *ptr) { - int i,l; - const char *string_ptr; - uint val; - - const char * const *table; - - switch(_game) { - case GAME_SIMON1WIN: table = opcode_arg_table_simon1win; break; - case GAME_SIMON2DOS: table = opcode_arg_table_simon2win; printf("right opcode table\n"); break; - case GAME_SIMON2WIN: table = opcode_arg_table_simon2win; break; - case GAME_SIMON1DOS: table = opcode_arg_table_simon1dos; break; - default: - error("Invalid game specified"); - } - - i = 0; - - string_ptr = table[*ptr++]; - if (!string_ptr) - error("Unable to locate opcode table. Perhaps you are using the wrong game target?"); - - for(;;) { - if (string_ptr[i] == ' ') - return ptr; - - l = string_ptr[i++]; - switch(l) { - case 'N': - case 'S': - case 'a': - case 'n': - case 'p': - case 'v': - val = fileReadBE16(in); - *ptr++ = val >> 8; - *ptr++ = val & 255; - break; - - case 'B': - *ptr++ = fileReadByte(in); - if (ptr[-1] == 0xFF) { - *ptr++ = fileReadByte(in); - } - break; - - case 'I': - val = fileReadBE16(in); - switch(val) { - case 1: val = 0xFFFF; break; - case 3: val = 0xFFFD; break; - case 5: val = 0xFFFB; break; - case 7: val = 0xFFF9; break; - case 9: val = 0xFFF7; break; - default: - val = fileReadItemID(in);; - } - *ptr++ = val >> 8; - *ptr++ = val & 255; - break; - - case 'T': - val = fileReadBE16(in); - switch(val) { - case 0: - val = 0xFFFF; - break; - case 3: - val = 0xFFFD; - break; - default: - val = (uint16)fileReadBE32(in); - break; - } - *ptr++ = val >> 8; - *ptr++ = val & 255; - break; - - default: - error("Bad cmd table entry %c", l); - } - } -} - void SimonState::readSubroutineLine(FILE *in, SubroutineLine *sl, Subroutine *sub) { byte line_buffer[1024], *q = line_buffer; int size; @@ -626,63 +273,6 @@ void SimonState::readSubroutineBlock(FILE *in) { } } -bool SimonState::loadGamePcFile(const char *filename) { - FILE *in; - int num_inited_objects; - int i, file_size; - - /* read main gamepc file */ - in = fopen_maybe_lowercase(filename); - if (in==NULL) return false; - - num_inited_objects = allocGamePcVars(in); - - allocItem1(); - loginPlayer(); - readGamePcText(in); - - for(i=2; i<num_inited_objects; i++) { - readItemFromGamePc(in, _itemarray_ptr[i]); - } - - readSubroutineBlock(in); - - fclose(in); - - /* Read list of TABLE resources */ - in = fopen_maybe_lowercase("TBLLIST"); - if (in==NULL) return false; - - fseek(in, 0, SEEK_END); - file_size = ftell(in); - - _tbl_list = (byte*)malloc(file_size); - if (_tbl_list == NULL) - error("Out of memory for strip table list"); - fseek(in, 0, SEEK_SET); - fread(_tbl_list, file_size, 1, in); - fclose(in); - - /* Remember the current state */ - _subroutine_list_org = _subroutine_list; - _tablesheap_ptr_org = _tablesheap_ptr; - _tablesheap_curpos_org = _tablesheap_curpos; - - /* Read list of TEXT resources */ - in = fopen_maybe_lowercase("STRIPPED.TXT"); - if (in==NULL) return false; - - fseek(in, 0, SEEK_END); - file_size = ftell(in); - _stripped_txt_mem = (byte*)malloc(file_size); - if (_stripped_txt_mem == NULL) - error("Out of memory for strip text list"); - fseek(in, 0, SEEK_SET); - fread(_stripped_txt_mem, file_size, 1, in); - fclose(in); - - return true; -} Child *SimonState::findChildOfType(Item *i, uint type) { Child *child = i->children; @@ -723,7 +313,6 @@ uint SimonState::getOffsetOfChild2Param(Child2 *child, uint prop) { return offset; } - Child *SimonState::allocateChildBlock(Item *i, uint type, uint size) { Child *child = (Child*)allocateItem(size); child->next = i->children; @@ -748,1181 +337,6 @@ void SimonState::setItemUnk3(Item *item, int value) { item->unk3 = value; } -int SimonState::startSubroutine(Subroutine *sub) { - int result = -1; - SubroutineLine *sl; - byte *old_code_ptr; - -// warning("startSubroutine(%d)", sub->id); -#ifdef DUMP_START_MAINSCRIPT - dumpSubroutine(sub); -#endif - - old_code_ptr = _code_ptr; - - if (++_recursion_depth > 40) - error("Recursion error"); - - sl = (SubroutineLine*)((byte*)sub + sub->first); - - while ((byte*)sl != (byte*)sub) { - if (checkIfToRunSubroutineLine(sl, sub)) { - result = 0; - _code_ptr = (byte*)sl; - if (sub->id) _code_ptr += 2; else _code_ptr += 8; - -#ifdef DUMP_CONTINOUS_MAINSCRIPT - fprintf(_dump_file,"; %d\n", sub->id); -#endif - result = runScript(); - if (result != 0) { - /* result -10 means restart subroutine */ - if (result == -10) { - delay(0); /* maybe leave control to the VGA */ - sl = (SubroutineLine*)((byte*)sub + sub->first); - continue; - } - break; - } - } - sl = (SubroutineLine*)((byte*)sub + sl->next); - } - - _code_ptr = old_code_ptr; - - _recursion_depth--; - return result; -} - -int SimonState::startSubroutineEx(Subroutine *sub) { - _item_1_ptr = _item_1; - return startSubroutine(sub); -} - -bool SimonState::checkIfToRunSubroutineLine(SubroutineLine *sl, Subroutine *sub) { - if (sub->id) - return true; - - if (sl->cond_a != -1 && sl->cond_a != _script_cond_a && - (sl->cond_a != -2 || _script_cond_a != -1)) - return false; - - if (sl->cond_b != -1 && sl->cond_b != _script_cond_b && - (sl->cond_b != -2 || _script_cond_b != -1)) - return false; - - if (sl->cond_c != -1 && sl->cond_c != _script_cond_c && - (sl->cond_c != -2 || _script_cond_c != -1)) - return false; - - return true; -} - -int SimonState::runScript() { - byte opcode; - bool flag, condition; - - do { -#ifdef DUMP_CONTINOUS_MAINSCRIPT - dumpOpcode(_code_ptr); -#endif - - opcode = getByte(); - if (opcode==0xFF) - return 0; - - if (_run_script_return_1) - return 1; - - /* Invert condition? */ - flag = false; - if (opcode==0) { - flag = true; - opcode = getByte(); - if (opcode==0xFF) - return 0; - } - - condition = true; - - switch(opcode) { - case 1: { /* ptrA parent is */ - condition = (getItem1Ptr()->parent == getNextItemID()); - } break; - - case 2: { /* ptrA parent is not */ - condition = (getItem1Ptr()->parent != getNextItemID()); - } break; - - case 5: { /* parent is 1 */ - condition = (getNextItemPtr()->parent == getItem1ID()); - } break; - - case 6: { /* parent isnot 1 */ - condition = (getNextItemPtr()->parent != getItem1ID()); - } break; - - case 7: { /* parent is */ - Item *item = getNextItemPtr(); - condition = (item->parent == getNextItemID()); - } break; - - case 11: { /* is zero */ - condition = (getNextVarContents() == 0); - } break; - - case 12: { /* isnot zero */ - condition = (getNextVarContents() != 0); - } break; - - case 13: { /* equal */ - uint tmp = getNextVarContents(); - condition = (tmp == getVarOrWord()); - } break; - - case 14: { /* not equal */ - uint tmp = getNextVarContents(); - condition = (tmp != getVarOrWord()); - } break; - - case 15: { /* is greater */ - uint tmp = getNextVarContents(); - condition = (tmp > getVarOrWord()); - } break; - - case 16: { /* is less */ - uint tmp = getNextVarContents(); - condition = (tmp < getVarOrWord()); - } break; - - case 17: { /* is eq f */ - uint tmp = getNextVarContents(); - condition = (tmp == getNextVarContents()); - } break; - - case 18: { /* is not equal f */ - uint tmp = getNextVarContents(); - condition = (tmp != getNextVarContents()); - } break; - - case 19: { /* is greater f */ - uint tmp = getNextVarContents(); - condition = (tmp < getNextVarContents()); - } break; - - case 20: { /* is less f */ - uint tmp = getNextVarContents(); - condition = (tmp > getNextVarContents()); - } break; - - case 23: { - condition = o_unk_23(getVarOrWord()); - } break; - - case 25: { /* has child of type 1 */ - condition = hasChildOfType1(getNextItemPtr()); - } break; - - case 26: { /* has child of type 2 */ - condition = hasChildOfType2(getNextItemPtr()); - } break; - - case 27: { /* item unk3 is */ - Item *item = getNextItemPtr(); - condition = ((uint)item->unk3 == getVarOrWord()); - } break; - - case 28: { /* item has prop */ - Child2 *child = findChildOfType2(getNextItemPtr()); - byte num = getVarOrByte(); - condition = child!=NULL && (child->avail_props & (1<<num)) != 0; - } break; - - case 31: { /* set no parent */ - setItemParent(getNextItemPtr(), NULL); - } break; - - case 33: { /* set item parent */ - Item *item = getNextItemPtr(); - setItemParent(item, getNextItemPtr()); - } break; - - case 36: { /* copy var */ - uint value = getNextVarContents(); - writeNextVarContents(value); - } break; - - case 41: { /* zero var */ - writeNextVarContents(0); - } break; - - case 42: { /* set var */ - uint var = getVarOrByte(); - writeVariable(var, getVarOrWord()); - } break; - - case 43: { /* add */ - uint var = getVarOrByte(); - writeVariable(var, readVariable(var) + getVarOrWord()); - } break; - - case 44: { /* sub */ - uint var = getVarOrByte(); - writeVariable(var, readVariable(var) - getVarOrWord()); - } break; - - case 45: { /* add f */ - uint var = getVarOrByte(); - writeVariable(var, readVariable(var) + getNextVarContents()); - } break; - - case 46: { /* sub f */ - uint var = getVarOrByte(); - writeVariable(var, readVariable(var) - getNextVarContents()); - } break; - - case 47: { /* mul */ - uint var = getVarOrByte(); - writeVariable(var, readVariable(var) * getVarOrWord()); - } break; - - case 48: { /* div */ - uint var = getVarOrByte(); - int value = getVarOrWord(); - if (value == 0) - error("Division by zero in div"); - writeVariable(var, readVariable(var) / value); - } break; - - case 49: { /* mul f */ - uint var = getVarOrByte(); - writeVariable(var, readVariable(var) * getNextVarContents()); - } break; - - case 50: { /* div f */ - uint var = getVarOrByte(); - int value = getNextVarContents(); - if (value == 0) - error("Division by zero in div f"); - writeVariable(var, readVariable(var) / value); - } break; - - case 51: { /* mod */ - uint var = getVarOrByte(); - int value = getVarOrWord(); - if (value == 0) - error("Division by zero in mod"); - writeVariable(var, readVariable(var) % value); - } break; - - case 52: { /* mod f */ - uint var = getVarOrByte(); - int value = getNextVarContents(); - if (value == 0) - error("Division by zero in mod f"); - writeVariable(var, readVariable(var) % value); - } break; - - case 53: { /* random */ - uint var = getVarOrByte(); - uint value = (uint16)getVarOrWord(); - uint rand_value; - - for(;;) { - uint value_2 = value; - rand_value = rand() & 0x7FFF; - - if (value == 0) - error("Invalid random range"); - - value = 0x8000 / value; - - if (value == 0) - error("Invalid random range"); - - if (rand_value / value != value_2) - break; - - value = value_2; - } - - writeVariable(var, rand_value / value); - } break; - - case 55: { /* set itemA parent */ - setItemParent(getItem1Ptr(), getNextItemPtr()); - } break; - - case 56: { /* set child2 fr bit */ - Child2 *child = findChildOfType2(getNextItemPtr()); - int value = getVarOrByte(); - if (child != NULL && value >= 0x10) - child->avail_props |= 1<<value; - } break; - - case 57: { /* clear child2 fr bit */ - Child2 *child = findChildOfType2(getNextItemPtr()); - int value = getVarOrByte(); - if (child != NULL && value >= 0x10) - child->avail_props &= ~(1<<value); - } break; - - case 58: { /* make siblings */ - Item *item = getNextItemPtr(); - setItemParent(item, derefItem(getNextItemPtr()->parent)); - } break; - - case 59: { /* item inc unk3 */ - Item *item = getNextItemPtr(); - if (item->unk3<=30000) - setItemUnk3(item, item->unk3 + 1); - } break; - - case 60: { /* item dec unk3 */ - Item *item = getNextItemPtr(); - if (item->unk3>=0) - setItemUnk3(item, item->unk3 - 1); - } break; - - case 61: { /* item set unk3 */ - Item *item = getNextItemPtr(); - int value = getVarOrWord(); - if (value<0) value = 0; - if (value>30000) value = 30000; - setItemUnk3(item, value); - } break; - - case 62: { /* show int */ - showMessageFormat("%d", getNextVarContents()); - } break; - - case 63: { /* show string nl */ - showMessageFormat("%s\n", getStringPtrByID(getNextStringID())); - } break; - - case 64: { /* show string */ - showMessageFormat("%s", getStringPtrByID(getNextStringID())); - } break; - - case 65: { /* add hit area */ - int id = getVarOrWord(); - int x = getVarOrWord(); - int y = getVarOrWord(); - int w = getVarOrWord(); - int h = getVarOrWord(); - int number = getVarOrByte(); - if (number < 20) - addNewHitArea(id, x, y, w, h, (number<<8) + 129, 0xD0, &_dummy_item_2); - } break; - - case 66: { /* set array 2 */ - uint var = getVarOrByte(); - uint string_id = getNextStringID(); - if (var < 20) - _stringid_array_2[var] = string_id; - } break; - - case 67: { /* set array 3 and 4 */ - if (_game == GAME_SIMON1WIN || _game&GAME_SIMON2) { - uint var = getVarOrByte(); - uint string_id = getNextStringID(); - uint value = getNextWord(); - if (var < 20) { - _stringid_array_3[var] = string_id; - _array_4[var] = value; - } - } else { - uint var = getVarOrByte(); - uint string_id = getNextStringID(); - if (var < 20) { - _stringid_array_3[var] = string_id; - } - } - } break; - - case 68: { /* exit interpreter */ - error("Exit interpreter opcode"); - } break; - - case 69: { /* return 1 */ - return 1; - } - - case 70: { /* show string from array */ - const char *str = (const char*)getStringPtrByID(_stringid_array_3[getVarOrByte()]); - - if (_game & GAME_SIMON2) { - writeVariable(51, strlen(str)/53 * 8 + 8); - } - - showMessageFormat("%s\n", str); - } break; - - case 71: { /* start subroutine */ - Subroutine *sub = getSubroutineByID(getVarOrWord()); - if (sub != NULL) - startSubroutine(sub); - } break; - - case 76: { /* add event */ - uint timeout = getVarOrWord(); - addTimeEvent(timeout, getVarOrWord()); - } break; - - case 77: { /* has item minus 1 */ - condition = _subject_item != NULL; - } break; - - case 78: { /* has item minus 3 */ - condition = _object_item != NULL; - } break; - - case 79: { /* childstruct fr2 is */ - Child2 *child = findChildOfType2(getNextItemPtr()); - uint string_id = getNextStringID(); - condition = (child != NULL) && child->string_id == string_id; - } break; - - case 80: { /* item equal */ - condition = getNextItemPtr() == getNextItemPtr(); - } break; - - case 82: { /* dummy opcode? */ - getVarOrByte(); - } break; - - case 83: { /* restart subroutine */ - return -10; - } - - case 87: { /* dummy opcode? */ - getNextStringID(); - } break; - - case 88: { /* or_lock_word */ - _lock_word |= 0x10; - } break; - - case 89: { /* and lock word */ - _lock_word &= ~0x10; - } break; - - case 90: { /* set minusitem to parent */ - Item *item = derefItem(getNextItemPtr()->parent); - switch(getVarOrByte()) { - case 0: - _object_item = item; - break; - case 1: - _subject_item = item; - break; - default: - error("set minusitem to parent, invalid subcode"); - } - } break; - - case 91: { /* set minusitem to sibling */ - Item *item = derefItem(getNextItemPtr()->sibling); - switch(getVarOrByte()) { - case 0: - _object_item = item; - break; - case 1: - _subject_item = item; - break; - default: - error("set minusitem to sibling, invalid subcode"); - } - } break; - - case 92: { /* set minusitem to child */ - Item *item = derefItem(getNextItemPtr()->child); - switch(getVarOrByte()) { - case 0: - _object_item = item; - break; - case 1: - _subject_item = item; - break; - default: - error("set minusitem to child, invalid subcode"); - } - } break; - - case 96: { - uint val = getVarOrWord(); - o_set_video_mode(getVarOrByte(), val); - } break; - - case 97: { /* load vga */ - ensureVgaResLoadedC(getVarOrWord()); - } break; - - case 98: { - if (!(_game & GAME_SIMON2)) { - uint a = getVarOrWord(); - uint b = getVarOrByte(); - uint c = getVarOrWord(); - uint d = getVarOrWord(); - uint f = getVarOrWord(); - start_vga_code(b, a/100, a, c, d, f); - } else { - uint a = getVarOrWord(); - uint b = getVarOrWord(); - uint c = getVarOrByte(); - uint d = getVarOrWord(); - uint e = getVarOrWord(); - uint f = getVarOrWord(); - start_vga_code(c,a,b,d,e,f); - } - } break; - - case 99: { - if (!(_game & GAME_SIMON2)) { - o_unk_99_simon1(getVarOrWord()); - } else { - uint a = getVarOrWord(); - uint b = getVarOrWord(); - o_unk_99_simon2(a,b); - } - } break; - - case 100: { - o_vga_reset(); - } break; - - case 101: { - uint a = getVarOrByte(); - uint b = getVarOrWord(); - uint c = getVarOrWord(); - uint d = getVarOrWord(); - uint e = getVarOrWord(); - uint f = getVarOrWord(); - uint g = getVarOrWord(); - o_unk26_helper(a, b, c, d, e, f, g, 0); - } break; - - case 102: { - fcs_unk_2(getVarOrByte() & 7); - } break; - - case 103: { - o_unk_103(); - } break; - - case 104: { - fcs_delete(getVarOrByte() & 7); - } break; - - case 107: { /* ADD_ITEM_HITAREA(id,x,y,w,h,item,unk3) */ - uint flags = 0; - uint id = getVarOrWord(); - uint params = id / 1000; - uint x,y,w,h,unk3; - Item *item; - - id = id % 1000; - - if (params & 1) flags |= 8; - if (params & 2) flags |= 4; - if (params & 4) flags |= 0x80; - if (params & 8) flags |= 1; - if (params & 16) flags |= 0x10; - - x = getVarOrWord(); - y = getVarOrWord(); - w = getVarOrWord(); - h = getVarOrWord(); - item = getNextItemPtrStrange(); - unk3 = getVarOrWord(); - if (x >= 1000) { - unk3 += 0x4000; - x -= 1000; - } - addNewHitArea(id, x, y, w, h, flags, unk3, item); - } break; - - case 108: { /* delete hitarea */ - delete_hitarea(getVarOrWord()); - } break; - - case 109: { /* clear hitarea bit 0x40 */ - clear_hitarea_bit_0x40(getVarOrWord()); - } break; - - case 110: { /* set hitarea bit 0x40 */ - set_hitarea_bit_0x40(getVarOrWord()); - } break; - - case 111: { /* set hitarea xy */ - uint hitarea_id = getVarOrWord(); - uint x = getVarOrWord(); - uint y = getVarOrWord(); - set_hitarea_x_y(hitarea_id, x, y); - } break; - - case 114: { - Item *item = getNextItemPtr(); - uint fcs_index = getVarOrByte(); - lock(); - fcs_unk_proc_1(fcs_index, item, 0, 0); - unlock(); - } break; - - case 115: { /* item has flag */ - Item *item = getNextItemPtr(); - condition = (item->unk4 & (1 << getVarOrByte())) != 0; - } break; - - case 116: { /* item set flag */ - Item *item = getNextItemPtr(); - item->unk4 |= (1 << getVarOrByte()); - } break; - - case 117: { /* item clear flag */ - Item *item = getNextItemPtr(); - item->unk4 &= ~(1 << getVarOrByte()); - } break; - - case 119: { /* WAIT_VGA */ - uint var = getVarOrWord(); - _scriptvar_2 = (var==200); - - if (var!=200 || !_skip_vga_wait) - o_wait_for_vga(var); - _skip_vga_wait = false; - } break; - - case 120: { - o_unk_120(getVarOrWord()); - } break; - - case 121: { /* SET_VGA_ITEM */ - uint slot = getVarOrByte(); - _vc_item_array[slot] = getNextItemPtr(); - } break; - - case 125: { /* item is sibling with item 1 */ - Item *item = getNextItemPtr(); - condition = (getItem1Ptr()->parent == item->parent); - } break; - - case 126: { - Item *item = getNextItemPtr(); - uint fcs_index = getVarOrByte(); - uint a = 1<<getVarOrByte(); - lock(); - fcs_unk_proc_1(fcs_index, item, 1, a); - unlock(); - } break; - - case 127: { /* deals with music */ - o_unk_127(); - } break; - - case 128: { /* dummy instruction? */ - getVarOrWord(); - } break; - - case 129: { /* dummy instruction? */ - getVarOrWord(); - condition = true; - } break; - - case 130: { /* set script cond */ - uint a = getVarOrByte(); - if (a == 1) { - getNextWord(); - _script_cond_b = getNextWord(); - } else { - getNextWord(); - _script_cond_c = getNextWord(); - } - } break; - - case 132: { - o_save_game(); - } break; - - case 133: { - o_load_game(); - } break; - - case 134: { - warning("stopMidiMusic: not implemented"); - /* dummy proc */ - } break; - - case 135: { - error("Quit if user presses Y unimplemented"); - } break; - - case 136: { /* set var to item unk3 */ - Item *item = getNextItemPtr(); - writeNextVarContents(item->unk3); - } break; - - case 137: { - o_unk_137(getVarOrByte()); - } break; - - case 138: { - o_unk_138(); - } break; - - case 139: { /* SET_PARENT_SPECIAL */ - Item *item = getNextItemPtr(); - _no_parent_notify = true; - setItemParent(item, getNextItemPtr()); - _no_parent_notify = false; - } break; - - case 140: { - killAllTimers(); - addTimeEvent(3, 0xA0); - } break; - - case 141: { - uint which = getVarOrByte(); - Item *item = getNextItemPtr(); - if(which == 1) { - _subject_item = item; - } else { - _object_item = item; - } - } break; - - case 142: { - condition = is_hitarea_0x40_clear(getVarOrWord()); - } break; - - case 143: { /* start item sub */ - Child1 *child = findChildOfType1(getNextItemPtr()); - if (child != NULL) { - Subroutine *sub = getSubroutineByID(child->subroutine_id); - if (sub) - startSubroutine(sub); - } - } break; - - case 151: { /* set array6 to item */ - uint var = getVarOrByte(); - Item *item = getNextItemPtr(); - _item_array_6[var] = item; - } break; - - case 152: { /* set m1 or m3 to array6 */ - Item *item = _item_array_6[getVarOrByte()]; - uint var = getVarOrByte(); - if (var==1) { - _subject_item = item; - } else { - _object_item = item; - } - } break; - - case 153: { /* set bit */ - uint bit = getVarOrByte(); - _bit_array[bit>>4] |= 1<<(bit&15); - break; - } - - case 154: { /* clear bit */ - uint bit = getVarOrByte(); - _bit_array[bit>>4] &= ~(1<<(bit&15)); - break; - } - - case 155: { /* is bit clear? */ - uint bit = getVarOrByte(); - condition = (_bit_array[bit>>4] & (1<<(bit&15))) == 0; - } break; - - case 156: { /* is bit set? */ - uint bit = getVarOrByte(); - condition = (_bit_array[bit>>4] & (1<<(bit&15))) != 0; - } break; - - case 157: { /* get item int prop */ - Item *item = getNextItemPtr(); - Child2 *child = findChildOfType2(item); - uint prop = getVarOrByte(); - - if (child != NULL && child->avail_props&(1<<prop) && prop < 16) { - uint offs = getOffsetOfChild2Param(child, 1<<prop); - writeNextVarContents(child->array[offs]); - } else { - writeNextVarContents(0); - } - } break; - - case 158: { /* set item prop */ - Item *item = getNextItemPtr(); - Child2 *child = findChildOfType2(item); - uint prop = getVarOrByte(); - int value = getVarOrWord(); - - if (child != NULL && child->avail_props&(1<<prop) && prop < 16) { - uint offs = getOffsetOfChild2Param(child, 1<<prop); - child->array[offs] = value; - } - } break; - - case 160: { - o_unk_160(getVarOrByte()); - } break; - - case 161: { /* setup text */ - uint value = getVarOrByte(); - ThreeValues *tv; - - switch(value) { - case 1: tv = &_threevalues_1; break; - case 2: tv = &_threevalues_2; break; - case 101: tv = &_threevalues_3; break; - case 102: tv = &_threevalues_4; break; - default: - error("setup text, invalid value %d", value); - } - - tv->a = getVarOrWord(); - tv->b = getVarOrByte(); - tv->c = getVarOrWord(); - } break; - - case 162: { - o_print_str(); - } break; - - case 163: { - o_unk_163(getVarOrWord()); - } break; - - case 164: { - _show_preposition = true; - o_setup_cond_c(); - _show_preposition = false; - } break; - - case 165: { - Item *item = getNextItemPtr(); - int16 a = getNextWord(), - b = getNextWord(); - condition = (item->unk2 == a && item->unk1 == b); - } break; - - case 166: { /* set bit2 */ - uint bit = getVarOrByte(); - _bit_array[(bit>>4)+16] |= 1<<(bit&15); - } break; - - case 167: { /* clear bit2 */ - uint bit = getVarOrByte(); - _bit_array[(bit>>4)+16] &= ~(1<<(bit&15)); - } break; - - case 168: { /* is bit clear? */ - uint bit = getVarOrByte(); - condition = (_bit_array[(bit>>4)+16] & (1<<(bit&15))) == 0; - } break; - - case 169: { /* is bit set? */ - uint bit = getVarOrByte(); - condition = (_bit_array[(bit>>4)+16] & (1<<(bit&15))) != 0; - } break; - - case 175: { - o_unk_175(); - } break; - - case 176: { - o_unk_176(); - } break; - - case 177: { - o_177(); - } break; - - case 178: { /* path find */ - uint a = getVarOrWord(); - uint b = getVarOrWord(); - uint c = getVarOrByte(); - uint d = getVarOrByte(); - o_pathfind(a,b,c,d); - } break; - - case 179: { - if (_game == GAME_SIMON1WIN) { - uint b = getVarOrByte(); - /*uint c = */getVarOrByte(); - uint a = getVarOrByte(); - uint d = _array_4[a]; - if (d!=0) - talk_with_speech(d, b); - } else if (_game == GAME_SIMON1DOS) { - uint b = getVarOrByte(); - uint c = getVarOrByte(); - uint a = getVarOrByte(); - const char *s = (const char*)getStringPtrByID(_stringid_array_3[a]); - ThreeValues *tv; - - switch(b) { - case 1: tv = &_threevalues_1; break; - case 2: tv = &_threevalues_2; break; - case 101: tv = &_threevalues_3; break; - case 102: tv = &_threevalues_4; break; - default: - error("setup text, invalid value %d", b); - } - - talk_with_text(b, c, s, tv->a, tv->b, tv->c); - } else if (_game == GAME_SIMON2WIN || _game == GAME_SIMON2DOS) { - uint b = getVarOrByte(); - uint c = getVarOrByte(); - uint a = getVarOrByte(); - uint d; - const char *s = (const char*)getStringPtrByID(_stringid_array_3[a]); - ThreeValues *tv; - - switch(b) { - case 1: tv = &_threevalues_1; break; - case 2: tv = &_threevalues_2; break; - case 101: tv = &_threevalues_3; break; - case 102: tv = &_threevalues_4; break; - default: - error("setup text, invalid value %d", b); - } - - d = _array_4[a]; - if (d!=0 && !_vk_t_toggle) - talk_with_speech(d, b); - - if (s!=NULL && _vk_t_toggle) - talk_with_text(b, c, s, tv->a, tv->b, tv->c); - } - } break; - - case 180: { - o_force_unlock(); - } break; - - case 181: { - o_force_lock(); - if (_game == GAME_SIMON2WIN || _game == GAME_SIMON2DOS) { - fcs_unk_2(1); - showMessageFormat("\xC"); - } - } break; - - case 182: { - if (_game & GAME_SIMON2) goto invalid_opcode; - o_read_vgares_328(); - } break; - - case 183: { - if (_game & GAME_SIMON2) goto invalid_opcode; - o_read_vgares_23(); - } break; - - case 184: { - o_clear_vgapointer_entry(getVarOrWord()); - } break; - - case 185: { - if (_game & GAME_SIMON2) goto invalid_opcode; - getVarOrWord(); - } break; - - case 186: { - o_unk_186(); - } break; - - case 187: { - if (_game & GAME_SIMON2) goto invalid_opcode; - o_fade_to_black(); - } break; - - case 188: - if (!(_game & GAME_SIMON2)) goto invalid_opcode; - { - uint i = getVarOrByte(); - uint str = getNextStringID(); - condition = (str<20 && _stringid_array_2[i] == str); - } break; - - case 189: { - if (!(_game & GAME_SIMON2)) goto invalid_opcode; - _op_189_flags = 0; - } break; - - case 190: { - uint i; - if (!(_game & GAME_SIMON2)) goto invalid_opcode; - i = getVarOrByte(); - if (!(_op_189_flags&(1<<i))) - o_190_helper(i); - } break; - - default: -invalid_opcode:; - error("Invalid opcode '%d'", opcode); - } - - } while (condition != flag); - - return 0; -} - -void SimonState::o_190_helper(uint i) { - warning("o_190_helper not implemented"); -} - - -bool SimonState::o_unk_23(uint a) { - if (a == 0) - return 0; - - if (a == 100) - return 1; - - a += _script_unk_1; - if (a<=0) { - _script_unk_1 = 0; - return 0; - } - - if (((uint)(rand()>>5))%100 < a) { - if (_script_unk_1 <= 0) - _script_unk_1 -= 5; - else - _script_unk_1 = 0; - return 1; - } - - if (_script_unk_1 >= 0) - _script_unk_1 += 5; - else - _script_unk_1 = 0; - - return 0; -} - -void SimonState::o_177() { - if (_game == GAME_SIMON1WIN) { - uint a = getVarOrByte(); - /*uint b = */getVarOrByte(); - uint offs; - Child2 *child = findChildOfType2(getNextItemPtr()); - if (child != NULL && child->avail_props&0x200) { - offs = getOffsetOfChild2Param(child, 0x200); - talk_with_speech(child->array[offs], a); - } else if (child != NULL && child->avail_props&0x100) { - offs = getOffsetOfChild2Param(child, 0x100); - talk_with_speech(child->array[offs]+3550, a); - } - } else if (_game == GAME_SIMON1DOS) { - uint a = getVarOrByte(); - uint b = getVarOrByte(); - Child2 *child = findChildOfType2(getNextItemPtr()); - if (child!=NULL && child->avail_props&1) { - const char *s = (const char*)getStringPtrByID(child->array[0]); - ThreeValues *tv; - char buf[256]; - switch(a) { - case 1: tv = &_threevalues_1; break; - case 2: tv = &_threevalues_2; break; - case 101: tv = &_threevalues_3; break; - case 102: tv = &_threevalues_4; break; - default: - error("setup text, invalid value %d", a); - } - - if (child->avail_props&0x100) { - uint x = getOffsetOfChild2Param(child,0x100); - sprintf(buf,"%d%s",child->array[x],s); - s = buf; - } - - talk_with_text(a,b,s,tv->a, tv->b,tv->c); - } - } else if (_game == GAME_SIMON2WIN || _game == GAME_SIMON2DOS) { - uint a = getVarOrByte(); - uint b = getVarOrByte(); - Child2 *child = findChildOfType2(getNextItemPtr()); - const char *s = NULL; - ThreeValues *tv = NULL; - char buf[256]; - - if (child != NULL && child->avail_props&1) { - s = (const char*)getStringPtrByID(child->array[0]); - switch(a) { - case 1: tv = &_threevalues_1; break; - case 2: tv = &_threevalues_2; break; - case 101: tv = &_threevalues_3; break; - case 102: tv = &_threevalues_4; break; - default: - error("setup text, invalid value %d", a); - } - } - - if (child != NULL && child->avail_props&0x200) { - uint var200 = child->array[getOffsetOfChild2Param(child, 0x200)]; - - if (child->avail_props&0x100) { - uint var100 = child->array[getOffsetOfChild2Param(child, 0x100)]; - - if (var200 == 116) var200 = var100 + 115; - if (var200 == 92) var200 = var100 + 98; - if (var200 == 99) var200 = 9; - if (var200 == 97) { - switch(var100) { - case 12: var200 = 109; break; - case 14: var200 = 108; break; - case 18: var200 = 107; break; - case 20: var200 = 106; break; - case 22: var200 = 105; break; - case 28: var200 = 104; break; - case 90: var200 = 103; break; - case 92: var200 = 102; break; - case 100: var200 = 51; break; - default: - error("o_177: invalid case %d", var100); - } - } - } - - if (!_vk_t_toggle) - talk_with_speech(var200, a); - } - - if (!_vk_t_toggle) - return; - - if (child==NULL || !(child->avail_props&1)) - return; - - if (child->avail_props&0x100) { - sprintf(buf, "%d%s", child->array[getOffsetOfChild2Param(child, 0x100)], s); - s = buf; - } - - talk_with_text(a,b,s,tv->a, tv->b,tv->c); - } -} - - -void SimonState::o_unk_137(uint fcs_index) { - FillOrCopyStruct *fcs; - - fcs = _fcs_ptr_array_3[fcs_index & 7]; - if (fcs->fcs_data == NULL) - return; - fcs_unk_proc_1(fcs_index, fcs->fcs_data->item_ptr, fcs->fcs_data->unk1, fcs->fcs_data->unk2); -} - -byte SimonState::getByte() { - return *_code_ptr++; -} int SimonState::getNextWord() { _code_ptr += 2; @@ -2533,404 +947,6 @@ void SimonState::startSubroutine170() { _run_script_return_1 = true; } -void SimonState::defocusHitarea() { - HitArea *last; - HitArea *ha; - - if ((_game == GAME_SIMON2WIN) || (_game == GAME_SIMON2DOS)) { - if (_bit_array[4]&0x8000) { - o_unk_120(202); - _last_hitarea_2_ptr = NULL; - return; - } - } - - last = _hitarea_ptr_5; - - if (last == _hitarea_ptr_7) - return; - - hitareaChangedHelper(); - _hitarea_ptr_7 = last; - - if (last != NULL && _hitarea_unk_6 && - (ha = findHitAreaByID(200)) && (ha->flags&0x40) && - !(last->flags&0x40)) - focusVerb(last->id); -} - -static const char * const verb_names[] = { - "Walk to", - "Look at", - "Open", - "Move", - - "Consume", - "Pick up", - "Close", - "Use", - - "Talk to", - "Remove", - "Wear", - "Give" -}; - -static const char * const verb_prep_names[] = { - "","","","", - "","","","with what ?", - "","","","to whom ?" -}; - -void SimonState::focusVerb(uint hitarea_id) { - uint x; - const char *txt; - - hitarea_id -= 101; - - CHECK_BOUNDS(hitarea_id, verb_prep_names); - - if (_show_preposition) { - txt = verb_prep_names[hitarea_id]; - } else { - txt = verb_names[hitarea_id]; - } - x = (53 - strlen(txt)) * 3; - showActionString(x, (const byte*)txt); - -} - -void SimonState::showActionString(uint x, const byte *string) { - FillOrCopyStruct *fcs; - - fcs = _fcs_ptr_array_3[1]; - if (fcs == NULL || fcs->text_color==0) - return; - - fcs->unk1 = x >> 3; - fcs->unk3 = x & 7; - - for(;*string;string++) - video_putchar(fcs, *string); -} - - -void SimonState::hitareaChangedHelper() { - FillOrCopyStruct *fcs; - - if ((_game == GAME_SIMON2WIN) || (_game == GAME_SIMON2WIN)) { - if (_bit_array[4]&0x8000) - return; - } - - fcs = _fcs_ptr_array_3[1]; - if (fcs != NULL && fcs->text_color != 0) - video_fill_or_copy_from_3_to_2(fcs); - - _last_hitarea_2_ptr = NULL; - _hitarea_ptr_7 = NULL; -} - -HitArea *SimonState::findHitAreaByID(uint hitarea_id) { - HitArea *ha = _hit_areas; - uint count = ARRAYSIZE(_hit_areas); - - do{ - if (ha->id == hitarea_id) - return ha; - } while(ha++,--count); - return NULL; -} - -HitArea *SimonState::findEmptyHitArea() { - HitArea *ha = _hit_areas; - uint count = ARRAYSIZE(_hit_areas); - - do{ - if (ha->flags == 0) - return ha; - } while(ha++,--count); - return NULL; -} - -void SimonState::clear_hitarea_bit_0x40(uint hitarea) { - HitArea *ha = findHitAreaByID(hitarea); - if (ha != NULL) - ha->flags &= ~0x40; -} - -void SimonState::set_hitarea_bit_0x40(uint hitarea) { - HitArea *ha = findHitAreaByID(hitarea); - if (ha != NULL) { - ha->flags |= 0x40; - ha->flags &= ~2; - if (hitarea == 102) - hitarea_proc_1(); - } -} - -void SimonState::set_hitarea_x_y(uint hitarea, int x, int y) { - HitArea *ha = findHitAreaByID(hitarea); - if (ha != NULL) { - ha->x = x; - ha->y = y; - } -} - -void SimonState::delete_hitarea(uint hitarea) { - HitArea *ha = findHitAreaByID(hitarea); - if (ha != NULL) { - ha->flags = 0; - if (ha == _last_hitarea_2_ptr) - defocusHitarea(); - _need_hitarea_recalc++; - } -} - -bool SimonState::is_hitarea_0x40_clear(uint hitarea) { - HitArea *ha = findHitAreaByID(hitarea); - if (ha == NULL) - return false; - return (ha->flags & 0x40) == 0; -} - -void SimonState::addNewHitArea(int id, int x, int y, int width, int height, - int flags, int unk3,Item *item_ptr) { - - HitArea *ha; - delete_hitarea(id); - - ha = findEmptyHitArea(); - ha->x = x; - ha->y = y; - ha->width = width; - ha->height = height; - ha->flags = flags | 0x20; - ha->id = ha->layer = id; - ha->unk3 = unk3; - ha->item_ptr = item_ptr; - - _need_hitarea_recalc++; -} - -void SimonState::hitarea_proc_1() { - uint id; - HitArea *ha; - - if (_game & GAME_SIMON2) { - id=2; - if (!(_bit_array[4]&0x8000)) - id = (_mouse_y >= 136) ? 102 : 101; - } else { - id = (_mouse_y >= 136) ? 102 : 101; - - } - - _hitarea_unk_4 = id; - - ha = findHitAreaByID(id); - if (ha == NULL) - return; - - if (ha->flags & 0x40) { - _hitarea_unk_4 = 999; - _hitarea_ptr_5 = NULL; - } else { - _verb_hitarea = ha->unk3; - handle_verb_hitarea(ha); - } -} - -void SimonState::handle_verb_hitarea(HitArea *ha) { - HitArea *tmp = _hitarea_ptr_5; - - if (ha == tmp) - return; - - if (!(_game & GAME_SIMON2)) { - if (tmp != NULL) { - tmp->flags |= 8; - video_toggle_colors(tmp, 0xd5, 0xd0, 0xd5, 0xA); - } - - if (ha->flags & 2) - video_toggle_colors(ha, 0xda, 0xd5, 0xd5, 5); - else - video_toggle_colors(ha, 0xdf, 0xda, 0xda, 0xA); - - ha->flags &= ~ (2 + 8); - - } else { - if (ha->id<101) - return; - _mouse_cursor = ha->id - 101; - _need_hitarea_recalc++; - - } - - _hitarea_ptr_5 = ha; -} - -void SimonState::hitarea_leave(HitArea *ha) { - if (!(_game & GAME_SIMON2)) { - video_toggle_colors(ha, 0xdf, 0xd5, 0xda, 5); - } else { - video_toggle_colors(ha, 0xe7, 0xe5, 0xe6, 1); - } -} - -void SimonState::leaveHitAreaById(uint hitarea_id) { - HitArea *ha = findHitAreaByID(hitarea_id); - if (ha) - hitarea_leave(ha); -} - -void SimonState::handle_unk2_hitarea(FillOrCopyStruct *fcs) { - uint index; - - index = get_fcs_ptr_3_index(fcs); - - if (fcs->fcs_data->unk1 == 0) - return; - - lock(); - fcs_unk_proc_1(index, fcs->fcs_data->item_ptr, - fcs->fcs_data->unk1-1, fcs->fcs_data->unk2); - unlock(); -} - -void SimonState::handle_unk_hitarea(FillOrCopyStruct *fcs) { - uint index; - - index = get_fcs_ptr_3_index(fcs); - - lock(); - fcs_unk_proc_1(index, fcs->fcs_data->item_ptr, - fcs->fcs_data->unk1+1, fcs->fcs_data->unk2); - unlock(); -} - -void SimonState::setup_hitarea_from_pos(uint x, uint y, uint mode) { - HitArea *best_ha; - - if (_game & GAME_SIMON2) { - if (_bit_array[4]&0x8000 || y < 134) { - x += _x_scroll * 8; - } - } - - { - HitArea *ha = _hit_areas; - uint count = ARRAYSIZE(_hit_areas); - uint16 layer = 0; - const uint16 x_ = x; - const uint16 y_ = y; - - best_ha = NULL; - - do{ - if (ha->flags & 0x20) { - if (!(ha->flags & 0x40)) { - if (x_ >= ha->x && y_ >= ha->y && - x_ - ha->x < ha->width && y_- ha->y < ha->height && - layer <= ha->layer) { - layer = ha->layer; - best_ha = ha; - } else { - if (ha->flags & 2) { - hitarea_leave(ha); - ha->flags &=~2; - } - } - } else { - ha->flags &= ~2; - } - } - } while(ha++,--count); - } - - if (best_ha == NULL) { - defocusHitarea(); - return; - } - - if (mode != 0 && mode != 3) { - _last_hitarea = best_ha; - _variableArray[1] = x; - _variableArray[2] = y; - } - - if (best_ha->flags&4) { - defocusHitarea(); - } else if (best_ha != _last_hitarea_2_ptr) { - new_current_hitarea(best_ha); - } - - if (best_ha->flags&8 && !(best_ha->flags&2)) { - hitarea_leave(best_ha); - best_ha->flags |= 2; - } - - return; -} - -void SimonState::new_current_hitarea(HitArea *ha) { - bool result; - - hitareaChangedHelper(); - if (ha->flags & 1) { - result = hitarea_proc_2(ha->flags>>8); - } else { - result = hitarea_proc_3(ha->item_ptr); - } - - if (result) - _last_hitarea_2_ptr = ha; -} - -bool SimonState::hitarea_proc_2(uint a) { - uint x; - const byte *string_ptr; - - if (_game & GAME_SIMON2) { - if (_bit_array[4]&0x8000) { - Subroutine *sub; - _variableArray[84] = a; - sub = getSubroutineByID(5003); - if (sub != NULL) - startSubroutineEx(sub); - return true; - } - } - - if (a >= 20) - return false; - - string_ptr = getStringPtrByID(_stringid_array_2[a]); - x = (53 - (strlen((const char*)string_ptr) - 1)) * 3; - showActionString(x, string_ptr); - - return true; -} - -bool SimonState::hitarea_proc_3(Item *item) { - Child2 *child2; - uint x; - const byte *string_ptr; - - if (item == 0 || item==&_dummy_item_2 || item == &_dummy_item_3) - return false; - - child2 = findChildOfType2(item); - if (child2 == NULL) - return false; - - string_ptr = getStringPtrByID(child2->string_id); - x = (53 - (strlen((const char*)string_ptr) - 1)) * 3; - showActionString(x, string_ptr); - return true; -} - uint SimonState::get_fcs_ptr_3_index(FillOrCopyStruct *fcs) { uint i; @@ -2941,25 +957,6 @@ uint SimonState::get_fcs_ptr_3_index(FillOrCopyStruct *fcs) { error("get_fcs_ptr_3_index: not found"); } -/* Used only in Simon1 */ -void SimonState::o_read_vgares_328() { - if (_vga_res_328_loaded == false) { - _vga_res_328_loaded = true; - _lock_word |= 0x4000; - read_vga_from_datfile_1(328); - _lock_word &= ~0x4000; - } -} - -/* Used only in Simon1 */ -void SimonState::o_read_vgares_23() { - if (_vga_res_328_loaded == true) { - _vga_res_328_loaded = false; - _lock_word |= 0x4000; - read_vga_from_datfile_1(23); - _lock_word &= ~0x4000; - } -} void SimonState::lock() { @@ -3712,25 +1709,6 @@ void SimonState::vga_buf_unk_proc2(uint a, byte *end) { } } -void SimonState::o_unk_138() { - _vga_buf_start = _vga_buf_free_start; - _vga_file_buf_org = _vga_buf_free_start; -} - -void SimonState::o_unk_186() { - _vga_buf_free_start = _vga_file_buf_org_2; - _vga_buf_start = _vga_file_buf_org_2; - _vga_file_buf_org = _vga_file_buf_org_2; -} - -void SimonState::o_unk_175() { - _vga_buf_start = _vga_buf_free_start; -} - -void SimonState::o_unk_176() { - _vga_buf_free_start = _vga_file_buf_org; - _vga_buf_start = _vga_file_buf_org; -} void SimonState::o_clear_vgapointer_entry(uint a) { VgaPointersEntry *vpe; @@ -3879,1808 +1857,7 @@ void SimonState::set_video_mode(uint mode, uint vga_res_id) { -typedef void (SimonState::*VgaOpcodeProc)(); - -static const uint16 vc_get_out_of_code = 0; - -void SimonState::run_vga_script() { - static const VgaOpcodeProc vga_opcode_table[] = { - NULL, - &SimonState::vc_1, - &SimonState::vc_2, - &SimonState::vc_3, - &SimonState::vc_4, - &SimonState::vc_5, - &SimonState::vc_6_maybe_skip_3_inv, - &SimonState::vc_7_maybe_skip_3, - &SimonState::vc_8_maybe_skip_2, - &SimonState::vc_9_maybe_skip, - &SimonState::vc_10, - &SimonState::vc_11_clear_pathfind_array, - &SimonState::vc_12_sleep_variable, - &SimonState::vc_13_offset_x, - &SimonState::vc_14_offset_y, - &SimonState::vc_15_start_funkystruct_by_id, - &SimonState::vc_16_setup_funkystruct, - &SimonState::vc_17_set_pathfind_item, - &SimonState::vc_18_jump_rel, - &SimonState::vc_19, - &SimonState::vc_20, - &SimonState::vc_21, - &SimonState::vc_22, - &SimonState::vc_23_set_pri, - &SimonState::vc_24_set_image_xy, - &SimonState::vc_25_del_sprite_and_get_out, - &SimonState::vc_26, - &SimonState::vc_27_reset, - &SimonState::vc_28, - &SimonState::vc_29_stop_all_sounds, - &SimonState::vc_30_set_base_delay, - &SimonState::vc_31_set_palette_mode, - &SimonState::vc_32_copy_var, - &SimonState::vc_33, - &SimonState::vc_34, - &SimonState::vc_35, - &SimonState::vc_36, - &SimonState::vc_37_sprite_unk3_add, - &SimonState::vc_38_skip_if_var_zero, - &SimonState::vc_39_set_var, - &SimonState::vc_40_var_add, - &SimonState::vc_41_var_sub, - &SimonState::vc_42_delay_if_not_eq, - &SimonState::vc_43_skip_if_bit_clear, - &SimonState::vc_44_skip_if_bit_set, - &SimonState::vc_45_set_x, - &SimonState::vc_46_set_y, - &SimonState::vc_47_add_var_f, - &SimonState::vc_48, - &SimonState::vc_49_set_bit, - &SimonState::vc_50_clear_bit, - &SimonState::vc_51_clear_hitarea_bit_0x40, - &SimonState::vc_52, - &SimonState::vc_53_no_op, - &SimonState::vc_54_no_op, - &SimonState::vc_55_offset_hit_area, - &SimonState::vc_56_no_op, - &SimonState::vc_57_no_op, - &SimonState::vc_58, - &SimonState::vc_59, - &SimonState::vc_60, - &SimonState::vc_61_sprite_change, - &SimonState::vc_62, - &SimonState::vc_63, - - &SimonState::vc_64, - &SimonState::vc_65, - &SimonState::vc_66, - &SimonState::vc_67, - &SimonState::vc_68, - &SimonState::vc_69, - &SimonState::vc_70, - &SimonState::vc_71, - &SimonState::vc_72, - &SimonState::vc_73, - &SimonState::vc_74, - }; - - - for(;;) { - uint opcode; - -#ifdef DUMP_CONTINOUS_VGASCRIPT - if ((void*)_vc_ptr != (void*)&vc_get_out_of_code) { -// if (_vga_cur_sprite_id==62 && _vga_cur_file_id==68 || -// _vga_cur_sprite_id==1 && _vga_cur_file_id==2) { - fprintf(_dump_file,"%.5d %.5X: %5d %4d ", _vga_tick_counter, _vc_ptr -_cur_vga_file_1, _vga_cur_sprite_id, _vga_cur_file_id); - dump_video_script(_vc_ptr, true); -// } - } -#endif - - if (!(_game & GAME_SIMON2)) { - opcode = READ_BE_UINT16_UNALIGNED(_vc_ptr); - _vc_ptr += 2; - } else { - opcode = *_vc_ptr++; - } - - if (opcode >= gss->NUM_VIDEO_OP_CODES) - error("Invalid VGA opcode '%d' encountered", opcode); - - if (opcode == 0) - return; - - (this->*vga_opcode_table[opcode])(); - } -} - -int SimonState::vc_read_var_or_word() { - int16 var = vc_read_next_word(); - if (var < 0) - var = vc_read_var(-var); - return var; -} - -uint SimonState::vc_read_next_word() { - uint a = READ_BE_UINT16_UNALIGNED(_vc_ptr); - _vc_ptr += 2; - return a; -} - -uint SimonState::vc_read_next_byte() { - return *_vc_ptr++; -} - - -void SimonState::vc_skip_next_instruction() { - static const byte opcode_param_len_simon1[] = { - 0, 6, 2,10, 6, 4, 2, 2, - 4, 4,10, 0, 2, 2, 2, 2, - 2, 0, 2, 0, 4, 2, 4, 2, - 8, 0,10, 0, 8, 0, 2, 2, - 4, 0, 0, 4, 4, 2, 2, 4, - 4, 4, 4, 2, 2, 2, 2, 4, - 0, 2, 2, 2, 2, 4, 6, 6, - 0, 0, 0, 0, 2, 6, 0, 0, - }; - - static const byte opcode_param_len_simon2[] = { - 0, 6, 2, 12, 6, 4, 2, 2, - 4, 4, 9, 0, 1, 2, 2, 2, - 2, 0, 2, 0, 4, 2, 4, 2, - 7, 0, 10, 0, 8, 0, 2, 2, - 4, 0, 0, 4, 4, 2, 2, 4, - 4, 4, 4, 2, 2, 2, 2, 4, - 0, 2, 2, 2, 2, 4, 6, 6, - 2, 0, 6, 6, 4, 6, 0, 0, - 0, 0, 4, 4, 4, 4, 4, 0, - 4, 2, 2 - }; - - if (_game & GAME_SIMON2) { - uint opcode = vc_read_next_byte(); - _vc_ptr += opcode_param_len_simon2[opcode]; - } else { - uint opcode = vc_read_next_word(); - _vc_ptr += opcode_param_len_simon1[opcode]; - } - -#ifdef DUMP_CONTINOUS_VGASCRIPT - fprintf(_dump_file,"; skipped\n"); -#endif -} - -void SimonState::vc_1() { - /* dummy opcode */ - _vc_ptr += 6; -} - -void SimonState::vc_2() { - VgaPointersEntry *vpe; - uint num; - uint res; - byte *old_file_1, *old_file_2; - byte *b,*bb, *vc_ptr_org; - - num = vc_read_var_or_word(); - - old_file_1 = _cur_vga_file_1; - old_file_2 = _cur_vga_file_2; - - for(;;) { - res = num / 100; - vpe = &_vga_buffer_pointers[res]; - - _cur_vga_file_1 = vpe->vgaFile1; - _cur_vga_file_2 = vpe->vgaFile2; - if (vpe->vgaFile1 != NULL) - break; - if (_vga_cur_file_2 != res) - _video_var_7 = _vga_cur_file_2; - - ensureVgaResLoaded(res); - _video_var_7 = 0xFFFF; - } - - - bb = _cur_vga_file_1; - b = bb + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header*)bb)->hdr2_start); - b = bb + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header2*)b)->unk2_offs); - - while (READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x8*)b)->id) != num) - b += sizeof(VgaFile1Struct0x8); - - vc_ptr_org = _vc_ptr; - - _vc_ptr = _cur_vga_file_1 + READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x8*)b)->script_offs); - - -// dump_vga_script(_vc_ptr, res, num); - run_vga_script(); - - _cur_vga_file_1 = old_file_1; - _cur_vga_file_2 = old_file_2; - - _vc_ptr = vc_ptr_org; -} - -void SimonState::vc_3() { - uint16 a,b,c,d,e,f; - uint16 res; - VgaSprite *vsp; - VgaPointersEntry *vpe; - byte *p,*pp; - - a = vc_read_next_word(); /* 0 */ - - if (_game & GAME_SIMON2) { - f = vc_read_next_word(); /* 0 */ - b = vc_read_next_word(); /* 2 */ - } else { - b = vc_read_next_word(); /* 2 */ - f = b / 100; - } - - c = vc_read_next_word(); /* 4 */ - d = vc_read_next_word(); /* 6 */ - e = vc_read_next_word(); /* 8 */ - - /* 2nd param ignored with simon1 */ - if (has_vgastruct_with_id(b,f)) - return; - - vsp = _vga_sprites; - while (vsp->id) vsp++; - - vsp->base_color = e; - vsp->unk6 = a; - vsp->unk5 = 0; - vsp->unk4 = 0; - vsp->image = 0; - vsp->x = c; - vsp->y = d; - vsp->id = b; - vsp->unk7 = res = f; - - for(;;) { - vpe = &_vga_buffer_pointers[res]; - _cur_vga_file_1 = vpe->vgaFile1; - - if (vpe->vgaFile1 != NULL) - break; - if (res != _vga_cur_file_2) - _video_var_7 = res; - - ensureVgaResLoaded(res); - _video_var_7 = 0xFFFF; - } - - pp = _cur_vga_file_1; - p = pp + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header*)pp)->hdr2_start); - p = pp + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header2*)p)->id_table); - - while (READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x6*)p)->id) != b) - p += sizeof(VgaFile1Struct0x6); - -#ifdef DUMP_FILE_NR -{ - static bool dumped=false; - if (res == DUMP_FILE_NR && !dumped) { - dumped = true; - dump_vga_file(_cur_vga_file_1); - } -} -#endif - -#ifdef DUMP_BITMAPS_FILE_NR -{ - static bool dumped=false; - if (res == DUMP_BITMAPS_FILE_NR && !dumped) { - dumped = true; - dump_vga_bitmaps(_cur_vga_file_2, _cur_vga_file_1, res); - } -} -#endif - - dump_vga_script(_cur_vga_file_1 + READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x6*)p)->script_offs), res, b); - - add_vga_timer(gss->VGA_DELAY_BASE, - _cur_vga_file_1 + READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x6*)p)->script_offs),b , res); -} - -void SimonState::vc_4() { - /* dummy opcode */ - _vc_ptr += 6; -} - -void SimonState::vc_5() { - uint var = vc_read_next_word(); - uint value = vc_read_next_word(); - if (vc_read_var(var) != value) - vc_skip_next_instruction(); -} - -void SimonState::vc_6_maybe_skip_3_inv() { - if (!vc_maybe_skip_proc_3(vc_read_next_word())) - vc_skip_next_instruction(); -} - -void SimonState::vc_7_maybe_skip_3() { - if (vc_maybe_skip_proc_3(vc_read_next_word())) - vc_skip_next_instruction(); -} - -void SimonState::vc_8_maybe_skip_2() { - uint a = vc_read_next_word(); - uint b = vc_read_next_word(); - if (!vc_maybe_skip_proc_2(a,b)) - vc_skip_next_instruction(); -} - -void SimonState::vc_9_maybe_skip() { - uint a = vc_read_next_word(); - uint b = vc_read_next_word(); - if (!vc_maybe_skip_proc_1(a,b)) - vc_skip_next_instruction(); -} - -struct VC10_state { - int image; - uint16 e; - int x,y; - - byte base_color; - - uint draw_width, draw_height; - uint x_skip, y_skip; - - byte *surf2_addr; - uint surf2_pitch; - - byte *surf_addr; - uint surf_pitch; - - byte dl,dh; - - byte *depack_src; - int8 depack_cont; - - byte depack_dest[200]; -}; - -byte *vc_10_depack_column(VC10_state *vs) { - int8 a = vs->depack_cont; - byte *src = vs->depack_src; - byte *dst = vs->depack_dest; - byte dh = vs->dh; - byte color; - - if (a != -0x80) - goto start_here; - - for(;;) { - a = *src++; -start_here:; - if (a>=0) { - color = *src++; - do { - *dst++ = color; - if (!--dh) { - if (--a<0) - a = -0x80; - else - src--; - goto get_out; - } - } while(--a>=0); - } else { - do { - *dst++ = *src++; - if (!--dh) { - if (++a==0) - a = -0x80; - goto get_out; - } - } while (++a!=0); - } - } - -get_out:; - vs->depack_src = src; - vs->depack_cont = a; - return vs->depack_dest + vs->y_skip; -} - -void vc_10_skip_cols(VC10_state *vs) { - vs->depack_cont = -0x80; - while(vs->x_skip) { - vc_10_depack_column(vs); - vs->x_skip--; - } -} - -byte *SimonState::vc_10_depack_swap(byte *src, uint w, uint h) { - w<<=3; - - { - byte *dst_org = _video_buf_1 + w; - byte color; - int8 cur = -0x80; - uint w_cur = w; - - do { - byte *dst = dst_org; - uint h_cur = h; - - if (cur == -0x80) - cur = *src++; - - for(;;) { - if (cur >= 0) { - /* rle_same */ - color = *src++; - do { - *dst = color; - dst += w; - if (!--h_cur) { - if (--cur<0) - cur = -0x80; - else - src--; - goto next_line; - } - } while (--cur>=0); - } else { - /* rle_diff */ - do { - *dst = *src++; - dst += w; - if (!--h_cur) { - if (++cur == 0) - cur = -0x80; - goto next_line; - } - } while (++cur != 0); - } - cur = *src++; - } - next_line: - dst_org++; - } while(--w_cur); - } - - { - byte *dst_org, *src_org; - uint i; - - src_org = dst_org = _video_buf_1 + w; - - do { - byte *dst = dst_org; - for(i=0; i!=w; ++i) { - byte b = src_org[i]; - b = (b>>4) | (b<<4); - *--dst = b; - } - - src_org += w; - dst_org += w; - } while (--h); - - } - - return _video_buf_1; - -} - -byte *vc_10_no_depack_swap(byte *src) { - error("vc_10_no_depack_swap unimpl"); -} - -/* must not be const */ -static uint16 _video_windows[128] = { - 0, 0, 20, 200, - 0, 0, 3, 136, - 17,0, 3, 136, - 0, 0, 20, 200, - 0, 0, 20, 134 -}; - -/* simon2 specific */ -void SimonState::vc_10_helper_8(byte *dst, byte *src) { - const uint pitch = _dx_surface_pitch; - int8 reps = (int8)0x80; - byte color; - byte *dst_org = dst; - uint h = _vga_var5, w = 8; - - for(;;) { - reps = *src++; - if (reps >= 0) { - color = *src++; - - do { - *dst = color; - dst += pitch; - - /* reached bottom? */ - if (--h == 0) { - /* reached right edge? */ - if (--w == 0) - return; - dst = ++dst_org; - h = _vga_var5; - } - } while (--reps >=0); - } else { - - do { - *dst = *src++; - dst += pitch; - - /* reached bottom? */ - if (--h == 0) { - /* reached right edge? */ - if (--w == 0) - return; - dst = ++dst_org; - h = _vga_var5; - } - } while (++reps != 0); - } - } -} - -void SimonState::vc_10() { - byte *p2; - uint width,height; - byte flags; - const uint16 *vlut; - VC10_state state; - - int cur; - - state.image = (int16)vc_read_next_word(); - if (state.image==0) - return; - -// if (_vga_cur_sprite_id != 802) -// return; - - state.base_color = (_vc_ptr[1]<<4); - _vc_ptr += 2; - state.x = (int16)vc_read_next_word(); - if (_game & GAME_SIMON2) { - state.x -= _x_scroll; - } - state.y = (int16)vc_read_next_word(); - - if (!(_game & GAME_SIMON2)) { - state.e = vc_read_next_word(); - } else { - state.e = vc_read_next_byte(); - } - - if (state.image < 0) - state.image = vc_read_var(-state.image); - - p2 = _cur_vga_file_2 + state.image * 8; - state.depack_src = _cur_vga_file_2 + READ_BE_UINT32_UNALIGNED(&*(uint32*)p2); - - width = READ_BE_UINT16_UNALIGNED(p2+6)>>4; - height = p2[5]; - flags = p2[4]; - - if (height==0 || width==0) - return; - -#ifdef DUMP_DRAWN_BITMAPS - dump_single_bitmap(_vga_cur_file_id, state.image, state.depack_src, width*16, height, state.base_color); -#endif - - if (flags&0x80 && !(state.e&0x10)) { - if (state.e&1) { - state.e&=~1; - state.e|=0x10; - } else { - state.e|=0x8; - } - } - - if (_game & GAME_SIMON2 && width>=21) { - byte *src,*dst; - uint w; - - _vga_var1 = width*2-40; - _vga_var7 = state.depack_src; - _vga_var5 = height; - if (_variableArray[34]==-1) - state.x = _variableArray[502/2]; - - _x_scroll = state.x; - - vc_write_var(0xfb, _x_scroll); - - dst = dx_lock_attached(); - src = state.depack_src + _x_scroll * 4; - - w = 40; - do { - vc_10_helper_8(dst, src + READ_BE_UINT32_UNALIGNED(&*(uint32*)src)); - dst += 8; - src += 4; - } while (--w); - - dx_unlock_attached(); - - - return; - } - - if (state.e&0x10) - state.depack_src = vc_10_depack_swap(state.depack_src, width, height); - else if (state.e&1) - state.depack_src = vc_10_no_depack_swap(state.depack_src); - - - vlut = &_video_windows[_video_palette_mode * 4]; - - state.draw_width = width << 1; /* cl */ - state.draw_height = height; /* ch */ - - state.x_skip = 0; /* colums to skip = bh */ - state.y_skip = 0; /* rows to skip = bl */ - - cur = state.x; - if (cur < 0) { - do { - if (!--state.draw_width) return; - state.x_skip++; - } while(++cur); - } - state.x = cur; - - cur += state.draw_width - (vlut[2]<<1); - if (cur > 0) { - do { - if (!--state.draw_width) return; - } while (--cur); - } - - cur = state.y; - if (cur < 0) { - do { - if (!--state.draw_height) return; - state.y_skip++; - } while(++cur); - } - state.y = cur; - - cur += state.draw_height - vlut[3]; - if (cur > 0) { - do { - if (!--state.draw_height) return; - } while (--cur); - } - - assert(state.draw_width!=0 && state.draw_height!=0); - - state.draw_width<<=2; - - state.surf2_addr = dx_lock_2(); - state.surf2_pitch = _dx_surface_pitch; - - state.surf_addr = dx_lock_attached(); - state.surf_pitch = _dx_surface_pitch; - - { - uint offs = ((vlut[0] - _video_windows[16])*2 + state.x) * 8; - uint offs2 = (vlut[1] - _video_windows[17] + state.y); - - state.surf2_addr += offs + offs2 * state.surf2_pitch; - state.surf_addr += offs + offs2 * state.surf_pitch; - } - - if (state.e & 0x20) { - byte *mask, *src, *dst; - byte h; - uint w; - - state.x_skip<<=2; - state.dl = width; - state.dh = height; - - vc_10_skip_cols(&state); - - /* XXX: implement transparency */ - - w = 0; - do { - mask = vc_10_depack_column(&state); /* esi */ - src = state.surf2_addr + w*2; /* ebx */ - dst = state.surf_addr + w*2; /* edi */ - - h = state.draw_height; - do { - if (mask[0] & 0xF0) dst[0] = src[0]; - if (mask[0] & 0x0F) dst[1] = src[1]; - mask++; - dst += state.surf_pitch; - src += state.surf2_pitch; - } while(--h); - } while(++w != state.draw_width); - - /* vc_10_helper_5 */ - } else if (_lock_word&0x20 && state.base_color==0 || state.base_color==0xC0) { - byte *src,*dst; - uint h,i; - - if (!(state.e&8)) { - src = state.depack_src + (width * state.y_skip<<4) + (state.x_skip<<3); - dst = state.surf_addr; - - state.draw_width *= 2; - - if(state.e&2) { - /* no transparency */ - h = state.draw_height; - do { - memcpy(dst,src,state.draw_width); - dst += 320; - src += width * 16; - } while(--h); - } else { - /* transparency */ - h = state.draw_height; - do { - for(i=0; i!=state.draw_width; i++) - if(src[i]) - dst[i] = src[i]; - dst += 320; - src += width * 16; - } while(--h); - } - - } else { - byte *dst_org = state.surf_addr; - src = state.depack_src; - /* AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD EEEEEEEE - * aaaaabbb bbcccccd ddddeeee efffffgg ggghhhhh - */ - - if (state.e & 2) { - /* no transparency */ - do { - uint count = state.draw_width>>2; - - dst = dst_org; - do { - uint32 bits = (src[0]<<24) | (src[1]<<16) | (src[2]<<8) | (src[3]); - - dst[0] = (byte)((bits >> (32-5)) & 31); - dst[1] = (byte)((bits >> (32-10)) & 31); - dst[2] = (byte)((bits >> (32-15)) & 31); - dst[3] = (byte)((bits >> (32-20)) & 31); - dst[4] = (byte)((bits >> (32-25)) & 31); - dst[5] = (byte)((bits >> (32-30)) & 31); - - bits = (bits<<8) | src[4]; - - dst[6] = (byte)((bits >> (40-35)) & 31); - dst[7] = (byte)((bits) & 31); - - dst += 8; - src += 5; - } while (--count); - dst_org += 320; - } while (--state.draw_height); - } else { - /* transparency */ - do { - uint count = state.draw_width>>2; - - dst = dst_org; - do { - uint32 bits = (src[0]<<24) | (src[1]<<16) | (src[2]<<8) | (src[3]); - byte tmp; - - tmp = (byte)((bits >> (32-5)) & 31); if (tmp) dst[0] = tmp; - tmp = (byte)((bits >> (32-10)) & 31); if (tmp) dst[1] = tmp; - tmp = (byte)((bits >> (32-15)) & 31); if (tmp) dst[2] = tmp; - tmp = (byte)((bits >> (32-20)) & 31); if (tmp) dst[3] = tmp; - tmp = (byte)((bits >> (32-25)) & 31); if (tmp) dst[4] = tmp; - tmp = (byte)((bits >> (32-30)) & 31); if (tmp) dst[5] = tmp; - - bits = (bits<<8) | src[4]; - - tmp = (byte)((bits >> (40-35)) & 31); if (tmp) dst[6] = tmp; - tmp = (byte)((bits) & 31); if (tmp) dst[7] = tmp; - - dst += 8; - src += 5; - } while (--count); - dst_org += 320; - } while (--state.draw_height); - } - } - /* vc_10_helper_4 */ - } else { - if (_game&GAME_SIMON2 && state.e&0x4 && _bit_array[10]&0x800) { - state.surf_addr = state.surf2_addr; - state.surf_pitch = state.surf2_pitch; - warning("vc_10: (state.e&0x4)"); - } - - if (state.e & 0x8) { - uint w,h; - byte *src, *dst,*dst_org; - - state.x_skip <<= 2; /* reached */ - state.dl = width; - state.dh = height; - - vc_10_skip_cols(&state); - - if (state.e&2) { - dst_org = state.surf_addr; - w = 0; - do { - src = vc_10_depack_column(&state); - dst = dst_org; - - h = 0; - do { - dst[0] = (*src >> 4) | state.base_color; - dst[1] = (*src&15) | state.base_color; - dst += 320; - src++; - } while (++h != state.draw_height); - dst_org += 2; - } while (++w != state.draw_width); - } else { - dst_org = state.surf_addr; - if (state.e & 0x40) { /* reached */ - dst_org += vc_read_var(252); - } - w = 0; - do { - byte color; - - src = vc_10_depack_column(&state); - dst = dst_org; - - h = 0; - do { - color = (*src >> 4); - if (color) dst[0] = color | state.base_color; - color = (*src&15); - if (color) dst[1] = color | state.base_color; - dst += 320; - src++; - } while (++h != state.draw_height); - dst_org += 2; - } while (++w != state.draw_width); - } - /* vc_10_helper_6 */ - } else { - byte *src,*dst; - uint count; - - src = state.depack_src + (width * state.y_skip) * 8; - dst = state.surf_addr; - state.x_skip <<= 2; - if (state.e&2) { - do { - for(count=0; count!=state.draw_width; count++) { - dst[count*2] = (src[count+state.x_skip]>>4) | state.base_color; - dst[count*2+1] = (src[count+state.x_skip]&15) | state.base_color; - } - dst += 320; - src += width * 8; - } while (--state.draw_height); - } else { - do { - for(count=0; count!=state.draw_width; count++) { - byte color; - color = (src[count+state.x_skip]>>4); - if(color) dst[count*2] = color | state.base_color; - color = (src[count+state.x_skip]&15); - if (color) dst[count*2+1] = color | state.base_color; - } - dst += 320; - src += width * 8; - } while (--state.draw_height); - - } - - /* vc_10_helper_7 */ - } - } - - dx_unlock_2(); - dx_unlock_attached(); - -} - -void SimonState::vc_11_clear_pathfind_array() { - memset(&_pathfind_array, 0, sizeof(_pathfind_array)); -} - -void SimonState::vc_12_sleep_variable() { - uint num; - - if (!(_game & GAME_SIMON2)) { - num = vc_read_var_or_word(); - } else { - num = vc_read_next_byte() * _vga_base_delay; - } - - add_vga_timer(num + gss->VGA_DELAY_BASE, _vc_ptr, _vga_cur_sprite_id, _vga_cur_file_id); - _vc_ptr = (byte*)&vc_get_out_of_code; -} - -void SimonState::vc_13_offset_x() { - VgaSprite *vsp = find_cur_sprite(); - int16 a = vc_read_next_word(); - vsp->x += a; - _vga_sprite_changed++; -} - -void SimonState::vc_14_offset_y() { - VgaSprite *vsp = find_cur_sprite(); - int16 a = vc_read_next_word(); - vsp->y += a; - _vga_sprite_changed++; -} - -/* wakeup_id */ -void SimonState::vc_15_start_funkystruct_by_id() { - VgaSleepStruct *vfs = _vga_sleep_structs, *vfs_tmp; - uint16 id = vc_read_next_word(); - while (vfs->ident != 0) { - if (vfs->ident == id) { - add_vga_timer(gss->VGA_DELAY_BASE, vfs->code_ptr, vfs->sprite_id, vfs->cur_vga_file); - vfs_tmp = vfs; - do { - memcpy(vfs_tmp, vfs_tmp + 1, sizeof(VgaSleepStruct)); - vfs_tmp++; - } while (vfs_tmp->ident != 0); - } else { - vfs++; - } - } - - /* clear a wait event */ - if (id == _vga_wait_for) - _vga_wait_for = 0; -} - - -/* sleep_on_id */ -void SimonState::vc_16_setup_funkystruct() { - VgaSleepStruct *vfs = _vga_sleep_structs; - while (vfs->ident) - vfs++; - - vfs->ident = vc_read_next_word(); - vfs->code_ptr = _vc_ptr; - vfs->sprite_id = _vga_cur_sprite_id; - vfs->cur_vga_file = _vga_cur_file_id; - - _vc_ptr = (byte*)&vc_get_out_of_code; -} - -void SimonState::vc_17_set_pathfind_item() { - uint a = vc_read_next_word(); - _pathfind_array[a - 1] = (uint16*)_vc_ptr; - while ( READ_BE_UINT16_UNALIGNED(_vc_ptr) != 999) - _vc_ptr += 4; - _vc_ptr += 2; -} - -void SimonState::vc_18_jump_rel() { - int16 offs = vc_read_next_word(); - _vc_ptr += offs; -} - -/* chain to script? */ -void SimonState::vc_19() { - /* XXX: not implemented */ - error("vc_19: chain to script not implemented"); -} - - -/* helper routines */ - -/* write unaligned 16-bit */ -static void write_16_le(void *p, uint16 a) { - ((byte*)p)[0] = (byte) (a); - ((byte*)p)[1] = (byte) (a >> 8); -} - -/* read unaligned 16-bit */ -static uint16 read_16_le(void *p) { - return ((byte*)p)[0] | (((byte*)p)[1] << 8); -} - -/* FIXME: unaligned access */ -void SimonState::vc_20() { - uint16 a = vc_read_next_word(); - write_16_le(_vc_ptr, a); - _vc_ptr += 2; -} - -/* FIXME: unaligned access */ -void SimonState::vc_21() { - if (!(_game & GAME_SIMON2)) { - int16 a = vc_read_next_word(); - byte *tmp = _vc_ptr + a; - uint16 val = read_16_le(tmp + 4); - - if (val != 0) { - write_16_le(tmp + 4, val - 1); - _vc_ptr = tmp + 6; - } - } else { - int16 a = vc_read_next_word(); - byte *tmp = _vc_ptr + a; - uint16 val = read_16_le(tmp + 3); - - if (val != 0) { - write_16_le(tmp + 3, val - 1); - _vc_ptr = tmp + 5; - } - } -} - -void SimonState::vc_22() { - uint a = vc_read_next_word(); - uint b = vc_read_next_word(); - uint num = a==0 ? 0x20 : 0x10; - byte *palptr, *src; - - palptr = &_palette[(a<<6)]; - - src = _cur_vga_file_1 + 6 + b*96; - - do { - palptr[0] = src[0]<<2; - palptr[1] = src[1]<<2; - palptr[2] = src[2]<<2; - palptr[3] = 0; - - palptr += 4; - src += 3; - } while (--num); - - _video_var_9 = 2; - _vga_sprite_changed++; -} - -void SimonState::vc_23_set_pri() { - VgaSprite *vsp = find_cur_sprite(), *vus2; - uint16 pri = vc_read_next_word(); - VgaSprite bak; - - if (vsp->id == 0) { - warning("tried to set pri for unknown id %d", _vga_cur_sprite_id); - return; - } - - memcpy(&bak, vsp, sizeof(bak)); - bak.unk5 = pri; - bak.unk6 |= 0x8000; - - vus2 = vsp; - - if (vsp != _vga_sprites && pri < vsp[-1].unk5) { - do { - vsp--; - } while (vsp != _vga_sprites && pri < vsp[-1].unk5); - do { - memcpy(vus2, vus2-1, sizeof(VgaSprite)); - } while (--vus2 != vsp); - memcpy(vus2, &bak, sizeof(VgaSprite)); - } else if (vsp[1].id!=0 && pri >= vsp[1].unk5) { - do { - vsp++; - } while (vsp[1].id!=0 && pri >= vsp[1].unk5); - do { - memcpy(vus2, vus2+1,sizeof(VgaSprite)); - } while (++vus2 != vsp); - memcpy(vus2, &bak, sizeof(VgaSprite)); - } else { - vsp->unk5 = pri; - } - _vga_sprite_changed++; -} - -void SimonState::vc_24_set_image_xy() { - VgaSprite *vsp = find_cur_sprite(); - vsp->image = vc_read_var_or_word(); - - if (vsp->id==0) { - warning("Trying to set XY of nonexistent sprite '%d'", _vga_cur_sprite_id); - } - - vsp->x += (int16)vc_read_next_word(); - vsp->y += (int16)vc_read_next_word(); - if (!(_game & GAME_SIMON2)) { - vsp->unk4 = vc_read_next_word(); - } else { - vsp->unk4 = vc_read_next_byte(); - } - - _vga_sprite_changed++; -} - -void SimonState::vc_25_del_sprite_and_get_out() { - VgaSprite *vsp = find_cur_sprite(); - while (vsp->id != 0) { - memcpy(vsp,vsp+1,sizeof(VgaSprite)); - vsp++; - } - _vc_ptr = (byte*)&vc_get_out_of_code; - _vga_sprite_changed++; -} - -void SimonState::vc_26() { - uint16 *as = &_video_windows[vc_read_next_word()*4]; - as[0] = vc_read_next_word(); - as[1] = vc_read_next_word(); - as[2] = vc_read_next_word(); - as[3] = vc_read_next_word(); -} - -void SimonState::vc_27_reset_simon1() { - VgaSprite bak,*vsp; - VgaSleepStruct *vfs; - VgaTimerEntry *vte,*vte2; - - _lock_word |= 8; - - memset(&bak,0,sizeof(bak)); - - vsp = _vga_sprites; - while (vsp->id) { - if (vsp->id == 128) { - memcpy(&bak,vsp,sizeof(VgaSprite)); - } - vsp->id = 0; - vsp++; - } - - if (bak.id != 0) - memcpy(_vga_sprites, &bak, sizeof(VgaSprite)); - - vfs = _vga_sleep_structs; - while (vfs->ident) { - vfs->ident = 0; - vfs++; - } - - - vte = _vga_timer_list; - while (vte->delay) { - if (vte->sprite_id != 0x80) { - vte2 = vte; - while (vte2->delay) { - memcpy(vte2,vte2+1,sizeof(VgaTimerEntry)); - vte2++; - } - } else { - vte++; - } - } - - vc_write_var(0xFE, 0); - - _lock_word &= ~8; -} - - -void SimonState::vc_27_reset_simon2() { - _lock_word |= 8; - - { - VgaSprite *vsp = _vga_sprites; - while (vsp->id) { - vsp->id = 0; - vsp++; - } - } - - { - VgaSleepStruct *vfs = _vga_sleep_structs; - while (vfs->ident) { - vfs->ident = 0; - vfs++; - } - } - - { - VgaTimerEntry *vte = _vga_timer_list; - while (vte->delay) { - VgaTimerEntry *vte2 = vte; - while (vte2->delay) { - memcpy(vte2,vte2+1,sizeof(VgaTimerEntry)); - vte2++; - } - } - } - - vc_write_var(0xFE, 0); - - _lock_word &= ~8; -} - -void SimonState::vc_27_reset() { - if (!(_game & GAME_SIMON2)) - vc_27_reset_simon1(); - else - vc_27_reset_simon2(); -} - -void SimonState::vc_28() { - /* dummy opcode */ - _vc_ptr += 8; -} - -void SimonState::vc_29_stop_all_sounds() { - _mixer->stop_all(); -} - -void SimonState::vc_30_set_base_delay() { - _vga_base_delay = vc_read_next_word(); -} - -void SimonState::vc_31_set_palette_mode() { - _video_palette_mode = vc_read_next_word(); -} - -uint SimonState::vc_read_var(uint var) { - assert(var<255); - return (uint16)_variableArray[var]; -} - -void SimonState::vc_write_var(uint var, int16 value) { - _variableArray[var] = value; -} - -void SimonState::vc_32_copy_var() { - uint16 a = vc_read_var(vc_read_next_word()); - vc_write_var(vc_read_next_word(), a); -} - -void SimonState::vc_33() { - if (_lock_counter != 0) { - _lock_counter = 1; - unlock(); - } -} - -void SimonState::vc_34() { - lock(); - _lock_counter = 200; - _left_button_down = 0; -} - -void SimonState::vc_35() { - /* not used? */ - _vc_ptr += 4; - _vga_sprite_changed++; -} - -void SimonState::vc_36() { - uint vga_res = vc_read_next_word(); - uint mode = vc_read_next_word(); - - if (!(_game & GAME_SIMON2)) { - if (mode == 16) { - _copy_partial_mode = 2; - } else { - set_video_mode_internal(mode,vga_res); - } - } else { - set_video_mode_internal(mode,vga_res); - } -} - -void SimonState::vc_37_sprite_unk3_add() { - VgaSprite *vsp = find_cur_sprite(); - vsp->y += vc_read_var(vc_read_next_word()); - _vga_sprite_changed++; -} - -void SimonState::vc_38_skip_if_var_zero() { - uint var = vc_read_next_word(); - if (vc_read_var(var) == 0) - vc_skip_next_instruction(); -} - -void SimonState::vc_39_set_var() { - uint var = vc_read_next_word(); - int16 value = vc_read_next_word(); - vc_write_var(var,value); -} - -void SimonState::vc_40_var_add() { - uint var = vc_read_next_word(); - int16 value = vc_read_var(var) + vc_read_next_word(); - - if (_game&GAME_SIMON2 && var==0xF && !(_bit_array[5]&1)) { - int16 tmp; - - if (_vga_var2!=0) { - if (_vga_var2>=0) goto no_scroll; - _vga_var2 = 0; - } else { - if (_vga_var3 != 0) goto no_scroll; - } - - if (value - _x_scroll >= 30) { - _vga_var2 = 20; - tmp = _vga_var1 - _x_scroll; - if (tmp < 20) - _vga_var2 = tmp; - add_vga_timer(10, NULL, 0, 0); /* special timer */ - } - } -no_scroll:; - - vc_write_var(var, value); -} - -void SimonState::vc_41_var_sub() { - uint var = vc_read_next_word(); - int16 value = vc_read_var(var) - vc_read_next_word(); - - if (_game&GAME_SIMON2 && var==0xF && !(_bit_array[5]&1)) { - int16 tmp; - - if (_vga_var2!=0) { - if (_vga_var2<0) goto no_scroll; - _vga_var2 = 0; - } else { - if (_vga_var3 != 0) goto no_scroll; - } - - if ((uint16)(value - _x_scroll) < 11) { - _vga_var2 = -20; - tmp = _vga_var1 - _x_scroll; - if (_x_scroll < 20) - _vga_var2 = -_x_scroll; - add_vga_timer(10, NULL, 0, 0); /* special timer */ - } - } -no_scroll:; - - vc_write_var(var, value); -} - -void SimonState::vc_42_delay_if_not_eq() { - uint val = vc_read_var(vc_read_next_word()); - if (val == vc_read_next_word()) { - - add_vga_timer(_vga_base_delay + 1, _vc_ptr - 4, _vga_cur_sprite_id, _vga_cur_file_id); - _vc_ptr = (byte*)&vc_get_out_of_code; - } -} - -void SimonState::vc_43_skip_if_bit_clear() { - if (!vc_get_bit(vc_read_next_word())) { - vc_skip_next_instruction(); - } -} - -void SimonState::vc_44_skip_if_bit_set() { - if (vc_get_bit(vc_read_next_word())) { - vc_skip_next_instruction(); - } -} - -void SimonState::vc_45_set_x() { - VgaSprite *vsp = find_cur_sprite(); - vsp->x = vc_read_var(vc_read_next_word()); - _vga_sprite_changed++; -} - -void SimonState::vc_46_set_y() { - VgaSprite *vsp = find_cur_sprite(); - vsp->y = vc_read_var(vc_read_next_word()); - _vga_sprite_changed++; -} - -void SimonState::vc_47_add_var_f() { - uint var = vc_read_next_word(); - vc_write_var(var, vc_read_var(var) + vc_read_var(vc_read_next_word())); -} - -void SimonState::vc_48() { - uint a = (uint16)_variableArray[12]; - uint b = (uint16)_variableArray[13]; - int c = _variableArray[14]; - uint16 *p = _pathfind_array[a-1]; - int step; - int y1,y2; - int16 *vp; - - p += b*2 + 1; - - step = 2; - if (c<0) { - c = -c; - step = -2; - } - - vp = &_variableArray[20]; - - do{ - y2 = READ_BE_UINT16_UNALIGNED(p); - p += step; - y1 = READ_BE_UINT16_UNALIGNED(p) - y2; - -// assert(READ_BE_UINT16_UNALIGNED(&p[1]) != 999); - - vp[0] = y1>>1; - vp[1] = y1 - (y1>>1); - - vp += 2; - } while (--c); - -} - -void SimonState::vc_set_bit_to(uint bit, bool value) { - uint16 *bits = &_bit_array[bit>>4]; - *bits = (*bits & ~(1<<(bit&15))) | (value << (bit&15)); -} - -bool SimonState::vc_get_bit(uint bit) { - uint16 *bits = &_bit_array[bit>>4]; - return (*bits & (1<<(bit&15))) != 0; -} - -void SimonState::vc_49_set_bit() { - vc_set_bit_to(vc_read_next_word(), true); -} - -void SimonState::vc_50_clear_bit() { - vc_set_bit_to(vc_read_next_word(), false); -} - -void SimonState::vc_51_clear_hitarea_bit_0x40() { - clear_hitarea_bit_0x40(vc_read_next_word()); -} - -void SimonState::vc_52() { - uint16 a = vc_read_next_word(); - - if (!(_game & GAME_SIMON2)) { - playSound(a); - } else { - if (a >= 0x8000) { - a = -a; - warning("vc_52(%d): unimpl"); - } else { - playSound(a); - } - } -} - -void SimonState::vc_53_no_op() { - /* no op */ -} - -void SimonState::vc_54_no_op() { - /* no op */ -} - -void SimonState::vc_55_offset_hit_area() { - HitArea *ha = _hit_areas; - uint count = ARRAYSIZE(_hit_areas); - uint16 id = vc_read_next_word(); - int16 x = vc_read_next_word(); - int16 y = vc_read_next_word(); - - for(;;) { - if (ha->id == id) { - ha->x += x; - ha->y += y; - break; - } - ha++; - if (!--count) - break; - } - - _need_hitarea_recalc++; -} - -void SimonState::vc_56_no_op() { - /* No-Op in simon1 */ - if (_game & GAME_SIMON2) { - uint num = vc_read_var_or_word() * _vga_base_delay; - -#ifdef DUMP_CONTINOUS_VGASCRIPT - fprintf(_dump_file,"; sleep_ex = %d\n", num + gss->VGA_DELAY_BASE); -#endif - - add_vga_timer(num + gss->VGA_DELAY_BASE, _vc_ptr, _vga_cur_sprite_id, _vga_cur_file_id); - _vc_ptr = (byte*)&vc_get_out_of_code; - } -} - -void SimonState::vc_59() { - if (_game & GAME_SIMON2) { - uint file = vc_read_next_word(); - uint start = vc_read_next_word(); - uint end = vc_read_next_word() + 1; - - do { - vc_kill_thread(file, start); - } while (++start != end); - } else { - if (vc_59_helper()) - vc_skip_next_instruction(); - } -} - -void SimonState::vc_58() { - uint sprite = _vga_cur_sprite_id; - uint file = _vga_cur_file_id; - byte *vc_ptr; - uint16 tmp; - - _vga_cur_file_id = vc_read_next_word(); - _vga_cur_sprite_id = vc_read_next_word(); - - tmp = TO_BE_16(vc_read_next_word()); - - vc_ptr = _vc_ptr; - _vc_ptr = (byte*)&tmp; - vc_23_set_pri(); - - _vc_ptr = vc_ptr; - _vga_cur_sprite_id = sprite; - _vga_cur_file_id = file; -} - -void SimonState::vc_57_no_op() { - /* no op */ - -} - -void SimonState::vc_kill_thread(uint file, uint sprite) { - uint16 old_sprite_id, old_cur_file_id; - VgaSleepStruct *vfs; - VgaSprite *vsp; - VgaTimerEntry *vte; - byte *vc_org; - - old_sprite_id = _vga_cur_sprite_id; - old_cur_file_id = _vga_cur_file_id; - vc_org = _vc_ptr; - - _vga_cur_file_id = file; - _vga_cur_sprite_id = sprite; - - vfs = _vga_sleep_structs; - while (vfs->ident != 0) { - if (vfs->sprite_id == _vga_cur_sprite_id - && (vfs->cur_vga_file == _vga_cur_file_id || !(_game & GAME_SIMON2)) - ) { - while (vfs->ident != 0){ - memcpy(vfs, vfs+1, sizeof(VgaSleepStruct)); - vfs++; - } - break; - } - vfs++; - } - - vsp = find_cur_sprite(); - if (vsp->id) { - vc_25_del_sprite_and_get_out(); - - vte = _vga_timer_list; - while (vte->delay != 0) { - if (vte->sprite_id == _vga_cur_sprite_id - && (vte->cur_vga_file == _vga_cur_file_id || !(_game & GAME_SIMON2) ) - ) { - delete_vga_timer(vte); - break; - } - vte++; - } - } - - _vga_cur_file_id = old_cur_file_id; - _vga_cur_sprite_id = old_sprite_id; - _vc_ptr = vc_org; -} - - -/* kill thread */ -void SimonState::vc_60() { - uint file; - - if (_game & GAME_SIMON2) { - file = vc_read_next_word(); - } else { - file = _vga_cur_file_id; - } - uint sprite = vc_read_next_word(); - vc_kill_thread(file, sprite); -} - -void SimonState::vc_61_sprite_change() { - VgaSprite *vsp = find_cur_sprite(); - - vsp->image = vc_read_var_or_word(); - - vsp->x += vc_read_next_word(); - vsp->y += vc_read_next_word(); - vsp->unk4 = 36; - - _vga_sprite_changed++; -} - -void SimonState::vc_62() { - uint i; - byte *vc_ptr_org = _vc_ptr; - - - vc_29_stop_all_sounds(); - -// if (!_video_var_3) { - _video_var_3 = true; - _video_num_pal_colors = 256; - if (_video_palette_mode == 4) - _video_num_pal_colors = 208; -// } - - memcpy(_video_buf_1, _palette_backup, _video_num_pal_colors * sizeof(uint32)); - for(i=NUM_PALETTE_FADEOUT;i!=0;--i) { - palette_fadeout((uint32*)_video_buf_1, _video_num_pal_colors); - _system->set_palette(_video_buf_1, 0, _video_num_pal_colors); - _system->update_screen(); - delay(5); - } - - if (!(_game & GAME_SIMON2)) { - uint16 params[5]; /* parameters to vc_10 */ - VgaSprite *vsp; - VgaPointersEntry *vpe; - - vsp = _vga_sprites; - while (vsp->id != 0) { - if (vsp->id == 128) { - byte *f1 = _cur_vga_file_1; - byte *f2 = _cur_vga_file_2; - uint palmode = _video_palette_mode; - - vpe = &_vga_buffer_pointers[vsp->unk7]; - _cur_vga_file_1 = vpe->vgaFile1; - _cur_vga_file_2 = vpe->vgaFile2; - _video_palette_mode = vsp->unk6; - - params[0] = READ_BE_UINT16_UNALIGNED(&vsp->image); - params[1] = READ_BE_UINT16_UNALIGNED(&vsp->base_color); - params[2] = READ_BE_UINT16_UNALIGNED(&vsp->x); - params[3] = READ_BE_UINT16_UNALIGNED(&vsp->y); - params[4] = READ_BE_UINT16_UNALIGNED(&vsp->unk4); - _vc_ptr = (byte*)params; - vc_10(); - - _video_palette_mode = palmode; - _cur_vga_file_1 = f1; - _cur_vga_file_2 = f2; - break; - } - vsp++; - } - } - - dx_clear_surfaces(_video_palette_mode==4 ? 134 : 200); - - _vc_ptr = vc_ptr_org; -} - -void SimonState::vc_63() { - _palette_color_count = 208; - if(_video_palette_mode != 4) { - _palette_color_count = 256; - } - _video_var_3 = false; -} - -/* Simon2 specific */ -void SimonState::vc_64() { - if (vc_59_helper()) - vc_skip_next_instruction(); - -} - -/* Simon2 specific */ -void SimonState::vc_65() { - error("vc_65 unimplemented"); -} - -/* Simon2 specific */ -void SimonState::vc_66() { - uint a = vc_read_next_word(); - uint b = vc_read_next_word(); - - if (vc_read_var(a) != vc_read_var(b)) - vc_skip_next_instruction(); -} - -/* Simon2 specific */ -void SimonState::vc_67() { - uint a = vc_read_next_word(); - uint b = vc_read_next_word(); - - if (vc_read_var(a) >= vc_read_var(b)) - vc_skip_next_instruction(); -} - -/* Simon2 specific */ -void SimonState::vc_68() { - uint a = vc_read_next_word(); - uint b = vc_read_next_word(); - - if (vc_read_var(a) <= vc_read_var(b)) - vc_skip_next_instruction(); -} - -/* Simon2 specific */ -void SimonState::vc_69() { - uint16 a = vc_read_next_word(); - uint16 b = vc_read_next_word(); - - warning("vc_69(%d,%d): music stuff?", a, b); -} - -/* Simon2 specific */ -void SimonState::vc_70() { - uint16 a = vc_read_next_word(); - uint16 b = vc_read_next_word(); - - _vc70_var1 = a; - _vc70_var2 = b; - - warning("vc_70(%d,%d): music stuff?", a, b); -} - -/* Simon2 specific */ -void SimonState::vc_71() { - if (_vc72_var3==0xFFFF && _vc72_var1==0xFFFF) - vc_skip_next_instruction(); -} - -/* Simon2 specific */ -void SimonState::vc_72() { - uint16 a = vc_read_next_word(); - uint16 b = vc_read_next_word(); - if (a != _vc72_var1) { - _vc72_var2 = b; - _vc72_var3 = a; - } - - warning("vc_72(%d,%d): music stuff?", a, b); -} - -/* Simon2 specific */ -void SimonState::vc_73() { - vc_read_next_byte(); - _op_189_flags |= 1<<vc_read_next_byte(); -} -/* Simon2 specific */ -void SimonState::vc_74() { - vc_read_next_byte(); - _op_189_flags &= ~(1<<vc_read_next_byte()); -} void SimonState::o_fade_to_black() { @@ -5846,66 +2023,6 @@ void SimonState::o_load_game() { } -int SimonState::o_unk_132_helper(bool *b, char *buf) { - HitArea *ha; - - *b = true; - - - if (!_saveload_flag) { -strange_jump:; - _saveload_flag = false; - savegame_dialog(buf); - } - -start_over:; - _key_pressed = 0; - -start_over_2:; - _last_hitarea = _last_hitarea_3 = 0; - - do { - if (_key_pressed != 0) { - if (_saveload_flag) { - *b = false; - return _key_pressed; - } - goto start_over; - } - delay(100); - } while (_last_hitarea_3 == 0); - - ha = _last_hitarea; - - if (ha == NULL || ha->id < 205) goto start_over_2; - - if (ha->id == 205) return ha->id; - - if (ha->id == 206) { - if (_saveload_row_curpos == 1) goto start_over_2; - if (_saveload_row_curpos < 7) _saveload_row_curpos = 1; - else _saveload_row_curpos -= 6; - - goto strange_jump; - } - - if (ha->id == 207) { - if (!_savedialog_flag) goto start_over_2; - _saveload_row_curpos += 6; -// if (_saveload_row_curpos >= _num_savegame_rows) -// _saveload_row_curpos = _num_savegame_rows; - goto strange_jump; - } - - if (ha->id >= 214) goto start_over_2; - return ha->id - 208; -} - -void SimonState::o_unk_132_helper_3() { - for(int i=208; i!=208+6; i++) - set_hitarea_bit_0x40(i); -} - int SimonState::display_savegame_list(int curpos, bool load, char *dst) { int slot, last_slot; @@ -5978,20 +2095,6 @@ void SimonState::savegame_dialog(char *buf) { } while (--i); } -void SimonState::o_unk_132_helper_2(FillOrCopyStruct *fcs, int x) { - byte old_text; - - video_putchar(fcs, x); - old_text = fcs->text_color; - fcs->text_color = fcs->fill_color; - - x += 120; - if (x != 128) x=129; - video_putchar(fcs, x); - - fcs->text_color = old_text; - video_putchar(fcs, 8); -} void SimonState::save_or_load_dialog(bool load) { time_t save_time; @@ -6133,36 +2236,6 @@ get_out:; } while (i == _timer_4); } -void SimonState::o_unk_127() { - if (_game & GAME_SIMON2) { - uint a = getVarOrWord(); - uint b = getVarOrWord(); - uint c = getVarOrByte(); - - warning("o_unk_127(%d,%d,%d) not implemented properly", a, b, c); - - if (a!=_last_music_played) { - _last_music_played = a; - playMusic(a); - } - } else { - uint a = getVarOrWord(); - /*uint b = */getVarOrWord(); - - if (a!=_last_music_played) { - _last_music_played = a; - playMusic(a); - } - } -} - -void SimonState::o_unk_120(uint a) { - uint16 id = TO_BE_16(a); - _lock_word |= 0x4000; - _vc_ptr = (byte*)&id; - vc_15_start_funkystruct_by_id(); - _lock_word &= ~0x4000; -} void SimonState::o_wait_for_vga(uint a) { _vga_wait_for = a; @@ -6411,51 +2484,17 @@ void SimonState::checkTimerCallback() { } -void SimonState::o_unk_163(uint a) { - playSound(a); -} - -void SimonState::o_unk_160(uint a) { - fcs_proc_1(_fcs_ptr_array_3[_fcs_unk_1], a); -} void SimonState::fcs_proc_1(FillOrCopyStruct *fcs, uint value) { fcs->text_color = value; } -void SimonState::o_unk_103() { - lock(); - fcs_unk1(_fcs_unk_1); - showMessageFormat("\x0C"); - unlock(); -} - void SimonState::o_vga_reset() { _lock_word |= 0x4000; vc_27_reset(); _lock_word &= ~0x4000; } -void SimonState::o_unk_99_simon1(uint a) { - uint16 b = TO_BE_16(a); - _lock_word |= 0x4000; - _vc_ptr = (byte*)&b; - vc_60(); - _lock_word &= ~0x4000; -} - -void SimonState::o_unk_99_simon2(uint a, uint b) { - uint16 items[2]; - - items[0] = TO_BE_16(a); - items[1] = TO_BE_16(a); - - _lock_word |= 0x4000; - _vc_ptr = (byte*)&items; - vc_60(); - _lock_word &= ~0x4000; -} - bool SimonState::vc_maybe_skip_proc_3(uint16 a) { Item *item; @@ -6522,20 +2561,6 @@ void SimonState::fcs_unk_2(uint a) { showmessage_helper_3(_fcs_ptr_1->unk6, _fcs_ptr_1->unk7); } -/* OK */ -void SimonState::o_unk26_helper(uint a, uint b, uint c, uint d, uint e, uint f, uint g, uint h) { - a &= 7; - - if (_fcs_ptr_array_3[a]) - fcs_delete(a); - - _fcs_ptr_array_3[a] = fcs_alloc(b,c,d,e,f,g,h); - - if (a == _fcs_unk_1) { - _fcs_ptr_1 = _fcs_ptr_array_3[a]; - showmessage_helper_3(_fcs_ptr_1->unk6, _fcs_ptr_1->unk7); - } -} /* OK */ FillOrCopyStruct *SimonState::fcs_alloc(uint x, uint y, uint w, uint h, uint flags, uint fill_color, uint unk4) { @@ -7217,7 +3242,7 @@ void SimonState::start_vga_code(uint b, uint vga_res, uint vga_struct_id, for(;;) { if (READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x6*)p)->id) == vga_struct_id) { - dump_vga_script(pp + READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x6*)p)->script_offs), vga_res, vga_struct_id); + //dump_vga_script(pp + READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x6*)p)->script_offs), vga_res, vga_struct_id); add_vga_timer(gss->VGA_DELAY_BASE, pp + READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x6*)p)->script_offs), @@ -7234,19 +3259,6 @@ void SimonState::start_vga_code(uint b, uint vga_res, uint vga_struct_id, _lock_word &= ~0x40; } -void SimonState::dump_vga_script_always(byte *ptr, uint res, uint sprite_id) { - fprintf(_dump_file,"; address=%x, vgafile=%d vgasprite=%d\n", - ptr - _vga_buffer_pointers[res].vgaFile1, res, sprite_id); - dump_video_script(ptr, false); - fprintf(_dump_file,"; end\n"); -} - -void SimonState::dump_vga_script(byte *ptr, uint res, uint sprite_id) { -#ifdef DUMP_START_VGASCRIPT - dump_Vga_script_always(ptr,res,sprite_id); -#endif -} - void SimonState::talk_with_speech(uint speech_id, uint num_1) { if (!(_game & GAME_SIMON2)) { if (speech_id == 9999) { @@ -8550,776 +4562,11 @@ byte *SimonState::dx_lock_attached() { void SimonState::dx_unlock_attached() { } - - -/**********************************************************************/ -/**********************************************************************/ -/**********************************************************************/ -/**********************************************************************/ - -void decompressIcon(byte *dst, byte *src, uint pitch, byte base) { - int8 reps = (int8)0x80; - byte color_1, color_2; - byte *dst_org = dst; - uint h = 12, w = 24; - - for(;;) { - reps = *src++; - if (reps < 0) { - color_1 = *src & 0xF; - if (color_1 != 0) color_1 += base; - color_2 = *src++ >> 4; - if (color_2 != 0) color_2 += base; - - do { - if (color_1 != 0) *dst = color_1; - dst += pitch; - if (color_2 != 0) *dst = color_2; - dst += pitch; - - /* reached bottom? */ - if (--h == 0) { - /* reached right edge? */ - if (--w == 0) - return; - dst = ++dst_org; - h = 12; - } - } while (++reps != 0); - } else { - - do { - color_1 = *src & 0xF; - if (color_1 != 0) *dst = color_1 | base; - dst += pitch; - - color_2 = *src++ >> 4; - if (color_2 != 0) *dst = color_2 | base; - dst += pitch; - - /* reached bottom? */ - if (--h == 0) { - /* reached right edge? */ - if (--w == 0) - return; - dst = ++dst_org; - h = 12; - } - } while (--reps >= 0); - } - } -} - -#define SIMON2 -#define SIMON2WIN - -static const char * const opcode_name_table[256] = { - /* 0 */ - "|INV_COND", - "IJ|PTRA_PARENT_IS", - "IJ|PTRA_PARENT_ISNOT", - NULL, - /* 4 */ - NULL, - "IJ|PARENT_IS_1", - "IJ|PARENT_ISNOT_1", - "IIJ|PARENT_IS", - /* 8 */ - NULL, - NULL, - NULL, - "VJ|IS_ZERO", - /* 12 */ - "VJ|ISNOT_ZERO", - "VWJ|IS_EQ", - "VWJ|IS_NEQ", - "VWJ|IS_LE", - /* 16 */ - "VWJ|IS_GE", - "VVJ|IS_EQF", - "VVJ|IS_NEQF", - "VVJ|IS_LEF", - /* 20 */ - "VVJ|IS_GEF", - NULL, - NULL, - "WJ|UNK23", - /* 24 */ - NULL, - "IJ|HAS_CHILD_1", - "IJ|HAS_CHILD_2", - "IWJ|ITEM_UNK3_IS", - /* 28 */ - "IBJ|CHILD_HAS_FLAG", - NULL, - NULL, - "I|SET_NO_PARENT", - /* 32 */ - NULL, - "II|SET_PARENT", - NULL, - NULL, - /* 36 */ - "VV|MOVE", - NULL, - NULL, - NULL, - /* 40 */ - NULL, - "V|ZERO", - "VW|SET", - "VW|ADD", - /* 44 */ - "VW|SUB", - "VV|ADDF", - "VV|SUBF", - "VW|MUL", - /* 48 */ - "VW|DIV", - "VV|MULF", - "VV|DIVF", - "VW|MOD", - /* 52 */ - "VV|MODF", - "VW|RANDOM", - NULL, - "I|SET_A_PARENT", - /* 56 */ - "IB|SET_CHILD2_BIT", - "IB|CLEAR_CHILD2_BIT", - "II|MAKE_SIBLING", - "I|INC_UNK3", - /* 60 */ - "I|DEC_UNK3", - "IW|SET_UNK3", - "V|SHOW_INT", - "T|SHOW_STRING_NL", - /* 64 */ - "T|SHOW_STRING", - "WWWWWB|ADD_HITAREA", - "BT|SET_ITEM_NAME", -#if defined SIMON1WIN || defined SIMON2 - "BTw|SET_ITEM_DESC", -#endif -#ifdef SIMON1DOS - "BT|SET_ITEM_DESC", -#endif - /* 68 */ - "x|HALT", - "x|RET1", - "V|SHOW_STRING_AR3", - "W|START_SUB", - /* 72 */ - NULL, - NULL, - NULL, - NULL, - /* 76 */ - "WW|ADD_TIMEOUT", - "J|IS_M1_EMPTY", - "J|IS_M3_EMPTY", - "ITJ|CHILD_FR2_IS", - /* 80 */ - "IIJ|IS_ITEM_EQ", - NULL, - "B|UNK82", - "|RETM10", - /* 84 */ - NULL, - NULL, - NULL, - "W|UNK87", - /* 88 */ - "|OR_SCRIPT_WORD_10", - "|AND_SCRIPT_WORD_10", - "IB|SET_M_TO_PARENT", - "IB|SET_M_TO_SIBLING", - /* 92 */ - "IB|SET_M_TO_CHILD", - NULL, - NULL, - NULL, - /* 96 */ - "WB|UNK96", - "W|LOAD_VGA", -#ifdef SIMON2 - "WWBWWW|START_VGA", -#else - "WBWWW|START_VGA", -#endif -#ifdef SIMON2 - "WW|KILL_THREAD", -#else - "W|KILL_THREAD", -#endif - /* 100 */ - "|VGA_RESET", - "BWWWWWW|UNK101", - "B|UNK102", - "|UNK103", - /* 104 */ - "B|UNK104", - NULL, - NULL, - "WWWWWIW|ADD_ITEM_HITAREA", - /* 108 */ - "W|DEL_HITAREA", - "W|CLEAR_HITAREA_0x40", - "W|SET_HITAREA_0x40", - "WWW|SET_HITAREA_XY", - /* 112 */ - NULL, - NULL, - "IB|UNK114", - "IBJ|HAS_FLAG", - /* 116 */ - "IB|SET_FLAG", - "IB|CLEAR_FLAG", - NULL, - "W|WAIT_VGA", - /* 120 */ - "W|UNK120", - "BI|SET_VGA_ITEM", - NULL, - NULL, - /* 124 */ - NULL, - "IJ|IS_SIBLING_WITH_A", - "IBB|UNK126", - "WW|UNK127", - /* 128 */ - "W|GET_DUMMY_WORD", - "W|GET_WORD_COND_TRUE", - "Bww|UNK131", - NULL, /* opcode 131 doesn't exist */ - /* 132 */ - "|SAVE_GAME", - "|LOAD_GAME", - "|DUMMYPROC_134", - "|QUIT_IF_USER_PRESSES_Y", - /* 136 */ - "IV|GET_ITEM_UNK3", - "B|UNK137", - "|VGA_POINTER_OP_4", - "II|SET_PARENT_SPECIAL", - /* 140 */ - "|DEL_TE_AND_ADD_ONE", - "BI|SET_M1_OR_M3", - "WJ|IS_HITAREA_0x40_CLEAR", - "I|START_ITEM_SUB", - /* 144 */ - NULL, - NULL, - NULL, - NULL, - /* 148 */ - NULL, - NULL, - NULL, - "BI|SET_ARRAY6_TO", - /* 152 */ - "BB|SET_M1_M3_TO_ARRAY6", - "B|SET_BIT", - "B|CLEAR_BIT", - "BJ|IS_BIT_CLEAR", - /* 156 */ - "BJ|IS_BIT_SET", - "IBB|GET_ITEM_PROP", - "IBW|SET_ITEM_PROP", - NULL, - /* 160 */ - "B|UNK160", - "BWBW|SETUP_TEXT", -#if defined SIMON1WIN || defined SIMON2 - "BBTW|PRINT_STR", -#endif -#ifdef SIMON1DOS - "BBT|PRINT_STR", -#endif - "W|SOUND_1", - /* 164 */ - "|UNK164", - "IWWJ|ITEM_UNK1_UNK2_IS", - "B|SET_BIT2", - "B|CLEAR_BIT2", - /* 168 */ - "BJ|IS_BIT2_CLEAR", - "BJ|IS_BIT2_SET", - NULL, - NULL, - /* 172 */ - NULL, - NULL, - NULL, - "|VGA_POINTER_OP_1", - /* 176 */ - "|VGA_POINTER_OP_2", - "BBI|UNK177", - "WWBB|PATHFIND", - "BBB|UNK179", - /* 180 */ - "|FORCE_UNLOCK", - "|FORCE_LOCK", - "|READ_VGARES_328", - "|READ_VGARES_23", - /* 184 */ - "W|CLEAR_VGAPOINTER_ENTRY", - "W|DUMMY_185", - "|VGA_POINTER_OP_3", - "|FADE_TO_BLACK", -#ifdef SIMON2 - /* 188 */ - "BSJ|STRING2_IS", - "|UNK189", - "B|UNK190", -#endif -}; - -byte *SimonState::dumpOpcode(byte *p) { - byte opcode; - const char *s, *st; - - opcode = *p++; - if (opcode == 255) - return NULL; - st = s = opcode_name_table[opcode]; - if (s == NULL) { - error("INVALID OPCODE %d\n", opcode); - return NULL; - } - while (*st != '|') st++; - fprintf(_dump_file,"%s ", st+1); - - for(;;) { - switch(*s++) { - case 'x': - fprintf(_dump_file,"\n"); - return NULL; - case '|': - fprintf(_dump_file,"\n"); - return p; - case 'B': { - byte b = *p++; - if (b==255) - fprintf(_dump_file,"[%d] ", *p++); - else - fprintf(_dump_file,"%d ", b); - break; - } - case 'V': { - byte b = *p++; - if (b==255) - fprintf(_dump_file,"[[%d]] ", *p++); - else - fprintf(_dump_file,"[%d] ", b); - break; - } - - case 'W': { - int n = (int16)((p[0]<<8)|p[1]); - p+=2; - if (n>=30000 && n<30512) - fprintf(_dump_file,"[%d] ", n - 30000); - else - fprintf(_dump_file,"%d ", n); - break; - } - - case 'w': { - int n = (int16)((p[0]<<8)|p[1]); - p+=2; - fprintf(_dump_file,"%d ", n); - break; - } - - case 'I': { - int n = (int16)((p[0]<<8)|p[1]);; - p+=2; - if (n == -1) - fprintf(_dump_file,"ITEM_M1 "); - else if (n == -3) - fprintf(_dump_file,"ITEM_M3 "); - else if (n == -5) - fprintf(_dump_file,"ITEM_1 "); - else if (n == -7) - fprintf(_dump_file,"ITEM_0 "); - else if (n == -9) - fprintf(_dump_file,"ITEM_A_PARENT "); - else - fprintf(_dump_file,"<%d> ", n); - break; - } - case 'J': { - fprintf(_dump_file,"-> "); - } break; - - - case 'T': { - uint n = ((p[0]<<8)|p[1]); - p+=2; - if (n != 0xFFFF) - fprintf(_dump_file,"\"%s\"(%d) ", getStringPtrByID(n), n); - else - fprintf(_dump_file,"NULL_STRING "); - } break; - } - } -} - -void SimonState::dumpSubroutineLine(SubroutineLine *sl, Subroutine *sub) { - byte *p; - - - printf("; ****\n"); - - p = (byte*)sl + SUBROUTINE_LINE_SMALL_SIZE; - if (sub->id == 0) { - fprintf(_dump_file,"; cond_a=%d, cond_b=%d, cond_c=%d\n", sl->cond_a, sl->cond_b, sl->cond_c); - p = (byte*)sl + SUBROUTINE_LINE_BIG_SIZE; - } - - for(;;) { - p = dumpOpcode(p); - if (p==NULL) - break; - } -} - -void SimonState::dumpSubroutine(Subroutine *sub) { - SubroutineLine *sl; - - fprintf(_dump_file,"\n******************************************\n;Subroutine, ID=%d:\nSUB_%d:\n", sub->id, sub->id); - sl = (SubroutineLine*) ((byte*)sub + sub->first); - for(;(byte*)sl != (byte*)sub; sl = (SubroutineLine*) ((byte*)sub + sl->next) ) { - dumpSubroutineLine(sl, sub); - } - fprintf(_dump_file,"\nEND ******************************************\n"); - fflush(_dump_file); -} - -void SimonState::dumpSubroutines() { - Subroutine *sub = _subroutine_list; - for(;sub;sub = sub->next) { - dumpSubroutine(sub); - } -} - -const char * const video_opcode_name_table[] = { - /* 0 */ - "x|RET", - "ddd|DUMMY", - "d|CALL", - "ddddd|NEW_THREAD", - /* 4 */ - "ddd|DUMMY_2", - "vd|SKIP_IF_NEQ", - "d|SKIP_IFN_SIB_WITH_A", - "d|SKIP_IF_SIB_WITH_A", - /* 8 */ - "dd|SKIP_IF_PARENT_IS", - "dd|SKIP_IF_UNK3_IS", -#ifdef SIMON2 - "ddddb|DRAW", -#else - "ddddd|DRAW", -#endif - "|CLEAR_PATHFIND_ARRAY", - /* 12 */ -#ifdef SIMON2 - "b|DELAY", -#else - "d|DELAY", -#endif - "d|OFFSET_X", - "d|OFFSET_Y", - "d|IDENT_WAKEUP", - /* 16 */ - "d|IDENT_SLEEP", - "dq|SET_PATHFIND_ITEM", - "i|JUMP_REL", - "|CHAIN_TO", - /* 20 */ - "dd|SET_CODE_WORD", - "i|JUMP_IF_CODE_WORD", - "dd|SET_PAL", - "d|SET_PRI", - /* 24 */ - "diid|SET_IMG_XY", - "x|HALT_THREAD", - "ddddd|SET_WINDOW", - "|RESET", - /* 28 */ - "dddd|DUMMY_3", - "|STOP_ALL_SOUNDS", - "d|SET_BASE_DELAY", - "d|SET_PALETTE_MODE", - /* 32 */ - "vv|COPY_VAR", - "|FORCE_UNLOCK", - "|FORCE_LOCK", - "dd|DUMMY_4", - /* 36 */ - "dd|SAVELOAD_THING", - "v|OFFSET_Y_F", - "v|SKIP_IF_VAR_ZERO", - "vd|SET_VAR", - /* 40 */ - "vd|ADD_VAR", - "vd|SUB_VAR", - "vd|SLEEP_UNTIL_SET", - "d|SKIP_IF_BIT_CLEAR", - /* 44 */ - "d|SKIP_IF_BIT_SET", - "v|SET_X_F", - "v|SET_Y_F", - "vv|ADD_VAR_F", - /* 48 */ - "|VC_48", - "d|SET_BIT", - "d|CLEAR_BIT", - "d|CLEAR_HITAREA_BIT_0x40", - /* 52 */ - "d|VC_52", - "dd|DUMMY_5", - "ddd|DUMMY_6", - "ddd|OFFSET_HIT_AREA", - /* 56 */ -#ifdef SIMON2 - "i|SLEEP_EX", -#else - "|DUMMY_7", -#endif - "|DUMMY_8", - "|DUMMY_9", -#ifdef SIMON2 - "ddd|KILL_MULTI_THREAD", -#else - "|SKIP_IF_SOUND??", -#endif - /* 60 */ -#ifdef SIMON2 - "dd|KILL_THREAD", -#else - "d|KILL_THREAD", -#endif - "ddd|INIT_SPRITE", - "|PALETTE_THING", - "|PALETTE_THING_2", -#ifdef SIMON2 - /* 64 */ - "|UNK64", - "|UNK65", - "|UNK66", - "|UNK67", - /* 68 */ - "|UNK68", - "dd|UNK69", - "dd|UNK70", - "|UNK71", - /* 72 */ - "dd|UNK72", - "bb|UNK73", - "bb|UNK74", -#endif -}; - -void SimonState::dump_video_script(byte *src, bool one_opcode_only) { - uint opcode; - const char *str, *strn; - - do { - if (!(_game & GAME_SIMON2)) { - opcode = READ_BE_UINT16_UNALIGNED(src); - src+=2; - } else { - opcode = *src++; - } - - if (opcode >= gss->NUM_VIDEO_OP_CODES) { - error("Invalid opcode %x\n", opcode); - return; - } - - strn = str = video_opcode_name_table[opcode]; - while (*strn != '|') strn++; - fprintf(_dump_file,"%.2d: %s ", opcode, strn + 1); - - for (;*str != '|';str++) { - switch(*str) { - case 'x': fprintf(_dump_file,"\n"); return; - case 'b': fprintf(_dump_file,"%d ", *src++); break; - case 'd': fprintf(_dump_file,"%d ", READ_BE_UINT16_UNALIGNED(src)); src+=2; break; - case 'v': fprintf(_dump_file,"[%d] ", READ_BE_UINT16_UNALIGNED(src)); src+=2; break; - case 'i': fprintf(_dump_file,"%d ", (int16)READ_BE_UINT16_UNALIGNED(src)); src+=2; break; - case 'q': - while (READ_BE_UINT16_UNALIGNED(src) != 999) { - fprintf(_dump_file,"(%d,%d) ", READ_BE_UINT16_UNALIGNED(src), READ_BE_UINT16_UNALIGNED(src+2)); - src += 4; - } - src++; - break; - default: - error("Invalid fmt string '%c' in decompile VGA", *str); - } - } - - fprintf(_dump_file,"\n"); - } while(!one_opcode_only); -} - -void SimonState::dump_vga_file(byte *vga) { - { - byte *pp; - byte *p; - int count; - - pp = vga; - p = pp + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header*)pp)->hdr2_start); - count = READ_BE_UINT16_UNALIGNED(&((VgaFile1Header2*)p)->id_count); - p = pp + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header2*)p)->id_table); - while (--count >= 0) { - int id = READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x6*)p)->id); - - dump_vga_script_always(vga + READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x6*)p)->script_offs), id/100, id); - p += sizeof(VgaFile1Struct0x6); - } - } - - { - byte *bb, *b; - int c; - - bb = vga; - b = bb + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header*)bb)->hdr2_start); - c = READ_BE_UINT16_UNALIGNED(&((VgaFile1Header2*)b)->unk1); - b = bb + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header2*)b)->unk2_offs); - - while (--c >= 0) { - int id = READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x8*)b)->id); - - dump_vga_script_always(vga + READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x8*)b)->script_offs), id/100, id); - b += sizeof(VgaFile1Struct0x8); - } - } -} - - - -const byte bmp_hdr[] = { -0x42,0x4D, -0x9E,0x14,0x00,0x00, /* offset 2, file size */ -0x00,0x00,0x00,0x00, -0x36,0x04,0x00,0x00, -0x28,0x00,0x00,0x00, - -0x3C,0x00,0x00,0x00, /* image width */ -0x46,0x00,0x00,0x00, /* image height */ -0x01,0x00,0x08,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00, - -0x00,0x01,0x00,0x00, -0x00,0x01,0x00,0x00, -}; - -void dump_bmp(const char *filename, int w, int h, const byte *bytes, const uint32 *palette) { - FILE *out = fopen(filename, "wb"); - byte my_hdr[sizeof(bmp_hdr)]; - int i; - - if (out == NULL) { - printf("DUMP ERROR\n"); - return; - } - - memcpy(my_hdr, bmp_hdr, sizeof(bmp_hdr)); - - *(uint32*)(my_hdr + 2) = w*h + 1024 + sizeof(bmp_hdr); - *(uint32*)(my_hdr + 18) = w; - *(uint32*)(my_hdr + 22) = h; - - - fwrite(my_hdr, 1, sizeof(my_hdr), out); - - for(i=0; i!=256; i++,palette++) { - byte color[4]; - color[0] = (byte)(*palette >> 16); - color[1] = (byte)(*palette >> 8); - color[2] = (byte)(*palette); - color[3] = 0; - fwrite(color, 1, 4, out); - } - - while (--h >= 0) { - fwrite(bytes + h * ((w+3)&~3), ((w+3)&~3), 1, out); - } - - fclose(out); -} - -void dump_bitmap(const char *filename, byte *offs, int w, int h, int flags, const byte *palette, byte base) { - /* allocate */ - byte *b = (byte*)malloc(w*h); - int i,j; - - VC10_state state; - - state.depack_cont = -0x80; - state.depack_src = offs; - state.dh = h; - state.y_skip = 0; - - for(i=0; i!=w; i+=2) { - byte *c = vc_10_depack_column(&state); - for(j=0;j!=h;j++) { - byte pix = c[j]; - b[j*w+i] = (pix>>4)|base; - b[j*w+i+1] = (pix&0xF)|base; - - } - } - - dump_bmp(filename, w, h, b, (uint32*)palette); - free(b); -} - -void SimonState::dump_single_bitmap(int file, int image, byte *offs, int w, int h, byte base) { -/* Only supported for win32 atm. mkdir doesn't work otherwise. */ -#if defined (WIN32) && !defined(_WIN32_WCE) - char buf[255], buf2[255]; - struct stat statbuf; - - sprintf(buf, "bmp_%d\\%d.bmp", file, image); - - if (stat(buf, &statbuf) == 0) - return; - - sprintf(buf2, "bmp_%d", file); - mkdir(buf2); - - dump_bitmap(buf, offs, w, h, 0, _palette, base); -#endif -} - -SimonState *SimonState::create(OSystem *syst, MidiDriver *driver) { - SimonState *s = new SimonState; - - s->_system = syst; - - /* Setup midi driver */ - s->midi.set_driver(driver); - - /* Setup mixer */ - if (!s->_mixer->bind_to_system(syst)) - warning("Sound initialization failed. " - "Features of the game that depend on sound synchronization will most likely break"); - - return s; - -} - void SimonState::set_volume(byte volume) { _mixer->set_volume(volume * 256 / 100); } + +byte SimonState::getByte() { + return *_code_ptr++; +} diff --git a/simon/simon.h b/simon/simon.h index 29e51e1532..68f0688726 100644 --- a/simon/simon.h +++ b/simon/simon.h @@ -19,9 +19,11 @@ * */ -/* GFX Settings. Sound & Music only works properly with SIMON1WIN */ -#define USE_SOUND -#define USE_MUSIC +#include <time.h> +#include <sys/stat.h> +#include "scummsys.h" +#include "system.h" +#include "../sound/mixer.h" /* Various other settings */ //#define DUMP_CONTINOUS_MAINSCRIPT @@ -42,10 +44,11 @@ uint32 fileReadBE32(FILE *in); uint32 fileReadLE32(FILE *in); void fileWriteBE32(FILE *in, uint32 value); void fileWriteBE16(FILE *in, uint16 value); - +uint fileReadItemID(FILE *in); #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0])) #define CHECK_BOUNDS(x,y) assert((uint)(x)<ARRAYSIZE(y)) +#define NUM_PALETTE_FADEOUT 32 struct Child { Child *next; @@ -236,7 +239,6 @@ enum { }; int GetAsyncKeyState(int key); - #endif class MidiDriver; @@ -415,9 +417,7 @@ public: uint32 _last_vga_tick; -//#ifdef SIMON2 uint16 _op_189_flags; -//#endif bool _scriptvar_2; bool _run_script_return_1; @@ -438,14 +438,9 @@ public: bool _dx_use_3_or_4_for_lock; bool _mouse_pos_changed; - -//#ifdef SIMON2 bool _vk_t_toggle; byte _mouse_cursor; bool _vga_var9; -//#endif - -//#ifdef SIMON2 int16 _script_unk_1; bool _vga_var6; int _x_scroll,_vga_var1,_vga_var2,_vga_var3,_vga_var5; @@ -454,9 +449,6 @@ public: uint16 _vc72_var1, _vc72_var2, _vc72_var3; uint16 _vc70_var1, _vc70_var2; byte *_vga_var7; -//#else -// int _script_unk_1; -//#endif int16 _script_cond_a, _script_cond_b, _script_cond_c; @@ -522,10 +514,6 @@ public: uint _invoke_timer_callback; -// uint32 _voice_size; - -// uint32 _sound_size; -// byte *_sound_ptr; uint _vga_sprite_changed; @@ -574,8 +562,6 @@ public: VgaSprite _vga_sprites[180]; VgaSleepStruct _vga_sleep_structs[30]; -// uint16 _unk21_word_array[32]; /* should be initialized to ones */ - uint16 *_pathfind_array[20]; uint8 _palette_backup[1024]; @@ -852,6 +838,7 @@ public: void run_vga_script(); + // Simon1/Simon2 video script opcodes void vc_1(); void vc_2(); void vc_3(); @@ -917,7 +904,7 @@ public: void vc_62(); void vc_63(); -//#ifdef SIMON2 + // Simon2 specific Video Script Opcodes void vc_64(); void vc_65(); void vc_66(); @@ -929,7 +916,6 @@ public: void vc_72(); void vc_73(); void vc_74(); -//#endif void delete_vga_timer(VgaTimerEntry *vte); void vc_resume_thread(byte *code_ptr, uint16 cur_file, uint16 cur_sprite); @@ -992,11 +978,15 @@ public: void dx_clear_surfaces(uint num_lines); void dx_update_screen_and_palette(); +#ifdef SIMONDEBUG void dump_video_script(byte *src, bool one_opcode_only); void dump_vga_file(byte *vga); + void dump_vga_script(byte *ptr, uint res, uint sprite_id); + void dump_vga_script_always(byte *ptr, uint res, uint sprite_id); void dump_vga_bitmaps(byte *vga, byte *vga1, int res); void dump_single_bitmap(int file, int image, byte *offs, int w, int h, byte base); - +#endif + void dx_clear_attached_from_top(uint lines); void dx_copy_from_attached_to_2(uint x, uint y, uint w, uint h); void dx_copy_from_attached_to_3(uint lines); @@ -1009,9 +999,7 @@ public: byte *vc_10_depack_swap(byte *src, uint w, uint h); - void dump_vga_script(byte *ptr, uint res, uint sprite_id); - void dump_vga_script_always(byte *ptr, uint res, uint sprite_id); - + Item *getNextItemPtrStrange(); bool save_game(uint slot, const char *caption); @@ -1027,16 +1015,10 @@ public: void playVoice(uint voice); void playSound(uint sound); - -// void generateSound(byte *ptr, int len); - void playMusic(uint music); - void checkTimerCallback(); - void delay(uint delay); -//#ifdef SIMON2 void o_190_helper(uint i); void vc_58(); void timer_vga_sprites_helper(); @@ -1044,7 +1026,6 @@ public: void vc_10_helper_8(byte *dst, byte *src); void scroll_timeout(); void hitarea_stuff_helper_2(); -//#endif void realizePalette(); void vc_kill_thread(uint file, uint sprite); @@ -1074,10 +1055,6 @@ public: void NORETURN CDECL error(const char *errmsg, ...); void CDECL warning(const char *errmsg, ...); -//uint16 swap16(uint16 a); -//uint32 swap32(uint32 a); - - void _2xSaI (uint8 *srcPtr, uint32 srcPitch, uint8 *deltaPtr, uint8 *dstPtr, uint32 dstPitch, int width, int height); int Init_2xSaI (uint32 BitFormat); void Super2xSaI (uint8 *srcPtr, uint32 srcPitch, @@ -1085,6 +1062,82 @@ void Super2xSaI (uint8 *srcPtr, uint32 srcPitch, int width, int height); void initializeHardware(); void dx_set_palette(uint32 *colors, uint num); +void palette_fadeout(uint32 *pal_values,uint num); + +static const GameSpecificSettings simon1_settings = { + 1, /* VGA_DELAY_BASE */ + 1576/4, /* TABLE_INDEX_BASE */ + 1460/4, /* TEXT_INDEX_BASE */ + 1700/4, /* NUM_GAME_OFFSETS */ + 64, /* NUM_VIDEO_OP_CODES */ + 1000000, /* VGA_MEM_SIZE */ + 50000, /* TABLES_MEM_SIZE */ + 3624, /* NUM_VOICE_RESOURCES */ + 141, /* NUM_EFFECT_RESOURCES */ + 1316/4, /* MUSIC_INDEX_BASE */ + 0, /* SOUND_INDEX_BASE */ + "SIMON.GME", /* gme_filename */ + "SIMON.WAV", /* wav_filename */ + "SIMON.VOC", /* wav_filename2 */ + "EFFECTS.VOC", /* effects_filename */ + "GAMEPC", /* gamepc_filename */ +}; + +static const GameSpecificSettings simon2_settings = { + 5, /* VGA_DELAY_BASE */ + 1580/4, /* TABLE_INDEX_BASE */ + 1500/4, /* TEXT_INDEX_BASE */ + 2116/4, /* NUM_GAME_OFFSETS */ + 75, /* NUM_VIDEO_OP_CODES */ + 2000000, /* VGA_MEM_SIZE */ + 100000, /* TABLES_MEM_SIZE */ + 12256, /* NUM_VOICE_RESOURCES */ + 0, + 1128/4, /* MUSIC_INDEX_BASE */ + 1660/4, /* SOUND_INDEX_BASE */ + "SIMON2.GME", /* gme_filename */ + "SIMON2.WAV", /* wav_filename */ + NULL, + "", + "GSPTR30", /* gamepc_filename */ +}; + +static const GameSpecificSettings simon2win_settings = { + 5, /* VGA_DELAY_BASE */ + 1580/4, /* TABLE_INDEX_BASE */ + 1500/4, /* TEXT_INDEX_BASE */ + 2116/4, /* NUM_GAME_OFFSETS */ + 75, /* NUM_VIDEO_OP_CODES */ + 2000000, /* VGA_MEM_SIZE */ + 100000, /* TABLES_MEM_SIZE */ + 12256, /* NUM_VOICE_RESOURCES */ + 0, + 1128/4, /* MUSIC_INDEX_BASE */ + 1660/4, /* SOUND_INDEX_BASE */ + "SIMON2.GME", /* gme_filename */ + "SIMON2.WAV", /* wav_filename */ + NULL, + "", + "GSPTR30", /* gamepc_filename */ +}; + +static const GameSpecificSettings simon2dos_settings = { + 5, /* VGA_DELAY_BASE */ + 1580/4, /* TABLE_INDEX_BASE */ + 1500/4, /* TEXT_INDEX_BASE */ + 2116/4, /* NUM_GAME_OFFSETS */ + 75, /* NUM_VIDEO_OP_CODES */ + 2000000, /* VGA_MEM_SIZE */ + 100000, /* TABLES_MEM_SIZE */ + 12256, /* NUM_VOICE_RESOURCES */ + 0, + 1128/4, /* MUSIC_INDEX_BASE */ + 1660/4, /* SOUND_INDEX_BASE */ + "SIMON2.GME", /* gme_filename */ + "SIMON2.WAV", /* wav_filename */ + NULL, + "", + "GAME32", /* gamepc_filename */ +}; + -//extern byte *sdl_buf; -//extern byte *sdl_buf_attached; diff --git a/simon/simondebug.cpp b/simon/simondebug.cpp new file mode 100644 index 0000000000..386fd636ad --- /dev/null +++ b/simon/simondebug.cpp @@ -0,0 +1,731 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001/2002 The ScummVM project + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +// Simon debug functions +#include "stdafx.h" +#include "simon.h" + +#ifdef SIMONDEBUG +#define SIMON2 +#define SIMON2WIN + +static const char * const opcode_name_table[256] = { + /* 0 */ + "|INV_COND", + "IJ|PTRA_PARENT_IS", + "IJ|PTRA_PARENT_ISNOT", + NULL, + /* 4 */ + NULL, + "IJ|PARENT_IS_1", + "IJ|PARENT_ISNOT_1", + "IIJ|PARENT_IS", + /* 8 */ + NULL, + NULL, + NULL, + "VJ|IS_ZERO", + /* 12 */ + "VJ|ISNOT_ZERO", + "VWJ|IS_EQ", + "VWJ|IS_NEQ", + "VWJ|IS_LE", + /* 16 */ + "VWJ|IS_GE", + "VVJ|IS_EQF", + "VVJ|IS_NEQF", + "VVJ|IS_LEF", + /* 20 */ + "VVJ|IS_GEF", + NULL, + NULL, + "WJ|UNK23", + /* 24 */ + NULL, + "IJ|HAS_CHILD_1", + "IJ|HAS_CHILD_2", + "IWJ|ITEM_UNK3_IS", + /* 28 */ + "IBJ|CHILD_HAS_FLAG", + NULL, + NULL, + "I|SET_NO_PARENT", + /* 32 */ + NULL, + "II|SET_PARENT", + NULL, + NULL, + /* 36 */ + "VV|MOVE", + NULL, + NULL, + NULL, + /* 40 */ + NULL, + "V|ZERO", + "VW|SET", + "VW|ADD", + /* 44 */ + "VW|SUB", + "VV|ADDF", + "VV|SUBF", + "VW|MUL", + /* 48 */ + "VW|DIV", + "VV|MULF", + "VV|DIVF", + "VW|MOD", + /* 52 */ + "VV|MODF", + "VW|RANDOM", + NULL, + "I|SET_A_PARENT", + /* 56 */ + "IB|SET_CHILD2_BIT", + "IB|CLEAR_CHILD2_BIT", + "II|MAKE_SIBLING", + "I|INC_UNK3", + /* 60 */ + "I|DEC_UNK3", + "IW|SET_UNK3", + "V|SHOW_INT", + "T|SHOW_STRING_NL", + /* 64 */ + "T|SHOW_STRING", + "WWWWWB|ADD_HITAREA", + "BT|SET_ITEM_NAME", +#if defined SIMON1WIN || defined SIMON2 + "BTw|SET_ITEM_DESC", +#endif +#ifdef SIMON1DOS + "BT|SET_ITEM_DESC", +#endif + /* 68 */ + "x|HALT", + "x|RET1", + "V|SHOW_STRING_AR3", + "W|START_SUB", + /* 72 */ + NULL, + NULL, + NULL, + NULL, + /* 76 */ + "WW|ADD_TIMEOUT", + "J|IS_M1_EMPTY", + "J|IS_M3_EMPTY", + "ITJ|CHILD_FR2_IS", + /* 80 */ + "IIJ|IS_ITEM_EQ", + NULL, + "B|UNK82", + "|RETM10", + /* 84 */ + NULL, + NULL, + NULL, + "W|UNK87", + /* 88 */ + "|OR_SCRIPT_WORD_10", + "|AND_SCRIPT_WORD_10", + "IB|SET_M_TO_PARENT", + "IB|SET_M_TO_SIBLING", + /* 92 */ + "IB|SET_M_TO_CHILD", + NULL, + NULL, + NULL, + /* 96 */ + "WB|UNK96", + "W|LOAD_VGA", +#ifdef SIMON2 + "WWBWWW|START_VGA", +#else + "WBWWW|START_VGA", +#endif +#ifdef SIMON2 + "WW|KILL_THREAD", +#else + "W|KILL_THREAD", +#endif + /* 100 */ + "|VGA_RESET", + "BWWWWWW|UNK101", + "B|UNK102", + "|UNK103", + /* 104 */ + "B|UNK104", + NULL, + NULL, + "WWWWWIW|ADD_ITEM_HITAREA", + /* 108 */ + "W|DEL_HITAREA", + "W|CLEAR_HITAREA_0x40", + "W|SET_HITAREA_0x40", + "WWW|SET_HITAREA_XY", + /* 112 */ + NULL, + NULL, + "IB|UNK114", + "IBJ|HAS_FLAG", + /* 116 */ + "IB|SET_FLAG", + "IB|CLEAR_FLAG", + NULL, + "W|WAIT_VGA", + /* 120 */ + "W|UNK120", + "BI|SET_VGA_ITEM", + NULL, + NULL, + /* 124 */ + NULL, + "IJ|IS_SIBLING_WITH_A", + "IBB|UNK126", + "WW|UNK127", + /* 128 */ + "W|GET_DUMMY_WORD", + "W|GET_WORD_COND_TRUE", + "Bww|UNK131", + NULL, /* opcode 131 doesn't exist */ + /* 132 */ + "|SAVE_GAME", + "|LOAD_GAME", + "|DUMMYPROC_134", + "|QUIT_IF_USER_PRESSES_Y", + /* 136 */ + "IV|GET_ITEM_UNK3", + "B|UNK137", + "|VGA_POINTER_OP_4", + "II|SET_PARENT_SPECIAL", + /* 140 */ + "|DEL_TE_AND_ADD_ONE", + "BI|SET_M1_OR_M3", + "WJ|IS_HITAREA_0x40_CLEAR", + "I|START_ITEM_SUB", + /* 144 */ + NULL, + NULL, + NULL, + NULL, + /* 148 */ + NULL, + NULL, + NULL, + "BI|SET_ARRAY6_TO", + /* 152 */ + "BB|SET_M1_M3_TO_ARRAY6", + "B|SET_BIT", + "B|CLEAR_BIT", + "BJ|IS_BIT_CLEAR", + /* 156 */ + "BJ|IS_BIT_SET", + "IBB|GET_ITEM_PROP", + "IBW|SET_ITEM_PROP", + NULL, + /* 160 */ + "B|UNK160", + "BWBW|SETUP_TEXT", +#if defined SIMON1WIN || defined SIMON2 + "BBTW|PRINT_STR", +#endif +#ifdef SIMON1DOS + "BBT|PRINT_STR", +#endif + "W|SOUND_1", + /* 164 */ + "|UNK164", + "IWWJ|ITEM_UNK1_UNK2_IS", + "B|SET_BIT2", + "B|CLEAR_BIT2", + /* 168 */ + "BJ|IS_BIT2_CLEAR", + "BJ|IS_BIT2_SET", + NULL, + NULL, + /* 172 */ + NULL, + NULL, + NULL, + "|VGA_POINTER_OP_1", + /* 176 */ + "|VGA_POINTER_OP_2", + "BBI|UNK177", + "WWBB|PATHFIND", + "BBB|UNK179", + /* 180 */ + "|FORCE_UNLOCK", + "|FORCE_LOCK", + "|READ_VGARES_328", + "|READ_VGARES_23", + /* 184 */ + "W|CLEAR_VGAPOINTER_ENTRY", + "W|DUMMY_185", + "|VGA_POINTER_OP_3", + "|FADE_TO_BLACK", +#ifdef SIMON2 + /* 188 */ + "BSJ|STRING2_IS", + "|UNK189", + "B|UNK190", +#endif +}; + +byte *SimonState::dumpOpcode(byte *p) { + byte opcode; + const char *s, *st; + + opcode = *p++; + if (opcode == 255) + return NULL; + st = s = opcode_name_table[opcode]; + if (s == NULL) { + error("INVALID OPCODE %d\n", opcode); + return NULL; + } + while (*st != '|') st++; + fprintf(_dump_file,"%s ", st+1); + + for(;;) { + switch(*s++) { + case 'x': + fprintf(_dump_file,"\n"); + return NULL; + case '|': + fprintf(_dump_file,"\n"); + return p; + case 'B': { + byte b = *p++; + if (b==255) + fprintf(_dump_file,"[%d] ", *p++); + else + fprintf(_dump_file,"%d ", b); + break; + } + case 'V': { + byte b = *p++; + if (b==255) + fprintf(_dump_file,"[[%d]] ", *p++); + else + fprintf(_dump_file,"[%d] ", b); + break; + } + + case 'W': { + int n = (int16)((p[0]<<8)|p[1]); + p+=2; + if (n>=30000 && n<30512) + fprintf(_dump_file,"[%d] ", n - 30000); + else + fprintf(_dump_file,"%d ", n); + break; + } + + case 'w': { + int n = (int16)((p[0]<<8)|p[1]); + p+=2; + fprintf(_dump_file,"%d ", n); + break; + } + + case 'I': { + int n = (int16)((p[0]<<8)|p[1]);; + p+=2; + if (n == -1) + fprintf(_dump_file,"ITEM_M1 "); + else if (n == -3) + fprintf(_dump_file,"ITEM_M3 "); + else if (n == -5) + fprintf(_dump_file,"ITEM_1 "); + else if (n == -7) + fprintf(_dump_file,"ITEM_0 "); + else if (n == -9) + fprintf(_dump_file,"ITEM_A_PARENT "); + else + fprintf(_dump_file,"<%d> ", n); + break; + } + case 'J': { + fprintf(_dump_file,"-> "); + } break; + + + case 'T': { + uint n = ((p[0]<<8)|p[1]); + p+=2; + if (n != 0xFFFF) + fprintf(_dump_file,"\"%s\"(%d) ", getStringPtrByID(n), n); + else + fprintf(_dump_file,"NULL_STRING "); + } break; + } + } +} + +void SimonState::dumpSubroutineLine(SubroutineLine *sl, Subroutine *sub) { + byte *p; + + + printf("; ****\n"); + + p = (byte*)sl + SUBROUTINE_LINE_SMALL_SIZE; + if (sub->id == 0) { + fprintf(_dump_file,"; cond_a=%d, cond_b=%d, cond_c=%d\n", sl->cond_a, sl->cond_b, sl->cond_c); + p = (byte*)sl + SUBROUTINE_LINE_BIG_SIZE; + } + + for(;;) { + p = dumpOpcode(p); + if (p==NULL) + break; + } +} + +void SimonState::dumpSubroutine(Subroutine *sub) { + SubroutineLine *sl; + + fprintf(_dump_file,"\n******************************************\n;Subroutine, ID=%d:\nSUB_%d:\n", sub->id, sub->id); + sl = (SubroutineLine*) ((byte*)sub + sub->first); + for(;(byte*)sl != (byte*)sub; sl = (SubroutineLine*) ((byte*)sub + sl->next) ) { + dumpSubroutineLine(sl, sub); + } + fprintf(_dump_file,"\nEND ******************************************\n"); + fflush(_dump_file); +} + +void SimonState::dumpSubroutines() { + Subroutine *sub = _subroutine_list; + for(;sub;sub = sub->next) { + dumpSubroutine(sub); + } +} + +const char * const video_opcode_name_table[] = { + /* 0 */ + "x|RET", + "ddd|DUMMY", + "d|CALL", + "ddddd|NEW_THREAD", + /* 4 */ + "ddd|DUMMY_2", + "vd|SKIP_IF_NEQ", + "d|SKIP_IFN_SIB_WITH_A", + "d|SKIP_IF_SIB_WITH_A", + /* 8 */ + "dd|SKIP_IF_PARENT_IS", + "dd|SKIP_IF_UNK3_IS", +#ifdef SIMON2 + "ddddb|DRAW", +#else + "ddddd|DRAW", +#endif + "|CLEAR_PATHFIND_ARRAY", + /* 12 */ +#ifdef SIMON2 + "b|DELAY", +#else + "d|DELAY", +#endif + "d|OFFSET_X", + "d|OFFSET_Y", + "d|IDENT_WAKEUP", + /* 16 */ + "d|IDENT_SLEEP", + "dq|SET_PATHFIND_ITEM", + "i|JUMP_REL", + "|CHAIN_TO", + /* 20 */ + "dd|SET_CODE_WORD", + "i|JUMP_IF_CODE_WORD", + "dd|SET_PAL", + "d|SET_PRI", + /* 24 */ + "diid|SET_IMG_XY", + "x|HALT_THREAD", + "ddddd|SET_WINDOW", + "|RESET", + /* 28 */ + "dddd|DUMMY_3", + "|STOP_ALL_SOUNDS", + "d|SET_BASE_DELAY", + "d|SET_PALETTE_MODE", + /* 32 */ + "vv|COPY_VAR", + "|FORCE_UNLOCK", + "|FORCE_LOCK", + "dd|DUMMY_4", + /* 36 */ + "dd|SAVELOAD_THING", + "v|OFFSET_Y_F", + "v|SKIP_IF_VAR_ZERO", + "vd|SET_VAR", + /* 40 */ + "vd|ADD_VAR", + "vd|SUB_VAR", + "vd|SLEEP_UNTIL_SET", + "d|SKIP_IF_BIT_CLEAR", + /* 44 */ + "d|SKIP_IF_BIT_SET", + "v|SET_X_F", + "v|SET_Y_F", + "vv|ADD_VAR_F", + /* 48 */ + "|VC_48", + "d|SET_BIT", + "d|CLEAR_BIT", + "d|CLEAR_HITAREA_BIT_0x40", + /* 52 */ + "d|VC_52", + "dd|DUMMY_5", + "ddd|DUMMY_6", + "ddd|OFFSET_HIT_AREA", + /* 56 */ +#ifdef SIMON2 + "i|SLEEP_EX", +#else + "|DUMMY_7", +#endif + "|DUMMY_8", + "|DUMMY_9", +#ifdef SIMON2 + "ddd|KILL_MULTI_THREAD", +#else + "|SKIP_IF_SOUND??", +#endif + /* 60 */ +#ifdef SIMON2 + "dd|KILL_THREAD", +#else + "d|KILL_THREAD", +#endif + "ddd|INIT_SPRITE", + "|PALETTE_THING", + "|PALETTE_THING_2", +#ifdef SIMON2 + /* 64 */ + "|UNK64", + "|UNK65", + "|UNK66", + "|UNK67", + /* 68 */ + "|UNK68", + "dd|UNK69", + "dd|UNK70", + "|UNK71", + /* 72 */ + "dd|UNK72", + "bb|UNK73", + "bb|UNK74", +#endif +}; + +void SimonState::dump_video_script(byte *src, bool one_opcode_only) { + uint opcode; + const char *str, *strn; + + do { + if (!(_game & GAME_SIMON2)) { + opcode = READ_BE_UINT16_UNALIGNED(src); + src+=2; + } else { + opcode = *src++; + } + + if (opcode >= gss->NUM_VIDEO_OP_CODES) { + error("Invalid opcode %x\n", opcode); + return; + } + + strn = str = video_opcode_name_table[opcode]; + while (*strn != '|') strn++; + fprintf(_dump_file,"%.2d: %s ", opcode, strn + 1); + + for (;*str != '|';str++) { + switch(*str) { + case 'x': fprintf(_dump_file,"\n"); return; + case 'b': fprintf(_dump_file,"%d ", *src++); break; + case 'd': fprintf(_dump_file,"%d ", READ_BE_UINT16_UNALIGNED(src)); src+=2; break; + case 'v': fprintf(_dump_file,"[%d] ", READ_BE_UINT16_UNALIGNED(src)); src+=2; break; + case 'i': fprintf(_dump_file,"%d ", (int16)READ_BE_UINT16_UNALIGNED(src)); src+=2; break; + case 'q': + while (READ_BE_UINT16_UNALIGNED(src) != 999) { + fprintf(_dump_file,"(%d,%d) ", READ_BE_UINT16_UNALIGNED(src), READ_BE_UINT16_UNALIGNED(src+2)); + src += 4; + } + src++; + break; + default: + error("Invalid fmt string '%c' in decompile VGA", *str); + } + } + + fprintf(_dump_file,"\n"); + } while(!one_opcode_only); +} + +void SimonState::dump_vga_file(byte *vga) { + { + byte *pp; + byte *p; + int count; + + pp = vga; + p = pp + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header*)pp)->hdr2_start); + count = READ_BE_UINT16_UNALIGNED(&((VgaFile1Header2*)p)->id_count); + p = pp + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header2*)p)->id_table); + while (--count >= 0) { + int id = READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x6*)p)->id); + + dump_vga_script_always(vga + READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x6*)p)->script_offs), id/100, id); + p += sizeof(VgaFile1Struct0x6); + } + } + + { + byte *bb, *b; + int c; + + bb = vga; + b = bb + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header*)bb)->hdr2_start); + c = READ_BE_UINT16_UNALIGNED(&((VgaFile1Header2*)b)->unk1); + b = bb + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header2*)b)->unk2_offs); + + while (--c >= 0) { + int id = READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x8*)b)->id); + + dump_vga_script_always(vga + READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x8*)b)->script_offs), id/100, id); + b += sizeof(VgaFile1Struct0x8); + } + } +} + + + +const byte bmp_hdr[] = { +0x42,0x4D, +0x9E,0x14,0x00,0x00, /* offset 2, file size */ +0x00,0x00,0x00,0x00, +0x36,0x04,0x00,0x00, +0x28,0x00,0x00,0x00, + +0x3C,0x00,0x00,0x00, /* image width */ +0x46,0x00,0x00,0x00, /* image height */ +0x01,0x00,0x08,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00, + +0x00,0x01,0x00,0x00, +0x00,0x01,0x00,0x00, +}; + +void dump_bmp(const char *filename, int w, int h, const byte *bytes, const uint32 *palette) { + FILE *out = fopen(filename, "wb"); + byte my_hdr[sizeof(bmp_hdr)]; + int i; + + if (out == NULL) { + printf("DUMP ERROR\n"); + return; + } + + memcpy(my_hdr, bmp_hdr, sizeof(bmp_hdr)); + + *(uint32*)(my_hdr + 2) = w*h + 1024 + sizeof(bmp_hdr); + *(uint32*)(my_hdr + 18) = w; + *(uint32*)(my_hdr + 22) = h; + + + fwrite(my_hdr, 1, sizeof(my_hdr), out); + + for(i=0; i!=256; i++,palette++) { + byte color[4]; + color[0] = (byte)(*palette >> 16); + color[1] = (byte)(*palette >> 8); + color[2] = (byte)(*palette); + color[3] = 0; + fwrite(color, 1, 4, out); + } + + while (--h >= 0) { + fwrite(bytes + h * ((w+3)&~3), ((w+3)&~3), 1, out); + } + + fclose(out); +} + +void dump_bitmap(const char *filename, byte *offs, int w, int h, int flags, const byte *palette, byte base) { + /* allocate */ + byte *b = (byte*)malloc(w*h); + int i,j; + + VC10_state state; + + state.depack_cont = -0x80; + state.depack_src = offs; + state.dh = h; + state.y_skip = 0; + + for(i=0; i!=w; i+=2) { + byte *c = vc_10_depack_column(&state); + for(j=0;j!=h;j++) { + byte pix = c[j]; + b[j*w+i] = (pix>>4)|base; + b[j*w+i+1] = (pix&0xF)|base; + + } + } + + dump_bmp(filename, w, h, b, (uint32*)palette); + free(b); +} + +void SimonState::dump_single_bitmap(int file, int image, byte *offs, int w, int h, byte base) { +/* Only supported for win32 atm. mkdir doesn't work otherwise. */ +#if defined (WIN32) && !defined(_WIN32_WCE) + char buf[255], buf2[255]; + struct stat statbuf; + + sprintf(buf, "bmp_%d\\%d.bmp", file, image); + + if (stat(buf, &statbuf) == 0) + return; + + sprintf(buf2, "bmp_%d", file); + mkdir(buf2); + + dump_bitmap(buf, offs, w, h, 0, _palette, base); +#endif +} + +void SimonState::dump_vga_script_always(byte *ptr, uint res, uint sprite_id) { + fprintf(_dump_file,"; address=%x, vgafile=%d vgasprite=%d\n", + ptr - _vga_buffer_pointers[res].vgaFile1, res, sprite_id); + dump_video_script(ptr, false); + fprintf(_dump_file,"; end\n"); +} + +void SimonState::dump_vga_script(byte *ptr, uint res, uint sprite_id) { + dump_Vga_script_always(ptr,res,sprite_id); +} + + +#endif diff --git a/simon/simonitems.cpp b/simon/simonitems.cpp new file mode 100644 index 0000000000..9d39a99783 --- /dev/null +++ b/simon/simonitems.cpp @@ -0,0 +1,1371 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001/2002 The ScummVM project + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +// Item script opcodes for Simon1/Simon2 +#include "stdafx.h" +#include "simon.h" + +int SimonState::runScript() { + byte opcode; + bool flag, condition; + + do { +#ifdef DUMP_CONTINOUS_MAINSCRIPT + dumpOpcode(_code_ptr); +#endif + + opcode = getByte(); + if (opcode==0xFF) + return 0; + + if (_run_script_return_1) + return 1; + + /* Invert condition? */ + flag = false; + if (opcode==0) { + flag = true; + opcode = getByte(); + if (opcode==0xFF) + return 0; + } + + condition = true; + + switch(opcode) { + case 1: { /* ptrA parent is */ + condition = (getItem1Ptr()->parent == getNextItemID()); + } break; + + case 2: { /* ptrA parent is not */ + condition = (getItem1Ptr()->parent != getNextItemID()); + } break; + + case 5: { /* parent is 1 */ + condition = (getNextItemPtr()->parent == getItem1ID()); + } break; + + case 6: { /* parent isnot 1 */ + condition = (getNextItemPtr()->parent != getItem1ID()); + } break; + + case 7: { /* parent is */ + Item *item = getNextItemPtr(); + condition = (item->parent == getNextItemID()); + } break; + + case 11: { /* is zero */ + condition = (getNextVarContents() == 0); + } break; + + case 12: { /* isnot zero */ + condition = (getNextVarContents() != 0); + } break; + + case 13: { /* equal */ + uint tmp = getNextVarContents(); + condition = (tmp == getVarOrWord()); + } break; + + case 14: { /* not equal */ + uint tmp = getNextVarContents(); + condition = (tmp != getVarOrWord()); + } break; + + case 15: { /* is greater */ + uint tmp = getNextVarContents(); + condition = (tmp > getVarOrWord()); + } break; + + case 16: { /* is less */ + uint tmp = getNextVarContents(); + condition = (tmp < getVarOrWord()); + } break; + + case 17: { /* is eq f */ + uint tmp = getNextVarContents(); + condition = (tmp == getNextVarContents()); + } break; + + case 18: { /* is not equal f */ + uint tmp = getNextVarContents(); + condition = (tmp != getNextVarContents()); + } break; + + case 19: { /* is greater f */ + uint tmp = getNextVarContents(); + condition = (tmp < getNextVarContents()); + } break; + + case 20: { /* is less f */ + uint tmp = getNextVarContents(); + condition = (tmp > getNextVarContents()); + } break; + + case 23: { + condition = o_unk_23(getVarOrWord()); + } break; + + case 25: { /* has child of type 1 */ + condition = hasChildOfType1(getNextItemPtr()); + } break; + + case 26: { /* has child of type 2 */ + condition = hasChildOfType2(getNextItemPtr()); + } break; + + case 27: { /* item unk3 is */ + Item *item = getNextItemPtr(); + condition = ((uint)item->unk3 == getVarOrWord()); + } break; + + case 28: { /* item has prop */ + Child2 *child = findChildOfType2(getNextItemPtr()); + byte num = getVarOrByte(); + condition = child!=NULL && (child->avail_props & (1<<num)) != 0; + } break; + + case 31: { /* set no parent */ + setItemParent(getNextItemPtr(), NULL); + } break; + + case 33: { /* set item parent */ + Item *item = getNextItemPtr(); + setItemParent(item, getNextItemPtr()); + } break; + + case 36: { /* copy var */ + uint value = getNextVarContents(); + writeNextVarContents(value); + } break; + + case 41: { /* zero var */ + writeNextVarContents(0); + } break; + + case 42: { /* set var */ + uint var = getVarOrByte(); + writeVariable(var, getVarOrWord()); + } break; + + case 43: { /* add */ + uint var = getVarOrByte(); + writeVariable(var, readVariable(var) + getVarOrWord()); + } break; + + case 44: { /* sub */ + uint var = getVarOrByte(); + writeVariable(var, readVariable(var) - getVarOrWord()); + } break; + + case 45: { /* add f */ + uint var = getVarOrByte(); + writeVariable(var, readVariable(var) + getNextVarContents()); + } break; + + case 46: { /* sub f */ + uint var = getVarOrByte(); + writeVariable(var, readVariable(var) - getNextVarContents()); + } break; + + case 47: { /* mul */ + uint var = getVarOrByte(); + writeVariable(var, readVariable(var) * getVarOrWord()); + } break; + + case 48: { /* div */ + uint var = getVarOrByte(); + int value = getVarOrWord(); + if (value == 0) + error("Division by zero in div"); + writeVariable(var, readVariable(var) / value); + } break; + + case 49: { /* mul f */ + uint var = getVarOrByte(); + writeVariable(var, readVariable(var) * getNextVarContents()); + } break; + + case 50: { /* div f */ + uint var = getVarOrByte(); + int value = getNextVarContents(); + if (value == 0) + error("Division by zero in div f"); + writeVariable(var, readVariable(var) / value); + } break; + + case 51: { /* mod */ + uint var = getVarOrByte(); + int value = getVarOrWord(); + if (value == 0) + error("Division by zero in mod"); + writeVariable(var, readVariable(var) % value); + } break; + + case 52: { /* mod f */ + uint var = getVarOrByte(); + int value = getNextVarContents(); + if (value == 0) + error("Division by zero in mod f"); + writeVariable(var, readVariable(var) % value); + } break; + + case 53: { /* random */ + uint var = getVarOrByte(); + uint value = (uint16)getVarOrWord(); + uint rand_value; + + for(;;) { + uint value_2 = value; + rand_value = rand() & 0x7FFF; + + if (value == 0) + error("Invalid random range"); + + value = 0x8000 / value; + + if (value == 0) + error("Invalid random range"); + + if (rand_value / value != value_2) + break; + + value = value_2; + } + + writeVariable(var, rand_value / value); + } break; + + case 55: { /* set itemA parent */ + setItemParent(getItem1Ptr(), getNextItemPtr()); + } break; + + case 56: { /* set child2 fr bit */ + Child2 *child = findChildOfType2(getNextItemPtr()); + int value = getVarOrByte(); + if (child != NULL && value >= 0x10) + child->avail_props |= 1<<value; + } break; + + case 57: { /* clear child2 fr bit */ + Child2 *child = findChildOfType2(getNextItemPtr()); + int value = getVarOrByte(); + if (child != NULL && value >= 0x10) + child->avail_props &= ~(1<<value); + } break; + + case 58: { /* make siblings */ + Item *item = getNextItemPtr(); + setItemParent(item, derefItem(getNextItemPtr()->parent)); + } break; + + case 59: { /* item inc unk3 */ + Item *item = getNextItemPtr(); + if (item->unk3<=30000) + setItemUnk3(item, item->unk3 + 1); + } break; + + case 60: { /* item dec unk3 */ + Item *item = getNextItemPtr(); + if (item->unk3>=0) + setItemUnk3(item, item->unk3 - 1); + } break; + + case 61: { /* item set unk3 */ + Item *item = getNextItemPtr(); + int value = getVarOrWord(); + if (value<0) value = 0; + if (value>30000) value = 30000; + setItemUnk3(item, value); + } break; + + case 62: { /* show int */ + showMessageFormat("%d", getNextVarContents()); + } break; + + case 63: { /* show string nl */ + showMessageFormat("%s\n", getStringPtrByID(getNextStringID())); + } break; + + case 64: { /* show string */ + showMessageFormat("%s", getStringPtrByID(getNextStringID())); + } break; + + case 65: { /* add hit area */ + int id = getVarOrWord(); + int x = getVarOrWord(); + int y = getVarOrWord(); + int w = getVarOrWord(); + int h = getVarOrWord(); + int number = getVarOrByte(); + if (number < 20) + addNewHitArea(id, x, y, w, h, (number<<8) + 129, 0xD0, &_dummy_item_2); + } break; + + case 66: { /* set array 2 */ + uint var = getVarOrByte(); + uint string_id = getNextStringID(); + if (var < 20) + _stringid_array_2[var] = string_id; + } break; + + case 67: { /* set array 3 and 4 */ + if (_game == GAME_SIMON1WIN || _game&GAME_SIMON2) { + uint var = getVarOrByte(); + uint string_id = getNextStringID(); + uint value = getNextWord(); + if (var < 20) { + _stringid_array_3[var] = string_id; + _array_4[var] = value; + } + } else { + uint var = getVarOrByte(); + uint string_id = getNextStringID(); + if (var < 20) { + _stringid_array_3[var] = string_id; + } + } + } break; + + case 68: { /* exit interpreter */ + error("Exit interpreter opcode"); + } break; + + case 69: { /* return 1 */ + return 1; + } + + case 70: { /* show string from array */ + const char *str = (const char*)getStringPtrByID(_stringid_array_3[getVarOrByte()]); + + if (_game & GAME_SIMON2) { + writeVariable(51, strlen(str)/53 * 8 + 8); + } + + showMessageFormat("%s\n", str); + } break; + + case 71: { /* start subroutine */ + Subroutine *sub = getSubroutineByID(getVarOrWord()); + if (sub != NULL) + startSubroutine(sub); + } break; + + case 76: { /* add event */ + uint timeout = getVarOrWord(); + addTimeEvent(timeout, getVarOrWord()); + } break; + + case 77: { /* has item minus 1 */ + condition = _subject_item != NULL; + } break; + + case 78: { /* has item minus 3 */ + condition = _object_item != NULL; + } break; + + case 79: { /* childstruct fr2 is */ + Child2 *child = findChildOfType2(getNextItemPtr()); + uint string_id = getNextStringID(); + condition = (child != NULL) && child->string_id == string_id; + } break; + + case 80: { /* item equal */ + condition = getNextItemPtr() == getNextItemPtr(); + } break; + + case 82: { /* dummy opcode? */ + getVarOrByte(); + } break; + + case 83: { /* restart subroutine */ + return -10; + } + + case 87: { /* dummy opcode? */ + getNextStringID(); + } break; + + case 88: { /* or_lock_word */ + _lock_word |= 0x10; + } break; + + case 89: { /* and lock word */ + _lock_word &= ~0x10; + } break; + + case 90: { /* set minusitem to parent */ + Item *item = derefItem(getNextItemPtr()->parent); + switch(getVarOrByte()) { + case 0: + _object_item = item; + break; + case 1: + _subject_item = item; + break; + default: + error("set minusitem to parent, invalid subcode"); + } + } break; + + case 91: { /* set minusitem to sibling */ + Item *item = derefItem(getNextItemPtr()->sibling); + switch(getVarOrByte()) { + case 0: + _object_item = item; + break; + case 1: + _subject_item = item; + break; + default: + error("set minusitem to sibling, invalid subcode"); + } + } break; + + case 92: { /* set minusitem to child */ + Item *item = derefItem(getNextItemPtr()->child); + switch(getVarOrByte()) { + case 0: + _object_item = item; + break; + case 1: + _subject_item = item; + break; + default: + error("set minusitem to child, invalid subcode"); + } + } break; + + case 96: { + uint val = getVarOrWord(); + o_set_video_mode(getVarOrByte(), val); + } break; + + case 97: { /* load vga */ + ensureVgaResLoadedC(getVarOrWord()); + } break; + + case 98: { + if (!(_game & GAME_SIMON2)) { + uint a = getVarOrWord(); + uint b = getVarOrByte(); + uint c = getVarOrWord(); + uint d = getVarOrWord(); + uint f = getVarOrWord(); + start_vga_code(b, a/100, a, c, d, f); + } else { + uint a = getVarOrWord(); + uint b = getVarOrWord(); + uint c = getVarOrByte(); + uint d = getVarOrWord(); + uint e = getVarOrWord(); + uint f = getVarOrWord(); + start_vga_code(c,a,b,d,e,f); + } + } break; + + case 99: { + if (!(_game & GAME_SIMON2)) { + o_unk_99_simon1(getVarOrWord()); + } else { + uint a = getVarOrWord(); + uint b = getVarOrWord(); + o_unk_99_simon2(a,b); + } + } break; + + case 100: { + o_vga_reset(); + } break; + + case 101: { + uint a = getVarOrByte(); + uint b = getVarOrWord(); + uint c = getVarOrWord(); + uint d = getVarOrWord(); + uint e = getVarOrWord(); + uint f = getVarOrWord(); + uint g = getVarOrWord(); + o_unk26_helper(a, b, c, d, e, f, g, 0); + } break; + + case 102: { + fcs_unk_2(getVarOrByte() & 7); + } break; + + case 103: { + o_unk_103(); + } break; + + case 104: { + fcs_delete(getVarOrByte() & 7); + } break; + + case 107: { /* ADD_ITEM_HITAREA(id,x,y,w,h,item,unk3) */ + uint flags = 0; + uint id = getVarOrWord(); + uint params = id / 1000; + uint x,y,w,h,unk3; + Item *item; + + id = id % 1000; + + if (params & 1) flags |= 8; + if (params & 2) flags |= 4; + if (params & 4) flags |= 0x80; + if (params & 8) flags |= 1; + if (params & 16) flags |= 0x10; + + x = getVarOrWord(); + y = getVarOrWord(); + w = getVarOrWord(); + h = getVarOrWord(); + item = getNextItemPtrStrange(); + unk3 = getVarOrWord(); + if (x >= 1000) { + unk3 += 0x4000; + x -= 1000; + } + addNewHitArea(id, x, y, w, h, flags, unk3, item); + } break; + + case 108: { /* delete hitarea */ + delete_hitarea(getVarOrWord()); + } break; + + case 109: { /* clear hitarea bit 0x40 */ + clear_hitarea_bit_0x40(getVarOrWord()); + } break; + + case 110: { /* set hitarea bit 0x40 */ + set_hitarea_bit_0x40(getVarOrWord()); + } break; + + case 111: { /* set hitarea xy */ + uint hitarea_id = getVarOrWord(); + uint x = getVarOrWord(); + uint y = getVarOrWord(); + set_hitarea_x_y(hitarea_id, x, y); + } break; + + case 114: { + Item *item = getNextItemPtr(); + uint fcs_index = getVarOrByte(); + lock(); + fcs_unk_proc_1(fcs_index, item, 0, 0); + unlock(); + } break; + + case 115: { /* item has flag */ + Item *item = getNextItemPtr(); + condition = (item->unk4 & (1 << getVarOrByte())) != 0; + } break; + + case 116: { /* item set flag */ + Item *item = getNextItemPtr(); + item->unk4 |= (1 << getVarOrByte()); + } break; + + case 117: { /* item clear flag */ + Item *item = getNextItemPtr(); + item->unk4 &= ~(1 << getVarOrByte()); + } break; + + case 119: { /* WAIT_VGA */ + uint var = getVarOrWord(); + _scriptvar_2 = (var==200); + + if (var!=200 || !_skip_vga_wait) + o_wait_for_vga(var); + _skip_vga_wait = false; + } break; + + case 120: { + o_unk_120(getVarOrWord()); + } break; + + case 121: { /* SET_VGA_ITEM */ + uint slot = getVarOrByte(); + _vc_item_array[slot] = getNextItemPtr(); + } break; + + case 125: { /* item is sibling with item 1 */ + Item *item = getNextItemPtr(); + condition = (getItem1Ptr()->parent == item->parent); + } break; + + case 126: { + Item *item = getNextItemPtr(); + uint fcs_index = getVarOrByte(); + uint a = 1<<getVarOrByte(); + lock(); + fcs_unk_proc_1(fcs_index, item, 1, a); + unlock(); + } break; + + case 127: { /* deals with music */ + o_unk_127(); + } break; + + case 128: { /* dummy instruction? */ + getVarOrWord(); + } break; + + case 129: { /* dummy instruction? */ + getVarOrWord(); + condition = true; + } break; + + case 130: { /* set script cond */ + uint a = getVarOrByte(); + if (a == 1) { + getNextWord(); + _script_cond_b = getNextWord(); + } else { + getNextWord(); + _script_cond_c = getNextWord(); + } + } break; + + case 132: { + o_save_game(); + } break; + + case 133: { + o_load_game(); + } break; + + case 134: { + warning("stopMidiMusic: not implemented"); + /* dummy proc */ + } break; + + case 135: { + error("Quit if user presses Y unimplemented"); + } break; + + case 136: { /* set var to item unk3 */ + Item *item = getNextItemPtr(); + writeNextVarContents(item->unk3); + } break; + + case 137: { + o_unk_137(getVarOrByte()); + } break; + + case 138: { + o_unk_138(); + } break; + + case 139: { /* SET_PARENT_SPECIAL */ + Item *item = getNextItemPtr(); + _no_parent_notify = true; + setItemParent(item, getNextItemPtr()); + _no_parent_notify = false; + } break; + + case 140: { + killAllTimers(); + addTimeEvent(3, 0xA0); + } break; + + case 141: { + uint which = getVarOrByte(); + Item *item = getNextItemPtr(); + if(which == 1) { + _subject_item = item; + } else { + _object_item = item; + } + } break; + + case 142: { + condition = is_hitarea_0x40_clear(getVarOrWord()); + } break; + + case 143: { /* start item sub */ + Child1 *child = findChildOfType1(getNextItemPtr()); + if (child != NULL) { + Subroutine *sub = getSubroutineByID(child->subroutine_id); + if (sub) + startSubroutine(sub); + } + } break; + + case 151: { /* set array6 to item */ + uint var = getVarOrByte(); + Item *item = getNextItemPtr(); + _item_array_6[var] = item; + } break; + + case 152: { /* set m1 or m3 to array6 */ + Item *item = _item_array_6[getVarOrByte()]; + uint var = getVarOrByte(); + if (var==1) { + _subject_item = item; + } else { + _object_item = item; + } + } break; + + case 153: { /* set bit */ + uint bit = getVarOrByte(); + _bit_array[bit>>4] |= 1<<(bit&15); + break; + } + + case 154: { /* clear bit */ + uint bit = getVarOrByte(); + _bit_array[bit>>4] &= ~(1<<(bit&15)); + break; + } + + case 155: { /* is bit clear? */ + uint bit = getVarOrByte(); + condition = (_bit_array[bit>>4] & (1<<(bit&15))) == 0; + } break; + + case 156: { /* is bit set? */ + uint bit = getVarOrByte(); + condition = (_bit_array[bit>>4] & (1<<(bit&15))) != 0; + } break; + + case 157: { /* get item int prop */ + Item *item = getNextItemPtr(); + Child2 *child = findChildOfType2(item); + uint prop = getVarOrByte(); + + if (child != NULL && child->avail_props&(1<<prop) && prop < 16) { + uint offs = getOffsetOfChild2Param(child, 1<<prop); + writeNextVarContents(child->array[offs]); + } else { + writeNextVarContents(0); + } + } break; + + case 158: { /* set item prop */ + Item *item = getNextItemPtr(); + Child2 *child = findChildOfType2(item); + uint prop = getVarOrByte(); + int value = getVarOrWord(); + + if (child != NULL && child->avail_props&(1<<prop) && prop < 16) { + uint offs = getOffsetOfChild2Param(child, 1<<prop); + child->array[offs] = value; + } + } break; + + case 160: { + o_unk_160(getVarOrByte()); + } break; + + case 161: { /* setup text */ + uint value = getVarOrByte(); + ThreeValues *tv; + + switch(value) { + case 1: tv = &_threevalues_1; break; + case 2: tv = &_threevalues_2; break; + case 101: tv = &_threevalues_3; break; + case 102: tv = &_threevalues_4; break; + default: + error("setup text, invalid value %d", value); + } + + tv->a = getVarOrWord(); + tv->b = getVarOrByte(); + tv->c = getVarOrWord(); + } break; + + case 162: { + o_print_str(); + } break; + + case 163: { + o_unk_163(getVarOrWord()); + } break; + + case 164: { + _show_preposition = true; + o_setup_cond_c(); + _show_preposition = false; + } break; + + case 165: { + Item *item = getNextItemPtr(); + int16 a = getNextWord(), + b = getNextWord(); + condition = (item->unk2 == a && item->unk1 == b); + } break; + + case 166: { /* set bit2 */ + uint bit = getVarOrByte(); + _bit_array[(bit>>4)+16] |= 1<<(bit&15); + } break; + + case 167: { /* clear bit2 */ + uint bit = getVarOrByte(); + _bit_array[(bit>>4)+16] &= ~(1<<(bit&15)); + } break; + + case 168: { /* is bit clear? */ + uint bit = getVarOrByte(); + condition = (_bit_array[(bit>>4)+16] & (1<<(bit&15))) == 0; + } break; + + case 169: { /* is bit set? */ + uint bit = getVarOrByte(); + condition = (_bit_array[(bit>>4)+16] & (1<<(bit&15))) != 0; + } break; + + case 175: { + o_unk_175(); + } break; + + case 176: { + o_unk_176(); + } break; + + case 177: { + o_177(); + } break; + + case 178: { /* path find */ + uint a = getVarOrWord(); + uint b = getVarOrWord(); + uint c = getVarOrByte(); + uint d = getVarOrByte(); + o_pathfind(a,b,c,d); + } break; + + case 179: { + if (_game == GAME_SIMON1WIN) { + uint b = getVarOrByte(); + /*uint c = */getVarOrByte(); + uint a = getVarOrByte(); + uint d = _array_4[a]; + if (d!=0) + talk_with_speech(d, b); + } else if (_game == GAME_SIMON1DOS) { + uint b = getVarOrByte(); + uint c = getVarOrByte(); + uint a = getVarOrByte(); + const char *s = (const char*)getStringPtrByID(_stringid_array_3[a]); + ThreeValues *tv; + + switch(b) { + case 1: tv = &_threevalues_1; break; + case 2: tv = &_threevalues_2; break; + case 101: tv = &_threevalues_3; break; + case 102: tv = &_threevalues_4; break; + default: + error("setup text, invalid value %d", b); + } + + talk_with_text(b, c, s, tv->a, tv->b, tv->c); + } else if (_game == GAME_SIMON2WIN || _game == GAME_SIMON2DOS) { + uint b = getVarOrByte(); + uint c = getVarOrByte(); + uint a = getVarOrByte(); + uint d; + const char *s = (const char*)getStringPtrByID(_stringid_array_3[a]); + ThreeValues *tv; + + switch(b) { + case 1: tv = &_threevalues_1; break; + case 2: tv = &_threevalues_2; break; + case 101: tv = &_threevalues_3; break; + case 102: tv = &_threevalues_4; break; + default: + error("setup text, invalid value %d", b); + } + + d = _array_4[a]; + if (d!=0 && !_vk_t_toggle) + talk_with_speech(d, b); + + if (s!=NULL && _vk_t_toggle) + talk_with_text(b, c, s, tv->a, tv->b, tv->c); + } + } break; + + case 180: { + o_force_unlock(); + } break; + + case 181: { + o_force_lock(); + if (_game == GAME_SIMON2WIN || _game == GAME_SIMON2DOS) { + fcs_unk_2(1); + showMessageFormat("\xC"); + } + } break; + + case 182: { + if (_game & GAME_SIMON2) goto invalid_opcode; + o_read_vgares_328(); + } break; + + case 183: { + if (_game & GAME_SIMON2) goto invalid_opcode; + o_read_vgares_23(); + } break; + + case 184: { + o_clear_vgapointer_entry(getVarOrWord()); + } break; + + case 185: { + if (_game & GAME_SIMON2) goto invalid_opcode; + getVarOrWord(); + } break; + + case 186: { + o_unk_186(); + } break; + + case 187: { + if (_game & GAME_SIMON2) goto invalid_opcode; + o_fade_to_black(); + } break; + + case 188: + if (!(_game & GAME_SIMON2)) goto invalid_opcode; + { + uint i = getVarOrByte(); + uint str = getNextStringID(); + condition = (str<20 && _stringid_array_2[i] == str); + } break; + + case 189: { + if (!(_game & GAME_SIMON2)) goto invalid_opcode; + _op_189_flags = 0; + } break; + + case 190: { + uint i; + if (!(_game & GAME_SIMON2)) goto invalid_opcode; + i = getVarOrByte(); + if (!(_op_189_flags&(1<<i))) + o_190_helper(i); + } break; + + default: +invalid_opcode:; + error("Invalid opcode '%d'", opcode); + } + + } while (condition != flag); + + return 0; +} + +int SimonState::startSubroutine(Subroutine *sub) { + int result = -1; + SubroutineLine *sl; + byte *old_code_ptr; + +#ifdef DUMP_START_MAINSCRIPT + dumpSubroutine(sub); +#endif + + old_code_ptr = _code_ptr; + + if (++_recursion_depth > 40) + error("Recursion error"); + + sl = (SubroutineLine*)((byte*)sub + sub->first); + + while ((byte*)sl != (byte*)sub) { + if (checkIfToRunSubroutineLine(sl, sub)) { + result = 0; + _code_ptr = (byte*)sl; + if (sub->id) _code_ptr += 2; else _code_ptr += 8; + +#ifdef DUMP_CONTINOUS_MAINSCRIPT + fprintf(_dump_file,"; %d\n", sub->id); +#endif + result = runScript(); + if (result != 0) { + /* result -10 means restart subroutine */ + if (result == -10) { + delay(0); /* maybe leave control to the VGA */ + sl = (SubroutineLine*)((byte*)sub + sub->first); + continue; + } + break; + } + } + sl = (SubroutineLine*)((byte*)sub + sl->next); + } + + _code_ptr = old_code_ptr; + + _recursion_depth--; + return result; +} + +int SimonState::startSubroutineEx(Subroutine *sub) { + _item_1_ptr = _item_1; + return startSubroutine(sub); +} + +bool SimonState::checkIfToRunSubroutineLine(SubroutineLine *sl, Subroutine *sub) { + if (sub->id) + return true; + + if (sl->cond_a != -1 && sl->cond_a != _script_cond_a && + (sl->cond_a != -2 || _script_cond_a != -1)) + return false; + + if (sl->cond_b != -1 && sl->cond_b != _script_cond_b && + (sl->cond_b != -2 || _script_cond_b != -1)) + return false; + + if (sl->cond_c != -1 && sl->cond_c != _script_cond_c && + (sl->cond_c != -2 || _script_cond_c != -1)) + return false; + + return true; +} + +void SimonState::o_190_helper(uint i) { + warning("o_190_helper not implemented"); +} + + +bool SimonState::o_unk_23(uint a) { + if (a == 0) + return 0; + + if (a == 100) + return 1; + + a += _script_unk_1; + if (a<=0) { + _script_unk_1 = 0; + return 0; + } + + if (((uint)(rand()>>5))%100 < a) { + if (_script_unk_1 <= 0) + _script_unk_1 -= 5; + else + _script_unk_1 = 0; + return 1; + } + + if (_script_unk_1 >= 0) + _script_unk_1 += 5; + else + _script_unk_1 = 0; + + return 0; +} + +void SimonState::o_177() { + if (_game == GAME_SIMON1WIN) { + uint a = getVarOrByte(); + /*uint b = */getVarOrByte(); + uint offs; + Child2 *child = findChildOfType2(getNextItemPtr()); + if (child != NULL && child->avail_props&0x200) { + offs = getOffsetOfChild2Param(child, 0x200); + talk_with_speech(child->array[offs], a); + } else if (child != NULL && child->avail_props&0x100) { + offs = getOffsetOfChild2Param(child, 0x100); + talk_with_speech(child->array[offs]+3550, a); + } + } else if (_game == GAME_SIMON1DOS) { + uint a = getVarOrByte(); + uint b = getVarOrByte(); + Child2 *child = findChildOfType2(getNextItemPtr()); + if (child!=NULL && child->avail_props&1) { + const char *s = (const char*)getStringPtrByID(child->array[0]); + ThreeValues *tv; + char buf[256]; + switch(a) { + case 1: tv = &_threevalues_1; break; + case 2: tv = &_threevalues_2; break; + case 101: tv = &_threevalues_3; break; + case 102: tv = &_threevalues_4; break; + default: + error("setup text, invalid value %d", a); + } + + if (child->avail_props&0x100) { + uint x = getOffsetOfChild2Param(child,0x100); + sprintf(buf,"%d%s",child->array[x],s); + s = buf; + } + + talk_with_text(a,b,s,tv->a, tv->b,tv->c); + } + } else if (_game == GAME_SIMON2WIN || _game == GAME_SIMON2DOS) { + uint a = getVarOrByte(); + uint b = getVarOrByte(); + Child2 *child = findChildOfType2(getNextItemPtr()); + const char *s = NULL; + ThreeValues *tv = NULL; + char buf[256]; + + if (child != NULL && child->avail_props&1) { + s = (const char*)getStringPtrByID(child->array[0]); + switch(a) { + case 1: tv = &_threevalues_1; break; + case 2: tv = &_threevalues_2; break; + case 101: tv = &_threevalues_3; break; + case 102: tv = &_threevalues_4; break; + default: + error("setup text, invalid value %d", a); + } + } + + if (child != NULL && child->avail_props&0x200) { + uint var200 = child->array[getOffsetOfChild2Param(child, 0x200)]; + + if (child->avail_props&0x100) { + uint var100 = child->array[getOffsetOfChild2Param(child, 0x100)]; + + if (var200 == 116) var200 = var100 + 115; + if (var200 == 92) var200 = var100 + 98; + if (var200 == 99) var200 = 9; + if (var200 == 97) { + switch(var100) { + case 12: var200 = 109; break; + case 14: var200 = 108; break; + case 18: var200 = 107; break; + case 20: var200 = 106; break; + case 22: var200 = 105; break; + case 28: var200 = 104; break; + case 90: var200 = 103; break; + case 92: var200 = 102; break; + case 100: var200 = 51; break; + default: + error("o_177: invalid case %d", var100); + } + } + } + + if (!_vk_t_toggle) + talk_with_speech(var200, a); + } + + if (!_vk_t_toggle) + return; + + if (child==NULL || !(child->avail_props&1)) + return; + + if (child->avail_props&0x100) { + sprintf(buf, "%d%s", child->array[getOffsetOfChild2Param(child, 0x100)], s); + s = buf; + } + + talk_with_text(a,b,s,tv->a, tv->b,tv->c); + } +} + + +void SimonState::o_unk_137(uint fcs_index) { + FillOrCopyStruct *fcs; + + fcs = _fcs_ptr_array_3[fcs_index & 7]; + if (fcs->fcs_data == NULL) + return; + fcs_unk_proc_1(fcs_index, fcs->fcs_data->item_ptr, fcs->fcs_data->unk1, fcs->fcs_data->unk2); +} + +void SimonState::o_unk_138() { + _vga_buf_start = _vga_buf_free_start; + _vga_file_buf_org = _vga_buf_free_start; +} + +void SimonState::o_unk_186() { + _vga_buf_free_start = _vga_file_buf_org_2; + _vga_buf_start = _vga_file_buf_org_2; + _vga_file_buf_org = _vga_file_buf_org_2; +} + +void SimonState::o_unk_175() { + _vga_buf_start = _vga_buf_free_start; +} + +void SimonState::o_unk_176() { + _vga_buf_free_start = _vga_file_buf_org; + _vga_buf_start = _vga_file_buf_org; +} + +int SimonState::o_unk_132_helper(bool *b, char *buf) { + HitArea *ha; + + *b = true; + + + if (!_saveload_flag) { +strange_jump:; + _saveload_flag = false; + savegame_dialog(buf); + } + +start_over:; + _key_pressed = 0; + +start_over_2:; + _last_hitarea = _last_hitarea_3 = 0; + + do { + if (_key_pressed != 0) { + if (_saveload_flag) { + *b = false; + return _key_pressed; + } + goto start_over; + } + delay(100); + } while (_last_hitarea_3 == 0); + + ha = _last_hitarea; + + if (ha == NULL || ha->id < 205) goto start_over_2; + + if (ha->id == 205) return ha->id; + + if (ha->id == 206) { + if (_saveload_row_curpos == 1) goto start_over_2; + if (_saveload_row_curpos < 7) _saveload_row_curpos = 1; + else _saveload_row_curpos -= 6; + + goto strange_jump; + } + + if (ha->id == 207) { + if (!_savedialog_flag) goto start_over_2; + _saveload_row_curpos += 6; +// if (_saveload_row_curpos >= _num_savegame_rows) +// _saveload_row_curpos = _num_savegame_rows; + goto strange_jump; + } + + if (ha->id >= 214) goto start_over_2; + return ha->id - 208; +} + +void SimonState::o_unk_132_helper_3() { + for(int i=208; i!=208+6; i++) + set_hitarea_bit_0x40(i); +} + +void SimonState::o_unk_132_helper_2(FillOrCopyStruct *fcs, int x) { + byte old_text; + + video_putchar(fcs, x); + old_text = fcs->text_color; + fcs->text_color = fcs->fill_color; + + x += 120; + if (x != 128) x=129; + video_putchar(fcs, x); + + fcs->text_color = old_text; + video_putchar(fcs, 8); +} + +void SimonState::o_unk_127() { + if (_game & GAME_SIMON2) { + uint a = getVarOrWord(); + uint b = getVarOrWord(); + uint c = getVarOrByte(); + + warning("o_unk_127(%d,%d,%d) not implemented properly", a, b, c); + + if (a!=_last_music_played) { + _last_music_played = a; + playMusic(a); + } + } else { + uint a = getVarOrWord(); + /*uint b = */getVarOrWord(); + + if (a!=_last_music_played) { + _last_music_played = a; + playMusic(a); + } + } +} + +void SimonState::o_unk_120(uint a) { + uint16 id = TO_BE_16(a); + _lock_word |= 0x4000; + _vc_ptr = (byte*)&id; + vc_15_start_funkystruct_by_id(); + _lock_word &= ~0x4000; +} + +void SimonState::o_unk_163(uint a) { + playSound(a); +} + +void SimonState::o_unk_160(uint a) { + fcs_proc_1(_fcs_ptr_array_3[_fcs_unk_1], a); +} + +void SimonState::o_unk_103() { + lock(); + fcs_unk1(_fcs_unk_1); + showMessageFormat("\x0C"); + unlock(); +} + +void SimonState::o_unk_99_simon1(uint a) { + uint16 b = TO_BE_16(a); + _lock_word |= 0x4000; + _vc_ptr = (byte*)&b; + vc_60(); + _lock_word &= ~0x4000; +} + +void SimonState::o_unk_99_simon2(uint a, uint b) { + uint16 items[2]; + + items[0] = TO_BE_16(a); + items[1] = TO_BE_16(a); + + _lock_word |= 0x4000; + _vc_ptr = (byte*)&items; + vc_60(); + _lock_word &= ~0x4000; +} + +/* OK */ +void SimonState::o_unk26_helper(uint a, uint b, uint c, uint d, uint e, uint f, uint g, uint h) { + a &= 7; + + if (_fcs_ptr_array_3[a]) + fcs_delete(a); + + _fcs_ptr_array_3[a] = fcs_alloc(b,c,d,e,f,g,h); + + if (a == _fcs_unk_1) { + _fcs_ptr_1 = _fcs_ptr_array_3[a]; + showmessage_helper_3(_fcs_ptr_1->unk6, _fcs_ptr_1->unk7); + } +} diff --git a/simon/simonsys.cpp b/simon/simonsys.cpp index cb7f34bc9e..446059ab67 100644 --- a/simon/simonsys.cpp +++ b/simon/simonsys.cpp @@ -19,28 +19,9 @@ * */ - #include "stdafx.h" -#include "scummsys.h" -#include "system.h" -#include "../sound/mixer.h" #include "simon.h" -#include <stdarg.h> - -#ifdef WIN32 -#include <conio.h> -#endif - -//uint16 swap16(uint16 a) { -// return (a>>8)|(a<<8); -//} - -//uint32 swap32(uint32 a) { -// return (a>>24)|(a>>8)&0xFF00|(a<<8)&0xFF0000|(a<<24); -//} - - uint fileReadByte(FILE *in) { byte b; fread(&b, sizeof(b), 1, in); @@ -84,41 +65,10 @@ void fileWriteBE16(FILE *in, uint16 value) { -#if 0 -void NORETURN CDECL error(const char *s, ...) { - char buf[1024]; - va_list va; - - va_start(va, s); - vsprintf(buf, s, va); - va_end(va); -#ifdef WIN32 - fprintf(stderr, "Error: %s!\nPress a key to quit.\n", buf); - _getch(); -#else - fprintf(stderr, "Error: %s!\n", buf); -#endif - exit(1); - -} - -void CDECL warning(const char *s, ...) { - char buf[1024]; - va_list va; - - va_start(va, s); - vsprintf(buf, s, va); - va_end(va); - fprintf(stdout, "Warning: %s!\n", buf); -} -#endif - #ifndef WIN32 /* GetAsyncKeyState for unix */ int GetAsyncKeyState(int key) { return 0; } - - #endif diff --git a/simon/simonverb.cpp b/simon/simonverb.cpp new file mode 100644 index 0000000000..29918be49b --- /dev/null +++ b/simon/simonverb.cpp @@ -0,0 +1,423 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001/2002 The ScummVM project + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +// Verb and hitarea handling +#include "stdafx.h" +#include "simon.h" + +void SimonState::defocusHitarea() { + HitArea *last; + HitArea *ha; + + if ((_game == GAME_SIMON2WIN) || (_game == GAME_SIMON2DOS)) { + if (_bit_array[4]&0x8000) { + o_unk_120(202); + _last_hitarea_2_ptr = NULL; + return; + } + } + + last = _hitarea_ptr_5; + + if (last == _hitarea_ptr_7) + return; + + hitareaChangedHelper(); + _hitarea_ptr_7 = last; + + if (last != NULL && _hitarea_unk_6 && + (ha = findHitAreaByID(200)) && (ha->flags&0x40) && + !(last->flags&0x40)) + focusVerb(last->id); +} + +static const char * const verb_names[] = { + "Walk to", + "Look at", + "Open", + "Move", + + "Consume", + "Pick up", + "Close", + "Use", + + "Talk to", + "Remove", + "Wear", + "Give" +}; + +static const char * const verb_prep_names[] = { + "","","","", + "","","","with what ?", + "","","","to whom ?" +}; + +void SimonState::focusVerb(uint hitarea_id) { + uint x; + const char *txt; + + hitarea_id -= 101; + + CHECK_BOUNDS(hitarea_id, verb_prep_names); + + if (_show_preposition) { + txt = verb_prep_names[hitarea_id]; + } else { + txt = verb_names[hitarea_id]; + } + x = (53 - strlen(txt)) * 3; + showActionString(x, (const byte*)txt); + +} + +void SimonState::showActionString(uint x, const byte *string) { + FillOrCopyStruct *fcs; + + fcs = _fcs_ptr_array_3[1]; + if (fcs == NULL || fcs->text_color==0) + return; + + fcs->unk1 = x >> 3; + fcs->unk3 = x & 7; + + for(;*string;string++) + video_putchar(fcs, *string); +} + + +void SimonState::hitareaChangedHelper() { + FillOrCopyStruct *fcs; + + if ((_game == GAME_SIMON2WIN) || (_game == GAME_SIMON2WIN)) { + if (_bit_array[4]&0x8000) + return; + } + + fcs = _fcs_ptr_array_3[1]; + if (fcs != NULL && fcs->text_color != 0) + video_fill_or_copy_from_3_to_2(fcs); + + _last_hitarea_2_ptr = NULL; + _hitarea_ptr_7 = NULL; +} + +HitArea *SimonState::findHitAreaByID(uint hitarea_id) { + HitArea *ha = _hit_areas; + uint count = ARRAYSIZE(_hit_areas); + + do{ + if (ha->id == hitarea_id) + return ha; + } while(ha++,--count); + return NULL; +} + +HitArea *SimonState::findEmptyHitArea() { + HitArea *ha = _hit_areas; + uint count = ARRAYSIZE(_hit_areas); + + do{ + if (ha->flags == 0) + return ha; + } while(ha++,--count); + return NULL; +} + +void SimonState::clear_hitarea_bit_0x40(uint hitarea) { + HitArea *ha = findHitAreaByID(hitarea); + if (ha != NULL) + ha->flags &= ~0x40; +} + +void SimonState::set_hitarea_bit_0x40(uint hitarea) { + HitArea *ha = findHitAreaByID(hitarea); + if (ha != NULL) { + ha->flags |= 0x40; + ha->flags &= ~2; + if (hitarea == 102) + hitarea_proc_1(); + } +} + +void SimonState::set_hitarea_x_y(uint hitarea, int x, int y) { + HitArea *ha = findHitAreaByID(hitarea); + if (ha != NULL) { + ha->x = x; + ha->y = y; + } +} + +void SimonState::delete_hitarea(uint hitarea) { + HitArea *ha = findHitAreaByID(hitarea); + if (ha != NULL) { + ha->flags = 0; + if (ha == _last_hitarea_2_ptr) + defocusHitarea(); + _need_hitarea_recalc++; + } +} + +bool SimonState::is_hitarea_0x40_clear(uint hitarea) { + HitArea *ha = findHitAreaByID(hitarea); + if (ha == NULL) + return false; + return (ha->flags & 0x40) == 0; +} + +void SimonState::addNewHitArea(int id, int x, int y, int width, int height, + int flags, int unk3,Item *item_ptr) { + + HitArea *ha; + delete_hitarea(id); + + ha = findEmptyHitArea(); + ha->x = x; + ha->y = y; + ha->width = width; + ha->height = height; + ha->flags = flags | 0x20; + ha->id = ha->layer = id; + ha->unk3 = unk3; + ha->item_ptr = item_ptr; + + _need_hitarea_recalc++; +} + +void SimonState::hitarea_proc_1() { + uint id; + HitArea *ha; + + if (_game & GAME_SIMON2) { + id=2; + if (!(_bit_array[4]&0x8000)) + id = (_mouse_y >= 136) ? 102 : 101; + } else { + id = (_mouse_y >= 136) ? 102 : 101; + + } + + _hitarea_unk_4 = id; + + ha = findHitAreaByID(id); + if (ha == NULL) + return; + + if (ha->flags & 0x40) { + _hitarea_unk_4 = 999; + _hitarea_ptr_5 = NULL; + } else { + _verb_hitarea = ha->unk3; + handle_verb_hitarea(ha); + } +} + +void SimonState::handle_verb_hitarea(HitArea *ha) { + HitArea *tmp = _hitarea_ptr_5; + + if (ha == tmp) + return; + + if (!(_game & GAME_SIMON2)) { + if (tmp != NULL) { + tmp->flags |= 8; + video_toggle_colors(tmp, 0xd5, 0xd0, 0xd5, 0xA); + } + + if (ha->flags & 2) + video_toggle_colors(ha, 0xda, 0xd5, 0xd5, 5); + else + video_toggle_colors(ha, 0xdf, 0xda, 0xda, 0xA); + + ha->flags &= ~ (2 + 8); + + } else { + if (ha->id<101) + return; + _mouse_cursor = ha->id - 101; + _need_hitarea_recalc++; + + } + + _hitarea_ptr_5 = ha; +} + +void SimonState::hitarea_leave(HitArea *ha) { + if (!(_game & GAME_SIMON2)) { + video_toggle_colors(ha, 0xdf, 0xd5, 0xda, 5); + } else { + video_toggle_colors(ha, 0xe7, 0xe5, 0xe6, 1); + } +} + +void SimonState::leaveHitAreaById(uint hitarea_id) { + HitArea *ha = findHitAreaByID(hitarea_id); + if (ha) + hitarea_leave(ha); +} + +void SimonState::handle_unk2_hitarea(FillOrCopyStruct *fcs) { + uint index; + + index = get_fcs_ptr_3_index(fcs); + + if (fcs->fcs_data->unk1 == 0) + return; + + lock(); + fcs_unk_proc_1(index, fcs->fcs_data->item_ptr, + fcs->fcs_data->unk1-1, fcs->fcs_data->unk2); + unlock(); +} + +void SimonState::handle_unk_hitarea(FillOrCopyStruct *fcs) { + uint index; + + index = get_fcs_ptr_3_index(fcs); + + lock(); + fcs_unk_proc_1(index, fcs->fcs_data->item_ptr, + fcs->fcs_data->unk1+1, fcs->fcs_data->unk2); + unlock(); +} + +void SimonState::setup_hitarea_from_pos(uint x, uint y, uint mode) { + HitArea *best_ha; + + if (_game & GAME_SIMON2) { + if (_bit_array[4]&0x8000 || y < 134) { + x += _x_scroll * 8; + } + } + + { + HitArea *ha = _hit_areas; + uint count = ARRAYSIZE(_hit_areas); + uint16 layer = 0; + const uint16 x_ = x; + const uint16 y_ = y; + + best_ha = NULL; + + do{ + if (ha->flags & 0x20) { + if (!(ha->flags & 0x40)) { + if (x_ >= ha->x && y_ >= ha->y && + x_ - ha->x < ha->width && y_- ha->y < ha->height && + layer <= ha->layer) { + layer = ha->layer; + best_ha = ha; + } else { + if (ha->flags & 2) { + hitarea_leave(ha); + ha->flags &=~2; + } + } + } else { + ha->flags &= ~2; + } + } + } while(ha++,--count); + } + + if (best_ha == NULL) { + defocusHitarea(); + return; + } + + if (mode != 0 && mode != 3) { + _last_hitarea = best_ha; + _variableArray[1] = x; + _variableArray[2] = y; + } + + if (best_ha->flags&4) { + defocusHitarea(); + } else if (best_ha != _last_hitarea_2_ptr) { + new_current_hitarea(best_ha); + } + + if (best_ha->flags&8 && !(best_ha->flags&2)) { + hitarea_leave(best_ha); + best_ha->flags |= 2; + } + + return; +} + +void SimonState::new_current_hitarea(HitArea *ha) { + bool result; + + hitareaChangedHelper(); + if (ha->flags & 1) { + result = hitarea_proc_2(ha->flags>>8); + } else { + result = hitarea_proc_3(ha->item_ptr); + } + + if (result) + _last_hitarea_2_ptr = ha; +} + +bool SimonState::hitarea_proc_2(uint a) { + uint x; + const byte *string_ptr; + + if (_game & GAME_SIMON2) { + if (_bit_array[4]&0x8000) { + Subroutine *sub; + _variableArray[84] = a; + sub = getSubroutineByID(5003); + if (sub != NULL) + startSubroutineEx(sub); + return true; + } + } + + if (a >= 20) + return false; + + string_ptr = getStringPtrByID(_stringid_array_2[a]); + x = (53 - (strlen((const char*)string_ptr) - 1)) * 3; + showActionString(x, string_ptr); + + return true; +} + +bool SimonState::hitarea_proc_3(Item *item) { + Child2 *child2; + uint x; + const byte *string_ptr; + + if (item == 0 || item==&_dummy_item_2 || item == &_dummy_item_3) + return false; + + child2 = findChildOfType2(item); + if (child2 == NULL) + return false; + + string_ptr = getStringPtrByID(child2->string_id); + x = (53 - (strlen((const char*)string_ptr) - 1)) * 3; + showActionString(x, string_ptr); + return true; +} + diff --git a/simon/simonvga.cpp b/simon/simonvga.cpp new file mode 100644 index 0000000000..c188b75513 --- /dev/null +++ b/simon/simonvga.cpp @@ -0,0 +1,1836 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001/2002 The ScummVM project + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +// Video script opcodes for Simon1/Simon2 +#include "stdafx.h" +#include "simon.h" + +typedef void (SimonState::*VgaOpcodeProc)(); +static const uint16 vc_get_out_of_code = 0; + +// Opcode tables +static const VgaOpcodeProc vga_opcode_table[] = { + NULL, + &SimonState::vc_1, + &SimonState::vc_2, + &SimonState::vc_3, + &SimonState::vc_4, + &SimonState::vc_5, + &SimonState::vc_6_maybe_skip_3_inv, + &SimonState::vc_7_maybe_skip_3, + &SimonState::vc_8_maybe_skip_2, + &SimonState::vc_9_maybe_skip, + &SimonState::vc_10, + &SimonState::vc_11_clear_pathfind_array, + &SimonState::vc_12_sleep_variable, + &SimonState::vc_13_offset_x, + &SimonState::vc_14_offset_y, + &SimonState::vc_15_start_funkystruct_by_id, + &SimonState::vc_16_setup_funkystruct, + &SimonState::vc_17_set_pathfind_item, + &SimonState::vc_18_jump_rel, + &SimonState::vc_19, + &SimonState::vc_20, + &SimonState::vc_21, + &SimonState::vc_22, + &SimonState::vc_23_set_pri, + &SimonState::vc_24_set_image_xy, + &SimonState::vc_25_del_sprite_and_get_out, + &SimonState::vc_26, + &SimonState::vc_27_reset, + &SimonState::vc_28, + &SimonState::vc_29_stop_all_sounds, + &SimonState::vc_30_set_base_delay, + &SimonState::vc_31_set_palette_mode, + &SimonState::vc_32_copy_var, + &SimonState::vc_33, + &SimonState::vc_34, + &SimonState::vc_35, + &SimonState::vc_36, + &SimonState::vc_37_sprite_unk3_add, + &SimonState::vc_38_skip_if_var_zero, + &SimonState::vc_39_set_var, + &SimonState::vc_40_var_add, + &SimonState::vc_41_var_sub, + &SimonState::vc_42_delay_if_not_eq, + &SimonState::vc_43_skip_if_bit_clear, + &SimonState::vc_44_skip_if_bit_set, + &SimonState::vc_45_set_x, + &SimonState::vc_46_set_y, + &SimonState::vc_47_add_var_f, + &SimonState::vc_48, + &SimonState::vc_49_set_bit, + &SimonState::vc_50_clear_bit, + &SimonState::vc_51_clear_hitarea_bit_0x40, + &SimonState::vc_52, + &SimonState::vc_53_no_op, + &SimonState::vc_54_no_op, + &SimonState::vc_55_offset_hit_area, + &SimonState::vc_56_no_op, + &SimonState::vc_57_no_op, + &SimonState::vc_58, + &SimonState::vc_59, + &SimonState::vc_60, + &SimonState::vc_61_sprite_change, + &SimonState::vc_62, + &SimonState::vc_63, + + &SimonState::vc_64, + &SimonState::vc_65, + &SimonState::vc_66, + &SimonState::vc_67, + &SimonState::vc_68, + &SimonState::vc_69, + &SimonState::vc_70, + &SimonState::vc_71, + &SimonState::vc_72, + &SimonState::vc_73, + &SimonState::vc_74, +}; + +// Script parser +void SimonState::run_vga_script() { + for(;;) { + uint opcode; + +#ifdef DUMP_CONTINOUS_VGASCRIPT + if ((void*)_vc_ptr != (void*)&vc_get_out_of_code) { +// if (_vga_cur_sprite_id==62 && _vga_cur_file_id==68 || +// _vga_cur_sprite_id==1 && _vga_cur_file_id==2) { + fprintf(_dump_file,"%.5d %.5X: %5d %4d ", _vga_tick_counter, _vc_ptr -_cur_vga_file_1, _vga_cur_sprite_id, _vga_cur_file_id); + dump_video_script(_vc_ptr, true); +// } + } +#endif + + if (!(_game & GAME_SIMON2)) { + opcode = READ_BE_UINT16_UNALIGNED(_vc_ptr); + _vc_ptr += 2; + } else { + opcode = *_vc_ptr++; + } + + if (opcode >= gss->NUM_VIDEO_OP_CODES) + error("Invalid VGA opcode '%d' encountered", opcode); + + if (opcode == 0) + return; + + (this->*vga_opcode_table[opcode])(); + } +} + +int SimonState::vc_read_var_or_word() { + int16 var = vc_read_next_word(); + if (var < 0) + var = vc_read_var(-var); + return var; +} + +uint SimonState::vc_read_next_word() { + uint a = READ_BE_UINT16_UNALIGNED(_vc_ptr); + _vc_ptr += 2; + return a; +} + +uint SimonState::vc_read_next_byte() { + return *_vc_ptr++; +} + + +void SimonState::vc_skip_next_instruction() { + static const byte opcode_param_len_simon1[] = { + 0, 6, 2,10, 6, 4, 2, 2, + 4, 4,10, 0, 2, 2, 2, 2, + 2, 0, 2, 0, 4, 2, 4, 2, + 8, 0,10, 0, 8, 0, 2, 2, + 4, 0, 0, 4, 4, 2, 2, 4, + 4, 4, 4, 2, 2, 2, 2, 4, + 0, 2, 2, 2, 2, 4, 6, 6, + 0, 0, 0, 0, 2, 6, 0, 0, + }; + + static const byte opcode_param_len_simon2[] = { + 0, 6, 2, 12, 6, 4, 2, 2, + 4, 4, 9, 0, 1, 2, 2, 2, + 2, 0, 2, 0, 4, 2, 4, 2, + 7, 0, 10, 0, 8, 0, 2, 2, + 4, 0, 0, 4, 4, 2, 2, 4, + 4, 4, 4, 2, 2, 2, 2, 4, + 0, 2, 2, 2, 2, 4, 6, 6, + 2, 0, 6, 6, 4, 6, 0, 0, + 0, 0, 4, 4, 4, 4, 4, 0, + 4, 2, 2 + }; + + if (_game & GAME_SIMON2) { + uint opcode = vc_read_next_byte(); + _vc_ptr += opcode_param_len_simon2[opcode]; + } else { + uint opcode = vc_read_next_word(); + _vc_ptr += opcode_param_len_simon1[opcode]; + } + +#ifdef DUMP_CONTINOUS_VGASCRIPT + fprintf(_dump_file,"; skipped\n"); +#endif +} + +void SimonState::o_read_vgares_23() { // Simon1 Only + if (_vga_res_328_loaded == true) { + _vga_res_328_loaded = false; + _lock_word |= 0x4000; + read_vga_from_datfile_1(23); + _lock_word &= ~0x4000; + } +} + +void SimonState::o_read_vgares_328() { // Simon1 Only + if (_vga_res_328_loaded == false) { + _vga_res_328_loaded = true; + _lock_word |= 0x4000; + read_vga_from_datfile_1(328); + _lock_word &= ~0x4000; + } +} + + +// VGA Script commands +void SimonState::vc_1() { + /* dummy opcode */ + _vc_ptr += 6; +} + +void SimonState::vc_2() { + VgaPointersEntry *vpe; + uint num; + uint res; + byte *old_file_1, *old_file_2; + byte *b,*bb, *vc_ptr_org; + + num = vc_read_var_or_word(); + + old_file_1 = _cur_vga_file_1; + old_file_2 = _cur_vga_file_2; + + for(;;) { + res = num / 100; + vpe = &_vga_buffer_pointers[res]; + + _cur_vga_file_1 = vpe->vgaFile1; + _cur_vga_file_2 = vpe->vgaFile2; + if (vpe->vgaFile1 != NULL) + break; + if (_vga_cur_file_2 != res) + _video_var_7 = _vga_cur_file_2; + + ensureVgaResLoaded(res); + _video_var_7 = 0xFFFF; + } + + + bb = _cur_vga_file_1; + b = bb + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header*)bb)->hdr2_start); + b = bb + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header2*)b)->unk2_offs); + + while (READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x8*)b)->id) != num) + b += sizeof(VgaFile1Struct0x8); + + vc_ptr_org = _vc_ptr; + + _vc_ptr = _cur_vga_file_1 + READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x8*)b)->script_offs); + + +// dump_vga_script(_vc_ptr, res, num); + run_vga_script(); + + _cur_vga_file_1 = old_file_1; + _cur_vga_file_2 = old_file_2; + + _vc_ptr = vc_ptr_org; +} + +void SimonState::vc_3() { + uint16 a,b,c,d,e,f; + uint16 res; + VgaSprite *vsp; + VgaPointersEntry *vpe; + byte *p,*pp; + + a = vc_read_next_word(); /* 0 */ + + if (_game & GAME_SIMON2) { + f = vc_read_next_word(); /* 0 */ + b = vc_read_next_word(); /* 2 */ + } else { + b = vc_read_next_word(); /* 2 */ + f = b / 100; + } + + c = vc_read_next_word(); /* 4 */ + d = vc_read_next_word(); /* 6 */ + e = vc_read_next_word(); /* 8 */ + + /* 2nd param ignored with simon1 */ + if (has_vgastruct_with_id(b,f)) + return; + + vsp = _vga_sprites; + while (vsp->id) vsp++; + + vsp->base_color = e; + vsp->unk6 = a; + vsp->unk5 = 0; + vsp->unk4 = 0; + vsp->image = 0; + vsp->x = c; + vsp->y = d; + vsp->id = b; + vsp->unk7 = res = f; + + for(;;) { + vpe = &_vga_buffer_pointers[res]; + _cur_vga_file_1 = vpe->vgaFile1; + + if (vpe->vgaFile1 != NULL) + break; + if (res != _vga_cur_file_2) + _video_var_7 = res; + + ensureVgaResLoaded(res); + _video_var_7 = 0xFFFF; + } + + pp = _cur_vga_file_1; + p = pp + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header*)pp)->hdr2_start); + p = pp + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header2*)p)->id_table); + + while (READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x6*)p)->id) != b) + p += sizeof(VgaFile1Struct0x6); + +#ifdef DUMP_FILE_NR +{ + static bool dumped=false; + if (res == DUMP_FILE_NR && !dumped) { + dumped = true; + dump_vga_file(_cur_vga_file_1); + } +} +#endif + +#ifdef DUMP_BITMAPS_FILE_NR +{ + static bool dumped=false; + if (res == DUMP_BITMAPS_FILE_NR && !dumped) { + dumped = true; + dump_vga_bitmaps(_cur_vga_file_2, _cur_vga_file_1, res); + } +} +#endif + +// dump_vga_script(_cur_vga_file_1 + READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x6*)p)->script_offs), res, b); + + add_vga_timer(gss->VGA_DELAY_BASE, + _cur_vga_file_1 + READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x6*)p)->script_offs),b , res); +} + +void SimonState::vc_4() { + /* dummy opcode */ + _vc_ptr += 6; +} + +void SimonState::vc_5() { + uint var = vc_read_next_word(); + uint value = vc_read_next_word(); + if (vc_read_var(var) != value) + vc_skip_next_instruction(); +} + +void SimonState::vc_6_maybe_skip_3_inv() { + if (!vc_maybe_skip_proc_3(vc_read_next_word())) + vc_skip_next_instruction(); +} + +void SimonState::vc_7_maybe_skip_3() { + if (vc_maybe_skip_proc_3(vc_read_next_word())) + vc_skip_next_instruction(); +} + +void SimonState::vc_8_maybe_skip_2() { + uint a = vc_read_next_word(); + uint b = vc_read_next_word(); + if (!vc_maybe_skip_proc_2(a,b)) + vc_skip_next_instruction(); +} + +void SimonState::vc_9_maybe_skip() { + uint a = vc_read_next_word(); + uint b = vc_read_next_word(); + if (!vc_maybe_skip_proc_1(a,b)) + vc_skip_next_instruction(); +} + +struct VC10_state { + int image; + uint16 e; + int x,y; + + byte base_color; + + uint draw_width, draw_height; + uint x_skip, y_skip; + + byte *surf2_addr; + uint surf2_pitch; + + byte *surf_addr; + uint surf_pitch; + + byte dl,dh; + + byte *depack_src; + int8 depack_cont; + + byte depack_dest[200]; +}; + +byte *vc_10_depack_column(VC10_state *vs) { + int8 a = vs->depack_cont; + byte *src = vs->depack_src; + byte *dst = vs->depack_dest; + byte dh = vs->dh; + byte color; + + if (a != -0x80) + goto start_here; + + for(;;) { + a = *src++; +start_here:; + if (a>=0) { + color = *src++; + do { + *dst++ = color; + if (!--dh) { + if (--a<0) + a = -0x80; + else + src--; + goto get_out; + } + } while(--a>=0); + } else { + do { + *dst++ = *src++; + if (!--dh) { + if (++a==0) + a = -0x80; + goto get_out; + } + } while (++a!=0); + } + } + +get_out:; + vs->depack_src = src; + vs->depack_cont = a; + return vs->depack_dest + vs->y_skip; +} + +void vc_10_skip_cols(VC10_state *vs) { + vs->depack_cont = -0x80; + while(vs->x_skip) { + vc_10_depack_column(vs); + vs->x_skip--; + } +} + +byte *SimonState::vc_10_depack_swap(byte *src, uint w, uint h) { + w<<=3; + + { + byte *dst_org = _video_buf_1 + w; + byte color; + int8 cur = -0x80; + uint w_cur = w; + + do { + byte *dst = dst_org; + uint h_cur = h; + + if (cur == -0x80) + cur = *src++; + + for(;;) { + if (cur >= 0) { + /* rle_same */ + color = *src++; + do { + *dst = color; + dst += w; + if (!--h_cur) { + if (--cur<0) + cur = -0x80; + else + src--; + goto next_line; + } + } while (--cur>=0); + } else { + /* rle_diff */ + do { + *dst = *src++; + dst += w; + if (!--h_cur) { + if (++cur == 0) + cur = -0x80; + goto next_line; + } + } while (++cur != 0); + } + cur = *src++; + } + next_line: + dst_org++; + } while(--w_cur); + } + + { + byte *dst_org, *src_org; + uint i; + + src_org = dst_org = _video_buf_1 + w; + + do { + byte *dst = dst_org; + for(i=0; i!=w; ++i) { + byte b = src_org[i]; + b = (b>>4) | (b<<4); + *--dst = b; + } + + src_org += w; + dst_org += w; + } while (--h); + + } + + return _video_buf_1; + +} + +byte *vc_10_no_depack_swap(byte *src) { + error("vc_10_no_depack_swap unimpl"); +} + +/* must not be const */ +static uint16 _video_windows[128] = { + 0, 0, 20, 200, + 0, 0, 3, 136, + 17,0, 3, 136, + 0, 0, 20, 200, + 0, 0, 20, 134 +}; + +/* simon2 specific */ +void SimonState::vc_10_helper_8(byte *dst, byte *src) { + const uint pitch = _dx_surface_pitch; + int8 reps = (int8)0x80; + byte color; + byte *dst_org = dst; + uint h = _vga_var5, w = 8; + + for(;;) { + reps = *src++; + if (reps >= 0) { + color = *src++; + + do { + *dst = color; + dst += pitch; + + /* reached bottom? */ + if (--h == 0) { + /* reached right edge? */ + if (--w == 0) + return; + dst = ++dst_org; + h = _vga_var5; + } + } while (--reps >=0); + } else { + + do { + *dst = *src++; + dst += pitch; + + /* reached bottom? */ + if (--h == 0) { + /* reached right edge? */ + if (--w == 0) + return; + dst = ++dst_org; + h = _vga_var5; + } + } while (++reps != 0); + } + } +} + +void SimonState::vc_10() { + byte *p2; + uint width,height; + byte flags; + const uint16 *vlut; + VC10_state state; + + int cur; + + state.image = (int16)vc_read_next_word(); + if (state.image==0) + return; + +// if (_vga_cur_sprite_id != 802) +// return; + + state.base_color = (_vc_ptr[1]<<4); + _vc_ptr += 2; + state.x = (int16)vc_read_next_word(); + if (_game & GAME_SIMON2) { + state.x -= _x_scroll; + } + state.y = (int16)vc_read_next_word(); + + if (!(_game & GAME_SIMON2)) { + state.e = vc_read_next_word(); + } else { + state.e = vc_read_next_byte(); + } + + if (state.image < 0) + state.image = vc_read_var(-state.image); + + p2 = _cur_vga_file_2 + state.image * 8; + state.depack_src = _cur_vga_file_2 + READ_BE_UINT32_UNALIGNED(&*(uint32*)p2); + + width = READ_BE_UINT16_UNALIGNED(p2+6)>>4; + height = p2[5]; + flags = p2[4]; + + if (height==0 || width==0) + return; + +#ifdef DUMP_DRAWN_BITMAPS + dump_single_bitmap(_vga_cur_file_id, state.image, state.depack_src, width*16, height, state.base_color); +#endif + + if (flags&0x80 && !(state.e&0x10)) { + if (state.e&1) { + state.e&=~1; + state.e|=0x10; + } else { + state.e|=0x8; + } + } + + if (_game & GAME_SIMON2 && width>=21) { + byte *src,*dst; + uint w; + + _vga_var1 = width*2-40; + _vga_var7 = state.depack_src; + _vga_var5 = height; + if (_variableArray[34]==-1) + state.x = _variableArray[502/2]; + + _x_scroll = state.x; + + vc_write_var(0xfb, _x_scroll); + + dst = dx_lock_attached(); + src = state.depack_src + _x_scroll * 4; + + w = 40; + do { + vc_10_helper_8(dst, src + READ_BE_UINT32_UNALIGNED(&*(uint32*)src)); + dst += 8; + src += 4; + } while (--w); + + dx_unlock_attached(); + + + return; + } + + if (state.e&0x10) + state.depack_src = vc_10_depack_swap(state.depack_src, width, height); + else if (state.e&1) + state.depack_src = vc_10_no_depack_swap(state.depack_src); + + + vlut = &_video_windows[_video_palette_mode * 4]; + + state.draw_width = width << 1; /* cl */ + state.draw_height = height; /* ch */ + + state.x_skip = 0; /* colums to skip = bh */ + state.y_skip = 0; /* rows to skip = bl */ + + cur = state.x; + if (cur < 0) { + do { + if (!--state.draw_width) return; + state.x_skip++; + } while(++cur); + } + state.x = cur; + + cur += state.draw_width - (vlut[2]<<1); + if (cur > 0) { + do { + if (!--state.draw_width) return; + } while (--cur); + } + + cur = state.y; + if (cur < 0) { + do { + if (!--state.draw_height) return; + state.y_skip++; + } while(++cur); + } + state.y = cur; + + cur += state.draw_height - vlut[3]; + if (cur > 0) { + do { + if (!--state.draw_height) return; + } while (--cur); + } + + assert(state.draw_width!=0 && state.draw_height!=0); + + state.draw_width<<=2; + + state.surf2_addr = dx_lock_2(); + state.surf2_pitch = _dx_surface_pitch; + + state.surf_addr = dx_lock_attached(); + state.surf_pitch = _dx_surface_pitch; + + { + uint offs = ((vlut[0] - _video_windows[16])*2 + state.x) * 8; + uint offs2 = (vlut[1] - _video_windows[17] + state.y); + + state.surf2_addr += offs + offs2 * state.surf2_pitch; + state.surf_addr += offs + offs2 * state.surf_pitch; + } + + if (state.e & 0x20) { + byte *mask, *src, *dst; + byte h; + uint w; + + state.x_skip<<=2; + state.dl = width; + state.dh = height; + + vc_10_skip_cols(&state); + + /* XXX: implement transparency */ + + w = 0; + do { + mask = vc_10_depack_column(&state); /* esi */ + src = state.surf2_addr + w*2; /* ebx */ + dst = state.surf_addr + w*2; /* edi */ + + h = state.draw_height; + do { + if (mask[0] & 0xF0) dst[0] = src[0]; + if (mask[0] & 0x0F) dst[1] = src[1]; + mask++; + dst += state.surf_pitch; + src += state.surf2_pitch; + } while(--h); + } while(++w != state.draw_width); + + /* vc_10_helper_5 */ + } else if (_lock_word&0x20 && state.base_color==0 || state.base_color==0xC0) { + byte *src,*dst; + uint h,i; + + if (!(state.e&8)) { + src = state.depack_src + (width * state.y_skip<<4) + (state.x_skip<<3); + dst = state.surf_addr; + + state.draw_width *= 2; + + if(state.e&2) { + /* no transparency */ + h = state.draw_height; + do { + memcpy(dst,src,state.draw_width); + dst += 320; + src += width * 16; + } while(--h); + } else { + /* transparency */ + h = state.draw_height; + do { + for(i=0; i!=state.draw_width; i++) + if(src[i]) + dst[i] = src[i]; + dst += 320; + src += width * 16; + } while(--h); + } + + } else { + byte *dst_org = state.surf_addr; + src = state.depack_src; + /* AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD EEEEEEEE + * aaaaabbb bbcccccd ddddeeee efffffgg ggghhhhh + */ + + if (state.e & 2) { + /* no transparency */ + do { + uint count = state.draw_width>>2; + + dst = dst_org; + do { + uint32 bits = (src[0]<<24) | (src[1]<<16) | (src[2]<<8) | (src[3]); + + dst[0] = (byte)((bits >> (32-5)) & 31); + dst[1] = (byte)((bits >> (32-10)) & 31); + dst[2] = (byte)((bits >> (32-15)) & 31); + dst[3] = (byte)((bits >> (32-20)) & 31); + dst[4] = (byte)((bits >> (32-25)) & 31); + dst[5] = (byte)((bits >> (32-30)) & 31); + + bits = (bits<<8) | src[4]; + + dst[6] = (byte)((bits >> (40-35)) & 31); + dst[7] = (byte)((bits) & 31); + + dst += 8; + src += 5; + } while (--count); + dst_org += 320; + } while (--state.draw_height); + } else { + /* transparency */ + do { + uint count = state.draw_width>>2; + + dst = dst_org; + do { + uint32 bits = (src[0]<<24) | (src[1]<<16) | (src[2]<<8) | (src[3]); + byte tmp; + + tmp = (byte)((bits >> (32-5)) & 31); if (tmp) dst[0] = tmp; + tmp = (byte)((bits >> (32-10)) & 31); if (tmp) dst[1] = tmp; + tmp = (byte)((bits >> (32-15)) & 31); if (tmp) dst[2] = tmp; + tmp = (byte)((bits >> (32-20)) & 31); if (tmp) dst[3] = tmp; + tmp = (byte)((bits >> (32-25)) & 31); if (tmp) dst[4] = tmp; + tmp = (byte)((bits >> (32-30)) & 31); if (tmp) dst[5] = tmp; + + bits = (bits<<8) | src[4]; + + tmp = (byte)((bits >> (40-35)) & 31); if (tmp) dst[6] = tmp; + tmp = (byte)((bits) & 31); if (tmp) dst[7] = tmp; + + dst += 8; + src += 5; + } while (--count); + dst_org += 320; + } while (--state.draw_height); + } + } + /* vc_10_helper_4 */ + } else { + if (_game&GAME_SIMON2 && state.e&0x4 && _bit_array[10]&0x800) { + state.surf_addr = state.surf2_addr; + state.surf_pitch = state.surf2_pitch; + warning("vc_10: (state.e&0x4)"); + } + + if (state.e & 0x8) { + uint w,h; + byte *src, *dst,*dst_org; + + state.x_skip <<= 2; /* reached */ + state.dl = width; + state.dh = height; + + vc_10_skip_cols(&state); + + if (state.e&2) { + dst_org = state.surf_addr; + w = 0; + do { + src = vc_10_depack_column(&state); + dst = dst_org; + + h = 0; + do { + dst[0] = (*src >> 4) | state.base_color; + dst[1] = (*src&15) | state.base_color; + dst += 320; + src++; + } while (++h != state.draw_height); + dst_org += 2; + } while (++w != state.draw_width); + } else { + dst_org = state.surf_addr; + if (state.e & 0x40) { /* reached */ + dst_org += vc_read_var(252); + } + w = 0; + do { + byte color; + + src = vc_10_depack_column(&state); + dst = dst_org; + + h = 0; + do { + color = (*src >> 4); + if (color) dst[0] = color | state.base_color; + color = (*src&15); + if (color) dst[1] = color | state.base_color; + dst += 320; + src++; + } while (++h != state.draw_height); + dst_org += 2; + } while (++w != state.draw_width); + } + /* vc_10_helper_6 */ + } else { + byte *src,*dst; + uint count; + + src = state.depack_src + (width * state.y_skip) * 8; + dst = state.surf_addr; + state.x_skip <<= 2; + if (state.e&2) { + do { + for(count=0; count!=state.draw_width; count++) { + dst[count*2] = (src[count+state.x_skip]>>4) | state.base_color; + dst[count*2+1] = (src[count+state.x_skip]&15) | state.base_color; + } + dst += 320; + src += width * 8; + } while (--state.draw_height); + } else { + do { + for(count=0; count!=state.draw_width; count++) { + byte color; + color = (src[count+state.x_skip]>>4); + if(color) dst[count*2] = color | state.base_color; + color = (src[count+state.x_skip]&15); + if (color) dst[count*2+1] = color | state.base_color; + } + dst += 320; + src += width * 8; + } while (--state.draw_height); + + } + + /* vc_10_helper_7 */ + } + } + + dx_unlock_2(); + dx_unlock_attached(); + +} + +void SimonState::vc_11_clear_pathfind_array() { + memset(&_pathfind_array, 0, sizeof(_pathfind_array)); +} + +void SimonState::vc_12_sleep_variable() { + uint num; + + if (!(_game & GAME_SIMON2)) { + num = vc_read_var_or_word(); + } else { + num = vc_read_next_byte() * _vga_base_delay; + } + + add_vga_timer(num + gss->VGA_DELAY_BASE, _vc_ptr, _vga_cur_sprite_id, _vga_cur_file_id); + _vc_ptr = (byte*)&vc_get_out_of_code; +} + +void SimonState::vc_13_offset_x() { + VgaSprite *vsp = find_cur_sprite(); + int16 a = vc_read_next_word(); + vsp->x += a; + _vga_sprite_changed++; +} + +void SimonState::vc_14_offset_y() { + VgaSprite *vsp = find_cur_sprite(); + int16 a = vc_read_next_word(); + vsp->y += a; + _vga_sprite_changed++; +} + +/* wakeup_id */ +void SimonState::vc_15_start_funkystruct_by_id() { + VgaSleepStruct *vfs = _vga_sleep_structs, *vfs_tmp; + uint16 id = vc_read_next_word(); + while (vfs->ident != 0) { + if (vfs->ident == id) { + add_vga_timer(gss->VGA_DELAY_BASE, vfs->code_ptr, vfs->sprite_id, vfs->cur_vga_file); + vfs_tmp = vfs; + do { + memcpy(vfs_tmp, vfs_tmp + 1, sizeof(VgaSleepStruct)); + vfs_tmp++; + } while (vfs_tmp->ident != 0); + } else { + vfs++; + } + } + + /* clear a wait event */ + if (id == _vga_wait_for) + _vga_wait_for = 0; +} + + +/* sleep_on_id */ +void SimonState::vc_16_setup_funkystruct() { + VgaSleepStruct *vfs = _vga_sleep_structs; + while (vfs->ident) + vfs++; + + vfs->ident = vc_read_next_word(); + vfs->code_ptr = _vc_ptr; + vfs->sprite_id = _vga_cur_sprite_id; + vfs->cur_vga_file = _vga_cur_file_id; + + _vc_ptr = (byte*)&vc_get_out_of_code; +} + +void SimonState::vc_17_set_pathfind_item() { + uint a = vc_read_next_word(); + _pathfind_array[a - 1] = (uint16*)_vc_ptr; + while ( READ_BE_UINT16_UNALIGNED(_vc_ptr) != 999) + _vc_ptr += 4; + _vc_ptr += 2; +} + +void SimonState::vc_18_jump_rel() { + int16 offs = vc_read_next_word(); + _vc_ptr += offs; +} + +/* chain to script? */ +void SimonState::vc_19() { + /* XXX: not implemented */ + error("vc_19: chain to script not implemented"); +} + + +/* helper routines */ + +/* write unaligned 16-bit */ +static void write_16_le(void *p, uint16 a) { + ((byte*)p)[0] = (byte) (a); + ((byte*)p)[1] = (byte) (a >> 8); +} + +/* read unaligned 16-bit */ +static uint16 read_16_le(void *p) { + return ((byte*)p)[0] | (((byte*)p)[1] << 8); +} + +/* FIXME: unaligned access */ +void SimonState::vc_20() { + uint16 a = vc_read_next_word(); + write_16_le(_vc_ptr, a); + _vc_ptr += 2; +} + +/* FIXME: unaligned access */ +void SimonState::vc_21() { + if (!(_game & GAME_SIMON2)) { + int16 a = vc_read_next_word(); + byte *tmp = _vc_ptr + a; + uint16 val = read_16_le(tmp + 4); + + if (val != 0) { + write_16_le(tmp + 4, val - 1); + _vc_ptr = tmp + 6; + } + } else { + int16 a = vc_read_next_word(); + byte *tmp = _vc_ptr + a; + uint16 val = read_16_le(tmp + 3); + + if (val != 0) { + write_16_le(tmp + 3, val - 1); + _vc_ptr = tmp + 5; + } + } +} + +void SimonState::vc_22() { + uint a = vc_read_next_word(); + uint b = vc_read_next_word(); + uint num = a==0 ? 0x20 : 0x10; + byte *palptr, *src; + + palptr = &_palette[(a<<6)]; + + src = _cur_vga_file_1 + 6 + b*96; + + do { + palptr[0] = src[0]<<2; + palptr[1] = src[1]<<2; + palptr[2] = src[2]<<2; + palptr[3] = 0; + + palptr += 4; + src += 3; + } while (--num); + + _video_var_9 = 2; + _vga_sprite_changed++; +} + +void SimonState::vc_23_set_pri() { + VgaSprite *vsp = find_cur_sprite(), *vus2; + uint16 pri = vc_read_next_word(); + VgaSprite bak; + + if (vsp->id == 0) { + warning("tried to set pri for unknown id %d", _vga_cur_sprite_id); + return; + } + + memcpy(&bak, vsp, sizeof(bak)); + bak.unk5 = pri; + bak.unk6 |= 0x8000; + + vus2 = vsp; + + if (vsp != _vga_sprites && pri < vsp[-1].unk5) { + do { + vsp--; + } while (vsp != _vga_sprites && pri < vsp[-1].unk5); + do { + memcpy(vus2, vus2-1, sizeof(VgaSprite)); + } while (--vus2 != vsp); + memcpy(vus2, &bak, sizeof(VgaSprite)); + } else if (vsp[1].id!=0 && pri >= vsp[1].unk5) { + do { + vsp++; + } while (vsp[1].id!=0 && pri >= vsp[1].unk5); + do { + memcpy(vus2, vus2+1,sizeof(VgaSprite)); + } while (++vus2 != vsp); + memcpy(vus2, &bak, sizeof(VgaSprite)); + } else { + vsp->unk5 = pri; + } + _vga_sprite_changed++; +} + +void SimonState::vc_24_set_image_xy() { + VgaSprite *vsp = find_cur_sprite(); + vsp->image = vc_read_var_or_word(); + + if (vsp->id==0) { + warning("Trying to set XY of nonexistent sprite '%d'", _vga_cur_sprite_id); + } + + vsp->x += (int16)vc_read_next_word(); + vsp->y += (int16)vc_read_next_word(); + if (!(_game & GAME_SIMON2)) { + vsp->unk4 = vc_read_next_word(); + } else { + vsp->unk4 = vc_read_next_byte(); + } + + _vga_sprite_changed++; +} + +void SimonState::vc_25_del_sprite_and_get_out() { + VgaSprite *vsp = find_cur_sprite(); + while (vsp->id != 0) { + memcpy(vsp,vsp+1,sizeof(VgaSprite)); + vsp++; + } + _vc_ptr = (byte*)&vc_get_out_of_code; + _vga_sprite_changed++; +} + +void SimonState::vc_26() { + uint16 *as = &_video_windows[vc_read_next_word()*4]; + as[0] = vc_read_next_word(); + as[1] = vc_read_next_word(); + as[2] = vc_read_next_word(); + as[3] = vc_read_next_word(); +} + +void SimonState::vc_27_reset_simon1() { + VgaSprite bak,*vsp; + VgaSleepStruct *vfs; + VgaTimerEntry *vte,*vte2; + + _lock_word |= 8; + + memset(&bak,0,sizeof(bak)); + + vsp = _vga_sprites; + while (vsp->id) { + if (vsp->id == 128) { + memcpy(&bak,vsp,sizeof(VgaSprite)); + } + vsp->id = 0; + vsp++; + } + + if (bak.id != 0) + memcpy(_vga_sprites, &bak, sizeof(VgaSprite)); + + vfs = _vga_sleep_structs; + while (vfs->ident) { + vfs->ident = 0; + vfs++; + } + + + vte = _vga_timer_list; + while (vte->delay) { + if (vte->sprite_id != 0x80) { + vte2 = vte; + while (vte2->delay) { + memcpy(vte2,vte2+1,sizeof(VgaTimerEntry)); + vte2++; + } + } else { + vte++; + } + } + + vc_write_var(0xFE, 0); + + _lock_word &= ~8; +} + + +void SimonState::vc_27_reset_simon2() { + _lock_word |= 8; + + { + VgaSprite *vsp = _vga_sprites; + while (vsp->id) { + vsp->id = 0; + vsp++; + } + } + + { + VgaSleepStruct *vfs = _vga_sleep_structs; + while (vfs->ident) { + vfs->ident = 0; + vfs++; + } + } + + { + VgaTimerEntry *vte = _vga_timer_list; + while (vte->delay) { + VgaTimerEntry *vte2 = vte; + while (vte2->delay) { + memcpy(vte2,vte2+1,sizeof(VgaTimerEntry)); + vte2++; + } + } + } + + vc_write_var(0xFE, 0); + + _lock_word &= ~8; +} + +void SimonState::vc_27_reset() { + if (!(_game & GAME_SIMON2)) + vc_27_reset_simon1(); + else + vc_27_reset_simon2(); +} + +void SimonState::vc_28() { + /* dummy opcode */ + _vc_ptr += 8; +} + +void SimonState::vc_29_stop_all_sounds() { + _mixer->stop_all(); +} + +void SimonState::vc_30_set_base_delay() { + _vga_base_delay = vc_read_next_word(); +} + +void SimonState::vc_31_set_palette_mode() { + _video_palette_mode = vc_read_next_word(); +} + +uint SimonState::vc_read_var(uint var) { + assert(var<255); + return (uint16)_variableArray[var]; +} + +void SimonState::vc_write_var(uint var, int16 value) { + _variableArray[var] = value; +} + +void SimonState::vc_32_copy_var() { + uint16 a = vc_read_var(vc_read_next_word()); + vc_write_var(vc_read_next_word(), a); +} + +void SimonState::vc_33() { + if (_lock_counter != 0) { + _lock_counter = 1; + unlock(); + } +} + +void SimonState::vc_34() { + lock(); + _lock_counter = 200; + _left_button_down = 0; +} + +void SimonState::vc_35() { + /* not used? */ + _vc_ptr += 4; + _vga_sprite_changed++; +} + +void SimonState::vc_36() { + uint vga_res = vc_read_next_word(); + uint mode = vc_read_next_word(); + + if (!(_game & GAME_SIMON2)) { + if (mode == 16) { + _copy_partial_mode = 2; + } else { + set_video_mode_internal(mode,vga_res); + } + } else { + set_video_mode_internal(mode,vga_res); + } +} + +void SimonState::vc_37_sprite_unk3_add() { + VgaSprite *vsp = find_cur_sprite(); + vsp->y += vc_read_var(vc_read_next_word()); + _vga_sprite_changed++; +} + +void SimonState::vc_38_skip_if_var_zero() { + uint var = vc_read_next_word(); + if (vc_read_var(var) == 0) + vc_skip_next_instruction(); +} + +void SimonState::vc_39_set_var() { + uint var = vc_read_next_word(); + int16 value = vc_read_next_word(); + vc_write_var(var,value); +} + +void SimonState::vc_40_var_add() { + uint var = vc_read_next_word(); + int16 value = vc_read_var(var) + vc_read_next_word(); + + if (_game&GAME_SIMON2 && var==0xF && !(_bit_array[5]&1)) { + int16 tmp; + + if (_vga_var2!=0) { + if (_vga_var2>=0) goto no_scroll; + _vga_var2 = 0; + } else { + if (_vga_var3 != 0) goto no_scroll; + } + + if (value - _x_scroll >= 30) { + _vga_var2 = 20; + tmp = _vga_var1 - _x_scroll; + if (tmp < 20) + _vga_var2 = tmp; + add_vga_timer(10, NULL, 0, 0); /* special timer */ + } + } +no_scroll:; + + vc_write_var(var, value); +} + +void SimonState::vc_41_var_sub() { + uint var = vc_read_next_word(); + int16 value = vc_read_var(var) - vc_read_next_word(); + + if (_game&GAME_SIMON2 && var==0xF && !(_bit_array[5]&1)) { + int16 tmp; + + if (_vga_var2!=0) { + if (_vga_var2<0) goto no_scroll; + _vga_var2 = 0; + } else { + if (_vga_var3 != 0) goto no_scroll; + } + + if ((uint16)(value - _x_scroll) < 11) { + _vga_var2 = -20; + tmp = _vga_var1 - _x_scroll; + if (_x_scroll < 20) + _vga_var2 = -_x_scroll; + add_vga_timer(10, NULL, 0, 0); /* special timer */ + } + } +no_scroll:; + + vc_write_var(var, value); +} + +void SimonState::vc_42_delay_if_not_eq() { + uint val = vc_read_var(vc_read_next_word()); + if (val == vc_read_next_word()) { + + add_vga_timer(_vga_base_delay + 1, _vc_ptr - 4, _vga_cur_sprite_id, _vga_cur_file_id); + _vc_ptr = (byte*)&vc_get_out_of_code; + } +} + +void SimonState::vc_43_skip_if_bit_clear() { + if (!vc_get_bit(vc_read_next_word())) { + vc_skip_next_instruction(); + } +} + +void SimonState::vc_44_skip_if_bit_set() { + if (vc_get_bit(vc_read_next_word())) { + vc_skip_next_instruction(); + } +} + +void SimonState::vc_45_set_x() { + VgaSprite *vsp = find_cur_sprite(); + vsp->x = vc_read_var(vc_read_next_word()); + _vga_sprite_changed++; +} + +void SimonState::vc_46_set_y() { + VgaSprite *vsp = find_cur_sprite(); + vsp->y = vc_read_var(vc_read_next_word()); + _vga_sprite_changed++; +} + +void SimonState::vc_47_add_var_f() { + uint var = vc_read_next_word(); + vc_write_var(var, vc_read_var(var) + vc_read_var(vc_read_next_word())); +} + +void SimonState::vc_48() { + uint a = (uint16)_variableArray[12]; + uint b = (uint16)_variableArray[13]; + int c = _variableArray[14]; + uint16 *p = _pathfind_array[a-1]; + int step; + int y1,y2; + int16 *vp; + + p += b*2 + 1; + + step = 2; + if (c<0) { + c = -c; + step = -2; + } + + vp = &_variableArray[20]; + + do{ + y2 = READ_BE_UINT16_UNALIGNED(p); + p += step; + y1 = READ_BE_UINT16_UNALIGNED(p) - y2; + +// assert(READ_BE_UINT16_UNALIGNED(&p[1]) != 999); + + vp[0] = y1>>1; + vp[1] = y1 - (y1>>1); + + vp += 2; + } while (--c); + +} + +void SimonState::vc_set_bit_to(uint bit, bool value) { + uint16 *bits = &_bit_array[bit>>4]; + *bits = (*bits & ~(1<<(bit&15))) | (value << (bit&15)); +} + +bool SimonState::vc_get_bit(uint bit) { + uint16 *bits = &_bit_array[bit>>4]; + return (*bits & (1<<(bit&15))) != 0; +} + +void SimonState::vc_49_set_bit() { + vc_set_bit_to(vc_read_next_word(), true); +} + +void SimonState::vc_50_clear_bit() { + vc_set_bit_to(vc_read_next_word(), false); +} + +void SimonState::vc_51_clear_hitarea_bit_0x40() { + clear_hitarea_bit_0x40(vc_read_next_word()); +} + +void SimonState::vc_52() { + uint16 a = vc_read_next_word(); + + if (!(_game & GAME_SIMON2)) { + playSound(a); + } else { + if (a >= 0x8000) { + a = -a; + warning("vc_52(%d): unimpl"); + } else { + playSound(a); + } + } +} + +void SimonState::vc_53_no_op() { + /* no op */ +} + +void SimonState::vc_54_no_op() { + /* no op */ +} + +void SimonState::vc_55_offset_hit_area() { + HitArea *ha = _hit_areas; + uint count = ARRAYSIZE(_hit_areas); + uint16 id = vc_read_next_word(); + int16 x = vc_read_next_word(); + int16 y = vc_read_next_word(); + + for(;;) { + if (ha->id == id) { + ha->x += x; + ha->y += y; + break; + } + ha++; + if (!--count) + break; + } + + _need_hitarea_recalc++; +} + +void SimonState::vc_56_no_op() { + /* No-Op in simon1 */ + if (_game & GAME_SIMON2) { + uint num = vc_read_var_or_word() * _vga_base_delay; + +#ifdef DUMP_CONTINOUS_VGASCRIPT + fprintf(_dump_file,"; sleep_ex = %d\n", num + gss->VGA_DELAY_BASE); +#endif + + add_vga_timer(num + gss->VGA_DELAY_BASE, _vc_ptr, _vga_cur_sprite_id, _vga_cur_file_id); + _vc_ptr = (byte*)&vc_get_out_of_code; + } +} + +void SimonState::vc_59() { + if (_game & GAME_SIMON2) { + uint file = vc_read_next_word(); + uint start = vc_read_next_word(); + uint end = vc_read_next_word() + 1; + + do { + vc_kill_thread(file, start); + } while (++start != end); + } else { + if (vc_59_helper()) + vc_skip_next_instruction(); + } +} + +void SimonState::vc_58() { + uint sprite = _vga_cur_sprite_id; + uint file = _vga_cur_file_id; + byte *vc_ptr; + uint16 tmp; + + _vga_cur_file_id = vc_read_next_word(); + _vga_cur_sprite_id = vc_read_next_word(); + + tmp = TO_BE_16(vc_read_next_word()); + + vc_ptr = _vc_ptr; + _vc_ptr = (byte*)&tmp; + vc_23_set_pri(); + + _vc_ptr = vc_ptr; + _vga_cur_sprite_id = sprite; + _vga_cur_file_id = file; +} + +void SimonState::vc_57_no_op() { + /* no op */ + +} + +void SimonState::vc_kill_thread(uint file, uint sprite) { + uint16 old_sprite_id, old_cur_file_id; + VgaSleepStruct *vfs; + VgaSprite *vsp; + VgaTimerEntry *vte; + byte *vc_org; + + old_sprite_id = _vga_cur_sprite_id; + old_cur_file_id = _vga_cur_file_id; + vc_org = _vc_ptr; + + _vga_cur_file_id = file; + _vga_cur_sprite_id = sprite; + + vfs = _vga_sleep_structs; + while (vfs->ident != 0) { + if (vfs->sprite_id == _vga_cur_sprite_id + && (vfs->cur_vga_file == _vga_cur_file_id || !(_game & GAME_SIMON2)) + ) { + while (vfs->ident != 0){ + memcpy(vfs, vfs+1, sizeof(VgaSleepStruct)); + vfs++; + } + break; + } + vfs++; + } + + vsp = find_cur_sprite(); + if (vsp->id) { + vc_25_del_sprite_and_get_out(); + + vte = _vga_timer_list; + while (vte->delay != 0) { + if (vte->sprite_id == _vga_cur_sprite_id + && (vte->cur_vga_file == _vga_cur_file_id || !(_game & GAME_SIMON2) ) + ) { + delete_vga_timer(vte); + break; + } + vte++; + } + } + + _vga_cur_file_id = old_cur_file_id; + _vga_cur_sprite_id = old_sprite_id; + _vc_ptr = vc_org; +} + + +/* kill thread */ +void SimonState::vc_60() { + uint file; + + if (_game & GAME_SIMON2) { + file = vc_read_next_word(); + } else { + file = _vga_cur_file_id; + } + uint sprite = vc_read_next_word(); + vc_kill_thread(file, sprite); +} + +void SimonState::vc_61_sprite_change() { + VgaSprite *vsp = find_cur_sprite(); + + vsp->image = vc_read_var_or_word(); + + vsp->x += vc_read_next_word(); + vsp->y += vc_read_next_word(); + vsp->unk4 = 36; + + _vga_sprite_changed++; +} + +void SimonState::vc_62() { + uint i; + byte *vc_ptr_org = _vc_ptr; + + + vc_29_stop_all_sounds(); + +// if (!_video_var_3) { + _video_var_3 = true; + _video_num_pal_colors = 256; + if (_video_palette_mode == 4) + _video_num_pal_colors = 208; +// } + + memcpy(_video_buf_1, _palette_backup, _video_num_pal_colors * sizeof(uint32)); + for(i=NUM_PALETTE_FADEOUT;i!=0;--i) { + palette_fadeout((uint32*)_video_buf_1, _video_num_pal_colors); + _system->set_palette(_video_buf_1, 0, _video_num_pal_colors); + _system->update_screen(); + delay(5); + } + + if (!(_game & GAME_SIMON2)) { + uint16 params[5]; /* parameters to vc_10 */ + VgaSprite *vsp; + VgaPointersEntry *vpe; + + vsp = _vga_sprites; + while (vsp->id != 0) { + if (vsp->id == 128) { + byte *f1 = _cur_vga_file_1; + byte *f2 = _cur_vga_file_2; + uint palmode = _video_palette_mode; + + vpe = &_vga_buffer_pointers[vsp->unk7]; + _cur_vga_file_1 = vpe->vgaFile1; + _cur_vga_file_2 = vpe->vgaFile2; + _video_palette_mode = vsp->unk6; + + params[0] = READ_BE_UINT16_UNALIGNED(&vsp->image); + params[1] = READ_BE_UINT16_UNALIGNED(&vsp->base_color); + params[2] = READ_BE_UINT16_UNALIGNED(&vsp->x); + params[3] = READ_BE_UINT16_UNALIGNED(&vsp->y); + params[4] = READ_BE_UINT16_UNALIGNED(&vsp->unk4); + _vc_ptr = (byte*)params; + vc_10(); + + _video_palette_mode = palmode; + _cur_vga_file_1 = f1; + _cur_vga_file_2 = f2; + break; + } + vsp++; + } + } + + dx_clear_surfaces(_video_palette_mode==4 ? 134 : 200); + + _vc_ptr = vc_ptr_org; +} + +void SimonState::vc_63() { + _palette_color_count = 208; + if(_video_palette_mode != 4) { + _palette_color_count = 256; + } + _video_var_3 = false; +} + +void SimonState::vc_64() { // Simon2 + if (vc_59_helper()) + vc_skip_next_instruction(); +} + +void SimonState::vc_65() { // Simon2 + error("vc_65 unimplemented"); +} + +void SimonState::vc_66() { // Simon2 + uint a = vc_read_next_word(); + uint b = vc_read_next_word(); + + if (vc_read_var(a) != vc_read_var(b)) + vc_skip_next_instruction(); +} + +void SimonState::vc_67() { // Simon2 + uint a = vc_read_next_word(); + uint b = vc_read_next_word(); + + if (vc_read_var(a) >= vc_read_var(b)) + vc_skip_next_instruction(); +} + +void SimonState::vc_68() { // Simon2 + uint a = vc_read_next_word(); + uint b = vc_read_next_word(); + + if (vc_read_var(a) <= vc_read_var(b)) + vc_skip_next_instruction(); +} + +void SimonState::vc_69() { // Simon2 + uint16 a = vc_read_next_word(); + uint16 b = vc_read_next_word(); + + warning("vc_69(%d,%d): music stuff?", a, b); +} + +void SimonState::vc_70() { // Simon2 + uint16 a = vc_read_next_word(); + uint16 b = vc_read_next_word(); + + _vc70_var1 = a; + _vc70_var2 = b; + + warning("vc_70(%d,%d): music stuff?", a, b); +} + + +void SimonState::vc_71() { // Simon2 + if (_vc72_var3==0xFFFF && _vc72_var1==0xFFFF) + vc_skip_next_instruction(); +} + +void SimonState::vc_72() { // Simon2 + uint16 a = vc_read_next_word(); + uint16 b = vc_read_next_word(); + if (a != _vc72_var1) { + _vc72_var2 = b; + _vc72_var3 = a; + } + + warning("vc_72(%d,%d): music stuff?", a, b); +} + +void SimonState::vc_73() { // Simon2 + vc_read_next_byte(); + _op_189_flags |= 1<<vc_read_next_byte(); +} + +void SimonState::vc_74() { // Simon2 + vc_read_next_byte(); + _op_189_flags &= ~(1<<vc_read_next_byte()); +} |