mirror of
https://github.com/spicyjpeg/573in1.git
synced 2025-01-22 11:43:39 +01:00
Fix IDE and file closing bugs
This commit is contained in:
parent
e836f665f4
commit
80be8fdd0e
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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<volatile uint16_t *>(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[]{
|
||||
|
@ -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) {
|
||||
|
@ -73,8 +73,10 @@ App::~App(void) {
|
||||
_unloadCartData();
|
||||
//_resourceProvider.close();
|
||||
|
||||
if (_resourceFile)
|
||||
if (_resourceFile) {
|
||||
_resourceFile->close();
|
||||
delete _resourceFile;
|
||||
}
|
||||
|
||||
//_fileProvider.close();
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user