ハードウェア - フラッシュカートリッジ

Visoly / Flash-Advance

The older-style non-turbo cartridges contain a single intel 28F Flash, while the newer turbo cartridges contain a pair of chips interleaved.
Type Flash RAM Notes
64M 1x 28F640J3A (120ns) 128 KB 3 bank bits, cannot reliably do 3/1 waits
Turbo 64M 2 x 28F320J3A (110ns) 256 KB Only has 3 bank bits
Turbo 128M 2 x 28F640J3A (120ns) 256 KByte Only has 3 bank bits
FA Pro 64M 2 x 28F320J3A (110ns) 256 KByte Also supports 4 kbit eeprom
FA Pro 128M 2 x 28F640J3A (120ns) 256 KByte Also supports 4 kbit eeprom
FA Pro 256M 2 x 28F640J3A (120ns) 256 KByte Also supports 4 kbit eeprom
FA Xtreme 512M/1G 2 or 4 x 28F256K3 256 KByte

Notes:

   * All carts use Intel flash parts.
   * All of the 256 KB SRAM carts use a NEC D442000LGU chip.
   * None of the carts support the 64 kbit eeprom type
   * The three bank bits carts only support the 8 MB, 4 MB, and 256 KB bits (see below for more information). 


VisolyCommand(uint32 address, uint16 data, uint16 count)
 for ( ; count > 0; count--)
   GBA_CART[addr << 1] = data;

VisolyUnlock(yes, it really is this stupid!)
 VisolyCommand(0x987654, 0x5354, 1)
 VisolyCommand(0x012345, 0x1234, 500)
 VisolyCommand(0x007654, 0x5354, 1)
 VisolyCommand(0x012345, 0x5354, 1)
 VisolyCommand(0x012345, 0x5678, 500)
 VisolyCommand(0x987654, 0x5354, 1)
 VisolyCommand(0x012345, 0x5354, 1)
 VisolyCommand(0x765400, 0x5678, 1)
 VisolyCommand(0x013450, 0x1234, 1)
 VisolyCommand(0x012345, 0xABCD, 500)
 VisolyCommand(0x987654, 0x5354, 1)

VisolyUnlockFlash
 VisolyUnlock
 VisolyCommand(0xF12345, 0x9413, 1)

VisolySetSRAMBank(bank)
 VisolyUnlock
 VisolyCommand(0xA12345, bank & 7, 1)

bool VisolySetFlashBaseAddress(offset)
 if (offset & 0xFF3F7FFF) return false

 base = ((offset >> 22) & 3) | ((offset >> 12) & 8)
 VisolyUnlock
 VisolyCommand(0xB5AC97, base, 1)

 return true

bool VisolySetFlashBaseAddress(offset)
 if (offset & 0xFE007FFF) return false

 base = ((offset >> 22) & 3) | ((offset >> 22) & 4) | ((offset >> 12) & 0x3F8)
 VisolyUnlock
 VisolyCommand(0xB5AC97, base, 1)

 return true


The Flash offset register is a bit funky, and only bits 0, 1, and 3 are implemented on the older cartridges. Format of the register is shown below:
15..10 9 8 7 6 5 4 3 2 1 0
  • 2 MB 1 MB 512 KB 256 KB 128 KB 64 KB 32 KB 16 MB 8 MB 4 MB

Thanks to Jeff Frohwein and Reiner Ziegler
GBA Movie Player
Components

   * FlashROM, SST39VF400A 256Kx16 (0x278000BF) or SST39VF800A 512Kx16 (0x278100BF)
   * CPLD, Actel eX64, 64 pin TQFP 

