Wednesday, 30 January 2013

Day 30 : First Release

I'm finally letting the game out into the wild.  You too can have hours of fun minutes of amazement that anyone would charge for such an awful piece of software.

The game is mimiced as closely as I can figure out from the screenshots and instructions.

You can download two extra files from the links on the right.

build.zip is a zip of the whole build tree (it is about 0.6Mb in total), all the source, all the code, the whole lot, you can see at first hand how erratic a programmer I am :)

release.zip is a much smaller archive which has the emulator (which requires Java 6 or better) and the game ROM, plus a couple of text files, i.e. just the bits you need to work.

The emulator has been updated again, but I've just removed the sound emulation because the game doesn't use any sound at all, and I don't know how well it copes on other machines, so I've just removed the code.

Given the minor detail that tomorrow is the last day in January it is unlikely that you will get the option to play these games on your TV. This is probably a blessing.




Monday, 28 January 2013

Day 29 : Read the instructions.

Woke up early so done some more testing and everything seems okay, so far.

Just realised I have made a minor error which I should have spotted ages ago. In the instructions it says when you "Double" in Blackjack you take one more card from the deck and that's it.

At the moment in my version if you double you play as normal except for the bet being doubled.

The rules do make sense, otherwise you just automatically double if you have a good hand ; there's no risk involved.

This fix should be fairly trivial though, but I will have to do it later on today.

Doesn't look like I'm going to have time to get the hardware version up and running. 

Day 28 : ROM Completion Day

I have some time to work on this today. So my aim is to complete the ROM image so that the Blackjack game will actually run. I hope to release a working game at the end of today.

Update 1 : So far : fixed a bug in the assembler (duplicate labels.... must've been asleep) and completed the gameplay core. Apart from testing, I only need the code for the special bets (doubling and insurance) and bet selection / player selection / bankroll selection / game selection code, all of which is hardcoded at present.

Update 2 : All the special bets are now coded and tested briefly. Just the selectors to do now.  The ROM size is 1724 bytes, comfortably within the 2k limit. Might even have space for a title page.

Update 3 : Now code complete. Chased down a couple of bugs (not fun without a proper debugger for the RISC Machine), so not yet releasable, want to test it a bit more yet. But it is complete at 2,026 bytes, just enough to fit into a 2k ROM.

Mind you the debug time is my own fault. I was calculating the offset in ROM as $1000 whereas it was actually $1200 so all the tracking was 512 out. 

Actually I could trim quite a few bytes. There are quite a few examples of code that ends something like,

bl someroutine
ret

which I could just shortcut into 'b someroutine' but I just don't like that sort of coding.  There are quite a few subroutines which are really broken down for clarity, things like that. I'm not using the Executive sound routines at all.

However, I will uploaded the latest Executive (1.3) and Blackjack (0.91) sources if anyone wants to have a look.

Friday, 25 January 2013

Day 25,26,27 : Nothing

I have done nothing this weekend. I hope to finish the Blackjack/Executive ROM image on Monday.

Thursday, 24 January 2013

Day 24 : Not much Game Development (cont)

Not much coding done today at all (had a tooth out at the Dentists), so for a picture this post I've created a diagram showing the 'stack' that is running.

At the bottom, the JVM. On top of this, a Java Unisonic Champion Emulator in Java.

The next level up is in CP1610 Assembler Code, assembled via the Intellivision SDK, and that is an emulator for the RISC VM that runs on the emulator.

The last two levels are the Executive ROM, containing standard routines, and finally on top of that the actual game code. Both of these are written in RISC Assembler and assembled using the Java program urmasm.jar.

Tomorrow, I hope to finish the game. In beta , anyway.

Wednesday, 23 January 2013

Day 23 : Game Development (cont.)

So, a little bit more development today. You can see I now have code dealing cards and counting their best totals, BlackJack style. Player 2 has gone bust, Player 2 has 21 through sheer dumb luck :)

Baccarat is really a simpler variant with just one round of 'hits' and a different scoring system, so tweaking the code for this is pretty simple.

At present the game, bankroll, #players and bet selection code are all dummies, though this is easy enough to write, as I've already written the menuing code and that works fine.

The bottom right white square is just a note to let me know the code has completed running. I don't have a debugger for this code, other than that in the CP1610 Emulator, so old style debugging methods are in use here.

