RETRO-ACTIVE RETR0CHALLENGE, 2018

Evan C. Wright / December 2017 - January 2018



PROJECT: Build an Altairduino kit and write a game for it. The game has to be in assembly because that's what the cool kids use.

In looking around for a project, I found the Altairduino kit, an Arduino based replica of the famous Altair 8800. This looks do-able from the complexity standpoint. The game will be "Hunt the Wumpus", I already have a version for the ZX81 I wrote for VCF-10. In the ZX81, IX and IY are used by BASIC, meaning the programmer effectively has an 8080 register set. Still, lots of stuff will need to be changed to make it run under CP/M. While I'm at it, I'll try to port the Wumpus game to the TRS-80 model I, too. For the assembler I'll use Z80asm which is free (though I paid the shareware fee). This assembler can produce both COM files (CP/M executables) and CMD files (TRS-80 executables). If I finish, I'll keep making more CP/M games.

DELIVERABLES:

All source code will be posted in GitHub at https://github.com/evancwright/RetroChallenge2018

The project folder includes...

          
  • the (buggy) ZX81 Wumpus code which I ported.       
  • the new Wumpus game (for TRS-80 and CP/M)       
  • a hangman game (for TRS-80 and CP/M)       
  • a TRS-80 screen maker tool I ended up making when porting the Wumpus game and Hangman.       
  • FloodIt! for CP/M.

DISCLAIMER:

Yes...the Retro Challenge in April. Unfortunately, April is going to be busy. Christmas break is going to be my window. Giving myself from 12/18/17 to 1/17/18 to get this done. John is being nice and letting me start/finish early.

EDUCATIONAL GOALS:

