mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-10 03:40:25 +00:00
GLK: FROTZ: Added remaining memory methods
This commit is contained in:
parent
5507242395
commit
e1de76b491
@ -320,6 +320,103 @@ void Mem::storew(zword addr, zword value) {
|
||||
storeb((zword)(addr + 1), lo(value));
|
||||
}
|
||||
|
||||
void Mem::free_undo(int count) {
|
||||
undo_t *p;
|
||||
|
||||
if (count > undo_count)
|
||||
count = undo_count;
|
||||
while (count--) {
|
||||
p = first_undo;
|
||||
if (curr_undo == first_undo)
|
||||
curr_undo = curr_undo->next;
|
||||
first_undo = first_undo->next;
|
||||
free(p);
|
||||
undo_count--;
|
||||
}
|
||||
if (first_undo)
|
||||
first_undo->prev = NULL;
|
||||
else
|
||||
last_undo = NULL;
|
||||
}
|
||||
|
||||
void Mem::reset_memory() {
|
||||
story_fp = nullptr;
|
||||
blorb_ofs = 0;
|
||||
blorb_len = 0;
|
||||
|
||||
if (undo_mem) {
|
||||
free_undo(undo_count);
|
||||
delete undo_mem;
|
||||
}
|
||||
|
||||
undo_mem = nullptr;
|
||||
undo_count = 0;
|
||||
delete[] zmp;
|
||||
zmp = nullptr;
|
||||
}
|
||||
|
||||
long Mem::mem_diff(zbyte *a, zbyte *b, zword mem_size, zbyte *diff) {
|
||||
unsigned size = mem_size;
|
||||
zbyte *p = diff;
|
||||
unsigned j;
|
||||
zbyte c = 0;
|
||||
|
||||
for (;;) {
|
||||
for (j = 0; size > 0 && (c = *a++ ^ *b++) == 0; j++)
|
||||
size--;
|
||||
if (size == 0) break;
|
||||
size--;
|
||||
if (j > 0x8000) {
|
||||
*p++ = 0;
|
||||
*p++ = 0xff;
|
||||
*p++ = 0xff;
|
||||
j -= 0x8000;
|
||||
}
|
||||
if (j > 0) {
|
||||
*p++ = 0;
|
||||
j--;
|
||||
if (j <= 0x7f) {
|
||||
*p++ = j;
|
||||
} else {
|
||||
*p++ = (j & 0x7f) | 0x80;
|
||||
*p++ = (j & 0x7f80) >> 7;
|
||||
}
|
||||
}
|
||||
|
||||
*p++ = c;
|
||||
*(b - 1) ^= c;
|
||||
}
|
||||
|
||||
return p - diff;
|
||||
}
|
||||
|
||||
void Mem::mem_undiff(zbyte *diff, long diff_length, zbyte *dest) {
|
||||
zbyte c;
|
||||
|
||||
while (diff_length) {
|
||||
c = *diff++;
|
||||
diff_length--;
|
||||
if (c == 0) {
|
||||
unsigned runlen;
|
||||
|
||||
if (!diff_length)
|
||||
return; // Incomplete run
|
||||
runlen = *diff++;
|
||||
diff_length--;
|
||||
if (runlen & 0x80) {
|
||||
if (!diff_length)
|
||||
return; // Incomplete extended run
|
||||
c = *diff++;
|
||||
diff_length--;
|
||||
runlen = (runlen & 0x7f) | (((unsigned)c) << 7);
|
||||
}
|
||||
|
||||
dest += runlen + 1;
|
||||
} else {
|
||||
*dest++ ^= c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Scott
|
||||
} // End of namespace Gargoyle
|
||||
|
@ -229,6 +229,11 @@ protected:
|
||||
*/
|
||||
void storew(zword addr, zword value);
|
||||
|
||||
/**
|
||||
* Free count undo blocks from the beginning of the undo list
|
||||
*/
|
||||
void free_undo(int count);
|
||||
|
||||
/**
|
||||
* Generates a runtime error
|
||||
*/
|
||||
@ -238,6 +243,26 @@ protected:
|
||||
* Called when the flags are changed
|
||||
*/
|
||||
virtual void flagsChanged(zbyte value) = 0;
|
||||
|
||||
/**
|
||||
* Close the story file and deallocate memory.
|
||||
*/
|
||||
void reset_memory();
|
||||
|
||||
/**
|
||||
* Set diff to a Quetzal-like difference between a and b,
|
||||
* copying a to b as we go. It is assumed that diff points to a
|
||||
* buffer which is large enough to hold the diff.
|
||||
* mem_size is the number of bytes to compare.
|
||||
* Returns the number of bytes copied to diff.
|
||||
*
|
||||
*/
|
||||
long mem_diff(zbyte *a, zbyte *b, zword mem_size, zbyte *diff);
|
||||
|
||||
/**
|
||||
* Applies a quetzal-like diff to dest
|
||||
*/
|
||||
void mem_undiff(zbyte *diff, long diff_length, zbyte *dest);
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -219,6 +219,18 @@ private:
|
||||
*/
|
||||
virtual void flagsChanged(zbyte value) override;
|
||||
|
||||
/**
|
||||
* This function does the dirty work for z_save_undo.
|
||||
*/
|
||||
int save_undo();
|
||||
|
||||
/**
|
||||
* This function does the dirty work for z_restore_undo.
|
||||
*/
|
||||
int restore_undo();
|
||||
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* \defgroup Object support methods
|
||||
* @{
|
||||
|
@ -26,7 +26,6 @@ namespace Gargoyle {
|
||||
namespace Frotz {
|
||||
|
||||
// TODO: Implement method stubs
|
||||
static void save_undo() {}
|
||||
static zword os_read_mouse() { return 0; }
|
||||
|
||||
|
||||
|
@ -35,5 +35,88 @@ void Processor::flagsChanged(zbyte value) {
|
||||
}
|
||||
}
|
||||
|
||||
int Processor::save_undo() {
|
||||
long diff_size;
|
||||
zword stack_size;
|
||||
undo_t *p;
|
||||
|
||||
if (_undo_slots == 0)
|
||||
// undo feature unavailable
|
||||
return -1;
|
||||
|
||||
// save undo possible
|
||||
while (last_undo != curr_undo) {
|
||||
p = last_undo;
|
||||
last_undo = last_undo->prev;
|
||||
delete p;
|
||||
undo_count--;
|
||||
}
|
||||
if (last_undo)
|
||||
last_undo->next = nullptr;
|
||||
else
|
||||
first_undo = nullptr;
|
||||
|
||||
if (undo_count == _undo_slots)
|
||||
free_undo(1);
|
||||
|
||||
diff_size = mem_diff(zmp, prev_zmp, h_dynamic_size, undo_diff);
|
||||
stack_size = _stack + STACK_SIZE - _sp;
|
||||
do {
|
||||
p = (undo_t *) malloc(sizeof(undo_t) + diff_size + stack_size * sizeof(*_sp));
|
||||
if (p == nullptr)
|
||||
free_undo(1);
|
||||
} while (!p && undo_count);
|
||||
if (p == nullptr)
|
||||
return -1;
|
||||
|
||||
GET_PC(p->pc);
|
||||
p->frame_count = _frameCount;
|
||||
p->diff_size = diff_size;
|
||||
p->stack_size = stack_size;
|
||||
p->frame_offset = _fp - _stack;
|
||||
memcpy(p + 1, undo_diff, diff_size);
|
||||
memcpy((zbyte *)(p + 1) + diff_size, _sp, stack_size * sizeof(*_sp));
|
||||
|
||||
if (!first_undo) {
|
||||
p->prev = nullptr;
|
||||
first_undo = p;
|
||||
} else {
|
||||
last_undo->next = p;
|
||||
p->prev = last_undo;
|
||||
}
|
||||
|
||||
p->next = nullptr;
|
||||
curr_undo = last_undo = p;
|
||||
undo_count++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Processor::restore_undo(void) {
|
||||
if (_undo_slots == 0)
|
||||
// undo feature unavailable
|
||||
return -1;
|
||||
|
||||
if (curr_undo == nullptr)
|
||||
// no saved game state
|
||||
return 0;
|
||||
|
||||
// undo possible
|
||||
memcpy(zmp, prev_zmp, h_dynamic_size);
|
||||
SET_PC(curr_undo->pc);
|
||||
_sp = _stack + STACK_SIZE - curr_undo->stack_size;
|
||||
_fp = _stack + curr_undo->frame_offset;
|
||||
_frameCount = curr_undo->frame_count;
|
||||
mem_undiff((zbyte *)(curr_undo + 1), curr_undo->diff_size, prev_zmp);
|
||||
memcpy(_sp, (zbyte *)(curr_undo + 1) + curr_undo->diff_size,
|
||||
curr_undo->stack_size * sizeof(*_sp));
|
||||
|
||||
curr_undo = curr_undo->prev;
|
||||
|
||||
restart_header();
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
} // End of namespace Scott
|
||||
} // End of namespace Gargoyle
|
||||
|
Loading…
Reference in New Issue
Block a user