Jump to content
IGNORED

Mechanics of FE bankswitching


DirtyHairy

Recommended Posts

There has already been a lot of discussion on the precise mechanics of FE banking before. In particular, as explained by @TomSon here and according to the patent, the reset sequence of the 6502 will trigger a bank switch that effectively will cause FE to start in a defined bank.

 

Now, since last summer, I have a new CPU core in 6502.ts that, among other things, models the reset cycle of the CPU precisely. Today, I have noticed that this actually *breaks* FE banking :) What happens is that the reset sequence causes an access to 0x01fe immediately before loading the reset vector low byte from 0xfffc. However, the low byte is zero (including the high bits that are used for selecting the bank), and this causes the emulated cartridge to switch to bank 1, which contains garbage at 0xf000.

 

After scratching my head for some time, my assumption is that (as the banks are usually selected with the high bit sequences 110 and 111) 000 is in fact treated specially to select the startup bank which is bank0. I have implemented this in 6502.ts, and it works for all FE carts that I am aware of, but I have no way to verify this. Has anybody here ever opened up a FE cartridge and checked what actually is going on inside?

Edited by DirtyHairy
Link to comment
Share on other sites

I have a PAL "Space Shuttle" cartridge. I'll crack it open later today, but probably the bankswitching logic is integrated within the rom chip and there won't be anything to see.


What about running  some test code from RIOT RAM to trigger bankswitching and see what bank is selected when pushig "000" as high bits in the stack?

Link to comment
Share on other sites

2 hours ago, alex_79 said:

What about running  some test code from RIOT RAM to trigger bankswitching and see what bank is selected when pushig "000" as high bits in the stack?

That's a good idea. I think I can cook up a test ROM, but I don't have a cartridge to test. If I put together a test, would you mind giving it a try?

Link to comment
Share on other sites

In the meantime, I tried making a test rom myself:


The rom performs a series of jsr and rts and reads the value at $FFFD inside the subroutine (shown on the left) and after returning from it (on the right). The value read at that address is $F0 in bank 0 and $D0 in bank 1.

The sequence of the address 3 high bits of the subroutine is increased on each row ($0xxx, $2xxx, $4xxx and so on up to $Exxx). Then the return address is increased in the same way and the sequence repeats. So there are 8 groups (one per each return address) with 8 values each (one for each subroutine address).

This is the result with my "Space Shuttle" cart:

testFE.thumb.jpeg.4f42dc84cb5e28f43fbf95f6f18b312a.jpeg
Basically, only bit 13 of the address determines the bank (A13=0 -> bank 1, A13=1 -> bank 0) the two highest bits don't matter, and a sequence of three '0' doesn't behave in a different way (it selects bank 1).

 

testFE.zip

 

  • Like 1
Link to comment
Share on other sites

Nice, you beat me to it, I was still debugging my own test ROM ;) I took another look at the Space Shuttle ROM, and this one actually contains a valid reset vector in bank 1, too, and has a JSR at the beginning of bank 1 that will switch over to bank 0. So, Space Shuttle starts up correctly in bank 1. I doublechecked, and the only example that really doesn't work (aka fails in bank 1) with the correct reset sequence is Decathlon, which I stumbled over in the first place.

 

Now we'd need someone with a decathlon cartridge... :P

Link to comment
Share on other sites

After doing a bit of research, I'm thinking that your implementation of the FE bankswitching is correct the way it is now, and the problem with "Decathlon" comes from the assumption that the Stack Pointer is 00 after the RESET line goes high.


The "MOS 6500 family programming manual", on page 126 says:

 

While the reset line is in the low state, it can be assumed that
internal registers may be initialized to any random condition; therefore,
no conditions about the internal state of the microprocessor are assumed
other than that the microprocessor will, one cycle after the reset line
goes high, implement the following sequence:

 

 

Example 9.1: Illustration of Start Cycle
Cycles 	Address Bus 	Data Bus 	External Operation 	Internal Operation
1 	?		?		Don't Care 		Hold During Reset
2 	? + 1 		? 		Don't Care 		First Start State
3 	0100 + SP 	?		Don't Care 		Second Start State
4 	0100 + SP-1 	?		Don't Care 		Third Start State
5 	0100 + SP-2 	? 		Don't Care 		Fourth Start State
6 	FFFC 		Start PCL 	Fetch First Vector
7 	FFFD 		Start PCH 	Fetch Second Vector 	Hold PCL
8 	PCH PCL 	First OP CODE	Load First OP CODE


Note that on cycles 3,4,5 the manual doesn't define an absolute address on the bus, but rather an offset from $100 which depends on the SP value. At the end of this sequence, the SP is $FD only if it was $00 after a RESET, but according to the previous paragraph, the internal registers (including SP) may be initialized with any random value.

 


Still, I clearly remember that a while ago there were discussions on the forum on this very same subject.
Links to analysis of the cpu power-on sequence and also the results of test roms run on the 2600 brought to the conclusion that after the startup sequence the value of SP in a 2600 is determined and this value is $FD. (This has been implemented in Stella too)

 

So I went back reviewing those dicussions.

 

Here is the relevant thread:

https://atariage.com/forums/topic/261488-reset-sp/

 

The document TomSon was referring to is here:
https://www.pagetable.com/?p=410

 

If you scroll down that page, in the section "RESET" it states:

 

Cycle 0: When a 6502 is turned on, the stack pointer is initialized with zero.

 

