tschak909 Posted September 4, 2016 Share Posted September 4, 2016 I am trying to do little exercises, to further my deeper understanding of writing kernels, and I've noticed something interesting, this particular listing causes the missiles/ball to shift one scanline upward in the middle of the screen... Why is this happening? LDX #ENABL ; 3 3 16 TXS ; 2 5 18 LDA SCANLINE ; 3 8 21 EOR BALLY2 ; 3 11 24 PHP ; 3 14 27 LDA SCANLINE ; 3 17 30 EOR BALLY1 ; 3 20 33 PHP ; 3 23 36 LDA SCANLINE ; 3 26 39 EOR BALLY0 ; 3 29 42 PHP ; 3 32 45 STA WSYNC ; 3 35 (---)48 INC SCANLINE ; 5 5 LDA SCANLINE ; 3 8 CMP #232 ; 2 10 BCC KERNloop ; 3 13 SpiceWare: yes, I am MAKING myself write down cycle counts... (This was always the same problem I had in maths classes, wouldn't write down my intermediate steps, and drive my teachers crazy...) binary attached. -Thom blip.bin Quote Link to comment Share on other sites More sharing options...
tschak909 Posted September 4, 2016 Author Share Posted September 4, 2016 This kernel seems to work better... KERNloop: LDX #ENABL ; 3 3 41 TXS ; 2 5 43 LDA SCANLINE ; 3 8 46 EOR BALLY2 ; 3 11 49 AND #$FE ; 2 13 51 STA WSYNC ; 3 16 54 PHP ; 3 3 LDA SCANLINE ; 3 6 EOR BALLY1 ; 3 9 AND #$FE ; 2 11 PHP ; 3 14 LDA SCANLINE ; 3 17 EOR BALLY0 ; 3 20 AND #$FE ; 2 22 PHP ; 3 25 INC SCANLINE ; 5 30 LDA SCANLINE ; 3 33 CMP #232 ; 2 35 BCC KERNloop ; 3 38 -Thom working.bin Quote Link to comment Share on other sites More sharing options...
tschak909 Posted September 4, 2016 Author Share Posted September 4, 2016 putting a write to COLUBK after reading the scanline visualized it a bit better for me... ...it's....starting....to....click.... -Thom Quote Link to comment Share on other sites More sharing options...
alex_79 Posted September 4, 2016 Share Posted September 4, 2016 (edited) I am trying to do little exercises, to further my deeper understanding of writing kernels, and I've noticed something interesting, this particular listing causes the missiles/ball to shift one scanline upward in the middle of the screen... Why is this happening? That's because you're enabling/disabling missiles and ball in the visible area of the scanline. So if you enable them after their position, they will show up in the next line. To avoid that glitch, you must ensure that all writes to ENAMx/ENABL (the 'php' instruction in your examples) happen during the horizontal blank, that is at most at cycle 22. In your first example writes happen at cycle 26,35 and 44 (your calculations were off by 1 as "ldx IMM" takes 2 cycles, not 3) which correspond to pixel 10,37 and 64 respectively. KERNloop: ;+1 if brach taken 13 LDX #ENABL ; 2 2 15 TXS ; 2 4 17 LDA SCANLINE ; 3 7 20 EOR BALLY2 ; 3 10 23 PHP ; 3 13 26 <----- LDA SCANLINE ; 3 16 29 EOR BALLY1 ; 3 19 32 PHP ; 3 22 35 <----- LDA SCANLINE ; 3 25 38 EOR BALLY0 ; 3 28 41 PHP ; 3 31 44 <----- STA WSYNC ; 3 0 0 INC SCANLINE ; 5 5 LDA SCANLINE ; 3 8 CMP #232 ; 2 10 BCC KERNloop ; 2* 12 In your second example, by putting the 'sta WSYNC' before the first write, things get better: KERNloop: ;+1 if branch taken 38 LDX #ENABL ; 2 2 40 TXS ; 2 4 42 LDA SCANLINE ; 3 7 45 EOR BALLY2 ; 3 10 48 AND #$FE ; 2 12 50 STA WSYNC ; 3 0 0 PHP ; 3 3 <----- LDA SCANLINE ; 3 6 EOR BALLY1 ; 3 9 AND #$FE ; 2 11 PHP ; 3 14 <----- LDA SCANLINE ; 3 17 EOR BALLY0 ; 3 20 AND #$FE ; 2 22 PHP ; 3 25 <----- INC SCANLINE ; 5 30 LDA SCANLINE ; 3 33 CMP #232 ; 2 35 BCC KERNloop ; 2* 37 Now, only the last write is in visible area (7 pixels from the left margin), so only missile0 is showing the glitch. Edited September 4, 2016 by alex_79 Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted September 4, 2016 Share Posted September 4, 2016 Yep, updating too late in the scanline results in shearing. I cover that at the start of Step 4 were I point out it occurs in Stay Frosty 2: For SF2 I found it to be an acceptable compromise vs not having the snowball. As you've noticed, shear is rather easy to spot in objects that only travel horizontally. The snowball travels in an arc, so the sheering is less noticeable. Quote Link to comment Share on other sites More sharing options...
tschak909 Posted September 5, 2016 Author Share Posted September 5, 2016 How can I ensure that all my important register writes for all the objects occurs in the horizontal blank, without resorting to e.g. a 3LK? I'm trying to work my way through building a kernel that can update all six objects (playfield, players, missiles, ball)...and am to do this WITHOUT cribbing code...just need to understand what's going on. ugh. I feel like i'm right on the edge of understanding, and that's always the most frustrating place to be -Thom Quote Link to comment Share on other sites More sharing options...
Omegamatrix Posted September 5, 2016 Share Posted September 5, 2016 If you are running out of time in HBLANK then here is two approaches: 1) Prep everything you can in spare time elsewhere in the kernel, and then stuff the registers quickly in HBLANK. This might mean using a few more temp registers but that's okay. 2) Have two kernels in the case for one of the objects (your choice). Split the screen in half vertically, if the object is on the leftside update it before HBLANK starts, on the far right side of the screen. If the object is on the right side update it after HBLANK, before you reach the right side of the screen. I have used both approaches in the past to solve kernel timing, and in some cases had to do a hybrid of both to get it done. Other than that, there are other techniques for drawing objects. For example: lda (player0Gfx),Y and (playerDraw),Y sta GRP0 That only takes 13 cycles to draw a player, provided your pointers aren't crossing over a page (+1 cycle penalty for each of those). The consequence is you must have a huge table for playerDraw, which is mostly comprised of 0's. Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted September 5, 2016 Share Posted September 5, 2016 Is player1 being updated on every scan line? If so then turning on VDELP0 and VDELBL can prove to be very handy as they make it so you can update GRP0 and ENABL during the visible portion of the prior scan line as those updates are delayed until GRP1 is written to. http://atariage.com/forums/blog/148/entry-10890-slick-kernel/ Quote Link to comment Share on other sites More sharing options...
tschak909 Posted September 5, 2016 Author Share Posted September 5, 2016 I really...need to fuck around with VDELP0/P1/BL... I feel like I'm really missing how these registers work.... I feel so silly, seriously...how long did it take you guys to get a serious grip on writing kernels? I've been at this specific project since May (having never ever done a VCS title before), and I feel like I'm progressing...very....slowly.... am I just being too hard on myself? My end goal is to do something that looks like the earliest launch titles (playfield updated every four lines), with the ability to position the players, missiles, and ball on each line...I thought this would be easier, because I'm not doing any weird VCS pet tricks...but... I guess I was a bit naive. sigh. -Thom Quote Link to comment Share on other sites More sharing options...
tschak909 Posted September 5, 2016 Author Share Posted September 5, 2016 Well, I've managed to get a bit closer, all the objects are on screen, no fun house mirror action happening, and the only rippling is with the PF.... KERNloop: LDX #ENABL ; 2 TXS ; 2 LDA PLAYERY0 SBC SCANLINE AND #$FE TAX AND #$F0 BEQ VdoP0 LDA #$00 BEQ VnoP0 VdoP0: LDA GRP,X VnoP0: STA WSYNC STA GRP0 LDA SCANLINE ; 3 3 EOR BALLY2 ; 3 6 AND #$FE ; 2 8 PHP ; 3 11 LDA SCANLINE ; 3 LSR ; 2 LSR ; 2 LSR ; 2 SEC SBC #$06 ; 2 TAY ; 2 STA TEMP INC SCANLINE LDA PF0_0,Y ; 4 4 STA PF0 ; 3 7 LDA PF1_0,Y ; 4 11 STA PF1 ; 3 14 LDA PF2_0,Y ; 4 18 STA PF2 ; 3 21 LDA PLAYERY1 SBC SCANLINE AND #$FE TAX AND #$F0 BEQ VdoP1 LDA #$00 BEQ VnoP1 VdoP1: LDA GRP,X VnoP1: STA GRP1 LDA SCANLINE ; 3 3 EOR BALLY1 ; 3 6 AND #$FE ; 2 8 PHP ; 3 11 LDA SCANLINE ; 3 3 EOR BALLY0 ; 3 6 AND #$FE ; 2 8 PHP ; 3 11 INC SCANLINE ; 5 LDA SCANLINE ; 3 CMP #232 ; 2 BCC KERNloop ; 3 -Thom dodgeball.asm Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted September 5, 2016 Share Posted September 5, 2016 Start counting from the WSYNC. Your cycle time listed is incorrect. PF writes are happening too late for all of them. To fix this, you could start calculating the value for Y in the available time someplace before WSYNC (there's 11 cycles remaining). Also, keep in mind that PF1 and PF2 writes can actually happen during the visible scanline with no consequence. PF1 needs to be written at cycle 27 or earlier, PF2 at cycle 38 or earlier. KERNloop: ;39 LDX #ENABL ; 2 41 TXS ; 2 43 LDA PLAYERY0 ; 3 46 SBC SCANLINE ; 3 49 AND #$FE ; 2 51 TAX ; 2 53 AND #$F0 ; 2 55 BEQ VdoP0 ; 2 57 LDA #$00 ; 2 59 BEQ VnoP0 ; 3 jmp 62 VdoP0: ;58 LDA GRP,X ; 4 62 VnoP0: ;62 STA WSYNC ; 3 STA GRP0 ; 3 3 LDA SCANLINE ; 3 6 EOR BALLY2 ; 3 9 AND #$FE ; 2 11 PHP ; 3 14 LDA SCANLINE ; 3 17 LSR ; 2 19 LSR ; 2 21 LSR ; 2 23 SEC ; 2 25 SBC #$06 ; 2 27 TAY ; 2 29 STA TEMP ; 3 32 INC SCANLINE ; 5 37 LDA PF0_0,Y ; 4 41 STA PF0 ; 3 44 LDA PF1_0,Y ; 4 48 STA PF1 ; 3 51 LDA PF2_0,Y ; 4 55 STA PF2 ; 3 58 LDA PLAYERY1 ; 3 61 SBC SCANLINE ; 3 64 AND #$FE ; 2 66 TAX ; 2 68 AND #$F0 ; 2 70 BEQ VdoP1 ; 2 72 LDA #$00 ; 2 74 BEQ VnoP1 ; 3 jmp 01 VdoP1: ;73 LDA GRP,X ; 4 01 VnoP1: ;01 STA GRP1 ; 3 04 LDA SCANLINE ; 3 07 EOR BALLY1 ; 3 10 AND #$FE ; 2 12 PHP ; 3 15 LDA SCANLINE ; 3 18 EOR BALLY0 ; 3 21 AND #$FE ; 2 23 PHP ; 3 26 INC SCANLINE ; 5 31 LDA SCANLINE ; 3 34 CMP #232 ; 2 36 BCC KERNloop ; 2 38 Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted September 5, 2016 Share Posted September 5, 2016 Try this...you can use X most of the time to hold the scanline count, Y for PF can be used for other purposes after playfield has been written - also 4 cycles saved by subtracting 6 from the PF data reads (locate tables at least 6 bytes from any page breaks). KERNloop: ;33 LDX #ENABL ; 2 35 TXS ; 2 37 LDA SCANLINE ; 3 40 LSR ; 2 42 LSR ; 2 44 LSR ; 2 46 TAY ; 2 48 used for PF LDA PLAYERY0 ; 3 51 SBC SCANLINE ; 3 54 AND #$FE ; 2 56 TAX ; 2 58 AND #$F0 ; 2 60 BEQ VdoP0 ; 2 62 LDA #$00 ; 2 64 BEQ VnoP0 ; 3 jmp 67 VdoP0: ;63 LDA GRP,X ; 4 67 VnoP0: ;67 ;X register not needed for awhile, ;use it for the scanline value... LDX SCANLINE ; 3 70 STA WSYNC ; 3 STA GRP0 ; 3 3 TXA ; 2 5 EOR BALLY2 ; 3 8 AND #$FE ; 2 10 PHP ; 3 13 LDA PF0_0-6,Y ; 4 17 STA PF0 ; 3 20 LDA PF1_0-6,Y ; 4 24 STA PF1 ; 3 27 LDA PF2_0-6,Y ; 4 31 STA PF2 ; 3 34 STY TEMP ; 3 37 INX ; 2 39 bump scanline LDA PLAYERY1 ; 3 42 SBC SCANLINE ; 3 45 AND #$FE ; 2 47 TAY ; 2 49 use Y instead AND #$F0 ; 2 51 BEQ VdoP1 ; 2 53 LDA #$00 ; 2 55 BEQ VnoP1 ; 3 jmp 58 VdoP1: ;54 LDA GRP,Y ; 4 58 VnoP1: ;58 STA WSYNC ; 3 STA GRP1 ; 3 03 TXA ; 2 05 scanline EOR BALLY1 ; 3 08 AND #$FE ; 2 10 PHP ; 3 13 TXA ; 2 15 scanline EOR BALLY0 ; 3 18 AND #$FE ; 2 20 PHP ; 3 23 INX ; 2 25 bump scanline STX SCANLINE ; 3 28 store for later CPX #232 ; 2 30 BCC KERNloop ; 2 32 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted September 5, 2016 Author Share Posted September 5, 2016 Nifty! I need to study this. Thanks! ! -Thom Quote Link to comment Share on other sites More sharing options...
tschak909 Posted September 5, 2016 Author Share Posted September 5, 2016 Nukey & others, so when cycle counting, take the last WSYNC in the loop, and use that as the starting point when counting cycles? -Thom Quote Link to comment Share on other sites More sharing options...
alex_79 Posted September 6, 2016 Share Posted September 6, 2016 (edited) In a kernel, cycle counts are usually referred to the start of the scanline to know exactly where you can update TIA registers. since strobing WSYNC halts the CPU till the start of the next line, that's where you start you counts from. (nothing stops you from using a differernt position as '0', though, if it makes more sense in a specific kernel). Note that in complex kernels you might not use WSYNC at all (Probably only Boulder Dash does that) and just rely on careful cycle counting to keep in sync with the TIA. That's an extreme case, and you still have to strobe WSYNC at least once outside the kernel to start counting when the electron beam in the CRT (or it's emulation in a digital display) is in a known position. Edit: Corrected the post as I previously wrote VSYNC instead of WSYNC. Thanks enthusi (see post below) for pointing this out!. Edited September 6, 2016 by alex_79 Quote Link to comment Share on other sites More sharing options...
enthusi Posted September 6, 2016 Share Posted September 6, 2016 But you mean WSYNC here, not VSYNC. Not to nitpick but to avoid confusion for beginners. Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted September 6, 2016 Share Posted September 6, 2016 Nifty! I need to study this. Thanks! ! It's just a matter of shuffling the code you already have so it does not interfere with the registers you need to write at the short windows they need to be written to. This code could be further streamlined, but it's best to work at things slowly. The accumulator is a workhorse, but don't overlook the value of the X and Y registers to save time. BTW what is TEMP used for? Nukey & others, so when cycle counting, take the last WSYNC in the loop, and use that as the starting point when counting cycles? Not necessarily. Any WSYNC is just a point where you know to begin counting from zero...so it's easy to follow the number of cycles taken onward. As your kernel grows in complexity, you may find it necessary to abandon WSYNC writes oocasionally to pick up additional cycles. Quote Link to comment Share on other sites More sharing options...
tschak909 Posted September 6, 2016 Author Share Posted September 6, 2016 It's just a matter of shuffling the code you already have so it does not interfere with the registers you need to write at the short windows they need to be written to. This code could be further streamlined, but it's best to work at things slowly. The accumulator is a workhorse, but don't overlook the value of the X and Y registers to save time. BTW what is TEMP used for? Not necessarily. Any WSYNC is just a point where you know to begin counting from zero...so it's easy to follow the number of cycles taken onward. As your kernel grows in complexity, you may find it necessary to abandon WSYNC writes oocasionally to pick up additional cycles. Temp was an attempt to try to break things up into calculation and write phases. And yeah, I see why you would need to abandon wsync cycles, the hardware simply does the HBLANK if you go over 76. I can see that this is one of those arts that you just have to keep doing over and over to really truly understand. -Thom Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted September 6, 2016 Share Posted September 6, 2016 Note that in complex kernels you might not use WSYNC at all (Probably only Boulder Dash does that) That happens quite a bit, even in the simple kernel used in my Collect tutorial. From step 12: One thing to notice about the revised 2LK is the 1st line uses exactly 76 cycles, so it no longer ends with a sta WSYNC. Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted September 9, 2016 Share Posted September 9, 2016 Note that in complex kernels you might not use WSYNC at all (Probably only Boulder Dash does that) and just rely on careful cycle counting to keep in sync with the TIA. ... and here it is! NEW_ROM_BANK ROM_SHADOW_KERNEL, "ROM_SHADOW_KERNEL", ROM_SEG_0 DEFINE_SHADOW_RAM_BANK SHADOW_MAIN_KERNEL, "SHADOW_MAIN_KERNEL", RAM_SEG_0 DrawTheScreen SUBROUTINE ; Thomas Jentzsch strikes again. And Andrew Davie too ; A refactor of the kernel to improve the timing. ; TODO: use GRP1 and COLUP1 for higher resolution Rockford ; 15.07.2014: reverted to single kernel/bank since it simplyfies PF draws .scanBLUE ; 5 @61 bpl .scanBLUECont ; 3 = 3 @64 unconditional .scanRED ; @60 SM_PF0_REDl lda CHARACTERSHAPE_BLANK,y ; 4 sta PF0 ; 3 @67 lda ScreenBitmapRED +0*LINES_PER_CHAR,y ; 4 sta PF1 ; 3 = 14 @74 SELFMOD_PLAYERCOL_RED lda SpriteColourRED,y ; 4 sta COLUP0 ; 3 @05 sta COLUP1 ; 3 = 10 @08 SELFMOD_RED lda #0 ; 2 sta COLUPF ; 3 = 5 @13 SELFMOD_PLAYER0_RED lda ShapePlayerRED,y ; 4 sta GRP0 ; 3 = 7 @20 lda ScreenBitmapRED +1*LINES_PER_CHAR,y ; 4 sta PF2 ; 3 = 7 @27 SM_PF0_REDr lda CHARACTERSHAPE_BLANK,y ; 4 sta PF0 ; 3 @34 lda ScreenBitmapRED +2*LINES_PER_CHAR,y ; 4 sta PF1 ; 3 @41 lda ScreenBitmapRED +3*LINES_PER_CHAR,y ; 4 sta PF2 ; 3 = 21 @48 must be >=48! :-) SELFMOD_PLAYER1_RED lda ShapePlayerRED,y ; 4 sta.w GRP1 ; 4 = 8 @56 VDELed! dey ; 2 bpl .scanBLUE ; 2/3 --> 61 if taken SELFMOD_X ; EXIT_RETURN_HERE inx ; 2 ; ldx #0 ; 2 TODO: fast vertical scrolling DEFINE_SUBROUTINE DrawTheScreenEntry ; @62 kernel entry point ldy #LINES_PER_CHAR/3-1 ; 2 .scanBLUECont ; @64 STX_RAM_BANK ; 3 @67 SWITCH TO CORRECT ROW BANK (OR EXIT BANK) ;------------------------------------------------------------------------------ SM_PF0_BLUEl lda CHARACTERSHAPE_BLANK,y ; 4 sta PF0 ; 3 = 7 @74 SELFMOD_PLAYERCOL_BLUE lda SpriteColourBLUE,y ; 4 sta COLUP1 ; 3 @05 sta COLUP0 ; 3 = 10 @08 SELFMOD_BLUE lda #0 ; 2 sta COLUPF ; 3 = 5 @13 SELFMOD_PLAYER0_BLUE lda ShapePlayerBLUE,y ; 4 sta GRP0 ; 3 = 7 @20 lda ScreenBitmapBLUE +0*LINES_PER_CHAR,y ; 4 sta PF1 ; 3 @27 <=27! :-) lda ScreenBitmapBLUE +1*LINES_PER_CHAR,y ; 4 sta PF2 ; 3 = 14 @34 SM_PF0_BLUEr lda CHARACTERSHAPE_BLANK,y ; 4 sta PF0 ; 3 @41 lda ScreenBitmapBLUE +2*LINES_PER_CHAR,y ; 4 sta PF1 ; 3 @48 lda ScreenBitmapBLUE +3*LINES_PER_CHAR,y ; 4 sta PF2 ; 3 = 21 @55 SELFMOD_PLAYER1_BLUE lda ShapePlayerBLUE,y ; 4 sta GRP1 ; 3 = 7 @62 VDELed! ;------------------------------------------------------------------------------ ; scan GREEN ; @62 SM_PF0_GREENl lda CHARACTERSHAPE_BLANK,y ; 4 sta PF0 ; 3 = 7 @69 SELFMOD_PLAYERCOL_GREEN lda SpriteColourGREEN,y ; 4 sta COLUP1 ; 3 @00 sta COLUP0 ; 3 = 10 @03 SELFMOD_GREEN lda #0 ; 2 sta COLUPF ; 3 = 5 @08 SELFMOD_PLAYER0_GREEN lda ShapePlayerGREEN,y ; 4 sta GRP0 ; 3 = 7 @15 lda ScreenBitmapGREEN +0*LINES_PER_CHAR,y ; 4 sta PF1 ; 3 @22 lda ScreenBitmapGREEN +1*LINES_PER_CHAR,y ; 4 sta PF2 ; 3 = 14 @29 SM_PF0_GREENr lda CHARACTERSHAPE_BLANK,y ; 4 sta PF0 ; 3 @36 lda ScreenBitmapGREEN +2*LINES_PER_CHAR,y ; 4 sta PF1 ; 3 @43 lda ScreenBitmapGREEN +3*LINES_PER_CHAR,y ; 4 sta PF2 ; 3 = 21 @50 SELFMOD_PLAYER1_GREEN lda ShapePlayerGREEN,y ; 4 sta GRP1 ; 3 = 7 @57 VDELed! jmp .scanRED ; 3 @60 OPTIONAL_PAGEBREAK "SCREEN_BITMAP", SCREEN_BITMAP_SIZE ScreenBitmap ds SCREEN_BITMAP_SIZE,$0 ; character bitmap row (10 chars wide) ScreenBitmapRED = ScreenBitmap + NUM_PF_COLOR_GROUPS*0 ScreenBitmapGREEN = ScreenBitmap + NUM_PF_COLOR_GROUPS*1 ScreenBitmapBLUE = ScreenBitmap + NUM_PF_COLOR_GROUPS*2 ShapePlayer = PLAYER_BLANK ShapePlayerBLUE = ShapePlayer ; low adresses patched ShapePlayerGREEN = ShapePlayer ; low adresses patched ShapePlayerRED = ShapePlayer ; low adresses patched END_SHADOW_RAM_BANK ; SHADOW_MAIN_KERNEL 3 Quote Link to comment Share on other sites More sharing options...
Mr SQL Posted September 9, 2016 Share Posted September 9, 2016 ... and here it is! I don't see a single WSYNC Andrew, does one of the other Kernel modules hold it that renders the next line? I pulled one WSYNC out of the two line Kernel for large virtual worlds, but the WSYNC at the end of the second line remains - none of the lines in your Kernel calls the WSYNC function? Quote Link to comment Share on other sites More sharing options...
+Gemintronic Posted September 9, 2016 Share Posted September 9, 2016 I don't see a single WSYNC Andrew, does one of the other Kernel modules hold it that renders the next line? I pulled one WSYNC out of the two line Kernel for large virtual worlds, but the WSYNC at the end of the second line remains - none of the lines in your Kernel calls the WSYNC function? They've got other amazing things in their too. From what little I understand they put in task scheduling so if a particular action would go over-cycle it's delayed until next frame. O_O Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted September 9, 2016 Share Posted September 9, 2016 I don't see a single WSYNC Andrew, does one of the other Kernel modules hold it that renders the next line? I pulled one WSYNC out of the two line Kernel for large virtual worlds, but the WSYNC at the end of the second line remains - none of the lines in your Kernel calls the WSYNC function? That section shows the basic triplet colour lines being drawn, 21 scanlines by 8 character rows (total 168 scanlines) being drawn and no, there are no WSYNC for the whole kernel at this stage of the frame draw. There's a bit of bank magic happening; the same code resides in different banks, and the final bank has a difference: a RTS which lets the draw 'break out' of the loop. It means that there is no comparison needed for a loop counter as to how many character lines to draw. It just automatically finishes when it switches to the bank with the RTS. Neat 2 Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted September 9, 2016 Share Posted September 9, 2016 They've got other amazing things in their too. From what little I understand they put in task scheduling so if a particular action would go over-cycle it's delayed until next frame. O_O Close. The delay is until the next bit of free time *within a frame*. A frame has a few places where stuff can be done (i.e., where it's using an INTIM wait). Each task has a known-time-to-complete, so the INTIM counter is used to determine if there's time enough to do that action. If not, then other actions which are less time consuming may or may not be executed instead, and the longer one will get a "look-in" ASAP when there's time to accomodate its needs. 2 Quote Link to comment Share on other sites More sharing options...
Mr SQL Posted September 9, 2016 Share Posted September 9, 2016 That section shows the basic triplet colour lines being drawn, 21 scanlines by 8 character rows (total 168 scanlines) being drawn and no, there are no WSYNC for the whole kernel at this stage of the frame draw. There's a bit of bank magic happening; the same code resides in different banks, and the final bank has a difference: a RTS which lets the draw 'break out' of the loop. It means that there is no comparison needed for a loop counter as to how many character lines to draw. It just automatically finishes when it switches to the bank with the RTS. Neat Pretty cool! That 168 scanline block is most of the screen, where else do you find time for the task queue besides the top and bottom vertical blanks? 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.