Example #1
0
static glui32 write_heapstate(dest_t *dest, int portable)
{
  glui32 res;
  glui32 sumlen;
  glui32 *sumarray;

  res = heap_get_summary(&sumlen, &sumarray);
  if (res)
    return res;

  if (!sumarray)
    return 0; /* no heap */

  res = write_heapstate_sub(sumlen, sumarray, dest, portable);

  glulx_free(sumarray);
  return res;
}
Example #2
0
git_sint32 saveToFile (git_sint32 * base, git_sint32 * sp, git_sint32 id)
{
    git_uint32 n, zeroCount;
    glui32 fileSize, fileSizePos;
    glui32 memSize, memSizePos;
    glui32 heapSize;
    glui32* heap;

    strid_t file, oldFile;

    // Find out what stream they want to use, and make sure it's valid.
    file = git_find_stream_by_id (id);
    if (file == 0)
        return 1;

    // Get the state of the heap.
    if (heap_get_summary (&heapSize, &heap))
        fatalError ("Couldn't get heap summary");

    // Make the given stream the default.
    oldFile = glk_stream_get_current ();
    glk_stream_set_current (file);

    // Write Quetzal header.
    glk_put_string ("FORM");

    fileSizePos = glk_stream_get_position (file);
    writeWord (0);

    glk_put_string ("IFZS");

    // Header chunk.
    glk_put_string ("IFhd");
    writeWord (128);
    glk_put_buffer ((char *) gRom, 128);

    // Stack chunk.
    glk_put_string ("Stks");
    writeWord ((sp - base) * 4);
    for (n = 0 ; n < (git_uint32) (sp - base) ; ++n)
        writeWord (base [n]);

    // Heap chunk.
    if (heap != 0)
    {
        glk_put_string ("MAll");
        writeWord (heapSize * 4);
        for (n = 0 ; n < heapSize ; ++n)
            writeWord (heap [n]);
        free(heap);
    }

    // Memory chunk.
    glk_put_string ("CMem");
    memSizePos = glk_stream_get_position (file);
    writeWord (0);

    writeWord (gEndMem);
    for (zeroCount = 0, n = gRamStart ; n < gEndMem ; ++n)
    {
        unsigned char romC = (n < gExtStart) ? gRom[n] : 0;
        unsigned char c = ((git_uint32) romC) ^ ((git_uint32) gRam[n]);
        if (c == 0)
            ++zeroCount;
        else
        {
            for ( ; zeroCount > 256 ; zeroCount -= 256)
            {
                glk_put_char (0);
                glk_put_char (0xff);
            }

            if (zeroCount > 0)
            {
                glk_put_char (0);
                glk_put_char ((char) (zeroCount - 1));
                zeroCount = 0;
            }

            glk_put_char (c);
        }
    }
    // Note: we don't bother writing out any remaining zeroes,
    // because the memory is padded out with zeroes on restore.

    memSize = glk_stream_get_position (file) - memSizePos - 4;
    if (memSize & 1)
       glk_put_char (0);

    // Back up and fill in the lengths.
    fileSize = glk_stream_get_position (file) - fileSizePos - 4;

    glk_stream_set_position (file, fileSizePos, seekmode_Start);
    writeWord (fileSize);

    glk_stream_set_position (file, memSizePos, seekmode_Start);
    writeWord (memSize);

    // Restore the previous default stream.
    glk_stream_set_current (oldFile);

    // And we're done.
    return 0;
}
Example #3
0
int saveUndo (git_sint32 * base, git_sint32 * sp)
{
    git_uint32 undoSize = sizeof(UndoRecord);
    git_uint32 mapSize = sizeof(MemoryPage*) * (gEndMem - gRamStart) / 256;
    git_uint32 stackSize = sizeof(git_sint32) * (sp - base);
    git_uint32 totalSize = undoSize + mapSize + stackSize;

    git_uint32 addr = gRamStart; // Address in glulx memory.
    git_uint32 slot = 0;         // Slot in our memory map.
    
    UndoRecord * undo = malloc (undoSize);
    if (undo == NULL)
        fatalError ("Couldn't allocate undo record");
        
    undo->endMem = gEndMem;
    undo->memoryMap = malloc (mapSize);
    undo->stackSize = stackSize;
    undo->stack = malloc (stackSize);
    undo->prev = NULL;
    undo->next = NULL;

    if (undo->memoryMap == NULL || undo->stack == NULL)
        fatalError ("Couldn't allocate memory for undo");

    // Save the stack.
    memcpy (undo->stack, base, undo->stackSize);

    // Are we diffing against the previous undo record,
    // or against the initial gamefile state?
    if (gUndo == NULL)
    {
        // We're diffing against the gamefile.        
        for ( ; addr < gExtStart ; addr += 256, ++slot)
        {
            if (memcmp (gInitMem + addr, gMem + addr, 256) != 0)
            {
                // We need to save this page.
                git_uint8 * page = malloc(256);
                if (page == NULL)
                    fatalError ("Couldn't allocate memory for undo");
                    
                memcpy (page, gMem + addr, 256);
                undo->memoryMap[slot] = page;
                totalSize += 256;
            }
            else
            {
                // We don't need to save this page.
                // Just make it point into ROM.
                undo->memoryMap[slot] = gInitMem + addr;
            }
        }

        // If the memory map has been extended, save the exended area
        for (addr = gExtStart ; addr < gEndMem ; addr += 256, ++slot)
        {
            git_uint8 * page = malloc(256);
            if (page == NULL)
                fatalError ("Couldn't allocate memory for undo");
                
            memcpy (page, gMem + addr, 256);
            undo->memoryMap[slot] = page;
            totalSize += 256;
        }
    }
    else
    {
        // We're diffing against the most recent undo record.
        git_uint32 endMem = (gUndo->endMem < gEndMem) ? gUndo->endMem : gEndMem;
        for ( ; addr < endMem ; addr += 256, ++slot)
        {
            if (memcmp (gUndo->memoryMap [slot], gMem + addr, 256) != 0)
            {
                // We need to save this page.
                git_uint8 * page = malloc(256);
                memcpy (page, gMem + addr, 256);
                undo->memoryMap[slot] = page;
                totalSize += 256;
            }
            else
            {
                // We don't need to save this page. Just copy
                // the pointer from the previous undo record.
                undo->memoryMap[slot] = gUndo->memoryMap[slot];
            }
        }

        // If the memory map has been extended, save the exended area
        for (addr = endMem ; addr < gEndMem ; addr += 256, ++slot)
        {
            git_uint8 * page = malloc(256);
            if (page == NULL)
                fatalError ("Couldn't allocate memory for undo");
                
            memcpy (page, gMem + addr, 256);
            undo->memoryMap[slot] = page;
            totalSize += 256;
        }
    }

    // Save the heap.
    if (heap_get_summary (&(undo->heapSize), &(undo->heap)))
        fatalError ("Couldn't get heap summary");
    totalSize += undo->heapSize * 4;

    // Link this record into the undo list.
    
    undo->prev = gUndo;
    if (gUndo)
        gUndo->next = undo;
    
    gUndo = undo;
    gUndoSize += totalSize;

    // Delete old records until we have enough free space.
    reserveSpace (0);

    // And we're done.
    return 0;
}