diff --git a/src/common/file.cpp b/src/common/file.cpp index 0a790a6..14e8f60 100644 --- a/src/common/file.cpp +++ b/src/common/file.cpp @@ -206,49 +206,50 @@ Provider::~Provider(void) { } size_t Provider::loadData(util::Data &output, const char *path) { - auto file = openFile(path, READ); + auto _file = openFile(path, READ); - if (!file) + if (!_file) return 0; //assert(file->length <= SIZE_MAX); - if (!output.allocate(size_t(file->length))) { - delete file; + if (!output.allocate(size_t(_file->length))) { + _file->close(); + delete _file; return 0; } - size_t actualLength = file->read(output.ptr, output.length); - file->close(); + size_t actualLength = _file->read(output.ptr, output.length); - delete file; + _file->close(); + delete _file; return actualLength; } size_t Provider::loadData(void *output, size_t length, const char *path) { - auto file = openFile(path, READ); + auto _file = openFile(path, READ); - if (!file) + if (!_file) return 0; //assert(file->length >= length); - size_t actualLength = file->read(output, length); - file->close(); + size_t actualLength = _file->read(output, length); - delete file; + _file->close(); + delete _file; return actualLength; } size_t Provider::saveData(const void *input, size_t length, const char *path) { #ifdef ENABLE_FILE_WRITING - auto file = openFile(path, WRITE | ALLOW_CREATE); + auto _file = openFile(path, WRITE | ALLOW_CREATE); - if (!file) + if (!_file) return 0; - size_t actualLength = file->write(input, length); - file->close(); + size_t actualLength = _file->write(input, length); - delete file; + _file->close(); + delete _file; return actualLength; #else return 0; @@ -511,17 +512,17 @@ File *FATProvider::openFile(const char *path, uint32_t flags) { if (!_selectDrive()) return nullptr; - auto file = new FATFile(); - auto error = f_open(&(file->_fd), path, uint8_t(flags)); + auto _file = new FATFile(); + auto error = f_open(&(_file->_fd), path, uint8_t(flags)); if (error) { LOG("%s, drive=%s", _FATFS_ERROR_NAMES[error], _drive); - delete file; + delete _file; return nullptr; } - file->length = f_size(&(file->_fd)); - return file; + _file->length = f_size(&(_file->_fd)); + return _file; } static constexpr uint32_t _ZIP_FLAGS = 0 diff --git a/src/common/ide.cpp b/src/common/ide.cpp index b4bccf2..fdd7d2b 100644 --- a/src/common/ide.cpp +++ b/src/common/ide.cpp @@ -45,6 +45,7 @@ static void _copyString(char *output, const uint16_t *input, size_t length) { output += length; input += length / 2; + *output = 0; for (; length; length -= 2) { uint16_t packed = *(--input); @@ -264,9 +265,9 @@ DeviceError Device::enumerate(void) { flags |= DEVICE_HAS_FLUSH; } - _copyString(model, block.model, sizeof(model)); - _copyString(revision, block.revision, sizeof(revision)); - _copyString(serialNumber, block.serialNumber, sizeof(serialNumber)); + _copyString(model, block.model, sizeof(block.model)); + _copyString(revision, block.revision, sizeof(block.revision)); + _copyString(serialNumber, block.serialNumber, sizeof(block.serialNumber)); LOG("drive %d: %s", (flags / DEVICE_SECONDARY) & 1, model); diff --git a/src/common/ide.hpp b/src/common/ide.hpp index 5f09ea3..6465ea2 100644 --- a/src/common/ide.hpp +++ b/src/common/ide.hpp @@ -331,7 +331,7 @@ private: public: uint32_t flags; - char model[40], revision[8], serialNumber[20]; + char model[41], revision[9], serialNumber[21]; uint64_t capacity; inline Device(uint32_t flags) diff --git a/src/common/rom.cpp b/src/common/rom.cpp index f787bbf..4a9b45a 100644 --- a/src/common/rom.cpp +++ b/src/common/rom.cpp @@ -177,25 +177,24 @@ enum JEDECCommand : uint16_t { _JEDEC_ERASE_SECTOR = 0x3030 }; -enum SharpCommand : uint16_t { - _SHARP_RESET = 0xffff, - _SHARP_GET_ID = 0x9090, - _SHARP_WRITE_BYTE = 0x4040, - _SHARP_ERASE_SECTOR1 = 0x2020, - _SHARP_ERASE_SECTOR2 = 0xd0d0, - _SHARP_GET_STATUS = 0x7070, - _SHARP_CLEAR_STATUS = 0x5050, - _SHARP_SUSPEND = 0xb0b0, - _SHARP_RESUME = 0xd0d0 +enum IntelCommand : uint16_t { + _INTEL_RESET = 0xffff, + _INTEL_GET_ID = 0x9090, + _INTEL_WRITE_BYTE = 0x4040, + _INTEL_ERASE_SECTOR1 = 0x2020, + _INTEL_ERASE_SECTOR2 = 0xd0d0, + _INTEL_GET_STATUS = 0x7070, + _INTEL_CLEAR_STATUS = 0x5050, + _INTEL_SUSPEND = 0xb0b0, + _INTEL_RESUME = 0xd0d0 }; enum FlashIdentifier : uint16_t { - // NOTE: the MBM29F017A datasheet incorrectly lists the device ID as 0xad in - // some places. The chip behaves pretty much identically to the MBM29F016A. - _ID_MBM29F016A = 0x04 | (0xad << 8), - _ID_MBM29F017A = 0x04 | (0x3d << 8), - _ID_FUJITSU_UNKNOWN = 0x04 | (0xa4 << 8), - _ID_LH28F016S = 0x89 | (0xaa << 8) + _ID_MBM29F016A = 0x04 | (0xad << 8), + _ID_MBM29F017A = 0x04 | (0x3d << 8), + _ID_MBM29F040A = 0x04 | (0xa4 << 8), + _ID_28F016S5 = 0x89 | (0xaa << 8), + _ID_28F640J5 = 0x89 | (0x15 << 8) }; bool FlashRegion::hasBootExecutable(void) const { @@ -234,11 +233,11 @@ uint32_t FlashRegion::getJEDECID(void) const { auto _ptr = reinterpret_cast(ptr); - _ptr[0x000] = _SHARP_RESET; - _ptr[0x000] = _SHARP_RESET; + _ptr[0x000] = _INTEL_RESET; + _ptr[0x000] = _INTEL_RESET; _ptr[0x555] = _JEDEC_HANDSHAKE1; _ptr[0x2aa] = _JEDEC_HANDSHAKE2; - _ptr[0x555] = _JEDEC_GET_ID; // Same as _SHARP_GET_ID + _ptr[0x555] = _JEDEC_GET_ID; // Same as _INTEL_GET_ID return _ptr[0] | (_ptr[1] << 16); } @@ -254,25 +253,36 @@ Driver *FlashRegion::newDriver(void) const { uint16_t high = ((id >> 8) & 0xff) | ((id >> 16) & 0xff00); LOG("low=0x%04x, high=0x%04x", low, high); - if (low != high) { - // TODO: implement single-chip (16-bit) flash support - return new Driver(*this); - } else { + if (low == high) { + // Two 8-bit chips for each bank switch (low) { case _ID_MBM29F016A: case _ID_MBM29F017A: + // The MBM29F017A datasheet incorrectly lists the device ID as + // 0xad rather than 0x3d in some places. The chip behaves pretty + // much identically to the MBM29F016A. return new MBM29F016ADriver(*this); - case _ID_FUJITSU_UNKNOWN: - return new FujitsuUnknownDriver(*this); + case _ID_MBM29F040A: + return new MBM29F040ADriver(*this); - case _ID_LH28F016S: - return new LH28F016SDriver(*this); - - default: - return new Driver(*this); + case _ID_28F016S5: + // The chip used by Konami is actually the Sharp LH28F016S, + // which uses the same ID and command set as the Intel 28F016S5. + return new Intel28F016S5Driver(*this); + } + //} else if (!high || (high == 0xff)) { + } else { + // Single 16-bit chip for each bank + switch (low) { + case _ID_28F640J5: + // Found in "Centennial" branded flash cards. Not supported by + // Konami's drivers. + return new Intel28F640J5Driver(*this); } } + + return new Driver(*this); } const BIOSRegion bios; @@ -350,7 +360,7 @@ const ChipSize &RTCDriver::getChipSize(void) const { return _RTC_CHIP_SIZE; } -/* Fujitsu MBM29F016A driver */ +/* Fujitsu MBM29F016A/017A driver */ enum FujitsuStatusFlag : uint16_t { _FUJITSU_STATUS_ERASE_TOGGLE = 0x101 << 2, @@ -440,13 +450,12 @@ const ChipSize &MBM29F016ADriver::getChipSize(void) const { return _STANDARD_CHIP_SIZE; } -/* Unknown Fujitsu chip driver */ +/* Fujitsu MBM29F040A driver */ // Konami's drivers handle this chip pretty much identically to the MBM29F016A, -// but using 0x5555/0x2aaa as command addresses instead of 0x555/0x2aa. This -// could actually be a >2 MB chip. +// but using 0x5555/0x2aaa as command addresses instead of 0x555/0x2aa. -void FujitsuUnknownDriver::write(uint32_t offset, uint16_t value) { +void MBM29F040ADriver::write(uint32_t offset, uint16_t value) { volatile uint16_t *ptr = _region.getRawPtr(offset, true); offset = (offset % FLASH_BANK_LENGTH) / 2; @@ -457,7 +466,7 @@ void FujitsuUnknownDriver::write(uint32_t offset, uint16_t value) { ptr[offset] = value; } -void FujitsuUnknownDriver::eraseSector(uint32_t offset) { +void MBM29F040ADriver::eraseSector(uint32_t offset) { volatile uint16_t *ptr = _region.getRawPtr(offset, true); offset = (offset % FLASH_BANK_LENGTH) / 2; @@ -470,7 +479,7 @@ void FujitsuUnknownDriver::eraseSector(uint32_t offset) { ptr[offset] = _JEDEC_ERASE_SECTOR; } -void FujitsuUnknownDriver::eraseChip(uint32_t offset) { +void MBM29F040ADriver::eraseChip(uint32_t offset) { volatile uint16_t *ptr = _region.getRawPtr(offset, true); ptr[0x0005] = _JEDEC_RESET; @@ -482,42 +491,42 @@ void FujitsuUnknownDriver::eraseChip(uint32_t offset) { ptr[0x5555] = _JEDEC_ERASE_CHIP; } -/* Sharp LH28F016S driver */ +/* Intel 28F016S5 (Sharp LH28F016S) driver */ -enum SharpStatusFlag : uint16_t { - _SHARP_STATUS_DPS = 0x101 << 1, - _SHARP_STATUS_BWSS = 0x101 << 2, - _SHARP_STATUS_VPPS = 0x101 << 3, - _SHARP_STATUS_BWSLBS = 0x101 << 4, - _SHARP_STATUS_ECLBS = 0x101 << 5, - _SHARP_STATUS_ESS = 0x101 << 6, - _SHARP_STATUS_WSMS = 0x101 << 7 +enum IntelStatusFlag : uint16_t { + _INTEL_STATUS_DPS = 0x101 << 1, + _INTEL_STATUS_BWSS = 0x101 << 2, + _INTEL_STATUS_VPPS = 0x101 << 3, + _INTEL_STATUS_BWSLBS = 0x101 << 4, + _INTEL_STATUS_ECLBS = 0x101 << 5, + _INTEL_STATUS_ESS = 0x101 << 6, + _INTEL_STATUS_WSMS = 0x101 << 7 }; -DriverError LH28F016SDriver::_flush(uint32_t offset, int timeout) { +DriverError Intel28F016S5Driver::_flush(uint32_t offset, int timeout) { volatile uint16_t *ptr = _region.getRawPtr(offset); // Not required as all write/erase commands already put the chip into status // reading mode. - //*ptr = _SHARP_GET_STATUS; + //*ptr = _INTEL_GET_STATUS; for (; timeout > 0; timeout--) { auto status = *ptr; - if (status & (_SHARP_STATUS_DPS | _SHARP_STATUS_VPPS)) { - *ptr = _SHARP_CLEAR_STATUS; + if (status & (_INTEL_STATUS_DPS | _INTEL_STATUS_VPPS)) { + *ptr = _INTEL_CLEAR_STATUS; LOG("locked @ 0x%08x, stat=0x%04x", offset, status); return WRITE_PROTECTED; } - if (status & (_SHARP_STATUS_BWSLBS | _SHARP_STATUS_ECLBS)) { - *ptr = _SHARP_CLEAR_STATUS; + if (status & (_INTEL_STATUS_BWSLBS | _INTEL_STATUS_ECLBS)) { + *ptr = _INTEL_CLEAR_STATUS; LOG("error @ 0x%08x, stat=0x%04x", offset, status); return CHIP_ERROR; } - if (status & _SHARP_STATUS_WSMS) + if (status & _INTEL_STATUS_WSMS) return NO_ERROR; delayMicroseconds(1); @@ -527,37 +536,48 @@ DriverError LH28F016SDriver::_flush(uint32_t offset, int timeout) { return CHIP_TIMEOUT; } -void LH28F016SDriver::write(uint32_t offset, uint16_t value) { +void Intel28F016S5Driver::write(uint32_t offset, uint16_t value) { volatile uint16_t *ptr = _region.getRawPtr(offset); - *ptr = _SHARP_RESET; - *ptr = _SHARP_CLEAR_STATUS; - *ptr = _SHARP_WRITE_BYTE; + *ptr = _INTEL_RESET; + *ptr = _INTEL_CLEAR_STATUS; + *ptr = _INTEL_WRITE_BYTE; *ptr = value; } -void LH28F016SDriver::eraseSector(uint32_t offset) { +void Intel28F016S5Driver::eraseSector(uint32_t offset) { volatile uint16_t *ptr = _region.getRawPtr(offset); - *ptr = _SHARP_RESET; - *ptr = _SHARP_ERASE_SECTOR1; - *ptr = _SHARP_ERASE_SECTOR2; + *ptr = _INTEL_RESET; + *ptr = _INTEL_ERASE_SECTOR1; + *ptr = _INTEL_ERASE_SECTOR2; } -DriverError LH28F016SDriver::flushWrite( +DriverError Intel28F016S5Driver::flushWrite( uint32_t offset, uint16_t value ) { return _flush(offset, _FLASH_WRITE_TIMEOUT); } -DriverError LH28F016SDriver::flushErase(uint32_t offset) { +DriverError Intel28F016S5Driver::flushErase(uint32_t offset) { return _flush(offset, _FLASH_ERASE_TIMEOUT); } -const ChipSize &LH28F016SDriver::getChipSize(void) const { +const ChipSize &Intel28F016S5Driver::getChipSize(void) const { return _STANDARD_CHIP_SIZE; } +/* Intel 28F640J5 driver */ + +static const ChipSize _28F640J5_CHIP_SIZE{ + .chipLength = 0x800000, + .eraseSectorLength = 0x20000 +}; + +const ChipSize &Intel28F640J5Driver::getChipSize(void) const { + return _28F640J5_CHIP_SIZE; +} + /* BIOS ROM headers */ static const ShellInfo _SHELL_VERSIONS[]{ diff --git a/src/common/rom.hpp b/src/common/rom.hpp index fd40b04..5278916 100644 --- a/src/common/rom.hpp +++ b/src/common/rom.hpp @@ -144,9 +144,9 @@ public: const ChipSize &getChipSize(void) const; }; -class FujitsuUnknownDriver : public MBM29F016ADriver { +class MBM29F040ADriver : public MBM29F016ADriver { public: - inline FujitsuUnknownDriver(const FlashRegion ®ion) + inline MBM29F040ADriver(const FlashRegion ®ion) : MBM29F016ADriver(region) {} void write(uint32_t offset, uint16_t value); @@ -154,12 +154,12 @@ public: void eraseChip(uint32_t offset); }; -class LH28F016SDriver : public Driver { +class Intel28F016S5Driver : public Driver { private: DriverError _flush(uint32_t offset, int timeout); public: - inline LH28F016SDriver(const FlashRegion ®ion) + inline Intel28F016S5Driver(const FlashRegion ®ion) : Driver(region) {} void write(uint32_t offset, uint16_t value); @@ -169,6 +169,14 @@ public: const ChipSize &getChipSize(void) const; }; +class Intel28F640J5Driver : public Intel28F016S5Driver { +public: + inline Intel28F640J5Driver(const FlashRegion ®ion) + : Intel28F016S5Driver(region) {} + + const ChipSize &getChipSize(void) const; +}; + extern const char *const DRIVER_ERROR_NAMES[]; static inline const char *getErrorString(DriverError error) { diff --git a/src/main/app/app.cpp b/src/main/app/app.cpp index 9e207be..c8cbaa6 100644 --- a/src/main/app/app.cpp +++ b/src/main/app/app.cpp @@ -73,8 +73,10 @@ App::~App(void) { _unloadCartData(); //_resourceProvider.close(); - if (_resourceFile) + if (_resourceFile) { + _resourceFile->close(); delete _resourceFile; + } //_fileProvider.close(); diff --git a/src/main/app/cartworkers.cpp b/src/main/app/cartworkers.cpp index 61b98e4..13b8957 100644 --- a/src/main/app/cartworkers.cpp +++ b/src/main/app/cartworkers.cpp @@ -291,6 +291,7 @@ bool App::_cartRestoreWorker(void) { if (length != newDump.getDumpLength()) goto _fileError; + _file->close(); delete _file; if (_dump.chipType != newDump.chipType) { @@ -336,6 +337,7 @@ bool App::_cartRestoreWorker(void) { return _cartUnlockWorker(); _fileError: + _file->close(); delete _file; _fileOpenError: diff --git a/src/main/app/miscworkers.cpp b/src/main/app/miscworkers.cpp index 87e3b3b..5f300ac 100644 --- a/src/main/app/miscworkers.cpp +++ b/src/main/app/miscworkers.cpp @@ -106,6 +106,7 @@ bool App::_executableWorker(void) { goto _validFile; } + _file->close(); delete _file; _fileOpenError: @@ -117,6 +118,7 @@ _fileOpenError: return false; _validFile: + _file->close(); delete _file; uintptr_t executableEnd, stackTop; @@ -169,8 +171,10 @@ _validFile: _unloadCartData(); _resourceProvider.close(); - if (_resourceFile) + if (_resourceFile) { + _resourceFile->close(); delete _resourceFile; + } _fileProvider.close(); @@ -240,8 +244,10 @@ bool App::_rebootWorker(void) { _unloadCartData(); _resourceProvider.close(); - if (_resourceFile) + if (_resourceFile) { + _resourceFile->close(); delete _resourceFile; + } _fileProvider.close(); _workerStatus.setStatus(WORKER_REBOOT); diff --git a/src/main/app/modals.cpp b/src/main/app/modals.cpp index 8d13d59..85cf50c 100644 --- a/src/main/app/modals.cpp +++ b/src/main/app/modals.cpp @@ -206,6 +206,7 @@ int FilePickerScreen::loadDirectory(ui::Context &ctx, const char *path) { _numFiles++; } + directory->close(); delete directory; _activeItem = 0; @@ -236,6 +237,7 @@ int FilePickerScreen::loadDirectory(ui::Context &ctx, const char *path) { __builtin_memcpy(ptr, &info, sizeof(file::FileInfo)); } + directory->close(); delete directory; __builtin_strncpy(_currentPath, path, sizeof(_currentPath)); diff --git a/src/main/app/romworkers.cpp b/src/main/app/romworkers.cpp index 91d6cef..25bafab 100644 --- a/src/main/app/romworkers.cpp +++ b/src/main/app/romworkers.cpp @@ -113,6 +113,7 @@ bool App::_romDumpWorker(void) { entry.region.read(buffer, offset, chunkLength); if (_file->write(buffer, chunkLength) < chunkLength) { + _file->close(); delete _file; delete[] buffer; @@ -122,6 +123,7 @@ bool App::_romDumpWorker(void) { offset += chunkLength; } + _file->close(); delete _file; delete[] buffer; @@ -209,6 +211,7 @@ bool App::_romRestoreWorker(void) { } } + _file->close(); delete _file; delete[] buffer; delete driver; @@ -234,6 +237,7 @@ _fileError: return false; _flashError: + _file->close(); delete _file; delete[] buffer; delete driver;