Learn something/anything about CP/M (I know nothing)
Code something for the Intel 8080 (I've done Z80, but not 8080)
Improve my soldering skills (I love to put things together)
Figure out how to do terminal graphics

WHAT I LEARNED:

The Altairduino is a GREAT project kit...you should build one.
            Everything in the kit is well labeled
            The box, front panel and metallic label look super cool!
            The PCB is designed so that soldering is easy
            The instructions clearly tell you what to do
            The instructions clearly tell how to test and use the Altairduino
            There are easily downloaded disk images that make the Altairduino "playable" out of the box
            You can move COM files to the Altair8800 using PCGET and TeraTerm
            This kit would be AWESOME to have in any class that deals with computer history

The 8080 is NOT just a Z80 minus a few registers.
            There are differences in the instruction set, flags, and timings.
            Several common Z80 instructions (notably djnz,ldir) are not supported!
            16 bit subtraction is not supported
            Many bit manipulation functions are not supported.

CP/M is simple and elegant. Interfacing with it is not difficult

DDT, CP/M's debugger, though basic is INDISPENSIBLE.
            Arguably, I would not have been able to retro-port my code without it.

ANSI serial terminals (and emulators such a Putty) support primitive character graphics via escape codes.
            There is educational potential here for doing games on UNIX/Linux platforms using C or Python.

8 bit shift registers are a BAD way to make random numbers. Use a 16 bit shift and take the low byte.

DAILY PROGRESS LOG:

Distant past...
Ordered CP/M books (just in case I needed them someday)

Sometime in mid-December, ordered Altairduino

There are two version of this kit a bluetooth and a serial one.
I ordered the Bluetooth one so I don't have to worry about a cable.
The serial one would be cool if I had a Lear Siegler/VT 100/Wyse terminal, which I don't.
Chris Davis, (who makes the kits) says he is working on a board so a keyboard and monitor can be connected later.
Note: It later turned out you can just use a Raspberry Pi as your terminal.

12/18/17
Altairduino arrives
Labeled it "From Evan to Evan" and threw it in the pile of Christmas presents to wrap. Wife finds this amusing.

12/19/17
Located a CP/M emulator called RunCPM on GitHub. The code is in the form of a Visual Studio project.
I downloaded it and built it with Visual Studio Community Edition (which is free).
No issues encountered during the build.
Instructions for setting up RunCPM were easy to follow. Unfortunately, it has no debugger except for DDT, the debugger built into CPM

Wondering how to manage the disk images...
Turns our there is no need to create a disk image and attach the file to it. Under RunCPM, you can just copy the COM file into the B\0 folder in the emulator's folder.
If the Altairduino runs the RunCPM emulator, I'm all set...otherwise I'll need to find some disk management tools.

Entered the test program in chapter 1 (CP/M Assembly Language Programming by Ken Barber, 1983). This is just a short program the prints a '$' to the console. It printed out a $ as expected.
Created a hello world program.
Text I/O achieved!

12/20/17
Started copying wumpus code from ZX81 project to a new file. The old ZX81 code was written for TASM, which has different formatting that z80Asm.
The switching from TASM to Z80Asm means a lot of reformatting is required.
ZX81 Random number generator will not work in CP/M because it assumes there is an R register.
-> Need to copy in the one from the Text Adventure project
Also the ZX81 used a custom character set.

Finished the reformatting. When the program starts it asks the user if they want help. While the input loop is polling, it updates a counter which is used as the random number seed.

Arg! The room numbers are printing out as garbage...The ZX81 had a custom character set. Forgot to convert the characters to ASCII.
Remember that thing about text I/O working. Well....sort of. The printstr command in DBOS doesn't wrap properly. I'll have to implement a smart printstr function that inserts carriage returns (or not). After some digging it turns out there is a command which return system variables such as the width of the screen.
Arg! The atoi stuff won't work either and will have to be CP/Mized. Oh wait it will. Good thing I put lots of comments in the old code.

12/21/17
Got it asking for a room, but the it says the room entered is invalid. Looked at atoi stuff, again forgot that ZX81 is non ASCII and that I need to fix the char_to_num_function
atoi working now!

game hangs in function that generates board
turns out is was a bug in the way I was calling the random_20 function

Copied in more functions. Game is almost playable.

Fixed typo in label for room 20

Added a "play again?" prompt

Turns out the S_SYSVAR BDOS call that can be used to get the console width is for 16-bit CP/M...nuts
There is a bug where the player gets flown to an invalid room...arg

Game is generally playable though...

12/22/17

More frustration from play testing. Added a function to dump the board. Looks like some of the flags are not getting set up right.
Also something is getting corrupted when the game restarts. Probably an out of range number from the random number generator, though I can't see how.
Turns out I wasn't looping correctly in my modulus loop. I was checking for the 'm' flag when I should have be checking for the 'c' flag
Function that dumps the board looks good. It is showing the flags for the rooms are not being correctly printed during gameplay though. Example: The I "smell a wumpus message" is not being printed out.
Fixed it! Stupid bug in the print flags function.
Game seems to work now.
Tomorrow more play testing and maybe convert it to the TRS-80 model I
Oh wait...the random number generator is starting with the same seed every time. Fixed. just need to copy the counter that runs while waiting for a keypress into the random number seed.

12/23/2017

My son, Elliot, and I were play-testing and found an error in the room linkage. Fixed. Cleaned up the help text.

12/24/2017

Added scores and an itoa function. Now it keeps a running tally of wumpus wins/player wins. Cool!
Here's a screenshot of the game running in the emulator


Put code in public Github repository at http://github.com/evancwright/RetroChallenge2018
Did not want the assembler put into GitHub though since it is licensed to me. Had to learn about .gitignore file.
Still ended up pushing stuff I didn't want to.

Still wondering about hooking up a serial terminal to the (unbuilt) altair kit. Wyse terminals, VT100s are VERY expensive on eBay. Not too late to exchange blue tooth for the serial module.
Trying to make a version that runs on the Model I. This will require conditional compilation, but the Z80asm docs are not clear on this. Emailed Matthew Reed (author of z80asm) for the specific syntax.
While waiting, I read some more Altairduino documentation
Looks like it does work with disk images rather than loose COM files.
Can't locate any tools for manipulating CP/M disk images.
Tried some CP/M utilities in DOSBox. Unfortunately they all seem to r/w to real disks and not images.
Emailed Herb Johnson who has an extensive CP/M website

More digging,ctrl+z might be the CLS command

Found this link https://www.seasip.info/Cpm/cpm86esc.html

Implies CP/M was designed to accept VT-52 terminal escape codes(?)
Tried echoing a ctrl+z. It just printed a junk char to the screen.
Apparently, this char needs to be intercepted by a terminal emulator.
Might have to prompt the user if they are in CP/M or a terminal?

12/25/17
Christmas! Kids are engrossed with their new Nintendo Switch...time to unpack the Altairduino.

The kit seems really well packaged with a checklist of the contents.
The front panel is thicker than I thought...a really high quality job.
Importantly, the solder pads are fairly large, so the soldering should go smoothly.
Also, the instructions are very good...to the point that my build-blog is really just a poor-man's copy of them.


(unpacking the kit)


Arg! Ran out of solder...I am not happy. Guess I'll have go back to coding and the disk image issue until I get get to Fry's.

Herb Johnson wrote back! His reply was not super helpful. He suggests I contact whoever wrote the RunCPM emulator.

12/26/17
Off to Fry's Electronics for more solder as soon as it opens.
Warming up the car now, since it is -1F outside.

Finished soldering on the transistors.

(so far, so good)


Soldered on all the header pins and the Arduino fits.

(The directions make sure you put them on the correct side)


All the front panel switches have been installed.

(resistors,transistors, and switches soldered on)


Got all the LEDS been installed.

Pushed the Arduino onto the pins and powered it up!
Ran the tests listed in the instructions, and it worked!

Struggling to get the face plate into the holes I drilled.
This is turning out to be the be the hardest part of the kit...though mostly because of my inability to measure properly.

Back to the file-transfer problem. The Altairduino instructions have you download a Zip file of CP/M disk images. The README file says they were compiled by Mike Douglas. I emailed him asking for this thoughts on how to move my program over.

Giving up for tonight, enough progress made today.

I lied...Matthew Reed just wrote back with how to do conditional compilation in z80Asm! Now I can have one file for the game instead of 2.

Read the README file for the disk files. Email the provider to see if he knows anything about how to make CP/M disk images

12/27/17
Drilled holes in the bamboo box.

USB connection works fine. Here is a shot of the Putty connection to the Arduino.



Followed the instructions for loading Zork...

(Running Zork under CP/M)

Minor set back. Can't cannot using Bluetooth from my HP Laptop
Windows just just says "That didn't work."
Hit the reset button on the Bluetooth receiver, now Windows sees it but I still can't connect.
Ok. This is a DFU problem. I just needed to keep reading...
Also to put the Altair in Config Mode you need to flip up STOP and AUX1 at the same time otherwise the machine goes into BASIC.
Uh oh! My Config menu doesn't match the ones in the instructions.
P) Is for configure printer, not the whether serial uses USB or Bluetooth.
Need to email Chris Davis...

