Add Glulxe and Git. They compile but don't work yet.
[rodin/chimara.git] / interpreters / git / memory.c
diff --git a/interpreters/git/memory.c b/interpreters/git/memory.c
new file mode 100644 (file)
index 0000000..b5f0729
--- /dev/null
@@ -0,0 +1,179 @@
+// $Id: memory.c,v 1.11 2004/01/25 21:04:19 iain Exp $
+
+#include "git.h"
+#include <stdlib.h>
+#include <string.h>
+
+const git_uint8 * gRom;
+git_uint8 * gRam;
+
+git_uint32 gRamStart;
+git_uint32 gExtStart;
+git_uint32 gEndMem;
+git_uint32 gOriginalEndMem;
+
+#define RAM_OVERLAP 8
+
+void initMemory (const git_uint8 * gamefile, git_uint32 size)
+{
+       // Make sure we have at least enough
+       // data for the standard glulx header.
+
+       if (size < 36)
+               fatalError("This file is too small to be a valid glulx gamefile");
+       
+       // Set up a basic environment that will
+       // let us inspect the header.
+
+       gRom = gamefile;
+       gRamStart = 36;
+
+       // Check the magic number. From the spec:
+       //     * Magic number: 47 6C 75 6C, which is to say ASCII 'Glul'.
+
+       if (memRead32 (0) != 0x476c756c)
+               fatalError("This is not a glulx game file");
+
+       // Load the correct values for ramstart, extstart and endmem.
+       // (Load ramstart last because it's required by memRead32 --
+       // if we get a wonky ramstart, the other reads could fail.)
+
+       gOriginalEndMem = gEndMem = memRead32 (16);
+       gExtStart = memRead32 (12);
+       gRamStart = memRead32 (8);
+
+       // Make sure the values are sane.
+
+    if (gRamStart < 36)
+           fatalError ("Bad header (RamStart is too low)");
+        
+    if (gRamStart > size)
+           fatalError ("Bad header (RamStart is bigger than the entire gamefile)");
+        
+    if (gExtStart > size)
+           fatalError ("Bad header (ExtStart is bigger than the entire gamefile)");
+        
+    if (gExtStart < gRamStart)
+           fatalError ("Bad header (ExtStart is lower than RamStart)");
+        
+    if (gEndMem < gExtStart)
+           fatalError ("Bad header (EndMem is lower than ExtStart)");
+        
+       if (gRamStart & 255)
+           fatalError ("Bad header (RamStart is not a multiple of 256)");
+
+       if (gExtStart & 255)
+           fatalError ("Bad header (ExtStart is not a multiple of 256)");
+
+       if (gEndMem & 255)
+           fatalError ("Bad header (EndMem is not a multiple of 256)");
+
+       // Allocate the RAM. We'll duplicate the last few bytes of ROM
+       // here so that reads which cross the ROM/RAM boundary don't fail.
+
+       gRamStart -= RAM_OVERLAP; // Adjust RAM boundary to include some ROM.
+
+       gRam = malloc (gEndMem - gRamStart);
+    if (gRam == NULL)
+        fatalError ("Failed to allocate game RAM");
+
+       gRam -= gRamStart;
+
+       // Copy the initial contents of RAM.
+       memcpy (gRam + gRamStart, gRom + gRamStart, gExtStart - gRamStart);
+
+       // Zero out the extended RAM.
+       memset (gRam + gExtStart, 0, gEndMem - gExtStart);
+
+       gRamStart += RAM_OVERLAP; // Restore boundary to its previous value.
+}
+
+int verifyMemory ()
+{
+    git_uint32 checksum = 0;
+
+    git_uint32 n;
+    for (n = 0 ; n < gExtStart ; n += 4)
+        checksum += read32 (gRom + n);
+    
+    checksum -= read32 (gRom + 32);
+    return (checksum == read32 (gRom + 32)) ? 0 : 1;
+}
+
+int resizeMemory (git_uint32 newSize, int isInternal)
+{
+    git_uint8* newRam;
+    
+    if (newSize == gEndMem)
+        return 0; // Size is not changed.
+    if (!isInternal && heap_is_active())
+        fatalError ("Cannot resize Glulx memory space while heap is active.");
+    if (newSize < gOriginalEndMem)
+        fatalError ("Cannot resize Glulx memory space smaller than it started.");
+    if (newSize & 0xFF)
+        fatalError ("Can only resize Glulx memory space to a 256-byte boundary.");
+    
+    gRamStart -= RAM_OVERLAP; // Adjust RAM boundary to include some ROM.
+    newRam = realloc(gRam + gRamStart, newSize - gRamStart);
+    if (!newRam)
+    {  
+        gRamStart += RAM_OVERLAP; // Restore boundary to its previous value.
+        return 1; // Failed to extend memory.
+    }
+    if (newSize > gEndMem)
+        memset (newRam + gEndMem - gRamStart, 0, newSize - gEndMem);
+
+    gRam = newRam - gRamStart;
+    gEndMem = newSize;
+    gRamStart += RAM_OVERLAP; // Restore boundary to its previous value.
+    return 0;
+}
+
+void resetMemory (git_uint32 protectPos, git_uint32 protectSize)
+{
+    git_uint32 protectEnd = protectPos + protectSize;
+    git_uint32 i;
+
+    // Deactivate the heap (if it was active).
+    heap_clear();
+
+    gEndMem = gOriginalEndMem;
+      
+    // Copy the initial contents of RAM.
+    for (i = gRamStart; i < gExtStart; ++i)
+    {
+        if (i >= protectEnd || i < protectPos)
+            gRam [i] = gRom [i];
+    }
+
+    // Zero out the extended RAM.
+    for (i = gExtStart; i < gEndMem; ++i)
+    {
+        if (i >= protectEnd || i < protectPos)
+            gRam [i] = 0;
+    }
+}
+
+void shutdownMemory ()
+{
+    // We didn't allocate the ROM, so we
+    // only need to dispose of the RAM.
+    
+    free (gRam + gRamStart - RAM_OVERLAP);
+    
+    // Zero out all our globals.
+    
+    gRamStart = gExtStart = gEndMem = gOriginalEndMem = 0;
+    gRom = gRam = NULL;
+}
+
+git_uint32 memReadError (git_uint32 address)
+{
+    fatalError ("Out-of-bounds memory access");
+    return 0;
+}
+
+void memWriteError (git_uint32 address)
+{
+    fatalError ("Out-of-bounds memory access");
+}