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...
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;
}
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....
// Â 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;
  }  Â
}
/*******************************************************************
* Jo Engine - Ultra Stable Native 16-Bit Dual Cartridge Tester
*******************************************************************/
#include <jo/jo.h>
/* Hardware Constants - Safe Probing Only */
#define CART_ID_ADDR ((volatile unsigned char *)0x24FFFFFF)
#define CART_INIT_ADDR ((volatile unsigned short *)0x257EFFFE)
#define A_BUS_SET_REG ((volatile unsigned long *)0x25FE0080)
#define A_BUS_REF_REG ((volatile unsigned long *)0x25FE0033)
/* Memory Map for Extended RAM (DRAM0) */
#define EXT_RAM_BASE 0x22400000
#define SIZE_1MB_BYTES (1 * 1024 * 1024)
#define SIZE_4MB_BYTES (4 * 1024 * 1024)
typedef enum {
TEST_STATE_IDLE = 0,
TEST_STATE_PASS1_WRITE,
TEST_STATE_PASS1_VERIFY,
TEST_STATE_COMPLETE_SUCCESS,
TEST_STATE_FAILED
} test_state_t;
/* Global Engine State Definitions */
static bool is_ram_cart_ready = false;
static test_state_t g_test_status = TEST_STATE_IDLE;
static unsigned long g_current_offset = 0;
static unsigned long g_failed_address = 0;
static unsigned short g_expected_val = 0;
static unsigned short g_actual_val = 0;
static unsigned long g_total_test_bytes = 0;
static unsigned long g_mirror_mask = 0;
static int g_display_expected_mb = 0;
/* Hardware spin-delay helper */
static void bus_delay(void)
{
for (volatile int i = 0; i < 0x200; i++) {
__asm__("nop");
}
}
#pragma GCC push_options
#pragma GCC optimize ("O0")
/* Baseline Hardware Identification and Safe Target Bus Init */
static bool _init_hardware_bus(void)
{
unsigned char cart_id = *CART_ID_ADDR;
if (cart_id == 0x5A || cart_id == 0x1A || cart_id == 0xDA) {
g_total_test_bytes = SIZE_1MB_BYTES;
g_mirror_mask = SIZE_1MB_BYTES - 1;
g_display_expected_mb = 1;
/* Force hardware refresh configurations strictly for physical 1MB layouts */
*CART_INIT_ADDR = 0x0001;
bus_delay();
*A_BUS_SET_REG = 0x23301FF0;
*A_BUS_REF_REG = 0x00000013;
bus_delay();
} else if (cart_id == 0x5C || cart_id == 0x1C || cart_id == 0xDC) {
g_total_test_bytes = SIZE_4MB_BYTES;
g_mirror_mask = SIZE_4MB_BYTES - 1;
g_display_expected_mb = 4;
/* Do NOT modify A_BUS registers to keep SAROO flashcarts functional */
} else {
return false;
}
return true;
}
void jo_dram_cart_init(void)
{
if (!_init_hardware_bus()) {
is_ram_cart_ready = false;
g_test_status = TEST_STATE_FAILED;
} else {
is_ram_cart_ready = true;
g_test_status = TEST_STATE_PASS1_WRITE;
g_current_offset = 0;
}
}
/* Sequential Non-Blocking 16-Bit Memory Validation Engine */
static void run_sequential_stress_test(void)
{
if (g_total_test_bytes == 0) return;
const unsigned long chunk_size = 64 * 1024; // 64KB parsed per loop cycle
unsigned long end_offset = g_current_offset + chunk_size;
if (end_offset > g_total_test_bytes) {
end_offset = g_total_test_bytes;
}
/* FIXED: Target the uncached region using native 16-bit shortward definitions */
volatile unsigned short *uncached_ram_16 = (volatile unsigned short *)(EXT_RAM_BASE | 0x20000000);
switch (g_test_status) {
case TEST_STATE_PASS1_WRITE:
/* Step by 2 bytes (16-bits) to match physical hardware layout dimensions */
for (; g_current_offset < end_offset; g_current_offset += 2) {
unsigned long target_index = (g_current_offset & g_mirror_mask) / 2;
/* Create a solid 16-bit alternating check sequence */
uncached_ram_16[target_index] = 0x5555;
}
if (g_current_offset >= g_total_test_bytes) {
g_current_offset = 0;
g_test_status = TEST_STATE_PASS1_VERIFY;
}
break;
case TEST_STATE_PASS1_VERIFY:
for (; g_current_offset < end_offset; g_current_offset += 2) {
unsigned long target_index = (g_current_offset & g_mirror_mask) / 2;
unsigned short read_val = uncached_ram_16[target_index];
if (read_val != 0x5555) {
g_failed_address = EXT_RAM_BASE + g_current_offset;
g_expected_val = 0x5555;
g_actual_val = read_val;
g_test_status = TEST_STATE_FAILED;
return;
}
}
if (g_current_offset >= g_total_test_bytes) {
g_test_status = TEST_STATE_COMPLETE_SUCCESS;
/* Expose the validated boundary pools back to Jo Engine */
jo_add_memory_zone((unsigned char *)EXT_RAM_BASE, g_total_test_bytes);
}
break;
default:
break;
}
}
#pragma GCC pop_options
void my_game_draw(void)
{
jo_printf(2, 2, "=== NATIVE 16-BIT RAM TESTER ===");
unsigned char current_id = *CART_ID_ADDR;
jo_printf(2, 4, "Detected Cartridge ID: 0x%02X", current_id);
jo_printf(2, 5, "Target Space Capacity: %d MB", g_display_expected_mb);
if (!is_ram_cart_ready && g_test_status == TEST_STATE_FAILED) {
jo_printf(2, 7, "Status: DETECT OPERATION ERROR");
return;
}
int current_kb = (int)(g_current_offset / 1024);
int total_kb = (int)(g_total_test_bytes / 1024);
switch (g_test_status) {
case TEST_STATE_PASS1_WRITE:
jo_printf(2, 7, "Status: STRESSING PASS (WRITE)... ");
jo_printf(2, 8, "Verified: %d KB / %d KB", current_kb, total_kb);
break;
case TEST_STATE_PASS1_VERIFY:
jo_printf(2, 7, "Status: STRESSING PASS (VERIFY)... ");
jo_printf(2, 8, "Verified: %d KB / %d KB", current_kb, total_kb);
break;
case TEST_STATE_COMPLETE_SUCCESS:
jo_printf(2, 7, "Status: SUCCESS! POOL IS OPERATIONAL ");
jo_printf(2, 8, "Result: %dMB Space fully operational.", g_display_expected_mb);
break;
case TEST_STATE_FAILED:
jo_printf(2, 7, "Status: !!! TEST VERIFICATION FAULT !!!");
jo_printf(2, 9, "Address: 0x%08X", (unsigned int)g_failed_address);
jo_printf(2, 10, "Expected: 0x%04X", g_expected_val);
jo_printf(2, 11,"Read Out: 0x%04X", g_actual_val);
break;
default:
break;
}
run_sequential_stress_test();
}
void jo_main(void)
{
jo_core_init(JO_COLOR_Black);
jo_dram_cart_init();
jo_core_add_callback(my_game_draw);
jo_core_run();
}