mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-01-10 16:29:48 +00:00
now we can live replay
This commit is contained in:
parent
caf56e14e3
commit
a071cd80db
@ -51,10 +51,7 @@ TODO:
|
||||
- tools (memory, disasm) use debugging state
|
||||
- text log debugging script
|
||||
- NES crt should mark raster pos when debugging
|
||||
- make sure we don't store files in local storage unnecc.
|
||||
- state buffer/replay
|
||||
- intro/help text for each platform
|
||||
- make sure controls work with replay feature (we'll have to save control state every frame)
|
||||
- vscode/atom extension?
|
||||
- navigator.getGamepads
|
||||
|
||||
|
@ -24,7 +24,8 @@ export class StateRecorderImpl implements EmuRecorder {
|
||||
this.checkpoints = [];
|
||||
this.framerecs = [];
|
||||
this.frameCount = 0;
|
||||
this.lastSeekFrame = -1;
|
||||
this.lastSeekFrame = 0;
|
||||
if (this.callbackStateChanged) this.callbackStateChanged();
|
||||
}
|
||||
|
||||
frameRequested() : boolean {
|
||||
@ -32,32 +33,35 @@ export class StateRecorderImpl implements EmuRecorder {
|
||||
if (this.checkpoints.length >= this.maxCheckpoints) {
|
||||
return false;
|
||||
}
|
||||
// record the control state, if available
|
||||
if (this.platform.saveControlsState) {
|
||||
this.framerecs.push({
|
||||
controls:this.platform.saveControlsState(),
|
||||
seed:getNoiseSeed()
|
||||
});
|
||||
var controls = {
|
||||
controls:this.platform.saveControlsState(),
|
||||
seed:getNoiseSeed()
|
||||
};
|
||||
var requested = false;
|
||||
// are we replaying? then we don't need to save a frame, just replace controls
|
||||
if (this.lastSeekFrame < this.frameCount) {
|
||||
this.loadControls(this.lastSeekFrame);
|
||||
} else {
|
||||
// record the control state, if available
|
||||
if (this.platform.saveControlsState) {
|
||||
this.framerecs.push(controls);
|
||||
}
|
||||
// time to save next frame?
|
||||
requested = (this.frameCount++ % this.checkpointInterval) == 0;
|
||||
}
|
||||
// pick up where we left off, if we used the seek function
|
||||
if (this.lastSeekFrame >= 0) {
|
||||
this.frameCount = this.lastSeekFrame;
|
||||
this.lastSeekFrame = -1;
|
||||
// truncate buffers
|
||||
this.checkpoints = this.checkpoints.slice(0, Math.floor((this.frameCount + this.checkpointInterval - 1) / this.checkpointInterval));
|
||||
this.framerecs = this.framerecs.slice(0, this.frameCount);
|
||||
}
|
||||
// time to save next frame?
|
||||
if (this.callbackStateChanged) {
|
||||
this.callbackStateChanged();
|
||||
}
|
||||
return (this.frameCount++ % this.checkpointInterval) == 0;
|
||||
this.lastSeekFrame++;
|
||||
if (this.callbackStateChanged) this.callbackStateChanged();
|
||||
return requested;
|
||||
}
|
||||
|
||||
numFrames() : number {
|
||||
return this.frameCount;
|
||||
}
|
||||
|
||||
currentFrame() : number {
|
||||
return this.lastSeekFrame;
|
||||
}
|
||||
|
||||
recordFrame(state : EmuState) {
|
||||
this.checkpoints.push(state);
|
||||
}
|
||||
@ -79,8 +83,7 @@ export class StateRecorderImpl implements EmuRecorder {
|
||||
this.platform.loadState(state);
|
||||
while (frame < seekframe) {
|
||||
if (frame < this.framerecs.length) {
|
||||
this.platform.loadControlsState(this.framerecs[frame].controls);
|
||||
setNoiseSeed(this.framerecs[frame].seed);
|
||||
this.loadControls(frame);
|
||||
}
|
||||
frame++;
|
||||
this.platform.advance(frame < seekframe); // TODO: infinite loop?
|
||||
@ -91,4 +94,10 @@ export class StateRecorderImpl implements EmuRecorder {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
loadControls(frame : number) {
|
||||
if (this.platform.loadControlsState)
|
||||
this.platform.loadControlsState(this.framerecs[frame].controls);
|
||||
setNoiseSeed(this.framerecs[frame].seed);
|
||||
}
|
||||
}
|
||||
|
12
src/ui.ts
12
src/ui.ts
@ -406,6 +406,7 @@ function setCompileOutput(data: WorkerResult) {
|
||||
if (rom) { // TODO instanceof Uint8Array) {
|
||||
try {
|
||||
clearBreakpoint(); // so we can replace memory (TODO: change toolbar btn)
|
||||
_resetRecording();
|
||||
platform.loadROM(getCurrentPresetTitle(), rom);
|
||||
if (!userPaused) _resume();
|
||||
current_output = rom;
|
||||
@ -550,6 +551,7 @@ function clearBreakpoint() {
|
||||
}
|
||||
|
||||
function resetAndDebug() {
|
||||
_disableRecording();
|
||||
if (platform.setupDebug && platform.readAddress) { // TODO??
|
||||
clearBreakpoint();
|
||||
_resume();
|
||||
@ -693,6 +695,12 @@ function _disableRecording() {
|
||||
}
|
||||
}
|
||||
|
||||
function _resetRecording() {
|
||||
if (recorderActive) {
|
||||
stateRecorder.reset();
|
||||
}
|
||||
}
|
||||
|
||||
function _enableRecording() {
|
||||
stateRecorder.reset();
|
||||
platform.setRecorder(stateRecorder);
|
||||
@ -790,8 +798,8 @@ function setupReplaySlider() {
|
||||
stateRecorder.callbackStateChanged = () => {
|
||||
replayslider.attr('min', 1);
|
||||
replayslider.attr('max', stateRecorder.numFrames());
|
||||
replayslider.val(stateRecorder.numFrames());
|
||||
updateFrameNo(stateRecorder.numFrames());
|
||||
replayslider.val(stateRecorder.currentFrame());
|
||||
updateFrameNo(stateRecorder.currentFrame());
|
||||
};
|
||||
replayslider.on('input', sliderChanged);
|
||||
replayslider.on('change', sliderChanged);
|
||||
|
@ -24,15 +24,16 @@ global.Log = require('tss/js/Log.js').Log;
|
||||
includeInThisContext('tss/js/tss/PsgDeviceChannel.js');
|
||||
includeInThisContext('tss/js/tss/MasterChannel.js');
|
||||
includeInThisContext('tss/js/tss/AudioLooper.js');
|
||||
|
||||
var jsnes = require("jsnes/jsnes.min.js");
|
||||
includeInThisContext("jsnes/jsnes.min.js");
|
||||
|
||||
var emu = require('gen/emu.js');
|
||||
var Keys = emu.Keys;
|
||||
var audio = require('gen/audio.js');
|
||||
var recorder = require('gen/recorder.js');
|
||||
var _vicdual = require('gen/platform/vicdual.js');
|
||||
var _apple2 = require('gen/platform/apple2.js');
|
||||
var _vcs = require('gen/platform/vcs.js');
|
||||
var _nes = require('gen/platform/nes.js');
|
||||
|
||||
//
|
||||
|
||||
@ -108,5 +109,14 @@ describe('Platform Replay', () => {
|
||||
assert.equal(platform.saveState().p.SA, 0xff ^ 0x40);
|
||||
});
|
||||
|
||||
it('Should run nes', () => {
|
||||
var platform = testPlatform('nes', 'shoot2.c.rom', 70, (platform, frameno) => {
|
||||
if (frameno == 60) {
|
||||
keycallback(Keys.VK_Z.c, Keys.VK_Z.c, 1);
|
||||
}
|
||||
});
|
||||
assert.equal(65, platform.saveControlsState().c1[0]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
BIN
test/roms/nes/shoot2.c.rom
Normal file
BIN
test/roms/nes/shoot2.c.rom
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user