Mallard Games Posted August 7, 2019 Share Posted August 7, 2019 Hi again, Did a bit of restructuring and now it seems to go to the correct bank on power up. The issue I think is right after that it jumps into no man's land a.k.a RAM and never returns which results in a black screen with a brown messed up playfield and a horrible death sound. ? The strange part is bank 0 is so small it is latterly only a few bytes in size with only a few calls to the required syncing subroutine, and then the title screen kernel which draws the title screen using the playfield and yes all the graphics are in the same bank. Links Source Listing Binary Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted August 7, 2019 Share Posted August 7, 2019 If you step through it with Stella's debugger, you should be able to spot the problem. Worth learning. Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted August 7, 2019 Share Posted August 7, 2019 You appear to be starting up in Bank 0, and calling VerticalSync (which is in another bank) without actually switching that bank in. I don't know enough about the bankswitch scheme you are using to know if that's an issue, but stella certainly doesn't seem to be stepping into that routine. So I'd be looking at which banks are switched in, and where the subroutines you call actually live. Quote Link to comment Share on other sites More sharing options...
Mallard Games Posted August 7, 2019 Author Share Posted August 7, 2019 (edited) 17 minutes ago, Andrew Davie said: If you step through it with Stella's debugger, you should be able to spot the problem. Worth learning. Alright I'll pretent I'm the world famous Andrew Davie who's disassembling yet another game. ? Ok, this is strange to me: L101f .byte a0 ;ldy ;2-6 That is this bit of code: sta Random ; use it to seed the random number generator Next line: L1020 jsr L101F ;6 That should be this this: jsr VerticalSync ; perform vertical sync but instead it's jumping back to our sta Random code, very weird. Anyways: 1029 jmp L1020 ;3 This should be jumping to the top of our loop, but instead it's jumping back to our vertical sync routine..... and then to top it all off it jumps back to sta Random instead of the top of the title screen loop. Update: All my subroutines and "logic" live in Bank 2. Bank 3 is reserved for sound effects and music. So I have to add a sta $FFF8 ; bank into subroutines every time I want to call a subroutine? That can amount to dozens of repetitions of the above code. Edited August 7, 2019 by Mallard Games Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted August 7, 2019 Share Posted August 7, 2019 Sometimes the debugger gets confused about which label to use when more than one have the same value, and also what is code and what is not code. But that area is exactly a clue that something is going wrong right there. It just so (unfortunately for you) happens that the label 'verticalsync' happens to correspond to that particular position in your code in BANK 0. If you step through (let's ignore the first time), then at the bottom of the loop it jumps to "TitleScreenLoop" Then the first thing it does is "jsr VerticalSync". Note that that label is displayed by the debugger as being one BYTE up above that call So it jsr's to the '$a0' as code, and tries to execute that. Uh oh. It should be jsr'ing to the VerticalSync at that address IN THE OTHER BANK, not this one. That's your problem, almost certainly. As I said, incorrect bank switched in for call to that subroutine. Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted August 7, 2019 Share Posted August 7, 2019 Oh, and kudos for making the effort and actually looking at the debugger. It is a very handy tool which will be your best friend before you know it. Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted August 7, 2019 Share Posted August 7, 2019 I am not familar with the ins and outs of the bankswitch scheme you are using, so I'm no help sorry. But basically, if you have stuff in different banks, then you have to make sure your desired bank is accessible before using it! And, in some schemes you have to be careful about switching OUT the bank you're in when you try to switch in another bank you need. So, that's all I'll say - work on your bankswitching Quote Link to comment Share on other sites More sharing options...
Mallard Games Posted August 7, 2019 Author Share Posted August 7, 2019 14 minutes ago, Andrew Davie said: I am not familar with the ins and outs of the bankswitch scheme you are using, so I'm no help sorry. But basically, if you have stuff in different banks, then you have to make sure your desired bank is accessible before using it! And, in some schemes you have to be careful about switching OUT the bank you're in when you try to switch in another bank you need. So, that's all I'll say - work on your bankswitching I'm using the standard Atari F6 bankswitching scheme. Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted August 7, 2019 Share Posted August 7, 2019 1 minute ago, Mallard Games said: I'm using the standard Atari F6 bankswitching scheme. First I've heard of it Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted August 7, 2019 Share Posted August 7, 2019 F6: 'hot spots' are 1FF6, 1FF7, 1FF8, and 1FF9. By accessing these addresses, you can select which 4K block to use. Note that accessing one of these addresses changes the *whole* 4K block! You must make sure you pick up where you left off in your code! i.e. If you're executing a program fragment in bank 0 (1FF6) and want to change to bank 1 (1FF7), you do so by issuing a 'fake' read of some sort. ususally it's by an 'LDA $xxxx'- type instruction. When the LDA $1FF7 (in our case) finishes executing, the processor will be in the #1 bank, with the program counter otherwise un-affected. So, to execute a subroutine in bank 2 from bank 1 we have to: Bank #1 Bank #2 -------------------------------------------------------------- 1000 JSR $1800 (do subroutine) . 1003 (program continues) 1200 _subroutine goes here_ . 1209 RTS . . 1800 LDA $1FF8 (switch to bank 2) 1802 (rest of program) 1803 NOP 1803 JSR $1200 1804 NOP . 1805 NOP . 1806 NOP 1806 LDA $1FF7 (Switch back to bank 1) 1807 NOP . 1808 NOP . 1809 RTS (We're done w/ routine) 1809 (rest of program) OK, we start out in bank #1 and we want to run a subroutine in bank #2. What happens is this- the processor starts at 1000h in bank #1. We call our subroutine from here. 1800h: We do a read to change us to bank #2. Remember that when we change banks, we are basically doing a ROM swap. (You can think of bankswitching as 'hot-swapping' ROMs) Now that we're in bank #2, the processor sees that JSR to $1200, which is the subroutine that we wanted to execute. We execute the subroutine and exit it with an RTS. This brings us back to 1806h. We then do another read to select bank #1. After this instruction finishes, the processor is now in bank #1, with the program counter pointing to 1809, which is an RTS which will take us back to 1003 and let us continue on with our program. Ugly! Quote Link to comment Share on other sites More sharing options...
Mallard Games Posted August 7, 2019 Author Share Posted August 7, 2019 5 hours ago, Andrew Davie said: F6: 'hot spots' are 1FF6, 1FF7, 1FF8, and 1FF9. By accessing these addresses, you can select which 4K block to use. Note that accessing one of these addresses changes the *whole* 4K block! You must make sure you pick up where you left off in your code! i.e. If you're executing a program fragment in bank 0 (1FF6) and want to change to bank 1 (1FF7), you do so by issuing a 'fake' read of some sort. ususally it's by an 'LDA $xxxx'- type instruction. When the LDA $1FF7 (in our case) finishes executing, the processor will be in the #1 bank, with the program counter otherwise un-affected. So, to execute a subroutine in bank 2 from bank 1 we have to: Bank #1 Bank #2 -------------------------------------------------------------- 1000 JSR $1800 (do subroutine) . 1003 (program continues) 1200 _subroutine goes here_ . 1209 RTS . . 1800 LDA $1FF8 (switch to bank 2) 1802 (rest of program) 1803 NOP 1803 JSR $1200 1804 NOP . 1805 NOP . 1806 NOP 1806 LDA $1FF7 (Switch back to bank 1) 1807 NOP . 1808 NOP . 1809 RTS (We're done w/ routine) 1809 (rest of program) OK, we start out in bank #1 and we want to run a subroutine in bank #2. What happens is this- the processor starts at 1000h in bank #1. We call our subroutine from here. 1800h: We do a read to change us to bank #2. Remember that when we change banks, we are basically doing a ROM swap. (You can think of bankswitching as 'hot-swapping' ROMs) Now that we're in bank #2, the processor sees that JSR to $1200, which is the subroutine that we wanted to execute. We execute the subroutine and exit it with an RTS. This brings us back to 1806h. We then do another read to select bank #1. After this instruction finishes, the processor is now in bank #1, with the program counter pointing to 1809, which is an RTS which will take us back to 1003 and let us continue on with our program. Ugly! Well I've made some progress at least. The issue I'm having now is trying to figure out how the #^*_ I'm supposed to get back to the correct respective display bank. I figured out how to get to the subroutine bank to perform the subroutines but, now how to get back! ??? Source Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted August 7, 2019 Share Posted August 7, 2019 (edited) 22 minutes ago, Mallard Games said: Well I've made some progress at least. The issue I'm having now is trying to figure out how the #^*_ I'm supposed to get back to the correct respective display bank. I figured out how to get to the subroutine bank to perform the subroutines but, now how to get back! ??? Source As the documentation posted gives an example, I suggest you read it carefully. You need to bankswitch again, back to the original. But you have to have the correct code at the very next PC address after the bankswitch. That is, if you are in bank 2, and you want to return to bank 0, then just after the bankswitch read/write to bank 0, execution will *continue* from the current PC address... but in bank 0. You need to know exactly where you're "at", so to speak, and write the code accordingly. That's why I said "ugly!". It must be a nightmare to program using this scheme. Edited August 7, 2019 by Andrew Davie removed dumb suggestion Quote Link to comment Share on other sites More sharing options...
Mallard Games Posted August 7, 2019 Author Share Posted August 7, 2019 15 minutes ago, Andrew Davie said: As the documentation posted gives an example, I suggest you read it carefully. You need to bankswitch again, back to the original. But you have to have the correct code at the very next PC address after the bankswitch. That is, if you are in bank 2, and you want to return to bank 0, then just after the bankswitch read/write to bank 0, execution will *continue* from the current PC address... but in bank 0. You need to know exactly where you're "at", so to speak, and write the code accordingly. That's why I said "ugly!". It must be a nightmare to program using this scheme. The only other option is to waste space by duplicating the subroutines every bank which defeats the purpose of having the extra space in the first place. @Andrew Davie weren't you a programmer back in the day? @Nukey Shay We're a bit stumped on how to proceed and need your godly advice. Quote Link to comment Share on other sites More sharing options...
+splendidnut Posted August 7, 2019 Share Posted August 7, 2019 This might help: 1 Quote Link to comment Share on other sites More sharing options...
+splendidnut Posted August 7, 2019 Share Posted August 7, 2019 And another one: 1 Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted August 8, 2019 Share Posted August 8, 2019 3 hours ago, Mallard Games said: The only other option is to waste space by duplicating the subroutines every bank which defeats the purpose of having the extra space in the first place. @Andrew Davie weren't you a programmer back in the day? Yes, I was. I would never use a bankswitching scheme like this one, given a choice . I don't think you are correct that "the only other option is..", but I do think that you're going to have a lot of pain ensuring that your code works. Quote Link to comment Share on other sites More sharing options...
Mallard Games Posted August 8, 2019 Author Share Posted August 8, 2019 34 minutes ago, Andrew Davie said: Yes, I was. I would never use a bankswitching scheme like this one, given a choice . I don't think you are correct that "the only other option is..", but I do think that you're going to have a lot of pain ensuring that your code works. Ok assuming I was you, what bankswitching scheme would I use? ? Quote Link to comment Share on other sites More sharing options...
+Karl G Posted August 8, 2019 Share Posted August 8, 2019 Once you have macros/routines setup to abstract the process, you really don't have to think about the underlying bankswitching scheme much, and can switch to a different one under the hood if you need to with a minimum of pain. Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted August 8, 2019 Share Posted August 8, 2019 34 minutes ago, Mallard Games said: Ok assuming I was you, what bankswitching scheme would I use? ? Assuming you were me, you'd most likely design your own bankswitching scheme because you'd be too lazy to learn how to use the ones that are out there but to be serious for just a few seconds... the bankswitching scheme you use depends on the needs of the game you want to write. There are pros and cons for each, and you need to understand those. For example, my games these days (what few there are) like having lots of RAM to play with. So I choose a bankswitch scheme that allows that. Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted August 8, 2019 Share Posted August 8, 2019 14 hours ago, Andrew Davie said: It must be a nightmare to program using this scheme. Not at all. Since F8 is the most-common scheme out there, and F6 & F4 are just adding additional 4k blocks, those are virtually identical. Just the hotspots need adjusting between all 3 schemes. And an additional 128 bytes of SARA Ram can later be added just by leaving the first 256 bytes of Rom untouched. The OP needs to get accustomed to how bankswitching is accomplished...this is the ~Nth example of this specific programs' routines being called when a different bank is switched in. I'd suggest scaling things back to 8k (F8) until those introductory issues are learned to be avoided. Once F8 is skillfully managed, then move to larger Rom sizes. Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted August 8, 2019 Share Posted August 8, 2019 1 minute ago, Nukey Shay said: Not at all. I have pretty strange nightmares 1 1 Quote Link to comment Share on other sites More sharing options...
Mallard Games Posted August 8, 2019 Author Share Posted August 8, 2019 (edited) 14 minutes ago, Nukey Shay said: Not at all. Since F8 is the most-common scheme out there, and F6 & F4 are just adding additional 4k blocks, those are virtually identical. Just the hotspots need adjusting between all 3 schemes. And an additional 128 bytes of SARA Ram can later be added just by leaving the first 256 bytes of Rom untouched. The OP needs to get accustomed to how bankswitching is accomplished...this is the ~Nth example of this specific programs' routines being called when a different bank is switched in. I'd suggest scaling things back to 8k (F8) until those introductory issues are learned to be avoided. Once F8 is skillfully managed, then move to larger Rom sizes. The issue with that is I don't remember if I had enough space for my title screen since most of the space was taken by the playfield data that the title screen is made up of. Edited August 8, 2019 by Mallard Games Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted August 8, 2019 Share Posted August 8, 2019 Solution: Don't use a title screen for now. Get the game working first. Eye candy can (and should) be added later. Quote Link to comment Share on other sites More sharing options...
Mallard Games Posted August 10, 2019 Author Share Posted August 10, 2019 Hey, Sorry for the silence, but I tried using the Medevil Mayhem macros to get bankswitching to work sith no success. What's weird is Stella detects it as a non-bankswitched game and not a F6 bankswitched one. Anyways I am post the latest code here to see if anyone can figure out what's going on. Source Bankswitch Macro List File Binrary Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted August 10, 2019 Share Posted August 10, 2019 That is because A) your vectors are in the wrong locations again, and B) your program has untagged code following JMP instructions. A) for whatever reason, you commented out the NMI vector. Even tho the macro then declares RORG to be $FFFC for the next 2 vectors, Dasm is still using $FFFA as the actual Rom address. Keep in mind that only ORG has the ability to reset the address. RORG just forces the addresses to be called something else. Solution: reinstate the NMI vector (or add 2 bytes of filler) to make up for the 2-byte shortfall. The following RORG $FFFC is not needed at all. B) You've got JMP's and JSR's intermingled everywhere, so it's difficult to follow which is supposed to be which. Consider the following loop: GameLoop jmp VerticalSync ; perform vertical sync jmp CheckJoystick ; check for joystick input jmp ClampObjects ; clamp the objects to the screen jmp PositionObjects ; position the objects jsr GameScreen_Kernal ; jump to game kernal jmp OverScan ; (3 13) jump to OverScan Routine jmp GameLoop The program jumps to VerticalSync and no tags exist below it, so the rest of the loop is never executed at all. Are these supposed to be subroutines or jumps? Take my advice. Go back to F8. Babystep until you've got something that runs. 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.