ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ This program is not finished. There are still bugs left ³ ³ and functionality missing. I'm grateful for ideas, bug ³ ³ reports etc. My email address is arnt@swix.ifi.unit.no. ³ ³ Please read this file before you mail me a question. ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ To use this program you need a copy of the Spectrum ROM, ³ ³ which is not included since it is copyrighted. ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ 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 flashing and special effects don't work. - 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 you might not want it. Since the emulator doesn't run at the same speed as a real Spectrum the pitch is most often wrong. (Well, one version does, if it works.) - Not the tape interface, yet. Licence agreement JPP is copyright (c) 1991-92 Arnt Gulbrandsen, except convert.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. Files convert.exe Converts snapshots between various formats. Written by Henk de Groot. extract.exe Extracts the ROM from data files. jpp.exe The main emulator. jpp-486.exe The exact-speed version, for very fast machines. jpp.txt This file. path.jpp Contains the locations of support files. 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. Usage JPP will try to interpret any command-line argument to be 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. - F12 aborts the emulator immediately. All other keys are ignored, except Ctrl-Alt-Del, which reboots the computer. PATH.JPP This file acts like the PATH statement for .SNA and .ROM files. It must be located in the current directory or along the PATH. Copying the ROM to a PC I'm not certain of the legal status of the Spectrum ROM. Three other emulators are distributed with the ROM, but one of them rumouredly had to be withdrawn because of it. I'm not risking that. There are several ways to get the ROM. A lot of people have asked me for a copy, and I've told a lot of people No. I may give you a copy, but *only* if you can prove to me that you have a working Spectrum. Do FOR n=0 TO 19: PRINT PEEK n: NEXT n and mail me the result. If you have one which doesn't work, or which is at your parents' home, or whatever, please don't ask me. You won't get the ROM and I'll feel bad because I hate to say no. The program "extract.exe" will extract the ROM from a file in which it is embedded. The FTP site terminator.cc.umich.edu has one, in /atari/emulators/spectrum.lzh. The file which contains the ROM is called specci.dat. I haven't asked the Terminator moderator about the status of the ROM, and you might not care to either, at least not before you've downloaded it :-) Alternatively, save the ROM do disk using CLEAR 49152: FOR n=0 TO 16383: POKE n+49152,PEEK n: NEXT n SAVE "ROM" CODE 49152,16384 The save syntax may be wrong for your disk drive, but you get the drift. If you have a Plus D, MGT or Disciple drive you can use Specdisc to convert the file to a Mess-DOS file. A program called 22Disk (22DSKnnn.ZIP, nnn is the version, shareware) may be able to copy the file to the hard disk, but anyway you can use a sector editor to save the entire disk to a Mess-DOS file and use Extract to extract the ROM from that file. Two good sector editors are Norton DE and Anadisk (ANADnnn.ZIP, shareware). To be able to use Anadisk the disk must have interleave 1. Turn off sector headers. If you have a serial port for your Spectrum it's easy to transfer the ROM to the PC, you probably know how to if you have one. Copying games to a PC The easiest way is to use a Plus D/Disciple/MGT disk drive to snap the game, then 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. Another PC emulator seems to be able to read Spectrum tapes via the parallel port. I've a copy of it, but the docs are in Spanish or Portuguese; I can't read either language. I'd like to hear from someone who can. Once I get a translation of the relevant docs adding tape support should be a ten-minute job. The CPU emulation My Z80 emulation code is 50-100% faster than any other Z80 emulator I've seen on the PC. 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. 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] is 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. 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 can occur only directly after CALL, JR, JP, RET, RETI, RETN and HALT instructions. - 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. It probably has to do with flag handling. 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. If you want the source, mail me. It's not completely bug-free, but I don't think it ever will be. It should be relatively painless to translate it to other CPUs, or to emulate other Z80 micros. 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. Unfortunately I don't know terribly much about the internals about the VGA chips, so some computers may misbehave when JPP attempts to switch to 320*240*16 mode. I made more or less the same changes to 320*200*16 as those which change 320*200*256 to 320*240*256. Please tell me if JPP behaves strangely on your computer. 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 (JPP-486) 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. JPP-486 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 port writes except across interrupts. For technical reasons this means that frequencies below approximately 160Hz won't come across very well. 'Not very well' indeed. There also is a limit to how high JPP-486 can go, roughly proportional to the speed of the processor, and a limit to how accurately it can match the intended frequency. 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 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 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 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 .sp and .sna format. This program is enclosed. The joystick emulation now uses an absolute-time routine which should work correctly 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! I've also changed the autodetect code, JPP now reads the stick and assumes it's there if reasonable values are returned. There may be some linguistic errors in this document. Sorry about that, but please bear in mind that English is not my first language. Other emulators I have about six other emulators, and there are several that I don't have. All, except where noted, are PD. They're not easy to get hold of, so mail me if you want any. PC: VGASPEC.EXE, originally by Alfonso Olloqui. Needs 286+VGA, runs at less that 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 is supposed to have tape support. This is the one with the Spanish/Portuguese doc file. 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. There's a Dutch emulator which I've been promised a copy of. There may be another emulator, someone on USENET mentioned one but didn't reply to my mail. I foolishly didn't save the original posting. Shareware, source available for US$25, 50% faster than JPP, runs on 286. 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. 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. 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. NB: I'm willing to copy only the stuff in the horizons and demos subdirectories. Don't bother asking for anything else. /spectrum/demos/cyber2.sna /spectrum/demos/drill-de.sna /spectrum/demos/king-dem.sna /spectrum/demos/mean-dem.sna /spectrum/demos/trant-de.sna /spectrum/dontwork/batman.sna /spectrum/dontwork/full-thr.sna /spectrum/dontwork/ghosts.sna /spectrum/dontwork/mugsy.sna /spectrum/dontwork/scumball.sna /spectrum/dontwork/sidewise.sna /spectrum/games/1942.sna /spectrum/games/3dtank.sna /spectrum/games/alchemis.sna /spectrum/games/alien8.sna /spectrum/games/android2.sna /spectrum/games/ant-atta.sna /spectrum/games/arcturus.sna /spectrum/games/arkanoid.sna /spectrum/games/ashes.sna /spectrum/games/atf.sna /spectrum/games/athena.sna /spectrum/games/aticatac.sna /spectrum/games/atrium.sna /spectrum/games/aufmonty.sna /spectrum/games/automani.sna /spectrum/games/backgamm.sna /spectrum/games/basil.sna /spectrum/games/batty.sna /spectrum/games/bombjac2.sna /spectrum/games/booty.sna /spectrum/games/bubblebo.sna /spectrum/games/cavelon.sna /spectrum/games/chuckegg.sna /spectrum/games/commando.sna /spectrum/games/cookie.sna /spectrum/games/cyber.sna /spectrum/games/cyberun.sna /spectrum/games/cyclone.sna /spectrum/games/daley-d1.sna /spectrum/games/daley-d2.sna /spectrum/games/darkside.sna /spectrum/games/darkstar.sna /spectrum/games/deathcha.sna /spectrum/games/defender.sna /spectrum/games/dictator.sna /spectrum/games/draughts.sna /spectrum/games/dustin.sna /spectrum/games/dynadan1.sna /spectrum/games/dynadan2.sna /spectrum/games/eaglenes.sna /spectrum/games/elite.sna /spectrum/games/enduro.sna /spectrum/games/exodus.sna /spectrum/games/exolon.sna /spectrum/games/fist.sna /spectrum/games/force.sna /spectrum/games/fp.sna /spectrum/games/froggy.sna /spectrum/games/g-force.sna /spectrum/games/galaxian.sna /spectrum/games/garfield.sna /spectrum/games/gauntlet.sna /spectrum/games/gunfrght.sna /spectrum/games/gyroscop.sna /spectrum/games/harrier.sna /spectrum/games/headball.sna /spectrum/games/headroom.sna /spectrum/games/heathrow.sna /spectrum/games/highway.sna /spectrum/games/hobbit.sna /spectrum/games/horace.sna /spectrum/games/ikari.sna /spectrum/games/is-chess.sna /spectrum/games/jetpac.sna /spectrum/games/jsw.sna /spectrum/games/karate.sna /spectrum/games/knightlo.sna /spectrum/games/kokotoni.sna /spectrum/games/kong.sna /spectrum/games/kosmic.sna /spectrum/games/krakout.sna /spectrum/games/lazerzne.sna /spectrum/games/lemans.sna /spectrum/games/lightfor.sna /spectrum/games/lunarjet.sna /spectrum/games/madmix.sna /spectrum/games/manicmin.sna /spectrum/games/matchpoi.sna /spectrum/games/maze.sna /spectrum/games/meteor.sna /spectrum/games/mission.sna /spectrum/games/monty-mo.sna /spectrum/games/mugsy.sna /spectrum/games/necropol.sna /spectrum/games/nifty.sna /spectrum/games/nightgun.sna /spectrum/games/orbiter.sna /spectrum/games/orbix.sna /spectrum/games/pacland.sna /spectrum/games/pacmania.sna /spectrum/games/penetrat.sna /spectrum/games/phenix.sna /spectrum/games/pioneer.sna /spectrum/games/pssst.sna /spectrum/games/rambo-3.sna /spectrum/games/ranarama.sna /spectrum/games/renegade.sna /spectrum/games/rollingt.sna /spectrum/games/sabre.sna /spectrum/games/sam-spad.sna /spectrum/games/sam-stoa.sna /spectrum/games/samfox.sna /spectrum/games/scooby.sna /spectrum/games/scrabble.sna /spectrum/games/sentinel.sna /spectrum/games/sherlock.sna /spectrum/games/sidearms.sna /spectrum/games/sirfred.sna /spectrum/games/skiing.sna /spectrum/games/spiders.sna /spectrum/games/spindizy.sna /spectrum/games/spyvsspy.sna /spectrum/games/st-berna.sna /spectrum/games/star-rai.sna /spectrum/games/starion.sna /spectrum/games/starquak.sna /spectrum/games/survivor.sna /spectrum/games/talk-che.sna /spectrum/games/tech-ted.sna /spectrum/games/tempest.sna /spectrum/games/terra.sna /spectrum/games/tetris.sna /spectrum/games/thing.sna /spectrum/games/thingbb.sna /spectrum/games/thunder.sna /spectrum/games/thunderc.sna /spectrum/games/tll.sna /spectrum/games/tomahawk.sna /spectrum/games/train-ga.sna /spectrum/games/transam.sna /spectrum/games/trantor.sna /spectrum/games/trashman.sna /spectrum/games/tron.sna /spectrum/games/uridium.sna /spectrum/games/virus.sna /spectrum/games/wally.sna /spectrum/games/warlord.sna /spectrum/games/wheelie.sna /spectrum/games/whodunit.sna /spectrum/games/xevious.sna /spectrum/games/zeus.sna /spectrum/games/zynaps.sna /spectrum/games/zzoom.sna /spectrum/horizons/bubbleso.sna /spectrum/horizons/characte.sna /spectrum/horizons/draw.sna /spectrum/horizons/evolutio.sna /spectrum/horizons/life.sna /spectrum/horizons/mon.sna /spectrum/horizons/montecar.sna /spectrum/horizons/wall.sna /spectrum/horizons/waves.sna /spectrum/test/buggy.sna /spectrum/test/cheqflag.sna /spectrum/test/editamon.sna /spectrum/test/firelord.sna /spectrum/test/flyshark.sna /spectrum/test/ground.sna /spectrum/test/imposbal.sna /spectrum/test/impossib.sna /spectrum/test/thrust2.sna The games that don't work either use an unknown opcode, (eg. Batman, DD CD), non-emulated hardware (eg. Sidewize, port 40FF), are faulty snaps (Scumball, probably), or fail for some other reason. I believe there still is at least one emulation bug, probably in a memory store instruction. 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 JPP-486 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. 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. - Add tape support to the exact-speed version. - Find out why JPP won't run after BC++ 3.0 has been run. - Fix Pause. - Find out why JPP-486 responds like a dead log to keypresses when sound is being made.