Skip navigation
NintendoAge
Welcome, Guest! Please Login or Join
Loading...

Ask all programming questions here!

Jul 22 at 2:43:19 AM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
Originally posted by: KHAN Games

You're only storing a variable that keeps track of where on the table you currently are.

I'm not sure how you're doing controller reads, but I'll post code here like is described in one of the later nerdy nights tutorials, week 7, as "Better Controller Reading."

Buttons: .rs 1 ;current button presses
MovementTimer: .rs 1 ;timer that needs to be reached in order for movement to begin
ShipDirection: .rs 1 ;current position on our lookup table for the ship direction

MoveShip:
  LDA Buttons ;load buttons variable
  AND #%00100000 ;only keep Left bit
  BEQ .TryRight ;if Left isn't held, branch to try Right
;;left is held
  INC MovementTimer ;increment movement timer
  LDA MovementTimer ;load increment timer
  CMP #$xx ;compare to whatever value you want
  BCC .End ;if it's less than this, go to end
  DEC ShipDirection ;decrement ship direction x2
  DEC ShipDirection
  LDA ShipDirection ;check to see if ShipDirection has wrapped around the table
  CMP #$FE
  BNE .Rotate ;if it hasn't jump to Rotate
  LDA #$0E
  STA ShipDirection ;reset ShipDirection to the highest starting value (you'll change this number when you add more directions to your table)
  JMP .Rotate ;jump to Rotate
.TryRight:
  LDA Buttons ;load buttons variable
  AND #%00010000 ;only keep Right bit
  BEQ .Reset ;if Right isn't held, branch to Reset to reset the MovementTimer variable since button isn't pressed
;;right is held
  INC MovementTimer ;increment movement timer
  LDA MovementTimer ;load increment timer
  CMP #$xx ;compare to whatever value you want
  BCC .End ;if it's less than this, go to end
  INC ShipDirection ;increment ship direction x2
  INC ShipDirection
  LDA ShipDirection ;check to see if ShipDirection has wrapped around the table
  CMP #$10
  BNE .Rotate ;if it hasn't, jump to Rotate
  LDA #$00
  STA ShipDirection ;reset ShipDirection to the lowest starting value
.Rotate:
  LDY ShipDirection ;load ShipDirection in the Y register
  LDA ShipLookupTable,y ;look at the sprite for the current direction using the Y register as the offset
  STA $0201 ;store
  LDA ShipLookupTable+1,y ;look at the attribute data for this direction
  STA $0202 ;store
  JMP .Reset ;reset MovementTimer
.End:
  RTS
.Reset:
  LDA #$00 ;reset the timer if Left or Right isn't pressed
  STA MovementTimer
  RTS

ShipLookupTable:
  .db $00,$00 ;up
  .db $02,%01000000 ;up/right
  .db $01,%01000000 ;right
  .db $02,%11000000 ;down/right
  .db $00,%10000000 ;down
  .db $02;%01000000 ;down/left
  .db $01,$00 ;left
  .db $02,$00 ;up/left

A better solution would probably be to move the Rotate part of the subroutine to its own subroutine that's constantly called so that when you implement de-accelaration (making the ship slowly stop spinning when you release the button) it isn't requiring a button press to set the current direction.

This should get you started though. Let me know if anything doesn't make sense.

Wow KHAN, thank you for your response!! You really can crank out this code quickly... I can't wait till I can do that, haha. Its a lot to take in, and its nothing like what I have so far, so I'm trying to understand it. 

Little things are throwing me off though, maybe I missed them in the NN weekly tutorials (I've been reading lots of different stuff). So for example:

1.) ShipDirection. So I see you initialized "ShipDirection: .rs 1 ", but what is its default value... 0? From the documenation says that rs is assigning the value to a symbol, but the value is taken from the internal counter. But why not use

ShipDirection: .rs 1 
vs
ShipDirection = #$01

I guess I'm not fully understanding the documenations description of the use of .rsset and .rs vice just making variables... wait instead of deleting all that, it may have clicked now that I had to type it out. Does the purpose of the .rs symbols allow you to change the value (such as INC / DEC) while the direct assignment to the value of 1 (#$01) would not work because it can only stay that one value? 
 
2.) I really had a hard time understanding a use case for this section, additionally why you chose $#0E (14 decimal?) as well:
...
  BNE .Rotate ;if it hasn't jump to Rotate
  LDA #$0E
  STA ShipDirection ;reset ShipDirection to the highest starting value (you'll change this number when you add more directions to your table)
  JMP .Rotate ;jump to Rotate
...

3.) General locations of things. I'm assuming that: 
- The Buttons and other variables go at the top before bank 0 and after iNES header
- The MoveShip to Reset labels can all go inside the NMI
- The ShipLocation data bytes go somewhere in bank 1, but I don't know why other than all my other db declarations are there (backgrounds, palettes, attributes, sprites, etc.). The why helps so that later on when I create more advanced demo / games I can understand how to place things more efficiently.  

