LABYRINTH - COMMODORE C128 in ACTION! - LOGICAL 'AND' EXPLAINED -------------------------------------------------------------------------------------------------- TOOL: Built-In ML-Monitor {Commodore C128} Language: Assembler Extra: None Author: Misel Zivanovic Note: (C) 11th DEC 2025 - www.lived.ch, mzretro.ch --------------------------------------------------------------------------------------------------- EXAMPLE 1: ---------- Probably everyone have seen this before: 10 print chr$(205.5+rnd(1));:goto10 EXAMPLE 2: ---------- This one maybe not so: 10 print chr$(205.5+rnd(ti));:goto10 EXAMPLE 3: ---------- The last one is very unlikly you have ever seen it because i just wrote it, haha... Compared to Commodore C64 with 80 characters per line, Commodore C128 can push it to 160 characters! I just added some extras for better speed differences demonstration. As long as SYS 4864 is involved, all are suspecting assembler and indeed it is, partly! However, my goal is to NOT show how fast assembler is, but how FAST actually the PRINT command is! But also there you need to know how to use it! See how much slower it can get if you use the wrong strategy! WHAT IS FASTER: 5 ti$="000000" 10 scnclr:c=160 20 a=4864:pokea,169:pokea+1,206:pokea+2,32:pokea+3,210:pokea+4,255:pokea+5,96 25 forb=1 to c:sys4864:next:print ti/60 30 print:ti$="000000" 40 fora=1toc:print"N";:next 45 print ti/60 50 print:ti$="000000" 60 fora=1toc:printchr$(206);:next 65 print ti/60 70 print:ti$="000000":d$=chr$(206) 80 fora=1toc:printd$;:next:print ti/60 This is what line 20 is doing {no need to enter this part below!} . 01300 a9 ce lda #$ce . 01302 20 d2 ff jsr $ffd2 . 01305 60 rts --------------------------------------------------------------------------------------------------- NOW LET US BEGIN WITH THE MAIN PART! FOR COMMODORE C128 - ONE OF MANY POSSIBLE VERSIONS! I AM TAKING THIS ONE JUST AS FOLLOW UP TO ALREADY USED BRANCH COMMANDS IN LAST TWO LESSONS! --------------------------------------------------------------------------------------------------- You can modify it from BASIC and change graphics parts if you want but it is not something you must do to have this running! Start (from BASIC) = SYS 2816 RETURN = Generate New Q = Quit poke 2899,x {0-255} = gfx element 1 poke 2904,x {0-255} = gfx element 2 EXAMPLES: 1. poke 2899,70:poke 2904,71 2. poke 2899,86:poke 2904,91 3. poke 2899,106:poke 2904,111 3. poke 2899,92:poke 2904,104 So your BASIC part for the assembly routine below could look like this: 10 poke 2899,77:poke 2904,78 20 sys 2816:scnclr THIS IS THE PART YOU CAN COPY/PASTE INTO ML-MONITOR OF Commodore C128! {IT WILL WORK ALSO WITHOUT THE BASIC PART!!!} By now you should know how to do it! If you don't, then you are a JUMPER! Help yourself! {NOTE how the listing is at $f0b00, meaning BANK 15} {to place it in BANK 0, just replace 1st f with 0} {or copy/paste it like this and then use t command to transfer it to BANK 0 = t f0b00 f0b5c 00b00} {this will transfer it to BANK 0, $0b00, SYS 2816} INFORMATION: This code can be relocated because it is actually going to the same addresses, just a different BANK. Because the BANK switch is in the code, it can be moved to BANK 0 and it still will work. CHOOSE WHAT YOU WANT! BANK 15 >f0b00 a9 00 8d 00 ff a9 ff 8d:I.M..I.. >f0b08 0e d4 8d 0f d4 a2 00 a9:.T..TB.I >f0b10 80 8d 12 d4 ad 1b d4 29:...TM.T) >f0b18 03 c9 00 f0 35 c9 01 f0:.I.P5I.P >f0b20 36 c9 02 b0 ea 9d 00 04:6I.PJ... >f0b28 9d c8 04 9d 90 05 9d 58:.H.....x >f0b30 06 9d 20 07 e8 e0 c8 d0:.. .H.HP >f0b38 d6 a9 40 8d 22 0a 20 e4:VI@.". D >f0b40 ff c9 0d f0 c8 c9 51 f0:.I.PHIqP >f0b48 03 4c 3e 0b a9 80 8d 22:.l>.I.." >f0b50 0a 60 a9 4d 4c 25 0b a9:..Iml%.I >f0b58 4e 4c 25 0b 00 00 00 00:nl%..... BANK 0 >00b00 a9 00 8d 00 ff a9 ff 8d:I.M..I.. >00b08 0e d4 8d 0f d4 a2 00 a9:.T..TB.I >00b10 80 8d 12 d4 ad 1b d4 29:...TM.T) >00b18 03 c9 00 f0 35 c9 01 f0:.I.P5I.P >00b20 36 c9 02 b0 ea 9d 00 04:6I.PJ... >00b28 9d c8 04 9d 90 05 9d 58:.H.....x >00b30 06 9d 20 07 e8 e0 c8 d0:.. .H.HP >00b38 d6 a9 40 8d 22 0a 20 e4:VI@.". D >00b40 ff c9 0d f0 c8 c9 51 f0:.I.PHIqP >00b48 03 4c 3e 0b a9 80 8d 22:.l>.I.." >00b50 0a 60 a9 4d 4c 25 0b a9:..Iml%.I >00b58 4e 4c 25 0b 00 00 00 00:nl%..... --------------------------------------------------------------------------------------------------- ALL EXPLAINED: . f0b00 a9 00 lda #$00 As we already know, we need BANK 15 to access the necessary registeres . f0b02 8d 00 ff sta $ff00 These 2 line are making this possible . f0b05 a9 ff lda #$ff Accumulator value #$ff, dec 255 . f0b07 8d 0e d4 sta $d40e Write to low . f0b0a 8d 0f d4 sta $d40f and high byte of the frequency register . f0b0d a2 00 ldx #$00 Set our counter to 0 . f0b0f a9 80 lda #$80 Load accumulator with #$80, dec 128 . f0b11 8d 12 d4 sta $d412 We are putting the value from above #$80, dec 128 into control register . f0b14 ad 1b d4 lda $d41b and we are loading the value from the oscillator to accumulator . f0b17 29 03 and #$03 This is a tricky one! FIND EXPLAINATION BELOW! . f0b19 c9 00 cmp #$00 If lda $d41b is delivering 0 then . f0b1b f0 35 beq $0b52 jump to $0b52 . f0b1d c9 01 cmp #$01 If it is 1 then . f0b1f f0 36 beq $0b57 jump to $0b57 . f0b21 c9 02 cmp #$02 Is it 2? . f0b23 b0 ea bcs $0b0f Let's then jump to repeat the process be cause we need just 0 or 1 . f0b25 9d 00 04 sta $0400,x Each of these lines is filling the screen with 200 characters {x-register LOOP} . f0b28 9d c8 04 sta $04c8,x Each of these lines is filling the screen with 200 characters {x-register LOOP} . f0b2b 9d 90 05 sta $0590,x Each of these lines is filling the screen with 200 characters {x-register LOOP} . f0b2e 9d 58 06 sta $0658,x Each of these lines is filling the screen with 200 characters {x-register LOOP} . f0b31 9d 20 07 sta $0720,x and is then tausend characters! A full screen starting from $0400, dec 1024 + x . f0b34 e8 inx increment the x-register . f0b35 e0 c8 cpx #$c8 Is it #$c8, dec 200? . f0b37 d0 d6 bne $0b0f If NOT, repeat it until we have our number! . f0b39 a9 40 lda #$40 This the part where you should start reading all the books you can download here . f0b3b 8d 22 0a sta $0a22 to better understand what is what. This is to disable key repeating! {#$80 to enable} . f0b3e 20 e4 ff jsr $ffe4 Kernal GETIN Routine a f0b41 c9 0d cmp #$0d Is wating to catch what we are pressing {ENTER is what the programmer want us to press} a f0b43 f0 c8 beq $0b0d If we do, branching to $0b0d is activated and we start from scratch . f0b45 c9 51 cmp #$51 To EXIT, you should click on Q key . f0b47 f0 03 beq $0b4c This will then jump to $0bc4 . f0b49 4c 3e 0b jmp $0b3e Jump to KERNAL GETIN and repeat and wait until something is pressed! . f0b4c a9 80 lda #$80 If Q key was pressed we enable key repeating and return to subroutine or BASIC . f0b4e 8d 22 0a sta $0a22 ENABLE KEY-REPEATING . f0b51 60 rts Back to subroutine or BASIC if called from there with SYS 2816 . f0b52 a9 4d lda #$4d This buddies here are drawing the labyrinth . f0b54 4c 25 0b jmp $0b25 and are jumping back to see who is next . f0b57 a9 4e lda #$4e This buddy or the upper one . f0b59 4c 25 0b jmp $0b25 and always return to choose again! . f0b5c 00 brk --------------------------------------------------------------------------------------------------- LOGICAL AND {e.g. lda #$bf, and #$03} . f0b17 29 03 and #$03 This is a tricky one! FIND EXPLAINATION BELOW! Let's check this code! If you run it with sys 2816 from BASIC it will deliver results in the right upper corner. we are running it with and #$03. It will deliver @,A,B,C {which are actually screen codes: 0,1,2,3} With and #$04 It will deliver @,A,B,C,D {which are actually screen codes: 0,1,2,3,4} This is the code from above, just the end part here was slightly modified: . 00b00 a9 00 lda #$00 . 00b02 8d 00 ff sta $ff00 . 00b05 a9 ff lda #$ff . 00b07 8d 0e d4 sta $d40e . 00b0a 8d 0f d4 sta $d40f . 00b0d a2 00 ldx #$00 . 00b0f a9 80 lda #$80 . 00b11 8d 12 d4 sta $d412 . 00b14 ad 1b d4 lda $d41b . 00b17 ea nop . 00b18 a9 bf lda #$bf POKE 2841,x {0-255} - This is instead of the random number . 00b1a 8d 27 04 sta $0427 Show it in the right upper corner . 00b1d 29 03 and #$03 Logical AND . 00b1f 8d 77 04 sta $0477 Show the result of it {depending on the number under POKE 2841,x} . 00b22 60 rts EXPLAINED: {I hope i did this understandable} --------------------------------------------------------------------------------------------------- As default we entered POKE 2841,191 {hex #$bf} BITS {0-7} & VALUES {1-128} = 255 when all is active binary that is: 1011 1111 {8 bit value} { 7 6 5 4 3 2 1 0} AND #$03 0000 0011 {128 64 32 16 8 4 2 1} ------------------------- 11 = 3 {0,1,2,3) {@,A,B,C} = C {wenn you run the code, it will be C} --------------------------------------------------------------------------------------------------- Here is why 191 is delivering C as a result! --------------------------------------------------------------------------------------------------- Practically, 191 is equal to 3, which is C as we know by now. binary for 3: 0000 0011 and we are watching just first 2 bits which also 191 is having active and that is counted together within the range we need 1+2 = 3 = C again. In other words, if we type POKE 2841,2 that would give us always a B {@=0, A=1, B=2, C=3} With POKE 2841,1 = A, and POKE 2841,0 = @ You can now easily guess what results will be delivered when we load random numbers {0-255} and just get values between 0 and 3! {NOTE: for 'and #$3' we need to watch just last two bits. You can ignore the rest} hex #$1c, dec 28, bin:0001 11 00 = @ {because our bits are 0, result is 0 = @} hex #$1d, dec 29, bin:0001 11 01 = A {because our bit is active: 1 = A} hex #$9f, dec 159, bin:1001 11 11 = C {because last 2 bits are active: 1+2 = C} Again, i really hope this was explained understandable! I added the code below which you can copy/paste and then experiment. --------------------------------------------------------------------------------------------------- CHECK IT FOR YOURSELF... PART 1: BASIC Enter this first! 10 poke 2841,191 20 sys 2816 Then copy/paste this code below to ML-MONITOR and run the BASIC part. >00b00 a9 00 ad 00 ff a9 ff 8d:I.M..I.. >00b08 0e d4 8d 0f d4 a2 00 a9:.T..TB.I >00b10 80 8d 12 d4 ad 1b d4 ea:...TM.TJ >00b18 a9 bf 8d 27 04 29 03 8d:I..'.).. >00b20 77 04 60 00 00 00 00 00:W....... ---------------------------------------------------------------------------------------------------