Moose1900 Posted December 5, 2015 Share Posted December 5, 2015 The X register is being used to keep track of which row of the Arena to draw. Your new sprite routine is trampling all over the value of the X register. oh, ok, so then I need to use two separate registers, one for the sprite and one for the playfield. Is that right? Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted December 5, 2015 Share Posted December 5, 2015 oh, ok, so then I need to use two separate registers, one for the sprite and one for the playfield. Is that right? Normally you use the same register for the sprite that you do for your scanline counter. That does require the use of zero page pointers for the sprite graphics. In Collect those are Player0Ptr and Player1Ptr. Have you finished going thru the Collect blog series? Later on in the series the X register is replaced with RAM variable ArenaIndex, which would have let you use X like you did. Namely: ArenaLoop: tya and #%11 bne SkipX inc ArenaIndex <-- this used to be inx ... ldx ArenaIndex lda ArenaPF0,x sta PF0 ... Quote Link to comment Share on other sites More sharing options...
Omegamatrix Posted December 5, 2015 Share Posted December 5, 2015 Wow- that's really advanced. Pushing processor status on to the stack? I'm not sure why that would work since all I know is the stack keeps track of addresses for subroutines. Now, if I could only figure out why that ball isn't moving... The status register holds all of the flags for the processor. When you look in Stella's debugger this is it: That register holds a bunch of individual bits. A bit can either be 0 or 1 (high or low). The lowercase letters represent 0's, and the uppercase represent 1's. The letter that we are interested in here is the 'z' (z-flag) which when you look at it matches the position of the bit used in the enable registers. Pushing the processor reads the contents of the status register and writes it to where the stack pointer is indexed to. If the stack pointer is pointing to the ENABL register ($1F) then the PHP (Push Processor) will set or clear ENABL with its z-flag. The other bits are ignored because the ENAxx register doesn't use them. Also the PHP instruction decrements the stack pointer by 1 each time it's used. So if the stack pointer was pointing at ENABL ($1F) and PHP was used, then the stack pointer would then be pointing at ENAM1 ($1E). This makes it easy to set up a routine that will set ENABL, ENAM1, and ENAM0 sequentially. Finally, about the z-flag. It stands for zero flag. It gets set 'Z' or cleared 'z' a few different ways. In this particular example we are concerned with setting or clearing it with a compare instruction. With a compare the z-flag will set when the value compared to matches exactly, and cleared otherwise. Here's a little bit of a code using this trick from a game I'm converting: ; Earlier in the code, set up stack pointer ldx #ENABL txs ; Y holds the current scanline cpy ball_Line php ; ENABL, SP decrements from $1F to $1E (ENAM1) cpy m1_Line php ; ENAM1, SP decrements from $1E to $1D (ENAM0) cpy m0_Line php ; ENAM0, SP decrements from $1D to $1C By using a few ram registers and throwing this all in a loop, you have a fast way of setting or clearing all the enable registers. If this all seems convoluted just remember you only have 76 cycles per line, and that can fill up quickly. This routine is fast. 1 Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted December 5, 2015 Share Posted December 5, 2015 Thanks.. Its making some sense but: Are you saying some of the locations the stack pointer runs through are registers for graphics and other stuff? I guess I imagined that it only looks at program code locations. I think I have a good idea of the processor status register, but can't grasp why we would have Z the way we wanted for D1 for ENABL. Quote Link to comment Share on other sites More sharing options...
Omegamatrix Posted December 5, 2015 Share Posted December 5, 2015 The stack pointer can be anywhere from $00 to $FF. Normally use of the stack pointer is to initialize it to a known ram location (usually $FF) and leave it alone. Every time you jump to subroutine (JSR) the return address gets pushed on the stack and the stack pointers decrements for each byte pushed on the stack. The addresses are two bytes, so the stack pointer would go from $FF to $FD when you do a JSR. When you do a return from subroutine (RTS) the address you return to is pulled from the stack. The stack pointer 'points' to the location to get the return address. As to where the stack pointer can be, locations $80 to $FF are the zero page RIOT ram and $00 to $2F are one of the mirrors of the TIA registers. The stack pointer can point to anywhere in that space. In this case we are deliberately setting it up to ENABL to perform this trick. In the code from the previous post, the idea is to have Ball, M0, and M1 appear for 1 scanline wherever we want on the screen. By using a separate ram register for each we have made the lines independent for each object. We could have M0 on line 56, the ball on line 130, and so on. The code is meant to be put in a loop that draws the kernel allowing this to happen. Each object will only be 1 scanline in height. To make them taller the code becomes longer. This I won't show here, but if you look at Star Wars Arcade, the crosshairs and stars are all set with this trick. The cross hairs are several scanlines in height, but the stars are all 1 scanline in height. Back to how it works with the Z flag... you use a compare instruction, in this case CPY. The Y register in this example is holding the current scanline number and will either get decremented or incremented (your choice). In the ram location you are comparing it to is the scanline you want the particular object to appear on. When Y is the same as that value the Z-flag goes high. When it is any other scanline the z-flag is low. What we are doing with PHP is taking the contents of the status register (which includes the Z-Flag in the D1 bit position) and writing it to ENAxx. On every line that we do that we are either setting or clearing ENAxx. Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted December 5, 2015 Share Posted December 5, 2015 Awesome. I get it. Thanks! My little games I've been trying to write always run into kernel issues so I'm sure it will come in handy. Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted December 6, 2015 Share Posted December 6, 2015 (edited) Good Morning.. Can anyone explain this a little bit? I've never seen the DCP command before (looks like it means decrement and compare but I can't find documentation on it) Also, I have no idea how the .byte even does anything here. I thought .byte just placed data in memory. lda #HUMAN_HEIGHT-1 ; 2 15 - height of the humanoid graphics, subtract 1 due to starting with 0 dcp HumanDraw ; 5 20 - Decrement HumanDraw and compare with height bcs DoDrawGrp0 ; 2 22 - (3 23) if Carry is Set, then humanoid is on current scanline lda #0 ; 2 24 - otherwise use 0 to turn off player0 .byte $2C ; 4 28 - $2C = BIT with absolute addressing, trick that ; causes the lda (HumanPtr),y to be skipped Edited December 6, 2015 by BNE Jeff Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted December 6, 2015 Share Posted December 6, 2015 Good Morning.. Can anyone explain this a little bit? I've never seen the DCP command before (looks like it means decrement and compare but I can't find documentation on it) Also, I have no idea how the .byte even does anything here. I thought .byte just placed data in memory. Both are answered in the comments of Step 4 of the Collect series. Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted December 6, 2015 Share Posted December 6, 2015 Thanks! Is it fair to say that the BITabs doesn't really produce anything useful here? The instruction causes consistent cycles, and also performs a mini-branch, but whatever value is the result, is not used- correct? Quote Link to comment Share on other sites More sharing options...
Omegamatrix Posted December 6, 2015 Share Posted December 6, 2015 Thanks! Is it fair to say that the BITabs doesn't really produce anything useful here? The instruction causes consistent cycles, and also performs a mini-branch, but whatever value is the result, is not used- correct? BIT is used because it won't trash A when you are skipping over the next instruction. In the DoDraw code you posted it doesn't matter what BIT does, but in general everyone has to be aware of what flags an instruction affects. I always use this page for a 6502 instruction set. You can see from that page that BIT affects the N, V, and Z flags. You will sometimes see people use the illegal NOP's instead of BIT for this skipping purpose, because NOP affects no flags. The absolute NOP instruction is $0C. Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted December 8, 2015 Share Posted December 8, 2015 Thanks- I like that instruction link a lot... I think I could use some help figuring out why my ball doesn't move. In my start up code, I have: LDA #1 STA CTRLPF STA HMBL ;Ball Speed Then in the main loop I have: LDA #2 STA VSYNC STA WSYNC STA WSYNC STA WSYNC STA HMOVE ;Move Ball and this is in the kernel: CheckBall CPY Ball BNE NoBall LDA #2 STA ENABL NoBall Does anything look wrong? Its an HMOVE immediately after a WSYNC, 1 is a legitimate speed for HMBL. The ball shows up (sort of) but doesn't move.. Thanks! Quote Link to comment Share on other sites More sharing options...
LS_Dracon Posted December 8, 2015 Share Posted December 8, 2015 The 4 bits used for hmove are in the left nibble. Helps if you write in hexadecimal (#$): LDA #1STA CTRLPF LDA #$10 ;%00010000STA HMBL ;Ball Speed Remember, once you write a HMOVE value, it keeps until you set HMCLR (hmove clear) I set HMCLR every frame, so I aways know the frame starts with all HMOVE as 0. Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted December 8, 2015 Share Posted December 8, 2015 Right there on page 41. I can't believe I made basically the same mistake as I did when I tried to ENABL... I checked the HMOVE register over and over, but not HMBL.. Thank you. Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted December 19, 2015 Share Posted December 19, 2015 Good Morning, I'm looking through some code and found some commands I don't recognize.. what are these Basic-looking commands? They're not really indented which makes me think they are labels for a subroutine, but they repeat which makes me think they can't be. Random: lda Rand8 lsr ifconst Rand16 rol Rand16 endif bcc noeor eor #$B4noeor sta Rand8 ifconst Rand16 eor Rand16 endif rts Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted December 19, 2015 Share Posted December 19, 2015 Good Morning, I'm looking through some code and found some commands I don't recognize.. what are these Basic-looking commands? While I don't specifically point it out, there's comments in the code of step 10 of the Collect series which explain what those do. It's also covered in dasm.txt, the manual that comes with dasm, under the section titled PSEUDOPS: They're not really indented which makes me think they are labels for a subroutine, but they repeat which makes me think they can't be. A single space is all that's required to indent something. When using jEdit, the different syntax coloring of inconst and endif helps to reinforce that they're not subroutine labels: Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted December 20, 2015 Share Posted December 20, 2015 I guess I'm pretty lost on this one and might have to drop it for now. I read through half of the DASM.txt and so much of it was above my head that I wasn't getting anything out of it. I read Collect #10 and I could follow, except for the terms "endif, and "ifconst", and the rest that I was specifically looking for- just not getting it. I could only figure that they were used in conjunction with the LFSG. I did learn what LFSG was- pretty cool.. and downloaded JEdit which I figured I'd have to start using eventually anyway. (It says its an editor for the "mature" programmer. uh-oh..) My idea after completing Collect #4 with some difficulty was to just go ahead and read through one of your more complete versions of a Collect assembly to get a sense of as many parts as possible of the entire program. I've been really enjoying that and learning a lot.. Thanks for the help! Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted December 21, 2015 Share Posted December 21, 2015 I guess I'm pretty lost on this one and might have to drop it for now I've family in town thru Tuesday, will go into this after they've left. Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted December 21, 2015 Share Posted December 21, 2015 I guess I'm pretty lost on this one and might have to drop it for now. Everybody was still asleep, so I added a comment to Collect step 10 that might help. Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted December 21, 2015 Share Posted December 21, 2015 Ahh.. Now it makes sense. Thanks. So, why write it this way? Is it to make it a sort of all-purpose code that you can paste into any program? Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted December 22, 2015 Share Posted December 22, 2015 Is it to make it a sort of all-purpose code that you can paste into any program? Yep Quote Link to comment Share on other sites More sharing options...
Moose1900 Posted December 22, 2015 Share Posted December 22, 2015 Does anyone have a working sample program that includes a skipdraw routine? I have seen many postings of the code for just the routine, but never a simple program that draws a sprite on the screen using skip draw. I have tried for the past few weeks, but can't seem to get it to work. I think if I saw a simple example that works, then I could see where I am going wrong. Any help would be much appreciated. Thanks. Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted December 31, 2015 Share Posted December 31, 2015 (edited) Moose.. I'm not sure if it will help, but I believe Spiceware's Collect program uses DoDraw which looks identical to SkipDraw to me (though its supposed to be different in some way.) There's an explanation in the comments at Step 4: http://atariage.com/forums/blog/blog-148/cat-188-collect Edited December 31, 2015 by BNE Jeff Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted December 31, 2015 Share Posted December 31, 2015 Good evening.. I finally downloaded Makewav, created a file for my Starpath Supercharger, played one of my little programs on an actual Atari, and it worked! However, all of the colors were completely wrong. The black background was orange, and the gray playfield was black. Anybody know why that might happen? Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted January 3, 2016 Share Posted January 3, 2016 Does anyone have any tips on adding variable playfield graphics to a kernel? I'm trying to have a prize (just a dot) show up in a random location using PF1 and can't figure out how to get the kernel deal with it. I've thought about decrementing and comparing a memory location or displaying an entirely new playfield just to show the one dot but those ways seem over-complicated and/or wrong. Note: my playfield is otherwise blank in the prize location. Thanks! Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted April 9, 2016 Share Posted April 9, 2016 Good Morning! I had to put this (post above) aside for a bit while finishing up a certification I needed for work.. I decided to start by just having the kernel look to a single RAM location and then storing it in PF1. I've been working at it all morning and I just cant figure out why nothing shows. Here is the relevant code (Note this started as Darrell Spice's "Collect"): Here is where I set aside 6 bytes for 6 or more prizes: PillPF: ds 6 ; stored in $9D,9E,9F,A0,A1,A2 Here is where I put in a test value: InitSystem: ; CLEAN_START is a macro found in macro.h ; it sets all RAM, TIA registers and CPU registers to 0 CLEAN_START lda #%10101010 ;added to test if pills will display sta PillPF ;added to test if pills will display And here is what is in the kernal. It's supposed to use PillPF,0 to make 2 sets of stripes on the screen. It doesn't show up: ; start of line 1 of the 2LK sta GRP1 ; 3 3 - @0-22, update player1 graphics stx ENAM1 ; 3 6 - @0-22, update missile1 graphics ldx ArenaIndex ; 3 9 lda ArenaPF0,x ; 4 13 - get current scanline's playfield pattern sta PF0 ; 3 16 - @0-22 and update it lda PillPF ; 4 20 - get pill PF . Also deleted offset sta PF1 ; 3 23 - @71-28 and update it lda ArenaPF2,x ; 4 27 - get current scanline's playfield pattern sta PF2 ; 3 30 - @60-39 Any ideas? 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.