Got a reply from Chris in about half an hour (That was fast!). Apparently the code in the Arduino was updated and is now out of sync with the instructions.
All I need to do is enter a lowercase 's' which will take me to the menu where I have to enter P.

Set primary interface to Pin 18/19...
This happened (as foretold by the instructions)


Bluetooth works now!

Below shows Zork in a Putty window with no serial cable.

(testing Bluetooth. You need to be careful with the LEDs, since they're easily bent)

Time to do the finally assembly which is just the power wires and the metalic sticker...

Done!

(Note my sweet TRS-80 model 1 in the background)


Still need to figure out how to get my game over onto it.

Currently very pissed off/discouraged about the disk utility situation.
Everything I find is on a 30 year old page with broken links...Omniflop, I'm looking in your direction.

Also, it seems that there is no one CP/M disk format. Every computer that ran CP/M used its own.
Wait, the ZORK games are on CP/M 2.2 disks. If I can find a until for manipulating CP/M 2.2 disks, I can remove Zork and put my game on (maybe).

Got a reply from Mike Douglas! He suggests using PCGET which is on one of the images in the Zip file.
There is hope!

Did more RTFming on Altairclone.com. Trying to figure out how to get PCGETto work.
Tried it and it started waiting for an XMODEM file tranfers. Need to download Tera Term so I can send the files to the emulator. Tera Term is basically Putty, but provides support for XMODEM file transfers.

Kids are downloading 1-2-Switch on their new Nintendo Switch. This is crushing my transfer speed..(Insert gratuitous cursing)

Finally some progress. CP/M Disk 1 on the SD card has PCGET on it.
However, when I try to do the XMODEM file transfer nothing happens.

Installed Extra Putty (Putty w/ XMODEM support) and tried that instead...it didn't work either.

Found a newsgroup post explaining the file transfer process
The trick is have two connections going at once.

Cool! The file transfers over now...(Happy dance!)

...then hangs when running (more gratuitous swearing)
Used the CP/M DUMP command to at least verify the contents of the file on the CP/M disk are valid.
Packing it in for the night. Tomorrow, I'll try a short "Hello World" program.

Just so I don't forget...
   File transfer procedure:
   Connect of USB with Putty
   Flip up STOP and AUX1 at the same time (to enter setup mode).
   Enter '4' to configure SIO2 to use pin 18/19 (Bluetooth)
   Enter 'i' until SIO2 says pin 18/19 (Bluetooth)
   Enter 'x' to leave setup menu
   Flip up STOP, then RESET (to halt).
   Switch 12 and 0 up (to select disk 1).
   AUX 2 (the right one) down (to mount disk 1).
   Switch 12 down, Switch 3 up. (all but 3 down)
   AUX 1 (the left one) down (to boot disk 1).
   You should see A> in the terminal window
   On the PC, launch Terra Term.
   In the Putty window, enter "pcget [filename] b"
   
   In Tera Term, send the file using XMODEM...
   You should then see this...
   

Copied over my hello world test program to see if it works.
The test program worked, which is great, but doesn't explain why my Wumpus prog won't run.


12/28/17

More aggravation. Not only does the program halt, it takes out the disk image with it and I have to restore it with a new copy from my laptop.

Tried relocating the stack...no luck
Definitely seems like the random number generator again.

Definitely not the mod loop.

Ok,deep breath...figured it out using DDT (built-in CP/M debugger).


MAJOR FACEPALM ALERT.There are several Z80 instructions NOT supported by the 8080.
DJNZ is one of these and there are probably more.
Hunted down all djnz and replaced them with the long hand version.
Still crashing...
SLA C is apparently not a valid opcode either.
Found this by entering 't65535' into ddt to force it to run to the next crash.
I am actually learning to like DDT.

The following website is proving very useful for 8080 vs. Z80 opcodes.
Game is starting to run better on the Altairduino. Still some crashes.
The SRL (right shift) instruction in the rand subroutine is not supported...arg.
Will tackle it tomorrow using rotate and then unsetting the leftmost bit
Hopefully, wrap this up tomorrow night (famous last words)

12/29/2017
Fixed the shifts.
Ran it on the Altairduino and there are still crashes (drops out to A>).
DDT to the rescue! The l options allows you to page through the dissamebly looking for invalid opcodes (they show up as ??)
jr label apparently isn't supported either.
After combing through the code, and replacing the unsupported opcode, there is just one bug left...entering double digit rooms doesn't work.
Obviously something in the atoi function.
Pasted in the known-to-work version from another project.
Removed debug messages.
Seems to work fine now!

Declaring victory and pushing code up GitHub.
Next steps...
1) Install Putty on a Raspberry Pi so it can be the terminal server.
2) Get the game working on the TRS-80 Model I.

