Prince of Persia: the Apple II source

It’s been a good few months for the 8 bit versions of Prince of Persia. Last October saw the release of a C64 version. Yesterday the original source code for the Apple II version was uploaded to github! Read about how Jason Scott recovered that source code from 20 year old disks (similar to what I did recently!)

The game was originally written in assembler so the source code was already out there. How? Machine code is the language a machine understands and assembler is a human representation of that machine code. For example, the machine code “A9 00 8D 20 D0” is actually this more readable assembler: (that inserts the value 0 into the memory location $D020)

LDA #00
STA $D020

The assembler code released yesterday goes one step further. It uses labels, variables and comments. See BOOT.S as a good example. Variables are defined at the top and labels are used throughout making it a lot easier to deal with moving and adding code around. Look for the text “skewtbl” where you’ll find a simple loop that reads in data from memory and inserts it into 2 registers.

:0 ldy sector
 lda skewtbl,y
 sta $3d
 lda sectaddr,y
 beq :1
 sta $27
:rdsect jsr $005c
:1 dec sector
 bne :0

 lda SLOT
 jmp $900

skewtbl hex 00,0d,0b,09,07,05,03,01
 hex 0e,0c,0a,08,06,04,02,0f

sectaddr hex 00,09,00,00,00,00,00,00
 hex 30,31,32,33,34,00,00,00

Jordan Mechner puts it more poetically:

Non-programming analogy: Video game source code is a bit like the sheet music to a piano sonata that’s already been performed and recorded. One might reasonably ask: If you have the recording, what do you need the sheet music for?
You don’t, if all you want is to listen and enjoy the music. But to a pianist performing the piece, or a composer who wants to study it or arrange it for different instruments, the original score is valuable.

Props to this Slashdot post for the extra links. Also worth a look is the development diary of the C64 version and there are videos showing how the game was made back in 1985!

RIP Jack Tramiel

Jack Tramiel, the man who founded Commodore and brought Atari back from the dead died on Sunday at the age of 83. RIP.

lemon64 thread.

Here’s a great Cringley post on Jack Tramiel.

What I learned this week that I didn’t know before was that the people who worked for Tramiel really loved him. Jack Tramiel was no Steve Jobs: he was better.