Pinout
GBA A flash A inverted pin
0 10 1 6
1 11 1 5
2 12 1 4
3 8 1 8
4 9 0 7
5 7 0 18
6 6 0 19
7 5 1 20
8 2 0 23
9 3 1 22
10 4 1 21
11 0 1 25
12 1 1 24
13 - - -
14 - - -
15 - - -
16 13 0 3
17 14 0 2
18 15 0 1
19 16 0 48
20 17 0 17
21 18 0 16 (512K x 16 only)
Registers
Data register MP_DATA 0x09000000
Error register MP_REG_ERR 0x09020000
Sector # MP_REG_SEC 0x09040000
LBA byte 1 MP_REG_LBA1 0x09060000
LBA byte 2 MP_REG_LBA2 0x09080000
LBA byte 3 MP_REG_LBA3 0x090A0000
0xE0 | LBA byte4 MP_REG_LBA4 0x090C0000
Command register MP_REG_CMD 0x090E0000
Status register MP_REG_STS 0x098C0000
Unlock sequence

Unlocking is required to read offset >=0x200.

A short unlock sequence that works in most cases can be performed by reading these offsets in order: 0x0134,0x00D4,0x0144,0x00EC,0x01E4,0x0188,0x01F4,0x01D4
M3 CF/SD

CompactFlash addresses
Data register MP_DATA 0x08800000
Error register MP_REG_ERR 0x08820000
Sector # MP_REG_SEC 0x08840000
LBA byte 1 MP_REG_LBA1 0x08860000
LBA byte 2 MP_REG_LBA2 0x08880000
LBA byte 3 MP_REG_LBA3 0x088A0000
0xE0 | LBA byte4 MP_REG_LBA4 0x088C0000
Command register MP_REG_CMD 0x088E0000
Status register MP_REG_STS 0x080C0000

M3 mode switching:


static u16 M3_readHalfword (u32 addr) {
  return *((vu16*)addr);
}

void M3_changeMode (u32 mode) {

  M3_readHalfword (0x08e00002);
  M3_readHalfword (0x0800000e);
  M3_readHalfword (0x08801ffc);
  M3_readHalfword (0x0800104a);
  M3_readHalfword (0x08800612);
  M3_readHalfword (0x08000000);
  M3_readHalfword (0x08801b66);
  M3_readHalfword (0x08000000 + (mode << 1));
  M3_readHalfword (0x0800080e);
  M3_readHalfword (0x08000000);

  if ((mode & 0x0f) == 4) {   // unlock ROM addr >= 0x200
     M3_readHalfword (0x080001e4);
     M3_readHalfword (0x080001e4);
     M3_readHalfword (0x08000188);
     M3_readHalfword (0x08000188);
  } else {
     M3_readHalfword (0x09000000);
  }

}

#define M3_MODE_ROM 0x00400004
#define M3_MODE_MEDIA 0x00400003
#define M3_MODE_RAM_R 0x00400002
#define M3_MODE_RAM_RW 0x00400006 // read-write access 



(Thanks to Chishm)

RAM R/W mode can also be enabled by writing 0xAA55 to 0x09FFEFFE.
G6

G6 SDRAM can be made writable by writing 0xAA55 to 0x09FFFFFE.
General CF information

CF card status:

   * Inserted: 0x50
   * Removed: 0x00
   * Ready: 0x58
   * DRQ: 0x08
   * Busy: 0x80 

CF card commands:

   * LBA: 0xE0
   * Read: 0x20
   * Write: 0x30 

Initialize CF by writing 0x50 to the status register: MP_REG_STS = 0x50.

Thanks to DarkFader, Chishm, and MightyMax for info on the GBA MP and M3.
SuperCard (CF version)

Components:

   * Lattice ispMACH LC4128V : CPLD (Mach4000 family)
   * HY57V561620CTP-H (Hynix): 256 Mbit SDRAM, 3.3V, PC133-CL3
   * M5M5V208AKV (Mitsubishi): 2 Mbit CMOS SRAM , 2.7-3.6V, 70ns
   * 29LV400TC-90PFTN (Fairchild also avail. from Fujitsu): 4Mbits FLASH, 90ns, 3V 

