+Andrew Davie Posted June 1, 2003 Share Posted June 1, 2003 The diagram below shows the bizarre way that bits in the TIA playfield registers (PF0, PF2) map to the onscreen pixels in reverse order. We have already seen how PF1 works - it is shown in this diagram, too. This strange backwardness (not to mention inconsistency!) is probably a result of the fact that it was simpler (cheaper) to design the hardware to operate in this fashion. Among other things, this layout of pixels in our TIA registers makes scrolling horizontally a major pain in the neck! The bits marked with a cross are not used by the '2600 (including the low bit in the colour registers), and you may write any value to these - it is ignored. The diagram shows a shadowy "right-side" - where the 20 pixels of the left side are duplicated. Be aware that this right-side may also be mirrored, further complicating things. 1 Quote Link to comment Share on other sites More sharing options...
Happy_Dude Posted June 1, 2003 Share Posted June 1, 2003 Any exercises ? Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted June 1, 2003 Author Share Posted June 1, 2003 Any exercises ? I'll be delivering this session in stages. I'll give some exercises once I've gotten through the explanations. If you want to play with some things then.... 1. Confirm that PF0 and PF2 have reverse pixel to bit position ordering (Hint: using binary for your values will assist you to see exactly what pixel corresponds to what bit (ie: lda #%01000000, sta PF0) 2. What happens if you write PF0, PF1 or PF2 in the middle of a scanline? What would you expect to happen? Can you see any use for this? (Hint: how do you think an asymmetric playfield - a different pattern on the left and right of the screen - is created?) 3. Write some solid shape(s) to PF0, PF1, PF2 (ie: lda #%01011110, sta PF0, sta PF1, sta PF2) and then play with changing the playfield colour several times during a scanline. How many colour changes (maximum) do you think you can get on any line? Why is there a limit? 4. How would a game do horizontal scrolling? This is a difficult question - but I'm trying to get you to think about the implications of the odd playfield->pixel correspondence, and the implications for game writing. 5. How would you make a "wall" which was 8 scanlines high, full screen width, followed by left and right walls just 1 pixel wide each, at extreme left/right edges of the screen, 176 scanlines high, followed by another horizontal "wall", full screen width and 8 scanlines high? Note: this would form a "box" border around the entire playfield. There we go, that should keep you busy! I'll answer last sessions sessions with example code, shortly. Quote Link to comment Share on other sites More sharing options...
Happy_Dude Posted June 1, 2003 Share Posted June 1, 2003 1: write same value to both PF0 and PF1 lda #%00100000 sta PF1 sta PF0 2: add during scanline sleep 40 lda #%00010000 sta PF2 Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted June 1, 2003 Author Share Posted June 1, 2003 1: write same value to both PF0 and PF1 lda #%00100000 sta PF1 sta PF0 2: add during scanline sleep 40 lda #%00010000 sta PF2 Happy, if you do these exercises and post your results... please explain in detail what you think you are doing/seeing. It will help others (rather than just pictures and code snippets), and also let me see if you're on the right track. The above samples... don't let me determine that. In short, a bit more blurb, thanks. Cheers A Quote Link to comment Share on other sites More sharing options...
Happy_Dude Posted June 1, 2003 Share Posted June 1, 2003 Alrighty then I fixed the code to be more obvious 1: lda #%10000000 sta PF1 sta PF0 This is showing the relation between PF1 and PF0. both in their 1st position. (now) They appear as 1 line (because PF0's 1st position is really it's last ) 2: sleep 40 lda #%00010000 sta PF2 I really didn't think this one through. If you change halfway through the scan, you'll have to change back at the begining or end of the scan lda #%000100000 sta PF1 sta PF0 sleep 12 lda #%00011100 sta PF0 sta PF1 This code changes the playfield mid scan and does what I thought the first bit of code was doing. Because its iterated 192 times it needs to load each side of the playfield on every pass... well hows that for a second attempt ? Quote Link to comment Share on other sites More sharing options...
Happy_Dude Posted June 5, 2003 Share Posted June 5, 2003 Oh yeah I got a "playfield" working It's ugly but it works ;------------------------------------------------ ;Top line lda #15 ; A nice whitish colour sta COLUPF lda #%11111111 ; Fill the whole playfield sta PF0 ; left sta PF1 ; mid sta PF2 ; right sta WSYNC sta WSYNC sta WSYNC sta WSYNC sta WSYNC sta WSYNC sta WSYNC sta WSYNC ; make it 8 scanlines please lda #%00000000 ; Reset Playfield sta PF1 sta PF2 ;------------------------------------------------ ;Side lines Picture lda #15 ; load up the white sta COLUPF lda #%00010000 ; PF0's left sta PF0 sleep 2 ; wait for it to draw lda #$0 sta COLUPF ; then kill it sleep 25 ; for 25 cycles lda #15 ; mmmm White sta COLUPF ; Colour Ready to draw some more. lda #%10000000 ; PF2's right sta PF2 ; Now draw the right side and sta WSYNC ; Snooze for the rest of the scanline inx cpx #176 bne Picture ;------------------------------------------------ ;bottom line - same as top (GOTO TOP to read comments :P ) lda #15 sta COLUPF lda #%11111111 sta PF0 sta PF1 sta PF2 sta WSYNC sta WSYNC sta WSYNC sta WSYNC sta WSYNC sta WSYNC sta WSYNC sta WSYNC lda #%00000000 sta PF1 sta PF2 As for horizontal scrolling - I wish I knew Quote Link to comment Share on other sites More sharing options...
Galaga_Freak Posted June 6, 2003 Share Posted June 6, 2003 Finally got this to work on a real tv with no flipping ;Scrolling color border thingy processor 6502 include "vcs.h" include "macro.h" COUNTER1 = $80 COLOROFFSET = $81 TIMETOCHANGE = 2 ; speed of "animation" SEG ORG $F000 Reset ; Clear RAM and all TIA registers ldx #0 lda #0 Clear sta 0,x inx bne Clear ;------------------------------------------------ ; Once-only initialisation... lda #0 ;lda #$45 sta COLUPF ; set the playfield colour StartOfFrame ; Start of vertical blank processing lda #0 sta VBLANK lda #2 sta VSYNC ; 3 scanlines of VSYNCH signal... sta WSYNC sta WSYNC sta WSYNC lda #0 sta VSYNC ; 37 scanlines of vertical blank... ldx #0 VerticalBlank sta WSYNC inx cpx #36; Now waiting 36 lines bne VerticalBlank ;do some color offset calcs ldx #$02 stx COLUBK;redundant as we never change COLUBK, but... :) ldx #0 ldy COUNTER1 cpy #TIMETOCHANGE bne notyet inc COLOROFFSET ldy COLOROFFSET lda #0 sta COUNTER1 notyet inc COUNTER1 ldy COLOROFFSET sta WSYNC ; wait for last line of vblank DrawField Top sty COLUPF lda #$FF sta PF0 sta PF1 sta PF2 lda #0 inx iny sta WSYNC cpx #15 bne Top SLEEP 3 ; sync up middle Middle sty COLUPF lda #$F0 sta PF0 lda #0 sta PF1 sta PF2 lda #0 SLEEP 15 sta PF0 lda #$F0 sta PF2 lda #0 sta WSYNC inx iny cpx #177 bne Middle Bottom sty COLUPF lda #$FF sta PF0 sta PF1 sta PF2 sta WSYNC inx iny cpx #192 bne Bottom lda #%01000010 sta VBLANK ; end of screen - enter blanking ldx #0 stx COLUPF Overscan sta WSYNC inx cpx #30 bne Overscan jmp StartOfFrame ORG $FFFA .word Reset ; NMI .word Reset ; RESET .word Reset ; IRQ END Now this has worked for a while on the emulators, but I came to discover that my vblank period was off because of the offset code which I assume put the rest of the frame out of sync slightly each pass which eventually caused the screen to hop or roll on a real tv (using cuttle cart). I fixed this once but then noticed that my scanline count was 264 not 262 as the code above produces. This actually worked on my tv, so my question is: How far out of the range of 262 can you be for the game to work on most tvs (NTSC) or is it a matter of the atari used (jr vs 4 switcher for example)? Also, is there a way to reproduce the effects (flipping, etc) on an emulator that you would see on a tv other than counting scanlines? Quote Link to comment Share on other sites More sharing options...
Happy_Dude Posted June 6, 2003 Share Posted June 6, 2003 I'd like to know how that works with 384 in picture scanlines ? I was under the impression stella only had 242 scanlines at the most (pal) Quote Link to comment Share on other sites More sharing options...
Galaga_Freak Posted June 6, 2003 Share Posted June 6, 2003 I'd like to know how that works with 384 in picture scanlines ?I was under the impression stella only had 242 scanlines at the most (pal) Where did you get 384? There's 3 vsych + 37 vblank + 192 picture + 30 overscan = 262 total scanlines of which only 192 are visible Quote Link to comment Share on other sites More sharing options...
Happy_Dude Posted June 6, 2003 Share Posted June 6, 2003 I'd like to know how that works with 384 in picture scanlines ?I was under the impression stella only had 242 scanlines at the most (pal) Where did you get 384? There's 3 vsych + 37 vblank + 192 picture + 30 overscan = 262 total scanlines of which only 192 are visible Mabey I'm reading it wrong but .... Top sty COLUPF lda #$FF sta PF0 sta PF1 sta PF2 lda #0 inx iny sta WSYNC cpx #15 bne Top SLEEP 3 ; sync up middle Middle sty COLUPF lda #$F0 sta PF0 lda #0 sta PF1 sta PF2 lda #0 SLEEP 15 sta PF0 lda #$F0 sta PF2 lda #0 sta WSYNC inx iny cpx #177 bne Middle Bottom sty COLUPF lda #$FF sta PF0 sta PF1 sta PF2 sta WSYNC inx iny cpx #192 bne Bottom 15 lines for the top 177 scanlines for the middle and 192 for the bottom = 384 not including overscan and vblank. Quote Link to comment Share on other sites More sharing options...
Galaga_Freak Posted June 6, 2003 Share Posted June 6, 2003 Ahh, I see how you got that number now. The x index register is never reset so after the top is done x = 15, after middle x = 177 after bottom x = 192. Basically it is the counter for the entire visible portion, not individual portions of the visible screen. :wink: Quote Link to comment Share on other sites More sharing options...
Happy_Dude Posted June 6, 2003 Share Posted June 6, 2003 I see now Quote Link to comment Share on other sites More sharing options...
Happy_Dude Posted June 6, 2003 Share Posted June 6, 2003 Galaga_Freak if COLUBK is never changed you should initalize it after Clear and before StartOfFrame. No use doing it once every frame I cleaned my code up a bit. There was a lot of weirdness going on. ;------------------------------------------------ ;Top line lda #%11111111 ;fill playfield sta PF0 sta PF1 sta PF2 lda #15 ; It looks like white sta WSYNC ; all thats visable so wait sta COLUPF ; before writing the line sta WSYNC sta WSYNC sta WSYNC sta WSYNC sta WSYNC sta WSYNC sta WSYNC ; Give me 7 lda #%00000000 ; Clear the 2 PF's that arn't PF0 sta PF1 sta PF2 ;------------------------------------------------ ;Side lines Picture lda #15 ; Re-initalize whiteness sta COLUPF lda #%00010000 ; And PF0 sta PF0 sleep 2 ; let it write lda #$0 ; now get rid of the damn thing sta COLUPF sleep 25 ; and wait until the reflected bit has been written black lda #15 ; and Re-initalize the colour (again) sta COLUPF lda #%10000000 ; Line up PF2 sta PF2 sta WSYNC ; wait till end of scanline inx cpx #176 bne Picture ; do it till it's done ;------------------------------------------------ ;bottom line (yadda yadda yadda...) lda #15 sta COLUPF lda #%11111111 sta PF0 sta PF1 sta PF2 sta WSYNC sta WSYNC sta WSYNC sta WSYNC sta WSYNC sta WSYNC sta WSYNC sta WSYNC lda #$0 ; Clear to return sta COLUPF Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted June 6, 2003 Share Posted June 6, 2003 This actually worked on my tv, so my question is: How far out of the range of 262 can you be for the game to work on most tvs (NTSC) or is it a matter of the atari used (jr vs 4 switcher for example)? That's a question hard to answer. The scanline range of NTSC games I have seen so far is somewhere between 241 (Artillery Duel, a few people have reported problems here!) and ~280 scanlines (e.g. Desert Falcon). And many TV (especially with a vertical hold) can even display PAL games (standard: 312 scanlines, but there are some with up to 342 scanlines like Acid Drop). So I assume +/- 15..20 scanlines should be no problem. Quote Link to comment Share on other sites More sharing options...
8BIT 1337 Posted June 6, 2003 Share Posted June 6, 2003 That's a question hard to answer. The scanline range of NTSC games I have seen so far is somewhere between 241 (Artillery Duel, a few people have reported problems here!) and ~280 scanlines (e.g. Desert Falcon). And many TV (especially with a vertical hold) can even display PAL games (standard: 312 scanlines, but there are some with up to 342 scanlines like Acid Drop). So I assume +/- 15..20 scanlines should be no problem. This might be a stupid question, but does altering the number of scanlines affect the number of FPS displayed? Seems to me that if you went with, say, 280 scanlines (keeping 192 for the picture), that the FPS would drop below 60. Or is there something else that comes into play that I'm not aware of? (I'm just talking NTSC numbers here). Another semi-related question - what if I decided to 'use' all my overscan time under VBlank? Why do the non-picture scanlines get split before/after the picture? (Or is that just a best practices standard - if so, what game(s) have done this out of curiousity?) Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted June 6, 2003 Share Posted June 6, 2003 This might be a stupid question, but does altering the number of scanlines affect the number of FPS displayed? Seems to me that if you went with, say, 280 scanlines (keeping 192 for the picture), that the FPS would drop below 60. Yup, exactly! You can calculate that quite easily: Artillery Duel: 60/241*262 = ~65Hz Demon Falcon: 60/280*262 = ~56Hz PAL games: 60/312*262 = ~50Hz Another semi-related question - what if I decided to 'use' all my overscan time under VBlank? Why do the non-picture scanlines get split before/after the picture? This is done to center the visible part on the screen. After OverScan we are doing a Vertical Sync to bring the beam back to the top of the screen. So both parts (called Overscan and VBLank) below and above the visible area are about the same size. Quote Link to comment Share on other sites More sharing options...
8BIT 1337 Posted June 6, 2003 Share Posted June 6, 2003 This is done to center the visible part on the screen. After OverScan we are doing a Vertical Sync to bring the beam back to the top of the screen. So both parts (called Overscan and VBLank) below and above the visible area are about the same size. I understand what you're saying, but I've played with this a bit (I had a simple playfield with only one scanline of overscan, the rest under VBLANK) and the image was still centered as far as I can tell. Was that 'cause I was using an emulator? Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted June 6, 2003 Share Posted June 6, 2003 I understand what you're saying, but I've played with this a bit (I had a simple playfield with only one scanline of overscan, the rest under VBLANK) and the image was still centered as far as I can tell. Did you increase the VBlank time then and still had 262 scanlines? If you only cut some blank lines at the bottom you won't notice that. Quote Link to comment Share on other sites More sharing options...
8BIT 1337 Posted June 6, 2003 Share Posted June 6, 2003 Did you increase the VBlank time then and still had 262 scanlines? If you only cut some blank lines at the bottom you won't notice that. Yup - I made sure my total scanlines were still 262 (using z26 to verify my math was correct). Seems like it would be simpler to use the 67 scanlines all together in one place instead of splitting code up into the 37 VBlank and 30 Overscan portions. Generally speaking of course. Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted June 6, 2003 Share Posted June 6, 2003 Looks like the emulator did some centering then. Definitely won't work that way on the real thing. Quote Link to comment Share on other sites More sharing options...
dew2050 Posted June 6, 2003 Share Posted June 6, 2003 Any exercises ? 4. How would a game do horizontal scrolling? This is a difficult question - but I'm trying to get you to think about the implications of the odd playfield->pixel correspondence, and the implications for game writing. I modified the kernel code to use ASL commands to shift the bits in my playfield variable to the left. Since I didn't want the playfield to repeat itself twice on the screen, I added a second variable to the original kernel lesson sample. The code only uses PF0 to draw the screen. The result is that the playfield scrolls horizontally from left to right, jumping the center and edges of the screen (everything else not drawned by PF0). The scrolling feels a lot like Vanguard. It's not smoothy like say, Chopper Command. I think for that you would need to use the HMOVE register with something other than the playfield, but that's ok for now. On PCAEWIN it works fine, but on Z26 it draws some garbage at the top of the screen. Take a look at the code: ; 2600 for Newbies ; lesson 14 - playfield ; Question 4 - One way to do horizontal scrolling with the playfield. processor 6502 include "vcs.h" include "macro.h" ; OBJECTIVE: This variation of the lesson 14 kernel does horizontal scrolling with the playfield. ; Only PF0 is used. The program uses to variables to store the left and right side values ; of the playfield. These are declared below: PATTERN_LEFT = $80 PATTERN_RIGHT = $82 TIMETOCHANGE = 20 SEG ORG $F000 RESET ; Clear RAM and all TIA regs LDX #0 LDA #0 CLEAR STA 0,X INX BNE CLEAR LDA #$45 STA COLUPF LDY #0 ; Here we assign the pattern values to our left and right side of the playfield. ; Try using different values. LDA #$0 STA PATTERN_LEFT LDA #$01 STA PATTERN_RIGHT STARTOFFRAME LDA #0 STA VBLANK LDA #2 STA VSYNC STA WSYNC STA WSYNC STA WSYNC LDA #0 STA VSYNC ; 37 scanlines of vertical blank LDX #0 VERTICALBLANK STA WSYNC INX CPX #37 BNE VERTICALBLANK ; HANDLE A CHANGE IN THE PATTERN ONCE EVERY 20 FRAMES ; WRITE THE PATTERN TO PF1 INY CPY #TIMETOCHANGE BNE SCROLLCOMPLETE LDY #0 ; The following code uses arithmetic left shift commands (ASL) to make the scrolling happen. ; We shift the bits of the playfield variables to the left. Original bit 7 is shifted to the Carry. ; The program uses BCC to check if a bit was dropped. Dropped bits are inserted to the ; opposite pattern variable by the INC command. The INC command can mess up the pattern if ; the original bit 0 is turned on. To avoid this we shift everything to the left before incrementing. SHIFTRIGHT CLC ASL PATTERN_RIGHT BCC SHIFTLEFT ASL PATTERN_LEFT INC PATTERN_LEFT BCC SCROLLCOMPLETE INC PATTERN_RIGHT JMP SCROLLCOMPLETE SHIFTLEFT ASL PATTERN_LEFT BCC SCROLLCOMPLETE INC PATTERN_RIGHT SCROLLCOMPLETE ; DO 192 SCANLINES OF COLOR CHANGING (OUR PICTURE) LDX #0 PICTURE STX COLUPF ; Load the left pattern into PF1 register. LDA PATTERN_LEFT STA PF1 ; Wait enough cycles before drawing right pattern. SLEEP 20 ; Load right pattern to PF1. LDA PATTERN_RIGHT STA PF1 STA WSYNC INX CPX #192 BNE PICTURE LDA #%01000010 STA VBLANK ; 30 LINES OF OVERSCAN LDX #0 OVERSCAN STA WSYNC INX CPX #30 BNE OVERSCAN JMP STARTOFFRAME ORG $FFFA INTERRUPTVECTORS .WORD RESET .WORD RESET .WORD RESET END The tricky code is the bit shifting. Here is the pseudocode: [color=blue]; Pseudocode: ; ; Clear Carry ; Shift bits in variable PATTERN_RIGHT to the left. Original bit 7 is shifted into the Carry. ; ; if no bit was dropped from PATTERN_RIGHT (Carry Clear) then ; ; Shift the bits in PATTERN_LEFT ; if no bit was dropped from PATTERN_LEFT then ; ; Scroll is complete. Continue program flow. ; ; else ; ; Insert dropped bit from left pattern into PATTERN_RIGHT (Using the INC command). ; ; end ; ; else ; ; Shift bits in PATTERN_LEFT ; Insert dropped bit from right pattern into PATTERN_LEFT. ; If no bit was dropped from PATTERN_LEFT then ; ; Scroll is complete. ; ; else ; ; Insert dropped bit from left pattern into PATTERN_RIGHT. ; ; end ; ; end[/color] This translates to: SHIFTRIGHT CLC ASL PATTERN_RIGHT BCC SHIFTLEFT ASL PATTERN_LEFT INC PATTERN_LEFT BCC SCROLLCOMPLETE INC PATTERN_RIGHT JMP SCROLLCOMPLETE SHIFTLEFT ASL PATTERN_LEFT BCC SCROLLCOMPLETE INC PATTERN_RIGHT SCROLLCOMPLETE I am sure there is a better way of doing this without so many BCC's and ASL's (perhaps getting rid of the JMP altogether). question4.zip Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted June 7, 2003 Share Posted June 7, 2003 I am sure there is a better way of doing this without so many BCC's and ASL's (perhaps getting rid of the JMP altogether). Hint: Have a look at ROL. This will make your code much simplier. Quote Link to comment Share on other sites More sharing options...
Zach Posted June 7, 2003 Share Posted June 7, 2003 Thanks Andrew, It took me a lot of frustrating trial and error before I concluded that the bits in PF2 were displayed in reverse. I'm glad someone is making the TIA's quirks clear. Zach Quote Link to comment Share on other sites More sharing options...
dew2050 Posted June 7, 2003 Share Posted June 7, 2003 I am sure there is a better way of doing this without so many BCC's and ASL's (perhaps getting rid of the JMP altogether). Hint: Have a look at ROL. This will make your code much simplier. Thanks Thomas. With your help I was able to take this: CLC ASL PATTERN_RIGHT BCC SHIFTLEFT ASL PATTERN_LEFT INC PATTERN_LEFT BCC SCROLLCOMPLETE INC PATTERN_RIGHT JMP SCROLLCOMPLETE SHIFTLEFT ASL PATTERN_LEFT BCC SCROLLCOMPLETE INC PATTERN_RIGHT SCROLLCOMPLETE Into this: CLC ROL PATTERN_RIGHT ROL PATTERN_LEFT BCC SCROLLCOMPLETE INC PATTERN_RIGHT SCROLLCOMPLETE Wow, what a difference ROL makes! I am glad I did it the hard way first, otherwise I wouldn't had appreciated the difference. I have a newbie assembler question: How many machine cycles does the ROL commands above take? Is it 5 for zero page? 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.