Edited:
4.) Forgot one more. How does Buttons get populated? I thought after you latched the controllers, you had to read the value from $4016 into the accumulator (LDA $4016). So how does reading Buttons get a value from $4016?

Buttons: .rs 1 ;current button presses
...
MoveShip:
  LDA Buttons ;load buttons variable
...

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...


Edited: 07/22/2019 at 04:10 AM by oleSchool

Jul 22 at 5:52:27 PM
KHAN Games (89)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 8123 - Joined: 06/21/2007
Florida
Profile
Sorry that I wasn't more clear.

1.) The .rs 1 variables are simply declaring them as variables in zero page. The default value is zero I guess, since your clearmem routine is zeroing out everything upon bootup initalization. .rs 1 is simply reserving a byte of RAM for a variable called whatever we do a .rs 1 for. Your assessment is correct. Setting it to ShipDirection = #$01 would make that variable be 1 the entire game (a constant). Reserving a byte of memory allows us to change the value to anything we want at any time.

2.) When we're looking at the table I typed out (ShipLookupTable), we can see there are 16 values (two per direction. One for sprite, and one for attribute byte). If, for example, the ship is facing up, ShipDirection would be $00 since it's at the first value of the table. If we're still turning left, it would decrement that value twice. If we decrement $00 twice, it would be $FE, which has wrapped off the bottom of the table, so we want to instead set it to the highest first-byte value of our table, which is $0E (the sprite of up/left). The same thing applies in the opposite direction. If the ship is facing up/left and we continue to press the Right direction, it will increment ShipDirection twice, which would put the value at $10, which is higher (more values) than our table goes. We want to wrap it back to the lowest first-byte of the table, which is $00.

ShipLookupTable: (the following numbers are just POSITIONS. Not values. The red text doesn't really exist in the table, but the increment/decrement code will get there when you're inc/dec past where there are values, hence the need to reset back onto the table)
$FE,$FF; if you've decremented down to this point, you've wrapped off table. reset back to $0E
$00,$01
$02,$03
$04,$05
$06,$07
$08,$09
$0A,$0B
$0C,$0D
$0E,$0F
$10,$11; if you've incremented up to this point, you've wrapped off table. reset back to $00

3.) All of the .rs values go at the top before bank zero. This is called zero page. The MoveShip subroutine (which includes a .Reset local subroutine) can go anywhere in any bank. The ShipLocation table can also go anywhere, assuming you are using a mapper that doesn't bankswitch.

4.) As mentioned in my post, Buttons gets populated through a subroutine detailed in Nerdy Nights week 7, labeled "Better Controller Reading." You don't have to use it. I was just using it to more simply illustrate the button presses (but I would recommend learning to use it, as it's how I still read controllers to this day).

-------------------------

gauauu: look, we all paid $10K at some point in our lives for the privilege of hanging out with Kevin



Edited: 07/22/2019 at 05:58 PM by KHAN Games

Jul 22 at 7:13:33 PM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
Originally posted by: KHAN Games

