This program emulates a Sinclair Spectrum 48k Z80-based computer 
on any PC with at least an 80386SX processor and VGA graphics.
  The following Spectrum features are implemented:
- Graphics, nearly perfectly.  The border is implemented, but only 
PJPP emulates flashing and special effects.
- The keyboard, nearly perfectly.
- Kempston joystick, if you have a PC joystick.  Both buttons on 
the PC joystick press the single Kempston button.
- Sound, but only one of the versions with the correct pitch.
- Not the tape interface.



                       Licence agreement

JPP is copyright (c) 1991-92 Arnt Gulbrandsen, except spconv.exe,
which is copyright (c) 1992 Henk de Groot, and specdisc.exe, which 
is copyright (c) 1992 Brian Havard.
  All rights are reserved, with the sole exception that, as long 
as the archive is kept together and no fee is involved, JPP may be 
copied by anyone.
  It is acceptable for BBSes to charge for general use but not 
specifically (additionally) for downloading of JPP.
  Disk vendors, user groups, or others who wish to distribute JPP 
for a fee may apply for permission.  Write to Arnt Gulbrandsen, 
Kometv. 8, N-7036 Trondheim, Norway, or agulbra@pvv.unit.no.



                             Files

spconv.exe     Converts snapshots between various formats.
                 Written by Henk de Groot.
groot.rom      A modified ROM.
jpp.cfg        The configuration file.
jpp.exe        The main emulator.
jpp.txt        This file.
js.exe         Reports how the joystick behaves.
pjpp.exe       The exact-speed version, for very fast machines.
readme.txt     A GIF showing, among others, Traci Lords.
specdisc.exe   Converts snapshots on MGT disks (48K SNP) to
                 .SNA format.  Written by Brian Havard,
                 s902150@minyos.xx.rmit.oz.au.
spectrum.rom   The Spectrum ROM.
tk95.rom       The Micro Digital TK95 ROM (a Spectrum clone).



                             Usage

JPP will try to interpret any command-line argument as either a 
ROM image or a snapshot, and load it.
  During execution, the 40 keys which correspond in layout to the 
Spectrum keyboard work as you'd expect.  There are also a number 
of extensions:
- Enter is Enter.
- Backspace is Caps-0.
- Both shifts are Caps-shift.
- Both alts are Symbol-shift.
- 0-9 on the keypad should work.
- +-*/ on the keypad work by 'pressing' Symbol-shift and another 
key.
- The cursor keys are Caps-5678.
  If you 'press' Caps-shift or Symbol-shift in several ways (eg. 
by pressing both DEL and a shift key) the (Spectrum) key will be 
released as soon as you release one (PC) key; this is because the 
emulator only counts whether a key is pressed or not, not (I know 
this sounds meaningless) how many times each key is pressed at 
once.
  Seven keys between 0-P-L-M and Backspace-Enter-Shift are unused.  
Unfortunately there's no way to find out what they characters they 
normally send, so JPP can't feed the 'normal' character to the 
Spectrum.  The key immediately to the right of 0, for instance, 
sends - and _ on North American keyboards, but + and ? on my 
Norwegian keyboard.
  Some function keys are interpreted by the emulator:
- F2 saves a snapshot.
- F3 loads a snapshot.
- F4 loads the snapshot which was saved or loaded last; very handy 
if you need to try a difficult part of a game again and again.
- F5 disables the sound.  Oh, blissful silence!
- F6 enables the sound.
- F10 and F12 both abort the emulator immediately.
  All other keys are ignored, except Ctrl-Alt-Del, which reboots 
the computer.



                     Windows, DV, OS/2 etc

  JPP is a real PC program; extremely aggressive towards operating 
systems.  It locks OS/2 2.0 up without even trying.  "Write 
down these numbers and call IBM."
  If, however, you want to use Windows or something, you should 
configure it so that JPP
- gets control of the hardware timers.  Without it many Spectrum 
games will run at a third of the intended speed.
- won't share the CPU when it's running in the foreground.
- won't run in the background.
- gets access to the sound.  If you don't want sound, press F5.
- won't share the screen.  Ten points to any straitjacket which 
manages to run JPP in a window.
- is allowed to do I/O.
  When JPP is brought back to foreground the screen may flicker 
wildly.  Press F3 then Esc to fix it.



                            JPP.CFG

This is the configuration file.  Presently it can only give the 
location of support files, whether the sound should initially be 
disabled, and which ROM file is the default.
  It is a case-insensitive pure text file.  All whitespace and 
everything after # on a line is ignored.  Each line may be up to 
255 characters, and is of the format <option>=<value>.
  <option> may be either "sound" or a file specification (which 
may include multiple * wildcards).
  If <option> is "sound", <value> may be "on" or "off".
  If <option> is "default-rom", <value> must be a file name, which 
will NOT be expanded according to the redirection rules.
  If <option> is a file specification, <value> must be a series of 
