SPRITE-BACKGROUND-COLLISIONS -------------------------------------------------------------------------------------------------- TOOL: EDASS-128 Editor/Assembler {and Commodore C128 ML-Monitor} Language: Assembler Extra: - Author: Misel Zivanovic Note: (C) 13th of May 2026 - www.lived.ch, mzretro.ch --------------------------------------------------------------------------------------------------- *************************************************************************************************** 1 BYTE = BIT : 007 006 005 004 003 002 001 000 VALUE : 128 064 032 016 008 004 002 001 = 255, $ff {real value 256, 0 to 255} *************************************************************************************************** In the process of programming the LABESC game, i noticed how just reading the registers 53279 wasn't really helpful. I had to refresh my knowledge! After a while I found out that also the register or address $d019 must be involved and from there you go and read the other registers {that said, i would probably need to rewrite the SPRITE <> SPRITE collision code to add some efficiency.} So, the address $d019, dec 53273 is only a read address which is reset afterwards! {otherwise there always would be an active collision registration} Therefore, you need to catch the changes and actually isolate the bits you need for whatever you'll need them. We have 8 bit in total, from 7 to 0, values from 128 to 1. Bit 1 is what we need in order to branch to a routine where we can then check which sprites were involved during the collision event. What we need to do, is isolated the 2nd bit and check the status {value} So let's read the $d019 address: print peek(53273) = dec 120 = bin 0111 1000 ------------------------------------------------------------------------------------- = bit 1 is zero and therefore we have NO SPRITE<>BACKGROUND collision. = print peek(53273) and 2 {this is is how we would read if bit 1 is on} = bit 1 is off = 0 ------------------------------------------------------------------------------------- Now let's assume how we have a collision: print peek(53273) = dec 122 = bin 0111 1010 ------------------------------------------------------------------------------------- = bit 1 is one and it's value is 2. It means there was a collision registered. = print peek(53273) and 2 = bit 1 is on = 2 ------------------------------------------------------------------------------------- Bit 1 was registered as active and has delivered a value of 2 accordingly. All we need to do now is branch to a subroutine where we can check the register 53279 which can tell us if sprite we needed was involved in the collision. If yes, we can go from there to whatever need to be done, and if our sprite wasn't part of the collision party, then we just go back like nothing happend. Following code in assembler would do that: --------------------------------------------------------------------------------------------------- SPRITE <> BACKGROUND COLLISION --------------------------------------------------------------------------------------------------- main jsr coll ... ... ... jmp main coll lda $d019 read the register, bit 1, value 2 {bit 1 is sprite <> background, bit 2 is sprite <> sprite} and #$02 is 1st bit active? [if yes, it would deliver a value of 2] cmp #$02 we check here what's the value beq collreg and if it is 2 then we branch to handle the collision rts if it wasn't, we go back to continue the code execution below the JSR call collreg lda $d01f read sprite <> background collision register and #$01 is sprite one involved? cmp #$01 {remember, sprite 1 is bit 0 and bit zero is value 1} beq action yes! then action rts otherwise return {instead of RTS here, you could jump with JMP somewhere and write a message or something} {to inform the player that he missed or make him lose points etc.} {and then you would return from there with RTS to main loop below JSR call} action lda #$00 there was a collision and we branched to over here. sta $d020 we do screen color change and sta $d021 ... lda $d01f read the register to empty it rts and go back with rts {not with JMP or JSR!!!} because we came over JSR call and need to Return To Subroutine with RTS! This JSR/RTS circle must always be closed --------------------------------------------------------------------------------------------------- And for the SPRITE <> SPRITE COLLISION? Basically the same, except it's bit 2, value 4! --------------------------------------------------------------------------------------------------- main jsr coll ... ... ... jmp main coll lda $d019 read the register, bit 2, value 4 and #$04 is 2nd bit active? [if yes, it would deliver a value of 4] cmp #$04 we check here what's the value, meaning 4 is what we want/need! beq collreg and if it is 4 then we branch to handle the collision rts if it wasn't, we go back to continue the code execution below the JSR call collreg lda $d01e sprite <> sprite collisions and #$0f this is involving bit 0,1,2,3 = four sprites collided in a massive crash cmp #$0f with each other = value of $0f or dec 15 {1 + 2 + 4 + 8 = 15} beq nice If that was the case, branch to nice! rts nice lda #$00 there was a massive collision and we branched to here. inc $d020 we do screen color change and inc $d021 bring A to the screen, left upper corner! lda #$01 sta $0400 lda $d01e read the register to empty it rts and go back with rts {not with JMP or JSR!!!} because we came over JSR call and need to Return To Subroutine with RTS! This JSR/RTS circle must always be closed. LAByrinth ESCape is using exactly the same processes and as you can see there, it is working! BOTTOM LINE: 1. Check if there was a collision in first place {$d019, bit 1 or 2} Bit 1 {value 2} = SPRITE <> BACKGROUND, Bit 2 {value 4} = SPRITE <> SPRITE} 2. Then check which sprite were involved. $d01f is reading SPRITE <> BACKGROUND cases. $d01e is reading SPRITE <> SPRITE cases 3. Execute proper event/processes to handle the collisions 4. The registers $d01e and $d01f must be reset afterwards to empty the collision registration and avoid fault collisions {reset is MANDATORY, do not avoid that!} 5. I did the reset {read the addresses} also at the beginning of the code just to make sure all possible scenarios are covered and to make sure registers are empty before the game starts! Follow these few steps and the collision will {or should work} work just fine! ---------------------------------------------------------------------------------------------------