aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorNorbert Lange2009-07-01 14:45:24 +0000
committerNorbert Lange2009-07-01 14:45:24 +0000
commitabef70f4e14f495b20097cb46411d1fafbafdd53 (patch)
tree27462f82f352b303ac059dd275466930c88b2de6 /engines
parent3b94e2488df9a699a899727515ac69af6a0a1a6e (diff)
parentf9298ff40310149779b37ccdecc873afba7adf2f (diff)
downloadscummvm-rg350-abef70f4e14f495b20097cb46411d1fafbafdd53.tar.gz
scummvm-rg350-abef70f4e14f495b20097cb46411d1fafbafdd53.tar.bz2
scummvm-rg350-abef70f4e14f495b20097cb46411d1fafbafdd53.zip
Merging in changes from trunk
svn-id: r41989
Diffstat (limited to 'engines')
-rw-r--r--engines/agi/agi.cpp2
-rw-r--r--engines/agi/cycle.cpp4
-rw-r--r--engines/agi/detection.cpp94
-rw-r--r--engines/agi/op_cmd.cpp3
-rw-r--r--engines/agi/sound.cpp40
-rw-r--r--engines/agi/sound.h59
-rw-r--r--engines/agos/animation.cpp8
-rw-r--r--engines/agos/animation.h1
-rw-r--r--engines/agos/charset-fontdata.cpp4
-rw-r--r--engines/cine/bg.cpp1
-rw-r--r--engines/cine/cine.h8
-rw-r--r--engines/cine/gfx.cpp354
-rw-r--r--engines/cine/gfx.h40
-rw-r--r--engines/cine/main_loop.cpp2
-rw-r--r--engines/cine/pal.cpp85
-rw-r--r--engines/cine/pal.h17
-rw-r--r--engines/cine/sound.cpp2
-rw-r--r--engines/cine/various.cpp12
-rw-r--r--engines/cruise/cruise.cpp21
-rw-r--r--engines/cruise/cruise.h11
-rw-r--r--engines/cruise/cruise_main.cpp26
-rw-r--r--engines/cruise/dataLoader.cpp42
-rw-r--r--engines/cruise/dataLoader.h1
-rw-r--r--engines/cruise/detection.cpp3
-rw-r--r--engines/cruise/function.cpp100
-rw-r--r--engines/cruise/menu.cpp3
-rw-r--r--engines/cruise/saveload.cpp7
-rw-r--r--engines/cruise/sound.cpp913
-rw-r--r--engines/cruise/sound.h89
-rw-r--r--engines/cruise/vars.cpp2
-rw-r--r--engines/cruise/vars.h2
-rw-r--r--engines/cruise/volume.cpp37
-rw-r--r--engines/gob/dataio.cpp18
-rw-r--r--engines/gob/dataio.h3
-rw-r--r--engines/gob/demos/demoplayer.cpp4
-rw-r--r--engines/gob/detection.cpp1081
-rw-r--r--engines/gob/draw.cpp10
-rw-r--r--engines/gob/draw_v1.cpp40
-rw-r--r--engines/gob/draw_v2.cpp76
-rw-r--r--engines/gob/expression.cpp1144
-rw-r--r--engines/gob/expression.h178
-rw-r--r--engines/gob/game.cpp669
-rw-r--r--engines/gob/game.h132
-rw-r--r--engines/gob/game_fascin.cpp1
-rw-r--r--engines/gob/game_v1.cpp318
-rw-r--r--engines/gob/game_v2.cpp315
-rw-r--r--engines/gob/game_v6.cpp254
-rw-r--r--engines/gob/global.cpp28
-rw-r--r--engines/gob/global.h76
-rw-r--r--engines/gob/gob.cpp45
-rw-r--r--engines/gob/gob.h4
-rw-r--r--engines/gob/init.cpp58
-rw-r--r--engines/gob/inter.cpp152
-rw-r--r--engines/gob/inter.h341
-rw-r--r--engines/gob/inter_bargon.cpp684
-rw-r--r--engines/gob/inter_fascin.cpp690
-rw-r--r--engines/gob/inter_v1.cpp1690
-rw-r--r--engines/gob/inter_v2.cpp1279
-rw-r--r--engines/gob/inter_v3.cpp702
-rw-r--r--engines/gob/inter_v4.cpp707
-rw-r--r--engines/gob/inter_v5.cpp785
-rw-r--r--engines/gob/inter_v6.cpp787
-rw-r--r--engines/gob/map_v1.cpp11
-rw-r--r--engines/gob/map_v2.cpp21
-rw-r--r--engines/gob/map_v4.cpp21
-rw-r--r--engines/gob/module.mk5
-rw-r--r--engines/gob/mult.cpp8
-rw-r--r--engines/gob/mult_v1.cpp25
-rw-r--r--engines/gob/mult_v2.cpp67
-rw-r--r--engines/gob/parse.cpp1499
-rw-r--r--engines/gob/parse.h128
-rw-r--r--engines/gob/resources.cpp706
-rw-r--r--engines/gob/resources.h207
-rw-r--r--engines/gob/save/savefile.h2
-rw-r--r--engines/gob/save/saveload.cpp2
-rw-r--r--engines/gob/save/saveload_v3.cpp8
-rw-r--r--engines/gob/save/saveload_v4.cpp6
-rw-r--r--engines/gob/scenery.cpp396
-rw-r--r--engines/gob/script.cpp522
-rw-r--r--engines/gob/script.h169
-rw-r--r--engines/gob/sound/adlib.cpp522
-rw-r--r--engines/gob/sound/adlib.h84
-rw-r--r--engines/gob/sound/bgatmosphere.cpp1
-rw-r--r--engines/gob/sound/bgatmosphere.h3
-rw-r--r--engines/gob/sound/cdrom.cpp3
-rw-r--r--engines/gob/sound/cdrom.h4
-rw-r--r--engines/gob/sound/infogrames.cpp4
-rw-r--r--engines/gob/sound/protracker.cpp2
-rw-r--r--engines/gob/sound/protracker.h1
-rw-r--r--engines/gob/sound/sound.cpp194
-rw-r--r--engines/gob/sound/sound.h26
-rw-r--r--engines/gob/sound/soundblaster.cpp1
-rw-r--r--engines/gob/sound/soundblaster.h3
-rw-r--r--engines/gob/sound/sounddesc.cpp50
-rw-r--r--engines/gob/sound/sounddesc.h17
-rw-r--r--engines/gob/sound/soundmixer.cpp1
-rw-r--r--engines/gob/sound/soundmixer.h4
-rw-r--r--engines/gob/totfile.cpp135
-rw-r--r--engines/gob/totfile.h80
-rw-r--r--engines/gob/util.cpp6
-rw-r--r--engines/gob/util.h1
-rw-r--r--engines/gob/videoplayer.cpp6
-rw-r--r--engines/groovie/detection.cpp24
-rw-r--r--engines/groovie/groovie.cpp5
-rw-r--r--engines/kyra/animator_mr.cpp2
-rw-r--r--engines/kyra/debugger.cpp16
-rw-r--r--engines/kyra/gui.cpp112
-rw-r--r--engines/kyra/gui.h9
-rw-r--r--engines/kyra/gui_hof.cpp48
-rw-r--r--engines/kyra/gui_lok.cpp41
-rw-r--r--engines/kyra/gui_lok.h2
-rw-r--r--engines/kyra/gui_lol.cpp675
-rw-r--r--engines/kyra/gui_lol.h116
-rw-r--r--engines/kyra/gui_mr.cpp44
-rw-r--r--engines/kyra/gui_v2.cpp34
-rw-r--r--engines/kyra/gui_v2.h2
-rw-r--r--engines/kyra/items_hof.cpp8
-rw-r--r--engines/kyra/items_lol.cpp2
-rw-r--r--engines/kyra/kyra_hof.cpp33
-rw-r--r--engines/kyra/kyra_lok.cpp10
-rw-r--r--engines/kyra/kyra_lok.h1
-rw-r--r--engines/kyra/kyra_mr.cpp79
-rw-r--r--engines/kyra/kyra_mr.h1
-rw-r--r--engines/kyra/kyra_v1.cpp24
-rw-r--r--engines/kyra/kyra_v1.h8
-rw-r--r--engines/kyra/lol.cpp440
-rw-r--r--engines/kyra/lol.h27
-rw-r--r--engines/kyra/saveload.cpp3
-rw-r--r--engines/kyra/scene_hof.cpp18
-rw-r--r--engines/kyra/scene_lok.cpp12
-rw-r--r--engines/kyra/scene_lol.cpp57
-rw-r--r--engines/kyra/scene_mr.cpp22
-rw-r--r--engines/kyra/screen.cpp689
-rw-r--r--engines/kyra/screen.h151
-rw-r--r--engines/kyra/screen_hof.cpp6
-rw-r--r--engines/kyra/screen_hof.h2
-rw-r--r--engines/kyra/screen_lok.cpp213
-rw-r--r--engines/kyra/screen_lok.h32
-rw-r--r--engines/kyra/screen_lol.cpp99
-rw-r--r--engines/kyra/screen_lol.h13
-rw-r--r--engines/kyra/screen_v2.cpp176
-rw-r--r--engines/kyra/screen_v2.h9
-rw-r--r--engines/kyra/script.cpp86
-rw-r--r--engines/kyra/script.h11
-rw-r--r--engines/kyra/script_hof.cpp46
-rw-r--r--engines/kyra/script_lok.cpp63
-rw-r--r--engines/kyra/script_lol.cpp110
-rw-r--r--engines/kyra/script_mr.cpp7
-rw-r--r--engines/kyra/script_tim.cpp144
-rw-r--r--engines/kyra/script_tim.h7
-rw-r--r--engines/kyra/seqplayer.cpp40
-rw-r--r--engines/kyra/sequences_hof.cpp153
-rw-r--r--engines/kyra/sequences_lok.cpp111
-rw-r--r--engines/kyra/sequences_lol.cpp116
-rw-r--r--engines/kyra/sound_lol.cpp11
-rw-r--r--engines/kyra/sound_midi.cpp4
-rw-r--r--engines/kyra/sound_towns.cpp8
-rw-r--r--engines/kyra/sprites.cpp12
-rw-r--r--engines/kyra/sprites_lol.cpp4
-rw-r--r--engines/kyra/staticres.cpp144
-rw-r--r--engines/kyra/text_lok.cpp22
-rw-r--r--engines/kyra/text_lol.cpp18
-rw-r--r--engines/kyra/text_lol.h9
-rw-r--r--engines/kyra/text_mr.cpp2
-rw-r--r--engines/kyra/util.cpp63
-rw-r--r--engines/kyra/util.h10
-rw-r--r--engines/kyra/vqa.cpp25
-rw-r--r--engines/kyra/vqa.h14
-rw-r--r--engines/kyra/wsamovie.cpp136
-rw-r--r--engines/kyra/wsamovie.h28
-rw-r--r--engines/parallaction/disk.cpp145
-rw-r--r--engines/parallaction/disk.h40
-rw-r--r--engines/parallaction/disk_br.cpp114
-rw-r--r--engines/parallaction/disk_ns.cpp79
-rw-r--r--engines/parallaction/gfxbase.cpp8
-rw-r--r--engines/parallaction/iff.cpp276
-rw-r--r--engines/parallaction/iff.h105
-rw-r--r--engines/parallaction/module.mk2
-rw-r--r--engines/parallaction/sound.h36
-rw-r--r--engines/parallaction/sound_br.cpp90
-rw-r--r--engines/parallaction/sound_ns.cpp69
-rw-r--r--engines/saga/scene.cpp7
-rw-r--r--engines/sci/console.cpp45
-rw-r--r--engines/sci/console.h9
-rw-r--r--engines/sci/detection.cpp58
-rw-r--r--engines/sci/engine/gc.h20
-rw-r--r--engines/sci/engine/intmap.h7
-rw-r--r--engines/sci/engine/kernel.cpp6
-rw-r--r--engines/sci/engine/kernel.h179
-rw-r--r--engines/sci/engine/kgraphics.cpp24
-rw-r--r--engines/sci/engine/ksound.cpp96
-rw-r--r--engines/sci/engine/memobj.cpp7
-rw-r--r--engines/sci/engine/memobj.h6
-rw-r--r--engines/sci/engine/script.cpp3
-rw-r--r--engines/sci/engine/scriptdebug.cpp28
-rw-r--r--engines/sci/engine/seg_manager.cpp2
-rw-r--r--engines/sci/engine/seg_manager.h267
-rw-r--r--engines/sci/engine/state.cpp69
-rw-r--r--engines/sci/engine/state.h26
-rw-r--r--engines/sci/engine/vm.cpp4
-rw-r--r--engines/sci/engine/vm.h500
-rw-r--r--engines/sci/gfx/font.h165
-rw-r--r--engines/sci/gfx/gfx_driver.h327
-rw-r--r--engines/sci/gfx/gfx_gui.cpp10
-rw-r--r--engines/sci/gfx/gfx_gui.h324
-rw-r--r--engines/sci/gfx/gfx_options.h22
-rw-r--r--engines/sci/gfx/gfx_res_options.h44
-rw-r--r--engines/sci/gfx/gfx_resmgr.h302
-rw-r--r--engines/sci/gfx/gfx_resource.h359
-rw-r--r--engines/sci/gfx/gfx_state_internal.h129
-rw-r--r--engines/sci/gfx/gfx_system.h227
-rw-r--r--engines/sci/gfx/gfx_tools.h273
-rw-r--r--engines/sci/gfx/gfx_widgets.h468
-rw-r--r--engines/sci/gfx/menubar.h80
-rw-r--r--engines/sci/gfx/operations.h955
-rw-r--r--engines/sci/gfx/palette.h20
-rw-r--r--engines/sci/gfx/res_pic.cpp2
-rw-r--r--engines/sci/gfx/res_view.cpp2
-rw-r--r--engines/sci/gfx/seq_decoder.h7
-rw-r--r--engines/sci/resource.cpp514
-rw-r--r--engines/sci/resource.h96
-rw-r--r--engines/sci/sci.cpp6
-rw-r--r--engines/sci/sci.h11
-rw-r--r--engines/sci/sfx/core.cpp203
-rw-r--r--engines/sci/sfx/core.h20
-rw-r--r--engines/scumm/actor.cpp16
-rw-r--r--engines/scumm/he/script_v100he.cpp3
-rw-r--r--engines/scumm/he/script_v72he.cpp3
-rw-r--r--engines/scumm/vars.cpp2
-rw-r--r--engines/sword1/music.cpp2
-rw-r--r--engines/sword1/sound.cpp4
-rw-r--r--engines/tinsel/detection.cpp6
-rw-r--r--engines/tinsel/palette.cpp3
-rw-r--r--engines/tinsel/tinsel.cpp15
-rw-r--r--engines/tucker/locations.cpp18
-rw-r--r--engines/tucker/resource.cpp1
-rw-r--r--engines/tucker/sequences.cpp87
-rw-r--r--engines/tucker/staticres.cpp458
-rw-r--r--engines/tucker/tucker.cpp3
-rw-r--r--engines/tucker/tucker.h32
240 files changed, 15516 insertions, 15914 deletions
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index 0676c0f8e4..e373dd3e6d 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -729,6 +729,8 @@ void AgiEngine::initialize() {
// because Apple IIGS AGI games use only Apple IIGS specific sound resources.
if (getPlatform() == Common::kPlatformApple2GS) {
_soundemu = SOUND_EMU_APPLE2GS;
+ } else if (getPlatform() == Common::kPlatformCoCo3) {
+ _soundemu = SOUND_EMU_COCO3;
} else {
switch (MidiDriver::detectMusicDriver(MDT_PCSPK)) {
case MD_PCSPK:
diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp
index aef236ce64..bf4622bc08 100644
--- a/engines/agi/cycle.cpp
+++ b/engines/agi/cycle.cpp
@@ -198,7 +198,9 @@ int AgiEngine::mainCycle() {
// In AGI Mouse emulation mode we must update the mouse-related
// vars in every interpreter cycle.
- if (getFeatures() & GF_AGIMOUSE) {
+ //
+ // We run AGIMOUSE always as a side effect
+ if (getFeatures() & GF_AGIMOUSE || 1) {
_game.vars[28] = g_mouse.x / 2;
_game.vars[29] = g_mouse.y;
}
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index 302951b69b..910f6e0e55 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -168,6 +168,9 @@ using Common::GUIO_NONE;
#define FANMADE_ILVF(id,name,md5,lang,ver,features) GAME_LVFPN(id,name,"logdir",md5,-1,lang,ver,(GF_FANMADE|features),GID_FANMADE,Common::kPlatformPC,GType_V2)
+#define FANMADE_ISVP(id,name,md5,size,ver,platform) GAME_LVFPN(id,name,"logdir",md5,size,Common::EN_ANY,ver,GF_FANMADE,GID_FANMADE,platform,GType_V2)
+#define FANMADE_SVP(name,md5,size,ver,platform) FANMADE_ISVP("agi-fanmade",name,md5,size,ver,platform)
+
#define FANMADE_LVF(name,md5,lang,ver,features) FANMADE_ILVF("agi-fanmade",name,md5,lang,ver,features)
#define FANMADE_LF(name,md5,lang,features) FANMADE_LVF(name,md5,lang,0x2917,features)
@@ -222,6 +225,12 @@ static const AGIGameDescription gameDescriptions[] = {
// Black Cauldron (PC) 2.10 [AGI 3.002.097]
GAME3("bc", "2.10", "bcdir", "0de3953c9225009dc91e5b0d1692967b", 0x3149, GID_BC),
+ // Black Cauldron (CoCo3 360k) [AGI 2.023]
+ GAME_PS("bc", "", "51212c54808ade96176f201ae0ac7a6f", 357, 0x2440, GID_BC, Common::kPlatformCoCo3),
+
+ // Black Cauldron (CoCo3 360k) [AGI 2.072]
+ GAME_PS("bc", "updated", "c4e1937f74e8100cd0152b904434d8b4", 357, 0x2440, GID_BC, Common::kPlatformCoCo3),
+
// TODO
// These aren't supposed to work now as they require unsupported agi engine 2.01
#if 0
@@ -279,6 +288,12 @@ static const AGIGameDescription gameDescriptions[] = {
},
+ // Gold Rush! (CoCo3 720k) [AGI 2.023]
+ GAME_PS("goldrush", "", "0a41b65efc0cd6c4271e957e6ffbbd8e", 744, 0x2440, GID_GOLDRUSH, Common::kPlatformCoCo3),
+
+ // Gold Rush! (CoCo3 360k/720k) [AGI 2.072]
+ GAME_PS("goldrush", "updated", "c49bf56bf91e31a4601a604e51ef8bfb", 744, 0x2440, GID_GOLDRUSH, Common::kPlatformCoCo3),
+
// King's Quest 1 (Amiga) 1.0U # 2.082
// The original game did not have menus, they are enabled under ScummVM
GAME_FP("kq1", "1.0U 1986", "246c695324f1c514aee2b904fa352fad", 0x2440, GF_MENUS, GID_KQ1, Common::kPlatformAmiga),
@@ -297,6 +312,15 @@ static const AGIGameDescription gameDescriptions[] = {
// King's Quest 1 (PC 5.25"/3.5") 2.0F [AGI 2.917]
GAME("kq1", "2.0F 1987-05-05 5.25\"/3.5\"", "10ad66e2ecbd66951534a50aedcd0128", 0x2917, GID_KQ1),
+ // King's Quest 1 (CoCo3 360k) [AGI 2.023]
+ GAME_PS("kq1", "", "10ad66e2ecbd66951534a50aedcd0128", 315, 0x2440, GID_KQ1, Common::kPlatformCoCo3),
+
+ // King's Quest 1 (CoCo3 360k) [AGI 2.023]
+ GAME_PS("kq1", "fixed", "4c8ef8b5d2f1b6c1a93e456d1f1ffc74", 768, 0x2440, GID_KQ1, Common::kPlatformCoCo3),
+
+ // King's Quest 1 (CoCo3 360k) [AGI 2.072]
+ GAME_PS("kq1", "updated", "94087178c78933a4af3cd24d1c8dd7b2", 315, 0x2440, GID_KQ1, Common::kPlatformCoCo3),
+
// King's Quest 2 (IIgs) 2.0A 6/16/88 (CE)
GAME_P("kq2", "2.0A 1988-06-16 (CE)", "5203c8b95250a2ecfee93ddb99414753", 0x2917, GID_KQ2, Common::kPlatformApple2GS),
@@ -316,6 +340,15 @@ static const AGIGameDescription gameDescriptions[] = {
// King's Quest 2 (Russian)
GAME_LPS("kq2", "", "35211c574ececebdc723b23e35f99275", 543, Common::RU_RUS, 0x2917, GID_KQ2, Common::kPlatformPC),
+ // King's Quest 2 (CoCo3 360k) [AGI 2.023]
+ GAME_PS("kq2", "", "b944c4ff18fb8867362dc21cc688a283", 543, 0x2440, GID_KQ2, Common::kPlatformCoCo3),
+
+ // King's Quest 2 (CoCo3 360k) [AGI 2.072]
+ GAME_PS("kq2", "updated", "f64a606de740a5348f3d125c03e989fe", 543, 0x2440, GID_KQ2, Common::kPlatformCoCo3),
+
+ // King's Quest 2 (CoCo3 360k) [AGI 2.023]
+ GAME_PS("kq2", "fixed", "fb33ac2768a94a89117a270771db465c", 768, 0x2440, GID_KQ2, Common::kPlatformCoCo3),
+
// King's Quest 3 (Amiga) 1.01 11/8/86
// The original game did not have menus, they are enabled under ScummVM
GAME_FP("kq3", "1.01 1986-11-08", "8ab343306df0e2d98f136be4e8cfd0ef", 0x2440, GF_MENUS, GID_KQ3, Common::kPlatformAmiga),
@@ -350,6 +383,9 @@ static const AGIGameDescription gameDescriptions[] = {
// King's Quest 3 (PC 3.5") 2.14 3/15/88 [AGI 2.936]
GAME("kq3", "2.14 1988-03-15 3.5\"", "d3d17b77b3b3cd13246749231d9473cd", 0x2936, GID_KQ3),
+ // King's Quest 3 (CoCo3 158k/360k) [AGI 2.023]
+ GAME_PS("kq3", "", "5a6be7d16b1c742c369ef5cc64fefdd2", 429, 0x2440, GID_KQ3, Common::kPlatformCoCo3),
+
// King's Quest 4 (PC 5.25") 2.3 9/27/88 [AGI 3.002.086]
GAME3("kq4", "2.3 1988-09-27", "kq4dir", "6d7714b8b61466a5f5981242b993498f", 0x3086, GID_KQ4),
@@ -371,6 +407,12 @@ static const AGIGameDescription gameDescriptions[] = {
// Menus not tested
GAME3("kq4", "Demo 1988-12-20", "dmdir", "a3332d70170a878469d870b14863d0bf", 0x3149, GID_KQ4),
+ // King's Quest 4 (CoCo3 720k) [AGI 2.023]
+ GAME_PS("kq4", "", "9e7729a28e749ca241d2bf71b9b2dbde", 741, 0x2440, GID_KQ4, Common::kPlatformCoCo3),
+
+ // King's Quest 4 (CoCo3 360k/720k) [AGI 2.072]
+ GAME_PS("kq4", "updated", "1959ca10739edb34069bb504dbd74805", 741, 0x2440, GID_KQ4, Common::kPlatformCoCo3),
+
// Leisure Suit Larry 1 (PC 5.25"/3.5") 1.00 6/1/87 [AGI 2.440]
GAME("lsl1", "1.00 1987-06-01 5.25\"/3.5\"", "1fe764e66857e7f305a5f03ca3f4971d", 0x2440, GID_LSL1),
@@ -392,6 +434,9 @@ static const AGIGameDescription gameDescriptions[] = {
// Leisure Suit Larry 1 (Mac) 1.05 6/26/87
GAME_P("lsl1", "1.05 1987-06-26", "8a0076429890531832f0dc113285e31e", 0x2440, GID_LSL1, Common::kPlatformMacintosh),
+ // Leisure Suit Larry 1 (CoCo3 158k/360k) [AGI 2.072]
+ GAME_PS("lsl1", "", "a2de1fe76565c3e8b40c9d036b5e5612", 198, 0x2440, GID_LSL1, Common::kPlatformCoCo3),
+
// Manhunter NY (ST) 1.03 10/20/88
GAME3_P("mh1", "1.03 1988-10-20", "mhdir", "f2d58056ad802452d60776ee920a52a6", 0x3149, 0, GID_MH1, Common::kPlatformAtariST),
@@ -408,6 +453,12 @@ static const AGIGameDescription gameDescriptions[] = {
// Manhunter NY (PC 3.5") 1.22 8/31/88 [AGI 3.002.102]
GAME3_PS("mh1", "1.22 1988-08-31", "mhdir", "5b625329021ad49fd0c1d6f2d6f54bba", 2141, 0x3149, 0, GID_MH1, Common::kPlatformPC),
+ // Manhunter NY (CoCo3 720k) [AGI 2.023]
+ GAME_PS("mh1", "", "b968285caf2f591c78dd9c9e26ab8974", 495, 0x2440, GID_MH1, Common::kPlatformCoCo3),
+
+ // Manhunter NY (CoCo3 360k/720k) [AGI 2.072]
+ GAME_PS("mh1", "updated", "d47da950c62289f8d4ccf36af73365f2", 495, 0x2440, GID_MH1, Common::kPlatformCoCo3),
+
// Manhunter SF (ST) 1.0 7/29/89
GAME3_P("mh2", "1.0 1989-07-29", "mh2dir", "5e3581495708b952fea24438a6c7e040", 0x3149, 0, GID_MH1, Common::kPlatformAtariST),
@@ -420,6 +471,12 @@ static const AGIGameDescription gameDescriptions[] = {
// Manhunter SF (PC 3.5") 3.02 7/26/89 [AGI 3.002.149]
GAME3("mh2", "3.02 1989-07-26 3.5\"", "mh2dir", "6fb6f0ee2437704c409cf17e081ba152", 0x3149, GID_MH2),
+ // Manhunter SF (CoCo3 720k) [AGI 2.023]
+ GAME_PS("mh2", "", "acaaa577e10d1753c5a74f6ae1d858d4", 591, 0x2440, GID_MH2, Common::kPlatformCoCo3),
+
+ // Manhunter SF (CoCo3 720k) [AGI 2.072]
+ GAME_PS("mh2", "updated", "c64875766700196e72a92359f70f45a9", 591, 0x2440, GID_MH2, Common::kPlatformCoCo3),
+
// Mickey's Space Adventure
// Preagi game
GAMEpre_P("mickey", "", "1.pic", "b6ec04c91a05df374792872c4d4ce66d", 0x0000, GID_MICKEY, Common::kPlatformPC),
@@ -437,11 +494,8 @@ static const AGIGameDescription gameDescriptions[] = {
// Mixed-Up Mother Goose (PC) [AGI 2.915]
GAME("mixedup", "1987-11-10", "e524655abf9b96a3b179ffcd1d0f79af", 0x2917, GID_MIXEDUP),
-#if 0
- // Mixed Up Mother Goose (PC) [AGI 2.915] (Broken)
- // Menus not tested
- GAME("mixedup", "[corrupt/OBJECT from disk 1]", "e524655abf9b96a3b179ffcd1d0f79af", 0x2917, GID_MIXEDUP),
-#endif
+ // Mixed-Up Mother Goose (CoCo3 360k) [AGI 2.072]
+ GAME_PS("mixedup", "", "44e63e9b4d4822a31edea0e8a7e7eac4", 606, 0x2440, GID_MIXEDUP, Common::kPlatformCoCo3),
// Police Quest 1 (PC) 2.0E 11/17/87 [AGI 2.915]
GAME("pq1", "2.0E 1987-11-17", "2fd992a92df6ab0461d5a2cd83c72139", 0x2917, GID_PQ1),
@@ -471,6 +525,12 @@ static const AGIGameDescription gameDescriptions[] = {
// not sure about disk format -- dsymonds
GAME("pq1", "2.0G 1987-12-03", "d194e5d88363095f55d5096b8e32fbbb", 0x2917, GID_PQ1),
+ // Police Quest 1 (CoCo3 360k) [AGI 2.023]
+ GAME_PS("pq1", "", "28a077041f75aab78f66804800940085", 375, 0x2440, GID_PQ1, Common::kPlatformCoCo3),
+
+ // Police Quest 1 (CoCo3 360k) [AGI 2.072]
+ GAME_PS("pq1", "updated", "63b9a9c6eec154751dd446cd3693e0e2", 768, 0x2440, GID_PQ1, Common::kPlatformCoCo3),
+
// Space Quest 1 (ST) 1.1A
// The original game did not have menus, they are enabled under ScummVM
GAME_FP("sq1", "1.1A 1986-02-06", "6421fb64b0e6604c9dd065975d9279e9", 0x2440, GF_MENUS, GID_SQ1, Common::kPlatformAtariST),
@@ -499,8 +559,14 @@ static const AGIGameDescription gameDescriptions[] = {
// Space Quest 1 (PC 5.25"/3.5") 2.2 [AGI 2.426/2.917]
GAME("sq1", "2.2 1987-05-07 5.25\"/3.5\"", "5d67630aba008ec5f7f9a6d0a00582f4", 0x2440, GID_SQ1),
- // Space Quest 1 (CoCo3)
- GAME_P("sq1", "", "5d67630aba008ec5f7f9a6d0a00582f4", 0x2440, GID_SQ1, Common::kPlatformCoCo3),
+ // Space Quest 1 (CoCo3 360k) [AGI 2.072]
+ GAME_PS("sq1", "", "5d67630aba008ec5f7f9a6d0a00582f4", 372, 0x2440, GID_SQ1, Common::kPlatformCoCo3),
+
+ // Space Quest 1 (CoCo3 360k) [AGI 2.023]
+ GAME_PS("sq1", "fixed", "ca822b768b6462e410423ea7f498daee", 768, 0x2440, GID_SQ1, Common::kPlatformCoCo3),
+
+ // Space Quest 1 (CoCo3 360k) [AGI 2.072]
+ GAME_PS("sq1", "updated", "7fa54e6bb7ffeb4cf20eca39d86f5fb2", 387, 0x2440, GID_SQ1, Common::kPlatformCoCo3),
// Space Quest 2 (PC 3.5") 2.0D [AGI 2.936]
GAME("sq2", "2.0D 1988-03-14 3.5\"", "85390bde8958c39830e1adbe9fff87f3", 0x2936, GID_SQ2),
@@ -550,6 +616,12 @@ static const AGIGameDescription gameDescriptions[] = {
// Space Quest 2 (PC 3.5") 2.0F [AGI 2.936]
GAME("sq2", "2.0F 1989-01-05 3.5\"", "28add5125484302d213911df60d2aded", 0x2936, GID_SQ2),
+ // Space Quest 2 (CoCo3 360k) [AGI 2.023]
+ GAME_PS("sq2", "", "12973d39b892dc9d280257fd271e9597", 768, 0x2440, GID_SQ2, Common::kPlatformCoCo3),
+
+ // Space Quest 2 (CoCo3 360k) [AGI 2.072]
+ GAME_PS("sq2", "updated", "d24f19b047e65e1763eff4b46f3d50df", 768, 0x2440, GID_SQ2, Common::kPlatformCoCo3),
+
// Troll's Tale
GAMEpre_PS("troll", "", "troll.img", "62903f264b3d849be4214b3a5c42a2fa", 184320, 0x0000, GID_TROLL, Common::kPlatformPC),
@@ -568,6 +640,9 @@ static const AGIGameDescription gameDescriptions[] = {
// Xmas Card 1986 (PC) [AGI 2.272]
GAME("xmascard", "1986-11-13 [version 1]", "3067b8d5957e2861e069c3c0011bd43d", 0x2272, GID_XMASCARD),
+ // Xmas Card 1986 (CoCo3 360k) [AGI 2.072]
+ GAME_PS("xmascard", "", "25ad35e9628fc77e5e0dd35852a272b6", 768, 0x2440, GID_XMASCARD, Common::kPlatformCoCo3),
+
FANMADE_F("2 Player Demo", "4279f46b3cebd855132496476b1d2cca", GF_AGIMOUSE),
FANMADE("AGI Contest 1 Template", "d879aed25da6fc655564b29567358ae2"),
FANMADE("AGI Contest 2 Template", "5a2fb2894207eff36c72f5c1b08bcc07"),
@@ -630,6 +705,7 @@ static const AGIGameDescription gameDescriptions[] = {
FANMADE("Elfintard", "c3b847e9e9e978af9708df76a0751dc2"),
FANMADE("Enclosure (v1.01)", "f08e66fee9ecdde77db7ee9a10c96ba2"),
FANMADE("Enclosure (v1.03)", "e4a0613ed02401502e506ba3565a8c40"),
+ FANMADE_SVP("Enclosure", "fe98e6126db74c6cc6fd8fe395cc6e8c", 345, 0x2440, Common::kPlatformCoCo3),
FANMADE("Epic Fighting (v0.1)", "aff24a1b3bdd676187685c4d95ba4294"),
FANMADE("Escape Quest (v0.0.3)", "2346b65619b1da0298b715b06d1a45a1"),
FANMADE("Escape from the Desert (beta 1)", "dfdc634d340854bd6ece28024010758d"),
@@ -777,8 +853,10 @@ static const AGIGameDescription gameDescriptions[] = {
FANMADE("Sorceror's Appraisal", "fe62615557b3cb7b08dd60c9d35efef1"),
FANMADE_I("sq0", "v1.03", "d2fd6f7404e86182458494e64375e590"),
FANMADE_I("sq0", "v1.04", "2ad9d1a4624a98571ee77dcc83f231b6"),
+ FANMADE_ISVP("sq0", "", "e1a8e4efcce86e1efcaa14633b9eb986", 762, 0x2440, Common::kPlatformCoCo3),
FANMADE_I("sqx", "v10.0 Feb 05", "c992ae2f8ab18360404efdf16fa9edd1"),
FANMADE_I("sqx", "v10.0 Jul 18", "812edec45cefad559d190ffde2f9c910"),
+ FANMADE_ISVP("sqx", "", "f0a59044475a5fa37c055d8c3eb4d1a7", 768, 0x2440, Common::kPlatformCoCo3),
FANMADE_F("Space Quest 3.5", "c077bc28d7b36213dd99dc9ecb0147fc", GF_AGIMOUSE|GF_AGIPAL),
FANMADE_F("Space Trek (v1.0)", "807a1aeadb2ace6968831d36ab5ea37a", GF_CLIPCOORDS),
FANMADE("Special Delivery", "88764dfe61126b8e73612c851b510a33"),
@@ -805,6 +883,7 @@ static const AGIGameDescription gameDescriptions[] = {
FANMADE("The Shadow Plan", "c02cd10267e721f4e836b1431f504a0a"),
FANMADE("Time Quest (Demo v0.1)", "12e1a6f03ea4b8c5531acd0400b4ed8d"),
FANMADE("Time Quest (Demo v0.2)", "7b710608abc99e0861ac59b967bf3f6d"),
+ FANMADE_SVP("Time Quest", "90314f473d8317be5cd1f0306f139aea", 300, 0x2440, Common::kPlatformCoCo3),
FANMADE("Tonight The Shrieking Corpses Bleed (Demo v0.11)", "bcc57a7c8d563fa0c333107ae1c0a6e6"),
FANMADE("Tonight The Shrieking Corpses Bleed (v1.01)", "36b38f621b38e8d104aa0807302dc8c9"),
FANMADE("Turks' Quest - Heir to the Planet", "3d19254b737c8b218e5bc4580542b79a"),
@@ -826,6 +905,7 @@ static const AGIGameDescription gameDescriptions[] = {
GF_FANMADE,
0x3149,
},
+ FANMADE_SVP("V - The Graphical Adventure", "1646eaade74f137a9041eb427a389969", 768, 0x2440, Common::kPlatformCoCo3),
FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Jan 1)", "ae95f0c77d9a97b61420fd192348b937"),
FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Mar 29)", "11d0417b7b886f963d0b36789dac4c8f"),
diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp
index a620788de2..97255097bc 100644
--- a/engines/agi/op_cmd.cpp
+++ b/engines/agi/op_cmd.cpp
@@ -1520,7 +1520,8 @@ cmd(print_at_v) {
}
cmd(push_script) {
- if (g_agi->getFeatures() & GF_AGIMOUSE) {
+ // We run AGIMOUSE always as a side effect
+ if (g_agi->getFeatures() & GF_AGIMOUSE || 1) {
game.vars[27] = g_mouse.button;
game.vars[28] = g_mouse.x / 2;
game.vars[29] = g_mouse.y;
diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp
index b0856f6ddf..fb73c6b71f 100644
--- a/engines/agi/sound.cpp
+++ b/engines/agi/sound.cpp
@@ -367,7 +367,7 @@ void SoundMgr::startSound(int resnum, int flag) {
_vm->_game.sounds[resnum]->play();
_playingSound = resnum;
- debugC(3, kDebugLevelSound, "startSound(resnum = %d, flag = %d)", resnum, flag);
+ debugC(3, kDebugLevelSound, "startSound(resnum = %d, flag = %d) type = %d", resnum, flag, type);
switch (type) {
case AGI_SOUND_SAMPLE: {
@@ -411,6 +411,8 @@ void SoundMgr::startSound(int resnum, int flag) {
void SoundMgr::stopSound() {
int i;
+ debugC(3, kDebugLevelSound, "stopSound() --> %d", _playingSound);
+
_endflag = -1;
if (_vm->_soundemu != SOUND_EMU_APPLE2GS) {
for (i = 0; i < NUM_CHANNELS; i++)
@@ -418,7 +420,8 @@ void SoundMgr::stopSound() {
}
if (_playingSound != -1) {
- _vm->_game.sounds[_playingSound]->stop();
+ if (_vm->_game.sounds[_playingSound]) // sanity checking
+ _vm->_game.sounds[_playingSound]->stop();
if (_vm->_soundemu == SOUND_EMU_APPLE2GS) {
_gsSound.stopSounds();
@@ -474,6 +477,8 @@ int SoundMgr::initSound() {
case SOUND_EMU_APPLE2GS:
_disabledMidi = !loadInstruments();
break;
+ case SOUND_EMU_COCO3:
+ break;
}
report("Initializing sound:\n");
@@ -819,6 +824,35 @@ void SoundMgr::playSampleSound() {
_playing = _gsSound.activeSounds() > 0;
}
+static int cocoFrequencies[] = {
+ 130, 138, 146, 155, 164, 174, 184, 195, 207, 220, 233, 246,
+ 261, 277, 293, 311, 329, 349, 369, 391, 415, 440, 466, 493,
+ 523, 554, 587, 622, 659, 698, 739, 783, 830, 880, 932, 987,
+ 1046, 1108, 1174, 1244, 1318, 1396, 1479, 1567, 1661, 1760, 1864, 1975,
+ 2093, 2217, 2349, 2489, 2637, 2793, 2959, 3135, 3322, 3520, 3729, 3951
+};
+
+void SoundMgr::playCoCoSound() {
+ int i = 0;
+ CoCoNote note;
+
+ do {
+ note.read(_chn[i].ptr);
+
+ if (note.freq != 0xff) {
+ playNote(0, cocoFrequencies[note.freq], note.volume);
+
+ uint32 start_time = _vm->_system->getMillis();
+
+ while (_vm->_system->getMillis() < start_time + note.duration) {
+ _vm->_system->updateScreen();
+
+ _vm->_system->delayMillis(10);
+ }
+ }
+ } while (note.freq != 0xff);
+}
+
void SoundMgr::playAgiSound() {
int i;
AgiNote note;
@@ -875,6 +909,8 @@ void SoundMgr::playSound() {
playSampleSound();
}
}
+ } else if (_vm->_soundemu == SOUND_EMU_COCO3) {
+ playCoCoSound();
} else {
//debugC(3, kDebugLevelSound, "playSound: Trying to play a PCjr 4-channel sound");
playAgiSound();
diff --git a/engines/agi/sound.h b/engines/agi/sound.h
index fd178e3a1d..a24a665b2a 100644
--- a/engines/agi/sound.h
+++ b/engines/agi/sound.h
@@ -51,6 +51,7 @@ namespace Agi {
#define SOUND_EMU_MAC 3
#define SOUND_EMU_AMIGA 4
#define SOUND_EMU_APPLE2GS 5
+#define SOUND_EMU_COCO3 6
#define WAVEFORM_SIZE 64
#define ENV_ATTACK 10000 /**< envelope attack rate */
@@ -228,27 +229,42 @@ struct IIgsChannelInfo {
bool playing(); ///< Is there a note playing on this channel?
};
- /**
- * AGI sound resource types.
- * It's probably coincidence that all the values here are powers of two
- * as they're simply the different used values in AGI sound resources'
- * starts (The first 16-bit little endian word, to be precise).
- */
- enum AgiSoundType {
- AGI_SOUND_SAMPLE = 0x0001,
- AGI_SOUND_MIDI = 0x0002,
- AGI_SOUND_4CHN = 0x0008
- };
- enum AgiSoundFlags {
- AGI_SOUND_LOOP = 0x0001,
- AGI_SOUND_ENVELOPE = 0x0002
- };
- enum AgiSoundEnv {
- AGI_SOUND_ENV_ATTACK = 3,
- AGI_SOUND_ENV_DECAY = 2,
- AGI_SOUND_ENV_SUSTAIN = 1,
- AGI_SOUND_ENV_RELEASE = 0
- };
+struct CoCoNote {
+ uint8 freq;
+ uint8 volume;
+ uint16 duration; ///< Note duration
+
+ /** Reads a CoCoNote through the given pointer. */
+ void read(const uint8 *ptr) {
+ freq = *ptr;
+ volume = *(ptr + 1);
+ duration = READ_LE_UINT16(ptr + 2);
+ }
+};
+
+/**
+ * AGI sound resource types.
+ * It's probably coincidence that all the values here are powers of two
+ * as they're simply the different used values in AGI sound resources'
+ * starts (The first 16-bit little endian word, to be precise).
+ */
+enum AgiSoundType {
+ AGI_SOUND_SAMPLE = 0x0001,
+ AGI_SOUND_MIDI = 0x0002,
+ AGI_SOUND_4CHN = 0x0008
+};
+enum AgiSoundFlags {
+ AGI_SOUND_LOOP = 0x0001,
+ AGI_SOUND_ENVELOPE = 0x0002
+};
+enum AgiSoundEnv {
+ AGI_SOUND_ENV_ATTACK = 3,
+ AGI_SOUND_ENV_DECAY = 2,
+ AGI_SOUND_ENV_SUSTAIN = 1,
+ AGI_SOUND_ENV_RELEASE = 0
+};
+
+
/**
* AGI engine sound channel structure.
*/
@@ -485,6 +501,7 @@ public:
void stopNote(int i);
void playNote(int i, int freq, int vol);
void playAgiSound();
+ void playCoCoSound();
uint32 mixSound();
bool loadInstruments();
void playMidiSound();
diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp
index 3be552a083..36399a7b2f 100644
--- a/engines/agos/animation.cpp
+++ b/engines/agos/animation.cpp
@@ -367,12 +367,7 @@ bool MoviePlayerDXA::processFrame() {
copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth);
_vm->_system->unlockScreen();
- if ((_bgSoundStream == NULL) || ((int)(_mixer->getSoundElapsedTime(_bgSound) * getFrameRate()) / 1000 < getCurFrame() + 1) ||
- _frameSkipped > getFrameRate()) {
- if (_frameSkipped > getFrameRate()) {
- warning("force frame %i redraw", getCurFrame());
- _frameSkipped = 0;
- }
+ if ((_bgSoundStream == NULL) || ((int)(_mixer->getSoundElapsedTime(_bgSound) * getFrameRate()) / 1000 < getCurFrame() + 1)) {
if (_bgSoundStream && _mixer->isSoundHandleActive(_bgSound)) {
while (_mixer->isSoundHandleActive(_bgSound) && (_mixer->getSoundElapsedTime(_bgSound) * getFrameRate()) / 1000 < (uint32)getCurFrame()) {
@@ -392,7 +387,6 @@ bool MoviePlayerDXA::processFrame() {
}
warning("dropped frame %i", getCurFrame());
- _frameSkipped++;
return false;
}
diff --git a/engines/agos/animation.h b/engines/agos/animation.h
index 9cd6913f08..4ebcb3d4b3 100644
--- a/engines/agos/animation.h
+++ b/engines/agos/animation.h
@@ -52,7 +52,6 @@ class MoviePlayer {
bool _rightButtonDown;
bool _skipMovie;
uint32 _ticks;
- uint16 _frameSkipped;
char baseName[40];
public:
diff --git a/engines/agos/charset-fontdata.cpp b/engines/agos/charset-fontdata.cpp
index 910c5cd5a6..d23e772306 100644
--- a/engines/agos/charset-fontdata.cpp
+++ b/engines/agos/charset-fontdata.cpp
@@ -2105,9 +2105,9 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) {
w = getFeebleFontSize(chr);
if (_language == Common::PL_POL)
- src = feeble_windowFont + (chr - 32) * 13;
- else
src = polish_feeble_windowFont + (chr - 32) * 13;
+ else
+ src = feeble_windowFont + (chr - 32) * 13;
} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
dst = (byte *)screen->pixels + y * _dxSurfacePitch + x + window->textColumnOffset;
h = 8;
diff --git a/engines/cine/bg.cpp b/engines/cine/bg.cpp
index cc7e843c2b..08722c42e5 100644
--- a/engines/cine/bg.cpp
+++ b/engines/cine/bg.cpp
@@ -82,7 +82,6 @@ byte loadCtOS(const char *ctName) {
ptr += 2;
if (bpp == 8) {
- memcpy(collisionPage, ptr + 256 * 3, 320 * 200);
renderer->loadCt256(ptr, ctName);
} else {
gfxConvertSpriteToRaw(collisionPage, ptr + 32, 160, 200);
diff --git a/engines/cine/cine.h b/engines/cine/cine.h
index bf56e9189b..1031d6d449 100644
--- a/engines/cine/cine.h
+++ b/engines/cine/cine.h
@@ -127,11 +127,15 @@ extern CineEngine *g_cine;
#define COPY_PROT_FAIL_PRC_NAME "L201.ANI"
enum {
- VAR_MOUSE_X_MODE = 253,
+ // Both FW and OS
VAR_MOUSE_X_POS = 249,
- VAR_MOUSE_Y_MODE = 251,
VAR_MOUSE_Y_POS = 250,
+ // FW only
+ VAR_MOUSE_X_MODE = 253,
+ VAR_MOUSE_Y_MODE = 251,
// OS only
+ VAR_MOUSE_X_POS_2ND = 251, // Many times used in conjunction with VAR_MOUSE_X_POS
+ VAR_MOUSE_Y_POS_2ND = 252, // Many times used in conjunction with VAR_MOUSE_Y_POS
VAR_BYPASS_PROTECTION = 255,
VAR_LOW_MEMORY = 0
};
diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp
index d388a9e206..ddc2d48152 100644
--- a/engines/cine/gfx.cpp
+++ b/engines/cine/gfx.cpp
@@ -90,9 +90,9 @@ static const byte cursorPalette[] = {
/*! \brief Initialize renderer
*/
-FWRenderer::FWRenderer() : _background(NULL), _palette(NULL), _cmd(""),
+FWRenderer::FWRenderer() : _background(NULL), _backupPal(), _cmd(""),
_cmdY(0), _messageBg(0), _backBuffer(new byte[_screenSize]),
- _activeLowPal(NULL), _changePal(0), _showCollisionPage(false) {
+ _activePal(), _changePal(0), _showCollisionPage(false) {
assert(_backBuffer);
@@ -104,21 +104,17 @@ FWRenderer::FWRenderer() : _background(NULL), _palette(NULL), _cmd(""),
*/
FWRenderer::~FWRenderer() {
delete[] _background;
- delete[] _palette;
delete[] _backBuffer;
- delete[] _activeLowPal;
}
/* \brief Reset renderer state
*/
void FWRenderer::clear() {
delete[] _background;
- delete[] _palette;
- delete[] _activeLowPal;
_background = NULL;
- _palette = NULL;
- _activeLowPal = NULL;
+ _backupPal.clear();
+ _activePal.clear();
memset(_backBuffer, 0, _screenSize);
@@ -550,59 +546,39 @@ void FWRenderer::setCommand(Common::String cmd) {
/*! \brief Refresh current palette
*/
void FWRenderer::refreshPalette() {
- int i;
- byte pal[16*4];
-
- assert(_activeLowPal);
-
- for (i = 0; i < 16; i++) {
- pal[i * 4 + 2] = ((_activeLowPal[i] & 0x007) >> 0) * 32;
- pal[i * 4 + 1] = ((_activeLowPal[i] & 0x070) >> 4) * 32;
- pal[i * 4 + 0] = ((_activeLowPal[i] & 0x700) >> 8) * 32;
- pal[i * 4 + 3] = 0;
- }
-
- g_system->setPalette(pal, 0, 16);
+ assert(_activePal.isValid() && !_activePal.empty());
+ _activePal.setGlobalOSystemPalette();
_changePal = 0;
}
/*! \brief Load palette of current background
*/
void FWRenderer::reloadPalette() {
- assert(_palette);
-
- if (!_activeLowPal) {
- _activeLowPal = new uint16[_lowPalSize];
- }
-
- assert(_activeLowPal);
-
- memcpy(_activeLowPal, _palette, _lowPalSize * sizeof (uint16));
+ assert(_backupPal.isValid() && !_backupPal.empty());
+ _activePal = _backupPal;
_changePal = 1;
}
/*! \brief Load background into renderer
* \param bg Raw background data
+ * \todo Combine with OSRenderer's version of loadBg16
*/
void FWRenderer::loadBg16(const byte *bg, const char *name, unsigned int idx) {
assert(idx == 0);
- int i;
if (!_background) {
_background = new byte[_screenSize];
}
- if (!_palette) {
- _palette = new uint16[_lowPalSize];
- }
-
- assert(_background && _palette);
+ assert(_background);
strcpy(_bgName, name);
- for (i = 0; i < _lowPalSize; i++, bg += 2) {
- _palette[i] = READ_BE_UINT16(bg);
- }
+ // Load the 16 color palette
+ _backupPal.load(bg, kLowPalNumBytes, kLowPalFormat, kLowPalNumColors, CINE_BIG_ENDIAN);
+
+ // Jump over the palette data to the background data
+ bg += kLowPalNumBytes;
gfxConvertSpriteToRaw(_background, bg, 160, 200);
}
@@ -668,25 +644,15 @@ const char *FWRenderer::getBgName(uint idx) const {
* \param fHandle Savefile open for reading
*/
void FWRenderer::restorePalette(Common::SeekableReadStream &fHandle) {
- int i;
-
- if (!_palette) {
- _palette = new uint16[_lowPalSize];
- }
-
- if (!_activeLowPal) {
- _activeLowPal = new uint16[_lowPalSize];
- }
-
- assert(_palette && _activeLowPal);
+ byte buf[kLowPalNumBytes];
- for (i = 0; i < _lowPalSize; i++) {
- _activeLowPal[i] = fHandle.readUint16BE();
- }
+ // Load the active 16 color palette from file
+ fHandle.read(buf, kLowPalNumBytes);
+ _activePal.load(buf, sizeof(buf), kLowPalFormat, kLowPalNumColors, CINE_BIG_ENDIAN);
- for (i = 0; i < _lowPalSize; i++) {
- _palette[i] = fHandle.readUint16BE();
- }
+ // Load the backup 16 color palette from file
+ fHandle.read(buf, kLowPalNumBytes);
+ _backupPal.load(buf, sizeof(buf), kLowPalFormat, kLowPalNumColors, CINE_BIG_ENDIAN);
_changePal = 1;
}
@@ -695,58 +661,59 @@ void FWRenderer::restorePalette(Common::SeekableReadStream &fHandle) {
* \param fHandle Savefile open for writing
*/
void FWRenderer::savePalette(Common::OutSaveFile &fHandle) {
- int i;
+ byte buf[kLowPalNumBytes];
- assert(_palette && _activeLowPal);
+ // Make sure the active palette has the correct format and color count
+ assert(_activePal.colorFormat() == kLowPalFormat);
+ assert(_activePal.colorCount() == kLowPalNumColors);
- for (i = 0; i < _lowPalSize; i++) {
- fHandle.writeUint16BE(_activeLowPal[i]);
- }
+ // Make sure the backup palette has the correct format and color count
+ assert(_backupPal.colorFormat() == kLowPalFormat);
+ assert(_backupPal.colorCount() == kLowPalNumColors);
- for (i = 0; i < _lowPalSize; i++) {
- fHandle.writeUint16BE(_palette[i]);
- }
+ // Write the active palette to the file
+ _activePal.save(buf, sizeof(buf), CINE_BIG_ENDIAN);
+ fHandle.write(buf, kLowPalNumBytes);
+
+ // Write the backup palette to the file
+ _backupPal.save(buf, sizeof(buf), CINE_BIG_ENDIAN);
+ fHandle.write(buf, kLowPalNumBytes);
}
/*! \brief Write active and backup palette to save
* \param fHandle Savefile open for writing
+ * \todo Add support for saving the palette in the 16 color version of Operation Stealth.
+ * Possibly combine with FWRenderer's savePalette-method?
*/
void OSRenderer::savePalette(Common::OutSaveFile &fHandle) {
- int i;
+ byte buf[kHighPalNumBytes];
- assert(_activeHiPal);
+ // Make sure the active palette has the correct format and color count
+ assert(_activePal.colorFormat() == kHighPalFormat);
+ assert(_activePal.colorCount() == kHighPalNumColors);
// Write the active 256 color palette.
- for (i = 0; i < _hiPalSize; i++) {
- fHandle.writeByte(_activeHiPal[i]);
- }
+ _activePal.save(buf, sizeof(buf), CINE_LITTLE_ENDIAN);
+ fHandle.write(buf, kHighPalNumBytes);
// Write the active 256 color palette a second time.
// FIXME: The backup 256 color palette should be saved here instead of the active one.
- for (i = 0; i < _hiPalSize; i++) {
- fHandle.writeByte(_activeHiPal[i]);
- }
+ fHandle.write(buf, kHighPalNumBytes);
}
/*! \brief Restore active and backup palette from save
* \param fHandle Savefile open for reading
*/
void OSRenderer::restorePalette(Common::SeekableReadStream &fHandle) {
- int i;
-
- if (!_activeHiPal) {
- _activeHiPal = new byte[_hiPalSize];
- }
+ byte buf[kHighPalNumBytes];
- assert(_activeHiPal);
-
- for (i = 0; i < _hiPalSize; i++) {
- _activeHiPal[i] = fHandle.readByte();
- }
+ // Load the active 256 color palette from file
+ fHandle.read(buf, kHighPalNumBytes);
+ _activePal.load(buf, sizeof(buf), kHighPalFormat, kHighPalNumColors, CINE_LITTLE_ENDIAN);
// Jump over the backup 256 color palette.
// FIXME: Load the backup 256 color palette and use it properly.
- fHandle.seek(_hiPalSize, SEEK_CUR);
+ fHandle.seek(kHighPalNumBytes, SEEK_CUR);
_changePal = 1;
}
@@ -754,10 +721,10 @@ void OSRenderer::restorePalette(Common::SeekableReadStream &fHandle) {
/*! \brief Rotate active palette
* \param a First color to rotate
* \param b Last color to rotate
- * \param c Possibly rotation step, must be equal to 1 at the moment
+ * \param c Possibly rotation step, must be 0 or 1 at the moment
*/
void FWRenderer::rotatePalette(int a, int b, int c) {
- palRotate(_activeLowPal, a, b, c);
+ _activePal.rotateRight(a, b, c);
refreshPalette();
}
@@ -769,12 +736,11 @@ void FWRenderer::rotatePalette(int a, int b, int c) {
* \param b Blue channel transformation
*/
void FWRenderer::transformPalette(int first, int last, int r, int g, int b) {
- if (!_activeLowPal) {
- _activeLowPal = new uint16[_lowPalSize];
- memset(_activeLowPal, 0, _lowPalSize * sizeof (uint16));
+ if (!_activePal.isValid() || _activePal.empty()) {
+ _activePal = Cine::Palette(kLowPalFormat, kLowPalNumColors);
}
- transformPaletteRange(_activeLowPal, _palette, first, last, r, g, b);
+ _backupPal.saturatedAddColor(_activePal, first, last, r, g, b);
refreshPalette();
}
@@ -889,22 +855,16 @@ void FWRenderer::drawInputBox(const char *info, const char *input, int cursor, i
}
/*! \brief Fade to black
+ * \bug Operation Stealth sometimes seems to fade to black using
+ * transformPalette resulting in double fadeout
*/
void FWRenderer::fadeToBlack() {
- // FIXME: _activeLowPal is invalid when starting Operation Stealth
- // Adding this sanity check fixes a crash when the game
- // starts, but I'm not sure if this is the best place to check it
- if (!_activeLowPal) {
- warning("_activeLowPal is invalid");
- return;
- }
-
- assert(_activeLowPal);
+ assert(_activePal.isValid() && !_activePal.empty());
for (int i = 0; i < 8; i++) {
- for (int j = 0; j < 16; j++) {
- _activeLowPal[j] = transformColor(_activeLowPal[j], -1, -1, -1);
- }
+ // Fade out the whole palette by 1/7th
+ // (Operation Stealth used 36 / 252, which is 1 / 7. Future Wars used 1 / 7 directly).
+ _activePal.saturatedAddNormalizedGray(_activePal, 0, _activePal.colorCount() - 1, -1, 7);
refreshPalette();
g_system->updateScreen();
@@ -914,45 +874,25 @@ void FWRenderer::fadeToBlack() {
/*! \brief Initialize Operation Stealth renderer
*/
-OSRenderer::OSRenderer() : _activeHiPal(NULL), _currentBg(0), _scrollBg(0),
+OSRenderer::OSRenderer() : FWRenderer(), _bgTable(), _currentBg(0), _scrollBg(0),
_bgShift(0) {
- int i;
- for (i = 0; i < 9; i++) {
- _bgTable[i].bg = NULL;
- _bgTable[i].lowPal = NULL;
- _bgTable[i].hiPal = NULL;
- memset(_bgTable[i].name, 0, sizeof (_bgTable[i].name));
- }
+ _bgTable.resize(9); // Resize the background table to its required size
}
/*! \brief Destroy Operation Stealth renderer
*/
OSRenderer::~OSRenderer() {
- delete[] _activeHiPal;
-
- for (int i = 0; i < 9; i++) {
- delete[] _bgTable[i].bg;
- delete[] _bgTable[i].lowPal;
- delete[] _bgTable[i].hiPal;
+ for (uint i = 0; i < _bgTable.size(); i++) {
+ _bgTable[i].clear();
}
}
/*! \brief Reset Operation Stealth renderer state
*/
void OSRenderer::clear() {
- delete[] _activeHiPal;
- _activeHiPal = NULL;
-
- for (int i = 0; i < 9; i++) {
- delete[] _bgTable[i].bg;
- delete[] _bgTable[i].lowPal;
- delete[] _bgTable[i].hiPal;
-
- _bgTable[i].bg = NULL;
- _bgTable[i].lowPal = NULL;
- _bgTable[i].hiPal = NULL;
- memset(_bgTable[i].name, 0, sizeof (_bgTable[i].name));
+ for (uint i = 0; i < _bgTable.size(); i++) {
+ _bgTable[i].clear();
}
_currentBg = 0;
@@ -1159,28 +1099,6 @@ void OSRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
}
}
-/*! \brief Refresh current palette
- */
-void OSRenderer::refreshPalette() {
- if (!_activeHiPal) {
- FWRenderer::refreshPalette();
- return;
- }
-
- int i;
- byte pal[256*4];
-
- for (i = 0; i < 256; i++) {
- pal[i * 4 + 0] = _activeHiPal[i * 3 + 0];
- pal[i * 4 + 1] = _activeHiPal[i * 3 + 1];
- pal[i * 4 + 2] = _activeHiPal[i * 3 + 2];
- pal[i * 4 + 3] = 0;
- }
-
- g_system->setPalette(pal, 0, 256);
- _changePal = 0;
-}
-
/*! \brief Load palette of current background
*/
void OSRenderer::reloadPalette() {
@@ -1188,49 +1106,12 @@ void OSRenderer::reloadPalette() {
// and 14, shift background has it right
palBg *bg = _bgShift ? &_bgTable[_scrollBg] : &_bgTable[_currentBg];
- assert(bg->lowPal || bg->hiPal);
-
- if (bg->lowPal) {
- if (!_activeLowPal) {
- _activeLowPal = new uint16[_lowPalSize];
- }
+ assert(bg->pal.isValid() && !(bg->pal.empty()));
- assert(_activeLowPal);
-
- delete[] _activeHiPal;
- _activeHiPal = NULL;
-
- memcpy(_activeLowPal, bg->lowPal, _lowPalSize * sizeof (uint16));
- } else {
- if (!_activeHiPal) {
- _activeHiPal = new byte[_hiPalSize];
- }
-
- assert(_activeHiPal);
-
- delete[] _activeLowPal;
- _activeLowPal = NULL;
-
- memcpy(_activeHiPal, bg->hiPal, _hiPalSize);
- }
+ _activePal = bg->pal;
_changePal = 1;
}
-/*! \brief Rotate active palette
- * \param a First color to rotate
- * \param b Last color to rotate
- * \param c Possibly rotation step, must be equal to 1 at the moment
- */
-void OSRenderer::rotatePalette(int a, int b, int c) {
- if (_activeLowPal) {
- FWRenderer::rotatePalette(a, b, c);
- return;
- }
-
- palRotate(_activeHiPal, a, b, c);
- refreshPalette();
-}
-
/*! \brief Copy part of backup palette to active palette and transform
* \param first First color to transform
* \param last Last color to transform
@@ -1241,28 +1122,12 @@ void OSRenderer::rotatePalette(int a, int b, int c) {
void OSRenderer::transformPalette(int first, int last, int r, int g, int b) {
palBg *bg = _bgShift ? &_bgTable[_scrollBg] : &_bgTable[_currentBg];
- if (!bg->lowPal) {
- if (!_activeHiPal) {
- _activeHiPal = new byte[_hiPalSize];
- memset(_activeHiPal, 0, _hiPalSize);
- }
-
- delete[] _activeLowPal;
- _activeLowPal = NULL;
-
- transformPaletteRange(_activeHiPal, bg->hiPal, first, last, r, g, b);
- } else {
- if (!_activeLowPal) {
- _activeLowPal = new uint16[_lowPalSize];
- memset(_activeLowPal, 0, _lowPalSize * sizeof (uint16));
- }
-
- delete[] _activeHiPal;
- _activeHiPal = NULL;
-
- transformPaletteRange(_activeLowPal, bg->lowPal, first, last, r, g, b);
+ // Initialize active palette to current background's palette format and size if they differ
+ if (_activePal.colorFormat() != bg->pal.colorFormat() || _activePal.colorCount() != bg->pal.colorCount()) {
+ _activePal = Cine::Palette(bg->pal.colorFormat(), bg->pal.colorCount());
}
+ bg->pal.saturatedAddColor(_activePal, first, last, r, g, b, kLowPalFormat);
refreshPalette();
}
@@ -1270,29 +1135,24 @@ void OSRenderer::transformPalette(int first, int last, int r, int g, int b) {
* \param bg Raw background data
* \param name Background filename
* \param pos Background index
+ * \todo Combine with FWRenderer's version of loadBg16
*/
void OSRenderer::loadBg16(const byte *bg, const char *name, unsigned int idx) {
- int i;
assert(idx < 9);
if (!_bgTable[idx].bg) {
_bgTable[idx].bg = new byte[_screenSize];
}
- if (!_bgTable[idx].lowPal) {
- _bgTable[idx].lowPal = new uint16[_lowPalSize];
- }
-
- assert(_bgTable[idx].bg && _bgTable[idx].lowPal);
-
- delete[] _bgTable[idx].hiPal;
- _bgTable[idx].hiPal = NULL;
+ assert(_bgTable[idx].bg);
strcpy(_bgTable[idx].name, name);
- for (i = 0; i < _lowPalSize; i++, bg += 2) {
- _bgTable[idx].lowPal[i] = READ_BE_UINT16(bg);
- }
+ // Load the 16 color palette
+ _bgTable[idx].pal.load(bg, kLowPalNumBytes, kLowPalFormat, kLowPalNumColors, CINE_BIG_ENDIAN);
+
+ // Jump over the palette data to the background data
+ bg += kLowPalNumBytes;
gfxConvertSpriteToRaw(_bgTable[idx].bg, bg, 160, 200);
}
@@ -1302,7 +1162,10 @@ void OSRenderer::loadBg16(const byte *bg, const char *name, unsigned int idx) {
* \param name Background filename
*/
void OSRenderer::loadCt16(const byte *ct, const char *name) {
- loadBg16(ct, name, 8);
+ // Make the 9th background point directly to the collision page
+ // and load the picture into it.
+ _bgTable[kCollisionPageBgIdxAlias].bg = collisionPage;
+ loadBg16(ct, name, kCollisionPageBgIdxAlias);
}
/*! \brief Load 256 color background into renderer
@@ -1317,18 +1180,11 @@ void OSRenderer::loadBg256(const byte *bg, const char *name, unsigned int idx) {
_bgTable[idx].bg = new byte[_screenSize];
}
- if (!_bgTable[idx].hiPal) {
- _bgTable[idx].hiPal = new byte[_hiPalSize];
- }
-
- assert(_bgTable[idx].bg && _bgTable[idx].hiPal);
-
- delete[] _bgTable[idx].lowPal;
- _bgTable[idx].lowPal = NULL;
+ assert(_bgTable[idx].bg);
strcpy(_bgTable[idx].name, name);
- memcpy(_bgTable[idx].hiPal, bg, _hiPalSize);
- memcpy(_bgTable[idx].bg, bg + _hiPalSize, _screenSize);
+ _bgTable[idx].pal.load(bg, kHighPalNumBytes, kHighPalFormat, kHighPalNumColors, CINE_LITTLE_ENDIAN);
+ memcpy(_bgTable[idx].bg, bg + kHighPalNumBytes, _screenSize);
}
/*! \brief Load 256 color CT data as background into renderer
@@ -1336,7 +1192,10 @@ void OSRenderer::loadBg256(const byte *bg, const char *name, unsigned int idx) {
* \param name Background filename
*/
void OSRenderer::loadCt256(const byte *ct, const char *name) {
- loadBg256(ct, name, 8);
+ // Make the 9th background point directly to the collision page
+ // and load the picture into it.
+ _bgTable[kCollisionPageBgIdxAlias].bg = collisionPage;
+ loadBg256(ct, name, kCollisionPageBgIdxAlias);
}
/*! \brief Select active background and load its palette
@@ -1344,7 +1203,7 @@ void OSRenderer::loadCt256(const byte *ct, const char *name) {
*/
void OSRenderer::selectBg(unsigned int idx) {
assert(idx < 9 && _bgTable[idx].bg);
- assert(_bgTable[idx].lowPal || _bgTable[idx].hiPal);
+ assert(_bgTable[idx].pal.isValid() && !(_bgTable[idx].pal.empty()));
_currentBg = idx;
reloadPalette();
@@ -1392,13 +1251,7 @@ void OSRenderer::removeBg(unsigned int idx) {
_scrollBg = 0;
}
- delete[] _bgTable[idx].bg;
- delete[] _bgTable[idx].lowPal;
- delete[] _bgTable[idx].hiPal;
- _bgTable[idx].bg = NULL;
- _bgTable[idx].lowPal = NULL;
- _bgTable[idx].hiPal = NULL;
- memset(_bgTable[idx].name, 0, sizeof (_bgTable[idx].name));
+ _bgTable[idx].clear();
}
void OSRenderer::saveBgNames(Common::OutSaveFile &fHandle) {
@@ -1412,27 +1265,6 @@ const char *OSRenderer::getBgName(uint idx) const {
return _bgTable[idx].name;
}
-/*! \brief Fade to black
- * \bug Operation Stealth sometimes seems to fade to black using
- * transformPalette resulting in double fadeout
- */
-void OSRenderer::fadeToBlack() {
- if (!_activeHiPal) {
- FWRenderer::fadeToBlack();
- return;
- }
-
- for (int i = 0; i < 8; i++) {
- for (int j = 0; j < _hiPalSize; j++) {
- _activeHiPal[j] = CLIP(_activeHiPal[j] - 32, 0, 255);
- }
-
- refreshPalette();
- g_system->updateScreen();
- g_system->delayMillis(50);
- }
-}
-
void setMouseCursor(int cursor) {
static int currentMouseCursor = -1;
assert(cursor >= 0 && cursor < 3);
diff --git a/engines/cine/gfx.h b/engines/cine/gfx.h
index 0ed1626ab0..f1503a4c46 100644
--- a/engines/cine/gfx.h
+++ b/engines/cine/gfx.h
@@ -31,13 +31,34 @@
namespace Cine {
+extern byte *collisionPage;
+static const int kCollisionPageBgIdxAlias = 8;
+
/*! \brief Background with palette
*/
struct palBg {
byte *bg; ///< Background data
- byte *hiPal; ///< 256 color palette
- uint16 *lowPal; ///< 16 color palette
+ Cine::Palette pal; ///< Background color palette
char name[15]; ///< Background filename
+
+ /** @brief Default constructor. */
+ palBg() : bg(NULL), pal(), name() {
+ // Make sure the name is empty (Maybe this is not needed?)
+ memset(this->name, 0, sizeof(this->name));
+ }
+
+ /** @brief Clears the struct (Releases allocated memory etc). */
+ void clear() {
+ // In Operation Stealth the 9th background is sometimes aliased to
+ // the collision page so we should take care not to double delete it
+ // (The collision page is deleted elsewhere).
+ if (this->bg != collisionPage) {
+ delete[] this->bg;
+ }
+ this->bg = NULL;
+ this->pal.clear();
+ memset(this->name, 0, sizeof(this->name));
+ }
};
/*! \brief Future Wars renderer
@@ -46,10 +67,10 @@ struct palBg {
* without calling drawFrame() all the time
*/
class FWRenderer : public Common::NonCopyable {
+protected:
private:
byte *_background; ///< Current background
char _bgName[13]; ///< Background filename
- uint16 *_palette; ///< 16 color backup palette
Common::String _cmd; ///< Player command string
@@ -57,10 +78,10 @@ protected:
static const int _screenSize = 320 * 200; ///< Screen size
static const int _screenWidth = 320; ///< Screen width
static const int _screenHeight = 200; ///< Screen height
- static const int _lowPalSize = 16; ///< 16 color palette size
byte *_backBuffer; ///< Screen backbuffer
- uint16 *_activeLowPal; ///< Active 16 color palette
+ Cine::Palette _backupPal; ///< The backup color palette
+ Cine::Palette _activePal; ///< The active color palette
int _changePal; ///< Load active palette to video backend on next frame
bool _showCollisionPage; ///< Should we show the collision page instead of the back buffer? Used for debugging.
@@ -130,15 +151,12 @@ public:
*/
class OSRenderer : public FWRenderer {
private:
- // FIXME: Background table's size is probably 8 instead of 9. Check to make sure and correct if necessary.
- palBg _bgTable[9]; ///< Table of backgrounds loaded into renderer
- byte *_activeHiPal; ///< Active 256 color palette
+ Common::Array<palBg> _bgTable; ///< Table of backgrounds loaded into renderer (Maximum is 9)
unsigned int _currentBg; ///< Current background
unsigned int _scrollBg; ///< Current scroll background
unsigned int _bgShift; ///< Background shift
protected:
- static const int _hiPalSize = 256 * 3; ///< 256 color palette size
void drawSprite(const objectStruct &obj);
int drawChar(char character, int x, int y);
@@ -169,19 +187,15 @@ public:
void saveBgNames(Common::OutSaveFile &fHandle);
const char *getBgName(uint idx = 0) const;
- void refreshPalette();
void reloadPalette();
void restorePalette(Common::SeekableReadStream &fHandle);
void savePalette(Common::OutSaveFile &fHandle);
- void rotatePalette(int a, int b, int c);
void transformPalette(int first, int last, int r, int g, int b);
- void fadeToBlack();
};
void gfxDrawSprite(byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy);
-extern byte *collisionPage;
extern FWRenderer *renderer;
void setMouseCursor(int cursor);
diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp
index c6bca84e46..44e4e43a6c 100644
--- a/engines/cine/main_loop.cpp
+++ b/engines/cine/main_loop.cpp
@@ -288,6 +288,8 @@ void CineEngine::mainLoop(int bootScriptIdx) {
globalVars[VAR_MOUSE_X_POS] = 0;
globalVars[VAR_MOUSE_Y_POS] = 0;
if (g_cine->getGameType() == Cine::GType_OS) {
+ globalVars[VAR_MOUSE_X_POS_2ND] = 0;
+ globalVars[VAR_MOUSE_Y_POS_2ND] = 0;
globalVars[VAR_BYPASS_PROTECTION] = 0; // set to 1 to bypass the copy protection
globalVars[VAR_LOW_MEMORY] = 0; // set to 1 to disable some animations, sounds etc.
}
diff --git a/engines/cine/pal.cpp b/engines/cine/pal.cpp
index 49edaef5e4..b3e3629239 100644
--- a/engines/cine/pal.cpp
+++ b/engines/cine/pal.cpp
@@ -103,65 +103,6 @@ void loadRelatedPalette(const char *fileName) {
}
}
-void palRotate(uint16 *pal, byte a, byte b, byte c) {
- assert(pal);
-
- if (c == 1) {
- uint16 currentColor = pal[b];
-
- for (int i = b; i > a; i--) {
- pal[i] = pal[i - 1];
- }
-
- pal[a] = currentColor;
- }
-}
-
-void palRotate(byte *pal, byte a, byte b, byte c) {
- assert(pal);
-
- if (c == 1) {
- byte currentR = pal[3 * b + 0];
- byte currentG = pal[3 * b + 1];
- byte currentB = pal[3 * b + 2];
-
- for (int i = b; i > a; i--) {
- pal[3 * i + 0] = pal[3 * (i - 1) + 0];
- pal[3 * i + 1] = pal[3 * (i - 1) + 1];
- pal[3 * i + 2] = pal[3 * (i - 1) + 2];
- }
-
- pal[3 * a + 0] = currentR;
- pal[3 * a + 1] = currentG;
- pal[3 * a + 2] = currentB;
- }
-}
-
-uint16 transformColor(uint16 baseColor, int r, int g, int b) {
- int8 oriR = CLIP( (baseColor & 0x007) + b, 0, 7);
- int8 oriG = CLIP(((baseColor & 0x070) >> 4) + g, 0, 7);
- int8 oriB = CLIP(((baseColor & 0x700) >> 8) + r, 0, 7);
-
- return oriR | (oriG << 4) | (oriB << 8);
-}
-
-void transformPaletteRange(uint16 *dstPal, uint16 *srcPal, int startColor, int stopColor, int r, int g, int b) {
- assert(srcPal && dstPal);
-
- for (int i = startColor; i <= stopColor; i++)
- dstPal[i] = transformColor(srcPal[i], r, g, b);
-}
-
-void transformPaletteRange(byte *dstPal, byte *srcPal, int startColor, int stopColor, int r, int g, int b) {
- assert(srcPal && dstPal);
-
- for (int i = startColor; i <= stopColor; i++) {
- dstPal[3 * i + 0] = CLIP(srcPal[3 * i + 0] + r * 36, 0, 252);
- dstPal[3 * i + 1] = CLIP(srcPal[3 * i + 1] + g * 36, 0, 252);
- dstPal[3 * i + 2] = CLIP(srcPal[3 * i + 2] + b * 36, 0, 252);
- }
-}
-
/*! \brief Shift byte to the left by given amount (Handles negative shifting amounts too, otherwise this would be trivial). */
byte shiftByteLeft(const byte value, const signed shiftLeft) {
if (shiftLeft >= 0)
@@ -198,13 +139,17 @@ int bytePos(const int bitPos, const int numBytes, const bool bigEndian) {
}
// a.k.a. palRotate
-Palette &Palette::rotateRight(byte firstIndex, byte lastIndex) {
- const Color lastColor = _colors[lastIndex];
+Palette &Palette::rotateRight(byte firstIndex, byte lastIndex, signed rotationAmount) {
+ assert(rotationAmount == 0 || rotationAmount == 1);
+
+ if (rotationAmount == 1) {
+ const Color lastColor = _colors[lastIndex];
- for (int i = lastIndex; i > firstIndex; i--)
- _colors[i] = _colors[i - 1];
+ for (int i = lastIndex; i > firstIndex; i--)
+ _colors[i] = _colors[i - 1];
- _colors[firstIndex] = lastColor;
+ _colors[firstIndex] = lastColor;
+ }
return *this;
}
@@ -277,18 +222,18 @@ Palette &Palette::saturatedAddColor(Palette& output, byte firstIndex, byte lastI
Palette &Palette::saturatedAddColor(Palette& output, byte firstIndex, byte lastIndex, signed rSource, signed gSource, signed bSource, const Graphics::PixelFormat &sourceFormat) {
// Convert the source color to the internal color format ensuring that no divide by zero will happen
- const signed r = _format.rMax() * rSource / MAX<int>(sourceFormat.rMax(), 1);
- const signed g = _format.gMax() * gSource / MAX<int>(sourceFormat.gMax(), 1);
- const signed b = _format.bMax() * bSource / MAX<int>(sourceFormat.bMax(), 1);
+ const signed r = ((signed) _format.rMax()) * rSource / MAX<int>(sourceFormat.rMax(), 1);
+ const signed g = ((signed) _format.gMax()) * gSource / MAX<int>(sourceFormat.gMax(), 1);
+ const signed b = ((signed) _format.bMax()) * bSource / MAX<int>(sourceFormat.bMax(), 1);
return saturatedAddColor(output, firstIndex, lastIndex, r, g, b);
}
Palette &Palette::saturatedAddNormalizedGray(Palette& output, byte firstIndex, byte lastIndex, int grayDividend, int grayDenominator) {
assert(grayDenominator != 0);
- const signed r = _format.rMax() * grayDividend / grayDenominator;
- const signed g = _format.gMax() * grayDividend / grayDenominator;
- const signed b = _format.bMax() * grayDividend / grayDenominator;
+ const signed r = ((signed) _format.rMax()) * grayDividend / grayDenominator;
+ const signed g = ((signed) _format.gMax()) * grayDividend / grayDenominator;
+ const signed b = ((signed) _format.bMax()) * grayDividend / grayDenominator;
return saturatedAddColor(output, firstIndex, lastIndex, r, g, b);
}
diff --git a/engines/cine/pal.h b/engines/cine/pal.h
index f59dee53df..4764d5a474 100644
--- a/engines/cine/pal.h
+++ b/engines/cine/pal.h
@@ -73,16 +73,8 @@ void loadPal(const char *fileName);
void loadRelatedPalette(const char *fileName);
-void palRotate(uint16 *pal, byte a, byte b, byte c);
-void palRotate(byte *pal, byte a, byte b, byte c);
-uint16 transformColor(uint16 baseColor, int r, int g, int b);
-void transformPaletteRange(uint16 *srcPal, uint16 *dstPal, int startColor, int stopColor, int r, int g, int b);
-void transformPaletteRange(byte *srcPal, byte *dstPal, int startColor, int stopColor, int r, int g, int b);
-
-// This class might be used for handling Cine-engine's palettes in the future. WIP!
-// TODO: Document
-// TODO: Make use of
-// TODO: Test
+// A class for handling Cine-engine's palettes.
+// TODO: Test a bit more
class Palette {
public:
struct Color {
@@ -135,7 +127,10 @@ public:
*/
byte *save(byte *buf, const uint size, const Graphics::PixelFormat format, const uint numColors, const EndianType endian, const byte firstIndex = 0) const;
- Palette &rotateRight(byte firstIndex, byte lastIndex);
+ /*! \brief Rotate the palette in color range [firstIndex, lastIndex] to the right by the specified rotation amount.
+ * \param rotationAmount Amount to rotate the sub-palette to the right. Only values 0 and 1 are currently supported!
+ */
+ Palette &rotateRight(byte firstIndex, byte lastIndex, signed rotationAmount = 1);
Palette &saturatedAddColor(Palette& output, byte firstIndex, byte lastIndex, signed r, signed g, signed b);
/*! \brief Saturated add an RGB color in given color format to current palette's subset and save the modified colors in the given output palette.
diff --git a/engines/cine/sound.cpp b/engines/cine/sound.cpp
index 164c5a9ca5..65b384ac7d 100644
--- a/engines/cine/sound.cpp
+++ b/engines/cine/sound.cpp
@@ -507,8 +507,6 @@ void AdlibSoundDriverADL::setChannelFrequency(int channel, int frequency) {
}
int freq, note, oct;
findNote(frequency, &note, &oct);
-
- note += oct * 12;
if (ins->amDepth) {
note = ins->amDepth;
}
diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp
index 1ec558c217..7192afcd92 100644
--- a/engines/cine/various.cpp
+++ b/engines/cine/various.cpp
@@ -1095,8 +1095,8 @@ uint16 executePlayerInput(void) {
// This fixes swimming at the bottom of the ocean after
// having been thrown into it with the girl.
if (g_cine->getGameType() == Cine::GType_OS) {
- globalVars[251] = globalVars[VAR_MOUSE_X_POS];
- globalVars[252] = globalVars[VAR_MOUSE_Y_POS];
+ globalVars[VAR_MOUSE_X_POS_2ND] = globalVars[VAR_MOUSE_X_POS];
+ globalVars[VAR_MOUSE_Y_POS_2ND] = globalVars[VAR_MOUSE_Y_POS];
}
return var_5E;
@@ -1501,10 +1501,7 @@ void processSeqListElement(SeqListElement &element) {
if (xMoveKeyb != kKeybMoveRight) {
adder = -adder;
}
- // FIXME: In Operation Stealth's disassembly global variable 251 is used here
- // but it's named as VAR_MOUSE_Y_MODE in ScummVM. Is it correct or a
- // left over from Future Wars's reverse engineering?
- globalVars[VAR_MOUSE_X_POS] = globalVars[251] = ptr1[4] + x + adder;
+ globalVars[VAR_MOUSE_X_POS] = globalVars[VAR_MOUSE_X_POS_2ND] = ptr1[4] + x + adder;
}
if (yMoveKeyb && allowPlayerInput) {
@@ -1512,8 +1509,7 @@ void processSeqListElement(SeqListElement &element) {
if (yMoveKeyb != kKeybMoveDown) {
adder = -adder;
}
- // TODO: Name currently unnamed global variable 252
- globalVars[VAR_MOUSE_Y_POS] = globalVars[252] = ptr1[5] + y + adder;
+ globalVars[VAR_MOUSE_Y_POS] = globalVars[VAR_MOUSE_Y_POS_2ND] = ptr1[5] + y + adder;
}
if (globalVars[VAR_MOUSE_X_POS] || globalVars[VAR_MOUSE_Y_POS]) {
diff --git a/engines/cruise/cruise.cpp b/engines/cruise/cruise.cpp
index 734f4b95c5..4656704cb8 100644
--- a/engines/cruise/cruise.cpp
+++ b/engines/cruise/cruise.cpp
@@ -52,26 +52,24 @@ CruiseEngine::CruiseEngine(OSystem * syst, const CRUISEGameDescription *gameDesc
_currentVolumeFile = new Common::File();
#endif
- Common::addDebugChannel(kCruiseDebugScript, "Script",
- "Script debug level");
+ Common::addDebugChannel(kCruiseDebugScript, "scripts", "Scripts debug level");
+ Common::addDebugChannel(kCruiseDebugSound, "sound", "Sound debug level");
// Setup mixer
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType,
- ConfMan.getInt("sfx_volume"));
+ ConfMan.getInt("sfx_volume"));
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType,
- ConfMan.getInt("music_volume"));
+ ConfMan.getInt("music_volume"));
_vm = this;
_debugger = new Debugger();
- _music = new MusicPlayer();
- _sound = new SoundPlayer();
+ _sound = new PCSound(_mixer, this);
syst->getEventManager()->registerRandomSource(_rnd, "cruise");
}
CruiseEngine::~CruiseEngine() {
delete _debugger;
- delete _music;
delete _sound;
freeSystem();
@@ -126,9 +124,8 @@ void CruiseEngine::initialize() {
readVolCnf();
// Setup mixer
- _musicVolume = ConfMan.getInt("music_volume");
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+// _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
+// _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
@@ -230,4 +227,8 @@ const char *CruiseEngine::getSavegameFile(int saveGameIdx) {
return buffer;
}
+void CruiseEngine::syncSoundSettings() {
+ _sound->syncSounds();
+}
+
} // End of namespace Cruise
diff --git a/engines/cruise/cruise.h b/engines/cruise/cruise.h
index 2fc69acea0..af098b4997 100644
--- a/engines/cruise/cruise.h
+++ b/engines/cruise/cruise.h
@@ -57,10 +57,8 @@ private:
bool _preLoad;
Debugger *_debugger;
MidiDriver *_driver;
- MusicPlayer *_music;
- SoundPlayer *_sound;
+ PCSound *_sound;
bool _mt32, _adlib;
- int _musicVolume;
Common::StringList _langStrings;
CursorType _savedCursor;
uint32 lastTick, lastTickDebug;
@@ -90,8 +88,7 @@ public:
uint32 getFeatures() const;
Common::Language getLanguage() const;
Common::Platform getPlatform() const;
- MusicPlayer &music() { return *_music; }
- SoundPlayer &sound() { return *_sound; }
+ PCSound &sound() { return *_sound; }
bool mt32() const { return _mt32; }
bool adlib() const { return _adlib; }
virtual GUI::Debugger *getDebugger() { return _debugger; }
@@ -103,6 +100,7 @@ public:
virtual bool canLoadGameStateCurrently();
virtual Common::Error saveGameState(int slot, const char *desc);
virtual bool canSaveGameStateCurrently();
+ virtual void syncSoundSettings();
const CRUISEGameDescription *_gameDescription;
void initAllData(void);
@@ -128,7 +126,8 @@ enum {
};
enum {
- kCruiseDebugScript = 1 << 0
+ kCruiseDebugScript = 1 << 0,
+ kCruiseDebugSound = 1 << 1
};
enum {
diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp
index 136aa92b81..938e823fe9 100644
--- a/engines/cruise/cruise_main.cpp
+++ b/engines/cruise/cruise_main.cpp
@@ -81,12 +81,11 @@ int getNumObjectsByClass(int scriptIdx, int param) {
return (counter);
}
-void resetFileEntryRange(int param1, int param2) {
+void resetFileEntryRange(int start, int count) {
int i;
- for (i = param1; i < param2; i++) {
- resetFileEntry(i);
- }
+ for (i = 0; i < count; ++i)
+ resetFileEntry(start + i);
}
int getProcParam(int overlayIdx, int param2, const char *name) {
@@ -294,15 +293,15 @@ int loadFileSub1(uint8 **ptr, const char *name, uint8 *ptr2) {
if (!strcmp(buffer, ".SPL")) {
removeExtention(name, buffer);
- // if (useH32)
- {
- strcat(buffer, ".H32");
- }
- /* else
+ /* if (useH32)
+ *{
+ * strcat(buffer, ".H32");
+ *}
+ * else
* if (useAdlib)
- * {
- * strcatuint8(buffer,".ADL");
- * }
+ * { */
+ strcat(buffer,".ADL");
+ /* }
* else
* {
* strcatuint8(buffer,".HP");
@@ -1739,6 +1738,9 @@ void CruiseEngine::mainLoop(void) {
int quitValue2 = 1;
int quitValue = 0;
+ if (ConfMan.hasKey("save_slot"))
+ loadGameState(ConfMan.getInt("save_slot"));
+
do {
// Handle frame delay
uint32 currentTick = g_system->getMillis();
diff --git a/engines/cruise/dataLoader.cpp b/engines/cruise/dataLoader.cpp
index d725e1bb89..3cf3957703 100644
--- a/engines/cruise/dataLoader.cpp
+++ b/engines/cruise/dataLoader.cpp
@@ -257,13 +257,15 @@ int loadFile(const char* name, int idx, int destIdx) {
return loadFNTSub(ptr, idx);
break;
}
- case type_UNK: {
- break;
- }
case type_SPL: {
+ // Sound file
+ loadSPLSub(ptr, idx);
break;
}
+ default:
+ error("Unknown fileType in loadFile");
}
+
return -1;
}
@@ -293,13 +295,15 @@ int loadFileRange(const char *name, int startIdx, int currentEntryIdx, int numId
loadFNTSub(ptr, startIdx);
break;
}
- case type_UNK: {
- break;
- }
case type_SPL: {
+ // Sound file
+ loadSPLSub(ptr, startIdx);
break;
}
+ default:
+ error("Unknown fileType in loadFileRange");
}
+
return 0;
}
@@ -316,6 +320,7 @@ int loadFullBundle(const char *name, int startIdx) {
switch (fileType) {
case type_SET: {
+ // Sprite set
int i;
int numMaxEntriesInSet;
@@ -328,15 +333,17 @@ int loadFullBundle(const char *name, int startIdx) {
break;
}
case type_FNT: {
+ // Font file
loadFNTSub(ptr, startIdx);
break;
}
- case type_UNK: {
- break;
- }
case type_SPL: {
+ // Sound file
+ loadSPLSub(ptr, startIdx);
break;
}
+ default:
+ error("Unknown fileType in loadFullBundle");
}
return 0;
@@ -387,6 +394,23 @@ int loadFNTSub(uint8 *ptr, int destIdx) {
return 1;
}
+int loadSPLSub(uint8 *ptr, int destIdx) {
+ uint8 *destPtr;
+ int fileIndex;
+
+ if (destIdx == -1) {
+ fileIndex = createResFileEntry(loadFileVar1, 1, loadFileVar1, 1);
+ } else {
+ fileIndex = updateResFileEntry(loadFileVar1, 1, loadFileVar1, destIdx, 1);
+ }
+
+ destPtr = filesDatabase[fileIndex].subData.ptr;
+ memcpy(destPtr, ptr, loadFileVar1);
+
+ return 1;
+}
+
+
int loadSetEntry(const char *name, uint8 *ptr, int currentEntryIdx, int currentDestEntry) {
uint8 *ptr3;
int offset;
diff --git a/engines/cruise/dataLoader.h b/engines/cruise/dataLoader.h
index 2e433acfcb..f6bea29cde 100644
--- a/engines/cruise/dataLoader.h
+++ b/engines/cruise/dataLoader.h
@@ -29,6 +29,7 @@
namespace Cruise {
int loadFNTSub(uint8 *ptr, int destIdx);
+int loadSPLSub(uint8 *ptr, int destIdx);
int loadSetEntry(const char *name, uint8 *ptr, int currentEntryIdx, int currentDestEntry);
int loadFile(const char* name, int idx, int destIdx);
int loadData(const char * name, int startIdx);
diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp
index a0a8cce970..879fad0210 100644
--- a/engines/cruise/detection.cpp
+++ b/engines/cruise/detection.cpp
@@ -209,7 +209,8 @@ bool CruiseMetaEngine::hasFeature(MetaEngineFeature f) const {
(f == kSupportsListSaves) ||
(f == kSupportsDeleteSave) ||
(f == kSavesSupportMetaInfo) ||
- (f == kSavesSupportThumbnail);
+ (f == kSavesSupportThumbnail) ||
+ (f == kSupportsLoadingDuringStartup);
}
SaveStateList CruiseMetaEngine::listSaves(const char *target) const {
diff --git a/engines/cruise/function.cpp b/engines/cruise/function.cpp
index 7789cb6fb1..eab69c6846 100644
--- a/engines/cruise/function.cpp
+++ b/engines/cruise/function.cpp
@@ -32,6 +32,10 @@
namespace Cruise {
+uint32 Period(uint32 hz) {
+ return ((uint32)(100000000L / ((uint32)hz * 28L)));
+}
+
//#define FUNCTION_DEBUG
int16 Op_LoadOverlay(void) {
@@ -198,15 +202,15 @@ int16 Op_Random(void) {
int16 Op_PlayFX(void) {
int volume = popVar();
int speed = popVar();
- int channelNum = popVar();
+ /*int channelNum = */popVar();
int sampleNum = popVar();
if ((sampleNum >= 0) && (sampleNum < NUM_FILE_ENTRIES) && (filesDatabase[sampleNum].subData.ptr)) {
if (speed == -1)
speed = filesDatabase[sampleNum].subData.transparency;
- _vm->sound().startSound(channelNum, filesDatabase[sampleNum].subData.ptr,
- filesDatabase[sampleNum].width, speed, volume, false);
+ _vm->sound().playSound(filesDatabase[sampleNum].subData.ptr,
+ filesDatabase[sampleNum].width, volume);
}
return (0);
@@ -215,15 +219,15 @@ int16 Op_PlayFX(void) {
int16 Op_LoopFX(void) {
int volume = popVar();
int speed = popVar();
- int channelNum = popVar();
+ /*int channelNum = */popVar();
int sampleNum = popVar();
if ((sampleNum >= 0) && (sampleNum < NUM_FILE_ENTRIES) && (filesDatabase[sampleNum].subData.ptr)) {
if (speed == -1)
speed = filesDatabase[sampleNum].subData.transparency;
- _vm->sound().startSound(channelNum, filesDatabase[sampleNum].subData.ptr,
- filesDatabase[sampleNum].width, speed, volume, true);
+ _vm->sound().playSound(filesDatabase[sampleNum].subData.ptr,
+ filesDatabase[sampleNum].width, volume);
}
return (0);
@@ -246,15 +250,14 @@ int16 Op_StopFX(void) {
int16 Op_FreqFX(void) {
int volume = popVar();
- int speed = popVar();
+ int freq2 = popVar();
int channelNum = popVar();
int sampleNum = popVar();
if ((sampleNum >= 0) && (sampleNum < NUM_FILE_ENTRIES) && (filesDatabase[sampleNum].subData.ptr)) {
- if (speed == -1)
- speed = filesDatabase[sampleNum].subData.transparency;
-
- _vm->sound().startNote(channelNum, volume, speed);
+ int freq = Period(freq2 * 1000);
+
+ _vm->sound().startNote(channelNum, volume, freq);
}
return (0);
@@ -357,10 +360,10 @@ int16 Op_FindSet(void) {
}
int16 Op_RemoveFrame(void) {
- int var1 = popVar();
- int var2 = popVar();
+ int count = popVar();
+ int start = popVar();
- resetFileEntryRange(var2, var1);
+ resetFileEntryRange(start, count);
return (0);
}
@@ -563,26 +566,22 @@ int16 Op_LoadFrame(void) {
}
int16 Op_LoadAbs(void) {
- int param1;
-// int param2;
-// int param3;
+ int slot;
char name[36] = "";
char *ptr;
int result = 0;
ptr = (char *) popPtr();
+ slot = popVar();
- strcpy(name, ptr);
-
- param1 = popVar();
-
- if (param1 >= 0 || param1 < NUM_FILE_ENTRIES) {
+ if ((slot >= 0) && (slot < NUM_FILE_ENTRIES)) {
+ strcpy(name, ptr);
strToUpper(name);
gfxModuleData_gfxWaitVSync();
gfxModuleData_gfxWaitVSync();
- result = loadFullBundle(name, param1);
+ result = loadFullBundle(name, slot);
}
changeCursor(CURSOR_NORMAL);
@@ -774,8 +773,6 @@ int16 Op_UnfreezeParent(void) {
return 0;
}
-int16 protectionCode = 0;
-
int16 Op_ProtectionFlag(void) {
int16 temp = protectionCode;
int16 newVar;
@@ -1356,22 +1353,22 @@ int16 Op_LoadSong(void) {
strcpy(buffer, ptr);
strToUpper(buffer);
- _vm->music().loadSong(buffer);
+ _vm->sound().loadMusic(buffer);
changeCursor(CURSOR_NORMAL);
return 0;
}
int16 Op_PlaySong(void) {
- if (_vm->music().songLoaded() && !_vm->music().songPlayed())
- _vm->music().startSong();
+ if (_vm->sound().songLoaded() && !_vm->sound().songPlayed())
+ _vm->sound().playMusic();
return 0;
}
int16 Op_StopSong(void) {
- if (_vm->music().isPlaying())
- _vm->music().stop();
+ if (_vm->sound().isPlaying())
+ _vm->sound().stopMusic();
return 0;
}
@@ -1385,12 +1382,12 @@ int16 Op_RestoreSong(void) {
int16 Op_SongSize(void) {
int size, oldSize;
- if (_vm->music().songLoaded()) {
- byte *pSize = _vm->music().songData() + 470;
- oldSize = *pSize;
+ if (_vm->sound().songLoaded()) {
+ oldSize = _vm->sound().numOrders();
+
size = popVar();
if ((size >= 1) && (size < 128))
- *pSize = size;
+ _vm->sound().setNumOrders(size);
} else
oldSize = 0;
@@ -1401,35 +1398,34 @@ int16 Op_SetPattern(void) {
int value = popVar();
int offset = popVar();
- if (_vm->music().songLoaded()) {
- byte *pData = _vm->music().songData();
- *(pData + 472 + offset) = (byte)value;
+ if (_vm->sound().songLoaded()) {
+ _vm->sound().setPattern(offset, value);
}
return 0;
}
int16 Op_FadeSong(void) {
- _vm->music().fadeSong();
+ _vm->sound().fadeSong();
return 0;
}
int16 Op_FreeSong(void) {
- _vm->music().stop();
- _vm->music().removeSong();
+ _vm->sound().stopMusic();
+ _vm->sound().removeMusic();
return 0;
}
int16 Op_SongLoop(void) {
- bool oldLooping = _vm->music().looping();
- _vm->music().setLoop(popVar() != 0);
+ bool oldLooping = _vm->sound().musicLooping();
+ _vm->sound().musicLoop(popVar() != 0);
return oldLooping;
}
int16 Op_SongPlayed(void) {
- return _vm->music().songPlayed();
+ return _vm->sound().songPlayed();
}
void setVar49Value(int value) {
@@ -1634,25 +1630,29 @@ int16 Op_GetNodeY(void) {
}
int16 Op_SetVolume(void) {
- int oldVolume = _vm->music().getVolume() >> 2;
+ int oldVolume = _vm->sound().getVolume();
int newVolume = popVar();
- // TODO: The game seems to expect the volume will only range from 0 - 63, so for now
- // I'm doing a translation of the full range 0 - 255 to the 0 - 63 for this script.
- // Need to verify at some point that there's no problem with this
if (newVolume > 63) newVolume = 63;
if (newVolume >= 0) {
int volume = 63 - newVolume;
- _vm->music().setVolume(volume << 2);
+ _vm->sound().setVolume(volume);
}
return oldVolume >> 2;
}
int16 Op_SongExist(void) {
- char* songName = (char*)popPtr();
+ const char *songName = (char*)popPtr();
+
+ if (songName) {
+ char name[33];
+ strcpy(name, songName);
+ strToUpper(name);
- warning("Unimplemented \"Op_SongExist\": %s", songName);
+ if (!strcmp(_vm->sound().musicName(), name))
+ return 1;
+ }
return 0;
}
diff --git a/engines/cruise/menu.cpp b/engines/cruise/menu.cpp
index 136bd281dc..0e9ab55c82 100644
--- a/engines/cruise/menu.cpp
+++ b/engines/cruise/menu.cpp
@@ -207,7 +207,7 @@ int playerMenu(int menuX, int menuY) {
if (playerMenuEnabled && displayOn) {
if (remdo) {
- _vm->music().removeSong();
+ _vm->sound().stopMusic();
freeStuff2();
}
/*
@@ -261,6 +261,7 @@ int playerMenu(int menuX, int menuY) {
loadSavegameData(0);
break;
case 6: // restart
+ _vm->sound().fadeOutMusic();
Op_FadeOut();
memset(globalScreen, 0, 320 * 200);
initVars();
diff --git a/engines/cruise/saveload.cpp b/engines/cruise/saveload.cpp
index 0084b10cb9..d151950c5e 100644
--- a/engines/cruise/saveload.cpp
+++ b/engines/cruise/saveload.cpp
@@ -25,6 +25,7 @@
#include "cruise/cruise_main.h"
#include "cruise/cruise.h"
+#include "cruise/vars.h"
#include "common/serializer.h"
#include "common/savefile.h"
@@ -143,6 +144,7 @@ static void syncBasicInfo(Common::Serializer &s) {
s.syncAsSint16LE(flagCt);
s.syncAsSint16LE(var41);
s.syncAsSint16LE(playerMenuEnabled);
+ s.syncAsSint16LE(protectionCode);
}
static void syncBackgroundTable(Common::Serializer &s) {
@@ -608,7 +610,7 @@ static void syncCT(Common::Serializer &s) {
static void DoSync(Common::Serializer &s) {
syncBasicInfo(s);
- _vm->music().doSync(s);
+ _vm->sound().doSync(s);
syncPalette(s, newPal);
syncPalette(s, workpal);
@@ -818,6 +820,7 @@ Common::Error loadSavegameData(int saveGameIdx) {
printInfoBlackBox("Loading in progress...");
initVars();
+ _vm->sound().stopMusic();
// Skip over the savegame header
CruiseSavegameHeader header;
@@ -926,8 +929,6 @@ Common::Error loadSavegameData(int saveGameIdx) {
currentcellHead = currentcellHead->next;
}
- //TODO: here, restart music
-
if (strlen(currentCtpName)) {
loadCtFromSave = 1;
initCt(currentCtpName);
diff --git a/engines/cruise/sound.cpp b/engines/cruise/sound.cpp
index fd638e6be5..92c2ac6256 100644
--- a/engines/cruise/sound.cpp
+++ b/engines/cruise/sound.cpp
@@ -30,199 +30,856 @@
#include "cruise/sound.h"
#include "cruise/volume.h"
+#include "sound/audiostream.h"
+#include "sound/fmopl.h"
+#include "sound/mods/soundfx.h"
+
namespace Cruise {
-MusicPlayer::MusicPlayer(): _looping(false), _isPlaying(false), _songPlayed(false) {
- _songPointer = NULL;
- _masterVolume = 0;
+class PCSoundDriver {
+public:
+ typedef void (*UpdateCallback)(void *);
+
+ virtual ~PCSoundDriver() {}
+
+ virtual void setupChannel(int channel, const byte *data, int instrument, int volume) = 0;
+ virtual void setChannelFrequency(int channel, int frequency) = 0;
+ virtual void stopChannel(int channel) = 0;
+ virtual void playSample(const byte *data, int size, int channel, int volume) = 0;
+ virtual void stopAll() = 0;
+ virtual const char *getInstrumentExtension() const { return ""; }
+ virtual void syncSounds();
+
+ void setUpdateCallback(UpdateCallback upCb, void *ref);
+ void resetChannel(int channel);
+ void findNote(int freq, int *note, int *oct) const;
+
+
+protected:
+ UpdateCallback _upCb;
+ void *_upRef;
+ uint8 _musicVolume;
+ uint8 _sfxVolume;
+
+ static const int _noteTable[];
+ static const int _noteTableCount;
+};
+
+const int PCSoundDriver::_noteTable[] = {
+ 0xEEE, 0xE17, 0xD4D, 0xC8C, 0xBD9, 0xB2F, 0xA8E, 0x9F7,
+ 0x967, 0x8E0, 0x861, 0x7E8, 0x777, 0x70B, 0x6A6, 0x647,
+ 0x5EC, 0x597, 0x547, 0x4FB, 0x4B3, 0x470, 0x430, 0x3F4,
+ 0x3BB, 0x385, 0x353, 0x323, 0x2F6, 0x2CB, 0x2A3, 0x27D,
+ 0x259, 0x238, 0x218, 0x1FA, 0x1DD, 0x1C2, 0x1A9, 0x191,
+ 0x17B, 0x165, 0x151, 0x13E, 0x12C, 0x11C, 0x10C, 0x0FD,
+ 0x0EE, 0x0E1, 0x0D4, 0x0C8, 0x0BD, 0x0B2, 0x0A8, 0x09F,
+ 0x096, 0x08E, 0x086, 0x07E, 0x077, 0x070, 0x06A, 0x064,
+ 0x05E, 0x059, 0x054, 0x04F, 0x04B, 0x047, 0x043, 0x03F,
+ 0x03B, 0x038, 0x035, 0x032, 0x02F, 0x02C, 0x02A, 0x027,
+ 0x025, 0x023, 0x021, 0x01F, 0x01D, 0x01C, 0x01A, 0x019,
+ 0x017, 0x016, 0x015, 0x013, 0x012, 0x011, 0x010, 0x00F
+};
+
+const int PCSoundDriver::_noteTableCount = ARRAYSIZE(_noteTable);
+
+struct AdlibRegisterSoundInstrument {
+ uint8 vibrato;
+ uint8 attackDecay;
+ uint8 sustainRelease;
+ uint8 feedbackStrength;
+ uint8 keyScaling;
+ uint8 outputLevel;
+ uint8 freqMod;
+};
+
+struct AdlibSoundInstrument {
+ byte mode;
+ byte channel;
+ AdlibRegisterSoundInstrument regMod;
+ AdlibRegisterSoundInstrument regCar;
+ byte waveSelectMod;
+ byte waveSelectCar;
+ byte amDepth;
+};
+
+struct VolumeEntry {
+ int original;
+ int adjusted;
+};
+
+class AdlibSoundDriver : public PCSoundDriver, Audio::AudioStream {
+public:
+ AdlibSoundDriver(Audio::Mixer *mixer);
+ virtual ~AdlibSoundDriver();
+
+ // PCSoundDriver interface
+ virtual void setupChannel(int channel, const byte *data, int instrument, int volume);
+ virtual void stopChannel(int channel);
+ virtual void stopAll();
+
+ // AudioStream interface
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+ virtual bool isStereo() const { return false; }
+ virtual bool endOfData() const { return false; }
+ virtual int getRate() const { return _sampleRate; }
+
+ void initCard();
+ void update(int16 *buf, int len);
+ void setupInstrument(const byte *data, int channel);
+ void setupInstrument(const AdlibSoundInstrument *ins, int channel);
+ void loadRegisterInstrument(const byte *data, AdlibRegisterSoundInstrument *reg);
+ virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi) = 0;
+ virtual void syncSounds();
+
+ void adjustVolume(int channel, int volume);
+
+protected:
+ FM_OPL *_opl;
+ int _sampleRate;
+ Audio::Mixer *_mixer;
+ Audio::SoundHandle _soundHandle;
+
+ byte _vibrato;
+ VolumeEntry _channelsVolumeTable[5];
+ AdlibSoundInstrument _instrumentsTable[5];
+
+ static const int _freqTable[];
+ static const int _freqTableCount;
+ static const int _operatorsTable[];
+ static const int _operatorsTableCount;
+ static const int _voiceOperatorsTable[];
+ static const int _voiceOperatorsTableCount;
+};
+
+const int AdlibSoundDriver::_freqTable[] = {
+ 0x157, 0x16C, 0x181, 0x198, 0x1B1, 0x1CB,
+ 0x1E6, 0x203, 0x222, 0x243, 0x266, 0x28A
+};
+
+const int AdlibSoundDriver::_freqTableCount = ARRAYSIZE(_freqTable);
+
+const int AdlibSoundDriver::_operatorsTable[] = {
+ 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21
+};
+
+const int AdlibSoundDriver::_operatorsTableCount = ARRAYSIZE(_operatorsTable);
+
+const int AdlibSoundDriver::_voiceOperatorsTable[] = {
+ 0, 3, 1, 4, 2, 5, 6, 9, 7, 10, 8, 11, 12, 15, 16, 16, 14, 14, 17, 17, 13, 13
+};
+
+const int AdlibSoundDriver::_voiceOperatorsTableCount = ARRAYSIZE(_voiceOperatorsTable);
+
+class AdlibSoundDriverADL : public AdlibSoundDriver {
+public:
+ AdlibSoundDriverADL(Audio::Mixer *mixer) : AdlibSoundDriver(mixer) {}
+ virtual const char *getInstrumentExtension() const { return ".ADL"; }
+ virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi);
+ virtual void setChannelFrequency(int channel, int frequency);
+ virtual void playSample(const byte *data, int size, int channel, int volume);
+};
+
+class PCSoundFxPlayer {
+private:
+ enum {
+ NUM_INSTRUMENTS = 15,
+ NUM_CHANNELS = 4
+ };
+
+ void update();
+ void handleEvents();
+ void handlePattern(int channel, const byte *patternData);
+
+ char _musicName[33];
+ bool _playing;
+ bool _songPlayed;
+ int _currentPos;
+ int _currentOrder;
+ int _numOrders;
+ int _eventsDelay;
+ bool _looping;
+ int _fadeOutCounter;
+ int _updateTicksCounter;
+ int _instrumentsChannelTable[NUM_CHANNELS];
+ byte *_sfxData;
+ byte *_instrumentsData[NUM_INSTRUMENTS];
+ PCSoundDriver *_driver;
+
+public:
+ PCSoundFxPlayer(PCSoundDriver *driver);
+ ~PCSoundFxPlayer();
+
+ bool load(const char *song);
+ void play();
+ void stop();
+ void unload();
+ void fadeOut();
+ void doSync(Common::Serializer &s);
+
+ static void updateCallback(void *ref);
+
+ bool songLoaded() const { return _sfxData != NULL; }
+ bool songPlayed() const { return _songPlayed; }
+ bool playing() const { return _playing; }
+ uint8 numOrders() const { assert(_sfxData); return _sfxData[470]; }
+ void setNumOrders(uint8 v) { assert(_sfxData); _sfxData[470] = v; }
+ void setPattern(int offset, uint8 value) { assert(_sfxData); _sfxData[472 + offset] = value; }
+ const char *musicName() { return _musicName; }
+
+ // Note: Original game never actually uses looping variable. Songs are hardcoded to loop
+ bool looping() const { return _looping; }
+ void setLooping(bool v) { _looping = v; }
+};
+
+byte *readBundleSoundFile(const char *name) {
+ // Load the correct file
+ int fileIdx = findFileInDisks(name);
+ if (fileIdx < 0) return NULL;
+
+ int unpackedSize = volumePtrToFileDescriptor[fileIdx].extSize + 2;
+ byte *data = (byte *)malloc(unpackedSize);
+ assert(data);
+
+ if (volumePtrToFileDescriptor[fileIdx].size + 2 != unpackedSize) {
+ uint8 *packedBuffer = (uint8 *)mallocAndZero(volumePtrToFileDescriptor[fileIdx].size + 2);
+
+ loadPackedFileToMem(fileIdx, packedBuffer);
+
+ //uint32 realUnpackedSize = READ_BE_UINT32(packedBuffer + volumePtrToFileDescriptor[fileIdx].size - 4);
+
+ delphineUnpack(data, packedBuffer, volumePtrToFileDescriptor[fileIdx].size);
+
+ free(packedBuffer);
+ } else {
+ loadPackedFileToMem(fileIdx, data);
+ }
+
+ return data;
}
-MusicPlayer::~MusicPlayer() {
- stop();
- if (_songPointer != NULL)
- free(_songPointer);
+
+void PCSoundDriver::setUpdateCallback(UpdateCallback upCb, void *ref) {
+ _upCb = upCb;
+ _upRef = ref;
}
-void MusicPlayer::setVolume(int volume) {
- _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
+void PCSoundDriver::findNote(int freq, int *note, int *oct) const {
+ *note = _noteTableCount - 1;
+ for (int i = 0; i < _noteTableCount; ++i) {
+ if (_noteTable[i] <= freq) {
+ *note = i;
+ break;
+ }
+ }
- if (_masterVolume == volume)
- return;
+ *oct = *note / 12;
+ *note %= 12;
+}
- _masterVolume = volume;
+void PCSoundDriver::resetChannel(int channel) {
+ stopChannel(channel);
+ stopAll();
}
-void MusicPlayer::stop() {
- _isPlaying = false;
- _songPlayed = songLoaded();
+void PCSoundDriver::syncSounds() {
+ // Get the new music and sfx volumes
+ _musicVolume = ConfMan.getBool("music_mute") ? 0 : MIN(255, ConfMan.getInt("music_volume"));
+ _sfxVolume = ConfMan.getBool("sfx_mute") ? 0 : MIN(255, ConfMan.getInt("sfx_volume"));
}
-void MusicPlayer::pause() {
- setVolume(-1);
- _isPlaying = false;
+AdlibSoundDriver::AdlibSoundDriver(Audio::Mixer *mixer)
+ : _mixer(mixer) {
+ _sampleRate = _mixer->getOutputRate();
+ _opl = makeAdlibOPL(_sampleRate);
+
+ for (int i = 0; i < 5; ++i) {
+ _channelsVolumeTable[i].original = 0;
+ _channelsVolumeTable[i].adjusted = 0;
+ }
+ memset(_instrumentsTable, 0, sizeof(_instrumentsTable));
+ initCard();
+ _mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true);
+
+ _musicVolume = ConfMan.getBool("music_mute") ? 0 : MIN(255, ConfMan.getInt("music_volume"));
+ _sfxVolume = ConfMan.getBool("sfx_mute") ? 0 : MIN(255, ConfMan.getInt("sfx_volume"));
}
-void MusicPlayer::resume() {
- setVolume(_masterVolume);
- _isPlaying = true;
- _songPlayed = false;
+AdlibSoundDriver::~AdlibSoundDriver() {
+ _mixer->stopHandle(_soundHandle);
+ OPLDestroy(_opl);
}
-void MusicPlayer::doSync(Common::Serializer &s) {
- // synchronise current music name, if any, state, and position
- s.syncBytes((byte *)_musicName, 33);
- uint16 v = (uint16)songLoaded();
- s.syncAsSint16LE(v);
- s.syncAsSint16LE(_songPlayed);
- s.syncAsSint16LE(_looping);
+void AdlibSoundDriver::syncSounds() {
+ PCSoundDriver::syncSounds();
+
+ // Force all instruments to reload on the next playing point
+ for (int i = 0; i < 5; ++i) {
+ adjustVolume(i, _channelsVolumeTable[i].original);
+ AdlibSoundInstrument *ins = &_instrumentsTable[i];
+ setupInstrument(ins, i);
+ }
}
-void MusicPlayer::loadSong(const char *name) {
- char tempName[20], baseName[20];
- uint8 *sampleData;
+void AdlibSoundDriver::adjustVolume(int channel, int volume) {
+ _channelsVolumeTable[channel].original = volume;
- if (songLoaded())
- removeSong();
+ if (volume > 80) {
+ volume = 80;
+ } else if (volume < 0) {
+ volume = 0;
+ }
+ volume += volume / 4;
+ if (volume > 127) {
+ volume = 127;
+ }
- // Load the correct file
- int fileIdx = findFileInDisks(name);
- if (fileIdx < 0) return;
+ int volAdjust = (channel == 4) ? _sfxVolume : _musicVolume;
+ volume = (volume * volAdjust) / 128;
- int unpackedSize = volumePtrToFileDescriptor[fileIdx].extSize + 2;
- _songPointer = (byte *)malloc(unpackedSize);
- assert(_songPointer);
+ if (volume > 127)
+ volume = 127;
- if (volumePtrToFileDescriptor[fileIdx].size + 2 != unpackedSize) {
- uint8 *packedBuffer = (uint8 *)mallocAndZero(volumePtrToFileDescriptor[fileIdx].size + 2);
+ _channelsVolumeTable[channel].adjusted = volume;
+}
- loadPackedFileToMem(fileIdx, packedBuffer);
+void AdlibSoundDriver::setupChannel(int channel, const byte *data, int instrument, int volume) {
+ assert(channel < 5);
+ if (data) {
+ adjustVolume(channel, volume);
+ setupInstrument(data, channel);
+ }
+}
- uint32 realUnpackedSize = READ_BE_UINT32(packedBuffer + volumePtrToFileDescriptor[fileIdx].size - 4);
+void AdlibSoundDriver::stopChannel(int channel) {
+ assert(channel < 5);
+ AdlibSoundInstrument *ins = &_instrumentsTable[channel];
+ if (ins->mode != 0 && ins->channel == 6) {
+ channel = 6;
+ }
+ if (ins->mode == 0 || channel == 6) {
+ OPLWriteReg(_opl, 0xB0 | channel, 0);
+ }
+ if (ins->mode != 0) {
+ _vibrato &= ~(1 << (10 - ins->channel));
+ OPLWriteReg(_opl, 0xBD, _vibrato);
+ }
+}
- delphineUnpack(_songPointer, packedBuffer, volumePtrToFileDescriptor[fileIdx].size);
- _songSize = realUnpackedSize;
+void AdlibSoundDriver::stopAll() {
+ int i;
+ for (i = 0; i < 18; ++i) {
+ OPLWriteReg(_opl, 0x40 | _operatorsTable[i], 63);
+ }
+ for (i = 0; i < 9; ++i) {
+ OPLWriteReg(_opl, 0xB0 | i, 0);
+ }
+ OPLWriteReg(_opl, 0xBD, 0);
+}
- free(packedBuffer);
- } else {
- loadPackedFileToMem(fileIdx, _songPointer);
- _songSize = unpackedSize;
+int AdlibSoundDriver::readBuffer(int16 *buffer, const int numSamples) {
+ update(buffer, numSamples);
+ return numSamples;
+}
+
+void AdlibSoundDriver::initCard() {
+ _vibrato = 0x20;
+ OPLWriteReg(_opl, 0xBD, _vibrato);
+ OPLWriteReg(_opl, 0x08, 0x40);
+
+ static const int oplRegs[] = { 0x40, 0x60, 0x80, 0x20, 0xE0 };
+
+ for (int i = 0; i < 9; ++i) {
+ OPLWriteReg(_opl, 0xB0 | i, 0);
+ }
+ for (int i = 0; i < 9; ++i) {
+ OPLWriteReg(_opl, 0xC0 | i, 0);
}
- strcpy(_musicName, name);
+ for (int j = 0; j < 5; j++) {
+ for (int i = 0; i < 18; ++i) {
+ OPLWriteReg(_opl, oplRegs[j] | _operatorsTable[i], 0);
+ }
+ }
- // Get the details of the song
- // TODO: Figure this out for sure for use in actually playing song
- //int size = *(_songPointer + 470);
- //int speed = 244 - *(_songPointer + 471);
- //int musicSpeed = (speed * 100) / 1060;
+ OPLWriteReg(_opl, 1, 0x20);
+ OPLWriteReg(_opl, 1, 0);
+}
+void AdlibSoundDriver::update(int16 *buf, int len) {
+ static int samplesLeft = 0;
+ while (len != 0) {
+ int count = samplesLeft;
+ if (count > len) {
+ count = len;
+ }
+ samplesLeft -= count;
+ len -= count;
+ YM3812UpdateOne(_opl, buf, count);
+ if (samplesLeft == 0) {
+ if (_upCb) {
+ (*_upCb)(_upRef);
+ }
+ samplesLeft = _sampleRate / 50;
+ }
+ buf += count;
+ }
+}
- // Get the file without the extension
- strcpy(baseName, name);
- char *p = strchr(baseName, '.');
- if (p)
- *p = '\0';
+void AdlibSoundDriver::setupInstrument(const byte *data, int channel) {
+ assert(channel < 5);
+ AdlibSoundInstrument *ins = &_instrumentsTable[channel];
+ loadInstrument(data, ins);
- // Get the instruments states file
- strcpy(tempName, baseName);
- strcat(tempName, ".IST");
+ setupInstrument(ins, channel);
+}
+
+void AdlibSoundDriver::setupInstrument(const AdlibSoundInstrument *ins, int channel) {
+ int mod, car, tmp;
+ const AdlibRegisterSoundInstrument *reg;
- fileIdx = findFileInDisks(tempName);
- if (fileIdx >= 0) {
- // TODO: Figure out instrument state usage
- uint8 instrumentState[15];
- loadPackedFileToMem(fileIdx, instrumentState);
+ if (ins->mode != 0) {
+ mod = _operatorsTable[_voiceOperatorsTable[2 * ins->channel + 0]];
+ car = _operatorsTable[_voiceOperatorsTable[2 * ins->channel + 1]];
+ } else {
+ mod = _operatorsTable[_voiceOperatorsTable[2 * channel + 0]];
+ car = _operatorsTable[_voiceOperatorsTable[2 * channel + 1]];
}
- for (int instrumentCtr = 0; instrumentCtr < 15; ++instrumentCtr) {
- if (_vm->mt32()) {
- // Handle loading Roland instrument data
- strcpy(tempName, baseName);
- strcat(tempName, ".H32");
+ if (ins->mode == 0 || ins->channel == 6) {
+ reg = &ins->regMod;
+ OPLWriteReg(_opl, 0x20 | mod, reg->vibrato);
+ if (reg->freqMod) {
+ tmp = reg->outputLevel & 0x3F;
+ } else {
+ tmp = (63 - (reg->outputLevel & 0x3F)) * _channelsVolumeTable[channel].adjusted;
+ tmp = 63 - (2 * tmp + 127) / (2 * 127);
+ }
+ OPLWriteReg(_opl, 0x40 | mod, tmp | (reg->keyScaling << 6));
+ OPLWriteReg(_opl, 0x60 | mod, reg->attackDecay);
+ OPLWriteReg(_opl, 0x80 | mod, reg->sustainRelease);
+ if (ins->mode != 0) {
+ OPLWriteReg(_opl, 0xC0 | ins->channel, reg->feedbackStrength);
+ } else {
+ OPLWriteReg(_opl, 0xC0 | channel, reg->feedbackStrength);
+ }
+ OPLWriteReg(_opl, 0xE0 | mod, ins->waveSelectMod);
+ }
- sampleData = loadInstrument(tempName, instrumentCtr);
- if (sampleData) {
- int v = *sampleData;
- if ((v >= 128) && (v < 192))
- patchMidi(0x80000L + (instrumentCtr * 512), sampleData + 1, 254);
+ reg = &ins->regCar;
+ OPLWriteReg(_opl, 0x20 | car, reg->vibrato);
+ tmp = (63 - (reg->outputLevel & 0x3F)) * _channelsVolumeTable[channel].adjusted;
+ tmp = 63 - (2 * tmp + 127) / (2 * 127);
+ OPLWriteReg(_opl, 0x40 | car, tmp | (reg->keyScaling << 6));
+ OPLWriteReg(_opl, 0x60 | car, reg->attackDecay);
+ OPLWriteReg(_opl, 0x80 | car, reg->sustainRelease);
+ OPLWriteReg(_opl, 0xE0 | car, ins->waveSelectCar);
+}
- // TODO: Currently I'm freeing the instrument data immediately. The original
- // holds onto the sample data, so it may actually still be needed
- free(sampleData);
- }
- } else if (_vm->adlib()) {
- // Handle loading Adlib instrument data
- strcpy(tempName, baseName);
- strcat(tempName, ".ADL");
+void AdlibSoundDriver::loadRegisterInstrument(const byte *data, AdlibRegisterSoundInstrument *reg) {
+ reg->vibrato = 0;
+ if (READ_LE_UINT16(data + 18)) { // amplitude vibrato
+ reg->vibrato |= 0x80;
+ }
+ if (READ_LE_UINT16(data + 20)) { // frequency vibrato
+ reg->vibrato |= 0x40;
+ }
+ if (READ_LE_UINT16(data + 10)) { // sustaining sound
+ reg->vibrato |= 0x20;
+ }
+ if (READ_LE_UINT16(data + 22)) { // envelope scaling
+ reg->vibrato |= 0x10;
+ }
+ reg->vibrato |= READ_LE_UINT16(data + 2) & 0xF; // frequency multiplier
- fileIdx = findFileInDisks(tempName);
- if (fileIdx >= 0) {
- sampleData = (byte *)malloc(volumePtrToFileDescriptor[fileIdx].extSize + 2);
- assert(sampleData);
- loadPackedFileToMem(fileIdx, sampleData);
+ reg->attackDecay = READ_LE_UINT16(data + 6) << 4; // attack rate
+ reg->attackDecay |= READ_LE_UINT16(data + 12) & 0xF; // decay rate
- // TODO: Make use of sample data
+ reg->sustainRelease = READ_LE_UINT16(data + 8) << 4; // sustain level
+ reg->sustainRelease |= READ_LE_UINT16(data + 14) & 0xF; // release rate
- free(sampleData);
- }
+ reg->feedbackStrength = READ_LE_UINT16(data + 4) << 1; // feedback
+ if (READ_LE_UINT16(data + 24) == 0) { // frequency modulation
+ reg->feedbackStrength |= 1;
+ }
+
+ reg->keyScaling = READ_LE_UINT16(data);
+ reg->outputLevel = READ_LE_UINT16(data + 16);
+ reg->freqMod = READ_LE_UINT16(data + 24);
+}
+
+void AdlibSoundDriverADL::loadInstrument(const byte *data, AdlibSoundInstrument *asi) {
+ asi->mode = *data++;
+ asi->channel = *data++;
+ asi->waveSelectMod = *data++ & 3;
+ asi->waveSelectCar = *data++ & 3;
+ asi->amDepth = *data++;
+ ++data;
+ loadRegisterInstrument(data, &asi->regMod); data += 26;
+ loadRegisterInstrument(data, &asi->regCar); data += 26;
+}
+
+void AdlibSoundDriverADL::setChannelFrequency(int channel, int frequency) {
+ assert(channel < 5);
+ AdlibSoundInstrument *ins = &_instrumentsTable[channel];
+ if (ins->mode != 0) {
+ channel = ins->channel;
+ if (channel == 9) {
+ channel = 8;
+ } else if (channel == 10) {
+ channel = 7;
}
}
+ int freq, note, oct;
+ findNote(frequency, &note, &oct);
- _songPlayed = false;
- _isPlaying = false;
+ note += oct * 12;
+ if (ins->amDepth) {
+ note = ins->amDepth;
+ }
+ if (note < 0) {
+ note = 0;
+ }
+
+ freq = _freqTable[note % 12];
+ OPLWriteReg(_opl, 0xA0 | channel, freq);
+ freq = ((note / 12) << 2) | ((freq & 0x300) >> 8);
+ if (ins->mode == 0) {
+ freq |= 0x20;
+ }
+ OPLWriteReg(_opl, 0xB0 | channel, freq);
+ if (ins->mode != 0) {
+ _vibrato |= 1 << (10 - channel);
+ OPLWriteReg(_opl, 0xBD, _vibrato);
+ }
}
-void MusicPlayer::startSong() {
- if (songLoaded()) {
- // Start playing song here
+void AdlibSoundDriverADL::playSample(const byte *data, int size, int channel, int volume) {
+ assert(channel < 5);
+ adjustVolume(channel, 127);
+
+ setupInstrument(data, channel);
+ AdlibSoundInstrument *ins = &_instrumentsTable[channel];
+ if (ins->mode != 0 && ins->channel == 6) {
+ OPLWriteReg(_opl, 0xB0 | channel, 0);
+ }
+ if (ins->mode != 0) {
+ _vibrato &= ~(1 << (10 - ins->channel));
+ OPLWriteReg(_opl, 0xBD, _vibrato);
}
+ if (ins->mode != 0) {
+ channel = ins->channel;
+ if (channel == 9) {
+ channel = 8;
+ } else if (channel == 10) {
+ channel = 7;
+ }
+ }
+ uint16 note = 48;
+ if (ins->amDepth) {
+ note = ins->amDepth;
+ }
+ int freq = _freqTable[note % 12];
+ OPLWriteReg(_opl, 0xA0 | channel, freq);
+ freq = ((note / 12) << 2) | ((freq & 0x300) >> 8);
+ if (ins->mode == 0) {
+ freq |= 0x20;
+ }
+ OPLWriteReg(_opl, 0xB0 | channel, freq);
+ if (ins->mode != 0) {
+ _vibrato |= 1 << (10 - channel);
+ OPLWriteReg(_opl, 0xBD, _vibrato);
+ }
+}
+
+PCSoundFxPlayer::PCSoundFxPlayer(PCSoundDriver *driver)
+ : _playing(false), _songPlayed(false), _driver(driver) {
+ memset(_instrumentsData, 0, sizeof(_instrumentsData));
+ _sfxData = NULL;
+ _fadeOutCounter = 0;
+ _driver->setUpdateCallback(updateCallback, this);
}
-void MusicPlayer::removeSong() {
- if (isPlaying())
+PCSoundFxPlayer::~PCSoundFxPlayer() {
+ _driver->setUpdateCallback(NULL, NULL);
+ if (_playing) {
stop();
+ }
+}
+
+bool PCSoundFxPlayer::load(const char *song) {
+ debug(9, "PCSoundFxPlayer::load('%s')", song);
- if (_songPointer) {
- free(_songPointer);
- _songPointer = NULL;
+ /* stop (w/ fade out) the previous song */
+ while (_fadeOutCounter != 0 && _fadeOutCounter < 100) {
+ g_system->delayMillis(50);
+ }
+ _fadeOutCounter = 0;
+
+ if (_playing) {
+ stop();
}
+ strcpy(_musicName, song);
_songPlayed = false;
+ _looping = false;
+ _sfxData = readBundleSoundFile(song);
+ if (!_sfxData) {
+ warning("Unable to load soundfx module '%s'", song);
+ return 0;
+ }
+
+ for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
+ _instrumentsData[i] = NULL;
+
+ char instrument[64];
+ memset(instrument, 0, 64); // Clear the data first
+ memcpy(instrument, _sfxData + 20 + i * 30, 12);
+ instrument[63] = '\0';
- strcpy(_musicName, "");
+ if (strlen(instrument) != 0) {
+ char *dot = strrchr(instrument, '.');
+ if (dot) {
+ *dot = '\0';
+ }
+ strcat(instrument, _driver->getInstrumentExtension());
+ _instrumentsData[i] = readBundleSoundFile(instrument);
+ if (!_instrumentsData[i]) {
+ warning("Unable to load soundfx instrument '%s'", instrument);
+ }
+ }
+ }
+ return 1;
}
-void MusicPlayer::fadeSong() {
- // TODO: Implement fading properly
- stop();
+void PCSoundFxPlayer::play() {
+ debug(9, "PCSoundFxPlayer::play()");
+ if (_sfxData) {
+ for (int i = 0; i < NUM_CHANNELS; ++i) {
+ _instrumentsChannelTable[i] = -1;
+ }
+ _currentPos = 0;
+ _currentOrder = 0;
+ _numOrders = _sfxData[470];
+ _eventsDelay = (244 - _sfxData[471]) * 100 / 1060;
+ _updateTicksCounter = 0;
+ _playing = true;
+ }
}
-void MusicPlayer::patchMidi(uint32 adr, const byte *data, int size) {
- // TODO: Handle patching midi
+void PCSoundFxPlayer::stop() {
+ if (_playing || _fadeOutCounter != 0) {
+ _fadeOutCounter = 0;
+ _playing = false;
+ for (int i = 0; i < NUM_CHANNELS; ++i) {
+ _driver->stopChannel(i);
+ }
+ _driver->stopAll();
+ unload();
+ }
}
-byte *MusicPlayer::loadInstrument(const char *name, int i) {
- // Find the resource
- int fileIdx = findFileInDisks(name);
- if (fileIdx < 0) {
- warning("Instrument '%s' not found", name);
- return NULL;
+void PCSoundFxPlayer::fadeOut() {
+ if (_playing) {
+ _fadeOutCounter = 1;
+ _playing = false;
+ }
+}
+
+void PCSoundFxPlayer::updateCallback(void *ref) {
+ ((PCSoundFxPlayer *)ref)->update();
+}
+
+void PCSoundFxPlayer::update() {
+ if (_playing || (_fadeOutCounter != 0 && _fadeOutCounter < 100)) {
+ ++_updateTicksCounter;
+ if (_updateTicksCounter > _eventsDelay) {
+ handleEvents();
+ _updateTicksCounter = 0;
+ }
}
+}
+
+void PCSoundFxPlayer::handleEvents() {
+ const byte *patternData = _sfxData + 600 + 1800;
+ const byte *orderTable = _sfxData + 472;
+ uint16 patternNum = orderTable[_currentOrder] * 1024;
- int size = volumePtrToFileDescriptor[fileIdx].extSize;
+ for (int i = 0; i < 4; ++i) {
+ handlePattern(i, patternData + patternNum + _currentPos);
+ patternData += 4;
+ }
- // Get the data
- byte *tmp = (byte *)malloc(size);
- assert(tmp);
- loadPackedFileToMem(fileIdx, tmp);
+ if (_fadeOutCounter != 0 && _fadeOutCounter < 100) {
+ _fadeOutCounter += 2;
+ }
+ if (_fadeOutCounter >= 100) {
+ stop();
+ return;
+ }
- // Create a copy of the resource that's 22 bytes smaller
- byte *result = (byte *)malloc(size - 22);
- assert(result);
- Common::copy(tmp, tmp + size - 22, result);
+ _currentPos += 16;
+ if (_currentPos >= 1024) {
+ _currentPos = 0;
+ ++_currentOrder;
+ if (_currentOrder == _numOrders) {
+ _currentOrder = 0;
+ }
+ }
+ debug(7, "_currentOrder=%d/%d _currentPos=%d", _currentOrder, _numOrders, _currentPos);
+}
+
+void PCSoundFxPlayer::handlePattern(int channel, const byte *patternData) {
+ int instrument = patternData[2] >> 4;
+ if (instrument != 0) {
+ --instrument;
+ if (_instrumentsChannelTable[channel] != instrument || _fadeOutCounter != 0) {
+ _instrumentsChannelTable[channel] = instrument;
+ const int volume = _sfxData[instrument] - _fadeOutCounter;
+ _driver->setupChannel(channel, _instrumentsData[instrument], instrument, volume);
+ }
+ }
+ int16 freq = (int16)READ_BE_UINT16(patternData);
+ if (freq > 0) {
+ _driver->stopChannel(channel);
+ _driver->setChannelFrequency(channel, freq);
+ }
+}
+
+void PCSoundFxPlayer::unload() {
+ for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
+ free(_instrumentsData[i]);
+ _instrumentsData[i] = NULL;
+ }
+ free(_sfxData);
+ _sfxData = NULL;
+ _songPlayed = true;
+}
+
+void PCSoundFxPlayer::doSync(Common::Serializer &s) {
+ s.syncBytes((byte *)_musicName, 33);
+ uint16 v = (uint16)songLoaded();
+ s.syncAsSint16LE(v);
+
+ if (s.isLoading() && v) {
+ load(_musicName);
+
+ for (int i = 0; i < NUM_CHANNELS; ++i) {
+ _instrumentsChannelTable[i] = -1;
+ }
+ }
+
+ s.syncAsSint16LE(_songPlayed);
+ s.syncAsSint16LE(_looping);
+ s.syncAsSint16LE(_currentPos);
+ s.syncAsSint16LE(_currentOrder);
+ s.syncAsSint16LE(_playing);
+}
+
+PCSound::PCSound(Audio::Mixer *mixer, CruiseEngine *vm) {
+ _vm = vm;
+ _mixer = mixer;
+ _soundDriver = new AdlibSoundDriverADL(_mixer);
+ _player = new PCSoundFxPlayer(_soundDriver);
+}
+
+PCSound::~PCSound() {
+ delete _player;
+ delete _soundDriver;
+}
+
+void PCSound::loadMusic(const char *name) {
+ debugC(5, kCruiseDebugSound, "PCSound::loadMusic('%s')", name);
+ _player->load(name);
+}
+
+void PCSound::playMusic() {
+ debugC(5, kCruiseDebugSound, "PCSound::playMusic()");
+ _player->play();
+}
+
+void PCSound::stopMusic() {
+ debugC(5, kCruiseDebugSound, "PCSound::stopMusic()");
+ _player->stop();
+}
+
+void PCSound::removeMusic() {
+ debugC(5, kCruiseDebugSound, "PCSound::removeMusic()");
+ _player->unload();
+}
+
+void PCSound::fadeOutMusic() {
+ debugC(5, kCruiseDebugSound, "PCSound::fadeOutMusic()");
+ _player->fadeOut();
+}
+
+void PCSound::playSound(const uint8 *data, int size, int volume) {
+ debugC(5, kCruiseDebugSound, "PCSound::playSound() channel %d size %d", 4, size);
+ _soundDriver->playSample(data, size, 4, volume);
+}
+
+void PCSound::stopSound(int channel) {
+ debugC(5, kCruiseDebugSound, "PCSound::stopSound() channel %d", channel);
+ _soundDriver->resetChannel(channel);
+}
+
+void PCSound::stopChannel(int channel) {
+ debugC(5, kCruiseDebugSound, "PCSound::stopChannel() channel %d", channel);
+ _soundDriver->stopChannel(channel);
+}
+
+bool PCSound::isPlaying() const {
+ return _player->playing();
+}
+
+bool PCSound::songLoaded() const {
+ return _player->songLoaded();
+}
+
+bool PCSound::songPlayed() const {
+ return _player->songPlayed();
+}
+
+void PCSound::fadeSong() {
+ _player->fadeOut();
+}
+
+uint8 PCSound::numOrders() const {
+ return _player->numOrders();
+}
+
+void PCSound::setNumOrders(uint8 v) {
+ _player->setNumOrders(v);
+}
+
+void PCSound::setPattern(int offset, uint8 value) {
+ _player->setPattern(offset, value);
+}
+
+bool PCSound::musicLooping() const {
+ return _player->looping();
+}
+
+void PCSound::musicLoop(bool v) {
+ _player->setLooping(v);
+}
+
+void PCSound::startNote(int channel, int volume, int freq) {
+ warning("TODO: startNote");
+// _soundDriver->setVolume(channel, volume);
+ _soundDriver->setChannelFrequency(channel, freq);
+}
+
+void PCSound::doSync(Common::Serializer &s) {
+ _player->doSync(s);
+ s.syncAsSint16LE(_genVolume);
+}
+
+const char *PCSound::musicName() {
+ return _player->musicName();
+}
- free(tmp);
- return result;
+void PCSound::syncSounds() {
+ _soundDriver->syncSounds();
}
} // End of namespace Cruise
diff --git a/engines/cruise/sound.h b/engines/cruise/sound.h
index faf3df995d..13a6b2ac5a 100644
--- a/engines/cruise/sound.h
+++ b/engines/cruise/sound.h
@@ -29,62 +29,55 @@
#include "sound/mididrv.h"
#include "sound/midiparser.h"
#include "sound/mixer.h"
+
+#include "common/config-manager.h"
#include "common/serializer.h"
namespace Cruise {
-class MusicPlayer {
-private:
- byte _channelVolume[16];
- int _fadeVolume;
- char _musicName[33];
-
- bool _isPlaying;
- bool _songPlayed;
- bool _looping;
- byte _masterVolume;
-
- byte *_songPointer;
- // TODO: lib_SongSize
- int _songSize;
+class CruiseEngine;
+class PCSoundDriver;
+class PCSoundFxPlayer;
- void patchMidi(uint32 adr, const byte *data, int size);
- byte *loadInstrument(const char *name, int i);
+class PCSound {
+private:
+ Audio::Mixer *_mixer;
+ CruiseEngine *_vm;
+ int _genVolume;
+protected:
+ PCSoundDriver *_soundDriver;
+ PCSoundFxPlayer *_player;
public:
- MusicPlayer();
- ~MusicPlayer();
-
- void setVolume(int volume);
- int getVolume() const { return _masterVolume; }
-
- void stop();
- void pause();
- void resume();
-
- // Common public access methods
+ PCSound(Audio::Mixer *mixer, CruiseEngine *vm);
+ virtual ~PCSound();
+
+ virtual void loadMusic(const char *name);
+ virtual void playMusic();
+ virtual void stopMusic();
+ virtual void removeMusic();
+ virtual void fadeOutMusic();
+
+ virtual void playSound(const uint8 *data, int size, int volume);
+ virtual void stopSound(int channel);
+
void doSync(Common::Serializer &s);
- void loadSong(const char *name);
- void startSong();
- void stopSong();
- void removeSong();
+ const char *musicName();
+ void stopChannel(int channel);
+ bool isPlaying() const;
+ bool songLoaded() const;
+ bool songPlayed() const;
void fadeSong();
-
- bool songLoaded() const { return _songPointer != NULL; }
- bool songPlayed() const { return _songPlayed; }
- bool isPlaying() const { return _isPlaying; }
- bool looping() const { return _looping; }
- byte *songData() { return _songPointer; }
- void setPlaying(bool playing) { _isPlaying = playing; }
- void setLoop(bool loop) { _looping = loop; }
-};
-
-class SoundPlayer {
-public:
- SoundPlayer() {}
-
- void startSound(int channelNum, const byte *ptr, int size, int speed, int volume, bool loop) {}
- void startNote(int channelNum, int speed, int volume) {}
- void stopChannel(int channelNum) {}
+ uint8 numOrders() const;
+ void setNumOrders(uint8 v);
+ void setPattern(int offset, uint8 value);
+ bool musicLooping() const;
+ void musicLoop(bool v);
+ void startNote(int channel, int volume, int freq);
+ void syncSounds();
+
+ // Note: Volume variable accessed by these methods is never actually used in original game
+ void setVolume(int volume) { _genVolume = volume; }
+ uint8 getVolume() const { return _genVolume; }
};
} // End of namespace Cruise
diff --git a/engines/cruise/vars.cpp b/engines/cruise/vars.cpp
index 3ea591ed43..94fd00cbfd 100644
--- a/engines/cruise/vars.cpp
+++ b/engines/cruise/vars.cpp
@@ -79,6 +79,8 @@ int16 volumeNumberOfEntry;
int16 displayOn = 1;
+int16 protectionCode = 0;
+
int16 globalVars[2000];
dataFileEntry filesDatabase[NUM_FILE_ENTRIES];
diff --git a/engines/cruise/vars.h b/engines/cruise/vars.h
index 7208a8bea0..4bb94ff691 100644
--- a/engines/cruise/vars.h
+++ b/engines/cruise/vars.h
@@ -183,6 +183,8 @@ extern int16 volumeNumberOfEntry;
extern int16 displayOn;
+extern int16 protectionCode;
+
#define NUM_FILE_ENTRIES 257
extern int16 globalVars[2000];
diff --git a/engines/cruise/volume.cpp b/engines/cruise/volume.cpp
index fda3b6bc1f..2b8cce0f05 100644
--- a/engines/cruise/volume.cpp
+++ b/engines/cruise/volume.cpp
@@ -107,11 +107,8 @@ int getVolumeDataEntry(volumeDataStruct *entry) {
changeCursor(CURSOR_DISK);
- currentVolumeFile.read(&volumeNumberOfEntry, 2);
- currentVolumeFile.read(&volumeSizeOfEntry, 2);
-
- bigEndianShortToNative(&volumeNumberOfEntry);
- bigEndianShortToNative(&volumeSizeOfEntry);
+ volumeNumberOfEntry = currentVolumeFile.readSint16BE();
+ volumeSizeOfEntry = currentVolumeFile.readSint16BE();
volumeNumEntry = volumeNumberOfEntry;
@@ -129,16 +126,10 @@ int getVolumeDataEntry(volumeDataStruct *entry) {
for (i = 0; i < volumeNumEntry; i++) {
currentVolumeFile.read(&volumePtrToFileDescriptor[i].name, 14);
- currentVolumeFile.read(&volumePtrToFileDescriptor[i].offset, 4);
- currentVolumeFile.read(&volumePtrToFileDescriptor[i].size, 4);
- currentVolumeFile.read(&volumePtrToFileDescriptor[i].extSize, 4);
- currentVolumeFile.read(&volumePtrToFileDescriptor[i].unk3, 4);
- }
-
- for (i = 0; i < volumeNumEntry; i++) {
- bigEndianLongToNative(&volumePtrToFileDescriptor[i].offset);
- bigEndianLongToNative(&volumePtrToFileDescriptor[i].size);
- bigEndianLongToNative(&volumePtrToFileDescriptor[i].extSize);
+ volumePtrToFileDescriptor[i].offset = currentVolumeFile.readSint32BE();
+ volumePtrToFileDescriptor[i].size = currentVolumeFile.readSint32BE();
+ volumePtrToFileDescriptor[i].extSize = currentVolumeFile.readSint32BE();
+ volumePtrToFileDescriptor[i].unk3 = currentVolumeFile.readSint32BE();
}
strcpy(currentBaseName, entry->ident);
@@ -355,29 +346,23 @@ int16 readVolCnf(void) {
return (0);
}
- fileHandle.read(&numOfDisks, 2);
- bigEndianShortToNative(&numOfDisks);
-
- fileHandle.read(&sizeHEntry, 2);
- bigEndianShortToNative(&sizeHEntry); // size of one header entry - 20 bytes
+ numOfDisks = fileHandle.readSint16BE();
+ sizeHEntry = fileHandle.readSint16BE(); // size of one header entry - 20 bytes
for (i = 0; i < numOfDisks; i++) {
// fread(&volumeData[i],20,1,fileHandle);
fileHandle.read(&volumeData[i].ident, 10);
fileHandle.read(&volumeData[i].ptr, 4);
- fileHandle.read(&volumeData[i].diskNumber, 2);
- fileHandle.read(&volumeData[i].size, 4);
+ volumeData[i].diskNumber = fileHandle.readSint16BE();
+ volumeData[i].size = fileHandle.readSint32BE();
- bigEndianShortToNative(&volumeData[i].diskNumber);
debug(1, "Disk number: %d", volumeData[i].diskNumber);
- bigEndianLongToNative(&volumeData[i].size);
}
for (i = 0; i < numOfDisks; i++) {
dataFileName *ptr;
- fileHandle.read(&volumeData[i].size, 4);
- bigEndianLongToNative(&volumeData[i].size);
+ volumeData[i].size = fileHandle.readSint32BE();
ptr = (dataFileName *) mallocAndZero(volumeData[i].size);
diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp
index a37586aee6..f59fa80e8d 100644
--- a/engines/gob/dataio.cpp
+++ b/engines/gob/dataio.cpp
@@ -239,7 +239,7 @@ int16 DataIO::getChunk(const char *chunkName) {
}
dataDesc = _dataFiles[file];
- for (int16 chunk = 0; chunk < _numDataChunks[file]; chunk++, dataDesc++) {
+ for (uint16 chunk = 0; chunk < _numDataChunks[file]; chunk++, dataDesc++) {
if (scumm_stricmp(chunkName, dataDesc->chunkName) != 0)
continue;
@@ -334,7 +334,6 @@ uint32 DataIO::getChunkPos(int16 handle) const {
int32 DataIO::getChunkSize(const char *chunkName) {
int16 file;
- int16 chunk;
struct ChunkDesc *dataDesc;
int16 slot;
int32 realSize;
@@ -344,7 +343,7 @@ int32 DataIO::getChunkSize(const char *chunkName) {
return -1;
dataDesc = _dataFiles[file];
- for (chunk = 0; chunk < _numDataChunks[file]; chunk++, dataDesc++) {
+ for (uint16 chunk = 0; chunk < _numDataChunks[file]; chunk++, dataDesc++) {
if (scumm_stricmp(chunkName, dataDesc->chunkName) != 0)
continue;
@@ -488,6 +487,16 @@ int16 DataIO::openData(const char *path) {
return file_open(path);
}
+bool DataIO::existData(const char *path) {
+ int16 handle = openData(path);
+
+ if (handle < 0)
+ return false;
+
+ closeData(handle);
+ return true;
+}
+
DataStream *DataIO::openAsStream(int16 handle, bool dispose) {
uint32 curPos = getPos(handle);
seekData(handle, 0, SEEK_END);
@@ -575,6 +584,9 @@ byte *DataIO::getData(const char *path) {
}
DataStream *DataIO::getDataStream(const char *path) {
+ if (!path || (path[0] == '\0') || !existData(path))
+ return 0;
+
uint32 size = getDataSize(path);
byte *data = getData(path);
diff --git a/engines/gob/dataio.h b/engines/gob/dataio.h
index c67dc89df8..1f55cac90d 100644
--- a/engines/gob/dataio.h
+++ b/engines/gob/dataio.h
@@ -80,6 +80,7 @@ public:
byte *getUnpackedData(const char *name);
void closeData(int16 handle);
int16 openData(const char *path);
+ bool existData(const char *path);
DataStream *openAsStream(int16 handle, bool dispose = false);
int32 getDataSize(const char *name);
@@ -92,7 +93,7 @@ public:
protected:
Common::File _filesHandles[MAX_FILES];
struct ChunkDesc *_dataFiles[MAX_DATA_FILES];
- int16 _numDataChunks[MAX_DATA_FILES];
+ uint16 _numDataChunks[MAX_DATA_FILES];
int16 _dataFileHandles[MAX_DATA_FILES];
bool _dataFileItk[MAX_DATA_FILES];
int32 _chunkPos[MAX_SLOT_COUNT * MAX_DATA_FILES];
diff --git a/engines/gob/demos/demoplayer.cpp b/engines/gob/demos/demoplayer.cpp
index ede90af333..0229bb7515 100644
--- a/engines/gob/demos/demoplayer.cpp
+++ b/engines/gob/demos/demoplayer.cpp
@@ -123,7 +123,9 @@ void DemoPlayer::init() {
void DemoPlayer::clearScreen() {
debugC(1, kDebugDemo, "Clearing the screen");
- _vm->_video->clearScreen();
+ _vm->_video->clearSurf(*_vm->_draw->_backSurface);
+ _vm->_draw->forceBlit();
+ _vm->_video->retrace();
}
void DemoPlayer::playVideo(const char *fileName) {
diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp
index af64a53b60..9426c01ef2 100644
--- a/engines/gob/detection.cpp
+++ b/engines/gob/detection.cpp
@@ -61,13 +61,14 @@ static const PlainGameDescriptor gobGames[] = {
{"woodruff", "The Bizarre Adventures of Woodruff and the Schnibble"},
{"dynasty", "The Last Dynasty"},
{"urban", "Urban Runner"},
- {"archi", "Playtoon 1 - Uncle Archibald"},
- {"spirou", "Playtoon 2 - The Case of the Counterfeit Collaborator"},
- {"chato", "Playtoon 3 - The Secret of the Castle"},
- {"manda", "Playtoon 4 - The Mandarine Prince"},
- {"wakan", "Playtoon 5 - The Stone of Wakan"},
- {"playtnck2", "Playtoon Construction Kit 2 - Les chevaliers"},
- {"bambou", "Playtoon Limited Edition - Bambou le sauveur de la jungle"},
+ {"playtoons1", "Playtoons 1 - Uncle Archibald"},
+ {"playtoons2", "Playtoons 2 - The Case of the Counterfeit Collaborator"},
+ {"playtoons3", "Playtoons 3 - The Secret of the Castle"},
+ {"playtoons4", "Playtoons 4 - The Mandarine Prince"},
+ {"playtoons5", "Playtoons 5 - The Stone of Wakan"},
+ {"playtnck1", "Playtoons Construction Kit 1 - Monsters"},
+ {"playtnck2", "Playtoons Construction Kit 2 - Knights"},
+ {"bambou", "Playtoons Limited Edition - Bambou le sauveur de la jungle"},
{"fascination", "Fascination"},
{"geisha", "Geisha"},
{"adibou4", "Adibou v4"},
@@ -84,6 +85,7 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = {
namespace Gob {
using Common::GUIO_NOSPEECH;
+using Common::GUIO_NOSUBTITLES;
using Common::GUIO_NONE;
static const GOBGameDescription gameDescriptions[] = {
@@ -95,7 +97,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesEGA,
@@ -109,7 +111,7 @@ static const GOBGameDescription gameDescriptions[] = {
RU_RUS,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesEGA,
@@ -123,7 +125,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesNone,
@@ -137,7 +139,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_GRB,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesAdlib,
@@ -151,7 +153,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesCD,
@@ -165,7 +167,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesCD,
@@ -179,7 +181,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesCD,
@@ -193,7 +195,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesCD,
@@ -207,7 +209,7 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesCD,
@@ -221,7 +223,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesCD,
@@ -235,7 +237,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesCD,
@@ -249,7 +251,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesCD,
@@ -263,7 +265,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesCD,
@@ -277,7 +279,63 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
+ HU_HUN,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesCD,
@@ -291,7 +349,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformAmiga,
ADGF_DEMO,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesNone,
@@ -305,7 +363,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformPC,
ADGF_DEMO,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesNone,
@@ -319,7 +377,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformPC,
ADGF_DEMO,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesNone,
@@ -333,7 +391,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_DEMO,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesNone,
@@ -347,7 +405,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_ANY,
kPlatformMacintosh,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesNone,
@@ -361,7 +419,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_ANY,
kPlatformMacintosh,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesAdlib,
@@ -375,7 +433,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformMacintosh,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesAdlib,
@@ -389,7 +447,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformMacintosh,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesAdlib,
@@ -403,7 +461,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformMacintosh,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesAdlib,
@@ -417,13 +475,13 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformMacintosh,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesAdlib,
0, 0, 0
},
- {
+ { // Supplied by Hkz on #scummvm
{
"gob1",
"",
@@ -435,7 +493,151 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformWindows,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ IT_ITA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ IT_ITA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesAdlib,
@@ -453,7 +655,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformWindows,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesAdlib,
@@ -467,7 +669,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_ANY,
kPlatformAmiga,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesNone,
@@ -481,7 +683,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformAmiga,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesNone,
@@ -495,7 +697,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformAmiga,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesNone,
@@ -509,7 +711,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformAtariST,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesNone,
@@ -527,7 +729,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformMacintosh,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -545,7 +747,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformMacintosh,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -559,7 +761,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_GRB,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -573,7 +775,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -587,7 +789,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -601,7 +803,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -615,7 +817,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -629,7 +831,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -643,7 +845,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -657,7 +859,7 @@ static const GOBGameDescription gameDescriptions[] = {
RU_RUS,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -671,7 +873,7 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -685,7 +887,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesCD,
@@ -699,7 +901,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_ANY,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesCD,
@@ -713,7 +915,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesCD,
@@ -727,7 +929,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesCD,
@@ -741,7 +943,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesCD,
@@ -755,7 +957,77 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob2cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
+ HU_HUN,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob2cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob2cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob2cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob2cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesCD,
@@ -769,7 +1041,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformPC,
ADGF_DEMO,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -783,7 +1055,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformPC,
ADGF_DEMO,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -797,7 +1069,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformAmiga,
ADGF_DEMO,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesNone,
@@ -811,7 +1083,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformAmiga,
ADGF_DEMO,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesNone,
@@ -829,7 +1101,43 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformWindows,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {0, 0, 0, 0}
+ },
+ EN_USA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -847,7 +1155,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformWindows,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -865,7 +1173,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_GRB,
kPlatformAmiga,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWeen,
kFeaturesNone,
@@ -879,7 +1187,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformAmiga,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWeen,
kFeaturesNone,
@@ -893,7 +1201,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformAmiga,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWeen,
kFeaturesNone,
@@ -907,7 +1215,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformAmiga,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWeen,
kFeaturesNone,
@@ -925,7 +1233,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformAmiga,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWeen,
kFeaturesNone,
@@ -943,7 +1251,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_GRB,
kPlatformAtariST,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWeen,
kFeaturesNone,
@@ -957,7 +1265,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformAtariST,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWeen,
kFeaturesNone,
@@ -971,7 +1279,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_GRB,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWeen,
kFeaturesAdlib,
@@ -985,7 +1293,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWeen,
kFeaturesAdlib,
@@ -999,7 +1307,7 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWeen,
kFeaturesAdlib,
@@ -1013,7 +1321,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWeen,
kFeaturesAdlib,
@@ -1027,7 +1335,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWeen,
kFeaturesAdlib,
@@ -1041,7 +1349,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWeen,
kFeaturesAdlib,
@@ -1055,7 +1363,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformPC,
ADGF_DEMO,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWeen,
kFeaturesAdlib,
@@ -1069,7 +1377,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformPC,
ADGF_DEMO,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWeen,
kFeaturesAdlib,
@@ -1083,7 +1391,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeBargon,
kFeaturesNone,
@@ -1097,7 +1405,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformAtariST,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeBargon,
kFeaturesNone,
@@ -1111,7 +1419,7 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeBargon,
kFeaturesNone,
@@ -1125,7 +1433,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeBargon,
kFeaturesNone,
@@ -1139,7 +1447,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_ANY,
kPlatformAmiga,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeBargon,
kFeaturesNone,
@@ -1153,7 +1461,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeBargon,
kFeaturesNone,
@@ -1167,7 +1475,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeBargon,
kFeaturesNone,
@@ -1181,7 +1489,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_GRB,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib | kFeaturesEGA,
@@ -1195,7 +1503,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib | kFeaturesEGA,
@@ -1209,7 +1517,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib | kFeaturesEGA,
@@ -1223,7 +1531,7 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib | kFeaturesEGA,
@@ -1237,7 +1545,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib | kFeaturesEGA,
@@ -1255,7 +1563,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformAmiga,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesNone,
@@ -1269,7 +1577,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_ANY,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -1283,7 +1591,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesAdlib,
@@ -1297,7 +1605,7 @@ static const GOBGameDescription gameDescriptions[] = {
HB_ISR,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesAdlib,
@@ -1311,7 +1619,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesAdlib,
@@ -1325,7 +1633,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesAdlib,
@@ -1339,7 +1647,7 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesAdlib,
@@ -1357,7 +1665,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformMacintosh,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesAdlib,
@@ -1371,7 +1679,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesCD,
@@ -1385,7 +1693,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesCD,
@@ -1399,7 +1707,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesCD,
@@ -1413,7 +1721,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesCD,
@@ -1427,7 +1735,7 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesCD,
@@ -1441,7 +1749,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_GRB,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesCD,
@@ -1455,7 +1763,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesCD,
@@ -1469,7 +1777,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesCD,
@@ -1483,7 +1791,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesCD,
@@ -1497,7 +1805,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesCD,
@@ -1511,7 +1819,7 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesCD,
@@ -1525,7 +1833,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_GRB,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesCD,
@@ -1536,10 +1844,38 @@ static const GOBGameDescription gameDescriptions[] = {
"lostintime",
"",
AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330),
- UNK_LANG,
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ {
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330),
+ FR_FRA,
kPlatformWindows,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ {
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330),
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesAdlib,
@@ -1553,7 +1889,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_ANY,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES
},
kGameTypeFascination,
kFeaturesCD,
@@ -1567,7 +1903,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeFascination,
kFeaturesAdlib,
@@ -1581,14 +1917,13 @@ static const GOBGameDescription gameDescriptions[] = {
HB_ISR,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeFascination,
kFeaturesAdlib,
"intro.stk", 0, 0
},
- //Provided by Sanguine
- {
+ { // Supplied by sanguine
{
"fascination",
"VGA 3 disks edition",
@@ -1596,7 +1931,21 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeFascination,
+ kFeaturesAdlib,
+ "disk0.stk", 0, 0
+ },
+ { // Supplied by windlepoons in bug report #2809247
+ {
+ "fascination",
+ "VGA 3 disks edition",
+ AD_ENTRY1s("disk0.stk", "3a24e60a035250189643c86a9ceafb97", 1062480),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeFascination,
kFeaturesAdlib,
@@ -1610,7 +1959,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeFascination,
kFeaturesAdlib,
@@ -1624,7 +1973,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformAmiga,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeFascination,
kFeaturesNone,
@@ -1638,7 +1987,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_ANY,
kPlatformAmiga,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeFascination,
kFeaturesNone,
@@ -1652,7 +2001,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformAmiga,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeFascination,
kFeaturesNone,
@@ -1666,7 +2015,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformAmiga,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeFascination,
kFeaturesNone,
@@ -1680,7 +2029,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGeisha,
kFeaturesNone,
@@ -1694,7 +2043,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGeisha,
kFeaturesNone,
@@ -1708,7 +2057,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformPC,
ADGF_DEMO,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesAdlib,
@@ -1722,7 +2071,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformPC,
ADGF_DEMO,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesAdlib,
@@ -1736,7 +2085,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_GRB,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -1750,7 +2099,7 @@ static const GOBGameDescription gameDescriptions[] = {
HB_ISR,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -1764,7 +2113,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_GRB,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -1782,7 +2131,43 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformWindows,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104},
+ {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104},
+ {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
+ {0, 0, 0, 0}
+ },
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -1800,7 +2185,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_GRB,
kPlatformMacintosh,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -1814,7 +2199,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -1828,7 +2213,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -1842,7 +2227,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -1856,7 +2241,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -1870,7 +2255,7 @@ static const GOBGameDescription gameDescriptions[] = {
RU_RUS,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -1884,7 +2269,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -1898,7 +2283,7 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -1912,7 +2297,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_GRB,
kPlatformAmiga,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesNone,
@@ -1926,7 +2311,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformAmiga,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesNone,
@@ -1940,7 +2325,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesCD,
@@ -1954,7 +2339,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_ANY,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesCD,
@@ -1968,7 +2353,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesCD,
@@ -1982,7 +2367,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesCD,
@@ -1996,7 +2381,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesCD,
@@ -2010,7 +2395,63 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
+ HU_HUN,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesCD,
@@ -2024,7 +2465,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_DEMO,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -2038,7 +2479,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_DEMO,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -2052,7 +2493,7 @@ static const GOBGameDescription gameDescriptions[] = {
UNK_LANG,
kPlatformPC,
ADGF_DEMO,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -2066,7 +2507,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_ANY,
kPlatformPC,
ADGF_DEMO,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -2084,7 +2525,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformWindows,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -2098,7 +2539,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeInca2,
kFeaturesCD,
@@ -2112,7 +2553,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeInca2,
kFeaturesCD,
@@ -2126,7 +2567,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeInca2,
kFeaturesCD,
@@ -2140,7 +2581,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeInca2,
kFeaturesCD,
@@ -2154,7 +2595,7 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeInca2,
kFeaturesCD,
@@ -2168,7 +2609,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeInca2,
kFeaturesAdlib,
@@ -2182,7 +2623,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeInca2,
kFeaturesAdlib,
@@ -2196,7 +2637,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeInca2,
kFeaturesAdlib,
@@ -2210,7 +2651,63 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformWindows,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
+ IT_ITA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesAdlib,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeInca2,
kFeaturesAdlib,
@@ -2237,7 +2734,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_ANY,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeInca2,
kFeaturesAdlib | kFeaturesBATDemo,
@@ -2251,7 +2748,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_GRB,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2265,7 +2762,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2279,7 +2776,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2293,7 +2790,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2307,7 +2804,7 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2321,7 +2818,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_GRB,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2335,7 +2832,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2349,7 +2846,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2363,7 +2860,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2377,7 +2874,7 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2391,7 +2888,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2405,7 +2902,7 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2419,7 +2916,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_GRB,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2433,7 +2930,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2447,7 +2944,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2461,7 +2958,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2475,7 +2972,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2489,7 +2986,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2503,7 +3000,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2517,7 +3014,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_GRB,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2531,7 +3028,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2545,7 +3042,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2559,7 +3056,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2573,7 +3070,7 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2587,7 +3084,7 @@ static const GOBGameDescription gameDescriptions[] = {
PL_POL,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -2605,7 +3102,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_ANY,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640 | kFeaturesSCNDemo,
@@ -2619,7 +3116,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeDynasty,
kFeatures640,
@@ -2633,7 +3130,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeDynasty,
kFeatures640,
@@ -2647,7 +3144,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeDynasty,
kFeatures640,
@@ -2661,7 +3158,21 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeDynasty,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "dynasty",
+ "",
+ AD_ENTRY1s("intro.stk", "bdbdac8919200a5e71ffb9fb0709f704", 2446652),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeDynasty,
kFeatures640,
@@ -2717,7 +3228,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_USA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeUrban,
kFeatures640,
@@ -2731,7 +3242,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeUrban,
kFeatures640,
@@ -2745,7 +3256,7 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeUrban,
kFeatures640,
@@ -2759,7 +3270,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeUrban,
kFeatures640,
@@ -2786,7 +3297,7 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "archi",
+ "playtoons1",
"",
{
{"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338},
@@ -2796,7 +3307,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640,
@@ -2804,8 +3315,8 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "archi",
- "Pack mes histoires animées",
+ "playtoons1",
+ "Pack mes histoires anim\xE9""es",
{
{"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474},
{"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674},
@@ -2814,7 +3325,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640,
@@ -2822,7 +3333,7 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "archi",
+ "playtoons1",
"",
{
{"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926},
@@ -2832,7 +3343,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640,
@@ -2840,7 +3351,7 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "archi",
+ "playtoons1",
"Non-Interactive Demo",
{
{"play123.scn", 0, "4689a31f543915e488c3bc46ea358add", 258},
@@ -2855,7 +3366,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_ANY,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640 | kFeaturesSCNDemo,
@@ -2863,7 +3374,7 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "archi",
+ "playtoons1",
"Non-Interactive Demo",
{
{"e.scn", 0, "8a0db733c3f77be86e74e8242e5caa61", 124},
@@ -2873,7 +3384,7 @@ static const GOBGameDescription gameDescriptions[] = {
EN_ANY,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640 | kFeaturesSCNDemo,
@@ -2881,7 +3392,7 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "archi",
+ "playtoons1",
"Non-Interactive Demo",
{
{"i.scn", 0, "8b3294474d39970463663edd22341730", 285},
@@ -2895,7 +3406,7 @@ static const GOBGameDescription gameDescriptions[] = {
IT_ITA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640 | kFeaturesSCNDemo,
@@ -2903,7 +3414,7 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "archi",
+ "playtoons1",
"Non-Interactive Demo",
{
{"s.scn", 0, "1f527010626b5490761f16ba7a6f639a", 251},
@@ -2916,7 +3427,7 @@ static const GOBGameDescription gameDescriptions[] = {
ES_ESP,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640 | kFeaturesSCNDemo,
@@ -2924,7 +3435,7 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "spirou",
+ "playtoons2",
"",
{
{"playtoon.stk", 0, "55a85036dd93cce93532d8f743d90074", 17467154},
@@ -2934,7 +3445,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640,
@@ -2942,7 +3453,7 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "spirou",
+ "playtoons2",
"",
{
{"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926},
@@ -2952,7 +3463,7 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640,
@@ -2960,7 +3471,7 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "chato",
+ "playtoons3",
"",
{
{"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338},
@@ -2970,7 +3481,25 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoon,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ {
+ {
+ "playtoons3",
+ "",
+ {
+ {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506},
+ {"chato.stk", 0, "8fc8d0da5b3e758908d1d7298d497d0b", 6041026},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640,
@@ -2978,8 +3507,8 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "chato",
- "Pack mes histoires animées",
+ "playtoons3",
+ "Pack mes histoires anim\xE9""es",
{
{"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474},
{"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793},
@@ -2988,7 +3517,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640,
@@ -2996,7 +3525,7 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "chato",
+ "playtoons3",
"",
{
{"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926},
@@ -3006,7 +3535,26 @@ static const GOBGameDescription gameDescriptions[] = {
DE_DEU,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoon,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+
+ {
+ {
+ "playtoons4",
+ "",
+ {
+ {"playtoon.stk", 0, "b7f5afa2dc1b0f75970b7c07d175db1b", 24340406},
+ {"manda.stk", 0, "92529e0b927191d9898a34c2892e9a3a", 6485072},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640,
@@ -3014,7 +3562,7 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "wakan",
+ "playtoons5",
"",
{
{"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474},
@@ -3024,7 +3572,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640,
@@ -3042,11 +3590,29 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeBambou,
kFeatures640,
- 0, 0, 0
+ "intro.stk", "intro.tot", 0
+ },
+ {
+ {
+ "playtnck1",
+ "",
+ {
+ {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024},
+ {"dan.itk", 0, "906d67b3e438d5e95ec7ea9e781a94f3", 3000320},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytnCk,
+ kFeatures640,
+ "intro2.stk", 0, 0
},
{
{
@@ -3054,12 +3620,13 @@ static const GOBGameDescription gameDescriptions[] = {
"",
{
{"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024},
+ {"dan.itk", 0, "74eeb075bd2cb47b243349730264af01", 3213312},
{0, 0, 0, 0}
},
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytnCk,
kFeatures640,
@@ -3073,7 +3640,7 @@ static const GOBGameDescription gameDescriptions[] = {
FR_FRA,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NONE
},
kGameTypeAdibou4,
kFeatures640,
@@ -3207,7 +3774,7 @@ static const GOBGameDescription gameDescriptions[] = {
{
{
"adibouunknown",
- "ADIBÙ 2 Ambiente",
+ "ADIB\xD9 2 Ambiente",
AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958),
IT_ITA,
kPlatformPC,
@@ -3221,7 +3788,7 @@ static const GOBGameDescription gameDescriptions[] = {
{
{
"adibouunknown",
- "ADIBÙ prima elementare : Imparo a leggere e a contare",
+ "ADIB\xD9 prima elementare : Imparo a leggere e a contare",
{
{"intro.stk", 0, "092707829555f27706920e4cacf1fada", 8737958},
{"appbou2.itk", 0, "f7bf045f6bdce5a7607c720e36704f33", 200005632},
@@ -3239,7 +3806,7 @@ static const GOBGameDescription gameDescriptions[] = {
{
{
"adibouunknown",
- "ADIBOU présente La Magie (STK2.1/OBC)",
+ "ADIBOU pr\xE9sente La Magie (STK2.1/OBC)",
{
{"adibou.stk", 0, "977d2449d398f3df23238d718fca35b5", 61097},
{"magic.stk", 0, "9776765dead3e338a32c43bf344b5819", 302664},
@@ -3320,7 +3887,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesNone,
@@ -3334,7 +3901,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob1,
kFeaturesCD,
@@ -3348,7 +3915,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -3362,7 +3929,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformMacintosh,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesAdlib,
@@ -3376,7 +3943,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob2,
kFeaturesCD,
@@ -3390,7 +3957,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeBargon,
kFeaturesNone,
@@ -3404,7 +3971,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesAdlib,
@@ -3418,7 +3985,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGob3,
kFeaturesCD,
@@ -3432,7 +3999,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeWoodruff,
kFeatures640,
@@ -3446,7 +4013,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesAdlib,
@@ -3460,7 +4027,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformMacintosh,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesAdlib,
@@ -3474,7 +4041,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeLostInTime,
kFeaturesCD,
@@ -3488,7 +4055,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NONE
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeUrban,
kFeaturesCD,
@@ -3496,13 +4063,13 @@ static const GOBGameDescription fallbackDescs[] = {
},
{
{
- "archi",
+ "playtoons1",
"unknown",
AD_ENTRY1(0, 0),
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640,
@@ -3510,13 +4077,13 @@ static const GOBGameDescription fallbackDescs[] = {
},
{
{
- "spirou",
+ "playtoons2",
"unknown",
AD_ENTRY1(0, 0),
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640,
@@ -3524,13 +4091,13 @@ static const GOBGameDescription fallbackDescs[] = {
},
{
{
- "chato",
+ "playtoons3",
"unknown",
AD_ENTRY1(0, 0),
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640,
@@ -3538,13 +4105,13 @@ static const GOBGameDescription fallbackDescs[] = {
},
{
{
- "manda",
+ "playtoons4",
"unknown",
AD_ENTRY1(0, 0),
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640,
@@ -3552,13 +4119,13 @@ static const GOBGameDescription fallbackDescs[] = {
},
{
{
- "wakan",
+ "playtoons5",
"unknown",
AD_ENTRY1(0, 0),
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytoon,
kFeatures640,
@@ -3572,7 +4139,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypePlaytnCk,
kFeatures640,
@@ -3586,7 +4153,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeBambou,
kFeatures640,
@@ -3600,7 +4167,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeFascination,
kFeaturesNone,
@@ -3614,7 +4181,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGeisha,
kFeaturesNone,
@@ -3628,7 +4195,7 @@ static const GOBGameDescription fallbackDescs[] = {
UNK_LANG,
kPlatformPC,
ADGF_NO_FLAGS,
- GUIO_NOSPEECH
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeAdibou4,
kFeatures640,
diff --git a/engines/gob/draw.cpp b/engines/gob/draw.cpp
index 8619e08e8b..b3e5e7418c 100644
--- a/engines/gob/draw.cpp
+++ b/engines/gob/draw.cpp
@@ -30,6 +30,7 @@
#include "gob/global.h"
#include "gob/util.h"
#include "gob/game.h"
+#include "gob/script.h"
#include "gob/inter.h"
#include "gob/video.h"
#include "gob/palanim.h"
@@ -389,11 +390,10 @@ void Draw::printTextCentered(int16 id, int16 left, int16 top, int16 right,
adjustCoords(1, &left, &top);
adjustCoords(1, &right, &bottom);
- if (READ_LE_UINT16(_vm->_game->_totFileData + 0x7E) != 0) {
- byte *storedIP = _vm->_global->_inter_execPtr;
+ uint16 centerOffset = _vm->_game->_script->getFunctionOffset(TOTFile::kFunctionCenter);
+ if (centerOffset != 0) {
+ _vm->_game->_script->call(centerOffset);
- _vm->_global->_inter_execPtr = _vm->_game->_totFileData +
- READ_LE_UINT16(_vm->_game->_totFileData + 0x7E);
WRITE_VAR(17, (uint32) id);
WRITE_VAR(18, (uint32) left);
WRITE_VAR(19, (uint32) top);
@@ -401,7 +401,7 @@ void Draw::printTextCentered(int16 id, int16 left, int16 top, int16 right,
WRITE_VAR(21, (uint32) (bottom - top + 1));
_vm->_inter->funcBlock(0);
- _vm->_global->_inter_execPtr = storedIP;
+ _vm->_game->_script->pop();
}
if (str[0] == '\0')
diff --git a/engines/gob/draw_v1.cpp b/engines/gob/draw_v1.cpp
index de71f20142..94ee32a031 100644
--- a/engines/gob/draw_v1.cpp
+++ b/engines/gob/draw_v1.cpp
@@ -32,6 +32,7 @@
#include "gob/global.h"
#include "gob/util.h"
#include "gob/game.h"
+#include "gob/resources.h"
#include "gob/scenery.h"
#include "gob/inter.h"
#include "gob/sound/sound.h"
@@ -173,12 +174,12 @@ void Draw_v1::printTotText(int16 id) {
_vm->_sound->cdPlayMultMusic();
- if (!_vm->_game->_totTextData || !_vm->_game->_totTextData->dataPtr)
+ TextItem *textItem = _vm->_game->_resources->getTextItem(id);
+ if (!textItem)
return;
- dataPtr = _vm->_game->_totTextData->dataPtr +
- _vm->_game->_totTextData->items[id].offset;
- ptr = dataPtr;
+ dataPtr = textItem->getData();
+ ptr = dataPtr;
destX = READ_LE_UINT16(ptr) & 0x7FFF;
destY = READ_LE_UINT16(ptr + 2);
@@ -312,7 +313,9 @@ void Draw_v1::printTotText(int16 id) {
}
}
+ delete textItem;
_renderFlags = savedFlags;
+
if (_renderFlags & RENDERFLAG_COLLISIONS)
_vm->_game->checkCollisions(0, 0, 0, 0);
@@ -323,11 +326,10 @@ void Draw_v1::printTotText(int16 id) {
}
void Draw_v1::spriteOperation(int16 operation) {
- uint16 id;
- byte *dataBuf;
int16 len;
int16 x, y;
int16 perLine;
+ Resource *resource;
if (_sourceSurface >= 100)
_sourceSurface -= 80;
@@ -396,30 +398,20 @@ void Draw_v1::spriteOperation(int16 operation) {
break;
case DRAW_LOADSPRITE:
- id = _spriteLeft;
- if (id >= 30000) {
- dataBuf =
- _vm->_game->loadExtData(id, &_spriteRight, &_spriteBottom);
- _vm->_video->drawPackedSprite(dataBuf,
- _spriteRight, _spriteBottom,
- _destSpriteX, _destSpriteY,
- _transparency, *_spritesArray[_destSurface]);
- dirtiedRect(_destSurface, _destSpriteX, _destSpriteY,
- _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1);
- delete[] dataBuf;
- break;
- }
+ resource = _vm->_game->_resources->getResource((uint16) _spriteLeft,
+ &_spriteRight, &_spriteBottom);
- if (!(dataBuf = _vm->_game->loadTotResource(id, 0, &_spriteRight, &_spriteBottom)))
+ if (!resource)
break;
- _vm->_video->drawPackedSprite(dataBuf,
- _spriteRight, _spriteBottom,
- _destSpriteX, _destSpriteY,
- _transparency, *_spritesArray[_destSurface]);
+ _vm->_video->drawPackedSprite(resource->getData(),
+ _spriteRight, _spriteBottom, _destSpriteX, _destSpriteY,
+ _transparency, *_spritesArray[_destSurface]);
dirtiedRect(_destSurface, _destSpriteX, _destSpriteY,
_destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1);
+
+ delete resource;
break;
case DRAW_PRINTTEXT:
diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp
index 4bb8120e3a..2843456f42 100644
--- a/engines/gob/draw_v2.cpp
+++ b/engines/gob/draw_v2.cpp
@@ -32,6 +32,8 @@
#include "gob/global.h"
#include "gob/util.h"
#include "gob/game.h"
+#include "gob/script.h"
+#include "gob/resources.h"
#include "gob/scenery.h"
#include "gob/inter.h"
#include "gob/video.h"
@@ -205,12 +207,6 @@ void Draw_v2::printTotText(int16 id) {
id &= 0xFFF;
- if (!_vm->_game->_totTextData || !_vm->_game->_totTextData->dataPtr ||
- (id >= _vm->_game->_totTextData->itemsCount) ||
- (_vm->_game->_totTextData->items[id].offset == -1) ||
- (_vm->_game->_totTextData->items[id].size == 0))
- return;
-
_vm->validateLanguage();
// WORKAROUND: In the scripts of some Gobliins 2 versions, the dialog text IDs
@@ -234,13 +230,18 @@ void Draw_v2::printTotText(int16 id) {
}
- size = _vm->_game->_totTextData->items[id].size;
- dataPtr = _vm->_game->_totTextData->dataPtr +
- _vm->_game->_totTextData->items[id].offset;
- ptr = dataPtr;
+ TextItem *textItem = _vm->_game->_resources->getTextItem(id);
+ if (!textItem)
+ return;
- if ((_renderFlags & RENDERFLAG_SKIPOPTIONALTEXT) && (ptr[1] & 0x80))
+ size = textItem->getSize();
+ dataPtr = textItem->getData();
+ ptr = dataPtr;
+
+ if ((_renderFlags & RENDERFLAG_SKIPOPTIONALTEXT) && (ptr[1] & 0x80)) {
+ delete textItem;
return;
+ }
if (_renderFlags & RENDERFLAG_DOUBLECOORDS) {
destX = (READ_LE_UINT16(ptr) & 0x7FFF) * 2;
@@ -328,7 +329,7 @@ void Draw_v2::printTotText(int16 id) {
ptrEnd = ptr;
while (((ptrEnd - dataPtr) < size) && (*ptrEnd != 1)) {
// Converting to unknown commands/characters to spaces
- if ((_vm->_game->_totFileData[0x29] < 0x32) && (*ptrEnd > 3) && (*ptrEnd < 32))
+ if ((_vm->_game->_script->getVersionMinor() < 2) && (*ptrEnd > 3) && (*ptrEnd < 32))
*ptrEnd = 32;
switch (*ptrEnd) {
@@ -524,7 +525,7 @@ void Draw_v2::printTotText(int16 id) {
case 10:
str[0] = (char) 255;
WRITE_LE_UINT16((uint16 *) (str + 1),
- ptr - _vm->_game->_totTextData->dataPtr);
+ ptr - _vm->_game->_resources->getTexts());
str[3] = 0;
ptr++;
for (int i = *ptr++; i > 0; i--) {
@@ -597,7 +598,9 @@ void Draw_v2::printTotText(int16 id) {
}
}
+ delete textItem;
_renderFlags = savedFlags;
+
if (!(_renderFlags & RENDERFLAG_COLLISIONS))
return;
@@ -610,14 +613,13 @@ void Draw_v2::printTotText(int16 id) {
}
void Draw_v2::spriteOperation(int16 operation) {
- uint16 id;
- byte *dataBuf;
int16 len;
int16 x, y;
SurfaceDescPtr sourceSurf, destSurf;
bool deltaVeto;
int16 left;
int16 ratio;
+ Resource *resource;
// Always assigned to -1 in Game::loadTotFile()
int16 someHandle = -1;
@@ -705,6 +707,11 @@ void Draw_v2::spriteOperation(int16 operation) {
sourceSurf = _spritesArray[_sourceSurface];
destSurf = _spritesArray[_destSurface];
+ if (!destSurf) {
+ warning("Can't do operation %d on surface %d: nonexistent", operation, _destSurface);
+ return;
+ }
+
switch (operation) {
case DRAW_BLITSURF:
case DRAW_DRAWLETTER:
@@ -755,41 +762,20 @@ void Draw_v2::spriteOperation(int16 operation) {
break;
case DRAW_LOADSPRITE:
- id = _spriteLeft;
-
- if ((id >= 30000) || (_vm->_game->_lomHandle >= 0)) {
- dataBuf = 0;
+ resource = _vm->_game->_resources->getResource((uint16) _spriteLeft,
+ &_spriteRight, &_spriteBottom);
- if (_vm->_game->_lomHandle >= 0)
- warning("Urban Stub: LOADSPRITE %d, LOM", id);
- else
- dataBuf = _vm->_game->loadExtData(id, &_spriteRight, &_spriteBottom);
-
- if (!dataBuf)
- break;
-
- _vm->_video->drawPackedSprite(dataBuf,
- _spriteRight, _spriteBottom, _destSpriteX, _destSpriteY,
- _transparency, *_spritesArray[_destSurface]);
-
- dirtiedRect(_destSurface, _destSpriteX, _destSpriteY,
- _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1);
-
- delete[] dataBuf;
+ if (!resource)
break;
- }
- // Load from .TOT resources
- if (!(dataBuf = _vm->_game->loadTotResource(id, 0, &_spriteRight, &_spriteBottom)))
- break;
-
- _vm->_video->drawPackedSprite(dataBuf,
- _spriteRight, _spriteBottom,
- _destSpriteX, _destSpriteY,
- _transparency, *_spritesArray[_destSurface]);
+ _vm->_video->drawPackedSprite(resource->getData(),
+ _spriteRight, _spriteBottom, _destSpriteX, _destSpriteY,
+ _transparency, *_spritesArray[_destSurface]);
dirtiedRect(_destSurface, _destSpriteX, _destSpriteY,
_destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1);
+
+ delete resource;
break;
case DRAW_PRINTTEXT:
@@ -802,7 +788,7 @@ void Draw_v2::spriteOperation(int16 operation) {
if (((int8) _textToPrint[0]) == -1) {
_vm->validateLanguage();
- dataBuf = _vm->_game->_totTextData->dataPtr + _textToPrint[1] + 1;
+ byte *dataBuf = _vm->_game->_resources->getTexts() + _textToPrint[1] + 1;
len = *dataBuf++;
for (int i = 0; i < len; i++, dataBuf += 2) {
_vm->_video->drawLetter(READ_LE_UINT16(dataBuf), _destSpriteX,
diff --git a/engines/gob/expression.cpp b/engines/gob/expression.cpp
new file mode 100644
index 0000000000..61376b2212
--- /dev/null
+++ b/engines/gob/expression.cpp
@@ -0,0 +1,1144 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+
+#include "gob/gob.h"
+#include "gob/expression.h"
+#include "gob/global.h"
+#include "gob/game.h"
+#include "gob/script.h"
+#include "gob/inter.h"
+
+namespace Gob {
+
+Expression::Stack::Stack(size_t size) {
+ opers = new byte[size];
+ values = new int32[size];
+ memset(opers , 0, size * sizeof(byte ));
+ memset(values, 0, size * sizeof(int32));
+}
+
+Expression::Stack::~Stack() {
+ delete[] opers;
+ delete[] values;
+}
+
+Expression::StackFrame::StackFrame(const Stack &stack) {
+ opers = stack.opers - 1;
+ values = stack.values - 1;
+ pos = -1;
+}
+
+void Expression::StackFrame::push(int count) {
+ opers += count;
+ values += count;
+ pos += count;
+}
+
+void Expression::StackFrame::pop(int count) {
+ opers -= count;
+ values -= count;
+ pos -= count;
+}
+
+Expression::Expression(GobEngine *vm) : _vm(vm) {
+ _resultStr[0] = 0;
+ _resultInt = 0;
+}
+
+int32 Expression::encodePtr(byte *ptr, int type) {
+ int32 offset = 0;
+
+ switch (type) {
+ case kExecPtr:
+ offset = _vm->_game->_script->getOffset(ptr);
+ break;
+ case kInterVar:
+ offset = ptr - ((byte *) _vm->_inter->_variables->getAddressOff8(0));
+ break;
+ case kResStr:
+ offset = ptr - ((byte *) _resultStr);
+ break;
+ default:
+ error("Expression::encodePtr(): Unknown pointer type");
+ }
+ assert((offset & 0xF0000000) == 0);
+ return (type << 28) | offset;
+}
+
+byte *Expression::decodePtr(int32 n) {
+ byte *ptr;
+
+ switch (n >> 28) {
+ case kExecPtr:
+ return _vm->_game->_script->getData((n & 0x0FFFFFFF));
+ case kInterVar:
+ ptr = (byte *) _vm->_inter->_variables->getAddressOff8(0);
+ break;
+ case kResStr:
+ ptr = (byte *) _resultStr;
+ break;
+ default:
+ error("Expression::decodePtr(): Unknown pointer type");
+ }
+ return ptr + (n & 0x0FFFFFFF);
+}
+
+void Expression::skipExpr(char stopToken) {
+ int16 dimCount;
+ byte operation;
+ int16 num;
+ int16 dim;
+
+ num = 0;
+ while (true) {
+ operation = _vm->_game->_script->readByte();
+
+ if ((operation >= 14) && (operation <= OP_FUNC)) {
+ switch (operation) {
+ case 14:
+ _vm->_game->_script->skip(4);
+ if (_vm->_game->_script->peekByte() == 97)
+ _vm->_game->_script->skip(1);
+ break;
+
+ case OP_LOAD_VAR_INT16:
+ case OP_LOAD_VAR_INT8:
+ case OP_LOAD_IMM_INT16:
+ case OP_LOAD_VAR_INT32:
+ case OP_LOAD_VAR_INT32_AS_INT16:
+ _vm->_game->_script->skip(2);
+ break;
+
+ case OP_LOAD_IMM_INT32:
+ _vm->_game->_script->skip(4);
+ break;
+
+ case OP_LOAD_IMM_INT8:
+ _vm->_game->_script->skip(1);
+ break;
+
+ case OP_LOAD_IMM_STR:
+ _vm->_game->_script->skip(strlen(_vm->_game->_script->peekString()) + 1);
+ break;
+
+ case OP_LOAD_VAR_STR:
+ _vm->_game->_script->skip(2);
+ if (_vm->_game->_script->peekByte() == 13) {
+ _vm->_game->_script->skip(1);
+ skipExpr(OP_END_MARKER);
+ }
+ break;
+
+ case 15:
+ _vm->_game->_script->skip(2);
+
+ case OP_ARRAY_INT8:
+ case OP_ARRAY_INT32:
+ case OP_ARRAY_INT16:
+ case OP_ARRAY_STR:
+ dimCount = _vm->_game->_script->peekByte(2);
+ // skip header and dimensions
+ _vm->_game->_script->skip(3 + dimCount);
+ // skip indices
+ for (dim = 0; dim < dimCount; dim++)
+ skipExpr(OP_END_MARKER);
+
+ if ((operation == OP_ARRAY_STR) && (_vm->_game->_script->peekByte() == 13)) {
+ _vm->_game->_script->skip(1);
+ skipExpr(OP_END_MARKER);
+ }
+ break;
+
+ case OP_FUNC:
+ _vm->_game->_script->skip(1);
+ skipExpr(OP_END_EXPR);
+ }
+ continue;
+ } // if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC))
+
+ if (operation == OP_BEGIN_EXPR) {
+ num++;
+ continue;
+ }
+
+ if ((operation == OP_NOT) || ((operation >= OP_NEG) && (operation <= 8)))
+ continue;
+
+ if ((operation >= OP_OR) && (operation <= OP_NEQ))
+ continue;
+
+ if (operation == OP_END_EXPR)
+ num--;
+
+ if (operation != stopToken)
+ continue;
+
+ if ((stopToken != OP_END_EXPR) || (num < 0))
+ return;
+ }
+}
+
+void Expression::printExpr(char stopToken) {
+ // Expression printing disabled by default
+ return;
+
+ int32 savedPos = _vm->_game->_script->pos();
+ printExpr_internal(stopToken);
+
+ // restore IP to start of expression
+ _vm->_game->_script->seek(savedPos);
+}
+
+void Expression::printExpr_internal(char stopToken) {
+ int16 dimCount;
+ byte operation;
+ int16 num;
+ int16 dim;
+ byte *arrDesc;
+ byte func;
+
+ num = 0;
+ while (true) {
+ operation = _vm->_game->_script->readByte();
+
+ if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC)) {
+ // operands
+
+ switch (operation) {
+ case OP_LOAD_VAR_INT16: // int16 variable load
+ debugN(5, "var16_%d", _vm->_game->_script->readUint16());
+ break;
+
+ case OP_LOAD_VAR_INT8: // int8 variable load:
+ debugN(5, "var8_%d", _vm->_game->_script->readUint16());
+ break;
+
+ case OP_LOAD_IMM_INT32: // int32/uint32 immediate
+ debugN(5, "%d", _vm->_game->_script->readInt32());
+ break;
+
+ case OP_LOAD_IMM_INT16: // int16 immediate
+ debugN(5, "%d", _vm->_game->_script->readInt16());
+ break;
+
+ case OP_LOAD_IMM_INT8: // int8 immediate
+ debugN(5, "%d", _vm->_game->_script->readInt8());
+ break;
+
+ case OP_LOAD_IMM_STR: // string immediate
+ debugN(5, "\42%s\42", _vm->_game->_script->readString());
+ break;
+
+ case OP_LOAD_VAR_INT32:
+ case OP_LOAD_VAR_INT32_AS_INT16:
+ debugN(5, "var_%d", _vm->_game->_script->readUint16());
+ break;
+
+ case OP_LOAD_VAR_STR: // string variable load
+ debugN(5, "(&var_%d)", _vm->_game->_script->readUint16());
+ if (_vm->_game->_script->peekByte() == 13) {
+ _vm->_game->_script->skip(1);
+ debugN(5, "{");
+ printExpr_internal(OP_END_MARKER); // this also prints the closing }
+ }
+ break;
+
+ case OP_ARRAY_INT8: // int8 array access
+ case OP_ARRAY_INT32: // int32 array access
+ case OP_ARRAY_INT16: // int16 array access
+ case OP_ARRAY_STR: // string array access
+ debugN(5, "\n");
+ if (operation == OP_ARRAY_STR)
+ debugN(5, "(&");
+
+ debugN(5, "var_%d[", _vm->_game->_script->readInt16());
+ dimCount = _vm->_game->_script->readByte();
+ arrDesc = _vm->_game->_script->getData() + _vm->_game->_script->pos();
+ _vm->_game->_script->skip(dimCount);
+ for (dim = 0; dim < dimCount; dim++) {
+ printExpr_internal(OP_END_MARKER);
+ debugN(5, " of %d", (int16) arrDesc[dim]);
+ if (dim != dimCount - 1)
+ debugN(5, ",");
+ }
+ debugN(5, "]");
+ if (operation == OP_ARRAY_STR)
+ debugN(5, ")");
+
+ if ((operation == OP_ARRAY_STR) && (_vm->_game->_script->peekByte() == 13)) {
+ _vm->_game->_script->skip(1);
+ debugN(5, "{");
+ printExpr_internal(OP_END_MARKER); // this also prints the closing }
+ }
+ break;
+
+ case OP_FUNC: // function
+ func = _vm->_game->_script->readByte();
+ if (func == FUNC_SQR)
+ debugN(5, "sqr(");
+ else if (func == FUNC_RAND)
+ debugN(5, "rand(");
+ else if (func == FUNC_ABS)
+ debugN(5, "abs(");
+ else if ((func == FUNC_SQRT1) || (func == FUNC_SQRT2) || (func == FUNC_SQRT3))
+ debugN(5, "sqrt(");
+ else
+ debugN(5, "id(");
+ printExpr_internal(OP_END_EXPR);
+ break;
+ }
+ continue;
+ } // if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC))
+
+ // operators
+ switch (operation) {
+ case OP_BEGIN_EXPR:
+ debugN(5, "(");
+ break;
+
+ case OP_NOT:
+ debugN(5, "!");
+ break;
+
+ case OP_END_EXPR:
+ debugN(5, ")");
+ break;
+
+ case OP_NEG:
+ debugN(5, "-");
+ break;
+
+ case OP_ADD:
+ debugN(5, "+");
+ break;
+
+ case OP_SUB:
+ debugN(5, "-");
+ break;
+
+ case OP_BITOR:
+ debugN(5, "|");
+ break;
+
+ case OP_MUL:
+ debugN(5, "*");
+ break;
+
+ case OP_DIV:
+ debugN(5, "/");
+ break;
+
+ case OP_MOD:
+ debugN(5, "%%");
+ break;
+
+ case OP_BITAND:
+ debugN(5, "&");
+ break;
+
+ case OP_OR:
+ debugN(5, "||");
+ break;
+
+ case 31:
+ debugN(5, "&&");
+ break;
+
+ case OP_LESS:
+ debugN(5, "<");
+ break;
+
+ case OP_LEQ:
+ debugN(5, "<=");
+ break;
+
+ case OP_GREATER:
+ debugN(5, ">");
+ break;
+
+ case OP_GEQ:
+ debugN(5, ">=");
+ break;
+
+ case OP_EQ:
+ debugN(5, "==");
+ break;
+
+ case OP_NEQ:
+ debugN(5, "!=");
+ break;
+
+ case 99:
+ debugN(5, "\n");
+ break;
+
+ case OP_END_MARKER:
+ debugN(5, "}");
+ if (stopToken != OP_END_MARKER) {
+ debugN(5, "Closing paren without opening?");
+ }
+ break;
+
+ default:
+ debugN(5, "<%d>", (int16) operation);
+ error("Expression::printExpr(): invalid operator in expression");
+ break;
+ }
+
+ if (operation == OP_BEGIN_EXPR) {
+ num++;
+ continue;
+ }
+
+ if ((operation == OP_NOT) || ((operation >= OP_NEG) && (operation <= 8)))
+ continue;
+
+ if ((operation >= OP_OR) && (operation <= OP_NEQ))
+ continue;
+
+ if (operation == OP_END_EXPR)
+ num--;
+
+ if (operation == stopToken) {
+ if ((stopToken != OP_END_EXPR) || (num < 0)) {
+ return;
+ }
+ }
+ }
+}
+
+
+void Expression::printVarIndex() {
+ byte *arrDesc;
+ int16 dim;
+ int16 dimCount;
+ int16 operation;
+ int16 temp;
+
+ int32 pos = _vm->_game->_script->pos();
+
+ operation = _vm->_game->_script->readByte();
+ switch (operation) {
+ case OP_LOAD_VAR_INT32:
+ case OP_LOAD_VAR_STR:
+ temp = _vm->_game->_script->readUint16() * 4;
+ debugN(5, "&var_%d", temp);
+ if ((operation == OP_LOAD_VAR_STR) && (_vm->_game->_script->peekByte() == 13)) {
+ _vm->_game->_script->skip(1);
+ debugN(5, "+");
+ printExpr(OP_END_MARKER);
+ }
+ break;
+
+ case OP_ARRAY_INT32:
+ case OP_ARRAY_STR:
+ debugN(5, "&var_%d[", _vm->_game->_script->readUint16());
+ dimCount = _vm->_game->_script->readByte();
+ arrDesc = _vm->_game->_script->getData() + _vm->_game->_script->pos();
+ _vm->_game->_script->skip(dimCount);
+ for (dim = 0; dim < dimCount; dim++) {
+ printExpr(OP_END_MARKER);
+ debugN(5, " of %d", (int16) arrDesc[dim]);
+ if (dim != dimCount - 1)
+ debugN(5, ",");
+ }
+ debugN(5, "]");
+
+ if ((operation == OP_ARRAY_STR) && (_vm->_game->_script->peekByte() == 13)) {
+ _vm->_game->_script->skip(1);
+ debugN(5, "+");
+ printExpr(OP_END_MARKER);
+ }
+ break;
+
+ default:
+ debugN(5, "var_0");
+ break;
+ }
+ debugN(5, "\n");
+
+ _vm->_game->_script->seek(pos);
+ return;
+}
+
+int Expression::cmpHelper(const StackFrame &stackFrame) {
+ byte type = stackFrame.opers[-3];
+ int cmpTemp = 0;
+
+ if (type == OP_LOAD_IMM_INT16) {
+ cmpTemp = (int)stackFrame.values[-3] - (int)stackFrame.values[-1];
+ } else if (type == OP_LOAD_IMM_STR) {
+ if ((char *)decodePtr(stackFrame.values[-3]) != _resultStr) {
+ strcpy(_resultStr, (char *)decodePtr(stackFrame.values[-3]));
+ stackFrame.values[-3] = encodePtr((byte *) _resultStr, kResStr);
+ }
+ cmpTemp = strcmp(_resultStr, (char *)decodePtr(stackFrame.values[-1]));
+ }
+
+ return cmpTemp;
+}
+
+bool Expression::getVarBase(uint32 &varBase, bool mindStop,
+ uint16 *size, uint16 *type) {
+
+ varBase = 0;
+
+ byte operation = _vm->_game->_script->peekByte();
+ while ((operation == 14) || (operation == 15)) {
+ _vm->_game->_script->skip(1);
+
+ if (operation == 14) {
+ // Add a direct offset
+
+ varBase += _vm->_game->_script->readInt16() * 4;
+
+ if (size)
+ *size = _vm->_game->_script->peekUint16();
+ if (type)
+ *type = 14;
+
+ _vm->_game->_script->skip(2);
+
+ debugC(2, kDebugExpression, "varBase: %d, by %d", varBase, operation);
+
+ if (_vm->_game->_script->peekByte() != 97) {
+ if (mindStop)
+ return true;
+ } else
+ _vm->_game->_script->skip(1);
+
+ } else if (operation == 15) {
+ // Add an offset from an array
+
+ varBase += _vm->_game->_script->readInt16() * 4;
+
+ uint16 offset1 = _vm->_game->_script->readUint16();
+
+ if (size)
+ *size = offset1;
+ if (type)
+ *type = 15;
+
+ uint8 dimCount = _vm->_game->_script->readByte();
+ byte *dimArray = _vm->_game->_script->getData() + _vm->_game->_script->pos();
+
+ _vm->_game->_script->skip(dimCount);
+
+ uint16 offset2 = 0;
+ for (int i = 0; i < dimCount; i++) {
+ int16 dim = CLIP<int>(parseValExpr(OP_END_MARKER), 0, dimArray[i] - 1);
+
+ offset2 = offset2 * dimArray[i] + dim;
+ }
+
+ varBase += offset2 * offset1 * 4;
+
+ debugC(2, kDebugExpression, "varBase: %d, by %d", varBase, operation);
+
+ if (_vm->_game->_script->peekByte() != 97) {
+ if (mindStop)
+ return true;
+ } else
+ _vm->_game->_script->skip(1);
+ }
+
+ operation = _vm->_game->_script->peekByte();
+ }
+
+ return false;
+}
+
+int16 Expression::parseVarIndex(uint16 *size, uint16 *type) {
+ int16 temp2;
+ byte *arrDesc;
+ int16 dim;
+ int16 dimCount;
+ int16 operation;
+ int16 temp;
+ int16 offset;
+ int16 val;
+ uint32 varBase;
+
+ if (getVarBase(varBase, true, size, type))
+ return varBase;
+
+ operation = _vm->_game->_script->readByte();
+
+ if (size)
+ *size = 0;
+ if (type)
+ *type = operation;
+
+ debugC(5, kDebugExpression, "var parse = %d", operation);
+ switch (operation) {
+ case OP_ARRAY_INT8:
+ case OP_ARRAY_INT32:
+ case OP_ARRAY_INT16:
+ case OP_ARRAY_STR:
+ temp = _vm->_game->_script->readInt16();
+ dimCount = _vm->_game->_script->readByte();
+ arrDesc = _vm->_game->_script->getData() + _vm->_game->_script->pos();
+ _vm->_game->_script->skip(dimCount);
+ offset = 0;
+ for (dim = 0; dim < dimCount; dim++) {
+ temp2 = parseValExpr(OP_END_MARKER);
+ offset = arrDesc[dim] * offset + temp2;
+ }
+ if (operation == OP_ARRAY_INT8)
+ return varBase + temp + offset;
+ if (operation == OP_ARRAY_INT32)
+ return varBase + (temp + offset) * 4;
+ if (operation == OP_ARRAY_INT16)
+ return varBase + (temp + offset) * 2;
+ temp *= 4;
+ offset *= 4;
+ if (_vm->_game->_script->peekByte() == 13) {
+ _vm->_game->_script->skip(1);
+ temp += parseValExpr(OP_END_MARKER);
+ }
+ return varBase + offset * _vm->_global->_inter_animDataSize + temp;
+
+ case OP_LOAD_VAR_INT16:
+ return varBase + _vm->_game->_script->readInt16() * 2;
+
+ case OP_LOAD_VAR_INT8:
+ return varBase + _vm->_game->_script->readInt16();
+
+ case OP_LOAD_VAR_INT32:
+ case OP_LOAD_VAR_INT32_AS_INT16:
+ case OP_LOAD_VAR_STR:
+ temp = _vm->_game->_script->readInt16() * 4;
+ debugC(5, kDebugExpression, "oper = %d", _vm->_game->_script->peekInt16());
+ if ((operation == OP_LOAD_VAR_STR) && (_vm->_game->_script->peekByte() == 13)) {
+ _vm->_game->_script->skip(1);
+ val = parseValExpr(OP_END_MARKER);
+ temp += val;
+ debugC(5, kDebugExpression, "parse subscript = %d", val);
+ }
+ return varBase + temp;
+
+ default:
+ return 0;
+ }
+}
+
+int16 Expression::parseValExpr(byte stopToken) {
+ parseExpr(stopToken, 0);
+
+ return _resultInt;
+}
+
+// Load a value according to the operation
+void Expression::loadValue(byte operation, uint32 varBase, const StackFrame &stackFrame) {
+ int16 dimCount;
+ int16 temp;
+ int16 temp2;
+ int16 offset;
+ int16 dim;
+ byte *arrDescPtr;
+ int32 prevPrevVal;
+ int32 prevVal;
+ int32 curVal;
+
+ switch (operation) {
+ case OP_ARRAY_INT8:
+ case OP_ARRAY_INT32:
+ case OP_ARRAY_INT16:
+ case OP_ARRAY_STR:
+ *stackFrame.opers = (operation == OP_ARRAY_STR) ? OP_LOAD_IMM_STR : OP_LOAD_IMM_INT16;
+ temp = _vm->_game->_script->readInt16();
+ dimCount = _vm->_game->_script->readByte();
+ arrDescPtr = _vm->_game->_script->getData() + _vm->_game->_script->pos();
+ _vm->_game->_script->skip(dimCount);
+ offset = 0;
+ for (dim = 0; dim < dimCount; dim++) {
+ temp2 = parseValExpr(OP_END_MARKER);
+ offset = offset * arrDescPtr[dim] + temp2;
+ }
+ if (operation == OP_ARRAY_INT8)
+ *stackFrame.values = (int8) READ_VARO_UINT8(varBase + temp + offset);
+ else if (operation == OP_ARRAY_INT32)
+ *stackFrame.values = READ_VARO_UINT32(varBase + temp * 4 + offset * 4);
+ else if (operation == OP_ARRAY_INT16)
+ *stackFrame.values = (int16) READ_VARO_UINT16(varBase + temp * 2 + offset * 2);
+ else if (operation == OP_ARRAY_STR) {
+ *stackFrame.values = encodePtr(_vm->_inter->_variables->getAddressOff8(
+ varBase + temp * 4 + offset * _vm->_global->_inter_animDataSize * 4),
+ kInterVar);
+ if (_vm->_game->_script->peekByte() == 13) {
+ _vm->_game->_script->skip(1);
+ temp2 = parseValExpr(OP_END_MARKER);
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = READ_VARO_UINT8(varBase + temp * 4 +
+ offset * 4 * _vm->_global->_inter_animDataSize + temp2);
+ }
+ }
+ break;
+
+ case OP_LOAD_VAR_INT16:
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = (int16) READ_VARO_UINT16(varBase + _vm->_game->_script->readInt16() * 2);
+ break;
+
+ case OP_LOAD_VAR_INT8:
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = (int8) READ_VARO_UINT8(varBase + _vm->_game->_script->readInt16());
+ break;
+
+ case OP_LOAD_IMM_INT32:
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = _vm->_game->_script->readInt32();
+ break;
+
+ case OP_LOAD_IMM_INT16:
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = _vm->_game->_script->readInt16();
+ break;
+
+ case OP_LOAD_IMM_INT8:
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = _vm->_game->_script->readInt8();
+ break;
+
+ case OP_LOAD_IMM_STR:
+ *stackFrame.opers = OP_LOAD_IMM_STR;
+ *stackFrame.values = encodePtr((byte *) _vm->_game->_script->readString(), kExecPtr);
+ break;
+
+ case OP_LOAD_VAR_INT32:
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = READ_VARO_UINT32(varBase + _vm->_game->_script->readInt16() * 4);
+ break;
+
+ case OP_LOAD_VAR_INT32_AS_INT16:
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = (int16) READ_VARO_UINT16(varBase + _vm->_game->_script->readInt16() * 4);
+ break;
+
+ case OP_LOAD_VAR_STR:
+ *stackFrame.opers = OP_LOAD_IMM_STR;
+ temp = _vm->_game->_script->readInt16() * 4;
+ *stackFrame.values = encodePtr(_vm->_inter->_variables->getAddressOff8(varBase + temp), kInterVar);
+ if (_vm->_game->_script->peekByte() == 13) {
+ _vm->_game->_script->skip(1);
+ temp += parseValExpr(OP_END_MARKER);
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = READ_VARO_UINT8(varBase + temp);
+ }
+ break;
+
+ case OP_FUNC:
+ operation = _vm->_game->_script->readByte();
+ parseExpr(OP_END_EXPR, 0);
+
+ switch (operation) {
+ case FUNC_SQRT1:
+ case FUNC_SQRT2:
+ case FUNC_SQRT3:
+ curVal = 1;
+ prevVal = 1;
+
+ do {
+ prevPrevVal = prevVal;
+ prevVal = curVal;
+ curVal = (curVal + _resultInt / curVal) / 2;
+ } while ((curVal != prevVal) && (curVal != prevPrevVal));
+ _resultInt = curVal;
+ break;
+
+ case FUNC_SQR:
+ _resultInt =
+ _resultInt * _resultInt;
+ break;
+
+ case FUNC_ABS:
+ if (_resultInt < 0)
+ _resultInt = -_resultInt;
+ break;
+
+ case FUNC_RAND:
+ _resultInt =
+ _vm->_util->getRandom(_resultInt);
+ break;
+ }
+
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = _resultInt;
+ break;
+ }
+}
+
+void Expression::simpleArithmetic1(StackFrame &stackFrame) {
+ switch (stackFrame.opers[-1]) {
+ case OP_ADD:
+ if (stackFrame.opers[-2] == OP_LOAD_IMM_STR) {
+ if ((char *) decodePtr(stackFrame.values[-2]) != _resultStr) {
+ strcpy(_resultStr, (char *) decodePtr(stackFrame.values[-2]));
+ stackFrame.values[-2] = encodePtr((byte *) _resultStr, kResStr);
+ }
+ strcat(_resultStr, (char *) decodePtr(stackFrame.values[0]));
+ stackFrame.pop(2);
+ }
+ break;
+
+ case OP_MUL:
+ stackFrame.values[-2] *= stackFrame.values[0];
+ stackFrame.pop(2);
+ break;
+
+ case OP_DIV:
+ stackFrame.values[-2] /= stackFrame.values[0];
+ stackFrame.pop(2);
+ break;
+
+ case OP_MOD:
+ stackFrame.values[-2] %= stackFrame.values[0];
+ stackFrame.pop(2);
+ break;
+
+ case OP_BITAND:
+ stackFrame.values[-2] &= stackFrame.values[0];
+ stackFrame.pop(2);
+ break;
+ }
+}
+
+void Expression::simpleArithmetic2(StackFrame &stackFrame) {
+ if (stackFrame.pos > 1) {
+ if (stackFrame.opers[-2] == OP_NEG) {
+ stackFrame.opers[-2] = OP_LOAD_IMM_INT16;
+ stackFrame.values[-2] = -stackFrame.values[-1];
+ stackFrame.pop();
+ } else if (stackFrame.opers[-2] == OP_NOT) {
+ stackFrame.opers[-2] = (stackFrame.opers[-1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE;
+ stackFrame.pop();
+ }
+ }
+
+ if (stackFrame.pos > 2) {
+ switch (stackFrame.opers[-2]) {
+ case OP_MUL:
+ stackFrame.values[-3] *= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_DIV:
+ stackFrame.values[-3] /= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_MOD:
+ stackFrame.values[-3] %= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_BITAND:
+ stackFrame.values[-3] &= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+ }
+ }
+
+}
+
+// Complex arithmetics with brackets
+bool Expression::complexArithmetic(Stack &stack, StackFrame &stackFrame, int16 brackStart) {
+ switch (stackFrame.opers[-2]) {
+ case OP_ADD:
+ if (stack.opers[brackStart] == OP_LOAD_IMM_INT16) {
+ stack.values[brackStart] += stackFrame.values[-1];
+ } else if (stack.opers[brackStart] == OP_LOAD_IMM_STR) {
+ if ((char *) decodePtr(stack.values[brackStart]) != _resultStr) {
+ strcpy(_resultStr, (char *) decodePtr(stack.values[brackStart]));
+ stack.values[brackStart] =
+ encodePtr((byte *) _resultStr, kResStr);
+ }
+ strcat(_resultStr, (char *) decodePtr(stackFrame.values[-1]));
+ }
+ stackFrame.pop(2);
+ break;
+
+ case OP_SUB:
+ stack.values[brackStart] -= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_BITOR:
+ stack.values[brackStart] |= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_MUL:
+ stackFrame.values[-3] *= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_DIV:
+ stackFrame.values[-3] /= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_MOD:
+ stackFrame.values[-3] %= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_BITAND:
+ stackFrame.values[-3] &= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_OR:
+ // (x OR false) == x
+ // (x OR true) == true
+ if (stackFrame.opers[-3] == GOB_FALSE)
+ stackFrame.opers[-3] = stackFrame.opers[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_AND:
+ // (x AND false) == false
+ // (x AND true) == x
+ if (stackFrame.opers[-3] == GOB_TRUE)
+ stackFrame.opers[-3] = stackFrame.opers[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_LESS:
+ stackFrame.opers[-3] = (cmpHelper(stackFrame) < 0) ? GOB_TRUE : GOB_FALSE;
+ stackFrame.pop(2);
+ break;
+
+ case OP_LEQ:
+ stackFrame.opers[-3] = (cmpHelper(stackFrame) <= 0) ? GOB_TRUE : GOB_FALSE;
+ stackFrame.pop(2);
+ break;
+
+ case OP_GREATER:
+ stackFrame.opers[-3] = (cmpHelper(stackFrame) > 0) ? GOB_TRUE : GOB_FALSE;
+ stackFrame.pop(2);
+ break;
+
+ case OP_GEQ:
+ stackFrame.opers[-3] = (cmpHelper(stackFrame) >= 0) ? GOB_TRUE : GOB_FALSE;
+ stackFrame.pop(2);
+ break;
+
+ case OP_EQ:
+ stackFrame.opers[-3] = (cmpHelper(stackFrame) == 0) ? GOB_TRUE : GOB_FALSE;
+ stackFrame.pop(2);
+ break;
+
+ case OP_NEQ:
+ stackFrame.opers[-3] = (cmpHelper(stackFrame) != 0) ? GOB_TRUE : GOB_FALSE;
+ stackFrame.pop(2);
+ break;
+
+ default:
+ return true;
+ }
+
+ return false;
+}
+
+// Assign the result to the appropriate _result variable
+void Expression::getResult(byte operation, int32 value, byte *type) {
+ if (type != 0)
+ *type = operation;
+
+ switch (operation) {
+ case OP_NOT:
+ if (type != 0)
+ *type ^= 1;
+ break;
+
+ case OP_LOAD_IMM_INT16:
+ _resultInt = value;
+ break;
+
+ case OP_LOAD_IMM_STR:
+ if ((char *) decodePtr(value) != _resultStr)
+ strcpy(_resultStr, (char *) decodePtr(value));
+ break;
+
+ case OP_LOAD_VAR_INT32:
+ case OP_LOAD_VAR_INT32_AS_INT16:
+ break;
+
+ default:
+ _resultInt = 0;
+ if (type != 0)
+ *type = OP_LOAD_IMM_INT16;
+ break;
+ }
+}
+
+int16 Expression::parseExpr(byte stopToken, byte *type) {
+ Stack stack;
+ StackFrame stackFrame(stack);
+ byte operation;
+ bool escape;
+ int16 brackStart;
+ uint32 varBase;
+
+ while (true) {
+ getVarBase(varBase);
+
+ stackFrame.push();
+
+ operation = _vm->_game->_script->readByte();
+ if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC)) {
+
+ loadValue(operation, varBase, stackFrame);
+
+ if ((stackFrame.pos > 0) && ((stackFrame.opers[-1] == OP_NEG) || (stackFrame.opers[-1] == OP_NOT))) {
+ stackFrame.pop();
+
+ if (*stackFrame.opers == OP_NEG) {
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ stackFrame.values[0] = -stackFrame.values[1];
+ } else
+ *stackFrame.opers = (stackFrame.opers[1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE;
+ }
+
+ if (stackFrame.pos <= 0)
+ continue;
+
+ simpleArithmetic1(stackFrame);
+
+ continue;
+ } // (op >= OP_ARRAY_INT8) && (op <= OP_FUNC)
+
+ if ((operation == stopToken) || (operation == OP_OR) ||
+ (operation == OP_AND) || (operation == OP_END_EXPR)) {
+ while (stackFrame.pos >= 2) {
+ escape = false;
+ if ((stackFrame.opers[-2] == OP_BEGIN_EXPR) &&
+ ((operation == OP_END_EXPR) || (operation == stopToken))) {
+ stackFrame.opers[-2] = stackFrame.opers[-1];
+ if ((stackFrame.opers[-2] == OP_LOAD_IMM_INT16) || (stackFrame.opers[-2] == OP_LOAD_IMM_STR))
+ stackFrame.values[-2] = stackFrame.values[-1];
+
+ stackFrame.pop();
+
+ simpleArithmetic2(stackFrame);
+
+ if (operation != stopToken)
+ break;
+ } // if ((stackFrame.opers[-2] == OP_BEGIN_EXPR) && ...)
+
+ for (brackStart = (stackFrame.pos - 2); (brackStart > 0) &&
+ (stack.opers[brackStart] < OP_OR) && (stack.opers[brackStart] != OP_BEGIN_EXPR);
+ brackStart--)
+ ;
+
+ if ((stack.opers[brackStart] >= OP_OR) || (stack.opers[brackStart] == OP_BEGIN_EXPR))
+ brackStart++;
+
+ if (complexArithmetic(stack, stackFrame, brackStart))
+ break;
+
+ } // while (stackFrame.pos >= 2)
+
+ if ((operation == OP_OR) || (operation == OP_AND)) {
+ if (stackFrame.opers[-1] == OP_LOAD_IMM_INT16) {
+ if (stackFrame.values[-1] != 0)
+ stackFrame.opers[-1] = GOB_TRUE;
+ else
+ stackFrame.opers[-1] = GOB_FALSE;
+ }
+
+ if (((operation == OP_OR) && (stackFrame.opers[-1] == GOB_TRUE)) ||
+ ((operation == OP_AND) && (stackFrame.opers[-1] == GOB_FALSE))) {
+ if ((stackFrame.pos > 1) && (stackFrame.opers[-2] == OP_BEGIN_EXPR)) {
+ skipExpr(OP_END_EXPR);
+ stackFrame.opers[-2] = stackFrame.opers[-1];
+ stackFrame.pop(2);
+ } else {
+ skipExpr(stopToken);
+ }
+ operation = _vm->_game->_script->peekByte(-1);
+ if ((stackFrame.pos > 0) && (stackFrame.opers[-1] == OP_NOT)) {
+ if (stackFrame.opers[0] == GOB_FALSE)
+ stackFrame.opers[-1] = GOB_TRUE;
+ else
+ stackFrame.opers[-1] = GOB_FALSE;
+
+ stackFrame.pop();
+ }
+ } else
+ stackFrame.opers[0] = operation;
+ } else
+ stackFrame.pop();
+
+ if (operation != stopToken)
+ continue;
+
+ getResult(stack.opers[0], stack.values[0], type);
+
+ return 0;
+ } // (operation == stopToken) || (operation == OP_OR) || (operation == OP_AND) || (operation == OP_END_EXPR)
+
+ if ((operation < OP_NEG) || (operation > OP_NOT)) {
+ if ((operation < OP_LESS) || (operation > OP_NEQ))
+ continue;
+
+ if (stackFrame.pos > 2) {
+ if (stackFrame.opers[-2] == OP_ADD) {
+ if (stackFrame.opers[-3] == OP_LOAD_IMM_INT16) {
+ stackFrame.values[-3] += stackFrame.values[-1];
+ } else if (stackFrame.opers[-3] == OP_LOAD_IMM_STR) {
+ if ((char *) decodePtr(stackFrame.values[-3]) != _resultStr) {
+ strcpy(_resultStr, (char *) decodePtr(stackFrame.values[-3]));
+ stackFrame.values[-3] = encodePtr((byte *) _resultStr, kResStr);
+ }
+ strcat(_resultStr, (char *) decodePtr(stackFrame.values[-1]));
+ }
+ stackFrame.pop(2);
+
+ } else if (stackFrame.opers[-2] == OP_SUB) {
+ stackFrame.values[-3] -= stackFrame.values[-1];
+ stackFrame.pop(2);
+ } else if (stackFrame.opers[-2] == OP_BITOR) {
+ stackFrame.values[-3] |= stackFrame.values[-1];
+ stackFrame.pop(2);
+ }
+ }
+ }
+ *stackFrame.opers = operation;
+ }
+}
+
+int32 Expression::getResultInt() {
+ return _resultInt;
+}
+
+char *Expression::getResultStr() {
+ return _resultStr;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/expression.h b/engines/gob/expression.h
new file mode 100644
index 0000000000..894704e2a9
--- /dev/null
+++ b/engines/gob/expression.h
@@ -0,0 +1,178 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_EXPRESSION_H
+#define GOB_EXPRESSION_H
+
+#include "common/scummsys.h"
+
+namespace Gob {
+
+class GobEngine;
+
+enum {
+ OP_NEG = 1,
+ OP_ADD = 2,
+ OP_SUB = 3,
+ OP_BITOR = 4,
+ OP_MUL = 5,
+ OP_DIV = 6,
+ OP_MOD = 7,
+ OP_BITAND = 8,
+ OP_BEGIN_EXPR = 9,
+ OP_END_EXPR = 10,
+ OP_NOT = 11,
+
+ OP_END_MARKER = 12, // Marks end of an array or string
+
+
+ OP_ARRAY_INT8 = 16,
+ OP_LOAD_VAR_INT16 = 17,
+ OP_LOAD_VAR_INT8 = 18,
+ OP_LOAD_IMM_INT32 = 19,
+ OP_LOAD_IMM_INT16 = 20,
+ OP_LOAD_IMM_INT8 = 21,
+ OP_LOAD_IMM_STR = 22,
+ OP_LOAD_VAR_INT32 = 23,
+ OP_LOAD_VAR_INT32_AS_INT16 = 24,
+ OP_LOAD_VAR_STR = 25,
+ OP_ARRAY_INT32 = 26,
+ OP_ARRAY_INT16 = 27,
+ OP_ARRAY_STR = 28,
+
+ OP_FUNC = 29,
+
+ OP_OR = 30, // Logical OR
+ OP_AND = 31, // Logical AND
+ OP_LESS = 32,
+ OP_LEQ = 33,
+ OP_GREATER = 34,
+ OP_GEQ = 35,
+ OP_EQ = 36,
+ OP_NEQ = 37
+};
+
+enum {
+ FUNC_SQRT1 = 0,
+ FUNC_SQRT2 = 1,
+ FUNC_SQRT3 = 6,
+
+ FUNC_SQR = 5,
+ FUNC_ABS = 7,
+ FUNC_RAND = 10
+};
+
+enum {
+ TYPE_IMM_INT8 = OP_LOAD_IMM_INT8, // 21
+ TYPE_IMM_INT32 = OP_LOAD_IMM_INT32, // 19
+ TYPE_IMM_INT16 = OP_LOAD_IMM_INT16, // 20
+ TYPE_IMM_STR = OP_LOAD_IMM_STR, // 22
+ TYPE_VAR_INT8 = OP_LOAD_VAR_INT8, // 18
+ TYPE_VAR_INT16 = OP_LOAD_VAR_INT16, // 17
+ TYPE_VAR_INT32 = OP_LOAD_VAR_INT32, // 23
+ TYPE_VAR_STR = OP_LOAD_VAR_STR, // 25
+ TYPE_ARRAY_INT8 = OP_ARRAY_INT8, // 16
+ TYPE_ARRAY_INT16 = OP_ARRAY_INT16, // 27
+ TYPE_ARRAY_INT32 = OP_ARRAY_INT32, // 26
+ TYPE_ARRAY_STR = OP_ARRAY_STR, // 28
+ TYPE_VAR_INT32_AS_INT16 = OP_LOAD_VAR_INT32_AS_INT16 // 24
+};
+
+enum {
+ // FIXME: The following two 'truth values' are stored inside the list
+ // of "operators". So they somehow coincide with OP_LOAD_VAR_INT32
+ // and OP_LOAD_VAR_INT32_AS_INT16. I haven't yet quite understood
+ // how, resp. what that means. You have been warned.
+ GOB_TRUE = 24,
+ GOB_FALSE = 23
+};
+
+class Expression {
+public:
+ Expression(GobEngine *vm);
+ virtual ~Expression() {}
+
+ void skipExpr(char stopToken);
+ void printExpr(char stopToken);
+ void printVarIndex(void);
+
+ int16 parseVarIndex(uint16 *size = 0, uint16 *type = 0);
+ int16 parseValExpr(byte stopToken = 99);
+ int16 parseExpr(byte stopToken, byte *type);
+
+ int32 getResultInt();
+ char *getResultStr();
+
+private:
+ class Stack {
+ public:
+ byte *opers;
+ int32 *values;
+
+ Stack(size_t size = 20);
+ ~Stack();
+ };
+ class StackFrame {
+ public:
+ byte *opers;
+ int32 *values;
+ int16 pos;
+
+ StackFrame(const Stack &stack);
+
+ void push(int count = 1);
+ void pop(int count = 1);
+ };
+
+ enum PointerType {
+ kExecPtr = 0,
+ kInterVar = 1,
+ kResStr = 2
+ };
+
+ GobEngine *_vm;
+
+ int32 _resultInt;
+ char _resultStr[200];
+
+ int32 encodePtr(byte *ptr, int type);
+ byte *decodePtr(int32 n);
+
+ void printExpr_internal(char stopToken);
+
+ bool getVarBase(uint32 &varBase, bool mindStop = false,
+ uint16 *size = 0, uint16 *type = 0);
+ int cmpHelper(const StackFrame &stackFrame);
+ void loadValue(byte operation, uint32 varBase, const StackFrame &stackFrame);
+
+ void simpleArithmetic1(StackFrame &stackFrame);
+ void simpleArithmetic2(StackFrame &stackFrame);
+ bool complexArithmetic(Stack &stack, StackFrame &stackFrame, int16 brackStart);
+ void getResult(byte operation, int32 value, byte *type);
+};
+
+} // End of namespace Gob
+
+#endif // GOB_EXPRESSION_H
diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp
index 09addc3900..5771ee9f76 100644
--- a/engines/gob/game.cpp
+++ b/engines/gob/game.cpp
@@ -31,8 +31,10 @@
#include "gob/global.h"
#include "gob/util.h"
#include "gob/dataio.h"
+#include "gob/variables.h"
+#include "gob/script.h"
+#include "gob/resources.h"
#include "gob/inter.h"
-#include "gob/parse.h"
#include "gob/draw.h"
#include "gob/mult.h"
#include "gob/videoplayer.h"
@@ -40,21 +42,139 @@
namespace Gob {
+Environments::Environments(GobEngine *vm) : _vm(vm) {
+ _environments = new Environment[kEnvironmentCount];
+
+ for (uint i = 0; i < kEnvironmentCount; i++) {
+ Environment &e = _environments[i];
+
+ e.cursorHotspotX = 0;
+ e.cursorHotspotY = 0;
+ e.variables = 0;
+ e.script = 0;
+ e.resources = 0;
+ e.curTotFile[0] = '\0';
+ }
+}
+
+Environments::~Environments() {
+ clear();
+
+ delete[] _environments;
+}
+
+void Environments::clear() {
+ // Deleting unique variables, script and resources
+
+ for (uint i = 0; i < kEnvironmentCount; i++) {
+ if (_environments[i].variables == _vm->_inter->_variables)
+ continue;
+
+ if (!has(_environments[i].variables, i + 1))
+ delete _environments[i].variables;
+ }
+
+ for (uint i = 0; i < kEnvironmentCount; i++) {
+ if (_environments[i].script == _vm->_game->_script)
+ continue;
+
+ if (!has(_environments[i].script, i + 1))
+ delete _environments[i].script;
+ }
+
+ for (uint i = 0; i < kEnvironmentCount; i++) {
+ if (_environments[i].resources == _vm->_game->_resources)
+ continue;
+
+ if (!has(_environments[i].resources, i + 1))
+ delete _environments[i].resources;
+ }
+}
+
+void Environments::set(uint8 env) {
+ if (env >= kEnvironmentCount)
+ return;
+
+ Environment &e = _environments[env];
+
+ // If it already has a unique script or resource assigned, delete them
+ if ((e.script != _vm->_game->_script) && !has(e.script, 0, env))
+ delete e.script;
+ if ((e.resources != _vm->_game->_resources) && !has(e.resources, 0, env))
+ delete e.resources;
+
+ e.cursorHotspotX = _vm->_draw->_cursorHotspotXVar;
+ e.cursorHotspotY = _vm->_draw->_cursorHotspotYVar;
+ e.script = _vm->_game->_script;
+ e.resources = _vm->_game->_resources;
+ e.variables = _vm->_inter->_variables;
+ strncpy(e.curTotFile, _vm->_game->_curTotFile, 14);
+}
+
+void Environments::get(uint8 env) const {
+ if (env >= kEnvironmentCount)
+ return;
+
+ const Environment &e = _environments[env];
+
+ _vm->_draw->_cursorHotspotXVar = e.cursorHotspotX;
+ _vm->_draw->_cursorHotspotYVar = e.cursorHotspotY;
+ _vm->_game->_script = e.script;
+ _vm->_game->_resources = e.resources;
+ _vm->_inter->_variables = e.variables;
+ strncpy(_vm->_game->_curTotFile, e.curTotFile, 14);
+}
+
+const char *Environments::getTotFile(uint8 env) const {
+ if (env >= kEnvironmentCount)
+ return "";
+
+ return _environments[env].curTotFile;
+}
+
+bool Environments::has(Variables *variables, uint8 startEnv, int16 except) const {
+ for (uint i = startEnv; i < kEnvironmentCount; i++) {
+ if ((except >= 0) && (((uint16) except) == i))
+ continue;
+
+ if (_environments[i].variables == variables)
+ return true;
+ }
+
+ return false;
+}
+
+bool Environments::has(Script *script, uint8 startEnv, int16 except) const {
+ for (uint i = startEnv; i < kEnvironmentCount; i++) {
+ if ((except >= 0) && (((uint16) except) == i))
+ continue;
+
+ if (_environments[i].script == script)
+ return true;
+ }
+
+ return false;
+}
+
+bool Environments::has(Resources *resources, uint8 startEnv, int16 except) const {
+ for (uint i = startEnv; i < kEnvironmentCount; i++) {
+ if ((except >= 0) && (((uint16) except) == i))
+ continue;
+
+ if (_environments[i].resources == resources)
+ return true;
+ }
+
+ return false;
+}
+
+
Game::Game(GobEngine *vm) : _vm(vm) {
- _extTable = 0;
- _totFileData = 0;
- _totResourceTable = 0;
- _imFileData = 0;
- _extHandle = 0;
- _lomHandle = -1;
_collisionAreas = 0;
_shouldPushColls = 0;
_captureCount = 0;
- _foundTotLoc = false;
- _totTextData = 0;
-
_collStackSize = 0;
for (int i = 0; i < 5; i++) {
@@ -63,7 +183,6 @@ Game::Game(GobEngine *vm) : _vm(vm) {
}
_curTotFile[0] = 0;
- _curExtFile[0] = 0;
_totToLoad[0] = 0;
_startTimeKey = 0;
@@ -85,138 +204,20 @@ Game::Game(GobEngine *vm) : _vm(vm) {
_noCd = false;
_tempStr[0] = 0;
- _curImaFile[0] = 0;
_collStr[0] = 0;
- _backupedCount = 0;
- _curBackupPos = 0;
+ _numEnvironments = 0;
+ _curEnvironment = 0;
- for (int i = 0; i < 5; i++) {
- _cursorHotspotXArray[i] = 0;
- _cursorHotspotYArray[i] = 0;
- _totTextDataArray[i] = 0;
- _totFileDataArray[i] = 0;
- _totResourceTableArray[i] = 0;
- _extTableArray[i] = 0;
- _extHandleArray[i] = 0;
- _imFileDataArray[i] = 0;
- _variablesArray[i] = 0;
- _curTotFileArray[i][0] = 0;
- }
+ _environments = new Environments(_vm);
+ _script = new Script(_vm);
+ _resources = new Resources(_vm);
}
Game::~Game() {
- delete[] _vm->_game->_totFileData;
- if (_vm->_game->_totTextData) {
- if (_vm->_game->_totTextData->items)
- delete[] _vm->_game->_totTextData->items;
- delete _vm->_game->_totTextData;
- }
- if (_vm->_game->_totResourceTable) {
- delete[] _vm->_game->_totResourceTable->items;
- delete _vm->_game->_totResourceTable;
- }
-}
-
-byte *Game::loadExtData(int16 itemId, int16 *pResWidth,
- int16 *pResHeight, uint32 *dataSize) {
- int16 commonHandle;
- int16 itemsCount;
- int32 offset;
- uint32 size;
- uint32 realSize;
- ExtItem *item;
- bool isPacked;
- int16 handle;
- int32 tableSize;
- char path[20];
- byte *dataBuf;
- byte *packedBuf;
- byte *dataPtr;
-
- itemId -= 30000;
- if (_extTable == 0)
- return 0;
-
- commonHandle = -1;
- itemsCount = _extTable->itemsCount;
- item = &_extTable->items[itemId];
- tableSize = szGame_ExtTable + szGame_ExtItem * itemsCount;
-
- offset = item->offset;
- size = item->size;
- isPacked = (item->width & 0x8000) != 0;
-
- if ((pResWidth != 0) && (pResHeight != 0)) {
- *pResWidth = item->width & 0x7FFF;
-
- if (*pResWidth & 0x4000)
- size += 1 << 16;
- if (*pResWidth & 0x2000)
- size += 2 << 16;
- if (*pResWidth & 0x1000)
- size += 4 << 16;
-
- *pResWidth &= 0xFFF;
-
- *pResHeight = item->height;
- debugC(7, kDebugFileIO, "loadExtData(%d, %d, %d)",
- itemId, *pResWidth, *pResHeight);
- }
-
- debugC(7, kDebugFileIO, "loadExtData(%d, 0, 0)", itemId);
-
- if (item->height == 0)
- size += (item->width & 0x7FFF) << 16;
-
- debugC(7, kDebugFileIO, "size: %d off: %d", size, offset);
- if (offset < 0) {
- offset = -(offset + 1);
- tableSize = 0;
- _vm->_dataIO->closeData(_extHandle);
- strcpy(path, "commun.ex1");
- path[strlen(path) - 1] = *(_totFileData + 0x3C) + '0';
- commonHandle = _vm->_dataIO->openData(path);
- handle = commonHandle;
- } else
- handle = _extHandle;
-
- DataStream *stream = _vm->_dataIO->openAsStream(handle);
-
- debugC(7, kDebugFileIO, "off: %d size: %d", offset, tableSize);
- stream->seek(offset + tableSize);
- realSize = size;
- if (isPacked)
- dataBuf = new byte[size + 2];
- else
- dataBuf = new byte[size];
-
- dataPtr = dataBuf;
- while (size > 32000) {
- // BUG: huge->far conversion. Need normalization?
- stream->read(dataPtr, 32000);
- size -= 32000;
- dataPtr += 32000;
- }
- stream->read(dataPtr, size);
-
- delete stream;
- if (commonHandle != -1) {
- _vm->_dataIO->closeData(commonHandle);
- _extHandle = _vm->_dataIO->openData(_curExtFile);
- }
-
- if (isPacked) {
- packedBuf = dataBuf;
- realSize = READ_LE_UINT32(packedBuf);
- dataBuf = new byte[realSize];
- _vm->_dataIO->unpackData(packedBuf, dataBuf);
- delete[] packedBuf;
- }
-
- if (dataSize)
- *dataSize = realSize;
- return dataBuf;
+ delete _environments;
+ delete _script;
+ delete _resources;
}
void Game::freeCollision(int16 id) {
@@ -281,39 +282,9 @@ void Game::capturePop(char doDraw) {
_vm->_draw->freeSprite(30 + _captureCount);
}
-byte *Game::loadTotResource(int16 id,
- int16 *dataSize, int16 *width, int16 *height) {
-
- TotResItem *itemPtr;
- int32 offset;
-
- if (id >= _vm->_game->_totResourceTable->itemsCount) {
- warning("Trying to load non-existent TOT resource (%s, %d/%d)",
- _curTotFile, id, _totResourceTable->itemsCount - 1);
- return 0;
- }
-
- itemPtr = &_totResourceTable->items[id];
- offset = itemPtr->offset;
-
- if (dataSize)
- *dataSize = itemPtr->size;
- if (width)
- *width = itemPtr->width;
- if (height)
- *height = itemPtr->height;
-
- if (offset < 0) {
- offset = (-offset - 1) * 4;
- return _imFileData + (int32) READ_LE_UINT32(_imFileData + offset);
- } else
- return _totResourceTable->dataPtr + szGame_TotResTable +
- szGame_TotResItem * _totResourceTable->itemsCount + offset;
-}
-
void Game::freeSoundSlot(int16 slot) {
if (slot == -1)
- slot = _vm->_parse->parseValExpr();
+ slot = _vm->_game->_script->readValExpr();
_vm->_sound->sampleFree(_vm->_sound->sampleGetBySlot(slot));
}
@@ -416,104 +387,6 @@ int16 Game::adjustKey(int16 key) {
return key - 0x20;
}
-int32 Game::loadTotFile(const char *path) {
- int16 handle;
- int32 size;
-
- _lomHandle = -1;
-
- size = -1;
- handle = _vm->_dataIO->openData(path);
- if (handle >= 0) {
-
- if (!scumm_stricmp(path + strlen(path) - 3, "LOM")) {
- warning("Urban Stub: loadTotFile %s", path);
-
- _lomHandle = handle;
-
- DataStream *stream = _vm->_dataIO->openAsStream(handle);
-
- stream->seek(48);
- size = stream->readUint32LE();
- stream->seek(0);
-
- _totFileData = new byte[size];
- stream->read(_totFileData, size);
-
- delete stream;
- } else {
- _vm->_dataIO->closeData(handle);
- size = _vm->_dataIO->getDataSize(path);
- _totFileData = _vm->_dataIO->getData(path);
- }
-
- } else {
- Common::MemoryReadStream *videoExtraData = _vm->_vidPlayer->getExtraData(path);
-
- if (videoExtraData) {
- warning("Found \"%s\" in video file", path);
-
- size = videoExtraData->size();
- _totFileData = new byte[size];
- videoExtraData->read(_totFileData, size);
- delete videoExtraData;
- } else
- _totFileData = 0;
- }
-
- return size;
-}
-
-void Game::loadExtTable(void) {
- int16 count;
-
- // Function is correct. [sev]
-
- _extHandle = _vm->_dataIO->openData(_curExtFile);
- if (_extHandle < 0)
- return;
-
- DataStream *stream = _vm->_dataIO->openAsStream(_extHandle);
- count = stream->readUint16LE();
-
- stream->seek(0);
- _extTable = new ExtTable;
- _extTable->items = 0;
- if (count)
- _extTable->items = new ExtItem[count];
-
- _extTable->itemsCount = stream->readUint16LE();
- _extTable->unknown = stream->readByte();
-
- for (int i = 0; i < count; i++) {
- _extTable->items[i].offset = stream->readUint32LE();
- _extTable->items[i].size = stream->readUint16LE();
- _extTable->items[i].width = stream->readUint16LE();
- _extTable->items[i].height = stream->readUint16LE();
- }
-
- delete stream;
-}
-
-void Game::loadImFile(void) {
- char path[20];
- int16 handle;
-
- if ((_totFileData[0x3D] != 0) && (_totFileData[0x3B] == 0))
- return;
-
- strcpy(path, "commun.im1");
- if (_totFileData[0x3B] != 0)
- path[strlen(path) - 1] = '0' + _totFileData[0x3B];
-
- handle = _vm->_dataIO->openData(path);
- if (handle < 0)
- return;
-
- _vm->_dataIO->closeData(handle);
- _imFileData = _vm->_dataIO->getData(path);
-}
-
void Game::start(void) {
_collisionAreas = new Collision[250];
memset(_collisionAreas, 0, 250 * sizeof(Collision));
@@ -533,27 +406,17 @@ void Game::start(void) {
void Game::totSub(int8 flags, const char *newTotFile) {
int8 curBackupPos;
- if (_backupedCount >= 5)
+ if (_numEnvironments >= Environments::kEnvironmentCount)
return;
- _cursorHotspotXArray[_backupedCount] = _vm->_draw->_cursorHotspotXVar;
- _cursorHotspotYArray[_backupedCount] = _vm->_draw->_cursorHotspotYVar;
- _totTextDataArray[_backupedCount] = _totTextData;
- _totFileDataArray[_backupedCount] = _totFileData;
- _totResourceTableArray[_backupedCount] = _totResourceTable;
- _extTableArray[_backupedCount] = _extTable;
- _extHandleArray[_backupedCount] = _extHandle;
- _imFileDataArray[_backupedCount] = _imFileData;
- _variablesArray[_backupedCount] = _vm->_inter->_variables;
- strcpy(_curTotFileArray[_backupedCount], _curTotFile);
-
- curBackupPos = _curBackupPos;
- _backupedCount++;
- _curBackupPos = _backupedCount;
-
- _totTextData = 0;
- _totFileData = 0;
- _totResourceTable = 0;
+ _environments->set(_numEnvironments);
+
+ curBackupPos = _curEnvironment;
+ _numEnvironments++;
+ _curEnvironment = _numEnvironments;
+
+ _script = new Script(_vm);
+ _resources = new Resources(_vm);
if (flags & 1)
_vm->_inter->_variables = 0;
@@ -563,8 +426,10 @@ void Game::totSub(int8 flags, const char *newTotFile) {
// else
strcat(_curTotFile, ".TOT");
- if (_vm->_inter->_terminate != 0)
+ if (_vm->_inter->_terminate != 0) {
+ clearUnusedEnvironment();
return;
+ }
pushCollisions(0);
@@ -582,197 +447,64 @@ void Game::totSub(int8 flags, const char *newTotFile) {
_vm->_inter->delocateVars();
}
- _backupedCount--;
- _curBackupPos = curBackupPos;
-
- _vm->_draw->_cursorHotspotXVar = _cursorHotspotXArray[_backupedCount];
- _vm->_draw->_cursorHotspotYVar = _cursorHotspotYArray[_backupedCount];
- _totTextData = _totTextDataArray[_backupedCount];
- _totFileData = _totFileDataArray[_backupedCount];
- _totResourceTable = _totResourceTableArray[_backupedCount];
- _extTable = _extTableArray[_backupedCount];
- _extHandle = _extHandleArray[_backupedCount];
- _imFileData = _imFileDataArray[_backupedCount];
- _vm->_inter->_variables = _variablesArray[_backupedCount];
- strcpy(_curTotFile, _curTotFileArray[_backupedCount]);
- strcpy(_curExtFile, _curTotFile);
- _curExtFile[strlen(_curExtFile) - 4] = '\0';
- strcat(_curExtFile, ".EXT");
+ clearUnusedEnvironment();
+
+ _numEnvironments--;
+ _curEnvironment = curBackupPos;
+ _environments->get(_numEnvironments);
}
void Game::switchTotSub(int16 index, int16 skipPlay) {
int16 backupedCount;
int16 curBackupPos;
- if ((_backupedCount - index) < 1)
+ if ((_numEnvironments - index) < 1)
+ return;
+
+ int16 newPos = _curEnvironment - index - ((index >= 0) ? 1 : 0);
+ if (newPos >= Environments::kEnvironmentCount)
return;
- int16 newPos = _curBackupPos - index - ((index >= 0) ? 1 : 0);
// WORKAROUND: Some versions don't make the MOVEMENT menu item unselectable
// in the dreamland screen, resulting in a crash when it's clicked.
if ((_vm->getGameType() == kGameTypeGob2) && (index == -1) && (skipPlay == 7) &&
- !scumm_stricmp(_curTotFileArray[newPos], "gob06.tot"))
+ !scumm_stricmp(_environments->getTotFile(newPos), "gob06.tot"))
return;
- curBackupPos = _curBackupPos;
- backupedCount = _backupedCount;
- if (_curBackupPos == _backupedCount) {
- _cursorHotspotXArray[_backupedCount] = _vm->_draw->_cursorHotspotXVar;
- _cursorHotspotYArray[_backupedCount] = _vm->_draw->_cursorHotspotYVar;
- _totTextDataArray[_backupedCount] = _totTextData;
- _totFileDataArray[_backupedCount] = _totFileData;
- _totResourceTableArray[_backupedCount] = _totResourceTable;
- _extTableArray[_backupedCount] = _extTable;
- _extHandleArray[_backupedCount] = _extHandle;
- _imFileDataArray[_backupedCount] = _imFileData;
- _variablesArray[_backupedCount] = _vm->_inter->_variables;
- strcpy(_curTotFileArray[_backupedCount], _curTotFile);
- _backupedCount++;
- }
- _curBackupPos -= index;
- if (index >= 0)
- _curBackupPos--;
-
- _vm->_draw->_cursorHotspotXVar = _cursorHotspotXArray[_curBackupPos];
- _vm->_draw->_cursorHotspotYVar = _cursorHotspotYArray[_curBackupPos];
- _totTextData = _totTextDataArray[_curBackupPos];
- _totFileData = _totFileDataArray[_curBackupPos];
- _totResourceTable = _totResourceTableArray[_curBackupPos];
- _imFileData = _imFileDataArray[_curBackupPos];
- _extTable = _extTableArray[_curBackupPos];
- _extHandle = _extHandleArray[_curBackupPos];
- _vm->_inter->_variables = _variablesArray[_curBackupPos];
- strcpy(_curTotFile, _curTotFileArray[_curBackupPos]);
- strcpy(_curExtFile, _curTotFile);
- _curExtFile[strlen(_curExtFile) - 4] = '\0';
- strcat(_curExtFile, ".EXT");
-
- if (_vm->_inter->_terminate != 0)
- return;
+ curBackupPos = _curEnvironment;
+ backupedCount = _numEnvironments;
+ if (_curEnvironment == _numEnvironments)
+ _environments->set(_numEnvironments++);
- _vm->_game->pushCollisions(0);
- _vm->_game->playTot(skipPlay);
+ _curEnvironment -= index;
+ if (index >= 0)
+ _curEnvironment--;
- if (_vm->_inter->_terminate != 2)
- _vm->_inter->_terminate = 0;
+ clearUnusedEnvironment();
- _vm->_game->popCollisions();
-
- _curBackupPos = curBackupPos;
- _backupedCount = backupedCount;
- _vm->_draw->_cursorHotspotXVar = _cursorHotspotXArray[_curBackupPos];
- _vm->_draw->_cursorHotspotYVar = _cursorHotspotYArray[_curBackupPos];
- _totTextData = _totTextDataArray[_curBackupPos];
- _totFileData = _totFileDataArray[_curBackupPos];
- _totResourceTable = _totResourceTableArray[_curBackupPos];
- _extTable = _extTableArray[_curBackupPos];
- _extHandle = _extHandleArray[_curBackupPos];
- _imFileData = _imFileDataArray[_curBackupPos];
- _vm->_inter->_variables = _variablesArray[_curBackupPos];
- strcpy(_curTotFile, _curTotFileArray[_curBackupPos]);
- strcpy(_curExtFile, _curTotFile);
- _curExtFile[strlen(_curExtFile) - 4] = '\0';
- strcat(_curExtFile, ".EXT");
-}
+ _environments->get(_curEnvironment);
-int16 Game::openLocTextFile(char *locTextFile, int language) {
- int n;
-
- n = strlen(locTextFile);
- if (n < 4)
- return -1;
-
- locTextFile[n - 4] = 0;
- switch (language) {
- case 0:
- strcat(locTextFile, ".dat");
- break;
- case 1:
- strcat(locTextFile, ".all");
- break;
- case 3:
- strcat(locTextFile, ".esp");
- break;
- case 4:
- strcat(locTextFile, ".ita");
- break;
- case 5:
- strcat(locTextFile, ".usa");
- break;
- case 6:
- strcat(locTextFile, ".ndl");
- break;
- case 7:
- strcat(locTextFile, ".kor");
- break;
- case 8:
- strcat(locTextFile, ".isr");
- break;
- default:
- strcat(locTextFile, ".ang");
- break;
+ if (_vm->_inter->_terminate != 0) {
+ clearUnusedEnvironment();
+ return;
}
- return _vm->_dataIO->openData(locTextFile);
-}
-
-byte *Game::loadLocTexts(int32 *dataSize) {
- char locTextFile[20];
- int16 handle;
- int i;
-
- strcpy(locTextFile, _curTotFile);
-
- handle = openLocTextFile(locTextFile, _vm->_global->_languageWanted);
- if (handle >= 0) {
-
- _foundTotLoc = true;
- _vm->_global->_language = _vm->_global->_languageWanted;
-
- } else if (!_foundTotLoc) {
- bool found = false;
-
- if (_vm->_global->_languageWanted == 2) {
- handle = openLocTextFile(locTextFile, 5);
- if (handle >= 0) {
- _vm->_global->_language = 5;
- found = true;
- }
- } else if (_vm->_global->_languageWanted == 5) {
- handle = openLocTextFile(locTextFile, 2);
- if (handle >= 0) {
- _vm->_global->_language = 2;
- found = true;
- }
- }
- if (!found) {
- for (i = 0; i < 10; i++) {
- handle = openLocTextFile(locTextFile, i);
- if (handle >= 0) {
- _vm->_global->_language = i;
- break;
- }
- }
- }
-
- }
+ pushCollisions(0);
+ playTot(skipPlay);
- debugC(1, kDebugFileIO, "Using language %d for %s",
- _vm->_global->_language, _curTotFile);
+ if (_vm->_inter->_terminate != 2)
+ _vm->_inter->_terminate = 0;
- if (handle >= 0) {
- _vm->_dataIO->closeData(handle);
+ popCollisions();
- if (dataSize)
- *dataSize = _vm->_dataIO->getDataSize(locTextFile);
+ clearUnusedEnvironment();
- return _vm->_dataIO->getData(locTextFile);
- }
- return 0;
+ _curEnvironment = curBackupPos;
+ _numEnvironments = backupedCount;
+ _environments->get(_curEnvironment);
}
void Game::setCollisions(byte arg_0) {
- byte *savedIP;
uint16 left;
uint16 top;
uint16 width;
@@ -783,12 +515,12 @@ void Game::setCollisions(byte arg_0) {
if (((collArea->id & 0xC000) != 0x8000) || (collArea->funcSub == 0))
continue;
- savedIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr = _totFileData + collArea->funcSub;
- left = _vm->_parse->parseValExpr();
- top = _vm->_parse->parseValExpr();
- width = _vm->_parse->parseValExpr();
- height = _vm->_parse->parseValExpr();
+ _script->call(collArea->funcSub);
+
+ left = _script->readValExpr();
+ top = _script->readValExpr();
+ width = _script->readValExpr();
+ height = _script->readValExpr();
if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) &&
(left != 0xFFFF)) {
left += _vm->_draw->_backDeltaX;
@@ -807,16 +539,15 @@ void Game::setCollisions(byte arg_0) {
collArea->top = top;
collArea->right = left + width - 1;
collArea->bottom = top + height - 1;
- _vm->_global->_inter_execPtr = savedIP;
+
+ _script->pop();
}
}
void Game::collSub(uint16 offset) {
- byte *savedIP;
int16 collStackSize;
- savedIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr = _totFileData + offset;
+ _script->call(offset);
_shouldPushColls = 1;
collStackSize = _collStackSize;
@@ -827,7 +558,9 @@ void Game::collSub(uint16 offset) {
popCollisions();
_shouldPushColls = 0;
- _vm->_global->_inter_execPtr = savedIP;
+
+ _script->pop();
+
setCollisions();
}
@@ -852,4 +585,16 @@ void Game::collAreaSub(int16 index, int8 enter) {
}
}
+void Game::clearUnusedEnvironment() {
+ if (!_environments->has(_script)) {
+ delete _script;
+ _script = 0;
+ }
+ if (!_environments->has(_resources)) {
+ delete _resources;
+ _resources = 0;
+ }
+
+}
+
} // End of namespace Gob
diff --git a/engines/gob/game.h b/engines/gob/game.h
index 3264288a32..ead4a56492 100644
--- a/engines/gob/game.h
+++ b/engines/gob/game.h
@@ -26,10 +26,45 @@
#ifndef GOB_GAME_H
#define GOB_GAME_H
-#include "gob/variables.h"
-
namespace Gob {
+class Script;
+class Resources;
+class Variables;
+
+class Environments {
+public:
+ static const uint8 kEnvironmentCount = 5;
+
+ Environments(GobEngine *vm);
+ ~Environments();
+
+ void set(uint8 env);
+ void get(uint8 env) const;
+
+ const char *getTotFile(uint8 env) const;
+
+ bool has(Variables *variables, uint8 startEnv = 0, int16 except = -1) const;
+ bool has(Script *script , uint8 startEnv = 0, int16 except = -1) const;
+ bool has(Resources *resources, uint8 startEnv = 0, int16 except = -1) const;
+
+ void clear();
+
+private:
+ struct Environment {
+ int16 cursorHotspotX;
+ int16 cursorHotspotY;
+ char curTotFile[14];
+ Variables *variables;
+ Script *script;
+ Resources *resources;
+ };
+
+ GobEngine *_vm;
+
+ Environment *_environments;
+};
+
class Game {
public:
@@ -46,20 +81,7 @@ public:
uint16 funcEnter;
uint16 funcLeave;
uint16 funcSub;
- byte *totFileData;
- } PACKED_STRUCT;
-
-#define szGame_TotTextItem (2 + 2)
- struct TotTextItem {
- int16 offset;
- int16 size;
- } PACKED_STRUCT;
-
-#define szGame_TotTextTable (2)
- struct TotTextTable {
- int16 itemsCount;
- TotTextItem *items;
- byte *dataPtr;
+ Script *script;
} PACKED_STRUCT;
struct InputDesc {
@@ -74,18 +96,10 @@ public:
Collision *_collisionAreas;
Collision *_collStack[5];
- bool _foundTotLoc;
- TotTextTable *_totTextData;
+ Script *_script;
+ Resources *_resources;
char _curTotFile[14];
- char _curExtFile[14];
-
- byte *_imFileData;
- byte *_totFileData;
-
- int16 _extHandle;
- int16 _lomHandle;
-
char _totToLoad[20];
int32 _startTimeKey;
@@ -100,9 +114,6 @@ public:
Game(GobEngine *vm);
virtual ~Game();
- byte *loadExtData(int16 dataId, int16 *pResWidth, int16 *pResHeight, uint32 *dataSize = 0);
- byte *loadTotResource(int16 id, int16 *dataSize = 0, int16 *width = 0, int16 *height = 0);
-
void capturePush(int16 left, int16 top, int16 width, int16 height);
void capturePop(char doDraw);
@@ -142,42 +153,6 @@ public:
virtual void popCollisions(void) = 0;
protected:
-#include "common/pack-start.h" // START STRUCT PACKING
-
-#define szGame_TotResItem (4 + 2 + 2 + 2)
- struct TotResItem {
- int32 offset; // if > 0, then offset from end of resource table.
- // If < 0, then -offset-1 is index in .IM file table
- int16 size;
- int16 width;
- int16 height;
- } PACKED_STRUCT;
-
-#define szGame_TotResTable (2 + 1)
- struct TotResTable {
- int16 itemsCount;
- byte unknown;
- TotResItem *items;
- byte *dataPtr;
- } PACKED_STRUCT;
-
-#define szGame_ExtItem (4 + 2 + 2 + 2)
- struct ExtItem {
- int32 offset; // offset from the table end
- uint16 size;
- int16 width; // width & 0x7FFF: width, width & 0x8000: pack flag
- int16 height; // not zero
- } PACKED_STRUCT;
-
-#define szGame_ExtTable (2 + 1)
- struct ExtTable {
- int16 itemsCount;
- byte unknown;
- ExtItem *items;
- } PACKED_STRUCT;
-
-#include "common/pack-end.h" // END STRUCT PACKING
-
int16 _lastCollKey;
int16 _lastCollAreaIndex;
int16 _lastCollId;
@@ -190,10 +165,6 @@ protected:
char _tempStr[256];
- TotResTable *_totResourceTable;
- ExtTable *_extTable;
- char _curImaFile[18];
-
int16 _collStackSize;
int16 _collStackElemSizes[5];
@@ -206,35 +177,22 @@ protected:
char _collStr[256];
// For totSub()
- int8 _backupedCount;
- int8 _curBackupPos;
- int16 _cursorHotspotXArray[5];
- int16 _cursorHotspotYArray[5];
- TotTextTable *_totTextDataArray[5];
- byte *_totFileDataArray[5];
- TotResTable *_totResourceTableArray[5];
- ExtTable *_extTableArray[5];
- int16 _extHandleArray[5];
- byte *_imFileDataArray[5];
- Variables *_variablesArray[5];
- char _curTotFileArray[5][14];
+ int8 _curEnvironment;
+ int8 _numEnvironments;
+ Environments *_environments;
GobEngine *_vm;
virtual int16 adjustKey(int16 key);
- byte *loadLocTexts(int32 *dataSize = 0);
- int32 loadTotFile(const char *path);
- void loadExtTable(void);
- void loadImFile(void);
-
void collAreaSub(int16 index, int8 enter);
- int16 openLocTextFile(char *locTextFile, int language);
virtual void setCollisions(byte arg_0 = 1);
virtual void collSub(uint16 offset);
virtual int16 checkMousePoint(int16 all, int16 *resId, int16 *resIndex) = 0;
+
+ void clearUnusedEnvironment();
};
class Game_v1 : public Game {
diff --git a/engines/gob/game_fascin.cpp b/engines/gob/game_fascin.cpp
index 8e77141ce6..38ad03f0f8 100644
--- a/engines/gob/game_fascin.cpp
+++ b/engines/gob/game_fascin.cpp
@@ -35,7 +35,6 @@
#include "gob/goblin.h"
#include "gob/inter.h"
#include "gob/mult.h"
-#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/video.h"
#include "gob/videoplayer.h"
diff --git a/engines/gob/game_v1.cpp b/engines/gob/game_v1.cpp
index ad24d7d9c6..87dc78e3b1 100644
--- a/engines/gob/game_v1.cpp
+++ b/engines/gob/game_v1.cpp
@@ -32,11 +32,12 @@
#include "gob/global.h"
#include "gob/util.h"
#include "gob/dataio.h"
+#include "gob/script.h"
+#include "gob/resources.h"
#include "gob/draw.h"
#include "gob/inter.h"
#include "gob/mult.h"
#include "gob/video.h"
-#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/sound/sound.h"
@@ -49,12 +50,12 @@ void Game_v1::playTot(int16 skipPlay) {
int16 _captureCounter;
int16 breakFrom;
int16 nestLevel;
- int32 variablesCount;
int16 *oldNestLevel = _vm->_inter->_nestLevel;
int16 *oldBreakFrom = _vm->_inter->_breakFromLevel;
int16 *oldCaptureCounter = _vm->_scenery->_pCaptureCounter;
- byte *savedIP = _vm->_global->_inter_execPtr;
+
+ _script->push();
_vm->_inter->_nestLevel = &nestLevel;
_vm->_inter->_breakFromLevel = &breakFrom;
@@ -93,86 +94,23 @@ void Game_v1::playTot(int16 skipPlay) {
for (int i = 0; i < 20; i++)
freeSoundSlot(i);
- _totTextData = 0;
- _totResourceTable = 0;
- _imFileData = 0;
- _extTable = 0;
- _extHandle = -1;
-
_totToLoad[0] = 0;
- if ((_curTotFile[0] == 0) && (_totFileData == 0))
+ if ((_curTotFile[0] == 0) && !_script->isLoaded())
break;
- loadTotFile(_curTotFile);
- if (_totFileData == 0) {
+ if (!_script->load(_curTotFile)) {
_vm->_draw->blitCursor();
break;
}
- strcpy(_curImaFile, _curTotFile);
- strcpy(_curExtFile, _curTotFile);
-
- _curImaFile[strlen(_curImaFile) - 4] = 0;
- strcat(_curImaFile, ".ima");
-
- _curExtFile[strlen(_curExtFile) - 4] = 0;
- strcat(_curExtFile, ".ext");
-
- debugC(4, kDebugFileIO, "IMA: %s", _curImaFile);
- debugC(4, kDebugFileIO, "EXT: %s", _curExtFile);
-
- byte *filePtr = _totFileData + 0x30;
-
- _totTextData = 0;
- if (READ_LE_UINT32(filePtr) != (uint32) -1) {
- _totTextData = new TotTextTable;
- _totTextData->dataPtr =
- (_totFileData + READ_LE_UINT32(_totFileData + 0x30));
- Common::MemoryReadStream totTextData(_totTextData->dataPtr,
- 4294967295U);
-
- _totTextData->itemsCount = totTextData.readSint16LE();
-
- _totTextData->items = new TotTextItem[_totTextData->itemsCount];
- for (int i = 0; i < _totTextData->itemsCount; ++i) {
- _totTextData->items[i].offset = totTextData.readSint16LE();
- _totTextData->items[i].size = totTextData.readSint16LE();
- }
- }
-
- filePtr = _totFileData + 0x34;
- _totResourceTable = 0;
- if (READ_LE_UINT32(filePtr) != (uint32) -1) {
- _totResourceTable = new TotResTable;
- _totResourceTable->dataPtr =
- _totFileData + READ_LE_UINT32( _totFileData + 0x34);
- Common::MemoryReadStream totResTable(_totResourceTable->dataPtr,
- 4294967295U);
-
- _totResourceTable->itemsCount = totResTable.readSint16LE();
- _totResourceTable->unknown = totResTable.readByte();
-
- _totResourceTable->items =
- new TotResItem[_totResourceTable->itemsCount];
- for (int i = 0; i < _totResourceTable->itemsCount; ++i) {
- _totResourceTable->items[i].offset = totResTable.readSint32LE();
- _totResourceTable->items[i].size = totResTable.readSint16LE();
- _totResourceTable->items[i].width = totResTable.readSint16LE();
- _totResourceTable->items[i].height = totResTable.readSint16LE();
- }
- }
-
- loadImFile();
- loadExtTable();
+ _resources->load(_curTotFile);
- _vm->_global->_inter_animDataSize =
- READ_LE_UINT16(_totFileData + 0x38);
+ _vm->_global->_inter_animDataSize = _script->getAnimDataSize();
if (!_vm->_inter->_variables)
- _vm->_inter->allocateVars(READ_LE_UINT16(_totFileData + 0x2C));
+ _vm->_inter->allocateVars(_script->getVariablesCount() & 0xFFFF);
- _vm->_global->_inter_execPtr = _totFileData;
- _vm->_global->_inter_execPtr += READ_LE_UINT32(_totFileData + 0x64);
+ _script->seek(_script->getFunctionOffset(TOTFile::kFunctionStart));
_vm->_inter->renewTimeInVars();
@@ -182,39 +120,16 @@ void Game_v1::playTot(int16 skipPlay) {
WRITE_VAR(16, _vm->_global->_language);
_vm->_inter->callSub(2);
+ _script->setFinished(false);
if (_totToLoad[0] != 0)
_vm->_inter->_terminate = 0;
- variablesCount = READ_LE_UINT32(_totFileData + 0x2C);
_vm->_draw->blitInvalidated();
- delete[] _totFileData;
- _totFileData = 0;
-
- if (_totTextData) {
- delete[] _totTextData->items;
- delete _totTextData;
- }
- _totTextData = 0;
-
- if (_totResourceTable) {
- delete[] _totResourceTable->items;
- delete _totResourceTable;
- }
- _totResourceTable = 0;
-
- delete[] _imFileData;
- _imFileData = 0;
- if (_extTable)
- delete[] _extTable->items;
- delete _extTable;
- _extTable = 0;
+ _script->unload();
- if (_extHandle >= 0)
- _vm->_dataIO->closeData(_extHandle);
-
- _extHandle = -1;
+ _resources->unload();
for (int i = 0; i < *_vm->_scenery->_pCaptureCounter; i++)
capturePop(0);
@@ -241,7 +156,8 @@ void Game_v1::playTot(int16 skipPlay) {
_vm->_inter->_nestLevel = oldNestLevel;
_vm->_inter->_breakFromLevel = oldBreakFrom;
_vm->_scenery->_pCaptureCounter = oldCaptureCounter;
- _vm->_global->_inter_execPtr = savedIP;
+
+ _script->pop();
}
void Game_v1::clearCollisions() {
@@ -279,7 +195,7 @@ int16 Game_v1::addNewCollision(int16 id, uint16 left, uint16 top,
ptr->funcEnter = funcEnter;
ptr->funcLeave = funcLeave;
ptr->funcSub = funcSub;
- ptr->totFileData = 0;
+ ptr->script = 0;
return i;
}
@@ -331,7 +247,6 @@ void Game_v1::popCollisions(void) {
int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime,
int16 *pResId, int16 *pResIndex) {
- byte *savedIP;
int16 resIndex;
int16 key;
int16 oldIndex;
@@ -357,12 +272,9 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime,
_lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex);
if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) {
- savedIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr = _totFileData +
- _collisionAreas[_lastCollAreaIndex].funcEnter;
-
+ _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter);
_vm->_inter->funcBlock(0);
- _vm->_global->_inter_execPtr = savedIP;
+ _script->pop();
}
}
@@ -423,12 +335,10 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime,
if ((_lastCollKey != 0) &&
(_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) {
- savedIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr = _totFileData +
- _collisionAreas[_lastCollAreaIndex].funcLeave;
+ _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave);
_vm->_inter->funcBlock(0);
- _vm->_global->_inter_execPtr = savedIP;
+ _script->pop();
}
_lastCollKey = 0;
@@ -463,12 +373,11 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime,
if ((_lastCollKey != 0) &&
(_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) {
- savedIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr = _totFileData +
- _collisionAreas[_lastCollAreaIndex].funcLeave;
+ _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave);
_vm->_inter->funcBlock(0);
- _vm->_global->_inter_execPtr = savedIP;
+ _script->pop();
+
}
_lastCollKey = 0;
return key;
@@ -476,24 +385,22 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime,
if ((_lastCollKey != 0) &&
(_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) {
- savedIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr = _totFileData +
- _collisionAreas[_lastCollAreaIndex].funcLeave;
+ _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave);
_vm->_inter->funcBlock(0);
- _vm->_global->_inter_execPtr = savedIP;
+ _script->pop();
+
}
_lastCollKey =
checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex);
if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) {
- savedIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr = _totFileData +
- _collisionAreas[_lastCollAreaIndex].funcEnter;
+ _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter);
_vm->_inter->funcBlock(0);
- _vm->_global->_inter_execPtr = savedIP;
+ _script->pop();
+
}
} else {
@@ -507,23 +414,22 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime,
if (key != _lastCollKey) {
if ((_lastCollKey != 0) && ((oldId & 0x8000) != 0)) {
- savedIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr = _totFileData +
- _collisionAreas[oldIndex].funcLeave;
+ _script->call(_collisionAreas[oldIndex].funcLeave);
_vm->_inter->funcBlock(0);
- _vm->_global->_inter_execPtr = savedIP;
+ _script->pop();
+
}
_lastCollKey = key;
if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) {
- savedIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr = _totFileData +
- _collisionAreas[_lastCollAreaIndex].funcEnter;
+ _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter);
_vm->_inter->funcBlock(0);
- _vm->_global->_inter_execPtr = savedIP;
+ _script->pop();
+
}
+
}
}
}
@@ -588,7 +494,6 @@ void Game_v1::collisionsBlock(void) {
int16 array[250];
byte count;
int16 collResId;
- byte *startIP;
int16 curCmd;
int16 cmd;
int16 cmdHigh;
@@ -615,27 +520,27 @@ void Game_v1::collisionsBlock(void) {
int16 collStackPos;
Collision *collPtr;
uint32 timeKey;
- byte *savedIP;
if (_shouldPushColls)
pushCollisions(1);
collResId = -1;
- _vm->_global->_inter_execPtr++;
- count = *_vm->_global->_inter_execPtr++;
- _handleMouse = _vm->_global->_inter_execPtr[0];
- deltaTime = 1000 * _vm->_global->_inter_execPtr[1];
- descIndex2 = _vm->_global->_inter_execPtr[2];
- stackPos2 = _vm->_global->_inter_execPtr[3];
- descIndex = _vm->_global->_inter_execPtr[4];
+ _script->skip(1);
+ count = _script->readByte();
+ _handleMouse = _script->readByte();
+ deltaTime = 1000 * _script->readByte();
+ descIndex2 = _script->readByte();
+ stackPos2 = _script->readByte();
+ descIndex = _script->readByte();
if ((stackPos2 != 0) || (descIndex != 0))
deltaTime /= 100;
timeVal = deltaTime;
- _vm->_global->_inter_execPtr += 6;
+ _script->skip(1);
+
+ uint32 startPos = _script->pos();
- startIP = _vm->_global->_inter_execPtr;
WRITE_VAR(16, 0);
var_22 = 0;
index = 0;
@@ -643,26 +548,25 @@ void Game_v1::collisionsBlock(void) {
for (curCmd = 0; curCmd < count; curCmd++) {
array[curCmd] = 0;
- cmd = *_vm->_global->_inter_execPtr++;
+ cmd = _script->readByte();
if ((cmd & 0x40) != 0) {
cmd -= 0x40;
- cmdHigh = *_vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr++;
+ cmdHigh = _script->readByte();
cmdHigh <<= 8;
} else
cmdHigh = 0;
if ((cmd & 0x80) != 0) {
- left = _vm->_parse->parseValExpr();
- top = _vm->_parse->parseValExpr();
- width = _vm->_parse->parseValExpr();
- height = _vm->_parse->parseValExpr();
+ left = _script->readValExpr();
+ top = _script->readValExpr();
+ width = _script->readValExpr();
+ height = _script->readValExpr();
} else {
- left = _vm->_inter->load16();
- top = _vm->_inter->load16();
- width = _vm->_inter->load16();
- height = _vm->_inter->load16();
+ left = _script->readUint16();
+ top = _script->readUint16();
+ width = _script->readUint16();
+ height = _script->readUint16();
}
cmd &= 0x7F;
@@ -680,16 +584,16 @@ void Game_v1::collisionsBlock(void) {
_vm->_util->clearKeyBuf();
var_22 = 1;
- key = _vm->_parse->parseVarIndex();
- descArray[index].fontIndex = _vm->_inter->load16();
- descArray[index].backColor = *_vm->_global->_inter_execPtr++;
- descArray[index].frontColor = *_vm->_global->_inter_execPtr++;
+ key = _script->readVarIndex();
+ descArray[index].fontIndex = _script->readInt16();
+ descArray[index].backColor = _script->readByte();
+ descArray[index].frontColor = _script->readByte();
if ((cmd < 5) || (cmd > 8)) {
descArray[index].ptr = 0;
} else {
- descArray[index].ptr = _vm->_global->_inter_execPtr + 2;
- _vm->_global->_inter_execPtr += _vm->_inter->load16();
+ descArray[index].ptr = _script->getData() + _script->pos() + 2;
+ _script->skip(_script->readInt16());
}
if (left == 0xFFFF)
@@ -698,12 +602,9 @@ void Game_v1::collisionsBlock(void) {
if ((cmd & 1) == 0) {
addNewCollision(curCmd + 0x8000, left, top, left + width *
_vm->_draw->_fonts[descArray[index].fontIndex]->itemWidth - 1,
- top + height - 1, cmd, key, 0,
- _vm->_global->_inter_execPtr - _totFileData);
+ top + height - 1, cmd, key, 0, _script->pos());
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
} else {
addNewCollision(curCmd + 0x8000, left, top, left + width *
_vm->_draw->_fonts[descArray[index].fontIndex]->itemWidth - 1,
@@ -713,18 +614,15 @@ void Game_v1::collisionsBlock(void) {
break;
case 21:
- key = _vm->_inter->load16();
- array[curCmd] = _vm->_inter->load16();
- flags = _vm->_inter->load16() & 3;
+ key = _script->readInt16();
+ array[curCmd] = _script->readInt16();
+ flags = _script->readInt16() & 3;
addNewCollision(curCmd + 0x8000, left, top,
left + width - 1, top + height - 1,
- (flags << 4) + cmdHigh + 2, key,
- _vm->_global->_inter_execPtr - _totFileData, 0);
+ (flags << 4) + cmdHigh + 2, key, _script->pos(), 0);
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
break;
case 20:
@@ -732,61 +630,48 @@ void Game_v1::collisionsBlock(void) {
// Fall through to case 2
case 2:
- key = _vm->_inter->load16();
- array[curCmd] = _vm->_inter->load16();
- flags = _vm->_inter->load16() & 3;
+ key = _script->readInt16();
+ array[curCmd] = _script->readInt16();
+ flags = _script->readInt16() & 3;
addNewCollision(curCmd + 0x8000, left, top,
left + width - 1,
top + height - 1,
- (flags << 4) + cmdHigh + 2, key, 0,
- _vm->_global->_inter_execPtr - _totFileData);
+ (flags << 4) + cmdHigh + 2, key, 0, _script->pos());
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
break;
case 0:
- _vm->_global->_inter_execPtr += 6;
- startIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(6);
+ startPos = _script->pos();
+ _script->skip(_script->peekUint16(2) + 2);
key = curCmd + 0xA000;
addNewCollision(curCmd + 0x8000, left, top,
left + width - 1, top + height - 1,
cmd + cmdHigh, key,
- startIP - _totFileData,
- _vm->_global->_inter_execPtr - _totFileData);
+ startPos, _script->pos());
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
break;
case 1:
- key = _vm->_inter->load16();
- array[curCmd] = _vm->_inter->load16();
- flags = _vm->_inter->load16() & 3;
-
- startIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ key = _script->readInt16();
+ array[curCmd] = _script->readInt16();
+ flags = _script->readInt16() & 3;
+
+ startPos = _script->pos();
+ _script->skip(_script->peekUint16(2) + 2);
if (key == 0)
key = curCmd + 0xA000;
addNewCollision(curCmd + 0x8000, left, top,
left + width - 1, top + height - 1,
(flags << 4) + cmd + cmdHigh, key,
- startIP - _totFileData,
- _vm->_global->_inter_execPtr - _totFileData);
+ startPos, _script->pos());
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
break;
}
}
@@ -895,9 +780,11 @@ void Game_v1::collisionsBlock(void) {
if (collPtr->funcLeave != 0) {
timeKey = _vm->_util->getTimeKey();
- savedIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr =
- _totFileData + collPtr->funcLeave;
+
+ uint32 savedPos = _script->pos();
+
+ _script->seek(collPtr->funcLeave);
+
_shouldPushColls = 1;
savedCollStackSize = _collStackSize;
_vm->_inter->funcBlock(0);
@@ -906,7 +793,8 @@ void Game_v1::collisionsBlock(void) {
popCollisions();
_shouldPushColls = 0;
- _vm->_global->_inter_execPtr = savedIP;
+
+ _script->seek(savedPos);
deltaTime = timeVal -
(_vm->_util->getTimeKey() - timeKey);
@@ -986,9 +874,9 @@ void Game_v1::collisionsBlock(void) {
WRITE_VAR(16, array[(uint16) _activeCollResId & ~0x8000]);
if (_collisionAreas[_activeCollIndex].funcEnter != 0) {
- savedIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr = _totFileData +
- _collisionAreas[_activeCollIndex].funcEnter;
+ uint32 savedPos = _script->pos();
+
+ _script->seek(_collisionAreas[_activeCollIndex].funcEnter);
_shouldPushColls = 1;
@@ -997,7 +885,8 @@ void Game_v1::collisionsBlock(void) {
if (collStackPos != _collStackSize)
popCollisions();
_shouldPushColls = 0;
- _vm->_global->_inter_execPtr = savedIP;
+
+ _script->seek(savedPos);
}
WRITE_VAR(16, 0);
@@ -1071,10 +960,8 @@ void Game_v1::collisionsBlock(void) {
WRITE_VAR(17, 1);
}
- savedIP = 0;
if (!_vm->_inter->_terminate) {
- savedIP = _totFileData +
- _collisionAreas[_activeCollIndex].funcLeave;
+ _script->seek(_collisionAreas[_activeCollIndex].funcLeave);
WRITE_VAR(2, _vm->_global->_inter_mouseX);
WRITE_VAR(3, _vm->_global->_inter_mouseY);
@@ -1082,12 +969,11 @@ void Game_v1::collisionsBlock(void) {
if (VAR(16) == 0)
WRITE_VAR(16, array[(uint16) _activeCollResId & ~0x8000]);
- }
+ } else
+ _script->setFinished(true);
for (curCmd = 0; curCmd < count; curCmd++)
freeCollision(curCmd + 0x8000);
-
- _vm->_global->_inter_execPtr = savedIP;
}
int16 Game_v1::multiEdit(int16 time, int16 index, int16 *pCurPos,
diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp
index e9656efa32..08184e73d0 100644
--- a/engines/gob/game_v2.cpp
+++ b/engines/gob/game_v2.cpp
@@ -32,11 +32,12 @@
#include "gob/global.h"
#include "gob/util.h"
#include "gob/dataio.h"
+#include "gob/script.h"
+#include "gob/resources.h"
#include "gob/draw.h"
#include "gob/goblin.h"
#include "gob/inter.h"
#include "gob/mult.h"
-#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/video.h"
#include "gob/videoplayer.h"
@@ -55,15 +56,12 @@ void Game_v2::playTot(int16 skipPlay) {
int16 _captureCounter;
int16 breakFrom;
int16 nestLevel;
- int32 totSize;
- byte *filePtr;
- byte *savedIP;
- bool totTextLoc;
oldNestLevel = _vm->_inter->_nestLevel;
oldBreakFrom = _vm->_inter->_breakFromLevel;
oldCaptureCounter = _vm->_scenery->_pCaptureCounter;
- savedIP = _vm->_global->_inter_execPtr;
+
+ _script->push();
_vm->_inter->_nestLevel = &nestLevel;
_vm->_inter->_breakFromLevel = &breakFrom;
@@ -94,125 +92,30 @@ void Game_v2::playTot(int16 skipPlay) {
} else
_vm->_inter->initControlVars(0);
- _totTextData = 0;
- _totResourceTable = 0;
- _imFileData = 0;
- _extTable = 0;
- _extHandle = -1;
-
_vm->_draw->_cursorHotspotXVar = -1;
_totToLoad[0] = 0;
- if ((_curTotFile[0] == 0) && (_totFileData == 0))
+ if ((_curTotFile[0] == 0) && (!_script->isLoaded()))
break;
- totSize = loadTotFile(_curTotFile);
-
if (skipPlay == -2) {
_vm->_vidPlayer->primaryClose();
skipPlay = 0;
}
- if (_totFileData == 0) {
+ if (!_script->load(_curTotFile)) {
_vm->_draw->blitCursor();
_vm->_inter->_terminate = 2;
break;
}
- strcpy(_curImaFile, _curTotFile);
- strcpy(_curExtFile, _curTotFile);
-
- _curImaFile[strlen(_curImaFile) - 4] = 0;
- strcat(_curImaFile, ".ima");
-
- _curExtFile[strlen(_curExtFile) - 4] = 0;
- strcat(_curExtFile, ".ext");
-
- debugC(4, kDebugFileIO, "IMA: %s", _curImaFile);
- debugC(4, kDebugFileIO, "EXT: %s", _curExtFile);
-
- filePtr = _totFileData + 0x30;
-
- _totTextData = 0;
- totTextLoc = false;
- if (READ_LE_UINT32(filePtr) != (uint32) -1) {
- _totTextData = new TotTextTable;
-
- int32 size;
-
- if (READ_LE_UINT32(filePtr) == 0) {
- _totTextData->dataPtr = loadLocTexts(&size);
- totTextLoc = true;
- } else {
- _totTextData->dataPtr =
- (_totFileData + READ_LE_UINT32(_totFileData + 0x30));
- size = totSize;
- _vm->_global->_language = _vm->_global->_languageWanted;
- }
-
- _totTextData->items = 0;
- if (_totTextData->dataPtr != 0) {
- Common::MemoryReadStream totTextData(_totTextData->dataPtr,
- 4294967295U);
- _totTextData->itemsCount = totTextData.readSint16LE() & 0x3FFF;
-
- _totTextData->items = new TotTextItem[_totTextData->itemsCount];
- for (int i = 0; i < _totTextData->itemsCount; ++i) {
- _totTextData->items[i].offset = totTextData.readSint16LE();
- _totTextData->items[i].size = totTextData.readSint16LE();
- }
- }
- }
-
- filePtr = _totFileData + 0x34;
- _totResourceTable = 0;
- int32 resSize;
- if (READ_LE_UINT32(filePtr) != (uint32) -1) {
- _totResourceTable = new TotResTable;
- _totResourceTable->dataPtr =
- _totFileData + READ_LE_UINT32(_totFileData + 0x34);
- Common::MemoryReadStream totResTable(_totResourceTable->dataPtr,
- 4294967295U);
-
- _totResourceTable->itemsCount = totResTable.readSint16LE();
- resSize = _totResourceTable->itemsCount * szGame_TotResItem + szGame_TotResTable;
- if (totSize > (resSize + 0x34)) {
- _totResourceTable->unknown = totResTable.readByte();
-
- _totResourceTable->items =
- new TotResItem[_totResourceTable->itemsCount];
- for (int i = 0; i < _totResourceTable->itemsCount; ++i) {
- _totResourceTable->items[i].offset = totResTable.readSint32LE();
- _totResourceTable->items[i].size = totResTable.readSint16LE();
- _totResourceTable->items[i].width = totResTable.readSint16LE();
- _totResourceTable->items[i].height = totResTable.readSint16LE();
- }
- }
- else {
- // WORKAROUND: In the original asm, _totResourceTable is
- // only assigned in playTot and evaluated later, right
- // before using it. In the Gobliins 2 demo, there is a
- // dummy tot that loads another tot, overwriting the dummy
- // pointer with the real one.
- debugC(1, kDebugFileIO,
- "Attempted to load invalid resource table (size = %d, totSize = %d)",
- resSize, totSize);
- delete _totResourceTable;
- _totResourceTable = 0;
- }
- }
-
- loadImFile();
- loadExtTable();
+ _resources->load(_curTotFile);
- _vm->_global->_inter_animDataSize =
- READ_LE_UINT16(_totFileData + 0x38);
+ _vm->_global->_inter_animDataSize = _script->getAnimDataSize();
if (!_vm->_inter->_variables)
- _vm->_inter->allocateVars(READ_LE_UINT16(_totFileData + 0x2C));
+ _vm->_inter->allocateVars(_script->getVariablesCount() & 0xFFFF);
- _vm->_global->_inter_execPtr = _totFileData;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_totFileData + 0x64);
+ _script->seek(_script->getFunctionOffset(TOTFile::kFunctionStart));
_vm->_inter->renewTimeInVars();
@@ -227,35 +130,10 @@ void Game_v2::playTot(int16 skipPlay) {
_vm->_inter->_terminate = 0;
_vm->_draw->blitInvalidated();
- delete[] _totFileData;
- _totFileData = 0;
-
- if (_totTextData) {
- delete[] _totTextData->items;
- if (totTextLoc)
- delete[] _totTextData->dataPtr;
- delete _totTextData;
- }
- _totTextData = 0;
- if (_totResourceTable) {
- delete[] _totResourceTable->items;
- delete _totResourceTable;
- }
- _totResourceTable = 0;
-
- delete[] _imFileData;
- _imFileData = 0;
-
- if (_extTable)
- delete[] _extTable->items;
- delete _extTable;
- _extTable = 0;
-
- if (_extHandle >= 0)
- _vm->_dataIO->closeData(_extHandle);
+ _script->unload();
- _extHandle = -1;
+ _resources->unload();
for (int i = 0; i < *_vm->_scenery->_pCaptureCounter; i++)
capturePop(0);
@@ -282,9 +160,7 @@ void Game_v2::playTot(int16 skipPlay) {
} else {
_vm->_inter->initControlVars(0);
_vm->_scenery->_pCaptureCounter = oldCaptureCounter;
- _vm->_global->_inter_execPtr = _totFileData;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_totFileData + (skipPlay << 1) + 0x66);
+ _script->seek(_script->getFunctionOffset(skipPlay + 1));
_menuLevel++;
_vm->_inter->callSub(2);
@@ -299,7 +175,8 @@ void Game_v2::playTot(int16 skipPlay) {
_vm->_inter->_nestLevel = oldNestLevel;
_vm->_inter->_breakFromLevel = oldBreakFrom;
_vm->_scenery->_pCaptureCounter = oldCaptureCounter;
- _vm->_global->_inter_execPtr = savedIP;
+
+ _script->pop();
}
void Game_v2::clearCollisions() {
@@ -337,7 +214,7 @@ int16 Game_v2::addNewCollision(int16 id, uint16 left, uint16 top,
ptr->funcEnter = funcEnter;
ptr->funcLeave = funcLeave;
ptr->funcSub = funcSub;
- ptr->totFileData = 0;
+ ptr->script = 0;
return i;
}
@@ -604,7 +481,6 @@ void Game_v2::collisionsBlock(void) {
int16 array[250];
byte count;
int16 collResId;
- byte *startIP;
int16 curCmd;
int16 cmd;
int16 cmdHigh;
@@ -621,7 +497,6 @@ void Game_v2::collisionsBlock(void) {
int16 stackPos2;
int16 descIndex;
int16 timeVal;
- int16 offsetIP;
char *str;
int16 i;
int16 counter;
@@ -631,8 +506,9 @@ void Game_v2::collisionsBlock(void) {
Collision *collPtr;
Collision *collArea;
int16 timeKey;
- byte *savedIP;
byte collAreaStart;
+ uint32 startPos;
+ uint32 offsetPos;
if (_shouldPushColls)
pushCollisions(0);
@@ -645,21 +521,22 @@ void Game_v2::collisionsBlock(void) {
_shouldPushColls = 0;
collResId = -1;
- _vm->_global->_inter_execPtr++;
- count = *_vm->_global->_inter_execPtr++;
+ _script->skip(1);
+ count = _script->readByte();
- _handleMouse = _vm->_global->_inter_execPtr[0];
- deltaTime = 1000 * _vm->_global->_inter_execPtr[1];
- stackPos2 = _vm->_global->_inter_execPtr[3];
- descIndex = _vm->_global->_inter_execPtr[4];
+ _handleMouse = _script->readByte();
+ deltaTime = 1000 * _script->readByte();
+ _script->skip(1);
+ stackPos2 = _script->readByte();
+ descIndex = _script->readByte();
if ((stackPos2 != 0) || (descIndex != 0))
deltaTime /= 100;
timeVal = deltaTime;
- _vm->_global->_inter_execPtr += 6;
+ _script->skip(1);
- startIP = _vm->_global->_inter_execPtr;
+ startPos = _script->pos();
WRITE_VAR(16, 0);
var_1C = 0;
@@ -668,28 +545,27 @@ void Game_v2::collisionsBlock(void) {
for (curCmd = 0; curCmd < count; curCmd++) {
array[curCmd] = 0;
- cmd = *_vm->_global->_inter_execPtr++;
+ cmd = _script->readByte();
if ((cmd & 0x40) != 0) {
cmd -= 0x40;
- cmdHigh = *_vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr++;
+ cmdHigh = _script->readByte();
cmdHigh <<= 8;
} else
cmdHigh = 0;
if ((cmd & 0x80) != 0) {
- offsetIP = _vm->_global->_inter_execPtr - _totFileData;
- left = _vm->_parse->parseValExpr();
- top = _vm->_parse->parseValExpr();
- width = _vm->_parse->parseValExpr();
- height = _vm->_parse->parseValExpr();
+ offsetPos = _script->pos();
+ left = _script->readValExpr();
+ top = _script->readValExpr();
+ width = _script->readValExpr();
+ height = _script->readValExpr();
} else {
- offsetIP = 0;
- left = _vm->_inter->load16();
- top = _vm->_inter->load16();
- width = _vm->_inter->load16();
- height = _vm->_inter->load16();
+ offsetPos = 0;
+ left = _script->readUint16();
+ top = _script->readUint16();
+ width = _script->readUint16();
+ height = _script->readUint16();
}
if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) {
@@ -712,46 +588,37 @@ void Game_v2::collisionsBlock(void) {
switch (cmd) {
case 0:
- _vm->_global->_inter_execPtr += 6;
- startIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(6);
+ startPos = _script->pos();
+ _script->skip(_script->peekUint16(2) + 2);
key = curCmd + 0xA000;
addNewCollision(curCmd + 0x8000, left, top,
left + width - 1, top + height - 1,
- cmd + cmdHigh, key, startIP - _totFileData,
- _vm->_global->_inter_execPtr - _totFileData, offsetIP);
+ cmd + cmdHigh, key, startPos,
+ _script->pos(), offsetPos);
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
break;
case 1:
- key = _vm->_inter->load16();
- array[curCmd] = _vm->_inter->load16();
- flags = _vm->_inter->load16();
+ key = _script->readInt16();
+ array[curCmd] = _script->readInt16();
+ flags = _script->readInt16();
- startIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ startPos = _script->pos();
+ _script->skip(_script->peekUint16(2) + 2);
if (key == 0)
key = curCmd + 0xA000;
addNewCollision(curCmd + 0x8000, left, top,
left + width - 1, top + height - 1,
- (flags << 4) + cmd + cmdHigh, key, startIP - _totFileData,
- _vm->_global->_inter_execPtr - _totFileData, offsetIP);
-
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ (flags << 4) + cmd + cmdHigh, key, startPos,
+ _script->pos(), offsetPos);
+ _script->skip(_script->peekUint16(2) + 2);
break;
case 3:
@@ -764,23 +631,20 @@ void Game_v2::collisionsBlock(void) {
case 10:
_vm->_util->clearKeyBuf();
var_1C = 1;
- key = _vm->_parse->parseVarIndex();
- descArray[index].fontIndex = _vm->_inter->load16();
- descArray[index].backColor = *_vm->_global->_inter_execPtr++;
- descArray[index].frontColor = *_vm->_global->_inter_execPtr++;
+ key = _script->readVarIndex();
+ descArray[index].fontIndex = _script->readInt16();
+ descArray[index].backColor = _script->readByte();
+ descArray[index].frontColor = _script->readByte();
if ((cmd >= 5) && (cmd <= 8)) {
- descArray[index].ptr = _vm->_global->_inter_execPtr + 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr) + 2;
+ descArray[index].ptr = _script->getData() + _script->pos() + 2;
+ _script->skip(_script->peekUint16() + 2);
} else
descArray[index].ptr = 0;
if (left == 0xFFFF) {
if ((cmd & 1) == 0) {
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
}
break;
}
@@ -789,11 +653,9 @@ void Game_v2::collisionsBlock(void) {
addNewCollision(curCmd + 0x8000, left, top, left + width *
_vm->_draw->_fonts[descArray[index].fontIndex]-> itemWidth - 1,
top + height - 1, cmd, key, 0,
- _vm->_global->_inter_execPtr - _totFileData);
+ _script->pos());
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
} else
addNewCollision(curCmd + 0x8000, left, top, left + width *
_vm->_draw->_fonts[descArray[index].fontIndex]-> itemWidth - 1,
@@ -803,35 +665,31 @@ void Game_v2::collisionsBlock(void) {
break;
case 11:
- _vm->_global->_inter_execPtr += 6;
+ _script->skip(6);
for (i = 0; i < 150; i++) {
if ((_collisionAreas[i].id & 0xF000) == 0xE000) {
_collisionAreas[i].id &= 0xBFFF;
_collisionAreas[i].funcEnter =
- _vm->_global->_inter_execPtr - _totFileData;
+ _script->pos();
_collisionAreas[i].funcLeave =
- _vm->_global->_inter_execPtr - _totFileData;
+ _script->pos();
}
}
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
break;
case 12:
- _vm->_global->_inter_execPtr += 6;
+ _script->skip(6);
for (i = 0; i < 150; i++) {
if ((_collisionAreas[i].id & 0xF000) == 0xD000) {
_collisionAreas[i].id &= 0xBFFF;
_collisionAreas[i].funcEnter =
- _vm->_global->_inter_execPtr - _totFileData;
+ _script->pos();
_collisionAreas[i].funcLeave =
- _vm->_global->_inter_execPtr - _totFileData;
+ _script->pos();
}
}
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
break;
case 20:
@@ -839,34 +697,30 @@ void Game_v2::collisionsBlock(void) {
// Fall through to case 2
case 2:
- key = _vm->_inter->load16();
- array[curCmd] = _vm->_inter->load16();
- flags = _vm->_inter->load16();
+ key = _script->readInt16();
+ array[curCmd] = _script->readInt16();
+ flags = _script->readInt16();
addNewCollision(curCmd + 0x8000, left, top,
left + width - 1, top + height - 1,
(flags << 4) + cmdHigh + 2, key, 0,
- _vm->_global->_inter_execPtr - _totFileData, offsetIP);
+ _script->pos(), offsetPos);
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
break;
case 21:
- key = _vm->_inter->load16();
- array[curCmd] = _vm->_inter->load16();
- flags = _vm->_inter->load16() & 3;
+ key = _script->readInt16();
+ array[curCmd] = _script->readInt16();
+ flags = _script->readInt16() & 3;
addNewCollision(curCmd + 0x8000, left, top,
left + width - 1, top + height - 1,
(flags << 4) + cmdHigh + 2, key,
- _vm->_global->_inter_execPtr - _totFileData, 0, offsetIP);
+ _script->pos(), 0, offsetPos);
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
break;
}
@@ -1116,10 +970,8 @@ void Game_v2::collisionsBlock(void) {
if (_handleMouse == 1)
_vm->_draw->blitCursor();
- savedIP = 0;
if (!_vm->_inter->_terminate) {
- savedIP = _totFileData +
- _collisionAreas[_activeCollIndex].funcLeave;
+ _script->seek(_collisionAreas[_activeCollIndex].funcLeave);
_vm->_inter->storeMouse();
if (VAR(16) == 0) {
@@ -1128,7 +980,8 @@ void Game_v2::collisionsBlock(void) {
else
WRITE_VAR(16, _activeCollResId & 0xFFF);
}
- }
+ } else
+ _script->setFinished(true);
for (curCmd = 0; curCmd < count; curCmd++)
freeCollision(curCmd + 0x8000);
@@ -1138,8 +991,6 @@ void Game_v2::collisionsBlock(void) {
((_collisionAreas[i].id & 0xF000) == 0x9000))
_collisionAreas[i].id |= 0x4000;
}
-
- _vm->_global->_inter_execPtr = savedIP;
}
int16 Game_v2::multiEdit(int16 time, int16 index, int16 *pCurPos,
diff --git a/engines/gob/game_v6.cpp b/engines/gob/game_v6.cpp
index 9d9bd1faa3..8d40d41acc 100644
--- a/engines/gob/game_v6.cpp
+++ b/engines/gob/game_v6.cpp
@@ -31,9 +31,10 @@
#include "gob/game.h"
#include "gob/helper.h"
#include "gob/global.h"
+#include "gob/script.h"
+#include "gob/resources.h"
#include "gob/inter.h"
#include "gob/draw.h"
-#include "gob/parse.h"
namespace Gob {
@@ -48,27 +49,17 @@ void Game_v6::totSub(int8 flags, const char *newTotFile) {
if ((flags == 16) || (flags == 17))
warning("Urban Stub: Game_v6::totSub(), flags == %d", flags);
- if (_backupedCount >= 5)
+ if (_numEnvironments >= Environments::kEnvironmentCount)
return;
- _cursorHotspotXArray[_backupedCount] = _vm->_draw->_cursorHotspotXVar;
- _cursorHotspotYArray[_backupedCount] = _vm->_draw->_cursorHotspotYVar;
- _totTextDataArray[_backupedCount] = _totTextData;
- _totFileDataArray[_backupedCount] = _totFileData;
- _totResourceTableArray[_backupedCount] = _totResourceTable;
- _extTableArray[_backupedCount] = _extTable;
- _extHandleArray[_backupedCount] = _extHandle;
- _imFileDataArray[_backupedCount] = _imFileData;
- _variablesArray[_backupedCount] = _vm->_inter->_variables;
- strcpy(_curTotFileArray[_backupedCount], _curTotFile);
-
- curBackupPos = _curBackupPos;
- _backupedCount++;
- _curBackupPos = _backupedCount;
-
- _totTextData = 0;
- _totFileData = 0;
- _totResourceTable = 0;
+ _environments->set(_numEnvironments);
+
+ curBackupPos = _curEnvironment;
+ _numEnvironments++;
+ _curEnvironment = _numEnvironments;
+
+ _script = new Script(_vm);
+ _resources = new Resources(_vm);
if (flags & 0x80)
warning("Urban Stub: Game_v6::totSub(), flags & 0x80");
@@ -79,8 +70,10 @@ void Game_v6::totSub(int8 flags, const char *newTotFile) {
strncpy0(_curTotFile, newTotFile, 9);
strcat(_curTotFile, ".TOT");
- if (_vm->_inter->_terminate != 0)
+ if (_vm->_inter->_terminate != 0) {
+ clearUnusedEnvironment();
return;
+ }
pushCollisions(0);
@@ -99,22 +92,11 @@ void Game_v6::totSub(int8 flags, const char *newTotFile) {
_vm->_inter->delocateVars();
}
- _backupedCount--;
- _curBackupPos = curBackupPos;
-
- _vm->_draw->_cursorHotspotXVar = _cursorHotspotXArray[_backupedCount];
- _vm->_draw->_cursorHotspotYVar = _cursorHotspotYArray[_backupedCount];
- _totTextData = _totTextDataArray[_backupedCount];
- _totFileData = _totFileDataArray[_backupedCount];
- _totResourceTable = _totResourceTableArray[_backupedCount];
- _extTable = _extTableArray[_backupedCount];
- _extHandle = _extHandleArray[_backupedCount];
- _imFileData = _imFileDataArray[_backupedCount];
- _vm->_inter->_variables = _variablesArray[_backupedCount];
- strcpy(_curTotFile, _curTotFileArray[_backupedCount]);
- strcpy(_curExtFile, _curTotFile);
- _curExtFile[strlen(_curExtFile) - 4] = '\0';
- strcat(_curExtFile, ".EXT");
+ clearUnusedEnvironment();
+
+ _numEnvironments--;
+ _curEnvironment = curBackupPos;
+ _environments->get(_numEnvironments);
}
int16 Game_v6::addNewCollision(int16 id, uint16 left, uint16 top,
@@ -148,7 +130,7 @@ int16 Game_v6::addNewCollision(int16 id, uint16 left, uint16 top,
ptr->funcEnter = funcEnter;
ptr->funcLeave = funcLeave;
ptr->funcSub = funcSub;
- ptr->totFileData = _totFileData;
+ ptr->script = _script;
return i;
}
@@ -383,7 +365,6 @@ void Game_v6::collisionsBlock(void) {
int16 array[300];
byte count;
int16 collResId;
- byte *startIP;
int16 curCmd;
int16 cmd;
int16 cmdHigh;
@@ -397,7 +378,6 @@ void Game_v6::collisionsBlock(void) {
int16 stackPos2;
int16 descIndex;
int16 timeVal;
- int16 offsetIP;
char *str;
int16 i;
int16 counter;
@@ -406,10 +386,11 @@ void Game_v6::collisionsBlock(void) {
int16 collStackPos;
Collision *collPtr;
Collision *collArea;
- byte *savedIP;
byte collAreaStart;
int16 activeCollResId = 0;
int16 activeCollIndex = 0;
+ uint32 startPos;
+ uint32 offsetPos;
if (_shouldPushColls)
pushCollisions(0);
@@ -422,25 +403,25 @@ void Game_v6::collisionsBlock(void) {
_shouldPushColls = 0;
collResId = -1;
- _vm->_global->_inter_execPtr++;
- count = *_vm->_global->_inter_execPtr++;
+ _script->skip(1);
+ count = _script->readByte();
- _handleMouse = _vm->_global->_inter_execPtr[0];
- deltaTime = 1000 * _vm->_global->_inter_execPtr[1];
- stackPos2 = _vm->_global->_inter_execPtr[3];
- descIndex = _vm->_global->_inter_execPtr[4];
- byte var_42 = _vm->_global->_inter_execPtr[5];
+ _handleMouse = _script->peekByte(0);
+ deltaTime = 1000 * _script->peekByte(1);
+ stackPos2 = _script->peekByte(3);
+ descIndex = _script->peekByte(4);
+ byte var_42 = _script->peekByte(5);
if ((stackPos2 != 0) || (descIndex != 0)) {
deltaTime /= 100;
- if (_vm->_global->_inter_execPtr[1] == 100)
+ if (_script->peekByte(1) == 100)
deltaTime = 2;
}
timeVal = deltaTime;
- _vm->_global->_inter_execPtr += 6;
+ _script->skip(6);
- startIP = _vm->_global->_inter_execPtr;
+ startPos = _script->pos();
WRITE_VAR(16, 0);
byte var_41 = 0;
@@ -452,28 +433,27 @@ void Game_v6::collisionsBlock(void) {
for (curCmd = 0; curCmd < count; curCmd++) {
array[curCmd] = 0;
- cmd = *_vm->_global->_inter_execPtr++;
+ cmd = _script->readByte();
if ((cmd & 0x40) != 0) {
cmd -= 0x40;
- cmdHigh = *_vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr++;
+ cmdHigh = _script->readByte();
cmdHigh <<= 8;
} else
cmdHigh = 0;
if ((cmd & 0x80) != 0) {
- offsetIP = _vm->_global->_inter_execPtr - _totFileData;
- left = _vm->_parse->parseValExpr();
- top = _vm->_parse->parseValExpr();
- width = _vm->_parse->parseValExpr();
- height = _vm->_parse->parseValExpr();
+ offsetPos = _script->pos();
+ left = _script->readValExpr();
+ top = _script->readValExpr();
+ width = _script->readValExpr();
+ height = _script->readValExpr();
} else {
- offsetIP = 0;
- left = _vm->_inter->load16();
- top = _vm->_inter->load16();
- width = _vm->_inter->load16();
- height = _vm->_inter->load16();
+ offsetPos = 0;
+ left = _script->readUint16();
+ top = _script->readUint16();
+ width = _script->readUint16();
+ height = _script->readUint16();
}
if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) {
@@ -496,45 +476,37 @@ void Game_v6::collisionsBlock(void) {
switch (cmd) {
case 0:
- _vm->_global->_inter_execPtr += 6;
- startIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(6);
+ startPos = _script->pos();
+ _script->skip(_script->peekUint16(2) + 2);
key = curCmd + 0xA000;
addNewCollision(curCmd + 0x8000, left, top,
left + width - 1, top + height - 1,
- cmd + cmdHigh, key, startIP - _totFileData,
- _vm->_global->_inter_execPtr - _totFileData, offsetIP);
+ cmd + cmdHigh, key, startPos,
+ _script->pos(), offsetPos);
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
break;
case 1:
- key = _vm->_inter->load16();
- array[curCmd] = _vm->_inter->load16();
- flags = _vm->_inter->load16();
+ key = _script->readInt16();
+ array[curCmd] = _script->readInt16();
+ flags = _script->readInt16();
- startIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ startPos = _script->pos();
+ _script->skip(_script->peekUint16(2) + 2);
if (key == 0)
key = curCmd + 0xA000;
addNewCollision(curCmd + 0x8000, left, top,
left + width - 1, top + height - 1,
- (flags << 4) + cmd + cmdHigh, key, startIP - _totFileData,
- _vm->_global->_inter_execPtr - _totFileData, offsetIP);
+ (flags << 4) + cmd + cmdHigh, key, startPos,
+ _script->pos(), offsetPos);
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
break;
@@ -548,23 +520,20 @@ void Game_v6::collisionsBlock(void) {
case 10:
_vm->_util->clearKeyBuf();
var_1C = 1;
- key = _vm->_parse->parseVarIndex();
- descArray[index].fontIndex = _vm->_inter->load16();
- descArray[index].backColor = *_vm->_global->_inter_execPtr++;
- descArray[index].frontColor = *_vm->_global->_inter_execPtr++;
+ key = _script->readVarIndex();
+ descArray[index].fontIndex = _script->readInt16();
+ descArray[index].backColor = _script->readByte();
+ descArray[index].frontColor = _script->readByte();
if ((cmd >= 5) && (cmd <= 8)) {
- descArray[index].ptr = _vm->_global->_inter_execPtr + 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr) + 2;
+ descArray[index].ptr = _script->getData() + _script->pos() + 2;
+ _script->skip(_script->peekUint16() + 2);
} else
descArray[index].ptr = 0;
if (left == 0xFFFF) {
if ((cmd & 1) == 0) {
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
}
break;
}
@@ -575,50 +544,44 @@ void Game_v6::collisionsBlock(void) {
funcLeave = 0;
if (!(cmd & 1))
- funcLeave = _vm->_global->_inter_execPtr - _totFileData;
+ funcLeave = _script->pos();
addNewCollision(curCmd + 0x8000, left, top, right,
top + height - 1, cmd, key, 0, funcLeave, 0);
if (!(cmd & 1)) {
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
}
index++;
break;
case 11:
- _vm->_global->_inter_execPtr += 6;
+ _script->skip(6);
for (i = 0; i < 150; i++) {
if ((_collisionAreas[i].id & 0xF000) == 0xE000) {
_collisionAreas[i].id &= 0xBFFF;
_collisionAreas[i].funcEnter =
- _vm->_global->_inter_execPtr - _totFileData;
+ _script->pos();
_collisionAreas[i].funcLeave =
- _vm->_global->_inter_execPtr - _totFileData;
+ _script->pos();
}
}
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
break;
case 12:
- _vm->_global->_inter_execPtr += 6;
+ _script->skip(6);
for (i = 0; i < 150; i++) {
if ((_collisionAreas[i].id & 0xF000) == 0xD000) {
_collisionAreas[i].id &= 0xBFFF;
_collisionAreas[i].funcEnter =
- _vm->_global->_inter_execPtr - _totFileData;
+ _script->pos();
_collisionAreas[i].funcLeave =
- _vm->_global->_inter_execPtr - _totFileData;
+ _script->pos();
}
}
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
break;
case 20:
@@ -626,34 +589,30 @@ void Game_v6::collisionsBlock(void) {
// Fall through to case 2
case 2:
- key = _vm->_inter->load16();
- array[curCmd] = _vm->_inter->load16();
- flags = _vm->_inter->load16();
+ key = _script->readInt16();
+ array[curCmd] = _script->readInt16();
+ flags = _script->readInt16();
addNewCollision(curCmd + 0x8000, left, top,
left + width - 1, top + height - 1,
(flags << 4) + cmdHigh + 2, key, 0,
- _vm->_global->_inter_execPtr - _totFileData, offsetIP);
+ _script->pos(), offsetPos);
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
break;
case 21:
- key = _vm->_inter->load16();
- array[curCmd] = _vm->_inter->load16();
- flags = _vm->_inter->load16() & 3;
+ key = _script->readInt16();
+ array[curCmd] = _script->readInt16();
+ flags = _script->readInt16() & 3;
addNewCollision(curCmd + 0x8000, left, top,
left + width - 1, top + height - 1,
(flags << 4) + cmdHigh + 2, key,
- _vm->_global->_inter_execPtr - _totFileData, 0, offsetIP);
+ _script->pos(), 0, offsetPos);
- _vm->_global->_inter_execPtr += 2;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _script->skip(_script->peekUint16(2) + 2);
break;
}
@@ -915,10 +874,8 @@ void Game_v6::collisionsBlock(void) {
if (_handleMouse == 1)
_vm->_draw->blitCursor();
- savedIP = 0;
if (!_vm->_inter->_terminate && (var_41 == 0)) {
- savedIP = _totFileData +
- _collisionAreas[activeCollIndex].funcLeave;
+ _script->seek(_collisionAreas[activeCollIndex].funcLeave);
_vm->_inter->storeMouse();
if (VAR(16) == 0) {
@@ -927,7 +884,8 @@ void Game_v6::collisionsBlock(void) {
else
WRITE_VAR(16, activeCollResId & 0xFFF);
}
- }
+ } else
+ _script->setFinished(true);
for (curCmd = 0; curCmd < count; curCmd++)
freeCollision(curCmd + 0x8000);
@@ -937,8 +895,6 @@ void Game_v6::collisionsBlock(void) {
((_collisionAreas[i].id & 0xF000) == 0x9000))
_collisionAreas[i].id |= 0x4000;
}
-
- _vm->_global->_inter_execPtr = savedIP;
}
void Game_v6::setCollisions(byte arg_0) {
@@ -950,23 +906,22 @@ void Game_v6::setCollisions(byte arg_0) {
if (collArea->flags & 0x80)
continue;
- byte *totFileData = collArea->totFileData;
-
- if (!totFileData)
- totFileData = _totFileData;
+ Script *curScript = _script;
- byte *savedIP = _vm->_global->_inter_execPtr;
+ _script = collArea->script;
+ if (!_script)
+ _script = curScript;
- _vm->_global->_inter_execPtr = totFileData + collArea->funcSub;
+ _script->call(collArea->funcSub);
- int16 left = _vm->_parse->parseValExpr();
- int16 top = _vm->_parse->parseValExpr();
- int16 width = _vm->_parse->parseValExpr();
- int16 height = _vm->_parse->parseValExpr();
+ int16 left = _script->readValExpr();
+ int16 top = _script->readValExpr();
+ int16 width = _script->readValExpr();
+ int16 height = _script->readValExpr();
uint16 flags = 0;
if ((collArea->id & 0xF000) == 0xA000)
- flags = _vm->_parse->parseValExpr();
+ flags = _script->readValExpr();
if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) &&
(left != -1)) {
@@ -1001,16 +956,18 @@ void Game_v6::setCollisions(byte arg_0) {
if ((collArea->id & 0xF000) == 0xA000)
collArea->flags = flags;
- _vm->_global->_inter_execPtr = savedIP;
+ _script->pop();
+
+ _script = curScript;
}
}
void Game_v6::collSub(uint16 offset) {
- byte *savedIP;
int16 collStackSize;
- savedIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr = _totFileData + offset;
+ uint32 savedPos = _script->pos();
+
+ _script->seek(offset);
_shouldPushColls = 1;
collStackSize = _collStackSize;
@@ -1021,7 +978,8 @@ void Game_v6::collSub(uint16 offset) {
popCollisions();
_shouldPushColls = 0;
- _vm->_global->_inter_execPtr = savedIP;
+
+ _script->seek(savedPos);
if ((_vm->_util->getTimeKey() - _someTimeDly) > 500)
setCollisions(0);
diff --git a/engines/gob/global.cpp b/engines/gob/global.cpp
index 005d65815f..4165938966 100644
--- a/engines/gob/global.cpp
+++ b/engines/gob/global.cpp
@@ -37,35 +37,36 @@ Global::Global(GobEngine *vm) : _vm(vm) {
_presentVGA = UNDEF;
_presentHER = UNDEF;
- _videoMode = 0;
+ _videoMode = 0;
_fakeVideoMode = 0;
- _oldMode = 3;
+ _oldMode = 3;
_soundFlags = 0;
- _language = 0x8000;
+ _language = 0x8000;
_languageWanted = 0x8000;
+ _foundLanguage = false;
- _useMouse = UNDEF;
+ _useMouse = UNDEF;
_mousePresent = UNDEF;
- _mouseXShift = 3;
- _mouseYShift = 3;
+ _mouseXShift = 3;
+ _mouseYShift = 3;
- _mouseMinX = 0;
- _mouseMinY = 0;
+ _mouseMinX = 0;
+ _mouseMinY = 0;
_mouseMaxX = 320;
_mouseMaxY = 200;
_useJoystick = 1;
- _primaryWidth = 0;
+ _primaryWidth = 0;
_primaryHeight = 0;
_colorCount = 16;
for (int i = 0; i < 256; i++) {
- _redPalette[i] = 0;
+ _redPalette [i] = 0;
_greenPalette[i] = 0;
- _bluePalette[i] = 0;
+ _bluePalette [i] = 0;
}
_unusedPalette1[ 0] = (int16) 0x0000;
@@ -109,15 +110,12 @@ Global::Global(GobEngine *vm) : _vm(vm) {
_pPaletteDesc = 0;
- _setAllPalette = false;
+ _setAllPalette = false;
_dontSetPalette = false;
_debugFlag = 0;
_inVM = 0;
- _inter_resStr[0] = 0;
- _inter_resVal = 0;
-
_inter_execPtr = 0;
_inter_animDataSize = 10;
diff --git a/engines/gob/global.h b/engines/gob/global.h
index 9f12f4ded6..982ce113cb 100644
--- a/engines/gob/global.h
+++ b/engines/gob/global.h
@@ -33,37 +33,51 @@
namespace Gob {
-#define VIDMODE_CGA 0x05
-#define VIDMODE_EGA 0x0D
-#define VIDMODE_VGA 0x13
-#define VIDMODE_HER 7
-
-#define PROAUDIO_FLAG 0x10
-#define ADLIB_FLAG 0x08
-#define BLASTER_FLAG 0x04
-#define INTERSOUND_FLAG 0x02
-#define SPEAKER_FLAG 0x01
-#define MIDI_FLAG 0x4000
-
-#define NO 0
-#define YES 1
-#define UNDEF 2
-
-#define F1_KEY 0x3B00
-#define F2_KEY 0x3C00
-#define F3_KEY 0x3D00
-#define F4_KEY 0x3E00
-#define F5_KEY 0x3F00
-#define F6_KEY 0x4000
-#define ESCAPE 0x001B
-#define ENTER 0x000D
+#define VIDMODE_CGA 0x05
+#define VIDMODE_EGA 0x0D
+#define VIDMODE_VGA 0x13
+#define VIDMODE_HER 0x07
+
+#define MIDI_FLAG 0x4000
+#define PROAUDIO_FLAG 0x0010
+#define ADLIB_FLAG 0x0008
+#define BLASTER_FLAG 0x0004
+#define INTERSOUND_FLAG 0x0002
+#define SPEAKER_FLAG 0x0001
+
+#define NO 0
+#define YES 1
+#define UNDEF 2
+
+#define F1_KEY 0x3B00
+#define F2_KEY 0x3C00
+#define F3_KEY 0x3D00
+#define F4_KEY 0x3E00
+#define F5_KEY 0x3F00
+#define F6_KEY 0x4000
+#define ESCAPE 0x001B
+#define ENTER 0x000D
/* Video drivers */
-#define UNK_DRIVER 0
-#define VGA_DRIVER 1
-#define EGA_DRIVER 2
-#define CGA_DRIVER 3
-#define HER_DRIVER 4
+#define UNK_DRIVER 0
+#define VGA_DRIVER 1
+#define EGA_DRIVER 2
+#define CGA_DRIVER 3
+#define HER_DRIVER 4
+
+enum Language {
+ kLanguageFrench = 0,
+ kLanguageGerman = 1,
+ kLanguageBritish = 2,
+ kLanguageSpanish = 3,
+ kLanguageItalian = 4,
+ kLanguageAmerican = 5,
+ kLanguageDutch = 6,
+ kLanguageKorean = 7,
+ kLanguageHebrew = 8,
+ kLanguagePortuguese = 9,
+ kLanguageJapanese = 10
+};
class Global {
public:
@@ -82,6 +96,7 @@ public:
uint16 _language;
uint16 _languageWanted;
+ bool _foundLanguage;
char _useMouse;
int16 _mousePresent;
@@ -117,9 +132,6 @@ public:
int16 _debugFlag;
int16 _inVM;
- char _inter_resStr[200];
- int32 _inter_resVal;
-
byte *_inter_execPtr;
int16 _inter_animDataSize;
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index 1de6245297..e534464cce 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -47,7 +47,6 @@
#include "gob/map.h"
#include "gob/mult.h"
#include "gob/palanim.h"
-#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/videoplayer.h"
#include "gob/save/saveload.h"
@@ -102,12 +101,12 @@ void PauseDialog::handleKeyDown(Common::KeyState state) {
GobEngine::GobEngine(OSystem *syst) : Engine(syst) {
- _sound = 0; _mult = 0; _game = 0;
- _global = 0; _dataIO = 0; _goblin = 0;
- _vidPlayer = 0; _init = 0; _inter = 0;
- _map = 0; _palAnim = 0; _parse = 0;
- _scenery = 0; _draw = 0; _util = 0;
- _video = 0; _saveLoad = 0;
+ _sound = 0; _mult = 0; _game = 0;
+ _global = 0; _dataIO = 0; _goblin = 0;
+ _vidPlayer = 0; _init = 0; _inter = 0;
+ _map = 0; _palAnim = 0; _scenery = 0;
+ _draw = 0; _util = 0; _video = 0;
+ _saveLoad = 0;
_pauseStart = 0;
@@ -121,7 +120,7 @@ GobEngine::GobEngine(OSystem *syst) : Engine(syst) {
Common::addDebugChannel(kDebugDrawOp, "DrawOpcodes", "Script DrawOpcodes debug level");
Common::addDebugChannel(kDebugGobOp, "GoblinOpcodes", "Script GoblinOpcodes debug level");
Common::addDebugChannel(kDebugSound, "Sound", "Sound output debug level");
- Common::addDebugChannel(kDebugParser, "Parser", "Parser debug level");
+ Common::addDebugChannel(kDebugExpression, "Expression", "Expression parser debug level");
Common::addDebugChannel(kDebugGameFlow, "Gameflow", "Gameflow debug level");
Common::addDebugChannel(kDebugFileIO, "FileIO", "File Input/Output debug level");
Common::addDebugChannel(kDebugSaveLoad, "SaveLoad", "Saving/Loading debug level");
@@ -248,42 +247,42 @@ Common::Error GobEngine::run() {
switch (_language) {
case Common::FR_FRA:
case Common::RU_RUS:
- _global->_language = 0;
+ _global->_language = kLanguageFrench;
break;
case Common::DE_DEU:
- _global->_language = 1;
+ _global->_language = kLanguageGerman;
break;
case Common::EN_ANY:
case Common::EN_GRB:
- _global->_language = 2;
+ case Common::HU_HUN:
+ _global->_language = kLanguageBritish;
break;
case Common::ES_ESP:
- _global->_language = 3;
+ _global->_language = kLanguageSpanish;
break;
case Common::IT_ITA:
- _global->_language = 4;
+ _global->_language = kLanguageItalian;
break;
case Common::EN_USA:
- _global->_language = 5;
+ _global->_language = kLanguageAmerican;
break;
case Common::NL_NLD:
- _global->_language = 6;
+ _global->_language = kLanguageDutch;
break;
case Common::KO_KOR:
- _global->_language = 7;
+ _global->_language = kLanguageKorean;
break;
case Common::HB_ISR:
- _global->_language = 8;
+ _global->_language = kLanguageHebrew;
break;
case Common::PT_BRA:
- _global->_language = 9;
+ _global->_language = kLanguagePortuguese;
break;
case Common::JA_JPN:
- _global->_language = 10;
+ _global->_language = kLanguageJapanese;
break;
default:
- // Default to English
- _global->_language = 2;
+ _global->_language = kLanguageBritish;
break;
}
_global->_languageWanted = _global->_language;
@@ -332,7 +331,6 @@ bool GobEngine::initGameParts() {
_palAnim = new PalAnim(this);
_vidPlayer = new VideoPlayer(this);
_sound = new Sound(this);
- _parse = new Parse(this);
switch (_gameType) {
case kGameTypeGeisha:
@@ -465,6 +463,8 @@ bool GobEngine::initGameParts() {
break;
}
+ _inter->setupOpcodes();
+
if (is640()) {
_video->_surfWidth = _width = 640;
_video->_surfHeight = _video->_splitHeight1 = _height = 480;
@@ -495,7 +495,6 @@ void GobEngine::deinitGameParts() {
delete _inter; _inter = 0;
delete _map; _map = 0;
delete _palAnim; _palAnim = 0;
- delete _parse; _parse = 0;
delete _scenery; _scenery = 0;
delete _draw; _draw = 0;
delete _util; _util = 0;
diff --git a/engines/gob/gob.h b/engines/gob/gob.h
index 43e2270354..5d1cb3ecf2 100644
--- a/engines/gob/gob.h
+++ b/engines/gob/gob.h
@@ -52,7 +52,6 @@ class Inter;
class Map;
class Mult;
class PalAnim;
-class Parse;
class Scenery;
class Util;
class SaveLoad;
@@ -128,7 +127,7 @@ enum {
kDebugDrawOp = 1 << 1,
kDebugGobOp = 1 << 2,
kDebugSound = 1 << 3,
- kDebugParser = 1 << 4,
+ kDebugExpression = 1 << 4,
kDebugGameFlow = 1 << 5,
kDebugFileIO = 1 << 6,
kDebugSaveLoad = 1 << 7,
@@ -197,7 +196,6 @@ public:
Map *_map;
Mult *_mult;
PalAnim *_palAnim;
- Parse *_parse;
Scenery *_scenery;
Inter *_inter;
SaveLoad *_saveLoad;
diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp
index 8bf9536286..f9a22f52fb 100644
--- a/engines/gob/init.cpp
+++ b/engines/gob/init.cpp
@@ -32,6 +32,7 @@
#include "gob/dataio.h"
#include "gob/draw.h"
#include "gob/game.h"
+#include "gob/script.h"
#include "gob/palanim.h"
#include "gob/inter.h"
#include "gob/video.h"
@@ -80,9 +81,6 @@ void Init::doDemo() {
}
void Init::initGame() {
- int16 handle2;
- int16 handle;
- int16 imdHandle;
byte *infBuf;
char *infPtr;
char *infEnd;
@@ -91,11 +89,8 @@ void Init::initGame() {
initVideo();
if (!_vm->isDemo()) {
- handle2 = _vm->_dataIO->openData(_vm->_startStk.c_str());
- if (handle2 >= 0) {
- _vm->_dataIO->closeData(handle2);
+ if (_vm->_dataIO->existData(_vm->_startStk.c_str()))
_vm->_dataIO->openDataFile(_vm->_startStk.c_str());
- }
}
_vm->_util->initInput();
@@ -104,8 +99,6 @@ void Init::initGame() {
_vm->_global->_mouseXShift = 1;
_vm->_global->_mouseYShift = 1;
- _vm->_game->_totTextData = 0;
- _vm->_game->_totFileData = 0;
_palDesc = new Video::PalDesc;
_vm->validateVideoMode(_vm->_global->_videoMode);
@@ -127,19 +120,13 @@ void Init::initGame() {
return;
}
- handle = _vm->_dataIO->openData("intro.inf");
+ if (!_vm->_dataIO->existData("intro.inf")) {
- if (handle < 0) {
- for (int i = 0; i < 4; i++) {
- handle2 = _vm->_dataIO->openData(_fontNames[i]);
- if (handle2 >= 0) {
- _vm->_dataIO->closeData(handle2);
+ for (int i = 0; i < 4; i++)
+ if (_vm->_dataIO->existData(_fontNames[i]))
_vm->_draw->_fonts[i] = _vm->_util->loadFont(_fontNames[i]);
- }
- }
- } else {
- _vm->_dataIO->closeData(handle);
+ } else {
infBuf = _vm->_dataIO->getData("intro.inf");
infPtr = (char *) infBuf;
@@ -153,11 +140,8 @@ void Init::initGame() {
buffer[j] = 0;
strcat(buffer, ".let");
- handle2 = _vm->_dataIO->openData(buffer);
- if (handle2 >= 0) {
- _vm->_dataIO->closeData(handle2);
+ if (_vm->_dataIO->existData(buffer))
_vm->_draw->_fonts[i] = _vm->_util->loadFont(buffer);
- }
if ((infPtr + 1) >= infEnd)
break;
@@ -167,26 +151,16 @@ void Init::initGame() {
delete[] infBuf;
}
- strcpy(buffer, _vm->_startTot.c_str());
- handle = _vm->_dataIO->openData(buffer);
+ if (_vm->_dataIO->existData(_vm->_startTot.c_str())) {
+ _vm->_inter->allocateVars(Script::getVariablesCount(_vm->_startTot.c_str(), _vm));
- if (handle >= 0) {
- DataStream *stream = _vm->_dataIO->openAsStream(handle, true);
-
- stream->seek(0x2C);
- _vm->_inter->allocateVars(stream->readUint16LE());
-
- delete stream;
-
- strcpy(_vm->_game->_curTotFile, buffer);
+ strcpy(_vm->_game->_curTotFile, _vm->_startTot.c_str());
_vm->_sound->cdTest(1, "GOB");
_vm->_sound->cdLoadLIC("gob.lic");
// Search for a Coktel logo animation or image to display
- imdHandle = _vm->_dataIO->openData("coktel.imd");
- if (imdHandle >= 0) {
- _vm->_dataIO->closeData(imdHandle);
+ if (_vm->_dataIO->existData("coktel.imd")) {
_vm->_draw->initScreen();
_vm->_draw->_cursorIndex = -1;
@@ -198,19 +172,17 @@ void Init::initGame() {
}
_vm->_draw->closeScreen();
- } else if ((imdHandle = _vm->_dataIO->openData("coktel.clt")) >= 0) {
+ } else if (_vm->_dataIO->existData("coktel.clt")) {
_vm->_draw->initScreen();
-
- stream = _vm->_dataIO->openAsStream(imdHandle, true);
_vm->_util->clearPalette();
+
+ DataStream *stream = _vm->_dataIO->getDataStream("coktel.clt");
stream->read((byte *) _vm->_draw->_vgaPalette, 768);
delete stream;
- imdHandle = _vm->_dataIO->openData("coktel.ims");
- if (imdHandle >= 0) {
+ if (_vm->_dataIO->existData("coktel.ims")) {
byte *sprBuf;
- _vm->_dataIO->closeData(imdHandle);
sprBuf = _vm->_dataIO->getData("coktel.ims");
_vm->_video->drawPackedSprite(sprBuf, 320, 200, 0, 0, 0,
*_vm->_draw->_frontSurface);
diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp
index ce7f2ba319..8be07034c6 100644
--- a/engines/gob/inter.cpp
+++ b/engines/gob/inter.cpp
@@ -33,7 +33,8 @@
#include "gob/util.h"
#include "gob/draw.h"
#include "gob/game.h"
-#include "gob/parse.h"
+#include "gob/expression.h"
+#include "gob/script.h"
#include "gob/scenery.h"
#include "gob/sound/sound.h"
@@ -67,65 +68,93 @@ Inter::~Inter() {
delocateVars();
}
-void Inter::initControlVars(char full) {
- *_nestLevel = 0;
- *_breakFromLevel = -1;
+void Inter::setupOpcodes() {
+ setupOpcodesDraw();
+ setupOpcodesFunc();
+ setupOpcodesGob();
+}
- *_vm->_scenery->_pCaptureCounter = 0;
+void Inter::executeOpcodeDraw(byte i) {
+ debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", i, i, getDescOpcodeDraw(i));
- _break = false;
- _terminate = 0;
+ if (_opcodesDraw[i].proc && _opcodesDraw[i].proc->isValid())
+ (*_opcodesDraw[i].proc)();
+ else
+ warning("unimplemented opcodeDraw: %d [0x%X]", i, i);
+}
- if (full == 1) {
- for (int i = 0; i < 8; i++)
- _animPalDir[i] = 0;
- _soundEndTimeKey = 0;
+bool Inter::executeOpcodeFunc(byte i, byte j, OpFuncParams &params) {
+ debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)",
+ i, j, i, j, getDescOpcodeFunc(i, j));
+
+ if ((i > 4) || (j > 15)) {
+ warning("unimplemented opcodeFunc: %d.%d [0x%X.0x%X]", i, j, i, j);
+ return false;
}
+
+ i = i * 16 + j;
+ if (_opcodesFunc[i].proc && _opcodesFunc[i].proc->isValid())
+ return (*_opcodesFunc[i].proc)(params);
+ else
+ warning("unimplemented opcodeFunc: %d.%d [0x%X.0x%X]", i, j, i, j);
+
+ return false;
}
-int16 Inter::load16() {
- int16 tmp = (int16) READ_LE_UINT16(_vm->_global->_inter_execPtr);
- _vm->_global->_inter_execPtr += 2;
- return tmp;
+void Inter::executeOpcodeGob(int i, OpGobParams &params) {
+ debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)",
+ i, i, getDescOpcodeGob(i));
+
+ OpcodeEntry<OpcodeGob> *op = 0;
+
+ if (_opcodesGob.contains(i))
+ op = &_opcodesGob.getVal(i);
+
+ if (op && op->proc && op->proc->isValid()) {
+ (*op->proc)(params);
+ return;
+ }
+
+ _vm->_game->_script->skip(params.paramCount << 1);
+ warning("unimplemented opcodeGob: %d [0x%X]", i, i);
}
-char Inter::evalExpr(int16 *pRes) {
- byte token;
+const char *Inter::getDescOpcodeDraw(byte i) {
+ const char *desc = _opcodesDraw[i].desc;
- _vm->_parse->printExpr(99);
+ return ((desc) ? desc : "");
+}
- _vm->_parse->parseExpr(99, &token);
- if (!pRes)
- return token;
+const char *Inter::getDescOpcodeFunc(byte i, byte j) {
+ if ((i > 4) || (j > 15))
+ return "";
- switch (token) {
- case 20:
- *pRes = _vm->_global->_inter_resVal;
- break;
+ const char *desc = _opcodesFunc[i * 16 + j].desc;
- case 22:
- case 23:
- *pRes = 0;
- break;
+ return ((desc) ? desc : "");
+}
- case 24:
- *pRes = 1;
- break;
- }
+const char *Inter::getDescOpcodeGob(int i) {
+ if (_opcodesGob.contains(i))
+ return _opcodesGob.getVal(i).desc;
- return token;
+ return "";
}
-bool Inter::evalBoolResult() {
- byte token;
+void Inter::initControlVars(char full) {
+ *_nestLevel = 0;
+ *_breakFromLevel = -1;
+
+ *_vm->_scenery->_pCaptureCounter = 0;
- _vm->_parse->printExpr(99);
+ _break = false;
+ _terminate = 0;
- _vm->_parse->parseExpr(99, &token);
- if ((token == 24) || ((token == 20) && _vm->_global->_inter_resVal))
- return true;
- else
- return false;
+ if (full == 1) {
+ for (int i = 0; i < 8; i++)
+ _animPalDir[i] = 0;
+ _soundEndTimeKey = 0;
+ }
}
void Inter::renewTimeInVars() {
@@ -185,14 +214,14 @@ void Inter::storeKey(int16 key) {
void Inter::writeVar(uint32 offset, uint16 type, uint32 value) {
switch (type) {
- case 16:
- case 18:
+ case TYPE_VAR_INT8:
+ case TYPE_ARRAY_INT8:
WRITE_VARO_UINT8(offset, value);
break;
- case 17:
- case 24:
- case 27:
+ case TYPE_VAR_INT16:
+ case TYPE_VAR_INT32_AS_INT16:
+ case TYPE_ARRAY_INT16:
WRITE_VARO_UINT16(offset, value);
break;
@@ -209,20 +238,20 @@ void Inter::funcBlock(int16 retFlag) {
params.retFlag = retFlag;
- if (!_vm->_global->_inter_execPtr)
+ if (_vm->_game->_script->isFinished())
return;
_break = false;
- _vm->_global->_inter_execPtr++;
- params.cmdCount = *_vm->_global->_inter_execPtr++;
- _vm->_global->_inter_execPtr += 2;
+ _vm->_game->_script->skip(1);
+ params.cmdCount = _vm->_game->_script->readByte();
+ _vm->_game->_script->skip(2);
if (params.cmdCount == 0) {
- _vm->_global->_inter_execPtr = 0;
+ _vm->_game->_script->setFinished(true);
return;
}
- int startaddr = _vm->_global->_inter_execPtr - _vm->_game->_totFileData;
+ int startaddr = _vm->_game->_script->pos();
params.counter = 0;
do {
@@ -237,7 +266,7 @@ void Inter::funcBlock(int16 retFlag) {
(_vm->getPlatform() == Common::kPlatformMacintosh) ||
(_vm->getPlatform() == Common::kPlatformWindows))) {
- int addr = _vm->_global->_inter_execPtr-_vm->_game->_totFileData;
+ int addr = _vm->_game->_script->pos();
if ((startaddr == 0x18B4 && addr == 0x1A7F && // Zombie, EGA
!strncmp(_vm->_game->_curTotFile, "avt005.tot", 10)) ||
@@ -263,20 +292,19 @@ void Inter::funcBlock(int16 retFlag) {
} // End of workaround
- cmd = *_vm->_global->_inter_execPtr;
+ cmd = _vm->_game->_script->readByte();
if ((cmd >> 4) >= 12) {
cmd2 = 16 - (cmd >> 4);
cmd &= 0xF;
} else
cmd2 = 0;
- _vm->_global->_inter_execPtr++;
params.counter++;
if (cmd2 == 0)
cmd >>= 4;
- if (executeFuncOpcode(cmd2, cmd, params))
+ if (executeOpcodeFunc(cmd2, cmd, params))
return;
if (_vm->shouldQuit())
@@ -292,17 +320,17 @@ void Inter::funcBlock(int16 retFlag) {
}
} while (params.counter != params.cmdCount);
- _vm->_global->_inter_execPtr = 0;
+ _vm->_game->_script->setFinished(true);
return;
}
void Inter::callSub(int16 retFlag) {
byte block;
- while (!_vm->shouldQuit() && _vm->_global->_inter_execPtr &&
- (_vm->_global->_inter_execPtr != _vm->_game->_totFileData)) {
+ while (!_vm->shouldQuit() && !_vm->_game->_script->isFinished() &&
+ (_vm->_game->_script->pos() != 0)) {
- block = *_vm->_global->_inter_execPtr;
+ block = _vm->_game->_script->peekByte();
if (block == 1)
funcBlock(retFlag);
else if (block == 2)
@@ -311,7 +339,7 @@ void Inter::callSub(int16 retFlag) {
error("Unknown block type %d in Inter::callSub()", block);
}
- if (_vm->_global->_inter_execPtr == _vm->_game->_totFileData)
+ if (!_vm->_game->_script->isFinished() && (_vm->_game->_script->pos() == 0))
_terminate = 1;
}
diff --git a/engines/gob/inter.h b/engines/gob/inter.h
index 412c3f2673..d4ed2d3240 100644
--- a/engines/gob/inter.h
+++ b/engines/gob/inter.h
@@ -26,6 +26,9 @@
#ifndef GOB_INTER_H
#define GOB_INTER_H
+#include "common/func.h"
+#include "common/hashmap.h"
+
#include "gob/goblin.h"
#include "gob/variables.h"
@@ -34,11 +37,54 @@ namespace Gob {
// This is to help devices with small memory (PDA, smartphones, ...)
// to save abit of memory used by opcode names in the Scumm engine.
#ifndef REDUCE_MEMORY_USAGE
-# define _OPCODE(ver, x) { &ver::x, #x }
+ #define _OPCODEDRAW(ver, x) setProc(new Common::Functor0Mem<void, ver>(this, &ver::x), #x)
+ #define _OPCODEFUNC(ver, x) setProc(new Common::Functor1Mem<OpFuncParams &, bool, ver>(this, &ver::x), #x)
+ #define _OPCODEGOB(ver, x) setProc(new Common::Functor1Mem<OpGobParams &, void, ver>(this, &ver::x), #x)
#else
-# define _OPCODE(ver, x) { &ver::x, "" }
+ #define _OPCODEDRAW(ver, x) setProc(new Common::Functor0Mem<void, ver>(this, &ver::x), "")
+ #define _OPCODEFUNC(ver, x) setProc(new Common::Functor1Mem<OpFuncParams &, bool, ver>(this, &ver::x), "")
+ #define _OPCODEGOB(ver, x) setProc(new Common::Functor1Mem<OpGobParams &, void, ver>(this, &ver::x), "")
#endif
+#define CLEAROPCODEDRAW(i) _opcodesDraw[i].setProc(0, 0)
+#define CLEAROPCODEFUNC(i) _opcodesFunc[i].setProc(0, 0)
+#define CLEAROPCODEGOB(i) _opcodesGob.erase(i)
+
+typedef Common::Functor0<void> OpcodeDraw;
+typedef Common::Functor1<struct OpFuncParams &, bool> OpcodeFunc;
+typedef Common::Functor1<struct OpGobParams &, void> OpcodeGob;
+
+struct OpFuncParams {
+ byte cmdCount;
+ byte counter;
+ int16 retFlag;
+};
+struct OpGobParams {
+ int16 extraData;
+ int16 paramCount;
+ VariableReference retVarPtr;
+ Goblin::Gob_Object *objDesc;
+};
+
+template<typename T>
+struct OpcodeEntry : Common::NonCopyable {
+ T *proc;
+ const char *desc;
+
+ OpcodeEntry() : proc(0), desc(0) {}
+ ~OpcodeEntry() {
+ setProc(0, 0);
+ }
+
+ void setProc(T *p, const char *d) {
+ if (proc != p) {
+ delete proc;
+ proc = p;
+ }
+ desc = d;
+ }
+};
+
class Inter {
public:
uint8 _terminate;
@@ -51,10 +97,9 @@ public:
Variables *_variables;
+ void setupOpcodes();
+
void initControlVars(char full);
- int16 load16();
- char evalExpr(int16 *pRes);
- bool evalBoolResult();
void renewTimeInVars();
void storeMouse();
void storeKey(int16 key);
@@ -74,16 +119,9 @@ public:
virtual ~Inter();
protected:
- struct OpFuncParams {
- byte cmdCount;
- byte counter;
- int16 retFlag;
- };
- struct OpGobParams {
- int16 extraData;
- VariableReference retVarPtr;
- Goblin::Gob_Object *objDesc;
- };
+ OpcodeEntry<OpcodeDraw> _opcodesDraw[256];
+ OpcodeEntry<OpcodeFunc> _opcodesFunc[256];
+ Common::HashMap<int, OpcodeEntry<OpcodeGob> > _opcodesGob;
bool _break;
@@ -99,15 +137,19 @@ protected:
GobEngine *_vm;
- virtual void setupOpcodes() = 0;
- virtual void executeDrawOpcode(byte i) = 0;
- virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams &params) = 0;
- virtual void executeGoblinOpcode(int i, OpGobParams &params) = 0;
- virtual const char *getOpcodeDrawDesc(byte i) = 0;
- virtual const char *getOpcodeFuncDesc(byte i, byte j) = 0;
- virtual const char *getOpcodeGoblinDesc(int i) = 0;
+ void executeOpcodeDraw(byte i);
+ bool executeOpcodeFunc(byte i, byte j, OpFuncParams &params);
+ void executeOpcodeGob(int i, OpGobParams &params);
+
+ const char *getDescOpcodeDraw(byte i);
+ const char *getDescOpcodeFunc(byte i, byte j);
+ const char *getDescOpcodeGob(int i);
- virtual void checkSwitchTable(byte **ppExec) = 0;
+ virtual void setupOpcodesDraw() = 0;
+ virtual void setupOpcodesFunc() = 0;
+ virtual void setupOpcodesGob() = 0;
+
+ virtual void checkSwitchTable(uint32 &offset) = 0;
void o_drawNOP() {}
bool o_funcNOP(OpFuncParams &params) { return false; }
@@ -123,35 +165,11 @@ public:
virtual void animPalette();
protected:
- typedef void (Inter_v1::*OpcodeDrawProcV1)();
- typedef bool (Inter_v1::*OpcodeFuncProcV1)(OpFuncParams &);
- typedef void (Inter_v1::*OpcodeGoblinProcV1)(OpGobParams &);
- struct OpcodeDrawEntryV1 {
- OpcodeDrawProcV1 proc;
- const char *desc;
- };
- struct OpcodeFuncEntryV1 {
- OpcodeFuncProcV1 proc;
- const char *desc;
- };
- struct OpcodeGoblinEntryV1 {
- OpcodeGoblinProcV1 proc;
- const char *desc;
- };
- const OpcodeDrawEntryV1 *_opcodesDrawV1;
- const OpcodeFuncEntryV1 *_opcodesFuncV1;
- const OpcodeGoblinEntryV1 *_opcodesGoblinV1;
- static const int _goblinFuncLookUp[][2];
-
- virtual void setupOpcodes();
- virtual void executeDrawOpcode(byte i);
- virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams &params);
- virtual void executeGoblinOpcode(int i, OpGobParams &params);
- virtual const char *getOpcodeDrawDesc(byte i);
- virtual const char *getOpcodeFuncDesc(byte i, byte j);
- virtual const char *getOpcodeGoblinDesc(int i);
-
- virtual void checkSwitchTable(byte **ppExec);
+ virtual void setupOpcodesDraw();
+ virtual void setupOpcodesFunc();
+ virtual void setupOpcodesGob();
+
+ virtual void checkSwitchTable(uint32 &offset);
void o1_loadMult();
void o1_playMult();
@@ -318,35 +336,11 @@ public:
virtual void animPalette();
protected:
- typedef void (Inter_v2::*OpcodeDrawProcV2)();
- typedef bool (Inter_v2::*OpcodeFuncProcV2)(OpFuncParams &);
- typedef void (Inter_v2::*OpcodeGoblinProcV2)(OpGobParams &);
- struct OpcodeDrawEntryV2 {
- OpcodeDrawProcV2 proc;
- const char *desc;
- };
- struct OpcodeFuncEntryV2 {
- OpcodeFuncProcV2 proc;
- const char *desc;
- };
- struct OpcodeGoblinEntryV2 {
- OpcodeGoblinProcV2 proc;
- const char *desc;
- };
- const OpcodeDrawEntryV2 *_opcodesDrawV2;
- const OpcodeFuncEntryV2 *_opcodesFuncV2;
- const OpcodeGoblinEntryV2 *_opcodesGoblinV2;
- static const int _goblinFuncLookUp[][2];
-
- virtual void setupOpcodes();
- virtual void executeDrawOpcode(byte i);
- virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams &params);
- virtual void executeGoblinOpcode(int i, OpGobParams &params);
- virtual const char *getOpcodeDrawDesc(byte i);
- virtual const char *getOpcodeFuncDesc(byte i, byte j);
- virtual const char *getOpcodeGoblinDesc(int i);
-
- virtual void checkSwitchTable(byte **ppExec);
+ virtual void setupOpcodesDraw();
+ virtual void setupOpcodesFunc();
+ virtual void setupOpcodesGob();
+
+ virtual void checkSwitchTable(uint32 &offset);
void o2_playMult();
void o2_freeMultKeys();
@@ -410,33 +404,9 @@ public:
virtual ~Inter_Bargon() {}
protected:
- typedef void (Inter_Bargon::*OpcodeDrawProcBargon)();
- typedef bool (Inter_Bargon::*OpcodeFuncProcBargon)(OpFuncParams &);
- typedef void (Inter_Bargon::*OpcodeGoblinProcBargon)(OpGobParams &);
- struct OpcodeDrawEntryBargon {
- OpcodeDrawProcBargon proc;
- const char *desc;
- };
- struct OpcodeFuncEntryBargon {
- OpcodeFuncProcBargon proc;
- const char *desc;
- };
- struct OpcodeGoblinEntryBargon {
- OpcodeGoblinProcBargon proc;
- const char *desc;
- };
- const OpcodeDrawEntryBargon *_opcodesDrawBargon;
- const OpcodeFuncEntryBargon *_opcodesFuncBargon;
- const OpcodeGoblinEntryBargon *_opcodesGoblinBargon;
- static const int _goblinFuncLookUp[][2];
-
- virtual void setupOpcodes();
- virtual void executeDrawOpcode(byte i);
- virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams &params);
- virtual void executeGoblinOpcode(int i, OpGobParams &params);
- virtual const char *getOpcodeDrawDesc(byte i);
- virtual const char *getOpcodeFuncDesc(byte i, byte j);
- virtual const char *getOpcodeGoblinDesc(int i);
+ virtual void setupOpcodesDraw();
+ virtual void setupOpcodesFunc();
+ virtual void setupOpcodesGob();
void oBargon_intro0(OpGobParams &params);
void oBargon_intro1(OpGobParams &params);
@@ -456,33 +426,9 @@ public:
virtual ~Inter_Fascination() {}
protected:
- typedef void (Inter_Fascination::*OpcodeDrawProcFascination)();
- typedef bool (Inter_Fascination::*OpcodeFuncProcFascination)(OpFuncParams &);
- typedef void (Inter_Fascination::*OpcodeGoblinProcFascination)(OpGobParams &);
- struct OpcodeDrawEntryFascination {
- OpcodeDrawProcFascination proc;
- const char *desc;
- };
- struct OpcodeFuncEntryFascination {
- OpcodeFuncProcFascination proc;
- const char *desc;
- };
- struct OpcodeGoblinEntryFascination {
- OpcodeGoblinProcFascination proc;
- const char *desc;
- };
- const OpcodeDrawEntryFascination *_opcodesDrawFascination;
- const OpcodeFuncEntryFascination *_opcodesFuncFascination;
- const OpcodeGoblinEntryFascination *_opcodesGoblinFascination;
- static const int _goblinFuncLookUp[][2];
-
- virtual void setupOpcodes();
- virtual void executeDrawOpcode(byte i);
- virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams &params);
- virtual void executeGoblinOpcode(int i, OpGobParams &params);
- virtual const char *getOpcodeDrawDesc(byte i);
- virtual const char *getOpcodeFuncDesc(byte i, byte j);
- virtual const char *getOpcodeGoblinDesc(int i);
+ virtual void setupOpcodesDraw();
+ virtual void setupOpcodesFunc();
+ virtual void setupOpcodesGob();
void oFascin_playProtracker(OpGobParams &params);
@@ -517,39 +463,12 @@ public:
virtual ~Inter_v3() {}
protected:
- typedef void (Inter_v3::*OpcodeDrawProcV3)();
- typedef bool (Inter_v3::*OpcodeFuncProcV3)(OpFuncParams &);
- typedef void (Inter_v3::*OpcodeGoblinProcV3)(OpGobParams &);
- struct OpcodeDrawEntryV3 {
- OpcodeDrawProcV3 proc;
- const char *desc;
- };
- struct OpcodeFuncEntryV3 {
- OpcodeFuncProcV3 proc;
- const char *desc;
- };
- struct OpcodeGoblinEntryV3 {
- OpcodeGoblinProcV3 proc;
- const char *desc;
- };
- const OpcodeDrawEntryV3 *_opcodesDrawV3;
- const OpcodeFuncEntryV3 *_opcodesFuncV3;
- const OpcodeGoblinEntryV3 *_opcodesGoblinV3;
- static const int _goblinFuncLookUp[][2];
-
- virtual void setupOpcodes();
- virtual void executeDrawOpcode(byte i);
- virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams &params);
- virtual void executeGoblinOpcode(int i, OpGobParams &params);
- virtual const char *getOpcodeDrawDesc(byte i);
- virtual const char *getOpcodeFuncDesc(byte i, byte j);
- virtual const char *getOpcodeGoblinDesc(int i);
+ virtual void setupOpcodesDraw();
+ virtual void setupOpcodesFunc();
+ virtual void setupOpcodesGob();
bool o3_getTotTextItemPart(OpFuncParams &params);
bool o3_copySprite(OpFuncParams &params);
- bool o3_checkData(OpFuncParams &params);
- bool o3_readData(OpFuncParams &params);
- bool o3_writeData(OpFuncParams &params);
void o3_wobble(OpGobParams &params);
};
@@ -560,33 +479,9 @@ public:
virtual ~Inter_v4() {}
protected:
- typedef void (Inter_v4::*OpcodeDrawProcV4)();
- typedef bool (Inter_v4::*OpcodeFuncProcV4)(OpFuncParams &);
- typedef void (Inter_v4::*OpcodeGoblinProcV4)(OpGobParams &);
- struct OpcodeDrawEntryV4 {
- OpcodeDrawProcV4 proc;
- const char *desc;
- };
- struct OpcodeFuncEntryV4 {
- OpcodeFuncProcV4 proc;
- const char *desc;
- };
- struct OpcodeGoblinEntryV4 {
- OpcodeGoblinProcV4 proc;
- const char *desc;
- };
- const OpcodeDrawEntryV4 *_opcodesDrawV4;
- const OpcodeFuncEntryV4 *_opcodesFuncV4;
- const OpcodeGoblinEntryV4 *_opcodesGoblinV4;
- static const int _goblinFuncLookUp[][2];
-
- virtual void setupOpcodes();
- virtual void executeDrawOpcode(byte i);
- virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams &params);
- virtual void executeGoblinOpcode(int i, OpGobParams &params);
- virtual const char *getOpcodeDrawDesc(byte i);
- virtual const char *getOpcodeFuncDesc(byte i, byte j);
- virtual const char *getOpcodeGoblinDesc(int i);
+ virtual void setupOpcodesDraw();
+ virtual void setupOpcodesFunc();
+ virtual void setupOpcodesGob();
void o4_initScreen();
void o4_playVmdOrMusic();
@@ -598,36 +493,12 @@ public:
virtual ~Inter_v5() {}
protected:
- typedef void (Inter_v5::*OpcodeDrawProcV5)();
- typedef bool (Inter_v5::*OpcodeFuncProcV5)(OpFuncParams &);
- typedef void (Inter_v5::*OpcodeGoblinProcV5)(OpGobParams &);
- struct OpcodeDrawEntryV5 {
- OpcodeDrawProcV5 proc;
- const char *desc;
- };
- struct OpcodeFuncEntryV5 {
- OpcodeFuncProcV5 proc;
- const char *desc;
- };
- struct OpcodeGoblinEntryV5 {
- OpcodeGoblinProcV5 proc;
- const char *desc;
- };
- const OpcodeDrawEntryV5 *_opcodesDrawV5;
- const OpcodeFuncEntryV5 *_opcodesFuncV5;
- const OpcodeGoblinEntryV5 *_opcodesGoblinV5;
- static const int _goblinFuncLookUp[][2];
-
- virtual void setupOpcodes();
- virtual void executeDrawOpcode(byte i);
- virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams &params);
- virtual void executeGoblinOpcode(int i, OpGobParams &params);
- virtual const char *getOpcodeDrawDesc(byte i);
- virtual const char *getOpcodeFuncDesc(byte i, byte j);
- virtual const char *getOpcodeGoblinDesc(int i);
-
byte _gob_97_98_val;
+ virtual void setupOpcodesDraw();
+ virtual void setupOpcodesFunc();
+ virtual void setupOpcodesGob();
+
void o5_deleteFile();
void o5_initScreen();
@@ -657,35 +528,11 @@ public:
virtual ~Inter_v6() {}
protected:
- typedef void (Inter_v6::*OpcodeDrawProcV6)();
- typedef bool (Inter_v6::*OpcodeFuncProcV6)(OpFuncParams &);
- typedef void (Inter_v6::*OpcodeGoblinProcV6)(OpGobParams &);
- struct OpcodeDrawEntryV6 {
- OpcodeDrawProcV6 proc;
- const char *desc;
- };
- struct OpcodeFuncEntryV6 {
- OpcodeFuncProcV6 proc;
- const char *desc;
- };
- struct OpcodeGoblinEntryV6 {
- OpcodeGoblinProcV6 proc;
- const char *desc;
- };
- const OpcodeDrawEntryV6 *_opcodesDrawV6;
- const OpcodeFuncEntryV6 *_opcodesFuncV6;
- const OpcodeGoblinEntryV6 *_opcodesGoblinV6;
- static const int _goblinFuncLookUp[][2];
-
bool _gotFirstPalette;
- virtual void setupOpcodes();
- virtual void executeDrawOpcode(byte i);
- virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams &params);
- virtual void executeGoblinOpcode(int i, OpGobParams &params);
- virtual const char *getOpcodeDrawDesc(byte i);
- virtual const char *getOpcodeFuncDesc(byte i, byte j);
- virtual const char *getOpcodeGoblinDesc(int i);
+ virtual void setupOpcodesDraw();
+ virtual void setupOpcodesFunc();
+ virtual void setupOpcodesGob();
void o6_totSub();
void o6_playVmdOrMusic();
diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp
index 54ca32fa9e..12079600c0 100644
--- a/engines/gob/inter_bargon.cpp
+++ b/engines/gob/inter_bargon.cpp
@@ -39,680 +39,36 @@
namespace Gob {
-#define OPCODE(x) _OPCODE(Inter_Bargon, x)
-
-const int Inter_Bargon::_goblinFuncLookUp[][2] = {
- {1, 0},
- {2, 1},
- {3, 2},
- {4, 3},
- {5, 4},
- {6, 5},
- {7, 6},
- {8, 7},
- {9, 8},
- {10, 9},
- {11, 10},
- {13, 11},
- {14, 12},
- {15, 13},
- {16, 14},
- {21, 15},
- {22, 16},
- {23, 17},
- {24, 18},
- {25, 19},
- {26, 20},
- {27, 21},
- {28, 22},
- {29, 23},
- {30, 24},
- {32, 25},
- {33, 26},
- {34, 27},
- {35, 28},
- {36, 29},
- {37, 30},
- {40, 31},
- {41, 32},
- {42, 33},
- {43, 34},
- {44, 35},
- {50, 36},
- {52, 37},
- {53, 38},
- {100, 39},
- {152, 40},
- {200, 41},
- {201, 42},
- {202, 43},
- {203, 44},
- {204, 45},
- {250, 46},
- {251, 47},
- {252, 48},
- {500, 49},
- {502, 50},
- {503, 51},
- {600, 52},
- {601, 53},
- {602, 54},
- {603, 55},
- {604, 56},
- {605, 57},
- {1000, 58},
- {1001, 59},
- {1002, 60},
- {1003, 61},
- {1004, 62},
- {1005, 63},
- {1006, 64},
- {1008, 65},
- {1009, 66},
- {1010, 67},
- {1011, 68},
- {1015, 69},
- {2005, 70}
-};
+#define OPCODEVER Inter_Bargon
+#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x)
+#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x)
+#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x)
Inter_Bargon::Inter_Bargon(GobEngine *vm) : Inter_v2(vm) {
- setupOpcodes();
-}
-
-void Inter_Bargon::setupOpcodes() {
- static const OpcodeDrawEntryBargon opcodesDraw[256] = {
- /* 00 */
- OPCODE(o1_loadMult),
- OPCODE(o2_playMult),
- OPCODE(o1_freeMultKeys),
- {0, ""},
- /* 04 */
- {0, ""},
- {0, ""},
- {0, ""},
- OPCODE(o1_initCursor),
- /* 08 */
- OPCODE(o1_initCursorAnim),
- OPCODE(o1_clearCursorAnim),
- OPCODE(o2_setRenderFlags),
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- OPCODE(o1_loadAnim),
- OPCODE(o1_freeAnim),
- OPCODE(o1_updateAnim),
- OPCODE(o2_multSub),
- /* 14 */
- OPCODE(o2_initMult),
- OPCODE(o1_freeMult),
- OPCODE(o1_animate),
- OPCODE(o2_loadMultObject),
- /* 18 */
- OPCODE(o1_getAnimLayerInfo),
- OPCODE(o1_getObjAnimSize),
- OPCODE(o1_loadStatic),
- OPCODE(o1_freeStatic),
- /* 1C */
- OPCODE(o2_renderStatic),
- OPCODE(o2_loadCurLayer),
- {0, ""},
- {0, ""},
- /* 20 */
- OPCODE(o2_playCDTrack),
- OPCODE(o2_waitCDTrackEnd),
- OPCODE(o2_stopCD),
- OPCODE(o2_readLIC),
- /* 24 */
- OPCODE(o2_freeLIC),
- OPCODE(o2_getCDTrackPos),
- {0, ""},
- {0, ""},
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- OPCODE(o2_loadFontToSprite),
- OPCODE(o1_freeFontToSprite),
- {0, ""},
- {0, ""},
- /* 34 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 38 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 3C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 40 */
- OPCODE(o2_totSub),
- OPCODE(o2_switchTotSub),
- OPCODE(o2_pushVars),
- OPCODE(o2_popVars),
- /* 44 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 48 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 4C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 50 */
- OPCODE(o2_loadMapObjects),
- OPCODE(o2_freeGoblins),
- OPCODE(o2_moveGoblin),
- OPCODE(o2_writeGoblinPos),
- /* 54 */
- OPCODE(o2_stopGoblin),
- OPCODE(o2_setGoblinState),
- OPCODE(o2_placeGoblin),
- {0, ""},
- /* 58 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 5C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 60 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 64 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 68 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 6C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 70 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 74 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 78 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 7C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 80 */
- OPCODE(o2_initScreen),
- OPCODE(o2_scroll),
- OPCODE(o2_setScrollOffset),
- OPCODE(o2_playImd),
- /* 84 */
- OPCODE(o2_getImdInfo),
- OPCODE(o2_openItk),
- OPCODE(o2_closeItk),
- OPCODE(o2_setImdFrontSurf),
- /* 88 */
- OPCODE(o2_resetImdFrontSurf),
- {0, ""},
- {0, ""},
- {0, ""},
- /* 8C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 90 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 94 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 98 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 9C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* AC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* BC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* CC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* DC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* EC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* FC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""}
- };
-
- static const OpcodeFuncEntryBargon opcodesFunc[80] = {
- /* 00 */
- OPCODE(o1_callSub),
- OPCODE(o1_callSub),
- OPCODE(o1_printTotText),
- OPCODE(o1_loadCursor),
- /* 04 */
- {0, ""},
- OPCODE(o1_switch),
- OPCODE(o1_repeatUntil),
- OPCODE(o1_whileDo),
- /* 08 */
- OPCODE(o1_if),
- OPCODE(o2_assign),
- OPCODE(o1_loadSpriteToPos),
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- {0, ""},
- OPCODE(o2_printText),
- OPCODE(o1_loadTot),
- OPCODE(o1_palLoad),
- /* 14 */
- OPCODE(o1_keyFunc),
- OPCODE(o1_capturePush),
- OPCODE(o1_capturePop),
- OPCODE(o2_animPalInit),
- /* 18 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 1C */
- {0, ""},
- {0, ""},
- OPCODE(o1_drawOperations),
- OPCODE(o1_setcmdCount),
- /* 20 */
- OPCODE(o1_return),
- OPCODE(o1_renewTimeInVars),
- OPCODE(o1_speakerOn),
- OPCODE(o1_speakerOff),
- /* 24 */
- OPCODE(o1_putPixel),
- OPCODE(o2_goblinFunc),
- OPCODE(o1_createSprite),
- OPCODE(o1_freeSprite),
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- OPCODE(o1_returnTo),
- OPCODE(o1_loadSpriteContent),
- OPCODE(o1_copySprite),
- OPCODE(o1_fillRect),
- /* 34 */
- OPCODE(o1_drawLine),
- OPCODE(o1_strToLong),
- OPCODE(o1_invalidate),
- OPCODE(o1_setBackDelta),
- /* 38 */
- OPCODE(o1_playSound),
- OPCODE(o2_stopSound),
- OPCODE(o2_loadSound),
- OPCODE(o1_freeSoundSlot),
- /* 3C */
- OPCODE(o1_waitEndPlay),
- OPCODE(o1_playComposition),
- OPCODE(o2_getFreeMem),
- OPCODE(o2_checkData),
- /* 40 */
- {0, ""},
- OPCODE(o1_prepareStr),
- OPCODE(o1_insertStr),
- OPCODE(o1_cutStr),
- /* 44 */
- OPCODE(o1_strstr),
- OPCODE(o1_istrlen),
- OPCODE(o1_setMousePos),
- OPCODE(o1_setFrameRate),
- /* 48 */
- OPCODE(o1_animatePalette),
- OPCODE(o1_animateCursor),
- OPCODE(o1_blitCursor),
- OPCODE(o1_loadFont),
- /* 4C */
- OPCODE(o1_freeFont),
- OPCODE(o2_readData),
- OPCODE(o2_writeData),
- OPCODE(o1_manageDataFile),
- };
-
- static const OpcodeGoblinEntryBargon opcodesGoblin[71] = {
- /* 00 */
- OPCODE(oBargon_intro0),
- OPCODE(oBargon_intro1),
- OPCODE(oBargon_intro2),
- OPCODE(oBargon_intro3),
- /* 04 */
- OPCODE(oBargon_intro4),
- OPCODE(oBargon_intro5),
- OPCODE(oBargon_intro6),
- OPCODE(oBargon_intro7),
- /* 08 */
- OPCODE(oBargon_intro8),
- OPCODE(oBargon_intro9),
- OPCODE(o_gobNOP),
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 14 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 18 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 1C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 20 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 24 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 34 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 38 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 3C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 40 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 44 */
- {0, ""},
- {0, ""},
- {0, ""},
- };
-
- _opcodesDrawBargon = opcodesDraw;
- _opcodesFuncBargon = opcodesFunc;
- _opcodesGoblinBargon = opcodesGoblin;
-}
-
-void Inter_Bargon::executeDrawOpcode(byte i) {
- debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)",
- i, i, getOpcodeDrawDesc(i));
-
- OpcodeDrawProcBargon op = _opcodesDrawBargon[i].proc;
-
- if (op == 0)
- warning("unimplemented opcodeDraw: %d", i);
- else
- (this->*op) ();
-}
-
-bool Inter_Bargon::executeFuncOpcode(byte i, byte j, OpFuncParams &params) {
- debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)",
- i, j, i, j, getOpcodeFuncDesc(i, j));
-
- if ((i > 4) || (j > 15)) {
- warning("unimplemented opcodeFunc: %d.%d", i, j);
- return false;
- }
-
- OpcodeFuncProcBargon op = _opcodesFuncBargon[i*16 + j].proc;
-
- if (op == 0)
- warning("unimplemented opcodeFunc: %d.%d", i, j);
- else
- return (this->*op) (params);
-
- return false;
}
-void Inter_Bargon::executeGoblinOpcode(int i, OpGobParams &params) {
- debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)",
- i, i, getOpcodeGoblinDesc(i));
-
- OpcodeGoblinProcBargon op = 0;
-
- for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
- if (_goblinFuncLookUp[j][0] == i) {
- op = _opcodesGoblinBargon[_goblinFuncLookUp[j][1]].proc;
- break;
- }
-
- if (op == 0) {
- int16 val;
-
- _vm->_global->_inter_execPtr -= 2;
- val = load16();
- _vm->_global->_inter_execPtr += val << 1;
- warning("unimplemented opcodeGob: %d", i);
- } else
- (this->*op) (params);
+void Inter_Bargon::setupOpcodesDraw() {
+ Inter_v2::setupOpcodesDraw();
}
-const char *Inter_Bargon::getOpcodeDrawDesc(byte i) {
- return _opcodesDrawBargon[i].desc;
+void Inter_Bargon::setupOpcodesFunc() {
+ Inter_v2::setupOpcodesFunc();
}
-const char *Inter_Bargon::getOpcodeFuncDesc(byte i, byte j) {
- if ((i > 4) || (j > 15))
- return "";
+void Inter_Bargon::setupOpcodesGob() {
+ OPCODEGOB( 1, oBargon_intro0);
+ OPCODEGOB( 2, oBargon_intro1);
+ OPCODEGOB( 3, oBargon_intro2);
+ OPCODEGOB( 4, oBargon_intro3);
- return _opcodesFuncBargon[i*16 + j].desc;
-}
+ OPCODEGOB( 5, oBargon_intro4);
+ OPCODEGOB( 6, oBargon_intro5);
+ OPCODEGOB( 7, oBargon_intro6);
+ OPCODEGOB( 8, oBargon_intro7);
-const char *Inter_Bargon::getOpcodeGoblinDesc(int i) {
- for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
- if (_goblinFuncLookUp[j][0] == i)
- return _opcodesGoblinBargon[_goblinFuncLookUp[j][1]].desc;
- return "";
+ OPCODEGOB( 9, oBargon_intro8);
+ OPCODEGOB(10, oBargon_intro9);
+ OPCODEGOB(11, o_gobNOP);
}
void Inter_Bargon::oBargon_intro0(OpGobParams &params) {
diff --git a/engines/gob/inter_fascin.cpp b/engines/gob/inter_fascin.cpp
index bd0b0a94c6..3c4713f9eb 100644
--- a/engines/gob/inter_fascin.cpp
+++ b/engines/gob/inter_fascin.cpp
@@ -31,8 +31,8 @@
#include "gob/util.h"
#include "gob/dataio.h"
#include "gob/draw.h"
-#include "gob/parse.h"
#include "gob/game.h"
+#include "gob/script.h"
#include "gob/palanim.h"
#include "gob/video.h"
#include "gob/videoplayer.h"
@@ -40,494 +40,73 @@
namespace Gob {
-#define OPCODE(x) _OPCODE(Inter_Fascination, x)
-
-const int Inter_Fascination::_goblinFuncLookUp[][2] = {
- {1, 0},
- {2, 1},
- {3, 2},
- {4, 3},
- {5, 4},
- {6, 5},
- {7, 6},
- {8, 7},
- {9, 8},
- {10, 9},
- {11, 10},
- {12, 11},
- {1000, 12},
- {1001, 13},
- {1002, 14}
-};
+#define OPCODEVER Inter_Fascination
+#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x)
+#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x)
+#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x)
Inter_Fascination::Inter_Fascination(GobEngine *vm) : Inter_v2(vm) {
- setupOpcodes();
}
-void Inter_Fascination::setupOpcodes() {
- static const OpcodeDrawEntryFascination opcodesDraw[256] = {
- /* 00 */
- OPCODE(o1_loadMult),
- OPCODE(o2_playMult),
- OPCODE(o1_freeMultKeys),
- OPCODE(oFascin_cdUnknown3),
- /* 04 */
- OPCODE(oFascin_cdUnknown4),
- OPCODE(oFascin_cdUnknown5),
- OPCODE(oFascin_cdUnknown6),
- OPCODE(o1_initCursor),
- /* 08 */
- OPCODE(o1_initCursorAnim),
- OPCODE(o1_clearCursorAnim),
- OPCODE(oFascin_setRenderFlags),
- OPCODE(oFascin_cdUnknown11),
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- OPCODE(o1_loadAnim),
- OPCODE(o1_freeAnim),
- OPCODE(o1_updateAnim),
- OPCODE(o2_multSub),
- /* 14 */
- OPCODE(o2_initMult),
- OPCODE(o1_freeMult),
- OPCODE(o1_animate),
- OPCODE(o2_loadMultObject),
- /* 18 */
- OPCODE(o1_getAnimLayerInfo),
- OPCODE(o1_getObjAnimSize),
- OPCODE(o1_loadStatic),
- OPCODE(o1_freeStatic),
- /* 1C */
- OPCODE(o2_renderStatic),
- OPCODE(o2_loadCurLayer),
- {0, ""},
- {0, ""},
- /* 20 */
- OPCODE(o2_playCDTrack),
- OPCODE(o2_waitCDTrackEnd),
- OPCODE(o2_stopCD),
- OPCODE(o2_readLIC),
- /* 24 */
- OPCODE(o2_freeLIC),
- OPCODE(o2_getCDTrackPos),
- {0, ""},
- {0, ""},
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- OPCODE(o2_loadFontToSprite),
- OPCODE(o1_freeFontToSprite),
- {0, ""},
- {0, ""},
- /* 34 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 38 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 3C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 40 */
- OPCODE(o2_totSub),
- OPCODE(o2_switchTotSub),
- OPCODE(o2_pushVars),
- OPCODE(o2_popVars),
- /* 44 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 48 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 4C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 50 */
- {0, ""},//OPCODE(o2_loadMapObjects),
- {0, ""},//OPCODE(o2_freeGoblins),
- {0, ""},//OPCODE(o2_moveGoblin),
- {0, ""},//OPCODE(o2_writeGoblinPos),
- /* 54 */
- {0, ""},//OPCODE(o2_stopGoblin),
- {0, ""},//OPCODE(o2_setGoblinState),
- {0, ""},//OPCODE(o2_placeGoblin),
- {0, ""},
- /* 58 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 5C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 60 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 64 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 68 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 6C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 70 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 74 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 78 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 7C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 80 */
- {0, ""},//OPCODE(o2_initScreen),
- {0, ""},//OPCODE(o2_scroll),
- {0, ""},//OPCODE(o2_setScrollOffset),
- {0, ""},//OPCODE(o2_playImd),
- /* 84 */
- {0, ""},//OPCODE(o2_getImdInfo),
- {0, ""},//OPCODE(o2_openItk),
- {0, ""},//OPCODE(o2_closeItk),
- {0, ""},//OPCODE(o2_setImdFrontSurf),
- /* 88 */
- {0, ""},//OPCODE(o2_resetImdFrontSurf),
- {0, ""},
- {0, ""},
- {0, ""},
- /* 8C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 90 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 94 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 98 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 9C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* AC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* BC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* CC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* DC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* EC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* FC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""}
- };
-
- static const OpcodeFuncEntryFascination opcodesFunc[80] = {
- /* 00 */
- OPCODE(o1_callSub),
- OPCODE(o1_callSub),
- OPCODE(o1_printTotText),
- OPCODE(o1_loadCursor),
- /* 04 */
- {0, ""},
- OPCODE(o1_switch),
- OPCODE(o1_repeatUntil),
- OPCODE(o1_whileDo),
- /* 08 */
- OPCODE(o1_if),
- OPCODE(o1_assign),
- OPCODE(o1_loadSpriteToPos),
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- {0, ""},
- OPCODE(o2_printText),
- OPCODE(o1_loadTot),
- OPCODE(o1_palLoad),
- /* 14 */
- OPCODE(o1_keyFunc),
- OPCODE(o1_capturePush),
- OPCODE(o1_capturePop),
- OPCODE(o1_animPalInit),
- /* 18 */
- OPCODE(o2_addCollision),
- OPCODE(o2_freeCollision),
- {0, ""},
- {0, ""},
- /* 1C */
- {0, ""},
- {0, ""},
- OPCODE(o1_drawOperations),
- OPCODE(o1_setcmdCount),
- /* 20 */
- OPCODE(o1_return),
- OPCODE(o1_renewTimeInVars),
- OPCODE(o1_speakerOn),
- OPCODE(o1_speakerOff),
- /* 24 */
- OPCODE(o1_putPixel),
- OPCODE(o2_goblinFunc),
- OPCODE(o1_createSprite),
- OPCODE(o1_freeSprite),
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- OPCODE(o1_returnTo),
- OPCODE(o1_loadSpriteContent),
- OPCODE(o1_copySprite),
- OPCODE(o1_fillRect),
- /* 34 */
- OPCODE(o1_drawLine),
- OPCODE(o1_strToLong),
- OPCODE(o1_invalidate),
- OPCODE(o1_setBackDelta),
- /* 38 */
- OPCODE(o1_playSound),
- OPCODE(o2_stopSound),
- OPCODE(o2_loadSound),
- OPCODE(o1_freeSoundSlot),
- /* 3C */
- OPCODE(o1_waitEndPlay),
- OPCODE(o1_playComposition),
- OPCODE(o2_getFreeMem),
- OPCODE(o2_checkData),
- /* 40 */
- {0, ""},
- OPCODE(o1_prepareStr),
- OPCODE(o1_insertStr),
- OPCODE(o1_cutStr),
- /* 44 */
- OPCODE(o1_strstr),
- OPCODE(o1_istrlen),
- OPCODE(o1_setMousePos),
- OPCODE(o1_setFrameRate),
- /* 48 */
- OPCODE(o1_animatePalette),
- OPCODE(o1_animateCursor),
- OPCODE(o1_blitCursor),
- OPCODE(o1_loadFont),
- /* 4C */
- OPCODE(o1_freeFont),
- OPCODE(o2_readData),
- OPCODE(o2_writeData),
- OPCODE(o1_manageDataFile),
- };
-
- static const OpcodeGoblinEntryFascination opcodesGoblin[15] = {
- /* 00 */
- OPCODE(oFascin_geUnknown0),
- OPCODE(oFascin_geUnknown1),
- OPCODE(oFascin_geUnknown2),
- OPCODE(oFascin_geUnknown3),
- /* 04 */
- OPCODE(oFascin_geUnknown4),
- OPCODE(oFascin_geUnknown5),
- OPCODE(oFascin_geUnknown6),
- OPCODE(oFascin_geUnknown7),
- /* 08 */
- OPCODE(oFascin_geUnknown8),
- OPCODE(oFascin_geUnknown9),
- OPCODE(oFascin_geUnknown10),
- OPCODE(oFascin_geUnknown11),
- /* 0C */
- OPCODE(oFascin_geUnknown1000),
- OPCODE(oFascin_geUnknown1001), //protrackerPlay doesn't play correctly "mod.extasy"
- OPCODE(oFascin_geUnknown1002), //to be replaced by o2_stopProtracker when protrackerPlay is fixed
- };
-
- _opcodesDrawFascination = opcodesDraw;
- _opcodesFuncFascination = opcodesFunc;
- _opcodesGoblinFascination = opcodesGoblin;
+void Inter_Fascination::setupOpcodesDraw() {
+ Inter_v2::setupOpcodesDraw();
+
+ OPCODEDRAW(0x03, oFascin_cdUnknown3);
+
+ OPCODEDRAW(0x04, oFascin_cdUnknown4);
+ OPCODEDRAW(0x05, oFascin_cdUnknown5);
+ OPCODEDRAW(0x06, oFascin_cdUnknown6);
+
+ OPCODEDRAW(0x0A, oFascin_setRenderFlags);
+ OPCODEDRAW(0x0B, oFascin_cdUnknown11);
+
+ CLEAROPCODEDRAW(0x50);
+ CLEAROPCODEDRAW(0x51);
+ CLEAROPCODEDRAW(0x52);
+ CLEAROPCODEDRAW(0x53);
+
+ CLEAROPCODEDRAW(0x54);
+ CLEAROPCODEDRAW(0x55);
+ CLEAROPCODEDRAW(0x56);
+
+ CLEAROPCODEDRAW(0x80);
+ CLEAROPCODEDRAW(0x81);
+ CLEAROPCODEDRAW(0x82);
+ CLEAROPCODEDRAW(0x83);
+
+ CLEAROPCODEDRAW(0x84);
+ CLEAROPCODEDRAW(0x85);
+ CLEAROPCODEDRAW(0x86);
+ CLEAROPCODEDRAW(0x87);
+
+ CLEAROPCODEDRAW(0x88);
}
-void Inter_Fascination::executeDrawOpcode(byte i) {
- debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)",
- i, i, getOpcodeDrawDesc(i));
+void Inter_Fascination::setupOpcodesFunc() {
+ Inter_v2::setupOpcodesFunc();
- OpcodeDrawProcFascination op = _opcodesDrawFascination[i].proc;
+ OPCODEFUNC(0x09, o1_assign);
+}
+
+void Inter_Fascination::setupOpcodesGob() {
+ OPCODEGOB( 1, oFascin_geUnknown0);
+ OPCODEGOB( 2, oFascin_geUnknown1);
+ OPCODEGOB( 3, oFascin_geUnknown2);
+ OPCODEGOB( 4, oFascin_geUnknown3);
+
+ OPCODEGOB( 5, oFascin_geUnknown4);
+ OPCODEGOB( 6, oFascin_geUnknown5);
+ OPCODEGOB( 7, oFascin_geUnknown6);
+ OPCODEGOB( 8, oFascin_geUnknown7);
+
+ OPCODEGOB( 9, oFascin_geUnknown8);
+ OPCODEGOB( 10, oFascin_geUnknown9);
+ OPCODEGOB( 11, oFascin_geUnknown10);
+ OPCODEGOB( 12, oFascin_geUnknown11);
- if (op == 0)
- warning("Not yet implemented Fascination opcodeDraw: %d", i);
- else
- (this->*op) ();
+ OPCODEGOB(1000, oFascin_geUnknown1000);
+ OPCODEGOB(1001, oFascin_geUnknown1001); //protrackerPlay doesn't play correctly "mod.extasy"
+ OPCODEGOB(1002, oFascin_geUnknown1002); //to be replaced by o2_stopProtracker when protrackerPlay is fixed
}
void Inter_Fascination::oFascin_geUnknown0(OpGobParams &params) {
@@ -552,70 +131,58 @@ void Inter_Fascination::oFascin_geUnknown1(OpGobParams &params) {
}
void Inter_Fascination::oFascin_geUnknown2(OpGobParams &params) {
- warning("Fascination Unknown GE Function 2");
- warning("funcLoadInstruments with parameter : 'extasy.tbr'. (Guess)");
- warning("funcLoadMusic with parameter : 'extasy.mdy'. (Guess)");
+ _vm->_sound->adlibLoadTBR("extasy.tbr");
+ _vm->_sound->adlibLoadMDY("extasy.mdy");
}
void Inter_Fascination::oFascin_geUnknown3(OpGobParams &params) {
- warning("Fascination Unknown GE Function 3");
- warning("Verify if 'Guess music' is loaded. If yes, call funcPlayMusic. (Guess)");
+ _vm->_sound->adlibPlay();
}
void Inter_Fascination::oFascin_geUnknown4(OpGobParams &params) {
- warning("Fascination Unknown GE Function 4");
- warning("Verify if 'Guess music' is loaded. If yes, call funcStopMusic. (Guess)");
+ _vm->_sound->adlibStop();
}
void Inter_Fascination::oFascin_geUnknown5(OpGobParams &params) {
- warning("Fascination Unknown GE Function 5");
- warning("Verify if 'instruments' are loaded, If so, call mem_free");
- warning("Verify if 'Guess music' is loaded. If yes, call _cleanupMdy");
- warning("Then set _ptrTbr and _ptrMdy to 0");
+ _vm->_sound->adlibUnload();
}
void Inter_Fascination::oFascin_geUnknown6(OpGobParams &params) {
- warning("Fascination Unknown GE Function 6");
- warning("funcLoadInstruments with parameter : 'music1.tbr'. (Guess)");
- warning("funcLoadMusic with parameter : 'music1.mdy'. (Guess)");
+ _vm->_sound->adlibLoadTBR("music1.tbr");
+ _vm->_sound->adlibLoadMDY("music1.mdy");
}
void Inter_Fascination::oFascin_geUnknown7(OpGobParams &params) {
- warning("Fascination Unknown GE Function 7");
- warning("funcLoadInstruments with parameter : 'music2.tbr'. (Guess)");
- warning("funcLoadMusic with parameter : 'music2.mdy'. (Guess)");
+ _vm->_sound->adlibLoadTBR("music2.tbr");
+ _vm->_sound->adlibLoadMDY("music2.mdy");
}
void Inter_Fascination::oFascin_geUnknown8(OpGobParams &params) {
- warning("Fascination Unknown GE Function 8");
- warning("funcLoadInstruments with parameter : 'music3.tbr'. (Guess)");
- warning("funcLoadMusic with parameter : 'music3.mdy'. (Guess)");
+ _vm->_sound->adlibLoadTBR("music3.tbr");
+ _vm->_sound->adlibLoadMDY("music3.mdy");
}
void Inter_Fascination::oFascin_geUnknown9(OpGobParams &params) {
- warning("Fascination Unknown GE Function 9");
- warning("funcLoadInstruments with parameter : 'batt1.tbr'. (Guess)");
- warning("funcLoadMusic with parameter : 'batt1.mdy'. (Guess)");
+ _vm->_sound->adlibLoadTBR("batt1.tbr");
+ _vm->_sound->adlibLoadMDY("batt1.mdy");
}
void Inter_Fascination::oFascin_geUnknown10(OpGobParams &params) {
- warning("Fascination Unknown GE Function 10");
- warning("funcLoadInstruments with parameter : 'batt2.tbr'. (Guess)");
- warning("funcLoadMusic with parameter : 'batt2.mdy'. (Guess)");
+ _vm->_sound->adlibLoadTBR("batt2.tbr");
+ _vm->_sound->adlibLoadMDY("batt2.mdy");
}
void Inter_Fascination::oFascin_geUnknown11(OpGobParams &params) {
- warning("Fascination Unknown GE Function 11");
- warning("funcLoadInstruments with parameter : 'batt3.tbr'. (Guess)");
- warning("funcLoadMusic with parameter : 'batt3.mdy'. (Guess)");
+ _vm->_sound->adlibLoadTBR("batt3.tbr");
+ _vm->_sound->adlibLoadMDY("batt3.mdy");
}
void Inter_Fascination::oFascin_geUnknown1000(OpGobParams &params) {
- warning("Fascination Unknown GE Function 1000 - Load music ?");
+ warning("Fascination Unknown GE Function 1000 - Load MOD music");
}
void Inter_Fascination::oFascin_geUnknown1001(OpGobParams &params) {
- warning("Fascination oFascin_playProtracker - MOD not compatible, ToBeFixed");
+ warning("Fascination oFascin_playProtracker - MOD not compatible (sample > 32768), To Be Fixed");
}
void Inter_Fascination::oFascin_geUnknown1002(OpGobParams &params) {
@@ -638,15 +205,15 @@ void Inter_Fascination::oFascin_cdUnknown3() {
warning("Fascination oFascin_cdUnknown3 - Variables initialisations");
- resVar = (uint16) load16();
- resVar2 = (uint16) load16();
- retVal1 = _vm->_parse->parseVarIndex();
- retVal2 = _vm->_parse->parseVarIndex();
- retVal3 = _vm->_parse->parseVarIndex();
- retVal4 = _vm->_parse->parseVarIndex();
- retVal5 = _vm->_parse->parseVarIndex();
- retVal6 = _vm->_parse->parseVarIndex();
- retVal7 = _vm->_parse->parseVarIndex();
+ resVar = _vm->_game->_script->readUint16();
+ resVar2 = _vm->_game->_script->readUint16();
+ retVal1 = _vm->_game->_script->readVarIndex();
+ retVal2 = _vm->_game->_script->readVarIndex();
+ retVal3 = _vm->_game->_script->readVarIndex();
+ retVal4 = _vm->_game->_script->readVarIndex();
+ retVal5 = _vm->_game->_script->readVarIndex();
+ retVal6 = _vm->_game->_script->readVarIndex();
+ retVal7 = _vm->_game->_script->readVarIndex();
warning ("Width? :%d Height? :%d",resVar, resVar2);
warning ("Fetched variables 1:%d 2:%d 3:%d 4:%d 5:%d 6:%d 7:%d", retVal1, retVal2, retVal3, retVal4, retVal5, retVal6, retVal7);
}
@@ -654,98 +221,37 @@ void Inter_Fascination::oFascin_cdUnknown3() {
void Inter_Fascination::oFascin_cdUnknown4() {
int16 expr;
warning("Fascination oFascin_cdUnknown4");
- evalExpr(&expr);
- warning ("evalExpr: %d, the rest is not yet implemented",expr);
+ _vm->_game->_script->evalExpr(&expr);
+ warning ("_vm->_game->_script->evalExpr: %d, the rest is not yet implemented",expr);
}
void Inter_Fascination::oFascin_cdUnknown5() {
int16 retVal1,expr;
warning("Fascination oFascin_cdUnknown5");
- evalExpr(&expr);
- retVal1 = _vm->_parse->parseVarIndex();
- warning ("evalExpr: %d Variable index %d, the rest is not yet implemented",expr, retVal1);
+ _vm->_game->_script->evalExpr(&expr);
+ retVal1 = _vm->_game->_script->readVarIndex();
+ warning ("_vm->_game->_script->evalExpr: %d Variable index %d, the rest is not yet implemented",expr, retVal1);
}
void Inter_Fascination::oFascin_cdUnknown6() {
int16 retVal1,expr;
warning("Fascination oFascin_cdUnknown6");
- evalExpr(&expr);
- retVal1 = _vm->_parse->parseVarIndex();
- warning ("evalExpr: %d Variable index %d, the rest is not yet implemented",expr, retVal1);
+ _vm->_game->_script->evalExpr(&expr);
+ retVal1 = _vm->_game->_script->readVarIndex();
+ warning ("_vm->_game->_script->evalExpr: %d Variable index %d, the rest is not yet implemented",expr, retVal1);
}
void Inter_Fascination::oFascin_setRenderFlags() {
int16 expr;
// warning("Fascination oFascin_cdUnknown10 (set render flags)");
- evalExpr(&expr);
+ _vm->_game->_script->evalExpr(&expr);
warning("_draw_renderFlags <- %d",expr);
_vm->_draw->_renderFlags = expr;
}
void Inter_Fascination::oFascin_cdUnknown11() {
// warning("Fascination oFascin_cdUnknown11 (set variable)");
- evalExpr(0);
-}
-
-bool Inter_Fascination::executeFuncOpcode(byte i, byte j, OpFuncParams &params) {
- debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)",
- i, j, i, j, getOpcodeFuncDesc(i, j));
-
- if ((i > 4) || (j > 16)) {
- warning("Invalid opcodeFunc: %d.%d", i, j);
- return false;
- }
-
- OpcodeFuncProcFascination op = _opcodesFuncFascination[i*16 + j].proc;
-
- if (op == 0)
- warning("unimplemented opcodeFunc: %d.%d", i, j);
- else
- return (this->*op) (params);
-
- return false;
-}
-
-void Inter_Fascination::executeGoblinOpcode(int i, OpGobParams &params) {
- debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)",
- i, i, getOpcodeGoblinDesc(i));
-
- OpcodeGoblinProcFascination op = 0;
-
- for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
- if (_goblinFuncLookUp[j][0] == i) {
- op = _opcodesGoblinFascination[_goblinFuncLookUp[j][1]].proc;
- break;
- }
-
- if (op == 0) {
- int16 val;
-
- _vm->_global->_inter_execPtr -= 2;
- val = load16();
- _vm->_global->_inter_execPtr += val << 1;
- warning("unimplemented opcodeGob: %d", i);
- } else
- (this->*op) (params);
-}
-
-const char *Inter_Fascination::getOpcodeDrawDesc(byte i) {
- return _opcodesDrawFascination[i].desc;
-}
-
-const char *Inter_Fascination::getOpcodeFuncDesc(byte i, byte j) {
- if ((i > 4) || (j > 15))
- return "";
-
- return _opcodesFuncFascination[i*16 + j].desc;
-}
-
-const char *Inter_Fascination::getOpcodeGoblinDesc(int i) {
- for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
- if (_goblinFuncLookUp[j][0] == i)
- return _opcodesGoblinFascination[_goblinFuncLookUp[j][1]].desc;
- warning("Error in getOpcodeGoblinDesc %d",i);
- return "";
+ _vm->_game->_script->evalExpr(0);
}
void Inter_Fascination::oFascin_playProtracker(OpGobParams &params) {
diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp
index ace5a7a3be..d5d5fcad9a 100644
--- a/engines/gob/inter_v1.cpp
+++ b/engines/gob/inter_v1.cpp
@@ -34,692 +34,214 @@
#include "gob/dataio.h"
#include "gob/draw.h"
#include "gob/game.h"
+#include "gob/expression.h"
+#include "gob/script.h"
+#include "gob/resources.h"
#include "gob/goblin.h"
#include "gob/inter.h"
#include "gob/map.h"
#include "gob/mult.h"
#include "gob/palanim.h"
-#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/video.h"
#include "gob/sound/sound.h"
namespace Gob {
-#define OPCODE(x) _OPCODE(Inter_v1, x)
-
-const int Inter_v1::_goblinFuncLookUp[][2] = {
- {1, 0},
- {2, 1},
- {3, 2},
- {4, 3},
- {5, 4},
- {6, 5},
- {7, 6},
- {8, 7},
- {9, 8},
- {10, 9},
- {12, 10},
- {13, 11},
- {14, 12},
- {15, 13},
- {16, 14},
- {21, 15},
- {22, 16},
- {23, 17},
- {24, 18},
- {25, 19},
- {26, 20},
- {27, 21},
- {28, 22},
- {29, 23},
- {30, 24},
- {32, 25},
- {33, 26},
- {34, 27},
- {35, 28},
- {36, 29},
- {37, 30},
- {40, 31},
- {41, 32},
- {42, 33},
- {43, 34},
- {44, 35},
- {50, 36},
- {52, 37},
- {53, 38},
- {150, 39},
- {152, 40},
- {200, 41},
- {201, 42},
- {202, 43},
- {203, 44},
- {204, 45},
- {250, 46},
- {251, 47},
- {252, 48},
- {500, 49},
- {502, 50},
- {503, 51},
- {600, 52},
- {601, 53},
- {602, 54},
- {603, 55},
- {604, 56},
- {605, 57},
- {1000, 58},
- {1001, 59},
- {1002, 60},
- {1003, 61},
- {1004, 62},
- {1005, 63},
- {1006, 64},
- {1008, 65},
- {1009, 66},
- {1010, 67},
- {1011, 68},
- {1015, 69},
- {2005, 70}
-};
+#define OPCODEVER Inter_v1
+#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x)
+#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x)
+#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x)
Inter_v1::Inter_v1(GobEngine *vm) : Inter(vm) {
- setupOpcodes();
-}
-
-void Inter_v1::setupOpcodes() {
- static const OpcodeDrawEntryV1 opcodesDraw[256] = {
- /* 00 */
- OPCODE(o1_loadMult),
- OPCODE(o1_playMult),
- OPCODE(o1_freeMultKeys),
- {0, ""},
- /* 04 */
- {0, ""},
- {0, ""},
- {0, ""},
- OPCODE(o1_initCursor),
- /* 08 */
- OPCODE(o1_initCursorAnim),
- OPCODE(o1_clearCursorAnim),
- OPCODE(o1_setRenderFlags),
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- OPCODE(o1_loadAnim),
- OPCODE(o1_freeAnim),
- OPCODE(o1_updateAnim),
- {0, ""},
- /* 14 */
- OPCODE(o1_initMult),
- OPCODE(o1_freeMult),
- OPCODE(o1_animate),
- OPCODE(o1_loadMultObject),
- /* 18 */
- OPCODE(o1_getAnimLayerInfo),
- OPCODE(o1_getObjAnimSize),
- OPCODE(o1_loadStatic),
- OPCODE(o1_freeStatic),
- /* 1C */
- OPCODE(o1_renderStatic),
- OPCODE(o1_loadCurLayer),
- {0, ""},
- {0, ""},
- /* 20 */
- OPCODE(o1_playCDTrack),
- OPCODE(o1_getCDTrackPos),
- OPCODE(o1_stopCD),
- {0, ""},
- /* 24 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- OPCODE(o1_loadFontToSprite),
- OPCODE(o1_freeFontToSprite),
- {0, ""},
- {0, ""},
- /* 34 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 38 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 3C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 40 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 44 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 48 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 4C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 50 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 54 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 58 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 5C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 60 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 64 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 68 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 6C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 70 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 74 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 78 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 7C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 80 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 84 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 88 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 8C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 90 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 94 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 98 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 9C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* AC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* BC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* CC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* DC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* EC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* FC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""}
- };
-
- static const OpcodeFuncEntryV1 opcodesFunc[80] = {
- /* 00 */
- OPCODE(o1_callSub),
- OPCODE(o1_callSub),
- OPCODE(o1_printTotText),
- OPCODE(o1_loadCursor),
- /* 04 */
- {0, ""},
- OPCODE(o1_switch),
- OPCODE(o1_repeatUntil),
- OPCODE(o1_whileDo),
- /* 08 */
- OPCODE(o1_if),
- OPCODE(o1_assign),
- OPCODE(o1_loadSpriteToPos),
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- {0, ""},
- OPCODE(o1_printText),
- OPCODE(o1_loadTot),
- OPCODE(o1_palLoad),
- /* 14 */
- OPCODE(o1_keyFunc),
- OPCODE(o1_capturePush),
- OPCODE(o1_capturePop),
- OPCODE(o1_animPalInit),
- /* 18 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 1C */
- {0, ""},
- {0, ""},
- OPCODE(o1_drawOperations),
- OPCODE(o1_setcmdCount),
- /* 20 */
- OPCODE(o1_return),
- OPCODE(o1_renewTimeInVars),
- OPCODE(o1_speakerOn),
- OPCODE(o1_speakerOff),
- /* 24 */
- OPCODE(o1_putPixel),
- OPCODE(o1_goblinFunc),
- OPCODE(o1_createSprite),
- OPCODE(o1_freeSprite),
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- OPCODE(o1_returnTo),
- OPCODE(o1_loadSpriteContent),
- OPCODE(o1_copySprite),
- OPCODE(o1_fillRect),
- /* 34 */
- OPCODE(o1_drawLine),
- OPCODE(o1_strToLong),
- OPCODE(o1_invalidate),
- OPCODE(o1_setBackDelta),
- /* 38 */
- OPCODE(o1_playSound),
- OPCODE(o1_stopSound),
- OPCODE(o1_loadSound),
- OPCODE(o1_freeSoundSlot),
- /* 3C */
- OPCODE(o1_waitEndPlay),
- OPCODE(o1_playComposition),
- OPCODE(o1_getFreeMem),
- OPCODE(o1_checkData),
- /* 40 */
- {0, ""},
- OPCODE(o1_prepareStr),
- OPCODE(o1_insertStr),
- OPCODE(o1_cutStr),
- /* 44 */
- OPCODE(o1_strstr),
- OPCODE(o1_istrlen),
- OPCODE(o1_setMousePos),
- OPCODE(o1_setFrameRate),
- /* 48 */
- OPCODE(o1_animatePalette),
- OPCODE(o1_animateCursor),
- OPCODE(o1_blitCursor),
- OPCODE(o1_loadFont),
- /* 4C */
- OPCODE(o1_freeFont),
- OPCODE(o1_readData),
- OPCODE(o1_writeData),
- OPCODE(o1_manageDataFile),
- };
-
- static const OpcodeGoblinEntryV1 opcodesGoblin[71] = {
- /* 00 */
- OPCODE(o1_setState),
- OPCODE(o1_setCurFrame),
- OPCODE(o1_setNextState),
- OPCODE(o1_setMultState),
- /* 04 */
- OPCODE(o1_setOrder),
- OPCODE(o1_setActionStartState),
- OPCODE(o1_setCurLookDir),
- OPCODE(o1_setType),
- /* 08 */
- OPCODE(o1_setNoTick),
- OPCODE(o1_setPickable),
- OPCODE(o1_setXPos),
- OPCODE(o1_setYPos),
- /* 0C */
- OPCODE(o1_setDoAnim),
- OPCODE(o1_setRelaxTime),
- OPCODE(o1_setMaxTick),
- OPCODE(o1_getState),
- /* 10 */
- OPCODE(o1_getCurFrame),
- OPCODE(o1_getNextState),
- OPCODE(o1_getMultState),
- OPCODE(o1_getOrder),
- /* 14 */
- OPCODE(o1_getActionStartState),
- OPCODE(o1_getCurLookDir),
- OPCODE(o1_getType),
- OPCODE(o1_getNoTick),
- /* 18 */
- OPCODE(o1_getPickable),
- OPCODE(o1_getObjMaxFrame),
- OPCODE(o1_getXPos),
- OPCODE(o1_getYPos),
- /* 1C */
- OPCODE(o1_getDoAnim),
- OPCODE(o1_getRelaxTime),
- OPCODE(o1_getMaxTick),
- OPCODE(o1_manipulateMap),
- /* 20 */
- OPCODE(o1_getItem),
- OPCODE(o1_manipulateMapIndirect),
- OPCODE(o1_getItemIndirect),
- OPCODE(o1_setPassMap),
- /* 24 */
- OPCODE(o1_setGoblinPosH),
- OPCODE(o1_getGoblinPosXH),
- OPCODE(o1_getGoblinPosYH),
- OPCODE(o1_setGoblinMultState),
- /* 28 */
- OPCODE(o1_setGoblinUnk14),
- OPCODE(o1_setItemIdInPocket),
- OPCODE(o1_setItemIndInPocket),
- OPCODE(o1_getItemIdInPocket),
- /* 2C */
- OPCODE(o1_getItemIndInPocket),
- OPCODE(o1_setItemPos),
- OPCODE(o1_setGoblinPos),
- OPCODE(o1_setGoblinState),
- /* 30 */
- OPCODE(o1_setGoblinStateRedraw),
- OPCODE(o1_decRelaxTime),
- OPCODE(o1_getGoblinPosX),
- OPCODE(o1_getGoblinPosY),
- /* 34 */
- OPCODE(o1_clearPathExistence),
- OPCODE(o1_setGoblinVisible),
- OPCODE(o1_setGoblinInvisible),
- OPCODE(o1_getObjectIntersect),
- /* 38 */
- OPCODE(o1_getGoblinIntersect),
- OPCODE(o1_setItemPos),
- OPCODE(o1_loadObjects),
- OPCODE(o1_freeObjects),
- /* 3C */
- OPCODE(o1_animateObjects),
- OPCODE(o1_drawObjects),
- OPCODE(o1_loadMap),
- OPCODE(o1_moveGoblin),
- /* 40 */
- OPCODE(o1_switchGoblin),
- OPCODE(o1_loadGoblin),
- OPCODE(o1_writeTreatItem),
- OPCODE(o1_moveGoblin0),
- /* 44 */
- OPCODE(o1_setGoblinTarget),
- OPCODE(o1_setGoblinObjectsPos),
- OPCODE(o1_initGoblin)
- };
-
- _opcodesDrawV1 = opcodesDraw;
- _opcodesFuncV1 = opcodesFunc;
- _opcodesGoblinV1 = opcodesGoblin;
-}
-
-void Inter_v1::executeDrawOpcode(byte i) {
- debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)",
- i, i, getOpcodeDrawDesc(i));
-
- OpcodeDrawProcV1 op = _opcodesDrawV1[i].proc;
-
- if (op == 0)
- warning("unimplemented opcodeDraw: %d", i);
- else
- (this->*op) ();
-}
-
-bool Inter_v1::executeFuncOpcode(byte i, byte j, OpFuncParams &params) {
- debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)",
- i, j, i, j, getOpcodeFuncDesc(i, j));
-
- if ((i > 4) || (j > 15)) {
- warning("unimplemented opcodeFunc: %d.%d", i, j);
- return false;
- }
-
- OpcodeFuncProcV1 op = _opcodesFuncV1[i*16 + j].proc;
-
- if (op == 0)
- warning("unimplemented opcodeFunc: %d.%d", i, j);
- else
- return (this->*op) (params);
- return false;
}
-void Inter_v1::executeGoblinOpcode(int i, OpGobParams &params) {
- debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)",
- i, i, getOpcodeGoblinDesc(i));
+void Inter_v1::setupOpcodesDraw() {
+ OPCODEDRAW(0x00, o1_loadMult);
+ OPCODEDRAW(0x01, o1_playMult);
+ OPCODEDRAW(0x02, o1_freeMultKeys);
- OpcodeGoblinProcV1 op = 0;
+ OPCODEDRAW(0x07, o1_initCursor);
+
+ OPCODEDRAW(0x08, o1_initCursorAnim);
+ OPCODEDRAW(0x09, o1_clearCursorAnim);
+ OPCODEDRAW(0x0A, o1_setRenderFlags);
- for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
- if (_goblinFuncLookUp[j][0] == i) {
- op = _opcodesGoblinV1[_goblinFuncLookUp[j][1]].proc;
- break;
- }
-
- if (op == 0) {
- warning("unimplemented opcodeGoblin: %d", i);
- _vm->_global->_inter_execPtr -= 2;
- int16 cmd = load16();
- _vm->_global->_inter_execPtr += cmd * 2;
- } else
- (this->*op) (params);
-}
-
-const char *Inter_v1::getOpcodeDrawDesc(byte i) {
- return _opcodesDrawV1[i].desc;
-}
-
-const char *Inter_v1::getOpcodeFuncDesc(byte i, byte j) {
- if ((i > 4) || (j > 15))
- return "";
-
- return _opcodesFuncV1[i*16 + j].desc;
-}
-
-const char *Inter_v1::getOpcodeGoblinDesc(int i) {
- for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
- if (_goblinFuncLookUp[j][0] == i)
- return _opcodesGoblinV1[_goblinFuncLookUp[j][1]].desc;
- return "";
-}
-
-void Inter_v1::checkSwitchTable(byte **ppExec) {
+ OPCODEDRAW(0x10, o1_loadAnim);
+ OPCODEDRAW(0x11, o1_freeAnim);
+ OPCODEDRAW(0x12, o1_updateAnim);
+
+ OPCODEDRAW(0x14, o1_initMult);
+ OPCODEDRAW(0x15, o1_freeMult);
+ OPCODEDRAW(0x16, o1_animate);
+ OPCODEDRAW(0x17, o1_loadMultObject);
+
+ OPCODEDRAW(0x18, o1_getAnimLayerInfo);
+ OPCODEDRAW(0x19, o1_getObjAnimSize);
+ OPCODEDRAW(0x1A, o1_loadStatic);
+ OPCODEDRAW(0x1B, o1_freeStatic);
+
+ OPCODEDRAW(0x1C, o1_renderStatic);
+ OPCODEDRAW(0x1D, o1_loadCurLayer);
+
+ OPCODEDRAW(0x20, o1_playCDTrack);
+ OPCODEDRAW(0x21, o1_getCDTrackPos);
+ OPCODEDRAW(0x22, o1_stopCD);
+
+ OPCODEDRAW(0x30, o1_loadFontToSprite);
+ OPCODEDRAW(0x31, o1_freeFontToSprite);
+}
+
+void Inter_v1::setupOpcodesFunc() {
+ OPCODEFUNC(0x00, o1_callSub);
+ OPCODEFUNC(0x01, o1_callSub);
+ OPCODEFUNC(0x02, o1_printTotText);
+ OPCODEFUNC(0x03, o1_loadCursor);
+
+ OPCODEFUNC(0x05, o1_switch);
+ OPCODEFUNC(0x06, o1_repeatUntil);
+ OPCODEFUNC(0x07, o1_whileDo);
+
+ OPCODEFUNC(0x08, o1_if);
+ OPCODEFUNC(0x09, o1_assign);
+ OPCODEFUNC(0x0A, o1_loadSpriteToPos);
+ OPCODEFUNC(0x11, o1_printText);
+ OPCODEFUNC(0x12, o1_loadTot);
+ OPCODEFUNC(0x13, o1_palLoad);
+
+ OPCODEFUNC(0x14, o1_keyFunc);
+ OPCODEFUNC(0x15, o1_capturePush);
+ OPCODEFUNC(0x16, o1_capturePop);
+ OPCODEFUNC(0x17, o1_animPalInit);
+
+ OPCODEFUNC(0x1E, o1_drawOperations);
+ OPCODEFUNC(0x1F, o1_setcmdCount);
+
+ OPCODEFUNC(0x20, o1_return);
+ OPCODEFUNC(0x21, o1_renewTimeInVars);
+ OPCODEFUNC(0x22, o1_speakerOn);
+ OPCODEFUNC(0x23, o1_speakerOff);
+
+ OPCODEFUNC(0x24, o1_putPixel);
+ OPCODEFUNC(0x25, o1_goblinFunc);
+ OPCODEFUNC(0x26, o1_createSprite);
+ OPCODEFUNC(0x27, o1_freeSprite);
+
+ OPCODEFUNC(0x30, o1_returnTo);
+ OPCODEFUNC(0x31, o1_loadSpriteContent);
+ OPCODEFUNC(0x32, o1_copySprite);
+ OPCODEFUNC(0x33, o1_fillRect);
+
+ OPCODEFUNC(0x34, o1_drawLine);
+ OPCODEFUNC(0x35, o1_strToLong);
+ OPCODEFUNC(0x36, o1_invalidate);
+ OPCODEFUNC(0x37, o1_setBackDelta);
+
+ OPCODEFUNC(0x38, o1_playSound);
+ OPCODEFUNC(0x39, o1_stopSound);
+ OPCODEFUNC(0x3A, o1_loadSound);
+ OPCODEFUNC(0x3B, o1_freeSoundSlot);
+
+ OPCODEFUNC(0x3C, o1_waitEndPlay);
+ OPCODEFUNC(0x3D, o1_playComposition);
+ OPCODEFUNC(0x3E, o1_getFreeMem);
+ OPCODEFUNC(0x3F, o1_checkData);
+
+ OPCODEFUNC(0x41, o1_prepareStr);
+ OPCODEFUNC(0x42, o1_insertStr);
+ OPCODEFUNC(0x43, o1_cutStr);
+
+ OPCODEFUNC(0x44, o1_strstr);
+ OPCODEFUNC(0x45, o1_istrlen);
+ OPCODEFUNC(0x46, o1_setMousePos);
+ OPCODEFUNC(0x47, o1_setFrameRate);
+
+ OPCODEFUNC(0x48, o1_animatePalette);
+ OPCODEFUNC(0x49, o1_animateCursor);
+ OPCODEFUNC(0x4A, o1_blitCursor);
+ OPCODEFUNC(0x4B, o1_loadFont);
+
+ OPCODEFUNC(0x4C, o1_freeFont);
+ OPCODEFUNC(0x4D, o1_readData);
+ OPCODEFUNC(0x4E, o1_writeData);
+ OPCODEFUNC(0x4F, o1_manageDataFile);
+}
+
+void Inter_v1::setupOpcodesGob() {
+ OPCODEGOB( 1, o1_setState);
+ OPCODEGOB( 2, o1_setCurFrame);
+ OPCODEGOB( 3, o1_setNextState);
+ OPCODEGOB( 4, o1_setMultState);
+ OPCODEGOB( 5, o1_setOrder);
+ OPCODEGOB( 6, o1_setActionStartState);
+ OPCODEGOB( 7, o1_setCurLookDir);
+ OPCODEGOB( 8, o1_setType);
+ OPCODEGOB( 9, o1_setNoTick);
+ OPCODEGOB( 10, o1_setPickable);
+ OPCODEGOB( 12, o1_setXPos);
+ OPCODEGOB( 13, o1_setYPos);
+ OPCODEGOB( 14, o1_setDoAnim);
+ OPCODEGOB( 15, o1_setRelaxTime);
+ OPCODEGOB( 16, o1_setMaxTick);
+ OPCODEGOB( 21, o1_getState);
+ OPCODEGOB( 22, o1_getCurFrame);
+ OPCODEGOB( 23, o1_getNextState);
+ OPCODEGOB( 24, o1_getMultState);
+ OPCODEGOB( 25, o1_getOrder);
+ OPCODEGOB( 26, o1_getActionStartState);
+ OPCODEGOB( 27, o1_getCurLookDir);
+ OPCODEGOB( 28, o1_getType);
+ OPCODEGOB( 29, o1_getNoTick);
+ OPCODEGOB( 30, o1_getPickable);
+ OPCODEGOB( 32, o1_getObjMaxFrame);
+ OPCODEGOB( 33, o1_getXPos);
+ OPCODEGOB( 34, o1_getYPos);
+ OPCODEGOB( 35, o1_getDoAnim);
+ OPCODEGOB( 36, o1_getRelaxTime);
+ OPCODEGOB( 37, o1_getMaxTick);
+ OPCODEGOB( 40, o1_manipulateMap);
+ OPCODEGOB( 41, o1_getItem);
+ OPCODEGOB( 42, o1_manipulateMapIndirect);
+ OPCODEGOB( 43, o1_getItemIndirect);
+ OPCODEGOB( 44, o1_setPassMap);
+ OPCODEGOB( 50, o1_setGoblinPosH);
+ OPCODEGOB( 52, o1_getGoblinPosXH);
+ OPCODEGOB( 53, o1_getGoblinPosYH);
+ OPCODEGOB( 150, o1_setGoblinMultState);
+ OPCODEGOB( 152, o1_setGoblinUnk14);
+ OPCODEGOB( 200, o1_setItemIdInPocket);
+ OPCODEGOB( 201, o1_setItemIndInPocket);
+ OPCODEGOB( 202, o1_getItemIdInPocket);
+ OPCODEGOB( 203, o1_getItemIndInPocket);
+ OPCODEGOB( 204, o1_setItemPos);
+ OPCODEGOB( 250, o1_setGoblinPos);
+ OPCODEGOB( 251, o1_setGoblinState);
+ OPCODEGOB( 252, o1_setGoblinStateRedraw);
+ OPCODEGOB( 500, o1_decRelaxTime);
+ OPCODEGOB( 502, o1_getGoblinPosX);
+ OPCODEGOB( 503, o1_getGoblinPosY);
+ OPCODEGOB( 600, o1_clearPathExistence);
+ OPCODEGOB( 601, o1_setGoblinVisible);
+ OPCODEGOB( 602, o1_setGoblinInvisible);
+ OPCODEGOB( 603, o1_getObjectIntersect);
+ OPCODEGOB( 604, o1_getGoblinIntersect);
+ OPCODEGOB( 605, o1_setItemPos);
+ OPCODEGOB(1000, o1_loadObjects);
+ OPCODEGOB(1001, o1_freeObjects);
+ OPCODEGOB(1002, o1_animateObjects);
+ OPCODEGOB(1003, o1_drawObjects);
+ OPCODEGOB(1004, o1_loadMap);
+ OPCODEGOB(1005, o1_moveGoblin);
+ OPCODEGOB(1006, o1_switchGoblin);
+ OPCODEGOB(1008, o1_loadGoblin);
+ OPCODEGOB(1009, o1_writeTreatItem);
+ OPCODEGOB(1010, o1_moveGoblin0);
+ OPCODEGOB(1011, o1_setGoblinTarget);
+ OPCODEGOB(1015, o1_setGoblinObjectsPos);
+ OPCODEGOB(2005, o1_initGoblin);
+}
+
+void Inter_v1::checkSwitchTable(uint32 &offset) {
int16 len;
int32 value;
bool found;
@@ -727,56 +249,54 @@ void Inter_v1::checkSwitchTable(byte **ppExec) {
found = false;
notFound = true;
- *ppExec = 0;
- value = VAR_OFFSET(_vm->_parse->parseVarIndex());
+ offset = 0;
+ value = VAR_OFFSET(_vm->_game->_script->readVarIndex());
- len = (int8) *_vm->_global->_inter_execPtr++;
+ len = _vm->_game->_script->readInt8();
while (len != -5) {
for (int i = 0; i < len; i++) {
- evalExpr(0);
+ _vm->_game->_script->evalExpr(0);
if (_terminate)
return;
- if (_vm->_global->_inter_resVal == value) {
+ if (_vm->_game->_script->getResultInt() == value) {
found = true;
notFound = false;
}
}
if (found)
- *ppExec = _vm->_global->_inter_execPtr;
+ offset = _vm->_game->_script->pos();
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2;
+ _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2);
found = false;
- len = (int8) *_vm->_global->_inter_execPtr++;
+ len = _vm->_game->_script->readInt8();
}
- if ((*_vm->_global->_inter_execPtr >> 4) != 4)
+ if ((_vm->_game->_script->peekByte() >> 4) != 4)
return;
- _vm->_global->_inter_execPtr++;
+ _vm->_game->_script->skip(1);
if (notFound)
- *ppExec = _vm->_global->_inter_execPtr;
+ offset = _vm->_game->_script->pos();
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2;
+ _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2);
}
void Inter_v1::o1_loadMult() {
- _vm->_mult->loadMult(load16());
+ _vm->_mult->loadMult(_vm->_game->_script->readInt16());
}
void Inter_v1::o1_playMult() {
int16 checkEscape;
- checkEscape = load16();
+ checkEscape = _vm->_game->_script->readInt16();
_vm->_mult->playMult(VAR(57), -1, checkEscape, 0);
}
void Inter_v1::o1_freeMultKeys() {
- load16();
+ _vm->_game->_script->readInt16();
_vm->_mult->freeMultKeys();
}
@@ -785,20 +305,20 @@ void Inter_v1::o1_initCursor() {
int16 height;
int16 count;
- _vm->_draw->_cursorHotspotXVar = _vm->_parse->parseVarIndex() / 4;
- _vm->_draw->_cursorHotspotYVar = _vm->_parse->parseVarIndex() / 4;
+ _vm->_draw->_cursorHotspotXVar = _vm->_game->_script->readVarIndex() / 4;
+ _vm->_draw->_cursorHotspotYVar = _vm->_game->_script->readVarIndex() / 4;
- width = load16();
+ width = _vm->_game->_script->readInt16();
if (width < 16)
width = 16;
- height = load16();
+ height = _vm->_game->_script->readInt16();
if (height < 16)
height = 16;
_vm->_draw->adjustCoords(0, &width, &height);
- count = load16();
+ count = _vm->_game->_script->readInt16();
if (count < 2)
count = 2;
@@ -846,24 +366,24 @@ void Inter_v1::o1_initCursorAnim() {
int16 ind;
_vm->_draw->_showCursor = 3;
- ind = _vm->_parse->parseValExpr();
- _vm->_draw->_cursorAnimLow[ind] = load16();
- _vm->_draw->_cursorAnimHigh[ind] = load16();
- _vm->_draw->_cursorAnimDelays[ind] = load16();
+ ind = _vm->_game->_script->readValExpr();
+ _vm->_draw->_cursorAnimLow[ind] = _vm->_game->_script->readInt16();
+ _vm->_draw->_cursorAnimHigh[ind] = _vm->_game->_script->readInt16();
+ _vm->_draw->_cursorAnimDelays[ind] = _vm->_game->_script->readInt16();
}
void Inter_v1::o1_clearCursorAnim() {
int16 ind;
_vm->_draw->_showCursor = 0;
- ind = _vm->_parse->parseValExpr();
+ ind = _vm->_game->_script->readValExpr();
_vm->_draw->_cursorAnimLow[ind] = -1;
_vm->_draw->_cursorAnimHigh[ind] = 0;
_vm->_draw->_cursorAnimDelays[ind] = 0;
}
void Inter_v1::o1_setRenderFlags() {
- _vm->_draw->_renderFlags = _vm->_parse->parseValExpr();
+ _vm->_draw->_renderFlags = _vm->_game->_script->readValExpr();
}
void Inter_v1::o1_loadAnim() {
@@ -882,12 +402,12 @@ void Inter_v1::o1_updateAnim() {
int16 layer;
int16 animation;
- evalExpr(&deltaX);
- evalExpr(&deltaY);
- evalExpr(&animation);
- evalExpr(&layer);
- evalExpr(&frame);
- flags = load16();
+ _vm->_game->_script->evalExpr(&deltaX);
+ _vm->_game->_script->evalExpr(&deltaY);
+ _vm->_game->_script->evalExpr(&animation);
+ _vm->_game->_script->evalExpr(&layer);
+ _vm->_game->_script->evalExpr(&frame);
+ flags = _vm->_game->_script->readInt16();
_vm->_scenery->updateAnim(layer, frame, animation, flags,
deltaX, deltaY, 1);
}
@@ -904,14 +424,14 @@ void Inter_v1::o1_initMult() {
oldAnimHeight = _vm->_mult->_animHeight;
oldObjCount = _vm->_mult->_objCount;
- _vm->_mult->_animLeft = load16();
- _vm->_mult->_animTop = load16();
- _vm->_mult->_animWidth = load16();
- _vm->_mult->_animHeight = load16();
- _vm->_mult->_objCount = load16();
- posXVar = _vm->_parse->parseVarIndex();
- posYVar = _vm->_parse->parseVarIndex();
- animDataVar = _vm->_parse->parseVarIndex();
+ _vm->_mult->_animLeft = _vm->_game->_script->readInt16();
+ _vm->_mult->_animTop = _vm->_game->_script->readInt16();
+ _vm->_mult->_animWidth = _vm->_game->_script->readInt16();
+ _vm->_mult->_animHeight = _vm->_game->_script->readInt16();
+ _vm->_mult->_objCount = _vm->_game->_script->readInt16();
+ posXVar = _vm->_game->_script->readVarIndex();
+ posYVar = _vm->_game->_script->readVarIndex();
+ animDataVar = _vm->_game->_script->readVarIndex();
if (_vm->_mult->_objects && (oldObjCount != _vm->_mult->_objCount)) {
@@ -944,8 +464,8 @@ void Inter_v1::o1_initMult() {
uint32 offPosY = i * 4 + (posYVar / 4) * 4;
uint32 offAnim = animDataVar + i * 4 * _vm->_global->_inter_animDataSize;
- _vm->_mult->_objects[i].pPosX = new VariableReference(*_vm->_inter->_variables, offPosX);
- _vm->_mult->_objects[i].pPosY = new VariableReference(*_vm->_inter->_variables, offPosY);
+ _vm->_mult->_objects[i].pPosX = new VariableReference(*_variables, offPosX);
+ _vm->_mult->_objects[i].pPosY = new VariableReference(*_variables, offPosY);
_vm->_mult->_objects[i].pAnimData =
(Mult::Mult_AnimData *) _variables->getAddressOff8(offAnim);
@@ -998,21 +518,21 @@ void Inter_v1::o1_loadMultObject() {
int16 objIndex;
byte *multData;
- evalExpr(&objIndex);
- evalExpr(&val);
+ _vm->_game->_script->evalExpr(&objIndex);
+ _vm->_game->_script->evalExpr(&val);
*_vm->_mult->_objects[objIndex].pPosX = val;
- evalExpr(&val);
+ _vm->_game->_script->evalExpr(&val);
*_vm->_mult->_objects[objIndex].pPosY = val;
debugC(4, kDebugGameFlow, "Loading mult object %d", objIndex);
multData = (byte *) _vm->_mult->_objects[objIndex].pAnimData;
for (int i = 0; i < 11; i++) {
- if (READ_LE_UINT16(_vm->_global->_inter_execPtr) != 99) {
- evalExpr(&val);
+ if (_vm->_game->_script->peekUint16() != 99) {
+ _vm->_game->_script->evalExpr(&val);
multData[i] = val;
} else
- _vm->_global->_inter_execPtr++;
+ _vm->_game->_script->skip(1);
}
}
@@ -1023,13 +543,13 @@ void Inter_v1::o1_getAnimLayerInfo() {
int16 varUnk0;
int16 varFrames;
- evalExpr(&anim);
- evalExpr(&layer);
+ _vm->_game->_script->evalExpr(&anim);
+ _vm->_game->_script->evalExpr(&layer);
- varDX = _vm->_parse->parseVarIndex();
- varDY = _vm->_parse->parseVarIndex();
- varUnk0 = _vm->_parse->parseVarIndex();
- varFrames = _vm->_parse->parseVarIndex();
+ varDX = _vm->_game->_script->readVarIndex();
+ varDY = _vm->_game->_script->readVarIndex();
+ varUnk0 = _vm->_game->_script->readVarIndex();
+ varFrames = _vm->_game->_script->readVarIndex();
_vm->_scenery->writeAnimLayerInfo(anim, layer,
varDX, varDY, varUnk0, varFrames);
@@ -1038,7 +558,7 @@ void Inter_v1::o1_getAnimLayerInfo() {
void Inter_v1::o1_getObjAnimSize() {
int16 objIndex;
- evalExpr(&objIndex);
+ _vm->_game->_script->evalExpr(&objIndex);
Mult::Mult_AnimData &animData = *(_vm->_mult->_objects[objIndex].pAnimData);
if (animData.isStatic == 0)
@@ -1048,10 +568,10 @@ void Inter_v1::o1_getObjAnimSize() {
_vm->_scenery->_toRedrawLeft = MAX(_vm->_scenery->_toRedrawLeft, (int16) 0);
_vm->_scenery->_toRedrawTop = MAX(_vm->_scenery->_toRedrawTop, (int16) 0);
- WRITE_VAR_OFFSET(_vm->_parse->parseVarIndex(), _vm->_scenery->_toRedrawLeft);
- WRITE_VAR_OFFSET(_vm->_parse->parseVarIndex(), _vm->_scenery->_toRedrawTop);
- WRITE_VAR_OFFSET(_vm->_parse->parseVarIndex(), _vm->_scenery->_toRedrawRight);
- WRITE_VAR_OFFSET(_vm->_parse->parseVarIndex(), _vm->_scenery->_toRedrawBottom);
+ WRITE_VAR_OFFSET(_vm->_game->_script->readVarIndex(), _vm->_scenery->_toRedrawLeft);
+ WRITE_VAR_OFFSET(_vm->_game->_script->readVarIndex(), _vm->_scenery->_toRedrawTop);
+ WRITE_VAR_OFFSET(_vm->_game->_script->readVarIndex(), _vm->_scenery->_toRedrawRight);
+ WRITE_VAR_OFFSET(_vm->_game->_script->readVarIndex(), _vm->_scenery->_toRedrawBottom);
}
void Inter_v1::o1_loadStatic() {
@@ -1066,20 +586,20 @@ void Inter_v1::o1_renderStatic() {
int16 layer;
int16 index;
- _vm->_inter->evalExpr(&index);
- _vm->_inter->evalExpr(&layer);
+ _vm->_game->_script->evalExpr(&index);
+ _vm->_game->_script->evalExpr(&layer);
_vm->_scenery->renderStatic(index, layer);
}
void Inter_v1::o1_loadCurLayer() {
- evalExpr(&_vm->_scenery->_curStatic);
- evalExpr(&_vm->_scenery->_curStaticLayer);
+ _vm->_game->_script->evalExpr(&_vm->_scenery->_curStatic);
+ _vm->_game->_script->evalExpr(&_vm->_scenery->_curStaticLayer);
}
void Inter_v1::o1_playCDTrack() {
- evalExpr(0);
+ _vm->_game->_script->evalExpr(0);
_vm->_sound->adlibPlayBgMusic(); // Mac version
- _vm->_sound->cdPlay(_vm->_global->_inter_resStr); // PC CD version
+ _vm->_sound->cdPlay(_vm->_game->_script->getResultStr()); // PC CD version
}
void Inter_v1::o1_getCDTrackPos() {
@@ -1103,15 +623,15 @@ void Inter_v1::o1_stopCD() {
}
void Inter_v1::o1_loadFontToSprite() {
- int16 i = load16();
- _vm->_draw->_fontToSprite[i].sprite = load16();
- _vm->_draw->_fontToSprite[i].base = load16();
- _vm->_draw->_fontToSprite[i].width = load16();
- _vm->_draw->_fontToSprite[i].height = load16();
+ int16 i = _vm->_game->_script->readInt16();
+ _vm->_draw->_fontToSprite[i].sprite = _vm->_game->_script->readInt16();
+ _vm->_draw->_fontToSprite[i].base = _vm->_game->_script->readInt16();
+ _vm->_draw->_fontToSprite[i].width = _vm->_game->_script->readInt16();
+ _vm->_draw->_fontToSprite[i].height = _vm->_game->_script->readInt16();
}
void Inter_v1::o1_freeFontToSprite() {
- int16 i = load16();
+ int16 i = _vm->_game->_script->readInt16();
_vm->_draw->_fontToSprite[i].sprite = -1;
_vm->_draw->_fontToSprite[i].base = -1;
_vm->_draw->_fontToSprite[i].width = -1;
@@ -1119,11 +639,7 @@ void Inter_v1::o1_freeFontToSprite() {
}
bool Inter_v1::o1_callSub(OpFuncParams &params) {
- byte *storedIP;
- uint16 offset;
-
- offset = load16();
- storedIP = _vm->_global->_inter_execPtr;
+ uint16 offset = _vm->_game->_script->readUint16();
debugC(5, kDebugGameFlow, "tot = \"%s\", offset = %d",
_vm->_game->_curTotFile, offset);
@@ -1147,79 +663,89 @@ bool Inter_v1::o1_callSub(OpFuncParams &params) {
return false;
}
- _vm->_global->_inter_execPtr = _vm->_game->_totFileData + offset;
+ _vm->_game->_script->call(offset);
- if ((params.counter == params.cmdCount) && (params.retFlag == 2))
+ if ((params.counter == params.cmdCount) && (params.retFlag == 2)) {
+ _vm->_game->_script->pop(false);
return true;
+ }
callSub(2);
- _vm->_global->_inter_execPtr = storedIP;
+
+ _vm->_game->_script->pop();
return false;
}
bool Inter_v1::o1_printTotText(OpFuncParams &params) {
- _vm->_draw->printTotText(load16());
+ _vm->_draw->printTotText(_vm->_game->_script->readInt16());
return false;
}
bool Inter_v1::o1_loadCursor(OpFuncParams &params) {
- int16 width, height;
- byte *dataBuf;
- int16 id;
- int8 index;
-
- id = load16();
- index = (int8) *_vm->_global->_inter_execPtr++;
+ int16 id = _vm->_game->_script->readInt16();
+ int8 index = _vm->_game->_script->readInt8();
if ((index * _vm->_draw->_cursorWidth) >= _vm->_draw->_cursorSprites->getWidth())
return false;
- dataBuf = _vm->_game->loadTotResource(id, 0, &width, &height);
+ Resource *resource = _vm->_game->_resources->getResource(id);
+ if (!resource)
+ return false;
_vm->_video->fillRect(*_vm->_draw->_cursorSprites,
index * _vm->_draw->_cursorWidth, 0,
index * _vm->_draw->_cursorWidth + _vm->_draw->_cursorWidth - 1,
_vm->_draw->_cursorHeight - 1, 0);
- _vm->_video->drawPackedSprite(dataBuf, width, height,
+ _vm->_video->drawPackedSprite(resource->getData(),
+ resource->getWidth(), resource->getHeight(),
index * _vm->_draw->_cursorWidth, 0, 0, *_vm->_draw->_cursorSprites);
_vm->_draw->_cursorAnimLow[index] = 0;
+ delete resource;
return false;
}
bool Inter_v1::o1_switch(OpFuncParams &params) {
- byte *callAddr;
+ uint32 offset;
+
+ checkSwitchTable(offset);
- checkSwitchTable(&callAddr);
- byte *storedIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr = callAddr;
+ _vm->_game->_script->call(offset);
- if ((params.counter == params.cmdCount) && (params.retFlag == 2))
+ if (offset == 0)
+ _vm->_game->_script->setFinished(true);
+
+ if ((params.counter == params.cmdCount) && (params.retFlag == 2)) {
+ _vm->_game->_script->pop(false);
return true;
+ }
funcBlock(0);
- _vm->_global->_inter_execPtr = storedIP;
+
+ _vm->_game->_script->pop();
return false;
}
bool Inter_v1::o1_repeatUntil(OpFuncParams &params) {
- byte *blockPtr;
int16 size;
bool flag;
_nestLevel[0]++;
- blockPtr = _vm->_global->_inter_execPtr;
+
+ uint32 blockPos = _vm->_game->_script->pos();
do {
- _vm->_global->_inter_execPtr = blockPtr;
- size = READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2;
+ _vm->_game->_script->seek(blockPos);
+ size = _vm->_game->_script->peekUint16(2) + 2;
funcBlock(1);
- _vm->_global->_inter_execPtr = blockPtr + size + 1;
- flag = evalBoolResult();
+
+ _vm->_game->_script->seek(blockPos + size + 1);
+
+ flag = _vm->_game->_script->evalBoolResult();
} while (!flag && !_break && !_terminate && !_vm->shouldQuit());
_nestLevel[0]--;
@@ -1232,32 +758,31 @@ bool Inter_v1::o1_repeatUntil(OpFuncParams &params) {
}
bool Inter_v1::o1_whileDo(OpFuncParams &params) {
- byte *blockPtr;
- byte *savedIP;
bool flag;
int16 size;
_nestLevel[0]++;
do {
- savedIP = _vm->_global->_inter_execPtr;
- flag = evalBoolResult();
+ uint32 startPos = _vm->_game->_script->pos();
+
+ flag = _vm->_game->_script->evalBoolResult();
if (_terminate)
return false;
- blockPtr = _vm->_global->_inter_execPtr;
+ uint32 blockPos = _vm->_game->_script->pos();
- size = READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2;
+ size = _vm->_game->_script->peekUint16(2) + 2;
if (flag) {
funcBlock(1);
- _vm->_global->_inter_execPtr = savedIP;
+ _vm->_game->_script->seek(startPos);
} else
- _vm->_global->_inter_execPtr += size;
+ _vm->_game->_script->skip(size);
if (_break || _terminate || _vm->shouldQuit()) {
- _vm->_global->_inter_execPtr = blockPtr;
- _vm->_global->_inter_execPtr += size;
+ _vm->_game->_script->seek(blockPos);
+ _vm->_game->_script->skip(size);
break;
}
} while (flag);
@@ -1273,76 +798,65 @@ bool Inter_v1::o1_whileDo(OpFuncParams &params) {
bool Inter_v1::o1_if(OpFuncParams &params) {
byte cmd;
bool boolRes;
- byte *storedIP;
- boolRes = evalBoolResult();
+ boolRes = _vm->_game->_script->evalBoolResult();
if (boolRes) {
if ((params.counter == params.cmdCount) && (params.retFlag == 2))
return true;
- storedIP = _vm->_global->_inter_execPtr;
+ _vm->_game->_script->push();
funcBlock(0);
- _vm->_global->_inter_execPtr = storedIP;
+ _vm->_game->_script->pop();
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2;
+ _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2);
- debugC(5, kDebugGameFlow, "cmd = %d",
- (int16) *_vm->_global->_inter_execPtr);
+ debugC(5, kDebugGameFlow, "cmd = %d", (int16) _vm->_game->_script->peekByte());
- cmd = *_vm->_global->_inter_execPtr >> 4;
- _vm->_global->_inter_execPtr++;
+ cmd = _vm->_game->_script->readByte() >> 4;
if (cmd != 12)
return false;
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2;
+ _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2);
} else {
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2;
+ _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2);
- debugC(5, kDebugGameFlow, "cmd = %d",
- (int16) *_vm->_global->_inter_execPtr);
+ debugC(5, kDebugGameFlow, "cmd = %d", (int16) _vm->_game->_script->peekByte());
- cmd = *_vm->_global->_inter_execPtr >> 4;
- _vm->_global->_inter_execPtr++;
+ cmd = _vm->_game->_script->readByte() >> 4;
if (cmd != 12)
return false;
if ((params.counter == params.cmdCount) && (params.retFlag == 2))
return true;
- storedIP = _vm->_global->_inter_execPtr;
+ _vm->_game->_script->push();
funcBlock(0);
- _vm->_global->_inter_execPtr = storedIP;
+ _vm->_game->_script->pop();
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2;
+ _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2);
}
return false;
}
bool Inter_v1::o1_assign(OpFuncParams &params) {
- byte *savedPos;
- int16 token;
+ byte destType = _vm->_game->_script->peekByte();
+ int16 dest = _vm->_game->_script->readVarIndex();
+
int16 result;
- int16 varOff;
+ int16 srcType = _vm->_game->_script->evalExpr(&result);
- savedPos = _vm->_global->_inter_execPtr;
- varOff = _vm->_parse->parseVarIndex();
- token = evalExpr(&result);
- switch (savedPos[0]) {
- case 23:
- case 26:
- WRITE_VAR_OFFSET(varOff, _vm->_global->_inter_resVal);
+ switch (destType) {
+ case TYPE_VAR_INT32:
+ case TYPE_ARRAY_INT32:
+ WRITE_VAR_OFFSET(dest, _vm->_game->_script->getResultInt());
break;
- case 25:
- case 28:
- if (token == 20)
- WRITE_VARO_UINT8(varOff, result);
+ case TYPE_VAR_STR:
+ case TYPE_ARRAY_STR:
+ if (srcType == TYPE_IMM_INT16)
+ WRITE_VARO_UINT8(dest, result);
else
- WRITE_VARO_STR(varOff, _vm->_global->_inter_resStr);
+ WRITE_VARO_STR(dest, _vm->_game->_script->getResultStr());
break;
}
@@ -1350,17 +864,17 @@ bool Inter_v1::o1_assign(OpFuncParams &params) {
}
bool Inter_v1::o1_loadSpriteToPos(OpFuncParams &params) {
- _vm->_draw->_spriteLeft = load16();
+ _vm->_draw->_spriteLeft = _vm->_game->_script->readInt16();
- _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr();
- _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr();
+ _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr();
+ _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr();
- _vm->_draw->_transparency = *_vm->_global->_inter_execPtr & 1;
- _vm->_draw->_destSurface = ((int16) (*_vm->_global->_inter_execPtr >> 1)) - 1;
+ _vm->_draw->_transparency = _vm->_game->_script->peekByte() & 1;
+ _vm->_draw->_destSurface = ((int16) (_vm->_game->_script->peekByte() >> 1)) - 1;
if (_vm->_draw->_destSurface < 0)
_vm->_draw->_destSurface = 101;
- _vm->_global->_inter_execPtr += 2;
+ _vm->_game->_script->skip(2);
_vm->_draw->spriteOperation(DRAW_LOADSPRITE);
@@ -1371,12 +885,12 @@ bool Inter_v1::o1_printText(OpFuncParams &params) {
char buf[60];
int i;
- _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr();
- _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr();
+ _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr();
+ _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr();
- _vm->_draw->_backColor = _vm->_parse->parseValExpr();
- _vm->_draw->_frontColor = _vm->_parse->parseValExpr();
- _vm->_draw->_fontIndex = _vm->_parse->parseValExpr();
+ _vm->_draw->_backColor = _vm->_game->_script->readValExpr();
+ _vm->_draw->_frontColor = _vm->_game->_script->readValExpr();
+ _vm->_draw->_fontIndex = _vm->_game->_script->readValExpr();
_vm->_draw->_destSurface = 21;
_vm->_draw->_textToPrint = buf;
_vm->_draw->_transparency = 0;
@@ -1387,35 +901,35 @@ bool Inter_v1::o1_printText(OpFuncParams &params) {
}
do {
- for (i = 0; (((char) *_vm->_global->_inter_execPtr) != '.') &&
- (*_vm->_global->_inter_execPtr != 200);
- i++, _vm->_global->_inter_execPtr++) {
- buf[i] = (char) *_vm->_global->_inter_execPtr;
+ for (i = 0; ((_vm->_game->_script->peekChar()) != '.') &&
+ (_vm->_game->_script->peekByte() != 200);
+ i++, _vm->_game->_script->skip(1)) {
+ buf[i] = _vm->_game->_script->peekChar();
}
- if (*_vm->_global->_inter_execPtr != 200) {
- _vm->_global->_inter_execPtr++;
- switch (*_vm->_global->_inter_execPtr) {
- case 23:
- case 26:
+ if (_vm->_game->_script->peekByte() != 200) {
+ _vm->_game->_script->skip(1);
+ switch (_vm->_game->_script->peekByte()) {
+ case TYPE_VAR_INT32:
+ case TYPE_ARRAY_INT32:
sprintf(buf + i, "%d",
- VAR_OFFSET(_vm->_parse->parseVarIndex()));
+ VAR_OFFSET(_vm->_game->_script->readVarIndex()));
break;
- case 25:
- case 28:
+ case TYPE_VAR_STR:
+ case TYPE_ARRAY_STR:
sprintf(buf + i, "%s",
- GET_VARO_STR(_vm->_parse->parseVarIndex()));
+ GET_VARO_STR(_vm->_game->_script->readVarIndex()));
break;
}
- _vm->_global->_inter_execPtr++;
+ _vm->_game->_script->skip(1);
} else
buf[i] = 0;
_vm->_draw->spriteOperation(DRAW_PRINTTEXT);
- } while (*_vm->_global->_inter_execPtr != 200);
+ } while (_vm->_game->_script->peekByte() != 200);
- _vm->_global->_inter_execPtr++;
+ _vm->_game->_script->skip(1);
return false;
}
@@ -1424,16 +938,14 @@ bool Inter_v1::o1_loadTot(OpFuncParams &params) {
char buf[20];
int8 size;
- if ((*_vm->_global->_inter_execPtr & 0x80) != 0) {
- _vm->_global->_inter_execPtr++;
- evalExpr(0);
- strncpy0(buf, _vm->_global->_inter_resStr, 15);
+ if ((_vm->_game->_script->peekByte() & 0x80) != 0) {
+ _vm->_game->_script->skip(1);
+ _vm->_game->_script->evalExpr(0);
+ strncpy0(buf, _vm->_game->_script->getResultStr(), 15);
} else {
- size = (int8) *_vm->_global->_inter_execPtr++;
- for (int i = 0; i < size; i++)
- buf[i] = *_vm->_global->_inter_execPtr++;
-
- buf[size] = 0;
+ size = _vm->_game->_script->readInt8();
+ memcpy(buf, _vm->_game->_script->readString(size), size);
+ buf[size] = '\0';
}
// if (_vm->getGameType() == kGameTypeGeisha)
@@ -1450,15 +962,15 @@ bool Inter_v1::o1_loadTot(OpFuncParams &params) {
bool Inter_v1::o1_palLoad(OpFuncParams &params) {
int index1, index2;
- byte *palPtr;
byte cmd;
+ Resource *resource;
- cmd = *_vm->_global->_inter_execPtr++;
+ cmd = _vm->_game->_script->readByte();
switch (cmd & 0x7F) {
case 48:
if ((_vm->_global->_fakeVideoMode < 0x32) ||
(_vm->_global->_fakeVideoMode > 0x63)) {
- _vm->_global->_inter_execPtr += 48;
+ _vm->_game->_script->skip(48);
return false;
}
break;
@@ -1466,35 +978,35 @@ bool Inter_v1::o1_palLoad(OpFuncParams &params) {
case 49:
if ((_vm->_global->_fakeVideoMode != 5) &&
(_vm->_global->_fakeVideoMode != 7)) {
- _vm->_global->_inter_execPtr += 18;
+ _vm->_game->_script->skip(18);
return false;
}
break;
case 50:
if (_vm->_global->_colorCount == 256) {
- _vm->_global->_inter_execPtr += 16;
+ _vm->_game->_script->skip(16);
return false;
}
break;
case 51:
if (_vm->_global->_fakeVideoMode < 0x64) {
- _vm->_global->_inter_execPtr += 2;
+ _vm->_game->_script->skip(2);
return false;
}
break;
case 52:
if (_vm->_global->_colorCount == 256) {
- _vm->_global->_inter_execPtr += 48;
+ _vm->_game->_script->skip(48);
return false;
}
break;
case 53:
if (_vm->_global->_colorCount != 256) {
- _vm->_global->_inter_execPtr += 2;
+ _vm->_game->_script->skip(2);
return false;
}
break;
@@ -1507,14 +1019,14 @@ bool Inter_v1::o1_palLoad(OpFuncParams &params) {
case 61:
if (_vm->_global->_fakeVideoMode < 0x13) {
- _vm->_global->_inter_execPtr += 4;
+ _vm->_game->_script->skip(4);
return false;
}
break;
}
if ((cmd & 0x7F) == 0x30) {
- _vm->_global->_inter_execPtr += 48;
+ _vm->_game->_script->skip(48);
return false;
}
@@ -1525,7 +1037,7 @@ bool Inter_v1::o1_palLoad(OpFuncParams &params) {
bool allZero = true;
for (int i = 2; i < 18; i++) {
- if (_vm->_global->_inter_execPtr[i] != 0) {
+ if (_vm->_game->_script->peekByte(i) != 0) {
allZero = false;
break;
}
@@ -1533,28 +1045,30 @@ bool Inter_v1::o1_palLoad(OpFuncParams &params) {
if (!allZero) {
_vm->_video->clearSurf(*_vm->_draw->_frontSurface);
_vm->_draw->_noInvalidated57 = true;
- _vm->_global->_inter_execPtr += 18;
+ _vm->_game->_script->skip(48);
return false;
}
_vm->_draw->_noInvalidated57 = false;
- for (int i = 0; i < 18; i++, _vm->_global->_inter_execPtr++) {
+ for (int i = 0; i < 18; i++) {
if (i < 2) {
if (!_vm->_draw->_applyPal)
continue;
- _vm->_draw->_unusedPalette1[i] = *_vm->_global->_inter_execPtr;
+ _vm->_draw->_unusedPalette1[i] = _vm->_game->_script->peekByte();
continue;
}
- index1 = *_vm->_global->_inter_execPtr >> 4;
- index2 = (*_vm->_global->_inter_execPtr & 0xF);
+ index1 = _vm->_game->_script->peekByte() >> 4;
+ index2 = _vm->_game->_script->peekByte() & 0xF;
_vm->_draw->_unusedPalette1[i] =
((_vm->_draw->_palLoadData1[index1] +
_vm->_draw->_palLoadData2[index2]) << 8) +
(_vm->_draw->_palLoadData2[index1] +
_vm->_draw->_palLoadData1[index2]);
+
+ _vm->_game->_script->skip(1);
}
_vm->_global->_pPaletteDesc->unused1 = _vm->_draw->_unusedPalette1;
@@ -1564,21 +1078,25 @@ bool Inter_v1::o1_palLoad(OpFuncParams &params) {
switch (cmd) {
case 50:
- for (int i = 0; i < 16; i++, _vm->_global->_inter_execPtr++)
- _vm->_draw->_unusedPalette2[i] = *_vm->_global->_inter_execPtr;
+ for (int i = 0; i < 16; i++)
+ _vm->_draw->_unusedPalette2[i] = _vm->_game->_script->readByte();
break;
case 52:
- for (int i = 0; i < 16; i++, _vm->_global->_inter_execPtr += 3) {
- _vm->_draw->_vgaPalette[i].red = _vm->_global->_inter_execPtr[0];
- _vm->_draw->_vgaPalette[i].green = _vm->_global->_inter_execPtr[1];
- _vm->_draw->_vgaPalette[i].blue = _vm->_global->_inter_execPtr[2];
+ for (int i = 0; i < 16; i++) {
+ _vm->_draw->_vgaPalette[i].red = _vm->_game->_script->readByte();
+ _vm->_draw->_vgaPalette[i].green = _vm->_game->_script->readByte();
+ _vm->_draw->_vgaPalette[i].blue = _vm->_game->_script->readByte();
}
break;
case 53:
- palPtr = _vm->_game->loadTotResource(_vm->_inter->load16());
- memcpy((char *) _vm->_draw->_vgaPalette, palPtr, 768);
+ resource = _vm->_game->_resources->getResource(_vm->_game->_script->readInt16());
+ if (!resource)
+ break;
+
+ memcpy((char *) _vm->_draw->_vgaPalette, resource->getData(), MIN(768, resource->getSize()));
+ delete resource;
break;
case 54:
@@ -1586,11 +1104,15 @@ bool Inter_v1::o1_palLoad(OpFuncParams &params) {
break;
case 61:
- index1 = *_vm->_global->_inter_execPtr++;
- index2 = (*_vm->_global->_inter_execPtr++ - index1 + 1) * 3;
- palPtr = _vm->_game->loadTotResource(_vm->_inter->load16());
+ index1 = _vm->_game->_script->readByte();
+ index2 = (_vm->_game->_script->readByte() - index1 + 1) * 3;
+ resource = _vm->_game->_resources->getResource(_vm->_game->_script->readInt16());
+ if (!resource)
+ break;
+
memcpy((char *) _vm->_draw->_vgaPalette + index1 * 3,
- palPtr + index1 * 3, index2);
+ resource->getData() + index1 * 3, index2);
+ delete resource;
if (_vm->_draw->_applyPal) {
_vm->_draw->_applyPal = false;
@@ -1628,7 +1150,7 @@ bool Inter_v1::o1_keyFunc(OpFuncParams &params) {
int16 key;
uint32 now;
- cmd = load16();
+ cmd = _vm->_game->_script->readInt16();
animPalette();
_vm->_draw->blitInvalidated();
@@ -1643,7 +1165,7 @@ bool Inter_v1::o1_keyFunc(OpFuncParams &params) {
// to become 5000. We deliberately slow down busy-waiting, so we shorten
// the counting, too.
if ((_vm->getGameType() == kGameTypeWeen) && (VAR(59) < 4000) &&
- ((_vm->_global->_inter_execPtr - _vm->_game->_totFileData) == 729) &&
+ (_vm->_game->_script->pos() == 729) &&
!scumm_stricmp(_vm->_game->_curTotFile, "intro5.tot"))
WRITE_VAR(59, 4000);
@@ -1689,10 +1211,10 @@ bool Inter_v1::o1_capturePush(OpFuncParams &params) {
int16 left, top;
int16 width, height;
- left = _vm->_parse->parseValExpr();
- top = _vm->_parse->parseValExpr();
- width = _vm->_parse->parseValExpr();
- height = _vm->_parse->parseValExpr();
+ left = _vm->_game->_script->readValExpr();
+ top = _vm->_game->_script->readValExpr();
+ width = _vm->_game->_script->readValExpr();
+ height = _vm->_game->_script->readValExpr();
if ((width < 0) || (height < 0))
return false;
@@ -1711,24 +1233,24 @@ bool Inter_v1::o1_capturePop(OpFuncParams &params) {
}
bool Inter_v1::o1_animPalInit(OpFuncParams &params) {
- _animPalDir[0] = load16();
- _animPalLowIndex[0] = _vm->_parse->parseValExpr();
- _animPalHighIndex[0] = _vm->_parse->parseValExpr();
+ _animPalDir[0] = _vm->_game->_script->readInt16();
+ _animPalLowIndex[0] = _vm->_game->_script->readValExpr();
+ _animPalHighIndex[0] = _vm->_game->_script->readValExpr();
return false;
}
bool Inter_v1::o1_drawOperations(OpFuncParams &params) {
byte cmd;
- cmd = *_vm->_global->_inter_execPtr++;
+ cmd = _vm->_game->_script->readByte();
- executeDrawOpcode(cmd);
+ executeOpcodeDraw(cmd);
return false;
}
bool Inter_v1::o1_setcmdCount(OpFuncParams &params) {
- params.cmdCount = *_vm->_global->_inter_execPtr++;
+ params.cmdCount = _vm->_game->_script->readByte();
params.counter = 0;
return false;
}
@@ -1737,7 +1259,7 @@ bool Inter_v1::o1_return(OpFuncParams &params) {
if (params.retFlag != 2)
_break = true;
- _vm->_global->_inter_execPtr = 0;
+ _vm->_game->_script->setFinished(true);
return true;
}
@@ -1747,7 +1269,7 @@ bool Inter_v1::o1_renewTimeInVars(OpFuncParams &params) {
}
bool Inter_v1::o1_speakerOn(OpFuncParams &params) {
- _vm->_sound->speakerOn(_vm->_parse->parseValExpr(), -1);
+ _vm->_sound->speakerOn(_vm->_game->_script->readValExpr(), -1);
return false;
}
@@ -1757,11 +1279,11 @@ bool Inter_v1::o1_speakerOff(OpFuncParams &params) {
}
bool Inter_v1::o1_putPixel(OpFuncParams &params) {
- _vm->_draw->_destSurface = load16();
+ _vm->_draw->_destSurface = _vm->_game->_script->readInt16();
- _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr();
- _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr();
- _vm->_draw->_frontColor = _vm->_parse->parseValExpr();
+ _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr();
+ _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr();
+ _vm->_draw->_frontColor = _vm->_game->_script->readValExpr();
_vm->_draw->spriteOperation(DRAW_PUTPIXEL);
return false;
}
@@ -1773,33 +1295,33 @@ bool Inter_v1::o1_goblinFunc(OpFuncParams &params) {
gobParams.extraData = 0;
gobParams.objDesc = 0;
- gobParams.retVarPtr.set(*_vm->_inter->_variables, 236);
+ gobParams.retVarPtr.set(*_variables, 236);
- cmd = load16();
- _vm->_global->_inter_execPtr += 2;
+ cmd = _vm->_game->_script->readInt16();
+ _vm->_game->_script->skip(2);
if ((cmd > 0) && (cmd < 17)) {
objDescSet = true;
- gobParams.extraData = load16();
+ gobParams.extraData = _vm->_game->_script->readInt16();
gobParams.objDesc = _vm->_goblin->_objects[gobParams.extraData];
- gobParams.extraData = load16();
+ gobParams.extraData = _vm->_game->_script->readInt16();
}
if ((cmd > 90) && (cmd < 107)) {
objDescSet = true;
- gobParams.extraData = load16();
+ gobParams.extraData = _vm->_game->_script->readInt16();
gobParams.objDesc = _vm->_goblin->_goblins[gobParams.extraData];
- gobParams.extraData = load16();
+ gobParams.extraData = _vm->_game->_script->readInt16();
cmd -= 90;
}
if ((cmd > 110) && (cmd < 128)) {
objDescSet = true;
- gobParams.extraData = load16();
+ gobParams.extraData = _vm->_game->_script->readInt16();
gobParams.objDesc = _vm->_goblin->_goblins[gobParams.extraData];
cmd -= 90;
} else if ((cmd > 20) && (cmd < 38)) {
objDescSet = true;
- gobParams.extraData = load16();
+ gobParams.extraData = _vm->_game->_script->readInt16();
gobParams.objDesc = _vm->_goblin->_objects[gobParams.extraData];
}
@@ -1815,7 +1337,7 @@ bool Inter_v1::o1_goblinFunc(OpFuncParams &params) {
if ((cmd < 40) && objDescSet && !gobParams.objDesc)
return false;
- executeGoblinOpcode(cmd, gobParams);
+ executeOpcodeGob(cmd, gobParams);
return false;
}
@@ -1825,31 +1347,31 @@ bool Inter_v1::o1_createSprite(OpFuncParams &params) {
int16 width, height;
int16 flag;
- if (_vm->_global->_inter_execPtr[1] == 0) {
- index = load16();
- width = load16();
- height = load16();
+ if (_vm->_game->_script->peekByte(1) == 0) {
+ index = _vm->_game->_script->readInt16();
+ width = _vm->_game->_script->readInt16();
+ height = _vm->_game->_script->readInt16();
} else {
- index = _vm->_parse->parseValExpr();
- width = _vm->_parse->parseValExpr();
- height = _vm->_parse->parseValExpr();
+ index = _vm->_game->_script->readValExpr();
+ width = _vm->_game->_script->readValExpr();
+ height = _vm->_game->_script->readValExpr();
}
- flag = load16();
+ flag = _vm->_game->_script->readInt16();
_vm->_draw->initSpriteSurf(index, width, height, flag ? 2 : 0);
return false;
}
bool Inter_v1::o1_freeSprite(OpFuncParams &params) {
- _vm->_draw->freeSprite(load16());
+ _vm->_draw->freeSprite(_vm->_game->_script->readInt16());
return false;
}
bool Inter_v1::o1_returnTo(OpFuncParams &params) {
if (params.retFlag == 1) {
_break = true;
- _vm->_global->_inter_execPtr = 0;
+ _vm->_game->_script->setFinished(true);
return true;
}
@@ -1858,14 +1380,14 @@ bool Inter_v1::o1_returnTo(OpFuncParams &params) {
*_breakFromLevel = *_nestLevel;
_break = true;
- _vm->_global->_inter_execPtr = 0;
+ _vm->_game->_script->setFinished(true);
return true;
}
bool Inter_v1::o1_loadSpriteContent(OpFuncParams &params) {
- _vm->_draw->_spriteLeft = load16();
- _vm->_draw->_destSurface = load16();
- _vm->_draw->_transparency = load16();
+ _vm->_draw->_spriteLeft = _vm->_game->_script->readInt16();
+ _vm->_draw->_destSurface = _vm->_game->_script->readInt16();
+ _vm->_draw->_transparency = _vm->_game->_script->readInt16();
_vm->_draw->_destSpriteX = 0;
_vm->_draw->_destSpriteY = 0;
@@ -1874,25 +1396,25 @@ bool Inter_v1::o1_loadSpriteContent(OpFuncParams &params) {
}
bool Inter_v1::o1_copySprite(OpFuncParams &params) {
- if (_vm->_global->_inter_execPtr[1] == 0)
- _vm->_draw->_sourceSurface = load16();
+ if (_vm->_game->_script->peekByte(1) == 0)
+ _vm->_draw->_sourceSurface = _vm->_game->_script->readInt16();
else
- _vm->_draw->_sourceSurface = _vm->_parse->parseValExpr();
+ _vm->_draw->_sourceSurface = _vm->_game->_script->readValExpr();
- if (_vm->_global->_inter_execPtr[1] == 0)
- _vm->_draw->_destSurface = load16();
+ if (_vm->_game->_script->peekByte(1) == 0)
+ _vm->_draw->_destSurface = _vm->_game->_script->readInt16();
else
- _vm->_draw->_destSurface = _vm->_parse->parseValExpr();
+ _vm->_draw->_destSurface = _vm->_game->_script->readValExpr();
- _vm->_draw->_spriteLeft = _vm->_parse->parseValExpr();
- _vm->_draw->_spriteTop = _vm->_parse->parseValExpr();
- _vm->_draw->_spriteRight = _vm->_parse->parseValExpr();
- _vm->_draw->_spriteBottom = _vm->_parse->parseValExpr();
+ _vm->_draw->_spriteLeft = _vm->_game->_script->readValExpr();
+ _vm->_draw->_spriteTop = _vm->_game->_script->readValExpr();
+ _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr();
+ _vm->_draw->_spriteBottom = _vm->_game->_script->readValExpr();
- _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr();
- _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr();
+ _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr();
+ _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr();
- _vm->_draw->_transparency = load16();
+ _vm->_draw->_transparency = _vm->_game->_script->readInt16();
_vm->_draw->spriteOperation(DRAW_BLITSURF);
return false;
@@ -1901,14 +1423,14 @@ bool Inter_v1::o1_copySprite(OpFuncParams &params) {
bool Inter_v1::o1_fillRect(OpFuncParams &params) {
int16 destSurf;
- _vm->_draw->_destSurface = destSurf = load16();
+ _vm->_draw->_destSurface = destSurf = _vm->_game->_script->readInt16();
- _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr();
- _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr();
- _vm->_draw->_spriteRight = _vm->_parse->parseValExpr();
- _vm->_draw->_spriteBottom = _vm->_parse->parseValExpr();
+ _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr();
+ _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr();
+ _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr();
+ _vm->_draw->_spriteBottom = _vm->_game->_script->readValExpr();
- _vm->_draw->_backColor = _vm->_parse->parseValExpr();
+ _vm->_draw->_backColor = _vm->_game->_script->readValExpr();
if (!_vm->_draw->_spritesArray[(destSurf >= 100) ? (destSurf - 80) : destSurf])
return false;
@@ -1927,14 +1449,14 @@ bool Inter_v1::o1_fillRect(OpFuncParams &params) {
}
bool Inter_v1::o1_drawLine(OpFuncParams &params) {
- _vm->_draw->_destSurface = load16();
+ _vm->_draw->_destSurface = _vm->_game->_script->readInt16();
- _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr();
- _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr();
- _vm->_draw->_spriteRight = _vm->_parse->parseValExpr();
- _vm->_draw->_spriteBottom = _vm->_parse->parseValExpr();
+ _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr();
+ _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr();
+ _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr();
+ _vm->_draw->_spriteBottom = _vm->_game->_script->readValExpr();
- _vm->_draw->_frontColor = _vm->_parse->parseValExpr();
+ _vm->_draw->_frontColor = _vm->_game->_script->readValExpr();
_vm->_draw->spriteOperation(DRAW_DRAWLINE);
return false;
}
@@ -1945,28 +1467,28 @@ bool Inter_v1::o1_strToLong(OpFuncParams &params) {
int16 destVar;
int32 res;
- strVar = _vm->_parse->parseVarIndex();
+ strVar = _vm->_game->_script->readVarIndex();
strncpy0(str, GET_VARO_STR(strVar), 19);
res = atoi(str);
- destVar = _vm->_parse->parseVarIndex();
+ destVar = _vm->_game->_script->readVarIndex();
WRITE_VAR_OFFSET(destVar, res);
return false;
}
bool Inter_v1::o1_invalidate(OpFuncParams &params) {
- _vm->_draw->_destSurface = load16();
- _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr();
- _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr();
- _vm->_draw->_spriteRight = _vm->_parse->parseValExpr();
- _vm->_draw->_frontColor = _vm->_parse->parseValExpr();
+ _vm->_draw->_destSurface = _vm->_game->_script->readInt16();
+ _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr();
+ _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr();
+ _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr();
+ _vm->_draw->_frontColor = _vm->_game->_script->readValExpr();
_vm->_draw->spriteOperation(DRAW_INVALIDATE);
return false;
}
bool Inter_v1::o1_setBackDelta(OpFuncParams &params) {
- _vm->_draw->_backDeltaX = _vm->_parse->parseValExpr();
- _vm->_draw->_backDeltaY = _vm->_parse->parseValExpr();
+ _vm->_draw->_backDeltaX = _vm->_game->_script->readValExpr();
+ _vm->_draw->_backDeltaY = _vm->_game->_script->readValExpr();
return false;
}
@@ -1977,9 +1499,9 @@ bool Inter_v1::o1_playSound(OpFuncParams &params) {
int16 index;
int16 endRep;
- index = _vm->_parse->parseValExpr();
- repCount = _vm->_parse->parseValExpr();
- frequency = _vm->_parse->parseValExpr();
+ index = _vm->_game->_script->readValExpr();
+ repCount = _vm->_game->_script->readValExpr();
+ frequency = _vm->_game->_script->readValExpr();
SoundDesc *sample = _vm->_sound->sampleGetBySlot(index);
@@ -2002,7 +1524,7 @@ bool Inter_v1::o1_playSound(OpFuncParams &params) {
}
if (sample->getType() == SOUND_ADL) {
- _vm->_sound->adlibLoad(sample->getData(), sample->size(), index);
+ _vm->_sound->adlibLoadADL(sample->getData(), sample->size(), index);
_vm->_sound->adlibSetRepeating(repCount - 1);
_vm->_sound->adlibPlay();
} else {
@@ -2015,7 +1537,7 @@ bool Inter_v1::o1_playSound(OpFuncParams &params) {
bool Inter_v1::o1_stopSound(OpFuncParams &params) {
_vm->_sound->adlibStop();
- _vm->_sound->blasterStop(_vm->_parse->parseValExpr());
+ _vm->_sound->blasterStop(_vm->_game->_script->readValExpr());
_soundEndTimeKey = 0;
return false;
@@ -2041,8 +1563,8 @@ bool Inter_v1::o1_playComposition(OpFuncParams &params) {
int16 dataVar;
int16 freqVal;
- dataVar = _vm->_parse->parseVarIndex();
- freqVal = _vm->_parse->parseValExpr();
+ dataVar = _vm->_game->_script->readVarIndex();
+ freqVal = _vm->_game->_script->readValExpr();
for (int i = 0; i < 50; i++)
composition[i] = (int16) VAR_OFFSET(dataVar + i * 4);
@@ -2054,8 +1576,8 @@ bool Inter_v1::o1_getFreeMem(OpFuncParams &params) {
int16 freeVar;
int16 maxFreeVar;
- freeVar = _vm->_parse->parseVarIndex();
- maxFreeVar = _vm->_parse->parseVarIndex();
+ freeVar = _vm->_game->_script->readVarIndex();
+ maxFreeVar = _vm->_game->_script->readVarIndex();
// HACK
WRITE_VAR_OFFSET(freeVar, 1000000);
@@ -2067,22 +1589,22 @@ bool Inter_v1::o1_checkData(OpFuncParams &params) {
int16 handle;
int16 varOff;
- evalExpr(0);
- varOff = _vm->_parse->parseVarIndex();
- handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr);
+ _vm->_game->_script->evalExpr(0);
+ varOff = _vm->_game->_script->readVarIndex();
+ handle = _vm->_dataIO->openData(_vm->_game->_script->getResultStr());
WRITE_VAR_OFFSET(varOff, handle);
if (handle >= 0)
_vm->_dataIO->closeData(handle);
else
- warning("File \"%s\" not found", _vm->_global->_inter_resStr);
+ warning("File \"%s\" not found", _vm->_game->_script->getResultStr());
return false;
}
bool Inter_v1::o1_prepareStr(OpFuncParams &params) {
int16 strVar;
- strVar = _vm->_parse->parseVarIndex();
+ strVar = _vm->_game->_script->readVarIndex();
_vm->_util->prepareStr(GET_VARO_FSTR(strVar));
return false;
}
@@ -2091,12 +1613,12 @@ bool Inter_v1::o1_insertStr(OpFuncParams &params) {
int16 pos;
int16 strVar;
- strVar = _vm->_parse->parseVarIndex();
- evalExpr(0);
- pos = _vm->_parse->parseValExpr();
+ strVar = _vm->_game->_script->readVarIndex();
+ _vm->_game->_script->evalExpr(0);
+ pos = _vm->_game->_script->readValExpr();
char *str = GET_VARO_FSTR(strVar);
- _vm->_util->insertStr(_vm->_global->_inter_resStr, str, pos);
+ _vm->_util->insertStr(_vm->_game->_script->getResultStr(), str, pos);
return false;
}
@@ -2105,9 +1627,9 @@ bool Inter_v1::o1_cutStr(OpFuncParams &params) {
int16 pos;
int16 size;
- strVar = _vm->_parse->parseVarIndex();
- pos = _vm->_parse->parseValExpr();
- size = _vm->_parse->parseValExpr();
+ strVar = _vm->_game->_script->readVarIndex();
+ pos = _vm->_game->_script->readValExpr();
+ size = _vm->_game->_script->readValExpr();
_vm->_util->cutFromStr(GET_VARO_STR(strVar), pos, size);
return false;
}
@@ -2117,11 +1639,11 @@ bool Inter_v1::o1_strstr(OpFuncParams &params) {
int16 resVar;
int16 pos;
- strVar = _vm->_parse->parseVarIndex();
- evalExpr(0);
- resVar = _vm->_parse->parseVarIndex();
+ strVar = _vm->_game->_script->readVarIndex();
+ _vm->_game->_script->evalExpr(0);
+ resVar = _vm->_game->_script->readVarIndex();
- char *res = strstr(GET_VARO_STR(strVar), _vm->_global->_inter_resStr);
+ char *res = strstr(GET_VARO_STR(strVar), _vm->_game->_script->getResultStr());
pos = res ? (res - (GET_VARO_STR(strVar))) : -1;
WRITE_VAR_OFFSET(resVar, pos);
return false;
@@ -2131,17 +1653,17 @@ bool Inter_v1::o1_istrlen(OpFuncParams &params) {
int16 len;
int16 strVar;
- strVar = _vm->_parse->parseVarIndex();
+ strVar = _vm->_game->_script->readVarIndex();
len = strlen(GET_VARO_STR(strVar));
- strVar = _vm->_parse->parseVarIndex();
+ strVar = _vm->_game->_script->readVarIndex();
WRITE_VAR_OFFSET(strVar, len);
return false;
}
bool Inter_v1::o1_setMousePos(OpFuncParams &params) {
- _vm->_global->_inter_mouseX = _vm->_parse->parseValExpr();
- _vm->_global->_inter_mouseY = _vm->_parse->parseValExpr();
+ _vm->_global->_inter_mouseX = _vm->_game->_script->readValExpr();
+ _vm->_global->_inter_mouseY = _vm->_game->_script->readValExpr();
_vm->_global->_inter_mouseX -= _vm->_video->_scrollOffsetX;
_vm->_global->_inter_mouseY -= _vm->_video->_scrollOffsetY;
if (_vm->_global->_useMouse != 0)
@@ -2151,7 +1673,7 @@ bool Inter_v1::o1_setMousePos(OpFuncParams &params) {
}
bool Inter_v1::o1_setFrameRate(OpFuncParams &params) {
- _vm->_util->setFrameRate(_vm->_parse->parseValExpr());
+ _vm->_util->setFrameRate(_vm->_game->_script->readValExpr());
return false;
}
@@ -2177,27 +1699,23 @@ bool Inter_v1::o1_blitCursor(OpFuncParams &params) {
bool Inter_v1::o1_loadFont(OpFuncParams &params) {
int16 index;
- evalExpr(0);
- index = load16();
+ _vm->_game->_script->evalExpr(0);
+ index = _vm->_game->_script->readInt16();
delete _vm->_draw->_fonts[index];
_vm->_draw->animateCursor(4);
- if (_vm->_game->_extHandle >= 0)
- _vm->_dataIO->closeData(_vm->_game->_extHandle);
_vm->_draw->_fonts[index] =
- _vm->_util->loadFont(_vm->_global->_inter_resStr);
+ _vm->_util->loadFont(_vm->_game->_script->getResultStr());
- if (_vm->_game->_extHandle >= 0)
- _vm->_game->_extHandle = _vm->_dataIO->openData(_vm->_game->_curExtFile);
return false;
}
bool Inter_v1::o1_freeFont(OpFuncParams &params) {
int16 index;
- index = load16();
+ index = _vm->_game->_script->readInt16();
delete _vm->_draw->_fonts[index];
_vm->_draw->_fonts[index] = 0;
return false;
@@ -2210,17 +1728,14 @@ bool Inter_v1::o1_readData(OpFuncParams &params) {
int16 offset;
int16 handle;
- evalExpr(0);
- dataVar = _vm->_parse->parseVarIndex();
- size = _vm->_parse->parseValExpr();
- offset = _vm->_parse->parseValExpr();
+ _vm->_game->_script->evalExpr(0);
+ dataVar = _vm->_game->_script->readVarIndex();
+ size = _vm->_game->_script->readValExpr();
+ offset = _vm->_game->_script->readValExpr();
retSize = 0;
- if (_vm->_game->_extHandle >= 0)
- _vm->_dataIO->closeData(_vm->_game->_extHandle);
-
WRITE_VAR(1, 1);
- handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr);
+ handle = _vm->_dataIO->openData(_vm->_game->_script->getResultStr());
if (handle >= 0) {
DataStream *stream = _vm->_dataIO->openAsStream(handle, true);
@@ -2241,8 +1756,6 @@ bool Inter_v1::o1_readData(OpFuncParams &params) {
delete stream;
}
- if (_vm->_game->_extHandle >= 0)
- _vm->_game->_extHandle = _vm->_dataIO->openData(_vm->_game->_curExtFile);
return false;
}
@@ -2255,22 +1768,22 @@ bool Inter_v1::o1_writeData(OpFuncParams &params) {
// (Gobliiins 1 doesn't use save file), so we just warn should it be
// called regardless.
- evalExpr(0);
- dataVar = _vm->_parse->parseVarIndex();
- size = _vm->_parse->parseValExpr();
- offset = _vm->_parse->parseValExpr();
+ _vm->_game->_script->evalExpr(0);
+ dataVar = _vm->_game->_script->readVarIndex();
+ size = _vm->_game->_script->readValExpr();
+ offset = _vm->_game->_script->readValExpr();
- warning("Attempted to write to file \"%s\"", _vm->_global->_inter_resStr);
+ warning("Attempted to write to file \"%s\"", _vm->_game->_script->getResultStr());
WRITE_VAR(1, 0);
return false;
}
bool Inter_v1::o1_manageDataFile(OpFuncParams &params) {
- evalExpr(0);
+ _vm->_game->_script->evalExpr(0);
- if (_vm->_global->_inter_resStr[0] != 0)
- _vm->_dataIO->openDataFile(_vm->_global->_inter_resStr);
+ if (_vm->_game->_script->getResultStr()[0] != 0)
+ _vm->_dataIO->openDataFile(_vm->_game->_script->getResultStr());
else
_vm->_dataIO->closeDataFile();
return false;
@@ -2434,16 +1947,16 @@ void Inter_v1::o1_getMaxTick(OpGobParams &params) {
}
void Inter_v1::o1_manipulateMap(OpGobParams &params) {
- int16 xPos = load16();
- int16 yPos = load16();
- int16 item = load16();
+ int16 xPos = _vm->_game->_script->readInt16();
+ int16 yPos = _vm->_game->_script->readInt16();
+ int16 item = _vm->_game->_script->readInt16();
manipulateMap(xPos, yPos, item);
}
void Inter_v1::o1_getItem(OpGobParams &params) {
- int16 xPos = load16();
- int16 yPos = load16();
+ int16 xPos = _vm->_game->_script->readInt16();
+ int16 yPos = _vm->_game->_script->readInt16();
if ((_vm->_map->getItem(xPos, yPos) & 0xFF00) != 0)
params.retVarPtr = (uint32) ((_vm->_map->getItem(xPos, yPos) & 0xFF00) >> 8);
@@ -2452,9 +1965,9 @@ void Inter_v1::o1_getItem(OpGobParams &params) {
}
void Inter_v1::o1_manipulateMapIndirect(OpGobParams &params) {
- int16 xPos = load16();
- int16 yPos = load16();
- int16 item = load16();
+ int16 xPos = _vm->_game->_script->readInt16();
+ int16 yPos = _vm->_game->_script->readInt16();
+ int16 item = _vm->_game->_script->readInt16();
xPos = VAR(xPos);
yPos = VAR(yPos);
@@ -2464,8 +1977,8 @@ void Inter_v1::o1_manipulateMapIndirect(OpGobParams &params) {
}
void Inter_v1::o1_getItemIndirect(OpGobParams &params) {
- int16 xPos = load16();
- int16 yPos = load16();
+ int16 xPos = _vm->_game->_script->readInt16();
+ int16 yPos = _vm->_game->_script->readInt16();
xPos = VAR(xPos);
yPos = VAR(yPos);
@@ -2477,17 +1990,17 @@ void Inter_v1::o1_getItemIndirect(OpGobParams &params) {
}
void Inter_v1::o1_setPassMap(OpGobParams &params) {
- int16 xPos = load16();
- int16 yPos = load16();
- int16 val = load16();
+ int16 xPos = _vm->_game->_script->readInt16();
+ int16 yPos = _vm->_game->_script->readInt16();
+ int16 val = _vm->_game->_script->readInt16();
_vm->_map->setPass(xPos, yPos, val);
}
void Inter_v1::o1_setGoblinPosH(OpGobParams &params) {
int16 layer;
- int16 item = load16();
- int16 xPos = load16();
- int16 yPos = load16();
+ int16 item = _vm->_game->_script->readInt16();
+ int16 xPos = _vm->_game->_script->readInt16();
+ int16 yPos = _vm->_game->_script->readInt16();
_vm->_goblin->_gobPositions[item].x = xPos * 2;
_vm->_goblin->_gobPositions[item].y = yPos * 2;
@@ -2522,20 +2035,20 @@ void Inter_v1::o1_setGoblinPosH(OpGobParams &params) {
}
void Inter_v1::o1_getGoblinPosXH(OpGobParams &params) {
- int16 item = load16();
+ int16 item = _vm->_game->_script->readInt16();
params.retVarPtr = (uint32) (_vm->_goblin->_gobPositions[item].x >> 1);
}
void Inter_v1::o1_getGoblinPosYH(OpGobParams &params) {
- int16 item = load16();
+ int16 item = _vm->_game->_script->readInt16();
params.retVarPtr = (uint32) (_vm->_goblin->_gobPositions[item].y >> 1);
}
void Inter_v1::o1_setGoblinMultState(OpGobParams &params) {
int16 layer;
- int16 item = load16();
- int16 xPos = load16();
- int16 yPos = load16();
+ int16 item = _vm->_game->_script->readInt16();
+ int16 xPos = _vm->_game->_script->readInt16();
+ int16 yPos = _vm->_game->_script->readInt16();
params.objDesc = _vm->_goblin->_goblins[item];
if (yPos == 0) {
@@ -2594,18 +2107,18 @@ void Inter_v1::o1_setGoblinMultState(OpGobParams &params) {
}
void Inter_v1::o1_setGoblinUnk14(OpGobParams &params) {
- int16 item = load16();
- int16 val = load16();
+ int16 item = _vm->_game->_script->readInt16();
+ int16 val = _vm->_game->_script->readInt16();
params.objDesc = _vm->_goblin->_objects[item];
params.objDesc->unk14 = val;
}
void Inter_v1::o1_setItemIdInPocket(OpGobParams &params) {
- _vm->_goblin->_itemIdInPocket = load16();
+ _vm->_goblin->_itemIdInPocket = _vm->_game->_script->readInt16();
}
void Inter_v1::o1_setItemIndInPocket(OpGobParams &params) {
- _vm->_goblin->_itemIndInPocket = load16();
+ _vm->_goblin->_itemIndInPocket = _vm->_game->_script->readInt16();
}
void Inter_v1::o1_getItemIdInPocket(OpGobParams &params) {
@@ -2618,9 +2131,9 @@ void Inter_v1::o1_getItemIndInPocket(OpGobParams &params) {
void Inter_v1::o1_setGoblinPos(OpGobParams &params) {
int16 layer;
- int16 item = load16();
- int16 xPos = load16();
- int16 yPos = load16();
+ int16 item = _vm->_game->_script->readInt16();
+ int16 xPos = _vm->_game->_script->readInt16();
+ int16 yPos = _vm->_game->_script->readInt16();
_vm->_goblin->_gobPositions[item].x = xPos;
_vm->_goblin->_gobPositions[item].y = yPos;
@@ -2655,8 +2168,8 @@ void Inter_v1::o1_setGoblinPos(OpGobParams &params) {
void Inter_v1::o1_setGoblinState(OpGobParams &params) {
int16 layer;
- int16 item = load16();
- int16 state = load16();
+ int16 item = _vm->_game->_script->readInt16();
+ int16 state = _vm->_game->_script->readInt16();
params.objDesc = _vm->_goblin->_goblins[item];
params.objDesc->nextState = state;
@@ -2680,8 +2193,8 @@ void Inter_v1::o1_setGoblinState(OpGobParams &params) {
void Inter_v1::o1_setGoblinStateRedraw(OpGobParams &params) {
int16 layer;
- int16 item = load16();
- int16 state = load16();
+ int16 item = _vm->_game->_script->readInt16();
+ int16 state = _vm->_game->_script->readInt16();
params.objDesc = _vm->_goblin->_objects[item];
params.objDesc->nextState = state;
@@ -2708,7 +2221,7 @@ void Inter_v1::o1_setGoblinStateRedraw(OpGobParams &params) {
}
void Inter_v1::o1_decRelaxTime(OpGobParams &params) {
- params.extraData = load16();
+ params.extraData = _vm->_game->_script->readInt16();
params.objDesc = _vm->_goblin->_objects[params.extraData];
params.objDesc->relaxTime--;
@@ -2722,12 +2235,12 @@ void Inter_v1::o1_decRelaxTime(OpGobParams &params) {
}
void Inter_v1::o1_getGoblinPosX(OpGobParams &params) {
- int16 item = load16();
+ int16 item = _vm->_game->_script->readInt16();
params.retVarPtr = (uint32) _vm->_goblin->_gobPositions[item].x;
}
void Inter_v1::o1_getGoblinPosY(OpGobParams &params) {
- int16 item = load16();
+ int16 item = _vm->_game->_script->readInt16();
params.retVarPtr = (uint32) _vm->_goblin->_gobPositions[item].y;
}
@@ -2736,18 +2249,18 @@ void Inter_v1::o1_clearPathExistence(OpGobParams &params) {
}
void Inter_v1::o1_setGoblinVisible(OpGobParams &params) {
- params.extraData = load16();
+ params.extraData = _vm->_game->_script->readInt16();
_vm->_goblin->_goblins[params.extraData]->visible = 1;
}
void Inter_v1::o1_setGoblinInvisible(OpGobParams &params) {
- params.extraData = load16();
+ params.extraData = _vm->_game->_script->readInt16();
_vm->_goblin->_goblins[params.extraData]->visible = 0;
}
void Inter_v1::o1_getObjectIntersect(OpGobParams &params) {
- params.extraData = load16();
- int16 item = load16();
+ params.extraData = _vm->_game->_script->readInt16();
+ int16 item = _vm->_game->_script->readInt16();
params.objDesc = _vm->_goblin->_objects[params.extraData];
if (_vm->_goblin->objIntersected(params.objDesc,
@@ -2758,8 +2271,8 @@ void Inter_v1::o1_getObjectIntersect(OpGobParams &params) {
}
void Inter_v1::o1_getGoblinIntersect(OpGobParams &params) {
- params.extraData = load16();
- int16 item = load16();
+ params.extraData = _vm->_game->_script->readInt16();
+ int16 item = _vm->_game->_script->readInt16();
params.objDesc = _vm->_goblin->_goblins[params.extraData];
if (_vm->_goblin->objIntersected(params.objDesc,
@@ -2770,10 +2283,10 @@ void Inter_v1::o1_getGoblinIntersect(OpGobParams &params) {
}
void Inter_v1::o1_setItemPos(OpGobParams &params) {
- int16 item = load16();
- int16 xPos = load16();
- int16 yPos = load16();
- int16 val = load16();
+ int16 item = _vm->_game->_script->readInt16();
+ int16 xPos = _vm->_game->_script->readInt16();
+ int16 yPos = _vm->_game->_script->readInt16();
+ int16 val = _vm->_game->_script->readInt16();
_vm->_map->_itemPoses[item].x = xPos;
_vm->_map->_itemPoses[item].y = yPos;
@@ -2781,12 +2294,9 @@ void Inter_v1::o1_setItemPos(OpGobParams &params) {
}
void Inter_v1::o1_loadObjects(OpGobParams &params) {
- params.extraData = load16();
- if (_vm->_game->_extHandle >= 0)
- _vm->_dataIO->closeData(_vm->_game->_extHandle);
+ params.extraData = _vm->_game->_script->readInt16();
_vm->_goblin->loadObjects((char *) VAR_ADDRESS(params.extraData));
- _vm->_game->_extHandle = _vm->_dataIO->openData(_vm->_game->_curExtFile);
}
void Inter_v1::o1_freeObjects(OpGobParams &params) {
@@ -2811,8 +2321,8 @@ void Inter_v1::o1_loadMap(OpGobParams &params) {
void Inter_v1::o1_moveGoblin(OpGobParams &params) {
int16 item;
- params.extraData = load16();
- int16 xPos = load16();
+ params.extraData = _vm->_game->_script->readInt16();
+ int16 xPos = _vm->_game->_script->readInt16();
if ((uint16) VAR(xPos) == 0) {
item =
@@ -2837,9 +2347,9 @@ void Inter_v1::o1_loadGoblin(OpGobParams &params) {
}
void Inter_v1::o1_writeTreatItem(OpGobParams &params) {
- params.extraData = load16();
- int16 cmd = load16();
- int16 xPos = load16();
+ params.extraData = _vm->_game->_script->readInt16();
+ int16 cmd = _vm->_game->_script->readInt16();
+ int16 xPos = _vm->_game->_script->readInt16();
if ((uint16) VAR(xPos) == 0) {
WRITE_VAR(cmd, _vm->_goblin->treatItem((uint16) VAR(params.extraData)));
@@ -2855,7 +2365,7 @@ void Inter_v1::o1_moveGoblin0(OpGobParams &params) {
}
void Inter_v1::o1_setGoblinTarget(OpGobParams &params) {
- params.extraData = load16();
+ params.extraData = _vm->_game->_script->readInt16();
if (VAR(params.extraData) != 0)
_vm->_goblin->_goesAtTarget = 1;
else
@@ -2863,11 +2373,11 @@ void Inter_v1::o1_setGoblinTarget(OpGobParams &params) {
}
void Inter_v1::o1_setGoblinObjectsPos(OpGobParams &params) {
- params.extraData = load16();
+ params.extraData = _vm->_game->_script->readInt16();
params.extraData = VAR(params.extraData);
_vm->_goblin->_objects[10]->xPos = params.extraData;
- params.extraData = load16();
+ params.extraData = _vm->_game->_script->readInt16();
params.extraData = VAR(params.extraData);
_vm->_goblin->_objects[10]->yPos = params.extraData;
}
@@ -2961,38 +2471,24 @@ void Inter_v1::o1_initGoblin(OpGobParams &params) {
}
int16 Inter_v1::loadSound(int16 slot) {
- byte *dataPtr;
- int16 id;
- uint32 dataSize;
- SoundSource source;
-
if (slot == -1)
- slot = _vm->_parse->parseValExpr();
+ slot = _vm->_game->_script->readValExpr();
- id = load16();
- if (id == -1) {
- _vm->_global->_inter_execPtr += 9;
+ uint16 id = _vm->_game->_script->readUint16();
+ if (id == 0xFFFF) {
+ _vm->_game->_script->skip(9);
return 0;
}
- if (id >= 30000) {
- source = SOUND_EXT;
-
- dataPtr = (byte *) _vm->_game->loadExtData(id, 0, 0, &dataSize);
- } else {
- int16 totSize;
-
- source = SOUND_TOT;
+ Resource *resource = _vm->_game->_resources->getResource(id);
+ if (!resource)
+ return 0;
- dataPtr = (byte *) _vm->_game->loadTotResource(id, &totSize);
- dataSize = (uint32) ((int32) totSize);
- }
+ SoundDesc *sample = _vm->_sound->sampleGetBySlot(slot);
+ if (!sample)
+ return 0;
- if (dataPtr) {
- SoundDesc *sample = _vm->_sound->sampleGetBySlot(slot);
- if (sample)
- sample->load(SOUND_SND, source, dataPtr, dataSize);
- }
+ sample->load(SOUND_SND, resource);
return 0;
}
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index 3107fcf9bc..82822330b1 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -36,10 +36,12 @@
#include "gob/dataio.h"
#include "gob/draw.h"
#include "gob/game.h"
+#include "gob/expression.h"
+#include "gob/script.h"
+#include "gob/resources.h"
#include "gob/goblin.h"
#include "gob/map.h"
#include "gob/mult.h"
-#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/video.h"
#include "gob/save/saveload.h"
@@ -48,673 +50,126 @@
namespace Gob {
-#define OPCODE(x) _OPCODE(Inter_v2, x)
-
-const int Inter_v2::_goblinFuncLookUp[][2] = {
- {0, 0},
- {1, 1},
- {2, 2},
- {4, 3},
- {5, 4},
- {6, 5},
- {7, 6},
- {8, 7},
- {9, 8},
- {10, 9},
- {12, 10},
- {13, 11},
- {14, 12},
- {15, 13},
- {16, 14},
- {21, 15},
- {22, 16},
- {23, 17},
- {24, 18},
- {25, 19},
- {26, 20},
- {27, 21},
- {28, 22},
- {29, 23},
- {30, 24},
- {32, 25},
- {33, 26},
- {34, 27},
- {35, 28},
- {36, 29},
- {37, 30},
- {40, 31},
- {41, 32},
- {42, 33},
- {43, 34},
- {44, 35},
- {50, 36},
- {52, 37},
- {53, 38},
- {100, 39},
- {500, 40},
- {501, 41}
-};
+#define OPCODEVER Inter_v2
+#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x)
+#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x)
+#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x)
Inter_v2::Inter_v2(GobEngine *vm) : Inter_v1(vm) {
- setupOpcodes();
}
-void Inter_v2::setupOpcodes() {
- static const OpcodeDrawEntryV2 opcodesDraw[256] = {
- /* 00 */
- OPCODE(o1_loadMult),
- OPCODE(o2_playMult),
- OPCODE(o2_freeMultKeys),
- {0, ""},
- /* 04 */
- {0, ""},
- {0, ""},
- {0, ""},
- OPCODE(o1_initCursor),
- /* 08 */
- OPCODE(o1_initCursorAnim),
- OPCODE(o1_clearCursorAnim),
- OPCODE(o2_setRenderFlags),
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- OPCODE(o1_loadAnim),
- OPCODE(o1_freeAnim),
- OPCODE(o1_updateAnim),
- OPCODE(o2_multSub),
- /* 14 */
- OPCODE(o2_initMult),
- OPCODE(o1_freeMult),
- OPCODE(o1_animate),
- OPCODE(o2_loadMultObject),
- /* 18 */
- OPCODE(o1_getAnimLayerInfo),
- OPCODE(o1_getObjAnimSize),
- OPCODE(o1_loadStatic),
- OPCODE(o1_freeStatic),
- /* 1C */
- OPCODE(o2_renderStatic),
- OPCODE(o2_loadCurLayer),
- {0, ""},
- {0, ""},
- /* 20 */
- OPCODE(o2_playCDTrack),
- OPCODE(o2_waitCDTrackEnd),
- OPCODE(o2_stopCD),
- OPCODE(o2_readLIC),
- /* 24 */
- OPCODE(o2_freeLIC),
- OPCODE(o2_getCDTrackPos),
- {0, ""},
- {0, ""},
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- OPCODE(o2_loadFontToSprite),
- OPCODE(o1_freeFontToSprite),
- {0, ""},
- {0, ""},
- /* 34 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 38 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 3C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 40 */
- OPCODE(o2_totSub),
- OPCODE(o2_switchTotSub),
- OPCODE(o2_pushVars),
- OPCODE(o2_popVars),
- /* 44 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 48 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 4C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 50 */
- OPCODE(o2_loadMapObjects),
- OPCODE(o2_freeGoblins),
- OPCODE(o2_moveGoblin),
- OPCODE(o2_writeGoblinPos),
- /* 54 */
- OPCODE(o2_stopGoblin),
- OPCODE(o2_setGoblinState),
- OPCODE(o2_placeGoblin),
- {0, ""},
- /* 58 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 5C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 60 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 64 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 68 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 6C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 70 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 74 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 78 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 7C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 80 */
- OPCODE(o2_initScreen),
- OPCODE(o2_scroll),
- OPCODE(o2_setScrollOffset),
- OPCODE(o2_playImd),
- /* 84 */
- OPCODE(o2_getImdInfo),
- OPCODE(o2_openItk),
- OPCODE(o2_closeItk),
- OPCODE(o2_setImdFrontSurf),
- /* 88 */
- OPCODE(o2_resetImdFrontSurf),
- {0, ""},
- {0, ""},
- {0, ""},
- /* 8C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 90 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 94 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 98 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 9C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* AC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* BC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* CC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* DC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* EC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* FC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""}
- };
-
- static const OpcodeFuncEntryV2 opcodesFunc[80] = {
- /* 00 */
- OPCODE(o1_callSub),
- OPCODE(o1_callSub),
- OPCODE(o1_printTotText),
- OPCODE(o1_loadCursor),
- /* 04 */
- {0, ""},
- OPCODE(o1_switch),
- OPCODE(o1_repeatUntil),
- OPCODE(o1_whileDo),
- /* 08 */
- OPCODE(o1_if),
- OPCODE(o2_assign),
- OPCODE(o1_loadSpriteToPos),
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- {0, ""},
- OPCODE(o2_printText),
- OPCODE(o1_loadTot),
- OPCODE(o1_palLoad),
- /* 14 */
- OPCODE(o1_keyFunc),
- OPCODE(o1_capturePush),
- OPCODE(o1_capturePop),
- OPCODE(o2_animPalInit),
- /* 18 */
- OPCODE(o2_addCollision),
- OPCODE(o2_freeCollision),
- {0, ""},
- {0, ""},
- /* 1C */
- {0, ""},
- {0, ""},
- OPCODE(o1_drawOperations),
- OPCODE(o1_setcmdCount),
- /* 20 */
- OPCODE(o1_return),
- OPCODE(o1_renewTimeInVars),
- OPCODE(o1_speakerOn),
- OPCODE(o1_speakerOff),
- /* 24 */
- OPCODE(o1_putPixel),
- OPCODE(o2_goblinFunc),
- OPCODE(o1_createSprite),
- OPCODE(o1_freeSprite),
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- OPCODE(o1_returnTo),
- OPCODE(o1_loadSpriteContent),
- OPCODE(o1_copySprite),
- OPCODE(o1_fillRect),
- /* 34 */
- OPCODE(o1_drawLine),
- OPCODE(o1_strToLong),
- OPCODE(o1_invalidate),
- OPCODE(o1_setBackDelta),
- /* 38 */
- OPCODE(o1_playSound),
- OPCODE(o2_stopSound),
- OPCODE(o2_loadSound),
- OPCODE(o1_freeSoundSlot),
- /* 3C */
- OPCODE(o1_waitEndPlay),
- OPCODE(o1_playComposition),
- OPCODE(o2_getFreeMem),
- OPCODE(o2_checkData),
- /* 40 */
- {0, ""},
- OPCODE(o1_prepareStr),
- OPCODE(o1_insertStr),
- OPCODE(o1_cutStr),
- /* 44 */
- OPCODE(o1_strstr),
- OPCODE(o1_istrlen),
- OPCODE(o1_setMousePos),
- OPCODE(o1_setFrameRate),
- /* 48 */
- OPCODE(o1_animatePalette),
- OPCODE(o1_animateCursor),
- OPCODE(o1_blitCursor),
- OPCODE(o1_loadFont),
- /* 4C */
- OPCODE(o1_freeFont),
- OPCODE(o2_readData),
- OPCODE(o2_writeData),
- OPCODE(o1_manageDataFile),
- };
-
- static const OpcodeGoblinEntryV2 opcodesGoblin[71] = {
- /* 00 */
- OPCODE(o2_loadInfogramesIns),
- OPCODE(o2_startInfogrames),
- OPCODE(o2_stopInfogrames),
- {0, ""},
- /* 04 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 08 */
- {0, ""},
- OPCODE(o2_playInfogrames),
- {0, ""},
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 14 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 18 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 1C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 20 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 24 */
- {0, ""},
- {0, ""},
- {0, ""},
- OPCODE(o2_handleGoblins),
- /* 28 */
- OPCODE(o2_playProtracker),
- OPCODE(o2_stopProtracker),
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 34 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 38 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 3C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 40 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 44 */
- {0, ""},
- {0, ""},
- {0, ""},
- };
-
- _opcodesDrawV2 = opcodesDraw;
- _opcodesFuncV2 = opcodesFunc;
- _opcodesGoblinV2 = opcodesGoblin;
-}
+void Inter_v2::setupOpcodesDraw() {
+ Inter_v1::setupOpcodesDraw();
-void Inter_v2::executeDrawOpcode(byte i) {
- debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)",
- i, i, getOpcodeDrawDesc(i));
+ OPCODEDRAW(0x01, o2_playMult);
+ OPCODEDRAW(0x02, o2_freeMultKeys);
- OpcodeDrawProcV2 op = _opcodesDrawV2[i].proc;
+ OPCODEDRAW(0x0A, o2_setRenderFlags);
- if (op == 0)
- warning("unimplemented opcodeDraw: %d", i);
- else
- (this->*op) ();
-}
+ OPCODEDRAW(0x13, o2_multSub);
-bool Inter_v2::executeFuncOpcode(byte i, byte j, OpFuncParams &params) {
- debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)",
- i, j, i, j, getOpcodeFuncDesc(i, j));
+ OPCODEDRAW(0x14, o2_initMult);
- if ((i > 4) || (j > 15)) {
- warning("unimplemented opcodeFunc: %d.%d", i, j);
- return false;
- }
+ OPCODEDRAW(0x17, o2_loadMultObject);
- OpcodeFuncProcV2 op = _opcodesFuncV2[i*16 + j].proc;
+ OPCODEDRAW(0x1C, o2_renderStatic);
+ OPCODEDRAW(0x1D, o2_loadCurLayer);
- if (op == 0)
- warning("unimplemented opcodeFunc: %d.%d", i, j);
- else
- return (this->*op) (params);
+ OPCODEDRAW(0x20, o2_playCDTrack);
+ OPCODEDRAW(0x21, o2_waitCDTrackEnd);
+ OPCODEDRAW(0x22, o2_stopCD);
+ OPCODEDRAW(0x23, o2_readLIC);
- return false;
-}
+ OPCODEDRAW(0x24, o2_freeLIC);
+ OPCODEDRAW(0x25, o2_getCDTrackPos);
-void Inter_v2::executeGoblinOpcode(int i, OpGobParams &params) {
- debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)",
- i, i, getOpcodeGoblinDesc(i));
+ OPCODEDRAW(0x30, o2_loadFontToSprite);
- OpcodeGoblinProcV2 op = 0;
+ OPCODEDRAW(0x40, o2_totSub);
+ OPCODEDRAW(0x41, o2_switchTotSub);
+ OPCODEDRAW(0x42, o2_pushVars);
+ OPCODEDRAW(0x43, o2_popVars);
- for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
- if (_goblinFuncLookUp[j][0] == i) {
- op = _opcodesGoblinV2[_goblinFuncLookUp[j][1]].proc;
- break;
- }
+ OPCODEDRAW(0x50, o2_loadMapObjects);
+ OPCODEDRAW(0x51, o2_freeGoblins);
+ OPCODEDRAW(0x52, o2_moveGoblin);
+ OPCODEDRAW(0x53, o2_writeGoblinPos);
- if (op == 0) {
- int16 val;
+ OPCODEDRAW(0x54, o2_stopGoblin);
+ OPCODEDRAW(0x55, o2_setGoblinState);
+ OPCODEDRAW(0x56, o2_placeGoblin);
- _vm->_global->_inter_execPtr -= 2;
- val = load16();
- _vm->_global->_inter_execPtr += val << 1;
- } else
- (this->*op) (params);
-}
+ OPCODEDRAW(0x80, o2_initScreen);
+ OPCODEDRAW(0x81, o2_scroll);
+ OPCODEDRAW(0x82, o2_setScrollOffset);
+ OPCODEDRAW(0x83, o2_playImd);
+
+ OPCODEDRAW(0x84, o2_getImdInfo);
+ OPCODEDRAW(0x85, o2_openItk);
+ OPCODEDRAW(0x86, o2_closeItk);
+ OPCODEDRAW(0x87, o2_setImdFrontSurf);
-const char *Inter_v2::getOpcodeDrawDesc(byte i) {
- return _opcodesDrawV2[i].desc;
+ OPCODEDRAW(0x88, o2_resetImdFrontSurf);
}
-const char *Inter_v2::getOpcodeFuncDesc(byte i, byte j) {
- if ((i > 4) || (j > 15))
- return "";
+void Inter_v2::setupOpcodesFunc() {
+ Inter_v1::setupOpcodesFunc();
+
+ OPCODEFUNC(0x09, o2_assign);
+
+ OPCODEFUNC(0x11, o2_printText);
+
+ OPCODEFUNC(0x17, o2_animPalInit);
- return _opcodesFuncV2[i*16 + j].desc;
+ OPCODEFUNC(0x18, o2_addCollision);
+ OPCODEFUNC(0x19, o2_freeCollision);
+
+ OPCODEFUNC(0x25, o2_goblinFunc);
+
+ OPCODEFUNC(0x39, o2_stopSound);
+ OPCODEFUNC(0x3A, o2_loadSound);
+
+ OPCODEFUNC(0x3E, o2_getFreeMem);
+ OPCODEFUNC(0x3F, o2_checkData);
+
+ OPCODEFUNC(0x4D, o2_readData);
+ OPCODEFUNC(0x4E, o2_writeData);
}
-const char *Inter_v2::getOpcodeGoblinDesc(int i) {
- for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
- if (_goblinFuncLookUp[j][0] == i)
- return _opcodesGoblinV2[_goblinFuncLookUp[j][1]].desc;
- return "";
+void Inter_v2::setupOpcodesGob() {
+ OPCODEGOB( 0, o2_loadInfogramesIns);
+ OPCODEGOB( 1, o2_startInfogrames);
+ OPCODEGOB( 2, o2_stopInfogrames);
+
+ OPCODEGOB( 10, o2_playInfogrames);
+
+ OPCODEGOB(100, o2_handleGoblins);
+
+ OPCODEGOB(500, o2_playProtracker);
+ OPCODEGOB(501, o2_stopProtracker);
}
-void Inter_v2::checkSwitchTable(byte **ppExec) {
- byte cmd;
+void Inter_v2::checkSwitchTable(uint32 &offset) {
+ byte type;
int16 len;
int32 value;
bool found;
found = false;
- *ppExec = 0;
+ offset = 0;
- cmd = *_vm->_global->_inter_execPtr;
+ type = _vm->_game->_script->peekByte();
- value = _vm->_parse->parseVarIndex();
+ value = _vm->_game->_script->readVarIndex();
- switch (cmd) {
- case 16:
- case 18:
+ switch (type) {
+ case TYPE_VAR_INT8:
+ case TYPE_ARRAY_INT8:
value = (int8) READ_VARO_UINT8(value);
break;
- case 23:
- case 26:
+ case TYPE_VAR_INT32:
+ case TYPE_ARRAY_INT32:
value = READ_VARO_UINT32(value);
break;
@@ -726,78 +181,74 @@ void Inter_v2::checkSwitchTable(byte **ppExec) {
if (_terminate)
return;
- len = (int8) *_vm->_global->_inter_execPtr++;
+ len = _vm->_game->_script->readInt8();
while (len != -5) {
for (int i = 0; i < len; i++) {
- cmd = *_vm->_global->_inter_execPtr;
+ type = _vm->_game->_script->peekByte();
- switch (cmd) {
- case 19:
- _vm->_global->_inter_execPtr++;
+ switch (type) {
+ case TYPE_IMM_INT32:
+ _vm->_game->_script->skip(1);
if (!found &&
- (value ==
- (int32) (READ_LE_UINT32(_vm->_global->_inter_execPtr))))
+ (value == _vm->_game->_script->peekInt32()))
found = true;
- _vm->_global->_inter_execPtr += 5;
+ _vm->_game->_script->skip(5);
break;
- case 20:
- _vm->_global->_inter_execPtr++;
+ case TYPE_IMM_INT16:
+ _vm->_game->_script->skip(1);
if (!found &&
- (value ==
- (int16) (READ_LE_UINT16(_vm->_global->_inter_execPtr))))
+ (value == _vm->_game->_script->peekInt16()))
found = true;
- _vm->_global->_inter_execPtr += 3;
+ _vm->_game->_script->skip(3);
break;
- case 21:
- _vm->_global->_inter_execPtr++;
- if (!found && (value == (int8) *_vm->_global->_inter_execPtr))
+ case TYPE_IMM_INT8:
+ _vm->_game->_script->skip(1);
+ if (!found && (value == _vm->_game->_script->peekInt8()))
found = true;
- _vm->_global->_inter_execPtr += 2;
+ _vm->_game->_script->skip(2);
break;
default:
if (!found) {
- evalExpr(0);
- if (value == _vm->_global->_inter_resVal)
+ _vm->_game->_script->evalExpr(0);
+ if (value == _vm->_game->_script->getResultInt())
found = true;
} else
- _vm->_parse->skipExpr(99);
+ _vm->_game->_script->skipExpr(99);
break;
}
}
- if (found && !*ppExec)
- *ppExec = _vm->_global->_inter_execPtr;
+ if (found && (offset == 0))
+ offset = _vm->_game->_script->pos();
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2;
- len = (int8) *_vm->_global->_inter_execPtr++;
+ _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2);
+ len = _vm->_game->_script->readInt8();
}
- if ((*_vm->_global->_inter_execPtr >> 4) != 4)
+ if ((_vm->_game->_script->peekByte() >> 4) != 4)
return;
- _vm->_global->_inter_execPtr++;
- if (!*ppExec)
- *ppExec = _vm->_global->_inter_execPtr;
+ _vm->_game->_script->skip(1);
+ if (offset == 0)
+ offset = _vm->_game->_script->pos();
- _vm->_global->_inter_execPtr +=
- READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2;
+ _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2);
}
void Inter_v2::o2_playMult() {
int16 checkEscape;
- checkEscape = load16();
+ checkEscape = _vm->_game->_script->readInt16();
_vm->_mult->setMultData(checkEscape >> 1);
_vm->_mult->playMult(VAR(57), -1, checkEscape & 0x1, 0);
}
void Inter_v2::o2_freeMultKeys() {
- uint16 index = load16();
+ uint16 index = _vm->_game->_script->readUint16();
if (!_vm->_mult->hasMultData(index))
return;
@@ -810,7 +261,7 @@ void Inter_v2::o2_freeMultKeys() {
void Inter_v2::o2_setRenderFlags() {
int16 expr;
- expr = _vm->_parse->parseValExpr();
+ expr = _vm->_game->_script->readValExpr();
if (expr & 0x8000) {
_vm->_draw->_renderFlags |= expr & 0x3FFF;
@@ -823,7 +274,7 @@ void Inter_v2::o2_setRenderFlags() {
}
void Inter_v2::o2_multSub() {
- _vm->_mult->multSub(_vm->_parse->parseValExpr());
+ _vm->_mult->multSub(_vm->_game->_script->readValExpr());
}
void Inter_v2::o2_initMult() {
@@ -838,14 +289,14 @@ void Inter_v2::o2_initMult() {
oldAnimHeight = _vm->_mult->_animHeight;
oldObjCount = _vm->_mult->_objCount;
- _vm->_mult->_animLeft = load16();
- _vm->_mult->_animTop = load16();
- _vm->_mult->_animWidth = load16();
- _vm->_mult->_animHeight = load16();
- _vm->_mult->_objCount = load16();
- posXVar = _vm->_parse->parseVarIndex();
- posYVar = _vm->_parse->parseVarIndex();
- animDataVar = _vm->_parse->parseVarIndex();
+ _vm->_mult->_animLeft = _vm->_game->_script->readInt16();
+ _vm->_mult->_animTop = _vm->_game->_script->readInt16();
+ _vm->_mult->_animWidth = _vm->_game->_script->readInt16();
+ _vm->_mult->_animHeight = _vm->_game->_script->readInt16();
+ _vm->_mult->_objCount = _vm->_game->_script->readInt16();
+ posXVar = _vm->_game->_script->readVarIndex();
+ posYVar = _vm->_game->_script->readVarIndex();
+ animDataVar = _vm->_game->_script->readVarIndex();
if (_vm->_mult->_objects && (oldObjCount != _vm->_mult->_objCount)) {
warning("Initializing new objects without having "
@@ -947,20 +398,20 @@ void Inter_v2::o2_loadMultObject() {
int16 layer;
byte *multData;
- objIndex = _vm->_parse->parseValExpr();
- val = _vm->_parse->parseValExpr();
+ objIndex = _vm->_game->_script->readValExpr();
+ val = _vm->_game->_script->readValExpr();
*_vm->_mult->_objects[objIndex].pPosX = val;
- val = _vm->_parse->parseValExpr();
+ val = _vm->_game->_script->readValExpr();
*_vm->_mult->_objects[objIndex].pPosY = val;
debugC(4, kDebugGameFlow, "Loading mult object %d", objIndex);
multData = (byte *) _vm->_mult->_objects[objIndex].pAnimData;
for (int i = 0; i < 11; i++) {
- if (*_vm->_global->_inter_execPtr != 99)
- multData[i] = _vm->_parse->parseValExpr();
+ if (_vm->_game->_script->peekByte() != 99)
+ multData[i] = _vm->_game->_script->readValExpr();
else
- _vm->_global->_inter_execPtr++;
+ _vm->_game->_script->skip(1);
}
Mult::Mult_Object &obj = _vm->_mult->_objects[objIndex];
@@ -1043,22 +494,22 @@ void Inter_v2::o2_renderStatic() {
int16 layer;
int16 index;
- index = _vm->_parse->parseValExpr();
- layer = _vm->_parse->parseValExpr();
+ index = _vm->_game->_script->readValExpr();
+ layer = _vm->_game->_script->readValExpr();
_vm->_scenery->renderStatic(index, layer);
}
void Inter_v2::o2_loadCurLayer() {
- _vm->_scenery->_curStatic = _vm->_parse->parseValExpr();
- _vm->_scenery->_curStaticLayer = _vm->_parse->parseValExpr();
+ _vm->_scenery->_curStatic = _vm->_game->_script->readValExpr();
+ _vm->_scenery->_curStaticLayer = _vm->_game->_script->readValExpr();
}
void Inter_v2::o2_playCDTrack() {
if (!(_vm->_draw->_renderFlags & RENDERFLAG_NOBLITINVALIDATED))
_vm->_draw->blitInvalidated();
- evalExpr(0);
- _vm->_sound->cdPlay(_vm->_global->_inter_resStr);
+ _vm->_game->_script->evalExpr(0);
+ _vm->_sound->cdPlay(_vm->_game->_script->getResultStr());
}
void Inter_v2::o2_waitCDTrackEnd() {
@@ -1075,8 +526,8 @@ void Inter_v2::o2_stopCD() {
void Inter_v2::o2_readLIC() {
char path[40];
- evalExpr(0);
- strncpy0(path, _vm->_global->_inter_resStr, 35);
+ _vm->_game->_script->evalExpr(0);
+ strncpy0(path, _vm->_game->_script->getResultStr(), 35);
strcat(path, ".LIC");
_vm->_sound->cdLoadLIC(path);
@@ -1092,24 +543,24 @@ void Inter_v2::o2_getCDTrackPos() {
_vm->_util->longDelay(1);
- varPos = _vm->_parse->parseVarIndex();
- varName = _vm->_parse->parseVarIndex();
+ varPos = _vm->_game->_script->readVarIndex();
+ varName = _vm->_game->_script->readVarIndex();
WRITE_VAR_OFFSET(varPos, _vm->_sound->cdGetTrackPos(GET_VARO_STR(varName)));
WRITE_VARO_STR(varName, _vm->_sound->cdGetCurrentTrack());
}
void Inter_v2::o2_loadFontToSprite() {
- int16 i = load16();
-
- _vm->_draw->_fontToSprite[i].sprite = *_vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += 2;
- _vm->_draw->_fontToSprite[i].base = *_vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += 2;
- _vm->_draw->_fontToSprite[i].width = *_vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += 2;
- _vm->_draw->_fontToSprite[i].height = *_vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += 2;
+ int16 i = _vm->_game->_script->readInt16();
+
+ _vm->_draw->_fontToSprite[i].sprite = _vm->_game->_script->readByte();
+ _vm->_game->_script->skip(1);
+ _vm->_draw->_fontToSprite[i].base = _vm->_game->_script->readByte();
+ _vm->_game->_script->skip(1);
+ _vm->_draw->_fontToSprite[i].width = _vm->_game->_script->readByte();
+ _vm->_game->_script->skip(1);
+ _vm->_draw->_fontToSprite[i].height = _vm->_game->_script->readByte();
+ _vm->_game->_script->skip(1);
}
void Inter_v2::o2_totSub() {
@@ -1118,16 +569,16 @@ void Inter_v2::o2_totSub() {
int flags;
int i;
- length = *_vm->_global->_inter_execPtr++;
+ length = _vm->_game->_script->readByte();
if ((length & 0x7F) > 13)
error("Length in o2_totSub is greater than 13 (%d)", length);
if (length & 0x80) {
- evalExpr(0);
- strcpy(totFile, _vm->_global->_inter_resStr);
+ _vm->_game->_script->evalExpr(0);
+ strcpy(totFile, _vm->_game->_script->getResultStr());
} else {
for (i = 0; i < length; i++)
- totFile[i] = (char) *_vm->_global->_inter_execPtr++;
+ totFile[i] = _vm->_game->_script->readChar();
totFile[i] = 0;
}
@@ -1135,7 +586,7 @@ void Inter_v2::o2_totSub() {
if (!scumm_stricmp(totFile, "edit"))
_vm->_util->forceMouseUp();
- flags = *_vm->_global->_inter_execPtr++;
+ flags = _vm->_game->_script->readByte();
_vm->_game->totSub(flags, totFile);
}
@@ -1143,8 +594,8 @@ void Inter_v2::o2_switchTotSub() {
int16 index;
int16 skipPlay;
- index = load16();
- skipPlay = load16();
+ index = _vm->_game->_script->readInt16();
+ skipPlay = _vm->_game->_script->readInt16();
_vm->_game->switchTotSub(index, skipPlay);
}
@@ -1153,13 +604,13 @@ void Inter_v2::o2_pushVars() {
byte count;
int16 varOff;
- count = *_vm->_global->_inter_execPtr++;
+ count = _vm->_game->_script->readByte();
for (int i = 0; i < count; i++, _varStackPos++) {
- if ((*_vm->_global->_inter_execPtr == 25) ||
- (*_vm->_global->_inter_execPtr == 28)) {
+ if ((_vm->_game->_script->peekByte() == 25) ||
+ (_vm->_game->_script->peekByte() == 28)) {
- varOff = _vm->_parse->parseVarIndex();
- _vm->_global->_inter_execPtr++;
+ varOff = _vm->_game->_script->readVarIndex();
+ _vm->_game->_script->skip(1);
_variables->copyTo(varOff, _varStack + _varStackPos, _vm->_global->_inter_animDataSize * 4);
@@ -1167,10 +618,12 @@ void Inter_v2::o2_pushVars() {
_varStack[_varStackPos] = _vm->_global->_inter_animDataSize * 4;
} else {
- if (evalExpr(&varOff) != 20)
- _vm->_global->_inter_resVal = 0;
+ int32 n = _vm->_game->_script->getResultInt();
+
+ if (_vm->_game->_script->evalExpr(&varOff) != 20)
+ n = 0;
- memcpy(_varStack + _varStackPos, &_vm->_global->_inter_resVal, 4);
+ memcpy(_varStack + _varStackPos, &n, 4);
_varStackPos += 4;
_varStack[_varStackPos] = 4;
}
@@ -1182,9 +635,9 @@ void Inter_v2::o2_popVars() {
int16 varOff;
int16 size;
- count = *_vm->_global->_inter_execPtr++;
+ count = _vm->_game->_script->readByte();
for (int i = 0; i < count; i++) {
- varOff = _vm->_parse->parseVarIndex();
+ varOff = _vm->_game->_script->readVarIndex();
size = _varStack[--_varStackPos];
_varStackPos -= size;
@@ -1204,9 +657,9 @@ void Inter_v2::o2_moveGoblin() {
int16 destX, destY;
int16 index;
- destX = _vm->_parse->parseValExpr();
- destY = _vm->_parse->parseValExpr();
- index = _vm->_parse->parseValExpr();
+ destX = _vm->_game->_script->readValExpr();
+ destY = _vm->_game->_script->readValExpr();
+ index = _vm->_game->_script->readValExpr();
_vm->_goblin->move(destX, destY, index);
}
@@ -1214,15 +667,15 @@ void Inter_v2::o2_writeGoblinPos() {
int16 varX, varY;
int16 index;
- varX = _vm->_parse->parseVarIndex();
- varY = _vm->_parse->parseVarIndex();
- index = _vm->_parse->parseValExpr();
+ varX = _vm->_game->_script->readVarIndex();
+ varY = _vm->_game->_script->readVarIndex();
+ index = _vm->_game->_script->readValExpr();
WRITE_VAR_OFFSET(varX, _vm->_mult->_objects[index].goblinX);
WRITE_VAR_OFFSET(varY, _vm->_mult->_objects[index].goblinY);
}
void Inter_v2::o2_stopGoblin() {
- int16 index = _vm->_parse->parseValExpr();
+ int16 index = _vm->_game->_script->readValExpr();
_vm->_mult->_objects[index].pAnimData->pathExistence = 4;
}
@@ -1236,9 +689,9 @@ void Inter_v2::o2_setGoblinState() {
int16 deltaX, deltaY;
int16 deltaWidth, deltaHeight;
- index = _vm->_parse->parseValExpr();
- state = _vm->_parse->parseValExpr();
- type = _vm->_parse->parseValExpr();
+ index = _vm->_game->_script->readValExpr();
+ state = _vm->_game->_script->readValExpr();
+ type = _vm->_game->_script->readValExpr();
Mult::Mult_Object &obj = _vm->_mult->_objects[index];
Mult::Mult_AnimData &objAnim = *(obj.pAnimData);
@@ -1334,10 +787,10 @@ void Inter_v2::o2_placeGoblin() {
int16 x, y;
int16 state;
- index = _vm->_parse->parseValExpr();
- x = _vm->_parse->parseValExpr();
- y = _vm->_parse->parseValExpr();
- state = _vm->_parse->parseValExpr();
+ index = _vm->_game->_script->readValExpr();
+ x = _vm->_game->_script->readValExpr();
+ y = _vm->_game->_script->readValExpr();
+ state = _vm->_game->_script->readValExpr();
_vm->_goblin->placeObject(0, 0, index, x, y, state);
}
@@ -1347,13 +800,13 @@ void Inter_v2::o2_initScreen() {
int16 videoMode;
int16 width, height;
- offY = load16();
+ offY = _vm->_game->_script->readInt16();
videoMode = offY & 0xFF;
offY = (offY >> 8) & 0xFF;
- width = _vm->_parse->parseValExpr();
- height = _vm->_parse->parseValExpr();
+ width = _vm->_game->_script->readValExpr();
+ height = _vm->_game->_script->readValExpr();
_vm->_video->clearScreen();
@@ -1441,16 +894,16 @@ void Inter_v2::o2_scroll() {
int16 curX;
int16 curY;
- startX = CLIP((int) _vm->_parse->parseValExpr(), 0,
+ startX = CLIP((int) _vm->_game->_script->readValExpr(), 0,
_vm->_video->_surfWidth - _vm->_width);
- startY = CLIP((int) _vm->_parse->parseValExpr(), 0,
+ startY = CLIP((int) _vm->_game->_script->readValExpr(), 0,
_vm->_video->_surfHeight - _vm->_height);
- endX = CLIP((int) _vm->_parse->parseValExpr(), 0,
+ endX = CLIP((int) _vm->_game->_script->readValExpr(), 0,
_vm->_video->_surfWidth - _vm->_width);
- endY = CLIP((int) _vm->_parse->parseValExpr(), 0,
+ endY = CLIP((int) _vm->_game->_script->readValExpr(), 0,
_vm->_video->_surfHeight - _vm->_height);
- stepX = _vm->_parse->parseValExpr();
- stepY = _vm->_parse->parseValExpr();
+ stepX = _vm->_game->_script->readValExpr();
+ stepY = _vm->_game->_script->readValExpr();
curX = startX;
curY = startY;
@@ -1470,8 +923,8 @@ void Inter_v2::o2_scroll() {
void Inter_v2::o2_setScrollOffset() {
int16 offsetX, offsetY;
- offsetX = _vm->_parse->parseValExpr();
- offsetY = _vm->_parse->parseValExpr();
+ offsetX = _vm->_game->_script->readValExpr();
+ offsetY = _vm->_game->_script->readValExpr();
if (offsetX == -1) {
WRITE_VAR(2, _vm->_draw->_scrollOffsetX);
@@ -1506,22 +959,22 @@ void Inter_v2::o2_playImd() {
uint16 palCmd;
bool close;
- evalExpr(0);
- _vm->_global->_inter_resStr[8] = 0;
- strncpy0(imd, _vm->_global->_inter_resStr, 127);
-
- x = _vm->_parse->parseValExpr();
- y = _vm->_parse->parseValExpr();
- startFrame = _vm->_parse->parseValExpr();
- lastFrame = _vm->_parse->parseValExpr();
- breakKey = _vm->_parse->parseValExpr();
- flags = _vm->_parse->parseValExpr();
- palStart = _vm->_parse->parseValExpr();
- palEnd = _vm->_parse->parseValExpr();
+ _vm->_game->_script->evalExpr(0);
+ _vm->_game->_script->getResultStr()[8] = 0;
+ strncpy0(imd, _vm->_game->_script->getResultStr(), 127);
+
+ x = _vm->_game->_script->readValExpr();
+ y = _vm->_game->_script->readValExpr();
+ startFrame = _vm->_game->_script->readValExpr();
+ lastFrame = _vm->_game->_script->readValExpr();
+ breakKey = _vm->_game->_script->readValExpr();
+ flags = _vm->_game->_script->readValExpr();
+ palStart = _vm->_game->_script->readValExpr();
+ palEnd = _vm->_game->_script->readValExpr();
palCmd = 1 << (flags & 0x3F);
debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, "
- "paletteCmd %d (%d - %d), flags %X", _vm->_global->_inter_resStr, x, y,
+ "paletteCmd %d (%d - %d), flags %X", _vm->_game->_script->getResultStr(), x, y,
startFrame, lastFrame, palCmd, palStart, palEnd, flags);
if ((imd[0] != 0) && !_vm->_vidPlayer->primaryOpen(imd, x, y, flags)) {
@@ -1550,28 +1003,28 @@ void Inter_v2::o2_getImdInfo() {
int16 varFrames;
int16 varWidth, varHeight;
- evalExpr(0);
- varX = _vm->_parse->parseVarIndex();
- varY = _vm->_parse->parseVarIndex();
- varFrames = _vm->_parse->parseVarIndex();
- varWidth = _vm->_parse->parseVarIndex();
- varHeight = _vm->_parse->parseVarIndex();
+ _vm->_game->_script->evalExpr(0);
+ varX = _vm->_game->_script->readVarIndex();
+ varY = _vm->_game->_script->readVarIndex();
+ varFrames = _vm->_game->_script->readVarIndex();
+ varWidth = _vm->_game->_script->readVarIndex();
+ varHeight = _vm->_game->_script->readVarIndex();
// WORKAROUND: The nut rolling animation in the administration center
// in Woodruff is called "noixroul", but the scripts think it's "noixroule".
if ((_vm->getGameType() == kGameTypeWoodruff) &&
- (!scumm_stricmp(_vm->_global->_inter_resStr, "noixroule")))
- strcpy(_vm->_global->_inter_resStr, "noixroul");
+ (!scumm_stricmp(_vm->_game->_script->getResultStr(), "noixroule")))
+ strcpy(_vm->_game->_script->getResultStr(), "noixroul");
- _vm->_vidPlayer->writeVideoInfo(_vm->_global->_inter_resStr, varX, varY,
+ _vm->_vidPlayer->writeVideoInfo(_vm->_game->_script->getResultStr(), varX, varY,
varFrames, varWidth, varHeight);
}
void Inter_v2::o2_openItk() {
char fileName[32];
- evalExpr(0);
- strncpy0(fileName, _vm->_global->_inter_resStr, 27);
+ _vm->_game->_script->evalExpr(0);
+ strncpy0(fileName, _vm->_game->_script->getResultStr(), 27);
if (!strchr(fileName, '.'))
strcat(fileName, ".ITK");
@@ -1589,49 +1042,46 @@ void Inter_v2::o2_resetImdFrontSurf() {
}
bool Inter_v2::o2_assign(OpFuncParams &params) {
- byte *savedPos;
- int16 varOff;
- int16 token;
- int16 result;
- byte loopCount;
-
- savedPos = _vm->_global->_inter_execPtr;
- varOff = _vm->_parse->parseVarIndex();
+ byte destType = _vm->_game->_script->peekByte();
+ int16 dest = _vm->_game->_script->readVarIndex();
- if (*_vm->_global->_inter_execPtr == 99) {
- _vm->_global->_inter_execPtr++;
- loopCount = *_vm->_global->_inter_execPtr++;
+ byte loopCount;
+ if (_vm->_game->_script->peekByte() == 99) {
+ _vm->_game->_script->skip(1);
+ loopCount = _vm->_game->_script->readByte();
} else
loopCount = 1;
for (int i = 0; i < loopCount; i++) {
- token = evalExpr(&result);
- switch (savedPos[0]) {
- case 16:
- case 18:
- WRITE_VARO_UINT8(varOff + i, _vm->_global->_inter_resVal);
+ int16 result;
+ int16 srcType = _vm->_game->_script->evalExpr(&result);
+
+ switch (destType) {
+ case TYPE_VAR_INT8:
+ case TYPE_ARRAY_INT8:
+ WRITE_VARO_UINT8(dest + i, _vm->_game->_script->getResultInt());
break;
- case 17:
- case 27:
- WRITE_VARO_UINT16(varOff + i * 2, _vm->_global->_inter_resVal);
+ case TYPE_VAR_INT16:
+ case TYPE_ARRAY_INT16:
+ WRITE_VARO_UINT16(dest + i * 2, _vm->_game->_script->getResultInt());
break;
- case 23:
- case 26:
- WRITE_VAR_OFFSET(varOff + i * 4, _vm->_global->_inter_resVal);
+ case TYPE_VAR_INT32:
+ case TYPE_ARRAY_INT32:
+ WRITE_VAR_OFFSET(dest + i * 4, _vm->_game->_script->getResultInt());
break;
- case 24:
- WRITE_VARO_UINT16(varOff + i * 4, _vm->_global->_inter_resVal);
+ case TYPE_VAR_INT32_AS_INT16:
+ WRITE_VARO_UINT16(dest + i * 4, _vm->_game->_script->getResultInt());
break;
- case 25:
- case 28:
- if (token == 20)
- WRITE_VARO_UINT8(varOff, result);
+ case TYPE_VAR_STR:
+ case TYPE_ARRAY_STR:
+ if (srcType == TYPE_IMM_INT16)
+ WRITE_VARO_UINT8(dest, result);
else
- WRITE_VARO_STR(varOff, _vm->_global->_inter_resStr);
+ WRITE_VARO_STR(dest, _vm->_game->_script->getResultStr());
break;
}
}
@@ -1643,12 +1093,12 @@ bool Inter_v2::o2_printText(OpFuncParams &params) {
char buf[60];
int i;
- _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr();
- _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr();
+ _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr();
+ _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr();
- _vm->_draw->_backColor = _vm->_parse->parseValExpr();
- _vm->_draw->_frontColor = _vm->_parse->parseValExpr();
- _vm->_draw->_fontIndex = _vm->_parse->parseValExpr();
+ _vm->_draw->_backColor = _vm->_game->_script->readValExpr();
+ _vm->_draw->_frontColor = _vm->_game->_script->readValExpr();
+ _vm->_draw->_fontIndex = _vm->_game->_script->readValExpr();
_vm->_draw->_destSurface = 21;
_vm->_draw->_textToPrint = buf;
_vm->_draw->_transparency = 0;
@@ -1659,48 +1109,47 @@ bool Inter_v2::o2_printText(OpFuncParams &params) {
}
do {
- for (i = 0; (((char) *_vm->_global->_inter_execPtr) != '.') &&
- (*_vm->_global->_inter_execPtr != 200);
- i++, _vm->_global->_inter_execPtr++) {
- buf[i] = (char) *_vm->_global->_inter_execPtr;
+ for (i = 0; (_vm->_game->_script->peekChar() != '.') &&
+ (_vm->_game->_script->peekByte() != 200); i++) {
+ buf[i] = _vm->_game->_script->readChar();
}
- if (*_vm->_global->_inter_execPtr != 200) {
- _vm->_global->_inter_execPtr++;
- switch (*_vm->_global->_inter_execPtr) {
- case 16:
- case 18:
+ if (_vm->_game->_script->peekByte() != 200) {
+ _vm->_game->_script->skip(1);
+ switch (_vm->_game->_script->peekByte()) {
+ case TYPE_VAR_INT8:
+ case TYPE_ARRAY_INT8:
sprintf(buf + i, "%d",
- (int8) READ_VARO_UINT8(_vm->_parse->parseVarIndex()));
+ (int8) READ_VARO_UINT8(_vm->_game->_script->readVarIndex()));
break;
- case 17:
- case 24:
- case 27:
+ case TYPE_VAR_INT16:
+ case TYPE_VAR_INT32_AS_INT16:
+ case TYPE_ARRAY_INT16:
sprintf(buf + i, "%d",
- (int16) READ_VARO_UINT16(_vm->_parse->parseVarIndex()));
+ (int16) READ_VARO_UINT16(_vm->_game->_script->readVarIndex()));
break;
- case 23:
- case 26:
+ case TYPE_VAR_INT32:
+ case TYPE_ARRAY_INT32:
sprintf(buf + i, "%d",
- VAR_OFFSET(_vm->_parse->parseVarIndex()));
+ VAR_OFFSET(_vm->_game->_script->readVarIndex()));
break;
- case 25:
- case 28:
+ case TYPE_VAR_STR:
+ case TYPE_ARRAY_STR:
sprintf(buf + i, "%s",
- GET_VARO_STR(_vm->_parse->parseVarIndex()));
+ GET_VARO_STR(_vm->_game->_script->readVarIndex()));
break;
}
- _vm->_global->_inter_execPtr++;
+ _vm->_game->_script->skip(1);
} else
buf[i] = 0;
_vm->_draw->spriteOperation(DRAW_PRINTTEXT);
- } while (*_vm->_global->_inter_execPtr != 200);
+ } while (_vm->_game->_script->peekByte() != 200);
- _vm->_global->_inter_execPtr++;
+ _vm->_game->_script->skip(1);
return false;
}
@@ -1708,20 +1157,20 @@ bool Inter_v2::o2_printText(OpFuncParams &params) {
bool Inter_v2::o2_animPalInit(OpFuncParams &params) {
int16 index;
- index = load16();
+ index = _vm->_game->_script->readInt16();
if (index > 0) {
index--;
- _animPalLowIndex[index] = _vm->_parse->parseValExpr();
- _animPalHighIndex[index] = _vm->_parse->parseValExpr();
+ _animPalLowIndex[index] = _vm->_game->_script->readValExpr();
+ _animPalHighIndex[index] = _vm->_game->_script->readValExpr();
_animPalDir[index] = 1;
} else if (index == 0) {
memset(_animPalDir, 0, 8 * sizeof(int16));
- _vm->_parse->parseValExpr();
- _vm->_parse->parseValExpr();
+ _vm->_game->_script->readValExpr();
+ _vm->_game->_script->readValExpr();
} else {
index = -index - 1;
- _animPalLowIndex[index] = _vm->_parse->parseValExpr();
- _animPalHighIndex[index] = _vm->_parse->parseValExpr();
+ _animPalLowIndex[index] = _vm->_game->_script->readValExpr();
+ _animPalHighIndex[index] = _vm->_game->_script->readValExpr();
_animPalDir[index] = -1;
}
return false;
@@ -1734,14 +1183,14 @@ bool Inter_v2::o2_addCollision(OpFuncParams &params) {
int16 key;
int16 funcSub;
- id = _vm->_parse->parseValExpr();
- funcSub = _vm->_global->_inter_execPtr - _vm->_game->_totFileData;
- left = _vm->_parse->parseValExpr();
- top = _vm->_parse->parseValExpr();
- width = _vm->_parse->parseValExpr();
- height = _vm->_parse->parseValExpr();
- flags = _vm->_parse->parseValExpr();
- key = load16();
+ id = _vm->_game->_script->readValExpr();
+ funcSub = _vm->_game->_script->pos();
+ left = _vm->_game->_script->readValExpr();
+ top = _vm->_game->_script->readValExpr();
+ width = _vm->_game->_script->readValExpr();
+ height = _vm->_game->_script->readValExpr();
+ flags = _vm->_game->_script->readValExpr();
+ key = _vm->_game->_script->readInt16();
if (key == 0)
key = ABS(id) + 41960;
@@ -1775,7 +1224,7 @@ bool Inter_v2::o2_addCollision(OpFuncParams &params) {
bool Inter_v2::o2_freeCollision(OpFuncParams &params) {
int16 id;
- id = _vm->_parse->parseValExpr();
+ id = _vm->_game->_script->readValExpr();
if (id == -2) {
for (int i = 0; i < 150; i++) {
if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xD000)
@@ -1797,9 +1246,9 @@ bool Inter_v2::o2_goblinFunc(OpFuncParams &params) {
// It's not yet implemented, so we fudge our way through
// and pretend we've won.
if (_vm->getGameType() == kGameTypeInca2) {
- _vm->_global->_inter_execPtr += 4;
- uint16 resVar = (uint16) load16();
- _vm->_global->_inter_execPtr += 4;
+ _vm->_game->_script->skip(4);
+ uint16 resVar = _vm->_game->_script->readUint16();
+ _vm->_game->_script->skip(4);
WRITE_VAR(resVar, 1);
return false;
@@ -1808,18 +1257,20 @@ bool Inter_v2::o2_goblinFunc(OpFuncParams &params) {
OpGobParams gobParams;
int16 cmd;
- cmd = load16();
- _vm->_global->_inter_execPtr += 2;
+ cmd = _vm->_game->_script->readInt16();
+
+ gobParams.paramCount = _vm->_game->_script->readInt16();
+ gobParams.extraData = cmd;
if (cmd != 101)
- executeGoblinOpcode(cmd, gobParams);
+ executeOpcodeGob(cmd, gobParams);
return false;
}
bool Inter_v2::o2_stopSound(OpFuncParams &params) {
int16 expr;
- expr = _vm->_parse->parseValExpr();
+ expr = _vm->_game->_script->readValExpr();
if (expr < 0) {
_vm->_sound->adlibStop();
@@ -1839,13 +1290,13 @@ bool Inter_v2::o2_getFreeMem(OpFuncParams &params) {
int16 freeVar;
int16 maxFreeVar;
- freeVar = _vm->_parse->parseVarIndex();
- maxFreeVar = _vm->_parse->parseVarIndex();
+ freeVar = _vm->_game->_script->readVarIndex();
+ maxFreeVar = _vm->_game->_script->readVarIndex();
// HACK
WRITE_VAR_OFFSET(freeVar, 1000000);
WRITE_VAR_OFFSET(maxFreeVar, 1000000);
- WRITE_VAR(16, READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4);
+ WRITE_VAR(16, _vm->_game->_script->getVariablesCount() * 4);
return false;
}
@@ -1855,23 +1306,22 @@ bool Inter_v2::o2_checkData(OpFuncParams &params) {
int32 size;
SaveLoad::SaveMode mode;
- evalExpr(0);
- varOff = _vm->_parse->parseVarIndex();
+ _vm->_game->_script->evalExpr(0);
+ varOff = _vm->_game->_script->readVarIndex();
size = -1;
handle = 1;
- mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr);
+ mode = _vm->_saveLoad->getSaveMode(_vm->_game->_script->getResultStr());
if (mode == SaveLoad::kSaveModeNone) {
- handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr);
- if (handle >= 0) {
- _vm->_dataIO->closeData(handle);
- size = _vm->_dataIO->getDataSize(_vm->_global->_inter_resStr);
- } else
- warning("File \"%s\" not found", _vm->_global->_inter_resStr);
+ if (_vm->_dataIO->existData(_vm->_game->_script->getResultStr()))
+ size = _vm->_dataIO->getDataSize(_vm->_game->_script->getResultStr());
+ else
+ warning("File \"%s\" not found", _vm->_game->_script->getResultStr());
+
} else if (mode == SaveLoad::kSaveModeSave)
- size = _vm->_saveLoad->getSize(_vm->_global->_inter_resStr);
+ size = _vm->_saveLoad->getSize(_vm->_game->_script->getResultStr());
else if (mode == SaveLoad::kSaveModeExists)
size = 23;
@@ -1879,7 +1329,7 @@ bool Inter_v2::o2_checkData(OpFuncParams &params) {
handle = -1;
debugC(2, kDebugFileIO, "Requested size of file \"%s\": %d",
- _vm->_global->_inter_resStr, size);
+ _vm->_game->_script->getResultStr(), size);
WRITE_VAR_OFFSET(varOff, handle);
WRITE_VAR(16, (uint32) size);
@@ -1896,20 +1346,20 @@ bool Inter_v2::o2_readData(OpFuncParams &params) {
byte *buf;
SaveLoad::SaveMode mode;
- evalExpr(0);
- dataVar = _vm->_parse->parseVarIndex();
- size = _vm->_parse->parseValExpr();
- evalExpr(0);
- offset = _vm->_global->_inter_resVal;
+ _vm->_game->_script->evalExpr(0);
+ dataVar = _vm->_game->_script->readVarIndex();
+ size = _vm->_game->_script->readValExpr();
+ _vm->_game->_script->evalExpr(0);
+ offset = _vm->_game->_script->getResultInt();
retSize = 0;
debugC(2, kDebugFileIO, "Read from file \"%s\" (%d, %d bytes at %d)",
- _vm->_global->_inter_resStr, dataVar, size, offset);
+ _vm->_game->_script->getResultStr(), dataVar, size, offset);
- mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr);
+ mode = _vm->_saveLoad->getSaveMode(_vm->_game->_script->getResultStr());
if (mode == SaveLoad::kSaveModeSave) {
WRITE_VAR(1, 1);
- if (_vm->_saveLoad->load(_vm->_global->_inter_resStr, dataVar, size, offset))
+ if (_vm->_saveLoad->load(_vm->_game->_script->getResultStr(), dataVar, size, offset))
WRITE_VAR(1, 0);
return false;
} else if (mode == SaveLoad::kSaveModeIgnore)
@@ -1917,22 +1367,22 @@ bool Inter_v2::o2_readData(OpFuncParams &params) {
if (size < 0) {
warning("Attempted to read a raw sprite from file \"%s\"",
- _vm->_global->_inter_resStr);
+ _vm->_game->_script->getResultStr());
return false ;
} else if (size == 0) {
dataVar = 0;
- size = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
+ size = _vm->_game->_script->getVariablesCount() * 4;
}
buf = _variables->getAddressOff8(dataVar);
- if (_vm->_global->_inter_resStr[0] == 0) {
+ if (_vm->_game->_script->getResultStr()[0] == 0) {
WRITE_VAR(1, size);
return false;
}
WRITE_VAR(1, 1);
- handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr);
+ handle = _vm->_dataIO->openData(_vm->_game->_script->getResultStr());
if (handle < 0)
return false;
@@ -1967,23 +1417,23 @@ bool Inter_v2::o2_writeData(OpFuncParams &params) {
int16 dataVar;
SaveLoad::SaveMode mode;
- evalExpr(0);
- dataVar = _vm->_parse->parseVarIndex();
- size = _vm->_parse->parseValExpr();
- evalExpr(0);
- offset = _vm->_global->_inter_resVal;
+ _vm->_game->_script->evalExpr(0);
+ dataVar = _vm->_game->_script->readVarIndex();
+ size = _vm->_game->_script->readValExpr();
+ _vm->_game->_script->evalExpr(0);
+ offset = _vm->_game->_script->getResultInt();
debugC(2, kDebugFileIO, "Write to file \"%s\" (%d, %d bytes at %d)",
- _vm->_global->_inter_resStr, dataVar, size, offset);
+ _vm->_game->_script->getResultStr(), dataVar, size, offset);
WRITE_VAR(1, 1);
- mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr);
+ mode = _vm->_saveLoad->getSaveMode(_vm->_game->_script->getResultStr());
if (mode == SaveLoad::kSaveModeSave) {
- if (_vm->_saveLoad->save(_vm->_global->_inter_resStr, dataVar, size, offset))
+ if (_vm->_saveLoad->save(_vm->_game->_script->getResultStr(), dataVar, size, offset))
WRITE_VAR(1, 0);
} else if (mode == SaveLoad::kSaveModeNone)
- warning("Attempted to write to file \"%s\"", _vm->_global->_inter_resStr);
+ warning("Attempted to write to file \"%s\"", _vm->_game->_script->getResultStr());
return false;
}
@@ -1992,7 +1442,7 @@ void Inter_v2::o2_loadInfogramesIns(OpGobParams &params) {
int16 varName;
char fileName[20];
- varName = load16();
+ varName = _vm->_game->_script->readInt16();
strncpy0(fileName, GET_VAR_STR(varName), 15);
strcat(fileName, ".INS");
@@ -2004,7 +1454,7 @@ void Inter_v2::o2_playInfogrames(OpGobParams &params) {
int16 varName;
char fileName[20];
- varName = load16();
+ varName = _vm->_game->_script->readInt16();
strncpy0(fileName, GET_VAR_STR(varName), 15);
strcat(fileName, ".DUM");
@@ -2014,13 +1464,13 @@ void Inter_v2::o2_playInfogrames(OpGobParams &params) {
}
void Inter_v2::o2_startInfogrames(OpGobParams &params) {
- load16();
+ _vm->_game->_script->readInt16();
_vm->_sound->infogramesPlay();
}
void Inter_v2::o2_stopInfogrames(OpGobParams &params) {
- load16();
+ _vm->_game->_script->readInt16();
_vm->_sound->infogramesStop();
}
@@ -2034,12 +1484,12 @@ void Inter_v2::o2_stopProtracker(OpGobParams &params) {
}
void Inter_v2::o2_handleGoblins(OpGobParams &params) {
- _vm->_goblin->_gob1NoTurn = VAR(load16()) != 0;
- _vm->_goblin->_gob2NoTurn = VAR(load16()) != 0;
- _vm->_goblin->_gob1RelaxTimeVar = load16();
- _vm->_goblin->_gob2RelaxTimeVar = load16();
- _vm->_goblin->_gob1Busy = VAR(load16()) != 0;
- _vm->_goblin->_gob2Busy = VAR(load16()) != 0;
+ _vm->_goblin->_gob1NoTurn = VAR(_vm->_game->_script->readInt16()) != 0;
+ _vm->_goblin->_gob2NoTurn = VAR(_vm->_game->_script->readInt16()) != 0;
+ _vm->_goblin->_gob1RelaxTimeVar = _vm->_game->_script->readInt16();
+ _vm->_goblin->_gob2RelaxTimeVar = _vm->_game->_script->readInt16();
+ _vm->_goblin->_gob1Busy = VAR(_vm->_game->_script->readInt16()) != 0;
+ _vm->_goblin->_gob2Busy = VAR(_vm->_game->_script->readInt16()) != 0;
_vm->_goblin->handleGoblins();
}
@@ -2050,21 +1500,20 @@ int16 Inter_v2::loadSound(int16 search) {
uint16 slotIdMask;
uint32 dataSize;
SoundType type;
- SoundSource source;
type = SOUND_SND;
slotIdMask = 0;
dataSize = 0;
if (!search) {
- slot = _vm->_parse->parseValExpr();
+ slot = _vm->_game->_script->readValExpr();
if (slot < 0) {
type = SOUND_ADL;
slot = -slot;
}
- id = load16();
+ id = _vm->_game->_script->readInt16();
} else {
- id = load16();
+ id = _vm->_game->_script->readInt16();
for (slot = 0; slot < Sound::kSoundsCount; slot++)
if (_vm->_sound->sampleGetBySlot(slot)->isId(id)) {
@@ -2093,37 +1542,37 @@ int16 Inter_v2::loadSound(int16 search) {
if (id == -1) {
char sndfile[14];
- source = SOUND_FILE;
-
- strncpy0(sndfile, (const char *) _vm->_global->_inter_execPtr, 9);
- _vm->_global->_inter_execPtr += 9;
+ strncpy0(sndfile, _vm->_game->_script->readString(9), 9);
if (type == SOUND_ADL)
strcat(sndfile, ".ADL");
else
strcat(sndfile, ".SND");
- dataPtr = (byte *) _vm->_dataIO->getData(sndfile);
- if (dataPtr)
- dataSize = _vm->_dataIO->getDataSize(sndfile);
- } else if (id >= 30000) {
- source = SOUND_EXT;
-
- dataPtr = (byte *) _vm->_game->loadExtData(id, 0, 0, &dataSize);
- } else {
- int16 totSize;
+ dataPtr = _vm->_dataIO->getData(sndfile);
+ dataSize = _vm->_dataIO->getDataSize(sndfile);
+ if (!dataPtr)
+ return 0;
- source = SOUND_TOT;
+ if (!sample->load(type, dataPtr, dataSize)) {
+ delete[] dataPtr;
+ return 0;
+ }
- dataPtr = (byte *) _vm->_game->loadTotResource(id, &totSize);
- dataSize = (uint32) ((int32) totSize);
+ sample->_id = id;
+ return slot | slotIdMask;
}
- if (dataPtr) {
- sample->load(type, source, dataPtr, dataSize);
- sample->_id = id;
+ Resource *resource = _vm->_game->_resources->getResource(id);
+ if (!resource)
+ return 0;
+
+ if (!sample->load(type, resource)) {
+ delete resource;
+ return 0;
}
+ sample->_id = id;
return slot | slotIdMask;
}
diff --git a/engines/gob/inter_v3.cpp b/engines/gob/inter_v3.cpp
index 6819b369b8..17ce7feafa 100644
--- a/engines/gob/inter_v3.cpp
+++ b/engines/gob/inter_v3.cpp
@@ -32,683 +32,38 @@
#include "gob/dataio.h"
#include "gob/draw.h"
#include "gob/game.h"
-#include "gob/parse.h"
+#include "gob/script.h"
+#include "gob/resources.h"
namespace Gob {
-#define OPCODE(x) _OPCODE(Inter_v3, x)
-
-const int Inter_v3::_goblinFuncLookUp[][2] = {
- {0, 0},
- {1, 1},
- {2, 2},
- {4, 3},
- {5, 4},
- {6, 5},
- {7, 6},
- {8, 7},
- {9, 8},
- {10, 9},
- {12, 10},
- {13, 11},
- {14, 12},
- {15, 13},
- {16, 14},
- {21, 15},
- {22, 16},
- {23, 17},
- {24, 18},
- {25, 19},
- {26, 20},
- {27, 21},
- {28, 22},
- {29, 23},
- {30, 24},
- {32, 25},
- {33, 26},
- {34, 27},
- {35, 28},
- {36, 29},
- {37, 30},
- {40, 31},
- {41, 32},
- {42, 33},
- {43, 34},
- {44, 35},
- {50, 36},
- {52, 37},
- {53, 38},
- {100, 39},
- {152, 40},
- {200, 41},
- {201, 42},
- {202, 43},
- {203, 44},
- {204, 45},
- {250, 46},
- {251, 47},
- {252, 48},
- {500, 49},
- {502, 50},
- {503, 51},
- {600, 52},
- {601, 53},
- {602, 54},
- {603, 55},
- {604, 56},
- {605, 57},
- {1000, 58},
- {1001, 59},
- {1002, 60},
- {1003, 61},
- {1004, 62},
- {1005, 63},
- {1006, 64},
- {1008, 65},
- {1009, 66},
- {1010, 67},
- {1011, 68},
- {1015, 69},
- {2005, 70}
-};
+#define OPCODEVER Inter_v3
+#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x)
+#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x)
+#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x)
Inter_v3::Inter_v3(GobEngine *vm) : Inter_v2(vm) {
- setupOpcodes();
}
-void Inter_v3::setupOpcodes() {
- static const OpcodeDrawEntryV3 opcodesDraw[256] = {
- /* 00 */
- OPCODE(o1_loadMult),
- OPCODE(o2_playMult),
- OPCODE(o2_freeMultKeys),
- {0, ""},
- /* 04 */
- {0, ""},
- {0, ""},
- {0, ""},
- OPCODE(o1_initCursor),
- /* 08 */
- OPCODE(o1_initCursorAnim),
- OPCODE(o1_clearCursorAnim),
- OPCODE(o2_setRenderFlags),
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- OPCODE(o1_loadAnim),
- OPCODE(o1_freeAnim),
- OPCODE(o1_updateAnim),
- OPCODE(o2_multSub),
- /* 14 */
- OPCODE(o2_initMult),
- OPCODE(o1_freeMult),
- OPCODE(o1_animate),
- OPCODE(o2_loadMultObject),
- /* 18 */
- OPCODE(o1_getAnimLayerInfo),
- OPCODE(o1_getObjAnimSize),
- OPCODE(o1_loadStatic),
- OPCODE(o1_freeStatic),
- /* 1C */
- OPCODE(o2_renderStatic),
- OPCODE(o2_loadCurLayer),
- {0, ""},
- {0, ""},
- /* 20 */
- OPCODE(o2_playCDTrack),
- OPCODE(o2_waitCDTrackEnd),
- OPCODE(o2_stopCD),
- OPCODE(o2_readLIC),
- /* 24 */
- OPCODE(o2_freeLIC),
- OPCODE(o2_getCDTrackPos),
- {0, ""},
- {0, ""},
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- OPCODE(o2_loadFontToSprite),
- OPCODE(o1_freeFontToSprite),
- {0, ""},
- {0, ""},
- /* 34 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 38 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 3C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 40 */
- OPCODE(o2_totSub),
- OPCODE(o2_switchTotSub),
- OPCODE(o2_pushVars),
- OPCODE(o2_popVars),
- /* 44 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 48 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 4C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 50 */
- OPCODE(o2_loadMapObjects),
- OPCODE(o2_freeGoblins),
- OPCODE(o2_moveGoblin),
- OPCODE(o2_writeGoblinPos),
- /* 54 */
- OPCODE(o2_stopGoblin),
- OPCODE(o2_setGoblinState),
- OPCODE(o2_placeGoblin),
- {0, ""},
- /* 58 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 5C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 60 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 64 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 68 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 6C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 70 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 74 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 78 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 7C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 80 */
- OPCODE(o2_initScreen),
- OPCODE(o2_scroll),
- OPCODE(o2_setScrollOffset),
- OPCODE(o2_playImd),
- /* 84 */
- OPCODE(o2_getImdInfo),
- OPCODE(o2_openItk),
- OPCODE(o2_closeItk),
- OPCODE(o2_setImdFrontSurf),
- /* 88 */
- OPCODE(o2_resetImdFrontSurf),
- {0, ""},
- {0, ""},
- {0, ""},
- /* 8C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 90 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 94 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 98 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 9C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* AC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* BC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* CC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* DC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* EC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* FC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""}
- };
-
- static const OpcodeFuncEntryV3 opcodesFunc[80] = {
- /* 00 */
- OPCODE(o1_callSub),
- OPCODE(o1_callSub),
- OPCODE(o1_printTotText),
- OPCODE(o1_loadCursor),
- /* 04 */
- {0, ""},
- OPCODE(o1_switch),
- OPCODE(o1_repeatUntil),
- OPCODE(o1_whileDo),
- /* 08 */
- OPCODE(o1_if),
- OPCODE(o2_assign),
- OPCODE(o1_loadSpriteToPos),
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- {0, ""},
- OPCODE(o2_printText),
- OPCODE(o1_loadTot),
- OPCODE(o1_palLoad),
- /* 14 */
- OPCODE(o1_keyFunc),
- OPCODE(o1_capturePush),
- OPCODE(o1_capturePop),
- OPCODE(o2_animPalInit),
- /* 18 */
- OPCODE(o2_addCollision),
- OPCODE(o2_freeCollision),
- OPCODE(o3_getTotTextItemPart),
- {0, ""},
- /* 1C */
- {0, ""},
- {0, ""},
- OPCODE(o1_drawOperations),
- OPCODE(o1_setcmdCount),
- /* 20 */
- OPCODE(o1_return),
- OPCODE(o1_renewTimeInVars),
- OPCODE(o1_speakerOn),
- OPCODE(o1_speakerOff),
- /* 24 */
- OPCODE(o1_putPixel),
- OPCODE(o2_goblinFunc),
- OPCODE(o1_createSprite),
- OPCODE(o1_freeSprite),
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- OPCODE(o1_returnTo),
- OPCODE(o1_loadSpriteContent),
- OPCODE(o3_copySprite),
- OPCODE(o1_fillRect),
- /* 34 */
- OPCODE(o1_drawLine),
- OPCODE(o1_strToLong),
- OPCODE(o1_invalidate),
- OPCODE(o1_setBackDelta),
- /* 38 */
- OPCODE(o1_playSound),
- OPCODE(o2_stopSound),
- OPCODE(o2_loadSound),
- OPCODE(o1_freeSoundSlot),
- /* 3C */
- OPCODE(o1_waitEndPlay),
- OPCODE(o1_playComposition),
- OPCODE(o2_getFreeMem),
- OPCODE(o2_checkData),
- /* 40 */
- {0, ""},
- OPCODE(o1_prepareStr),
- OPCODE(o1_insertStr),
- OPCODE(o1_cutStr),
- /* 44 */
- OPCODE(o1_strstr),
- OPCODE(o1_istrlen),
- OPCODE(o1_setMousePos),
- OPCODE(o1_setFrameRate),
- /* 48 */
- OPCODE(o1_animatePalette),
- OPCODE(o1_animateCursor),
- OPCODE(o1_blitCursor),
- OPCODE(o1_loadFont),
- /* 4C */
- OPCODE(o1_freeFont),
- OPCODE(o2_readData),
- OPCODE(o2_writeData),
- OPCODE(o1_manageDataFile),
- };
-
- static const OpcodeGoblinEntryV3 opcodesGoblin[71] = {
- /* 00 */
- OPCODE(o2_loadInfogramesIns),
- OPCODE(o2_startInfogrames),
- OPCODE(o2_stopInfogrames),
- {0, ""},
- /* 04 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 08 */
- {0, ""},
- OPCODE(o2_playInfogrames),
- {0, ""},
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 14 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 18 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 1C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 20 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 24 */
- {0, ""},
- {0, ""},
- {0, ""},
- OPCODE(o3_wobble),
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 34 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 38 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 3C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 40 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 44 */
- {0, ""},
- {0, ""},
- {0, ""},
- };
-
- _opcodesDrawV3 = opcodesDraw;
- _opcodesFuncV3 = opcodesFunc;
- _opcodesGoblinV3 = opcodesGoblin;
+void Inter_v3::setupOpcodesDraw() {
+ Inter_v2::setupOpcodesDraw();
}
-void Inter_v3::executeDrawOpcode(byte i) {
- debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)",
- i, i, getOpcodeDrawDesc(i));
+void Inter_v3::setupOpcodesFunc() {
+ Inter_v2::setupOpcodesFunc();
- OpcodeDrawProcV3 op = _opcodesDrawV3[i].proc;
-
- if (op == 0)
- warning("unimplemented opcodeDraw: %d", i);
- else
- (this->*op) ();
-}
-
-bool Inter_v3::executeFuncOpcode(byte i, byte j, OpFuncParams &params) {
- debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)",
- i, j, i, j, getOpcodeFuncDesc(i, j));
-
- if ((i > 4) || (j > 15)) {
- warning("unimplemented opcodeFunc: %d.%d", i, j);
- return false;
- }
-
- OpcodeFuncProcV3 op = _opcodesFuncV3[i*16 + j].proc;
-
- if (op == 0)
- warning("unimplemented opcodeFunc: %d.%d", i, j);
- else
- return (this->*op) (params);
-
- return false;
-}
-
-void Inter_v3::executeGoblinOpcode(int i, OpGobParams &params) {
- debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)",
- i, i, getOpcodeGoblinDesc(i));
-
- OpcodeGoblinProcV3 op = 0;
-
- for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
- if (_goblinFuncLookUp[j][0] == i) {
- op = _opcodesGoblinV3[_goblinFuncLookUp[j][1]].proc;
- break;
- }
-
- if (op == 0) {
- int16 val;
-
- _vm->_global->_inter_execPtr -= 2;
- val = load16();
- _vm->_global->_inter_execPtr += val << 1;
- } else
- (this->*op) (params);
+ OPCODEFUNC(0x1A, o3_getTotTextItemPart);
+ OPCODEFUNC(0x32, o3_copySprite);
}
-const char *Inter_v3::getOpcodeDrawDesc(byte i) {
- return _opcodesDrawV3[i].desc;
-}
+void Inter_v3::setupOpcodesGob() {
+ OPCODEGOB( 0, o2_loadInfogramesIns);
+ OPCODEGOB( 1, o2_startInfogrames);
+ OPCODEGOB( 2, o2_stopInfogrames);
-const char *Inter_v3::getOpcodeFuncDesc(byte i, byte j) {
- if ((i > 4) || (j > 15))
- return "";
+ OPCODEGOB( 10, o2_playInfogrames);
- return _opcodesFuncV3[i*16 + j].desc;
-}
-
-const char *Inter_v3::getOpcodeGoblinDesc(int i) {
- for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
- if (_goblinFuncLookUp[j][0] == i)
- return _opcodesGoblinV3[_goblinFuncLookUp[j][1]].desc;
- return "";
+ OPCODEGOB(100, o3_wobble);
}
bool Inter_v3::o3_getTotTextItemPart(OpFuncParams &params) {
@@ -720,18 +75,18 @@ bool Inter_v3::o3_getTotTextItemPart(OpFuncParams &params) {
uint32 stringStartVar, stringVar;
bool end;
- totTextItem = load16();
- stringStartVar = _vm->_parse->parseVarIndex();
- part = _vm->_parse->parseValExpr();
+ totTextItem = _vm->_game->_script->readInt16();
+ stringStartVar = _vm->_game->_script->readVarIndex();
+ part = _vm->_game->_script->readValExpr();
stringVar = stringStartVar;
WRITE_VARO_UINT8(stringVar, 0);
- if (!_vm->_game->_totTextData)
+ TextItem *textItem = _vm->_game->_resources->getTextItem(totTextItem);
+ if (!textItem)
return false;
- totData = _vm->_game->_totTextData->dataPtr +
- _vm->_game->_totTextData->items[totTextItem].offset;
+ totData = textItem->getData();
// Skip background rectangles
while (((int16) READ_LE_UINT16(totData)) != -1)
@@ -782,6 +137,7 @@ bool Inter_v3::o3_getTotTextItemPart(OpFuncParams &params) {
if ((n != 0) || (*totData == 1) ||
(*totData == 6) || (*totData == 7)) {
WRITE_VARO_UINT8(stringVar, 0);
+ delete textItem;
return false;
}
@@ -813,8 +169,9 @@ bool Inter_v3::o3_getTotTextItemPart(OpFuncParams &params) {
WRITE_VARO_UINT16(stringVar, offX);
WRITE_VARO_UINT16(stringVar + 2, offY);
WRITE_VARO_UINT16(stringVar + 4,
- totData - _vm->_game->_totTextData->dataPtr);
+ totData - _vm->_game->_resources->getTexts());
WRITE_VARO_UINT8(stringVar + 6, 0);
+ delete textItem;
return false;
}
@@ -860,8 +217,10 @@ bool Inter_v3::o3_getTotTextItemPart(OpFuncParams &params) {
if (((*totData != 2) && (*totData != 5)) ||
(ABS(offY - READ_LE_UINT16(totData + 3)) > 1)) {
- if (curPart == part)
+ if (curPart == part) {
+ delete textItem;
return false;
+ }
stringVar = stringStartVar;
WRITE_VARO_UINT8(stringVar, 0);
@@ -881,6 +240,7 @@ bool Inter_v3::o3_getTotTextItemPart(OpFuncParams &params) {
}
}
+ delete textItem;
return false;
}
diff --git a/engines/gob/inter_v4.cpp b/engines/gob/inter_v4.cpp
index 6ab55d70af..48378a5987 100644
--- a/engines/gob/inter_v4.cpp
+++ b/engines/gob/inter_v4.cpp
@@ -32,689 +32,32 @@
#include "gob/global.h"
#include "gob/draw.h"
#include "gob/game.h"
-#include "gob/parse.h"
+#include "gob/script.h"
#include "gob/videoplayer.h"
#include "gob/sound/sound.h"
namespace Gob {
-#define OPCODE(x) _OPCODE(Inter_v4, x)
-
-const int Inter_v4::_goblinFuncLookUp[][2] = {
- {0, 0},
- {1, 1},
- {2, 2},
- {4, 3},
- {5, 4},
- {6, 5},
- {7, 6},
- {8, 7},
- {9, 8},
- {10, 9},
- {12, 10},
- {13, 11},
- {14, 12},
- {15, 13},
- {16, 14},
- {21, 15},
- {22, 16},
- {23, 17},
- {24, 18},
- {25, 19},
- {26, 20},
- {27, 21},
- {28, 22},
- {29, 23},
- {30, 24},
- {32, 25},
- {33, 26},
- {34, 27},
- {35, 28},
- {36, 29},
- {37, 30},
- {40, 31},
- {41, 32},
- {42, 33},
- {43, 34},
- {44, 35},
- {50, 36},
- {52, 37},
- {53, 38},
- {100, 39},
- {152, 40},
- {200, 41},
- {201, 42},
- {202, 43},
- {203, 44},
- {204, 45},
- {250, 46},
- {251, 47},
- {252, 48},
- {500, 49},
- {502, 50},
- {503, 51},
- {600, 52},
- {601, 53},
- {602, 54},
- {603, 55},
- {604, 56},
- {605, 57},
- {1000, 58},
- {1001, 59},
- {1002, 60},
- {1003, 61},
- {1004, 62},
- {1005, 63},
- {1006, 64},
- {1008, 65},
- {1009, 66},
- {1010, 67},
- {1011, 68},
- {1015, 69},
- {2005, 70}
-};
+#define OPCODEVER Inter_v4
+#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x)
+#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x)
+#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x)
Inter_v4::Inter_v4(GobEngine *vm) : Inter_v3(vm) {
- setupOpcodes();
}
-void Inter_v4::setupOpcodes() {
- static const OpcodeDrawEntryV4 opcodesDraw[256] = {
- /* 00 */
- OPCODE(o1_loadMult),
- OPCODE(o2_playMult),
- OPCODE(o2_freeMultKeys),
- {0, ""},
- /* 04 */
- {0, ""},
- {0, ""},
- {0, ""},
- OPCODE(o1_initCursor),
- /* 08 */
- OPCODE(o1_initCursorAnim),
- OPCODE(o1_clearCursorAnim),
- OPCODE(o2_setRenderFlags),
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- OPCODE(o1_loadAnim),
- OPCODE(o1_freeAnim),
- OPCODE(o1_updateAnim),
- OPCODE(o2_multSub),
- /* 14 */
- OPCODE(o2_initMult),
- OPCODE(o1_freeMult),
- OPCODE(o1_animate),
- OPCODE(o2_loadMultObject),
- /* 18 */
- OPCODE(o1_getAnimLayerInfo),
- OPCODE(o1_getObjAnimSize),
- OPCODE(o1_loadStatic),
- OPCODE(o1_freeStatic),
- /* 1C */
- OPCODE(o2_renderStatic),
- OPCODE(o2_loadCurLayer),
- {0, ""},
- {0, ""},
- /* 20 */
- OPCODE(o2_playCDTrack),
- OPCODE(o2_waitCDTrackEnd),
- OPCODE(o2_stopCD),
- OPCODE(o2_readLIC),
- /* 24 */
- OPCODE(o2_freeLIC),
- OPCODE(o2_getCDTrackPos),
- {0, ""},
- {0, ""},
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- OPCODE(o2_loadFontToSprite),
- OPCODE(o1_freeFontToSprite),
- {0, ""},
- {0, ""},
- /* 34 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 38 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 3C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 40 */
- OPCODE(o2_totSub),
- OPCODE(o2_switchTotSub),
- OPCODE(o2_pushVars),
- OPCODE(o2_popVars),
- /* 44 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 48 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 4C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 50 */
- OPCODE(o2_loadMapObjects),
- OPCODE(o2_freeGoblins),
- OPCODE(o2_moveGoblin),
- OPCODE(o2_writeGoblinPos),
- /* 54 */
- OPCODE(o2_stopGoblin),
- OPCODE(o2_setGoblinState),
- OPCODE(o2_placeGoblin),
- {0, ""},
- /* 58 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 5C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 60 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 64 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 68 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 6C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 70 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 74 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 78 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 7C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 80 */
- OPCODE(o4_initScreen),
- OPCODE(o2_scroll),
- OPCODE(o2_setScrollOffset),
- OPCODE(o4_playVmdOrMusic),
- /* 84 */
- OPCODE(o2_getImdInfo),
- OPCODE(o2_openItk),
- OPCODE(o2_closeItk),
- OPCODE(o2_setImdFrontSurf),
- /* 88 */
- OPCODE(o2_resetImdFrontSurf),
- {0, ""},
- {0, ""},
- {0, ""},
- /* 8C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 90 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 94 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 98 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 9C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* AC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* BC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* CC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* DC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* EC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* FC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""}
- };
-
- static const OpcodeFuncEntryV4 opcodesFunc[80] = {
- /* 00 */
- OPCODE(o1_callSub),
- OPCODE(o1_callSub),
- OPCODE(o1_printTotText),
- OPCODE(o1_loadCursor),
- /* 04 */
- {0, ""},
- OPCODE(o1_switch),
- OPCODE(o1_repeatUntil),
- OPCODE(o1_whileDo),
- /* 08 */
- OPCODE(o1_if),
- OPCODE(o2_assign),
- OPCODE(o1_loadSpriteToPos),
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- {0, ""},
- OPCODE(o2_printText),
- OPCODE(o1_loadTot),
- OPCODE(o1_palLoad),
- /* 14 */
- OPCODE(o1_keyFunc),
- OPCODE(o1_capturePush),
- OPCODE(o1_capturePop),
- OPCODE(o2_animPalInit),
- /* 18 */
- OPCODE(o2_addCollision),
- OPCODE(o2_freeCollision),
- OPCODE(o3_getTotTextItemPart),
- {0, ""},
- /* 1C */
- {0, ""},
- {0, ""},
- OPCODE(o1_drawOperations),
- OPCODE(o1_setcmdCount),
- /* 20 */
- OPCODE(o1_return),
- OPCODE(o1_renewTimeInVars),
- OPCODE(o1_speakerOn),
- OPCODE(o1_speakerOff),
- /* 24 */
- OPCODE(o1_putPixel),
- OPCODE(o2_goblinFunc),
- OPCODE(o1_createSprite),
- OPCODE(o1_freeSprite),
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- OPCODE(o1_returnTo),
- OPCODE(o1_loadSpriteContent),
- OPCODE(o1_copySprite),
- OPCODE(o1_fillRect),
- /* 34 */
- OPCODE(o1_drawLine),
- OPCODE(o1_strToLong),
- OPCODE(o1_invalidate),
- OPCODE(o1_setBackDelta),
- /* 38 */
- OPCODE(o1_playSound),
- OPCODE(o2_stopSound),
- OPCODE(o2_loadSound),
- OPCODE(o1_freeSoundSlot),
- /* 3C */
- OPCODE(o1_waitEndPlay),
- OPCODE(o1_playComposition),
- OPCODE(o2_getFreeMem),
- OPCODE(o2_checkData),
- /* 40 */
- {0, ""},
- OPCODE(o1_prepareStr),
- OPCODE(o1_insertStr),
- OPCODE(o1_cutStr),
- /* 44 */
- OPCODE(o1_strstr),
- OPCODE(o1_istrlen),
- OPCODE(o1_setMousePos),
- OPCODE(o1_setFrameRate),
- /* 48 */
- OPCODE(o1_animatePalette),
- OPCODE(o1_animateCursor),
- OPCODE(o1_blitCursor),
- OPCODE(o1_loadFont),
- /* 4C */
- OPCODE(o1_freeFont),
- OPCODE(o2_readData),
- OPCODE(o2_writeData),
- OPCODE(o1_manageDataFile),
- };
-
- static const OpcodeGoblinEntryV4 opcodesGoblin[71] = {
- /* 00 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 04 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 08 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 14 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 18 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 1C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 20 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 24 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 34 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 38 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 3C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 40 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 44 */
- {0, ""},
- {0, ""},
- {0, ""},
- };
-
- _opcodesDrawV4 = opcodesDraw;
- _opcodesFuncV4 = opcodesFunc;
- _opcodesGoblinV4 = opcodesGoblin;
-}
-
-void Inter_v4::executeDrawOpcode(byte i) {
- debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)",
- i, i, getOpcodeDrawDesc(i));
-
- OpcodeDrawProcV4 op = _opcodesDrawV4[i].proc;
-
- if (op == 0)
- warning("unimplemented opcodeDraw: %d", i);
- else
- (this->*op) ();
-}
-
-bool Inter_v4::executeFuncOpcode(byte i, byte j, OpFuncParams &params) {
- debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s) - %s, %d, %d",
- i, j, i, j, getOpcodeFuncDesc(i, j), _vm->_game->_curTotFile,
- (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData),
- (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData - params.counter - 4));
-
- if ((i > 4) || (j > 15)) {
- warning("unimplemented opcodeFunc: %d.%d", i, j);
- return false;
- }
-
- OpcodeFuncProcV4 op = _opcodesFuncV4[i*16 + j].proc;
-
- if (op == 0)
- warning("unimplemented opcodeFunc: %d.%d", i, j);
- else
- return (this->*op) (params);
+void Inter_v4::setupOpcodesDraw() {
+ Inter_v3::setupOpcodesDraw();
- return false;
+ OPCODEDRAW(0x80, o4_initScreen);
+ OPCODEDRAW(0x83, o4_playVmdOrMusic);
}
-void Inter_v4::executeGoblinOpcode(int i, OpGobParams &params) {
- debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)",
- i, i, getOpcodeGoblinDesc(i));
-
- OpcodeGoblinProcV4 op = 0;
-
- for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
- if (_goblinFuncLookUp[j][0] == i) {
- op = _opcodesGoblinV4[_goblinFuncLookUp[j][1]].proc;
- break;
- }
-
- if (op == 0) {
- warning("unimplemented opcodeGoblin: %d", i);
-
- int16 val;
-
- _vm->_global->_inter_execPtr -= 2;
- val = load16();
- _vm->_global->_inter_execPtr += val << 1;
- } else
- (this->*op) (params);
-}
-
-const char *Inter_v4::getOpcodeDrawDesc(byte i) {
- return _opcodesDrawV4[i].desc;
-}
-
-const char *Inter_v4::getOpcodeFuncDesc(byte i, byte j) {
- if ((i > 4) || (j > 15))
- return "";
-
- return _opcodesFuncV4[i*16 + j].desc;
+void Inter_v4::setupOpcodesFunc() {
+ Inter_v3::setupOpcodesFunc();
}
-const char *Inter_v4::getOpcodeGoblinDesc(int i) {
- for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
- if (_goblinFuncLookUp[j][0] == i)
- return _opcodesGoblinV4[_goblinFuncLookUp[j][1]].desc;
- return "";
+void Inter_v4::setupOpcodesGob() {
}
void Inter_v4::o4_initScreen() {
@@ -722,13 +65,13 @@ void Inter_v4::o4_initScreen() {
int16 videoMode;
int16 width, height;
- offY = load16();
+ offY = _vm->_game->_script->readInt16();
videoMode = offY & 0xFF;
offY = (offY >> 8) & 0xFF;
- width = _vm->_parse->parseValExpr();
- height = _vm->_parse->parseValExpr();
+ width = _vm->_game->_script->readValExpr();
+ height = _vm->_game->_script->readValExpr();
_vm->_video->clearScreen();
@@ -809,8 +152,8 @@ void Inter_v4::o4_playVmdOrMusic() {
uint16 palCmd;
bool close;
- evalExpr(0);
- strncpy0(fileName, _vm->_global->_inter_resStr, 127);
+ _vm->_game->_script->evalExpr(0);
+ strncpy0(fileName, _vm->_game->_script->getResultStr(), 127);
// WORKAROUND: The nut rolling animation in the administration center
// in Woodruff is called "noixroul", but the scripts think it's "noixroule".
@@ -818,14 +161,14 @@ void Inter_v4::o4_playVmdOrMusic() {
(!scumm_stricmp(fileName, "noixroule")))
strcpy(fileName, "noixroul");
- x = _vm->_parse->parseValExpr();
- y = _vm->_parse->parseValExpr();
- startFrame = _vm->_parse->parseValExpr();
- lastFrame = _vm->_parse->parseValExpr();
- breakKey = _vm->_parse->parseValExpr();
- flags = _vm->_parse->parseValExpr();
- palStart = _vm->_parse->parseValExpr();
- palEnd = _vm->_parse->parseValExpr();
+ x = _vm->_game->_script->readValExpr();
+ y = _vm->_game->_script->readValExpr();
+ startFrame = _vm->_game->_script->readValExpr();
+ lastFrame = _vm->_game->_script->readValExpr();
+ breakKey = _vm->_game->_script->readValExpr();
+ flags = _vm->_game->_script->readValExpr();
+ palStart = _vm->_game->_script->readValExpr();
+ palEnd = _vm->_game->_script->readValExpr();
palCmd = 1 << (flags & 0x3F);
debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, "
diff --git a/engines/gob/inter_v5.cpp b/engines/gob/inter_v5.cpp
index cb5b28cb67..1c20851c8d 100644
--- a/engines/gob/inter_v5.cpp
+++ b/engines/gob/inter_v5.cpp
@@ -30,652 +30,73 @@
#include "gob/inter.h"
#include "gob/global.h"
#include "gob/game.h"
-#include "gob/parse.h"
+#include "gob/script.h"
#include "gob/draw.h"
namespace Gob {
-#define OPCODE(x) _OPCODE(Inter_v5, x)
-
-const int Inter_v5::_goblinFuncLookUp[][2] = {
- {0, 0},
- {1, 0},
- {3, 0},
- {2, 0},
- {33, 0},
- {80, 1},
- {81, 2},
- {82, 3},
- {83, 4},
- {84, 5},
- {85, 6},
- {86, 7},
- {87, 0},
- {88, 0},
- {89, 0},
- {90, 0},
- {91, 0},
- {92, 8},
- {93, 0},
- {94, 0},
- {95, 9},
- {96, 10},
- {97, 11},
- {98, 12},
- {99, 0},
- {100, 13},
- {200, 14}
-};
+#define OPCODEVER Inter_v5
+#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x)
+#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x)
+#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x)
Inter_v5::Inter_v5(GobEngine *vm) : Inter_v4(vm) {
- setupOpcodes();
}
-void Inter_v5::setupOpcodes() {
- static const OpcodeDrawEntryV5 opcodesDraw[256] = {
- /* 00 */
- OPCODE(o1_loadMult),
- OPCODE(o2_playMult),
- OPCODE(o2_freeMultKeys),
- {0, ""},
- /* 04 */
- {0, ""},
- {0, ""},
- {0, ""},
- OPCODE(o1_initCursor),
- /* 08 */
- OPCODE(o1_initCursorAnim),
- OPCODE(o1_clearCursorAnim),
- OPCODE(o2_setRenderFlags),
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- OPCODE(o1_loadAnim),
- OPCODE(o1_freeAnim),
- OPCODE(o1_updateAnim),
- OPCODE(o2_multSub),
- /* 14 */
- OPCODE(o2_initMult),
- OPCODE(o1_freeMult),
- OPCODE(o1_animate),
- OPCODE(o2_loadMultObject),
- /* 18 */
- OPCODE(o1_getAnimLayerInfo),
- OPCODE(o1_getObjAnimSize),
- OPCODE(o1_loadStatic),
- OPCODE(o1_freeStatic),
- /* 1C */
- OPCODE(o2_renderStatic),
- OPCODE(o2_loadCurLayer),
- {0, ""},
- {0, ""},
- /* 20 */
- OPCODE(o2_playCDTrack),
- OPCODE(o2_waitCDTrackEnd),
- OPCODE(o2_stopCD),
- OPCODE(o2_readLIC),
- /* 24 */
- OPCODE(o2_freeLIC),
- OPCODE(o2_getCDTrackPos),
- {0, ""},
- {0, ""},
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- OPCODE(o2_loadFontToSprite),
- OPCODE(o1_freeFontToSprite),
- {0, ""},
- {0, ""},
- /* 34 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 38 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 3C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 40 */
- OPCODE(o2_totSub),
- OPCODE(o2_switchTotSub),
- OPCODE(o2_pushVars),
- OPCODE(o2_popVars),
- /* 44 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 48 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 4C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 50 */
- OPCODE(o2_loadMapObjects),
- OPCODE(o2_freeGoblins),
- OPCODE(o2_moveGoblin),
- OPCODE(o2_writeGoblinPos),
- /* 54 */
- OPCODE(o2_stopGoblin),
- OPCODE(o2_setGoblinState),
- OPCODE(o2_placeGoblin),
- {0, ""},
- /* 58 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 5C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 60 */
- {0, ""},
- OPCODE(o5_deleteFile),
- {0, ""},
- {0, ""},
- /* 64 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 68 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 6C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 70 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 74 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 78 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 7C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 80 */
- OPCODE(o5_initScreen),
- OPCODE(o2_scroll),
- OPCODE(o2_setScrollOffset),
- OPCODE(o4_playVmdOrMusic),
- /* 84 */
- OPCODE(o2_getImdInfo),
- OPCODE(o2_openItk),
- OPCODE(o2_closeItk),
- OPCODE(o2_setImdFrontSurf),
- /* 88 */
- OPCODE(o2_resetImdFrontSurf),
- {0, ""},
- {0, ""},
- {0, ""},
- /* 8C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 90 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 94 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 98 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 9C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* AC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* BC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* CC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* DC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* EC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* FC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""}
- };
-
- static const OpcodeFuncEntryV5 opcodesFunc[80] = {
- /* 00 */
- OPCODE(o1_callSub),
- OPCODE(o1_callSub),
- OPCODE(o1_printTotText),
- OPCODE(o1_loadCursor),
- /* 04 */
- {0, ""},
- OPCODE(o1_switch),
- OPCODE(o1_repeatUntil),
- OPCODE(o1_whileDo),
- /* 08 */
- OPCODE(o1_if),
- OPCODE(o2_assign),
- OPCODE(o1_loadSpriteToPos),
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- {0, ""},
- OPCODE(o2_printText),
- OPCODE(o1_loadTot),
- OPCODE(o1_palLoad),
- /* 14 */
- OPCODE(o1_keyFunc),
- OPCODE(o1_capturePush),
- OPCODE(o1_capturePop),
- OPCODE(o2_animPalInit),
- /* 18 */
- OPCODE(o2_addCollision),
- OPCODE(o2_freeCollision),
- OPCODE(o3_getTotTextItemPart),
- {0, ""},
- /* 1C */
- {0, ""},
- {0, ""},
- OPCODE(o1_drawOperations),
- OPCODE(o1_setcmdCount),
- /* 20 */
- OPCODE(o1_return),
- OPCODE(o1_renewTimeInVars),
- OPCODE(o1_speakerOn),
- OPCODE(o1_speakerOff),
- /* 24 */
- OPCODE(o1_putPixel),
- OPCODE(o2_goblinFunc),
- OPCODE(o1_createSprite),
- OPCODE(o1_freeSprite),
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- OPCODE(o1_returnTo),
- OPCODE(o1_loadSpriteContent),
- OPCODE(o1_copySprite),
- OPCODE(o1_fillRect),
- /* 34 */
- OPCODE(o1_drawLine),
- OPCODE(o1_strToLong),
- OPCODE(o1_invalidate),
- OPCODE(o1_setBackDelta),
- /* 38 */
- OPCODE(o1_playSound),
- OPCODE(o2_stopSound),
- OPCODE(o2_loadSound),
- OPCODE(o1_freeSoundSlot),
- /* 3C */
- OPCODE(o1_waitEndPlay),
- OPCODE(o1_playComposition),
- OPCODE(o2_getFreeMem),
- OPCODE(o2_checkData),
- /* 40 */
- {0, ""},
- OPCODE(o1_prepareStr),
- OPCODE(o1_insertStr),
- OPCODE(o1_cutStr),
- /* 44 */
- OPCODE(o1_strstr),
- OPCODE(o5_istrlen),
- OPCODE(o1_setMousePos),
- OPCODE(o1_setFrameRate),
- /* 48 */
- OPCODE(o1_animatePalette),
- OPCODE(o1_animateCursor),
- OPCODE(o1_blitCursor),
- OPCODE(o1_loadFont),
- /* 4C */
- OPCODE(o1_freeFont),
- OPCODE(o2_readData),
- OPCODE(o2_writeData),
- OPCODE(o1_manageDataFile),
- };
-
- static const OpcodeGoblinEntryV5 opcodesGoblin[71] = {
- /* 00 */
- OPCODE(o5_spaceShooter),
- OPCODE(o5_getSystemCDSpeed),
- OPCODE(o5_getSystemRAM),
- OPCODE(o5_getSystemCPUSpeed),
- /* 04 */
- OPCODE(o5_getSystemDrawSpeed),
- OPCODE(o5_totalSystemSpecs),
- OPCODE(o5_saveSystemSpecs),
- OPCODE(o5_loadSystemSpecs),
- /* 08 */
- OPCODE(o5_gob92),
- OPCODE(o5_gob95),
- OPCODE(o5_gob96),
- OPCODE(o5_gob97),
- /* 0C */
- OPCODE(o5_gob98),
- OPCODE(o5_gob100),
- OPCODE(o5_gob200),
- {0, ""},
- /* 10 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 14 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 18 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 1C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 20 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 24 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 34 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 38 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 3C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 40 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 44 */
- {0, ""},
- {0, ""},
- {0, ""},
- };
-
- _opcodesDrawV5 = opcodesDraw;
- _opcodesFuncV5 = opcodesFunc;
- _opcodesGoblinV5 = opcodesGoblin;
-}
-
-void Inter_v5::executeDrawOpcode(byte i) {
- debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)",
- i, i, getOpcodeDrawDesc(i));
-
- OpcodeDrawProcV5 op = _opcodesDrawV5[i].proc;
+void Inter_v5::setupOpcodesDraw() {
+ Inter_v4::setupOpcodesDraw();
- if (op == 0)
- warning("unimplemented opcodeDraw: %d", i);
- else
- (this->*op) ();
+ OPCODEDRAW(0x61, o5_deleteFile);
+ OPCODEDRAW(0x80, o5_initScreen);
}
-bool Inter_v5::executeFuncOpcode(byte i, byte j, OpFuncParams &params) {
- debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s) - %s, %d, %d",
- i, j, i, j, getOpcodeFuncDesc(i, j), _vm->_game->_curTotFile,
- (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData),
- (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData - params.counter - 4));
-
- if ((i > 4) || (j > 15)) {
- warning("unimplemented opcodeFunc: %d.%d", i, j);
- return false;
- }
+void Inter_v5::setupOpcodesFunc() {
+ Inter_v4::setupOpcodesFunc();
- OpcodeFuncProcV5 op = _opcodesFuncV5[i*16 + j].proc;
-
- if (op == 0)
- warning("unimplemented opcodeFunc: %d.%d", i, j);
- else
- return (this->*op) (params);
-
- return false;
-}
-
-void Inter_v5::executeGoblinOpcode(int i, OpGobParams &params) {
- debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)",
- i, i, getOpcodeGoblinDesc(i));
-
- OpcodeGoblinProcV5 op = 0;
-
- for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
- if (_goblinFuncLookUp[j][0] == i) {
- op = _opcodesGoblinV5[_goblinFuncLookUp[j][1]].proc;
- break;
- }
-
- _vm->_global->_inter_execPtr -= 2;
-
- if (op == 0) {
- warning("unimplemented opcodeGoblin: %d", i);
-
- int16 paramCount = load16();
- _vm->_global->_inter_execPtr += paramCount * 2;
- } else {
- params.extraData = i;
-
- (this->*op) (params);
- }
+ OPCODEFUNC(0x45, o5_istrlen);
}
-const char *Inter_v5::getOpcodeDrawDesc(byte i) {
- return _opcodesDrawV5[i].desc;
-}
-
-const char *Inter_v5::getOpcodeFuncDesc(byte i, byte j) {
- if ((i > 4) || (j > 15))
- return "";
-
- return _opcodesFuncV5[i*16 + j].desc;
-}
-
-const char *Inter_v5::getOpcodeGoblinDesc(int i) {
- for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
- if (_goblinFuncLookUp[j][0] == i)
- return _opcodesGoblinV5[_goblinFuncLookUp[j][1]].desc;
- return "";
+void Inter_v5::setupOpcodesGob() {
+ OPCODEGOB( 0, o5_spaceShooter);
+ OPCODEGOB( 1, o5_spaceShooter);
+ OPCODEGOB( 2, o5_spaceShooter);
+ OPCODEGOB( 3, o5_spaceShooter);
+
+ OPCODEGOB( 33, o5_spaceShooter);
+
+ OPCODEGOB( 80, o5_getSystemCDSpeed);
+ OPCODEGOB( 81, o5_getSystemRAM);
+ OPCODEGOB( 82, o5_getSystemCPUSpeed);
+ OPCODEGOB( 83, o5_getSystemDrawSpeed);
+ OPCODEGOB( 84, o5_totalSystemSpecs);
+
+ OPCODEGOB( 85, o5_saveSystemSpecs);
+ OPCODEGOB( 86, o5_loadSystemSpecs);
+
+ OPCODEGOB( 87, o5_spaceShooter);
+ OPCODEGOB( 88, o5_spaceShooter);
+ OPCODEGOB( 89, o5_spaceShooter);
+ OPCODEGOB( 90, o5_spaceShooter);
+
+ OPCODEGOB( 91, o5_spaceShooter);
+ OPCODEGOB( 92, o5_gob92);
+ OPCODEGOB( 93, o5_spaceShooter);
+ OPCODEGOB( 94, o5_spaceShooter);
+
+ OPCODEGOB( 95, o5_gob95);
+ OPCODEGOB( 96, o5_gob96);
+ OPCODEGOB( 97, o5_gob97);
+ OPCODEGOB( 98, o5_gob98);
+
+ OPCODEGOB( 99, o5_spaceShooter);
+ OPCODEGOB(100, o5_gob100);
+ OPCODEGOB(200, o5_gob200);
}
void Inter_v5::o5_deleteFile() {
- evalExpr(0);
+ _vm->_game->_script->evalExpr(0);
- warning("Dynasty Stub: deleteFile \"%s\"", _vm->_global->_inter_resStr);
+ warning("Dynasty Stub: deleteFile \"%s\"", _vm->_game->_script->getResultStr());
}
void Inter_v5::o5_initScreen() {
@@ -683,13 +104,13 @@ void Inter_v5::o5_initScreen() {
int16 videoMode;
int16 width, height;
- offY = load16();
+ offY = _vm->_game->_script->readInt16();
videoMode = offY & 0xFF;
offY = (offY >> 8) & 0xFF;
- width = _vm->_parse->parseValExpr();
- height = _vm->_parse->parseValExpr();
+ width = _vm->_game->_script->readValExpr();
+ height = _vm->_game->_script->readValExpr();
warning("initScreen: %d, %d, %d, %d", width, height, offY, videoMode);
@@ -784,18 +205,18 @@ bool Inter_v5::o5_istrlen(OpFuncParams &params) {
int16 len;
uint16 type;
- if (*_vm->_global->_inter_execPtr == 0x80) {
- _vm->_global->_inter_execPtr++;
+ if (_vm->_game->_script->peekByte() == 0x80) {
+ _vm->_game->_script->skip(1);
- strVar1 = _vm->_parse->parseVarIndex();
- strVar2 = _vm->_parse->parseVarIndex(0, &type);
+ strVar1 = _vm->_game->_script->readVarIndex();
+ strVar2 = _vm->_game->_script->readVarIndex(0, &type);
len = _vm->_draw->stringLength(GET_VARO_STR(strVar1), READ_VARO_UINT16(strVar2));
} else {
- strVar1 = _vm->_parse->parseVarIndex();
- strVar2 = _vm->_parse->parseVarIndex(0, &type);
+ strVar1 = _vm->_game->_script->readVarIndex();
+ strVar2 = _vm->_game->_script->readVarIndex(0, &type);
if (_vm->_global->_language == 10) {
// Extra handling for Japanese strings
@@ -814,40 +235,36 @@ bool Inter_v5::o5_istrlen(OpFuncParams &params) {
}
void Inter_v5::o5_spaceShooter(OpGobParams &params) {
- int16 paramCount = load16();
-
warning("Dynasty Stub: Space shooter: %d, %d, %s",
- params.extraData, paramCount, _vm->_game->_curTotFile);
+ params.extraData, params.paramCount, _vm->_game->_curTotFile);
- if (paramCount < 4) {
+ if (params.paramCount < 4) {
warning("Space shooter variable counter < 4");
- _vm->_global->_inter_execPtr += paramCount * 2;
+ _vm->_game->_script->skip(params.paramCount * 2);
return;
}
- uint32 var1 = load16() * 4;
- uint32 var2 = load16() * 4;
+ uint32 var1 = _vm->_game->_script->readInt16() * 4;
+ uint32 var2 = _vm->_game->_script->readInt16() * 4;
- load16();
- load16();
+ _vm->_game->_script->readInt16();
+ _vm->_game->_script->readInt16();
if (params.extraData != 0) {
WRITE_VARO_UINT32(var1, 2);
WRITE_VARO_UINT32(var2, 0);
} else {
- if (paramCount < 5) {
+ if (params.paramCount < 5) {
warning("Space shooter variable counter < 5");
return;
}
- _vm->_global->_inter_execPtr += (paramCount - 4) * 2;
+ _vm->_game->_script->skip((params.paramCount - 4) * 2);
}
}
void Inter_v5::o5_getSystemCDSpeed(OpGobParams &params) {
- _vm->_global->_inter_execPtr += 2;
-
- WRITE_VAR_UINT32(load16(), 100); // Fudging 100%
+ WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100%
Video::FontDesc *font;
if ((font = _vm->_util->loadFont("SPEED.LET"))) {
@@ -859,9 +276,7 @@ void Inter_v5::o5_getSystemCDSpeed(OpGobParams &params) {
}
void Inter_v5::o5_getSystemRAM(OpGobParams &params) {
- _vm->_global->_inter_execPtr += 2;
-
- WRITE_VAR_UINT32(load16(), 100); // Fudging 100%
+ WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100%
Video::FontDesc *font;
if ((font = _vm->_util->loadFont("SPEED.LET"))) {
@@ -873,9 +288,7 @@ void Inter_v5::o5_getSystemRAM(OpGobParams &params) {
}
void Inter_v5::o5_getSystemCPUSpeed(OpGobParams &params) {
- _vm->_global->_inter_execPtr += 2;
-
- WRITE_VAR_UINT32(load16(), 100); // Fudging 100%
+ WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100%
Video::FontDesc *font;
if ((font = _vm->_util->loadFont("SPEED.LET"))) {
@@ -887,9 +300,7 @@ void Inter_v5::o5_getSystemCPUSpeed(OpGobParams &params) {
}
void Inter_v5::o5_getSystemDrawSpeed(OpGobParams &params) {
- _vm->_global->_inter_execPtr += 2;
-
- WRITE_VAR_UINT32(load16(), 100); // Fudging 100%
+ WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100%
Video::FontDesc *font;
if ((font = _vm->_util->loadFont("SPEED.LET"))) {
@@ -901,9 +312,7 @@ void Inter_v5::o5_getSystemDrawSpeed(OpGobParams &params) {
}
void Inter_v5::o5_totalSystemSpecs(OpGobParams &params) {
- _vm->_global->_inter_execPtr += 2;
-
- WRITE_VAR_UINT32(load16(), 100); // Fudging 100%
+ WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100%
Video::FontDesc *font;
if ((font = _vm->_util->loadFont("SPEED.LET"))) {
@@ -917,8 +326,6 @@ void Inter_v5::o5_totalSystemSpecs(OpGobParams &params) {
void Inter_v5::o5_saveSystemSpecs(OpGobParams &params) {
warning("Dynasty Stub: Saving system specifications");
- _vm->_global->_inter_execPtr += 2;
-
/*
FILE *f = fopen("SAVE\\SPEED.INF", w);
fwrite(&_cdSpeed, sizeof(_cdSpeed), 1, f);
@@ -933,8 +340,6 @@ void Inter_v5::o5_saveSystemSpecs(OpGobParams &params) {
void Inter_v5::o5_loadSystemSpecs(OpGobParams &params) {
warning("Dynasty Stub: Loading system specifications");
- _vm->_global->_inter_execPtr += 2;
-
/*
FILE *f = fopen("SAVE\\SPEED.INF", r);
fread(&_cdSpeed, sizeof(_cdSpeed), 1, f);
@@ -971,32 +376,26 @@ void Inter_v5::o5_loadSystemSpecs(OpGobParams &params) {
void Inter_v5::o5_gob92(OpGobParams &params) {
warning("Dynasty Stub: GobFunc 92");
- _vm->_global->_inter_execPtr += 2;
-
- WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int8) _gob92_1)) */);
+ WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 0 /* (uint32) ((int32) ((int8) _gob92_1)) */);
}
void Inter_v5::o5_gob95(OpGobParams &params) {
warning("Dynasty Stub: GobFunc 95");
- _vm->_global->_inter_execPtr += 2;
-
- WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int16) speedThrottle4)) */);
- WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int8) speedThrottle3)) */);
- WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int8) speedThrottle2)) */);
- WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int16) speedThrottle1)) */);
+ WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 0 /* (uint32) ((int32) ((int16) speedThrottle4)) */);
+ WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 0 /* (uint32) ((int32) ((int8) speedThrottle3)) */);
+ WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 0 /* (uint32) ((int32) ((int8) speedThrottle2)) */);
+ WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 0 /* (uint32) ((int32) ((int16) speedThrottle1)) */);
}
void Inter_v5::o5_gob96(OpGobParams &params) {
int16 speedThrottle4, speedThrottle1;
byte speedThrottle3, speedThrottle2;
- _vm->_global->_inter_execPtr += 2;
-
- speedThrottle4 = READ_VAR_UINT16(load16());
- speedThrottle3 = READ_VAR_UINT8(load16());
- speedThrottle2 = READ_VAR_UINT8(load16());
- speedThrottle1 = READ_VAR_UINT16(load16());
+ speedThrottle4 = READ_VAR_UINT16(_vm->_game->_script->readInt16());
+ speedThrottle3 = READ_VAR_UINT8(_vm->_game->_script->readInt16());
+ speedThrottle2 = READ_VAR_UINT8(_vm->_game->_script->readInt16());
+ speedThrottle1 = READ_VAR_UINT16(_vm->_game->_script->readInt16());
warning("Dynasty Stub: GobFunc 96: %d, %d, %d, %d",
speedThrottle4, speedThrottle3, speedThrottle2, speedThrottle1);
@@ -1006,23 +405,17 @@ void Inter_v5::o5_gob96(OpGobParams &params) {
void Inter_v5::o5_gob97(OpGobParams &params) {
_gob_97_98_val = 1;
-
- _vm->_global->_inter_execPtr += 2;
}
void Inter_v5::o5_gob98(OpGobParams &params) {
_gob_97_98_val = 0;
-
- _vm->_global->_inter_execPtr += 2;
}
void Inter_v5::o5_gob100(OpGobParams &params) {
- _vm->_global->_inter_execPtr += 2;
-
- uint16 var1 = READ_VAR_UINT16(load16());
- uint16 var2 = READ_VAR_UINT16(load16());
- uint16 var3 = READ_VAR_UINT16(load16());
- uint16 var4 = READ_VAR_UINT16(load16());
+ uint16 var1 = READ_VAR_UINT16(_vm->_game->_script->readInt16());
+ uint16 var2 = READ_VAR_UINT16(_vm->_game->_script->readInt16());
+ uint16 var3 = READ_VAR_UINT16(_vm->_game->_script->readInt16());
+ uint16 var4 = READ_VAR_UINT16(_vm->_game->_script->readInt16());
warning("Dynasty Stub: GobFunc 100: %d, %d, %d, %d", var1, var2, var3, var4);
@@ -1031,11 +424,9 @@ void Inter_v5::o5_gob100(OpGobParams &params) {
}
void Inter_v5::o5_gob200(OpGobParams &params) {
- _vm->_global->_inter_execPtr += 2;
-
- uint16 var1 = load16(); // index into the spritesArray
- uint16 var2 = load16();
- uint16 var3 = load16();
+ uint16 var1 = _vm->_game->_script->readUint16(); // index into the spritesArray
+ uint16 var2 = _vm->_game->_script->readUint16();
+ uint16 var3 = _vm->_game->_script->readUint16();
warning("Dynasty Stub: GobFunc 200: %d, %d, %d", var1, var2, var3);
}
diff --git a/engines/gob/inter_v6.cpp b/engines/gob/inter_v6.cpp
index f40314f87e..506de821d4 100644
--- a/engines/gob/inter_v6.cpp
+++ b/engines/gob/inter_v6.cpp
@@ -32,626 +32,43 @@
#include "gob/helper.h"
#include "gob/global.h"
#include "gob/game.h"
-#include "gob/parse.h"
+#include "gob/expression.h"
+#include "gob/script.h"
+#include "gob/resources.h"
#include "gob/draw.h"
#include "gob/sound/sound.h"
#include "gob/videoplayer.h"
namespace Gob {
-#define OPCODE(x) _OPCODE(Inter_v6, x)
-
-const int Inter_v6::_goblinFuncLookUp[][2] = {
- {0, 0},
-};
+#define OPCODEVER Inter_v6
+#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x)
+#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x)
+#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x)
Inter_v6::Inter_v6(GobEngine *vm) : Inter_v5(vm) {
_gotFirstPalette = false;
-
- setupOpcodes();
-}
-
-void Inter_v6::setupOpcodes() {
- static const OpcodeDrawEntryV6 opcodesDraw[256] = {
- /* 00 */
- OPCODE(o1_loadMult),
- OPCODE(o2_playMult),
- OPCODE(o2_freeMultKeys),
- {0, ""},
- /* 04 */
- {0, ""},
- {0, ""},
- {0, ""},
- OPCODE(o1_initCursor),
- /* 08 */
- OPCODE(o1_initCursorAnim),
- OPCODE(o1_clearCursorAnim),
- OPCODE(o2_setRenderFlags),
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- OPCODE(o1_loadAnim),
- OPCODE(o1_freeAnim),
- OPCODE(o1_updateAnim),
- OPCODE(o2_multSub),
- /* 14 */
- OPCODE(o2_initMult),
- OPCODE(o1_freeMult),
- OPCODE(o1_animate),
- OPCODE(o2_loadMultObject),
- /* 18 */
- OPCODE(o1_getAnimLayerInfo),
- OPCODE(o1_getObjAnimSize),
- OPCODE(o1_loadStatic),
- OPCODE(o1_freeStatic),
- /* 1C */
- OPCODE(o2_renderStatic),
- OPCODE(o2_loadCurLayer),
- {0, ""},
- {0, ""},
- /* 20 */
- OPCODE(o2_playCDTrack),
- OPCODE(o2_waitCDTrackEnd),
- OPCODE(o2_stopCD),
- OPCODE(o2_readLIC),
- /* 24 */
- OPCODE(o2_freeLIC),
- OPCODE(o2_getCDTrackPos),
- {0, ""},
- {0, ""},
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- OPCODE(o2_loadFontToSprite),
- OPCODE(o1_freeFontToSprite),
- {0, ""},
- {0, ""},
- /* 34 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 38 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 3C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 40 */
- OPCODE(o6_totSub),
- OPCODE(o2_switchTotSub),
- OPCODE(o2_pushVars),
- OPCODE(o2_popVars),
- /* 44 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 48 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 4C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 50 */
- OPCODE(o2_loadMapObjects),
- OPCODE(o2_freeGoblins),
- OPCODE(o2_moveGoblin),
- OPCODE(o2_writeGoblinPos),
- /* 54 */
- OPCODE(o2_stopGoblin),
- OPCODE(o2_setGoblinState),
- OPCODE(o2_placeGoblin),
- {0, ""},
- /* 58 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 5C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 60 */
- {0, ""},
- OPCODE(o5_deleteFile),
- {0, ""},
- {0, ""},
- /* 64 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 68 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 6C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 70 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 74 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 78 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 7C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 80 */
- OPCODE(o5_initScreen),
- OPCODE(o2_scroll),
- OPCODE(o2_setScrollOffset),
- OPCODE(o6_playVmdOrMusic),
- /* 84 */
- OPCODE(o2_getImdInfo),
- OPCODE(o6_openItk),
- OPCODE(o2_closeItk),
- OPCODE(o2_setImdFrontSurf),
- /* 88 */
- OPCODE(o2_resetImdFrontSurf),
- {0, ""},
- {0, ""},
- {0, ""},
- /* 8C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 90 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 94 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 98 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 9C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* A8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* AC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* B8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* BC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* C8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* CC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* D8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* DC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* E8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* EC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F0 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F4 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* F8 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* FC */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""}
- };
-
- static const OpcodeFuncEntryV6 opcodesFunc[80] = {
- /* 00 */
- OPCODE(o1_callSub),
- OPCODE(o1_callSub),
- OPCODE(o1_printTotText),
- OPCODE(o6_loadCursor),
- /* 04 */
- {0, ""},
- OPCODE(o1_switch),
- OPCODE(o1_repeatUntil),
- OPCODE(o1_whileDo),
- /* 08 */
- OPCODE(o1_if),
- OPCODE(o6_assign),
- OPCODE(o1_loadSpriteToPos),
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- {0, ""},
- OPCODE(o2_printText),
- OPCODE(o1_loadTot),
- OPCODE(o6_palLoad),
- /* 14 */
- OPCODE(o1_keyFunc),
- OPCODE(o1_capturePush),
- OPCODE(o1_capturePop),
- OPCODE(o2_animPalInit),
- /* 18 */
- OPCODE(o2_addCollision),
- OPCODE(o6_freeCollision),
- OPCODE(o3_getTotTextItemPart),
- {0, ""},
- /* 1C */
- {0, ""},
- {0, ""},
- OPCODE(o1_drawOperations),
- OPCODE(o1_setcmdCount),
- /* 20 */
- OPCODE(o1_return),
- OPCODE(o1_renewTimeInVars),
- OPCODE(o1_speakerOn),
- OPCODE(o1_speakerOff),
- /* 24 */
- OPCODE(o1_putPixel),
- OPCODE(o2_goblinFunc),
- OPCODE(o1_createSprite),
- OPCODE(o1_freeSprite),
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- OPCODE(o1_returnTo),
- OPCODE(o1_loadSpriteContent),
- OPCODE(o1_copySprite),
- OPCODE(o6_fillRect),
- /* 34 */
- OPCODE(o1_drawLine),
- OPCODE(o1_strToLong),
- OPCODE(o1_invalidate),
- OPCODE(o1_setBackDelta),
- /* 38 */
- OPCODE(o1_playSound),
- OPCODE(o2_stopSound),
- OPCODE(o2_loadSound),
- OPCODE(o1_freeSoundSlot),
- /* 3C */
- OPCODE(o1_waitEndPlay),
- OPCODE(o1_playComposition),
- OPCODE(o2_getFreeMem),
- OPCODE(o2_checkData),
- /* 40 */
- {0, ""},
- OPCODE(o1_prepareStr),
- OPCODE(o1_insertStr),
- OPCODE(o1_cutStr),
- /* 44 */
- OPCODE(o1_strstr),
- OPCODE(o5_istrlen),
- OPCODE(o1_setMousePos),
- OPCODE(o1_setFrameRate),
- /* 48 */
- OPCODE(o1_animatePalette),
- OPCODE(o1_animateCursor),
- OPCODE(o1_blitCursor),
- OPCODE(o1_loadFont),
- /* 4C */
- OPCODE(o1_freeFont),
- OPCODE(o2_readData),
- OPCODE(o2_writeData),
- OPCODE(o1_manageDataFile),
- };
-
- static const OpcodeGoblinEntryV6 opcodesGoblin[71] = {
- /* 00 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 04 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 08 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 0C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 10 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 14 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 18 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 1C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 20 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 24 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 28 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 2C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 30 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 34 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 38 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 3C */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 40 */
- {0, ""},
- {0, ""},
- {0, ""},
- {0, ""},
- /* 44 */
- {0, ""},
- {0, ""},
- {0, ""},
- };
-
- _opcodesDrawV6 = opcodesDraw;
- _opcodesFuncV6 = opcodesFunc;
- _opcodesGoblinV6 = opcodesGoblin;
-}
-
-void Inter_v6::executeDrawOpcode(byte i) {
- debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)",
- i, i, getOpcodeDrawDesc(i));
-
- OpcodeDrawProcV6 op = _opcodesDrawV6[i].proc;
-
- if (op == 0)
- warning("unimplemented opcodeDraw: %d", i);
- else
- (this->*op) ();
-}
-
-bool Inter_v6::executeFuncOpcode(byte i, byte j, OpFuncParams &params) {
- _vm->_video->_palLUT->buildNext();
-
- debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s) - %s, %d, %d",
- i, j, i, j, getOpcodeFuncDesc(i, j), _vm->_game->_curTotFile,
- (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData),
- (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData - params.counter - 4));
-
- if ((i > 4) || (j > 15)) {
- warning("unimplemented opcodeFunc: %d.%d", i, j);
- return false;
- }
-
- OpcodeFuncProcV6 op = _opcodesFuncV6[i*16 + j].proc;
-
- if (op == 0)
- warning("unimplemented opcodeFunc: %d.%d", i, j);
- else
- return (this->*op) (params);
-
- return false;
}
-void Inter_v6::executeGoblinOpcode(int i, OpGobParams &params) {
- debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)",
- i, i, getOpcodeGoblinDesc(i));
-
- OpcodeGoblinProcV6 op = 0;
-
- for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
- if (_goblinFuncLookUp[j][0] == i) {
- op = _opcodesGoblinV6[_goblinFuncLookUp[j][1]].proc;
- break;
- }
-
- _vm->_global->_inter_execPtr -= 2;
-
- if (op == 0) {
- warning("unimplemented opcodeGoblin: %d", i);
-
- int16 paramCount = load16();
- _vm->_global->_inter_execPtr += paramCount * 2;
- } else {
- params.extraData = i;
+void Inter_v6::setupOpcodesDraw() {
+ Inter_v5::setupOpcodesDraw();
- (this->*op) (params);
- }
-}
-
-const char *Inter_v6::getOpcodeDrawDesc(byte i) {
- return _opcodesDrawV6[i].desc;
+ OPCODEDRAW(0x40, o6_totSub);
+ OPCODEDRAW(0x83, o6_playVmdOrMusic);
+ OPCODEDRAW(0x85, o6_openItk);
}
-const char *Inter_v6::getOpcodeFuncDesc(byte i, byte j) {
- if ((i > 4) || (j > 15))
- return "";
+void Inter_v6::setupOpcodesFunc() {
+ Inter_v5::setupOpcodesFunc();
- return _opcodesFuncV6[i*16 + j].desc;
+ OPCODEFUNC(0x03, o6_loadCursor);
+ OPCODEFUNC(0x09, o6_assign);
+ OPCODEFUNC(0x13, o6_palLoad);
+ OPCODEFUNC(0x19, o6_freeCollision);
+ OPCODEFUNC(0x33, o6_fillRect);
}
-const char *Inter_v6::getOpcodeGoblinDesc(int i) {
- for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
- if (_goblinFuncLookUp[j][0] == i)
- return _opcodesGoblinV6[_goblinFuncLookUp[j][1]].desc;
- return "";
+void Inter_v6::setupOpcodesGob() {
}
void Inter_v6::o6_totSub() {
@@ -660,20 +77,20 @@ void Inter_v6::o6_totSub() {
int flags;
int i;
- length = *_vm->_global->_inter_execPtr++;
+ length = _vm->_game->_script->readByte();
if ((length & 0x7F) > 13)
error("Length in o2_totSub is greater than 13 (%d)", length);
if (length & 0x80) {
- evalExpr(0);
- strcpy(totFile, _vm->_global->_inter_resStr);
+ _vm->_game->_script->evalExpr(0);
+ strcpy(totFile, _vm->_game->_script->getResultStr());
} else {
for (i = 0; i < length; i++)
- totFile[i] = (char) *_vm->_global->_inter_execPtr++;
+ totFile[i] = _vm->_game->_script->readChar();
totFile[i] = 0;
}
- flags = *_vm->_global->_inter_execPtr++;
+ flags = _vm->_game->_script->readByte();
if (flags & 0x40)
warning("Urban Stub: o6_totSub(), flags & 0x40");
@@ -693,17 +110,17 @@ void Inter_v6::o6_playVmdOrMusic() {
uint16 palCmd;
bool close;
- evalExpr(0);
- strncpy0(fileName, _vm->_global->_inter_resStr, 127);
-
- x = _vm->_parse->parseValExpr();
- y = _vm->_parse->parseValExpr();
- startFrame = _vm->_parse->parseValExpr();
- lastFrame = _vm->_parse->parseValExpr();
- breakKey = _vm->_parse->parseValExpr();
- flags = _vm->_parse->parseValExpr();
- palStart = _vm->_parse->parseValExpr();
- palEnd = _vm->_parse->parseValExpr();
+ _vm->_game->_script->evalExpr(0);
+ strncpy0(fileName, _vm->_game->_script->getResultStr(), 127);
+
+ x = _vm->_game->_script->readValExpr();
+ y = _vm->_game->_script->readValExpr();
+ startFrame = _vm->_game->_script->readValExpr();
+ lastFrame = _vm->_game->_script->readValExpr();
+ breakKey = _vm->_game->_script->readValExpr();
+ flags = _vm->_game->_script->readValExpr();
+ palStart = _vm->_game->_script->readValExpr();
+ palEnd = _vm->_game->_script->readValExpr();
palCmd = 1 << (flags & 0x3F);
debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, "
@@ -759,8 +176,8 @@ void Inter_v6::o6_playVmdOrMusic() {
void Inter_v6::o6_openItk() {
char fileName[32];
- evalExpr(0);
- strncpy0(fileName, _vm->_global->_inter_resStr, 27);
+ _vm->_game->_script->evalExpr(0);
+ strncpy0(fileName, _vm->_game->_script->getResultStr(), 27);
if (!strchr(fileName, '.'))
strcat(fileName, ".ITK");
@@ -778,21 +195,21 @@ void Inter_v6::o6_openItk() {
}
bool Inter_v6::o6_loadCursor(OpFuncParams &params) {
- int16 id = load16();
+ int16 id = _vm->_game->_script->readInt16();
if ((id == -1) || (id == -2)) {
char file[10];
if (id == -1) {
for (int i = 0; i < 9; i++)
- file[i] = *_vm->_global->_inter_execPtr++;
+ file[i] = _vm->_game->_script->readChar();
} else
- strncpy(file, GET_VAR_STR(load16()), 10);
+ strncpy(file, GET_VAR_STR(_vm->_game->_script->readInt16()), 10);
file[9] = '\0';
- uint16 start = load16();
- int8 index = (int8) *_vm->_global->_inter_execPtr++;
+ uint16 start = _vm->_game->_script->readUint16();
+ int8 index = _vm->_game->_script->readInt8();
int vmdSlot = _vm->_vidPlayer->slotOpen(file);
@@ -820,101 +237,102 @@ bool Inter_v6::o6_loadCursor(OpFuncParams &params) {
return false;
}
- int8 index = (int8) *_vm->_global->_inter_execPtr++;
+ int8 index = _vm->_game->_script->readInt8();
if ((index * _vm->_draw->_cursorWidth) >= _vm->_draw->_cursorSprites->getWidth())
return false;
- int16 width, height;
- byte *dataBuf = _vm->_game->loadTotResource(id, 0, &width, &height);
+ Resource *resource = _vm->_game->_resources->getResource((uint16) id);
+ if (!resource)
+ return false;
_vm->_video->fillRect(*_vm->_draw->_cursorSprites,
index * _vm->_draw->_cursorWidth, 0,
index * _vm->_draw->_cursorWidth + _vm->_draw->_cursorWidth - 1,
_vm->_draw->_cursorHeight - 1, 0);
- _vm->_video->drawPackedSprite(dataBuf, width, height,
+ _vm->_video->drawPackedSprite(resource->getData(),
+ resource->getWidth(), resource->getHeight(),
index * _vm->_draw->_cursorWidth, 0, 0, *_vm->_draw->_cursorSprites);
_vm->_draw->_cursorAnimLow[index] = 0;
+ delete resource;
return false;
}
bool Inter_v6::o6_assign(OpFuncParams &params) {
- byte *savedPos;
- int16 varOff;
- int16 token;
- int16 result;
- byte loopCount;
- uint16 var_6, var_A;
+ uint16 size, destType;
+ int16 dest = _vm->_game->_script->readVarIndex(&size, &destType);
- varOff = _vm->_parse->parseVarIndex(&var_6, &var_A);
+ if (size != 0) {
+ int16 src;
- if (var_6 != 0) {
- int16 var_4;
+ _vm->_game->_script->push();
- savedPos = _vm->_global->_inter_execPtr;
+ src = _vm->_game->_script->readVarIndex(&size, 0);
- var_4 = _vm->_parse->parseVarIndex(&var_6, 0);
+ memcpy(_vm->_inter->_variables->getAddressOff8(dest),
+ _vm->_inter->_variables->getAddressOff8(src), size * 4);
- memcpy(_vm->_inter->_variables->getAddressOff8(varOff),
- _vm->_inter->_variables->getAddressOff8(var_4), var_6 * 4);
+ _vm->_game->_script->pop();
- _vm->_global->_inter_execPtr = savedPos;
- evalExpr(&var_4);
+ _vm->_game->_script->evalExpr(&src);
return false;
}
- if (*_vm->_global->_inter_execPtr == 98) {
- _vm->_global->_inter_execPtr++;
- loopCount = *_vm->_global->_inter_execPtr++;
+ byte loopCount;
+ if (_vm->_game->_script->peekByte() == 98) {
+ _vm->_game->_script->skip(1);
+ loopCount = _vm->_game->_script->readByte();
for (int i = 0; i < loopCount; i++) {
- uint8 c = *_vm->_global->_inter_execPtr++;
- uint16 n = load16();
+ uint8 c = _vm->_game->_script->readByte();
+ uint16 n = _vm->_game->_script->readUint16();
- memset(_vm->_inter->_variables->getAddressOff8(varOff), c, n);
+ memset(_vm->_inter->_variables->getAddressOff8(dest), c, n);
- varOff += n;
+ dest += n;
}
return false;
- } else if (*_vm->_global->_inter_execPtr == 99) {
- _vm->_global->_inter_execPtr++;
- loopCount = *_vm->_global->_inter_execPtr++;
+ } else if (_vm->_game->_script->peekByte() == 99) {
+ _vm->_game->_script->skip(1);
+ loopCount = _vm->_game->_script->readByte();
} else
loopCount = 1;
for (int i = 0; i < loopCount; i++) {
- token = evalExpr(&result);
- switch (var_A) {
- case 16:
- case 18:
- WRITE_VARO_UINT8(varOff + i, _vm->_global->_inter_resVal);
+ int16 result;
+ int16 srcType = _vm->_game->_script->evalExpr(&result);
+
+ switch (destType) {
+ case TYPE_VAR_INT8:
+ case TYPE_ARRAY_INT8:
+ WRITE_VARO_UINT8(dest + i, _vm->_game->_script->getResultInt());
break;
- case 17:
- case 27:
- WRITE_VARO_UINT16(varOff + i * 2, _vm->_global->_inter_resVal);
+ case TYPE_VAR_INT16:
+ case TYPE_ARRAY_INT16:
+ WRITE_VARO_UINT16(dest + i * 2, _vm->_game->_script->getResultInt());
break;
- case 23:
- case 26:
- WRITE_VAR_OFFSET(varOff + i * 4, _vm->_global->_inter_resVal);
+ case TYPE_VAR_INT32:
+ case TYPE_ARRAY_INT32:
+ WRITE_VAR_OFFSET(dest + i * 4, _vm->_game->_script->getResultInt());
break;
- case 24:
- WRITE_VARO_UINT16(varOff + i * 4, _vm->_global->_inter_resVal);
+ case TYPE_VAR_INT32_AS_INT16:
+ WRITE_VARO_UINT16(dest + i * 4, _vm->_game->_script->getResultInt());
break;
- case 25:
- case 28:
- if (token == 20)
- WRITE_VARO_UINT8(varOff, result);
+ case TYPE_VAR_STR:
+ case TYPE_ARRAY_STR:
+ if (srcType == TYPE_IMM_INT16)
+ WRITE_VARO_UINT8(dest, result);
else
- WRITE_VARO_STR(varOff, _vm->_global->_inter_resStr);
+ WRITE_VARO_STR(dest, _vm->_game->_script->getResultStr());
break;
}
}
@@ -936,7 +354,7 @@ bool Inter_v6::o6_palLoad(OpFuncParams &params) {
bool Inter_v6::o6_freeCollision(OpFuncParams &params) {
int16 id;
- id = _vm->_parse->parseValExpr();
+ id = _vm->_game->_script->readValExpr();
switch (id + 5) {
case 0:
@@ -972,17 +390,17 @@ bool Inter_v6::o6_freeCollision(OpFuncParams &params) {
bool Inter_v6::o6_fillRect(OpFuncParams &params) {
int16 destSurf;
- _vm->_draw->_destSurface = destSurf = load16();
+ _vm->_draw->_destSurface = destSurf = _vm->_game->_script->readInt16();
- _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr();
- _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr();
- _vm->_draw->_spriteRight = _vm->_parse->parseValExpr();
- _vm->_draw->_spriteBottom = _vm->_parse->parseValExpr();
+ _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr();
+ _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr();
+ _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr();
+ _vm->_draw->_spriteBottom = _vm->_game->_script->readValExpr();
- evalExpr(0);
+ _vm->_game->_script->evalExpr(0);
- _vm->_draw->_backColor = _vm->_global->_inter_resVal & 0xFFFF;
- uint16 extraVar = _vm->_global->_inter_resVal >> 16;
+ _vm->_draw->_backColor = _vm->_game->_script->getResultInt() & 0xFFFF;
+ uint16 extraVar = _vm->_game->_script->getResultInt() >> 16;
if (extraVar != 0)
warning("Urban Stub: o6_fillRect(), extraVar = %d", extraVar);
@@ -1019,11 +437,8 @@ void Inter_v6::probe16bitMusic(char *fileName) {
fileName[len - 1] = 'V';
- int16 handle;
- if ((handle = _vm->_dataIO->openData(fileName)) >= 0) {
- _vm->_dataIO->closeData(handle);
+ if (_vm->_dataIO->existData(fileName))
return;
- }
fileName[len - 1] = '8';
}
diff --git a/engines/gob/map_v1.cpp b/engines/gob/map_v1.cpp
index 2c94b3fb24..dacc72d6c7 100644
--- a/engines/gob/map_v1.cpp
+++ b/engines/gob/map_v1.cpp
@@ -64,7 +64,6 @@ void Map_v1::init(void) {
void Map_v1::loadMapObjects(const char *avjFile) {
char avoName[128];
byte *dataBuf;
- int16 handle;
int16 tmp;
int32 flag;
int16 gobDataCount;
@@ -75,15 +74,14 @@ void Map_v1::loadMapObjects(const char *avjFile) {
strcpy(avoName, _sourceFile);
strcat(avoName, ".avo");
- handle = _vm->_dataIO->openData(avoName);
- if (handle >= 0) {
+ if (_vm->_dataIO->existData(avoName)) {
_loadFromAvo = true;
- _vm->_dataIO->closeData(handle);
dataBuf = _vm->_dataIO->getData(avoName);
} else {
_loadFromAvo = false;
dataBuf = _vm->_dataIO->getData(avjFile);
}
+
Common::MemoryReadStream mapData(dataBuf, 4294967295U);
init();
@@ -146,7 +144,6 @@ void Map_v1::loadMapObjects(const char *avjFile) {
void Map_v1::loadSounds(Common::SeekableReadStream &data) {
int16 count;
- int16 handle;
char buf[19];
char sndNames[20][14];
@@ -162,11 +159,9 @@ void Map_v1::loadSounds(Common::SeekableReadStream &data) {
_vm->_sound->sampleLoad(&_vm->_goblin->_soundData[14], SOUND_SND, "diamant1.snd");
for (int i = 0; i < count; i++) {
- handle = _vm->_dataIO->openData(sndNames[i]);
- if (handle < 0)
+ if (!_vm->_dataIO->existData(sndNames[i]))
continue;
- _vm->_dataIO->closeData(handle);
_vm->_sound->sampleLoad(&_vm->_goblin->_soundData[i], SOUND_SND, sndNames[i]);
}
}
diff --git a/engines/gob/map_v2.cpp b/engines/gob/map_v2.cpp
index db4f2075e1..6ceda7ab44 100644
--- a/engines/gob/map_v2.cpp
+++ b/engines/gob/map_v2.cpp
@@ -31,7 +31,8 @@
#include "gob/goblin.h"
#include "gob/inter.h"
#include "gob/game.h"
-#include "gob/parse.h"
+#include "gob/script.h"
+#include "gob/resources.h"
#include "gob/mult.h"
namespace Gob {
@@ -51,22 +52,24 @@ void Map_v2::loadMapObjects(const char *avjFile) {
int16 mapWidth, mapHeight;
int16 tmp;
byte *variables;
- byte *extData;
uint32 tmpPos;
uint32 passPos;
- var = _vm->_parse->parseVarIndex();
+ var = _vm->_game->_script->readVarIndex();
variables = _vm->_inter->_variables->getAddressOff8(var);
- id = _vm->_inter->load16();
+ id = _vm->_game->_script->readInt16();
if (id == -1) {
_passMap = (int8 *) _vm->_inter->_variables->getAddressOff8(var);
return;
}
- extData = _vm->_game->loadExtData(id, 0, 0);
- Common::MemoryReadStream mapData(extData, 4294967295U);
+ Resource *resource = _vm->_game->_resources->getResource(id);
+ if (!resource)
+ return;
+
+ Common::SeekableReadStream &mapData = *resource->stream();
if (mapData.readByte() == 3) {
_screenWidth = 640;
@@ -88,7 +91,7 @@ void Map_v2::loadMapObjects(const char *avjFile) {
passPos = mapData.pos();
mapData.skip(_mapWidth * _mapHeight);
- if (*extData == 1)
+ if (resource->getData()[0] == 1)
wayPointsCount = _wayPointsCount = 40;
else
wayPointsCount = _wayPointsCount == 0 ? 1 : _wayPointsCount;
@@ -130,11 +133,11 @@ void Map_v2::loadMapObjects(const char *avjFile) {
for (int i = 0; i < _vm->_goblin->_gobsCount; i++)
loadGoblinStates(mapData, i);
- _vm->_goblin->_soundSlotsCount = _vm->_inter->load16();
+ _vm->_goblin->_soundSlotsCount = _vm->_game->_script->readInt16();
for (int i = 0; i < _vm->_goblin->_soundSlotsCount; i++)
_vm->_goblin->_soundSlots[i] = _vm->_inter->loadSound(1);
- delete[] extData;
+ delete resource;
}
void Map_v2::loadGoblinStates(Common::SeekableReadStream &data, int index) {
diff --git a/engines/gob/map_v4.cpp b/engines/gob/map_v4.cpp
index 858e7972bc..1db3d6a3f8 100644
--- a/engines/gob/map_v4.cpp
+++ b/engines/gob/map_v4.cpp
@@ -31,7 +31,8 @@
#include "gob/goblin.h"
#include "gob/inter.h"
#include "gob/game.h"
-#include "gob/parse.h"
+#include "gob/script.h"
+#include "gob/resources.h"
#include "gob/mult.h"
namespace Gob {
@@ -49,14 +50,13 @@ void Map_v4::loadMapObjects(const char *avjFile) {
int16 mapWidth, mapHeight;
int16 tmp;
byte *variables;
- byte *extData;
uint32 tmpPos;
uint32 passPos;
- var = _vm->_parse->parseVarIndex();
+ var = _vm->_game->_script->readVarIndex();
variables = _vm->_inter->_variables->getAddressOff8(var);
- id = _vm->_inter->load16();
+ id = _vm->_game->_script->readInt16();
if (((uint16) id) >= 65520) {
warning("Woodruff Stub: loadMapObjects ID >= 65520");
@@ -66,8 +66,11 @@ void Map_v4::loadMapObjects(const char *avjFile) {
return;
}
- extData = _vm->_game->loadExtData(id, 0, 0);
- Common::MemoryReadStream mapData(extData, 4294967295U);
+ Resource *resource = _vm->_game->_resources->getResource(id);
+ if (!resource)
+ return;
+
+ Common::SeekableReadStream &mapData = *resource->stream();
_widthByte = mapData.readByte();
if (_widthByte == 4) {
@@ -99,7 +102,7 @@ void Map_v4::loadMapObjects(const char *avjFile) {
passPos = mapData.pos();
mapData.skip(_mapWidth * _mapHeight);
- if (*extData == 1)
+ if (resource->getData()[0] == 1)
wayPointsCount = _wayPointsCount = 40;
else
wayPointsCount = _wayPointsCount == 0 ? 1 : _wayPointsCount;
@@ -146,11 +149,11 @@ void Map_v4::loadMapObjects(const char *avjFile) {
for (int i = 0; i < _vm->_goblin->_gobsCount; i++)
loadGoblinStates(mapData, i);
- _vm->_goblin->_soundSlotsCount = _vm->_inter->load16();
+ _vm->_goblin->_soundSlotsCount = _vm->_game->_script->readInt16();
for (int i = 0; i < _vm->_goblin->_soundSlotsCount; i++)
_vm->_goblin->_soundSlots[i] = _vm->_inter->loadSound(1);
- delete[] extData;
+ delete resource;
}
} // End of namespace Gob
diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index 22a5cd37b9..695976da61 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -9,6 +9,7 @@ MODULE_OBJS := \
draw_bargon.o \
draw_fascin.o \
driver_vga.o \
+ expression.o \
game.o \
game_v1.o \
game_v2.o \
@@ -43,10 +44,12 @@ MODULE_OBJS := \
mult_v1.o \
mult_v2.o \
palanim.o \
- parse.o \
+ resources.o \
scenery.o \
scenery_v1.o \
scenery_v2.o \
+ script.o \
+ totfile.o \
util.o \
variables.o \
video.o \
diff --git a/engines/gob/mult.cpp b/engines/gob/mult.cpp
index 1670c26ea5..5aec5ff76e 100644
--- a/engines/gob/mult.cpp
+++ b/engines/gob/mult.cpp
@@ -31,6 +31,7 @@
#include "gob/util.h"
#include "gob/draw.h"
#include "gob/game.h"
+#include "gob/script.h"
#include "gob/palanim.h"
#include "gob/scenery.h"
#include "gob/video.h"
@@ -251,8 +252,6 @@ void Mult::playMult(int16 startFrame, int16 endFrame, char checkEscape,
}
void Mult::drawText(bool &stop, bool &stopNoClear) {
- byte *savedIP;
-
int16 cmd;
for (_index = 0; _index < _multData->textKeysCount; _index++) {
if (_multData->textKeys[_index].frame != _frame)
@@ -265,9 +264,10 @@ void Mult::drawText(bool &stop, bool &stopNoClear) {
stopNoClear = true;
_multData->frameStart = 0;
} else if (cmd == 3) {
+ warning("Mult::drawText, cmd == 3");
stop = false;
- savedIP = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr = _multData->textKeys[_index].script;
+// uint32 startPos = _vm->_game->_script->pos();
+// _vm->_global->_inter_execPtr = _multData->textKeys[_index].script;
}
}
}
diff --git a/engines/gob/mult_v1.cpp b/engines/gob/mult_v1.cpp
index e2c16674c9..1bb162c789 100644
--- a/engines/gob/mult_v1.cpp
+++ b/engines/gob/mult_v1.cpp
@@ -1,4 +1,4 @@
-/* ScummVM - Graphic Adventure Engine
+/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
@@ -32,6 +32,8 @@
#include "gob/util.h"
#include "gob/draw.h"
#include "gob/game.h"
+#include "gob/script.h"
+#include "gob/resources.h"
#include "gob/inter.h"
#include "gob/scenery.h"
@@ -41,9 +43,6 @@ Mult_v1::Mult_v1(GobEngine *vm) : Mult(vm) {
}
void Mult_v1::loadMult(int16 resId) {
- uint32 dataSize;
- byte *extData;
-
debugC(4, kDebugGameFlow, "Loading mult");
_multData = new Mult_Data;
@@ -52,8 +51,11 @@ void Mult_v1::loadMult(int16 resId) {
_multData->sndSlotsCount = 0;
_multData->frameStart = 0;
- extData = (byte *) _vm->_game->loadExtData(resId, 0, 0, &dataSize);
- Common::MemoryReadStream data(extData, dataSize);
+ Resource *resource = _vm->_game->_resources->getResource(resId);
+ if (!resource)
+ return;
+
+ Common::SeekableReadStream &data = *resource->stream();
_multData->staticCount = data.readSByte() + 1;
_multData->animCount = data.readSByte() + 1;
@@ -157,15 +159,14 @@ void Mult_v1::loadMult(int16 resId) {
switch (_multData->sndKeys[i].cmd) {
case 1:
case 4:
- _multData->sndKeys[i].resId =
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _multData->sndKeys[i].resId = _vm->_game->_script->peekUint16();
for (j = 0; j < i; j++) {
if (_multData->sndKeys[i].resId ==
_multData->sndKeys[j].resId) {
_multData->sndKeys[i].soundIndex =
_multData->sndKeys[j].soundIndex;
- _vm->_global->_inter_execPtr += 2;
+ _vm->_game->_script->skip(2);
break;
}
}
@@ -178,16 +179,16 @@ void Mult_v1::loadMult(int16 resId) {
break;
case 3:
- _vm->_global->_inter_execPtr += 6;
+ _vm->_game->_script->skip(6);
break;
case 5:
- _vm->_global->_inter_execPtr += _multData->sndKeys[i].freq * 2;
+ _vm->_game->_script->skip(_multData->sndKeys[i].freq * 2);
break;
}
}
- delete[] extData;
+ delete resource;
}
void Mult_v1::freeMultKeys() {
diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp
index d9b5be0847..135c50c92c 100644
--- a/engines/gob/mult_v2.cpp
+++ b/engines/gob/mult_v2.cpp
@@ -32,9 +32,10 @@
#include "gob/util.h"
#include "gob/draw.h"
#include "gob/game.h"
+#include "gob/script.h"
+#include "gob/resources.h"
#include "gob/goblin.h"
#include "gob/inter.h"
-#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/video.h"
#include "gob/videoplayer.h"
@@ -60,11 +61,9 @@ void Mult_v2::loadMult(int16 resId) {
int8 index;
uint8 staticCount;
uint8 animCount;
- uint32 dataSize;
- byte *extData;
bool hasImds;
- index = (resId & 0x8000) ? *_vm->_global->_inter_execPtr++ : 0;
+ index = (resId & 0x8000) ? _vm->_game->_script->readByte() : 0;
resId &= 0x7FFF;
debugC(4, kDebugGameFlow, "Loading mult %d", index);
@@ -80,8 +79,11 @@ void Mult_v2::loadMult(int16 resId) {
_multData->sndSlotsCount = 0;
_multData->frameStart = 0;
- extData = (byte *) _vm->_game->loadExtData(resId, 0, 0, &dataSize);
- Common::MemoryReadStream data(extData, dataSize);
+ Resource *resource = _vm->_game->_resources->getResource(resId);
+ if (!resource)
+ return;
+
+ Common::SeekableReadStream &data = *resource->stream();
_multData->staticCount = staticCount = data.readSByte();
_multData->animCount = animCount = data.readSByte();
@@ -206,14 +208,13 @@ void Mult_v2::loadMult(int16 resId) {
switch (_multData->sndKeys[i].cmd) {
case 1:
case 4:
- _multData->sndKeys[i].resId =
- READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ _multData->sndKeys[i].resId = _vm->_game->_script->peekUint16();
for (j = 0; j < i; j++) {
if (_multData->sndKeys[j].resId ==
_multData->sndKeys[i].resId) {
_multData->sndKeys[i].soundIndex =
_multData->sndKeys[j].soundIndex;
- _vm->_global->_inter_execPtr += 2;
+ _vm->_game->_script->skip(2);
break;
}
}
@@ -226,7 +227,7 @@ void Mult_v2::loadMult(int16 resId) {
}
break;
case 3:
- _vm->_global->_inter_execPtr += 4;
+ _vm->_game->_script->skip(4);
break;
case -1:
@@ -244,17 +245,17 @@ void Mult_v2::loadMult(int16 resId) {
if (hasImds)
loadImds(data);
- delete[] extData;
+ delete resource;
}
void Mult_v2::loadImds(Common::SeekableReadStream &data) {
int16 size;
- size = _vm->_inter->load16();
- _multData->execPtr = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += size * 2;
+ size = _vm->_game->_script->readInt16();
+ _multData->execPtr = _vm->_game->_script->getData() + _vm->_game->_script->pos();
+ _vm->_game->_script->skip(size * 2);
- if (_vm->_game->_totFileData[0x29] < 51)
+ if (_vm->_game->_script->getVersionMinor() < 3)
return;
size = data.readSint16LE();
@@ -263,13 +264,27 @@ void Mult_v2::loadImds(Common::SeekableReadStream &data) {
data.read(_multData->somepointer10, size * 20);
}
- size = _vm->_inter->load16();
+ size = _vm->_game->_script->readInt16();
if (size <= 0)
return;
_multData->imdFiles = new char[size * 14];
- memcpy(_multData->imdFiles, _vm->_global->_inter_execPtr, size * 14);
- _vm->_global->_inter_execPtr += size * 14;
+ memcpy(_multData->imdFiles,
+ _vm->_game->_script->getData() + _vm->_game->_script->pos(), size * 14);
+
+ // WORKAROUND: The Windows version of Lost in Time has VMD not IMD files,
+ // but they are still referenced as IMD.
+ if ((_vm->getGameType() == kGameTypeLostInTime) &&
+ (_vm->getPlatform() == Common::kPlatformWindows)) {
+
+ for (int i = 0; i < size; i++) {
+ char *dot = strrchr(_multData->imdFiles + (i * 14), '.');
+ if (dot)
+ *dot = '\0';
+ }
+ }
+
+ _vm->_game->_script->skip(size * 14);
data.seek(2, SEEK_CUR);
for (int i = 0; i < 4; i++) {
_multData->imdKeysCount[i] = data.readSint16LE();
@@ -382,14 +397,16 @@ void Mult_v2::multSub(uint16 multIndex) {
if (multIndex > 7)
error("Multindex out of range");
+ _vm->_util->notifyNewAnim();
+
debugC(4, kDebugGameFlow, "Sub mult %d", multIndex);
_multData = _multDatas[multIndex];
if (!_multData) {
- _vm->_parse->parseValExpr();
- _vm->_parse->parseValExpr();
- _vm->_parse->parseValExpr();
- _vm->_parse->parseValExpr();
+ _vm->_game->_script->readValExpr();
+ _vm->_game->_script->readValExpr();
+ _vm->_game->_script->readValExpr();
+ _vm->_game->_script->readValExpr();
return;
}
@@ -412,9 +429,9 @@ void Mult_v2::multSub(uint16 multIndex) {
_multData->animObjs[index][0] = flags;
for (int i = 1; i < 4; i++)
- _multData->animObjs[index][i] = _vm->_parse->parseValExpr();
+ _multData->animObjs[index][i] = _vm->_game->_script->readValExpr();
- expr = _vm->_parse->parseValExpr();
+ expr = _vm->_game->_script->readValExpr();
_multData->animKeysFrames[index] = expr;
_multData->animKeysStartFrames[index] = expr;
@@ -856,7 +873,7 @@ void Mult_v2::animate() {
animObj.newBottom =
MAX(animObj.lastBottom, _vm->_scenery->_toRedrawBottom);
- if ((_vm->_game->_totFileData[0x29] > 50) &&
+ if ((_vm->_game->_script->getVersionMinor() > 2) &&
(animObj.newLeft == animObj.lastLeft) &&
(animObj.newTop == animObj.lastTop) &&
(animObj.newRight == animObj.lastRight) &&
diff --git a/engines/gob/parse.cpp b/engines/gob/parse.cpp
deleted file mode 100644
index 0fa46097a3..0000000000
--- a/engines/gob/parse.cpp
+++ /dev/null
@@ -1,1499 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/endian.h"
-
-#include "gob/gob.h"
-#include "gob/parse.h"
-#include "gob/global.h"
-#include "gob/game.h"
-#include "gob/inter.h"
-
-namespace Gob {
-
-Parse::Parse(GobEngine *vm) : _vm(vm) {
-}
-
-int32 Parse::encodePtr(byte *ptr, int type) {
- int32 offset = 0;
-
- switch (type) {
- case kExecPtr:
- offset = ptr - _vm->_game->_totFileData;
- break;
- case kInterVar:
- offset = ptr - ((byte *) _vm->_inter->_variables->getAddressOff8(0));
- break;
- case kResStr:
- offset = ptr - ((byte *) _vm->_global->_inter_resStr);
- break;
- default:
- error("Parse::encodePtr(): Unknown pointer type");
- }
- assert((offset & 0xF0000000) == 0);
- return (type << 28) | offset;
-}
-
-byte *Parse::decodePtr(int32 n) {
- byte *ptr;
-
- switch (n >> 28) {
- case kExecPtr:
- ptr = _vm->_game->_totFileData;
- break;
- case kInterVar:
- ptr = (byte *) _vm->_inter->_variables->getAddressOff8(0);
- break;
- case kResStr:
- ptr = (byte *) _vm->_global->_inter_resStr;
- break;
- default:
- error("Parse::decodePtr(): Unknown pointer type");
- }
- return ptr + (n & 0x0FFFFFFF);
-}
-
-void Parse::skipExpr(char stopToken) {
- int16 dimCount;
- byte operation;
- int16 num;
- int16 dim;
-
- num = 0;
- while (true) {
- operation = *_vm->_global->_inter_execPtr++;
-
- if ((operation >= 14) && (operation <= OP_FUNC)) {
- switch (operation) {
- case 14:
- _vm->_global->_inter_execPtr += 4;
- if (*_vm->_global->_inter_execPtr == 97)
- _vm->_global->_inter_execPtr++;
- break;
-
- case OP_LOAD_VAR_INT16:
- case OP_LOAD_VAR_INT8:
- case OP_LOAD_IMM_INT16:
- case 23:
- case 24:
- _vm->_global->_inter_execPtr += 2;
- break;
-
- case OP_LOAD_IMM_INT32:
- _vm->_global->_inter_execPtr += 4;
- break;
-
- case OP_LOAD_IMM_INT8:
- _vm->_global->_inter_execPtr += 1;
- break;
-
- case OP_LOAD_IMM_STR:
- _vm->_global->_inter_execPtr +=
- strlen((char *) _vm->_global->_inter_execPtr) + 1;
- break;
-
- case OP_LOAD_VAR_STR:
- _vm->_global->_inter_execPtr += 2;
- if (*_vm->_global->_inter_execPtr == 13) {
- _vm->_global->_inter_execPtr++;
- skipExpr(OP_END_MARKER);
- }
- break;
-
- case 15:
- _vm->_global->_inter_execPtr += 2;
-
- case OP_ARRAY_UINT8:
- case OP_ARRAY_UINT32:
- case OP_ARRAY_UINT16:
- case OP_ARRAY_STR:
- dimCount = _vm->_global->_inter_execPtr[2];
- // skip header and dimensions
- _vm->_global->_inter_execPtr += 3 + dimCount;
- // skip indices
- for (dim = 0; dim < dimCount; dim++)
- skipExpr(OP_END_MARKER);
-
- if ((operation == OP_ARRAY_STR) && (*_vm->_global->_inter_execPtr == 13)) {
- _vm->_global->_inter_execPtr++;
- skipExpr(OP_END_MARKER);
- }
- break;
-
- case OP_FUNC:
- _vm->_global->_inter_execPtr++;
- skipExpr(OP_END_EXPR);
- }
- continue;
- } // if ((operation >= OP_ARRAY_UINT8) && (operation <= OP_FUNC))
-
- if (operation == OP_BEGIN_EXPR) {
- num++;
- continue;
- }
-
- if ((operation == OP_NOT) || ((operation >= OP_NEG) && (operation <= 8)))
- continue;
-
- if ((operation >= OP_OR) && (operation <= OP_NEQ))
- continue;
-
- if (operation == OP_END_EXPR)
- num--;
-
- if (operation != stopToken)
- continue;
-
- if ((stopToken != OP_END_EXPR) || (num < 0))
- return;
- }
-}
-
-void Parse::printExpr(char stopToken) {
- // Expression printing disabled by default
- return;
-
- byte *savedPos = _vm->_global->_inter_execPtr;
- printExpr_internal(stopToken);
-
- // restore IP to start of expression
- _vm->_global->_inter_execPtr = savedPos;
-}
-
-void Parse::printExpr_internal(char stopToken) {
- int16 dimCount;
- byte operation;
- int16 num;
- int16 dim;
- byte *arrDesc;
- byte func;
-
- num = 0;
- while (true) {
- operation = *_vm->_global->_inter_execPtr++;
-
- if ((operation >= OP_ARRAY_UINT8) && (operation <= OP_FUNC)) {
- // operands
-
- switch (operation) {
- case OP_LOAD_VAR_INT16: // int16 variable load
- debugN(5, "var16_%d", _vm->_inter->load16());
- break;
-
- case OP_LOAD_VAR_INT8: // int8 variable load:
- debugN(5, "var8_%d", _vm->_inter->load16());
- break;
-
- case OP_LOAD_IMM_INT32: // int32/uint32 immediate
- debugN(5, "%d", READ_LE_UINT32(_vm->_global->_inter_execPtr));
- _vm->_global->_inter_execPtr += 4;
- break;
-
- case OP_LOAD_IMM_INT16: // int16 immediate
- debugN(5, "%d", _vm->_inter->load16());
- break;
-
- case OP_LOAD_IMM_INT8: // int8 immediate
- debugN(5, "%d", (int8) *_vm->_global->_inter_execPtr++);
- break;
-
- case OP_LOAD_IMM_STR: // string immediate
- debugN(5, "\42%s\42", _vm->_global->_inter_execPtr);
- _vm->_global->_inter_execPtr +=
- strlen((char *) _vm->_global->_inter_execPtr) + 1;
- break;
-
- case 23: // uint32 variable load
- case 24: // uint32 variable load as uint16
- debugN(5, "var_%d", _vm->_inter->load16());
- break;
-
- case OP_LOAD_VAR_STR: // string variable load
- debugN(5, "(&var_%d)", _vm->_inter->load16());
- if (*_vm->_global->_inter_execPtr == 13) {
- _vm->_global->_inter_execPtr++;
- debugN(5, "{");
- printExpr_internal(OP_END_MARKER); // this also prints the closing }
- }
- break;
-
- case OP_ARRAY_UINT8: // uint8 array access
- case OP_ARRAY_UINT32: // uint32 array access
- case OP_ARRAY_UINT16: // uint16 array access
- case OP_ARRAY_STR: // string array access
- debugN(5, "\n");
- if (operation == OP_ARRAY_STR)
- debugN(5, "(&");
-
- debugN(5, "var_%d[", _vm->_inter->load16());
- dimCount = *_vm->_global->_inter_execPtr++;
- arrDesc = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += dimCount;
- for (dim = 0; dim < dimCount; dim++) {
- printExpr_internal(OP_END_MARKER);
- debugN(5, " of %d", (int16) arrDesc[dim]);
- if (dim != dimCount - 1)
- debugN(5, ",");
- }
- debugN(5, "]");
- if (operation == OP_ARRAY_STR)
- debugN(5, ")");
-
- if ((operation == OP_ARRAY_STR) && (*_vm->_global->_inter_execPtr == 13)) {
- _vm->_global->_inter_execPtr++;
- debugN(5, "{");
- printExpr_internal(OP_END_MARKER); // this also prints the closing }
- }
- break;
-
- case OP_FUNC: // function
- func = *_vm->_global->_inter_execPtr++;
- if (func == FUNC_SQR)
- debugN(5, "sqr(");
- else if (func == FUNC_RAND)
- debugN(5, "rand(");
- else if (func == FUNC_ABS)
- debugN(5, "abs(");
- else if ((func == FUNC_SQRT1) || (func == FUNC_SQRT2) || (func == FUNC_SQRT3))
- debugN(5, "sqrt(");
- else
- debugN(5, "id(");
- printExpr_internal(OP_END_EXPR);
- break;
- }
- continue;
- } // if ((operation >= OP_ARRAY_UINT8) && (operation <= OP_FUNC))
-
- // operators
- switch (operation) {
- case OP_BEGIN_EXPR:
- debugN(5, "(");
- break;
-
- case OP_NOT:
- debugN(5, "!");
- break;
-
- case OP_END_EXPR:
- debugN(5, ")");
- break;
-
- case OP_NEG:
- debugN(5, "-");
- break;
-
- case OP_ADD:
- debugN(5, "+");
- break;
-
- case OP_SUB:
- debugN(5, "-");
- break;
-
- case OP_BITOR:
- debugN(5, "|");
- break;
-
- case OP_MUL:
- debugN(5, "*");
- break;
-
- case OP_DIV:
- debugN(5, "/");
- break;
-
- case OP_MOD:
- debugN(5, "%%");
- break;
-
- case OP_BITAND:
- debugN(5, "&");
- break;
-
- case OP_OR:
- debugN(5, "||");
- break;
-
- case 31:
- debugN(5, "&&");
- break;
-
- case OP_LESS:
- debugN(5, "<");
- break;
-
- case OP_LEQ:
- debugN(5, "<=");
- break;
-
- case OP_GREATER:
- debugN(5, ">");
- break;
-
- case OP_GEQ:
- debugN(5, ">=");
- break;
-
- case OP_EQ:
- debugN(5, "==");
- break;
-
- case OP_NEQ:
- debugN(5, "!=");
- break;
-
- case 99:
- debugN(5, "\n");
- break;
-
- case OP_END_MARKER:
- debugN(5, "}");
- if (stopToken != OP_END_MARKER) {
- debugN(5, "Closing paren without opening?");
- }
- break;
-
- default:
- debugN(5, "<%d>", (int16) operation);
- error("Parse::printExpr(): invalid operator in expression");
- break;
- }
-
- if (operation == OP_BEGIN_EXPR) {
- num++;
- continue;
- }
-
- if ((operation == OP_NOT) || ((operation >= OP_NEG) && (operation <= 8)))
- continue;
-
- if ((operation >= OP_OR) && (operation <= OP_NEQ))
- continue;
-
- if (operation == OP_END_EXPR)
- num--;
-
- if (operation == stopToken) {
- if ((stopToken != OP_END_EXPR) || (num < 0)) {
- return;
- }
- }
- }
-}
-
-
-void Parse::printVarIndex() {
- byte *arrDesc;
- int16 dim;
- int16 dimCount;
- int16 operation;
- int16 temp;
-
- byte *pos = _vm->_global->_inter_execPtr;
-
- operation = *_vm->_global->_inter_execPtr++;
- switch (operation) {
- case 23:
- case OP_LOAD_VAR_STR:
- temp = _vm->_inter->load16() * 4;
- debugN(5, "&var_%d", temp);
- if ((operation == OP_LOAD_VAR_STR) && (*_vm->_global->_inter_execPtr == 13)) {
- _vm->_global->_inter_execPtr++;
- debugN(5, "+");
- printExpr(OP_END_MARKER);
- }
- break;
-
- case OP_ARRAY_UINT32:
- case OP_ARRAY_STR:
- debugN(5, "&var_%d[", _vm->_inter->load16());
- dimCount = *_vm->_global->_inter_execPtr++;
- arrDesc = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += dimCount;
- for (dim = 0; dim < dimCount; dim++) {
- printExpr(OP_END_MARKER);
- debugN(5, " of %d", (int16) arrDesc[dim]);
- if (dim != dimCount - 1)
- debugN(5, ",");
- }
- debugN(5, "]");
-
- if ((operation == OP_ARRAY_STR) && (*_vm->_global->_inter_execPtr == 13)) {
- _vm->_global->_inter_execPtr++;
- debugN(5, "+");
- printExpr(OP_END_MARKER);
- }
- break;
-
- default:
- debugN(5, "var_0");
- break;
- }
- debugN(5, "\n");
- _vm->_global->_inter_execPtr = pos;
- return;
-}
-
-int16 Parse::getOffset(int16 arg_0, byte arg_2, uint32 arg_3, uint16 arg_7, uint16 arg_9) {
- if (arg_0 < 0)
- return 0;
-
- if (arg_2 > arg_0)
- return arg_0;
-
- return arg_2 - 1;
-}
-
-int Parse::cmpHelper(byte *operPtr, int32 *valPtr) {
- byte var_C = operPtr[-3];
- int cmpTemp = 0;
- if (var_C == OP_LOAD_IMM_INT16) {
- cmpTemp = (int)valPtr[-3] - (int)valPtr[-1];
- } else if (var_C == OP_LOAD_IMM_STR) {
- if ((char *)decodePtr(valPtr[-3]) != _vm->_global->_inter_resStr) {
- strcpy(_vm->_global->_inter_resStr, (char *)decodePtr(valPtr[-3]));
- valPtr[-3] = encodePtr((byte *) _vm->_global->_inter_resStr, kResStr);
- }
- cmpTemp = strcmp(_vm->_global->_inter_resStr, (char *)decodePtr(valPtr[-1]));
- }
-
- return cmpTemp;
-}
-
-int16 Parse::parseVarIndex(uint16 *arg_0, uint16 *arg_4) {
- int16 temp2;
- byte *arrDesc;
- int16 dim;
- int16 dimCount;
- int16 operation;
- int16 temp;
- int16 offset;
- int16 val;
- uint32 varPos = 0;
-
- operation = *_vm->_global->_inter_execPtr++;
-
- while ((operation == 14) || (operation == 15)) {
- if (operation == 14) {
- uint16 n = _vm->_inter->load16();
- varPos += n * 4;
-
- if (arg_0)
- *arg_0 = READ_LE_UINT16(_vm->_global->_inter_execPtr);
- if (arg_4)
- *arg_4 = 14;
-
- _vm->_global->_inter_execPtr += 2;
-
- debugC(2, kDebugParser, "parseVarIndex: Prefix %d (%d)", varPos, operation);
-
- if (*_vm->_global->_inter_execPtr != 97)
- return varPos;
-
- _vm->_global->_inter_execPtr++;
-
- } else if (operation == 15) {
- uint16 n = _vm->_inter->load16();
- varPos += n * 4;
-
- uint16 var_0C = _vm->_inter->load16();
- if (arg_0)
- *arg_0 = var_0C;
- if (arg_4)
- *arg_4 = 15;
-
- uint8 var_A = *_vm->_global->_inter_execPtr++;
-
- byte *var_12 = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += var_A;
-
- uint16 var_6 = 0;
-
- for (int i = 0; i < var_A; i++) {
- temp2 = parseValExpr(OP_END_MARKER);
-
- int16 ax = getOffset(temp2, var_12[i], varPos, 0, 0);
-
- var_6 = var_6 * var_12[i] + ax;
- }
-
- varPos += var_6 * var_0C * 4;
-
- debugC(2, kDebugParser, "parseVarIndex: Prefix %d (%d)", varPos, operation);
-
- if (*_vm->_global->_inter_execPtr != 97)
- return varPos;
-
- _vm->_global->_inter_execPtr++;
- }
-
- operation = *_vm->_global->_inter_execPtr++;
- }
-
- if (arg_0)
- *arg_0 = 0;
- if (arg_4)
- *arg_4 = operation;
-
- debugC(5, kDebugParser, "var parse = %d", operation);
- switch (operation) {
- case OP_ARRAY_UINT8:
- case OP_ARRAY_UINT32:
- case OP_ARRAY_UINT16:
- case OP_ARRAY_STR:
- temp = _vm->_inter->load16();
- dimCount = *_vm->_global->_inter_execPtr++;
- arrDesc = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += dimCount;
- offset = 0;
- for (dim = 0; dim < dimCount; dim++) {
- temp2 = parseValExpr(OP_END_MARKER);
- offset = arrDesc[dim] * offset + temp2;
- }
- if (operation == OP_ARRAY_UINT8)
- return varPos + temp + offset;
- if (operation == OP_ARRAY_UINT32)
- return varPos + (temp + offset) * 4;
- if (operation == OP_ARRAY_UINT16)
- return varPos + (temp + offset) * 2;
- temp *= 4;
- offset *= 4;
- if (*_vm->_global->_inter_execPtr == 13) {
- _vm->_global->_inter_execPtr++;
- temp += parseValExpr(OP_END_MARKER);
- }
- return varPos + offset * _vm->_global->_inter_animDataSize + temp;
-
- case OP_LOAD_VAR_INT16:
- return varPos + _vm->_inter->load16() * 2;
-
- case OP_LOAD_VAR_INT8:
- return varPos + _vm->_inter->load16();
-
- case 23:
- case 24:
- case OP_LOAD_VAR_STR:
- temp = _vm->_inter->load16() * 4;
- debugC(5, kDebugParser, "oper = %d",
- (int16) *_vm->_global->_inter_execPtr);
- if ((operation == OP_LOAD_VAR_STR) && (*_vm->_global->_inter_execPtr == 13)) {
- _vm->_global->_inter_execPtr++;
- val = parseValExpr(OP_END_MARKER);
- temp += val;
- debugC(5, kDebugParser, "parse subscript = %d", val);
- }
- return varPos + temp;
-
- default:
- return 0;
- }
-}
-
-int16 Parse::parseValExpr(byte stopToken) {
- int16 values[20];
- byte operStack[20];
- int16 *valPtr;
- byte *operPtr;
- byte *arrDesc;
- byte operation;
- int16 temp2;
- int16 dim;
- int16 dimCount;
- int16 temp;
- int16 offset;
- int16 stkPos;
- int16 brackPos;
- static int16 flag = 0;
- int16 oldflag;
- uint32 varPos = 0;
-
- memset(values, 0, 20 * sizeof(int16));
-
- oldflag = flag;
- if (flag == 0) {
- flag = 1;
- printExpr(stopToken);
- }
-
- stkPos = -1;
- operPtr = operStack - 1;
- valPtr = values - 1;
-
- while (1) {
- operation = *_vm->_global->_inter_execPtr++;
-
- while ((operation == 14) || (operation == 15)) {
- if (operation == 14) {
- uint16 n = _vm->_inter->load16();
- varPos += n * 4;
-
- _vm->_global->_inter_execPtr += 3;
- } else if (operation == 15) {
- uint16 n = _vm->_inter->load16();
- varPos += n * 4;
-
- uint16 var_0C = _vm->_inter->load16();
- uint8 var_A = *_vm->_global->_inter_execPtr++;
-
- byte *var_12 = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += var_A;
-
- uint16 var_6 = 0;
-
- for (int i = 0; i < var_A; i++) {
- temp2 = parseValExpr(OP_END_MARKER);
-
- int16 ax = getOffset(temp2, var_12[i], varPos, 0, 0);
-
- var_6 = var_6 * var_12[i] + ax;
- }
-
- varPos += var_6 * var_0C * 4;
-
- _vm->_global->_inter_execPtr++;
- }
-
- debugC(2, kDebugParser, "parseValExpr: Prefix %d (%d)", varPos, operation);
-
- operation = *_vm->_global->_inter_execPtr++;
- }
-
- stkPos++;
- operPtr++;
- valPtr++;
-
- if ((operation >= OP_ARRAY_UINT8) && (operation <= OP_FUNC)) {
- *operPtr = OP_LOAD_IMM_INT16;
- switch (operation) {
- case OP_ARRAY_UINT8:
- case OP_ARRAY_UINT32:
- case OP_ARRAY_UINT16:
- case OP_ARRAY_STR:
- temp = _vm->_inter->load16();
- dimCount = *_vm->_global->_inter_execPtr++;
- arrDesc = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += dimCount;
- offset = 0;
- for (dim = 0; dim < dimCount; dim++) {
- temp2 = parseValExpr(OP_END_MARKER);
- offset = arrDesc[dim] * offset + temp2;
- }
- if (operation == OP_ARRAY_UINT8)
- *valPtr = (int8) READ_VARO_UINT8(varPos + temp + offset);
- else if (operation == OP_ARRAY_UINT32)
- *valPtr = (uint16) READ_VARO_UINT32(varPos + temp * 4 + offset * 4);
- else if (operation == OP_ARRAY_UINT16)
- *valPtr = READ_VARO_UINT16(varPos + temp * 2 + offset * 2);
- else if (operation == OP_ARRAY_STR) {
- _vm->_global->_inter_execPtr++;
- temp2 = parseValExpr(OP_END_MARKER);
- *valPtr = READ_VARO_UINT8(varPos + temp * 4 +
- offset * 4 * _vm->_global->_inter_animDataSize + temp2);
- }
- break;
-
- case OP_LOAD_VAR_INT16:
- *valPtr = READ_VARO_UINT16(varPos + _vm->_inter->load16() * 2);
- break;
-
- case OP_LOAD_VAR_INT8:
- *valPtr = (int8) READ_VARO_UINT8(varPos + _vm->_inter->load16());
- break;
-
- case OP_LOAD_IMM_INT32:
- *valPtr = (uint16) READ_LE_UINT32(varPos + _vm->_global->_inter_execPtr);
- _vm->_global->_inter_execPtr += 4;
- break;
-
- case OP_LOAD_IMM_INT16:
- *valPtr = _vm->_inter->load16();
- break;
-
- case OP_LOAD_IMM_INT8:
- *valPtr = (int8) *_vm->_global->_inter_execPtr++;
- break;
-
- case 23:
- *valPtr = (uint16) READ_VARO_UINT32(varPos + _vm->_inter->load16() * 4);
- break;
-
- case 24:
- *valPtr = READ_VARO_UINT16(varPos + _vm->_inter->load16() * 4);
- break;
-
- case OP_LOAD_VAR_STR:
- temp = _vm->_inter->load16() * 4;
- _vm->_global->_inter_execPtr++;
- temp += parseValExpr(OP_END_MARKER);
- *valPtr = READ_VARO_UINT8(varPos + temp);
- break;
-
- case OP_FUNC:
- operation = *_vm->_global->_inter_execPtr++;
- parseExpr(OP_END_EXPR, 0);
-
- if (operation == FUNC_SQR) {
- _vm->_global->_inter_resVal =
- _vm->_global->_inter_resVal * _vm->_global->_inter_resVal;
- } else if (operation == FUNC_ABS) {
- if (_vm->_global->_inter_resVal < 0)
- _vm->_global->_inter_resVal = -_vm->_global->_inter_resVal;
- } else if (operation == FUNC_RAND) {
- _vm->_global->_inter_resVal =
- _vm->_util->getRandom(_vm->_global->_inter_resVal);
- }
- *valPtr = _vm->_global->_inter_resVal;
- break;
-
- } // switch
- if ((stkPos > 0) && (operPtr[-1] == OP_NEG)) {
- stkPos--;
- operPtr--;
- valPtr--;
- operPtr[0] = OP_LOAD_IMM_INT16;
- valPtr[0] = -valPtr[1];
- }
-
- if ((stkPos > 0) && (operPtr[-1] >= OP_MUL) && (operPtr[-1] <= OP_BITAND)) {
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
-
- switch (operPtr[1]) {
- case OP_MUL:
- valPtr[0] *= valPtr[2];
- break;
-
- case OP_DIV:
- valPtr[0] /= valPtr[2];
- break;
-
- case OP_MOD:
- valPtr[0] %= valPtr[2];
- break;
-
- case OP_BITAND:
- valPtr[0] &= valPtr[2];
- break;
- }
- } // if ((stkPos > 0) && (cmdPtr[-1] >= OP_MUL) && (cmdPtr[-1] <= OP_BITAND))
- varPos = 0;
- continue;
- }
-
- if ((operation >= OP_NEG) && (operation <= OP_BEGIN_EXPR)) {
- *operPtr = operation;
- continue;
- }
-
- while (stkPos >= 2) {
- if (operPtr[-2] == OP_BEGIN_EXPR) {
- stkPos--;
- operPtr--;
- valPtr--;
-
- operPtr[-1] = operPtr[0];
- valPtr[-1] = valPtr[0];
- if ((stkPos > 1) && (operPtr[-2] == OP_NEG)) {
- operPtr[-2] = OP_LOAD_IMM_INT16;
- valPtr[-2] = -valPtr[-1];
-
- stkPos--;
- operPtr--;
- valPtr--;
- }
-
- if ((stkPos > 2) && (operPtr[-2] >= OP_MUL) && (operPtr[-2] <= OP_BITAND)) {
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- switch (operPtr[0]) {
- case OP_MUL:
- valPtr[-1] *= valPtr[1];
- break;
-
- case OP_DIV:
- valPtr[-1] /= valPtr[1];
- break;
-
- case OP_MOD:
- valPtr[-1] %= valPtr[1];
- break;
-
- case OP_BITAND:
- valPtr[-1] &= valPtr[1];
- break;
- }
- }
- if (operation == OP_END_EXPR)
- break;
- } // operPtr[-2] == OP_BEGIN_EXPR
-
- for (brackPos = (stkPos - 2); (brackPos > 0) &&
- (operStack[brackPos] < OP_OR) && (operStack[brackPos] != OP_BEGIN_EXPR);
- brackPos--)
- ;
-
- if ((operStack[brackPos] >= OP_OR) || (operStack[brackPos] == OP_BEGIN_EXPR))
- brackPos++;
-
- if ((operPtr[-2] < 2) || (operPtr[-2] > 8))
- break;
-
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- switch (operPtr[0]) {
- case OP_ADD:
- values[brackPos] += valPtr[1];
- continue;
- case OP_SUB:
- values[brackPos] -= valPtr[1];
- continue;
- case OP_BITOR:
- values[brackPos] |= valPtr[1];
- continue;
- case OP_MUL:
- valPtr[-1] *= valPtr[1];
- continue;
- case OP_DIV:
- valPtr[-1] /= valPtr[1];
- continue;
- case OP_MOD:
- valPtr[-1] %= valPtr[1];
- continue;
- case OP_BITAND:
- valPtr[-1] &= valPtr[1];
- continue;
- }
- }
-
- if (operation != OP_END_EXPR) {
- if (operation != stopToken) {
- debugC(5, kDebugParser, "stoptoken error: %d != %d",
- operation, stopToken);
- }
- flag = oldflag;
- return values[0];
- }
-
- stkPos--;
- operPtr--;
- valPtr--;
- }
-}
-
-int16 Parse::parseExpr(byte stopToken, byte *arg_2) {
- int32 values[20];
- byte operStack[20];
- int32 prevPrevVal;
- int32 prevVal;
- int32 curVal;
- int32 *valPtr;
- byte *operPtr;
- byte *arrDescPtr;
- byte operation;
- int16 dimCount;
- int16 temp;
- int16 temp2;
- int16 offset;
- int16 dim;
- bool var_1A;
- int16 stkPos;
- int16 brackStart;
- uint32 varPos = 0;
-
- memset(operStack, 0, 20);
-
- stkPos = -1;
- operPtr = operStack - 1;
- valPtr = values - 1;
-
- while (true) {
- operation = *_vm->_global->_inter_execPtr++;
-
- while ((operation == 14) || (operation == 15)) {
- if (operation == 14) {
- uint16 n = _vm->_inter->load16();
- varPos += n * 4;
-
- _vm->_global->_inter_execPtr += 2;
- if (*_vm->_global->_inter_execPtr == 97)
- _vm->_global->_inter_execPtr++;
- } else if (operation == 15) {
- uint16 n = _vm->_inter->load16();
- varPos += n * 4;
-
- uint16 var_0C = _vm->_inter->load16();
- uint8 var_A = *_vm->_global->_inter_execPtr++;
-
- byte *var_12 = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += var_A;
-
- uint16 var_6 = 0;
-
- for (int i = 0; i < var_A; i++) {
- temp2 = parseValExpr(OP_END_MARKER);
-
- int16 ax = getOffset(temp2, var_12[i], varPos, 0, 0);
-
- var_6 = var_6 * var_12[i] + ax;
- }
-
- varPos += var_6 * var_0C * 4;
-
- if (*_vm->_global->_inter_execPtr == 97)
- _vm->_global->_inter_execPtr++;
- }
-
- debugC(2, kDebugParser, "parseExpr: Prefix %d (%d)", varPos, operation);
-
- operation = *_vm->_global->_inter_execPtr++;
- }
-
- stkPos++;
- operPtr++;
- valPtr++;
-
- if ((operation >= OP_ARRAY_UINT8) && (operation <= OP_FUNC)) {
- switch (operation) {
- case OP_ARRAY_UINT8:
- case OP_ARRAY_UINT32:
- case OP_ARRAY_UINT16:
- case OP_ARRAY_STR:
- *operPtr = (operation == OP_ARRAY_STR) ? OP_LOAD_IMM_STR : OP_LOAD_IMM_INT16;
- temp = _vm->_inter->load16();
- dimCount = *_vm->_global->_inter_execPtr++;
- arrDescPtr = _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += dimCount;
- offset = 0;
- for (dim = 0; dim < dimCount; dim++) {
- temp2 = parseValExpr(OP_END_MARKER);
- offset = offset * arrDescPtr[dim] + temp2;
- }
- if (operation == OP_ARRAY_UINT8)
- *valPtr = (int8) READ_VARO_UINT8(varPos + temp + offset);
- else if (operation == OP_ARRAY_UINT32)
- *valPtr = READ_VARO_UINT32(varPos + temp * 4 + offset * 4);
- else if (operation == OP_ARRAY_UINT16)
- *valPtr = (int16) READ_VARO_UINT16(varPos + temp * 2 + offset * 2);
- else if (operation == OP_ARRAY_STR) {
- *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(
- varPos + temp * 4 + offset * _vm->_global->_inter_animDataSize * 4),
- kInterVar);
- if (*_vm->_global->_inter_execPtr == 13) {
- _vm->_global->_inter_execPtr++;
- temp2 = parseValExpr(OP_END_MARKER);
- *operPtr = OP_LOAD_IMM_INT16;
- *valPtr = READ_VARO_UINT8(varPos + temp * 4 +
- offset * 4 * _vm->_global->_inter_animDataSize + temp2);
- }
- }
- break;
-
- case OP_LOAD_VAR_INT16:
- *operPtr = OP_LOAD_IMM_INT16;
- *valPtr = (int16) READ_VARO_UINT16(varPos + _vm->_inter->load16() * 2);
- break;
-
- case OP_LOAD_VAR_INT8:
- *operPtr = OP_LOAD_IMM_INT16;
- *valPtr = (int8) READ_VARO_UINT8(varPos + _vm->_inter->load16());
- break;
-
- case OP_LOAD_IMM_INT32:
- *operPtr = OP_LOAD_IMM_INT16;
- *valPtr = READ_LE_UINT32(varPos + _vm->_global->_inter_execPtr);
- _vm->_global->_inter_execPtr += 4;
- break;
-
- case OP_LOAD_IMM_INT16:
- *operPtr = OP_LOAD_IMM_INT16;
- *valPtr = _vm->_inter->load16();
- break;
-
- case OP_LOAD_IMM_INT8:
- *operPtr = OP_LOAD_IMM_INT16;
- *valPtr = (int8) *_vm->_global->_inter_execPtr++;
- break;
-
- case OP_LOAD_IMM_STR:
- *operPtr = OP_LOAD_IMM_STR;
- *valPtr = encodePtr(_vm->_global->_inter_execPtr, kExecPtr);
- _vm->_global->_inter_execPtr +=
- strlen((char *) _vm->_global->_inter_execPtr) + 1;
- break;
-
- case 23:
- *operPtr = OP_LOAD_IMM_INT16;
- *valPtr = READ_VARO_UINT32(varPos + _vm->_inter->load16() * 4);
- break;
-
- case 24:
- *operPtr = OP_LOAD_IMM_INT16;
- *valPtr = (int16) READ_VARO_UINT16(varPos + _vm->_inter->load16() * 4);
- break;
-
- case OP_LOAD_VAR_STR:
- *operPtr = OP_LOAD_IMM_STR;
- temp = _vm->_inter->load16() * 4;
- *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(varPos + temp), kInterVar);
- if (*_vm->_global->_inter_execPtr == 13) {
- _vm->_global->_inter_execPtr++;
- temp += parseValExpr(OP_END_MARKER);
- *operPtr = OP_LOAD_IMM_INT16;
- *valPtr = READ_VARO_UINT8(varPos + temp);
- }
- break;
-
- case OP_FUNC:
- operation = *_vm->_global->_inter_execPtr++;
- parseExpr(OP_END_EXPR, 0);
-
- switch (operation) {
- case FUNC_SQRT1:
- case FUNC_SQRT2:
- case FUNC_SQRT3:
- curVal = 1;
- prevVal = 1;
-
- do {
- prevPrevVal = prevVal;
- prevVal = curVal;
- curVal = (curVal + _vm->_global->_inter_resVal / curVal) / 2;
- } while ((curVal != prevVal) && (curVal != prevPrevVal));
- _vm->_global->_inter_resVal = curVal;
- break;
-
- case FUNC_SQR:
- _vm->_global->_inter_resVal =
- _vm->_global->_inter_resVal * _vm->_global->_inter_resVal;
- break;
-
- case FUNC_ABS:
- if (_vm->_global->_inter_resVal < 0)
- _vm->_global->_inter_resVal = -_vm->_global->_inter_resVal;
- break;
-
- case FUNC_RAND:
- _vm->_global->_inter_resVal =
- _vm->_util->getRandom(_vm->_global->_inter_resVal);
- break;
- }
-
- *operPtr = OP_LOAD_IMM_INT16;
- *valPtr = _vm->_global->_inter_resVal;
- break;
- }
-
- if ((stkPos > 0) && ((operPtr[-1] == OP_NEG) || (operPtr[-1] == OP_NOT))) {
- stkPos--;
- operPtr--;
- valPtr--;
-
- if (*operPtr == OP_NEG) {
- *operPtr = OP_LOAD_IMM_INT16;
- valPtr[0] = -valPtr[1];
- } else
- *operPtr = (operPtr[1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE;
- }
-
- if (stkPos <= 0) {
- varPos = 0;
- continue;
- }
-
- switch (operPtr[-1]) {
- case OP_ADD:
- if (operPtr[-2] == OP_LOAD_IMM_STR) {
- if ((char *) decodePtr(valPtr[-2]) != _vm->_global->_inter_resStr) {
- strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-2]));
- valPtr[-2] = encodePtr((byte *) _vm->_global->_inter_resStr, kResStr);
- }
- strcat(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[0]));
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- }
- break;
-
- case OP_MUL:
- valPtr[-2] *= valPtr[0];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
-
- case OP_DIV:
- valPtr[-2] /= valPtr[0];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
-
- case OP_MOD:
- valPtr[-2] %= valPtr[0];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
-
- case OP_BITAND:
- valPtr[-2] &= valPtr[0];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
- }
- varPos = 0;
- continue;
- } // (op >= OP_ARRAY_UINT8) && (op <= OP_FUNC)
-
- if ((operation == stopToken) || (operation == OP_OR) ||
- (operation == OP_AND) || (operation == OP_END_EXPR)) {
- while (stkPos >= 2) {
- var_1A = false;
- if ((operPtr[-2] == OP_BEGIN_EXPR) &&
- ((operation == OP_END_EXPR) || (operation == stopToken))) {
- operPtr[-2] = operPtr[-1];
- if ((operPtr[-2] == OP_LOAD_IMM_INT16) || (operPtr[-2] == OP_LOAD_IMM_STR))
- valPtr[-2] = valPtr[-1];
-
- stkPos--;
- operPtr--;
- valPtr--;
-
- if (stkPos > 1) {
- if (operPtr[-2] == OP_NEG) {
- operPtr[-2] = OP_LOAD_IMM_INT16;
- valPtr[-2] = -valPtr[-1];
- stkPos--;
- operPtr--;
- valPtr--;
- } else if (operPtr[-2] == OP_NOT) {
- operPtr[-2] = (operPtr[-1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE;
- stkPos--;
- operPtr--;
- valPtr--;
- }
- } // stkPos > 1
-
- if (stkPos > 2) {
- switch (operPtr[-2]) {
- case OP_MUL:
- valPtr[-3] *= valPtr[-1];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
-
- case OP_DIV:
- valPtr[-3] /= valPtr[-1];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
-
- case OP_MOD:
- valPtr[-3] %= valPtr[-1];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
-
- case OP_BITAND:
- valPtr[-3] &= valPtr[-1];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
- } // switch
- } // stkPos > 2
-
- if (operation != stopToken)
- break;
- } // if ((operPtr[-2] == OP_BEGIN_EXPR) && ...)
-
- for (brackStart = (stkPos - 2); (brackStart > 0) &&
- (operStack[brackStart] < OP_OR) && (operStack[brackStart] != OP_BEGIN_EXPR);
- brackStart--)
- ;
-
- if ((operStack[brackStart] >= OP_OR) || (operStack[brackStart] == OP_BEGIN_EXPR))
- brackStart++;
-
- switch (operPtr[-2]) {
- case OP_ADD:
- if (operStack[brackStart] == OP_LOAD_IMM_INT16) {
- values[brackStart] += valPtr[-1];
- } else if (operStack[brackStart] == OP_LOAD_IMM_STR) {
- if ((char *) decodePtr(values[brackStart]) != _vm->_global->_inter_resStr) {
- strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(values[brackStart]));
- values[brackStart] =
- encodePtr((byte *) _vm->_global->_inter_resStr, kResStr);
- }
- strcat(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-1]));
- }
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- continue;
-
- case OP_SUB:
- values[brackStart] -= valPtr[-1];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- continue;
-
- case OP_BITOR:
- values[brackStart] |= valPtr[-1];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- continue;
-
- case OP_MUL:
- valPtr[-3] *= valPtr[-1];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
-
- case OP_DIV:
- valPtr[-3] /= valPtr[-1];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
-
- case OP_MOD:
- valPtr[-3] %= valPtr[-1];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
-
- case OP_BITAND:
- valPtr[-3] &= valPtr[-1];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
-
- case OP_OR:
- // (x OR false) == x
- // (x OR true) == true
- if (operPtr[-3] == GOB_FALSE)
- operPtr[-3] = operPtr[-1];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
-
- case OP_AND:
- // (x AND false) == false
- // (x AND true) == x
- if (operPtr[-3] == GOB_TRUE)
- operPtr[-3] = operPtr[-1];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
-
- case OP_LESS:
- operPtr[-3] = (cmpHelper(operPtr, valPtr) < 0) ? GOB_TRUE : GOB_FALSE;
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
-
- case OP_LEQ:
- operPtr[-3] = (cmpHelper(operPtr, valPtr) <= 0) ? GOB_TRUE : GOB_FALSE;
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
-
- case OP_GREATER:
- operPtr[-3] = (cmpHelper(operPtr, valPtr) > 0) ? GOB_TRUE : GOB_FALSE;
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
-
- case OP_GEQ:
- operPtr[-3] = (cmpHelper(operPtr, valPtr) >= 0) ? GOB_TRUE : GOB_FALSE;
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
-
- case OP_EQ:
- operPtr[-3] = (cmpHelper(operPtr, valPtr) == 0) ? GOB_TRUE : GOB_FALSE;
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
-
- case OP_NEQ: {
- int cmpTemp = 0;
-
- if (operPtr[-3] == OP_LOAD_IMM_INT16) {
- cmpTemp = valPtr[-3] - valPtr[-1];
- } else if (operPtr[-3] == OP_LOAD_IMM_STR) {
- if ((char *) decodePtr(valPtr[-3]) != _vm->_global->_inter_resStr) {
- strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-3]));
- valPtr[-3] = encodePtr((byte *) _vm->_global->_inter_resStr, kResStr);
- }
- // FIXME: Why scumm_stricmp here and strcmp everywhere else?
- cmpTemp = scumm_stricmp(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-1]));
- }
- operPtr[-3] = (cmpTemp != 0) ? GOB_TRUE : GOB_FALSE;
- //operPtr[-3] = (cmpHelper(operPtr, valPtr) != 0) ? GOB_TRUE : GOB_FALSE;
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- break;
- }
-
- default:
- var_1A = true;
- break;
- } // switch
-
- if (var_1A)
- break;
- } // while (stkPos >= 2)
-
- if ((operation == OP_OR) || (operation == OP_AND)) {
- if (operPtr[-1] == OP_LOAD_IMM_INT16) {
- if (valPtr[-1] != 0)
- operPtr[-1] = GOB_TRUE;
- else
- operPtr[-1] = GOB_FALSE;
- }
-
- if (((operation == OP_OR) && (operPtr[-1] == GOB_TRUE)) ||
- ((operation == OP_AND) && (operPtr[-1] == GOB_FALSE))) {
- if ((stkPos > 1) && (operPtr[-2] == OP_BEGIN_EXPR)) {
- skipExpr(OP_END_EXPR);
- operPtr[-2] = operPtr[-1];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- } else {
- skipExpr(stopToken);
- }
- operation = _vm->_global->_inter_execPtr[-1];
- if ((stkPos > 0) && (operPtr[-1] == OP_NOT)) {
- if (operPtr[0] == GOB_FALSE)
- operPtr[-1] = GOB_TRUE;
- else
- operPtr[-1] = GOB_FALSE;
-
- stkPos--;
- operPtr--;
- valPtr--;
- }
- } else
- operPtr[0] = operation;
- } else {
- stkPos--;
- operPtr--;
- valPtr--;
- }
-
- if (operation != stopToken)
- continue;
-
- if (arg_2 != 0)
- *arg_2 = operStack[0];
-
- switch (operStack[0]) {
- case OP_NOT:
- if (arg_2 != 0)
- *arg_2 ^= 1;
- break;
-
- case OP_LOAD_IMM_INT16:
- _vm->_global->_inter_resVal = values[0];
- break;
-
- case OP_LOAD_IMM_STR:
- if ((char *) decodePtr(values[0]) != _vm->_global->_inter_resStr)
- strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(values[0]));
- break;
-
- case 23:
- case 24:
- break;
-
- default:
- _vm->_global->_inter_resVal = 0;
- if (arg_2 != 0)
- *arg_2 = OP_LOAD_IMM_INT16;
- break;
- }
- return 0;
- } // (operation == stopToken) || (operation == OP_OR) || (operation == OP_AND) || (operation == OP_END_EXPR)
-
- if ((operation < OP_NEG) || (operation > OP_NOT)) {
- if ((operation < OP_LESS) || (operation > OP_NEQ))
- continue;
-
- if (stkPos > 2) {
- if (operPtr[-2] == OP_ADD) {
- if (operPtr[-3] == OP_LOAD_IMM_INT16) {
- valPtr[-3] += valPtr[-1];
- } else if (operPtr[-3] == OP_LOAD_IMM_STR) {
- if ((char *) decodePtr(valPtr[-3]) != _vm->_global->_inter_resStr) {
- strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-3]));
- valPtr[-3] = encodePtr((byte *) _vm->_global->_inter_resStr, kResStr);
- }
- strcat(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-1]));
- }
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
-
- } else if (operPtr[-2] == OP_SUB) {
- valPtr[-3] -= valPtr[-1];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- } else if (operPtr[-2] == OP_BITOR) {
- valPtr[-3] |= valPtr[-1];
- stkPos -= 2;
- operPtr -= 2;
- valPtr -= 2;
- }
- }
- }
- *operPtr = operation;
- }
-}
-
-} // End of namespace Gob
diff --git a/engines/gob/parse.h b/engines/gob/parse.h
deleted file mode 100644
index 01f5762b6d..0000000000
--- a/engines/gob/parse.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#ifndef GOB_PARSE_H
-#define GOB_PARSE_H
-
-namespace Gob {
-
-enum {
- OP_NEG = 1,
- OP_ADD = 2,
- OP_SUB = 3,
- OP_BITOR = 4,
- OP_MUL = 5,
- OP_DIV = 6,
- OP_MOD = 7,
- OP_BITAND = 8,
- OP_BEGIN_EXPR = 9,
- OP_END_EXPR = 10,
- OP_NOT = 11,
-
- OP_END_MARKER = 12, // Marks end of an array or string
-
-
- OP_ARRAY_UINT8 = 16,
-
- OP_LOAD_VAR_INT16 = 17,
- OP_LOAD_VAR_INT8 = 18,
- OP_LOAD_IMM_INT32 = 19,
- OP_LOAD_IMM_INT16 = 20,
- OP_LOAD_IMM_INT8 = 21,
- OP_LOAD_IMM_STR = 22,
-
- OP_LOAD_VAR_UINT32 = 23, // ???
- OP_LOAD_VAR_UINT32_AS_UINT16 = 24, // ???
- OP_LOAD_VAR_STR = 25,
-
- OP_ARRAY_UINT32 = 26,
- OP_ARRAY_UINT16 = 27,
- OP_ARRAY_STR = 28,
-
- OP_FUNC = 29,
-
- OP_OR = 30, // Logical OR
- OP_AND = 31, // Logical AND
- OP_LESS = 32,
- OP_LEQ = 33,
- OP_GREATER = 34,
- OP_GEQ = 35,
- OP_EQ = 36,
- OP_NEQ = 37
-};
-
-enum {
- FUNC_SQRT1 = 0,
- FUNC_SQRT2 = 1,
- FUNC_SQRT3 = 6,
-
- FUNC_SQR = 5,
- FUNC_ABS = 7,
- FUNC_RAND = 10
-};
-
-enum {
- // FIXME: The following two 'truth values' are stored inside the list
- // of "operators". So they somehow coincide with OP_LOAD_VAR_UINT32
- // and OP_LOAD_VAR_UINT32_AS_UINT16. I haven't yet quite understood
- // how, resp. what that means. You have been warned.
- GOB_TRUE = 24,
- GOB_FALSE = 23
-};
-
-class Parse {
-public:
- void skipExpr(char stopToken);
- void printExpr(char stopToken);
- void printVarIndex(void);
-
- int16 parseVarIndex(uint16 *arg_0 = 0, uint16 *arg_4 = 0);
- int16 parseValExpr(byte stopToken = 99);
- int16 parseExpr(byte stopToken, byte *resultPtr);
-
- Parse(GobEngine *vm);
- virtual ~Parse() {}
-
-private:
- enum PointerType {
- kExecPtr = 0,
- kInterVar = 1,
- kResStr = 2
- };
-
- GobEngine *_vm;
-
- int32 encodePtr(byte *ptr, int type);
- byte *decodePtr(int32 n);
-
- void printExpr_internal(char stopToken);
-
- int16 getOffset(int16 arg_0, byte arg_2, uint32 arg_3, uint16 arg_7, uint16 arg_9);
- int cmpHelper(byte *operPtr, int32 *valPtr);
-};
-
-} // End of namespace Gob
-
-#endif // GOB_PARSE_H
diff --git a/engines/gob/resources.cpp b/engines/gob/resources.cpp
new file mode 100644
index 0000000000..20427e547b
--- /dev/null
+++ b/engines/gob/resources.cpp
@@ -0,0 +1,706 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/util.h"
+#include "common/endian.h"
+#include "common/stream.h"
+
+#include "gob/gob.h"
+#include "gob/resources.h"
+#include "gob/totfile.h"
+#include "gob/dataio.h"
+#include "gob/game.h"
+#include "gob/global.h"
+
+namespace Gob {
+
+Resource::Resource(byte *data, int32 size, bool needFree,
+ int16 width, int16 height) {
+
+ _data = data;
+ _size = size;
+ _width = width;
+ _height = height;
+ _needFree = needFree;
+
+ _stream = new Common::MemoryReadStream(data, size);
+}
+
+Resource::~Resource() {
+ delete _stream;
+
+ if (_needFree)
+ delete[] _data;
+}
+
+byte *Resource::getData() const {
+ return _data;
+}
+
+int32 Resource::getSize() const {
+ return _size;
+}
+
+int16 Resource::getWidth() const {
+ return _width;
+}
+
+int16 Resource::getHeight() const {
+ return _height;
+}
+
+Common::MemoryReadStream *Resource::stream() const {
+ return _stream;
+}
+
+
+TextItem::TextItem(byte *data, int32 size) {
+ _data = data;
+ _size = size;
+
+ _stream = new Common::MemoryReadStream(data, size);
+}
+
+TextItem::~TextItem() {
+ delete _stream;
+}
+
+byte *TextItem::getData() const {
+ return _data;
+}
+
+int32 TextItem::getSize() const {
+ return _size;
+}
+
+Common::MemoryReadStream *TextItem::stream() const {
+ return _stream;
+}
+
+
+Resources::TOTResourceTable::TOTResourceTable() {
+ items = 0;
+}
+
+Resources::TOTResourceTable::~TOTResourceTable() {
+ delete[] items;
+}
+
+
+Resources::EXTResourceTable::EXTResourceTable() {
+ itemsCount = 0;
+ unknown = 0;
+ items = 0;
+}
+
+Resources::EXTResourceTable::~EXTResourceTable() {
+ delete[] items;
+}
+
+
+Resources::TOTTextTable::TOTTextTable() {
+ items = 0;
+ data = 0;
+ needFree = false;
+}
+
+Resources::TOTTextTable::~TOTTextTable() {
+ delete[] items;
+ if (needFree)
+ delete[] data;
+}
+
+
+Resources::Resources(GobEngine *vm) : _vm(vm) {
+ unload(false);
+}
+
+Resources::~Resources() {
+ unload();
+}
+
+bool Resources::load(const Common::String &fileName) {
+ unload();
+
+ Common::String fileBase;
+
+ _totFile = TOTFile::createFileName(fileName, _hasLOM);
+
+ if (_hasLOM) {
+ warning("Stub: Resources::load(%s)", fileName.c_str());
+ unload();
+ return false;
+ }
+
+ fileBase = TOTFile::getFileBase(fileName);
+
+ _extFile = fileBase + ".ext";
+
+ if (!loadTOTResourceTable()) {
+ unload();
+ return false;
+ }
+
+ if (!loadEXTResourceTable()) {
+ unload();
+ return false;
+ }
+
+ if (!loadTOTTextTable(fileBase)) {
+ unload();
+ return false;
+ }
+
+ if (!loadIMFile()) {
+ unload();
+ return false;
+ }
+
+ if (!loadEXFile()) {
+ unload();
+ return false;
+ }
+
+ return true;
+}
+
+void Resources::unload(bool del) {
+ if (del) {
+ delete _totResourceTable;
+ delete _extResourceTable;
+ delete _totTextTable;
+
+ delete[] _totData;
+ delete[] _imData;
+
+ _totFile.clear();
+ _extFile.clear();
+ _exFile.clear();
+ }
+
+ _totResourceTable = 0;
+ _extResourceTable = 0;
+ _totTextTable = 0;
+ _totData = 0;
+ _totSize = 0;
+ _imData = 0;
+ _imSize = 0;
+}
+
+bool Resources::isLoaded() const {
+ return (_totResourceTable != 0);
+}
+
+bool Resources::loadTOTResourceTable() {
+ TOTFile totFile(_vm);
+
+ if (!totFile.load(_totFile))
+ return false;
+
+ TOTFile::Properties totProps;
+ if (!totFile.getProperties(totProps))
+ return false;
+
+ Common::SeekableReadStream *stream = totFile.getStream();
+ if (!stream)
+ return false;
+
+ if ((totProps.resourcesOffset == 0xFFFFFFFF) ||
+ (totProps.resourcesOffset == 0))
+ // No resources here
+ return false;
+
+ _totResourceTable = new TOTResourceTable;
+
+ stream->seek(totProps.resourcesOffset);
+ _totResourceTable->itemsCount = stream->readSint16LE();
+
+ _totResourceTable->dataOffset = totProps.resourcesOffset + kTOTResTableSize +
+ _totResourceTable->itemsCount * kTOTResItemSize;
+
+
+ uint32 resSize = _totResourceTable->itemsCount * kTOTResItemSize +
+ kTOTResTableSize;
+
+ // Would the table actually fit into the TOT?
+ if ((totProps.resourcesOffset + resSize) > ((uint32) stream->size()))
+ return false;
+
+ _totResourceTable->unknown = stream->readByte();
+ _totResourceTable->items = new TOTResourceItem[_totResourceTable->itemsCount];
+
+ for (int i = 0; i < _totResourceTable->itemsCount; ++i) {
+ TOTResourceItem &item = _totResourceTable->items[i];
+
+ item.offset = stream->readSint32LE();
+ item.size = stream->readSint16LE();
+ item.width = stream->readSint16LE();
+ item.height = stream->readSint16LE();
+
+ if (item.offset < 0) {
+ item.type = kResourceIM;
+ item.index = -item.offset - 1;
+ } else
+ item.type = kResourceTOT;
+ }
+
+ _totResStart = totProps.scriptEnd;
+ _totSize = stream->size() - _totResStart;
+ if (_totSize <= 0)
+ return false;
+
+ if (!stream->seek(totProps.scriptEnd))
+ return false;
+
+ _totData = new byte[_totSize];
+ if (stream->read(_totData, _totSize) != _totSize)
+ return false;
+
+ return !stream->err();
+}
+
+bool Resources::loadEXTResourceTable() {
+ _extResourceTable = new EXTResourceTable;
+
+ DataStream *stream = _vm->_dataIO->getDataStream(_extFile.c_str());
+ if (!stream)
+ return true;
+
+ _extResourceTable->itemsCount = stream->readSint16LE();
+ _extResourceTable->unknown = stream->readByte();
+
+ if (_extResourceTable->itemsCount > 0)
+ _extResourceTable->items = new EXTResourceItem[_extResourceTable->itemsCount];
+
+ for (int i = 0; i < _extResourceTable->itemsCount; i++) {
+ EXTResourceItem &item = _extResourceTable->items[i];
+
+ item.offset = stream->readUint32LE();
+ item.size = stream->readUint16LE();
+ item.width = stream->readUint16LE();
+ item.height = stream->readUint16LE();
+
+ if (item.offset < 0) {
+ item.type = kResourceEX;
+ item.offset = -item.offset - 1;
+ } else {
+ item.type = kResourceEXT;
+ item.offset += kEXTResTableSize +
+ kEXTResItemSize * _extResourceTable->itemsCount;
+ }
+
+ item.packed = (item.width & 0x8000) != 0;
+
+ item.width &= 0x7FFF;
+ }
+
+ delete stream;
+ return true;
+}
+
+bool Resources::loadTOTTextTable(const Common::String &fileBase) {
+ TOTFile totFile(_vm);
+
+ if (!totFile.load(_totFile))
+ return false;
+
+ TOTFile::Properties totProps;
+ if (!totFile.getProperties(totProps))
+ return false;
+
+ Common::SeekableReadStream *stream = totFile.getStream();
+ if (!stream)
+ return false;
+
+ if (totProps.textsOffset == ((uint32) -1))
+ // No texts
+ return true;
+
+ _totTextTable = new TOTTextTable;
+
+ bool fromTOT;
+ if (totProps.textsOffset == 0) {
+ fromTOT = false;
+ _totTextTable->data = loadTOTLocTexts(fileBase, _totTextTable->size);
+ _totTextTable->needFree = true;
+ } else {
+ fromTOT = true;
+ _totTextTable->data = _totData + totProps.textsOffset - _totResStart;
+ _totTextTable->needFree = false;
+ _totTextTable->size = _totSize - totProps.textsOffset;
+ }
+
+ if (_totTextTable->data) {
+ Common::MemoryReadStream totTextTable(_totTextTable->data, _totTextTable->size);
+ _totTextTable->itemsCount = totTextTable.readSint16LE() & 0x3FFF;
+
+ _totTextTable->items = new TOTTextItem[_totTextTable->itemsCount];
+ for (int i = 0; i < _totTextTable->itemsCount; ++i) {
+ TOTTextItem &item = _totTextTable->items[i];
+
+ item.offset = totTextTable.readSint16LE();
+ item.size = totTextTable.readSint16LE();
+
+ if (fromTOT)
+ item.offset -= (totProps.textsOffset - _totResStart);
+ }
+ }
+
+ return true;
+}
+
+bool Resources::loadIMFile() {
+ TOTFile totFile(_vm);
+
+ if (!totFile.load(_totFile))
+ return false;
+
+ TOTFile::Properties totProps;
+ if (!totFile.getProperties(totProps))
+ return false;
+
+ if ((totProps.communHandling != 0) && (totProps.imFileNumber == 0))
+ // No IM file
+ return true;
+
+ Common::String imFile = "commun.im";
+
+ char num = totProps.imFileNumber + '0';
+ if (num == '0')
+ num = '1';
+
+ imFile += num;
+
+ DataStream *stream = _vm->_dataIO->getDataStream(imFile.c_str());
+ if (!stream)
+ return true;
+
+ _imSize = stream->size();
+ if (_imSize <= 0) {
+ _imSize = 0;
+ delete stream;
+ return true;
+ }
+
+ _imData = new byte[_imSize];
+ if (stream->read(_imData, _imSize) != _imSize) {
+ delete[] _imData;
+ _imData = 0;
+ _imSize = 0;
+ }
+
+ delete stream;
+ return true;
+}
+
+bool Resources::loadEXFile() {
+ TOTFile totFile(_vm);
+
+ if (!totFile.load(_totFile))
+ return false;
+
+ TOTFile::Properties totProps;
+ if (!totFile.getProperties(totProps))
+ return false;
+
+ _exFile = "commun.ex";
+ _exFile += totProps.exFileNumber + '0';
+
+ if (!_vm->_dataIO->existData(_exFile.c_str())) {
+ _exFile.clear();
+ return true;
+ }
+
+ return true;
+}
+
+Common::String Resources::getLocTextFile(const Common::String &fileBase,
+ int language) {
+
+ Common::String locTextFile = fileBase + ".";
+ switch (language) {
+ case kLanguageFrench:
+ locTextFile += "dat";
+ break;
+ case kLanguageGerman:
+ locTextFile += "all";
+ break;
+ case kLanguageSpanish:
+ locTextFile += "esp";
+ break;
+ case kLanguageItalian:
+ locTextFile += "ita";
+ break;
+ case kLanguageAmerican:
+ locTextFile += "usa";
+ break;
+ case kLanguageDutch:
+ locTextFile += "ndl";
+ break;
+ case kLanguageKorean:
+ locTextFile += "kor";
+ break;
+ case kLanguageHebrew:
+ locTextFile += "isr";
+ break;
+ default:
+ locTextFile += "ang";
+ break;
+ }
+
+ if (!_vm->_dataIO->existData(locTextFile.c_str()))
+ locTextFile.clear();
+
+ return locTextFile;
+}
+
+byte *Resources::loadTOTLocTexts(const Common::String &fileBase, int32 &size) {
+ Common::String locTextFile;
+
+ locTextFile = getLocTextFile(fileBase, _vm->_global->_languageWanted);
+
+ if (!locTextFile.empty()) {
+
+ _vm->_global->_foundLanguage = true;
+ _vm->_global->_language = _vm->_global->_languageWanted;
+
+ } else if (!_vm->_global->_foundLanguage) {
+
+ // Trying US for GB and vice versa
+ if (_vm->_global->_languageWanted == kLanguageBritish) {
+
+ locTextFile = getLocTextFile(fileBase, kLanguageAmerican);
+ if (!locTextFile.empty())
+ _vm->_global->_language = kLanguageAmerican;
+
+ } else if (_vm->_global->_languageWanted == kLanguageAmerican) {
+
+ locTextFile = getLocTextFile(fileBase, kLanguageBritish);
+ if (!locTextFile.empty())
+ _vm->_global->_language = kLanguageBritish;
+
+ }
+
+ if (locTextFile.empty()) {
+ // Looking for the first existing language
+ for (int i = 0; i < 10; i++) {
+ locTextFile = getLocTextFile(fileBase, i);
+ if (!locTextFile.empty()) {
+ _vm->_global->_language = i;
+ break;
+ }
+ }
+ }
+
+ }
+
+ debugC(1, kDebugFileIO, "Using language %d for %s",
+ _vm->_global->_language, _totFile.c_str());
+
+ if (locTextFile.empty())
+ return 0;
+
+ size = _vm->_dataIO->getDataSize(locTextFile.c_str());
+ return _vm->_dataIO->getData(locTextFile.c_str());
+}
+
+Resource *Resources::getResource(uint16 id, int16 *width, int16 *height) const {
+ if (_hasLOM) {
+ warning("Stub: Resources::getResource(): Has LOM");
+ return 0;
+ }
+
+ Resource *resource = 0;
+ if (id >= 30000)
+ resource = getEXTResource(id - 30000);
+ else
+ resource = getTOTResource(id);
+
+ if (!resource)
+ return 0;
+
+ if (width)
+ *width = resource->getWidth();
+ if (height)
+ *height = resource->getHeight();
+
+ return resource;
+}
+
+TextItem *Resources::getTextItem(uint16 id) const {
+ if (!_totTextTable || !_totTextTable->data)
+ return 0;
+
+ if (id >= _totTextTable->itemsCount)
+ return 0;
+
+ TOTTextItem &totItem = _totTextTable->items[id];
+
+ if ((totItem.offset == 0xFFFF) || (totItem.size == 0))
+ return 0;
+ if ((totItem.offset + totItem.size) > (_totTextTable->size))
+ return 0;
+
+ return new TextItem(_totTextTable->data + totItem.offset, totItem.size);
+}
+
+byte *Resources::getTexts() const {
+ if (!_totTextTable)
+ return 0;
+
+ return _totTextTable->data;
+}
+
+Resource *Resources::getTOTResource(uint16 id) const {
+ if (id >= _totResourceTable->itemsCount) {
+ warning("Trying to load non-existent TOT resource (%s, %d/%d)",
+ _totFile.c_str(), id, _totResourceTable->itemsCount - 1);
+ return 0;
+ }
+
+ TOTResourceItem &totItem = _totResourceTable->items[id];
+
+ byte *data = 0;
+ if (totItem.type == kResourceIM)
+ data = getIMData(totItem);
+ if (totItem.type == kResourceTOT)
+ data = getTOTData(totItem);
+
+ if (!data)
+ return 0;
+
+ return new Resource(data, totItem.size, false, totItem.width, totItem.height);
+}
+
+Resource *Resources::getEXTResource(uint16 id) const {
+ if (!_extResourceTable || (id > _extResourceTable->itemsCount))
+ return 0;
+
+ EXTResourceItem &extItem = _extResourceTable->items[id];
+
+ uint32 size = extItem.size;
+
+ if (extItem.width & 0x4000)
+ size += 1 << 16;
+ if (extItem.width & 0x2000)
+ size += 2 << 16;
+ if (extItem.width & 0x1000)
+ size += 4 << 16;
+ if (extItem.height == 0)
+ size += extItem.width << 16;
+
+ byte *data = 0;
+ if (extItem.type == kResourceEXT)
+ data = getEXTData(extItem, size);
+ if (extItem.type == kResourceEX)
+ data = getEXData(extItem, size);
+
+ if (!data)
+ return 0;
+
+ if (extItem.packed) {
+ byte *packedData = data;
+
+ size = READ_LE_UINT32(packedData);
+ data = new byte[size];
+
+ _vm->_dataIO->unpackData(packedData, data);
+
+ delete[] packedData;
+ }
+
+ return new Resource(data, size, true, extItem.width & 0xFFF, extItem.height);
+}
+
+byte *Resources::getTOTData(TOTResourceItem &totItem) const {
+ if (totItem.size < 0)
+ return 0;
+
+ int32 offset = _totResourceTable->dataOffset + totItem.offset - _totResStart;
+
+ if ((offset < 0) || (((uint32) (offset + totItem.size)) > _totSize))
+ return 0;
+
+ return _totData + offset;
+}
+
+byte *Resources::getIMData(TOTResourceItem &totItem) const {
+ if (totItem.size < 0)
+ return 0;
+
+ int32 indexOffset = totItem.index * 4;
+ if ((indexOffset < 0) || (((uint32) indexOffset) >= _imSize))
+ return 0;
+
+ uint32 offset = READ_LE_UINT32(_imData + indexOffset);
+ if ((offset + totItem.size) > _imSize)
+ return 0;
+
+ return _imData + offset;
+}
+
+byte *Resources::getEXTData(EXTResourceItem &extItem, uint32 size) const {
+ DataStream *stream = _vm->_dataIO->getDataStream(_extFile.c_str());
+ if (!stream)
+ return 0;
+
+ if (!stream->seek(extItem.offset)) {
+ delete stream;
+ return 0;
+ }
+
+ byte *data = new byte[extItem.packed ? (size + 2) : size];
+ if (stream->read(data, size) != size) {
+ delete[] data;
+ delete stream;
+ return 0;
+ }
+
+ delete stream;
+ return data;
+}
+
+byte *Resources::getEXData(EXTResourceItem &extItem, uint32 size) const {
+ DataStream *stream = _vm->_dataIO->getDataStream(_exFile.c_str());
+ if (!stream)
+ return 0;
+
+ if (!stream->seek(extItem.offset)) {
+ delete stream;
+ return 0;
+ }
+
+ byte *data = new byte[extItem.packed ? (size + 2) : size];
+ if (stream->read(data, size) != size) {
+ delete[] data;
+ delete stream;
+ return 0;
+ }
+
+ delete stream;
+ return data;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/resources.h b/engines/gob/resources.h
new file mode 100644
index 0000000000..80acef645c
--- /dev/null
+++ b/engines/gob/resources.h
@@ -0,0 +1,207 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_RESOURCES_H
+#define GOB_RESOURCES_H
+
+#include "common/str.h"
+
+namespace Common {
+ class MemoryReadStream;
+}
+
+namespace Gob {
+
+class GobEngine;
+
+class Resource {
+public:
+ Resource(byte *data, int32 size, bool needFree = true,
+ int16 width = 0, int16 height = 0);
+ ~Resource();
+
+ byte *getData () const;
+ int32 getSize () const;
+ int16 getWidth () const;
+ int16 getHeight() const;
+
+ Common::MemoryReadStream *stream() const;
+
+private:
+ byte *_data;
+ int32 _size;
+ int16 _width;
+ int16 _height;
+ bool _needFree;
+
+ Common::MemoryReadStream *_stream;
+};
+
+class TextItem {
+public:
+ TextItem(byte *data, int32 size);
+ ~TextItem();
+
+ byte *getData() const;
+ int32 getSize() const;
+
+ Common::MemoryReadStream *stream() const;
+
+private:
+ byte *_data;
+ int32 _size;
+
+ Common::MemoryReadStream *_stream;
+};
+
+class Resources {
+public:
+ Resources(GobEngine *vm);
+ ~Resources();
+
+ bool load(const Common::String &fileName);
+ void unload(bool del = true);
+
+ bool isLoaded() const;
+
+ Resource *getResource(uint16 id, int16 *width = 0, int16 *height = 0) const;
+ TextItem *getTextItem(uint16 id) const;
+
+ byte *getTexts() const;
+
+private:
+ // Structure sizes in the files
+ static const int kTOTResItemSize = 4 + 2 + 2 + 2;
+ static const int kTOTResTableSize = 2 + 1;
+ static const int kEXTResItemSize = 4 + 2 + 2 + 2;
+ static const int kEXTResTableSize = 2 + 1;
+ static const int kTOTTextTableSize = 2;
+ static const int kTOTTextItemSize = 2 + 2;
+
+ enum ResourceType {
+ kResourceTOT,
+ kResourceIM,
+ kResourceEXT,
+ kResourceEX
+ };
+
+ struct TOTResourceItem {
+ ResourceType type;
+ int16 size;
+ int16 width;
+ int16 height;
+ union {
+ int32 offset;
+ int32 index;
+ };
+ };
+
+ struct TOTResourceTable {
+ int16 itemsCount;
+ byte unknown;
+ TOTResourceItem *items;
+ uint32 dataOffset;
+
+ TOTResourceTable();
+ ~TOTResourceTable();
+ };
+
+ struct EXTResourceItem {
+ ResourceType type;
+ int32 offset;
+ uint16 size;
+ int16 width;
+ int16 height;
+ bool packed;
+ };
+
+ struct EXTResourceTable {
+ int16 itemsCount;
+ byte unknown;
+ EXTResourceItem *items;
+
+ EXTResourceTable();
+ ~EXTResourceTable();
+ };
+
+ struct TOTTextItem {
+ uint16 offset;
+ int16 size;
+ };
+
+ struct TOTTextTable {
+ bool needFree;
+ int16 itemsCount;
+
+ byte *data;
+ int32 size;
+
+ TOTTextItem *items;
+
+ TOTTextTable();
+ ~TOTTextTable();
+ };
+
+ GobEngine *_vm;
+
+ Common::String _totFile;
+ Common::String _extFile;
+ Common::String _exFile;
+
+ byte *_totData;
+ uint32 _totSize;
+
+ byte *_imData;
+ uint32 _imSize;
+
+ bool _hasLOM;
+ int32 _totResStart;
+
+ TOTResourceTable *_totResourceTable;
+ EXTResourceTable *_extResourceTable;
+ TOTTextTable *_totTextTable;
+
+ bool loadTOTResourceTable();
+ bool loadEXTResourceTable();
+ bool loadTOTTextTable(const Common::String &fileBase);
+ bool loadIMFile();
+ bool loadEXFile();
+
+ byte *loadTOTLocTexts(const Common::String &fileBase, int32 &size);
+ bool getLocTextFile(char *locTextFile, int language);
+ Common::String getLocTextFile(const Common::String &fileBase, int language);
+
+ Resource *getTOTResource(uint16 id) const;
+ Resource *getEXTResource(uint16 id) const;
+
+ byte *getTOTData(TOTResourceItem &totItem) const;
+ byte *getIMData(TOTResourceItem &totItem) const;
+ byte *getEXTData(EXTResourceItem &extItem, uint32 size) const;
+ byte *getEXData(EXTResourceItem &extItem, uint32 size) const;
+};
+
+} // End of namespace Gob
+
+#endif // GOB_RESOURCES_H
diff --git a/engines/gob/save/savefile.h b/engines/gob/save/savefile.h
index 989a37277e..615be8e0f2 100644
--- a/engines/gob/save/savefile.h
+++ b/engines/gob/save/savefile.h
@@ -163,7 +163,7 @@ public:
bool readPalette(const byte *palette);
/** Read a sprite into the part. */
bool readSprite(const SurfaceDesc &sprite);
-
+
/** Read size bytes of raw data into the sprite. */
bool readSpriteRaw(const byte *data, uint32 size);
diff --git a/engines/gob/save/saveload.cpp b/engines/gob/save/saveload.cpp
index abda2f8a65..81239f07dc 100644
--- a/engines/gob/save/saveload.cpp
+++ b/engines/gob/save/saveload.cpp
@@ -61,7 +61,7 @@ int32 SaveLoad::getSize(const char *fileName) {
int32 size = handler->getSize();
debugC(4, kDebugSaveLoad, "Size is %d", size);
-
+
return size;
}
diff --git a/engines/gob/save/saveload_v3.cpp b/engines/gob/save/saveload_v3.cpp
index 2f89644ee0..58232e6991 100644
--- a/engines/gob/save/saveload_v3.cpp
+++ b/engines/gob/save/saveload_v3.cpp
@@ -302,7 +302,7 @@ bool SaveLoad_v3::GameHandler::createReader(int slot) {
if (!_reader || (_reader->getSlot() != ((uint32) slot))) {
Common::String slotFile = _slotFile->build(slot);
-
+
if (slotFile.empty())
return false;
@@ -319,7 +319,7 @@ bool SaveLoad_v3::GameHandler::createReader(int slot) {
} else
_reader = new SaveReader(_usesScreenshots ? 3 : 2, slot, slotFile);
-
+
if (!_reader->load()) {
delete _reader;
_reader = 0;
@@ -337,7 +337,7 @@ bool SaveLoad_v3::GameHandler::createWriter(int slot) {
if (!_writer || (_writer->getSlot() != ((uint32) slot))) {
Common::String slotFile = _slotFile->build(slot);
-
+
if (slotFile.empty())
return false;
@@ -495,7 +495,7 @@ SaveLoad_v3::SaveLoad_v3(GobEngine *vm, const char *targetName, ScreenshotType s
_gameHandler = new GameHandler(vm, targetName, true);
_screenshotHandler = new ScreenshotHandler(vm, _gameHandler, sShotType);
}
-
+
_tempSpriteHandler = new TempSpriteHandler(vm);
_notesHandler = new NotesHandler(2560, vm, targetName);
diff --git a/engines/gob/save/saveload_v4.cpp b/engines/gob/save/saveload_v4.cpp
index 6e1d5208ff..06280af2a6 100644
--- a/engines/gob/save/saveload_v4.cpp
+++ b/engines/gob/save/saveload_v4.cpp
@@ -317,7 +317,7 @@ bool SaveLoad_v4::GameHandler::createReader(int slot) {
if (!_reader || (_reader->getSlot() != ((uint32) slot))) {
Common::String slotFile = _slotFile->build(slot);
-
+
if (slotFile.empty())
return false;
@@ -334,7 +334,7 @@ bool SaveLoad_v4::GameHandler::createReader(int slot) {
} else
_reader = new SaveReader(3, slot, slotFile);
-
+
if (!_reader->load()) {
delete _reader;
_reader = 0;
@@ -352,7 +352,7 @@ bool SaveLoad_v4::GameHandler::createWriter(int slot) {
if (!_writer || (_writer->getSlot() != ((uint32) slot))) {
Common::String slotFile = _slotFile->build(slot);
-
+
if (slotFile.empty())
return false;
diff --git a/engines/gob/scenery.cpp b/engines/gob/scenery.cpp
index 71750509b4..7a4b8ad868 100644
--- a/engines/gob/scenery.cpp
+++ b/engines/gob/scenery.cpp
@@ -31,6 +31,8 @@
#include "gob/global.h"
#include "gob/draw.h"
#include "gob/game.h"
+#include "gob/script.h"
+#include "gob/resources.h"
#include "gob/inter.h"
#include "gob/map.h"
#include "gob/videoplayer.h"
@@ -39,33 +41,33 @@ namespace Gob {
Scenery::Scenery(GobEngine *vm) : _vm(vm) {
for (int i = 0; i < 20; i++) {
- _spriteRefs[i] = 0;
+ _spriteRefs[i] = 0;
_spriteResId[i] = 0;
}
for (int i = 0; i < 10; i++) {
_staticPictCount[i] = 0;
- _staticResId[i] = 0;
- _animPictCount[i] = 0;
- _animResId[i] = 0;
+ _staticResId[i] = 0;
+ _animPictCount[i] = 0;
+ _animResId[i] = 0;
}
- _curStatic = 0;
+ _curStatic = 0;
_curStaticLayer = 0;
- _toRedrawLeft = 0;
- _toRedrawRight = 0;
- _toRedrawTop = 0;
+ _toRedrawLeft = 0;
+ _toRedrawRight = 0;
+ _toRedrawTop = 0;
_toRedrawBottom = 0;
- _animTop = 0;
+ _animTop = 0;
_animLeft = 0;
_pCaptureCounter = 0;
for (int i = 0; i < 70; i++ ) {
_staticPictToSprite[i] = 0;
- _animPictToSprite[i] = 0;
+ _animPictToSprite[i] = 0;
}
}
@@ -78,17 +80,17 @@ Scenery::~Scenery() {
void Scenery::init() {
for (int i = 0; i < 10; i++) {
- _animPictCount[i] = 0;
+ _animPictCount[i] = 0;
_staticPictCount[i] = -1;
}
for (int i = 0; i < 20; i++) {
- _spriteRefs[i] = 0;
+ _spriteRefs[i] = 0;
_spriteResId[i] = -1;
}
_curStaticLayer = -1;
- _curStatic = -1;
+ _curStatic = -1;
}
int16 Scenery::loadStatic(char search) {
@@ -97,28 +99,26 @@ int16 Scenery::loadStatic(char search) {
int16 picsCount;
int16 resId;
int16 sceneryIndex;
- byte *extData = 0;
- byte *dataPtr;
Static *ptr;
int16 width;
int16 height;
int16 sprResId;
int16 sprIndex;
- _vm->_inter->evalExpr(&sceneryIndex);
+ _vm->_game->_script->evalExpr(&sceneryIndex);
- size = _vm->_inter->load16();
- backsPtr = (int16 *) _vm->_global->_inter_execPtr;
- _vm->_global->_inter_execPtr += size * 2;
- picsCount = _vm->_inter->load16();
- resId = _vm->_inter->load16();
+ size = _vm->_game->_script->readInt16();
+ backsPtr = (int16 *) (_vm->_game->_script->getData() + _vm->_game->_script->pos());
+ _vm->_game->_script->skip(size * 2);
+ picsCount = _vm->_game->_script->readInt16();
+ resId = _vm->_game->_script->readInt16();
if (search) {
int i;
for (i = 0; i < 10; i++) {
if ((_staticPictCount[i] != -1) && (_staticResId[i] == resId)) {
- _vm->_global->_inter_execPtr += 8 * _staticPictCount[i];
+ _vm->_game->_script->skip(8 * _staticPictCount[i]);
return i;
}
@@ -128,52 +128,54 @@ int16 Scenery::loadStatic(char search) {
}
_staticPictCount[sceneryIndex] = picsCount;
- _staticResId[sceneryIndex] = resId;
+ _staticResId[sceneryIndex] = resId;
- if (resId >= 30000) {
- extData = _vm->_game->loadExtData(resId, 0, 0);
- dataPtr = extData;
- } else
- dataPtr = _vm->_game->loadTotResource(resId);
+ Resource *resource = _vm->_game->_resources->getResource((uint16) resId);
+ if (!resource)
+ return 0;
ptr = &_statics[sceneryIndex];
- ptr->layersCount = (int16) READ_LE_UINT16(dataPtr);
- dataPtr += 2;
+ ptr->layersCount = resource->stream()->readSint16LE();
ptr->layers = new StaticLayer[ptr->layersCount];
for (int i = 0; i < ptr->layersCount; i++) {
- int16 offset = READ_LE_UINT16(dataPtr + i * 2);
- Common::MemoryReadStream layerData(dataPtr + offset, 4294967295U);
+ Common::SeekableReadStream &layerData = *resource->stream();
- ptr->layers[i].planeCount = layerData.readSint16LE();
+ layerData.seek(2 + i * 2);
+ layerData.seek(layerData.readUint16LE());
- ptr->layers[i].planes = new StaticPlane[ptr->layers[i].planeCount];
- for (int j = 0; j < ptr->layers[i].planeCount; ++j) {
- ptr->layers[i].planes[j].pictIndex = layerData.readByte();
- ptr->layers[i].planes[j].pieceIndex = layerData.readByte();
- ptr->layers[i].planes[j].drawOrder = layerData.readByte();
- ptr->layers[i].planes[j].destX = layerData.readSint16LE();
- ptr->layers[i].planes[j].destY = layerData.readSint16LE();
- ptr->layers[i].planes[j].transp = layerData.readSByte();
- }
+ ptr->layers[i].backResId = layerData.readSint16LE();
+ ptr->layers[i].planeCount = layerData.readSint16LE();
+ if (ptr->layers[i].planeCount > 0) {
+ ptr->layers[i].planes = new StaticPlane[ptr->layers[i].planeCount];
+ for (int j = 0; j < ptr->layers[i].planeCount; j++) {
+ ptr->layers[i].planes[j].pictIndex = layerData.readByte();
+ ptr->layers[i].planes[j].pieceIndex = layerData.readByte();
+ ptr->layers[i].planes[j].drawOrder = layerData.readByte();
+ ptr->layers[i].planes[j].destX = layerData.readSint16LE();
+ ptr->layers[i].planes[j].destY = layerData.readSint16LE();
+ ptr->layers[i].planes[j].transp = layerData.readSByte();
+ }
+ } else
+ ptr->layers[i].planes = 0;
ptr->layers[i].backResId = (int16) READ_LE_UINT16(backsPtr);
backsPtr++;
}
- ptr->pieces = new PieceDesc*[picsCount];
+ ptr->pieces = new PieceDesc*[picsCount];
ptr->piecesCount = new uint32[picsCount];
for (int i = 0; i < picsCount; i++) {
- int16 pictDescId = _vm->_inter->load16();
+ int16 pictDescId = _vm->_game->_script->readInt16();
loadPieces(pictDescId, ptr->pieces[i], ptr->piecesCount[i]);
- width = _vm->_inter->load16();
- height = _vm->_inter->load16();
- sprResId = _vm->_inter->load16();
+ width = _vm->_game->_script->readInt16();
+ height = _vm->_game->_script->readInt16();
+ sprResId = _vm->_game->_script->readInt16();
for (sprIndex = 0; sprIndex < 20; sprIndex++) {
if (_spriteResId[sprIndex] == sprResId)
break;
@@ -183,9 +185,7 @@ int16 Scenery::loadStatic(char search) {
_staticPictToSprite[7 * sceneryIndex + i] = sprIndex;
_spriteRefs[sprIndex]++;
} else {
- for (sprIndex = 19; _vm->_draw->_spritesArray[sprIndex] != 0;
- sprIndex--)
- ;
+ for (sprIndex = 19; _vm->_draw->_spritesArray[sprIndex] != 0; sprIndex--);
_staticPictToSprite[7 * sceneryIndex + i] = sprIndex;
_spriteRefs[sprIndex] = 1;
@@ -193,17 +193,16 @@ int16 Scenery::loadStatic(char search) {
_vm->_draw->initSpriteSurf(sprIndex, width, height, 2);
_vm->_video->clearSurf(*_vm->_draw->_spritesArray[sprIndex]);
- _vm->_draw->_destSurface = sprIndex;
- _vm->_draw->_spriteLeft = sprResId;
+ _vm->_draw->_destSurface = sprIndex;
+ _vm->_draw->_spriteLeft = sprResId;
_vm->_draw->_transparency = 0;
- _vm->_draw->_destSpriteX = 0;
- _vm->_draw->_destSpriteY = 0;
+ _vm->_draw->_destSpriteX = 0;
+ _vm->_draw->_destSpriteY = 0;
_vm->_draw->spriteOperation(DRAW_LOADSPRITE);
}
}
- delete[] extData;
-
+ delete resource;
return sceneryIndex + 100;
}
@@ -211,7 +210,7 @@ void Scenery::freeStatic(int16 index) {
int16 spr;
if (index == -1)
- _vm->_inter->evalExpr(&index);
+ _vm->_game->_script->evalExpr(&index);
if (_staticPictCount[index] == -1)
return;
@@ -229,12 +228,13 @@ void Scenery::freeStatic(int16 index) {
for (int i = 0; i < _statics[index].layersCount; i++)
delete[] _statics[index].layers[i].planes;
+
delete[] _statics[index].layers;
delete[] _statics[index].pieces;
delete[] _statics[index].piecesCount;
_statics[index].layersCount = 0;
- _staticPictCount[index] = -1;
+ _staticPictCount[index] = -1;
}
void Scenery::renderStatic(int16 scenery, int16 layer) {
@@ -261,22 +261,21 @@ void Scenery::renderStatic(int16 scenery, int16 layer) {
_vm->_draw->_spriteLeft = layerPtr->backResId;
if (_vm->_draw->_spriteLeft != -1) {
- _vm->_draw->_destSpriteX = 0;
- _vm->_draw->_destSpriteY = 0;
- _vm->_draw->_destSurface = 21;
- _vm->_draw->_transparency = 0;
+ _vm->_draw->_destSpriteX = 0;
+ _vm->_draw->_destSpriteY = 0;
+ _vm->_draw->_destSurface = 21;
+ _vm->_draw->_transparency = 0;
_vm->_draw->spriteOperation(DRAW_LOADSPRITE);
}
planeCount = layerPtr->planeCount;
for (order = 0; order < 100; order++) {
- for (plane = 0, planePtr = layerPtr->planes;
- plane < planeCount; plane++, planePtr++) {
+ for (plane = 0, planePtr = layerPtr->planes; plane < planeCount; plane++, planePtr++) {
if (planePtr->drawOrder != order)
continue;
pieceIndex = planePtr->pieceIndex;
- pictIndex = planePtr->pictIndex - 1;
+ pictIndex = planePtr->pictIndex - 1;
if (pictIndex >= _staticPictCount[scenery])
continue;
@@ -289,19 +288,19 @@ void Scenery::renderStatic(int16 scenery, int16 layer) {
_vm->_draw->_destSpriteX = planePtr->destX;
_vm->_draw->_destSpriteY = planePtr->destY;
- left = ptr->pieces[pictIndex][pieceIndex].left;
- right = ptr->pieces[pictIndex][pieceIndex].right;
- top = ptr->pieces[pictIndex][pieceIndex].top;
+ left = ptr->pieces[pictIndex][pieceIndex].left;
+ right = ptr->pieces[pictIndex][pieceIndex].right;
+ top = ptr->pieces[pictIndex][pieceIndex].top;
bottom = ptr->pieces[pictIndex][pieceIndex].bottom;
_vm->_draw->_sourceSurface =
_staticPictToSprite[scenery * 7 + pictIndex];
- _vm->_draw->_destSurface = 21;
- _vm->_draw->_spriteLeft = left;
- _vm->_draw->_spriteTop = top;
- _vm->_draw->_spriteRight = right - left + 1;
- _vm->_draw->_spriteBottom = bottom - top + 1;
- _vm->_draw->_transparency = planePtr->transp ? 3 : 0;
+ _vm->_draw->_destSurface = 21;
+ _vm->_draw->_spriteLeft = left;
+ _vm->_draw->_spriteTop = top;
+ _vm->_draw->_spriteRight = right - left + 1;
+ _vm->_draw->_spriteBottom = bottom - top + 1;
+ _vm->_draw->_transparency = planePtr->transp ? 3 : 0;
_vm->_draw->spriteOperation(DRAW_BLITSURF);
}
}
@@ -337,7 +336,7 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) {
continue;
pieceIndex = planePtr->pieceIndex;
- pictIndex = planePtr->pictIndex - 1;
+ pictIndex = planePtr->pictIndex - 1;
if (pictIndex >= _staticPictCount[index])
continue;
@@ -351,9 +350,9 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) {
_vm->_draw->_destSpriteX = planePtr->destX;
_vm->_draw->_destSpriteY = planePtr->destY;
- left = pictPtr[pictIndex][pieceIndex].left;
- right = pictPtr[pictIndex][pieceIndex].right;
- top = pictPtr[pictIndex][pieceIndex].top;
+ left = pictPtr[pictIndex][pieceIndex].left;
+ right = pictPtr[pictIndex][pieceIndex].right;
+ top = pictPtr[pictIndex][pieceIndex].top;
bottom = pictPtr[pictIndex][pieceIndex].bottom;
if (_vm->_draw->_destSpriteX > _toRedrawRight)
@@ -372,10 +371,10 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) {
_vm->_draw->_destSpriteY = _toRedrawTop;
}
- _vm->_draw->_spriteLeft = left;
- _vm->_draw->_spriteTop = top;
- _vm->_draw->_spriteRight = right - left + 1;
- _vm->_draw->_spriteBottom = bottom - top + 1;
+ _vm->_draw->_spriteLeft = left;
+ _vm->_draw->_spriteTop = top;
+ _vm->_draw->_spriteRight = right - left + 1;
+ _vm->_draw->_spriteBottom = bottom - top + 1;
if ((_vm->_draw->_spriteRight <= 0) ||
(_vm->_draw->_spriteBottom <= 0))
@@ -393,8 +392,8 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) {
_vm->_draw->_sourceSurface =
_staticPictToSprite[index * 7 + pictIndex];
- _vm->_draw->_destSurface = 21;
- _vm->_draw->_transparency = planePtr->transp ? 3 : 0;
+ _vm->_draw->_destSurface = 21;
+ _vm->_draw->_transparency = planePtr->transp ? 3 : 0;
_vm->_draw->spriteOperation(DRAW_BLITSURF);
}
}
@@ -422,8 +421,6 @@ int16 Scenery::loadAnim(char search) {
int16 j;
int16 sceneryIndex;
int16 framesCount;
- byte *extData;
- byte *dataPtr;
Animation *ptr;
int16 width;
int16 height;
@@ -431,15 +428,14 @@ int16 Scenery::loadAnim(char search) {
int16 sprIndex;
uint32 layerPos;
- extData = 0;
- _vm->_inter->evalExpr(&sceneryIndex);
- picsCount = _vm->_inter->load16();
- resId = _vm->_inter->load16();
+ _vm->_game->_script->evalExpr(&sceneryIndex);
+ picsCount = _vm->_game->_script->readInt16();
+ resId = _vm->_game->_script->readInt16();
if (search) {
for (i = 0; i < 10; i++) {
if ((_animPictCount[i] != 0) && (_animResId[i] == resId)) {
- _vm->_global->_inter_execPtr += 8 * _animPictCount[i];
+ _vm->_game->_script->skip(8 * _animPictCount[i]);
return i;
}
@@ -451,50 +447,50 @@ int16 Scenery::loadAnim(char search) {
_animPictCount[sceneryIndex] = picsCount;
_animResId[sceneryIndex] = resId;
- if (resId >= 30000) {
- extData = _vm->_game->loadExtData(resId, 0, 0);
- dataPtr = extData;
- } else
- dataPtr = _vm->_game->loadTotResource(resId);
+ Resource *resource = _vm->_game->_resources->getResource((uint16) resId);
+ if (!resource)
+ return 0;
ptr = &_animations[sceneryIndex];
- ptr->layersCount = READ_LE_UINT16(dataPtr);
- dataPtr += 2;
+ ptr->layersCount = resource->stream()->readSint16LE();
ptr->layers = new AnimLayer[ptr->layersCount];
for (i = 0; i < ptr->layersCount; i++) {
- int16 offset = READ_LE_UINT16(dataPtr + i * 2);
- Common::MemoryReadStream layerData(dataPtr + offset - 2, 4294967295U);
-
- ptr->layers[i].unknown0 = layerData.readSint16LE();
- ptr->layers[i].posX = layerData.readSint16LE();
- ptr->layers[i].posY = layerData.readSint16LE();
- ptr->layers[i].animDeltaX = layerData.readSint16LE();
- ptr->layers[i].animDeltaY = layerData.readSint16LE();
- ptr->layers[i].transp = layerData.readSByte();
+ Common::SeekableReadStream &layerData = *resource->stream();
+
+ layerData.seek(2 + i * 2);
+ layerData.seek(layerData.readUint16LE());
+
+ ptr->layers[i].unknown0 = layerData.readSint16LE();
+ ptr->layers[i].posX = layerData.readSint16LE();
+ ptr->layers[i].posY = layerData.readSint16LE();
+ ptr->layers[i].animDeltaX = layerData.readSint16LE();
+ ptr->layers[i].animDeltaY = layerData.readSint16LE();
+ ptr->layers[i].transp = layerData.readSByte();
ptr->layers[i].framesCount = layerData.readSint16LE();
+ // Going through the AnimFramePiece, finding the end for each
layerPos = layerData.pos();
framesCount = 0;
- layerData.seek(4, SEEK_CUR);
- for (j = 0; j < ptr->layers[i].framesCount;
- j++, framesCount++, layerData.seek(4, SEEK_CUR)) {
+ for (j = 0; j < ptr->layers[i].framesCount; j++) {
+ layerData.skip(4); // pictIndex, pieceIndex, destX, destY
while (layerData.readByte() == 1) {
framesCount++;
- layerData.seek(4, SEEK_CUR);
+ layerData.skip(4); // pictIndex, pieceIndex, destX, destY
}
+ framesCount++;
}
layerData.seek(layerPos);
ptr->layers[i].frames = new AnimFramePiece[framesCount];
for (j = 0; j < framesCount; j++) {
- ptr->layers[i].frames[j].pictIndex = layerData.readByte();
+ ptr->layers[i].frames[j].pictIndex = layerData.readByte();
ptr->layers[i].frames[j].pieceIndex = layerData.readByte();
- ptr->layers[i].frames[j].destX = layerData.readSByte();
- ptr->layers[i].frames[j].destY = layerData.readSByte();
- ptr->layers[i].frames[j].notFinal = layerData.readSByte();
+ ptr->layers[i].frames[j].destX = layerData.readSByte();
+ ptr->layers[i].frames[j].destY = layerData.readSByte();
+ ptr->layers[i].frames[j].notFinal = layerData.readSByte();
}
}
@@ -502,13 +498,13 @@ int16 Scenery::loadAnim(char search) {
ptr->piecesCount = new uint32[picsCount];
for (i = 0; i < picsCount; i++) {
- int16 pictDescId = _vm->_inter->load16();
+ int16 pictDescId = _vm->_game->_script->readInt16();
loadPieces(pictDescId, ptr->pieces[i], ptr->piecesCount[i]);
- width = _vm->_inter->load16();
- height = _vm->_inter->load16();
- sprResId = _vm->_inter->load16();
+ width = _vm->_game->_script->readInt16();
+ height = _vm->_game->_script->readInt16();
+ sprResId = _vm->_game->_script->readInt16();
for (sprIndex = 0; sprIndex < 20; sprIndex++)
if (_spriteResId[sprIndex] == sprResId)
break;
@@ -522,22 +518,21 @@ int16 Scenery::loadAnim(char search) {
;
_animPictToSprite[7 * sceneryIndex + i] = sprIndex;
- _spriteRefs[sprIndex] = 1;
+ _spriteRefs[sprIndex] = 1;
_spriteResId[sprIndex] = sprResId;
_vm->_draw->initSpriteSurf(sprIndex, width, height, 2);
_vm->_video->clearSurf(*_vm->_draw->_spritesArray[sprIndex]);
- _vm->_draw->_destSurface = sprIndex;
- _vm->_draw->_spriteLeft = sprResId;
+ _vm->_draw->_destSurface = sprIndex;
+ _vm->_draw->_spriteLeft = sprResId;
_vm->_draw->_transparency = 0;
- _vm->_draw->_destSpriteX = 0;
- _vm->_draw->_destSpriteY = 0;
+ _vm->_draw->_destSpriteX = 0;
+ _vm->_draw->_destSpriteY = 0;
_vm->_draw->spriteOperation(DRAW_LOADSPRITE);
}
}
- delete[] extData;
-
+ delete resource;
return sceneryIndex + 100;
}
@@ -545,7 +540,7 @@ void Scenery::freeAnim(int16 index) {
int16 spr;
if (index == -1)
- _vm->_inter->evalExpr(&index);
+ _vm->_game->_script->evalExpr(&index);
if (_animPictCount[index] == 0)
return;
@@ -563,6 +558,7 @@ void Scenery::freeAnim(int16 index) {
for (int i = 0; i < _animations[index].layersCount; i++)
delete[] _animations[index].layers[i].frames;
+
delete[] _animations[index].layers;
delete[] _animations[index].pieces;
delete[] _animations[index].piecesCount;
@@ -607,8 +603,8 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
return;
_vm->_game->capturePush(_toRedrawLeft, _toRedrawTop,
- _toRedrawRight - _toRedrawLeft + 1,
- _toRedrawBottom - _toRedrawTop + 1);
+ _toRedrawRight - _toRedrawLeft + 1,
+ _toRedrawBottom - _toRedrawTop + 1);
*_pCaptureCounter = *_pCaptureCounter + 1;
}
@@ -628,7 +624,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
while (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) <= frame)
_vm->_vidPlayer->slotPlay(obj.videoSlot - 1);
} else {
- int16 curFrame = _vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1);
+ int16 curFrame = _vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1);
uint8 frameWrap = curFrame / 256;
frame = (frame + 1) % 256;
@@ -636,17 +632,17 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
_vm->_vidPlayer->slotPlay(obj.videoSlot - 1);
}
- destX = 0;
- destY = 0;
- left = *(obj.pPosX);
- top = *(obj.pPosY);
- right = left + _vm->_vidPlayer->getWidth(obj.videoSlot - 1) - 1;
- bottom = top + _vm->_vidPlayer->getHeight(obj.videoSlot - 1) - 1;
+ destX = 0;
+ destY = 0;
+ left = *(obj.pPosX);
+ top = *(obj.pPosY);
+ right = left + _vm->_vidPlayer->getWidth(obj.videoSlot - 1) - 1;
+ bottom = top + _vm->_vidPlayer->getHeight(obj.videoSlot - 1) - 1;
if (flags & 2) {
if (left < _vm->_mult->_animLeft) {
destX += _vm->_mult->_animLeft - left;
- left = _vm->_mult->_animLeft;
+ left = _vm->_mult->_animLeft;
}
if ((_vm->_mult->_animLeft + _vm->_mult->_animWidth) <= right)
@@ -654,7 +650,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
if (top < _vm->_mult->_animTop) {
destY += _vm->_mult->_animTop - top;
- top = _vm->_mult->_animTop;
+ top = _vm->_mult->_animTop;
}
if ((_vm->_mult->_animTop + _vm->_mult->_animHeight) <= bottom)
@@ -663,7 +659,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
} else if (flags & 4) {
if (left < _toRedrawLeft) {
destX += _toRedrawLeft - left;
- left = _toRedrawLeft;
+ left = _toRedrawLeft;
}
if (right > _toRedrawRight)
@@ -671,16 +667,16 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
if (top < _toRedrawTop) {
destY += _toRedrawTop - top;
- top = _toRedrawTop;
+ top = _toRedrawTop;
}
if (bottom > _toRedrawBottom)
bottom = _toRedrawBottom;
} else {
- _toRedrawTop = top;
- _toRedrawLeft = left;
- _toRedrawRight = right;
+ _toRedrawTop = top;
+ _toRedrawLeft = left;
+ _toRedrawRight = right;
_toRedrawBottom = bottom;
}
@@ -690,7 +686,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
if (left < _vm->_mult->_animLeft) {
destX += _vm->_mult->_animLeft - left;
- left = _vm->_mult->_animLeft;
+ left = _vm->_mult->_animLeft;
}
if ((_vm->_mult->_animLeft + _vm->_mult->_animWidth) <= right)
@@ -698,40 +694,40 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
if (top < _vm->_mult->_animTop) {
destY += _vm->_mult->_animTop - top;
- top = _vm->_mult->_animTop;
+ top = _vm->_mult->_animTop;
}
if ((_vm->_mult->_animTop + _vm->_mult->_animHeight) <= bottom)
bottom = _vm->_mult->_animTop + _vm->_mult->_animHeight - 1;
- _vm->_draw->_spriteLeft = destX;
- _vm->_draw->_spriteTop = destY;
- _vm->_draw->_spriteRight = right - left + 1;
- _vm->_draw->_spriteBottom = bottom - top + 1;
- _vm->_draw->_destSpriteX = left;
- _vm->_draw->_destSpriteY = top;
+ _vm->_draw->_spriteLeft = destX;
+ _vm->_draw->_spriteTop = destY;
+ _vm->_draw->_spriteRight = right - left + 1;
+ _vm->_draw->_spriteBottom = bottom - top + 1;
+ _vm->_draw->_destSpriteX = left;
+ _vm->_draw->_destSpriteY = top;
_vm->_draw->_transparency = layer;
if (layer & 0x80)
_vm->_draw->_spriteLeft = _vm->_vidPlayer->getWidth(obj.videoSlot - 1) -
(destX + _vm->_draw->_spriteRight);
_vm->_vidPlayer->slotCopyFrame(obj.videoSlot - 1, _vm->_draw->_backSurface->getVidMem(),
- _vm->_draw->_spriteLeft, _vm->_draw->_spriteTop,
+ _vm->_draw->_spriteLeft, _vm->_draw->_spriteTop,
_vm->_draw->_spriteRight, _vm->_draw->_spriteBottom,
_vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY,
_vm->_draw->_backSurface->getWidth(),
(_vm->_draw->_transparency != 0) ? 0 : -1);
_vm->_draw->invalidateRect(_vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY,
- _vm->_draw->_destSpriteX + _vm->_draw->_spriteRight - 1,
+ _vm->_draw->_destSpriteX + _vm->_draw->_spriteRight - 1,
_vm->_draw->_destSpriteY + _vm->_draw->_spriteBottom - 1);
}
if (!(flags & 4)) {
- _animLeft = _toRedrawLeft = left;
- _animTop = _toRedrawTop = top;
- _animRight = _toRedrawRight = right;
+ _animLeft = _toRedrawLeft = left;
+ _animTop = _toRedrawTop = top;
+ _animRight = _toRedrawRight = right;
_animBottom = _toRedrawBottom = bottom;
}
@@ -757,13 +753,13 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
return;
_vm->_game->capturePush(_toRedrawLeft, _toRedrawTop,
- _toRedrawRight - _toRedrawLeft + 1,
- _toRedrawBottom - _toRedrawTop + 1);
+ _toRedrawRight - _toRedrawLeft + 1,
+ _toRedrawBottom - _toRedrawTop + 1);
*_pCaptureCounter = *_pCaptureCounter + 1;
}
- pictPtr = _animations[animation].pieces;
+ pictPtr = _animations[animation].pieces;
framePtr = layerPtr->frames;
for (i = 0; i < frame; i++, framePtr++)
@@ -771,9 +767,9 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
framePtr++;
if (flags & 4) {
- _toRedrawLeft = MAX(_toRedrawLeft, _vm->_mult->_animLeft);
- _toRedrawTop = MAX(_toRedrawTop, _vm->_mult->_animTop);
- _toRedrawRight = MIN(_toRedrawRight,
+ _toRedrawLeft = MAX(_toRedrawLeft, _vm->_mult->_animLeft);
+ _toRedrawTop = MAX(_toRedrawTop, _vm->_mult->_animTop);
+ _toRedrawRight = MIN(_toRedrawRight,
(int16)(_vm->_mult->_animLeft + _vm->_mult->_animWidth - 1));
_toRedrawBottom = MIN(_toRedrawBottom,
(int16)(_vm->_mult->_animTop + _vm->_mult->_animHeight - 1));
@@ -844,7 +840,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
(_vm->_mult->_animLeft + _vm->_mult->_animWidth) + 1;
if (destY < _vm->_mult->_animTop) {
- top += _vm->_mult->_animTop - destY;
+ top += _vm->_mult->_animTop - destY;
destY = _vm->_mult->_animTop;
}
@@ -863,7 +859,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
right -= destX + right - left - _toRedrawRight;
if (destY < _toRedrawTop) {
- top += _toRedrawTop - destY;
+ top += _toRedrawTop - destY;
destY = _toRedrawTop;
}
@@ -877,33 +873,33 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
if (doDraw) {
_vm->_draw->_sourceSurface =
_animPictToSprite[animation * 7 + pictIndex];
- _vm->_draw->_destSurface = 21;
+ _vm->_draw->_destSurface = 21;
- _vm->_draw->_spriteLeft = left;
- _vm->_draw->_spriteTop = top;
- _vm->_draw->_spriteRight = right - left + 1;
+ _vm->_draw->_spriteLeft = left;
+ _vm->_draw->_spriteTop = top;
+ _vm->_draw->_spriteRight = right - left + 1;
_vm->_draw->_spriteBottom = bottom - top + 1;
- _vm->_draw->_destSpriteX = destX;
- _vm->_draw->_destSpriteY = destY;
+ _vm->_draw->_destSpriteX = destX;
+ _vm->_draw->_destSpriteY = destY;
_vm->_draw->_transparency = transp;
_vm->_draw->spriteOperation(DRAW_BLITSURF);
}
if (!(flags & 4)) {
if (_toRedrawLeft == -12345) {
- _toRedrawLeft = destX;
- _animLeft = destX;
- _toRedrawTop = destY;
- _animTop = destY;
- _toRedrawRight = destX + right - left;
- _animRight = destX + right - left;
+ _toRedrawLeft = destX;
+ _animLeft = destX;
+ _toRedrawTop = destY;
+ _animTop = destY;
+ _toRedrawRight = destX + right - left;
+ _animRight = destX + right - left;
_toRedrawBottom = destY + bottom - top;
- _animBottom = destY + bottom - top;
+ _animBottom = destY + bottom - top;
} else {
- _toRedrawLeft = MIN(_toRedrawLeft, destX);
- _toRedrawTop = MIN(_toRedrawTop, destY);
- _toRedrawRight =
- MAX(_toRedrawRight, (int16)(destX + right - left));
+ _toRedrawLeft = MIN(_toRedrawLeft, destX);
+ _toRedrawTop = MIN(_toRedrawTop, destY);
+ _toRedrawRight =
+ MAX(_toRedrawRight, (int16)(destX + right - left));
_toRedrawBottom =
MAX(_toRedrawBottom, (int16)(destY + bottom - top));
}
@@ -952,41 +948,23 @@ Scenery::AnimLayer *Scenery::getAnimLayer(uint16 index, uint16 layer) {
}
void Scenery::loadPieces(int16 pictDescId, PieceDesc *&pieceDesc, uint32 &piecesCount) {
- byte *data;
- uint32 size;
- bool fromExt = false;
-
- if (pictDescId >= 30000) {
- fromExt = true;
-
- uint32 eSize;
-
- data = _vm->_game->loadExtData(pictDescId, 0, 0, &eSize);
- size = eSize;
- } else {
- int16 tSize;
-
- data = _vm->_game->loadTotResource(pictDescId, &tSize);
- size = tSize;
+ Resource *resource = _vm->_game->_resources->getResource(pictDescId);
+ if (!resource) {
+ warning("Scenery::loadPieces(): Can't load %d", pictDescId);
+ return;
}
- if (!data)
- error("Scenery::loadPieces(): Can't load pictDescId %d", pictDescId);
-
- piecesCount = size / 8;
+ piecesCount = resource->getSize() / 8;
pieceDesc = new PieceDesc[piecesCount];
- Common::MemoryReadStream pieceData(data, size);
-
for (uint32 i = 0; i < piecesCount; i++) {
- pieceDesc[i].left = (int16) pieceData.readUint16LE();
- pieceDesc[i].right = (int16) pieceData.readUint16LE();
- pieceDesc[i].top = (int16) pieceData.readUint16LE();
- pieceDesc[i].bottom = (int16) pieceData.readUint16LE();
+ pieceDesc[i].left = resource->stream()->readSint16LE();
+ pieceDesc[i].right = resource->stream()->readSint16LE();
+ pieceDesc[i].top = resource->stream()->readSint16LE();
+ pieceDesc[i].bottom = resource->stream()->readSint16LE();
}
- if (fromExt)
- delete[] data;
+ delete resource;
}
} // End of namespace Gob
diff --git a/engines/gob/script.cpp b/engines/gob/script.cpp
new file mode 100644
index 0000000000..6162e943bf
--- /dev/null
+++ b/engines/gob/script.cpp
@@ -0,0 +1,522 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/util.h"
+#include "common/endian.h"
+
+#include "gob/gob.h"
+#include "gob/script.h"
+#include "gob/dataio.h"
+#include "gob/expression.h"
+#include "gob/videoplayer.h"
+
+namespace Gob {
+
+Script::Script(GobEngine *vm) : _vm(vm) {
+ _expression = new Expression(vm);
+
+ _finished = true;
+
+ _totData = 0;
+ _totPtr = 0;
+ _totSize = 0;
+
+ _lomHandle = -1;
+
+ memset(&_totProperties, 0, sizeof(TOTFile::Properties));
+}
+
+Script::~Script() {
+ unload();
+
+ delete _expression;
+}
+
+uint32 Script::read(byte *data, int32 size) {
+ int32 toRead = MIN<int32>(size, _totSize - (_totPtr - _totData));
+
+ if (toRead < 1)
+ return 0;
+
+ memcpy(data, _totPtr, toRead);
+ _totPtr += toRead;
+
+ return toRead;
+}
+
+uint32 Script::peek(byte *data, int32 size, int32 offset) const {
+ int32 totOffset = ((_totPtr + offset) - _totData);
+
+ if (totOffset < 1)
+ return 0;
+ if (((uint32) totOffset) >= _totSize)
+ return 0;
+
+ int32 toPeek = MIN<int32>(size, _totSize - totOffset);
+ if (toPeek < 1)
+ return 0;
+
+ memcpy(data, _totPtr + offset, toPeek);
+
+ return toPeek;
+}
+
+int32 Script::pos() const {
+ if (!_totData)
+ return -1;
+
+ return _totPtr - _totData;
+}
+
+int32 Script::getSize() const {
+ if (!_totData)
+ return -1;
+
+ return _totSize;
+}
+
+bool Script::seek(int32 offset, int whence) {
+ if (!_totData)
+ return false;
+
+ if (whence == SEEK_CUR)
+ offset += pos();
+ else if (whence == SEEK_END)
+ offset += _totSize;
+
+ if ((offset < 0) || (((uint32) offset) >= _totSize))
+ return false;
+
+ // Cannot seek into the header
+ if (offset < 128) {
+ _finished = true;
+ return false;
+ }
+
+ // A successful seek means the script file continues to be executed
+ _finished = false;
+
+ _totPtr = _totData + offset;
+
+ return true;
+}
+
+bool Script::skip(int32 offset) {
+ return seek(offset, SEEK_CUR);
+}
+
+int32 Script::getOffset(byte *ptr) const {
+ if (!_totData)
+ return -1;
+
+ if ((ptr < _totData) || (ptr >= (_totData + _totSize)))
+ return -1;
+
+ return ptr - _totData;
+}
+
+byte *Script::getData(int32 offset) const {
+ if (!_totData)
+ return 0;
+ if ((offset < 0) || (((uint32) offset) >= _totSize))
+ return 0;
+
+ return _totData + offset;
+}
+
+byte *Script::getData() {
+ return _totData;
+}
+
+byte Script::readByte() {
+ byte v;
+
+ read(&v, 1);
+
+ return v;
+}
+
+char Script::readChar() {
+ return (char) readByte();
+}
+
+uint8 Script::readUint8() {
+ return (uint8) readByte();
+}
+
+uint16 Script::readUint16() {
+ byte v[2];
+
+ read(v, 2);
+
+ return READ_LE_UINT16(v);
+}
+
+uint32 Script::readUint32() {
+ byte v[4];
+
+ read(v, 4);
+
+ return READ_LE_UINT32(v);
+}
+
+int8 Script::readInt8() {
+ return (int8) readByte();
+}
+
+int16 Script::readInt16() {
+ return (int16) readUint16();
+}
+
+int32 Script::readInt32() {
+ return (int32) readUint32();
+}
+
+char *Script::readString(int32 length) {
+ if (length < 0) {
+ length = 0;
+ while (_totPtr[length++] != '\0');
+ }
+
+ char *string = (char *) _totPtr;
+
+ _totPtr += length;
+
+ return string;
+}
+
+byte Script::peekByte(int32 offset) {
+ byte v;
+
+ peek(&v, 1, offset);
+
+ return v;
+}
+
+char Script::peekChar(int32 offset) {
+ return (char) peekByte(offset);
+}
+
+uint8 Script::peekUint8(int32 offset) {
+ return (uint8) peekByte(offset);
+}
+
+uint16 Script::peekUint16(int32 offset) {
+ byte v[2];
+
+ peek(v, 2, offset);
+
+ return READ_LE_UINT16(v);
+}
+
+uint32 Script::peekUint32(int32 offset) {
+ byte v[4];
+
+ peek(v, 4, offset);
+
+ return READ_LE_UINT32(v);
+}
+
+int8 Script::peekInt8(int32 offset) {
+ return (int8) peekByte(offset);
+}
+
+int16 Script::peekInt16(int32 offset) {
+ return (int16) peekUint16(offset);
+}
+
+int32 Script::peekInt32(int32 offset) {
+ return (int32) peekUint32(offset);
+}
+
+char *Script::peekString(int32 offset) {
+ return (char *) (_totPtr + offset);
+}
+
+int16 Script::readVarIndex(uint16 *size, uint16 *type) {
+ return _expression->parseVarIndex(size, type);
+}
+
+int16 Script::readValExpr(byte stopToken) {
+ return _expression->parseValExpr(stopToken);
+}
+
+int16 Script::readExpr(byte stopToken, byte *type) {
+ return _expression->parseExpr(stopToken, type);
+}
+
+void Script::skipExpr(char stopToken) {
+ _expression->skipExpr(stopToken);
+}
+
+char Script::evalExpr(int16 *pRes) {
+ byte type;
+
+ _expression->printExpr(99);
+
+ _expression->parseExpr(99, &type);
+ if (!pRes)
+ return type;
+
+ switch (type) {
+ case TYPE_IMM_INT16:
+ *pRes = _expression->getResultInt();
+ break;
+
+ case TYPE_IMM_STR:
+ case GOB_FALSE:
+ *pRes = 0;
+ break;
+
+ case GOB_TRUE:
+ *pRes = 1;
+ break;
+ }
+
+ return type;
+}
+
+bool Script::evalBoolResult() {
+ byte type;
+
+ _expression->printExpr(99);
+
+ _expression->parseExpr(99, &type);
+ if ( (type == GOB_TRUE) ||
+ ((type == TYPE_IMM_INT16) && _expression->getResultInt()))
+ return true;
+ else
+ return false;
+}
+
+int32 Script::getResultInt() const {
+ return _expression->getResultInt();
+}
+
+char *Script::getResultStr() const {
+ return _expression->getResultStr();
+}
+
+bool Script::load(const Common::String &fileName) {
+ unload();
+
+ _finished = false;
+
+ bool isLOM;
+
+ _totFile = TOTFile::createFileName(fileName, isLOM);
+
+ if (isLOM) {
+ if (!loadLOM(_totFile)) {
+ unload();
+ return false;
+ }
+ } else {
+ if (!loadTOT(_totFile)) {
+ unload();
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool Script::loadTOT(const Common::String &fileName) {
+ TOTFile totFile(_vm);
+
+ if (!totFile.load(fileName))
+ return false;
+
+ Common::SeekableReadStream *stream = totFile.getStream();
+ if (!stream)
+ return false;
+
+ if (!totFile.getProperties(_totProperties))
+ return false;
+
+ _totSize = _totProperties.scriptEnd;
+ if (_totSize <= 0)
+ return false;
+
+ _totData = new byte[_totSize];
+ if (stream->read(_totData, _totSize) != _totSize)
+ return false;
+
+ return true;
+}
+
+bool Script::loadLOM(const Common::String &fileName) {
+ warning("Stub: Script::loadLOM(%s)", _totFile.c_str());
+
+ _lomHandle = _vm->_dataIO->openData(_totFile.c_str());
+ if (_lomHandle < 0)
+ return false;
+
+ DataStream *stream = _vm->_dataIO->openAsStream(_lomHandle);
+
+ stream->seek(48);
+ _totSize = stream->readUint32LE();
+ stream->seek(0);
+
+ _totData = new byte[_totSize];
+ stream->read(_totData, _totSize);
+
+ delete stream;
+
+ return false;
+}
+
+void Script::unload() {
+ unloadTOT();
+}
+
+void Script::unloadTOT() {
+ if (_lomHandle >= 0)
+ _vm->_dataIO->closeData(_lomHandle);
+
+ // Unwind the call stack
+ while (!_callStack.empty())
+ pop();
+
+ delete[] _totData;
+
+ _totData = 0;
+ _totSize = 0;
+ _totPtr = 0;
+ _lomHandle = -1;
+ _totFile.clear();
+
+ _finished = true;
+}
+
+bool Script::isLoaded() const {
+ return _totData != 0;
+}
+
+void Script::setFinished(bool finished) {
+ _finished = finished;
+}
+
+bool Script::isFinished() const {
+ return _finished;
+}
+
+void Script::push() {
+ if (!isLoaded())
+ // Nothing to do
+ return;
+
+ CallEntry currentCall;
+
+ currentCall.totPtr = _totPtr;
+ currentCall.finished = _finished;
+
+ _callStack.push(currentCall);
+}
+
+void Script::pop(bool ret) {
+ if (!isLoaded())
+ // Nothing to do
+ return;
+
+ // Unmatched pop?
+ assert(!_callStack.empty());
+
+ CallEntry lastCall = _callStack.pop();
+
+ if (ret) {
+ _totPtr = lastCall.totPtr;
+ _finished = lastCall.finished;
+ }
+}
+
+void Script::call(uint32 offset) {
+ if (!isLoaded())
+ // Nothing to do
+ return;
+
+ push();
+ seek(offset);
+}
+
+uint8 Script::getVersionMajor() const {
+ return _totProperties.versionMajor;
+}
+
+uint8 Script::getVersionMinor() const {
+ return _totProperties.versionMinor;
+}
+
+uint32 Script::getVariablesCount() const {
+ return _totProperties.variablesCount;
+}
+
+uint32 Script::getTextsOffset() const {
+ return _totProperties.textsOffset;
+}
+
+uint32 Script::getResourcesOffset() const {
+ return _totProperties.resourcesOffset;
+}
+
+uint16 Script::getAnimDataSize() const {
+ return _totProperties.animDataSize;
+}
+
+uint8 Script::getImFileNumber() const {
+ return _totProperties.imFileNumber;
+}
+
+uint8 Script::getExFileNumber() const {
+ return _totProperties.exFileNumber;
+}
+
+uint8 Script::getCommunHandling() const {
+ return _totProperties.communHandling;
+}
+
+uint16 Script::getFunctionOffset(uint8 function) const {
+ if (!_totData)
+ return 0;
+
+ // Offsets 100-128, 2 bytes per function
+ assert(function <= 13);
+
+ return _totProperties.functions[function];
+}
+
+uint32 Script::getVariablesCount(const char *fileName, GobEngine *vm) {
+ DataStream *stream = vm->_dataIO->getDataStream(fileName);
+ if (!stream)
+ return 0;
+
+ stream->seek(0x2C);
+ uint32 variablesCount = stream->readUint32LE();
+ delete stream;
+
+ return variablesCount;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/script.h b/engines/gob/script.h
new file mode 100644
index 0000000000..64a04503b1
--- /dev/null
+++ b/engines/gob/script.h
@@ -0,0 +1,169 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_SCRIPT_H
+#define GOB_SCRIPT_H
+
+#include "common/str.h"
+#include "common/stack.h"
+
+#include "gob/totfile.h"
+
+namespace Gob {
+
+class GobEngine;
+class Expression;
+
+class Script {
+public:
+ Script(GobEngine *vm);
+ ~Script();
+
+ /** Read data and move the pointer accordingly. */
+ uint32 read(byte *data, int32 size);
+ /** Read data (from an optional offset) without moving the pointer. */
+ uint32 peek(byte *data, int32 size, int32 offset = 0) const;
+
+ // Stream properties
+ int32 pos() const;
+ int32 getSize() const;
+
+ // Stream seeking
+ bool seek(int32 offset, int whence = SEEK_SET);
+ bool skip(int32 offset);
+
+ // Reading data
+ byte readByte ();
+ char readChar ();
+ uint8 readUint8 ();
+ uint16 readUint16();
+ uint32 readUint32();
+ int8 readInt8 ();
+ int16 readInt16 ();
+ int32 readInt32 ();
+ char *readString(int32 length = -1);
+
+ // Peeking data
+ byte peekByte (int32 offset = 0);
+ char peekChar (int32 offset = 0);
+ uint8 peekUint8 (int32 offset = 0);
+ uint16 peekUint16(int32 offset = 0);
+ uint32 peekUint32(int32 offset = 0);
+ int8 peekInt8 (int32 offset = 0);
+ int16 peekInt16 (int32 offset = 0);
+ int32 peekInt32 (int32 offset = 0);
+ char *peekString(int32 offset = 0);
+
+ // Expression parsing functions
+ int16 readVarIndex(uint16 *size = 0, uint16 *type = 0);
+ int16 readValExpr(byte stopToken = 99);
+ int16 readExpr(byte stopToken, byte *type);
+ void skipExpr(char stopToken);
+
+ // Higher-level expression parsing functions
+ char evalExpr(int16 *pRes);
+ bool evalBoolResult();
+
+ // Accessing the result of expressions
+ int32 getResultInt() const;
+ char *getResultStr() const;
+
+ /** Returns the offset the specified pointer is within the script data. */
+ int32 getOffset(byte *ptr) const;
+ /** Returns the data pointer to the offset. */
+ byte *getData(int32 offset) const;
+
+ /** Returns the raw data pointer. */
+ byte *getData();
+
+ /** Load a script file. */
+ bool load(const Common::String &fileName);
+ /** Unload the script. */
+ void unload();
+ /** Was a script loaded? */
+ bool isLoaded() const;
+
+ /** Setting the 'finished' property. */
+ void setFinished(bool finished);
+ /** Querying the 'finished' property. */
+ bool isFinished() const;
+
+ // Call stack operations
+ /** Push the current script position onto the call stack. */
+ void push();
+ /** Pop a script position from the call stack (and return there). */
+ void pop(bool ret = true);
+ /** Push the current script position and branch to the specified offset. */
+ void call(uint32 offset);
+
+ // Fixed properties
+ uint8 getVersionMajor () const;
+ uint8 getVersionMinor () const;
+ uint32 getVariablesCount () const;
+ uint32 getTextsOffset () const;
+ uint32 getResourcesOffset() const;
+ uint16 getAnimDataSize () const;
+ uint8 getImFileNumber () const;
+ uint8 getExFileNumber () const;
+ uint8 getCommunHandling () const;
+
+ uint16 getFunctionOffset (uint8 function) const;
+
+ static uint32 getVariablesCount(const char *fileName, GobEngine *vm);
+
+private:
+ struct CallEntry {
+ byte *totPtr;
+ bool finished;
+ };
+
+ GobEngine *_vm;
+ Expression *_expression;
+
+ bool _finished;
+
+ Common::String _totFile;
+ byte *_totData;
+ byte *_totPtr;
+ uint32 _totSize;
+
+ int16 _lomHandle;
+
+ TOTFile::Properties _totProperties;
+
+ Common::Stack<CallEntry> _callStack;
+
+ /** Loading a TOT file. */
+ bool loadTOT(const Common::String &fileName);
+ /** Loading a LOM file. */
+ bool loadLOM(const Common::String &fileName);
+
+ /** Unloading a TOT file. */
+ void unloadTOT();
+};
+
+} // End of namespace Gob
+
+#endif // GOB_SCRIPT_H
diff --git a/engines/gob/sound/adlib.cpp b/engines/gob/sound/adlib.cpp
index 07481431b6..7ab8e1f8dd 100644
--- a/engines/gob/sound/adlib.cpp
+++ b/engines/gob/sound/adlib.cpp
@@ -39,18 +39,33 @@ const unsigned char AdLib::_volRegNums[] = {
};
AdLib::AdLib(Audio::Mixer &mixer) : _mixer(&mixer) {
+ init();
+}
+
+AdLib::~AdLib() {
+ Common::StackLock slock(_mutex);
+
+ _mixer->stopHandle(_handle);
+ OPLDestroy(_opl);
+ if (_data && _freeData)
+ delete[] _data;
+}
+
+void AdLib::init() {
_index = -1;
_data = 0;
_playPos = 0;
_dataSize = 0;
_rate = _mixer->getOutputRate();
+
_opl = makeAdlibOPL(_rate);
_first = true;
_ended = false;
_playing = false;
- _needFree = false;
+
+ _freeData = false;
_repCount = -1;
_samplesTillPoll = 0;
@@ -63,15 +78,6 @@ AdLib::AdLib(Audio::Mixer &mixer) : _mixer(&mixer) {
this, -1, 255, 0, false, true);
}
-AdLib::~AdLib() {
- Common::StackLock slock(_mutex);
-
- _mixer->stopHandle(_handle);
- OPLDestroy(_opl);
- if (_data && _needFree)
- delete[] _data;
-}
-
int AdLib::readBuffer(int16 *buffer, const int numSamples) {
Common::StackLock slock(_mutex);
int samples;
@@ -107,7 +113,9 @@ int AdLib::readBuffer(int16 *buffer, const int numSamples) {
if (_ended) {
_first = true;
_ended = false;
- _playPos = _data + 3 + (_data[1] + 1) * 0x38;
+
+ rewind();
+
_samplesTillPoll = 0;
if (_repCount == -1) {
reset();
@@ -120,7 +128,6 @@ int AdLib::readBuffer(int16 *buffer, const int numSamples) {
else
_playing = false;
}
-
return numSamples;
}
@@ -173,48 +180,6 @@ void AdLib::reset() {
writeOPL(0x01, 0x20);
}
-void AdLib::setVoices() {
- // Definitions of the 9 instruments
- for (int i = 0; i < 9; i++)
- setVoice(i, i, true);
-}
-
-void AdLib::setVoice(byte voice, byte instr, bool set) {
- int i;
- int j;
- uint16 strct[27];
- byte channel;
- byte *dataPtr;
-
- // i = 0 : 0 1 2 3 4 5 6 7 8 9 10 11 12 26
- // i = 1 : 13 14 15 16 17 18 19 20 21 22 23 24 25 27
- for (i = 0; i < 2; i++) {
- dataPtr = _data + 3 + instr * 0x38 + i * 0x1A;
- for (j = 0; j < 27; j++) {
- strct[j] = READ_LE_UINT16(dataPtr);
- dataPtr += 2;
- }
- channel = _operators[voice] + i * 3;
- writeOPL(0xBD, 0x00);
- writeOPL(0x08, 0x00);
- writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F));
- if (!i)
- writeOPL(0xC0 | voice,
- ((strct[2] & 7) << 1) | (1 - (strct[12] & 1)));
- writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF));
- writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF));
- writeOPL(0x20 | channel, ((strct[9] & 1) << 7) |
- ((strct[10] & 1) << 6) | ((strct[5] & 1) << 5) |
- ((strct[11] & 1) << 4) | (strct[1] & 0xF));
- if (!i)
- writeOPL(0xE0 | channel, (strct[26] & 3));
- else
- writeOPL(0xE0 | channel, (strct[14] & 3));
- if (i && set)
- writeOPL(0x40 | channel, 0);
- }
-}
-
void AdLib::setKey(byte voice, byte note, bool on, bool spec) {
short freq = 0;
short octa = 0;
@@ -278,7 +243,7 @@ void AdLib::setKey(byte voice, byte note, bool on, bool spec) {
writeOPL(0xB0 + voice, (freq >> 8) | (octa << 2) | 0x20 * on);
if (!freq)
- warning("Voice %d, note %02X unknown", voice, note);
+ warning("AdLib: Voice %d, note %02X unknown", voice, note);
}
void AdLib::setVolume(byte voice, byte volume) {
@@ -287,17 +252,102 @@ void AdLib::setVolume(byte voice, byte volume) {
}
void AdLib::pollMusic() {
+ if ((_playPos > (_data + _dataSize)) && (_dataSize != 0xFFFFFFFF)) {
+ _ended = true;
+ return;
+ }
+
+ interpret();
+}
+
+void AdLib::unload() {
+ _playing = false;
+ _index = -1;
+
+ if (_data && _freeData)
+ delete[] _data;
+
+ _freeData = false;
+}
+
+bool AdLib::isPlaying() const {
+ return _playing;
+}
+
+bool AdLib::getRepeating() const {
+ return _repCount != 0;
+}
+
+void AdLib::setRepeating(int32 repCount) {
+ _repCount = repCount;
+}
+
+int AdLib::getIndex() const {
+ return _index;
+}
+
+void AdLib::startPlay() {
+ if (_data) _playing = true;
+}
+
+void AdLib::stopPlay() {
+ Common::StackLock slock(_mutex);
+ _playing = false;
+}
+
+ADLPlayer::ADLPlayer(Audio::Mixer &mixer) : AdLib(mixer) {
+}
+
+ADLPlayer::~ADLPlayer() {
+}
+
+bool ADLPlayer::load(const char *fileName) {
+ Common::File song;
+
+ unload();
+ song.open(fileName);
+ if (!song.isOpen())
+ return false;
+
+ _freeData = true;
+ _dataSize = song.size();
+ _data = new byte[_dataSize];
+ song.read(_data, _dataSize);
+ song.close();
+
+ reset();
+ setVoices();
+ _playPos = _data + 3 + (_data[1] + 1) * 0x38;
+
+ return true;
+}
+
+bool ADLPlayer::load(byte *data, uint32 size, int index) {
+ unload();
+ _repCount = 0;
+
+ _dataSize = size;
+ _data = data;
+ _index = index;
+
+ reset();
+ setVoices();
+ _playPos = _data + 3 + (_data[1] + 1) * 0x38;
+
+ return true;
+}
+
+void ADLPlayer::unload() {
+ AdLib::unload();
+}
+
+void ADLPlayer::interpret() {
unsigned char instr;
byte channel;
byte note;
byte volume;
uint16 tempo;
- if ((_playPos > (_data + _dataSize)) && (_dataSize != 0xFFFFFFFF)) {
- _ended = true;
- return;
- }
-
// First tempo, we'll ignore it...
if (_first) {
tempo = *(_playPos++);
@@ -352,7 +402,7 @@ void AdLib::pollMusic() {
_samplesTillPoll = 0;
return;
default:
- warning("Unknown special command in ADL, stopping playback: %X",
+ warning("ADLPlayer: Unknown special command %X, stopping playback",
instr & 0x0F);
_repCount = 0;
_ended = true;
@@ -360,7 +410,7 @@ void AdLib::pollMusic() {
}
break;
default:
- warning("Unknown command in ADL, stopping playback: %X",
+ warning("ADLPlayer: Unknown command %X, stopping playback",
instr & 0xF0);
_repCount = 0;
_ended = true;
@@ -383,75 +433,349 @@ void AdLib::pollMusic() {
_samplesTillPoll = tempo * (_rate / 1000);
}
-bool AdLib::load(const char *fileName) {
+void ADLPlayer::reset() {
+ AdLib::reset();
+}
+
+void ADLPlayer::rewind() {
+ _playPos = _data + 3 + (_data[1] + 1) * 0x38;
+}
+
+void ADLPlayer::setVoices() {
+ // Definitions of the 9 instruments
+ for (int i = 0; i < 9; i++)
+ setVoice(i, i, true);
+}
+
+void ADLPlayer::setVoice(byte voice, byte instr, bool set) {
+ uint16 strct[27];
+ byte channel;
+ byte *dataPtr;
+
+ // i = 0 : 0 1 2 3 4 5 6 7 8 9 10 11 12 26
+ // i = 1 : 13 14 15 16 17 18 19 20 21 22 23 24 25 27
+ for (int i = 0; i < 2; i++) {
+ dataPtr = _data + 3 + instr * 0x38 + i * 0x1A;
+ for (int j = 0; j < 27; j++) {
+ strct[j] = READ_LE_UINT16(dataPtr);
+ dataPtr += 2;
+ }
+ channel = _operators[voice] + i * 3;
+ writeOPL(0xBD, 0x00);
+ writeOPL(0x08, 0x00);
+ writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F));
+ if (!i)
+ writeOPL(0xC0 | voice,
+ ((strct[2] & 7) << 1) | (1 - (strct[12] & 1)));
+ writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF));
+ writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF));
+ writeOPL(0x20 | channel, ((strct[9] & 1) << 7) |
+ ((strct[10] & 1) << 6) | ((strct[5] & 1) << 5) |
+ ((strct[11] & 1) << 4) | (strct[1] & 0xF));
+ if (!i)
+ writeOPL(0xE0 | channel, (strct[26] & 3));
+ else
+ writeOPL(0xE0 | channel, (strct[14] & 3));
+ if (i && set)
+ writeOPL(0x40 | channel, 0);
+ }
+}
+
+
+MDYPlayer::MDYPlayer(Audio::Mixer &mixer) : AdLib(mixer) {
+ init();
+}
+
+MDYPlayer::~MDYPlayer() {
+}
+
+void MDYPlayer::init() {
+ _soundMode = 0;
+
+ _timbres = 0;
+ _tbrCount = 0;
+ _tbrStart = 0;
+ _timbresSize = 0;
+}
+
+bool MDYPlayer::loadMDY(Common::SeekableReadStream &stream) {
+ unloadMDY();
+
+ _freeData = true;
+
+ byte mdyHeader[70];
+ stream.read(mdyHeader, 70);
+
+ _tickBeat = mdyHeader[36];
+ _beatMeasure = mdyHeader[37];
+ _totalTick = mdyHeader[38] + (mdyHeader[39] << 8) + (mdyHeader[40] << 16) + (mdyHeader[41] << 24);
+ _dataSize = mdyHeader[42] + (mdyHeader[43] << 8) + (mdyHeader[44] << 16) + (mdyHeader[45] << 24);
+ _nrCommand = mdyHeader[46] + (mdyHeader[47] << 8) + (mdyHeader[48] << 16) + (mdyHeader[49] << 24);
+// _soundMode is either 0 (melodic) or 1 (percussive)
+ _soundMode = mdyHeader[58];
+ _pitchBendRangeStep = 25*mdyHeader[59];
+ _basicTempo = mdyHeader[60] + (mdyHeader[61] << 8);
+
+ if (_pitchBendRangeStep < 25)
+ _pitchBendRangeStep = 25;
+ else if (_pitchBendRangeStep > 300)
+ _pitchBendRangeStep = 300;
+
+ _data = new byte[_dataSize];
+ stream.read(_data, _dataSize);
+
+ reset();
+ _playPos = _data;
+
+ return true;
+}
+
+bool MDYPlayer::loadMDY(const char *fileName) {
Common::File song;
- unload();
song.open(fileName);
if (!song.isOpen())
return false;
- _needFree = true;
- _dataSize = song.size();
- _data = new byte[_dataSize];
- song.read(_data, _dataSize);
- song.close();
+ bool loaded = loadMDY(song);
- reset();
- setVoices();
- _playPos = _data + 3 + (_data[1] + 1) * 0x38;
+ song.close();
- return true;
+ return loaded;
}
-bool AdLib::load(byte *data, uint32 size, int index) {
- unload();
- _repCount = 0;
+bool MDYPlayer::loadTBR(Common::SeekableReadStream &stream) {
+ unloadTBR();
- _dataSize = size;
- _data = data;
- _index = index;
+ _timbresSize = stream.size();
+
+ _timbres = new byte[_timbresSize];
+ stream.read(_timbres, _timbresSize);
reset();
setVoices();
- _playPos = _data + 3 + (_data[1] + 1) * 0x38;
return true;
}
-void AdLib::unload() {
- _playing = false;
- _index = -1;
+bool MDYPlayer::loadTBR(const char *fileName) {
+ Common::File timbres;
- if (_data && _needFree)
- delete[] _data;
+ timbres.open(fileName);
+ if (!timbres.isOpen())
+ return false;
+
+ bool loaded = loadTBR(timbres);
- _needFree = false;
+ timbres.close();
+
+ return loaded;
}
-bool AdLib::isPlaying() const {
- return _playing;
+void MDYPlayer::unload() {
+ unloadTBR();
+ unloadMDY();
}
-bool AdLib::getRepeating() const {
- return _repCount != 0;
+void MDYPlayer::unloadMDY() {
+ AdLib::unload();
}
-void AdLib::setRepeating(int32 repCount) {
- _repCount = repCount;
+void MDYPlayer::unloadTBR() {
+ delete[] _timbres;
+
+ _timbres = 0;
+ _timbresSize = 0;
}
-int AdLib::getIndex() const {
- return _index;
+void MDYPlayer::interpret() {
+ unsigned char instr;
+ byte channel;
+ byte note;
+ byte volume;
+ uint8 tempoMult, tempoFrac;
+ uint8 ctrlByte1, ctrlByte2;
+ uint8 timbre;
+
+ if (_first) {
+ for (int i = 0; i < 11; i ++)
+ setVolume(i, 0);
+
+// TODO : Set pitch range
+
+ _tempo = _basicTempo;
+ _wait = *(_playPos++);
+ _first = false;
+ }
+ do {
+ instr = *_playPos;
+// printf("instr 0x%X\n", instr);
+ switch(instr) {
+ case 0xF8:
+ _wait = *(_playPos++);
+ break;
+ case 0xFC:
+ _ended = true;
+ _samplesTillPoll = 0;
+ return;
+ case 0xF0:
+ _playPos++;
+ ctrlByte1 = *(_playPos++);
+ ctrlByte2 = *(_playPos++);
+ if (ctrlByte1 != 0x7F || ctrlByte2 != 0) {
+ _playPos -= 2;
+ while (*(_playPos++) != 0xF7);
+ } else {
+ tempoMult = *(_playPos++);
+ tempoFrac = *(_playPos++);
+ _tempo = _basicTempo * tempoMult + (unsigned)(((long)_basicTempo * tempoFrac) >> 7);
+ _playPos++;
+ }
+ _wait = *(_playPos++);
+ break;
+ default:
+ if (instr >= 0x80) {
+ _playPos++;
+ }
+ channel = (int)(instr & 0x0f);
+
+ switch(instr & 0xf0) {
+ case 0x90:
+ note = *(_playPos++);
+ volume = *(_playPos++);
+ _pollNotes[channel] = note;
+ setVolume(channel, volume);
+ setKey(channel, note, true, false);
+ break;
+ case 0x80:
+ _playPos += 2;
+ note = _pollNotes[channel];
+ setKey(channel, note, false, false);
+ break;
+ case 0xA0:
+ setVolume(channel, *(_playPos++));
+ break;
+ case 0xC0:
+ timbre = *(_playPos++);
+ setVoice(channel, timbre, false);
+ break;
+ case 0xE0:
+ warning("MDYPlayer: Pitch bend not yet implemented");
+
+ note = *(_playPos)++;
+ note += (unsigned)(*(_playPos++)) << 7;
+
+ setKey(channel, note, _notOn[channel], true);
+
+ break;
+ case 0xB0:
+ _playPos += 2;
+ break;
+ case 0xD0:
+ _playPos++;
+ break;
+ default:
+ warning("MDYPlayer: Bad MIDI instr byte: 0%X", instr);
+ while ((*_playPos) < 0x80)
+ _playPos++;
+ if (*_playPos != 0xF8)
+ _playPos--;
+ break;
+ } //switch instr & 0xF0
+ _wait = *(_playPos++);
+ break;
+ } //switch instr
+ } while (_wait == 0);
+
+ if (_wait == 0xF8) {
+ _wait = 0xF0;
+ if (*_playPos != 0xF8)
+ _wait += *(_playPos++);
+ }
+// _playPos++;
+ _samplesTillPoll = _wait * (_rate / 1000);
}
-void AdLib::startPlay() {
- if (_data) _playing = true;
+void MDYPlayer::reset() {
+ AdLib::reset();
+
+// _soundMode 1 : Percussive mode.
+ if (_soundMode == 1) {
+ writeOPL(0xA6, 0);
+ writeOPL(0xB6, 0);
+ writeOPL(0xA7, 0);
+ writeOPL(0xB7, 0);
+ writeOPL(0xA8, 0);
+ writeOPL(0xB8, 0);
+
+// TODO set the correct frequency for the last 4 percussive voices
+ }
}
-void AdLib::stopPlay() {
- Common::StackLock slock(_mutex);
- _playing = false;
+void MDYPlayer::rewind() {
+ _playPos = _data;
+}
+
+void MDYPlayer::setVoices() {
+ byte *timbrePtr;
+
+ timbrePtr = _timbres;
+ debugC(6, kDebugSound, "TBR version: %X.%X", timbrePtr[0], timbrePtr[1]);
+ timbrePtr += 2;
+
+ _tbrCount = READ_LE_UINT16(timbrePtr);
+ debugC(6, kDebugSound, "Timbres counter: %d", _tbrCount);
+ timbrePtr += 2;
+ _tbrStart = READ_LE_UINT16(timbrePtr);
+
+ timbrePtr += 2;
+ for (int i = 0; i < _tbrCount ; i++)
+ setVoice(i, i, true);
+}
+
+void MDYPlayer::setVoice(byte voice, byte instr, bool set) {
+ uint16 strct[27];
+ byte channel;
+ byte *timbrePtr;
+ char timbreName[10];
+
+ timbreName[9] = '\0';
+ for (int j = 0; j < 9; j++)
+ timbreName[j] = _timbres[6 + j + (instr * 9)];
+ debugC(6, kDebugSound, "Loading timbre %s", timbreName);
+
+ // i = 0 : 0 1 2 3 4 5 6 7 8 9 10 11 12 26
+ // i = 1 : 13 14 15 16 17 18 19 20 21 22 23 24 25 27
+ for (int i = 0; i < 2; i++) {
+ timbrePtr = _timbres + _tbrStart + instr * 0x38 + i * 0x1A;
+ for (int j = 0; j < 27; j++) {
+ if (timbrePtr >= (_timbres + _timbresSize)) {
+ warning("MDYPlayer: Instrument %d out of range (%d, %d)", instr,
+ (uint32) (timbrePtr - _timbres), _timbresSize);
+ strct[j] = 0;
+ } else
+ strct[j] = READ_LE_UINT16(timbrePtr);
+ timbrePtr += 2;
+ }
+ channel = _operators[voice] + i * 3;
+ writeOPL(0xBD, 0x00);
+ writeOPL(0x08, 0x00);
+ writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F));
+ if (!i)
+ writeOPL(0xC0 | voice,
+ ((strct[2] & 7) << 1) | (1 - (strct[12] & 1)));
+ writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF));
+ writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF));
+ writeOPL(0x20 | channel, ((strct[9] & 1) << 7) |
+ ((strct[10] & 1) << 6) | ((strct[5] & 1) << 5) |
+ ((strct[11] & 1) << 4) | (strct[1] & 0xF));
+ if (!i)
+ writeOPL(0xE0 | channel, (strct[26] & 3));
+ else {
+ writeOPL(0xE0 | channel, (strct[14] & 3));
+ writeOPL(0x40 | channel, 0);
+ }
+ }
}
} // End of namespace Gob
diff --git a/engines/gob/sound/adlib.h b/engines/gob/sound/adlib.h
index 4cd83d5883..3f7b46643f 100644
--- a/engines/gob/sound/adlib.h
+++ b/engines/gob/sound/adlib.h
@@ -38,7 +38,7 @@ class GobEngine;
class AdLib : public Audio::AudioStream {
public:
AdLib(Audio::Mixer &mixer);
- ~AdLib();
+ virtual ~AdLib();
bool isPlaying() const;
int getIndex() const;
@@ -49,9 +49,7 @@ public:
void startPlay();
void stopPlay();
- bool load(const char *fileName);
- bool load(byte *data, uint32 size, int index = -1);
- void unload();
+ virtual void unload();
// AudioStream API
int readBuffer(int16 *buffer, const int numSamples);
@@ -89,18 +87,88 @@ protected:
bool _playing;
bool _first;
bool _ended;
- bool _needFree;
+
+ bool _freeData;
int _index;
+ unsigned char _wait;
+ uint8 _tickBeat;
+ uint8 _beatMeasure;
+ uint32 _totalTick;
+ uint32 _nrCommand;
+ uint16 _pitchBendRangeStep;
+ uint16 _basicTempo, _tempo;
+
void writeOPL(byte reg, byte val);
void setFreqs();
- void reset();
- void setVoices();
- void setVoice(byte voice, byte instr, bool set);
void setKey(byte voice, byte note, bool on, bool spec);
void setVolume(byte voice, byte volume);
void pollMusic();
+
+ virtual void interpret() = 0;
+
+ virtual void reset();
+ virtual void rewind() = 0;
+ virtual void setVoices() = 0;
+
+private:
+ void init();
+};
+
+class ADLPlayer : public AdLib {
+public:
+ ADLPlayer(Audio::Mixer &mixer);
+ ~ADLPlayer();
+
+ bool load(const char *fileName);
+ bool load(byte *data, uint32 size, int index = -1);
+
+ void unload();
+
+protected:
+ void interpret();
+
+ void reset();
+ void rewind();
+
+ void setVoices();
+ void setVoice(byte voice, byte instr, bool set);
+};
+
+class MDYPlayer : public AdLib {
+public:
+ MDYPlayer(Audio::Mixer &mixer);
+ ~MDYPlayer();
+
+ bool loadMDY(const char *fileName);
+ bool loadMDY(Common::SeekableReadStream &stream);
+ bool loadTBR(const char *fileName);
+ bool loadTBR(Common::SeekableReadStream &stream);
+
+ void unload();
+
+protected:
+ byte _soundMode;
+
+ byte *_timbres;
+ uint16 _tbrCount;
+ uint16 _tbrStart;
+ uint32 _timbresSize;
+
+ void interpret();
+
+ void reset();
+ void rewind();
+
+ void setVoices();
+ void setVoice(byte voice, byte instr, bool set);
+
+ void unloadTBR();
+ void unloadMDY();
+
+private:
+ void init();
};
} // End of namespace Gob
diff --git a/engines/gob/sound/bgatmosphere.cpp b/engines/gob/sound/bgatmosphere.cpp
index 12ceb031b7..6ce184155e 100644
--- a/engines/gob/sound/bgatmosphere.cpp
+++ b/engines/gob/sound/bgatmosphere.cpp
@@ -27,6 +27,7 @@
#include "common/events.h"
#include "gob/sound/bgatmosphere.h"
+#include "gob/sound/sounddesc.h"
namespace Gob {
diff --git a/engines/gob/sound/bgatmosphere.h b/engines/gob/sound/bgatmosphere.h
index 3fa648b94d..aa8cf58e10 100644
--- a/engines/gob/sound/bgatmosphere.h
+++ b/engines/gob/sound/bgatmosphere.h
@@ -29,11 +29,12 @@
#include "sound/mixer.h"
#include "common/mutex.h"
-#include "gob/sound/sounddesc.h"
#include "gob/sound/soundmixer.h"
namespace Gob {
+class SoundDesc;
+
class BackgroundAtmosphere : private SoundMixer {
public:
enum PlayMode {
diff --git a/engines/gob/sound/cdrom.cpp b/engines/gob/sound/cdrom.cpp
index ec9b2aaccb..4d6a7ec966 100644
--- a/engines/gob/sound/cdrom.cpp
+++ b/engines/gob/sound/cdrom.cpp
@@ -30,6 +30,7 @@
#include "gob/gob.h"
#include "gob/sound/cdrom.h"
#include "gob/helper.h"
+#include "gob/dataio.h"
namespace Gob {
@@ -86,7 +87,7 @@ void CDROM::startTrack(const char *trackName) {
byte *matchPtr = getTrackBuffer(trackName);
if (!matchPtr) {
- warning("Track \"%s\" not found", trackName);
+ warning("CDROM: Track \"%s\" not found", trackName);
return;
}
diff --git a/engines/gob/sound/cdrom.h b/engines/gob/sound/cdrom.h
index 201f7adb75..6f01e6f90a 100644
--- a/engines/gob/sound/cdrom.h
+++ b/engines/gob/sound/cdrom.h
@@ -26,10 +26,10 @@
#ifndef GOB_SOUND_CDROM_H
#define GOB_SOUND_CDROM_H
-#include "gob/dataio.h"
-
namespace Gob {
+class DataStream;
+
class CDROM {
public:
CDROM();
diff --git a/engines/gob/sound/infogrames.cpp b/engines/gob/sound/infogrames.cpp
index 0b46f3485c..c955dba43f 100644
--- a/engines/gob/sound/infogrames.cpp
+++ b/engines/gob/sound/infogrames.cpp
@@ -55,7 +55,7 @@ bool Infogrames::loadSong(const char *fileName) {
_mixer->getOutputRate(), _mixer->getOutputRate() / 75);
if (!_song->load(fileName)) {
- warning("Couldn't load infogrames music");
+ warning("Infogrames: Couldn't load music \"%s\"", fileName);
clearSong();
return false;
}
@@ -92,7 +92,7 @@ void Infogrames::clearSong() {
bool Infogrames::loadInst(const char *fileName) {
_instruments = new Audio::Infogrames::Instruments;
if (!_instruments->load(fileName)) {
- warning("Couldn't load instruments file");
+ warning("Infogrames: Couldn't load instruments \"%s\"", fileName);
clearInstruments();
return false;
}
diff --git a/engines/gob/sound/protracker.cpp b/engines/gob/sound/protracker.cpp
index 891580ef40..3e33cfd494 100644
--- a/engines/gob/sound/protracker.cpp
+++ b/engines/gob/sound/protracker.cpp
@@ -25,6 +25,8 @@
#include "common/file.h"
+#include "sound/mods/protracker.h"
+
#include "gob/sound/protracker.h"
namespace Gob {
diff --git a/engines/gob/sound/protracker.h b/engines/gob/sound/protracker.h
index 6270530427..73cae0d510 100644
--- a/engines/gob/sound/protracker.h
+++ b/engines/gob/sound/protracker.h
@@ -28,7 +28,6 @@
#include "sound/mixer.h"
#include "sound/audiostream.h"
-#include "sound/mods/protracker.h"
namespace Gob {
diff --git a/engines/gob/sound/sound.cpp b/engines/gob/sound/sound.cpp
index f0cf17b989..d3afc9baa3 100644
--- a/engines/gob/sound/sound.cpp
+++ b/engines/gob/sound/sound.cpp
@@ -31,20 +31,28 @@
#include "gob/game.h"
#include "gob/inter.h"
+#include "gob/sound/pcspeaker.h"
+#include "gob/sound/soundblaster.h"
+#include "gob/sound/adlib.h"
+#include "gob/sound/infogrames.h"
+#include "gob/sound/protracker.h"
+#include "gob/sound/cdrom.h"
+
namespace Gob {
Sound::Sound(GobEngine *vm) : _vm(vm) {
_pcspeaker = new PCSpeaker(*_vm->_mixer);
_blaster = new SoundBlaster(*_vm->_mixer);
- _adlib = 0;
+ _adlPlayer = 0;
+ _mdyPlayer = 0;
_infogrames = 0;
_protracker = 0;
_cdrom = 0;
_bgatmos = 0;
- if (!_vm->_noMusic && _vm->hasAdlib())
- _adlib = new AdLib(*_vm->_mixer);
+ _hasAdLib = (!_vm->_noMusic && _vm->hasAdlib());
+
if (!_vm->_noMusic && (_vm->getPlatform() == Common::kPlatformAmiga)) {
_infogrames = new Infogrames(*_vm->_mixer);
_protracker = new Protracker(*_vm->_mixer);
@@ -62,7 +70,8 @@ Sound::Sound(GobEngine *vm) : _vm(vm) {
Sound::~Sound() {
delete _pcspeaker;
delete _blaster;
- delete _adlib;
+ delete _adlPlayer;
+ delete _mdyPlayer;
delete _infogrames;
delete _protracker;
delete _cdrom;
@@ -105,14 +114,11 @@ bool Sound::sampleLoad(SoundDesc *sndDesc, SoundType type, const char *fileName,
debugC(2, kDebugSound, "Loading sample \"%s\"", fileName);
- int16 handle = _vm->_dataIO->openData(fileName);
- if (handle < 0) {
+ if (!_vm->_dataIO->existData(fileName)) {
warning("Can't open sample file \"%s\"", fileName);
return false;
}
- _vm->_dataIO->closeData(handle);
-
byte *data;
uint32 size;
@@ -121,7 +127,7 @@ bool Sound::sampleLoad(SoundDesc *sndDesc, SoundType type, const char *fileName,
return false;
size = _vm->_dataIO->getDataSize(fileName);
- return sndDesc->load(type, SOUND_FILE, data, size);
+ return sndDesc->load(type, data, size);
}
void Sound::sampleFree(SoundDesc *sndDesc, bool noteAdlib, int index) {
@@ -130,9 +136,14 @@ void Sound::sampleFree(SoundDesc *sndDesc, bool noteAdlib, int index) {
if (sndDesc->getType() == SOUND_ADL) {
- if (_adlib && noteAdlib)
- if ((index == -1) || (_adlib->getIndex() == index))
- _adlib->stopPlay();
+ if (noteAdlib) {
+ if (_adlPlayer)
+ if ((index == -1) || (_adlPlayer->getIndex() == index))
+ _adlPlayer->stopPlay();
+ if (_mdyPlayer)
+ if ((index == -1) || (_mdyPlayer->getIndex() == index))
+ _mdyPlayer->stopPlay();
+ }
} else {
@@ -223,50 +234,112 @@ void Sound::infogramesStop() {
_infogrames->stop();
}
-bool Sound::adlibLoad(const char *fileName) {
- if (!_adlib)
+bool Sound::adlibLoadADL(const char *fileName) {
+ if (!_hasAdLib)
return false;
- debugC(1, kDebugSound, "Adlib: Loading data (\"%s\")", fileName);
+ if (!_adlPlayer)
+ _adlPlayer = new ADLPlayer(*_vm->_mixer);
+
+ debugC(1, kDebugSound, "Adlib: Loading ADL data (\"%s\")", fileName);
- return _adlib->load(fileName);
+ return _adlPlayer->load(fileName);
}
-bool Sound::adlibLoad(byte *data, uint32 size, int index) {
- if (!_adlib)
+bool Sound::adlibLoadADL(byte *data, uint32 size, int index) {
+ if (!_hasAdLib)
return false;
- debugC(1, kDebugSound, "Adlib: Loading data (%d)", index);
+ if (!_adlPlayer)
+ _adlPlayer = new ADLPlayer(*_vm->_mixer);
+
+ debugC(1, kDebugSound, "Adlib: Loading ADL data (%d)", index);
- return _adlib->load(data, size, index);
+ return _adlPlayer->load(data, size, index);
}
void Sound::adlibUnload() {
- if (!_adlib)
+ if (!_hasAdLib)
return;
debugC(1, kDebugSound, "Adlib: Unloading data");
- _adlib->unload();
+ if (_adlPlayer)
+ _adlPlayer->unload();
+ if (_mdyPlayer)
+ _mdyPlayer->unload();
+}
+
+bool Sound::adlibLoadMDY(const char *fileName) {
+ if (!_hasAdLib)
+ return false;
+
+ if (!_mdyPlayer)
+ _mdyPlayer = new MDYPlayer(*_vm->_mixer);
+
+ debugC(1, kDebugSound, "Adlib: Loading MDY data (\"%s\")", fileName);
+
+ if (!_vm->_dataIO->existData(fileName)) {
+ warning("Can't open MDY file \"%s\"", fileName);
+ return false;
+ }
+
+ DataStream *stream = _vm->_dataIO->getDataStream(fileName);
+
+ bool loaded = _mdyPlayer->loadMDY(*stream);
+
+ delete stream;
+
+ return loaded;
+}
+
+bool Sound::adlibLoadTBR(const char *fileName) {
+ if (!_hasAdLib)
+ return false;
+
+ if (!_mdyPlayer)
+ _mdyPlayer = new MDYPlayer(*_vm->_mixer);
+
+ if (!_vm->_dataIO->existData(fileName)) {
+ warning("Can't open TBR file \"%s\"", fileName);
+ return false;
+ }
+
+ debugC(1, kDebugSound, "Adlib: Loading MDY instruments (\"%s\")", fileName);
+
+ DataStream *stream = _vm->_dataIO->getDataStream(fileName);
+
+ bool loaded = _mdyPlayer->loadTBR(*stream);
+
+ delete stream;
+
+ return loaded;
}
void Sound::adlibPlayTrack(const char *trackname) {
- if (!_adlib || _adlib->isPlaying())
+ if (!_hasAdLib)
return;
- debugC(1, kDebugSound, "Adlib: Playing track \"%s\"", trackname);
+ if (!_adlPlayer)
+ _adlPlayer = new ADLPlayer(*_vm->_mixer);
- _adlib->unload();
- _adlib->load(trackname);
- _adlib->startPlay();
+ if (_adlPlayer->isPlaying())
+ return;
+
+ debugC(1, kDebugSound, "Adlib: Playing ADL track \"%s\"", trackname);
+
+ _adlPlayer->unload();
+ _adlPlayer->load(trackname);
+ _adlPlayer->startPlay();
}
void Sound::adlibPlayBgMusic() {
- int track;
-
- if (!_adlib)
+ if (!_hasAdLib)
return;
+ if (!_adlPlayer)
+ _adlPlayer = new ADLPlayer(*_vm->_mixer);
+
static const char *tracksMac[] = {
// "musmac1.adl", // TODO: This track isn't played correctly at all yet
"musmac2.adl",
@@ -285,58 +358,82 @@ void Sound::adlibPlayBgMusic() {
};
if (_vm->getPlatform() == Common::kPlatformWindows) {
- track = _vm->_util->getRandom(ARRAYSIZE(tracksWin));
+ int track = _vm->_util->getRandom(ARRAYSIZE(tracksWin));
adlibPlayTrack(tracksWin[track]);
} else {
- track = _vm->_util->getRandom(ARRAYSIZE(tracksMac));
+ int track = _vm->_util->getRandom(ARRAYSIZE(tracksMac));
adlibPlayTrack(tracksMac[track]);
}
}
void Sound::adlibPlay() {
- if (!_adlib)
+ if (!_hasAdLib)
return;
debugC(1, kDebugSound, "Adlib: Starting playback");
- _adlib->startPlay();
+ if (_adlPlayer)
+ _adlPlayer->startPlay();
+ if (_mdyPlayer)
+ _mdyPlayer->startPlay();
}
void Sound::adlibStop() {
- if (!_adlib)
+ if (!_hasAdLib)
return;
debugC(1, kDebugSound, "Adlib: Stopping playback");
- _adlib->stopPlay();
+ if (_adlPlayer)
+ _adlPlayer->stopPlay();
+ if (_mdyPlayer)
+ _mdyPlayer->stopPlay();
}
bool Sound::adlibIsPlaying() const {
- if (!_adlib)
+ if (!_hasAdLib)
return false;
- return _adlib->isPlaying();
+ if (_adlPlayer && _adlPlayer->isPlaying())
+ return true;
+ if (_mdyPlayer && _mdyPlayer->isPlaying())
+ return true;
+
+ return false;
}
int Sound::adlibGetIndex() const {
- if (!_adlib)
+ if (!_hasAdLib)
return -1;
- return _adlib->getIndex();
+ if (_adlPlayer)
+ return _adlPlayer->getIndex();
+ if (_mdyPlayer)
+ return _mdyPlayer->getIndex();
+
+ return -1;
}
bool Sound::adlibGetRepeating() const {
- if (!_adlib)
+ if (!_hasAdLib)
return false;
- return _adlib->getRepeating();
+ if (_adlPlayer)
+ return _adlPlayer->getRepeating();
+ if (_mdyPlayer)
+ return _mdyPlayer->getRepeating();
+
+ return false;
}
void Sound::adlibSetRepeating(int32 repCount) {
- if (!_adlib)
+ if (!_hasAdLib)
return;
- _adlib->setRepeating(repCount);
+ if (_adlPlayer)
+ _adlPlayer->setRepeating(repCount);
+ if (_mdyPlayer)
+ _mdyPlayer->setRepeating(repCount);
}
void Sound::blasterPlay(SoundDesc *sndDesc, int16 repCount,
@@ -425,17 +522,12 @@ void Sound::cdLoadLIC(const char *fname) {
debugC(1, kDebugSound, "CDROM: Loading LIC \"%s\"", fname);
- int handle = _vm->_dataIO->openData(fname);
-
- if (handle == -1)
+ if (!_vm->_dataIO->existData(fname))
return;
- _vm->_dataIO->closeData(handle);
-
_vm->_dataIO->getUnpackedData(fname);
- handle = _vm->_dataIO->openData(fname);
- DataStream *stream = _vm->_dataIO->openAsStream(handle, true);
+ DataStream *stream = _vm->_dataIO->getDataStream(fname);
_cdrom->readLIC(*stream);
diff --git a/engines/gob/sound/sound.h b/engines/gob/sound/sound.h
index dbdd580ec7..6f6c1d0469 100644
--- a/engines/gob/sound/sound.h
+++ b/engines/gob/sound/sound.h
@@ -27,16 +27,19 @@
#define GOB_SOUND_SOUND_H
#include "gob/sound/sounddesc.h"
-#include "gob/sound/pcspeaker.h"
-#include "gob/sound/soundblaster.h"
-#include "gob/sound/adlib.h"
-#include "gob/sound/infogrames.h"
-#include "gob/sound/protracker.h"
-#include "gob/sound/cdrom.h"
#include "gob/sound/bgatmosphere.h"
namespace Gob {
+class GobEngine;
+class PCSpeaker;
+class SoundBlaster;
+class ADLPlayer;
+class MDYPlayer;
+class Infogrames;
+class Protracker;
+class CDROM;
+
class Sound {
public:
static const int kSoundsCount = 60;
@@ -77,8 +80,10 @@ public:
// AdLib
- bool adlibLoad(const char *fileName);
- bool adlibLoad(byte *data, uint32 size, int index = -1);
+ bool adlibLoadADL(const char *fileName);
+ bool adlibLoadADL(byte *data, uint32 size, int index = -1);
+ bool adlibLoadMDY(const char *fileName);
+ bool adlibLoadTBR(const char *fileName);
void adlibUnload();
void adlibPlayTrack(const char *trackname);
@@ -139,11 +144,14 @@ public:
private:
GobEngine *_vm;
+ bool _hasAdLib;
+
SoundDesc _sounds[kSoundsCount];
PCSpeaker *_pcspeaker;
SoundBlaster *_blaster;
- AdLib *_adlib;
+ ADLPlayer *_adlPlayer;
+ MDYPlayer *_mdyPlayer;
Infogrames *_infogrames;
Protracker *_protracker;
CDROM *_cdrom;
diff --git a/engines/gob/sound/soundblaster.cpp b/engines/gob/sound/soundblaster.cpp
index 23eea90688..69610dc949 100644
--- a/engines/gob/sound/soundblaster.cpp
+++ b/engines/gob/sound/soundblaster.cpp
@@ -24,6 +24,7 @@
*/
#include "gob/sound/soundblaster.h"
+#include "gob/sound/sounddesc.h"
namespace Gob {
diff --git a/engines/gob/sound/soundblaster.h b/engines/gob/sound/soundblaster.h
index c57e4a443e..a2dc87267c 100644
--- a/engines/gob/sound/soundblaster.h
+++ b/engines/gob/sound/soundblaster.h
@@ -29,11 +29,12 @@
#include "common/mutex.h"
#include "sound/mixer.h"
-#include "gob/sound/sounddesc.h"
#include "gob/sound/soundmixer.h"
namespace Gob {
+class SoundDesc;
+
class SoundBlaster : public SoundMixer {
public:
SoundBlaster(Audio::Mixer &mixer);
diff --git a/engines/gob/sound/sounddesc.cpp b/engines/gob/sound/sounddesc.cpp
index c4c78eebbd..b9b327d105 100644
--- a/engines/gob/sound/sounddesc.cpp
+++ b/engines/gob/sound/sounddesc.cpp
@@ -29,15 +29,17 @@
#include "sound/wave.h"
#include "gob/sound/sounddesc.h"
+#include "gob/resources.h"
namespace Gob {
SoundDesc::SoundDesc() {
+ _resource = 0;
+
_data = _dataPtr = 0;
_size = 0;
_type = SOUND_SND;
- _source = SOUND_FILE;
_repCount = 0;
_frequency = 0;
@@ -50,23 +52,31 @@ SoundDesc::~SoundDesc() {
free();
}
-void SoundDesc::set(SoundType type, SoundSource src,
- byte *data, uint32 dSize) {
-
+void SoundDesc::set(SoundType type, byte *data, uint32 dSize) {
free();
_type = type;
- _source = src;
_data = _dataPtr = data;
_size = dSize;
}
-bool SoundDesc::load(SoundType type, SoundSource src,
- byte *data, uint32 dSize) {
+void SoundDesc::set(SoundType type, Resource *resource) {
+ byte *data = 0;
+ uint32 dSize = 0;
+
+ if (resource && (resource->getSize() > 0)) {
+ data = resource->getData();
+ dSize = resource->getSize();
+ }
+
+ set(type, data, dSize);
+ _resource = resource;
+}
+
+bool SoundDesc::load(SoundType type, byte *data, uint32 dSize) {
free();
- _source = src;
switch (type) {
case SOUND_ADL:
return loadADL(data, dSize);
@@ -79,10 +89,28 @@ bool SoundDesc::load(SoundType type, SoundSource src,
return false;
}
+bool SoundDesc::load(SoundType type, Resource *resource) {
+ if (!resource || (resource->getSize() <= 0))
+ return false;
+
+ if (!load(type, resource->getData(), resource->getSize()))
+ return false;
+
+ _resource = resource;
+ return true;
+}
+
void SoundDesc::free() {
- if (_source != SOUND_TOT)
- delete[] _data;
- _data = _dataPtr = 0;
+ if (_resource) {
+ delete _resource;
+ _data = 0;
+ }
+
+ delete[] _data;
+
+ _resource = 0;
+ _data = 0;
+ _dataPtr = 0;
_id = 0;
}
diff --git a/engines/gob/sound/sounddesc.h b/engines/gob/sound/sounddesc.h
index 83efd61e6d..9e5d20e138 100644
--- a/engines/gob/sound/sounddesc.h
+++ b/engines/gob/sound/sounddesc.h
@@ -30,18 +30,14 @@
namespace Gob {
+class Resource;
+
enum SoundType {
SOUND_SND,
SOUND_WAV,
SOUND_ADL
};
-enum SoundSource {
- SOUND_FILE,
- SOUND_TOT,
- SOUND_EXT
-};
-
class SoundDesc {
public:
int16 _repCount;
@@ -58,8 +54,11 @@ public:
bool isId(int16 id) const { return _dataPtr && (_id == id); }
- void set(SoundType type, SoundSource src, byte *data, uint32 dSize);
- bool load(SoundType type, SoundSource src, byte *data, uint32 dSize);
+ void set(SoundType type, byte *data, uint32 dSize);
+ void set(SoundType type, Resource *resource);
+ bool load(SoundType type, byte *data, uint32 dSize);
+ bool load(SoundType type, Resource *resource);
+
void free();
void convToSigned();
@@ -71,12 +70,12 @@ public:
~SoundDesc();
private:
+ Resource *_resource;
byte *_data;
byte *_dataPtr;
uint32 _size;
SoundType _type;
- SoundSource _source;
bool loadSND(byte *data, uint32 dSize);
bool loadWAV(byte *data, uint32 dSize);
diff --git a/engines/gob/sound/soundmixer.cpp b/engines/gob/sound/soundmixer.cpp
index ea1dd2ef82..68a96d3b01 100644
--- a/engines/gob/sound/soundmixer.cpp
+++ b/engines/gob/sound/soundmixer.cpp
@@ -24,6 +24,7 @@
*/
#include "gob/sound/soundmixer.h"
+#include "gob/sound/sounddesc.h"
namespace Gob {
diff --git a/engines/gob/sound/soundmixer.h b/engines/gob/sound/soundmixer.h
index f32beb149f..20376b5152 100644
--- a/engines/gob/sound/soundmixer.h
+++ b/engines/gob/sound/soundmixer.h
@@ -31,10 +31,10 @@
#include "sound/audiostream.h"
#include "sound/mixer.h"
-#include "gob/sound/sounddesc.h"
-
namespace Gob {
+class SoundDesc;
+
class SoundMixer : public Audio::AudioStream {
public:
SoundMixer(Audio::Mixer &mixer, Audio::Mixer::SoundType type);
diff --git a/engines/gob/totfile.cpp b/engines/gob/totfile.cpp
new file mode 100644
index 0000000000..bbf62c143b
--- /dev/null
+++ b/engines/gob/totfile.cpp
@@ -0,0 +1,135 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/str.h"
+#include "common/stream.h"
+
+#include "gob/gob.h"
+#include "gob/totfile.h"
+#include "gob/dataio.h"
+#include "gob/videoplayer.h"
+
+namespace Gob {
+
+TOTFile::TOTFile(GobEngine *vm) : _vm(vm) {
+ _stream = 0;
+
+ memset(_header, 0, 128);
+}
+
+TOTFile::~TOTFile() {
+ unload();
+}
+
+bool TOTFile::load(const Common::String &fileName) {
+ // Trying to open normally
+ _stream = _vm->_dataIO->getDataStream(fileName.c_str());
+
+ if (!_stream)
+ // Trying to open from video
+ _stream = _vm->_vidPlayer->getExtraData(fileName.c_str());
+
+ if (!_stream)
+ return false;
+
+ if (_stream->read(_header, 128) != 128)
+ return false;
+
+ _stream->seek(0);
+
+ return true;
+}
+
+void TOTFile::unload() {
+ delete _stream;
+
+ _stream = 0;
+}
+
+Common::SeekableReadStream *TOTFile::getStream() const {
+ return _stream;
+}
+
+bool TOTFile::getProperties(Properties &props) const {
+ if (!_stream)
+ return false;
+
+ // Offset 39-41: Version in "Major.Minor" string form
+ if (_header[40] != '.')
+ return false;
+
+ props.versionMajor = _header[39] - '0';
+ props.versionMinor = _header[41] - '0';
+
+ props.variablesCount = READ_LE_UINT32(_header + 44);
+
+ props.textsOffset = READ_LE_UINT32(_header + 48);
+ props.resourcesOffset = READ_LE_UINT32(_header + 52);
+
+ props.animDataSize = READ_LE_UINT16(_header + 56);
+
+ props.imFileNumber = _header[59];
+ props.exFileNumber = _header[60];
+ props.communHandling = _header[61];
+
+ for (int i = 0; i < 14; i++)
+ props.functions[i] = READ_LE_UINT16(_header + 100 + i * 2);
+
+ props.scriptEnd = _stream->size();
+ if (props.textsOffset > 0)
+ props.scriptEnd = MIN(props.scriptEnd, props.textsOffset);
+ if (props.resourcesOffset > 0)
+ props.scriptEnd = MIN(props.scriptEnd, props.resourcesOffset);
+
+ return true;
+}
+
+Common::String TOTFile::createFileName(const Common::String &base, bool &isLOM) {
+ isLOM = false;
+
+ const char *dot;
+ if ((dot = strrchr(base.c_str(), '.'))) {
+ // fileName includes an extension
+
+ if (!scumm_stricmp(dot + 1, "LOM"))
+ isLOM = true;
+
+ return base;
+ }
+
+ return base + ".tot";
+}
+
+Common::String TOTFile::getFileBase(const Common::String &fileName) {
+ const char *dot;
+ if ((dot = strrchr(fileName.c_str(), '.'))) {
+ // fileName includes an extension
+ return Common::String(fileName.c_str(), dot);
+ }
+
+ return fileName;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/totfile.h b/engines/gob/totfile.h
new file mode 100644
index 0000000000..00963d36a2
--- /dev/null
+++ b/engines/gob/totfile.h
@@ -0,0 +1,80 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_TOTFILE_H
+#define GOB_TOTFILE_H
+
+#include "common/str.h"
+
+namespace Common {
+ class SeekableReadStream;
+}
+
+namespace Gob {
+
+class TOTFile {
+public:
+ enum Function {
+ kFunctionStart = 0,
+ kFunctionCenter = 13
+ };
+
+ struct Properties {
+ uint8 versionMajor;
+ uint8 versionMinor;
+ uint32 variablesCount;
+ uint32 textsOffset;
+ uint32 resourcesOffset;
+ uint16 animDataSize;
+ uint8 imFileNumber;
+ uint8 exFileNumber;
+ uint8 communHandling;
+ uint16 functions[14];
+ uint32 scriptEnd;
+ };
+
+ TOTFile(GobEngine *vm);
+ ~TOTFile();
+
+ bool load(const Common::String &fileName);
+ void unload();
+
+ Common::SeekableReadStream *getStream() const;
+ bool getProperties(Properties &props) const;
+
+ static Common::String createFileName(const Common::String &base, bool &isLOM);
+ static Common::String getFileBase(const Common::String &fileName);
+
+private:
+ GobEngine *_vm;
+
+ Common::SeekableReadStream *_stream;
+
+ byte _header[128];
+};
+
+} // End of namespace Gob
+
+#endif // GOB_TOTFILE_H
diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp
index e1148dacb9..b0e7691c07 100644
--- a/engines/gob/util.cpp
+++ b/engines/gob/util.cpp
@@ -331,6 +331,12 @@ void Util::setFrameRate(int16 rate) {
_frameRate = rate;
_frameWaitTime = 1000 / rate;
_startFrameTime = getTimeKey();
+ _frameWaitLag = 0;
+}
+
+void Util::notifyNewAnim() {
+ _startFrameTime = getTimeKey();
+ _frameWaitLag = 0;
}
void Util::waitEndFrame() {
diff --git a/engines/gob/util.h b/engines/gob/util.h
index 3d7520fe69..0a76ee40ab 100644
--- a/engines/gob/util.h
+++ b/engines/gob/util.h
@@ -76,6 +76,7 @@ public:
void clearPalette(void);
int16 getFrameRate();
void setFrameRate(int16 rate);
+ void notifyNewAnim();
void waitEndFrame();
void setScrollOffset(int16 x = -1, int16 y = -1);
diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp
index e82805d6ac..6c07d22333 100644
--- a/engines/gob/videoplayer.cpp
+++ b/engines/gob/videoplayer.cpp
@@ -201,15 +201,11 @@ bool VideoPlayer::findFile(char *fileName, Type &which) {
int i;
for (i = 0; i < ARRAYSIZE(_extensions); i++) {
if ((which == kVideoTypeTry) || (which == ((Type) i))) {
- int16 handle;
-
fileName[len] = '.';
fileName[len + 1] = 0;
strcat(fileName, _extensions[i]);
- handle = _vm->_dataIO->openData(fileName);
- if (handle >= 0) {
- _vm->_dataIO->closeData(handle);
+ if (_vm->_dataIO->existData(fileName)) {
which = (Type) i;
break;
}
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index 8d0e466bba..14f1c6463c 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -48,8 +48,6 @@ static const PlainGameDescriptor groovieGames[] = {
{0, 0}
};
-using Common::GUIO_NONE;
-
static const GroovieGameDescription gameDescriptions[] = {
// The 7th Guest DOS English
@@ -57,7 +55,7 @@ static const GroovieGameDescription gameDescriptions[] = {
{
"t7g", "",
AD_ENTRY1s("script.grv", "d1b8033b40aa67c076039881eccce90d", 16659),
- Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE
+ Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NONE
},
kGroovieT7G, 0
},
@@ -67,7 +65,7 @@ static const GroovieGameDescription gameDescriptions[] = {
{
"t7g", "",
AD_ENTRY1s("script.grv", "6e30b54b1f3bc2262cdcf7961db2ae67", 17191),
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_NO_FLAGS, GUIO_NONE
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_NO_FLAGS, Common::GUIO_NONE
},
kGroovieT7G, 0
},
@@ -81,7 +79,7 @@ static const GroovieGameDescription gameDescriptions[] = {
{ "intro.gjd", 0, NULL, 31711554},
{ NULL, 0, NULL, 0}
},
- Common::RU_RUS, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE
+ Common::RU_RUS, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NONE
},
kGroovieT7G, 0
},
@@ -92,7 +90,7 @@ static const GroovieGameDescription gameDescriptions[] = {
{
"11h", "",
AD_ENTRY1s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227),
- Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE
+ Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NONE
},
kGroovieV2, 1
},
@@ -102,7 +100,7 @@ static const GroovieGameDescription gameDescriptions[] = {
{
"11h", "Demo",
AD_ENTRY1s("disk.1", "aacb32ce07e0df2894bd83a3dee40c12", 70),
- Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NONE
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, Common::GUIO_NOLAUNCHLOAD
},
kGroovieV2, 1
},
@@ -112,7 +110,7 @@ static const GroovieGameDescription gameDescriptions[] = {
{
"11h", "Making Of",
AD_ENTRY1s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227),
- Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE
+ Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NOMIDI | Common::GUIO_NOLAUNCHLOAD
},
kGroovieV2, 2
},
@@ -122,7 +120,7 @@ static const GroovieGameDescription gameDescriptions[] = {
{
"clandestiny", "Trailer",
AD_ENTRY1s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227),
- Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE
+ Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NOMIDI | Common::GUIO_NOLAUNCHLOAD
},
kGroovieV2, 3
},
@@ -132,7 +130,7 @@ static const GroovieGameDescription gameDescriptions[] = {
{
"clandestiny", "",
AD_ENTRY1s("disk.1", "f79fc1515174540fef6a34132efc4c53", 76),
- Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE
+ Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NOMIDI
},
kGroovieV2, 1
},
@@ -142,7 +140,7 @@ static const GroovieGameDescription gameDescriptions[] = {
{
"unclehenry", "",
AD_ENTRY1s("disk.1", "0e1b1d3cecc4fc7efa62a968844d1f7a", 72),
- Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE
+ Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NOMIDI
},
kGroovieV2, 1
},
@@ -152,7 +150,7 @@ static const GroovieGameDescription gameDescriptions[] = {
{
"tlc", "",
AD_ENTRY1s("disk.1", "32a1afa68478f1f9d2b25eeea427f2e3", 84),
- Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE
+ Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NOMIDI
},
kGroovieV2, 1
},
@@ -179,7 +177,7 @@ static const ADParams detectionParams = {
// Flags
kADFlagUseExtraAsHint,
// Additional GUI options (for every game}
- Common::GUIO_NOMIDI
+ Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX
};
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 6e18b86062..e2315459d4 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -264,6 +264,11 @@ void GroovieEngine::errorString(const char *buf_input, char *buf_output, int buf
void GroovieEngine::syncSoundSettings() {
_musicPlayer->setUserVolume(ConfMan.getInt("music_volume"));
+ // VDX videos just contain one digital audio track, which can be used for
+ // both SFX or Speech, but the engine doesn't know what they contain, so
+ // we have to use just one volume setting for videos.
+ // We use "speech" because most users will want to change the videos
+ // volume when they can't hear the speech because of the music.
_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, ConfMan.getInt("speech_volume"));
}
diff --git a/engines/kyra/animator_mr.cpp b/engines/kyra/animator_mr.cpp
index d7139a9e70..faf1b150a2 100644
--- a/engines/kyra/animator_mr.cpp
+++ b/engines/kyra/animator_mr.cpp
@@ -119,7 +119,7 @@ void KyraEngine_MR::drawSceneAnimObject(AnimObj *obj, int x, int y, int layer) {
flags |= 0x8000;
x = obj->xPos2 - _sceneAnimMovie[obj->animNum]->xAdd();
y = obj->yPos2 - _sceneAnimMovie[obj->animNum]->yAdd();
- _sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, 2, x, y, flags | layer);
+ _sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, 2, x, y, flags | layer, 0, 0);
}
}
}
diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp
index e0c2c0aa77..d71f7b8b25 100644
--- a/engines/kyra/debugger.cpp
+++ b/engines/kyra/debugger.cpp
@@ -69,7 +69,7 @@ bool Debugger::cmd_setScreenDebug(int argc, const char **argv) {
}
bool Debugger::cmd_loadPalette(int argc, const char **argv) {
- uint8 palette[768];
+ Palette palette(_vm->screen()->getPalette(0).getNumColors());
if (argc <= 1) {
DebugPrintf("Use load_palette <file> [start_col] [end_col]\n");
@@ -80,7 +80,7 @@ bool Debugger::cmd_loadPalette(int argc, const char **argv) {
uint8 buffer[320*200];
_vm->screen()->copyRegionToBuffer(5, 0, 0, 320, 200, buffer);
_vm->screen()->loadBitmap(argv[1], 5, 5, 0);
- memcpy(palette, _vm->screen()->getCPagePtr(5), 768);
+ palette.copy(_vm->screen()->getCPagePtr(5), 0, 256);
_vm->screen()->copyBlockToPage(5, 0, 0, 320, 200, buffer);
} else if (!_vm->screen()->loadPalette(argv[1], palette)) {
DebugPrintf("ERROR: Palette '%s' not found!\n", argv[1]);
@@ -88,16 +88,16 @@ bool Debugger::cmd_loadPalette(int argc, const char **argv) {
}
int startCol = 0;
- int endCol = 255;
+ int endCol = palette.getNumColors();
if (argc > 2)
- startCol = MIN(255, MAX(0, atoi(argv[2])));
+ startCol = MIN(palette.getNumColors(), MAX(0, atoi(argv[2])));
if (argc > 3)
- endCol = MIN(255, MAX(0, atoi(argv[3])));
+ endCol = MIN(palette.getNumColors(), MAX(0, atoi(argv[3])));
if (startCol > 0)
- memcpy(palette, _vm->screen()->getScreenPalette(), startCol*3);
- if (endCol < 255)
- memcpy(palette + endCol * 3, _vm->screen()->getScreenPalette() + endCol * 3, (255-endCol)*3);
+ palette.copy(_vm->screen()->getPalette(0), 0, startCol);
+ if (endCol < palette.getNumColors())
+ palette.copy(_vm->screen()->getPalette(0), endCol);
_vm->screen()->setScreenPalette(palette);
_vm->screen()->updateScreen();
diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp
index faea2c9a72..85d974f675 100644
--- a/engines/kyra/gui.cpp
+++ b/engines/kyra/gui.cpp
@@ -83,17 +83,21 @@ void GUI::initMenu(Menu &menu) {
int menu_y2 = menu.height + menu.y - 1;
_screen->fillRect(menu.x + 2, menu.y + 2, menu_x2 - 2, menu_y2 - 2, menu.bkgdColor);
- _screen->drawShadedBox(menu.x, menu.y, menu_x2, menu_y2, menu.color1, menu.color2);
+ _screen->drawShadedBox(menu.x, menu.y, menu_x2, menu_y2, menu.color1, menu.color2, _vm->gameFlags().gameID == GI_LOL ? Screen::kShadeTypeLol : Screen::kShadeTypeKyra);
if (menu.titleX != -1)
textX = menu.titleX;
else
- textX = _text->getCenterStringX(getMenuTitle(menu), menu.x, menu_x2);
+ textX = getMenuCenterStringX(getMenuTitle(menu), menu.x, menu_x2);
textY = menu.y + menu.titleY;
- _text->printText(getMenuTitle(menu), textX - 1, textY + 1, defaultColor1(), defaultColor2(), 0);
- _text->printText(getMenuTitle(menu), textX, textY, menu.textColor, 0, 0);
+ if (_vm->gameFlags().gameID == GI_LOL) {
+ printMenuText(getMenuTitle(menu), textX, textY, menu.textColor, 0, 9);
+ } else {
+ printMenuText(getMenuTitle(menu), textX - 1, textY + 1, defaultColor1(), defaultColor2(), 0);
+ printMenuText(getMenuTitle(menu), textX, textY, menu.textColor, 0, 0);
+ }
int x1, y1, x2, y2;
for (int i = 0; i < menu.numberOfItems; ++i) {
@@ -114,35 +118,49 @@ void GUI::initMenu(Menu &menu) {
menuButtonData->width = menu.item[i].width - 1;
menuButtonData->height = menu.item[i].height - 1;
menuButtonData->buttonCallback = menu.item[i].callback;
- menuButtonData->keyCode = menu.item[i].unk1F;
+ menuButtonData->keyCode = menu.item[i].keyCode;
menuButtonData->keyCode2 = 0;
+ menuButtonData->arg = menu.item[i].itemId;
_menuButtonList = addButtonToList(_menuButtonList, menuButtonData);
}
_screen->fillRect(x1, y1, x2, y2, menu.item[i].bkgdColor);
- _screen->drawShadedBox(x1, y1, x2, y2, menu.item[i].color1, menu.item[i].color2);
+ _screen->drawShadedBox(x1, y1, x2, y2, menu.item[i].color1, menu.item[i].color2, _vm->gameFlags().gameID == GI_LOL ? Screen::kShadeTypeLol : Screen::kShadeTypeKyra);
if (getMenuItemTitle(menu.item[i])) {
if (menu.item[i].titleX != -1)
textX = x1 + menu.item[i].titleX + 3;
else
- textX = _text->getCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2);
+ textX = getMenuCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2);
textY = y1 + 2;
- _text->printText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0);
-
- if (i == menu.highlightedItem)
- _text->printText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0);
- else
- _text->printText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0);
+ if (_vm->gameFlags().gameID == GI_LOL) {
+ textY++;
+ if (i == menu.highlightedItem)
+ printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 8);
+ else
+ printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 8);
+ } else {
+ printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0);
+ if (i == menu.highlightedItem)
+ printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0);
+ else
+ printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0);
+ }
}
}
for (int i = 0; i < menu.numberOfItems; ++i) {
if (getMenuItemLabel(menu.item[i])) {
- _text->printText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX - 1, menu.y + menu.item[i].labelY + 1, defaultColor1(), 0, 0);
- _text->printText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX, menu.y + menu.item[i].labelY, menu.item[i].textColor, 0, 0);
+ if (_vm->gameFlags().gameID == GI_LOL) {
+ menu.item[i].labelX = menu.item[i].x - 1;
+ menu.item[i].labelY = menu.item[i].y + 3;
+ printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX, menu.y + menu.item[i].labelY, menu.item[i].textColor, 0, 10);
+ } else {
+ printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX - 1, menu.y + menu.item[i].labelY + 1, defaultColor1(), 0, 0);
+ printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX, menu.y + menu.item[i].labelY, menu.item[i].textColor, 0, 0);
+ }
}
}
@@ -172,8 +190,22 @@ void GUI::initMenu(Menu &menu) {
_screen->updateScreen();
}
-void GUI::processHighlights(Menu &menu, int mouseX, int mouseY) {
+void GUI::processHighlights(Menu &menu) {
int x1, y1, x2, y2;
+ Common::Point p = _vm->getMousePos();
+ int mouseX = p.x;
+ int mouseY = p.y;
+
+ if (_vm->_flags.gameID == GI_LOL && menu.highlightedItem != 255) {
+ // LoL doesnt't have default highlighted items.
+ // We use a highlightedItem value of 255 for this.
+
+ // With LoL no highlighting should take place unless the
+ // mouse cursor moves over a button. The highlighting should end
+ // when the mouse cursor leaves the button.
+ if (menu.item[menu.highlightedItem].enabled)
+ redrawText(menu);
+ }
for (int i = 0; i < menu.numberOfItems; ++i) {
if (!menu.item[i].enabled)
@@ -188,9 +220,11 @@ void GUI::processHighlights(Menu &menu, int mouseX, int mouseY) {
if (mouseX > x1 && mouseX < x2 &&
mouseY > y1 && mouseY < y2) {
- if (menu.highlightedItem != i) {
- if (menu.item[menu.highlightedItem].enabled)
- redrawText(menu);
+ if (menu.highlightedItem != i || _vm->_flags.gameID == GI_LOL) {
+ if (_vm->_flags.gameID != GI_LOL) {
+ if (menu.item[menu.highlightedItem].enabled)
+ redrawText(menu);
+ }
menu.highlightedItem = i;
redrawHighlight(menu);
@@ -212,11 +246,16 @@ void GUI::redrawText(const Menu &menu) {
if (menu.item[i].titleX >= 0)
textX = x1 + menu.item[i].titleX + 3;
else
- textX = _text->getCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2);
+ textX = getMenuCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2);
int textY = y1 + 2;
- _text->printText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0);
- _text->printText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0);
+ if (_vm->gameFlags().gameID == GI_LOL) {
+ textY++;
+ printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 8);
+ } else {
+ printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0);
+ printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0);
+ }
}
void GUI::redrawHighlight(const Menu &menu) {
@@ -231,11 +270,17 @@ void GUI::redrawHighlight(const Menu &menu) {
if (menu.item[i].titleX != -1)
textX = x1 + menu.item[i].titleX + 3;
else
- textX = _text->getCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2);
+ textX = getMenuCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2);
int textY = y1 + 2;
- _text->printText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0);
- _text->printText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0);
+
+ if (_vm->gameFlags().gameID == GI_LOL) {
+ textY++;
+ printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 8);
+ } else {
+ printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0);
+ printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0);
+ }
}
void GUI::updateAllMenuButtons() {
@@ -296,7 +341,7 @@ int GUI::redrawShadedButtonCallback(Button *button) {
return 0;
}
-void GUI::updateSaveList() {
+void GUI::updateSaveList(bool excludeQuickSaves) {
Common::String pattern = _vm->_targetName + ".???";
Common::StringList saveFileList = _vm->_saveFileMan->listSavefiles(pattern);
_saveSlots.clear();
@@ -311,6 +356,8 @@ void GUI::updateSaveList() {
s1 -= '0';
s2 -= '0';
s3 -= '0';
+ if (excludeQuickSaves && s1 == 9 && s2 == 9)
+ continue;
_saveSlots.push_back(s1*100+s2*10+s3);
}
@@ -383,6 +430,14 @@ void GUI::checkTextfieldInput() {
_vm->_system->delayMillis(3);
}
+void GUI::printMenuText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2, Screen::FontId font) {
+ _text->printText(str, x, y, c0, c1, c2, font);
+}
+
+int GUI::getMenuCenterStringX(const char *str, int x1, int x2) {
+ return _text->getCenterStringX(str, x1, x2);
+}
+
#pragma mark -
MainMenu::MainMenu(KyraEngine_v1 *vm) : _vm(vm), _screen(0) {
@@ -404,7 +459,7 @@ void MainMenu::updateAnimation() {
if (now > _nextUpdate) {
_nextUpdate = now + _anim.delay * _vm->tickLength();
- _anim.anim->displayFrame(_animIntern.curFrame, 0, 0, 0);
+ _anim.anim->displayFrame(_animIntern.curFrame, 0, 0, 0, 0, 0, 0);
_animIntern.curFrame += _animIntern.direction ;
if (_animIntern.curFrame < _anim.startFrame) {
_animIntern.curFrame = _anim.startFrame;
@@ -421,8 +476,9 @@ void MainMenu::updateAnimation() {
bool MainMenu::getInput() {
Common::Event event;
+ Common::EventManager *eventMan = _vm->getEventManager();
- while (_system->getEventManager()->pollEvent(event)) {
+ while (eventMan->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_LBUTTONUP:
return true;
diff --git a/engines/kyra/gui.h b/engines/kyra/gui.h
index f83620c8f9..3989062506 100644
--- a/engines/kyra/gui.h
+++ b/engines/kyra/gui.h
@@ -114,7 +114,7 @@ struct MenuItem {
uint16 labelId;
int16 labelX, labelY;
- uint16 unk1F;
+ uint16 keyCode;
};
struct Menu {
@@ -161,7 +161,7 @@ public:
virtual void initMenuLayout(Menu &menu);
void initMenu(Menu &menu);
- void processHighlights(Menu &menu, int mouseX, int mouseY);
+ void processHighlights(Menu &menu);
// utilities for thumbnail creation
virtual void createScreenThumbnail(Graphics::Surface &dst) = 0;
@@ -176,6 +176,9 @@ protected:
bool _displaySubMenu;
bool _cancelSubMenu;
+ virtual void printMenuText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2, Screen::FontId font=Screen::FID_8_FNT);
+ virtual int getMenuCenterStringX(const char *str, int x1, int x2);
+
Button::Callback _redrawShadedButtonFunctor;
Button::Callback _redrawButtonFunctor;
@@ -201,7 +204,7 @@ protected:
void redrawHighlight(const Menu &menu);
Common::Array<int> _saveSlots;
- void updateSaveList();
+ void updateSaveList(bool excludeQuickSaves = false);
int getNextSavegameSlot();
uint32 _lastScreenUpdate;
diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp
index a37ac7b306..69e7419757 100644
--- a/engines/kyra/gui_hof.cpp
+++ b/engines/kyra/gui_hof.cpp
@@ -95,7 +95,11 @@ const char *GUI_HoF::getMenuItemTitle(const MenuItem &menuItem) {
if (!menuItem.itemId)
return 0;
- return _vm->getTableString(menuItem.itemId, _vm->_optionsBuffer, 1);
+ // Strings 41-45 are menu labels, those must be handled uncompressed!
+ if (menuItem.itemId >= 41 && menuItem.itemId <= 45)
+ return _vm->getTableString(menuItem.itemId, _vm->_optionsBuffer, 0);
+ else
+ return _vm->getTableString(menuItem.itemId, _vm->_optionsBuffer, 1);
}
const char *GUI_HoF::getMenuItemLabel(const MenuItem &menuItem) {
@@ -272,7 +276,7 @@ void KyraEngine_HoF::redrawInventory(int page) {
}
void KyraEngine_HoF::scrollInventoryWheel() {
- WSAMovie_v2 movie(this, _screen);
+ WSAMovie_v2 movie(this);
movie.open("INVWHEEL.WSA", 0, 0);
int frames = movie.opened() ? movie.frames() : 6;
memcpy(_screenBuffer, _screen->getCPagePtr(2), 64000);
@@ -287,7 +291,7 @@ void KyraEngine_HoF::scrollInventoryWheel() {
for (int i = 0; i <= 6 && !breakFlag; ++i) {
if (movie.opened()) {
_screen->hideMouse();
- movie.displayFrame(i % frames, 0, 0, 0, 0);
+ movie.displayFrame(i % frames, 0, 0, 0, 0, 0, 0);
_screen->showMouse();
_screen->updateScreen();
}
@@ -361,9 +365,9 @@ int KyraEngine_HoF::bookButton(Button *button) {
_screen->showMouse();
}
- memcpy(_screen->getPalette(2), _screen->getPalette(0), 768);
+ _screen->copyPalette(2, 0);
_screen->fadeToBlack(7, &_updateFunctor);
- _res->loadFileToBuf("_BOOK.COL", _screen->getPalette(0), 768);
+ _screen->loadPalette("_BOOK.COL", _screen->getPalette(0));
loadBookBkgd();
showBookPage();
_screen->copyRegion(0, 0, 0, 0, 0x140, 0xC8, 2, 0, Screen::CR_NO_P_CHECK);
@@ -389,7 +393,7 @@ int KyraEngine_HoF::bookButton(Button *button) {
}
setHandItem(_itemInHand);
- memcpy(_screen->getPalette(0), _screen->getPalette(2), 768);
+ _screen->copyPalette(0, 2);
_screen->fadePalette(_screen->getPalette(0), 7, &_updateFunctor);
_screen->showMouse();
@@ -700,7 +704,6 @@ int GUI_HoF::optionsButton(Button *button) {
int oldHandItem = _vm->_itemInHand;
_screen->setMouseCursor(0, 0, _vm->getShapePtr(0));
_vm->displayInvWsaLastFrame();
- //XXX
_displayMenu = true;
for (uint i = 0; i < ARRAYSIZE(_menuButtons); ++i) {
@@ -763,7 +766,7 @@ int GUI_HoF::optionsButton(Button *button) {
}
while (_displayMenu) {
- processHighlights(*_currentMenu, _vm->_mouseX, _vm->_mouseY);
+ processHighlights(*_currentMenu);
getInput();
}
@@ -796,16 +799,11 @@ void GUI_HoF::createScreenThumbnail(Graphics::Surface &dst) {
}
void GUI_HoF::setupPalette() {
- memcpy(_screen->getPalette(1), _screen->getPalette(0), 768);
-
- uint8 *palette = _screen->getPalette(0);
- for (int i = 0; i < 768; ++i)
- palette[i] >>= 1;
-
- static const uint8 guiPal[] = { 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFc, 0xFD, 0xFE };
+ _screen->copyPalette(1, 0);
- for (uint i = 0; i < ARRAYSIZE(guiPal); ++i)
- memcpy(_screen->getPalette(0)+guiPal[i]*3, _screen->getPalette(1)+guiPal[i]*3, 3);
+ Palette &pal = _screen->getPalette(0);
+ for (int i = 0; i < 741; ++i)
+ pal[i] >>= 1;
if (_isDeathMenu)
_screen->fadePalette(_screen->getPalette(0), 0x64);
@@ -814,7 +812,7 @@ void GUI_HoF::setupPalette() {
}
void GUI_HoF::restorePalette() {
- memcpy(_screen->getPalette(0), _screen->getPalette(1), 768);
+ _screen->copyPalette(0, 1);
_screen->setScreenPalette(_screen->getPalette(0));
}
@@ -851,8 +849,7 @@ void GUI_HoF::drawSliderBar(int slider, const uint8 *shape) {
position = _vm->_configTextspeed;
}
- position = MAX(2, position);
- position = MIN(97, position);
+ position = CLIP(position, 2, 97);
_screen->drawShape(0, shape, x+position, y, 0, 0);
}
@@ -908,7 +905,7 @@ int GUI_HoF::audioOptions(Button *caller) {
updateAllMenuButtons();
bool speechEnabled = _vm->speechEnabled();
while (_isOptionsMenu) {
- processHighlights(_audioOptions, _vm->_mouseX, _vm->_mouseY);
+ processHighlights(_audioOptions);
getInput();
}
@@ -956,7 +953,7 @@ int GUI_HoF::gameOptions(Button *caller) {
}
while (_isOptionsMenu) {
- processHighlights(_gameOptions, _vm->_mouseX, _vm->_mouseY);
+ processHighlights(_gameOptions);
getInput();
}
@@ -983,7 +980,7 @@ int GUI_HoF::gameOptionsTalkie(Button *caller) {
_isOptionsMenu = true;
while (_isOptionsMenu) {
- processHighlights(_gameOptions, _vm->_mouseX, _vm->_mouseY);
+ processHighlights(_gameOptions);
getInput();
}
@@ -1094,8 +1091,7 @@ int GUI_HoF::sliderHandler(Button *caller) {
else
newVolume = _vm->_mouseX - caller->x - 7;
- newVolume = MAX(2, newVolume);
- newVolume = MIN(97, newVolume);
+ newVolume = CLIP(newVolume, 2, 97);
if (newVolume == oldVolume)
return 0;
@@ -1175,7 +1171,7 @@ int GUI_HoF::loadMenu(Button *caller) {
_screen->updateScreen();
while (_isLoadMenu) {
- processHighlights(_loadMenu, _vm->_mouseX, _vm->_mouseY);
+ processHighlights(_loadMenu);
getInput();
}
diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp
index 560bc6c2f2..9f42697ec7 100644
--- a/engines/kyra/gui_lok.cpp
+++ b/engines/kyra/gui_lok.cpp
@@ -31,6 +31,7 @@
#include "kyra/sound.h"
#include "kyra/gui_lok.h"
#include "kyra/timer.h"
+#include "kyra/util.h"
#include "common/config-manager.h"
#include "common/savefile.h"
@@ -86,7 +87,6 @@ int KyraEngine_LoK::buttonInventoryCallback(Button *caller) {
}
}
_screen->updateScreen();
- // XXX clearKyrandiaButtonIO
return 0;
}
@@ -182,7 +182,6 @@ int KyraEngine_LoK::buttonAmuletCallback(Button *caller) {
break;
}
_unkAmuletVar = 0;
- // XXX clearKyrandiaButtonIO (!used before every return in this function!)
return 1;
}
@@ -479,7 +478,7 @@ int GUI_LoK::buttonMenuCallback(Button *caller) {
}
while (_displayMenu && !_vm->shouldQuit()) {
- processHighlights(_menu[_toplevelMenu], _vm->_mouseX, _vm->_mouseY);
+ processHighlights(_menu[_toplevelMenu]);
getInput();
}
@@ -538,6 +537,9 @@ void GUI_LoK::setupSavegames(Menu &menu, int num) {
if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset]), header))) {
strncpy(savenames[i], header.description.c_str(), ARRAYSIZE(savenames[0]));
savenames[i][34] = 0;
+
+ Util::convertISOToDOS(savenames[i]);
+
menu.item[i].itemString = savenames[i];
menu.item[i].enabled = 1;
menu.item[i].saveSlot = _saveSlots[i + _savegameOffset];
@@ -570,7 +572,7 @@ int GUI_LoK::saveGameMenu(Button *button) {
_cancelSubMenu = false;
while (_displaySubMenu && !_vm->shouldQuit()) {
- processHighlights(_menu[2], _vm->_mouseX, _vm->_mouseY);
+ processHighlights(_menu[2]);
getInput();
}
@@ -616,7 +618,7 @@ int GUI_LoK::loadGameMenu(Button *button) {
_vm->_gameToLoad = -1;
while (_displaySubMenu && !_vm->shouldQuit()) {
- processHighlights(_menu[2], _vm->_mouseX, _vm->_mouseY);
+ processHighlights(_menu[2]);
getInput();
}
@@ -654,9 +656,12 @@ void GUI_LoK::updateSavegameString() {
if (_keyPressed.keycode) {
length = strlen(_savegameName);
- if (_keyPressed.ascii > 31 && _keyPressed.ascii < 127) {
+ char inputKey = _keyPressed.ascii;
+ Util::convertISOToDOS(inputKey);
+
+ if ((uint8)inputKey > 31 && (uint8)inputKey < 226) {
if (length < ARRAYSIZE(_savegameName)-1) {
- _savegameName[length] = _keyPressed.ascii;
+ _savegameName[length] = inputKey;
_savegameName[length+1] = 0;
redrawTextfield();
}
@@ -703,7 +708,7 @@ int GUI_LoK::saveGame(Button *button) {
while (_displaySubMenu && !_vm->shouldQuit()) {
checkTextfieldInput();
updateSavegameString();
- processHighlights(_menu[3], _vm->_mouseX, _vm->_mouseY);
+ processHighlights(_menu[3]);
}
if (_cancelSubMenu) {
@@ -715,6 +720,8 @@ int GUI_LoK::saveGame(Button *button) {
if (_savegameOffset == 0 && _vm->_gameToLoad == 0)
_vm->_gameToLoad = getNextSavegameSlot();
if (_vm->_gameToLoad > 0) {
+ Util::convertDOSToISO(_savegameName);
+
Graphics::Surface thumb;
createScreenThumbnail(thumb);
_vm->saveGameState(_vm->_gameToLoad, _savegameName, &thumb);
@@ -773,7 +780,7 @@ bool GUI_LoK::quitConfirm(const char *str) {
_cancelSubMenu = true;
while (_displaySubMenu && !_vm->shouldQuit()) {
- processHighlights(_menu[1], _vm->_mouseX, _vm->_mouseY);
+ processHighlights(_menu[1]);
getInput();
}
@@ -833,7 +840,7 @@ int GUI_LoK::gameControlsMenu(Button *button) {
_cancelSubMenu = false;
while (_displaySubMenu && !_vm->shouldQuit()) {
- processHighlights(_menu[5], _vm->_mouseX, _vm->_mouseY);
+ processHighlights(_menu[5]);
getInput();
}
@@ -1015,25 +1022,25 @@ void GUI_LoK::fadePalette() {
static const int16 menuPalIndexes[] = {248, 249, 250, 251, 252, 253, 254, -1};
int index = 0;
- memcpy(_screen->getPalette(2), _screen->_currentPalette, 768);
+ _screen->copyPalette(2, 0);
for (int i = 0; i < 768; i++)
- _screen->_currentPalette[i] >>= 1;
+ _screen->getPalette(0)[i] >>= 1;
while (menuPalIndexes[index] != -1) {
- memcpy(&_screen->_currentPalette[menuPalIndexes[index]*3], &_screen->getPalette(2)[menuPalIndexes[index]*3], 3);
- index++;
+ _screen->getPalette(0).copy(_screen->getPalette(2), menuPalIndexes[index], 1);
+ ++index;
}
- _screen->fadePalette(_screen->_currentPalette, 2);
+ _screen->fadePalette(_screen->getPalette(0), 2);
}
void GUI_LoK::restorePalette() {
if (_vm->gameFlags().platform == Common::kPlatformAmiga)
return;
- memcpy(_screen->_currentPalette, _screen->getPalette(2), 768);
- _screen->fadePalette(_screen->_currentPalette, 2);
+ _screen->copyPalette(0, 2);
+ _screen->fadePalette(_screen->getPalette(0), 2);
}
#pragma mark -
diff --git a/engines/kyra/gui_lok.h b/engines/kyra/gui_lok.h
index eec57f5546..5982ef1ce2 100644
--- a/engines/kyra/gui_lok.h
+++ b/engines/kyra/gui_lok.h
@@ -89,7 +89,7 @@ namespace Kyra {
item.labelString = r; \
item.labelX = s; \
item.labelY = t; \
- item.unk1F = v; \
+ item.keyCode = v; \
} while (0)
class KyraEngine_LoK;
diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp
index af8bc6aa97..5e03f3d9bb 100644
--- a/engines/kyra/gui_lol.cpp
+++ b/engines/kyra/gui_lol.cpp
@@ -28,6 +28,14 @@
#include "kyra/lol.h"
#include "kyra/screen_lol.h"
#include "kyra/gui_lol.h"
+#include "kyra/resource.h"
+#include "kyra/util.h"
+
+#include "common/savefile.h"
+#include "common/config-manager.h"
+#include "graphics/scaler.h"
+
+#include "base/version.h"
namespace Kyra {
@@ -577,7 +585,7 @@ void LoLEngine::gui_drawCompass() {
}
int LoLEngine::gui_enableControls() {
- _floatingMouseArrowControl = 0;
+ _floatingCursorControl = 0;
if (!_currentControlMode) {
for (int i = 76; i < 85; i++)
@@ -592,7 +600,7 @@ int LoLEngine::gui_disableControls(int controlMode) {
if (_currentControlMode)
return 0;
- _floatingMouseArrowControl = (controlMode & 2) ? 2 : 1;
+ _floatingCursorControl = (controlMode & 2) ? 2 : 1;
gui_toggleFightButtons(true);
@@ -1364,7 +1372,7 @@ int LoLEngine::clickedInventorySlot(Button *button) {
(_itemsInPlay[hItem].itemPropertyIndex == 220 || _itemsInPlay[slotItem].itemPropertyIndex == 220)) {
// merge ruby of truth
- WSAMovie_v2 *wsa = new WSAMovie_v2(this, _screen);
+ WSAMovie_v2 *wsa = new WSAMovie_v2(this);
wsa->open("truth.wsa", 0, 0);
_screen->hideMouse();
@@ -1377,7 +1385,7 @@ int LoLEngine::clickedInventorySlot(Button *button) {
for (int i = 0; i < 25; i++) {
uint32 delayTimer = _system->getMillis() + 7 * _tickLength;
_screen->copyRegion(button->x, button->y - 3, 0, 0, 25, 27, 2, 2);
- wsa->displayFrame(i, 2, 0, 0, 0x4000);
+ wsa->displayFrame(i, 2, 0, 0, 0x4000, 0, 0);
_screen->copyRegion(0, 0, button->x, button->y - 3, 25, 27, 2, 0);
_screen->updateScreen();
delayUntil(delayTimer);
@@ -1536,10 +1544,43 @@ int LoLEngine::clickedSceneThrowItem(Button *button) {
}
int LoLEngine::clickedOptions(Button *button) {
+ removeInputTop();
gui_toggleButtonDisplayMode(76, 1);
+ _updateFlags |= 4;
+
+ Button b;
+ b.data0Val2 = b.data1Val2 = b.data2Val2 = 0xfe;
+ b.data0Val3 = b.data1Val3 = b.data2Val3 = 0x01;
+
+ if (_weaponsDisabled)
+ clickedExitCharInventory(&b);
+
+ initTextFading(0, 1);
+ updatePortraits();
+ setLampMode(true);
+ setMouseCursorToIcon(0);
+ disableSysTimer(2);
+
gui_toggleButtonDisplayMode(76, 0);
+ bool speechWasEnabled = speechEnabled();
+ _gui->runMenu(_gui->_mainMenu);
+
+ _updateFlags &= 0xfffb;
+ setMouseCursorToItemInHand();
+ resetLampStatus();
+ gui_enableDefaultPlayfieldButtons();
+ enableSysTimer(2);
+ updateDrawPage2();
+
+ gui_drawPlayField();
+
+ if (speechWasEnabled && !textEnabled() && (!speechEnabled() || getVolume(kVolumeSpeech) == 2))
+ _configVoice = 0;
+
+ writeSettings();
+
return 1;
}
@@ -1773,7 +1814,7 @@ int LoLEngine::clickedAutomap(Button *button) {
displayAutomap();
gui_drawPlayField();
- setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect);
+ setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect);
return 1;
}
@@ -1801,7 +1842,7 @@ int LoLEngine::clickedLamp(Button *button) {
}
if (_brightness)
- setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect);
+ setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect);
return 1;
}
@@ -1826,9 +1867,13 @@ int LoLEngine::clickedStatusIcon(Button *button) {
GUI_LoL::GUI_LoL(LoLEngine *vm) : GUI(vm), _vm(vm), _screen(vm->_screen) {
_scrollUpFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::scrollUp);
_scrollDownFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::scrollDown);
+ _redrawButtonFunctor = BUTTON_FUNCTOR(GUI, this, &GUI::redrawButtonCallback);
+ _redrawShadedButtonFunctor = BUTTON_FUNCTOR(GUI, this, &GUI::redrawShadedButtonCallback);
+
_specialProcessButton = _backUpButtonList = 0;
_flagsModifier = 0;
_mouseClick = 0;
+ _sliderSfx = 11;
_buttonListChanged = false;
}
@@ -2164,6 +2209,624 @@ int GUI_LoL::processButtonList(Button *buttonList, uint16 inputFlag, int8 mouseW
return returnValue;
}
+int GUI_LoL::redrawButtonCallback(Button *button) {
+ if (!_displayMenu)
+ return 0;
+
+ _screen->drawBox(button->x + 1, button->y + 1, button->x + button->width - 1, button->y + button->height - 1, 225);
+ return 0;
+}
+
+int GUI_LoL::redrawShadedButtonCallback(Button *button) {
+ if (!_displayMenu)
+ return 0;
+
+ _screen->drawShadedBox(button->x, button->y, button->x + button->width, button->y + button->height, 223, 227, Screen::kShadeTypeLol);
+ return 0;
+}
+
+int GUI_LoL::runMenu(Menu &menu) {
+ _currentMenu = &menu;
+ _lastMenu = _currentMenu;
+ _newMenu = 0;
+ _displayMenu = true;
+ _menuResult = 1;
+ _savegameOffset = 0;
+ backupPage0();
+
+ const ScreenDim *d = _screen->getScreenDim(8);
+ uint32 textCursorTimer = 0;
+ uint8 textCursorStatus = 1;
+ int wW = _screen->getCharWidth('W');
+ int fW = (d->w << 3) - wW;
+ int fC = 0;
+
+ // LoL doesnt't have default higlighted items. No item should be
+ // highlighted when entering a new menu.
+ // Instead, the respevtive struct entry is used to determine whether
+ // a menu has scroll buttons or slider bars.
+ uint8 hasSpecialButtons = 0;
+
+ while (_displayMenu) {
+ _vm->_mouseX = _vm->_mouseY = 0;
+
+ if (_currentMenu == &_loadMenu || _currentMenu == &_saveMenu || _currentMenu == &_deleteMenu) {
+ updateSaveList(true);
+ Common::sort(_saveSlots.begin(), _saveSlots.end(), Common::Greater<int>());
+ setupSavegameNames(*_currentMenu, 4);
+ }
+
+ hasSpecialButtons = _currentMenu->highlightedItem;
+ _currentMenu->highlightedItem = 255;
+
+ if (_currentMenu == &_gameOptions) {
+ char *s = (char *)_vm->_tempBuffer5120;
+ strncpy(s, _vm->getLangString(0x406f + _vm->_monsterDifficulty), 30);
+ s[29] = 0;
+ _currentMenu->item[0].itemString = s;
+ s += (strlen(s) + 1);
+
+ strncpy(s, _vm->getLangString(_vm->_smoothScrollingEnabled ? 0x4068 : 0x4069), 30);
+ s[29] = 0;
+ _currentMenu->item[1].itemString = s;
+ s += (strlen(s) + 1);
+
+ strncpy(s, _vm->getLangString(_vm->_floatingCursorsEnabled ? 0x4068 : 0x4069), 30);
+ s[29] = 0;
+ _currentMenu->item[2].itemString = s;
+ s += (strlen(s) + 1);
+
+ strncpy(s, _vm->getLangString(0x42d6 + _vm->_lang), 30);
+ s[29] = 0;
+ _currentMenu->item[3].itemString = s;
+ s += (strlen(s) + 1);
+
+ strncpy(s, _vm->getLangString(_vm->textEnabled() ? 0x4068 : 0x4069), 30);
+ s[29] = 0;
+ _currentMenu->item[4].itemString = s;
+ s += (strlen(s) + 1);
+ }
+
+ if (hasSpecialButtons == 1) {
+ if (_savegameOffset == 0) {
+ _scrollUpButton.data0ShapePtr = _scrollUpButton.data1ShapePtr = _scrollUpButton.data2ShapePtr = 0;
+ } else {
+ _scrollUpButton.data0ShapePtr = _vm->_gameShapes[17];
+ _scrollUpButton.data1ShapePtr = _scrollUpButton.data2ShapePtr = _vm->_gameShapes[19];
+ }
+ if ((uint)_savegameOffset == _saveSlots.size() - 4) {
+ _scrollDownButton.data0ShapePtr = _scrollDownButton.data1ShapePtr = _scrollDownButton.data2ShapePtr = 0;
+ } else {
+ _scrollDownButton.data0ShapePtr = _vm->_gameShapes[18];
+ _scrollDownButton.data1ShapePtr = _scrollDownButton.data2ShapePtr = _vm->_gameShapes[20];
+ }
+ }
+
+ for (uint i = 0; i < _currentMenu->numberOfItems; ++i) {
+ _menuButtons[i].data0Val1 = _menuButtons[i].data1Val1 = _menuButtons[i].data2Val1 = 4;
+ _menuButtons[i].data0Callback = _redrawShadedButtonFunctor;
+ _menuButtons[i].data1Callback = _menuButtons[i].data2Callback = _redrawButtonFunctor;
+ _menuButtons[i].flags = 0x4487;
+ _menuButtons[i].flags2 = 0;
+ }
+
+ initMenu(*_currentMenu);
+
+ if (hasSpecialButtons == 2) {
+ static const uint8 oX[] = { 0, 10, 124 };
+ static const uint8 oW[] = { 10, 114, 10 };
+
+ for (int i = 1; i < 4; ++i) {
+ int tX = _currentMenu->x + _currentMenu->item[i].x;
+ int tY = _currentMenu->y + _currentMenu->item[i].y;
+
+ for (int ii = 0; ii < 3; ++ii) {
+ Button *b = getButtonListData() + 1 + (i - 1) * 3 + ii;
+ b->nextButton = 0;
+ b->data0Val2 = b->data1Val2 = b->data2Val2 = 0xfe;
+ b->data0Val3 = b->data1Val3 = b->data2Val3 = 0x01;
+
+ b->index = ii;
+ b->keyCode = b->keyCode2 = 0;
+
+ b->x = tX + oX[ii];
+ b->y = tY;
+ b->width = oW[ii];
+ b->height = _currentMenu->item[i].height;
+
+ b->data0Val1 = b->data1Val1 = b->data2Val1 = 0;
+ b->flags = (ii == 1) ? 0x6606 : 0x4406;
+
+ b->dimTableIndex = 0;
+
+ b->buttonCallback = _currentMenu->item[i].callback;
+ b->arg = _currentMenu->item[i].itemId;
+
+ _menuButtonList = addButtonToList(_menuButtonList, b);
+
+ processButton(b);
+ updateButton(b);
+ }
+
+ _currentMenu->item[i].labelX = _currentMenu->item[i].x - 5;
+ _currentMenu->item[i].labelY = _currentMenu->item[i].y + 3;
+
+ printMenuText(getMenuItemLabel(_currentMenu->item[i]), _currentMenu->x + _currentMenu->item[i].labelX, _currentMenu->y + _currentMenu->item[i].labelY, _currentMenu->item[i].textColor, 0, 10);
+
+ int volume = _vm->getVolume((KyraEngine_v1::kVolumeEntry)(i - 1));
+ _screen->drawShape(_screen->_curPage, _vm->_gameShapes[85], tX , tY, 0, 0x10);
+ _screen->drawShape(_screen->_curPage, _vm->_gameShapes[87], tX + 2 + oX[1], tY, 0, 0x10);
+ _screen->drawShape(_screen->_curPage, _vm->_gameShapes[86], tX + oX[1] + volume, tY, 0, 0x10);
+ }
+
+ _screen->updateScreen();
+ }
+
+ if (_currentMenu == &_mainMenu) {
+ Screen::FontId f = _screen->setFont(Screen::FID_6_FNT);
+ _screen->fprintString("%s", menu.x + 8, menu.y + menu.height - 12, 204, 0, 8, gScummVMVersion);
+ _screen->setFont(f);
+ _screen->updateScreen();
+ }
+
+ if (_currentMenu == &_savenameMenu) {
+ int mx = (d->sx << 3) - 1;
+ int my = d->sy - 1;
+ int mw = (d->w << 3) + 1;
+ int mh = d->h + 1;
+ _screen->drawShadedBox(mx, my, mx + mw, my + mh, 227, 223, Screen::kShadeTypeLol);
+ int pg = _screen->setCurPage(0);
+ _vm->_txt->clearDim(8);
+ textCursorTimer = 0;
+ textCursorStatus = 0;
+
+ fC = _screen->getTextWidth(_saveDescription);
+ while (fC >= fW) {
+ _saveDescription[strlen(_saveDescription) - 1] = 0;
+ fC = _screen->getTextWidth(_saveDescription);
+ }
+
+ _screen->fprintString(_saveDescription, (d->sx << 3), d->sy + 2, d->unk8, d->unkA, 0);
+ _screen->fillRect((d->sx << 3) + fC, d->sy, (d->sx << 3) + fC + wW, d->sy + d->h - 1, d->unk8, 0);
+ _screen->setCurPage(pg);
+ }
+
+ while (!_newMenu && _displayMenu) {
+ processHighlights(*_currentMenu);
+
+ if (_currentMenu == &_savenameMenu) {
+ if (textCursorTimer <= _vm->_system->getMillis()) {
+ fC = _screen->getTextWidth(_saveDescription);
+ textCursorStatus ^= 1;
+ textCursorTimer = _vm->_system->getMillis() + 20 * _vm->_tickLength;
+ _screen->fillRect((d->sx << 3) + fC, d->sy, (d->sx << 3) + fC + wW, d->sy + d->h - 1, textCursorStatus ? d->unk8 : d->unkA, 0);
+ _screen->updateScreen();
+ }
+ }
+
+ if (getInput()) {
+ if (!_newMenu)
+ _newMenu = (_currentMenu != &_audioOptions) ? _currentMenu : 0;
+ else
+ _lastMenu = _menuResult == -1 ? _lastMenu : _currentMenu;
+ }
+
+ if (!_menuResult)
+ _displayMenu = false;
+ }
+
+ if (_newMenu != _currentMenu || !_displayMenu)
+ restorePage0();
+
+ _currentMenu->highlightedItem = hasSpecialButtons;
+
+ if (_newMenu)
+ _currentMenu = _newMenu;
+
+ _newMenu = 0;
+ }
+
+ return _menuResult;
+}
+
+void GUI_LoL::createScreenThumbnail(Graphics::Surface &dst) {
+ uint8 *screenPal = new uint8[768];
+ _screen->getRealPalette(1, screenPal);
+ ::createThumbnail(&dst, _screen->getCPagePtr(7), Screen::SCREEN_W, Screen::SCREEN_H, screenPal);
+ delete[] screenPal;
+}
+
+void GUI_LoL::backupPage0() {
+ _screen->copyPage(0, 7);
+}
+
+void GUI_LoL::restorePage0() {
+ _screen->copyPage(7, 0);
+ _screen->updateScreen();
+}
+
+void GUI_LoL::setupSavegameNames(Menu &menu, int num) {
+ char *s = (char *)_vm->_tempBuffer5120;
+
+ for (int i = 0; i < num; ++i) {
+ menu.item[i].saveSlot = -1;
+ menu.item[i].enabled = false;
+ }
+
+ int startSlot = 0;
+ if (&menu == &_saveMenu && _savegameOffset == 0)
+ startSlot = 1;
+
+ KyraEngine_v1::SaveHeader header;
+ Common::InSaveFile *in;
+ for (int i = startSlot; i < num && uint(_savegameOffset + i) < _saveSlots.size(); ++i) {
+ if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset - startSlot]), header)) != 0) {
+ strncpy(s, header.description.c_str(), 80);
+ s[79] = 0;
+
+ Util::convertISOToDOS(s);
+
+ menu.item[i].itemString = s;
+ s += (strlen(s) + 1);
+ menu.item[i].saveSlot = _saveSlots[i + _savegameOffset];
+ menu.item[i].enabled = true;
+ delete in;
+ }
+ }
+
+ if (_savegameOffset == 0) {
+ if (&menu == &_saveMenu) {
+ strcpy(s, _vm->getLangString(0x4010));
+ menu.item[0].itemString = s;
+ menu.item[0].saveSlot = -3;
+ menu.item[0].enabled = true;
+ }
+ }
+}
+
+void GUI_LoL::printMenuText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 flags, Screen::FontId font) {
+ _screen->fprintString(str, x, y, c0, c1, flags);
+}
+
+int GUI_LoL::getMenuCenterStringX(const char *str, int x1, int x2) {
+ if (!str)
+ return 0;
+
+ int strWidth = _screen->getTextWidth(str);
+ int w = x2 - x1 + 1;
+ return x1 + (w - strWidth) / 2;
+}
+
+int GUI_LoL::getInput() {
+ if (!_displayMenu)
+ return 0;
+
+ Common::Point p = _vm->getMousePos();
+ _vm->_mouseX = p.x;
+ _vm->_mouseY = p.y;
+
+ if (_currentMenu == &_savenameMenu) {
+ _vm->updateInput();
+
+ for (Common::List<KyraEngine_v1::Event>::const_iterator evt = _vm->_eventList.begin(); evt != _vm->_eventList.end(); evt++) {
+ if (evt->event.type == Common::EVENT_KEYDOWN)
+ _keyPressed = evt->event.kbd;
+ }
+ }
+
+ int inputFlag = _vm->checkInput(_menuButtonList);
+
+ if (_currentMenu == &_savenameMenu && _keyPressed.ascii){
+ char inputKey = _keyPressed.ascii;
+ Util::convertISOToDOS(inputKey);
+
+ if ((uint8)inputKey > 31 && (uint8)inputKey < 226) {
+ _saveDescription[strlen(_saveDescription) + 1] = 0;
+ _saveDescription[strlen(_saveDescription)] = inputKey;
+ inputFlag |= 0x8000;
+ } else if (_keyPressed.keycode == Common::KEYCODE_BACKSPACE && strlen(_saveDescription)) {
+ _saveDescription[strlen(_saveDescription) - 1] = 0;
+ inputFlag |= 0x8000;
+ }
+ }
+
+ _vm->removeInputTop();
+ _keyPressed.reset();
+
+ if (_vm->shouldQuit())
+ _displayMenu = false;
+
+ _vm->delay(8);
+ return inputFlag & 0x8000 ? 1 : 0;
+}
+
+int GUI_LoL::clickedMainMenu(Button *button) {
+ updateMenuButton(button);
+ switch (button->arg) {
+ case 0x4001:
+ _savegameOffset = 0;
+ _newMenu = &_loadMenu;
+ break;
+ case 0x4002:
+ _savegameOffset = 0;
+ _newMenu = &_saveMenu;
+ break;
+ case 0x4003:
+ _savegameOffset = 0;
+ _newMenu = &_deleteMenu;
+ break;
+ case 0x4004:
+ _newMenu = &_gameOptions;
+ break;
+ case 0x42D9:
+ _newMenu = &_audioOptions;
+ break;
+ case 0x4006:
+ _choiceMenu.menuNameId = 0x400a;
+ _newMenu = &_choiceMenu;
+ break;
+ case 0x4005:
+ _displayMenu = false;
+ break;
+ }
+ return 1;
+}
+
+int GUI_LoL::clickedLoadMenu(Button *button) {
+ updateMenuButton(button);
+
+ if (button->arg == 0x4011) {
+ if (_currentMenu != _lastMenu)
+ _newMenu = _lastMenu;
+ else
+ _menuResult = 0;
+ return 1;
+ }
+
+ int16 s = (int16)button->arg;
+ _vm->_gameToLoad = _loadMenu.item[-s - 2].saveSlot;
+ _displayMenu = false;
+
+ return 1;
+}
+
+int GUI_LoL::clickedSaveMenu(Button *button) {
+ updateMenuButton(button);
+
+ if (button->arg == 0x4011) {
+ _newMenu = &_mainMenu;
+ return 1;
+ }
+
+ _newMenu = &_savenameMenu;
+ int16 s = (int16)button->arg;
+ _menuResult = _saveMenu.item[-s - 2].saveSlot + 1;
+ _saveDescription = (char*)_vm->_tempBuffer5120 + 1000;
+ _saveDescription[0] = 0;
+ if (_saveMenu.item[-s - 2].saveSlot != -3)
+ strcpy(_saveDescription, _saveMenu.item[-s - 2].itemString);
+
+ return 1;
+}
+
+int GUI_LoL::clickedDeleteMenu(Button *button) {
+ updateMenuButton(button);
+
+ if (button->arg == 0x4011) {
+ _newMenu = &_mainMenu;
+ return 1;
+ }
+
+ _choiceMenu.menuNameId = 0x400b;
+ _newMenu = &_choiceMenu;
+ int16 s = (int16)button->arg;
+ _menuResult = _deleteMenu.item[-s - 2].saveSlot + 1;
+
+ return 1;
+}
+
+int GUI_LoL::clickedOptionsMenu(Button *button) {
+ updateMenuButton(button);
+
+ switch (button->arg) {
+ case 0xfff7:
+ _vm->_monsterDifficulty = ++_vm->_monsterDifficulty % 3;
+ break;
+ case 0xfff6:
+ _vm->_smoothScrollingEnabled ^= true;
+ break;
+ case 0xfff5:
+ _vm->_floatingCursorsEnabled ^= true;
+ break;
+ case 0xfff4:
+ _vm->_lang = ++_vm->_lang % 3;
+ break;
+ case 0xfff3:
+ _vm->_configVoice ^= 1;
+ break;
+ case 0x4072:
+ char filename[13];
+ snprintf(filename, sizeof(filename), "LEVEL%02d.%s", _vm->_currentLevel, _vm->_languageExt[_vm->_lang]);
+ if (_vm->_levelLangFile)
+ delete[] _vm->_levelLangFile;
+ _vm->_levelLangFile = _vm->resource()->fileData(filename, 0);
+ snprintf(filename, sizeof(filename), "LANDS.%s", _vm->_languageExt[_vm->_lang]);
+ if (_vm->_landsFile)
+ delete[] _vm->_landsFile;
+ _vm->_landsFile = _vm->resource()->fileData(filename, 0);
+ _newMenu = _lastMenu;
+ break;
+ }
+
+ return 1;
+}
+
+int GUI_LoL::clickedAudioMenu(Button *button) {
+ updateMenuButton(button);
+
+ if (button->arg == 0x4072) {
+ _newMenu = _lastMenu;
+ return 1;
+ }
+
+ int tX = button->x;
+ const int oldVolume = _vm->getVolume((KyraEngine_v1::kVolumeEntry)(button->arg - 3));
+ int newVolume = oldVolume;
+
+ if (button->index == 0) {
+ newVolume -= 10;
+ tX += 10;
+ } else if (button->index == 1) {
+ newVolume = _vm->_mouseX - (tX + 7);
+ } else if (button->index == 2) {
+ newVolume += 10;
+ tX -= 114;
+ }
+
+ newVolume = CLIP(newVolume, 2, 102);
+
+ if (newVolume == oldVolume) {
+ _screen->updateScreen();
+ return 0;
+ }
+
+ _screen->drawShape(0, _vm->_gameShapes[87], tX + oldVolume, button->y, 0, 0x10);
+ // Temporary HACK
+ const int volumeDrawX = _vm->convertVolumeFromMixer(_vm->convertVolumeToMixer(newVolume));
+ _screen->drawShape(0, _vm->_gameShapes[86], tX + volumeDrawX, button->y, 0, 0x10);
+ _screen->updateScreen();
+
+ _vm->snd_stopSpeech(0);
+
+ _vm->setVolume((KyraEngine_v1::kVolumeEntry)(button->arg - 3), newVolume);
+
+ if (newVolume) {
+ if (button->arg == 4) {
+ _vm->snd_playSoundEffect(_sliderSfx, -1);
+ int16 vocIndex = (int16)READ_LE_UINT16(&_vm->_ingameSoundIndex[_sliderSfx * 2]);
+ do {
+ ++_sliderSfx;
+ if (_sliderSfx < 47)
+ _sliderSfx++;
+ if (vocIndex == 199)
+ _sliderSfx = 11;
+ vocIndex = (int16)READ_LE_UINT16(&_vm->_ingameSoundIndex[_sliderSfx * 2]);
+ if (vocIndex == -1)
+ continue;
+ if (!scumm_stricmp(_vm->_ingameSoundList[vocIndex], "EMPTY"))
+ continue;
+ break;
+ } while (1);
+ } else if (button->arg == 5) {
+ _vm->_lastSpeechId = -1;
+ _vm->snd_playCharacterSpeech(0x42e0, 0, 0);
+ }
+ }
+
+ return 1;
+}
+
+int GUI_LoL::clickedDeathMenu(Button *button) {
+ updateMenuButton(button);
+ if (button->arg == _deathMenu.item[0].itemId) {
+ _vm->quitGame();
+ } else if (button->arg == _deathMenu.item[1].itemId) {
+ _newMenu = &_loadMenu;
+ }
+ return 1;
+}
+
+int GUI_LoL::clickedSavenameMenu(Button *button) {
+ updateMenuButton(button);
+ if (button->arg == _savenameMenu.item[0].itemId) {
+
+ Util::convertDOSToISO(_saveDescription);
+
+ int slot = _menuResult == -2 ? getNextSavegameSlot() : _menuResult;
+ Graphics::Surface thumb;
+ createScreenThumbnail(thumb);
+ _vm->saveGameState(slot, _saveDescription, &thumb);
+ thumb.free();
+
+ _displayMenu = false;
+
+ } else if (button->arg == _savenameMenu.item[1].itemId) {
+ _newMenu = &_saveMenu;
+ }
+
+ return 1;
+}
+
+int GUI_LoL::clickedChoiceMenu(Button *button) {
+ updateMenuButton(button);
+ if (button->arg == _choiceMenu.item[0].itemId) {
+ if (_lastMenu == &_mainMenu) {
+ _vm->quitGame();
+ } else if (_lastMenu == &_deleteMenu) {
+ _vm->_saveFileMan->removeSavefile(_vm->getSavegameFilename(_menuResult - 1));
+ Common::Array<int>::iterator i = Common::find(_saveSlots.begin(), _saveSlots.end(), _menuResult);
+ while (i != _saveSlots.end()) {
+ ++i;
+ if (i == _saveSlots.end())
+ break;
+ // We are only renaming all savefiles until we get some slots missing
+ // Also not rename quicksave slot filenames
+ if (*(i-1) != *i || *i >= 990)
+ break;
+ Common::String oldName = _vm->getSavegameFilename(*i);
+ Common::String newName = _vm->getSavegameFilename(*i-1);
+ _vm->_saveFileMan->renameSavefile(oldName, newName);
+ }
+ _newMenu = &_mainMenu;
+ }
+ } else if (button->arg == _choiceMenu.item[1].itemId) {
+ _newMenu = &_mainMenu;
+ }
+ return 1;
+}
+
+int GUI_LoL::scrollUp(Button *button) {
+ updateButton(button);
+ if (_savegameOffset > 0) {
+ _savegameOffset--;
+ _newMenu = _currentMenu;
+ _menuResult = -1;
+ }
+ return 1;
+}
+
+int GUI_LoL::scrollDown(Button *button) {
+ updateButton(button);
+ if ((uint)_savegameOffset < _saveSlots.size() - 4) {
+ _savegameOffset++;
+ _newMenu = _currentMenu;
+ _menuResult = -1;
+ }
+ return 1;
+}
+
+const char *GUI_LoL::getMenuTitle(const Menu &menu) {
+ if (!menu.menuNameId)
+ return 0;
+ return _vm->getLangString(menu.menuNameId);
+}
+
+const char *GUI_LoL::getMenuItemTitle(const MenuItem &menuItem) {
+ if (menuItem.itemId & 0x8000 && menuItem.itemString)
+ return menuItem.itemString;
+ else if (menuItem.itemId & 0x8000 || !menuItem.itemId)
+ return 0;
+ return _vm->getLangString(menuItem.itemId);
+}
+
+const char *GUI_LoL::getMenuItemLabel(const MenuItem &menuItem) {
+ if (menuItem.labelId & 0x8000 && menuItem.labelString)
+ return menuItem.labelString;
+ else if (menuItem.labelId & 0x8000 || !menuItem.labelId)
+ return 0;
+ return _vm->getLangString(menuItem.labelId);
+}
+
} // end of namespace Kyra
#endif // ENABLE_LOL
diff --git a/engines/kyra/gui_lol.h b/engines/kyra/gui_lol.h
index 631e29bd3b..832199f23e 100644
--- a/engines/kyra/gui_lol.h
+++ b/engines/kyra/gui_lol.h
@@ -31,6 +31,50 @@
#include "kyra/gui.h"
namespace Kyra {
+#define GUI_LOL_MENU(menu, a, b, c, d, e, f, g, i) \
+ do { \
+ const ScreenDim *dim = _screen->getScreenDim(a); \
+ menu.x = (dim->sx << 3); \
+ menu.y = (dim->sy); \
+ menu.width = (dim->w << 3); \
+ menu.height = (dim->h); \
+ menu.bkgdColor = 225; \
+ menu.color1 = 223; \
+ menu.color2 = 227; \
+ menu.menuNameId = b; \
+ menu.highlightedItem = c; \
+ menu.numberOfItems = d; \
+ menu.titleX = (dim->sx << 3) + (dim->w << 2); \
+ menu.titleY = 6; \
+ menu.textColor = 254; \
+ menu.scrollUpButtonX = e; \
+ menu.scrollUpButtonY = f; \
+ menu.scrollDownButtonX = g; \
+ menu.scrollDownButtonY = i; \
+ } while (0)
+
+ #define GUI_LOL_MENU_ITEM(item, a, b, c, d, e, f, g) \
+ do { \
+ item.enabled = 1; \
+ item.itemId = a; \
+ item.itemString = 0; \
+ item.x = b; \
+ item.y = c; \
+ item.width = d; \
+ item.height = e; \
+ item.textColor = 204; \
+ item.highlightColor = 254; \
+ item.titleX = -1; \
+ item.bkgdColor = 225; \
+ item.color1 = 223; \
+ item.color2 = 227; \
+ item.saveSlot = 0; \
+ item.labelId = f; \
+ item.labelString = 0; \
+ item.labelX = 0; \
+ item.labelY = 0; \
+ item.keyCode = g; \
+ } while (0)
class LoLEngine;
class Screen_LoL;
@@ -40,14 +84,67 @@ class GUI_LoL : public GUI {
public:
GUI_LoL(LoLEngine *vm);
+ void initStaticData();
+
// button specific
void processButton(Button *button);
int processButtonList(Button *buttonList, uint16 inputFlags, int8 mouseWheel);
+ int redrawShadedButtonCallback(Button *button);
+ int redrawButtonCallback(Button *button);
+
+ int runMenu(Menu &menu);
+
// utilities for thumbnail creation
- void createScreenThumbnail(Graphics::Surface &dst) {}
+ void createScreenThumbnail(Graphics::Surface &dst);
private:
+ void backupPage0();
+ void restorePage0();
+
+ void setupSavegameNames(Menu &menu, int num);
+
+ void printMenuText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 flags, Screen::FontId font=Screen::FID_9_FNT);
+ int getMenuCenterStringX(const char *str, int x1, int x2);
+
+ int getInput();
+
+ int clickedMainMenu(Button *button);
+ int clickedLoadMenu(Button *button);
+ int clickedSaveMenu(Button *button);
+ int clickedDeleteMenu(Button *button);
+ int clickedOptionsMenu(Button *button);
+ int clickedAudioMenu(Button *button);
+ int clickedDeathMenu(Button *button);
+ int clickedSavenameMenu(Button *button);
+ int clickedChoiceMenu(Button *button);
+
+ int scrollUp(Button *button);
+ int scrollDown(Button *button);
+
+ Button *getButtonListData() { return _menuButtons; }
+ Button *getScrollUpButton() { return &_scrollUpButton; }
+ Button *getScrollDownButton() { return &_scrollDownButton; }
+
+
+ Button::Callback getScrollUpButtonHandler() const { return _scrollUpFunctor; }
+ Button::Callback getScrollDownButtonHandler() const { return _scrollDownFunctor; }
+
+ uint8 defaultColor1() const { return 0xFE; }
+ uint8 defaultColor2() const { return 0x00; }
+
+ const char *getMenuTitle(const Menu &menu);
+ const char *getMenuItemTitle(const MenuItem &menuItem);
+ const char *getMenuItemLabel(const MenuItem &menuItem);
+
+ Button _menuButtons[10];
+ Button _scrollUpButton;
+ Button _scrollDownButton;
+ Menu _mainMenu, _gameOptions, _audioOptions, _choiceMenu, _loadMenu, _saveMenu, _deleteMenu, _savenameMenu, _deathMenu;
+ Menu *_currentMenu, *_lastMenu, *_newMenu;
+ int _menuResult;
+ char *_saveDescription;
+
LoLEngine *_vm;
Screen_LoL *_screen;
@@ -59,24 +156,11 @@ private:
uint16 _flagsModifier;
uint8 _mouseClick;
- int scrollUp(Button *button) { return 0; }
- int scrollDown(Button *button) { return 0; }
-
- Button *getButtonListData() { return 0; }
- Button *getScrollUpButton() { return 0; }
- Button *getScrollDownButton() { return 0; }
+ int _savegameOffset;
+ int _sliderSfx;
Button::Callback _scrollUpFunctor;
Button::Callback _scrollDownFunctor;
- Button::Callback getScrollUpButtonHandler() const { return _scrollUpFunctor; }
- Button::Callback getScrollDownButtonHandler() const { return _scrollDownFunctor; }
-
- uint8 defaultColor1() const { return 0; }
- uint8 defaultColor2() const { return 0; }
-
- const char *getMenuTitle(const Menu &menu) { return 0; }
- const char *getMenuItemTitle(const MenuItem &menuItem) { return 0; }
- const char *getMenuItemLabel(const MenuItem &menuItem) { return 0; }
};
} // end of namespace Kyra
diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp
index c4d804c14d..e7001ed31f 100644
--- a/engines/kyra/gui_mr.cpp
+++ b/engines/kyra/gui_mr.cpp
@@ -352,10 +352,10 @@ void KyraEngine_MR::drawMalcolmsMoodPointer(int frame, int page) {
frame = 13;
if (page == 0) {
- _invWsa->displayFrame(frame, 0, 0, 0, 0);
+ _invWsa->displayFrame(frame, 0, 0, 0, 0, 0, 0);
_screen->updateScreen();
} else if (page == 30) {
- _invWsa->displayFrame(frame, 2, 0, -144, 0);
+ _invWsa->displayFrame(frame, 2, 0, -144, 0, 0, 0);
}
_invWsaFrame = frame;
@@ -674,21 +674,21 @@ void KyraEngine_MR::showAlbum() {
_screen->copyRegionToBuffer(0, 0, 0, 320, 200, _screenBuffer);
_screen->copyRegionToBuffer(4, 0, 0, 320, 200, _album.backUpPage);
- memcpy(_screen->getPalette(1), _screen->getPalette(0), 768);
+ _screen->copyPalette(1, 0);
_screen->fadeToBlack(9);
int itemInHand = _itemInHand;
removeHandItem();
- _res->loadFileToBuf("ALBUM.COL", _screen->getPalette(0), 768);
+ _screen->loadPalette("ALBUM.COL", _screen->getPalette(0));
loadAlbumPage();
loadAlbumPageWSA();
if (_album.leftPage.wsa->opened())
- _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000);
+ _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000, 0, 0);
if (_album.rightPage.wsa->opened())
- _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000);
+ _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000, 0, 0);
printAlbumPageText();
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
@@ -707,7 +707,7 @@ void KyraEngine_MR::showAlbum() {
_screen->copyBlockToPage(0, 0, 0, 320, 200, _screenBuffer);
_screen->copyBlockToPage(4, 0, 0, 320, 200, _album.backUpPage);
- memcpy(_screen->getPalette(0), _screen->getPalette(1), 768);
+ _screen->copyPalette(0, 1);
_screen->fadePalette(_screen->getPalette(0), 9);
delete[] _album.backUpRect;
@@ -843,10 +843,10 @@ void KyraEngine_MR::processAlbum() {
loadAlbumPageWSA();
if (_album.leftPage.wsa->opened())
- _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000);
+ _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000, 0, 0);
if (_album.rightPage.wsa->opened())
- _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000);
+ _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000, 0, 0);
printAlbumPageText();
@@ -899,7 +899,7 @@ void KyraEngine_MR::albumUpdateAnims() {
nextRun = _album.leftPage.timer + 5 * _tickLength;
if (nextRun < _system->getMillis() && _album.leftPage.wsa->opened()) {
- _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000);
+ _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000, 0, 0);
_screen->copyRegion(40, 17, 40, 17, 87, 73, 2, 0, Screen::CR_NO_P_CHECK);
++_album.leftPage.curFrame;
@@ -918,7 +918,7 @@ void KyraEngine_MR::albumUpdateAnims() {
nextRun = _album.rightPage.timer + 5 * _tickLength;
if (nextRun < _system->getMillis() && _album.rightPage.wsa->opened()) {
- _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000);
+ _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000, 0, 0);
_screen->copyRegion(194, 20, 194, 20, 85, 69, 2, 0, Screen::CR_NO_P_CHECK);
++_album.rightPage.curFrame;
@@ -936,13 +936,13 @@ void KyraEngine_MR::albumUpdateAnims() {
void KyraEngine_MR::albumAnim1() {
for (int i = 6; i >= 3; --i) {
albumRestoreRect();
- _album.wsa->displayFrame(i, 2, -100, 90, 0x4000);
+ _album.wsa->displayFrame(i, 2, -100, 90, 0x4000, 0, 0);
albumUpdateRect();
delayWithTicks(1);
}
albumRestoreRect();
- _album.wsa->displayFrame(14, 2, -100, 90, 0x4000);
+ _album.wsa->displayFrame(14, 2, -100, 90, 0x4000, 0, 0);
albumUpdateRect();
delayWithTicks(1);
}
@@ -950,7 +950,7 @@ void KyraEngine_MR::albumAnim1() {
void KyraEngine_MR::albumAnim2() {
for (int i = 3; i <= 6; ++i) {
albumRestoreRect();
- _album.wsa->displayFrame(i, 2, -100, 90, 0x4000);
+ _album.wsa->displayFrame(i, 2, -100, 90, 0x4000, 0, 0);
albumUpdateRect();
delayWithTicks(1);
}
@@ -1269,7 +1269,7 @@ int GUI_MR::optionsButton(Button *button) {
}
while (_displayMenu) {
- processHighlights(*_currentMenu, _vm->_mouseX, _vm->_mouseY);
+ processHighlights(*_currentMenu);
getInput();
}
@@ -1312,7 +1312,7 @@ int GUI_MR::loadMenu(Button *caller) {
_screen->updateScreen();
while (_isLoadMenu) {
- processHighlights(_loadMenu, _vm->_mouseX, _vm->_mouseY);
+ processHighlights(_loadMenu);
getInput();
}
@@ -1362,7 +1362,7 @@ int GUI_MR::gameOptions(Button *caller) {
_isOptionsMenu = true;
while (_isOptionsMenu) {
- processHighlights(_gameOptions, _vm->_mouseX, _vm->_mouseY);
+ processHighlights(_gameOptions);
getInput();
}
@@ -1525,7 +1525,7 @@ int GUI_MR::audioOptions(Button *caller) {
updateAllMenuButtons();
bool speechEnabled = _vm->speechEnabled();
while (_isOptionsMenu) {
- processHighlights(_audioOptions, _vm->_mouseX, _vm->_mouseY);
+ processHighlights(_audioOptions);
getInput();
}
@@ -1554,7 +1554,7 @@ int GUI_MR::sliderHandler(Button *caller) {
assert(button >= 0 && button <= 3);
- int oldVolume = _vm->getVolume(KyraEngine_v1::kVolumeEntry(button));
+ const int oldVolume = _vm->getVolume(KyraEngine_v1::kVolumeEntry(button));
int newVolume = oldVolume;
if (caller->index >= 24 && caller->index <= 27)
@@ -1564,8 +1564,7 @@ int GUI_MR::sliderHandler(Button *caller) {
else
newVolume = _vm->_mouseX - caller->x - 7;
- newVolume = MAX(2, newVolume);
- newVolume = MIN(97, newVolume);
+ newVolume = CLIP(newVolume, 2, 97);
if (newVolume == oldVolume)
return 0;
@@ -1621,8 +1620,7 @@ void GUI_MR::drawSliderBar(int slider, const uint8 *shape) {
int position = _vm->getVolume(KyraEngine_v1::kVolumeEntry(slider));
- position = MAX(2, position);
- position = MIN(97, position);
+ position = CLIP(position, 2, 97);
_screen->drawShape(0, shape, x+position, y, 0, 0);
}
diff --git a/engines/kyra/gui_v2.cpp b/engines/kyra/gui_v2.cpp
index 7e3d2b5afb..e5c8637fb5 100644
--- a/engines/kyra/gui_v2.cpp
+++ b/engines/kyra/gui_v2.cpp
@@ -27,6 +27,7 @@
#include "kyra/kyra_v2.h"
#include "kyra/screen_v2.h"
#include "kyra/text.h"
+#include "kyra/util.h"
#include "common/savefile.h"
@@ -158,8 +159,9 @@ int GUI_v2::processButtonList(Button *buttonList, uint16 inputFlag, int8 mouseWh
}
}
- int mouseX = _vm->_mouseX;
- int mouseY = _vm->_mouseY;
+ Common::Point p = _vm->getMousePos();
+ int mouseX = _vm->_mouseX = p.x;
+ int mouseY = _vm->_mouseY = p.y;
uint16 flags = 0;
@@ -454,8 +456,11 @@ void GUI_v2::setupSavegameNames(Menu &menu, int num) {
Common::InSaveFile *in;
for (int i = startSlot; i < num && uint(_savegameOffset + i) < _saveSlots.size(); ++i) {
if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset]), header)) != 0) {
- strncpy(getTableString(menu.item[i].itemId), header.description.c_str(), 80);
- getTableString(menu.item[i].itemId)[79] = 0;
+ char *s = getTableString(menu.item[i].itemId);
+ strncpy(s, header.description.c_str(), 80);
+ s[79] = 0;
+ Util::convertISOToDOS(s);
+
menu.item[i].saveSlot = _saveSlots[i + _savegameOffset];
menu.item[i].enabled = true;
delete in;
@@ -601,7 +606,7 @@ int GUI_v2::saveMenu(Button *caller) {
updateAllMenuButtons();
while (_isSaveMenu) {
- processHighlights(_saveMenu, _vm->_mouseX, _vm->_mouseY);
+ processHighlights(_saveMenu);
getInput();
}
@@ -620,6 +625,7 @@ int GUI_v2::saveMenu(Button *caller) {
Graphics::Surface thumb;
createScreenThumbnail(thumb);
+ Util::convertDOSToISO(_saveDescription);
_vm->saveGameState(_saveSlot, _saveDescription, &thumb);
thumb.free();
@@ -697,7 +703,7 @@ int GUI_v2::deleteMenu(Button *caller) {
updateAllMenuButtons();
while (_isDeleteMenu) {
- processHighlights(_saveMenu, _vm->_mouseX, _vm->_mouseY);
+ processHighlights(_saveMenu);
getInput();
}
@@ -749,7 +755,11 @@ const char *GUI_v2::nameInputProcess(char *buffer, int x, int y, uint8 c1, uint8
_cancelNameInput = _finishNameInput = false;
while (running && !_vm->shouldQuit()) {
checkTextfieldInput();
- processHighlights(_savenameMenu, _vm->_mouseX, _vm->_mouseY);
+ processHighlights(_savenameMenu);
+
+ char inputKey = _keyPressed.ascii;
+ Util::convertISOToDOS(inputKey);
+
if (_keyPressed.keycode == Common::KEYCODE_RETURN || _keyPressed.keycode == Common::KEYCODE_KP_ENTER || _finishNameInput) {
if (checkSavegameDescription(buffer, curPos)) {
buffer[curPos] = 0;
@@ -767,12 +777,12 @@ const char *GUI_v2::nameInputProcess(char *buffer, int x, int y, uint8 c1, uint8
drawTextfieldBlock(x2, y2, c3);
_screen->updateScreen();
_lastScreenUpdate = _vm->_system->getMillis();
- } else if (_keyPressed.ascii > 31 && _keyPressed.ascii < 127 && curPos < bufferSize) {
- if (x2 + getCharWidth(_keyPressed.ascii) + 7 < 0x11F) {
- buffer[curPos] = _keyPressed.ascii;
+ } else if ((uint8)inputKey > 31 && (uint8)inputKey < 226 && curPos < bufferSize) {
+ if (x2 + getCharWidth(inputKey) + 7 < 0x11F) {
+ buffer[curPos] = inputKey;
const char text[2] = { buffer[curPos], 0 };
_text->printText(text, x2, y2, c1, c2, c2);
- x2 += getCharWidth(_keyPressed.ascii);
+ x2 += getCharWidth(inputKey);
drawTextfieldBlock(x2, y2, c3);
++curPos;
_screen->updateScreen();
@@ -840,7 +850,7 @@ bool GUI_v2::choiceDialog(int name, bool type) {
_choice = false;
while (_isChoiceMenu) {
- processHighlights(_choiceMenu, _vm->_mouseX, _vm->_mouseY);
+ processHighlights(_choiceMenu);
getInput();
}
diff --git a/engines/kyra/gui_v2.h b/engines/kyra/gui_v2.h
index ec30640b88..9af4572e4d 100644
--- a/engines/kyra/gui_v2.h
+++ b/engines/kyra/gui_v2.h
@@ -96,7 +96,7 @@ namespace Kyra {
item.labelId = n; \
item.labelX = o; \
item.labelY = p; \
- item.unk1F = q; \
+ item.keyCode = q; \
} while (0)
class KyraEngine_v2;
diff --git a/engines/kyra/items_hof.cpp b/engines/kyra/items_hof.cpp
index 9d18829252..13e269f363 100644
--- a/engines/kyra/items_hof.cpp
+++ b/engines/kyra/items_hof.cpp
@@ -238,9 +238,7 @@ void KyraEngine_HoF::itemDropDown(int startX, int startY, int dstX, int dstY, in
_screen->drawShape(0, itemShape, curX, curY-16, 0, 0);
_screen->updateScreen();
- // XXX: original doesn't update game state while delaying
- // our implementation *could* do it, so maybe check this again
- delayUntil(endDelay);
+ delayUntil(endDelay, false, true);
}
if (dstX != dstY || (dstY - startY > 16)) {
@@ -275,9 +273,7 @@ void KyraEngine_HoF::itemDropDown(int startX, int startY, int dstX, int dstY, in
_screen->drawShape(0, itemShape, x, y, 0, 0);
_screen->updateScreen();
- // XXX: original doesn't update game state while delaying
- // our implementation *could* do it, so maybe check this again
- delayUntil(endDelay);
+ delayUntil(endDelay, false, true);
}
restoreGfxRect24x24(x, y);
diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp
index e75a13c870..c0ddd0c860 100644
--- a/engines/kyra/items_lol.cpp
+++ b/engines/kyra/items_lol.cpp
@@ -477,7 +477,7 @@ void LoLEngine::objectFlightProcessHits(FlyingObject *t, int x, int y, int objec
r = getNearestPartyMemberFromPos(x, y);
runItemScript(t->attackerId, t->item, 0x8000, r, 0);
}
- }
+ }
}
void LoLEngine::updateFlyingObject(FlyingObject *t) {
diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp
index c2c36dcc95..5c41989713 100644
--- a/engines/kyra/kyra_hof.cpp
+++ b/engines/kyra/kyra_hof.cpp
@@ -381,10 +381,10 @@ void KyraEngine_HoF::startup() {
memset(_sceneAnims, 0, sizeof(_sceneAnims));
for (int i = 0; i < ARRAYSIZE(_sceneAnimMovie); ++i)
- _sceneAnimMovie[i] = new WSAMovie_v2(this, _screen);
+ _sceneAnimMovie[i] = new WSAMovie_v2(this);
memset(_wsaSlots, 0, sizeof(_wsaSlots));
for (int i = 0; i < ARRAYSIZE(_wsaSlots); ++i)
- _wsaSlots[i] = new WSAMovie_v2(this, _screen);
+ _wsaSlots[i] = new WSAMovie_v2(this);
_screen->_curPage = 0;
@@ -415,7 +415,7 @@ void KyraEngine_HoF::startup() {
setupLangButtonShapes();
loadInventoryShapes();
- _res->loadFileToBuf("PALETTE.COL", _screen->_currentPalette, 0x300);
+ _screen->loadPalette("PALETTE.COL", _screen->getPalette(0));
_screen->loadBitmap("_PLAYFLD.CPS", 3, 3, 0);
_screen->copyPage(3, 0);
_screen->showMouse();
@@ -451,7 +451,6 @@ void KyraEngine_HoF::startup() {
(*_inventoryButtons[0].buttonCallback)(&_inventoryButtons[0]);
setNextIdleAnimTimer();
- //XXX
setWalkspeed(_configWalkspeed);
}
@@ -643,8 +642,6 @@ bool KyraEngine_HoF::handleInputUnkSub(int x, int y) {
while (_emc->isValid(&_sceneScriptState))
_emc->run(&_sceneScriptState);
- //XXXsys_unkKeyboad (flush? wait? whatever...)
-
if (queryGameFlag(0x1ED)) {
_sound->beginFadeOut();
_screen->fadeToBlack();
@@ -919,9 +916,9 @@ void KyraEngine_HoF::showMessage(const char *string, int16 palIndex) {
if (string) {
if (palIndex != -1 || _fadeMessagePalette) {
palIndex *= 3;
- memcpy(_messagePal, _screen->_currentPalette + palIndex, 3);
- memmove(_screen->_currentPalette + 765, _screen->_currentPalette + palIndex, 3);
- _screen->setScreenPalette(_screen->_currentPalette);
+ memcpy(_messagePal, _screen->getPalette(0).getData() + palIndex, 3);
+ _screen->getPalette(0).copy(_screen->getPalette(0), palIndex / 3, 1, 255);
+ _screen->setScreenPalette(_screen->getPalette(0));
}
int x = _text->getCenterStringX(string, 0, 320);
@@ -978,7 +975,7 @@ void KyraEngine_HoF::fadeMessagePalette() {
}
if (updatePalette) {
- memcpy(_screen->getPalette(0) + 765, _messagePal, 3);
+ _screen->getPalette(0).copy(_messagePal, 0, 1, 255);
_screen->setScreenPalette(_screen->getPalette(0));
} else {
_fadeMessagePalette = false;
@@ -1139,7 +1136,7 @@ void KyraEngine_HoF::updateCharPal(int unk1) {
if (palEntry != _charPalEntry && unk1) {
const uint8 *src = &_scenePal[(palEntry << 4) * 3];
- uint8 *ptr = _screen->getPalette(0) + 336;
+ uint8 *ptr = _screen->getPalette(0).getData() + 336;
for (int i = 0; i < 48; ++i) {
*ptr -= (*ptr - *src) >> 1;
++ptr;
@@ -1149,7 +1146,7 @@ void KyraEngine_HoF::updateCharPal(int unk1) {
unkVar1 = true;
_charPalEntry = palEntry;
} else if (unkVar1 || !unk1) {
- memcpy(_screen->getPalette(0) + 336, &_scenePal[(palEntry << 4) * 3], 48);
+ _screen->getPalette(0).copy(_scenePal, palEntry << 4, 16, 112);
_screen->setScreenPalette(_screen->getPalette(0));
unkVar1 = false;
}
@@ -1550,7 +1547,7 @@ void KyraEngine_HoF::loadInvWsa(const char *filename, int run_, int delayTime, i
wsaFlags |= 2;
if (!_invWsa.wsa)
- _invWsa.wsa = new WSAMovie_v2(this, _screen);
+ _invWsa.wsa = new WSAMovie_v2(this);
if (!_invWsa.wsa->open(filename, wsaFlags, 0))
error("Couldn't open inventory WSA file '%s'", filename);
@@ -1656,12 +1653,12 @@ void KyraEngine_HoF::displayInvWsaLastFrame() {
#pragma mark -
void KyraEngine_HoF::setCauldronState(uint8 state, bool paletteFade) {
- memcpy(_screen->getPalette(2), _screen->getPalette(0), 768);
+ _screen->copyPalette(2, 0);
Common::SeekableReadStream *file = _res->createReadStream("_POTIONS.PAL");
if (!file)
error("Couldn't load cauldron palette");
file->seek(state*18, SEEK_SET);
- file->read(_screen->getPalette(2)+723, 18);
+ _screen->getPalette(0).loadVGAPalette(*file, 241, 6);
delete file;
file = 0;
@@ -1673,7 +1670,7 @@ void KyraEngine_HoF::setCauldronState(uint8 state, bool paletteFade) {
_screen->updateScreen();
}
- memcpy(_screen->getPalette(0)+723, _screen->getPalette(2)+723, 18);
+ _screen->getPalette(0).copy(_screen->getPalette(2), 241, 6);
_cauldronState = state;
_cauldronUseCount = 0;
//if (state == 5)
@@ -1833,11 +1830,11 @@ void KyraEngine_HoF::cauldronRndPaletteFade() {
if (!file)
error("Couldn't load cauldron palette");
file->seek(index*18, SEEK_SET);
- file->read(_screen->getPalette(0)+723, 18);
+ _screen->getPalette(0).loadVGAPalette(*file, 241, 6);
snd_playSoundEffect(0x6A);
_screen->fadePalette(_screen->getPalette(0), 0x1E, &_updateFunctor);
file->seek(0, SEEK_SET);
- file->read(_screen->getPalette(0)+723, 18);
+ _screen->getPalette(0).loadVGAPalette(*file, 241, 6);
delete file;
_screen->fadePalette(_screen->getPalette(0), 0x1E, &_updateFunctor);
}
diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp
index fcd35e7282..e5ca52abcc 100644
--- a/engines/kyra/kyra_lok.cpp
+++ b/engines/kyra/kyra_lok.cpp
@@ -157,7 +157,10 @@ KyraEngine_LoK::~KyraEngine_LoK() {
}
Common::Error KyraEngine_LoK::init() {
- _screen = new Screen_LoK(this, _system);
+ if (_flags.platform == Common::kPlatformPC98 && _flags.useHiResOverlay && ConfMan.getBool("16_color"))
+ _screen = new Screen_LoK_16(this, _system);
+ else
+ _screen = new Screen_LoK(this, _system);
assert(_screen);
_screen->setResolution();
@@ -358,7 +361,7 @@ void KyraEngine_LoK::startup() {
loadButtonShapes();
initMainButtonList();
loadMainScreen();
- _screen->loadPalette("PALETTE.COL", _screen->_currentPalette);
+ _screen->loadPalette("PALETTE.COL", _screen->getPalette(0));
// XXX
_animator->initAnimStateList();
@@ -906,6 +909,9 @@ void KyraEngine_LoK::registerDefaultSettings() {
// Most settings already have sensible defaults. This one, however, is
// specific to the Kyra engine.
ConfMan.registerDefault("walkspeed", 2);
+
+ if (_flags.platform == Common::kPlatformPC98 && _flags.useHiResOverlay)
+ ConfMan.registerDefault("16_color", false);
}
void KyraEngine_LoK::readSettings() {
diff --git a/engines/kyra/kyra_lok.h b/engines/kyra/kyra_lok.h
index a0f38c3acc..a905c5521b 100644
--- a/engines/kyra/kyra_lok.h
+++ b/engines/kyra/kyra_lok.h
@@ -113,7 +113,6 @@ public:
KyraEngine_LoK(OSystem *system, const GameFlags &flags);
~KyraEngine_LoK();
- //TODO: proper extended implementation of KyraEngine_v1::pauseEngineIntern.
// _sprites and _seqplayer should be paused here too, to avoid some animation glitches,
// also parts of the hardcoded Malcolm fight might need some special handling.
diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp
index f2ea0c91df..871edd578d 100644
--- a/engines/kyra/kyra_mr.cpp
+++ b/engines/kyra/kyra_mr.cpp
@@ -230,7 +230,7 @@ Common::Error KyraEngine_MR::init() {
_screen->setAnimBlockPtr(3500);
_screen->setScreenDim(0);
- _res->loadFileToBuf("PALETTE.COL", _screen->getPalette(0), 768);
+ _screen->loadPalette("PALETTE.COL", _screen->getPalette(0));
_screen->setScreenPalette(_screen->getPalette(0));
return Common::kNoError;
@@ -269,19 +269,18 @@ Common::Error KyraEngine_MR::go() {
_screen->setScreenPalette(_screen->getPalette(0));
- // XXX
playMenuAudioFile();
for (int i = 0; i < 64 && !shouldQuit(); ++i) {
uint32 nextRun = _system->getMillis() + 3 * _tickLength;
- _menuAnim->displayFrame(i, 0, 0, 0, 0);
+ _menuAnim->displayFrame(i, 0, 0, 0, 0, 0, 0);
_screen->updateScreen();
delayUntil(nextRun);
}
for (int i = 64; i > 29 && !shouldQuit(); --i) {
uint32 nextRun = _system->getMillis() + 3 * _tickLength;
- _menuAnim->displayFrame(i, 0, 0, 0, 0);
+ _menuAnim->displayFrame(i, 0, 0, 0, 0, 0, 0);
_screen->updateScreen();
delayUntil(nextRun);
}
@@ -327,9 +326,9 @@ Common::Error KyraEngine_MR::go() {
}
void KyraEngine_MR::initMainMenu() {
- _menuAnim = new WSAMovie_v2(this, _screen);
- _menuAnim->open("REVENGE.WSA", 1, _screen->getPalette(0));
- memset(_screen->getPalette(0), 0, 3);
+ _menuAnim = new WSAMovie_v2(this);
+ _menuAnim->open("REVENGE.WSA", 1, &_screen->getPalette(0));
+ _screen->getPalette(0).fill(0, 1, 0);
_menu = new MainMenu(this);
MainMenu::StaticData data = {
@@ -378,7 +377,7 @@ void KyraEngine_MR::playVQA(const char *name) {
}
_screen->hideMouse();
- memcpy(_screen->getPalette(1), _screen->getPalette(0), 768);
+ _screen->copyPalette(1, 0);
fadeOutMusic(60);
_screen->fadeToBlack(60);
_screen->clearPage(0);
@@ -390,12 +389,11 @@ void KyraEngine_MR::playVQA(const char *name) {
_soundDigital->stopAllSounds();
_screen->showMouse();
- uint8 pal[768];
// Taken from original, it used '1' here too
- memset(pal, 1, sizeof(pal));
- _screen->setScreenPalette(pal);
+ _screen->getPalette(0).fill(0, 256, 1);
+ _screen->setScreenPalette(_screen->getPalette(0));
_screen->clearPage(0);
- memcpy(_screen->getPalette(0), _screen->getPalette(1), 768);
+ _screen->copyPalette(0, 1);
_wasPlayingVQA = true;
}
}
@@ -541,11 +539,11 @@ void KyraEngine_MR::initMouseShapes() {
}
void KyraEngine_MR::startup() {
- _album.wsa = new WSAMovie_v2(this, _screen);
+ _album.wsa = new WSAMovie_v2(this);
assert(_album.wsa);
- _album.leftPage.wsa = new WSAMovie_v2(this, _screen);
+ _album.leftPage.wsa = new WSAMovie_v2(this);
assert(_album.leftPage.wsa);
- _album.rightPage.wsa = new WSAMovie_v2(this, _screen);
+ _album.rightPage.wsa = new WSAMovie_v2(this);
assert(_album.rightPage.wsa);
musicUpdate(0);
@@ -559,9 +557,7 @@ void KyraEngine_MR::startup() {
_screen->setFont(Screen::FID_6_FNT);
_stringBuffer = new char[500];
- //XXX
musicUpdate(0);
- //XXX
allocAnimObjects(1, 16, 50);
musicUpdate(0);
@@ -586,19 +582,16 @@ void KyraEngine_MR::startup() {
error("couldn't load _ACTOR");
musicUpdate(0);
- //XXX
- musicUpdate(0);
openTalkFile(0);
musicUpdate(0);
_currentTalkFile = 0;
openTalkFile(1);
- //XXX
loadCostPal();
musicUpdate(0);
for (int i = 0; i < 16; ++i) {
_sceneAnims[i].flags = 0;
- _sceneAnimMovie[i] = new WSAMovie_v2(this, _screen);
+ _sceneAnimMovie[i] = new WSAMovie_v2(this);
assert(_sceneAnimMovie[i]);
}
@@ -627,7 +620,7 @@ void KyraEngine_MR::startup() {
loadInterfaceShapes();
musicUpdate(0);
- _res->loadFileToBuf("PALETTE.COL", _screen->getPalette(0), 768);
+ _screen->loadPalette("PALETTE.COL", _screen->getPalette(0));
_paletteOverlay = new uint8[256];
_screen->generateOverlay(_screen->getPalette(0), _paletteOverlay, 0xF0, 0x19);
@@ -655,7 +648,7 @@ void KyraEngine_MR::startup() {
musicUpdate(0);
runStartupScript(1, 0);
_res->exists("MOODOMTR.WSA", true);
- _invWsa = new WSAMovie_v2(this, _screen);
+ _invWsa = new WSAMovie_v2(this);
assert(_invWsa);
_invWsa->open("MOODOMTR.WSA", 1, 0);
_invWsaFrame = 6;
@@ -899,40 +892,30 @@ void KyraEngine_MR::updateCharAnimFrame(int character, int *table) {
void KyraEngine_MR::updateCharPal(int unk1) {
int layer = _screen->getLayer(_mainCharacter.x1, _mainCharacter.y1) - 1;
const uint8 *src = _costPalBuffer + _characterShapeFile * 72;
- uint8 *dst = _screen->getPalette(0) + 432;
+ Palette &dst = _screen->getPalette(0);
const int8 *sceneDatPal = &_sceneDatPalette[layer * 3];
if (layer != _lastCharPalLayer && unk1) {
- for (int i = 0, j = 0; i < 72; ++i) {
- uint8 col = *dst;
- int8 addCol = *src + *sceneDatPal;
- addCol = MAX<int8>(0, MIN<int8>(addCol, 63));
- addCol = (col - addCol) >> 1;
- *dst -= addCol;
- ++dst;
- ++src;
- ++sceneDatPal;
- ++j;
- if (j > 3) {
- sceneDatPal = &_sceneDatPalette[layer * 3];
- j = 0;
+ for (int i = 144; i < 168; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ uint8 col = dst[i * 3 + j];
+ int subCol = src[(i - 144) * 3 + j] + sceneDatPal[j];
+ subCol = CLIP(subCol, 0, 63);
+ subCol = (col - subCol) / 2;
+ dst[i * 3 + j] -= subCol;
}
}
+
_charPalUpdate = true;
_screen->setScreenPalette(_screen->getPalette(0));
_lastCharPalLayer = layer;
} else if (_charPalUpdate || !unk1) {
- memcpy(dst, src, 72);
-
- for (int i = 0, j = 0; i < 72; ++i) {
- uint8 col = *dst + *sceneDatPal;
- *dst = MAX<int8>(0, MIN<int8>(col, 63));
- ++dst;
- ++sceneDatPal;
- ++j;
- if (j >= 3) {
- sceneDatPal = &_sceneDatPalette[layer * 3];
- j = 0;
+ dst.copy(_costPalBuffer, _characterShapeFile * 24, 24, 144);
+
+ for (int i = 144; i < 168; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ int col = dst[i * 3 + j] + sceneDatPal[j];
+ dst[i * 3 + j] = CLIP(col, 0, 63);
}
}
diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h
index 6c06a84433..88bfb8c89b 100644
--- a/engines/kyra/kyra_mr.h
+++ b/engines/kyra/kyra_mr.h
@@ -50,7 +50,6 @@ public:
KyraEngine_MR(OSystem *system, const GameFlags &flags);
~KyraEngine_MR();
- //TODO: proper extended implementation of KyraEngine_v2::pauseEngineIntern.
// Idle animation time, item animations and album animations should be taken
// care of, but since those would just produce minor glitches it's not that
// important.
diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp
index d9fc8f9d66..80872877d5 100644
--- a/engines/kyra/kyra_v1.cpp
+++ b/engines/kyra/kyra_v1.cpp
@@ -81,7 +81,7 @@ KyraEngine_v1::KyraEngine_v1(OSystem *system, const GameFlags &flags)
Common::addDebugChannel(kDebugLevelMovie, "Movie", "Movie debug level");
Common::addDebugChannel(kDebugLevelTimer, "Timer", "Timer debug level");
- system->getEventManager()->registerRandomSource(_rnd, "kyra");
+ _eventMan->registerRandomSource(_rnd, "kyra");
}
::GUI::Debugger *KyraEngine_v1::getDebugger() {
@@ -94,8 +94,6 @@ void KyraEngine_v1::pauseEngineIntern(bool pause) {
}
Common::Error KyraEngine_v1::init() {
- registerDefaultSettings();
-
// Setup mixer
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
@@ -278,10 +276,10 @@ int KyraEngine_v1::checkInput(Button *buttonList, bool mainLoop, int eventFlag)
} else {
switch(event.kbd.keycode) {
case Common::KEYCODE_SPACE:
- keys = 43;
+ keys = 61;
break;
case Common::KEYCODE_RETURN:
- keys = 61;
+ keys = 43;
break;
case Common::KEYCODE_UP:
case Common::KEYCODE_KP8:
@@ -594,27 +592,27 @@ bool KyraEngine_v1::textEnabled() {
return !_flags.isTalkie || (_configVoice == 0 || _configVoice == 2);
}
-inline int convertValueToMixer(int value) {
+int KyraEngine_v1::convertVolumeToMixer(int value) {
value -= 2;
return (value * Audio::Mixer::kMaxMixerVolume) / 95;
}
-inline int convertValueFromMixer(int value) {
+int KyraEngine_v1::convertVolumeFromMixer(int value) {
return (value * 95) / Audio::Mixer::kMaxMixerVolume + 2;
}
void KyraEngine_v1::setVolume(kVolumeEntry vol, uint8 value) {
switch (vol) {
case kVolumeMusic:
- ConfMan.setInt("music_volume", convertValueToMixer(value));
+ ConfMan.setInt("music_volume", convertVolumeToMixer(value));
break;
case kVolumeSfx:
- ConfMan.setInt("sfx_volume", convertValueToMixer(value));
+ ConfMan.setInt("sfx_volume", convertVolumeToMixer(value));
break;
case kVolumeSpeech:
- ConfMan.setInt("speech_volume", convertValueToMixer(value));
+ ConfMan.setInt("speech_volume", convertVolumeToMixer(value));
break;
}
@@ -629,16 +627,16 @@ void KyraEngine_v1::setVolume(kVolumeEntry vol, uint8 value) {
uint8 KyraEngine_v1::getVolume(kVolumeEntry vol) {
switch (vol) {
case kVolumeMusic:
- return convertValueFromMixer(ConfMan.getInt("music_volume"));
+ return convertVolumeFromMixer(ConfMan.getInt("music_volume"));
break;
case kVolumeSfx:
- return convertValueFromMixer(ConfMan.getInt("sfx_volume"));
+ return convertVolumeFromMixer(ConfMan.getInt("sfx_volume"));
break;
case kVolumeSpeech:
if (speechEnabled())
- return convertValueFromMixer(ConfMan.getInt("speech_volume"));
+ return convertVolumeFromMixer(ConfMan.getInt("speech_volume"));
else
return 2;
break;
diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h
index b45f21dd89..5ece70e3f1 100644
--- a/engines/kyra/kyra_v1.h
+++ b/engines/kyra/kyra_v1.h
@@ -153,7 +153,7 @@ public:
kVolumeSpeech = 2
};
- // volume reaches from 2 to 97
+ // volume reaches per default from 2 to 97
void setVolume(kVolumeEntry vol, uint8 value);
uint8 getVolume(kVolumeEntry vol);
@@ -181,13 +181,16 @@ protected:
// Engine APIs
virtual Common::Error init();
virtual Common::Error go() = 0;
+
virtual Common::Error run() {
Common::Error err;
+ registerDefaultSettings();
err = init();
if (err != Common::kNoError)
return err;
return go();
}
+
virtual ::GUI::Debugger *getDebugger();
virtual bool hasFeature(EngineFeature f) const;
virtual void pauseEngineIntern(bool pause);
@@ -289,6 +292,9 @@ protected:
const int8 *_trackMap;
int _trackMapSize;
+ virtual int convertVolumeToMixer(int value);
+ virtual int convertVolumeFromMixer(int value);
+
// pathfinder
virtual int findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize);
int findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end);
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index 3461fa5da9..020e1ea3ea 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -82,7 +82,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_curTlkFile = -1;
_lastSpeaker = _lastSpeechId = _nextSpeechId = _nextSpeaker = -1;
- memset(_moneyColumnHeight, 0, 5);
+ memset(_moneyColumnHeight, 0, sizeof(_moneyColumnHeight));
_credits = 0;
_itemsInPlay = 0;
@@ -200,7 +200,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_partyPosX = _partyPosY = 0;
_shpDmX = _shpDmY = _dmScaleW = _dmScaleH = 0;
- _floatingMouseArrowControl = 0;
+ _floatingCursorControl = _currentFloatingCursor = 0;
memset(_activeTim, 0, sizeof(_activeTim));
memset(_openDoorState, 0, sizeof(_openDoorState));
@@ -222,10 +222,6 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_preserveEvents = false;
_buttonList1 = _buttonList2 = _buttonList3 = _buttonList4 = _buttonList5 = _buttonList6 = _buttonList7 = _buttonList8 = 0;
- _monsterDifficulty = 1;
- _smoothScrollingEnabled = true;
- _floatingCursorsEnabled = false;
-
memset(_lvlTempData, 0, sizeof(_lvlTempData));
_mapOverlay = 0;
@@ -436,6 +432,7 @@ Common::Error LoLEngine::init() {
_gui = new GUI_LoL(this);
assert(_gui);
+ _gui->initStaticData();
_txt = new TextDisplayer_LoL(this, _screen);
@@ -456,8 +453,6 @@ Common::Error LoLEngine::init() {
if (!_sound->init())
error("Couldn't init sound");
- _speechFlag = speechEnabled() ? 0x48 : 0;
-
_wllVmpMap = new uint8[80];
memset(_wllVmpMap, 0, 80);
_wllShapeMap = new int8[80];
@@ -561,7 +556,7 @@ Common::Error LoLEngine::go() {
// Usually fonts etc. would be setup by the prologue code, if we skip
// the prologue code we need to setup them manually here.
- if (_gameToLoad != -1) {
+ if (_gameToLoad != -1 && action != 3) {
preInit();
_screen->setFont(Screen::FID_9_FNT);
}
@@ -591,8 +586,6 @@ Common::Error LoLEngine::go() {
if (loadGameState(_gameToLoad) != Common::kNoError)
error("Couldn't load game slot %d on startup", _gameToLoad);
_gameToLoad = -1;
- } else if (action == 3) {
- // XXX
}
_screen->_fadeFlag = 3;
@@ -639,6 +632,15 @@ void LoLEngine::loadItemIconShapes() {
_itemIconShapes[i] = _screen->makeShapeCopy(shp, i);
_screen->setMouseCursor(0, 0, _itemIconShapes[0]);
+
+ if (!_gameShapes) {
+ _screen->loadBitmap("GAMESHP.SHP", 3, 3, 0);
+ shp = _screen->getCPagePtr(3);
+ _numGameShapes = READ_LE_UINT16(shp);
+ _gameShapes = new uint8*[_numGameShapes];
+ for (int i = 0; i < _numGameShapes; i++)
+ _gameShapes[i] = _screen->makeShapeCopy(shp, i);
+ }
}
void LoLEngine::setMouseCursorToIcon(int icon) {
@@ -661,6 +663,53 @@ bool LoLEngine::posWithinRect(int mouseX, int mouseY, int x1, int y1, int x2, in
return true;
}
+void LoLEngine::checkFloatingPointerRegions() {
+ if (!_floatingCursorsEnabled)
+ return;
+
+ int t = -1;
+
+ Common::Point p = getMousePos();
+
+ if (!(_updateFlags & 4) & !_floatingCursorControl) {
+ if (posWithinRect(p.x, p.y, 96, 0, 303, 136)) {
+ if (!posWithinRect(p.x, p.y, 128, 16, 271, 119)) {
+ if (posWithinRect(p.x, p.y, 112, 0, 287, 15))
+ t = 0;
+ if (posWithinRect(p.x, p.y, 272, 88, 303, 319))
+ t = 1;
+ if (posWithinRect(p.x, p.y, 112, 110, 287, 135))
+ t = 2;
+ if (posWithinRect(p.x, p.y, 96, 88, 127, 119))
+ t = 3;
+ if (posWithinRect(p.x, p.y, 96, 16, 127, 87))
+ t = 4;
+ if (posWithinRect(p.x, p.y, 272, 16, 303, 87))
+ t = 5;
+
+ if (t < 4) {
+ int d = (_currentDirection + t) & 3;
+ if (!checkBlockPassability(calcNewBlockPosition(_currentBlock, d), d))
+ t = 6;
+ }
+ }
+ }
+ }
+
+ if (t == _currentFloatingCursor)
+ return;
+
+ if (t == -1) {
+ setMouseCursorToItemInHand();
+ } else {
+ static const uint8 floatingPtrX[] = { 7, 13, 7, 0, 0, 15, 7 };
+ static const uint8 floatingPtrY[] = { 0, 7, 12, 7, 6, 6, 7 };
+ _screen->setMouseCursor(floatingPtrX[t], floatingPtrY[t], _gameShapes[10 + t]);
+ }
+
+ _currentFloatingCursor = t;
+}
+
uint8 *LoLEngine::getItemIconShapePtr(int index) {
int ix = _itemProperties[_itemsInPlay[index].itemPropertyIndex].shpIndex;
if (_itemProperties[_itemsInPlay[index].itemPropertyIndex].flags & 0x200)
@@ -714,7 +763,7 @@ int LoLEngine::mainMenu() {
assert(menu);
menu->init(data[dataIndex], MainMenu::Animation());
- int selection = menu->handle(_flags.isTalkie ? (hasSave ? 17 : 6) : (hasSave ? 6 : 18));
+ int selection = menu->handle(_flags.isTalkie ? (hasSave ? 19 : 6) : (hasSave ? 6 : 20));
delete menu;
_screen->setScreenDim(0);
@@ -729,20 +778,20 @@ int LoLEngine::mainMenu() {
void LoLEngine::startup() {
_screen->clearPage(0);
- _screen->loadBitmap("PLAYFLD.CPS", 3, 3, _screen->_currentPalette);
- uint8 *tmpPal = new uint8[0x300];
- memcpy(tmpPal, _screen->_currentPalette, 0x300);
- memset(_screen->_currentPalette, 0x3f, 0x180);
- memcpy(_screen->_currentPalette + 3, tmpPal + 3, 3);
- memset(_screen->_currentPalette + 0x240, 0x3f, 12);
- _screen->generateOverlay(_screen->_currentPalette, _screen->_paletteOverlay1, 1, 96);
- _screen->generateOverlay(_screen->_currentPalette, _screen->_paletteOverlay2, 144, 65);
- memcpy(_screen->_currentPalette, tmpPal, 0x300);
- delete[] tmpPal;
+ Palette &pal = _screen->getPalette(0);
+ _screen->loadBitmap("PLAYFLD.CPS", 3, 3, &pal);
- memset(_screen->getPalette(1), 0, 0x300);
- memset(_screen->getPalette(2), 0, 0x300);
+ _screen->copyPalette(1, 0);
+ pal.fill(0, 1, 0x3F);
+ pal.fill(2, 126, 0x3F);
+ pal.fill(192, 4, 0x3F);
+ _screen->generateOverlay(pal, _screen->_paletteOverlay1, 1, 96);
+ _screen->generateOverlay(pal, _screen->_paletteOverlay2, 144, 65);
+ _screen->copyPalette(0, 1);
+
+ _screen->getPalette(1).clear();
+ _screen->getPalette(2).clear();
loadItemIconShapes();
_screen->setMouseCursor(0, 0, _itemIconShapes[0x85]);
@@ -754,13 +803,6 @@ void LoLEngine::startup() {
for (int i = 0; i < _numItemShapes; i++)
_itemShapes[i] = _screen->makeShapeCopy(shp, i);
- _screen->loadBitmap("GAMESHP.SHP", 3, 3, 0);
- shp = _screen->getCPagePtr(3);
- _numGameShapes = READ_LE_UINT16(shp);
- _gameShapes = new uint8*[_numGameShapes];
- for (int i = 0; i < _numGameShapes; i++)
- _gameShapes[i] = _screen->makeShapeCopy(shp, i);
-
_screen->loadBitmap("THROWN.SHP", 3, 3, 0);
shp = _screen->getCPagePtr(3);
_numThrownShapes = READ_LE_UINT16(shp);
@@ -808,9 +850,6 @@ void LoLEngine::startup() {
_loadSuppFilesFlag = 1;
- _txt->setAnimParameters("<MORE>", 10, 31, 0);
- _txt->setAnimFlag(true);
-
_sound->loadSfxFile("LORESFX");
setMouseCursorToItemInHand();
@@ -822,12 +861,6 @@ void LoLEngine::startupNew() {
_compassDirection = _compassDirectionIndex = -1;
_lastMouseRegion = -1;
-
- /*
- _unk5 = 1;
- _unk6 = 1;
- _unk7 = 1
- _unk8 = 1*/
_currentLevel = 1;
giveCredits(41, 0);
@@ -858,6 +891,12 @@ void LoLEngine::runLoop() {
_flagsTable[73] |= 0x08;
while (!shouldQuit() && _runFlag) {
+ if (_gameToLoad != -1) {
+ if (loadGameState(_gameToLoad) != Common::kNoError)
+ error("Couldn't load game slot %d", _gameToLoad);
+ _gameToLoad = -1;
+ }
+
if (_nextScriptFunc) {
runLevelScript(_nextScriptFunc, 2);
_nextScriptFunc = 0;
@@ -865,7 +904,7 @@ void LoLEngine::runLoop() {
_timer->update();
- //checkFloatingPointerRegions();
+ checkFloatingPointerRegions();
gui_updateInput();
update();
@@ -884,6 +923,55 @@ void LoLEngine::runLoop() {
}
}
+void LoLEngine::registerDefaultSettings() {
+ KyraEngine_v1::registerDefaultSettings();
+
+ // Most settings already have sensible defaults. This one, however, is
+ // specific to the LoL engine.
+ ConfMan.registerDefault("floating_cursors", false);
+ ConfMan.registerDefault("smooth_scrolling", true);
+ ConfMan.registerDefault("monster_difficulty", 1);
+}
+
+void LoLEngine::writeSettings() {
+ ConfMan.setInt("monster_difficulty", _monsterDifficulty);
+ ConfMan.setBool("floating_cursors", _floatingCursorsEnabled);
+ ConfMan.setBool("smooth_scrolling", _smoothScrollingEnabled);
+
+ switch (_lang) {
+ case 1:
+ _flags.lang = Common::FR_FRA;
+ break;
+
+ case 2:
+ _flags.lang = Common::DE_DEU;
+ break;
+
+ case 3:
+ _flags.lang = Common::JA_JPN;
+ break;
+
+ case 0:
+ default:
+ _flags.lang = Common::EN_ANY;
+ }
+
+ if (_flags.lang == _flags.replacedLang && _flags.fanLang != Common::UNK_LANG)
+ _flags.lang = _flags.fanLang;
+
+ ConfMan.set("language", Common::getLanguageCode(_flags.lang));
+
+ KyraEngine_v1::writeSettings();
+}
+
+void LoLEngine::readSettings() {
+ _monsterDifficulty = ConfMan.getInt("monster_difficulty");
+ _smoothScrollingEnabled = ConfMan.getBool("smooth_scrolling");
+ _floatingCursorsEnabled = ConfMan.getBool("floating_cursors");
+
+ KyraEngine_v1::readSettings();
+}
+
void LoLEngine::update() {
updateSequenceBackgroundAnimations();
@@ -1095,7 +1183,7 @@ void LoLEngine::updatePortraitSpeechAnim() {
f -= 5;
f += 7;
- if (_speechFlag) {
+ if (speechEnabled()) {
if (snd_updateCharacterSpeech() == 2)
_updatePortraitSpeechAnimDuration = 2;
else
@@ -1233,7 +1321,7 @@ void LoLEngine::setCharacterMagicOrHitPoints(int charNum, int type, int points,
if (charNum > 3)
return;
-
+
LoLCharacter *c = &_characters[charNum];
if (!(c->flags & 1))
return;
@@ -1421,7 +1509,7 @@ void LoLEngine::gui_specialSceneSuspendControls(int controlMode) {
_specialSceneFlag = 1;
_currentControlMode = controlMode;
calcCharPortraitXpos();
- //checkMouseRegions();
+ checkFloatingPointerRegions();
}
void LoLEngine::gui_specialSceneRestoreControls(int restoreLamp) {
@@ -1431,7 +1519,7 @@ void LoLEngine::gui_specialSceneRestoreControls(int restoreLamp) {
}
_updateFlags &= 0xfffe;
_specialSceneFlag = 0;
- //checkMouseRegions();
+ checkFloatingPointerRegions();
}
void LoLEngine::restoreAfterSceneWindowDialogue(int redraw) {
@@ -1450,7 +1538,7 @@ void LoLEngine::restoreAfterSceneWindowDialogue(int redraw) {
if (_screen->_fadeFlag != 2)
_screen->fadeClearSceneWindow(10);
gui_drawPlayField();
- setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect);
+ setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect);
_screen->_fadeFlag = 0;
}
@@ -1584,15 +1672,16 @@ void LoLEngine::transformRegion(int x1, int y1, int x2, int y2, int w, int h, in
}
}
-void LoLEngine::setPaletteBrightness(uint8 *palette, int brightness, int modifier) {
- generateBrightnessPalette(palette, _screen->getPalette(1), brightness, modifier);
+void LoLEngine::setPaletteBrightness(const Palette &srcPal, int brightness, int modifier) {
+ generateBrightnessPalette(srcPal, _screen->getPalette(1), brightness, modifier);
_screen->fadePalette(_screen->getPalette(1), 5, 0);
_screen->_fadeFlag = 0;
}
-void LoLEngine::generateBrightnessPalette(uint8 *src, uint8 *dst, int brightness, int modifier) {
- memcpy(dst, src, 0x300);
+void LoLEngine::generateBrightnessPalette(const Palette &src, Palette &dst, int brightness, int modifier) {
+ dst.copy(src);
_screen->loadSpecialColors(dst);
+
brightness = (8 - brightness) << 5;
if (modifier >= 0 && modifier < 8 && (_flagsTable[31] & 0x08)) {
brightness = 256 - ((((modifier & 0xfffe) << 5) * (256 - brightness)) >> 8);
@@ -1606,26 +1695,21 @@ void LoLEngine::generateBrightnessPalette(uint8 *src, uint8 *dst, int brightness
}
}
-void LoLEngine::generateFlashPalette(uint8 *src, uint8 *dst, int colorFlags) {
- if (!src || !dst)
- return;
-
- memcpy(dst, src, 6);
-
- uint8 *s = src + 6;
- uint8 *d = dst + 6;
+void LoLEngine::generateFlashPalette(const Palette &src, Palette &dst, int colorFlags) {
+ dst.copy(src, 0, 2);
for (int i = 2; i < 128; i++) {
for (int ii = 0; ii < 3; ii++) {
- uint8 t = *s++ & 0x3f;
+ uint8 t = src[i * 3 + ii] & 0x3f;
if (colorFlags & (1 << ii))
t += ((0x3f - t) >> 1);
else
t -= (t >> 1);
- *d++ = t;
+ dst[i * 3 + ii] = t;
}
}
- memcpy(d, s, 384);
+
+ dst.copy(src, 128);
}
void LoLEngine::updateSequenceBackgroundAnimations() {
@@ -1790,32 +1874,6 @@ void LoLEngine::delay(uint32 millis, bool doUpdate, bool) {
}
}
-uint8 LoLEngine::getRandomNumberSpecial() {
- uint8 a = _rndSpecial & 0xff;
- uint8 b = (_rndSpecial >> 8) & 0xff;
- uint8 c = (_rndSpecial >> 16) & 0xff;
-
- a >>= 1;
-
- uint as = a & 1;
- uint bs = (b >> 7) ? 0 : 1;
- uint cs = c >> 7;
-
- a >>= 1;
- c = (c << 1) | as;
- b = (b << 1) | cs;
-
- a -= ((_rndSpecial & 0xff) - bs);
- as = a & 1;
- a >>= 1;
-
- a = ((_rndSpecial & 0xff) >> 1) | (as << 7);
-
- _rndSpecial = (_rndSpecial & 0xff000000) | (c << 16) | (b << 8) | a;
-
- return a ^ b;
-}
-
void LoLEngine::updateEnvironmentalSfx(int soundId) {
snd_processEnvironmentalSoundEffect(soundId, _currentBlock);
}
@@ -1919,7 +1977,7 @@ int LoLEngine::castHealOnSingleCharacter(ActiveSpell *a) {
}
int LoLEngine::processMagicSpark(int charNum, int spellLevel) {
- WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+ WSAMovie_v2 *mov = new WSAMovie_v2(this);
_screen->copyPage(0, 12);
mov->open("spark1.wsa", 0, 0);
@@ -2120,25 +2178,24 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) {
gui_drawScene(0);
_screen->copyPage(0, 12);
- uint8 *tpal = new uint8[768];
- uint8 *swampCol = new uint8[768];
+ Palette tpal(768), swampCol(768);
if (_currentLevel == 11 && !(_flagsTable[52] & 0x04)) {
- uint8 *sc = _screen->_currentPalette;
- uint8 *dc = _screen->getPalette(2);
+ uint8 *sc = _screen->getPalette(0).getData();
+ uint8 *dc = _screen->getPalette(2).getData();
for (int i = 1; i < 768; i++)
SWAP(sc[i], dc[i]);
+
_flagsTable[52] |= 0x04;
static const uint8 freezeTimes[] = { 20, 28, 40, 60 };
setCharacterUpdateEvent(charNum, 8, freezeTimes[spellLevel], 1);
}
- uint8 *sc = _res->fileData("swampice.col", 0);
- memcpy(swampCol, sc, 384);
- uint8 *s = _screen->getPalette(1);
- for (int i = 384; i < 768; i++)
- swampCol[i] = tpal[i] = s[i] & 0x3f;
+ _screen->loadPalette("SWAMPICE.COL", swampCol);
+ tpal.copy(_screen->getPalette(1), 128);
+ swampCol.copy(_screen->getPalette(1), 128);
+ Palette &s = _screen->getPalette(1);
for (int i = 1; i < 128; i++) {
tpal[i * 3] = 0;
uint16 v = (s[i * 3] + s[i * 3 + 1] + s[i * 3 + 2]) / 3;
@@ -2148,24 +2205,25 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) {
if (tpal[i * 3 + 2] > 0x3f)
tpal[i * 3 + 2] = 0x3f;
}
+
generateBrightnessPalette(tpal, tpal, _brightness, _lampEffect);
generateBrightnessPalette(swampCol, swampCol, _brightness, _lampEffect);
swampCol[0] = swampCol[1] = swampCol[2] = tpal[0] = tpal[1] = tpal[2] = 0;
- generateBrightnessPalette(_screen->_currentPalette, s, _brightness, _lampEffect);
+ generateBrightnessPalette(_screen->getPalette(0), s, _brightness, _lampEffect);
int sX = 112;
int sY = 0;
- WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+ WSAMovie_v2 *mov = new WSAMovie_v2(this);
if (spellLevel == 0) {
sX = 0;
} if (spellLevel == 1 || spellLevel == 2) {
- mov->open("snow.wsa", 1, 0);
+ mov->open("SNOW.WSA", 1, 0);
if (!mov->opened())
error("Ice: Unable to load snow.wsa");
} if (spellLevel == 3) {
- mov->open("ice.wsa", 1, 0);
+ mov->open("ICE.WSA", 1, 0);
if (!mov->opened())
error("Ice: Unable to load ice.wsa");
sX = 136;
@@ -2174,9 +2232,9 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) {
snd_playSoundEffect(71, -1);
- playSpellAnimation(0, 0, 0, 2, 0, 0, 0, s, tpal, 40, false);
+ playSpellAnimation(0, 0, 0, 2, 0, 0, 0, s.getData(), tpal.getData(), 40, false);
- _screen->fadePaletteStep(s, tpal, _system->getMillis(), _tickLength);
+ _screen->fadePaletteStep(s.getData(), tpal.getData(), _system->getMillis(), _tickLength);
if (mov->opened()) {
int r = true;
if (spellLevel > 2) {
@@ -2241,22 +2299,19 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) {
enableSysTimer(2);
if (_currentLevel != 11)
- generateBrightnessPalette(_screen->_currentPalette, swampCol, _brightness, _lampEffect);
+ generateBrightnessPalette(_screen->getPalette(0), swampCol, _brightness, _lampEffect);
- playSpellAnimation(0, 0, 0, 2, 0, 0, 0, tpal, swampCol, 40, 0);
+ playSpellAnimation(0, 0, 0, 2, 0, 0, 0, tpal.getData(), swampCol.getData(), 40, 0);
- _screen->fadePaletteStep(tpal, swampCol, _system->getMillis(), _tickLength);
+ _screen->fadePaletteStep(tpal.getData(), swampCol.getData(), _system->getMillis(), _tickLength);
if (breakWall)
- breakIceWall(tpal, swampCol);
+ breakIceWall(tpal.getData(), swampCol.getData());
static const uint8 freezeTime[] = { 20, 28, 40, 60 };
if (_currentLevel == 11)
setCharacterUpdateEvent(charNum, 8, freezeTime[spellLevel], 1);
- delete[] sc;
- delete[] swampCol;
- delete[] tpal;
_screen->setCurPage(cp);
return 1;
}
@@ -2417,7 +2472,7 @@ int LoLEngine::processMagicHandOfFate(int spellLevel) {
int cp = _screen->setCurPage(2);
_screen->copyPage(0, 12);
- WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+ WSAMovie_v2 *mov = new WSAMovie_v2(this);
mov->open("hand.wsa", 1, 0);
if (!mov->opened())
error("Hand: Unable to load HAND.WSA");
@@ -2495,8 +2550,8 @@ int LoLEngine::processMagicHandOfFate(int spellLevel) {
int LoLEngine::processMagicMistOfDoom(int charNum, int spellLevel) {
static const uint8 mistDamage[] = { 30, 70, 110, 200 };
-
- _envSfxUseQueue = true;
+
+ _envSfxUseQueue = true;
inflictMagicalDamageForBlock(calcNewBlockPosition(_currentBlock, _currentDirection), charNum, mistDamage[spellLevel], 0x80);
_envSfxUseQueue = false;
@@ -2509,7 +2564,7 @@ int LoLEngine::processMagicMistOfDoom(int charNum, int spellLevel) {
char wsafile[13];
snprintf(wsafile, 13, "mists%0d.wsa", spellLevel + 1);
- WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+ WSAMovie_v2 *mov = new WSAMovie_v2(this);
mov->open(wsafile, 1, 0);
if (!mov->opened())
error("Mist: Unable to load mists.wsa");
@@ -2541,7 +2596,7 @@ int LoLEngine::processMagicLightning(int charNum, int spellLevel) {
char wsafile[13];
snprintf(wsafile, 13, "litning%d.wsa", spellLevel + 1);
- WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+ WSAMovie_v2 *mov = new WSAMovie_v2(this);
mov->open(wsafile, 1, 0);
if (!mov->opened())
error("Litning: Unable to load litning.wsa");
@@ -2570,7 +2625,7 @@ int LoLEngine::processMagicFog() {
int cp = _screen->setCurPage(2);
_screen->copyPage(0, 12);
- WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+ WSAMovie_v2 *mov = new WSAMovie_v2(this);
int numFrames = mov->open("fog.wsa", 0, 0);
if (!mov->opened())
error("Fog: Unable to load fog.wsa");
@@ -2646,7 +2701,7 @@ int LoLEngine::processMagicSwarm(int charNum, int damage) {
_monsters[destIds[i]].fightCurTick = destTicks[i];
}
- WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+ WSAMovie_v2 *mov = new WSAMovie_v2(this);
mov->open("swarm.wsa", 0, 0);
if (!mov->opened())
@@ -2671,7 +2726,7 @@ int LoLEngine::processMagicSwarm(int charNum, int damage) {
int LoLEngine::processMagicVaelansCube() {
uint8 *tmpPal1 = new uint8[768];
uint8 *tmpPal2 = new uint8[768];
- uint8 *sp1 = _screen->getPalette(1);
+ uint8 *sp1 = _screen->getPalette(1).getData();
memcpy(tmpPal1, sp1, 768);
memcpy(tmpPal2, sp1, 768);
@@ -2734,7 +2789,7 @@ int LoLEngine::processMagicGuardian(int charNum) {
_screen->copyPage(0, 2);
_screen->copyPage(2, 12);
- WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+ WSAMovie_v2 *mov = new WSAMovie_v2(this);
mov->open("guardian.wsa", 0, 0);
if (!mov->opened())
error("Guardian: Unable to load guardian.wsa");
@@ -2742,7 +2797,7 @@ int LoLEngine::processMagicGuardian(int charNum) {
playSpellAnimation(mov, 0, 37, 2, 112, 0, 0, 0, 0, 0, false);
_screen->copyPage(2, 12);
-
+
uint16 bl = calcNewBlockPosition(_currentBlock, _currentDirection);
int res = (_levelBlockProperties[bl].assignedObjects & 0x8000) ? 1 : 0;
inflictMagicalDamageForBlock(bl, charNum, 200, 0x80);
@@ -2754,7 +2809,7 @@ int LoLEngine::processMagicGuardian(int charNum) {
_screen->copyPage(2, 12);
snd_playSoundEffect(176, -1);
playSpellAnimation(mov, 38, 48, 8, 112, 0, 0, 0, 0, 0, false);
-
+
mov->close();
delete mov;
@@ -2771,20 +2826,22 @@ void LoLEngine::callbackProcessMagicSwarm(WSAMovie_v2 *mov, int x, int y) {
}
void LoLEngine::callbackProcessMagicLightning(WSAMovie_v2 *mov, int x, int y) {
- uint8 *tpal = new uint8[768];
if (_lightningDiv == 2)
shakeScene(1, 2, 3, 0);
- uint8 *p1 = _screen->getPalette(1);
+ const Palette &p1 = _screen->getPalette(1);
if (_lightningSfxFrame % _lightningDiv) {
_screen->setScreenPalette(p1);
} else {
- memcpy(tpal, p1, 768);
+ Palette tpal(p1.getNumColors());
+ tpal.copy(p1);
+
for (int i = 6; i < 384; i++) {
uint16 v = (tpal[i] * 120) / 64;
tpal[i] = (v < 64) ? v : 63;
}
+
_screen->setScreenPalette(tpal);
}
@@ -2799,7 +2856,55 @@ void LoLEngine::callbackProcessMagicLightning(WSAMovie_v2 *mov, int x, int y) {
}
_lightningSfxFrame++;
- delete[] tpal;
+}
+
+void LoLEngine::drinkBezelCup(int numUses, int charNum) {
+ int cp = _screen->setCurPage(2);
+ snd_playSoundEffect(73, -1);
+
+ WSAMovie_v2 *mov = new WSAMovie_v2(this);
+ mov->open("bezel.wsa", 0, 0);
+ if (!mov->opened())
+ error("Bezel: Unable to load bezel.wsa");
+
+ int x = _activeCharsXpos[charNum] - 11;
+ int y = 124;
+ int w = mov->width();
+ int h = mov->height();
+
+ _screen->copyRegion(x, y, 0, 0, w, h, 0, 2, Screen::CR_NO_P_CHECK);
+
+ static const uint8 bezelAnimData[] = { 0, 26, 20, 27, 61, 55, 62, 92, 86, 93, 131, 125 };
+ int frm = bezelAnimData[numUses * 3];
+ int hpDiff = _characters[charNum].hitPointsMax - _characters[charNum].hitPointsCur;
+ uint16 step = 0;
+
+ do {
+ step = (step & 0xff) + (hpDiff * 256) / (bezelAnimData[numUses * 3 + 2]);
+ increaseCharacterHitpoints(charNum, step / 256, true);
+ gui_drawCharPortraitWithStats(charNum);
+
+ uint32 etime = _system->getMillis() + 4 * _tickLength;
+
+ _screen->copyRegion(0, 0, x, y, w, h, 2, 2, Screen::CR_NO_P_CHECK);
+ mov->displayFrame(frm, 2, x, y, 0x5000, _trueLightTable1, _trueLightTable2);
+ _screen->copyRegion(x, y, x, y, w, h, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+
+ delayUntil(etime);
+ } while (++frm < bezelAnimData[numUses * 3 + 1]);
+
+ _characters[charNum].hitPointsCur = _characters[charNum].hitPointsMax;
+ _screen->copyRegion(0, 0, x, y, w, h, 2, 2, Screen::CR_NO_P_CHECK);
+ removeCharacterEffects(&_characters[charNum], 4, 4);
+ gui_drawCharPortraitWithStats(charNum);
+ _screen->copyRegion(x, y, x, y, w, h, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+
+ mov->close();
+ delete mov;
+
+ _screen->setCurPage(cp);
}
void LoLEngine::addSpellToScroll(int spell, int charNum) {
@@ -2871,7 +2976,7 @@ void LoLEngine::transferSpellToScollAnimation(int charNum, int spell, int slot)
snd_playSoundEffect(_updateSpellBookAnimData[(spell << 2) + 3], -1);
snd_playSoundEffect(95, -1);
- WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+ WSAMovie_v2 *mov = new WSAMovie_v2(this);
mov->open("getspell.wsa", 0, 0);
if (!mov->opened())
@@ -3282,6 +3387,52 @@ int LoLEngine::calcInflictableDamagePerItem(int16 attacker, int16 target, uint16
}
void LoLEngine::checkForPartyDeath() {
+ Button b;
+ b.data0Val2 = b.data1Val2 = b.data2Val2 = 0xfe;
+ b.data0Val3 = b.data1Val3 = b.data2Val3 = 0x01;
+
+ for (int i = 0; i < 4; i++) {
+ if (!(_characters[i].flags & 1) || _characters[i].hitPointsCur <= 0)
+ continue;
+ return;
+ }
+
+ if (_weaponsDisabled)
+ clickedExitCharInventory(&b);
+
+ gui_drawAllCharPortraitsWithStats();
+
+ if (_partyDamageFlags & 0x40) {
+ _screen->fadeToBlack(40);
+ for (int i = 0; i < 4; i++) {
+ if (_characters[i].flags & 1)
+ increaseCharacterHitpoints(i, 1, true);
+ }
+ gui_drawAllCharPortraitsWithStats();
+ _screen->fadeToPalette1(40);
+
+ } else {
+ _screen->fadeClearSceneWindow(10);
+ restoreAfterSpecialScene(0, 1, 1, 0);
+
+ snd_playTrack(325);
+ updatePortraits();
+ initTextFading(0, 1);
+ setMouseCursorToIcon(0);
+ _updateFlags |= 4;
+ setLampMode(true);
+ disableSysTimer(2);
+
+ _gui->runMenu(_gui->_deathMenu);
+
+ setMouseCursorToItemInHand();
+ _updateFlags &= 0xfffb;
+ resetLampStatus();
+
+ gui_enableDefaultPlayfieldButtons();
+ enableSysTimer(2);
+ updateDrawPage2();
+ }
}
void LoLEngine::applyMonsterAttackSkill(MonsterInPlay *monster, int16 target, int16 damage) {
@@ -3499,16 +3650,16 @@ void LoLEngine::restoreSwampPalette() {
if (_currentLevel != 11)
return;
- uint8 *s = _screen->getPalette(2);
- uint8 *d = _screen->_currentPalette;
- uint8 *d2 = _screen->getPalette(1);
+ uint8 *s = _screen->getPalette(2).getData();
+ uint8 *d = _screen->getPalette(0).getData();
+ uint8 *d2 = _screen->getPalette(1).getData();
for (int i = 1; i < 768; i++)
SWAP(s[i], d[i]);
- generateBrightnessPalette(d, d2, _brightness, _lampEffect);
- _screen->loadSpecialColors(s);
- _screen->loadSpecialColors(d2);
+ generateBrightnessPalette(_screen->getPalette(0), _screen->getPalette(1), _brightness, _lampEffect);
+ _screen->loadSpecialColors(_screen->getPalette(2));
+ _screen->loadSpecialColors(_screen->getPalette(1));
playSpellAnimation(0, 0, 0, 2, 0, 0, 0, s, d2, 40, 0);
}
@@ -3529,7 +3680,7 @@ void LoLEngine::launchMagicViper() {
_screen->copyPage(0, 12);
snd_playSoundEffect(148, -1);
- WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+ WSAMovie_v2 *mov = new WSAMovie_v2(this);
int numFrames = mov->open("viper.wsa", 1, 0);
if (!mov->opened())
error("Viper: Unable to load viper.wsa");
@@ -3579,7 +3730,7 @@ void LoLEngine::breakIceWall(uint8 *pal1, uint8 *pal2) {
gui_drawScene(2);
_screen->copyPage(2, 10);
- WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+ WSAMovie_v2 *mov = new WSAMovie_v2(this);
int numFrames = mov->open("shatter.wsa", 1, 0);
if (!mov->opened())
error("Shatter: Unable to load shatter.wsa");
@@ -3681,7 +3832,7 @@ void LoLEngine::displayAutomap() {
uint8 *tmpWll = new uint8[80];
memcpy(tmpWll, _wllBuffer4, 80);
- _screen->loadBitmap("parch.cps", 2, 2, _screen->getPalette(3));
+ _screen->loadBitmap("parch.cps", 2, 2, &_screen->getPalette(3));
_screen->loadBitmap("autobut.shp", 3, 5, 0);
const uint8 *shp = _screen->getCPagePtr(5);
@@ -3848,12 +3999,17 @@ void LoLEngine::loadMapLegendData(int level) {
}
void LoLEngine::drawMapPage(int pageNum) {
+ // WORKAROUND for French version. The Text does not always properly fit the screen there.
+ int8 textOffset = (_lang == 1) ? -2 : 0;
+
for (int i = 0; i < 2; i++) {
- _screen->loadBitmap("parch.cps", pageNum, pageNum, _screen->getPalette(3));
+ _screen->loadBitmap("parch.cps", pageNum, pageNum, &_screen->getPalette(3));
+ if (_lang == 1)
+ _screen->copyRegion(236, 16, 236 + textOffset, 16, -textOffset, 1, pageNum, pageNum, Screen::CR_NO_P_CHECK);
int cp = _screen->setCurPage(pageNum);
Screen::FontId of = _screen->setFont(Screen::FID_9_FNT);
- _screen->printText(getLangString(_autoMapStrings[_currentMapLevel]), 236, 8, 1, 0);
+ _screen->printText(getLangString(_autoMapStrings[_currentMapLevel]), 236 + textOffset, 8, 1, 0);
uint16 blX = mapGetStartPosX();
uint16 bl = (mapGetStartPosY() << 5) + blX;
@@ -3932,7 +4088,7 @@ void LoLEngine::drawMapPage(int pageNum) {
if (l[2] == 0xffff)
continue;
- printMapText(l[2], 244, (tY << 3) + 22);
+ printMapText(l[2], 244 + textOffset, (tY << 3) + 22);
if (l[5] == 0xffff) {
tY++;
@@ -3942,7 +4098,7 @@ void LoLEngine::drawMapPage(int pageNum) {
uint16 cbl2 = l[3] + (l[4] << 5);
_levelBlockProperties[cbl2].flags |= 7;
_screen->drawShape(2, _automapShapes[l[5] << 2], (l[3] - sx) * 7 + _automapTopLeftX - 3, (l[4] - sy) * 6 + _automapTopLeftY - 3, 0, 0);
- _screen->drawShape(2, _automapShapes[l[5] << 2], 231, (tY << 3) + 19, 0, 0);
+ _screen->drawShape(2, _automapShapes[l[5] << 2], 231 + textOffset, (tY << 3) + 19, 0, 0);
tY++;
}
@@ -3951,9 +4107,9 @@ void LoLEngine::drawMapPage(int pageNum) {
for (int ii = 0; ii < 11; ii++) {
if (!_defaultLegendData[ii].enable)
continue;
- _screen->copyBlockAndApplyOverlay(_screen->_curPage, 235, (tY << 3) + 21, _screen->_curPage, 235, (tY << 3) + 21, 7, 6, 0, _mapOverlay);
- _screen->drawShape(_screen->_curPage, _automapShapes[_defaultLegendData[ii].shapeIndex << 2], 232, (tY << 3) + 18 + _defaultLegendData[ii].x, 0, 0);
- printMapText(_defaultLegendData[ii].stringId, 244, (tY << 3) + 22);
+ _screen->copyBlockAndApplyOverlay(_screen->_curPage, 235, (tY << 3) + 21, _screen->_curPage, 235 + textOffset, (tY << 3) + 21, 7, 6, 0, _mapOverlay);
+ _screen->drawShape(_screen->_curPage, _automapShapes[_defaultLegendData[ii].shapeIndex << 2], 232 + textOffset, (tY << 3) + 18 + _defaultLegendData[ii].x, 0, 0);
+ printMapText(_defaultLegendData[ii].stringId, 244 + textOffset, (tY << 3) + 22);
tY++;
}
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h
index 45795a7cab..12000c31fa 100644
--- a/engines/kyra/lol.h
+++ b/engines/kyra/lol.h
@@ -307,6 +307,7 @@ public:
Screen *screen();
GUI *gui() const;
+
private:
Screen_LoL *_screen;
GUI_LoL *_gui;
@@ -326,6 +327,10 @@ private:
void startup();
void startupNew();
+ void registerDefaultSettings();
+ void writeSettings();
+ void readSettings();
+
// options
int _monsterDifficulty;
bool _smoothScrollingEnabled;
@@ -342,7 +347,9 @@ private:
uint8 *getItemIconShapePtr(int index);
bool posWithinRect(int mouseX, int mouseY, int x1, int y1, int x2, int y2);
- int _floatingMouseArrowControl;
+ void checkFloatingPointerRegions();
+ int _floatingCursorControl;
+ int _currentFloatingCursor;
// intro + character selection
int processPrologue();
@@ -441,6 +448,9 @@ private:
int _timer3Para;
// sound
+ int convertVolumeToMixer(int value);
+ int convertVolumeFromMixer(int value);
+
void loadTalkFile(int index);
void snd_playVoiceFile(int track) {}
bool snd_playCharacterSpeech(int id, int8 speaker, int);
@@ -473,7 +483,6 @@ private:
Common::List<Audio::AudioStream*> _speechList;
int _curTlkFile;
- int _speechFlag;
char **_ingameSoundList;
int _ingameSoundListSize;
@@ -772,11 +781,12 @@ private:
int olol_getNextActiveCharacter(EMCState *script);
int olol_paralyzePoisonCharacter(EMCState *script);
int olol_drawCharPortrait(EMCState *script);
- int olol_removeInventoryItem(EMCState *script);
+ int olol_removeInventoryItem(EMCState *script);
int olol_getAnimationLastPart(EMCState *script);
int olol_assignSpecialGuiShape(EMCState *script);
int olol_findInventoryItem(EMCState *script);
int olol_restoreFadePalette(EMCState *script);
+ int olol_drinkBezelCup(EMCState *script);
int olol_changeItemTypeOrFlag(EMCState *script);
int olol_placeInventoryItemInHand(EMCState *script);
int olol_castSpell(EMCState *script);
@@ -862,9 +872,9 @@ private:
void toggleSelectedCharacterFrame(bool mode);
void fadeText();
void transformRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage);
- void setPaletteBrightness(uint8 *palette, int brightness, int modifier);
- void generateBrightnessPalette(uint8 *src, uint8 *dst, int brightness, int modifier);
- void generateFlashPalette(uint8 *src, uint8 *dst, int colorFlags);
+ void setPaletteBrightness(const Palette &srcPal, int brightness, int modifier);
+ void generateBrightnessPalette(const Palette &src, Palette &dst, int brightness, int modifier);
+ void generateFlashPalette(const Palette &src, Palette &dst, int colorFlags);
void updateSequenceBackgroundAnimations();
bool _dialogueField;
@@ -905,7 +915,7 @@ private:
void setCharacterMagicOrHitPoints(int charNum, int type, int points, int mode);
void increaseExperience(int charNum, int skill, uint32 points);
- void increaseCharacterHitpoints(int charNum, int points, bool unk);
+ void increaseCharacterHitpoints(int charNum, int points, bool ignoreDeath);
LoLCharacter *_characters;
uint16 _activeCharsXpos[3];
@@ -1303,7 +1313,6 @@ private:
// misc
void delay(uint32 millis, bool doUpdate = false, bool isMainLoop = false);
- uint8 getRandomNumberSpecial();
uint8 _compassBroken;
uint8 _drainMagic;
@@ -1349,6 +1358,8 @@ private:
void callbackProcessMagicSwarm(WSAMovie_v2 *mov, int x, int y);
void callbackProcessMagicLightning(WSAMovie_v2 *mov, int x, int y);
+ void drinkBezelCup(int a, int charNum);
+
void addSpellToScroll(int spell, int charNum);
void transferSpellToScollAnimation(int charNum, int spell, int slot);
diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp
index 79665068f6..ecd6bbe450 100644
--- a/engines/kyra/saveload.cpp
+++ b/engines/kyra/saveload.cpp
@@ -29,6 +29,7 @@
#include "graphics/thumbnail.h"
#include "kyra/kyra_v1.h"
+#include "kyra/util.h"
#define CURRENT_SAVE_VERSION 16
@@ -65,6 +66,8 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab
in->read(descriptionBuffer, descriptionSize[i]);
descriptionBuffer[descriptionSize[i]] = 0;
+ Util::convertDOSToISO(descriptionBuffer);
+
type = in->readUint32BE();
header.version = in->readUint16LE();
if (type == MKID_BE('MBL3') && header.version == 100) {
diff --git a/engines/kyra/scene_hof.cpp b/engines/kyra/scene_hof.cpp
index fed7877c0b..2d15af92fd 100644
--- a/engines/kyra/scene_hof.cpp
+++ b/engines/kyra/scene_hof.cpp
@@ -330,9 +330,6 @@ int KyraEngine_HoF::trySceneChange(int *moveTable, int unk1, int updateChar) {
updateCharacterAnim(0);
refreshAnimObjectsIfNeed();
- if (!changedScene && !_unk4) {
- //XXX
- }
return changedScene;
}
@@ -396,14 +393,14 @@ void KyraEngine_HoF::unloadScene() {
void KyraEngine_HoF::loadScenePal() {
uint16 sceneId = _mainCharacter.sceneId;
- memcpy(_screen->getPalette(1), _screen->getPalette(0), 768);
+ _screen->copyPalette(1, 0);
char filename[14];
strcpy(filename, _sceneList[sceneId].filename1);
strcat(filename, ".COL");
_screen->loadBitmap(filename, 3, 3, 0);
- memcpy(_screen->getPalette(1), _screen->getCPagePtr(3), 384);
- memset(_screen->getPalette(1), 0, 3);
+ _screen->getPalette(1).copy(_screen->getCPagePtr(3), 0, 128);
+ _screen->getPalette(1).fill(0, 1, 0);
memcpy(_scenePal, _screen->getCPagePtr(3)+336, 432);
}
@@ -669,7 +666,7 @@ void KyraEngine_HoF::initSceneScreen(int unk1) {
}
if (_noScriptEnter) {
- memset(_screen->getPalette(0), 0, 384);
+ _screen->getPalette(0).fill(0, 128, 0);
_screen->setScreenPalette(_screen->getPalette(0));
}
@@ -677,7 +674,7 @@ void KyraEngine_HoF::initSceneScreen(int unk1) {
if (_noScriptEnter) {
_screen->setScreenPalette(_screen->getPalette(1));
- memcpy(_screen->getPalette(0), _screen->getPalette(1), 384);
+ _screen->getPalette(0).copy(_screen->getPalette(1), 0, 128);
}
updateCharPal(0);
@@ -695,10 +692,7 @@ void KyraEngine_HoF::freeSceneShapePtrs() {
}
void KyraEngine_HoF::fadeScenePal(int srcIndex, int delayTime) {
- uint8 *dst = _screen->getPalette(0) + 336;
- const uint8 *src = _scenePal + (srcIndex << 4)*3;
- memcpy(dst, src, 48);
-
+ _screen->getPalette(0).copy(_scenePal, srcIndex << 4, 16, 112);
_screen->fadePalette(_screen->getPalette(0), delayTime, &_updateFunctor);
}
diff --git a/engines/kyra/scene_lok.cpp b/engines/kyra/scene_lok.cpp
index 345998e40e..fc1ca41189 100644
--- a/engines/kyra/scene_lok.cpp
+++ b/engines/kyra/scene_lok.cpp
@@ -406,7 +406,7 @@ void KyraEngine_LoK::startSceneScript(int brandonAlive) {
_screen->clearPage(3);
_res->exists(fileNameBuffer, true);
// FIXME: check this hack for amiga version
- _screen->loadBitmap(fileNameBuffer, 3, 3, (_flags.platform == Common::kPlatformAmiga ? _screen->getPalette(0) : 0));
+ _screen->loadBitmap(fileNameBuffer, 3, 3, (_flags.platform == Common::kPlatformAmiga ? &_screen->getPalette(0) : 0));
_sprites->loadSceneShapes();
_exitListPtr = 0;
@@ -770,7 +770,7 @@ void KyraEngine_LoK::initSceneObjectList(int brandonAlive) {
void KyraEngine_LoK::initSceneScreen(int brandonAlive) {
if (_flags.platform == Common::kPlatformAmiga) {
if (_unkScreenVar1 && !queryGameFlag(0xF0)) {
- memset(_screen->getPalette(2), 0, 32*3);
+ _screen->getPalette(2).clear();
if (_currentCharacter->sceneId != 117 || !queryGameFlag(0xB3))
_screen->setScreenPalette(_screen->getPalette(2));
}
@@ -782,10 +782,10 @@ void KyraEngine_LoK::initSceneScreen(int brandonAlive) {
if (_unkScreenVar1 && !queryGameFlag(0xA0)) {
if (_currentCharacter->sceneId == 45 && _paletteChanged)
- memcpy(_screen->getPalette(0) + 12*3, _screen->getPalette(4) + 12*3, 2);
+ _screen->getPalette(0).copy(_screen->getPalette(4), 12, 1);
if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245 && (_brandonStatusBit & 1))
- memcpy(_screen->getPalette(0), _screen->getPalette(0) + 320*3, 64);
+ _screen->copyPalette(0, 10);
_screen->setScreenPalette(_screen->getPalette(0));
}
@@ -807,10 +807,10 @@ void KyraEngine_LoK::initSceneScreen(int brandonAlive) {
if (_unkScreenVar1 && _paletteChanged) {
if (!queryGameFlag(0xA0)) {
- memcpy(_screen->getPalette(0) + 684, _screen->getPalette(1) + 684, 60);
+ _screen->getPalette(0).copy(_screen->getPalette(1), 228, 20);
_screen->setScreenPalette(_screen->getPalette(0));
} else {
- memset(_screen->getPalette(0), 0, 768);
+ _screen->getPalette(0).clear();
}
}
}
diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp
index 0236e4fa7d..945495517f 100644
--- a/engines/kyra/scene_lol.cpp
+++ b/engines/kyra/scene_lol.cpp
@@ -86,7 +86,7 @@ void LoLEngine::loadLevel(int index) {
addLevelItems();
deleteMonstersFromBlock(_currentBlock);
- _screen->generateGrayOverlay(_screen->_currentPalette, _screen->_grayOverlay, 32, 16, 0, 0, 128, true);
+ _screen->generateGrayOverlay(_screen->getPalette(0), _screen->_grayOverlay, 32, 16, 0, 0, 128, true);
_sceneDefaultUpdate = 0;
if (_screen->_fadeFlag == 3)
@@ -94,7 +94,7 @@ void LoLEngine::loadLevel(int index) {
gui_drawPlayField();
- setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect);
+ setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect);
setMouseCursorToItemInHand();
snd_playTrack(_curMusicTheme);
@@ -379,28 +379,24 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight
v += 128;
if (_lastOverridePalFilePtr) {
- uint8 *tpal = _res->fileData(_lastOverridePalFilePtr, 0);
- memcpy(_screen->_currentPalette, tpal, 384);
- delete[] tpal;
+ _res->loadFileToBuf(_lastOverridePalFilePtr, _screen->getPalette(0).getData(), 384);
} else {
- memcpy(_screen->_currentPalette, v, 384);
+ _screen->getPalette(0).copy(v, 0, 128);
}
v += 384;
/*uint8 tmpPal = new uint8[384];
- memcpy(tmpPal, _screen->_currentPalette + 384, 384);
- memset(_screen->_currentPalette + 384, 0xff, 384);
- memcpy(_screen->_currentPalette + 384, tmpPal, 384);*/
+ memcpy(tmpPal, _screen->getPalette(0) + 384, 384);
+ memset(_screen->getPalette(0) + 384, 0xff, 384);
+ memcpy(_screen->getPalette(0) + 384, tmpPal, 384);*/
if (_currentLevel == 11) {
- uint8 *swampPal = _res->fileData("SWAMPICE.COL", 0);
- memcpy(_screen->getPalette(2), swampPal, 384);
- memcpy(_screen->getPalette(2) + 384, _screen->_currentPalette + 384, 384);
- delete[] swampPal;
+ _screen->loadPalette("SWAMPICE.COL", _screen->getPalette(2));
+ _screen->getPalette(2).copy(_screen->getPalette(0), 128);
if (_flagsTable[52] & 0x04) {
- uint8 *pal0 = _screen->_currentPalette;
- uint8 *pal2 = _screen->getPalette(2);
+ uint8 *pal0 = _screen->getPalette(0).getData();
+ uint8 *pal2 = _screen->getPalette(2).getData();
for (int i = 1; i < 768; i++)
SWAP(pal0[i], pal2[i]);
}
@@ -427,7 +423,7 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight
for (int i = 0; i < 7; i++) {
weight = 100 - (i * _lastSpecialColorWeight);
weight = (weight > 0) ? (weight * 255) / 100 : 0;
- _screen->generateLevelOverlay(_screen->_currentPalette, _screen->getLevelOverlay(i), _lastSpecialColor, weight);
+ _screen->generateLevelOverlay(_screen->getPalette(0), _screen->getLevelOverlay(i), _lastSpecialColor, weight);
for (int ii = 0; ii < 128; ii++) {
if (_screen->getLevelOverlay(i)[ii] == 255)
@@ -442,7 +438,7 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight
_screen->getLevelOverlay(7)[i] = i & 0xff;
_loadSuppFilesFlag = 0;
- generateBrightnessPalette(_screen->_currentPalette, _screen->getPalette(1), _brightness, _lampEffect);
+ generateBrightnessPalette(_screen->getPalette(0), _screen->getPalette(1), _brightness, _lampEffect);
char tname[13];
snprintf(tname, sizeof(tname), "LEVEL%.02d.TLC", _currentLevel);
@@ -548,14 +544,14 @@ void LoLEngine::updateLampStatus() {
if (!_brightness || !_lampOilStatus) {
newLampEffect = 8;
if (newLampEffect != _lampEffect && _screen->_fadeFlag == 0)
- setPaletteBrightness(_screen->_currentPalette, _brightness, newLampEffect);
+ setPaletteBrightness(_screen->getPalette(0), _brightness, newLampEffect);
} else {
tmpOilStatus = (_lampOilStatus < 100) ? _lampOilStatus : 100;
newLampEffect = (3 - ((tmpOilStatus - 1) / 25)) << 1;
if (_lampEffect == -1) {
if (_screen->_fadeFlag == 0)
- setPaletteBrightness(_screen->_currentPalette, _brightness, newLampEffect);
+ setPaletteBrightness(_screen->getPalette(0), _brightness, newLampEffect);
_lampStatusTimer = _system->getMillis() + (10 + _rnd.getRandomNumberRng(1, 30)) * _tickLength;
} else {
if ((_lampEffect & 0xfe) == (newLampEffect & 0xfe)) {
@@ -567,7 +563,7 @@ void LoLEngine::updateLampStatus() {
}
} else {
if (_screen->_fadeFlag == 0)
- setPaletteBrightness(_screen->_currentPalette, _lampEffect, newLampEffect);
+ setPaletteBrightness(_screen->getPalette(0), _lampEffect, newLampEffect);
}
}
}
@@ -604,7 +600,7 @@ void LoLEngine::updateCompass() {
if (_compassStep)
_compassStep -= (((ABS(_compassStep) >> 4) + 2) * dir);
- int16 d = _compassBroken ? ((int8)getRandomNumberSpecial() - _compassDirection) : (_currentDirection << 6) - _compassDirection;
+ int16 d = _compassBroken ? (int8(_rnd.getRandomNumber(255)) - _compassDirection) : (_currentDirection << 6) - _compassDirection;
if (d <= -128)
d += 256;
if (d >= 128)
@@ -1261,8 +1257,8 @@ void LoLEngine::shakeScene(int duration, int width, int height, int restore) {
while (endTime > _system->getMillis()) {
uint32 delayTimer = _system->getMillis() + 2 * _tickLength;
- int s1 = width ? (getRandomNumberSpecial() % (width << 1)) - width : 0;
- int s2 = height ? (getRandomNumberSpecial() % (height << 1)) - height : 0;
+ int s1 = width ? (_rnd.getRandomNumber(255) % (width << 1)) - width : 0;
+ int s2 = height ? (_rnd.getRandomNumber(255) % (height << 1)) - height : 0;
int x1, y1, x2, y2, w, h;
if (s1 >= 0) {
@@ -1308,11 +1304,11 @@ void LoLEngine::processGasExplosion(int soundId) {
uint16 targetBlock = 0;
int dist = getSpellTargetBlock(_currentBlock, _currentDirection, 3, targetBlock);
- uint8 *p1 = _screen->getPalette(1);
- uint8 *p2 = _screen->getPalette(3);
+ uint8 *p1 = _screen->getPalette(1).getData();
+ uint8 *p2 = _screen->getPalette(3).getData();
if (dist) {
- WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+ WSAMovie_v2 *mov = new WSAMovie_v2(this);
char file[13];
snprintf(file, 13, "gasexp%0d.wsa", dist);
mov->open(file, 1, 0);
@@ -1331,11 +1327,11 @@ void LoLEngine::processGasExplosion(int soundId) {
p2[i * 3] = 0x3f;
uint32 ctime = _system->getMillis();
- while (_screen->fadePaletteStep(_screen->_currentPalette, p2, _system->getMillis() - ctime, 10))
+ while (_screen->fadePaletteStep(_screen->getPalette(0).getData(), p2, _system->getMillis() - ctime, 10))
updateInput();
ctime = _system->getMillis();
- while (_screen->fadePaletteStep(p2, _screen->_currentPalette, _system->getMillis() - ctime, 50))
+ while (_screen->fadePaletteStep(p2, _screen->getPalette(0).getData(), _system->getMillis() - ctime, 50))
updateInput();
}
@@ -1437,7 +1433,7 @@ void LoLEngine::prepareSpecialScene(int fieldType, int hasDialogue, int suspendG
gui_disableControls(controlMode);
if (fadeFlag) {
- memcpy(_screen->getPalette(3) + 384, _screen->_currentPalette + 384, 384);
+ _screen->getPalette(3).copy(_screen->getPalette(0), 128);
_screen->loadSpecialColors(_screen->getPalette(3));
_screen->fadePalette(_screen->getPalette(3), 10);
_screen->_fadeFlag = 0;
@@ -1495,7 +1491,7 @@ int LoLEngine::restoreAfterSpecialScene(int fadeFlag, int redrawPlayField, int r
if (redrawPlayField)
gui_drawPlayField();
- setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect);
+ setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect);
} else {
_currentControlMode = 0;
@@ -1517,6 +1513,7 @@ void LoLEngine::setSequenceButtons(int x, int y, int w, int h, int enableFlags)
_seqWindowY2 = y + h;
int offs = _itemInHand ? 10 : 0;
_screen->setMouseCursor(offs, offs, getItemIconShapePtr(_itemInHand));
+ _currentFloatingCursor = -1;
if (w == 320) {
setLampMode(0);
_lampStatusSuspended = true;
diff --git a/engines/kyra/scene_mr.cpp b/engines/kyra/scene_mr.cpp
index 07a7aa0d07..a68dcfb394 100644
--- a/engines/kyra/scene_mr.cpp
+++ b/engines/kyra/scene_mr.cpp
@@ -48,10 +48,8 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2
}
musicUpdate(0);
- if (!unk3) {
- //XXX
+ if (!unk3)
musicUpdate(0);
- }
if (unk1) {
int x = _mainCharacter.x1;
@@ -88,7 +86,7 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2
newSoundFile = true;
}
- //XXX
+ _chatAltFlag = false;
if (!unk3) {
_emc->init(&_sceneScriptState, &_sceneScriptData);
@@ -328,25 +326,23 @@ void KyraEngine_MR::freeSceneShapes() {
void KyraEngine_MR::loadScenePal() {
char filename[16];
- memcpy(_screen->getPalette(2), _screen->getPalette(0), 768);
+ _screen->copyPalette(2, 0);
strcpy(filename, _sceneList[_mainCharacter.sceneId].filename1);
strcat(filename, ".COL");
_screen->loadBitmap(filename, 3, 3, 0);
- memcpy(_screen->getPalette(2), _screen->getCPagePtr(3), 432);
- memset(_screen->getPalette(2), 0, 3);
+ _screen->getPalette(2).copy(_screen->getCPagePtr(3), 0, 144);
+ _screen->getPalette(2).fill(0, 1, 0);
for (int i = 144; i <= 167; ++i) {
- uint8 *palette = _screen->getPalette(2) + i * 3;
+ uint8 *palette = _screen->getPalette(2).getData() + i * 3;
palette[0] = palette[2] = 63;
palette[1] = 0;
}
_screen->generateOverlay(_screen->getPalette(2), _paletteOverlay, 0xF0, 0x19);
- uint8 *palette = _screen->getPalette(2) + 432;
- const uint8 *costPal = _costPalBuffer + _characterShapeFile * 72;
- memcpy(palette, costPal, 24*3);
+ _screen->getPalette(2).copy(_costPalBuffer, _characterShapeFile * 24, 24, 144);
}
void KyraEngine_MR::loadSceneMsc() {
@@ -609,7 +605,7 @@ void KyraEngine_MR::initSceneScreen(int unk1) {
}
if (_noScriptEnter) {
- memset(_screen->getPalette(0), 0, 432);
+ _screen->getPalette(0).fill(0, 144, 0);
if (!_wasPlayingVQA)
_screen->setScreenPalette(_screen->getPalette(0));
}
@@ -619,7 +615,7 @@ void KyraEngine_MR::initSceneScreen(int unk1) {
if (_noScriptEnter) {
if (!_wasPlayingVQA)
_screen->setScreenPalette(_screen->getPalette(2));
- memcpy(_screen->getPalette(0), _screen->getPalette(2), 432);
+ _screen->getPalette(0).copy(_screen->getPalette(2), 0, 144);
if (_wasPlayingVQA) {
_screen->fadeFromBlack(0x3C);
_wasPlayingVQA = false;
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index 2b3a9366e6..fa54bffa98 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -34,9 +34,15 @@
namespace Kyra {
Screen::Screen(KyraEngine_v1 *vm, OSystem *system)
- : _system(system), _vm(vm), _sjisInvisibleColor(0) {
+ : _system(system), _vm(vm), _sjisInvisibleColor(0),
+ _cursorColorKey((vm->gameFlags().gameID == GI_KYRA1) ? 0xFF : 0x00) {
_debugEnabled = false;
_maskMinY = _maskMaxY = -1;
+
+ _drawShapeVar1 = 0;
+ _drawShapeVar3 = 1;
+ _drawShapeVar4 = 0;
+ _drawShapeVar5 = 0;
}
Screen::~Screen() {
@@ -52,15 +58,13 @@ Screen::~Screen() {
delete[] _sjisFontData;
delete[] _sjisTempPage;
- delete[] _currentPalette;
- delete[] _screenPalette;
+ delete _screenPalette;
+ delete _internFadePalette;
delete[] _decodeShapeBuffer;
delete[] _animBlockPtr;
- if (_vm->gameFlags().platform != Common::kPlatformAmiga) {
- for (int i = 0; i < ARRAYSIZE(_palettes); ++i)
- delete[] _palettes[i];
- }
+ for (uint i = 0; i < _palettes.size(); ++i)
+ delete _palettes[i];
CursorMan.popAllCursors();
}
@@ -123,30 +127,38 @@ bool Screen::init() {
memset(_shapePages, 0, sizeof(_shapePages));
- memset(_palettes, 0, sizeof(_palettes));
- _screenPalette = new uint8[768];
+ const int paletteCount = (_vm->gameFlags().platform == Common::kPlatformAmiga) ? 12 : 4;
+ const int numColors = _use16ColorMode ? 16 : ((_vm->gameFlags().platform == Common::kPlatformAmiga) ? 32 : 256);
+
+ _screenPalette = new Palette(numColors);
assert(_screenPalette);
- memset(_screenPalette, 0, 768);
- if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
- _currentPalette = new uint8[1248];
- assert(_currentPalette);
- memset(_currentPalette, 0, 1248);
+ _palettes.resize(paletteCount);
+ for (int i = 0; i < paletteCount; ++i) {
+ _palettes[i] = new Palette(numColors);
+ assert(_palettes[i]);
+ }
- for (int i = 0; i < 6; ++i)
- _palettes[i] = _currentPalette + (i+1)*96;
- } else {
- _currentPalette = new uint8[768];
- assert(_currentPalette);
- memset(_currentPalette, 0, 768);
- for (int i = 0; i < 3; ++i) {
- _palettes[i] = new uint8[768];
- assert(_palettes[i]);
- memset(_palettes[i], 0, 768);
+ _internFadePalette = new Palette(numColors);
+ assert(_internFadePalette);
+
+ setScreenPalette(getPalette(0));
+
+ // We setup the PC98 text mode palette at [16, 24], since that will be used
+ // for KANJI characters in Lands of Lore.
+ if (_use16ColorMode && _vm->gameFlags().platform == Common::kPlatformPC98) {
+ uint8 palette[8 * 4];
+
+ for (int i = 0; i < 8; ++i) {
+ palette[i * 4 + 0] = ((i >> 1) & 1) * 0xFF;
+ palette[i * 4 + 1] = ((i >> 2) & 1) * 0xFF;
+ palette[i * 4 + 2] = ((i >> 0) & 1) * 0xFF;
+ palette[i * 4 + 3] = 0;
+
+ _system->setPalette(palette, 16, 8);
}
}
- setScreenPalette(_currentPalette);
_curDim = 0;
_charWidth = 0;
_charOffset = 0;
@@ -339,6 +351,148 @@ void Screen::clearCurPage() {
clearOverlayPage(_curPage);
}
+void Screen::copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src,
+ int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2) {
+ uint8 *dstPtr = getPagePtr(_curPage);
+ uint8 *origDst = dstPtr;
+
+ const ScreenDim *dim = getScreenDim(dimState);
+ int dimX1 = dim->sx << 3;
+ int dimX2 = dim->w << 3;
+ dimX2 += dimX1;
+
+ int dimY1 = dim->sy;
+ int dimY2 = dim->h;
+ dimY2 += dimY1;
+
+ int temp = y - dimY1;
+ if (temp < 0) {
+ if ((temp += h) <= 0)
+ return;
+ else {
+ SWAP(temp, h);
+ y += temp - h;
+ src += (temp - h) * w;
+ }
+ }
+
+ temp = dimY2 - y;
+ if (temp <= 0)
+ return;
+
+ if (temp < h)
+ h = temp;
+
+ int srcOffset = 0;
+ temp = x - dimX1;
+ if (temp < 0) {
+ temp = -temp;
+ srcOffset = temp;
+ x += temp;
+ w -= temp;
+ }
+
+ int srcAdd = 0;
+
+ temp = dimX2 - x;
+ if (temp <= 0)
+ return;
+
+ if (temp < w) {
+ SWAP(w, temp);
+ temp -= w;
+ srcAdd = temp;
+ }
+
+ dstPtr += y * SCREEN_W + x;
+ uint8 *dst = dstPtr;
+
+ if (_curPage == 0 || _curPage == 1)
+ addDirtyRect(x, y, w, h);
+
+ clearOverlayRect(_curPage, x, y, w, h);
+
+ temp = h;
+ int curY = y;
+ while (h--) {
+ src += srcOffset;
+ ++curY;
+ int cW = w;
+
+ switch (plotFunc) {
+ case 0:
+ memcpy(dst, src, cW);
+ dst += cW; src += cW;
+ break;
+
+ case 1:
+ while (cW--) {
+ uint8 d = *src++;
+ uint8 t = unkPtr1[d];
+ if (t != 0xFF)
+ d = unkPtr2[*dst + (t << 8)];
+ *dst++ = d;
+ }
+ break;
+
+ case 4:
+ while (cW--) {
+ uint8 d = *src++;
+ if (d)
+ *dst = d;
+ ++dst;
+ }
+ break;
+
+ case 5:
+ while (cW--) {
+ uint8 d = *src++;
+ if (d) {
+ uint8 t = unkPtr1[d];
+ if (t != 0xFF)
+ d = unkPtr2[*dst + (t << 8)];
+ *dst = d;
+ }
+ ++dst;
+ }
+ break;
+
+ case 8:
+ case 9:
+ while (cW--) {
+ uint8 d = *src++;
+ uint8 t = _shapePages[0][dst - origDst] & 7;
+ if (unk1 < t && (curY > _maskMinY && curY < _maskMaxY))
+ d = _shapePages[1][dst - origDst];
+ *dst++ = d;
+ }
+ break;
+
+ case 12:
+ case 13:
+ while (cW--) {
+ uint8 d = *src++;
+ if (d) {
+ uint8 t = _shapePages[0][dst - origDst] & 7;
+ if (unk1 < t && (curY > _maskMinY && curY < _maskMaxY))
+ d = _shapePages[1][dst - origDst];
+ *dst++ = d;
+ } else {
+ d = _shapePages[1][dst - origDst];
+ *dst++ = d;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ dst = (dstPtr += SCREEN_W);
+ src += srcAdd;
+ }
+}
+
uint8 Screen::getPagePixel(int pageNum, int x, int y) {
assert(pageNum < SCREEN_PAGE_NUM);
assert(x >= 0 && x < SCREEN_W && y >= 0 && y < SCREEN_H);
@@ -354,26 +508,25 @@ void Screen::setPagePixel(int pageNum, int x, int y, uint8 color) {
}
void Screen::fadeFromBlack(int delay, const UpdateFunctor *upFunc) {
- fadePalette(_currentPalette, delay, upFunc);
+ fadePalette(getPalette(0), delay, upFunc);
}
void Screen::fadeToBlack(int delay, const UpdateFunctor *upFunc) {
- uint8 blackPal[768];
- memset(blackPal, 0, 768);
- fadePalette(blackPal, delay, upFunc);
+ Palette pal(getPalette(0).getNumColors());
+ fadePalette(pal, delay, upFunc);
}
-void Screen::fadePalette(const uint8 *palData, int delay, const UpdateFunctor *upFunc) {
+void Screen::fadePalette(const Palette &pal, int delay, const UpdateFunctor *upFunc) {
updateScreen();
int diff = 0, delayInc = 0;
- getFadeParams(palData, delay, delayInc, diff);
+ getFadeParams(pal, delay, delayInc, diff);
int delayAcc = 0;
while (!_vm->shouldQuit()) {
delayAcc += delayInc;
- int refreshed = fadePalStep(palData, diff);
+ int refreshed = fadePalStep(pal, diff);
if (upFunc && upFunc->isValid())
(*upFunc)();
@@ -388,7 +541,7 @@ void Screen::fadePalette(const uint8 *palData, int delay, const UpdateFunctor *u
}
if (_vm->shouldQuit()) {
- setScreenPalette(palData);
+ setScreenPalette(pal);
if (upFunc && upFunc->isValid())
(*upFunc)();
else
@@ -396,12 +549,11 @@ void Screen::fadePalette(const uint8 *palData, int delay, const UpdateFunctor *u
}
}
-void Screen::getFadeParams(const uint8 *palette, int delay, int &delayInc, int &diff) {
+void Screen::getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff) {
uint8 maxDiff = 0;
- const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256) * 3;
- for (int i = 0; i < colors; ++i) {
- diff = ABS(palette[i] - _screenPalette[i]);
+ for (int i = 0; i < pal.getNumColors() * 3; ++i) {
+ diff = ABS(pal[i] - (*_screenPalette)[i]);
maxDiff = MAX<uint8>(maxDiff, diff);
}
@@ -417,17 +569,14 @@ void Screen::getFadeParams(const uint8 *palette, int delay, int &delayInc, int &
}
}
-int Screen::fadePalStep(const uint8 *palette, int diff) {
- const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : (_use16ColorMode ? 16 : 256)) * 3;
-
- uint8 fadePal[768];
- memcpy(fadePal, _screenPalette, colors);
+int Screen::fadePalStep(const Palette &pal, int diff) {
+ _internFadePalette->copy(*_screenPalette);
bool needRefresh = false;
- for (int i = 0; i < colors; ++i) {
- int c1 = palette[i];
- int c2 = fadePal[i];
+ for (int i = 0; i < pal.getNumColors() * 3; ++i) {
+ int c1 = pal[i];
+ int c2 = (*_internFadePalette)[i];
if (c1 != c2) {
needRefresh = true;
if (c1 > c2) {
@@ -442,26 +591,26 @@ int Screen::fadePalStep(const uint8 *palette, int diff) {
c2 = c1;
}
- fadePal[i] = (uint8)c2;
+ (*_internFadePalette)[i] = (uint8)c2;
}
}
if (needRefresh)
- setScreenPalette(fadePal);
+ setScreenPalette(*_internFadePalette);
return needRefresh ? 1 : 0;
}
void Screen::setPaletteIndex(uint8 index, uint8 red, uint8 green, uint8 blue) {
- _currentPalette[index * 3 + 0] = red;
- _currentPalette[index * 3 + 1] = green;
- _currentPalette[index * 3 + 2] = blue;
- setScreenPalette(_currentPalette);
+ getPalette(0)[index * 3 + 0] = red;
+ getPalette(0)[index * 3 + 1] = green;
+ getPalette(0)[index * 3 + 2] = blue;
+ setScreenPalette(getPalette(0));
}
void Screen::getRealPalette(int num, uint8 *dst) {
const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256);
- const uint8 *palData = getPalette(num);
+ const uint8 *palData = getPalette(num).getData();
if (!palData) {
memset(dst, 0, colors * 3);
@@ -469,46 +618,26 @@ void Screen::getRealPalette(int num, uint8 *dst) {
}
for (int i = 0; i < colors; ++i) {
- dst[0] = (palData[0] << 2) | (palData[0] & 3);
- dst[1] = (palData[1] << 2) | (palData[1] & 3);
- dst[2] = (palData[2] << 2) | (palData[2] & 3);
+ dst[0] = (palData[0] * 0xFF) / 0x3F;
+ dst[1] = (palData[1] * 0xFF) / 0x3F;
+ dst[2] = (palData[2] * 0xFF) / 0x3F;
dst += 3;
palData += 3;
}
}
-void Screen::setScreenPalette(const uint8 *palData) {
- const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256);
-
+void Screen::setScreenPalette(const Palette &pal) {
uint8 screenPal[256 * 4];
- if (palData != _screenPalette)
- memcpy(_screenPalette, palData, colors*3);
+ _screenPalette->copy(pal);
- if (_use16ColorMode && _vm->gameFlags().platform == Common::kPlatformPC98) {
- for (int l = 0; l < 1024; l += 64) {
- const uint8 *tp = palData;
- for (int i = 0; i < 16; ++i) {
- screenPal[l + 4 * i + 0] = palData[1];
- screenPal[l + 4 * i + 1] = palData[0];
- screenPal[l + 4 * i + 2] = palData[2];
- screenPal[l + 4 * i + 3] = 0;
- palData += 3;
- }
- palData = tp;
- }
- } else {
- if (palData != _screenPalette)
- memcpy(_screenPalette, palData, colors*3);
- for (int i = 0; i < colors; ++i) {
- screenPal[4 * i + 0] = (palData[0] << 2) | (palData[0] & 3);
- screenPal[4 * i + 1] = (palData[1] << 2) | (palData[1] & 3);
- screenPal[4 * i + 2] = (palData[2] << 2) | (palData[2] & 3);
- screenPal[4 * i + 3] = 0;
- palData += 3;
- }
+ for (int i = 0; i < pal.getNumColors(); ++i) {
+ screenPal[4 * i + 0] = (pal[i * 3 + 0] * 0xFF) / 0x3F;
+ screenPal[4 * i + 1] = (pal[i * 3 + 1] * 0xFF) / 0x3F;
+ screenPal[4 * i + 2] = (pal[i * 3 + 2] * 0xFF) / 0x3F;
+ screenPal[4 * i + 3] = 0;
}
- _system->setPalette(screenPal, 0, colors);
+ _system->setPalette(screenPal, 0, pal.getNumColors());
}
void Screen::copyToPage0(int y, int h, uint8 page, uint8 *seqBuf) {
@@ -656,63 +785,6 @@ void Screen::copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint
}
}
-void Screen::copyFromCurPageBlock(int x, int y, int w, int h, const uint8 *src) {
- if (x < 0)
- x = 0;
- else if (x >= 40)
- return;
-
- if (x + w > 40)
- w = 40 - x;
-
- if (y < 0)
- y = 0;
- else if (y >= 200)
- return;
-
- if (y + h > 200)
- h = 200 - y;
-
- uint8 *dst = getPagePtr(_curPage) + y * SCREEN_W + x * 8;
-
- if (_curPage == 0 || _curPage == 1)
- addDirtyRect(x*8, y, w*8, h);
-
- clearOverlayRect(_curPage, x*8, y, w*8, h);
-
- while (h--) {
- memcpy(dst, src, w*8);
- dst += SCREEN_W;
- src += w*8;
- }
-}
-
-void Screen::copyCurPageBlock(int x, int y, int w, int h, uint8 *dst) {
- assert(dst);
- if (x < 0)
- x = 0;
- else if (x >= 40)
- return;
-
- if (x + w > 40)
- w = 40 - x;
-
- if (y < 0)
- y = 0;
- else if (y >= 200)
- return;
-
- if (y + h > 200)
- h = 200 - y;
-
- const uint8 *src = getPagePtr(_curPage) + y * SCREEN_W + x * 8;
- while (h--) {
- memcpy(dst, src, w*8);
- dst += w*8;
- src += SCREEN_W;
- }
-}
-
void Screen::shuffleScreen(int sx, int sy, int w, int h, int srcPage, int dstPage, int ticks, bool transparent) {
assert(sx >= 0 && w <= SCREEN_W);
int x;
@@ -802,17 +874,26 @@ void Screen::drawBox(int x1, int y1, int x2, int y2, int color) {
drawClippedLine(x1, y2, x2, y2, color);
}
-void Screen::drawShadedBox(int x1, int y1, int x2, int y2, int color1, int color2) {
+void Screen::drawShadedBox(int x1, int y1, int x2, int y2, int color1, int color2, ShadeType shadeType) {
assert(x1 >= 0 && y1 >= 0);
hideMouse();
fillRect(x1, y1, x2, y1 + 1, color1);
- fillRect(x2 - 1, y1, x2, y2, color1);
+ if (shadeType == kShadeTypeLol)
+ fillRect(x1, y1, x1 + 1, y2, color1);
+ else
+ fillRect(x2 - 1, y1, x2, y2, color1);
- drawClippedLine(x1, y1, x1, y2, color2);
- drawClippedLine(x1 + 1, y1 + 1, x1 + 1, y2 - 1, color2);
+ if (shadeType == kShadeTypeLol) {
+ drawClippedLine(x2, y1, x2, y2, color2);
+ drawClippedLine(x2 - 1, y1 + 1, x2 - 1, y2 - 1, color2);
+ drawClippedLine(x1 + 1, y2 - 1, x2, y2 - 1, color2);
+ } else {
+ drawClippedLine(x1, y1, x1, y2, color2);
+ drawClippedLine(x1 + 1, y1 + 1, x1 + 1, y2 - 1, color2);
+ drawClippedLine(x1, y2 - 1, x2 - 1, y2 - 1, color2);
+ }
drawClippedLine(x1, y2, x2, y2, color2);
- drawClippedLine(x1, y2 - 1, x2 - 1, y2 - 1, color2);
showMouse();
}
@@ -909,11 +990,13 @@ bool Screen::loadFont(FontId fontId, const char *filename) {
error("Invalid font data (file '%s', fontSig: %.04X)", filename, fontSig);
fnt->charWidthTable = fontData + READ_LE_UINT16(fontData + 8);
- fnt->charSizeOffset = READ_LE_UINT16(fontData + 4);
+ fnt->fontDescOffset = READ_LE_UINT16(fontData + 4);
fnt->charBitmapOffset = READ_LE_UINT16(fontData + 6);
fnt->charWidthTableOffset = READ_LE_UINT16(fontData + 8);
fnt->charHeightTableOffset = READ_LE_UINT16(fontData + 0xC);
+ fnt->lastGlyph = *(fnt->fontData + fnt->fontDescOffset + 3);
+
return true;
}
@@ -927,23 +1010,30 @@ int Screen::getFontHeight() const {
// FIXME: add font support for amiga version
if (_vm->gameFlags().platform == Common::kPlatformAmiga)
return 0;
- return *(_fonts[_currentFont].fontData + _fonts[_currentFont].charSizeOffset + 4);
+
+ return *(_fonts[_currentFont].fontData + _fonts[_currentFont].fontDescOffset + 4);
}
int Screen::getFontWidth() const {
// FIXME: add font support for amiga version
if (_vm->gameFlags().platform == Common::kPlatformAmiga)
return 0;
- return *(_fonts[_currentFont].fontData + _fonts[_currentFont].charSizeOffset + 5);
+
+ return *(_fonts[_currentFont].fontData + _fonts[_currentFont].fontDescOffset + 5);
}
int Screen::getCharWidth(uint16 c) const {
// FIXME: add font support for amiga version
if (_vm->gameFlags().platform == Common::kPlatformAmiga)
return 0;
+
if (c & 0xFF00)
return SJIS_CHARSIZE >> 1;
- return (int)_fonts[_currentFont].charWidthTable[c] + _charWidth;
+
+ if (_fonts[_currentFont].lastGlyph < c)
+ return 0;
+ else
+ return (int)_fonts[_currentFont].charWidthTable[c] + _charWidth;
}
int Screen::getTextWidth(const char *str) const {
@@ -986,8 +1076,7 @@ void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2
cmap[1] = color1;
setTextColor(cmap, 0, 1);
- Font *fnt = &_fonts[_currentFont];
- const uint8 charHeightFnt = *(fnt->fontData + fnt->charSizeOffset + 4);
+ const uint8 charHeightFnt = getFontHeight();
uint8 charHeight = 0;
if (x < 0)
@@ -1037,6 +1126,10 @@ void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2
void Screen::drawCharANSI(uint8 c, int x, int y) {
Font *fnt = &_fonts[_currentFont];
+
+ if (c > fnt->lastGlyph)
+ return;
+
uint8 *dst = getPagePtr(_curPage) + y * SCREEN_W + x;
uint16 bitmapOffset = READ_LE_UINT16(fnt->fontData + fnt->charBitmapOffset + c * 2);
@@ -1044,15 +1137,16 @@ void Screen::drawCharANSI(uint8 c, int x, int y) {
return;
uint8 charWidth = *(fnt->fontData + fnt->charWidthTableOffset + c);
- if (charWidth + x > SCREEN_W)
+ if (!charWidth || charWidth + x > SCREEN_W)
return;
- uint8 charH0 = *(fnt->fontData + fnt->charSizeOffset + 4);
- if (charH0 + y > SCREEN_H)
+ uint8 charH0 = getFontHeight();
+ if (!charH0 || charH0 + y > SCREEN_H)
return;
uint8 charH1 = *(fnt->fontData + fnt->charHeightTableOffset + c * 2);
uint8 charH2 = *(fnt->fontData + fnt->charHeightTableOffset + c * 2 + 1);
+
charH0 -= charH1 + charH2;
const uint8 *src = fnt->fontData + bitmapOffset;
@@ -1097,15 +1191,17 @@ void Screen::drawCharANSI(uint8 c, int x, int y) {
}
if (_curPage == 0 || _curPage == 1)
- addDirtyRect(x, y, charWidth, *(fnt->fontData + fnt->charSizeOffset + 4));
+ addDirtyRect(x, y, charWidth, getFontHeight());
}
void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...) {
if (!shapeData)
return;
- int f = _vm->gameFlags().useAltShapeHeader ? 2 : 0;
- if (shapeData[f] & 1)
+ if (_vm->gameFlags().useAltShapeHeader)
+ shapeData += 2;
+
+ if (*shapeData & 1)
flags |= 0x400;
va_list args;
@@ -1115,11 +1211,6 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int
1, 3, 2, 5, 4, 3, 2, 1
};
- _drawShapeVar1 = 0;
- _drawShapeVar3 = 1;
- _drawShapeVar4 = 0;
- _drawShapeVar5 = 0;
-
_dsTable = 0;
_dsTableLoopCount = 0;
_dsTable2 = 0;
@@ -1145,8 +1236,8 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int
}
if (flags & 0x200) {
- _drawShapeVar1 += 1;
- _drawShapeVar1 &= 7;
+ ++_drawShapeVar1;
+ _drawShapeVar1 &= (_vm->gameFlags().gameID == GI_KYRA1) ? 0x7 : 0xF;
_drawShapeVar3 = drawShapeVar2[_drawShapeVar1];
_drawShapeVar4 = 0;
_drawShapeVar5 = 256;
@@ -1237,12 +1328,12 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int
int scaleCounterV = 0;
- f = flags & 0x0f;
- _dsProcessMargin = dsMarginFunc[f];
- _dsScaleSkip = dsSkipFunc[f];
- _dsProcessLine = dsLineFunc[f];
+ const int drawFunc = flags & 0x0f;
+ _dsProcessMargin = dsMarginFunc[drawFunc];
+ _dsScaleSkip = dsSkipFunc[drawFunc];
+ _dsProcessLine = dsLineFunc[drawFunc];
- int ppc = (flags >> 8) & 0x3F;
+ const int ppc = (flags >> 8) & 0x3F;
_dsPlot = dsPlotFunc[ppc];
DsPlotFunc dsPlot2 = dsPlotFunc[ppc], dsPlot3 = dsPlotFunc[ppc];
if (flags & 0x800)
@@ -1274,8 +1365,6 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int
int y2 = y1 + dsDim->h;
- if (_vm->gameFlags().useAltShapeHeader)
- src += 2;
uint16 shapeFlags = READ_LE_UINT16(src); src += 2;
int shapeHeight = *src++;
@@ -1318,8 +1407,6 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int
int t = (flags & 2) ? y2 - y - shapeHeight : y - y1;
- const uint8 *s = src;
-
if (t < 0) {
shapeHeight += t;
if (shapeHeight <= 0) {
@@ -1328,23 +1415,29 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int
}
t *= -1;
- uint8 *tmp = dst;
+ const uint8 *srcBackUp = 0;
do {
_dsOffscreenScaleVal1 = 0;
+ srcBackUp = src;
_dsTmpWidth = shapeWidth;
+
int cnt = shapeWidth;
- (this->*_dsScaleSkip)(tmp, s, cnt);
+ (this->*_dsScaleSkip)(dst, src, cnt);
+
scaleCounterV += _dsScaleH;
- if (!(scaleCounterV & 0xff00))
- continue;
- uint8 r = scaleCounterV >> 8;
- scaleCounterV &= 0xff;
- t -= r;
- } while (t > 0);
-
- if (t < 0)
+
+ if (scaleCounterV & 0xFF00) {
+ uint8 r = scaleCounterV >> 8;
+ scaleCounterV &= 0xFF;
+ t -= r;
+ }
+ } while (!(scaleCounterV & 0xFF00) && (t > 0));
+
+ if (t < 0) {
+ src = srcBackUp;
scaleCounterV += (-t << 8);
+ }
if (!(flags & 2))
y = y1;
@@ -1409,6 +1502,9 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int
_dsOffscreenLeft /= _dsScaleW;
}
+ if (shapeHeight <= 0 || shpWidthScaled1 <= 0)
+ return;
+
if (pageNum == 0 || pageNum == 1)
addDirtyRect(x, y, shpWidthScaled1, shapeHeight);
clearOverlayRect(pageNum, x, y, shpWidthScaled1, shapeHeight);
@@ -1422,28 +1518,28 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int
if (!(scaleCounterV & 0xFF00)) {
_dsTmpWidth = shapeWidth;
int cnt = shapeWidth;
- (this->*_dsScaleSkip)(d, s, cnt);
+ (this->*_dsScaleSkip)(d, src, cnt);
}
}
- const uint8 *b_src = s;
+ const uint8 *b_src = src;
do {
- s = b_src;
+ src = b_src;
_dsTmpWidth = shapeWidth;
int cnt = _dsOffscreenLeft;
- int scaleState = (this->*_dsProcessMargin)(d, s, cnt);
+ int scaleState = (this->*_dsProcessMargin)(d, src, cnt);
if (_dsTmpWidth) {
cnt += shpWidthScaled1;
if (cnt > 0) {
if (flags & 0x800)
normalPlot = (curY > _maskMinY && curY < _maskMaxY);
_dsPlot = normalPlot ? dsPlot2 : dsPlot3;
- (this->*_dsProcessLine)(d, s, cnt, scaleState);
+ (this->*_dsProcessLine)(d, src, cnt, scaleState);
}
cnt += _dsOffscreenRight;
if (cnt)
- (this->*_dsScaleSkip)(d, s, cnt);
+ (this->*_dsScaleSkip)(d, src, cnt);
}
dst += dsPitch;
d = dst;
@@ -2492,9 +2588,14 @@ void Screen::hideMouse() {
}
void Screen::showMouse() {
- if (_mouseLockCount == 1)
+ if (_mouseLockCount == 1) {
CursorMan.showMouse(true);
+ // We need to call OSystem::updateScreen here, else the mouse cursor
+ // will only be visible on mouse movment.
+ _system->updateScreen();
+ }
+
if (_mouseLockCount > 0)
_mouseLockCount--;
}
@@ -2531,12 +2632,11 @@ void Screen::setMouseCursor(int x, int y, const byte *shape) {
y <<= 1;
mouseWidth <<= 1;
mouseHeight <<= 1;
- fillRect(mouseWidth, 0, mouseWidth, mouseHeight, 0, 8);
}
uint8 *cursor = new uint8[mouseHeight * mouseWidth];
- fillRect(0, 0, mouseWidth, mouseHeight, 0, 8);
+ fillRect(0, 0, mouseWidth, mouseHeight, _cursorColorKey, 8);
drawShape(8, shape, 0, 0, 0, 0);
int xOffset = 0;
@@ -2544,11 +2644,14 @@ void Screen::setMouseCursor(int x, int y, const byte *shape) {
if (_vm->gameFlags().useHiResOverlay) {
xOffset = mouseWidth;
scale2x(getPagePtr(8) + mouseWidth, SCREEN_W, getPagePtr(8), SCREEN_W, mouseWidth, mouseHeight);
+ postProcessCursor(getPagePtr(8) + mouseWidth, mouseWidth, mouseHeight, SCREEN_W);
+ } else {
+ postProcessCursor(getPagePtr(8), mouseWidth, mouseHeight, SCREEN_W);
}
CursorMan.showMouse(false);
copyRegionToBuffer(8, xOffset, 0, mouseWidth, mouseHeight, cursor);
- CursorMan.replaceCursor(cursor, mouseWidth, mouseHeight, x, y, 0);
+ CursorMan.replaceCursor(cursor, mouseWidth, mouseHeight, x, y, _cursorColorKey);
if (isMouseVisible())
CursorMan.showMouse(true);
delete[] cursor;
@@ -2560,12 +2663,13 @@ void Screen::setMouseCursor(int x, int y, const byte *shape) {
_system->updateScreen();
}
-uint8 *Screen::getPalette(int num) {
- assert(num >= 0 && num < (_vm->gameFlags().platform == Common::kPlatformAmiga ? 6 : 4));
- if (num == 0)
- return _currentPalette;
+Palette &Screen::getPalette(int num) {
+ assert(num >= 0 && (uint)num < _palettes.size());
+ return *_palettes[num];
+}
- return _palettes[num-1];
+void Screen::copyPalette(const int dst, const int src) {
+ getPalette(dst).copy(getPalette(src));
}
byte Screen::getShapeFlag1(int x, int y) {
@@ -2685,7 +2789,7 @@ void Screen::shakeScreen(int times) {
}
}
-void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, uint8 *palData, bool skip) {
+void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, Palette *pal, bool skip) {
uint32 fileSize;
uint8 *srcData = _vm->resource()->fileData(filename, &fileSize);
@@ -2702,9 +2806,8 @@ void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, uint8 *
uint32 imgSize = scumm_stricmp(ext, "CMP") ? READ_LE_UINT32(srcData + 4) : READ_LE_UINT16(srcData);
uint16 palSize = READ_LE_UINT16(srcData + 8);
- if (palData && palSize) {
- loadPalette(srcData + 10, palData, palSize);
- }
+ if (pal && palSize)
+ loadPalette(srcData + 10, *pal, palSize);
uint8 *srcPtr = srcData + 10 + palSize;
uint8 *dstData = getPagePtr(dstPage);
@@ -2738,38 +2841,62 @@ void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, uint8 *
delete[] srcData;
}
-bool Screen::loadPalette(const char *filename, uint8 *palData) {
- uint32 fileSize = 0;
- uint8 *srcData = _vm->resource()->fileData(filename, &fileSize);
- if (!srcData)
+bool Screen::loadPalette(const char *filename, Palette &pal) {
+ Common::SeekableReadStream *stream = _vm->resource()->createReadStream(filename);
+
+ if (!stream)
return false;
- if (palData && fileSize) {
- loadPalette(srcData, palData, fileSize);
- }
- delete[] srcData;
+ debugC(3, kDebugLevelScreen, "Screen::loadPalette('%s', %p)", filename, (const void *)&pal);
+
+ if (_vm->gameFlags().platform == Common::kPlatformAmiga)
+ pal.loadAmigaPalette(*stream, 0, stream->size() / Palette::kAmigaBytesPerColor);
+ else if (_vm->gameFlags().platform == Common::kPlatformPC98 && _use16ColorMode)
+ pal.loadPC98Palette(*stream, 0, stream->size() / Palette::kPC98BytesPerColor);
+ else
+ pal.loadVGAPalette(*stream, 0, stream->size() / Palette::kVGABytesPerColor);
+
+ delete stream;
return true;
}
-void Screen::loadPalette(const byte *data, uint8 *palData, int bytes) {
+bool Screen::loadPaletteTable(const char *filename, int firstPalette) {
+ Common::SeekableReadStream *stream = _vm->resource()->createReadStream(filename);
+
+ if (!stream)
+ return false;
+
+ debugC(3, kDebugLevelScreen, "Screen::loadPaletteTable('%s', %d)", filename, firstPalette);
+
if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
- assert(bytes % 2 == 0);
- assert(bytes / 2 <= 256);
- bytes >>= 1;
- const uint16 *src = (const uint16 *)data;
- for (int i = 0; i < bytes; ++i) {
- uint16 col = READ_BE_UINT16(src); ++src;
- palData[2] = (col & 0xF) << 2; col >>= 4;
- palData[1] = (col & 0xF) << 2; col >>= 4;
- palData[0] = (col & 0xF) << 2; col >>= 4;
- palData += 3;
- }
- } else if (_use16ColorMode) {
- for (int i = 0; i < bytes; ++i)
- palData[i] = ((data[i] & 0xF) << 4) | (data[i] & 0xF0);
+ const int numColors = getPalette(firstPalette).getNumColors();
+ const int palSize = getPalette(firstPalette).getNumColors() * Palette::kAmigaBytesPerColor;
+ const int numPals = stream->size() / palSize;
+
+ for (int i = 0; i < numPals; ++i)
+ getPalette(i + firstPalette).loadAmigaPalette(*stream, 0, numColors);
} else {
- memcpy(palData, data, bytes);
+ const int numColors = getPalette(firstPalette).getNumColors();
+ const int palSize = getPalette(firstPalette).getNumColors() * Palette::kVGABytesPerColor;
+ const int numPals = stream->size() / palSize;
+
+ for (int i = 0; i < numPals; ++i)
+ getPalette(i + firstPalette).loadVGAPalette(*stream, 0, numColors);
}
+
+ delete stream;
+ return true;
+}
+
+void Screen::loadPalette(const byte *data, Palette &pal, int bytes) {
+ Common::MemoryReadStream stream(data, bytes, false);
+
+ if (_vm->gameFlags().platform == Common::kPlatformAmiga)
+ pal.loadAmigaPalette(stream, 0, stream.size() / Palette::kAmigaBytesPerColor);
+ else if (_vm->gameFlags().platform == Common::kPlatformPC98 && _use16ColorMode)
+ pal.loadPC98Palette(stream, 0, stream.size() / Palette::kPC98BytesPerColor);
+ else
+ pal.loadVGAPalette(stream, 0, stream.size() / Palette::kVGABytesPerColor);
}
// dirty rect handling
@@ -2967,8 +3094,17 @@ int SJIStoFMTChunk(int f, int s) { // copied from scumm\charset.cpp
} // end of anonymous namespace
void Screen::drawCharSJIS(uint16 c, int x, int y) {
- int color1 = _textColorsMap[1];
- int color2 = _textColorsMap[0];
+ int color1, color2;
+
+ if (_use16ColorMode) {
+ // PC98 16 color games specify a color value which is for the
+ // PC98 text mode palette, thus we need to remap it.
+ color1 = ((_textColorsMap[1] >> 5) & 0x7) + 16;
+ color2 = ((_textColorsMap[0] >> 5) & 0x7) + 16;
+ } else {
+ color1 = _textColorsMap[1];
+ color2 = _textColorsMap[0];
+ }
memset(_sjisTempPage2, _sjisInvisibleColor, 324);
memset(_sjisSourceChar, 0, 36);
@@ -3139,5 +3275,102 @@ void Screen::drawCharSJIS(uint16 c, int x, int y) {
#pragma mark -
+Palette::Palette(const int numColors) : _palData(0), _numColors(numColors) {
+ _palData = new uint8[numColors * 3];
+ assert(_palData);
+
+ memset(_palData, 0, numColors * 3);
+}
+
+Palette::~Palette() {
+ delete[] _palData;
+ _palData = 0;
+}
+
+void Palette::loadVGAPalette(Common::ReadStream &stream, int startIndex, int colors) {
+ assert(startIndex + colors <= _numColors);
+
+ stream.read(_palData + startIndex * 3, colors * 3);
+}
+
+void Palette::loadAmigaPalette(Common::ReadStream &stream, int startIndex, int colors) {
+ assert(startIndex + colors <= _numColors);
+
+ for (int i = 0; i < colors; ++i) {
+ uint16 col = stream.readUint16BE();
+ _palData[(i + startIndex) * 3 + 2] = ((col & 0xF) * 0xFF) / 0x3F; col >>= 4;
+ _palData[(i + startIndex) * 3 + 1] = ((col & 0xF) * 0xFF) / 0x3F; col >>= 4;
+ _palData[(i + startIndex) * 3 + 0] = ((col & 0xF) * 0xFF) / 0x3F; col >>= 4;
+ }
+}
+
+void Palette::loadPC98Palette(Common::ReadStream &stream, int startIndex, int colors) {
+ assert(startIndex + colors <= _numColors);
+
+ for (int i = 0; i < colors; ++i) {
+ const byte g = stream.readByte(), r = stream.readByte(), b = stream.readByte();
+
+ _palData[(i + startIndex) * 3 + 0] = ((r & 0x0F) * 0x3F) / 0x0F;
+ _palData[(i + startIndex) * 3 + 1] = ((g & 0x0F) * 0x3F) / 0x0F;
+ _palData[(i + startIndex) * 3 + 2] = ((b & 0x0F) * 0x3F) / 0x0F;
+ }
+}
+
+void Palette::clear() {
+ memset(_palData, 0, _numColors * 3);
+}
+
+void Palette::fill(int firstCol, int numCols, uint8 value) {
+ assert(firstCol >= 0 && firstCol + numCols <= _numColors);
+
+ memset(_palData + firstCol * 3, CLIP<int>(value, 0, 63), numCols * 3);
+}
+
+void Palette::copy(const Palette &source, int firstCol, int numCols, int dstStart) {
+ if (numCols == -1)
+ numCols = MIN(source.getNumColors(), _numColors) - firstCol;
+ if (dstStart == -1)
+ dstStart = firstCol;
+
+ assert(numCols >= 0 && numCols <= _numColors);
+ assert(firstCol >= 0 && firstCol <= source.getNumColors());
+ assert(dstStart >= 0 && dstStart + numCols <= _numColors);
+
+ memcpy(_palData + dstStart * 3, source._palData + firstCol * 3, numCols * 3);
+}
+
+void Palette::copy(const uint8 *source, int firstCol, int numCols, int dstStart) {
+ if (source == _palData)
+ return;
+
+ if (dstStart == -1)
+ dstStart = firstCol;
+
+ assert(numCols >= 0 && numCols <= _numColors);
+ assert(firstCol >= 0);
+ assert(dstStart >= 0 && dstStart + numCols <= _numColors);
+
+ memcpy(_palData + dstStart * 3, source + firstCol * 3, numCols * 3);
+}
+
+uint8 *Palette::fetchRealPalette() const {
+ uint8 *buffer = new uint8[_numColors * 3];
+ assert(buffer);
+
+ uint8 *dst = buffer;
+ const uint8 *palData = _palData;
+
+ for (int i = 0; i < _numColors; ++i) {
+ dst[0] = (palData[0] << 2) | (palData[0] & 3);
+ dst[1] = (palData[1] << 2) | (palData[1] & 3);
+ dst[2] = (palData[2] << 2) | (palData[2] & 3);
+
+ dst += 3;
+ palData += 3;
+ }
+
+ return buffer;
+}
+
} // End of namespace Kyra
diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h
index 1691c73a90..390d058bb8 100644
--- a/engines/kyra/screen.h
+++ b/engines/kyra/screen.h
@@ -29,7 +29,9 @@
#include "common/util.h"
#include "common/func.h"
#include "common/list.h"
+#include "common/array.h"
#include "common/rect.h"
+#include "common/stream.h"
class OSystem;
@@ -53,10 +55,112 @@ struct ScreenDim {
struct Font {
uint8 *fontData;
uint8 *charWidthTable;
- uint16 charSizeOffset;
+ uint16 fontDescOffset;
uint16 charBitmapOffset;
uint16 charWidthTableOffset;
uint16 charHeightTableOffset;
+
+ uint8 lastGlyph;
+};
+
+/**
+ * A class that manages KYRA palettes.
+ *
+ * This class stores the palette data as VGA RGB internally.
+ */
+class Palette {
+public:
+ Palette(const int numColors);
+ ~Palette();
+
+ enum {
+ kVGABytesPerColor = 3,
+ kPC98BytesPerColor = 3,
+ kAmigaBytesPerColor = 2
+ };
+
+ /**
+ * Load a VGA palette from the given stream.
+ */
+ void loadVGAPalette(Common::ReadStream &stream, int startIndex, int colors);
+
+ /**
+ * Load a AMIGA palette from the given stream.
+ */
+ void loadAmigaPalette(Common::ReadStream &stream, int startIndex, int colors);
+
+ /**
+ * Load a PC98 16 color palette from the given stream.
+ */
+ void loadPC98Palette(Common::ReadStream &stream, int startIndex, int colors);
+
+ /**
+ * Return the number of colors this palette manages.
+ */
+ int getNumColors() const { return _numColors; }
+
+ /**
+ * Set all palette colors to black.
+ */
+ void clear();
+
+ /**
+ * Fill the given indexes with the given component value.
+ *
+ * @param firstCol the first color, which should be overwritten.
+ * @param numCols number of colors, which schould be overwritten.
+ * @param value color component value, which should be stored.
+ */
+ void fill(int firstCol, int numCols, uint8 value);
+
+ /**
+ * Copy data from another palette.
+ *
+ * @param source palette to copy data from.
+ * @param firstCol the first color of the source which should be copied.
+ * @param numCols number of colors, which should be copied. -1 all remaining colors.
+ * @param dstStart the first color, which should be ovewritten. If -1 firstCol will be used as start.
+ */
+ void copy(const Palette &source, int firstCol = 0, int numCols = -1, int dstStart = -1);
+
+ /**
+ * Copy data from a raw VGA palette.
+ *
+ * @param source source buffer
+ * @param firstCol the first color of the source which should be copied.
+ * @param numCols number of colors, which should be copied.
+ * @param dstStart the first color, which should be ovewritten. If -1 firstCol will be used as start.
+ */
+ void copy(const uint8 *source, int firstCol, int numCols, int dstStart = -1);
+
+ /**
+ * Fetch a RGB palette.
+ *
+ * @return a pointer to the RGB palette data, the client must delete[] it.
+ */
+ uint8 *fetchRealPalette() const;
+
+ //XXX
+ uint8 &operator[](const int index) {
+ assert(index >= 0 && index <= _numColors * 3);
+ return _palData[index];
+ }
+
+ const uint8 &operator[](const int index) const {
+ assert(index >= 0 && index <= _numColors * 3);
+ return _palData[index];
+ }
+
+ /**
+ * Gets raw access to the palette.
+ *
+ * TODO: Get rid of this.
+ */
+ uint8 *getData() { return _palData; }
+ const uint8 *getData() const { return _palData; }
+private:
+ uint8 *_palData;
+ const int _numColors;
};
class Screen {
@@ -110,12 +214,11 @@ public:
// page cur. functions
int setCurPage(int pageNum);
-
- void copyFromCurPageBlock(int x, int y, int w, int h, const uint8 *src);
- void copyCurPageBlock(int x, int y, int w, int h, uint8 *dst);
-
void clearCurPage();
+ void copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src,
+ int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2);
+
// page 0 functions
void copyToPage0(int y, int h, uint8 page, uint8 *seqBuf);
void shakeScreen(int times);
@@ -142,21 +245,25 @@ public:
void fadeFromBlack(int delay=0x54, const UpdateFunctor *upFunc = 0);
void fadeToBlack(int delay=0x54, const UpdateFunctor *upFunc = 0);
- void fadePalette(const uint8 *palData, int delay, const UpdateFunctor *upFunc = 0);
- virtual void getFadeParams(const uint8 *palette, int delay, int &delayInc, int &diff);
- int fadePalStep(const uint8 *palette, int diff);
+ virtual void fadePalette(const Palette &pal, int delay, const UpdateFunctor *upFunc = 0);
+ virtual void getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff);
+ virtual int fadePalStep(const Palette &pal, int diff);
void setPaletteIndex(uint8 index, uint8 red, uint8 green, uint8 blue);
- void setScreenPalette(const uint8 *palData);
- const uint8 *getScreenPalette() const { return _screenPalette; }
+ virtual void setScreenPalette(const Palette &pal);
void getRealPalette(int num, uint8 *dst);
- uint8 *getPalette(int num);
+ Palette &getPalette(int num);
+ void copyPalette(const int dst, const int src);
// gui specific (processing on _curPage)
+ enum ShadeType {
+ kShadeTypeKyra,
+ kShadeTypeLol
+ };
void drawLine(bool vertical, int x, int y, int length, int color);
void drawClippedLine(int x1, int y1, int x2, int y2, int color);
- void drawShadedBox(int x1, int y1, int x2, int y2, int color1, int color2);
+ void drawShadedBox(int x1, int y1, int x2, int y2, int color1, int color2, ShadeType shadeType = kShadeTypeKyra);
void drawBox(int x1, int y1, int x2, int y2, int color);
// font/text handling
@@ -199,10 +306,11 @@ public:
void rectClip(int &x, int &y, int w, int h);
// misc
- void loadBitmap(const char *filename, int tempPage, int dstPage, uint8 *palData, bool skip=false);
+ void loadBitmap(const char *filename, int tempPage, int dstPage, Palette *pal, bool skip=false);
- bool loadPalette(const char *filename, uint8 *palData);
- void loadPalette(const byte *data, uint8 *palData, int bytes);
+ bool loadPalette(const char *filename, Palette &pal);
+ bool loadPaletteTable(const char *filename, int firstPalette);
+ void loadPalette(const byte *data, Palette &pal, int bytes);
void setAnimBlockPtr(int size);
@@ -220,7 +328,6 @@ public:
int _charWidth;
int _charOffset;
int _curPage;
- uint8 *_currentPalette;
uint8 *_shapePages[2];
int _maskMinY, _maskMaxY;
FontId _currentFont;
@@ -231,6 +338,7 @@ public:
static uint decodeFrame4(const uint8 *src, uint8 *dst, uint32 dstSize);
static void decodeFrameDelta(uint8 *dst, const uint8 *src, bool noXor = false);
static void decodeFrameDeltaPage(uint8 *dst, const uint8 *src, const int pitch, bool noXor);
+
static void convertAmigaGfx(uint8 *data, int w, int h, bool offscreen = true);
static void convertAmigaMsc(uint8 *data);
@@ -240,7 +348,7 @@ protected:
void updateDirtyRectsOvl();
void scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h);
- void mergeOverlay(int x, int y, int w, int h);
+ virtual void mergeOverlay(int x, int y, int w, int h);
// overlay specific
byte *getOverlayPtr(int pageNum);
@@ -275,8 +383,9 @@ protected:
uint8 *_sjisSourceChar;
uint8 _sjisInvisibleColor;
- uint8 *_screenPalette;
- uint8 *_palettes[6];
+ Palette *_screenPalette;
+ Common::Array<Palette *> _palettes;
+ Palette *_internFadePalette;
Font _fonts[FID_NUM];
uint8 _textColorsMap[16];
@@ -287,7 +396,11 @@ protected:
uint8 *_animBlockPtr;
int _animBlockSize;
+ // mouse handling
int _mouseLockCount;
+ const uint8 _cursorColorKey;
+
+ virtual void postProcessCursor(uint8 *data, int w, int h, int pitch) {};
enum {
kMaxDirtyRects = 50
diff --git a/engines/kyra/screen_hof.cpp b/engines/kyra/screen_hof.cpp
index 206f8beb87..516cb5bc41 100644
--- a/engines/kyra/screen_hof.cpp
+++ b/engines/kyra/screen_hof.cpp
@@ -44,8 +44,8 @@ const ScreenDim *Screen_HoF::getScreenDim(int dim) {
return &_screenDimTable[dim];
}
-void Screen_HoF::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag) {
- uint8 tmpPal[768];
+void Screen_HoF::generateGrayOverlay(const Palette &srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag) {
+ Palette tmpPal(lastColor);
for (int i = 0; i != lastColor; i++) {
if (flag) {
@@ -63,7 +63,7 @@ void Screen_HoF::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, in
}
for (int i = 0; i < lastColor; i++)
- grayOverlay[i] = findLeastDifferentColor(tmpPal + 3 * i, srcPal, lastColor);
+ grayOverlay[i] = findLeastDifferentColor(tmpPal.getData() + 3 * i, srcPal, 0, lastColor);
}
void Screen_HoF::cmpFadeFrameStep(int srcPage, int srcW, int srcH, int srcX, int srcY, int dstPage, int dstW,
diff --git a/engines/kyra/screen_hof.h b/engines/kyra/screen_hof.h
index 088e8b7f55..1c17a424b3 100644
--- a/engines/kyra/screen_hof.h
+++ b/engines/kyra/screen_hof.h
@@ -41,7 +41,7 @@ public:
const ScreenDim *getScreenDim(int dim);
// sequence player
- void generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag);
+ void generateGrayOverlay(const Palette &pal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag);
void cmpFadeFrameStep(int srcPage, int srcW, int srcH, int srcX, int srcY, int dstPage, int dstW, int dstH, int dstX, int dstY, int cmpW, int cmpH, int cmpPage);
void copyPageMemory(int srcPage, int srcPos, int dstPage, int dstPos, int numBytes);
void copyRegionEx(int srcPage, int srcW, int srcH, int dstPage, int dstX,int dstY, int dstW, int dstH, const ScreenDim *d, bool flag = false);
diff --git a/engines/kyra/screen_lok.cpp b/engines/kyra/screen_lok.cpp
index 6d97db2f28..9fdeae1398 100644
--- a/engines/kyra/screen_lok.cpp
+++ b/engines/kyra/screen_lok.cpp
@@ -26,8 +26,9 @@
#include "kyra/kyra_lok.h"
#include "kyra/screen_lok.h"
-namespace Kyra {
+#include "graphics/cursorman.h"
+namespace Kyra {
Screen_LoK::Screen_LoK(KyraEngine_LoK *vm, OSystem *system)
: Screen(vm, system) {
@@ -80,13 +81,15 @@ const ScreenDim *Screen_LoK::getScreenDim(int dim) {
void Screen_LoK::fadeSpecialPalette(int palIndex, int startIndex, int size, int fadeTime) {
assert(_vm->palTable1()[palIndex]);
- assert(_currentPalette);
- uint8 tempPal[768];
- memcpy(tempPal, _currentPalette, 768);
- memcpy(&tempPal[startIndex*3], _vm->palTable1()[palIndex], size*3);
+
+ Palette tempPal(getPalette(0).getNumColors());
+ tempPal.copy(getPalette(0));
+ tempPal.copy(_vm->palTable1()[palIndex], 0, size, startIndex);
+
fadePalette(tempPal, fadeTime*18);
- memcpy(&_currentPalette[startIndex*3], &tempPal[startIndex*3], size*3);
- setScreenPalette(_currentPalette);
+
+ getPalette(0).copy(tempPal, startIndex, size);
+ setScreenPalette(getPalette(0));
_system->updateScreen();
}
@@ -237,4 +240,200 @@ int Screen_LoK::getRectSize(int x, int y) {
return ((x*y) << 3);
}
+#pragma mark -
+
+Screen_LoK_16::Screen_LoK_16(KyraEngine_LoK *vm, OSystem *system) : Screen_LoK(vm, system) {
+ memset(_paletteDither, 0, sizeof(_paletteDither));
+}
+
+void Screen_LoK_16::setScreenPalette(const Palette &pal) {
+ _screenPalette->copy(pal);
+
+ for (int i = 0; i < 256; ++i)
+ paletteMap(i, pal[i * 3 + 0] << 2, pal[i * 3 + 1] << 2, pal[i * 3 + 2] << 2);
+
+ set16ColorPalette(_palette16);
+}
+
+void Screen_LoK_16::fadePalette(const Palette &pal, int delay, const UpdateFunctor *upFunc) {
+ uint8 notBlackFlag = 0;
+ for (int i = 0; i < 768; ++i) {
+ if ((*_screenPalette)[i])
+ notBlackFlag |= 1;
+ if (pal[i])
+ notBlackFlag |= 2;
+ }
+
+ if (notBlackFlag == 1 || notBlackFlag == 2) {
+ bool upFade = false;
+
+ for (int i = 0; i < 768; ++i) {
+ if ((*_screenPalette)[i] < pal[i]) {
+ upFade = true;
+ break;
+ }
+ }
+
+ if (upFade) {
+ for (int i = 0; i < 256; ++i)
+ paletteMap(i, pal[i * 3 + 0] << 2, pal[i * 3 + 1] << 2, pal[i * 3 + 2] << 2);
+ _forceFullUpdate = true;
+ }
+
+ uint8 color16Palette[16 * 3];
+
+ if (upFade)
+ memset(color16Palette, 0, sizeof(color16Palette));
+ else
+ memcpy(color16Palette, _palette16, sizeof(color16Palette));
+
+ set16ColorPalette(color16Palette);
+ updateScreen();
+
+ for (int i = 0; i < 16; ++i) {
+ set16ColorPalette(color16Palette);
+
+ for (int k = 0; k < 48; ++k) {
+ if (upFade) {
+ if (color16Palette[k] < _palette16[k])
+ ++color16Palette[k];
+ } else {
+ if (color16Palette[k] > 0)
+ --color16Palette[k];
+ }
+ }
+
+ if (upFunc && upFunc->isValid())
+ (*upFunc)();
+ else
+ _system->updateScreen();
+
+ _vm->delay((delay >> 5) * _vm->tickLength());
+ }
+ }
+
+ setScreenPalette(pal);
+}
+
+void Screen_LoK_16::getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff) {
+ error("Screen_LoK_16::getFadeParams called");
+}
+
+int Screen_LoK_16::fadePalStep(const Palette &pal, int diff) {
+ error("Screen_LoK_16::fadePalStep called");
+ return 0;
+}
+
+void Screen_LoK_16::paletteMap(uint8 idx, int r, int g, int b) {
+ const int red = r;
+ const int green = g;
+ const int blue = b;
+
+ uint16 rgbDiff = 1000;
+ int rDiff = 0, gDiff = 0, bDiff = 0;
+
+ int index1 = -1;
+
+ for (int i = 0; i < 16; ++i) {
+ const int realR = _palette16[i * 3 + 0] << 4;
+ const int realG = _palette16[i * 3 + 1] << 4;
+ const int realB = _palette16[i * 3 + 2] << 4;
+
+ uint16 diff = ABS(r - realR) + ABS(g - realG) + ABS(b - realB);
+
+ if (diff < rgbDiff) {
+ rgbDiff = diff;
+ index1 = i;
+
+ rDiff = r - realR;
+ gDiff = g - realG;
+ bDiff = b - realB;
+ }
+ }
+
+ r = rDiff / 4 + red;
+ g = gDiff / 4 + green;
+ b = bDiff / 4 + blue;
+
+ rgbDiff = 1000;
+ int index2 = -1;
+
+ for (int i = 0; i < 16; ++i) {
+ const int realR = _palette16[i * 3 + 0] << 4;
+ const int realG = _palette16[i * 3 + 1] << 4;
+ const int realB = _palette16[i * 3 + 2] << 4;
+
+ uint16 diff = ABS(r - realR) + ABS(g - realG) + ABS(b - realB);
+
+ if (diff < rgbDiff) {
+ rgbDiff = diff;
+ index2 = i;
+ }
+ }
+
+ _paletteDither[idx].bestMatch = index1;
+ _paletteDither[idx].invertMatch = index2;
+}
+
+void Screen_LoK_16::convertTo16Colors(uint8 *page, int w, int h, int pitch, int keyColor) {
+ const int rowAdd = pitch * 2 - w;
+
+ uint8 *row1 = page;
+ uint8 *row2 = page + pitch;
+
+ for (int i = 0; i < h; i += 2) {
+ for (int k = 0; k < w; k += 2) {
+ if (keyColor == -1 || keyColor != *row1) {
+ const PaletteDither &dither = _paletteDither[*row1];
+
+ *row1++ = dither.bestMatch;
+ *row1++ = dither.invertMatch;
+ *row2++ = dither.invertMatch;
+ *row2++ = dither.bestMatch;
+ } else {
+ row1 += 2;
+ row2 += 2;
+ }
+ }
+
+ row1 += rowAdd;
+ row2 += rowAdd;
+ }
+}
+
+void Screen_LoK_16::mergeOverlay(int x, int y, int w, int h) {
+ byte *dst = _sjisOverlayPtrs[0] + y * 640 + x;
+
+ // We do a game screen rect to 16 color dithering here. It is
+ // important that we do not dither the overlay, since else the
+ // japanese fonts will look wrong.
+ convertTo16Colors(dst, w, h, 640);
+
+ const byte *src = _sjisOverlayPtrs[1] + y * 640 + x;
+
+ int add = 640 - w;
+
+ while (h--) {
+ for (x = 0; x < w; ++x, ++dst) {
+ byte col = *src++;
+ if (col != _sjisInvisibleColor)
+ *dst = _paletteDither[col].bestMatch;
+ }
+ dst += add;
+ src += add;
+ }
+}
+
+void Screen_LoK_16::set16ColorPalette(const uint8 *pal) {
+ uint8 palette[16 * 4];
+ for (int i = 0; i < 16; ++i) {
+ palette[i * 4 + 0] = (pal[i * 3 + 0] * 0xFF) / 0x0F;
+ palette[i * 4 + 1] = (pal[i * 3 + 1] * 0xFF) / 0x0F;
+ palette[i * 4 + 2] = (pal[i * 3 + 2] * 0xFF) / 0x0F;
+ palette[i * 4 + 3] = 0;
+ }
+
+ _system->setPalette(palette, 0, 16);
+}
+
} // end of namespace Kyra
diff --git a/engines/kyra/screen_lok.h b/engines/kyra/screen_lok.h
index d74da66df5..4eb22df374 100644
--- a/engines/kyra/screen_lok.h
+++ b/engines/kyra/screen_lok.h
@@ -77,6 +77,38 @@ protected:
uint8 *_saveLoadPageOvl[8];
};
+class Screen_LoK_16 : public Screen_LoK {
+public:
+ Screen_LoK_16(KyraEngine_LoK *vm, OSystem *system);
+
+ void setScreenPalette(const Palette &pal);
+
+ void fadePalette(const Palette &pal, int delay, const UpdateFunctor *upFunc = 0);
+ void getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff);
+ int fadePalStep(const Palette &pal, int diff);
+private:
+ void updateDirtyRectsOvl();
+
+ void convertTo16Colors(uint8 *page, int w, int h, int pitch, int keyColor = -1);
+ void postProcessCursor(uint8 *data, int width, int height, int pitch) {
+ convertTo16Colors(data, width, height, pitch, _cursorColorKey);
+ }
+ void mergeOverlay(int x, int y, int w, int h);
+
+ void set16ColorPalette(const uint8 *pal);
+
+ void paletteMap(uint8 idx, int r, int g, int b);
+
+ struct PaletteDither {
+ uint8 bestMatch;
+ uint8 invertMatch;
+ };
+
+ PaletteDither _paletteDither[256];
+
+ static const uint8 _palette16[48];
+};
+
} // end of namespace Kyra
#endif
diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp
index 3f3aef72fe..b9bf9961c5 100644
--- a/engines/kyra/screen_lol.cpp
+++ b/engines/kyra/screen_lol.cpp
@@ -105,7 +105,7 @@ void Screen_LoL::fprintString(const char *format, int x, int y, uint8 col1, uint
va_end(vaList);
if (flags & 1)
- x -= getTextWidth(string) >> 1;
+ x -= (getTextWidth(string) >> 1);
if (flags & 2)
x -= getTextWidth(string);
@@ -144,8 +144,8 @@ void Screen_LoL::fprintStringIntro(const char *format, int x, int y, uint8 c1, u
printText(buffer, x, y, c1, c2);
}
-void Screen_LoL::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors) {
- uint8 tmpPal[768];
+void Screen_LoL::generateGrayOverlay(const Palette &srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors) {
+ Palette tmpPal(lastColor);
for (int i = 0; i != lastColor; i++) {
int v = (((srcPal[3 * i] & 0x3f) * factor) / 0x40) + addR;
@@ -157,11 +157,11 @@ void Screen_LoL::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, in
}
for (int i = 0; i < lastColor; i++)
- grayOverlay[i] = findLeastDifferentColor(tmpPal + 3 * i, srcPal, lastColor, skipSpecialColors);
+ grayOverlay[i] = findLeastDifferentColor(tmpPal.getData() + 3 * i, srcPal, 0, lastColor, skipSpecialColors);
}
-uint8 *Screen_LoL::generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight) {
- if (!srcPal || !ovl)
+uint8 *Screen_LoL::generateLevelOverlay(const Palette &srcPal, uint8 *ovl, int opColor, int weight) {
+ if (!ovl)
return ovl;
if (weight > 255)
@@ -186,7 +186,7 @@ uint8 *Screen_LoL::generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opC
int m = 0x7fff;
int ii = 127;
int x = 1;
- const uint8 *s = srcPal + 3;
+ const uint8 *s = srcPal.getData() + 3;
do {
if (i == x) {
@@ -282,14 +282,13 @@ void Screen_LoL::fadeClearSceneWindow(int delay) {
if (_fadeFlag == 1)
return;
- uint8 *tpal = new uint8[768];
+ Palette tpal(getPalette(0).getNumColors());
+ tpal.copy(getPalette(0), 128);
- memcpy(tpal, _currentPalette, 768);
- memset(tpal, 0, 384);
loadSpecialColors(tpal);
fadePalette(tpal, delay);
+
fillRect(112, 0, 288, 120, 0);
- delete[] tpal;
_fadeFlag = 1;
}
@@ -838,18 +837,18 @@ void Screen_LoL::fadeToBlack(int delay, const UpdateFunctor *upFunc) {
}
void Screen_LoL::fadeToPalette1(int delay) {
- loadSpecialColors(_palettes[0]);
- fadePalette(_palettes[0], delay);
+ loadSpecialColors(getPalette(1));
+ fadePalette(getPalette(1), delay);
_fadeFlag = 0;
}
-void Screen_LoL::loadSpecialColors(uint8 *destPalette) {
- memcpy(destPalette + 0x240, _screenPalette + 0x240, 12);
+void Screen_LoL::loadSpecialColors(Palette &dst) {
+ dst.copy(*_screenPalette, 192, 4);
}
void Screen_LoL::copyColor(int dstColorIndex, int srcColorIndex) {
- uint8 *s = _screenPalette + srcColorIndex * 3;
- uint8 *d = _screenPalette + dstColorIndex * 3;
+ uint8 *s = _screenPalette->getData() + srcColorIndex * 3;
+ uint8 *d = _screenPalette->getData() + dstColorIndex * 3;
memcpy(d, s, 3);
uint8 ci[4];
@@ -862,9 +861,9 @@ void Screen_LoL::copyColor(int dstColorIndex, int srcColorIndex) {
}
bool Screen_LoL::fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedTime, uint32 targetTime) {
- uint8 *dst = _screenPalette + 3 * dstColorIndex;
- uint8 *src = _screenPalette + 3 * srcColorIndex;
- uint8 *p = getPalette(1) + 3 * dstColorIndex;
+ const uint8 *dst = _screenPalette->getData() + 3 * dstColorIndex;
+ const uint8 *src = _screenPalette->getData() + 3 * srcColorIndex;
+ uint8 *p = getPalette(1).getData() + 3 * dstColorIndex;
bool res = false;
@@ -897,22 +896,21 @@ bool Screen_LoL::fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedT
p++;
}
- uint8 tpal[768];
- memcpy(tpal, _screenPalette, 768);
- memcpy(tpal + dstColorIndex * 3, tmpPalEntry, 3);
- setScreenPalette(tpal);
+ _internFadePalette->copy(*_screenPalette);
+ _internFadePalette->copy(tmpPalEntry, 0, 1, dstColorIndex);
+ setScreenPalette(*_internFadePalette);
updateScreen();
return res;
}
bool Screen_LoL::fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime) {
- uint8 tpal[768];
- uint8 *p1 = _palettes[0];
+ Palette &p1 = getPalette(1);
bool res = false;
for (int i = 0; i < 768; i++) {
uint8 out = 0;
+
if (elapsedTime < targetTime) {
int32 d = ((pal2[i] & 0x3f) - (pal1[i] & 0x3f));
if (d)
@@ -925,10 +923,10 @@ bool Screen_LoL::fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, u
res = false;
}
- tpal[i] = out;
+ (*_internFadePalette)[i] = out;
}
- setScreenPalette(tpal);
+ setScreenPalette(*_internFadePalette);
updateScreen();
return res;
@@ -936,7 +934,7 @@ bool Screen_LoL::fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, u
uint8 *Screen_LoL::generateFadeTable(uint8 *dst, uint8 *src1, uint8 *src2, int numTabs) {
if (!src1)
- src1 = _screenPalette;
+ src1 = _screenPalette->getData();
uint8 *p1 = dst;
uint8 *p2 = src1;
@@ -949,14 +947,14 @@ uint8 *Screen_LoL::generateFadeTable(uint8 *dst, uint8 *src1, uint8 *src2, int n
int16 t = 0;
int16 d = 256 / numTabs;
-
+
for (int i = 1; i < numTabs - 1; i++) {
p2 = src1;
p3 = p1;
t += d;
for (int ii = 0; ii < 768; ii++) {
- int val = (((int8)*p3++ * t) >> 8) + (int8)*p2++;
+ int16 val = (((int8)*p3++ * t) >> 8) + (int8)*p2++;
*dst++ = (uint8)val;
}
}
@@ -972,6 +970,45 @@ uint8 Screen_LoL::getShapePaletteSize(const uint8 *shp) {
return shp[10];
}
+void Screen_LoL::mergeOverlay(int x, int y, int w, int h) {
+ // For now we convert to 16 colors on overlay merging. If that gives
+ // any problems, like Screen functionallity not prepared for the
+ // format PC98 16 color uses, we'll need to think of a better way.
+ //
+ // We must do this before merging the overlay, else the font colors
+ // will be wrong.
+ if (_use16ColorMode)
+ convertPC98Gfx(_sjisOverlayPtrs[0] + y * 640 + x, w, h, 640);
+
+ Screen_v2::mergeOverlay(x, y, w, h);
+}
+
+void Screen_LoL::convertPC98Gfx(uint8 *data, int w, int h, int pitch) {
+ while (h--) {
+ for (int i = 0; i < w; ++i) {
+ *data = _paletteConvTable[*data];
+ ++data;
+ }
+
+ data += pitch - w;
+ }
+}
+
+void Screen_LoL::postProcessCursor(uint8 *data, int w, int h, int pitch) {
+ if (!_use16ColorMode)
+ return;
+
+ while (h--) {
+ for (int i = 0; i < w; ++i) {
+ if (*data != _cursorColorKey)
+ *data = _paletteConvTable[*data];
+ ++data;
+ }
+
+ data += pitch - w;
+ }
+}
+
} // end of namespace Kyra
#endif // ENABLE_LOL
diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h
index 017af4ba48..db355977f8 100644
--- a/engines/kyra/screen_lol.h
+++ b/engines/kyra/screen_lol.h
@@ -70,14 +70,14 @@ public:
// palette stuff
void fadeToBlack(int delay=0x54, const UpdateFunctor *upFunc = 0);
void fadeToPalette1(int delay);
- void loadSpecialColors(uint8 *destPalette);
+ void loadSpecialColors(Palette &dst);
void copyColor(int dstColorIndex, int srcColorIndex);
bool fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedTime, uint32 targetTime);
bool fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime);
uint8 *generateFadeTable(uint8 *dst, uint8 *src1, uint8 *src2, int numTabs);
- void generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors);
- uint8 *generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight);
+ void generateGrayOverlay(const Palette &Pal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors);
+ uint8 *generateLevelOverlay(const Palette &Pal, uint8 *ovl, int opColor, int weight);
uint8 *getLevelOverlay(int index) { return _levelOverlays[index]; }
void copyBlockAndApplyOverlay(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl);
@@ -92,6 +92,9 @@ public:
uint8 *_grayOverlay;
int _fadeFlag;
+ // PC98 specific
+ static void convertPC98Gfx(uint8 *data, int w, int h, int pitch);
+
private:
LoLEngine *_vm;
@@ -106,6 +109,10 @@ private:
uint8 *_levelOverlays[8];
+ static const uint8 _paletteConvTable[256];
+ void mergeOverlay(int x, int y, int w, int h);
+ void postProcessCursor(uint8 *data, int width, int height, int pitch);
+
// magic atlas
void calcBoundariesIntern(int dstX, int dstY, int c, int d);
diff --git a/engines/kyra/screen_v2.cpp b/engines/kyra/screen_v2.cpp
index a4e014e8c1..177d7d66dd 100644
--- a/engines/kyra/screen_v2.cpp
+++ b/engines/kyra/screen_v2.cpp
@@ -38,39 +38,38 @@ Screen_v2::~Screen_v2() {
delete[] _wsaFrameAnimBuffer;
}
-uint8 *Screen_v2::generateOverlay(const uint8 *palette, uint8 *buffer, int startColor, uint16 factor) {
- if (!palette || !buffer)
+uint8 *Screen_v2::generateOverlay(const Palette &pal, uint8 *buffer, int startColor, uint16 factor) {
+ if (!buffer)
return buffer;
factor = MIN<uint16>(255, factor);
factor >>= 1;
factor &= 0xFF;
- const byte col1 = palette[startColor * 3 + 0];
- const byte col2 = palette[startColor * 3 + 1];
- const byte col3 = palette[startColor * 3 + 2];
+ const byte col1 = pal[startColor * 3 + 0];
+ const byte col2 = pal[startColor * 3 + 1];
+ const byte col3 = pal[startColor * 3 + 2];
uint8 *dst = buffer;
*dst++ = 0;
for (int i = 1; i != 255; ++i) {
uint8 processedPalette[3];
- const uint8 *src = palette + i*3;
byte col;
- col = *src++;
+ col = pal[i * 3 + 0];
col -= ((((col - col1) * factor) << 1) >> 8) & 0xFF;
processedPalette[0] = col;
- col = *src++;
+ col = pal[i * 3 + 1];
col -= ((((col - col2) * factor) << 1) >> 8) & 0xFF;
processedPalette[1] = col;
- col = *src++;
+ col = pal[i * 3 + 2];
col -= ((((col - col3) * factor) << 1) >> 8) & 0xFF;
processedPalette[2] = col;
- *dst++ = findLeastDifferentColor(processedPalette, palette+3, 255)+1;
+ *dst++ = findLeastDifferentColor(processedPalette, pal, 1, 255) + 1;
}
return buffer;
@@ -90,7 +89,7 @@ void Screen_v2::applyOverlay(int x, int y, int w, int h, int pageNum, const uint
}
}
-int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors, bool skipSpecialColors) {
+int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const Palette &pal, uint8 firstColor, uint16 numColors, bool skipSpecialColors) {
int m = 0x7fff;
int r = 0x101;
@@ -98,11 +97,11 @@ int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *p
if (skipSpecialColors && i >= 0xc0 && i <= 0xc3)
continue;
- int v = paletteEntry[0] - *palette++;
+ int v = paletteEntry[0] - pal[(i + firstColor) * 3 + 0];
int c = v * v;
- v = paletteEntry[1] - *palette++;
+ v = paletteEntry[1] - pal[(i + firstColor) * 3 + 1];
c += (v * v);
- v = paletteEntry[2] - *palette++;
+ v = paletteEntry[2] - pal[(i + firstColor) * 3 + 2];
c += (v * v);
if (c <= m) {
@@ -114,12 +113,11 @@ int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *p
return r;
}
-void Screen_v2::getFadeParams(const uint8 *palette, int delay, int &delayInc, int &diff) {
+void Screen_v2::getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff) {
int maxDiff = 0;
diff = 0;
- int len = _use16ColorMode ? 48 : 768;
- for (int i = 0; i < len; ++i) {
- diff = ABS(palette[i] - _screenPalette[i]);
+ for (int i = 0; i < pal.getNumColors() * 3; ++i) {
+ diff = ABS(pal[i] - (*_screenPalette)[i]);
maxDiff = MAX(maxDiff, diff);
}
@@ -137,148 +135,6 @@ void Screen_v2::getFadeParams(const uint8 *palette, int delay, int &delayInc, in
}
}
-void Screen_v2::copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src,
- int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2) {
- uint8 *dstPtr = getPagePtr(_curPage);
- uint8 *origDst = dstPtr;
-
- const ScreenDim *dim = getScreenDim(dimState);
- int dimX1 = dim->sx << 3;
- int dimX2 = dim->w << 3;
- dimX2 += dimX1;
-
- int dimY1 = dim->sy;
- int dimY2 = dim->h;
- dimY2 += dimY1;
-
- int temp = y - dimY1;
- if (temp < 0) {
- if ((temp += h) <= 0)
- return;
- else {
- SWAP(temp, h);
- y += temp - h;
- src += (temp - h) * w;
- }
- }
-
- temp = dimY2 - y;
- if (temp <= 0)
- return;
-
- if (temp < h)
- h = temp;
-
- int srcOffset = 0;
- temp = x - dimX1;
- if (temp < 0) {
- temp = -temp;
- srcOffset = temp;
- x += temp;
- w -= temp;
- }
-
- int srcAdd = 0;
-
- temp = dimX2 - x;
- if (temp <= 0)
- return;
-
- if (temp < w) {
- SWAP(w, temp);
- temp -= w;
- srcAdd = temp;
- }
-
- dstPtr += y * SCREEN_W + x;
- uint8 *dst = dstPtr;
-
- if (_curPage == 0 || _curPage == 1)
- addDirtyRect(x, y, w, h);
-
- clearOverlayRect(_curPage, x, y, w, h);
-
- temp = h;
- int curY = y;
- while (h--) {
- src += srcOffset;
- ++curY;
- int cW = w;
-
- switch (plotFunc) {
- case 0:
- memcpy(dst, src, cW);
- dst += cW; src += cW;
- break;
-
- case 1:
- while (cW--) {
- uint8 d = *src++;
- uint8 t = unkPtr1[d];
- if (t != 0xFF)
- d = unkPtr2[*dst + (t << 8)];
- *dst++ = d;
- }
- break;
-
- case 4:
- while (cW--) {
- uint8 d = *src++;
- if (d)
- *dst = d;
- ++dst;
- }
- break;
-
- case 5:
- while (cW--) {
- uint8 d = *src++;
- if (d) {
- uint8 t = unkPtr1[d];
- if (t != 0xFF)
- d = unkPtr2[*dst + (t << 8)];
- *dst = d;
- }
- ++dst;
- }
- break;
-
- case 8:
- case 9:
- while (cW--) {
- uint8 d = *src++;
- uint8 t = _shapePages[0][dst - origDst] & 7;
- if (unk1 < t && (curY > _maskMinY && curY < _maskMaxY))
- d = _shapePages[1][dst - origDst];
- *dst++ = d;
- }
- break;
-
- case 12:
- case 13:
- while (cW--) {
- uint8 d = *src++;
- if (d) {
- uint8 t = _shapePages[0][dst - origDst] & 7;
- if (unk1 < t && (curY > _maskMinY && curY < _maskMaxY))
- d = _shapePages[1][dst - origDst];
- *dst++ = d;
- } else {
- d = _shapePages[1][dst - origDst];
- *dst++ = d;
- }
- }
- break;
-
- default:
- break;
- }
-
- dst = (dstPtr += SCREEN_W);
- src += srcAdd;
- }
-}
-
const uint8 *Screen_v2::getPtrToShape(const uint8 *shpFile, int shape) {
uint16 shapes = READ_LE_UINT16(shpFile);
diff --git a/engines/kyra/screen_v2.h b/engines/kyra/screen_v2.h
index 18bac764ec..3aa726334c 100644
--- a/engines/kyra/screen_v2.h
+++ b/engines/kyra/screen_v2.h
@@ -37,17 +37,14 @@ public:
~Screen_v2();
// screen page handling
- void copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src,
- int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2);
-
void checkedPageUpdate(int srcPage, int dstPage);
// palette handling
- uint8 *generateOverlay(const uint8 *palette, uint8 *buffer, int color, uint16 factor);
+ uint8 *generateOverlay(const Palette &pal, uint8 *buffer, int color, uint16 factor);
void applyOverlay(int x, int y, int w, int h, int pageNum, const uint8 *overlay);
- int findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors, bool skipSpecialColors = false);
+ int findLeastDifferentColor(const uint8 *paletteEntry, const Palette &pal, uint8 firstColor, uint16 numColors, bool skipSpecialColors = false);
- virtual void getFadeParams(const uint8 *palette, int delay, int &delayInc, int &diff);
+ virtual void getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff);
// shape handling
uint8 *getPtrToShape(uint8 *shpFile, int shape);
diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp
index 9035708f5e..0473f03591 100644
--- a/engines/kyra/script.cpp
+++ b/engines/kyra/script.cpp
@@ -66,6 +66,42 @@ EMCInterpreter::EMCInterpreter(KyraEngine_v1 *vm) : _vm(vm) {
#undef OPCODE
}
+bool EMCInterpreter::callback(Common::IFFChunk &chunk) {
+ switch (chunk._type) {
+ case MKID_BE('TEXT'):
+ _scriptData->text = new byte[chunk._size];
+ assert(_scriptData->text);
+ if (chunk._stream->read(_scriptData->text, chunk._size) != chunk._size)
+ error("Couldn't read TEXT chunk from file '%s'", _filename);
+ break;
+
+ case MKID_BE('ORDR'):
+ _scriptData->ordr = new uint16[chunk._size >> 1];
+ assert(_scriptData->ordr);
+ if (chunk._stream->read(_scriptData->ordr, chunk._size) != chunk._size)
+ error("Couldn't read ORDR chunk from file '%s'", _filename);
+
+ for (int i = (chunk._size >> 1) - 1; i >= 0; --i)
+ _scriptData->ordr[i] = READ_BE_UINT16(&_scriptData->ordr[i]);
+ break;
+
+ case MKID_BE('DATA'):
+ _scriptData->data = new uint16[chunk._size >> 1];
+ assert(_scriptData->data);
+ if (chunk._stream->read(_scriptData->data, chunk._size) != chunk._size)
+ error("Couldn't read DATA chunk from file '%s'", _filename);
+
+ for (int i = (chunk._size >> 1) - 1; i >= 0; --i)
+ _scriptData->data[i] = READ_BE_UINT16(&_scriptData->data[i]);
+ break;
+
+ default:
+ warning("Unexpected chunk '%s' of size %d found in file '%s'", Common::ID2string(chunk._type), chunk._size, _filename);
+ }
+
+ return false;
+}
+
bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Common::Array<const Opcode*> *opcodes) {
Common::SeekableReadStream *stream = _vm->resource()->createReadStream(filename);
if (!stream) {
@@ -75,47 +111,17 @@ bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Commo
memset(scriptData, 0, sizeof(EMCData));
+ _scriptData = scriptData;
+ _filename = filename;
+
IFFParser iff(*stream);
- Common::IFFChunk *chunk = 0;
-
- while ((chunk = iff.nextChunk()) != 0) {
- switch (chunk->id) {
- case MKID_BE('TEXT'):
- scriptData->text = new byte[chunk->size];
- assert(scriptData->text);
- if (chunk->read(scriptData->text, chunk->size) != chunk->size)
- error("Couldn't read TEXT chunk from file '%s'", filename);
- break;
-
- case MKID_BE('ORDR'):
- scriptData->ordr = new uint16[chunk->size >> 1];
- assert(scriptData->ordr);
- if (chunk->read(scriptData->ordr, chunk->size) != chunk->size)
- error("Couldn't read ORDR chunk from file '%s'", filename);
-
- for (int i = (chunk->size >> 1) - 1; i >= 0; --i)
- scriptData->ordr[i] = READ_BE_UINT16(&scriptData->ordr[i]);
- break;
-
- case MKID_BE('DATA'):
- scriptData->data = new uint16[chunk->size >> 1];
- assert(scriptData->data);
- if (chunk->read(scriptData->data, chunk->size) != chunk->size)
- error("Couldn't read DATA chunk from file '%s'", filename);
-
- for (int i = (chunk->size >> 1) - 1; i >= 0; --i)
- scriptData->data[i] = READ_BE_UINT16(&scriptData->data[i]);
- break;
-
- default:
- warning("Unexpected chunk '%s' of size %d found in file '%s'", Common::ID2string(chunk->id), chunk->size, filename);
- }
- }
+ Common::Functor1Mem< Common::IFFChunk &, bool, EMCInterpreter > c(this, &EMCInterpreter::callback);
+ iff.parse(c);
- if (!scriptData->ordr)
+ if (!_scriptData->ordr)
error("No ORDR chunk found in file: '%s'", filename);
- if (!scriptData->data)
+ if (!_scriptData->data)
error("No DATA chunk found in file: '%s'", filename);
if (stream->err())
@@ -123,10 +129,10 @@ bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Commo
delete stream;
- scriptData->sysFuncs = opcodes;
+ _scriptData->sysFuncs = opcodes;
- strncpy(scriptData->filename, filename, 13);
- scriptData->filename[12] = 0;
+ strncpy(_scriptData->filename, filename, 13);
+ _scriptData->filename[12] = 0;
return true;
}
diff --git a/engines/kyra/script.h b/engines/kyra/script.h
index 88bbe86c4d..862cfb7d97 100644
--- a/engines/kyra/script.h
+++ b/engines/kyra/script.h
@@ -70,7 +70,7 @@ class KyraEngine_v1;
class IFFParser : public Common::IFFParser {
public:
- IFFParser(Common::SeekableReadStream &input) : Common::IFFParser(input) {
+ IFFParser(Common::ReadStream &input) : Common::IFFParser(&input) {
// It seems Westwood missunderstood the 'size' field of the FORM chunk.
//
// For EMC scripts (type EMC2) it's filesize instead of filesize - 8,
@@ -84,9 +84,9 @@ public:
// Both lead to some problems in our IFF parser, either reading after the end
// of file or producing a "Chunk overread" error message. To work around this
// we need to adjust the size field properly.
- if (_typeId == MKID_BE('EMC2'))
+ if (_formType == MKID_BE('EMC2'))
_formChunk.size -= 8;
- else if (_typeId == MKID_BE('AVFS'))
+ else if (_formType == MKID_BE('AVFS'))
_formChunk.size += 4;
}
};
@@ -108,6 +108,11 @@ protected:
KyraEngine_v1 *_vm;
int16 _parameter;
+ const char *_filename;
+ EMCData *_scriptData;
+
+ bool callback(Common::IFFChunk &chunk);
+
typedef void (EMCInterpreter::*OpcodeProc)(EMCState *);
struct OpcodeEntry {
OpcodeProc proc;
diff --git a/engines/kyra/script_hof.cpp b/engines/kyra/script_hof.cpp
index b2a581cece..1b8c1d32b3 100644
--- a/engines/kyra/script_hof.cpp
+++ b/engines/kyra/script_hof.cpp
@@ -146,7 +146,7 @@ int KyraEngine_HoF::o2_meanWhileScene(EMCState *script) {
const char *palfile = stackPosString(1);
_screen->loadBitmap(cpsfile, 3, 3, 0);
- memcpy(_screen->getPalette(2), _screen->_currentPalette, 768);
+ _screen->copyPalette(2, 0);
_screen->loadPalette(palfile, _screen->getPalette(2));
_screen->fillRect(0, 0, 319, 199, 207);
_screen->setScreenPalette(_screen->getPalette(2));
@@ -559,14 +559,14 @@ int KyraEngine_HoF::o2_enableAnimObject(EMCState *script) {
int KyraEngine_HoF::o2_loadPalette384(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_loadPalette384(%p) ('%s')", (const void *)script, stackPosString(0));
- memcpy(_screen->getPalette(1), _screen->getPalette(0), 768);
- _res->loadFileToBuf(stackPosString(0), _screen->getPalette(1), 384);
+ _screen->copyPalette(1, 0);
+ _res->loadFileToBuf(stackPosString(0), _screen->getPalette(1).getData(), 384);
return 0;
}
int KyraEngine_HoF::o2_setPalette384(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_setPalette384(%p) ()", (const void *)script);
- memcpy(_screen->getPalette(0), _screen->getPalette(1), 384);
+ _screen->getPalette(0).copy(_screen->getPalette(1), 0, 128);
_screen->setScreenPalette(_screen->getPalette(0));
return 0;
}
@@ -774,13 +774,13 @@ int KyraEngine_HoF::o2_showLetter(EMCState *script) {
displayInvWsaLastFrame();
backUpPage0();
- memcpy(_screen->getPalette(2), _screen->getPalette(0), 768);
+ _screen->copyPalette(2, 0);
_screen->clearPage(3);
_screen->loadBitmap("_NOTE.CPS", 3, 3, 0);
sprintf(filename, "_NTEPAL%.1d.COL", letter+1);
- _res->loadFileToBuf(filename, _screen->getPalette(0), 768);
+ _screen->loadPalette(filename, _screen->getPalette(0));
_screen->fadeToBlack(0x14);
@@ -819,7 +819,7 @@ int KyraEngine_HoF::o2_showLetter(EMCState *script) {
_screen->hideMouse();
_screen->fadeToBlack(0x14);
restorePage0();
- memcpy(_screen->getPalette(0), _screen->getPalette(2), 768);
+ _screen->copyPalette(0, 2);
_screen->fadePalette(_screen->getPalette(0), 0x14);
setHandItem(_itemInHand);
_screen->showMouse();
@@ -1125,25 +1125,25 @@ int KyraEngine_HoF::o2_resetInputColorCode(EMCState *script) {
int KyraEngine_HoF::o2_mushroomEffect(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_mushroomEffect(%p)", (const void *)script);
- memcpy(_screen->getPalette(2), _screen->_currentPalette, 768);
+ _screen->copyPalette(2, 0);
for (int i = 1; i < 768; i += 3)
- _screen->_currentPalette[i] = 0;
+ _screen->getPalette(0)[i] = 0;
snd_playSoundEffect(106);
- _screen->fadePalette(_screen->_currentPalette, 90, &_updateFunctor);
- memcpy(_screen->_currentPalette, _screen->getPalette(2), 768);
+ _screen->fadePalette(_screen->getPalette(0), 90, &_updateFunctor);
+ _screen->copyPalette(0, 2);
for (int i = 0; i < 768; i += 3) {
- _screen->_currentPalette[i] = _screen->_currentPalette[i + 1] = 0;
- _screen->_currentPalette[i + 2] += (((int8)_screen->_currentPalette[i + 2]) >> 1);
- if (_screen->_currentPalette[i + 2] > 63)
- _screen->_currentPalette[i + 2] = 63;
+ _screen->getPalette(0)[i] = _screen->getPalette(0)[i + 1] = 0;
+ _screen->getPalette(0)[i + 2] += (((int8)_screen->getPalette(0)[i + 2]) >> 1);
+ if (_screen->getPalette(0)[i + 2] > 63)
+ _screen->getPalette(0)[i + 2] = 63;
}
snd_playSoundEffect(106);
- _screen->fadePalette(_screen->_currentPalette, 90, &_updateFunctor);
+ _screen->fadePalette(_screen->getPalette(0), 90, &_updateFunctor);
- memcpy(_screen->_currentPalette, _screen->getPalette(2), 768);
- _screen->fadePalette(_screen->_currentPalette, 30, &_updateFunctor);
+ _screen->copyPalette(0, 2);
+ _screen->fadePalette(_screen->getPalette(0), 30, &_updateFunctor);
return 0;
}
@@ -1262,19 +1262,23 @@ int KyraEngine_HoF::o2_stopSceneAnimation(EMCState *script) {
int KyraEngine_HoF::o2_processPaletteIndex(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_processPaletteIndex(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
- uint8 *palette = _screen->getPalette(0);
+ Palette &palette = _screen->getPalette(0);
+
const int index = stackPos(0);
const bool updatePalette = (stackPos(4) != 0);
const int delayTime = stackPos(5);
+
palette[index*3+0] = (stackPos(1) * 0x3F) / 100;
palette[index*3+1] = (stackPos(2) * 0x3F) / 100;
palette[index*3+2] = (stackPos(3) * 0x3F) / 100;
+
if (updatePalette) {
if (delayTime > 0)
_screen->fadePalette(palette, delayTime, &_updateFunctor);
else
_screen->setScreenPalette(palette);
}
+
return 0;
}
@@ -1396,7 +1400,7 @@ int KyraEngine_HoF::o2_demoFinale(EMCState *script) {
assert(strings);
_screen->clearPage(0);
- _screen->loadPalette("THANKS.COL", _screen->_currentPalette);
+ _screen->loadPalette("THANKS.COL", _screen->getPalette(0));
_screen->loadBitmap("THANKS.CPS", 3, 3, 0);
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0);
@@ -1406,7 +1410,7 @@ int KyraEngine_HoF::o2_demoFinale(EMCState *script) {
for (int i = 0; i < 6; i++)
_text->printText(strings[i], _text->getCenterStringX(strings[i], 1, 319), y + i * 10, 255, 207, 0);
- _screen->setScreenPalette(_screen->_currentPalette);
+ _screen->setScreenPalette(_screen->getPalette(0));
_screen->updateScreen();
_eventList.clear();
diff --git a/engines/kyra/script_lok.cpp b/engines/kyra/script_lok.cpp
index 03a5d4efc1..849c6b776d 100644
--- a/engines/kyra/script_lok.cpp
+++ b/engines/kyra/script_lok.cpp
@@ -231,7 +231,8 @@ int KyraEngine_LoK::o1_fadeSpecialPalette(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_fadeSpecialPalette(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
if (_currentCharacter->sceneId != 45) {
if (stackPos(0) == 13) {
- memcpy(_screen->getPalette(0), _screen->getPalette(0) + 384*3, 32*3);
+ // TODO: Check this!
+ _screen->copyPalette(0, 12);
_screen->setScreenPalette(_screen->getPalette(0));
}
} else {
@@ -427,7 +428,7 @@ int KyraEngine_LoK::o1_runWSAFromBeginningToEnd(EMCState *script) {
int wsaFrame = 0;
while (running) {
- _movieObjects[wsaIndex]->displayFrame(wsaFrame++, 0, xpos, ypos);
+ _movieObjects[wsaIndex]->displayFrame(wsaFrame++, 0, xpos, ypos, 0, 0, 0);
_animator->_updateScreen = true;
if (wsaFrame >= _movieObjects[wsaIndex]->frames())
running = false;
@@ -458,7 +459,7 @@ int KyraEngine_LoK::o1_displayWSAFrame(EMCState *script) {
int waitTime = stackPos(3);
int wsaIndex = stackPos(4);
_screen->hideMouse();
- _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos);
+ _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos, 0, 0, 0);
_animator->_updateScreen = true;
uint32 continueTime = waitTime * _tickLength + _system->getMillis();
while (_system->getMillis() < continueTime) {
@@ -500,7 +501,7 @@ int KyraEngine_LoK::o1_runWSAFrames(EMCState *script) {
_screen->hideMouse();
for (; startFrame <= endFrame; ++startFrame) {
uint32 nextRun = _system->getMillis() + delayTime * _tickLength;
- _movieObjects[wsaIndex]->displayFrame(startFrame, 0, xpos, ypos);
+ _movieObjects[wsaIndex]->displayFrame(startFrame, 0, xpos, ypos, 0, 0, 0);
_animator->_updateScreen = true;
while (_system->getMillis() < nextRun) {
_sprites->updateSceneAnims();
@@ -578,7 +579,7 @@ int KyraEngine_LoK::o1_restoreAllObjectBackgrounds(EMCState *script) {
int KyraEngine_LoK::o1_setCustomPaletteRange(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setCustomPaletteRange(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
- memcpy(_screen->getPalette(1) + stackPos(1)*3, _specialPalettes[stackPos(0)], stackPos(2)*3);
+ _screen->getPalette(1).copy(_specialPalettes[stackPos(0)], 0, stackPos(2), stackPos(1));
return 0;
}
@@ -682,7 +683,7 @@ int KyraEngine_LoK::o1_displayWSAFrameOnHidPage(EMCState *script) {
_screen->hideMouse();
uint32 continueTime = waitTime * _tickLength + _system->getMillis();
- _movieObjects[wsaIndex]->displayFrame(frame, 2, xpos, ypos);
+ _movieObjects[wsaIndex]->displayFrame(frame, 2, xpos, ypos, 0, 0, 0);
_animator->_updateScreen = true;
while (_system->getMillis() < continueTime) {
_sprites->updateSceneAnims();
@@ -753,7 +754,7 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) {
// what shouldn't happen. So we're not updating the screen for this special
// case too.
if (startFrame == 18 && endFrame == 18 && _currentRoom == 45) {
- _movieObjects[wsaIndex]->displayFrame(18, 0, xpos, ypos);
+ _movieObjects[wsaIndex]->displayFrame(18, 0, xpos, ypos, 0, 0, 0);
delay(waitTime * _tickLength);
return 0;
}
@@ -765,7 +766,7 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) {
int frame = startFrame;
while (endFrame >= frame) {
uint32 continueTime = waitTime * _tickLength + _system->getMillis();
- _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos);
+ _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos, 0, 0, 0);
if (waitTime)
_animator->_updateScreen = true;
while (_system->getMillis() < continueTime) {
@@ -783,7 +784,7 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) {
int frame = startFrame;
while (endFrame <= frame) {
uint32 continueTime = waitTime * _tickLength + _system->getMillis();
- _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos);
+ _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos, 0, 0, 0);
if (waitTime)
_animator->_updateScreen = true;
while (_system->getMillis() < continueTime) {
@@ -912,8 +913,6 @@ int KyraEngine_LoK::o1_placeCharacterInOtherScene(EMCState *script) {
int KyraEngine_LoK::o1_getKey(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_getKey(%p) ()", (const void *)script);
- // TODO: Check this implementation
-
while (true) {
delay(10);
@@ -1243,8 +1242,8 @@ int KyraEngine_LoK::o1_setFireberryGlowPalette(EMCState *script) {
palIndex = 14;
}
}
- const uint8 *palette = _specialPalettes[palIndex];
- memcpy(_screen->getPalette(1) + 684, palette, 44);
+
+ _screen->getPalette(1).copy(_specialPalettes[palIndex], 0, 15, 228);
return 0;
}
@@ -1276,7 +1275,7 @@ int KyraEngine_LoK::o1_makeAmuletAppear(EMCState *script) {
if (code == 14)
snd_playSoundEffect(0x73);
- amulet.displayFrame(code, 0, 224, 152);
+ amulet.displayFrame(code, 0, 224, 152, 0, 0, 0);
_animator->_updateScreen = true;
while (_system->getMillis() < nextTime) {
@@ -1501,40 +1500,38 @@ int KyraEngine_LoK::o1_setNoDrawShapesFlag(EMCState *script) {
int KyraEngine_LoK::o1_fadeEntirePalette(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_fadeEntirePalette(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
int cmd = stackPos(0);
- uint8 *fadePal = 0;
+
+ int fadePal = 0;
if (_flags.platform == Common::kPlatformAmiga) {
if (cmd == 0) {
- fadePal = _screen->getPalette(2);
- memset(fadePal, 0, 32*3);
- memcpy(_screen->getPalette(4), _screen->getPalette(0), 32*3);
+ _screen->getPalette(2).clear();
+ fadePal = 2;
+ _screen->copyPalette(4, 0);
} else if (cmd == 1) {
- fadePal = _screen->getPalette(0);
- memcpy(_screen->getPalette(0), _screen->getPalette(4), 32*3);
+ fadePal = 0;
+ _screen->copyPalette(0, 4);
} else if (cmd == 2) {
- fadePal = _screen->getPalette(0);
- memset(_screen->getPalette(2), 0, 32*3);
+ fadePal = 0;
+ _screen->getPalette(2).clear();
}
} else {
if (cmd == 0) {
- fadePal = _screen->getPalette(2);
- uint8 *screenPal = _screen->getPalette(0);
- uint8 *backUpPal = _screen->getPalette(3);
-
- memcpy(backUpPal, screenPal, sizeof(uint8)*768);
- memset(fadePal, 0, sizeof(uint8)*768);
+ fadePal = 2;
+ _screen->getPalette(2).clear();
+ _screen->copyPalette(3, 0);
} else if (cmd == 1) {
- //fadePal = _screen->getPalette(3);
+ //fadePal = 3;
warning("unimplemented o1_fadeEntirePalette function");
return 0;
} else if (cmd == 2) {
- memset(_screen->getPalette(2), 0, 768);
- memcpy(_screen->getPalette(0), _screen->getPalette(1), 768);
- fadePal = _screen->getPalette(0);
+ _screen->getPalette(2).clear();
+ _screen->copyPalette(0, 1);
+ fadePal = 0;
}
}
- _screen->fadePalette(fadePal, stackPos(1));
+ _screen->fadePalette(_screen->getPalette(fadePal), stackPos(1));
return 0;
}
diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp
index 3d57b23181..a606419722 100644
--- a/engines/kyra/script_lol.cpp
+++ b/engines/kyra/script_lol.cpp
@@ -609,7 +609,7 @@ int LoLEngine::olol_fadePalette(EMCState *script) {
int LoLEngine::olol_loadBitmap(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_clearDialogueField(%p) (%s, %d)", (const void *)script, stackPosString(0), stackPos(1));
- _screen->loadBitmap(stackPosString(0), 3, 3, _screen->getPalette(3));
+ _screen->loadBitmap(stackPosString(0), 3, 3, &_screen->getPalette(3));
if (stackPos(1) != 2)
_screen->copyPage(3, stackPos(1));
return 1;
@@ -663,7 +663,7 @@ int LoLEngine::olol_getGlobalVar(EMCState *script) {
case 12:
return _drainMagic;
case 13:
- return _speechFlag;
+ return getVolume(kVolumeSpeech) - 2;
default:
break;
}
@@ -864,7 +864,7 @@ int LoLEngine::olol_fadeClearSceneWindow(EMCState *script) {
int LoLEngine::olol_fadeSequencePalette(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_fadeSequencePalette(%p)", (const void *)script);
- memcpy(_screen->getPalette(3) + 0x180, _screen->_currentPalette + 0x180, 0x180);
+ _screen->getPalette(3).copy(_screen->getPalette(0), 128);
_screen->loadSpecialColors(_screen->getPalette(3));
_screen->fadePalette(_screen->getPalette(3), 10);
_screen->_fadeFlag = 0;
@@ -876,7 +876,7 @@ int LoLEngine::olol_redrawPlayfield(EMCState *script) {
if (_screen->_fadeFlag != 2)
_screen->fadeClearSceneWindow(10);
gui_drawPlayField();
- setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect);
+ setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect);
_screen->_fadeFlag = 0;
return 1;
}
@@ -1276,7 +1276,7 @@ int LoLEngine::olol_getMonsterStat(EMCState *script) {
int LoLEngine::olol_releaseMonsterShapes(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_releaseMonsterShapes(%p)", (const void *)script);
for (int i = 0; i < 3; i++)
- releaseMonsterShapes(i);
+ releaseMonsterShapes(i);
return 0;
}
@@ -1399,17 +1399,17 @@ int LoLEngine::olol_playEndSequence(EMCState *script){
if (_characters[0].id == -9)
c = 1;
else if (_characters[0].id == -5)
- c = 3;
+ c = 3;
else if (_characters[0].id == -1)
c = 2;
while (snd_updateCharacterSpeech())
delay(_tickLength);
-
+
_eventList.clear();
_screen->hideMouse();
- memset(_screen->getPalette(1), 0, 768);
-
+ _screen->getPalette(1).clear();
+
showOutro(c, (_monsterDifficulty == 2));
quitGame();
@@ -1428,7 +1428,7 @@ int LoLEngine::olol_setPaletteBrightness(EMCState *script) {
uint16 old = _brightness;
_brightness = stackPos(0);
if (stackPos(1) == 1)
- setPaletteBrightness(_screen->_currentPalette, stackPos(0), _lampEffect);
+ setPaletteBrightness(_screen->getPalette(0), stackPos(0), _lampEffect);
return old;
}
@@ -1994,10 +1994,16 @@ int LoLEngine::olol_findInventoryItem(EMCState *script) {
return -1;
}
+int LoLEngine::olol_drinkBezelCup(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_drinkBezelCup(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ drinkBezelCup(3 - stackPos(0), stackPos(1));
+ return 1;
+}
+
int LoLEngine::olol_restoreFadePalette(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_restoreFadePalette(%p)", (const void *)script);
- memcpy(_screen->_currentPalette, _screen->getPalette(1), 384);
- _screen->fadePalette(_screen->_currentPalette, 10);
+ _screen->getPalette(0).copy(_screen->getPalette(1), 0, 128);
+ _screen->fadePalette(_screen->getPalette(0), 10);
_screen->_fadeFlag = 0;
return 1;
}
@@ -2095,27 +2101,29 @@ int LoLEngine::olol_increaseSkill(EMCState *script) {
int LoLEngine::olol_paletteFlash(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_paletteFlash(%p) (%d)", (const void *)script, stackPos(0));
- uint8 *s = _screen->getPalette(1);
- uint8 *d = _screen->getPalette(3);
+ Palette &p1 = _screen->getPalette(1);
+ Palette &p2 = _screen->getPalette(3);
+
uint8 ovl[256];
- generateFlashPalette(s, d, stackPos(0));
- _screen->loadSpecialColors(s);
- _screen->loadSpecialColors(d);
+ generateFlashPalette(p1, p2, stackPos(0));
+ _screen->loadSpecialColors(p1);
+ _screen->loadSpecialColors(p2);
if (_smoothScrollModeNormal) {
for (int i = 0; i < 256; i++)
ovl[i] = i;
ovl[1] = 6;
+
_screen->copyRegion(112, 0, 112, 0, 176, 120, 0, 2);
_screen->applyOverlay(112, 0, 176, 120, 0, ovl);
}
- _screen->setScreenPalette(d);
+ _screen->setScreenPalette(p2);
_screen->updateScreen();
delay(2 * _tickLength);
- _screen->setScreenPalette(s);
+ _screen->setScreenPalette(p1);
if (_smoothScrollModeNormal)
_screen->copyRegion(112, 0, 112, 0, 176, 120, 2, 0);
@@ -2126,55 +2134,65 @@ int LoLEngine::olol_paletteFlash(EMCState *script) {
int LoLEngine::olol_restoreMagicShroud(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_restoreMagicShroud(%p)", (const void *)script);
- WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+ WSAMovie_v2 *mov = new WSAMovie_v2(this);
mov->open("DARKLITE.WSA", 2, 0);
if (!mov->opened())
return 0;
_screen->hideMouse();
+ // TODO: This function could need some major cleanup to work with our
+ // new palette code without needless conversions.
uint8 *fadeTab = new uint8[21504];
uint8 *tpal1 = fadeTab;
uint8 *tpal2 = tpal1 + 768;
uint8 *tpal3 = tpal2 + 768;
uint8 *tpal4 = 0;
- _screen->loadPalette("LITEPAL1.COL", tpal1);
+ _res->loadFileToBuf("LITEPAL1.COL", tpal1, 768);
tpal2 = _screen->generateFadeTable(tpal3, 0, tpal1, 21);
- _screen->loadPalette("LITEPAL2.COL", tpal2);
+ _res->loadFileToBuf("LITEPAL2.COL", tpal2, 768);
tpal4 = tpal2;
tpal2 += 768;
- _screen->loadPalette("LITEPAL3.COL", tpal1);
+ _res->loadFileToBuf("LITEPAL3.COL", tpal1, 768);
_screen->generateFadeTable(tpal2, tpal4, tpal1, 4);
+ Palette pal(768);
+
for (int i = 0; i < 21; i++) {
uint32 etime = _system->getMillis() + 20 * _tickLength;
- mov->displayFrame(i, 0, 0, 0, 0);
+ mov->displayFrame(i, 0, 0, 0, 0, 0, 0);
_screen->updateScreen();
- _screen->setScreenPalette(tpal3);
+
+ pal.copy(tpal3, 0, 256);
+ _screen->setScreenPalette(pal);
tpal3 += 768;
+
if (i == 2 || i == 5 || i == 8 || i == 11 || i == 13 || i == 15 || i == 17 || i == 19)
snd_playSoundEffect(95, -1);
delayUntil(etime);
}
+ pal.copy(tpal3, 0, 256);
snd_playSoundEffect(91, -1);
- _screen->fadePalette(tpal3, 300);
+ _screen->fadePalette(pal, 300);
tpal3 += 768;
for (int i = 22; i < 38; i++) {
uint32 etime = _system->getMillis() + 12 * _tickLength;
- mov->displayFrame(i, 0, 0, 0, 0);
+ mov->displayFrame(i, 0, 0, 0, 0, 0, 0);
_screen->updateScreen();
if (i == 22 || i == 24 || i == 28 || i == 32) {
snd_playSoundEffect(131, -1);
- _screen->setScreenPalette(tpal3);
+
+ pal.copy(tpal3, 0, 256);
+ _screen->setScreenPalette(pal);
tpal3 += 768;
}
delayUntil(etime);
}
mov->close();
- delete mov;
+ delete mov;
delete[] fadeTab;
_screen->showMouse();
@@ -2297,7 +2315,7 @@ int LoLEngine::tlol_loadPalette(const TIM *tim, const uint16 *param) {
int LoLEngine::tlol_setupPaletteFadeEx(const TIM *tim, const uint16 *param) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_setupPaletteFadeEx(%p, %p) (%d)", (const void *)tim, (const void *)param, param[0]);
- memcpy(_screen->getPalette(0), _screen->getPalette(1), 768);
+ _screen->copyPalette(0, 1);
_screen->getFadeParams(_screen->getPalette(0), param[0], _tim->_palDelayInc, _tim->_palDiff);
_tim->_palDelayAcc = 0;
@@ -2375,7 +2393,6 @@ int LoLEngine::tlol_setPartyPosition(const TIM *tim, const uint16 *param) {
int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_fadeClearWindow(%p, %p) (%d)", (const void *)tim, (const void *)param, param[0]);
- uint8 *tmp = 0;
switch (param[0]) {
case 0:
@@ -2383,10 +2400,9 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) {
break;
case 1:
- tmp = _screen->getPalette(3);
- memcpy(tmp + 0x180, _screen->_currentPalette + 0x180, 0x180);
- _screen->loadSpecialColors(tmp);
- _screen->fadePalette(tmp, 10);
+ _screen->getPalette(3).copy(_screen->getPalette(0), 128);
+ _screen->loadSpecialColors(_screen->getPalette(3));
+ _screen->fadePalette(_screen->getPalette(3), 10);
_screen->_fadeFlag = 0;
break;
@@ -2395,9 +2411,8 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) {
break;
case 3:
- tmp = _screen->getPalette(3);
- _screen->loadSpecialColors(tmp);
- _screen->fadePalette(tmp, 10);
+ _screen->loadSpecialColors(_screen->getPalette(3));
+ _screen->fadePalette(_screen->getPalette(3), 10);
_screen->_fadeFlag = 0;
break;
@@ -2405,13 +2420,12 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) {
if (_screen->_fadeFlag != 2)
_screen->fadeClearSceneWindow(10);
gui_drawPlayField();
- setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect);
+ setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect);
_screen->_fadeFlag = 0;
break;
case 5:
- tmp = _screen->getPalette(3);
- _screen->loadSpecialColors(tmp);
+ _screen->loadSpecialColors(_screen->getPalette(3));
_screen->fadePalette(_screen->getPalette(1), 10);
_screen->_fadeFlag = 0;
break;
@@ -2511,7 +2525,7 @@ int LoLEngine::tlol_fadeInScene(const TIM *tim, const uint16 *param) {
strcpy(filename, sceneFile);
strcat(filename, ".CPS");
- _screen->loadBitmap(filename, 7, 5, _screen->getPalette(0));
+ _screen->loadBitmap(filename, 7, 5, &_screen->getPalette(0));
filename[0] = 0;
@@ -2547,9 +2561,11 @@ int LoLEngine::tlol_unusedResourceFunc(const TIM *tim, const uint16 *param) {
int LoLEngine::tlol_fadeInPalette(const TIM *tim, const uint16 *param) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_fadeInPalette(%p, %p) (%d, %d)", (const void *)tim, (const void *)param, param[0], param[1]);
const char *bitmap = (const char *)(tim->text + READ_LE_UINT16(tim->text + (param[0]<<1)));
- uint8 palette[768];
- _screen->loadBitmap(bitmap, 3, 3, palette);
- _screen->fadePalette(palette, param[1]);
+
+ Palette pal(_screen->getPalette(0).getNumColors());
+ _screen->loadBitmap(bitmap, 3, 3, &pal);
+ _screen->fadePalette(pal, param[1]);
+
return 1;
}
@@ -2566,7 +2582,7 @@ int LoLEngine::tlol_displayAnimFrame(const TIM *tim, const uint16 *param) {
if (param[1] == 0xFFFF) {
_screen->copyRegion(0, 0, 0, 0, 320, 200, 0, 2, Screen::CR_NO_P_CHECK);
} else {
- anim->wsa->displayFrame(param[1], 2, anim->x, anim->y, 0);
+ anim->wsa->displayFrame(param[1], 2, anim->x, anim->y, 0, 0, 0);
_screen->copyRegion(anim->wsa->xAdd(), anim->wsa->yAdd(), anim->wsa->xAdd(), anim->wsa->yAdd(), anim->wsa->width(), anim->wsa->height(), 2, 0);
}
@@ -2852,7 +2868,7 @@ void LoLEngine::setupOpcodeTable() {
// 0xA8
OpcodeUnImpl();
OpcodeUnImpl();
- OpcodeUnImpl();
+ Opcode(olol_drinkBezelCup);
Opcode(olol_changeItemTypeOrFlag);
// 0xAC
diff --git a/engines/kyra/script_mr.cpp b/engines/kyra/script_mr.cpp
index 558d703f15..1800bd1939 100644
--- a/engines/kyra/script_mr.cpp
+++ b/engines/kyra/script_mr.cpp
@@ -381,13 +381,10 @@ int KyraEngine_MR::o3_checkInRect(EMCState *script) {
y += desc[1];
}
- if (x >= x1 && x <= x2 && y >= y1 && y <= y2) {
- //XXX
+ if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
return 1;
- } else {
- //XXX
+ else
return 0;
- }
}
int KyraEngine_MR::o3_updateConversations(EMCState *script) {
diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp
index e9ca23a4c9..424a62aaf8 100644
--- a/engines/kyra/script_tim.cpp
+++ b/engines/kyra/script_tim.cpp
@@ -116,6 +116,33 @@ TIMInterpreter::~TIMInterpreter() {
delete[] _animations;
}
+bool TIMInterpreter::callback(Common::IFFChunk &chunk) {
+ switch (chunk._type) {
+ case MKID_BE('TEXT'):
+ _tim->text = new byte[chunk._size];
+ assert(_tim->text);
+ if (chunk._stream->read(_tim->text, chunk._size) != chunk._size)
+ error("Couldn't read TEXT chunk from file '%s'", _filename);
+ break;
+
+ case MKID_BE('AVTL'):
+ _avtlChunkSize = chunk._size >> 1;
+ _tim->avtl = new uint16[_avtlChunkSize];
+ assert(_tim->avtl);
+ if (chunk._stream->read(_tim->avtl, chunk._size) != chunk._size)
+ error("Couldn't read AVTL chunk from file '%s'", _filename);
+
+ for (int i = _avtlChunkSize - 1; i >= 0; --i)
+ _tim->avtl[i] = READ_LE_UINT16(&_tim->avtl[i]);
+ break;
+
+ default:
+ warning("Unexpected chunk '%s' of size %d found in file '%s'", Common::ID2string(chunk._type), chunk._size, _filename);
+ }
+
+ return false;
+}
+
TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpcode *> *opcodes) {
if (!_vm->resource()->exists(filename))
return 0;
@@ -124,44 +151,21 @@ TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpc
if (!stream)
error("Couldn't open TIM file '%s'", filename);
- IFFParser iff(*stream);
- Common::IFFChunk *chunk = 0;
-
- TIM *tim = new TIM;
- assert(tim);
- memset(tim, 0, sizeof(TIM));
+ _avtlChunkSize = 0;
+ _filename = filename;
- tim->procFunc = -1;
- tim->opcodes = opcodes;
+ _tim = new TIM;
+ assert(_tim);
+ memset(_tim, 0, sizeof(TIM));
- int avtlChunkSize = 0;
-
- while ((chunk = iff.nextChunk()) != 0) {
- switch (chunk->id) {
- case MKID_BE('TEXT'):
- tim->text = new byte[chunk->size];
- assert(tim->text);
- if (chunk->read(tim->text, chunk->size) != chunk->size)
- error("Couldn't read TEXT chunk from file '%s'", filename);
- break;
-
- case MKID_BE('AVTL'):
- avtlChunkSize = chunk->size >> 1;
- tim->avtl = new uint16[avtlChunkSize];
- assert(tim->avtl);
- if (chunk->read(tim->avtl, chunk->size) != chunk->size)
- error("Couldn't read AVTL chunk from file '%s'", filename);
-
- for (int i = avtlChunkSize - 1; i >= 0; --i)
- tim->avtl[i] = READ_LE_UINT16(&tim->avtl[i]);
- break;
+ _tim->procFunc = -1;
+ _tim->opcodes = opcodes;
- default:
- warning("Unexpected chunk '%s' of size %d found in file '%s'", Common::ID2string(chunk->id), chunk->size, filename);
- }
- }
+ IFFParser iff(*stream);
+ Common::Functor1Mem< Common::IFFChunk &, bool, TIMInterpreter > c(this, &TIMInterpreter::callback);
+ iff.parse(c);
- if (!tim->avtl)
+ if (!_tim->avtl)
error("No AVTL chunk found in file: '%s'", filename);
if (stream->err())
@@ -169,17 +173,17 @@ TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpc
delete stream;
- int num = (avtlChunkSize < TIM::kCountFuncs) ? avtlChunkSize : (int)TIM::kCountFuncs;
+ int num = (_avtlChunkSize < TIM::kCountFuncs) ? _avtlChunkSize : (int)TIM::kCountFuncs;
for (int i = 0; i < num; ++i)
- tim->func[i].avtl = tim->avtl + tim->avtl[i];
+ _tim->func[i].avtl = _tim->avtl + _tim->avtl[i];
- strncpy(tim->filename, filename, 13);
- tim->filename[12] = 0;
+ strncpy(_tim->filename, filename, 13);
+ _tim->filename[12] = 0;
- tim->isLoLOutro = (_vm->gameFlags().gameID == GI_LOL) && !scumm_stricmp(filename, "LOLFINAL.TIM");
- tim->lolCharacter = 0;
+ _tim->isLoLOutro = (_vm->gameFlags().gameID == GI_LOL) && !scumm_stricmp(filename, "LOLFINAL.TIM");
+ _tim->lolCharacter = 0;
- return tim;
+ return _tim;
}
void TIMInterpreter::unload(TIM *&tim) const {
@@ -300,13 +304,15 @@ void TIMInterpreter::displayText(uint16 textId, int16 flags) {
memcpy(filename, text+1, end-1-text);
}
- if (filename[0])
+ const bool isPC98 = (_vm->gameFlags().platform == Common::kPlatformPC98);
+ if (filename[0] && (_vm->speechEnabled() || isPC98))
_vm->sound()->voicePlay(filename);
if (text[0] == '$')
text = strchr(text + 1, '$') + 1;
- setupTextPalette((flags < 0) ? 1 : flags, 0);
+ if (!isPC98)
+ setupTextPalette((flags < 0) ? 1 : flags, 0);
if (flags < 0) {
static const uint8 colorMap[] = { 0x00, 0xF0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -324,7 +330,7 @@ void TIMInterpreter::displayText(uint16 textId, int16 flags) {
char *str = text;
int heightAdd = 0;
- while (str[0]) {
+ while (str[0] && _vm->textEnabled()) {
char *nextLine = strchr(str, '\r');
backupChar = 0;
@@ -335,10 +341,16 @@ void TIMInterpreter::displayText(uint16 textId, int16 flags) {
int width = _screen->getTextWidth(str);
- if (flags >= 0)
- _screen->printText(str, (320 - width) >> 1, 160 + heightAdd, 0xF0, 0x00);
- else
+ if (flags >= 0) {
+ if (isPC98) {
+ static const uint8 colorMap[] = { 0xE1, 0xE1, 0xC1, 0xA1, 0x81, 0x61 };
+ _screen->printText(str, (320 - width) >> 1, 160 + heightAdd, colorMap[flags], 0x00);
+ } else {
+ _screen->printText(str, (320 - width) >> 1, 160 + heightAdd, 0xF0, 0x00);
+ }
+ } else {
_screen->printText(str, (320 - width) >> 1, 188, 0xF0, 0x00);
+ }
heightAdd += _screen->getFontHeight();
str += strlen(str);
@@ -423,7 +435,7 @@ void TIMInterpreter::setupTextPalette(uint index, int fadePalette) {
};
for (int i = 0; i < 15; ++i) {
- uint8 *palette = _screen->getPalette(0) + (240 + i) * 3;
+ uint8 *palette = _screen->getPalette(0).getData() + (240 + i) * 3;
uint8 c1 = (((15 - i) << 2) * palTable[index*3+0]) / 100;
uint8 c2 = (((15 - i) << 2) * palTable[index*3+1]) / 100;
@@ -471,10 +483,10 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char
if (isLoLDemo)
anim->wsa = new WSAMovie_v1(_vm);
else
- anim->wsa = new WSAMovie_v2(_vm, _screen);
+ anim->wsa = new WSAMovie_v2(_vm);
assert(anim->wsa);
- anim->wsa->open(file, wsaOpenFlags, (index == 1) ? _screen->getPalette(0) : 0);
+ anim->wsa->open(file, wsaOpenFlags, (index == 1) ? &_screen->getPalette(0) : 0);
}
if (anim->wsa && anim->wsa->opened()) {
@@ -511,14 +523,14 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char
snprintf(file, 32, "%s.CPS", filename);
if (_vm->resource()->exists(file)) {
- _screen->loadBitmap(file, 3, 3, _screen->getPalette(0));
+ _screen->loadBitmap(file, 3, 3, &_screen->getPalette(0));
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, _drawPage2, Screen::CR_NO_P_CHECK);
if (_drawPage2)
_screen->checkedPageUpdate(8, 4);
_screen->updateScreen();
}
- anim->wsa->displayFrame(0, 0, x, y, 0);
+ anim->wsa->displayFrame(0, 0, x, y, 0, 0, 0);
}
if (wsaFlags & 2)
@@ -535,7 +547,7 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char
snprintf(file, 32, "%s.CPS", filename);
if (_vm->resource()->exists(file)) {
- _screen->loadBitmap(file, 3, 3, _screen->getPalette(0));
+ _screen->loadBitmap(file, 3, 3, &_screen->getPalette(0));
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, _drawPage2, Screen::CR_NO_P_CHECK);
if (_drawPage2)
_screen->checkedPageUpdate(8, 4);
@@ -941,21 +953,21 @@ TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const c
snprintf(file, 32, "%s.WSA", filename);
if (_vm->resource()->exists(file)) {
- anim->wsa = new WSAMovie_v2(_vm, TIMInterpreter::_screen);
+ anim->wsa = new WSAMovie_v2(_vm);
assert(anim->wsa);
- anim->wsa->open(file, wsaOpenFlags, _screen->getPalette(3));
+ anim->wsa->open(file, wsaOpenFlags, &_screen->getPalette(3));
}
if (wsaFlags & 1) {
if (_screen->_fadeFlag != 1)
_screen->fadeClearSceneWindow(10);
- memcpy(_screen->getPalette(3) + 384, _screen->_currentPalette + 384, 384);
+ _screen->getPalette(3).copy(_screen->getPalette(0), 128, 128);
} else if (wsaFlags & 2) {
_screen->fadeToBlack(10);
}
if (wsaFlags & 7)
- anim->wsa->displayFrame(0, 0, x, y, 0);
+ anim->wsa->displayFrame(0, 0, x, y, 0, 0, 0);
if (wsaFlags & 3) {
_screen->loadSpecialColors(_screen->getPalette(3));
@@ -1000,7 +1012,7 @@ void TIMInterpreter_LoL::advanceToOpcode(int opcode) {
void TIMInterpreter_LoL::drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3) {
_screen->setScreenDim(5);
- if (numStr == 1 && _vm->_speechFlag) {
+ if (numStr == 1 && _vm->speechEnabled()) {
_dialogueNumButtons = 0;
_dialogueButtonString[0] = _dialogueButtonString[1] = _dialogueButtonString[2] = 0;
} else {
@@ -1051,7 +1063,7 @@ void TIMInterpreter_LoL::startBackgroundAnimation(int animIndex, int part) {
// WORKAROUND for some bugged scripts that will try to display frames of non-existent animations
if (anim->wsa)
- anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0);
+ anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0);
}
void TIMInterpreter_LoL::stopBackgroundAnimation(int animIndex) {
@@ -1110,7 +1122,7 @@ void TIMInterpreter_LoL::updateBackgroundAnimation(int animIndex) {
anim->nextFrame += (anim->frameDelay * _vm->_tickLength);
- anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0);
+ anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0);
anim->nextFrame += _system->getMillis();
}
@@ -1126,10 +1138,12 @@ void TIMInterpreter_LoL::playAnimationPart(int animIndex, int firstFrame, int la
_screen->copyRegion(112, 0, 112, 0, 176, 120, 2, 0);
_screen->updateScreen();
} else {
- anim->wsa->displayFrame(i - 1, 0, anim->x, anim->y, 0);
+ anim->wsa->displayFrame(i - 1, 0, anim->x, anim->y, 0, 0, 0);
_screen->updateScreen();
}
- _vm->delayUntil(next);
+ int32 del = (int32)(next - _system->getMillis());
+ if (del > 0)
+ _vm->delay(del, true);
}
}
@@ -1162,7 +1176,8 @@ uint16 TIMInterpreter_LoL::processDialogue() {
int x = _dialogueButtonPosX;
for (int i = 0; i < _dialogueNumButtons; i++) {
- if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, x, _dialogueButtonPosY, x + 74, _dialogueButtonPosY + 9)) {
+ Common::Point p = _vm->getMousePos();
+ if (_vm->posWithinRect(p.x, p.y, x, _dialogueButtonPosY, x + 74, _dialogueButtonPosY + 9)) {
_dialogueHighlightedButton = i;
break;
}
@@ -1222,7 +1237,8 @@ uint16 TIMInterpreter_LoL::processDialogue() {
x = _dialogueButtonPosX;
for (int i = 0; i < _dialogueNumButtons; i++) {
- if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, x, _dialogueButtonPosY, x + 74, _dialogueButtonPosY + 9)) {
+ Common::Point p = _vm->getMousePos();
+ if (_vm->posWithinRect(p.x, p.y, x, _dialogueButtonPosY, x + 74, _dialogueButtonPosY + 9)) {
_dialogueHighlightedButton = i;
res = _dialogueHighlightedButton + 1;
break;
diff --git a/engines/kyra/script_tim.h b/engines/kyra/script_tim.h
index 10337b4b09..40049c3dec 100644
--- a/engines/kyra/script_tim.h
+++ b/engines/kyra/script_tim.h
@@ -121,6 +121,8 @@ public:
TIM *load(const char *filename, const Common::Array<const TIMOpcode*> *opcodes);
void unload(TIM *&tim) const;
+ bool callback(Common::IFFChunk &chunk);
+
virtual Animation *initAnimStruct(int index, const char *filename, int x, int y, int, int offscreenBuffer, uint16 wsaFlags);
virtual int freeAnimStruct(int index);
@@ -169,6 +171,11 @@ protected:
bool _finished;
+ // used when loading
+ int _avtlChunkSize;
+ const char *_filename;
+ TIM *_tim;
+
Common::String _vocFiles[120];
Animation *_animations;
diff --git a/engines/kyra/seqplayer.cpp b/engines/kyra/seqplayer.cpp
index 54d6f2cbe3..2145591c03 100644
--- a/engines/kyra/seqplayer.cpp
+++ b/engines/kyra/seqplayer.cpp
@@ -92,7 +92,7 @@ uint8 *SeqPlayer::setPanPages(int pageNum, int shape) {
}
void SeqPlayer::makeHandShapes() {
- _screen->loadBitmap("WRITING.CPS", 3, 3, _screen->_currentPalette);
+ _screen->loadBitmap("WRITING.CPS", 3, 3, &_screen->getPalette(0));
if (_vm->gameFlags().platform == Common::kPlatformMacintosh || _vm->gameFlags().platform == Common::kPlatformAmiga) {
freeHandShapes();
@@ -148,7 +148,7 @@ void SeqPlayer::s1_wsaPlayFrame() {
_seqMovies[wsaObj].pos.x = READ_LE_UINT16(_seqData); _seqData += 2;
_seqMovies[wsaObj].pos.y = *_seqData++;
assert(_seqMovies[wsaObj].movie);
- _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y);
+ _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y, 0, 0, 0);
_seqMovies[wsaObj].frame = frame;
}
@@ -160,7 +160,7 @@ void SeqPlayer::s1_wsaPlayNextFrame() {
frame = 0;
_seqMovies[wsaObj].frame = 0;
}
- _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y);
+ _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y, 0, 0, 0);
}
void SeqPlayer::s1_wsaPlayPrevFrame() {
@@ -171,7 +171,7 @@ void SeqPlayer::s1_wsaPlayPrevFrame() {
frame = _seqMovies[wsaObj].numFrames;
_seqMovies[wsaObj].frame = frame;
} else {
- _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y);
+ _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y, 0, 0, 0);
}
}
@@ -194,21 +194,18 @@ void SeqPlayer::s1_copyWaitTicks() {
void SeqPlayer::s1_shuffleScreen() {
_screen->shuffleScreen(0, 16, 320, 128, 2, 0, 0, false);
- _screen->_curPage = 2;
if (_specialBuffer)
- _screen->copyCurPageBlock(0, 16, 40, 128, _specialBuffer);
+ _screen->copyRegionToBuffer(2, 0, 16, 320, 128, _specialBuffer);
_screen->_curPage = 0;
}
void SeqPlayer::s1_copyView() {
- int y = 128;
- if (!_copyViewOffs)
- y -= 8;
+ int h = !_copyViewOffs ? 120 : 128;
if (_specialBuffer && !_copyViewOffs)
- _screen->copyToPage0(16, y, 3, _specialBuffer);
+ _screen->copyToPage0(16, h, 3, _specialBuffer);
else
- _screen->copyRegion(0, 16, 0, 16, 320, y, 2, 0);
+ _screen->copyRegion(0, 16, 0, 16, 320, h, 2, 0);
}
void SeqPlayer::s1_loopInit() {
@@ -244,25 +241,21 @@ void SeqPlayer::s1_loadPalette() {
if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
if (!colNum)
- memcpy(_screen->_currentPalette, _screen->_currentPalette + 576, 3*32);
+ _screen->copyPalette(0, 6);
else if (colNum == 3)
- memcpy(_screen->_currentPalette, _screen->_currentPalette + 672, 3*32);
+ _screen->copyPalette(0, 7);
else if (colNum == 4)
- memcpy(_screen->_currentPalette, _screen->_currentPalette + 288, 3*32);
+ _screen->copyPalette(0, 3);
- _screen->setScreenPalette(_screen->_currentPalette);
+ _screen->setScreenPalette(_screen->getPalette(0));
} else {
- uint32 fileSize;
- uint8 *srcData;
- srcData = _res->fileData(_vm->seqCOLTable()[colNum], &fileSize);
- memcpy(_screen->_currentPalette, srcData, fileSize);
- delete[] srcData;
+ _screen->loadPalette(_vm->seqCOLTable()[colNum], _screen->getPalette(0));
}
}
void SeqPlayer::s1_loadBitmap() {
uint8 cpsNum = *_seqData++;
- _screen->loadBitmap(_vm->seqCPSTable()[cpsNum], 3, 3, _screen->_currentPalette);
+ _screen->loadBitmap(_vm->seqCPSTable()[cpsNum], 3, 3, &_screen->getPalette(0));
}
void SeqPlayer::s1_fadeToBlack() {
@@ -449,10 +442,7 @@ void SeqPlayer::s1_allocTempBuffer() {
if (!_specialBuffer && !_copyViewOffs) {
_specialBuffer = new uint8[40960];
assert(_specialBuffer);
- int page = _screen->_curPage;
- _screen->_curPage = 0;
- _screen->copyCurPageBlock(0, 0, 320, 128, _specialBuffer);
- _screen->_curPage = page;
+ _screen->copyRegionToBuffer(2, 0, 16, 320, 128, _specialBuffer);
}
}
}
diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp
index 4e53399fbf..90b2fdd580 100644
--- a/engines/kyra/sequences_hof.cpp
+++ b/engines/kyra/sequences_hof.cpp
@@ -62,7 +62,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) {
int oldPage = _screen->setCurPage(2);
for (int i = 0; i < 4; ++i)
- memset(_screen->getPalette(i), 0, 0x300);
+ _screen->getPalette(i).clear();
_screen->clearPage(10);
_screen->clearPage(12);
@@ -77,7 +77,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) {
for (int seqNum = startSeq; seqNum <= endSeq && !((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice); seqNum++) {
_screen->clearPage(0);
_screen->clearPage(8);
- memcpy(_screen->getPalette(1), _screen->getPalette(0), 0x300);
+ _screen->copyPalette(1, 0);
_seqFrameCounter = 0;
_seqStartTime = _system->getMillis();
@@ -87,7 +87,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) {
SeqProc cb = _callbackS[seqNum];
if (cseq.flags & 2) {
- _screen->loadBitmap(cseq.cpsFile, 2, 2, _screen->getPalette(0));
+ _screen->loadBitmap(cseq.cpsFile, 2, 2, &_screen->getPalette(0));
_screen->setScreenPalette(_screen->getPalette(0));
} else {
_screen->setCurPage(2);
@@ -100,9 +100,9 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) {
if (cseq.flags & 1) {
_seqWsa->close();
- _seqWsa->open(cseq.wsaFile, 0, _screen->getPalette(0));
+ _seqWsa->open(cseq.wsaFile, 0, &_screen->getPalette(0));
_screen->setScreenPalette(_screen->getPalette(0));
- _seqWsa->displayFrame(0, 2, cseq.xPos, cseq.yPos, 0);
+ _seqWsa->displayFrame(0, 2, cseq.xPos, cseq.yPos, 0, 0, 0);
}
if (cseq.flags & 4) {
@@ -174,7 +174,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) {
if (_seqWsa) {
int f = _seqWsaCurrentFrame % _seqWsa->frames();
- _seqWsa->displayFrame(f, 2, cseq.xPos, cseq.yPos, 0);
+ _seqWsa->displayFrame(f, 2, cseq.xPos, cseq.yPos, 0, 0, 0);
}
_screen->copyPage(2, 12);
@@ -361,7 +361,7 @@ int KyraEngine_HoF::seq_introTitle(WSAMovie_v2 *wsaObj, int x, int y, int frm) {
}
int KyraEngine_HoF::seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm) {
- uint8 *tmpPal = &(_screen->getPalette(3)[0x101]);
+ uint8 *tmpPal = _screen->getPalette(3).getData() + 0x101;
memset(tmpPal, 0, 256);
_seqSubFrameEndTimeInternal = 0;
uint32 now = 0;
@@ -372,9 +372,9 @@ int KyraEngine_HoF::seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm
_sound->playTrack(4);
_seqSubFrameEndTimeInternal = _system->getMillis() + 60 * _tickLength;
- _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff;
+ _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff;
memset(_seqTextColorMap, _seqTextColor[1], 16);
- _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff;
+ _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff;
_screen->setTextColorMap(_seqTextColorMap);
@@ -384,7 +384,7 @@ int KyraEngine_HoF::seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm
break;
case 1:
- _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3), 0x40, 0, 0, 0, 0x100, true);
+ _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x40, 0, 0, 0, 0x100, true);
for (int i = 0; i < 256; i++)
tmpPal[_screen->getPalette(3)[i]] = 1;
@@ -417,7 +417,7 @@ int KyraEngine_HoF::seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm
case 201:
_screen->setScreenPalette(_screen->getPalette(2));
_screen->updateScreen();
- _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3));
+ _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData());
_screen->copyPage(2, 12);
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0);
_screen->setScreenPalette(_screen->getPalette(0));
@@ -465,10 +465,10 @@ int KyraEngine_HoF::seq_introLibrary(WSAMovie_v2 *wsaObj, int x, int y, int frm)
_seqSubframePlaying = true;
_sound->playTrack(5);
- _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3), 0x24, 0, 0, 0, 0x100, false);
- _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff;
+ _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false);
+ _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff;
memset(_seqTextColorMap, _seqTextColor[1], 16);
- _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff;
+ _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff;
_screen->setTextColorMap(_seqTextColorMap);
break;
@@ -482,7 +482,7 @@ int KyraEngine_HoF::seq_introLibrary(WSAMovie_v2 *wsaObj, int x, int y, int frm)
seq_waitForTextsTimeout();
_screen->copyPage(12, 2);
- _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3));
+ _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData());
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0);
_screen->updateScreen();
_screen->copyPage(2, 12);
@@ -503,7 +503,7 @@ int KyraEngine_HoF::seq_introLibrary(WSAMovie_v2 *wsaObj, int x, int y, int frm)
case 340:
seq_resetActiveWSA(0);
- _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3));
+ _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData());
_screen->copyPage(2, 12);
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0);
_screen->updateScreen();
@@ -539,10 +539,10 @@ int KyraEngine_HoF::seq_introHand(WSAMovie_v2 *wsaObj, int x, int y, int frm) {
_seqSubframePlaying = true;
_sound->playTrack(6);
- _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3), 0x24, 0, 0, 0, 0x100, false);
- _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff;
+ _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false);
+ _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff;
memset(_seqTextColorMap, _seqTextColor[1], 16);
- _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff;
+ _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff;
_screen->setTextColorMap(_seqTextColorMap);
break;
@@ -556,7 +556,7 @@ int KyraEngine_HoF::seq_introHand(WSAMovie_v2 *wsaObj, int x, int y, int frm) {
case 201:
seq_waitForTextsTimeout();
- _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3));
+ _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData());
_screen->copyPage(2, 12);
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0);
_screen->updateScreen();
@@ -631,9 +631,9 @@ int KyraEngine_HoF::seq_introPoint(WSAMovie_v2 *wsaObj, int x, int y, int frm) {
_seqTextColor[1] = 0xf7;
memset(_seqTextColorMap, _seqTextColor[1], 16);
- _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff;
+ _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff;
_screen->setTextColorMap(_seqTextColorMap);
- _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3), 0x24, 0, 0, 0, 0x100, false);
+ _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false);
break;
case 1:
@@ -661,7 +661,7 @@ int KyraEngine_HoF::seq_introZanfaun(WSAMovie_v2 *wsaObj, int x, int y, int frm)
_seqTextColor[1] = 0xfd;
memset(_seqTextColorMap, _seqTextColor[1], 16);
- _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff;
+ _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff;
_screen->setTextColorMap(_seqTextColorMap);
break;
@@ -831,7 +831,7 @@ int KyraEngine_HoF::seq_finaleFunters(WSAMovie_v2 *wsaObj, int x, int y, int frm
case 0:
_sound->playTrack(3);
- _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff;
+ _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff;
memset(_seqTextColorMap, _seqTextColor[1], 16);
_seqTextColor[0] = _seqTextColorMap[1] = 0xff;
_screen->setTextColorMap(_seqTextColorMap);
@@ -924,7 +924,7 @@ int KyraEngine_HoF::seq_finaleFerb(WSAMovie_v2 *wsaObj, int x, int y, int frm) {
break;
case 0:
- _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff;
+ _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff;
memset(_seqTextColorMap, _seqTextColor[1], 16);
_seqTextColor[0] = _seqTextColorMap[1] = 255;
_screen->setTextColorMap(_seqTextColorMap);
@@ -1006,7 +1006,7 @@ int KyraEngine_HoF::seq_finaleFish(WSAMovie_v2 *wsaObj, int x, int y, int frm) {
break;
case 0:
- _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff;
+ _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff;
memset(_seqTextColorMap, _seqTextColor[1], 16);
_seqTextColor[0] = _seqTextColorMap[1] = 0xff;
_screen->setTextColorMap(_seqTextColorMap);
@@ -1096,7 +1096,7 @@ int KyraEngine_HoF::seq_finaleFheep(WSAMovie_v2 *wsaObj, int x, int y, int frm)
break;
case 0:
- _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff;
+ _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff;
memset(_seqTextColorMap, _seqTextColor[1], 16);
_seqTextColor[0] = _seqTextColorMap[1] = 0xff;
_screen->setTextColorMap(_seqTextColorMap);
@@ -1172,9 +1172,9 @@ int KyraEngine_HoF::seq_finaleFarmer(WSAMovie_v2 *wsaObj, int x, int y, int frm)
break;
case 0:
- _seqTextColor[1] = 1 + (_screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 254) & 0xff);
+ _seqTextColor[1] = 1 + (_screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 254) & 0xff);
memset(_seqTextColorMap, _seqTextColor[1], 16);
- _seqTextColorMap[1] = _seqTextColor[0] = 1 + (_screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 254) & 0xff);
+ _seqTextColorMap[1] = _seqTextColor[0] = 1 + (_screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 254) & 0xff);
_screen->setTextColorMap(_seqTextColorMap);
seq_playTalkText(_flags.isTalkie ? 30 : 26);
break;
@@ -1339,7 +1339,7 @@ int KyraEngine_HoF::seq_finaleFirates(WSAMovie_v2 *wsaObj, int x, int y, int frm
break;
case 0:
- _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff;
+ _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff;
memset(_seqTextColorMap, _seqTextColor[1], 16);
_seqTextColor[0] = _seqTextColorMap[1] = 0xff;
_screen->setTextColorMap(_seqTextColorMap);
@@ -1426,7 +1426,7 @@ int KyraEngine_HoF::seq_finaleFrash(WSAMovie_v2 *wsaObj, int x, int y, int frm)
case 0:
if (_seqFrameCounter == 1) {
_sound->playTrack(4);
- _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff;
+ _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff;
memset(_seqTextColorMap, _seqTextColor[1], 16);
_seqTextColor[0] = _seqTextColorMap[1] = 0xff;
_screen->setTextColorMap(_seqTextColorMap);
@@ -1501,7 +1501,7 @@ void KyraEngine_HoF::seq_finaleActorScreen() {
static const uint8 colormap[] = {0, 0, 102, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static const ScreenDim d = { 0x00, 0x0C, 0x28, 0xB4, 0xFF, 0x00, 0x00, 0x00 };
- _screen->loadBitmap("finale.cps", 3, 3, _screen->_currentPalette);
+ _screen->loadBitmap("finale.cps", 3, 3, &_screen->getPalette(0));
_screen->setFont(Screen::FID_GOLDFONT_FNT);
int talkieCreditsSize, talkieCreditsSpecialSize;
@@ -1781,19 +1781,21 @@ int KyraEngine_HoF::seq_demoDig(WSAMovie_v2 *wsaObj, int x, int y, int frm) {
#ifdef ENABLE_LOL
int KyraEngine_HoF::seq_lolDemoScene1(WSAMovie_v2 *wsaObj, int x, int y, int frm) {
- uint8 *tmpPal = _screen->getPalette(2);
+ Palette &tmpPal = _screen->getPalette(2);
if (!(_seqFrameCounter % 100)) {
if (_seqFrameCounter == 0) {
_sound->haltTrack();
_sound->playTrack(6);
}
- memcpy(tmpPal, _screen->getPalette(0), 0x300);
+ tmpPal.copy(_screen->getPalette(0));
+
for (int i = 3; i < 0x300; i++) {
tmpPal[i] = ((int)tmpPal[i] * 120) / 64;
if (tmpPal[i] > 0x3f)
tmpPal[i] = 0x3f;
}
+
seq_playTalkText(_rnd.getRandomBit());
_screen->setScreenPalette(tmpPal);
_screen->updateScreen();
@@ -1926,13 +1928,15 @@ int KyraEngine_HoF::seq_lolDemoScene6(WSAMovie_v2 *wsaObj, int x, int y, int frm
if (_seqFrameCounter % 175) {
_screen->setScreenPalette(_screen->getPalette(0));
} else {
- uint8 *tmpPal = _screen->getPalette(2);
- memcpy(tmpPal, _screen->getPalette(0), 0x300);
+ Palette &tmpPal = _screen->getPalette(2);
+ tmpPal.copy(_screen->getPalette(0));
+
for (int i = 3; i < 0x300; i++) {
tmpPal[i] = ((int)tmpPal[i] * 120) / 64;
if (tmpPal[i] > 0x3f)
tmpPal[i] = 0x3f;
}
+
seq_playTalkText(_rnd.getRandomBit());
_screen->setScreenPalette(tmpPal);
_screen->updateScreen();
@@ -2045,37 +2049,35 @@ char *KyraEngine_HoF::seq_preprocessString(const char *srcStr, int width) {
}
void KyraEngine_HoF::seq_sequenceCommand(int command) {
- uint8 pal[768];
-
for (int i = 0; i < 8; i++)
seq_resetActiveWSA(i);
switch (command) {
case 0:
- memset(pal, 0, 0x300);
- _screen->fadePalette(pal, 36);
- memcpy(_screen->getPalette(0), pal, 0x300);
- memcpy(_screen->getPalette(1), pal, 0x300);
+ _screen->fadeToBlack(36);
+ _screen->getPalette(0).clear();
+ _screen->getPalette(1).clear();
break;
case 1:
- memset(pal, 0x3F, 0x300);
seq_playTalkText(_rnd.getRandomBit());
- _screen->fadePalette(pal, 16);
- memcpy(_screen->getPalette(0), pal, 0x300);
- memcpy(_screen->getPalette(1), pal, 0x300);
+
+ _screen->getPalette(0).fill(0, 256, 0x3F);
+ _screen->fadePalette(_screen->getPalette(0), 16);
+
+ _screen->copyPalette(1, 0);
break;
case 3:
_screen->copyPage(2, 0);
_screen->fadePalette(_screen->getPalette(0), 16);
- memcpy(_screen->getPalette(1), _screen->getPalette(0), 0x300);
+ _screen->copyPalette(1, 0);
break;
case 4:
_screen->copyPage(2, 0);
_screen->fadePalette(_screen->getPalette(0), 36);
- memcpy(_screen->getPalette(1), _screen->getPalette(0), 0x300);
+ _screen->copyPalette(1, 0);
break;
case 5:
@@ -2093,17 +2095,17 @@ void KyraEngine_HoF::seq_sequenceCommand(int command) {
break;
case 8:
- memset(pal, 0, 0x300);
- _screen->fadePalette(pal, 16);
- memcpy(_screen->getPalette(0), pal, 0x300);
- memcpy(_screen->getPalette(1), pal, 0x300);
+ _screen->fadeToBlack(16);
+ _screen->getPalette(0).clear();
+ _screen->getPalette(1).clear();
delay(120 * _tickLength);
break;
- case 9:
- for (int i = 0; i < 0x100; i++) {
- int pv = (_screen->getPalette(0)[3 * i] + _screen->getPalette(0)[3 * i + 1] + _screen->getPalette(0)[3 * i + 2]) / 3;
+ case 9: {
+ Palette &pal = _screen->getPalette(0);
+ for (int i = 0; i < 256; i++) {
+ int pv = (pal[3 * i] + pal[3 * i + 1] + pal[3 * i + 2]) / 3;
pal[3 * i] = pal[3 * i + 1] = pal[3 * i + 2] = pv & 0xff;
}
@@ -2112,9 +2114,8 @@ void KyraEngine_HoF::seq_sequenceCommand(int command) {
//pal[3 * i] = pal[3 * i + 1] = pal[3 * i + 2] = 0x3f;
_screen->fadePalette(pal, 64);
- memcpy(_screen->getPalette(0), pal, 0x300);
- memcpy(_screen->getPalette(1), pal, 0x300);
- break;
+ _screen->copyPalette(1, 0);
+ } break;
default:
break;
@@ -2201,7 +2202,7 @@ void KyraEngine_HoF::seq_loadNestedSequence(int wsaNum, int seqNum) {
NestedSequence s = _sequences->seqn[seqNum];
if (!_activeWSA[wsaNum].movie) {
- _activeWSA[wsaNum].movie = new WSAMovie_v2(this, _screen);
+ _activeWSA[wsaNum].movie = new WSAMovie_v2(this);
assert(_activeWSA[wsaNum].movie);
}
@@ -2246,7 +2247,7 @@ void KyraEngine_HoF::seq_nestedSequenceFrame(int command, int wsaNum) {
case 0:
xa = -_activeWSA[wsaNum].movie->xAdd();
ya = -_activeWSA[wsaNum].movie->yAdd();
- _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0);
+ _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0, 0, 0);
seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(),
_activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 1, 2);
break;
@@ -2254,7 +2255,7 @@ void KyraEngine_HoF::seq_nestedSequenceFrame(int command, int wsaNum) {
case 1:
xa = -_activeWSA[wsaNum].movie->xAdd();
ya = -_activeWSA[wsaNum].movie->yAdd();
- _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0);
+ _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0, 0, 0);
seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(),
_activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 1, 1);
break;
@@ -2263,21 +2264,21 @@ void KyraEngine_HoF::seq_nestedSequenceFrame(int command, int wsaNum) {
seq_waitForTextsTimeout();
xa = -_activeWSA[wsaNum].movie->xAdd();
ya = -_activeWSA[wsaNum].movie->yAdd();
- _activeWSA[wsaNum].movie->displayFrame(0x15, 8, xa, ya, 0);
+ _activeWSA[wsaNum].movie->displayFrame(0x15, 8, xa, ya, 0, 0, 0);
seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(),
_activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 0, 2);
break;
case 3:
_screen->copyPage(2, 10);
- _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0);
+ _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0, 0, 0);
_screen->copyPage(2, 12);
seq_cmpFadeFrame("scene2.cmp");
break;
case 4:
_screen->copyPage(2, 10);
- _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0);
+ _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0, 0, 0);
_screen->copyPage(2, 12);
seq_cmpFadeFrame("scene3.cmp");
break;
@@ -2364,10 +2365,10 @@ bool KyraEngine_HoF::seq_processNextSubFrame(int wsaNum) {
if (_activeWSA[wsaNum].movie) {
if (_activeWSA[wsaNum].flags & 0x20) {
- _activeWSA[wsaNum].movie->displayFrame(_activeWSA[wsaNum].control[currentFrame].index, 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000);
+ _activeWSA[wsaNum].movie->displayFrame(_activeWSA[wsaNum].control[currentFrame].index, 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000, 0, 0);
_activeWSA[wsaNum].frameDelay = _activeWSA[wsaNum].control[currentFrame].delay;
} else {
- _activeWSA[wsaNum].movie->displayFrame(currentFrame % _activeWSA[wsaNum].movie->frames(), 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000);
+ _activeWSA[wsaNum].movie->displayFrame(currentFrame % _activeWSA[wsaNum].movie->frames(), 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000, 0, 0);
}
}
@@ -2477,7 +2478,7 @@ void KyraEngine_HoF::seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, i
_seqWsaChatFrameTimeout = _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength;
if (wsa)
- wsa->displayFrame(curframe % wsa->frames(), 2, wsaXpos, wsaYpos, 0);
+ wsa->displayFrame(curframe % wsa->frames(), 2, wsaXpos, wsaYpos, 0, 0, 0);
_screen->copyPage(2, 12);
@@ -2663,9 +2664,9 @@ void KyraEngine_HoF::seq_displayScrollText(uint8 *data, const ScreenDim *d, int
if (palCycle) {
for (int col = 133; col > 112; col--)
- memcpy(_screen->_currentPalette + (col * 3), _screen->_currentPalette + ((col - 1) * 3), 3);
- memcpy(_screen->_currentPalette + 336, _screen->_currentPalette + 399, 3);
- _screen->setScreenPalette(_screen->_currentPalette);
+ _screen->getPalette(0).copy(_screen->getPalette(0), col - 1, 1, col);
+ _screen->getPalette(0).copy(_screen->getPalette(0), 133, 1, 112);
+ _screen->setScreenPalette(_screen->getPalette(0));
}
delayUntil(_seqSubFrameEndTimeInternal);
@@ -2721,32 +2722,32 @@ void KyraEngine_HoF::seq_scrollPage(int bottom, int top) {
}
void KyraEngine_HoF::seq_showStarcraftLogo() {
- WSAMovie_v2 *ci = new WSAMovie_v2(this, _screen);
+ WSAMovie_v2 *ci = new WSAMovie_v2(this);
assert(ci);
_screen->clearPage(2);
_res->loadPakFile("INTROGEN.PAK");
- int endframe = ci->open("ci.wsa", 0, _screen->_currentPalette);
+ int endframe = ci->open("ci.wsa", 0, &_screen->getPalette(0));
_res->unloadPakFile("INTROGEN.PAK");
if (!ci->opened()) {
delete ci;
return;
}
_screen->hideMouse();
- ci->displayFrame(0, 2, 0, 0, 0);
+ ci->displayFrame(0, 2, 0, 0, 0, 0, 0);
_screen->copyPage(2, 0);
_screen->fadeFromBlack();
for (int i = 1; i < endframe; i++) {
_seqEndTime = _system->getMillis() + 50;
if (skipFlag())
break;
- ci->displayFrame(i, 2, 0, 0, 0);
+ ci->displayFrame(i, 2, 0, 0, 0, 0, 0);
_screen->copyPage(2, 0);
_screen->updateScreen();
delay(_seqEndTime - _system->getMillis());
}
if (!skipFlag()) {
_seqEndTime = _system->getMillis() + 50;
- ci->displayFrame(0, 2, 0, 0, 0);
+ ci->displayFrame(0, 2, 0, 0, 0, 0, 0);
_screen->copyPage(2, 0);
_screen->updateScreen();
delay(_seqEndTime - _system->getMillis());
@@ -2760,7 +2761,7 @@ void KyraEngine_HoF::seq_showStarcraftLogo() {
void KyraEngine_HoF::seq_init() {
_seqProcessedString = new char[200];
- _seqWsa = new WSAMovie_v2(this, _screen);
+ _seqWsa = new WSAMovie_v2(this);
_activeWSA = new ActiveWSA[8];
_activeText = new ActiveText[10];
diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp
index 12ede98ad4..d483409090 100644
--- a/engines/kyra/sequences_lok.cpp
+++ b/engines/kyra/sequences_lok.cpp
@@ -42,7 +42,7 @@ namespace Kyra {
void KyraEngine_LoK::seq_demo() {
snd_playTheme(0, 2);
- _screen->loadBitmap("START.CPS", 7, 7, _screen->_currentPalette);
+ _screen->loadBitmap("START.CPS", 7, 7, &_screen->getPalette(0));
_screen->copyRegion(0, 0, 0, 0, 320, 200, 6, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
_screen->fadeFromBlack();
@@ -50,8 +50,8 @@ void KyraEngine_LoK::seq_demo() {
_screen->fadeToBlack();
_screen->clearPage(0);
- _screen->loadBitmap("TOP.CPS", 7, 7, NULL);
- _screen->loadBitmap("BOTTOM.CPS", 5, 5, _screen->_currentPalette);
+ _screen->loadBitmap("TOP.CPS", 7, 7, 0);
+ _screen->loadBitmap("BOTTOM.CPS", 5, 5, &_screen->getPalette(0));
_screen->copyRegion(0, 91, 0, 8, 320, 103, 6, 0);
_screen->copyRegion(0, 0, 0, 111, 320, 64, 6, 0);
_screen->updateScreen();
@@ -77,7 +77,7 @@ void KyraEngine_LoK::seq_demo() {
_seq->playSequence(_seq_Demo4, true);
_screen->clearPage(0);
- _screen->loadBitmap("FINAL.CPS", 7, 7, _screen->_currentPalette);
+ _screen->loadBitmap("FINAL.CPS", 7, 7, &_screen->getPalette(0));
_screen->_curPage = 0;
_screen->copyRegion(0, 0, 0, 0, 320, 200, 6, 0);
_screen->updateScreen();
@@ -128,7 +128,7 @@ void KyraEngine_LoK::seq_intro() {
void KyraEngine_LoK::seq_introLogos() {
if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) {
- _screen->loadBitmap("LOGO.CPS", 3, 3, _screen->_currentPalette);
+ _screen->loadBitmap("LOGO.CPS", 3, 3, &_screen->getPalette(0));
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0);
_screen->updateScreen();
_screen->fadeFromBlack();
@@ -141,7 +141,7 @@ void KyraEngine_LoK::seq_introLogos() {
_screen->clearPage(0);
if (_flags.platform == Common::kPlatformAmiga) {
- _screen->loadPalette("INTRO.PAL", _screen->_currentPalette);
+ _screen->loadPaletteTable("INTRO.PAL", 0);
_screen->loadBitmap("BOTTOM.CPS", 3, 5, 0);
_screen->loadBitmap("TOP.CPS", 3, 3, 0);
_screen->copyRegion(0, 0, 0, 111, 320, 64, 2, 0);
@@ -149,7 +149,7 @@ void KyraEngine_LoK::seq_introLogos() {
_screen->copyRegion(0, 0, 0, 0, 320, 190, 0, 2);
} else {
_screen->loadBitmap("TOP.CPS", 7, 7, 0);
- _screen->loadBitmap("BOTTOM.CPS", 5, 5, _screen->_currentPalette);
+ _screen->loadBitmap("BOTTOM.CPS", 5, 5, &_screen->getPalette(0));
_screen->copyRegion(0, 91, 0, 8, 320, 103, 6, 0);
_screen->copyRegion(0, 0, 0, 111, 320, 64, 6, 0);
}
@@ -166,8 +166,8 @@ void KyraEngine_LoK::seq_introLogos() {
delay(60 * _tickLength);
if (_flags.platform == Common::kPlatformAmiga) {
- memcpy(_screen->_currentPalette, _screen->_currentPalette + 3*32, 3*32);
- _screen->setScreenPalette(_screen->_currentPalette);
+ _screen->copyPalette(0, 1);
+ _screen->setScreenPalette(_screen->getPalette(0));
}
if ((_seq->playSequence(_seq_KyrandiaLogo, skipFlag()) && !seq_skipSequence()) || shouldQuit()) {
@@ -181,7 +181,7 @@ void KyraEngine_LoK::seq_introLogos() {
return;
if (_flags.platform == Common::kPlatformAmiga) {
- memcpy(_screen->_currentPalette, _screen->_currentPalette + 3*64, 3*32);
+ _screen->copyPalette(0, 2);
_screen->fadeToBlack();
_screen->copyRegion(0, 0, 0, 0, 320, 200, 4, 0);
_screen->fadeFromBlack();
@@ -236,22 +236,22 @@ void KyraEngine_LoK::seq_introStory() {
return;
if (_flags.lang == Common::EN_ANY && !_flags.isTalkie && (_flags.platform == Common::kPlatformPC || _flags.platform == Common::kPlatformAmiga))
- _screen->loadBitmap("TEXT.CPS", 3, 3, _screen->_currentPalette);
+ _screen->loadBitmap("TEXT.CPS", 3, 3, &_screen->getPalette(0));
else if (_flags.lang == Common::EN_ANY || _flags.lang == Common::JA_JPN)
- _screen->loadBitmap("TEXT_ENG.CPS", 3, 3, _screen->_currentPalette);
+ _screen->loadBitmap("TEXT_ENG.CPS", 3, 3, &_screen->getPalette(0));
else if (_flags.lang == Common::DE_DEU)
- _screen->loadBitmap("TEXT_GER.CPS", 3, 3, _screen->_currentPalette);
+ _screen->loadBitmap("TEXT_GER.CPS", 3, 3, &_screen->getPalette(0));
else if (_flags.lang == Common::FR_FRA)
- _screen->loadBitmap("TEXT_FRE.CPS", 3, 3, _screen->_currentPalette);
+ _screen->loadBitmap("TEXT_FRE.CPS", 3, 3, &_screen->getPalette(0));
else if (_flags.lang == Common::ES_ESP)
- _screen->loadBitmap("TEXT_SPA.CPS", 3, 3, _screen->_currentPalette);
+ _screen->loadBitmap("TEXT_SPA.CPS", 3, 3, &_screen->getPalette(0));
else if (_flags.lang == Common::IT_ITA && !_flags.isTalkie)
- _screen->loadBitmap("TEXT_ITA.CPS", 3, 3, _screen->_currentPalette);
+ _screen->loadBitmap("TEXT_ITA.CPS", 3, 3, &_screen->getPalette(0));
else if (_flags.lang == Common::IT_ITA && _flags.isTalkie)
- _screen->loadBitmap("TEXT_ENG.CPS", 3, 3, _screen->_currentPalette);
+ _screen->loadBitmap("TEXT_ENG.CPS", 3, 3, &_screen->getPalette(0));
else
warning("no story graphics file found");
- _screen->setScreenPalette(_screen->_currentPalette);
+ _screen->setScreenPalette(_screen->getPalette(0));
_screen->copyRegion(0, 0, 0, 0, 320, 200, 3, 0);
if (_flags.lang == Common::JA_JPN) {
@@ -569,12 +569,9 @@ void KyraEngine_LoK::seq_winterScroll1() {
_sprites->_anims[i].play = false;
_animator->sprites()[i].active = 0;
}
- uint8 tmpPal[768];
- memcpy(tmpPal, _screen->_currentPalette, 768);
- memcpy(&tmpPal[684], palTable2()[0], 60);
- _screen->fadePalette(tmpPal, 72);
- memcpy(&_screen->_currentPalette[684], palTable2()[0], 60);
- _screen->setScreenPalette(_screen->_currentPalette);
+ _screen->getPalette(0).copy(palTable2()[0], 0, 20, 228);
+ _screen->fadePalette(_screen->getPalette(0), 72);
+ _screen->setScreenPalette(_screen->getPalette(0));
setGameFlag(0xB3);
} else {
delayWithTicks(120);
@@ -950,8 +947,8 @@ int KyraEngine_LoK::seq_playEnd() {
_screen->hideMouse();
_screen->fadeSpecialPalette(32, 228, 20, 60);
delay(60 * _tickLength);
- _screen->loadBitmap("GEMHEAL.CPS", 3, 3, _screen->_currentPalette);
- _screen->setScreenPalette(_screen->_currentPalette);
+ _screen->loadBitmap("GEMHEAL.CPS", 3, 3, &_screen->getPalette(0));
+ _screen->setScreenPalette(_screen->getPalette(0));
_screen->shuffleScreen(8, 8, 304, 128, 2, 0, 1, 0);
uint32 nextTime = _system->getMillis() + 120 * _tickLength;
_finalA = new WSAMovie_v1(this);
@@ -966,7 +963,7 @@ int KyraEngine_LoK::seq_playEnd() {
else if (i == 20)
snd_playSoundEffect(0x0E);
nextTime = _system->getMillis() + 8 * _tickLength;
- _finalA->displayFrame(i, 0, 8, 8);
+ _finalA->displayFrame(i, 0, 8, 8, 0, 0, 0);
_screen->updateScreen();
}
delete _finalA;
@@ -1004,14 +1001,14 @@ void KyraEngine_LoK::seq_playEnding() {
_screen->hideMouse();
_screen->_curPage = 0;
_screen->fadeToBlack();
- _screen->loadBitmap("REUNION.CPS", 3, 3, _screen->_currentPalette);
+ _screen->loadBitmap("REUNION.CPS", 3, 3, &_screen->getPalette(0));
_screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0);
_screen->_curPage = 0;
// XXX
assert(_homeString);
drawSentenceCommand(_homeString[0], 179);
- memset(_screen->getPalette(2), 0, sizeof(uint8)*768);
+ _screen->getPalette(2).clear();
_screen->setScreenPalette(_screen->getPalette(2));
_seqPlayerFlag = true;
@@ -1045,7 +1042,7 @@ void KyraEngine_LoK::seq_playCredits() {
} else
_screen->setFont(Screen::FID_8_FNT);
- _screen->loadBitmap("CHALET.CPS", 4, 4, _screen->_currentPalette);
+ _screen->loadBitmap("CHALET.CPS", 4, 4, &_screen->getPalette(0));
_screen->setCurPage(0);
_screen->clearCurPage();
@@ -1123,10 +1120,10 @@ void KyraEngine_LoK::seq_playCredits() {
_screen->setCurPage(2);
- memset(_screen->getPalette(2), 0, sizeof(uint8)*768);
+ _screen->getPalette(2).clear();
_screen->setScreenPalette(_screen->getPalette(2));
_screen->copyRegion(8, 32, 8, 32, 312, 128, 4, 0, Screen::CR_NO_P_CHECK);
- _screen->fadePalette(_screen->_currentPalette, 0x5A);
+ _screen->fadePalette(_screen->getPalette(0), 0x5A);
Common::Event event;
bool finished = false;
@@ -1198,7 +1195,7 @@ int KyraEngine_LoK::handleMalcolmFlag() {
case 2:
if (_system->getMillis() >= timer2) {
- _finalA->displayFrame(frame, 0, 8, 46);
+ _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
timer2 = _system->getMillis() + 8 * _tickLength;
++frame;
@@ -1213,7 +1210,7 @@ int KyraEngine_LoK::handleMalcolmFlag() {
if (_system->getMillis() < timer1) {
if (_system->getMillis() >= timer2) {
frame = _rnd.getRandomNumberRng(14, 17);
- _finalA->displayFrame(frame, 0, 8, 46);
+ _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
timer2 = _system->getMillis() + 8 * _tickLength;
}
@@ -1225,7 +1222,7 @@ int KyraEngine_LoK::handleMalcolmFlag() {
case 4:
if (_system->getMillis() >= timer2) {
- _finalA->displayFrame(frame, 0, 8, 46);
+ _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
timer2 = _system->getMillis() + 8 * _tickLength;
++frame;
@@ -1239,7 +1236,7 @@ int KyraEngine_LoK::handleMalcolmFlag() {
case 5:
if (_system->getMillis() >= timer2) {
- _finalA->displayFrame(frame, 0, 8, 46);
+ _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
timer2 = _system->getMillis() + 8 * _tickLength;
++frame;
@@ -1253,7 +1250,7 @@ int KyraEngine_LoK::handleMalcolmFlag() {
case 6:
if (_unkEndSeqVar4) {
if (frame <= 33 && _system->getMillis() >= timer2) {
- _finalA->displayFrame(frame, 0, 8, 46);
+ _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
timer2 = _system->getMillis() + 8 * _tickLength;
++frame;
@@ -1278,7 +1275,7 @@ int KyraEngine_LoK::handleMalcolmFlag() {
case 8:
if (_system->getMillis() >= timer2) {
- _finalA->displayFrame(frame, 0, 8, 46);
+ _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
timer2 = _system->getMillis() + 8 * _tickLength;
++frame;
@@ -1295,7 +1292,7 @@ int KyraEngine_LoK::handleMalcolmFlag() {
snd_playSoundEffect(12);
for (int i = 0; i < 18; ++i) {
timer2 = _system->getMillis() + 4 * _tickLength;
- _finalC->displayFrame(i, 0, 16, 50);
+ _finalC->displayFrame(i, 0, 16, 50, 0, 0, 0);
_screen->updateScreen();
delayUntil(timer2);
}
@@ -1353,7 +1350,7 @@ int KyraEngine_LoK::handleBeadState() {
switch (_beadStateVar) {
case 0:
if (beadState1.x != -1 && _endSequenceBackUpRect) {
- _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
_screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
}
@@ -1367,7 +1364,7 @@ int KyraEngine_LoK::handleBeadState() {
case 1:
if (beadState1.x != -1) {
if (_endSequenceBackUpRect) {
- _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
_screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
}
beadState1.x = -1;
@@ -1402,14 +1399,14 @@ int KyraEngine_LoK::handleBeadState() {
beadState1.dstY = beadState1.y;
return 0;
} else {
- _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
_screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
beadState1.x = x;
beadState1.y = y;
}
}
- _screen->copyCurPageBlock(x >> 3, y, beadState1.width, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyRegionToBuffer(_screen->_curPage, x, y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
_screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0);
if (_lastDisplayedPanPage > 17)
@@ -1422,12 +1419,12 @@ int KyraEngine_LoK::handleBeadState() {
case 3:
if (_system->getMillis() >= timer1) {
timer1 = _system->getMillis() + 4 * _tickLength;
- _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
_screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
beadState1.x = beadState1.dstX + table1[beadState1.tableIndex];
beadState1.y = beadState1.dstY + table2[beadState1.tableIndex];
- _screen->copyCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyRegionToBuffer(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
_screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], beadState1.x, beadState1.y, 0, 0);
if (_lastDisplayedPanPage >= 17)
@@ -1476,11 +1473,11 @@ int KyraEngine_LoK::handleBeadState() {
_beadStateVar = 0;
}
} else {
- _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyBlockToPage(_screen->_curPage, beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect);
_screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
beadState1.x = x;
beadState1.y = y;
- _screen->copyCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyRegionToBuffer(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
_screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0);
if (_lastDisplayedPanPage > 17) {
_lastDisplayedPanPage = 0;
@@ -1496,24 +1493,24 @@ int KyraEngine_LoK::handleBeadState() {
int x = 0, y = 0;
if (processBead(beadState1.x, beadState1.y, x, y, &beadState2)) {
if (beadState2.dstX == 290) {
- _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
uint32 nextRun = 0;
for (int i = 0; i < 8; ++i) {
nextRun = _system->getMillis() + _tickLength;
- _finalB->displayFrame(i, 0, 224, 8);
+ _finalB->displayFrame(i, 0, 224, 8, 0, 0, 0);
_screen->updateScreen();
delayUntil(nextRun);
}
snd_playSoundEffect(0x0D);
for (int i = 7; i >= 0; --i) {
nextRun = _system->getMillis() + _tickLength;
- _finalB->displayFrame(i, 0, 224, 8);
+ _finalB->displayFrame(i, 0, 224, 8, 0, 0, 0);
_screen->updateScreen();
delayUntil(nextRun);
}
initBeadState(beadState1.x, beadState1.y, 63, 60, 12, &beadState2);
} else {
- _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
_screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
beadState1.x = -1;
beadState1.tableIndex = 0;
@@ -1521,11 +1518,11 @@ int KyraEngine_LoK::handleBeadState() {
_malcolmFlag = 9;
}
} else {
- _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
_screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
beadState1.x = x;
beadState1.y = y;
- _screen->copyCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyRegionToBuffer(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
_screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0);
if (_lastDisplayedPanPage > 17)
_lastDisplayedPanPage = 0;
@@ -1679,11 +1676,11 @@ void KyraEngine_LoK::updateKyragemFading() {
_kyragemFadingState.timerCount = _system->getMillis() + 4 * _tickLength;
int palPos = 684;
for (int i = 0; i < 20; ++i) {
- _screen->_currentPalette[palPos++] = kyraGemPalette[i + _kyragemFadingState.rOffset];
- _screen->_currentPalette[palPos++] = kyraGemPalette[i + _kyragemFadingState.gOffset];
- _screen->_currentPalette[palPos++] = kyraGemPalette[i + _kyragemFadingState.bOffset];
+ _screen->getPalette(0)[palPos++] = kyraGemPalette[i + _kyragemFadingState.rOffset];
+ _screen->getPalette(0)[palPos++] = kyraGemPalette[i + _kyragemFadingState.gOffset];
+ _screen->getPalette(0)[palPos++] = kyraGemPalette[i + _kyragemFadingState.bOffset];
}
- _screen->setScreenPalette(_screen->_currentPalette);
+ _screen->setScreenPalette(_screen->getPalette(0));
_animator->_updateScreen = true;
switch (_kyragemFadingState.nextOperation) {
case 0:
diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp
index 849a325560..beea129f66 100644
--- a/engines/kyra/sequences_lol.cpp
+++ b/engines/kyra/sequences_lol.cpp
@@ -43,7 +43,7 @@ int LoLEngine::processPrologue() {
if (_flags.isDemo) {
_screen->fadePalette(_screen->getPalette(1), 30, 0);
- _screen->loadBitmap("FINAL.CPS", 2, 2, _screen->getPalette(0));
+ _screen->loadBitmap("FINAL.CPS", 2, 2, &_screen->getPalette(0));
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
_screen->fadePalette(_screen->getPalette(0), 30, 0);
delayWithTicks(300);
@@ -57,7 +57,7 @@ int LoLEngine::processPrologue() {
int processSelection = -1;
while (!shouldQuit() && processSelection == -1) {
- _screen->loadBitmap("TITLE.CPS", 2, 2, _screen->getPalette(0));
+ _screen->loadBitmap("TITLE.CPS", 2, 2, &_screen->getPalette(0));
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
_screen->setFont(Screen::FID_6_FNT);
@@ -71,11 +71,14 @@ int LoLEngine::processPrologue() {
_eventList.clear();
int selection = mainMenu();
- _screen->hideMouse();
- // Unlike the original, we add a nice fade to black
- memset(_screen->getPalette(0), 0, 768);
- _screen->fadePalette(_screen->getPalette(0), 0x54);
+ if (selection != 3) {
+ _screen->hideMouse();
+
+ // Unlike the original, we add a nice fade to black
+ _screen->getPalette(0).clear();
+ _screen->fadeToBlack(0x54);
+ }
switch (selection) {
case 0: // New game
@@ -90,7 +93,8 @@ int LoLEngine::processPrologue() {
break;
case 3: // Load game
- //processSelection = 3;
+ if (_gui->runMenu(_gui->_loadMenu))
+ processSelection = 3;
break;
case 4: // Quit game
@@ -100,7 +104,7 @@ int LoLEngine::processPrologue() {
}
}
- if (processSelection == 0 || processSelection == 3) {
+ if (processSelection == 0) {
_sound->loadSoundFile(0);
_sound->playTrack(6);
chooseCharacter();
@@ -131,7 +135,6 @@ void LoLEngine::setupPrologueData(bool load) {
const char * const *fileList = _flags.isTalkie ? fileListCD :
(_flags.useInstallerPackage ? fileListFloppy : fileListFloppyExtracted);
-
char filename[32];
for (uint i = 0; fileList[i]; ++i) {
filename[0] = '\0';
@@ -155,7 +158,7 @@ void LoLEngine::setupPrologueData(bool load) {
_screen->clearPage(3);
if (load) {
- _chargenWSA = new WSAMovie_v2(this, _screen);
+ _chargenWSA = new WSAMovie_v2(this);
assert(_chargenWSA);
//_charSelection = -1;
@@ -165,7 +168,7 @@ void LoLEngine::setupPrologueData(bool load) {
_selectionAnimFrames[1] = _selectionAnimFrames[3] = 1;
memset(_selectionAnimTimers, 0, sizeof(_selectionAnimTimers));
- memset(_screen->getPalette(1), 0, 768);
+ _screen->getPalette(1).clear();
_sound->setSoundList(&_soundData[kMusicIntro]);
@@ -181,9 +184,8 @@ void LoLEngine::setupPrologueData(bool load) {
} else {
delete _chargenWSA; _chargenWSA = 0;
- uint8 *pal = _screen->getPalette(0);
- memset(pal, 0, 768);
- _screen->setScreenPalette(pal);
+ _screen->getPalette(0).clear();
+ _screen->setScreenPalette(_screen->getPalette(0));
if (shouldQuit())
return;
@@ -200,9 +202,8 @@ void LoLEngine::showIntro() {
if (_flags.platform == Common::kPlatformPC98)
showStarcraftLogo();
- uint8 *pal = _screen->getPalette(0);
- memset(pal, 0, 768);
- _screen->setScreenPalette(pal);
+ _screen->getPalette(0).clear();
+ _screen->setScreenPalette(_screen->getPalette(0));
_screen->clearPage(0);
_screen->clearPage(4);
@@ -274,8 +275,8 @@ int LoLEngine::chooseCharacter() {
while (!_screen->isMouseVisible())
_screen->showMouse();
- _screen->loadBitmap("CHAR.CPS", 2, 2, _screen->getPalette(0));
- _screen->loadBitmap("BACKGRND.CPS", 4, 4, _screen->getPalette(0));
+ _screen->loadBitmap("CHAR.CPS", 2, 2, &_screen->getPalette(0));
+ _screen->loadBitmap("BACKGRND.CPS", 4, 4, &_screen->getPalette(0));
if (!_chargenWSA->open("CHARGEN.WSA", 1, 0))
error("Couldn't load CHARGEN.WSA");
@@ -368,7 +369,7 @@ void LoLEngine::kingSelectionIntro() {
_sound->voicePlay("KING01", &_speechHandle);
int index = 4;
- while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying(&_speechHandle))) && _charSelection == -1 && !shouldQuit() && !skipFlag()) {
+ while ((!speechEnabled() || (speechEnabled() && _sound->voiceIsPlaying(&_speechHandle))) && _charSelection == -1 && !shouldQuit() && !skipFlag()) {
index = MAX(index, 4);
_chargenWSA->displayFrame(_chargenFrameTable[index], 0, 113, 0, 0, 0, 0);
@@ -384,7 +385,7 @@ void LoLEngine::kingSelectionIntro() {
_system->delayMillis(10);
}
- if (_speechFlag)
+ if (speechEnabled())
index = (index + 1) % 22;
else if (++index >= 27)
break;
@@ -407,7 +408,7 @@ void LoLEngine::kingSelectionReminder() {
_sound->voicePlay("KING02", &_speechHandle);
int index = 0;
- while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying(&_speechHandle))) && _charSelection == -1 && !shouldQuit() && index < 15) {
+ while ((!speechEnabled() || (speechEnabled() && _sound->voiceIsPlaying(&_speechHandle))) && _charSelection == -1 && !shouldQuit() && index < 15) {
_chargenWSA->displayFrame(_chargenFrameTable[index+9], 0, 113, 0, 0, 0, 0);
_screen->copyRegion(_selectionPosTable[_reminderChar1IdxTable[index]*2+0], _selectionPosTable[_reminderChar1IdxTable[index]*2+1], _charPreviews[0].x, _charPreviews[0].y, 32, 32, 4, 0);
_screen->copyRegion(_selectionPosTable[_reminderChar2IdxTable[index]*2+0], _selectionPosTable[_reminderChar2IdxTable[index]*2+1], _charPreviews[1].x, _charPreviews[1].y, 32, 32, 4, 0);
@@ -421,7 +422,7 @@ void LoLEngine::kingSelectionReminder() {
_system->delayMillis(10);
}
- if (_speechFlag)
+ if (speechEnabled())
index = (index + 1) % 22;
else if (++index >= 27)
break;
@@ -434,7 +435,7 @@ void LoLEngine::kingSelectionOutro() {
_sound->voicePlay("KING03", &_speechHandle);
int index = 0;
- while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying(&_speechHandle))) && !shouldQuit() && !skipFlag()) {
+ while ((!speechEnabled() || (speechEnabled() && _sound->voiceIsPlaying(&_speechHandle))) && !shouldQuit() && !skipFlag()) {
index = MAX(index, 4);
_chargenWSA->displayFrame(_chargenFrameTable[index], 0, 113, 0, 0, 0, 0);
@@ -446,7 +447,7 @@ void LoLEngine::kingSelectionOutro() {
_system->delayMillis(10);
}
- if (_speechFlag)
+ if (speechEnabled())
index = (index + 1) % 22;
else if (++index >= 27)
break;
@@ -581,13 +582,13 @@ void LoLEngine::selectionCharInfoIntro(char *file) {
bool processAnim = true;
while (_charSelectionInfoResult == -1 && !shouldQuit()) {
- if (_speechFlag && !_sound->isVoicePresent(file))
+ if (speechEnabled() && !_sound->isVoicePresent(file))
break;
_sound->voicePlay(file, &_speechHandle);
int i = 0;
- while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying(&_speechHandle))) && _charSelectionInfoResult == -1 && !shouldQuit()) {
+ while ((!speechEnabled() || (speechEnabled() && _sound->voiceIsPlaying(&_speechHandle))) && _charSelectionInfoResult == -1 && !shouldQuit()) {
_screen->drawShape(0, _screen->getPtrToShape(_screen->getCPagePtr(9), _charInfoFrameTable[i]), 11, 130, 0, 0);
_screen->updateScreen();
@@ -597,7 +598,7 @@ void LoLEngine::selectionCharInfoIntro(char *file) {
_system->delayMillis(10);
}
- if (_speechFlag || processAnim)
+ if (speechEnabled() || processAnim)
i = (i + 1) % 32;
if (i == 0)
processAnim = false;
@@ -641,19 +642,19 @@ int LoLEngine::selectionCharAccept() {
}
void LoLEngine::showStarcraftLogo() {
- WSAMovie_v2 *ci = new WSAMovie_v2(this, _screen);
+ WSAMovie_v2 *ci = new WSAMovie_v2(this);
assert(ci);
_screen->clearPage(0);
_screen->clearPage(2);
- int endframe = ci->open("ci01.wsa", 0, _screen->_currentPalette);
+ int endframe = ci->open("ci01.wsa", 0, &_screen->getPalette(0));
if (!ci->opened()) {
delete ci;
return;
}
_screen->hideMouse();
- ci->displayFrame(0, 2, 32, 80, 0);
+ ci->displayFrame(0, 2, 32, 80, 0, 0, 0);
_screen->copyPage(2, 0);
_screen->fadeFromBlack();
int inputFlag = 0;
@@ -661,7 +662,7 @@ void LoLEngine::showStarcraftLogo() {
inputFlag = checkInput(0) & 0xff;
if (shouldQuit() || inputFlag)
break;
- ci->displayFrame(i, 2, 32, 80, 0);
+ ci->displayFrame(i, 2, 32, 80, 0, 0, 0);
_screen->copyPage(2, 0);
_screen->updateScreen();
delay(4 * _tickLength);
@@ -725,9 +726,8 @@ void LoLEngine::setupEpilogueData(bool load) {
if (_flags.platform == Common::kPlatformPC98)
_sound->loadSoundFile("SOUND.DAT");
} else {
- uint8 *pal = _screen->getPalette(0);
- memset(pal, 0, 768);
- _screen->setScreenPalette(pal);
+ _screen->getPalette(0).clear();
+ _screen->setScreenPalette(_screen->getPalette(0));
if (shouldQuit())
return;
@@ -742,9 +742,8 @@ void LoLEngine::showOutro(int character, bool maxDifficulty) {
TIMInterpreter *timBackUp = _tim;
_tim = new TIMInterpreter(this, _screen, _system);
- uint8 *pal = _screen->getPalette(0);
- memset(pal, 0, 768);
- _screen->setScreenPalette(pal);
+ _screen->getPalette(0).clear();
+ _screen->setScreenPalette(_screen->getPalette(0));
_screen->clearPage(0);
_screen->clearPage(4);
@@ -803,25 +802,24 @@ void LoLEngine::showOutro(int character, bool maxDifficulty) {
switch (character) {
case 0:
- _screen->loadBitmap("KIERAN.CPS", 3, 3, _screen->getPalette(0));
+ _screen->loadBitmap("KIERAN.CPS", 3, 3, &_screen->getPalette(0));
break;
case 1:
- _screen->loadBitmap("AK'SHEL.CPS", 3, 3, _screen->getPalette(0));
+ _screen->loadBitmap("AK'SHEL.CPS", 3, 3, &_screen->getPalette(0));
break;
case 2:
- _screen->loadBitmap("MICHAEL.CPS", 3, 3, _screen->getPalette(0));
+ _screen->loadBitmap("MICHAEL.CPS", 3, 3, &_screen->getPalette(0));
break;
case 3:
- _screen->loadBitmap("CONRAD.CPS", 3, 3, _screen->getPalette(0));
+ _screen->loadBitmap("CONRAD.CPS", 3, 3, &_screen->getPalette(0));
break;
default:
_screen->clearPage(3);
- memset(_screen->getPalette(0), 0, 768);
- break;
+ _screen->getPalette(0).clear();
}
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
@@ -856,8 +854,8 @@ void LoLEngine::showCredits() {
_screen->setTextColorMap(colorMap);
_screen->_charWidth = 0;
- _screen->loadBitmap("ROOM.CPS", 2, 2, _screen->getPalette(0));
- memset(_screen->getPalette(0) + 764, 0, 3);
+ _screen->loadBitmap("ROOM.CPS", 2, 2, &_screen->getPalette(0));
+ _screen->getPalette(0).fill(255, 1, 0);
_screen->fadeToBlack(30);
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
@@ -865,7 +863,7 @@ void LoLEngine::showCredits() {
_screen->_charOffset = 0;
char *credits = (char *)_res->fileData("CREDITS.TXT", 0);
- processCredits(credits, 19, 4, 5);
+ processCredits(credits, 21, 4, 5);
delete[] credits;
uint32 endTime = _system->getMillis() + 120 * _tickLength;
@@ -895,8 +893,8 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) {
uint8 *doorShape = _screen->makeShapeCopy(_screen->getCPagePtr(5), 0);
assert(doorShape);
- _screen->drawShape(0, doorShape, 0, 0, 20, 0x10);
- _screen->drawShape(0, doorShape, 0, 0, 21, 0x11);
+ _screen->drawShape(0, doorShape, 0, 0, 22, 0x10);
+ _screen->drawShape(0, doorShape, 0, 0, 23, 0x11);
int curShapeFile = 0;
uint8 *shapes[12];
@@ -906,7 +904,7 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) {
uint8 *monsterPal = _res->fileData("MONSTERS.PAL", 0);
assert(monsterPal);
- memcpy(_screen->getPalette(0) + 88 * 3, monsterPal + 0 * 3, 40 * 3);
+ _screen->getPalette(0).copy(monsterPal, 0, 40, 88);
_screen->fadePalette(_screen->getPalette(0), 30);
uint32 waitTimer = _system->getMillis();
@@ -1042,8 +1040,8 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) {
} else {
if (!monsterAnimFrame && doorRedraw) {
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, page, Screen::CR_NO_P_CHECK);
- _screen->drawShape(page, doorShape, 0, 0, 20, 0x10);
- _screen->drawShape(page, doorShape, 0, 0, 21, 0x11);
+ _screen->drawShape(page, doorShape, 0, 0, 22, 0x10);
+ _screen->drawShape(page, doorShape, 0, 0, 23, 0x11);
--frameCounter;
doorRedraw = false;
@@ -1062,32 +1060,32 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) {
bool isRightMonster = ((curShapeFile - 1) & 1) != 0;
if (isRightMonster) {
- doorSD = 21;
+ doorSD = 23;
doorX = _outroRightDoorPos[monsterAnimFrame * 2 + 0];
doorY = _outroRightDoorPos[monsterAnimFrame * 2 + 1];
monsterX = _outroRightMonsterPos[monsterAnimFrame * 2 + 0];
monsterY = _outroRightMonsterPos[monsterAnimFrame * 2 + 1];
- _screen->drawShape(page, doorShape, 0, 0, 20, 0x10);
+ _screen->drawShape(page, doorShape, 0, 0, 22, 0x10);
} else {
- doorSD = 20;
+ doorSD = 22;
doorX = _outroLeftDoorPos[monsterAnimFrame * 2 + 0];
doorY = _outroLeftDoorPos[monsterAnimFrame * 2 + 1];
monsterX = _outroLeftMonsterPos[monsterAnimFrame * 2 + 0];
monsterY = _outroLeftMonsterPos[monsterAnimFrame * 2 + 1];
- _screen->drawShape(page, doorShape, 0, 0, 21, 0x11);
+ _screen->drawShape(page, doorShape, 0, 0, 23, 0x11);
}
if (monsterAnimFrame >= 8)
- _screen->drawShape(page, doorShape, doorX, doorY, doorSD, (doorSD == 20) ? 0 : 1);
+ _screen->drawShape(page, doorShape, doorX, doorY, doorSD, (doorSD == 22) ? 0 : 1);
_screen->drawShape(page, monsterShape, monsterX, monsterY, 0, 0x104 | ((!isRightMonster | (monsterAnimFrame < 20)) ? 0 : 1), _outroShapeTable, 1, _outroMonsterScaleTableX[monsterAnimFrame], _outroMonsterScaleTableY[monsterAnimFrame]);
if (monsterAnimFrame < 8)
- _screen->drawShape(page, doorShape, doorX, doorY, doorSD, (doorSD == 20) ? 0 : 1);
+ _screen->drawShape(page, doorShape, doorX, doorY, doorSD, (doorSD == 22) ? 0 : 1);
_screen->copyRegion(0, 0, 0, 0, 320, 200, page, 6, Screen::CR_NO_P_CHECK);
doorRedraw = true;
@@ -1129,7 +1127,7 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) {
curShapeFile = curShapeFile % 28;
loadOutroShapes(curShapeFile, shapes);
- memcpy(_screen->getPalette(0) + 88 * 3, monsterPal + curShapeFile * 40 * 3, 40 * 3);
+ _screen->getPalette(0).copy(monsterPal, curShapeFile * 40, 40, 88);
_screen->setScreenPalette(_screen->getPalette(0));
needNewShape = false;
diff --git a/engines/kyra/sound_lol.cpp b/engines/kyra/sound_lol.cpp
index 3f87036849..63a42837aa 100644
--- a/engines/kyra/sound_lol.cpp
+++ b/engines/kyra/sound_lol.cpp
@@ -34,7 +34,7 @@
namespace Kyra {
bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) {
- if (!_speechFlag)
+ if (!speechEnabled())
return false;
if (speaker < 65) {
@@ -304,6 +304,15 @@ int LoLEngine::snd_stopMusic() {
return snd_playTrack(-1);
}
+int LoLEngine::convertVolumeToMixer(int value) {
+ value -= 2;
+ return (value * Audio::Mixer::kMaxMixerVolume) / 100;
+}
+
+int LoLEngine::convertVolumeFromMixer(int value) {
+ return (value * 100) / Audio::Mixer::kMaxMixerVolume + 2;
+}
+
} // end of namespace Kyra
#endif // ENABLE_LOL
diff --git a/engines/kyra/sound_midi.cpp b/engines/kyra/sound_midi.cpp
index f798251525..451b77cec2 100644
--- a/engines/kyra/sound_midi.cpp
+++ b/engines/kyra/sound_midi.cpp
@@ -311,10 +311,8 @@ void MidiOutput::sendSysEx(const byte p1, const byte p2, const byte p3, const by
}
void MidiOutput::metaEvent(byte type, byte *data, uint16 length) {
- if (type == 0x2F) { // End of Track
+ if (type == 0x2F) // End of Track
deinitSource(_curSource);
- //XXX
- }
_output->metaEvent(type, data, length);
}
diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp
index 1980f62d7c..fe0a44c052 100644
--- a/engines/kyra/sound_towns.cpp
+++ b/engines/kyra/sound_towns.cpp
@@ -1504,7 +1504,7 @@ public:
private:
void updatesRegs();
- uint8 _updateRequestBuf[32];
+ uint8 _updateRequestBuf[64];
int _updateRequest;
int _rand;
@@ -2657,7 +2657,7 @@ void TownsPC98_OpnSquareSineSource::writeReg(uint8 address, uint8 value, bool fo
}
if (!force) {
- if (_updateRequest == 31) {
+ if (_updateRequest >= 63) {
warning("TownsPC98_OpnSquareSineSource: event buffer overflow");
_updateRequest = -1;
}
@@ -3420,6 +3420,8 @@ TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : To
}
TownsPC98_OpnDriver::~TownsPC98_OpnDriver() {
+ reset();
+
if (_channels) {
for (int i = 0; i < _numChan; i++)
delete _channels[i];
@@ -4120,7 +4122,7 @@ void SoundPC98::playSoundEffect(uint8 track) {
// This has been disabled for now since I don't know
// how to make up the correct track number. It probably
// needs a map.
- //_driver->loadSoundEffectData(_sfxTrackData, track);
+ _driver->loadSoundEffectData(_sfxTrackData, track);
}
diff --git a/engines/kyra/sprites.cpp b/engines/kyra/sprites.cpp
index 147ded3cfd..3cc632a391 100644
--- a/engines/kyra/sprites.cpp
+++ b/engines/kyra/sprites.cpp
@@ -47,7 +47,7 @@ Sprites::Sprites(KyraEngine_LoK *vm, OSystem *system) {
_spriteDefStart = 0;
memset(_drawLayerTable, 0, sizeof(_drawLayerTable));
_sceneAnimatorBeaconFlag = 0;
- system->getEventManager()->registerRandomSource(_rnd, "kyraSprites");
+ _vm->getEventManager()->registerRandomSource(_rnd, "kyraSprites");
}
Sprites::~Sprites() {
@@ -420,16 +420,16 @@ void Sprites::loadDat(const char *filename, SceneExits &exits) {
if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
if (_vm->queryGameFlag(0xA0))
- memcpy(_screen->getPalette(3), _screen->getPalette(4), 32*3);
+ _screen->copyPalette(3, 4);
else
- memcpy(_screen->getPalette(3), _screen->getPalette(0), 32*3);
+ _screen->copyPalette(3, 0);
} else {
if (_vm->queryGameFlag(0xA0))
- memcpy(_screen->getPalette(1), _screen->getPalette(3), 768);
+ _screen->copyPalette(1, 3);
else
- memcpy(_screen->getPalette(1), _screen->getPalette(0), 768);
+ _screen->copyPalette(1, 0);
- _screen->loadPalette(_dat + 0x17, _screen->getPalette(1) + 684, 60);
+ _screen->getPalette(1).copy(_dat + 0x17, 0, 20, 228);
}
uint8 *data = _dat + 0x6B;
diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp
index 732a8bb2ca..8cee1dc5fc 100644
--- a/engines/kyra/sprites_lol.cpp
+++ b/engines/kyra/sprites_lol.cpp
@@ -784,7 +784,7 @@ int LoLEngine::getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags) {
default:
return m->damageReceived ? 5 : m->currentSubFrame;
}
-
+
break;
default:
break;
@@ -1092,7 +1092,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
setMonsterMode(monster, 7);
if ((monster->mode != 11) && (monster->mode != 14)) {
- if (!(getRandomNumberSpecial() & 3)) {
+ if (!(_rnd.getRandomNumber(255) & 3)) {
monster->shiftStep = (++monster->shiftStep) & 0x0f;
checkSceneUpdateNeed(monster->block);
}
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index 3f41768c3c..e8597c8326 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -1584,7 +1584,7 @@ void KyraEngine_LoK::loadMainScreen(int page) {
_screen->clearPage(page);
if (_flags.lang == Common::EN_ANY && !_flags.isTalkie && (_flags.platform == Common::kPlatformPC || _flags.platform == Common::kPlatformAmiga))
- _screen->loadBitmap("MAIN15.CPS", page, page, _screen->getPalette(0));
+ _screen->loadBitmap("MAIN15.CPS", page, page, &_screen->getPalette(0));
else if (_flags.lang == Common::EN_ANY || _flags.lang == Common::JA_JPN || (_flags.isTalkie && _flags.lang == Common::IT_ITA))
_screen->loadBitmap("MAIN_ENG.CPS", page, page, 0);
else if (_flags.lang == Common::FR_FRA)
@@ -1599,7 +1599,7 @@ void KyraEngine_LoK::loadMainScreen(int page) {
warning("no main graphics file found");
if (_flags.platform == Common::kPlatformAmiga)
- memcpy(_screen->getPalette(1), _screen->getPalette(0), 32*3);
+ _screen->copyPalette(1, 0);
_screen->copyRegion(0, 0, 0, 0, 320, 200, page, 0);
}
@@ -2011,9 +2011,108 @@ void LoLEngine::initStaticResource() {
#undef cb
}
+void GUI_LoL::initStaticData() {
+ GUI_V2_BUTTON(_scrollUpButton, 20, 96, 0, 1, 1, 1, 0x4487, 0, 0, 0, 25, 16, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0);
+ GUI_V2_BUTTON(_scrollDownButton, 21, 98, 0, 1, 1, 1, 0x4487, 0, 0, 0, 25, 16, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0);
+
+ for (uint i = 0; i < ARRAYSIZE(_menuButtons); ++i)
+ GUI_V2_BUTTON(_menuButtons[i], i, 0, 0, 0, 0, 0, 0x4487, 0, 0, 0, 0, 0, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0);
+
+ GUI_LOL_MENU(_mainMenu, 9, 0x4000, 0, 7, -1, -1, -1, -1);
+ GUI_LOL_MENU_ITEM(_mainMenu.item[0], 0x4001, 16, 23, 176, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_mainMenu.item[1], 0x4002, 16, 40, 176, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_mainMenu.item[2], 0x4003, 16, 57, 176, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_mainMenu.item[3], 0x4004, 16, 74, 176, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_mainMenu.item[4], 0x42D9, 16, 91, 176, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_mainMenu.item[5], 0x4006, 16, 108, 176, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_mainMenu.item[6], 0x4005, 88, 127, 104, 15, 0, 110);
+ Button::Callback mainMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedMainMenu);
+ for (int i = 0; i < 7; ++i)
+ _mainMenu.item[i].callback = mainMenuFunctor;
+
+ GUI_LOL_MENU(_loadMenu, 10, 0x400e, 1, 5, 128, 20, 128, 118);
+ GUI_LOL_MENU_ITEM(_loadMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_loadMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_loadMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_loadMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_loadMenu.item[4], 0x4011, 168, 118, 96, 15, 0, 110);
+ Button::Callback loadMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedLoadMenu);
+ for (int i = 0; i < 5; ++i)
+ _loadMenu.item[i].callback = loadMenuFunctor;
+
+ GUI_LOL_MENU(_saveMenu, 10, 0x400d, 1, 5, 128, 20, 128, 118);
+ GUI_LOL_MENU_ITEM(_saveMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_saveMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_saveMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_saveMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_saveMenu.item[4], 0x4011, 168, 118, 96, 15, 0, 110);
+ Button::Callback saveMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedSaveMenu);
+ for (int i = 0; i < 5; ++i)
+ _saveMenu.item[i].callback = saveMenuFunctor;
+
+ GUI_LOL_MENU(_deleteMenu, 10, 0x400f, 1, 5, 128, 20, 128, 118);
+ GUI_LOL_MENU_ITEM(_deleteMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_deleteMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_deleteMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_deleteMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_deleteMenu.item[4], 0x4011, 168, 118, 96, 15, 0, 110);
+ Button::Callback deleteMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedDeleteMenu);
+ for (int i = 0; i < 5; ++i)
+ _deleteMenu.item[i].callback = deleteMenuFunctor;
+
+ GUI_LOL_MENU(_gameOptions, 17, 0x400c, 0, 6, -1, -1, -1, -1);
+ GUI_LOL_MENU_ITEM(_gameOptions.item[0], 0xfff7, 120, 22, 80, 15, 0x406e, 0);
+ GUI_LOL_MENU_ITEM(_gameOptions.item[1], 0xfff6, 120, 39, 80, 15, 0x406c, 0);
+ GUI_LOL_MENU_ITEM(_gameOptions.item[2], 0xfff5, 120, 56, 80, 15, 0x406d, 0);
+ GUI_LOL_MENU_ITEM(_gameOptions.item[3], 0xfff4, 120, 73, 80, 15, 0x42d5, 0);
+ GUI_LOL_MENU_ITEM(_gameOptions.item[4], 0xfff3, 120, 90, 80, 15, 0x42d2, 0);
+ GUI_LOL_MENU_ITEM(_gameOptions.item[5], 0x4072, 104, 110, 96, 15, 0, 110);
+ Button::Callback optionsMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedOptionsMenu);
+ for (int i = 0; i < 6; ++i)
+ _gameOptions.item[i].callback = optionsMenuFunctor;
+
+ GUI_LOL_MENU(_audioOptions, 18, 0x42d9, 2, 1, -1, -1, -1, -1);
+ GUI_LOL_MENU_ITEM(_audioOptions.item[0], 0x4072, 152, 76, 96, 15, 0, 110);
+ GUI_LOL_MENU_ITEM(_audioOptions.item[1], 3, 128, 22, 114, 14, 0x42db, 0);
+ GUI_LOL_MENU_ITEM(_audioOptions.item[2], 4, 128, 39, 114, 14, 0x42da, 0);
+ GUI_LOL_MENU_ITEM(_audioOptions.item[3], 5, 128, 56, 114, 14, 0x42dc, 0);
+ Button::Callback audioMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedAudioMenu);
+ for (int i = 0; i < 4; ++i)
+ _audioOptions.item[i].callback = audioMenuFunctor;
+
+ GUI_LOL_MENU(_deathMenu, 11, 0x4013, 0, 2, -1, -1, -1, -1);
+ GUI_LOL_MENU_ITEM(_deathMenu.item[0], 0x4006, 8, 30, 104, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_deathMenu.item[1], 0x4001, 176, 30, 104, 15, 0, 0);
+ Button::Callback deathMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedDeathMenu);
+ for (int i = 0; i < 2; ++i)
+ _deathMenu.item[i].callback = deathMenuFunctor;
+
+ GUI_LOL_MENU(_savenameMenu, 7, 0x4053, 0, 2, -1, -1, -1, -1);
+ GUI_LOL_MENU_ITEM(_savenameMenu.item[0], 0x4012, 8, 38, 72, 15, 0, 43);
+ GUI_LOL_MENU_ITEM(_savenameMenu.item[1], 0x4011, 176, 38, 72, 15, 0, 110);
+ Button::Callback savenameMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedSavenameMenu);
+ for (int i = 0; i < 2; ++i)
+ _savenameMenu.item[i].callback = savenameMenuFunctor;
+
+ GUI_LOL_MENU(_choiceMenu, 11, 0, 0, 2, -1, -1, -1, -1);
+ GUI_LOL_MENU_ITEM(_choiceMenu.item[0], 0x4007, 8, 30, 72, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_choiceMenu.item[1], 0x4008, 208, 30, 72, 15, 0, 0);
+ Button::Callback choiceMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedChoiceMenu);
+ for (int i = 0; i < 2; ++i)
+ _choiceMenu.item[i].callback = choiceMenuFunctor;
+}
#endif // ENABLE_LOL
+const uint8 Screen_LoK_16::_palette16[48] = {
+ 0x00, 0x00, 0x00, 0x02, 0x07, 0x0B, 0x0C, 0x06, 0x04,
+ 0x0E, 0x09, 0x07, 0x00, 0x06, 0x03, 0x00, 0x0C, 0x07,
+ 0x0A, 0x0A, 0x0A, 0x08, 0x03, 0x03, 0x02, 0x02, 0x02,
+ 0x08, 0x0B, 0x0E, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x0A,
+ 0x05, 0x05, 0x05, 0x00, 0x0F, 0x0F, 0x0F, 0x0D, 0x00,
+ 0x0F, 0x0F, 0x0F
+};
+
const ScreenDim Screen_LoK::_screenDimTable[] = {
{ 0x00, 0x00, 0x28, 0xC8, 0x0F, 0x0C, 0x00, 0x00 },
{ 0x08, 0x48, 0x18, 0x38, 0x0F, 0x0C, 0x00, 0x00 },
@@ -3018,6 +3117,8 @@ const ScreenDim Screen_LoL::_screenDimTable256C[] = {
{ 0x0D, 0xA2, 0x18, 0x0C, 0xFE, 0x01, 0x00, 0x00 },
{ 0x0F, 0x06, 0x14, 0x6E, 0x01, 0x00, 0x00, 0x00 },
{ 0x1A, 0xBE, 0x0A, 0x07, 0xFE, 0x01, 0x00, 0x00 },
+ { 0x07, 0x21, 0x1A, 0x85, 0x00, 0x00, 0x00, 0x00 },
+ { 0x03, 0x32, 0x22, 0x62, 0x00, 0x00, 0x00, 0x00 },
{ 0x0B, 0x8C, 0x10, 0x33, 0x3D, 0x01, 0x00, 0x00 }, // Main menu box (5 entries, CD version only)
{ 0x0B, 0x8C, 0x10, 0x23, 0x3D, 0x01, 0x00, 0x00 }, // Main menu box (3 entries, floppy version only)
@@ -3045,6 +3146,8 @@ const ScreenDim Screen_LoL::_screenDimTable16C[] = {
{ 0x0D, 0xA2, 0x18, 0x0C, 0x33, 0x44, 0x00, 0x00 },
{ 0x0F, 0x06, 0x14, 0x6E, 0x44, 0x00, 0x00, 0x00 },
{ 0x1A, 0xBE, 0x0A, 0x07, 0x33, 0x44, 0x00, 0x00 },
+ { 0x07, 0x21, 0x1A, 0x85, 0x00, 0x00, 0x00, 0x00 },
+ { 0x03, 0x32, 0x22, 0x62, 0x00, 0x00, 0x00, 0x00 },
{ 0x0B, 0x8C, 0x10, 0x33, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (5 entries, not used here)
{ 0x0B, 0x8C, 0x10, 0x23, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (3 entries)
@@ -3056,6 +3159,42 @@ const ScreenDim Screen_LoL::_screenDimTable16C[] = {
const int Screen_LoL::_screenDimTableCount = ARRAYSIZE(Screen_LoL::_screenDimTable256C);
+// 256 -> 16 color conversion table
+const uint8 Screen_LoL::_paletteConvTable[256] = {
+ 0x0, 0x1, 0x0, 0x3, 0x0, 0x5, 0x0, 0x7,
+ 0x0, 0x9, 0x0, 0xB, 0x0, 0xD, 0x0, 0xF,
+ 0x1, 0x1, 0x1, 0x3, 0x1, 0x5, 0x1, 0x7,
+ 0x1, 0x9, 0x1, 0xB, 0x1, 0xD, 0x1, 0xF,
+ 0x2, 0x1, 0x2, 0x3, 0x2, 0x5, 0x2, 0x7,
+ 0x2, 0x9, 0x2, 0xB, 0x2, 0xD, 0x2, 0xF,
+ 0x3, 0x1, 0x3, 0x3, 0x3, 0x5, 0x3, 0x7,
+ 0x3, 0x9, 0x3, 0xB, 0x3, 0xD, 0x3, 0xF,
+ 0x4, 0x1, 0x4, 0x3, 0x4, 0x5, 0x4, 0x7,
+ 0x4, 0x9, 0x4, 0xB, 0x4, 0xD, 0x4, 0xF,
+ 0x5, 0x1, 0x5, 0x3, 0x5, 0x5, 0x5, 0x7,
+ 0x5, 0x9, 0x5, 0xB, 0x5, 0xD, 0x5, 0xF,
+ 0x6, 0x1, 0x6, 0x3, 0x6, 0x5, 0x6, 0x7,
+ 0x6, 0x9, 0x6, 0xB, 0x6, 0xD, 0x6, 0xF,
+ 0x7, 0x1, 0x7, 0x3, 0x7, 0x5, 0x7, 0x7,
+ 0x7, 0x9, 0x7, 0xB, 0x7, 0xD, 0x7, 0xF,
+ 0x8, 0x1, 0x8, 0x3, 0x8, 0x5, 0x8, 0x7,
+ 0x8, 0x9, 0x8, 0xB, 0x8, 0xD, 0x8, 0xF,
+ 0x9, 0x1, 0x9, 0x3, 0x9, 0x5, 0x9, 0x7,
+ 0x9, 0x9, 0x9, 0xB, 0x9, 0xD, 0x9, 0xF,
+ 0xA, 0x1, 0xA, 0x3, 0xA, 0x5, 0xA, 0x7,
+ 0xA, 0x9, 0xA, 0xB, 0xA, 0xD, 0xA, 0xF,
+ 0xB, 0x1, 0xB, 0x3, 0xB, 0x5, 0xB, 0x7,
+ 0xB, 0x9, 0xB, 0xB, 0xB, 0xD, 0xB, 0xF,
+ 0xC, 0x1, 0xC, 0x3, 0xC, 0x5, 0xC, 0x7,
+ 0xC, 0x9, 0xC, 0xB, 0xC, 0xD, 0xC, 0xF,
+ 0xD, 0x1, 0xD, 0x3, 0xD, 0x5, 0xD, 0x7,
+ 0xD, 0x9, 0xD, 0xB, 0xD, 0xD, 0xD, 0xF,
+ 0xE, 0x1, 0xE, 0x3, 0xE, 0x5, 0xE, 0x7,
+ 0xE, 0x9, 0xE, 0xB, 0xE, 0xD, 0xE, 0xF,
+ 0xF, 0x1, 0xF, 0x3, 0xF, 0x5, 0xF, 0x7,
+ 0xF, 0x9, 0xF, 0xB, 0xF, 0xD, 0xF, 0xF
+};
+
const char * const LoLEngine::_languageExt[] = {
"ENG",
"FRE",
@@ -3241,4 +3380,3 @@ const int LoLEngine::_outroMonsterScaleTableY[] = {
#endif // ENABLE_LOL
} // End of namespace Kyra
-
diff --git a/engines/kyra/text_lok.cpp b/engines/kyra/text_lok.cpp
index 6b1cb4eca2..3f4bfb65ac 100644
--- a/engines/kyra/text_lok.cpp
+++ b/engines/kyra/text_lok.cpp
@@ -39,12 +39,9 @@ void KyraEngine_LoK::waitForChatToFinish(int vocFile, int16 chatDuration, const
uint8 currPage;
Common::Event event;
- //while (towns_isEscKeyPressed() )
- //towns_getKey();
-
uint32 timeToEnd = strlen(chatStr) * 8 * _tickLength + _system->getMillis();
- if (_configVoice == 0 && chatDuration != -1) {
+ if (textEnabled() && !speechEnabled() && chatDuration != -1) {
switch (_configTextspeed) {
case 0:
chatDuration *= 2;
@@ -136,7 +133,6 @@ void KyraEngine_LoK::waitForChatToFinish(int vocFile, int16 chatDuration, const
_timer->enable(15);
_timer->enable(18);
_timer->enable(19);
- //clearKyrandiaButtonIO();
}
void KyraEngine_LoK::endCharacterChat(int8 charNum, int16 convoInitialized) {
@@ -329,11 +325,11 @@ void KyraEngine_LoK::drawSentenceCommand(const char *sentence, int color) {
_screen->fillRect(8, 143, 311, 152, 12);
if (_startSentencePalIndex != color || _fadeText != false) {
- _currSentenceColor[0] = _screen->_currentPalette[765] = _screen->_currentPalette[color*3];
- _currSentenceColor[1] = _screen->_currentPalette[766] = _screen->_currentPalette[color*3+1];
- _currSentenceColor[2] = _screen->_currentPalette[767] = _screen->_currentPalette[color*3+2];
+ _currSentenceColor[0] = _screen->getPalette(0)[765] = _screen->getPalette(0)[color*3];
+ _currSentenceColor[1] = _screen->getPalette(0)[766] = _screen->getPalette(0)[color*3+1];
+ _currSentenceColor[2] = _screen->getPalette(0)[767] = _screen->getPalette(0)[color*3+2];
- _screen->setScreenPalette(_screen->_currentPalette);
+ _screen->setScreenPalette(_screen->getPalette(0));
_startSentencePalIndex = 0;
}
@@ -368,10 +364,10 @@ void KyraEngine_LoK::updateTextFade() {
}
}
- _screen->_currentPalette[765] = _currSentenceColor[0];
- _screen->_currentPalette[766] = _currSentenceColor[1];
- _screen->_currentPalette[767] = _currSentenceColor[2];
- _screen->setScreenPalette(_screen->_currentPalette);
+ _screen->getPalette(0)[765] = _currSentenceColor[0];
+ _screen->getPalette(0)[766] = _currSentenceColor[1];
+ _screen->getPalette(0)[767] = _currSentenceColor[2];
+ _screen->setScreenPalette(_screen->getPalette(0));
if (finished) {
_fadeText = false;
diff --git a/engines/kyra/text_lol.cpp b/engines/kyra/text_lol.cpp
index 7ce12f47c7..2174bcc441 100644
--- a/engines/kyra/text_lol.cpp
+++ b/engines/kyra/text_lol.cpp
@@ -33,8 +33,8 @@
namespace Kyra {
TextDisplayer_LoL::TextDisplayer_LoL(LoLEngine *vm, Screen_LoL *screen) : _vm(vm), _screen(screen),
- _scriptParameter(0), _animWidth(0), _animColor1(0), _animColor2(0), _animFlag(true), _lineCount(0),
- _printFlag(false), _lineWidth(0), _numCharsTotal(0), _numCharsLeft(0), _numCharsPrinted(0) {
+ _scriptParameter(0), _lineCount(0), _printFlag(false), _lineWidth(0), _numCharsTotal(0),
+ _numCharsLeft(0), _numCharsPrinted(0) {
memset(_stringParameters, 0, 15 * sizeof(char *));
_buffer = new char[600];
@@ -138,7 +138,7 @@ void TextDisplayer_LoL::resetDimTextPositions(int dim) {
_textDimData[dim].line = 0;
}
-void TextDisplayer_LoL::setAnimParameters(const char *str, int x, uint8 col1, uint8 col2) {
+/*void TextDisplayer_LoL::setAnimParameters(const char *str, int x, uint8 col1, uint8 col2) {
static const char defaultStr[] = "<MORE>";
if (str) {
@@ -152,7 +152,7 @@ void TextDisplayer_LoL::setAnimParameters(const char *str, int x, uint8 col1, ui
_animColor1 = 0;
_animColor2 = 0;
}
-}
+}*/
void TextDisplayer_LoL::printDialogueText(int dim, char *str, EMCState *script, const uint16 *paramList, int16 paramIndex) {
int oldDim = 0;
@@ -496,7 +496,7 @@ void TextDisplayer_LoL::printLine(char *str) {
int lines = (sd->h - _screen->_charOffset) / fh;
while (_textDimData[sdx].line >= lines) {
- if (lines <= _lineCount && _animFlag) {
+ if (lines <= _lineCount) {
_lineCount = 0;
textPageBreak();
_numCharsPrinted = 0;
@@ -521,8 +521,8 @@ void TextDisplayer_LoL::printLine(char *str) {
char c = 0;
if ((lw + _textDimData[sdx].column) > w) {
- if ((lines - 1) <= _lineCount && _animFlag)
- w -= (_animWidth * (_screen->getFontWidth() + _screen->_charWidth));
+ if ((lines - 1) <= _lineCount)
+ w -= (10 * (_screen->getFontWidth() + _screen->_charWidth));
w -= _textDimData[sdx].column;
@@ -608,7 +608,7 @@ void TextDisplayer_LoL::textPageBreak() {
}
uint32 speechPartTime = 0;
- if (_vm->_speechFlag && _vm->_activeVoiceFileTotalTime && _numCharsTotal)
+ if (_vm->speechEnabled() && _vm->_activeVoiceFileTotalTime && _numCharsTotal)
speechPartTime = _vm->_system->getMillis() + ((_numCharsPrinted * _vm->_activeVoiceFileTotalTime) / _numCharsTotal);
const ScreenDim *dim = _screen->getScreenDim(_screen->curDimIndex());
@@ -643,7 +643,7 @@ void TextDisplayer_LoL::textPageBreak() {
while (!inputFlag) {
_vm->update();
- if (_vm->_speechFlag) {
+ if (_vm->speechEnabled()) {
if (((_vm->_system->getMillis() > speechPartTime) || (_vm->snd_updateCharacterSpeech() != 2)) && speechPartTime) {
loop = false;
inputFlag = 43;
diff --git a/engines/kyra/text_lol.h b/engines/kyra/text_lol.h
index fc707843aa..06c13e1fef 100644
--- a/engines/kyra/text_lol.h
+++ b/engines/kyra/text_lol.h
@@ -40,9 +40,6 @@ public:
TextDisplayer_LoL(LoLEngine *vm, Screen_LoL *screen);
~TextDisplayer_LoL();
- void setAnimParameters(const char *str, int x, uint8 col1, uint8 col2);
- void setAnimFlag(bool flag) { _animFlag = flag; }
-
void setupField(bool mode);
void expandField();
@@ -80,12 +77,6 @@ private:
uint32 _numCharsLeft;
uint32 _numCharsPrinted;
- const char *_animString;
- int16 _animWidth;
- uint8 _animColor1;
- uint8 _animColor2;
-
- bool _animFlag;
bool _printFlag;
LoLEngine *_vm;
diff --git a/engines/kyra/text_mr.cpp b/engines/kyra/text_mr.cpp
index e28d97d154..40f651ab01 100644
--- a/engines/kyra/text_mr.cpp
+++ b/engines/kyra/text_mr.cpp
@@ -581,7 +581,7 @@ void KyraEngine_MR::albumChatWaitToFinish() {
frame = 13;
albumRestoreRect();
- _album.wsa->displayFrame(frame, 2, -100, 90, 0x4000);
+ _album.wsa->displayFrame(frame, 2, -100, 90, 0x4000, 0, 0);
albumUpdateRect();
nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(4, 8) * _tickLength;
diff --git a/engines/kyra/util.cpp b/engines/kyra/util.cpp
index 794a1c78e3..fe02ba49ba 100644
--- a/engines/kyra/util.cpp
+++ b/engines/kyra/util.cpp
@@ -85,5 +85,68 @@ void Util::decodeString2(const char *src, char *dst) {
*dst = 0;
}
+void Util::convertDOSToISO(char *str) {
+ uint8 *s = (uint8 *)str;
+
+ for (; *s; ++s) {
+ if (*s >= 128) {
+ uint8 c = _charMapDOSToISO[*s - 128];
+
+ if (!c)
+ c = 0x20;
+
+ *s = c;
+ }
+ }
+}
+
+void Util::convertISOToDOS(char *str) {
+ while (*str)
+ convertISOToDOS(*str++);
+}
+
+void Util::convertISOToDOS(char &c) {
+ uint8 code = (uint8)c;
+ if (code >= 128) {
+ code = _charMapISOToDOS[code - 128];
+ if (!code)
+ code = 0x20;
+ }
+
+ c = code;
+}
+
+// CP850 to ISO-8859-1 (borrowed from engines/saga/font_map.cpp)
+const uint8 Util::_charMapDOSToISO[128] = {
+ 199, 252, 233, 226, 228, 224, 229, 231, 234, 235, 232,
+ 239, 238, 236, 196, 197, 201, 230, 198, 244, 246, 242,
+ 251, 249, 255, 214, 220, 248, 163, 216, 215, 0, 225,
+ 237, 243, 250, 241, 209, 170, 186, 191, 174, 172, 189,
+ 188, 161, 171, 187, 0, 0, 0, 0, 0, 193, 194,
+ 192, 169, 0, 0, 0, 0, 162, 165, 0, 0, 0,
+ 0, 0, 0, 0, 227, 195, 0, 0, 0, 0, 0,
+ 0, 0, 164, 240, 208, 202, 203, 200, 0, 205, 206,
+ 207, 0, 0, 0, 0, 166, 204, 0, 211, 223, 212,
+ 210, 245, 213, 181, 254, 222, 218, 219, 217, 253, 221,
+ 175, 180, 173, 177, 0, 190, 182, 167, 247, 184, 176,
+ 168, 183, 185, 179, 178, 0, 160
+};
+
+// ISO-8859-1 to CP850
+const uint8 Util::_charMapISOToDOS[128] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
+ 173, 189, 156, 207, 190, 221, 245, 249, 184, 166, 174,
+ 170, 240, 169, 238, 248, 241, 253, 252, 239, 230, 244,
+ 250, 247, 251, 167, 175, 172, 171, 243, 168, 183, 181,
+ 182, 199, 142, 143, 146, 128, 212, 144, 210, 211, 222,
+ 214, 215, 216, 209, 165, 227, 224, 226, 229, 153, 158,
+ 157, 235, 233, 234, 154, 237, 232, 225, 133, 160, 131,
+ 198, 132, 134, 145, 135, 138, 130, 136, 137, 141, 161,
+ 140, 139, 208, 164, 149, 162, 147, 228, 148, 246, 155,
+ 151, 163, 150, 129, 236, 231, 152
+};
+
} // end of namespace Kyra
diff --git a/engines/kyra/util.h b/engines/kyra/util.h
index ee869d9c04..6850a4d757 100644
--- a/engines/kyra/util.h
+++ b/engines/kyra/util.h
@@ -34,6 +34,16 @@ class Util {
public:
static int decodeString1(const char *src, char *dst);
static void decodeString2(const char *src, char *dst);
+
+ // Since our current GUI font uses ISO-8859-1, this
+ // conversion functionallty uses that as a base.
+ static void convertDOSToISO(char *str);
+ static void convertISOToDOS(char *str);
+ static void convertISOToDOS(char &c);
+
+private:
+ static const uint8 _charMapDOSToISO[128];
+ static const uint8 _charMapISOToDOS[128];
};
} // end of namespace Kyra
diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp
index 0b8f9c99a2..1225bc9976 100644
--- a/engines/kyra/vqa.cpp
+++ b/engines/kyra/vqa.cpp
@@ -32,12 +32,14 @@
// The jung2.vqa movie does work, but only thanks to a grotesque hack.
+#include "kyra/vqa.h"
+
#include "common/system.h"
#include "sound/audiostream.h"
#include "sound/mixer.h"
+
#include "kyra/sound.h"
#include "kyra/screen.h"
-#include "kyra/vqa.h"
#include "kyra/resource.h"
namespace Kyra {
@@ -45,6 +47,7 @@ namespace Kyra {
VQAMovie::VQAMovie(KyraEngine_v1 *vm, OSystem *system) {
_system = system;
_vm = vm;
+ _screen = _vm->screen();
_opened = false;
_x = _y = _drawPage = -1;
}
@@ -474,13 +477,13 @@ void VQAMovie::displayFrame(uint frameNum) {
case MKID_BE('CPL0'): // Palette
assert(size <= 3 * 256);
- _file->read(_vm->screen()->_currentPalette, size);
+ _file->read(_screen->getPalette(0).getData(), size);
break;
case MKID_BE('CPLZ'): // Palette
inbuf = (byte *)allocBuffer(0, size);
_file->read(inbuf, size);
- Screen::decodeFrame4(inbuf, _vm->screen()->_currentPalette, 768);
+ Screen::decodeFrame4(inbuf, _screen->getPalette(0).getData(), 768);
break;
case MKID_BE('VPT0'): // Frame data
@@ -520,9 +523,8 @@ void VQAMovie::displayFrame(uint frameNum) {
// The frame has been decoded
- if (_frameInfo[frameNum] & 0x80000000) {
- _vm->screen()->setScreenPalette(_vm->screen()->_currentPalette);
- }
+ if (_frameInfo[frameNum] & 0x80000000)
+ _screen->setScreenPalette(_screen->getPalette(0));
int blockPitch = _header.width / _header.blockW;
@@ -562,7 +564,7 @@ void VQAMovie::displayFrame(uint frameNum) {
_partialCodeBookSize = 0;
}
- _vm->screen()->copyBlockToPage(_drawPage, _x, _y, _header.width, _header.height, _frame);
+ _screen->copyBlockToPage(_drawPage, _x, _y, _header.width, _header.height, _frame);
}
void VQAMovie::play() {
@@ -638,6 +640,7 @@ void VQAMovie::play() {
}
_vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sound, _stream);
+ Common::EventManager *eventMan = _vm->getEventManager();
for (uint i = 0; i < _header.numFrames; i++) {
displayFrame(i);
@@ -656,17 +659,17 @@ void VQAMovie::play() {
break;
Common::Event event;
-
- Common::EventManager *eventMan = _system->getEventManager();
while (eventMan->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_KEYDOWN:
- if (event.kbd.ascii == 27)
+ if (event.kbd.keycode == Common::KEYCODE_ESCAPE)
return;
break;
+
case Common::EVENT_RTL:
case Common::EVENT_QUIT:
return;
+
default:
break;
}
@@ -675,7 +678,7 @@ void VQAMovie::play() {
_system->delayMillis(10);
}
- _vm->screen()->updateScreen();
+ _screen->updateScreen();
}
// TODO: Wait for the sound to finish?
diff --git a/engines/kyra/vqa.h b/engines/kyra/vqa.h
index 46d3bd48fb..98e279bd29 100644
--- a/engines/kyra/vqa.h
+++ b/engines/kyra/vqa.h
@@ -26,13 +26,24 @@
#ifndef KYRA_VQA_H
#define KYRA_VQA_H
-#include "common/stream.h"
+#include "common/scummsys.h"
+
+#include "sound/mixer.h"
class OSystem;
+namespace Audio {
+class AppendableAudioStream;
+} // end of namespace Audio
+
+namespace Common {
+class SeekableReadStream;
+} // end of namespace Common
+
namespace Kyra {
class KyraEngine_v1;
+class Screen;
class VQAMovie {
public:
@@ -57,6 +68,7 @@ public:
protected:
OSystem *_system;
KyraEngine_v1 *_vm;
+ Screen *_screen;
bool _opened;
int _x, _y;
diff --git a/engines/kyra/wsamovie.cpp b/engines/kyra/wsamovie.cpp
index 26638b8172..ef3fd1a966 100644
--- a/engines/kyra/wsamovie.cpp
+++ b/engines/kyra/wsamovie.cpp
@@ -38,7 +38,7 @@ namespace Kyra {
WSAMovie_v1::WSAMovie_v1(KyraEngine_v1 *vm) : Movie(vm) {}
WSAMovie_v1::~WSAMovie_v1() { close(); }
-int WSAMovie_v1::open(const char *filename, int offscreenDecode, uint8 *palBuf) {
+int WSAMovie_v1::open(const char *filename, int offscreenDecode, Palette *palBuf) {
close();
uint32 flags = 0;
@@ -64,7 +64,7 @@ int WSAMovie_v1::open(const char *filename, int offscreenDecode, uint8 *palBuf)
offsPal = 0x300;
_flags |= WF_HAS_PALETTE;
if (palBuf)
- memcpy(palBuf, wsaData + 8 + (_numFrames << 2), 0x300);
+ _screen->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), *palBuf, 0x300);
}
if (offscreenDecode) {
@@ -137,19 +137,19 @@ void WSAMovie_v1::close() {
}
}
-void WSAMovie_v1::displayFrame(int frameNum, int pageNum, int x, int y, ...) {
- if (frameNum >= _numFrames || !_opened)
+void WSAMovie_v1::displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2) {
+ if (frameNum >= _numFrames || frameNum < 0 || !_opened)
return;
_x = x;
_y = y;
_drawPage = pageNum;
- uint8 *dst;
+ uint8 *dst = 0;
if (_flags & WF_OFFSCREEN_DECODE)
dst = _offscreenBuffer;
else
- dst = _vm->screen()->getPageRect(_drawPage, _x, _y, _width, _height);
+ dst = _screen->getPageRect(_drawPage, _x, _y, _width, _height);
if (_currentFrame == _numFrames) {
if (!(_flags & WF_NO_FIRST_FRAME)) {
@@ -200,8 +200,16 @@ void WSAMovie_v1::displayFrame(int frameNum, int pageNum, int x, int y, ...) {
// display
_currentFrame = frameNum;
- if (_flags & WF_OFFSCREEN_DECODE)
- _vm->screen()->copyBlockToPage(_drawPage, _x, _y, _width, _height, _offscreenBuffer);
+ if (_flags & WF_OFFSCREEN_DECODE) {
+ int pageBackUp = _screen->setCurPage(_drawPage);
+
+ int plotFunc = (flags & 0xFF00) >> 12;
+ int unk1 = flags & 0xFF;
+
+ _screen->copyWsaRect(_x, _y, _width, _height, 0, plotFunc, _offscreenBuffer, unk1, table1, table2);
+
+ _screen->_curPage = pageBackUp;
+ }
}
void WSAMovie_v1::processFrame(int frameNum, uint8 *dst) {
@@ -220,7 +228,7 @@ void WSAMovie_v1::processFrame(int frameNum, uint8 *dst) {
WSAMovieAmiga::WSAMovieAmiga(KyraEngine_v1 *vm) : WSAMovie_v1(vm), _buffer(0) {}
-int WSAMovieAmiga::open(const char *filename, int offscreenDecode, uint8 *palBuf) {
+int WSAMovieAmiga::open(const char *filename, int offscreenDecode, Palette *palBuf) {
int res = WSAMovie_v1::open(filename, offscreenDecode, palBuf);
if (!res)
@@ -239,7 +247,7 @@ void WSAMovieAmiga::close() {
WSAMovie_v1::close();
}
-void WSAMovieAmiga::displayFrame(int frameNum, int pageNum, int x, int y, ...) {
+void WSAMovieAmiga::displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2) {
if (frameNum >= _numFrames || frameNum < 0 || !_opened)
return;
@@ -266,7 +274,7 @@ void WSAMovieAmiga::displayFrame(int frameNum, int pageNum, int x, int y, ...) {
dst = _buffer;
} else {
- _vm->screen()->copyBlockToPage(_drawPage, _x, _y, _width, _height, _buffer);
+ _screen->copyBlockToPage(_drawPage, _x, _y, _width, _height, _buffer);
}
}
_currentFrame = 0;
@@ -311,8 +319,16 @@ void WSAMovieAmiga::displayFrame(int frameNum, int pageNum, int x, int y, ...) {
// display
_currentFrame = frameNum;
- if (_flags & WF_OFFSCREEN_DECODE)
- _vm->screen()->copyBlockToPage(_drawPage, _x, _y, _width, _height, _offscreenBuffer);
+ if (_flags & WF_OFFSCREEN_DECODE) {
+ int pageBackUp = _screen->setCurPage(_drawPage);
+
+ int plotFunc = (flags & 0xFF00) >> 12;
+ int unk1 = flags & 0xFF;
+
+ _screen->copyWsaRect(_x, _y, _width, _height, 0, plotFunc, _offscreenBuffer, unk1, table1, table2);
+
+ _screen->_curPage = pageBackUp;
+ }
}
void WSAMovieAmiga::processFrame(int frameNum, uint8 *dst) {
@@ -334,7 +350,7 @@ void WSAMovieAmiga::processFrame(int frameNum, uint8 *dst) {
dst = _offscreenBuffer;
dstPitch = _width;
} else {
- dst = _vm->screen()->getPageRect(_drawPage, _x, _y, _width, _height);
+ dst = _screen->getPageRect(_drawPage, _x, _y, _width, _height);
dstPitch = Screen::SCREEN_W;
}
@@ -347,9 +363,9 @@ void WSAMovieAmiga::processFrame(int frameNum, uint8 *dst) {
#pragma mark -
-WSAMovie_v2::WSAMovie_v2(KyraEngine_v1 *vm, Screen_v2 *screen) : WSAMovie_v1(vm), _screen(screen), _xAdd(0), _yAdd(0) {}
+WSAMovie_v2::WSAMovie_v2(KyraEngine_v1 *vm) : WSAMovie_v1(vm), _xAdd(0), _yAdd(0) {}
-int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) {
+int WSAMovie_v2::open(const char *filename, int unk1, Palette *palBuf) {
close();
uint32 flags = 0;
@@ -376,7 +392,7 @@ int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) {
offsPal = 0x300;
_flags |= WF_HAS_PALETTE;
if (palBuf)
- _vm->screen()->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), palBuf, 0x300);
+ _screen->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), *palBuf, 0x300);
}
if (flags & 2) {
@@ -384,7 +400,7 @@ int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) {
offsPal = 0x30;
_flags |= WF_HAS_PALETTE;
if (palBuf)
- _vm->screen()->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), palBuf, 0x30);
+ _screen->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), *palBuf, 0x30);
}
_flags |= WF_XOR;
@@ -448,90 +464,6 @@ int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) {
return _numFrames;
}
-void WSAMovie_v2::displayFrame(int frameNum, int pageNum, int x, int y, ...) {
- if (frameNum >= _numFrames || frameNum < 0 || !_opened)
- return;
-
- _x = x + _xAdd;
- _y = y + _yAdd;
- _drawPage = pageNum;
-
- uint8 *dst = 0;
- if (_flags & WF_OFFSCREEN_DECODE)
- dst = _offscreenBuffer;
- else
- dst = _screen->getPageRect(_drawPage, _x, _y, _width, _height);
-
- if (_currentFrame == _numFrames) {
- if (!(_flags & WF_NO_FIRST_FRAME)) {
- if (_flags & WF_OFFSCREEN_DECODE)
- Screen::decodeFrameDelta(dst, _deltaBuffer);
- else
- Screen::decodeFrameDeltaPage(dst, _deltaBuffer, _width, (_flags & WF_XOR) == 0);
- }
- _currentFrame = 0;
- }
-
- // try to reduce the number of needed frame operations
- int diffCount = ABS(_currentFrame - frameNum);
- int frameStep = 1;
- int frameCount;
- if (_currentFrame < frameNum) {
- frameCount = _numFrames - frameNum + _currentFrame;
- if (diffCount > frameCount && !(_flags & WF_NO_LAST_FRAME))
- frameStep = -1;
- else
- frameCount = diffCount;
- } else {
- frameCount = _numFrames - _currentFrame + frameNum;
- if (frameCount >= diffCount || (_flags & WF_NO_LAST_FRAME)) {
- frameStep = -1;
- frameCount = diffCount;
- }
- }
-
- // process
- if (frameStep > 0) {
- uint16 cf = _currentFrame;
- while (frameCount--) {
- cf += frameStep;
- processFrame(cf, dst);
- if (cf == _numFrames)
- cf = 0;
- }
- } else {
- uint16 cf = _currentFrame;
- while (frameCount--) {
- if (cf == 0)
- cf = _numFrames;
- processFrame(cf, dst);
- cf += frameStep;
- }
- }
-
- // display
- _currentFrame = frameNum;
- if (_flags & WF_OFFSCREEN_DECODE) {
- int pageBackUp = _screen->_curPage;
- _screen->_curPage = _drawPage;
-
- va_list args;
- va_start(args, y);
-
- int copyParam = va_arg(args, int);
- int plotFunc = (copyParam & 0xFF00) >> 12;
- int unk1 = copyParam & 0xFF;
-
- const uint8 *unkPtr1 = va_arg(args, const uint8*);
- const uint8 *unkPtr2 = va_arg(args, const uint8*);
- va_end(args);
-
- _screen->copyWsaRect(_x, _y, _width, _height, 0, plotFunc, _offscreenBuffer, unk1, unkPtr1, unkPtr2);
-
- _screen->_curPage = pageBackUp;
- }
-}
-
} // end of namespace Kyra
diff --git a/engines/kyra/wsamovie.h b/engines/kyra/wsamovie.h
index fdceca1cd8..49ac5a28fe 100644
--- a/engines/kyra/wsamovie.h
+++ b/engines/kyra/wsamovie.h
@@ -26,6 +26,7 @@
#ifndef KYRA_WSAMOVIE_H
#define KYRA_WSAMOVIE_H
+
namespace Audio {
class AppendableAudioStream;
class SoundHandle;
@@ -34,10 +35,11 @@ class SoundHandle;
namespace Kyra {
class KyraEngine_v1;
class Screen_v2;
+class Palette;
class Movie {
public:
- Movie(KyraEngine_v1 *vm) : _vm(vm), _opened(false), _x(-1), _y(-1), _drawPage(-1) {}
+ Movie(KyraEngine_v1 *vm) : _vm(vm), _screen(vm->screen()), _opened(false), _x(-1), _y(-1), _drawPage(-1) {}
virtual ~Movie() {}
virtual bool opened() { return _opened; }
@@ -48,15 +50,16 @@ public:
virtual int width() const = 0;
virtual int height() const = 0;
- virtual int open(const char *filename, int offscreen, uint8 *palette) = 0;
+ virtual int open(const char *filename, int offscreen, Palette *palette) = 0;
virtual void close() = 0;
virtual int frames() = 0;
- virtual void displayFrame(int frameNum, int pageNum, int x, int y, ...) = 0;
+ virtual void displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2) = 0;
protected:
KyraEngine_v1 *_vm;
+ Screen *_screen;
bool _opened;
int _x, _y;
@@ -71,12 +74,12 @@ public:
int width() const { return _width; }
int height() const { return _height; }
- virtual int open(const char *filename, int offscreen, uint8 *palette);
+ virtual int open(const char *filename, int offscreen, Palette *palette);
virtual void close();
virtual int frames() { return _opened ? _numFrames : -1; }
- virtual void displayFrame(int frameNum, int pageNum, int x, int y, ...);
+ virtual void displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2);
enum WSAFlags {
WF_OFFSCREEN_DECODE = 0x10,
@@ -104,10 +107,10 @@ protected:
class WSAMovieAmiga : public WSAMovie_v1 {
public:
WSAMovieAmiga(KyraEngine_v1 *vm);
- int open(const char *filename, int offscreen, uint8 *palette);
+ int open(const char *filename, int offscreen, Palette *palette);
void close();
- void displayFrame(int frameNum, int pageNum, int x, int y, ...);
+ void displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2);
private:
void processFrame(int frameNum, uint8 *dst);
@@ -116,11 +119,12 @@ private:
class WSAMovie_v2 : public WSAMovie_v1 {
public:
- WSAMovie_v2(KyraEngine_v1 *vm, Screen_v2 *screen);
-
- int open(const char *filename, int unk1, uint8 *palette);
+ WSAMovie_v2(KyraEngine_v1 *vm);
- virtual void displayFrame(int frameNum, int pageNum, int x, int y, ...);
+ int open(const char *filename, int unk1, Palette *palette);
+ virtual void displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2) {
+ WSAMovie_v1::displayFrame(frameNum, pageNum, x + _xAdd, y + _yAdd, flags, table1, table2);
+ }
int xAdd() const { return _xAdd; }
int yAdd() const { return _yAdd; }
@@ -128,8 +132,6 @@ public:
void setWidth(int w) { _width = w; }
void setHeight(int h) { _height = h; }
protected:
- Screen_v2 *_screen;
-
int16 _xAdd;
int16 _yAdd;
};
diff --git a/engines/parallaction/disk.cpp b/engines/parallaction/disk.cpp
new file mode 100644
index 0000000000..6928c1eefc
--- /dev/null
+++ b/engines/parallaction/disk.cpp
@@ -0,0 +1,145 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "parallaction/disk.h"
+#include "parallaction/graphics.h"
+
+namespace Parallaction {
+
+void ILBMLoader::setupBuffer(uint32 w, uint32 h) {
+ _intBuffer = 0;
+ switch (_bodyMode) {
+ case BODYMODE_SURFACE:
+ if (!_surf) {
+ _surf = new Graphics::Surface;
+ assert(_surf);
+ }
+ _surf->create(w, h, 1);
+ _mode = Graphics::ILBMDecoder::ILBM_UNPACK_PLANES;
+ _intBuffer = (byte*)_surf->pixels;
+ break;
+
+ case BODYMODE_MASKBUFFER:
+ if (!_maskBuffer) {
+ _maskBuffer = new MaskBuffer;
+ assert(_maskBuffer);
+ }
+ _maskBuffer->create(w, h);
+ _mode = Graphics::ILBMDecoder::ILBM_2_PACK_PLANES;
+ _intBuffer = _maskBuffer->data;
+ break;
+
+ case BODYMODE_PATHBUFFER:
+ if (!_pathBuffer) {
+ _pathBuffer = new PathBuffer;
+ assert(_pathBuffer);
+ }
+ _pathBuffer->create(w, h);
+ _mode = Graphics::ILBMDecoder::ILBM_1_PACK_PLANES;
+ _intBuffer = _pathBuffer->data;
+ break;
+
+ default:
+ error("Invalid bodyMode '%i' for ILBMLoader", _bodyMode);
+ break;
+ }
+}
+
+bool ILBMLoader::callback(Common::IFFChunk &chunk) {
+ switch (chunk._type) {
+ case ID_BMHD:
+ _decoder.loadHeader(chunk._stream);
+ break;
+
+ case ID_CMAP:
+ if (_palette) {
+ chunk._stream->read(_palette, chunk._size);
+ }
+ break;
+
+ case ID_CRNG:
+ if (_crng) {
+ PaletteFxRange *ptr = &_crng[_numCRNG];
+ chunk._stream->read((byte*)ptr, chunk._size);
+ ptr->_timer = FROM_BE_16(ptr->_timer);
+ ptr->_step = FROM_BE_16(ptr->_step);
+ ptr->_flags = FROM_BE_16(ptr->_flags);
+ ++_numCRNG;
+ }
+ break;
+
+ case ID_BODY:
+ setupBuffer(_decoder._header.width, _decoder._header.height);
+ assert(_intBuffer);
+ _decoder.loadBitmap(_mode, _intBuffer, chunk._stream);
+ return true; // stop the parser
+ }
+
+ return false;
+}
+
+void ILBMLoader::load(Common::ReadStream *in, bool disposeStream) {
+ Common::IFFParser parser(in, disposeStream);
+ Common::Functor1Mem< Common::IFFChunk&, bool, ILBMLoader > c(this, &ILBMLoader::callback);
+ parser.parse(c);
+}
+
+ILBMLoader::ILBMLoader(uint32 bodyMode, byte *palette, PaletteFxRange *crng) {
+ _bodyMode = bodyMode;
+ _surf = 0;
+ _maskBuffer = 0;
+ _pathBuffer = 0;
+ _palette = palette;
+ _crng = crng;
+ _numCRNG = 0;
+}
+
+ILBMLoader::ILBMLoader(Graphics::Surface *surf, byte *palette, PaletteFxRange *crng) {
+ _bodyMode = ILBMLoader::BODYMODE_SURFACE;
+ _surf = surf;
+ _palette = palette;
+ _crng = crng;
+ _numCRNG = 0;
+}
+
+ILBMLoader::ILBMLoader(MaskBuffer *buffer) {
+ _bodyMode = ILBMLoader::BODYMODE_MASKBUFFER;
+ _maskBuffer = buffer;
+ _palette = 0;
+ _crng = 0;
+ _numCRNG = 0;
+}
+
+ILBMLoader::ILBMLoader(PathBuffer *buffer) {
+ _bodyMode = ILBMLoader::BODYMODE_PATHBUFFER;
+ _pathBuffer = buffer;
+ _palette = 0;
+ _crng = 0;
+ _numCRNG = 0;
+}
+
+
+
+}
diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h
index 4cc2711e96..a9da429473 100644
--- a/engines/parallaction/disk.h
+++ b/engines/parallaction/disk.h
@@ -33,6 +33,7 @@
#include "common/file.h"
#include "graphics/surface.h"
+#include "graphics/iff.h"
@@ -77,8 +78,37 @@ public:
virtual Table* loadTable(const char* name) = 0;
virtual Common::SeekableReadStream* loadMusic(const char* name) = 0;
virtual Common::SeekableReadStream* loadSound(const char* name) = 0;
- virtual void loadMask(const char *name, MaskBuffer &buffer) { }
- virtual void loadPath(const char *name, PathBuffer &buffer) { }
+ virtual MaskBuffer *loadMask(const char *name, uint32 w, uint32 h) { return 0; }
+ virtual PathBuffer *loadPath(const char *name, uint32 w, uint32 h) { return 0; }
+};
+
+struct PaletteFxRange;
+
+struct ILBMLoader {
+ enum {
+ BODYMODE_SURFACE,
+ BODYMODE_MASKBUFFER,
+ BODYMODE_PATHBUFFER
+ };
+ uint32 _bodyMode;
+ Graphics::Surface *_surf;
+ MaskBuffer *_maskBuffer;
+ PathBuffer *_pathBuffer;
+ byte *_palette;
+ PaletteFxRange *_crng;
+ uint32 _mode;
+ byte* _intBuffer;
+ uint32 _numCRNG;
+ Graphics::ILBMDecoder _decoder;
+
+ ILBMLoader(uint32 bodyMode, byte *palette = 0, PaletteFxRange *crng = 0);
+ ILBMLoader(Graphics::Surface *surf, byte *palette = 0, PaletteFxRange *crng = 0);
+ ILBMLoader(MaskBuffer *buffer);
+ ILBMLoader(PathBuffer *buffer);
+
+ bool callback(Common::IFFChunk &chunk);
+ void setupBuffer(uint32 w, uint32 h);
+ void load(Common::ReadStream *in, bool disposeStream = false);
};
@@ -235,8 +265,8 @@ public:
Table* loadTable(const char* name);
Common::SeekableReadStream* loadMusic(const char* name);
Common::SeekableReadStream* loadSound(const char* name);
- void loadMask(const char *name, MaskBuffer &buffer);
- void loadPath(const char *name, PathBuffer &buffer);
+ MaskBuffer *loadMask(const char *name, uint32 w, uint32 h);
+ PathBuffer *loadPath(const char *name, uint32 w, uint32 h);
};
class DosDemoDisk_br : public DosDisk_br {
@@ -272,7 +302,7 @@ public:
GfxObj* loadObjects(const char *name, uint8 part = 0);
Common::SeekableReadStream* loadMusic(const char* name);
Common::SeekableReadStream* loadSound(const char* name);
- void loadMask(const char *name, MaskBuffer &buffer);
+ MaskBuffer *loadMask(const char *name, uint32 w, uint32 h);
};
} // namespace Parallaction
diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp
index ec4fc32cc1..46c849e6f2 100644
--- a/engines/parallaction/disk_br.cpp
+++ b/engines/parallaction/disk_br.cpp
@@ -28,7 +28,6 @@
#include "common/config-manager.h"
#include "parallaction/parallaction.h"
#include "parallaction/parser.h"
-#include "parallaction/iff.h"
namespace Parallaction {
@@ -331,32 +330,40 @@ void DosDisk_br::loadSlide(BackgroundInfo& info, const char *name) {
}
}
-void DosDisk_br::loadMask(const char *name, MaskBuffer &buffer) {
+MaskBuffer *DosDisk_br::loadMask(const char *name, uint32 w, uint32 h) {
if (!name) {
- return;
+ return 0;
}
Common::SeekableReadStream *stream = openFile("msk/" + Common::String(name), ".msk");
- // NOTE: info.width and info.height are only valid if the background graphics
- // have already been loaded
- buffer.bigEndian = false;
- stream->read(buffer.data, buffer.size);
+ MaskBuffer *buffer = new MaskBuffer;
+ assert(buffer);
+ buffer->create(w, h);
+ buffer->bigEndian = false;
+
+ stream->read(buffer->data, buffer->size);
delete stream;
+
+ return buffer;
}
-void DosDisk_br::loadPath(const char *name, PathBuffer &buffer) {
+PathBuffer *DosDisk_br::loadPath(const char *name, uint32 w, uint32 h) {
if (!name) {
- return;
+ return 0;
}
Common::SeekableReadStream *stream = openFile("pth/" + Common::String(name), ".pth");
- // NOTE: info.width and info.height are only valid if the background graphics
- // have already been loaded
- buffer.bigEndian = false;
- stream->read(buffer.data, buffer.size);
+ PathBuffer *buffer = new PathBuffer;
+ assert(buffer);
+ buffer->create(w, h);
+ buffer->bigEndian = false;
+
+ stream->read(buffer->data, buffer->size);
delete stream;
+
+ return buffer;
}
void DosDisk_br::loadScenery(BackgroundInfo& info, const char *name, const char *mask, const char* path) {
@@ -380,18 +387,12 @@ void DosDisk_br::loadScenery(BackgroundInfo& info, const char *name, const char
}
if (mask) {
- info._mask = new MaskBuffer;
- info._mask->create(info.width, info.height);
- loadMask(mask, *info._mask);
+ info._mask = loadMask(mask, info.width, info.height);
}
if (path) {
- info._path = new PathBuffer;
- info._path->create(info.width, info.height);
- loadPath(path, *info._path);
+ info._path = loadPath(path, info.width, info.height);
}
-
- return;
}
Table* DosDisk_br::loadTable(const char* name) {
@@ -459,7 +460,7 @@ void AmigaDisk_br::adjustForPalette(Graphics::Surface &surf, int transparentColo
void AmigaDisk_br::loadBackground(BackgroundInfo& info, const char *filename) {
byte r,g,b;
- byte *pal, *p;
+ byte *p;
Common::SeekableReadStream *stream;
uint i;
@@ -488,20 +489,14 @@ void AmigaDisk_br::loadBackground(BackgroundInfo& info, const char *filename) {
}
stream = openFile("backs/" + Common::String(filename), ".bkg");
- ILBMDecoder decoder(stream, true);
- // TODO: encapsulate surface creation
- info.bg.w = decoder.getWidth();
- info.bg.h = decoder.getHeight();
- info.bg.pitch = info.bg.w;
- info.bg.bytesPerPixel = 1;
- info.bg.pixels = decoder.getBitmap();
- assert(info.bg.pixels);
+ byte pal[768];
+ ILBMLoader loader(&info.bg, pal);
+ loader.load(stream, true);
info.width = info.bg.w;
info.height = info.bg.h;
- pal = decoder.getPalette();
p = pal;
for (i = 16; i < 32; i++) {
r = *p >> 2;
@@ -516,8 +511,6 @@ void AmigaDisk_br::loadBackground(BackgroundInfo& info, const char *filename) {
// Overwrite the first color (transparent key) in the palette
info.palette.setEntry(0, pal[0] >> 2, pal[1] >> 2, pal[2] >> 0);
- delete []pal;
-
// background data is drawn used the upper portion of the palette
adjustForPalette(info.bg);
}
@@ -543,27 +536,24 @@ void finalpass(byte *buffer, uint32 size) {
}
}
-void AmigaDisk_br::loadMask(const char *name, MaskBuffer &buffer) {
+MaskBuffer *AmigaDisk_br::loadMask(const char *name, uint32 w, uint32 h) {
if (!name) {
- return;
+ return 0;
}
debugC(1, kDebugDisk, "AmigaDisk_br::loadMask '%s'", name);
Common::SeekableReadStream *stream = tryOpenFile("msk/" + Common::String(name), ".msk");
if (!stream) {
- return;
+ return 0;
}
- ILBMDecoder decoder(stream, true);
+ ILBMLoader loader(ILBMLoader::BODYMODE_MASKBUFFER);
+ loader.load(stream, true);
- // TODO: the buffer is allocated by the caller, so a copy here is
- // unavoidable... a better solution would be inform the function
- // of the size of the mask (the size in the mask file is not valid!)
- byte *bitmap = decoder.getBitmap(2, true);
- memcpy(buffer.data, bitmap, buffer.size);
- finalpass(buffer.data, buffer.size);
-
- buffer.bigEndian = true;
+ MaskBuffer *buffer = loader._maskBuffer;
+ buffer->bigEndian = true;
+ finalpass(buffer->data, buffer->size);
+ return buffer;
}
void AmigaDisk_br::loadScenery(BackgroundInfo& info, const char* name, const char* mask, const char* path) {
@@ -573,18 +563,12 @@ void AmigaDisk_br::loadScenery(BackgroundInfo& info, const char* name, const cha
loadBackground(info, name);
}
if (mask) {
- info._mask = new MaskBuffer;
- info._mask->create(info.width, info.height);
- loadMask(mask, *info._mask);
+ info._mask = loadMask(mask, info.width, info.height);
}
if (path) {
- info._path = new PathBuffer;
- info._path->create(info.width, info.height);
- loadPath(path, *info._path);
+ info._path = loadPath(path, info.width, info.height);
}
-
- return;
}
void AmigaDisk_br::loadSlide(BackgroundInfo& info, const char *name) {
@@ -596,20 +580,13 @@ GfxObj* AmigaDisk_br::loadStatic(const char* name) {
debugC(1, kDebugDisk, "AmigaDisk_br::loadStatic '%s'", name);
Common::String sName = name;
-
Common::SeekableReadStream *stream = openFile("ras/" + sName, ".ras");
- ILBMDecoder decoder(stream, true);
- Graphics::Surface* surf = new Graphics::Surface;
- assert(surf);
+ ILBMLoader loader(ILBMLoader::BODYMODE_SURFACE);
+ loader.load(stream, true);
- // TODO: encapsulate surface creation
- surf->w = decoder.getWidth();
- surf->h = decoder.getHeight();
- surf->pitch = surf->w;
- surf->bytesPerPixel = 1;
- surf->pixels = decoder.getBitmap();
- assert(surf->pixels);
+ Graphics::Surface* surf = loader._surf;
+ assert(surf);
// Static pictures are drawn used the upper half of the palette: this must be
// done before shadow mask is applied. This way, only really transparent pixels
@@ -741,15 +718,16 @@ GfxObj* AmigaDisk_br::loadObjects(const char *name, uint8 part) {
debugC(5, kDebugDisk, "AmigaDisk_br::loadObjects");
Common::SeekableReadStream *stream = openFile(name);
- ILBMDecoder decoder(stream, true);
+ ILBMLoader loader(ILBMLoader::BODYMODE_SURFACE);
+ loader.load(stream, true);
uint16 max = objectsMax[part];
if (_vm->getFeatures() & GF_DEMO)
max = 72;
byte *data = new byte[max * 2601];
- byte *srcPtr = decoder.getBitmap();
- int w = decoder.getWidth();
+ byte *srcPtr = (byte*)loader._surf->getBasePtr(0,0);
+ int w = loader._surf->w;
// Convert to the expected display format
for (int i = 0; i < max; i++) {
@@ -764,7 +742,7 @@ GfxObj* AmigaDisk_br::loadObjects(const char *name, uint8 part) {
dst += 51;
}
}
- free(srcPtr);
+ delete loader._surf;
return new GfxObj(0, new Cnv(max, 51, 51, data, true));
}
diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp
index 8aa2a9f543..d35b338069 100644
--- a/engines/parallaction/disk_ns.cpp
+++ b/engines/parallaction/disk_ns.cpp
@@ -23,18 +23,11 @@
*
*/
-#include "parallaction/iff.h"
#include "common/config-manager.h"
#include "parallaction/parser.h"
#include "parallaction/parallaction.h"
-namespace Audio {
- class AudioStream;
-
- AudioStream *make8SVXStream(Common::ReadStream &input);
-}
-
namespace Parallaction {
@@ -900,56 +893,18 @@ void AmigaDisk_ns::buildMask(byte* buf) {
}
}
-// TODO: extend the ILBMDecoder to return CRNG chunks and get rid of this BackgroundDecoder crap
-class BackgroundDecoder : public ILBMDecoder {
-
-public:
- BackgroundDecoder(Common::SeekableReadStream *input, bool disposeStream = false) : ILBMDecoder(input, disposeStream) {
- }
-
- uint32 getCRNG(PaletteFxRange *ranges, uint32 num) {
- assert(ranges);
-
- uint32 size = _parser.getIFFBlockSize(ID_CRNG);
- if (size == (uint32)-1) {
- return 0;
- }
-
- uint32 count = MIN((uint32)(size / sizeof(PaletteFxRange)), num);
- _parser.loadIFFBlock(ID_CRNG, ranges, count * sizeof(PaletteFxRange));
-
- for (uint32 i = 0; i < count; ++i) {
- ranges[i]._timer = FROM_BE_16(ranges[i]._timer);
- ranges[i]._step = FROM_BE_16(ranges[i]._step);
- ranges[i]._flags = FROM_BE_16(ranges[i]._flags);
- }
-
- return count;
- }
-};
-
void AmigaDisk_ns::loadBackground(BackgroundInfo& info, const char *name) {
-
- Common::SeekableReadStream *s = openFile(name);
- BackgroundDecoder decoder(s, true);
-
PaletteFxRange ranges[6];
- memset(ranges, 0, 6*sizeof(PaletteFxRange));
- decoder.getCRNG(ranges, 6);
+ byte pal[768];
- // TODO: encapsulate surface creation
- info.bg.w = decoder.getWidth();
- info.bg.h = decoder.getHeight();
- info.bg.pitch = info.bg.w;
- info.bg.bytesPerPixel = 1;
- info.bg.pixels = decoder.getBitmap();
+ Common::SeekableReadStream *s = openFile(name);
+ ILBMLoader loader(&info.bg, pal, ranges);
+ loader.load(s, true);
info.width = info.bg.w;
info.height = info.bg.h;
- byte *pal = decoder.getPalette();
- assert(pal);
byte *p = pal;
for (uint i = 0; i < 32; i++) {
byte r = *p >> 2;
@@ -960,7 +915,6 @@ void AmigaDisk_ns::loadBackground(BackgroundInfo& info, const char *name) {
p++;
info.palette.setEntry(i, r, g, b);
}
- delete []pal;
for (uint j = 0; j < 6; j++) {
info.setPaletteRange(j, ranges[j]);
@@ -979,9 +933,9 @@ void AmigaDisk_ns::loadMask(BackgroundInfo& info, const char *name) {
return; // no errors if missing mask files: not every location has one
}
- ILBMDecoder decoder(s, true);
- byte *pal = decoder.getPalette();
- assert(pal);
+ byte pal[768];
+ ILBMLoader loader(ILBMLoader::BODYMODE_MASKBUFFER, pal);
+ loader.load(s, true);
byte r, g, b;
for (uint i = 0; i < 4; i++) {
@@ -990,14 +944,8 @@ void AmigaDisk_ns::loadMask(BackgroundInfo& info, const char *name) {
b = pal[i*3+2];
info.layers[i] = (((r << 4) & 0xF00) | (g & 0xF0) | (b >> 4)) & 0xFF;
}
- delete []pal;
- info._mask = new MaskBuffer;
- info._mask->w = info.width;
- info._mask->h = info.height;
- info._mask->internalWidth = info.width >> 2;
- info._mask->size = info._mask->internalWidth * info._mask->h;
- info._mask->data = decoder.getBitmap(2, true);
+ info._mask = loader._maskBuffer;
}
void AmigaDisk_ns::loadPath(BackgroundInfo& info, const char *name) {
@@ -1010,15 +958,10 @@ void AmigaDisk_ns::loadPath(BackgroundInfo& info, const char *name) {
return; // no errors if missing path files: not every location has one
}
- ILBMDecoder decoder(s, true);
- info._path = new PathBuffer;
- info._path->create(info.width, info.height);
+ ILBMLoader loader(ILBMLoader::BODYMODE_PATHBUFFER);
+ loader.load(s, true);
+ info._path = loader._pathBuffer;
info._path->bigEndian = true;
-
- byte *bitmap = decoder.getBitmap(1, true);
- assert(bitmap);
- memcpy(info._path->data, bitmap, info._path->size);
- delete bitmap;
}
void AmigaDisk_ns::loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path) {
diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp
index ec72b14c15..fc6cb28d9e 100644
--- a/engines/parallaction/gfxbase.cpp
+++ b/engines/parallaction/gfxbase.cpp
@@ -162,9 +162,7 @@ void BackgroundInfo::loadGfxObjMask(const char *name, GfxObj *obj) {
Common::Rect rect;
obj->getRect(0, rect);
- MaskBuffer *buf = new MaskBuffer;
- buf->create(rect.width(), rect.height());
- _vm->_disk->loadMask(name, *buf);
+ MaskBuffer *buf = _vm->_disk->loadMask(name, rect.width(), rect.height());
obj->_maskId = addMaskPatch(buf);
obj->_hasMask = true;
@@ -174,9 +172,7 @@ void BackgroundInfo::loadGfxObjPath(const char *name, GfxObj *obj) {
Common::Rect rect;
obj->getRect(0, rect);
- PathBuffer *buf = new PathBuffer;
- buf->create(rect.width(), rect.height());
- _vm->_disk->loadPath(name, *buf);
+ PathBuffer *buf = _vm->_disk->loadPath(name, rect.width(), rect.height());
obj->_pathId = addPathPatch(buf);
obj->_hasPath = true;
diff --git a/engines/parallaction/iff.cpp b/engines/parallaction/iff.cpp
deleted file mode 100644
index 43dcac3697..0000000000
--- a/engines/parallaction/iff.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-
-#include "common/iff_container.h"
-#include "common/stream.h"
-#include "common/util.h"
-#include "parallaction/iff.h"
-
-namespace Parallaction {
-
-
-void IFFParser::setInputStream(Common::SeekableReadStream *stream) {
- destroy();
-
- assert(stream);
- _stream = stream;
- _startOffset = 0;
- _endOffset = _stream->size();
-
- _formType = 0;
- _formSize = (uint32)-1;
-
- if (_stream->size() < 12) {
- // this file is too small to be a valid IFF container
- return;
- }
-
- if (_stream->readUint32BE() != ID_FORM) {
- // no FORM header was found
- return;
- }
-
- _formSize = _stream->readUint32BE();
- _formType = _stream->readUint32BE();
-}
-
-void IFFParser::destroy() {
- _stream = 0;
- _startOffset = _endOffset = 0;
-}
-
-uint32 IFFParser::getFORMSize() const {
- return _formSize;
-}
-
-Common::IFF_ID IFFParser::getFORMType() const {
- return _formType;
-}
-
-uint32 IFFParser::moveToIFFBlock(Common::IFF_ID chunkName) {
- uint32 size = (uint32)-1;
-
- _stream->seek(_startOffset + 0x0C);
-
- while ((uint)_stream->pos() < _endOffset) {
- uint32 chunk = _stream->readUint32BE();
- uint32 size_temp = _stream->readUint32BE();
-
- if (chunk != chunkName) {
- _stream->seek((size_temp + 1) & (~1), SEEK_CUR);
- assert((uint)_stream->pos() <= _endOffset);
- } else {
- size = size_temp;
- break;
- }
- }
-
- return size;
-}
-
-uint32 IFFParser::getIFFBlockSize(Common::IFF_ID chunkName) {
- uint32 size = moveToIFFBlock(chunkName);
- return size;
-}
-
-bool IFFParser::loadIFFBlock(Common::IFF_ID chunkName, void *loadTo, uint32 ptrSize) {
- uint32 chunkSize = moveToIFFBlock(chunkName);
-
- if (chunkSize == (uint32)-1) {
- return false;
- }
-
- uint32 loadSize = 0;
- loadSize = MIN(ptrSize, chunkSize);
- _stream->read(loadTo, loadSize);
- return true;
-}
-
-Common::SeekableReadStream *IFFParser::getIFFBlockStream(Common::IFF_ID chunkName) {
- uint32 chunkSize = moveToIFFBlock(chunkName);
-
- if (chunkSize == (uint32)-1) {
- return 0;
- }
-
- uint32 pos = _stream->pos();
- return new Common::SeekableSubReadStream(_stream, pos, pos + chunkSize, false);
-}
-
-
-// ILBM decoder implementation
-
-ILBMDecoder::ILBMDecoder(Common::SeekableReadStream *in, bool disposeStream) : _in(in), _disposeStream(disposeStream), _hasHeader(false), _bodySize((uint32)-1), _paletteSize((uint32)-1) {
- assert(in);
- _parser.setInputStream(in);
-
- if (_parser.getFORMType() != ID_ILBM) {
- return;
- }
-
- _hasHeader = _parser.loadIFFBlock(ID_BMHD, &_header, sizeof(_header));
- if (!_hasHeader) {
- return;
- }
-
- _header.width = TO_BE_16(_header.width);
- _header.height = TO_BE_16(_header.height);
-
- _paletteSize = _parser.getIFFBlockSize(ID_CMAP);
- _bodySize = _parser.getIFFBlockSize(ID_BODY);
-}
-
-
-ILBMDecoder::~ILBMDecoder() {
- if (_disposeStream) {
- delete _in;
- }
-}
-
-uint32 ILBMDecoder::getWidth() {
- assert(_hasHeader);
- return _header.width;
-}
-
-uint32 ILBMDecoder::getHeight() {
- assert(_hasHeader);
- return _header.height;
-}
-
-uint32 ILBMDecoder::getNumColors() {
- assert(_hasHeader);
- return (1 << _header.depth);
-}
-
-byte *ILBMDecoder::getPalette() {
- assert(_paletteSize != (uint32)-1);
- byte *palette = new byte[_paletteSize];
- assert(palette);
- _parser.loadIFFBlock(ID_CMAP, palette, _paletteSize);
- return palette;
-}
-
-byte *ILBMDecoder::getBitmap(uint32 numPlanes, bool packPlanes) {
- assert(_bodySize != (uint32)-1);
- assert(numPlanes == 1 || numPlanes == 2 || numPlanes == 3 || numPlanes == 4 || numPlanes == 5 || numPlanes == 8);
-
- numPlanes = MIN(numPlanes, (uint32)_header.depth);
- if (numPlanes > 4) {
- packPlanes = false;
- }
-
- uint32 bitmapSize = _header.width * _header.height;
- uint32 bitmapWidth = _header.width;
- if (packPlanes) {
- bitmapSize /= (8 / numPlanes);
- bitmapWidth /= (8 / numPlanes);
- }
-
- Common::SeekableReadStream *bodyStream = _parser.getIFFBlockStream(ID_BODY);
- assert(bodyStream);
-
- byte *bitmap = (byte*)calloc(bitmapSize, 1);
- assert(bitmap);
-
- switch (_header.pack) {
- case 1: { // PackBits compressed bitmap
- Graphics::PackBitsReadStream stream(*bodyStream);
-
- byte *out = bitmap;
-
- // setup a buffer to hold enough data to build a line in the output
- uint32 scanWidth = ((_header.width + 15)/16) << 1;
- byte *scanBuffer = (byte*)malloc(scanWidth * _header.depth);
-
- for (uint i = 0; i < _header.height; ++i) {
- byte *s = scanBuffer;
- for (uint32 j = 0; j < _header.depth; ++j) {
- stream.read(s, scanWidth);
- s += scanWidth;
- }
-
- planarToChunky(out, bitmapWidth, scanBuffer, scanWidth, numPlanes, packPlanes);
- out += bitmapWidth;
- }
-
- free(scanBuffer);
- break;
- }
- default:
- error("only RLE compressed ILBM files are supported");
- break;
- }
-
- delete bodyStream;
-
- return bitmap;
-}
-
-
-void ILBMDecoder::planarToChunky(byte *out, uint32 width, byte *in, uint32 planeWidth, uint32 nPlanes, bool packPlanes) {
- byte pix, ofs, bit;
- byte *s;
-
- uint32 pixels = width;
- if (packPlanes) {
- pixels *= (8 / nPlanes);
- }
-
- for (uint32 x = 0; x < pixels; ++x) {
-
- pix = 0;
- ofs = x >> 3;
- bit = 0x80 >> (x & 7);
-
- // first build a pixel by scanning all the usable planes in the input
- s = in;
- for (uint32 plane = 0; plane < nPlanes; ++plane) {
- if (s[ofs] & bit) {
- pix |= (1 << plane);
- }
- s += planeWidth;
- }
-
-
- // then output the pixel according to the requested packing
- if (!packPlanes) {
- out[x] = pix;
- } else
- if (nPlanes == 1) {
- out[x/8] |= (pix << (x & 7));
- } else
- if (nPlanes == 2) {
- out[x/4] |= (pix << ((x & 3) << 1));
- } else
- if (nPlanes == 4) {
- out[x/2] |= (pix << ((x & 1) << 2));
- }
- }
-
-}
-
-
-} // End of namespace Parallaction
diff --git a/engines/parallaction/iff.h b/engines/parallaction/iff.h
deleted file mode 100644
index 43f78bf001..0000000000
--- a/engines/parallaction/iff.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#ifndef PARALLACTION_IFF_H
-#define PARALLACTION_IFF_H
-
-#include "common/stream.h"
-#include "common/iff_container.h" // for IFF chunk names
-#include "graphics/iff.h" // for BMHD
-
-// this IFF parser code is courtesy of the Kyra engine team ;)
-
-namespace Parallaction {
-
-class IFFParser {
-public:
- IFFParser() : _stream(0), _startOffset(0), _endOffset(0) {}
- IFFParser(Common::SeekableReadStream *stream) : _stream(0), _startOffset(0), _endOffset(0) {
- setInputStream(stream);
- }
- ~IFFParser() { destroy(); }
-
- void setInputStream(Common::SeekableReadStream *stream);
-
- operator bool() const { return (_startOffset != _endOffset) && _stream; }
-
- uint32 getFORMSize() const;
- Common::IFF_ID getFORMType() const;
-
- uint32 getIFFBlockSize(Common::IFF_ID chunk);
- bool loadIFFBlock(Common::IFF_ID chunk, void *loadTo, uint32 ptrSize);
- Common::SeekableReadStream *getIFFBlockStream(Common::IFF_ID chunkName);
-private:
- void destroy();
- uint32 moveToIFFBlock(Common::IFF_ID chunkName);
-
- Common::SeekableReadStream *_stream;
- uint32 _startOffset;
- uint32 _endOffset;
-
- uint32 _formSize;
- Common::IFF_ID _formType;
-};
-
-
-
-
-class ILBMDecoder {
- Common::SeekableReadStream *_in;
- bool _disposeStream;
-
- void planarToChunky(byte *out, uint32 width, byte *in, uint32 planeWidth, uint32 nPlanes, bool packPlanes);
-
-protected:
- IFFParser _parser;
- Graphics::BMHD _header;
- bool _hasHeader;
- uint32 _bodySize;
- uint32 _paletteSize;
-
-
-public:
- ILBMDecoder(Common::SeekableReadStream *input, bool disposeStream = false);
-
- virtual ~ILBMDecoder();
-
- uint32 getWidth();
- uint32 getHeight();
- uint32 getNumColors();
- byte *getPalette();
-
- byte *getBitmap(uint32 numPlanes, bool packPlanes);
- byte *getBitmap() {
- assert(_hasHeader);
- return getBitmap(_header.depth, false);
- }
-};
-
-
-}
-
-#endif
-
diff --git a/engines/parallaction/module.mk b/engines/parallaction/module.mk
index 16b79c3d5a..d65653cd92 100644
--- a/engines/parallaction/module.mk
+++ b/engines/parallaction/module.mk
@@ -7,6 +7,7 @@ MODULE_OBJS := \
debug.o \
detection.o \
dialogue.o \
+ disk.o \
disk_br.o \
disk_ns.o \
exec.o \
@@ -18,7 +19,6 @@ MODULE_OBJS := \
gui.o \
gui_br.o \
gui_ns.o \
- iff.o \
input.o \
inventory.o \
objects.o \
diff --git a/engines/parallaction/sound.h b/engines/parallaction/sound.h
index f0ecea67bb..8fcfb94a9a 100644
--- a/engines/parallaction/sound.h
+++ b/engines/parallaction/sound.h
@@ -84,6 +84,14 @@ enum {
SC_PAUSE
};
+struct Channel {
+ Audio::AudioStream *stream;
+ Audio::SoundHandle handle;
+ uint32 volume;
+};
+
+
+
class SoundMan_ns : public SoundManImpl {
public:
enum {
@@ -148,16 +156,9 @@ class AmigaSoundMan_ns : public SoundMan_ns {
Audio::AudioStream *_musicStream;
Audio::SoundHandle _musicHandle;
- struct Channel {
- Audio::Voice8Header header;
- int8 *data;
- uint32 dataSize;
- bool dispose;
- Audio::SoundHandle handle;
- uint32 flags;
- } _channels[NUM_SFX_CHANNELS];
+ Channel _channels[NUM_SFX_CHANNELS];
- void loadChannelData(const char *filename, Channel *ch);
+ Audio::AudioStream *loadChannelData(const char *filename, Channel *ch, bool looping);
public:
AmigaSoundMan_ns(Parallaction_ns *vm);
@@ -192,21 +193,12 @@ protected:
bool _musicEnabled;
bool _sfxEnabled;
+ Channel _channels[NUM_SFX_CHANNELS];
+
virtual void playMusic() = 0;
virtual void stopMusic() = 0;
virtual void pause(bool p) = 0;
- struct Channel {
- Audio::Voice8Header header;
- int8 *data;
- uint32 dataSize;
- bool dispose;
- Audio::SoundHandle handle;
- uint32 flags;
- } _channels[NUM_SFX_CHANNELS];
-
- virtual void loadChannelData(const char *filename, Channel *ch) = 0;
-
public:
SoundMan_br(Parallaction_br *vm);
~SoundMan_br();
@@ -228,7 +220,7 @@ class DosSoundMan_br : public SoundMan_br {
MidiPlayer_MSC *_midiPlayer;
- void loadChannelData(const char *filename, Channel *ch);
+ Audio::AudioStream *loadChannelData(const char *filename, Channel *ch, bool looping);
public:
DosSoundMan_br(Parallaction_br *vm, MidiDriver *midiDriver);
@@ -246,7 +238,7 @@ class AmigaSoundMan_br : public SoundMan_br {
Audio::AudioStream *_musicStream;
Audio::SoundHandle _musicHandle;
- void loadChannelData(const char *filename, Channel *ch);
+ Audio::AudioStream *loadChannelData(const char *filename, Channel *ch, bool looping);
public:
AmigaSoundMan_br(Parallaction_br *vm);
diff --git a/engines/parallaction/sound_br.cpp b/engines/parallaction/sound_br.cpp
index 4915eb41e2..c0e3f3b24a 100644
--- a/engines/parallaction/sound_br.cpp
+++ b/engines/parallaction/sound_br.cpp
@@ -401,19 +401,29 @@ DosSoundMan_br::~DosSoundMan_br() {
delete _midiPlayer;
}
-void DosSoundMan_br::loadChannelData(const char *filename, Channel *ch) {
+Audio::AudioStream *DosSoundMan_br::loadChannelData(const char *filename, Channel *ch, bool looping) {
Common::SeekableReadStream *stream = _vm->_disk->loadSound(filename);
- ch->dataSize = stream->size();
- ch->data = (int8*)malloc(ch->dataSize);
- if (stream->read(ch->data, ch->dataSize) != ch->dataSize)
+ uint32 dataSize = stream->size();
+ int8 *data = (int8*)malloc(dataSize);
+ if (stream->read(data, dataSize) != dataSize)
error("DosSoundMan_br::loadChannelData: Read failed");
- ch->dispose = true;
delete stream;
// TODO: Confirm sound rate
- ch->header.samplesPerSec = 11025;
+ int rate = 11025;
+
+ uint32 loopStart = 0, loopEnd = 0;
+ uint32 flags = Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_AUTOFREE;
+
+ if (looping) {
+ loopEnd = dataSize;
+ flags |= Audio::Mixer::FLAG_LOOP;
+ }
+
+ ch->stream = Audio::makeLinearInputStream((byte *)data, dataSize, rate, flags, loopStart, loopEnd);
+ return ch->stream;
}
void DosSoundMan_br::playSfx(const char *filename, uint channel, bool looping, int volume) {
@@ -426,16 +436,8 @@ void DosSoundMan_br::playSfx(const char *filename, uint channel, bool looping, i
debugC(1, kDebugAudio, "DosSoundMan_br::playSfx(%s, %u, %i, %i)", filename, channel, looping, volume);
Channel *ch = &_channels[channel];
- loadChannelData(filename, ch);
-
- uint32 loopStart = 0, loopEnd = 0, flags = Audio::Mixer::FLAG_UNSIGNED;
- if (looping) {
- loopEnd = ch->dataSize;
- flags |= Audio::Mixer::FLAG_LOOP;
- }
-
- _mixer->playRaw(Audio::Mixer::kSFXSoundType, &ch->handle, ch->data, ch->dataSize,
- ch->header.samplesPerSec, flags, -1, volume, 0, loopStart, loopEnd);
+ Audio::AudioStream *input = loadChannelData(filename, ch, looping);
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &ch->handle, input, -1, volume);
}
void DosSoundMan_br::playMusic() {
@@ -468,22 +470,27 @@ AmigaSoundMan_br::~AmigaSoundMan_br() {
stopMusic();
}
-void AmigaSoundMan_br::loadChannelData(const char *filename, Channel *ch) {
+Audio::AudioStream *AmigaSoundMan_br::loadChannelData(const char *filename, Channel *ch, bool looping) {
Common::SeekableReadStream *stream = _vm->_disk->loadSound(filename);
+ Audio::AudioStream *input = 0;
+
if (_vm->getFeatures() & GF_DEMO) {
- ch->dataSize = stream->size();
- ch->data = (int8*)malloc(ch->dataSize);
- if (stream->read(ch->data, ch->dataSize) != ch->dataSize)
+ uint32 dataSize = stream->size();
+ int8 *data = (int8*)malloc(dataSize);
+ if (stream->read(data, dataSize) != dataSize)
error("DosSoundMan_br::loadChannelData: Read failed");
// TODO: Confirm sound rate
- ch->header.samplesPerSec = 11025;
+ int rate = 11025;
+ input = Audio::makeLinearInputStream((byte *)data, dataSize, rate, Audio::Mixer::FLAG_AUTOFREE, 0, 0);
} else {
- Audio::A8SVXDecoder decoder(*stream, ch->header, ch->data, ch->dataSize);
- decoder.decode();
+ input = Audio::make8SVXStream(*stream, looping);
}
- ch->dispose = true;
+
delete stream;
+
+ ch->stream = input;
+ return input;
}
void AmigaSoundMan_br::playSfx(const char *filename, uint channel, bool looping, int volume) {
@@ -501,24 +508,13 @@ void AmigaSoundMan_br::playSfx(const char *filename, uint channel, bool looping,
debugC(1, kDebugAudio, "AmigaSoundMan_ns::playSfx(%s, %i)", filename, channel);
Channel *ch = &_channels[channel];
- loadChannelData(filename, ch);
-
- uint32 loopStart = 0, loopEnd = 0, flags = 0;
- if (looping) {
- // the standard way to loop 8SVX audio implies use of the oneShotHiSamples and
- // repeatHiSamples fields, but Nippon Safes handles loops according to flags
- // set in its location scripts and always operates on the whole data.
- loopStart = 0;
- loopEnd = ch->header.oneShotHiSamples + ch->header.repeatHiSamples;
- flags = Audio::Mixer::FLAG_LOOP;
- }
+ Audio::AudioStream *input = loadChannelData(filename, ch, looping);
if (volume == -1) {
- volume = ch->header.volume;
+ volume = ch->volume;
}
- _mixer->playRaw(Audio::Mixer::kSFXSoundType, &ch->handle, ch->data, ch->dataSize,
- ch->header.samplesPerSec, flags, -1, volume, 0, loopStart, loopEnd);
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &ch->handle, input, -1, volume);
}
void AmigaSoundMan_br::playMusic() {
@@ -560,15 +556,6 @@ void AmigaSoundMan_br::pause(bool p) {
SoundMan_br::SoundMan_br(Parallaction_br *vm) : _vm(vm) {
_mixer = _vm->_mixer;
- _channels[0].data = 0;
- _channels[0].dispose = false;
- _channels[1].data = 0;
- _channels[1].dispose = false;
- _channels[2].data = 0;
- _channels[2].dispose = false;
- _channels[3].data = 0;
- _channels[3].dispose = false;
-
_musicEnabled = true;
_sfxEnabled = true;
}
@@ -595,12 +582,9 @@ void SoundMan_br::stopSfx(uint channel) {
return;
}
- if (_channels[channel].dispose) {
- debugC(1, kDebugAudio, "SoundMan_br::stopSfx(%i)", channel);
- _mixer->stopHandle(_channels[channel].handle);
- free(_channels[channel].data);
- _channels[channel].data = 0;
- }
+ debugC(1, kDebugAudio, "SoundMan_br::stopSfx(%i)", channel);
+ _mixer->stopHandle(_channels[channel].handle);
+ _channels[channel].stream = 0;
}
void SoundMan_br::execute(int command, const char *parm) {
diff --git a/engines/parallaction/sound_ns.cpp b/engines/parallaction/sound_ns.cpp
index d0688c7264..65ee75ed98 100644
--- a/engines/parallaction/sound_ns.cpp
+++ b/engines/parallaction/sound_ns.cpp
@@ -335,14 +335,6 @@ void DosSoundMan_ns::playLocationMusic(const char *location) {
AmigaSoundMan_ns::AmigaSoundMan_ns(Parallaction_ns *vm) : SoundMan_ns(vm) {
_musicStream = 0;
- _channels[0].data = 0;
- _channels[0].dispose = false;
- _channels[1].data = 0;
- _channels[1].dispose = false;
- _channels[2].data = 0;
- _channels[2].dispose = false;
- _channels[3].data = 0;
- _channels[3].dispose = false;
}
AmigaSoundMan_ns::~AmigaSoundMan_ns() {
@@ -360,30 +352,30 @@ static int8 res_amigaBeep[AMIGABEEP_SIZE] = {
0, 20, 40, 60, 80, 60, 40, 20, 0, -20, -40, -60, -80, -60, -40, -20
};
+Audio::AudioStream *AmigaSoundMan_ns::loadChannelData(const char *filename, Channel *ch, bool looping) {
+ Audio::AudioStream *input = 0;
-void AmigaSoundMan_ns::loadChannelData(const char *filename, Channel *ch) {
if (!scumm_stricmp("beep", filename)) {
- ch->header.oneShotHiSamples = 0;
- ch->header.repeatHiSamples = 0;
- ch->header.samplesPerHiCycle = 0;
- ch->header.samplesPerSec = 11934;
- ch->header.volume = 160;
- ch->data = (int8*)malloc(AMIGABEEP_SIZE * NUM_REPEATS);
- int8* odata = ch->data;
+ // TODO: make a permanent stream out of this
+ uint32 dataSize = AMIGABEEP_SIZE * NUM_REPEATS;
+ int8 *data = (int8*)malloc(dataSize);
+ int8 *odata = data;
for (uint i = 0; i < NUM_REPEATS; i++) {
memcpy(odata, res_amigaBeep, AMIGABEEP_SIZE);
odata += AMIGABEEP_SIZE;
}
- ch->dataSize = AMIGABEEP_SIZE * NUM_REPEATS;
- ch->dispose = true;
- return;
+ int rate = 11934;
+ ch->volume = 160;
+ input = Audio::makeLinearInputStream((byte *)data, dataSize, rate, Audio::Mixer::FLAG_AUTOFREE, 0, 0);
+ } else {
+ Common::SeekableReadStream *stream = _vm->_disk->loadSound(filename);
+ input = Audio::make8SVXStream(*stream, looping);
+ delete stream;
}
- Common::SeekableReadStream *stream = _vm->_disk->loadSound(filename);
- Audio::A8SVXDecoder decoder(*stream, ch->header, ch->data, ch->dataSize);
- decoder.decode();
- ch->dispose = true;
- delete stream;
+ ch->stream = input;
+
+ return input;
}
void AmigaSoundMan_ns::playSfx(const char *filename, uint channel, bool looping, int volume) {
@@ -397,27 +389,13 @@ void AmigaSoundMan_ns::playSfx(const char *filename, uint channel, bool looping,
debugC(1, kDebugAudio, "AmigaSoundMan_ns::playSfx(%s, %i)", filename, channel);
Channel *ch = &_channels[channel];
- loadChannelData(filename, ch);
-
- uint32 loopStart, loopEnd, flags;
- if (looping) {
- // the standard way to loop 8SVX audio implies use of the oneShotHiSamples and
- // repeatHiSamples fields, but Nippon Safes handles loops according to flags
- // set in its location scripts and always operates on the whole data.
- loopStart = 0;
- loopEnd = ch->header.oneShotHiSamples + ch->header.repeatHiSamples;
- flags = Audio::Mixer::FLAG_LOOP;
- } else {
- loopStart = loopEnd = 0;
- flags = 0;
- }
+ Audio::AudioStream *input = loadChannelData(filename, ch, looping);
if (volume == -1) {
- volume = ch->header.volume;
+ volume = ch->volume;
}
- _mixer->playRaw(Audio::Mixer::kSFXSoundType, &ch->handle, ch->data, ch->dataSize,
- ch->header.samplesPerSec, flags, -1, volume, 0, loopStart, loopEnd);
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &ch->handle, input, -1, volume);
}
void AmigaSoundMan_ns::stopSfx(uint channel) {
@@ -426,12 +404,9 @@ void AmigaSoundMan_ns::stopSfx(uint channel) {
return;
}
- if (_channels[channel].dispose) {
- debugC(1, kDebugAudio, "AmigaSoundMan_ns::stopSfx(%i)", channel);
- _mixer->stopHandle(_channels[channel].handle);
- free(_channels[channel].data);
- _channels[channel].data = 0;
- }
+ debugC(1, kDebugAudio, "AmigaSoundMan_ns::stopSfx(%i)", channel);
+ _mixer->stopHandle(_channels[channel].handle);
+ _channels[channel].stream = 0;
}
void AmigaSoundMan_ns::playMusic() {
diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index a7c802f0c9..f43db12d1a 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -472,7 +472,7 @@ void Scene::changeScene(int16 sceneNumber, int actorsEntrance, SceneTransitionTy
for (int i = 0; i < ARRAYSIZE(sceneSubstitutes); i++) {
if (sceneSubstitutes[i].sceneId == sceneNumber) {
Surface bbmBuffer;
- byte *pal, *colors;
+ byte *pal, colors[768];
Common::File file;
Rect rect;
PalEntry cPal[PAL_ENTRIES];
@@ -480,8 +480,8 @@ void Scene::changeScene(int16 sceneNumber, int actorsEntrance, SceneTransitionTy
_vm->_interface->setMode(kPanelSceneSubstitute);
if (file.open(sceneSubstitutes[i].image)) {
- Graphics::decodePBM(file, bbmBuffer, pal);
- colors = pal;
+ Graphics::decodePBM(file, bbmBuffer, colors);
+ pal = colors;
rect.setWidth(bbmBuffer.w);
rect.setHeight(bbmBuffer.h);
_vm->_gfx->drawRegion(rect, (const byte*)bbmBuffer.pixels);
@@ -490,7 +490,6 @@ void Scene::changeScene(int16 sceneNumber, int actorsEntrance, SceneTransitionTy
cPal[j].green = *pal++;
cPal[j].blue = *pal++;
}
- free(colors);
_vm->_gfx->setPalette(cPal);
}
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 4816f87a20..2f2fbc5243 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -55,15 +55,6 @@ int g_debug_seeking = 0; // Stepping forward until some special condition is met
int g_debug_seek_special = 0; // Used for special seeks
int g_debug_seek_level = 0; // Used for seekers that want to check their exec stack depth
-enum DebugSeeking {
- kDebugSeekNothing = 0,
- kDebugSeekCallk = 1, // Step forward until callk is found
- kDebugSeekLevelRet = 2, // Step forward until returned from this level
- kDebugSeekSpecialCallk = 3, // Step forward until a /special/ callk is found
- kDebugSeekSO = 4, // Step forward until specified PC (after the send command) and stack depth
- kDebugSeekGlobal = 5 // Step forward until one specified global variable is modified
-};
-
Console::Console(SciEngine *vm) : GUI::Debugger() {
_vm = vm;
@@ -152,11 +143,17 @@ Console::Console(SciEngine *vm) : GUI::Debugger() {
DCmd_Register("dissect_script", WRAP_METHOD(Console, cmdDissectScript));
DCmd_Register("set_acc", WRAP_METHOD(Console, cmdSetAccumulator));
DCmd_Register("backtrace", WRAP_METHOD(Console, cmdBacktrace));
+ DCmd_Register("bt", WRAP_METHOD(Console, cmdBacktrace)); // alias
DCmd_Register("step", WRAP_METHOD(Console, cmdStep));
+ DCmd_Register("s", WRAP_METHOD(Console, cmdStep)); // alias
DCmd_Register("step_event", WRAP_METHOD(Console, cmdStepEvent));
+ DCmd_Register("se", WRAP_METHOD(Console, cmdStepEvent)); // alias
DCmd_Register("step_ret", WRAP_METHOD(Console, cmdStepRet));
+ DCmd_Register("sret", WRAP_METHOD(Console, cmdStepRet)); // alias
DCmd_Register("step_global", WRAP_METHOD(Console, cmdStepGlobal));
+ DCmd_Register("sg", WRAP_METHOD(Console, cmdStepGlobal)); // alias
DCmd_Register("step_callk", WRAP_METHOD(Console, cmdStepCallk));
+ DCmd_Register("snk", WRAP_METHOD(Console, cmdStepCallk)); // alias
DCmd_Register("disasm", WRAP_METHOD(Console, cmdDissassemble));
DCmd_Register("disasm_addr", WRAP_METHOD(Console, cmdDissassembleAddress));
DCmd_Register("send", WRAP_METHOD(Console, cmdSend));
@@ -165,7 +162,9 @@ Console::Console(SciEngine *vm) : GUI::Debugger() {
DCmd_Register("bp_list", WRAP_METHOD(Console, cmdBreakpointList));
DCmd_Register("bp_del", WRAP_METHOD(Console, cmdBreakpointDelete));
DCmd_Register("bp_exec_method", WRAP_METHOD(Console, cmdBreakpointExecMethod));
+ DCmd_Register("bpx", WRAP_METHOD(Console, cmdBreakpointExecMethod)); // alias
DCmd_Register("bp_exec_function", WRAP_METHOD(Console, cmdBreakpointExecFunction));
+ DCmd_Register("bpe", WRAP_METHOD(Console, cmdBreakpointExecFunction)); // alias
// VM
DCmd_Register("script_steps", WRAP_METHOD(Console, cmdScriptSteps));
DCmd_Register("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist));
@@ -174,7 +173,9 @@ Console::Console(SciEngine *vm) : GUI::Debugger() {
DCmd_Register("value_type", WRAP_METHOD(Console, cmdValueType));
DCmd_Register("view_listnode", WRAP_METHOD(Console, cmdViewListNode));
DCmd_Register("view_reference", WRAP_METHOD(Console, cmdViewReference));
+ DCmd_Register("vr", WRAP_METHOD(Console, cmdViewReference)); // alias
DCmd_Register("view_object", WRAP_METHOD(Console, cmdViewObject));
+ DCmd_Register("vo", WRAP_METHOD(Console, cmdViewObject)); // alias
DCmd_Register("active_object", WRAP_METHOD(Console, cmdViewActiveObject));
DCmd_Register("acc_object", WRAP_METHOD(Console, cmdViewAccumulatorObject));
@@ -225,6 +226,12 @@ bool Console::cmdHelp(int argc, const char **argv) {
DebugPrintf("weak_validations: Turns some validation errors into warnings\n");
DebugPrintf("script_abort_flag: Set to 1 to abort script execution. Set to 2 to force a replay afterwards\n");
DebugPrintf("\n");
+ DebugPrintf("Debug flags\n");
+ DebugPrintf("-----------\n");
+ DebugPrintf("debugflag_list - Lists the available debug flags and their status\n");
+ DebugPrintf("debugflag_enable - Enables a debug flag\n");
+ DebugPrintf("debugflag_disable - Disables a debug flag\n");
+ DebugPrintf("\n");
DebugPrintf("Commands\n");
DebugPrintf("--------\n");
DebugPrintf("Kernel:\n");
@@ -310,12 +317,12 @@ bool Console::cmdHelp(int argc, const char **argv) {
DebugPrintf(" registers - Shows the current register values\n");
DebugPrintf(" dissect_script - Examines a script\n");
DebugPrintf(" set_acc - Sets the accumulator\n");
- DebugPrintf(" backtrace - Dumps the send/self/super/call/calle/callb stack\n");
- DebugPrintf(" step - Executes one operation (no parameters) or several operations (specified as a parameter) \n");
- DebugPrintf(" step_event - Steps forward until a SCI event is received.\n");
- DebugPrintf(" step_ret - Steps forward until ret is called on the current execution stack level.\n");
- DebugPrintf(" step_global - Steps until the global variable with the specified index is modified.\n");
- DebugPrintf(" step_callk - Steps forward until it hits the next callk operation, or a specific callk (specified as a parameter)\n");
+ DebugPrintf(" backtrace / bt - Dumps the send/self/super/call/calle/callb stack\n");
+ DebugPrintf(" step / s - Executes one operation (no parameters) or several operations (specified as a parameter) \n");
+ DebugPrintf(" step_event / se - Steps forward until a SCI event is received.\n");
+ DebugPrintf(" step_ret / sret - Steps forward until ret is called on the current execution stack level.\n");
+ DebugPrintf(" step_global / sg - Steps until the global variable with the specified index is modified.\n");
+ DebugPrintf(" step_callk / snk - Steps forward until it hits the next callk operation, or a specific callk (specified as a parameter)\n");
DebugPrintf(" disasm - Disassembles a method by name\n");
DebugPrintf(" disasm_addr - Disassembles one or more commands\n");
DebugPrintf(" send - Sends a message to an object\n");
@@ -324,8 +331,8 @@ bool Console::cmdHelp(int argc, const char **argv) {
DebugPrintf("Breakpoints:\n");
DebugPrintf(" bp_list - Lists the current breakpoints\n");
DebugPrintf(" bp_del - Deletes a breakpoint with the specified index\n");
- DebugPrintf(" bp_exec_method - Sets a breakpoint on the execution of the specified method\n");
- DebugPrintf(" bp_exec_function - Sets a breakpoint on the execution of the specified exported function\n");
+ DebugPrintf(" bp_exec_method / bpx - Sets a breakpoint on the execution of the specified method\n");
+ DebugPrintf(" bp_exec_function / bpe - Sets a breakpoint on the execution of the specified exported function\n");
DebugPrintf("\n");
DebugPrintf("VM:\n");
DebugPrintf(" script_steps - Shows the number of executed SCI operations\n");
@@ -334,8 +341,8 @@ bool Console::cmdHelp(int argc, const char **argv) {
DebugPrintf(" stack - Lists the specified number of stack elements\n");
DebugPrintf(" value_type - Determines the type of a value\n");
DebugPrintf(" view_listnode - Examines the list node at the given address\n");
- DebugPrintf(" view_reference - Examines an arbitrary reference\n");
- DebugPrintf(" view_object - Examines the object at the given address\n");
+ DebugPrintf(" view_reference / vr - Examines an arbitrary reference\n");
+ DebugPrintf(" view_object / vo - Examines the object at the given address\n");
DebugPrintf(" active_object - Shows information on the currently active object or class\n");
DebugPrintf(" acc_object - Shows information on the object or class at the address indexed by the accumulator\n");
DebugPrintf("\n");
diff --git a/engines/sci/console.h b/engines/sci/console.h
index c45202de16..22b5505bf2 100644
--- a/engines/sci/console.h
+++ b/engines/sci/console.h
@@ -35,6 +35,15 @@ namespace Sci {
class SciEngine;
struct List;
+enum DebugSeeking {
+ kDebugSeekNothing = 0,
+ kDebugSeekCallk = 1, // Step forward until callk is found
+ kDebugSeekLevelRet = 2, // Step forward until returned from this level
+ kDebugSeekSpecialCallk = 3, // Step forward until a /special/ callk is found
+ kDebugSeekSO = 4, // Step forward until specified PC (after the send command) and stack depth
+ kDebugSeekGlobal = 5 // Step forward until one specified global variable is modified
+};
+
// Refer to the "addresses" command on how to pass address parameters
int parse_reg_t(EngineState *s, const char *str, reg_t *dest);
int printObject(EngineState *s, reg_t pos);
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index ac5268dd4c..bdf2c7c72a 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -953,9 +953,9 @@ static const struct SciGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "59b13619078bd47011421468959ee5d4", 954},
{"resource.001", 0, "4cfb9040db152868f7cb6a1e8151c910", 296555},
{NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH},
- 0,
+ GF_SCI0_SCI1VOCAB,
SCI_VERSION_AUTODETECT,
- SCI_VERSION_01
+ SCI_VERSION_0
},
// King's Quest 1 SCI Remake - English DOS (from the King's Quest Collection)
@@ -969,7 +969,7 @@ static const struct SciGameDescription SciGameDescriptions[] = {
{NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH},
0,
SCI_VERSION_AUTODETECT,
- SCI_VERSION_01
+ SCI_VERSION_0
},
// King's Quest 4 - English Amiga (from www.back2roots.org)
@@ -2504,6 +2504,32 @@ static const struct SciGameDescription SciGameDescriptions[] = {
SCI_VERSION_0
},
+ // Quest for Glory 1 - Japanese PC-98 5.25" Floppy
+ // Executable scanning reports "S.old.201"
+ {{"qfg1", "8 Colors", {
+ {"resource.map", 0, "5cbeb95dd2a4b7cb242b415cc6ec1c47", 6444},
+ {"resource.001", 0, "a21451ef6fa8179bd4b22c4950004c44", 859959},
+ {"resource.002", 0, "a21451ef6fa8179bd4b22c4950004c44", 1136968},
+ {"resource.003", 0, "a21451ef6fa8179bd4b22c4950004c44", 769897},
+ {NULL, 0, NULL, 0}}, Common::JA_JPN, Common::kPlatformPC98, 0, GUIO_NOSPEECH},
+ 0,
+ SCI_VERSION_AUTODETECT,
+ SCI_VERSION_01
+ },
+
+ // Quest for Glory 1 - Japanese PC-98 5.25" Floppy
+ // Executable scanning reports "S.old.201"
+ {{"qfg1", "16 Colors", {
+ {"resource.map", 0, "3ecaba33bf77cb434067a0b8aee15097", 6444},
+ {"resource.001", 0, "a21451ef6fa8179bd4b22c4950004c44", 864754},
+ {"resource.002", 0, "a21451ef6fa8179bd4b22c4950004c44", 1147121},
+ {"resource.003", 0, "a21451ef6fa8179bd4b22c4950004c44", 777575},
+ {NULL, 0, NULL, 0}}, Common::JA_JPN, Common::kPlatformPC98, 0, GUIO_NOSPEECH},
+ 0,
+ SCI_VERSION_AUTODETECT,
+ SCI_VERSION_01
+ },
+
// Quest for Glory 1 - English Amiga
// Executable scanning reports "1.002.020"
// SCI interpreter version 0.000.685
@@ -3085,6 +3111,32 @@ static const struct SciGameDescription SciGameDescriptions[] = {
SCI_VERSION_1
},
+ // Space Quest 4 - Japanese PC-98 5.25" Floppy
+ // SCI interpreter version 1.000.1068
+ {{"sq4", "", {
+ {"resource.map", 0, "ca7bba01019222b6f3e54e9051067a99", 5283},
+ {"resource.000", 0, "161d719f38ed98d33f058a8cf3dc09c3", 952909},
+ {"resource.001", 0, "454684e3a7a68cbca073945e50778447", 1187088},
+ {"resource.002", 0, "6dc668326cc22cb9e8bd8ca9e68d2a66", 1181249},
+ {NULL, 0, NULL, 0}}, Common::JA_JPN, Common::kPlatformPC98, 0, GUIO_NOSPEECH},
+ GF_FOR_SCI1_510_OR_LATER | GF_SCI1_EGA,
+ SCI_VERSION_AUTODETECT,
+ SCI_VERSION_1
+ },
+
+ // Space Quest 4 - Japanese PC-98 5.25" Floppy
+ // SCI interpreter version 1.000.1068
+ {{"sq4", "", {
+ {"resource.map", 0, "ca7bba01019222b6f3e54e9051067a99", 5283},
+ {"resource.000", 0, "161d719f38ed98d33f058a8cf3dc09c3", 952909},
+ {"resource.001", 0, "454684e3a7a68cbca073945e50778447", 1187088},
+ {"resource.002", 0, "6dc668326cc22cb9e8bd8ca9e68d2a66", 1181249},
+ {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC98, 0, GUIO_NOSPEECH},
+ GF_FOR_SCI1_510_OR_LATER | GF_SCI1_EGA,
+ SCI_VERSION_AUTODETECT,
+ SCI_VERSION_1
+ },
+
// Space Quest 4 - English DOS CD (from the Space Quest Collection)
// Executable scanning reports "1.001.064", VERSION file reports "1.0"
{{"sq4", "CD", {
diff --git a/engines/sci/engine/gc.h b/engines/sci/engine/gc.h
index e6fa737aaf..9f9347ca18 100644
--- a/engines/sci/engine/gc.h
+++ b/engines/sci/engine/gc.h
@@ -45,19 +45,23 @@ struct reg_t_Hash {
}
};
-// The reg_t_hash_map is actually really a hashset
+/*
+ * The reg_t_hash_map is actually really a hashset
+ */
typedef Common::HashMap<reg_t, bool, reg_t_Hash, reg_t_EqualTo> reg_t_hash_map;
+/**
+ * Finds all used references and normalises them to their memory addresses
+ * @param s The state to gather all information from
+ * @return A hash map containing entries for all used references
+ */
reg_t_hash_map *find_all_used_references(EngineState *s);
-/* Finds all used references and normalises them to their memory addresses
-** Parameters: (EngineState *) s: The state to gather all information from
-** Returns : (reg_t_hash_map *) A hash map containing entries for all used references
-*/
+/**
+ * Runs garbage collection on the current system state
+ * @param s The state in which we should gc
+ */
void run_gc(EngineState *s);
-/* Runs garbage collection on the current system state
-** Parameters: (EngineState *) s: The state in which we should gc
-*/
} // End of namespace Sci
diff --git a/engines/sci/engine/intmap.h b/engines/sci/engine/intmap.h
index 2cb4f69f1f..1c028975a9 100644
--- a/engines/sci/engine/intmap.h
+++ b/engines/sci/engine/intmap.h
@@ -83,7 +83,7 @@ public:
/**
* Checks whether a key is in the map, adds it if neccessary.
- * @param value The key to check for/add
+ * @param key The key to check for/add
* @param add Whether to add the key if it's not in there
* @param was_added Set to non-zero if and only if the key is new, ignored if NULL.
* @return The new (or old) index, or -1 if add was zero and
@@ -91,6 +91,11 @@ public:
*/
int checkKey(int key, bool add, bool *wasAdded = 0);
+ /**
+ * Looks up a key in the map
+ * @parmam key The key to look for
+ * @return The value or -1 if not found
+ */
int lookupKey(int key) const;
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index baf45d80c7..eafc6dbd4d 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -945,7 +945,11 @@ bool Kernel::loadKernelNames() {
switch (_resmgr->_sciVersion) {
case SCI_VERSION_0:
case SCI_VERSION_01:
- vocab_get_knames0(_resmgr, _kernelNames);
+ // HACK: The KQ1 demo requires the SCI1 vocabulary.
+ if (((SciEngine*)g_engine)->getFlags() & GF_SCI0_SCI1VOCAB)
+ vocab_get_knames1(_resmgr, _kernelNames);
+ else
+ vocab_get_knames0(_resmgr, _kernelNames);
break;
case SCI_VERSION_01_VGA:
case SCI_VERSION_01_VGA_ODD:
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 27d9df059d..46913a5b39 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -69,16 +69,17 @@ public:
uint getKernelNamesSize() const { return _kernelNames.size(); }
const Common::String &getKernelName(uint number) const { return _kernelNames[number]; }
- /* Determines the selector ID of a selector by its name
- ** (const char *) selectorName: Name of the selector to look up
- ** Returns : (int) The appropriate selector ID, or -1 on error
- */
+ /**
+ * Determines the selector ID of a selector by its name
+ * @param selectorName Name of the selector to look up
+ * @return The appropriate selector ID, or -1 on error
+ */
int findSelector(const char *selectorName) const;
- /* Detects whether a particular kernel function is required in the game
- ** (const char *) functionName: The name of the desired kernel function
- ** Returns : (bool) true if the kernel function is listed in the kernel table,
- ** false otherwise
+ /**
+ * Detects whether a particular kernel function is required in the game
+ * @param functionName The name of the desired kernel function
+ * @return True if the kernel function is listed in the kernel table, false otherwise
*/
bool hasKernelFunction(const char *functionName) const;
@@ -104,18 +105,18 @@ private:
/**
* Loads the kernel selector names.
- * Returns true upon success, false otherwise.
+ * @return True upon success, false otherwise.
*/
bool loadSelectorNames(bool isOldSci0);
- /* Maps special selectors
- ** Returns : (void)
- */
+ /**
+ * Maps special selectors
+ */
void mapSelectors();
- /* Maps kernel functions
- ** Returns : (void)
- */
+ /**
+ * Maps kernel functions
+ */
void mapFunctions();
/**
@@ -127,8 +128,10 @@ private:
ResourceManager *_resmgr;
// Kernel-related lists
- // List of opcodes, loaded from vocab.998. This list is only used for debugging
- // purposes, as we hardcode the list of opcodes in the sci_opcodes enum (script.h)
+ /**
+ * List of opcodes, loaded from vocab.998. This list is only used for debugging
+ * purposes, as we hardcode the list of opcodes in the sci_opcodes enum (script.h)
+ */
Common::Array<opcode> _opcodes;
Common::StringList _selectorNames;
Common::StringList _kernelNames;
@@ -178,61 +181,62 @@ int invoke_selector(EngineState *s, reg_t object, int selector_id, SelectorInvoc
/******************** Text functionality ********************/
+/**
+ * Looks up text referenced by scripts
+ * SCI uses two values to reference to text: An address, and an index. The address
+ * determines whether the text should be read from a resource file, or from the heap,
+ * while the index either refers to the number of the string in the specified source,
+ * or to a relative position inside the text.
+ *
+ * @param s The current state
+ * @param address The address to look up
+ * @param index The relative index
+ * @return The referenced text, or NULL on error.
+ */
char *kernel_lookup_text(EngineState *s, reg_t address, int index);
-/* Looks up text referenced by scripts
-** Parameters: (EngineState *s): The current state
-** (reg_t) address: The address to look up
-** (int) index: The relative index
-** Returns : (char *): The referenced text, or NULL on error.
-** SCI uses two values to reference to text: An address, and an index. The address
-** determines whether the text should be read from a resource file, or from the heap,
-** while the index either refers to the number of the string in the specified source,
-** or to a relative position inside the text.
-*/
/******************** Debug functionality ********************/
-
+/**
+ * Checks whether a heap address contains an object
+ * @param s The current state
+ * @parm obj The address to check
+ * @return True if it is an object, false otherwise
+ */
bool is_object(EngineState *s, reg_t obj);
-/* Checks whether a heap address contains an object
-** Parameters: (EngineState *) s: The current state
-** (reg_t) obj: The address to check
-** Returns : (bool) true if it is an object, false otherwise
-*/
/******************** Kernel function parameter macros ********************/
/* Returns the parameter value or (alt) if not enough parameters were supplied */
-
+/**
+ * Dereferences a heap pointer
+ * @param s The state to operate on
+ * @param pointer The pointer to dereference
+ * @parm entries The number of values expected (for checking; use 0 for strings)
+ * @return A physical reference to the address pointed to, or NULL on error or
+ * if not enugh entries were available.
+ * reg_t dereferenciation also assures alignedness of data.
+ */
reg_t *kernel_dereference_reg_pointer(EngineState *s, reg_t pointer, int entries);
byte *kernel_dereference_bulk_pointer(EngineState *s, reg_t pointer, int entries);
#define kernel_dereference_char_pointer(state, pointer, entries) (char*)kernel_dereference_bulk_pointer(state, pointer, entries)
-/* Dereferences a heap pointer
-** Parameters: (EngineState *) s: The state to operate on
-** (reg_t ) pointer: The pointer to dereference
-** (int) entries: The number of values expected (for checking)
-** (use 0 for strings)
-** Returns : (reg_t/char *): A physical reference to the address pointed
-** to, or NULL on error or if not enugh entries
-** were available
-** reg_t dereferenciation also assures alignedness of data.
-*/
/******************** Priority macros/functions ********************/
-
+/**
+ * Finds the position of the priority band specified
+ * Parameters: (EngineState *) s: State to search in
+ * (int) band: Band to look for
+ * Returns : (int) Offset at which the band starts
+ */
int _find_priority_band(EngineState *s, int band);
-/* Finds the position of the priority band specified
-** Parameters: (EngineState *) s: State to search in
-** (int) band: Band to look for
-** Returns : (int) Offset at which the band starts
-*/
+/**
+ * Does the opposite of _find_priority_band
+ * @param s Engine state
+ * @param y Coordinate to check
+ * @return The priority band y belongs to
+ */
int _find_view_priority(EngineState *s, int y);
-/* Does the opposite of _find_priority_band
-** Parameters: (EngineState *) s: State
-** (int) y: Coordinate to check
-** Returns : (int) The priority band y belongs to
-*/
#define SCI0_VIEW_PRIORITY_14_ZONES(y) (((y) < s->priority_first)? 0 : (((y) >= s->priority_last)? 14 : 1\
+ ((((y) - s->priority_first) * 14) / (s->priority_last - s->priority_first))))
@@ -249,50 +253,59 @@ int _find_view_priority(EngineState *s, int y);
/******************** Dynamic view list functions ********************/
-
+/**
+ * Determines the base rectangle of the specified view object
+ * @param s The state to use
+ * @param object The object to set
+ * @return The absolute base rectangle
+ */
Common::Rect set_base(EngineState *s, reg_t object);
-/* Determines the base rectangle of the specified view object
-** Parameters: (EngineState *) s: The state to use
-** (reg_t) object: The object to set
-** Returns : (abs_rect) The absolute base rectangle
-*/
+/**
+ * Determines the now-seen rectangle of a view object
+ * @param s The state to use
+ * @param object The object to check
+ * @param clip Flag to determine wheter priority band clipping
+ * should be performed
+ * @return The absolute rectangle describing the now-seen area.
+ */
extern Common::Rect get_nsrect(EngineState *s, reg_t object, byte clip);
-/* Determines the now-seen rectangle of a view object
-** Parameters: (EngineState *) s: The state to use
-** (reg_t) object: The object to check
-** (byte) clip: Flag to determine wheter priority band
-** clipping should be performed
-** Returns : (abs_rect) The absolute rectangle describing the
-** now-seen area.
-*/
+/**
+ * Removes all views in anticipation of a new window or text
+ */
void _k_dyn_view_list_prepare_change(EngineState *s);
-/* Removes all views in anticipation of a new window or text */
+
+/**
+ * Redraws all views after a new window or text was added
+ */
void _k_dyn_view_list_accept_change(EngineState *s);
-/* Redraws all views after a new window or text was added */
/******************** Misc functions ********************/
-void process_sound_events(EngineState *s); /* Get all sound events, apply their changes to the heap */
+/**
+ * Get all sound events, apply their changes to the heap
+ */
+void process_sound_events(EngineState *s);
+/**
+ * Resolves an address into a list node
+ * @param s The state to operate on
+ * @param addr The address to resolve
+ * @return The list node referenced, or NULL on error
+ */
Node *lookup_node(EngineState *s, reg_t addr);
-/* Resolves an address into a list node
-** Parameters: (EngineState *) s: The state to operate on
-** (reg_t) addr: The address to resolve
-** Returns : (Node *) The list node referenced, or NULL on error
-*/
-
+/**
+ * Resolves a list pointer to a list
+ * @param s The state to operate on
+ * @param addr The address to resolve
+ * @return The list referenced, or NULL on error
+ */
List *lookup_list(EngineState *s, reg_t addr);
-/* Resolves a list pointer to a list
-** Parameters: (EngineState *) s: The state to operate on
-** (reg_t) addr: The address to resolve
-** Returns : (List *) The list referenced, or NULL on error
-*/
/******************** Constants ********************/
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index a26c2dbcb1..2856c76aa3 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -621,10 +621,14 @@ reg_t kGraph(EngineState *s, int funct_nr, int argc, reg_t *argv) {
reg_t kTextSize(EngineState *s, int funct_nr, int argc, reg_t *argv) {
int width, height;
char *text = argv[1].segment ? (char *) kernel_dereference_bulk_pointer(s, argv[1], 0) : NULL;
+ const char *sep = NULL;
reg_t *dest = kernel_dereference_reg_pointer(s, argv[0], 4);
int maxwidth = (argc > 3) ? argv[3].toUint16() : 0;
int font_nr = argv[2].toUint16();
+ if ((argc > 4) && (argv[4].segment))
+ sep = (const char *)kernel_dereference_bulk_pointer(s, argv[4], 0);
+
if (maxwidth < 0)
maxwidth = 0;
@@ -636,7 +640,7 @@ reg_t kTextSize(EngineState *s, int funct_nr, int argc, reg_t *argv) {
return s->r_acc;
}
- GFX_ASSERT(gfxop_get_text_params(s->gfx_state, font_nr, text, maxwidth ? maxwidth : MAX_TEXT_WIDTH_MAGIC_VALUE,
+ GFX_ASSERT(gfxop_get_text_params(s->gfx_state, font_nr, s->strSplit(text, sep).c_str(), maxwidth ? maxwidth : MAX_TEXT_WIDTH_MAGIC_VALUE,
&width, &height, 0, NULL, NULL, NULL));
debugC(2, kDebugLevelStrings, "GetTextSize '%s' -> %dx%d\n", text, width, height);
@@ -1570,7 +1574,7 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
int font_nr = GET_SEL32V(obj, font);
reg_t text_pos = GET_SEL32(obj, text);
- char *text = text_pos.isNull() ? NULL : (char *)s->seg_manager->dereference(text_pos, NULL);
+ const char *text = text_pos.isNull() ? NULL : (char *)s->seg_manager->dereference(text_pos, NULL);
int view = GET_SEL32V(obj, view);
int cel = sign_extend_byte(GET_SEL32V(obj, cel));
int loop = sign_extend_byte(GET_SEL32V(obj, loop));
@@ -1584,7 +1588,7 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
switch (type) {
case K_CONTROL_BUTTON:
debugC(2, kDebugLevelGraphics, "drawing button %04x:%04x to %d,%d\n", PRINT_REG(obj), x, y);
- ADD_TO_CURRENT_PICTURE_PORT(sciw_new_button_control(s->port, obj, area, text, font_nr,
+ ADD_TO_CURRENT_PICTURE_PORT(sciw_new_button_control(s->port, obj, area, s->strSplit(text, NULL).c_str(), font_nr,
(int8)(state & kControlStateFramed), (int8)inverse, (int8)(state & kControlStateDisabled)));
break;
@@ -1593,7 +1597,7 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
debugC(2, kDebugLevelGraphics, "drawing text %04x:%04x to %d,%d, mode=%d\n", PRINT_REG(obj), x, y, mode);
- ADD_TO_CURRENT_PICTURE_PORT(sciw_new_text_control(s->port, obj, area, text, font_nr, mode,
+ ADD_TO_CURRENT_PICTURE_PORT(sciw_new_text_control(s->port, obj, area, s->strSplit(text).c_str(), font_nr, mode,
(int8)(!!(state & kControlStateDitherFramed)), (int8)inverse));
break;
@@ -1620,8 +1624,8 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
case K_CONTROL_CONTROL:
case K_CONTROL_CONTROL_ALIAS: {
- char **entries_list = NULL;
- char *seeker;
+ const char **entries_list = NULL;
+ const char *seeker;
int entries_nr;
int lsTop = GET_SEL32V(obj, lsTop) - text_pos.offset;
int list_top = 0;
@@ -1641,7 +1645,7 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
if (entries_nr) { // determine list_top, selection, and the entries_list
seeker = text;
- entries_list = (char**)malloc(sizeof(char *) * entries_nr);
+ entries_list = (const char**)malloc(sizeof(char *) * entries_nr);
for (i = 0; i < entries_nr; i++) {
entries_list[i] = seeker;
seeker += entry_size ;
@@ -2524,10 +2528,10 @@ reg_t kNewWindow(EngineState *s, int funct_nr, int argc, reg_t *argv) {
lWhite.alpha = 0;
lWhite.priority = -1;
lWhite.control = -1;
+ const char *title = argv[4 + argextra].segment ? kernel_dereference_char_pointer(s, argv[4 + argextra], 0) : NULL;
window = sciw_new_window(s, gfx_rect(x, y, xl, yl), s->titlebar_port->_font, fgcolor, bgcolor,
- s->titlebar_port->_font, lWhite, black, argv[4 + argextra].segment ?
- kernel_dereference_char_pointer(s, argv[4 + argextra], 0) : NULL, flags);
+ s->titlebar_port->_font, lWhite, black, title ? s->strSplit(title, NULL).c_str() : NULL, flags);
// PQ3 and SCI1.1 games have the interpreter store underBits implicitly
if (argextra)
@@ -3287,7 +3291,7 @@ reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) {
assert_primary_widget_lists(s);
- text_handle = gfxw_new_text(s->gfx_state, area, font_nr, text, halign, ALIGN_TOP, color0, *color1, bg_color, 0);
+ text_handle = gfxw_new_text(s->gfx_state, area, font_nr, s->strSplit(text).c_str(), halign, ALIGN_TOP, color0, *color1, bg_color, 0);
if (!text_handle) {
error("Display: Failed to create text widget");
diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp
index b742c93a52..bb27589d84 100644
--- a/engines/sci/engine/ksound.cpp
+++ b/engines/sci/engine/ksound.cpp
@@ -975,49 +975,42 @@ reg_t kDoSound(EngineState *s, int funct_nr, int argc, reg_t *argv) {
// Used for speech playback in CD games
reg_t kDoAudio(EngineState *s, int funct_nr, int argc, reg_t *argv) {
Audio::Mixer *mixer = g_system->getMixer();
- int sampleLen = 0;
-
- if (!s->_sound._audioResource)
- s->_sound._audioResource = new AudioResource(s->resmgr, s->_version);
switch (argv[0].toUint16()) {
case kSciAudioWPlay:
- case kSciAudioPlay:
- s->_sound._audioResource->stop();
-
- if (argc == 2) { // KQ5CD, KQ6 floppy
- Audio::AudioStream *audioStream = s->_sound._audioResource->getAudioStream(argv[1].toUint16(), 65535, &sampleLen);
-
- if (audioStream)
- mixer->playInputStream(Audio::Mixer::kSpeechSoundType, s->_sound._audioResource->getAudioHandle(), audioStream);
- } else if (argc == 6) { // SQ4CD or newer
- // Make a BE number
- uint32 audioNumber = (((argv[2].toUint16() & 0xFF) << 24) & 0xFF000000) |
- (((argv[3].toUint16() & 0xFF) << 16) & 0x00FF0000) |
- (((argv[4].toUint16() & 0xFF) << 8) & 0x0000FF00) |
- ( (argv[5].toUint16() & 0xFF) & 0x000000FF);
-
- Audio::AudioStream *audioStream = s->_sound._audioResource->getAudioStream(audioNumber, argv[1].toUint16(), &sampleLen);
-
- if (audioStream)
- mixer->playInputStream(Audio::Mixer::kSpeechSoundType, s->_sound._audioResource->getAudioHandle(), audioStream);
- } else { // Hopefully, this should never happen
+ case kSciAudioPlay: {
+ uint16 module;
+ uint32 number;
+
+ s->_sound.stopAudio();
+
+ if (argc == 2) {
+ module = 65535;
+ number = argv[1].toUint16();
+ } else if (argc == 6) {
+ module = argv[1].toUint16();
+ number = ((argv[2].toUint16() & 0xff) << 24) | ((argv[3].toUint16() & 0xff) << 16) |
+ ((argv[4].toUint16() & 0xff) << 8) | (argv[5].toUint16() & 0xff);
+ } else {
warning("kDoAudio: Play called with an unknown number of parameters (%d)", argc);
+ return NULL_REG;
}
- return make_reg(0, sampleLen); // return sample length in ticks
+
+ return make_reg(0, s->_sound.startAudio(module, number)); // return sample length in ticks
+ }
case kSciAudioStop:
- s->_sound._audioResource->stop();
+ s->_sound.stopAudio();
break;
case kSciAudioPause:
- s->_sound._audioResource->pause();
+ s->_sound.pauseAudio();
break;
case kSciAudioResume:
- s->_sound._audioResource->resume();
+ s->_sound.resumeAudio();
break;
case kSciAudioPosition:
- return make_reg(0, s->_sound._audioResource->getAudioPosition());
+ return make_reg(0, s->_sound.getAudioPosition());
case kSciAudioRate:
- s->_sound._audioResource->setAudioRate(argv[1].toUint16());
+ s->_sound.setAudioRate(argv[1].toUint16());
break;
case kSciAudioVolume:
mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, argv[1].toUint16());
@@ -1027,7 +1020,7 @@ reg_t kDoAudio(EngineState *s, int funct_nr, int argc, reg_t *argv) {
// In SCI1.1: tests for digital audio support
return make_reg(0, 1);
} else {
- s->_sound._audioResource->setAudioLang(argv[1].toSint16());
+ s->resmgr->setAudioLanguage(argv[1].toSint16());
}
break;
default:
@@ -1042,8 +1035,10 @@ reg_t kDoSync(EngineState *s, int funct_nr, int argc, reg_t *argv) {
case kSciAudioSyncStart: {
ResourceId id;
- if (s->_sound._soundSync)
- s->resmgr->unlockResource(s->_sound._soundSync);
+ if (s->_sound._syncResource) {
+ s->resmgr->unlockResource(s->_sound._syncResource);
+ s->_sound._syncResource = NULL;
+ }
// Load sound sync resource and lock it
if (argc == 3) {
@@ -1056,10 +1051,11 @@ reg_t kDoSync(EngineState *s, int funct_nr, int argc, reg_t *argv) {
return s->r_acc;
}
- s->_sound._soundSync = (ResourceSync *)s->resmgr->findResource(id, 1);
+ s->_sound._syncResource = s->resmgr->findResource(id, 1);
- if (s->_sound._soundSync) {
- s->_sound._soundSync->startSync(s, argv[1]);
+ if (s->_sound._syncResource) {
+ PUT_SEL32V(argv[1], syncCue, 0);
+ s->_sound._syncOffset = 0;
} else {
warning("DoSync: failed to find resource %s", id.toString().c_str());
// Notify the scripts to stop sound sync
@@ -1067,20 +1063,32 @@ reg_t kDoSync(EngineState *s, int funct_nr, int argc, reg_t *argv) {
}
break;
}
- case kSciAudioSyncNext:
- if (s->_sound._soundSync) {
- s->_sound._soundSync->nextSync(s, argv[1]);
+ case kSciAudioSyncNext: {
+ Resource *res = s->_sound._syncResource;
+ if (res && (s->_sound._syncOffset < res->size - 1)) {
+ int16 syncCue = -1;
+ int16 syncTime = (int16)READ_LE_UINT16(res->data + s->_sound._syncOffset);
+
+ s->_sound._syncOffset += 2;
+
+ if ((syncTime != -1) && (s->_sound._syncOffset < res->size - 1)) {
+ syncCue = (int16)READ_LE_UINT16(res->data + s->_sound._syncOffset);
+ s->_sound._syncOffset += 2;
+ }
+
+ PUT_SEL32V(argv[1], syncTime, syncTime);
+ PUT_SEL32V(argv[1], syncCue, syncCue);
}
break;
+ }
case kSciAudioSyncStop:
- if (s->_sound._soundSync) {
- s->_sound._soundSync->stopSync();
- s->resmgr->unlockResource(s->_sound._soundSync);
- s->_sound._soundSync = NULL;
+ if (s->_sound._syncResource) {
+ s->resmgr->unlockResource(s->_sound._syncResource);
+ s->_sound._syncResource = NULL;
}
break;
default:
- warning("kDoSync: Unhandled case %d", argv[0].toUint16());
+ warning("DoSync: Unhandled subfunction %d", argv[0].toUint16());
}
return s->r_acc;
diff --git a/engines/sci/engine/memobj.cpp b/engines/sci/engine/memobj.cpp
index c0775ae51e..4d37d2aece 100644
--- a/engines/sci/engine/memobj.cpp
+++ b/engines/sci/engine/memobj.cpp
@@ -269,13 +269,6 @@ void Script::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param,
//-------------------- clones --------------------
-template<typename T>
-void Table<T>::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
- for (uint i = 0; i < _table.size(); i++)
- if (isValidEntry(i))
- (*note)(param, make_reg(segId, i));
-}
-
void CloneTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
CloneTable *clone_table = this;
Clone *clone;
diff --git a/engines/sci/engine/memobj.h b/engines/sci/engine/memobj.h
index f800695df5..50c43a0e88 100644
--- a/engines/sci/engine/memobj.h
+++ b/engines/sci/engine/memobj.h
@@ -502,7 +502,11 @@ public:
entries_used--;
}
- virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
+ virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
+ for (uint i = 0; i < _table.size(); i++)
+ if (isValidEntry(i))
+ (*note)(param, make_reg(segId, i));
+ }
};
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp
index a0bfdeddc9..fb094e00f6 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -200,6 +200,9 @@ void Kernel::mapSelectors() {
FIND_SELECTOR(points);
FIND_SELECTOR(syncCue);
FIND_SELECTOR(syncTime);
+ FIND_SELECTOR(printLang);
+ FIND_SELECTOR(subtitleLang);
+ FIND_SELECTOR(parseLang);
}
void Kernel::dumpScriptObject(char *data, int seeker, int objsize) {
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index 63e99ad122..11c38052db 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -26,24 +26,9 @@
// Script debugger functionality. Absolutely not threadsafe.
#include "sci/sci.h"
+#include "sci/console.h"
#include "sci/debug.h"
#include "sci/engine/state.h"
-#include "sci/engine/gc.h"
-#include "sci/engine/kernel_types.h"
-#include "sci/engine/kernel.h"
-#include "sci/engine/savegame.h"
-#include "sci/gfx/gfx_widgets.h"
-#include "sci/gfx/gfx_gui.h"
-#include "sci/gfx/gfx_state_internal.h" // required for GfxContainer, GfxPort, GfxVisual
-#include "sci/resource.h"
-#include "sci/vocabulary.h"
-#include "sci/sfx/iterator.h"
-#include "sci/sfx/sci_midi.h"
-
-#include "common/util.h"
-#include "common/savefile.h"
-
-#include "sound/audiostream.h"
namespace Sci {
@@ -63,13 +48,13 @@ static int *p_var_max; // May be NULL even in valid state!
extern const char *selector_name(EngineState *s, int selector);
-int prop_ofs_to_id(EngineState *s, int prop_ofs, reg_t objp) {
+int propertyOffsetToId(EngineState *s, int prop_ofs, reg_t objp) {
Object *obj = obj_get(s, objp);
byte *selectoroffset;
int selectors;
if (!obj) {
- sciprintf("Applied prop_ofs_to_id on non-object at %04x:%04x\n", PRINT_REG(objp));
+ sciprintf("Applied propertyOffsetToId on non-object at %04x:%04x\n", PRINT_REG(objp));
return -1;
}
@@ -86,7 +71,7 @@ int prop_ofs_to_id(EngineState *s, int prop_ofs, reg_t objp) {
}
if (prop_ofs < 0 || (prop_ofs >> 1) >= selectors) {
- sciprintf("Applied prop_ofs_to_id to invalid property offset %x (property #%d not in [0..%d]) on object at %04x:%04x\n",
+ sciprintf("Applied propertyOffsetToId to invalid property offset %x (property #%d not in [0..%d]) on object at %04x:%04x\n",
prop_ofs, prop_ofs >> 1, selectors - 1, PRINT_REG(objp));
return -1;
}
@@ -257,7 +242,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod
if ((opcode == op_pTos) || (opcode == op_sTop) || (opcode == op_pToa) || (opcode == op_aTop) ||
(opcode == op_dpToa) || (opcode == op_ipToa) || (opcode == op_dpTos) || (opcode == op_ipTos)) {
int prop_ofs = scr[pos.offset + 1];
- int prop_id = prop_ofs_to_id(s, prop_ofs, *p_objp);
+ int prop_id = propertyOffsetToId(s, prop_ofs, *p_objp);
sciprintf(" (%s)", selector_name(s, prop_id));
}
@@ -342,8 +327,6 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod
void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *objp, int *restadjust,
SegmentId *segids, reg_t **variables, reg_t **variables_base, int *variables_nr, int bp) {
-// TODO: disabled till this is moved in console.cpp
-#if 0
// Do we support a separate console?
int old_debugstate = g_debugstate_valid;
@@ -412,7 +395,6 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *
// OK, found whatever we were looking for
}
}
-#endif
g_debugstate_valid = (g_debug_step_running == 0);
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index 98fbd8bad7..2227167673 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -430,7 +430,7 @@ void SegManager::heapRelocate(reg_t block) {
#define INST_LOOKUP_CLASS(id) ((id == 0xffff) ? NULL_REG : get_class_address(s, id, SCRIPT_GET_LOCK, NULL_REG))
-reg_t get_class_address(EngineState *s, int classnr, int lock, reg_t caller);
+reg_t get_class_address(EngineState *s, int classnr, SCRIPT_GET lock, reg_t caller);
Object *SegManager::scriptObjInit0(EngineState *s, reg_t obj_pos) {
Object *obj;
diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h
index dc91d60e69..a41d820014 100644
--- a/engines/sci/engine/seg_manager.h
+++ b/engines/sci/engine/seg_manager.h
@@ -45,29 +45,38 @@ namespace Sci {
class SegManager : public Common::Serializable {
public:
- // Initialize the segment manager
+ /**
+ * Initialize the segment manager
+ */
SegManager(bool sci1_1);
- // Deallocate all memory associated with the segment manager
+ /**
+ * Deallocate all memory associated with the segment manager
+ */
~SegManager();
virtual void saveLoadWithSerializer(Common::Serializer &ser);
// 1. Scripts
- // Allocate a script into the segment manager
- // Parameters: (int) script_nr: number of the script to load
- // (state_t *) s: The state containing resource manager handlers to load the
- // script data
- // Returns : (int) 0 on failure, 1 on success
- // (int) *seg_id: The segment ID of the newly allocated segment, on success
+ /**
+ * Allocate a script into the segment manager
+ * @param s The state containing resource manager
+ * handlers to load the script data
+ * @param script_nr The number of the script to load
+ * @param seg_id The segment ID of the newly allocated segment,
+ * on success
+ * @return 0 on failure, 1 on success
+ */
Script *allocateScript(EngineState *s, int script_nr, SegmentId *seg_id);
// The script must then be initialised; see section (1b.), below.
- // Forcefully deallocate a previously allocated script
- // Parameters: (int) script_nr: number of the script to deallocate
- // Returns : (int) 1 on success, 0 on failure
+ /**
+ * Forcefully deallocate a previously allocated script
+ * @param script_nr number of the script to deallocate
+ * @return 1 on success, 0 on failure
+ */
int deallocateScript(int script_nr);
/**
@@ -76,30 +85,40 @@ public:
*/
bool scriptIsLoaded(SegmentId seg);
- // Validate whether the specified public function is exported by the script in the specified segment
- // Parameters: (int) pubfunct: Index of the function to validate
- // (int) seg: Segment ID of the script the check is to be performed for
- // Returns : (uint16) 0 if the public function is invalid, its offset into the script's segment
- // otherwise
+ /**
+ * Validate whether the specified public function is exported by
+ * the script in the specified segment
+ * @param pubfunct Index of the function to validate
+ * @param seg Segment ID of the script the check is to
+ * be performed for
+ * @return NULL if the public function is invalid, its
+ * offset into the script's segment otherwise
+ */
uint16 validateExportFunc(int pubfunct, SegmentId seg);
- // Get the segment ID associated with a script number
- // Parameters: (int) script_nr: Number of the script to look up
- // Returns : (int) The associated segment ID, or -1 if no matching segment exists
+ /**
+ * Get the segment ID associated with a script number
+ * @param script_nr Number of the script to look up
+ * @return The associated segment ID, or -1 if no
+ * matching segment exists
+ */
SegmentId segGet(int script_nr) const;
/**
- * Return a pointer to the specified script. If the id is invalid, does not refer
- * to a script or the script is not loaded, this will invoke error().
+ * Return a pointer to the specified script.
+ * If the id is invalid, does not refer to a script or the script is
+ * not loaded, this will invoke error().
* @param seg ID of the script segment to check for
- * @return pointer to the Script object
+ * @return A pointer to the Script object
*/
Script *getScript(SegmentId seg);
/**
- * Return a pointer to the specified script. If the id is invalid, does not refer
+ * Return a pointer to the specified script.
+ * If the id is invalid, does not refer to a script, or
+ * the script is not loaded, this will return NULL
* @param seg ID of the script segment to check for
- * @return pointer to the Script object, or NULL
+ * @return A pointer to the Script object, or NULL
*/
Script *getScriptIfLoaded(SegmentId seg);
@@ -112,51 +131,70 @@ public:
// to be used during script instantiation,
// i.e. loading and linking.
- // Initializes a script's local variable block
- // Parameters: (SegmentId) seg: Segment containing the script to initialize
- // (int) nr: Number of local variables to allocate
- // All variables are initialized to zero.
+ /**
+ * Initializes a script's local variable block
+ * All variables are initialized to zero.
+ * @param seg Segment containing the script to initialize
+ * @param nr Number of local variables to allocate
+ */
void scriptInitialiseLocalsZero(SegmentId seg, int nr);
- // Initializes a script's local variable block according to a prototype
- // Parameters: (reg_t) location: Location to initialize from
+ /**
+ * Initializes a script's local variable block according to a prototype
+ * @param location Location to initialize from
+ */
void scriptInitialiseLocals(reg_t location);
- // Initializes an object within the segment manager
- // Parameters: (reg_t) obj_pos: Location (segment, offset) of the object
- // Returns : (Object *) A newly created Object describing the object
- // obj_pos must point to the beginning of the script/class block (as opposed
- // to what the VM considers to be the object location)
- // The corresponding Object is stored within the relevant script.
+ /**
+ * Initializes an object within the segment manager
+ * @param obj_pos Location (segment, offset) of the object. It must
+ * point to the beginning of the script/class block
+ * (as opposed to what the VM considers to be the
+ * object location)
+ * @returns A newly created Object describing the object,
+ * stored within the relevant script
+ */
Object *scriptObjInit(EngineState *s, reg_t obj_pos);
- // Informs the segment manager that a code block must be relocated
- // Parameters: (reg_t) location: Start of block to relocate
+ /**
+ * Informs the segment manager that a code block must be relocated
+ * @param location Start of block to relocate
+ */
void scriptAddCodeBlock(reg_t location);
- // Tells the segment manager whether exports are wide (32-bit) or not.
- // Parameters: (int) flag: 1 if exports are wide, 0 otherwise
+ /**
+ * Tells the segment manager whether exports are wide (32-bit) or not.
+ * @param flag 1 if exports are wide, 0 otherwise
+ */
void setExportWidth(int flag);
- // Processes a relocation block witin a script
- // Parameters: (reg_t) obj_pos: Location (segment, offset) of the block
- // Returns : (Object *) Location of the relocation block
- // This function is idempotent, but it must only be called after all
- // objects have been instantiated, or a run-time error will occur.
+ /**
+ * Processes a relocation block witin a script
+ * This function is idempotent, but it must only be called after all
+ * objects have been instantiated, or a run-time error will occur.
+ * @param obj_pos Location (segment, offset) of the block
+ * @return Location of the relocation block
+ */
void scriptRelocate(reg_t block);
- // Determines whether the script referenced by the indicated segment is marked as being deleted.
- // Parameters: (SegmentId) Segment ID of the script to investigate
- // Returns : (int) 1 iff seg points to a script and the segment is deleted, 0 otherwise
- // Will return 0 when applied to an invalid or non-script seg.
+ /**
+ * Determines whether the script referenced by the indicated segment
+ * is marked as being deleted.
+ * Will return 0 when applied to an invalid or non-script seg.
+ * @param seg Segment ID of the script to investigate
+ * @return 1 iff seg points to a script and the segment is
+ * deleted, 0 otherwise
+ */
bool scriptIsMarkedAsDeleted(SegmentId seg);
// 2. Clones
- // Allocate a fresh clone
- // Returns : (Clone*): Reference to the memory allocated for the clone
- // (reg_t) *addr: The offset of the freshly allocated clone
+ /**
+ * Allocate a fresh clone
+ * @param addr The offset of the freshly allocated clone
+ * @return Reference to the memory allocated for the clone
+ */
Clone *alloc_Clone(reg_t *addr);
@@ -166,76 +204,96 @@ public:
// 4. Stack
- // Allocates a data stack
- // Parameters: (int) size: Number of stack entries to reserve
- // Returns : (DataStack *): The physical stack
- // (SegmentId) segid: Segment ID of the stack
+ /**
+ * Allocates a data stack
+ * @param size Number of stack entries to reserve
+ * @param segid Segment ID of the stack
+ * @return The physical stack
+ */
DataStack *allocateStack(int size, SegmentId *segid);
// 5. System Strings
- // Allocates a system string table
- // Returns : (DataStack *): The physical stack
- // (SegmentId) segid: Segment ID of the stack
- // See also sys_string_acquire();
+ /**
+ * Allocates a system string table
+ * See also sys_string_acquire();
+ * @param[in] segid Segment ID of the stack
+ * @returns The physical stack
+ */
SystemStrings *allocateSysStrings(SegmentId *segid);
// 5. System Strings
- // Allocates a string fragments segment
- // Returns : (SegmentId): Segment ID to use for string fragments
- // See also stringfrag.h
+ /**
+ * Allocates a string fragments segment
+ * See also stringfrag.h
+ * @return Segment ID to use for string fragments
+ */
SegmentId allocateStringFrags();
// 6, 7. Lists and Nodes
- // Allocate a fresh list
- // Returns : (listY_t*): Reference to the memory allocated for the list
- // (reg_t) *addr: The offset of the freshly allocated list
+ /**
+ * Allocate a fresh list
+ * @param[in] addr The offset of the freshly allocated list
+ * @return Reference to the memory allocated for the list
+ */
List *alloc_List(reg_t *addr);
- // Allocate a fresh node
- // Returns : (node_t*): Reference to the memory allocated for the node
- // (reg_t) *addr: The offset of the freshly allocated node
+ /**
+ * Allocate a fresh node
+ * @param[in] addr The offset of the freshly allocated node
+ * @return Reference to the memory allocated for the node
+ */
Node *alloc_Node(reg_t *addr);
// 8. Hunk Memory
- // Allocate a fresh chunk of the hunk
- // Parameters: (int) size: Number of bytes to allocate for the hunk entry
- // (const char *) hunk_type: A descriptive string for the hunk entry,
- // for debugging purposes
- // Returns : (Hunk *): Reference to the memory allocated for the hunk piece
- // (reg_t) *addr: The offset of the freshly allocated hunk entry
+ /**
+ * Allocate a fresh chunk of the hunk
+ * @param[in] size Number of bytes to allocate for the hunk entry
+ * @param[in] hunk_type A descriptive string for the hunk entry, for
+ * debugging purposes
+ * @param[out] addr The offset of the freshly allocated hunk entry
+ * @return Reference to the memory allocated for the hunk
+ * piece
+ */
Hunk *alloc_hunk_entry(const char *hunk_type, int size, reg_t *addr);
- // Deallocates a hunk entry
- // Parameters: (reg_t) addr: Offset of the hunk entry to delete
+ /**
+ * Deallocates a hunk entry
+ * @param[in] addr Offset of the hunk entry to delete
+ */
void free_hunk_entry(reg_t addr);
// 9. Dynamic Memory
- // Allocate some dynamic memory
- // Parameters: (int) size: Number of bytes to allocate
- // (const char_ *) description: A descriptive string,
- // for debugging purposes
- // Returns : (unsigned char*): Raw pointer into the allocated dynamic memory
- // (reg_t) *addr: The offset of the freshly allocated X
+ /**
+ * Allocate some dynamic memory
+ * @param[in] size Number of bytes to allocate
+ * @param[in] description A descriptive string for debugging purposes
+ * @param[out] addr The offset of the freshly allocated X
+ * @return Raw pointer into the allocated dynamic
+ * memory
+ */
unsigned char *allocDynmem(int size, const char *description, reg_t *addr);
- // Deallocates a piece of dynamic memory
- // Parameters: (reg_t) addr: Offset of the dynmem chunk to free
+ /**
+ * Deallocates a piece of dynamic memory
+ * @param[in] addr Offset of the dynmem chunk to free
+ */
int freeDynmem(reg_t addr);
- // Gets the description of a dynmem segment
- // Parameters: (reg_t) addr: Segment to describe
- // Returns : (const char *): Pointer to the descriptive string set in
- // allocDynmem
+ /**
+ * Gets the description of a dynmem segment
+ * @param[in] addr Segment to describe
+ * @return Pointer to the descriptive string set in allocDynmem
+ */
const char *getDescription(reg_t addr);
@@ -251,10 +309,12 @@ public:
// Generic Operations on Segments and Addresses
- // Dereferences a raw memory pointer
- // Parameters: (reg_t) reg: The reference to dereference
- // Returns : (byte *) The data block referenced
- // (int) size: (optionally) the theoretical maximum size of it
+ /**
+ * Dereferences a raw memory pointer
+ * @param[in] reg The reference to dereference
+ * @param[out] size (optional) The theoretical maximum size
+ * @return The data block referenced
+ */
byte *dereference(reg_t reg, int *size);
@@ -266,17 +326,17 @@ public:
int initialiseScript(Script &scr, EngineState *s, int script_nr);
private:
- IntMapper *id_seg_map; // id - script id; seg - index of heap
+ IntMapper *id_seg_map; ///< id - script id; seg - index of heap
public: // TODO: make private
Common::Array<MemObject *> _heap;
int reserved_id;
int exports_wide;
bool isSci1_1;
- SegmentId Clones_seg_id; // ID of the (a) clones segment
- SegmentId Lists_seg_id; // ID of the (a) list segment
- SegmentId Nodes_seg_id; // ID of the (a) node segment
- SegmentId Hunks_seg_id; // ID of the (a) hunk segment
+ SegmentId Clones_seg_id; ///< ID of the (a) clones segment
+ SegmentId Lists_seg_id; ///< ID of the (a) list segment
+ SegmentId Nodes_seg_id; ///< ID of the (a) node segment
+ SegmentId Hunks_seg_id; ///< ID of the (a) hunk segment
private:
MemObject *allocNonscriptSegment(MemObjectType type, SegmentId *segid);
@@ -295,11 +355,12 @@ private:
Object *scriptObjInit0(EngineState *s, reg_t obj_pos);
Object *scriptObjInit11(EngineState *s, reg_t obj_pos);
- /* Check segment validity
- ** Parameters: (int) seg: The segment to validate
- ** Returns : (bool) false if 'seg' is an invalid segment
- ** true if 'seg' is a valid segment
- */
+ /**
+ * Check segment validity
+ * @param[in] seg The segment to validate
+ * @return false if 'seg' is an invalid segment, true if
+ * 'seg' is a valid segment
+ */
bool check(SegmentId seg);
void dbgPrint(const char* msg, void *i); // for debug only
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index e35530700e..e618077d54 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -126,4 +126,73 @@ uint16 EngineState::currentRoomNumber() const {
return script_000->locals_block->_locals[13].toUint16();
}
+kLanguage EngineState::charToLanguage(const char c) const {
+ switch (c) {
+ case 'F':
+ return K_LANG_FRENCH;
+ case 'S':
+ return K_LANG_SPANISH;
+ case 'I':
+ return K_LANG_ITALIAN;
+ case 'G':
+ return K_LANG_GERMAN;
+ case 'J':
+ case 'j':
+ return K_LANG_JAPANESE;
+ case 'P':
+ return K_LANG_PORTUGUESE;
+ default:
+ return K_LANG_NONE;
+ }
+}
+
+Common::String EngineState::getLanguageString(const char *str, kLanguage lang) const {
+ kLanguage secondLang = K_LANG_NONE;
+
+ const char *seeker = str;
+ while (*seeker) {
+ if ((*seeker == '%') || (*seeker == '#')) {
+ secondLang = charToLanguage(*(seeker + 1));
+
+ if (secondLang != K_LANG_NONE)
+ break;
+ }
+
+ seeker++;
+ }
+
+ if ((secondLang == K_LANG_JAPANESE) && (*(seeker + 1) == 'J')) {
+ // FIXME: Add Kanji support
+ lang = K_LANG_ENGLISH;
+ }
+
+ if (secondLang == lang)
+ return Common::String(seeker + 2);
+
+ if (seeker)
+ return Common::String(str, seeker - str);
+ else
+ return Common::String(str);
+}
+
+Common::String EngineState::strSplit(const char *str, const char *sep) {
+ EngineState *s = this;
+
+ kLanguage lang = (kLanguage)GET_SEL32V(s->game_obj, printLang);
+ kLanguage subLang = (kLanguage)GET_SEL32V(s->game_obj, subtitleLang);
+
+ // Use English when no language settings are present in the game
+ if (lang == K_LANG_NONE)
+ lang = K_LANG_ENGLISH;
+
+ Common::String retval = getLanguageString(str, lang);
+
+ if ((subLang != K_LANG_NONE) && (sep != NULL)) {
+ retval += sep;
+ retval += getLanguageString(str, subLang);
+ }
+
+ return retval;
+}
+
} // End of namespace Sci
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index 15c1c2e63e..ecfb9fe6f7 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -88,6 +88,18 @@ enum {
SCI_GAME_WAS_RESTARTED_AT_LEAST_ONCE = 4
};
+/** Supported languages */
+enum kLanguage {
+ K_LANG_NONE = 0,
+ K_LANG_ENGLISH = 1,
+ K_LANG_FRENCH = 33,
+ K_LANG_SPANISH = 34,
+ K_LANG_ITALIAN = 39,
+ K_LANG_GERMAN = 49,
+ K_LANG_JAPANESE = 81,
+ K_LANG_PORTUGUESE = 351
+};
+
struct drawn_pic_t {
int nr;
int palette;
@@ -209,6 +221,16 @@ public:
uint16 currentRoomNumber() const;
+ /**
+ * Processes a multilanguage string based on the current language settings and
+ * returns a string that is ready to be displayed.
+ * @param str the multilanguage string
+ * @param sep optional seperator between main language and subtitle language,
+ * if NULL is passed no subtitle will be added to the returned string
+ * @return processed string
+ */
+ Common::String strSplit(const char *str, const char *sep = "\r----------\r");
+
/* Debugger data: */
Breakpoint *bp_list; /**< List of breakpoints */
int have_bp; /**< Bit mask specifying which types of breakpoints are used in bp_list */
@@ -239,6 +261,10 @@ public:
Kernel *_kernel;
EngineState *successor; /**< Successor of this state: Used for restoring */
+
+private:
+ kLanguage charToLanguage(const char c) const;
+ Common::String getLanguageString(const char *str, kLanguage lang) const;
};
/**
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index 0b84c0ef3c..cbd0b0cfbb 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -193,7 +193,7 @@ int script_error(EngineState *s, const char *file, int line, const char *reason)
}
#define CORE_ERROR(area, msg) script_error(s, "[" area "] " __FILE__, __LINE__, msg)
-reg_t get_class_address(EngineState *s, int classnr, int lock, reg_t caller) {
+reg_t get_class_address(EngineState *s, int classnr, SCRIPT_GET lock, reg_t caller) {
if (NULL == s) {
warning("vm.c: get_class_address(): NULL passed for \"s\"");
@@ -1550,7 +1550,7 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select
return _lookup_selector_function(s, obj_location.segment, obj, selector_id, fptr);
}
-SegmentId script_get_segment(EngineState *s, int script_nr, int load) {
+SegmentId script_get_segment(EngineState *s, int script_nr, SCRIPT_GET load) {
SegmentId segment;
if ((load & SCRIPT_GET_LOAD) == SCRIPT_GET_LOAD)
diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h
index dfbbc39780..a3fabbe44b 100644
--- a/engines/sci/engine/vm.h
+++ b/engines/sci/engine/vm.h
@@ -198,7 +198,11 @@ struct selector_map_t {
Selector points; /**< Used by AvoidPath() */
Selector syncCue; /**< Used by DoSync() */
- Selector syncTime; /**< Used by DoSync() */
+ Selector syncTime;
+
+ Selector printLang; /**< Used for i18n */
+ Selector subtitleLang;
+ Selector parseLang;
};
// A reference to an object's variable.
@@ -287,8 +291,8 @@ struct Breakpoint {
};
/**
- * Set this to 1 to abort script execution immediately. Aborting will leave the
- * debug exec stack intact.
+ * Set this to 1 to abort script execution immediately. Aborting will
+ * leave the debug exec stack intact.
* Set it to 2 to force a replay afterwards.
*/
extern int script_abort_flag;
@@ -307,31 +311,36 @@ extern int script_step_counter;
/**
* Executes function pubfunct of the specified script.
- * Parameters: (EngineState *) s: The state which is to be executed with
- * (uint16) script: The script which is called
- * (uint16) pubfunct: The exported script function which is to be called
- * (StackPtr) sp: Stack pointer position
- * (reg_t) calling_obj: The heap address of the object which executed the call
- * (uint16) argc: Number of arguments supplied
- * (StackPtr) argp: Pointer to the first supplied argument
- * Returns : (ExecStack *): A pointer to the new exec stack TOS entry
+ * @param[in] s The state which is to be executed with
+ * @param[in] script The script which is called
+ * @param[in] pubfunct The exported script function which is to
+ * be called
+ * @param[in] sp Stack pointer position
+ * @param[in] calling_obj The heap address of the object that
+ * executed the call
+ * @param[in] argc Number of arguments supplied
+ * @param[in] argp Pointer to the first supplied argument
+ * @return A pointer to the new exec stack TOS entry
*/
-ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackPtr sp, reg_t calling_obj,
- uint16 argc, StackPtr argp);
+ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct,
+ StackPtr sp, reg_t calling_obj, uint16 argc, StackPtr argp);
/**
* Executes a "send" or related operation to a selector.
- * Parameters: (EngineState *) s: The EngineState to operate on
- * (reg_t) send_obj: Heap address of the object to send to
- * (reg_t) work_obj: Heap address of the object initiating the send
- * (StackPtr) sp: Stack pointer position
- * (int) framesize: Size of the send as determined by the "send" operation
- * (StackPtr) argp: Pointer to the beginning of the heap block containing the
- * data to be sent. This area is a succession of one or more
- * sequences of [selector_number][argument_counter] and then
- * "argument_counter" word entries with the parameter values.
- * Returns : (ExecStack *): A pointer to the new execution stack TOS entry
+ * @param[in] s The EngineState to operate on
+ * @param[in] send_obj Heap address of the object to send to
+ * @param[in] work_obj Heap address of the object initiating the send
+ * @param[in] sp Stack pointer position
+ * @param[in] framesize Size of the send as determined by the "send"
+ * operation
+ * @param[in] argp Pointer to the beginning of the heap block
+ * containing the data to be sent. This area is a
+ * succession of one or more sequences of
+ * [selector_number][argument_counter] and then
+ * "argument_counter" word entries with the
+ * parameter values.
+ * @return A pointer to the new execution stack TOS entry
*/
ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj,
StackPtr sp, int framesize, StackPtr argp);
@@ -342,267 +351,300 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj,
/**
* Adds an entry to the top of the execution stack.
*
- * @param s The state with which to execute
- * @param pc The initial program counter
- * @param sp The initial stack pointer
- * @param objp Pointer to the beginning of the current object
- * @param argc Number of parameters to call with
- * @param argp Heap pointer to the first parameter
- * @param selector The selector by which it was called or
- * NULL_SELECTOR if n.a. For debugging.
- * @param sendp Pointer to the object which the message was sent to.
- * Equal to objp for anything but super.
- * @param origin Number of the execution stack element this entry was created by
- * (usually the current TOS number, except for multiple sends).
- * @param local_segment The segment to use for local variables,
- * or SCI_XS_CALLEE_LOCALS to use obj's segment.
- * @return a pointer to the new exec stack TOS entry
- */
-ExecStack *add_exec_stack_entry(EngineState *s, reg_t pc, StackPtr sp, reg_t objp, int argc,
- StackPtr argp, Selector selector, reg_t sendp, int origin, SegmentId local_segment);
+ * @param[in] s The state with which to execute
+ * @param[in] pc The initial program counter
+ * @param[in] sp The initial stack pointer
+ * @param[in] objp Pointer to the beginning of the current object
+ * @param[in] argc Number of parameters to call with
+ * @param[in] argp Heap pointer to the first parameter
+ * @param[in] selector The selector by which it was called or
+ * NULL_SELECTOR if n.a. For debugging.
+ * @param[in] sendp Pointer to the object which the message was
+ * sent to. Equal to objp for anything but super.
+ * @param[in] origin Number of the execution stack element this
+ * entry was created by (usually the current TOS
+ * number, except for multiple sends).
+ * @param[in] local_segment The segment to use for local variables,
+ * or SCI_XS_CALLEE_LOCALS to use obj's segment.
+ * @return A pointer to the new exec stack TOS entry
+ */
+ExecStack *add_exec_stack_entry(EngineState *s, reg_t pc, StackPtr sp,
+ reg_t objp, int argc, StackPtr argp, Selector selector,
+ reg_t sendp, int origin, SegmentId local_segment);
/**
* Adds one varselector access to the execution stack.
- * Parameters: (EngineState *) s: The EngineState to use
- * (reg_t) objp: Pointer to the object owning the selector
- * (int) argc: 1 for writing, 0 for reading
- * (StackPtr) argp: Pointer to the address of the data to write -2
- * (int) selector: Selector name
- * (ObjVarRef& ) address: Heap address of the selector
- * (int) origin: Stack frame which the access originated from
- * Returns : (ExecStack *): Pointer to the new exec-TOS element
* This function is called from send_selector only.
+ * @param[in] s The EngineState to use
+ * @param[in] objp Pointer to the object owning the selector
+ * @param[in] argc 1 for writing, 0 for reading
+ * @param[in] argp Pointer to the address of the data to write -2
+ * @param[in] selector Selector name
+ * @param[in] address Heap address of the selector
+ * @param[in] origin Stack frame which the access originated from
+ * @return Pointer to the new exec-TOS element
*/
-ExecStack *add_exec_stack_varselector(EngineState *s, reg_t objp, int argc, StackPtr argp,
- Selector selector, const ObjVarRef& address, int origin);
-
+ExecStack *add_exec_stack_varselector(EngineState *s, reg_t objp, int argc,
+ StackPtr argp, Selector selector, const ObjVarRef& address,
+ int origin);
+/**
+ * This function executes SCI bytecode
+ * It executes the code on s->heap[pc] until it hits a 'ret' operation
+ * while (stack_base == stack_pos). Requires s to be set up correctly.
+ * @param[in] s The state to use
+ * @param[in] restoring 1 if s has just been restored, 0 otherwise
+ */
void run_vm(EngineState *s, int restoring);
-/* Executes the code on s->heap[pc] until it hits a 'ret' operation while (stack_base == stack_pos)
-** Parameters: (EngineState *) s: The state to use
-** (int) restoring: 1 if s has just been restored, 0 otherwise
-** Returns : (void)
-** This function will execute SCI bytecode. It requires s to be set up
-** correctly.
-*/
+/**
+ * Handles a fatal error condition
+ * @param[in] s The state to recover from
+ * @param[in] line Source code line number the error occured in
+ * @param[in] file File the error occured in
+ */
void vm_handle_fatal_error(EngineState *s, int line, const char *file);
-/* Handles a fatal error condition
-** Parameters: (EngineState *) s: The state to recover from
-** (int) line: Source code line number the error occured in
-** (const char *) file: File the error occured in
-*/
-
-
-void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *objp,
- int *restadjust, SegmentId *segids, reg_t **variables, reg_t **variables_base,
- int *variables_nr, int bp);
-/* Debugger functionality
-** Parameters: (EngineState *) s: The state at which debugging should take place
-** (reg_t *) pc: Pointer to the program counter
-** (StackPtr *) sp: Pointer to the stack pointer
-** (StackPtr *) pp: Pointer to the frame pointer
-** (reg_t *) objp: Pointer to the object base pointer
-** (int *) restadjust: Pointer to the &rest adjustment value
-** (SegmentId *) segids: four-element array containing segment IDs for locals etc.
-** (reg_t **) variables: four-element array referencing registers for globals etc.
-** (reg_t **) variables_base: four-element array referencing
-** register bases for temps etc.
-** (int *) variables_nr: four-element array giving sizes for params etc. (may be NULL)
-** (int) bp: Flag, set to 1 when a breakpoint is triggered
-** Returns : (void)
-*/
+
+/**
+ * Debugger functionality
+ * @param[in] s The state at which debugging should take
+ * place
+ * @param[in] pc Pointer to the program counter
+ * @param[in] sp Pointer to the stack pointer
+ * @param[in] pp Pointer to the frame pointer
+ * @param[in] objp Pointer to the object base pointer
+ * @param[in] restadjust Pointer to the &rest adjustment value
+ * @param[in] segids four-element array containing segment IDs
+ * for locals etc.
+ * @param[in] variables four-element array referencing registers
+ * for globals etc.
+ * @param[in] variables_base four-element array referencing register
+ * bases for temps etc.
+ * @param[in] variables_nr four-element array giving sizes for params
+ * etc. (may be NULL)
+ * @param[in] bp Flag, set to 1 when a breakpoint is
+ * triggered
+ */
+void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp,
+ reg_t *objp, int *restadjust, SegmentId *segids, reg_t **variables,
+ reg_t **variables_base, int *variables_nr, int bp);
+
+/**
+ * Initializes a EngineState block
+ * @param[in] s The state to initialize
+ * @return 0 on success, 1 if vocab.996 (the class table) is missing
+ * or corrupted
+ */
int script_init_engine(EngineState *s);
-/* Initializes a EngineState block
-** Parameters: (EngineState *) s: The state to initialize
-** Returns : 0 on success, 1 if vocab.996 (the class table) is missing or corrupted
-*/
+/**
+ * Sets the gamestate's save_dir to the parameter path
+ * @param[in] s The state to set
+ * @param[in] path Path where save_dir will point to
+ */
void script_set_gamestate_save_dir(EngineState *s, const char *path);
-/* Sets the gamestate's save_dir to the parameter path
-** Parameters: (EngineState *) s: The state to set
-** (const char *) path: Path where save_dir will point to
-** Returns : (void)
-*/
+/**
+ * Frees all additional memory associated with a EngineState block
+ * @param[in] s The EngineState whose elements should be cleared
+ */
void script_free_engine(EngineState *s);
-/* Frees all additional memory associated with a EngineState block
-** Parameters: (EngineState *) s: The EngineState whose elements should be cleared
-** Returns : (void)
-*/
+/**
+ * Frees all script memory (heap, hunk, and class tables).
+ * This operation is implicit in script_free_engine(), but is required for
+ * restoring the game state.
+ * @param[in] s The EngineState to free
+ */
void script_free_vm_memory(EngineState *s);
-/* Frees all script memory (heap, hunk, and class tables).
-** Parameters: (EngineState *) s: The EngineState to free
-** Returns : (void)
-** This operation is implicit in script_free_engine(), but is required for restoring
-** the game state.
-*/
-
-
-SelectorType lookup_selector(EngineState *s, reg_t obj, Selector selectorid, ObjVarRef *varp, reg_t *fptr);
-/* Looks up a selector and returns its type and value
-** Parameters: (EngineState *) s: The EngineState to use
-** (reg_t) obj: Address of the object to look the selector up in
-** (Selector) selectorid: The selector to look up
-** Returns : (SelectorType) kSelectorNone if the selector was not found in the object or its superclasses.
-** kSelectorVariable if the selector represents an object-relative variable
-** kSelectorMethod if the selector represents a method
-** (ObjVarRef *) *varp: A reference to the selector, if
-** it is a variable
-** (reg_t) *fptr: A reference to the function described by that selector, if it is
-** a valid function selector.
-** *varindex is written to iff it is non-NULL and the selector indicates a property of the object.
-** *fptr is written to iff it is non-NULL and the selector indicates a member function of that object.
-*/
-enum {
+/**
+ * Looks up a selector and returns its type and value
+ * varindex is written to iff it is non-NULL and the selector indicates a property of the object.
+ * @param[in] s The EngineState to use
+ * @param[in] obj Address of the object to look the selector up in
+ * @param[in] selectorid The selector to look up
+ * @param[out] varp A reference to the selector, if it is a
+ * variable.
+ * @param[out] fptr A reference to the function described by that
+ * selector, if it is a valid function selector.
+ * fptr is written to iff it is non-NULL and the
+ * selector indicates a member function of that
+ * object.
+ * @return kSelectorNone if the selector was not found in
+ * the object or its superclasses.
+ * kSelectorVariable if the selector represents an
+ * object-relative variable.
+ * kSelectorMethod if the selector represents a
+ * method
+ */
+SelectorType lookup_selector(EngineState *s, reg_t obj, Selector selectorid,
+ ObjVarRef *varp, reg_t *fptr);
+
+/**
+ * Parameters for script_get_segment()
+ */
+typedef enum {
SCRIPT_GET_DONT_LOAD = 0, /**< Fail if not loaded */
SCRIPT_GET_LOAD = 1, /**< Load, if neccessary */
SCRIPT_GET_LOCK = 3 /**< Load, if neccessary, and lock */
-};
+} SCRIPT_GET;
-SegmentId script_get_segment(EngineState *s, int script_id, int load);
-/* Determines the segment occupied by a certain script
-** Parameters: (EngineState *) s: The state to operate on
-** (int) script_id: The script in question
-** (int) load: One of SCRIPT_GET_*
-** Returns : The script's segment, or 0 on failure
-*/
+/**
+ * Determines the segment occupied by a certain script
+ * @param[in] s The state to operate on
+ * @param[in] script_id The script in question
+ * @param[in] load One of SCRIPT_GET_*
+ * @return The script's segment, or 0 on failure
+ */
+SegmentId script_get_segment(EngineState *s, int script_id, SCRIPT_GET load);
+/**
+ * Looks up an entry of the exports table of a script
+ * @param[in] s The state to operate on
+ * @param[in] script_nr The script to look up in
+ * @param[out] export_index The index of the export entry to look up
+ * @return The handle
+ */
reg_t script_lookup_export(EngineState *s, int script_nr, int export_index);
-/* Looks up an entry of the exports table of a script
-** Parameters: (EngineState *) s: The state to operate on
-** (int) script_nr: The script to look up in
-** Returns : (int) export_index: index of the export entry to look up
-*/
+/**
+ * Makes sure that a script and its superclasses get loaded to the heap.
+ * If the script already has been loaded, only the number of lockers is
+ * increased. All scripts containing superclasses of this script are loaded
+ * recursively as well, unless 'recursive' is set to zero. The
+ * complementary function is "script_uninstantiate()" below.
+ * @param[in] s The state to operate on
+ * @param[in] script_nr The script number to load
+ * @return The script's segment ID or 0 if out of heap
+ */
int script_instantiate(EngineState *s, int script_nr);
-/* Makes sure that a script and its superclasses get loaded to the heap
-** Parameters: (EngineState *) s: The state to operate on
-** (int) script_nr: The script number to load
-** Returns : (int) The script's segment ID or 0 if out of heap
-** If the script already has been loaded, only the number of lockers is increased.
-** All scripts containing superclasses of this script aret loaded recursively as well,
-** unless 'recursive' is set to zero.
-** The complementary function is "script_uninstantiate()" below.
-*/
-
+/**
+ * Decreases the numer of lockers of a script and unloads it if that number
+ * reaches zero.
+ * This function will recursively unload scripts containing its
+ * superclasses, if those aren't locked by other scripts as well.
+ * @param[in] s The state to operate on
+ * @param[in] script_nr The script number that is requestet to be unloaded
+ */
void script_uninstantiate(EngineState *s, int script_nr);
-/* Decreases the numer of lockers of a script and unloads it if that number reaches zero
-** Parameters: (EngineState *) s: The state to operate on
-** (int) script_nr: The script number that is requestet to be unloaded
-** Returns : (void)
-** This function will recursively unload scripts containing its superclasses, if those
-** aren't locked by other scripts as well.
-*/
-
+/**
+ * Initializes an SCI game
+ * This function must be run before script_run() is executed. Graphics data
+ * is initialized iff s->gfx_state != NULL.
+ * @param[in] s The state to operate on
+ * @return 0 on success, 1 if an error occured.
+ */
int game_init(EngineState *s);
-/* Initializes an SCI game
-** Parameters: (EngineState *) s: The state to operate on
-** Returns : (int): 0 on success, 1 if an error occured.
-** This function must be run before script_run() is executed.
-** Graphics data is initialized iff s->gfx_state != NULL.
-*/
+/**
+ * Initializes the graphics part of an SCI game
+ * This function may only be called if game_init() did not initialize
+ * the graphics data.
+ * @param[in] s The state to initialize the graphics in
+ * @return 0 on success, 1 if an error occured
+ */
int game_init_graphics(EngineState *s);
-/* Initializes the graphics part of an SCI game
-** Parameters: (EngineState *) s: The state to initialize the graphics in
-** Returns : (int) 0 on success, 1 if an error occured
-** This function may only be called if game_init() did not initialize
-** the graphics data.
-*/
+/**
+ * Initializes the sound part of an SCI game
+ * This function may only be called if game_init() did not initialize
+ * the sound data.
+ * @param[in] s The state to initialize the sound in
+ * @param[in] sound_flags Flags to pass to the sound subsystem
+ * @return 0 on success, 1 if an error occured
+ */
int game_init_sound(EngineState *s, int sound_flags);
-/* Initializes the sound part of an SCI game
-** Parameters: (EngineState *) s: The state to initialize the sound in
-** (int) sound_flags: Flags to pass to the sound subsystem
-** Returns : (int) 0 on success, 1 if an error occured
-** This function may only be called if game_init() did not initialize
-** the graphics data.
-*/
-
+/**
+ * Runs an SCI game
+ * This is the main function for SCI games. It takes a valid state, loads
+ * script 0 to it, finds the game object, allocates a stack, and runs the
+ * init method of the game object. In layman's terms, this runs an SCI game.
+ * Note that, EngineState *s may be changed during the game, e.g. if a game
+ * state is restored.
+ * @param[in] s Pointer to the pointer of the state to operate on
+ * @return 0 on success, 1 if an error occured.
+ */
int game_run(EngineState **s);
-/* Runs an SCI game
-** Parameters: (EngineState **) s: Pointer to the pointer of the state to operate on
-** Returns : (int): 0 on success, 1 if an error occured.
-** This is the main function for SCI games. It takes a valid state, loads script 0 to it,
-** finds the game object, allocates a stack, and runs the init method of the game object.
-** In layman's terms, this runs an SCI game.
-** By the way, *s may be changed during the game, e.g. if a game state is restored.
-*/
+/**
+ * Restores an SCI game state and runs the game
+ * This restores a savegame; otherwise, it behaves just like game_run().
+ * @param[in] s Pointer to the pointer of the state to
+ * operate on
+ * @param[in] savegame_name Name of the savegame to restore
+ * @return 0 on success, 1 if an error occured.
+ */
int game_restore(EngineState **s, char *savegame_name);
-/* Restores an SCI game state and runs the game
-** Parameters: (EngineState **) s: Pointer to the pointer of the state to operate on
-** (char *) savegame_name: Name of the savegame to restore
-** Returns : (int): 0 on success, 1 if an error occured.
-** This restores a savegame; otherwise, it behaves just like game_run().
-*/
+/**
+ * Uninitializes an initialized SCI game
+ * This function should be run after each script_run() call.
+ * @param[in] s The state to operate on
+ * @return 0 on success, 1 if an error occured.
+ */
int game_exit(EngineState *s);
-/* Uninitializes an initialized SCI game
-** Parameters: (EngineState *) s: The state to operate on
-** Returns : (int): 0 on success, 1 if an error occured.
-** This function should be run after each script_run() call.
-*/
+/**
+ * Instructs the virtual machine to abort
+ */
void quit_vm();
-/* Instructs the virtual machine to abort
-** Paramteres: (void)
-** Returns : (void)
-*/
+/**
+ * Allocates "kernel" memory and returns a handle suitable to be passed on
+ * to SCI scripts
+ * @param[in] s Pointer to the EngineState to operate on
+ * @param[in] type A free-form type description string (static)
+ * @param[in] space The space to allocate
+ * @return The handle
+ */
reg_t kalloc(EngineState *s, const char *type, int space);
-/* Allocates "kernel" memory and returns a handle suitable to be passed on to SCI scripts
-** Parameters: (EngineState *) s: Pointer to the EngineState to operate on
-** (const char *) type: A free-form type description string (static)
-** (int) space: The space to allocate
-** Returns : (reg_t) The handle
-*/
+/**
+ * Returns a pointer to "kernel" memory based on the handle
+ * @param[in] s Pointer to the EngineState to operate on
+ * @param[in] handle The handle to use
+ * @return A pointer to the allocated memory
+ */
byte *kmem(EngineState *s, reg_t handle);
-/* Returns a pointer to "kernel" memory based on the handle
-** Parameters: (EngineState *) s: Pointer to the EngineState to operate on
-** (reg_t) handle: The handle to use
-** Returns : (byte *) A pointer to the allocated memory
-*/
-
+/**
+ * Frees all "kernel" memory associated with a handle
+ * @param[in] s Pointer to the EngineState to operate on
+ * @param[in] handle The handle to free
+ * @return 0 on success, 1 otherwise
+ */
int kfree(EngineState *s, reg_t handle);
-/* Frees all "kernel" memory associated with a handle
-** Parameters: (EngineState *) s: Pointer to the EngineState to operate on
-** (reg_t) handle: The handle to free
-** Returns : (int) 0 on success, 1 otherwise
-*/
+/**
+ * Determines the name of an object
+ * @param[in] s Pointer to the EngineState to operate on
+ * @param[in] pos Location of the object whose name we want to inspect
+ * @return A name for that object, or a string describing an error
+ * that occured while looking it up. The string is stored
+ * in a static buffer and need not be freed (neither may
+ * it be modified).
+ */
const char *obj_get_name(EngineState *s, reg_t pos);
-/* Determines the name of an object
-** Parameters: (EngineState *) s: Pointer to the EngineState to operate on
-** (reg_t) pos: Location of the object whose name we want to
-** inspect
-** Returns : (const char *) A name for that object, or a string describing
-** an error that occured while looking it up
-** The string is stored in a static buffer and need not be freed (neither
-** may it be modified).
-*/
+/**
+ * Retrieves an object from the specified location
+ * @param[in] s Pointer to the EngineState to operate on
+ * @param[in] offset The object's offset
+ * @return The object in question, or NULL if there is none
+ */
Object *obj_get(EngineState *s, reg_t offset);
-/* Retrieves an object from the specified location
-** Parameters: (EngineState *) s: Pointer to the EngineState to operate on
-** (reg_t) offset: The object's offset
-** Returns : (Object *) The object in question, or NULL if there is none
-*/
+/**
+ * Shrink execution stack to size.
+ * Contains an assert it is not already smaller.
+ */
void shrink_execution_stack(EngineState *s, uint size);
-/* Shrink execution stack to size.
-** Contains an assert it is not already smaller.
-*/
} // End of namespace Sci
diff --git a/engines/sci/gfx/font.h b/engines/sci/gfx/font.h
index 935414f550..fe0d81d135 100644
--- a/engines/sci/gfx/font.h
+++ b/engines/sci/gfx/font.h
@@ -30,6 +30,8 @@
namespace Sci {
+/** @name Font operations and stuctures */
+/** @{ */
struct TextFragment {
const char *offset;
@@ -39,90 +41,109 @@ struct TextFragment {
TextFragment(const char *o) : offset(o), length(0) {}
};
-
-struct gfx_bitmap_font_t { /* gfx_bitmap_font_t: Bitmap font information */
- int ID; /* Unique resource ID */
-
- int chars_nr; /* Numer of available characters */
-
- int *widths; /* chars_nr character widths, in pixels */
-
- int row_size; /* Byte size of each pixel row. For unscaled fonts, this is
- ** always 1, 2, or 4. Otherwise, it's a multiple of 4.
- */
-
- int line_height; /* Height of each text line (usually identical to height) */
- int height; /* Height for all characters, in pixel rows */
- int char_size; /* Amount of memory occupied by one character in data */
-
- byte *data; /* Font data, consisting of 'chars_nr' entries of 'height' rows
- ** of 'row_size' bytes. For each character ch, its first byte
- ** (the topmost row) is located at (data + (charsize * ch)), and
- ** its pixel width is widths[ch], provided that (ch < chars_nr).
- */
-
+/**
+ * Bitmap font information.
+ */
+struct gfx_bitmap_font_t {
+ int ID; /**< Unique resource ID */
+ int chars_nr; /**< Numer of available characters */
+ int *widths; /**< chars_nr character widths, in pixels */
+ int row_size; /**
+ * Byte size of each pixel row. For unscaled fonts,
+ * this is always 1, 2, or 4. Otherwise, it's a
+ * multiple of 4.
+ */
+ int line_height; /**
+ * Height of each text line (usually identical to
+ * height)
+ */
+ int height; /**< Height for all characters, in pixel rows */
+ int char_size; /**
+ * Amount of memory occupied by one character
+ * in data
+ */
+ byte *data; /**
+ * Font data, consisting of 'chars_nr' entries
+ * of 'height' rows of 'row_size' bytes. For each
+ * character ch, its first byte (the topmost row)
+ * is located at (data + (charsize * ch)), and its
+ * pixel width is widths[ch], provided that
+ * (ch < chars_nr).
+ */
};
-/*******************/
-/* Font operations */
-/*******************/
-
-/* SCI0, SCI01 and SCI1 all use the same font format. */
+/**
+ * Font handling flags.
+ *
+ * SCI0, SCI01 and SCI1 all use the same font format.
+ */
enum fontFlags {
- kFontCountWhitespace = 1 << 0, // In SQ3, whitespace is included in text size
- kFontNoNewlines = 1 << 1, // Don't treat newline characters
- kFontIgnoreLF = 1 << 2 // Interpret CR LF sequences as a single newline, rather than two
+ kFontCountWhitespace = 1 << 0, //!< In SQ3, whitespace is included in text size
+ kFontNoNewlines = 1 << 1, //!< Don't treat newline characters
+ kFontIgnoreLF = 1 << 2 //!< Interpret CR LF sequences as a single newline, rather than two
};
+/**
+ * Generates a bitmap font data structure from a resource.
+ *
+ * @param[in] id Resource ID of the resulting font
+ * @param[in] resource Pointer to the resource data
+ * @param[in] size Size of the resource block
+ * @return The resulting font structure, or NULL on error
+ */
gfx_bitmap_font_t *gfxr_read_font(int id, byte *resource, int size);
-/* Generates a bitmap font data structure from a resource
-** Parameters: (int) id: Resource ID of the resulting font
-** (byte *) resource: Pointer to the resource data
-** (int) size: Size of the resource block
-** Returns : (gfx_bitmap_font_t *) The resulting font structure, or
-** NULL on error
-*/
+/**
+ * Frees a previously allocated font structure.
+ *
+ * @param font The font to free
+ */
void gfxr_free_font(gfx_bitmap_font_t *font);
-/* Frees a previously allocated font structure
-** Parameters: (gfx_bitmap_font_t *) font: The font to free
-** Returns : (void)
-*/
+/**
+ * Calculates the size that would be occupied by drawing a specified
+ * text.
+ *
+ * This function assumes 320x200 mode.
+ *
+ * @param[in] font The font to calculate with
+ * @param[in] max_width Maximum pixel width allowed for the output
+ * @param[in] text The text to calculate for
+ * @param[in] flags Any text formatting flags
+ * @param[out] fragments A newly allocated array of text_fragments,
+ * containing the start and size of each string
+ * segment.
+ * @param[out] width The resulting width
+ * @param[out] height The resulting height
+ * @param[out] line_height Pixel height of a single line of text
+ * @param[out] last_offset Pixel offset after the last drawn line
+ * @return true if successful, false otherwise
+ */
bool gfxr_font_calculate_size(Common::Array<TextFragment> &fragments,
gfx_bitmap_font_t *font, int max_width, const char *text,
int *width, int *height, int *line_height, int *last_offset, int flags);
-/* Calculates the size that would be occupied by drawing a specified text
-** Parameters: (gfx_bitmap_font_t *) font: The font to calculate with
-** (int) max_width: Maximum pixel width allowed for the output
-** (const char *) text: The text to calculate for
-** (int) flags: Any text formatting flags
-** Returns : (text_fragment *) a newly allocated array of text_fragments,
-** containing the start and size of each string
-** segment
-** (int) *width: The resulting width
-** (int) *height: The resulting height
-** (int) *line_height: Pixel height of a single line of text
-** (int) *last_offset: Pixel offset after the last drawn line
-** This function assumes 320x200 mode.
-*/
-
-gfx_pixmap_t *gfxr_draw_font(gfx_bitmap_font_t *font, const char *text, int characters,
- PaletteEntry *fg0, PaletteEntry *fg1, PaletteEntry *bg);
-/* Draws text in a specific font to a pixmap
-** Parameters: (gfx_bitmap_font_t *) font: The font to use for drawing
-** (char *) text: The start of the text to draw
-** (int) characters: The number of characters to draw
-** (gfx_pixmap_color_t *) fg0: The first foreground color
-** (gfx_pixmap_color_t *) fg1: The second foreground color
-** (gfx_pixmap_color_t *) bg: The background color
-** Returns : (gfx_pixmap_t *) The result pixmap, or NULL on error
-** The results are written to the pixmap's index buffer. Contents of the
-** foreground and background fields are copied into a newly allocated font
-** structure, so that the pixmap may be translated directly.
-** If any of the colors is null, it will be assumed to be transparent.
-** In color index mode, the specified colors have to be preallocated.
-*/
+
+/**
+ * Draws text in a specific font to a pixmap.
+ *
+ * The results are written to the pixmap's index buffer. Contents of the
+ * foreground and background fields are copied into a newly allocated font
+ * structure, so that the pixmap may be translated directly. If any of the
+ * colors is null, it will be assumed to be transparent.
+ * In color index mode, the specified colors have to be preallocated.
+ *
+ * @param[in] font The font to use for drawing
+ * @param[in] text The start of the text to draw
+ * @param[in] characters The number of characters to draw
+ * @param[in] fg0 The first foreground color
+ * @param[in] fg1 The second foreground color
+ * @param[in] bg The background color
+ * @return The result pixmap, or NULL on error
+ */
+gfx_pixmap_t *gfxr_draw_font(gfx_bitmap_font_t *font, const char *text,
+ int characters, PaletteEntry *fg0, PaletteEntry *fg1,
+ PaletteEntry *bg);
+/** @} */
} // End of namespace Sci
diff --git a/engines/sci/gfx/gfx_driver.h b/engines/sci/gfx/gfx_driver.h
index b74511de77..f7cbd0b6c2 100644
--- a/engines/sci/gfx/gfx_driver.h
+++ b/engines/sci/gfx/gfx_driver.h
@@ -38,171 +38,202 @@ enum gfx_buffer_t {
};
-/* Principial graphics driver architecture
-** ---------------------------------------
-**
-** All graphics drivers must provide
-** - One visual front buffer (the actually visible thing)
-** - Two dynamic back buffers:
-** + visual
-** + priority
-** - Two static buffers (containing the background image and picviews):
-** + visual
-** + priority
-**
-** The control buffer is handled outside the graphics driver architecture.
-** Graphics are drawn by first setting the static buffers, then updating
-** the back buffers (from the static buffers), adding all picviews and other
-** widgets, and finally updating the front buffer.
-**
-** All coordinates refer to the scaled coordinate system.
-** Invalid parameters should produce an error message.
-** Support for some valid parameter values is optional (like different line
-** modes). If an unsupported but valid parameter is specified, the function
-** must use a reasonable default value.
-*/
-
+/**
+ * Graphics driver.
+ *
+ * Principial graphics driver architecture:
+ *
+ * All graphics drivers must provide
+ * - One visual front buffer (the actually visible thing)
+ * - Two dynamic back buffers:
+ * - visual
+ * - priority
+ * - Two static buffers (containing the background image and picviews):
+ * - visual
+ * - priority
+ *
+ * The control buffer is handled outside the graphics driver architecture.
+ * Graphics are drawn by first setting the static buffers, then updating
+ * the back buffers (from the static buffers), adding all picviews and other
+ * widgets, and finally updating the front buffer.
+ *
+ * All coordinates refer to the scaled coordinate system.
+ * Invalid parameters should produce an error message.
+ * Support for some valid parameter values is optional (like different line
+ * modes). If an unsupported but valid parameter is specified, the function
+ * must use a reasonable default value.
+ */
class GfxDriver {
public:
- /*** Initialization ***/
-
+ /** @name Initialization */
+ /** @{ */
+ /**
+ * Attempts to initialize a specific graphics mode.
+ *
+ * The scaling factors apply to the standard SCI resolution of 320x200
+ * pixels and is used for internal representation of graphical data.
+ * The physical resolution set by the graphics driver may be different
+ * for practical reasons.
+ * Must also set _mode, preferably with the gfx_new_mode() function
+ * specified in gfx_tools.h.
+ *
+ * @param[in] xfact Horizontal scaling factor
+ * @param[in] yfact Vertical scaling factor
+ * @param[in] bytespp Any of GFX_COLOR_MODE_*. GFX_COLOR_MODE_INDEX
+ * implies color index mode.
+ * @return GFX_OK on success, GFX_ERROR if the mode could
+ * not be set, or GFX_FATAL if the graphics target
+ * is unuseable.
+ */
GfxDriver(int xfact, int yfact, int bytespp);
- /* Attempts to initialize a specific graphics mode
- ** Parameters: (int x int) xres, yres: Horizontal and vertical scaling
- ** factors
- ** (int) bytespp: Any of GFX_COLOR_MODE_*. GFX_COLOR_MODE_INDEX
- ** implies color index mode.
- ** Returns : (int) GFX_OK on success, GFX_ERROR if the mode could not be
- ** set, or GFX_FATAL if the graphics target is unuseable.
- ** The scaling factors apply to the standard SCI resolution of 320x200 pixels
- ** and is used for internal representation of graphical data. The physical
- ** resolution set by the graphics driver may be different for practical
- ** reasons.
- ** Must also set _mode, preferably with the gfx_new_mode() function
- ** specified in gfx_tools.h.
- */
+ /**
+ * Uninitializes the current graphics mode.
+ *
+ * This function frees all memory allocated by the graphics driver,
+ * including mode and palette information, uninstalls all console
+ * commands introduced by preceeding init() or init_specific()
+ * commands, and does any clean-up work (like closing visuals or
+ * returning to text mode) required by the graphics infrastructure used.
+ */
~GfxDriver();
- /* Uninitializes the current graphics mode
- ** This function frees all memory allocated by the graphics driver,
- ** including mode and palette information, uninstalls all console commands
- ** introduced by preceeding init() or init_specific() commands, and does any
- ** clean-up work (like closing visuals or returning to text mode) required by
- ** the graphics infrastructure used.
- */
-
-
- /*** Drawing operations ***/
-
+ /** @} */
+
+ /** @name Drawing operations */
+ /** @{ */
+
+ /**
+ * Draws a single line to the back buffer.
+ *
+ * Note that color.priority is relevant and must be drawn if
+ * (color.mask & GFX_MASK_PRIORITY). Support for line modes other than
+ * GFX_LINE_MODE_FAST is optional. For non-fine lines, the coordinates
+ * provided describe the upper left corner of the pixels of the line
+ * to draw.line_style support is optional, if
+ * GFX_CAPABILITY_STIPPLED_LINES is not set.
+ *
+ * @param[in] start Starting point of the line to draw
+ * @param[in] end End point of the line to draw
+ * @param[in] color The color to draw with
+ * @param[in] line_mode Any of the line modes
+ * @param[in] line_style Any of the line styles
+ * @return GFX_OK or GFX_FATAL
+ */
int drawLine(Common::Point start, Common::Point end, gfx_color_t color,
gfx_line_mode_t line_mode, gfx_line_style_t line_style);
- /* Draws a single line to the back buffer.
- ** Parameters: (Common::Point) start: Starting point of the line to draw
- ** (Common::Point) end: End point of the line to draw
- ** (gfx_color_t *) color: The color to draw with
- ** (int) line_mode: Any of the line modes
- ** (int) line_style: Any of the line styles
- ** Returns : (int) GFX_OK or GFX_FATAL
- ** Note that color.priority is relevant and must be drawn if
- ** (color.mask & GFX_MASK_PRIORITY).
- ** Support for line modes other than GFX_LINE_MODE_FAST is optional.
- ** For non-fine lines, the coordinates provided describe the upper left
- ** corner of the pixels of the line to draw.
- ** line_style support is optional, if GFX_CAPABILITY_STIPPLED_LINES is not
- ** set.
- */
+ /**
+ * Draws a single filled and possibly shaded rectangle to the back
+ * buffer.
+ *
+ * Note that color.priority is relevant and must be drawn if
+ * (color.mask & GFX_MASK_PRIORITY). color2 is relevant only if
+ * shade_mode is not GFX_SHADE_FLAT. Support for shade modes other
+ * than GFX_SHADE_FLAT is optional.
+ *
+ * @param[in] rect The rectangle to draw
+ * @param[in] color1 The first color to draw with
+ * @param[in] color2 The second color to draw with
+ * @param[in] shade_mode Any of GFX_SHADE_*.
+ * @return GFX_OK or GFX_FATAL
+ */
int drawFilledRect(rect_t rect, gfx_color_t color1, gfx_color_t color2,
gfx_rectangle_fill_t shade_mode);
- /* Draws a single filled and possibly shaded rectangle to the back buffer.
- ** Parameters: (rect_t *) rect: The rectangle to draw
- ** (gfx_color_t *) color1, color2: The colors to draw with
- ** (int) shade_mode: Any of GFX_SHADE_*.
- ** Returns : (int) GFX_OK or GFX_FATAL
- ** Note that color.priority is relevant and must be drawn if
- ** (color.mask & GFX_MASK_PRIORITY).
- ** color2 is relevant only if shade_mode is not GFX_SHADE_FLAT.
- ** Support for shade modes other than GFX_SHADE_FLAT is optional.
- */
-
- /*** Pixmap operations ***/
-
+ /** @} */
+
+ /** @name Pixmap operations */
+ /** @{ */
+
+ /**
+ * Draws part of a pixmap to the static or back buffer.
+ *
+ * @param[in] pxm The pixmap to draw
+ * @param[in] priority The priority to draw with, or GFX_NO_PRIORITY
+ * to draw on top of everything without setting the
+ * priority back buffer.
+ * @param[in] src The pixmap-relative source rectangle
+ * @param[in] dest The destination rectangle
+ * @param[in] buffer One of GFX_BUFFER_STATIC and GFX_BUFFER_BACK
+ * @return GFX_OK or GFX_FATAL, or GFX_ERROR if pxm was
+ * not (but should have been) registered.
+ */
int drawPixmap(gfx_pixmap_t *pxm, int priority,
rect_t src, rect_t dest, gfx_buffer_t buffer);
- /* Draws part of a pixmap to the static or back buffer
- ** Parameters: (gfx_pixmap_t *) pxm: The pixmap to draw
- ** (int) priority: The priority to draw with, or GFX_NO_PRIORITY
- ** to draw on top of everything without setting the
- ** priority back buffer
- ** (rect_t) src: The pixmap-relative source rectangle
- ** (rect_t) dest: The destination rectangle
- ** (int) buffer: One of GFX_BUFFER_STATIC and GFX_BUFFER_BACK
- ** Returns : (int) GFX_OK or GFX_FATAL, or GFX_ERROR if pxm was not
- ** (but should have been) registered.
- */
+ /**
+ * Grabs an image from the visual or priority back buffer.
+ *
+ * This function is now mandatory.
+ *
+ * @param[in] src The rectangle to grab
+ * @param[in] pxm The pixmap structure the data is to be written to
+ * @param[in] map GFX_MASK_VISUAL or GFX_MASK_PRIORITY
+ * @return GFX_OK, GFX_FATAL, or GFX_ERROR for invalid map
+ * values pxm may be assumed to be empty and
+ * pre-allocated with an appropriate memory size.
+ */
int grabPixmap(rect_t src, gfx_pixmap_t *pxm, gfx_map_mask_t map);
- /* Grabs an image from the visual or priority back buffer
- ** Parameters: (rect_t) src: The rectangle to grab
- ** (gfx_pixmap_t *) pxm: The pixmap structure the data is to
- ** be written to
- ** (int) map: GFX_MASK_VISUAL or GFX_MASK_PRIORITY
- ** Returns : (int) GFX_OK, GFX_FATAL, or GFX_ERROR for invalid map values
- ** pxm may be assumed to be empty and pre-allocated with an appropriate
- ** memory size.
- ** This function is now mandatory.
- */
-
-
- /*** Buffer operations ***/
-
+ /** @} */
+
+ /** @name Buffer operations */
+ /** @{ */
+
+ /**
+ * Updates the front buffer or the back buffers.
+ *
+ * This function updates either the visual front buffer, or the two
+ * back buffers, by copying the specified source region to the
+ * destination region.
+ * For heuristical reasons, it may be assumed that the x and y fields
+ * of src and dest will be identical in /most/ cases.If they aren't,
+ * the priority map will not be required to be copied.
+ *
+ * @param[in] src: Source rectangle
+ * @param[in] dest: Destination point
+ * @param[in] buffer: One of GFX_BUFFER_FRONT or GFX_BUFFER_BACK
+ * @return GFX_OK, GFX_ERROR or GFX_FATAL
+ */
int update(rect_t src, Common::Point dest, gfx_buffer_t buffer);
- /* Updates the front buffer or the back buffers
- ** Parameters: (rect_t) src: Source rectangle
- ** (Common::Point) dest: Destination point
- ** (int) buffer: One of GFX_BUFFER_FRONT or GFX_BUFFER_BACK
- ** Returns : (int) GFX_OK, GFX_ERROR or GFX_FATAL
- ** This function updates either the visual front buffer, or the two back
- ** buffers, by copying the specified source region to the destination
- ** region.
- ** For heuristical reasons, it may be assumed that the x and y fields of
- ** src and dest will be identical in /most/ cases.
- ** If they aren't, the priority map will not be required to be copied.
- */
+ /**
+ * Sets the contents of the static visual and priority buffers.
+ *
+ * pic and priority may be modified or written to freely. They may also
+ * be used as the actual static buffers, since they are not freed and
+ * reallocated between calls to set_static_buffer() and update(),
+ * unless exit() was called in between.
+ * Note that later version of the driver interface may disallow
+ * modifying pic and priority. pic and priority are always scaled to
+ * the appropriate resolution
+ *
+ * @param[in] pic The image defining the new content of the
+ * visual back buffer
+ * @param[in] priority The priority map containing the new content of
+ * the priority back buffer in the index buffer
+ * @return GFX_OK or GFX_FATAL
+ */
int setStaticBuffer(gfx_pixmap_t *pic, gfx_pixmap_t *priority);
- /* Sets the contents of the static visual and priority buffers
- ** Parameters: (gfx_pixmap_t *) pic: The image defining the new content
- ** of the visual back buffer
- ** (gfx_pixmap_t *) priority: The priority map containing
- ** the new content of the priority back buffer
- ** in the index buffer
- ** Returns : (int) GFX_OK or GFX_FATAL
- ** pic and priority may be modified or written to freely. They may also be
- ** used as the actual static buffers, since they are not freed and re-
- ** allocated between calls to set_static_buffer() and update(), unless
- ** exit() was called in between.
- ** Note that later version of the driver interface may disallow modifying
- ** pic and priority.
- ** pic and priority are always scaled to the appropriate resolution
- */
-
-
- /*** Mouse pointer operations ***/
-
+ /** @} */
+
+ /** @name Mouse pointer operations */
+ /** @{ */
+
+ /**
+ * Sets a new mouse pointer.
+ *
+ * If pointer is not NULL, it will have been scaled to the appropriate
+ * size and registered as a pixmap (if neccessary) beforehand. If this
+ * function is called for a target that supports only two-color
+ * pointers, the image is a color index image, where only color index
+ * values 0, 1, and GFX_COLOR_INDEX_TRANSPARENT are used.
+ *
+ * @param[in] pointer The pointer to set, or NULL to set no pointer.
+ * @param[in] hotspot The coordinates of the hotspot, or NULL to set
+ * no pointer.
+ * @return GFX_OK or GFX_FATAL
+ */
int setPointer(gfx_pixmap_t *pointer, Common::Point *hotspot);
- /* Sets a new mouse pointer.
- ** Parameters: (gfx_pixmap_t *) pointer: The pointer to set, or NULL to set
- ** no pointer
- ** (Common::Point *) hotspot: The coordinates of the hotspot,
- ** or NULL to set no pointer
- ** Returns : (int) GFX_OK or GFX_FATAL
- ** If pointer is not NULL, it will have been scaled to the appropriate
- ** size and registered as a pixmap (if neccessary) beforehand.
- ** If this function is called for a target that supports only two-color
- ** pointers, the image is a color index image, where only color index values
- ** 0, 1, and GFX_COLOR_INDEX_TRANSPARENT are used.
- */
+ /** @} */
gfx_mode_t *getMode() { return _mode; }
byte *getVisual0() { return _visual[0]; }
@@ -212,7 +243,7 @@ private:
gfx_pixmap_t *_priority[2];
byte *_visual[2];
- gfx_mode_t *_mode; /* Currently active mode, NULL if no mode is active */
+ gfx_mode_t *_mode; /**< Currently active mode, NULL if no mode is active */
};
} // End of namespace Sci
diff --git a/engines/sci/gfx/gfx_gui.cpp b/engines/sci/gfx/gfx_gui.cpp
index f73a13d6dd..fb05c0fe29 100644
--- a/engines/sci/gfx/gfx_gui.cpp
+++ b/engines/sci/gfx/gfx_gui.cpp
@@ -266,7 +266,7 @@ static rect_t _move_and_extend_rect(rect_t rect, Common::Point point, int yplus)
return gfx_rect(rect.x + point.x, rect.y + point.y, rect.width + 1, rect.height + yplus);
}
-GfxList *_sciw_add_text_to_list(GfxList *list, GfxPort *port, rect_t zone, char *text,
+GfxList *_sciw_add_text_to_list(GfxList *list, GfxPort *port, rect_t zone, const char *text,
int font, gfx_alignment_t align, char framed, char inverse, int flags, char gray_text) {
gfx_color_t *color1, *color2, *bgcolor;
@@ -294,7 +294,7 @@ GfxList *_sciw_add_text_to_list(GfxList *list, GfxPort *port, rect_t zone, char
return list;
}
-GfxList *sciw_new_button_control(GfxPort *port, reg_t ID, rect_t zone, char *text, int font, char selected, char inverse, char grayed_out) {
+GfxList *sciw_new_button_control(GfxPort *port, reg_t ID, rect_t zone, const char *text, int font, char selected, char inverse, char grayed_out) {
gfx_color_t *frame_col = (inverse) ? &(port->_bgcolor) : &(port->_color);
GfxList *list;
@@ -332,7 +332,7 @@ GfxList *sciw_new_button_control(GfxPort *port, reg_t ID, rect_t zone, char *tex
return list;
}
-GfxList *sciw_new_text_control(GfxPort *port, reg_t ID, rect_t zone, char *text, int font,
+GfxList *sciw_new_text_control(GfxPort *port, reg_t ID, rect_t zone, const char *text, int font,
gfx_alignment_t align, char framed, char inverse) {
GfxList *list = gfxw_new_list(_move_and_extend_rect(zone, Common::Point(port->zone.x, port->zone.y), 2), 0);
@@ -344,7 +344,7 @@ GfxList *sciw_new_text_control(GfxPort *port, reg_t ID, rect_t zone, char *text,
return _sciw_add_text_to_list(list, port, zone, text, font, align, framed, inverse, 0, port->gray_text);
}
-GfxList *sciw_new_edit_control(GfxPort *port, reg_t ID, rect_t zone, char *text, int font, unsigned int cursor,
+GfxList *sciw_new_edit_control(GfxPort *port, reg_t ID, rect_t zone, const char *text, int font, unsigned int cursor,
char inverse) {
GfxText *text_handle;
@@ -440,7 +440,7 @@ GfxList *sciw_new_icon_control(GfxPort *port, reg_t ID, rect_t zone, int view, i
return list;
}
-GfxList *sciw_new_list_control(GfxPort *port, reg_t ID, rect_t zone, int font_nr, char **entries_list,
+GfxList *sciw_new_list_control(GfxPort *port, reg_t ID, rect_t zone, int font_nr, const char **entries_list,
int entries_nr, int list_top, int selection, char inverse) {
GfxList *list;
diff --git a/engines/sci/gfx/gfx_gui.h b/engines/sci/gfx/gfx_gui.h
index e712d30660..68342aa0c0 100644
--- a/engines/sci/gfx/gfx_gui.h
+++ b/engines/sci/gfx/gfx_gui.h
@@ -23,8 +23,6 @@
*
*/
-/* SCI-specific widget handling */
-
#ifndef SCI_INCLUDE_SCI_WIDGETS_H
#define SCI_INCLUDE_SCI_WIDGETS_H
@@ -34,152 +32,196 @@ namespace Sci {
class Menu;
-// The following flags are applicable to windows in SCI0
+/* SCI-specific widget handling */
+
+/**
+ * Flags for windows in SCI0.
+ */
enum windowFlags {
- kWindowTransparent = 0x01, // 0000 0001
- kWindowNoFrame = 0x02, // 0000 0010 - a window without a frame
- // Add title bar to window (10 pixels high, framed, text is centered and written in white on dark gray)
- kWindowTitle = 0x04, // 0000 0100
- // bits 3-6 are unused
- kWindowDontDraw = 0x80, // 1000 0000 - don't draw anything
- kWindowNoDropShadow = 0x1000000, // 0001 0000 0000 0000 0000 0000 0000 (not in SCI)
+ kWindowTransparent = 0x01, //!< 0000 0001
+ kWindowNoFrame = 0x02, //!< 0000 0010 - a window without a frame
+ kWindowTitle = 0x04, /**
+ * 0000 0100 - Add title bar to
+ * window (10 pixels high, framed,
+ * text is centered and written in
+ * white on dark gray), bits 3-6
+ * are unused
+ */
+ kWindowDontDraw = 0x80, //!< 1000 0000 - don't draw anything
+ kWindowNoDropShadow = 0x1000000, //!< 0001 0000 0000 0000 0000 0000 0000 (not in SCI)
kWindowAutoRestore = 0x2000000
};
+/** Button and frame control flags. */
enum controlStateFlags {
- kControlStateEnabled = 0x0001, // 0001 - enabled buttons (used by the interpreter)
- kControlStateDisabled = 0x0004, // 0010 - grayed out buttons (used by the interpreter)
- kControlStateFramed = 0x0008, // 1000 - widgets surrounded by a frame (used by the interpreter)
- kControlStateDitherFramed = 0x1000 // 0001 0000 0000 0000 - widgets surrounded by a dithered frame (used in kgraphics)
+ kControlStateEnabled = 0x0001, //!< 0001 - enabled buttons (used by the interpreter)
+ kControlStateDisabled = 0x0004, //!< 0010 - grayed out buttons (used by the interpreter)
+ kControlStateFramed = 0x0008, //!< 1000 - widgets surrounded by a frame (used by the interpreter)
+ kControlStateDitherFramed = 0x1000 //!< 0001 0000 0000 0000 - widgets surrounded by a dithered frame (used in kgraphics)
};
-void sciw_set_status_bar(EngineState *s, GfxPort *status_bar, const Common::String &text, int fgcolor, int bgcolor);
-/* Sets the contents of a port used as status bar
-** Parmeters: (EngineState *) s: The affected game state
-** (GfxPort *) status_bar: The status bar port
-** (const char *) text: The text to draw
-** Returns : (void)
-*/
-
-GfxPort *sciw_new_window(EngineState *s, rect_t area, int font, gfx_color_t color, gfx_color_t bgcolor,
- int title_font, gfx_color_t title_color, gfx_color_t title_bg_color,
- const char *title, int flags);
-/* Creates a new SCI style window
-** Parameters: (EngineState *) s: The affected game state
-** (rect_t) area: The screen area to frame (not including a potential window title)
-** (int) font: Default font number to use
-** (gfx_color_t) color: The foreground color to use for drawing
-** (gfx_color_t) bgcolor: The background color to use
-** (int) title_font: The font to use for the title bar (if any)
-** (gfx_color_t) title_color: Color to use for the title bar text
-** (gfx_color_t) title_bg_color: Color to use for the title bar background
-** (const char *) title: The text to write into the title bar
-** (int) flags: Any ORred combination of window flags
-** Returns : (GfxPort *) A newly allocated port with the requested characteristics
-*/
-
-/*---------------------*/
-/*** Control widgets ***/
-/*---------------------*/
-
-GfxList *sciw_new_button_control(GfxPort *port, reg_t ID, rect_t zone, char *text, int font, char selected, char inverse, char gray);
-/* Creates a new button control list
-** Parameters: (GfxPort *) port: The port containing the color values to use for the
-** button (the button is /not/ appended to the port there)
-** (reg_t) ID: Button's ID
-** (rect_t) zone: The area occupied by the button
-** (char *) text: The text to write into the button
-** (int) font: The font to use for the button
-** (char) selected: Whether the button should be marked as being selected by the keyboard focus
-** (char) inverse: Whether to inverse the color scheme
-** (char) gray: Whether the button should be grayed out
-** Returns : (GfxList *) The button
-*/
-
-GfxList *sciw_new_text_control(GfxPort *port, reg_t ID, rect_t zone, char *text, int font,
- gfx_alignment_t align, char frame, char inverse);
-/* Creates a new text control list
-** Parameters: (GfxPort *) port: The port containing the color values to use
-** (reg_t) ID: Text widget ID
-** (rect_t) zone: Area occupied by the text
-** (char *) text: The text
-** (int) font: The font the text is to be drawn in
-** (gfx_alignment_t) align: Horizontal text alignment to use
-** (char) frame: Whether a dithered frame should surround the text
-** (char) inverse: Whether the text colors should be inversed
-** Returns : (GfxList *) The text control widget list
-*/
-
-GfxList *sciw_new_edit_control(GfxPort *port, reg_t ID, rect_t zone, char *text, int font, unsigned int cursor,
- char inverse);
-/* Creates a new edit control list
-** Parameters: (GfxPort *) port: The port containing the color values to use
-** (reg_t) ID: Text widget ID
-** (rect_t) zone: Area occupied by the text
-** (char *) text: The text
-** (int) font: The font the text is to be drawn in
-** (int) cursor: Cursor position
-** (char) inverse: Whether the edit widget should be reversed
-** Returns : (GfxList *) An appropriate widget list
-*/
-
-GfxList *sciw_new_icon_control(GfxPort *port, reg_t ID, rect_t zone, int view, int loop, int cel,
- char frame, char inverse);
-/* Creates a new icon control list
-** Parameters: (GfxPort *) port: The port containing the color values to use
-** (reg_t) ID: Text widget ID
-** (rect_t) zone: Area occupied by the text
-** (int x int x int) view, loop, cel: The cel to display
-** (char) frame: Whether the widget should be surrounded by a frame
-** (char) lina inverse: Whether colors should be inversed
-** Returns : (GfxList *) An appropriate widget list
-*/
-
-GfxList *sciw_new_list_control(GfxPort *port, reg_t ID, rect_t zone, int font_nr, char **entries_list,
- int entries_nr, int list_top, int selection, char inverse);
-/* Creates a new list control list
-** Parameters: (GfxPort *) port: The port containing the color values to use
-** (int) ID: Text widget ID
-** (rect_t) zone: Area occupied by the text
-** (int) font_nr: number of the font to use
-** (char **) entries_list: List of strings to contain within the list
-** (int) entries_nr: Number of entries in entries_list
-** (int) list_top: First list item that is visible
-** (int) selection: The list item that is selected
-** (char) invserse: The usual meaning
-** Returns : (GfxList *) An appropriate widget list
-*/
-
-/*---------------------*/
-/*** Menubar widgets ***/
-/*---------------------*/
-
-void sciw_set_menubar(EngineState *s, GfxPort *status_bar, Menubar *menubar, int selection);
-/* Draws the menu bar
-** Parameters: (EngineState *) s: The state to operate on
-** (GfxPort *) status_bar: The status bar port to modify
-** (Menubar *) menubar: The menu bar to use
-** (int) selection: Number of the menu to hightlight, or -1 for 'none'
-** Returns : (void)
-*/
-
-GfxPort *sciw_new_menu(EngineState *s, GfxPort *status_bar, Menubar *menubar, int selection);
-/* Creates a menu port
-** Parameters: (EngineState *) s: The state to operate on
-** (GfxPort *) status_bar: The status bar
-** (Menubar *) menubar: The menu bar to use
-** (int) selection: Number of the menu to interpret
-** Returns : (GfxPort *) The result port
-*/
-
-GfxPort *sciw_toggle_item(GfxPort *menu_port, Menu *menu, int selection, bool selected);
-/* Toggle the selection of a menu item from a menu port
-** Parameters: (GfxPort *) menu_port: The port to modify
-** (Menu *) menu: The menu the menu port corresponds to
-** (int) selection: Number of the menu entry to unselect, or -1 to do a NOP
-** (bool) selected: Whether to set the item's state to selected or not
-** Returns : (GfxPort *) The modified menu
-*/
+/**
+ * Sets the contents of a port used as status bar.
+ *
+ * @param[in] s The affected EngineState
+ * @param[in] status_bar The status bar port
+ * @param[in] text The text to draw
+ * @param[in] fgcolor The foreground color
+ * @param[in] bgcolor The background color
+ */
+void sciw_set_status_bar(EngineState *s, GfxPort *status_bar,
+ const Common::String &text, int fgcolor, int bgcolor);
+
+/**
+ * Creates a new SCI style window.
+ *
+ * @param[in] s The affected EngineState
+ * @param[in] area The screen area to frame (not including a
+ * potential window title)
+ * @param[in] font Default font number to use
+ * @param[in] color The foreground color to use for drawing
+ * @param[in] bgcolor The background color to use
+ * @param[in] title_font The font to use for the title bar (if any)
+ * @param[in] title_color Color to use for the title bar text
+ * @param[in] title_bg_color Color to use for the title bar background
+ * @param[in] title The text to write into the title bar
+ * @param[in] flags Any ORred combination of window flags
+ * @return A newly allocated port with the requested characteristics
+ */
+GfxPort *sciw_new_window(EngineState *s, rect_t area, int font,
+ gfx_color_t color, gfx_color_t bgcolor, int title_font,
+ gfx_color_t title_color, gfx_color_t title_bg_color,
+ const char *title, int flags);
+
+
+/** @name Control widgets */
+/** @{ */
+/**
+ * Creates a new button control list.
+ *
+ * @param[in] port The port containing the color values to use for the
+ * button (the button is /not/ appended to the port
+ * there)
+ * @param[in] ID Button's ID
+ * @param[in] zone The area occupied by the button
+ * @param[in] text The text to write into the button
+ * @param[in] font The font to use for the button
+ * @param[in] selected Whether the button should be marked as being
+ * selected by the keyboard focus
+ * @param[in] inverse Whether to inverse the color scheme
+ * @param[in] gray Whether the button should be grayed out
+ * @return The button
+ */
+GfxList *sciw_new_button_control(GfxPort *port, reg_t ID, rect_t zone,
+ const char *text, int font, char selected, char inverse, char gray);
+
+/**
+ * Creates a new text control list.
+ *
+ * @param[in] port The port containing the color values to use
+ * @param[in] ID Text widget ID
+ * @param[in] zone Area occupied by the text
+ * @param[in] text The text
+ * @param[in] font The font the text is to be drawn in
+ * @param[in] align Horizontal text alignment to use
+ * @param[in] frame Whether a dithered frame should surround the text
+ * @param[in] inverse Whether the text colors should be inversed
+ * @return The text control widget list
+ */
+GfxList *sciw_new_text_control(GfxPort *port, reg_t ID, rect_t zone,
+ const char *text, int font, gfx_alignment_t align, char frame,
+ char inverse);
+
+/**
+ * Creates a new edit control list.
+ *
+ * @param[in] port The port containing the color values to use
+ * @param[in] ID Text widget ID
+ * @param[in] zone Area occupied by the text
+ * @param[in] text The text
+ * @param[in] font The font the text is to be drawn in
+ * @param[in] cursor Cursor position
+ * @param[in] inverse Whether the edit widget should be reversed
+ * @return An appropriate widget list
+ */
+GfxList *sciw_new_edit_control(GfxPort *port, reg_t ID, rect_t zone,
+ const char *text, int font, unsigned int cursor, char inverse);
+
+/**
+ * Creates a new icon control list.
+ *
+ * @param[in] port The port containing the color values to use
+ * @param[in] ID Text widget ID
+ * @param[in] zone Area occupied by the text
+ * @param[in] view The view index
+ * @param[in] loop The loop index
+ * @param[in] cel The cel to display
+ * @param[in] frame Whether the widget should be surrounded by a frame
+ * @param[in] inverse Whether colors should be inversed
+ * @return An appropriate widget list
+ */
+GfxList *sciw_new_icon_control(GfxPort *port, reg_t ID, rect_t zone,
+ int view, int loop, int cel, char frame, char inverse);
+
+/**
+ * Creates a new list control list.
+ *
+ * @param[in] port: The port containing the color values to use
+ * @param[in] ID: Text widget ID
+ * @param[in] zone: Area occupied by the text
+ * @param[in] font_nr: Number of the font to use
+ * @param[in] entries_list: List of strings to contain within the list
+ * @param[in] entries_nr: Number of entries in entries_list
+ * @param[in] list_top: First list item that is visible
+ * @param[in] selection: The list item that is selected
+ * @param[in] inverse: The usual meaning
+ * @return An appropriate widget list
+ */
+GfxList *sciw_new_list_control(GfxPort *port, reg_t ID, rect_t zone,
+ int font_nr, const char **entries_list, int entries_nr,
+ int list_top, int selection, char inverse);
+/** @} */
+
+/** @name Menubar widgets */
+/** @{ */
+
+/**
+ * Draws the menu bar.
+ *
+ * @param[in] s: The EngineState to operate on
+ * @param[in] status_bar: The status bar port to modify
+ * @param[in] menubar: The menu bar to use
+ * @param[in] selection: Number of the menu to hightlight, or -1 for
+ * 'none'
+ */
+void sciw_set_menubar(EngineState *s, GfxPort *status_bar, Menubar *menubar,
+ int selection);
+
+/**
+ * Creates a menu port.
+ *
+ * @param[in] s The state to operate on
+ * @param[in] status_bar The status bar
+ * @param[in] menubar The menu bar to use
+ * @param[in] selection Number of the menu to interpret
+ * @return The result port
+ */
+GfxPort *sciw_new_menu(EngineState *s, GfxPort *status_bar,
+ Menubar *menubar, int selection);
+
+/**
+ * Toggle the selection of a menu item from a menu port.
+ *
+ * @param[in] menu_port The port to modify
+ * @param[in] menu The menu the menu port corresponds to
+ * @param[in] selection Number of the menu entry to unselect, or -1 to do
+ * a NOP
+ * @param[in] selected Whether to set the item's state to selected or not
+ * @return The modified menu
+ */
+GfxPort *sciw_toggle_item(GfxPort *menu_port, Menu *menu, int selection,
+ bool selected);
+/** @} */
} // End of namespace Sci
diff --git a/engines/sci/gfx/gfx_options.h b/engines/sci/gfx/gfx_options.h
index 393627a1a2..2e2b853562 100644
--- a/engines/sci/gfx/gfx_options.h
+++ b/engines/sci/gfx/gfx_options.h
@@ -42,20 +42,20 @@
namespace Sci {
-/* Dirty rectangle heuristics: */
-
-/* One: Redraw one rectangle surrounding the dirty area (insert is O(1)) */
-#define GFXOP_DIRTY_FRAMES_ONE 1
-
-/* Clusters: Accumulate dirty rects, merging those that overlap (insert is O(n)) */
-#define GFXOP_DIRTY_FRAMES_CLUSTERS 2
+/** Dirty rectangle heuristics. */
+enum {
+ GFXOP_DIRTY_FRAMES_ONE = 1, /**< One: Redraw one rectangle surrounding the dirty area (insert is O(1)) */
+ GFXOP_DIRTY_FRAMES_CLUSTERS = 2 /**< Clusters: Accumulate dirty rects, merging those that overlap (insert is O(n)) */
+};
+/**
+ * All user options to the rendering pipeline
+ *
+ * See note in sci_conf.h for config_entry_t before changing types of
+ * variables
+ */
struct gfx_options_t {
#ifdef CUSTOM_GRAPHICS_OPTIONS
- /* gfx_options_t: Contains all user options to the rendering pipeline */
- /* See note in sci_conf.h for config_entry_t before changing types of
- ** variables */
-
int buffer_pics_nr; /* Number of unused pics to buffer */
/* SCI0 pic resource options */
diff --git a/engines/sci/gfx/gfx_res_options.h b/engines/sci/gfx/gfx_res_options.h
index f01f93d21b..a595c56606 100644
--- a/engines/sci/gfx/gfx_res_options.h
+++ b/engines/sci/gfx/gfx_res_options.h
@@ -23,8 +23,6 @@
*
*/
-/* Configuration options for per-resource customisations */
-
#ifndef SCI_GFX_GFX_RES_OPTIONS_H
#define SCI_GFX_GFX_RES_OPTIONS_H
@@ -35,13 +33,16 @@
#include "sci/gfx/gfx_resmgr.h"
namespace Sci {
+/** @name Configuration options for per-resource customisations */
+/** @{ */
struct gfx_res_pattern_t {
int min, max;
};
-/* GFX resource assignments */
-
+/**
+ * GFX resource assignments.
+ */
struct gfx_res_assign_t {
union {
struct {
@@ -52,23 +53,24 @@ struct gfx_res_assign_t {
};
-/* GFX resource modifications */
-
+/**
+ * GFX resource modifications/
+ */
struct gfx_res_conf_t {
- int type; /* Resource type-- only one allowed */
+ int type; /**< Resource type-- only one allowed */
/* If any of the following is 0, it means that there is no restriction.
** Otherwise, one of the patterns associated with them must match. */
- int patterns_nr; /* Number of patterns (only 'view' patterns for views) */
- int loops_nr, cels_nr; /* Number of loop/cel patterns, for views only.
+ int patterns_nr; /**< Number of patterns (only 'view' patterns for views) */
+ int loops_nr, cels_nr; /**< Number of loop/cel patterns, for views only.
** For pics, loops_nr identifies the palette. */
gfx_res_pattern_t *patterns;
union {
gfx_res_assign_t assign;
- byte factor[3]; /* divide by 16 to retrieve factor */
- } conf; /* The actual configuration */
+ byte factor[3]; /**< divide by 16 to retrieve factor */
+ } conf; /**< The actual configuration */
gfx_res_conf_t *next;
};
@@ -84,16 +86,20 @@ struct gfx_res_fullconf_t {
struct gfx_options_t;
+/**
+ * Configures a graphical pixmap according to config options.
+ *
+ * Modifies pxm as considered appropriate by configuration options. Does
+ * not do anything in colour index mode.
+ *
+ * @param[in] options The options according to which configuration
+ * should be performed
+ * @param[in] pxm The pixmap to configure
+ * @return 0 on success, non-zero otherwise
+ */
int gfx_get_res_config(gfx_options_t *options, gfx_pixmap_t *pxm);
-/* Configures a graphical pixmap according to config options
-** Parameters: (gfx_options_t *) options: The options according to which
-** configuration should be performed
-** (gfx_resource_type_t) pxm: The pixmap to configure
-** Returns : (int) 0 on success, non-zero otherwise
-** Modifies pxm as considered appropriate by configuration options. Does
-** not do anything in colour index mode.
-*/
+/** @} */
} // End of namespace Sci
#endif
diff --git a/engines/sci/gfx/gfx_resmgr.h b/engines/sci/gfx/gfx_resmgr.h
index c5878bf529..1f0f58dce9 100644
--- a/engines/sci/gfx/gfx_resmgr.h
+++ b/engines/sci/gfx/gfx_resmgr.h
@@ -49,7 +49,7 @@ enum gfx_resource_type_t {
GFX_RESOURCE_TYPE_PALETTE,
/* FIXME: Add PAL resource */
- GFX_RESOURCE_TYPES_NR /* Number of resource types that are to be supported */
+ GFX_RESOURCE_TYPES_NR /**< Number of resource types that are to be supported */
};
#define GFX_RESOURCE_TYPE_0 GFX_RESOURCE_TYPE_VIEW
@@ -58,12 +58,13 @@ enum gfx_resource_type_t {
#define GFXR_RES_TYPE(id) (id >> 16)
#define GFXR_RES_NR(id) (id & 0xffff)
-
+/** Graphics resource */
struct gfx_resource_t {
- int ID; /* Resource ID */
- int lock_sequence_nr; /* See description of lock_counter in GfxResManager */
- int mode; /* A mode type hash */
+ int ID; /**< Resource ID */
+ int lock_sequence_nr; /**< See description of lock_counter in GfxResManager */
+ int mode; /**< A mode type hash */
+ /** Scaled pic */
union {
gfx_pixmap_t *pointer;
gfxr_view_t *view;
@@ -71,6 +72,7 @@ struct gfx_resource_t {
gfxr_pic_t *pic;
} scaled_data;
+ /** Original pic */
union {
gfx_pixmap_t *pointer;
gfxr_view_t *view;
@@ -85,152 +87,204 @@ struct gfx_options_t;
typedef Common::HashMap<int, gfx_resource_t *> IntResMap;
-
+/** Graphics resource manager */
class GfxResManager {
public:
- GfxResManager(int version, bool isVGA, gfx_options_t *options, GfxDriver *driver, ResourceManager *resManager);
+ GfxResManager(int version, bool isVGA, gfx_options_t *options,
+ GfxDriver *driver, ResourceManager *resManager);
~GfxResManager();
- /* Calculates a unique hash value for the specified options/type setup
- ** Parameters: (gfx_resource_type_t) type: The type the hash is to be generated for
- ** Returns : (int) A hash over the values of the options entries, covering entries iff
- ** they are relevant for the specified type
- ** Covering more entries than relevant may slow down the system when options are changed,
- ** while covering less may result in invalid cached data being used.
- ** Only positive values may be returned, as negative values are used internally by the generic
- ** resource manager code.
- ** Also, only the lower 20 bits are available to the interpreter.
- ** (Yes, this isn't really a "hash" in the traditional sense...)
- */
+ /**
+ * Calculates a unique hash value for the specified options/type
+ * setup.
+ *
+ * Covering more entries than relevant may slow down the system when
+ * options are changed, while covering less may result in invalid
+ * cached data being used.
+ * Only positive values may be returned, as negative values are used
+ * internally by the generic resource manager code.
+ * Also, only the lower 20 bits are available to the interpreter.
+ * (Yes, this isn't really a "hash" in the traditional sense...)
+ *
+ * @param[in] type The type the hash is to be generated for
+ * @return A hash over the values of the options entries,
+ * covering entries iff they are relevant for the
+ * specified type.
+ */
int getOptionsHash(gfx_resource_type_t type);
- /* 'Tags' all resources for deletion
- ** Paramters: (void)
- ** Returns : (void)
- ** Tagged resources are untagged if they are referenced.
- */
+ /**
+ * 'Tags' all resources for deletion.
+ *
+ * Tagged resources are untagged if they are referenced.
+ */
void tagResources() { _tagLockCounter++; }
- /* Retrieves an SCI0/SCI01 mouse cursor
- ** Parameters: (int) num: The cursor number
- ** Returns : (gfx_font_t *) The approprate cursor as a pixmap, or NULL on error
- */
+ /**
+ * Retrieves an SCI0/SCI01 mouse cursor.
+ *
+ * @param[in] num The cursor number
+ * @return The approprate cursor as a pixmap, or NULL on error
+ */
gfx_pixmap_t *getCursor(int num);
- /* Retrieves the static palette from the interpreter-specific code
- ** Parameters: (int *) colors_nr: Number of colors to use
- ** (int) nr: The palette to read
- ** Returns : (Palette *) static palette
- ** if a static palette must be used, NULL otherwise
- */
+ /**
+ * Retrieves the static palette from the interpreter-specific code.
+ *
+ * @param[in] colors_nr Number of colors to use
+ * @param[in] num The palette to read
+ * @return Static palette if a static palette must be
+ * used, NULL otherwise
+ */
Palette *getPalette(int *colors_nr, int num = 999);
- /* Retrieves a font
- ** Parameters: (int) nr: The font number
- ** (int) scaled: Whether the font should be font-scaled
- ** Returns : (gfx_font_t *) The appropriate font, or NULL on error
- */
+ /**
+ * Retrieves a font.
+ *
+ * @param[in] num The font number
+ * @param[in] scaled Whether the font should be font-scaled
+ * @return The appropriate font, or NULL on error
+ */
gfx_bitmap_font_t *getFont(int num, bool scaled = false);
- /* Retrieves a translated view cel
- ** Parameters:
- ** (int) nr: The view number
- ** (int *) loop: Pointer to a variable containing the loop number
- ** (int *) cel: Pointer to a variable containing the cel number
- ** (int) palette: The palette to use
- ** Returns : (gfx_view_t *) The relevant view, or NULL if nr was invalid
- ** loop and cel are given as pointers in order to allow the underlying variables to be
- ** modified if they are invalid (this is relevant for SCI version 0, where invalid
- ** loop and cel numbers have to be interpreted as 'maximum' or 'minimum' by the interpreter)
- */
+ /**
+ * Retrieves a translated view cel.
+ *
+ * @param[in] nr The view number
+ * @param[in] loop Pointer to a variable containing the loop number
+ * @param[in] cel Pointer to a variable containing the cel number
+ * @param[in] palette The palette to use
+ * @return The relevant view, or NULL if nr was invalid
+ * loop and cel are given as pointers in order to
+ * allow the underlying variables to be modified
+ * if they are invalid (this is relevant for SCI
+ * version 0, where invalid loop and cel numbers
+ * have to be interpreted as 'maximum' or 'minimum'
+ * by the interpreter)
+ */
gfxr_view_t *getView(int nr, int *loop, int *cel, int palette);
- /* Retrieves a displayable (translated) pic resource
- ** Parameters: (int) nr: Number of the pic resource
- ** (int) maps: The maps to translate (ORred GFX_MASK_*)
- ** (int) flags: Interpreter-dependant pic flags
- ** (int) default_palette: The default palette to use for drawing (if applicable)
- ** (bool) scaled: Whether to return the scaled maps, or the unscaled
- ** ones (which may be identical) for some special operations.
- ** Returns : (gfxr_pic_t *) The appropriate pic resource with all maps as index (but not
- ** neccessarily translated) data.
- */
- gfxr_pic_t *getPic(int num, int maps, int flags, int default_palette, bool scaled = false);
-
-
- /* Retrieves a displayable (translated) pic resource written ontop of an existing pic
- ** Parameters: (int) old_nr: Number of the pic resource to write on
- ** (int) new_nr: Number of the pic resource that is to be added
- ** (int) flags: Interpreter-dependant pic flags
- ** (int) default_palette: The default palette to use for drawing (if applicable)
- ** (int) scaled: Whether to return the scaled maps, or the unscaled
- ** ones (which may be identical) for some special operations.
- ** Returns : (gfxr_pic_t *) The appropriate pic resource with all maps as index (but not
- ** neccessarily translated) data.
- ** This function invalidates the cached pic pointed to by old_nr in the cache. While subsequent
- ** addToPic() writes will still modify the 'invalidated' pic, gfxr_get_pic() operations will
- ** cause it to be removed from the cache and to be replaced by a clean version.
- */
- gfxr_pic_t *addToPic(int old_nr, int new_nr, int flags, int old_default_palette, int default_palette);
-
- /* Calculate a picture
- ** Parameters: (gfxr_pic_t *) scaled_pic: The pic structure that is to be written to
- ** (gfxr_pic_t *) unscaled_pic: The pic structure the unscaled pic is to be written to,
- ** or NULL if it isn't needed.
- ** (int) flags: Pic drawing flags (interpreter dependant)
- ** (int) default_palette: The default palette to use for pic drawing (interpreter dependant)
- ** (int) nr: pic resource number
- ** Returns : (int) GFX_ERROR if the resource could not be found, GFX_OK otherwise
- */
- int calculatePic(gfxr_pic_t *scaled_pic, gfxr_pic_t *unscaled_pic, int flags, int default_palette, int nr);
-
- /* Determines whether support for pointers with more than two colors is required
- ** Returns : (bool) false if no support for multi-colored pointers is required, true
- ** otherwise
- */
+ /**
+ * Retrieves a displayable (translated) pic resource.
+ *
+ * @param[in] num Number of the pic resource
+ * @param[in] maps The maps to translate (ORred GFX_MASK_*)
+ * @param[in] flags Interpreter-dependant pic flags
+ * @param[in] default_palette The default palette to use for drawing
+ * (if applicable)
+ * @param[in] scaled Whether to return the scaled maps, or
+ * the unscaled ones (which may be
+ * identical) for some special operations.
+ * @return The appropriate pic resource with all
+ * maps as index (but not neccessarily
+ * translated) data.
+ */
+ gfxr_pic_t *getPic(int num, int maps, int flags, int default_palette,
+ bool scaled = false);
+
+
+ /**
+ * Retrieves a displayable (translated) pic resource written ontop of
+ * an existing pic.
+ *
+ * This function invalidates the cached pic pointed to by old_nr in the
+ * cache. While subsequent addToPic() writes will still modify the
+ * 'invalidated' pic, gfxr_get_pic() operations will cause it to be
+ * removed from the cache and to be replaced by a clean version.
+ *
+ * @param[in] old_nr Number of the pic resource to write on
+ * @param[in] new_nr Number of the pic resource that is to
+ * be added
+ * @param[in] flags Interpreter-dependant pic flags
+ * @param[in] old_default_palette The default palette of the pic before
+ * translation
+ * @param[in] default_palette The default palette to use for drawing
+ * (if applicable)
+ * @return The appropriate pic resource with all
+ * maps as index (but not neccessarily
+ * translated) data.
+ */
+ gfxr_pic_t *addToPic(int old_nr, int new_nr, int flags,
+ int old_default_palette, int default_palette);
+
+ /**
+ * Calculate a picture
+ *
+ * @param[in] scaled_pic The pic structure that is to be
+ * written to
+ * @param[in] unscaled_pic The pic structure the unscaled pic is
+ * to be written to, or NULL if it isn't
+ * needed.
+ * @param[in] flags Pic drawing flags (interpreter
+ * dependant)
+ * @param[in] default_palette The default palette to use for pic
+ * drawing (interpreter dependant)
+ * @param[in] nr pic resource number
+ * @return GFX_ERROR if the resource could not be
+ * found, GFX_OK otherwise
+ */
+ int calculatePic(gfxr_pic_t *scaled_pic, gfxr_pic_t *unscaled_pic,
+ int flags, int default_palette, int nr);
+
+ /**
+ * Determines whether support for pointers with more than two colors
+ * is required.
+ *
+ * @return false if no support for multi-colored pointers is required,
+ * true otherwise
+ */
bool multicoloredPointers() { return _version > SCI_VERSION_1; }
- /* Frees all resources currently allocated
- ** Parameter: (void)
- ** Returns : (void)
- ** This function is intended to be used primarily for debugging.
- */
+ /**
+ * Frees all resources currently allocated.
+ *
+ * This function is intended to be used primarily for debugging.
+ */
void freeAllResources();
- /* Frees all tagged resources.
- ** Parameters: (void)
- ** Returns : (void)
- ** Resources are tagged by calling gfx_tag_resources(), and untagged by calling the
- ** approprate dereferenciation function.
- ** Note that this function currently only affects view resources, as pic resources are
- ** treated differently, while font and cursor resources are relatively rare.
- */
+ /**
+ * Frees all tagged resources.
+ *
+ * Resources are tagged by calling gfx_tag_resources(), and untagged by
+ * calling the approprate dereferenciation function.
+ * Note that this function currently only affects view resources, as
+ * pic resources are treated differently, while font and cursor
+ * resources are relatively rare.
+ */
void freeTaggedResources();
- /* Frees a previously allocated resource manager, and all allocated resources.
- ** Parameters: (void)
- ** Return : (void)
- */
+ /**
+ * Frees a previously allocated resource manager, and all allocated
+ * resources.
+ */
void freeResManager();
- const PaletteEntry &getColor(int color) { return _staticPalette->getColor(color); }
+ /**
+ * Retrieves a color from the static palette
+ */
+ const PaletteEntry &getColor(int color)
+ {
+ return _staticPalette->getColor(color);
+ }
- // Set static palette and merge it into the global palette
+ /**
+ * Set static palette and merge it into the global palette
+ */
void setStaticPalette(Palette *newPalette);
- /*
- ** Sets the picture port bounds
- */
+ /**
+ * Sets the picture port bounds
+ */
void changePortBounds(int x1, int y1, int x2, int y2) {
_portBounds = Common::Rect(x1, y1, x2, y2);
}
@@ -252,7 +306,15 @@ public:
}
#endif
- int getColorCount() { return _staticPalette ? _staticPalette->size() : 0; }
+ /**
+ * Gets the number of colors in the static palette.
+ *
+ * @return Number of pallete entries
+ */
+ int getColorCount()
+ {
+ return _staticPalette ? _staticPalette->size() : 0;
+ }
private:
int _version;
@@ -260,11 +322,11 @@ private:
gfx_options_t *_options;
GfxDriver *_driver;
Palette *_staticPalette;
- int _lockCounter; /* Global lock counter; increased for each new resource allocated.
- ** The newly allocated resource will then be assigned the new value
- ** of the lock_counter, as will any resources referenced afterwards.
- */
- int _tagLockCounter; /* lock counter value at tag time */
+ int _lockCounter; /**< Global lock counter; increased for each new
+ * resource allocated. The newly allocated resource will
+ * then be assigned the new value of the lock_counter,
+ * as will any resources referenced afterwards. */
+ int _tagLockCounter; /**< lock counter value at tag time */
Common::Rect _portBounds;
IntResMap _resourceMaps[GFX_RESOURCE_TYPES_NR];
diff --git a/engines/sci/gfx/gfx_resource.h b/engines/sci/gfx/gfx_resource.h
index 8ce4a8ea83..780060bc4f 100644
--- a/engines/sci/gfx/gfx_resource.h
+++ b/engines/sci/gfx/gfx_resource.h
@@ -23,7 +23,9 @@
*
*/
-/* SCI Resource library */
+/** @file gfx_resource.h
+ * SCI Resource library.
+ */
#ifndef SCI_GFX_GFX_RESOURCE_H
#define SCI_GFX_GFX_RESOURCE_H
@@ -44,6 +46,7 @@ namespace Sci {
#define GFXR_DITHER_MODE_D16 0 /* Sierra SCI style */
#define GFXR_DITHER_MODE_F256 1 /* Flat color interpolation */
#define GFXR_DITHER_MODE_D256 2 /* 256 color dithering */
+
/* Dithering patterns */
#define GFXR_DITHER_PATTERN_SCALED 0 /* Dither per pixel on the 320x200 grid */
#define GFXR_DITHER_PATTERN_1 1 /* Dither per pixel on the target */
@@ -64,52 +67,53 @@ namespace Sci {
extern int sci0_palette;
-/* (gfx_pic_0.c) The 16 EGA base colors */
+/** The 16 EGA base colors */
extern Palette* gfx_sci0_image_pal[];
extern gfx_pixmap_color_t gfx_sci0_image_colors[][16];
-/* (gfx_pic_0.c) The 256 interpolated colors (initialized when
-** gfxr_init_pic() is called for the first time, or when gfxr_init_static_palette() is called)
-*/
+/**
+ * The 256 interpolated colors (initialized when gfxr_init_pic() is called
+ * for the first time, or when gfxr_init_static_palette() is called)
+ */
extern Palette* gfx_sci0_pic_colors;
-
struct gfxr_pic0_params_t {
gfx_line_mode_t line_mode; /* one of GFX_LINE_MODE_* */
gfx_brush_mode_t brush_mode;
};
+/** A SCI resource pic */
struct gfxr_pic_t {
- int ID; /* pic number (NOT resource ID, just number) */
+ int ID; /**< pic number (NOT resource ID, just number) */
gfx_mode_t *mode;
- gfx_pixmap_t *visual_map;
- gfx_pixmap_t *priority_map;
- gfx_pixmap_t *control_map;
-
+ gfx_pixmap_t *visual_map; /**< Visual part of pic */
+ gfx_pixmap_t *priority_map; /**< Priority map for pic */
+ gfx_pixmap_t *control_map; /**< Control map for pic */
+
+ /**
+ * Auxiliary map.
+ * Bit 0: Vis
+ * Bit 1: Pri
+ * Bit 2: Ctrl
+ * Bit 3-5: 'filled' (all three bits are set to 1)
+ */
byte aux_map[GFXR_AUX_MAP_SIZE];
- /* Auxiliary map details:
- ** Bit 0: Vis
- ** Bit 1: Pri
- ** Bit 2: Ctrl
- ** Bit 3-5: 'filled' (all three bits are set to 1)
- */
-
// rect_t bounds; // unused
- void *undithered_buffer; /* copies visual_map->index_data before dithering */
+ void *undithered_buffer; /**< copies visual_map->index_data before dithering */
int undithered_buffer_size;
int *priorityTable;
};
-
+/** A animation loop */
struct gfxr_loop_t {
- int cels_nr;
- gfx_pixmap_t **cels;
+ int cels_nr; /**< Number of 'cels' or frames in the animation */
+ gfx_pixmap_t **cels; /**< Pointer to the pixmaps for the cels */
};
-
+/** A graphics view */
struct gfxr_view_t {
int ID;
@@ -122,172 +126,197 @@ struct gfxr_view_t {
int translation[GFX_SCI0_IMAGE_COLORS_NR];
};
+/**
+ * Initializes the static 256 color palette.
+ */
void gfxr_init_static_palette();
-/* Initializes the static 256 color palette
-** Parameters: (void)
-** Returns : (void)
-*/
-
-gfxr_pic_t *gfxr_init_pic(gfx_mode_t *mode, int ID, int sci1);
-/* Initializes a gfxr_pic_t for a specific mode
-** Parameters: (gfx_mode_t *) mode: The specific graphics mode
-** (int) ID: The ID to assign to the resulting pixmaps
-** Returns : (gfxr_pic_t *) The allocated pic resource, or NULL on error.
-** This function allocates memory for use by resource drawer functions.
-*/
-void gfxr_free_pic(gfxr_pic_t *pic);
-/* Uninitializes a pic resource
-** Parameters: (gfxr_pic_t *) pic: The pic to free
-** Returns : (void)
-*/
-
-void gfxr_free_view(gfxr_view_t *view);
-/* Frees all memory associated with a view
-** Paremeters: (gfxr_view_t *) view: The view to free
-** Returns : (void)
-*/
+/** @name Resource picture management functions */
+/** @{ */
+/**
+ * Initializes a gfxr_pic_t for a specific mode.
+ *
+ * This function allocates memory for use by resource drawer functions.
+ *
+ * @param[in] mode The specific graphics mode
+ * @param[in] ID The ID to assign to the resulting pixmaps
+ * @param[in] sci1 true if a SCI1 pic, false otherwise
+ * @return The allocated pic resource, or NULL on error.
+ */
+gfxr_pic_t *gfxr_init_pic(gfx_mode_t *mode, int ID, bool sci1);
+/**
+ * Uninitializes a pic resource.
+ *
+ * @param[in] pic The pic to free
+ */
+void gfxr_free_pic(gfxr_pic_t *pic);
+/**
+ * Frees all memory associated with a view.
+ *
+ * @param[in] view The view to free
+ */
+void gfxr_free_view(gfxr_view_t *view);
+/** @} */
+/** @name SCI0 resource picture operations */
+/** @{ */
-/*********************/
-/* SCI0 operations */
-/*********************/
+/**
+ * Clears all pic buffers of one pic/
+ *
+ * This function should be called before gfxr_draw_pic0, unless cumulative
+ * drawing is intended
+ *
+ * @param[in] pic The picture to clear
+ * @param[in] titlebar_size How much space to reserve for the title bar
+ */
+void gfxr_clear_pic0(gfxr_pic_t *pic, int titlebar_size);
+/**
+ * Draws a pic resource (all formats prior to SCI1.1).
+ *
+ * The result is stored in gfxr_visual_map, gfxr_priority_map, and
+ * gfxr_control_map. The palette entry of gfxr_visual_map is never used.
+ * Note that the picture will not be drawn dithered; use gfxr_dither_pic0
+ * for that.
+ *
+ * @param[in] pic The pic to draw to
+ * @param[in] fill_normally If 1, the pic is drawn normally; if 0, all
+ * fill operations will fill with black
+ * @param[in] default_palette The default palette to use for drawing
+ * @param[in] size Resource size
+ * @param[in] resource Pointer to the resource data
+ * @param[in] style The drawing style
+ * @param[in] resid The resource ID
+ * @param[in] sci1 true if SCI1, false otherwise
+ * @param[in] static_pal The static palette
+ * @param[in] portBounds The bounds of the port being drawn to
+ */
+void gfxr_draw_pic01(gfxr_pic_t *pic, int fill_normally,
+ int default_palette, int size, byte *resource,
+ gfxr_pic0_params_t *style, int resid, int sci1,
+ Palette *static_pal, Common::Rect portBounds);
-void gfxr_clear_pic0(gfxr_pic_t *pic, int titlebar_size);
-/* Clears all pic buffers of one pic
-** Parameters: (gfxr_pic_t) pic: The picture to clear
-** (int) titlebar_size: How much space to reserve for the title bar
-** Returns : (void)
-** This function should be called before gfxr_draw_pic0, unless cumulative
-** drawing is intended
-*/
-
-
-void gfxr_draw_pic01(gfxr_pic_t *pic, int fill_normally, int default_palette,
- int size, byte *resource, gfxr_pic0_params_t *style, int resid, int sci1,
- Palette *static_pal, Common::Rect portBounds);
-/* Draws a pic resource (all formats prior to SCI1.1)
-** Parameters: (gfxr_pic_t *) pic: The pic to draw to
-** (int) fill_normally: If 1, the pic is drawn normally; if 0, all
-** fill operations will fill with black
-** (int) default_palette: The default palette to use for drawing
-** (int) size: Resource size
-** (byte *) resource: Pointer to the resource data
-** (gfxr_pic0_params_t *) style: The drawing style
-** (int) resid: The resource ID
-** (int) sci1: Nonzero if SCI1
-** (Palette *) static_pal: The static palette
-** (int) static_pal_nr: Number of entries in static palette
-** Returns : (void)
-** The result is stored in gfxr_visual_map, gfxr_priority_map, and gfxr_control_map.
-** The palette entry of gfxr_visual_map is never used.
-** Note that the picture will not be drawn dithered; use gfxr_dither_pic0 for that.
-*/
-
-void gfxr_draw_pic11(gfxr_pic_t *pic, int fill_normally, int default_palette,
- int size, byte *resource, gfxr_pic0_params_t *style, int resid,
- Palette *static_pal, Common::Rect portBounds);
-/* Draws a pic resource (SCI1.1)
-** Parameters: (gfxr_pic_t *) pic: The pic to draw to
-** (int) fill_normally: If 1, the pic is drawn normally; if 0, all
-** fill operations will fill with black
-** (int) default_palette: The default palette to use for drawing
-** (int) size: Resource size
-** (byte *) resource: Pointer to the resource data
-** (gfxr_pic0_params_t *) style: The drawing style
-** (int) resid: The resource ID
-** (Palette *) static_pal: The static palette
-** (int) static_pal_nr: Number of entries in static palette
-** Returns : (void)
-** The result is stored in gfxr_visual_map, gfxr_priority_map, and gfxr_control_map.
-** The palette entry of gfxr_visual_map is never used.
-** Note that the picture will not be drawn dithered; use gfxr_dither_pic0 for that.
-*/
+/**
+ * Draws a pic resource (SCI1.1).
+ *
+ * The result is stored in gfxr_visual_map, gfxr_priority_map, and
+ * gfxr_control_map. The palette entry of gfxr_visual_map is never used.
+ * Note that the picture will not be drawn dithered; use gfxr_dither_pic11
+ * for that.
+ *
+ * @param[in] pic The pic to draw to
+ * @param[in] fill_normally If 1, the pic is drawn normally; if 0, all
+ * fill operations will fill with black
+ * @param[in] default_palette The default palette to use for drawing
+ * @param[in] size Resource size
+ * @param[in] resource Pointer to the resource data
+ * @param[in] style The drawing style
+ * @param[in] resid The resource ID
+ * @param[in] static_pal The static palette
+ * @param[in] portBounds Bounds of the port being drawn to
+ */
+void gfxr_draw_pic11(gfxr_pic_t *pic, int fill_normally,
+ int default_palette, int size, byte *resource,
+ gfxr_pic0_params_t *style, int resid, Palette *static_pal,
+ Common::Rect portBounds);
+/**
+ * Removes artifacts from a scaled pic.
+ *
+ * Using information from the (correctly rendered) src pic, this function
+ * implements some heuristics to remove artifacts from dest. Must be used
+ * before dither_pic0 is called, because it operates on the index buffer.
+ *
+ * @param[in] dest The scaled pic
+ * @param[in] src An unscaled pic
+ */
void gfxr_remove_artifacts_pic0(gfxr_pic_t *dest, gfxr_pic_t *src);
-/* Removes artifacts from a scaled pic
-** Parameters: (gfxr_pic_t *) dest: The scaled pic
-** (gfxr_pic_t *) src: An unscaled pic
-** Returns : (void)
-** Using information from the (correctly rendered) src pic, this function implements
-** some heuristics to remove artifacts from dest. Must be used before dither_pic0 is
-** called, because it operates on the index buffer.
-*/
+/**
+ * Dithers a gfxr_visual_map.
+ *
+ * @param[in] pic The pic to dither
+ * @param[in] mode One of GFXR_DITHER_MODE
+ * @param[in] pattern One of GFXR_DITHER_PATTERN
+ */
void gfxr_dither_pic0(gfxr_pic_t *pic, int mode, int pattern);
-/* Dithers a gfxr_visual_map
-** Parameters: (gfxr_pic_t *) pic: The pic to dither
-** (int) mode: One of GFXR_DITHER_MODE
-** (int) pattern: One of GFXR_DITHER_PATTERN
-** Returns : (void)
-*/
+/**
+ * Calculates a SCI0 view.
+ *
+ * @param[in] id Resource ID of the view
+ * @param[in] resource Pointer to the resource to read
+ * @param[in] size Size of the resource
+ * @param[in] palette The palette to use
+ * @return The resulting view
+ */
gfxr_view_t *gfxr_draw_view0(int id, byte *resource, int size, int palette);
-/* Calculates an SCI0 view
-** Parameters: (int) id: Resource ID of the view
-** (byte *) resource: Pointer to the resource to read
-** (int) size: Size of the resource
-** (int) palette: The palette to use
-** Returns : (gfxr_view_t *) The resulting view
-*/
-
-gfx_pixmap_t *gfxr_draw_cursor(int id, byte *resource, int size, bool isSci01);
-/* Calculates n SCI cursor
-** Parameters: (int) id: The cursor's resource ID
-** (byte *) resource: Pointer to the resource data
-** (int) size: Resource size
-** (bool) isSci01: Set to true to load a SCI1 cursor
-** Returns : (gfx_pixmap_t *) A newly allocated pixmap containing an index
-** color representation of the cursor
-*/
-
-/*********************/
-/* SCI1 operations */
-/*********************/
+/**
+ * Calculates a SCI cursor.
+ *
+ * @param[in] id The cursor's resource ID
+ * @param[in] resource Pointer to the resource data
+ * @param[in] size Resource size
+ * @param[in] isSci01 Set to true to load a SCI1 cursor
+ * @return A newly allocated pixmap containing an index color
+ * representation of the cursor
+ */
+gfx_pixmap_t *gfxr_draw_cursor(int id, byte *resource, int size,
+ bool isSci01);
+/** @} */
+
+
+/** @name SCI1/1.1 resource picture operations */
+/** @{ */
+
+/**
+ * Reads an SCI1 palette.
+ *
+ * @param[in] id Resource ID for the palette (or the view it was
+ * found in)
+ * @param[in] resource Source data
+ * @param[in] size Size of the memory block pointed to by resource
+ * @return Palette with the colors
+ */
Palette *gfxr_read_pal1(int id, byte *resource, int size);
-/* Reads an SCI1 palette
-** Parameters: (int) id: Resource ID for the palette (or the view it was found in)
-** (int *) colors_nr: Pointer to the variable the number of colors
-** will be stored in
-** (byte *) resource: Source data
-** (int) size: Size of the memory block pointed to by resource
-** Returns : (Palette *) *colors_nr Palette with the colors
-*/
+/**
+ * Reads an SCI1 palette.
+ *
+ * @param[in] file Palette file
+ * @return Palette with the colors
+ */
Palette *gfxr_read_pal1_amiga(Common::File &file);
-/* Reads an SCI1 palette
-** Parameters: (int *) colors_nr: Pointer to the variable the number of colors
-** will be stored in
-** (FILE *) f: Palette file
-** Returns : (Palette *) Palette with the colors
-*/
+/**
+ * Reads an SCI1.1 palette.
+ *
+ * @param[in] id Resource ID for the palette (or the view it was
+ * found in)
+ * @param[in] resource Source data
+ * @param[in] size Size of the memory block pointed to by resource
+ * @return Palette with the colors
+ */
Palette *gfxr_read_pal11(int id, byte *resource, int size);
-/* Reads an SCI1.1 palette
-** Parameters: (int) id: Resource ID for the palette (or the view it was found in)
-** (int *) colors_nr: Pointer to the variable the number of colors
-** will be stored in
-** (byte *) resource: Source data
-** (int) size: Size of the memory block pointed to by resource
-** Returns : (Palette *) Palette with the colors
-*/
+/**
+ * Calculates an SCI1 view.
+ *
+ * @param[in] id Resource ID of the view
+ * @param[in] resource Pointer to the resource to read
+ * @param[in] size Size of the resource
+ * @param[in] static_pal The static palette
+ * @param[in] isSci11 true if SCI1.1, false otherwise
+ * @return The resulting view
+ */
gfxr_view_t *gfxr_draw_view1(int id, byte *resource, int size, Palette *static_pal, bool isSci11);
-/* Calculates an SCI1 view
-** Parameters: (int) id: Resource ID of the view
-** (byte *) resource: Pointer to the resource to read
-** (int) size: Size of the resource
-** (Palette *) static_pal: The static palette
-** (int) static_pal_nr: Number of entries in static palette
-** Returns : (gfxr_view_t *) The resulting view
-*/
gfx_pixmap_t *gfxr_draw_cel1(int id, int loop, int cel, int mirrored, byte *resource, byte *cel_base, int size, gfxr_view_t *view, bool isAmiga, bool isSci11);
-
+/** @} */
} // End of namespace Sci
diff --git a/engines/sci/gfx/gfx_state_internal.h b/engines/sci/gfx/gfx_state_internal.h
index d03c5e9519..3f00b5213c 100644
--- a/engines/sci/gfx/gfx_state_internal.h
+++ b/engines/sci/gfx/gfx_state_internal.h
@@ -34,14 +34,16 @@
namespace Sci {
-#define GFXW_FLAG_VISIBLE (1<<0)
-#define GFXW_FLAG_OPAQUE (1<<1)
-#define GFXW_FLAG_CONTAINER (1<<2)
-#define GFXW_FLAG_DIRTY (1<<3)
-#define GFXW_FLAG_TAGGED (1<<4)
-#define GFXW_FLAG_MULTI_ID (1<<5) /**< Means that the ID used herein may be used more than once, i.e. is not unique */
-#define GFXW_FLAG_IMMUNE_TO_SNAPSHOTS (1<<6) /**< Snapshot restoring doesn't kill this widget, and +5 bonus to saving throws vs. Death Magic */
-#define GFXW_FLAG_NO_IMPLICIT_SWITCH (1<<7) /**< Ports: Don't implicitly switch to this port when disposing windows */
+enum gfxw_flag_t {
+ GFXW_FLAG_VISIBLE = (1<<0),
+ GFXW_FLAG_OPAQUE = (1<<1),
+ GFXW_FLAG_CONTAINER = (1<<2),
+ GFXW_FLAG_DIRTY = (1<<3),
+ GFXW_FLAG_TAGGED = (1<<4),
+ GFXW_FLAG_MULTI_ID = (1<<5), /**< Means that the ID used herein may be used more than once, i.e. is not unique */
+ GFXW_FLAG_IMMUNE_TO_SNAPSHOTS = (1<<6), /**< Snapshot restoring doesn't kill this widget, and +5 bonus to saving throws vs. Death Magic */
+ GFXW_FLAG_NO_IMPLICIT_SWITCH = (1<<7) /**< Ports: Don't implicitly switch to this port when disposing windows */
+};
struct gfxw_snapshot_t {
int serial; /**< The first serial number to kill */
@@ -82,6 +84,7 @@ struct GfxPort;
typedef int gfxw_bin_op(GfxWidget *, GfxWidget *);
+/** SCI graphics widget */
struct GfxWidget {
public:
int _magic; /**< Extra check after typecasting */
@@ -101,27 +104,28 @@ public:
/**
* The widget automatically removes itself from its owner, if it has one.
- * Deleting a container will recursively free all of its
- * contents.
+ * Deleting a container will recursively free all of its contents.
*/
virtual ~GfxWidget();
/**
* Draws the widget.
*
- * The widget is drawn iff it is flagged as dirty. Invoking this operation on
- * a container widget will recursively draw all of its contents.
+ * The widget is drawn iff it is flagged as dirty. Invoking this operation
+ * on a container widget will recursively draw all of its contents.
*
- * @param pos The position to draw to (added to the widget's internal position)
+ * @param[in] pos The position to draw to (added to the widget's
+ * internal position)
*/
virtual int draw(const Common::Point &pos) = 0;
/**
* Tags the specified widget.
*
- * If invoked on a container widget, this will also tag all of the container's
- * contents (but not the contents' contents!)
- * FIXME: Actually, the code in GfxContainer::tag contradicts the last claim!
+ * If invoked on a container widget, this will also tag all of the
+ * container's contents (but not the contents' contents!)
+ * FIXME: Actually, the code in GfxContainer::tag contradicts the last
+ * claim!
*/
virtual void tag() {
_flags |= GFXW_FLAG_TAGGED;
@@ -130,10 +134,10 @@ public:
/**
* Prints a string representation of the widget with sciprintf.
*
- * Will recursively print all of the widget's contents if the widget contains
- * further sub-widgets
+ * Will recursively print all of the widget's contents if the widget
+ * contains further sub-widgets
*
- * @param indentation Number of double spaces to indent
+ * @param[in] indentation Number of double spaces to indent
*/
virtual void print(int indentation) const;
@@ -143,55 +147,63 @@ public:
* This comparison only applies to some widgets; compare_to(a,a)=0 is not
* guaranteed. It may be used for sorting for all widgets.
*
- * @param other other widget
- * @return <0, 0, or >0 if other is, respectively, less than, equal
- * to, or greater than self
+ * @param other The other widget
+ * @return <0, 0, or >0 if other is, respectively, less than, equal
+ * to, or greater than self
*/
gfxw_bin_op *compare_to;
/**
* Compares two compareable widgets for equality.
*
- * This operation checks whether two widgets describe the same graphical data.
- * It is used to determine whether a new widget should be discarded because it
- * describes the same graphical data as an old widget that has already been
- * drawn. For lists, it also checks whether all contents are in an identical
- * order.
+ * This operation checks whether two widgets describe the same graphical
+ * data. It is used to determine whether a new widget should be discarded
+ * because it describes the same graphical data as an old widget that has
+ * already been drawn. For lists, it also checks whether all contents are
+ * in an identical order.
*
- * @param other other widget
- * @return false if the widgets are not equal, true if they match
+ * @param[in] other The other widget
+ * @return false if the widgets are not equal, true if they match
*/
gfxw_bin_op *equals;
/**
- * Determine whether other should replace this even though they are equivalent.
+ * Determine whether other should replace this even though they are
+ * equivalent.
*
* When 'equals' returns true, this means that no new widget will be added.
* However, in some cases newer widgets may contain information that should
- * cause the older widget to be removed nonetheless; this is indicated by this
- * function.
+ * cause the older widget to be removed nonetheless; this is indicated by
+ * this function.
*
- * @param other other widget
- * @return false if this should be kept, true if this should be replaced by the 'other'
+ * @param[in] other The other widget
+ * @return false if this should be kept, true if this should be
+ * replaced by the 'other'
*/
gfxw_bin_op *should_replace;
/**
- * Tests whether drawing this after other would reduce all traces of other.
+ * Tests whether drawing this after other would reduce all traces of
+ * other.
*
- * /a superarea_of b <=> for each pixel of b there exists an opaque pixel in a at the same location
+ * /a superarea_of b <=> for each pixel of b there exists an opaque pixel
+ * in a at the same location
*
- * @param other the widget to compare for containment
- * @return true if this is superarea_of other, false otherwise
+ * @param[in] other The widget to compare for containment
+ * @return true if this is superarea_of other, false otherwise
*/
gfxw_bin_op *superarea_of;
/**
* Sets the visual for the widget
- * This function is called by container->add() and need not be invoked explicitly.
- * It also makes sure that dirty rectangles are passed to parent containers.
+ *
+ * This function is called by container->add() and need not be invoked
+ * explicitly. It also makes sure that dirty rectangles are passed to
+ * parent containers.
+ *
+ * @param[in] visual GfxVisual to set for the widget
*/
- virtual int setVisual(GfxVisual *);
+ virtual int setVisual(GfxVisual *visual);
//protected:
void printIntern(int indentation) const;
@@ -200,6 +212,7 @@ public:
#define GFXW_IS_BOX(widget) ((widget)->_type == GFXW_BOX)
+/** SCI box widget */
struct GfxBox : public GfxWidget {
gfx_color_t _color1, _color2;
gfx_box_shade_t _shadeType;
@@ -213,6 +226,7 @@ public:
#define GFXW_IS_PRIMITIVE(widget) ((widget)->_type == GFXW_RECT || (widget)->_type == GFXW_LINE)
+/** SCI graphics primitive */
struct GfxPrimitive : public GfxWidget {
gfx_color_t _color;
gfx_line_mode_t _lineMode;
@@ -227,6 +241,7 @@ public:
#define GFXW_IS_VIEW(widget) ((widget)->_type == GFXW_VIEW || (widget)->_type == GFXW_STATIC_VIEW \
|| (widget)->_type == GFXW_DYN_VIEW || (widget)->_type == GFXW_PIC_VIEW)
+/** SCI graphics view */
struct GfxView : public GfxWidget {
Common::Point _pos; /**< Implies the value of 'bounds' in GfxWidget */
gfx_color_t _color;
@@ -242,6 +257,7 @@ public:
};
#define GFXW_IS_DYN_VIEW(widget) ((widget)->_type == GFXW_DYN_VIEW || (widget)->_type == GFXW_PIC_VIEW)
+/** SCI dynamic view */
struct GfxDynView : public GfxView {
/* FIXME: This code is specific to SCI */
rect_t draw_bounds; /* The correct position to draw to */
@@ -265,6 +281,7 @@ public:
#define GFXW_IS_TEXT(widget) ((widget)->_type == GFXW_TEXT)
+/** SCI text widget */
struct GfxText : public GfxWidget {
int _font;
int lines_nr, lineheight, lastline_width;
@@ -293,7 +310,7 @@ typedef int gfxw_unary_container_op(GfxContainer *);
typedef int gfxw_container_op(GfxContainer *, GfxWidget *);
typedef int gfxw_rect_op(GfxContainer *, rect_t, int);
-
+/** SCI container widget */
struct GfxContainer : public GfxWidget {
rect_t zone; /**< The writeable zone (absolute) for contained objects */
DirtyRectList _dirtyRects; /**< List of dirty rectangles */
@@ -324,7 +341,7 @@ public:
#define GFXW_IS_LIST(widget) ((widget)->_type == GFXW_LIST || (widget)->_type == GFXW_SORTED_LIST)
#define GFXW_IS_SORTED_LIST(widget) ((widget)->_type == GFXW_SORTED_LIST)
-
+/** SCI graphics list */
struct GfxList : public GfxContainer {
public:
GfxList(rect_t area, bool sorted);
@@ -334,6 +351,7 @@ public:
};
#define GFXW_IS_VISUAL(widget) ((widget)->_type == GFXW_VISUAL)
+/** SCI graphic visual */
struct GfxVisual : public GfxContainer {
Common::Array<GfxPort *> _portRefs; /**< References to ports */
int _font; /**< Default font */
@@ -353,6 +371,7 @@ public:
};
#define GFXW_IS_PORT(widget) ((widget)->_type == GFXW_PORT)
+/** SCI graphics port */
struct GfxPort : public GfxContainer {
GfxList *_decorations; /**< optional window decorations - drawn before the contents */
GfxWidget *port_bg; /**< Port background widget or NULL */
@@ -366,16 +385,20 @@ struct GfxPort : public GfxContainer {
byte gray_text; /**< Whether text is 'grayed out' (dithered) */
public:
- /* Creates a new port widget with the default settings
- ** Paramaters: (GfxVisual *) visual: The visual the port is added to
- ** (GfxPort *) predecessor: The port's predecessor
- ** (rect_t) area: The screen area covered by the port (absolute position)
- ** (gfx_color_t) fgcolor: Foreground drawing color
- ** (gfx_color_t) bgcolor: Background color
- ** A port differentiates itself from a list in that it contains additional information,
- ** and an optional title (stored in a display list).
- ** Ports are assigned implicit IDs identifying their position within the port stack.
- */
+ /**
+ * Creates a new port widget with the default settings
+ *
+ * A port differentiates itself from a list in that it contains additional
+ * information, and an optional title (stored in a display list).
+ * Ports are assigned implicit IDs identifying their position within the
+ * port stack.
+ *
+ * @param[in] visual The visual the port is added to
+ * @param[in] area The screen area covered by the port (absolute
+ * position)
+ * @param[in] fgcolor Foreground drawing color
+ * @param[in] bgcolor Background color
+ */
GfxPort(GfxVisual *visual, rect_t area, gfx_color_t fgcolor, gfx_color_t bgcolor);
~GfxPort();
diff --git a/engines/sci/gfx/gfx_system.h b/engines/sci/gfx/gfx_system.h
index 3922b21db2..6b7724a6bd 100644
--- a/engines/sci/gfx/gfx_system.h
+++ b/engines/sci/gfx/gfx_system.h
@@ -36,7 +36,7 @@ namespace Sci {
#define GFX_DEBUG
/* General output macros */
-# define GFXERROR sciprintf("GFX Error: %s, L%d:", __FILE__, __LINE__); error
+#define GFXERROR sciprintf("GFX Error: %s, L%d:", __FILE__, __LINE__); error
/***********************/
/*** Data structures ***/
@@ -50,32 +50,35 @@ namespace Sci {
** enabled */
#define GFX_MODE_FLAG_REVERSE_ALPHA (1<<1)
-/** Graphics mode description */
-struct gfx_mode_t {
+/** Graphics mode description
+ *
+ * Color masks:
+ * Each of the mask/shift pairs describe where the corresponding color
+ * values are stored for the described mode. Internally, color
+ * calculations are done by using 32 bit values for r, g, b, a. After
+ * the internal values have been calculated, they are shifted RIGHT
+ * by the xxx_shift amount described above, then ANDed with the
+ * corresponding color mask; finally, all three results are ORred to-
+ * gether. The alpha values are used as appropriate; if alpha_mask is
+ * zero, then images use a special alpha map.
+ */
- int xfact, yfact; /* Horizontal and vertical scaling factors */
- int xsize, ysize; /* Horizontal and vertical size */
- int bytespp; /* Bytes per pixel */
+struct gfx_mode_t {
- uint32 flags; /* GFX_MODE_FLAG_* Flags- see above */
+ int xfact, yfact; /**< Horizontal and vertical scaling factors */
+ int xsize, ysize; /**< Horizontal and vertical size */
+ int bytespp; /**< Bytes per pixel */
+ uint32 flags; /**< GFX_MODE_FLAG_* Flags- see above */
- Palette *palette; // Palette or NULL to indicate non-palette mode.
- // Palette mode is only supported for bytespp = 1
+ /**
+ * Palette or NULL to indicate non-palette mode.
+ * Palette mode is only supported for bytespp = 1
+ */
+ Palette *palette;
- /* Color masks */
uint32 red_mask, green_mask, blue_mask, alpha_mask;
short red_shift, green_shift, blue_shift, alpha_shift;
-
- /* Each of the mask/shift pairs describe where the corresponding color
- ** values are stored for the described mode. Internally, color
- ** calculations are done by using 32 bit values for r, g, b, a. After
- ** the internal values have been calculated, they are shifted RIGHT
- ** by the xxx_shift amount described above, then ANDed with the
- ** corresponding color mask; finally, all three results are ORred to-
- ** gether. The alpha values are used as appropriate; if alpha_mask is
- ** zero, then images use a special alpha map. */
-
};
@@ -84,16 +87,16 @@ struct gfx_mode_t {
/** Pixmap-specific color entries */
struct gfx_pixmap_color_t{
- int global_index; /* Global index color or GFX_COLOR_INDEX_UNMAPPED. */
- uint8 r, g, b; /* Real color */
+ int global_index; /**< Global index color or GFX_COLOR_INDEX_UNMAPPED. */
+ uint8 r, g, b; /**< Real color */
};
/** Full color */
struct gfx_color_t {
PaletteEntry visual;
- uint8 alpha; /* transparency = (1-opacity) */
+ uint8 alpha; /**< transparency = (1-opacity) */
int8 priority, control;
- byte mask; /* see mask values below */
+ byte mask; /**< see mask values below */
};
@@ -104,11 +107,15 @@ struct rect_t {
int width, height; /* width, height: (x,y,width,height)=(5,5,1,1) occupies 1 pixel */
};
-/* Generates a rect_t from index data
-** Parameters: (int x int) x,y: Upper left point of the rectangle
-** (int x int) width, height: Horizontal and vertical extension of the rectangle
-** Returns : (rect_t) A rectangle matching the supplied parameters
-*/
+/**
+ * Generates a rect_t from index data
+ *
+ * @param[in] x Left side of the rectangle
+ * @param[in] y Top side of the rectangle
+ * @param[in] width Horizontal extent of the rectangle
+ * @param[in] height Verical extent of the rectangle
+ * @return A rectangle matching the supplied parameters
+ */
static inline rect_t gfx_rect(int x, int y, int width, int height) {
rect_t rect;
@@ -120,11 +127,16 @@ static inline rect_t gfx_rect(int x, int y, int width, int height) {
return rect;
}
-// Temporary helper functions to ease the transition from rect_t to Common::Rect
+/**
+ * Temporary helper function to ease the transition from rect_t to Common::Rect
+ */
static inline rect_t toSCIRect(Common::Rect in) {
return gfx_rect(in.left, in.top, in.width(), in.height());
}
+/**
+ * Temporary helper function to ease the transition from rect_t to Common::Rect
+ */
static inline Common::Rect toCommonRect(rect_t in) {
return Common::Rect(in.x, in.y, in.x + in.width, in.y + in.height);
}
@@ -133,10 +145,13 @@ static inline Common::Rect toCommonRect(rect_t in) {
#define OVERLAP(a, b, z, zl) (a.z >= b.z && a.z < (b.z + b.zl))
-/* Determines whether two rects overlap
-** Parameters: (rect_t x rect_t) a,b: The two rect_ts to check for overlap
-** Returns : (int) 1 if they overlap, 0 otherwise
-*/
+/**
+ * Determines whether two rects overlap
+ *
+ * @param[in] a First rect to check for overlap
+ * @param[in] b Second rect to check for overlap
+ * @return 1 if they overlap, 0 otherwise
+ */
static inline int gfx_rects_overlap(rect_t a, rect_t b) {
return (OVERLAP(a, b, x, width) || OVERLAP(b, a, x, width)) && (OVERLAP(a, b, y, height) || OVERLAP(b, a, y, height));
}
@@ -150,86 +165,95 @@ extern rect_t gfx_rect_fullscreen;
#define GFX_PIC_COLORS 256
-#define GFX_PIXMAP_FLAG_SCALED_INDEX (1<<0) /* Index data is scaled already */
-#define GFX_PIXMAP_FLAG_INSTALLED (1<<2) /* Pixmap has been registered */
-#define GFX_PIXMAP_FLAG_PALETTIZED (1<<6) /* Indicates a palettized view */
+#define GFX_PIXMAP_FLAG_SCALED_INDEX (1<<0) /* Index data is scaled already */
+#define GFX_PIXMAP_FLAG_INSTALLED (1<<2) /* Pixmap has been registered */
+#define GFX_PIXMAP_FLAG_PALETTIZED (1<<6) /* Indicates a palettized view */
#define GFX_PIXMAP_COLOR_KEY_NONE -1 /* No transpacency colour key */
#define GFX_CURSOR_TRANSPARENT 255 // Cursor colour key
-struct gfx_pixmap_t { /* gfx_pixmap_t: Pixel map */
+/** Pixel map */
+struct gfx_pixmap_t {
- /*** Meta information ***/
- int ID; /* Resource ID, or GFX_RESID_NONE for anonymous graphical data */
- short loop, cel; /* loop and cel number for views */
+ /** @name Meta information
+ * @{*/
+ int ID; /**< Resource ID, or GFX_RESID_NONE for anonymous graphical data */
+ short loop; /**< loop number for view */
+ short cel; /**< cel number for view */
+ /** @}*/
-
- /*** Color map ***/
+ /** @name Color map
+ * @{*/
Palette *palette;
- int colors_nr() const { return palette ? palette->size() : 0; }
- /* color entries, or NULL if the
- ** default palette is to be used.
- ** A maximum of 255 colors is allowed; color
- ** index 0xff is reserved for transparency.
- ** As a special exception, 256 colors are
- ** allowed for background pictures (which do
- ** not use transparency)
- */
- uint32 flags;
-
- /*** Hot spot ***/
- int xoffset, yoffset; /* x and y coordinates of the 'hot spot' (unscaled) */
- /*** Index data ***/
- int index_width, index_height; /* width and height of the indexed original image */
- byte *index_data; /* Color-index data, or NULL if read from an
- ** external source
- */
-
- /*** Drawable data ***/
- int width, height; /* width and height of the actual image */
- int data_size; /* Amount of allocated memory */
- byte *data; /* Drawable data, or NULL if not converted. */
-
- byte *alpha_map; /* Byte map with alpha values. It is used only if the
- ** graphics mode's alpha_mask is zero.
- */
+ /**
+ * color entries, or NULL if the default palette is to be used. A maximum
+ * of 255 colors is allowed; color index 0xff is reserved for transparency.
+ * As a special exception, 256 colors are allowed for background pictures
+ * (which do not use transparency)
+ */
+ int colors_nr() const { return palette ? palette->size() : 0; }
- int color_key;
- int palette_revision; // Revision of palette at the time data was generated
+ uint32 flags;
+ /* @} */
+
+ /** @name Hot spot
+ * x and y coordinates of the 'hot spot' (unscaled)
+ * @{*/
+ int xoffset, yoffset;
+ /** @} */
+
+ /** @name Index data
+ * @{
+ */
+ int index_width; /**< width of the indexed original image */
+ int index_height; /**< height of the indexed original image */
+ byte *index_data; /**< Color-index data, or NULL if read from an external source */
+ /** @} */
+
+ /** @name Drawable data
+ * @{
+ */
+ int width; /**< width of the actual image */
+ int height; /**< height of the actual image */
+ int data_size; /**< Amount of allocated memory */
+ byte *data; /**< Drawable data, or NULL if not converted. */
+
+ byte *alpha_map; /**< Byte map with alpha values. It is used only if the graphics mode's alpha_mask is zero. */
+
+ int color_key; /**< The color to make transparent */
+ int palette_revision; /**< Revision of palette at the time data was generated */
+ /** @} */
};
-/***********************/
-/*** Constant values ***/
-/***********************/
-/* Return values */
+/** @name Constant values
+ * @{ */
+
+/** Return values */
enum gfx_return_value_t {
- GFX_OK = 0, /* Indicates "operation successful" */
- GFX_ERROR = -1, /* Indicates "operation failed" */
- GFX_FATAL = -2
- /* Fatal error: Used by graphics drivers to indicate that they were unable to
- ** do anything useful
- */
+ GFX_OK = 0, /**< Indicates "operation successful" */
+ GFX_ERROR = -1, /**< Indicates "operation failed" */
+ GFX_FATAL = -2 /**< Fatal error: Used by graphics drivers to indicate
+ that they were unable to do anything useful */
};
-
-enum gfx_map_mask_t {/* Map masks */
+/** Map masks */
+enum gfx_map_mask_t {
GFX_MASK_NONE = 0,
GFX_MASK_VISUAL = 1,
GFX_MASK_PRIORITY = 2,
GFX_MASK_CONTROL = 4
};
-/* 'no priority' mode */
+/** 'no priority' mode */
enum {
GFX_NO_PRIORITY = -1
};
-/* Text alignment values */
-
+/** Text alignment values */
enum gfx_alignment_t {
ALIGN_RIGHT = -1,
ALIGN_TOP = -1,
@@ -240,16 +264,16 @@ enum gfx_alignment_t {
enum gfx_line_mode_t {
- GFX_LINE_MODE_CORRECT, /* Scaled separately */
- GFX_LINE_MODE_FAST, /* Scaled by (xfact+yfact)/2 */
- GFX_LINE_MODE_FINE /* Always drawn at width 1 */
+ GFX_LINE_MODE_CORRECT, /**< Scaled separately */
+ GFX_LINE_MODE_FAST, /**< Scaled by (xfact+yfact)/2 */
+ GFX_LINE_MODE_FINE /**< Always drawn at width 1 */
};
enum gfx_brush_mode_t {
- GFX_BRUSH_MODE_SCALED, /* Just scale the brush pixels */
- GFX_BRUSH_MODE_ELLIPSES, /* Replace pixels with ellipses */
- GFX_BRUSH_MODE_RANDOM_ELLIPSES, /* Replace pixels with ellipses moved and re-scaled randomly */
- GFX_BRUSH_MODE_MORERANDOM /* Distribute randomly */
+ GFX_BRUSH_MODE_SCALED, /**< Just scale the brush pixels */
+ GFX_BRUSH_MODE_ELLIPSES, /**< Replace pixels with ellipses */
+ GFX_BRUSH_MODE_RANDOM_ELLIPSES, /**< Replace pixels with ellipses moved and re-scaled randomly */
+ GFX_BRUSH_MODE_MORERANDOM /**< Distribute randomly */
};
@@ -260,18 +284,19 @@ enum gfx_line_style_t {
enum gfx_rectangle_fill_t {
- GFX_SHADE_FLAT, /* Don't shade */
- GFX_SHADE_VERTICALLY, /* Shade vertically */
- GFX_SHADE_HORIZONTALLY /* Shade horizontally */
+ GFX_SHADE_FLAT, /**< Don't shade */
+ GFX_SHADE_VERTICALLY, /**< Shade vertically */
+ GFX_SHADE_HORIZONTALLY /**< Shade horizontally */
};
enum gfx_color_mode_t {
- GFX_COLOR_MODE_AUTO = 0, /* Auto-detect- handled by the gfxop library */
- GFX_COLOR_MODE_INDEX = 1, /* Index mode */
- GFX_COLOR_MODE_HIGH = 2, /* High color mode (15bpp or 16 bpp) */
- GFX_COLOR_MODE_TRUE = 4 /* True color mode (24 bpp padded to 32 bpp) */
+ GFX_COLOR_MODE_AUTO = 0, /**< Auto-detect- handled by the gfxop library */
+ GFX_COLOR_MODE_INDEX = 1, /**< Index mode */
+ GFX_COLOR_MODE_HIGH = 2, /**< High color mode (15bpp or 16 bpp) */
+ GFX_COLOR_MODE_TRUE = 4 /**< True color mode (24 bpp padded to 32 bpp) */
};
+/** @} */
} // End of namespace Sci
diff --git a/engines/sci/gfx/gfx_tools.h b/engines/sci/gfx/gfx_tools.h
index 8582dfa565..9b4ce32e89 100644
--- a/engines/sci/gfx/gfx_tools.h
+++ b/engines/sci/gfx/gfx_tools.h
@@ -23,9 +23,6 @@
*
*/
-/* SCI graphics subsystem helper functions */
-
-
#ifndef SCI_GFX_GFX_TOOLS_H
#define SCI_GFX_GFX_TOOLS_H
@@ -36,162 +33,198 @@
namespace Sci {
+/** @name SCI graphics subsystem helper functions */
+/** @{ */
+
enum gfx_xlate_filter_t {
GFX_XLATE_FILTER_NONE,
GFX_XLATE_FILTER_LINEAR,
GFX_XLATE_FILTER_TRILINEAR
};
+/**
+ * Allocates a new gfx_mode_t structure with the specified parameters
+ *
+ * @param[in] xfact Horizontal scaling factors
+ * @param[in] yfact Vertical scaling factors
+ * @param[in] format Pixel format description
+ * @param[in] palette Number of palette colors, 0 if we're not in palette mode
+ * @param[in] flags GFX_MODE_FLAG_* values ORred together, or just 0
+ * @return A newly allocated gfx_mode_t structure
+ */
gfx_mode_t *gfx_new_mode(int xfact, int yfact, const Graphics::PixelFormat &format, Palette *palette, int flags);
-/* Allocates a new gfx_mode_t structure with the specified parameters
-** Parameters: (int x int) xfact x yfact: Horizontal and vertical scaling factors
-** (Graphics::PixelFormat) format: pixel format description
-** (int) palette: Number of palette colors, 0 if we're not in palette mode
-** (int) flags: GFX_MODE_FLAG_* values ORred together, or just 0
-** Returns : (gfx_mode_t *) A newly allocated gfx_mode_t structure
-*/
-
+/**
+ * Clips a rect_t
+ *
+ * @param[in] box Pointer to the box to clip
+ * @param[in] maxx Maximum allowed width
+ * @param[in] maxy Maximum allowed height
+ */
void gfx_clip_box_basic(rect_t *box, int maxx, int maxy);
-/* Clips a rect_t
-** Parameters: (rect_t *) box: Pointer to the box to clip
-** (int x int) maxx, maxy: Maximum allowed width and height
-** Returns : (void)
-*/
-
+/**
+ * Frees all memory allocated by a mode structure
+ * @param[in] mode The mode to free
+ */
void gfx_free_mode(gfx_mode_t *mode);
-/* Frees all memory allocated by a mode structure
-** Parameters: (gfx_mode_t *) mode: The mode to free
-** Returns : (void)
-*/
-
+/**
+ * Creates a new pixmap structure
+ *
+ * The following fiels are initialized:
+ * ID, loop, cel, index_width, index_height, xl, yl, data <- NULL,
+ * alpha_map <- NULL, internal.handle <- 0, internal.info <- NULL,
+ * colors <- NULL, index_scaled <- 0
+ *
+ * @param[in] xl Width (in SCI coordinates) of the pixmap
+ * @param[in] yl Height (in SCI coordinates) of the pixmap
+ * @param[in] resid The pixmap's resource ID, or GFX_RESID_NONE
+ * @param[in] loop For views: The pixmap's loop number
+ * @param[in] cel For cels: The pixmap's cel number
+ * @return The newly allocated pixmap
+ */
gfx_pixmap_t *gfx_new_pixmap(int xl, int yl, int resid, int loop, int cel);
-/* Creates a new pixmap structure
-** Parameters: (int x int) xl x yl: The dimensions (in SCI coordinates) of the pixmap
-** (int) resid: The pixmap's resource ID, or GFX_RESID_NONE
-** (int) loop: For views: The pixmap's loop number
-** (int) cel: For cels: The pixmap's cel number
-** Returns : (gfx_pixmap_t *) The newly allocated pixmap
-** The following fiels are initialized:
-** ID, loop, cel, index_width, index_height, xl, yl, data <- NULL,
-** alpha_map <- NULL, internal.handle <- 0, internal.info <- NULL, colors <- NULL,
-** index_scaled <- 0
-*/
+/**
+ * Clones a pixmap, minus its index data, palette and driver-specific
+ * handles
+ *
+ * @param[in] pixmap The pixmap to clone
+ * @param[in] mode The mode to be applied to the pixmap
+ * @return The clone
+ */
gfx_pixmap_t *gfx_clone_pixmap(gfx_pixmap_t *pixmap, gfx_mode_t *mode);
-/* Clones a pixmap, minus its index data, palette and driver-specific handles
-** Parameters: (gfx_pixmap_t *) pixmap: The pixmap to clone
-** (gfx_mode_t *) mode: The mode to be applied to the pixmap
-** Returns : (gfx_pixmap_t *) The clone
-*/
-
+/**
+ * Allocates the index_data field of a pixmap
+ *
+ * @param[in] pixmap The pixmap to allocate for
+ * @return The pixmap
+ */
gfx_pixmap_t *gfx_pixmap_alloc_index_data(gfx_pixmap_t *pixmap);
-/* Allocates the index_data field of a pixmap
-** Parameters: (gfx_pixmap_t *) pixmap: The pixmap to allocate for
-** Returns : (gfx_pixmap_t *) pixmap
-*/
+/**
+ * Frees the index_data field of a pixmap
+ *
+ * @param[in] pixmap The pixmap to modify
+ * @return The pixmap
+ */
gfx_pixmap_t *gfx_pixmap_free_index_data(gfx_pixmap_t *pixmap);
-/* Frees the index_data field of a pixmap
-** Parameters: (gfx_pixmap_t *) pixmap: The pixmap to modify
-** Returns : (gfx_pixmap_t *) pixmap
-*/
+/**
+ * Allocates the data field of a pixmap
+ *
+ * @param[in] pixmap The pixmap to allocate for
+ * @param[in] mode The mode the memory is to be allocated for
+ * @return The pixmap
+ */
gfx_pixmap_t *gfx_pixmap_alloc_data(gfx_pixmap_t *pixmap, gfx_mode_t *mode);
-/* Allocates the data field of a pixmap
-** Parameters: (gfx_pixmap_t *) pixmap: The pixmap to allocate for
-** (gfx_mode_t *) mode: The mode the memory is to be allocated for
-** Returns : (gfx_pixmap_t *) pixmap
-*/
+/**
+ * Frees the memory allocated for a pixmap's data field
+ *
+ * @param[in] pixmap The pixmap to modify
+ * @return The pixmap
+ */
gfx_pixmap_t *gfx_pixmap_free_data(gfx_pixmap_t *pixmap);
-/* Frees the memory allocated for a pixmap's data field
-** Parameters: (gfx_pixmap_t *) pixmap: The pixmap to modify
-** Returns : (gfx_pixmap_t *) pixmap
-*/
+/**
+ * Frees all memory associated with a pixmap
+ *
+ * @param[in] pxm The pixmap to free
+ */
void gfx_free_pixmap(gfx_pixmap_t *pxm);
-/* Frees all memory associated with a pixmap
-** Parameters: (gfx_pixmap_t *) pxm: The pixmap to free
-** Returns : (void)
-*/
-
-void gfx_draw_line_pixmap_i(gfx_pixmap_t *pxm, Common::Point start, Common::Point end, int color);
-/* Draws a line to a pixmap's index data buffer
-** Parameters: (gfx_pixmap_t *) pxm: The pixmap to draw to
-** (Common::Point) start: Starting point of the line to draw
-** (Common::Point) end: End point of the line to draw
-** (int) color: The byte value to write
-** Returns : (void)
-** Remember, this only draws to the /index/ buffer, not to the drawable buffer.
-** The line is not clipped. Invalid x, y, x1, y1 values will result in memory corruption.
-*/
+/**
+ * Draws a line to a pixmap's index data buffer
+ *
+ * Remember, this only draws to the /index/ buffer, not to the drawable buffer.
+ * The line is not clipped. Invalid x, y, x1, y1 values will result in memory
+ * corruption.
+ *
+ * @param[in] pxm The pixmap to draw to
+ * @param[in] start Starting point of the line to draw
+ * @param[in] end End point of the line to draw
+ * @param[in] color The byte value to write
+ */
+void gfx_draw_line_pixmap_i(gfx_pixmap_t *pxm, Common::Point start,
+ Common::Point end, int color);
+
+/**
+ * Draws a filled rectangular area to a pixmap's index buffer
+ *
+ * This function only draws to the index buffer.
+ *
+ * @param[in] pxm The pixmap to draw to
+ * @param[in] box The box to fill
+ * @param[in] color The color to use for drawing
+ */
void gfx_draw_box_pixmap_i(gfx_pixmap_t *pxm, rect_t box, int color);
-/* Draws a filled rectangular area to a pixmap's index buffer
-** Parameters: (gfx_pixmap_t *) pxm: The pixmap to draw to
-** (rect_t) box: The box to fill
-** (int) color: The color to use for drawing
-** Returns : (void)
-** This function only draws to the index buffer.
-*/
+/**
+ * Copies part of a pixmap to another pixmap, with clipping
+ *
+ * @param[in] dest The destination pixmap
+ * @param[in] src The source pixmap
+ * @param[in] box The area to copy
+ */
void gfx_copy_pixmap_box_i(gfx_pixmap_t *dest, gfx_pixmap_t *src, rect_t box);
-/* Copies part of a pixmap to another pixmap, with clipping
-** Parameters: (gfx_pixmap_t *) dest: The destination pixmap
-** (gfx_pixmap_t *) src: The source pixmap
-** (rect_t) box: The area to copy
-** Returns : (void)
-*/
+/**
+ * Translates a pixmap's index data to drawable graphics data
+ *
+ * @param[in] pxm The pixmap to translate
+ * @param[in] mode The mode according which to scale
+ * @param[in] filter How to filter the data
+ */
void gfx_xlate_pixmap(gfx_pixmap_t *pxm, gfx_mode_t *mode, gfx_xlate_filter_t filter);
-/* Translates a pixmap's index data to drawable graphics data
-** Parameters: (gfx_pixmap_t *) pxm: The pixmap to translate
-** (gfx_mode_t *) mode: The mode according which to scale
-** (gfx_xlate_filter_t) filter: How to filter the data
-** Returns : (void)
-*/
-#define GFX_CROSSBLIT_FLAG_DATA_IS_HOMED (1<<0)
-/* Means that the first byte in the visual data refers to the
-** point corresponding to (dest.x, dest.y) */
+#define GFX_CROSSBLIT_FLAG_DATA_IS_HOMED (1<<0) /**< Means that the first byte in the visual data refers to the point corresponding to (dest.x, dest.y) */
+/**
+ * Transfers the non-transparent part of a pixmap to a linear pixel
+ * buffer.
+ *
+ * A 'linear buffer' in this context means a data buffer containing an entire
+ * screen (visual or priority), with fixed offsets between each data row, and
+ * linear access.
+ *
+ * @param[in] mode The graphics mode of the target buffer
+ * @param[in] pxm The pixmap to transfer
+ * @param[in] priority The pixmap's priority
+ * @param[in] src_coords The source coordinates within the pixmap
+ * @param[in] dest_coords The destination coordinates (no scaling)
+ * @param[in] dest Memory position of the upper left pixel of
+ * the linear pixel buffer
+ * @param[in] dest_line_width Byte offset of the very first pixel in the
+ * second line of the linear pixel buffer,
+ * relative to dest.
+ * @param[in] priority_dest Destination buffer for the pixmap's priority
+ * values
+ * @param[in] priority_line_width Byte offset of the first pixel in the second
+ * line of the priority buffer
+ * @param[in] priority_skip Amount of bytes allocated by each priority
+ * value
+ * @param[in] flags Any crossblit flags
+ * @return GFX_OK, or GFX_ERROR if the specified mode
+ * was invalid or unsupported
+ */
int gfx_crossblit_pixmap(gfx_mode_t *mode, gfx_pixmap_t *pxm, int priority,
rect_t src_coords, rect_t dest_coords, byte *dest, int dest_line_width,
byte *priority_dest, int priority_line_width, int priority_skip, int flags);
-/* Transfers the non-transparent part of a pixmap to a linear pixel buffer
-** Parameters: (gfx_mode_t *) mode: The graphics mode of the target buffer
-** (gfx_pixmap_t *) pxm: The pixmap to transfer
-** (int priority): The pixmap's priority
-** (rect_t) src_coords: The source coordinates within the pixmap
-** (rect_t) dest_coords: The destination coordinates (no scaling)
-** (byte *) dest: Memory position of the upper left pixel of the
-** linear pixel buffer
-** (int) dest_line_width: Byte offset of the very first pixel in the
-** second line of the linear pixel buffer,
-** relative to dest.
-** (byte *) priority_dest: Destination buffer for the pixmap's priority
-** values
-** (int) priority_line_width: Byte offset of the first pixel in the
-** second line of the priority buffer
-** (int) priority_skip: Amount of bytes allocated by each priority value
-** (int) flags: Any crossblit flags
-** Returns : (int) GFX_OK, or GFX_ERROR if the specified mode was invalid or unsupported
-** A 'linear buffer' in this context means a data buffer containing an entire
-** screen (visual or priority), with fixed offsets between each data row, and
-** linear access.
-*/
+
+/**
+ * Scales the index data associated with a pixmap
+ *
+ * @param[in] pixmap The pixmap whose index data should be scaled
+ * @param[in] mode The mode to scale it to
+ * @return The pixmap
+ */
gfx_pixmap_t *gfx_pixmap_scale_index_data(gfx_pixmap_t *pixmap, gfx_mode_t *mode);
-/* Scales the index data associated with a pixmap
-** Parameters: (gfx_pixmap_t *) pixmap: The pixmap whose index data should be scaled
-** (gfx_mode_t *) mode: The mode to scale it to
-** Returns : (gfx_pixmap_t *) pixmap
-*/
+/** @} */
} // End of namespace Sci
#endif // SCI_GFX_GFX_TOOLS_H
diff --git a/engines/sci/gfx/gfx_widgets.h b/engines/sci/gfx/gfx_widgets.h
index bd884ffbb4..80129152cb 100644
--- a/engines/sci/gfx/gfx_widgets.h
+++ b/engines/sci/gfx/gfx_widgets.h
@@ -23,7 +23,6 @@
*
*/
-/* Graphical state management */
#ifndef SCI_GFX_GFX_WIDGETS_H
#define SCI_GFX_GFX_WIDGETS_H
@@ -34,6 +33,8 @@
#include "sci/gfx/operations.h"
namespace Sci {
+/** @name Widget Graphical State Management */
+/** @{ */
struct GfxState;
struct GfxBox;
@@ -155,241 +156,324 @@ extern Common::Point gfxw_point_zero;
/*-- Primitive types --*/
+/**
+ * Creates a new box
+ *
+ * The graphics state, if non-NULL, is used here for some optimizations.
+ *
+ * @param[in] state The (optional) state
+ * @param[in] area The box's dimensions, relative to its container
+ * widget
+ * @param[in] color1 The primary color
+ * @param[in] color2 The secondary color (ignored if shading is disabled)
+ * @param[in] shade_type The shade type for the box
+ * @return The resulting box widget
+ */
GfxBox *gfxw_new_box(GfxState *state, rect_t area, gfx_color_t color1, gfx_color_t color2, gfx_box_shade_t shade_type);
-/* Creates a new box
-** Parameters: (GfxState *) state: The (optional) state
-** (rect_t) area: The box's dimensions, relative to its container widget
-** (gfx_color_t) color1: The primary color
-** (gfx_color_t) color1: The secondary color (ignored if shading is disabled)
-** (gfx_box_shade_t) shade_type: The shade type for the box
-** Returns : (GfxBox *) The resulting box widget
-** The graphics state- if non-NULL- is used here for some optimizations.
-*/
-GfxPrimitive *gfxw_new_rect(rect_t rect, gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style);
-/* Creates a new rectangle
-** Parameters: (rect_t) rect: The rectangle area
-** (gfx_color_t) color: The rectangle's color
-** (gfx_line_mode_t) line_mode: The line mode for the lines that make up the rectangle
-** (gfx_line_style_t) line_style: The rectangle's lines' style
-** Returns : (GfxPrimitive *) The newly allocated rectangle widget (a Primitive)
-*/
+/**
+ * Creates a new rectangle
+ *
+ * @param[in] rect The rectangle area
+ * @param[in] color The rectangle's color
+ * @param[in] line_mode The line mode for the lines that make up the
+ * rectangle
+ * @param[in] line_style The rectangle's lines' style
+ * @return The newly allocated rectangle widget (a Primitive)
+ */
+GfxPrimitive *gfxw_new_rect(rect_t rect, gfx_color_t color,
+ gfx_line_mode_t line_mode, gfx_line_style_t line_style);
-GfxPrimitive *gfxw_new_line(Common::Point start, Common::Point end, gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style);
-/* Creates a new line
-** Parameters: (Common::Point * Common::Point) (start, line): The line origin and end point
-** (gfx_color_t) color: The line's color
-** (gfx_line_mode_t) line_mode: The line mode to use for drawing
-** (gfx_line_style_t) line_style: The line style
-** Returns : (GfxPrimitive *) The newly allocated line widget (a Primitive)
-*/
+/**
+ * Creates a new line
+ *
+ * @param[in] start The line's origin
+ * @param[in] end The line's end point
+ * @param[in] color The line's color
+ * @param[in] line_mode The line mode to use for drawing
+ * @param[in] line_style The line style
+ * @return The newly allocated line widget (a Primitive)
+ */
+GfxPrimitive *gfxw_new_line(Common::Point start, Common::Point end,
+ gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style);
+/** View flags */
+enum {
+ GFXW_VIEW_FLAG_STATIC = (1 << 0), /**< Whether the view should be static */
+ GFXW_VIEW_FLAG_DONT_MODIFY_OFFSET = (1 << 1) /**< Whether the view should _not_ apply its x/y offset modifyers */
+};
-/* Whether the view should be static */
-#define GFXW_VIEW_FLAG_STATIC (1 << 0)
-
-/* Whether the view should _not_ apply its x/y offset modifyers */
-#define GFXW_VIEW_FLAG_DONT_MODIFY_OFFSET (1 << 1)
-
-GfxView *gfxw_new_view(GfxState *state, Common::Point pos, int view, int loop, int cel, int palette, int priority, int control,
- gfx_alignment_t halign, gfx_alignment_t valign, int flags);
-/* Creates a new view (a cel, actually)
-** Parameters: (GfxState *) state: The graphics state
-** (Common::Point) pos: The position to place the view at
-** (int x int x int) view, loop, cel: The global cel ID
-** (int) priority: The priority to use for drawing, or -1 for none
-** (int) control: The value to write to the control map, or -1 for none
-** (gfx_alignment_t x gfx_alignment_t) halign, valign: Horizontal and vertical
-** cel alignment
-** (int) flags: Any combination of GFXW_VIEW_FLAGs
-** Returns : (gfxw_cel_t *) A newly allocated cel according to the specs
-*/
+/**
+ * Creates a new view (a cel, actually)
+ *
+ * @param[in] state The graphics state
+ * @param[in] pos The position to place the view at
+ * @param[in] view The global cel ID
+ * @param[in] loop The global cel ID
+ * @param[in] cel The global cel ID
+ * @param[in] palette The palette to use
+ * @param[in] priority The priority to use for drawing, or -1 for none
+ * @param[in] control The value to write to the control map, or -1 for none
+ * @param[in] halign Horizontal cel alignment
+ * @param[in] valign Vertical cel alignment
+ * @param[in] flags Any combination of GFXW_VIEW_FLAGs
+ * @return A newly allocated cel according to the specs
+ */
+GfxView *gfxw_new_view(GfxState *state, Common::Point pos, int view, int loop,
+ int cel, int palette, int priority, int control, gfx_alignment_t halign,
+ gfx_alignment_t valign, int flags);
-GfxDynView *gfxw_new_dyn_view(GfxState *state, Common::Point pos, int z, int view, int loop, int cel, int palette,
- int priority, int control, gfx_alignment_t halign, gfx_alignment_t valign, int sequence);
-/* Creates a new dyn view
-** Parameters: (GfxState *) state: The graphics state
-** (Common::Point) pos: The position to place the dynamic view at
-** (int) z: The z coordinate
-** (int x int x int) view, loop, cel: The global cel ID
-** (int) priority: The priority to use for drawing, or -1 for none
-** (int) control: The value to write to the control map, or -1 for none
-** (gfx_alignment_t x gfx_alignment_t) halign, valign: Horizontal and vertical
-** cel alignment
-** (int) sequence: Sequence number: When sorting dynviews, this number is
-** considered last for sorting (ascending order)
-** Returns : (gfxw_cel_t *) A newly allocated cel according to the specs
-** Dynamic views are non-pic views with a unique global identifyer. This allows for drawing
-** optimizations when they move or change shape.
-*/
-GfxText *gfxw_new_text(GfxState *state, rect_t area, int font, const char *text, gfx_alignment_t halign,
- gfx_alignment_t valign, gfx_color_t color1, gfx_color_t color2,
- gfx_color_t bgcolor, int flags);
-/* Creates a new text widget
-** Parameters: (GfxState *) state: The state the text is to be calculated from
-** (rect_t) area: The area the text is to be confined to (the yl value is only
-** relevant for text aligment, though)
-** (int) font: The number of the font to use
-** (gfx_alignment_t x gfx_alignment_t) halign, valign: Horizontal and
-** vertical text alignment
-** (gfx_color_t x gfx_color_t) color1, color2: Text foreground colors (if not equal,
-** The foreground is dithered between them)
-** (gfx_color_t) bgcolor: Text background color
-** (int) flags: GFXR_FONT_FLAGs, orred together (see gfx_resource.h)
-** Returns : (GfxText *) The resulting text widget
-*/
+/**
+ * Creates a new dyn view
+ *
+ * Dynamic views are non-pic views with a unique global identifyer. This allows for drawing optimizations when they move or change shape.
+ *
+ * @param[in] state The graphics state
+ * @param[in] pos The position to place the dynamic view at
+ * @param[in] z The z coordinate
+ * @param[in] view The global cel ID
+ * @param[in] loop The global cel ID
+ * @param[in] cel The global cel ID
+ * @param[in] palette The palette to use
+ * @param[in] priority The priority to use for drawing, or -1 for none
+ * @param[in] control The value to write to the control map, or -1 for none
+ * @param[in] halign Horizontal cel alignment
+ * @param[in] valign Vertical cel alignment
+ * @param[in] sequence Sequence number: When sorting dynviews, this number is
+ * considered last for sorting (ascending order)
+ * @return A newly allocated cel according to the specs
+ */
+GfxDynView *gfxw_new_dyn_view(GfxState *state, Common::Point pos, int z,
+ int view, int loop, int cel, int palette, int priority, int control,
+ gfx_alignment_t halign, gfx_alignment_t valign, int sequence);
+/**
+ * Creates a new text widget
+ *
+ * @param[in] state The state the text is to be calculated from
+ * @param[in] area The area the text is to be confined to (the yl value is
+ * only relevant for text aligment, though)
+ * @param[in] font The number of the font to use
+ * @param[in] text String to put in text widget
+ * @param[in] halign Horizontal text alignment
+ * @param[in] valign Vertical text alignment
+ * @param[in] color1 Text foreground colors (if not equal, the foreground is
+ * dithered between them)
+ * @param[in] color2 Text foreground colors (if not equal, the foreground is
+ * dithered between them)
+ * @param[in] bgcolor Text background color
+ * @param[in] flags GFXR_FONT_FLAGs, orred together (see gfx_resource.h)
+ * @return The resulting text widget
+ */
+GfxText *gfxw_new_text(GfxState *state, rect_t area, int font, const char *text,
+ gfx_alignment_t halign, gfx_alignment_t valign, gfx_color_t color1,
+ gfx_color_t color2, gfx_color_t bgcolor, int flags);
+
+/**
+ * Determines text widget meta-information
+ *
+ * @param[in] state The state to operate on
+ * @param[in] text The widget to query
+ * @param[out] lines_nr Number of lines used in the text
+ * @param[out] lineheight Pixel height (SCI scale) of each text line
+ * @param[out] offset Pixel offset (SCI scale) of the space after the last
+ * character in the last line
+ */
void gfxw_text_info(GfxState *state, GfxText *text, int *lines_nr,
int *lineheight, int *offset);
-/* Determines text widget meta-information
-** Parameters: (GfxState *) state: The state to operate on
-** (gfx_text_t *) text: The widget to query
-** Returns : (int) lines_nr: Number of lines used in the text
-** (int) lineheight: Pixel height (SCI scale) of each text line
-** (int) offset: Pixel offset (SCI scale) of the space after the
-** last character in the last line
-*/
+/**
+ * Sets a widget's ID
+ *
+ * A widget ID is unique within the container it is stored in, if and only if it
+ * was added to that container with gfxw_add(). This function handles widget ==
+ * NULL gracefully (by doing nothing and returning NULL).
+ *
+ * @param[in] widget The widget whose ID should be set
+ * @param[in] ID The ID to set
+ * @param[in] subID The ID to set
+ * @return The widget
+ */
GfxWidget *gfxw_set_id(GfxWidget *widget, int ID, int subID);
-/* Sets a widget's ID
-** Parmaeters: (GfxWidget *) widget: The widget whose ID should be set
-** (int x int) ID, subID: The ID to set
-** Returns : (GfxWidget *) widget
-** A widget ID is unique within the container it is stored in, if and only if it was
-** added to that container with gfxw_add().
-** This function handles widget = NULL gracefully (by doing nothing and returning NULL).
-*/
+/**
+ * Finds a widget with a specific ID in a container and removes it from there
+ *
+ * Search is non-recursive; widgets with IDs hidden in subcontainers will not
+ * be found.
+ *
+ * @param[in] container The container to search in
+ * @param[in] ID The ID to look for
+ * @param[in] subID The subID to look for, or GFXW_NO_ID for any
+ * @return The resulting widget or NULL if no match was found
+ */
GfxWidget *gfxw_remove_id(GfxContainer *container, int ID, int subID);
-/* Finds a widget with a specific ID in a container and removes it from there
-** Parameters: (GfxContainer *) container: The container to search in
-** (int) ID: The ID to look for
-** (int) subID: The subID to look for, or GFXW_NO_ID for any
-** Returns : (GfxWidget *) The resulting widget or NULL if no match was found
-** Search is non-recursive; widgets with IDs hidden in subcontainers will not be found.
-*/
+/**
+ * Initializes a dyn view's interpreter attributes
+ *
+ * @param[in] widget The widget affected
+ * @param[in] under_bits Interpreter-dependant data
+ * @param[in] under_bitsp Interpreter-dependant data
+ * @param[in] signal Interpreter-dependant data
+ * @param[in] signalp Interpreter-dependant data
+ * @return The widget
+ */
+GfxDynView *gfxw_dyn_view_set_params(GfxDynView *widget, int under_bits,
+ const ObjVarRef& under_bitsp, int signal, const ObjVarRef& signalp);
-GfxDynView *gfxw_dyn_view_set_params(GfxDynView *widget, int under_bits, const ObjVarRef& under_bitsp, int signal, const ObjVarRef& signalp);
-/* Initializes a dyn view's interpreter attributes
-** Parameters: (GfxDynView *) widget: The widget affected
-** (int x void * x int x void *) under_bits, inder_bitsp, signal, signalp: Interpreter-dependant data
-** Returns : (GfxDynView *) widget
-*/
-
+/**
+ * Makes a widget invisible without removing it from the list of widgets
+ *
+ * Has no effect on invisible widgets
+ *
+ * @param[in] widget The widget to invisibilize
+ * @return The widget
+ */
GfxWidget *gfxw_hide_widget(GfxWidget *widget);
-/* Makes a widget invisible without removing it from the list of widgets
-** Parameters: (GfxWidget *) widget: The widget to invisibilize
-** Returns : (GfxWidget *) widget
-** Has no effect on invisible widgets
-*/
+/**
+ * Makes an invisible widget reappear
+ *
+ * Does not affect visible widgets
+ *
+ * @param[in] widget The widget to show again
+ * @return The widget
+ */
GfxWidget *gfxw_show_widget(GfxWidget *widget);
-/* Makes an invisible widget reappear
-** Parameters: (GfxWidget *) widget: The widget to show again
-** Returns : (GfxWidget *) widget
-** Does not affect visible widgets
-*/
+/**
+ * Marks a widget as "abandoned"
+ *
+ * @param[in] widget The widget to abandon
+ * @return The widget
+ */
GfxWidget *gfxw_abandon_widget(GfxWidget *widget);
-/* Marks a widget as "abandoned"
-** Parameters: (GfxWidget *) widget: The widget to abandon
-** Returns : (GfxWidget *) widget
-*/
-
-/*-- Container types --*/
-#define GFXW_LIST_UNSORTED 0
-#define GFXW_LIST_SORTED 1
+/** Container types */
+enum {
+ GFXW_LIST_UNSORTED = 0,
+ GFXW_LIST_SORTED = 1
+};
+/**
+ * Creates a new list widget
+ *
+ * List widgets are also referred to as Display Lists.
+ *
+ * @param[in] area The area covered by the list (absolute position)
+ * @param[in] sorted Whether the list should be a sorted list
+ * @return A newly allocated list widget
+ */
GfxList *gfxw_new_list(rect_t area, int sorted);
-/* Creates a new list widget
-** Parameters: (rect_t) area: The area covered by the list (absolute position)
-** (int) sorted: Whether the list should be a sorted list
-** Returns : (GfxList *) A newly allocated list widget
-** List widgets are also referred to as Display Lists.
-*/
+/**
+ * Retrieves the default port from a visual
+ *
+ * The 'default port' is the last port to be instantiated; usually the topmost
+ * or highest-ranking port.
+ *
+ * @param[in] visual The visual the port should be retrieved from
+ * @return The default port, or NULL if no port is present
+ */
GfxPort *gfxw_find_default_port(GfxVisual *visual);
-/* Retrieves the default port from a visual
-** Parameters: (GfxVisual *) visual: The visual the port should be retrieved from
-** Returns : (GfxPort *) The default port, or NULL if no port is present
-** The 'default port' is the last port to be instantiated; usually the topmost
-** or highest-ranking port.
-*/
+/**
+ * Sets rectangle to be restored upon port removal
+ *
+ * @param[in] visual The visual to operate on
+ * @param[in] window The affected window
+ * @param[in] auto_rect The area to restore
+ */
void gfxw_port_set_auto_restore(GfxVisual *visual, GfxPort *window, rect_t auto_rect);
-/* Sets rectangle to be restored upon port removal
-** Parameters: (state_t *) s: The state to operate on
-** (GfxPort *) window: The affected window
-** (rect_t) auto_rect: The area to restore
-** Returns : (void)
-*/
+/**
+ * Removes a port from a visual
+ *
+ * @param[in] visual The visual the port should be removed from
+ * @param[in] port The port to remove
+ * @return port's parent port, or NULL if it had none
+ */
GfxPort *gfxw_remove_port(GfxVisual *visual, GfxPort *port);
-/* Removes a port from a visual
-** Parameters: (GfxVisual *) visual: The visual the port should be removed from
-** (GfxPort *) port: The port to remove
-** Returns : (GfxPort *) port's parent port, or NULL if it had none
-*/
+/**
+ * Removes the widget from the specified port
+ *
+ * @param[in] container The container it should be removed from
+ * @param[in] widget The widget to remove
+ */
void gfxw_remove_widget_from_container(GfxContainer *container, GfxWidget *widget);
-/* Removes the widget from the specified port
-** Parameters: (GfxContainer *) container: The container it should be removed from
-** (GfxWidget *) widget: The widget to remove
-** Returns : (void)
-*/
+/**
+ * Makes a "snapshot" of a visual
+ *
+ * It's not really a full qualified snaphot, though. See gfxw_restore_snapshot
+ * for a full discussion. This operation also increases the global serial number
+ * counter by one.
+ *
+ * @param[in] visual The visual a snapshot is to be taken of
+ * @param[in] area The area a snapshot should be taken of
+ * @return The resulting, newly allocated snapshot
+ */
gfxw_snapshot_t *gfxw_make_snapshot(GfxVisual *visual, rect_t area);
-/* Makes a "snapshot" of a visual
-** Parameters: (GfxVisual *) visual: The visual a snapshot is to be taken of
-** (rect_t) area: The area a snapshot should be taken of
-** Returns : (gfxw_snapshot_t *) The resulting, newly allocated snapshot
-** It's not really a full qualified snaphot, though. See gfxw_restore_snapshot
-** for a full discussion.
-** This operation also increases the global serial number counter by one.
-*/
+/**
+ * Predicate to test whether a widget would be destroyed by applying a snapshot
+ *
+ * @param[in] snapshot The snapshot to test against
+ * @param[in] widget The widget to test
+ * @return An appropriate boolean value
+ */
int gfxw_widget_matches_snapshot(gfxw_snapshot_t *snapshot, GfxWidget *widget);
-/* Predicate to test whether a widget would be destroyed by applying a snapshot
-** Parameters: (gfxw_snapshot_t *) snapshot: The snapshot to test against
-** (GfxWidget *) widget: The widget to test
-** Retunrrs : (int) An appropriate boolean value
-*/
+/**
+ * Restores a snapshot to a visual
+ *
+ * The snapshot is not really restored; only more recent widgets touching
+ * the snapshotted area are destroyed.
+ *
+ * @param[in] visual The visual to operate on
+ * @param[in] snapshot The snapshot to restore
+ * @return The snapshot (still needs to be freed)
+ */
gfxw_snapshot_t *gfxw_restore_snapshot(GfxVisual *visual, gfxw_snapshot_t *snapshot);
-/* Restores a snapshot to a visual
-** Parameters: (GfxVisual *) visual: The visual to operate on
-** (gfxw_snapshot_t *) snapshot: The snapshot to restore
-** Returns : (gfxw_snapshot_t *) snapshot (still needs to be freed)
-** The snapshot is not really restored; only more recent widgets touching
-** the snapshotted area are destroyed.
-*/
+/**
+ * As widget->widfree(widget), but destroys all overlapping widgets
+ *
+ * This operation calls widget->widfree(widget), but it also destroys all
+ * widgets with a higher or equal priority drawn after this widget.
+ *
+ * @param[in] widget The widget to use
+ */
void gfxw_annihilate(GfxWidget *widget);
-/* As widget->widfree(widget), but destroys all overlapping widgets
-** Parameters: (GfxWidget *) widget: The widget to use
-** Returns : (void)
-** This operation calls widget->widfree(widget), but it also destroys
-** all widgets with a higher or equal priority drawn after this widget.
-*/
+/**
+ * Turns a dynview into a picview
+ *
+ * The only changes are in function and type variables, actually.
+ *
+ * @param[in] dynview The victim
+ * @return The victim, after his transformation
+ */
GfxDynView *gfxw_picviewize_dynview(GfxDynView *dynview);
-/* Turns a dynview into a picview
-** Parameters: (GfxDynView *) dynview: The victim
-** Returns : (GfxDynView *) The victim, after his transformation
-** The only changes are in function and type variables, actually.
-*/
-void gfxw_port_auto_restore_background(GfxVisual *visual, GfxPort *window, rect_t auto_rect);
-/* Tags a window widget as automatically restoring the visual background upon removal
-** Parameters: (gfx_visual_t *) visual: The base visual
-** (GfxPort *) window: The window to tag
-** (rect_t) auto_rect: The background to remember
-** Also records the specified background rectangle, for later recovery
-*/
+/**
+ * Tags a window widget as automatically restoring the visual background
+ * upon removal.
+ *
+ * Also records the specified background rectangle, for later recovery.
+ *
+ * @param[in] visual The base visual
+ * @param[in] window The window to tag
+ * @param[in] auto_rect The background to remember
+
+ */
+void gfxw_port_auto_restore_background(GfxVisual *visual, GfxPort *window,
+ rect_t auto_rect);
+/** @} */
} // End of namespace Sci
#endif // SCI_GFX_GFX_WIDGETS_H
diff --git a/engines/sci/gfx/menubar.h b/engines/sci/gfx/menubar.h
index 02d99332d9..44ecd8f1bb 100644
--- a/engines/sci/gfx/menubar.h
+++ b/engines/sci/gfx/menubar.h
@@ -50,9 +50,7 @@ struct EngineState;
/* The number of pixels added to the left of the first menu */
#define MENU_BOX_CENTER_PADDING 10
-/* Number of pixels to leave in between the left and the right centered text content in boxes
-** that use right centered content
-*/
+/* Number of pixels to leave in between the left and the right centered text content in boxes that use right centered content */
#define MENU_BOX_LEFT_PADDING 0
/* Number of pixels to pad to the left */
@@ -88,16 +86,16 @@ enum MenuType {
class MenuItem : public Common::Serializable {
public:
- MenuType _type; /* Normal or hbar */
- Common::String _keytext; /* right-centered part of the text (the key) */
+ MenuType _type; /**< Normal or hbar */
+ Common::String _keytext; /**< right-centered part of the text (the key) */
int _flags;
- byte _said[MENU_SAID_SPEC_SIZE]; /* Said spec for this item */
+ byte _said[MENU_SAID_SPEC_SIZE]; /**< Said spec for this item */
reg_t _saidPos;
Common::String _text;
reg_t _textPos;
- int _modifiers; /* Hotkey for this item */
- int _key; /* Hotkey for this item */
+ int _modifiers; /**< Hotkey for this item */
+ int _key; /**< Hotkey for this item */
int _enabled;
int _tag;
@@ -108,9 +106,10 @@ public:
/**
* Determines whether a message/modifiers key pair matches a menu item's key parameters.
- * @param message The message to match
- * @param modifiers The modifier flags to match
- * @return true on match, false otherwise
+ *
+ * @param[in] message The message to match
+ * @param[in] modifiers The modifier flags to match
+ * @return true on match, false otherwise
*/
bool matchKey(int message, int modifiers);
};
@@ -156,59 +155,68 @@ public:
/**
* Adds a menu to the menubar.
- * Parameters: (GfxState *) state: The state the fonts are stored in
- * (char *) title: The menu title
- * (char *) entries: A string of menu entries
- * (int) font: The font which is to be used for drawing
- * (reg_t) entries_base: Segmented VM address of the entries string
- * Returns : (void)
+ *
* The menu entries use the following special characters:
* '`' : Right justify the following part
* ':' : End of this entry
* '#' : Function key (replaced by 'F')
* '^' : Control key (replaced by \002, which looks like "CTRL")
* '=' : Initial tag value
- * and the special string "--!", which represents a horizontal bar in the menu.
+ * and the special string "--!", which represents a horizontal bar in the
+ * menu.
+ *
+ * @param[in] state The state the fonts are stored in
+ * @param[in] title The menu title
+ * @param[in] entries A string of menu entries
+ * @param[in] font The font which is to be used for drawing
+ * @param[in] entries_base Segmented VM address of the entries string
*/
void addMenu(GfxState *state, const char *title, const char *entries, int font, reg_t entries_base);
/**
- * Sets the (currently unidentified) foo and bar values.
- * Parameters: (state_t *) s: The current state
- * (int) menu: The menu number to edit
- * (int) item: The menu item to change
- * (int) attribute: The attribute to modify
- * (int) value: The value the attribute should be set to
- * Returns : (int) 0 on success, 1 if either menu or item were invalid
+ * Sets the attributes for a menu item.
+ *
+ * @param[in] s The current state
+ * @param[in] menu The menu number to edit
+ * @param[in] item The menu item to change
+ * @param[in] attribute The attribute to modify
+ * @param[in] value The value the attribute should be set to
+ * @return 0 on success, 1 if either menu or item were invalid
*/
int setAttribute(EngineState *s, int menu, int item, int attribute, reg_t value);
/**
- * Sets the (currently unidentified) foo and bar values.
- * Parameters: (int) menu: The menu number
- * (int) item: The menu item to read
- * (int) attribute: The attribute to read from
- * Returns : (int) The attribute value, or -1 on error
+ * Gets an attribute for a menuitem.
+ *
+ * @param[in] menu The menu number
+ * @param[in] item The menu item to read
+ * @param[in] attribute The attribute to read from
+ * @return The attribute value, or -1 on error
*/
reg_t getAttribute(int menu, int item, int attribute) const;
/**
* Determines whether the specified menu entry may be activated.
- * @return true if the menu item may be selected, false otherwise
+ *
+ * @return true if the menu item may be selected, false otherwise
*/
bool itemValid(int menu, int item) const;
/**
* Maps the pointer position to a (menu,item) tuple.
- * @param pointerPos the current pointer position
- * @param menu_nr the current menu (updated by this function if necessary)
- * @param item_nr the current menu item (updated by this function if necessary)
- * @param port the port of the currently active menu (if any)
- * @return true if the pointer is outside a valid port, false otherwise.
+ *
+ * @param[in] pointerPos the current pointer position
+ * @param[in] menu_nr the current menu (updated by this function if
+ * necessary)
+ * @param[in] item_nr the current menu item (updated by this function
+ * if necessary)
+ * @param[in] port the port of the currently active menu (if any)
+ * @return true if the pointer is outside a valid port,
+ * false otherwise.
*/
bool mapPointer(const Common::Point &pointerPos, int &menu_nr, int &item_nr, GfxPort *port) const;
diff --git a/engines/sci/gfx/operations.h b/engines/sci/gfx/operations.h
index d559d3b6d2..491b485da0 100644
--- a/engines/sci/gfx/operations.h
+++ b/engines/sci/gfx/operations.h
@@ -93,10 +93,10 @@ typedef Common::List<rect_t> DirtyRectList;
struct GfxState {
gfx_options_t *options;
- Common::Point pointer_pos; /* Mouse pointer coordinates */
+ Common::Point pointer_pos; /**< Mouse pointer coordinates */
- rect_t clip_zone_unscaled; /* The current UNSCALED clipping zone */
- rect_t clip_zone; /* The current SCALED clipping zone; a cached scaled version of clip_zone_unscaled */
+ rect_t clip_zone_unscaled; /**< The current UNSCALED clipping zone */
+ rect_t clip_zone; /**< The current SCALED clipping zone; a cached scaled version of clip_zone_unscaled */
GfxDriver *driver;
@@ -104,543 +104,640 @@ struct GfxState {
GfxResManager *gfxResMan;
- gfx_pixmap_t *priority_map; /* back buffer priority map (unscaled) */
- gfx_pixmap_t *static_priority_map; /* static buffer priority map (unscaled) */
- gfx_pixmap_t *control_map; /* back buffer control map (only exists unscaled in the first place) */
+ gfx_pixmap_t *priority_map; /**< back buffer priority map (unscaled) */
+ gfx_pixmap_t *static_priority_map; /**< static buffer priority map (unscaled) */
+ gfx_pixmap_t *control_map; /**< back buffer control map (only exists unscaled in the first place) */
- int tag_mode; /* Set to 1 after a new pic is drawn and the resource manager
- ** has tagged all resources. Reset after the next front buffer
- ** update is done, when all resources that are still tagged are
- ** flushed. */
+ int tag_mode; /**< Set to 1 after a new pic is drawn and the resource manager has tagged all resources. Reset after the next front buffer update is done, when all resources that are still tagged are flushed. */
- int disable_dirty; /* Set to 1 to disable dirty rect accounting */
+ int disable_dirty; /**< Set to 1 to disable dirty rect accounting */
- int pic_nr; /* Number of the current pic */
- int palette_nr; /* Palette number of the current pic */
+ int pic_nr; /**< Number of the current pic */
+ int palette_nr; /**< Palette number of the current pic */
Common::List<sci_event_t> _events;
- gfx_pixmap_t *fullscreen_override; /* An optional override picture which must have unscaled
- ** full-screen size, which overrides all other visibility, and
- ** which is generally slow */
+ gfx_pixmap_t *fullscreen_override; /**< An optional override picture which must have unscaled full-screen size, which overrides all other visibility, and which is generally slow */
- gfxr_pic_t *pic, *pic_unscaled; /* The background picture and its unscaled equivalent */
- rect_t pic_port_bounds; /* Picture port bounds */
+ gfxr_pic_t *pic, *pic_unscaled; /**< The background picture and its unscaled equivalent */
+ rect_t pic_port_bounds; /**< Picture port bounds */
- DirtyRectList _dirtyRects; /* Dirty rectangles */
+ DirtyRectList _dirtyRects; /**< Dirty rectangles */
};
-/**************************/
-/* Fundamental operations */
-/**************************/
-
-int gfxop_init(int version, bool isVGA, GfxState *state, gfx_options_t *options, ResourceManager *resManager,
- int xfact = 1, int yfact = 1, gfx_color_mode_t bpp = GFX_COLOR_MODE_INDEX);
-/* Initializes a graphics mode
-** Parameters: (int) version: The interpreter version
-** (GfxState *) state: The state to initialize
-** (int x int) xfact, yfact: Horizontal and vertical scale factors
-** (gfx_color_mode_t) bpp: Bytes per pixel to initialize with, or
-** 0 (GFX_COLOR_MODE_AUTO) to auto-detect
-** (gfx_options_t *) options: Rendering options
-** (void *) misc_info: Additional information for the interpreter
-** part of the resource loader
-** Returns : (int) GFX_OK on success, GFX_ERROR if that particular mode is
-** unavailable, or GFX_FATAL if the graphics driver is unable
-** to provide any useful graphics support
-*/
+/** @name Fundamental operations */
+/** @{ */
+
+/**
+ * Initializes a graphics mode.
+ *
+ * @param[in] version The interpreter version
+ * @param[in] isVGA true if using VGA resolution
+ * @param[in] state The state to initialize
+ * @param[in] xfact Horizontal scale factor
+ * @param[in] yfact Vertical scale factors
+ * @param[in] bpp Bytes per pixel to initialize with, or 0
+ * (GFX_COLOR_MODE_AUTO) to auto-detect
+ * @param[in] options Rendering options
+ * @param[in] resManager Resource manager to use
+ * @return GFX_OK on success, GFX_ERROR if that particular mode
+ * is unavailable, or GFX_FATAL if the graphics driver
+ * is unable to provide any useful graphics support
+ */
+int gfxop_init(int version, bool isVGA, GfxState *state, gfx_options_t *options,
+ ResourceManager *resManager, int xfact = 1, int yfact = 1,
+ gfx_color_mode_t bpp = GFX_COLOR_MODE_INDEX);
+
+/**
+ * Deinitializes a currently active driver.
+ *
+ * @param[in] state The state encapsulating the driver in question
+ * @return GFX_OK
+ */
int gfxop_exit(GfxState *state);
-/* Deinitializes a currently active driver
-** Parameters: (GfxState *) state: The state encapsulating the driver in question
-** Returns : (int) GFX_OK
-*/
+/**
+ * Calculates a bit mask calculated from some pixels on the specified
+ * map.
+ *
+ * @param[in] state The state containing the pixels to scan
+ * @param[in] area The area to check
+ * @param[in] map The GFX_MASKed map(s) to test
+ * @return An integer value where, for each 0 <= i <= 15, bit i is set
+ * iff there exists a map for which the corresponding bit was
+ * set in the 'map' parameter and for which there exists a
+ * pixel within the specified area so that the pixel's lower 4
+ * bits, interpreted as an integer value, equal i. (Short
+ * version: This is an implementation of "on_control()").
+ */
int gfxop_scan_bitmask(GfxState *state, rect_t area, gfx_map_mask_t map);
-/* Calculates a bit mask calculated from some pixels on the specified map
-** Parameters: (GfxState *) state: The state containing the pixels to scan
-** (rect_t) area: The area to check
-** (gfx_map_mask_t) map: The GFX_MASKed map(s) to test
-** Returns : (int) An integer value where, for each 0<=i<=15, bit #i is set
-** iff there exists a map for which the corresponding bit was set
-** in the 'map' parameter and for which there exists a pixel within
-** the specified area so that the pixel's lower 4 bits, interpreted
-** as an integer value, equal i.
-** (Short version: This is an implementation of "on_control()").
-*/
+/**
+ * Sets the currently visible map.
+ *
+ * 'visible_map' can be any of GFX_MASK_VISUAL, GFX_MASK_PRIORITY and
+ * GFX_MASK_CONTROL; the appropriate map (as far as its contents are known to
+ * the graphics subsystem) is then subsequently drawn to the screen at each
+ * update. If this is set to anything other than GFX_MASK_VISUAL, slow
+ * full-screen updates are performed. Mostly useful for debugging. The screen
+ * needs to be updated for the changes to take effect.
+ *
+ * @param[in] state The state to modify
+ * @param[in] map The GFX_MASK to set
+ * @return GFX_OK, or GFX_ERROR if map was invalid
+ */
int gfxop_set_visible_map(GfxState *state, gfx_map_mask_t map);
-/* Sets the currently visible map
-** Parameters: (GfxState *) state: The state to modify
-** (gfx_map_mask_t) map: The GFX_MASK to set
-** Returns : (int) GFX_OK, or GFX_ERROR if map was invalid
-** 'visible_map' can be any of GFX_MASK_VISUAL, GFX_MASK_PRIORITY and GFX_MASK_CONTROL; the appropriate
-** map (as far as its contents are known to the graphics subsystem) is then subsequently drawn to the
-** screen at each update. If this is set to anything other than GFX_MASK_VISUAL, slow full-screen updates
-** are performed. Mostly useful for debugging.
-** The screen needs to be updated for the changes to take effect.
-*/
+/**
+ * Sets a new clipping zone.
+ *
+ * @param[in] state The affected state
+ * @param[in] zone The new clipping zone
+ * @return GFX_OK
+ */
int gfxop_set_clip_zone(GfxState *state, rect_t zone);
-/* Sets a new clipping zone
-** Parameters: (GfxState *) state: The affected state
-** (rect_t) zone: The new clipping zone
-** Returns : (int) GFX_OK
-*/
+/** @} */
+
-/******************************/
-/* Generic drawing operations */
-/******************************/
+/** @name Generic drawing operations */
+/** @{ */
+/**
+ * Renders a clipped line to the back buffer.
+ *
+ * @param[in] state The state affected
+ * @param[in] start Starting point of the line
+ * @param[in] end End point of the line
+ * @param[in] color The color to use for drawing
+ * @param[in] line_mode Any valid line mode to use
+ * @param[in] line_style The line style to use
+ * @return GFX_OK or GFX_FATAL
+ */
int gfxop_draw_line(GfxState *state,
Common::Point start, Common::Point end, gfx_color_t color,
gfx_line_mode_t line_mode, gfx_line_style_t line_style);
-/* Renders a clipped line to the back buffer
-** Parameters: (GfxState *) state: The state affected
-** (Common::Point) start: Starting point of the line
-** (Common::Point) end: End point of the line
-** (gfx_color_t) color: The color to use for drawing
-** (gfx_line_mode_t) line_mode: Any valid line mode to use
-** (gfx_line_style_t) line_style: The line style to use
-** Returns : (int) GFX_OK or GFX_FATAL
-*/
-int gfxop_draw_rectangle(GfxState *state, rect_t rect, gfx_color_t color, gfx_line_mode_t line_mode,
- gfx_line_style_t line_style);
-/* Draws a non-filled rectangular box to the back buffer
-** Parameters: (GfxState *) state: The affected state
-** (rect_t) rect: The rectangular area the box is drawn to
-** (gfx_color_t) color: The color the box is to be drawn in
-** (gfx_line_mode_t) line_mode: The line mode to use
-** (gfx_line_style_t) line_style: The line style to use for the box
-** Returns : (int) GFX_OK or GFX_FATAL
-** Boxes drawn in thin lines will surround the minimal area described by rect.
-*/
+/**
+ * Draws a non-filled rectangular box to the back buffer.
+ *
+ * Boxes drawn in thin lines will surround the minimal area described by rect.
+ *
+ * @param[in] state The affected state
+ * @param[in] rect The rectangular area the box is drawn to
+ * @param[in] color The color the box is to be drawn in
+ * @param[in] line_mode The line mode to use
+ * @param[in] line_style The line style to use for the box
+ * @return GFX_OK or GFX_FATAL
+ */
+int gfxop_draw_rectangle(GfxState *state, rect_t rect, gfx_color_t color,
+ gfx_line_mode_t line_mode, gfx_line_style_t line_style);
-int gfxop_draw_box(GfxState *state, rect_t box, gfx_color_t color1, gfx_color_t color2,
- gfx_box_shade_t shade_type);
-/* Draws a filled box to the back buffer
-** Parameters: (GfxState *) state: The affected state
-** (rect_t) box: The area to draw to
-** (gfx_color_t) color1: The primary color to use for drawing
-** (gfx_color_t) color2: The secondary color to draw in
-** (gfx_box_shade_t) shade_type: The shading system to use
-** (e.g. GFX_BOX_SHADE_FLAT)
-** Returns : (int) GFX_OK or GFX_FATAL
-** The draw mask, control, and priority values are derived from color1.
-*/
+/**
+ * Draws a filled box to the back buffer.
+ *
+ * The draw mask, control, and priority values are derived from color1.
+ *
+ * @param[in] state The affected state
+ * @param[in] box The area to draw to
+ * @param[in] color1 The primary color to use for drawing
+ * @param[in] color2 The secondary color to draw in
+ * @param[in] shade_type The shading system to use (e.g. GFX_BOX_SHADE_FLAT)
+ * @return GFX_OK or GFX_FATAL
+ */
+int gfxop_draw_box(GfxState *state, rect_t box, gfx_color_t color1,
+ gfx_color_t color2, gfx_box_shade_t shade_type);
+/**
+ * Fills a box in the back buffer with a specific color.
+ *
+ * This is a simple wrapper function for gfxop_draw_box
+ *
+ * @param[in] state The state to draw to
+ * @param[in] box The box to fill
+ * @param[in] color The color to use for filling
+ * @return GFX_OK or GFX_FATAL
+ */
int gfxop_fill_box(GfxState *state, rect_t box, gfx_color_t color);
-/* Fills a box in the back buffer with a specific color
-** Parameters: (GfxState *) state: The state to draw to
-** (rect_t) box: The box to fill
-** (gfx_color_t) color: The color to use for filling
-** Returns : (int) GFX_OK or GFX_FATAL
-** This is a simple wrapper function for gfxop_draw_box
-*/
+/**
+ * Copies a box from the static buffer to the back buffer.
+ *
+ * @param[in] state The affected state
+ * @param[in] box The box to propagate from the static buffer
+ * @return GFX_OK or GFX_FATAL
+ */
int gfxop_clear_box(GfxState *state, rect_t box);
-/* Copies a box from the static buffer to the back buffer
-** Parameters: (GfxState *) state: The affected state
-** (rect_t) box: The box to propagate from the static buffer
-** Returns : (int) GFX_OK or GFX_FATAL
-*/
+/**
+ * Updates all dirty rectangles.
+ *
+ * In order to track dirty rectangles, they must be enabled in the options. This
+ * function instructs the resource manager to free all tagged data on certain
+ * occasions (see gfxop_new_pic).
+ *
+ * @param[in] state The relevant state
+ * @return GFX_OK or GFX_FATAL if reported by the driver
+ */
int gfxop_update(GfxState *state);
-/* Updates all dirty rectangles
-** Parameters: (GfxState) *state: The relevant state
-** Returns : (int) GFX_OK or GFX_FATAL if reported by the driver
-** In order to track dirty rectangles, they must be enabled in the options.
-** This function instructs the resource manager to free all tagged data
-** on certain occasions (see gfxop_new_pic).
-*/
+/**
+ * Propagates a box from the back buffer to the front (visible) buffer.
+ *
+ * This function instructs the resource manager to free all tagged data on
+ * certain occasions (see gfxop_new_pic). When called with dirty rectangle
+ * management enabled, it will automatically propagate all dirty rectangles as
+ * well, UNLESS dirty frame accounting has been disabled explicitly.
+ *
+ * @param[in] state The affected state
+ * @param[in] box The box to propagate to the front buffer
+ * @return GFX_OK or GFX_FATAL
+ */
int gfxop_update_box(GfxState *state, rect_t box);
-/* Propagates a box from the back buffer to the front (visible) buffer
-** Parameters: (GfxState *) state: The affected state
-** (rect_t) box: The box to propagate to the front buffer
-** Returns : (int) GFX_OK or GFX_FATAL
-** This function instructs the resource manager to free all tagged data
-** on certain occasions (see gfxop_new_pic).
-** When called with dirty rectangle management enabled, it will automatically
-** propagate all dirty rectangles as well, UNLESS dirty frame accounting has
-** been disabled explicitly.
-*/
+/**
+ * Enables dirty frame accounting.
+ *
+ * Dirty frame accounting is enabled by default.
+ *
+ * @param[in] state The state dirty frame accounting is to be enabled in
+ * @return GFX_OK or GFX_ERROR if state was invalid
+ */
int gfxop_enable_dirty_frames(GfxState *state);
-/* Enables dirty frame accounting
-** Parameters: (GfxState *) state: The state dirty frame accounting is to be enabled in
-** Returns : (int) GFX_OK or GFX_ERROR if state was invalid
-** Dirty frame accounting is enabled by default.
-*/
+/**
+ * Disables dirty frame accounting.
+ *
+ * @param[in] state The state dirty frame accounting is to be disabled in
+ * @return GFX_OK or GFX_ERROR if state was invalid
+ */
int gfxop_disable_dirty_frames(GfxState *state);
-/* Disables dirty frame accounting
-** Parameters: (GfxState *) state: The state dirty frame accounting is to be disabled in
-** Returns : (int) GFX_OK or GFX_ERROR if state was invalid
-*/
+/** @} */
-/********************/
-/* Color operations */
-/********************/
-
-int gfxop_set_color(GfxState *state, gfx_color_t *color, int r, int g, int b, int a,
- int priority, int control);
-/* Maps an r/g/b value to a color and sets a gfx_color_t structure
-** Parameters: (GfxState *) state: The current state
-** (gfx_color_t *) color: Pointer to the structure to write to
-** (int x int x int) r,g,b: The red/green/blue color intensity values
-** of the result color (0x00 (minimum) to 0xff (max))
-** If any of these values is less than zero, the
-** resulting color will not affect the visual map when
-** used for drawing
-** (int) a: The alpha (transparency) value, with 0x00 meaning absolutely
-** opaque and 0xff meaning fully transparent. Alpha blending support
-** is optional for drivers, so these are the only two values that
-** are guaranteed to work as intended. Any value in between them
-** must guarantee the following opaqueness:
-** opaqueness(x-1) >= opaqueness(x) >= opaqueness (x+1)
-** (i.e. ([0,255], less-transparent-than) must define a partial order)
-** (int) priority: The priority to use for drawing, or -1 for none
-** (int) control: The control to use for drawing, or -1 to disable drawing to the
-** control map
-** Returns : (int) GFX_OK or GFX_ERROR if state is invalid
-** In palette mode, this may allocate a new color. Use gfxop_free_color() described below to
-** free that color.
-*/
+/** @name Color operations */
+/** @{ */
+
+/**
+ * Maps an r/g/b value to a color and sets a gfx_color_t structure.
+ *
+ * In palette mode, this may allocate a new color. Use gfxop_free_color() to
+ * free that color. If any of the r/g/b values are less than zero, the resulting
+ * color will not affect the visual map when used for drawing
+ *
+ * @param[in] state The current state
+ * @param[in] color Pointer to the structure to write to
+ * @param[in] r The red color intensity values of the result color
+ * @param[in] g The green color intensity values of the result color
+ * @param[in] b The blue color intensity values of the result color
+ * @param[in] a The alpha (transparency) value, with 0x00 meaning
+ * absolutely opaque and 0xff meaning fully transparent.
+ * Alpha blending support is optional for drivers, so these
+ * are the only two values that are guaranteed to work as
+ * intended. Any value in between them must guarantee the
+ * following opaqueness: opaqueness(x-1) >= opaqueness(x)
+ * >= opaqueness (x+1) (i.e. ([0,255],
+ * less-transparent-than) must define a partial order)
+ * @param[in] priority The priority to use for drawing, or -1 for none
+ * @param[in] control The control to use for drawing, or -1 to disable drawing
+ * to the control map
+ * @return GFX_OK or GFX_ERROR if state is invalid
+ */
+int gfxop_set_color(GfxState *state, gfx_color_t *color, int r, int g, int b,
+ int a, int priority, int control);
+/**
+ * Designates a color as a 'system color'.
+ *
+ * system colors are permanent colors that cannot be deallocated. as such, they must be used with caution.
+ *
+ * @param[in] state The affected state
+ * @param[in] index The index for the new system color
+ * @param[in] color The color to designate as a system color
+ * @return GFX_OK or GFX_ERROR if state is invalid
+ */
int gfxop_set_system_color(GfxState *state, unsigned int index, gfx_color_t *color);
-/* Designates a color as a 'system color'
-** Parameters: (GfxState *) state: The affected state
-** (unsigned int) index: The index for the new system color
-** (gfx_color_t *) color: The color to designate as a system color
-** Returns : (int) GFX_OK or GFX_ERROR if state is invalid
-** System colors are permanent colors that cannot be deallocated. As such, they must be used
-** with caution.
-*/
+/**
+ * Frees a color allocated by gfxop_set_color().
+ *
+ * This function is a no-op in non-index mode, or if color is a system color.
+ *
+ * @param[in] state The state affected
+ * @param[in] color The color to de-allocate
+ * @return GFX_OK or GFX_ERROR if state is invalid
+ */
int gfxop_free_color(GfxState *state, gfx_color_t *color);
-/* Frees a color allocated by gfxop_set_color()
-** Parmaeters: (GfxState *) state: The state affected
-** (gfx_color_t *) color: The color to de-allocate
-** Returns : (int) GFX_OK or GFX_ERROR if state is invalid
-** This function is a no-op in non-index mode, or if color is a system color.
-*/
-
+/** @} */
-/**********************/
-/* Pointer and IO ops */
-/**********************/
+/** @name Pointer and IO ops */
+/** @{ */
+/**
+ * Suspends program execution for the specified amount of milliseconds.
+ *
+ * The mouse pointer will be redrawn continually, if applicable
+ *
+ * @param[in] state The state affected
+ * @param[in] msecs The amount of milliseconds to wait
+ * @return GFX_OK or GFX_ERROR
+ */
int gfxop_sleep(GfxState *state, uint32 msecs);
-/* Suspends program execution for the specified amount of milliseconds
-** Parameters: (GfxState *) state: The state affected
-** (uint32) usecs: The amount of milliseconds to wait
-** Returns : (int) GFX_OK or GFX_ERROR
-** The mouse pointer will be redrawn continually, if applicable
-*/
+/**
+ * Sets the mouse pointer to a cursor resource.
+ *
+ * @param[in] state The affected state
+ * @param[in] nr Number of the cursor resource to use
+ * @return GFX_OK, GFX_ERROR if the resource did not exist and was not
+ * GFXOP_NO_POINTER, or GFX_FATAL on fatal error conditions.
+ * Use nr = GFX_NO_POINTER to disable the mouse pointer
+ * (default).
+ */
int gfxop_set_pointer_cursor(GfxState *state, int nr);
-/* Sets the mouse pointer to a cursor resource
-** Parameters: (GfxState *) state: The affected state
-** (int) nr: Number of the cursor resource to use
-** Returns : (int) GFX_OK, GFX_ERROR if the resource did not
-** exist and was not GFXOP_NO_POINTER, or GFX_FATAL on
-** fatal error conditions.
-** Use nr = GFX_NO_POINTER to disable the mouse pointer (default).
-*/
+/**
+ * Sets the mouse pointer to a view resource.
+ *
+ * Use gfxop_set_pointer_cursor(state, GFXOP_NO_POINTER) to disable the pointer.
+ *
+ * @param[in] state The affected state
+ * @param[in] nr Number of the view resource to use
+ * @param[in] loop View loop to use
+ * @param[in] cel View cel to use
+ * @param[in] hotspot Manually set hotspot to use, or NULL for default.
+ * @return GFX_OK or GFX_FATAL
+ */
int gfxop_set_pointer_view(GfxState *state, int nr, int loop, int cel, Common::Point *hotspot);
-/* Sets the mouse pointer to a view resource
-** Parameters: (GfxState *) state: The affected state
-** (int) nr: Number of the view resource to use
-** (int) loop: View loop to use
-** (int) cel: View cel to use
-** (Common::Point *) hotspot: Manually set hotspot to use, or NULL for default.
-** Returns : (int) GFX_OK or GFX_FATAL
-** Use gfxop_set_pointer_cursor(state, GFXOP_NO_POINTER) to disable the
-** pointer.
-*/
+/**
+ * Teleports the mouse pointer to a specific position.
+ *
+ * Depending on the graphics driver, this operation may be without any effect
+ *
+ * @param[in] state The state the pointer is in
+ * @param[in] pos The position to teleport it to
+ * @return Any error code or GFX_OK
+ */
int gfxop_set_pointer_position(GfxState *state, Common::Point pos);
-/* Teleports the mouse pointer to a specific position
-** Parameters: (GfxState *) state: The state the pointer is in
-** (Common::Point) pos: The position to teleport it to
-** Returns : (int) Any error code or GFX_OK
-** Depending on the graphics driver, this operation may be without
-** any effect
-*/
+/**
+ * Retrieves the next input event from the driver.
+ *
+ * @param[in] state The affected state
+ * @param[in] mask The event mask to poll from (see uinput.h)
+ * @return The next event in the driver's event queue, or a NONE event
+ * if no event matching the mask was found.
+ */
sci_event_t gfxop_get_event(GfxState *state, unsigned int mask);
-/* Retrieves the next input event from the driver
-** Parameters: (GfxState *) state: The affected state
-** (int) mask: The event mask to poll from (see uinput.h)
-** Returns : (sci_event_t) The next event in the driver's event queue, or
-** a NONE event if no event matching the mask was found.
-*/
+/** @} */
+/** @name View operations */
+/** @{ */
-/*******************/
-/* View operations */
-/*******************/
-
+/**
+ * Determines the number of loops associated with a view.
+ *
+ * @param[in] state The state to use
+ * @param[in] nr Number of the view to investigate
+ * @return The number of loops, or GFX_ERROR if the view didn't exist
+ */
int gfxop_lookup_view_get_loops(GfxState *state, int nr);
-/* Determines the number of loops associated with a view
-** Parameters: (GfxState *) state: The state to use
-** (int) nr: Number of the view to investigate
-** Returns : (int) The number of loops, or GFX_ERROR if the view didn't exist
-*/
+/**
+ * Determines the number of cels associated stored in a loop.
+ *
+ * @param[in] state The state to look up in
+ * @param[in] nr Number of the view to look up in
+ * @param[in] loop Number of the loop the number of cels of are to be
+ * investigated
+ * @return The number of cels in that loop, or GFX_ERROR if either the
+ * view or the loop didn't exist
+ */
int gfxop_lookup_view_get_cels(GfxState *state, int nr, int loop);
-/* Determines the number of cels associated stored in a loop
-** Parameters: (GfxState *) state: The state to look up in
-** (int) nr: Number of the view to look up in
-** (int) loop: Number of the loop the number of cels of
-** are to be investigated
-** Returns : (int) The number of cels in that loop, or GFX_ERROR if either
-** the view or the loop didn't exist
-*/
+/**
+ * Clips the view/loop/cel position of a cel.
+ *
+ * *loop is clipped first, then *cel. The resulting setup will be a valid view
+ * configuration.
+ *
+ * @param[in] state The state to use
+ * @param[in] nr Number of the view to use
+ * @param[in] loop Pointer to the variable storing the loop number to verify
+ * @param[in] cel Pointer to the variable storing the cel number to check
+ * @return GFX_OK or GFX_ERROR if the view didn't exist
+ */
int gfxop_check_cel(GfxState *state, int nr, int *loop, int *cel);
-/* Clips the view/loop/cel position of a cel
-** Parameters: (GfxState *) state: The state to use
-** (int) nr: Number of the view to use
-** (int *) loop: Pointer to the variable storing the loop
-** number to verify
-** (int *) cel: Pointer to the variable storing the cel
-** number to check
-** Returns : (int) GFX_OK or GFX_ERROR if the view didn't exist
-** *loop is clipped first, then *cel. The resulting setup will be a valid
-** view configuration.
-*/
+/**
+ * Resets loop/cel values to zero if they have become invalid.
+ *
+ * @param[in] state The state to use
+ * @param[in] nr Number of the view to use
+ * @param[in] loop Pointer to the variable storing the loop number to verify
+ * @param[in] cel Pointer to the variable storing the cel number to check
+ * @return GFX_OK or GFX_ERROR if the view didn't exist *loop is
+ * clipped first, then *cel. The resulting setup will be a
+ * valid view configuration.
+ */
int gfxop_overflow_cel(GfxState *state, int nr, int *loop, int *cel);
-/* Resets loop/cel values to zero if they have become invalid
-** Parameters: (GfxState *) state: The state to use
-** (int) nr: Number of the view to use
-** (int *) loop: Pointer to the variable storing the loop
-** number to verify
-** (int *) cel: Pointer to the variable storing the cel
-** number to check
-** Returns : (int) GFX_OK or GFX_ERROR if the view didn't exist
-** *loop is clipped first, then *cel. The resulting setup will be a valid
-** view configuration.
-*/
+/**
+ * Retrieves the width and height of a cel.
+ *
+ * @param[in] state The state to use
+ * @param[in] nr Number of the view
+ * @param[in] loop Loop number to examine
+ * @param[in] cel The cel (inside the loop) to look up
+ * @param[in] width The variable the width will be stored in
+ * @param[in] height The variable the height will be stored in
+ * @param[in] offset The variable the cel's x/y offset will be stored in
+ * @return GFX_OK if the lookup succeeded, GFX_ERROR if the
+ * nr/loop/cel combination was invalid
+ */
int gfxop_get_cel_parameters(GfxState *state, int nr, int loop, int cel,
int *width, int *height, Common::Point *offset);
-/* Retrieves the width and height of a cel
-** Parameters: (GfxState *) state: The state to use
-** (int) nr: Number of the view
-** (int) loop: Loop number to examine
-** (int) cel: The cel (inside the loop) to look up
-** (int *) width: The variable the width will be stored in
-** (int *) height: The variable the height will be stored in
-** (Common::Point *) offset: The variable the cel's x/y offset will be stored in
-** Returns : (int) GFX_OK if the lookup succeeded, GFX_ERROR if the nr/loop/cel
-** combination was invalid
-*/
-int gfxop_draw_cel(GfxState *state, int nr, int loop, int cel, Common::Point pos,
- gfx_color_t color, int palette);
-/* Draws (part of) a cel to the back buffer
-** Parameters: (GfxState *) state: The state encapsulating the driver to draw with
-** (int) nr: Number of the view to draw
-** (int) loop: Loop of the cel to draw
-** (int) cel: The cel number of the cel to draw
-** (Common::Point) pos: The positino the cel is to be drawn to
-** (gfx_color_t color): The priority and control values to use for drawing
-** (int) palette: The palette to use
-** Returns : (int) GFX_OK or GFX_FATAL
-*/
+/**
+ * Draws (part of) a cel to the back buffer.
+ *
+ * @param[in] state The state encapsulating the driver to draw with
+ * @param[in] nr Number of the view to draw
+ * @param[in] loop Loop of the cel to draw
+ * @param[in] cel The cel number of the cel to draw
+ * @param[in] pos The positino the cel is to be drawn to
+ * @param[in] color The priority and control values to use for drawing
+ * @param[in] palette The palette to use
+ * @return GFX_OK or GFX_FATAL
+ */
+int gfxop_draw_cel(GfxState *state, int nr, int loop, int cel,
+ Common::Point pos, gfx_color_t color, int palette);
-int gfxop_draw_cel_static(GfxState *state, int nr, int loop, int cel, Common::Point pos,
- gfx_color_t color, int palette);
-/* Draws a cel to the static buffer; no clipping is performed
-** Parameters: (GfxState *) state: The state encapsulating the driver to draw with
-** (int) nr: Number of the view to draw
-** (int) loop: Loop of the cel to draw
-** (int) cel: The cel number of the cel to draw
-** (Common::Point) pos: The positino the cel is to be drawn to
-** (gfx_color_t color): The priority and control values to use for drawing
-** (int) palette: The palette to use
-** Returns : (int) GFX_OK or GFX_FATAL
-** Let me repeat, no clipping (except for the display borders) is performed.
-*/
+/**
+ * Draws a cel to the static buffer; no clipping is performed.
+ *
+ * No clipping (except for the display borders) is performed.
+ *
+ * @param[in] state The state encapsulating the driver to draw with
+ * @param[in] nr Number of the view to draw
+ * @param[in] loop Loop of the cel to draw
+ * @param[in] cel The cel number of the cel to draw
+ * @param[in] pos The positino the cel is to be drawn to
+ * @param[in] color The priority and control values to use for drawing
+ * @param[in] palette The palette to use
+ * @return GFX_OK or GFX_FATAL
+ */
+int gfxop_draw_cel_static(GfxState *state, int nr, int loop, int cel,
+ Common::Point pos, gfx_color_t color, int palette);
-int gfxop_draw_cel_static_clipped(GfxState *state, int nr, int loop, int cel, Common::Point pos,
- gfx_color_t color, int palette);
-/* Draws (part of) a clipped cel to the static buffer
-** Parameters: (GfxState *) state: The state encapsulating the driver to draw with
-** (int) nr: Number of the view to draw
-** (int) loop: Loop of the cel to draw
-** (int) cel: The cel number of the cel to draw
-** (Common::Point) pos: The positino the cel is to be drawn to
-** (gfx_color_t color): The priority and control values to use for drawing
-** (int) palette: The palette to use
-** Returns : (int) GFX_OK or GFX_FATAL
-** This function does clip.
-*/
+/**
+ * Draws (part of) a clipped cel to the static buffer.
+ *
+ * This function does clip.
+ *
+ * @param[in] state The state encapsulating the driver to draw with
+ * @param[in] nr Number of the view to draw
+ * @param[in] loop Loop of the cel to draw
+ * @param[in] cel The cel number of the cel to draw
+ * @param[in] pos The positino the cel is to be drawn to
+ * @param[in] color The priority and control values to use for drawing
+ * @param[in] palette The palette to use
+ * @return GFX_OK or GFX_FATAL
+ */
+int gfxop_draw_cel_static_clipped(GfxState *state, int nr, int loop, int cel,
+ Common::Point pos, gfx_color_t color, int palette);
+/** @} */
-/******************/
-/* Pic operations */
-/******************/
-/* These operations are exempt from clipping */
+/** @name Pic operations
+ * These operations are exempt from clipping */
+/** @{ */
+/**
+ * Draws a pic and writes it over the static buffer.
+ *
+ * This function instructs the resource manager to tag all data as "unused".
+ * See the resource manager tag functions for a full description.
+ *
+ * @param[in] state The state affected
+ * @param[in] nr Number of the pic to draw
+ * @param[in] flags Interpreter-dependant flags to use for drawing
+ * @param[in] default_palette The default palette for drawing
+ * @return GFX_OK or GFX_FATAL
+ */
int gfxop_new_pic(GfxState *state, int nr, int flags, int default_palette);
-/* Draws a pic and writes it over the static buffer
-** Parameters: (GfxState *) state: The state affected
-** (int) nr: Number of the pic to draw
-** (int) flags: Interpreter-dependant flags to use for drawing
-** (int) default_palette: The default palette for drawing
-** Returns : (int) GFX_OK or GFX_FATAL
-** This function instructs the resource manager to tag all data as "unused".
-** See the resource manager tag functions for a full description.
-*/
+/**
+ * Retrieves all meta-information assigned to the current pic.
+ *
+ * @param[in] state The state affected
+ * @return NULL if the pic doesn't exist or has no meta-information,
+ * the meta-info otherwise. This meta-information is referred
+ * to as 'internal data' in the pic code
+ */
int *gfxop_get_pic_metainfo(GfxState *state);
-/* Retrieves all meta-information assigned to the current pic
-** Parameters: (GfxState *) state: The state affected
-** Returns : (int *) NULL if the pic doesn't exist or has no meta-information,
-** the meta-info otherwise
-** This meta-information is referred to as 'internal data' in the pic code
-*/
+/**
+ * Adds a pic to the static buffer.
+ *
+ * @param[in] state The state affected
+ * @param[in] nr Number of the pic to add
+ * @param[in] flags Interpreter-dependant flags to use for drawing
+ * @param[in] default_palette The default palette for drawing
+ * @return GFX_OK or GFX_FATAL
+ */
int gfxop_add_to_pic(GfxState *state, int nr, int flags, int default_palette);
-/* Adds a pic to the static buffer
-** Parameters: (GfxState *) state: The state affected
-** (int) nr: Number of the pic to add
-** (int) flags: Interpreter-dependant flags to use for drawing
-** (int) default_palette: The default palette for drawing
-** Returns : (int) GFX_OK or GFX_FATAL
-*/
-
+/** @} */
+/** @name Text operations */
+/** @{ */
-/*******************/
-/* Text operations */
-/*******************/
-
-
+/**
+ * Returns the fixed line height for one specified font.
+ *
+ * @param[in] state The state to work on
+ * @param[in] font_nr Number of the font to inspect
+ * @return GFX_ERROR, GFX_FATAL, or the font line height
+ */
int gfxop_get_font_height(GfxState *state, int font_nr);
-/* Returns the fixed line height for one specified font
-** Parameters: (GfxState *) state: The state to work on
-** (int) font_nr: Number of the font to inspect
-** Returns : (int) GFX_ERROR, GFX_FATAL, or the font line height
-*/
+/**
+ * Calculates the width and height of a specified text in a specified
+ * font.
+ *
+ * @param[in] state The state to use
+ * @param[in] font_nr Font number to use for the calculation
+ * @param[in] text The text to examine
+ * @param[in] flags ORred GFXR_FONT_FLAGs
+ * @param[in] maxwidth The maximum pixel width to allow for the text
+ * @param[out] width The resulting width
+ * @param[out] height The resulting height
+ * @param[out] lines_nr Number of lines used in the text
+ * @param[out] lineheight Pixel height (SCI scale) of each text line
+ * @param[out] lastline_width Pixel offset (SCI scale) of the space after
+ * the last character in the last line
+ * @return GFX_OK or GFX_ERROR if the font didn't exist
+ */
int gfxop_get_text_params(GfxState *state, int font_nr, const char *text,
int maxwidth, int *width, int *height, int flags,
int *lines_nr, int *lineheight, int *lastline_width);
-/* Calculates the width and height of a specified text in a specified font
-** Parameters: (GfxState *) state: The state to use
-** (int) font_nr: Font number to use for the calculation
-** (const char *) text: The text to examine
-** (int) flags: ORred GFXR_FONT_FLAGs
-** (int) maxwidth: The maximum pixel width to allow for the text
-** Returns : (int) GFX_OK or GFX_ERROR if the font didn't exist
-** (int) *width: The resulting width
-** (int) *height: The resulting height
-** (int) *lines_nr: Number of lines used in the text
-** (int) *lineheight: Pixel height (SCI scale) of each text line
-** (int) *lastline_wdith: Pixel offset (SCI scale) of the space
-** after the last character in the last line
-*/
-TextHandle *gfxop_new_text(GfxState *state, int font_nr, const Common::String &text, int maxwidth,
- gfx_alignment_t halign, gfx_alignment_t valign, gfx_color_t color1,
- gfx_color_t color2, gfx_color_t bg_color, int flags);
-/* Generates a new text handle that can be used to draw any text
-** Parameters: (GfxState *) state: The state to use
-** (int) font_nr: Font number to use for the calculation
-** (const char *) text: The text to examine
-** (int) maxwidth: The maximum pixel width to allow for the text
-** (gfx_alignment_t) halign: The horizontal text alignment
-** (gfx_alignment_t) valign: The vertical text alignment
-** (gfx_color_t x gfx_color_t) color1, color2: The text's foreground colors
-** (the function will dither between those two)
-** (gfx_color_t) bg_color: The background color
-** (int) flags: ORred GFXR_FONT_FLAGs
-** Returns : (TextHandle *) A newly allocated TextHandle, or
-** NULL if font_nr was invalid
-** The control and priority values for the text will be extracted from color1.
-** Note that the colors must have been allocated properly, or the text may display in
-** incorrect colors.
-*/
+/**
+ * Generates a new text handle that can be used to draw any text.
+ *
+ * The control and priority values for the text will be extracted from color1.
+ * Note that the colors must have been allocated properly, or the text may
+ * display in incorrect colors.
+ *
+ * @param[in] state The state to use
+ * @param[in] font_nr Font number to use for the calculation
+ * @param[in] text The text to examine
+ * @param[in] maxwidth: The maximum pixel width to allow for the text
+ * @param[in] halign The horizontal text alignment
+ * @param[in] valign The vertical text alignment
+ * @param[in] color1 The text's foreground colors (the function will dither
+ * between color1 and 2)
+ * @param[in] color2 The text's foreground colors (the function will dither
+ * between color1 and 2)
+ * @param[in] bg_color The background color
+ * @param[in] flags ORred GFXR_FONT_FLAGs
+ * @return A newly allocated TextHandle, or NULL if font_nr was
+ * invalid
+ */
+TextHandle *gfxop_new_text(GfxState *state, int font_nr,
+ const Common::String &text, int maxwidth, gfx_alignment_t halign,
+ gfx_alignment_t valign, gfx_color_t color1, gfx_color_t color2,
+ gfx_color_t bg_color, int flags);
+/**
+ * Frees a previously allocated text handle and all related resources.
+ *
+ * @param[in] state The state to use
+ * @param[in] handle The handle to free
+ * @return GFX_OK
+ */
int gfxop_free_text(GfxState *state, TextHandle *handle);
-/* Frees a previously allocated text handle and all related resources
-** Parameters: (GfxState *) state: The state to use
-** (TextHandle *) handle: The handle to free
-** Returns : (int) GFX_OK
-*/
+/**
+ * Draws text stored in a text handle.
+ *
+ * @param[in] state The target state
+ * @param[in] handle The text handle to use for drawing
+ * @param[in] zone The rectangular box to draw to. In combination with
+ * halign and valign, this defines where the text is drawn
+ * to.
+ * @return GFX_OK or GFX_FATAL
+ */
int gfxop_draw_text(GfxState *state, TextHandle *handle, rect_t zone);
-/* Draws text stored in a text handle
-** Parameters: (GfxState *) state: The target state
-** (TextHandle *) handle: The text handle to use for drawing
-** (rect_t) zone: The rectangular box to draw to. In combination with
-** halign and valign, this defines where the text is
-** drawn to.
-** Returns : (int) GFX_OK or GFX_FATAL
-*/
+/** @} */
-/****************************/
-/* Manual pixmap operations */
-/****************************/
+/** @name Manual pixmap operations */
+/** @{ */
+/**
+ * Grabs a screen section from the back buffer and stores it in a pixmap.
+ *
+ * Obviously, this only affects the visual map
+ *
+ * @param[in] state The affected state
+ * @param[in] area The area to grab
+ * Returns A result pixmap, or NULL on error
+ */
gfx_pixmap_t *gfxop_grab_pixmap(GfxState *state, rect_t area);
-/* Grabs a screen section from the back buffer and stores it in a pixmap
-** Parameters: (GfxState *) state: The affected state
-** (rect_t) area: The area to grab
-** Returns : (gfx_pixmap_t *) A result pixmap, or NULL on error
-** Obviously, this only affects the visual map
-*/
-int gfxop_draw_pixmap(GfxState *state, gfx_pixmap_t *pxm, rect_t zone, Common::Point pos);
-/* Draws part of a pixmap to the screen
-** Parameters: (GfxState *) state: The affected state
-** (gfx_pixmap_t *) pxm: The pixmap to draw
-** (rect_t) zone: The segment of the pixmap to draw
-** (Common::Point) pos: The position the pixmap should be drawn to
-** Returns : (int) GFX_OK or any error code
-*/
+/**
+ * Draws part of a pixmap to the screen.
+ *
+ * @param[in] state The affected state
+ * @param[in] pxm The pixmap to draw
+ * @param[in] zone The segment of the pixmap to draw
+ * @param[in] pos The position the pixmap should be drawn to
+ * @return GFX_OK or any error code
+ */
+int gfxop_draw_pixmap(GfxState *state, gfx_pixmap_t *pxm, rect_t zone,
+ Common::Point pos);
+/**
+ * Frees a pixmap returned by gfxop_grab_pixmap().
+ *
+ * @param[in] state The affected state
+ * @param[in] pxm The pixmap to free
+ * @return GFX_OK, or GFX_ERROR if the state was invalid
+ */
int gfxop_free_pixmap(GfxState *state, gfx_pixmap_t *pxm);
-/* Frees a pixmap returned by gfxop_grab_pixmap()
-** Parameters: (GfxState *) state: The affected state
-** (gfx_pixmap_t *) pxm: The pixmap to free
-** Returns : (int) GFX_OK, or GFX_ERROR if the state was invalid
-*/
+/** @} */
-/******************************/
-/* Dirty rectangle operations */
-/******************************/
+
+/** @name Dirty rectangle operations */
+/** @{ */
/**
* Adds a dirty rectangle to 'base' according to a strategy.
- * @param list the list to add to
- * @param box the dirty frame to addable
- * @param strategy the dirty frame heuristic to use (see gfx_options.h)
+ *
+ * @param[in] list the list to add to
+ * @param[in] box the dirty frame to addable
+ * @param[in] strategy the dirty frame heuristic to use (see gfx_options.h)
*/
void gfxdr_add_dirty(DirtyRectList &list, rect_t box, int strategy);
+/**
+ * Clips a rectangle against another one.
+ *
+ * @param[in] rect The rectangle to clip
+ * @param[in] clipzone The outer bounds rect must be in
+ * @return 1 if rect is empty now, 0 otherwise
+ */
int _gfxop_clip(rect_t *rect, rect_t clipzone);
-/* Clips a rectangle against another one
-** Parameters: (rect_t *) rect: The rectangle to clip
-** (rect_t) clipzone: The outer bounds rect must be in
-** Reuturns : (int) 1 if rect is empty now, 0 otherwise
-*/
+/** @} */
} // End of namespace Sci
diff --git a/engines/sci/gfx/palette.h b/engines/sci/gfx/palette.h
index 127871bce4..65d1cac18e 100644
--- a/engines/sci/gfx/palette.h
+++ b/engines/sci/gfx/palette.h
@@ -42,15 +42,18 @@ struct PaletteEntry {
: r(R), g(G), b(B), parent_index(-1), refcount(PALENTRY_FREE)
{ }
- // Color data
+ /** @name Color data */
+ /** @{ */
byte r, g, b;
+ /** @} */
- // Index in parent palette, or -1
+ /** Index in parent palette, or -1 */
int parent_index;
- // Number of references from child palettes. (This includes palettes
- // of pixmaps.)
- // Special values: PALENTRY_LOCKED, PALENTRY_FREE
+ /**
+ * Number of references from child palettes. (This includes palettes
+ * of pixmaps.)
+ * Special values: PALENTRY_LOCKED, PALENTRY_FREE */
int refcount;
};
@@ -98,10 +101,9 @@ private:
Palette *_parent;
- bool _dirty; // Palette has changed
- int _refcount; // Number of pixmaps (or other objects) using this palette
- int _revision; // When this is incremented, all child references are
- // invalidated
+ bool _dirty; /**< Palette has changed */
+ int _refcount; /**< Number of pixmaps (or other objects) using this palette */
+ int _revision; /**< When this is incremented, all child references are invalidated */
};
diff --git a/engines/sci/gfx/res_pic.cpp b/engines/sci/gfx/res_pic.cpp
index 762cb7b55d..5ee2665b50 100644
--- a/engines/sci/gfx/res_pic.cpp
+++ b/engines/sci/gfx/res_pic.cpp
@@ -152,7 +152,7 @@ void gfxr_init_static_palette() {
}
-gfxr_pic_t *gfxr_init_pic(gfx_mode_t *mode, int ID, int sci1) {
+gfxr_pic_t *gfxr_init_pic(gfx_mode_t *mode, int ID, bool sci1) {
gfxr_pic_t *pic = (gfxr_pic_t*)malloc(sizeof(gfxr_pic_t));
pic->mode = mode;
diff --git a/engines/sci/gfx/res_view.cpp b/engines/sci/gfx/res_view.cpp
index f282369e15..b30c57f38d 100644
--- a/engines/sci/gfx/res_view.cpp
+++ b/engines/sci/gfx/res_view.cpp
@@ -331,7 +331,7 @@ gfx_pixmap_t *gfxr_draw_cel1(int id, int loop, int cel, int mirrored, byte *reso
int yl = READ_LE_UINT16(cel_base + 2);
int pixmap_size = xl * yl;
int xdisplace = isSci11 ? READ_LE_UINT16(cel_base + 4) : (int8) cel_base[4];
- int ydisplace = isSci11 ? READ_LE_UINT16(cel_base + 6) : (int8) cel_base[5];
+ int ydisplace = isSci11 ? READ_LE_UINT16(cel_base + 6) : cel_base[5];
int runlength_offset = isSci11 ? READ_LE_UINT16(cel_base + 24) : 8;
int literal_offset = isSci11 ? READ_LE_UINT16(cel_base + 28) : 8;
gfx_pixmap_t *retval = gfx_pixmap_alloc_index_data(gfx_new_pixmap(xl, yl, id, loop, cel));
diff --git a/engines/sci/gfx/seq_decoder.h b/engines/sci/gfx/seq_decoder.h
index 16574007fe..b9feadb5f3 100644
--- a/engines/sci/gfx/seq_decoder.h
+++ b/engines/sci/gfx/seq_decoder.h
@@ -28,6 +28,9 @@
namespace Sci {
+/**
+ * Decoder for image sequences
+ */
class SeqDecoder {
public:
SeqDecoder() : _fileStream(0), _palette(0) { }
@@ -37,7 +40,9 @@ public:
gfx_pixmap_t *getFrame(bool &hasNext);
private:
- bool decodeFrame(byte *runlength_data, int runlength_size, byte *literal_data, int literal_size, byte *dest, int xl, int yl, int color_key);
+ bool decodeFrame(byte *runlength_data, int runlength_size,
+ byte *literal_data, int literal_size, byte *dest, int xl, int yl,
+ int color_key);
Common::SeekableReadStream *_fileStream;
Palette *_palette;
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index 5edf1b7145..3c377e8ef2 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -56,13 +56,6 @@ const char *sci_version_types[] = {
const int sci_max_resource_nr[] = {65536, 1000, 2048, 2048, 2048, 65536, 65536, 65536};
-enum SolFlags {
- kSolFlagCompressed = 1 << 0,
- kSolFlagUnknown = 1 << 1,
- kSolFlag16Bit = 1 << 2,
- kSolFlagIsSigned = 1 << 3
-};
-
static const char *sci_error_types[] = {
"No error",
"I/O error",
@@ -217,7 +210,7 @@ bool ResourceManager::loadFromPatchFile(Resource *res) {
return loadPatch(res, file);
}
-bool ResourceManager::loadFromAudioVolume(Resource *res, Common::File &file) {
+bool ResourceManager::loadFromAudioVolumeSCI11(Resource *res, Common::File &file) {
ResourceType type = (ResourceType)(file.readByte() & 0x7f);
if (((res->id.type == kResourceTypeAudio || res->id.type == kResourceTypeAudio36) && (type != kResourceTypeAudio))
|| ((res->id.type == kResourceTypeSync || res->id.type == kResourceTypeSync36) && (type != kResourceTypeSync))) {
@@ -243,6 +236,21 @@ bool ResourceManager::loadFromAudioVolume(Resource *res, Common::File &file) {
return loadPatch(res, file);
}
+bool ResourceManager::loadFromAudioVolumeSCI1(Resource *res, Common::File &file) {
+ res->data = new byte[res->size];
+
+ if (res->data == NULL) {
+ error("Can't allocate %d bytes needed for loading %s", res->size, res->id.toString().c_str());
+ }
+
+ unsigned int really_read = file.read(res->data, res->size);
+ if (really_read != res->size)
+ warning("Read %d bytes from %s but expected %d", really_read, res->id.toString().c_str(), res->size);
+
+ res->status = kResStatusAllocated;
+ return true;
+}
+
Common::File *ResourceManager::getVolumeFile(const char *filename) {
Common::List<Common::File *>::iterator it = _volumeFiles.begin();
Common::File *file;
@@ -292,7 +300,10 @@ void ResourceManager::loadResource(Resource *res) {
file->seek(res->file_offset, SEEK_SET);
if (res->source->source_type == kSourceAudioVolume) {
- loadFromAudioVolume(res, *file);
+ if (_sciVersion < SCI_VERSION_1_1)
+ loadFromAudioVolumeSCI1(res, *file);
+ else
+ loadFromAudioVolumeSCI11(res, *file);
} else {
int error = decompress(res, file);
if (error) {
@@ -436,8 +447,11 @@ void ResourceManager::scanNewSources() {
else
readResourceMapSCI1(source);
break;
+ case kSourceExtAudioMap:
+ readAudioMapSCI1(source);
+ break;
case kSourceIntMap:
- readMap(source);
+ readAudioMapSCI11(source);
break;
default:
break;
@@ -460,6 +474,7 @@ ResourceManager::ResourceManager(int version, int maxMemory) {
_LRU.clear();
_resMap.clear();
_sciVersion = version;
+ _audioMapSCI1 = NULL;
addAppropriateSources();
@@ -607,15 +622,10 @@ void ResourceManager::printLRU() {
debug("Total: %d entries, %d bytes (mgr says %d)", entries, mem, _memoryLRU);
}
-void ResourceManager::freeOldResources(int last_invulnerable) {
- while (_maxMemory < _memoryLRU && (!last_invulnerable || !_LRU.empty())) {
+void ResourceManager::freeOldResources() {
+ while (_maxMemory < _memoryLRU) {
+ assert(!_LRU.empty());
Resource *goner = *_LRU.reverse_begin();
- if (!goner) {
- debug("Internal error: mgr->lru_last is NULL!");
- debug("LRU-mem= %d", _memoryLRU);
- debug("lru_first = %p", (void *)*_LRU.begin());
- printLRU();
- }
removeFromLRU(goner);
goner->unalloc();
#ifdef SCI_VERBOSE_RESMGR
@@ -659,6 +669,8 @@ Resource *ResourceManager::findResource(ResourceId id, bool lock) {
// Unless an error occured, the resource is now either
// locked or allocated, but never queued or freed.
+ freeOldResources();
+
if (lock) {
if (retval->status == kResStatusAllocated) {
retval->status = kResStatusLocked;
@@ -671,8 +683,6 @@ Resource *ResourceManager::findResource(ResourceId id, bool lock) {
addToLRU(retval);
}
- freeOldResources(retval->status == kResStatusAllocated);
-
if (retval->data)
return retval;
else {
@@ -695,7 +705,7 @@ void ResourceManager::unlockResource(Resource *res) {
addToLRU(res);
}
- freeOldResources(0);
+ freeOldResources();
}
int ResourceManager::detectMapVersion() {
@@ -871,15 +881,7 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType restype,
}
// Prepare destination, if neccessary
if (_resMap.contains(resId) == false) {
- // FIXME: code duplication
- switch (restype) {
- case kResourceTypeSync:
- newrsc = new ResourceSync;
- break;
- default:
- newrsc = new Resource;
- break;
- }
+ newrsc = new Resource;
_resMap.setVal(resId, newrsc);
} else
newrsc = _resMap.getVal(resId);
@@ -1042,15 +1044,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
resId = ResourceId((ResourceType)type, number);
// adding new resource only if it does not exist
if (_resMap.contains(resId) == false) {
- switch (type) {
- case kResourceTypeSync:
- res = new ResourceSync;
- break;
- default:
- res = new Resource;
- break;
- }
-
+ res = new Resource;
_resMap.setVal(resId, res);
res->id = resId;
res->source = getVolume(map, volume_nr);
@@ -1064,11 +1058,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
void ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size) {
// Adding new resource only if it does not exist
if (_resMap.contains(resId) == false) {
- Resource *res;
- if ((resId.type == kResourceTypeSync) || (resId.type == kResourceTypeSync36))
- res = new ResourceSync;
- else
- res = new Resource;
+ Resource *res = new Resource;
_resMap.setVal(resId, res);
res->id = resId;
res->source = src;
@@ -1077,6 +1067,22 @@ void ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32
}
}
+void ResourceManager::removeAudioResource(ResourceId resId) {
+ // Remove resource, unless it was loaded from a patch
+ if (_resMap.contains(resId)) {
+ Resource *res = _resMap.getVal(resId);
+
+ if (res->source->source_type == kSourceAudioVolume) {
+ if (res->lockers == 0) {
+ _resMap.erase(resId);
+ delete res;
+ } else {
+ warning("Failed to remove resource %s (still in use)", resId.toString().c_str());
+ }
+ }
+ }
+}
+
// Early SCI1.1 65535.MAP structure (uses RESOURCE.AUD):
// =========
// 6-byte entries:
@@ -1112,7 +1118,7 @@ void ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32
// w syncSize (iff seq has bit 7 set)
// w syncAscSize (iff seq has bit 6 set)
-int ResourceManager::readMap(ResourceSource *map) {
+int ResourceManager::readAudioMapSCI11(ResourceSource *map) {
bool isEarly = true;
uint32 offset = 0;
Resource *mapRes = findResource(ResourceId(kResourceTypeMap, map->volume_number), false);
@@ -1197,6 +1203,103 @@ int ResourceManager::readMap(ResourceSource *map) {
return 0;
}
+// AUDIOnnn.MAP contains 10-byte entries:
+// w nEntry
+// dw offset+volume (as in resource.map)
+// dw size
+// ending with 10 0xFFs
+
+int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) {
+ Common::File file;
+
+ if (!file.open(map->location_name))
+ return SCI_ERROR_RESMAP_NOT_FOUND;
+
+ while (1) {
+ uint16 n = file.readUint16LE();
+ uint32 offset = file.readUint32LE();
+ uint32 size = file.readUint32LE();
+
+ if (file.ioFailed()) {
+ warning("Error while reading %s", map->location_name.c_str());
+ return SCI_ERROR_RESMAP_NOT_FOUND;
+ }
+
+ if (n == 0xffff)
+ break;
+
+ byte volume_nr = offset >> 28; // most significant 4 bits
+ offset &= 0x0fffffff; // least significant 28 bits
+
+ ResourceSource *src = getVolume(map, volume_nr);
+
+ if (src) {
+ if (unload)
+ removeAudioResource(ResourceId(kResourceTypeAudio, n));
+ else
+ addResource(ResourceId(kResourceTypeAudio, n), src, offset, size);
+ } else {
+ warning("Failed to find audio volume %i", volume_nr);
+ }
+ }
+
+ return 0;
+}
+
+void ResourceManager::setAudioLanguage(int language) {
+ if (_audioMapSCI1) {
+ if (_audioMapSCI1->volume_number == language) {
+ // This language is already loaded
+ return;
+ }
+
+ // We already have a map loaded, so we unload it first
+ readAudioMapSCI1(_audioMapSCI1, true);
+
+ // Remove all volumes that use this map from the source list
+ Common::List<ResourceSource *>::iterator it = _sources.begin();
+ while (it != _sources.end()) {
+ ResourceSource *src = *it;
+ if (src->associated_map == _audioMapSCI1) {
+ it = _sources.erase(it);
+ delete src;
+ } else {
+ ++it;
+ }
+ }
+
+ // Remove the map itself from the source list
+ _sources.remove(_audioMapSCI1);
+ delete _audioMapSCI1;
+
+ _audioMapSCI1 = NULL;
+ }
+
+ char filename[9];
+ snprintf(filename, 9, "AUDIO%03d", language);
+
+ Common::String fullname = Common::String(filename) + ".MAP";
+ if (!Common::File::exists(fullname)) {
+ warning("No audio map found for language %i", language);
+ return;
+ }
+
+ _audioMapSCI1 = addSource(NULL, kSourceExtAudioMap, fullname.c_str(), language);
+
+ // Search for audio volumes for this language and add them to the source list
+ Common::ArchiveMemberList files;
+ SearchMan.listMatchingMembers(files, Common::String(filename) + ".0??");
+ for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
+ const Common::String name = (*x)->getName();
+ const char *dot = strrchr(name.c_str(), '.');
+ int number = atoi(dot + 1);
+
+ addSource(_audioMapSCI1, kSourceAudioVolume, name.c_str(), number);
+ }
+
+ scanNewSources();
+}
+
int ResourceManager::readResourceInfo(Resource *res, Common::File *file,
uint32&szPacked, ResourceCompression &compression) {
// SCI0 volume format: {wResId wPacked+4 wUnpacked wCompression} = 8 bytes
@@ -1328,325 +1431,4 @@ int ResourceManager::decompress(Resource *res, Common::File *file) {
return error;
}
-void ResourceSync::startSync(EngineState *s, reg_t obj) {
- _syncTime = _syncCue = -1;
- PUT_SEL32V(obj, syncCue, 0);
- _ptr = (uint16 *)data;
- //syncStarted = true; // not used
-}
-
-void ResourceSync::nextSync(EngineState *s, reg_t obj) {
- if (_ptr) {
- _syncTime = (int16)READ_LE_UINT16(_ptr);
- if (_syncTime == -1) {
- stopSync();
- } else {
- _syncCue = (int16)READ_LE_UINT16(_ptr + 1);
- _ptr += 2;
- }
- PUT_SEL32V(obj, syncTime, _syncTime);
- PUT_SEL32V(obj, syncCue, _syncCue);
- }
-}
-//--------------------------------
-void ResourceSync::stopSync() {
- _ptr = 0;
- _syncCue = -1;
- //syncStarted = false; // not used
-}
-
-
-AudioResource::AudioResource(ResourceManager *resMgr, int sciVersion) {
- _resMgr = resMgr;
- _sciVersion = sciVersion;
- _audioRate = 11025;
- _lang = 0;
- _audioMapSCI1 = 0;
- _audioMapSCI11 = 0;
-}
-
-AudioResource::~AudioResource() {
- if (_sciVersion < SCI_VERSION_1_1) {
- if (_audioMapSCI1) {
- delete[] _audioMapSCI1;
- _audioMapSCI1 = 0;
- }
- } else {
- if (_audioMapSCI11)
- _resMgr->unlockResource(_audioMapSCI11);
- }
-}
-
-// Used in SCI1 games
-void AudioResource::setAudioLang(int16 lang) {
- if (lang != -1) {
- _lang = lang;
-
- char filename[40];
- sprintf(filename, "AUDIO%03d.MAP", _lang);
-
- Common::File* audioMapFile = new Common::File();
- if (audioMapFile->open(filename)) {
- // The audio map is freed in the destructor
- _audioMapSCI1 = new byte[audioMapFile->size()];
- audioMapFile->read(_audioMapSCI1, audioMapFile->size());
- audioMapFile->close();
- delete audioMapFile;
- } else {
- _audioMapSCI1 = 0;
- }
- }
-}
-
-int AudioResource::getAudioPosition() {
- if (g_system->getMixer()->isSoundHandleActive(_audioHandle)) {
- return g_system->getMixer()->getSoundElapsedTime(_audioHandle) * 6 / 100; // return elapsed time in ticks
- } else {
- return -1; // Sound finished
- }
-}
-
-bool AudioResource::findAudEntrySCI1(uint16 audioNumber, byte &volume, uint32 &offset, uint32 &size) {
- // AUDIO00X.MAP contains 10-byte entries:
- // w nEntry
- // dw offset+volume (as in resource.map)
- // dw size
- // ending with 10 0xFFs
- uint16 n;
- uint32 off;
-
- if (_audioMapSCI1 == 0)
- return false;
-
- byte *ptr = _audioMapSCI1;
- while ((n = READ_LE_UINT16(ptr)) != 0xFFFF) {
- if (n == audioNumber) {
- off = READ_LE_UINT32(ptr + 2);
- size = READ_LE_UINT32(ptr + 6);
- volume = off >> 28;
- offset = off & 0x0FFFFFFF;
- return true;
- }
- ptr += 10;
- }
-
- return false;
-}
-
-// FIXME: Move this to sound/adpcm.cpp?
-// Note that the 16-bit version is also used in coktelvideo.cpp
-static const uint16 tableDPCM16[128] = {
- 0x0000, 0x0008, 0x0010, 0x0020, 0x0030, 0x0040, 0x0050, 0x0060, 0x0070, 0x0080,
- 0x0090, 0x00A0, 0x00B0, 0x00C0, 0x00D0, 0x00E0, 0x00F0, 0x0100, 0x0110, 0x0120,
- 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x0180, 0x0190, 0x01A0, 0x01B0, 0x01C0,
- 0x01D0, 0x01E0, 0x01F0, 0x0200, 0x0208, 0x0210, 0x0218, 0x0220, 0x0228, 0x0230,
- 0x0238, 0x0240, 0x0248, 0x0250, 0x0258, 0x0260, 0x0268, 0x0270, 0x0278, 0x0280,
- 0x0288, 0x0290, 0x0298, 0x02A0, 0x02A8, 0x02B0, 0x02B8, 0x02C0, 0x02C8, 0x02D0,
- 0x02D8, 0x02E0, 0x02E8, 0x02F0, 0x02F8, 0x0300, 0x0308, 0x0310, 0x0318, 0x0320,
- 0x0328, 0x0330, 0x0338, 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370,
- 0x0378, 0x0380, 0x0388, 0x0390, 0x0398, 0x03A0, 0x03A8, 0x03B0, 0x03B8, 0x03C0,
- 0x03C8, 0x03D0, 0x03D8, 0x03E0, 0x03E8, 0x03F0, 0x03F8, 0x0400, 0x0440, 0x0480,
- 0x04C0, 0x0500, 0x0540, 0x0580, 0x05C0, 0x0600, 0x0640, 0x0680, 0x06C0, 0x0700,
- 0x0740, 0x0780, 0x07C0, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00,
- 0x0F00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
-};
-
-static const byte tableDPCM8[8] = {0, 1, 2, 3, 6, 10, 15, 21};
-
-static void deDPCM16(byte *soundBuf, Common::SeekableReadStream &audioStream, uint32 n) {
- int16 *out = (int16 *) soundBuf;
-
- int32 s = 0;
- for (uint32 i = 0; i < n; i++) {
- byte b = audioStream.readByte();
- if (b & 0x80)
- s -= tableDPCM16[b & 0x7f];
- else
- s += tableDPCM16[b];
-
- s = CLIP<int32>(s, -32768, 32767);
- *out++ = TO_BE_16(s);
- }
-}
-
-static void deDPCM8Nibble(byte *soundBuf, int32 &s, byte b) {
- if (b & 8)
- s -= tableDPCM8[7 - (b & 7)];
- else
- s += tableDPCM8[b & 7];
- s = CLIP<int32>(s, 0, 255);
- *soundBuf = s;
-}
-
-static void deDPCM8(byte *soundBuf, Common::SeekableReadStream &audioStream, uint32 n) {
- int32 s = 0x80;
-
- for (uint i = 0; i < n; i++) {
- byte b = audioStream.readByte();
-
- deDPCM8Nibble(soundBuf++, s, b >> 4);
- deDPCM8Nibble(soundBuf++, s, b & 0xf);
- }
-}
-
-// Sierra SOL audio file reader
-// Check here for more info: http://wiki.multimedia.cx/index.php?title=Sierra_Audio
-static bool readSOLHeader(Common::SeekableReadStream *audioStream, int headerSize, uint32 &size, uint16 &audioRate, byte &audioFlags) {
- if (headerSize != 11 && headerSize != 12) {
- warning("SOL audio header of size %i not supported", headerSize);
- return false;
- }
-
- audioStream->readUint32LE(); // skip "SOL" + 0 (4 bytes)
- audioRate = audioStream->readUint16LE();
- audioFlags = audioStream->readByte();
-
- size = audioStream->readUint32LE();
- return true;
-}
-
-static byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 &size, byte audioFlags, byte &flags) {
- byte *buffer;
-
- // Convert the SOL stream flags to our own format
- flags = 0;
- if (audioFlags & kSolFlag16Bit)
- flags |= Audio::Mixer::FLAG_16BITS;
- if (!(audioFlags & kSolFlagIsSigned))
- flags |= Audio::Mixer::FLAG_UNSIGNED;
-
- if (audioFlags & kSolFlagCompressed) {
- buffer = (byte *)malloc(size * 2);
-
- if (audioFlags & kSolFlag16Bit)
- deDPCM16(buffer, *audioStream, size);
- else
- deDPCM8(buffer, *audioStream, size);
-
- size *= 2;
- } else {
- // We assume that the sound data is raw PCM
- buffer = (byte *)malloc(size);
- audioStream->read(buffer, size);
- }
-
- return buffer;
-}
-
-Audio::AudioStream* AudioResource::getAudioStream(uint32 audioNumber, uint32 volume, int *sampleLen) {
- Audio::AudioStream *audioStream = 0;
- uint32 offset;
- uint32 size;
- bool found = false;
- byte *data = 0;
- char filename[40];
- byte flags = 0;
- Sci::Resource* audioRes = NULL;
-
- // Try to load from resource manager
- if (volume == 65535)
- audioRes = _resMgr->findResource(ResourceId(kResourceTypeAudio, audioNumber), false);
- else
- audioRes = _resMgr->findResource(ResourceId(kResourceTypeAudio36, volume, audioNumber), false);
-
- if (audioRes) {
- if (_sciVersion < SCI_VERSION_1_1) {
- size = audioRes->size;
- data = audioRes->data;
- } else {
- byte audioFlags;
-
- Common::MemoryReadStream *headerStream =
- new Common::MemoryReadStream(audioRes->header, audioRes->headerSize, false);
-
- if (readSOLHeader(headerStream, audioRes->headerSize, size, _audioRate, audioFlags)) {
- Common::MemoryReadStream *dataStream =
- new Common::MemoryReadStream(audioRes->data, audioRes->size, false);
- data = readSOLAudio(dataStream, size, audioFlags, flags);
- delete dataStream;
- }
- delete headerStream;
- }
-
- if (data) {
- audioStream = Audio::makeLinearInputStream(data, size, _audioRate,
- flags | Audio::Mixer::FLAG_AUTOFREE, 0, 0);
- }
- } else {
- // Load it from the audio file
- if (_sciVersion < SCI_VERSION_1_1) {
- byte sci1Volume;
- found = findAudEntrySCI1(audioNumber, sci1Volume, offset, size);
- sprintf(filename, "AUDIO%03d.%03d", _lang, sci1Volume);
- flags |= Audio::Mixer::FLAG_UNSIGNED;
- }
-
- if (found) {
- #if 0
- // TODO: This tries to load directly from the KQ5CD audio file with MP3/OGG/FLAC
- // compression. Once we got a tool to compress this file AND update the map file
- // at the same time, we can use this code to play compressed audio.
- if (_sciVersion < SCI_VERSION_1_1) {
- uint32 start = offset * 1000 / _audioRate;
- uint32 duration = size * 1000 / _audioRate;
-
- // Try to load compressed
- audioStream = Audio::AudioStream::openStreamFile(filename, start, duration);
- }
- #endif
-
- if (!audioStream) {
- // Compressed file load failed, try to load original raw data
- Common::File* audioFile = new Common::File();
- if (audioFile->open(filename)) {
- audioFile->seek(offset);
-
- if (_sciVersion < SCI_VERSION_1_1) {
- data = (byte *)malloc(size);
- audioFile->read(data, size);
- } else {
- byte type = audioFile->readByte() & 0x7f;
- byte audioFlags;
-
- if (type != kResourceTypeAudio) {
- warning("Resource type mismatch");
- delete audioFile;
- return NULL;
- }
-
- byte headerSize = audioFile->readByte();
-
- if (readSOLHeader(audioFile, headerSize, size, _audioRate, audioFlags))
- data = readSOLAudio(audioFile, size, audioFlags, flags);
-
- if (!data) {
- delete audioFile;
- return NULL;
- }
- }
-
- audioFile->close();
-
- if (data) {
- audioStream = Audio::makeLinearInputStream(data, size, _audioRate,
- flags | Audio::Mixer::FLAG_AUTOFREE, 0, 0);
- }
- }
-
- delete audioFile;
- }
- } else {
- warning("Failed to find audio entry (%i, %i, %i, %i, %i)", volume, (audioNumber >> 24) & 0xff,
- (audioNumber >> 16) & 0xff, (audioNumber >> 8) & 0xff, audioNumber & 0xff);
- }
- }
-
- if (audioStream) {
- *sampleLen = (flags & Audio::Mixer::FLAG_16BITS ? size >> 1 : size) * 60 / _audioRate;
- return audioStream;
- }
-
- return NULL;
-}
-
} // End of namespace Sci
diff --git a/engines/sci/resource.h b/engines/sci/resource.h
index fc3f37f25c..77c92840ee 100644
--- a/engines/sci/resource.h
+++ b/engines/sci/resource.h
@@ -72,19 +72,14 @@ enum {
enum ResSourceType {
kSourceDirectory = 0,
- kSourcePatch = 1,
- kSourceVolume = 2,
- kSourceExtMap = 3,
- kSourceIntMap = 4,
- kSourceAudioVolume = 5,
- kSourceMask = 127
+ kSourcePatch,
+ kSourceVolume,
+ kSourceExtMap,
+ kSourceIntMap,
+ kSourceAudioVolume,
+ kSourceExtAudioMap
};
-#define RESSOURCE_ADDRESSING_BASIC 0
-#define RESSOURCE_ADDRESSING_EXTENDED 128
-#define RESSOURCE_ADDRESSING_MASK 128
-
-#define RESOURCE_HASH(type, number) (uint32)((type<<16) | number)
#define SCI0_RESMAP_ENTRIES_SIZE 6
#define SCI1_RESMAP_ENTRIES_SIZE 6
#define SCI11_RESMAP_ENTRIES_SIZE 5
@@ -136,7 +131,6 @@ struct ResourceSource {
Common::String location_name; // FIXME: Replace by FSNode ?
int volume_number;
ResourceSource *associated_map;
- ResourceSource *next;
};
class ResourceManager;
@@ -270,6 +264,8 @@ public:
*/
Common::List<ResourceId> *listResources(ResourceType type, int mapNumber = -1);
+ void setAudioLanguage(int language);
+
protected:
int _maxMemory; //!< Config option: Maximum total byte number allocated
Common::List<ResourceSource *> _sources;
@@ -278,6 +274,7 @@ protected:
Common::List<Resource *> _LRU; //!< Last Resource Used list
ResourceMap _resMap;
Common::List<Common::File *> _volumeFiles; //!< list of opened volume files
+ ResourceSource *_audioMapSCI1; //!< Currently loaded audio map for SCI1
/**
* Add a path to the resource manager's list of sources.
@@ -325,11 +322,13 @@ protected:
void loadResource(Resource *res);
bool loadPatch(Resource *res, Common::File &file);
bool loadFromPatchFile(Resource *res);
- bool loadFromAudioVolume(Resource *res, Common::File &file);
- void freeOldResources(int last_invulnerable);
+ bool loadFromAudioVolumeSCI1(Resource *res, Common::File &file);
+ bool loadFromAudioVolumeSCI11(Resource *res, Common::File &file);
+ void freeOldResources();
int decompress(Resource *res, Common::File *file);
int readResourceInfo(Resource *res, Common::File *file, uint32&szPacked, ResourceCompression &compression);
void addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size = 0);
+ void removeAudioResource(ResourceId resId);
/**--- Resource map decoding functions ---*/
int detectMapVersion();
@@ -337,21 +336,32 @@ protected:
/**
* Reads the SCI0 resource.map file from a local directory.
+ * @param map The map
* @return 0 on success, an SCI_ERROR_* code otherwise
*/
int readResourceMapSCI0(ResourceSource *map);
/**
* Reads the SCI1 resource.map file from a local directory.
+ * @param map The map
* @return 0 on success, an SCI_ERROR_* code otherwise
*/
int readResourceMapSCI1(ResourceSource *map);
/**
- * Reads SCI1.1 MAP resources
+ * Reads SCI1.1 audio map resources
+ * @param map The map
* @return 0 on success, an SCI_ERROR_* code otherwise
*/
- int readMap(ResourceSource *map);
+ int readAudioMapSCI11(ResourceSource *map);
+
+ /**
+ * Reads SCI1 audio map files
+ * @param map The map
+ * @param unload Unload the map instead of loading it
+ * @return 0 on success, an SCI_ERROR_* code otherwise
+ */
+ int readAudioMapSCI1(ResourceSource *map, bool unload = false);
/**--- Patch management functions ---*/
@@ -368,60 +378,6 @@ protected:
int guessSciVersion();
};
-/**
- * Used for lip and animation syncing in CD talkie games
- */
-class ResourceSync : public Resource {
-public:
- ResourceSync() {}
- ~ResourceSync() {}
-
- void startSync(EngineState *s, reg_t obj);
- void nextSync(EngineState *s, reg_t obj);
- void stopSync();
-
-protected:
- uint16 *_ptr;
- int16 _syncTime, _syncCue;
- //bool _syncStarted; // not used
-};
-
-/**
- * Used for speech playback and digital music playback
- * in CD talkie games
- */
-class AudioResource {
-public:
- AudioResource(ResourceManager *resMgr, int sciVersion);
- ~AudioResource();
-
- void setAudioRate(uint16 audioRate) { _audioRate = audioRate; }
- void setAudioLang(int16 lang);
-
- Audio::SoundHandle* getAudioHandle() { return &_audioHandle; }
- int getAudioPosition();
-
- Audio::AudioStream* getAudioStream(uint32 audioNumber, uint32 volume, int *sampleLen);
-
- void stop() { g_system->getMixer()->stopHandle(_audioHandle); }
- void pause() { g_system->getMixer()->pauseHandle(_audioHandle, true); }
- void resume() { g_system->getMixer()->pauseHandle(_audioHandle, false); }
-
-private:
- Audio::SoundHandle _audioHandle;
- uint16 _audioRate;
- int16 _lang;
- byte *_audioMapSCI1;
- Resource *_audioMapSCI11;
- ResourceManager *_resMgr;
- int _sciVersion;
-
- bool findAudEntrySCI1(uint16 audioNumber, byte &volume, uint32 &offset, uint32 &size);
- bool findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 &offset, bool getSync = false, uint32 *size = NULL);
- bool findAudEntrySCI11Late(uint32 audioNumber, uint32 &offset, bool getSync, uint32 *size);
- bool findAudEntrySCI11Early(uint32 audioNumber, uint32 &offset, bool getSync, uint32 *size);
-};
-
} // End of namespace Sci
#endif // SCI_SCICORE_RESOURCE_H
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index f58d729bf6..9b277b058f 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -158,7 +158,8 @@ Common::Error SciEngine::run() {
if (flags & GF_SCI0_OLD ||
flags & GF_SCI0_OLDGFXFUNCS ||
- flags & GF_SCI0_OLDGETTIME) {
+ flags & GF_SCI0_OLDGETTIME ||
+ flags & GF_SCI0_SCI1VOCAB) {
error("This game entry is erroneous. It's marked as SCI1, but it has SCI0 flags set");
}
} else if (version == SCI_VERSION_1_1 || version == SCI_VERSION_32) {
@@ -170,7 +171,8 @@ Common::Error SciEngine::run() {
if (flags & GF_SCI0_OLD ||
flags & GF_SCI0_OLDGFXFUNCS ||
- flags & GF_SCI0_OLDGETTIME) {
+ flags & GF_SCI0_OLDGETTIME ||
+ flags & GF_SCI0_SCI1VOCAB) {
error("This game entry is erroneous. It's marked as SCI1.1/SCI32, but it has SCI0 flags set");
}
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index 91f491fe71..18b1b93a92 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -108,6 +108,11 @@ enum SciGameFlags {
** Older SCI versions had simpler code for GetTime()
*/
GF_SCI0_OLDGETTIME = (1 << 2),
+
+ /* Applies to any game that requires the SCI1 kernel vocab
+ ** Some games (such as the King's Quest I demo) require the default kernel vocab table.
+ */
+ GF_SCI0_SCI1VOCAB = (1 << 3),
// ----------------------------------------------------------------------------
@@ -118,18 +123,18 @@ enum SciGameFlags {
/*
** Used to distinguish SCI1 EGA games
*/
- GF_SCI1_EGA = (1 << 3),
+ GF_SCI1_EGA = (1 << 4),
/* Applies to all SCI1 versions after 1.000.200
** In late SCI1 versions, the argument of lofs[as] instructions
** is absolute rather than relative.
*/
- GF_SCI1_LOFSABSOLUTE = (1 << 4),
+ GF_SCI1_LOFSABSOLUTE = (1 << 5),
/* Applies to all versions from 1.000.510 onwards
** kDoSound() is different than in earlier SCI1 versions.
*/
- GF_SCI1_NEWDOSOUND = (1 << 5)
+ GF_SCI1_NEWDOSOUND = (1 << 6)
};
class SciEngine : public Engine {
diff --git a/engines/sci/sfx/core.cpp b/engines/sci/sfx/core.cpp
index e37007bf8e..9bf7730fc9 100644
--- a/engines/sci/sfx/core.cpp
+++ b/engines/sci/sfx/core.cpp
@@ -348,11 +348,13 @@ SfxState::SfxState() {
_flags = 0;
_song = NULL;
_suspended = 0;
- _soundSync = 0;
- _audioResource = 0;
+ _syncResource = NULL;
+ _audioRate = 11025;
}
SfxState::~SfxState() {
+ if (_syncResource)
+ _resMgr->unlockResource(_syncResource);
}
@@ -526,7 +528,7 @@ void SfxState::updateSingleSong() {
debugMessage += " none\n";
}
- debugC(2, kDebugLevelSound, debugMessage.c_str());
+ debugC(2, kDebugLevelSound, "%s", debugMessage.c_str());
_song = newsong;
thawTime(); /* Recover song delay time */
@@ -641,8 +643,8 @@ void SfxState::sfx_init(ResourceManager *resmgr, int flags) {
_songlib._lib = 0;
_song = NULL;
_flags = flags;
- _soundSync = NULL;
- _audioResource = NULL;
+ _syncResource = NULL;
+ _syncOffset = 0;
player = NULL;
@@ -676,6 +678,8 @@ void SfxState::sfx_init(ResourceManager *resmgr, int flags) {
delete player;
player = NULL;
}
+
+ _resMgr = resmgr;
}
void SfxState::sfx_exit() {
@@ -689,12 +693,6 @@ void SfxState::sfx_exit() {
g_system->getMixer()->stopAll();
_songlib.freeSounds();
-
- // Delete audio resources for CD talkie games
- if (_audioResource) {
- delete _audioResource;
- _audioResource = 0;
- }
}
void SfxState::sfx_suspend(bool suspend) {
@@ -1004,4 +1002,187 @@ void SfxState::sfx_all_stop() {
update();
}
+int SfxState::startAudio(uint16 module, uint32 number) {
+ int sampleLen;
+ Audio::AudioStream *audioStream = getAudioStream(number, module, &sampleLen);
+
+ if (audioStream) {
+ g_system->getMixer()->playInputStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream);
+ return sampleLen;
+ }
+
+ return 0;
+}
+
+int SfxState::getAudioPosition() {
+ if (g_system->getMixer()->isSoundHandleActive(_audioHandle))
+ return g_system->getMixer()->getSoundElapsedTime(_audioHandle) * 6 / 100; // return elapsed time in ticks
+ else
+ return -1; // Sound finished
+}
+
+enum SolFlags {
+ kSolFlagCompressed = 1 << 0,
+ kSolFlagUnknown = 1 << 1,
+ kSolFlag16Bit = 1 << 2,
+ kSolFlagIsSigned = 1 << 3
+};
+
+// FIXME: Move this to sound/adpcm.cpp?
+// Note that the 16-bit version is also used in coktelvideo.cpp
+static const uint16 tableDPCM16[128] = {
+ 0x0000, 0x0008, 0x0010, 0x0020, 0x0030, 0x0040, 0x0050, 0x0060, 0x0070, 0x0080,
+ 0x0090, 0x00A0, 0x00B0, 0x00C0, 0x00D0, 0x00E0, 0x00F0, 0x0100, 0x0110, 0x0120,
+ 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x0180, 0x0190, 0x01A0, 0x01B0, 0x01C0,
+ 0x01D0, 0x01E0, 0x01F0, 0x0200, 0x0208, 0x0210, 0x0218, 0x0220, 0x0228, 0x0230,
+ 0x0238, 0x0240, 0x0248, 0x0250, 0x0258, 0x0260, 0x0268, 0x0270, 0x0278, 0x0280,
+ 0x0288, 0x0290, 0x0298, 0x02A0, 0x02A8, 0x02B0, 0x02B8, 0x02C0, 0x02C8, 0x02D0,
+ 0x02D8, 0x02E0, 0x02E8, 0x02F0, 0x02F8, 0x0300, 0x0308, 0x0310, 0x0318, 0x0320,
+ 0x0328, 0x0330, 0x0338, 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370,
+ 0x0378, 0x0380, 0x0388, 0x0390, 0x0398, 0x03A0, 0x03A8, 0x03B0, 0x03B8, 0x03C0,
+ 0x03C8, 0x03D0, 0x03D8, 0x03E0, 0x03E8, 0x03F0, 0x03F8, 0x0400, 0x0440, 0x0480,
+ 0x04C0, 0x0500, 0x0540, 0x0580, 0x05C0, 0x0600, 0x0640, 0x0680, 0x06C0, 0x0700,
+ 0x0740, 0x0780, 0x07C0, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00,
+ 0x0F00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
+};
+
+static const byte tableDPCM8[8] = {0, 1, 2, 3, 6, 10, 15, 21};
+
+static void deDPCM16(byte *soundBuf, Common::SeekableReadStream &audioStream, uint32 n) {
+ int16 *out = (int16 *) soundBuf;
+
+ int32 s = 0;
+ for (uint32 i = 0; i < n; i++) {
+ byte b = audioStream.readByte();
+ if (b & 0x80)
+ s -= tableDPCM16[b & 0x7f];
+ else
+ s += tableDPCM16[b];
+
+ s = CLIP<int32>(s, -32768, 32767);
+ *out++ = TO_BE_16(s);
+ }
+}
+
+static void deDPCM8Nibble(byte *soundBuf, int32 &s, byte b) {
+ if (b & 8)
+ s -= tableDPCM8[7 - (b & 7)];
+ else
+ s += tableDPCM8[b & 7];
+ s = CLIP<int32>(s, 0, 255);
+ *soundBuf = s;
+}
+
+static void deDPCM8(byte *soundBuf, Common::SeekableReadStream &audioStream, uint32 n) {
+ int32 s = 0x80;
+
+ for (uint i = 0; i < n; i++) {
+ byte b = audioStream.readByte();
+
+ deDPCM8Nibble(soundBuf++, s, b >> 4);
+ deDPCM8Nibble(soundBuf++, s, b & 0xf);
+ }
+}
+
+// Sierra SOL audio file reader
+// Check here for more info: http://wiki.multimedia.cx/index.php?title=Sierra_Audio
+static bool readSOLHeader(Common::SeekableReadStream *audioStream, int headerSize, uint32 &size, uint16 &audioRate, byte &audioFlags) {
+ if (headerSize != 11 && headerSize != 12) {
+ warning("SOL audio header of size %i not supported", headerSize);
+ return false;
+ }
+
+ audioStream->readUint32LE(); // skip "SOL" + 0 (4 bytes)
+ audioRate = audioStream->readUint16LE();
+ audioFlags = audioStream->readByte();
+
+ size = audioStream->readUint32LE();
+ return true;
+}
+
+static byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 &size, byte audioFlags, byte &flags) {
+ byte *buffer;
+
+ // Convert the SOL stream flags to our own format
+ flags = 0;
+ if (audioFlags & kSolFlag16Bit)
+ flags |= Audio::Mixer::FLAG_16BITS;
+ if (!(audioFlags & kSolFlagIsSigned))
+ flags |= Audio::Mixer::FLAG_UNSIGNED;
+
+ if (audioFlags & kSolFlagCompressed) {
+ buffer = (byte *)malloc(size * 2);
+
+ if (audioFlags & kSolFlag16Bit)
+ deDPCM16(buffer, *audioStream, size);
+ else
+ deDPCM8(buffer, *audioStream, size);
+
+ size *= 2;
+ } else {
+ // We assume that the sound data is raw PCM
+ buffer = (byte *)malloc(size);
+ audioStream->read(buffer, size);
+ }
+
+ return buffer;
+}
+
+Audio::AudioStream* SfxState::getAudioStream(uint32 number, uint32 volume, int *sampleLen) {
+ Audio::AudioStream *audioStream = 0;
+ uint32 size;
+ byte *data = 0;
+ byte flags = 0;
+ Sci::Resource* audioRes;
+
+ if (volume == 65535) {
+ audioRes = _resMgr->findResource(ResourceId(kResourceTypeAudio, number), false);
+ if (!audioRes) {
+ warning("Failed to find audio entry %i", number);
+ return NULL;
+ }
+ } else {
+ audioRes = _resMgr->findResource(ResourceId(kResourceTypeAudio36, volume, number), false);
+ if (!audioRes) {
+ warning("Failed to find audio entry (%i, %i, %i, %i, %i)", volume, (number >> 24) & 0xff,
+ (number >> 16) & 0xff, (number >> 8) & 0xff, number & 0xff);
+ return NULL;
+ }
+ }
+
+ byte audioFlags;
+
+ if (audioRes->headerSize > 0) {
+ // SCI1.1
+ Common::MemoryReadStream *headerStream =
+ new Common::MemoryReadStream(audioRes->header, audioRes->headerSize, false);
+
+ if (readSOLHeader(headerStream, audioRes->headerSize, size, _audioRate, audioFlags)) {
+ Common::MemoryReadStream *dataStream =
+ new Common::MemoryReadStream(audioRes->data, audioRes->size, false);
+ data = readSOLAudio(dataStream, size, audioFlags, flags);
+ delete dataStream;
+ }
+ delete headerStream;
+ } else {
+ // SCI1
+ size = audioRes->size;
+ data = (byte *)malloc(size);
+ assert(data);
+ memcpy(data, audioRes->data, size);
+ flags = Audio::Mixer::FLAG_UNSIGNED;
+ }
+
+ if (data) {
+ audioStream = Audio::makeLinearInputStream(data, size, _audioRate,
+ flags | Audio::Mixer::FLAG_AUTOFREE, 0, 0);
+ if (audioStream) {
+ *sampleLen = (flags & Audio::Mixer::FLAG_16BITS ? size >> 1 : size) * 60 / _audioRate;
+ return audioStream;
+ }
+ }
+
+ return NULL;
+}
+
} // End of namespace Sci
diff --git a/engines/sci/sfx/core.h b/engines/sci/sfx/core.h
index 5db56bd864..e7eba85c99 100644
--- a/engines/sci/sfx/core.h
+++ b/engines/sci/sfx/core.h
@@ -50,8 +50,9 @@ public: // FIXME, make private
SongLibrary _songlib; /**< Song library */
Song *_song; /**< Active song, or start of active song chain */
bool _suspended; /**< Whether we are suspended */
- ResourceSync *_soundSync; /**< Used by kDoSync for speech syncing in CD talkie games */
- AudioResource *_audioResource; /**< Used for audio resources in CD talkie games */
+ Resource *_syncResource; /**< Used by kDoSync for speech syncing in CD talkie games */
+ uint _syncOffset;
+ ResourceManager *_resMgr;
public:
SfxState();
@@ -164,6 +165,15 @@ public:
Common::Error sfx_send_midi(SongHandle handle, int channel,
int command, int arg1, int arg2);
+ // Functions for digital sound
+ void setAudioRate(uint16 rate) { _audioRate = rate; }
+ Audio::SoundHandle* getAudioHandle() { return &_audioHandle; }
+ int getAudioPosition();
+ int startAudio(uint16 module, uint32 tuple);
+ void stopAudio() { g_system->getMixer()->stopHandle(_audioHandle); }
+ void pauseAudio() { g_system->getMixer()->pauseHandle(_audioHandle, true); }
+ void resumeAudio() { g_system->getMixer()->pauseHandle(_audioHandle, false); }
+
protected:
void freezeTime();
void thawTime();
@@ -173,8 +183,12 @@ protected:
void updateSingleSong();
void updateMultiSong();
void update();
-};
+private:
+ uint16 _audioRate;
+ Audio::SoundHandle _audioHandle;
+ Audio::AudioStream* getAudioStream(uint32 number, uint32 volume, int *sampleLen);
+};
} // End of namespace Sci
diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp
index cf90094112..88c258a2e6 100644
--- a/engines/scumm/actor.cpp
+++ b/engines/scumm/actor.cpp
@@ -1348,6 +1348,22 @@ void ScummEngine::processActors() {
}
}
}
+ } else if (_game.heversion >= 90) {
+ for (int j = 0; j < numactors; ++j) {
+ for (int i = 0; i < numactors; ++i) {
+ int sc_actor1 = _sortedActors[j]->_layer;
+ int sc_actor2 = _sortedActors[i]->_layer;
+ if (sc_actor1 < sc_actor2) {
+ SWAP(_sortedActors[i], _sortedActors[j]);
+ } else if (sc_actor1 == sc_actor2) {
+ sc_actor1 = _sortedActors[j]->getPos().y;
+ sc_actor2 = _sortedActors[i]->getPos().y;
+ if (sc_actor1 < sc_actor2) {
+ SWAP(_sortedActors[i], _sortedActors[j]);
+ }
+ }
+ }
+ }
} else {
for (int j = 0; j < numactors; ++j) {
for (int i = 0; i < numactors; ++i) {
diff --git a/engines/scumm/he/script_v100he.cpp b/engines/scumm/he/script_v100he.cpp
index 665782bf36..fe0904d632 100644
--- a/engines/scumm/he/script_v100he.cpp
+++ b/engines/scumm/he/script_v100he.cpp
@@ -420,8 +420,7 @@ void ScummEngine_v100he::o100_actorOps() {
a->_needRedraw = true;
break;
case 59:
- // HE games use reverse order of layering, so we adjust
- a->_layer = -pop();
+ a->_layer = pop();
a->_needRedraw = true;
break;
case 63:
diff --git a/engines/scumm/he/script_v72he.cpp b/engines/scumm/he/script_v72he.cpp
index bb209e78d1..64c63baa9d 100644
--- a/engines/scumm/he/script_v72he.cpp
+++ b/engines/scumm/he/script_v72he.cpp
@@ -770,8 +770,7 @@ void ScummEngine_v72he::o72_actorOps() {
a->setTalkCondition(k);
break;
case 43: // HE 90+
- // HE games use reverse order of layering, so we adjust
- a->_layer = -pop();
+ a->_layer = pop();
a->_needRedraw = true;
break;
case 64:
diff --git a/engines/scumm/vars.cpp b/engines/scumm/vars.cpp
index caae659766..22487b43a3 100644
--- a/engines/scumm/vars.cpp
+++ b/engines/scumm/vars.cpp
@@ -727,7 +727,7 @@ void ScummEngine::resetScummVars() {
// Value only used by the Macintosh version of Indiana Jones and the Last Crusade
else if (_game.platform == Common::kPlatformMacintosh && _game.version == 3)
VAR(VAR_VIDEOMODE) = 50;
- // Value only used by the Amiga of Monkey Island 2
+ // Value only used by the Amiga version of Monkey Island 2
else if (_game.platform == Common::kPlatformAmiga)
VAR(VAR_VIDEOMODE) = 82;
else if (_renderMode == Common::kRenderCGA)
diff --git a/engines/sword1/music.cpp b/engines/sword1/music.cpp
index 9f602aca2c..fb9068dde7 100644
--- a/engines/sword1/music.cpp
+++ b/engines/sword1/music.cpp
@@ -272,7 +272,7 @@ bool MusicHandle::playPSX(uint16 id, bool loop) {
tableFile.close();
- if (size != 0xffffffff && size) {
+ if ((size != 0) && (size != 0xffffffff)) {
_file.seek(offset, SEEK_SET);
_audioSource = new Audio::VagStream(_file.readStream(size), loop);
fadeUp();
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 306d23db57..5577c66fc6 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -226,14 +226,14 @@ bool Sound::startSpeech(uint16 roomNo, uint16 localNo) {
return false;
}
- uint16 numRooms = file.readUint16LE(); // Number of rooms
+ uint16 numRooms = file.readUint16LE(); // Read number of rooms referenced in this file
file.seek(locIndex * 4 + 2); // 4 bytes per room, skip first 2 bytes
uint16 numLines = file.readUint16LE();
uint16 roomOffset = file.readUint16LE();
- file.seek(2 + numRooms * 4 + roomOffset * 2); // The offset is in terms of uint16's, so multiply by 2. Skip the 0x112 byte header too.
+ file.seek(2 + numRooms * 4 + roomOffset * 2); // The offset is in terms of uint16's, so multiply by 2. Skip the room indexes too.
locIndex = 0xFFFFFFFF;
diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp
index 863848bee1..a3cd0bc7b7 100644
--- a/engines/tinsel/detection.cpp
+++ b/engines/tinsel/detection.cpp
@@ -297,15 +297,11 @@ static const TinselGameDescription gameDescriptions[] = {
TINSEL_V1,
},
- { // UK multilanguage PSX CD
+ { // Discworld PSX CD
{
"dw",
"CD",
{
- {"french.txt", 0, "e7020d35f58d0d187052ac406d86cc87", 273918},
- {"german.txt", 0, "6e2c0f0655bc3cec5a6b3552164ec984", 263942},
- {"italian.txt", 0, "15f0703f85477d7fab4280bf938b61c1", 239830},
- {"spanish.txt", 0, "bda9bea9078d1483409082a3e180378a", 236702},
{"english.txt", 0, "7526cfc3a64e00f223795de476b4e2c9", 230326},
{NULL, 0, NULL, 0}
},
diff --git a/engines/tinsel/palette.cpp b/engines/tinsel/palette.cpp
index c544bddbb1..8df9e9a375 100644
--- a/engines/tinsel/palette.cpp
+++ b/engines/tinsel/palette.cpp
@@ -99,6 +99,7 @@ void psxPaletteMapper(PALQ *originalPal, uint8 *psxClut, byte *mapperTable) {
bool colorFound = false;
uint16 clutEntry = 0;
+ // Empty the table with color correspondences
memset(mapperTable, 0, 16);
for (int j = 1; j < 16; j++) {
@@ -115,7 +116,7 @@ void psxPaletteMapper(PALQ *originalPal, uint8 *psxClut, byte *mapperTable) {
uint16 psxEquivalent = TINSEL_PSX_RGB(TINSEL_GetRValue(pal->palRGB[i]) >> 3, TINSEL_GetGValue(pal->palRGB[i]) >> 3, TINSEL_GetBValue(pal->palRGB[i]) >> 3);
if (psxEquivalent == clutEntry) {
- mapperTable[j] = i + 1;
+ mapperTable[j] = i + 1; // Add entry in the table for the found color
colorFound = true;
}
}
diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp
index 47602b5862..1a08fd2420 100644
--- a/engines/tinsel/tinsel.cpp
+++ b/engines/tinsel/tinsel.cpp
@@ -850,19 +850,8 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc)
Common::File::addDefaultDirectory(_gameDataDir.getChild("dw2"));
// Add subfolders needed for psx versions of Discworld 1
- if(TinselV1PSX) {
- Common::File::addDefaultDirectory(_gameDataDir.getChild("MIDI"));
- Common::File::addDefaultDirectory(_gameDataDir.getChild("SAMPLES"));
- Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX"));
- Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX").getChild("GFXAB"));
- Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX").getChild("GFXC"));
- Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX").getChild("GFXDG"));
- Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX").getChild("GFXHL"));
- Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX").getChild("GFXMO"));
- Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX").getChild("GFXP"));
- Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX").getChild("GFXRS"));
- Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX").getChild("GFXTW"));
- }
+ if (TinselV1PSX)
+ SearchMan.addDirectory(_gameDataDir.getPath(), _gameDataDir, 0, 3, true);
const GameSettings *g;
diff --git a/engines/tucker/locations.cpp b/engines/tucker/locations.cpp
index ec60086abf..9faa2024a6 100644
--- a/engines/tucker/locations.cpp
+++ b/engines/tucker/locations.cpp
@@ -650,21 +650,17 @@ void TuckerEngine::execData3PostUpdate_locationNum8() {
if (_execData3Counter > 30) {
_updateLocationYPosTable2[0] = 16;
_updateLocationXPosTable2[0] = 264;
-
}
}
if (_updateLocationYPosTable2[0] > 0) {
const int offset = _updateLocationYPosTable2[0] * 640 + _updateLocationXPosTable2[0];
- _locationBackgroundGfxBuf[offset] = 142;
- _locationBackgroundGfxBuf[offset + 640 - 1] = 143;
- _locationBackgroundGfxBuf[offset + 640] = 143;
- _locationBackgroundGfxBuf[offset + 640 + 1] = 144;
- _locationBackgroundGfxBuf[offset + 640 * 2 - 1] = 144;
- _locationBackgroundGfxBuf[offset + 640 * 2] = 144;
- _locationBackgroundGfxBuf[offset + 640 * 2 + 1] = 145;
- _locationBackgroundGfxBuf[offset + 640 * 3 - 1] = 147;
- _locationBackgroundGfxBuf[offset + 640 * 3] = 143;
- _locationBackgroundGfxBuf[offset + 640 * 3 + 1] = 147;
+ static const int colorsTable[] = { 143, 143, 144, 144, 144, 145, 147, 143, 147 };
+ _locationBackgroundGfxBuf[offset] = 142;
+ for (int j = 1; j <= 3; ++j) {
+ for (int i = -1; i <= 1; ++i) {
+ _locationBackgroundGfxBuf[offset + 640 * j + i] = colorsTable[(j - 1) * 3 + i + 1];
+ }
+ }
addDirtyRect(_updateLocationXPosTable2[0] - 1, _updateLocationYPosTable2[0], 3, 4);
_updateLocationYPosTable2[0] += 2;
if (_updateLocationYPosTable2[0] > 120) {
diff --git a/engines/tucker/resource.cpp b/engines/tucker/resource.cpp
index 1195fe4894..11c1c78133 100644
--- a/engines/tucker/resource.cpp
+++ b/engines/tucker/resource.cpp
@@ -218,6 +218,7 @@ void TuckerEngine::openCompressedSoundFile() {
int version = _fCompressedSound.readUint16LE();
if (version == kCurrentCompressedSoundDataVersion) {
_compressedSoundType = i;
+ debug(1, "Using compressed sound file '%s'", compressedSoundFilesTable[i].filename);
return;
}
warning("Unhandled version %d for compressed sound file '%s'", version, compressedSoundFilesTable[i].filename);
diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp
index d977813a31..11a535e54a 100644
--- a/engines/tucker/sequences.cpp
+++ b/engines/tucker/sequences.cpp
@@ -494,13 +494,9 @@ int TuckerEngine::handleSpecialObjectSelectionSequence() {
AnimationSequencePlayer::AnimationSequencePlayer(OSystem *system, Audio::Mixer *mixer, Common::EventManager *event, int num)
: _system(system), _mixer(mixer), _event(event), _seqNum(num) {
memset(_animationPalette, 0, sizeof(_animationPalette));
- _soundSeqDataOffset = 0;
_soundSeqDataCount = 0;
_soundSeqDataIndex = 0;
- _soundsList1Offset = 0;
- _soundsList1Count = 0;
- _soundsList2Offset = 0;
- _soundsList2Count = 0;
+ _soundSeqData = 0;
_offscreenBuffer = (uint8 *)malloc(kScreenWidth * kScreenHeight);
_updateScreenWidth = 0;
_updateScreenPicture = false;
@@ -589,20 +585,9 @@ void AnimationSequencePlayer::syncTime() {
}
Audio::AudioStream *AnimationSequencePlayer::loadSoundFileAsStream(int index, AnimationSoundType type) {
- const char *name = 0;
- switch (type) {
- case kAnimationSoundType8BitsRAW:
- case kAnimationSoundType16BitsRAW:
- name = _musicFileNamesTable[index];
- break;
- case kAnimationSoundTypeWAV:
- case kAnimationSoundTypeLoopingWAV:
- name = _audioFileNamesTable[index];
- break;
- }
Audio::AudioStream *stream = 0;
char fileName[64];
- snprintf(fileName, sizeof(fileName), "audio/%s", name);
+ snprintf(fileName, sizeof(fileName), "audio/%s", _audioFileNamesTable[index]);
Common::File f;
if (f.open(fileName)) {
int size = 0, rate = 0;
@@ -637,88 +622,53 @@ Audio::AudioStream *AnimationSequencePlayer::loadSoundFileAsStream(int index, An
return stream;
}
-enum {
- kSoundsList_Seq3_4,
- kSoundsList_Seq9_10,
- kSoundsList_Seq21_20,
- kSoundsList_Seq13_14,
- kSoundsList_Seq15_16,
- kSoundsList_Seq27_28,
- kSoundsList_Seq17_18,
- kSoundsList_Seq19_20
-};
-
void AnimationSequencePlayer::loadSounds(int num) {
- static const int soundsList[][8] = {
- { 1, 0, 14, 0, 10, 14, 58, 0 },
- { 1, 0, 14, 24, 5, 38, 60, 58 },
- { 1, 0, 14, 43, 9, 57, 48, 118 },
- { 6, 80, 14, 79, 4, 93, 25, 185 },
- { 7, 80, 13, 97, 9, 110, 43, 210 },
- { 10, 80, 11, 119, 0, 0, 11, 253 },
- { 8, 100, 0, 0, 0, 0, 0, 0 },
- { 0, 100, 4, 146, 0, 0, 7, 300 }
- };
- int musicIndex = soundsList[num][0];
- int musicVolume = soundsList[num][1];
- _soundsList1Count = soundsList[num][2];
- _soundsList1Offset = soundsList[num][3];
- _soundsList2Count = soundsList[num][4];
- _soundsList2Offset = soundsList[num][5];
- _soundSeqDataCount = soundsList[num][6];
- _soundSeqDataOffset = soundsList[num][7];
- if (musicVolume != 0) {
+ if (_soundSeqDataList[num].musicVolume != 0) {
Audio::AudioStream *s;
- if ((s = loadSoundFileAsStream(musicIndex, kAnimationSoundType8BitsRAW)) != 0) {
- _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, s, -1, scaleMixerVolume(musicVolume));
+ if ((s = loadSoundFileAsStream(_soundSeqDataList[num].musicIndex, kAnimationSoundType8BitsRAW)) != 0) {
+ _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, s, -1, scaleMixerVolume(_soundSeqDataList[num].musicVolume));
}
}
_soundSeqDataIndex = 0;
+ _soundSeqDataCount = _soundSeqDataList[num].soundSeqDataCount;
+ _soundSeqData = _soundSeqDataList[num].soundSeqData;
}
void AnimationSequencePlayer::updateSounds() {
Audio::AudioStream *s = 0;
- const SoundSequenceData *p = &_soundSeqData[_soundSeqDataOffset + _soundSeqDataIndex];
+ const SoundSequenceData *p = &_soundSeqData[_soundSeqDataIndex];
while (_soundSeqDataIndex < _soundSeqDataCount && p->timestamp <= _frameCounter) {
switch (p->opcode) {
case 0:
- if (p->index < _soundsList1Count) {
- if ((s = loadSoundFileAsStream(_soundsList1Offset + p->index, kAnimationSoundTypeWAV)) != 0) {
- _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_soundsHandle[p->index], s, -1, scaleMixerVolume(p->volume));
- }
+ if ((s = loadSoundFileAsStream(p->num, kAnimationSoundTypeWAV)) != 0) {
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_soundsHandle[p->index], s, -1, scaleMixerVolume(p->volume));
}
break;
case 1:
- if (p->index < _soundsList1Count) {
- if ((s = loadSoundFileAsStream(_soundsList1Offset + p->index, kAnimationSoundTypeLoopingWAV)) != 0) {
- _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_soundsHandle[p->index], s, -1, scaleMixerVolume(p->volume));
- }
+ if ((s = loadSoundFileAsStream(p->num, kAnimationSoundTypeLoopingWAV)) != 0) {
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_soundsHandle[p->index], s, -1, scaleMixerVolume(p->volume));
}
break;
case 2:
- if (p->index < _soundsList1Count) {
- _mixer->stopHandle(_soundsHandle[p->index]);
- }
+ _mixer->stopHandle(_soundsHandle[p->index]);
break;
case 3:
_mixer->stopHandle(_musicHandle);
break;
case 4:
_mixer->stopHandle(_musicHandle);
- if ((s = loadSoundFileAsStream(p->index, kAnimationSoundType8BitsRAW)) != 0) {
+ if ((s = loadSoundFileAsStream(p->num, kAnimationSoundType8BitsRAW)) != 0) {
_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, s, -1, scaleMixerVolume(p->volume));
}
break;
case 5:
- if (p->index < _soundsList2Count) {
- if ((s = loadSoundFileAsStream(_soundsList2Offset + p->index, kAnimationSoundTypeWAV)) != 0) {
- _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, s, -1, scaleMixerVolume(p->volume));
- }
+ if ((s = loadSoundFileAsStream(p->num, kAnimationSoundTypeWAV)) != 0) {
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, s, -1, scaleMixerVolume(p->volume));
}
break;
case 6:
_mixer->stopHandle(_musicHandle);
- if ((s = loadSoundFileAsStream(p->index, kAnimationSoundType16BitsRAW)) != 0) {
+ if ((s = loadSoundFileAsStream(p->num, kAnimationSoundType16BitsRAW)) != 0) {
_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, s, -1, scaleMixerVolume(p->volume));
}
break;
@@ -796,8 +746,7 @@ uint8 *AnimationSequencePlayer::loadPicture(const char *fileName) {
}
void AnimationSequencePlayer::getRGBPalette(int index) {
- byte rgbPalette[3 * 256];
- memcpy(rgbPalette, _flicPlayer[index].getPalette(), 3 * 256);
+ const byte *rgbPalette = _flicPlayer[index].getPalette();
for (int i = 0; i < 256; i++) {
_animationPalette[i * 4 + 0] = rgbPalette[i * 3 + 0];
_animationPalette[i * 4 + 1] = rgbPalette[i * 3 + 1];
diff --git a/engines/tucker/staticres.cpp b/engines/tucker/staticres.cpp
index 62472e2704..b663fb38da 100644
--- a/engines/tucker/staticres.cpp
+++ b/engines/tucker/staticres.cpp
@@ -246,138 +246,181 @@ const uint8 TuckerEngine::_charWidthCharset2[58] = {
0x13, 0x12, 0x10, 0x11, 0x13, 0x14, 0x14, 0x10, 0x13, 0x10,
};
-const SoundSequenceData AnimationSequencePlayer::_soundSeqData[] = {
- { 16, 3, 1, 100 }, { 18, 5, 1, 100 }, { 26, 9, 5, 100 }, { 74, 9, 0, 100 },
- { 118, 10, 0, 100 }, { 139, 9, 0, 100 }, { 140, 10, 2, 100 }, { 144, 5, 2, 100 },
- { 146, 3, 2, 100 }, { 147, 9, 2, 100 }, { 148, 2, 1, 100 }, { 156, 0, 1, 50 },
- { 158, 4, 5, 100 }, { 188, 4, 5, 100 }, { 212, 2, 2, 100 }, { 223, 1, 0, 100 },
- { 230, 1, 2, 100 }, { 234, 1, 0, 100 }, { 251, 1, 0, 100 }, { 265, 11, 6, 80 },
- { 293, 5, 1, 80 }, { 295, 12, 6, 80 }, { 343, 13, 6, 110 }, { 373, 14, 6, 80 },
- { 429, 5, 2, 100 }, { 431, 15, 6, 80 }, { 456, 2, 1, 100 }, { 457, 1, 5, 100 },
- { 463, 0, 5, 100 }, { 482, 2, 2, 100 }, { 483, 8, 1, 100 }, { 494, 8, 5, 100 },
- { 507, 7, 5, 100 }, { 511, 7, 5, 100 }, { 522, 13, 1, 100 }, { 547, 6, 5, 100 },
- { 548, 11, 0, 100 }, { 556, 12, 0, 100 }, { 557, 2, 5, 100 }, { 599, 7, 1, 100 },
- { 639, 7, 2, 100 }, { 641, 12, 0, 100 }, { 642, 7, 5, 100 }, { 718, 14, 2, 100 },
- { 719, 1, 2, 100 }, { 720, 2, 2, 100 }, { 721, 3, 2, 100 }, { 722, 4, 2, 100 },
- { 723, 5, 2, 100 }, { 724, 6, 2, 100 }, { 725, 7, 2, 100 }, { 726, 8, 2, 100 },
- { 727, 9, 2, 100 }, { 728, 10, 2, 100 }, { 729, 11, 2, 100 }, { 730, 12, 2, 100 },
- { 731, 0, 2, 100 }, { 732, 13, 2, 100 },
- // count 2,58
- // offset 3,58
- { 2, 0, 3, 100 }, { 3, 2, 0, 100 }, { 3, 5, 1, 20 }, { 6, 25, 6, 80 },
- { 22, 1, 5, 100 }, { 37, 29, 6, 80 }, { 59, 30, 6, 80 }, { 69, 26, 6, 80 },
- { 124, 27, 6, 80 }, { 163, 28, 6, 80 }, { 197, 31, 6, 80 }, { 224, 32, 6, 80 },
- { 306, 33, 6, 80 }, { 350, 34, 6, 80 }, { 388, 8, 0, 100 }, { 389, 6, 1, 100 },
- { 390, 9, 1, 100 }, { 395, 10, 0, 100 }, { 398, 3, 0, 100 }, { 408, 3, 0, 100 },
- { 413, 4, 0, 100 }, { 418, 3, 0, 100 }, { 426, 6, 2, 100 }, { 427, 9, 2, 100 },
- { 430, 35, 6, 80 }, { 472, 36, 6, 80 }, { 514, 9, 1, 100 }, { 515, 7, 0, 100 },
- { 516, 6, 1, 100 }, { 517, 4, 0, 100 }, { 520, 11, 0, 100 }, { 523, 3, 0, 100 },
- { 531, 7, 2, 100 }, { 532, 9, 2, 100 }, { 533, 6, 2, 100 }, { 534, 3, 0, 100 },
- { 535, 37, 6, 80 }, { 553, 38, 6, 80 }, { 569, 39, 6, 80 }, { 588, 40, 6, 80 },
- { 662, 41, 6, 80 }, { 777, 42, 6, 80 }, { 978, 1, 0, 100 }, { 1008, 12, 0, 100 },
- { 1011, 4, 5, 100 }, { 1022, 52, 6, 80 }, { 1039, 3, 5, 100 }, { 1045, 3, 5, 100 },
- { 1051, 3, 5, 100 }, { 1057, 3, 5, 100 }, { 1063, 3, 5, 100 }, { 1066, 3, 5, 40 },
- { 1074, 43, 6, 80 }, { 1256, 44, 6, 80 }, { 1322, 45, 6, 80 }, { 1373, 46, 6, 80 },
- { 1419, 47, 6, 80 }, { 1792, 13, 0, 100 }, { 1793, 0, 5, 100 }, { 1895, 51, 6, 80 },
- // count 3,60
- // offset 4,118
- { 2, 0, 3, 100 }, { 4, 3, 1, 40 }, { 5, 7, 1, 20 }, { 7, 3, 5, 100 },
- { 62, 3, 2, 100 }, { 63, 48, 6, 80 }, { 198, 7, 2, 100 }, { 202, 5, 1, 100 },
- { 203, 16, 6, 80 }, { 211, 1, 5, 100 }, { 216, 0, 1, 40 }, { 217, 5, 2, 100 },
- { 218, 6, 1, 100 }, { 224, 2, 5, 100 }, { 229, 17, 6, 80 }, { 273, 6, 2, 100 },
- { 274, 4, 1, 100 }, { 275, 4, 5, 100 }, { 335, 1, 1, 100 }, { 336, 13, 0, 100 },
- { 339, 11, 0, 100 }, { 358, 0, 5, 100 }, { 364, 24, 4, 100 }, { 397, 7, 5, 100 },
- { 399, 6, 5, 100 }, { 433, 5, 5, 100 }, { 451, 13, 0, 100 }, { 459, 1, 2, 100 },
- { 508, 4, 2, 100 }, { 509, 1, 1, 100 }, { 521, 11, 0, 100 }, { 530, 8, 0, 100 },
- { 537, 9, 0, 100 }, { 557, 8, 5, 100 }, { 578, 5, 5, 100 }, { 602, 13, 0, 100 },
- { 609, 1, 2, 100 }, { 626, 12, 0, 100 }, { 628, 10, 0, 100 }, { 670, 6, 5, 100 },
- { 690, 10, 0, 100 }, { 692, 3, 5, 100 }, { 705, 11, 0, 100 }, { 710, 2, 5, 100 },
- { 714, 9, 0, 100 }, { 720, 9, 2, 100 }, { 721, 7, 5, 100 }, { 725, 0, 5, 100 },
- // count 4,48
- // offset 5,166
- { 3, 8, 0, 100 }, { 43, 11, 0, 100 }, { 68, 5, 1, 100 }, { 100, 5, 2, 100 },
- { 104, 6, 0, 100 }, { 139, 7, 0, 100 }, { 192, 3, 0, 100 }, { 199, 4, 0, 100 },
- { 207, 4, 0, 100 }, { 208, 2, 0, 100 }, { 254, 0, 0, 100 }, { 260, 0, 0, 100 },
- { 266, 0, 0, 100 }, { 272, 0, 0, 100 }, { 276, 0, 0, 100 }, { 282, 1, 0, 100 },
- { 303, 10, 0, 100 }, { 319, 12, 0, 100 }, { 355, 9, 0, 100 },
- // count 5,19
- // offset 6,185
- { 3, 0, 1, 100 }, { 34, 0, 2, 100 }, { 57, 0, 5, 100 }, { 77, 0, 5, 100 },
- { 84, 9, 0, 100 }, { 100, 9, 0, 100 }, { 140, 3, 5, 100 }, { 157, 2, 5, 100 },
- { 158, 1, 0, 100 }, { 204, 1, 5, 100 }, { 220, 2, 1, 100 }, { 235, 7, 0, 100 },
- { 236, 2, 2, 100 }, { 248, 12, 0, 100 }, { 251, 13, 0, 100 }, { 265, 11, 0, 100 },
- { 276, 11, 0, 100 }, { 310, 5, 0, 100 }, { 335, 6, 0, 100 }, { 370, 4, 0, 100 },
- { 373, 8, 0, 100 }, { 378, 8, 0, 100 }, { 434, 10, 0, 100 }, { 453, 3, 0, 100 },
- { 484, 3, 2, 100 },
- // count 6,25
- // offset 7,210
- { 3, 4, 5, 100 }, { 10, 5, 5, 100 }, { 22, 6, 5, 100 }, { 32, 7, 5, 100 },
- { 39, 6, 5, 100 }, { 48, 7, 5, 100 }, { 57, 6, 5, 100 }, { 65, 3, 0, 50 },
- { 102, 4, 0, 50 }, { 151, 2, 5, 50 }, { 205, 3, 5, 100 }, { 218, 0, 5, 100 },
- { 227, 0, 5, 100 }, { 236, 0, 5, 100 }, { 245, 0, 5, 100 }, { 254, 0, 5, 100 },
- { 263, 0, 5, 100 }, { 272, 0, 5, 100 }, { 291, 1, 1, 40 }, { 309, 8, 5, 100 },
- { 360, 8, 5, 100 }, { 384, 2, 1, 60 }, { 398, 10, 0, 100 }, { 440, 2, 2, 100 },
- { 441, 1, 2, 100 }, { 452, 11, 0, 100 }, { 466, 1, 5, 100 }, { 470, 8, 0, 100 },
- { 503, 6, 0, 100 }, { 519, 7, 0, 100 }, { 536, 8, 0, 100 }, { 538, 4, 5, 100 },
- { 549, 5, 5, 100 }, { 558, 4, 5, 100 }, { 568, 5, 5, 100 }, { 578, 4, 5, 100 },
- { 586, 5, 5, 100 }, { 593, 4, 5, 100 }, { 600, 5, 5, 100 }, { 606, 4, 5, 100 },
- { 613, 5, 5, 100 }, { 620, 9, 0, 100 }, { 630, 12, 0, 100 },
- // count 7,43
- // offset 8,253
- { 17, 2, 0, 100 }, { 57, 8, 0, 100 }, { 62, 10, 0, 100 }, { 67, 9, 0, 100 },
- { 74, 3, 1, 100 }, { 87, 3, 2, 100 }, { 85, 0, 0, 100 }, { 138, 5, 0, 100 },
- { 196, 7, 0, 100 }, { 222, 6, 0, 100 }, { 228, 1, 0, 100 },
- // count 8,11
- // offset 9,264
- { 20, 4, 0, 100 }, { 132, 0, 0, 100 }, { 145, 0, 2, 100 }, { 171, 1, 0, 100 },
- { 315, 2, 0, 50 }, { 334, 3, 0, 100 }, { 602, 5, 0, 50 }, { 631, 5, 0, 50 },
- { 660, 5, 0, 50 }, { 767, 5, 0, 50 }, { 795, 5, 0, 50 }, { 824, 5, 0, 50 },
- // count 9,12
- // offset 10,276
- { 4, 8, 1, 100 }, { 5, 6, 0, 100 }, { 47, 8, 2, 100 }, { 125, 8, 1, 100 },
- { 126, 6, 0, 100 }, { 156, 8, 2, 100 }, { 168, 2, 0, 100 }, { 174, 2, 0, 100 },
- { 180, 2, 0, 100 }, { 186, 2, 0, 100 }, { 192, 2, 0, 100 }, { 267, 2, 0, 100 },
- { 273, 2, 0, 100 }, { 279, 2, 0, 100 }, { 285, 2, 0, 100 }, { 291, 2, 0, 100 },
- { 297, 2, 0, 100 }, { 302, 0, 0, 100 }, { 417, 1, 0, 100 }, { 472, 5, 0, 100 },
- { 600, 5, 0, 100 }, { 623, 3, 0, 100 }, { 643, 9, 0, 100 }, { 781, 4, 0, 80 },
- // count 10,24
- // offset 11,300
- { 2, 0, 3, 100 }, { 3, 0, 1, 100 }, { 33, 0, 2, 100 }, { 33, 1, 0, 100 },
- { 53, 2, 1, 100 }, { 78, 2, 2, 100 }, { 80, 0, 4, 100 }
- // count 11,7
+static const SoundSequenceData _soundDataSeq3_4[] = {
+ { 16, 3, 33, 100, 1 }, { 18, 5, 34, 100, 1 }, { 26, 9, 16, 100, 5 }, { 74, 9, 35, 100, 0 },
+ { 118, 10, 36, 100, 0 }, { 139, 9, 35, 100, 0 }, { 140, 10, 0, 100, 2 }, { 144, 5, 0, 100, 2 },
+ { 146, 3, 0, 100, 2 }, { 147, 9, 0, 100, 2 }, { 148, 2, 30, 100, 1 }, { 156, 0, 103, 50, 1 },
+ { 158, 4, 31, 100, 5 }, { 188, 4, 31, 100, 5 }, { 212, 2, 0, 100, 2 }, { 223, 1, 20, 100, 0 },
+ { 230, 1, 0, 100, 2 }, { 234, 1, 20, 100, 0 }, { 251, 1, 20, 100, 0 }, { 265, 11, 69, 80, 6 },
+ { 293, 5, 34, 80, 1 }, { 295, 12, 76, 80, 6 }, { 343, 13, 87, 110, 6 }, { 373, 14, 97, 80, 6 },
+ { 429, 5, 0, 100, 2 }, { 431, 15, 100, 80, 6 }, { 456, 2, 30, 100, 1 }, { 457, 1, 19, 100, 5 },
+ { 463, 0, 18, 100, 5 }, { 482, 2, 0, 100, 2 }, { 483, 8, 40, 100, 1 }, { 494, 8, 37, 100, 5 },
+ { 507, 7, 17, 100, 5 }, { 511, 7, 17, 100, 5 }, { 522, 13, 21, 100, 1 }, { 547, 6, 49, 100, 5 },
+ { 548, 11, 48, 100, 0 }, { 556, 12, 38, 100, 0 }, { 557, 2, 23, 100, 5 }, { 599, 7, 39, 100, 1 },
+ { 639, 7, 0, 100, 2 }, { 641, 12, 38, 100, 0 }, { 642, 7, 17, 100, 5 }, { 718, 14, 0, 100, 2 },
+ { 719, 1, 0, 100, 2 }, { 720, 2, 0, 100, 2 }, { 721, 3, 0, 100, 2 }, { 722, 4, 0, 100, 2 },
+ { 723, 5, 0, 100, 2 }, { 724, 6, 0, 100, 2 }, { 725, 7, 0, 100, 2 }, { 726, 8, 0, 100, 2 },
+ { 727, 9, 0, 100, 2 }, { 728, 10, 0, 100, 2 }, { 729, 11, 0, 100, 2 }, { 730, 12, 0, 100, 2 },
+ { 731, 0, 0, 100, 2 }, { 732, 13, 0, 100, 2 },
};
-const char *AnimationSequencePlayer::_musicFileNamesTable[] = {
+static const SoundSequenceData _soundDataSeq9_10[] = {
+ { 2, 0, 0, 100, 3 }, { 3, 2, 32, 100, 0 }, { 3, 5, 54, 20, 1 }, { 6, 25, 71, 80, 6 },
+ { 22, 1, 18, 100, 5 }, { 37, 29, 75, 80, 6 }, { 59, 30, 77, 80, 6 }, { 69, 26, 72, 80, 6 },
+ { 124, 27, 73, 80, 6 }, { 163, 28, 74, 80, 6 }, { 197, 31, 78, 80, 6 }, { 224, 32, 79, 80, 6 },
+ { 306, 33, 80, 80, 6 }, { 350, 34, 81, 80, 6 }, { 388, 8, 57, 100, 0 }, { 389, 6, 55, 100, 1 },
+ { 390, 9, 58, 100, 1 }, { 395, 10, 59, 100, 0 }, { 398, 3, 52, 100, 0 }, { 408, 3, 52, 100, 0 },
+ { 413, 4, 53, 100, 0 }, { 418, 3, 52, 100, 0 }, { 426, 6, 0, 100, 2 }, { 427, 9, 0, 100, 2 },
+ { 430, 35, 82, 80, 6 }, { 472, 36, 83, 80, 6 }, { 514, 9, 58, 100, 1 }, { 515, 7, 56, 100, 0 },
+ { 516, 6, 55, 100, 1 }, { 517, 4, 53, 100, 0 }, { 520, 11, 60, 100, 0 }, { 523, 3, 52, 100, 0 },
+ { 531, 7, 0, 100, 2 }, { 532, 9, 0, 100, 2 }, { 533, 6, 0, 100, 2 }, { 534, 3, 52, 100, 0 },
+ { 535, 37, 84, 80, 6 }, { 553, 38, 85, 80, 6 }, { 569, 39, 86, 80, 6 }, { 588, 40, 88, 80, 6 },
+ { 662, 41, 89, 80, 6 }, { 777, 42, 90, 80, 6 }, { 978, 1, 22, 100, 0 }, { 1008, 12, 61, 100, 0 },
+ { 1011, 4, 15, 100, 5 }, { 1022, 52, 99, 80, 6 }, { 1039, 3, 63, 100, 5 }, { 1045, 3, 63, 100, 5 },
+ { 1051, 3, 63, 100, 5 }, { 1057, 3, 63, 100, 5 }, { 1063, 3, 63, 100, 5 }, { 1066, 3, 63, 40, 5 },
+ { 1074, 43, 91, 80, 6 }, { 1256, 44, 92, 80, 6 }, { 1322, 45, 93, 80, 6 }, { 1373, 46, 94, 80, 6 },
+ { 1419, 47, 95, 80, 6 }, { 1792, 13, 62, 100, 0 }, { 1793, 0, 50, 100, 5 }, { 1895, 51, 98, 80, 6 },
+};
+
+static const SoundSequenceData _soundDataSeq21_20[] = {
+ { 2, 0, 0, 100, 3 }, { 4, 3, 34, 40, 1 }, { 5, 7, 54, 20, 1 }, { 7, 3, 51, 100, 5 },
+ { 62, 3, 0, 100, 2 }, { 63, 48, 96, 80, 6 }, { 198, 7, 0, 100, 2 }, { 202, 5, 46, 100, 1 },
+ { 203, 16, 101, 80, 6 }, { 211, 1, 41, 100, 5 }, { 216, 0, 103, 40, 1 }, { 217, 5, 0, 100, 2 },
+ { 218, 6, 47, 100, 1 }, { 224, 2, 43, 100, 5 }, { 229, 17, 102, 80, 6 }, { 273, 6, 0, 100, 2 },
+ { 274, 4, 40, 100, 1 }, { 275, 4, 44, 100, 5 }, { 335, 1, 21, 100, 1 }, { 336, 13, 42, 100, 0 },
+ { 339, 11, 28, 100, 0 }, { 358, 0, 25, 100, 5 }, { 364, 24, 70, 100, 4 }, { 397, 7, 49, 100, 5 },
+ { 399, 6, 48, 100, 5 }, { 433, 5, 45, 100, 5 }, { 451, 13, 42, 100, 0 }, { 459, 1, 0, 100, 2 },
+ { 508, 4, 0, 100, 2 }, { 509, 1, 21, 100, 1 }, { 521, 11, 28, 100, 0 }, { 530, 8, 118, 100, 0 },
+ { 537, 9, 26, 100, 0 }, { 557, 8, 106, 100, 5 }, { 578, 5, 45, 100, 5 }, { 602, 13, 42, 100, 0 },
+ { 609, 1, 0, 100, 2 }, { 626, 12, 29, 100, 0 }, { 628, 10, 27, 100, 0 }, { 670, 6, 48, 100, 5 },
+ { 690, 10, 27, 100, 0 }, { 692, 3, 51, 100, 5 }, { 705, 11, 28, 100, 0 }, { 710, 2, 43, 100, 5 },
+ { 714, 9, 26, 100, 0 }, { 720, 9, 0, 100, 2 }, { 721, 7, 49, 100, 5 }, { 725, 0, 25, 100, 5 },
+};
+
+static const SoundSequenceData _soundDataSeq13_14[] = {
+ { 3, 0, 128, 100, 1 }, { 34, 0, 0, 100, 2 }, { 57, 0, 123, 100, 5 }, { 77, 0, 123, 100, 5 },
+ { 84, 9, 24, 100, 0 }, { 100, 9, 24, 100, 0 }, { 140, 3, 19, 100, 5 }, { 157, 2, 109, 100, 5 },
+ { 158, 1, 129, 100, 0 }, { 204, 1, 114, 100, 5 }, { 220, 2, 107, 100, 1 }, { 235, 7, 113, 100, 0 },
+ { 236, 2, 0, 100, 2 }, { 248, 12, 118, 100, 0 }, { 251, 13, 119, 100, 0 }, { 265, 11, 117, 100, 0 },
+ { 276, 11, 117, 100, 0 }, { 310, 5, 110, 100, 0 }, { 335, 6, 112, 100, 0 }, { 370, 4, 124, 100, 0 },
+ { 373, 8, 127, 100, 0 }, { 378, 8, 127, 100, 0 }, { 434, 10, 120, 100, 0 }, { 453, 3, 108, 100, 0 },
+ { 484, 3, 0, 100, 2 },
+};
+
+static const SoundSequenceData _soundDataSeq15_16[] = {
+ { 3, 4, 3, 100, 5 }, { 10, 5, 4, 100, 5 }, { 22, 6, 64, 100, 5 }, { 32, 7, 65, 100, 5 },
+ { 39, 6, 64, 100, 5 }, { 48, 7, 65, 100, 5 }, { 57, 6, 64, 100, 5 }, { 65, 3, 67, 50, 0 },
+ { 102, 4, 68, 50, 0 }, { 151, 2, 12, 50, 5 }, { 205, 3, 5, 100, 5 }, { 218, 0, 63, 100, 5 },
+ { 227, 0, 63, 100, 5 }, { 236, 0, 63, 100, 5 }, { 245, 0, 63, 100, 5 }, { 254, 0, 63, 100, 5 },
+ { 263, 0, 63, 100, 5 }, { 272, 0, 63, 100, 5 }, { 291, 1, 54, 40, 1 }, { 309, 8, 6, 100, 5 },
+ { 360, 8, 6, 100, 5 }, { 384, 2, 55, 60, 1 }, { 398, 10, 66, 100, 0 }, { 440, 2, 0, 100, 2 },
+ { 441, 1, 0, 100, 2 }, { 452, 11, 62, 100, 0 }, { 466, 1, 2, 100, 5 }, { 470, 8, 9, 100, 0 },
+ { 503, 6, 7, 100, 0 }, { 519, 7, 8, 100, 0 }, { 536, 8, 9, 100, 0 }, { 538, 4, 3, 100, 5 },
+ { 549, 5, 4, 100, 5 }, { 558, 4, 3, 100, 5 }, { 568, 5, 4, 100, 5 }, { 578, 4, 3, 100, 5 },
+ { 586, 5, 4, 100, 5 }, { 593, 4, 3, 100, 5 }, { 600, 5, 4, 100, 5 }, { 606, 4, 3, 100, 5 },
+ { 613, 5, 4, 100, 5 }, { 620, 9, 10, 100, 0 }, { 630, 12, 11, 100, 0 },
+};
+
+static const SoundSequenceData _soundDataSeq27_28[] = {
+ { 17, 2, 111, 100, 0 }, { 57, 8, 105, 100, 0 }, { 62, 10, 126, 100, 0 }, { 67, 9, 110, 100, 0 },
+ { 74, 3, 115, 100, 1 }, { 87, 3, 0, 100, 2 }, { 85, 0, 121, 100, 0 }, { 138, 5, 116, 100, 0 },
+ { 196, 7, 125, 100, 0 }, { 222, 6, 122, 100, 0 }, { 228, 1, 129, 100, 0 },
+};
+
+static const SoundSequenceData _soundDataSeq19_20[] = {
+ { 2, 0, 0, 100, 3 }, { 3, 0, 115, 100, 1 }, { 33, 0, 0, 100, 2 }, { 33, 1, 13, 100, 0 },
+ { 53, 2, 14, 100, 1 }, { 78, 2, 0, 100, 2 }, { 80, 0, 0, 100, 4 },
+};
+
+const SoundSequenceDataList AnimationSequencePlayer::_soundSeqDataList[] = {
+ { 0, 0, 14, 10, 58, _soundDataSeq3_4 },
+ { 0, 0, 14, 5, 60, _soundDataSeq9_10 },
+ { 0, 0, 14, 9, 48, _soundDataSeq21_20 },
+ { 1, 80, 14, 4, 25, _soundDataSeq13_14 },
+ { 1, 80, 13, 9, 43, _soundDataSeq15_16 },
+ { 1, 80, 11, 0, 11, _soundDataSeq27_28 },
+ { 104, 100, 0, 0, 0, 0 },
+ { 0, 100, 4, 0, 7, _soundDataSeq19_20 }
+};
+
+const char *AnimationSequencePlayer::_audioFileNamesTable[] = {
"demomenu.raw",
- "introdub.raw",
- "introdua.raw",
- "demorola.raw",
- "democha1.raw",
- "icrmusic.raw",
- "demorolc.raw",
- "demorolc.raw",
- "merilogo.raw",
- "democha2.raw",
"demorolc.raw",
+ "fx101.wav",
+ "fx102.wav",
+ "fx103.wav",
+ "fx104.wav",
+ "fx105.wav",
+ "fx107.wav",
+ "fx108.wav",
+ "fx109.wav",
+ "fx110.wav",
+ "fx111.wav",
+ "fx112.wav",
+ "fx113.wav",
+ "fx114.wav",
+ "fx116.wav",
+ "fx117.wav",
+ "fx32.wav",
+ "fx33.wav",
+ "fx34.wav",
+ "fx35.wav",
+ "fx36.wav",
+ "fx37.wav",
+ "fx38.wav",
+ "fx39.wav",
+ "fx40.wav",
+ "fx42.wav",
+ "fx43.wav",
+ "fx44.wav",
+ "fx45.wav",
+ "fx47.wav",
+ "fx48.wav",
+ "fx49.wav",
+ "fx50.wav",
+ "fx52.wav",
+ "fx53.wav",
+ "fx55.wav",
+ "fx56.wav",
+ "fx57.wav",
+ "fx58.wav",
+ "fx59.wav",
+ "fx60.wav",
+ "fx61.wav",
+ "fx62.wav",
+ "fx63.wav",
+ "fx64.wav",
+ "fx66.wav",
+ "fx67.wav",
+ "fx68.wav",
+ "fx69.wav",
+ "fx70.wav",
+ "fx71.wav",
+ "fx72.wav",
+ "fx73.wav",
+ "fx74.wav",
+ "fx75.wav",
+ "fx76.wav",
+ "fx77.wav",
+ "fx78.wav",
+ "fx79.wav",
+ "fx80.wav",
+ "fx81.wav",
+ "fx83.wav",
+ "fx86.wav",
+ "fx91.wav",
+ "fx92.wav",
+ "fx93.wav",
+ "fx97.wav",
+ "fx98.wav",
"int1.raw",
- "int2.raw",
- "int3.raw",
- "int4.raw",
- "int5.raw",
- "int6.raw",
- "int7.raw",
- "int8.raw",
- "int9.raw",
- "int10.raw",
- "int11.raw",
- "int12.raw",
- "int13.raw",
"int14.raw",
"int15.raw",
"int16.raw",
"int17.raw",
"int18.raw",
"int19.raw",
+ "int2.raw",
"int20.raw",
"int21.raw",
"int22.raw",
@@ -388,6 +431,7 @@ const char *AnimationSequencePlayer::_musicFileNamesTable[] = {
"int27.raw",
"int28.raw",
"int29.raw",
+ "int3.raw",
"int30.raw",
"int31.raw",
"int32.raw",
@@ -397,177 +441,39 @@ const char *AnimationSequencePlayer::_musicFileNamesTable[] = {
"int36.raw",
"int37.raw",
"int38.raw",
- "int39.raw",
- "int40.raw",
+ "int4.raw",
"int41.raw",
- "int42.raw"
-};
-
-const char *AnimationSequencePlayer::_audioFileNamesTable[] = {
- "introdua.wav",
- "fx35.wav",
- "fx47.wav",
- "fx50.wav",
- "fx51.wav",
- "fx52.wav",
- "fx54.wav",
- "fx58.wav",
- "fx59.wav",
- "fx53.wav",
- "fx55.wav",
- "fx68.wav",
- "fx57.wav",
- "fx36.wav",
- // offset 2,14
- "fx33.wav",
- "fx34.wav",
- "fx38.wav",
- "fx39.wav",
- "fx48.wav",
- "fx49.wav",
- "fx69.wav",
- "fx32.wav",
- "fx56.wav",
- "fx117.wav",
- // offset 3,24
- "introdua.wav",
- "fx37.wav",
- "fx49.wav",
- "fx72.wav",
- "fx73.wav",
- "fx74.wav",
- "fx75.wav",
- "fx76.wav",
- "fx77.wav",
- "fx78.wav",
- "fx79.wav",
- "fx80.wav",
- "fx81.wav",
- "fx83.wav",
- // offset 4,38
- "fx70.wav",
- "fx33.wav",
- "rdfx12.wav",
- "fx86.wav",
- "fx116.wav",
- // offset 5,43
+ "int42.raw",
+ "int5.raw",
+ "int6.raw",
+ "int7.raw",
"introdua.wav",
- "fx36.wav",
- "fx46.wav",
- "fx52.wav",
- "fx59.wav",
- "fx66.wav",
- "fx67.wav",
- "fx74.wav",
- "rdfx26.wav",
- "fx42.wav",
- "fx43.wav",
- "fx44.wav",
- "fx45.wav",
- "fx61.wav",
- // offset 6,57
- "fx40.wav",
- "fx60.wav",
- "fx62.wav",
- "fx71.wav",
- "fx63.wav",
- "fx64.wav",
- "fx68.wav",
- "fx69.wav",
- "rdfx12.wav",
- // offset 7,66
+ "merilogo.raw",
"rdfx1.wav",
- "rdfx2.wav",
- "rdfx4.wav",
- "rdfx5.wav",
- "rdfx6.wav",
- "rdfx7.wav",
- "rdfx10.wav",
- "rdfx11.wav",
"rdfx12.wav",
- "rdfx19.wav",
- "rdfx29.wav",
- "rdfx32.wav",
- "rdfx35.wav",
- // offset 8,79
- "rdfx8.wav",
- "rdfx9.wav",
"rdfx13.wav",
"rdfx14.wav",
- "rdfx33.wav",
+ "rdfx15.wav",
"rdfx16.wav",
+ "rdfx17.wav",
"rdfx18.wav",
"rdfx20.wav",
- "rdfx38.wav",
- "fx39.wav",
- "rdfx28.wav",
+ "rdfx21.wav",
+ "rdfx22.wav",
+ "rdfx24.wav",
"rdfx25.wav",
"rdfx26.wav",
"rdfx27.wav",
- // offset 9,93
- "rdfx31.wav",
- "rdfx21.wav",
- "rdfx15.wav",
- "fx34.wav",
- // offset 10,97
- "fx96.wav",
- "fx74.wav",
- "fx75.wav",
- "fx97.wav",
- "fx98.wav",
- "fx106.wav",
- "fx107.wav",
- "fx108.wav",
- "fx109.wav",
- "fx110.wav",
- "fx93.wav",
- "fx83.wav",
- "fx111.wav",
- // offset 11,110
- "fx86.wav",
- "fx101.wav",
- "fx112.wav",
- "fx104.wav",
- "fx102.wav",
- "fx103.wav",
- "fx91.wav",
- "fx92.wav",
- "fx105.wav",
- // offset 12,119
+ "rdfx28.wav",
"rdfx3.wav",
- "rdfx9.wav",
- "rdfx17.wav",
- "rdfx22.wav",
- "rdfx23.wav",
- "rdfx24.wav",
"rdfx30.wav",
+ "rdfx31.wav",
+ "rdfx33.wav",
"rdfx36.wav",
- "rdfx1.wav",
- "rdfx16.wav",
"rdfx37.wav",
- // offset 13,130
- "fx82.wav",
- "fx80.wav",
- "fx89.wav",
- "fx90.wav",
- "fx83.wav",
- "fx84.wav",
- // offset 14,136
- "rdfx2.wav",
- "fx85.wav",
- "fx86.wav",
- "fx87.wav",
- "fx88.wav",
- "fx99.wav",
- "fx98.wav",
- "fx97.wav",
- "fx96.wav",
- "fx100.wav",
- // offset 15,146
- "rdfx22.wav",
- "fx113.wav",
- "fx114.wav",
- "fx115.wav"
+ "rdfx38.wav",
+ "rdfx8.wav",
+ "rdfx9.wav",
};
} // namespace Tucker
diff --git a/engines/tucker/tucker.cpp b/engines/tucker/tucker.cpp
index cedd9ec723..692335d5ef 100644
--- a/engines/tucker/tucker.cpp
+++ b/engines/tucker/tucker.cpp
@@ -304,7 +304,7 @@ void TuckerEngine::restart() {
_currentGfxBackgroundCounter = 0;
_currentGfxBackground = 0;
_fadePaletteCounter = 0;
- memset(&_currentPalette, 0, sizeof(_currentPalette));
+ memset(_currentPalette, 0, sizeof(_currentPalette));
_fullRedrawCounter = 0;
_dirtyRectsPrevCount = _dirtyRectsCount = 0;
@@ -3395,7 +3395,6 @@ void TuckerEngine::setSelectedObjectKey() {
_selectedObject.locationObject_toY2 = _locationObjectsTable[_selectedCharacterNum].toY2;
_selectedObject.locationObject_toWalkX2 = _locationObjectsTable[_selectedCharacterNum].toWalkX2;
_selectedObject.locationObject_toWalkY2 = _locationObjectsTable[_selectedCharacterNum].toWalkY2;
-
}
}
} else {
diff --git a/engines/tucker/tucker.h b/engines/tucker/tucker.h
index 966900c923..6afccdc4da 100644
--- a/engines/tucker/tucker.h
+++ b/engines/tucker/tucker.h
@@ -848,11 +848,32 @@ enum AnimationSoundType {
kAnimationSoundTypeLoopingWAV
};
+enum {
+ kSoundsList_Seq3_4,
+ kSoundsList_Seq9_10,
+ kSoundsList_Seq21_20,
+ kSoundsList_Seq13_14,
+ kSoundsList_Seq15_16,
+ kSoundsList_Seq27_28,
+ kSoundsList_Seq17_18,
+ kSoundsList_Seq19_20
+};
+
struct SoundSequenceData {
int timestamp;
int index;
- int opcode;
+ int num;
int volume;
+ int opcode;
+};
+
+struct SoundSequenceDataList {
+ int musicIndex;
+ int musicVolume;
+ int soundList1Count;
+ int soundList2Count;
+ int soundSeqDataCount;
+ const SoundSequenceData *soundSeqData;
};
class AnimationSequencePlayer {
@@ -919,13 +940,9 @@ private:
int _updateFuncIndex;
::Graphics::FlicDecoder _flicPlayer[2];
uint8 _animationPalette[256 * 4];
- int _soundsList1Offset;
- int _soundsList1Count;
- int _soundsList2Offset;
- int _soundsList2Count;
- int _soundSeqDataOffset;
int _soundSeqDataCount;
int _soundSeqDataIndex;
+ const SoundSequenceData *_soundSeqData;
uint8 *_offscreenBuffer;
int _updateScreenWidth;
int _updateScreenPicture;
@@ -938,8 +955,7 @@ private:
Audio::SoundHandle _sfxHandle;
Audio::SoundHandle _musicHandle;
- static const SoundSequenceData _soundSeqData[];
- static const char *_musicFileNamesTable[];
+ static const SoundSequenceDataList _soundSeqDataList[];
static const char *_audioFileNamesTable[];
};