Jump to content

Photo

ColecoVision MegaCart FAQ

Bank switching

30 replies to this topic

#1 retroillucid OFFLINE  

retroillucid

    Quadrunner

  • 8,114 posts

Posted Wed Sep 4, 2013 8:39 PM

I usually don't post thread here since I'm not a programmer...
 
However, since we publish games for the CV, sometimes programmer(s) get stuck when it comes to use the ''Bank Switching Sheme'' or call it, the MegaCart
 
So I decided to gather informations I already had and start an official MegaCart FAQ
 
Feel free to make changes and add your informations wich could help other Colecovision programmers out there!

Attached Files


Edited by retroillucid, Sat Sep 7, 2013 1:43 AM.


#2 retroillucid OFFLINE  

retroillucid

    Quadrunner

  • Topic Starter
  • 8,114 posts

Posted Thu Sep 5, 2013 8:55 AM

Albert gave me access to edit this thread so I can update the MegaCart FAQ

 

So, If you have any question(s) about the MegaCart / Bank Switching , post your question here and I'll update the FAQ each time we have new infos

 

 

Thanks



#3 PkK OFFLINE  

PkK

    Moonsweeper

  • 469 posts
  • Location:Europe

Posted Thu Sep 5, 2013 11:27 AM

There seems to be a bug in the current  (revision #8835) sdcc pephole rules that results in the access being optimized away despite the volatile. Until it is fixed, compile with --no-peep. Also the variable is unnecessary, a simple

 

*((volatile char*)0xFFFF);

 

is sufficient to generate a read access.

 

Philipp



#4 PkK OFFLINE  

PkK

    Moonsweeper

  • 469 posts
  • Location:Europe

Posted Thu Sep 5, 2013 11:45 AM

A few years ago, I made my own MegaCart. But I never found enough free time to make a game that really required it, and I found the use from sdcc too cumbersome (similart to how this one works).

 

So I started on building support for bank-switching into sdcc. I just had a look at the current state. It would work for bankswitched RAM, but needs a bit of work for the ROM. When I find a bit of time, I'll fix it. Once that is done, using the MegaCart from sdcc should be much simpler. We would use named address spaces (see section 3.6.2 in the sdcc manual, which also contains a small example of how this works for RAM).

 

You just write a function to switch to a particular bank, declare banks for your variables and then just access them normally:

void set_bank_a(void)
{
	*((volatile char*)0xffff);
}

void set_bank_b(void)
{
	*((volatile char*)0xfffe);
}

__addressmod set_bank_a bank_a;
__addressmod set_bank_b bank_b;

const bank_a char d = 'c'; // A const char in bank a.
const bank_a char *const bank_b c = &d; // A const pointer in bank b that points to a const char in bank a.

char f(void)
{
	return *c; // sdcc will automatically insert the calls to set_bank_a() and set_bank_b() as necessary.
}

Actually, sdcc already generates correct code for the function f() in this example, but messes up the initialization of c and d (sdcc behaves as if they were in RAM).

 

sdcc will try to minimize the calls to the bank selection function, and will only insert the minimum number necessary. Read "Optimal Placement of Bank Selection Instructions in Polynomial Time" for the details. However, it does not yet do inter-procedural analysis, so it doesn't know which bank is active after a function call.

 

Philipp

 

P.S.:  All this is about data in banked memory, not calling functions in banked memory. To me, the latter problem seemed less interesting from a theoretical computer science perspective, so I never bothered with it.

 



#5 nanochess OFFLINE  

nanochess

    Processorus Polyglotus

  • 5,835 posts
  • Coding something good
  • Location:Mexico City

Posted Thu Sep 5, 2013 2:44 PM

Very useful info, J-F! I was wondering how Megacart was used with C language :)

 

For Princess Quest and Mecha-8 I'm using assembler, I've found useful the following definitions (TNIasm v0.44):

; For 128K Megacart (for 256K one I start on $fff0 upto SLOT_15 at $ffff)
SLOT_0: equ $fff8
SLOT_1: equ $fff9
SLOT_2: equ $fffa
SLOT_3: equ $fffb
SLOT_4: equ $fffc
SLOT_5: equ $fffd
SLOT_6: equ $fffe
SLOT_7: equ $ffff

; At start of code
        ld hl,SLOT_0     ; Default slot of Megacart, but set again because user can do a Colecovision RESET
        call sel_slot

; My typical switching code
        ld hl,SLOT_3
        call sel_slot

; Slot selection
sel_slot:
        ld (slot),hl     ; Saves current slot, useful because in NMI routine sometimes I switch slots to play music from OTHER slot
        ld a,(hl)
        ret
;

