restore static method
bool
restore(
- dynamic rawBytes
)
Implementation
static bool restore(rawBytes){
var fileBytes = List.from(rawBytes);
//List<int> restoreData = List<int>();
Chunk? nextChunk = IFF.readChunk(fileBytes);
if (!assertChunk(Chunk.form, nextChunk)) return false;
nextChunk = IFF.readChunk(fileBytes);
if (!assertChunk(Chunk.ifzs, nextChunk)) return false;
var gotStacks = false;
var gotMem = false;
var gotHeader = false;
late int pc;
var memBytes = [];
final stackList = <StackFrame>[];
nextChunk = IFF.readChunk(fileBytes);
if (nextChunk == null) return false;
while(nextChunk != null){
switch(nextChunk){
case Chunk.ifhd:
// here we are validating that this file is compatible
// with the game currently loaded into the machine.
IFF.read4Byte(fileBytes); //size (always 13)
if (Z.engine.mem.loadw(Header.release) != IFF.read2Byte(fileBytes)){
return false;
}
if (Z.engine.mem.loadw(Header.serialNumber) != IFF.read2Byte(fileBytes)){
return false;
}
if (Z.engine.mem.loadw(Header.serialNumber + 2) != IFF.read2Byte(fileBytes)){
return false;
}
if (Z.engine.mem.loadw(Header.serialNumber + 4) != IFF.read2Byte(fileBytes)){
return false;
}
if (Z.engine.mem.loadw(Header.checkSumOfFile) != IFF.read2Byte(fileBytes)){
return false;
}
pc = IFF.read3Byte(fileBytes); //PC
IFF.nextByte(fileBytes); //pad
gotHeader = true;
break;
case Chunk.stks:
var stacksLen = IFF.read4Byte(fileBytes);
StackFrame getNextStackFrame(){
var sf = StackFrame.empty();
sf.returnAddr = IFF.read3Byte(fileBytes);
var flagByte = IFF.nextByte(fileBytes)!;
var returnVar = IFF.nextByte(fileBytes);
sf.returnVar = BinaryHelper.isSet(flagByte, 4)
? Engine.stackMarker
: returnVar!;
var numLocals = BinaryHelper.bottomBits(flagByte, 4);
var argsPassed = IFF.nextByte(fileBytes)!;
var args = 0;
while(BinaryHelper.isSet(argsPassed, 0)){
args++;
argsPassed = argsPassed >> 1;
}
sf.totalArgsPassed = args;
var numEvals = IFF.read2Byte(fileBytes);
for(int i = 0; i < numLocals; i++){
sf.locals.add(IFF.read2Byte(fileBytes));
}
for(int i = 0; i < numEvals; i++){
sf.evals.add(IFF.read2Byte(fileBytes));
}
return sf;
}
while(stacksLen > 0){
if (stacksLen == 1){
//pad byte
IFF.nextByte(fileBytes);
continue;
}
stackList.add(getNextStackFrame());
stacksLen -= stackList.last.computedByteSize;
}
gotStacks = true;
break;
case Chunk.umem:
var numBytes = IFF.read4Byte(fileBytes);
//memory length mismatch
if (numBytes != Z.engine.mem.memList.length) {
return false;
}
memBytes = fileBytes.getRange(0, numBytes) as List<dynamic>;
fileBytes.removeRange(0, numBytes);
//IFF.read pad byte if present
if (numBytes % 2 != 0) {
IFF.nextByte(fileBytes);
}
gotMem = true;
break;
default:
if (!gotStacks || !gotMem || !gotHeader){
if (nextChunk == Chunk.form || nextChunk == Chunk.ifzs){
return false; //something went horribly wrong in the file format
}
//attempt to skip the chunk
var sizeOfChunk = IFF.read4Byte(fileBytes);
fileBytes.removeRange(0, sizeOfChunk);
}
}
if(gotStacks && gotMem && gotHeader) break;
nextChunk = IFF.readChunk(fileBytes);
}
if (!gotStacks || !gotMem || !gotHeader) return false;
//now that we have all the data structures, do the restore...
//memory
Z.engine.mem = MemoryMap(memBytes as List<int>);
Z.engine.visitHeader();
Z.engine.callStack.clear();
Z.engine.stack.clear();
//stacks
for(StackFrame sf in stackList){
//callstack first
stdout.writeln(sf);
//locals
Z.engine.callStack.push(sf.locals.length);
for(final local in sf.locals){
Z.engine.callStack.push(local!);
}
//total locals
Z.engine.callStack.push(sf.locals.length);
//returnTo variable
Z.engine.callStack.push(sf.returnVar);
//return addr
Z.engine.callStack.push(sf.returnAddr);
//eval stack
Z.engine.stack.push(Engine.stackMarker);
for(final eval in sf.evals){
Z.engine.stack.push(eval!);
}
}
Z.engine.programCounter = pc;
return true;
}