Category Archives: hacks

Commodore 64 BASIC inside your USB Connector

Tomu is a super cheap Open Source Hardware 24 MHz ARM computer with 8 KB of RAM and 64 KB of ROM that fits into your USB connector! Of course I had to put Commodore 64 BASIC on it, which can be accessed through the USB-Serial port exposed by the device.

It can be found in the cbmbasic subdirectory of my fork of the tomu-quickstart project.

Update: It has been merged into the official tomu-quickstart repository!

Use a terminal emulator to connect to the virtual serial port and hack away!

Copy Protection Traps in GEOS for C64

Major GEOS applications on the Commodore 64 protect themselves from unauthorized duplication by keying themselves to the operating system's serial number. To avoid tampering with this mechanism, the system contains some elaborate traps, which will be discussed in this article.

GEOS Copy Protection

The GEOS boot disk protects itself with a complex copy protection scheme, which uses code uploaded to the disk drive to verify the authenticity of the boot disk. Berkeley Softworks, the creators of GEOS, found it necessary to also protect their applications like geoCalc and geoPublish from unauthorized duplication. Since these applications were running inside the GEOS "KERNAL" environment, which abstracted most hardware details away, these applications could not use the same kind of low-level tricks that the system was using to protect itself.

Serial Numbers for Protection

