Jump to content
IGNORED

Which bankswitching should I use?


bent_pin

Recommended Posts

I'd like to make a game with more RAM so I can unpack stuff from ROM and use less ROM that way. I wanted to go with 3E+ but it is unsupported by Harmony and that's currently a deal breaker for me. So I'm thinking 3E is the way to go. Is there a better bankswitching scheme that's Harmony compatible? The game should be under 8K and I need 1K of extra RAM. All the RAM should be accessible at the same time.

 

I'm also looking for a guide on how to program for that bankswitching scheme in ASM, and maybe a sample game.

 

Any help is appreciated.

Link to comment
Share on other sites

11 minutes ago, Bruce-Robert Pocock said:

3E+ works on current Harmony firmware, as far as I know.

Use the extension `3EP` to signal the banking protocol.

 

 

UPDATE: Sorry, mis-remembered. Works on UNO/Plus, but probably not Harmony.

I checked with batari first to be sure. Thank you, though.

  • Like 1
Link to comment
Share on other sites

3 hours ago, bent_pin said:

The game should be under 8K and I need 1K of extra RAM.

M-Network's E7 bank-switching scheme meets these requirements and should work on most/all of the different multi-carts:

 

https://www.taswegian.com/WoodgrainWizard/tiki-index.php?page=E7

 

I've done a little bit of playing around with this.... but @MarcoJ would probably be the better one to talk to, since he used this extensively for Pitkat.

 

  • Thanks 1
Link to comment
Share on other sites

1 minute ago, splendidnut said:

I've done a little bit of playing around with this.... but @MarcoJ would probably be the better one to talk to, since he used this extensively for Pitkat.

Thanks for the shoutout @splendidnut

 

E7 has the most RAM (2K) of bankswitching schemes universally supported by both Harmony (Encore AND standard) and PlusCart/Unocart. It has a big rom too(16K). I actually prefer 3E+ objectively, but as said above it's only supported on Uno/PlusCart at this time.

 

