Jump to content
retroillucid

ColecoVision MegaCart FAQ

Recommended Posts

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!

MegaCart FAQ V1-2.pdf

Edited by retroillucid
  • Like 4

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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.

 

  • Like 1

Share this post


Link to post
Share on other sites

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.

  • Like 2

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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 ;)

  • Like 1

Share this post


Link to post
Share on other sites

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)

  • Like 3

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

 

  • Like 3

Share this post


Link to post
Share on other sites

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



  • Like 1

Share this post


Link to post
Share on other sites

 

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

Share this post


Link to post
Share on other sites

 

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

 

Fixed in revision #8961.

 

Philipp

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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?

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

 

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

Share this post


Link to post
Share on other sites

 

 

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

Share this post


Link to post
Share on other sites

 

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

Share this post


Link to post
Share on other sites

 

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.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
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.

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