diff --git a/tests/autotester/autotester.cpp b/tests/autotester/autotester.cpp index a80e2a31..5b0f7d67 100644 --- a/tests/autotester/autotester.cpp +++ b/tests/autotester/autotester.cpp @@ -45,6 +45,37 @@ static char* myrealpath(const char* file_name) #endif } +static void dumpScreenshot(const std::string& description) +{ + std::string safe_name = description; + for (char& c : safe_name) { + if (c == '/' || c == '\\' || c == ':' || c == '*' || c == '?' || c == '"' || c == '<' || c == '>' || c == '|') { + c = '_'; + } + } + + std::string path = safe_name + ".rgba"; + + uint32_t *frame = static_cast(malloc(LCD_SIZE * sizeof(uint32_t))); + if (!frame) { + std::cerr << "\t[Screenshot] Failed to allocate frame buffer" << std::endl; + return; + } + + cemucore::emu_lcd_drawframe(frame); + + FILE *f = fopen(path.c_str(), "wb"); + if (f) { + fwrite(frame, sizeof(uint32_t), LCD_SIZE, f); + fclose(f); + std::cout << "\t[Screenshot] Saved " << path << std::endl; + } else { + std::cerr << "\t[Screenshot] Failed to write " << path << std::endl; + } + + free(frame); +} + namespace autotester { @@ -54,6 +85,7 @@ config_t config; std::string oldCWD; bool debugMode = true; +bool screenshotsMode = false; bool ignoreROMfield = false; bool configLoaded = false; @@ -217,6 +249,9 @@ static const std::unordered_map valid_seq_commands ::free(temp_buffer_dup); } hashesTested++; + if (screenshotsMode) { + dumpScreenshot(param.description); + } } else { std::cerr << "\t[Error] hash #" << which_hash << " was not declared in the JSON file. Ignoring." << std::endl; } diff --git a/tests/autotester/autotester.h b/tests/autotester/autotester.h index 6bc4c156..fb5c11e2 100644 --- a/tests/autotester/autotester.h +++ b/tests/autotester/autotester.h @@ -135,6 +135,7 @@ namespace autotester extern config_t config; extern bool debugMode; + extern bool screenshotsMode; extern bool ignoreROMfield; extern bool configLoaded; @@ -147,4 +148,3 @@ namespace autotester } #endif - diff --git a/tests/autotester/autotester_cli.cpp b/tests/autotester/autotester_cli.cpp index 6d17ed54..cdcb6ad7 100644 --- a/tests/autotester/autotester_cli.cpp +++ b/tests/autotester/autotester_cli.cpp @@ -60,21 +60,29 @@ int main(int argc, char* argv[]) // Used if the coreThread has been started (need to exit properly ; uses gotos) int retVal = 0; - if (argc < 2) - { - std::cerr << "[Error] Needs a path argument, the test config JSON file" << std::endl; - return -1; + autotester::debugMode = false; + autotester::screenshotsMode = false; + int argi = 1; + while (argi < argc && argv[argi][0] == '-') { + if (strcmp(argv[argi], "-d") == 0) { + autotester::debugMode = true; + } else if (strcmp(argv[argi], "-s") == 0 || strcmp(argv[argi], "--screenshots") == 0) { + autotester::screenshotsMode = true; + } else { + std::cerr << "[Error] Unknown option: " << argv[argi] << std::endl; + std::cerr << "Usage: autotester [-d] [-s|--screenshots] " << std::endl; + return -1; + } + argi++; } - if (strcmp(argv[1], "-d") == 0) - { - autotester::debugMode = true; - argv++; - } else { - autotester::debugMode = false; + if (argi >= argc) { + std::cerr << "[Error] Needs a path argument, the test config JSON file" << std::endl; + std::cerr << "Usage: autotester [-d] [-s|--screenshots] " << std::endl; + return -1; } - const std::string jsonPath(argv[1]); + const std::string jsonPath(argv[argi]); std::string jsonContents; std::ifstream ifs(jsonPath); if (ifs.good())