Jump to content
IGNORED

My 1st Homebrew - Mr. Yo-Yo, WIP


DaveM

Recommended Posts

5 hours ago, Thomas Jentzsch said:

Not sure if I get you here. You already realized that flickering objects can be missed by the hardware collision registers. Why would you want to revert back to it? Or are you sure that the hardware collisions will always trigger? And why don't you use your old code again then?

Glad I finally got the correct xmacro file to you ?

 

So here's what happened...  As Dennis developed the new kernel, I don't think I properly communicated that the player should have 2 missiles in play at the same time.  So when he put together the new kernel, he only developed it for one missile object.  As we started to combine his code with mine, we discovered the issue.  We discussed a few ways to fix the problem:

  1. Allow only 1 active missile per horizontal zone.  I didn't like this idea.  In watching others play the game, I noticed players tended to hover within one zone and fire like crazy to hit the various objects, so 2 active missiles in the same zone I felt was necessary.
  2. Re-write the kernel so that there are two missile objects.  This would require a lot of work, and I thought there was a simpler solution....
  3. Flicker the missiles.  In playing around with the code, I found the collision detection registers worked fine if the missiles are flickered, but nothing else was.  In my original version, EVERYTHING flickered, so using the cx registers just didn't work.  But when the missile is the only flickering object, the cx registers worked just fine.  So rather than go through all the work of adding a second missile object, which would require finding the necessary cycles, etc., I thought it would just be easier to flicker.  Unfortunately, the results weren't good.  I've attached the last ROM and code of the original kernel for comparison.  You can see the missiles looked better with the original code for some reason.

I think that having two non-flickering missile objects would be the best solution.  I was just trying to save work.  Dennis put in a lot of work on the kernel, and I felt horrible about having to go back and change the whole thing to add a 2nd missile.

 

5 hours ago, Thomas Jentzsch said:

BTW: How do you play the game. Are there some brief instructions somewhere?

It's kinda scattered throughout this thread, so I'll give you a quick summary.  I should note that in the "new" kernel version, I've removed the collision detection, so the game isn't fully playable.  However, in the attached "old" kernel version, then game is fully playable (albeit with an error here or there which briefly skews the line count).

 

You control Mr. Yo-Yo.  The object is to rescue the little musical note guys ("Notelies") that appear in the bucket at the bottom of the screen.  To rescue them, descend to the bottom of your string when a Notely appears in the bucket.  You'll start flashing various colors when you've collected a Notely.  Return to the top of the screen to release them to safety.  Each round ("cave") has a certain number of Notelies to be rescued before time expires.

 

Controls:  The button controls your movement.  Push the button and Mr. Yo-Yo descends.  Release the button, and goes back up the string.  Push the joystick right and left to fire the lasers at the enemies.  You can hold the joystick in one direction for continuous fire.

 

Console Controls:  The left difficulty switch controls Mr. Yo-Yo's speed (B = normal, A = slow), while the right difficulty switch controls the enemy speed (B = normal, A = fast).  The color/B&W switch acts as a pause button.  Reset starts a new game.  Select is not used.

 

Status Bar:  The grey bar at the bottom of the screen is your status bar.  The red marker is the timer, and the green marker shows your progress.  The red marker starts at the right, and slowly counts down to the left.  When it reaches the left end of the bar, you're out of time, and can no longer score any points in that cave.  The green marker starts at the left, and moves to the right each time you rescue a Notely.  When the green marker reaches the right side of the bar, you've completed the cave, and will receive bonus points for any time remaining.

 

Caves:  Each level consists of three caves, followed by a bonus cave.  To get to the bonus cave, you must complete the three other caves all before the time expires.  The color of the cave walls determine how many Notelies to rescue, as well as how to get the Notelies to appear in the bucket.

 

Blue caves - Rescue 5 Notelies.  They appear immediately.

Purple caves - Rescue 6 Notelies.  You must shoot one object or collect one coin to get them to appear.

Green caves - Rescue 7 Notelies.  Shoot 2 objects or collect 1 coin to get them to appear.

Orange caves - Rescue 8 Notelies.  Shoot 3 objects or collect 1 coin to get them to appear.

 

The 1st level consists of a blue, purple, and green cave.  All other levels consist of purple, green, and orange caves.

 

Bonus caves - If you successfully complete all 3 caves in a level before time expires, you get a bonus cave.  Shoot 15 bonus targets to get the bonus gem to appear.  Rescue the bonus gem before time expires to get 9900 points, an extra life, and you'll also get an intermission/cut scene in celebration of your accomplishment.

 

Enemies - There's 5 enemies, each with their own characteristics.  If any of them touch Mr. Yo-Yo, you lose a life.  In addition, some may interact with your string.

Grey: "Blobs" - They just move across the screen and do not interact with your string.  100 points.

Purple: "Flappers" - Faster than Blobs, and they hover up and down.  They do not interact with your string.  150 points.

Blue: "Bouncers" - When they hit your string or the end of the screen, they will reverse and speed up.  They will not leave the screen until you shoot them.  200 points.

Green: "Stunners" - If they touch your string, you'll be paralyzed for about 2 seconds.  250 points.

Red: "Snippers" - Scissor guys who'll cut your string if they touch it, costing you a life.  300 points.  If you can shoot 3 of them in a cave without losing a life, they'll stop spawning for the rest of that cave (unless you lose a life in the process).

 

