--- Friday 21st of May, 2021
-------------------------------

Jim posts his weekly status update of the CSSCGC, wondering aloud if someone
will send him a machine code game for the 1K ZX80, for the Blue Challenge.
I reply to say I might try my hand at it.

--- Friday 28th of May, 2021
-------------------------------

Jim posts his next weekly update, tagging me in the post. I haven't done any
work on it since I've been busy with end-of-year exams for uni. Now that they're
done, I can get to work on the entry. I'm thinking of doing a sort of rubbishy
"Where's Wally" type game - identify the figure within the jumble of random
characters.

--- Saturday 29th of May, 2021
-------------------------------

I've decided to do an Amogus-themed game (an internet meme which is a
bastardisation of Among Us, a whodunit-style online game).

As a starting exercise, I decide to try and reduce down one of the meme images
into ZX80 form. The image in question is of a man with a manic smile, which is
typically captioned, "When the impostor is sus". I had been doing some work on
image compression using vector quantisation prior to the exam workload precluding
any serious progess on it. I was able to reuse some of the test Python scripts
I had written and adapt them to match each block of the image with its closest
match in the ZX80 character set.

The end result was much better than I had expected! You can still clearly
determine the facial features despite the drastic reduction in quality.

(see amogus.png)

--- Sunday 30th of May, 2021
-------------------------------

I send the test image to Jim, along with some text explaining that it might
be the first ever use of digitised images in a ZX80 program.

--- Monday 31st of May, 2021
-------------------------------

Trying to find ways to maintain the display file without storing it in
extra memory.

Searching the web for "ZX80 autorun program" yielded several results from
Paul Farrow's website, advertising his 4K ROM ZX80 games. He says the programs
use a technique developed by Martin Knorth to automatically start upon loading.
Unfortunately, searching Mr. Knorth's name into Google along with ZX80 just
referenced back to the Farrow website, so I resorted to reverse engineering
the 4K KONG loader to figure out the technique. It uses a certain configuration
of the system variables to trick the ROM into jumping into some part of RAM - 
this is quite restricted, as the MSB and LSB have to be identical. This is what
I've gleaned from my somewhat simple analysis.

Looked at memory map mirroring - to be honest, the rigmarole of it is too
complicated to make it ultimately worthwhile.

--- Friday 1st of October, 2021
-------------------------------

Finally getting started again with the ZX80 game. Just going to write a simple
"Simon" style game. No screen output, just audio. To make the most of the 1K,
I'm using a digitised sample in place of simple beeps. At least then it'll
still be a "world-first" for the ZX80. I need something annoying to distract
from the awful quality of the audio output - think I'll try Ricky Gervais' laugh.

Also, figured out that Paul Farrow messed up the spelling of Martin Korth's name
(hence why nothing really came up in my searches a few months ago). I only
realised when looking back now because I've been fiddling around with some
Nintendo DS programming over the summer, using his GBATEK document as a technical
reference, and so I recognised his typoed name from this devlog as soon as I
saw it again.

His Sinclair hardware reference might have some details of the autoloading
mechanism, but again, it seems quite complex, and it's not strictly necessary
this time either, since I won't have to worry about the display file getting
trampled on by BASIC, as this program won't use any screen output.

--- Saturday 2nd of October, 2021
-------------------------------

Finally getting down to coding today. Should be fairly simple to get this working -
Korth's NO$ZX document states that the .80 tape format is just a copy of the computer's
memory from $4000 to E_LINE - 1, so I should just be able to make the final tape file
from my assembler program.

Sound (well, tape) output is a bit non-standard, probably due to the limits imposed
by using a relatively small amount of TTL chips for the design. Writing to $FF turns
on the tape output bit, and reading from $FE turns it off. Still, will be easy
to write a PCM playback routine, and a beep routine for win/lose signals.

Digitised Ricky's laugh yesterday - runs for 1.3 seconds at 4000Hz, meaning it
consumes just under 700 bytes of memory. If I can fit the rest of the program in
150 bytes or so, the entire thing should fit nicely in the 1K RAM, with enough
space for a small display file so that the user can type the starting command.

***

Looks like EightyOne won't handle .80 format - luckily, Korth's spec says that the .O
format (which it can handle) is internally equivalent.

***

EightyOne doesn't seem to be able to redirect tape output to the audio device either.
Might have to try Korth's NO$ZX emulator instead.

***

Korth's emulator doesn't have sound output either, but luckily I've discovered a way to
get tbe sound going in EightyOne - redirect the tape output to the Wave Loader, and make
sure the "Loading Sounds" option is enabled. Strangely, the "Audio Out" option doesn't
work, but the Wave Loader is functionally equivalent (except for the fact that it can
record the output simultaneously).

Now that's out of the way, it's time to get cracking.

***

Just assembled a test program, and compared it against one saved from EightyOne to
make sure the system variables are all correctly set (which they are). It contains
a single line:

