[Scummvm-git-logs] scummvm master -> bd0dd3d825451a883d3e1852f3de5531ceb2d875

dreammaster noreply at scummvm.org
Mon Jun 22 00:03:25 UTC 2026


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
504c93db1f MADS: FOREST: Implement journal open/close code
bd0dd3d825 MADS: FOREST: Implement daemon trigger when digi finishes playing


Commit: 504c93db1f1cd3c54240916add46a2c314114d71
    https://github.com/scummvm/scummvm/commit/504c93db1f1cd3c54240916add46a2c314114d71
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2026-06-22T10:03:15+10:00

Commit Message:
MADS: FOREST: Implement journal open/close code

Changed paths:
    engines/mads/madsv2/core/sprite.cpp
    engines/mads/madsv2/core/sprite.h
    engines/mads/madsv2/forest/journal.cpp
    engines/mads/madsv2/forest/journal.h


diff --git a/engines/mads/madsv2/core/sprite.cpp b/engines/mads/madsv2/core/sprite.cpp
index 2346a8e6160..9c06e9f4655 100644
--- a/engines/mads/madsv2/core/sprite.cpp
+++ b/engines/mads/madsv2/core/sprite.cpp
@@ -65,6 +65,11 @@ void sprite_draw(SeriesPtr series, int id, Buffer *buf, int target_x, int target
 #undef translate
 #undef interface
 
+void sprite_draw_clipped(SeriesPtr series, int id, int clip_x, Buffer *buf, int target_x, int target_y) {
+	// TODO: implement clipped/partial draw; for now delegate to full draw
+	sprite_draw(series, id, buf, target_x, target_y);
+}
+
 //=== sprite_draw_scaled =====================================
 #define three_d         false           /* depth coding  OFF */
 #define bresenham       true            /* bresenham     ON  */
diff --git a/engines/mads/madsv2/core/sprite.h b/engines/mads/madsv2/core/sprite.h
index 5daebd7c955..006be642afa 100644
--- a/engines/mads/madsv2/core/sprite.h
+++ b/engines/mads/madsv2/core/sprite.h
@@ -300,6 +300,7 @@ extern int sprite_error;
 
 
 void sprite_draw(SeriesPtr series, int id, Buffer *buf, int target_x, int target_y);
+void sprite_draw_clipped(SeriesPtr series, int id, int clip_x, Buffer *buf, int target_x, int target_y);
 void sprite_draw_scaled(SeriesPtr series, int id, Buffer *buf,
 	int target_x, int target_y, int scale_factor);
 void sprite_draw_3d_scaled(SeriesPtr series, int id, Buffer *buf, Buffer *attr,
diff --git a/engines/mads/madsv2/forest/journal.cpp b/engines/mads/madsv2/forest/journal.cpp
index 07ee1c45009..a3e152e4b38 100644
--- a/engines/mads/madsv2/forest/journal.cpp
+++ b/engines/mads/madsv2/forest/journal.cpp
@@ -20,25 +20,165 @@
  */
 
 #include "mads/madsv2/forest/journal.h"
+#include "mads/madsv2/core/buffer.h"
+#include "mads/madsv2/core/global.h"
+#include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/matte.h"
+#include "mads/madsv2/core/mouse.h"
+#include "mads/madsv2/core/player.h"
+#include "mads/madsv2/core/sprite.h"
+#include "mads/madsv2/core/timer.h"
+#include "mads/madsv2/forest/digi.h"
+#include "mads/madsv2/forest/global.h"
+#include "mads/madsv2/forest/midi.h"
 
 namespace MADS {
 namespace MADSV2 {
 namespace Forest {
 
+static int prior_room;
+
+static void change_to_journal() {
+	save_player();
+	prior_room = room_id;
+	new_room = 199;
+}
+
+static int get_prior_room() {
+	return prior_room;
+}
+
 void display_journal() {
-	// TODO
+	open_journal(1);
+	change_to_journal();
 }
 
 void leave_journal() {
-	// TODO
+	close_journal(1);
+	global[g009] = 0;
+	midi_stop();
+	new_room = get_prior_room();
 }
 
-void open_journal() {
-	// TODO
+void open_journal(int mode) {
+	mouse_hide();
+
+	int count = 0;
+	do {
+		digi_read_another_chunk();
+		if (global[g009])
+			midi_loop();
+
+		long current_time = timer_read();
+
+		buffer_rect_copy(scr_inter_orig, scr_inter, 0, 0, 165, 44);
+
+		if (mode == 1) {
+			if (count != 23) {
+				int id = count * 2 + 46;
+				int clip_x = 100 - count * 9;
+				sprite_draw_clipped(series_list[0], id, clip_x, &scr_inter, 1, 30);
+			}
+		} else {
+			sprite_draw(series_list[0], 3, &scr_inter, 1, 8);
+		}
+
+		if (mode == 2) {
+			if (count != 23) {
+				int id = count * 2 + 40;
+				int clip_x = 100 - count * 9;
+				sprite_draw_clipped(series_list[1], id, clip_x, &scr_inter, 1, 96);
+			}
+		} else {
+			sprite_draw(series_list[1], 1, &scr_inter, 1, 68);
+		}
+
+		buffer_rect_copy_2(scr_inter, scr_main, 0, 0, 0, 156, 165, 44);
+		buffer_rect_copy(scr_inter_orig, scr_inter, 168, 0, 152, 44);
+
+		if (mode == 3)
+			count = 24;
+
+		if (global[walker_converse_state])
+			sprite_draw(series_list[5], 4, &scr_inter, 1, 194);
+		else
+			sprite_draw(series_list[2], 4, &scr_inter, 1, 194);
+
+		if (mode == 4) {
+			sprite_draw(series_list[4], 2, &scr_inter, 1, 264);
+			count = 24;
+		} else {
+			sprite_draw(series_list[3], 2, &scr_inter, 1, 264);
+		}
+
+		buffer_rect_copy_2(scr_inter, scr_main, 168, 0, 168, 156, 152, 44);
+
+		while (timer_read() - current_time < 2) {}
+
+		count++;
+	} while (count < 24);
+
+	mouse_show();
 }
 
 void close_journal(int mode) {
-	// TODO
+	mouse_hide();
+
+	int count = 24;
+	do {
+		digi_read_another_chunk();
+		if (global[g009])
+			midi_loop();
+
+		long current_time = timer_read();
+
+		buffer_rect_copy(scr_inter_orig, scr_inter, 0, 0, 165, 44);
+
+		if (mode == 1) {
+			if (count != 0) {
+				int id = count * 2 + 43;
+				int clip_x = 100 - count * 9;
+				sprite_draw_clipped(series_list[0], id, clip_x, &scr_inter, 1, 30);
+			} else {
+				sprite_draw(series_list[0], 3, &scr_inter, 1, 8);
+			}
+		} else {
+			sprite_draw(series_list[0], 3, &scr_inter, 1, 8);
+		}
+
+		if (mode == 2) {
+			if (count != 0) {
+				int id = count * 2 + 37;
+				int clip_x = 100 - count * 9;
+				sprite_draw_clipped(series_list[1], id, clip_x, &scr_inter, 1, 96);
+			} else {
+				sprite_draw(series_list[1], 1, &scr_inter, 1, 68);
+			}
+		} else {
+			sprite_draw(series_list[1], 1, &scr_inter, 1, 68);
+		}
+
+		buffer_rect_copy_2(scr_inter, scr_main, 0, 0, 0, 156, 165, 44);
+		buffer_rect_copy(scr_inter_orig, scr_inter, 168, 0, 152, 44);
+
+		if (mode == 3)
+			count = 0;
+
+		if (global[walker_converse_state])
+			sprite_draw(series_list[5], 4, &scr_inter, 1, 194);
+		else
+			sprite_draw(series_list[2], 4, &scr_inter, 1, 194);
+
+		sprite_draw(series_list[3], 2, &scr_inter, 1, 264);
+
+		buffer_rect_copy_2(scr_inter, scr_main, 168, 0, 168, 156, 152, 44);
+
+		while (timer_read() - current_time < 2) {}
+
+		count--;
+	} while (count >= 0);
+
+	mouse_show();
 }
 
 } // namespace Forest
diff --git a/engines/mads/madsv2/forest/journal.h b/engines/mads/madsv2/forest/journal.h
index c0bf195f389..0d1a0bc1804 100644
--- a/engines/mads/madsv2/forest/journal.h
+++ b/engines/mads/madsv2/forest/journal.h
@@ -30,7 +30,7 @@ namespace Forest {
 
 extern void display_journal();
 extern void leave_journal();
-extern void open_journal();
+extern void open_journal(int num);
 extern void close_journal(int mode);
 
 } // namespace Forest


Commit: bd0dd3d825451a883d3e1852f3de5531ceb2d875
    https://github.com/scummvm/scummvm/commit/bd0dd3d825451a883d3e1852f3de5531ceb2d875
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2026-06-22T10:03:15+10:00

Commit Message:
MADS: FOREST: Implement daemon trigger when digi finishes playing

Changed paths:
    engines/mads/madsv2/core/game.cpp
    engines/mads/madsv2/core/kernel.cpp
    engines/mads/madsv2/forest/digi.cpp
    engines/mads/madsv2/forest/digi.h


diff --git a/engines/mads/madsv2/core/game.cpp b/engines/mads/madsv2/core/game.cpp
index 649ca02bf4e..9e2118ef213 100644
--- a/engines/mads/madsv2/core/game.cpp
+++ b/engines/mads/madsv2/core/game.cpp
@@ -66,6 +66,7 @@
 #include "mads/madsv2/core/imath.h"
 #include "mads/madsv2/core/screen.h"
 #include "mads/madsv2/forest/extra.h"
+#include "mads/madsv2/forest/digi.h"
 
 namespace MADS {
 namespace MADSV2 {
@@ -2300,11 +2301,13 @@ static void game_control_loop() {
 			}
 		}
 	}
-#if 0
-	digi_stop(1);
-	digi_stop(2);
-	digi_stop(3);
-#endif
+
+	if (g_engine->getGameID() == GType_Forest) {
+		Forest::digi_stop(1);
+		Forest::digi_stop(2);
+		Forest::digi_stop(3);
+	}
+
 	if (debugger) game_exec_function(debugger_reset);
 }
 
diff --git a/engines/mads/madsv2/core/kernel.cpp b/engines/mads/madsv2/core/kernel.cpp
index 94adbca3805..d23424393bf 100644
--- a/engines/mads/madsv2/core/kernel.cpp
+++ b/engines/mads/madsv2/core/kernel.cpp
@@ -59,6 +59,7 @@
 #include "mads/madsv2/core/quote.h"
 #include "mads/madsv2/core/game.h"
 #include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/forest/digi.h"
 
 namespace MADS {
 namespace MADSV2 {
@@ -125,8 +126,6 @@ KernelGame game;                        /* Kernel level game data */
 
 Sequence sequence_list[KERNEL_MAX_SEQUENCES];
 
-int stop_speech_on_run_anim = true;
-
 KernelMessage kernel_message[KERNEL_MAX_MESSAGES];
 FontPtr kernel_message_font;
 int kernel_message_spacing;
@@ -1456,15 +1455,13 @@ int kernel_run_animation(const char *name, int trigger_code) {
 	int count;
 	int load_flags;
 	int id;
-	long largest_block;
+	int largest_block;
 
-#if 0
-	if (stop_speech_on_run_anim) {
-		digi_stop(1);
-		digi_stop(2);
-		digi_stop(3);
+	if (g_engine->getGameID() == GType_Forest && stop_speech_on_run_animation) {
+		Forest::digi_stop(1);
+		Forest::digi_stop(2);
+		Forest::digi_stop(3);
 	}
-#endif
 
 	anim_error = -2;
 
@@ -1492,7 +1489,7 @@ int kernel_run_animation(const char *name, int trigger_code) {
 	if (kernel_anim[found].anim->misc_any_packed) {
 		kernel_anim[found].buffer_id = -1;
 		id = kernel_anim[found].anim->series_id[kernel_anim[found].anim->misc_packed_series];
-		memcpy(&largest_block, &series_list[id]->misc_largest_block, sizeof(long));
+		memcpy(&largest_block, &series_list[id]->misc_largest_block, sizeof(int));
 		if (mem_get_avail() - 128 >= largest_block) {
 			mem_free(series_list[id]->arena);
 			series_list[id]->arena = (byte *)mem_get_name(largest_block * 2, "$arena$");
@@ -2960,7 +2957,7 @@ void init_kernel() {
 	memset(&kernel, 0, sizeof(Kernel));
 	memset(&game, 0, sizeof(KernelGame));
 	memset(sequence_list, 0, sizeof(sequence_list));
-	stop_speech_on_run_anim = true;
+	stop_speech_on_run_animation = true;
 	memset(kernel_message, 0, sizeof(kernel_message));
 	kernel_message_font = NULL;
 	kernel_message_spacing = 0;
@@ -2979,7 +2976,6 @@ void init_kernel() {
 	random_message_color = 0;
 	random_message_duration = 0;
 	memset(kernel_interface_loaded, 0, sizeof(kernel_interface_loaded));
-	stop_speech_on_run_animation = false;
 }
 
 void kernel_random_frame(int handle, int16 *frame, int mode) {
diff --git a/engines/mads/madsv2/forest/digi.cpp b/engines/mads/madsv2/forest/digi.cpp
index 3c4cef59988..970d2e14ba5 100644
--- a/engines/mads/madsv2/forest/digi.cpp
+++ b/engines/mads/madsv2/forest/digi.cpp
@@ -23,6 +23,7 @@
 #include "mads/madsv2/forest/digi.h"
 #include "mads/madsv2/forest/forest.h"
 #include "mads/madsv2/core/env.h"
+#include "mads/madsv2/core/kernel.h"
 
 namespace MADS {
 namespace MADSV2 {
@@ -32,9 +33,19 @@ int digi_val2;
 int digi_timing_index;
 bool digi_flag1, digi_flag2;
 
+DigiPlayer::DigiPlayer(Audio::Mixer *mixer) : _mixer(mixer) {
+	_channels[0]._triggerId = 7;
+	_channels[1]._triggerId = 8;
+	_channels[2]._triggerId = 9;
+
+	digi_val2 = 0;
+	digi_timing_index = 0;
+	digi_flag1 = digi_flag2 = false;
+}
+
 void DigiPlayer::play(const char *name, int slot) {
-	assert(slot >= 0 && slot < 8);
-	_mixer->stopHandle(_slots[slot]);
+	stop(slot);
+	DigiChannel &c = _channels[slot - 1];
 
 	Common::SeekableReadStream *src;
 	src = env_open(Common::String::format("*%s.rac", name).c_str());
@@ -51,21 +62,34 @@ void DigiPlayer::play(const char *name, int slot) {
 
 	Audio::AudioStream *audioStream = Audio::makeADPCMStream(src, DisposeAfterUse::YES,
 		src->size() - 0x20, Audio::kADPCMDVI, 11025, 1);
-	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_slots[slot], audioStream);
+	_mixer->playStream(Audio::Mixer::kSFXSoundType, &c._soundHandle, audioStream);
+	c._isPlaying = true;
 }
 
 void DigiPlayer::stop(int slot) {
-	assert(slot >= 0 && slot < 8);
-	_mixer->stopHandle(_slots[slot]);
-}
+	assert(slot >= 1 && slot <= MAX_DIGI_CHANNELS);
+	DigiChannel &c = _channels[slot - 1];
 
+	if (c._isPlaying) {
+		_mixer->stopHandle(c._soundHandle);
+		c._isPlaying = false;
 
-void digi_install() {
-	digi_val2 = 0;
-	digi_timing_index = 0;
+		if (c._endTrigger) {
+			kernel.trigger_setup_mode = KERNEL_TRIGGER_DAEMON;
+			kernel_timing_trigger(1, c._triggerId);
+		}
+
+		c._endTrigger = true;
+	}
 }
 
-void digi_uninstall() {
+void DigiPlayer::poll() {
+	for (int slot = 1; slot <= MAX_DIGI_CHANNELS; ++slot) {
+		DigiChannel &c = _channels[slot - 1];
+
+		if (c._isPlaying && !_mixer->isSoundHandleActive(c._soundHandle))
+			digi_stop(slot);
+	}
 }
 
 void digi_play_build_ii(char thing, int num, int slot) {
@@ -74,9 +98,9 @@ void digi_play_build_ii(char thing, int num, int slot) {
 	digi_play(name.c_str(), slot);
 }
 
-void digi_play_build(int room, char thing, int num, int slot) {
+void digi_play_build(int roomNum, char thing, int num, int slot) {
 	Common::String name = Common::String::format("%c%d%c%03d",
-		(thing == '_') ? 's' : 'd', room, thing, num);
+		(thing == '_') ? 's' : 'd', roomNum, thing, num);
 	digi_play(name.c_str(), slot);
 }
 
@@ -88,6 +112,10 @@ void digi_stop(int which_one) {
 	g_engine->_digiPlayer.stop(which_one);
 }
 
+void digi_read_another_chunk() {
+	g_engine->_digiPlayer.poll();
+}
+
 void digi_initial_volume(int vol) {
 }
 
diff --git a/engines/mads/madsv2/forest/digi.h b/engines/mads/madsv2/forest/digi.h
index accd62d3520..1561a375399 100644
--- a/engines/mads/madsv2/forest/digi.h
+++ b/engines/mads/madsv2/forest/digi.h
@@ -29,31 +29,52 @@ namespace MADS {
 namespace MADSV2 {
 namespace Forest {
 
+#define MAX_DIGI_CHANNELS 3
+
 class DigiPlayer {
+	struct DigiChannel {
+		Audio::SoundHandle _soundHandle;
+		bool _isPlaying = false;
+		int _triggerId;
+		bool _endTrigger = true;
+	};
 private:
 	Audio::Mixer *_mixer;
-	Audio::SoundHandle _slots[8];
+	DigiChannel _channels[MAX_DIGI_CHANNELS];
+
 public:
-	DigiPlayer(Audio::Mixer *mixer) : _mixer(mixer) {
-	}
+	DigiPlayer(Audio::Mixer *mixer);
 
+	/**
+	 * Play a digital sound
+	 * @param name	Resource name
+	 * @param slot	Channel to play it in
+	*/
 	void play(const char *name, int slot);
+
+	/**
+	 * Stop any playing digital sound in a particular channel
+	 * @param slot	Channel to stop
+	 */
 	void stop(int slot);
+
+	/**
+	 * Polls for any playing sounds that are finished
+	 */
+	void poll();
 };
 
 extern int digi_val2;
 extern int digi_timing_index;
 extern bool digi_flag1, digi_flag2;
 
-extern void digi_install();
 extern void digi_play(const char *name, int slot);
-extern void digi_play_build(int room, char thing, int num, int slot);
+extern void digi_play_build(int roomNum, char thing, int num, int slot);
 extern void digi_play_build_ii(char thing, int num, int slot);
 extern void digi_stop(int which_one);
-extern void digi_uninstall();
 extern void digi_initial_volume(int vol);
 extern void digi_set_volume(int vol, int slot);
-inline void digi_read_another_chunk() {}
+extern void digi_read_another_chunk();
 
 } // namespace Forest
 } // namespace MADSV2




More information about the Scummvm-git-logs mailing list