Other objects:

Coins - You can shoot them for 100 points, or collect them for 1000 points.  Collecting a coin also causes a new Notely to appear (as long as you're not carrying one with you), and it doubles the value of a Notely rescue, up to 3200 points.

 

Power Pods - If you shoot one, you get 300 points, and it acts as a smart bomb, killing all enemies on the screen.  You'll also get the points for those enemies.  If you collect a Power Pod, you'll score 3000 points, it turns all enemies on the screen into coins, and it triggers a "coin frenzy" where nothing but coins are spawned for about 4 seconds.

 

To do list:

  • Add 2 player options - 2 player alternating turns, and a 2 player co-op where one player moves and the other fires
  • Selectable starting level

I think that's about it.

 

Thanks for the scoreboard fix!

mr_yo_yo.0.20.1.bin mr_yo_yo 0.20.1.a

Link to comment
Share on other sites

3 hours ago, DEBRO said:

Hi David,

 

So sorry I had gone silent on you. I would like to see your game completed. I just haven't had time to devote to the hobby lately. If anyone is willing to help; please do.

Yeah, no problem!  This stuff happens.  Feel free to jump back in whenever you're ready. ?

Link to comment
Share on other sites

On 10/31/2020 at 3:45 PM, Thomas Jentzsch said:

Yes, that's the single pixel shift at the top area. The position is 72, reflection is on. When moving down, the position switches between 71 and 73, depending on reflection. That explains the problem.

I'm finally getting around to working on this today.  I meant to do this last week, but a lot has popped up that prevented that.  Unfortunately, I can't figure out how to fix this issue.  Any suggestions?  Not working on the game for a few months has really hurt.

 

I'm starting to think I may have to just scrap the new kernel and return to the old one.  I'm left with a lot of code that I don't understand and don't know how to modify.  I'm a bit at a loss on how to proceed with this game.  As I'm going through the code today, I'm noticing other smaller issues that I'll need to correct that I just can't figure out.  I'd like to make it the best game it possibly can be and finish it off so that I can move onto other projects, including other game ideas that I have, but I'm just at a roadblock here.  Any advice?

Link to comment
Share on other sites

I decided to go back to my original kernel (for now), and have made some updates:

  • The scoreboard has been fixed, with thanks to Thomas Jentzch for finding the bug there.
  • With the fixed scoreboard, I reinstated my original number designs, which were too wide to use with the bug.  
  • I've given the blue "Bouncer" enemy a new look.  I originally intended him to look a bit like an upside-down Nike "swoosh", but everyone kept calling him a fish.  So I just went all-in on the fish concept and made him more fish-like.
  • I slowed down the red "Snipper" enemies that you meet in the higher levels.  At their previous speed, the player just didn't have time to react to them and was dead almost the instant they appeared on the screen.  I think I may have slowed them down too much, but I'm going to leave it where it is until I get a chance to test it a bit more.
  • The green progress marker will now start flashing when there is only 1 rescue to go in a round.  I noticed a number of players had trouble telling how far they had left to go to complete the round, so I thought this might help.
  • I changed the sound effect when you collide with a square target in the bonus round.  Previously, there was a "tinkling" type of sound, which I noticed many players would take as a positive sound, so they would then try to collide with the targets instead of shooting them, which is what they're supposed to do.  The new sound effect is the tail end of the "boing" sound the bouncers make, played in reverse.  Definitely can't mistake that for a positive sound.

Known issues:

  • About halfway between the left side of the screen and the player's string, the enemies have a little pixel shift, where they will drop down one scanline.
  • The game still occasionally jumps to 263 lines.  I think it's because of how I'm cycling through all the objects during my collision detection.

To do list:

  • The kernel does still need to be re-written.  I'm going to take some time over the next few weeks to re-familiarize myself with the code and go back through my notes and the book I'm using and try to figure out how to write a better kernel.  I'd like to eliminate the flicker, but at the very least, I've got to get rid of that shift where the enemies jump one scanline.
  • Implement the menu I created a short while back, and with that, implement the options available on that menu (2 player, selectable starting level, etc.)
  • I've got a few other little things I'd like to throw in the game if I've got the space to do it.

So that's where I stand right now.  I'd appreciate any feedback, and if anyone has any suggestions on how to fix any of the issues I'm having, I'd appreciate it.  Thanks!

Mr_Yo-Yo_A20201108.bin Mr_Yo-Yo_A20201108.a

  • Like 4
Link to comment
Share on other sites

Hi DaveM, after having been reading the kernel code written by Dennis a few days ago, I have found the error of the "yo-yo pixel shift", what happens is that at the beginning of the kernel, the sprite moves one pixel to the left by the "HMOVE", you have to clear the HMP1 register (or with HMCLR) before the HMOVE, I just added a "stx HMP1" on line 1156, now I had to modify lines 1658 and 4002 (offset by 2 pixels how was before).

 

I also found another isue at the end of the kernel, 2 scanlines were missing, (line 1389, it was "ldx #13", I changed it to #15), also "PVmin" should be 158 now (line 636).

I do not remember if there was something else that I had corrected, you can see the source (I used the source of this post).
Cheers,
DINTAR816

mr_yo_yo 0.24.7.2.asm

  • Thanks 1
Link to comment
Share on other sites

21 hours ago, DINTAR816 said:

Hi DaveM, after having been reading the kernel code written by Dennis a few days ago, I have found the error of the "yo-yo pixel shift"...

Thank you! I meant to look at this today, but work/life got in the way. I'll have a look over the next few days, add in the changes I made to the other kernel, and see where things stand. I'm definitely still open to using the new kernel if all the issues get resolved. 

Link to comment
Share on other sites

It took me a lot longer to get to this than I hoped, but it's been a long week.  

 

So I finally got to look at the changes DINTAR816 made, and combine those with the changes I made to the old kernel demo, and here's where things stand...

On 11/8/2020 at 10:05 PM, DINTAR816 said:

Hi DaveM, after having been reading the kernel code written by Dennis a few days ago, I have found the error of the "yo-yo pixel shift", what happens is that at the beginning of the kernel, the sprite moves one pixel to the left by the "HMOVE", you have to clear the HMP1 register (or with HMCLR) before the HMOVE, I just added a "stx HMP1" on line 1156, now I had to modify lines 1658 and 4002 (offset by 2 pixels how was before).

Absolutely fantastic!  This works perfectly now!  THANK YOU!

On 11/8/2020 at 10:05 PM, DINTAR816 said:

I also found another isue at the end of the kernel, 2 scanlines were missing, (line 1389, it was "ldx #13", I changed it to #15), also "PVmin" should be 158 now (line 636).

This I had to change back.  Those two scanlines had to be taken out to compensate for something or other that changed and keep the frame at a constant 262 lines.  So I switched this back, no biggie.

 

Two problems that now need to be resolved.

 

First, what would be the best way to get a second missile in there?  I tried flickering, but that just doesn't look as good.  So it would seem that I need to add a 2nd missile object, but I don't understand how Dennis did the first one, and I think I'm running short on cycles to implement the second.

 

The other issue has to do with a vertical black band that we added to the left of the screen.  One bit of feedback I got on the original kernel was that the enemies just disappeared when they reached the end of the screen, rather than "sliding" off it.  So Dennis added the black band to solve this problem.  The issue now is that the band isn't wide enough to cover the enemies, so they still just vanish when they reach the edges of the screen.  So, I either have to make the band wider, or remove it completely and just live with the enemies vanishing rather than sliding off the screen (which, to be honest, is OK with me).  Would removing this black band free up enough cycles to implement the 2nd missile object?  If that doesn't matter, how do I widen the band so that it covers up the enemies properly?

 

Thanks!

Mr_Yo-Yo_B20201115.a Mr_Yo-Yo_B20201115.bin

Link to comment
Share on other sites

Hi David,

 

Again, please accept my apology. I haven't had the time to work on this. Maybe my little input here could help.

 

On 11/15/2020 at 5:00 PM, DaveM said:

First, what would be the best way to get a second missile in there?  I tried flickering, but that just doesn't look as good.  So it would seem that I need to add a 2nd missile object, but I don't understand how Dennis did the first one, and I think I'm running short on cycles to implement the second.

I believe we landed on using the other missile to allow two missiles in flight at a time. The trade off here is the "other" missile will be the color of the obstacle. There should be enough time in the kernel to enable/disable another missile though it would need to be changed. My initial thoughts are you would position the missiles before entering the kernel and look to see when it is time to draw / enable the missile based on the missile's vertical position.

 

You will have to have a variable (2 bits) to control when a missile is active or in flight. If only one is flight at a given time then use M1 so it is the same color as Mr. Yo-Yo. When two are in flight then use the alternate player missile.

 

To draw the missiles, I'm using the typical stack trick. Before entering the kernel, the stack is set to point to ENAM1. Since your missiles are one scan line high; this makes it easy to determine when to draw. The kernel mockup I sent will decrement the missile vertical position on each scan line (within a kernel section). I then "push" the result to the stack. This has benefit of when the subtraction reaches zero (i.e. when to draw the missile) the stack push moves the Z flag to ENAM1 and enables the missile. You can read more about this in Paul Slocum's ATARI 2600 ADVANCED PROGRAMMING GUIDE. Search for "Showing Missiles/Ball using PHP".

 

The kernel will need to be updated to allow time so set the new missile's vertical position so it can be decremented to know if it is time to draw. This could be done while positioning the obstacle. Currently the horizontal positioning routine takes up a full scan line. Splitting this up should allow time to set this new missile's vertical position. To do this, compare the obstacle's vertical position with the screen's midpoint. This will let you know which side the obstacle is to be placed. When the obstacle is to be positioned on the left then start the horizontal positioning and after set the missile's vertical position variable. When the obstacle is to be positioned in the right then use the early time to set the missile's vertical position variable before starting the obstacle's horizontal positioning. That's a lot of words...I know. I used this technique in Climber 5. A similar technique is also present in Asteroids. You can find my Climber 5 source code (as ugly as it is) for reference on @Atarius Maximus site. Look for "MoveGirderOnRight".

 

On 11/15/2020 at 5:00 PM, DaveM said:

The other issue has to do with a vertical black band that we added to the left of the screen.  One bit of feedback I got on the original kernel was that the enemies just disappeared when they reached the end of the screen, rather than "sliding" off it.  So Dennis added the black band to solve this problem.  The issue now is that the band isn't wide enough to cover the enemies, so they still just vanish when they reach the edges of the screen.

What you are seeing is I'm doing HMOVE on every scan line within the kernel zone. This creates a black border on the left side of the screen but its not enough space to mask your obstacle. Your obstacle is DOUBLE_SIZE and will need more "tricks" to have it slide off the side. I'd recommend watching David Crane's speech at the 2015 Portland Retro Gaming Expo. He explains how he did this for Grand Prix. Here is a link to the talk...https://www.youtube.com/watch?v=nbinkHyWde8. To summarize, he had to build extra sprites to adjust for the screen wrapping on the VCS. I reverse-engineered Grand Prix as well if looking at the source would help. Here is a link to my reverse-engineered Grand Prix on Github...https://github.com/DNSDEBRO/Disassemblies/tree/master/Atari2600/Grand%20Prix. This would be a perfect model for your game kernel.

 

I know this is a lot to take in at one time. Hopefully it will help get you back on track. Good luck and have fun!

  • Thanks 1
Link to comment
Share on other sites

8 hours ago, DEBRO said:

Again, please accept my apology. I haven't had the time to work on this. Maybe my little input here could help.

No problem!  Any help is appreciated.  Thank you!

8 hours ago, DEBRO said:

I believe we landed on using the other missile to allow two missiles in flight at a time. The trade off here is the "other" missile will be the color of the obstacle.

Yes, I think flickering the missiles was an attempt at a quick fix, and it didn't quite work.  So a 2nd missile object is the answer, and the color doesn't matter at this point.

8 hours ago, DEBRO said:

(a lot of other stuff ?)

A ton of helpful info, and my head is spinning right now just going through it.  I'll take a few days to go through all this, and I'll probably come back with a lot of questions.  But I'll give it a shot.

 

On 11/8/2020 at 3:53 PM, DaveM said:

Known issues:

  • About halfway between the left side of the screen and the player's string, the enemies have a little pixel shift, where they will drop down one scanline.

I've been trying to fix this issue the past couple days, with no luck. This problem is on the original "flicker" kernel, so it has nothing to do with Dennis' code.  My guess is that the issue is caused by the enemies being drawn after the HBLANK period, but in trying to re-write the code to fix this, I was unable to solve the issue.  Given the complexity (at least to me) of what Dennis said above, I think I'll abandon fixing the old kernel for now and try to concentrate on the newer one.

 

I've had one friend suggest to me to forget about this game completely, and start work on my next game idea.  I don't think I'll do that.  I'd really like to finish this off.  Seems so close.

  • Like 2
Link to comment
Share on other sites

As usual, it's taken me longer to get around to this than I had hoped, but I'm finally tackling some of this tonight.  I decided to start with the black border first.

 

On 11/17/2020 at 7:15 AM, DEBRO said:

What you are seeing is I'm doing HMOVE on every scan line within the kernel zone. This creates a black border on the left side of the screen but its not enough space to mask your obstacle. Your obstacle is DOUBLE_SIZE and will need more "tricks" to have it slide off the side. I'd recommend watching David Crane's speech at the 2015 Portland Retro Gaming Expo. He explains how he did this for Grand Prix. Here is a link to the talk...https://www.youtube.com/watch?v=nbinkHyWde8. To summarize, he had to build extra sprites to adjust for the screen wrapping on the VCS.

Very informative talk.  Thanks for sharing that!  He actually solves a problem that I've been thinking about for my next game - how to smoothly move a playfield object horizontally.  So at the very least, I now know how to do that going in.  But back to this game and that black band on the left of the screen and getting objects to slide off the screen...

 

I understand what he's saying.  Since his Grand Prix cars were 4x wide, he had to build 4 sets of sprites for the car graphic, and use those when the cars reached the edge of the screen.  I'm assuming since my enemies are 2x wide, I'd only need to build 2 sets of sprites for each frame of animation for each enemy.  That doesn't seem to be much of a problem at first.  It looks like I have plenty of room in that first bank, and it's simple enough to construct extra sprites that only show half of each character.

 

But here's he potential problem: We have all the sprites lines up in the EnemyGfx array.  I remember as we were putting together the logic for the new kernel, the kernel wouldn't display any sprite that started after the 256th byte of that array.  Because I've got so many different enemies and objects in the game, I've already maxed that out.  Any additional sprites I add would push stuff way past that 256th byte.  So my guess is that if I tried doing all this, it wouldn't work anyway.  I would have to build an alternate array containing the "half" sprites, and have the kernel select that alternate array when setting up the enemy graphic; or, I would have to do four LSR's to each line when one of these "half" sprites are needed, and I don't think I have the cycle time to do either.  

 

Am I correct in all that?

 

So if this isn't going to work, I'll just have to live with the enemies not sliding off the screen.  In which case, I'm guessing that I'd remove whichever HMOVE was added to make this work.  I'm guessing it's the one at line 1428, but when I take that out, it doesn't seem to make a difference.  Am I missing something?

 

As for adding the 2nd missile object, I've only just scratched the surface of that so far, but here's where I am:

On 11/17/2020 at 7:15 AM, DEBRO said:

My initial thoughts are you would position the missiles before entering the kernel and look to see when it is time to draw / enable the missile based on the missile's vertical position.

Yes, it does look like we do that with the one missile object currently:

Quote

    lda FrameCtr
        ;and #1        ; **** Temporarily disabling flicker
        and #0        ; **** Disables flicker. Only Missile #0 is shown
        tay        ; A -> Y
        lda MHPos,y    ; Missile Horiz Pos for HMOVE
        sta MissileH       
        lda MVPos,y    ; store variables to use for display
        sta MissileV
    beq .setupKernel    ; If missile is not active, branch
        
DetermineToActivateMissile
   ldx #NUM_KERNEL_SECTIONS - 1
.determineLane
   dex
   sbc #H_INNER_CAVE + 4            ; subtract height of cave zones
   bcs .determineLane
   adc #H_INNER_CAVE + 5            ; increment to get offset
   cmp #H_INNER_CAVE + 1            ; compare with cave zone height
   bcc .determineToMoveMissile      ; branch if within zone
   sbc #H_INNER_CAVE                ; Mr. Yo-Yo center in another zone
   dex
.determineToMoveMissile
   cpx #0
   beq .setupKernel        ; branch if in bottom zone...no missile
   sta missileVertPos,x        
   stx MissileZone        ; store x to variable to use later in collision detection
        
.setupKernel
   lda EnemyVPos + NUM_KERNEL_SECTIONS - 1;get top obstacle vertical position
   sta tmpObstacleGraphicIdx
   lda EnemyColor + NUM_KERNEL_SECTIONS - 1;get top obstacle color
   sta COLUP0                       ; color top obstacle
   lda EnemyLSB + NUM_KERNEL_SECTIONS - 1;get top obstacle LSB value
   sta obstaclePointer              ; set obstacle graphic LSB value
   lda EnemyReflect + NUM_KERNEL_SECTIONS - 1;get top obstacle attributes
   sta REFP0                        ; set obstacle REFLECT state
   sta NUSIZ0                       ; set obstacle size
   lda EnemyHPos + NUM_KERNEL_SECTIONS - 1;get top obstacle horizonal position
   ldx #<RESP0 - RESP0
   jsr SetHorizPos                  ; position top obstacle
   
   
   lda MissileH
   ldx #<RESM1 - RESP0 
   jsr SetHorizPos                  ; position Mr. Yo-Yo missile

So that top part would need to be changed, since we won't be flickering, but basically what it's doing is checking the missile's vertical position.  If it's equal to 0, then the missile isn't active.  I could re-write that to check for both missiles, no problem.  I'd then need to turn the DetermineToActivateMissile code into a loop, passing through once for each missile object.  Now there's two variables at the end of that bit of code: missileVertPos,x and MissileZone.  I'd need to change the latter into an array, so it could hold one value for each missile, but I think I'd have to create an additional variable for the first one, essentially missileVertPos0,x and missileVertPos1,x, where x represents the number of the zone in which the missile appears.  This leads to my next problem...

 

If I remember correctly, I'm about at my limit as far as the number of bytes I can use to store my variables, and I'm pretty sure this would push me over the limit.  Is there any way I can get around that?

 

That's as far as I've gotten so far.  I've attached the last source code I had for reference, so no one has to go searching upward to find it.

Mr_Yo-Yo_B20201108.a

Link to comment
Share on other sites

On 11/21/2020 at 8:57 PM, DaveM said:

So that top part would need to be changed, since we won't be flickering, but basically what it's doing is checking the missile's vertical position.  If it's equal to 0, then the missile isn't active.  I could re-write that to check for both missiles, no problem.  I'd then need to turn the DetermineToActivateMissile code into a loop, passing through once for each missile object.  Now there's two variables at the end of that bit of code: missileVertPos,x and MissileZone.  I'd need to change the latter into an array, so it could hold one value for each missile, but I think I'd have to create an additional variable for the first one, essentially missileVertPos0,x and missileVertPos1,x, where x represents the number of the zone in which the missile appears.  This leads to my next problem...

 

If I remember correctly, I'm about at my limit as far as the number of bytes I can use to store my variables, and I'm pretty sure this would push me over the limit.  Is there any way I can get around that?

I think I worked my way through that.  I re-wrote the missile positioning routine, and it appears to work so far, although, I haven't gotten around to actually drawing the 2nd missile.  But, the first missile works, so that's good.  As for having too many variables, I think I'm ok for the time being.  In re-writing the routine, I was able to eliminate 3 variables that I don't need anymore, including that MissileZone variable I mention above (I think once I add the collision registers, those will give me enough if I do things right, so hopefully I won't need a variable).  IIRC, I had 5 bytes to play with, so I removed 3, added 6, so I've got a couple left, I think.  I may need some help on that later, but for now, I think I'm ok.

 

I'll tackle drawing the 2nd missile later this week.

Mr_Yo-Yo_B20201122.a

Link to comment
Share on other sites

Hi David,

 

Glad to see you making progress.

On 11/21/2020 at 10:57 PM, DaveM said:

I understand what he's saying.  Since his Grand Prix cars were 4x wide, he had to build 4 sets of sprites for the car graphic, and use those when the cars reached the edge of the screen.  I'm assuming since my enemies are 2x wide, I'd only need to build 2 sets of sprites for each frame of animation for each enemy.  That doesn't seem to be much of a problem at first.  It looks like I have plenty of room in that first bank, and it's simple enough to construct extra sprites that only show half of each character.

 

But here's he potential problem: We have all the sprites lines up in the EnemyGfx array.  I remember as we were putting together the logic for the new kernel, the kernel wouldn't display any sprite that started after the 256th byte of that array.  Because I've got so many different enemies and objects in the game, I've already maxed that out.  Any additional sprites I add would push stuff way past that 256th byte.  So my guess is that if I tried doing all this, it wouldn't work anyway.  I would have to build an alternate array containing the "half" sprites, and have the kernel select that alternate array when setting up the enemy graphic; or, I would have to do four LSR's to each line when one of these "half" sprites are needed, and I don't think I have the cycle time to do either.  

 

Am I correct in all that?

I'll attempt to answer this or comment.

 

I'm familiarizing myself with your horizontal positioning. Your position routine gives your sprites a horizontal range of 5 - 164. This equates roughly to color clocks 73 - 232. If your sprites were ONE_COPY in size then the maximum horizontal position before a screen wrap would be 152 (i.e. roughly color clock 220). Your sprites are DOUBLE_SIZE. This gives a maximum horizontal value of 143 (i.e. roughly color clock 211) before a wrap around occurs.

 

Currently, the kernel example I supplied is doing an HMOVE on each scan line within a zone. This masks 8 pixels on the left. Because of this masking you can have a maximum horizontal position of 151 (i.e. roughly color clock 219) before the player sees the sprite wrap around. Given this, your sprite range should be...0 - 151 (i.e. roughly color clocks 68 - 219).

 

You have some decisions here. Here are some I've outlined though there could be more options...
(1) Like Grand Prix you would need additional sprites to show a smooth transition. You could have an additional graphic for masking that all the obstacles share. You'd need an ~additional 7 cycles to set the masking LSB value and an additional 8 cycles to mask the sprite data.
(2) You could add playfield graphics on either side of the playfield. Setting PF0 should give enough space to mask the player sprites for a smooth transition. The trade off though is the player looses ~ 8 pixels of the playfield on each side.
(3) You could not worry about the smooth transition and have the obstacles "vanish" when they reach their perspective boundaries. It's not bad to do this. Other games have done the same. I personally would prefer to see the transition but it wouldn't hurt not having it.

 

At the end of it all this is your game and whichever decision you make well...its yours. You only need to answer to yourself. So you want to be content on your decision.

 

I wish I kept a log of how many times I restarted my Climber 5 kernel. Trust me, it was a lot. All of these are learning experiences. Keep pushing through and having fun.

Link to comment
Share on other sites

On 11/17/2020 at 7:15 AM, DEBRO said:

To draw the missiles, I'm using the typical stack trick. Before entering the kernel, the stack is set to point to ENAM1. Since your missiles are one scan line high; this makes it easy to determine when to draw. The kernel mockup I sent will decrement the missile vertical position on each scan line (within a kernel section). I then "push" the result to the stack. This has benefit of when the subtraction reaches zero (i.e. when to draw the missile) the stack push moves the Z flag to ENAM1 and enables the missile. You can read more about this in Paul Slocum's ATARI 2600 ADVANCED PROGRAMMING GUIDE. Search for "Showing Missiles/Ball using PHP".

 

The kernel will need to be updated to allow time so set the new missile's vertical position so it can be decremented to know if it is time to draw. This could be done while positioning the obstacle. Currently the horizontal positioning routine takes up a full scan line. Splitting this up should allow time to set this new missile's vertical position. To do this, compare the obstacle's vertical position with the screen's midpoint. This will let you know which side the obstacle is to be placed. When the obstacle is to be positioned on the left then start the horizontal positioning and after set the missile's vertical position variable. When the obstacle is to be positioned in the right then use the early time to set the missile's vertical position variable before starting the obstacle's horizontal positioning. That's a lot of words...I know. I used this technique in Climber 5. A similar technique is also present in Asteroids. You can find my Climber 5 source code (as ugly as it is) for reference on @Atarius Maximus site. Look for "MoveGirderOnRight".

Sorry, I'm just not quite able to put all the pieces together here.  I looked at Slocum's guide (I think I get what he's doing... and thanks for sharing that link - I didn't know about that doc and it looks like it'll come in handy) and your Climber 5 code (I sorta get it) as you suggested, and I'm looking at my current code (the download from 2 posts above), and I can't quite figure out how to put it all together to get the 2nd missile to work.  These are all brand new concepts for me still, so I'm having a tough time comprehending these things sometimes.

 

9 hours ago, DEBRO said:

You have some decisions here. Here are some I've outlined though there could be more options...
(1) Like Grand Prix you would need additional sprites to show a smooth transition. You could have an additional graphic for masking that all the obstacles share. You'd need an ~additional 7 cycles to set the masking LSB value and an additional 8 cycles to mask the sprite data.
(2) You could add playfield graphics on either side of the playfield. Setting PF0 should give enough space to mask the player sprites for a smooth transition. The trade off though is the player looses ~ 8 pixels of the playfield on each side.
(3) You could not worry about the smooth transition and have the obstacles "vanish" when they reach their perspective boundaries. It's not bad to do this. Other games have done the same. I personally would prefer to see the transition but it wouldn't hurt not having it.

I think I'll play around with these options a little later on in the game's development.  I think for now, I'll go with option #3, and just try to get everything else working.  Once the game's playable again and I get to a point where I'm comfortable with everything else, I think I'll play around with the PF0 option a bit.

 

But for now, I still need a little assistance on the missiles.  

Link to comment
Share on other sites

I've been working on this the last few days, and I just can't figure this one out.  I'm stuck.  I thought I had it figured out a bit, but nothing worked.

 

Is anyone able to provide any further help?  I just don't know what to do at this point.

Link to comment
Share on other sites

9 hours ago, DaveM said:

I've been working on this the last few days, and I just can't figure this one out.  I'm stuck.  I thought I had it figured out a bit, but nothing worked.

 

Is anyone able to provide any further help?  I just don't know what to do at this point.

Could you describe in more detail how you are attempting to enable the missiles in your code, and what is or isn't happening when you try?

Link to comment
Share on other sites

9 hours ago, Karl G said:

Could you describe in more detail how you are attempting to enable the missiles in your code, and what is or isn't happening when you try?

Sure, no problem.

 

I've attached the latest copy of the code I'm working off of, so no one has to go searching for it.

 

I'm trying to implement the "Showing missiles using PHP" method in Paul Slocum's Advanced Programming Guide.  It seemed simple enough.  

 

Looking at the code Dennis wrote for my kernel, it looks like he sets this up properly before the kernel here:

Quote

   ldx #<ENAM1
   ldy #NUM_KERNEL_SECTIONS - 2
   sty tmpKernelSection
   txs                              ; point stack to ENAM1

Then the section of the kernel that draws the missile is here:

Quote

    ldx tmpKernelSection       ; 3         get current kernel section
    lda missileVertPos0,x      ; 4         get next missile vertical position
    sta tmpMissileVertPos      ; 3         set missile vertical position
    ldy #H_INNER_CAVE          ; 2
    sty tmpInnerCaveIdx        ; 3
    lda #0                     ; 2         assume we are not drawing Yo-Yo
    tax                        ; 2
    ldy tmpYoYoGraphicIdx      ; 3         get Yo-Yo graphic index
    cpy #H_YO_YO               ; 2
.drawPlayfieldLane
    bcs .drawYoYoInPlayfieldLane;2³        branch if not time to draw Yo-Yo
    sta ENABL                  ; 3 = @58   disable BALL (i.e. a = 0)
    lda (yoyoGraphicPtr),y     ; 5         get Mr. Yo-Yo graphic data
.drawYoYoInPlayfieldLane
    dec tmpYoYoGraphicIdx      ; 5         decrement Yo-Yo graphic index
    dec tmpMissileVertPos      ; 5 = @73
;
; At most cycle time ends at cycle 73. No more time available without focusing
; on constant cycle time.
;
    sta WSYNC
;--------------------------------------   fourth line after cave
    sta HMOVE                  ; 3
    sta GRP1                   ; 3 = @06
    php                        ; 3 = @09   enable / disable M1
    plp                        ; 4         point stack back to ENAM1
 


So I started by commenting out the highlighted lines above.  Basically, I wanted to replace those lines with lines from Slocum's guide.  The variables I'm using for the missiles' vertical positions are missileVertPos0,x and missileVertPos1,x, where 'x' is the number of the horizontal band that the missile will reside in.

 

I started by assigning the horizontal band number to x, and the scanline number to y, by inserting these lines in place of the dec tmpMissileVertPos line:

 

stx Temp

ldx tmpKernelSection

ldy tmpInnerCaveIdx

 

I then added a ldx Temp after the php and plp lines to restore that value.

 

Next, I tried adding the cpy instructions, but I got those wrong.  I tried:

cpy missileVertPos0,x

 

...but as I found out, I can't do that. 

 

My next step was to try to move the missileVertPos0,x  value to the A register, but as soon as I did that, I started exceeding the scanline count, and the screen started changing colors and flipping.

 

I tried a few other things after that, trying to set the A register to that value, but I always ran into cycle count issues.

 

So that's about it.  I'm kinda at a loss as to what my next steps should be.

 

 

 

Mr_Yo-Yo_B20201122.a

Edited by DaveM
Incomplete
Link to comment
Share on other sites

Hi David,

 

In the current kernel mockup I sent, each horizontal band holds a vertical position for a missile. Inside the kernel we pull the vertical position from missileVertPos,x (with x being the index for the horizontal band) and place it in the temporary variable tmpMissileVertPos. This value is decremented each scan line within the horizontal band. When the value reaches zero then the missile is enabled. A value of zero would be the scan line to show the missile. This is where the PHP trick comes in.

 

I believe this can be done with less RAM. I think I originally was thinking multiple missiles could be in flight for a given horizontal band. It's been a while so I'm not really sure if that was my original thinking. If only two missiles can be active at a time then the kernel could be redone to where only two RAM locations for vertical positioning is needed instead of using 6 (i.e. 12 with two missiles).

 

Also, the current mockup has a bug in it?‍♂️ Replace the PLP with PLA. The PLP opcode will affect processor status flags.

  • Thanks 1
Link to comment
Share on other sites

21 hours ago, DEBRO said:

I believe this can be done with less RAM. I think I originally was thinking multiple missiles could be in flight for a given horizontal band. It's been a while so I'm not really sure if that was my original thinking. If only two missiles can be active at a time then the kernel could be redone to where only two RAM locations for vertical positioning is needed instead of using 6 (i.e. 12 with two missiles).

There can be up to two missiles in flight at any given time.  Both missiles could be active within the same band.

 

21 hours ago, DEBRO said:

In the current kernel mockup I sent, each horizontal band holds a vertical position for a missile. Inside the kernel we pull the vertical position from missileVertPos,x (with x being the index for the horizontal band) and place it in the temporary variable tmpMissileVertPos.

Got it.  Since we need two missiles active, I've added a variable, so there's now missileVertPos0,x and missileVertPos1,x.  I'm unsure yet whether or not I'll need an additional tmpMissileVertPos variable, or if we can reuse the same one.  If an additional one is needed, I'm sure the "Temp" variable could be used here without affecting anything, and save us from allocating space for an additional variable, since I know I'm running low on that.

 

21 hours ago, DEBRO said:

Also, the current mockup has a bug in it?‍♂️ Replace the PLP with PLA. The PLP opcode will affect processor status flags.

Gotcha.  

 

Still can't figure out how to get it to work though.

Edited by DaveM
Link to comment
Share on other sites

So here's where I'm at....  Still can't get the 2nd missile to work.  I'm really hoping someone can see where I've gone horribly wrong and can correct it.  I've highlighted the lines I've added/changed in the samples below.

 

I start off by setting the top of the stack to ENAM1+1 prior to drawing the screen:

Quote

   ldx #<ENAM1+1
   ldy #NUM_KERNEL_SECTIONS - 2
   sty tmpKernelSection
   txs                              ; point stack to ENAM1

Then I've taken the code Dennis did, and added lines for the 2nd missile object, hoping to use the same method he did.  The result is a screen that flips out of control, as I've exceeded the scanline counts:

Quote

    ldx tmpKernelSection       ; 3         get current kernel section
    lda missileVertPos0,x      ; 4         get next missile vertical position
    sta tmpMissileVertPos      ; 3         set missile vertical position
        
        lda missileVertPos1,x
        sta Temp
        
    ldy #H_INNER_CAVE          ; 2
    sty tmpInnerCaveIdx        ; 3
    lda #0                     ; 2         assume we are not drawing Yo-Yo
    tax                        ; 2
    ldy tmpYoYoGraphicIdx      ; 3         get Yo-Yo graphic index
    cpy #H_YO_YO               ; 2
.drawPlayfieldLane
    bcs .drawYoYoInPlayfieldLane;2³        branch if not time to draw Yo-Yo
    sta ENABL                  ; 3 = @58   disable BALL (i.e. a = 0)
    lda (yoyoGraphicPtr),y     ; 5         get Mr. Yo-Yo graphic data
.drawYoYoInPlayfieldLane
    dec tmpYoYoGraphicIdx      ; 5         decrement Yo-Yo graphic index
    dec tmpMissileVertPos      ; 5 = @73       
;
; At most cycle time ends at cycle 73. No more time available without focusing
; on constant cycle time.
;
    sta WSYNC
;--------------------------------------   fourth line after cave
    sta HMOVE                  ; 3
    sta GRP1                   ; 3 = @06
    php                        ; 3 = @09   enable / disable M1
        dec Temp
        php
    pla                        ; 4         point stack back to ENAM1
        pla

I'm beyond frustrated with this.  This is the last thing I need corrected before I can continue with finishing up the game. I'm confident I can take care of the rest of the game with little to no problems, but I have to get this resolved first, and I'm at a bit of a loss as to how to do it.  Once this issue is resolved, I think I can wrap up the rest of the game in a matter of a few weeks, but I've been stuck on this for months!

Mr_Yo-Yo_B_2MissileFail.a

Link to comment
Share on other sites

I'm still stuck with this.  I've looked at this a few times since last week, and I'm a bit lost as to what my next steps to solve this problem really should be. 

 

I noticed a few people downloaded the code in the previous post.  Has anyone had a chance to look at the code and see if there's a solution? 

 

I know I have to learn more about writing kernels if I want to produce more games, and I intend to do that, but I guess I'm looking for a bit of a quick fix here as I'm kinda working against the clock for reasons I'll explain later on.  So I'm hoping someone's willing to work with me to add the 2nd missile in, so that I can continue with the rest of the game.  

On 12/3/2020 at 5:52 PM, DEBRO said:

I believe this can be done with less RAM. I think I originally was thinking multiple missiles could be in flight for a given horizontal band. It's been a while so I'm not really sure if that was my original thinking. If only two missiles can be active at a time then the kernel could be redone to where only two RAM locations for vertical positioning is needed instead of using 6 (i.e. 12 with two missiles).

If it can be done, I sure would like to know how to do it. ?

 

I've attached the mockup kernel Dennis did for the game.  It might be easier to look at the smaller bit of code rather than the full game.  After Dennis completed this file, I worked to implement the code into the game.  So if a 2nd missile can be added to this file, I can figure out how to add it to the game.

 

MYY__Dennis Kernel Mockup.a

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...