Jump to content
IGNORED

Bank Switching Madness - I just don't get it why it won't work!


Pixman

Recommended Posts

Hi folks,

 

I saw many examples, but none that satisfied my learning for a working program.

 

I don't know what I am doing wrong.

Look at this, I wrote a little program, that displays on every 192 scanlines a different color.

 

You can see it here:

http://pastebin.com/xbQu8FNk

 

Written like this, it works.

I'm working on something big and I really need the 8kb for that.

Here's the code I can't get to work:
http://pastebin.com/4b8CpeMj

 

It should come back after a few nops and the program should run flawlessly! All I get is a black screen and some beeping noises. Sometimes some garbled graphics.

 

Can please anybody explain me this properly?

I worked 4 hours on this crappy bank switching. It seems all so easy, I'm missing something.

I'd be very grateful for any help!

My brain is hurting. Really. I just don't get it. And I have plenty of experience in C64/6502 and PC development.

 

Thank you :)

 

Best Regards,

Pix

Edited by Pixman
Link to comment
Share on other sites

I can see what's wrong, though I don't have time to go into detail at the moment. For now, I suggest you use Stella's debugger mode to single step through the code so you can see what's happening, that should provide you with some insight to help you figure out what's wrong.

 

You can also check out the development history for Medieval Mayhem, this blog entry was when I implemented bankswitching.

Link to comment
Share on other sites

Oh, this is awesome. :)

I thank you a lot. I will try this when my brain is a bit more unstuck. I'm currently also fighting with Quaternions (grrr, evil fuckers ;)).

 

Very interesting, I think I might figure it out with this. I'll give some feedback if I can.

 

 

BTW, in your code, I can't see any usage of $1ff6 to $1ff9, which is a bit confusing to me.

How's that?

I saw into your macros. They make sense, sure. But I don't get why you don't have to fiddle around with setting the banks with those particular registers.

 

€dit: Oh, I see, you're doing this on each bank with

SelectBank1 .byte $00
SelectBank2 .byte $00
SelectBank3 .byte $00
SelectBank4 .byte $00

 

But what I don't get, you never write any values into those bytes.

Or are you going back to bank 1 each time?

Edited by Pixman
Link to comment
Share on other sites

Yep - using labels instead of $1ff6 to $1ff9 makes the code self documenting, no need to remember what each and every memory location is used for. Also those memory locations depend upon the type of bank switching you're using, for 32K games $1ff4 is used to select the first bank.

 

All that's required to trigger a bankswitch is for the 6507 to access those memory locations. You could use any of these methods for it to work:

  sta SelectBank1
  lda SelectBank1
  cmp SelectBank1
  nop SelectBank1


Nowadays I'd most likely use nop because it doesn't doesn't change any of the registers or CPU flags.

Link to comment
Share on other sites

The 6502 processor can address 64K of memory, but the 6507 in the Atari doesn't have as many pins to connect to the circuit board so it's limited to addressing 8K. However, internally it's still a 6502 so it thinks it's addressing 64K.

 

This ends up creating what are known as mirrors. The memory location $1ff6 is the same as $3ff6, $5ff6, $7ff6, $9ff6, $bff6, $dff6 or $fff6.

 

I'm going offline for a few hours, later.

Link to comment
Share on other sites

Well, I kinda got it working with a simple example I modified:

processor 6502
;---BANK ONE---

   org $D000
   rorg $F000
   
b1:
nop
nop
nop
inc $82
sta $fff7
jmp b2
;--code code code

   org $DFFA
   rorg $FFFA
    .word b1
    .word b1
    .word b1
;--bank one vectors here.

;---BANK TWO

   org $E000
   rorg $F000
    b2:
    nop
    nop
    nop
    sta $eff6
    inc $81
    jmp b1
;---code, code, code, code

   org $EFFA
   rorg $FFFA
    .word b2
    .word b2
    .word b2

But when I check in the debugger, I get steps of four in $81. Dunno why.

Any idea?

Anyway, I'd be glad, if anybody could help me out with an easy solution to the first example (with the colored scanlines in the OP) using 2 banks.

Don't care if the 2nd bank does nothing or just display a playfield or something.