In Princess Quest, I tend to keep all code for game in the most upper slot (always mapped in $8000-$BFFF) and some code/data in SLOT_0 (default one, mapped at $C000-$FFBF), then code switches slots as needed to access other data (no code)

 

For Mecha-8 finally I've jumped the bridge and apart from basic SLOT_7/SLOT_0 containing 32K code/data, there is a separate intermediate slot were are contained various routines for bosses, SGM detection and so.



#6 retroillucid OFFLINE  

retroillucid

    Quadrunner

  • Topic Starter
  • 8,114 posts

Posted Thu Sep 5, 2013 2:51 PM

Very useful info, J-F! I was wondering how Megacart was used with C language :)
 
For Princess Quest and Mecha-8 I'm using assembler, I've found useful the following definitions (TNIasm v0.44):

; For 128K Megacart (for 256K one I start on $fff0 upto SLOT_15 at $ffff)SLOT_0: equ $fff8SLOT_1: equ $fff9SLOT_2: equ $fffaSLOT_3: equ $fffbSLOT_4: equ $fffcSLOT_5: equ $fffdSLOT_6: equ $fffeSLOT_7: equ $ffff; At start of code        ld hl,SLOT_0     ; Default slot of Megacart, but set again because user can do a Colecovision RESET        call sel_slot; My typical switching code        ld hl,SLOT_3        call sel_slot; Slot selectionsel_slot:        ld (slot),hl     ; Saves current slot, useful because in NMI routine sometimes I switch slots to play music from OTHER slot        ld a,(hl)        ret;
In Princess Quest, I tend to keep all code for game in the most upper slot (always mapped in $8000-$BFFF) and some code/data in SLOT_0 (default one, mapped at $C000-$FFBF), then code switches slots as needed to access other data (no code)
 
For Mecha-8 finally I've jumped the bridge and apart from basic SLOT_7/SLOT_0 containing 32K code/data, there is a separate intermediate slot were are contained various routines for bosses, SGM detection and so.
Awesome! Glad it help!

Please, update the FAQ with your informations too! :)


EDIT: Maybe it will be good to have to seperate section, one for C and one for Assembler ?

Edited by retroillucid, Thu Sep 5, 2013 2:55 PM.


#7 nanochess OFFLINE  

nanochess

    Processorus Polyglotus

  • 5,835 posts
  • Coding something good
  • Location:Mexico City

Posted Thu Sep 5, 2013 3:29 PM

Awesome! Glad it help!

Please, update the FAQ with your informations too! :)


EDIT: Maybe it will be good to have to seperate section, one for C and one for Assembler ?

 

Feel free to use my info in your FAQ ;)



#8 Kiwi OFFLINE  

Kiwi

    Stargunner

  • 1,674 posts

Posted Thu Sep 5, 2013 9:28 PM

Thank you for posting the Megacart FAQ.  I have some theories how I may do these.  Doing and experimenting is going to get me somewhere.:)  Eventually I'll crack the case. :idea: 8)



#9 retroillucid OFFLINE  

retroillucid

    Quadrunner

  • Topic Starter
  • 8,114 posts

Posted Fri Sep 6, 2013 4:41 PM

Quick update

And decide to convert it into PDF

 

I'll do my best to make a nice document, with pictures

 

If you have something you think should be in the FAQ, please post it here

 

 

Thanks :)


Edited by retroillucid, Fri Sep 6, 2013 4:43 PM.


#10 retroillucid OFFLINE  

retroillucid

    Quadrunner

  • Topic Starter
  • 8,114 posts

Posted Sat Sep 7, 2013 1:44 AM

Another quick update  :)



#11 PkK OFFLINE  

PkK

    Moonsweeper

  • 469 posts
  • Location:Europe

Posted Sun Sep 8, 2013 2:53 PM