The running is still slow - which is not unreasonable as it's a fairly slow processor (CP1610) which only runs when the vertical blank is on (25% of the time), and the processor itself is running a virtual machine emulator. It's fast enough for this sort of game. It would (like Chip 8 which on a 1802 system has all the same problems) struggle a bit with Space Invaders, but then that's near impossible on this system anyway.

I suppose I could have just written it in CP1610 machine code in the first place, but I do quite like coding in this RISC VM, and if I have time to port it to Arduino, which might be a bit of a stretch in the week remaining, it will make it much easier as I only have to port the VM, not the 1610 - this also solves problems such as an Arduino having seperate code and data and a 1610 not - the VM has ROM code and small RAM data so it's a pretty good match for an MCU.

I actually have got, somewhere, an Arduino screen display that does something like 24 x 20 with a 6 bit character set which would work fine so maybe the Arduino version wouldn't take long to code up, given that I already have a 'C' core.

Tuesday, 22 January 2013

Day 22 : Blackjack/Baccarat Development

Started today on developing the actual game that is part of the System ROM.

Lots of skeleton work and basic design work and starting the coding, not done a lot really, half an hour or so on it.

I think it will work but it will have that Chip-8 sort of feel where games sort of slide on slowly rather than just appear.


Monday, 21 January 2013

Day 21 : Bug Fix time.

When developing more OS Routines for the ROM I came across a couple of bugs in the display.

Firstly - and how I didn't notice this before I don't know, in the right hand side the ASCII text was on the top half of the character area not the bottom half.

Secondly - and more embarrassingly, when I write to RAM I only write to the hardware device (via an Interface) if the address is <= 150 (i.e. display RAM or the sound byte).

However, I was testing the data so when I wrote a value of 150-255 to the display, nothing happened.

This didn't show up mainly because you don't write these values to the display normally, the values $80-$FF in display RAM all mean the same thing, a solid white block, and the hardware writes to values $97-$FF were ignored because there is no hardware there.

Anyway, I have fixed these and the emulator zip on the right has been updated.

L8R: I have added some extra functionality to the executive ROM, which has also been updated.

Sunday, 20 January 2013

Day 20 : Unisonic Executive ROM (Part 3)

Done a bit more today, finished off the printing and menu options in the Executive part of the ROM. It's a bit like the old home computers, the ROM provides a set of utility functions and also some code using them - in this case, the game itself.

I have uploaded the unfinished ROM assembler code if anyone is interested - it's on the links on the right.

It can all be made to work - download the CP1610 interpreter, assemble that with AS1600, download the exec ROM assembler, assemble that with urmasm.jar, concatenate the two binary files together, call that file code.bin then run it with gimini.jar. If you do this you get a rotating menu of the type used in Unisonic games (the options change sequentially and you push 'Yes' when you see the one you want).

I will make a more releasable one when there is something to see.

Anyway, I will review this ROM code and then once that is done, start work on the Blackjack / Baccarat game.

Saturday, 19 January 2013

Day 19 : Unisonic Executive ROM (Part 2)

Done very little today.  Tinkered with ideas and designs for the Exec. ROM.

I did rewrite the Card-Deck handling part of the executive ROM entirely, and started on the 'printf()' method - this is the base of the menuing system as well.

Hopefully the Exec ROM will be done tomorrow, more or less, and then I can actually focus on the Game part of the Exec ROM - the system comes with a built in game.

Friday, 18 January 2013

Day 18 : Unisonic Executive ROM (Part 1)

Today I have done some work on the Unisonic ROM - the utility routines.

The screen on the right shows the Card Dealing executive routine having dealt a 52 card deck.

Tomorrow I will write the display routines - the ROMs equivalent to printf() and also the menu routines.

Thursday, 17 January 2013

Day 17 : URM Interpreter complete and tested.

Yet another snowy day.

I have completed and tested the CP1610 Assembler URM Interpreter (the source code is uploaded on the side bar - I will eventually upload everything). It ended up about 300 decles (the GI version of bytes, 10 bits long) which isn't too bad.

It passed the fairly simple processor test code I wrote and some other tests written to check the system functions.

I can now get away from CP1610 mostly. It's confusing because the CP1610 and URM are backwards - the CP1610 does mvii #42,r0 to put 42 in r0 and the URM does it the more usual way around, mov r0,#42 and I keep getting them mixed up.

