Rather than continue to hijack superjoebob's thread, I'm splitting this off into a separate thread.
The issue: 1 - Writing the flash via the PC client can be "troublesome" - many people have problems with the USB timing out, and blocks randomly reporting as bad when trying to write games. The longer the game, the more likely a random bad block will crop up. 2 - Most people don't have the V5 or newer Myth needed to run SMS games from the SD card; they HAVE to be written to flash and run from there.
The solution: Writing the flash from the menu on the console. Avoid the PC client altogether. At least, that's what we're hoping.
This involves two carts: the Neo2-SD, and the Neo2-Pro. They are the carts that have game flash and an SD card interface. We wish to load the game from the SD card and burn it to flash.
Neo2-SD:
This cart has an ST M36DR432A chip for the menu flash and save ram, and two Intel 4050L0YTQ2 chips for the game flash and zip ram.
Neo2-Pro:
This cart has an ST M36DR432A chip for the menu flash and save ram, and two Intel 4455LLYBQ1 chips for the game flash and zip ram.
ST and Intel have slightly different NOR operations, so we need two sets of code to deal with writing menu flash versus writing game flash. I have successfully read the manufacturer and device IDs via CFI Query on both menu and game flash on the Neo2-SD. I'll check the Pro later.
NOR flash operations involve doing specific writes to specific locations, followed by more writes and reads. We have a datasheet for the M36DR432, but not the Intel chips. However, Intel chips all seem to use the same NOR operations, so I think we can get by with a datasheet for a similar chip from Intel.
M36DR432.pdf
Intel Flash datasheet
EDIT:
Datasheet on larger Intel Flash
I've tried reading the flash man/dev id on the Neo2-SD and Neo2-Pro on a V1, V4, and V5 Myth. The game flash (Intel memory) returns a proper ID on all carts for both the SD and Pro, however, the menu flash (ST memory) seems to not respond to commands on V1 and V4 carts. Only the V5 hardware seems to be able to do flash operations on the menu flash. I was thinking of having the info about what was written to the game flash saved to the SD card anyway.
Writing the flash on the NeoMyth cart
Moderator: BigEvilCorporation
-
- Very interested
- Posts: 2993
- Joined: Fri Aug 17, 2007 9:33 pm
If you look in EnumCry.ini (should be in your GBA menu source tree) there are game flash command strings in there, in the sections named [G_x].
They're encrypted with a really basic encryption scheme (you can find the decrypting function in Neos.cpp). These commands are then used e.g. in CN2Cartridge::GameRomWrite.
They're encrypted with a really basic encryption scheme (you can find the decrypting function in Neos.cpp). These commands are then used e.g. in CN2Cartridge::GameRomWrite.
-
- Very interested
- Posts: 2993
- Joined: Fri Aug 17, 2007 9:33 pm
Kinda stupid trying to encrypt them like that. I'll look at it more later when I want to look into the USB programming more. I think I have enough info right now for just writing the game flash from the console.
My thoughts are to have another option in the SD browser's options screen to write the current file to game flash. It will keep a list of entries in a file in the menu folder, and when you go to the flash browser, if there's a menu list on the SD, it'll use that rather than the menu entries in the menu flash.
My thoughts are to have another option in the SD browser's options screen to write the current file to game flash. It will keep a list of entries in a file in the menu folder, and when you go to the flash browser, if there's a menu list on the SD, it'll use that rather than the menu entries in the menu flash.
-
- Very interested
- Posts: 2993
- Joined: Fri Aug 17, 2007 9:33 pm
Wow, trying to use the N64 bus is a real pain. It's a word bus, like most other consoles of the period, but it is designed for bursts of words, not single accesses. That makes reading the flash IDs tough... not sure if I'll be able to write the flash on the N64 or not at this point. Here's the code to read the ids on the N64:
where
Note how the ST bus ops differ from the Intel bus ops. That DOES work, and I get the correct man/dev codes from the menu and game flash.
Now look at the MD code for the same thing:
where
Notice that the read/write code is more complex since you have to set a couple bank registers on the MD Myth, but other than that, the bus operations are simple - just read or write the word as needed. That's because the MD cart bus is a plain word bus that works around single cycles - no bursts or anything like that.
Code: Select all
u32 v;
_neo_asic_cmd(0x00E21500, 1); // GBA CARD WE ON !
_neo_asic_cmd(0x00372002, 0); // set cr = menu flash and write enabled
_neo_asic_cmd(0x00DA0044, 0); // set iosr = select menu flash
// NEO_IO = 0xFFFFFFFF; // 16 bit mode
// neo_sync_bus();
/* get menu flash ID */
_neo_asic_op(0x00000000);
_neo_asic_op(0x00000054) = 0x00000098; // ST CFI Query
_neo_asic_op(0x00000000);
v = _neo_asic_op(0x00000000);
ptr->MenuMan = v >> 16;
ptr->MenuDev = v & 0xFFFF;
_neo_asic_op(0x00000000);
_neo_asic_op(0x00000000) = 0x000000F0; // ST Read Array/Reset
_neo_asic_op(0x00000000);
_neo_asic_cmd(0x00372202, 0); // set cr = game flash and write enabled
_neo_asic_cmd(0x00DAAE44, 0); // set iosr = select game flash
// NEO_IO = 0xFFFFFFFF; // 16 bit mode
// neo_sync_bus();
/* get game flash ID */
_neo_asic_op(0x00000000);
_neo_asic_wop(0x00000000) = 0x0098; // Intel CFI Query
_neo_asic_op(0x00000000);
ptr->GameMan = _neo_asic_wop(0x00000000);
_neo_asic_op(0x00000000);
ptr->GameDev = _neo_asic_wop(0x00000001);
_neo_asic_op(0x00000000);
_neo_asic_wop(0x00000000) = 0x00FF; // Intel Read Array/Reset
_neo_asic_op(0x00000000);
_neo_asic_cmd(0x00E2D200, 0); // GBA CARD WE OFF !
Code: Select all
#define _neo_asic_op(cmd) *(vu32 *)(0xB2000000 | (cmd<<1))
#define _neo_asic_wop(cmd) *(vu16 *)(0xB2000000 | (cmd<<1))
Now look at the MD code for the same thing:
Code: Select all
move.l #0x00E21500,d0
bsr _neo_asic_cmd /* set flash & psram write enable */
move.l #0x00372003,d0
bsr _neo_asic_cmd /* set cr = flash & psram we, select menu flash */
/* get menu flash ID */
move.l #0x00000055,d0
move.w #0x0098,d1 /* ST CFI Query */
bsr _neo_asic_wop
moveq #0,d0
bsr _neo_asic_op
ror.w #8,d0
move.w d0,8(a2) /* menu flash man id */
moveq #1,d0
bsr _neo_asic_op
ror.w #8,d0
move.w d0,10(a2) /* menu flash dev id */
move.l #0x00000000,d0
move.w #0x00F0,d1 /* ST Read Array/Reset */
bsr _neo_asic_wop
move.l #0x00372203,d0
bsr _neo_asic_cmd /* set cr = flash & psram we, select game flash */
/* get game flash ID */
move.l #0x00000000,d0
move.w #0x0098,d1 /* Intel CFI Query */
bsr _neo_asic_wop
moveq #0,d0
bsr _neo_asic_op
ror.w #8,d0
move.w d0,12(a2) /* game flash man id */
moveq #1,d0
bsr _neo_asic_op
ror.w #8,d0
move.w d0,14(a2) /* game flash dev id */
move.l #0x00000000,d0
move.w #0x00FF,d1 /* Intel Read Array/Reset */
bsr _neo_asic_wop
move.l #0x00E2D200,d0
bsr _neo_asic_cmd /* flash-psram write disable */
Code: Select all
| do a Neo Flash ASIC operation
| entry: d0 = Neo Flash ASIC operation
| b23-16 = addr, b15-b0 = value
| a1 = hardware base (0xA10000)
| exit: d0 = result (usually dummy read)
_neo_asic_op:
move.l d0,d1
rol.l #8,d1
andi.w #0x000F,d1 /* keep b27-24 */
move.w d1,GBAC_HIO(a1) /* set high bank select reg (holds flash space A27-A24) */
rol.l #8,d1
andi.w #0x00F8,d1 /* keep b23-19, b18-16 = 0 */
move.w d1,GBAC_LIO(a1) /* set low bank select reg (holds flash space A23-A16) */
andi.l #0x0007FFFF,d0 /* b23-19 = 0, keep b18-b0 */
add.l d0,d0 /* 68000 A19-A1 = b18-b0 */
movea.l d0,a0
move.w (a0),d0 /* access the flash space to do the operation */
rts
| do a Neo Flash ASIC write operation
| entry: d0 = address
| d1 = write data
| a1 = hardware base (0xA10000)
_neo_asic_wop:
movea.l d1,a0 /* save write data */
move.l d0,d1
rol.l #8,d1
andi.w #0x000F,d1 /* keep b27-24 */
move.w d1,GBAC_HIO(a1) /* set high bank select reg (holds flash space A27-A24) */
rol.l #8,d1
andi.w #0x00F8,d1 /* keep b23-19, b18-16 = 0 */
move.w d1,GBAC_LIO(a1) /* set low bank select reg (holds flash space A23-A16) */
move.l a0,d1 /* restore write data */
andi.l #0x0007FFFF,d0 /* b23-19 = 0, keep b18-b0 */
add.l d0,d0 /* 68000 A19-A1 = b18-b0 */
movea.l d0,a0
move.w d1,(a0) /* write access to flash space */
rts