2017-12-29 19:46:27 +00:00
package jace.lawless ;
2023-07-03 20:44:23 +00:00
import java.io.File ;
import java.io.FileInputStream ;
import java.io.FileNotFoundException ;
import java.io.IOException ;
import java.io.InputStream ;
import java.nio.file.StandardCopyOption ;
import java.util.Optional ;
import java.util.logging.Level ;
import java.util.logging.Logger ;
2017-12-29 19:46:27 +00:00
import jace.Emulator ;
import jace.LawlessLegends ;
import jace.apple2e.RAM128k ;
2023-07-03 20:44:23 +00:00
import jace.core.Computer ;
2017-12-29 19:46:27 +00:00
import jace.core.Keyboard ;
import jace.core.Utility ;
import jace.hardware.massStorage.CardMassStorage ;
import jace.library.DiskType ;
import jace.library.MediaConsumer ;
import jace.library.MediaEntry ;
import jace.library.MediaEntry.MediaFile ;
import javafx.scene.control.Label ;
2023-07-03 20:44:23 +00:00
import javafx.stage.FileChooser ;
2017-12-29 19:46:27 +00:00
/ * *
*
* @author brobert
* /
public class LawlessImageTool implements MediaConsumer {
Optional < Label > icon = Optional . empty ( ) ;
MediaEntry gameMediaEntry ;
MediaFile gameMediaFile ;
public LawlessImageTool ( ) {
icon = Utility . loadIconLabel ( " game_icon.png " ) ;
icon . ifPresent ( i - > {
i . setText ( " Upgrade Game " ) ;
} ) ;
}
@Override
public Optional < Label > getIcon ( ) {
return icon ;
}
@Override
public void setIcon ( Optional < Label > i ) {
icon = i ;
}
@Override
public void insertMedia ( MediaEntry e , MediaEntry . MediaFile f ) throws IOException {
2020-06-06 07:05:08 +00:00
Utility . decision ( " Upgrade Game " , " Do you want to attempt to preserve your save game? " , " Yes " , " No " , ( ) - > performGameUpgradeConfirmation ( e , f ) , ( ) - > replaceGameImageConfirmation ( e , f ) ) ;
}
public void performGameUpgradeConfirmation ( MediaEntry e , MediaEntry . MediaFile f ) {
2017-12-29 19:46:27 +00:00
Utility . confirm ( " Upgrade Game " ,
" This will upgrade your game and attempt to copy your progress. "
2020-06-06 07:05:08 +00:00
+ " If this is unsuccessful you will lose your progress and have to start over. Proceed? " ,
2017-12-29 19:46:27 +00:00
( ) - > performGameUpgrade ( e , f ) ) ;
}
2020-06-06 07:05:08 +00:00
public void replaceGameImageConfirmation ( MediaEntry e , MediaEntry . MediaFile f ) {
Utility . confirm ( " Upgrade Game " ,
" You are about to replace your game and lose any saved progress. Proceed? " ,
( ) - > performGameReplace ( e , f ) ) ;
}
2017-12-29 19:46:27 +00:00
@Override
public MediaEntry getMediaEntry ( ) {
return gameMediaEntry ;
}
@Override
public MediaFile getMediaFile ( ) {
return gameMediaFile ;
}
@Override
public boolean isAccepted ( MediaEntry e , MediaEntry . MediaFile f ) {
2020-01-02 00:56:30 +00:00
return e . type = = DiskType . FLOPPY800 | | e . type = = DiskType . LARGE ;
2017-12-29 19:46:27 +00:00
}
@Override
public void eject ( ) {
// Do nothing
}
private void insertHardDisk ( int drive , MediaEntry entry , MediaFile file ) {
2023-07-03 20:44:23 +00:00
Emulator . withMemory ( m - > m . getCard ( 7 ) . ifPresent ( card - > {
2017-12-29 19:46:27 +00:00
try {
( ( CardMassStorage ) card ) . getConsumers ( ) [ drive ] . insertMedia ( entry , file ) ;
} catch ( IOException ex ) {
Logger . getLogger ( LawlessLegends . class . getName ( ) ) . log ( Level . SEVERE , null , ex ) ;
}
2023-07-03 20:44:23 +00:00
} ) ) ;
2017-12-29 19:46:27 +00:00
if ( drive = = 0 ) {
gameMediaEntry = entry ;
gameMediaFile = file ;
}
}
2020-06-06 07:05:08 +00:00
private void readCurrentDisk ( int drive ) {
2023-07-03 20:44:23 +00:00
Emulator . withMemory ( m - > m . getCard ( 7 ) . ifPresent ( card - > {
2020-06-06 07:05:08 +00:00
gameMediaEntry = ( ( CardMassStorage ) card ) . getConsumers ( ) [ drive ] . getMediaEntry ( ) ;
gameMediaFile = ( ( CardMassStorage ) card ) . getConsumers ( ) [ drive ] . getMediaFile ( ) ;
2023-07-03 20:44:23 +00:00
} ) ) ;
2020-06-06 07:05:08 +00:00
}
2017-12-29 19:46:27 +00:00
private void ejectHardDisk ( int drive ) {
2023-07-03 20:44:23 +00:00
Emulator . withMemory ( m - > m . getCard ( 7 ) . ifPresent ( card - > {
2017-12-29 19:46:27 +00:00
( ( CardMassStorage ) card ) . getConsumers ( ) [ drive ] . eject ( ) ;
2023-07-03 20:44:23 +00:00
} ) ) ;
2017-12-29 19:46:27 +00:00
if ( drive = = 0 ) {
gameMediaEntry = null ;
gameMediaFile = null ;
}
}
public void loadGame ( ) {
// Insert game disk image
MediaEntry e = new MediaEntry ( ) ;
e . author = " 8 Bit Bunch " ;
e . name = " Lawless Legends " ;
e . type = DiskType . LARGE ;
MediaFile f = new MediaEntry . MediaFile ( ) ;
f . path = getGamePath ( " game.2mg " ) ;
if ( f . path ! = null & & f . path . exists ( ) ) {
insertHardDisk ( 0 , e , f ) ;
}
}
private File getGamePath ( String filename ) {
File base = getApplicationStoragePath ( ) ;
File target = new File ( base , filename ) ;
if ( ! target . exists ( ) ) {
copyResource ( filename , target ) ;
}
return target ;
}
private File getApplicationStoragePath ( ) {
String path = System . getenv ( " APPDATA " ) ;
if ( path = = null ) {
path = System . getProperty ( " user.home " ) ;
}
if ( path = = null ) {
2023-07-03 20:44:23 +00:00
path = System . getProperty ( " user.dir " ) ;
2017-12-29 19:46:27 +00:00
}
File base = new File ( path ) ;
File appPath = new File ( base , " lawless-legends " ) ;
appPath . mkdirs ( ) ;
return appPath ;
}
2023-07-03 20:44:23 +00:00
private File getUserGameFile ( ) {
return new File ( getApplicationStoragePath ( ) , " game.2mg " ) ;
}
2017-12-29 19:46:27 +00:00
private void copyResource ( String filename , File target ) {
2023-07-03 20:44:23 +00:00
File localResource = getUserGameFile ( ) ;
2017-12-29 19:46:27 +00:00
InputStream in = null ;
if ( localResource . exists ( ) ) {
try {
in = new FileInputStream ( localResource ) ;
} catch ( FileNotFoundException ex ) {
Logger . getLogger ( LawlessLegends . class . getName ( ) ) . log ( Level . SEVERE , null , ex ) ;
}
} else {
2023-07-03 20:44:23 +00:00
in = getClass ( ) . getResourceAsStream ( " /jace/data/ " + filename ) ;
2017-12-29 19:46:27 +00:00
}
if ( in ! = null ) {
try {
java . nio . file . Files . copy ( in , target . toPath ( ) , StandardCopyOption . REPLACE_EXISTING ) ;
} catch ( IOException ex ) {
Logger . getLogger ( LawlessLegends . class . getName ( ) ) . log ( Level . SEVERE , null , ex ) ;
}
} else {
Logger . getLogger ( LawlessLegends . class . getName ( ) ) . log ( Level . SEVERE , " Unable to find resource {0} " , filename ) ;
2023-07-03 20:44:23 +00:00
Utility . decision ( " Unable to find game " , " Sorry partner, we can't find yer game disk. What're ya' gonna do about it? " , " I have it " , " Tuck tail and leave " , this : : selectGameFile , ( ) - > System . exit ( 1 ) ) ;
2017-12-29 19:46:27 +00:00
}
}
2023-07-03 20:44:23 +00:00
private void selectGameFile ( ) {
try {
FileChooser fileChooser = new FileChooser ( ) ;
fileChooser . setInitialFileName ( " game.2mg " ) ;
fileChooser . setTitle ( " Please locate your Lawless Legends game.2mg file to continue " ) ;
File gameFile = fileChooser . showOpenDialog ( null ) ;
if ( gameFile = = null | | ! gameFile . exists ( ) ) {
Utility . gripe ( " Sorry pardner, can't help ya' this time. " , true , ( ) - > { System . exit ( 1 ) ; } ) ;
} else {
java . nio . file . Files . copy ( gameFile . toPath ( ) , getUserGameFile ( ) . toPath ( ) , StandardCopyOption . REPLACE_EXISTING ) ;
loadGame ( ) ;
Emulator . withComputer ( Computer : : coldStart ) ;
}
} catch ( IOException ex ) {
Logger . getLogger ( LawlessImageTool . class . getName ( ) ) . log ( Level . SEVERE , null , ex ) ;
Utility . gripe ( " Couldn't load yer game, friend. Heard some fellow mumbling something about " + ex . getMessage ( ) , true , ( ) - > { System . exit ( 1 ) ; } ) ;
}
}
2017-12-29 19:46:27 +00:00
2020-06-06 07:05:08 +00:00
private void performGameReplace ( MediaEntry e , MediaFile f ) {
try {
File target = getMediaFile ( ) . path ;
ejectHardDisk ( 0 ) ;
java . nio . file . Files . copy ( f . path . toPath ( ) , target . toPath ( ) , StandardCopyOption . REPLACE_EXISTING ) ;
f . path = target ;
insertHardDisk ( 0 , e , f ) ;
2023-07-03 20:44:23 +00:00
Emulator . withComputer ( Computer : : coldStart ) ;
2020-06-06 07:05:08 +00:00
System . out . println ( " Upgrade completed " ) ;
} catch ( IOException ex ) {
Logger . getLogger ( LawlessImageTool . class . getName ( ) ) . log ( Level . SEVERE , null , ex ) ;
Utility . gripe ( ex . getMessage ( ) ) ;
}
}
2017-12-29 19:46:27 +00:00
private void performGameUpgrade ( MediaEntry e , MediaFile f ) {
try {
System . out . println ( " Game upgrade starting " ) ;
2020-06-06 07:05:08 +00:00
readCurrentDisk ( 0 ) ;
MediaEntry originalEntry = gameMediaEntry ;
MediaFile originalFile = gameMediaFile ;
// Put in new disk and boot it -- we want to use its importer in case that importer works better!
ejectHardDisk ( 0 ) ;
insertHardDisk ( 0 , e , f ) ;
2023-07-03 20:44:23 +00:00
Emulator . withComputer ( Computer : : coldStart ) ;
2017-12-29 19:46:27 +00:00
if ( ! waitForText ( " I)mport " , 1 ) ) {
2023-07-03 20:44:23 +00:00
Emulator . withComputer ( Computer : : coldStart ) ;
if ( ! waitForText ( " I)mport " , 2000 ) ) {
2017-12-29 19:46:27 +00:00
throw new Exception ( " Unable to detect upgrade prompt - Upgrade aborted. " ) ;
}
}
System . out . println ( " Menu Propmt detected " ) ;
2020-06-06 07:05:08 +00:00
2017-12-29 19:46:27 +00:00
Keyboard . pasteFromString ( " i " ) ;
2023-07-03 20:44:23 +00:00
if ( ! waitForText ( " Insert disk for import " , 1500 ) ) {
2020-06-06 07:05:08 +00:00
throw new Exception ( " Unable to detect first insert prompt - Upgrade aborted. " ) ;
2017-12-29 19:46:27 +00:00
}
System . out . println ( " First Propmt detected " ) ;
2020-06-06 07:05:08 +00:00
// Now put in the original disk to load its saved game (hopefully!)
ejectHardDisk ( 0 ) ;
insertHardDisk ( 0 , originalEntry , originalFile ) ;
2017-12-29 19:46:27 +00:00
Keyboard . pasteFromString ( " " ) ;
2023-07-03 20:44:23 +00:00
if ( ! waitForText ( " Game imported " , 2000 ) ) {
2020-06-06 07:05:08 +00:00
throw new Exception ( " Unable to detect second insert prompt - Upgrade aborted. " ) ;
2017-12-29 19:46:27 +00:00
}
2020-06-06 07:05:08 +00:00
System . out . println ( " Completing upgrade " ) ;
// Now we copy the new game disk over the old and insert it to write the save game and complete the upgrade.
2017-12-29 19:46:27 +00:00
File target = getMediaFile ( ) . path ;
ejectHardDisk ( 0 ) ;
java . nio . file . Files . copy ( f . path . toPath ( ) , target . toPath ( ) , StandardCopyOption . REPLACE_EXISTING ) ;
f . path = target ;
insertHardDisk ( 0 , e , f ) ;
Keyboard . pasteFromString ( " " ) ;
System . out . println ( " Upgrade completed " ) ;
} catch ( Exception ex ) {
Logger . getLogger ( LawlessImageTool . class . getName ( ) ) . log ( Level . SEVERE , null , ex ) ;
Utility . gripe ( ex . getMessage ( ) ) ;
}
}
private boolean waitForText ( String message , int timeout ) throws InterruptedException {
while ( timeout - - > 0 ) {
StringBuilder allText = new StringBuilder ( ) ;
2023-07-03 20:44:23 +00:00
Emulator . withMemory ( mem - > {
for ( int i = 0x0400 ; i < 0x07ff ; i + + ) {
allText . append ( ( char ) ( ( RAM128k ) mem ) . getMainMemory ( ) . readByte ( i ) & 0x07f ) ;
}
} ) ;
2017-12-29 19:46:27 +00:00
if ( allText . toString ( ) . contains ( message ) ) {
return true ;
} else {
2023-07-03 20:44:23 +00:00
Emulator . withComputer ( c - > {
try {
( ( LawlessComputer ) c ) . waitForVBL ( ) ;
} catch ( InterruptedException ex ) {
// Ignore
}
} ) ;
2017-12-29 19:46:27 +00:00
}
}
return false ;
}
}