It seems that what I post here is getting some attention from those who would like to examine it, pull it apart, and see what improvements can be made. Such is the way with a more technical forum than anything likely to be found in Spectrumville. So, for your delectation, delight and hopefully not disgust, I present:
Get it here:
ALL YOUR BASE ARE BELONG TO US
This was all sparked by my recent efforts trying to get a ZX80 to do something -
anything, even - with machine code. It started with a
Hex Bin Converter, a 16K ZX81 BASIC listing that would convert between decimal, hex and binary with a two-byte limit, and do so with string and array manipulation. As I'd been looking into the Z80's bit manipulation instructions, I then wrote a really simple routine on the Spectrum to poke a value from 0 to 255 into a specific address, pick it apart bit by bit and shove those bits into other addresses where they needed to be and perform a few additions here and there, leaving two addresses which can be fed into CHR$ when PEEKed to reveal the hex equivalent, and eight further addresses all containing either 0 or 1 that can also be PEEKed without the intervention of CHR$ to reveal the binary. This was then converted to the ZX81, and simplified as there's no need to account for the letters being held in a different block of the character set from the numbers - they follow on immediately afterwards. And as the only functions needed to read the data from BASIC are CHR$ and PEEK (as well as USR to make the machine code work in the first place), that meant I could convert it for the ZX80 and achieve my goal.
Here's the evidence.
The advantage that the QL brings to the table, and once which I've used before, is is wide MODE 4 screen which can hold 85 characters. Could I make a QL version of
Hex Bin Converter that would extend the range of values as far as 18,446,744,073,709,551,615? Who is ever going to need to count to 18 quintillion anyway? Why not just use WolframAlpha? As with all my QL programs, it's more of an exercise to see if I can do it. And, as you can see, I can. Numbers as huge as those this program can handle are best contained either in strings, or in arrays where each element houses one digit each. As this program was put together bit by bit - I'd get the decimal conversion working first, and then adapt it to the other bases later - I've used a bit of both each time. It's easier to use arrays to handle the conversion between bases, and strings to handle the display format.
And talking of the display format, there are more windows in this program than in a concrete tower block in the grimmest parts of any city in the former Soviet Union. #0, #1 and #2 are all redefined to TV-mode size (but retained in MODE 4), #3 displays the decimal output, #8 handles octal, #4-#7 are used for the "D/H/B/O" menu, and the hex and binary outputs get eight windows each - #11-18 and #21-28 - for a total of 25 windows defined, although window #2 is never used, it's just there to maintain compatibility if the program needs to be stopped and LISTed. So 24 windows will see action along the course of this program.
I make no guarantees that the code is perfect - it may look like a bit of a mess, but I've tried to keep all the procedures in one place, so the 1000s are the printing procedures, the 2000s-5000s are the conversions (2000 = decimal, 3000 = hex, 4000 = binary, 5000 = octal), the 6000s are any shared conversion sub-procedures, the 7000s ask which base is required, the 8000s ask for the value, and the 9000s are setting up the arrays and screen. With any error-trapping procedures, I've tried to make sure they're watertight, but the decimal input was so tricky (seeing as it's checking for a value that's higher than the QL can store accurately and
isn't just a string of repeating digits) that this is the one most likely to be less than perfect.
Anyway, have fun with this - what's the longest word you can make using only hex digits, and what's its value in decimal?