mirror of
https://github.com/spicyjpeg/573in1.git
synced 2025-01-22 19:52:05 +01:00
Bump to 0.4.2, parallelize flash writing, minor tweaks
This commit is contained in:
parent
d85582d9b5
commit
1e79613029
@ -6,7 +6,7 @@ set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_LIST_DIR}/cmake/toolchain.cmake")
|
|||||||
project(
|
project(
|
||||||
cart_tool_private
|
cart_tool_private
|
||||||
LANGUAGES C CXX ASM
|
LANGUAGES C CXX ASM
|
||||||
VERSION 0.4.1
|
VERSION 0.4.2
|
||||||
DESCRIPTION "Konami System 573 security cartridge tool"
|
DESCRIPTION "Konami System 573 security cartridge tool"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -354,7 +354,7 @@ size_t Provider::saveVRAMBMP(gpu::RectWH &rect, const char *path) {
|
|||||||
size_t length = _file->write(&header, sizeof(header));
|
size_t length = _file->write(&header, sizeof(header));
|
||||||
util::Data buffer;
|
util::Data buffer;
|
||||||
|
|
||||||
if (buffer.allocate(rect.w * 2 + 32)) {
|
if (buffer.allocate<uint16_t>(rect.w + 32)) {
|
||||||
// Read the image from VRAM one line at a time from the bottom up, as
|
// Read the image from VRAM one line at a time from the bottom up, as
|
||||||
// the BMP format stores lines in reversed order.
|
// the BMP format stores lines in reversed order.
|
||||||
gpu::RectWH slice;
|
gpu::RectWH slice;
|
||||||
|
@ -18,7 +18,7 @@ void init(void) {
|
|||||||
| SYS573_MISC_OUT_ADC_MOSI
|
| SYS573_MISC_OUT_ADC_MOSI
|
||||||
| SYS573_MISC_OUT_ADC_CS
|
| SYS573_MISC_OUT_ADC_CS
|
||||||
| SYS573_MISC_OUT_ADC_SCK
|
| SYS573_MISC_OUT_ADC_SCK
|
||||||
| SYS573_MISC_OUT_JVS_STAT;
|
| SYS573_MISC_OUT_JVS_RESET;
|
||||||
|
|
||||||
BIU_DEV0_ADDR = DEV0_BASE & 0x1fffffff;
|
BIU_DEV0_ADDR = DEV0_BASE & 0x1fffffff;
|
||||||
BIU_DEV0_CTRL = 0
|
BIU_DEV0_CTRL = 0
|
||||||
@ -204,13 +204,15 @@ bool loadRawBitstream(const uint8_t *data, size_t length) {
|
|||||||
for (int i = 3; i; i--) {
|
for (int i = 3; i; i--) {
|
||||||
SYS573D_CPLD_UNK_RESET = 0;
|
SYS573D_CPLD_UNK_RESET = 0;
|
||||||
|
|
||||||
SYS573D_CPLD_CTRL = SYS573D_CPLD_CTRL_UNK4;
|
SYS573D_CPLD_CTRL = SYS573D_CPLD_CTRL_UNKNOWN;
|
||||||
SYS573D_CPLD_CTRL = SYS573D_CPLD_CTRL_UNK3 | SYS573D_CPLD_CTRL_UNK4;
|
|
||||||
SYS573D_CPLD_CTRL = 0
|
SYS573D_CPLD_CTRL = 0
|
||||||
| SYS573D_CPLD_CTRL_UNK1
|
| SYS573D_CPLD_CTRL_PROGRAM
|
||||||
| SYS573D_CPLD_CTRL_UNK2
|
| SYS573D_CPLD_CTRL_UNKNOWN;
|
||||||
| SYS573D_CPLD_CTRL_UNK3
|
SYS573D_CPLD_CTRL = 0
|
||||||
| SYS573D_CPLD_CTRL_UNK4;
|
| SYS573D_CPLD_CTRL_INIT
|
||||||
|
| SYS573D_CPLD_CTRL_DONE
|
||||||
|
| SYS573D_CPLD_CTRL_PROGRAM
|
||||||
|
| SYS573D_CPLD_CTRL_UNKNOWN;
|
||||||
delayMicroseconds(5000);
|
delayMicroseconds(5000);
|
||||||
|
|
||||||
if (!(SYS573D_CPLD_STAT & SYS573D_CPLD_STAT_INIT))
|
if (!(SYS573D_CPLD_STAT & SYS573D_CPLD_STAT_INIT))
|
||||||
|
@ -141,11 +141,10 @@ static inline void setMiscOutput(MiscOutputPin pin, bool value) {
|
|||||||
|
|
||||||
/* Digital I/O board driver */
|
/* Digital I/O board driver */
|
||||||
|
|
||||||
// TODO: these do not seem to actually be LDC and HDC...
|
|
||||||
static inline bool isDigitalIOPresent(void) {
|
static inline bool isDigitalIOPresent(void) {
|
||||||
return (
|
return (
|
||||||
(SYS573D_CPLD_STAT & (SYS573D_CPLD_STAT_LDC | SYS573D_CPLD_STAT_HDC))
|
(SYS573D_CPLD_STAT & (SYS573D_CPLD_STAT_ID1 | SYS573D_CPLD_STAT_ID2)) ==
|
||||||
== SYS573D_CPLD_STAT_HDC
|
SYS573D_CPLD_STAT_ID1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,26 @@ Hash hash(const uint8_t *data, size_t length) {
|
|||||||
|
|
||||||
/* Date and time class */
|
/* Date and time class */
|
||||||
|
|
||||||
|
bool Date::isValid(void) const {
|
||||||
|
if ((hour > 23) || (minute > 59) || (second > 59))
|
||||||
|
return false;
|
||||||
|
if ((month < 1) || (month > 12))
|
||||||
|
return false;
|
||||||
|
if ((day < 1) || (day > getMonthDayCount()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Date::isLeapYear(void) const {
|
||||||
|
if (year % 4)
|
||||||
|
return false;
|
||||||
|
if (!(year % 100) && (year % 400))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int Date::getDayOfWeek(void) const {
|
int Date::getDayOfWeek(void) const {
|
||||||
// See https://datatracker.ietf.org/doc/html/rfc3339#appendix-B
|
// See https://datatracker.ietf.org/doc/html/rfc3339#appendix-B
|
||||||
int _year = year, _month = month - 2;
|
int _year = year, _month = month - 2;
|
||||||
|
@ -103,6 +103,9 @@ public:
|
|||||||
template<typename T> inline const T *as(void) const {
|
template<typename T> inline const T *as(void) const {
|
||||||
return reinterpret_cast<const T *>(ptr);
|
return reinterpret_cast<const T *>(ptr);
|
||||||
}
|
}
|
||||||
|
template<typename T> inline T *allocate(size_t count = 1) {
|
||||||
|
return reinterpret_cast<T *>(allocate(sizeof(T) * count));
|
||||||
|
}
|
||||||
|
|
||||||
inline void *allocate(size_t _length) {
|
inline void *allocate(size_t _length) {
|
||||||
if (ptr)
|
if (ptr)
|
||||||
@ -170,15 +173,8 @@ public:
|
|||||||
uint8_t month, day;
|
uint8_t month, day;
|
||||||
uint8_t hour, minute, second;
|
uint8_t hour, minute, second;
|
||||||
|
|
||||||
inline bool isLeapYear(void) const {
|
bool isValid(void) const;
|
||||||
if (year % 4)
|
bool isLeapYear(void) const;
|
||||||
return false;
|
|
||||||
if (!(year % 100) && (year % 400))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getDayOfWeek(void) const;
|
int getDayOfWeek(void) const;
|
||||||
int getMonthDayCount(void) const;
|
int getMonthDayCount(void) const;
|
||||||
uint32_t toDOSTime(void) const;
|
uint32_t toDOSTime(void) const;
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include "common/defs.hpp"
|
#include "common/defs.hpp"
|
||||||
#include "common/file.hpp"
|
#include "common/file.hpp"
|
||||||
#include "common/gpu.hpp"
|
#include "common/gpu.hpp"
|
||||||
@ -154,27 +156,47 @@ void App::_loadResources(void) {
|
|||||||
_resourceProvider.loadVAG(_ctx.sounds[i], _UI_SOUND_PATHS[i]);
|
_resourceProvider.loadVAG(_ctx.sounds[i], _UI_SOUND_PATHS[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool App::_takeScreenshot(void) {
|
bool App::_createDataDirectory(void) {
|
||||||
|
file::FileInfo info;
|
||||||
|
|
||||||
|
if (!_fileProvider.getFileInfo(info, EXTERNAL_DATA_DIR))
|
||||||
|
return _fileProvider.createDirectory(EXTERNAL_DATA_DIR);
|
||||||
|
if (info.attributes & file::DIRECTORY)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool App::_getNumberedPath(char *output, size_t length, const char *path) {
|
||||||
file::FileInfo info;
|
file::FileInfo info;
|
||||||
char path[32];
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
index++;
|
if (++index > 9999)
|
||||||
snprintf(path, sizeof(path), EXTERNAL_DATA_DIR "/shot%04d.bmp", index);
|
return false;
|
||||||
} while (_fileProvider.getFileInfo(info, path));
|
|
||||||
|
snprintf(output, length, path, index);
|
||||||
|
} while (_fileProvider.getFileInfo(info, output));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool App::_takeScreenshot(void) {
|
||||||
|
char path[32];
|
||||||
|
|
||||||
|
if (!_createDataDirectory())
|
||||||
|
return false;
|
||||||
|
if (!_getNumberedPath(path, sizeof(path), EXTERNAL_DATA_DIR "/shot%04d.bmp"))
|
||||||
|
return false;
|
||||||
|
|
||||||
gpu::RectWH clip;
|
gpu::RectWH clip;
|
||||||
|
|
||||||
_ctx.gpuCtx.getVRAMClipRect(clip);
|
_ctx.gpuCtx.getVRAMClipRect(clip);
|
||||||
|
if (!_fileProvider.saveVRAMBMP(clip, path))
|
||||||
if (_fileProvider.saveVRAMBMP(clip, path)) {
|
|
||||||
LOG("%s saved", path);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
LOG("%s saving failed", path);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
LOG("%s saved", path);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::_worker(void) {
|
void App::_worker(void) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include "common/file.hpp"
|
#include "common/file.hpp"
|
||||||
#include "main/app/cartactions.hpp"
|
#include "main/app/cartactions.hpp"
|
||||||
#include "main/app/cartunlock.hpp"
|
#include "main/app/cartunlock.hpp"
|
||||||
@ -131,6 +132,8 @@ private:
|
|||||||
void _setupWorker(bool (App::*func)(void));
|
void _setupWorker(bool (App::*func)(void));
|
||||||
void _setupInterrupts(void);
|
void _setupInterrupts(void);
|
||||||
void _loadResources(void);
|
void _loadResources(void);
|
||||||
|
bool _createDataDirectory(void);
|
||||||
|
bool _getNumberedPath(char *output, size_t length, const char *path);
|
||||||
bool _takeScreenshot(void);
|
bool _takeScreenshot(void);
|
||||||
|
|
||||||
// cartworkers.cpp
|
// cartworkers.cpp
|
||||||
|
@ -202,20 +202,11 @@ bool App::_qrCodeWorker(void) {
|
|||||||
bool App::_cartDumpWorker(void) {
|
bool App::_cartDumpWorker(void) {
|
||||||
_workerStatus.update(0, 1, WSTR("App.cartDumpWorker.save"));
|
_workerStatus.update(0, 1, WSTR("App.cartDumpWorker.save"));
|
||||||
|
|
||||||
file::FileInfo info;
|
char path[32], code[8], region[8];
|
||||||
char path[32];
|
size_t length = _cartDump.getDumpLength();
|
||||||
|
|
||||||
__builtin_strcpy(path, EXTERNAL_DATA_DIR);
|
if (!_createDataDirectory())
|
||||||
|
goto _error;
|
||||||
if (!_fileProvider.getFileInfo(info, path)) {
|
|
||||||
if (!_fileProvider.createDirectory(path))
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
char code[8], region[8];
|
|
||||||
size_t length;
|
|
||||||
|
|
||||||
length = _cartDump.getDumpLength();
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
_identified && _cartParser->getCode(code) &&
|
_identified && _cartParser->getCode(code) &&
|
||||||
@ -225,14 +216,10 @@ bool App::_cartDumpWorker(void) {
|
|||||||
path, sizeof(path), EXTERNAL_DATA_DIR "/%s%s.573", code, region
|
path, sizeof(path), EXTERNAL_DATA_DIR "/%s%s.573", code, region
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
int index = 0;
|
if (!_getNumberedPath(
|
||||||
|
path, sizeof(path), EXTERNAL_DATA_DIR "/cart%04d.573"
|
||||||
do {
|
))
|
||||||
index++;
|
goto _error;
|
||||||
snprintf(
|
|
||||||
path, sizeof(path), EXTERNAL_DATA_DIR "/cart%04d.573", index
|
|
||||||
);
|
|
||||||
} while (_fileProvider.getFileInfo(info, path));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG("saving %s, length=%d", path, length);
|
LOG("saving %s, length=%d", path, length);
|
||||||
|
@ -34,7 +34,10 @@ void WarningScreen::update(ui::Context &ctx) {
|
|||||||
if (_locked) {
|
if (_locked) {
|
||||||
time = (time / ctx.gpuCtx.refreshRate) + 1;
|
time = (time / ctx.gpuCtx.refreshRate) + 1;
|
||||||
|
|
||||||
sprintf(_buttonText, STR("WarningScreen.cooldown"), time);
|
snprintf(
|
||||||
|
_buttonText, sizeof(_buttonText), STR("WarningScreen.cooldown"),
|
||||||
|
time
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,13 +217,12 @@ int FilePickerScreen::loadDirectory(ui::Context &ctx, const char *path) {
|
|||||||
LOG("path: %s", path);
|
LOG("path: %s", path);
|
||||||
LOG("files=%d, dirs=%d", _numFiles, _numDirectories);
|
LOG("files=%d, dirs=%d", _numFiles, _numDirectories);
|
||||||
|
|
||||||
if (_numFiles)
|
file::FileInfo *files, *directories;
|
||||||
_files.allocate(sizeof(file::FileInfo) * _numFiles);
|
|
||||||
if (_numDirectories)
|
|
||||||
_directories.allocate(sizeof(file::FileInfo) * _numDirectories);
|
|
||||||
|
|
||||||
auto files = _files.as<file::FileInfo>();
|
if (_numFiles)
|
||||||
auto directories = _directories.as<file::FileInfo>();
|
files = _files.allocate<file::FileInfo>(_numFiles);
|
||||||
|
if (_numDirectories)
|
||||||
|
directories = _directories.allocate<file::FileInfo>(_numDirectories);
|
||||||
|
|
||||||
// Iterate over all entries again to populate the newly allocated arrays.
|
// Iterate over all entries again to populate the newly allocated arrays.
|
||||||
directory = APP->_fileProvider.openDirectory(path);
|
directory = APP->_fileProvider.openDirectory(path);
|
||||||
|
@ -326,10 +326,10 @@ void StorageActionsScreen::update(ui::Context &ctx) {
|
|||||||
void CardSizeScreen::show(ui::Context &ctx, bool goBack) {
|
void CardSizeScreen::show(ui::Context &ctx, bool goBack) {
|
||||||
_title = STR("CardSizeScreen.title");
|
_title = STR("CardSizeScreen.title");
|
||||||
_body = STR("CardSizeScreen.body");
|
_body = STR("CardSizeScreen.body");
|
||||||
_buttons[0] = STR("CardSizeScreen.16");
|
_buttons[0] = STR("CardSizeScreen.cancel");
|
||||||
_buttons[1] = STR("CardSizeScreen.32");
|
_buttons[1] = STR("CardSizeScreen.16");
|
||||||
_buttons[2] = STR("CardSizeScreen.64");
|
_buttons[2] = STR("CardSizeScreen.32");
|
||||||
_buttons[3] = STR("CardSizeScreen.cancel");
|
_buttons[3] = STR("CardSizeScreen.64");
|
||||||
|
|
||||||
_numButtons = 4;
|
_numButtons = 4;
|
||||||
|
|
||||||
@ -340,11 +340,11 @@ void CardSizeScreen::update(ui::Context &ctx) {
|
|||||||
MessageBoxScreen::update(ctx);
|
MessageBoxScreen::update(ctx);
|
||||||
|
|
||||||
if (ctx.buttons.pressed(ui::BTN_START)) {
|
if (ctx.buttons.pressed(ui::BTN_START)) {
|
||||||
if (_activeButton == 3) {
|
if (_activeButton) {
|
||||||
ctx.show(APP->_storageActionsScreen, true, true);
|
selectedLength = 0x800000 << _activeButton;
|
||||||
} else {
|
|
||||||
selectedLength = 0x1000000 << _activeButton;
|
|
||||||
(APP->_storageActionsScreen.*callback)(ctx);
|
(APP->_storageActionsScreen.*callback)(ctx);
|
||||||
|
} else {
|
||||||
|
ctx.show(APP->_storageActionsScreen, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,33 +98,21 @@ bool App::_romChecksumWorker(void) {
|
|||||||
bool App::_romDumpWorker(void) {
|
bool App::_romDumpWorker(void) {
|
||||||
_workerStatus.update(0, 1, WSTR("App.romDumpWorker.init"));
|
_workerStatus.update(0, 1, WSTR("App.romDumpWorker.init"));
|
||||||
|
|
||||||
// Store all dumps in a subdirectory named "dumpN" within the main data
|
// Store all dumps in a subdirectory named "dumpNNNN" within the main data
|
||||||
// folder.
|
// folder.
|
||||||
file::FileInfo info;
|
char dirPath[32], filePath[32];
|
||||||
char dirPath[32];
|
|
||||||
|
|
||||||
__builtin_strcpy(dirPath, EXTERNAL_DATA_DIR);
|
|
||||||
|
|
||||||
if (!_fileProvider.getFileInfo(info, dirPath)) {
|
|
||||||
if (!_fileProvider.createDirectory(dirPath))
|
|
||||||
goto _initError;
|
|
||||||
}
|
|
||||||
|
|
||||||
int index;
|
|
||||||
char filePath[32];
|
|
||||||
|
|
||||||
index = 0;
|
|
||||||
|
|
||||||
do {
|
|
||||||
index++;
|
|
||||||
snprintf(dirPath, sizeof(dirPath), EXTERNAL_DATA_DIR "/dump%04d", index);
|
|
||||||
} while (_fileProvider.getFileInfo(info, dirPath));
|
|
||||||
|
|
||||||
LOG("saving dumps to %s", dirPath);
|
|
||||||
|
|
||||||
|
if (!_createDataDirectory())
|
||||||
|
goto _initError;
|
||||||
|
if (!_getNumberedPath(
|
||||||
|
dirPath, sizeof(dirPath), EXTERNAL_DATA_DIR "/dump%04d"
|
||||||
|
))
|
||||||
|
goto _initError;
|
||||||
if (!_fileProvider.createDirectory(dirPath))
|
if (!_fileProvider.createDirectory(dirPath))
|
||||||
goto _initError;
|
goto _initError;
|
||||||
|
|
||||||
|
LOG("saving dumps to %s", dirPath);
|
||||||
|
|
||||||
for (auto &entry : _REGION_INFO) {
|
for (auto &entry : _REGION_INFO) {
|
||||||
if (!entry.region.isPresent())
|
if (!entry.region.isPresent())
|
||||||
continue;
|
continue;
|
||||||
@ -142,19 +130,19 @@ bool App::_romDumpWorker(void) {
|
|||||||
if (!_file)
|
if (!_file)
|
||||||
goto _fileError;
|
goto _fileError;
|
||||||
|
|
||||||
auto buffer = new uint8_t[chunkLength];
|
util::Data buffer;
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
|
|
||||||
//assert(buffer);
|
buffer.allocate(chunkLength);
|
||||||
|
|
||||||
for (size_t i = 0; i < numChunks; i++) {
|
for (size_t i = 0; i < numChunks; i++) {
|
||||||
_workerStatus.update(i, numChunks, WSTRH(entry.dumpPrompt));
|
_workerStatus.update(i, numChunks, WSTRH(entry.dumpPrompt));
|
||||||
entry.region.read(buffer, offset, chunkLength);
|
entry.region.read(buffer.ptr, offset, chunkLength);
|
||||||
|
|
||||||
if (_file->write(buffer, chunkLength) < chunkLength) {
|
if (_file->write(buffer.ptr, chunkLength) < chunkLength) {
|
||||||
|
buffer.destroy();
|
||||||
_file->close();
|
_file->close();
|
||||||
delete _file;
|
delete _file;
|
||||||
delete[] buffer;
|
|
||||||
|
|
||||||
goto _fileError;
|
goto _fileError;
|
||||||
}
|
}
|
||||||
@ -162,9 +150,9 @@ bool App::_romDumpWorker(void) {
|
|||||||
offset += chunkLength;
|
offset += chunkLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buffer.destroy();
|
||||||
_file->close();
|
_file->close();
|
||||||
delete _file;
|
delete _file;
|
||||||
delete[] buffer;
|
|
||||||
|
|
||||||
LOG("%s saved", filePath);
|
LOG("%s saved", filePath);
|
||||||
}
|
}
|
||||||
@ -202,67 +190,117 @@ bool App::_romRestoreWorker(void) {
|
|||||||
auto region = _storageActionsScreen.selectedRegion;
|
auto region = _storageActionsScreen.selectedRegion;
|
||||||
auto regionLength = _cardSizeScreen.selectedLength;
|
auto regionLength = _cardSizeScreen.selectedLength;
|
||||||
|
|
||||||
|
size_t bytesWritten = 0;
|
||||||
|
|
||||||
|
util::Data buffers, chunkLengths;
|
||||||
|
|
||||||
if (!_file)
|
if (!_file)
|
||||||
goto _fileError;
|
goto _fileError;
|
||||||
if (!_romEraseWorker())
|
if (!_romEraseWorker())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
size_t fileLength, dataLength;
|
|
||||||
|
|
||||||
fileLength = size_t(_file->length);
|
|
||||||
dataLength = util::min(fileLength, regionLength);
|
|
||||||
|
|
||||||
rom::Driver *driver;
|
rom::Driver *driver;
|
||||||
size_t sectorLength, numSectors;
|
size_t chipLength, numChips, maxChunkLength;
|
||||||
|
|
||||||
driver = region->newDriver();
|
driver = region->newDriver();
|
||||||
sectorLength = driver->getChipSize().eraseSectorLength;
|
chipLength = driver->getChipSize().chipLength;
|
||||||
numSectors = (dataLength + sectorLength - 1) / sectorLength;
|
numChips = (regionLength + chipLength - 1) / chipLength;
|
||||||
|
maxChunkLength = util::min(regionLength, _DUMP_CHUNK_LENGTH / numChips);
|
||||||
|
|
||||||
|
LOG("%d chips, buf=%d", numChips, maxChunkLength);
|
||||||
|
|
||||||
rom::DriverError error;
|
rom::DriverError error;
|
||||||
uint8_t *buffer;
|
|
||||||
uint32_t offset;
|
|
||||||
|
|
||||||
buffer = new uint8_t[sectorLength];
|
buffers.allocate(maxChunkLength * numChips);
|
||||||
offset = 0;
|
chunkLengths.allocate<size_t>(numChips);
|
||||||
|
|
||||||
//assert(buffer);
|
// Parallelize writing by buffering a chunk for each chip into RAM, then
|
||||||
|
// writing all chunks to the respective chips at the same time.
|
||||||
|
for (size_t i = 0; i < chipLength; i += maxChunkLength) {
|
||||||
|
_workerStatus.update(i, chipLength, WSTR("App.romRestoreWorker.write"));
|
||||||
|
|
||||||
for (size_t i = 0; i < numSectors; i++) {
|
auto bufferPtr = buffers.as<uint8_t>();
|
||||||
_workerStatus.update(i, numSectors, WSTR("App.romRestoreWorker.write"));
|
auto lengthPtr = chunkLengths.as<size_t>();
|
||||||
|
size_t offset = i;
|
||||||
|
size_t totalLength = 0;
|
||||||
|
|
||||||
auto length = _file->read(buffer, sectorLength);
|
for (
|
||||||
auto ptr = reinterpret_cast<const uint16_t *>(buffer);
|
size_t j = numChips; j > 0; j--, bufferPtr += maxChunkLength,
|
||||||
|
offset += chipLength
|
||||||
|
) {
|
||||||
|
_file->seek(offset);
|
||||||
|
auto length = _file->read(bufferPtr, maxChunkLength);
|
||||||
|
|
||||||
// Data is written 16 bits at a time, so the buffer must be padded to an
|
// Data is written 16 bits at a time, so the chunk must be padded to
|
||||||
// even number of bytes.
|
// an even number of bytes.
|
||||||
if (length % 2)
|
if (length % 2)
|
||||||
buffer[length++] = 0xff;
|
bufferPtr[length++] = 0xff;
|
||||||
|
|
||||||
for (uint32_t end = offset + length; offset < end; offset += 2) {
|
*(lengthPtr++) = length;
|
||||||
auto value = *(ptr++);
|
totalLength += length;
|
||||||
|
}
|
||||||
|
|
||||||
driver->write(offset, value);
|
// Stop once there is no more data to write.
|
||||||
error = driver->flushWrite(offset, value);
|
if (!totalLength)
|
||||||
|
break;
|
||||||
|
|
||||||
if (error)
|
bufferPtr = buffers.as<uint8_t>();
|
||||||
goto _flashError;
|
offset = i;
|
||||||
|
|
||||||
|
for (
|
||||||
|
size_t j = 0; j < maxChunkLength; j += 2, bufferPtr += 2,
|
||||||
|
offset += 2
|
||||||
|
) {
|
||||||
|
auto chunkOffset = offset;
|
||||||
|
auto chunkPtr = bufferPtr;
|
||||||
|
lengthPtr = chunkLengths.as<size_t>();
|
||||||
|
|
||||||
|
for (
|
||||||
|
size_t k = numChips; k > 0;
|
||||||
|
k--, chunkPtr += maxChunkLength, chunkOffset += chipLength
|
||||||
|
) {
|
||||||
|
if (j >= *(lengthPtr++))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto value = *reinterpret_cast<const uint16_t *>(chunkPtr);
|
||||||
|
|
||||||
|
driver->write(chunkOffset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
chunkOffset = offset;
|
||||||
|
chunkPtr = bufferPtr;
|
||||||
|
lengthPtr = chunkLengths.as<size_t>();
|
||||||
|
|
||||||
|
for (
|
||||||
|
size_t k = numChips; k > 0; k--, chunkPtr += maxChunkLength,
|
||||||
|
chunkOffset += chipLength, bytesWritten += 2
|
||||||
|
) {
|
||||||
|
if (j >= *(lengthPtr++))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto value = *reinterpret_cast<const uint16_t *>(chunkPtr);
|
||||||
|
error = driver->flushWrite(chunkOffset, value);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
goto _flashError;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_file->close();
|
|
||||||
delete _file;
|
|
||||||
delete[] buffer;
|
|
||||||
delete driver;
|
|
||||||
|
|
||||||
util::Hash message;
|
util::Hash message;
|
||||||
|
|
||||||
message = (fileLength > dataLength)
|
message = (_file->length > regionLength)
|
||||||
? "App.romRestoreWorker.overflow"_h
|
? "App.romRestoreWorker.overflow"_h
|
||||||
: "App.romRestoreWorker.success"_h;
|
: "App.romRestoreWorker.success"_h;
|
||||||
|
|
||||||
|
buffers.destroy();
|
||||||
|
chunkLengths.destroy();
|
||||||
|
_file->close();
|
||||||
|
delete _file;
|
||||||
|
delete driver;
|
||||||
|
|
||||||
_messageScreen.setMessage(
|
_messageScreen.setMessage(
|
||||||
MESSAGE_SUCCESS, _storageInfoScreen, WSTRH(message), offset
|
MESSAGE_SUCCESS, _storageInfoScreen, WSTRH(message), bytesWritten
|
||||||
);
|
);
|
||||||
_workerStatus.setNextScreen(_messageScreen);
|
_workerStatus.setNextScreen(_messageScreen);
|
||||||
return true;
|
return true;
|
||||||
@ -276,15 +314,16 @@ _fileError:
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
_flashError:
|
_flashError:
|
||||||
|
buffers.destroy();
|
||||||
|
chunkLengths.destroy();
|
||||||
_file->close();
|
_file->close();
|
||||||
delete _file;
|
delete _file;
|
||||||
delete[] buffer;
|
delete driver;
|
||||||
delete driver;
|
|
||||||
|
|
||||||
_messageScreen.setMessage(
|
_messageScreen.setMessage(
|
||||||
MESSAGE_ERROR, _storageInfoScreen,
|
MESSAGE_ERROR, _storageInfoScreen,
|
||||||
WSTR("App.romRestoreWorker.flashError"), rom::getErrorString(error),
|
WSTR("App.romRestoreWorker.flashError"), rom::getErrorString(error),
|
||||||
offset
|
bytesWritten
|
||||||
);
|
);
|
||||||
_workerStatus.setNextScreen(_messageScreen);
|
_workerStatus.setNextScreen(_messageScreen);
|
||||||
return false;
|
return false;
|
||||||
@ -293,10 +332,12 @@ _flashError:
|
|||||||
bool App::_romEraseWorker(void) {
|
bool App::_romEraseWorker(void) {
|
||||||
auto region = _storageActionsScreen.selectedRegion;
|
auto region = _storageActionsScreen.selectedRegion;
|
||||||
auto regionLength = _cardSizeScreen.selectedLength;
|
auto regionLength = _cardSizeScreen.selectedLength;
|
||||||
auto driver = region->newDriver();
|
|
||||||
|
|
||||||
size_t chipLength = driver->getChipSize().chipLength;
|
auto driver = region->newDriver();
|
||||||
size_t sectorLength = driver->getChipSize().eraseSectorLength;
|
size_t chipLength = driver->getChipSize().chipLength;
|
||||||
|
size_t sectorLength = driver->getChipSize().eraseSectorLength;
|
||||||
|
//size_t numChips = (regionLength + chipLength - 1) / chipLength;
|
||||||
|
|
||||||
size_t sectorsErased = 0;
|
size_t sectorsErased = 0;
|
||||||
|
|
||||||
if (!chipLength)
|
if (!chipLength)
|
||||||
@ -306,7 +347,8 @@ bool App::_romEraseWorker(void) {
|
|||||||
|
|
||||||
_checksumScreen.valid = false;
|
_checksumScreen.valid = false;
|
||||||
|
|
||||||
// Erase one sector at a time on each chip.
|
// Parallelize erasing by sending the same sector erase command to all chips
|
||||||
|
// at the same time.
|
||||||
for (size_t i = 0; i < chipLength; i += sectorLength) {
|
for (size_t i = 0; i < chipLength; i += sectorLength) {
|
||||||
_workerStatus.update(i, chipLength, WSTR("App.romEraseWorker.erase"));
|
_workerStatus.update(i, chipLength, WSTR("App.romEraseWorker.erase"));
|
||||||
|
|
||||||
@ -356,6 +398,8 @@ bool App::_flashHeaderWriteWorker(void) {
|
|||||||
auto driver = rom::flash.newDriver();
|
auto driver = rom::flash.newDriver();
|
||||||
size_t sectorLength = driver->getChipSize().eraseSectorLength;
|
size_t sectorLength = driver->getChipSize().eraseSectorLength;
|
||||||
|
|
||||||
|
util::Data buffer;
|
||||||
|
|
||||||
// This should never happen since the flash chips are soldered to the 573,
|
// This should never happen since the flash chips are soldered to the 573,
|
||||||
// but whatever.
|
// but whatever.
|
||||||
if (!sectorLength)
|
if (!sectorLength)
|
||||||
@ -367,14 +411,10 @@ bool App::_flashHeaderWriteWorker(void) {
|
|||||||
// The flash can only be erased with sector granularity, so all data in the
|
// The flash can only be erased with sector granularity, so all data in the
|
||||||
// first sector other than the header must be backed up and rewritten.
|
// first sector other than the header must be backed up and rewritten.
|
||||||
rom::DriverError error;
|
rom::DriverError error;
|
||||||
uint8_t *buffer;
|
|
||||||
const uint16_t *ptr;
|
const uint16_t *ptr;
|
||||||
|
|
||||||
buffer = new uint8_t[sectorLength];
|
buffer.allocate(sectorLength);
|
||||||
|
rom::flash.read(buffer.ptr, 0, sectorLength);
|
||||||
//assert(buffer);
|
|
||||||
|
|
||||||
rom::flash.read(buffer, 0, sectorLength);
|
|
||||||
|
|
||||||
driver->eraseSector(0);
|
driver->eraseSector(0);
|
||||||
error = driver->flushErase(0);
|
error = driver->flushErase(0);
|
||||||
@ -403,7 +443,7 @@ bool App::_flashHeaderWriteWorker(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Restore the rest of the sector that was erased.
|
// Restore the rest of the sector that was erased.
|
||||||
ptr = reinterpret_cast<const uint16_t *>(&buffer[rom::FLASH_CRC_OFFSET]);
|
ptr = &buffer.as<const uint16_t>()[rom::FLASH_CRC_OFFSET / 2];
|
||||||
|
|
||||||
for (
|
for (
|
||||||
uint32_t offset = rom::FLASH_CRC_OFFSET; offset < sectorLength;
|
uint32_t offset = rom::FLASH_CRC_OFFSET; offset < sectorLength;
|
||||||
@ -418,15 +458,15 @@ bool App::_flashHeaderWriteWorker(void) {
|
|||||||
goto _flashError;
|
goto _flashError;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] buffer;
|
buffer.destroy();
|
||||||
delete driver;
|
delete driver;
|
||||||
|
|
||||||
_workerStatus.setNextScreen(_storageInfoScreen);
|
_workerStatus.setNextScreen(_storageInfoScreen);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
_flashError:
|
_flashError:
|
||||||
delete[] buffer;
|
buffer.destroy();
|
||||||
delete driver;
|
delete driver;
|
||||||
|
|
||||||
_messageScreen.setMessage(
|
_messageScreen.setMessage(
|
||||||
MESSAGE_ERROR, _storageInfoScreen,
|
MESSAGE_ERROR, _storageInfoScreen,
|
||||||
|
@ -29,7 +29,7 @@ typedef enum {
|
|||||||
SYS573_MISC_OUT_AMP_ENABLE = 1 << 5,
|
SYS573_MISC_OUT_AMP_ENABLE = 1 << 5,
|
||||||
SYS573_MISC_OUT_CDDA_ENABLE = 1 << 6,
|
SYS573_MISC_OUT_CDDA_ENABLE = 1 << 6,
|
||||||
SYS573_MISC_OUT_SPU_ENABLE = 1 << 7,
|
SYS573_MISC_OUT_SPU_ENABLE = 1 << 7,
|
||||||
SYS573_MISC_OUT_JVS_STAT = 1 << 8
|
SYS573_MISC_OUT_JVS_RESET = 1 << 8
|
||||||
} Sys573MiscOutputFlag;
|
} Sys573MiscOutputFlag;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -37,10 +37,10 @@ typedef enum {
|
|||||||
SYS573_MISC_IN_ADC_SARS = 1 << 1,
|
SYS573_MISC_IN_ADC_SARS = 1 << 1,
|
||||||
SYS573_MISC_IN_CART_SDA = 1 << 2,
|
SYS573_MISC_IN_CART_SDA = 1 << 2,
|
||||||
SYS573_MISC_IN_JVS_SENSE = 1 << 3,
|
SYS573_MISC_IN_JVS_SENSE = 1 << 3,
|
||||||
SYS573_MISC_IN_JVS_AVAIL = 1 << 4,
|
SYS573_MISC_IN_JVS_IRDY = 1 << 4,
|
||||||
SYS573_MISC_IN_JVS_UNK = 1 << 5,
|
SYS573_MISC_IN_JVS_DRDY = 1 << 5,
|
||||||
SYS573_MISC_IN_CART_ISIG = 1 << 6,
|
SYS573_MISC_IN_CART_IRDY = 1 << 6,
|
||||||
SYS573_MISC_IN_CART_DSIG = 1 << 7,
|
SYS573_MISC_IN_CART_DRDY = 1 << 7,
|
||||||
SYS573_MISC_IN_COIN1 = 1 << 8,
|
SYS573_MISC_IN_COIN1 = 1 << 8,
|
||||||
SYS573_MISC_IN_COIN2 = 1 << 9,
|
SYS573_MISC_IN_COIN2 = 1 << 9,
|
||||||
SYS573_MISC_IN_PCMCIA_CD1 = 1 << 10,
|
SYS573_MISC_IN_PCMCIA_CD1 = 1 << 10,
|
||||||
@ -126,17 +126,18 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
SYS573D_CPLD_STAT_INIT = 1 << 12,
|
SYS573D_CPLD_STAT_INIT = 1 << 12,
|
||||||
SYS573D_CPLD_STAT_DONE = 1 << 13,
|
SYS573D_CPLD_STAT_DONE = 1 << 13,
|
||||||
SYS573D_CPLD_STAT_LDC = 1 << 14,
|
SYS573D_CPLD_STAT_ID1 = 1 << 14,
|
||||||
SYS573D_CPLD_STAT_HDC = 1 << 15
|
SYS573D_CPLD_STAT_ID2 = 1 << 15
|
||||||
} Sys573DCPLDStatusFlag;
|
} Sys573DCPLDStatusFlag;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SYS573D_CPLD_CTRL_UNK1 = 1 << 12,
|
SYS573D_CPLD_CTRL_INIT = 1 << 12,
|
||||||
SYS573D_CPLD_CTRL_UNK2 = 1 << 13,
|
SYS573D_CPLD_CTRL_DONE = 1 << 13,
|
||||||
SYS573D_CPLD_CTRL_UNK3 = 1 << 14,
|
SYS573D_CPLD_CTRL_PROGRAM = 1 << 14,
|
||||||
SYS573D_CPLD_CTRL_UNK4 = 1 << 15
|
SYS573D_CPLD_CTRL_UNKNOWN = 1 << 15
|
||||||
} Sys573DCPLDControlFlag;
|
} Sys573DCPLDControlFlag;
|
||||||
|
|
||||||
|
#define SYS573D_FPGA_MAGIC _MMIO16(DEV0_BASE | 0x640080)
|
||||||
#define SYS573D_FPGA_LIGHTS_A1 _MMIO16(DEV0_BASE | 0x6400e0)
|
#define SYS573D_FPGA_LIGHTS_A1 _MMIO16(DEV0_BASE | 0x6400e0)
|
||||||
#define SYS573D_FPGA_LIGHTS_A0 _MMIO16(DEV0_BASE | 0x6400e2)
|
#define SYS573D_FPGA_LIGHTS_A0 _MMIO16(DEV0_BASE | 0x6400e2)
|
||||||
#define SYS573D_FPGA_LIGHTS_B1 _MMIO16(DEV0_BASE | 0x6400e4)
|
#define SYS573D_FPGA_LIGHTS_B1 _MMIO16(DEV0_BASE | 0x6400e4)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user