//Dev.ID Size Blocks Manufacturer //====== ===== ======== ============ //0xd4bf 64KB 16x4096 SST //0x1cc2 64KB 16x4096 Macronix //0x1b32 64KB 16x4096 Panasonic //0x3d1f 64KB 512x 128 Atmel //0x1362 128KB 32x4096 Sanyo //0x09c2 128KB 32x4096 Macronix auto Cartridge::FLASH::read(uint16 addr) -> uint8 { if(idmode) { if(addr == 0x0000) return id >> 0; if(addr == 0x0001) return id >> 8; return 0u; } return data[bank << 16 | addr]; } auto Cartridge::FLASH::write(uint16 addr, uint8 byte) -> void { if(bankselect) { bankselect = false; //bank select is only applicable on 128KB chips if(addr == 0x0000) bank = byte & (size > 64 * 1024); return; } if(writeselect) { //Atmel writes 128 bytes per command; all others write 1 byte per command if(id != 0x3d1f || (addr & 0x007f) == 0x007f) writeselect = false; data[bank << 16 | addr] = byte; return; } if(byte == 0xaa && addr == 0x5555) { unlockhi = true; return; } if(byte == 0x55 && addr == 0x2aaa) { unlocklo = true; return; } if(unlockhi && unlocklo) { unlockhi = false; unlocklo = false; if(byte == 0x10 && addr == 0x5555) { if(erasemode) { erasemode = false; for(uint n : range(size)) data[n] = 0xff; } } if(byte == 0x30 && (addr & 0x0fff) == 0x0000) { //command only valid for non-Atmel chips if(erasemode && id != 0x3d1f) { erasemode = false; uint offset = bank << 16 | (addr & ~4095); for(uint n : range(4096)) data[offset++] = 0xff; } } if(byte == 0x80 && addr == 0x5555) { erasemode = true; } if(byte == 0x90 && addr == 0x5555) { idmode = true; } if(byte == 0xa0 && addr == 0x5555) { writeselect = true; } if(byte == 0xb0 && addr == 0x5555) { bankselect = true; } if(byte == 0xf0 && addr == 0x5555) { idmode = false; } } } auto Cartridge::FLASH::power() -> void { unlockhi = false; unlocklo = false; idmode = false; bankselect = false; writeselect = false; bank = 0; } auto Cartridge::FLASH::serialize(serializer& s) -> void { s.array(data, size); s.integer(size); s.integer(id); s.integer(unlockhi); s.integer(unlocklo); s.integer(idmode); s.integer(erasemode); s.integer(bankselect); s.integer(writeselect); s.integer(bank); }