So, I next need to think about utility functions. There are two that spring to mind immediately ; the first one is to maintain a sorted deck of cards, and the second one a sort of 'printf' function. The sound setting probably wants to go through a function itself. The controllers are effectively virtualised by the sys operation.

Utility functions need to be thought out because the Unisonic comes in with 2k x 10 bit ROM which is always available, so it makes sense to write routines that can be reused in other cartridges.

If I ever write any. Which given this is day 17 of 31, is not that likely.

Wednesday, 16 January 2013

Day 16 : CPU Test Code runs okay

Snow day today. So the UK grinds to a complete halt :)

I've been tinkering with the completed CP1610 version of the interpreter, and it has passed the test code I wrote for the reference implementation - it tests every instruction as far as is possible.

Initial tests show a speed of about 1,000 instructions per second, which is not blazingly fast but fast enough to write some code for this system.

Annoyingly the CP1610 assembler keeps arbitrarily plonking zeros on the end of the binary file, padding it out to the nearest page, so I might have to find a work round for that.

So, next thing is to write the CP1610 for the system functions - nearest thing I have to an "operating system".

Once that is complete the CP1610 coding is more or less over except for bug fixing - the next part is to start writing game code for the URM to run on the CP1610 virtual machine.

Later on

I've written and tested the first three system functions - they scan the player 1 and player 2 keypads and generate a pseudo random number. The last three allow program data to be accessed as code (Harvard machine) and have a fixed delay.

It also produced another problem, sort of. The constant $7F. I'm using 7 bit constants sign extended in this system. so constants can only be directly coded in the range $00-$3F to $C0-$FF. All other constants can be implemented as the sum of two constants - it's a bit long winded but I don't think it is too important. The exception to this is $7F which has to be calculated I think as $3F+$3F+$01. How important this constant will be I do not know :)

Later on again

Actually not a problem. I forgot about exclusive-or $7F = $40 ^ $3F :)

Tuesday, 15 January 2013

Day 15 : Finished CP1610 Interpreter

Actually I haven't had much time today , either, but I have finished the CP1610 version of the URM Interpreter - the advantage of a RISC type machine which only has two instruction formats is that it's fairly easy to code - 100 lines of C or Java, 2-300 of Assembler.

Initial tests of the most simple instructions (mov r0,#0) suggests it executes in 26 machine instruction cycles, about 1,000 instructions per second.

The slowest (outside things like delay instructions !) would be addpl 1(r0),2(r0). This is (in C) if (lastResult >= 0) Memory[Memory[0]+1] = Memory[Memory[0]+2] with tracking of carry, sign and zero of the result.

I haven't single stepped it but on current code takes 15 more instructions to evaluate the pl condition, 10 more instructions to calculate the RHS (2(r0)) and 8 more instructions to calculate the indexed indirection on the left hand side, i.e. 33 instructions, about 450 instructions per second. Though this is an unusual case, the worst case scenario on everything.

Branch/Branch Link and their psuedo operations ret and sys are quicker because the address decoding is much simpler.

Monday, 14 January 2013

Day 14 : Started CP1610 Interpreter

Well, tbh, I haven't done a lot today, I've written a little bit of the URM Interpreter for the CP1610, and tweaked the specification slightly.

Sunday, 13 January 2013

Day 13 : Reference Implementation & Test Program

The assembler in the urmasm.zip archive (see link on right) has been updated to fix the following bugs :

  1. couldn't cope with upper case identifiers. Not quite sure how I missed this one :)
  2. outputting string data in 7 bit ASCII not 6 bit ASCII (e.g. 'A' was output as 65 rather than 1), the Gimini is a 6 bit ASCII machine.
  3. incorrectly handled hexadecimal constants beginning with A-F (e.g. $A7) . Careless :(
To be fair to me :) I only really started testing it when I started writing code in it. Yes, I know, bad practice.

I have also finished the 'C' reference implementation of the URM Virtual Machine, and the program used to test the implementation works, and it is downloadable from the links area.

'C' code is for Code::Blocks, the executables included are 64 bit Arch Linux 'cos that's my machine.

Saturday, 12 January 2013

Day 12 : Reference Implementation

Today, I 'ave been mostly .... writing the 'C' reference implementation.

This isn't an actual working emulator version - none of the system calls or the hardware will be there, it's a working emulation core.  That's about 90% done. L8R: Finished it.

Once I've done that, I'll write reference program which runs code and checks it actually works, using a system call #255 (which won't normally exist) as a sort of assert-false. This I can then run on the CP1610 based interpreter and any others to check they actually work.

The assert code will be something like this.


     mov r0,#-1    ; put $FF in R0 (e.g. system call 255, $FF)
.
. (later on - this code checks the indexed indirection and the
.  add instruction, partially)
.
     mov r14,#5    ; put +5 in r14
     mov r3,#10    ; put 10 in r3 (so r(r3+4) == r14) holds 5
     mov r1,#-5    ; load r1 with -5
     add r1,4(r3)  ; add the contents of r3+4 to r1 e.g. r14 or 5
     sysnz         ; fail if zero flag clear(+5 + -5 == 0)
     syscc         ; fail if carry clear (carry set in 8 bit)
     sysmi         ; fail if sign flag set (result is zero)

Just for clarity the 4(r3) notation means take the contents of r3 (e.g. 10), add 4 to them, making 14 and use that register. It's a long winded way of pointing to r14 (add r1,r14 would do the same thing)

The failure works as follows

     mov r0,#-1    ; puts -1 (e.g. 255 in 8 bit) into R0
     xor r1,r1     ; clear r1 - xor updates S and Z flags
     sysnz         ; that will clear Z so this condition will 
                   ; succeed causing the system function 255 to
                   ; be called which will report a failure

Friday, 11 January 2013

Day 11 : Errrrr....

I've actually done nothing today. Except install Code::Blocks. Which involves pacman -S codeblocks ......

Ah well :)