I fixed the peephole issue and implemented support for named address spaces in ROM. Something like this should work now (sdcc 3.3.1 #8837 or later):

void setb0(void) // The function that sets the currently active memory bank to b0
{
  *((volatile char*)0xffff);
}

void setb1(void) // The function that sets the currently active memory bank to b1
{
  *((volatile char*)0xfffe);
}

__addressmod const setb0 spaceb0; // Declare a named address space called spaceb0 that uses setb0() and reisdes in RAM
__addressmod setb1 spaceb1; // Declare a named address space called spaceb1 that uses setb1() and resides in ROM
const spaceb0 int x = 42; // An int in address space spaceb0
spaceb1 int *y; // A pointer to an int in address space spaceb1
const spaceb0 int *spaceb1 z; //A pointer in address space sapceb1 that points to a constant int in address space spaceb0

The variables will be placed into areas of the same name, so you can use linker options -b to place the named address spaces into memory.

 

Again, you might also want to have a look at section 3.6.2 of the sdcc manual.

 

Philipp

 



#12 retroillucid OFFLINE  

retroillucid

    Quadrunner

  • Topic Starter
  • 8,114 posts

Posted Wed Sep 11, 2013 3:07 PM

thanks Philipp!

I'll update the FAQ

#13 PkK OFFLINE  

PkK

    Moonsweeper

  • 469 posts
  • Location:Europe

Posted Mon Mar 17, 2014 4:42 PM

I jut noticed there was a minor mistake in the example I posted. Here's a corrected version:

void setb0(void) // The function that sets the currently active memory bank to b0

{

  *((volatile char*)0xffff);

}



void setb1(void) // The function that sets the currently active memory bank to b1

{

  *((volatile char*)0xfffe);

}



__addressmod setb0 const spaceb0; // Declare a named address space called spaceb0 that uses setb0() and resides in ROM

__addressmod setb1 spaceb1; // Declare a named address space called spaceb1 that uses setb1() and resides in RAM

const spaceb0 int x = 42; // An int in address space spaceb0

spaceb1 int *y; // A pointer to an int in address space spaceb1

const spaceb0 int *spaceb1 z; //A pointer in address space sapceb1 that points to a constant int in address space spaceb0





#14 youki OFFLINE  

youki

    River Patroller

  • 2,448 posts

Posted Tue Mar 18, 2014 2:06 AM

 

I jut noticed there was a minor mistake in the example I posted. Here's a corrected version:

void setb0(void) // The function that sets the currently active memory bank to b0

{

  *((volatile char*)0xffff);

}



void setb1(void) // The function that sets the currently active memory bank to b1

{

  *((volatile char*)0xfffe);

}



__addressmod setb0 const spaceb0; // Declare a named address space called spaceb0 that uses setb0() and resides in ROM

__addressmod setb1 spaceb1; // Declare a named address space called spaceb1 that uses setb1() and resides in RAM

const spaceb0 int x = 42; // An int in address space spaceb0

spaceb1 int *y; // A pointer to an int in address space spaceb1

const spaceb0 int *spaceb1 z; //A pointer in address space sapceb1 that points to a constant int in address space spaceb0



 

Hi Philip ,

 

Thanks for the update.   You should also correct that in the SDCC documentation  (paragraph 3.6.2 )  

 

I will try again tonight. :)



#15 PkK OFFLINE  

PkK

    Moonsweeper

  • 469 posts
  • Location:Europe

Posted Tue Mar 18, 2014 7:43 AM


 

You should also correct that in the SDCC documentation  (paragraph 3.6.2 )  

 

Fixed in revision #8961.

 

Philipp



#16 digress OFFLINE  

digress

    Stargunner

  • 1,123 posts
  • Location:Toronto, Ontario, Canada

Posted Tue Mar 18, 2014 8:08 AM

Cool,

 

I would love to be able to program in C language for the bank switching megacart in the future. Any development to make that easier for me is very welcome. I also would need to locate some megacart pcbs.

 

Please keep up the good work.



#17 Pixelboy OFFLINE  

Pixelboy

    Quadrunner

  • 8,176 posts
  • Location:Montreal, Canada

Posted Tue Mar 18, 2014 11:57 AM

I just had a look at the PDF posted in the first post of this thread, and I think it needs some work. What is the C code doing in section 1, when it clearly belongs in section 2? And the entire content of section 2 has nothing to do with C language.

Furthermore, it's good to know how to switch banks in C, but that's only half of the required knowledge. The second part, which is just as important if not more so, is how to create/compile a 128K or 256K ROM file. Do I need to piece the banks together with an hex editor? Some tips about how to do this would be nice. :)

#18 youki OFFLINE  

youki

    River Patroller

  • 2,448 posts

Posted Tue Mar 18, 2014 1:08 PM

I just had a look at the PDF posted in the first post of this thread, and I think it needs some work. What is the C code doing in section 1, when it clearly belongs in section 2? And the entire content of section 2 has nothing to do with C language.

Furthermore, it's good to know how to switch banks in C, but that's only half of the required knowledge. The second part, which is just as important if not more so, is how to create/compile a 128K or 256K ROM file. Do I need to piece the banks together with an hex editor? Some tips about how to do this would be nice. :)

 

My question would be more ,  if you have a 256k ROM  , said one file of 256k .. how to you put it on a MegaCart?   Do we have to split it in 32k part  in order to burn each bank on eeprom or what ever used in the cartridge?

 

I think you have experience with that Luc? ... Does Mecha8 comes to you to be burn in one file or multiple files?



#19 retroillucid OFFLINE  

