1 // $Id: memory.c,v 1.11 2004/01/25 21:04:19 iain Exp $
7 const git_uint8 * gRom;
13 git_uint32 gOriginalEndMem;
17 void initMemory (const git_uint8 * gamefile, git_uint32 size)
19 // Make sure we have at least enough
20 // data for the standard glulx header.
23 fatalError("This file is too small to be a valid glulx gamefile");
25 // Set up a basic environment that will
26 // let us inspect the header.
31 // Check the magic number. From the spec:
32 // * Magic number: 47 6C 75 6C, which is to say ASCII 'Glul'.
34 if (memRead32 (0) != 0x476c756c)
35 fatalError("This is not a glulx game file");
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.)
41 gOriginalEndMem = gEndMem = memRead32 (16);
42 gExtStart = memRead32 (12);
43 gRamStart = memRead32 (8);
45 // Make sure the values are sane.
48 fatalError ("Bad header (RamStart is too low)");
51 fatalError ("Bad header (RamStart is bigger than the entire gamefile)");
54 fatalError ("Bad header (ExtStart is bigger than the entire gamefile)");
56 if (gExtStart < gRamStart)
57 fatalError ("Bad header (ExtStart is lower than RamStart)");
59 if (gEndMem < gExtStart)
60 fatalError ("Bad header (EndMem is lower than ExtStart)");
63 fatalError ("Bad header (RamStart is not a multiple of 256)");
66 fatalError ("Bad header (ExtStart is not a multiple of 256)");
69 fatalError ("Bad header (EndMem is not a multiple of 256)");
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.
74 gRamStart -= RAM_OVERLAP; // Adjust RAM boundary to include some ROM.
76 gRam = malloc (gEndMem - gRamStart);
78 fatalError ("Failed to allocate game RAM");
82 // Copy the initial contents of RAM.
83 memcpy (gRam + gRamStart, gRom + gRamStart, gExtStart - gRamStart);
85 // Zero out the extended RAM.
86 memset (gRam + gExtStart, 0, gEndMem - gExtStart);
88 gRamStart += RAM_OVERLAP; // Restore boundary to its previous value.
93 git_uint32 checksum = 0;
96 for (n = 0 ; n < gExtStart ; n += 4)
97 checksum += read32 (gRom + n);
99 checksum -= read32 (gRom + 32);
100 return (checksum == read32 (gRom + 32)) ? 0 : 1;
103 int resizeMemory (git_uint32 newSize, int isInternal)
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.");
114 fatalError ("Can only resize Glulx memory space to a 256-byte boundary.");
116 gRamStart -= RAM_OVERLAP; // Adjust RAM boundary to include some ROM.
117 newRam = realloc(gRam + gRamStart, newSize - gRamStart);
120 gRamStart += RAM_OVERLAP; // Restore boundary to its previous value.
121 return 1; // Failed to extend memory.
123 if (newSize > gEndMem)
124 memset (newRam + gEndMem - gRamStart, 0, newSize - gEndMem);
126 gRam = newRam - gRamStart;
128 gRamStart += RAM_OVERLAP; // Restore boundary to its previous value.
132 void resetMemory (git_uint32 protectPos, git_uint32 protectSize)
134 git_uint32 protectEnd = protectPos + protectSize;
137 // Deactivate the heap (if it was active).
140 gEndMem = gOriginalEndMem;
142 // Copy the initial contents of RAM.
143 for (i = gRamStart; i < gExtStart; ++i)
145 if (i >= protectEnd || i < protectPos)
149 // Zero out the extended RAM.
150 for (i = gExtStart; i < gEndMem; ++i)
152 if (i >= protectEnd || i < protectPos)
157 void shutdownMemory ()
159 // We didn't allocate the ROM, so we
160 // only need to dispose of the RAM.
162 free (gRam + gRamStart - RAM_OVERLAP);
164 // Zero out all our globals.
166 gRamStart = gExtStart = gEndMem = gOriginalEndMem = 0;
170 git_uint32 memReadError (git_uint32 address)
172 fatalError ("Out-of-bounds memory access");
176 void memWriteError (git_uint32 address)
178 fatalError ("Out-of-bounds memory access");