directories separated by ";".   I recommended that the directories 
be specified as absolute paths.



                     Copying games to a PC

I just put in support for reading tapes.  It doesn't work for me,
and I won't try to fix it, but you could always try it:  First
you use VREC (enclosed with the Soundblaster card) or another
sampler to copy the entire tape to disk.  Any frequency should
do.  The result should be fairly large, 4 megs or so, and be
called "tape-in.voc".  Then start PJPP from the directory where
the sample is and type LOAD "".  Oh, and remember to press F2 to
write the snapshot to disk when it's loaded, or you'll have to
keep that 4-meg file.  Three points:  Since it doesn't depend on
the real tape speed, PJPP can read (no it can't) tapes on any
386/486, even if not in real time.  Speedlock, Lenslock and other
loaders that depend on the R register won't work.  And, since I
use 32-bit arithmetic, there may be anomalies every 613 seconds.
To be safe, load the game immediately after starting PJPP.
  Much easier, if you have a Plus D/Disciple/MGT disk drive, is to 
snap the game to it, then use Specdisc to convert it to .sna 
format.  This has the disadvantage that the game may detect that 
the Spectrum has a disk drive and presume that it won't disappear 
(which it does once the snapshot is run under an emulator).
  Alternatively, a Mirage Microdriver snapshot box may be used to 
snap the game, either to Microdrive or to tape.  From a Microdrive 
it's easy to transfer it to a PC via serial cable.  From tape it's 
rather hard.
  One real hacker rewrote his Spectrum ROM to snap directly to 
serial cable; he just triggers an NMI, the game is sent out and in 
the other end of the cable a COPY command or something stores the 
output directly to a snapshot file.  Not for the novice, but very 
elegant.
  Peter McGavin's emulator can read from tape via a sound sampler, 
and uses the same snapshot format as JPP.
  Two other PC emulator can read Spectrum tapes via the parallel 
port.



                       The CPU emulation

My Z80 emulation code is 50-100% faster than any other Z80 
emulator I've seen on the PC.  (Whoops, no, not any more.  G. A. 
Lunter of the Netherlands has written one which sometimes is 
nearly as fast.)  The main reasons are that nearly all the Z80 
registers are kept in 386 registers and that very little time is 
spent on instruction decoding.  The design is based on Peter 
McGavin's Spectrum emulator on the Amiga.
  It is perfectly possible to rewrite JPP to work on a 286, less 
than a day's work, but it would run half as fast again on a 286/16 
as this version does on a 386SX/16.  Too slow to bother, IMHO.  If 
you only have a 286, get Mr. Lunter's emulator.  It won't run fast 
enough, but it will run.
  The register allocation is as follows:
 Z80  386
  AF  AX       F is kept in AH, A in AL
  BC  CX
  DE  DX
  HL  BX       In BX since BX can access memory
  SP  BP
  PC  SI
IX, IY, I, R and the alternates are kept in memory.  DI is used as 
scratch register.  DS points to the Spectrum address space, ES 
points to a special bookkeeping table, FS and GS to a 128k table 
of decoded instructions.  (FS and GS don't exist on the 286.)
  All the other emulators I've seen (except Peter's) decode each 
instruction every time it is used.  I avoid that by storing the 
address of the emulation routine for each address in a special 
128k table.  FS points to a 64k segment which contains the entries 
for the even Z80 addresses, GS  - blah blah - odd.  Each opcode 
knows how long it is and whether it is located on an even or odd 
address so it can jump through the correct table.
  In order to work with self-modifying code the decoding of an 
address must be invalidated whenever it is written to.  Another 
64k table (ES) keeps track of which decodings must be invalidated 
when an address is written to.  Bit N at address M is set if the 
decoding of address M-N depends on address M, for N<4.  Bits 4..6 
are unused (0) and bit 7 is set if the address is write protected.  
Thus, an opcode which writes to eg. [di] need only
    test [byte ptr es:di],255  ;rom, or previously decoded?
    jnz fix_write_di           ;any bit set -> go fix it (slow!)
    jmp [word ptr fs:si]       ;[word ptr gs:si-1] if si is odd
  Each opcode must be emulated twice, 192K RAM must be used for 
extra tables, and the code won't run on anything smaller than a 
386SX since so many segment registers are used, but!  It is twice 
as fast as anything else (except the Dutch emulator, more about 
which later).
  The only way to speed it up further is to compile and optimise, 
which could eliminate a lot of flag handling (many instructions 
affect several flags, at most one of which is actually used) and 
concatenate some instructions (eg. ld a,e; add a,7; ld e,a).  One 
possibility is to translate the Z80 code to a simple 2-register 
language, optimise the resulting code and finally interpret it.  
But would the optimised code be fast enough to offset the time 
taken to optimise it?
  To return to reality, there are some known bugs:
