From 74e9bcd0844fcee308688d7f2f9c39cdba665977 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 26 Feb 2024 03:15:44 +0600 Subject: [PATCH 1/3] Add Novell NetWare 2.x Card Key emulation --- src/86box.c | 4 + src/config.c | 12 ++- src/device/CMakeLists.txt | 3 +- src/device/novell_cardkey.c | 115 +++++++++++++++++++++++++ src/include/86box/86box.h | 1 + src/include/86box/novell_cardkey.h | 37 ++++++++ src/qt/qt_settingsotherperipherals.cpp | 24 +++++- src/qt/qt_settingsotherperipherals.hpp | 4 + src/qt/qt_settingsotherperipherals.ui | 70 +++++++++++---- 9 files changed, 244 insertions(+), 26 deletions(-) create mode 100644 src/device/novell_cardkey.c create mode 100644 src/include/86box/novell_cardkey.h diff --git a/src/86box.c b/src/86box.c index 8218c208c..9e3bc9dca 100644 --- a/src/86box.c +++ b/src/86box.c @@ -66,6 +66,7 @@ #include <86box/bugger.h> #include <86box/postcard.h> #include <86box/unittester.h> +#include <86box/novell_cardkey.h> #include <86box/isamem.h> #include <86box/isartc.h> #include <86box/lpt.h> @@ -173,6 +174,7 @@ char video_shader[512] = { '\0' }; /* (C) video * bool serial_passthrough_enabled[SERIAL_MAX] = { 0, 0, 0, 0 }; /* (C) activation and kind of pass-through for serial ports */ int bugger_enabled = 0; /* (C) enable ISAbugger */ +int novell_keycard_enabled = 0; /* (C) enable Novell NetWare 2.x key card emulation. */ int postcard_enabled = 0; /* (C) enable POST card */ int unittester_enabled = 0; /* (C) enable unit tester device */ int isamem_type[ISAMEM_MAX] = { 0, 0, 0, 0 }; /* (C) enable ISA mem cards */ @@ -1226,6 +1228,8 @@ pc_reset_hard_init(void) device_add(&postcard_device); if (unittester_enabled) device_add(&unittester_device); + if (novell_keycard_enabled) + device_add(&novell_keycard_device); if (IS_ARCH(machine, MACHINE_BUS_PCI)) { pci_register_cards(); diff --git a/src/config.c b/src/config.c index 3e4fd7222..e4a86d7bd 100644 --- a/src/config.c +++ b/src/config.c @@ -1568,9 +1568,10 @@ load_other_peripherals(void) char *p; char temp[512]; - bugger_enabled = !!ini_section_get_int(cat, "bugger_enabled", 0); - postcard_enabled = !!ini_section_get_int(cat, "postcard_enabled", 0); - unittester_enabled = !!ini_section_get_int(cat, "unittester_enabled", 0); + bugger_enabled = !!ini_section_get_int(cat, "bugger_enabled", 0); + postcard_enabled = !!ini_section_get_int(cat, "postcard_enabled", 0); + unittester_enabled = !!ini_section_get_int(cat, "unittester_enabled", 0); + novell_keycard_enabled = !!ini_section_get_int(cat, "novell_keycard_enabled", 0); for (uint8_t c = 0; c < ISAMEM_MAX; c++) { sprintf(temp, "isamem%d_type", c); @@ -2365,6 +2366,11 @@ save_other_peripherals(void) else ini_section_set_int(cat, "unittester_enabled", unittester_enabled); + if (novell_keycard_enabled == 0) + ini_section_delete_var(cat, "novell_keycard_enabled"); + else + ini_section_set_int(cat, "novell_keycard_enabled", novell_keycard_enabled); + for (uint8_t c = 0; c < ISAMEM_MAX; c++) { sprintf(temp, "isamem%d_type", c); if (isamem_type[c] == 0) diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 9c5705325..c0719af2a 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -22,7 +22,8 @@ add_library(dev OBJECT bugger.c cassette.c cartridge.c hasp.c hwm.c hwm_lm75.c h kbc_at.c kbc_at_dev.c keyboard_at.c mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c nec_mate_unk.c phoenix_486_jumper.c - serial_passthrough.c) + serial_passthrough.c + novell_cardkey.c) if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") target_link_libraries(86Box atomic) diff --git a/src/device/novell_cardkey.c b/src/device/novell_cardkey.c new file mode 100644 index 000000000..ad3f0a5ea --- /dev/null +++ b/src/device/novell_cardkey.c @@ -0,0 +1,115 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the Novell NetWare 2.x Key Card, which + * was used for anti-piracy protection. + * + * + * Authors: Cacodemon345 + * + * Copyright 2024 Cacodemon345. + */ + +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/plat.h> +#include <86box/novell_cardkey.h> + +typedef struct novell_cardkey_t +{ + char serial_number_str[13]; +} novell_cardkey_t; + +static uint8_t +novell_cardkey_read(uint16_t port, void *priv) +{ + novell_cardkey_t* cardkey = (novell_cardkey_t*)priv; + uint8_t val = 0x00; + switch (port) { + case 0x23A: + val = ((cardkey->serial_number_str[11] - '0') << 4) | ((cardkey->serial_number_str[9] - '0')); + break; + case 0x23B: + val = ((cardkey->serial_number_str[10] - '0') << 4) | ((cardkey->serial_number_str[8] - '0')); + break; + + case 0x23C: + val = ((cardkey->serial_number_str[4] - '0') << 4) | ((cardkey->serial_number_str[2] - '0')); + break; + case 0x23D: + val = ((cardkey->serial_number_str[1] - '0') << 4) | ((cardkey->serial_number_str[6] - '0')); + break; + case 0x23E: + val = ((cardkey->serial_number_str[0] - '0') << 4) | ((cardkey->serial_number_str[7] - '0')); + break; + case 0x23F: + val = ((cardkey->serial_number_str[3] - '0') << 4) | ((cardkey->serial_number_str[5] - '0')); + break; + } + return val ^ 0xFF; +} + +void* novell_cardkey_init(const device_t* info) +{ + char sernumstr[13] = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 0 }; + int i = 0; + novell_cardkey_t* cardkey = calloc(1, sizeof(novell_cardkey_t)); + + strncpy(sernumstr, device_get_config_string("serial_number"), sizeof(sernumstr) - 1); + + for (i = 0; i < sizeof(sernumstr); i++) { + if (sernumstr[i] > '8' || sernumstr[i] < '0') + sernumstr[i] = '0'; + } + sernumstr[12] = 0; + strncpy(cardkey->serial_number_str, sernumstr, sizeof(sernumstr)); + io_sethandler(NOVELL_KEYCARD_ADDR, NOVELL_KEYCARD_ADDRLEN, novell_cardkey_read, NULL, NULL, NULL, NULL, NULL, cardkey); + return cardkey; +} + +void novell_cardkey_close(void* priv) +{ + free(priv); +} + +static const device_config_t keycard_config[] = { + // clang-format off + { + .name = "serial_number", + .description = "Serial Number", + .type = CONFIG_STRING, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { 0 } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t novell_keycard_device = { + .name = "Novell Netware 2.x Key Card", + .internal_name = "mssystems", + .flags = DEVICE_ISA, + .local = 0, + .init = novell_cardkey_init, + .close = novell_cardkey_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = keycard_config +}; \ No newline at end of file diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 20f3fffcc..8a11cc610 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -124,6 +124,7 @@ extern int video_framerate; /* (C) video */ extern int gfxcard[2]; /* (C) graphics/video card */ extern char video_shader[512]; /* (C) video */ extern int bugger_enabled; /* (C) enable ISAbugger */ +extern int novell_keycard_enabled; /* (C) enable Novell NetWare 2.x key card emulation. */ extern int postcard_enabled; /* (C) enable POST card */ extern int unittester_enabled; /* (C) enable unit tester device */ extern int isamem_type[]; /* (C) enable ISA mem cards */ diff --git a/src/include/86box/novell_cardkey.h b/src/include/86box/novell_cardkey.h new file mode 100644 index 000000000..8ad3eabab --- /dev/null +++ b/src/include/86box/novell_cardkey.h @@ -0,0 +1,37 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the Novell NetWare 2.x Key Card, which + * was used for anti-piracy protection. + * + * + * Authors: Cacodemon345 + * + * Copyright 2024 Cacodemon345. + */ +#ifndef NOVELL_KEYCARD_H +#define NOVELL_KEYCARD_H + +/* I/O port range used. */ +#define NOVELL_KEYCARD_ADDR 0x23a +#define NOVELL_KEYCARD_ADDRLEN 6 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Global variables. */ +extern const device_t novell_keycard_device; + +/* Functions. */ + +#ifdef __cplusplus +} +#endif + +#endif /*BUGGER_H*/ \ No newline at end of file diff --git a/src/qt/qt_settingsotherperipherals.cpp b/src/qt/qt_settingsotherperipherals.cpp index f662b644c..3904b653a 100644 --- a/src/qt/qt_settingsotherperipherals.cpp +++ b/src/qt/qt_settingsotherperipherals.cpp @@ -24,6 +24,7 @@ extern "C" { #include <86box/isamem.h> #include <86box/isartc.h> #include <86box/unittester.h> +#include <86box/novell_cardkey.h> } #include "qt_deviceconfig.hpp" @@ -46,7 +47,10 @@ SettingsOtherPeripherals::onCurrentMachineChanged(int machineId) ui->checkBoxISABugger->setChecked((machineHasIsa && (bugger_enabled > 0)) ? true : false); ui->checkBoxPOSTCard->setChecked(postcard_enabled > 0 ? true : false); ui->checkBoxUnitTester->setChecked(unittester_enabled > 0 ? true : false); + ui->checkBoxKeyCard->setChecked((machineHasIsa && (novell_keycard_enabled > 0)) ? true : false); ui->checkBoxISABugger->setEnabled(machineHasIsa); + ui->checkBoxKeyCard->setEnabled(machineHasIsa); + ui->pushButtonConfigureKeyCard->setEnabled(novell_keycard_enabled > 0); ui->pushButtonConfigureUT->setEnabled(unittester_enabled > 0); ui->comboBoxRTC->setEnabled(machineHasIsa); ui->pushButtonConfigureRTC->setEnabled(machineHasIsa); @@ -115,10 +119,11 @@ void SettingsOtherPeripherals::save() { /* Other peripherals category */ - bugger_enabled = ui->checkBoxISABugger->isChecked() ? 1 : 0; - postcard_enabled = ui->checkBoxPOSTCard->isChecked() ? 1 : 0; - unittester_enabled = ui->checkBoxUnitTester->isChecked() ? 1 : 0; - isartc_type = ui->comboBoxRTC->currentData().toInt(); + bugger_enabled = ui->checkBoxISABugger->isChecked() ? 1 : 0; + postcard_enabled = ui->checkBoxPOSTCard->isChecked() ? 1 : 0; + unittester_enabled = ui->checkBoxUnitTester->isChecked() ? 1 : 0; + novell_keycard_enabled = ui->checkBoxKeyCard->isChecked() ? 1 : 0; + isartc_type = ui->comboBoxRTC->currentData().toInt(); /* ISA memory boards. */ for (int i = 0; i < ISAMEM_MAX; i++) { @@ -213,3 +218,14 @@ SettingsOtherPeripherals::on_pushButtonConfigureUT_clicked() { DeviceConfig::ConfigureDevice(&unittester_device); } + +void SettingsOtherPeripherals::on_pushButtonConfigureKeyCard_clicked() +{ + DeviceConfig::ConfigureDevice(&novell_keycard_device); +} + +void SettingsOtherPeripherals::on_checkBoxKeyCard_stateChanged(int arg1) +{ + ui->pushButtonConfigureKeyCard->setEnabled(arg1 != 0); +} + diff --git a/src/qt/qt_settingsotherperipherals.hpp b/src/qt/qt_settingsotherperipherals.hpp index feaa7a001..d5804a68b 100644 --- a/src/qt/qt_settingsotherperipherals.hpp +++ b/src/qt/qt_settingsotherperipherals.hpp @@ -33,6 +33,10 @@ private slots: void on_checkBoxUnitTester_stateChanged(int arg1); void on_pushButtonConfigureUT_clicked(); + void on_pushButtonConfigureKeyCard_clicked(); + + void on_checkBoxKeyCard_stateChanged(int arg1); + private: Ui::SettingsOtherPeripherals *ui; int machineId { 0 }; diff --git a/src/qt/qt_settingsotherperipherals.ui b/src/qt/qt_settingsotherperipherals.ui index af953a984..41df2deac 100644 --- a/src/qt/qt_settingsotherperipherals.ui +++ b/src/qt/qt_settingsotherperipherals.ui @@ -37,15 +37,15 @@ - - 30 - 0 0 + + 30 + @@ -72,15 +72,15 @@ - - 30 - 0 0 + + 30 + @@ -113,15 +113,15 @@ - - 30 - 0 0 + + 30 + @@ -133,28 +133,28 @@ - - 30 - 0 0 + + 30 + - - 30 - 0 0 + + 30 + @@ -196,15 +196,15 @@ - - 86Box Unit Tester - 0 0 + + 86Box Unit Tester + @@ -216,6 +216,40 @@ + + + + 0 + + + + + Novell NetWare 2.x Key Card + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Configure + + + + + From 1be08f9a9f5d4419ff2a28767de2077911f949f5 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 26 Feb 2024 13:43:35 +0600 Subject: [PATCH 2/3] Handle Application Number part correctly --- src/device/novell_cardkey.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/device/novell_cardkey.c b/src/device/novell_cardkey.c index ad3f0a5ea..54b716cc3 100644 --- a/src/device/novell_cardkey.c +++ b/src/device/novell_cardkey.c @@ -39,10 +39,10 @@ novell_cardkey_read(uint16_t port, void *priv) uint8_t val = 0x00; switch (port) { case 0x23A: - val = ((cardkey->serial_number_str[11] - '0') << 4) | ((cardkey->serial_number_str[9] - '0')); + val = (((cardkey->serial_number_str[11] > 'A') ? ((cardkey->serial_number_str[11] - 'A') + 10) : (cardkey->serial_number_str[11] - '0')) << 4) | (((cardkey->serial_number_str[9] > 'A') ? ((cardkey->serial_number_str[9] - 'A') + 10) : (cardkey->serial_number_str[9] - '0')) << 4); break; case 0x23B: - val = ((cardkey->serial_number_str[10] - '0') << 4) | ((cardkey->serial_number_str[8] - '0')); + val = (((cardkey->serial_number_str[10] > 'A') ? ((cardkey->serial_number_str[10] - 'A') + 10) : (cardkey->serial_number_str[10] - '0')) << 4) | (((cardkey->serial_number_str[8] > 'A') ? ((cardkey->serial_number_str[8] - 'A') + 10) : (cardkey->serial_number_str[8] - '0')) << 4); break; case 0x23C: @@ -69,7 +69,7 @@ void* novell_cardkey_init(const device_t* info) strncpy(sernumstr, device_get_config_string("serial_number"), sizeof(sernumstr) - 1); - for (i = 0; i < sizeof(sernumstr); i++) { + for (i = 0; i < sizeof(sernumstr) - 4; i++) { if (sernumstr[i] > '8' || sernumstr[i] < '0') sernumstr[i] = '0'; } From 8363144dbf9b8d7c2333ab4d62d08d454ea890b3 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 26 Feb 2024 13:49:13 +0600 Subject: [PATCH 3/3] More validation --- src/device/novell_cardkey.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/device/novell_cardkey.c b/src/device/novell_cardkey.c index 54b716cc3..9f489cad7 100644 --- a/src/device/novell_cardkey.c +++ b/src/device/novell_cardkey.c @@ -73,6 +73,14 @@ void* novell_cardkey_init(const device_t* info) if (sernumstr[i] > '8' || sernumstr[i] < '0') sernumstr[i] = '0'; } + if (sernumstr[8] > 'F' || sernumstr[8] < '0') + sernumstr[8] = '0'; + if (sernumstr[9] > 'F' || sernumstr[9] < '0') + sernumstr[9] = '0'; + if (sernumstr[10] > 'F' || sernumstr[10] < '0') + sernumstr[10] = '0'; + if (sernumstr[11] > 'F' || sernumstr[11] < '0') + sernumstr[11] = '0'; sernumstr[12] = 0; strncpy(cardkey->serial_number_str, sernumstr, sizeof(sernumstr)); io_sethandler(NOVELL_KEYCARD_ADDR, NOVELL_KEYCARD_ADDRLEN, novell_cardkey_read, NULL, NULL, NULL, NULL, NULL, cardkey);