Having completed a reverse engineering of the Lambda 8300 ROM in the previous post.
The next step was to see if I could get that running on the Minstrel 4th.
Leaning heavily on the port of ZX81 BASIC to the Minstrel 4th, I knew quite a of lot of what would be required.
- Replace the display routines to write to the Minstrel 4th video RAM and font RAM.
- Remap the middle 8 keys on the bottom row of the keyboard.
- Replace the LOAD and SAVE routines.
Additionally for the Lambda 8300:
- Expand the range of memory to use the 48K available
- The font ROM is not part of the main ROM, so that will need to be copied separately.
- Replace the sound commands to work with the Minstrel 4th speaker.
- Extra merit for optimising the display routine.
- Unlikely to be an issue, but fix LPRINT to reference the font from ROM.
Trial Run
I am not sure I planned it to be a trial run when I started, but that was the way it worked out.
I started modifying the disassembled ROM file, in the same way I had done for the ZX81, replacing functions in place where there was space, or jumping to code in the extra 5K of ROM available on the Minstrel 4th.
When I first put it together, I had the display working, and initially the sound, but at one point, something got messed up and I couldn't work out what I had broken.
I had already learned enough to warrant starting again, with a different approach.
This time, rather than modifying functions in place, I am going to add an overlay to the ROM with the patches, most of which will point to new routines in the 5K of bonus ROM you get in the Minstrel 4th.
This is using a "feature" of the assembler I am using, TASM, you can specify multiple pieces of code for a location in memory. Just set the .ORG directive before the code, and the following code will appear at that location, even if there is already code there.
That means I can change original code such as:
And add an overlay to patch the bits I need to change.
The new code can then be as long as it needs to be, and can return back to where the original would have returned to (although the display function is not the best example as the original did start to "execute" the display file at this point c.f. how the ZX81 works).
That also means I can leave the main source code unmodified as I continue to add more comments to it.
The commented disassembly can be found on my GitHub.
1) The Display Routine
The Lambda 8300 is very similar to the ZX81, although one big change is the way the screen is stored in RAM. In the ZX81, this was a movable location, and a variable size. It could be as small as 25 bytes or as much as 793 bytes. The location was referenced by system variables at $400C/D, DFILE, and was usually located AFTER the user program.
The Lambda 8300 does this differently, and instead has a fixed size display file, in a fixed location, BEFORE the user program.
I generated various versions of the "ZX81 BASIC for Minstrel 4th" version of the display file routine, trying to optimise speed, as the faster the display routine runs, the faster SLOW mode becomes.
The routine was necessarily complicated as it had to check every character to see if it had reached the end of the variable length lines.
Here everything is fixed, so I can have a very simple routine to copy 32 bytes, skip the newline character, copy the next 32 bytes etc. And finished.
I remembered I had modified a version of the Eighty One emulator to support the Minstrel 4th bonus ROM, so I used that for a lot of the testing.
EightyOne is setup up as 48K Jupiter Ace, so is showing the default colour of the Jupiter Ace, and, as it happens, the Lambda 8300.
The Minstrel 4th is configurable, I prefer to use the ZX81 style colours as I find that easier to photograph, you can of course chose whichever suits you.
That also makes it easy to tell shots from the real hardware (black on white) and emulator (white on black).
2) Remap The Keyboard
The Minstrel 4th keyboard is wired to suit the Jupiter Ace, and as such, the bottom row is rearranged.
Logically, the keys on the bottom row are arranged as two rows of 5.
SHIFT, Symbol Shift, Z, X, C and V, B, N, M, Space
My first Jupiter Ace clone here uses an overlay sticker on a ZX81 membrane. This has to follow the logical order, so Symbol Shift appears on the left and the other keys are shifted one to the right.
Physically on the Jupiter Ace, the Symbol Shift appears on the right, and the letters are shifted to the left so they appears where they normally would on a ZX81.
SHIFT, Z, X, C, V and B, N, M, Symbol Shift, Space
The ACE ROM is arranged to expect this, so knows that C is the end of the left hand row. So when you press that, C is displayed.
The ZX81 and Lambda 8300 does not expect this, so when you press the key marked C, this is where the ZX81 expects V to be, so V appears on the screen.
The overlay code patches part of the table and replaces Z with dot, X with Z, C with X etc.
The Lambda 8300 doesn't have a Symbol Shift key, so like the ZX81, this is the dot / full stop character.
39 of the keys are basically right, but most of the symbols and all of the keywords are wrong.
This is a change to the ROM scanning code, there are situations where a program will do it's own keyboard scanning, so you end up with things like Zevious Seven where M is fire, but on the Minstrel 4th running ZX81 BASIC, you have to press N (or redefine the keys).
I have drawn out a keyboard overlay for the Lambda 8300, I am considering having this and possibly the ZX80 and ZX81 versions as optional extras with the Minstrel 4th. Anyone interested?
OK, that appears to be working, time to try loading things.
3) LOAD and SAVE routines to be replaced
The original LOAD and SAVE functions did actually work (sort of), because the new Minstrel 4th board has the ear signal wired to bits 5 (where the Ace expects it) and 7 (where the ZX81 and Lambda 8300 expect it).
You do get the signals on the border, but no countdown.
I have seen the benefit of the countdown in loading troublesome tapes, so have added it here.
I had several problems getting loading to work.
Load Problem #1
The first one was a bit intermittent, and I initially thought it might be a hardware issue.
When you typed LOAD "" it would detect break had been pressed and immediately stop.
However, I then saw the same thing on the Eighty One emulator.
This took a bit of head scratching, but I finally caught it during debugging.
This reads the input port at $FE, and masks off bits 0 and 5 only. It is mainly interested in the data on bit 5, but it also check bit 0 to see if the break key has been pressed.
Debugging, I am seeing the value of the A register as $21, indicating both bits are set. Bit 0 will be 0 if break is pressed.
That all makes sense, stepping through, until suddenly....
Hang on, how can it be $40? It is masked with $21, so it can only ever have those bits set.
Oh wait, what's that in AF', the shadow register. That's my $21 value. How did it get over there?
Hmmm.
In the display routine interrupt, there is an EX AF,AF' instruction which swaps the main Accumulator and Flags registers with the shadow AF' to allow A to be used to check the CDFLAG system variable to see if we are in FAST or SLOW mode.
Looking at the debug monitor before and after, all the other registers were reasonable, it was only A that had changed (and presumably F, but I wasn't following the flags register).
The ZX81 has balanced EX AF,AF' instructions, with one on the way in, and the reverse on the way out to keep everything in check.
The Lambda doesn't. In SLOW mode, there is a matching set, but in FAST mode, there was no EX AF,AF' on exit. The missing EX AF,AF' was in another function, which was called from various places in the code to try to keep them in check.
I decided the best option was to avoid using AF' in the display routines altogether. It had been important on the ZX81 hardware as that was the line counter it maintained between interrupts, but now I was only using it to temporarily read and test a value.
I re-arranged the routine to PUSH AF at the start. For FAST mode, there is now a matching POP AF at the exit. For SLOW mode, there was already a PUSH AF, so I effectively moved that earlier into the routine. It's not a problem that A is modified as one of the first bits of code in the function called after this will load a new value into A. (the main registers are popped back off the stack later on to return to the user code after doing the top of frame stuff, scanning the keyboard etc.)
That all worked nicely and I was back loading things again. (yes, even in the emulator)
Load Problem #2
I had seen some problems in the trial run, but I thought that was part of something I had broken with the quick hack code changes.
What was happening was the program was loading, but a line of code was appearing at the bottom of the screen, then it was getting confused.
And then I would also get confused.
I was able to get some things passed this point by deleting the line, and got some to run.
There are a few differences in the font, so there are a few odd character choices. There is now an impenetrable wall of racing cars around the edge of the swamp.
The token for "" is missing, that would normally show up as a " in a PRINT, but in the Lambda 8300, there is an * in place of that.
Another notable absence is the question mark. Seriously, they got rid of the question mark?
As if in protest, the game doesn't run after you press a key, possibly related, will look more into that after the simple stuff.
I switched to the emulator, and a simpler program. Again a line of code appears at the bottom of the screen after loading, and it's not quite working.
I could not find anything obviously wrong stepping through the code, so I ended up running two copies of the emulator, one with the new ROM and one with the original Lambda 8300 ROM, both stepping through loading the same programs.
Many lines of code are stepped through (in parallel). Much time passes ...
I finally found the issue, it wasn't actually to do with the loading. Once it is loaded, it jumps into the initialisation routine that normally runs at power on.
This does a lot of setting up system variables etc., but the bits that are relevant here is that it creates a blank display file, does some more stuff, and then does an unnecessary CLS to clear the newly created screen.
I had injected code there to detect if this was a power on reset and add the banner at the top of the screen. I jumped back in after the CLS, as the screen would have already been clear, and now had the banner at the top, so I didn't want it cleared.
What I eventually found out is that the CLS routine leaves a pointer pointing at the top of the screen.
Without CLS, that pointer is pointing at the bottom of the screen.
The LOAD routine assumes CLS has just been called and starts to populate the program, assuming it is at the top of the screen. It recalculates where line 2 should be, and so all the subsequent lines are in the right place, only the first one ends up at the bottom rather than the top.
I rearranged the code to call CLS, then write the banner, and finally jump back after CLS, and all was well again.
That's better.
OK, so LOAD is working, but I will come back to that later.
4) Extend the Memory Range
Not a difficult one, but I need an easy win occasionally.
The RAM test is set a range, a top limit point, originally $BFFF, and a base of $4000.
It fills the RAM with $02 from the top down until it hits $4000. Then it steps upwards, decrementing the value twice and making sure it ends up at $00. If it does, it is considered good and it steps upwards. It stops either when it hits the end, or when it finds an address that fails the test.
All I needed to do was change the limit from $BFFF (which minus the $4000 start point of the RAM would give 32K) to $FFFF (which would give the full 48K).
Well, I say full 48K, there is actually 49K, there is 1K from $3C00 to $3FFF, but that is not used here.
Testing that, the RAMTOP value is now $0000, which is 1 above the last good byte $FFFF.
The ZX80 and ZX81 ROMs for the Minstrel 4th were fixed at 16K, as the display file is at the end of the user code and things get complicated if that goes over the $8000 line. That isn't an issue here as the DFILE is always at the start of RAM, so will never go over the line.
I have two thoughts for the display file next version, the dedicated Minstrel 4th BASIC. The ideal option is to move it to the ACE video RAM location at $2400. That would eliminate the need to have a display routine, or any copying of blocks each frame. There are two issues there, the first that I would need to modify all the ROM code to not need to rely on the $76 newline characters at the end of the line, which might be tricky.
The second is there is no code currently to limit writes, so it may cause the PET 2001 style snowy display if you are updating the screen whilst it is being drawn.
A less risky, and potentially better solution is to move the display file into the currently unused spare 1K below $4000. This would mean the user program could start directly after the system variables, like the ZX81 and would free up almost the full 48K of RAM, although that is unlikely to be required.
5) The Lambda 8300 Font
The display work also involved adding the Lambda 8300 font ROM. This is now separate from the main ROM, sand needed to be stored separately and copied into the Minstrel 4th font RAM at boot.
The Lambda 8300 font is identical to the ZX81 with the exception of six characters, all between $08 and $0F.
I can understand the loss of the £ sign, even the 50% grey squares, but colon is quite useful, and certainly the question mark is needed. At least they kept " and $.
I have written some simple C programs I use to generate C and assembler files from binary data
I added one for the font.
You can see the new characters in all their glory in the comments.
I wondered if the new diagonals would make a nice 10 PRINT maze program.
That works quite nicely. It is not optimised for speed, I am sure it could be faster.
I use the normal ($09 and $0A) and inverted ($89 and $8A) versions to create alternating space that seemed to create an Escheresque 3D space.
I have been leaving that running on the real hardware to test stability. No problems so far.
6) Make Some Noise
The Lamdba 8300 can make sounds. So can the Minstrel 4th. However, the two use different mechanism, so the code will need to be adapted to use the new hardware.
There are 5 new sound related commands.
When you press a key, the Lambda 8300 makes a beep whose frequency is dependent on the key number. This can be turned off and on respectively with the commands NOBEEP and BEEP.
The SOUND x,y command plays a note, defined as 32500Hz/x, so 127Hz to 32.5KHz. This will last for a duration of y/65 milliseconds, so 15µs to 1 second.
That is best in fast mode as slow mode will be slower (the clue is in the name....). There it will be interrupted 50 times a second for the display routine.
The MUSIC "s" command takes a string s made up of note and duration pairs. For example "C1" plays middle C for 1 period. This is initially 100ms. "C1D2E3" would play C for 100ms, D for 200ms, E for 300ms.
The "black notes" are entered using inverse characters, this is C, C#, D, D#, E, each for 100ms.
Which makes more sense in the ZX81 colour scheme.
(N.B. don't get the Music Format wrong, you don't want to see what it calls you in the error message)
The TEMPO x command can be used to adjust the period of notes in the MUSIC command to x times 3.94ms. The default is 25, giving approximately 100ms.
The Minstrel 4th uses the Jupiter Ace style sounder (now with a volume control).
This is toggled on by WRITEs to port $FE (which also set the save data) and toggled off by READs to port $FE, which is the keyboard and tape data. This is useful because it will mean the speaker will never get left on as the keyboard scan should run every frame and it will read port $FE and turn off the speaker.
The Lambda 8300 appears to have a flip-flop which toggles the speaker on and off with READs of port $F5 (a port not used on the ZX81).
This loops around counting down the duration until it gets to zero, then returns.
It also counts down the note. Every time that gets to zero, it toggles the speaker.
I tried a few ways around, but ended up replacing this with a function with two loops.
The first loop starts counting down the duration until that hits zero or the note does. When the note hits zero, it turns the speaker off and jumps into a second loop.
The second loop continues counting down and will exit if duration hits zero, or when note hits zero, it will turn the speaker back on and jump back to the first loop.
That avoids having to remember if the speaker is on or off.
I tested this with MUSIC "C<1C1C>1", which plays C one octave below middle C, middle C and C one octave higher, each for one period (100ms).
The manual expects the frequencies of these notes to be 131Hz, 262Hz and 524Hz (C3, C4 and C5)
I'll take that, looks pretty good to me.
Whilst I have that set up, I checked SAVE.
As on the Ace, SAVE also drives the speaker, there are writes to turn the output on and off, which also turn the speaker on. These are followed by reading the keyboard to check for BREAK, which turns the speaker off again. You have a volume control if you are bothered by this.
That's all looking good. I did try saving my maze program to tape and it loaded back fine.
7) Optimise Display Routine
Already did that. I used the old version for the trial run, so wrote the new minimal version for V0.2.
8) Fix LPRINT
The Sinclair ZX Printer is an incredibly minimal piece of hardware. It just writes series of dots or not dots, moves on, line feeds, carriage returns. End of story.
The rasterisation happens in the ZX81 ROM. It turns the LPRINT or LLIST outputs or screen COPY into a bitmap pattern using the font in ROM.
But the font isn't in the ROM on the Lambda 8300.
The code appears to write the character code and pixel row numbers to two IO ports and then read back a bytes which is the bitmap for that row of that character.
That may be part of a custom printer, or more likely part of the ULA.
I would need to change the code to go back to the ZX81 style of reading from ROM, just at a different address.
I was initially thinking this was not really going to be an issue as not many people are likely to be using a ZX Printer these days.
I have done this anyway, as I was almost finished changing the code when I realised that you couldn't even plug one in to the Minstrel 4th anyway as it doesn't have a ZX81 style expansion connector.
(yes, I know adapters have been made, and I had already made the changes anyway, so they can stay)
Update:
Thanks to George Beckett who pointed out that EightyOne does actually support the ZX Printer in the Jupiter Ace mode (which I am using to test the Minstrel 4th ROMs).
This triptych shows LPRINT, COPY and LLIST all working with the mods I made to the Lambda 8300 ROM to access the font in the style of the ZX81 ROM, but from a different location. Very happy with that.
Load Problem #3
Ha!, you thought I was finished. Not so fast.
Earlier on, I had tested loading things like Tut-Tut and 3D Monster Maze, and they hadn't worked, presumably due to the issues I have now fixed, so they should work?
No.
If I load Tut-Tut, I get the listing, as usual for Z88DK generated programs, just the one line.
When I run this I get
Did I load Internet Explorer by mistake?
No, it means Invalid Expression in line 2. (I didn't know there was a line 2?)
3D Monster Maze get to the "Anyone There?" and then fails as shown earlier in the post.
I was sure these loaded in the past. Looking at my previous blog post, I had both running?
I read back through the post and then it slowly dawned upon me.
That was using a different ROM.
There were two different boot screens shown in the post.
One with the solid cursor and READY at the top of the screen.
And one with the flashing K cursor, and no READY banner.
And neither of those was the one I have been working with.
Did I choose the wrong ROM?
Do I have time to go back and change the title to something more clickbaity like "Have I made a terrible mistake"?
Many Bad Subscripts and Music Format errors were shouted, before it turned into a silent scream.
OK. Let's check what ROMs I have.
I feel this should maybe have been done earlier?
0) Check ROM Versions
I went through all the various Lambda 8300 and similar ROMs I had collected, and by generating checksums found there were three versions:
A) No banner, solid cursor [Checksum $306B]
This is the one I reverse engineered, the one in the EightyOne emulator, and files named:
- lambda8300.rom
- LAM10061.BIN
B) READY banner, solid cursor [Checksum $3961]
This looks to be one I used in the 2019 blog posts. It is in EightyOne as
"lambda8300colour", also
- Lambda8300 alt (ready).rom
- Lambda 8300.rom
- Lambda 8300 2.rom
- lambda8300colour.rom
C) No banner, K cursor [Checksum $8BAD]
This one is in EightyOne as pc8300timex, also:
- pc8300timex.rom
- Power 3000.rom
- Lambda 8300 ROM modified ZX81 compatible.rom
Have I chosen the wrong ROM?
Have a made a terrible mistake?
FX: dramatic music
Well, I don't think so. The colour one is very differently arranged, but seems to work pretty much the same. There are no colour commands that I can see, so it is probably relying on you poking the colour RAM to use it. I don't think there is any reason to use this one in preference, it doesn't seem any different to use as far as I can see apart from the READY banner. It will not run 3DMM or Tut-Tut.
The other is from a different machine. The keyboard layout is ZX81 style, so would not be fitted in a Lambda 8300 with the wrong keyboard keywords and symbols etc.
It is like a ZX81 with a flashing cursor that beeps when you press keys and likely some incompatibilities. It does, however, sort of run those games.
I think if I wanted to add the keyboard beep, I would probably add that to the ZX81 BASIC for Minstrel 4th ROM, rather than using this version.
If you do want to run all most of the ZX81 games, then the ZX81 BASIC for Minstrel 4th ROM is there at the flick of a DIP switch, so I don't need this ROM to be able to do that as well.
So I think I am happy enough with the choice.
For a while there I thought I had just wasted a fortnight and I would have to start back at square one and reverse engineer a completely different ROM.
Load Problems #4
Wait. What. No. It must be finished by now. There can't be more, can there?
OK, this is not quite a problem, just something interesting I found in the Lambda ROM and expanded on.
When the ZX81 finished loading a program, it goes straight into slow mode and gives you back the cursor (or autostart if the program was saved using a SAVE command within the program).
The Lambda 8300 ROM did something different. It went into a new block of code which started looking at the newly loaded code.
First it checked the version number system variable. Normally this is $00.
I later found when saving, it changed this to $FF.
After loading, it increments this value. If it was $FF, it becomes $00 as it should be. In this case, it jumps straight to SLOW mode and you can run your Lambda 8300 program (such as this Space Invaders style program "Space Hunt" that uses the new characters).
If, however, the value was previously $00, for example, a program saved by a ZX81, it would now be $01.
This is detected and various things happen. The code is shuffled around in RAM to insert a space for the display file, various pointers are updated.
It also steps through the code, looking for certain characters and replacing them. I think this is adapting the ZX81 command tokens to the different list on the Lamdba 8300.
The result is ZX81 BASIC programs programs should run fine. No Z88DK or machine code in REM statements, pure BASIC programs only. (assuming they don't PEEK or POKE at places they shouldn't).
One program I tried was the CLCKFREQ test program I used to check the speed of ZX81 BASIC for Minstrel 4th.
Wow, that is a lot faster. The sped up ZX81 version got to something like 222%, without all the overheads of checking for collapsed display files, we're getting 360% of the ZX81 speed here.
Those replacement graphics are a bit annoying those, that should be a line of half height 50% grey bars, and the aliens (?) should be colons.
If only there were a way I could detect if this was a ZX81 program and change the font.....
...
Hang on, I can do that!
If it reads VERSN as $01 after incrementing, then this was a ZX81 program, and it will have gone through all the moving about and patching to make all the BASIC tokens correct. I think it would be perfectly fine to replace the special characters with the original ones.
I just need to run my FONT2ASM code on the ZX81 character set and cut out the relevant section.
There are 6 changes, within the space of 8 characters, so for simplicity, I just replaced all characters from $08 to $0F.
The original Lambda 8300 font will be restored when you press reset, so I don't see any problem with that.
Ah that's better.
I've dredged the swamp and had all those racing cars towed away, back to grey squares again, and the question mark is back.
I have had a look around for some other ZX81 BASIC games, this one is quite good, Reactor, suggested by Brendan Alford.
Lots of the other programs I looked at have some machine code, so unfortunately do not work.
Load Problem #5
Oh now this is getting silly.
This is not quite a LOAD problem as such, but it started with a LOAD ...
I was looking around for programs to test, and I have a little test program called PATTERNS.
This reads through the character ROM and display each character as a series of blocks.
Simple enough, a nice little test program to leave running for a stability check.
It is hard coded to the location of the font in the ZX81 ROM, $1C00, or 7680.
That's not a problem, I just need to edit the code to change that to $2800 or 10240, the new location of the font.
That's easy enough once you have mastered the new locations of the edit and arrow keys.
Hmmm, it is not accepting that. There is an error?
Ah, I see, it is assuming the AT in PATTERN is the AT, as in PRINT AT.
Hmm, that's interesting. It limits the variable choice slightly, but I can just name this P (not sure why I had one florid variable name and just letters for the rest?)
Note the names were fine in the saved program, it is only as the line is edited and parsed that the letters are searched for those matching patterns of BASIC keywords, where they are converted to tokens to be stored. It is only P R I N T when you type it in, and when you list it. In memory it is whatever the code for PRINT is (I think it might be $F5).
And that's working fine now.
A ZX81 program, running on a Minstrel 4th, running a modified Lambda 8300 ROM, using the ZX81 font to display characters from the Lambda 8300 character ROM.
Does your head hurt now? Mind does.
Source and Binaries
The source code and binary build for this and the other Minstrel 4th ROMs can be found on my github:
The main version is the one I described here, the the base Lambda8300 ROM source code, now reformatted into my usual style with lots of regular expression search and replaces). This has a patch file and several extra code files with new functions for display, load, save, sound etc.
I have also just added a version with a single source file if you prefer that (well, 1 code file, 1 font file). That has all the patches in place, and includes the redundant code which is retained to build binary identical.
That is partly to help with the next stage, where I am looking at replacing all the L_1234 and SUB_1234 with GET_CHAR and MAKE_SOUND type function names to make it easier to relocate the code. That is a lot easier when all the code is in a single file as I can do one search and replace operation each time.
This ROM is included in the new Minstrel 4ths, but you could also burn a ROM for an older Minstrel 4th or Minstrel 4D (disable boot to menu before changing the ROM), with your selection of ROM images.
What's Next?
I have quite enjoyed my little Lambda 8300 distraction, when I go back to the Forth or ZX81 BASIC I will be sad to loose the keyboard chirps. I have just about get used to SHIFT+5 for quotes, SHIFT+. for delete, SHIFT+M for edit and the SHIFT + C,V,B, and N arrow keys.
The third target for this process was the build upon this and make a dedicated Minstrel 4th BASIC ROM.
It doesn't need to be Lambda 8300 or ZX81 compatible, after all if you want either of those, there are ROMs available at the flick of a DIP switch.
There is 5K of bonus ROM in the Minstrel 4th, and I have used just over 1K, including the font ROM and all the modified code. That could be optimised, but there is still almost 4K space free to add new things.
But there are some new things I would like to add.
- IN and OUT commands, like the ZX Spectrum, to make use of RC2014 expansion cards.
- I wonder if I can use NEW 81 to act like NEW, but to set the ZX81 font?
- I wonder if there is any benefit in adding a delay to the display routine to get 100% ZX81 speed?
- Maybe with a TURBO ON/OFF command?
- George suggested DATA, READ and RESTORE
- Just out of pure laziness, I might modify LOAD to accept LOAD instead of LOAD "".
- A JOYSTICK command to read a boldfield joystick?
- A JOYKEYS command to scan joystick every frame and press keys
- JOYKEYS="QAOP " or JOYKEYS="58670" etc. to set which keys?
- Serial IO support, modified from enhanced forth ROM.
- BBC Micro style optional keyword expansion LO. for LOAD, PR. for PRINT ?
- Or possibly override the SHIFT+X which generates the next line number. Let it do that on blank lines, but if you have typed some letters and press SHIFT+X, it could complete the nearest keyword?
- If I do move the display file to the 1K system RAM below $4000, I can keep the memory map above there the same as the ZX81, which should make more ZX81 programs compatible. (but again, the ZX81 ROM is there as well if you need that).
Any other ideas?
I vaguely remember seeing a photo of a prototype ZX81 with different keywords on some keys (I think including DATA, READ and RESTORE), I wonder what else was on there? Was there ever anything on function SHIFT + V, that gap always intrigued me.
Update - Found it!
They don't have a clear photo of just the keyboard, but I was able to stretch the image out flat.
Yes, DATA, READ and RESTORE, and also DRAW and UNDRAW (which explains why there is a system variable ready to deal with that, but no actual code). But still nothing under the V key. (and no ZX Printer commands or FAST and SLOW at that point).
You can also see the ZX80 style GO TO and GO SUB rather than GOTO and GOSUB (apparently they were that short of space). SQRT became SQR. RANDOMISE has already dropped to RAND. But RET went back to RETURN in the end. The space in IN KEY$ was still there in the actual ZX81 keyboard.
Adverts
There are all sort of kits, test gear and upgrades and recreations of the ZX80, ZX81, Jupiter ACE and Commodore PET in my Tindie store.
Including the Minstrel 2, Minstrel 3 and the newly updated Minstrel 4th
EU shipping charges will have to increase from July 1st due to new rules to add a €3 charge + handling fee for every type of item in a parcel sent to the EU from here in the UK. It's unclear how that is going to work out, so if you want to avoid the extra charges, best order in the next few days (or spend over €150 where is apparently will not apply)
Patreon
If you enjoy posts like these, you can support me via Patreon, and get access to advance previews of blog posts (the next parts of this series are already on there) plus exclusive posts.
You also get progress updates on new projects and other behind the scenes updates, as well as access to my Patreon only Discord server for even more regular updates, and to discuss your own projects.