- The H processor flag is set incorrectly by 16-bit arithmetic 
instructions (it is the carry/borrow between bits 7 and 8, not 11 
and 12).
- The two 'unused' bits in the Z80 F register may be corrupted by 
some instructions on some processors.  The 386 seems ok but future 
Intel processors may not.
- Interrupts are delayed until directly after a CALL, JR, JP, RET, 
RETI, RETN and HALT instruction.
- LDIR may turn off the write protection of a few bytes at either 
end of the ROM (it resets bit 7 in ES of up to five bytes before 
the start if the destination block and one byte after its end).
- R is not quite perfectly emulated.  LD A,R loads bits 0..6 of A 
from 8253 timer 0 and bit 7 from R (set by LD R,A).
  There also is at least one (more) bug, which I am having trouble 
tracking down.
  Mr. Lunter's emulator does things mainly like JPP, but uses BX
for instruction decoding, puts DE in RAM, doesn't use the three 
extra segments used by JPP, and has some other, less important
differences.
  JPP emulates most documented and undocumented opcodes, the 
exceptions being IND, INI, INDR, INIR, OTDR, OTIR and the shift- 
with-autocopy instructions.  Instructions which aren't recognised 
abort the emulator.
  Starion uses OUTI and International Karate OUTD so they are now 
partially emulated.  B and HL are modified, but the flags aren't 
set and the port isn't written to.



                     The graphics emulation

JPP (now) runs in 320*240 16-colour mode.  Flashing is emulated by 
changing the bytes in the PC video memory rather than by changing 
the palette.
  DESQview and other programs which try to manage the screen 
generally don't restore it properly when JPP is brought back to 
foreground.  If you have this problem, press F3 then Esc.
  The fast version updates the entire PC screen from the Spectrum 
screen every 3rd interrupt (ie. the refresh frequency is 16.67Hz).  
The exact-speed version (PJPP) updates as many lines as there is 
time to before each interrupt (ie. the refresh frequency is at 
least 2.08Hz, at most 50Hz).



                      The sound emulation

The Spectrum sound system, as you probably know, is simple.  The 
processor controls the loudspeaker level, and by raising and 
lowering it at regular intervals can make tones.
  The PC system is, for practical purposes, exactly the same.  So 
emulating the Spectrum sound system should be simple?
  No, because the PC has to sample the joystick and update the 
screen as well.  Both require rather long time slices.  Also, 
unless the instructions take exactly as long as on the real 
Spectrum, the delay loops won't work and the tones will be thrown 
off.
  The standard JPP ignores timing and just outputs the sound as 
the Spectrum program does.  Hopefully it'll sound much as 
intended.
  PJPP is intended to do better, but still has to sample the 
joystick and update the screen.  The method I've chosen is to try 
to get the correct interval between clicks except when this is too 
long (frequencies below 160Hz) or when there's an overflow of some 
sort (between sounds, generally).  There is a limit to how high 
PJPP can go (roughly proportional to the CPU speed) and a limit to 
how accurately it can match the intended frequency (more or less 
constant).
  Since sound output requires extremely accurate timing the screen 
output is more or less suspended while the sound is being made.  
Currently the refresh frequency may be as low as 2.08Hz, but it 
would be easy to increase that limit.



                          Peripherals

The Spectrum has very little in the way of peripherals, and JPP 
emulates even less.
  On ports XXFEh, JPP emulates the keyboard (and PJPP the tape 
too) on input, and the speaker and border on output.
  On ports XX1Fh, JPP emulates a Kempston joystick on input and 
nothing on output.  If the PC doesn't have a joystick the Kempston 
always is in the neutral position.
  On port XXFFh, JPP returns FFh during Spectrum vertical retrace, 
else ((n+1) mod 256) where n is the previous value returned.  The 
Spectrum vertical retrace occurs 50 times a second, the real 
retrace usually has a frequency of 60-75Hz.
  On all other ports JPP returns FFh on input and ignores output.
  Since reading the PC joystick position is inordinately slow, JPP 
reads it every 0.02 second (starting when the Spectrum program 
first accesses the Kempston) and feeds the value read to the 
Spectrum whenever the Spectrum program reads the Kempston.  The 
button status is read whenever the Spectrum program wants to.



                         General Notes

There is a not very active mailing list for the Spectrum, mail 
mauricio@mozart.aero.ufl.edu to be added.  New versions of JPP 
(hah! none!) will be announced on the list.
  You may have wondered about the name JPP.  Try typing J 
Symbolshift-P Symbolshift-P on a Spectrum; I was feeling rather 
sentimental when I named the emulator.
  This document is based on the documentation Peter McGavin wrote 
for his Spectrum emulator.  I am extremely grateful to Peter for 
all his help.
  Henk de Groot has fixed the Spectrum ROM bugs, but at least one 
game breaks on his ROM.  Unfortunately his email address is likely 
to change in the near future; Mauricio or I will know what it is.  
He has also written a program, "convert.exe", to convert snapshots 
between various format.  This program is enclosed.
  The joystick emulation uses a routine which should work no 