Note: Untested, based on code posted to forum. Credit due to the unknown author of 20051024113435206.zip
Name Define Address Size
Sector buffer SC_CF_DATA 0x09000000 512
Unlock register SC_UNLOCK 0x09FFFFFE 2
Sector count SC_CF_SECTOR_COUNT 0x09040000 2
LBA byte 1 SC_CF_LBA1 0x09060000 2
LBA byte 2 SC_CF_LBA2 0x09080000 2
LBA byte 3 SC_CF_LBA3 0x090A0000 2
0xE0 | LBA byte4 SC_CF_LBA4 0x090C0000 2
Command register SC_CF_CMD 0x090E0000 2
Status register SC_CF_STATUS 0x099C0000 2
Status register SC_CF_STATUS_L 0x099C0000 1

The status register can be accessed as both a byte or halfword, the others all seem to be treated as halfwords (even though only 8 bits of data are stored in each). I don't have a supercard to test this for sure. Thus, you can't read more than 255 sectors at a time either (possibly 256 if 0 is stored?).

Unlike the M3, either the supercard appears to have a 512 byte sector buffer (unlikely), rather than a one byte FIFO, or the daft code just makes use of address mirroring to read the one byte FIFO at 512 addresses (more likely).

Format of the Supercard unlock register:
15..3 ?
2 Enable SDRAM
1 Enable CF / SD
0 Always 1 after 0x5AA5

You write 0xA55A twice, then write 0x5 (enable SDRAM), 0x3 (enable CF / SD), or 0x1 (disable SDRAM, presumably also disable CF/SD) twice.

I'm going to take a wild guess and say that enabling both SDRAM and CF/SD at the same time is a bad idea. Also, on the cartridges with both SD and CF, are there two seperate bits to enable them?


Supercard_Unlock:
 SC_UNLOCK = 0xA55A
 SC_UNLOCK = 0xA55A
 SC_UNLOCK = 0x0003
 SC_UNLOCK = 0x0003

Supercard_IsCFInserted
 SC_CF_STATUS = 0x0050
 nop
 return (SC_CF_STATUS_L == 0x50)

Supercard_CFCommand(command, address, count)
 while ((SC_CF_STATUS_L & 0xC0) != 0x40) ;
 SC_CF_SECTOR_COUNT = count;
 SC_CF_LBA1 = address & 0xFF;
 SC_CF_LBA2 = (address>>8) & 0xFF;
 SC_CF_LBA3 = (address>>16) & 0xFF;
 SC_CF_LBA4 = ((address>>24) & 0xFF) | 0xE0;
 SC_CF_CMD = command;


Delay16
 DelayLoop(0x10)

Supercard_ReadSectors(address, count, destination)
 Supercard_CFCommand(0x20, address, count)
 Delay16
 for each sector do
   while ((SC_CF_STATUS & 0x88) == 0x80) ;
   Copy 512 bytes from SC_CF_DATA to destination and advance destination
 end;


Supercard_WriteSectors(source, address, count)
 Supercard_CFCommand(0x30, address, count)
 Delay16
 for each sector do
   while ((SC_CF_STATUS & 0x88) == 0x80) ;
   Copy 512 bytes from source to SC_CF_DATA and advance destination
 end;
 while ((SC_CF_STATUS & 0x80) != 0) ;


Supercard (SD version)
Components

   * FlashROM, 512KB, Fairchild 29LV400TV-80PFTN
   * SDRAM, 32 MBytes, Hynix HY57V561620CT-H
   * SRAM, 256 KBytes, Samsung KM68V2000LTGI-8L
   * CPLD, Lattice ispMACH LC4128V 75T100-10I
   * Oscillator, 50 MHz
   * JTAG connections at bottom cart edge 

Unlock register
15 ?
14 Should be 1 ?
13 ?
12 some bankswitch?
9..11 ?
8 some bankswitch?
7 ?
5..6 Should be 0 ?
4 0=select ROM, 1=select SD
3 ?
2 SDRAM: 0=write protect, 1=allow writes
1 ?
0 0=select ROM or SD, 1=select SDRAM

