Badlines on the SuperCPU Today, we will once again have a look at the theme of "Timing". To be precise, we will deal with badlines, raster lines that are called that name because they are slowing down the C64's processor. But does this hold true for the SuperCPU also? by Wolfram Sang (Ninja/The Dreams - www.the-dreams.de) ======================================================= First, we need to clarify, what the real story behind a baldine is. Actually, it isn't that bad, since it is bringing color onto our screen. The VIC can't collect the color information covertly besides the graphic data. Therefore, it needs to block the processor temporarily in order to be able to use the data bus undisturbed when fetching the colors. While there are under PAL 63 and under NTSC 65 cycles available per normal raster line, there are only 23 or 25 cycles respectively available in a badline (with a stock C64). This reduction of computation time annoyed the programmers, of course, and thus the name "badline". Because it is so important for your understanding, summarized again: In order to fetch additional data, the VIC needs the data bus. Because it can only be used by one chip at a time, the processor is stopped for that period. FLI & Co With this really clever VIC trick (Flexible Line Interpretation), you cause artificial badlines in order to increase the picture's variety of colors. The results look really good, but eat up lots of computation time. After all, a badline is created in every screen raster line (except for the border), which requires changiung two VIC registers every time. Since you only have 23 or 25 cycles to do so, there isn't much left for anything else. This is why this graphics mode has been reserved for inanimate pictures. You can see that badlines can be a processor brake not to be underestimated. To begin with, the things said thus far are valid only for the "normal" C64. In spite of this, it would be interesting to know how this looks with the SuperCPU. After all, we want to make good use of the 20 MHz, and don't want to have the 65816 rot in a blocked condition. Let's go through the theory once more in detail. Two Systems? The graphics chip fetches his data from the C64 memory and requires the data bus in the C64 for that. The SCPU has its own memory and also a data bus of its own, which is synchronized with the host computer's one when needed. Then you could actually think that both could run parallel, as long as you avoid synchronization, in other words don't access any of the C64's own registers (VIC, CIA, SID ...).. This can be easily checked using a small routine. The principle is the following: We wait for a reaster line N. As soon as it is reached, we have a counter, the X register in this case count up in an infinite loop. In raster line N+1, we trigger an IRQ and check how far the counter has come. We do this once for a badline and once for a normal raster line. Since counting up involves only the processor, this makes it visible, whether it had been blocked during its work (the values are different) or not (the values are equal). This example is not perfectly timed, so that it suffices for the values to be very similar instead of equal. A difference of +/- 1 doesn't need to mean anything, slight diviations are immaterial. We want to measure a blockade of 40 cycles, after all, the difference between the values should be noticable. By the way, the program has been designed in such a fashion that it will also run on a stock C64, so that we have a means of comparison. And indeed it returns the expected result. During a badline, the counter doesn't get as far as during a normal raster line, because of the VIC interfering. Let's quickly activate the SuperCPU, throw in the 20MHz gear, and start it again. And behold: The difference has disappeared! While the host computer is occupied with the badline, the SCPU can happily continue computing, as long as it doesn't need to access the C64 itself. Therefore, something like showing a FLI picture would eat up that much time anymore, in theory. But things get even better! As is commonly known, displaying sprites also costs some cycles, because the VIC needs to fetch additional graphics data as well. The principle is the same as with badlines, though, which means that sprites can also be displayed with the SuperCPU without any loss of time. The Catch Unfortunately, I have to quench expectations of hot, colorful action games and wild demo parts in UIFLI right away. After all, a major part of such modi is filling the graphics memory quickly with new contents. But the graphics memory resides within the host computer, and in order to write into it, the data busses need to be synchronized. And this is exactly what you shouldn't do, since the C64's bus is blocked during a badline. Trying to synchronize them would necessarily force the SuperCPU to wait. Aforementioned projects are not completely impossible, after all, there is still the vertical border where jobs within the C64 itself can be dealt with. Managing this cleverly is an interesting programming job. For instance, you could compute the enemy intelligence during badlines, this being pure processor work. On the other hand, with all that computation time available, would anyone want to play such damned tough games? Well, methods of apropriately taking advantage of this additional feature of the SuperCPU will certainly be found. Just like Daddy ... Finally, we will test the program with a SuperCPU at one MHz. Once again the turbo card's 65816 is used, so why shouldn't it keep on computing while the C64 is handling badlines?. But the result is negative, again there is a difference. The reason is simple: In order to ensure the utmost compatibility, the C64's timing has simply been adopted 1:1. And this is actually for the best, because otherwise you would need to completely deactivate the SuperCPU whenever using programs with time-critical tricks. And that would really be a shame. === source code ; Test routine for the SuperCPU's behavior ; during a badline or when dealing with sprites ; by Wolfram "Ninja" Sang for GO64!/CW in 2000 org $0801 adr $080b, 64 byt $9e,"2061",0,0,0 ; BASIC line result1 = $fb result2 = $fc jmp_in: jsr $e544 ; clear screen lda #lo(text) ldy #hi(text) jsr $ab1e ; print text sei ; disable IRQs lda #$35 sta $01 ; mask ROM lda #$60 sta $d000 ; set sprite x/y, sta $d001 ; lying within test area lda #1 sta $d027 ; sprite color white sta $d015 ; activate sprite lda #$7f sta $dc0d lda $dc0d ; clear CIA IRQ lda #1 sta $d01a ; set VIC IRQ lda #lo(irq1) sta $fffe lda #hi(irq1) sta $ffff ; redirect IRQ vectors lda #$1b sta $d011 lda #$64 ; set raster line sta $d012 ; for IRQ ($64) ldx #0 ; clear counter lda #$63 cmp $d012 ; wait for raster bne *-3 ; line $63 (badline) cli ; enable IRQ endless: nop ; a short delay, so that nop ; the counter doesn't overflow inx ; and increase it jmp endless ; again and again and again .... irq1: stx result1 ; store result lda #1 sta $d019 ; confirm IRQ lda #lo(irq2) sta $fffe ; redirect IRQ vector lda #$67 ; set raszer line for sta $d012 ; IRQ ($67) ldx #0 ; clear counter lda #$66 cmp $d012 ; wait for raster bne *-3 ; line $66 (no badline) rti ; back to endless loop irq2: stx result2 ; store result lda result1 ldx #9 jsr hexout ; put result 1 onto screen lda result2 ldx #92 jsr hexout ; put result 2 onto screen lda #1 sta $d019 ; confirm IRQ lda #lo(irq1) sta $fffe ; redirect IRQ vector lda #$64 ; set raster line sta $d012 ; for IRQ ($64) ldx #0 ; clear counter lda #$63 cmp $d012 ; wait for raster bne *-3 ; line $63 (badline) rti ; back to the endless loop hexout: pha ; outputs a hex number from the accu lsr ; x register defines postion lsr ; on the screen lsr ; of no importance for the lsr ; timing jsr hexout2 pla and #$0f hexout2: clc adc #$30 cmp #$3a bcc hexout_l1 sbc #$39 hexout_l1: sta $0400,x inx rts text: byt "BADLINE:",$0d,$0d,"NO BADLINE:",0 === uuencoded binary begin 666 badline-test.prg M`0@+"$``GC(P-C$````@1.6INJ`((!ZK>*DUA0&I8(T`T(T!T*D!C2?0C170 MJ7^-#=RM#=RI`8T:T*E=C?[_J0B-__^I&XT1T*EDC1+0H@"I8\T2T-#[6.KJ MZ$Q7"(;[J0&-&="I>(W^_ZEGC1+0H@"I9LT2T-#[0(;\I?NB"2"A"*7\HEP@ MH0BI`8T9T*E=C?[_J62-$M"B`*ECS1+0T/M`2$I*2DH@K`AH*0\8:3#).I`" =Z3F=``3H8$)!1$Q)3D4Z#0U.3R!"041,24Y%.@`` ` end