matter how fast the processor is.  If the 558 in your joystick 
interface is clocked faster or slower than mine (the neutral 
position is off-centre), tell me!
  There may be some linguistic errors in this document.  Sorry 
about that, but please bear in mind that English is not my first 
language.
  The speed indicator (the little bar to the right of the display) 
is the average number of clock cycles JPP emulates relative to how 
fast I think the real Spectrum is, averaged over the last half 
second.  It occasionally dips over 100%, which is quite right, 
during HALT and large LDIRs JPP does work faster than the real 
Spectrum.
  The differences between the two executables are that PJPP:
  - counts clock cycles and makes sure that 3500000 are emulated 
each second.
  - allows LDIR to be interrupted.
  - does tape emulation, of sorts.
  - shows the relative speed of the emulator on the right of the 
screen.
  - emulates the border properly, including striped loading.
  - uses a variable-frequency graphics update.
  - HALT works perfectly.  JPP just guesses.
  Both versions share the following faults:
  - R isn't properly emulated.
  - Tape output isn't supported.
  - Rainbowing isn't emulated.
  - Port 255 may be used to find the vertical retrace, but not to 
sync with specific colours on-screen.
  - The two unused flag bits seem to be corrupted by some 
instructions.
  The FTP/FSP site wuarchive.wustl.edu has some Spectrum files in 
/systems/sinclair.  South African users should use the mirror site 
ftp.sun.ac.za, directory /pub/msdos/zx.



                        Other emulators

I have about six other emulators, and there are several that I 
don't have.  All, except where noted, are PD and available for 
anonymous FTP and FSP at wuarchive.wustl.edu, somewhere below 
directory /systems/sinclair.

PC:
  VGASPEC.EXE, originally by Alfonso Olloqui.  Needs 286+VGA, runs 
at less than half the speed of JPP.  A later version by another 
author seems to be better, but I haven't tested it yet.  The newer 
version has some tape support.  This is the one with the doc file 
I can't read.
  SP.EXE, untested, I've consistently forgotten to bring it home.  
CGA, I think, and a built-in debugger.
  Brian Havard wrote, but didn't release, an emulator.  Simple and 
short, slow, not developed very far since it was so slow.
  G. A. Lunter has written an excellent emulator.  Unfortunately 
the docs and on-screen prompts are in Dutch, so it's not too 
usable.  Version 1.30 adds a short summary in English.  Versions 
from 1.41 on support full tape input and output.  This is the only 
emulator which approaches the speed of JPP.
  IRISH.ZIP, buggy and slow.

Amiga:
  Spectrum, by Peter McGavin.  Very good, JPP is based to a large 
extent on it.  Needs about a 25MHz machine to run at full speed.  
Has tape support.
  KGB.  I haven't seen it.  A bit slower than Peter's, and the 
version Peter saw wouldn't work on the Amiga 3000.
  An Italian emulator which I don't know the name of.  Excellent 
compatibility, rather fast.  May be shareware.
  Dirk Akkerman wrote one; he says it's good but I haven't seen it.
I'm sure it will appear on wuarchive shortly.
  Several unreleased emulators.  Peter knows more about them.

Atari ST/TT:
  One, called Spectrum.  Don't know anything about it, but the doc 
file is written in quite the worst English I've seen.  Available 
by anonymous ftp from terminator.cc.umich.edu.

Acorn Archimedes:
  A company called Arxe wrote one, intended to be commercial but 
never released because Amstrad wouldn't permit Arxe to enclose the 
ROM.
  Someone called D. Lawrence wrote another, or maybe the same.  
This one is floating around but nobody has any documentation.  I 
don't know what its status is.  Runs at about 70% of Spectrum 
speed on an ARM2, not quite perfect graphics emulation.

Commodore 64:
  The Whitby Software Spectrum simulator is a rewrite of the 
Spectrum Basic.  It will not run machine-code programs.  I don't 
know whether it's PD, shareware, or commercial.



                    The snapshot file format

This format (filetype .SNA) is the format used by the Mirage 
Microdriver "Dump" command.  It is also used by Peter McGavin's 
Spectrum emulator for the Amiga.

 Byte offset    Contents

    0          i  register
    1          l' register
    2          h' register
    3          e' register
    4          d' register
    5          c' register
    6          b' register
    7          f' register
    8          a' register
    9          l  register
   10          h  register
   11          e  register
   12          d  register
   13          c  register
   14          b  register
   15          iy low register
   16          iy high register
   17          ix low register
   18          ix high register
   19          bit 2 contains iff2
   20          r register
   21          flags register
   22          a register
   23          sp low register
   24          sp high register
   25          interrupt mode (0, 1 or 2)
   26          border colour (0..7).
 27..49178     48 kbytes ram dump

When the registers have been loaded a RETN command is required to 
start the program.
  IFF2 is short for interrupt flip-flop 2, and for all practical 
purposes is the interrupt-enabled flag.  Set means enabled.
  Since Peter's emulator stores rubbish in byte 26 JPP sets the 
