aboutsummaryrefslogtreecommitdiff
path: root/simon/vga.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'simon/vga.cpp')
-rw-r--r--simon/vga.cpp1966
1 files changed, 1966 insertions, 0 deletions
diff --git a/simon/vga.cpp b/simon/vga.cpp
new file mode 100644
index 0000000000..39d56d0c85
--- /dev/null
+++ b/simon/vga.cpp
@@ -0,0 +1,1966 @@
+/* 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/simon.h"
+#include "simon/intern.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");
+ return NULL;
+}
+
+/* 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());
+}