Sorry that I wasn't more clear.

1.) The .rs 1 variables are simply declaring them as variables in zero page. The default value is zero I guess, since your clearmem routine is zeroing out everything upon bootup initalization. .rs 1 is simply reserving a byte of RAM for a variable called whatever we do a .rs 1 for. Your assessment is correct. Setting it to ShipDirection = #$01 would make that variable be 1 the entire game (a constant). Reserving a byte of memory allows us to change the value to anything we want at any time.

2.) When we're looking at the table I typed out (ShipLookupTable), we can see there are 16 values (two per direction. One for sprite, and one for attribute byte). If, for example, the ship is facing up, ShipDirection would be $00 since it's at the first value of the table. If we're still turning left, it would decrement that value twice. If we decrement $00 twice, it would be $FE, which has wrapped off the bottom of the table, so we want to instead set it to the highest first-byte value of our table, which is $0E (the sprite of up/left). The same thing applies in the opposite direction. If the ship is facing up/left and we continue to press the Right direction, it will increment ShipDirection twice, which would put the value at $10, which is higher (more values) than our table goes. We want to wrap it back to the lowest first-byte of the table, which is $00.

ShipLookupTable: (the following numbers are just POSITIONS. Not values. The red text doesn't really exist in the table, but the increment/decrement code will get there when you're inc/dec past where there are values, hence the need to reset back onto the table)
$FE,$FF; if you've decremented down to this point, you've wrapped off table. reset back to $0E
$00,$01
$02,$03
$04,$05
$06,$07
$08,$09
$0A,$0B
$0C,$0D
$0E,$0F
$10,$11; if you've incremented up to this point, you've wrapped off table. reset back to $00

3.) All of the .rs values go at the top before bank zero. This is called zero page. The MoveShip subroutine (which includes a .Reset local subroutine) can go anywhere in any bank. The ShipLocation table can also go anywhere, assuming you are using a mapper that doesn't bankswitch.

4.) As mentioned in my post, Buttons gets populated through a subroutine detailed in Nerdy Nights week 7, labeled "Better Controller Reading." You don't have to use it. I was just using it to more simply illustrate the button presses (but I would recommend learning to use it, as it's how I still read controllers to this day).

No worries about the clarity, hopefully my questions are coming off as I hope, very geniune.
I'm happy to get any help I can, and even if you never responded, I'd still be VERY grateful for what nudges you've given me so far  

Question 1
"since your clearmem routine is zeroing out everything upon bootup initalization" 
This sentence made the first part click, for whatever reason I never realized that..  

Question 2
The table you drew out makes lots of sense, I have to see it, and that made it click... the paragraph before it I'm still on my 4th read trying to gather it in, lol.. I'm a visual learner so takes me a while to get it, but thankyou!! 

Question 3
So yeah, I'm using nrom / mapper 0, because I don't know how to bankswitch yet. I'm baby stepping, single screen game (like asteroids). So no scrolling, no bank switching, etc. just getting the basics in this asteroids demo. Crawl, walk, run kinda plan.  It is interesting that you said the subroutine could go anywhere. I thought controller manipulation had to be in the NMI section, preferrably before you draw / update sprites.

The ShipLocation table going anywhere also blew me away.   I'm still learning banks and where stuff goes. I know based on my header for inesprg I have 1 16K bank for my code, ineschr I have 1 single 8KB for my bin / chr file. NN week 2 was where I based most of that information from. But for example, its not explained the purpose of $0800-$2000, which is another 6KB. So the purpose and addresses of each banks and overall total size (for mapper 0) I'm still a little fuzzy on. 

Question 4  
Gotcha. Yeah, I saw your code and it wasn't until earlier this morning it kinda clicked that it was code, but a bit psuedo code and I needed to use this with the week 7 subroutines. I was gonna delete my question but then I was like...oh well. 

Anyway, thanks again, I'll be working on this for the next few evenings I'm sure, and running into more issues I'm sure. But thats my joy in doing this, learning while creating something, so cool!



 

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...

