So we’ve covered the method required for printing the value from an 8 or 16-bit register, but have found two drawbacks with it – the size of the number we can print, and the time it takes to print it (as it has to keep looping for each value in each numeric ‘column’) I also hinted that there are at least two other methods you can use for doing this tasks, and both rely on using a more ‘direct’ method for storing the number – just store the digits themselves instead of using binary as the registers do.
For example, we could represent an 8-digit number for a score – allowing us to store from 0 to 99,999,999 – by using a byte for each digit. So, for our 8-bit number set to zero we could use the following:
SCORE: defb 0, 0, 0, 0, 0, 0, 0, 0
Or for 6,031,769:
defb 0, 6, 0, 3, 1, 7, 6, 9
In order to print that number onto the screen we can simply loop for each digit, adding the ASCII (or equivalent) for zero / ‘0’ to each value before we display it.
That’s much easier and faster than the previous method, and it’s also a fixed cost – the whole number will always take the same amount of time to show. If you don’t want to show the leading zeros you can use a flag to ignore each digit until you reach one which is non-zero, and then draw the rest, making sure that you always show the last digit (or have a special case for the whole number being zero)
The difficulty with this method is how we do arithmetic on it – how do we add 10 for shooting the alien? or 500 for finishing the level? With the registers that was more straightforward, but here we’re going to have to do it all ourselves. That’s not too bad though if you arrange the number you want to add (or subtract) in the same format, and so can work along both numbers together from right to left (i.e units, then ten, hundreds, thousands, and so on) and add each digit in turn. You need to be aware that you might need to carry-over from one digit to the next – i.e. if you add 9 to 6 the result isn’t 15, but 5 in the units (current), and +1 in the tens (next), so will need something like below for each digit:
; Perform 9 + 6 ld a, 9 ld b, 6 ; Do the addition add a, b ; Check if the result overflows into the next digit cp 10 jp c, NO_OVERFLOW ; Result carries into the next digit ; Correct the value for this digit sub 10 ; Increase the value for the next digit ... NO_OVERFLOW ...
The above would need to be looped for as many times as you have digits in your number, and you’ll need to decide what you do if your final/left-most digit overflows – as there is no ‘next’ digit to overflow into. Many games simply ignore this issue entirely, and just assume that the player will never fill all 8 (or how ever many) digits – it’ll just wrap around back to zero again.
So long as you keep the operations you need to perform on the number simple – adding and subtracting – then this method is straightforward to use, has a constant draw time, and can be expanded to work with as large a number as you need (so long as you have the memory to store it).
You can take this method further by storing the number directly using ASCII (or whatever), and altering the overflow check to work from ‘0’+10. With this change the draw loop becomes faster, but the calculation remains the same, with the number you add/remove still being zero-based. Using this change you can update the number directly within an other text – so ‘PLAYER1: 06031769’ can be printed as a single string if required – which could be good for when the screen is first shown.