I'm tired...off to bed.

12/30/2017
Didn't do any of that stuff I said I was going to do...yet.
Instead, wrote Hangman for CP/M.

(Hangman running in RunCPM emulator)


12/31/2017
My Rodnay Zaks CP/M manual arrived today. It's a good guide to CP/M, but from the user perspective. No info on how to do terminal graphics.

I unforgivably did work for school today instead of retroprogramming and didn't get around to .
Plugged in the Raspberry Pi and installed Putty using
    sudo apt-get install putty
...which was easy. The slightly tricky part was figuring out which serial port it was attached to.
It showed up on my Pi as /dev/ttyACM0. I was able to figure this out by plugging in the Altairduino, and doing an 'ls' in /dev. Then, I unplugged it, did the 'ls' again and looked for the device that disappeared.
Was able to connect fine and play the Wumpus game!


(Connected to the Altairduino using a Raspberry Pi)
Now thinking about how to add pseudo graphics to TRS-80 version.

Just for fun, checked if there are any Altair 8800s on eBay. Wow! Only $10,414...what a bargain!

1/1/2018
New Year's morning. Dug up TRS-80 screen dimensions, 64x16.
Making a tool in Visual Studio to draw screens.


Trying to get the TRS-80 version to draw the pit walls.
Apparently you can't print 255 as a char...you need to poke it into memory.