I somehow don't get it to work as I want it for me. very weird stuff is going on. ;)

Link to comment
Share on other sites

Just curious, what does "rorg $FFFA" directive do? I know org is the initial position, but rorg, I couldn't find the directive meaning of this. I don't think you need any data at the bankswitching hotspot. As I remember you have to read that address to trigger the bankswitching. I think the mapper of the chip get probed if being read at that address. You may have to store the program pointer before bankswitching to point the direction where the data is on the other chip.

Link to comment
Share on other sites

Haha, that's a nice on.

Thanks for the support so far.

 

I already thought, that I was missing the thing about the PC-thing.

The only bank switching I did so far was on the C64 with the VIC-II, means: I switched 16kb blocks which didn't actually interfere with the actual code, basically. But since the VIC-II graphic chip only can see 16kb at once, you can switch between 4 blocks and mandy different screen RAM & bitmap adresses :)

 

I think I get it now.

 

I've got an F8 scheme working now.

I can't believe I didn't get it.

I already got it before but I implemented it all the way wrong.

 

 

For the sake of documentation:

processor 6502
;---BANK ONE---

   org $d000
   rorg $f000

b1:
nop
nop
inc $82
lda $fff9
jmp b2
; Using the same amount of bytes as in b1/b2, so that the program counter (PC) jumps back at the right address when we switch banks

   org $DFFA
   rorg $FFFA
    .word b1
    .word b1
    .word b1
;--bank one vectors here.

;---BANK TWO

   org $e000
   rorg $f000
    b2:
    nop
    nop
    inc $81
    lda $fff8
    jmp b1
;same as above

   org $EFFA
   rorg $FFFA
    .word b2
    .word b2
    .word b2

I don't want to be grumpy, but could it have been so hard to explain it like that with a code like this? Seriously?

Edited by Pixman
Link to comment
Share on other sites

Just curious, what does "rorg $FFFA" directive do? I know org is the initial position, but rorg, I couldn't find the directive meaning of this. I don't think you need any data at the bankswitching hotspot.

 

ORG sets the actual address, whereas RORG is used to relocate the code to some other logical address.

 

For example, if you're going to create a 16K ROM image then you can set ORG to $C000 at the beginning of the code, which would give you room for 16K from $C000 to $FFFF. But each 4K ROM bank needs to be at an address which reduces to $1000 after you strip off the three highest bits, which can't be "seen" by the address bus since it has 13 bits instead of 16. So you could use RORG $9000 for the first 4K of the ROM image, then RORG $B000 for the second 4K, then RORG $D000 for the third 4K, and RORG $F000 for the last 4K. The assembler will use each bank's RORG address for any instructions that reference memory addresses within that bank. If you don't give a RORG address, the ORG address will be used.

 

There are a few things to note:

 

If you're using RORG addresses for everything in the ROM image then the ORG address doesn't matter-- it could be $0000, $1000, $2000, etc. I'm not sure if it matters whether the ORG addresses overlap the addresses for the TIA, RAM, and RIOT, since they aren't part of the actual ROM image.

 

If you are using RORG, the addresses for each bank don't need to be in order and don't need to be different. For example, you could use RORG $F000, RORG $F000, RORG $F000, RORG $F000 if you wanted, although giving each bank a unique address range makes it easier to keep track of which bank is which when you're looking at an assembly listing. Or you could use RORG $F000 for the first bank, RORG $D000 for the second bank, RORG $B000 for the third bank, and $9000 for the fourth bank.

 

The RORG addresses don't determine what bank is the first one, which is second, etc.-- rather, the ORG addresses do that, because the bank numbers depend on what order the banks are in the ROM image, not what their logical addresses are.

 

You should put some sort of data at the bankswitching hotspots, even though it's just "dummy" data, because you can't leave any "holes" inside the ROM image-- so you put dummy filler bytes at those addresses to plug the holes.

 

EDIT: You can leave memory "undefined" in your code, but when the assembler assembles your code into a ROM image, it will fill those holes with default values. So you don't necessarily have to put data at the bankswitching hotspots, but whether you do or not the assembler will put something there anyway.

Edited by SeaGtGruff
  • Like 1
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...