The Commodore 64 was a phenomenal success. People forget that in the early 1980s the C64 outsold the Apple ][, IBM PC, and the Atari 400/800 combined. Commodore was the first to sell computers through discount retailers, opening whole new distribution channels. And don’t forget it was Jack who saw the value in Amiga, which in many ways set performance targets that took Apple years to beat. It would have been very interesting to see how the Amiga would have faired had Jack Tramiel stayed at Commodore.

I should have written more in this post yesterday but I didn’t have time. The Commodore 64 was the first computer I really obsessed about and learned loads about. Previously I had dabbled in BASIC using the Vic 20 and then a 48K Spectrum but after I got a C64 I learned how games were coded, learned quite a bit of assembler and produced and distributed my first software. That software wasn’t amazing or anything but I was always learning new things.

So, thanks Jack for creating the company that created such an amazing computer that had a huge influence on my life. When Steve Jobs died last year there were glowing blog posts about his machines. I vaguely recall an Apple II in a school lab but I hardly ever used it. The C64s in the same lab were much more interesting!

The Commodore 64 Disk Masher (C64 DMS)

DMSREADER and DMSWRITER are two parts of a Commodore 64 tool I wrote way back in 1994. I presume I got the name from the Amiga DMS tool but I really don’t know. The purpose of the tool was to create an image of 5 1/4 disks but break the image up into smaller DMS files.

Download dms64-1.0.zip.

According to the attached note, I wrote it to upload C64 demos to local BBSes but it was also used by me and the few people I still swapped C64 disks with back then. Were D64 image files around in 1994? If they were I didn’t know about them. They could only be useful to users of higher capacity disks anyway. Don’t bother trying to send a message to the email address in the note. It’s an address I had in first year in college and is long gone!

I’m posting this here because there’s no sign of this tool at all online. Some of my demos are already on CSDB but not this. It’s obviously not that useful these days when a D64 image file is only 171KB but for historical reasons it’s probably of interest. Each of the two parts are a mixture of BASIC and assembly language. By the looks of things I used some sort of illegal character trick to hide the BASIC loader but you can view it easily in CBMXfer.

DMSWRITER recreates the disk from the DMS files. It’s fairly easy to use. Enter your drive number(s) and follow the instructions. Well, almost.

Where I wrote “destination disk” in the DMSWRITER it should have been “source disk” instead. Ooops. When data is written to the destination disk the border flashes with thick multicolour bars but when it flashes quickly with a grey/blue flicker you need to change the source disk to feed it more DMS files.
I noticed that the source drive light continues to flicker after the process is over but sending a reset or loading the disk directory will sort that out. I also noticed the text of the on screen display flashes up while writing as if that data is written to disk. I need to make sure that isn’t the case or we’ll end up with corrupted disks. I never noticed any problems previously so hopefully it’s a false alarm.

DMSREADER is responsible for creating DMS files. The process is much the same, only in reverse. The source drive should contain the disk you want to make an image of and the destination will be a blank disk. You’ll have to use two destination disks unfortunately as I never got around to compressing the output files. There’s still a bug in the READER where it asks you to flip the destination disk a second time, ignore that and just hit space.
Unfortunately when I first tested the reader I received a “?SYNTAX ERROR IN 1000” error just after I was told to flip the destination disk. Fixing it was easy, replacing the following code:

1000 IF (PEEK ($DC01)AND $10)< > 0THEN GOTO 1000
1000 IF PEEK (56321)< > 239THEN 1000

When I wrote that BASIC programme I was too smart by half. To stop people looking at the code I added REM commands followed by an illegal character. Just so I could debug the programme itself I had to edit the RAM where it lived and replace that character. Look for 8F CC in the screenshot below of the Action Replay machine code monitor. I replaced CC with 34 (character “4”) to get a code listing.

The DMSWRITER BASIC loader uses 56321 which is correct, but I have to wonder why I didn’t use a BASIC command to wait for a key press rather than fooling around with low level registers. The original file has been renamed DMSREADER.ORIG.

While looking at the ASM code in the file DMSREAD I think I found a small bug in the otherwise excellent CBMXfer. The first screenshot below is from CBMXfer and you’ll notice that the BNE returns to the wrong address. I loaded an Action Replay cartridge and used the monitor in that to view the same code in Vice where the BNE address is correct. Gave me a fright to think there was such an obvious bug in my code…

Oh yes, make sure you disable any fastloaders and enable true drive emulation in Vice when using these tools.

So totally chuffed that I can use an Action Replay in Vice. I did all my development in that monitor. Yes, not easy …

DMSREADER (BASIC listing)

2 A= 53280
  IF PEEK (52769)= 216OR LO= 1THEN GOTO 4
3 LO= 1
  LOAD "DMSREAD.ASM",8,1
4 POKE A,0
  POKE A+ 1,0
  PRINT CHR$ (8)
  PRINT "{CLR}{WHITE}   DMS 64 READER BY XEER/OZONE"
  REM 4
5 INPUT "SOURCE DEVICE NUMBER(RETURN FOR 8)";Z
6 INPUT "DEST DEVICE NUMBER(RETURN FOR 8)";X
7 IF Z= 0THEN  Z= 8
8 IF X= 0THEN  X= 8
9 SYS 4096
  POKE 52739,X
10 PRINT "{CLR}"
   SYS 52992
   OPEN 15,Z,15
   OPEN 5,Z,5,"#"
20 READ A,B,C
   IF A= - 1THEN GOTO 50
25 TR= A
30 PRINT# 15,"U1";5;0;TR;D
35 SYS 53008
   PRINT "{HOME}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}TRACK     ";"{LEFT}{LEFT}{LEFT}{LEFT}";TR,"SECTOR     ";"{LEFT}{LEFT}{LEFT}{LEFT}";D
40 D= D+ 1
   IF D= CTHEN TR= TR+ 1
   D= 0
45 IF TR= (B+ 1)THEN D= 0
   GOTO 60
46 GOTO 30
50 CLOSE 5
   CLOSE 15
   END 
60 CLOSE 5
   CLOSE 15
100 IF  TR< 33 THEN  GOTO  110
101 PRINT "FLIP DEST DISK!!!"
    GOSUB 1000
110 IF  Z= XTHEN PRINT "{HOME}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}  INSERT DEST DISK AND PRESS SPACE"
    GOSUB 1000
130 POKE 52800,NAME+ 65
    SYS 52736
140 IF Z= XTHEN  PRINT  "{UP}    INSERT SOURCE DISK AND PRESS SPACE"
    GOSUB 1000
150 NA= NA+ 1
    GOTO 10
200 DATA  1,3,21,4,6,21,7,9,21,10,12,21,13,15,21,16,17,21
210 DATA  18,19,19,20,22,19,23,24,19
220 DATA  25,27,18,28,30,18
230 DATA  31,33,17,34,35,17
240 DATA  -1,-1,-1
1000 IF (PEEK (56321))< > 239THEN GOTO 1000
1010 RETURN 

DMSWRITER (BASIC listing)

7 IF PEEK (52757)= 213THEN  LO= 4
8 IF LO= 4THEN GOTO 10
9 LO= 4
  LOAD "DMSWRITE.ASM",8,1
10 POKE 53280,0
   POKE 53281,0
   PRINT "{CLR}{WHITE}DMS 64 WRITE BY XEER/OZONE"
   SYS 4096
11 INPUT "SOURCE DEVICE NUMBER(RETURN FOR 8)";Z
12 INPUT "DEST DEVICE NUMBER(RETURN FOR 8)";X
13 PRINT "INSERT SOURCE DISK AND PRESS SPACE"
   GOSUB 3000
   IF Z= 0THEN Z= 8
14 IF X= 0THEN X= 8
15 NAME= 0
   D= - 1
   POKE 52739,Z
   GOSUB 1000
   POKE 52800,NAME+ 65
   SYS 52992
16 PRINT "{CLR}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}IF THE DISK STOPS ON ONE DISK MODE,"
17 PRINT "SWAP DISKS AND PRESS SPACE!"
18 PRINT "IF THE SCREEN FLASHES THEN U MUST USE   SIDE 2 OF THE DESTINATION DISK"
20 OPEN 15,X,15
   OPEN 5,X,5,"#"
   READ A,B,C
   IF A= - 1THEN GOTO 50
25 TR= A
30 PRINT# 15,"U2";5;0;TR;D
31 PRINT# 15,"B-P";5;0
32 SYS 53008
40 D= D+ 1
   IF D= CTHEN TR= TR+ 1
   D= 0
41 IF TR= (B+ 1)THEN D= 0
   GOTO 60
46 GOTO 30
50 PRINT "FINISHED!"
   CLOSE 5
   CLOSE 15
   END 
60 CLOSE 5
   CLOSE 15
100 TR= A
    D= - 1
    Z= 8
    GOSUB 1000
110 NA= NA+ 1
    POKE 52800,NA+ 65
115 IF  PEEK (52800)= 76 THEN  GOSUB 4000
120 GOSUB 1000
    SYS 52992
140 GOTO 20
200 DATA  1,3,21,4,6,21,7,9,21,10,12,21,13,15,21,16,17,21
210 DATA  18,19,19,20,22,19,23,24,19
220 DATA  25,27,18,28,30,18
230 DATA  31,33,17,34,35,17
240 DATA  -1,-1,-1
1000 IF Z= XTHEN GOSUB 3000
1005 SYS 52736
1010 IF Z= XTHEN GOSUB 3000
1020 RETURN 
3000 IF PEEK (56321)< > 239THEN 3000
3005 RETURN 
4000 POKE 53280,PEEK (53280)+ 1
     POKE 53280,PEEK (53280)- 1
4004 IF PEEK (56321)< > 239THEN 4000
4005 RETURN

It’s not too late to archive old disks

I have a collection of around 300 Commodore 64 5 1/4 disks. They were last used around 1995 and were kept in an unheated, sometimes damp room in my family home. It’s not all bad, I kept them in proper disk boxes so the disks were mostly upright during that time and not horizontal and pressing down on each other. For a long time I wondered about transferring the disks to more permanent and modern media.

When I had an Amiga I joined it and the C64 together using some sort of serial cable and an ASM programme I painstakingly typed into my C64 from the Amiga. Then when PCs became popular I hooked my 1541-II disk drive to the parallel port of my 486 and transferred over some of my own demos but nothing else. Unfortunately with the passage of time parallel ports became as rare as the Dodo and more complicated cables are now required which discouraged me from trying to build them.

So I did a little shopping last month.

On Ebay France I found an old Commodore 1541-II disk drive in pristine condition. The Irish Ebay site was useless and I couldn’t find any local drives. I bought a Zoom Floppy from Jim Brain in the USA. That’s a USB interface you can use to connect the 1541 to a modern PC. You can use the ordinary IEC cable that came with the 1541 or a parallel port variant to “nibble copy” protected disks.

Shortly after ordering both of those I read this post saying it was too late to archive disks. The author, Jason Scott, warned that we had left it too long to move everything off old floppy disks and other magnetic media. Too much time had elapsed. The magnetic signature of the data would have degraded, the media dirty and unusable. I was worried.

Back in the day I had swapped disks with people all over Europe and further beyond. It was my first contact with people from Germany, Denmark, Poland, Belgium and elsewhere. Stuck on those disks were notes and personalised collections of demos and programmes that couldn’t be found online.

The disk drive arrived first, then a few days later the Zoom Floppy interface. Was it too late? Thankfully no.

I’ve transferred 243 disks now and I’m not finished yet. I couldn’t rescue all the disks I tried. In some the media had stuck to the outer covering. In others the magnetic media was so dirty it wasn’t readable. By the time I got to 180 double sided disks done the disk drive packed it in giving the ominous “74, DRIVE NOT READY” error. All it took was a swipe of an alcohol swab over the drive head and all was right with the world again. Then I retried one of Iain’s disks and it died again so that disk will remain uncopied! As luck would have it some of the disks that would inevitably fail were those I used often and had snippets of code, graphics or music on them! I guess less than 10% failed however which isn’t bad for 20 year old magnetic media.

After a number of failures I went searching online for disk images when I recognised directory listings. CSDB is invaluable, and the Binary Zone disks section lists all the disks they offered. I remember buying demos from there so it was great to get the disk images. I sent Kenz a PayPal donation to thank him for his efforts.

I found many interesting things, including stuff that isn’t online. Some of it I have to talk to a few people about but I found something called DMSREAD (and related utilities) for creating disk images. The nice thing about it was that it would break up the image into smaller files so you could squeeze in an extra disk at the end of a double sided disk. Very important when you had to pay postage! Nothing about the C64 version online that I can find.

Setting up the Zoom Floppy was easy. It comes with no documentation (beyond a copy of the GPL) but the xum1541 homepage has the required install files. I used CBMXfer and GUI4CBM4WIN, both frontends to the Open CBM library to read the disks.
Also read about Rob’s experiences with the Zoom Floppy. I definitely recommend it if you need to connect a Commodore drive to a modern PC!

Once I’m satisfied with my archive I’ll probably throw out the disks but can they be recycled? I presume so. I’ll miss them though. A directory listing of D64 images can’t hope to compete with the variety of disk covers and hand written labels!

This 5 years of my personal data amounted to less than 130MB of data. I’ll run through that amount of space today in half an hour of taking photos so I shudder to think how much storage I’ll need in another 20 years time. I use 1.6TB of the space on an external 2TB drive and I find that external USB drives fail every 2-3 years. I’m currently waiting on a new 2TB drive to replace two 1TB drives that died recently (they mirrored each other so no data lost, unless this 2TB drive dies. Gulp!) but I’ll probably go down the route of a gigabit network and a NAS when I can afford it. Any suggestions for a quiet NAS enclosure are more than welcome in the comments section please!

Amazing C64 and Speccy Pixel Art

Computers have always been home to amazing artwork. The C64 has so many graphics modes that artists were spoiled for choice near the end of the machine’s life. Luckily, artists are still working on the machine and releasing stuff even now!



You can find some amazing Commodore 64 artwork on c64pixels.com and it’s even sorted by graphics format like hires, FLI and others.

There’s also a comprehensive and detailed collection at CSDB of course but it does have a gallery. You’ll have to click through to each image to view it.





Here’s a wonderful ZX Spectrum gallery. The Speccy was known for attribute clash but despite this you can create really amazing work if you know what you’re doing. Check out this Binary Zone tribute to Speccy artist David Thorpe. You will recognise the loading screens!

Mastering Machine Code on your Commodore 64

Before the internet became popular and the web was still in diapers I had a Commodore 64 at home. “Mastering Machine Code on your Commodore 64” by Mark Greenshields was the first programming book I owned that wasn’t full of BASIC listings and opened my eyes to the wonders of low level assembly development. It was a daunting task learning machine code on my own but I devoured the book and learned so much by looking at the code in demos and games of the time.

The book was originally published in 1984, and I discovered it in a small bookshop next to Paul Street Shopping Centre in Cork sometime in 1990 or 1991. I still remember the excitement I felt at finding any book on the subject. The city library had books on computers, even one or two on building robots and things you could connect to a computer but nothing that explored the C64 in depth.

Based on what I learned in that book and from hacking demos with the aid of an Action Replay I was able to do quite a bit. Nothing amazing but I’m proud of what I did along with others in my demo group way back 20 years ago. I was 16 at the time. I wonder what I’d be hacking on now if I was that age?

You can find a zip file with all our demos in this post. Commodore 64 emulator required!

While flicking through the book I stumbled upon a favourite section, the one on interrupts which I’ve scanned and posted the first two pages of in this post. Here’s another doc on this subject, with the same example code flashing the border 60 times a second. Happy memories.

What was your first programming book?

Ghosts ‘n Goblins is much easier..

Games are a hell of a lot easier when they’re trained! Ghosts ‘n Goblins was one of the first games I dived into to see how it worked back in the day. Earlier I played a remix of it’s soundtrack and fired up the game afterwards. I remembered it was hard but compared to games today it’s a demon!

Luckily it was trained and my son and I had an enjoyable half hour shooting the baddies and jumping from platform to platform. I wish the compatible joysticks from back then had more than one button, left/right and up to diagonal jump is a PITA!

In case you’re wondering, a trained game is where the game has been hacked and various cheats added. Usually a fancy intro with swirling graphics and music is added at the start and the group that has hacked the game give you the option of adding infinite lives, time, invulnerability or whatever suits the games. Practically every C64 game you’ll find online has these features now. 🙂

Reverse Engineering the MOS 6502

This is the first part of a great presentation given by Michael Steil at 27C3 last year. The 6502 was the CPU used on many 8 bit computers of the eighties like the Commodore 64, Apple I and II and NES.

It’s an hour long presentation split into 6 parts, I’ve only watched the part above but it brings me back 20 years when I used to code in assembler using an Action Replay cartridge on my C64.

Check out this post for the rest of the presentation. I’ll be watching them later tonight.