HomeForumsWhat's newResources 
 
 
4-mb Ram Cart
black - Jun 29, 2004
   black Jun 29, 2004 
Is there any way to incorporate in to home dev. I'm planning to work on a ngpc emu but I want to use the whole system ram for the emu and other stuff and the 4 mb ram cart for roms, but i dont want to make it if i cant use the 4-mb ram cart.

   antime Jun 29, 2004 
Just check for the presence of the cart (if you want to make it easy for people with the faulty carts sold now, check both the cart id and the amount of memory present) then just use it.

   RockinB Jun 30, 2004 

  
Originally posted by black@Jun 30, 2004 @ 02:22 AM

...I want to use the whole system ram for the emu and other stuff and the 4 mb ram cart for roms...


Hey, what a great idea!

There is the SEGA_MEM library, for which you define an area of RAM (Cartridge, ...) and then you can use this area for dynamic allocation via malloc. The library has it's own malloc, free,... functions. And you can only define one such area. I doubt you would need multiple areas on Saturn, but little modification could overcome this.

   RockinB Jan 10, 2005 
1. How to use External RAM cartridge

2. How to use half of CPU internal cache as RAM

1. Based on the ST-TECH-47.pdf manual and SCU user manual for memory mapping, i coded a sample to init the external RAM Cartridge:

Code:
  