Finally have the stick man falling down the pit!

Took about half an hour to get the arrow flying...

Still need to animate the bats and the teeth(a pain)
Got the death screen (teeth) working (almost).

There is a bug, translating double digit rooms to an int
Thought I fixed this. I'll hunt it down tomorrow.

1/2/2018
4:45am...can't sleep...found good listing of ANSI terminal escape sequences here, though.
Fixed the atoi issue...was passing the start of the input buffer, need to pass the addr of last char in the buffer.
Checking for upper case input now (no lower case on my TRS-80)
Randomization isn't working on the TRS-80. Now using r as the seed.
Pushed code up to GitHub.

Added the TRS-80 screen maker tool to GitHub.
Put my old ZX81 Wumpus code into GitHub as well.

1/3/2018
Back to CP/M. Going to try using the terminal escape sequences to do ASCII graphics.
Will have to prompt the player if they are on a 'real' machine or logged in via a terminal.
Starting with the arrow.

Made some progress with the escape sequences.
I don't think they'll work well with the Wumpus game, though.
The problem is that Putty can be resized to any dimension so the graphics won't look good.
Terminal graphics would work with hangman, where the game would be confined to the top left corner of the screen.

1/4/2018
Binge-watched Orville...no progress

1/5/2018
Putting in ANSI escape sequences into hangman.
This means running it on the Altair instead of RunCPM.
Game works fine on RunCPM, but crashes on the Altair. Nuts!
Ran Hangman through DDT and found another Z80 op-code that is not supported by the 8080.

     ld de,(curWordPtr)

replaced the code with the longhand version...

     ld a,(curWordPtr+1)
     ld d,a
     ld a,(curWordPtr)
     ld e,a

Note:The low-order byte has to come first because the Z80/8080 byte-swaps addresses.


(Hangman running in Putty on the Altairduino)

Cool...it works now.

Going to port hangman to the TRS-80 model 1.
Updated TRS-80 screen maker to import code it exported.
Currently adding TRS-80 support to the code.

This is going to take more work than I thought...I'll resume tomorrow.

1/6/2018
Progress on the TRS-80 version... Still need to...
     add a win graphic
     fix the fact that it is not randomized
     fix the winning letter not being drawn


(TRS-80 version)

Added code to erase the rope when the player wins.