The solution was to use serial numbers. On the very first boot, the GEOS system created a 16 bit random number, the "serial number", and stored it in the KERNAL binary. (Since the system came with a "backup" boot disk, the system asked for that disk to be inserted, and stored the same serial in the backup's KERNAL.) Now whenever an application was run for the first time, it read the system's serial number and stored it in the application's binary. On subsequent runs, it read the system's serial number and compared it with the stored version. If the serial numbers didn't match, the application knew it was running on a different GEOS system than the first time – presumably as a copy on someone else's system: Since the boot disk could not be copied, two different people had to buy their own copies of GEOS, and different copies of GEOS had different serial numbers.

Serial Numbers in Practice

The code to verify the serial number usually looked something like this:

.,D5EF  20 D8 C1    JSR $C1D8 ; GetSerialNumber
.,D5F2  A5 03       LDA $03   ; read the hi byte
.,D5F4  CD 2F D8    CMP $D82F ; compare with stored version
.,D5F7  F0 03       BEQ $D5FC ; branch if equal
.,D5F9  EE 18 C2    INC $C218 ; sabotage LdDeskAcc syscall: increment vector
.,D5FC  A0 00       LDY #$00  ; ...

If the highest 8 bits of the serial don't match the value stored in the application's binary, it increments the pointer of the LdDeskAcc vector. This code was taken from the "DeskTop" file manager, which uses this subtle sabotage to make loading a "desk accessory" (a small helper program that can be run from within an application) unstable. Every time DeskTop gets loaded, the pointer gets incremented, and while LdDeskAcc might still work by coincidence the first few times (because it only skips a few instructions), it will break eventually. Other applications used different checks and sabotaged the system in different ways, but they all had in common that they called GetSerialNumber.

(DeskTop came with every GEOS system and didn't need any extra copy protection, but it checked the serial anyway to prevent users from permanantly changing their GEOS serial to match one specific pirated application.)

A Potential Generic Hack

The downside of this scheme is that all applications are protected the same way, and a single hack could potentially circumvent the protection of all applications.

A generic hack would change the system's GetSerialNumber implementation to return exactly the serial number expected by the application by reading the saved value from the application's binary. The address where the saved valus is stored is different for every application, so the hack could either analyze the instructions after the GetSerialNumber call to detect the address, or come with a small table that knows these addresses for all major applications.

GEOS supports auto-execute applications (file type $0E) that will be executed right after boot – this would be the perfect way to make this hack available at startup without patching the (encrypted) system files.

Trap 1: Preventing Changing the Vector

Such a hack would change the GetSerialNumber vector in the system call jump table to point to new code in some previously unused memory. But the GEOS KERNAL has some code to counter this:

                                ; (Y = $FF from the code before)
.,EE59  B9 98 C0    LDA $C098,Y ; read lo byte of GetSerialNumber vector
.,EE5C  18          CLC
.,EE5D  69 5A       ADC #$5A    ; add $5A
.,EE5F  99 38 C0    STA $C038,Y ; overwrite low byte GraphicsString vector

In the middle of code that deals with the menu bar and menus, it uses this obfuscated code to sabotage the GraphicsString system call if the GetSerialNumber vector was changed. If the GetSerialNumber vector is unchanged, these instructions are effectively a no-op: The lo byte of the system's GetSerialNumber vector ($F3) plus $5A equals the lo byte of the GraphicsString vector ($4D). But if the GetSerialNumber vector was changed, then GraphicsString will point to a random location and probably crash.

Berkely Softworks was cross-developing GEOS on UNIX machines with a toolchain that supported complex expressions, so they probably used code like this to express this:

    ; Y = $FF
    lda GetSerialNumber + 1 - $FF,y
    adc #<(_GraphicsString - _GetSerialNumber)
    sta GraphicsString + 1 - $FF,y

In fact, different variations of GEOS (like the GeoRAM version) were separate builds with different build time arguments, so because of different memory layouts, they were using different ADC values here.

Note that the pointers to the GetSerialNumber and GraphicsString have been obfuscated, so that an attacker that has detected the trashed GraphicsString vector won't be able to find the sabotage code by looking for the address.

Trap 2: Preventing Changing the Implementation

If the hack can't change the GetSerialNumber vector, it could put a JMP instruction at the beginning of the implementation to the new code. But the GEOS KERNAL counters this as well. The GetSerialNumber implementation looks like this:

.,CFF3  AD A7 9E    LDA $9EA7 ; load lo byte of serial
.,CFF6  85 02       STA $02   ; into return value (lo)
.,CFF8  AD A8 9E    LDA $9EA8 ; load hi byte of serial
.,CFFB  85 03       STA $03   ; into return value (hi)
.,CFFD  60          RTS       ; return

At the end of the system call function UseSystemFont, it does this:

.,E6C9  AD 2F D8    LDA $D82F ; read copy of hi byte of serial
.,E6CC  D0 06       BNE $E6D4 ; non-zero? done this before already
.,E6CE  20 F8 CF    JSR $CFF8 ; call second half of GetSerialNumber
.,E6D1  8D 2F D8    STA $D82F ; and store the hi byte in our copy
.,E6D4  60          RTS       ; ...

And in the middle of the system call function FindFTypes, it does this:

.,D5EB  A2 C1       LDX #$C1
.,D5ED  A9 96       LDA #$96  ; public GetSerialNumber vector ($C196)
.,D5EF  20 D8 C1    JSR $C1D8 ; "CallRoutine": call indirectly (obfuscation)
.,D5F2  A5 03       LDA $03   ; read hi byte of serial
.,D5F4  CD 2F D8    CMP $D82F ; compare with copy
.,D5F7  F0 03       BEQ $D5FC ; if identical, skip next instruction
.,D5F9  EE 18 C2    INC $C218 ; sabotage LdDeskAcc by incrementing its vector
.,D5FC  A0 00       LDY #$00  ; ...

So UseSystemFont makes a copy of the hi byte of the serial, and FindFTypes compares the copy with the serial – so what's the protection? The trick is that one path goes through the proper GetSerialNumber vector, while the other one calls into the bottom half of the original implementation. If the hack overwrites the first instruction of the implementation (or managed to disable the first trap and changed the system call vector directly), calling though the vector will reach the hack, while calling into the middle of the original implementation will still reach the original code. If the hack returns a different value than the original code, this will sabotage the system in a subtle way, by incrementing the LdDeskAcc system call vector.

Note that this code calls a KERNAL system function that will call GetSerialNumber indirectly, so the function pointer is split into two 8 bit loads and can't be found by just searching for the constant. Since the code in UseSystemFont doesn't call GetSerialNumber either, an attacker won't find a call to that function anywhere inside KERNAL.


I don't know whether anyone has ever created a generic serial number hack for GEOS, but it would have been a major effort – in a time before emulators allowed for memory watch points. An attacker would have needed to suspect the memory corruption, compared memory dumps before and after, and then found the two places that change code. The LdDeskAcc sabotage would have been easy to find, because it encodes the address as a constant, but the GraphicsString sabotage would have been nearly impossible to find, because the trap neither uses the verbatim GraphicsString address nor GetSerialNumber function.

Usual effective hacks were much more low-tech and instead "un-keyed" applications, i.e. removed the cached serial number from their binaries to revert them into their original, out-of-the-box state.

Wikileaks Movie “The Fifth Estate” pirated my “Xbox Hacking” Slides

Xbox hacking has made it to the silver screen, and Felix Domke and me (Michael Steil) are movie stars! …and so are at least 14 of my presentation slides!

This a picture from the Julian Assange and Wikileaks movie The Fifth Estate (2013), starring Benedict Cumberbatch and Daniel Brühl, directed by Bill Condon:

“Linux is Inevitable”? Sounds like something I would say. In fact, looks like a slide from my presentation at the 24th Chaos Communication Congress in Berlin in December 2007:

Coincidence? Let’s get some context. The scene in the movie is indeed set at the 24th Chaos Communication Congress (24C3), where Julian Assange (Cumberbatch) presents his vision about Wikileaks in the break between two talks. From the movie’s screenplay (ironically leaked by Wikileaks):

           I'm afraid the small conference
           rooms are all booked.

                 (off the schedule)
           What about the auditorium? It's
           empty 'til the X-Box Security talk.

At the 24C3, Felix Domke and me indeed presented Why Silicon-Based Security is still that hard: Deconstructing Xbox 360 Security on day 2 at 16:00 in the main auditorium. (In reality, Julian Assange did not present in the main auditorium, but in a workshop area.)

 To one side of the stage, THE NEXT SPEAKER sets up a few
 deconstructed X-BOX 360s beside a CORKBOARD covered with
 exhibits for his talk: 'Deconstructing Xbox 360 Security.'

To be clear: These are pictures from the movie, not actual pictures from the conference. They really deconstructed an Xbox 360 for the movie!

 Daniel, also on stage, watches as Julian pulls out a WAD of
 TWINE, moves to the corkboard.

 The X-Box guy looks up, CONCERNED, as Julian wraps the twine
 around a PUSH PIN holding up part of the X-Box exhibit,
 STRINGING THE TWINE to another pin holding up another part.

 Julian POINTS to the two pins and the twine. ILLUSTRATING.

           Two people and a secret. The
           beginning of any conspiracy, of all
           corruption. As it grows...

 Daniel watches, RIVETED, as Julian STRETCHES the twine to
 another pin. And another. And another...

           More people... and more secrets.

 ensnaring more of the exhibit in his web. It's MESMERIZING.

           But. If we can find one moral man,
           one whistleblower...

 Julian focuses on a PIN at the CENTER of his web of twine.

           Someone willing to expose these
           secrets --


           That man... can topple the most
           repressive of regimes.


                       X BOX GUY 
           Was zur hoelle!

           And there's the problem.

                       X BOX GUY 
           Otto, my talk is in ten minutes.

 The X-Box guy, PISSED, looks to Otto who's with a CUTE

In the movie, the “Xbox Guy” actually shouts “What the hell!” with a German accent.

I assume the person with the voltmeter is supposed to be Felix, and the angry German with the long hair (called “Game Console Hacker” in the credits, played by Christoph Franken) is supposed to be me.

On the corkboard in the movie, there are about two dozen printed slides.

This is a reconstructed version created from many individual frames of the scene:

It looks like the “Xbox Guy” is named “Denis Schnegg”, and the name of the talk is “Hacking Game Consoles”.

Most slides I could decipher are direct copies from slides from either our 24C3 talk, or our Google Tech Talk in 2008. Here are the screen captures of the slides in the movie, and the corresponding slides from our talks:

1 24c3, slide 6
2 Google, slide 6
3 24c3, slide 8
4 24c3, slide 7
5 Google, slide 24
6 Google, slide 26
7 Google, slide 28
8 Google, slide 36
9 Google, slide 8
10 Google, slide 9
11 Google, slide 15
12 Google, slide 11
13 Google, slide 14
25 24c3, slide 2

For reference, here are the full presentations the scene in the movie is based on:

Why Silicon-Based Security is still that hard: Deconstructing Xbox 360 Security (24C3)

The Xbox 360 Security System and its Weaknesses (Google TechTalk)

And since the producers of the movie consider it fair use to copy 14 of my slides without giving me credit, it must also be fair use to quote the scene of the movie here:

If you manage to decipher more slides, please post a comment.

P.S.: This dialog was cut from the movie:

           Look at them. Useless idiots,
           cracking X-Boxes, building antennae
           out of Pringles cans, probably
           spending all their free time
           reading Neuromancer and playing
           Call of Cthulhu. What a waste.

Chaosradio Express #177: Commodore 64

(This article is about a German-language podcast episode on the C64.)

Im Februar hat mich Tim Pritlove auf der Durchreise in Frankfurt abgefangen, wo ich mit einem Koffer voll mit zwölf Commodore 64 Motherboards in einem Hotelzimmer saß, und mit mir eine 2 Stunden und 42 Minuten lange Episode für Chaosradio Express aufgenommen.

Chaosradio Express #177: Commodore 64

Hier also nochmal der Hinweis auf die Folge, die jetzt schon ein paar Monate zurückliegt, für all diejenigen, die sie nicht schon anderweitig entdeckt haben. 🙂

Oops! I don't have my CashCard here.

It seems that a lot of readers of are fans of SCUMM games like Maniac Mansion (and at least one is their creator). Here is a puzzle for you (credits go to Bernhard Bauer):

In Zak McKracken, how can you get into the situation pictured below? Note that you need the CashCard in order to leave San Francisco, and Zak cannot give away his CashCard.


FM Towns:

Bonus points if you solve it by converting the SCUMM script into a graph and programmatically finding the shortest path to this state.

(Read the solution in the comments.)

Xbox Serial Number Statistics

Slashdot had a story recently on how in 1942, the allies were able to estimate the number of German taks produced based on the serial numbers of the tanks. In 2010, a German hacker is doing the exact same thing with Xboxes. This article describes the generic approach, shows some results, and provides previously unreleased raw data of 14,000 Xbox serials so you can do your own statistics!

Between October 2003 and January 2005, the Xbox Linux Project asked all visitors to their website to enter their Xbox serial numbers, date and country of manufacture, ROM version, hard disk and DVD drive brand and other properties, and gathered more than 14,000 entries. The original idea was to find a rule to deduce the hard disk and DVD drive types in an Xbox by only looking at the serial number, which was visible through the unopened packaging.

The serial sticker on an Xbox looks like this:

MFG. DATE  2002-03-03
SERIAL NO. 1166356 20903

After looking at several serial numbers, it was already clear that the last two digits (“03” in my example) are the location of manufacture: 02 is Mexico, 03 is Hungary, 05 is China and 06 is Taiwan. The three digits before (“209” in my example) are the one-digit year (“2” for “2002”) and the two-digit calender week (“09” for around the first week of March).

Now we want to find out how many devices were manufactured. A first approximation is to look at the manufacturing dates of all Xboxes in our database.

This gives us an idea when production was ramped up (in 2001 and 2002 in November, and in 2003 in August, September and October), but the statistics don’t give us absolute numbers, and they are biased towards older devices (newer devices are not entered yet, and visitors of our site tend to be early adopters).

But what about these first seven digits of the serial number? Shouldn’t these be actual “serial” numbers? Let’s look at all devices from August 2003 and sort the first seven digits by manufacturing date:

This does not look like a serial number. But all numbers are > 1,000,000, which implies that the first digit has a special meaning and is not part of the number. Let’s look at distribution of the first digit:

The first digit seems to be the number of the assembly line in the factory! So let’s look at the remaining 6 digits again:

This looks a lot better! But there are several things interleaved in this chart – because the serial numbers are of course counted independently in every factory. If we filter just all numbers form the Chinese factory, we get this:

We can see serial numbers are counted up every week, but we still see all assembly lines interleaved here, and the different lines don’t reset at the same time. Here is line 6 all by itself:

Looks almost perfect, if we assume the wild shots are caused by typos. Here is a manually fixed version of it:

Voilà! Serial numbers that count up monotonically and get reset on every Sunday.

By inspection of the graph, we can estimate that assembly line 6 of the factory in China produced about 275,000 devices per week in week 33 (mid August) of 2003. This works well, because we have so many samples; but for other weeks, we have as few as five. This is the formula for the German Tank Problem:

k is the sample size and m s the highest serial number observed.

The estimate of Xboxes produced by assembly line 6 in China in week 33 of 2003 is therefore 285,269. Applying this to every assembly line of every factory and every week, it should be easy to get great statistics on the productivity of the different lines and factories, as well as a very good estimate of the total number of devices produced. …and this is where you come in!

The Data

You want to do your own statistics? Here is the raw data:

xbox_serials.csv (2.5 MB)

It is a comma-separated-value file with the following columns:

Column Example Description Comment
1 2002-03-03 Manufacture Date YYYY-MM-DD
2 2002-04-30 Date of Purchace YYYY-MM-DD
3 de Country of Purchase two-digit code
4 1166356 20903 Serial Number nnnnnnn nnnnn
5 v1.0 Xbox Version motherboard revision
6 3944 Kernel Version ROM version as shown in “About” dialog
7 4034 Dashboard Version HD software version as shown in “About” dialog
8 Unknown/Other Flash what’s printed on flash ROM chip
9 PAL Video Standard PAL or NTSC
10 Black Case Color Xboxes are black, but there are some special editions
11 Thomson DVD Drive Philips, Samsung, Thomson
12 Seagate 10 GB Hard Disk Seagate or Western Digital
13 Conexant Video Encoder Brand Conexant, Focus, Xcalibur
14 Golden Xbox comments free-form field

Please note that people were able to fill some fields with arbitraty data, so they might not necessarily be in exactly the specified form. There are also lots of typos in the serial numbers and the month and day fields in the data fields have been mixed up sometimes. You probably want to run a script over the data first that sanitizes some of the input, e.g. removes dashes and spaces from serial numbers etc.

Here are some ideas on what you might want to find out:

  1. Is there a better formula to estimate the number of Xboxes produced per week on a certain assembly line?
  2. What day does a week start with? Does the factory produce Xboxes on Sundays? Do they produce just as many? Is it different in the respective countries?
  3. How many Xboxes were produced per assembly line, per week and per factory?
  4. Are all assembly lines in a certain factory just as productive?
  5. Are all factories just as productive (per assembly line)?
  6. Did productivity go up over time? Did it hit a maximum?
  7. How many Xboxes were produced total?
  8. Does an assembly line in a certain factory use all the same flash chips, hard drives and DVD drives in a certain week?
  9. When did an assembly line in a certan factory switch between board revisions?
  10. How long does it take an assembly line to be reconfigured for a different board revision?
  11. When did factories open/close? When did assembly lines get created and torn down in certain factories? Is there a correlation? Did assembly lines get migrated between factories? How long does this take?
  12. How long does it take on average for an Xbox from manufacuring to when it’s bought, per country? Does it change over the years?
  13. Which factories serve which countries? Did it change?
  14. How do ROM version, HD software version, motherboard version and video encoder brand correlate to each other?
  15. Which countries have PAL, which have NTSC?
  16. Where were the non-black Xboxes made?
  17. What percentage of Xboxes has a Philips, a Samsung or a Thomson DVD drive?
  18. What is the distribution of hard drive types?
  19. Some people claim they have a 20 GB hard drive. How credible is this?
  20. When and at which factories were certain DVD and HD types introduced?
  21. Over time, how did the distribution of DVD and HD types change?
  22. What is the distribution of flash chips, how did it change, and how does it correlate to factories?
  23. Is there enough data to make statements about the refurbishment process (search for “refurb” in comments)?
  24. What percentage of people misses a digit when trying to type in 12 digits?
  25. What percentage of people replaced digits of the serial number with an ‘X’ or a ‘*’? What percentage of these chose the right digits to properly anonymize their serial numbers?
  26. Any more interesting observations you can come up with?

Please share your ideas as well as your results (plus source code of your scripts, please)! If you know any statistics teachers looking for a large real-world data set and an interesting set of problems, feel free to refer them to this site! 🙂

Emu8080: an HTML5 App to Emulate a Complete CP/M Machine

by Stefan Tramm

There are a lot of web-based computer emulators out there for ancient machines – the Commodore 64 and MSX home computers or the more exotic Space Invaders arcade machines. Such emulators are nice to play with but they are incomplete – they lack an Input/Output subsystem.

Emu8080 is the first known Javascript-based emulator which adds a floppy disk system, a fast paper tape reader/writer, a line printer and a VT100 terminal emulator to the mix. Modern web browsers offer a local WebSQL database, which is used to implement block storage devices. Drag-and-Drop is used to mount a desktop file onto the virtual tape device. Together with CPU and RAM emulation, you have a complete machine inside your web browser…

Want to try out? Use Chrome6+ (or Safari5) and visit

Now you are working inside a classical machine monitor for an 8080 microcomputer from the 70’s. Available commands are:

  • m to modify memory
  • d to dump memory on the screen
  • l to disassemble a program (in Z80 Syntax)
  • g to start execution
  • <Enter> to perform a single step
  • x to show and modify CPU registers
  • h for help

So far this is pretty normal machine emulation.

The first important command is “r”. Without any parameters, it lists the available files on the server. “r file” reads an Intel HEX file into memory, for example “r basic” will load the well-known Microsoft 8K BASIC interpreter for the Intel 8080.

But as already mentioned, a disk subsystem is also available. The first step in using it is to either insert a pre-formatted disk or to format an empty disk. To insert a pre-formatted CP/M disk, issue a “r 0 cpma” command.

This command expects the image of an 8-inch IBM formatted SS/SD diskette and writes it sector-wise into the browser-local WebSQL database. This needs to be done only once, causing the disk to now be loaded into your browser as Emu8080 drive 0. With the “b” command, the boot sector is loaded into “main memory”, starting at address 0. Now issue a “g” command to start execution. Ta da!, CP/M 2.2 has been loaded and started!

To go back to the monitor, you have two choices: Ctrl-. or via the “bye” executable.

Emu8080 supports four drives, so you can either format the other drives (“F” command) or search for other images on the internet and load them yourself. But how do we mount these drives? The “dsk” commands comes to rescue. It opens a new window, showing the current status of each drive. Every disk is also a drop-area, so you can mount disk images per drag-and-drop from your desktop into the emulator. Technically the FileReader API of Javascript is used, and this API is currently (November 2010) implemented only by Chrome (or Opera). Yes, you do not need the server anymore to transport data into a Javascript application.

Now you can mount disks and boot CP/M. You can edit files with ED.COM or Wordmaster, or write programs in 8080 assembler. But how to get the modified disk images out of the emulator again? The “dsk [n]” commands opens a new window, which allows to post the binary disk image to an arbitrary web server, e.g. localhost. (btw: there is no FileWriter API in HTML5). Just change the target URL and the form will post it where ever you want.

Sometimes mounting and posting whole images is overkill, transmitting a single file into the CP/M machine or getting it out may be all you want to do. And here comes the emulated paper tape device to rescue. Just drag a file onto the terminal’s main window and it will be mounted. Inside CP/M, just use the PIP command: “pip file.txt=rdr:” and you will have the tape’s content in FILE.TXT. Please keep in mind that CP/M is not 8-bit clean.

To get a single file out of the emulator, the paper tape puncher is used. Inside CP/M just use PIP again: “pip ptp:=rew.asm” to punch the file out. Then enter the monitor again (Ctrl-. or “bye”) and use the “ptp” command, which opens a window, where you either post the tape content to an arbitrary web server or simply copy-paste the content.

The final device is a line printer. It just opens a separate window where every character is shown. No escape sequences are implemented – therefore no bold or underlined characters.

In the unlikely case that the user has no clue about CP/M and its commands, the emulator includes a PDF of the original documentation by Digital Research.

Now, lets take a short look into the technical details:

  1. WebSQL: The emulator uses the browser local SQL DB as block storage for the four disk drives. The storage is persistent and writable.
  2. Drag-and-Drop / FileReader API: The emulator uses drag-and-drop and the FileReader API to read paper tape or disc images from your local machine.
  3. HTML5 manifest: The emulator supports the browser local database and browser local file reading. To make it also runnable without an active internet connection, it is built as a HTML 5 App by providing an emu8080.manifest file. This file tells the browser which resources (HTML, JS, CSS, PNG, HEX, CPM, PDF files) must be cached. This means that if you bookmark, you can start the emulator and access the disk drives even without an internet connection — just like a local application.
  4. ShellInABox: Without the fabulous VT100 emulation of ShellInABox, this emulator would not have been possible. The provided example of a BASIC interpreter was the starting point for the 8080 emulator.
  5. z80pack: The C based implementation of a Z80 machine was the basis for the IO-subsystem implementation, the custom BIOS, and the boot disk image. The trick for reducing host CPU cycles in tight IO-Loops (eg. when CP/M is waiting for a key press) was taken from this package.
  6. js8080: The Space Invaders emulator js8080 gifted the core CPU emulation.

One last word on performance. On a usual x86 processor the emulator performs like a 2 MHz 8080. With the monitor command “instr” you can tune the performance, by increasing the number of executed 8080 instructions per Javascript timeslice. With today’s hardware, you can expect the performance of a 8 MHz CPU (which was never available as real silicon).

And for Microsoft BASIC fans, try “r basic” and “g” afterwards instead of booting CP/M – welcome to 8K BASIC. Use “SAVE” to save your programs on the paper tape 🙂 and “LOAD” to read saved programs.

Neozeed provided the Zork adventure game disk image.

And now — happy hacking.

Other links: