C128-BCD-Mystery-And-Solutions-HiScoreCounter --------------------------------------------------------------------------------------------------- TOOL: Built-in ML-Monitor {Commodore C128} Language: Machine Language {Assembler} Extra: none Author: Misel Zivanovic Note: (C) 18th of OCTOBER 2026 - www.lived.ch, mzretro.ch Doc Revision: 1.0 Last update: 07:42 20.10.2026 Additional: Read here about BCD: https://en.wikipedia.org/wiki/Binary-coded_decimal --------------------------------------------------------------------------------------------------- I already made a funny counter, but it took tons of bytes... This one is just a handful of bytes {actually 62 bytes} and is counting until 9990 in steps {10} It easily can be extended to 99990 and more as you can see. Just follow the logical steps from previous digits. Note that this counter is using screen positions $0400,$0401,$0402,$0403 Which basically means, that you need to adapt this numbers according to position of your score counter, in your game or wherever you plant to use it. Not so difficult, no worries. This below is a BASIC example to show that it is working. It is, of course, not the idea to use it from BASIC, but in directly in Assembler. Practically, when a collision is reached or you win something you call this routine with JSR in Assembler to update the score results. It's counted plus 10 {actually, the 4th 0 {zero} is untouched as it's always a zero}, each time you call the routine, but you can add even more than 10 points. The 0 {zero} makes it look like is counted in 10th steps! Nice little trick, hehe... EXAMPLE: {adding 30 points to the score} d 1400 . 01400 a2 00 ldx #$00 . 01402 20 00 13 jsr $1300 . 01405 e8 inx . 01406 e0 05 cpx #$03 . 01408 d0 f8 bne $1402 . 0140a 60 rts Now, by calling this routine jsr $1400 in assembler you would add 30 to the counter! You can use this to add score according to achieved goals! Like collecting gold, silver, big treasures, time bonus etc. To add more that 30, just change the compare value before you call JSR $1400 EXAMPLE: {First call, JSR $1400 added 30 to the counter} {2nd call changed compare value to 8 {80} and added 80 to the counter {30 + 80 = 110} {NOTE: Calling $1400 now would add again 80 to the counter and not 30 because we have change } { the compare value to 8 {80}. You have to change it again to get default 3 or other values} { before you call it again } 0110 d 1400 140a a 01400 a2 00 ldx #$00 a 01402 20 00 13 jsr $1300 a 01405 e8 inx a 01406 e0 03 cpx #$03 a 01408 d0 f8 bne $1402 a 0140a 60 rts d 1410 1418 a 01410 a9 08 lda #$08 a 01412 8d 07 14 sta $1407 a 01415 20 00 14 jsr $1400 a 01418 60 rts j 1400 j 1410 BOTTOM LINE IS: Having a counter in assembler isn't so difficult after all. You could also save this counter to a disk and load it the next time players starts the game. This probably will be the subject for the next lesson or maybe a bit after because i was thinking to make this counter available also in EDASS-128-Assembler first... Main reason is that doing editing in ML-Monitor, assembly mode, aren't really easy when the code gets larger! --------------------------------------------------------------------------------------------------- AND NOW THE CODE ITSELF! By now everyone should know how to handle this lines of code below, but a small hint won't hurt anyone, right... 0000 ready. list {BASIC lines. Execute FIRST after the assembly or ML-Code is entered!} 10 scnclr:char 0,0,0,"0000" 20 for a=1to999 30 sys 4864 40 forb=1to25:next 50 next {Use ML-Monitor, assembly mode, to enter these lines here} {To copy/paste the same, better use the ML-Code below} d 1300 1330 . 01300 f8 sed . 01301 ad 02 04 lda $0402 . 01304 18 clc . 01305 69 01 adc #$01 . 01307 8d 02 04 sta $0402 . 0130a ad 02 04 lda $0402 . 0130d c9 40 cmp #$40 . 0130f b0 02 bcs $1313 . 01311 d8 cld . 01312 60 rts . 01313 ad 01 04 lda $0401 . 01316 18 clc . 01317 69 01 adc #$01 . 01319 8d 01 04 sta $0401 . 0131c ad 03 04 lda $0403 . 0131f 8d 02 04 sta $0402 . 01322 ad 01 04 lda $0401 . 01325 c9 40 cmp #$40 . 01327 b0 03 bcs $132c . 01329 4c 11 13 jmp $1311 . 0132c ad 00 04 lda $0400 . 0132f 18 clc . 01330 69 01 adc #$01 . 01332 8d 00 04 sta $0400 . 01335 ad 03 04 lda $0403 . 01338 8d 01 04 sta $0401 . 0133b 4c 11 13 jmp $1311 {these ML-Code lines are ideal to copy/paste it into the ML-Monitor of the Commodore C-128} {when it is done, you can run the BASIC example we already mentioned before} {this code below is the same as assembly lines above!} >01300 f8 ad 02 04 18 69 01 8d:XM...I.. >01308 02 04 ad 02 04 c9 40 b0:..M..I@P >01310 02 d8 60 ad 01 04 18 69:.X?M...I >01318 01 8d 01 04 ad 03 04 8d:....M... >01320 02 04 ad 01 04 c9 40 b0:..M..I@P >01328 03 4c 11 13 ad 00 04 18:.l..M... >01330 69 01 8d 00 04 ad 03 04:I....M.. >01338 8d 01 04 4c 11 13 00 00:...l.... --------------------------------------------------------------------------------------------------- Short explanation and warning! Usually, the numbers 0 to 9 are from $30 to $39! $30 being a zero {#0} and $39 being a #9 {nine} But as you can see, we are using $00 as a zero and $09 as a new which then basically is 1-10 in "normal" decimal world. All this thanks to BCD mode or SED command which is SET DECIMAL MODE! Note that you have to clear this mode before you return to BASIC {with RTS command}. Also if you plan to change the code! Always keep in mind to use CLD {CLEAR DECIMAL Mode}, before you return. OR YOUR C128 will catch COLD awakening! We are doing that here with : . jmp $1311 As you can see, it's always executing CLD before the RTS! ---------------------------------------------------------------------------------------------------