I worked on some of the XROM software during its initial release, and still have my prototype XROM board. This is the C source I wrote for accessing XROM flash.
Code:
inline void XROMUnlockSequence() {
*(vu16*)0x08001554 = 0xAAAA;
*(vu16*)0x08000AAA = 0x5555;
}
void xrom_erase(u32 addr, u32 size) {
int i = 0;
while (i < size) {
*(vu16*)0x09000000 = 0x8000;
*(vu16*)0x09000000 = (0x8400 | (addr >> 17));
XROMUnlockSequence();
*(vu16*)0x08001554 = 0x8080;
XROMUnlockSequence();
*(vu16*)0x08000000 = 0x3030;
while ((*(vu16*)0x08000000 & 0x8080) != 0x8080);
i += (128 * 1024);
addr += (128 * 1024);
}
}
void xrom_write(u32 addr, u16 *buffer, u32 size) {
int i = 0, j;
while (i < size) {
*(vu16*)0x09000000 = 0x8000;
*(vu16*)0x09000000 = (0x8400 | (addr >> 17));
XROMUnlockSequence();
*(vu16*)(0x08000000 | (addr & 0x0001FFFF)) = 0x2525;
*(vu16*)(0x08000000 | (addr & 0x0001FFFF)) = 0x1F1F;
for (j = 0; j < 32; j++) {
*(vu16*)(0x08000000 | (addr & 0x0001FFFF) | (j << 1)) = buffer[(i >> 1) + j];
}
*(vu16*)0x08000000 = 0x2929;
while ((*(vu16*)(0x08000000 | (addr & 0x0001FFFF) | (31 << 1)) & 0x8080) != (buffer[(i >> 1) + 31] & 0x8080));
i += 64;
addr += 64;
}
}
Usage is fairly simple, just erase as much as you need with xrom_erase(). (Block size is exactly 256KB, so your erases will be aligned to 256KB blocks.) Then you may begin writing your buffer to flash with xrom_write(). The 'addr' input argument to both functions is a relative address, NOT absolute. In other words, you will pass 0x00000000 as the first address, not 0x08000000.
This code can be converted to ARM assembly and run that way. Some problems to watch for:
1) XROM has two 256mbit AMD NOR flash chips. They are rather slow, and will take a few minutes to complete a full erase/write cycle. (As with all NOR flash chips, you must erase before you will be able to write.)
2) AR's code engine runs on ARM7, which is only half as fast as the ARM9. The write cycle will especially be slow if you use something like Kenobi's ASM hack on the code engine.
3) If you want to use the ARM9 instead for faster writing, you will have to first patch the ARM9 executable in some way to get the ASM running, then you must enable ARM9 access to the GBA bus using the 16-bit I/O register at 0x04000304. (ExMem Control) Then you may finally begin erasing the flash, and finally writing.