Jul 23 at 9:18:50 AM
KHAN Games (89)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 8123 - Joined: 06/21/2007
Florida
Profile
ShipLookupTable: ;values
  .db $00,$00 ;up
  .db $02,%01000000 ;up/right
  .db $01,%01000000 ;right
  .db $02,%11000000 ;down/right
  .db $00,%10000000 ;down
  .db $02;%01000000 ;down/left
  .db $01,$00 ;left
  .db $02,$00 ;up/left

ShipLookupTable: ;positions (not actually in the game code. just writing for clarity's sake)

  .db $00,$01 ;up
  .db $02,$03 ;up/right
  .db $04,$05 ;right
  .db $06,$07 ;down/right
  .db $08,$09 ;down
  .db $0A,$0B ;down/left
  .db $0C,$0D ;left
  .db $0E,$0F ;up/left

If we load ShipLookupTable, it will be looking at the first value under ShipLookupTable. Position 0. The value just happens to also be $00. Bad example.

The way I'm looking up ShipLookupTable in the code I sent a few posts ago, I'm offsetting that by Y.

LDA ShipLookupTable,y

What this means is look up ShipLookupTable+y.

In this code, we are setting ShipDirection to Y and using that to tell us where in the table we want to use the values from.

So let's say ShipDirection is $06 and we load that into Y and then we LDA ShipLookupTable,y. That would be looking at the 6th position in the table. If we look at our positions table (which I've just written for clarity's sake and wouldn't actually be in the game code) we can see that is the first value of down/right, which is actually $02 if we look in the actual ShipDirection table. LDA ShipLookupTable,y would be $02.

LDA ShipLookupTable+1,y will load the value AFTER ShipLookupTable,y, because Y doesn't change. That would be looking at position 7, which is the palette attribute byte of down/right, which is %11000000.

So everything is basically automatic in the code I wrote. You're pressing a direction, it's running a delay timer so that it is facing a single direction for more than a single frame, then it's incrementing or decrementing ShipDirection by 2 to get to the next row of values in the table and using those values to 1) store the sprite tile and 2) store the sprite attribute byte.

No idea if you already understood this stuff, but it sounded like you might need more explanation on it so I tried to break it down more. If there's anything specific you're struggling with please let me know.

-------------------------

gauauu: look, we all paid $10K at some point in our lives for the privilege of hanging out with Kevin


Jul 23 at 2:36:09 PM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
Originally posted by: KHAN Games

ShipLookupTable: ;values
  .db $00,$00 ;up
  .db $02,%01000000 ;up/right
  .db $01,%01000000 ;right
  .db $02,%11000000 ;down/right
  .db $00,%10000000 ;down
  .db $02;%01000000 ;down/left
  .db $01,$00 ;left
  .db $02,$00 ;up/left

ShipLookupTable: ;positions (not actually in the game code. just writing for clarity's sake)

  .db $00,$01 ;up
  .db $02,$03 ;up/right
  .db $04,$05 ;right
  .db $06,$07 ;down/right
  .db $08,$09 ;down
  .db $0A,$0B ;down/left
  .db $0C,$0D ;left
  .db $0E,$0F ;up/left

If we load ShipLookupTable, it will be looking at the first value under ShipLookupTable. Position 0. The value just happens to also be $00. Bad example.

The way I'm looking up ShipLookupTable in the code I sent a few posts ago, I'm offsetting that by Y.

LDA ShipLookupTable,y

What this means is look up ShipLookupTable+y.

In this code, we are setting ShipDirection to Y and using that to tell us where in the table we want to use the values from.

So let's say ShipDirection is $06 and we load that into Y and then we LDA ShipLookupTable,y. That would be looking at the 6th position in the table. If we look at our positions table (which I've just written for clarity's sake and wouldn't actually be in the game code) we can see that is the first value of down/right, which is actually $02 if we look in the actual ShipDirection table. LDA ShipLookupTable,y would be $02.