border to black if byte 26 is larger than 7.



         List of working programs (and some that don't)

I haven't tested them very thoroughly, most games bore me very 
quickly, but at least the title screen and the start of the first 
level work.
  This list was produced by `ls */*.sna', so it's not more correct 
that my directories were tidy.

10frame.zip    dambust.zip    horiza2.zip    mugsyii.zip    split.zip
10indian.zip   dan2.zip       horiza3.zip    mutant.zip     sportsh.zip
180.zip        dandy.zip      horiza4.zip    necropol.zip   spray.zip
1942.zip       darkstar.zip   horiza5.zip    nederlan.zip   sprinter.zip
2112ad.zip     dbltake.zip    horiza6.zip    nemesis.zip    spyhunt.zip
2guntrtl.zip   dchase.zip     horizb1.zip    newterm.zip    spyvspy.zip
3descap.zip    deathcha.zip   horizb2.zip    nflite2.zip    ssprint.zip
3dluna.zip     decath-1.zip   horizb3.zip    nifty.zip      st-berna.zip
3dtank.zip     decath-2.zip   horizb4.zip    nipper.zip     stainste.zip
3weeks.zip     defender.zip   horizb5.zip    niteshde.zip   stanley.zip
a_mole1.zip    deus_1.zip     horizb6.zip    nod_ysod.zip   star-rai.zip
a_mole2.zip    deus_2.zip     horizb7.zip    nomad.zip      starbike.zip
acrojet.zip    devpac.zip     horizb8.zip    nosferat.zip   starion.zip
adastra.zip    dictator.zip   horizb9.zip    octagon.zip    starmap.zip
advent-8.zip   dmouse2.zip    horizons.doc   olli.zip       starquak.zip
advent_a.zip   donkey.zip     howhero.doc    olympiad.zip   starship.zip
advent_b.zip   doomsday.zip   howhero1.zip   omega.zip      starstr2.zip
advent_c.zip   dragontc.zip   howhero2.zip   ometron.zip    starstrk.zip
advent_d.zip   drats.zip      hpascal.zip    orbiter.zip    startrek.zip
ageddon.zip    draughts.zip   hskiing.zip    orbix.zip      stonkers.zip
ahdiddum.zip   dreadngt.zip   hulk.zip       pacland.zip    supchess.zip
airwolf.zip    driller.zip    hunch2.zip     pacmania.zip   superstr.zip
alchemis.zip   druid.zip      hunchbck.zip   painter.zip    survivor.zip
alien8.zip     dukes.zip      hunter.zip     panama.zip     sweevo.zip
alienh.zip     dundarac.zip   hypaball.zip   panza.zip      system15.zip
aliens.zip     dustin.zip     hyperact.zip   paperboy.zip   talk-che.zip
america.zip    dwarrior.zip   hypsport.zip   paravia.zip    talk.zip
android2.zip   dwing.zip      i_karate.zip   paws.zip       tanx.zip
ant-atta.zip   dynadan1.zip   id.zip         pedro.zip      tapper.zip
antattak.zip   dynadan2.zip   imask.zip      penetrat.zip   tarzan.zip
antics.zip     eaglenes.zip   imposbal.zip   penta.zip      tasword.zip
anything.zip   eagles.zip     impsball.zip   ph_tomb.zip    tau_ceti.zip
aquaplan.zip   editamon.zip   indidemo.zip   pharaoh.zip    tcresta.zip
arabian.zip    elevator.zip   invaders.zip   phenix.zip     ted.zip
arc_ysod.zip   elite.zip      is-chess.zip   pigeon.zip     tempest.zip
arcadia.zip    embassy.zip    jackbean.zip   pimania.zip    temple.zip
arkanoid.zip   empire.zip     jason.zip      pinball.zip    termolin.zip
artist2.zip    enduro.zip     jeroen.zip     pingpong.zip   terra.zip
ashes.zip      enigma.zip     jetman.zip     pioneer.zip    tetris.zip
asterix.zip    equinox.zip    jetpac.zip     pitman7.zip    tfdemo.zip
atf.zip        eric.zip       jetset.zip     planet.zip     tformers.zip
aufmonty.zip   escape.zip     jetset2.zip    planets.zip    thanatos.zip
automani.zip   eskimo.zip     jetsetw3.zip   platoon.zip    thing.zip
b17intro.zip   esmerald.zip   jfever.zip     pogo.zip       thingbb.zip
backgamm.zip   europe.zip     joeblade.zip   pontoon.zip    think.zip
barrybox.zip   evolutn.zip    johnreb.zip    pool.zip       thuncats.zip
baseball.zip   exodus.zip     jsw.zip        popeye.zip     thunder.zip
basicod3.zip   exolon.zip     jsw2.zip       position.zip   time.zip
basil.zip      express.zip    jumbly.zip     postpat.zip    timegate.zip
basket.zip     factory.zip    jump-j1.zip    progolf.zip    tirnanog.zip
batman.zip     fairlght.zip   jumpjack.zip   projectf.zip   tll.zip
battle17.zip   fairlgt2.zip   k_tyme.zip     pshotdem.zip   toadrun.zip
batty.zip      fb_year.zip    kanga.zip      pssst.zip      tomahawk.zip
bazooka.zip    files.bbs      karnov.zip     psyche.zip     tomatoes.zip
bcquest.zip    finance.zip    ket.zip        psytron.zip    topgun.zip
bdash.zip      findkeep.zip   knight.zip     pulsar7.zip    toymaker.zip
bearbovr.zip   finhours.zip   knot3d.zip     pyjamara.zip   train-ga.zip
betbasic.zip   firelord.zip   kobayasi.zip   pyramid.zip    transam.zip
bgammon.zip    fist.zip       kokotoni.zip   quazatrn.zip   trantor.zip
bhead.zip      fistii.zip     kong.zip       quill.zip      tranzam.zip
bhead2.zip     flag.zip       kong2.zip      rack-it.zip    trapdoor.zip
biggles.zip    flashp.zip     kosmic.zip     radix.zip      trashman.zip
birdy.zip      flashpnt.zip   krakatoa.zip   raiders.zip    tribble.zip
blackbrd.zip   flintstn.zip   krakout.zip    rambo.zip      trivial.zip
blagger.zip    fltsim.zip     lazerzne.zip   rasputin.zip   tron.zip
blckjack.zip   football.zip   lcycle.zip     rastersc.zip   ttracer.zip
blind.zip      force.zip      leadbord.zip   rcoaster.zip   tttdoor.zip
bluemax.zip    forth.zip      lees.dit       redhawk.zip    ttwins.zip
bluethun.zip   fox.zip        lifeline.zip   redmoon.zip    tunnel.zip
bmx.zip        fp.zip         lightfor.zip   renegade.zip   turtldem.zip
boa.zip        fpcomp.zip     lmagic.zip     reversi.zip    twister.zip
bobby.zip      fpilot.zip     lode-1.zip     revolutn.zip   ugh!.zip
bobslgh.zip    fred.zip       lode-2.zip     riddlers.zip   under.zip
boggit-1.zip   freezbee.zip   lordring.zip   river.zip      underwld.zip
bombjac2.zip   frenzy.zip     lordsofm.zip   robin.zip      unihero.zip
bombjack.zip   frogger.zip    lordtime.zip   rocket.zip     uridium.zip
booty.zip      froggy.zip     lread1.zip     rocky.zip      v.zip
bored-1.zip    fruitmac.zip   lread2.zip     roodkapj.zip   valhalla.zip
bored-2.zip    full-thr.zip   lread3.zip     roomten.zip    valkyrie.zip
bored-3.zip    future.zip     lread4.zip     rratrace.zip   vampire.zip
bouncer.zip    g-force.zip    lunar.zip      rriot.zip      vectron.zip
bounder.zip    galaxian.zip   m-chess.zip    rupert.zip     velnor.zip
bounzai.zip    galvan.zip     macadam.zip    rygar.zip      veracrz1.zip
boxchamp.zip   gazeteer.zip   mailstro.zip   saboteur.zip   veracrz2.zip
brainspo.zip   gbaret.zip     makechip.zip   sabotr_2.zip   viewkill.zip
brave.zip      gd.zip         manic.zip      sabre.zip      viking.zip
bravesta.zip   geo1.zip       manic2.zip     sai.zip        virus.zip
brianaxe.zip   geo2.zip       manicmin.zip   sam-spad.zip   voicechs.zip
brucelee.zip   ghostbst.zip   manmin2.zip    sam-stoa.zip   vu3d.zip
btlships.zip   ghosts.zip     marsport.zip   samfox.zip     vu3dxmp.zip
bugaboo.zip    gilligan.zip   martha.zip     scooby.zip     vufile.zip
buggy.zip      gladiatr.zip   masterfl.zip   scrabble.zip   w-cauldr.zip
bugsy.zip      glass.zip      match.zip      scuba.zip      wally.zip
cabaldem.zip   glider-e.zip   matchday.zip   seiddab.zip    war.zip
caesar.zip     glider.zip     matchpoi.zip   sentinel.zip   warlord.zip
cars.zip       gobblema.zip   math.zip       sfcobra.zip    wartoad.zip
castdoom.zip   gordella.zip   matlucas.zip   shadowsk.zip   westbank.zip
catchy.zip     grail.zip      maxhead.zip    shawk.zip      wheelie.zip
cauldron.zip   gremlins.zip   mazegold.zip   sherlock.zip   whodunit.zip
cavelon.zip    groucho.zip    maziacs.zip    sherwood.zip   wild.zip
cclash.zip     ground.zip     mctutor0.zip   shockway.zip   wiledemo.zip
cct.zip        gryzor.zip     mctutor1.zip   short_1.zip    willow.zip
cdebris.zip    gulpman.zip    mctutor2.zip   short_2.zip    winter1.zip
centiped.zip   gun.zip        mctutor3.zip   shuttle.zip    winter2.zip
chchase.zip    gunfrite.zip   mctutor4.zip   sidewize.zip   wizard.zip
chess.zip      gunstar.zip    mdraw.zip      sirfred.zip    wthasea.zip
chimera.zip    gyron.zip      meltdown.zip   skiing.zip     xevious.zip
chuckegg.zip   gyroscop.zip   messiah.zip    skool.zip      xword.zip
chuckie.zip    hacker.zip     meteor.zip     skooldaz.zip   yahtzie.zip
chuckman.zip   hacker2.zip    mikie.zip      skyfox.zip     yie-ar-2.zip
classic.zip    hampstd.zip    million.zip    sleuth.zip     yie-ar.zip
claws.zip      happy.zip      minedout.zip   slippery.zip   zaxxan.zip
cobra.zip      harrier.zip    mininfor.zip   slord.zip      zeus.zip
combat.zip     havoc.zip      mission.zip    smudge.zip     zigzag.zip
combatsk.zip   head.zip       mndstone.zip   snakepit.zip   zip
commando.zip   headball.zip   molar.zip      snowball.zip   zipzap.zip
cookie.zip     headroom.zip   molecman.zip   snowman.zip    zolyx.zip
cpforth.zip    heartl.zip     mon.zip        soldier.zip    zolyx_f.zip
crtcmass.zip   heathrow.zip   monopoli.zip   solomon.zip    zombie.zip
crystal.zip    heavy.zip      monty.zip      sorderon.zip   zombies.zip
cyberrat.zip   hellfire.zip   mordon.zip     space7.zip     zub.zip
cyberun.zip    herbert.zip    moscow.zip     spacehrr.zip   zxforth.zip
cycle.zip      hero.zip       movie.zip      spacerac.zip   zynaps.zip
cyclone.zip    hhorace.zip    mrcopy.zip     spacezeb.zip   zythum.zip
cyrus.zip      highway.zip    mrwimpy.zip    spectres.zip   zzoom.zip
czone.zip      hijack.zip     mshadow.zip    spellbnd.zip
daktil4d.zip   hobbit.zip     mspacman.zip   spiders.zip
daley-d1.zip   horace.zip     mssion91.zip   spinads.zip
daley-d2.zip   horiza1.zip    mugsy.zip      splat.zip

  The games that don't work either use an unknown opcode,
non-emulated hardware, are faulty snaps (Scumball, probably),
require too close emulation of peripherals or fail for some other
reason.  I believe there still is at least one emulation bug,
probably in a memory store instruction.



                     The other executables

  Spconv.exe converts snapshots between various formats.  There
are two different .sp formats of which spconv handles one.
Spconv takes two arguments, eg. "spconv jsw.sp jsw.sna" or
"spconv jsw.sna .z80".  Spconv also can convert straight RAM
dumps (save "name" code 16384,49152) to .sna; I don't know 
anything about that.  Ask Henk if you want to know, his email 
address is groot@idca.tds.philips.nl.
  Specdisc reads files off Disciple/MGT/+D disks, optionally 
converting 48K SNP files to .sna files.
  JS is a small ditty to check if your joystick behaves like mine.  
It prints six numbers, minx miny x y maxx maxy, of which x and y 
are the current coordinates of the joystick and the others are the 
minimum and maximum values read.  The minima should close to 0 and 
the maxima to 2000.  In neutral position x and y should be between 
600 and 1300, preferably between 900 and 1000.  If you get maxima 
of 64000 or so, Ctrl-Break and try again, it's a bug I haven't 
cared to fix.  (I know how to, but it's too much bother.)  If your 
values are different from what I've said, tell me.



                            History

  Beta 1
  First release available via anonymous FTP.

  Beta 2
  New joystick routine which doesn't need calibration.
  New joystick autodetect, modeled after Info+ v1.50.
  LD A,R randomises the lower 7 bits of A after loading R into A.
  The two unused flag bits are preserved during RLC (IX+d).
  All jump destinations are placed on even addresses; supposed to 
be slightly faster on the 386SX.
  The border colour is read correctly from snapshots.
  JPP aborts if run on a 286 or smaller.
  "convert.exe" added.

  Beta 3
  Partial OUTI emulation added to make Starion run.  Full 
emulation would be too slow.
  "extract.exe" added.
  Backtracking added, but disabled due to strange crashes.
  "Out of memory" handled gracefully.
  IN {B,C,D,E,H,L},(C) store the result in the correct register, 
not in A.
  Switched to 16-colour mode; flicker-free and slightly faster.  
  The normal colours have been brightened slightly.
  A Kempston is always emulated, but on PCs without a joystick it 
always is in the neutral position.
  Some idiot (me) made the 386 stack pointer point to the Spectrum 
ROM a very short while.  Not any more.
  JPP now doesn't use any 386-specific instructions until it has 
checked that the processor actually is a 386.
  "specdisc.exe" added.

  Beta 4
  Changed to a different CPU test; the old one crashed on at least 
two systems.
  Reenabled VGA-present test; the old CPU test made it crash.
  Carved backtracking completely out of the code.
  Fixed another bug in IN r,(C); carry and the two unused flag 
bits are preserved.
  Fixed a bug which prevented more than 50% of the screen from 
flashing at the same time.  Speeded up the flash routine.
  Fixed a truly horrible bug.  A routine was declared near but 
called far, and so left two bytes on the stack after each 
invocation, eventually overflowing the stack.  Bad shit.
  *Really* fixed IN r,(C); the previous fix cancelled the one 
before.
  Finally wrote the exact-speed version.  No tape support yet and 
it's horrible on my machine (a 16Mhz 386SX), but it may work on 
fast enough machines.  Or again it may not.
  Fixed a bug whereby SLA (HL) rotated a random bit into bit 0.
  Fixed a bug in PJPP HALT; the clock counters weren't updated.  
Now the counters are updated and the normal speed control systems 
handles the HALTing.
  Rewrote the sound frequency control system; I stupidly made the 
sound at the correct spot in the 50Hz time slice, wasting time 
until it arrived.
  Added a hack to update the whole screen immediately whenever an 
LDIR has destination 4000h or 5800h.
  Added OUTD (partially) so International Karate will run.
  Changed startup code slightly.
  Added register and memory dump when the emulator aborts.

  1.0
  Added support for port 255 (undocumented, returns 255 during 
retrace, not 255 else).  Topgun still doesn't work.
  Increased the joystick dead zone, moved the centre slightly.
  JS.EXE added.
  F10 now exits from JPP; not absolutely all 386es have 102-key 
keyboards.
  The emulator would hang if either of the last (bottom right) two 
squares of the screen was flashing, due to a fencepost error.
  Yet another undocumented Z80 feature!  In interrupt mode 2 all 8 
bits of the supplied byte are used, not (as at least two Z80 
references state) the top 7 bits with lsb 0.  Thus the interrupt 
table has space for exactly 128 addresses.  JPP now emulates it 
correctly and Chequered Flag runs.  Locomotion crashes later than 
it did.
  Slightly changed the arithmetic/logic opcodes in the range 80 to 
C0 to avoid one branch in approx. 50% of the cases.
  Slightly changed {inc,dec} {b,c,d,e,g,h,a} to avoid one branch 
in close to 100% of the cases.
  Made the joystick presence test stricter.
  Removed the automatic screen updating which followed LDIR to 
4000h or 5800h.
  Changed the PJPP sound delay logic.  Shouldn't work better, but 
it seems to do.
  Now resets the VGA registers when the flash-colours change, to 
restore mode X properly when JPP is switched back to foreground by 
eg. DESQview.
  Added a speed indicator to PJPP (to the right of the Spectrum 
display).
  Changed the interrupt system so PJPP responds to F-keys at once.
  Fixed a speed control bug which I'm never going to admit I 
perpetrated.  I think PJPP works properly now. *blush*
  Changed the adc, add, cp, sbc and sub macros to save memory.
  Improved the handling of port 255.
  Changed the speed control constants to 3.5MHz from 4.0MHz.
  Removed the code which I intended to restore the video after DV 
fucks it up; it didn't work at all.  Use F3+Enter.
  Added 'perfect' border emulation to PJPP.  The screen may 
flicker a bit when the border is stripey, if it does your video 
card is no good.
  Added some wimpy menu stuff to the snapshot loading.  Had to put 
the main dialogue in a window to work around a library bug.
  Added tape support to read via the Soundblaster.  Probably 
doesn't work yet.
  Fixed one-character error in tape support so int 21h gets called 
with ax=3f00 rather than 003f.
  Added an extra delay to the sound output.  Some very fast 
machines wouldn't make sound without it.
  Fixed a bug in the load-snapshot routine.  It would crash with 
'divide overflow' message if it found no snapshots.
  Added 50 line feeds to the initialisation, so the cursor is left 
at the bottom of the screen.
  Renamed JPP-486 to PJPP (for Perfect JPP) and changed this doc 
accordingly.  Changed 'PJPP' in the previous sentence back to 
'JPP-486'.
  Renamed PATH.JPP to JPP.CFG.  Added my own indirection module.
  Added options in the config file to enable or disable the sound 
and to specify the ROM file name.
  Really fixed that bug in the menu code; it shouldn't divide by 0 
or deference NIL pointers now.



                              Todo
                 (don't seem to ever get done)

- Implement disk support by breakpointing the ROM save/load 
routines.
- Label the function keys along the top of the screen.
- Implement a help screen on F1 with a picture of a Spectrum 
keyboard.
- Rewrite the debugger.
- NMI on ESC.

These will _not_ get done.  Ever.  I'm done with JPP.

