/*
* @(#)Jasper.java 1.1 27/04/97 Adam Davidson & Andrew Pollard
*/
import java.awt.*;
import java.applet.*;
import java.net.*;
import java.io.*;
/**
*
The Jasper class wraps up
* the Spectrum class into an Applet which emulates a ZX Spectrum in a Web Page.
*
*
*
*
*
* This applet can be supplied the following parameters:
*
* - snapshot - name of SNA or Z80 snapshot to load
*
- rom - filename of ROM (default=spectrum.rom)
*
- borderWidth - width of spectrum border (default=20)
*
- refreshRate - refresh screen every 'X' interrupts (default=1)
*
- sleepHack - sleep per interrupt in ms, for old VMs (default=0)
*
- showStats - show progress bar (default=Yes)
*
*
* The snapshot parameter can specify a file in one of two popuplar formats,
* .z80
* or .sna.
* The type is determined at runtime by checking the length of the snapshot
* file, if it is 49,179 then it is assumed to be of type .sna else it is assumed to
* be of type .z80.
*
* The rom parameter can be used to specify a different ROM to load
* other than the standard sinclair ROM. This file must be 16,384 bytes in length.
* The default value is spectrum.rom.
*
* The borderWidth parameter specifies the width in pixels of the border
* which surrounds the main screen. The default value is 20.
*
* The refreshRate parameter specifies how often the screen should be
* updated in terms of Z80 interrupts. The default value is 1.
*
* The sleepHack parameter is needed to introduce a delay into the main
* Z80 execute loop. In some browsers, the thread which updates the screen and
* delivers keyboard/mouse events to the applet can be blocked out by the Spectrum
* thread since it never gives up its timeslice. By default the value for this
* is 0 which means that the main execute loop runs at full speed.
*
*
The showStats parameter enables or disables the progress bar at the
* foot of the screen. The values that can be supplied are Yes and No.
* The default value is Yes.
*
* Since the release of version 1.0 Jasper has won various awards:
*
*
*
*
*
*
*
*
*
*
* Jasper is best viewed with:
*
*
*
*
*
* Thanks to Adam Doppelt
* for his AMDProgressBar class.
*
* Version: 1.1 27 Apr 1997
* Authors: Adam Davidson & Andrew Pollard
*
* @see Spectrum
* @see Z80
*/
public class Jasper extends Applet implements Runnable {
Spectrum spectrum = null;
Thread thread = null;
/** Version and author information. */
public String getAppletInfo() {
return "Jasper V1.1 by Adam Davidson and Andrew Pollard";
}
/** Applet parameters and their descriptions. */
public String[][] getParameterInfo() {
String [][] info = {
{ "snapshot", "filename", "name of SNA or Z80 snapshot to load" },
{ "rom", "filename", "filename of ROM (default=spectrum.rom)" },
{ "borderWidth", "integer", "width of spectrum border (default=20)" },
{ "refreshRate", "integer", "refresh screen every 'X' interrupts (default=1)" },
{ "sleepHack", "integer", "sleep per interrupt in ms, for old VMs (default=0)" },
{ "showStats", "Yes/No", "show progress bar (default=Yes)" },
};
return info;
}
/** Initailize the applet. */
public void init() {
setLayout( null );
}
/** Start the applet creating a new thread which invokes run(). */
public void start() {
if ( thread == null ) {
thread = new Thread( this, "Jasper" );
thread.start();
}
}
/** Stop the applet. */
public void stop() {
if ( thread != null ) {
thread.stop();
thread = null;
}
}
/** Parse available applet parameters.
* @exception Exception Problem loading ROM or snaphot.
*/
public void readParameters() throws Exception {
String rom = getParameter( "rom" );
if ( rom == null ) {
rom = "spectrum.rom";
}
spectrum.setBorderWidth( getIntParameter( "borderWidth",
spectrum.borderWidth*spectrum.pixelScale, 0, 100 ) );
spectrum.refreshRate = getIntParameter( "refreshRate",
spectrum.refreshRate, 1, 100 );
spectrum.sleepHack = getIntParameter( "sleepHack",
spectrum.sleepHack, 0, 100 );
resize( preferredSize() ); // once borderWidth is set up
String showStats = getParameter( "showStats" );
if ( showStats != null ) {
if ( showStats.equals( "Yes" ) ) {
spectrum.showStats = true;
}
else
if ( showStats.equals( "No" ) ) {
spectrum.showStats = false;
}
}
URL baseURL = getDocumentBase();
spectrum.urlField.setText( baseURL.toString() );
URL romURL = new URL( baseURL, rom );
spectrum.loadROM( romURL.toString(), romURL.openStream() );
String snapshot = getParameter( "snapshot" );
snapshot = ((snapshot == null) ? getParameter( "sna" ) : snapshot);
snapshot = ((snapshot == null) ? getParameter( "z80" ) : snapshot);
if ( snapshot != null ) {
URL url = new URL( baseURL, snapshot );
URLConnection snap = url.openConnection();
InputStream input = snap.getInputStream();
spectrum.loadSnapshot( url.toString(), input, snap.getContentLength() );
input.close();
}
else {
spectrum.reset();
spectrum.refreshWholeScreen();
}
}
/** Read applet parameters and start the Spectrum. */
public void run() {
showStatus( getAppletInfo() );
if ( spectrum == null ) {
try {
spectrum = new Spectrum( this );
readParameters();
}
catch ( Exception e ) {
showStatus( "Caught IO Error: " + e.toString() );
}
}
if ( spectrum != null ) {
spectrum.execute();
}
}
/** Handle integer parameters in a range with defaults. */
public int getIntParameter( String name, int ifUndef, int min, int max ) {
String param = getParameter( name );
if ( param == null ) {
return ifUndef;
}
try {
int n = Integer.parseInt( param );
if ( n < min ) return min;
if ( n > max ) return max;
return n;
}
catch ( Exception e ) {
return ifUndef;
}
}
/** Refresh handling. */
public void update( Graphics g ) {
paint( g );
}
/** Paint sets a flag on the spectrum to tell it to redraw the
screen on the next Z80 interrupt. */
public void paint( Graphics g ) {
if ( spectrum != null ) {
spectrum.repaint();
}
}
/** Event handling. */
public boolean handleEvent( Event e ) {
if ( spectrum != null ) {
return spectrum.handleEvent( e );
}
return super.handleEvent( e );
}
/** Applet size. */
public Dimension minimumSize() {
int scale = spectrum.pixelScale;
int border = (spectrum == null) ? 20 : spectrum.borderWidth;
return new Dimension(
spectrum.nPixelsWide * scale + border*2,
spectrum.nPixelsHigh * scale + border*2
);
}
/** Returns Jasper.minimumSize(). */
public Dimension preferredSize() {
return minimumSize();
}
}