[Scummvm-git-logs] scummvm master -> e51035f2e79f21ab2b8d1c3536b4c9c2986c7f62
dreammaster
noreply at scummvm.org
Thu May 28 11:13:44 UTC 2026
This automated email contains information about 6 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
17751dd9b7 MADS: DRAGONSPHERE: Fix array indexing error in map screen
acd8198462 MADS: DRAGONSPHERE: Implement custom player_keep_walking for the game
7175f1472e MADS: FOREST: Skeleton subengine codebase
74ed86e494 MADS: FOREST: Implementing section 9 rooms
a57e2b6ae1 MADS: DRAGONSPHERE: Warning fixes
e51035f2e7 MADS: DRAGONSPHERE: Fix re-entering Caliph's tent
Commit: 17751dd9b71b9b2f830fb92f3eba8171e1fd1214
https://github.com/scummvm/scummvm/commit/17751dd9b71b9b2f830fb92f3eba8171e1fd1214
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2026-05-28T21:12:18+10:00
Commit Message:
MADS: DRAGONSPHERE: Fix array indexing error in map screen
Changed paths:
engines/mads/madsv2/core/player.cpp
diff --git a/engines/mads/madsv2/core/player.cpp b/engines/mads/madsv2/core/player.cpp
index 41aeccd3403..04dc8e1714c 100644
--- a/engines/mads/madsv2/core/player.cpp
+++ b/engines/mads/madsv2/core/player.cpp
@@ -797,6 +797,7 @@ static void player_walk_directly(int walk_form) {
void player_new_command() {
int count;
int walk_spot;
+ int id;
player_cancel_command();
@@ -866,10 +867,11 @@ void player_new_command() {
// Be sure player moves immediately even if in the middle of a long
// stop-walker frame.
- // WORKAROUND: For ROTP chandelier fight cutscene
- if (!series_list[player.series_base + player.series])
+ // WORKAROUND: For ROTP chandelier fight cutscene and Dragonsphere cutscenes
+ id = player.series_base + player.series;
+ if (id < 0 || !series_list[id])
return;
- WalkerInfoPtr walker = series_list[player.series_base + player.series]->walker;
+ WalkerInfoPtr walker = series_list[id]->walker;
if (!walker)
return;
Commit: acd8198462b347b429c248b147ef41521d857667
https://github.com/scummvm/scummvm/commit/acd8198462b347b429c248b147ef41521d857667
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2026-05-28T21:12:19+10:00
Commit Message:
MADS: DRAGONSPHERE: Implement custom player_keep_walking for the game
Changed paths:
engines/mads/madsv2/core/player.cpp
engines/mads/madsv2/core/player.h
engines/mads/madsv2/dragonsphere/dragonsphere.cpp
engines/mads/madsv2/dragonsphere/dragonsphere.h
engines/mads/madsv2/engine.cpp
engines/mads/madsv2/engine.h
diff --git a/engines/mads/madsv2/core/player.cpp b/engines/mads/madsv2/core/player.cpp
index 04dc8e1714c..a8219d7b8aa 100644
--- a/engines/mads/madsv2/core/player.cpp
+++ b/engines/mads/madsv2/core/player.cpp
@@ -33,6 +33,7 @@
#include "mads/madsv2/core/pal.h"
#include "mads/madsv2/core/himem.h"
#include "mads/madsv2/core/object.h"
+#include "mads/madsv2/engine.h"
namespace MADS {
namespace MADSV2 {
@@ -265,7 +266,7 @@ void player_select_series() {
player.sprite_changed = true;
}
-static void player_activate_trigger() {
+void player_activate_trigger() {
int count;
player.commands_allowed |= player.enable_at_target;
@@ -283,12 +284,7 @@ static void player_activate_trigger() {
}
}
-/**
- * When the player needs to turn to face a different direction
- * than his current facing, this routine rotates him one place
- * in the right direction.
- */
-static void player_keep_turning() {
+void player_keep_turning() {
int clockwise_count = 0;
int clockwise_sum = 0;
int counter_clockwise_count = 0;
@@ -478,105 +474,7 @@ void player_set_sprite() {
}
void player_keep_walking() {
- int at_x, at_y;
- int walk_code;
- int id;
- int new_facing = false;
- int temp_velocity;
- int angle_scale;
- int angle_range;
-
- while (player.walking && !player.walk_off_edge && (player.x == player.target_x) && (player.y == player.target_y)) {
- if (rail_solution_stack_pointer == 0) {
- if (player.walk_off_edge_to_room) {
- player.walk_off_edge = player.walk_off_edge_to_room;
- player.walk_anywhere = true;
- player.walk_off_edge_to_room = 0;
- player.commands_allowed = false;
- new_facing = false;
- } else {
- player.walking = false;
- player_set_final_facing();
- new_facing = true;
- }
- } else {
- id = rail_solution_stack[--rail_solution_stack_pointer];
- player.target_x = room->rail[id].x;
- player.target_y = room->rail[id].y;
- new_facing = true;
- }
- }
-
- if (new_facing) {
- if (player.walking) player_set_facing();
- }
-
- if (player.facing != player.turn_to_facing) {
- player_keep_turning();
- } else {
- if (!player.walking) {
- player_new_stop_walker();
- player_activate_trigger();
- }
- }
-
- temp_velocity = player.velocity;
-
- if (player.scaling_velocity && (player.total_distance > 0)) {
- angle_range = 100 - player.scale;
- angle_scale = player.scale + ((angle_range * (player.x_count - 1)) / player.total_distance);
- temp_velocity = (int)(((long)temp_velocity * ((long)player.scale * (long)angle_scale)) / 10000L);
- temp_velocity = MAX(temp_velocity, 1);
- }
-
- if (player.walking && (player.facing == player.turn_to_facing)) {
- at_x = player.x;
- at_y = player.y;
- walk_code = false;
- player.special_code = 0;
-
- if (player.dist_accum < temp_velocity) {
-
- do {
- if (player.pixel_accum < player.x_count) {
- player.pixel_accum += player.y_count;
- }
- if (player.pixel_accum >= player.x_count) {
- if ((player.y_counter > 0) || player.walk_off_edge) at_y += player.sign_y;
- player.y_counter--;
- player.pixel_accum -= player.x_count;
- }
- if (player.pixel_accum < player.x_count) {
- if ((player.x_counter > 0) || player.walk_off_edge) at_x += player.sign_x;
- player.x_counter--;
- }
-
- if (!player.walk_anywhere && !(player.walk_off_edge || player.walk_off_edge_to_room)) {
- walk_code |= attr_walk(&scr_walk, at_x, at_y);
- if (!player.special_code) {
- player.special_code = attr_special(&scr_special, at_x, at_y);
- }
- }
-
- player.dist_accum += player.delta_distance;
- } while ((player.dist_accum < temp_velocity) && (!walk_code) &&
- ((player.x_counter > 0) || (player.y_counter > 0) || (player.walk_off_edge)));
-
- }
-
- player.dist_accum -= temp_velocity;
-
- if (walk_code) {
- player_cancel_command();
- } else {
- if (!player.walk_off_edge) {
- if (player.x_counter <= 0) at_x = player.target_x;
- if (player.y_counter <= 0) at_y = player.target_y;
- }
- player.x = at_x;
- player.y = at_y;
- }
- }
+ g_engine->player_keep_walking();
}
int player_search_image() {
diff --git a/engines/mads/madsv2/core/player.h b/engines/mads/madsv2/core/player.h
index 740a2126bb7..392ff7bb418 100644
--- a/engines/mads/madsv2/core/player.h
+++ b/engines/mads/madsv2/core/player.h
@@ -333,6 +333,15 @@ extern void player_demand_location(int x, int y);
extern void player_first_walk(int from_x, int from_y, int from_facing,
int to_x, int to_y, int to_facing, int enable_at_target);
+/**
+ * When the player needs to turn to face a different direction
+ * than his current facing, this routine rotates him one place
+ * in the right direction.
+ */
+extern void player_keep_turning();
+
+extern void player_activate_trigger();
+
} // namespace MADSV2
} // namespace MADS
diff --git a/engines/mads/madsv2/dragonsphere/dragonsphere.cpp b/engines/mads/madsv2/dragonsphere/dragonsphere.cpp
index 2c0f343ff85..00f952aa103 100644
--- a/engines/mads/madsv2/dragonsphere/dragonsphere.cpp
+++ b/engines/mads/madsv2/dragonsphere/dragonsphere.cpp
@@ -21,14 +21,17 @@
#include "engines/util.h"
#include "mads/madsv2/console.h"
+#include "mads/madsv2/core/attr.h"
#include "mads/madsv2/core/conv.h"
#include "mads/madsv2/core/env.h"
#include "mads/madsv2/core/game.h"
#include "mads/madsv2/core/imath.h"
#include "mads/madsv2/core/inter.h"
#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/matte.h"
#include "mads/madsv2/core/object.h"
#include "mads/madsv2/core/pal.h"
+#include "mads/madsv2/core/rail.h"
#include "mads/madsv2/core/screen.h"
#include "mads/madsv2/core/sound.h"
#include "mads/madsv2/core/text.h"
@@ -1301,6 +1304,184 @@ void DragonsphereEngine::global_sound_driver() {
env_catint(kernel.sound_driver, new_section, 1);
}
+void DragonsphereEngine::player_keep_walking() {
+ int at_x, at_y;
+ int walk_code;
+ int id;
+ int new_facing = false;
+ int temp_velocity;
+ int angle_scale;
+ int angle_range;
+
+ int countt;
+ int rum = 400;
+ int countt2 = global[oasis] - 1;
+
+ while (player.walking && !player.walk_off_edge && (player.x == player.target_x) && (player.y == player.target_y)) {
+ if (rail_solution_stack_pointer == 0) {
+ if (player.walk_off_edge_to_room) {
+
+ if (room_id == 302) {
+ if (player_said_2(walk_down, path_to_east) && game.difficulty == 0) {
+ if (!player_has_been_in_room(303)) {
+ global[bubble_wont_attack] = false;
+ }
+ }
+ }
+
+ if (room_id == 401 || room_id == 402 || room_id == 403) {
+ if (player_said_1(desert_to_east) || player_said_1(desert_to_west)) {
+ if (player_has_been_in_room(405) && player_said_1(desert_to_west)) {
+ global[from_direction] = FROM_EAST;
+ player.walk_off_edge_to_room = 405;
+
+ } else if (player_has_been_in_room(405) && player_said_1(desert_to_east)) {
+ global[pre_room] = 401;
+ if (player.walk_off_edge_to_room != 111) {
+ player.walk_off_edge_to_room = 120;
+ }
+
+ } else if (player_said_1(desert_to_east) && global[desert_room] % 7 == 0) {
+ global[pre_room] = 401;
+ if (player.walk_off_edge_to_room != 111) {
+ player.walk_off_edge_to_room = 120;
+ }
+
+ } else if (player_said_1(desert_to_east)) {
+ ++global[desert_room];
+ global[from_direction] = FROM_WEST;
+
+ } else if (player_said_1(desert_to_west)) {
+ --global[desert_room];
+ global[from_direction] = FROM_EAST;
+ }
+
+ if (player.walk_off_edge_to_room != 120 &&
+ player.walk_off_edge_to_room != 111 &&
+ player.walk_off_edge_to_room != 405) for (countt = 0; countt < 77; countt++) {
+ ++rum; if (rum == 404) rum = 401;
+ ++countt2; if (countt2 == 78) countt2 = 1;
+
+ if (countt2 == global[desert_room]) {
+ if (global[desert_room] == 42) rum = 401;
+ if (global[desert_room] == global[oasis]) rum = 454;
+ if (global[desert_room] == global[fire_holes]) rum = 412;
+
+ if (player_said_1(desert_to_east) || player_said_1(desert_to_west)) {
+ if (room_id == rum) {
+ player.walk_off_edge_to_room = room_id;
+ } else {
+ player.walk_off_edge_to_room = rum;
+ }
+ }
+ goto over;
+ }
+ }
+ }
+ }
+
+over:
+ if ((room_id == 401 || room_id == 402 || room_id == 403) &&
+ !player_has_been_in_room(405)) {
+ ++global[desert_counter];
+ if (global[desert_counter] == 6) {
+ player.walk_off_edge_to_room = 404;
+ }
+ }
+
+ player.walk_off_edge = player.walk_off_edge_to_room;
+ player.walk_anywhere = true;
+ player.walk_off_edge_to_room = 0;
+ player.commands_allowed = false;
+ new_facing = false;
+
+ } else {
+ player.walking = false;
+ player_set_final_facing();
+ new_facing = true;
+ }
+
+ } else {
+ id = rail_solution_stack[--rail_solution_stack_pointer];
+ player.target_x = room->rail[id].x;
+ player.target_y = room->rail[id].y;
+ new_facing = true;
+ }
+ }
+
+ if (new_facing) {
+ if (player.walking) player_set_facing();
+ }
+
+ if (player.facing != player.turn_to_facing) {
+ player_keep_turning();
+ } else {
+ if (!player.walking) {
+ player_new_stop_walker();
+ player_activate_trigger();
+ }
+ }
+
+ temp_velocity = player.velocity;
+
+ if (player.scaling_velocity && (player.total_distance > 0)) {
+ angle_range = 100 - player.scale;
+ angle_scale = player.scale + ((angle_range * (player.x_count - 1)) / player.total_distance);
+ temp_velocity = (int)(((long)temp_velocity * ((long)player.scale * (long)angle_scale)) / 10000L);
+ temp_velocity = MAX(temp_velocity, 1);
+ }
+
+ if (player.walking && (player.facing == player.turn_to_facing)) {
+ at_x = player.x;
+ at_y = player.y;
+ walk_code = false;
+ player.special_code = 0;
+
+ if (player.dist_accum < temp_velocity) {
+ do {
+ if (player.pixel_accum < player.x_count) {
+ player.pixel_accum += player.y_count;
+ }
+ if (player.pixel_accum >= player.x_count) {
+ if ((player.y_counter > 0) || player.walk_off_edge) at_y += player.sign_y;
+ player.y_counter--;
+ player.pixel_accum -= player.x_count;
+ }
+ if (player.pixel_accum < player.x_count) {
+ if ((player.x_counter > 0) || player.walk_off_edge) at_x += player.sign_x;
+ player.x_counter--;
+ }
+
+ if (!player.walk_anywhere && !(player.walk_off_edge || player.walk_off_edge_to_room)) {
+ walk_code |= attr_walk(&scr_walk, at_x, at_y);
+ if (!player.special_code) {
+ player.special_code = attr_special(&scr_special, at_x, at_y);
+ }
+ }
+
+ player.dist_accum += player.delta_distance;
+ } while ((player.dist_accum < temp_velocity) && (!walk_code) &&
+ ((player.x_counter > 0) || (player.y_counter > 0) || (player.walk_off_edge)));
+ }
+
+ player.dist_accum -= temp_velocity;
+
+ if (walk_code) {
+ player_cancel_command();
+ } else {
+ if (!player.walk_off_edge) {
+ if (player.x_counter <= 0)
+ at_x = player.target_x;
+ if (player.y_counter <= 0)
+ at_y = player.target_y;
+ }
+
+ player.x = at_x;
+ player.y = at_y;
+ }
+ }
+}
+
} // namespace Dragonsphere
} // namespace MADSV2
} // namespace MADS
diff --git a/engines/mads/madsv2/dragonsphere/dragonsphere.h b/engines/mads/madsv2/dragonsphere/dragonsphere.h
index d5e3f721170..9d88ee47945 100644
--- a/engines/mads/madsv2/dragonsphere/dragonsphere.h
+++ b/engines/mads/madsv2/dragonsphere/dragonsphere.h
@@ -49,6 +49,7 @@ public:
void global_error_code() override;
void global_room_init() override;
void global_sound_driver() override;
+ void player_keep_walking() override;
};
} // namespace Dragonsphere
diff --git a/engines/mads/madsv2/engine.cpp b/engines/mads/madsv2/engine.cpp
index b81ee403683..e7fe891fcb9 100644
--- a/engines/mads/madsv2/engine.cpp
+++ b/engines/mads/madsv2/engine.cpp
@@ -376,5 +376,107 @@ SaveStateList MADSV2Engine::listSaves() const {
return getMetaEngine()->listSaves(_targetName.c_str());
}
+void MADSV2Engine::player_keep_walking() {
+ int at_x, at_y;
+ int walk_code;
+ int id;
+ int new_facing = false;
+ int temp_velocity;
+ int angle_scale;
+ int angle_range;
+
+ while (player.walking && !player.walk_off_edge && (player.x == player.target_x) && (player.y == player.target_y)) {
+ if (rail_solution_stack_pointer == 0) {
+ if (player.walk_off_edge_to_room) {
+ player.walk_off_edge = player.walk_off_edge_to_room;
+ player.walk_anywhere = true;
+ player.walk_off_edge_to_room = 0;
+ player.commands_allowed = false;
+ new_facing = false;
+ } else {
+ player.walking = false;
+ player_set_final_facing();
+ new_facing = true;
+ }
+ } else {
+ id = rail_solution_stack[--rail_solution_stack_pointer];
+ player.target_x = room->rail[id].x;
+ player.target_y = room->rail[id].y;
+ new_facing = true;
+ }
+ }
+
+ if (new_facing) {
+ if (player.walking) player_set_facing();
+ }
+
+ if (player.facing != player.turn_to_facing) {
+ player_keep_turning();
+ } else {
+ if (!player.walking) {
+ player_new_stop_walker();
+ player_activate_trigger();
+ }
+ }
+
+ temp_velocity = player.velocity;
+
+ if (player.scaling_velocity && (player.total_distance > 0)) {
+ angle_range = 100 - player.scale;
+ angle_scale = player.scale + ((angle_range * (player.x_count - 1)) / player.total_distance);
+ temp_velocity = (int)(((long)temp_velocity * ((long)player.scale * (long)angle_scale)) / 10000L);
+ temp_velocity = MAX(temp_velocity, 1);
+ }
+
+ if (player.walking && (player.facing == player.turn_to_facing)) {
+ at_x = player.x;
+ at_y = player.y;
+ walk_code = false;
+ player.special_code = 0;
+
+ if (player.dist_accum < temp_velocity) {
+
+ do {
+ if (player.pixel_accum < player.x_count) {
+ player.pixel_accum += player.y_count;
+ }
+ if (player.pixel_accum >= player.x_count) {
+ if ((player.y_counter > 0) || player.walk_off_edge) at_y += player.sign_y;
+ player.y_counter--;
+ player.pixel_accum -= player.x_count;
+ }
+ if (player.pixel_accum < player.x_count) {
+ if ((player.x_counter > 0) || player.walk_off_edge) at_x += player.sign_x;
+ player.x_counter--;
+ }
+
+ if (!player.walk_anywhere && !(player.walk_off_edge || player.walk_off_edge_to_room)) {
+ walk_code |= attr_walk(&scr_walk, at_x, at_y);
+ if (!player.special_code) {
+ player.special_code = attr_special(&scr_special, at_x, at_y);
+ }
+ }
+
+ player.dist_accum += player.delta_distance;
+ } while ((player.dist_accum < temp_velocity) && (!walk_code) &&
+ ((player.x_counter > 0) || (player.y_counter > 0) || (player.walk_off_edge)));
+
+ }
+
+ player.dist_accum -= temp_velocity;
+
+ if (walk_code) {
+ player_cancel_command();
+ } else {
+ if (!player.walk_off_edge) {
+ if (player.x_counter <= 0) at_x = player.target_x;
+ if (player.y_counter <= 0) at_y = player.target_y;
+ }
+ player.x = at_x;
+ player.y = at_y;
+ }
+ }
+}
+
} // namespace MADSV2
} // namespace MADS
diff --git a/engines/mads/madsv2/engine.h b/engines/mads/madsv2/engine.h
index a7ff7a00890..6db62148dc5 100644
--- a/engines/mads/madsv2/engine.h
+++ b/engines/mads/madsv2/engine.h
@@ -112,6 +112,7 @@ public:
virtual void global_room_init() = 0;
virtual void global_sound_driver() = 0;
virtual void global_verb_filter() {}
+ virtual void player_keep_walking();
void playSpeech(Audio::AudioStream *stream);
void stopSpeech();
Commit: 7175f1472eda4246aab45ce435ac777a110f883d
https://github.com/scummvm/scummvm/commit/7175f1472eda4246aab45ce435ac777a110f883d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2026-05-28T21:12:19+10:00
Commit Message:
MADS: FOREST: Skeleton subengine codebase
Changed paths:
A engines/mads/madsv2/forest/asound.cpp
A engines/mads/madsv2/forest/asound.h
A engines/mads/madsv2/forest/global.cpp
A engines/mads/madsv2/forest/global.h
A engines/mads/madsv2/forest/mads/inventory.h
A engines/mads/madsv2/forest/mads/mads.cpp
A engines/mads/madsv2/forest/mads/quotes.h
A engines/mads/madsv2/forest/mads/sounds.h
A engines/mads/madsv2/forest/mads/words.h
A engines/mads/madsv2/forest/main.cpp
A engines/mads/madsv2/forest/main.h
A engines/mads/madsv2/forest/main_menu.cpp
A engines/mads/madsv2/forest/main_menu.h
A engines/mads/madsv2/forest/menus.cpp
A engines/mads/madsv2/forest/menus.h
A engines/mads/madsv2/forest/rooms/room101.cpp
A engines/mads/madsv2/forest/rooms/room101.h
A engines/mads/madsv2/forest/rooms/room103.cpp
A engines/mads/madsv2/forest/rooms/room103.h
A engines/mads/madsv2/forest/rooms/room104.cpp
A engines/mads/madsv2/forest/rooms/room104.h
A engines/mads/madsv2/forest/rooms/room106.cpp
A engines/mads/madsv2/forest/rooms/room106.h
A engines/mads/madsv2/forest/rooms/room107.cpp
A engines/mads/madsv2/forest/rooms/room107.h
A engines/mads/madsv2/forest/rooms/room199.cpp
A engines/mads/madsv2/forest/rooms/room199.h
A engines/mads/madsv2/forest/rooms/room201.cpp
A engines/mads/madsv2/forest/rooms/room201.h
A engines/mads/madsv2/forest/rooms/room203.cpp
A engines/mads/madsv2/forest/rooms/room203.h
A engines/mads/madsv2/forest/rooms/room204.cpp
A engines/mads/madsv2/forest/rooms/room204.h
A engines/mads/madsv2/forest/rooms/room205.cpp
A engines/mads/madsv2/forest/rooms/room205.h
A engines/mads/madsv2/forest/rooms/room210.cpp
A engines/mads/madsv2/forest/rooms/room210.h
A engines/mads/madsv2/forest/rooms/room211.cpp
A engines/mads/madsv2/forest/rooms/room211.h
A engines/mads/madsv2/forest/rooms/room220.cpp
A engines/mads/madsv2/forest/rooms/room220.h
A engines/mads/madsv2/forest/rooms/room221.cpp
A engines/mads/madsv2/forest/rooms/room221.h
A engines/mads/madsv2/forest/rooms/room301.cpp
A engines/mads/madsv2/forest/rooms/room301.h
A engines/mads/madsv2/forest/rooms/room302.cpp
A engines/mads/madsv2/forest/rooms/room302.h
A engines/mads/madsv2/forest/rooms/room303.cpp
A engines/mads/madsv2/forest/rooms/room303.h
A engines/mads/madsv2/forest/rooms/room304.cpp
A engines/mads/madsv2/forest/rooms/room304.h
A engines/mads/madsv2/forest/rooms/room305.cpp
A engines/mads/madsv2/forest/rooms/room305.h
A engines/mads/madsv2/forest/rooms/room306.cpp
A engines/mads/madsv2/forest/rooms/room306.h
A engines/mads/madsv2/forest/rooms/room307.cpp
A engines/mads/madsv2/forest/rooms/room307.h
A engines/mads/madsv2/forest/rooms/room308.cpp
A engines/mads/madsv2/forest/rooms/room308.h
A engines/mads/madsv2/forest/rooms/room321.cpp
A engines/mads/madsv2/forest/rooms/room321.h
A engines/mads/madsv2/forest/rooms/room322.cpp
A engines/mads/madsv2/forest/rooms/room322.h
A engines/mads/madsv2/forest/rooms/room401.cpp
A engines/mads/madsv2/forest/rooms/room401.h
A engines/mads/madsv2/forest/rooms/room402.cpp
A engines/mads/madsv2/forest/rooms/room402.h
A engines/mads/madsv2/forest/rooms/room403.cpp
A engines/mads/madsv2/forest/rooms/room403.h
A engines/mads/madsv2/forest/rooms/room404.cpp
A engines/mads/madsv2/forest/rooms/room404.h
A engines/mads/madsv2/forest/rooms/room405.cpp
A engines/mads/madsv2/forest/rooms/room405.h
A engines/mads/madsv2/forest/rooms/room420.cpp
A engines/mads/madsv2/forest/rooms/room420.h
A engines/mads/madsv2/forest/rooms/room501.cpp
A engines/mads/madsv2/forest/rooms/room501.h
A engines/mads/madsv2/forest/rooms/room503.cpp
A engines/mads/madsv2/forest/rooms/room503.h
A engines/mads/madsv2/forest/rooms/room509.cpp
A engines/mads/madsv2/forest/rooms/room509.h
A engines/mads/madsv2/forest/rooms/room510.cpp
A engines/mads/madsv2/forest/rooms/room510.h
A engines/mads/madsv2/forest/rooms/room520.cpp
A engines/mads/madsv2/forest/rooms/room520.h
A engines/mads/madsv2/forest/rooms/room901.cpp
A engines/mads/madsv2/forest/rooms/room901.h
A engines/mads/madsv2/forest/rooms/room903.cpp
A engines/mads/madsv2/forest/rooms/room903.h
A engines/mads/madsv2/forest/rooms/room904.cpp
A engines/mads/madsv2/forest/rooms/room904.h
A engines/mads/madsv2/forest/rooms/section1.cpp
A engines/mads/madsv2/forest/rooms/section1.h
A engines/mads/madsv2/forest/rooms/section2.cpp
A engines/mads/madsv2/forest/rooms/section2.h
A engines/mads/madsv2/forest/rooms/section3.cpp
A engines/mads/madsv2/forest/rooms/section3.h
A engines/mads/madsv2/forest/rooms/section4.cpp
A engines/mads/madsv2/forest/rooms/section4.h
A engines/mads/madsv2/forest/rooms/section5.cpp
A engines/mads/madsv2/forest/rooms/section5.h
A engines/mads/madsv2/forest/rooms/section9.cpp
A engines/mads/madsv2/forest/rooms/section9.h
A engines/mads/madsv2/forest/sound_forest.cpp
A engines/mads/madsv2/forest/sound_forest.h
engines/mads/madsv2/forest/forest.cpp
engines/mads/madsv2/forest/forest.h
engines/mads/module.mk
diff --git a/engines/mads/madsv2/forest/asound.cpp b/engines/mads/madsv2/forest/asound.cpp
new file mode 100644
index 00000000000..70022f4fdb8
--- /dev/null
+++ b/engines/mads/madsv2/forest/asound.cpp
@@ -0,0 +1,1805 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "audio/fmopl.h"
+#include "mads/madsv2/forest/asound.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+
+
+bool AdlibChannel::_isDisabled;
+
+/*
+ * PATCH_ATTEN_TO_TL (seg001:0x0092 / offset from _asound_samples base)
+ * patchAttenuation (0-127) -> 6-bit OPL total-level.
+ * The Dragonsphere asm uses PATCH_ATTEN_TO_TL[bx] for the modulator lookup
+ * and unk_12431 - bx (i.e. PATCH_ATTEN_TO_TL[127 - patchAtt]) for the
+ * carrier lookup.
+ */
+static const uint8 PATCH_ATTEN_TO_TL[128] = {
+ 63, 54, 49, 45, 42, 40, 38, 36, 34, 33, 32, 31, 30, 29, 28, 27,
+ 26, 25, 25, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18,
+ 18, 17, 17, 16, 16, 16, 15, 15, 15, 14, 14, 14, 14, 13, 13, 13,
+ 12, 12, 12, 12, 11, 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9,
+ 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 6,
+ 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4,
+ 4, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
+};
+
+/*
+ * VOL_VEL_TO_ATTEN_STEP (_volVelToAttenStep)
+ * volume or velocity byte (0-127) -> attenuation step (1-32).
+ * Groups of 4 inputs map to the same step.
+ */
+static const uint8 VOL_VEL_TO_ATTEN_STEP[128] = {
+ 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
+ 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 9, 9, 9, 9, 10,10,10,10, 11,11,11,11, 12,12,12,12,
+ 13,13,13,13, 14,14,14,14, 15,15,15,15, 16,16,16,16,
+ 17,17,17,17, 18,18,18,18, 19,19,19,19, 20,20,20,20,
+ 21,21,21,21, 22,22,22,22, 23,23,23,23, 24,24,24,24,
+ 25,25,25,25, 26,26,26,26, 27,27,27,27, 28,28,28,28,
+ 29,29,29,29, 30,30,30,30, 31,31,31,31, 32,32,32,32
+};
+
+/*
+ * SEMITONE_FREQ_TABLE (_semitoneFreqTable)
+ * OPL F-number base for each semitone within an octave.
+ */
+static const uint16 SEMITONE_FREQ_TABLE[12] = {
+ 0x0200, 0x021E, 0x023F, 0x0261, 0x0285, 0x02AB,
+ 0x02D4, 0x02FF, 0x032D, 0x035D, 0x0390, 0x03C7
+};
+
+/*
+ * VOICE_SLOTS (byte_1239B in the binary, also used as the operator-reg
+ * index table for command6/7)
+ *
+ * Layout for each voice: { slot0 (modulator), slot1 (carrier) }
+ * The writeVolume loop uses:
+ * pass 0 -> VOICE_SLOTS[ch][0] (modulator)
+ * pass 1 -> VOICE_SLOTS[ch][1] (carrier)
+ * The alg!=0 single-op path (loc_11692) goes directly to VOICE_SLOTS[ch][1].
+ */
+static const uint8 VOICE_SLOTS[ADLIB_CHANNEL_COUNT][2] = {
+ { 0, 3 }, { 1, 4 }, { 2, 5 },
+ { 6, 9 }, { 7, 10 }, { 8, 11 },
+ { 12, 15 }, { 13, 16 }, { 14, 17 }
+};
+
+/*
+ * SLOT_TO_REG_OFFSET (_slotToRegOffset)
+ * operator-slot index (0-17) -> OPL register group offset.
+ */
+static const uint8 SLOT_TO_REG_OFFSET[18] = {
+ 0, 1, 2, 3, 4, 5,
+ 8, 9, 10, 11, 12, 13,
+ 16, 17, 18, 19, 20, 21
+};
+
+/*
+ * byte_1239B - all 22 operator TL register indices muted/restored by
+ * command6 and command7. They cover every OPL operator slot (0x40-0x55).
+ */
+static const uint8 ALL_OP_TL_REGS[22] = {
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55
+};
+
+/* Null / silence sound-data placeholder stream. */
+static uint8 ADLIB_NULLDATA[] = {
+ 0x00, 0x01, 0xF3, 0x00, 0x00, 0xEF, 0x00, 0x00,
+ 0xF5, 0x00, 0x00, 0x00, 0xF7, 0x00, 0xF8, 0x1D,
+ 0xFF, 0x00, 0xF4, 0x6E, 0x2A, 0x1C, 0xF4, 0x5F,
+ 0x2A, 0x1C, 0x2A, 0x1C, 0x2A, 0x1C, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00
+};
+
+/* OPL version flag (_adlib_v5660 / opl_version_flag).
+ * 0x18 = OPL3 (patch-attenuation-aware writeVolume path). */
+constexpr uint16 OPL_VERSION_FLAG = 0x18;
+
+/* Rhythm-mode flags (from data segment). */
+constexpr bool RHYTHM_HI_HAT = true;
+constexpr bool RHYTHM_CYMBAL = true;
+constexpr bool RHYTHM_ENABLE = true;
+
+AdlibSample::AdlibSample(Common::SeekableReadStream &s) {
+ _attackRate = s.readByte();
+ _decayRate = s.readByte();
+ _sustainLevel = s.readByte();
+ _releaseRate = s.readByte();
+ _egTyp = s.readByte();
+ _ksr = s.readByte();
+ _totalLevel = s.readByte();
+ _scalingLevel = s.readByte();
+ _waveformSelect = s.readByte();
+ _freqMultiple = s.readByte();
+ _feedback = s.readByte();
+ _ampMod = s.readByte();
+ _vib = s.readByte();
+ _alg = s.readByte();
+ _freqSweepInit = s.readByte();
+ _reserved = s.readByte();
+ _freqMask = s.readUint16LE();
+ _freqBase = s.readUint16LE();
+ _outerLoopPtr = s.readUint16LE();
+}
+
+void AdlibChannel::reset() {
+ /* Zero the scalar "live" fields only.
+ *
+ * From AdlibChannel_reset in the binary: clears _activeCount, _pitchBend,
+ * _volumeFadeStep, _vibratoDepth, _arpCounterReload (field_13),
+ * _writeVolumePending (field_11), _transpose, _patchAttenuation,
+ * _pendingStop, _velocity, _volume, _freqSweepCounter, _noiseFreqMask,
+ * _freqAccum, _freqStep, _loopStartPtr, _pSrc.
+ * All other fields are left as-is (they are overwritten by load() or
+ * by the bytecode stream before being read).
+ */
+ _activeCount = 0;
+ _pitchBend = 0;
+ _volumeFadeStep = 0;
+ _vibratoDepth = 0;
+ _arpCounterReload = 0; /* field_13 */
+ _writeVolumePending = 0; /* field_11 */
+ _transpose = 0;
+ _patchAttenuation = 0;
+ _pendingStop = 0;
+ _velocity = 0;
+ _volume = 0;
+ _freqSweepCounter = 0;
+ _noiseFreqMask = 0;
+ _freqAccum = 0;
+ _freqStep = 0;
+ _loopStartPtr = nullptr;
+ _pSrc = nullptr;
+}
+
+void AdlibChannel::load(byte *soundData) {
+ _isDisabled = true;
+
+ /* Zero all bytes in the struct. */
+ memset(this, 0, sizeof(AdlibChannel));
+
+ /* Initialise all loop/source pointers to the supplied data block. */
+ _loopStartPtr = soundData;
+ _pSrc = soundData;
+ _innerLoopPtr = soundData;
+ _outerLoopPtr = soundData;
+ _soundData = soundData;
+
+ /* Start at maximum attenuation (silent) and mark the channel active. */
+ _patchAttenuation = 0x40;
+ _activeCount = 1;
+
+ _isDisabled = false;
+}
+
+void AdlibChannel::setPtr2(byte *ptr) {
+ /* Hard-redirect both read pointers, then arm a one-step fade. */
+ _loopStartPtr = ptr;
+ _pSrc = ptr;
+ _volumeFadeStep = 0xFF; /* -1 signed: fade down */
+ _fadePeriodReload = 1;
+ _fadePeriodCounter = 1;
+}
+
+void AdlibChannel::enable() {
+ /* AdlibChannel_enable: mark pending-stop on active channels only. */
+ if (_activeCount == 0)
+ return;
+ _pendingStop = 0xFF;
+ _soundData = ADLIB_NULLDATA;
+}
+
+void AdlibChannel::processChannelFade() {
+ if (_activeCount == 0)
+ return;
+ if (_pendingStop == 0)
+ return;
+
+ /* Channel has fully faded when both velocity and volume are zero. */
+ if (_velocity == 0 && _volume == 0) {
+ _loopStartPtr = ADLIB_NULLDATA;
+ _pSrc = ADLIB_NULLDATA;
+ _pendingStop = 0;
+ return;
+ }
+
+ /* Arm a quick fade-down (period 2, step -1). */
+ _volumeFadeStep = 0xFF;
+ _fadePeriodReload = 2;
+ if (_fadePeriodCounter == 0)
+ _fadePeriodCounter = 1;
+}
+
+ASound::ASound(Audio::Mixer *mixer, OPL::OPL *opl, const Common::Path &filename,
+ int dataOffset, int dataSize)
+ : SoundDriver(mixer, opl, filename, dataOffset, dataSize) {
+ AdlibChannel::_isDisabled = false;
+
+ /* Standard OPL timer-reset sequence. */
+ write(4, 0x60);
+ write(4, 0x80);
+ write(2, 0xFF);
+ write(4, 0x21);
+ write(4, 0x60);
+ write(4, 0x80);
+
+ Common::fill(_adlibPorts, _adlibPorts + 256, 0);
+ command0();
+
+ _opl->start(new Common::Functor0Mem<void, ASound>(this, &ASound::onTimer),
+ CALLBACKS_PER_SECOND);
+}
+
+int ASound::stop() {
+ command0();
+ int result = _pollResult;
+ _pollResult = 0;
+ return result;
+}
+
+int ASound::poll() {
+ update();
+ int result = _pollResult;
+ _pollResult = 0;
+ return result;
+}
+
+void ASound::noise() {
+ Common::StackLock slock(_driverMutex);
+ for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i)
+ noise_inner(i);
+}
+
+int ASound::command0() {
+ /* Push _isDisabled, temporarily force to 0xFFFF while resetting. */
+ uint16 savedDisabled = _isDisabled;
+ _isDisabled = 0xFFFF;
+
+ /* 1. Reset all 9 channels. */
+ for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i)
+ _channels[i]->reset();
+
+ /* 2. Mute all operator TL registers (0x40 down to 0x4F, via adlib_write2
+ * with value 0x3F, stepping from 0x4F down while reg >= 0x40). */
+ for (int reg = 0x4F; reg >= 0x40; --reg)
+ write((uint8)reg, 0x3F);
+
+ /* 3. Zero registers 0xFF down to 0x60. */
+ for (int reg = 0xFF; reg >= 0x60; --reg)
+ write((uint8)reg, 0x00);
+
+ /* 4. Zero registers 0x3F down to 0x01. */
+ for (int reg = 0x3F; reg >= 0x01; --reg)
+ write((uint8)reg, 0x00);
+
+ /* 5. Waveform Select Enable. */
+ write(0x01, 0x20);
+
+ /* 6. Reset tick callback. */
+ resetCallback();
+
+ _isDisabled = savedDisabled;
+ return 0;
+}
+
+int ASound::command1() {
+ /* Fade all channels: music 0-6 (command3) then SFX 7-8 (command5). */
+ command3();
+ command5();
+ return 0;
+}
+
+int ASound::command2() {
+ /* Hard-redirect music channels 0-6 to null stream with setPtr2. */
+ _channel0.setPtr2(ADLIB_NULLDATA);
+ _channel1.setPtr2(ADLIB_NULLDATA);
+ _channel2.setPtr2(ADLIB_NULLDATA);
+ _channel3.setPtr2(ADLIB_NULLDATA);
+ _channel4.setPtr2(ADLIB_NULLDATA);
+ _channel5.setPtr2(ADLIB_NULLDATA);
+ _channel6.setPtr2(ADLIB_NULLDATA);
+ return 0;
+}
+
+int ASound::command3() {
+ /* Pending-stop music channels 0-6 (natural envelope fade via enable). */
+ _channel0.enable();
+ _channel1.enable();
+ _channel2.enable();
+ _channel3.enable();
+ _channel4.enable();
+ _channel5.enable();
+ _channel6.enable();
+ return 0;
+}
+
+int ASound::command4() {
+ /* Hard-redirect SFX channels 7-8. */
+ _channel7.setPtr2(ADLIB_NULLDATA);
+ _channel8.setPtr2(ADLIB_NULLDATA);
+ return 0;
+}
+
+int ASound::command5() {
+ /* Pending-stop SFX channels 7-8. */
+ _channel7.enable();
+ _channel8.enable();
+ return 0;
+}
+
+int ASound::command6() {
+ /* Guard: already disabled. */
+ if (_isDisabled == 0xFFFF)
+ return 0;
+ _isDisabled = 0xFFFF;
+
+ /* Save each channel's _freqSweepCounter -> _savedSweepCounter, then zero it. */
+ for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i) {
+ AdlibChannel *ch = _channels[i];
+ ch->_savedSweepCounter = ch->_freqSweepCounter;
+ ch->_freqSweepCounter = 0;
+ }
+
+ /* Mute all 22 operator TL registers. */
+ for (int i = 0; i < 22; ++i)
+ adlib_channelOff(ALL_OP_TL_REGS[i]);
+
+ return 0;
+}
+
+int ASound::command7() {
+ /* Guard: only resume from a paused state. */
+ if (_isDisabled != 0xFFFF)
+ return 0;
+
+ /* Restore all operator volumes from the _adlibPorts shadow
+ * (asound_playMusicC: just re-writes whatever was last written). */
+ for (int i = 0; i < 22; ++i)
+ adlib_channelOn(ALL_OP_TL_REGS[i]);
+
+ /* Restore each channel's sweep counter and check whether any was non-zero. */
+ uint8 anySweep = 0;
+ for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i) {
+ AdlibChannel *ch = _channels[i];
+ ch->_freqSweepCounter = ch->_savedSweepCounter;
+ anySweep |= ch->_savedSweepCounter;
+ }
+
+ if (anySweep != 0)
+ signalSoundPlaying();
+
+ _isDisabled = 0;
+ return 0;
+}
+
+int ASound::command8() {
+ /* Returns non-zero if any channel is currently active.
+ * Clears byte_12393 (music-only flag) first so all 9 channels are checked. */
+ _musicOnlyFlag = 0;
+ uint8 result = 0;
+ for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i)
+ result |= _channels[i]->_activeCount;
+ return result;
+}
+
+int ASound::command18() {
+ /* Re-entrant background-music launcher (asound_command18 in the binary).
+ * Fades everything, then dispatches back through the command table using
+ * _musicIndex (word_12370) as the command ID. */
+ command1();
+ return command(_musicIndex, 0);
+}
+
+void ASound::callFunction(uint16 offset) {
+ error("Unsupported call to sound driver function at offset %.4x", offset);
+}
+
+void ASound::write(uint8 reg, uint8 value) {
+ _adlibPorts[reg] = value;
+ _opl->writeReg(reg, value);
+}
+
+void ASound::onTimer() {
+ Common::StackLock slock(_driverMutex);
+ poll();
+}
+
+uint16 ASound::getRandomNumber() {
+ /* asound_getRandomNumber: ax = ror3(0x9248 + seed). */
+ uint16 ax = (uint16)(0x9248u + _randomSeed);
+ ax = (uint16)((ax >> 3) | (ax << 13));
+ _randomSeed = ax;
+ return ax;
+}
+
+void ASound::adlib_channelOff(uint8 portIndex) {
+ /* sub_1018F: OR the register with 0x3F (force max attenuation),
+ * then write back both to _adlibPorts and to the OPL chip.
+ * Note: unlike the Phantom driver, the original value is NOT preserved
+ * in _adlibPorts - the ORed value is stored back. */
+ uint8 val = _adlibPorts[portIndex] | 0x3F;
+ _adlibPorts[portIndex] = val;
+ _opl->writeReg(portIndex, val);
+}
+
+void ASound::adlib_channelOn(uint8 portIndex) {
+ /* asound_playMusicC: re-writes whatever _adlibPorts already holds.
+ * command7 simply replays the shadow without recalculating anything. */
+ _opl->writeReg(portIndex, _adlibPorts[portIndex]);
+}
+
+void ASound::signalSoundPlaying() {
+ /* asound_signalSoundPlaying: set resultFlag/pollResult to non-zero. */
+ if (_resultFlag == (int16)0xFFFF)
+ return;
+ _resultFlag = (int16)0xFFFF;
+ _pollResult = (int16)0xFFFF;
+}
+
+void ASound::clearCallback() {
+ _callbackFnPtr = nullptr;
+ _callbackCounter = 0;
+ _callbackPeriod = 0;
+}
+
+void ASound::tickCallback() {
+ if (_callbackPeriod == 0)
+ return;
+ if (--_callbackCounter != 0)
+ return;
+
+ _callbackCounter = _callbackPeriod;
+ if (_callbackFnPtr == nullptr)
+ return;
+
+ auto fn = _callbackFnPtr;
+ _callbackFnPtr = nullptr;
+ (this->*fn)();
+}
+
+void ASound::writeVolume() {
+ AdlibChannel *ch = _activeChannelPtr;
+ uint8 chanNum = _activeChannelNumber;
+
+ /* Compute combined attenuation step from volume and velocity. */
+ uint8 volIdx = ch->_volume;
+ uint8 velIdx = ch->_velocity;
+ int16 volStep = (int16)(uint16)VOL_VEL_TO_ATTEN_STEP[volIdx];
+ int16 velStep = (int16)(uint16)VOL_VEL_TO_ATTEN_STEP[velIdx];
+ int16 var4 = volStep + velStep - 1; /* var_4: combined step (shared) */
+
+ /* Check _alg of the first sample to determine loop count. */
+ AdlibSample *smpFirst = &_samples[ch->_sampleIndex * 2];
+ int passes = (smpFirst->_alg == 0) ? 2 : 1;
+
+ /* si and di track the two TL values written per pass for caching. */
+ int16 finalSi = 0, finalDi = 0;
+
+ /* var_6 = loop counter (0, then 1 for the two-pass case).
+ * For alg != 0 we jump straight into the carrier path (var_6 stays at
+ * effectively 1: VOICE_SLOTS[ch][1]). */
+ for (int var6 = (passes == 1 ? 1 : 0); var6 < 2; ++var6) {
+
+ /* Reload var_2 = var_4 at the start of each pass (loc_11642). */
+ int16 var2 = var4;
+
+ /* Select the operator slot. */
+ uint8 slot = VOICE_SLOTS[chanNum][var6];
+ uint8 regOff = SLOT_TO_REG_OFFSET[slot];
+ uint16 tlReg = (uint16)regOff + 0x40; /* var_8 */
+
+ /* KSL bits from the port shadow. */
+ int16 kslBits = (int16)((uint16)_adlibPorts[tlReg] & 0xC0); /* var_A */
+
+ int16 si, di;
+
+ if (OPL_VERSION_FLAG < 0x18) {
+ /* ---- OPL2 simple path (loc_1167C / loc_1167C equivalent) ---- */
+ int16 tl = (int16)0x3F - var2;
+ tl |= kslBits;
+ si = tl;
+ di = tl;
+ /* adlib_write2(8, tlReg, tl) */
+ write((uint8)tlReg, (uint8)tl);
+ } else {
+ /* ---- OPL3 patch-attenuation path (loc_115BE / loc_116D4) ---- */
+ uint8 pa = ch->_patchAttenuation;
+
+ /* Modulator TL (first register, offset 0): */
+ int16 tlMod = (int16)(uint16)PATCH_ATTEN_TO_TL[pa];
+ /* -(tlMod - var2) = var2 - tlMod */
+ int16 atten1 = var2 - tlMod; /* ax = si initially */
+ si = atten1;
+ if (si < 0) si = 0;
+ else if (si > 63) si = 63;
+ int16 reg0val = ((int16)0x3F - si) | kslBits;
+ si = reg0val;
+ write((uint8)tlReg, (uint8)reg0val);
+
+ /* Carrier TL (second register, offset 2):
+ * unk_12431 - bx (where bx = pa) == PATCH_ATTEN_TO_TL[127 - pa]. */
+ int16 tlCar = (int16)(uint16)PATCH_ATTEN_TO_TL[127 - pa];
+ /* di = var_2 - tlCar (var_4 for alg!=0, var_2=var_4 reload for alg==0) */
+ di = var2 - tlCar;
+ int16 diClamped = di;
+ if (diClamped < 0) diClamped = 0;
+ else if (diClamped > 0x3F) diClamped = 0x3F;
+ int16 reg2val = ((int16)0x3F - diClamped) | kslBits;
+ di = reg2val;
+ write((uint8)(tlReg + 2), (uint8)reg2val);
+ }
+
+ /* For the alg!=0 single-pass case we only run this once (var6==1).
+ * For the alg==0 two-pass case, record both sets. */
+ if (var6 == 1) {
+ finalSi = si;
+ finalDi = di;
+ } else {
+ /* var6==0: record si/di for the mod pass; di is overwritten on
+ * the carrier pass so we use si for the high byte of field_2A. */
+ finalSi = si;
+ finalDi = di;
+ }
+ }
+
+ /* Cache the written TL bytes in field_2A:
+ * dl = di & 0x3F (carrier / second register)
+ * dh = si & 0x3F (modulator / first register)
+ * Packed as a word at offset 0x2A. */
+ ch->_cachedCarrierTL = (uint8)(finalDi & 0x3F); /* dl -> field_2A low byte */
+ /* The high byte (si & 0x3F) is stored in _savedFreqSweep (offset 0x2B)
+ * by the assembly. We write it separately to avoid clobbering the real
+ * savedFreqSweep which lives there - the original asm stores both bytes
+ * as a word at [bx+2Ah], meaning field_2A=dl and field_2B=dh=si&0x3F.
+ * In our C++ layout _savedFreqSweep is at 0x2B; we shadow the dh byte
+ * into it only when writing volume, consistent with the original. */
+ ch->_savedFreqSweep = (uint8)(finalSi & 0x3F);
+}
+
+void ASound::writeFrequency() {
+ AdlibChannel *ch = _activeChannelPtr;
+ uint8 chanNum = _activeChannelNumber;
+ uint16 aReg = (uint16)chanNum + 0xA0;
+ uint16 bReg = (uint16)chanNum + 0xB0;
+
+ /* Note is 1-based; _octaveTranspose shifts by whole octaves. */
+ int note = (int)ch->_note + (int)ch->_octaveTranspose - 1;
+ int octave = note / 12;
+ int semi = note % 12;
+ if (semi < 0) {
+ semi += 12; --octave;
+ }
+
+ /* F-number from table, with optional signed transpose offset. */
+ int16 fnum = (int16)SEMITONE_FREQ_TABLE[semi] + (int16)(int8)ch->_transpose;
+
+ write((uint8)aReg, (uint8)fnum);
+
+ uint8 bVal = _adlibPorts[bReg] & 0x20; /* preserve key-on bit */
+ bVal |= (uint8)((fnum >> 8) & 0x03); /* F-num bits 9:8 */
+ bVal |= (uint8)(((uint8)octave & 0x07) << 2); /* block/octave bits 4:2 */
+ write((uint8)bReg, bVal);
+}
+
+void ASound::writePitchBend() {
+ AdlibChannel *ch = _activeChannelPtr;
+ uint8 chanNum = _activeChannelNumber;
+ uint16 aReg = (uint16)chanNum + 0xA0;
+ uint16 bReg = (uint16)chanNum + 0xB0;
+
+ /* Reconstruct the 10-bit F-number from the port shadow. */
+ uint16 fnum = (uint16)_adlibPorts[aReg]
+ | ((uint16)(_adlibPorts[bReg] & 0x1F) << 8);
+
+ int16 bent = (int16)fnum + (int16)(int8)ch->_pitchBend;
+
+ write((uint8)aReg, (uint8)bent);
+
+ /* Preserve block + key-on, update F-num[9:8]. */
+ uint8 bVal = _adlibPorts[bReg] & 0x20;
+ bVal |= (uint8)((bent >> 8) & 0x03);
+ write((uint8)bReg, bVal);
+}
+
+void ASound::writeArpeggio() {
+ AdlibChannel *ch = _activeChannelPtr;
+ uint8 chanNum = _activeChannelNumber;
+ uint16 aReg = (uint16)chanNum + 0xA0;
+ uint16 bReg = (uint16)chanNum + 0xB0;
+
+ /* dl = _note + _octaveTranspose + _writeVolumePending - 1 */
+ int note = (int)ch->_note + (int)ch->_octaveTranspose
+ + (int)ch->_writeVolumePending - 1;
+ int octave = note / 12;
+ int semi = note % 12;
+ if (semi < 0) {
+ semi += 12; --octave;
+ }
+
+ uint16 freqEntry = SEMITONE_FREQ_TABLE[semi];
+ uint8 fnHigh = (uint8)((freqEntry >> 8) & 0x03);
+ uint8 block = (uint8)(octave & 0x07);
+ uint8 bVal = (uint8)((block << 2) | fnHigh) | (_adlibPorts[bReg] & 0x20);
+
+ write((uint8)aReg, (uint8)freqEntry);
+ write((uint8)bReg, bVal);
+}
+
+void ASound::updateOctave() {
+ uint8 chanNum = _activeChannelNumber;
+ uint16 bReg = (uint16)chanNum + 0xB0;
+ write((uint8)bReg, _adlibPorts[bReg] & 0xDF);
+}
+
+void ASound::noteOn() {
+ AdlibChannel *ch = _activeChannelPtr;
+ AdlibSample *smp = &_samples[ch->_sampleIndex];
+
+ writeVolume();
+
+ ch->_freqSweepCounter = smp->_freqSweepInit;
+
+ if (ch->_freqSweepCounter != 0) {
+ /* Sweep is pending; signal that sound is active but don't key on yet. */
+ signalSoundPlaying();
+ return;
+ }
+
+ /* No sweep - write frequency and set key-on immediately. */
+ writeFrequency();
+
+ uint8 chanNum = _activeChannelNumber;
+ uint16 bReg = (uint16)chanNum + 0xB0;
+ write((uint8)bReg, _adlibPorts[bReg] | 0x20);
+}
+
+void ASound::writeSampleRegs() {
+ AdlibSample *smp = _samplePtr;
+ uint16 base = _currentOpBase;
+
+ /* 0xBD: rhythm mode flags. */
+ uint8 bdVal = _adlibPorts[0xBD] & 0x3F;
+ if (RHYTHM_HI_HAT) bdVal |= 0x80;
+ if (RHYTHM_CYMBAL) bdVal |= 0x40;
+ write(0xBD, bdVal);
+
+ /* 0x08: note-select / rhythm enable. */
+ write(0x08, RHYTHM_ENABLE ? 0x40 : 0x00);
+
+ /* 0xC0+voice: feedback and algorithm.
+ * asm: feedback << 1, then alg==1 -> bit0=0, else -> bit0=1. */
+ write((uint8)(_activeChannelReg + 0xC0),
+ (uint8)((smp->_feedback << 1) | (smp->_alg == 1 ? 0 : 1)));
+
+ /* 0x60+base: attack / decay. */
+ write((uint8)(base + 0x60),
+ (uint8)(((smp->_attackRate & 0x0F) << 4) | (smp->_decayRate & 0x0F)));
+
+ /* 0x80+base: sustain level / release rate. */
+ write((uint8)(base + 0x80),
+ (uint8)(((smp->_sustainLevel & 0x0F) << 4) | (smp->_releaseRate & 0x0F)));
+
+ /* 0x20+base: AM/VIB/EGT/KSR/mult flags. */
+ uint8 amVal = smp->_freqMultiple & 0x0F;
+ if (smp->_egTyp == 1) amVal |= 0x20;
+ if (smp->_vib == 1) amVal |= 0x40;
+ if (smp->_ksr == 1) amVal |= 0x10;
+ if (smp->_ampMod == 1) amVal |= 0x80;
+ write((uint8)(base + 0x20), amVal);
+
+ /* 0xE0+base: waveform select. */
+ write((uint8)(base + 0xE0), (uint8)(smp->_waveformSelect & 0x03));
+}
+
+void ASound::loadSample() {
+ AdlibChannel *ch = _activeChannelPtr;
+ uint8 chanNum = _activeChannelNumber;
+
+ /* Phase 1: Silence modulator operator (slot 0). */
+ uint8 mSlot = VOICE_SLOTS[chanNum][0];
+ uint8 mRegOff = SLOT_TO_REG_OFFSET[mSlot];
+ write((uint8)(mRegOff + 0x80), 0xFF);
+ write((uint8)(mRegOff + 0x40), 63);
+
+ /* Phase 2: Silence carrier operator (slot 1). */
+ uint8 cSlot = VOICE_SLOTS[chanNum][1];
+ uint8 cRegOff = SLOT_TO_REG_OFFSET[cSlot];
+ write((uint8)(cRegOff + 0x80), 0xFF);
+ write((uint8)(cRegOff + 0x40), 63);
+
+ /* Phase 3: Write first sample (modulator) registers. */
+ _activeChannelReg = (uint16)chanNum;
+ _currentOpBase = mRegOff;
+ _samplePtr = &_samples[ch->_sampleIndex * 2];
+ writeSampleRegs();
+
+ /* Phase 4: Write second sample (carrier) registers. */
+ _currentOpBase = cRegOff;
+ _samplePtr = &_samples[ch->_sampleIndex * 2 + 1];
+ writeSampleRegs();
+
+ /* Phase 5: Write carrier TL (KSL | 0x3F for full attenuation initially). */
+ write((uint8)(cRegOff + 0x40),
+ (uint8)((_samplePtr->_scalingLevel << 6) | 0x3F));
+
+ /* Phase 6: Use the first sample again for the modulator TL and for
+ * sweep/frequency initialisation. */
+ AdlibSample *smp3 = &_samples[ch->_sampleIndex * 2];
+ uint16 mTLReg = (uint16)mRegOff + 0x40;
+
+ if (smp3->_alg == 0) {
+ write((uint8)mTLReg, (uint8)((smp3->_scalingLevel << 6) | 0x3F));
+ } else {
+ /* alg != 0: negate (totalLevel - 63) to get the TL value. */
+ uint8 tl = (uint8)(-(int8)(smp3->_totalLevel - 63));
+ write((uint8)mTLReg, (uint8)((smp3->_scalingLevel << 6) | (tl & 0x3F)));
+ }
+
+ /* Copy sweep/frequency parameters from the sample into the channel. */
+ ch->_freqSweepCounter = smp3->_freqSweepInit;
+ ch->_noiseFreqMask = smp3->_freqMask;
+ ch->_freqAccum = smp3->_freqBase;
+ ch->_freqStep = smp3->_outerLoopPtr;
+}
+
+void ASound::update() {
+ if (_isDisabled)
+ return;
+
+ (void)getRandomNumber();
+ ++_frameNumber2;
+
+ pollAllChannels();
+ tickCallback(); /* asound_updateCallback */
+ updateAllChannels();
+
+ _anySweepActive = 0;
+
+ for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i)
+ update1(i);
+
+ /* If no sweep is active, flag the result as "done". */
+ if (!_anySweepActive) {
+ if (_resultFlag != (int16)0xFFFF) {
+ _resultFlag = (int16)0xFFFF;
+ _pollResult = (int16)0xFFFF;
+ }
+ }
+}
+
+void ASound::update1(int channelIndex) {
+ /* asound_update1: called with cx = channelIndex+1 in the original loop.
+ * Accesses channel via the adlib_channels pointer table. */
+ AdlibChannel *ch = _channels[channelIndex];
+
+ if (ch->_freqSweepCounter == 0)
+ return;
+
+ _anySweepActive = 1;
+ ch->_freqAccum += ch->_freqStep;
+ ch->_freqSweepCounter--;
+
+ if (ch->_freqSweepCounter != 0)
+ return;
+
+ /* Sweep finished: write zero frequency to silence this OPL voice. */
+ uint8 voice = (uint8)channelIndex;
+ write((uint8)(voice + 0xA0), 0x00);
+ write((uint8)(voice + 0xB0), 0x00);
+}
+
+void ASound::setFrequency(uint8 voice, uint16 freq) {
+ /* asound_setFrequency: writes A0+v and B0+v (with key-on). */
+ write((uint8)(voice + 0xA0), (uint8)(freq & 0xFF));
+ uint8 bVal = (_adlibPorts[voice + 0xB0] & 0x20)
+ | (uint8)((freq >> 8) & 0x03)
+ | 0x20;
+ write((uint8)(voice + 0xB0), bVal);
+}
+
+void ASound::noise_inner(int channelIndex) {
+ /* adlib_noise_inner */
+ AdlibChannel *ch = _channels[channelIndex];
+
+ if (ch->_freqSweepCounter == 0)
+ return;
+
+ uint16 rnd = getRandomNumber();
+ uint16 freq = (rnd & ch->_noiseFreqMask) + ch->_freqAccum;
+ setFrequency((uint8)channelIndex, freq);
+}
+
+void ASound::updateAllChannels() {
+ for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i)
+ _channels[i]->processChannelFade();
+}
+
+void ASound::findFreeChannel(byte *soundData) {
+ _findChannelMode = 0;
+
+ /* Scan channels 0-6 for an empty slot. */
+ for (int ch = 0; ch < 7; ++ch) {
+ if (_channels[ch]->_activeCount == 0) {
+ _channels[ch]->load(soundData);
+ return;
+ }
+ }
+
+ /* _findChannelMode==0: fall through to full search. */
+ findFreeChannelFull(soundData);
+}
+
+void ASound::findFreeChannelFull(byte *soundData) {
+ _findChannelMode = 2;
+
+ /* Scan channels 7-8 for an empty slot. */
+ if (_channel7._activeCount == 0) {
+ _channel7.load(soundData); return;
+ }
+ if (_channel8._activeCount == 0) {
+ _channel8.load(soundData); return;
+ }
+
+ /* Scan ch8 then ch7 for pending-stop (pre-emptible). */
+ if (_channel8._pendingStop == 0xFF) {
+ _channel8.load(soundData); return;
+ }
+ if (_channel7._pendingStop == 0xFF) {
+ _channel7.load(soundData); return;
+ }
+
+ /* If _findChannelMode allows it, scan ch6..ch0 for pending-stop. */
+ if (_findChannelMode == 0) {
+ if (_channel6._pendingStop == 0xFF) {
+ _channel6.load(soundData); return;
+ }
+ if (_channel5._pendingStop == 0xFF) {
+ _channel5.load(soundData); return;
+ }
+ if (_channel4._pendingStop == 0xFF) {
+ _channel4.load(soundData); return;
+ }
+ if (_channel3._pendingStop == 0xFF) {
+ _channel3.load(soundData); return;
+ }
+ if (_channel2._pendingStop == 0xFF) {
+ _channel2.load(soundData); return;
+ }
+ if (_channel1._pendingStop == 0xFF) {
+ _channel1.load(soundData); return;
+ }
+ if (_channel0._pendingStop == 0xFF) {
+ _channel0.load(soundData); return;
+ }
+ }
+}
+
+int ASound::isMusicChannelsActive() {
+ _musicOnlyFlag = 1;
+ uint8 result = 0;
+ for (int i = 0; i <= 6; ++i)
+ result |= _channels[i]->_activeCount;
+ return result;
+}
+
+int ASound::isAnyChannelActive() {
+ _musicOnlyFlag = 0;
+ uint8 result = 0;
+ for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i)
+ result |= _channels[i]->_activeCount;
+ return result;
+}
+
+void ASound::pollAllChannels() {
+ _activeChannelNumber = 0;
+ for (int ch = 0; ch < ADLIB_CHANNEL_COUNT; ++ch) {
+ _activeChannelPtr = _channels[ch];
+ pollActiveChannel();
+ /* Note: _activeChannelNumber is incremented at the end of
+ * pollActiveChannel, not here. */
+ }
+}
+
+bool ASound::isSoundActive(byte *ptr) const {
+ for (int ch = 0; ch < ADLIB_CHANNEL_COUNT; ++ch) {
+ if (_channels[ch]->_activeCount && _channels[ch]->_soundData == ptr)
+ return true;
+ }
+ return false;
+}
+
+uint16 ASound::readWord_impl() {
+ /* asound_readWord: advance pSrc past the low byte, read lo then hi. */
+ uint16 lo = *++pSrc;
+ uint16 hi = *++pSrc;
+ return lo | (hi << 8);
+}
+
+void ASound::pollActiveChannel() {
+ AdlibChannel *ch = _activeChannelPtr;
+
+ if (ch->_activeCount == 0) {
+ ++_activeChannelNumber;
+ return;
+ }
+
+ /* byte_16A0A: volume-dirty flag. Cleared here, set by various opcodes
+ * and by the fade/vibrato sections; causes writeVolume at the end. */
+ bool volDirty = false;
+
+ /* ---- Key-on delay countdown ---- */
+ if (ch->_keyOnDelay != 0) {
+ ch->_keyOnDelay--;
+ ch = _activeChannelPtr;
+ if (ch->_keyOnDelay == 0)
+ updateOctave();
+ }
+
+ /* ---- Duration countdown ---- */
+ ch = _activeChannelPtr;
+ ch->_activeCount--;
+ ch = _activeChannelPtr;
+ if (ch->_activeCount != 0)
+ goto post_keyon;
+
+ /* ================================================================
+ * Command-dispatch loop.
+ * Re-entered (via goto dispatch) after each command that does not
+ * consume a duration tick. Falls through to the note-event path
+ * when a note byte is encountered.
+ * ================================================================ */
+dispatch:
+ {
+ ch = _activeChannelPtr;
+ pSrc = ch->_pSrc;
+
+ uint8 b = *pSrc;
+
+ if (!(b & 0x80))
+ goto note_event;
+
+ /* Decode group (si) and sub-opcode (di). */
+ uint8 si = b & 0x70;
+ uint8 di = b & 0x0F;
+
+ if (si == 0x00) {
+ /* ============================================================
+ * opcodes1 (group 0, 0x8_)
+ * Called with: pSrc pointing at the command byte.
+ * On entry, opcodes1 does: inc pSrc (skip past command byte).
+ * On exit, sets _pSrc = pSrc + 1 (def_10CDC).
+ * ============================================================ */
+ pSrc++; /* skip command byte */
+
+ switch (di) {
+
+ case 0x0: /* set sampleIndex, call loadSample */
+ ch->_sampleIndex = *pSrc;
+ loadSample();
+ volDirty = true;
+ /* def_10CDC: _pSrc = pSrc + 1 */
+ ch->_pSrc = pSrc + 1;
+ goto dispatch;
+
+ case 0x1: /* set velocity */
+ {
+ uint8 vel = *pSrc;
+ if (ch->_pendingStop != 0) {
+ /* If current velocity (signed) > new vel (signed), clamp down. */
+ if ((int16)(int8)ch->_velocity > (int16)(int8)vel)
+ ch->_velocity = vel;
+ } else {
+ ch->_velocity = vel;
+ }
+ volDirty = true;
+ ch->_pSrc = pSrc + 1;
+ goto dispatch;
+ }
+
+ case 0x2: /* set volume */
+ {
+ uint8 vol = *pSrc;
+ if (ch->_pendingStop != 0) {
+ /* Don't raise volume above current when fading out. */
+ uint16 curVol = (uint16)ch->_volume;
+ if (curVol <= (uint16)vol)
+ goto op2_set_vol;
+ /* else fall through and skip the set */
+ volDirty = true;
+ ch->_pSrc = pSrc + 1;
+ goto dispatch;
+ }
+op2_set_vol:
+ ch->_volume = vol;
+ volDirty = true;
+ ch->_pSrc = pSrc + 1;
+ goto dispatch;
+ }
+
+ case 0x3: /* set patchAttenuation */
+ ch->_patchAttenuation = *pSrc;
+ volDirty = true; /* opcodes1 case 3 jumps to loc_10B56 -> byte_16A0A=1 */
+ ch->_pSrc = pSrc + 1;
+ goto dispatch;
+
+ case 0x4: /* set fade: fadePeriodReload, volumeFadeStep */
+ if (ch->_pendingStop != 0) {
+ /* Skip this opcode entirely when pending-stop is set. */
+ ch->_pSrc = pSrc + 2;
+ goto dispatch;
+ }
+ ch->_fadePeriodReload = *pSrc++;
+ ch->_volumeFadeStep = *pSrc;
+ ch->_fadePeriodCounter = 1;
+ ch->_pSrc = pSrc + 1;
+ goto dispatch;
+
+ case 0x5: /* set vibrato: vibPeriodReload, vibPeriodCounter=reload, vibratoDepth, vibratoMode */
+ ch->_vibPeriodReload = *pSrc++;
+ ch->_vibPeriodCounter = ch->_vibPeriodReload;
+ ch->_vibratoDepth = *pSrc++;
+ ch->_vibratoMode = *pSrc;
+ ch->_pSrc = pSrc + 1;
+ goto dispatch;
+
+ case 0x6: /* set transpose */
+ ch->_transpose = *pSrc;
+ ch->_pSrc = pSrc + 1;
+ goto dispatch;
+
+ case 0x7: /* set octaveTranspose */
+ ch->_octaveTranspose = *pSrc;
+ ch->_pSrc = pSrc + 1;
+ goto dispatch;
+
+ case 0x8: /* set field_11 (_writeVolumePending) */
+ ch->_writeVolumePending = *pSrc;
+ ch->_pSrc = pSrc + 1;
+ goto dispatch;
+
+ case 0x9: /* set arpeggio: field_12->field_C, pitchBend, field_13 */
+ ch->_arpPeriodReload = *pSrc++;
+ ch->_arpPeriodCounter = ch->_arpPeriodReload; /* field_C = field_12 */
+ ch->_pitchBend = *pSrc++;
+ ch->_arpCounterReload = *pSrc;
+ ch->_pSrc = pSrc + 1;
+ goto dispatch;
+
+ case 0xA: /* skip forward by N+3 bytes (from the command byte) */
+ {
+ uint8 skip = *pSrc;
+ /* pSrc currently points at the byte after the command byte.
+ * Advance _pSrc by (skip + 3) from the *command* byte position,
+ * which is pSrc-1. So _pSrc += skip + 3 from original _pSrc,
+ * which was command byte. But def_10CDC does _pSrc = pSrc+1
+ * giving +2 past command. Then skip+3 total from command: */
+ /* asm: si = skip; ax = si + 3; add pSrc, ax; then def_10CDC
+ * does pSrc+1. So net advance from the command byte =
+ * skip + 3 + 1 = skip + 4. But pSrc already points one past
+ * command byte, so _pSrc = pSrc + skip + 3. */
+ ch->_pSrc = pSrc + (uint16)skip + 3;
+ goto dispatch;
+ }
+
+ case 0xB: /* set durationOverride, clear noteOffset */
+ ch->_durationOverride = *pSrc;
+ ch->_noteOffset = 0;
+ ch->_pSrc = pSrc + 1;
+ goto dispatch;
+
+ case 0xC: /* set noteOffset, clear durationOverride */
+ ch->_noteOffset = *pSrc;
+ ch->_durationOverride = 0;
+ ch->_pSrc = pSrc + 1;
+ goto dispatch;
+
+ default:
+ /* Unknown sub-opcode: advance past the single operand byte. */
+ ch->_pSrc = pSrc + 1;
+ goto dispatch;
+ }
+ }
+
+ if (si == 0x10) {
+ /* ============================================================
+ * opcodes2 (group 1, 0x9_)
+ * Loop control, restart, branch / call.
+ * On exit: either sets _pSrc directly or falls to def_10EAC
+ * (which just returns without touching _pSrc - the handlers
+ * themselves are responsible for updating _pSrc).
+ * ============================================================ */
+ switch (di) {
+
+ case 0x0: /* inner loop */
+ {
+ ch = _activeChannelPtr;
+ if (ch->_innerLoopCount == 0) {
+ pSrc++; /* advance to count byte */
+ uint8 cnt = *pSrc;
+ if (cnt == 0) {
+ ch->_pSrc += 2;
+ ch = _activeChannelPtr;
+ ch->_innerLoopPtr = ch->_pSrc;
+ ch->_innerLoopCount = 0;
+ goto dispatch;
+ }
+ ch->_innerLoopCount = (uint16)cnt;
+ /* Jump to innerLoopPtr (loc_10D5A). */
+ ch->_pSrc = ch->_innerLoopPtr;
+ goto dispatch;
+ }
+ /* Count is non-zero: decrement. */
+ ch->_innerLoopCount--;
+ ch = _activeChannelPtr;
+ if (ch->_innerLoopCount == 0) {
+ /* Loop done: advance past the two-byte opcode. */
+ ch->_pSrc += 2;
+ ch = _activeChannelPtr;
+ ch->_innerLoopPtr = ch->_pSrc;
+ goto dispatch;
+ }
+ /* Still looping: jump back. */
+ ch->_pSrc = ch->_innerLoopPtr;
+ goto dispatch;
+ }
+
+ case 0x1: /* outer loop */
+ {
+ ch = _activeChannelPtr;
+ if (ch->_outerLoopCount == 0) {
+ pSrc++;
+ uint8 cnt = *pSrc;
+ if (cnt == 0) {
+ ch->_pSrc += 2;
+ ch = _activeChannelPtr;
+ ch->_outerLoopPtr = ch->_pSrc;
+ ch->_innerLoopPtr = ch->_pSrc;
+ ch->_innerLoopCount = 0;
+ ch->_outerLoopCount = 0;
+ goto dispatch;
+ }
+ ch->_outerLoopCount = (uint16)cnt;
+ /* Jump to outerLoopPtr. */
+ ch->_pSrc = ch->_outerLoopPtr;
+ ch = _activeChannelPtr;
+ ch->_innerLoopPtr = ch->_outerLoopPtr;
+ goto dispatch;
+ }
+ /* Count non-zero: decrement. */
+ ch->_outerLoopCount--;
+ ch = _activeChannelPtr;
+ if (ch->_outerLoopCount == 0) {
+ ch->_pSrc += 2;
+ ch = _activeChannelPtr;
+ ch->_outerLoopPtr = ch->_pSrc;
+ ch->_innerLoopPtr = ch->_pSrc;
+ goto dispatch;
+ }
+ ch->_pSrc = ch->_outerLoopPtr;
+ ch = _activeChannelPtr;
+ ch->_innerLoopPtr = ch->_outerLoopPtr;
+ goto dispatch;
+ }
+
+ case 0x2: /* restart: reset all loop pointers to _soundData */
+ {
+ ch = _activeChannelPtr;
+ uint16 sd = (uint16)(uintptr_t)ch->_soundData;
+ ch->_loopStartPtr = ch->_soundData;
+ ch->_pSrc = ch->_soundData;
+ ch->_innerLoopPtr = ch->_soundData;
+ ch->_outerLoopPtr = ch->_soundData;
+ (void)sd;
+ goto dispatch;
+ }
+
+ case 0x3: /* set sound-data pointer (abs word offset), reset all loops */
+ {
+ byte *ptr = &_soundData[readWord_impl()];
+ ch = _activeChannelPtr;
+ ch->_loopStartPtr = ptr;
+ ch->_pSrc = ptr;
+ ch->_innerLoopPtr = ptr;
+ ch->_outerLoopPtr = ptr;
+ ch->_soundData = ptr;
+ goto dispatch;
+ }
+
+ case 0x4: /* branch unconditional */
+ {
+ byte *dest = &_soundData[readWord_impl()];
+ ch = _activeChannelPtr;
+ ch->_pSrc = dest;
+ goto dispatch;
+ }
+
+ case 0x5: /* branch with return-address save */
+ {
+ byte *dest = &_soundData[readWord_impl()];
+ ch = _activeChannelPtr;
+ ch->_branchTargetPtr = ch->_pSrc + 3;
+ ch->_pSrc = dest;
+ goto dispatch;
+ }
+
+ case 0x6: /* return from branch */
+ {
+ ch = _activeChannelPtr;
+ if (ch->_branchTargetPtr != nullptr) {
+ ch->_pSrc = ch->_branchTargetPtr;
+ ch->_branchTargetPtr = nullptr;
+ } else {
+ ch->_pSrc++;
+ }
+ goto dispatch;
+ }
+
+ default:
+ /* Unknown sub-opcode: no _pSrc advance (def_10EAC). */
+ goto dispatch;
+ }
+ }
+
+ if (si == 0x20) {
+ /* ============================================================
+ * opcodes3 (group 2, 0xA_)
+ * Tempo/callback globals, random table operations,
+ * indirect-table operations, call-by-address, nullsub.
+ *
+ * opcodes3 receives di (sub-opcode) but NOT the already-
+ * incremented pSrc; each case increments pSrc itself as needed.
+ * ============================================================ */
+ switch (di) {
+
+ case 0x0: /* random pick from packed table -> write to stream */
+ {
+ /* Format: [cmd] [tblSize] [entry0..N-1] [targetSlot]
+ * pSrc points at the command byte on entry. */
+ pSrc++;
+ uint8 tblSize = *pSrc;
+ pSrc++; /* now at entry[0] */
+ (void)getRandomNumber();
+ uint16 rnd = _randomSeed & 0x7FFF;
+ int16 idx = (int16)((int16)rnd % (int16)(uint16)tblSize);
+ uint8 chosen = *(pSrc + idx);
+ uint8 target = *(pSrc + tblSize);
+ *(pSrc + (uint16)target + 1) = chosen;
+ ch = _activeChannelPtr;
+ ch->_pSrc += (uint16)tblSize + 3;
+ goto dispatch;
+ }
+
+ case 0x1: /* random range [lo..hi] -> write to stream */
+ {
+ /* Format: [cmd] [lo] [hi] [targetSlot] ... */
+ pSrc++;
+ uint8 lo = *pSrc++;
+ uint8 hi = *pSrc++;
+ uint16 range = (uint16)(hi - lo) + 1;
+ /* pSrc now at targetSlot byte. */
+ (void)getRandomNumber();
+ uint16 rnd = _randomSeed & 0x7FFF;
+ uint8 res = (uint8)((int16)rnd % (int16)range) + lo;
+ uint8 slot = *pSrc;
+ *(pSrc + (uint16)slot + 1) = res;
+ ch = _activeChannelPtr;
+ ch->_pSrc += 4; /* command+lo+hi+slot = 4 bytes consumed */
+ goto dispatch;
+ }
+
+ case 0x2: /* indirect table read from scriptVar -> write to stream */
+ {
+ /* Format: [cmd] [varIdx] [tableSlot] [table...] */
+ pSrc++;
+ uint8 varIdx = *pSrc++;
+ uint8 tableSlot = *pSrc++;
+ /* pSrc now points at the inline table. */
+ uint8 idxVal = _scriptVars[varIdx];
+ uint8 chosen = *(pSrc + idxVal);
+ uint8 target = *(pSrc + tableSlot);
+ *(pSrc + (uint16)target + 1) = chosen;
+ ch = _activeChannelPtr;
+ ch->_pSrc += (uint16)tableSlot + 4;
+ goto dispatch;
+ }
+
+ case 0x3: /* call function by address (near call in original) */
+ {
+ uint16 fnOffset = readWord_impl();
+ callFunction(fnOffset);
+ ch = _activeChannelPtr;
+ ch->_pSrc += 3;
+ goto dispatch;
+ }
+
+ case 0x4: /* nullsub_1 with byte arg */
+ {
+ /* "call near ptr aAsoundDriverAn+33h" - the target is a no-op. */
+ pSrc++;
+ /* (void)*pSrc; */
+ ch = _activeChannelPtr;
+ ch->_pSrc += 2;
+ goto dispatch;
+ }
+
+ case 0x5: /* advance _pSrc by 4 (from command byte) */
+ {
+ /* loc_10F55 is shared with case 1's epilogue: _pSrc += 4. */
+ ch = _activeChannelPtr;
+ ch->_pSrc += 4;
+ goto dispatch;
+ }
+
+ case 0x6: /* set word_124F2 (_tempoFineStep) */
+ {
+ pSrc++;
+ uint8 val = *pSrc;
+ _tempoFineStep = (uint16)val;
+ ch = _activeChannelPtr;
+ ch->_pSrc += 2;
+ goto dispatch;
+ }
+
+ case 0x7: /* set word_124F0 (_tempoCoarseStep) */
+ {
+ pSrc++;
+ uint8 val = *pSrc;
+ _tempoCoarseStep = (uint16)val;
+ ch = _activeChannelPtr;
+ ch->_pSrc += 2;
+ goto dispatch;
+ }
+
+ case 0x8: /* set word_124EE (_tempoPeriod), enable tick callback */
+ {
+ uint16 period = readWord_impl();
+ _tempoPeriod = period;
+ ch = _activeChannelPtr;
+ ch->_pSrc += 3;
+ _tempoEnabled = 1;
+ _tempoTickCounter = 1;
+ goto dispatch;
+ }
+
+ case 0x9: /* set word_124F4 (_tempoShift) */
+ {
+ pSrc++;
+ uint8 val = *pSrc;
+ _tempoShift = (uint16)val;
+ ch = _activeChannelPtr;
+ ch->_pSrc += 2;
+ goto dispatch;
+ }
+
+ default:
+ goto dispatch;
+ }
+ }
+
+ if (si == 0x30) {
+ /* ============================================================
+ * opcodes4 (group 3, 0xB_)
+ * Script-variable load (imm or var), store to stream, inc, dec.
+ * Each case increments pSrc itself, then sets _pSrc.
+ *
+ * Switch on di (0-4); di >= 5 falls through to return.
+ * ============================================================ */
+ switch (di) {
+
+ case 0x0: /* var[dst] = imm */
+ {
+ pSrc++;
+ uint8 dst = *pSrc++;
+ uint8 imm = *pSrc;
+ _scriptVars[dst] = imm;
+ ch = _activeChannelPtr;
+ ch->_pSrc += 3;
+ goto dispatch;
+ }
+
+ case 0x1: /* var[dst] = var[src] */
+ {
+ pSrc++;
+ uint8 dst = *pSrc++;
+ uint8 src = *pSrc;
+ _scriptVars[dst] = _scriptVars[src];
+ ch = _activeChannelPtr;
+ ch->_pSrc += 3;
+ goto dispatch;
+ }
+
+ case 0x2: /* stream[tableSlot+1] = var[src] */
+ {
+ /* asm: [bx+di+1] = cl, where bx=pSrc, di=tableSlot. */
+ pSrc++;
+ uint8 src = *pSrc++;
+ uint8 tableSlot = *pSrc;
+ *(pSrc + (uint16)tableSlot + 1) = _scriptVars[src];
+ ch = _activeChannelPtr;
+ ch->_pSrc += 3;
+ goto dispatch;
+ }
+
+ case 0x3: /* var[dst]++ */
+ {
+ pSrc++;
+ uint8 dst = *pSrc;
+ _scriptVars[dst]++;
+ ch = _activeChannelPtr;
+ ch->_pSrc += 2;
+ goto dispatch;
+ }
+
+ case 0x4: /* var[dst]-- */
+ {
+ pSrc++;
+ uint8 dst = *pSrc;
+ _scriptVars[dst]--;
+ ch = _activeChannelPtr;
+ ch->_pSrc += 2;
+ goto dispatch;
+ }
+
+ default:
+ goto dispatch;
+ }
+ }
+
+ if (si == 0x40) {
+ /* ============================================================
+ * opcodes5 (group 4, 0xC_)
+ * Script-variable ALU: add/sub/mul/div/rem/and/or/xor.
+ *
+ * Entry: inc pSrc, read dst (si), inc pSrc, read src (di).
+ * Then _pSrc += 3 (command + dst + src).
+ * 16 sub-opcodes (0-15).
+ *
+ * For sub-opcodes 0,2,4: src is an immediate (di from the byte).
+ * For sub-opcodes 1,3,5: src is _scriptVars[di].
+ * For 6-9: signed or unsigned division/remainder.
+ * For 10-15: bitwise AND/OR/XOR, imm or var.
+ * ============================================================ */
+ pSrc++;
+ uint8 dst = *pSrc++;
+ uint8 src = *pSrc; /* immediate value or var index */
+ ch = _activeChannelPtr;
+ ch->_pSrc += 3;
+
+ switch (di) {
+ case 0x0: _scriptVars[dst] += src; break;
+ case 0x1: _scriptVars[dst] += _scriptVars[src]; break;
+ case 0x2: _scriptVars[dst] -= src; break;
+ case 0x3: _scriptVars[dst] -= _scriptVars[src]; break;
+ case 0x4: /* mul ax=di, mul [si] -> al stored */
+ _scriptVars[dst] = (uint8)((uint16)src * (uint16)_scriptVars[dst]); break;
+ case 0x5:
+ _scriptVars[dst] = (uint8)((uint16)_scriptVars[src] * (uint16)_scriptVars[dst]); break;
+ case 0x6: /* signed idiv by imm -> quotient in al */
+ _scriptVars[dst] = (uint8)((int8)_scriptVars[dst] / (int8)src); break;
+ case 0x7: /* unsigned div by var -> quotient in al */
+ _scriptVars[dst] = _scriptVars[dst] / _scriptVars[src]; break;
+ case 0x8: /* signed idiv by imm -> remainder in dl (stored to dst) */
+ _scriptVars[dst] = (uint8)((int8)_scriptVars[dst] % (int8)src); break;
+ case 0x9: /* unsigned div by var -> remainder in ah (stored to dst) */
+ _scriptVars[dst] = _scriptVars[dst] % _scriptVars[src]; break;
+ case 0xA: _scriptVars[dst] &= src; break;
+ case 0xB: _scriptVars[dst] &= _scriptVars[src]; break;
+ case 0xC: _scriptVars[dst] |= src; break;
+ case 0xD: _scriptVars[dst] |= _scriptVars[src]; break;
+ case 0xE: _scriptVars[dst] ^= src; break;
+ case 0xF: _scriptVars[dst] ^= _scriptVars[src]; break;
+ default: break;
+ }
+ goto dispatch;
+ }
+
+ if (si == 0x50) {
+ /* ============================================================
+ * opcodes6 (group 5, 0xD_)
+ * Conditional branch: compare var[si] vs immediate (di as imm byte).
+ *
+ * Format: [cmd] [varIdx] [imm] [addrLo] [addrHi]
+ * Entry: inc pSrc, read varIdx (si reg), inc pSrc, read imm (di reg).
+ * Comparison: var[varIdx] vs imm.
+ *
+ * If condition met: call asound_readWord (reads addrLo/addrHi
+ * from current pSrc position), set _pSrc = &_soundData[addr].
+ * If not met: _pSrc += 5 (command+varIdx+imm+addr word = 5 bytes).
+ *
+ * var_2 is used as a flag: 0 = branch taken, 1 = not taken.
+ * (Confusingly, var_2 = 1 means "taken" in opcodes7 but
+ * 0 means "taken" in opcodes6 - see def_11292 / def_11360 difference.)
+ *
+ * opcodes6: var_2=1 -> taken (call readWord, set pSrc),
+ * var_2=0 -> not taken (_pSrc += 5).
+ * ============================================================ */
+ pSrc++;
+ uint8 varIdx = *pSrc++;
+ uint8 imm = *pSrc;
+ uint8 vval = _scriptVars[varIdx];
+ bool taken = false;
+
+ switch (di) {
+ case 0x0: taken = ((uint16)vval == (uint16)imm); break; /* == */
+ case 0x1: taken = ((uint16)vval != (uint16)imm); break; /* != */
+ case 0x2: taken = ((int16)(uint16)vval >= (int16)(uint16)imm); break; /* jge -> taken if >= */
+ case 0x3: taken = ((int16)(uint16)vval <= (int16)(uint16)imm); break; /* jle -> taken if <= */
+ case 0x4: taken = (_scriptVars[varIdx] != _scriptVars[imm]); break; /* jnz after cmp [di],[si] */
+ case 0x5: taken = (_scriptVars[varIdx] == _scriptVars[imm]); break; /* jz after cmp [di],[si] */
+ case 0x6: taken = (_scriptVars[imm] <= _scriptVars[varIdx]); break; /* jbe -> [di]<=[si] taken */
+ case 0x7: taken = (_scriptVars[imm] >= _scriptVars[varIdx]); break; /* jnb -> [di]>=[si] taken */
+ default: break;
+ }
+
+ ch = _activeChannelPtr;
+ if (taken) {
+ ch->_pSrc = &_soundData[readWord_impl()];
+ } else {
+ ch->_pSrc += 5;
+ }
+ goto dispatch;
+ }
+
+ if (si == 0x60) {
+ /* ============================================================
+ * opcodes7 (group 6, 0xE_)
+ * Conditional branch: compare var[si] vs var[di] (both scriptVars).
+ *
+ * Format: [cmd] [varIdxA] [varIdxB] [addrLo] [addrHi]
+ * Entry: inc pSrc, read varIdxA (si), inc pSrc, read varIdxB (di).
+ * var_2 = 0 initially.
+ *
+ * If condition met: var_2 = 1 -> branch taken:
+ * _pSrc = pSrc + 5; _branchTargetPtr = pSrc + 5;
+ * call readWord -> _pSrc = &_soundData[addr].
+ * If not met (var_2 = 0): _pSrc += 5 (skip condition + word).
+ *
+ * Note: unlike opcodes6, opcodes7 DOES save a branch-target
+ * (_branchTargetPtr = _pSrc + 5) on the taken path.
+ * ============================================================ */
+ pSrc++;
+ uint8 idxA = *pSrc++;
+ uint8 idxB = *pSrc;
+ uint8 va = _scriptVars[idxA];
+ uint8 vb = (uint8)idxB; /* di byte used as an immediate in some cases... */
+
+ /* Actually in opcodes7 the layout is var vs var:
+ * si = varIdxA, di = varIdxB (both are variable indices). */
+ vb = _scriptVars[idxB];
+
+ bool taken = false;
+ switch (di & 0x07) {
+ case 0x0: taken = ((uint16)va != (uint16)vb); break; /* jnz after cmp ax,di (case 0: jz -> NOT taken if ==; var_2 stays 0; but then def path: var_2==0 -> skip. Wait - let me re-read.) */
+ /* Re-reading loc_112F0: cmp ax,di; jz loc_11352 (-> var_2=1=taken).
+ * So case 0: taken = (va == vb). */
+ default: break;
+ }
+
+ /* Actually re-reading carefully:
+ * case 0 (loc_112F0): cmp ax,di; jz -> loc_11352 (var_2=1, taken)
+ * else -> loc_112FA (ax=0, var_2=0, not taken)
+ * case 1 (loc_11302): cmp ax,di; jz -> loc_1130A -> (jz loc_112FA, not taken)
+ * else -> loc_11284 (var_2=1, taken)
+ * -> case 1: taken = (va != vb)
+ * case 2 (loc_1130E): jge -> loc_112FA (not taken); else loc_11284 (taken)
+ * -> taken = (va < vb) (signed)
+ * case 3 (loc_1131A): jle -> not taken; else taken
+ * -> taken = (va > vb) (signed)
+ * case 4 (loc_11326): cmp [di],al; jnz -> loc_112FA (not taken); else loc_11284 (taken)
+ * -> taken = (_scriptVars[idxB] == va) (already same as case 0 with vars swapped)
+ * case 5 (loc_11332): cmp [di],al; jz->loc_1130A (not taken if ==, taken if !=)
+ * -> taken = (_scriptVars[idxB] != va)
+ * case 6 (loc_1133C): jbe -> not taken; else taken -> taken = (_scriptVars[idxB] > va)
+ * case 7 (loc_11348): jnb -> not taken; else taken -> taken = (_scriptVars[idxB] < va)
+ */
+ switch (di) {
+ case 0x0: taken = (va == vb); break;
+ case 0x1: taken = (va != vb); break;
+ case 0x2: taken = ((int8)va < (int8)vb); break;
+ case 0x3: taken = ((int8)va > (int8)vb); break;
+ case 0x4: taken = (vb == va); break;
+ case 0x5: taken = (vb != va); break;
+ case 0x6: taken = (vb > va); break;
+ case 0x7: taken = (vb < va); break;
+ default: break;
+ }
+
+ ch = _activeChannelPtr;
+ if (taken) {
+ /* Save return target (pSrc+5 from the command byte). */
+ ch->_branchTargetPtr = ch->_pSrc + 5;
+ ch->_pSrc = &_soundData[readWord_impl()];
+ } else {
+ ch->_pSrc += 5;
+ }
+ goto dispatch;
+ }
+
+ /* Unknown group: skip. */
+ goto dispatch;
+ }
+
+note_event:
+ {
+ /* ---- Note event: [note][duration] ---- */
+ ch = _activeChannelPtr;
+ pSrc = ch->_pSrc;
+ ch->_note = *pSrc;
+ pSrc++;
+ ch->_activeCount = *pSrc;
+ pSrc++;
+ ch->_pSrc += 2;
+
+ ch = _activeChannelPtr;
+ if (ch->_note == 0 || ch->_activeCount == 0) {
+ updateOctave();
+ goto post_keyon;
+ }
+
+ /* ---- Key-on ---- */
+ ch = _activeChannelPtr;
+ if (ch->_durationOverride != 0)
+ ch->_keyOnDelay = ch->_durationOverride;
+ else
+ ch->_keyOnDelay = ch->_activeCount - ch->_noteOffset;
+ noteOn();
+ }
+
+post_keyon:
+ {
+ ch = _activeChannelPtr;
+
+ /* ---- Arpeggio counter (field_13 / _arpCounterReload) ---- */
+ if (ch->_arpCounterReload != 0) {
+ /* Decrement the arpeggio period counter (field_C / _arpPeriodCounter). */
+ ch->_arpPeriodCounter--;
+ ch = _activeChannelPtr;
+ if (ch->_arpPeriodCounter == 0) {
+ /* Reload from field_12 (_arpPeriodReload). */
+ ch->_arpPeriodCounter = ch->_arpPeriodReload;
+ /* Call sub_117E8 (writeArpeggio - writes the arpeggio frequency). */
+ writeArpeggio();
+ }
+ ch = _activeChannelPtr;
+ /* Decrement the repeat counter unless it is the infinite sentinel 0xFF. */
+ if (ch->_arpCounterReload != 0xFF)
+ ch->_arpCounterReload--;
+ }
+
+ /* ---- Write-volume pending (field_11 / _writeVolumePending) ---- */
+ ch = _activeChannelPtr;
+ if (ch->_writeVolumePending != 0) {
+ /* sub_11856 was already called by writeArpeggio above (or this is
+ * a standalone field_11 set via opcode 8). Clear the flag. */
+ writeArpeggio();
+ ch = _activeChannelPtr;
+ ch->_writeVolumePending = 0;
+ }
+
+ /* ---- Fade / volume step ---- */
+ ch = _activeChannelPtr;
+ if (ch->_fadePeriodCounter != 0) {
+ ch->_fadePeriodCounter--;
+ ch = _activeChannelPtr;
+ if (ch->_fadePeriodCounter == 0) {
+ ch->_fadePeriodCounter = ch->_fadePeriodReload;
+ ch = _activeChannelPtr;
+ if (ch->_volumeFadeStep != 0) {
+ if (ch->_pendingStop != 0) {
+ /* Pending-stop fade: step velocity and volume down. */
+ if (ch->_velocity > 0)
+ ch->_velocity += ch->_volumeFadeStep;
+ ch = _activeChannelPtr;
+ if (ch->_volume != 0)
+ ch->_volume += ch->_volumeFadeStep;
+ } else {
+ /* Normal fade: step velocity, clamp to [0, 0x7F]. */
+ if ((int8)ch->_volumeFadeStep > 0) {
+ ch->_velocity += ch->_volumeFadeStep;
+ ch = _activeChannelPtr;
+ if ((uint16)ch->_velocity > 0x7F)
+ ch->_velocity = 0x7F;
+ } else {
+ ch->_velocity += ch->_volumeFadeStep;
+ ch = _activeChannelPtr;
+ if ((int8)ch->_velocity < 0)
+ ch->_velocity = 0;
+ }
+ }
+ volDirty = true; /* byte_16A0A = 1 */
+ }
+ }
+ }
+
+ /* ---- Vibrato ---- */
+ ch = _activeChannelPtr;
+ if (ch->_vibPeriodCounter != 0) {
+ ch->_vibPeriodCounter--;
+ ch = _activeChannelPtr;
+ if (ch->_vibPeriodCounter == 0) {
+ ch->_vibPeriodCounter = ch->_vibPeriodReload;
+ ch = _activeChannelPtr;
+
+ if ((int8)ch->_vibratoDepth > 0) {
+ /* Positive vibrato: ceiling at 0x7F. */
+ uint8 sum = ch->_vibratoDepth + ch->_patchAttenuation;
+ if (sum > 0x7F) {
+ if (ch->_vibratoMode == 0xFF) {
+ /* One-shot: clamp and stop. */
+ ch->_vibratoDepth = 0;
+ ch->_patchAttenuation = 0x7F;
+ } else if (sum == 0x80 && ch->_vibratoDepth != 1) {
+ /* Soft bounce at 0x80: patchAtten = 0x7F - vibratoDepth. */
+ ch->_patchAttenuation = 0x7F - ch->_vibratoDepth;
+ } else {
+ ch->_vibratoDepth = (uint8)(-(int8)ch->_vibratoDepth);
+ }
+ }
+ ch = _activeChannelPtr;
+ ch->_patchAttenuation += ch->_vibratoDepth;
+ volDirty = true;
+
+ } else if ((int8)ch->_vibratoDepth < 0) {
+ /* Negative vibrato: floor at 0. */
+ uint8 sum = ch->_vibratoDepth + ch->_patchAttenuation;
+ /* Note: sum is uint8 wrapping, but the asm uses "or al,al; jge"
+ * treating the result as signed. */
+ if ((int8)sum < 0) {
+ if (ch->_vibratoMode == 0xFF) {
+ ch->_vibratoDepth = 0;
+ ch->_patchAttenuation = 0;
+ } else if (sum == 0xFF && ch->_vibratoDepth != 0xFF) {
+ /* Soft bounce: patchAtten = neg(vibratoDepth). */
+ ch->_patchAttenuation = (uint8)(-(int8)ch->_vibratoDepth);
+ } else {
+ ch->_vibratoDepth = (uint8)(-(int8)ch->_vibratoDepth);
+ }
+ }
+ ch = _activeChannelPtr;
+ ch->_patchAttenuation += ch->_vibratoDepth;
+ volDirty = true;
+ }
+ /* vibratoDepth == 0: nothing to do. */
+ }
+ }
+
+ if (volDirty)
+ writeVolume();
+ }
+
+ ++_activeChannelNumber;
+}
+
+void ASound::playSound(int offset) {
+ findFreeChannelFull(loadData(offset));
+}
+
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/asound.h b/engines/mads/madsv2/forest/asound.h
new file mode 100644
index 00000000000..32fefa08461
--- /dev/null
+++ b/engines/mads/madsv2/forest/asound.h
@@ -0,0 +1,649 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ASOUND_H
+#define MADS_FOREST_ASOUND_H
+
+#include "common/mutex.h"
+#include "common/queue.h"
+#include "common/util.h"
+#include "mads/core/sound_manager.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+
+#define ADLIB_CHANNEL_COUNT 9
+
+struct AdlibChannel {
+ static bool _isDisabled;
+
+ // ---- byte fields (offsets 0x00 - 0x13) --------------------------------
+
+ uint8 _activeCount = 0; // 0x00 duration tick countdown; 0 = channel idle
+ uint8 _pitchBend = 0; // 0x01 signed pitch-bend offset applied by writePitchBend
+ uint8 _volumeFadeStep = 0; // 0x02 signed per-period volume/velocity delta (0xFF = fade out)
+ uint8 _vibratoDepth = 0; // 0x03 signed LFO depth; negated each period to oscillate
+ uint8 _note = 0; // 0x04 MIDI note number for current event
+ uint8 _sampleIndex = 0; // 0x05 index into _samples[] selecting the OPL patch
+ uint8 _volume = 0; // 0x06 channel volume (0-127)
+ uint8 _noteOffset = 0; // 0x07 subtracted from _activeCount to shorten note duration
+ uint8 _durationOverride = 0; // 0x08 when non-zero, overrides the stream's duration byte
+ uint8 _keyOnDelay = 0; // 0x09 countdown before the OPL key-on bit is cleared (gate time)
+ uint8 _fadePeriodCounter = 0; // 0x0A counts down to 0 before applying _volumeFadeStep
+ uint8 _fadePeriodReload = 0; // 0x0B reload value for _fadePeriodCounter
+ uint8 _arpPeriodCounter = 0; // 0x0C arpeggio tick counter (reloaded from _arpPeriodReload)
+ uint8 _vibPeriodCounter = 0; // 0x0D LFO tick counter; when it reaches 0 a vibrato step fires
+ uint8 _vibPeriodReload = 0; // 0x0E reload value for _vibPeriodCounter
+ uint8 _patchAttenuation = 0; // 0x0F per-note attenuation offset added on top of the patch TL
+ uint8 _velocity = 0; // 0x10 note velocity (0-127); used together with _volume for TL
+ uint8 _writeVolumePending = 0; // 0x11 non-zero -> call sub_11856 (secondary freq write) this tick
+ uint8 _arpPeriodReload = 0; // 0x12 arpeggio period reload value (set by opcode 9)
+ uint8 _arpCounterReload = 0; // 0x13 arpeggio counter reload (decremented; 0xFF = infinite)
+
+ // ---- pointer fields (offsets 0x14 - 0x1F, word-sized in original) ----
+
+ byte *_loopStartPtr = nullptr; // 0x14 start of the current loop body
+ byte *_pSrc = nullptr; // 0x16 current read pointer into the sound-data stream
+ byte *_innerLoopPtr = nullptr; // 0x18 inner-loop restart address
+ byte *_outerLoopPtr = nullptr; // 0x1A outer-loop restart address
+ byte *_soundData = nullptr; // 0x1C base address of this channel's sound-data block
+ byte *_branchTargetPtr = nullptr; // 0x1E target of the most recent branch/jump opcode
+
+ // ---- word counter fields (offsets 0x20 - 0x29) ----------------------
+
+ uint16 _innerLoopCount = 0; // 0x20 remaining inner-loop iterations (0 = infinite until opcode)
+ uint16 _outerLoopCount = 0; // 0x22 remaining outer-loop iterations (0 = infinite until opcode)
+ uint16 _noiseFreqMask = 0; // 0x24 AND mask applied to the random number in noise mode
+ uint16 _freqAccum = 0; // 0x26 frequency sweep accumulator (base frequency + swept offset)
+ uint16 _freqStep = 0; // 0x28 per-tick increment added to _freqAccum during a sweep
+
+ // ---- sweep / pause state (offsets 0x2A - 0x2D) ----------------------
+
+ // 0x2A-0x2B Last computed OPL total-level bytes written by writeVolume.
+ // lo byte (0x2A) = carrier TL nibble; hi byte (0x2B) = modulator TL nibble.
+ // Written at the end of asound_writeVolume so that command7 (resume) can
+ // restore operator levels without a full recalculation.
+ uint8 _cachedCarrierTL = 0; // 0x2A cached carrier total-level (6-bit, 0 = loudest)
+ uint8 _savedFreqSweep = 0; // 0x2B copy of _freqSweepCounter saved by command6 (pause)
+ uint8 _freqSweepCounter = 0; // 0x2C countdown for frequency-sweep ticks; 0 = sweep done
+ uint8 _savedSweepCounter = 0; // 0x2D second save slot: _freqSweepCounter is mirrored here
+ // by command6/7 so command7 can restore the live value
+
+// ---- tuning / control (offsets 0x2E - 0x31) ------------------------
+
+ uint8 _transpose = 0; // 0x2E semitone offset added when looking up _semitoneFreqTable
+ uint8 _octaveTranspose = 0; // 0x2F octave shift: added to _note before octave calculation
+ uint8 _pendingStop = 0; // 0x30 0xFF = channel is fading out and will go idle when silent
+ uint8 _vibratoMode = 0; // 0x31 0xFF = one-shot vibrato (clamp & stop); else = continuous
+
+ /**
+ * Zeroes the "live" fields of one channel without touching the
+ * loop/sound-data pointers (those are handled separately by load).
+ */
+ void reset();
+
+ /**
+ * Clears the entire channel struct, then initialises all loop/source
+ * pointers to the supplied sound-data address, sets _patchAttenuation to
+ * 0x40 (maximum, silent), and marks the channel active (_activeCount = 1).
+ */
+ void load(byte *soundData);
+
+ /**
+ * Redirects _loopStartPtr and _pSrc to the null/silence stream and arms a
+ * one-step volume fade (_volumeFadeStep = 0xFF, _fadePeriodReload/Counter = 1)
+ * so the channel fades out gracefully over the next tick.
+ */
+ void setPtr2(byte *ptr);
+
+ /**
+ * Marks the channel pending-stop (_pendingStop = 0xFF) and redirects
+ * _soundData to the null/silence stream. Unlike setPtr2 this does not
+ * touch _volumeFadeStep; the channel fades naturally via processChannelFade.
+ */
+ void enable();
+
+ /**
+ * Called every frame for each channel. When _pendingStop is set, waits
+ * until both _velocity and _volume are zero before marking the channel idle
+ * (_activeCount = 0); otherwise applies _volumeFadeStep to velocity/volume
+ * each _fadePeriodReload ticks and clamps the result to [0, 0x7F].
+ */
+ void processChannelFade();
+};
+
+// ---------------------------------------------------------------------------
+// AdlibSample (unchanged from Return of the Phantom, 0x16 bytes)
+// ---------------------------------------------------------------------------
+struct AdlibSample {
+ uint8 _attackRate = 0;
+ uint8 _decayRate = 0;
+ uint8 _sustainLevel = 0;
+ uint8 _releaseRate = 0;
+ uint8 _egTyp = 0;
+ uint8 _ksr = 0;
+ uint8 _totalLevel = 0;
+ uint8 _scalingLevel = 0;
+ uint8 _waveformSelect = 0;
+ uint8 _freqMultiple = 0;
+ uint8 _feedback = 0;
+ uint8 _ampMod = 0;
+ uint8 _vib = 0;
+ uint8 _alg = 0;
+ uint8 _freqSweepInit = 0; // initial _freqSweepCounter value; 0 = immediate key-on
+ uint8 _reserved = 0;
+ uint16 _freqMask = 0; // loaded into channel _noiseFreqMask
+ uint16 _freqBase = 0; // loaded into channel _freqAccum
+ uint16 _outerLoopPtr = 0; // loaded into channel _freqStep
+
+ AdlibSample() {
+ }
+ AdlibSample(Common::SeekableReadStream &s);
+};
+
+// ---------------------------------------------------------------------------
+// ASound - Dragonsphere Adlib sound driver base class
+//
+// Command dispatch table layout (from off_11A14 / off_11A26 / off_11A2E /
+// funcs_12251 / off_11A64 in the disassembly):
+//
+// Table 1 off_11A14 commands 0- 8 (max=8, base=0, 9 entries)
+// Table 2 off_11A26 commands 16-19 (max=0x13, base=0x10, 4 entries)
+// command16 = background-music dispatcher (calls command18)
+// command17 = play specific piece (loads 7 channels direct)
+// command18 = re-entrant music launcher (reads word_12370 to pick a sub-command)
+// command19 = no-op (asound_command98)
+// Table 3 off_11A2E commands 24-32 (max=0x20, base=0x18, 9 entries)
+// Table 4 funcs_12251 commands 32-49 (max=0x31, base=0x20, 18 entries)
+// Includes asound_command32-48 (music pieces / SFX loaders)
+// and asound_command98 (no-op) in the last slot.
+// Table 5 off_11A64 commands 64-101 (max=0x65, base=0x40, 38 entries)
+// Includes asound_command64-101 (single-shot SFX loaders via
+// findFreeChannel / findFreeChannelFull) and two no-ops.
+//
+// The driver also exposes:
+// asound_command90 / 91 - two-voice SFX (findFreeChannelFull x2)
+// asound_command95 - four-voice music piece (findFreeChannel x4)
+// sub_11F98 - two-voice SFX (findFreeChannelFull x2)
+//
+// word_12370 tracks the "current music index" used by command18 to select
+// which music-piece loader to call.
+// ---------------------------------------------------------------------------
+class ASound : public SoundDriver {
+protected:
+ /** Member-function pointer type for deferred sound-loader callbacks. */
+ typedef void (ASound::*CallbackFunction)();
+
+private:
+ // ---- callback / tick state ------------------------------------------
+ uint16 _callbackCounter = 0; // per-tick countdown
+ uint16 _callbackPeriod = 0; // reload value; 0 = callback disabled
+ // Pointer to the deferred sound-loader called when the
+ // counter fires (stored as uint16 in the original; typed as a member
+ // function pointer in the C++ port).
+ CallbackFunction _callbackFnPtr = nullptr;
+
+ // ---- active-channel context (set by pollAllChannels) ----------------
+ AdlibChannel *_activeChannelPtr = nullptr;
+ uint8 _activeChannelNumber = 0;
+ uint16 _activeChannelReg = 0; // 0xA0+ch register for the active channel
+ uint16 _currentOpBase = 0; // operator register base for the active channel
+
+ // ---- per-frame working state ----------------------------------------
+ AdlibSample *_samplePtr = nullptr; // patch being loaded/written
+ byte *pSrc = nullptr; // current read pointer (mirrors channel _pSrc)
+ int16 _pollResult = 0;
+ int16 _resultFlag = 0;
+ uint16 _randomSeed = 0x4D2;
+
+ // ---- driver-wide flags ----------------------------------------------
+ uint16 _isDisabled = 0; // non-zero while the engine is paused (command6)
+ uint8 _findChannelMode = 0; // 0=full search, 1=ch0-5 only, 2=ch6-8 then pending
+
+ // ---- per-channel sweep shadows (for channel 5 special-casing) -------
+ // Not present as separate globals in Dragonsphere; the channel
+ // struct fields _savedFreqSweep / _savedSweepCounter handle this.
+
+ // ---- misc globals ---------------------------------------------------
+ uint8 _anySweepActive = 0; // set to 1 if any channel has _freqSweepCounter > 0
+ int _frameNumber2 = 0; // secondary frame counter incremented every update
+
+ // ---- script / sequencer registers -----------------------------------
+ uint8 _scriptVars[32] = {}; // byte_16A10: 32 general-purpose script registers
+
+ // ---- music-index tracker (word_12370) --------------------------------
+ // Tracks which music piece was last launched by command18.
+ uint16 _musicIndex = 0;
+
+ // ---- tempo / sequencer state (from opcodes3 group 2 handlers) --------
+ uint8 _musicOnlyFlag = 0; // byte_12393: 1=music-only check, 0=all channels
+ uint16 _tempoFineStep = 0; // word_124F2: fine tempo step (opcode A6)
+ uint16 _tempoCoarseStep = 0; // word_124F0: coarse tempo step (opcode A7)
+ uint16 _tempoPeriod = 0; // word_124EE: tempo period in ticks (opcode A8)
+ uint8 _tempoEnabled = 0; // non-zero when tempo tick is active (opcode A8)
+ uint16 _tempoTickCounter = 0; // countdown for tempo callback
+ uint16 _tempoShift = 0; // word_124F4: tempo shift (opcode A9)
+
+ // =========================================================================
+ // Private helpers
+ // =========================================================================
+
+ /** Timer callback entry point; calls update(). */
+ void onTimer();
+
+ /** Zeros _callbackFnPtr, _callbackCounter, and _callbackPeriod. */
+ void clearCallback();
+ void resetCallback() {
+ clearCallback();
+ }
+
+ /**
+ * Forces one OPL operator to maximum attenuation (total-level = 0x3F)
+ * while preserving its upper KSL bits. 'portIndex' is the register index
+ * into _adlibPorts (i.e. the 0x40-range operator register).
+ * Used by command6 to mute all operator pairs during a pause.
+ */
+ void adlib_channelOff(uint8 portIndex);
+
+ /**
+ * Computes and writes the total-level registers for the active channel
+ * (asound_writeVolume).
+ *
+ * Two top-level paths depending on the _alg field of the first sample:
+ * _alg == 0 (FM): both operators contribute; loop twice writing
+ * VOICE_SLOTS[ch][0] then VOICE_SLOTS[ch][1].
+ * _alg != 0 (additive): only the carrier (slot 1) carries volume.
+ *
+ * Within each pass, two inner paths based on OPL version:
+ * < 0x18 (OPL2): TL = clamp(0x3F - var_2, 0, 0x3F).
+ * >= 0x18 (OPL3): patch-attenuation-aware mapping using
+ * PATCH_ATTEN_TO_TL and VOL_VEL_TO_ATTEN_STEP tables;
+ * writes two registers (offset 0 and offset 2).
+ *
+ * Caches the two written TL bytes in _cachedCarrierTL / _savedFreqSweep
+ * so command7 can restore levels without a full recalculation.
+ */
+ void writeVolume();
+
+ /**
+ * Derives the OPL F-number and block (octave) from _note, _octaveTranspose,
+ * and _transpose using _semitoneFreqTable, then writes registers 0xA0+ch
+ * and 0xB0+ch (with key-on bit set).
+ */
+ void writeFrequency();
+
+ /**
+ * Applies _pitchBend as a signed offset to the already-computed frequency
+ * registers without a full note recalculation.
+ */
+ void writePitchBend();
+
+ /**
+ * Arpeggio frequency write (sub_11856).
+ * Called from pollActiveChannel when _writeVolumePending (field_11) is set.
+ * Computes a modified frequency from _note + _octaveTranspose + field_11 - 1
+ * and writes it to the OPL registers, preserving the key-on bit.
+ */
+ void writeArpeggio();
+
+ /**
+ * Clears the key-on bit (bit 5) of the 0xB0+ch register, silencing the
+ * note while preserving pitch. Called during _keyOnDelay countdown.
+ */
+ void updateOctave();
+
+ /**
+ * Arms the frequency sweep counter from the sample definition, then - if
+ * _freqSweepCounter is zero - immediately triggers the note by writing
+ * volume and frequency registers and setting the key-on bit.
+ */
+ void noteOn();
+
+ /**
+ * Writes all OPL operator registers for the patch pointed to by _samplePtr,
+ * using _currentOpBase as the operator base. Covers ADSR, KSL/TL,
+ * feedback/algorithm, AM/VIB flags, and waveform-select registers.
+ */
+ void writeSampleRegs();
+
+ /**
+ * Loads all OPL registers for the patch assigned to the active channel,
+ * covering both modulator and carrier operators, and sets up the channel's
+ * sweep/frequency state from the AdlibSample definition.
+ */
+ void loadSample();
+
+ /**
+ * Main per-frame update: increments frame counters, polls all channels,
+ * fires the tick callback, calls updateAllChannels, then runs the per-channel
+ * frequency-sweep tick for all 9 voices.
+ */
+ void update();
+
+ /**
+ * Per-channel frequency-sweep tick for channel 'channelIndex' (0-based).
+ * When _freqSweepCounter > 0: adds _freqStep to _freqAccum, decrements the
+ * counter, and - when it reaches zero - zeroes the voice's frequency registers.
+ * Sets _anySweepActive when the counter is still non-zero.
+ */
+ void update1(int channelIndex);
+
+ /**
+ * Writes a frequency value directly to the OPL registers for 'voice'.
+ * The high byte selects the block/octave; the low byte is the F-number LSB.
+ */
+ void setFrequency(uint8 voice, uint16 freq);
+
+ /**
+ * Noise-channel inner tick: picks a random frequency offset masked by
+ * _noiseFreqMask, adds _freqAccum, and writes the result to the voice
+ * frequency registers.
+ */
+ void noise_inner(int channelIndex);
+
+ /**
+ * Calls processChannelFade for all 9 channels each frame.
+ */
+ void updateAllChannels();
+
+ /**
+ * Advances pSrc by one, reads two bytes little-endian, and returns the word.
+ * Used by the bytecode opcodes that take 16-bit operands.
+ */
+ uint16 readWord_impl();
+
+ /**
+ * Deferred-callback tick: decrements _callbackCounter; when it reaches zero,
+ * reloads it from _callbackPeriod and calls _callbackFnPtr (if non-null),
+ * then clears _callbackFnPtr so it fires exactly once.
+ */
+ void tickCallback();
+
+protected:
+ // ---- nine AdlibChannel instances ------------------------------------
+ AdlibChannel _channel0, _channel1, _channel2;
+ AdlibChannel _channel3, _channel4, _channel5;
+ AdlibChannel _channel6, _channel7, _channel8;
+ AdlibChannel *_channels[ADLIB_CHANNEL_COUNT] = {
+ &_channel0, &_channel1, &_channel2,
+ &_channel3, &_channel4, &_channel5,
+ &_channel6, &_channel7, &_channel8
+ };
+
+ uint8 _adlibPorts[0x100] = { 0 };
+ Common::Array<AdlibSample> _samples;
+
+protected:
+ // =========================================================================
+ // Protected helpers (used by ASound1âASound9)
+ // =========================================================================
+
+ /**
+ * Checks whether any of channels 0-6 (or 0-8 when _musicOnlyFlag is clear)
+ * have a non-zero _activeCount. Returns non-zero if sound is playing.
+ * This is 'sub_1061A' in the disassembly.
+ */
+ int isMusicChannelsActive();
+
+ /**
+ * Like isMusicChannelsActive but scans all 9 channels unconditionally
+ * (clears the ch0-6-only flag first). This is 'sub_1064E'.
+ */
+ int isAnyChannelActive();
+
+ /**
+ * Schedule fn as the next deferred-load callback.
+ * Does NOT touch _callbackCounter or _callbackPeriod â those are preserved
+ * from the previous loader so the callback fires on the right beat.
+ * Cast the derived-class member-function pointer with reinterpret_cast.
+ */
+ void scheduleCallback(CallbackFunction fn) { _callbackFnPtr = fn; }
+
+ /**
+ * Arm the periodic timer and clear any pending callback pointer.
+ * Call at the head of every immediate-load function (symmetric counter/period).
+ */
+ void resetCallbackTimer(uint16 period) {
+ _callbackFnPtr = nullptr;
+ _callbackCounter = period;
+ _callbackPeriod = period;
+ }
+
+ /**
+ * Arm the periodic timer with separate counter and period values.
+ * Used by command44 which sets counter=0x60 but period=0xE0.
+ */
+ void resetCallbackTimerEx(uint16 counter, uint16 period) {
+ _callbackFnPtr = nullptr;
+ _callbackCounter = counter;
+ _callbackPeriod = period;
+ }
+
+ /** Set the music-piece index (word_12370) read by command18. */
+ void setMusicIndex(uint16 idx) { _musicIndex = idx; }
+ /** Read the current music-piece index. */
+ uint16 getMusicIndex() const { return _musicIndex; }
+
+ /** Write one script-variable register (byte_16A10[idx]). */
+ void setScriptVar(int idx, uint8 val) { _scriptVars[idx] = val; }
+ /**
+ * Writes (reg, value) to the OPL chip and updates the _adlibPorts shadow
+ * array so subsequent reads return the last-written value.
+ */
+ void write(uint8 reg, uint8 value);
+
+ /** Updates and returns _randomSeed using a simple linear-feedback shift. */
+ uint16 getRandomNumber();
+
+ /**
+ * Restores one OPL operator by re-writing the value already stored in the
+ * _adlibPorts shadow array. command7 uses this to resume playback after
+ * a command6 pause without recalculating any TL values.
+ * 'portIndex' is the operator register index into _adlibPorts.
+ */
+ void adlib_channelOn(uint8 portIndex);
+
+ /** Sets _pollResult and _resultFlag to indicate that sound is playing. */
+ void signalSoundPlaying();
+
+ /**
+ * Iterates over all 9 channels, sets _activeChannelPtr / _activeChannelNumber,
+ * and calls pollActiveChannel for each one.
+ */
+ void pollAllChannels();
+
+ /**
+ * Per-channel bytecode interpreter, called once per frame per active channel.
+ *
+ * Sound data is a sequence of (note, duration) byte pairs plus command bytes
+ * with the high bit set (0x80-0xFF). The upper nibble of a command byte
+ * (after masking out the high bit) selects one of seven opcode groups:
+ *
+ * 0x0_ -> opcodes1 (patch/velocity/volume/vibrato/transpose/arpeggio)
+ * 0x1_ -> opcodes2 (inner/outer loop control, restart, branch/call)
+ * 0x2_ -> opcodes3 (tempo, script-variable arithmetic, call-by-address)
+ * 0x3_ -> opcodes4 (script-variable load/store/copy/inc/dec)
+ * 0x4_ -> opcodes5 (script-variable ALU: add/sub/mul/div with imm or var)
+ * 0x5_ -> opcodes6 (extended: random-range, indexed table read/write)
+ * 0x6_ -> opcodes7 (driver-level calls: command dispatch, etc.)
+ *
+ * The lower nibble is passed as the sub-opcode to each group handler.
+ * Note bytes (high bit clear) consume one duration tick per call.
+ */
+ void pollActiveChannel();
+
+ /** Returns true if the sound data block at 'ptr' is already playing. */
+ bool isSoundActive(byte *ptr) const;
+
+ /**
+ * Scans channels 0-6 for an empty slot (_activeCount == 0) and calls
+ * load() on the first one found. Falls through to findFreeChannelFull
+ * for channels 6-8 when _findChannelMode != 1.
+ */
+ void findFreeChannel(byte *soundData);
+
+ /**
+ * Extends the search to channels 7-8, then checks for pending-stop
+ * channels (which can be pre-empted), working in reverse priority order
+ * (ch8, ch7, ch6 ... ch0).
+ */
+ void findFreeChannelFull(byte *soundData);
+
+ /** Returns a pointer to the sound data at the given offset. */
+ byte *loadData(int offset) {
+ return &_soundData[offset];
+ }
+
+protected:
+ // =========================================================================
+ // Core commands (0-8) - identical in purpose to Return of the Phantom
+ // =========================================================================
+
+ /**
+ * command0: Full hardware reset.
+ * 1. Reset all 9 channels.
+ * 2. Mute all operator TL registers (0x40-0x55) to 0x3F.
+ * 3. Zero remaining operator registers (0x60-0xFF and 0x01-0x3F).
+ * 4. Write Waveform Select Enable (register 0x01 = 0x20).
+ * 5. Reset the tick callback.
+ */
+ int command0();
+
+ /**
+ * command1: Fade out all channels.
+ * Calls command3 (fade music channels 0-6) then command5 (fade SFX 7-8).
+ */
+ int command1();
+
+ /**
+ * command2: Fade out music channels 0-6.
+ * Calls AdlibChannel::setPtr2 on each, redirecting to the null stream
+ * and arming a one-step fade.
+ */
+ int command2();
+
+ /**
+ * command3: Fade out music channels 0-6 with pending-stop.
+ * Calls AdlibChannel::enable on channels 0-6.
+ */
+ int command3();
+
+ /**
+ * command4: Fade out SFX channels 7-8.
+ * Calls AdlibChannel::setPtr2 on channels 7 and 8.
+ */
+ int command4();
+
+ /**
+ * command5: Stop SFX channels 7-8 with pending-stop flag.
+ * Calls AdlibChannel::enable on channels 7 and 8, letting each channel
+ * finish its current OPL envelope before going idle.
+ */
+ int command5();
+
+ /**
+ * command6: Pause playback.
+ * Saves each channel's _freqSweepCounter into _savedSweepCounter, zeroes
+ * _freqSweepCounter on all channels, then mutes all 22 operator TL
+ * registers (the byte_1239B table covers all operator slots 0x40-0x55).
+ * Sets _isDisabled to prevent further updates.
+ */
+ int command6();
+
+ /**
+ * command7: Resume playback.
+ * Restores operator volumes for all channels from _adlibPorts shadow,
+ * copies _savedSweepCounter back to _freqSweepCounter on all channels,
+ * signals sound playing if any channel was active, then clears _isDisabled.
+ */
+ int command7();
+
+ /**
+ * command8: Returns non-zero if any of the 9 channels has a non-zero
+ * _activeCount (i.e. sound is currently playing).
+ * Also clears the music-only flag (byte_12393 = 0) so the check covers
+ * all 9 channels.
+ */
+ int command8();
+
+ /**
+ * Calls a function at a fixed offset within the sound driver.
+ * @param offset Offset of the function
+ */
+ virtual void callFunction(uint16 offset);
+
+ // =========================================================================
+ // Music-index launcher (called via command18)
+ // =========================================================================
+
+ /**
+ * command18: Re-entrant music launcher.
+ * First calls command1 to fade current output, then branches on _musicIndex
+ * (word_12370):
+ * <= 0x12 -> calls off_11A26 table (commands 16-19)
+ * > 0x12 -> calls funcs_12251 table (commands 32-49), index = _musicIndex - 0x20
+ */
+ int command18();
+
+public:
+ /**
+ * Constructor.
+ * @param mixer Mixer instance
+ * @param opl OPL chip instance
+ * @param filename Path to the .DR1 (or equivalent) sound-driver file
+ * @param dataOffset Offset in the file of the data segment
+ * @param dataSize Size of the data segment
+ */
+ ASound(Audio::Mixer *mixer, OPL::OPL *opl, const Common::Path &filename,
+ int dataOffset, int dataSize);
+
+ ~ASound() override {
+ }
+
+ /** Stop all currently playing sounds (wraps command0). */
+ virtual int stop() override;
+
+ /** Main poll method; drives the per-frame update. */
+ int poll() override;
+
+ /**
+ * Noise channel tick: for each of the 9 channels calls noise_inner,
+ * which randomises the voice frequency each frame using _noiseFreqMask.
+ */
+ void noise() override;
+
+ /**
+ * Starts playback of the sound data at the given byte offset within the
+ * driver's data segment, using findFreeChannelFull to select a channel.
+ */
+ void playSound(int offset);
+
+ void setVolume(int volume) override {
+ // TODO: implement if needed
+ }
+};
+
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/forest.cpp b/engines/mads/madsv2/forest/forest.cpp
index af0c9cc5913..4f2a10e778c 100644
--- a/engines/mads/madsv2/forest/forest.cpp
+++ b/engines/mads/madsv2/forest/forest.cpp
@@ -21,11 +21,34 @@
#include "engines/util.h"
#include "mads/madsv2/console.h"
-#include "mads/madsv2/forest/forest.h"
+#include "mads/madsv2/core/attr.h"
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/env.h"
#include "mads/madsv2/core/game.h"
#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/matte.h"
+#include "mads/madsv2/core/object.h"
+#include "mads/madsv2/core/pal.h"
+#include "mads/madsv2/core/rail.h"
#include "mads/madsv2/core/screen.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/forest.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/main.h"
+#include "mads/madsv2/forest/sound_forest.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/section2.h"
+#include "mads/madsv2/forest/rooms/section3.h"
+#include "mads/madsv2/forest/rooms/section4.h"
+#include "mads/madsv2/forest/rooms/section5.h"
+#include "mads/madsv2/forest/rooms/section9.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/core/mps_installer.h"
namespace MADS {
namespace MADSV2 {
@@ -39,135 +62,74 @@ Common::Error ForestEngine::run() {
// Create a debugger console
setDebugger(new Console());
+ // Set up to read mpslabs installer archive if needed
+ if (_gameDescription->desc.flags & GF_INSTALLER) {
+ Common::Archive *arch = MpsInstaller::open("MPSLABS");
+ if (arch)
+ SearchMan.add("mpslabs", arch);
+ }
+
// Set up sound manager
- _soundManager = nullptr; // new ForestSoundManager(_mixer, _soundFlag);
- //_soundManager->validate();
+ _soundManager = new ForestSoundManager(_mixer, _soundFlag);
+ _soundManager->validate();
// Run the game
- // TODO
+ Forest::forest_main();
return Common::kNoError;
}
void ForestEngine::global_init_code() {
-
-}
-
-void ForestEngine::section_music(int section_num) {
-
-}
-
-void ForestEngine::global_object_sprite() {
-
-}
-
-void ForestEngine::stop_walker_basic() {
- int random;
int count;
- int how_many;
-
- random = imath_random(1, 30000);
-
- switch (player.facing) {
- case FACING_SOUTH:
- if (random < 500) {
- how_many = imath_random(4, 10);
- for (count = 0; count < how_many; count++) {
- player_add_stop_walker((random < 250) ? 1 : 2, 0);
- }
- } else if (random < 750) {
- for (count = 0; count < 4; count++) {
- player_add_stop_walker(1, 0);
- }
-
- player_add_stop_walker(0, 0);
-
- for (count = 0; count < 4; count++) {
- player_add_stop_walker(2, 0);
- }
-
- player_add_stop_walker(0, 0);
- }
- break;
-
- case FACING_SOUTHEAST:
- case FACING_SOUTHWEST:
- case FACING_NORTHEAST:
- case FACING_NORTHWEST:
- if (random < 150) {
- player_add_stop_walker(-1, 0);
- player_add_stop_walker(1, 0);
- for (count = 0; count < 6; count++) {
- player_add_stop_walker(0, 0);
- }
- }
- break;
-
- case FACING_EAST:
- case FACING_WEST:
- if (random < 250) {
- player_add_stop_walker(-1, 0);
- how_many = imath_random(2, 6);
- for (count = 0; count < how_many; count++) {
- player_add_stop_walker(2, 0);
- }
- player_add_stop_walker(1, 0);
- player_add_stop_walker(0, 0);
- player_add_stop_walker(0, 0);
- } else if (random < 500) {
- WRITE_LE_UINT32(&global[walker_timing], kernel.clock);
- }
- break;
-
- case FACING_NORTH:
- if (random < 250) {
- player_add_stop_walker(-1, 0);
- how_many = imath_random(3, 7);
- for (count = 0; count < how_many; count++) {
- player_add_stop_walker(2, 0);
- }
- player_add_stop_walker(1, 0);
- player_add_stop_walker(0, 0);
- }
- break;
+ for (count = 0; count < GLOBAL_LIST_SIZE; count++) {
+ global[count] = 0;
}
-}
-void ForestEngine::stop_walker_tricks() {
+ player.facing = FACING_NORTH;
+ player.turn_to_facing = FACING_NORTH;
+}
+void ForestEngine::section_music(int section_num) {
+ switch (section_num) {
+ case 1: Rooms::section_1_music(); break;
+ case 2: Rooms::section_2_music(); break;
+ case 3: Rooms::section_3_music(); break;
+ case 4: Rooms::section_4_music(); break;
+ case 5: Rooms::section_5_music(); break;
+ case 9: Rooms::section_9_music(); break;
+ }
}
void ForestEngine::global_section_constructor() {
-
+ Forest::global_section_constructor();
}
void ForestEngine::syncRoom(Common::Serializer &s) {
-
+ Forest::sync_room(s);
}
void ForestEngine::global_daemon_code() {
-
}
void ForestEngine::global_pre_parser_code() {
-
}
void ForestEngine::global_parser_code() {
+}
+void ForestEngine::global_object_examine() {
}
void ForestEngine::global_error_code() {
-
}
void ForestEngine::global_room_init() {
-
}
void ForestEngine::global_sound_driver() {
-
+ Common::strcpy_s(kernel.sound_driver, "/");
+ env_catint(kernel.sound_driver, new_section, 1);
}
} // namespace Forest
diff --git a/engines/mads/madsv2/forest/forest.h b/engines/mads/madsv2/forest/forest.h
index 577492d4ef8..e7f9d2f6662 100644
--- a/engines/mads/madsv2/forest/forest.h
+++ b/engines/mads/madsv2/forest/forest.h
@@ -19,8 +19,8 @@
*
*/
-#ifndef MADS_FOREST_FOREST_H
-#define MADS_FOREST_FOREST_H
+#ifndef MADS_FOREST_H
+#define MADS_FOREST_H
#include "mads/madsv2/engine.h"
@@ -30,9 +30,7 @@ namespace Forest {
class ForestEngine : public MADSV2Engine {
private:
- static void global_object_sprite();
- static void stop_walker_basic();
- static void stop_walker_tricks();
+ static void global_object_examine();
public:
ForestEngine(OSystem *syst, const MADSGameDescription *gameDesc) :
diff --git a/engines/mads/madsv2/forest/global.cpp b/engines/mads/madsv2/forest/global.cpp
new file mode 100644
index 00000000000..3d926fd63b1
--- /dev/null
+++ b/engines/mads/madsv2/forest/global.cpp
@@ -0,0 +1,166 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/error.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+
+namespace Rooms {
+
+// Section preloads
+extern void section_1_preload();
+extern void section_2_preload();
+extern void section_3_preload();
+extern void section_4_preload();
+extern void section_5_preload();
+extern void section_9_preload();
+
+extern void room_101_synchronize(Common::Serializer &s);
+extern void room_101_synchronize(Common::Serializer &s);
+extern void room_103_synchronize(Common::Serializer &s);
+extern void room_104_synchronize(Common::Serializer &s);
+extern void room_106_synchronize(Common::Serializer &s);
+extern void room_107_synchronize(Common::Serializer &s);
+extern void room_199_synchronize(Common::Serializer &s);
+extern void room_201_synchronize(Common::Serializer &s);
+extern void room_203_synchronize(Common::Serializer &s);
+extern void room_204_synchronize(Common::Serializer &s);
+extern void room_205_synchronize(Common::Serializer &s);
+extern void room_210_synchronize(Common::Serializer &s);
+extern void room_211_synchronize(Common::Serializer &s);
+extern void room_220_synchronize(Common::Serializer &s);
+extern void room_221_synchronize(Common::Serializer &s);
+extern void room_301_synchronize(Common::Serializer &s);
+extern void room_302_synchronize(Common::Serializer &s);
+extern void room_303_synchronize(Common::Serializer &s);
+extern void room_304_synchronize(Common::Serializer &s);
+extern void room_305_synchronize(Common::Serializer &s);
+extern void room_306_synchronize(Common::Serializer &s);
+extern void room_307_synchronize(Common::Serializer &s);
+extern void room_308_synchronize(Common::Serializer &s);
+extern void room_321_synchronize(Common::Serializer &s);
+extern void room_322_synchronize(Common::Serializer &s);
+extern void room_401_synchronize(Common::Serializer &s);
+extern void room_402_synchronize(Common::Serializer &s);
+extern void room_403_synchronize(Common::Serializer &s);
+extern void room_404_synchronize(Common::Serializer &s);
+extern void room_405_synchronize(Common::Serializer &s);
+extern void room_420_synchronize(Common::Serializer &s);
+extern void room_501_synchronize(Common::Serializer &s);
+extern void room_503_synchronize(Common::Serializer &s);
+extern void room_509_synchronize(Common::Serializer &s);
+extern void room_510_synchronize(Common::Serializer &s);
+extern void room_520_synchronize(Common::Serializer &s);
+extern void room_901_synchronize(Common::Serializer &s);
+extern void room_903_synchronize(Common::Serializer &s);
+extern void room_904_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+
+void global_section_constructor() {
+ section_preload_code_pointer = NULL;
+ section_room_constructor = NULL;
+ section_init_code_pointer = NULL;
+ section_parser_code_pointer = NULL;
+ section_daemon_code_pointer = NULL;
+
+ room_preload_code_pointer = NULL;
+ room_init_code_pointer = NULL;
+ room_daemon_code_pointer = NULL;
+ room_pre_parser_code_pointer = NULL;
+ room_parser_code_pointer = NULL;
+ room_error_code_pointer = NULL;
+ room_shutdown_code_pointer = NULL;
+
+ switch (new_section) {
+ case 1:
+ section_preload_code_pointer = Rooms::section_1_preload;
+ break;
+ case 2:
+ section_preload_code_pointer = Rooms::section_2_preload;
+ break;
+ case 3:
+ section_preload_code_pointer = Rooms::section_3_preload;
+ break;
+ case 4:
+ section_preload_code_pointer = Rooms::section_4_preload;
+ break;
+ case 5:
+ section_preload_code_pointer = Rooms::section_5_preload;
+ break;
+ case 9:
+ section_preload_code_pointer = Rooms::section_9_preload;
+ break;
+ }
+}
+
+void sync_room(Common::Serializer &s) {
+ switch (new_room) {
+ case 101: Rooms::room_101_synchronize(s); break;
+ case 103: Rooms::room_103_synchronize(s); break;
+ case 104: Rooms::room_104_synchronize(s); break;
+ case 106: Rooms::room_106_synchronize(s); break;
+ case 107: Rooms::room_107_synchronize(s); break;
+ case 199: Rooms::room_199_synchronize(s); break;
+ case 201: Rooms::room_201_synchronize(s); break;
+ case 203: Rooms::room_203_synchronize(s); break;
+ case 204: Rooms::room_204_synchronize(s); break;
+ case 205: Rooms::room_205_synchronize(s); break;
+ case 210: Rooms::room_210_synchronize(s); break;
+ case 211: Rooms::room_211_synchronize(s); break;
+ case 220: Rooms::room_220_synchronize(s); break;
+ case 221: Rooms::room_221_synchronize(s); break;
+ case 301: Rooms::room_301_synchronize(s); break;
+ case 302: Rooms::room_302_synchronize(s); break;
+ case 303: Rooms::room_303_synchronize(s); break;
+ case 304: Rooms::room_304_synchronize(s); break;
+ case 305: Rooms::room_305_synchronize(s); break;
+ case 306: Rooms::room_306_synchronize(s); break;
+ case 307: Rooms::room_307_synchronize(s); break;
+ case 308: Rooms::room_308_synchronize(s); break;
+ case 321: Rooms::room_321_synchronize(s); break;
+ case 322: Rooms::room_322_synchronize(s); break;
+ case 401: Rooms::room_401_synchronize(s); break;
+ case 402: Rooms::room_402_synchronize(s); break;
+ case 403: Rooms::room_403_synchronize(s); break;
+ case 404: Rooms::room_404_synchronize(s); break;
+ case 405: Rooms::room_405_synchronize(s); break;
+ case 420: Rooms::room_420_synchronize(s); break;
+ case 501: Rooms::room_501_synchronize(s); break;
+ case 503: Rooms::room_503_synchronize(s); break;
+ case 509: Rooms::room_509_synchronize(s); break;
+ case 510: Rooms::room_510_synchronize(s); break;
+ case 520: Rooms::room_520_synchronize(s); break;
+ case 901: Rooms::room_901_synchronize(s); break;
+ case 903: Rooms::room_903_synchronize(s); break;
+ case 904: Rooms::room_904_synchronize(s); break;
+ default: break;
+ }
+}
+
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/global.h b/engines/mads/madsv2/forest/global.h
new file mode 100644
index 00000000000..b64a68b9aca
--- /dev/null
+++ b/engines/mads/madsv2/forest/global.h
@@ -0,0 +1,39 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_GLOBAL_H
+#define MADS_FOREST_GLOBAL_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/vocabh.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+
+extern void global_section_constructor();
+extern void sync_room(Common::Serializer &s);
+
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/mads/inventory.h b/engines/mads/madsv2/forest/mads/inventory.h
new file mode 100644
index 00000000000..daf83353cf1
--- /dev/null
+++ b/engines/mads/madsv2/forest/mads/inventory.h
@@ -0,0 +1,37 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_MADS_INVENTORY_H
+#define MADS_FOREST_MADS_INVENTORY_H
+
+#include "common/scummsys.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+
+//enum {};
+
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/mads/mads.cpp b/engines/mads/madsv2/forest/mads/mads.cpp
new file mode 100644
index 00000000000..d058cc2d316
--- /dev/null
+++ b/engines/mads/madsv2/forest/mads/mads.cpp
@@ -0,0 +1,25 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/quotes.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
diff --git a/engines/mads/madsv2/forest/mads/quotes.h b/engines/mads/madsv2/forest/mads/quotes.h
new file mode 100644
index 00000000000..65cadc2ddbf
--- /dev/null
+++ b/engines/mads/madsv2/forest/mads/quotes.h
@@ -0,0 +1,37 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_MADS_QUOTES_H
+#define MADS_FOREST_MADS_QUOTES_H
+
+#include "common/scummsys.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+
+//enum {};
+
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/mads/sounds.h b/engines/mads/madsv2/forest/mads/sounds.h
new file mode 100644
index 00000000000..84513db6c9d
--- /dev/null
+++ b/engines/mads/madsv2/forest/mads/sounds.h
@@ -0,0 +1,37 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_MADS_SOUNDS_H
+#define MADS_FOREST_MADS_SOUNDS_H
+
+#include "common/scummsys.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+
+//enum {};
+
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/mads/words.h b/engines/mads/madsv2/forest/mads/words.h
new file mode 100644
index 00000000000..8ba2af5b3ac
--- /dev/null
+++ b/engines/mads/madsv2/forest/mads/words.h
@@ -0,0 +1,37 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_MADS_WORDS_H
+#define MADS_FOREST_MADS_WORDS_H
+
+#include "common/scummsys.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+
+//enum {};
+
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/main.cpp b/engines/mads/madsv2/forest/main.cpp
new file mode 100644
index 00000000000..eac24e274b3
--- /dev/null
+++ b/engines/mads/madsv2/forest/main.cpp
@@ -0,0 +1,278 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/config-manager.h"
+#include "gui/saveload.h"
+#include "mads/madsv2/forest/main.h"
+#include "mads/madsv2/animview/animview.h"
+#include "mads/madsv2/textview/textview.h"
+#include "mads/madsv2/core/env.h"
+#include "mads/madsv2/core/error.h"
+#include "mads/madsv2/core/fileio.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/himem.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/magic.h"
+#include "mads/madsv2/core/matte.h"
+#include "mads/madsv2/core/mcga.h"
+#include "mads/madsv2/core/mouse.h"
+#include "mads/madsv2/core/pal.h"
+#include "mads/madsv2/core/player.h"
+#include "mads/madsv2/core/quote.h"
+#include "mads/madsv2/core/speech.h"
+#include "mads/madsv2/forest/main_menu.h"
+#include "mads/madsv2/forest/menus.h"
+#include "mads/madsv2/engine.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+
+constexpr bool SHOW_LINES = true;
+constexpr byte LINE_COLOR = 2;
+
+char *quotes;
+
+static void main_menu_main() {
+ auto &screen = *g_engine->getScreen();
+ Palette palette;
+
+ if (!kernel_game_startup(19, KERNEL_STARTUP_CURSOR | KERNEL_STARTUP_INTERRUPT | KERNEL_STARTUP_FONT,
+ nullptr, nullptr)) {
+ matte_init(0xFFFF);
+ bool valid = !kernel_room_startup(920, 0, nullptr, true, true);
+
+ // Setup scr_work to use the full surface of scr_main (i.e. 320x200).
+ // Because of this, viewing_at_y is actually == 0
+ scr_work.y = picture_map.viewport_y;
+ viewing_at_y = (200 - scr_work.y) >> 1;
+
+ mouse_cursor_sprite(cursor, 7);
+ mouse_show();
+ mouse_force(280, 126);
+ mouse_hide();
+
+ mouse_cursor_sprite(cursor, 1);
+ kernel_seq_init();
+ kernel_message_init();
+ kernel_animation_init();
+ kernel_init_dynamic();
+
+ picture_view_x = 0;
+ picture_view_y = 0;
+ new_background = true;
+
+ if (valid) {
+ memset(&palette, 0, sizeof(palette));
+ mcga_setpal(&palette);
+ mouse_cursor_sprite(cursor, 1);
+
+ if (SHOW_LINES && viewing_at_y != 0) {
+ screen.hLine(0, viewing_at_y - 2, 319, LINE_COLOR);
+ screen.hLine(0, scr_work.y + viewing_at_y + 1, 319, LINE_COLOR);
+ }
+
+ kernel_load_sound_driver("*#SOUND.DR9", 'N', 544, 0, 49);
+
+ menu_control();
+
+ if (selected_item >= 0) {
+ // Zero out the first 3 entries of both magic color arrays
+ for (int i = 0; i < 3; i++) {
+ magic_color_values[i] = 0;
+ magic_color_flags[i] = 0;
+ }
+
+ mcga_getpal(&palette);
+
+ magic_fade_to_grey(palette, 0, 0x10, 1, 1, 0, 0, 0);
+ }
+ }
+
+ free(quotes);
+ kernel_unload_sound_driver();
+ kernel_game_shutdown();
+ }
+
+ mcga_reset();
+}
+
+static void main_cold_data_init() {
+ debugger_reset = game_debugger_reset;
+ debugger_update = game_debugger;
+ game_menu_routine = global_game_menu;
+ game_menu_init = global_menu_system_init;
+ game_menu_exit = global_menu_system_shutdown;
+ game_emergency_save = global_emergency_save;
+
+ Common::strcpy_s(config_file_name, "config.dra");
+ Common::strcpy_s(save_game_key, "drag");
+ Common::strcpy_s(restart_game_key, "dragon");
+
+ Common::strcpy_s(player.series_name, "RAL");
+ player.walker_must_reload = true;
+ player.walker_loads_first = false;
+ player.walker_visible = true;
+ player.scaling_velocity = true;
+
+ Common::strcpy_s(kernel_cheating_password, "WIDECHEW");
+ kernel_cheating_allowed = strlen(kernel_cheating_password);
+
+ kernel.cheating = gDebugLevel == 9 ? kernel_cheating_allowed : 0;
+}
+
+static void game_main(int argc, const char **argv) {
+ int count;
+ int mads_mode;
+ const char *scan;
+
+ pack_enable_pfab_explode();
+
+ mads_mode = env_verify();
+
+ new_section = 1;
+ new_room = 101;
+ player.x = 160;
+ player.y = 78;
+
+ player.target_facing = FACING_NORTH;
+
+ game_cold_data_init();
+ main_cold_data_init();
+ g_engine->readConfigFile();
+ global_load_config_parameters();
+
+ if (argc >= 2) {
+ for (count = 1; count < argc; count++) {
+ if (strchr("-/", argv[count][0]) != NULL) {
+ for (scan = argv[count] + 1; *scan != 0; scan++) {
+ flag_parse(&scan);
+ }
+ } else if (argv[count][0] == '?') {
+ show_logo();
+
+ if (!mads_mode) env_search_mode = ENV_SEARCH_CONCAT_FILES;
+ error_dump_file("*warn2.dat");
+ goto done;
+ }
+ }
+ }
+
+ if (report_version) {
+ show_version();
+ goto done;
+ }
+
+ if (fileio_exist("global.hag")) {
+ art_hags_are_on_hd = true;
+ } else {
+ art_hags_are_on_hd = false;
+ }
+
+ himem_startup();
+
+ himem_shutdown();
+
+ if (!mads_mode && (env_search_mode == ENV_SEARCH_MADS_PATH))
+ error("false start");
+
+ game_control();
+
+done:
+ global_unload_config_parameters();
+
+ if (fileio_exist("config.for")) {
+ global_write_config_file();
+ }
+ if (chain_flag && (win_status || force_chain) && (key_abort_level < 2)) {
+ warning("TODO: chain_execute");
+ } else {
+ if (win_status) {
+ debug("(Ending: %d)", win_status);
+ }
+ }
+}
+
+void forest_main() {
+ static const char *CMD_LINE[] = { nullptr, "-p" };
+
+ pack_enable_pfab_explode();
+ if (!env_verify())
+ env_search_mode = ENV_SEARCH_CONCAT_FILES;
+
+ if (ConfMan.getBool("start_game") || ConfMan.hasKey("save_slot"))
+ selected_item = 0;
+ else if (ConfMan.getBool("start_intro"))
+ selected_item = 3;
+ else
+ selected_item = -1;
+
+ while (!g_engine->shouldQuit()) {
+ g_engine->getScreen()->clear();
+
+ switch (selected_item) {
+ case -1:
+ main_menu_main();
+ break;
+
+ case 0:
+ game_main(2, CMD_LINE);
+ return;
+
+ case 1: {
+ // Resume savegame
+ // Get a list of saves and choose the last one
+ auto saves = g_engine->listSaves();
+ if (!saves.empty())
+ savegame_slot = saves.back().getSaveSlot();
+
+ // Start the game, which will also load the selected savegame
+ game_main(2, CMD_LINE);
+ return;
+ }
+
+ case 2:
+ // Restore savegame
+ game_restore_flag = 2;
+ game_main(2, CMD_LINE);
+ return;
+
+ case 3:
+ AnimView::animview_main("@forest");
+ selected_item = -1;
+ break;
+
+ case 4:
+ // Exit
+ return;
+
+ default:
+ // Credits
+ TextView::textview_main("credits");
+ selected_item = -1;
+ break;
+ }
+ }
+}
+
+} // namespace Foreste
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/main.h b/engines/mads/madsv2/forest/main.h
new file mode 100644
index 00000000000..7d74c096016
--- /dev/null
+++ b/engines/mads/madsv2/forest/main.h
@@ -0,0 +1,37 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_MAIN_H
+#define MADS_FOREST_MAIN_H
+
+#include "common/scummsys.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+
+extern void forest_main();
+
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/main_menu.cpp b/engines/mads/madsv2/forest/main_menu.cpp
new file mode 100644
index 00000000000..7dff7b0108e
--- /dev/null
+++ b/engines/mads/madsv2/forest/main_menu.cpp
@@ -0,0 +1,433 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/engine.h"
+#include "mads/madsv2/core/general.h"
+#include "mads/madsv2/core/config.h"
+#include "mads/madsv2/core/font.h"
+#include "mads/madsv2/core/speech.h"
+#include "mads/madsv2/core/matte.h"
+#include "mads/madsv2/core/sprite.h"
+#include "mads/madsv2/core/error.h"
+#include "mads/madsv2/core/room.h"
+#include "mads/madsv2/core/fileio.h"
+#include "mads/madsv2/core/env.h"
+#include "mads/madsv2/core/buffer.h"
+#include "mads/madsv2/core/mem.h"
+#include "mads/madsv2/core/pal.h"
+#include "mads/madsv2/core/timer.h"
+#include "mads/madsv2/core/mcga.h"
+#include "mads/madsv2/core/cycle.h"
+#include "mads/madsv2/core/mouse.h"
+#include "mads/madsv2/core/screen.h"
+#include "mads/madsv2/core/video.h"
+#include "mads/madsv2/core/lib.h"
+#include "mads/madsv2/core/keys.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/btype.h"
+#include "mads/madsv2/core/hspot.h"
+#include "mads/madsv2/core/magic.h"
+#include "mads/madsv2/core/ems.h"
+#include "mads/madsv2/core/xms.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/pack.h"
+#include "mads/madsv2/core/quote.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/main_menu.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+
+#define CONFIG_FILE_NAME "CONFIG.PHA"
+
+#define EYE_QUOTES 16
+#define EYE_HOTSPOT 32
+#define EYE_MESSAGES 2
+
+#undef MESSAGE_COLOR
+#define MESSAGE_COLOR 1284
+
+
+ConfigFile config_file;
+
+int mads_mode = false;
+
+FontPtr font = NULL;
+int font_auto_spacing = -1;
+
+bool new_background = false;
+int room_number = 0;
+
+int win_status = 0;
+
+bool force_opening = false;
+bool dont_return = false;
+bool white_bars = true;
+byte white_border = 2;
+
+char command_line[COMMAND_LINE_MAX][80];
+char *command_list[COMMAND_LINE_MAX+1];
+int command_line_size = 0;
+
+int use_mouse_cursor_fix = false;
+
+bool going;
+int menu_mode;
+int must_perform_matte;
+
+long frame_clock;
+long now_clock;
+long menu_clock;
+
+int menu_state;
+int menu_appear_state;
+
+int highest_y = -1;
+int next_x = -1;
+
+char sound_file[80] = "*#SOUND.PH9";
+char sound_letter = 'N';
+
+int sound_board_address = 0x220; /* Default sound board address */
+int sound_board_type = sound_board_roland; /* Default sound board type */
+
+int swapping = false; /* Flag when swapping in new background */
+int swap_line; /* Currently active swap line */
+long swap_clock; /* Time for next swap */
+
+int current_item;
+int current_eye = false;
+int eye_latch = false;
+int selected_item = -1;
+
+#define LEFT_EYE 0
+#define RIGHT_EYE 1
+
+extern char *quotes;
+int eye_message[2];
+int eye_pokes = 0;
+int recent_eye = 0;
+int rebel_base = 0;
+int poke_count_message = -1;
+int poke_count = 0;
+int poke_counting = false;
+
+char poke_count_buf[2][20];
+
+char bonus_buf[80] = "";
+
+Palette special_pal; /* Palette for fadeout */
+
+
+MenuItem menu_item[NUM_MENU_ITEMS+1]; /* Menu item array */
+
+static void start_series() {
+ int error_flag = true;
+ int count;
+ int handle;
+ char temp_buf[80];
+
+ for (count = 0; count < NUM_MENU_ITEMS; count++) {
+ handle = -1;
+ Common::strcpy_s(temp_buf, "*MAIN0.SS");
+ temp_buf[5] = (char)('0' + count);
+
+ handle = matte_load_series(temp_buf, 0, 0);
+ if (handle < 0) goto done;
+
+ menu_item[count].handle = handle;
+ menu_item[count].active = count != 6; // Quotes button was never implemented
+ menu_item[count].status = 0;
+ }
+
+ error_flag = false;
+
+done:
+ if (error_flag) {
+ Common::strcpy_s(error_string, temp_buf);
+ error_report(ERROR_SERIES_LOAD_FAILED, WARNING, MODULE_UNKNOWN, count, handle);
+ }
+}
+
+static void stop_series() {
+ int count;
+
+ for (count = NUM_MENU_ITEMS - 1; count >= 0; count--) {
+ matte_deallocate_series(menu_item[count].handle, true);
+ }
+}
+
+static void start_hotspots() {
+ int count;
+ int x1, x2, y1, y2;
+ int xs, ys;
+ SeriesPtr series;
+
+ numspots = 0;
+
+ for (count = 0; count < NUM_MENU_ITEMS; count++) {
+ series = series_list[menu_item[count].handle];
+ xs = series->index[0].xs;
+ ys = series->index[0].ys;
+ x1 = series->index[0].x - (xs >> 1);
+ y1 = series->index[0].y - (ys - 1);
+
+ x2 = x1 + xs - 1;
+ y2 = y1 + ys - 1;
+ hspot_add(x1, y1, x2, y2, 1, count, mcga_mode);
+ }
+}
+
+static void process_menu() {
+ int myspot;
+
+ myspot = hspot_which(mouse_x, mouse_y - viewing_at_y, mcga_mode);
+
+ current_eye = false;
+
+ if ((myspot > 0) && mouse_any_stroke && (menu_mode == MENU_ACCEPTING_COMMANDS)) {
+ current_item = spot[myspot].num;
+ if (current_item >= EYE_HOTSPOT) {
+ current_item = -1;
+ current_eye = true;
+ }
+ } else {
+ current_item = -1;
+ }
+
+ if (mouse_stop_stroke && (current_item >= 0) && (menu_mode == MENU_ACCEPTING_COMMANDS)) {
+ selected_item = current_item;
+ menu_mode = MENU_DISAPPEARING;
+ menu_state = 1;
+ }
+}
+
+static void process_sprites() {
+ int count;
+ int sprite;
+ int series;
+ int look, match;
+ Image image;
+
+ for (count = 0; count < (int)image_marker; count++) {
+ if ((image_list[count].segment_id < KERNEL_SEGMENT_ANIMATION) ||
+ (image_list[count].segment_id > KERNEL_SEGMENT_ANIMATION_HIGH)) {
+ if (image_list[count].flags >= IMAGE_STATIC) {
+ image_list[count].flags = IMAGE_ERASE;
+ }
+ }
+ }
+
+ if (menu_mode == MENU_APPEARING) goto done;
+
+ for (count = 0; count < NUM_MENU_ITEMS; count++) {
+ if (menu_item[count].active) {
+ image.flags = IMAGE_UPDATE;
+ image.segment_id = (byte)(count + 1);
+
+ series = count;
+ if (menu_mode == MENU_ACCEPTING_COMMANDS) {
+ if (count != current_item) {
+ sprite = 1;
+ } else {
+ sprite = 2;
+ }
+ } else {
+ sprite = 1;
+ }
+
+ image.series_id = (byte)menu_item[series].handle;
+ image.sprite_id = sprite;
+
+ image.x = series_list[series]->index[sprite - 1].x;
+ image.y = series_list[series]->index[sprite - 1].y;
+
+ image.depth = 0;
+ image.scale = 100;
+
+ match = !(sprite <= MENU_HIGH_SPRITE);
+
+ for (look = 0; !match && (look < (int)image_marker); look++) {
+ if (image_list[look].segment_id == image.segment_id) {
+ if (memcmp(&image_list[look].series_id,
+ &image.series_id, 9) == 0) {
+ image_list[look].flags = IMAGE_STATIC;
+ match = true;
+ }
+ }
+ }
+
+ if (!match) {
+ image_list[image_marker] = image;
+ image_marker++;
+ }
+ }
+ }
+
+done:
+ ;
+}
+
+void menu_control() {
+ int fx;
+ int mykey;
+ int last_frame = -1;
+ int now_frame;
+ int reset_frame;
+ int anim;
+ int initial_reset = false;
+
+ menu_mode = MENU_APPEARING;
+ menu_state = MENU_HIGH_SPRITE;
+ menu_appear_state = 0;
+ menu_clock = 999999999;
+
+ going = true;
+ must_perform_matte = false;
+
+ frame_clock = 0;
+
+ start_series();
+ start_hotspots();
+
+ anim = kernel_run_animation("*RM902A.AA", 0);
+
+ mouse_init_cycle();
+
+ while (going && !g_engine->shouldQuit()) {
+ if (keys_any()) {
+ mykey = keys_get();
+ switch (toupper(mykey)) {
+ case esc_key:
+ selected_item = 4;
+ going = false;
+ break;
+
+ case alt_x_key:
+ case alt_q_key:
+ case ctrl_x_key:
+ case ctrl_q_key:
+ going = false;
+ break;
+
+ case 'S':
+ menu_mode = MENU_APPEARING;
+ menu_state = MENU_HIGH_SPRITE;
+ menu_appear_state = 0;
+ break;
+
+ default:
+ if (menu_mode == MENU_APPEARING) {
+ menu_mode = MENU_ACCEPTING_COMMANDS;
+ kernel_reset_animation(anim, 105);
+ kernel_anim[anim].next_clock = kernel.clock;
+ }
+ break;
+ }
+ }
+
+ mouse_begin_cycle(false);
+
+ if (mouse_stroke_going) {
+ if (menu_mode == MENU_APPEARING) {
+ menu_mode = MENU_ACCEPTING_COMMANDS;
+ kernel_reset_animation(anim, 105);
+ kernel_anim[anim].next_clock = kernel.clock;
+ mouse_init_cycle();
+ }
+ }
+
+ if (menu_mode != MENU_APPEARING) {
+ mouse_show();
+ }
+
+ now_clock = timer_read();
+ kernel.clock = now_clock;
+
+ if (now_clock >= menu_clock) {
+ if (menu_mode == MENU_DISAPPEARING)
+ going = false;
+
+ menu_clock = now_clock + MENU_FRAME_RATE;
+ }
+
+ process_menu();
+ kernel_message_update_all();
+ kernel_process_all_animations();
+
+ reset_frame = -1;
+ now_frame = kernel_anim[anim].frame;
+ if (now_frame != last_frame) {
+ last_frame = now_frame;
+
+ if (now_frame < 105) {
+ if (menu_mode != MENU_APPEARING) {
+ if (!initial_reset) {
+ reset_frame = 105;
+ initial_reset = true;
+ }
+ }
+ }
+
+ if (now_frame >= 109) {
+ if (menu_mode == MENU_APPEARING)
+ menu_mode = MENU_ACCEPTING_COMMANDS;
+
+ reset_frame = 105;
+ }
+
+ if (reset_frame >= 0) {
+ kernel_reset_animation(anim, reset_frame);
+ last_frame = reset_frame;
+ }
+ }
+
+ if (now_clock >= frame_clock) {
+ process_sprites();
+
+ fx = new_background ? 1 : 0;
+ matte_frame(fx, false);
+
+ if (fx) {
+ now_clock = timer_read();
+ menu_clock = now_clock + MENU_FRAME_RATE;
+ }
+
+ must_perform_matte = false;
+ new_background = false;
+
+ frame_clock = now_clock + FRAME_RATE;
+ }
+
+ mouse_end_cycle(false, going);
+ }
+
+ kernel_abort_animation(anim);
+
+ stop_series();
+}
+
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/main_menu.h b/engines/mads/madsv2/forest/main_menu.h
new file mode 100644
index 00000000000..ae655e0f4c3
--- /dev/null
+++ b/engines/mads/madsv2/forest/main_menu.h
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_MAIN_MENU_H
+#define MADS_FOREST_MAIN_MENU_H
+
+#include "common/str.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+
+#define COMMAND_LINE_MAX 10
+
+#define FRAME_RATE 1
+#define MENU_FRAME_RATE 3
+
+#define NUM_MENU_ITEMS 6
+
+#define MENU_APPEARING 0
+#define MENU_ACCEPTING_COMMANDS 1
+#define MENU_DISAPPEARING 2
+
+#define MENU_HIGH_SPRITE 15
+
+typedef struct {
+ int handle; /* Sprite series handle */
+ int active; /* Menu item is active */
+ int status; /* Current status */
+} MenuItem;
+
+extern bool new_background;
+extern int selected_item;
+
+extern void menu_control();
+
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/menus.cpp b/engines/mads/madsv2/forest/menus.cpp
new file mode 100644
index 00000000000..ee9fe1c8bb5
--- /dev/null
+++ b/engines/mads/madsv2/forest/menus.cpp
@@ -0,0 +1,615 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/config.h"
+#include "mads/madsv2/core/echo.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/global.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/keys.h"
+#include "mads/madsv2/core/matte.h"
+#include "mads/madsv2/core/mem.h"
+#include "mads/madsv2/core/speech.h"
+#include "mads/madsv2/core/quote.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/menus.h"
+#include "mads/madsv2/forest/global.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+
+#define SAVE_MENU_PIXEL_WIDTH 200
+#define MAX_SAVES_ON_SCREEN 10
+
+#define SPACE_BETWEEN -1
+
+#define MAIN_MENU_ITEM_WIDTH 140
+#define MAIN_MENU_FORCE_WIDTH 160
+
+#define DIFFICULTY_MENU_FORCE_WIDTH 140
+
+#define OPTIONS_MENU_ITEM_WIDTH 160
+#define OPTIONS_MENU_FORCE_WIDTH 170
+#define OPTIONS_MENU_OFF_CENTER 10
+
+
+#define SAVE_SUCCESSFUL 1
+#define RESTORE_SUCCESSFUL 2
+#define SAVE_FAILED 3
+#define RESTORE_FAILED 4
+
+
+int global_menu_direct_jump;
+int global_menu_force_restart;
+
+char *menu_quotes = NULL;
+
+
+static int global_save(int id, const char *save_game_name) {
+ int status;
+
+ game_save_name(id + 1);
+
+ if (g_engine->saveGameState(id + 1, save_game_name).getCode() == Common::kNoError)
+ status = SAVE_SUCCESSFUL;
+ else
+ status = SAVE_FAILED;
+
+ return status;
+}
+
+static int global_restore(int id) {
+ int status;
+
+ if (g_engine->loadGameState(id + 1).getCode() == Common::kNoError)
+ status = RESTORE_SUCCESSFUL;
+ else
+ status = RESTORE_FAILED;
+
+ WRITE_LE_UINT32(&global[walker_timing], 0);
+
+ return status;
+}
+
+void global_menu_system_init() {
+}
+
+void global_menu_system_shutdown() {
+ if (menu_quotes != NULL)
+ mem_free(menu_quotes);
+}
+
+static char *menu_quote(int id) {
+ return quote_string(menu_quotes, id);
+}
+
+void global_emergency_save() {
+ game_save_name(0);
+
+ if (scr_orig.data != NULL) mem_free(scr_orig.data);
+
+ g_engine->saveAutosaveIfEnabled();
+}
+
+static void global_alert(int status) {
+}
+
+static void global_menu_score() {
+}
+
+static void global_menu_save_restore(int save) {
+#if 0
+ int status = -1;
+ int selection;
+ char *save_game_name;
+ PopupItem *save_list;
+ PopupItem *go_button;
+ PopupItem *clear_button;
+ PopupItem *cancel_button;
+ PopupItem *result;
+
+ popup_dialog_create(game_menu_popup, GAME_DIALOG_HEAP, 20);
+
+ if (save) {
+ popup_message(menu_quote(quote_save_title), POPUP_CENTER, POPUP_FILL);
+ } else {
+ popup_message(menu_quote(quote_restore_title), POPUP_CENTER, POPUP_FILL);
+ }
+ popup_blank(4);
+
+ save_list = popup_savelist(game_save_directory, menu_quote(quote_menu_empty),
+ GAME_MAX_SAVE_SLOTS,
+ GAME_MAX_SAVE_LENGTH + 1,
+ GAME_MAX_SAVE_LENGTH,
+ SAVE_MENU_PIXEL_WIDTH,
+ MAX_SAVES_ON_SCREEN,
+ save, game.last_save);
+
+ if (save) {
+ go_button = popup_button(menu_quote(quote_menu_save), POPUP_BUTTON_LEFT);
+ clear_button = popup_button(menu_quote(quote_menu_clear), POPUP_CENTER);
+ game_menu_popup->clear_item = clear_button;
+ } else {
+ go_button = popup_button(menu_quote(quote_menu_restore), POPUP_BUTTON_LEFT);
+ }
+ cancel_button = popup_cancel_button(menu_quote(quote_menu_cancel));
+
+ result = popup_execute();
+
+ if (result == cancel_button) {
+ switch (game_menu_popup->key) {
+ case alt_x_key:
+ case ctrl_x_key:
+ case alt_q_key:
+ case ctrl_q_key:
+ game.going = false;
+ kernel.activate_menu = GAME_NO_MENU;
+ break;
+
+ case f1_key:
+ kernel.activate_menu = GAME_MAIN_MENU;
+ break;
+
+ case f2_key:
+ if (save) {
+ kernel.activate_menu = GAME_MAIN_MENU;
+ } else {
+ kernel.activate_menu = GAME_SAVE_MENU;
+ }
+ break;
+
+ case f3_key:
+ if (!save) {
+ kernel.activate_menu = GAME_MAIN_MENU;
+ } else {
+ kernel.activate_menu = GAME_RESTORE_MENU;
+ }
+ break;
+
+ case f4_key:
+ kernel.activate_menu = GAME_SCORE_MENU;
+ break;
+
+ case f5_key:
+ kernel.activate_menu = GAME_OPTIONS_MENU;
+ break;
+
+ default:
+ kernel.activate_menu = GAME_MAIN_MENU;
+ break;
+ }
+ } else {
+ kernel.activate_menu = GAME_NO_MENU;
+ }
+
+ popup_dialog_destroy();
+
+ if (result == go_button) {
+ selection = save_list->list->picked_element;
+ game.last_save = selection;
+ if (save) {
+ save_game_name = game_save_directory + ((GAME_MAX_SAVE_LENGTH + 1) * selection);
+ if (!strlen(save_game_name)) {
+ Common::strcpy_s(save_game_name, GAME_MAX_SAVE_LENGTH, menu_quote(quote_menu_unnamed));
+ }
+ status = global_save(selection, save_game_name);
+
+ } else {
+ status = global_restore(selection);
+ }
+
+ if (status > 0)
+ // Dummy name to signal save/load went ok
+ Common::strcpy_s(save_game_buf, "OK");
+ }
+
+ if (status >= 0) {
+ global_alert(status);
+ }
+#endif
+}
+
+static void global_menu_options() {
+#if 0
+ int initial_1, initial_2, initial_3;
+ int initial_4, initial_5, initial_6;
+ int former_music;
+ int former_sound;
+ PopupItem *music_item;
+ PopupItem *sound_item;
+ PopupItem *interface_item;
+ PopupItem *fade_item;
+ PopupItem *panning_item;
+ PopupItem *speech_item;
+ PopupItem *done_button;
+ PopupItem *cancel_button;
+ PopupItem *result;
+
+ global_unload_config_parameters();
+
+ popup_dialog_create(game_menu_popup, GAME_DIALOG_HEAP, 20);
+
+ popup_sprite(box_param.logo, 1, POPUP_CENTER, POPUP_FILL);
+ popup_blank(2);
+
+ former_music = config_file.music_flag;
+ former_sound = config_file.sound_flag;
+
+ initial_1 = config_file.music_flag ? 0 : 1;
+ initial_2 = config_file.sound_flag ? 0 : 1;
+ initial_6 = config_file.speech_flag ? 0 : 1;
+ initial_3 = config_file.interface_hotspots;
+ initial_4 = config_file.screen_fade;
+ initial_5 = config_file.panning_speed;
+
+ music_item = popup_menu(menu_quote(quote_options_item1),
+ POPUP_CENTER, POPUP_FILL, OPTIONS_MENU_ITEM_WIDTH,
+ OPTIONS_MENU_OFF_CENTER,
+ 2, 40, initial_1);
+ popup_menu_option(music_item, menu_quote(quote_options_item1a));
+ popup_menu_option(music_item, menu_quote(quote_options_item1b));
+
+ popup_blank(SPACE_BETWEEN);
+
+
+ sound_item = popup_menu(menu_quote(quote_options_item2),
+ POPUP_CENTER, POPUP_FILL, OPTIONS_MENU_ITEM_WIDTH,
+ OPTIONS_MENU_OFF_CENTER,
+ 2, 40, initial_2);
+ popup_menu_option(sound_item, menu_quote(quote_options_item2a));
+ popup_menu_option(sound_item, menu_quote(quote_options_item2b));
+
+ popup_blank(SPACE_BETWEEN);
+
+
+ speech_item = popup_menu(menu_quote(quote_options_item6),
+ POPUP_CENTER, POPUP_FILL, OPTIONS_MENU_ITEM_WIDTH,
+ OPTIONS_MENU_OFF_CENTER,
+ 2, 40, initial_6);
+ popup_menu_option(speech_item, menu_quote(quote_options_item6a));
+ popup_menu_option(speech_item, menu_quote(quote_options_item6b));
+
+ popup_blank(SPACE_BETWEEN);
+
+
+ interface_item = popup_menu(menu_quote(quote_options_item3),
+ POPUP_CENTER, POPUP_FILL, OPTIONS_MENU_ITEM_WIDTH,
+ OPTIONS_MENU_OFF_CENTER,
+ 2, 40, initial_3);
+ popup_menu_option(interface_item, menu_quote(quote_options_item3a));
+ popup_menu_option(interface_item, menu_quote(quote_options_item3b));
+
+ popup_blank(SPACE_BETWEEN);
+
+
+ fade_item = popup_menu(menu_quote(quote_options_item4),
+ POPUP_CENTER, POPUP_FILL, OPTIONS_MENU_ITEM_WIDTH,
+ OPTIONS_MENU_OFF_CENTER,
+ 3, 40, initial_4);
+ popup_menu_option(fade_item, menu_quote(quote_options_item4a));
+ popup_menu_option(fade_item, menu_quote(quote_options_item4b));
+ popup_menu_option(fade_item, menu_quote(quote_options_item4c));
+
+ popup_blank(SPACE_BETWEEN);
+
+
+ panning_item = popup_menu(menu_quote(quote_options_item5),
+ POPUP_CENTER, POPUP_FILL, OPTIONS_MENU_ITEM_WIDTH,
+ OPTIONS_MENU_OFF_CENTER,
+ 3, 40, initial_5);
+ popup_menu_option(panning_item, menu_quote(quote_options_item5a));
+ popup_menu_option(panning_item, menu_quote(quote_options_item5b));
+ popup_menu_option(panning_item, menu_quote(quote_options_item5c));
+
+
+
+ done_button = popup_button(menu_quote(quote_menu_done), POPUP_LEFT);
+ cancel_button = popup_cancel_button(menu_quote(quote_menu_cancel));
+
+ popup_width_force(OPTIONS_MENU_FORCE_WIDTH);
+
+ result = popup_execute();
+
+ kernel.activate_menu = GAME_MAIN_MENU;
+
+ if (result == cancel_button) {
+ switch (game_menu_popup->key) {
+ case alt_x_key:
+ case ctrl_x_key:
+ case alt_q_key:
+ case ctrl_q_key:
+ game.going = false;
+ kernel.activate_menu = GAME_NO_MENU;
+ break;
+
+ case f1_key:
+ kernel.activate_menu = GAME_MAIN_MENU;
+ break;
+
+ case f2_key:
+ kernel.activate_menu = GAME_SAVE_MENU;
+ break;
+
+ case f3_key:
+ kernel.activate_menu = GAME_RESTORE_MENU;
+ break;
+
+ case f4_key:
+ kernel.activate_menu = GAME_SCORE_MENU;
+ break;
+
+ case f5_key:
+ kernel.activate_menu = GAME_MAIN_MENU;
+ break;
+
+ default:
+ kernel.activate_menu = GAME_MAIN_MENU;
+ break;
+ }
+ }
+
+ if (result == done_button) {
+ config_file.music_flag = !music_item->list->picked_element;
+ config_file.sound_flag = !sound_item->list->picked_element;
+ config_file.speech_flag = !speech_item->list->picked_element;
+ config_file.interface_hotspots = interface_item->list->picked_element;
+ config_file.screen_fade = fade_item->list->picked_element;
+ config_file.panning_speed = panning_item->list->picked_element;
+
+ global_write_config_file();
+ global_load_config_parameters();
+
+ kernel.activate_menu = GAME_NO_MENU;
+ }
+
+ if ((former_music != config_file.music_flag) ||
+ (former_sound != config_file.sound_flag)) {
+ game_exec_function(section_music_reset_pointer);
+ }
+
+ if (!config_file.speech_flag) {
+ if (speech_system_active)
+ speech_all_off();
+ }
+
+ popup_dialog_destroy();
+#endif
+}
+
+static void global_menu_difficulty() {
+#if 0
+ PopupItem *easy_item;
+ PopupItem *result;
+
+ popup_dialog_create(game_menu_popup, GAME_DIALOG_HEAP, 20);
+
+ popup_message(menu_quote(quote_difficulty_title), POPUP_CENTER, POPUP_FILL);
+ popup_blank(6);
+
+ easy_item = popup_menu(menu_quote(quote_difficulty_item1),
+ POPUP_CENTER, POPUP_FILL, MAIN_MENU_ITEM_WIDTH, 0,
+ 0, 0, 0);
+
+ popup_blank(SPACE_BETWEEN);
+
+ (void)popup_menu(menu_quote(quote_difficulty_item2),
+ POPUP_CENTER, POPUP_FILL, MAIN_MENU_ITEM_WIDTH, 0,
+ 0, 0, 0);
+
+
+ popup_width_force(DIFFICULTY_MENU_FORCE_WIDTH);
+
+ game_menu_popup->cancel_item = NULL;
+
+ result = popup_execute();
+
+ kernel.activate_menu = GAME_NO_MENU;
+
+ if (result == easy_item) {
+ game.difficulty = EASY_MODE;
+ } else {
+ game.difficulty = HARD_MODE;
+ }
+
+ if (result == NULL) {
+ game.going = false;
+ }
+
+ switch (game_menu_popup->key) {
+ case alt_x_key:
+ case ctrl_x_key:
+ case alt_q_key:
+ case ctrl_q_key:
+ case esc_key:
+ game.going = false;
+ break;
+ }
+
+ popup_dialog_destroy();
+#endif
+}
+
+static void global_menu_main() {
+#if 0
+ PopupItem *save_item;
+ PopupItem *restore_item;
+ PopupItem *score_item;
+ PopupItem *options_item;
+ PopupItem *resume_item;
+ PopupItem *quit_item;
+ PopupItem *result;
+
+ popup_dialog_create(game_menu_popup, GAME_DIALOG_HEAP, 20);
+
+ popup_sprite(box_param.logo, 1, POPUP_CENTER, POPUP_FILL);
+ popup_blank(6);
+
+ save_item = popup_menu(menu_quote(quote_main_item1),
+ POPUP_CENTER, POPUP_FILL, MAIN_MENU_ITEM_WIDTH, 0,
+ 0, 0, 0);
+
+ popup_blank(SPACE_BETWEEN);
+
+ restore_item = popup_menu(menu_quote(quote_main_item2),
+ POPUP_CENTER, POPUP_FILL, MAIN_MENU_ITEM_WIDTH, 0,
+ 0, 0, 0);
+
+ popup_blank(SPACE_BETWEEN);
+
+ score_item = popup_menu(menu_quote(quote_main_item6),
+ POPUP_CENTER, POPUP_FILL, MAIN_MENU_ITEM_WIDTH, 0,
+ 0, 0, 0);
+
+ popup_blank(SPACE_BETWEEN);
+
+ options_item = popup_menu(menu_quote(quote_main_item3),
+ POPUP_CENTER, POPUP_FILL, MAIN_MENU_ITEM_WIDTH, 0,
+ 0, 0, 0);
+
+ popup_blank(SPACE_BETWEEN);
+
+ resume_item = popup_menu(menu_quote(quote_main_item4),
+ POPUP_CENTER, POPUP_FILL, MAIN_MENU_ITEM_WIDTH, 0,
+ 0, 0, 0);
+
+ popup_blank(SPACE_BETWEEN);
+
+ quit_item = popup_menu(menu_quote(quote_main_item5),
+ POPUP_CENTER, POPUP_FILL, MAIN_MENU_ITEM_WIDTH, 0,
+ 0, 0, 0);
+
+ popup_width_force(MAIN_MENU_FORCE_WIDTH);
+ game_menu_popup->cancel_item = resume_item;
+
+ result = popup_execute();
+
+ if (result == save_item) {
+ kernel.activate_menu = GAME_SAVE_MENU;
+ } else if (result == restore_item) {
+ kernel.activate_menu = GAME_RESTORE_MENU;
+ } else if (result == options_item) {
+ kernel.activate_menu = GAME_OPTIONS_MENU;
+ } else if (result == score_item) {
+ kernel.activate_menu = GAME_SCORE_MENU;
+ } else {
+ kernel.activate_menu = GAME_NO_MENU;
+ }
+
+ if (result == quit_item)
+ game.going = false;
+
+ switch (game_menu_popup->key) {
+ case alt_q_key:
+ case alt_x_key:
+ case ctrl_q_key:
+ game.going = false;
+ kernel.activate_menu = GAME_NO_MENU;
+ break;
+
+ case f5_key:
+ kernel.activate_menu = GAME_SAVE_MENU;
+ break;
+
+ case f7_key:
+ kernel.activate_menu = GAME_RESTORE_MENU;
+ break;
+
+ case f8_key:
+ kernel.activate_menu = GAME_SCORE_MENU;
+ break;
+
+ case f10_key:
+ kernel.activate_menu = GAME_OPTIONS_MENU;
+ break;
+
+ default:
+ break;
+ }
+#endif
+}
+
+void global_game_menu() {
+ bool loaded = false;
+
+ if (box_param.series == NULL) {
+ Common::strcpy_s(box_param.name, "*BOX");
+ if (popup_box_load())
+ goto done;
+ loaded = true;
+ }
+
+ game_menu_setup();
+ g_engine->flushKeys();
+
+ do {
+ switch (kernel.activate_menu) {
+ case GAME_MAIN_MENU:
+ global_menu_main();
+ break;
+ case GAME_SAVE_MENU:
+ if (config_file.original_save_load) {
+ global_menu_save_restore(true);
+ } else {
+ kernel.activate_menu = GAME_NO_MENU;
+ g_engine->saveGameDialog();
+ }
+ break;
+ case GAME_RESTORE_MENU:
+ if (config_file.original_save_load) {
+ global_menu_save_restore(false);
+ } else {
+ kernel.activate_menu = GAME_NO_MENU;
+ if (g_engine->loadGameDialog())
+ // Dummy name to flag that load was successful
+ Common::strcpy_s(save_game_buf, "OK");
+ }
+ break;
+ case GAME_OPTIONS_MENU:
+ global_menu_options();
+ break;
+ case GAME_DIFFICULTY_MENU:
+ global_menu_difficulty();
+ break;
+ case GAME_SCORE_MENU:
+ global_menu_score();
+ break;
+ default:
+ kernel.activate_menu = GAME_NO_MENU;
+ break;
+ }
+ } while (!g_engine->shouldQuit() && game.going && kernel.activate_menu != GAME_NO_MENU);
+
+ game_menu_shutdown();
+
+ if (loaded) {
+ sprite_free(&box_param.menu, true);
+ sprite_free(&box_param.logo, true);
+ sprite_free(&box_param.series, true);
+ }
+
+done:
+ ;
+}
+
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/menus.h b/engines/mads/madsv2/forest/menus.h
new file mode 100644
index 00000000000..2b0635f7cb3
--- /dev/null
+++ b/engines/mads/madsv2/forest/menus.h
@@ -0,0 +1,40 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_MENUS_H
+#define MADS_FOREST_MENUS_H
+
+#include "common/scummsys.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+
+extern void global_menu_system_init();
+extern void global_menu_system_shutdown();
+extern void global_emergency_save();
+extern void global_game_menu();
+
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room101.cpp b/engines/mads/madsv2/forest/rooms/room101.cpp
new file mode 100644
index 00000000000..204d289745d
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room101.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room101.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_101_init() {
+}
+
+static void room_101_daemon() {
+}
+
+static void room_101_pre_parser() {
+}
+
+static void room_101_parser() {
+}
+
+void room_101_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_101_preload() {
+ room_init_code_pointer = room_101_init;
+ room_pre_parser_code_pointer = room_101_pre_parser;
+ room_parser_code_pointer = room_101_parser;
+ room_daemon_code_pointer = room_101_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room101.h b/engines/mads/madsv2/forest/rooms/room101.h
new file mode 100644
index 00000000000..ac8e31fd121
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room101.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_101_H
+#define MADS_FOREST_ROOMS_101_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_101_preload();
+extern void room_101_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room103.cpp b/engines/mads/madsv2/forest/rooms/room103.cpp
new file mode 100644
index 00000000000..a019225a50d
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room103.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room103.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_103_init() {
+}
+
+static void room_103_daemon() {
+}
+
+static void room_103_pre_parser() {
+}
+
+static void room_103_parser() {
+}
+
+void room_103_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_103_preload() {
+ room_init_code_pointer = room_103_init;
+ room_pre_parser_code_pointer = room_103_pre_parser;
+ room_parser_code_pointer = room_103_parser;
+ room_daemon_code_pointer = room_103_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room103.h b/engines/mads/madsv2/forest/rooms/room103.h
new file mode 100644
index 00000000000..78fb07904e4
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room103.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_103_H
+#define MADS_FOREST_ROOMS_103_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_103_preload();
+extern void room_103_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room104.cpp b/engines/mads/madsv2/forest/rooms/room104.cpp
new file mode 100644
index 00000000000..680889df50d
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room104.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room104.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_104_init() {
+}
+
+static void room_104_daemon() {
+}
+
+static void room_104_pre_parser() {
+}
+
+static void room_104_parser() {
+}
+
+void room_104_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_104_preload() {
+ room_init_code_pointer = room_104_init;
+ room_pre_parser_code_pointer = room_104_pre_parser;
+ room_parser_code_pointer = room_104_parser;
+ room_daemon_code_pointer = room_104_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room104.h b/engines/mads/madsv2/forest/rooms/room104.h
new file mode 100644
index 00000000000..803eb127a36
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room104.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_104_H
+#define MADS_FOREST_ROOMS_104_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_104_preload();
+extern void room_104_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room106.cpp b/engines/mads/madsv2/forest/rooms/room106.cpp
new file mode 100644
index 00000000000..46646593123
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room106.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room106.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_106_init() {
+}
+
+static void room_106_daemon() {
+}
+
+static void room_106_pre_parser() {
+}
+
+static void room_106_parser() {
+}
+
+void room_106_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_106_preload() {
+ room_init_code_pointer = room_106_init;
+ room_pre_parser_code_pointer = room_106_pre_parser;
+ room_parser_code_pointer = room_106_parser;
+ room_daemon_code_pointer = room_106_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room106.h b/engines/mads/madsv2/forest/rooms/room106.h
new file mode 100644
index 00000000000..dffcf0c2682
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room106.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_106_H
+#define MADS_FOREST_ROOMS_106_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_106_preload();
+extern void room_106_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room107.cpp b/engines/mads/madsv2/forest/rooms/room107.cpp
new file mode 100644
index 00000000000..4e4075d4524
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room107.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room107.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_107_init() {
+}
+
+static void room_107_daemon() {
+}
+
+static void room_107_pre_parser() {
+}
+
+static void room_107_parser() {
+}
+
+void room_107_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_107_preload() {
+ room_init_code_pointer = room_107_init;
+ room_pre_parser_code_pointer = room_107_pre_parser;
+ room_parser_code_pointer = room_107_parser;
+ room_daemon_code_pointer = room_107_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room107.h b/engines/mads/madsv2/forest/rooms/room107.h
new file mode 100644
index 00000000000..3a733abbcd3
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room107.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_107_H
+#define MADS_FOREST_ROOMS_107_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_107_preload();
+extern void room_107_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room199.cpp b/engines/mads/madsv2/forest/rooms/room199.cpp
new file mode 100644
index 00000000000..1ad9e804b96
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room199.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room199.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_199_init() {
+}
+
+static void room_199_daemon() {
+}
+
+static void room_199_pre_parser() {
+}
+
+static void room_199_parser() {
+}
+
+void room_199_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_199_preload() {
+ room_init_code_pointer = room_199_init;
+ room_pre_parser_code_pointer = room_199_pre_parser;
+ room_parser_code_pointer = room_199_parser;
+ room_daemon_code_pointer = room_199_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room199.h b/engines/mads/madsv2/forest/rooms/room199.h
new file mode 100644
index 00000000000..a777a883676
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room199.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_199_H
+#define MADS_FOREST_ROOMS_199_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_199_preload();
+extern void room_199_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room201.cpp b/engines/mads/madsv2/forest/rooms/room201.cpp
new file mode 100644
index 00000000000..9fc82b87e5f
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room201.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room201.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_201_init() {
+}
+
+static void room_201_daemon() {
+}
+
+static void room_201_pre_parser() {
+}
+
+static void room_201_parser() {
+}
+
+void room_201_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_201_preload() {
+ room_init_code_pointer = room_201_init;
+ room_pre_parser_code_pointer = room_201_pre_parser;
+ room_parser_code_pointer = room_201_parser;
+ room_daemon_code_pointer = room_201_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room201.h b/engines/mads/madsv2/forest/rooms/room201.h
new file mode 100644
index 00000000000..3d452fa6f65
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room201.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_201_H
+#define MADS_FOREST_ROOMS_201_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_201_preload();
+extern void room_201_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room203.cpp b/engines/mads/madsv2/forest/rooms/room203.cpp
new file mode 100644
index 00000000000..7dba244347d
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room203.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room203.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_203_init() {
+}
+
+static void room_203_daemon() {
+}
+
+static void room_203_pre_parser() {
+}
+
+static void room_203_parser() {
+}
+
+void room_203_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_203_preload() {
+ room_init_code_pointer = room_203_init;
+ room_pre_parser_code_pointer = room_203_pre_parser;
+ room_parser_code_pointer = room_203_parser;
+ room_daemon_code_pointer = room_203_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room203.h b/engines/mads/madsv2/forest/rooms/room203.h
new file mode 100644
index 00000000000..f41afaf244b
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room203.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_203_H
+#define MADS_FOREST_ROOMS_203_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_203_preload();
+extern void room_203_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room204.cpp b/engines/mads/madsv2/forest/rooms/room204.cpp
new file mode 100644
index 00000000000..a3265ab6f87
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room204.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room204.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_204_init() {
+}
+
+static void room_204_daemon() {
+}
+
+static void room_204_pre_parser() {
+}
+
+static void room_204_parser() {
+}
+
+void room_204_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_204_preload() {
+ room_init_code_pointer = room_204_init;
+ room_pre_parser_code_pointer = room_204_pre_parser;
+ room_parser_code_pointer = room_204_parser;
+ room_daemon_code_pointer = room_204_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room204.h b/engines/mads/madsv2/forest/rooms/room204.h
new file mode 100644
index 00000000000..5b60edffc52
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room204.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_204_H
+#define MADS_FOREST_ROOMS_204_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_204_preload();
+extern void room_204_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room205.cpp b/engines/mads/madsv2/forest/rooms/room205.cpp
new file mode 100644
index 00000000000..f0ba29ce313
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room205.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room205.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_205_init() {
+}
+
+static void room_205_daemon() {
+}
+
+static void room_205_pre_parser() {
+}
+
+static void room_205_parser() {
+}
+
+void room_205_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_205_preload() {
+ room_init_code_pointer = room_205_init;
+ room_pre_parser_code_pointer = room_205_pre_parser;
+ room_parser_code_pointer = room_205_parser;
+ room_daemon_code_pointer = room_205_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room205.h b/engines/mads/madsv2/forest/rooms/room205.h
new file mode 100644
index 00000000000..5c961acdbff
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room205.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_205_H
+#define MADS_FOREST_ROOMS_205_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_205_preload();
+extern void room_205_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room210.cpp b/engines/mads/madsv2/forest/rooms/room210.cpp
new file mode 100644
index 00000000000..ae17ec3faae
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room210.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room210.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_210_init() {
+}
+
+static void room_210_daemon() {
+}
+
+static void room_210_pre_parser() {
+}
+
+static void room_210_parser() {
+}
+
+void room_210_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_210_preload() {
+ room_init_code_pointer = room_210_init;
+ room_pre_parser_code_pointer = room_210_pre_parser;
+ room_parser_code_pointer = room_210_parser;
+ room_daemon_code_pointer = room_210_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room210.h b/engines/mads/madsv2/forest/rooms/room210.h
new file mode 100644
index 00000000000..e33943b7497
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room210.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_210_H
+#define MADS_FOREST_ROOMS_210_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_210_preload();
+extern void room_210_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room211.cpp b/engines/mads/madsv2/forest/rooms/room211.cpp
new file mode 100644
index 00000000000..8173536b2dd
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room211.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room211.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_211_init() {
+}
+
+static void room_211_daemon() {
+}
+
+static void room_211_pre_parser() {
+}
+
+static void room_211_parser() {
+}
+
+void room_211_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_211_preload() {
+ room_init_code_pointer = room_211_init;
+ room_pre_parser_code_pointer = room_211_pre_parser;
+ room_parser_code_pointer = room_211_parser;
+ room_daemon_code_pointer = room_211_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room211.h b/engines/mads/madsv2/forest/rooms/room211.h
new file mode 100644
index 00000000000..acd4d55057d
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room211.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_211_H
+#define MADS_FOREST_ROOMS_211_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_211_preload();
+extern void room_211_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room220.cpp b/engines/mads/madsv2/forest/rooms/room220.cpp
new file mode 100644
index 00000000000..83679c727bc
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room220.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room220.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_220_init() {
+}
+
+static void room_220_daemon() {
+}
+
+static void room_220_pre_parser() {
+}
+
+static void room_220_parser() {
+}
+
+void room_220_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_220_preload() {
+ room_init_code_pointer = room_220_init;
+ room_pre_parser_code_pointer = room_220_pre_parser;
+ room_parser_code_pointer = room_220_parser;
+ room_daemon_code_pointer = room_220_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room220.h b/engines/mads/madsv2/forest/rooms/room220.h
new file mode 100644
index 00000000000..eefc984dede
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room220.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_220_H
+#define MADS_FOREST_ROOMS_220_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_220_preload();
+extern void room_220_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room221.cpp b/engines/mads/madsv2/forest/rooms/room221.cpp
new file mode 100644
index 00000000000..81bb0747d0a
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room221.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room221.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_221_init() {
+}
+
+static void room_221_daemon() {
+}
+
+static void room_221_pre_parser() {
+}
+
+static void room_221_parser() {
+}
+
+void room_221_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_221_preload() {
+ room_init_code_pointer = room_221_init;
+ room_pre_parser_code_pointer = room_221_pre_parser;
+ room_parser_code_pointer = room_221_parser;
+ room_daemon_code_pointer = room_221_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room221.h b/engines/mads/madsv2/forest/rooms/room221.h
new file mode 100644
index 00000000000..727083335cf
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room221.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_221_H
+#define MADS_FOREST_ROOMS_221_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_221_preload();
+extern void room_221_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room301.cpp b/engines/mads/madsv2/forest/rooms/room301.cpp
new file mode 100644
index 00000000000..bc879fa1355
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room301.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room301.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_301_init() {
+}
+
+static void room_301_daemon() {
+}
+
+static void room_301_pre_parser() {
+}
+
+static void room_301_parser() {
+}
+
+void room_301_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_301_preload() {
+ room_init_code_pointer = room_301_init;
+ room_pre_parser_code_pointer = room_301_pre_parser;
+ room_parser_code_pointer = room_301_parser;
+ room_daemon_code_pointer = room_301_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room301.h b/engines/mads/madsv2/forest/rooms/room301.h
new file mode 100644
index 00000000000..3b4d6a2ad63
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room301.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_301_H
+#define MADS_FOREST_ROOMS_301_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_301_preload();
+extern void room_301_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room302.cpp b/engines/mads/madsv2/forest/rooms/room302.cpp
new file mode 100644
index 00000000000..fe16ebcf227
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room302.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room302.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_302_init() {
+}
+
+static void room_302_daemon() {
+}
+
+static void room_302_pre_parser() {
+}
+
+static void room_302_parser() {
+}
+
+void room_302_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_302_preload() {
+ room_init_code_pointer = room_302_init;
+ room_pre_parser_code_pointer = room_302_pre_parser;
+ room_parser_code_pointer = room_302_parser;
+ room_daemon_code_pointer = room_302_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room302.h b/engines/mads/madsv2/forest/rooms/room302.h
new file mode 100644
index 00000000000..3954e480767
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room302.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_302_H
+#define MADS_FOREST_ROOMS_302_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_302_preload();
+extern void room_302_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room303.cpp b/engines/mads/madsv2/forest/rooms/room303.cpp
new file mode 100644
index 00000000000..6d476f668ff
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room303.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room303.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_303_init() {
+}
+
+static void room_303_daemon() {
+}
+
+static void room_303_pre_parser() {
+}
+
+static void room_303_parser() {
+}
+
+void room_303_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_303_preload() {
+ room_init_code_pointer = room_303_init;
+ room_pre_parser_code_pointer = room_303_pre_parser;
+ room_parser_code_pointer = room_303_parser;
+ room_daemon_code_pointer = room_303_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room303.h b/engines/mads/madsv2/forest/rooms/room303.h
new file mode 100644
index 00000000000..ee4b4ef75fa
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room303.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_303_H
+#define MADS_FOREST_ROOMS_303_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_303_preload();
+extern void room_303_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room304.cpp b/engines/mads/madsv2/forest/rooms/room304.cpp
new file mode 100644
index 00000000000..105c64b1714
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room304.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room304.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_304_init() {
+}
+
+static void room_304_daemon() {
+}
+
+static void room_304_pre_parser() {
+}
+
+static void room_304_parser() {
+}
+
+void room_304_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_304_preload() {
+ room_init_code_pointer = room_304_init;
+ room_pre_parser_code_pointer = room_304_pre_parser;
+ room_parser_code_pointer = room_304_parser;
+ room_daemon_code_pointer = room_304_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room304.h b/engines/mads/madsv2/forest/rooms/room304.h
new file mode 100644
index 00000000000..bbc85359cb4
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room304.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_304_H
+#define MADS_FOREST_ROOMS_304_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_304_preload();
+extern void room_304_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room305.cpp b/engines/mads/madsv2/forest/rooms/room305.cpp
new file mode 100644
index 00000000000..b789bcd6474
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room305.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room305.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_305_init() {
+}
+
+static void room_305_daemon() {
+}
+
+static void room_305_pre_parser() {
+}
+
+static void room_305_parser() {
+}
+
+void room_305_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_305_preload() {
+ room_init_code_pointer = room_305_init;
+ room_pre_parser_code_pointer = room_305_pre_parser;
+ room_parser_code_pointer = room_305_parser;
+ room_daemon_code_pointer = room_305_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room305.h b/engines/mads/madsv2/forest/rooms/room305.h
new file mode 100644
index 00000000000..1a55b1d83a2
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room305.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_305_H
+#define MADS_FOREST_ROOMS_305_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_305_preload();
+extern void room_305_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room306.cpp b/engines/mads/madsv2/forest/rooms/room306.cpp
new file mode 100644
index 00000000000..27fbacdc6cb
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room306.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room306.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_306_init() {
+}
+
+static void room_306_daemon() {
+}
+
+static void room_306_pre_parser() {
+}
+
+static void room_306_parser() {
+}
+
+void room_306_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_306_preload() {
+ room_init_code_pointer = room_306_init;
+ room_pre_parser_code_pointer = room_306_pre_parser;
+ room_parser_code_pointer = room_306_parser;
+ room_daemon_code_pointer = room_306_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room306.h b/engines/mads/madsv2/forest/rooms/room306.h
new file mode 100644
index 00000000000..57f2e70ff9b
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room306.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_306_H
+#define MADS_FOREST_ROOMS_306_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_306_preload();
+extern void room_306_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room307.cpp b/engines/mads/madsv2/forest/rooms/room307.cpp
new file mode 100644
index 00000000000..409ed029d8b
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room307.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room307.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_307_init() {
+}
+
+static void room_307_daemon() {
+}
+
+static void room_307_pre_parser() {
+}
+
+static void room_307_parser() {
+}
+
+void room_307_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_307_preload() {
+ room_init_code_pointer = room_307_init;
+ room_pre_parser_code_pointer = room_307_pre_parser;
+ room_parser_code_pointer = room_307_parser;
+ room_daemon_code_pointer = room_307_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room307.h b/engines/mads/madsv2/forest/rooms/room307.h
new file mode 100644
index 00000000000..e303654ec9f
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room307.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_307_H
+#define MADS_FOREST_ROOMS_307_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_307_preload();
+extern void room_307_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room308.cpp b/engines/mads/madsv2/forest/rooms/room308.cpp
new file mode 100644
index 00000000000..8555f6dbd6d
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room308.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room308.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_308_init() {
+}
+
+static void room_308_daemon() {
+}
+
+static void room_308_pre_parser() {
+}
+
+static void room_308_parser() {
+}
+
+void room_308_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_308_preload() {
+ room_init_code_pointer = room_308_init;
+ room_pre_parser_code_pointer = room_308_pre_parser;
+ room_parser_code_pointer = room_308_parser;
+ room_daemon_code_pointer = room_308_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room308.h b/engines/mads/madsv2/forest/rooms/room308.h
new file mode 100644
index 00000000000..878bb459214
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room308.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_308_H
+#define MADS_FOREST_ROOMS_308_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_308_preload();
+extern void room_308_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room321.cpp b/engines/mads/madsv2/forest/rooms/room321.cpp
new file mode 100644
index 00000000000..7325c714f9f
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room321.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room321.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_321_init() {
+}
+
+static void room_321_daemon() {
+}
+
+static void room_321_pre_parser() {
+}
+
+static void room_321_parser() {
+}
+
+void room_321_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_321_preload() {
+ room_init_code_pointer = room_321_init;
+ room_pre_parser_code_pointer = room_321_pre_parser;
+ room_parser_code_pointer = room_321_parser;
+ room_daemon_code_pointer = room_321_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room321.h b/engines/mads/madsv2/forest/rooms/room321.h
new file mode 100644
index 00000000000..50d9b82d4ef
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room321.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_321_H
+#define MADS_FOREST_ROOMS_321_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_321_preload();
+extern void room_321_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room322.cpp b/engines/mads/madsv2/forest/rooms/room322.cpp
new file mode 100644
index 00000000000..07c0a80e45c
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room322.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room322.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_322_init() {
+}
+
+static void room_322_daemon() {
+}
+
+static void room_322_pre_parser() {
+}
+
+static void room_322_parser() {
+}
+
+void room_322_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_322_preload() {
+ room_init_code_pointer = room_322_init;
+ room_pre_parser_code_pointer = room_322_pre_parser;
+ room_parser_code_pointer = room_322_parser;
+ room_daemon_code_pointer = room_322_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room322.h b/engines/mads/madsv2/forest/rooms/room322.h
new file mode 100644
index 00000000000..7f17842cbfe
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room322.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_322_H
+#define MADS_FOREST_ROOMS_322_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_322_preload();
+extern void room_322_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room401.cpp b/engines/mads/madsv2/forest/rooms/room401.cpp
new file mode 100644
index 00000000000..626d2f7cb9e
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room401.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room401.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_401_init() {
+}
+
+static void room_401_daemon() {
+}
+
+static void room_401_pre_parser() {
+}
+
+static void room_401_parser() {
+}
+
+void room_401_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_401_preload() {
+ room_init_code_pointer = room_401_init;
+ room_pre_parser_code_pointer = room_401_pre_parser;
+ room_parser_code_pointer = room_401_parser;
+ room_daemon_code_pointer = room_401_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room401.h b/engines/mads/madsv2/forest/rooms/room401.h
new file mode 100644
index 00000000000..8a278732cb1
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room401.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_401_H
+#define MADS_FOREST_ROOMS_401_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_401_preload();
+extern void room_401_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room402.cpp b/engines/mads/madsv2/forest/rooms/room402.cpp
new file mode 100644
index 00000000000..34273aa93ce
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room402.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room402.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_402_init() {
+}
+
+static void room_402_daemon() {
+}
+
+static void room_402_pre_parser() {
+}
+
+static void room_402_parser() {
+}
+
+void room_402_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_402_preload() {
+ room_init_code_pointer = room_402_init;
+ room_pre_parser_code_pointer = room_402_pre_parser;
+ room_parser_code_pointer = room_402_parser;
+ room_daemon_code_pointer = room_402_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room402.h b/engines/mads/madsv2/forest/rooms/room402.h
new file mode 100644
index 00000000000..59b9629dd34
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room402.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_402_H
+#define MADS_FOREST_ROOMS_402_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_402_preload();
+extern void room_402_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room403.cpp b/engines/mads/madsv2/forest/rooms/room403.cpp
new file mode 100644
index 00000000000..35bcb54e03f
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room403.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room403.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_403_init() {
+}
+
+static void room_403_daemon() {
+}
+
+static void room_403_pre_parser() {
+}
+
+static void room_403_parser() {
+}
+
+void room_403_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_403_preload() {
+ room_init_code_pointer = room_403_init;
+ room_pre_parser_code_pointer = room_403_pre_parser;
+ room_parser_code_pointer = room_403_parser;
+ room_daemon_code_pointer = room_403_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room403.h b/engines/mads/madsv2/forest/rooms/room403.h
new file mode 100644
index 00000000000..a12e4c0cdf1
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room403.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_403_H
+#define MADS_FOREST_ROOMS_403_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_403_preload();
+extern void room_403_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room404.cpp b/engines/mads/madsv2/forest/rooms/room404.cpp
new file mode 100644
index 00000000000..a0e1dff1e99
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room404.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room404.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_404_init() {
+}
+
+static void room_404_daemon() {
+}
+
+static void room_404_pre_parser() {
+}
+
+static void room_404_parser() {
+}
+
+void room_404_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_404_preload() {
+ room_init_code_pointer = room_404_init;
+ room_pre_parser_code_pointer = room_404_pre_parser;
+ room_parser_code_pointer = room_404_parser;
+ room_daemon_code_pointer = room_404_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room404.h b/engines/mads/madsv2/forest/rooms/room404.h
new file mode 100644
index 00000000000..08b49e94a69
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room404.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_404_H
+#define MADS_FOREST_ROOMS_404_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_404_preload();
+extern void room_404_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room405.cpp b/engines/mads/madsv2/forest/rooms/room405.cpp
new file mode 100644
index 00000000000..794e67c6d6e
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room405.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room405.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_405_init() {
+}
+
+static void room_405_daemon() {
+}
+
+static void room_405_pre_parser() {
+}
+
+static void room_405_parser() {
+}
+
+void room_405_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_405_preload() {
+ room_init_code_pointer = room_405_init;
+ room_pre_parser_code_pointer = room_405_pre_parser;
+ room_parser_code_pointer = room_405_parser;
+ room_daemon_code_pointer = room_405_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room405.h b/engines/mads/madsv2/forest/rooms/room405.h
new file mode 100644
index 00000000000..ec0d4dacced
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room405.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_405_H
+#define MADS_FOREST_ROOMS_405_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_405_preload();
+extern void room_405_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room420.cpp b/engines/mads/madsv2/forest/rooms/room420.cpp
new file mode 100644
index 00000000000..e3ccd7685e7
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room420.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room420.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_420_init() {
+}
+
+static void room_420_daemon() {
+}
+
+static void room_420_pre_parser() {
+}
+
+static void room_420_parser() {
+}
+
+void room_420_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_420_preload() {
+ room_init_code_pointer = room_420_init;
+ room_pre_parser_code_pointer = room_420_pre_parser;
+ room_parser_code_pointer = room_420_parser;
+ room_daemon_code_pointer = room_420_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room420.h b/engines/mads/madsv2/forest/rooms/room420.h
new file mode 100644
index 00000000000..db92afc132e
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room420.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_420_H
+#define MADS_FOREST_ROOMS_420_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_420_preload();
+extern void room_420_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room501.cpp b/engines/mads/madsv2/forest/rooms/room501.cpp
new file mode 100644
index 00000000000..c2075289b60
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room501.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room501.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_501_init() {
+}
+
+static void room_501_daemon() {
+}
+
+static void room_501_pre_parser() {
+}
+
+static void room_501_parser() {
+}
+
+void room_501_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_501_preload() {
+ room_init_code_pointer = room_501_init;
+ room_pre_parser_code_pointer = room_501_pre_parser;
+ room_parser_code_pointer = room_501_parser;
+ room_daemon_code_pointer = room_501_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room501.h b/engines/mads/madsv2/forest/rooms/room501.h
new file mode 100644
index 00000000000..cf4c880bbf2
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room501.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_501_H
+#define MADS_FOREST_ROOMS_501_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_501_preload();
+extern void room_501_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room503.cpp b/engines/mads/madsv2/forest/rooms/room503.cpp
new file mode 100644
index 00000000000..0c66b325ff4
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room503.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room503.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_503_init() {
+}
+
+static void room_503_daemon() {
+}
+
+static void room_503_pre_parser() {
+}
+
+static void room_503_parser() {
+}
+
+void room_503_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_503_preload() {
+ room_init_code_pointer = room_503_init;
+ room_pre_parser_code_pointer = room_503_pre_parser;
+ room_parser_code_pointer = room_503_parser;
+ room_daemon_code_pointer = room_503_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room503.h b/engines/mads/madsv2/forest/rooms/room503.h
new file mode 100644
index 00000000000..e71795c42af
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room503.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_503_H
+#define MADS_FOREST_ROOMS_503_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_503_preload();
+extern void room_503_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room509.cpp b/engines/mads/madsv2/forest/rooms/room509.cpp
new file mode 100644
index 00000000000..50881aa9434
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room509.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room509.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_509_init() {
+}
+
+static void room_509_daemon() {
+}
+
+static void room_509_pre_parser() {
+}
+
+static void room_509_parser() {
+}
+
+void room_509_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_509_preload() {
+ room_init_code_pointer = room_509_init;
+ room_pre_parser_code_pointer = room_509_pre_parser;
+ room_parser_code_pointer = room_509_parser;
+ room_daemon_code_pointer = room_509_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room509.h b/engines/mads/madsv2/forest/rooms/room509.h
new file mode 100644
index 00000000000..b8db30bda3b
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room509.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_509_H
+#define MADS_FOREST_ROOMS_509_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_509_preload();
+extern void room_509_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room510.cpp b/engines/mads/madsv2/forest/rooms/room510.cpp
new file mode 100644
index 00000000000..815c6ed21e3
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room510.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room510.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_510_init() {
+}
+
+static void room_510_daemon() {
+}
+
+static void room_510_pre_parser() {
+}
+
+static void room_510_parser() {
+}
+
+void room_510_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_510_preload() {
+ room_init_code_pointer = room_510_init;
+ room_pre_parser_code_pointer = room_510_pre_parser;
+ room_parser_code_pointer = room_510_parser;
+ room_daemon_code_pointer = room_510_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room510.h b/engines/mads/madsv2/forest/rooms/room510.h
new file mode 100644
index 00000000000..eecc96b3ced
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room510.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_510_H
+#define MADS_FOREST_ROOMS_510_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_510_preload();
+extern void room_510_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room520.cpp b/engines/mads/madsv2/forest/rooms/room520.cpp
new file mode 100644
index 00000000000..f907dd7d515
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room520.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room520.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_520_init() {
+}
+
+static void room_520_daemon() {
+}
+
+static void room_520_pre_parser() {
+}
+
+static void room_520_parser() {
+}
+
+void room_520_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_520_preload() {
+ room_init_code_pointer = room_520_init;
+ room_pre_parser_code_pointer = room_520_pre_parser;
+ room_parser_code_pointer = room_520_parser;
+ room_daemon_code_pointer = room_520_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room520.h b/engines/mads/madsv2/forest/rooms/room520.h
new file mode 100644
index 00000000000..4f77e8f3e7b
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room520.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_520_H
+#define MADS_FOREST_ROOMS_520_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_520_preload();
+extern void room_520_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room901.cpp b/engines/mads/madsv2/forest/rooms/room901.cpp
new file mode 100644
index 00000000000..d712e4bf527
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room901.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room901.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_901_init() {
+}
+
+static void room_901_daemon() {
+}
+
+static void room_901_pre_parser() {
+}
+
+static void room_901_parser() {
+}
+
+void room_901_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_901_preload() {
+ room_init_code_pointer = room_901_init;
+ room_pre_parser_code_pointer = room_901_pre_parser;
+ room_parser_code_pointer = room_901_parser;
+ room_daemon_code_pointer = room_901_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room901.h b/engines/mads/madsv2/forest/rooms/room901.h
new file mode 100644
index 00000000000..dc4c9893ad5
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room901.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_901_H
+#define MADS_FOREST_ROOMS_901_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_901_preload();
+extern void room_901_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room903.cpp b/engines/mads/madsv2/forest/rooms/room903.cpp
new file mode 100644
index 00000000000..0cb0de40fa4
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room903.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room903.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
+
+static Scratch scratch;
+
+#define local (&scratch)
+#define ss local->sprite
+#define seq local->sequence
+#define aa local->animation
+
+
+static void room_903_init() {
+}
+
+static void room_903_daemon() {
+}
+
+static void room_903_pre_parser() {
+}
+
+static void room_903_parser() {
+}
+
+void room_903_synchronize(Common::Serializer &s) {
+ for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
+ for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+}
+
+void room_903_preload() {
+ room_init_code_pointer = room_903_init;
+ room_pre_parser_code_pointer = room_903_pre_parser;
+ room_parser_code_pointer = room_903_parser;
+ room_daemon_code_pointer = room_903_daemon;
+
+ section_1_walker();
+ section_1_interface();
+}
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/forest/rooms/room903.h b/engines/mads/madsv2/forest/rooms/room903.h
new file mode 100644
index 00000000000..6b49d960006
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room903.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_FOREST_ROOMS_903_H
+#define MADS_FOREST_ROOMS_903_H
+
+#include "common/serializer.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+extern void room_903_preload();
+extern void room_903_synchronize(Common::Serializer &s);
+
+} // namespace Rooms
+} // namespace Forest
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/forest/rooms/room904.cpp b/engines/mads/madsv2/forest/rooms/room904.cpp
new file mode 100644
index 00000000000..90da7832d10
--- /dev/null
+++ b/engines/mads/madsv2/forest/rooms/room904.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mads/madsv2/core/conv.h"
+#include "mads/madsv2/core/game.h"
+#include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/text.h"
+#include "mads/madsv2/forest/mads/inventory.h"
+#include "mads/madsv2/forest/mads/sounds.h"
+#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/room904.h"
+
+namespace MADS {
+namespace MADSV2 {
+namespace Forest {
+namespace Rooms {
+
+struct Scratch {
+ int16 sprite[15]; /* Sprite series handles */
+ int16 sequence[15]; /* Sequence handles */
+ int16 animation[4]; /* Animation handles */
+
+ int16 dragon_frame; /* frame animation is on */
+
+ int16 done_with_conv; /* T if done with conv */
+ int16 prev_room;
+};
Commit: 74ed86e494d28182d7df07bab68bc37cf5c52b96
https://github.com/scummvm/scummvm/commit/74ed86e494d28182d7df07bab68bc37cf5c52b96
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2026-05-28T21:12:20+10:00
Commit Message:
MADS: FOREST: Implementing section 9 rooms
Changed paths:
engines/mads/madsv2/forest/global.cpp
engines/mads/madsv2/forest/global.h
engines/mads/madsv2/forest/mads/sounds.h
engines/mads/madsv2/forest/mads/words.h
engines/mads/madsv2/forest/rooms/room901.cpp
engines/mads/madsv2/forest/rooms/room903.cpp
engines/mads/madsv2/forest/rooms/room904.cpp
engines/mads/madsv2/forest/rooms/section9.cpp
diff --git a/engines/mads/madsv2/forest/global.cpp b/engines/mads/madsv2/forest/global.cpp
index 3d926fd63b1..28cd2afc830 100644
--- a/engines/mads/madsv2/forest/global.cpp
+++ b/engines/mads/madsv2/forest/global.cpp
@@ -19,6 +19,7 @@
*
*/
+#include "common/textconsole.h"
#include "mads/madsv2/forest/global.h"
#include "mads/madsv2/core/game.h"
#include "mads/madsv2/core/kernel.h"
@@ -161,6 +162,11 @@ void sync_room(Common::Serializer &s) {
}
}
+void global_digi_play(int num) {
+ // TODO
+ warning("TODO: global_digi_play");
+}
+
} // namespace Forest
} // namespace MADSV2
} // namespace MADS
diff --git a/engines/mads/madsv2/forest/global.h b/engines/mads/madsv2/forest/global.h
index b64a68b9aca..bf1498e4907 100644
--- a/engines/mads/madsv2/forest/global.h
+++ b/engines/mads/madsv2/forest/global.h
@@ -29,9 +29,18 @@ namespace MADS {
namespace MADSV2 {
namespace Forest {
+enum {
+ g009 = 9,
+ g010 = 10,
+ g016 = 16,
+ g017 = 17
+};
+
extern void global_section_constructor();
extern void sync_room(Common::Serializer &s);
+extern void global_digi_play(int num);
+
} // namespace Forest
} // namespace MADSV2
} // namespace MADS
diff --git a/engines/mads/madsv2/forest/mads/sounds.h b/engines/mads/madsv2/forest/mads/sounds.h
index 84513db6c9d..184b0c02101 100644
--- a/engines/mads/madsv2/forest/mads/sounds.h
+++ b/engines/mads/madsv2/forest/mads/sounds.h
@@ -28,7 +28,13 @@ namespace MADS {
namespace MADSV2 {
namespace Forest {
-//enum {};
+enum {
+ // General (shared) sounds
+ N_AllFade = 1,
+ N_MusicFade = 3,
+ N_NoiseOff = 4,
+ N_NoiseFade = 5
+};
} // namespace Forest
} // namespace MADSV2
diff --git a/engines/mads/madsv2/forest/mads/words.h b/engines/mads/madsv2/forest/mads/words.h
index 8ba2af5b3ac..199d01ec063 100644
--- a/engines/mads/madsv2/forest/mads/words.h
+++ b/engines/mads/madsv2/forest/mads/words.h
@@ -28,7 +28,9 @@ namespace MADS {
namespace MADSV2 {
namespace Forest {
-//enum {};
+enum {
+ dummy = 0
+};
} // namespace Forest
} // namespace MADSV2
diff --git a/engines/mads/madsv2/forest/rooms/room901.cpp b/engines/mads/madsv2/forest/rooms/room901.cpp
index d712e4bf527..0a3a52d6128 100644
--- a/engines/mads/madsv2/forest/rooms/room901.cpp
+++ b/engines/mads/madsv2/forest/rooms/room901.cpp
@@ -19,60 +19,59 @@
*
*/
+#include "common/config-manager.h"
#include "mads/madsv2/core/conv.h"
#include "mads/madsv2/core/game.h"
-#include "mads/madsv2/core/imath.h"
-#include "mads/madsv2/core/inter.h"
#include "mads/madsv2/core/kernel.h"
-#include "mads/madsv2/core/sound.h"
-#include "mads/madsv2/core/text.h"
-#include "mads/madsv2/forest/mads/inventory.h"
-#include "mads/madsv2/forest/mads/sounds.h"
-#include "mads/madsv2/forest/mads/words.h"
-#include "mads/madsv2/forest/global.h"
-#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/core/matte.h"
+#include "mads/madsv2/core/mouse.h"
+#include "mads/madsv2/forest/rooms/section9.h"
#include "mads/madsv2/forest/rooms/room901.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/forest.h"
namespace MADS {
namespace MADSV2 {
namespace Forest {
namespace Rooms {
-struct Scratch {
- int16 sprite[15]; /* Sprite series handles */
- int16 sequence[15]; /* Sequence handles */
- int16 animation[4]; /* Animation handles */
-
- int16 dragon_frame; /* frame animation is on */
-
- int16 done_with_conv; /* T if done with conv */
- int16 prev_room;
-};
-
-static Scratch scratch;
-
-#define local (&scratch)
-#define ss local->sprite
-#define seq local->sequence
-#define aa local->animation
-
+/* Triggers */
+#define START_INTRO 100
static void room_901_init() {
+ global[g009] = 0;
+ global[g010] = 0;
+ player.walker_visible = false;
+ viewing_at_y = 22;
+ mouse_hide();
+
+ if (ConfMan.getBool("seen_intro")) {
+ new_room = 904;
+ } else {
+ ConfMan.setBool("seen_intro", true);
+ ConfMan.flushToDisk();
+
+ kernel_timing_trigger(300, START_INTRO);
+ }
}
static void room_901_daemon() {
+ if (mouse_any_stroke || g_engine->hasPendingKey() || kernel.trigger == START_INTRO) {
+ g_engine->flushKeys();
+ mouse_hide();
+ new_room = 903;
+ }
}
static void room_901_pre_parser() {
+ new_room = 903;
}
static void room_901_parser() {
}
void room_901_synchronize(Common::Serializer &s) {
- for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
- for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
- for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+ // Room has no scratch area
}
void room_901_preload() {
@@ -81,8 +80,10 @@ void room_901_preload() {
room_parser_code_pointer = room_901_parser;
room_daemon_code_pointer = room_901_daemon;
- section_1_walker();
- section_1_interface();
+ global[g016] = true;
+ mouse_hide();
+ section_9_walker();
+ section_9_interface();
}
} // namespace Rooms
diff --git a/engines/mads/madsv2/forest/rooms/room903.cpp b/engines/mads/madsv2/forest/rooms/room903.cpp
index 0cb0de40fa4..34444129e99 100644
--- a/engines/mads/madsv2/forest/rooms/room903.cpp
+++ b/engines/mads/madsv2/forest/rooms/room903.cpp
@@ -24,55 +24,58 @@
#include "mads/madsv2/core/imath.h"
#include "mads/madsv2/core/inter.h"
#include "mads/madsv2/core/kernel.h"
-#include "mads/madsv2/core/sound.h"
-#include "mads/madsv2/core/text.h"
-#include "mads/madsv2/forest/mads/inventory.h"
-#include "mads/madsv2/forest/mads/sounds.h"
-#include "mads/madsv2/forest/mads/words.h"
+#include "mads/madsv2/core/matte.h"
+#include "mads/madsv2/core/mouse.h"
#include "mads/madsv2/forest/global.h"
-#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/section9.h"
#include "mads/madsv2/forest/rooms/room903.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/forest.h"
namespace MADS {
namespace MADSV2 {
namespace Forest {
namespace Rooms {
-struct Scratch {
- int16 sprite[15]; /* Sprite series handles */
- int16 sequence[15]; /* Sequence handles */
- int16 animation[4]; /* Animation handles */
-
- int16 dragon_frame; /* frame animation is on */
-
- int16 done_with_conv; /* T if done with conv */
- int16 prev_room;
-};
-
-static Scratch scratch;
-
#define local (&scratch)
#define ss local->sprite
#define seq local->sequence
#define aa local->animation
+/* Triggers */
+#define TRIGGER0 100
+#define TRIGGER1 101
+
static void room_903_init() {
+ mouse_hide();
+ global[g009] = false;
+ global[g010] = false;
+ viewing_at_y = 22;
+ kernel_timing_trigger(20, TRIGGER1);
+ kernel_run_animation("*rm903i", TRIGGER0);
+ player.walker_visible = false;
}
static void room_903_daemon() {
+ if (kernel.trigger == TRIGGER1)
+ global_digi_play(14);
+
+ if (mouse_any_stroke || g_engine->hasPendingKey() || kernel.trigger == TRIGGER0) {
+ g_engine->flushKeys();
+ new_room = 904;
+ }
}
static void room_903_pre_parser() {
+ new_room = 904;
}
static void room_903_parser() {
}
void room_903_synchronize(Common::Serializer &s) {
- for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
- for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
- for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+ // Room has no scratch area
}
void room_903_preload() {
@@ -81,8 +84,9 @@ void room_903_preload() {
room_parser_code_pointer = room_903_parser;
room_daemon_code_pointer = room_903_daemon;
- section_1_walker();
- section_1_interface();
+ global[g016] = true;
+ section_9_walker();
+ section_9_interface();
}
} // namespace Rooms
diff --git a/engines/mads/madsv2/forest/rooms/room904.cpp b/engines/mads/madsv2/forest/rooms/room904.cpp
index 90da7832d10..11d6e17e8c5 100644
--- a/engines/mads/madsv2/forest/rooms/room904.cpp
+++ b/engines/mads/madsv2/forest/rooms/room904.cpp
@@ -24,13 +24,15 @@
#include "mads/madsv2/core/imath.h"
#include "mads/madsv2/core/inter.h"
#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/matte.h"
+#include "mads/madsv2/core/mouse.h"
#include "mads/madsv2/core/sound.h"
#include "mads/madsv2/core/text.h"
#include "mads/madsv2/forest/mads/inventory.h"
#include "mads/madsv2/forest/mads/sounds.h"
#include "mads/madsv2/forest/mads/words.h"
#include "mads/madsv2/forest/global.h"
-#include "mads/madsv2/forest/rooms/section1.h"
+#include "mads/madsv2/forest/rooms/section9.h"
#include "mads/madsv2/forest/rooms/room904.h"
namespace MADS {
@@ -38,29 +40,23 @@ namespace MADSV2 {
namespace Forest {
namespace Rooms {
-struct Scratch {
- int16 sprite[15]; /* Sprite series handles */
- int16 sequence[15]; /* Sequence handles */
- int16 animation[4]; /* Animation handles */
-
- int16 dragon_frame; /* frame animation is on */
-
- int16 done_with_conv; /* T if done with conv */
- int16 prev_room;
-};
-
-static Scratch scratch;
-
-#define local (&scratch)
-#define ss local->sprite
-#define seq local->sequence
-#define aa local->animation
+/* Triggers */
+#define TRIGGER0 100
+#define TRIGGER1 101
static void room_904_init() {
+ mouse_hide();
+ global[g009] = false;
+ global[g010] = false;
+ viewing_at_y = 22;
+ kernel_timing_trigger(20, TRIGGER1);
+ kernel_run_animation("*rm903i", TRIGGER0);
+ player.walker_visible = false;
}
static void room_904_daemon() {
+ // TODO: room_904_daemon
}
static void room_904_pre_parser() {
@@ -70,9 +66,7 @@ static void room_904_parser() {
}
void room_904_synchronize(Common::Serializer &s) {
- for (int16 &v : scratch.sprite) s.syncAsSint16LE(v);
- for (int16 &v : scratch.sequence) s.syncAsSint16LE(v);
- for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+ // Room has no scratch area
}
void room_904_preload() {
@@ -81,8 +75,10 @@ void room_904_preload() {
room_parser_code_pointer = room_904_parser;
room_daemon_code_pointer = room_904_daemon;
- section_1_walker();
- section_1_interface();
+ global[g016] = true;
+ kernel.activate_menu = false;
+ section_9_walker();
+ section_9_interface();
}
} // namespace Rooms
diff --git a/engines/mads/madsv2/forest/rooms/section9.cpp b/engines/mads/madsv2/forest/rooms/section9.cpp
index bada0e7ed05..068482fe958 100644
--- a/engines/mads/madsv2/forest/rooms/section9.cpp
+++ b/engines/mads/madsv2/forest/rooms/section9.cpp
@@ -44,9 +44,24 @@ void section_9_init() {
}
void section_9_walker() {
+ char temp_buf[80];
+ Common::strcpy_s(temp_buf, player.series_name);
+ global[g017] = true;
+
+ if (!global[g016]) {
+ *player.series_name = '\0';
+ } else if (!player.force_series) {
+ Common::strcpy_s(player.series_name, "B");
+ }
+
+ if (strcmp(temp_buf, player.series_name) != 0)
+ player.walker_must_reload = true;
+ player.scaling_velocity = true;
}
void section_9_interface() {
+ Common::strcpy_s(kernel.interface, kernel_interface_name(0));
+ pal_change_color(254, 56, 47, 32);
}
void section_9_music() {
Commit: a57e2b6ae1546f3b44b6725d0d18bad7bb2c9dbe
https://github.com/scummvm/scummvm/commit/a57e2b6ae1546f3b44b6725d0d18bad7bb2c9dbe
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2026-05-28T21:12:20+10:00
Commit Message:
MADS: DRAGONSPHERE: Warning fixes
Changed paths:
engines/mads/madsv2/dragonsphere/rooms/room205.cpp
engines/mads/madsv2/dragonsphere/rooms/room404.cpp
engines/mads/madsv2/dragonsphere/rooms/section4.cpp
diff --git a/engines/mads/madsv2/dragonsphere/rooms/room205.cpp b/engines/mads/madsv2/dragonsphere/rooms/room205.cpp
index f4c5f506a53..852b15aac20 100644
--- a/engines/mads/madsv2/dragonsphere/rooms/room205.cpp
+++ b/engines/mads/madsv2/dragonsphere/rooms/room205.cpp
@@ -496,7 +496,7 @@ static void room_205_pre_parser() {
}
if (player_said_2(walk_to, shifter_village) ||
- player_said_2(walk_across, ground) && inter_point_y < 117) {
+ (player_said_2(walk_across, ground) && inter_point_y < 117)) {
if (global[slime_healed]) {
switch (kernel.trigger) {
case 0:
@@ -611,7 +611,7 @@ static void room_205_parser() {
}
if (player_said_2(walk_to, shifter_village) ||
- player_said_2(walk_across, ground) && inter_point_y < 117) {
+ (player_said_2(walk_across, ground) && inter_point_y < 117)) {
if (global[slime_healed]) {
new_room = 206;
diff --git a/engines/mads/madsv2/dragonsphere/rooms/room404.cpp b/engines/mads/madsv2/dragonsphere/rooms/room404.cpp
index 35a5089786b..5e599078061 100644
--- a/engines/mads/madsv2/dragonsphere/rooms/room404.cpp
+++ b/engines/mads/madsv2/dragonsphere/rooms/room404.cpp
@@ -302,7 +302,8 @@ static void room_404_init() {
if (global[desert_counter] == 6) {
aa[1] = kernel_run_animation(kernel_name('d', 1), 1);
local->anim_1_running = true;
- kernel_reset_animation(aa[25], 30);
+ // WORKAROUND: Invalid line from the original commented out
+ //kernel_reset_animation(aa[25], 30);
} else if (previous_room == 120 || previous_room != KERNEL_RESTORING_GAME) {
ss[fx_dune_1] = kernel_load_series(kernel_name('x', 0), false);
diff --git a/engines/mads/madsv2/dragonsphere/rooms/section4.cpp b/engines/mads/madsv2/dragonsphere/rooms/section4.cpp
index d0affc84fd9..0801715b4c7 100644
--- a/engines/mads/madsv2/dragonsphere/rooms/section4.cpp
+++ b/engines/mads/madsv2/dragonsphere/rooms/section4.cpp
@@ -63,7 +63,7 @@ void section_4_walker() {
Common::strcpy_s(temp_buf, player.series_name);
- if (new_room == 401 || new_room == 402 || new_room == 403 && global[player_persona] == PLAYER_IS_KING) {
+ if (new_room == 401 || new_room == 402 || (new_room == 403 && global[player_persona] == PLAYER_IS_KING)) {
global[perform_displacements] = false;
} else {
global[perform_displacements] = true;
Commit: e51035f2e79f21ab2b8d1c3536b4c9c2986c7f62
https://github.com/scummvm/scummvm/commit/e51035f2e79f21ab2b8d1c3536b4c9c2986c7f62
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2026-05-28T21:12:21+10:00
Commit Message:
MADS: DRAGONSPHERE: Fix re-entering Caliph's tent
Changed paths:
engines/mads/madsv2/dragonsphere/mads/conv.h
diff --git a/engines/mads/madsv2/dragonsphere/mads/conv.h b/engines/mads/madsv2/dragonsphere/mads/conv.h
index eaad7c58914..46ef64ef0b4 100644
--- a/engines/mads/madsv2/dragonsphere/mads/conv.h
+++ b/engines/mads/madsv2/dragonsphere/mads/conv.h
@@ -264,9 +264,9 @@ enum {
};
enum {
- conv040_enter_b_b = 4,
+ conv040_leave_b_b = 4,
conv040_repeater = 7,
- conv040_leave_b_b = 8
+ conv040_enter_b_b = 8
};
enum {
More information about the Scummvm-git-logs
mailing list