Thursday, 10 January 2013

Day 10 : Assembler available

So, today I've finished the assembler without managing to irritate Stalin.

It's now available from here www.robsons.org.uk/Gimini/urmasm.zip It isn't much use yet because there isn't anything to run this code on, but to run it you run java -jar urmasm.jar demo.asm data.asm which assembles those two source files producing a binary file code.bin which is layout compatible with the CP1610 and code.lst which is a disassembled version of that binary code.

Basic, but it appears to work.

Next up - a reference implementation in 'C' , which will, conveniently, work in an Arduino, and following that a processor verification program in URM Assembler so any implementation can be tested.

Wednesday, 9 January 2013

Day 9 : Writing an Assembler

I've now got the guts of a simple assembler working. Just need to tidy up and wrap the worker classes so the assembler is in a fairly easy to use form.

Release tomorrow. Probably.

Tuesday, 8 January 2013

Day 8 : Virtual Machine Design

I always quite fancied the idea of having a Virtual Machine in here, a bit like the old Chip 8.  I do like the CP1610 and it's fun to code for, but the defects described elsewhere in respect to the RAM system spoil it really.

So I came up with this design. It's a RISC system with a 20 bit instruction word. Every instructional is conditional on simple status bits (Carry Out, Sign and Zero). It is designed for 8 bit usage without much memory - what I've done is shifted the memory map slightly so the display is now at $40 (rather than $00), so the last 64 bytes of RAM at $C0-$FF are now at $00-$3F in the virtual machine and become R0-R63, rather like on an 8048 Microcontroller. The sound byte shifts from $96 to $D6 - every address goes $40 forward.

This is of course in the RISC interpreter - I'm not cheating by changing the actual target machine - to keep me honest it has to run as if it ran on the real machine.

There are, arguably, 8 instructions. The four data instructions, add, and, xor and mov which have two operands - the left one can either be a direct register (e.g. r2) or an indirect offset (e.g. 4(r3)). The right one can either be a similar register address, or it can be a 7 bit constant which is sign extended to 8 bits (I don't have many bits to work with !)

There are 2 branch instructions, branch and branch link which are jump and subroutine call respectively, they take a 15 bit operand (every instruction is 2 decles so is on an even address) which is relative, which makes all the code relative (there is no option to do indirect jumps)

The two left are fiddles. branch link 0 , e.g. a subroutine call to the next address is used for return, and branch 0, e.g. branch to the next address is used to access some basic system functions (e.g. a random number generator). Both of these are effectively useless (you could actually have branch-link 0 in some rare cases) so are coopted to do other things.

This gives me two options for producing a hardware version. My calculations suggest a typical Arduino Uno can actually keep up with generating the video and emulating a CP1610 in real time on this machine, remarkably. Alternatively the hardware version could just dump the CP1610 and use a 'C' based RISC interpreter.

Haven't really decided yet :)

Anyway, this is the specification document (pdf)

Next task is to write an assembler for it.

Because almost every instruction is basically the same, this isn't too difficult.


Monday, 7 January 2013

Day 7 : I win another compo !

I won for my game "Base Attack" - this is it running on the left (using the same debugger framework as the Unisonic emulator).

I'm genuinely amazed. Whilst it was a fun thing to do producing a game on a rather limited platform (it's a new game for the MB Simon toy) does make the game a bit limited. (And the idea is completely bonkers anyway).

