cc: option for artificially delaying printer (#925)

## Link to GitHub Issue or related Pull Request, if one exists
#0

## Description of change
Add an option to artificially delay the printing process (70 seconds or
so, more for holo cards) so that the minigame is triggered on the
screen.

## Testing
This commit is contained in:
bicarus
2026-10-12 10:25:34 -07:00
committed by GitHub
parent fdc7adff7f
commit c83496776e
6 changed files with 83 additions and 7 deletions
@@ -20,9 +20,8 @@ namespace games::cardconnect {
void CardConnectGame::attach() { void CardConnectGame::attach() {
Game::attach(); Game::attach();
// EXECEXE redirects Unity's raw-data writes under the game directory. fileutils::dir_create_recursive_log("cardconnect", "dev/raw/log");
fileutils::dir_create_recursive_log("cardconnect", "game/dev/raw/log"); if (!fileutils::bin_write("dev/raw/log/output_log.txt", nullptr, 0)) {
if (!fileutils::bin_write("game/dev/raw/log/output_log.txt", nullptr, 0)) {
log_warning("cardconnect", "failed to create Unity output log"); log_warning("cardconnect", "failed to create Unity output log");
} }
+67 -4
View File
@@ -9,6 +9,7 @@
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <mutex> #include <mutex>
#include <optional>
#include <vector> #include <vector>
#include "games/shared/printer.h" #include "games/shared/printer.h"
@@ -20,6 +21,7 @@ namespace games::cardconnect {
// Settings and native protocol values. // Settings and native protocol values.
bool PRINTER_DISABLED = false; bool PRINTER_DISABLED = false;
bool PRINTER_SIMULATE_DELAY = false;
static constexpr uint16_t READY = 0; static constexpr uint16_t READY = 0;
static constexpr uint16_t INVALID_PARAMETER = 1006; static constexpr uint16_t INVALID_PARAMETER = 1006;
@@ -38,6 +40,21 @@ namespace games::cardconnect {
INFO_IR_CORRECTION = 22, INFO_IR_CORRECTION = 22,
}; };
enum PrinterMode : uint8_t {
MODE_YMC_MAT = 2,
MODE_YMC_LAM = 3,
MODE_YMC_MAT_HOLO = 5,
MODE_YMC_LAM_HOLO = 6,
MODE_IR_R_YMAC_MAT = 8,
MODE_IR_R_YMAC_LAM = 9,
MODE_R_YMAC_MAT = 10,
MODE_R_YMAC_LAM = 11,
MODE_YMC_GROSS = 18,
MODE_YMC_GROSS_HOLO = 21,
MODE_IR_R_YMAC_GROSS = 24,
MODE_R_YMAC_GROSS = 25,
};
static constexpr uint16_t FORMAT_RGB = 3; static constexpr uint16_t FORMAT_RGB = 3;
static constexpr uint16_t FORMAT_BGR = 4; static constexpr uint16_t FORMAT_BGR = 4;
static constexpr uint16_t COLOR_COMPONENTS = 3; static constexpr uint16_t COLOR_COMPONENTS = 3;
@@ -47,6 +64,25 @@ namespace games::cardconnect {
static constexpr uint32_t RIBBON_REMAINING = 4096; static constexpr uint32_t RIBBON_REMAINING = 4096;
static constexpr auto PRINT_TIME = std::chrono::seconds(5); static constexpr auto PRINT_TIME = std::chrono::seconds(5);
static constexpr std::optional<std::chrono::seconds> get_mode_delay(uint8_t mode) {
// Printer::GetPrintTime adds 10s for holo and 8s per finished side.
if (mode == MODE_YMC_GROSS || mode == MODE_IR_R_YMAC_GROSS || mode == MODE_R_YMAC_GROSS) {
return std::chrono::seconds(0);
}
if (mode == MODE_YMC_MAT || mode == MODE_YMC_LAM ||
mode == MODE_IR_R_YMAC_MAT || mode == MODE_IR_R_YMAC_LAM ||
mode == MODE_R_YMAC_MAT || mode == MODE_R_YMAC_LAM) {
return std::chrono::seconds(8);
}
if (mode == MODE_YMC_GROSS_HOLO) {
return std::chrono::seconds(10);
}
if (mode == MODE_YMC_MAT_HOLO || mode == MODE_YMC_LAM_HOLO) {
return std::chrono::seconds(18);
}
return std::nullopt;
}
// Native reply layouts. // Native reply layouts.
#pragma pack(push, 1) #pragma pack(push, 1)
struct FirmwareRecord { struct FirmwareRecord {
@@ -121,6 +157,8 @@ namespace games::cardconnect {
bool receiving = false; bool receiving = false;
// Submitted jobs stay busy while waiting for this baseline. // Submitted jobs stay busy while waiting for this baseline.
bool awaiting_counter_baseline = false; bool awaiting_counter_baseline = false;
std::array<std::chrono::seconds, 2> mode_delays {};
std::chrono::seconds print_time = PRINT_TIME;
std::chrono::steady_clock::time_point next_copy; std::chrono::steady_clock::time_point next_copy;
}; };
@@ -156,7 +194,7 @@ namespace games::cardconnect {
while (job.remaining && now >= job.next_copy) { while (job.remaining && now >= job.next_copy) {
++total_count; ++total_count;
--job.remaining; --job.remaining;
job.next_copy += PRINT_TIME; job.next_copy += job.print_time;
log_info("cardconnect::printer", "job {}: total count={}, remaining={}", log_info("cardconnect::printer", "job {}: total count={}, remaining={}",
job.id, total_count, job.remaining); job.id, total_count, job.remaining);
} }
@@ -262,9 +300,10 @@ namespace games::cardconnect {
// CoMain needs its post-cleanup baseline before any copy finishes. // CoMain needs its post-cleanup baseline before any copy finishes.
if (tag == INFO_PRINT_COUNT && job.awaiting_counter_baseline) { if (tag == INFO_PRINT_COUNT && job.awaiting_counter_baseline) {
job.awaiting_counter_baseline = false; job.awaiting_counter_baseline = false;
job.next_copy = std::chrono::steady_clock::now() + PRINT_TIME; job.next_copy = std::chrono::steady_clock::now() + job.print_time;
log_info("cardconnect::printer", "job {}: counter baseline={}, starting print timer", log_info("cardconnect::printer",
job.id, total_count); "job {}: counter baseline={}, starting print timer ({}s per copy)",
job.id, total_count, job.print_time.count());
} }
return TRUE; return TRUE;
@@ -293,6 +332,25 @@ namespace games::cardconnect {
return invalid_parameter(result, "setPrinterInfo"); return invalid_parameter(result, "setPrinterInfo");
} }
if (PRINTER_SIMULATE_DELAY && (tag == INFO_FRONT_MODE || tag == INFO_BACK_MODE)) {
const auto mode = *static_cast<const uint8_t *>(buffer);
const auto delay = get_mode_delay(mode);
if (!delay) {
log_warning("cardconnect::printer", "cannot estimate delay for print mode {}", mode);
return invalid_parameter(result, "setPrinterInfo print mode");
}
if (!result) {
return set_result(result);
}
std::lock_guard lock(printer_mutex);
if (tag == INFO_FRONT_MODE) {
job.mode_delays[0] = *delay;
} else {
job.mode_delays[1] = *delay;
}
}
return set_result(result); return set_result(result);
} }
@@ -346,6 +404,10 @@ namespace games::cardconnect {
} }
job.id = next_page_id; job.id = next_page_id;
job.print_time = PRINT_TIME;
if (PRINTER_SIMULATE_DELAY) {
job.print_time = std::chrono::seconds(73) + job.mode_delays[0] + job.mode_delays[1];
}
job.error = READY; job.error = READY;
job.receiving = true; job.receiving = true;
job.sides = {}; job.sides = {};
@@ -549,6 +611,7 @@ namespace games::cardconnect {
namespace games::cardconnect { namespace games::cardconnect {
bool PRINTER_DISABLED = false; bool PRINTER_DISABLED = false;
bool PRINTER_SIMULATE_DELAY = false;
} }
#endif #endif
+1
View File
@@ -2,5 +2,6 @@
namespace games::cardconnect { namespace games::cardconnect {
extern bool PRINTER_DISABLED; extern bool PRINTER_DISABLED;
extern bool PRINTER_SIMULATE_DELAY;
void printer_attach(); void printer_attach();
} }
+3
View File
@@ -1521,6 +1521,9 @@ int main_implementation(int argc, char *argv[]) {
} }
games::cardconnect::PRINTER_DISABLED = games::cardconnect::PRINTER_DISABLED =
options[launcher::Options::CardConnectNoPrinter].value_bool(); options[launcher::Options::CardConnectNoPrinter].value_bool();
if (options[launcher::Options::CardConnectPrinterDelay].value_bool()) {
games::cardconnect::PRINTER_SIMULATE_DELAY = true;
}
if (options[launcher::Options::spice2x_EnableSMXStage].value_bool()) { if (options[launcher::Options::spice2x_EnableSMXStage].value_bool()) {
rawinput::ENABLE_SMX_STAGE = true; rawinput::ENABLE_SMX_STAGE = true;
} }
+9
View File
@@ -2502,6 +2502,15 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = std::invoke([]()
.game_name = "Card Connect", .game_name = "Card Connect",
.category = "Cab Peripherals", .category = "Cab Peripherals",
}; };
c[launcher::Options::CardConnectPrinterDelay] = {
.title = "Card Connect Simulate Printer Delay",
.name = "cardconnectprinterdelay",
.desc = "Simulate real printing time: 73 seconds per card, plus hologram and coating delays "
"(up to 99 seconds). Off by default (5 seconds per card).",
.type = OptionType::Bool,
.game_name = "Card Connect",
.category = "Cab Peripherals",
};
c[launcher::Options::CardConnectPrinterOutputPath] = { c[launcher::Options::CardConnectPrinterOutputPath] = {
.title = "Card Connect Printer Output Path", .title = "Card Connect Printer Output Path",
.name = "cardconnectprinterpath", .name = "cardconnectprinterpath",
+1
View File
@@ -256,6 +256,7 @@ namespace launcher {
UDNNoIO, UDNNoIO,
CardConnectArgs, CardConnectArgs,
CardConnectNoPrinter, CardConnectNoPrinter,
CardConnectPrinterDelay,
CardConnectPrinterOutputPath, CardConnectPrinterOutputPath,
CardConnectPrinterOutputClear, CardConnectPrinterOutputClear,
CardConnectPrinterOutputOverwrite, CardConnectPrinterOutputOverwrite,