(bits are manually tested without looking to any code)

To set a new value, write 0xA55A to this register twice, then write the desired value twice.

Below code is translated from some whack assembly, so it might contain bugs. Credit due to the unknown author of 20051024113435206.zip


SC_SD_COMMAND 0x09800000
SC_SD_DATA 0x09000000
SC_SD_READ 0x09100000


void sd_data_write_s(uint16 * buffer, uint16 * crc16buff)
 // Wait until it's idle
 while (!(SC_SD_DATA & 0x100)) ;
 r3 = SC_SD_DATA;

 // start bit
 SC_SD_DATA = 0

 r5 = 512;
 do {
   r3 = *buffer++
   r3 = r3 + (r3 << 20)
   r4 = r3 << 8
   SC_SD_DATA32 = r3
   SC_SD_DATA32 = r4
 } while (--r5 > 0);

 if (crc16buff) {
   r0 = crc16buff
   r1 = 0
   r5 = 8
   goto the copy loop again just above
 }

 // end bit
 SC_SD_DATA = 0xFF
 while (SC_SD_DATA & 0x100) ;
 r3 = SC_SD_DATA32
 r4 = SC_SD_DATA32


sd_data_read_s(uint16 * destination)
 while (SC_SD_READ & 0x100) ; // wait for the start bit to clear

 for (i = 0; i < 256; i++)
   r3 = SC_SD_READ32
   r4 = SC_SD_READ32
   r3 = r4 >> 16
   *destination++ = r4 >> 16;

 // Read (and throw away) the CRC-16 (2 bytes)
 r3 = SC_SD_READ32
 r4 = SC_SD_READ32
 r3 = SC_SD_READ32
 r4 = SC_SD_READ32

 // Read (and throw away) the end bit
 r3 = SC_SD_READ



void sd_com_crc16_s(uint8 * buffer, uint16 num, uint8 * crc16buff)
 r3 = r4 = r5 = r6 = 0

 r7 = 0x80808080
 r8 = 0x1021
 r1 = r1 << 3

 do {
   if (r7 & 0x80) r2 = *buffer++

   r3 = r3 << 1
   if (r3 & 0x10000) r3 = r3 ^ r8
   if (r2 & (r7>>24)) r3 = r3 ^ r8

   r4 = r4 << 1  
   if (r4 & 0x10000) r4 = r4 ^ r8
   if (r2 & (r7>>25)) r4 = r4 ^ r8

   r5 = r5 << 1
   if (r5 & 0x10000) r5 = r5 ^ r8
   if (r2 & (r7>>26)) r5 = r5 ^ r8

   r6 = r6 << 1
   if (r6 & 0x10000) r6 = r6 ^ r8
   if (r2 & (r7>>27)) r6 = r6 ^ r8

   r7 = (r7 >> 4) | (r7 << 28)

   r1 -= 4;
 } while (r1);


 mov  r2 = crc16buff
 r8 = 16
 do {
   r7 = r7 << 4
   if (r3 & 0x8000) r7 = r7 | 8
   if (r4 & 0x8000) r7 = r7 | 4
   if (r5 & 0x8000) r7 = r7 | 2
   if (r6 & 0x8000) r7 = r7 | 1

   r3 = r3 << 1
   r4 = r4 << 1
   r5 = r5 << 1
   r6 = r6 << 1

   r8--;
   if (r8 & 1) *crc16buf++ = r7
 } while (r8);


sd_crc7_s(uint8 * buffer, uint16 count)
 r3 = 0
 r4 = 0x80808080

 r1 = count*8
 do {
   if (r4 & 0x80) r2 = *buffer++
   r3 = r3 << 1

   if (r3 & 0x80) r3 ^= 9;
   if (r2 & (r4>>24)) r3 ^= 9;
   r4 = (r4 >> 1) | (r4 << 31)
 } while (--r1 > 0);  

 return (r3 << 1) + 1


