aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/frotz/mem.h
blob: a632bc6e63885139e9b34a1fed0cb85d4661456b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#ifndef GLK_FROTZ_MEM
#define GLK_FROTZ_MEM

#include "glk/frotz/frotz_types.h"
#include "glk/frotz/config.h"

namespace Glk {
namespace Frotz {

#define SET_WORD(addr,v)  zmp[addr] = hi(v); zmp[addr+1] = lo(v)
#define LOW_WORD(addr,v)  v = READ_BE_UINT16(&zmp[addr])
#define HIGH_WORD(addr,v) v = READ_BE_UINT16(&zmp[addr])
#define HIGH_LONG(addr,v) v = READ_BE_UINT32(&zmp[addr])
#define SET_BYTE(addr,v)   zmp[addr] = v
#define LOW_BYTE(addr,v)   v = zmp[addr]

/**
 * Stores undo information
 */
struct undo_struct {
	undo_struct *next;
	undo_struct *prev;
	long pc;
	long diff_size;
	zword frame_count;
	zword stack_size;
	zword frame_offset;
	// undo diff and stack data follow
};
typedef undo_struct undo_t;

/**
 * Handles the memory, header, and user options
 */
class Mem : public Header, public virtual UserOptions {
protected:
	Common::SeekableReadStream *story_fp;
	uint story_size;
	byte *pcp;
	byte *zmp;

	undo_t *first_undo, *last_undo, *curr_undo;
	zbyte *undo_mem, *prev_zmp, *undo_diff;
	int undo_count;
	int reserve_mem;
private:
	/**
	 * Handles setting the story file, parsing it if it's a Blorb file
	 */
	void initializeStoryFile();

	/**
	 * Setup undo data
	 */
	void initializeUndo();

	/**
	 * Handles loading the game header
	 */
	void loadGameHeader();
protected:
	/**
	 * Read a value from the header extension (former mouse table).
	 */
	zword get_header_extension(int entry);

	/**
	 * Set an entry in the header extension (former mouse table).
	 */
	void set_header_extension(int entry, zword val);

	/**
	 * Set all header fields which hold information about the interpreter.
	 */
	void restart_header();

	/**
	 * Write a byte value to the dynamic Z-machine memory.
	 */
	void storeb(zword addr, zbyte value);

	/**
	 * Write a word value to the dynamic Z-machine memory.
	 */
	void storew(zword addr, zword value);

	/**
	 * Free count undo blocks from the beginning of the undo list
	 */
	void free_undo(int count);

	/**
	 * Generates a runtime error
	 */
	virtual void runtimeError(ErrorCode errNum) = 0;

	/**
	 * Called when the flags are changed
	 */
	virtual void flagsChanged(zbyte value) = 0;

	/**
	 * Close the story file and deallocate memory.
	 */
	void reset_memory();

	/**
	 * Set diff to a Quetzal-like difference between a and b,
	 * copying a to b as we go.  It is assumed that diff points to a
	 * buffer which is large enough to hold the diff.
	 * mem_size is the number of bytes to compare.
	 * Returns the number of bytes copied to diff.
	 *
	 */
	long mem_diff(zbyte *a, zbyte *b, zword mem_size, zbyte *diff);

	/**
	 * Applies a quetzal-like diff to dest
	 */
	void mem_undiff(zbyte *diff, long diff_length, zbyte *dest);
public:
	/**
	 * Constructor
	 */
	Mem();
	virtual ~Mem() {}

	/**
	 * Initialize
	 */
	void initialize();
};

} // End of namespace Frotz
} // End of namespace Glk

#endif