tschak909 Posted July 29, 2016 Share Posted July 29, 2016 Can somebody explain _WHY_ this works? LDA ScanLine BPL VvRefl ; If on the bottom half of the screen, EOR #$F8 ; reverse direction so we can mirror. VvRefl CMP #$20 BCC VfDone ; Branch if at bottom. Is it simply a combination of a two-compliment flip, with a corresponding AND mask, as a side effect? -Thom Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted July 30, 2016 Share Posted July 30, 2016 Too little context for me. Quote Link to comment Share on other sites More sharing options...
tschak909 Posted July 30, 2016 Author Share Posted July 30, 2016 Sorry, this comes from the combat disassembly, inside the kernel: ; ; ------------------------------------------------------------ ; ; Video OUT -- THE KERNAL ; ; We start with the score, then we render the playfield, players, ; and missiles simultaneously. All in all, an average day for a VCS. ; VOUT LDA #$20 STA ScanLine ; We're assuming scanline $20. STA WSYNC STA HMOVE ; Move sprites horizontally. VOUT_VB LDA INTIM BNE VOUT_VB ; Wait for INTIM to time-out. STA WSYNC STA CXCLR ; Clear collision latches STA VBLANK ; End vertical blank TSX STX TMPSTK ; Save stack pointer LDA #$02 STA CTRLPF ; Double, instead of reflect. LDX KLskip Vskip1 STA WSYNC ; Skip a few scanlines... DEX BNE Vskip1 LDA KLskip CMP #$0E ; "No Score" value of KLskip BEQ Vmain ; ; KLskip is set as such so that when the score is ; to be displayed, it waits for just the right time ; to start drawing the score, but if the score is ; not to be displayed, as when the score flashes ; signifying "time's almost up", it waits for just ; the right time to start drawing the rest of the ; screen. ; ; Draw the score: ; LDX #$05 ; Score is five bytes high. LDA #$00 ; Clear number graphics. STA NUMG0 ; They won't be calculated yet, STA NUMG1 ; but first time through the loop ; the game will try to draw with ; them anyway. VSCOR STA WSYNC ; Start with a fresh scanline. LDA NUMG0 ; Take last scanline's left score, STA PF1 ; and recycle it, ; ; Here, we begin drawing the next scanline's ; left score, as the electron beam moves towards ; the right score's position in this scanline. ; LDY SCROFF+2 LDA NUMBERS,Y ; Get left digit. AND #$F0 STA NUMG0 LDY SCROFF LDA NUMBERS,Y ; Get right digit. AND #$0F ORA NUMG0 STA NUMG0 ; Left score is ready to ship. LDA NUMG1 ; Take last scanline's right score, STA PF1 ; and recycle it. LDY SCROFF+3 LDA NUMBERS,Y ; Left digit... AND #$F0 STA NUMG1 LDY SCROFF+1 LDA NUMBERS,Y ; right digit... AND SHOWSCR ; ; Now, we use our fresh, new score graphics in this next scanline. ; STA WSYNC ; *COUNT* ORA NUMG1 ;Finish calculating (0) +3 STA NUMG1 ;right score. (3) +3 LDA NUMG0 ; (6) +3 STA PF1 ; *9* +3 ; ; We use this time to check whether we're at the end of our loop. ; DEX ; (12)+2 BMI Vmain ; (14)+2 No Branch ; ; If so, we're out of here. Don't worry, the score will be ; cleared immediately, so nobody will know that we've gone ; past five bytes and are displaying garbage. ; INC SCROFF ; (16)+5 INC SCROFF+2 ; Get ready to draw the next INC SCROFF+1 ; line of the byte. INC SCROFF+3 LDA NUMG1 STA PF1 ; Right score is in place. JMP VSCOR ; Go to next scanline, ; ; Main Kernal Display loop for the game itself ; Vmain LDA #$00 ; Inner Display Loop STA PF1 ; Clear the score. STA WSYNC LDA #$05 STA CTRLPF ; Reflecting playfield. LDA Color0 STA COLUP0 ; How often must THIS be done? LDA Color1 STA COLUP1 Vfield LDX #$1E ; Very Sneaky - TXS ; Set stack to missile registers SEC ; ; This yields which line of player 0 to draw. ; LDA TankY0 SBC ScanLine ; A=TankY0-ScanLine AND #$FE ; Force an even number TAX ; Only sixteen bytes of AND #$F0 ; sprite memory, so... BEQ VdoTank ; If not valid, LDA #$00 ; blank the tank. BEQ VnoTank ; (unconditional branch) VdoTank LDA HIRES,X ; Else, load the appropriate byte. VnoTank STA WSYNC ; ----END OF ONE LINE---- STA GRP0 ; Just for player 0. ; ; The infamous Combat Stack Trick: ; ; Keep in mind that at this point, the stack pointer ; is set to the missile registers, and the "zero-result" ; bit of the P register is the same at the bit ENAM0/1 ; looks at. ; LDA MissileY1 EOR ScanLine AND #$FE PHP ; This turns the missle 1 on/off LDA MissileY0 EOR ScanLine AND #$FE PHP ; This turns the missle 0 on/off ; ; We've got the missile taken care of. ; Now let's see which line of the playfield to draw. ; LDA ScanLine BPL VvRefl ; If on the bottom half of the screen, EOR #$F8 ; reverse direction so we can mirror. VvRefl CMP #$20 BCC VfDone ; Branch if at bottom. LSR LSR LSR ; Divide by eight, TAY ; and stow it in the Y-register. ; ; By now, the electron beam is already at the next ; scanline, so we don't have to do a STA WSYNC. ; ; This yields which line of Tank 1 to draw. ; VfDone LDA TankY1 ; TankY1 is other player's position. SEC SBC ScanLine ; A=TankY1 - ScanLine INC ScanLine ; Increment the loop. NOP ORA #$01 ; Add bit 0, force odd number. TAX ; AND #$F0 ; There are only sixteen bytes of BEQ VdoT1 ; sprite memory, so... LDA #$00 ; If tank is not ready, blank it. BEQ VnoT1 VdoT1 LDA HIRES,X ; Else, draw the tank VnoT1 BIT PF_PONG STA GRP1 BMI VnoPF ; If PF_PONG bit 7 set, don't write PF LDA (LORES),Y ; (this means game variation has blank STA PF0 ; background) LDA (LORES+2),Y STA PF1 LDA (LORES+4),Y STA PF2 VnoPF INC ScanLine ; One more up in the loop. LDA ScanLine EOR #$EC ; When we've reached the $ECth line, BNE Vfield ; we've had enough. LDX TMPSTK ; Restore stack pointer, which is TXS ; is used for calls in main game loop STA ENAM0 ; Clear a bunch of registers. STA ENAM1 STA GRP0 STA GRP1 STA GRP0 ; In case GRP0 isn't COMPLETELY zeroed. STA PF0 STA PF1 STA PF2 RTS Quote Link to comment Share on other sites More sharing options...
+nanochess Posted July 30, 2016 Share Posted July 30, 2016 Apparently the maps for Combat are into ROM but only the top half, once the scanline count reaches half of screen, the EOR changes index so the half map is put out in reverse order. Note how the value is put into Y register and later read indexed to put in playfield registers. Quote Link to comment Share on other sites More sharing options...
tschak909 Posted July 30, 2016 Author Share Posted July 30, 2016 Yes, that's what I'm understanding, the key instruction is the EOR #$F8 ... my question is _why_ ... it keeps the bottom three bits untouched, which...makes me believe it's a two's compliment/mask combo. -Thom Quote Link to comment Share on other sites More sharing options...
+nanochess Posted July 30, 2016 Share Posted July 30, 2016 Yes, that's what I'm understanding, the key instruction is the EOR #$F8 ... my question is _why_ ... it keeps the bottom three bits untouched, which...makes me believe it's a two's compliment/mask combo. -Thom That depends on the programmer style. It can be $F8, $FC, $FE or $FF because when dividing by 8 the lower 3 bits are lost. Only the top 5 bits matter, changing $00-$1f to $1f-$00 (after divide) Quote Link to comment Share on other sites More sharing options...
phoenixdownita Posted July 30, 2016 Share Posted July 30, 2016 Without knowing anything about the VCS here is my take: At the bit level on any bit (B here is the value of that bit) the XOR truth table is like this: 1) B XOR 1 = NOT B 2) B XOR 0 = B With F8 (11111000) as you notice the lower 3 bits are left untouched because of rule 2 above, the higher 5 bit are instead negated/inverted by rule 1 (the operation is also called 1-complement and not 2-complement). Feel free to skip this next part if irrelevant to you, I just write it for completeness. 2-complements has meaning only on signed quantities and in that setting can be implemented by first negating everything (XOR FF) then adding 1, this sequence will return the negative form of any positive number < 128. For example if you want to obtain -1 from 1 in 2-complement you have to go thru the steps: Value = 00000001 /Value = 11111110 +1 = 11111111 so FF is the representation of -1 (quick way for me to remember how to read signed quantities is to invert the value of bit 7, example unsigned FF = 128 + 64 + 32 + ..... + 1 = 255 but for signed FF = -128 + 64 + 32 .... = -1 [and this is the 2-complement representation of -1 in 8 bits] Quote Link to comment Share on other sites More sharing options...
Omegamatrix Posted July 31, 2016 Share Posted July 31, 2016 Check out my old blog entry for more on the Magic of EOR. Quote Link to comment Share on other sites More sharing options...
tschak909 Posted July 31, 2016 Author Share Posted July 31, 2016 Great blog post! Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.