+Andrew Davie Posted June 27, 2003 Share Posted June 27, 2003 The following diagram shows the timing relationship between the TIA, the 6502, and playfield pixels. Further, it shows the times at which it is safe to write the playfield registers for both left and right-sides of the screen. Link to comment Share on other sites More sharing options...
rixard Posted June 27, 2003 Share Posted June 27, 2003 I have been reading these lessons for a couple of days now. I'm starting to learn a few things here... a few things there It's so great you're doing this. Why not eventually show how to move sprites, how to implement simple routines (enemies moving towards the player, collision checks) or more simply... show how to make a simple game and explain everything.Step by step Link to comment Share on other sites More sharing options...
Pitfall Harry Posted June 27, 2003 Share Posted June 27, 2003 The graphic certainly lives up to its namesake. It truly is an "Incredibly Good Timing Diagram." The only thing I'd add to the diagram is an annotation or a footnote stating that a write to the WSYNC register halts the microprocessor until the TIA gets to time zero, the start of the Horizontal Blanking period. I was confused over this "obvious" fact for the longest time, thinking the microprocessor resumed execution immediately AFTER the 68 color clocks of Horizontal Blanking. Ben Link to comment Share on other sites More sharing options...
Happy_Dude Posted June 27, 2003 Share Posted June 27, 2003 The graphic certainly lives up to its namesake. It truly is an "Incredibly Good Timing Diagram." The only thing I'd add to the diagram is an annotation or a footnote stating that a write to the WSYNC register halts the microprocessor until the TIA gets to time zero, the start of the Horizontal Blanking period. I was confused over this "obvious" fact for the longest time, thinking the microprocessor resumed execution immediately AFTER the 68 color clocks of Horizontal Blanking. Ben Thanks I was just about to ask that one Link to comment Share on other sites More sharing options...
Emehr Posted June 27, 2003 Share Posted June 27, 2003 Excellent diagram. Now I have something to compare to my sketches! Keep up the great work, Andrew. I'm lovin' this tutorial and have been following it closely. Right now I have an animated sprite that can run around the screen. When he gets above the "horizon" his sprite goes into jump mode, although you can still move him around like he were walking...sort of a Crouching Tiger, Hidden Dragon thing. Thanks! Jason Rein Link to comment Share on other sites More sharing options...
+Andrew Davie Posted June 27, 2003 Author Share Posted June 27, 2003 Why not eventually show how to move sprites, how to implement simple routines (enemies moving towards the player, collision checks) or more simply... show how to make a simple game and explain everything.Step by step Patience, young Jedi master! All things will be revealed to those who seek the way. Link to comment Share on other sites More sharing options...
Sheldon Sims Posted June 28, 2003 Share Posted June 28, 2003 I am also enjoying this tutorial. You are doing a great job on it. I am spending most of my time away from work following this tutorial. I can't get away from it. It is challenging, yet fun. Keep up the good work. Link to comment Share on other sites More sharing options...
rixard Posted June 28, 2003 Share Posted June 28, 2003 I shall wait master I'm thinking of converting a little game I wrote in BASIC to the Atari 2600. The game was called NEOBYKE and was based on the lightcycles in the movie TRON. So I'm trying to learn 6502(6507) assembly to get the job done In a way it's much more fun program for a console like the 2600. I mean, anyone can write a game for the PC but it'll just drown with 1000s of other similar games. And besides, the 2600 is quite a beast and being able to tame it... well then I suppose you COULD call yourself a jedi master Keep up the good work. Link to comment Share on other sites More sharing options...
+Andrew Davie Posted July 1, 2003 Author Share Posted July 1, 2003 Thomas Jentzsch has pointed out that there is a mimimum delay before a change to a TIA playfield register becomes visible. He suggests ~2 TIA clocks. When one considers that a 6502 instruction may take anywhere from 2 cycles (=6 TIA colour clocks) to 7 cycles, it is apparent that any particular 6502 instruction "occupies" a fairly wide slice of TIA time during its execution. All instructions require a fetch of the opcode (=6502 instruction) from memory, the decoding and execution of that instruction, and sometimes a write of data back to memory. These stages of 'execution' of an instruction happen at various times during the time taken to execute the entire instruction. For example, the first cycle of the total instruction time might be allocated to retrieving the opcode from ROM. The second might be allocated to decoding and executing some of the instruction. Truth be told, I'm not really sure what happens when - it will differ for each of the instructions and addressing (=access to memory) modes. The point is, though, that when we write to the TIA playfield registers (or any other register for that matter), one may have to make allowances for the fact that although you may start an instruction on a particular TIA / 6502 clock cycle, the actual write to the TIA memory/register will most definitely not happen until 2 or more cycles later - and that depends on the addressing mode. We will cover addressing modes later - but basically they deal with ways of accessing memory (eg: directly, indirectly via pointers, via a list (indexec), etc). The timing diagram above should be considered to indicate the time at which TIA playfield registers must be updated by, for correct playfield data to be displayed. Another issue altogether - and one I simply don't know the answer to right now - is *EXACTLY* what happens when you write to a playfield register when that playfield register is currently being displayed. I am not sure exactly what timing constraints determine which pixel is displayed in which situation - the old or the new. Thomas has also indicated that there are some reports of consoles behaving differently when you get into this sort of extreme 'pushing the envelope' timing, too. Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted July 1, 2003 Share Posted July 1, 2003 I am sure the emulator programmers know the exact answers. Eckhard? Link to comment Share on other sites More sharing options...
Eckhard Stolberg Posted July 1, 2003 Share Posted July 1, 2003 On the Atari VCS you can't change the state of a playfield pixel while it is being processed. So, for example, you could write the data for the right copy of PF2 while the last pixel of the left copy PF2 is still being displayed. This pixel will stay on or off, even if the new value is the opposite of it's current state. You can however change the colour of a playfield pixel while it is diplayed. The colour information is evaluated ion a TIA-pixel by TIA-pixel basis. So if you wrote to COLUPF in such a way that the write finishes halfway though a playfield pixel, then it's first two TIA-pixels will have the old colour and it's last two TIA-pixels will have the new colour. I have heard reports that the Coleco expansion module behaves a bit differently when rewriting playfield registers, but I don't know the exact timing either. Ciao, Eckhard Stolberg Link to comment Share on other sites More sharing options...
SmileyDude Posted July 1, 2003 Share Posted July 1, 2003 So, from what Eckhard is saying, it sounds as if the TIA latches the value of the PFx register when it starts drawing, and uses that value, even if the original value changes. Does that sound right? BTW, I've been working off the assumption that as long as the instruction finishes on or before the cycle on the chart, that should be fine. For example, PF0 finishes at 6502 cycle 28, so as long as my STA PF0 finishes at cycle 28 or later, it should be fine. But, I've been waiting for the TIA to finish drawing a particular portion of the playfield (i.e, I'm stuffing the values into the registers as early as I possibly can, and I'm just waiting for the register to be free again), so my assumptions may be completely wrong. And considering what Eckard said, it might not matter anyway So, does anyone know for certain how the timing works for these fringe cases? If I reverse my example above, if I have a STA PF1 that takes 3 cycles, and I start it on 6502 cycle 25, since it finished on cycle 28, will that display properly? Logically, it should work since the instruction is finished at cycle 28, and the TIA shouldn't be drawing until when cycle 29 begins... Link to comment Share on other sites More sharing options...
SmileyDude Posted July 2, 2003 Share Posted July 2, 2003 Dang it -- I just re-read Eckards post... the TIA appears to be latching a single pixel, not the entire value of PFx, right? That actually makes more sense when I look at it Link to comment Share on other sites More sharing options...
dew2050 Posted July 2, 2003 Share Posted July 2, 2003 As our knowledge of playfield manipulation increases, so does the desire to create more complex backgrounds. What are the best tools to design playfields? I think someone mentioned not so long ago the use of an Excel spreadsheet as a huge grid map. If there is any experienced homebrewer out there reading this: what have worked best for you? Link to comment Share on other sites More sharing options...
+Andrew Davie Posted July 2, 2003 Author Share Posted July 2, 2003 As our knowledge of playfield manipulation increases, so does the desire to create more complex backgrounds. What are the best tools to design playfields? I think someone mentioned not so long ago the use of an Excel spreadsheet as a huge grid map. If there is any experienced homebrewer out there reading this: what have worked best for you? I draw my stuff in a paint program, save it out as a 40 x 192 pixel file (or whatever depth you like) and run it through a tool written for the purpose. This tool creates tables of data which can be simply copied to the screen as required. I'm happy to share it - but it's not that tricky to write your own. Link to comment Share on other sites More sharing options...
Eckhard Stolberg Posted July 2, 2003 Share Posted July 2, 2003 Dang it -- I just re-read Eckards post... the TIA appears to be latching a single pixel, not the entire value of PFx, right? That actually makes more sense when I look at it This is correct. If you change a playfield register while the third playfield pixel is currently being displayed, then the first three playfield pixels will be taken from the old value in the playfield register, and the last five playfield pixels will be taken from the new value. Ciao, Eckhard Stolberg Link to comment Share on other sites More sharing options...
EricBall Posted July 3, 2003 Share Posted July 3, 2003 This is correct. If you change a playfield register while the third playfield pixel is currently being displayed, then the first three playfield pixels will be taken from the old value in the playfield register, and the last five playfield pixels will be taken from the new value. Which TIA cycle does the 6507 write cycle "complete" on? The last third, I think, right? Link to comment Share on other sites More sharing options...
Eckhard Stolberg Posted July 3, 2003 Share Posted July 3, 2003 I'm not quite sure if I understand your question correctly. Is it about the relation between the TIA clock and the processor clock? There are three TIA cycles for every CPU cycle. The CPU dosn't do anything between the cycles it gets clocked with, so CPU write cycles (like all other CPU cycles too) happen on every third TIA cycle. If you'd do something like: sta WSYNC nop nop nop nop nop nop nop nop nop nop sta COLUBK then the background colour would change after the first TIA pixel has already been drawn, because the STA COLUBK would finisch it's write cycle at CPU cycle 23 (which is TIA cycle 69, which is one TIA cycle after the horizontal blank period). Ciao, Eckhard Stolberg Link to comment Share on other sites More sharing options...
EricBall Posted July 5, 2003 Share Posted July 5, 2003 then the background colour would change after the first TIA pixel has already been drawn, because the STA COLUBK would finisch it's write cycle at CPU cycle 23 (which is TIA cycle 69, which is one TIA cycle after the horizontal blank period). Thanks, that was the info I was looking for. Link to comment Share on other sites More sharing options...
dew2050 Posted July 7, 2003 Share Posted July 7, 2003 The assymmetric chart has been extremely helpful to me. I first read about the timing quirk in "How to draw an assymetrical playfield" source sample at The Dig but never fully understood it until now. Here is the stuff I did: Sample1.zip is a mockup of the Donkey Kong stage. Sample2.zip is the Atari Age banner, 2600 style For the last one I changed the PF color once per frame right before the text logo for a simple color cycling effect. While doing this I found myself thinking where to "put it". I needed 9 free cpu cycles that wouldn't interfere with the PF writing code. After some trial and error I put it somewhere at beginning of the scan loop. 1) Is it possible to create the data tables in a separate text file and have it inserted into our program as an 'include "mypfdata.h"'? 2) I used PF data tables to draw my assymetrical playfields. The data is for every scanline in the visible kernel. The drawings I did have empty spaces at the top and bottom. This translates into a lot of zero byte entries, that takes valuable ROM space. I could shave off those data lines and adjust the kernel code accordingly. Is there is another way? sample2.zip sample1.zip Link to comment Share on other sites More sharing options...
Christopher Tumber Posted July 7, 2003 Share Posted July 7, 2003 1) Is it possible to create the data tables in a separate text file and have it inserted into out program as an 'include "mypfdata.h"'? Yes. That's really all the line: include vcs.h does. 2) I used PF data tables to draw my assymetrical playfields. The data is for every scanline in the visible kernel. The drawings I did have empty spaces at the top and bottom. This translates into a lot of zero byte entries, that takes valuable ROM space. I could shave off those data lines and adjust the kernel code accordingly. Is there is another way? Yes, there's always another way. Here are a couple suggestions... If the blank lines are a known constant, then at the top and bottom of the screen (ie: Before and after you actually start drawing) you can add something like: lda #10 nextblank: sta WSYNC dex bpl nextblank where #10 is the number of blank lines you need. If the number of blank lines is not constant (ie: You're writing a general purpose screen display routine that could display any of several different "bitmaps") then you can turn taht #10 into a variable. Or, you could include it all in your graphics data like: ldy GraphicsData ;Get number of blank lines at top nextblankline1: sta WSYNC dey bne nextblankline1 ldx #0;Index of graphics data ldy GraphicsData+1 nextdrawline: sta WSYNC lda GraphicsData1,x sta PF0 lda GraphicsData2,x sta PF1 lda GraphicsData3,x sta PF2 nop ;Some NOPs in here, I'm not going to cycle count nop lda GraphicsData4,x sta PF0 lda GraphicsData5,x sta PF1 lda GraphicsData6,x sta PF2 inx dey bne nextdrawline ldy GraphicsData+2 ;Get number of blank lines at bottom nextblankline2: sta WSYNC dey bne nextblankline2 GraphicsData: .byte 20;10 blank lines at top .byte 150;150 lines of graphics .byte 22;22 blank lines at bottom GraphicsData1: .byte ;150 bytes of data for left PF0 GraphicsData2: .byte ;150 bytes of data for left PF1 GraphicsData3: .byte ;150 bytes of data for left PF2 GraphicsData4: .byte ;150 bytes of data for right PF0 GraphicsData5: .byte ;150 bytes of data for right PF1 GraphicsData6: .byte ;150 bytes of data for right PF2 You can further abstract that by using indexed indirect addressing: lda (),y but that should wait until Andrew explains the more advanced addressing modes... Chris... Link to comment Share on other sites More sharing options...
dew2050 Posted July 8, 2003 Share Posted July 8, 2003 When I place the include command (for PF data) at the beginning of the asm file, right after the macro.h and vcs.h includes, dasm gives me errors. If I put it where the data tables would usually be (before the org $fffa) it works fine though. Why doesn't dasm allows this? Here is a quote of the dasm results: 9 references to unknown symbols.7 events requiring another assembler pass. - Expression in mnemonic not resolved. - Obscure reason - to be documented --- Unresolved Symbol List NO_ILLEGAL_OPCODES 0000 ???? (R ) PFData0A 10000 ???? (R ) PFData0B 100a7 ???? (R ) PFData1A 10037 ???? (R ) PFData1B 100df ???? (R ) PFData2A 1006f ???? (R ) PFData2B 10117 ???? (R ) --- 7 Unresolved Symbols Link to comment Share on other sites More sharing options...
Christopher Tumber Posted July 8, 2003 Share Posted July 8, 2003 When I place the include command (for PF data) at the beginning of the asm file, right after the macro.h and vcs.h includes, dasm gives me errors. Yes, because the assembler tries put the included file right where you have the INCLUDE command which in this case is before all the rest of your code. And given it's probably before any ORG statements this is a real problem! (The assembler doesn't know where to put the PFData tables). An include file consisting entirely of label definitions and/or macros is the only include file you're going to put at the very top with VCS.H and MACROS.H. Labels and macros don't really care because they aren't "anchored" to any specific place in ROM. However any code or data must be put in a specific ROM location. In other words, include File1 include File2 include File3 Will give you a completely different result than: include File3 include File2 include File1 Just like: lda #$10 sta $80 Is completely different from: sta $80 lda #$10 All the INCLUDE command does is drop the included file directly in that spot. If you put everything back into one file like it was originally, would it make a difference if you moved all those PFData tables to the very start of your code? That's what you did by putting the include up there. If you have to, think of an include file as a super label. So just as: TMP EQU $80 LDA TEMP is really just: LDA $80 because the label TEMP gets replaced by the $80. So too your INCLUDE statement gets replaced, right there, with the contents of the included file. Chris... Link to comment Share on other sites More sharing options...
dew2050 Posted July 8, 2003 Share Posted July 8, 2003 Very interesting. I was thinking about it in C terms, where the includes are always declared at the start of your code, but this is obviously not the case. Thanks for the help! Link to comment Share on other sites More sharing options...
Cybergoth Posted July 8, 2003 Share Posted July 8, 2003 Hi there! Very interesting. I was thinking about it in C terms, where the includes are always declared at the start of your code, but this is obviously not the case. Thanks for the help! Actually in C it works exactly the same. Greetings, Manuel Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.