LDA ShipLookupTable+1,y will load the value AFTER ShipLookupTable,y, because Y doesn't change. That would be looking at position 7, which is the palette attribute byte of down/right, which is %11000000.

So everything is basically automatic in the code I wrote. You're pressing a direction, it's running a delay timer so that it is facing a single direction for more than a single frame, then it's incrementing or decrementing ShipDirection by 2 to get to the next row of values in the table and using those values to 1) store the sprite tile and 2) store the sprite attribute byte.

No idea if you already understood this stuff, but it sounded like you might need more explanation on it so I tried to break it down more. If there's anything specific you're struggling with please let me know.

Dude, its your birthday and you're spending it on here helping me, what a guy!! That's it, I nominate KHAN Games for MOTM! (member of the month)   
But in all seriousness, much thanks again. I understood it about 90%, but even still I was able to learn more information.

The timing piece is nice, basically increment a few frames before branching off to actually rotate. That's pretty slick and could have other uses, so that's a tool I'm gonna keep in the bag. I'm playing around with different numbers to see what works the smoothest, 2 is still to fast, and 3 is way to slow, not sure why such a huge disparity in a single frame, but I'm working on it. 

As far as the indexing with the ShipLookupTable, I was happy you said this: "...then it's incrementing or decrementing ShipDirection by 2 to get to the next row of values in the table...".  For whatever reason I wasn't sure why you were INC/DEC x2, now I get it and that made the rest of the 10% click. It got me thinking though. Just for an exercise / my understanding purposes, I flattened out the code like so:

ShipLookupTable:
  .db $00,$00, $02,%01000000, $01,%01000000, $02,%11000000, $00,%10000000, $02,%01000000, $01,$00, $02,$00

And it still works, this helped me clarify the reason for DEC/INC x2, and it was because the values are in "pairs". Obviously harder to read / document / maintain so not recommended but it helped me get how it works a bit more. 

Very cool stuff! I'm always appreciative and happy birthday bro!  


 

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...

Jul 23 at 6:05:06 PM
KHAN Games (89)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 8123 - Joined: 06/21/2007
Florida
Profile
Thanks.   Sounds like you're fully understanding things now. That's awesome!

-------------------------

gauauu: look, we all paid $10K at some point in our lives for the privilege of hanging out with Kevin


Jul 29 at 3:02:17 AM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
Originally posted by: KHAN Games

Thanks.   Sounds like you're fully understanding things now. That's awesome!

Hmm... I thought so too until I tried to add a player 2 this week. Here I am late sunday on the weekend still can't get it lol. 
I added a second MoveShip, buttons2, even rotate2, end2, etc. (just to make sure it wasn't going to another subroutine and overwriting / getting lost)

No dice, so this is what I did for debugging so far (which seems to be my shortfall, so help me learn some debugging on this).
So I wanted to test the controller and the 2 sprites so I did this: 

1.) Setup FCEUX and tested that 2nd controller is being detected and usable. (CHECK)
2.) I swapped ReadController1's LDA $4016 for $4017 and the MoveShip to see if controller 2 could move sprite 1 (CHECK) 
3.) I swapped ReadController1's LDA $4016 for $4017 and the MoveShip to see if controller 1 could move sprite 2 (CHECK) 
3.) I changed from sprite 1's tile / attributes ($0201 / $0202) to sprite 2's tile and attributes ($0204 / $0205) to see if controller 2 could rotated sprite 2 (CHECK)

So I know its not the sprite code, I know its not the controller...so its the buttons2 / ship movement2 code. Well, I opened debugger, got lost   
I wanted to somehow setup a test to verify a few things:

1.) Is buttons2 being populated with a byte of correct values?
2.) View the AND results to see if it even sees left / right bits
3.) etc...but to step through the rest to see where its failing or jumping off. 

So if you or anyone can, I'd like to be helped a bit more on debugging rather than the answer to the problem. I really need to learn debugging and need some help with doing it. 

Thanks!

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...

Jul 29 at 7:18:21 AM
KHAN Games (89)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 8123 - Joined: 06/21/2007
Florida
Profile
Originally posted by: oleSchool

