Пример #1
0
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);
	}
}
Пример #2
0
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);
}
Пример #3
0
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;
}