retroillucid

    Quadrunner

  • Topic Starter
  • 8,114 posts

Posted Tue Mar 18, 2014 1:10 PM

My question would be more ,  if you have a 256k ROM  , said one file of 256k .. how to you put it on a MegaCart?   Do we have to split it in 32k part  in order to burn each bank on eeprom or what ever used in the cartridge?
 
I think you have experience with that Luc? ... Does Mecha8 comes to you to be burn in one file or multiple files?


You burn one file into the eprom

#20 Pixelboy OFFLINE  

Pixelboy

    Quadrunner

  • 8,176 posts
  • Location:Montreal, Canada

Posted Tue Mar 18, 2014 2:36 PM

 

My question would be more ,  if you have a 256k ROM  , said one file of 256k .. how to you put it on a MegaCart?   Do we have to split it in 32k part  in order to burn each bank on eeprom or what ever used in the cartridge?
 
I think you have experience with that Luc? ... Does Mecha8 comes to you to be burn in one file or multiple files?


5-11under could answer that question with absolute certainty. :)

#21 retroillucid OFFLINE  

retroillucid

    Quadrunner

  • Topic Starter
  • 8,114 posts

Posted Tue Mar 18, 2014 2:48 PM

 

5-11under could answer that question with absolute certainty. :)

 

I've burned all the first batch of Mario eproms by myself

There was only 1 file to burn

 

The bankswitching is on 1 eprom ... the banks are NOT located in another eprom(s)


Edited by retroillucid, Tue Mar 18, 2014 2:49 PM.


#22 youki OFFLINE  

youki

    River Patroller

  • 2,448 posts

Posted Tue Mar 18, 2014 3:23 PM

 

I jut noticed there was a minor mistake in the example I posted. Here's a corrected version:

void setb0(void) // The function that sets the currently active memory bank to b0

{

  *((volatile char*)0xffff);

}



void setb1(void) // The function that sets the currently active memory bank to b1

{

  *((volatile char*)0xfffe);

}



__addressmod setb0 const spaceb0; // Declare a named address space called spaceb0 that uses setb0() and resides in ROM

__addressmod setb1 spaceb1; // Declare a named address space called spaceb1 that uses setb1() and resides in RAM

const spaceb0 int x = 42; // An int in address space spaceb0

spaceb1 int *y; // A pointer to an int in address space spaceb1

const spaceb0 int *spaceb1 z; //A pointer in address space sapceb1 that points to a constant int in address space spaceb0



 

Hi Philip,

 

I managed to compile now and link.  But the result rom is not usable.

 

In fact, the coleco's cartridge header (0x55 0xAA...etc )  in the rom file is now located at  0x0F8F   instead of 0x0000 .

 

Do you have an idea how to fix that?  

 

Thanks



#23 5-11under OFFLINE  

5-11under

    River Patroller

  • 3,396 posts
  • Location:Ontario, Canada

Posted Tue Mar 18, 2014 4:12 PM

 

My question would be more ,  if you have a 256k ROM  , said one file of 256k .. how to you put it on a MegaCart?   Do we have to split it in 32k part  in order to burn each bank on eeprom or what ever used in the cartridge?

 

I think you have experience with that Luc? ... Does Mecha8 comes to you to be burn in one file or multiple files?

 

See page 3 of the FAQ for reference. For the EPROM, bank 0 is at the start (of the EPROM - takes up 16K), followed by bank 1, 2, etc. These get mapped (one at a time, depending on which one is selected) to the upper 16K of memory space in the CV (Cxxx to Fxxx). The final (upper) bank of the EPROM gets mapped to 8xxx to Bxxx of the memory space in the CV.



#24 bfg.gamepassion OFFLINE  

bfg.gamepassion

    Chopper Commander

  • 247 posts
  • Location:Lille - France

Posted Sat Nov 22, 2014 1:51 AM

Hello,

 

 can someone make a hellow world example for SDCC with makefile, ctr0 modified is needed and so ? Because i've got the theory in mind, but for the moment i know no one (Youki,Alekmaul and me) succeeding making a megacart rom in SDCC ... :( :(

 

Edit : forget it, seems like AlekMaul just suceed for Bagman :) :)


Edited by bfg.gamepassion, Sat Nov 22, 2014 1:53 AM.


#25 nanochess OFFLINE  

nanochess

    Processorus Polyglotus

  • 5,835 posts
  • Coding something good
  • Location:Mexico City

Posted Sat Nov 22, 2014 8:24 AM

Here is the link to AlekMaul code for using Megacart with SDCC 3.3.0

http://www.gamopat-f...egacart#1945318

 

:)







Also tagged with one or more of these keywords: Bank switching

0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users