1.) Is buttons2 being populated with a byte of correct values?
 

I don't know how to do the other two things you're asking, as I'm pretty crappy with using the Debugger myself. But for this you just need to open the Hex editor in FCEUX (or Mesen) and look at the $0200-$02FF addresses. You can see what values all your sprites have for all their bytes. The addresses you gave for sprite 2 are wrong though (you gave the tile/attribute for sprite one, but v pos and tile for sprite two)

And you can look in the $0000-00FF area for your zero page variable values (like Buttons and Buttons2), but you have to count how many reserved bytes you've used ahead of these variables in order to narrow down exactly which byte to look at for each variable. (ie: the first zero page variable would be $0000, the second $0001, assuming they are all a single byte).

I can show you how to use the Debugger to break when your Buttons variable is not zero, but other than that I don't know how to step through the AND reads.

Open debugger and click on Add Breakpoint. After you've figured out which address your Buttons variable is, you'll want to type this address in both Address fields. (If you can't deduce which zeropage variable is your Buttons variable, you can open the FCEUX Hex Editor and start pressing directions and a/b. You should see a value jumping around as you press them.)

After you put the address in, you'll want to click on Write and then for condition put A != #0

This is pretty much the extent of my debugging skills.   Good luck!

-------------------------

gauauu: look, we all paid $10K at some point in our lives for the privilege of hanging out with Kevin



Edited: 07/29/2019 at 11:54 AM by KHAN Games

Jul 30 at 2:34:47 AM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
Originally posted by: KHAN Games
 
Originally posted by: oleSchool

1.) Is buttons2 being populated with a byte of correct values?
 

I don't know how to do the other two things you're asking, as I'm pretty crappy with using the Debugger myself. But for this you just need to open the Hex editor in FCEUX (or Mesen) and look at the $0200-$02FF addresses. You can see what values all your sprites have for all their bytes. The addresses you gave for sprite 2 are wrong though (you gave the tile/attribute for sprite one, but v pos and tile for sprite two)

And you can look in the $0000-00FF area for your zero page variable values (like Buttons and Buttons2), but you have to count how many reserved bytes you've used ahead of these variables in order to narrow down exactly which byte to look at for each variable. (ie: the first zero page variable would be $0000, the second $0001, assuming they are all a single byte).

I can show you how to use the Debugger to break when your Buttons variable is not zero, but other than that I don't know how to step through the AND reads.

