Relaxed requirement for Gtk-doc 1.11, as Debian stable only has 1.10.
[projects/chimara/chimara.git] / interpreters / git / memory.c
1 // $Id: memory.c,v 1.11 2004/01/25 21:04:19 iain Exp $
2
3 #include "git.h"
4 #include <stdlib.h>
5 #include <string.h>
6
7 const git_uint8 * gRom;
8 git_uint8 * gRam;
9
10 git_uint32 gRamStart;
11 git_uint32 gExtStart;
12 git_uint32 gEndMem;
13 git_uint32 gOriginalEndMem;
14
15 #define RAM_OVERLAP 8
16
17 void initMemory (const git_uint8 * gamefile, git_uint32 size)
18 {
19         // Make sure we have at least enough
20         // data for the standard glulx header.
21
22         if (size < 36)
23                 fatalError("This file is too small to be a valid glulx gamefile");
24         
25         // Set up a basic environment that will
26         // let us inspect the header.
27
28         gRom = gamefile;
29         gRamStart = 36;
30
31         // Check the magic number. From the spec:
32         //     * Magic number: 47 6C 75 6C, which is to say ASCII 'Glul'.
33
34         if (memRead32 (0) != 0x476c756c)
35                 fatalError("This is not a glulx game file");
36
37         // Load the correct values for ramstart, extstart and endmem.
38         // (Load ramstart last because it's required by memRead32 --
39         // if we get a wonky ramstart, the other reads could fail.)
40
41         gOriginalEndMem = gEndMem = memRead32 (16);
42         gExtStart = memRead32 (12);
43         gRamStart = memRead32 (8);
44
45         // Make sure the values are sane.
46
47     if (gRamStart < 36)
48             fatalError ("Bad header (RamStart is too low)");
49         
50     if (gRamStart > size)
51             fatalError ("Bad header (RamStart is bigger than the entire gamefile)");
52         
53     if (gExtStart > size)
54             fatalError ("Bad header (ExtStart is bigger than the entire gamefile)");
55         
56     if (gExtStart < gRamStart)
57             fatalError ("Bad header (ExtStart is lower than RamStart)");
58         
59     if (gEndMem < gExtStart)
60             fatalError ("Bad header (EndMem is lower than ExtStart)");
61         
62         if (gRamStart & 255)
63             fatalError ("Bad header (RamStart is not a multiple of 256)");
64
65         if (gExtStart & 255)
66             fatalError ("Bad header (ExtStart is not a multiple of 256)");
67
68         if (gEndMem & 255)
69             fatalError ("Bad header (EndMem is not a multiple of 256)");
70
71         // Allocate the RAM. We'll duplicate the last few bytes of ROM
72         // here so that reads which cross the ROM/RAM boundary don't fail.
73
74         gRamStart -= RAM_OVERLAP; // Adjust RAM boundary to include some ROM.
75
76         gRam = malloc (gEndMem - gRamStart);
77     if (gRam == NULL)
78         fatalError ("Failed to allocate game RAM");
79
80         gRam -= gRamStart;
81
82         // Copy the initial contents of RAM.
83         memcpy (gRam + gRamStart, gRom + gRamStart, gExtStart - gRamStart);
84
85         // Zero out the extended RAM.
86         memset (gRam + gExtStart, 0, gEndMem - gExtStart);
87
88         gRamStart += RAM_OVERLAP; // Restore boundary to its previous value.
89 }
90
91 int verifyMemory ()
92 {
93     git_uint32 checksum = 0;
94
95     git_uint32 n;
96     for (n = 0 ; n < gExtStart ; n += 4)
97         checksum += read32 (gRom + n);
98     
99     checksum -= read32 (gRom + 32);
100     return (checksum == read32 (gRom + 32)) ? 0 : 1;
101 }
102
103 int resizeMemory (git_uint32 newSize, int isInternal)
104 {
105     git_uint8* newRam;
106     
107     if (newSize == gEndMem)
108         return 0; // Size is not changed.
109     if (!isInternal && heap_is_active())
110         fatalError ("Cannot resize Glulx memory space while heap is active.");
111     if (newSize < gOriginalEndMem)
112         fatalError ("Cannot resize Glulx memory space smaller than it started.");
113     if (newSize & 0xFF)
114         fatalError ("Can only resize Glulx memory space to a 256-byte boundary.");
115     
116     gRamStart -= RAM_OVERLAP; // Adjust RAM boundary to include some ROM.
117     newRam = realloc(gRam + gRamStart, newSize - gRamStart);
118     if (!newRam)
119     {   
120         gRamStart += RAM_OVERLAP; // Restore boundary to its previous value.
121         return 1; // Failed to extend memory.
122     }
123     if (newSize > gEndMem)
124         memset (newRam + gEndMem - gRamStart, 0, newSize - gEndMem);
125
126     gRam = newRam - gRamStart;
127     gEndMem = newSize;
128     gRamStart += RAM_OVERLAP; // Restore boundary to its previous value.
129     return 0;
130 }
131
132 void resetMemory (git_uint32 protectPos, git_uint32 protectSize)
133 {
134     git_uint32 protectEnd = protectPos + protectSize;
135     git_uint32 i;
136
137     // Deactivate the heap (if it was active).
138     heap_clear();
139
140     gEndMem = gOriginalEndMem;
141       
142     // Copy the initial contents of RAM.
143     for (i = gRamStart; i < gExtStart; ++i)
144     {
145         if (i >= protectEnd || i < protectPos)
146             gRam [i] = gRom [i];
147     }
148
149     // Zero out the extended RAM.
150     for (i = gExtStart; i < gEndMem; ++i)
151     {
152         if (i >= protectEnd || i < protectPos)
153             gRam [i] = 0;
154     }
155 }
156
157 void shutdownMemory ()
158 {
159     // We didn't allocate the ROM, so we
160     // only need to dispose of the RAM.
161     
162     free (gRam + gRamStart - RAM_OVERLAP);
163     
164     // Zero out all our globals.
165     
166     gRamStart = gExtStart = gEndMem = gOriginalEndMem = 0;
167     gRom = gRam = NULL;
168 }
169
170 git_uint32 memReadError (git_uint32 address)
171 {
172     fatalError ("Out-of-bounds memory access");
173     return 0;
174 }
175
176 void memWriteError (git_uint32 address)
177 {
178     fatalError ("Out-of-bounds memory access");
179 }