E7 works by splitting RAM and ROM into two different slice sizes and keeping some fixed ROM at the end. Banks are changed by doing a fake strobe to some hotspots. The first half of the address space is used by the big slice (either 2K of ROM, or 1K of RAM( with an equal sized read and write area for RAM). After that there's a small slice (512 bytes) which is used for reading and writing to 4 individual 256 byte RAM slots. Finally, at the very end, there's roughly 1.5kB of fixed ROM. The fixed ROM never changes, it is always mounted in the same spot and is usually where all bankswitching commands are launched from. The great thing about E7 is the big slice and small slice areas can be switched in and out independently so that layering can occur, mixing and matching with ROM and RAM, so you could have for example 2K ROM and 256b of RAM, 1K RAM and 256b of RAM. The RAM split is such that the first 1K is only used in the big slice, while the last 1K (4x 256b) is used in the small slice. Typically i've used the big RAM slice for self modifying kernels, while the small RAM slices have been used for variable storage and sprites. It's possible to run code in both the big and small slices too. Overall it's a very flexible arrangement, well suited to RAM kernels. I've used it so far for Pitkat, Modern Battle and Kovi Kovi. 

 

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

3 hours ago, bent_pin said:

I'm also looking for a guide on how to program for that bankswitching scheme in ASM, and maybe a sample game.

I have an unfinished article about using bankswitching on the VCS here. The first part (which is not specific about any bank switching scheme) might be interesting if you have no previous experience, and since my current project is stalled I could write the part about bank E7 if it could help.

  • Thanks 1
Link to comment
Share on other sites

18 minutes ago, Windless said:

I have an unfinished article about using bankswitching on the VCS here. The first part (which is not specific about any bank switching scheme) might be interesting if you have no previous experience, and since my current project is stalled I could write the part about bank E7 if it could help.

From what I see, E7 provides 1K + 4*256bytes RAM and up to 16K ROM. Assuming that entire 1K RAM has read/write access without bankswitching, that would be a winner. Your help there would be greatly appreciated. Thank you.

Link to comment
Share on other sites

53 minutes ago, MarcoJ said:

Thanks for the shoutout @splendidnut

 

E7 has the most RAM (2K) of bankswitching schemes universally supported by both Harmony (Encore AND standard) and PlusCart/Unocart. It has a big rom too(16K). I actually prefer 3E+ objectively, but as said above it's only supported on Uno/PlusCart at this time.

 

E7 works by splitting RAM and ROM into two different slice sizes and keeping some fixed ROM at the end. Banks are changed by doing a fake strobe to some hotspots. The first half of the address space is used by the big slice (either 2K of ROM, or 1K of RAM( with an equal sized read and write area for RAM). After that there's a small slice (512 bytes) which is used for reading and writing to 4 individual 256 byte RAM slots. Finally, at the very end, there's roughly 1.5kB of fixed ROM. The fixed ROM never changes, it is always mounted in the same spot and is usually where all bankswitching commands are launched from. The great thing about E7 is the big slice and small slice areas can be switched in and out independently so that layering can occur, mixing and matching with ROM and RAM, so you could have for example 2K ROM and 256b of RAM, 1K RAM and 256b of RAM. The RAM split is such that the first 1K is only used in the big slice, while the last 1K (4x 256b) is used in the small slice. Typically i've used the big RAM slice for self modifying kernels, while the small RAM slices have been used for variable storage and sprites. It's possible to run code in both the big and small slices too. Overall it's a very flexible arrangement, well suited to RAM kernels. I've used it so far for Pitkat, Modern Battle and Kovi Kovi. 

 

 

Sounds perfect. Thank you. I'm going to have to draw out what you've said to better understand it, but it's what I need. I've made a really nice self-modifying kernel but it uses 113 bytes so zp is shot with it in there, then it requires almost a page of ROM to support it, but so much of that is redundant copies and zeros for padding that it's a crying shame to put it into ROM. Instead, I can unpack it into RAM and save loads of space. Would you have a simple sample to share?

 

BTW, I'm still picking apart your 16char sample that you provided in another thread. That's some interesting code. I might figure it out by about 12 o'clock next summer.

Link to comment
Share on other sites

2 minutes ago, MarcoJ said:

Hi

This is a basic E7 asm structure. It's been a while since I looked at it. Looks like it implements the ROM banks, but not sure about the ROM. I have to head out, cheers.

 

E7.bin 16 kB · 1 download E7.asm 2.26 kB · 2 downloads
 

Wonderful, thank you. I will spend the next few days digging into this.

 

I appreciate it.

Link to comment
Share on other sites

16 hours ago, bent_pin said:

I will spend the next few days digging into this.

Here is an updated version which explains a lot more.

 

 

Compile with DASM with:

dasm E7.asm -d -lE7.lst -sE7.sym -f3 -v5 -oE7.bin

 

The lst and sym files are used by emulators for showing nice address names in the instruction readout, handy for debugging.

 

An important thing to remember with the RAM slices is that reading and writing variables needs to be handled with two addresses, similarly to using the SARA chip. 

For the 1K RAM Bank, a variable will be $F000 as the read port, and $F400 as the write port, use $F001 and $F401 for next variable, etc.

For the 256b RAM bank, a variable will be $F800 as the read port and $F900 as the write port. For the next variable, use $F801 and $F901, etc.

 

the "RORG" statements in the dasm file allow jumping between subroutines in different sections of the ROM space to work. It forces sections in the rom to believe they are addressed at where the RORG statement specifies. For example, 

	org $0800
	rorg $F000

says that the code in the ROM starts at $0800, but when jumping to subroutines of code that are there, it will instead pretend $0800 is actually $F000 instead.

 

This new template includes a BRK instruction handler and ROM usage readout. There's also a few other sections defined where code can and can't be used.

 

Usage of the BRK trick:

https://www.qotile.net/minidig/docs/2600_advanced_prog_guide.txt

 

ROM usage readout (when compiled using dasm).

image.png.473d710b211a3de4157f83a67d970752.png

E7.asm vcs.h macro.h E7.bin

  • Thanks 1
Link to comment
Share on other sites

Thank you so much for the great details. You've saved me a lot of time. I should be able to jump right into working with this.

 

1 hour ago, MarcoJ said:

me too. One recent pioneering user of 3E+ is mzxrules' Legend of Zelda project. 

 

I have a copy of the current Zelda ROM. It's a project @mzxrules should be proud of.

  • Like 1
Link to comment
Share on other sites

The only tiny drawback that I see to using any non-ZP RAM is that store register takes 4 clocks. My kernel depends on ZP write speeds to modify itself each scanline. So, it still has to run from ZP. However, I can move all of my variables out of ZP and leave a minimum of 15 bytes for the stack. Since the read/load from non-ZP RAM is the same as a ROM read/load, I think that will work perfectly.

Link to comment
Share on other sites

Yes, zeropage RAM is a mystical unicorn. The other RAM areas will need at least 4 clocks for reading and writing. The reason that its faster is it saves 1 cycle from ignoring the upper address byte. Since zeropage is lower address (<256). But yes, non critical variables for speed can be removed from the zero page and will placed in the small or

big slices. 

  • Like 1
Link to comment
Share on other sites

1 hour ago, bent_pin said:

The only tiny drawback that I see to using any non-ZP RAM is that store register takes 4 clocks. My kernel depends on ZP write speeds to modify itself each scanline. So, it still has to run from ZP. However, I can move all of my variables out of ZP and leave a minimum of 15 bytes for the stack. Since the read/load from non-ZP RAM is the same as a ROM read/load, I think that will work perfectly.

 

Consider using the macros presented in the 3E+ discussion linked above, which provide "local" variables and reuse of zero-page through an automated "overlay" system. I found it most useful in some of my coding. Takes a little to get your head around it, but it guarantees no overlap in usage (=crashes) and also makes your zero page seem HUGE.  :). Just sayin.

  • Thanks 1
Link to comment
Share on other sites

7 hours ago, Andrew Davie said:

 

Consider using the macros presented in the 3E+ discussion linked above, which provide "local" variables and reuse of zero-page through an automated "overlay" system. I found it most useful in some of my coding. Takes a little to get your head around it, but it guarantees no overlap in usage (=crashes) and also makes your zero page seem HUGE.  :). Just sayin.

Now I see what you mean. I will learn and integrate them. Thank you.

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