Thursday, March 19, 2020

Using BCD

Binary Coded Decimal (BCD)

Binary coded decimal is a way in which decimal values are represented as digits in hexadecimal. In gaming one of the primary uses for BCD is to display information to the player such as scores or other details on screen.

So how does BDC differ from normal hex?

$28 in hex would be 40 in decimal, to converting hex to decimal in 6502 is a  semi-complex coding exercise which is also quite expensive in terms of CPU usage especially if the values are many digits long.

With BCD the values in the $28 are read as their decimal values, so $28 is 28, making it much easier to display on screen as there is no conversion required.

BCD splits the byte in half, creating two 4 bits values so $28 is represented as 0010 1000. So a byte when using BCD can store a number between 0 and 99. For numbers greater than 99 additional bytes need to be used as they would be when storing a larger number.

BCD mode cannot be used all the time it must be turned on and off whenever calculations are required on the values.

To turn on BCD use the sed instruction and the cld instruction turns off BCD. This can be check in a debugger as it sets a bit in the status flag, 1 for on 0 for off.

Example 1:

sed          ; set BCD mode
lda #$19. ; set a to NINETEEN
adc #$11 ; add ELEVEN

cld          ; turn off BCD mode

after the abovet code is run the accumulator contains the value $30. Normally the expected value would be $2a.

Example 2:

sed          ; set BCD Mode
lda #$19  ; set a to NINETEEN
sta temp   ; save to memory
inc temp   ; increase memory

cld           ; turn off BCD mode

in this example the memory address (temp) now contains the value $1A, not $20; some commands do not support BCD.

example 3

To add 150 (decimal) to a score, for example, the usual carry flag rules still apple

        .word 5011

sed          ; set BCD mode
lda score  ; get the lower byte
adc #$50 ; add the lower part of the score

sta score

lda score+1 ; get next. byte
adc #$01     ; previously the carry bit was set because 50+50 = 100 the 1st digit goes into the carry

sta score+1
cld          ; turn off BCD mode

The score will now be 0013, remember that in 6502 we store the numbers in little-endian format. 1150 + 150 = 1300.

This example can be continued for as many digits as required,

BCD is just a representation so if the values need to be compared or accessed for other reasons the BCD mode does not need to set, the values can simply be read and worked upon.

Example 4

To print the values to the screen the individual digits can be accessed and used.

      .byte $21

lda number      ; get the number
; print the left digit 1st, to do this move the top 4 bits to the bottom 4 bits
adc #digits                ; where digits is the value of the 0 in the character set
sta startOfScreen

lda number.     ; get number again
and #0f            ; mask out the top 4 bits
adc #digits
sta statrtOfScreen

The above example takes a single byte, isolates the two halves of it and prints two digits to the screen, note there was no need to use the sed command as the program just reads the digits as they already are.

The value for startOfScreen will depend upon where the program and placed the screen and will usually need an offset to make sure the information is printed in the correct place.

The value for digits is whichever character code the current character set starts the number characters from. The position in which the number characters are placed has no effect on how this works.

For values longer than one byte simply repeat the process for each byte of the number remembering to make sure it is printed in the correct order 

1 comment:

Setting up Mega65 Connect for LAN

The latest Mega65 Core (0.96) now supports remote access from the  M65Connect using Jtag and now ethernet. This guide will explain how to se...