sd_com_read_s
 while (SC_SD_COMMAND & 1) ; // wait for start bit to clear
 do r1--; while (r1);



sd_com_write_s(uint8 * buffer, uint32 count):
 while (!(SC_SD_COMMAND & 1)) ; // wait for start bit to set
 temp = SC_SD_COMMAND;          // throwaway read


 do {
   temp = *buffer++
   temp = temp + (temp << 17)
   r4 = temp<<2
   r5 = r4<<2
   r6 = r5<<2
   SC_SD_COMMAND = temp
   SC_SD_COMMAND = r4
   SC_SD_COMMAND = r5
   SC_SD_COMMAND = r6
 } while (--count)



send_clk(count)
 do {
   temp = SC_SD_COMMAND; // throwaway read
 } while (--count)



void SDCommand(uint8 command, uint8 num, uint32 sector)
 uint8 buffer[6];

 buffer[0] = command | 0x40;
 buffer[1] = sector >> 24;
 buffer[2] = (sector >> 16) & 0xFF;
 buffer[3] = (sector >> 8) & 0xFF;
 buffer[4] = sector & 0xFF;
 buffer[5] = sd_crc7_s((u32)databuff, 5);

 sd_com_write_s(databuff, 6);



void ReadSector(u16 *buff,u32 sector,u8 readnum)
{
 SDCommand(18, 0, sector << 9); 

 for (j = 0; j < readnum; j++)
   sd_data_read_s((u32)buff+j*512);

 SDCommand(12, 0, 0); 
 get_resp();
 send_clk(0x10);
}



get_resp:
 sd_com_read_s(r0 = ?, r1 = 6)


void WriteSector(uint16 * buffer, uint32 sector, uint8 writenum)
{
 register u16 i,j;
 u16 crc16[5];
 i=writenum;

 sectno<<=9;

 SDCommand(25,0,sector); 
 get_resp();
 send_clk(0x10); 

 for (j=0;j<i ; j++)
 {
   sd_crc16_s((u32)(u32)buff+j*512,512,(u32)crc16);
   sd_data_write_s((u32)buff+j*512,(u32)crc16);
   send_clk(0x10); 
 }
 SDCommand(12,0,0); 
 get_resp();
 send_clk(0x10);
 while((*(u16*)sd_dataadd &0x0100)==0);
}


MemoryCard_IsInserted:
 return (SC_SD_COMMAND & 0x0300 == 0);


NeoFlash (same as XG Flash v2 ?)

Unlock sequence:


 0x09555554:16 = 0xAAAA
 0x08AAAAAA:16 = 0x5555


Any read to the AD mux bus will disable the 'unlock'.

The following registers are on the compatible bus (0x0E00xxxx on the GBA, 0x0A00xxxx on the DS), and are thus 8 bits wide.

Save memory type register (0xFFF8)
7 6 5 4 3 2 1 0
0 1 1 1 1 Mode

Mode:

   * 000: 32 KB SRAM
   * 001: 64 KB Flash
   * 010: EEPROM
   * 101: 128 KB Flash (bankswitched with 0xB0)
   * dunno about other values 

Flash offset register (0xFFFE)
7 6 5 4 3 2 1 0
A23 A22 A21 A20 A19 A18 A17 A16

Save memory offset register (0xFFFF)
7 6 5 4 3 2 1 0
Fixed Shared SRAM EEPROM
1 H2 H1 H0 A15 A15 A14 A13

Notes:

   * The high address bits are shared for all 3 types of memory
   * EEPROM specific bits are only used for EEPROM
   * SRAM A15 should be zero when using Flash 

The flash chip (Intel Z412LA35A on the NeoFlash cart) can be erased/written after being unlocked. If anyone has chip names for Xg1 / Xg2 carts, I'd appreciate the information.
EZFlash III