Open debugger and click on Add Breakpoint. After you've figured out which address your Buttons variable is, you'll want to type this address in both Address fields. (If you can't deduce which zeropage variable is your Buttons variable, you can open the FCEUX Hex Editor and start pressing directions and a/b. You should see a value jumping around as you press them.)

After you put the address in, you'll want to click on Write and then for condition put A != #0

This is pretty much the extent of my debugging skills.   Good luck!

Yeah, typo for sprite 2 addresses. I was thinking "add 4" when I backspaced, so I typed 4, then added 1 for $0205..lol but all good. 

Hex editor was great. I saw the 8th byte (reserved for buttons2) populate correctly with every type of button press, so thats good to go! Very cool tip to learn as well. 

I added the breakpoint, but nothing happened. Seemed pretty straight forward, but no matter which controller or direction / button pressed, nothing happened. Did I miss something?




 

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...

Jul 30 at 3:15:21 PM
KHAN Games (89)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 8123 - Joined: 06/21/2007
Florida
Profile
I'm assuming it has to do with how the controller is read or something because when I try to use the same kinda breakpoint on another variable that doesn't have to do with a controller it works fine.

Like I said, I don't know much about using the debugger.

-------------------------

gauauu: look, we all paid $10K at some point in our lives for the privilege of hanging out with Kevin


Jul 31 at 4:53:07 AM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
Originally posted by: KHAN Games

I'm assuming it has to do with how the controller is read or something because when I try to use the same kinda breakpoint on another variable that doesn't have to do with a controller it works fine.

Like I said, I don't know much about using the debugger.

I'm honestly not sure what fixed it... but I put both MoveShip and MoveShip2 (copy of MoveShip but uses buttons2) outside the NMI, and created a JSR to MoveShip and JSR to MoveShip2 and now each controller can rotate each players ship. 
Not sure why that was needed, but it works... odd. 

 

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...


Edited: 07/31/2019 at 04:54 AM by oleSchool

Jul 31 at 9:07:14 AM
KHAN Games (89)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 8123 - Joined: 06/21/2007
Florida
Profile
I guess I would have had to see how things were organized prior, but glad it is working now.

-------------------------

gauauu: look, we all paid $10K at some point in our lives for the privilege of hanging out with Kevin


Aug 01 at 3:57:14 AM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
I'm very interested in the why simply so I know for later when it may bite me in the butt haha. Here is the current (attached). 

In its current version, both player 1 and 2 controllers can rotate their respective sprites. So to revert to the "non working" version you take lines 210 - 332  and cut them.
Then paste it over / replace the 2 "JSR MoveShip[1|2]" lines at the end of the NMI. I think you have to remove the last RTS as well since its no longer a subroutine being referenced, but that should be all.  
Player 1 controller will be able to spin the player 1 sprite, but Player 2 controller won't be able to spin player 2 sprite. 

Other than taking it out of the NMI and calling the MoveShip as a subroutine there's no changes to the code really. 

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...


Edited: 08/01/2019 at 03:58 AM by oleSchool

Aug 01 at 12:26:32 PM
KHAN Games (89)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 8123 - Joined: 06/21/2007
Florida
Profile
Well, looking at the code, in order for the code to work inside NMI after pasting it back in there, you'd have to take out more than a single RTS. The NMI needs to get all the way down to RTI no matter what, so your code needs to be modified a little bit. Basically in every spot there is a RTS in MoveShip1, you'll need to delete the RTS and instead JMP to MoveShip2, so the second ship's routine is read. Then every place there is a RTS in MoveShip2, you'll need to delete the RTS and instead JMP to the end of MoveShip2 (after the RTS after .Reset2) so that it arrives at RTI.

Writing it the way you have it currently written (moving the routines out of NMI and just JSR'ing to them) is way cleaner/easier due to the ability to use the RTS in the individual subroutines. Jumping back to the main NMI this way allows you to not have to keep track of all the weird flow of things.

Right now, if it hits an RTS inside of NMI without having to go through a JSR to get there, it is returning to god knows where and it will behave erratically. I'm surprised it worked at all, honestly.  

-------------------------

gauauu: look, we all paid $10K at some point in our lives for the privilege of hanging out with Kevin


Aug 04 at 5:40:41 AM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
Originally posted by: KHAN Games

Well, looking at the code, in order for the code to work inside NMI after pasting it back in there, you'd have to take out more than a single RTS. The NMI needs to get all the way down to RTI no matter what, so your code needs to be modified a little bit. Basically in every spot there is a RTS in MoveShip1, you'll need to delete the RTS and instead JMP to MoveShip2, so the second ship's routine is read. Then every place there is a RTS in MoveShip2, you'll need to delete the RTS and instead JMP to the end of MoveShip2 (after the RTS after .Reset2) so that it arrives at RTI.

Writing it the way you have it currently written (moving the routines out of NMI and just JSR'ing to them) is way cleaner/easier due to the ability to use the RTS in the individual subroutines. Jumping back to the main NMI this way allows you to not have to keep track of all the weird flow of things.

Right now, if it hits an RTS inside of NMI without having to go through a JSR to get there, it is returning to god knows where and it will behave erratically. I'm surprised it worked at all, honestly.  
I never got to say thanks bud! Yeah, all good now. 
Anyway, I thought it'd be cool if you had to hit refresh one more time  

But seriously, much thanks for the help, you guys rock!

 

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...

Oct 06 at 12:45:42 PM
LambBrainz (0)

(Mason Stooksbury) < Cherub >
Posts: 12 - Joined: 10/01/2019
Kentucky
Profile
Fellow kids, a quick question about "everything in NMI", "everything in main", and how to structure a game.

I've seen lots of different forums, articles on NesDev, answers here at NA, and other places talk about where to put the bulk of your code and mention something to the effect of "if your game is small enough" or "if your game isn't very complex", etc.

My question is (since no real context was provided in any of those places), what makes a game "small" or "complex" or "big"? Would small be something like Pong from Nerdy Nights or something smaller? Would complex be like SMB or Zelda II? I'm trying to have some examples so I know how exactly I would classify the game I'm working on so I don't have to do some massive overhaul later on and can do it more properly from the start. (Namely, deciding what functionality the NMI will do. Whether that's incrementing a counter like some people do, putting all the code in NMI which apparently SMB does, or making my code interrupt aware and going from there).

Thanks for the help whenever someone sees this,
LambBrainz

Oct 07 at 10:57:40 AM
Mario's Right Nut (352)
avatar
(Cunt Punch) < Bowser >
Posts: 6634 - Joined: 11/21/2008
Texas
Profile
My 0.02 would be to do it properly from the start, which, in my opinion, would be to put the NMI stuff in NMI and the rest in Main. It'll save you headaches later on, especially if you move onto bigger or better games.

Don't worry with doing it one way or the other depending on complexity, do it right. IIRC, NN and my tutorials all do it "correctly". It's been a while though.

-------------------------

This is my shiny thing, and if you try to take it off me, I may have to eat you.

Check out my dev blog.


Oct 07 at 11:48:52 AM
LambBrainz (0)

(Mason Stooksbury) < Cherub >
Posts: 12 - Joined: 10/01/2019
Kentucky
Profile
And "NMI stuff" being what exactly? Cause even that has varying answers. The most common being graphics updates and what not; but I've also seen the "NMI increments a counter" method as well. What is considered best practice in that regard?

Also, thanks for the reply!

Oct 07 at 2:17:55 PM
KHAN Games (89)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 8123 - Joined: 06/21/2007
Florida
Profile
Every game I've made has been entirely in the NMI, although I have had to fight background update flickering occasionally.

The "proper" way to do it is to create some sort of routine that writes to RAM all the background graphics/palette updates you need to do, and then when NMI hits it looks to see if there are values in that buffer and draws them. So you're always constantly putting the "next frame's updates" in RAM and then when NMI comes it draws them all at once in one fell swoop.

-------------------------

gauauu: look, we all paid $10K at some point in our lives for the privilege of hanging out with Kevin


Oct 07 at 2:37:01 PM
SoleGooseProductions (129)
avatar
(Beau ) < King Solomon >
Posts: 3503 - Joined: 04/22/2013
Michigan
Profile
My gamestate NMI is generally empty, depending on the gamestate. When it is needed it only does absolutely what is essential, like drawing background tiles. Any normal stuff like reading the controller, incrementing a single counter like a random seed, music, etc. all runs in a separate NMI space. See MRN's tutorials for what that might look like (thanks buddy, still using your basic setup six years later!).

These days I also split things like scroll writes, sprite 0 hits, and delay loops off from normal and gamestate NMI, which having NMI already in a separate area helped a lot with. Any time that you have to sit there and find a bunch of different ways to work around your own code it is probably time to start splitting things off.

-------------------------
"The light that burns twice as bright burns half as long..." ~ Blade Runner

SoleGooseProductions.com


Oct 07 at 3:08:43 PM
LambBrainz (0)

(Mason Stooksbury) < Cherub >
Posts: 12 - Joined: 10/01/2019
Kentucky
Profile
That makes sense, thanks for the responses everyone.

I like the buffer idea, I've seen that with drawing logic and it definitely becomes necessary when doing music (per MetalSlime's tutorials) so I'mma sharpen my skills with buffers and give that a go. And I'll definitely hunt down MRN's stuff and start working thru that.

Thanks again, everyone!