scummvm/simon/vga.cpp

1950 lines
38 KiB
C++
Raw Normal View History

/* 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"
2002-08-21 16:07:07 +00:00
#include "simon/simon.h"
#include "simon/intern.h"
#include "simon/vga.h"
2002-07-07 19:06:48 +00:00
typedef void (SimonState::*VgaOpcodeProc) ();
static const uint16 vc_get_out_of_code = 0;
// Opcode tables
static const VgaOpcodeProc vga_opcode_table[] = {
2002-07-07 19:06:48 +00:00
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
2002-07-07 19:06:48 +00:00
void SimonState::run_vga_script()
{
for (;;) {
uint opcode;
if (_vgascript_toggle) {
2002-07-07 19:06:48 +00:00
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);
// }
}
}
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;
2002-07-07 19:06:48 +00:00
(this->*vga_opcode_table[opcode]) ();
}
}
2002-07-07 19:06:48 +00:00
int SimonState::vc_read_var_or_word()
{
int16 var = vc_read_next_word();
if (var < 0)
var = vc_read_var(-var);
return var;
}
2002-07-07 19:06:48 +00:00
uint SimonState::vc_read_next_word()
{
uint a = READ_BE_UINT16_UNALIGNED(_vc_ptr);
_vc_ptr += 2;
return a;
}
2002-07-07 19:06:48 +00:00
uint SimonState::vc_read_next_byte()
{
return *_vc_ptr++;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_skip_next_instruction()
{
static const byte opcode_param_len_simon1[] = {
2002-07-07 19:06:48 +00:00
0, 6, 2, 10, 6, 4, 2, 2,
4, 4, 10, 0, 2, 2, 2, 2,
2, 0, 2, 0, 4, 2, 4, 2,
2002-07-07 19:06:48 +00:00
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];
}
if (_vgascript_toggle)
fprintf(_dump_file, "; skipped\n");
}
2002-07-07 19:06:48 +00:00
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;
}
}
2002-07-07 19:06:48 +00:00
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
2002-07-07 19:06:48 +00:00
void SimonState::vc_1()
{
/* dummy opcode */
_vc_ptr += 6;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_2()
{
VgaPointersEntry *vpe;
uint num;
uint res;
byte *old_file_1, *old_file_2;
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
}
bb = _cur_vga_file_1;
2002-07-07 19:06:48 +00:00
b = bb + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header *) bb)->hdr2_start);
b = bb + READ_BE_UINT16_UNALIGNED(&((VgaFile1Header2 *) b)->unk2_offs);
2002-07-07 19:06:48 +00:00
while (READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x8 *) b)->id) != num)
b += sizeof(VgaFile1Struct0x8);
vc_ptr_org = _vc_ptr;
2002-07-07 19:06:48 +00:00
_vc_ptr = _cur_vga_file_1 + READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x8 *) b)->script_offs);
if (_vgascript_toggle)
dump_vga_script(_vc_ptr, res, num);
run_vga_script();
2002-07-07 19:06:48 +00:00
_cur_vga_file_1 = old_file_1;
_cur_vga_file_2 = old_file_2;
_vc_ptr = vc_ptr_org;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_3()
{
uint16 a, b, c, d, e, f;
uint16 res;
VgaSprite *vsp;
VgaPointersEntry *vpe;
2002-07-07 19:06:48 +00:00
byte *p, *pp;
2002-07-07 19:06:48 +00:00
a = vc_read_next_word(); /* 0 */
if (_game & GAME_SIMON2) {
2002-07-07 19:06:48 +00:00
f = vc_read_next_word(); /* 0 */
b = vc_read_next_word(); /* 2 */
} else {
2002-07-07 19:06:48 +00:00
b = vc_read_next_word(); /* 2 */
f = b / 100;
}
2002-07-07 19:06:48 +00:00
c = vc_read_next_word(); /* 4 */
d = vc_read_next_word(); /* 6 */
e = vc_read_next_word(); /* 8 */
/* 2nd param ignored with simon1 */
2002-07-07 19:06:48 +00:00
if (has_vgastruct_with_id(b, f))
return;
vsp = _vga_sprites;
2002-07-07 19:06:48 +00:00
while (vsp->id)
vsp++;
vsp->base_color = e;
vsp->unk6 = a;
vsp->priority = 0;
vsp->unk4 = 0;
vsp->image = 0;
vsp->x = c;
vsp->y = d;
vsp->id = b;
vsp->unk7 = res = f;
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
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
2002-07-07 19:06:48 +00:00
{
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
2002-07-07 19:06:48 +00:00
{
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
if (_vgascript_toggle)
dump_vga_script(_cur_vga_file_1 + READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x6*)p)->script_offs), res, b);
2002-07-07 19:06:48 +00:00
add_vga_timer(gss->VGA_DELAY_BASE,
_cur_vga_file_1 + READ_BE_UINT16_UNALIGNED(&((VgaFile1Struct0x6 *) p)->script_offs),
b, res);
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_4()
{
/* dummy opcode */
_vc_ptr += 6;
}
2002-07-07 19:06:48 +00:00
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();
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_6_maybe_skip_3_inv()
{
if (!vc_maybe_skip_proc_3(vc_read_next_word()))
vc_skip_next_instruction();
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_7_maybe_skip_3()
{
if (vc_maybe_skip_proc_3(vc_read_next_word()))
vc_skip_next_instruction();
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_8_maybe_skip_2()
{
uint a = vc_read_next_word();
uint b = vc_read_next_word();
2002-07-07 19:06:48 +00:00
if (!vc_maybe_skip_proc_2(a, b))
vc_skip_next_instruction();
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_9_maybe_skip()
{
uint a = vc_read_next_word();
uint b = vc_read_next_word();
2002-07-07 19:06:48 +00:00
if (!vc_maybe_skip_proc_1(a, b))
vc_skip_next_instruction();
}
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
for (;;) {
a = *src++;
2002-07-07 19:06:48 +00:00
start_here:;
if (a >= 0) {
color = *src++;
do {
*dst++ = color;
if (!--dh) {
2002-07-07 19:06:48 +00:00
if (--a < 0)
a = -0x80;
else
src--;
goto get_out;
}
2002-07-07 19:06:48 +00:00
} while (--a >= 0);
} else {
do {
*dst++ = *src++;
if (!--dh) {
2002-07-07 19:06:48 +00:00
if (++a == 0)
a = -0x80;
goto get_out;
}
2002-07-07 19:06:48 +00:00
} while (++a != 0);
}
}
get_out:;
vs->depack_src = src;
vs->depack_cont = a;
return vs->depack_dest + vs->y_skip;
}
2002-07-07 19:06:48 +00:00
void vc_10_skip_cols(VC10_state * vs)
{
vs->depack_cont = -0x80;
2002-07-07 19:06:48 +00:00
while (vs->x_skip) {
vc_10_depack_column(vs);
vs->x_skip--;
}
}
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
if (cur == -0x80)
cur = *src++;
2002-07-07 19:06:48 +00:00
for (;;) {
if (cur >= 0) {
/* rle_same */
color = *src++;
do {
*dst = color;
dst += w;
if (!--h_cur) {
2002-07-07 19:06:48 +00:00
if (--cur < 0)
cur = -0x80;
else
src--;
goto next_line;
}
2002-07-07 19:06:48 +00:00
} 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++;
}
2002-07-07 19:06:48 +00:00
next_line:
dst_org++;
2002-07-07 19:06:48 +00:00
} while (--w_cur);
}
{
byte *dst_org, *src_org;
uint i;
2002-07-07 19:06:48 +00:00
src_org = dst_org = _video_buf_1 + w;
do {
byte *dst = dst_org;
2002-07-07 19:06:48 +00:00
for (i = 0; i != w; ++i) {
byte b = src_org[i];
2002-07-07 19:06:48 +00:00
b = (b >> 4) | (b << 4);
*--dst = b;
}
src_org += w;
dst_org += w;
} while (--h);
}
return _video_buf_1;
}
2002-07-07 19:06:48 +00:00
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,
2002-07-07 19:06:48 +00:00
0, 0, 3, 136,
17, 0, 3, 136,
0, 0, 20, 200,
0, 0, 20, 134
};
/* simon2 specific */
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
for (;;) {
reps = *src++;
if (reps >= 0) {
color = *src++;
2002-07-07 19:06:48 +00:00
do {
*dst = color;
dst += pitch;
/* reached bottom? */
if (--h == 0) {
2002-07-07 19:06:48 +00:00
/* reached right edge? */
if (--w == 0)
return;
dst = ++dst_org;
h = _vga_var5;
}
2002-07-07 19:06:48 +00:00
} while (--reps >= 0);
} else {
2002-07-07 19:06:48 +00:00
do {
*dst = *src++;
dst += pitch;
/* reached bottom? */
if (--h == 0) {
2002-07-07 19:06:48 +00:00
/* reached right edge? */
if (--w == 0)
return;
dst = ++dst_org;
h = _vga_var5;
}
} while (++reps != 0);
}
}
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_10()
{
byte *p2;
2002-07-07 19:06:48 +00:00
uint width, height;
byte flags;
const uint16 *vlut;
VC10_state state;
2002-07-07 19:06:48 +00:00
int cur;
state.image = (int16)vc_read_next_word();
2002-07-07 19:06:48 +00:00
if (state.image == 0)
return;
2002-07-07 19:06:48 +00:00
// if (_vga_cur_sprite_id != 802)
// return;
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
state.depack_src = _cur_vga_file_2 + READ_BE_UINT32_UNALIGNED(&*(uint32 *)p2);
2002-07-07 19:06:48 +00:00
width = READ_BE_UINT16_UNALIGNED(p2 + 6) >> 4;
height = p2[5];
flags = p2[4];
2002-07-07 19:06:48 +00:00
if (height == 0 || width == 0)
return;
#ifdef DUMP_DRAWN_BITMAPS
2002-07-07 19:06:48 +00:00
dump_single_bitmap(_vga_cur_file_id, state.image, state.depack_src, width * 16, height,
state.base_color);
#endif
2002-07-07 19:06:48 +00:00
if (flags & 0x80 && !(state.e & 0x10)) {
if (state.e & 1) {
state.e &= ~1;
state.e |= 0x10;
} else {
2002-07-07 19:06:48 +00:00
state.e |= 0x8;
}
}
2002-07-07 19:06:48 +00:00
if (_game & GAME_SIMON2 && width >= 21) {
byte *src, *dst;
uint w;
2002-07-07 19:06:48 +00:00
_vga_var1 = width * 2 - 40;
_vga_var7 = state.depack_src;
_vga_var5 = height;
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
w = 40;
do {
2002-07-07 19:06:48 +00:00
vc_10_helper_8(dst, src + READ_BE_UINT32_UNALIGNED(&*(uint32 *)src));
dst += 8;
src += 4;
} while (--w);
2002-07-07 19:06:48 +00:00
dx_unlock_attached();
2002-07-07 19:06:48 +00:00
return;
}
2002-07-07 19:06:48 +00:00
if (state.e & 0x10)
state.depack_src = vc_10_depack_swap(state.depack_src, width, height);
2002-07-07 19:06:48 +00:00
else if (state.e & 1)
state.depack_src = vc_10_no_depack_swap(state.depack_src);
vlut = &_video_windows[_video_palette_mode * 4];
2002-07-07 19:06:48 +00:00
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 {
2002-07-07 19:06:48 +00:00
if (!--state.draw_width)
return;
state.x_skip++;
2002-07-07 19:06:48 +00:00
} while (++cur);
}
state.x = cur;
2002-07-07 19:06:48 +00:00
cur += state.draw_width - (vlut[2] << 1);
if (cur > 0) {
do {
2002-07-07 19:06:48 +00:00
if (!--state.draw_width)
return;
} while (--cur);
}
2002-07-07 19:06:48 +00:00
cur = state.y;
if (cur < 0) {
do {
2002-07-07 19:06:48 +00:00
if (!--state.draw_height)
return;
state.y_skip++;
2002-07-07 19:06:48 +00:00
} while (++cur);
}
state.y = cur;
cur += state.draw_height - vlut[3];
if (cur > 0) {
do {
2002-07-07 19:06:48 +00:00
if (!--state.draw_height)
return;
} while (--cur);
}
2002-07-07 19:06:48 +00:00
assert(state.draw_width != 0 && state.draw_height != 0);
2002-07-07 19:06:48 +00:00
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;
{
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
state.x_skip <<= 2;
state.dl = width;
state.dh = height;
2002-07-07 19:06:48 +00:00
vc_10_skip_cols(&state);
2002-07-07 19:06:48 +00:00
/* XXX: implement transparency */
w = 0;
do {
2002-07-07 19:06:48 +00:00
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 {
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
} while (--h);
} while (++w != state.draw_width);
/* vc_10_helper_5 */
2002-07-07 19:06:48 +00:00
} 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;
2002-07-07 19:06:48 +00:00
if (state.e & 2) {
/* no transparency */
h = state.draw_height;
do {
2002-07-07 19:06:48 +00:00
memcpy(dst, src, state.draw_width);
dst += 320;
src += width * 16;
2002-07-07 19:06:48 +00:00
} while (--h);
} else {
/* transparency */
h = state.draw_height;
do {
2002-07-07 19:06:48 +00:00
for (i = 0; i != state.draw_width; i++)
if (src[i])
dst[i] = src[i];
dst += 320;
src += width * 16;
2002-07-07 19:06:48 +00:00
} while (--h);
}
} else {
byte *dst_org = state.surf_addr;
src = state.depack_src;
/* AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD EEEEEEEE
* aaaaabbb bbcccccd ddddeeee efffffgg ggghhhhh
*/
2002-07-07 19:06:48 +00:00
if (state.e & 2) {
/* no transparency */
do {
2002-07-07 19:06:48 +00:00
uint count = state.draw_width >> 2;
dst = dst_org;
do {
2002-07-07 19:06:48 +00:00
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 {
2002-07-07 19:06:48 +00:00
uint count = state.draw_width >> 2;
dst = dst_org;
do {
2002-07-07 19:06:48 +00:00
uint32 bits = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | (src[3]);
byte tmp;
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
} while (--count);
dst_org += 320;
} while (--state.draw_height);
}
}
/* vc_10_helper_4 */
} else {
2002-07-07 19:06:48 +00:00
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)");
2002-07-07 19:06:48 +00:00
}
if (state.e & 0x8) {
2002-07-07 19:06:48 +00:00
uint w, h;
byte *src, *dst, *dst_org;
2002-07-07 19:06:48 +00:00
state.x_skip <<= 2; /* reached */
state.dl = width;
state.dh = height;
vc_10_skip_cols(&state);
2002-07-07 19:06:48 +00:00
if (state.e & 2) {
dst_org = state.surf_addr;
w = 0;
do {
src = vc_10_depack_column(&state);
dst = dst_org;
2002-07-07 19:06:48 +00:00
h = 0;
do {
dst[0] = (*src >> 4) | state.base_color;
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
h = 0;
do {
color = (*src >> 4);
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
} while (++w != state.draw_width);
}
/* vc_10_helper_6 */
} else {
2002-07-07 19:06:48 +00:00
byte *src, *dst;
uint count;
src = state.depack_src + (width * state.y_skip) * 8;
dst = state.surf_addr;
state.x_skip <<= 2;
2002-07-07 19:06:48 +00:00
if (state.e & 2) {
do {
2002-07-07 19:06:48 +00:00
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 {
2002-07-07 19:06:48 +00:00
for (count = 0; count != state.draw_width; count++) {
byte color;
2002-07-07 19:06:48 +00:00
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();
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_11_clear_pathfind_array()
{
memset(&_pathfind_array, 0, sizeof(_pathfind_array));
}
2002-07-07 19:06:48 +00:00
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);
2002-07-07 19:06:48 +00:00
_vc_ptr = (byte *)&vc_get_out_of_code;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_13_offset_x()
{
VgaSprite *vsp = find_cur_sprite();
int16 a = vc_read_next_word();
vsp->x += a;
_vga_sprite_changed++;
}
2002-07-07 19:06:48 +00:00
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 */
2002-07-07 19:06:48 +00:00
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 */
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
_vc_ptr = (byte *)&vc_get_out_of_code;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_17_set_pathfind_item()
{
uint a = vc_read_next_word();
2002-07-07 19:06:48 +00:00
_pathfind_array[a - 1] = (uint16 *)_vc_ptr;
while (READ_BE_UINT16_UNALIGNED(_vc_ptr) != 999)
_vc_ptr += 4;
_vc_ptr += 2;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_18_jump_rel()
{
int16 offs = vc_read_next_word();
_vc_ptr += offs;
}
/* chain to script? */
2002-07-07 19:06:48 +00:00
void SimonState::vc_19()
{
/* XXX: not implemented */
error("vc_19: chain to script not implemented");
}
/* helper routines */
/* write unaligned 16-bit */
2002-07-07 19:06:48 +00:00
static void write_16_le(void *p, uint16 a)
{
((byte *)p)[0] = (byte)(a);
((byte *)p)[1] = (byte)(a >> 8);
}
/* read unaligned 16-bit */
2002-07-07 19:06:48 +00:00
static uint16 read_16_le(void *p)
{
return ((byte *)p)[0] | (((byte *)p)[1] << 8);
}
/* FIXME: unaligned access */
2002-07-07 19:06:48 +00:00
void SimonState::vc_20()
{
uint16 a = vc_read_next_word();
write_16_le(_vc_ptr, a);
_vc_ptr += 2;
}
/* FIXME: unaligned access */
2002-07-07 19:06:48 +00:00
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;
}
}
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_22()
{
uint a = vc_read_next_word();
uint b = vc_read_next_word();
2002-07-07 19:06:48 +00:00
uint num = a == 0 ? 0x20 : 0x10;
byte *palptr, *src;
2002-07-07 19:06:48 +00:00
palptr = &_palette[(a << 6)];
src = _cur_vga_file_1 + 6 + b * 96;
do {
2002-07-07 19:06:48 +00:00
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++;
}
2002-07-07 19:06:48 +00:00
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;
}
2002-07-07 19:06:48 +00:00
memcpy(&bak, vsp, sizeof(bak));
bak.priority = pri;
bak.unk6 |= 0x8000;
vus2 = vsp;
if (vsp != _vga_sprites && pri < vsp[-1].priority) {
do {
vsp--;
} while (vsp != _vga_sprites && pri < vsp[-1].priority);
do {
2002-07-07 19:06:48 +00:00
memcpy(vus2, vus2 - 1, sizeof(VgaSprite));
} while (--vus2 != vsp);
memcpy(vus2, &bak, sizeof(VgaSprite));
} else if (vsp[1].id != 0 && pri >= vsp[1].priority) {
do {
vsp++;
} while (vsp[1].id != 0 && pri >= vsp[1].priority);
do {
2002-07-07 19:06:48 +00:00
memcpy(vus2, vus2 + 1, sizeof(VgaSprite));
} while (++vus2 != vsp);
memcpy(vus2, &bak, sizeof(VgaSprite));
} else {
vsp->priority = pri;
}
_vga_sprite_changed++;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_24_set_image_xy()
{
VgaSprite *vsp = find_cur_sprite();
vsp->image = vc_read_var_or_word();
2002-07-07 19:06:48 +00:00
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++;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_25_del_sprite_and_get_out()
{
VgaSprite *vsp = find_cur_sprite();
while (vsp->id != 0) {
2002-07-07 19:06:48 +00:00
memcpy(vsp, vsp + 1, sizeof(VgaSprite));
vsp++;
}
2002-07-07 19:06:48 +00:00
_vc_ptr = (byte *)&vc_get_out_of_code;
_vga_sprite_changed++;
}
2002-07-07 19:06:48 +00:00
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();
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_27_reset_simon1()
{
VgaSprite bak, *vsp;
VgaSleepStruct *vfs;
2002-07-07 19:06:48 +00:00
VgaTimerEntry *vte, *vte2;
_lock_word |= 8;
2002-07-07 19:06:48 +00:00
memset(&bak, 0, sizeof(bak));
vsp = _vga_sprites;
while (vsp->id) {
if (vsp->id == 128) {
2002-07-07 19:06:48 +00:00
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++;
}
2002-07-07 19:06:48 +00:00
vte = _vga_timer_list;
while (vte->delay) {
if (vte->sprite_id != 0x80) {
vte2 = vte;
while (vte2->delay) {
2002-07-07 19:06:48 +00:00
memcpy(vte2, vte2 + 1, sizeof(VgaTimerEntry));
vte2++;
}
} else {
vte++;
}
}
vc_write_var(0xFE, 0);
2002-07-07 19:06:48 +00:00
_lock_word &= ~8;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_27_reset_simon2()
{
_lock_word |= 8;
2002-07-07 19:06:48 +00:00
{
VgaSprite *vsp = _vga_sprites;
while (vsp->id) {
vsp->id = 0;
vsp++;
}
}
{
VgaSleepStruct *vfs = _vga_sleep_structs;
while (vfs->ident) {
vfs->ident = 0;
vfs++;
}
}
2002-07-07 19:06:48 +00:00
{
VgaTimerEntry *vte = _vga_timer_list;
while (vte->delay) {
VgaTimerEntry *vte2 = vte;
while (vte2->delay) {
2002-07-07 19:06:48 +00:00
memcpy(vte2, vte2 + 1, sizeof(VgaTimerEntry));
vte2++;
}
}
}
vc_write_var(0xFE, 0);
2002-07-07 19:06:48 +00:00
_lock_word &= ~8;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_27_reset()
{
if (!(_game & GAME_SIMON2))
vc_27_reset_simon1();
else
vc_27_reset_simon2();
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_28()
{
/* dummy opcode */
_vc_ptr += 8;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_29_stop_all_sounds()
{
2002-11-24 12:53:01 +00:00
_sound->stopAll();
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_30_set_base_delay()
{
_vga_base_delay = vc_read_next_word();
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_31_set_palette_mode()
{
_video_palette_mode = vc_read_next_word();
}
2002-07-07 19:06:48 +00:00
uint SimonState::vc_read_var(uint var)
{
assert(var < 255);
return (uint16)_variableArray[var];
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_write_var(uint var, int16 value)
{
_variableArray[var] = value;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_32_copy_var()
{
uint16 a = vc_read_var(vc_read_next_word());
vc_write_var(vc_read_next_word(), a);
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_33()
{
if (_lock_counter != 0) {
_lock_counter = 1;
unlock();
}
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_34()
{
lock();
_lock_counter = 200;
_left_button_down = 0;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_35()
{
/* not used? */
_vc_ptr += 4;
_vga_sprite_changed++;
}
2002-07-07 19:06:48 +00:00
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 {
2002-07-07 19:06:48 +00:00
set_video_mode_internal(mode, vga_res);
}
} else {
2002-07-07 19:06:48 +00:00
set_video_mode_internal(mode, vga_res);
}
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_37_sprite_unk3_add()
{
VgaSprite *vsp = find_cur_sprite();
vsp->y += vc_read_var(vc_read_next_word());
2002-07-07 19:06:48 +00:00
_vga_sprite_changed++;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_38_skip_if_var_zero()
{
uint var = vc_read_next_word();
if (vc_read_var(var) == 0)
vc_skip_next_instruction();
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_39_set_var()
{
uint var = vc_read_next_word();
int16 value = vc_read_next_word();
2002-07-07 19:06:48 +00:00
vc_write_var(var, value);
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_40_var_add()
{
uint var = vc_read_next_word();
int16 value = vc_read_var(var) + vc_read_next_word();
2002-07-07 19:06:48 +00:00
if (_game & GAME_SIMON2 && var == 0xF && !(_bit_array[5] & 1)) {
int16 tmp;
2002-07-07 19:06:48 +00:00
if (_vga_var2 != 0) {
if (_vga_var2 >= 0)
goto no_scroll;
_vga_var2 = 0;
} else {
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
add_vga_timer(10, NULL, 0, 0); /* special timer */
}
}
no_scroll:;
vc_write_var(var, value);
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_41_var_sub()
{
uint var = vc_read_next_word();
int16 value = vc_read_var(var) - vc_read_next_word();
2002-07-07 19:06:48 +00:00
if (_game & GAME_SIMON2 && var == 0xF && !(_bit_array[5] & 1)) {
int16 tmp;
2002-07-07 19:06:48 +00:00
if (_vga_var2 != 0) {
if (_vga_var2 < 0)
goto no_scroll;
_vga_var2 = 0;
} else {
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
add_vga_timer(10, NULL, 0, 0); /* special timer */
}
}
no_scroll:;
vc_write_var(var, value);
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_42_delay_if_not_eq()
{
uint val = vc_read_var(vc_read_next_word());
if (val == vc_read_next_word()) {
2002-07-07 19:06:48 +00:00
add_vga_timer(_vga_base_delay + 1, _vc_ptr - 4, _vga_cur_sprite_id, _vga_cur_file_id);
2002-07-07 19:06:48 +00:00
_vc_ptr = (byte *)&vc_get_out_of_code;
}
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_43_skip_if_bit_clear()
{
if (!vc_get_bit(vc_read_next_word())) {
vc_skip_next_instruction();
}
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_44_skip_if_bit_set()
{
if (vc_get_bit(vc_read_next_word())) {
vc_skip_next_instruction();
}
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_45_set_x()
{
VgaSprite *vsp = find_cur_sprite();
vsp->x = vc_read_var(vc_read_next_word());
_vga_sprite_changed++;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_46_set_y()
{
VgaSprite *vsp = find_cur_sprite();
vsp->y = vc_read_var(vc_read_next_word());
_vga_sprite_changed++;
}
2002-07-07 19:06:48 +00:00
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()));
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_48()
{
uint a = (uint16)_variableArray[12];
uint b = (uint16)_variableArray[13];
int c = _variableArray[14];
2002-07-07 19:06:48 +00:00
uint16 *p = _pathfind_array[a - 1];
int step;
2002-07-07 19:06:48 +00:00
int y1, y2;
int16 *vp;
2002-07-07 19:06:48 +00:00
p += b * 2 + 1;
step = 2;
2002-07-07 19:06:48 +00:00
if (c < 0) {
c = -c;
step = -2;
}
vp = &_variableArray[20];
2002-07-07 19:06:48 +00:00
do {
y2 = READ_BE_UINT16_UNALIGNED(p);
p += step;
y1 = READ_BE_UINT16_UNALIGNED(p) - y2;
2002-07-07 19:06:48 +00:00
// assert(READ_BE_UINT16_UNALIGNED(&p[1]) != 999);
2002-07-07 19:06:48 +00:00
vp[0] = y1 >> 1;
vp[1] = y1 - (y1 >> 1);
vp += 2;
} while (--c);
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_set_bit_to(uint bit, bool value)
{
uint16 *bits = &_bit_array[bit >> 4];
*bits = (*bits & ~(1 << (bit & 15))) | (value << (bit & 15));
}
2002-07-07 19:06:48 +00:00
bool SimonState::vc_get_bit(uint bit)
{
uint16 *bits = &_bit_array[bit >> 4];
return (*bits & (1 << (bit & 15))) != 0;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_49_set_bit()
{
vc_set_bit_to(vc_read_next_word(), true);
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_50_clear_bit()
{
vc_set_bit_to(vc_read_next_word(), false);
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_51_clear_hitarea_bit_0x40()
{
clear_hitarea_bit_0x40(vc_read_next_word());
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_52()
{
uint16 a = vc_read_next_word();
if (!(_game & GAME_SIMON2)) {
2002-11-24 12:53:01 +00:00
_sound->playEffects(a);
} else {
if (a >= 0x8000) {
a = -a;
2002-11-24 12:53:01 +00:00
_sound->playAmbient(a);
} else {
2002-11-24 12:53:01 +00:00
_sound->playEffects(a);
}
}
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_53_no_op()
{
/* no op */
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_54_no_op()
{
/* no op */
}
2002-07-07 19:06:48 +00:00
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();
2002-07-07 19:06:48 +00:00
for (;;) {
if (ha->id == id) {
ha->x += x;
ha->y += y;
break;
}
ha++;
if (!--count)
break;
}
2002-07-07 19:06:48 +00:00
_need_hitarea_recalc++;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_56_no_op()
{
/* No-Op in simon1 */
if (_game & GAME_SIMON2) {
uint num = vc_read_var_or_word() * _vga_base_delay;
if (_vgascript_toggle)
fprintf(_dump_file, "; sleep_ex = %d\n", num + gss->VGA_DELAY_BASE);
add_vga_timer(num + gss->VGA_DELAY_BASE, _vc_ptr, _vga_cur_sprite_id, _vga_cur_file_id);
2002-07-07 19:06:48 +00:00
_vc_ptr = (byte *)&vc_get_out_of_code;
}
}
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
do {
vc_kill_thread(file, start);
} while (++start != end);
} else {
if (vc_59_helper())
vc_skip_next_instruction();
}
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_58()
{
uint sprite = _vga_cur_sprite_id;
uint file = _vga_cur_file_id;
byte *vc_ptr;
uint16 tmp;
2002-07-07 19:06:48 +00:00
_vga_cur_file_id = vc_read_next_word();
_vga_cur_sprite_id = vc_read_next_word();
tmp = TO_BE_16(vc_read_next_word());
2002-07-07 19:06:48 +00:00
vc_ptr = _vc_ptr;
2002-07-07 19:06:48 +00:00
_vc_ptr = (byte *)&tmp;
vc_23_set_pri();
_vc_ptr = vc_ptr;
_vga_cur_sprite_id = sprite;
_vga_cur_file_id = file;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_57_no_op()
{
/* no op */
2002-07-07 19:06:48 +00:00
}
2002-07-07 19:06:48 +00:00
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;
2002-07-07 19:06:48 +00:00
_vga_cur_file_id = file;
_vga_cur_sprite_id = sprite;
2002-07-07 19:06:48 +00:00
vfs = _vga_sleep_structs;
while (vfs->ident != 0) {
if (vfs->sprite_id == _vga_cur_sprite_id
2002-07-07 19:06:48 +00:00
&& (vfs->cur_vga_file == _vga_cur_file_id || !(_game & GAME_SIMON2))
) {
while (vfs->ident != 0) {
memcpy(vfs, vfs + 1, sizeof(VgaSleepStruct));
vfs++;
}
break;
}
vfs++;
}
2002-07-07 19:06:48 +00:00
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
2002-07-07 19:06:48 +00:00
&& (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 */
2002-07-07 19:06:48 +00:00
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);
}
2002-07-07 19:06:48 +00:00
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++;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_62()
{
uint i;
byte *vc_ptr_org = _vc_ptr;
vc_29_stop_all_sounds();
2002-07-07 19:06:48 +00:00
if ((_game & GAME_SIMON2) && (!_video_var_3)) {
warning("vc_62: music stuff?");
}
2002-07-07 19:06:48 +00:00
_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));
2002-07-07 19:06:48 +00:00
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);
}
2002-07-07 19:06:48 +00:00
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);
2002-07-07 19:06:48 +00:00
_vc_ptr = (byte *)params;
vc_10();
_video_palette_mode = palmode;
_cur_vga_file_1 = f1;
_cur_vga_file_2 = f2;
break;
}
vsp++;
}
}
2002-07-07 19:06:48 +00:00
dx_clear_surfaces(_video_palette_mode == 4 ? 134 : 200);
_vc_ptr = vc_ptr_org;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_63()
{
_palette_color_count = 208;
2002-07-07 19:06:48 +00:00
if (_video_palette_mode != 4) {
_palette_color_count = 256;
}
_video_var_3 = false;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_64()
{ // Simon2
if (vc_59_helper())
vc_skip_next_instruction();
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_65()
{ // Simon2
warning("vc_65 unimplemented");
//_palette_color_count = 0x270;
//_video_num_pal_colors = 0x0D0;
//if (_video_palette_mode != 4) {
//_palette_color_count = 0x300;
//_video_num_pal_colors = 0x100;
//}
//_palette_color_count |= 0x8000;
//_video_var_3 = false;
}
2002-07-07 19:06:48 +00:00
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();
}
2002-07-07 19:06:48 +00:00
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();
}
2002-07-07 19:06:48 +00:00
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();
}
2002-07-07 19:06:48 +00:00
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);
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_70()
{ // Simon2
uint16 a = vc_read_next_word();
uint16 b = vc_read_next_word();
_vc70_var1 = a;
_vc70_var2 = b;
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_71()
{ // Simon2
if (_vc72_var3 == 0xFFFF && _vc72_var1 == 0xFFFF)
vc_skip_next_instruction();
}
2002-07-07 19:06:48 +00:00
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;
}
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_73()
{ // Simon2
vc_read_next_byte();
2002-07-07 19:06:48 +00:00
_op_189_flags |= 1 << vc_read_next_byte();
}
2002-07-07 19:06:48 +00:00
void SimonState::vc_74()
{ // Simon2
vc_read_next_byte();
2002-07-07 19:06:48 +00:00
_op_189_flags &= ~(1 << vc_read_next_byte());
}