void Glulxe::release_temp_c_array(char *arr, uint addr, uint len, int passout) { arrayref_t *arref = nullptr; arrayref_t **aptr; uint ix, val, addr2; if (arr) { for (aptr = (&arrays); (*aptr); aptr = (&((*aptr)->next))) { if ((*aptr)->array == arr) break; } arref = *aptr; if (!arref) error("Unable to re-find array argument in Glk call."); if (arref->addr != addr || arref->len != len) error("Mismatched array argument in Glk call."); if (arref->retained) { return; } *aptr = arref->next; arref->next = nullptr; if (passout) { for (ix = 0, addr2 = addr; ix < len; ix++, addr2 += 1) { val = arr[ix]; MemW1(addr2, val); } } glulx_free(arr); glulx_free(arref); } }
void Glulxe::glulxe_retained_unregister(void *array, uint len, const char *typecode, gidispatch_rock_t objrock) { arrayref_t *arref = nullptr; arrayref_t **aptr; uint ix, addr2, val; uint elemsize = 0; // TODO: See if original GLULXE has code I'm overlooking to cleanly close everything before freeing memmap if (!memmap) return; if (typecode[4] == 'C') elemsize = 1; else if (typecode[4] == 'I') elemsize = 4; if (!elemsize || array == nullptr) { return; } for (aptr = (&arrays); (*aptr); aptr = (&((*aptr)->next))) { if ((*aptr)->array == array) break; } arref = *aptr; if (!arref) error("Unable to re-find array argument in Glk call."); if (arref != objrock.ptr) error("Mismatched array reference in Glk call."); if (!arref->retained) error("Unretained array reference in Glk call."); if (arref->elemsize != elemsize || arref->len != len) error("Mismatched array argument in Glk call."); *aptr = arref->next; arref->next = nullptr; if (elemsize == 1) { for (ix = 0, addr2 = arref->addr; ix < arref->len; ix++, addr2 += 1) { val = ((char *)array)[ix]; MemW1(addr2, val); } } else if (elemsize == 4) { for (ix = 0, addr2 = arref->addr; ix < arref->len; ix++, addr2 += 4) { val = ((uint *)array)[ix]; MemW4(addr2, val); } } glulx_free(array); glulx_free(arref); }
static glui32 read_memstate(dest_t *dest, glui32 chunklen) { glui32 chunkend = dest->pos + chunklen; glui32 newlen; glui32 res, pos; int val; int runlen; unsigned char ch, ch2; #ifdef SERIALIZE_CACHE_RAM glui32 cachepos; #endif /* SERIALIZE_CACHE_RAM */ heap_clear(); res = read_long(dest, &newlen); if (res) return res; res = change_memsize(newlen, FALSE); if (res) return res; runlen = 0; #ifdef SERIALIZE_CACHE_RAM cachepos = 0; #else /* SERIALIZE_CACHE_RAM */ glk_stream_set_position(gamefile, gamefile_start+ramstart, seekmode_Start); #endif /* SERIALIZE_CACHE_RAM */ for (pos=ramstart; pos<endmem; pos++) { if (pos < endgamefile) { #ifdef SERIALIZE_CACHE_RAM val = ramcache[cachepos]; cachepos++; #else /* SERIALIZE_CACHE_RAM */ val = glk_get_char_stream(gamefile); if (val == -1) { fatal_error("The game file ended unexpectedly while restoring."); } #endif /* SERIALIZE_CACHE_RAM */ ch = (unsigned char)val; } else { ch = 0; } if (dest->pos >= chunkend) { /* we're into the final, unstored run. */ } else if (runlen) { runlen--; } else { res = read_byte(dest, &ch2); if (res) return res; if (ch2 == 0) { res = read_byte(dest, &ch2); if (res) return res; runlen = (glui32)ch2; } else { ch ^= ch2; } } if (pos >= protectstart && pos < protectend) continue; MemW1(pos, ch); } return 0; }