mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-10-15 20:46:55 +08:00
1002 lines
33 KiB
C++
1002 lines
33 KiB
C++
/*
|
|
* Copyright (C) 2002-2021 The DOSBox Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include "control.h"
|
|
#include "dosbox.h"
|
|
#include "callback.h"
|
|
#include "regs.h"
|
|
#include "mem.h"
|
|
#include "bios.h"
|
|
#include "dos_inc.h"
|
|
#include "support.h"
|
|
#include "parport.h"
|
|
#include "drives.h" //Wildcmp
|
|
#include "render.h"
|
|
/* Include all the devices */
|
|
|
|
#include "dev_con.h"
|
|
#include <fstream>
|
|
|
|
DOS_Device * Devices[DOS_DEVICES] = {NULL};
|
|
extern int dos_clipboard_device_access;
|
|
extern const char * dos_clipboard_device_name;
|
|
bool isDBCSCP(), shiftjis_lead_byte(int c);
|
|
bool Network_IsNetworkResource(const char * filename);
|
|
bool CodePageGuestToHostUTF16(uint16_t *d/*CROSS_LEN*/,const char *s/*CROSS_LEN*/);
|
|
|
|
struct ExtDeviceData {
|
|
uint16_t attribute;
|
|
uint16_t segment;
|
|
uint16_t strategy;
|
|
uint16_t interrupt;
|
|
};
|
|
|
|
class DOS_ExtDevice : public DOS_Device {
|
|
public:
|
|
DOS_ExtDevice(const char *name, uint16_t seg, uint16_t off) {
|
|
SetName(name);
|
|
ext.attribute = real_readw(seg, off + 4);
|
|
ext.segment = seg;
|
|
ext.strategy = real_readw(seg, off + 6);
|
|
ext.interrupt = real_readw(seg, off + 8);
|
|
}
|
|
virtual bool Read(uint8_t * data,uint16_t * size);
|
|
virtual bool Write(const uint8_t * data,uint16_t * size);
|
|
virtual bool Seek(uint32_t * pos,uint32_t type);
|
|
virtual bool Close();
|
|
virtual uint16_t GetInformation(void);
|
|
virtual bool ReadFromControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode);
|
|
virtual bool WriteToControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode);
|
|
virtual uint8_t GetStatus(bool input_flag);
|
|
bool CheckSameDevice(uint16_t seg, uint16_t s_off, uint16_t i_off);
|
|
private:
|
|
struct ExtDeviceData ext;
|
|
|
|
uint16_t CallDeviceFunction(uint8_t command, uint8_t length, PhysPt bufptr, uint16_t size);
|
|
};
|
|
|
|
bool DOS_ExtDevice::CheckSameDevice(uint16_t seg, uint16_t s_off, uint16_t i_off) {
|
|
if(seg == ext.segment && s_off == ext.strategy && i_off == ext.interrupt) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
uint16_t DOS_ExtDevice::CallDeviceFunction(uint8_t command, uint8_t length, PhysPt bufptr, uint16_t size) {
|
|
uint16_t oldbx = reg_bx;
|
|
uint16_t oldes = SegValue(es);
|
|
|
|
real_writeb(dos.dcp, 0, length);
|
|
real_writeb(dos.dcp, 1, 0);
|
|
real_writeb(dos.dcp, 2, command);
|
|
real_writew(dos.dcp, 3, 0);
|
|
real_writed(dos.dcp, 5, 0);
|
|
real_writed(dos.dcp, 9, 0);
|
|
real_writeb(dos.dcp, 13, 0);
|
|
real_writew(dos.dcp, 14, (uint16_t)(bufptr & 0x000f));
|
|
real_writew(dos.dcp, 16, (uint16_t)(bufptr >> 4));
|
|
real_writew(dos.dcp, 18, size);
|
|
|
|
reg_bx = 0;
|
|
SegSet16(es, dos.dcp);
|
|
CALLBACK_RunRealFar(ext.segment, ext.strategy);
|
|
CALLBACK_RunRealFar(ext.segment, ext.interrupt);
|
|
reg_bx = oldbx;
|
|
SegSet16(es, oldes);
|
|
|
|
return real_readw(dos.dcp, 3);
|
|
}
|
|
|
|
bool DOS_ExtDevice::ReadFromControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode) {
|
|
if(ext.attribute & 0x4000) {
|
|
// IOCTL INPUT
|
|
if((CallDeviceFunction(3, 26, bufptr, size) & 0x8000) == 0) {
|
|
*retcode = real_readw(dos.dcp, 18);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool DOS_ExtDevice::WriteToControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode) {
|
|
if(ext.attribute & 0x4000) {
|
|
// IOCTL OUTPUT
|
|
if((CallDeviceFunction(12, 26, bufptr, size) & 0x8000) == 0) {
|
|
*retcode = real_readw(dos.dcp, 18);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool DOS_ExtDevice::Read(uint8_t * data,uint16_t * size) {
|
|
PhysPt bufptr = (dos.dcp << 4) | 32;
|
|
for(uint16_t no = 0 ; no < *size ; no++) {
|
|
// INPUT
|
|
if((CallDeviceFunction(4, 26, bufptr, 1) & 0x8000)) {
|
|
return false;
|
|
} else {
|
|
if(real_readw(dos.dcp, 18) != 1) {
|
|
return false;
|
|
}
|
|
*data++ = mem_readb(bufptr);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool DOS_ExtDevice::Write(const uint8_t * data,uint16_t * size) {
|
|
PhysPt bufptr = (dos.dcp << 4) | 32;
|
|
for(uint16_t no = 0 ; no < *size ; no++) {
|
|
mem_writeb(bufptr, *data);
|
|
// OUTPUT
|
|
if((CallDeviceFunction(8, 26, bufptr, 1) & 0x8000)) {
|
|
return false;
|
|
} else {
|
|
if(real_readw(dos.dcp, 18) != 1) {
|
|
return false;
|
|
}
|
|
}
|
|
data++;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool DOS_ExtDevice::Close() {
|
|
return true;
|
|
}
|
|
|
|
bool DOS_ExtDevice::Seek(uint32_t * pos,uint32_t type) {
|
|
(void)pos;//UNUSED
|
|
(void)type;//UNUSED
|
|
return true;
|
|
}
|
|
|
|
uint16_t DOS_ExtDevice::GetInformation(void) {
|
|
// bit9=1 .. ExtDevice
|
|
return (ext.attribute & 0xc07f) | 0x0080 | EXT_DEVICE_BIT;
|
|
}
|
|
|
|
uint8_t DOS_ExtDevice::GetStatus(bool input_flag) {
|
|
uint16_t status;
|
|
if(input_flag) {
|
|
// NON-DESTRUCTIVE INPUT NO WAIT
|
|
status = CallDeviceFunction(5, 14, 0, 0);
|
|
} else {
|
|
// OUTPUT STATUS
|
|
status = CallDeviceFunction(10, 13, 0, 0);
|
|
}
|
|
// check NO ERROR & BUSY
|
|
if((status & 0x8200) == 0) {
|
|
return 0xff;
|
|
}
|
|
return 0x00;
|
|
}
|
|
|
|
uint32_t DOS_CheckExtDevice(const char *name, bool already_flag) {
|
|
uint32_t addr = dos_infoblock.GetDeviceChain();
|
|
uint16_t seg, off;
|
|
uint16_t next_seg, next_off;
|
|
uint16_t no;
|
|
char devname[8 + 1];
|
|
|
|
seg = addr >> 16;
|
|
off = addr & 0xffff;
|
|
while(1) {
|
|
no = real_readw(seg, off + 4);
|
|
next_seg = real_readw(seg, off + 2);
|
|
next_off = real_readw(seg, off);
|
|
if(next_seg == 0xffff && next_off == 0xffff) {
|
|
break;
|
|
}
|
|
if(no & 0x8000) {
|
|
for(no = 0 ; no < 8 ; no++) {
|
|
if((devname[no] = real_readb(seg, off + 10 + no)) <= 0x20) {
|
|
devname[no] = 0;
|
|
break;
|
|
}
|
|
}
|
|
devname[8] = 0;
|
|
if(!strcmp(name, devname)) {
|
|
if(already_flag) {
|
|
for(no = 0 ; no < DOS_DEVICES ; no++) {
|
|
if(Devices[no]) {
|
|
if(Devices[no]->GetInformation() & EXT_DEVICE_BIT) {
|
|
if(((DOS_ExtDevice *)Devices[no])->CheckSameDevice(seg, real_readw(seg, off + 6), real_readw(seg, off + 8))) {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return (uint32_t)seg << 16 | (uint32_t)off;
|
|
}
|
|
}
|
|
seg = next_seg;
|
|
off = next_off;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void DOS_CheckOpenExtDevice(const char *name) {
|
|
uint32_t addr;
|
|
|
|
if((addr = DOS_CheckExtDevice(name, true)) != 0) {
|
|
DOS_ExtDevice *device = new DOS_ExtDevice(name, addr >> 16, addr & 0xffff);
|
|
DOS_AddDevice(device);
|
|
}
|
|
}
|
|
|
|
class device_NUL : public DOS_Device {
|
|
public:
|
|
device_NUL() { SetName("NUL"); };
|
|
virtual bool Read(uint8_t * data,uint16_t * size) {
|
|
(void)data; // UNUSED
|
|
*size = 0; //Return success and no data read.
|
|
// LOG(LOG_IOCTL,LOG_NORMAL)("%s:READ",GetName());
|
|
return true;
|
|
}
|
|
virtual bool Write(const uint8_t * data,uint16_t * size) {
|
|
(void)data; // UNUSED
|
|
(void)size; // UNUSED
|
|
// LOG(LOG_IOCTL,LOG_NORMAL)("%s:WRITE",GetName());
|
|
return true;
|
|
}
|
|
virtual bool Seek(uint32_t * pos,uint32_t type) {
|
|
(void)type;
|
|
(void)pos;
|
|
// LOG(LOG_IOCTL,LOG_NORMAL)("%s:SEEK",GetName());
|
|
return true;
|
|
}
|
|
virtual bool Close() { return true; }
|
|
virtual uint16_t GetInformation(void) { return 0x8084; }
|
|
virtual bool ReadFromControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode) { (void)bufptr; (void)size; (void)retcode; return false; }
|
|
virtual bool WriteToControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode) { (void)bufptr; (void)size; (void)retcode; return false; }
|
|
};
|
|
|
|
class device_PRN : public DOS_Device {
|
|
public:
|
|
device_PRN() {
|
|
SetName("PRN");
|
|
}
|
|
bool Read(uint8_t * data,uint16_t * size) {
|
|
(void)data; // UNUSED
|
|
(void)size; // UNUSED
|
|
DOS_SetError(DOSERR_ACCESS_DENIED);
|
|
return false;
|
|
}
|
|
bool Write(const uint8_t * data,uint16_t * size) {
|
|
for(int i = 0; i < 9; i++) {
|
|
// look up a parallel port
|
|
if(parallelPortObjects[i] != NULL) {
|
|
// send the data
|
|
for (uint16_t j=0; j<*size; j++) {
|
|
if(!parallelPortObjects[i]->Putchar(data[j])) return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
bool Seek(uint32_t * pos,uint32_t type) {
|
|
(void)type; // UNUSED
|
|
*pos = 0;
|
|
return true;
|
|
}
|
|
uint16_t GetInformation(void) {
|
|
return 0x80A0;
|
|
}
|
|
bool Close() {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
uint16_t cpMap[512] = { // Codepage is standard 437
|
|
0x0020, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2219, 0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
|
|
0x25ba, 0x25c4, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8, 0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
|
|
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
|
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
|
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
|
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
|
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
|
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
|
|
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
|
|
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
|
|
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
|
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, // 176 - 223 line/box drawing
|
|
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
|
|
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
|
|
0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
|
|
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x0020,
|
|
|
|
0x211e, 0x2120, 0x2122, 0x00ae, 0x00a9, 0x00a4, 0x2295, 0x2299, 0x2297, 0x2296, 0x2a38, 0x21d5, 0x21d4, 0x21c4, 0x2196, 0x2198, // Second bank for WP extended charset
|
|
0x2197, 0x2199, 0x22a4, 0x22a5, 0x22a2, 0x22a3, 0x2213, 0x2243, 0x2260, 0x2262, 0x00b3, 0x00be, 0x0153, 0x0152, 0x05d0, 0x05d1,
|
|
0x0000, 0x2111, 0x211c, 0x2200, 0x2207, 0x29cb, 0x0394, 0x039b, 0x03a0, 0x039e, 0x03a8, 0x05d2, 0x03b3, 0x03b7, 0x03b9, 0x03ba,
|
|
0x03bb, 0x03bd, 0x03c1, 0x03a5, 0x03c9, 0x03be, 0x03b6, 0x02bf, 0x03c5, 0x03c8, 0x03c2, 0x2113, 0x03c7, 0x222e, 0x0178, 0x00cf,
|
|
0x00cb, 0x2227, 0x00c1, 0x0107, 0x0106, 0x01f5, 0x013a, 0x00cd, 0x0139, 0x0144, 0x0143, 0x00d3, 0x0155, 0x0154, 0x015b, 0x015a,
|
|
0x00da, 0x00fd, 0x00dd, 0x017a, 0x0179, 0x00c0, 0x00c8, 0x00cc, 0x00d2, 0x00d9, 0x0151, 0x0150, 0x0171, 0x0170, 0x016f, 0x016e,
|
|
0x010b, 0x010a, 0x0117, 0x0116, 0x0121, 0x0120, 0x0130, 0x017c, 0x017b, 0x00c2, 0x0109, 0x0108, 0x00ca, 0x011d, 0x011c, 0x0125,
|
|
0x0124, 0x00ce, 0x0135, 0x0134, 0x00d4, 0x015d, 0x015c, 0x00db, 0x0175, 0x0174, 0x0177, 0x0176, 0x00e3, 0x00c3, 0x0129, 0x0128,
|
|
0x00f5, 0x00d5, 0x0169, 0x0168, 0x0103, 0x0102, 0x011f, 0x011e, 0x016d, 0x016c, 0x010d, 0x010c, 0x010f, 0x010e, 0x011b, 0x011a,
|
|
0x013e, 0x013d, 0x0148, 0x0147, 0x0159, 0x0158, 0x0161, 0x0160, 0x0165, 0x0164, 0x017e, 0x017d, 0x00f0, 0x0122, 0x0137, 0x0136,
|
|
0x013c, 0x013b, 0x0146, 0x0145, 0x0157, 0x0156, 0x015f, 0x015e, 0x0163, 0x0162, 0x00df, 0x0133, 0x0132, 0x00f8, 0x00d8, 0x2218,
|
|
0x0123, 0x0000, 0x01f4, 0x01e6, 0x2202, 0x0000, 0x0020, 0x2309, 0x2308, 0x230b, 0x230a, 0x23ab, 0x2320, 0x2321, 0x23a9, 0x23a8,
|
|
0x23ac, 0x01e7, 0x2020, 0x2021, 0x201e, 0x222b, 0x222a, 0x2282, 0x2283, 0x2288, 0x2289, 0x2286, 0x2287, 0x220d, 0x2209, 0x2203,
|
|
0x21d1, 0x21d3, 0x21d0, 0x21d2, 0x25a1, 0x2228, 0x22bb, 0x2234, 0x2235, 0x2237, 0x201c, 0x201d, 0x2026, 0x03b8, 0x0101, 0x0113,
|
|
0x0100, 0x0112, 0x012b, 0x012a, 0x014d, 0x014c, 0x016b, 0x016a, 0x0105, 0x0104, 0x0119, 0x0118, 0x012f, 0x012e, 0x0173, 0x0172,
|
|
0x0111, 0x0110, 0x0127, 0x0126, 0x0167, 0x0166, 0x0142, 0x0141, 0x0140, 0x013f, 0x00fe, 0x00de, 0x014a, 0x014b, 0x0149, 0x0000
|
|
};
|
|
|
|
uint16_t cpMap_PC98[256] = {
|
|
// 0 1 2 3 4 5 6 7
|
|
0x0020, 0x2401, 0x2402, 0x2403, 0x2404, 0x2405, 0x2406, 0x2407, // 0x00-0x07 Except NUL, control chars have small letters spelling out the ASCII control code
|
|
0x2408, 0x2409, 0x240A, 0x240B, 0x240C, 0x240D, 0x240E, 0x240F, // 0x08-0x0F i.e. CR is ␍. The mapping here does not EXACTLY render as it does on real hardware.
|
|
0x2410, 0x2411, 0x2412, 0x2413, 0x2414, 0x2415, 0x2416, 0x2417, // 0x10-0x17
|
|
0x2418, 0x2419, 0x241A, 0x241B, 0x2192, 0x2190, 0x2191, 0x2193, // 0x18-0x1F The last 4 are single-wide arrows
|
|
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, // 0x20-0x27
|
|
0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, // 0x28-0x2F
|
|
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, // 0x30-0x37
|
|
0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, // 0x38-0x3F
|
|
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, // 0x40-0x47
|
|
0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, // 0x48-0x4F
|
|
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, // 0x50-0x57
|
|
0x0058, 0x0059, 0x005A, 0x005B, 0x00A5, 0x005D, 0x005E, 0x005F, // 0x58-0x5F 0x5C = Yen
|
|
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, // 0x60-0x67
|
|
0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, // 0x68-0x6F
|
|
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, // 0x70-0x77
|
|
0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x0020, // 0x78-0x7F 0x7F = Does not display as anything
|
|
0x2581, 0x2582, 0x2583, 0x2584, 0x2585, 0x2586, 0x2587, 0x2588, // 0x80-0x87 Block characters, vertical 1/8 to 8/8
|
|
0x258F, 0x258E, 0x258D, 0x258C, 0x258B, 0x258A, 0x2589, 0x253C, // 0x88-0x8F Block characters, horizontal 1/8 to 7/8
|
|
0x2534, 0x252C, 0x2524, 0x251C, 0x0020, 0x2500, 0x2502, 0x2595, // 0x90-0x97
|
|
0x250C, 0x2510, 0x2514, 0x2518, 0x256D, 0x256E, 0x2570, 0x256F, // 0x98-0x9F
|
|
0x0020, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, // 0xA0-0xA7 0xA0 = Nothing. 0xA1-0xDF = Single-wide Katakana
|
|
0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, // 0xA8-0xAF
|
|
0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, // 0xB0-0xB7
|
|
0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, // 0xB8-0xBF
|
|
0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, // 0xC0-0xC7
|
|
0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, // 0xC8-0xCF
|
|
0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, // 0xD0-0xD7
|
|
0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, // 0xD8-0xDF
|
|
0x2550, 0x255E, 0x256A, 0x2561, 0x0020, 0x0020, 0x0020, 0x0020, // 0xE0-0xE7 FIXME: E0h-E3h is an approximation. Find Unicode approx. for E4h-E7h
|
|
0x2660, 0x2665, 0x2666, 0x2663, 0x25CF, 0x25CB, 0x2571, 0x2572, // 0xE8-0xEF
|
|
0x2573, 0x0020, 0x5E74, 0x6708, 0x65E5, 0x0020, 0x5206, 0x0020, // 0xF0-0xF7 FIXME: What is F1h, F5h, F7h?
|
|
0x0020, 0x0020, 0x0020, 0x0020, 0x005C, 0x0020, 0x0020, 0x0020 // 0xF8-0xFF 0xFC = Backslash
|
|
};
|
|
|
|
bool lastwrite = false;
|
|
uint8_t *clipAscii = NULL;
|
|
uint32_t clipSize = 0, cPointer = 0, fPointer;
|
|
|
|
#if defined(WIN32)
|
|
void Unicode2Ascii(const uint16_t* unicode) {
|
|
int memNeeded = WideCharToMultiByte(dos.loaded_codepage==808?866:(dos.loaded_codepage==872?855:dos.loaded_codepage), WC_NO_BEST_FIT_CHARS, (LPCWSTR)unicode, -1, NULL, 0, "\x07", NULL);
|
|
if (memNeeded <= 1) // Includes trailing null
|
|
return;
|
|
if (!(clipAscii = (uint8_t *)malloc(memNeeded)))
|
|
return;
|
|
// Untranslated characters will be set to 0x07 (BEL), and later stripped
|
|
if (WideCharToMultiByte(dos.loaded_codepage==808?866:(dos.loaded_codepage==872?855:dos.loaded_codepage), WC_NO_BEST_FIT_CHARS, (LPCWSTR)unicode, -1, (LPSTR)clipAscii, memNeeded, "\x07", NULL) != memNeeded)
|
|
{ // Can't actually happen of course
|
|
free(clipAscii);
|
|
clipAscii = NULL;
|
|
return;
|
|
}
|
|
memNeeded--; // Don't include trailing null
|
|
for (int i = 0; i < memNeeded; i++)
|
|
if (clipAscii[i] > 31 || clipAscii[i] == 9 || clipAscii[i] == 10 || clipAscii[i] == 13) // Space and up, or TAB, CR/LF allowed (others make no sense when pasting)
|
|
clipAscii[clipSize++] = clipAscii[i];
|
|
return; // clipAscii dould be downsized, but of no real interest
|
|
}
|
|
#else
|
|
typedef char host_cnv_char_t;
|
|
host_cnv_char_t *CodePageGuestToHost(const char *s);
|
|
#endif
|
|
|
|
bool swapad=true;
|
|
extern std::string strPasteBuffer;
|
|
void PasteClipboard(bool bPressed);
|
|
bool getClipboard() {
|
|
if (clipAscii) {
|
|
free(clipAscii);
|
|
clipAscii = NULL;
|
|
}
|
|
#if defined(WIN32)
|
|
clipSize = 0;
|
|
if (OpenClipboard(NULL)) {
|
|
if (HANDLE cbText = GetClipboardData(CF_UNICODETEXT)) {
|
|
uint16_t *unicode = (uint16_t *)GlobalLock(cbText);
|
|
Unicode2Ascii(unicode);
|
|
GlobalUnlock(cbText);
|
|
}
|
|
CloseClipboard();
|
|
}
|
|
#else
|
|
swapad=false;
|
|
PasteClipboard(true);
|
|
swapad=true;
|
|
clipSize = 0;
|
|
unsigned int extra = 0;
|
|
unsigned char head, last=13;
|
|
for (size_t i=0; i<strPasteBuffer.length(); i++) if (strPasteBuffer[i]==10||strPasteBuffer[i]==13) extra++;
|
|
clipAscii = (uint8_t*)malloc(strPasteBuffer.length() + extra);
|
|
if (clipAscii)
|
|
while (strPasteBuffer.length()) {
|
|
head = strPasteBuffer[0];
|
|
if (head == 10 && last != 13) clipAscii[clipSize++] = 13;
|
|
if (head > 31 || head == 9 || head == 10 || head == 13)
|
|
clipAscii[clipSize++] = head;
|
|
if (head == 13 && (strPasteBuffer.length() < 2 || strPasteBuffer[1] != 10)) clipAscii[clipSize++] = 10;
|
|
strPasteBuffer = strPasteBuffer.substr(1, strPasteBuffer.length());
|
|
last = head;
|
|
}
|
|
#endif
|
|
return clipSize != 0;
|
|
}
|
|
|
|
class device_CLIP : public DOS_Device {
|
|
private:
|
|
char tmpAscii[20];
|
|
char tmpUnicode[20];
|
|
std::string rawdata; // the raw data sent to CLIP$...
|
|
virtual void CommitData() {
|
|
if (cPointer>0) {
|
|
if (!clipSize)
|
|
getClipboard();
|
|
if (cPointer>clipSize)
|
|
cPointer=clipSize;
|
|
if (clipSize) {
|
|
if (rawdata.capacity() < 100000)
|
|
rawdata.reserve(100000);
|
|
std::string temp=std::string((char *)clipAscii).substr(0, cPointer);
|
|
if (temp[temp.length()-1]!='\n') temp+="\n";
|
|
rawdata.insert(0, temp);
|
|
clipSize=0;
|
|
}
|
|
cPointer=0;
|
|
}
|
|
FILE* fh = fopen(tmpAscii, "wb"); // Append or write to ASCII file
|
|
if (fh)
|
|
{
|
|
fwrite(rawdata.c_str(), rawdata.size(), 1, fh);
|
|
fclose(fh);
|
|
fh = fopen(tmpUnicode, "w+b"); // The same for Unicode file (it's eventually read)
|
|
if (fh)
|
|
{
|
|
char text[3];
|
|
bool lead = false;
|
|
uint16_t uname[4];
|
|
uint8_t pchr = 0;
|
|
fprintf(fh, "\xff\xfe"); // It's a Unicode text file
|
|
for (uint32_t i = 0; i < rawdata.size(); i++)
|
|
{
|
|
if (lead) {
|
|
lead = false;
|
|
if (pchr && isKanji2(rawdata[i]&0xff)) {
|
|
text[0]=pchr&0xff;
|
|
text[1]=rawdata[i]&0xff;
|
|
text[2]=0;
|
|
uname[0]=0;
|
|
uname[1]=0;
|
|
if ((IS_JDOSV || dos.loaded_codepage == 932) && del_flag && (text[1] & 0xFF) == 0x7F) text[1]++;
|
|
if (CodePageGuestToHostUTF16(uname,text)) {
|
|
fwrite(uname, 1, 2, fh);
|
|
continue;
|
|
} else
|
|
fwrite(cpMap+pchr, 1, 2, fh);
|
|
} else
|
|
fwrite(cpMap+pchr, 1, 2, fh);
|
|
pchr = 0;
|
|
} else if ((IS_PC98_ARCH && shiftjis_lead_byte(rawdata[i]&0xff)) || (isDBCSCP() && isKanji1(rawdata[i]&0xff))) {
|
|
pchr = rawdata[i];
|
|
lead = true;
|
|
continue;
|
|
}
|
|
uint16_t textChar = (uint8_t)rawdata[i];
|
|
switch (textChar)
|
|
{
|
|
case 9: // Tab
|
|
case 12: // Formfeed
|
|
fwrite(&textChar, 1, 2, fh);
|
|
break;
|
|
case 10: // Linefeed (combination)
|
|
case 13:
|
|
fwrite("\x0d\x00\x0a\x00", 1, 4, fh);
|
|
if (i < rawdata.size() -1 && textChar == 23-rawdata[i+1])
|
|
i++;
|
|
break;
|
|
default:
|
|
if (textChar >= 32) // Forget about further control characters?
|
|
fwrite(cpMap+textChar, 1, 2, fh);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!fh)
|
|
{
|
|
rawdata.clear();
|
|
return;
|
|
}
|
|
#if defined(WIN32)
|
|
if (OpenClipboard(NULL))
|
|
{
|
|
if (EmptyClipboard())
|
|
{
|
|
int bytes = ftell(fh);
|
|
HGLOBAL hCbData = GlobalAlloc(NULL, bytes);
|
|
uint8_t* pChData = (uint8_t*)GlobalLock(hCbData);
|
|
if (pChData)
|
|
{
|
|
fseek(fh, 2, SEEK_SET); // Skip Unicode signature
|
|
fread(pChData, 1, bytes-2, fh);
|
|
pChData[bytes-2] = 0;
|
|
pChData[bytes-1] = 0;
|
|
SetClipboardData(CF_UNICODETEXT, hCbData);
|
|
GlobalUnlock(hCbData);
|
|
}
|
|
}
|
|
CloseClipboard();
|
|
}
|
|
#elif defined(C_SDL2) || defined(MACOSX)
|
|
std::ifstream in(tmpAscii);
|
|
std::string contents((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
|
|
std::string result="";
|
|
std::istringstream iss(contents.c_str());
|
|
for (std::string token; std::getline(iss, token); ) {
|
|
char* uname = CodePageGuestToHost(token.c_str());
|
|
result+=(uname!=NULL?std::string(uname):token)+std::string(1, 10);
|
|
}
|
|
if (result.size()&&result.back()==10) result.pop_back();
|
|
#if defined(C_SDL2)
|
|
SDL_SetClipboardText(result.c_str());
|
|
#else
|
|
bool SetClipboard(std::string value);
|
|
SetClipboard(result);
|
|
#endif
|
|
#endif
|
|
fclose(fh);
|
|
remove(tmpAscii);
|
|
remove(tmpUnicode);
|
|
rawdata.clear();
|
|
return;
|
|
}
|
|
public:
|
|
device_CLIP() {
|
|
SetName(*dos_clipboard_device_name?dos_clipboard_device_name:"CLIP$");
|
|
strcpy(tmpAscii, "#clip$.asc");
|
|
strcpy(tmpUnicode, "#clip$.txt");
|
|
}
|
|
virtual bool Read(uint8_t * data,uint16_t * size) {
|
|
if(control->SecureMode()||!(dos_clipboard_device_access==2||dos_clipboard_device_access==4)) {
|
|
*size = 0;
|
|
return true;
|
|
}
|
|
lastwrite=false;
|
|
if (!clipSize) // If no data, we have to read the Windows CLipboard (clipSize gets reset on device close)
|
|
{
|
|
getClipboard();
|
|
fPointer = 0;
|
|
}
|
|
if (fPointer >= clipSize)
|
|
*size = 0;
|
|
else if (fPointer+*size > clipSize)
|
|
*size = (uint16_t)(clipSize-fPointer);
|
|
if (*size > 0) {
|
|
memmove(data, clipAscii+fPointer, *size);
|
|
fPointer += *size;
|
|
}
|
|
return true;
|
|
}
|
|
virtual bool Write(const uint8_t * data,uint16_t * size) {
|
|
if(control->SecureMode()||!(dos_clipboard_device_access==3||dos_clipboard_device_access==4)) {
|
|
DOS_SetError(DOSERR_ACCESS_DENIED);
|
|
return false;
|
|
}
|
|
lastwrite=true;
|
|
const uint8_t* datasrc = (uint8_t*)data;
|
|
uint8_t * datadst = (uint8_t *) data;
|
|
|
|
int numSpaces = 0;
|
|
for (uint16_t idx = *size; idx; idx--)
|
|
{
|
|
if (*datasrc == ' ') // Put spaces on hold
|
|
numSpaces++;
|
|
else
|
|
{
|
|
if (numSpaces && *datasrc != 0x0a && *datasrc != 0x0d) // Spaces on hold and not end of line
|
|
while (numSpaces--)
|
|
*(datadst++) = ' ';
|
|
numSpaces = 0;
|
|
*(datadst++) = *datasrc;
|
|
}
|
|
datasrc++;
|
|
}
|
|
while (numSpaces--)
|
|
*(datadst++) = ' ';
|
|
if (uint16_t newsize = (uint16_t)(datadst - data)) // If data
|
|
{
|
|
if (rawdata.capacity() < 100000) // Prevent repetive size allocations
|
|
rawdata.reserve(100000);
|
|
rawdata.append((char *)data, newsize);
|
|
}
|
|
return true;
|
|
}
|
|
virtual bool Seek(uint32_t * pos,uint32_t type) {
|
|
if(control->SecureMode()||!(dos_clipboard_device_access==2||dos_clipboard_device_access==4)) {
|
|
*pos = 0;
|
|
return true;
|
|
}
|
|
lastwrite=false;
|
|
if (clipSize == 0) // No data yet
|
|
{
|
|
getClipboard();
|
|
fPointer =0;
|
|
}
|
|
int32_t newPos;
|
|
switch (type)
|
|
{
|
|
case 0: // Start of file
|
|
newPos = *pos;
|
|
break;
|
|
case 1: // Current file position
|
|
newPos = fPointer+*pos;
|
|
break;
|
|
case 2: // End of file
|
|
newPos = clipSize+*pos;
|
|
break;
|
|
default:
|
|
{
|
|
DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID);
|
|
return false;
|
|
}
|
|
}
|
|
if (newPos > (int32_t)clipSize) // Different from "real" Files
|
|
newPos = clipSize;
|
|
else if (newPos < 0)
|
|
newPos = 0;
|
|
*pos = newPos;
|
|
cPointer = newPos;
|
|
fPointer = newPos;
|
|
return true;
|
|
}
|
|
virtual bool Close() {
|
|
if(control->SecureMode()||dos_clipboard_device_access<2)
|
|
return false;
|
|
clipSize = 0; // Reset clipboard read
|
|
rawdata.erase(rawdata.find_last_not_of(" \n\r\t")+1); // Remove trailing white space
|
|
if (!rawdata.size()&&!lastwrite) // Nothing captured/to do
|
|
return false;
|
|
lastwrite=false;
|
|
int len = (int)rawdata.size();
|
|
if (len > 2 && rawdata[len-3] == 0x0c && rawdata[len-2] == 27 && rawdata[len-1] == 64) // <ESC>@ after last FF?
|
|
rawdata.erase(len-2, 2);
|
|
CommitData();
|
|
return true;
|
|
}
|
|
uint16_t GetInformation(void) {
|
|
return 0x80E0;
|
|
}
|
|
};
|
|
|
|
bool DOS_Device::Read(uint8_t * data,uint16_t * size) {
|
|
return Devices[devnum]->Read(data,size);
|
|
}
|
|
|
|
bool DOS_Device::Write(const uint8_t * data,uint16_t * size) {
|
|
return Devices[devnum]->Write(data,size);
|
|
}
|
|
|
|
bool DOS_Device::Seek(uint32_t * pos,uint32_t type) {
|
|
return Devices[devnum]->Seek(pos,type);
|
|
}
|
|
|
|
bool DOS_Device::Close() {
|
|
return Devices[devnum]->Close();
|
|
}
|
|
|
|
uint16_t DOS_Device::GetInformation(void) {
|
|
return Devices[devnum]->GetInformation();
|
|
}
|
|
|
|
bool DOS_Device::ReadFromControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode) {
|
|
return Devices[devnum]->ReadFromControlChannel(bufptr,size,retcode);
|
|
}
|
|
|
|
bool DOS_Device::WriteToControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode) {
|
|
return Devices[devnum]->WriteToControlChannel(bufptr,size,retcode);
|
|
}
|
|
|
|
uint8_t DOS_Device::GetStatus(bool input_flag) {
|
|
uint16_t info = Devices[devnum]->GetInformation();
|
|
if(info & EXT_DEVICE_BIT) {
|
|
return Devices[devnum]->GetStatus(input_flag);
|
|
}
|
|
return (info & 0x40) ? 0x00 : 0xff;
|
|
}
|
|
|
|
DOS_File::DOS_File(const DOS_File& orig) : flags(orig.flags), open(orig.open), attr(orig.attr),
|
|
time(orig.time), date(orig.date), refCtr(orig.refCtr), hdrive(orig.hdrive) {
|
|
if(orig.name) {
|
|
name=new char [strlen(orig.name) + 1];strcpy(name,orig.name);
|
|
}
|
|
}
|
|
|
|
DOS_File& DOS_File::operator= (const DOS_File& orig) {
|
|
if (this != &orig) {
|
|
flags = orig.flags;
|
|
time = orig.time;
|
|
date = orig.date;
|
|
attr = orig.attr;
|
|
refCtr = orig.refCtr;
|
|
open = orig.open;
|
|
hdrive = orig.hdrive;
|
|
drive = orig.drive;
|
|
newtime = orig.newtime;
|
|
if (name) {
|
|
delete[] name; name = 0;
|
|
}
|
|
if (orig.name) {
|
|
name = new char[strlen(orig.name) + 1]; strcpy(name, orig.name);
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
uint8_t DOS_FindDevice(char const * name) {
|
|
/* should only check for the names before the dot and spacepadded */
|
|
char fullname[DOS_PATHLENGTH];uint8_t drive;
|
|
bool ime_flag = false;
|
|
// if(!name || !(*name)) return DOS_DEVICES; //important, but makename does it
|
|
if(*name == '@' && *(name + 1) == ':') {
|
|
strcpy(fullname, name + 2);
|
|
ime_flag = true;
|
|
} else {
|
|
if (!DOS_MakeName(name,fullname,&drive)) return DOS_DEVICES;
|
|
}
|
|
char* name_part = strrchr_dbcs(fullname,'\\');
|
|
#if defined(WIN32) && !(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
|
|
if(Network_IsNetworkResource(name))
|
|
name_part = fullname;
|
|
else
|
|
#endif
|
|
if(name_part) {
|
|
*name_part++ = 0;
|
|
//Check validity of leading directory.
|
|
if(!Drives[drive]->TestDir(fullname)) return DOS_DEVICES;
|
|
} else name_part = fullname;
|
|
|
|
char* dot = strrchr(name_part,'.');
|
|
if(dot) *dot = 0; //no ext checking
|
|
|
|
DOS_CheckOpenExtDevice(name_part);
|
|
for(int index = DOS_DEVICES - 1 ; index >= 0 ; index--) {
|
|
if(Devices[index]) {
|
|
if(Devices[index]->GetInformation() & EXT_DEVICE_BIT) {
|
|
if(WildFileCmp(name_part, Devices[index]->name)) {
|
|
if(DOS_CheckExtDevice(name_part, false) != 0) {
|
|
return index;
|
|
} else {
|
|
delete Devices[index];
|
|
Devices[index] = 0;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(ime_flag) {
|
|
return DOS_DEVICES;
|
|
}
|
|
|
|
static char com[5] = { 'C','O','M','1',0 };
|
|
static char lpt[5] = { 'L','P','T','1',0 };
|
|
// AUX is alias for COM1 and PRN for LPT1
|
|
// A bit of a hack. (but less then before).
|
|
// no need for casecmp as makename returns uppercase
|
|
if (strcmp(name_part, "AUX") == 0) name_part = com;
|
|
if (strcmp(name_part, "PRN") == 0) name_part = lpt;
|
|
|
|
/* loop through devices */
|
|
for(uint8_t index = 0;index < DOS_DEVICES;index++) {
|
|
if (Devices[index]) {
|
|
if (WildFileCmp(name_part,Devices[index]->name)) return index;
|
|
}
|
|
}
|
|
return DOS_DEVICES;
|
|
}
|
|
|
|
|
|
void DOS_AddDevice(DOS_Device * adddev) {
|
|
//Caller creates the device. We store a pointer to it
|
|
//TODO Give the Device a real handler in low memory that responds to calls
|
|
if (adddev == NULL) E_Exit("DOS_AddDevice with null ptr");
|
|
for(Bitu i = 0; i < DOS_DEVICES;i++) {
|
|
if (Devices[i] == NULL){
|
|
// LOG_MSG("DOS_AddDevice %s (%p)\n",adddev->name,(void*)adddev);
|
|
Devices[i] = adddev;
|
|
Devices[i]->SetDeviceNumber(i);
|
|
return;
|
|
}
|
|
}
|
|
E_Exit("DOS:Too many devices added");
|
|
}
|
|
|
|
void DOS_DelDevice(DOS_Device * dev) {
|
|
// We will destroy the device if we find it in our list.
|
|
// TODO:The file table is not checked to see the device is opened somewhere!
|
|
if (dev == NULL) return E_Exit("DOS_DelDevice with null ptr");
|
|
for (Bitu i = 0; i <DOS_DEVICES;i++) {
|
|
if (Devices[i] == dev) { /* NTS: The mainline code deleted by matching names??? Why? */
|
|
// LOG_MSG("DOS_DelDevice %s (%p)\n",dev->name,(void*)dev);
|
|
delete Devices[i];
|
|
Devices[i] = 0;
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* hm. unfortunately, too much code in DOSBox assumes that we delete the object.
|
|
* prior to this fix, failure to delete caused a memory leak */
|
|
LOG_MSG("WARNING: DOS_DelDevice() failed to match device object '%s' (%p). Deleting anyway\n",dev->name,(void*)dev);
|
|
delete dev;
|
|
}
|
|
|
|
void DOS_ShutdownDevices(void) {
|
|
for (Bitu i=0;i < DOS_DEVICES;i++) {
|
|
if (Devices[i] != NULL) {
|
|
// LOG_MSG("DOS: Shutting down device %s (%p)\n",Devices[i]->name,(void*)Devices[i]);
|
|
delete Devices[i];
|
|
Devices[i] = NULL;
|
|
}
|
|
}
|
|
|
|
/* NTS: CON counts as a device */
|
|
if (IS_PC98_ARCH) update_pc98_function_row(0);
|
|
}
|
|
|
|
// INT 29h emulation needs to keep track of CON
|
|
device_CON *DOS_CON = NULL;
|
|
|
|
bool ANSI_SYS_installed() {
|
|
if (DOS_CON != NULL)
|
|
return DOS_CON->ANSI_SYS_installed();
|
|
|
|
return false;
|
|
}
|
|
|
|
void DOS_ClearKeyMap()
|
|
{
|
|
for(Bitu i = 0 ; i < DOS_DEVICES ; i++) {
|
|
if(Devices[i]) {
|
|
if(Devices[i]->IsName("CON")) {
|
|
device_CON *con = (device_CON *)Devices[i];
|
|
con->ClearKeyMap();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void DOS_SetConKey(uint16_t src, uint16_t dst)
|
|
{
|
|
for(Bitu i = 0 ; i < DOS_DEVICES ; i++) {
|
|
if(Devices[i]) {
|
|
if(Devices[i]->IsName("CON")) {
|
|
device_CON *con = (device_CON *)Devices[i];
|
|
con->SetKeyMap(src, dst);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void DOS_SetupDevices(void) {
|
|
DOS_Device * newdev;
|
|
DOS_CON=new device_CON(); newdev=DOS_CON;
|
|
DOS_AddDevice(newdev);
|
|
DOS_Device * newdev2;
|
|
newdev2=new device_NUL();
|
|
DOS_AddDevice(newdev2);
|
|
DOS_Device * newdev3;
|
|
newdev3=new device_PRN();
|
|
DOS_AddDevice(newdev3);
|
|
if (dos_clipboard_device_access) {
|
|
DOS_Device * newdev4;
|
|
newdev4=new device_CLIP();
|
|
DOS_AddDevice(newdev4);
|
|
}
|
|
}
|
|
|
|
/* PC-98 INT DC CL=0x10 AH=0x00 DL=cjar */
|
|
void PC98_INTDC_WriteChar(unsigned char b) {
|
|
if (DOS_CON != NULL) {
|
|
uint16_t sz = 1;
|
|
|
|
DOS_CON->Write(&b,&sz);
|
|
}
|
|
}
|
|
|
|
void INTDC_CL10h_AH03h(uint16_t raw) {
|
|
if (DOS_CON != NULL)
|
|
DOS_CON->INTDC_CL10h_AH03h(raw);
|
|
}
|
|
|
|
void INTDC_CL10h_AH04h(void) {
|
|
if (DOS_CON != NULL)
|
|
DOS_CON->INTDC_CL10h_AH04h();
|
|
}
|
|
|
|
void INTDC_CL10h_AH05h(void) {
|
|
if (DOS_CON != NULL)
|
|
DOS_CON->INTDC_CL10h_AH05h();
|
|
}
|
|
|
|
void INTDC_CL10h_AH06h(uint16_t count) {
|
|
if (DOS_CON != NULL)
|
|
DOS_CON->INTDC_CL10h_AH06h(count);
|
|
}
|
|
|
|
void INTDC_CL10h_AH07h(uint16_t count) {
|
|
if (DOS_CON != NULL)
|
|
DOS_CON->INTDC_CL10h_AH07h(count);
|
|
}
|
|
|
|
void INTDC_CL10h_AH08h(uint16_t count) {
|
|
if (DOS_CON != NULL)
|
|
DOS_CON->INTDC_CL10h_AH08h(count);
|
|
}
|
|
|
|
void INTDC_CL10h_AH09h(uint16_t count) {
|
|
if (DOS_CON != NULL)
|
|
DOS_CON->INTDC_CL10h_AH09h(count);
|
|
}
|
|
|
|
Bitu INT29_HANDLER(void) {
|
|
if (DOS_CON != NULL) {
|
|
unsigned char b = reg_al;
|
|
uint16_t sz = 1;
|
|
|
|
DOS_CON->Write(&b,&sz);
|
|
}
|
|
|
|
return CBRET_NONE;
|
|
}
|
|
|
|
extern bool dos_kernel_disabled;
|
|
|
|
// save state support
|
|
void POD_Save_DOS_Devices( std::ostream& stream )
|
|
{
|
|
if (!dos_kernel_disabled) {
|
|
if( strcmp( Devices[2]->GetName(), "CON" ) == 0 )
|
|
Devices[2]->SaveState(stream);
|
|
}
|
|
}
|
|
|
|
void POD_Load_DOS_Devices( std::istream& stream )
|
|
{
|
|
if (!dos_kernel_disabled) {
|
|
if( strcmp( Devices[2]->GetName(), "CON" ) == 0 )
|
|
Devices[2]->LoadState(stream, false);
|
|
}
|
|
}
|