(My son, Owen, testing the game in MAME)
1/7/2018
Last day of Winter break. Spent the day getting ready for the next semester. No progress :(
I think I've hit the end of the line here.

1/8/2018
Not giving up yet.
Today was the first day teaching after break. I set up Altair in my class, and (no joke) a student walked in and said "Wow! Is that an Altair?"
Had "Hunt the Wumpus" running on it and found some cosmetic bugs which I fixed and push to GitHub.
In class, some students have reached the "Flood it" game...going to try to write an Altair version (I still have a few days!)
Blasted out some code. Will resume coding tomorrow.

1/9/2018
Some progress on FloodIt. Got a board generated.
Now doing the usual DDT debugging to find unsupported opcodes
SBC is causing an issue

There is a bug in the Wumpus game. In some cases, if you are next to a pit, then move back to the previous room, you fall into the pit.
Need to investigate.
Ok. This wasn't hard to fix. When placing the player, I wasn't checking to see if the player's room already had a pit.
Code fixed and uploaded.

1/10/2018
One week to go. Need to get FloodIt done.
Just learned the hard way that the 8080 doesn't support 16 bit subtraction.
This can be modelled though use two's complement and 16 bit addition.
LDIR is not supported either (more cursing)
Program mow seems stuck in an endless loop near 022Bh,
which is the shift_queue function.
Debugged some more...found a bug in my "subtraction"
Now it looks like there is an error in the get_square_color function...it is returning the wrong code.
Fixed. Forgot to dereference a pointer.
Not crashing,but not working either.
Fixed the get_square_ptr subroutine
Still issues get_square_ptr seems to be working though.
Found the major (stupid) mistake in the function which clears the flags indicating whether a cell has been filled.
There is still an issue queuing data.
Will try to get to it tomorrow. Definite progress,though.
1/11/2018
Something is getting queued when it shouldn't. This is causing an endless loop.
Off to have hand surgery...seriously I am.

1/12/2018
Hand now in a cast :(
Something is getting queued when it shouldn't. This is causing and endless loop.
Figured it out with a hand trace...need to mark square when they are put in the queue,not pulled out
This allowed squares to get queued twice.
Committed and pushed code.



Made an ASCII title screen



bug in itoa8. It's not printing left-most number. Arg.

Lose screen added


Fixed the itoa8 bug. Wasn't preserving the shifted number properly in the loop.
Just need a win screen and I'm done.
That was overly optimistic...there seems to be a bug in the random number generator.

1/13/2018
Wrote a test program in C# that duplicates the 8 bit LSR.
It falls into a repeating sequence,too! Going to make it 16 bits, then take the bottom 8 for the value as suggested by this page

After fumbling around with 8 bit rotations through the carry flag, I learned that you can do a 16 bit rotate on memory using rr (hl).
Problem solved!
Code pushed to GitHub

1/14/2018
Changed the way the filling was drawn
Rather than doing a CLS and reprinting the board, the cursor is moved to each square individually using an ANSI escape sequence. This should look a lot better.

Somewhat belatedly, I found this site...
http://obsolescence.wixsite.com/obsolescence/cpm-internals
The memory map doesn't show any sort of video memory.
Wondering if CP/M computer monitors just behaved like terminals?
Wikipedia has a list of CP/M games...they are all character based.
Just realized TRS-80 Wumpus isn't in GitHub. I'll fix that tomorrow.
1/15/2018
MLK Day.
Created a README file explaining how to build the Wumpus game.
TRS80 version is crashing in setup...nuts this was working.
Fixed the dumb mistake that was causing the crash.
Figured out how to get the BASIC prompt back...
put a CR at index 0 of the input buffer (41E8h)

1/16/2018
Ran FloodIt! on the Altairduino and there are two problems... 1) rr,(hl) is not an 8080 instruction
2) The screen redrawing is spamming chars all over the place

Fixed the random number generator by doing a 16 bit shift using two 8 bit shifts.
Still need to figure out the character spamming.
There was a bug in the escape sequence...
I was missing a character and had x,y reversed...
also the x,y have to be ascii chars, not binary...
also the position is 1 based, not 0 based!
Finally done. Have the game running correctly on the Altairduino!

1/17/2018
Last day to work. Mark (coworker) suggests colorizing the letters using ANSI escape codes.
Great idea!
Wrote a test program, then integrated it into the game.

Calling it quits.

Post window developement:
2/8/2017
Fixed the bug where there screen redraws itself needlessly.
Figured out why the Game Over screen is printing garbage.
The letter on the screen is converted into a color code, however this assumes the letter is a-f.
Uppercase letters will get garbage codes!!!

Made the fix and checked in the code.


(Everything set up at CoCoFest 2018)


Evan C. Wright, 2018