[Scummvm-git-logs] scummvm master -> 23662f44d5ffddfe75cdfa3f47ab8b880c3f070a

dreammaster noreply at scummvm.org
Sun Oct 6 03:36:31 UTC 2024


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

Summary:
5ce40aee15 M4: Move the bulk of gui_cheapo.cpp into m4/gui/
23662f44d5 M4: RIDDLE: Beginnings of user interface


Commit: 5ce40aee1565e6685acf660193286e0cfe30bfe2
    https://github.com/scummvm/scummvm/commit/5ce40aee1565e6685acf660193286e0cfe30bfe2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2024-10-05T20:36:19-07:00

Commit Message:
M4: Move the bulk of gui_cheapo.cpp into m4/gui/

It looks like Riddle will share most of the UI controls used
in the user interface in common, with the likely exception of the
Inventory control.

Changed paths:
  A engines/m4/gui/gui_cheapo.cpp
  A engines/m4/gui/gui_cheapo.h
  A engines/m4/riddle/gui/gui_cheapo.cpp
  A engines/m4/riddle/gui/gui_cheapo.h
    engines/m4/burger/gui/gui_cheapo.cpp
    engines/m4/burger/gui/gui_cheapo.h
    engines/m4/console.h
    engines/m4/module.mk
    engines/m4/riddle/gui/interface.cpp
    engines/m4/riddle/gui/interface.h


diff --git a/engines/m4/burger/gui/gui_cheapo.cpp b/engines/m4/burger/gui/gui_cheapo.cpp
index 3a71f78491f..00cba239613 100644
--- a/engines/m4/burger/gui/gui_cheapo.cpp
+++ b/engines/m4/burger/gui/gui_cheapo.cpp
@@ -20,504 +20,16 @@
  */
 
 #include "m4/burger/gui/gui_cheapo.h"
-#include "m4/gui/gui_vmng_core.h"
-#include "m4/gui/gui_vmng_screen.h"
-#include "m4/graphics/gr_font.h"
+#include "m4/burger/vars.h"
+#include "m4/core/errors.h"
 #include "m4/graphics/gr_line.h"
-#include "m4/graphics/gr_pal.h"
 #include "m4/graphics/gr_series.h"