The EZF-3 contains five chips:

   * 32 Mbit NOR flash (mapped in at boot-time)
   * 128 Mbit PSRAM
   * 256 Mbit NOR flash
   * 1 Gbit NAND flash
   * 2 Mbit SRAM 

Memory map in OS mode:

   * 0x08000000: 32 MBit NOR Flash
   * 0x08400000: 128 MBit PSRAM
   * 0x08800000: 64 MBit window into 256 MBit NOR flash (see ROM bank reg)
   * 0x08C00000: ?
   * 0x08FFE000: NAND flash interface 

Memory map in game mode:

   * 256 MBit NOR Flash
   * 128 MBit PSRAM
   * 32 MBit NOR Flash 

The offset into these for 0x08000000 is written to using the ROM page control register (e.g. if you wrote 0 for the page there, the 256 MBit of NOR would fill the cartridge bus, but writing 256 places the PSRAM in the space, ***I think***).


void SetRomPage(uint16 page) {
 *(u16 *)0x9FE0000 = 0xD200;
 *(u16 *)0x8000000 = 0x1500;
 *(u16 *)0x8020000 = 0xD200;
 *(u16 *)0x8040000 = 0x1500;

 *(u16 *)0x9880000 = page;

 *(u16 *)0x9FC0000 = 0x1500;
}


void SetRampage(uint16 page)
{
 *(u16 *)0x9FE0000 = 0xD200;
 *(u16 *)0x8000000 = 0x1500;
 *(u16 *)0x8020000 = 0xD200;
 *(u16 *)0x8040000 = 0x1500;

 *(u16 *)0x9C00000 = page;

 *(u16 *)0x9FC0000 = 0x1500;
}


void OpenWrite()
{
 *(u16 *)0x9FE0000 = 0xD200;
 *(u16 *)0x8000000 = 0x1500;
 *(u16 *)0x8020000 = 0xD200;
 *(u16 *)0x8040000 = 0x1500;

 *(u16 *)0x9C40000 = 0x1500;

 *(u16 *)0x9FC0000 = 0x1500;
}


void CloseWrite()
{
 *(u16 *)0x9FE0000 = 0xD200;
 *(u16 *)0x8000000 = 0x1500;
 *(u16 *)0x8020000 = 0xD200;
 *(u16 *)0x8040000 = 0x1500;

 *(u16 *)0x9C40000 = 0xD200;

 *(u16 *)0x9FC0000 = 0x1500;
}


void SetNandControl(uint16 control)
{
 *(u16 *)0x9FE0000 = 0xD200;
 *(u16 *)0x8000000 = 0x1500;
 *(u16 *)0x8020000 = 0xD200;
 *(u16 *)0x8040000 = 0x1500;

 *(u16 *)0x9400000 = control;

 *(u16 *)0x9fc0000 = 0x1500;
}



ROM page control register:
15 1: OS mode, 0: Game mode
14 Dunno
13..12 Which 64 Mbit bank of NOR appears at 0x09400000 .. 0x09C00000
11..9 Dunno, could be more page register
8..0 Page register (in 1 MBit chunks)

Bits 13 and 12 do not work in game mode.

NAND interface:

   * 0xFFFFF0: WRITE COMMAND
   * FFFFF0: WRITE ADDRESS
   * 0xFFE000 TO 0xFFEFFF: R/W DATA 

NAND control register format:
15..2 ?
1 0: 8 bit mode, 1: 16 bit mode
0 0: Disabled, 1: Enabled

Thanks to Davr and DarkFader for information on the EZF-3.

Thanks to pepsiman for the info on enabling SDRAM for M3 / G6 / Supercard.

Any information on the EZFA, F2A, and XgFlash 1 carts would be appreciated (and any others I'm not thinking of).



タグ:

+ タグ編集
  • タグ:

このサイトはreCAPTCHAによって保護されており、Googleの プライバシーポリシー利用規約 が適用されます。

最終更新:2007年06月18日 09:36
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。