int initCartridge(unsigned char cs) { Uint32 id, setReg, *ptr, i, size, ok; //!!!!!! on real Saturn, it doesn't go beyound this check // on emu, always reports id == 0 // cartridge initialization: as in ST-TECH-47.pdf // 1. verify cartridge id // 5A - 8 MB // 5C - 32 MB id = *((Uint32 *)0x24ffffff); if(id == 0x5a) { slPrint("8 MB RAM cart detected!", slLocate(2,5)); } else if(id == 0x5c) { slPrint("32 MB RAM cart detected!", slLocate(2,5)); } else { // 2. prompt proper connection slPrint("There is no external RAM cartridge!", slLocate(2,5)); slPrintHex(id, slLocate(5,6)); // return 0; } slPrintHex(id, slLocate(5,6)); // 3. write 1 to initialize *((Uint32 *)0x257efffe) = 1; // 4. set A-bus set and refresh registers setReg = 0; if(cs == 0) { // set cs0 for 32MBit setReg |= 1 << 29; // After-READ precharge insert bit ptr = (Uint32 *)0x22000000; size = 1048576; } else { // set cs1 for 16MBit ?? setReg |= 1 << 28; // external wait effective bit ptr = (Uint32 *)0x24000000; size = 262144; } setReg |= 3 << 24; // Burst cycle wait number setReg |= 3 << 20; // Normal cycle wait number *((Uint32 *)0x25fe0080) = setReg; // 5. verify data before proceeding // write for(i = 0; i < size; i++) *(ptr++) = i; // read ok = 1; for(i = 0; i < size; i++) { if(*(ptr++) != i) { ok = 0; } } slPrint("verifying RAM cartridge:", slLocate(2,7)); slPrintHex(ok, slLocate(5,8)); return ok; }

Now the problem is that it freezes on real Saturn and always reports id = 0 in Satourne emu.

Furthermore, the manual states that area 0x22400000 - 0x227FFFFF is allocated to the cartridge, but I cannot find this elsewhere, it's not on SCU's memory map....

2. I know how to set 2kB of the 4kB cpu cache as local RAM:

If the cache is set to 2-way mode(instead of 4-way mode), it is set to 2kB RAM, too. The SEGA_CSH library can be taken to do this: CSH_SET_WAY_MODE( CSH_2WAY )

But I don't know how to address this RAM directly!

Now that I had another look into CSH_MAIN.C of SBL's cache lib, I see that CSH_init() writes zeros to locations after 0x60000000 and performs CSH_SET_ACS_WAY(way) 4 times.

Could this have something to do with the RAM location?

   antime Jan 10, 2005 
Reading a 32-bit int from 0x24ffffff isn't going to net you more than an alignment exception. The memory range in the cartridge manual is the correct one, and the SH7604 manual will have info on using the cache as RAM.

   ExCyber Jan 10, 2005 

  
Furthermore, the manual states that area 0x22400000 - 0x227FFFFF is allocated to the cartridge, but I cannot find this elsewhere, it's not on SCU's memory map....


Cartridges are mapped to the "A-Bus CS0" (normally ROM/RAM) and "A-Bus CS1" (normally cart ID) regions.

   RockinB Jan 12, 2005 
I'm very, very happy to say:

Both problems are solved! :banana :cheers

(thanks antime and ExCyber!)

1. checking for, initializing and using extended RAM carts:

Code:
  
//  RB_initRAMCart(Uint8 cs, Uint8 quiet) //  - checks for present RAM cart, inits and verifies it // //  inputs: //      cs          -   select whether to set CS0 or CS1 space //                      (both works, don't know where the difference is)   //      quiet       -   don't print messages // //  returns: //      cartridge id    -   on success //                          (8MB: 0x5a or 32MB: 0x5c) //      -1              -   no cart //      -2              -   data verify failed Sint16 RB_CartRAM_init(Uint8 cs, Uint8 quiet) {    Uint32 setReg, refReg, *DRAM0, *DRAM1, DRAMsize, i, ok;    Uint8 id;    // cartridge initialization: as in ST-TECH-47.pdf    // 1. verify cartridge id    // 5A - 8 MB    // 5C - 32 MB    //! is last byte of A-BUS CS1 area    id = *((Uint8 *)0x24ffffff);    if(id == 0x5a) {        DRAMsize = 0x80000;        if(quiet == 0)            slPrint("8 MB RAM cart detected!", slLocate(2,5));    } else if(id == 0x5c) {        DRAMsize = 0x200000;        if(quiet == 0)            slPrint("32 MB RAM cart detected!", slLocate(2,5));    } else {              // 2. prompt proper connection        if(quiet == 0) {            slPrint("The extended RAM", slLocate(2,5));            slPrint("cartridge is not", slLocate(2,6));            slPrint("inserted properly.", slLocate(2,7));            slPrint("Please turn off", slLocate(2,9));            slPrint("power and reinsert", slLocate(2,10));            slPrint("the extended RAM", slLocate(2,11));            slPrint("cartridge.", slLocate(2,12));        }            return -1;    }    // 3. write 1 to initialize    // is at the end of A-BUS Dummy area    // !!! word format !!! (but what is meant?)    *((Uint16 *)0x257efffe) = 1;        // 4. set A-bus set and refresh registers    setReg = refReg = 0;    if(cs == 0) {        // set cs0 for 32MBit        setReg |= 1 << 29;  // After-READ precharge insert bit        setReg |= 3 << 24;  // Burst cycle wait number        setReg |= 3 << 20;  // Normal cycle wait number    } else {        // set cs1 for 16MBit ??        setReg |= 1 << 28;  // external wait effective bit        setReg |= 15 << 24; // Burst cycle wait number        setReg |= 15 << 20; // Normal cycle wait number    }    *((Uint32 *)0x25fe00B0) = setReg;        // A-Bus refresh register    refReg |= 1 << 4;       // A-Bus refresh enable bit            // I've just take this value            // see SCU user manual for value range    refReg |= 1;            // A-Bus refresh cycle wait    *((Uint32 *)0x25fe00B8) = refReg;        // 5. verify data before proceeding        // cache-through DRAM0 and DRAM1    DRAMsize >>= 2; // byte length -> longword length    DRAM0 = (Uint32 *)0x22400000;    DRAM1 = (Uint32 *)0x22600000;        // write    for(i = 0; i < DRAMsize; i++) {        *(DRAM0 + i) = i;        *(DRAM1 + i) = DRAMsize - 1 - i;    }            // read    ok = 1;    for(i = 0; i < DRAMsize; i++) {        if(*(DRAM0 + i) != i) {            were_here("DRAM0 %i != %i", *(DRAM0 + i), i);            ok = 0;        }            if(*(DRAM1 + i) != (DRAMsize - 1 - i)) {            were_here("DRAM1 %i != %i", *(DRAM1 + i), (DRAMsize - 1 - i));            ok = 0;        }        }          if(ok == 1) {                                if(quiet == 0)            slPrint("verifying RAM cart OK!", slLocate(2,7));        return id;    } else {        if(quiet == 0)            slPrint("verifying RAM cart FAILED!", slLocate(2,7));        return -2;    }     }

2. initializing and using half of CPU's Cache as RAM:

init:

CSH_SET_WAY_MODE( CSH_2WAY )

Edit: better use CSH_Init(CSH_2WAY), it cares about cache disabling and stuff

now ways 0, 1 are RAM,

ways 2,3 mixed instruction/data cache memory

use:

0xC0000000

way 0

0xC00003FF

0xC0000400

way 1

0xC00007FF

Wow, I'm very excited about that! Now borders are shifted back...

Edit: look at 2.