mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
311404f56b
## Link to GitHub Issue or related Pull Request, if one exists n/a ## Description of change Adds toast notifications to the overlay. Toast notifications are transient windows (shown for about 4 seconds). These are drawn on top of the game even when the overlay is inactive (i.e., when no window is open), and does not cause any input sink behavior. Add toasts for some common user-driven actions that could use a notification, such as: * screenshot * card insert * PIN macro * API client connect/disconnect * virtual printer * screen resize toggle / scene switch Add an option to change where the toasts are displayed, or to turn it off entirely. Add SDK function for it, and add it to the samples. ## Testing Tested DDR (shown at bottom right, as is for most games) and RB (shown top right by default).
637 lines
21 KiB
C++
637 lines
21 KiB
C++
#include "printer.h"
|
|
|
|
#include <vector>
|
|
#include <thread>
|
|
|
|
#include "avs/game.h"
|
|
#include "hooks/sleephook.h"
|
|
#include "hooks/libraryhook.h"
|
|
#include "launcher/launcher.h"
|
|
#include "overlay/notifications.h"
|
|
#include "util/detour.h"
|
|
#include "util/fileutils.h"
|
|
#include "util/libutils.h"
|
|
#include "util/logging.h"
|
|
#include "util/utils.h"
|
|
|
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
|
#include "external/stb_image_write.h"
|
|
|
|
namespace games::shared {
|
|
|
|
// settings
|
|
std::vector<std::string> PRINTER_PATH;
|
|
std::vector<std::string> PRINTER_FORMAT;
|
|
int PRINTER_JPG_QUALITY = 85;
|
|
bool PRINTER_CLEAR = false;
|
|
bool PRINTER_OVERWRITE_FILE = false;
|
|
static DWORD PRINTER_TOTAL_COUNT = 1024;
|
|
static short PRINTER_PAPER_REMAIN = 4096;
|
|
|
|
typedef struct tagCPDIDinfo {
|
|
short usbNo;
|
|
short printerID;
|
|
CHAR serialNo[6];
|
|
WORD mediaType;
|
|
} CPDIDinfo, *PCPDIDinfo;
|
|
|
|
typedef struct tagCPDPaperRemainParams {
|
|
short restNum;
|
|
BOOL isWarning;
|
|
} CPDPaperRemainParams, *PCPDPaperRemainParams;
|
|
|
|
typedef struct tagCP9StatusInfo {
|
|
DWORD printerStatus;
|
|
DWORD detail;
|
|
DWORD reserved2;
|
|
DWORD reserved3;
|
|
} CP9StatusInfo, *PCP9StatusInfo;
|
|
|
|
typedef struct tagCP9FWInfo {
|
|
char version_info1[6];
|
|
char version_info2[6];
|
|
char version_info3[6];
|
|
} CP9FWInfo, *PCP9FWInfo;
|
|
|
|
typedef struct tagCP9PrinterParams2 {
|
|
DWORD flags1;
|
|
DWORD reserved1;
|
|
short mechaPreFeed;
|
|
short jobResume;
|
|
short TransferOnPrinting;
|
|
} CP9PrinterParams2, *PCP9PrinterParams2;
|
|
|
|
typedef struct tagCPDMediaType {
|
|
WORD mediaType;
|
|
WORD mediaDetail;
|
|
WORD reserved;
|
|
} CPDMediaType, *PCPDMediaType;
|
|
|
|
typedef struct tagCPAPrinterParams {
|
|
DWORD ver;
|
|
DWORD flags1;
|
|
DWORD reserved1;
|
|
POINTS printPixel;
|
|
short sidePrint;
|
|
WORD printCount;
|
|
short overCoat;
|
|
short mirror;
|
|
short marginCut;
|
|
short multiCut;
|
|
short multipanel;
|
|
short printOut;
|
|
short reserved4;
|
|
short inkSkip;
|
|
} CPAPrinterParams, *PCPAPrinterParams;
|
|
|
|
typedef struct tagCPDBandImageParams {
|
|
PVOID baseAddr;
|
|
long rowBytes;
|
|
RECT bounds;
|
|
} CPDBandImageParams, *PCPDBandImageParams;
|
|
|
|
typedef struct tagCPDContrastTable {
|
|
BYTE r[256];
|
|
BYTE g[256];
|
|
BYTE b[256];
|
|
} CPDContrastTable, *PCPDContrastTable;
|
|
|
|
typedef struct tagCPDGammaTable {
|
|
WORD r[256];
|
|
WORD g[256];
|
|
WORD b[256];
|
|
} CPDGammaTable, *PCPDGammaTable;
|
|
|
|
typedef struct tagCPAImageEffectParams {
|
|
DWORD ver;
|
|
short ColorTabel;
|
|
short DLLColorTabel;
|
|
short ContrastTabel;
|
|
const CPDContrastTable *pContTbl;
|
|
short sharpness0;
|
|
const BYTE *pSharpnessTbl;
|
|
short sharpness1;
|
|
short gamma;
|
|
short printMode;
|
|
short linesharpness;
|
|
const CPDGammaTable *pGammaTbl;
|
|
short overcoatMode;
|
|
} CPAImageEffectParams, *PCPAImageEffectParams;
|
|
|
|
enum {
|
|
PStatus_Ready = 0,
|
|
PStatus_Printing,
|
|
PStatus_MechaInit,
|
|
PStatus_FeedandCut
|
|
};
|
|
|
|
enum {
|
|
Error_NoError = 0,
|
|
Error_Something,
|
|
Error_DeviceNotFound = 100,
|
|
Error_Busy,
|
|
Error_Printing_Busy,
|
|
Error_Printing_Ready,
|
|
Error_PortBusy,
|
|
Error_GetCPDIDinfo,
|
|
Error_PrinterBusy,
|
|
Error_FuncParamError = 201,
|
|
Error_MemAllocError,
|
|
Error_Timeout,
|
|
Error_MattePrinter = 301,
|
|
Error_MatteRibbon,
|
|
Error_InvalidParam = 1000,
|
|
Error_SheetEnd,
|
|
Error_PaperEnd,
|
|
Error_PaperJam,
|
|
Error_SheetJam,
|
|
Error_SheetCassetNotSet,
|
|
Error_PaperSheetIllegal,
|
|
Error_PaperCassetNotSet,
|
|
Error_PaperSizeIllegal,
|
|
Error_PaperTrayNotSet,
|
|
Error_OHPReverse,
|
|
Error_HeatError,
|
|
Error_DewError,
|
|
Error_DoorOpen,
|
|
Error_UnusableSheet,
|
|
Error_SheetCassetIllegal,
|
|
Error_PaperRemain,
|
|
Error_SheetRemain,
|
|
Error_NotSupported,
|
|
Error_SheetMarkError = 1101,
|
|
Error_PaperJam_D,
|
|
Error_MechaError,
|
|
Error_MechaError_D,
|
|
Error_MechaInitReq,
|
|
Error_PrintingTurnOff,
|
|
Error_ContrastDataError,
|
|
Error_TableError,
|
|
Error_PrinterError,
|
|
Error_PickPosition,
|
|
Error_NoScrapBox,
|
|
Error_PrintingDoorOpen,
|
|
Error_SheetError,
|
|
Error_SheetCountError,
|
|
Error38_HeadVoltage = 1200,
|
|
Error38_HeadPosition,
|
|
Error38_FunStopped,
|
|
Error38_CutterError,
|
|
Error38_PinchRollerPosition,
|
|
Error38_HeadTemp,
|
|
Error38_MediaTemp,
|
|
Error38_PaperWindingMorterTemp,
|
|
Error38_RibbonTension = 1210,
|
|
Error38_RFID_Error = 1220,
|
|
Error38_SystemError = 1230,
|
|
Error_JInvalidParam = 1300,
|
|
Error_JMemoryFull,
|
|
Error_JPaperSizeIllegal = 1310,
|
|
Error_JLastJobError,
|
|
Error_JTimeout = 1320,
|
|
Error_JJobCancel,
|
|
Error_JUSBInterrupt,
|
|
};
|
|
|
|
static DWORD __stdcall CPU9CheckPaperRemain(PCPDPaperRemainParams pPaperRemain, PCPDIDinfo pIDInfo) {
|
|
pPaperRemain->restNum = PRINTER_PAPER_REMAIN;
|
|
pPaperRemain->isWarning = FALSE;
|
|
return Error_NoError;
|
|
}
|
|
|
|
static DWORD __stdcall CPU9CheckPrinter(PCP9StatusInfo pStInfo, PCPDIDinfo pIDInfo) {
|
|
pStInfo->printerStatus = PStatus_Ready;
|
|
pStInfo->detail = 0;
|
|
return Error_NoError;
|
|
}
|
|
|
|
static DWORD __stdcall CPU9CheckPrintEnd(DWORD meminfo, PBOOL pbisEnd, PCPDIDinfo pIDInfo) {
|
|
*pbisEnd = true;
|
|
return Error_NoError;
|
|
}
|
|
|
|
static DWORD __stdcall CPU9GetFWInfo(PCP9FWInfo pFWInfo, PCPDIDinfo pIDInfo) {
|
|
strcpy(pFWInfo->version_info1, std::string("1").c_str());
|
|
strcpy(pFWInfo->version_info2, std::string("0").c_str());
|
|
strcpy(pFWInfo->version_info3, std::string("1").c_str());
|
|
return Error_NoError;
|
|
}
|
|
|
|
static DWORD __stdcall CPU9GetMediaType(PCPDMediaType pMType, PCPDIDinfo pIDInfo) {
|
|
if (avs::game::is_model("KLP")) {
|
|
pMType->mediaType = 56;
|
|
} else {
|
|
pMType->mediaType = 2;
|
|
}
|
|
|
|
pMType->mediaDetail = 18432;
|
|
|
|
return Error_NoError;
|
|
}
|
|
|
|
static DWORD __stdcall CPU9GetTempInfo(void *pTempInfo, PCPDIDinfo pIDInfo) {
|
|
return Error_NoError;
|
|
}
|
|
|
|
static DWORD __stdcall CPU9GetTotalPrintCount(PDWORD pdwCount, PCPDIDinfo pIDInfo) {
|
|
*pdwCount = PRINTER_TOTAL_COUNT;
|
|
return Error_NoError;
|
|
}
|
|
|
|
static DWORD __stdcall CPU9PreHeat(PCPDIDinfo pIDInfo) {
|
|
return Error_NoError;
|
|
}
|
|
|
|
static DWORD __stdcall CPU9PrintJobCancel(PCPDIDinfo pIDInfo) {
|
|
return Error_NoError;
|
|
}
|
|
|
|
static DWORD __stdcall CPU9PrintOut(PDWORD pmeminfo, PCPDIDinfo pIDInfo) {
|
|
|
|
// do logic
|
|
if (PRINTER_PAPER_REMAIN > 0) {
|
|
PRINTER_TOTAL_COUNT++;
|
|
PRINTER_PAPER_REMAIN--;
|
|
return Error_NoError;
|
|
} else {
|
|
return Error_PaperRemain;
|
|
}
|
|
}
|
|
|
|
static DWORD __stdcall CPU9SetPrintParameter2(const CP9PrinterParams2 *setP, PCPDIDinfo pIDInfo) {
|
|
return Error_NoError;
|
|
}
|
|
|
|
typedef void (CALLBACK *PFNACBfunc)(DWORD dwErr, short PrintFlag, short PrintUsbNo, long nJid, int CopyNumber);
|
|
|
|
static inline std::string get_image_out_path(bool clear, std::string path, const std::string &format) {
|
|
|
|
// check path
|
|
if (path.empty()) {
|
|
log_warning("printer", "Printer Emulation output directory can't be empty. Resetting to \".\"");
|
|
path = ".";
|
|
}
|
|
|
|
// check trailing slash
|
|
if (string_ends_with(path.c_str(), "\\"))
|
|
path = std::string(path.c_str(), path.length() - 1);
|
|
|
|
// find non-existing filename
|
|
static std::string prefix = "printer_";
|
|
for (int n = 0; n < 4096; n++) {
|
|
std::ostringstream filename_s;
|
|
filename_s << path << "\\" << prefix << n << "." << format;
|
|
std::string filename = filename_s.str();
|
|
if (clear && fileutils::file_exists(filename.c_str())) {
|
|
log_info("printer", "deleting {}...", filename);
|
|
DeleteFile(filename.c_str());
|
|
if (PRINTER_OVERWRITE_FILE) {
|
|
return filename;
|
|
}
|
|
}
|
|
else if (!fileutils::file_exists(filename.c_str()))
|
|
return filename;
|
|
}
|
|
|
|
// error
|
|
if (!clear) {
|
|
log_fatal("printer", "could not find path");
|
|
}
|
|
|
|
return "DUMMY";
|
|
}
|
|
|
|
static inline bool process_image_print(const CPDBandImageParams *pBandImage) {
|
|
|
|
// log
|
|
log_info("printer", "processing incoming print job");
|
|
|
|
// get image bounds
|
|
int image_width = pBandImage->bounds.right - pBandImage->bounds.left;
|
|
int image_height = pBandImage->bounds.bottom - pBandImage->bounds.top;
|
|
|
|
// check bounds
|
|
if (image_width <= 0 || image_height <= 0) {
|
|
log_warning("printer", "invalid image size: {}x{}", image_width, image_height);
|
|
return false;
|
|
}
|
|
|
|
// check rowBytes
|
|
if (pBandImage->rowBytes < 0 || pBandImage->rowBytes != image_width * 3) {
|
|
log_warning("printer", "unsupported image data layout: {}", pBandImage->rowBytes);
|
|
return false;
|
|
}
|
|
|
|
// make a copy of the image data
|
|
auto image_data = new uint8_t[image_width * image_height * 3];
|
|
memcpy(image_data, pBandImage->baseAddr, (size_t) (image_width * image_height * 3));
|
|
|
|
// convert BGR to RGB
|
|
log_misc("printer", "converting BGR to RGB...");
|
|
for (int pixel = 0; pixel < image_width * image_height; pixel++) {
|
|
int index = pixel * 3;
|
|
uint8_t tmp = image_data[index];
|
|
image_data[index] = image_data[index + 2];
|
|
image_data[index + 2] = tmp;
|
|
}
|
|
|
|
if (avs::game::is_model({"KLP", "KFC", "NCG"})) {
|
|
// rotate image clockwise
|
|
log_misc("printer", "rotate clockwise...");
|
|
auto rotated = new uint8_t[image_width * image_height * 3];
|
|
for (int x = 0; x < image_width; x++) {
|
|
for (int y = 0; y < image_height; y++) {
|
|
int index1 = (y * image_width + x) * 3;
|
|
int index2 = (x * image_height + y) * 3;
|
|
rotated[index2 + 0] = image_data[index1 + 0];
|
|
rotated[index2 + 1] = image_data[index1 + 1];
|
|
rotated[index2 + 2] = image_data[index1 + 2];
|
|
}
|
|
}
|
|
delete[] image_data;
|
|
image_data = rotated;
|
|
std::swap(image_width, image_height);
|
|
|
|
} else {
|
|
// flip horizontally
|
|
log_misc("printer", "flip horizontally...");
|
|
for (int x = 0; x < image_width / 2; x++) {
|
|
for (int y = 0; y < image_height; y++) {
|
|
int index1 = (y * image_width + x) * 3;
|
|
int index2 = (y * image_width + image_width - x - 1) * 3;
|
|
uint8_t r = image_data[index1 + 0];
|
|
uint8_t g = image_data[index1 + 1];
|
|
uint8_t b = image_data[index1 + 2];
|
|
image_data[index1 + 0] = image_data[index2 + 0];
|
|
image_data[index1 + 1] = image_data[index2 + 1];
|
|
image_data[index1 + 2] = image_data[index2 + 2];
|
|
image_data[index2 + 0] = r;
|
|
image_data[index2 + 1] = g;
|
|
image_data[index2 + 2] = b;
|
|
}
|
|
}
|
|
}
|
|
|
|
// iterate folders
|
|
log_misc("printer", "writing files...");
|
|
for (const auto &path : PRINTER_PATH) {
|
|
for (const auto &format : PRINTER_FORMAT) {
|
|
|
|
// get image path
|
|
std::string image_path = get_image_out_path(PRINTER_OVERWRITE_FILE, path, format);
|
|
bool success = false;
|
|
|
|
// call write function depending on format
|
|
if (format == "png" && stbi_write_png(
|
|
image_path.c_str(), image_width, image_height, 3, image_data, image_width * 3))
|
|
success = true;
|
|
if (format == "bmp" && stbi_write_bmp(
|
|
image_path.c_str(), image_width, image_height, 3, image_data))
|
|
success = true;
|
|
if (format == "tga" && stbi_write_tga(
|
|
image_path.c_str(), image_width, image_height, 3, image_data))
|
|
success = true;
|
|
if (format == "jpg" && stbi_write_jpg(
|
|
image_path.c_str(), image_width, image_height, 3, image_data, PRINTER_JPG_QUALITY))
|
|
success = true;
|
|
|
|
// logging
|
|
if (success) {
|
|
log_info("printer", "printer emulation has written an image to {}", image_path);
|
|
overlay::notifications::add(
|
|
overlay::notifications::Severity::Success,
|
|
fmt::format("Printer: saved {}", fileutils::basename(image_path)));
|
|
} else {
|
|
log_warning("printer", "printer emulation failed to write image to {}", image_path);
|
|
overlay::notifications::add(
|
|
overlay::notifications::Severity::Error,
|
|
fmt::format("Printer: failed to write {}", fileutils::basename(image_path)));
|
|
}
|
|
}
|
|
}
|
|
|
|
// clean up
|
|
delete[] image_data;
|
|
return true;
|
|
}
|
|
|
|
static DWORD __stdcall CPUASendImage(
|
|
const CPDBandImageParams *pBandImage,
|
|
const CPAPrinterParams *setP,
|
|
const CPAImageEffectParams *piep,
|
|
PCPDIDinfo pIDInfo
|
|
) {
|
|
// process image
|
|
if (!process_image_print(pBandImage)) {
|
|
return Error_InvalidParam;
|
|
}
|
|
|
|
return Error_NoError;
|
|
}
|
|
|
|
/*
|
|
* This is the function which seems to get called from the game.
|
|
* Default card layout parameters:
|
|
* rowBytes = 3216
|
|
* bounds.left = 0
|
|
* bounds.top = 0
|
|
* bounds.right = 1072
|
|
* bounds.bottom = 712
|
|
*/
|
|
static DWORD __stdcall CPUASendImagePrint(const CPAPrinterParams *setP, const CPDBandImageParams *pBandImage,
|
|
const CPAImageEffectParams *piep, BOOL memClear, PFNACBfunc pfncb,
|
|
long nJid, PCPDIDinfo pIDInfo) {
|
|
/*
|
|
* From documentation: rowBytes
|
|
* Number of bits a line of image data. Usually, in case of a bitmap file of 24bit, it is
|
|
* (bmInfoHeader.biWidth * 3 + 3) / 4 * 4
|
|
* It scans up from the lower left in case of a positive numeric (bitmap file standard).
|
|
* In this case, the address at the lower left of image data is usually set in baseAddr.
|
|
* It scans below from the upper left in the case of a negative numeric. In this case,
|
|
* The address in the upper left of image data is usually set in baseAddr.
|
|
*/
|
|
|
|
// process image
|
|
if (!process_image_print(pBandImage)) {
|
|
return Error_InvalidParam;
|
|
}
|
|
|
|
// fire up printer thread
|
|
// the game fires up a listener around 4 seconds after the call
|
|
WORD printCount = setP->printCount;
|
|
short usbNo = pIDInfo->usbNo;
|
|
std::thread t([printCount, pfncb, usbNo, nJid]() {
|
|
for (int print_no = 1; print_no <= printCount; print_no++) {
|
|
|
|
// wait for game listener
|
|
Sleep(4000);
|
|
|
|
// do logic
|
|
if (PRINTER_PAPER_REMAIN > 0) {
|
|
PRINTER_TOTAL_COUNT++;
|
|
PRINTER_PAPER_REMAIN--;
|
|
pfncb(Error_NoError, 0, usbNo, nJid, print_no);
|
|
} else {
|
|
pfncb(Error_PaperRemain, 0, usbNo, nJid, print_no);
|
|
}
|
|
}
|
|
});
|
|
|
|
// detach thread so it will keep running
|
|
t.detach();
|
|
|
|
return Error_NoError;
|
|
}
|
|
|
|
/*
|
|
* Probably irrelevant, doesn't seem to get called by the game.
|
|
*/
|
|
static DWORD __stdcall CPUASendImagePrint2(
|
|
const CPAPrinterParams *setP,
|
|
const CPDBandImageParams *pBandImage,
|
|
const CPAImageEffectParams *piep,
|
|
BOOL memClear,
|
|
BOOL sendOnPrn,
|
|
PFNACBfunc pfncb,
|
|
long nJid,
|
|
PCPDIDinfo pIDInfo
|
|
) {
|
|
// forward to other function
|
|
return CPUASendImagePrint(setP, pBandImage, piep, memClear, pfncb, nJid, pIDInfo);
|
|
}
|
|
|
|
static DWORD __stdcall CPUASetPrintParameter(
|
|
const CPAPrinterParams *setP,
|
|
CPAImageEffectParams *piep,
|
|
BOOL memClear,
|
|
PDWORD pmeminfo,
|
|
PCPDIDinfo pIDInfo
|
|
) {
|
|
return Error_NoError;
|
|
}
|
|
|
|
static DWORD __stdcall CPUXSearchPrinters(
|
|
PCPDIDinfo pIDInfo,
|
|
DWORD infoSize,
|
|
LPDWORD pSizeNeeded,
|
|
LPDWORD pInfoNum
|
|
) {
|
|
// set information number
|
|
// (LovePlus needs this to determine how many info structures to allocate)
|
|
*pInfoNum = 1;
|
|
|
|
// check info size
|
|
if (infoSize != 12) {
|
|
*pSizeNeeded = 12;
|
|
|
|
return Error_GetCPDIDinfo;
|
|
}
|
|
|
|
// set printer information
|
|
pIDInfo->usbNo = 1;
|
|
pIDInfo->printerID = 1;
|
|
memset(pIDInfo->serialNo, 'F', 5);
|
|
memset(pIDInfo->serialNo + 5, 0, 1);
|
|
pIDInfo->mediaType = 2;
|
|
|
|
// LovePlus
|
|
if (avs::game::is_model("KLP")) {
|
|
|
|
// LovePlus uses a different media type
|
|
pIDInfo->mediaType = 56;
|
|
}
|
|
|
|
// Otoca D'or
|
|
if (avs::game::is_model("NCG")) {
|
|
|
|
// requires a specific printer ID
|
|
pIDInfo->printerID = 2160;
|
|
}
|
|
|
|
return Error_NoError;
|
|
}
|
|
|
|
static void __stdcall CPUXInit() {
|
|
log_info("printer", "CPUXInit called");
|
|
}
|
|
|
|
void printer_attach() {
|
|
log_info("printer", "SpiceTools Printer");
|
|
|
|
// default parameters
|
|
if (PRINTER_PATH.empty()) {
|
|
PRINTER_PATH.emplace_back(".");
|
|
}
|
|
if (PRINTER_FORMAT.empty()) {
|
|
PRINTER_FORMAT.emplace_back("png");
|
|
}
|
|
|
|
// validate file formats
|
|
for (const auto &format : PRINTER_FORMAT) {
|
|
if (format != "png" &&
|
|
format != "bmp" &&
|
|
format != "tga" &&
|
|
format != "jpg")
|
|
{
|
|
log_fatal("printer", "unknown file format: {}", format);
|
|
}
|
|
}
|
|
|
|
// validate JPEG quality
|
|
if (PRINTER_JPG_QUALITY <= 0 || PRINTER_JPG_QUALITY > 100) {
|
|
log_fatal("printer", "invalid JPEG quality setting (1-100): {}",
|
|
PRINTER_JPG_QUALITY);
|
|
}
|
|
|
|
// clear
|
|
if (PRINTER_CLEAR) {
|
|
PRINTER_CLEAR = false;
|
|
for (const auto &path : PRINTER_PATH) {
|
|
for (const auto &format : PRINTER_FORMAT) {
|
|
get_image_out_path(true, path, format);
|
|
}
|
|
}
|
|
}
|
|
|
|
// IAT hooks
|
|
detour::iat_try("CPU9CheckPaperRemain", CPU9CheckPaperRemain);
|
|
detour::iat_try("CPU9CheckPrinter", CPU9CheckPrinter);
|
|
detour::iat_try("CPU9CheckPrintEnd", CPU9CheckPrintEnd);
|
|
detour::iat_try("CPU9GetFWInfo", CPU9GetFWInfo);
|
|
detour::iat_try("CPU9GetMediaType", CPU9GetMediaType);
|
|
detour::iat_try("CPU9GetTempInfo", CPU9GetTempInfo);
|
|
detour::iat_try("CPU9GetTotalPrintCount", CPU9GetTotalPrintCount);
|
|
detour::iat_try("CPU9PreHeat", CPU9PreHeat);
|
|
detour::iat_try("CPU9PrintJobCancel", CPU9PrintJobCancel);
|
|
detour::iat_try("CPU9PrintOut", CPU9PrintOut);
|
|
detour::iat_try("CPU9SetPrintParameter2", CPU9SetPrintParameter2);
|
|
detour::iat_try("CPUASendImage", CPUASendImage);
|
|
detour::iat_try("CPUASendImagePrint", CPUASendImagePrint);
|
|
detour::iat_try("CPUASendImagePrint2", CPUASendImagePrint2);
|
|
detour::iat_try("CPUASetPrintParameter", CPUASetPrintParameter);
|
|
detour::iat_try("CPUXInit", CPUXInit);
|
|
detour::iat_try("CPUXSearchPrinters", CPUXSearchPrinters);
|
|
|
|
// library hook
|
|
libraryhook_hook_library("CPUSBXPKM.DLL", GetModuleHandle(nullptr));
|
|
libraryhook_hook_proc("CPU9CheckPaperRemain", CPU9CheckPaperRemain);
|
|
libraryhook_hook_proc("CPU9CheckPrinter", CPU9CheckPrinter);
|
|
libraryhook_hook_proc("CPU9CheckPrintEnd", CPU9CheckPrintEnd);
|
|
libraryhook_hook_proc("CPU9GetFWInfo", CPU9GetFWInfo);
|
|
libraryhook_hook_proc("CPU9GetMediaType", CPU9GetMediaType);
|
|
libraryhook_hook_proc("CPU9GetTempInfo", CPU9GetTempInfo);
|
|
libraryhook_hook_proc("CPU9GetTotalPrintCount", CPU9GetTotalPrintCount);
|
|
libraryhook_hook_proc("CPU9PreHeat", CPU9PreHeat);
|
|
libraryhook_hook_proc("CPU9PrintJobCancel", CPU9PrintJobCancel);
|
|
libraryhook_hook_proc("CPU9PrintOut", CPU9PrintOut);
|
|
libraryhook_hook_proc("CPU9SetPrintParameter2", CPU9SetPrintParameter2);
|
|
libraryhook_hook_proc("CPUASendImage", CPUASendImage);
|
|
libraryhook_hook_proc("CPUASendImagePrint", CPUASendImagePrint);
|
|
libraryhook_hook_proc("CPUASendImagePrint2", CPUASendImagePrint2);
|
|
libraryhook_hook_proc("CPUASetPrintParameter", CPUASetPrintParameter);
|
|
libraryhook_hook_proc("CPUXInit", CPUXInit);
|
|
libraryhook_hook_proc("CPUXSearchPrinters", CPUXSearchPrinters);
|
|
libraryhook_enable(avs::game::DLL_INSTANCE);
|
|
}
|
|
}
|