-#include "m4/adv_r/adv_trigger.h"
-#include "m4/core/cstring.h"
-#include "m4/core/errors.h"
-#include "m4/mem/mem.h"
-#include "m4/mem/memman.h"
-#include "m4/burger/vars.h"
+#include "m4/gui/gui_vmng_screen.h"
 
 namespace M4 {
 namespace Burger {
 namespace GUI {
 
-RectClass::RectClass() {
-}
-
-RectClass::RectClass(const RectClass *r) {
-	if (!r) {
-		error_show(FL, 'CGNR');
-	} else {
-		_x1 = r->_x1;
-		_y1 = r->_y1;
-		_x2 = r->_x2;
-		_y2 = r->_y2;
-	}
-}
-
-RectClass::RectClass(int16 x1, int16 y1, int16 x2, int16 y2) :
-	_x1(x1), _y1(y1), _x2(x2), _y2(y2) {
-}
-
-RectClass::~RectClass() {
-}
-
-void RectClass::copyInto(RectClass *r) const {
-	if (!r) {
-		error_show(FL, 'CGNR');
-	} else {
-		r->_x1 = _x1;
-		r->_y1 = _y1;
-		r->_x2 = _x2;
-		r->_y2 = _y2;
-	}
-}
-
-void RectClass::set(int16 x1, int16 y1, int16 x2, int16 y2) {
-	_x1 = x1;
-	_y1 = y1;
-	_x2 = x2;
-	_y2 = y2;
-}
-
-void RectClass::set(const RectClass *r) {
-	if (!r) {
-		error_show(FL, 'CGNR');
-	} else {
-		_x1 = r->_x1;
-		_y1 = r->_y1;
-		_x2 = r->_x2;
-		_y2 = r->_y2;
-	}
-}
-
-int16 RectClass::inside(int16 x, int16 y) const {
-	if ((x >= _x1) && (x <= _x2) && (y >= _y1) && (y <= _y2))
-		return 1;
-
-	return 0;
-}
-
-//-------------------------------------------------------------------------------------------
-
-TextField::TextField(int16 x1, int16 y1, int16 x2, int16 y2) :
-	RectClass(x1, y1, x2, y2) {
-	_string = nullptr;
-	_string_len = 0;
-	_must_redraw = true;
-}
-
-TextField::~TextField() {
-	if (_string != nullptr)
-		mem_free(_string);
-}
-
-void TextField::set_string(const char *string) {
-	_must_redraw = true;
-
-	if (string == nullptr && _string != nullptr) {
-		_string[0] = '\0';
-		return;
-	}
-
-	int16 string_len = (int16)(cstrlen(string) + 1);
-	if (_string == nullptr) {
-		_string = (char *)mem_alloc(string_len, "string");
-	} else {
-		if (_string_len < string_len) {
-			_string = (char *)mem_realloc(_string, string_len, "string");
-		}
-	}
-
-	if (!_string)
-		error_show(FL, 'OOM!', "TextField set_string:%s", _string);
-
-	_string_len = string_len;
-	cstrcpy(_string, string);
-}
-
-void TextField::draw(GrBuff *myBuffer) {
-	if (!_GI(visible))
-		return;
-
-	Buffer *myBuff = myBuffer->get_buffer();
-	gr_color_set(__BLACK);
-	gr_buffer_rect_fill(myBuff, _x1, _y1, _x2 - _x1, _y2 - _y1);
-
-	gr_font_set(_G(font_inter));
-	font_set_colors(1, 2, 3);
-	gr_font_write(myBuff, _string, _x1, _y1, 0, 1);
-	myBuffer->release();
-
-	ScreenContext *iC = vmng_screen_find(_G(gameInterfaceBuff), nullptr);
-	RestoreScreensInContext(_x1, _y1, _x2, _y2, iC);
-	_must_redraw = false;
-}
-
-//-------------------------------------------------------------------------------------------
-
-void ButtonClass::init() {
-	_relaxed = _over = _picked = 0;
-	_tag = 0;
-	_must_redraw = true;
-	_state = BUTTON_RELAXED;
-	_tracking = -1;
-}
-
-ButtonClass::ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag) : RectClass(r) {
-	init();
-	_name = btnName;
-	_tag = tag;
-}
-
-ButtonClass::ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag,
-	int16 unknown, int16 relaxed, int16 over, int16 picked, int sprite) : RectClass(r),
-	_tag(tag), _unknown(unknown), _relaxed(relaxed), _over(over), _picked(picked), _sprite(sprite) {
-}
-
-ButtonClass::ButtonClass() : RectClass() {
-	init();
-	_name = "?";
-}
-
-ButtonClass::~ButtonClass() {
-	zap_resources();
-}
-
-void ButtonClass::set_name(const Common::String &btnName) {
-	_name = btnName;
-}
-
-bool ButtonClass::is_hidden() const {
-	return _hidden;
-}
-
-void ButtonClass::set_sprite_relaxed(int16 r) {
-	_relaxed = r;
-}
-
-void ButtonClass::set_sprite_picked(int16 p) {
-	_picked = p;
-}
-
-void ButtonClass::set_sprite_over(int16 o) {
-	_over = o;
-}
-
-void ButtonClass::set_sprite_unknown(int16 val) {
-	_unknown = val;
-}
-
-int16 ButtonClass::get_tag() const {
-	return _tag;
-}
-
-void ButtonClass::zap_resources() {
-	if (_relaxed)
-		ClearWSAssets(_WS_ASSET_CELS, _relaxed, _relaxed);
-	if (_over)
-		ClearWSAssets(_WS_ASSET_CELS, _over, _over);
-	if (_picked)
-		ClearWSAssets(_WS_ASSET_CELS, _picked, _picked);
-}
-
-void ButtonClass::set(const ButtonClass *b) {
-	zap_resources();
-	_name = b->_name;
-	_x1 = b->_x1;
-	_y1 = b->_y1;
-	_x2 = b->_x2;
-	_y2 = b->_y2;
-	_tag = b->_tag;
-	_relaxed = b->_relaxed;
-	_over = b->_over;
-	_picked = b->_picked;
-}
-
-void ButtonClass::set(int16 x1, int16 y1, int16 x2, int16 y2, int16 tag) {
-	_x1 = x1;
-	_y1 = y1;
-	_x2 = x2;
-	_y2 = y2;
-	_tag = tag;
-}
-
-void ButtonClass::set(int16 x1, int16 y1, int16 x2, int16 y2, int16 tag,
-	int16 unknown, int16 relaxed, int16 over, int16 picked, int32 sprite) {
-	zap_resources();
-	_x1 = x1;
-	_y1 = y1;
-	_x2 = x2;
-	_y2 = y2;
-	_tag = tag;
-	_unknown = unknown;
-	_relaxed = relaxed;
-	_over = over;
-	_picked = picked;
-	_sprite = sprite;
-}
-
-int16 ButtonClass::inside(int16 x, int16 y) const {
-	if (RectClass::inside(x, y))
-		return _tag;
-
-	return -1;
-}
-
-ControlStatus ButtonClass::track(int32 eventType, int16 x, int16 y) {
-	if (!_GI(visible))
-		return NOTHING;
-
-	ButtonState old_state = _state;
-	ControlStatus result = NOTHING;
-
-	bool button_clicked = (eventType == _ME_L_click) || (eventType == _ME_L_hold) || (eventType == _ME_L_drag);
-
-	int16 overTag = inside(x, y);
-
-	if (overTag == _tag) {
-		// if Button is pressed
-		if (button_clicked) {
-			if (_tracking == 1) {
-				result = TRACKING;
-			} else {
-				_tracking = 1;
-				result = IN_CONTROL;
-				_state = BUTTON_PICKED;
-			}
-
-			_G(inv_suppress_click_sound) = false;
-
-		} else {
-			// if Button isn't pressed
-			if (_tracking == 1) {
-				result = SELECTED;
-			} else {
-				result = OVER_CONTROL;
-			}
-
-			_state = BUTTON_OVER;
-			_tracking = -1;
-		}
-	} else {
-		result = NOTHING;
-		_tracking = -1;
-		_state = BUTTON_RELAXED;
-	}
-
-	if (old_state != _state)
-		_must_redraw = true;
-
-	return result;
-}
-
-void ButtonClass::draw(GrBuff *myBuffer) {
-	if (!_GI(visible))
-		return;
-
-	if (!_must_redraw)
-		return;
-
-	Buffer *myBuff = myBuffer->get_buffer();
-
-	gr_color_set(__BLACK);
-	gr_buffer_rect_fill(myBuff, _x1, _y1 - 2, _x2 - _x1, _y2 - _y1 + 2);
-
-	if (_hidden == false) {
-		switch (_state) {
-		case BUTTON_0:
-			series_show_frame(_sprite, _unknown, myBuff, _x1, _y1);
-			break;
-
-		case BUTTON_RELAXED:
-			series_show_frame(_sprite, _relaxed, myBuff, _x1, _y1);
-			break;
-
-		case BUTTON_OVER:
-			series_show_frame(_sprite, _over, myBuff, _x1, _y1);
-			break;
-
-		case BUTTON_PICKED:
-			series_show_frame(_sprite, _picked, myBuff, _x1, _y1);
-			break;
-		}
-	}
-
-	myBuffer->release();
-
-	_must_redraw = false;
-	ScreenContext *iC = vmng_screen_find(_G(gameInterfaceBuff), nullptr);
-	RestoreScreensInContext(_x1, _y1 - 2, _x2, _y2, iC);
-}
-
-void ButtonClass::hide() {
-	_hidden = true;
-	_must_redraw = true;
-}
-
-void ButtonClass::unhide() {
-	_hidden = false;
-	_must_redraw = true;
-}
-
-//-------------------------------------------------------------------------------------------
-
-Toggler::Toggler() : ButtonClass() {
-	_toggle_state = SELECTED;
-	_state = BUTTON_PICKED;
-}
-
-ControlStatus Toggler::track(int32 eventType, int16 x, int16 y) {
-	if (!_GI(visible))
-		return NOTHING;
-
-	ButtonState old_state = _state;
-	ControlStatus result = NOTHING;
-
-	bool button_clicked = (eventType == _ME_L_click) || (eventType == _ME_L_hold) || (eventType == _ME_L_drag);
-
-	int16 overTag = inside(x, y);
-
-	if (overTag == _tag) {
-		// if Button is pressed
-		if (button_clicked) {
-			_tracking = 1;
-			result = IN_CONTROL;
-
-		} else {
-			// Button isn't pressed
-			if (_tracking == 1) {
-				result = SELECTED;
-				_toggle_state = (_toggle_state == SELECTED) ? NOTHING : SELECTED;
-			} else {
-				result = OVER_CONTROL;
-			}
-			_tracking = -1;
-		}
-	} else {
-		if (button_clicked && _tracking == 1) {
-			result = TRACKING;
-		} else {
-			result = NOTHING;
-			_tracking = -1;
-		}
-	}
-
-	_state = (_toggle_state == SELECTED) ? BUTTON_PICKED : BUTTON_RELAXED;
-
-	if (old_state != _state)
-		_must_redraw = true;
-
-	return result;
-}
-
-//-------------------------------------------------------------------------------------------
-
-InterfaceBox::InterfaceBox(const RectClass &r) {
-	r.copyInto(this);
-	_highlight_index = -1;
-	_must_redraw_all = true;
-	_selected = false;
-	_index = 0;
-
-	for (int16 iter = 0; iter < MAX_BUTTONS; iter++)
-		_button[iter] = nullptr;
-}
-
-InterfaceBox::~InterfaceBox() {
-}
-
-int16 InterfaceBox::inside(int16 x, int16 y) const {
-	if (!_index)
-		return -1;
-
-	if (!RectClass::inside(x, y))
-		return -1;
-
-	int16 iter;
-	for (iter = 0; iter < _index; iter++) {
-		if (_button[iter]->inside(x, y))
-			return _button[iter]->get_tag();
-	}
-
-	return -1;
-}
-
-void InterfaceBox::highlight_button(int16 index) {
-	if (_highlight_index == index) {
-		return;
-	}
-
-	if (_highlight_index != -1)
-		_button[_highlight_index]->_must_redraw = true;
-
-	if (index == -1)
-		_selected = false;
-
-	_highlight_index = index;
-
-	if (_highlight_index != -1)
-		_button[_highlight_index]->_must_redraw = true;
-}
-
-void InterfaceBox::set_selected(bool s) {
-	if (s == _selected)
-		return;
-
-	_selected = s;
-
-	if (_highlight_index != -1)
-		_button[_highlight_index]->_must_redraw = true;
-}
-
-void InterfaceBox::add(ButtonClass *b) {
-	if (!b) {
-		error_show(FL, 'CGIA');
-	} else if (_index >= MAX_BUTTONS) {
-		error_show(FL, 'CGIA');
-	} else {
-		// Convert to global coordinates
-		b->_x1 += _x1;
-		b->_x2 += _x1;
-		b->_y1 += _y1;
-		b->_y2 += _y1;
-
-		_button[_index] = b;
-		_button[_index]->_must_redraw = true;
-		++_index;
-	}
-}
-
-ControlStatus InterfaceBox::track(int32 eventType, int16 x, int16 y) {
-	ControlStatus result = NOTHING;
-
-	for (int iter = 0; iter < _index; iter++) {
-		if (_button[iter]->track(eventType, x, y) == SELECTED) {
-			_highlight_index = _button[iter]->get_tag();
-			term_message("selected button: %d", iter);
-			result = SELECTED;
-			break;
-		}
-	}
-
-	return result;
-}
-
-void InterfaceBox::draw(GrBuff *myBuffer) {
-	if (!_GI(visible))
-		return;
-
-	for (int iter = 0; iter < _index; iter++) {
-		_button[iter]->_must_redraw |= _must_redraw_all;
-		_button[iter]->draw(myBuffer);
-	}
-
-	if (_must_redraw_all) {
-		ScreenContext *iC = vmng_screen_find(_G(gameInterfaceBuff), nullptr);
-		RestoreScreensInContext(_x1, _y1, _x2, _y2, iC);
-	}
-
-	_must_redraw_all = false;
-}
-
-//-------------------------------------------------------------------------------------------
-
 Inventory::Inventory(const RectClass &r, int32 sprite, int16 cells_h, int16 cells_v, int16 cell_w, int16 cell_h, int16 tag)
 	: RectClass(r) {
 	_sprite = sprite;
diff --git a/engines/m4/burger/gui/gui_cheapo.h b/engines/m4/burger/gui/gui_cheapo.h
index f4935940425..4a44a09e233 100644
--- a/engines/m4/burger/gui/gui_cheapo.h
+++ b/engines/m4/burger/gui/gui_cheapo.h
@@ -23,17 +23,16 @@
 #ifndef M4_BURGER_GUI_CHEAPO_H
 #define M4_BURGER_GUI_CHEAPO_H
 
-#include "common/str.h"
-#include "m4/graphics/gr_buff.h"
-#include "m4/m4_types.h"
+#include "m4/gui/gui_cheapo.h"
 
 namespace M4 {
 namespace Burger {
 namespace GUI {
 
+using namespace M4::GUI;
+
 constexpr int16 INVENTORY_CELLS_COUNT = 128;
 constexpr int16 ARROW_WIDTH = 8;
-constexpr int16 MAX_BUTTONS = 20;
 constexpr int16 MAX_INVENTORY = 9;
 
 constexpr int16 LEFT_ARROW_TAG = 128;
@@ -48,131 +47,6 @@ constexpr int16 RIGHT_ARROW_TAG_DOWN = 136;
 constexpr int16 LEFT_ARROW_TAG_NONFUNC = 133;
 constexpr int16 RIGHT_ARROW_TAG_NONFUNC = 137;
 
-enum ControlStatus {
-	NOTHING, IN_CONTROL, OVER_CONTROL, SELECTED, TRACKING
-};
-
-enum ButtonState {
-	BUTTON_0, BUTTON_RELAXED, BUTTON_OVER, BUTTON_PICKED
-};
-
-class RectClass;
-class ButtonClass;
-class InterfaceBox;
-class Inventory;
-
-class RectClass {
-public:
-	int16 _x1 = 0, _x2 = 0, _y1 = 0, _y2 = 0;
-public:
-	RectClass();
-	RectClass(int16 x1, int16 y1, int16 x2, int16 y2);
-	RectClass(const RectClass *);
-	virtual ~RectClass();
-	virtual int16 inside(int16 x, int16 y) const;
-
-	void copyInto(RectClass *r) const;
-
-	void set(int16 x1, int16 y1, int16 x2, int16 y2);
-	void set(const RectClass *r);
-};
-
-class TextField : public RectClass {
-private:
-	char *_string = nullptr;
-	int16 _string_len = 0;
-public:
-	bool _must_redraw = false;
-
-public:
-	TextField(int16 x1, int16 y1, int16 x2, int16 y2);
-	~TextField();
-
-	void set_string(const char *string);
-	void draw(GrBuff *interface_buffer);
-};
-
-class ButtonClass : public RectClass {
-protected:
-	int16 _tag = 0;
-	int16 _unknown = 0;
-	int16 _relaxed = 0;
-	int16 _over = 0;
-	int16 _picked = 0;
-	int16 _tracking = 0;
-	int32 _sprite = 0;
-	bool _highlighted = false;
-	bool _hidden = false;
-
-	void init();
-	void zap_resources();
-
-public:
-	ButtonState	_state = BUTTON_RELAXED;
-	Common::String _name;
-	bool _must_redraw = false;
-
-public:
-	ButtonClass();
-	ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag);
-	ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag,
-		int16 unknown, int16 relaxed, int16 over, int16 picked, int sprite);
-	~ButtonClass();
-
-	void draw(GrBuff *interface_buffer);
-	int16 inside(int16 x, int16 y) const override;
-	virtual ControlStatus track(int32 eventType, int16 x, int16 y);
-
-	void set(const ButtonClass *b);
-	void set(int16 x1, int16 y1, int16 x2, int16 y2, int16 tag);
-	void set(int16 x1, int16 y1, int16 x2, int16 y2, int16 tag, int16 unknown,
-		int16 relaxed, int16 over, int16 picked, int32 sprite);
-	void set_name(const Common::String &btnName);
-
-	int16 get_tag() const;
-
-	void hide();
-	void unhide();
-	bool is_hidden() const;
-	void set_sprite_relaxed(int16 r);
-	void set_sprite_picked(int16 p);
-	void set_sprite_over(int16 o);
-	void set_sprite_unknown(int16 val);
-};
-
-class Toggler : public ButtonClass {
-public:
-	ControlStatus _toggle_state;
-public:
-	Toggler();
-	ControlStatus track(int32 eventType, int16 x, int16 y);
-};
-
-class InterfaceBox : public RectClass {
-private:
-	bool _selected = false;
-	int16 _index = 0;
-	ButtonClass *_button[MAX_BUTTONS] = { nullptr };
-
-public:
-	int16 _highlight_index = 0;
-	bool _must_redraw_all = false;
-
-public:
-	InterfaceBox(const RectClass &r);
-	~InterfaceBox();
-
-	void draw(GrBuff *interface_buffer);
-	int16 inside(int16 x, int16 y) const override;
-	ControlStatus track(int32 eventType, int16 x, int16 y);
-
-	void add(ButtonClass *b);
-	int16 check_inventory(int16 x, int16 y);
-	void highlight_button(int16 index);
-	void set_selected(bool);
-
-};
-
 class Inventory : public RectClass {
 	struct Entry {
 		Common::String _name;
diff --git a/engines/m4/console.h b/engines/m4/console.h
index dae130e4801..e2861ac4036 100644
--- a/engines/m4/console.h
+++ b/engines/m4/console.h
@@ -27,7 +27,7 @@
 
 namespace M4 {
 
-class Console : public GUI::Debugger {
+class Console : public ::GUI::Debugger {
 private:
 	bool cmdTeleport(int argc, const char **argv);
 	bool cmdItem(int argc, const char **argv);
diff --git a/engines/m4/gui/gui_cheapo.cpp b/engines/m4/gui/gui_cheapo.cpp
new file mode 100644
index 00000000000..47c6cc0423f
--- /dev/null
+++ b/engines/m4/gui/gui_cheapo.cpp
@@ -0,0 +1,519 @@
+/* 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 "m4/gui/gui_cheapo.h"
+#include "m4/gui/gui_vmng_core.h"
+#include "m4/gui/gui_vmng_screen.h"
+#include "m4/graphics/gr_font.h"
+#include "m4/graphics/gr_line.h"
+#include "m4/graphics/gr_pal.h"
+#include "m4/graphics/gr_series.h"
+#include "m4/adv_r/adv_trigger.h"
+#include "m4/core/cstring.h"
+#include "m4/core/errors.h"
+#include "m4/mem/mem.h"
+#include "m4/mem/memman.h"
+#include "m4/vars.h"
+
+namespace M4 {
+namespace GUI {
+
+RectClass::RectClass() {
+}
+
+RectClass::RectClass(const RectClass *r) {
+	if (!r) {
+		error_show(FL, 'CGNR');
+	} else {
+		_x1 = r->_x1;
+		_y1 = r->_y1;
+		_x2 = r->_x2;
+		_y2 = r->_y2;
+	}
+}
+
+RectClass::RectClass(int16 x1, int16 y1, int16 x2, int16 y2) :
+	_x1(x1), _y1(y1), _x2(x2), _y2(y2) {
+}
+
+RectClass::~RectClass() {
+}
+
+void RectClass::copyInto(RectClass *r) const {
+	if (!r) {
+		error_show(FL, 'CGNR');
+	} else {
+		r->_x1 = _x1;
+		r->_y1 = _y1;
+		r->_x2 = _x2;
+		r->_y2 = _y2;
+	}
+}
+
+void RectClass::set(int16 x1, int16 y1, int16 x2, int16 y2) {
+	_x1 = x1;
+	_y1 = y1;
+	_x2 = x2;
+	_y2 = y2;
+}
+
+void RectClass::set(const RectClass *r) {
+	if (!r) {
+		error_show(FL, 'CGNR');
+	} else {
+		_x1 = r->_x1;
+		_y1 = r->_y1;
+		_x2 = r->_x2;
+		_y2 = r->_y2;
+	}
+}
+
+int16 RectClass::inside(int16 x, int16 y) const {
+	if ((x >= _x1) && (x <= _x2) && (y >= _y1) && (y <= _y2))
+		return 1;
+
+	return 0;
+}
+
+//-------------------------------------------------------------------------------------------
+
+TextField::TextField(int16 x1, int16 y1, int16 x2, int16 y2) :
+	RectClass(x1, y1, x2, y2) {
+	_string = nullptr;
+	_string_len = 0;
+	_must_redraw = true;
+}
+
+TextField::~TextField() {
+	if (_string != nullptr)
+		mem_free(_string);
+}
+
+void TextField::set_string(const char *string) {
+	_must_redraw = true;
+
+	if (string == nullptr && _string != nullptr) {
+		_string[0] = '\0';
+		return;
+	}
+
+	int16 string_len = (int16)(cstrlen(string) + 1);
+	if (_string == nullptr) {
+		_string = (char *)mem_alloc(string_len, "string");
+	} else {
+		if (_string_len < string_len) {
+			_string = (char *)mem_realloc(_string, string_len, "string");
+		}
+	}
+
+	if (!_string)
+		error_show(FL, 'OOM!', "TextField set_string:%s", _string);
+
+	_string_len = string_len;
+	cstrcpy(_string, string);
+}
+
+void TextField::draw(GrBuff *myBuffer) {
+	if (!INTERFACE_VISIBLE)
+		return;
+
+	Buffer *myBuff = myBuffer->get_buffer();
+	gr_color_set(__BLACK);
+	gr_buffer_rect_fill(myBuff, _x1, _y1, _x2 - _x1, _y2 - _y1);
+
+	gr_font_set(_G(font_inter));
+	font_set_colors(1, 2, 3);
+	gr_font_write(myBuff, _string, _x1, _y1, 0, 1);
+	myBuffer->release();
+
+	ScreenContext *iC = vmng_screen_find(_G(gameInterfaceBuff), nullptr);
+	RestoreScreensInContext(_x1, _y1, _x2, _y2, iC);
+	_must_redraw = false;
+}
+
+//-------------------------------------------------------------------------------------------
+
+void ButtonClass::init() {
+	_relaxed = _over = _picked = 0;
+	_tag = 0;
+	_must_redraw = true;
+	_state = BUTTON_RELAXED;
+	_tracking = -1;
+}
+
+ButtonClass::ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag) : RectClass(r) {
+	init();
+	_name = btnName;
+	_tag = tag;
+}
+
+ButtonClass::ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag,
+	int16 unknown, int16 relaxed, int16 over, int16 picked, int sprite) : RectClass(r),
+	_tag(tag), _unknown(unknown), _relaxed(relaxed), _over(over), _picked(picked), _sprite(sprite) {
+}
+
+ButtonClass::ButtonClass() : RectClass() {
+	init();
+	_name = "?";
+}
+
+ButtonClass::~ButtonClass() {
+	zap_resources();
+}
+
+void ButtonClass::set_name(const Common::String &btnName) {
+	_name = btnName;
+}
+
+bool ButtonClass::is_hidden() const {
+	return _hidden;
+}
+
+void ButtonClass::set_sprite_relaxed(int16 r) {
+	_relaxed = r;
+}
+
+void ButtonClass::set_sprite_picked(int16 p) {
+	_picked = p;
+}
+
+void ButtonClass::set_sprite_over(int16 o) {
+	_over = o;
+}
+
+void ButtonClass::set_sprite_unknown(int16 val) {
+	_unknown = val;
+}
+
+int16 ButtonClass::get_tag() const {
+	return _tag;
+}
+
+void ButtonClass::zap_resources() {
+	if (_relaxed)
+		ClearWSAssets(_WS_ASSET_CELS, _relaxed, _relaxed);
+	if (_over)
+		ClearWSAssets(_WS_ASSET_CELS, _over, _over);
+	if (_picked)
+		ClearWSAssets(_WS_ASSET_CELS, _picked, _picked);
+}
+
+void ButtonClass::set(const ButtonClass *b) {
+	zap_resources();
+	_name = b->_name;
+	_x1 = b->_x1;
+	_y1 = b->_y1;
+	_x2 = b->_x2;
+	_y2 = b->_y2;
+	_tag = b->_tag;
+	_relaxed = b->_relaxed;
+	_over = b->_over;
+	_picked = b->_picked;
+}
+
+void ButtonClass::set(int16 x1, int16 y1, int16 x2, int16 y2, int16 tag) {
+	_x1 = x1;
+	_y1 = y1;
+	_x2 = x2;
+	_y2 = y2;
+	_tag = tag;
+}
+
+void ButtonClass::set(int16 x1, int16 y1, int16 x2, int16 y2, int16 tag,
+	int16 unknown, int16 relaxed, int16 over, int16 picked, int32 sprite) {
+	zap_resources();
+	_x1 = x1;
+	_y1 = y1;
+	_x2 = x2;
+	_y2 = y2;
+	_tag = tag;
+	_unknown = unknown;
+	_relaxed = relaxed;
+	_over = over;
+	_picked = picked;
+	_sprite = sprite;
+}
+
+int16 ButtonClass::inside(int16 x, int16 y) const {
+	if (RectClass::inside(x, y))
+		return _tag;
+
+	return -1;
+}
+
+ControlStatus ButtonClass::track(int32 eventType, int16 x, int16 y) {
+	if (!INTERFACE_VISIBLE)
+		return NOTHING;
+
+	ButtonState old_state = _state;
+	ControlStatus result = NOTHING;
+
+	bool button_clicked = (eventType == _ME_L_click) || (eventType == _ME_L_hold) || (eventType == _ME_L_drag);
+
+	int16 overTag = inside(x, y);
+
+	if (overTag == _tag) {
+		// if Button is pressed
+		if (button_clicked) {
+			if (_tracking == 1) {
+				result = TRACKING;
+			} else {
+				_tracking = 1;
+				result = IN_CONTROL;
+				_state = BUTTON_PICKED;
+			}
+
+			_G(inv_suppress_click_sound) = false;
+
+		} else {
+			// if Button isn't pressed
+			if (_tracking == 1) {
+				result = SELECTED;
+			} else {
+				result = OVER_CONTROL;
+			}
+
+			_state = BUTTON_OVER;
+			_tracking = -1;
+		}
+	} else {
+		result = NOTHING;
+		_tracking = -1;
+		_state = BUTTON_RELAXED;
+	}
+
+	if (old_state != _state)
+		_must_redraw = true;
+
+	return result;
+}
+
+void ButtonClass::draw(GrBuff *myBuffer) {
+	if (!INTERFACE_VISIBLE)
+		return;
+
+	if (!_must_redraw)
+		return;
+
+	Buffer *myBuff = myBuffer->get_buffer();
+
+	gr_color_set(__BLACK);
+	gr_buffer_rect_fill(myBuff, _x1, _y1 - 2, _x2 - _x1, _y2 - _y1 + 2);
+
+	if (_hidden == false) {
+		switch (_state) {
+		case BUTTON_0:
+			series_show_frame(_sprite, _unknown, myBuff, _x1, _y1);
+			break;
+
+		case BUTTON_RELAXED:
+			series_show_frame(_sprite, _relaxed, myBuff, _x1, _y1);
+			break;
+
+		case BUTTON_OVER:
+			series_show_frame(_sprite, _over, myBuff, _x1, _y1);
+			break;
+
+		case BUTTON_PICKED:
+			series_show_frame(_sprite, _picked, myBuff, _x1, _y1);
+			break;
+		}
+	}
+
+	myBuffer->release();
+
+	_must_redraw = false;
+	ScreenContext *iC = vmng_screen_find(_G(gameInterfaceBuff), nullptr);
+	RestoreScreensInContext(_x1, _y1 - 2, _x2, _y2, iC);
+}
+
+void ButtonClass::hide() {
+	_hidden = true;
+	_must_redraw = true;
+}
+
+void ButtonClass::unhide() {
+	_hidden = false;
+	_must_redraw = true;
+}
+
+//-------------------------------------------------------------------------------------------
+
+Toggler::Toggler() : ButtonClass() {
+	_toggle_state = SELECTED;
+	_state = BUTTON_PICKED;
+}
+
+ControlStatus Toggler::track(int32 eventType, int16 x, int16 y) {
+	if (!INTERFACE_VISIBLE)
+		return NOTHING;
+
+	ButtonState old_state = _state;
+	ControlStatus result = NOTHING;
+
+	bool button_clicked = (eventType == _ME_L_click) || (eventType == _ME_L_hold) || (eventType == _ME_L_drag);
+
+	int16 overTag = inside(x, y);
+
+	if (overTag == _tag) {
+		// if Button is pressed
+		if (button_clicked) {
+			_tracking = 1;
+			result = IN_CONTROL;
+
+		} else {
+			// Button isn't pressed
+			if (_tracking == 1) {
+				result = SELECTED;
+				_toggle_state = (_toggle_state == SELECTED) ? NOTHING : SELECTED;
+			} else {
+				result = OVER_CONTROL;
+			}
+			_tracking = -1;
+		}
+	} else {
+		if (button_clicked && _tracking == 1) {
+			result = TRACKING;
+		} else {
+			result = NOTHING;
+			_tracking = -1;
+		}
+	}
+
+	_state = (_toggle_state == SELECTED) ? BUTTON_PICKED : BUTTON_RELAXED;
+
+	if (old_state != _state)
+		_must_redraw = true;
+
+	return result;
+}
+
+//-------------------------------------------------------------------------------------------
+
+InterfaceBox::InterfaceBox(const RectClass &r) {
+	r.copyInto(this);
+	_highlight_index = -1;
+	_must_redraw_all = true;
+	_selected = false;
+	_index = 0;
+
+	for (int16 iter = 0; iter < MAX_BUTTONS; iter++)
+		_button[iter] = nullptr;
+}
+
+InterfaceBox::~InterfaceBox() {
+}
+
+int16 InterfaceBox::inside(int16 x, int16 y) const {
+	if (!_index)
+		return -1;
+
+	if (!RectClass::inside(x, y))
+		return -1;
+
+	int16 iter;
+	for (iter = 0; iter < _index; iter++) {
+		if (_button[iter]->inside(x, y))
+			return _button[iter]->get_tag();
+	}
+
+	return -1;
+}
+
+void InterfaceBox::highlight_button(int16 index) {
+	if (_highlight_index == index) {
+		return;
+	}
+
+	if (_highlight_index != -1)
+		_button[_highlight_index]->_must_redraw = true;
+
+	if (index == -1)
+		_selected = false;
+
+	_highlight_index = index;
+
+	if (_highlight_index != -1)
+		_button[_highlight_index]->_must_redraw = true;
+}
+
+void InterfaceBox::set_selected(bool s) {
+	if (s == _selected)
+		return;
+
+	_selected = s;
+
+	if (_highlight_index != -1)
+		_button[_highlight_index]->_must_redraw = true;
+}
+
+void InterfaceBox::add(ButtonClass *b) {
+	if (!b) {
+		error_show(FL, 'CGIA');
+	} else if (_index >= MAX_BUTTONS) {
+		error_show(FL, 'CGIA');
+	} else {
+		// Convert to global coordinates
+		b->_x1 += _x1;
+		b->_x2 += _x1;
+		b->_y1 += _y1;
+		b->_y2 += _y1;
+
+		_button[_index] = b;
+		_button[_index]->_must_redraw = true;
+		++_index;
+	}
+}
+
+ControlStatus InterfaceBox::track(int32 eventType, int16 x, int16 y) {
+	ControlStatus result = NOTHING;
+
+	for (int iter = 0; iter < _index; iter++) {
+		if (_button[iter]->track(eventType, x, y) == SELECTED) {
+			_highlight_index = _button[iter]->get_tag();
+			term_message("selected button: %d", iter);
+			result = SELECTED;
+			break;
+		}
+	}
+
+	return result;
+}
+
+void InterfaceBox::draw(GrBuff *myBuffer) {
+	if (!INTERFACE_VISIBLE)
+		return;
+
+	for (int iter = 0; iter < _index; iter++) {
+		_button[iter]->_must_redraw |= _must_redraw_all;
+		_button[iter]->draw(myBuffer);
+	}
+
+	if (_must_redraw_all) {
+		ScreenContext *iC = vmng_screen_find(_G(gameInterfaceBuff), nullptr);
+		RestoreScreensInContext(_x1, _y1, _x2, _y2, iC);
+	}
+
+	_must_redraw_all = false;
+}
+
+} // namespace GUI
+} // namespace M4
diff --git a/engines/m4/gui/gui_cheapo.h b/engines/m4/gui/gui_cheapo.h
new file mode 100644
index 00000000000..3ee81afef1a
--- /dev/null
+++ b/engines/m4/gui/gui_cheapo.h
@@ -0,0 +1,162 @@
+
+/* 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 M4_GUI_CHEAPO_H
+#define M4_GUI_CHEAPO_H
+
+#include "common/str.h"
+#include "m4/graphics/gr_buff.h"
+#include "m4/m4_types.h"
+
+namespace M4 {
+namespace GUI {
+
+constexpr int16 MAX_BUTTONS = 20;
+
+enum ControlStatus {
+	NOTHING, IN_CONTROL, OVER_CONTROL, SELECTED, TRACKING
+};
+
+enum ButtonState {
+	BUTTON_0, BUTTON_RELAXED, BUTTON_OVER, BUTTON_PICKED
+};
+
+class RectClass;
+class ButtonClass;
+class InterfaceBox;
+
+class RectClass {
+public:
+	int16 _x1 = 0, _x2 = 0, _y1 = 0, _y2 = 0;
+public:
+	RectClass();
+	RectClass(int16 x1, int16 y1, int16 x2, int16 y2);
+	RectClass(const RectClass *);
+	virtual ~RectClass();
+	virtual int16 inside(int16 x, int16 y) const;
+
+	void copyInto(RectClass *r) const;
+
+	void set(int16 x1, int16 y1, int16 x2, int16 y2);
+	void set(const RectClass *r);
+};
+
+class TextField : public RectClass {
+private:
+	char *_string = nullptr;
+	int16 _string_len = 0;
+public:
+	bool _must_redraw = false;
+
+public:
+	TextField(int16 x1, int16 y1, int16 x2, int16 y2);
+	~TextField();
+
+	void set_string(const char *string);
+	void draw(GrBuff *interface_buffer);
+};
+
+class ButtonClass : public RectClass {
+protected:
+	int16 _tag = 0;
+	int16 _unknown = 0;
+	int16 _relaxed = 0;
+	int16 _over = 0;
+	int16 _picked = 0;
+	int16 _tracking = 0;
+	int32 _sprite = 0;
+	bool _highlighted = false;
+	bool _hidden = false;
+
+	void init();
+	void zap_resources();
+
+public:
+	ButtonState	_state = BUTTON_RELAXED;
+	Common::String _name;
+	bool _must_redraw = false;
+
+public:
+	ButtonClass();
+	ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag);
+	ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag,
+		int16 unknown, int16 relaxed, int16 over, int16 picked, int sprite);
+	~ButtonClass();
+
+	void draw(GrBuff *interface_buffer);
+	int16 inside(int16 x, int16 y) const override;
+	virtual ControlStatus track(int32 eventType, int16 x, int16 y);
+
+	void set(const ButtonClass *b);
+	void set(int16 x1, int16 y1, int16 x2, int16 y2, int16 tag);
+	void set(int16 x1, int16 y1, int16 x2, int16 y2, int16 tag, int16 unknown,
+		int16 relaxed, int16 over, int16 picked, int32 sprite);
+	void set_name(const Common::String &btnName);
+
+	int16 get_tag() const;
+
+	void hide();
+	void unhide();
+	bool is_hidden() const;
+	void set_sprite_relaxed(int16 r);
+	void set_sprite_picked(int16 p);
+	void set_sprite_over(int16 o);
+	void set_sprite_unknown(int16 val);
+};
+
+class Toggler : public ButtonClass {
+public:
+	ControlStatus _toggle_state;
+public:
+	Toggler();
+	ControlStatus track(int32 eventType, int16 x, int16 y);
+};
+
+class InterfaceBox : public RectClass {
+private:
+	bool _selected = false;
+	int16 _index = 0;
+	ButtonClass *_button[MAX_BUTTONS] = { nullptr };
+
+public:
+	int16 _highlight_index = 0;
+	bool _must_redraw_all = false;
+
+public:
+	InterfaceBox(const RectClass &r);
+	~InterfaceBox();
+
+	void draw(GrBuff *interface_buffer);
+	int16 inside(int16 x, int16 y) const override;
+	ControlStatus track(int32 eventType, int16 x, int16 y);
+
+	void add(ButtonClass *b);
+	int16 check_inventory(int16 x, int16 y);
+	void highlight_button(int16 index);
+	void set_selected(bool);
+
+};
+
+} // namespace GUI
+} // namespace M4
+
+#endif
diff --git a/engines/m4/module.mk b/engines/m4/module.mk
index 070b4700886..5bfc7399751 100644
--- a/engines/m4/module.mk
+++ b/engines/m4/module.mk
@@ -49,6 +49,7 @@ MODULE_OBJS = \
 	graphics/krn_pal.o \
 	graphics/rend.o \
 	gui/gui_buffer.o \
+	gui/gui_cheapo.o \
 	gui/gui_dialog.o \
 	gui/gui_item.o \
 	gui/gui_mouse.o \
@@ -180,6 +181,7 @@ MODULE_OBJS = \
 	burger/series_player.o \
 	burger/vars.o \
 	burger/walker.o \
+	riddle/gui/gui_cheapo.o \
 	riddle/gui/interface.o \
 	riddle/rooms/room.o \
 	riddle/rooms/section.o \
diff --git a/engines/m4/riddle/gui/gui_cheapo.cpp b/engines/m4/riddle/gui/gui_cheapo.cpp
new file mode 100644
index 00000000000..18a3d2fa1c5
--- /dev/null
+++ b/engines/m4/riddle/gui/gui_cheapo.cpp
@@ -0,0 +1,292 @@
+/* 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 "m4/riddle/gui/gui_cheapo.h"
+#include "m4/riddle/vars.h"
+#include "m4/core/errors.h"
+#include "m4/graphics/gr_line.h"
+#include "m4/graphics/gr_series.h"
+#include "m4/gui/gui_vmng_core.h"
+#include "m4/gui/gui_vmng_screen.h"
+
+namespace M4 {
+namespace Riddle {
+namespace GUI {
+
+Inventory::Inventory(const RectClass &r, int32 sprite, int16 cells_h, int16 cells_v, int16 cell_w, int16 cell_h, int16 tag)
+	: RectClass(r) {
+	_sprite = sprite;
+
+	for (int16 iter = 0; iter < INVENTORY_CELLS_COUNT; iter++) {
+		_items[iter]._cell = -1;
+		_items[iter]._cursor = -1;
+	}
+
+	_num_cells = 0;
+	_tag = tag;
+	_cells_h = cells_h;
+	_cells_v = cells_v;
+	_cell_w = cell_w;
+	_cell_h = cell_h;
+
+	// If requested cell configuration doesn't fit, blow up.
+	if ((cells_h * cell_w > (_x2 - _x1)) || (cells_v * cell_h > (_y2 - _y1))) {
+		error_show(FL, 'CGIC');
+	}
+
+	_highlight = -1;
+	_must_redraw_all = true;
+	_must_redraw1 = -1;
+	_must_redraw2 = -1;
+	_scroll = 0;
+	_right_arrow_visible = false;
+}
+
+Inventory::~Inventory() {
+}
+
+bool Inventory::add(const Common::String &name, const Common::String &verb, int32 invSprite, int32 cursor) {
+	// Don't add something twice
+	int iter;
+	for (iter = 0; iter < _num_cells; iter++) {
+		if (name.equals(_items[iter]._name))
+			return true;
+	}
+
+	if (_num_cells >= INVENTORY_CELLS_COUNT) {
+		error_show(FL, 'CGIA');
+		return false;
+	}
+
+	// Shift existing items up by one
+	for (int i = _num_cells; i > 0; --i)
+		_items[i] = _items[i - 1];
+
+	auto &item = _items[0];
+	item._name = name;
+	item._verb = verb;
+	item._cell = invSprite;
+	item._cursor = cursor;
+	++_num_cells;
+
+	_must_redraw_all = true;
+
+	if (INTERFACE_VISIBLE)
+		_G(interface).show();
+
+	return true;
+}
+
+bool Inventory::need_left() const {
+	return (_scroll != 0);
+}
+
+bool Inventory::need_right() const {
+	if ((_num_cells - _scroll - MAX_INVENTORY) > 0)
+		return true;
+
+	return false;
+}
+
+void Inventory::set_scroll(int32 new_scroll) {
+	_scroll = new_scroll;
+	_must_redraw_all = true;
+}
+
+bool Inventory::remove(const Common::String &name) {
+	int iter;
+	for (iter = 0; iter < _num_cells; iter++) {
+		// Found the thing?
+		if (name.equals(_items[iter]._name)) {
+			// Eat up its slot by moving everything down
+			for (; iter < _num_cells; ++iter)
+				_items[iter] = _items[iter + 1];
+
+			--_num_cells;
+			_must_redraw_all = true;
+			_scroll = 0;
+
+			if (INTERFACE_VISIBLE)
+				_G(interface).show();
+
+			return true;
+		}
+	}
+
+	// Didn't find that thing.
+	return false;
+}
+
+int16 Inventory::inside(int16 x, int16 y) const {
+	if ((x < _x1) || (x >= (_x2 - 1)) || (y < _y1 + 2) ||
+		(y > _y1 + _cells_v * _cell_h - 2))
+		return -1;
+
+	x -= _x1;
+	y -= _y1;
+	return (int16)((x / _cell_w) * _cells_v + (y / _cell_h));
+}
+
+int16 Inventory::cell_pos_x(int16 index) {
+	if (_cells_h > _cells_v) {				// Horizontal orientation, fill left to right
+		return (int16)((index / _cells_v) * _cell_w);
+	} else {								// Vertical orientation, fill top to bottom
+		return (int16)((index / _cells_h) * _cell_w);
+	}
+}
+
+int16 Inventory::cell_pos_y(int16 index) {
+	if (_cells_h > _cells_v) {
+		// Horizontal orientation, fill left to right
+		return (int16)((index % _cells_v) * _cell_h);
+	} else {
+		// Vertical orientation, fill top to bottom
+		return (int16)((index % _cells_h) * _cell_h);
+	}
+}
+
+void Inventory::highlight_part(int16 index) {
+	if (_highlight == index)
+		return;
+
+	_must_redraw1 = _highlight;
+	_highlight = index;
+	_must_redraw2 = _highlight;
+}
+
+void Inventory::draw(GrBuff *myBuffer) {
+	if (!INTERFACE_VISIBLE)
+		return;
+
+	if (!_must_redraw1 && !_must_redraw2 && !_must_redraw_all)
+		return;
+
+	int cell_iter;
+
+	Buffer *myBuff = myBuffer->get_buffer();
+
+	if (_must_redraw_all) {
+		gr_color_set(__BLACK);
+		gr_buffer_rect_fill(myBuff, _x1, _y1, _x2 - _x1, _y2 - _y1);
+	}
+
+	_right_arrow_visible = false;
+
+	for (cell_iter = 0; (cell_iter + _scroll < _num_cells) && (cell_iter < MAX_INVENTORY); cell_iter++) {
+		int16 left = (int16)(_x1 + cell_pos_x(cell_iter));
+		int16 top = (int16)(_y1 + cell_pos_y(cell_iter));
+		int16 leftOffset = left + _cell_w;
+		int16 topOffset = top + _cell_h;
+
+		if (_must_redraw1 == cell_iter || _must_redraw2 == cell_iter || _must_redraw_all) {
+			// This does the button update....
+			_G(interface).refresh_right_arrow();
+			_G(interface).refresh_left_arrow();
+
+			// Draw icon here
+			gr_color_set(__BLACK);
+			gr_buffer_rect_fill(myBuff, left, top, leftOffset - left, topOffset - top);
+			series_show_frame(_sprite, _items[cell_iter + _scroll]._cell, myBuff,
+				left + (_cell_w - 31) / 2, top + (_cell_h - 31) / 2);
+
+			// Draw box around icon
+			if (_highlight == cell_iter) {
+				left += 2;
+				top += 20;
+				gr_line(left, top, left + 35, top, __GREEN, myBuff);
+				gr_line(left + 35, top, left + 35, top + 35, __GREEN, myBuff);
+				gr_line(left, top, left, top + 35, __GREEN, myBuff);
+				gr_line(left, top + 35, left + 35, top + 35, __GREEN, myBuff);
+			}
+		}
+	}
+
+	// Draw inventory slot frames
+	for (cell_iter = 0; cell_iter < MAX_INVENTORY; ++cell_iter) {
+		series_show_frame(_sprite, 67, myBuff, cell_iter * 39 + 188, 22);
+		series_show_frame(_sprite, 68, myBuff, cell_iter * 39 + 188, 92);
+	}
+
+	ScreenContext *iC = vmng_screen_find(_G(gameInterfaceBuff), nullptr);
+	RestoreScreensInContext(_x1, _y1, _x2, _y2, iC);
+	_must_redraw1 = _must_redraw2 = -1;
+	_must_redraw_all = false;
+
+	myBuffer->release();
+}
+
+ControlStatus Inventory::track(int32 eventType, int16 x, int16 y) {
+	if (!INTERFACE_VISIBLE)
+		return NOTHING;
+
+	ControlStatus result = NOTHING;
+
+	int16 over = inside(x, y);
+	bool button_clicked = eventType == _ME_L_click || eventType == _ME_L_hold || eventType == _ME_L_drag;
+
+	// If Button is pressed
+	if (button_clicked) {
+		// If we are not tracking, start tracking
+		if (interface_tracking == -1) {
+			highlight_part(over);
+			interface_tracking = over;
+			result = IN_CONTROL;
+		} else {
+			// Else if we are over something we are tracking
+			if (interface_tracking == over) {
+				highlight_part(over);
+				result = IN_CONTROL;
+			} else {
+				// Else highlight nothing
+				highlight_part(-1);
+				result = NOTHING;
+			}
+		}
+	} else {
+		// If Button isn't pressed
+
+		// If we unpressed on something we were tracking
+		if (interface_tracking == over) {
+			if (interface_tracking == -1)
+				result = NOTHING;
+			else
+				result = SELECTED;
+		} else {
+			if (over + _scroll < _num_cells)
+				result = OVER_CONTROL;
+			else
+				result = NOTHING;
+		}
+
+		// Stop tracking anything
+		highlight_part(over);
+		interface_tracking = -1;
+	}
+
+	if (result == NOTHING && button_clicked)
+		return TRACKING;
+
+	return result;
+}
+
+} // namespace GUI
+} // namespace Riddle
+} // namespace M4
diff --git a/engines/m4/riddle/gui/gui_cheapo.h b/engines/m4/riddle/gui/gui_cheapo.h
new file mode 100644
index 00000000000..e441283a5cc
--- /dev/null
+++ b/engines/m4/riddle/gui/gui_cheapo.h
@@ -0,0 +1,99 @@
+
+/* 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 M4_RIDDLE_GUI_CHEAPO_H
+#define M4_RIDDLE_GUI_CHEAPO_H
+
+#include "m4/gui/gui_cheapo.h"
+
+namespace M4 {
+namespace Riddle {
+namespace GUI {
+
+using namespace M4::GUI;
+
+constexpr int16 INVENTORY_CELLS_COUNT = 128;
+constexpr int16 ARROW_WIDTH = 8;
+constexpr int16 MAX_INVENTORY = 9;
+
+constexpr int16 LEFT_ARROW_TAG = 128;
+constexpr int16 RIGHT_ARROW_TAG = 129;
+
+constexpr int16 LEFT_ARROW_TAG_DORMANT = 130;
+constexpr int16 RIGHT_ARROW_TAG_DORMANT = 134;
+constexpr int16 LEFT_ARROW_TAG_ROLL = 131;
+constexpr int16 RIGHT_ARROW_TAG_ROLL = 135;
+constexpr int16 LEFT_ARROW_TAG_DOWN = 132;
+constexpr int16 RIGHT_ARROW_TAG_DOWN = 136;
+constexpr int16 LEFT_ARROW_TAG_NONFUNC = 133;
+constexpr int16 RIGHT_ARROW_TAG_NONFUNC = 137;
+
+class Inventory : public RectClass {
+	struct Entry {
+		Common::String _name;
+		Common::String _verb;
+		int16 _cell = -1;
+		int16 _cursor = -1;
+	};
+private:
+	int32 _sprite = 0;
+	int16 _tag = 0;
+	int16 _num_cells = 0;
+	bool _right_arrow_visible = false;
+
+	int16 cell_pos_x(int16 index);
+	int16 cell_pos_y(int16 index);
+	int16 interface_tracking = -1;
+
+public:
+	int16 _scroll = 0;
+	int16 _cells_h = 0, _cells_v = 0;
+	int16 _cell_w = 0, _cell_h = 0;
+	int16 _must_redraw1 = 0, _must_redraw2 = 0;
+	int16 _highlight = 0;
+	bool _must_redraw_all = false;
+
+	Entry _items[INVENTORY_CELLS_COUNT];
+
+public:
+	Inventory(const RectClass &r, int32 sprite, int16 cells_h, int16 cells_v, int16 cell_w, int16 cell_h, int16 tag);
+	~Inventory();
+
+	void draw(GrBuff *interface_buffer);
+
+	int16 inside(int16 x, int16 y) const override;
+	ControlStatus track(int32 eventType, int16 x, int16 y);
+
+	bool add(const Common::String &name, const Common::String &verb, int32 cel, int32 cursor);
+	bool remove(const Common::String &name);
+	void highlight_part(int16 index);
+
+	bool need_left() const;
+	bool need_right() const;
+	void set_scroll(int32 new_scroll);
+};
+
+} // namespace GUI
+} // namespace Riddle
+} // namespace M4
+
+#endif
diff --git a/engines/m4/riddle/gui/interface.cpp b/engines/m4/riddle/gui/interface.cpp
index 0a8612c2016..4354c71d724 100644
--- a/engines/m4/riddle/gui/interface.cpp
+++ b/engines/m4/riddle/gui/interface.cpp
@@ -432,7 +432,7 @@ ControlStatus Interface::trackHotspots(int event, int x, int y) {
 		return IN_CONTROL;
 	}
 #endif
-	return NOTHING;
+	return ControlStatus::NOTHING;
 }
 
 void Interface::dispatch_command() {
diff --git a/engines/m4/riddle/gui/interface.h b/engines/m4/riddle/gui/interface.h
index 9e98dfa025e..87a0dd9f3ae 100644
--- a/engines/m4/riddle/gui/interface.h
+++ b/engines/m4/riddle/gui/interface.h
@@ -27,14 +27,13 @@
 #include "m4/adv_r/adv_hotspot.h"
 #include "m4/graphics/graphics.h"
 #include "m4/graphics/gr_buff.h"
+#include "m4/gui/gui_cheapo.h"
 
 namespace M4 {
 namespace Riddle {
 namespace GUI {
 
-enum ControlStatus {
-	NOTHING, IN_CONTROL, OVER_CONTROL, SELECTED, TRACKING
-};
+using M4::GUI::ControlStatus;
 
 struct Interface : public M4::Interface {
 private:


Commit: 23662f44d5ffddfe75cdfa3f47ab8b880c3f070a
    https://github.com/scummvm/scummvm/commit/23662f44d5ffddfe75cdfa3f47ab8b880c3f070a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2024-10-05T20:36:19-07:00

Commit Message:
M4: RIDDLE: Beginnings of user interface

Changed paths:
    engines/m4/console.cpp
    engines/m4/console.h
    engines/m4/gui/gui_cheapo.cpp
    engines/m4/gui/gui_cheapo.h
    engines/m4/riddle/gui/gui_cheapo.h
    engines/m4/riddle/gui/interface.cpp
    engines/m4/riddle/gui/interface.h
    engines/m4/riddle/vars.cpp


diff --git a/engines/m4/console.cpp b/engines/m4/console.cpp
index 29a06645641..268aa857fba 100644
--- a/engines/m4/console.cpp
+++ b/engines/m4/console.cpp
@@ -34,6 +34,7 @@ Console::Console() : GUI::Debugger() {
 	registerCmd("trigger",   WRAP_METHOD(Console, cmdTrigger));
 	registerCmd("cels",      WRAP_METHOD(Console, cmdCels));
 	registerCmd("cel",       WRAP_METHOD(Console, cmdCel));
+	registerCmd("interface", WRAP_METHOD(Console, cmdInterface));
 }
 
 bool Console::cmdTeleport(int argc, const char **argv) {
@@ -129,4 +130,20 @@ bool Console::cmdCel(int argc, const char **argv) {
 	return true;
 }
 
+bool Console::cmdInterface(int argc, const char **argv) {
+	if (argc < 2) {
+		debugPrintf("interface ['show', 'hide']\n");
+		return true;
+	} else {
+		Common::String param(argv[1]);
+
+		if (param == "hide" || param == "off" || param == "false")
+			interface_hide();
+		else
+			interface_show();
+
+		return false;
+	}
+}
+
 } // End of namespace M4
diff --git a/engines/m4/console.h b/engines/m4/console.h
index e2861ac4036..a4bb2c86051 100644
--- a/engines/m4/console.h
+++ b/engines/m4/console.h
@@ -36,6 +36,7 @@ private:
 	bool cmdTrigger(int argc, const char **argv);
 	bool cmdCels(int argc, const char **argv);
 	bool cmdCel(int argc, const char **argv);
+	bool cmdInterface(int argc, const char **argv);
 
 public:
 	Console();
diff --git a/engines/m4/gui/gui_cheapo.cpp b/engines/m4/gui/gui_cheapo.cpp
index 47c6cc0423f..0bc1f33b596 100644
--- a/engines/m4/gui/gui_cheapo.cpp
+++ b/engines/m4/gui/gui_cheapo.cpp
@@ -170,6 +170,11 @@ ButtonClass::ButtonClass(const RectClass &r, const Common::String &btnName, int1
 	_tag(tag), _unknown(unknown), _relaxed(relaxed), _over(over), _picked(picked), _sprite(sprite) {
 }
 
+ButtonClass::ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag,
+	int16 relaxed, int16 over, int16 picked, int sprite) : RectClass(r),
+	_tag(tag), _unknown(0), _relaxed(relaxed), _over(over), _picked(picked), _sprite(sprite) {
+}
+
 ButtonClass::ButtonClass() : RectClass() {
 	init();
 	_name = "?";
diff --git a/engines/m4/gui/gui_cheapo.h b/engines/m4/gui/gui_cheapo.h
index 3ee81afef1a..120b799f014 100644
--- a/engines/m4/gui/gui_cheapo.h
+++ b/engines/m4/gui/gui_cheapo.h
@@ -100,6 +100,8 @@ public:
 	ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag);
 	ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag,
 		int16 unknown, int16 relaxed, int16 over, int16 picked, int sprite);
+	ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag,
+		int16 relaxed, int16 over, int16 picked, int sprite);
 	~ButtonClass();
 
 	void draw(GrBuff *interface_buffer);
diff --git a/engines/m4/riddle/gui/gui_cheapo.h b/engines/m4/riddle/gui/gui_cheapo.h
index e441283a5cc..427e027598b 100644
--- a/engines/m4/riddle/gui/gui_cheapo.h
+++ b/engines/m4/riddle/gui/gui_cheapo.h
@@ -47,6 +47,17 @@ constexpr int16 RIGHT_ARROW_TAG_DOWN = 136;
 constexpr int16 LEFT_ARROW_TAG_NONFUNC = 133;
 constexpr int16 RIGHT_ARROW_TAG_NONFUNC = 137;
 
+class BackpackClass : public ButtonClass {
+private:
+	int _field32 = 0;
+
+public:
+	BackpackClass(const RectClass &r, const Common::String &btnName, int16 tag,
+		int16 relaxed, int16 over, int16 picked, int sprite) :
+		ButtonClass(r, btnName, tag, relaxed, over, picked, sprite) {}
+	~BackpackClass() override {}
+};
+
 class Inventory : public RectClass {
 	struct Entry {
 		Common::String _name;
diff --git a/engines/m4/riddle/gui/interface.cpp b/engines/m4/riddle/gui/interface.cpp
index 4354c71d724..f62dca28895 100644
--- a/engines/m4/riddle/gui/interface.cpp
+++ b/engines/m4/riddle/gui/interface.cpp
@@ -20,14 +20,15 @@
  */
 
 #include "m4/riddle/gui/interface.h"
+#include "m4/riddle/gui/gui_cheapo.h"
+#include "m4/riddle/riddle.h"
+#include "m4/riddle/vars.h"
+#include "m4/adv_r/other.h"
 #include "m4/core/cstring.h"
 #include "m4/core/errors.h"
 #include "m4/graphics/gr_series.h"
 #include "m4/gui/gui_event.h"
 #include "m4/gui/gui_vmng.h"
-#include "m4/riddle/riddle.h"
-#include "m4/riddle/vars.h"
-#include "m4/adv_r/other.h"
 
 namespace M4 {
 namespace Riddle {
@@ -45,7 +46,9 @@ Interface::Interface() : M4::Interface() {
 bool Interface::init(int arrow, int wait, int look, int grab, int use) {
 	M4::Interface::init(arrow, wait, look, grab, use);
 
-	_sprite = series_load("999intr", 22, nullptr);
+	_sprite = AddWSAssetCELS("INTERFACE STUFF", 22, _G(master_palette));
+	gr_pal_interface(_G(master_palette));
+
 	if (_sprite != 22)
 		error_show(FL, 'SLF!');
 
@@ -61,64 +64,51 @@ bool Interface::init(int arrow, int wait, int look, int grab, int use) {
 }
 
 Interface::~Interface() {
-#ifdef TODO
 	delete _interfaceBox;
 	delete _inventory;
 	delete _textField;
 	delete _btnTake;
 	delete _btnManipulate;
 	delete _btnHandle;
-	delete _btnAbductFail;
-	delete _btnMenu;
+	delete _btnBackpack;
+	delete _btnBinky;
 	delete _btnScrollLeft;
 	delete _btnScrollRight;
-#endif
 }
 
 void Interface::show() {
-#ifdef TODO
 	M4::Interface::show();
 	_interfaceBox->_must_redraw_all = true;
 	vmng_screen_show(_G(gameInterfaceBuff));
 	_visible = true;
 	track_hotspots_refresh();
-#endif
 }
 
 void Interface::setup() {
-#ifdef TODO
-	_interfaceBox = new InterfaceBox(RectClass(0, 0, SCREEN_WIDTH - 1, 105));
-	_inventory = new GUI::Inventory(RectClass(188, 22, 539, 97), _sprite, 9, 1, 39, 75, 3);
-	_textField = new TextField(200, 1, 450, 21);
-	_btnTake = new ButtonClass(RectClass(60, 35, 92, 66), "take", 4, 3, 3, 4, 5, INTERFACE_SPRITES);
-	_btnManipulate = new ButtonClass(RectClass(105, 35, 137, 66), "manipulate", 7, 6, 6, 7, 8, INTERFACE_SPRITES);
-	_btnHandle = new ButtonClass(RectClass(15, 35, 47, 66), "handle", 5, 0, 0, 1, 2, INTERFACE_SPRITES);
-
+	_interfaceBox = new InterfaceBox(RectClass(10, 10, SCREEN_WIDTH - 11, 101));
+	_inventory = new GUI::Inventory(RectClass(207, 2, 557, 74),
+		_sprite, 4, 2, 35, 35, 3);
+	_textField = new TextField(13, 2, 189, 20);
+
+	_btnTake = new ButtonClass(RectClass(2, 10, 40, 50), "take", 4,3, 5, 4, INTERFACE_SPRITES);
+	_btnManipulate = new ButtonClass(RectClass(47, 10, 86, 50), "manipulate", 7, 6, 8, 7, INTERFACE_SPRITES);
+	_btnHandle = new ButtonClass(RectClass(92, 10, 130, 50), "handle", 5, 0, 2, 4, INTERFACE_SPRITES);
 	_interfaceBox->add(_btnTake);
 	_interfaceBox->add(_btnManipulate);
 	_interfaceBox->add(_btnHandle);
 
+	_btnBackpack = new BackpackClass(RectClass(135, 10, 176, 50), "backpack", 6, 9, 9, 10, INTERFACE_SPRITES);
+	_btnBinky = new ButtonClass(RectClass(582, 10, 629, 50), "binky", 8, 11, 13, 12, INTERFACE_SPRITES);
+	_interfaceBox->add(_btnBackpack);
+	_interfaceBox->add(_btnBinky);
 
-	if (_G(executing) == WHOLE_GAME) {
-		_btnAbductFail = new ButtonClass(RectClass(580, 10, 620, 69), "abductfail", 10, 69, 69, 70, 71, INTERFACE_SPRITES);
-		_btnMenu = new ButtonClass(RectClass(582, 70, 619, 105), "menu", 11, 76, 76, 77, 78, INTERFACE_SPRITES);
-		_interfaceBox->add(_btnAbductFail);
-		_interfaceBox->add(_btnMenu);
-
-	} else {
-		_btnAbductFail = new ButtonClass(RectClass(580, 22, 620, 75), "abductfail", 10, 69, 69, 70, 71, INTERFACE_SPRITES);
-		_interfaceBox->add(_btnAbductFail);
-	}
-
-	_btnScrollLeft = new ButtonClass(RectClass(168, 22, 188, 97), "scroll left", 8, 59, 60, 61, 62, INTERFACE_SPRITES);
-	_btnScrollRight = new ButtonClass(RectClass(539, 22, 559, 97), "scroll right", 9, 63, 64, 65, 66, INTERFACE_SPRITES);
+	_btnScrollLeft = new ButtonClass(RectClass(178, -8, 198, 101), "scroll left", 9, 129, 130, 131, INTERFACE_SPRITES);
+	_btnScrollRight = new ButtonClass(RectClass(551, -8, 571, 10), "scroll right", 9, 133, 134, 135, INTERFACE_SPRITES);
 	_interfaceBox->add(_btnScrollLeft);
 	_interfaceBox->add(_btnScrollRight);
-#endif
 }
 
 void Interface::cancel_sentence() {
-#ifdef TODO
 	_textField->set_string(" ");
 	_G(player).need_to_walk = false;
 	_G(player).ready_to_walk = false;
@@ -130,11 +120,9 @@ void Interface::cancel_sentence() {
 	_iconSelected = false;
 
 	track_hotspots_refresh();
-#endif
 }
 
 void Interface::freshen_sentence() {
-#ifdef TODO
 	_textField->set_string(" ");
 	_G(player).need_to_walk = false;
 	_G(player).ready_to_walk = _G(player).need_to_walk;
@@ -143,42 +131,30 @@ void Interface::freshen_sentence() {
 	_nounText[0] = '\0';
 
 	track_hotspots_refresh();
-#endif
 }
 
 bool Interface::set_interface_palette(RGB8 *myPalette) {
+	gr_pal_set_RGB8(&myPalette[0], 0, 0, 0);
 	gr_pal_set_RGB8(&myPalette[1], 0, 68, 0);
-	gr_pal_set_RGB8(&myPalette[2], 0, 134, 0);
-	gr_pal_set_RGB8(&myPalette[3], 0, 204, 0);
-	gr_pal_set_RGB8(&myPalette[4], 28, 8, 90);
-	gr_pal_set_RGB8(&myPalette[5], 204, 204, 250);
-	gr_pal_set_RGB8(&myPalette[6], 204, 204, 102);
-	gr_pal_set_RGB8(&myPalette[7], 5, 1, 0);
-	gr_pal_set_RGB8(&myPalette[8], 102, 51, 222);
-	gr_pal_set_RGB8(&myPalette[9], 85, 117, 255);
-	gr_pal_set_RGB8(&myPalette[10], 68, 68, 68);
-	gr_pal_set_RGB8(&myPalette[11], 51, 255, 0);
-	gr_pal_set_RGB8(&myPalette[12], 51, 51, 115);
-	gr_pal_set_RGB8(&myPalette[13], 119, 119, 119);
-	gr_pal_set_RGB8(&myPalette[14], 151, 153, 150);
-	gr_pal_set_RGB8(&myPalette[15], 153, 0, 0);
-	gr_pal_set_RGB8(&myPalette[16], 153, 53, 9);
-	gr_pal_set_RGB8(&myPalette[17], 117, 246, 255);
-	gr_pal_set_RGB8(&myPalette[18], 88, 0, 0);
-	gr_pal_set_RGB8(&myPalette[19], 195, 0, 83);
-	gr_pal_set_RGB8(&myPalette[20], 204, 102, 61);
-	gr_pal_set_RGB8(&myPalette[21], 204, 153, 118);
-	gr_pal_set_RGB8(&myPalette[22], 204, 255, 204);
-	gr_pal_set_RGB8(&myPalette[23], 207, 158, 73);
-	gr_pal_set_RGB8(&myPalette[24], 238, 0, 0);
-	gr_pal_set_RGB8(&myPalette[25], 248, 51, 31);
-	gr_pal_set_RGB8(&myPalette[26], 255, 131, 0);
-	gr_pal_set_RGB8(&myPalette[27], 255, 153, 102);
-	gr_pal_set_RGB8(&myPalette[28], 255, 204, 153);
-	gr_pal_set_RGB8(&myPalette[29], 255, 252, 144);
-	gr_pal_set_RGB8(&myPalette[30], 255, 255, 0);
-	gr_pal_set_RGB8(&myPalette[31], 255, 255, 255);
-	gr_pal_set_range(myPalette, 1, 31);
+	gr_pal_set_RGB8(&myPalette[2], 0, 0, 39);
+	gr_pal_set_RGB8(&myPalette[3], 0, 75, 71);
+	gr_pal_set_RGB8(&myPalette[4], 0, 107, 103);
+	gr_pal_set_RGB8(&myPalette[5], 0, 135, 131);
+	gr_pal_set_RGB8(&myPalette[6], 0, 171, 163);
+	gr_pal_set_RGB8(&myPalette[7], 199, 215, 207);
+	gr_pal_set_RGB8(&myPalette[8], 235, 247, 231);
+	gr_pal_set_RGB8(&myPalette[9], 131, 103, 63);
+	gr_pal_set_RGB8(&myPalette[10], 143, 115, 75);
+	gr_pal_set_RGB8(&myPalette[11], 155, 127, 91);
+	gr_pal_set_RGB8(&myPalette[12], 167, 143, 107);
+	gr_pal_set_RGB8(&myPalette[13], 175, 131, 115);
+	gr_pal_set_RGB8(&myPalette[14], 199, 155, 131);
+	gr_pal_set_RGB8(&myPalette[15], 227, 183, 143);
+	gr_pal_set_RGB8(&myPalette[16], 255, 215, 159);
+	gr_pal_set_RGB8(&myPalette[17], 99, 27, 39);
+	gr_pal_set_RGB8(&myPalette[18], 83, 19, 27);
+	gr_pal_set_RGB8(&myPalette[19], 71, 11, 19);
+	gr_pal_set_RGB8(&myPalette[20], 59, 7, 15);
 
 	return true;
 }
@@ -193,7 +169,6 @@ void Interface::track_hotspots_refresh() {
 }
 
 bool Interface::eventHandler(void *bufferPtr, int32 eventType, int32 event, int32 x, int32 y, bool *z) {
-#ifdef TODO
 	if (eventType != EVENT_MOUSE)
 		return false;
 
@@ -256,7 +231,7 @@ bool Interface::eventHandler(void *bufferPtr, int32 eventType, int32 event, int3
 	_interfaceBox->draw(_G(gameInterfaceBuff));
 	_textField->draw(_G(gameInterfaceBuff));
 	_inventory->draw(_G(gameInterfaceBuff));
-#endif
+
 	return true;
 }
 
@@ -380,7 +355,6 @@ void Interface::trackIcons() {
 }
 
 ControlStatus Interface::trackHotspots(int event, int x, int y) {
-#ifdef TODO
 	const HotSpotRec *hotspot = g_engine->_activeRoom->custom_hotspot_which(x, y);
 	if (!hotspot)
 		hotspot = hotspot_which(_G(currentSceneDef).hotspots, x, y);
@@ -431,7 +405,7 @@ ControlStatus Interface::trackHotspots(int event, int x, int y) {
 	} else {
 		return IN_CONTROL;
 	}
-#endif
+
 	return ControlStatus::NOTHING;
 }
 
diff --git a/engines/m4/riddle/gui/interface.h b/engines/m4/riddle/gui/interface.h
index 87a0dd9f3ae..695585e82ba 100644
--- a/engines/m4/riddle/gui/interface.h
+++ b/engines/m4/riddle/gui/interface.h
@@ -23,11 +23,11 @@
 #ifndef M4_RIDDLE_INTERFACE_H
 #define M4_RIDDLE_INTERFACE_H
 
+#include "m4/riddle/gui/gui_cheapo.h"
 #include "m4/adv_r/adv_interface.h"
 #include "m4/adv_r/adv_hotspot.h"
 #include "m4/graphics/graphics.h"
 #include "m4/graphics/gr_buff.h"
-#include "m4/gui/gui_cheapo.h"
 
 namespace M4 {
 namespace Riddle {
@@ -45,6 +45,17 @@ private:
 	void handleState(ControlStatus status);
 
 public:
+	GUI::InterfaceBox *_interfaceBox = nullptr;
+	GUI::Inventory *_inventory = nullptr;
+	GUI::TextField *_textField = nullptr;
+	GUI::ButtonClass *_btnTake = nullptr;
+	GUI::ButtonClass *_btnManipulate = nullptr;
+	GUI::ButtonClass *_btnHandle = nullptr;
+	GUI::BackpackClass *_btnBackpack = nullptr;
+	GUI::ButtonClass *_btnBinky = nullptr;
+	GUI::ButtonClass *_btnScrollLeft = nullptr;
+	GUI::ButtonClass *_btnScrollRight = nullptr;
+
 	int _sprite = 22; // main_interface_sprite;
 	bool _shown = false;
 	const HotSpotRec *_hotspot = nullptr;
diff --git a/engines/m4/riddle/vars.cpp b/engines/m4/riddle/vars.cpp
index 350f5ced4bb..fa654336aeb 100644
--- a/engines/m4/riddle/vars.cpp
+++ b/engines/m4/riddle/vars.cpp
@@ -23,7 +23,9 @@
 #include "common/events.h"
 #include "m4/riddle/vars.h"
 #include "m4/riddle/inventory.h"
+#include "m4/gui/gui_sys.h"
 #include "m4/gui/gui_vmng.h"
+#include "m4/platform/keys.h"
 
 namespace M4 {
 namespace Riddle {
@@ -66,14 +68,12 @@ void Vars::main_cold_data_init() {
 }
 
 void Vars::global_menu_system_init() {
-/*
 	AddSystemHotkey(KEY_ESCAPE, escape_key_pressed);
 	AddSystemHotkey(KEY_F2, cb_F2);
 	AddSystemHotkey(KEY_F3, cb_F3);
 
 	if (_interface.init(0, 5, 6, 8, 9))
 		static_cast<Inventory *>(_inventory)->init();
-		*/
 }
 
 void Vars::initialize_game() {




More information about the Scummvm-git-logs mailing list