diff --git a/CMakeLists.txt b/CMakeLists.txt index 2570ecb..aab301e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_LIST_DIR}/cmake/toolchain.cmake") project( cart_tool_private LANGUAGES C CXX ASM - VERSION 0.4.1 + VERSION 0.4.2 DESCRIPTION "Konami System 573 security cartridge tool" ) diff --git a/src/common/file.cpp b/src/common/file.cpp index c976938..f5769d2 100644 --- a/src/common/file.cpp +++ b/src/common/file.cpp @@ -354,7 +354,7 @@ size_t Provider::saveVRAMBMP(gpu::RectWH &rect, const char *path) { size_t length = _file->write(&header, sizeof(header)); util::Data buffer; - if (buffer.allocate(rect.w * 2 + 32)) { + if (buffer.allocate(rect.w + 32)) { // Read the image from VRAM one line at a time from the bottom up, as // the BMP format stores lines in reversed order. gpu::RectWH slice; diff --git a/src/common/io.cpp b/src/common/io.cpp index 4f0b145..e5dbb10 100644 --- a/src/common/io.cpp +++ b/src/common/io.cpp @@ -18,7 +18,7 @@ void init(void) { | SYS573_MISC_OUT_ADC_MOSI | SYS573_MISC_OUT_ADC_CS | SYS573_MISC_OUT_ADC_SCK - | SYS573_MISC_OUT_JVS_STAT; + | SYS573_MISC_OUT_JVS_RESET; BIU_DEV0_ADDR = DEV0_BASE & 0x1fffffff; BIU_DEV0_CTRL = 0 @@ -204,13 +204,15 @@ bool loadRawBitstream(const uint8_t *data, size_t length) { for (int i = 3; i; i--) { SYS573D_CPLD_UNK_RESET = 0; - SYS573D_CPLD_CTRL = SYS573D_CPLD_CTRL_UNK4; - SYS573D_CPLD_CTRL = SYS573D_CPLD_CTRL_UNK3 | SYS573D_CPLD_CTRL_UNK4; + SYS573D_CPLD_CTRL = SYS573D_CPLD_CTRL_UNKNOWN; SYS573D_CPLD_CTRL = 0 - | SYS573D_CPLD_CTRL_UNK1 - | SYS573D_CPLD_CTRL_UNK2 - | SYS573D_CPLD_CTRL_UNK3 - | SYS573D_CPLD_CTRL_UNK4; + | SYS573D_CPLD_CTRL_PROGRAM + | SYS573D_CPLD_CTRL_UNKNOWN; + SYS573D_CPLD_CTRL = 0 + | SYS573D_CPLD_CTRL_INIT + | SYS573D_CPLD_CTRL_DONE + | SYS573D_CPLD_CTRL_PROGRAM + | SYS573D_CPLD_CTRL_UNKNOWN; delayMicroseconds(5000); if (!(SYS573D_CPLD_STAT & SYS573D_CPLD_STAT_INIT)) diff --git a/src/common/io.hpp b/src/common/io.hpp index b2e2493..7271789 100644 --- a/src/common/io.hpp +++ b/src/common/io.hpp @@ -141,11 +141,10 @@ static inline void setMiscOutput(MiscOutputPin pin, bool value) { /* Digital I/O board driver */ -// TODO: these do not seem to actually be LDC and HDC... static inline bool isDigitalIOPresent(void) { return ( - (SYS573D_CPLD_STAT & (SYS573D_CPLD_STAT_LDC | SYS573D_CPLD_STAT_HDC)) - == SYS573D_CPLD_STAT_HDC + (SYS573D_CPLD_STAT & (SYS573D_CPLD_STAT_ID1 | SYS573D_CPLD_STAT_ID2)) == + SYS573D_CPLD_STAT_ID1 ); } diff --git a/src/common/util.cpp b/src/common/util.cpp index 3c66eb5..892f3cb 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -33,6 +33,26 @@ Hash hash(const uint8_t *data, size_t length) { /* 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 { // See https://datatracker.ietf.org/doc/html/rfc3339#appendix-B int _year = year, _month = month - 2; diff --git a/src/common/util.hpp b/src/common/util.hpp index d0f4744..92fd2db 100644 --- a/src/common/util.hpp +++ b/src/common/util.hpp @@ -103,6 +103,9 @@ public: template inline const T *as(void) const { return reinterpret_cast(ptr); } + template inline T *allocate(size_t count = 1) { + return reinterpret_cast(allocate(sizeof(T) * count)); + } inline void *allocate(size_t _length) { if (ptr) @@ -170,15 +173,8 @@ public: uint8_t month, day; uint8_t hour, minute, second; - inline bool isLeapYear(void) const { - if (year % 4) - return false; - if (!(year % 100) && (year % 400)) - return false; - - return true; - } - + bool isValid(void) const; + bool isLeapYear(void) const; int getDayOfWeek(void) const; int getMonthDayCount(void) const; uint32_t toDOSTime(void) const; diff --git a/src/main/app/app.cpp b/src/main/app/app.cpp index 302b65d..86021f3 100644 --- a/src/main/app/app.cpp +++ b/src/main/app/app.cpp @@ -1,4 +1,6 @@ +#include +#include #include "common/defs.hpp" #include "common/file.hpp" #include "common/gpu.hpp" @@ -154,27 +156,47 @@ void App::_loadResources(void) { _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; - char path[32]; int index = 0; do { - index++; - snprintf(path, sizeof(path), EXTERNAL_DATA_DIR "/shot%04d.bmp", index); - } while (_fileProvider.getFileInfo(info, path)); + if (++index > 9999) + return false; + + 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; _ctx.gpuCtx.getVRAMClipRect(clip); - - if (_fileProvider.saveVRAMBMP(clip, path)) { - LOG("%s saved", path); - return true; - } else { - LOG("%s saving failed", path); + if (!_fileProvider.saveVRAMBMP(clip, path)) return false; - } + + LOG("%s saved", path); + return true; } void App::_worker(void) { diff --git a/src/main/app/app.hpp b/src/main/app/app.hpp index 600edd7..cd3e270 100644 --- a/src/main/app/app.hpp +++ b/src/main/app/app.hpp @@ -1,6 +1,7 @@ #pragma once +#include #include "common/file.hpp" #include "main/app/cartactions.hpp" #include "main/app/cartunlock.hpp" @@ -131,6 +132,8 @@ private: void _setupWorker(bool (App::*func)(void)); void _setupInterrupts(void); void _loadResources(void); + bool _createDataDirectory(void); + bool _getNumberedPath(char *output, size_t length, const char *path); bool _takeScreenshot(void); // cartworkers.cpp diff --git a/src/main/app/cartworkers.cpp b/src/main/app/cartworkers.cpp index 55aa8c9..f9805e3 100644 --- a/src/main/app/cartworkers.cpp +++ b/src/main/app/cartworkers.cpp @@ -202,20 +202,11 @@ bool App::_qrCodeWorker(void) { bool App::_cartDumpWorker(void) { _workerStatus.update(0, 1, WSTR("App.cartDumpWorker.save")); - file::FileInfo info; - char path[32]; + char path[32], code[8], region[8]; + size_t length = _cartDump.getDumpLength(); - __builtin_strcpy(path, EXTERNAL_DATA_DIR); - - if (!_fileProvider.getFileInfo(info, path)) { - if (!_fileProvider.createDirectory(path)) - goto _error; - } - - char code[8], region[8]; - size_t length; - - length = _cartDump.getDumpLength(); + if (!_createDataDirectory()) + goto _error; if ( _identified && _cartParser->getCode(code) && @@ -225,14 +216,10 @@ bool App::_cartDumpWorker(void) { path, sizeof(path), EXTERNAL_DATA_DIR "/%s%s.573", code, region ); } else { - int index = 0; - - do { - index++; - snprintf( - path, sizeof(path), EXTERNAL_DATA_DIR "/cart%04d.573", index - ); - } while (_fileProvider.getFileInfo(info, path)); + if (!_getNumberedPath( + path, sizeof(path), EXTERNAL_DATA_DIR "/cart%04d.573" + )) + goto _error; } LOG("saving %s, length=%d", path, length); diff --git a/src/main/app/main.cpp b/src/main/app/main.cpp index 40b24bc..0b8d5f0 100644 --- a/src/main/app/main.cpp +++ b/src/main/app/main.cpp @@ -34,7 +34,10 @@ void WarningScreen::update(ui::Context &ctx) { if (_locked) { time = (time / ctx.gpuCtx.refreshRate) + 1; - sprintf(_buttonText, STR("WarningScreen.cooldown"), time); + snprintf( + _buttonText, sizeof(_buttonText), STR("WarningScreen.cooldown"), + time + ); return; } diff --git a/src/main/app/modals.cpp b/src/main/app/modals.cpp index 85cf50c..a891ac7 100644 --- a/src/main/app/modals.cpp +++ b/src/main/app/modals.cpp @@ -217,13 +217,12 @@ int FilePickerScreen::loadDirectory(ui::Context &ctx, const char *path) { LOG("path: %s", path); LOG("files=%d, dirs=%d", _numFiles, _numDirectories); - if (_numFiles) - _files.allocate(sizeof(file::FileInfo) * _numFiles); - if (_numDirectories) - _directories.allocate(sizeof(file::FileInfo) * _numDirectories); + file::FileInfo *files, *directories; - auto files = _files.as(); - auto directories = _directories.as(); + if (_numFiles) + files = _files.allocate(_numFiles); + if (_numDirectories) + directories = _directories.allocate(_numDirectories); // Iterate over all entries again to populate the newly allocated arrays. directory = APP->_fileProvider.openDirectory(path); diff --git a/src/main/app/romactions.cpp b/src/main/app/romactions.cpp index 1bc2795..51e615c 100644 --- a/src/main/app/romactions.cpp +++ b/src/main/app/romactions.cpp @@ -326,10 +326,10 @@ void StorageActionsScreen::update(ui::Context &ctx) { void CardSizeScreen::show(ui::Context &ctx, bool goBack) { _title = STR("CardSizeScreen.title"); _body = STR("CardSizeScreen.body"); - _buttons[0] = STR("CardSizeScreen.16"); - _buttons[1] = STR("CardSizeScreen.32"); - _buttons[2] = STR("CardSizeScreen.64"); - _buttons[3] = STR("CardSizeScreen.cancel"); + _buttons[0] = STR("CardSizeScreen.cancel"); + _buttons[1] = STR("CardSizeScreen.16"); + _buttons[2] = STR("CardSizeScreen.32"); + _buttons[3] = STR("CardSizeScreen.64"); _numButtons = 4; @@ -340,11 +340,11 @@ void CardSizeScreen::update(ui::Context &ctx) { MessageBoxScreen::update(ctx); if (ctx.buttons.pressed(ui::BTN_START)) { - if (_activeButton == 3) { - ctx.show(APP->_storageActionsScreen, true, true); - } else { - selectedLength = 0x1000000 << _activeButton; + if (_activeButton) { + selectedLength = 0x800000 << _activeButton; (APP->_storageActionsScreen.*callback)(ctx); + } else { + ctx.show(APP->_storageActionsScreen, true, true); } } } diff --git a/src/main/app/romworkers.cpp b/src/main/app/romworkers.cpp index a983d4a..a44a598 100644 --- a/src/main/app/romworkers.cpp +++ b/src/main/app/romworkers.cpp @@ -98,33 +98,21 @@ bool App::_romChecksumWorker(void) { bool App::_romDumpWorker(void) { _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. - file::FileInfo info; - 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); + char dirPath[32], filePath[32]; + if (!_createDataDirectory()) + goto _initError; + if (!_getNumberedPath( + dirPath, sizeof(dirPath), EXTERNAL_DATA_DIR "/dump%04d" + )) + goto _initError; if (!_fileProvider.createDirectory(dirPath)) goto _initError; + LOG("saving dumps to %s", dirPath); + for (auto &entry : _REGION_INFO) { if (!entry.region.isPresent()) continue; @@ -142,19 +130,19 @@ bool App::_romDumpWorker(void) { if (!_file) goto _fileError; - auto buffer = new uint8_t[chunkLength]; - uint32_t offset = 0; + util::Data buffer; + uint32_t offset = 0; - //assert(buffer); + buffer.allocate(chunkLength); for (size_t i = 0; i < numChunks; i++) { _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(); - delete _file; - delete[] buffer; + delete _file; goto _fileError; } @@ -162,9 +150,9 @@ bool App::_romDumpWorker(void) { offset += chunkLength; } + buffer.destroy(); _file->close(); - delete _file; - delete[] buffer; + delete _file; LOG("%s saved", filePath); } @@ -202,67 +190,117 @@ bool App::_romRestoreWorker(void) { auto region = _storageActionsScreen.selectedRegion; auto regionLength = _cardSizeScreen.selectedLength; + size_t bytesWritten = 0; + + util::Data buffers, chunkLengths; + if (!_file) goto _fileError; if (!_romEraseWorker()) return false; - size_t fileLength, dataLength; - - fileLength = size_t(_file->length); - dataLength = util::min(fileLength, regionLength); - rom::Driver *driver; - size_t sectorLength, numSectors; + size_t chipLength, numChips, maxChunkLength; - driver = region->newDriver(); - sectorLength = driver->getChipSize().eraseSectorLength; - numSectors = (dataLength + sectorLength - 1) / sectorLength; + driver = region->newDriver(); + chipLength = driver->getChipSize().chipLength; + numChips = (regionLength + chipLength - 1) / chipLength; + maxChunkLength = util::min(regionLength, _DUMP_CHUNK_LENGTH / numChips); + + LOG("%d chips, buf=%d", numChips, maxChunkLength); rom::DriverError error; - uint8_t *buffer; - uint32_t offset; - buffer = new uint8_t[sectorLength]; - offset = 0; + buffers.allocate(maxChunkLength * numChips); + chunkLengths.allocate(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++) { - _workerStatus.update(i, numSectors, WSTR("App.romRestoreWorker.write")); + auto bufferPtr = buffers.as(); + auto lengthPtr = chunkLengths.as(); + size_t offset = i; + size_t totalLength = 0; - auto length = _file->read(buffer, sectorLength); - auto ptr = reinterpret_cast(buffer); + for ( + 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 - // even number of bytes. - if (length % 2) - buffer[length++] = 0xff; + // Data is written 16 bits at a time, so the chunk must be padded to + // an even number of bytes. + if (length % 2) + bufferPtr[length++] = 0xff; - for (uint32_t end = offset + length; offset < end; offset += 2) { - auto value = *(ptr++); + *(lengthPtr++) = length; + totalLength += length; + } - driver->write(offset, value); - error = driver->flushWrite(offset, value); + // Stop once there is no more data to write. + if (!totalLength) + break; - if (error) - goto _flashError; + bufferPtr = buffers.as(); + offset = i; + + for ( + size_t j = 0; j < maxChunkLength; j += 2, bufferPtr += 2, + offset += 2 + ) { + auto chunkOffset = offset; + auto chunkPtr = bufferPtr; + lengthPtr = chunkLengths.as(); + + for ( + size_t k = numChips; k > 0; + k--, chunkPtr += maxChunkLength, chunkOffset += chipLength + ) { + if (j >= *(lengthPtr++)) + continue; + + auto value = *reinterpret_cast(chunkPtr); + + driver->write(chunkOffset, value); + } + + chunkOffset = offset; + chunkPtr = bufferPtr; + lengthPtr = chunkLengths.as(); + + for ( + size_t k = numChips; k > 0; k--, chunkPtr += maxChunkLength, + chunkOffset += chipLength, bytesWritten += 2 + ) { + if (j >= *(lengthPtr++)) + continue; + + auto value = *reinterpret_cast(chunkPtr); + error = driver->flushWrite(chunkOffset, value); + + if (error) + goto _flashError; + } } } - _file->close(); - delete _file; - delete[] buffer; - delete driver; - util::Hash message; - message = (fileLength > dataLength) + message = (_file->length > regionLength) ? "App.romRestoreWorker.overflow"_h : "App.romRestoreWorker.success"_h; + buffers.destroy(); + chunkLengths.destroy(); + _file->close(); + delete _file; + delete driver; + _messageScreen.setMessage( - MESSAGE_SUCCESS, _storageInfoScreen, WSTRH(message), offset + MESSAGE_SUCCESS, _storageInfoScreen, WSTRH(message), bytesWritten ); _workerStatus.setNextScreen(_messageScreen); return true; @@ -276,15 +314,16 @@ _fileError: return false; _flashError: + buffers.destroy(); + chunkLengths.destroy(); _file->close(); - delete _file; - delete[] buffer; - delete driver; + delete _file; + delete driver; _messageScreen.setMessage( MESSAGE_ERROR, _storageInfoScreen, WSTR("App.romRestoreWorker.flashError"), rom::getErrorString(error), - offset + bytesWritten ); _workerStatus.setNextScreen(_messageScreen); return false; @@ -293,10 +332,12 @@ _flashError: bool App::_romEraseWorker(void) { auto region = _storageActionsScreen.selectedRegion; auto regionLength = _cardSizeScreen.selectedLength; - auto driver = region->newDriver(); - size_t chipLength = driver->getChipSize().chipLength; - size_t sectorLength = driver->getChipSize().eraseSectorLength; + auto driver = region->newDriver(); + size_t chipLength = driver->getChipSize().chipLength; + size_t sectorLength = driver->getChipSize().eraseSectorLength; + //size_t numChips = (regionLength + chipLength - 1) / chipLength; + size_t sectorsErased = 0; if (!chipLength) @@ -306,7 +347,8 @@ bool App::_romEraseWorker(void) { _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) { _workerStatus.update(i, chipLength, WSTR("App.romEraseWorker.erase")); @@ -356,6 +398,8 @@ bool App::_flashHeaderWriteWorker(void) { auto driver = rom::flash.newDriver(); size_t sectorLength = driver->getChipSize().eraseSectorLength; + util::Data buffer; + // This should never happen since the flash chips are soldered to the 573, // but whatever. if (!sectorLength) @@ -367,14 +411,10 @@ bool App::_flashHeaderWriteWorker(void) { // 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. rom::DriverError error; - uint8_t *buffer; const uint16_t *ptr; - buffer = new uint8_t[sectorLength]; - - //assert(buffer); - - rom::flash.read(buffer, 0, sectorLength); + buffer.allocate(sectorLength); + rom::flash.read(buffer.ptr, 0, sectorLength); driver->eraseSector(0); error = driver->flushErase(0); @@ -403,7 +443,7 @@ bool App::_flashHeaderWriteWorker(void) { } // Restore the rest of the sector that was erased. - ptr = reinterpret_cast(&buffer[rom::FLASH_CRC_OFFSET]); + ptr = &buffer.as()[rom::FLASH_CRC_OFFSET / 2]; for ( uint32_t offset = rom::FLASH_CRC_OFFSET; offset < sectorLength; @@ -418,15 +458,15 @@ bool App::_flashHeaderWriteWorker(void) { goto _flashError; } - delete[] buffer; - delete driver; + buffer.destroy(); + delete driver; _workerStatus.setNextScreen(_storageInfoScreen); return true; _flashError: - delete[] buffer; - delete driver; + buffer.destroy(); + delete driver; _messageScreen.setMessage( MESSAGE_ERROR, _storageInfoScreen, diff --git a/src/ps1/registers573.h b/src/ps1/registers573.h index 4f53fbd..280f388 100644 --- a/src/ps1/registers573.h +++ b/src/ps1/registers573.h @@ -29,7 +29,7 @@ typedef enum { SYS573_MISC_OUT_AMP_ENABLE = 1 << 5, SYS573_MISC_OUT_CDDA_ENABLE = 1 << 6, SYS573_MISC_OUT_SPU_ENABLE = 1 << 7, - SYS573_MISC_OUT_JVS_STAT = 1 << 8 + SYS573_MISC_OUT_JVS_RESET = 1 << 8 } Sys573MiscOutputFlag; typedef enum { @@ -37,10 +37,10 @@ typedef enum { SYS573_MISC_IN_ADC_SARS = 1 << 1, SYS573_MISC_IN_CART_SDA = 1 << 2, SYS573_MISC_IN_JVS_SENSE = 1 << 3, - SYS573_MISC_IN_JVS_AVAIL = 1 << 4, - SYS573_MISC_IN_JVS_UNK = 1 << 5, - SYS573_MISC_IN_CART_ISIG = 1 << 6, - SYS573_MISC_IN_CART_DSIG = 1 << 7, + SYS573_MISC_IN_JVS_IRDY = 1 << 4, + SYS573_MISC_IN_JVS_DRDY = 1 << 5, + SYS573_MISC_IN_CART_IRDY = 1 << 6, + SYS573_MISC_IN_CART_DRDY = 1 << 7, SYS573_MISC_IN_COIN1 = 1 << 8, SYS573_MISC_IN_COIN2 = 1 << 9, SYS573_MISC_IN_PCMCIA_CD1 = 1 << 10, @@ -126,17 +126,18 @@ typedef enum { typedef enum { SYS573D_CPLD_STAT_INIT = 1 << 12, SYS573D_CPLD_STAT_DONE = 1 << 13, - SYS573D_CPLD_STAT_LDC = 1 << 14, - SYS573D_CPLD_STAT_HDC = 1 << 15 + SYS573D_CPLD_STAT_ID1 = 1 << 14, + SYS573D_CPLD_STAT_ID2 = 1 << 15 } Sys573DCPLDStatusFlag; typedef enum { - SYS573D_CPLD_CTRL_UNK1 = 1 << 12, - SYS573D_CPLD_CTRL_UNK2 = 1 << 13, - SYS573D_CPLD_CTRL_UNK3 = 1 << 14, - SYS573D_CPLD_CTRL_UNK4 = 1 << 15 + SYS573D_CPLD_CTRL_INIT = 1 << 12, + SYS573D_CPLD_CTRL_DONE = 1 << 13, + SYS573D_CPLD_CTRL_PROGRAM = 1 << 14, + SYS573D_CPLD_CTRL_UNKNOWN = 1 << 15 } Sys573DCPLDControlFlag; +#define SYS573D_FPGA_MAGIC _MMIO16(DEV0_BASE | 0x640080) #define SYS573D_FPGA_LIGHTS_A1 _MMIO16(DEV0_BASE | 0x6400e0) #define SYS573D_FPGA_LIGHTS_A0 _MMIO16(DEV0_BASE | 0x6400e2) #define SYS573D_FPGA_LIGHTS_B1 _MMIO16(DEV0_BASE | 0x6400e4)