Skip to content

Commit 10e43e9

Browse files
committed
Implemented the ability to reset the persisted disk image back to the original state via a keyboard shortcut.
1 parent d33840d commit 10e43e9

15 files changed

Lines changed: 494 additions & 32 deletions

core/src/main/java/emu/jvic/JVicRunner.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@
4444
*/
4545
public abstract class JVicRunner {
4646

47+
public interface ResetDiskHandler {
48+
49+
void onResetComplete();
50+
51+
void onResetFailed();
52+
}
53+
4754
protected MachineScreen machineScreen;
4855

4956
protected KeyboardMatrix keyboardMatrix;
@@ -257,6 +264,14 @@ public byte[] loadBlankDiskImage() {
257264
public abstract void cancelImport();
258265

259266
public abstract boolean isRunning();
267+
268+
public boolean canResetMountedDisk() {
269+
return false;
270+
}
271+
272+
public void requestMountedDiskReset(ResetDiskHandler resetDiskHandler) {
273+
resetDiskHandler.onResetFailed();
274+
}
260275

261276
public abstract void sendNmi();
262277

core/src/main/java/emu/jvic/Machine.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@
3636
*/
3737
public class Machine {
3838

39+
public interface ResetDiskHandler {
40+
41+
void onResetComplete();
42+
43+
void onResetFailed();
44+
}
45+
3946
// Machine components.
4047
private Vic20Memory memory;
4148
private Vic vic;
@@ -57,6 +64,10 @@ public class Machine {
5764

5865
private boolean paused = true;
5966

67+
private DiskImagePersistenceSession activeDiskPersistenceSession;
68+
private boolean activeDiskWriteProtected;
69+
private boolean hasMountedDisk;
70+
6071
private MachineType machineType;
6172

6273
/**
@@ -194,6 +205,10 @@ public Callable<Queue<char[]>> init(
194205
// Initialise the sound generator.
195206
soundGenerator.init(memory.getMemoryArray(), machineType);
196207

208+
activeDiskPersistenceSession = null;
209+
activeDiskWriteProtected = false;
210+
hasMountedDisk = false;
211+
197212
if (shouldMountDisk(programType, appConfigItem, mountedDiskImageData)) {
198213
AppConfigItem.DiskWriteMode diskWriteMode = (appConfigItem != null)
199214
? appConfigItem.getDiskWriteMode()
@@ -205,6 +220,9 @@ public Callable<Queue<char[]>> init(
205220
}
206221
byte[] startupDiskImage = persistenceSession.getStartupDiskImage();
207222
c1541Drive.insertDisk(startupDiskImage, true, persistenceSession, writeProtected);
223+
activeDiskPersistenceSession = persistenceSession;
224+
activeDiskWriteProtected = writeProtected;
225+
hasMountedDisk = true;
208226
}
209227

210228
// Check if the resource parameters have been set.
@@ -327,6 +345,37 @@ public boolean isPaused() {
327345
return paused;
328346
}
329347

348+
public boolean canResetMountedDisk() {
349+
return hasMountedDisk && (c1541Drive != null) && (activeDiskPersistenceSession != null)
350+
&& activeDiskPersistenceSession.isPersistent();
351+
}
352+
353+
public void resetMountedDisk(ResetDiskHandler resetDiskHandler) {
354+
if (!canResetMountedDisk()) {
355+
resetDiskHandler.onResetFailed();
356+
return;
357+
}
358+
359+
activeDiskPersistenceSession.resetToOriginalImage(
360+
new DiskImagePersistenceSession.ResetHandler() {
361+
@Override
362+
public void onResetComplete(byte[] diskImageBytes) {
363+
if ((diskImageBytes == null) || (diskImageBytes.length == 0)) {
364+
resetDiskHandler.onResetFailed();
365+
return;
366+
}
367+
368+
c1541Drive.replaceDisk(diskImageBytes, activeDiskWriteProtected);
369+
resetDiskHandler.onResetComplete();
370+
}
371+
372+
@Override
373+
public void onResetFailed() {
374+
resetDiskHandler.onResetFailed();
375+
}
376+
});
377+
}
378+
330379
/**
331380
* Gets the MachineType of this Machine, i.e. either PAL or NTSC.
332381
*

core/src/main/java/emu/jvic/io/disk/C1541Drive.java

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,28 @@ public void insertDisk(byte[] diskData, boolean warmup,
161161
this.diskPersistenceSession.close();
162162
}
163163

164+
initialiseDisk(diskData, diskPersistenceSession, writeProtected);
165+
166+
if (warmup) {
167+
// Run the 1541 drive for a second to get it warmed up (needed for some games).
168+
for (int i = 0; i < 1500000; i++) {
169+
emulateCycle();
170+
}
171+
}
172+
}
173+
174+
/**
175+
* Replaces the currently inserted disk image without closing the current
176+
* persistence session.
177+
*/
178+
public void replaceDisk(byte[] diskData, boolean writeProtected) {
179+
initialiseDisk(diskData, diskPersistenceSession, writeProtected);
180+
}
181+
182+
private void initialiseDisk(byte[] diskData,
183+
DiskImagePersistenceSession diskPersistenceSession,
184+
boolean writeProtected) {
185+
164186
disk = new GcrDiskImage(diskData);
165187
this.diskPersistenceSession = diskPersistenceSession;
166188

@@ -171,13 +193,11 @@ public void insertDisk(byte[] diskData, boolean warmup,
171193
currentTrackSize = disk.getSectorCount(currentTrack);
172194
currentSector = disk.getSector(currentTrack, 0);
173195
this.writeProtected = writeProtected;
174-
175-
if (warmup) {
176-
// Run the 1541 drive for a second to get it warmed up (needed for some games).
177-
for (int i = 0; i < 1500000; i++) {
178-
emulateCycle();
179-
}
180-
}
196+
bytesWritten = 0;
197+
currentByte = -1;
198+
byteReady = false;
199+
lastSync = false;
200+
nextMoveForward = 0;
181201
}
182202

183203
/**

core/src/main/java/emu/jvic/io/disk/persistence/DiskImagePersistenceSession.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,20 @@
55
*/
66
public interface DiskImagePersistenceSession {
77

8+
interface ResetHandler {
9+
10+
void onResetComplete(byte[] diskImageBytes);
11+
12+
void onResetFailed();
13+
}
14+
815
byte[] getStartupDiskImage();
916

1017
boolean isPersistent();
1118

1219
void onDiskChanged(byte[] diskImageBytes);
1320

21+
void resetToOriginalImage(ResetHandler resetHandler);
22+
1423
void close();
1524
}

core/src/main/java/emu/jvic/io/disk/persistence/NoOpDiskImagePersistenceSession.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ public boolean isPersistent() {
2525
public void onDiskChanged(byte[] diskImageBytes) {
2626
}
2727

28+
@Override
29+
public void resetToOriginalImage(ResetHandler resetHandler) {
30+
resetHandler.onResetComplete(startupDiskImage);
31+
}
32+
2833
@Override
2934
public void close() {
3035
}

core/src/main/java/emu/jvic/ui/MachineInputProcessor.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.badlogic.gdx.utils.Scaling;
1111
import com.badlogic.gdx.utils.viewport.ExtendViewport;
1212

13+
import emu.jvic.JVicRunner;
1314
import emu.jvic.KeyboardMatrix;
1415
import emu.jvic.KeyboardType;
1516
import emu.jvic.MachineScreen;
@@ -165,6 +166,9 @@ public boolean keyUp(int keycode) {
165166
}
166167
return true;
167168
case Keys.Z:
169+
handleDiskReset();
170+
return true;
171+
case Keys.MINUS:
168172
rotateScreenSize();
169173
return true;
170174
default:
@@ -506,6 +510,41 @@ public void no() {
506510
});
507511
}
508512

513+
private void handleDiskReset() {
514+
if (dialogHandler.isDialogOpen() || !machineScreen.getJvicRunner().canResetMountedDisk()) {
515+
return;
516+
}
517+
518+
if (Gdx.app.getType().equals(ApplicationType.Desktop) && Gdx.graphics.isFullscreen()) {
519+
switchOutOfFullScreen();
520+
}
521+
522+
machineScreen.getJvicRunner().pause();
523+
dialogHandler.confirm("Reset the mounted disk to its original image? Any persisted changes will be lost.",
524+
new ConfirmResponseHandler() {
525+
@Override
526+
public void yes() {
527+
machineScreen.getJvicRunner().requestMountedDiskReset(
528+
new JVicRunner.ResetDiskHandler() {
529+
@Override
530+
public void onResetComplete() {
531+
machineScreen.getJvicRunner().resume();
532+
}
533+
534+
@Override
535+
public void onResetFailed() {
536+
machineScreen.getJvicRunner().resume();
537+
}
538+
});
539+
}
540+
541+
@Override
542+
public void no() {
543+
machineScreen.getJvicRunner().resume();
544+
}
545+
});
546+
}
547+
509548
private void handleShowFPSToggle() {
510549
machineScreen.toggleShowFPS();
511550
}

html/src/main/java/emu/jvic/gwt/GwtJVicRunner.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ public class GwtJVicRunner extends JVicRunner {
5959
* The web worker that will execute the VIC 20 emulator in the background.
6060
*/
6161
private Worker worker;
62+
63+
private boolean resetMountedDiskSupported;
64+
65+
private ResetDiskHandler pendingResetDiskHandler;
6266

6367
/**
6468
* Indicates that the GWT GwtJVicRunner is in the stopped state, i.e. it was previously
@@ -187,6 +191,19 @@ private byte[] resolveMountedDiskImageData(AppConfigItem appConfigItem, Program
187191

188192
return loadBlankDiskImage();
189193
}
194+
195+
private boolean supportsMountedDiskReset(AppConfigItem appConfigItem,
196+
byte[] mountedDiskImageData) {
197+
switch (appConfigItem.getDiskWriteMode()) {
198+
case OFF:
199+
case TEMP:
200+
return false;
201+
case DEFAULT:
202+
case PERSIST:
203+
default:
204+
return "DISK".equals(appConfigItem.getFileType()) || (mountedDiskImageData != null);
205+
}
206+
}
190207

191208
/**
192209
* Creates a new web worker to run the VIC 20 program.
@@ -197,6 +214,7 @@ public void createWorker(AppConfigItem appConfigItem, Program program) {
197214
clearPerformanceStats();
198215

199216
byte[] mountedDiskImageData = resolveMountedDiskImageData(appConfigItem, program);
217+
resetMountedDiskSupported = supportsMountedDiskReset(appConfigItem, mountedDiskImageData);
200218
int programDataLength = (program != null) ? program.getProgramData().length : 0;
201219
int mountedDiskImageDataLength = (mountedDiskImageData != null)
202220
? mountedDiskImageData.length
@@ -230,6 +248,14 @@ public void onMessage(MessageEvent event) {
230248
getNestedInt(eventObject, "audioQueueSamples"),
231249
getNestedDouble(eventObject, "audioQueueMillis"));
232250
break;
251+
252+
case "MountedDiskResetComplete":
253+
completeMountedDiskReset(true);
254+
break;
255+
256+
case "MountedDiskResetFailed":
257+
completeMountedDiskReset(false);
258+
break;
233259

234260
default:
235261
// Unknown. Ignore.
@@ -390,6 +416,8 @@ public void stop() {
390416
worker.terminate();
391417
soundGenerator.pauseSound();
392418
stopped = true;
419+
resetMountedDiskSupported = false;
420+
pendingResetDiskHandler = null;
393421
}
394422

395423
@Override
@@ -398,6 +426,8 @@ public void reset() {
398426
paused = false;
399427
stopped = false;
400428
worker = null;
429+
resetMountedDiskSupported = false;
430+
pendingResetDiskHandler = null;
401431
clearPerformanceStats();
402432

403433
clearUrl();
@@ -501,6 +531,22 @@ public boolean hasStopped() {
501531
public boolean isRunning() {
502532
return (worker != null);
503533
}
534+
535+
@Override
536+
public boolean canResetMountedDisk() {
537+
return (worker != null) && resetMountedDiskSupported;
538+
}
539+
540+
@Override
541+
public void requestMountedDiskReset(ResetDiskHandler resetDiskHandler) {
542+
if (!canResetMountedDisk() || (pendingResetDiskHandler != null)) {
543+
resetDiskHandler.onResetFailed();
544+
return;
545+
}
546+
547+
pendingResetDiskHandler = resetDiskHandler;
548+
worker.postObject("ResetMountedDisk", JavaScriptObject.createObject());
549+
}
504550

505551
@Override
506552
public void changeSound(boolean soundOn) {
@@ -536,6 +582,20 @@ public void saveScreenshot(Pixmap screenPixmap, AppConfigItem appConfigItem) {
536582
// Not supported yet by the HTML5/GWT version.
537583
}
538584

585+
private void completeMountedDiskReset(boolean success) {
586+
ResetDiskHandler resetDiskHandler = pendingResetDiskHandler;
587+
pendingResetDiskHandler = null;
588+
if (resetDiskHandler == null) {
589+
return;
590+
}
591+
592+
if (success) {
593+
resetDiskHandler.onResetComplete();
594+
} else {
595+
resetDiskHandler.onResetFailed();
596+
}
597+
}
598+
539599
public void updatePerformanceStats(double avgUnusedNanosPerCycle, double headroomFactor,
540600
double busyPercent, double avgBatchWorkMillis, double avgBatchCycles,
541601
int audioQueueSamples, double audioQueueMillis) {

0 commit comments

Comments
 (0)