0 PRINT USR(0)

Ran it, and as expected, it caused the machine to reset. I think I can call that
a success. Now to try and get some machine code working.

***

Spent half an hour trying to figure out why my code wasn't making any noise. Turns out
I had a typo - I was reading & writing to port $FF, when I should have been
writing to $FF and reading from $FE. Fixed now, and I get a nice square wave beep
from my test program.

***

Using my findings from the test program, I wrote a small "beep" routine, and a short
snippet of code to test it. I tried loading it the first time and it seemed to crash
the machine. Omitting the "LOAD SP,$4400" from the top of the machine code made it
work again. I will have to investigate further.

Something odd as well - listening to my program's output in real time, it sounds like
a square wave beep. However, when listening back to the recording in the wave recorder,
it sounds more like a pin-pulse. I expect that the latter is actually the output that
would be produced by a real ZX80 with its MIC socket hooked up to a speaker/recorder,
since the MIC output is driven by the SYNC signal from the video generation circuit.
The Z80 can make the circuit output a synchronisation pulse at will with a port write,
but I think the maximal length of said pulse might be determined in the circuit logic.

Tried to see if I could mitigate this by re-triggering the vertical sync circuit
with consecutive port read/writes, but that seemed to cause EightyOne to lock up and exit
spontaneously. I guess I'll just put up with the pin-pulse sound, although now I haven't
much confidence in the quality of my digitised sample.

***

I think I figured out the issue - the stack pointer address of $4400 is stored in memory
as $00, $44 ($44 comes last since the Z80 is a little-endian CPU). The $00 is no problem,
since that maps to a zero, but the $44 is very much a problem, since it maps to an
unprintable character, and crashes the 4K ROM BASIC. Replacing it with $c400 works fine,
since $c4 is a printable character (and because there is a mirror of the computer's memory
starting at $c000. God bless Uncle Clive's tight-fistedness for providing us with
incomplete address decoding, eh?).

It reminds me now that I read Toni Baker's machine code book during my first attempt at
getting a ZX80 program going, which had a few tips for storing the bytes in a BASIC program.
I'll have a look at it again in case there's anything about unprintable characters. Up to
now, I thought the only limitation was that you couldn't have a $76 byte in your code
(since it maps to HALT, which is used by the video circuit to indicate the end of a row,
and is also cleverly reused by the 4K BASIC to indicate the end of a program line).

***

Yep, there's a big warning in the Toni Baker book about storing machine code in a REM statement
on a 4K ROM ZX80 (or OLD ROM as it is called in the book):

"OLD ROM users should ensure that line one does not appear on the automatic LISTing. You can
use the command POKE 16403,10 to remove it.

[...]

On the OLD ROM you must not even attempt to list line one or you may cause a crash."

I'll have to revise the system variables in my listing, and also rejig the listing to put
my machine code on the top line instead of the bottom.

***

I managed to fix my system variables, and now the listing starts at the correct spot. Because it
doesn't crash on unprintable characters, I've changed my code back to using $4400 for the stack
pointer, since it's more technically correct (it can be a bit dodgy to rely on a mirror if your
code is going to be run on less accurate emulators).
On to trying PCM playback now...

***

Great, my PCM playback works! Well, technically it works, but it doesn't sound much like the
original sample. At all. Still, I think it's an improvement on Ricky Gervais' real laugh.

Also, did some testing, and I determined empirically that I can just about fit my game in the RAM
as long as my .O file is under 950 bytes or so. That means I've got about 100 bytes left for 
the actual "game" part of my code. Gulp!

I should be able to cut some corners by using RND from the ROM. Otherwise, it's going to be a
tight squeeze.

***

Wrote out the entire game in one short blast of an hour or so. There was a little bug where
I forgot to set the bounds for the second invocation of the RND routine, but apart from that,
it works as desired.

I have to say that I've had a fairly enjoyable afternoon writing this game. It has certainly been
interesting trying to work within the limitations of the ZX80, and it was a lot more fun building
something simple, rather than trying to start out ludicrously complex like I did last time.

The ZX80 has the potential for some amusing little code-golf challenges which I am eager to explore,
but the main barrier to entry is the lack of information. Unlike the Spectrum, where there's a tool
for everything, the available documentation for the ZX80 hasn't progressed that far past the early
1980s. To really make the most of the computer, I suspect I would have to thoroughly investigate
the 4K ROM BASIC. Thankfully, there are already commented disassemblies availabe, which I used in
the writing of this game, to check the inputs/outputs to the RND routine. Still, I think something
more substantial is required, perhaps a summary of which ROM routines do what, and what variables
and registers they read and write.

Either way, working on this game has been an interesting learning experience. I just hope Jim
has some fun reviewing it.

- John Connolly
16:38pm, Saturday 2nd of October 2021