Next time I do one of these things I'll probably do it for the Microvision, or possibly the Entex Select-a-Game if I can find out how it's wired up.

http://minigamecompo.weebly.com/results.html

No prize for this one though :(

Sunday, 6 January 2013

Day 6 : First Release

Here is something you can actually download and play with. It is very dull but then again it's only a 50k download. It requires Java 6 or better. I've only run it on Linux, but the bit that might give problems (the sound generation) has been tested on a Windows platform and appears to work fine).

The download (http://www.robsons.org.uk/Gimini/gimini1.zip) contains three files - a jar file, an object file and and assembly source file of the demo program. If you run the jar file (java -jar gimini.jar) it displays the screen(s) you see above.

If you then run it (either press F11, or Run from the Debug menu) it will show the screen on the left, and play the three tones one after the other , changing about every second. If you press one of the control keys (QW for Player 1, OP for player 2) a white block will appear in the gap on the screen at the top in the middle.

Only one catch-ette - for those keys to work the Display window needs to have the focus, not the debugger window. The program will still run with the display window not having the focus, but it doesn't handle the keyboard.

PS: Creativision as the worst console ? How can something with a 6502, a TMS9918 and a 76489 be a bad machine - sure the games might not have been that great, but the potential's there.........

L8R: Tested on Windows XP/Java 7 on VirtualBox, seems to work fine.

Saturday, 5 January 2013

Day 5 : Life interferes.

Life, well Mrs R really, has got in the way of doing anything much with the code today. However, I do have a working .jar file and a CP1610 binary file which is a demo which displays characters on the screen, beeps, and responds to the keyboard.

However, it does not have the sound yet, so those demanding tweets ...... will have to wait a little while (probably till tomorrow morning).

This shows it running. There are four windows visible here on my Gnome Desktop. Top Left is the Gimini display windows. Bottom Left is the code in the editor (rubbish bodge code for testing but it works). Top right you can see the blogger window where I'm writing this post. Bottom left is the debugger.

Currently as you press the four keys a 'Y' appears where one of the four dots are. And it beeps, or will fairly soon.

Friday, 4 January 2013

Day 4 : Sticking all the bits together

As I wrote before, I do have a simple Debugger Framework that you can just plug an emulator class into.

This (on the left) is the result. It is pretty basic, but it does work. The debugger window is in three bits - the top bit is the registers R0-R7 and the flag bits, the middle bit the disassembled code and the bottom bit the memory display.

It's a bit scruffy (it's actually the first piece of Java Swing code I've ever written beyond hello world stuff .....) but it does work. You can single step, set breakpoints, all that sort of thing. The display of the emulator consists of two windows, this one and the display screen shown in a previous post.

As you can see there is no actual code loaded yet. The next thing I want to do is to write a little demo program that tests the display, the game control keys, the beeper and so on, and also tests the emulator.

I might do that tomorrow, or maybe the day after, depends (real life interfering with important things again .....) but once that is done, I'll release a first working version so people can play with it if they like.

Thursday, 3 January 2013

Day 3 : Unit testing

A processor emulation is an odd thing to try to Unit test. I've done it in the past by using a psuedo RNG to seed the machine status, and running an instruction and checking before/after statuses.

This approach has worked okay with this emulator but it's a bit thrown by the fact that the PC is a register like any other, so you can Shift it Left, or Exclusive Or it, which produces rather odd results. Some processors are just bad for this ; the 1802 has all kinds of wierd cases where X or P are the same (for example STXD with P=X effectively stops the processor because it keeps decrementing it).

To save myself going completely bonkers by coding test results for countless utterly wierd examples I've just not tested these odd border cases and it seems to have worked quite smoothly, just the odd bug fix.

The worry with these things is that you've misinterpreted the CPU docs twice, so your emulation does what it's supposed to do, but doesn't actually do what it should. For odd cases I've used the MAME/MESS CP1610 processor core as a reference.

So I left it running for a while testing a few million instructions and it seems fine. This will be enough for the code to run the virtual machine interpreter (actually I reckon it's pretty goo anyway).  It's way way too fast so I'll have to sync it to the system clock, but that's not hard.

For a bit of a change I also wrote some Java code to mimic the screen using the fonts on day 1. I've implemented it as a 19 x 12 display which is memory mapped and has each character in white with four different backgrounds (green, red, black,white). I then wrote a superclass/adaptor for it so it could be written to to mimic the wierd split screen design of the Gimini console (left half 6 x 12, right half 13 x 6) - when it writes to certain areas it updates two cells on the 19x12 display so effectively it's the same thing.
This is what it looks like - writing values 0-226 into equivalent locations 0-226 (It is just write only, I will mirror the 256 bytes of RAM for r/w access)

There's actually very little else to do to make it work. I've already got working key tracking classes and beeper classes, and a working debugger framework, so I've just really got to glue it all together.

I've also found a useable CP1610 assembler that's part of the Intellivision Development Kit, so I won't have to write my own.

Wednesday, 2 January 2013

Day 2 : CP1610 Definition File.

Waking up rather early this AM gave me the opportunity to write the 'generator' code for the processor.

This is a definition file for the processor which is run through a Python program which generates the actual code - rather than hand writing every opcode on its own.

It looks a bit like this (below). In a CP1610 each opcode is organised in groups of 8 (except for 000-007) so we can save on some cases by dividing the opcode by 8.

It is sort of code. The * is replaced by the lower 3 bits of the opcode, szWord is a 16 bit value used to track the current values of S and Z. Rather than actually setting the bits on every ALU operation we simply update this word, which works the same way. If I convert this to an Arduino or similar in 'C' these optimisations will speed things up signficantly.

000-007     if (* == 4) { jump(); } else carry = (* == 7) ? 1 : 0;    {} // Handles JUMP, SETC, CLRC

008-00F     szWord = reg[*] = (reg[*]+1) & 0xFFFF;                          {INCR R*}

010-017     szWord = reg[*] = (reg[*]-1) & 0xFFFF;                          {DECR R*}

018-01F     szWord = reg[*] = reg[*] ^ 0xFFFF;                              {COMR R*}

020-027     reg[*] = subCode(0,reg[*]);                                   {NEGR R*}

028-02F     reg[*] = addCode(reg[*],(carry != 0 ? 1 : 0));                {ADCR R*}

The whole thing is at http://www.robsons.org.uk/Gimini/cp1610.def

Tomorrow - write some unit tests.

Tuesday, 1 January 2013

A plan for Retrochallenge 2013

The working plan is something like:
  • Writing a CP1610 Emulator and testing it. I've already got a debugger/emulator library which does the shell part which I wrote for my Simon emulator, so this is just a matter of emulating the instruction set and plugging it in.
  • Extending this so it emulates the Unisonic Challenger hardware - which is almost nonexistent - the memory mapped display, the 3 tone sound and the 4 buttons.
  • Designing a virtual machine targeted at this processor and hardware (a bit like Chip 8 but completely different Harvard/RISC type processor design with a 20 bit word (the machine has 10 bit ROMs))
  • Writing an emulator for this virtual machine both for the CP1610 (to run on the first emulator) and stand alone (for actually writing working games)
  • Writing an assembler for the RISC virtual machine
  • Rewrite the OS ROM and the "pack in" game (this is the Blackjack/Baccarat game shown in the screen shots)
  • Write an emulator for the virtual machine and get it running on hardware (probably an Arduino generating composite video)
The last bit will depend on the time available.  I've already got a design for the RISC VM in my head (didn't actually start the challenge until 1/1/13 unlike some people ..... but I thought about it a fair bit)


Day 1 : Creating the Bitmap Font

Hi folks and a happy new year.

A quick task today - creating the bitmap font. This is an 8x8 64 bit font, and isn't actually documented anywhere. I know what each character is (it's a slightly modified 64 bit ASCII set) but not what they look like.

Fortunately there is a mix of screen grabs, box shots and photos from which most of the font characters can be copied.

A few I've had to guess, keeping the 'serif blocky square style' of the Gimini Font - these are V,X,Z and about half the punctuation characters, as these don't appear anywhere on the screenshots.

The screenshot shows a Java app whose sole purpose is to display the font for testing.

(The running font won't have the seperator lines for each pixel)