Add Glk unit test framework
[projects/chimara/chimara.git] / interpreters / git / memory.h
1 // $Id: memory.h,v 1.7 2004/01/25 21:04:19 iain Exp $
2 // Functions and macros for accessing game memory.
3
4 #ifndef GIT_MEMORY_H
5 #define GIT_MEMORY_H
6
7 #include "config.h"
8
9 // --------------------------------------------------------------
10 // Macros for reading and writing big-endian data.
11
12 #ifdef USE_BIG_ENDIAN_UNALIGNED
13 // We're on a big-endian platform which can handle unaligned
14 // accesses, such as the PowerPC. This means we can read and
15 // write multi-byte values in glulx memory directly, without
16 // having to pack and unpack each byte.
17
18 #define read32(ptr)    (*((git_uint32*)(ptr)))
19 #define read16(ptr)    (*((git_uint16*)(ptr)))
20 #define write32(ptr,v) (read32(ptr)=(git_uint32)(v))
21 #define write16(ptr,v) (read16(ptr)=(git_uint16)(v))
22
23 #else
24 // We're on a little-endian platform, such as the x86, or a
25 // big-endian platform that doesn't like unaligned accesses,
26 // such as the 68K. This means we have to read and write the
27 // slow and tedious way.
28
29 #define read32(ptr)    \
30   ( (git_uint32)(((git_uint8 *)(ptr))[0] << 24) \
31   | (git_uint32)(((git_uint8 *)(ptr))[1] << 16) \
32   | (git_uint32)(((git_uint8 *)(ptr))[2] << 8)  \
33   | (git_uint32)(((git_uint8 *)(ptr))[3]))
34 #define read16(ptr)    \
35   ( (git_uint16)(((git_uint8 *)(ptr))[0] << 8)  \
36   | (git_uint16)(((git_uint8 *)(ptr))[1]))
37
38 #define write32(ptr, v)   \
39   (((ptr)[0] = (git_uint8)(((git_uint32)(v)) >> 24)), \
40    ((ptr)[1] = (git_uint8)(((git_uint32)(v)) >> 16)), \
41    ((ptr)[2] = (git_uint8)(((git_uint32)(v)) >> 8)),  \
42    ((ptr)[3] = (git_uint8)(((git_uint32)(v)))))
43 #define write16(ptr, v)   \
44   (((ptr)[0] = (git_uint8)(((git_uint32)(v)) >> 8)),  \
45    ((ptr)[1] = (git_uint8)(((git_uint32)(v)))))
46
47 #endif // USE_BIG_ENDIAN_UNALIGNED
48
49 // Accessing single bytes is easy on any platform.
50
51 #define read8(ptr)     (*((git_uint8*)(ptr)))
52 #define write8(ptr, v) (read8(ptr)=(git_uint8)(v))
53
54 // --------------------------------------------------------------
55 // Globals
56
57 extern git_uint32 gRamStart; // The start of RAM.
58 extern git_uint32 gExtStart; // The start of extended memory (initialised to zero).
59 extern git_uint32 gEndMem;   // The current end of memory.
60 extern git_uint32 gOriginalEndMem; // The value of EndMem when the game was first loaded.
61
62 // This is the entire gamefile, as read-only memory. It contains
63 // both the ROM, which is constant for the entire run of the program,
64 // and the original RAM, which is useful for checking what's changed
65 // when saving to disk or remembering a position for UNDO.
66 extern const git_uint8 * gRom;
67
68 // This is the current contents of RAM. This pointer actually points
69 // to the start of ROM, so that you don't have to keep adding and
70 // subtracting gRamStart, but don't try to access ROM via this pointer.
71 extern git_uint8 * gRam;
72
73 // --------------------------------------------------------------
74 // Functions
75
76 // Initialise game memory. This sets up all the global variables
77 // declared above. Note that it does *not* copy the given memory
78 // image: it must be valid for the lifetime of the program.
79
80 extern void initMemory (const git_uint8 * game, git_uint32 gameSize);
81
82 // Verifies the gamefile based on its checksum. 0 on success, 1 on failure.
83
84 extern int verifyMemory ();
85
86 // Resizes the game's memory. Returns 0 on success, 1 on failure.
87
88 extern int resizeMemory (git_uint32 newSize, int isInternal);
89
90 // Resets memory to its initial state. Call this when the game restarts.
91
92 extern void resetMemory (git_uint32 protectPos, git_uint32 protectSize);
93
94 // Disposes of all the data structures allocated in initMemory().
95
96 extern void shutdownMemory ();
97
98 // Utility functions -- these just pass an appropriate
99 // string to fatalError().
100
101 extern git_uint32 memReadError (git_uint32 address);
102 extern void memWriteError (git_uint32 address);
103
104 // Functions for reading and writing game memory.
105
106 GIT_INLINE git_uint32 memRead32 (git_uint32 address)
107 {
108         if (address <= gRamStart - 4)
109                 return read32 (gRom + address);
110         else if (address <= gEndMem - 4)
111                 return read32 (gRam + address);
112     else
113         return memReadError (address);
114 }
115
116 GIT_INLINE git_uint32 memRead16 (git_uint32 address)
117 {
118         if (address <= gRamStart - 4)
119                 return read16 (gRom + address);
120         else if (address <= gEndMem - 2)
121                 return read16 (gRam + address);
122     else
123         return memReadError (address);
124 }
125
126 GIT_INLINE git_uint32 memRead8 (git_uint32 address)
127 {
128     if (address <= gRamStart - 4)
129         return read8 (gRom + address);
130     else if (address < gEndMem)
131         return read8 (gRam + address);
132     else
133         return memReadError (address);
134 }
135
136 GIT_INLINE void memWrite32 (git_uint32 address, git_uint32 val)
137 {
138         if (address >= gRamStart && address <= (gEndMem - 4))
139                 write32 (gRam + address, val);
140         else
141         memWriteError (address);
142 }
143
144 GIT_INLINE void memWrite16 (git_uint32 address, git_uint32 val)
145 {
146         if (address >= gRamStart && address <= (gEndMem - 2))
147                 write16 (gRam + address, val);
148         else
149         memWriteError (address);
150 }
151
152 GIT_INLINE void memWrite8 (git_uint32 address, git_uint32 val)
153 {
154         if (address >= gRamStart && address < gEndMem)
155                 write8 (gRam + address, val);
156         else
157         memWriteError (address);
158 }
159
160 #endif // GIT_MEMORY_H