SuperFX Multicart

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
SuperFX Multicart
by on (#109559)
I'm trying to make a Mario-All-Stars-esque cart with a few SuperFX games on it. I'm trying to achieve this using a 74x363 with it's latch input connected to the SNES A23 line and it's outputs feeding a AVR ATmega8. The AVR is controls the address and CS lines needed to select the various eprom chip/bank (I'm using two 27c160s), the SRAM bank select (to provide protection for Starfox 2's save) and lastly its connected to the cart /reset line.

On power on the first thing the AVR does is pull /reset low and selects the eprom bank for the menu. After doing this and waiting ~50ms it releases /reset by changing the relevant I/O pin to input with the pull-up disables (hi-z essentially). This part works and the menu comes up no problem.

When a game is selected the menu code fades out the screen writes a 3 byte unlock code to the AVR followed by the selected game. The AVR then pulls /reset low, waits ~250ms, sets the eprom banking, waits another ~250ms, releases /reset and then switched the I/O pin back to input (no pull-up) and begins monitoring /reset.

This part doesn't work. On game selection the screen fades out and the music stops (I guess the /reset pull down is working) but then the SNES just sits there with a blank screen. Hitting the reset button does nothing. It should as the AVR should be monitoring the /reset line so it can bank the menu back in. At the moment the only way to get the menu to come back is to power-cycle the SNES.

When my menu fades out the screen on game selection it doesn't do anything other than send the bankswitching command and then sit in a endless loop. I assume thats enough because when the AVR does the reset at it's end the game would be banked in and the SNES would start executing it's code.

Any hints? Do I need to put some code in WRAM to perform the bankswitching comms (with interrupts off perhaps?). That could make returning to the menu by the reset button pretty much impossible would it?

EDIT:

I think that this is a problem on the AVR side of things. Bumping the clockspeed to 2MHz for some reason has got the reset-start game part to work but for some reason that I can't fathom at all every menu option selects just one game and resetting just restarts that game...

EDIT EDIT:

Success! The cause of that last problem was down to the very bad address decoding I use for the 74x363. Because all I use is A23 it can also respond to reads. All I had to do is alter the AVR's code to wait a moment after receiving the unlock byte sequence and then sample the 74x363's outputs once the SNES has reached that endless loop I mentioned earlier.

3 out of the 4 games on the cart work (game 4 starts game 3 for some reason. EDIT EDIT EDIT: because of a typo...) and even my 'reset lock' feature, where one can choose to lock the chosen game until a power-cycle.
Re: SuperFX multigame experement
by on (#109753)
So do you have a menu system on screen? Any screen shots??? Would love to see that!

I am just a few days away from getting my multi-FX adapter that I had made. Sounds like we are on the same page except mine isn't as sophicated but mine does utilize 12 meg of flash roms and is reflash able in circuit. Mine just uses physical switches for game selection and SRAM bank switching. So if I could, I would like to know more of how you did this. Very nice!

Mark
Re: SuperFX multigame experement
by on (#109765)
Markfrizb wrote:
So do you have a menu system on screen? Any screen shots??? Would love to see that!

I am just a few days away from getting my multi-FX adapter that I had made. Sounds like we are on the same page except mine isn't as sophicated but mine does utilize 12 meg of flash roms and is reflash able in circuit. Mine just uses physical switches for game selection and SRAM bank switching. So if I could, I would like to know more of how you did this. Very nice!

Mark

Thanks. Essentially I have replaced the physical switches with a microcontroller (I'm using a Atmel ATMega8). I have a 74x363 sitting between it and the SNES bus for communications. The SNES writes a enable sequence and then a game number. The uIC then resets the SNES while pulling the required EPROM and SRAM lines high/low.

Here is it working.

I'm now actually thinking of building a 64Mbit version now. I figured a 128Kbyte sram can hold save data for both Starfox 2 and Yoshi's Island while still leaving a scratch area for most other SFX games. Another way of handling SRAM without upgrading the SRAM would be to read/write the SRAM to/from a nonvolatiale storage (serial flash perhaps?) on game selection and reset. The SFX SRAM is full accessible to the SNES cpu on reset according to the docs.

By the way, I barely know any SNES asm. I cobbled that menu together using various examples found on the net and then fiddling with them until they worked. :D
Re: SuperFX multigame experement
by on (#109772)
Wow, it looks very nice with the menu you put together.
Re: SuperFX multigame experement
by on (#109858)
This is insanely awesome!
Re: SuperFX multigame experement
by on (#110125)
That is incredible wow :) registered to say this

Any chance of a release?
Re: SuperFX multigame experement
by on (#110307)
WARNING! Big wall-o-text incoming. If you are like 'TLDR' then go play CoD or go fondle your iDevice or something...
Also 'B' is bytes, 'b' is bits and I don't recognise that silly new tellytubby prefix system stuff.

Wow. I finally got round to checking on the replies on this thing. A bit of interest from a few people asking the usual questions on how I did this and that. Well, it's been quite the learning experience for me also so I recon I'm not overly qualified to type up a detailed step-by step so instead what I am going to do is go over the process I went through go get to where I am today. Now unlike some (very talented and credit to community) people, I'm all for sharing what I have learned. Now there aren't any schematics but I'll release the sourcecode for the menu once I get round to contacting the people who's code I used as a base for it. Or you can try doing what I did and have a go yourself, all the info you need is mainly only a searchengine away...

So what did I have before I started? I knew how the various buslines worked in a microcomputer system (address lines, data lines and so on) and generally how memory access corresponds to what address line and so on. I know enough to know about active high/low logic and so on. Basic digital electronics essentially. With the internet there is a way, you just need the will (and time).

Next I have a bit of experience in programming... in BASIC (yep, my mind is poisoned for life some might say) but I can muddle stuff together in C well enough to program 8bit AVRs in C. When it comes to the flavour of ASM that the SNES uses my experience ends with me making my C64 flash it's border colour fast and thats it. Essentially I know enough about registers and so on and I can usually LDA, STA, BEQ my way through with the aid of a instruction reference. Again the internet provides. A steady hand with a soldering iron helps as well...

So the first step was to see if I could make a multicart work at all:
Attachment:
File comment: Switched Multicart
$R28QFSN.jpg
$R28QFSN.jpg [ 66.7 KiB | Viewed 7627 times ]

This was a success. Things I learned myself or from online documentation were that the ROM always has it's /CE (chip enable) and /OE (output enable or read enable) tied low meaning that the ROM is always active. I guess this is to save on a couple of lines from the GSU and possibly gain a little extra read access performance. The arrangement in that image is the larger EPROM is a 27c160 in 8bit mode and the smaller is a 27c080. The 080 holds Starfox 2 and the 160 holds Starfox and Starfox Compo. on the other side of the cart PCB I removed the stock 64KB sram and replaced it with a 128KB sram. All the lines on the EPROMS are connected to their various points on each other and on the pcb (the infos all there in the datasheets and in fullsnes.txt). The first of the two switches is simple, all it does is connect A19 (technically A20) of the 160 to either GND or VCC. What this does is selects either the bottom half or the top half of the EPROM. Starfox lives in one half and Compo in the other. Doing this essentially makes the 16Mb EPROM act like a 8Mb one in the eyes of the GSU. The second switch does two things, firstly it switches the /CE and /OE lines of the EPROMS to high or low depending on which one is wanted. Then the switch is in one position the lines to the 080 are high and the ones to the 160 are low, selecting the 160. When the switch is in the other position the opposite is true, selecting the 080.

Now having multiple SFX games living on the same cart where one or more of the games has a battery save poses a problem. I experimented with Starfox 2 to try and see if it keeps it's save data entirely in one half or the other of it's 64KB sram. As Starfox only needs 32KB I thought I could get away with just locking down one half of the stock sram but apparently Starfox 2 must do checks across the entire 64KB and will wipe the saves if any of the 64KB is tampered with. The only easy solution to this was to double the sram to 128KB. The new address line on the sram, A16 is connected to the /CE/OE output for the 080 on the switch so when Starfox/Compo is selected one bank of 64KB sram is selected and when Starfox 2 is selected the other 64KB bank is selected. As Starfox 2 now has it's own 64KB to play with the save is left intact.

When I posted this image over on the JammaPlus forum, I called it the 'Heath Robinson' after the nickname that one of the early British WW2 codebreaking computers got.

More to follow...
Re: SuperFX multigame experement
by on (#110308)
Now a few years had passed since building the Heath Robinson and after a comment on the Jammaplus forum in a Starfox 2 thread I decided to have a go at building a Mario-all-stars-esque version. I knew I needed 3 things, a electronic method to switch the EPROM and SRAM banks, a way to interface that to the SNES bus and a menu to drive it all. I decided to tackle the hardest thing first, the menu.

I had no idea where to begin so again a search on the internet took me to the wiki at superfamicom.org which in turn led me to Neviksti's SNES starter kit. Inside amongst other things was a fullscreen slideshow example. 'Super' I thought because the code was commented nicely and easy enough to get my own pictures into it (source imagery provided by a search engine). I did learn a few things about how to do SNES images in a half decent way:

1. Don't work at the SNES native resolution. It isn't 4:3 so anything you draw (unless you manually compensate) will look stretched on your TV screen (or properly configured emulator). Work at a much larger 4:3 resolution (I use 1024x768) and then use your image editor to scale it down to 256x224 (I use PSP4 and the command is called 'Resample'). The resulting image on your computer screen will look stretched but will display correctly. The only time you would work at SNES native is when using GFX from SNES games, just remember to turn off your emulators 'make the image look like it should' filters and any scaling so it outputs in the SNES native resolution. Then It's a simple cut/clean/paste.

2. The starter pack comes with two tools, 'pcx2snes' and 'fixpcx'. After a while I figured that for fullscreen stuff you don't need to bother with fixpcx. It seemed to do more harm than good to the image.

Next I needed a nicer way to flick between each image. The slideshow sourcecode had lines like these here and there:
Code:
      lda #$0F      ;Turn on screen, full brightness
      sta $2100   

So I thought if $0F is fullbright then logically $00 is fulldark. After a little while I had muddled these two subroutines together:
Code:
fade_out:
   lda #$0f
fade_out_l:
   dec a
   wai
   sta $2100
   cmp #$00
   bne fade_out_l
   rts
   
fade_in:
   lda #$00
fade_in_l:
   inc a
   wai
   sta $2100
   cmp #$0f
   bne fade_in_l
   rts

After a few more hackish alterations and additions I had something that acted like what you see in the vid. However something was missing, music. I supposed that the easiest way for me to get some half decent music going was to find a way to get a regular SPC dump to play and sure enough the NesDev forum's search function brought me to this thread. I am not ashamed to say that I used _mic's code pretty much unaltered at this point.

Now up until now I had been using snes9x as my test environment and all was working so far. So I decided to test on real hardware so out came the GDSF7 and sure enough it worked. So ever confident I burned the menu along with the games and wired it into this:
Attachment:
File comment: electronic multicart
sfxcollosus_front.jpg
sfxcollosus_front.jpg [ 90.48 KiB | Viewed 7624 times ]

Annnnnnd it didn't work at all. After a lot of headscratching I figured out the problem was with the slideshow code. The slideshow is coded in HiROM. I also had to adapt the SPC loader to HiROM to save on ROM space. The SuperFX is inherently a LoROM device. Even tho all the docs said it also supported HiROM all I could come up with was 'BLIP BLEEP BLIP. CONCLUSION, THE DOCS IS A BUNCH OF LIARS'.

So after a surprisingly little amount of work I managed to adapt Neviksti's slideshow to LoROM. Also at this time I decided that if it wasn't going to work the second time I sure as not wasn't going to de/re-solder that thing, (The SFX Colossus named after the worlds first electronic programmable computer, built by the British during WW2 to break codes). So I got the first Starfox 2 cart I built. I had built it with a socket inside (barely fits) so it proved to be useful in testing the menu code. Also I temporarily spliced the 74x393 and some LEDs onto it so I could see if my simple communication register worked. It all did. The menu worked, the music worked and the LEDs flashed and stopped on the correct pattern for each game.

The only thing remaining was the bankswicher...
Re: SuperFX multigame experement
by on (#110309)
Ok. A little thing arrived in the post this morning so I thought now would be a good time to wrap up my little explanation. I might end up repeating stuff from earlier posts but I may be more detailed about it.
Attachment:
rev1.jpg
rev1.jpg [ 180.94 KiB | Viewed 7531 times ]

Now, there are three main segments to this arrangement. Firstly you have the flash ROM. My new PCB is designed to take 16Mb flash and as you can see it can take 4 of them giving a nominal capacity of 64Mb. There is not much to explain here, the flash for the most part is directly wired to the GSU ROM bus as one would expect with special considerations taken for the two MSB of the ROM address bus and /CE lines but more on this later.

The second segment is the 74x373 + AVR combo. The 373 is essentially a octal latch with five of the SNES data bus lines connected to it (four on the proto) and is used as the communications register that the SNES writes to when it needs to talk to the AVR. The latch enable line is connected to A23 on the SNES address bus. In terms of memory mapping this is about as wrong as you can get but for my uses it works well enough considering most of the issues that arise can be compensated for in the AVR's code. With this arrangement what happens is then the SNES does anything at all in the top half of the memory map the 373 will latch what is on the data bus. During my testing I found that on system reset there was a brief period of activity that would trigger the 373.

The AVR (A Mega8 or compatible in this case) does a few things ans is what made the entire thing possible for me to acomplish. Yes you could probably do it with descrete logic, but you would need a number of ICs, making the design more complex. You could use a CPLD. That would ultimately be the best as you would most likely be able to reduce the parts count down to just the flash and the CPLD and at the same time improve the memory mapping of the comm register. The simple reasons why I didn't go this route was inexperience and lack of parts.

The AVR (again I use Atmel simply because of experience) is a good compromise. It needs little support logic to allow it pretty much the same flexibility of the CPLD with the bonus that the entire system operates in a sequential manor, allowing (in my experience) easier debugging. The AVR is connected to the outputs of the 373, this facilitates the communication from the SNES. It is also connected to the SNES /RESET line where it can both control and monitor the state of this line. In the PCB design there are three lines devoted to SRAM bankswitching and depending on the AVR code these can either be address lines or /CEs. They also serve as the main ISP lines for programming the AVR. The AVR has four lines going to the 74x138 and two to the 74x32 for bankswitching control. The sequence of events that happen on power on with the AVR are fairly straight forward. Firstly pretty much the first thing that happens is that the AVR pulls the SNES /RESET line down, keeping the system in reset. While it is doing this it selects the SRAM bank for the non-saving games and selects the ROM bank where the menu lives. Once it has done this the AVR lifts the /RESET line and allows the SNES to boot. Finally the AVR sits in a loop waiting for the menu to communicate with it.

The menu code running on the SNES, once a game has been selected executes a series of writes high in the SNES memory map where the 373 catches them. After each write the menu executes a WAI instruction to allow the AVR plenty of time to register the change. About that, with my crude implementation the AVR can only detect when the comm register has changed rather than written to therefore it is important the I write a sequence that does not repeat the same byte twice. In my current implementation the menu writes (and the AVR expects to see):
Code:
00 0C 00 0x

Where x is the id number of the game requested. After the sequence has been written the menu enters a endless loop. The AVR on reading the 4th byte waits a short amount of time and then reads it again. Is is another of the workarounds to get by my dodgy address decoding on the 373 as for some reason the 4th byte is not stable straight after the third. Once the 4th byte is properly read the AVR pulls /RESET down again and sets the ROM bankswitching and SRAM bankswitching appropriate to the game selected. Once this has been done the AVR lifts /RESET and the selected game boots. Next one of two things happens. The SNES-side menu code can request a function which I call reset lock. This is where pressing the reset button on your control deck will not return you to the menu but instead reset the currently selected game. The SNES-side menu does this by ANDing $A with the game id number. The AVR checks for this. If it sees the reset-lock request it proceeds to a never ending loop that can only be broken by a full systems power-cycle. If reset-lock is not requested the AVR moves to a loop where it monitors the SNES /RESET line. If the AVR sees /RESET go low if jumps right to the beginning of the sequence. By the time you remove your finger from the reset button the AVR has most likely already banked the menu back in ready to select a new game.

The third segment to all of this is the ROM bankswitching. The PCB version makes use of a 74x138 (a 3 to 8 demultiplexer) and a 74x32 (a quad OR). The 74x32's job is to allow the AVR and the GSU2 to co-exist peacefully on A19 and A20 of the GSU ROM bus. In this arrangement the AVR can override the GSU2's control on these to lines, forcing the upper 8Mb out of 16Mb and/or the upper 4Mb out of 8Mb. The 74x138 is responsible for flash selection based on the AVR entirely or with a change of a solder jumper a combination of the AVR and A20. The 138 is wired in such a way that it's odd numbered outputs are connected to the flash ICs. The even numbered outputs are connected to solder pads. A0 of the 138 can either be connected to the AVR or A20. The reasons for this are twofold. Firstly if one only has access to 29F080s (8Mb) then it is possible to stack two together, with the piggybacked 'top' IC connected to one of the corresponding solder pad. When he jumper is set to A20 mode, the two 8Mb ICs can be access as a single 16Mb block allowing for 8 8Mb ICs to be used for a total of 64Mb. When the jumper is set to AVR, 16Mb IC must be used for 16Mb games but on the up side 16Mb ICs can also be stacked for a total of 128Mb. The 138 is also connected to the main rom /CE line and has a override from the AVR to forcibly de-select the flash. This line is weakly wired high so the flash stays de-selected until the AVR has booted and pulls the line low.

Ultimately there is a decent amount of flexibility in the design as the brunt of the bankswitching logic is in the AVR code which can be tailored for almost any combination of games. Unlike the prototype, the main /CE line is routed to the edge so in theory the PCB can be used in non-SFX carts as long as you stick to 16Mb game or lower. Also enough lines go to the edge to enable the construction of a adapter to allow the flash ICs to be programmed.

If anybody is wondering, I had my PCB made by OSH Park. From ordering to arrival from the US it took ~2 1/2 weeks.
Re: SuperFX Multicart
by on (#111105)
Just added the last part of my explanation. Also the PCB for my new version arrived today, and it is a little bit too big. :oops: Nothing a little filing wont fix...
Re: SuperFX multigame experement
by on (#111119)
What type of ROM chip do you have on that sweet looking board? Is that a 5V flash chip?
Re: SuperFX multigame experement
by on (#111127)
getafixx wrote:
What type of ROM chip do you have on that sweet looking board? Is that a 5V flash chip?


The chips I got are AM29F016D, 16Mb 8 bit 5V in a SO44 package.
Re: SuperFX Multicart
by on (#115964)
Would be great to use that methode for a 4 Weeks Zelda AST !!
Re: SuperFX multigame experement
by on (#116033)
Hojo_Norem wrote:
getafixx wrote:
What type of ROM chip do you have on that sweet looking board? Is that a 5V flash chip?


The chips I got are AM29F016D, 16Mb 8 bit 5V in a SO44 package.


How are you handling the CE/OE lines? The AM29F* chips don't work with their CE/OE lines tied low, since the address is latched on the falling edge of whichever of the two goes low later. I'd love to build a GSU dev cart, probably nothing this fancy, but I would like to use a flash ROM, and the CE/OE decoding is the main thing keeping me from being able to use Flash ROM with the GSU.
Re: SuperFX Multicart
by on (#116036)
Ah, something like this???

http://youtu.be/Vmpn4pTsUPk

:)


Or a more simple version with standard EPROMs...
(An earlier version).
http://youtu.be/45dXfbmhawc
Re: SuperFX multigame experement
by on (#116048)
qwertymodo wrote:
Hojo_Norem wrote:
getafixx wrote:
What type of ROM chip do you have on that sweet looking board? Is that a 5V flash chip?


The chips I got are AM29F016D, 16Mb 8 bit 5V in a SO44 package.


How are you handling the CE/OE lines? The AM29F* chips don't work with their CE/OE lines tied low, since the address is latched on the falling edge of whichever of the two goes low later. I'd love to build a GSU dev cart, probably nothing this fancy, but I would like to use a flash ROM, and the CE/OE decoding is the main thing keeping me from being able to use Flash ROM with the GSU.


I am fairly confident it should work without any monkeying around with /CE/OE any more thats needed to provide bankswitching. I'm no expert but as fas as I can tell there is nothing stated that having both held low wont work, in fact this segment of the datasheet:
Quote:
Requirements for Reading Array Data
To read array data from the outputs, the system must drive the CE# and OE# pins to V IL . CE# is the power control and selects the device. OE# is the output control
and gates array data to the output pins. WE# should remain at V IH . The internal state machine is set for reading array data upon device power-up, or after a hardware reset. This ensures that no spurious alteration of the memory content occurs during the power transition. No command is necessary in this mode to obtain array data. Standard microprocessor read cycles that assert valid addresses on the device address inputs produce valid data on the device data outputs.


I understand that doesn't necessarily guarantee it will work but this along with information in the AC characteristics table gives me confidence it will. The AC characteristics table lists delay values for /OE -> Data, /CE -> Data where /OE=low and Address -> Data where both /OE and /CE are low.

I've had the parts to build my finished pcb but I need to build a custom programmer (a uIC with some GPIO being fed from a serial link) and software to drive it. I could make a adapter for my Willem but eventually I want to be able to have a generic firmware running on the pcb's uIC and then just upload configuration data to it while programming the flash.

If this works as well as I hope and there is enough interest I might do a re-design. A single ~128Mb 3.3v flash chip with level shifters and regulator would be much easier to source than ageing EOL 5v stuff... heck, you can get 2Gigabit parallel 3.3v flash now (8 bit even I think)
Re: SuperFX Multicart
by on (#116051)
I tried array reads with CE/OE held low on a few different FlashROMs yesterday before I posted and it wasn't working. However, that may have just been a copy-paste error wrt my bit-bang read function. I'll try re-writing the read function from scratch and see if I can get it to work.
Re: SuperFX Multicart
by on (#116091)
i just remembered another thing, my pcb is designed for the GSU2 which has a /CE output afaik.
Re: SuperFX Multicart
by on (#116210)
Markfrizb wrote:
Ah, something like this???

http://youtu.be/Vmpn4pTsUPk

Got myself one of those -- thanks again, Mark :) -- and it works fantastic! :D :D
Re: SuperFX Multicart
by on (#116221)
Hojo_Norem wrote:
i just remembered another thing, my pcb is designed for the GSU2 which has a /CE output afaik.

That makes quite a bit of difference. Could be that some flash chips work with CE and OE tied low, but actually driving CE makes it much more likely to work. I'll try again on my end, it's possible I did something wrong when I tried to read it with CE and OE held low, not sure. In any case, it would be good to figure out for the sake of GSU-1 carts.
Re: SuperFX Multicart
by on (#116224)
qwertymodo wrote:
Hojo_Norem wrote:
i just remembered another thing, my pcb is designed for the GSU2 which has a /CE output afaik.

That makes quite a bit of difference. Could be that some flash chips work with CE and OE tied low, but actually driving CE makes it much more likely to work. I'll try again on my end, it's possible I did something wrong when I tried to read it with CE and OE held low, not sure. In any case, it would be good to figure out for the sake of GSU-1 carts.



On the FX carts, the CE lines are hard wired low. The GSU doesn't toggle them. only the OE line is used by the GSU.
So you can tie the CE low and connect the OE to the GSU/Mask rom OE. I use the CE line to select between the ROMs (cause there are 3 roms on my cart). Pulling the CE line high on the roms that you DON'T want to be read and pull the CE line low on the ROM you do want read. This is of course if you use more than 1 flash rom.

hope this helps
Re: SuperFX Multicart
by on (#116225)
Yeah, that makes sense as long as either CE or OE is toggling. Toggling OE and using CE to select between ROMs actually makes more sense. It's just when both are tied low that I don't think works with Flash ROMs (or at least I haven't been able to get it to work).
Re: SuperFX Multicart
by on (#116228)
qwertymodo wrote:
Yeah, that makes sense as long as either CE or OE is toggling. Toggling OE and using CE to select between ROMs actually makes more sense. It's just when both are tied low that I don't think works with Flash ROMs (or at least I haven't been able to get it to work).


Yeah, if you have more than 1 rom, then tieing them both low is a buss conflict. That's not just flash roms but ALL roms.
Reading a rom (any rom - flash or eprom) is a standard reading of address lines. The "flash" aspect is really just for programming. You'll want to pull the WE line high with a resistor (10K) in your design to prevent accidental writes after you have programmed the roms.


EDIT: also the flash roms have a reset line. And usually the reset line is pulled high. It's hard to describe its function but it acts like a CE. Maybe someone here can explain it better....


PM me if you want to borrow (or buy) one of my carts.

Mark