The source of this piece of info seems to be the Visual6502 simulator.

 

Further down in the AA thread, Tomson posted a testrom displaying a colored screen if SP value was $FD at startup, and I posted a testrom too displaying the SP value and confirmed $FD as the result in a 2600 (Note: that rom has a bug in that it doesn't initialize the D flag, which sometimes results in corrupted display). There's also a link to another testrom by Omegamatrix showing a more detailed view of the startup state of the VCS, including the entire ram and all the CPU registers.

 

Case closed, I guess.

 

No, actually.

I repeated those tests with the console I have currently hooked up (a 2600 Jr).
I tried all 3 test roms (flashing them in single game mode on the harmony) and the value of SP is completely random and changing on each power cycle on this machine!

So I pulled out of storage a couple more consoles to test (a 4 switch and a 6 switch). The result here is often $FD, but not always. The 6 switch, returned $FD for several powercycles after a cold start. Anyway, as it got warmer, it started to return different values sometimes ($7D and $FC, mostly). The 4 switch behaves the opposite: the values mostly stabilize as it gets warmer to $FD. (and the D flag is set more often when is warm too, revealing the bug in my testrom...)

 

So, at the time, I only did a few tests on one console, which happened to match what was being stated. Since the source of that info seemed to be an authorative one, I had no reason to doubt it, and didn't test further.

 

 

 

Edited by alex_79
  • Like 2
Link to comment
Share on other sites

Hmm, I thought we had this one figured out for good.  Looks like there's still more work to do.  For what it's worth, it's working fine in Stella, but that may be because we coded it to work to the ROMs, and not to the actual underlying behaviour.

 

In Stella, the bankswitch doesn't happen until the next cycle.  So the address is strobed on one cycle, and the actual switch happens on the next.

Link to comment
Share on other sites

10 hours ago, alex_79 said:

No, actually.

I repeated those tests with the console I have currently hooked up (a 2600 Jr).
I tried all 3 test roms (flashing them in single game mode on the harmony) and the value of SP is completely random and changing on each power cycle on this machine!

So I pulled out of storage a couple more consoles to test (a 4 switch and a 6 switch). The result here is often $FD, but not always. The 6 switch, returned $FD for several powercycles after a cold start. Anyway, as it got warmer, it started to return different values sometimes ($7D and $FC, mostly). The 4 switch behaves the opposite: the values mostly stabilize as it gets warmer to $FD. (and the D flag is set more often when is warm too, revealing the bug in my testrom...)

 

So, at the time, I only did a few tests on one console, which happened to match what was being stated. Since the source of that info seemed to be an authorative one, I had no reason to doubt it, and didn't test further.

Interesting, thanks alot! I just played a bit more with decathlon, and I think I have found what is going on: there still are still a few undocumented opcodes in 6502.ts that I haven't implemented (which, I think, are unstable on hardware), and that's what is causing the issue. If I stub out those with NOPs, then Decathlon actually runs. The same happens if I start Decathlon with Stella in bank 1. Looking at the trace in 6502.ts it seems that, somehow, it manages to run through garbage until it finally, by magic, hits BRK with S and P in the right state to switch back to bank 0 when pushing PCL. BRK then jumps to the interrupt vector in bank 0 (which is 0xf000) and the program finally enters the startup code.  I am pretty sure David Crane didn't do that one on purpose :P

 

Sorry for the confusion, time to implement those opcodes I guess... ;)

Edited by DirtyHairy
  • Like 1
Link to comment
Share on other sites

9 hours ago, stephena said:

In Stella, the bankswitch doesn't happen until the next cycle.  So the address is strobed on one cycle, and the actual switch happens on the next.

In Stella, the whole issue cannot be reproduced as we don't emulate the reset sequence --- on reset, the CPU starts with the reset vector already loaded in P, so the problematic bank switch cannot happen in the first place.

Link to comment
Share on other sites

10 minutes ago, DirtyHairy said:

In Stella, the whole issue cannot be reproduced as we don't emulate the reset sequence --- on reset, the CPU starts with the reset vector already loaded in P, so the problematic bank switch cannot happen in the first place.

Do you think it's worthwhile to implement this in Stella too?

Link to comment
Share on other sites

16 minutes ago, stephena said:

Do you think it's worthwhile to implement this in Stella too?

Apart from a possible interaction with emulated bankswitching hardware (like here), the reset sequence has no detectable effect, so I don't think there is any real reason to implement it. However, I don't think it is hard to do, either ;) If you like, let's open a ticket --- I can do it once I have fixed decathlon in 6502.ts for good (I'd like to have a final confirmation that my reasoning is really correct here).

Edited by DirtyHairy
  • Like 1
Link to comment
Share on other sites

7 hours ago, DirtyHairy said:

Looking at the trace in 6502.ts it seems that, somehow, it manages to run through garbage until it finally, by magic, hits BRK with S and P in the right state to switch back to bank 0 when pushing PCL. BRK then jumps to the interrupt vector in bank 0 (which is 0xf000) and the program finally enters the startup code.  I am pretty sure David Crane didn't do that one on purpose :P

Interesting, thanks for the explanation!

 

BTW, I opened my "space shuttle" cart and indeed, there's nothing useful there to check (that is, unless someone decap that chip-on-board and reverse engineer it using an electron microscope...)

FE_spaceshuttle_PAL.thumb.jpg.1ce05b182af1677aad8bcdb3b5439003.jpg

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...