+Propane13 Posted April 13, 2008 Share Posted April 13, 2008 Hi! I want to make a demo, and I decided right off the bat to use 32K. I am not using bAtari for this, so I need a quick refresher on how to do this in assembly. On a 32K game with 8 banks, what do I need to do in order to swap between the 8 banks? LDA $FFF<bank> or something? Sorry for the easy question; there's a lot of discussion about different bankswitching methods in these forums, so searches are giving me lots of strange results. I'm just interested in the old-fashioned LDA method, so I can get something working. Any help would be appreciated. Thanks! -John Quote Link to comment Share on other sites More sharing options...
+Propane13 Posted April 13, 2008 Author Share Posted April 13, 2008 Oh, one other thing. Do I start in a random bank? If so, I assume that I need code in every bank at the startup vector's destination address that switches to the bank I want initially, correct? -John Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted April 13, 2008 Share Posted April 13, 2008 Check the source for Medieval Mayhem, specifically the JUMP_TABLE macro. I don't think the starting bank is defined, so you need the startup vector pointing somewhere valid in every bank. Quote Link to comment Share on other sites More sharing options...
+Propane13 Posted April 13, 2008 Author Share Posted April 13, 2008 That's a pretty wild table. I like it. I tried fusing this code into Nick Bensema's "how to draw a playfield" code. Seems that when I do this, I can't power up anymore-- I just get a black screen. I think either this means I now need to pass a parameter to z26 (which is odd, because mm.bin does not need it), or that I missed something. I have checked the code 3x, and am a little confused as to what I could have missed. The macros are in each bank, and if I trace via start vector in any bank, it should jump to Bank8, at section Bank8Code. So, am I missing something? bob.zip Thanks! -John Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted April 13, 2008 Share Posted April 13, 2008 In bank 8 change the following: org $F100 ... org $FF00 to org $F100 rorg $F100 ... org $FF00 rorg $FF00 Stella's quite helpful in tracking issues like this down. I went into the debugger by hitting ~ and right away noticed that the CMP for bank 8 was followed by JMP $F030 instead of $F100 that I expected to see. Quote Link to comment Share on other sites More sharing options...
+Propane13 Posted April 13, 2008 Author Share Posted April 13, 2008 You are the man! Thanks for the help. I am glad that I have a framework that I can start with now. -John Quote Link to comment Share on other sites More sharing options...
+Propane13 Posted April 28, 2008 Author Share Posted April 28, 2008 So, this framework is working great! My little project is coming along nicely. I was thinking that eventually, I may want to give this thing a shot on real hardware. To do that, I think I'll pick up a few of the "Atari 2600 8K/16K/32K PCB - Assembled w/Socket" boards from the Atariage store. The exact item can be found here: http://www.atariage.com/store/index.php?ma...products_id=218 The specs say that it supports standard "Atari F4 bankswitching". Is that what this method is called? Is it called this because of the LDA $FF(F4) through FF(FB) loads that do the bankswitching? I just don't want to mistakenly buy the wrong circuit board type. Thanks! -John Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted April 28, 2008 Share Posted April 28, 2008 Cool! It's not the most efficient since the table has all jumps in every bank*, but I found it easy to understand. I haven't bought any of those as I was able to get the Krokodile Cart, but you have to select the specific size you want(8K, 16K or 32K) in the drop-down when you order it. And yep, 32K is F4. Here's a Bankswitching guide that covers the various methods. * even though you're not going to jump from the Vertical Blank to the Over Scan, the bank with Vertical Blank code still has 6 bytes allocated for a jump to Over Scan. Quote Link to comment Share on other sites More sharing options...
+Propane13 Posted July 29, 2008 Author Share Posted July 29, 2008 So, I'm looking at taking this model, and shrinking it for 8K. Problem is, bank 2 is booting fine. But, the jumps to Bank1 are failing. Here's some code example. ;=================================== processor 6502 include vcs.h ;=================================== MAC JUMP_TABLE ; put this at the start of every bank RORG $F000 Bank1 cmp SelectBank1 jmp Bank1Code Bank2 cmp SelectBank2 jmp Bank2Code ENDM ;=================================== MAC BANKS_AND_VECTORS ; put this at the end of every bank RORG $FFFA SelectBank1 .byte $00 SelectBank2 .byte $00 ; .word Bank2 ; NMI and 8 overlap NMI .word Bank2 ; RESET .word Bank2 ; IRQ ENDM ;=================================== ... ;##################################################### ; Bank 1 below ;##################################################### org $E000 JUMP_TABLE org $E100 Bank1Code ; i.e GameInitBank1 ... ;============================== ORG $EFFA BANKS_AND_VECTORS ;============================== ;##################################################### ; Bank 2 below ;##################################################### org $F000 rorg $F000 JUMP_TABLE org $F100 rorg $F100 Bank2Code ... ;============================== ORG $FFFA BANKS_AND_VECTORS ;============================== ; org $FFFC ; .word Start ; .word Start In Bank2, I have the following code: GameCalcBank2 LDA SWCHB AND #%00000011 EOR #%00000011 BEQ ConsoleSwitchNotHit JMP Bank1 ConsoleSwitchNotHit From my perspective, everything looks the same as it did for the 32K version. But, the behavior is weird. Bank 2 is fine (264 scanlines). But, when I go to Bank1, it runs for 46 scanlines, and then jumps immediately back to bank 2. That makes me think I'm going "out there" somewhere. Is there something obviously wrong in the above framework? I can post more code if necessary, but I thought I'd double-check my base bankswitch code first. -John Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted July 29, 2008 Share Posted July 29, 2008 8K cartridges use F8 bankswitching, the hotspots in F8 do not overlap the NMI vector. MAC BANKS_AND_VECTORS; put this at the end of every bank RORG $FFF8 SelectBank1 .byte $00 SelectBank2 .byte $00 .word Bank2; NMI .word Bank2; RESET .word Bank2; IRQ ENDM ... ;============================== ORG $EFF8 BANKS_AND_VECTORS ;============================== ... ;============================== ORG $FFF8 BANKS_AND_VECTORS ;============================== Quote Link to comment Share on other sites More sharing options...
+Propane13 Posted August 27, 2008 Author Share Posted August 27, 2008 Seems I still can't get it to go.... I stripped it down as bare as I could. What's missing here? ;=================================== ; Constants NTSC = 1 ;=================================== ;=================================== processor 6502 include vcs.h ;=================================== MAC JUMP_TABLE ; put this at the start of every bank RORG $F000 Bank1 cmp SelectBank1 jmp Bank1Code Bank2 cmp SelectBank2 jmp Bank2Code ENDM ;=================================== MAC BANKS_AND_VECTORS; put this at the end of every bank RORG $FFFA SelectBank1 .byte $00 SelectBank2 .byte $00 .word Bank2; NMI .word Bank2; RESET .word Bank2; IRQ ENDM ;=================================== ;##################################################### ; Bank 1 below ;##################################################### org $E000 JUMP_TABLE org $E100 ;================= Bank1Code GameInitBank1 ;================= ;================= MainLoopBank1 ;================= JSR VerticalBlankBank1 ;Execute the vertical blank. JSR GameCalcBank1 ;Do calculations during Vblank JSR DrawScreenBank1 ;Draw the screen JSR OverScanBank1 ;Do more calculations during overscan JMP MainLoopBank1 ;Continue forever. ;================= VerticalBlankBank1 ;================= LDX #0 LDA #2 STA WSYNC STA VSYNC ; Begin vertical sync. STA WSYNC ; First line of VSYNC STA WSYNC ; Second line of VSYNC. IF NTSC LDA #44 ELSE ; (PAL) LDA #54 ENDIF STA TIM64T LDA #0 STA CXCLR ; now's as good a time as any to clear the collision latches. ; Now we can end the VSYNC period. STA WSYNC ; Third line of VSYNC. STA VSYNC ; (0) RTS ;================= GameCalcBank1 ;================= LDA #0 ; same as PAL and NTSC STA COLUBK ; Background will be black. ; set colors for first scanline LDA #3 STA CTRLPF IF NTSC LDA #$52 ELSE ; (PAL) LDA #$82 ENDIF STA COLUP0 IF NTSC LDA #$5E ELSE ; (PAL) LDA #$8E ENDIF STA COLUPF IF NTSC LDA #$76 ELSE ; (PAL) LDA #$D6 ENDIF STA COLUP1 RTS ;================= DrawScreenBank1 ;================= LDA INTIM BNE DrawScreenBank1 ; Whew! STA WSYNC STA VBLANK ; Enable drawing again (set vblank to 0) LDY #191 TitleScreenScanLoop1 STY PF0 STY PF1 STY PF2 STA WSYNC DEY BNE TitleScreenScanLoop1 ; Clear all registers here to prevent any possible bleeding. LDA #2 STA WSYNC ;Finish this scanline. STA VBLANK ; Make TIA output invisible, ; Now we need to worry about it bleeding when we turn ; the TIA output back on. LDY #0 STY PF0 STY PF1 STY PF1 STY GRP0 STY GRP1 STY ENAM0 STY ENAM1 STY ENABL RTS ;================= OverScanBank1 ;================= IF NTSC LDA #35 ELSE ; (PAL) LDA #85 ENDIF STA TIM64T ;================= GameCalc2Bank1 ;================= ;============================ ; Loop to get our 30 scanlines for overscan ;============================ WaitForEndOfOverscanBank1 LDA INTIM BNE WaitForEndOfOverscanBank1 STA WSYNC ; finish scanline 30 RTS ;============================== ORG $EFF8 BANKS_AND_VECTORS ;============================== ;##################################################### ; Bank 2 below ;##################################################### org $F000 rorg $F000 JUMP_TABLE org $F100 rorg $F100 ;================= Bank2Code Start ;================= SEI CLD LDX #$FF TXS LDA #0 B1 STA 0,X ; clear $FF through $1 (not $0, VSYNC) DEX BNE B1 ;================= GameInitBank2 ;================= ;================= MainLoopBank2 ;================= JSR VerticalBlankBank2 ;Execute the vertical blank. JSR GameCalcBank2 ;Do calculations during Vblank JSR DrawScreenBank2 ;Draw the screen JSR OverScanBank2 ;Do more calculations during overscan JMP MainLoopBank2 ;Continue forever. ;================= VerticalBlankBank2 ;================= LDX #0 LDA #2 STA WSYNC STA VSYNC ; Begin vertical sync. STA WSYNC ; First line of VSYNC STA WSYNC ; Second line of VSYNC. IF NTSC LDA #44 ELSE ; (PAL) LDA #54 ENDIF STA TIM64T LDA #0 STA CXCLR ; now's as good a time as any to clear the collision latches. ; Now we can end the VSYNC period. STA WSYNC ; Third line of VSYNC. STA VSYNC ; (0) RTS ;================= GameCalcBank2 ;================= LDA SWCHB AND #%00000011 EOR #%00000011 BEQ ConsoleSwitchNotHit ;======================== ; Reset was pressed. Start game JMP Bank1 ;======================== ConsoleSwitchNotHit LDA #0 ; Same color for PAL and NTSC STA COLUBK ; Background will be black. ; set colors for first scanline LDA #%00110011 STA CTRLPF IF NTSC LDA #$44 ELSE ; (PAL) LDA #$64 ENDIF STA COLUP0 IF NTSC LDA #$5E ELSE ; (PAL) LDA #$8E ENDIF STA COLUPF IF NTSC LDA #$98 ELSE ; (PAL) LDA #$B8 ENDIF STA COLUP1 RTS ;================= DrawScreenBank2 ;================= LDA INTIM BNE DrawScreenBank2 ; Whew! STA WSYNC STA VBLANK ; Enable drawing again (set vblank to 0) LDY #191 TitleScreenScanLoop2 STY PF0 STY PF1 STY PF2 STA WSYNC DEY BNE TitleScreenScanLoop2 ; Clear all registers here to prevent any possible bleeding. LDA #2 STA WSYNC ;Finish this scanline. STA VBLANK ; Make TIA output invisible, ; Now we need to worry about it bleeding when we turn ; the TIA output back on. ; Y is still zero. STY PF0 STY PF1 STY PF2 STY GRP0 STY GRP1 STY ENAM0 STY ENAM1 STY ENABL RTS ;================= OverScanBank2 ;================= IF NTSC LDA #35 ELSE ; (PAL) LDA #85 ENDIF STA TIM64T ;================= GameCalc2Bank2 ;================= ;============================ ; Loop to get our 30 scanlines for overscan ;============================ WaitForEndOfOverscanBank2 LDA INTIM BNE WaitForEndOfOverscanBank2 STA WSYNC ; finish scanline 30 RTS ;============================== ORG $FFF8 BANKS_AND_VECTORS ;============================== Quote Link to comment Share on other sites More sharing options...
+Propane13 Posted August 27, 2008 Author Share Posted August 27, 2008 Just to clarify. Starts in Bank2 (ok) Hit reset, goes to 43 scanlines, and back to bank2. Not sure if we hit bank1 at all. -John Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted August 27, 2008 Share Posted August 27, 2008 (edited) 8K cartridges are known as F8 bank switching as the hot spots are FFF8 and FFF9. You correctly changed the ORGs at the end of each bank to use xxF8, but the BANKS_AND_VECTORS macro is using RORG $FFFA instead of RORG $FFF8. I fixed that and it now crashes when RESET is hit - as before the ORG $E100 needs to be followed by RORG $F100. Once those changes are in place the screen shows: and hitting reset causes it to show: Revised source below, just change the .txt back to .asm 8k.txt Edited August 27, 2008 by SpiceWare Quote Link to comment Share on other sites More sharing options...
+Propane13 Posted August 27, 2008 Author Share Posted August 27, 2008 You Sir, are a gentleman. Thank you very much for finding those. Everything is great now, and I can finally start work on an 8K project. -John Quote Link to comment Share on other sites More sharing options...
+Propane13 Posted November 18, 2008 Author Share Posted November 18, 2008 One more 8K bank-switching question (using the current method). In the 32K world, the sequence of switching to different spots within a bank seemed pretty easy to me. 1) Power-up 2) Use table to determine start vector (let's say bank ; jump there 3) Bank 8 is a purely dedicated bank for clearing ram out, and displaying the title screen 4) In Bank 8, set a "jump address" for the program to redirect to once inside the next bank jumped to (such as $D030). 5) On "reset" event, go to any other bank (say, 2), and immediately jump to the "jump address" in that bank ($D030) using a JMP.ind. It seems to work very well for 32K game design. In that environment, if we ever jump to bank 8, we're reseting everything anyway, so having multiple addresses to jump to in that bank isn't necessary, and therefore works fine. Basically, what I'm saying is that Bank 8 has one entry point-- and that's for restarting the game via soft-reset and hard-reset. Now, in an 8K world, things are different. I have multiple addresses that I want to start out from in both banks when I switch to different banks. Say that I power up in bank 2. In this bank, we have 2 things that happen: 1) Initial RAM clearing/setting for power-up/reset 2) Some game code (for a mini-game). So, if I switch to bank 1 sometime in the game, and then need to go to bank 2, I have a problem. I need to differentiate the 2 paths. The way I had been coding before was to essentially do a JMP.ind in a bank right away, to get to the necessary address. However, since my initialization code is in bank 2, this won't work, as the values in my 2 return address variable bytes will either be a) random (from powerup) or b) fixed (set by me in bank 1 on purpose). I was thinking the best way to alleviate this sort of problem would be to have a simple check: Here's what I'm thinking: If in bank 2, - check return address high-byte and low-byte. Do they match valid values that could be set by bank 1? - if yes, then jump to that address - if no, then jump to "reset" routine address Though I know this can work, there is a 1/65536 chance that due to random powerup data in RAM, we may jump to the "Gameplay" routine in this bank instead of the initialization routine. On a console that is "fried", or with slowness to clear memory out on powerdown/powerup, I'm sure this is figure is more alarming. So, the questions are: 1) Is this a gamble that I can live with, without any worry? 2) Is there a better way to do this? Thanks a lot! -John Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted November 18, 2008 Share Posted November 18, 2008 From what I understand, you are trying to execute a random bank after ramclear has executed from a specific bank. If that's the case, just have an index register hold a random value that's used in conjunction with the bankswitch instruction (so a random hotspot is accessed). You only need 1 bit for 8k, 2 bits for 16k, and 3 bits for 32k...so you could couple this with 7800 code-detection if desired (that's not done here, tho). Example 8k: each bank holds a different program, the second bank only holds the startup routine. ORG $1000 RORG $D000 ;the 2600's bankswitch status is unknown ;on powerup...so just place identical code ;in both banks at the same point. The ;start of ROM is used here... START1: LDA $1FF9;select 2nd bank JMP START;superfluous here, used for filler ;second game LDA $1FF8,Y;Y should hold 0 or 1 for 8k ;...program for first bank continues here... ORG $1FF8 RORG $DFF8 .word 0,0,START1,START1 ORG $2000 RORG $F000 START2: LDA $1FF9;no effect here JMP START;execute ram clear Game: LDA $1FF8,Y;Y should hold 0 or 1 for 8k ;...program for second bank continues here... ;at some other point in the 2nd bank, place your ;ramclear loop. Done at the end of ROM here: ORG $2FE5 RORG $FFE5 START: LDY INTIM;used for random value later LDA #$00 TAX RamClear: STA $00,X TXS INX BNE RameClear TYA;now handle the random bank... AND #$01;keep only the low bit TAY;give it back to the Y register JMP Game ORG $2FF8 RORG $FFF8 .word 0,0,START2,START2 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.