mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-05-07 18:36:09 +08:00
1083 lines
40 KiB
C++
1083 lines
40 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.
|
|
*/
|
|
|
|
|
|
#ifndef DOSBOX_DOS_INC_H
|
|
#define DOSBOX_DOS_INC_H
|
|
|
|
#define CTBUF 127
|
|
|
|
#include "dos_system.h"
|
|
|
|
#include <list>
|
|
#include <stddef.h> //for offsetof
|
|
|
|
/* Macros SSET_* and SGET_* are used to safely access fields in memory-mapped
|
|
* DOS structures represented via classes inheriting from MemStruct class.
|
|
*
|
|
* All of these macros depend on 'pt' base pointer from MemStruct base class;
|
|
* all DOS-specific fields are accessed by reading memory relative to that
|
|
* pointer.
|
|
*
|
|
* Example usage:
|
|
*
|
|
* SSET_WORD(dos-structure-name, field-name, value);
|
|
* uint16_t x = SGET_WORD(dos-structure-name, field-name);
|
|
*/
|
|
template <size_t N, typename S, typename T1, typename T2 = T1>
|
|
constexpr PhysPt assert_macro_args_ok()
|
|
{
|
|
static_assert(sizeof(T1) == N, "Requested struct field has unexpected size");
|
|
static_assert(sizeof(T2) == N, "Type used to save value has unexpected size");
|
|
static_assert(std::is_standard_layout<S>::value,
|
|
"Struct needs to have standard layout for offsetof calculation");
|
|
// returning 0, so compiler can optimize-out no-op "0 +" expression
|
|
return 0;
|
|
}
|
|
|
|
#define VERIFY_SSET_ARGS(n, s, f, v) \
|
|
assert_macro_args_ok<n, s, decltype(s::f), decltype(v)>()
|
|
#define VERIFY_SGET_ARGS(n, s, f) \
|
|
assert_macro_args_ok<n, s, decltype(s::f)>()
|
|
|
|
#define SSET_BYTE(s, f, v) \
|
|
mem_writeb(VERIFY_SSET_ARGS(1, s, f, v) + pt + offsetof(s, f), v)
|
|
#define SSET_WORD(s, f, v) \
|
|
mem_writew(VERIFY_SSET_ARGS(2, s, f, v) + pt + offsetof(s, f), v)
|
|
#define SSET_DWORD(s, f, v) \
|
|
mem_writed(VERIFY_SSET_ARGS(4, s, f, v) + pt + offsetof(s, f), v)
|
|
|
|
#define SGET_BYTE(s, f) \
|
|
mem_readb(VERIFY_SGET_ARGS(1, s, f) + pt + offsetof(s, f))
|
|
#define SGET_WORD(s, f) \
|
|
mem_readw(VERIFY_SGET_ARGS(2, s, f) + pt + offsetof(s, f))
|
|
#define SGET_DWORD(s, f) \
|
|
mem_readd(VERIFY_SGET_ARGS(4, s, f) + pt + offsetof(s, f))
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma pack (1)
|
|
#endif
|
|
struct CommandTail{
|
|
uint8_t count; /* number of bytes returned */
|
|
char buffer[CTBUF]; /* the buffer itself */
|
|
} GCC_ATTRIBUTE(packed);
|
|
#ifdef _MSC_VER
|
|
#pragma pack ()
|
|
#endif
|
|
|
|
extern bool dos_kernel_disabled;
|
|
|
|
#define IS_DOS_JAPANESE (!dos_kernel_disabled && mem_readb(Real2Phys(dos.tables.dbcs) + 0x02) == 0x81 && mem_readb(Real2Phys(dos.tables.dbcs) + 0x03) == 0x9F)
|
|
#define IS_DOS_CJK (!dos_kernel_disabled && ((mem_readb(Real2Phys(dos.tables.dbcs) + 0x02) == 0x81 || mem_readb(Real2Phys(dos.tables.dbcs) + 0x02) == 0xA1) && (mem_readb(Real2Phys(dos.tables.dbcs) + 0x03) == 0x9F || mem_readb(Real2Phys(dos.tables.dbcs) + 0x03) == 0xFE)))
|
|
#define IS_DOSV (dos.set_jdosv_enabled || dos.set_kdosv_enabled || dos.set_pdosv_enabled || dos.set_tdosv_enabled)
|
|
#define IS_JDOSV (dos.set_jdosv_enabled)
|
|
#define IS_KDOSV (dos.set_kdosv_enabled)
|
|
#define IS_PDOSV (dos.set_pdosv_enabled)
|
|
#define IS_TDOSV (dos.set_tdosv_enabled)
|
|
#define IS_J3100 (dos.set_j3100_enabled)
|
|
|
|
#define EXT_DEVICE_BIT 0x0200
|
|
|
|
extern uint16_t first_umb_seg;
|
|
extern uint16_t first_umb_size;
|
|
|
|
bool MEM_unmap_physmem(Bitu start,Bitu end);
|
|
bool MEM_map_RAM_physmem(Bitu start,Bitu end);
|
|
bool MEM_map_ROM_physmem(Bitu start,Bitu end);
|
|
|
|
struct BuiltinFileBlob {
|
|
const char *recommended_file_name;
|
|
const unsigned char *data;
|
|
size_t length;
|
|
};
|
|
|
|
struct DOS_Date {
|
|
uint16_t year;
|
|
uint8_t month;
|
|
uint8_t day;
|
|
};
|
|
|
|
struct DOS_Version {
|
|
uint8_t major,minor,revision;
|
|
};
|
|
|
|
#ifndef MACOSX
|
|
#if defined (__APPLE__)
|
|
#define MACOSX 1
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
typedef signed char INT8, *PINT8;
|
|
typedef signed short INT16, *PINT16;
|
|
typedef signed int INT32, *PINT32;
|
|
//typedef signed __int64 INT64, *PINT64;
|
|
typedef unsigned char UINT8, *PUINT8;
|
|
typedef unsigned short UINT16, *PUINT16;
|
|
typedef unsigned int UINT32, *PUINT32;
|
|
//typedef unsigned __int64 UINT64, *PUINT64;
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#define SECTOR_SIZE_MAX 2048
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma pack (1)
|
|
#endif
|
|
union bootSector {
|
|
struct entries {
|
|
uint8_t jump[3];
|
|
uint8_t oem_name[8];
|
|
uint16_t bytesect;
|
|
uint8_t sectclust;
|
|
uint16_t reserve_sect;
|
|
} bootdata;
|
|
uint8_t rawdata[SECTOR_SIZE_MAX];
|
|
} GCC_ATTRIBUTE(packed);
|
|
#ifdef _MSC_VER
|
|
#pragma pack ()
|
|
#endif
|
|
|
|
|
|
enum { MCB_FREE=0x0000,MCB_DOS=0x0008 };
|
|
enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3};
|
|
|
|
extern Bitu DOS_FILES;
|
|
|
|
#define DOS_DRIVES 26
|
|
#define DOS_DEVICES 45
|
|
|
|
|
|
#if 0 /* ORIGINAL DEFINES FOR REFERENCE */
|
|
// dos swappable area is 0x320 bytes beyond the sysvars table
|
|
// device driver chain is inside sysvars
|
|
#define DOS_INFOBLOCK_SEG 0x80 // sysvars (list of lists)
|
|
#define DOS_CONDRV_SEG 0xa0
|
|
#define DOS_CONSTRING_SEG 0xa8
|
|
#define DOS_SDA_SEG 0xb2 // dos swappable area
|
|
#define DOS_SDA_OFS 0
|
|
#define DOS_CDS_SEG 0x108
|
|
#define DOS_MEM_START 0x158 // regression to r3437 fixes nascar 2 colors
|
|
//#define DOS_MEM_START 0x16f //First Segment that DOS can use
|
|
|
|
#define DOS_PRIVATE_SEGMENT 0xc800
|
|
#define DOS_PRIVATE_SEGMENT_END 0xd000
|
|
#endif
|
|
|
|
// dos swappable area is 0x320 bytes beyond the sysvars table
|
|
// device driver chain is inside sysvars
|
|
extern uint16_t DOS_INFOBLOCK_SEG;// 0x80 // sysvars (list of lists)
|
|
extern uint16_t DOS_CONDRV_SEG;// 0xa0
|
|
extern uint16_t DOS_CONSTRING_SEG;// 0xa8
|
|
extern uint16_t DOS_SDA_SEG;// 0xb2 // dos swappable area
|
|
extern uint16_t DOS_SDA_SEG_SIZE;
|
|
extern uint16_t DOS_SDA_OFS;// 0
|
|
extern uint16_t DOS_CDS_SEG;// 0x108
|
|
extern uint16_t DOS_MEM_START;// 0x158 // regression to r3437 fixes nascar 2 colors
|
|
|
|
extern uint16_t DOS_PRIVATE_SEGMENT;// 0xc800
|
|
extern uint16_t DOS_PRIVATE_SEGMENT_END;// 0xd000
|
|
|
|
constexpr int SftHeaderSize = 6;
|
|
constexpr int SftEntrySize = 59;
|
|
constexpr int SftNumEntries = 16;
|
|
|
|
/* internal Dos Tables */
|
|
|
|
extern DOS_File ** Files;
|
|
extern DOS_Drive * Drives[DOS_DRIVES];
|
|
extern DOS_Device * Devices[DOS_DEVICES];
|
|
|
|
extern uint8_t ZDRIVE_NUM;
|
|
|
|
extern uint8_t dos_copybuf[0x10000];
|
|
|
|
|
|
void DOS_SetError(uint16_t code);
|
|
|
|
/* File Handling Routines */
|
|
|
|
enum { STDIN=0,STDOUT=1,STDERR=2,STDAUX=3,STDPRN=4};
|
|
enum { HAND_NONE=0,HAND_FILE,HAND_DEVICE};
|
|
|
|
namespace DeviceInfoFlags
|
|
{
|
|
// Device flags
|
|
constexpr uint16_t StdIn = 1<<0;
|
|
constexpr uint16_t StdOut = 1<<1;
|
|
constexpr uint16_t Nul = 1<<2;
|
|
constexpr uint16_t Clock = 1<<3;
|
|
constexpr uint16_t Special = 1<<4;
|
|
constexpr uint16_t Binary = 1<<5;
|
|
constexpr uint16_t EofOnInput = 1<<6;
|
|
constexpr uint16_t Device = 1<<7;
|
|
constexpr uint16_t OpenCloseSupport = 1<<11;
|
|
constexpr uint16_t OutputUntilBusy = 1<<13;
|
|
constexpr uint16_t IoctlSupport = 1<<14;
|
|
|
|
// File flags
|
|
constexpr uint16_t NotWritten = 1<<6;
|
|
constexpr uint16_t NotRemovable = 1<<11;
|
|
constexpr uint16_t NoTimeUpdate = 1<<14;
|
|
constexpr uint16_t Remote = 1<<15;
|
|
}
|
|
namespace DeviceAttributeFlags
|
|
{
|
|
constexpr uint16_t CurrentStdIn = 1<<0;
|
|
constexpr uint16_t CurrentStdOut = 1<<1;
|
|
constexpr uint16_t CurrentNul = 1<<2;
|
|
constexpr uint16_t CurrentClock = 1<<3;
|
|
constexpr uint16_t SupportsRemovable = 1<<11;
|
|
constexpr uint16_t NonIBM = 1<<13;
|
|
constexpr uint16_t SupportsIoctl = 1<<14;
|
|
constexpr uint16_t CharacterDevice = 1<<15;
|
|
|
|
constexpr uint16_t CoreDevicesMask = CurrentStdIn | CurrentStdOut | CurrentNul | CurrentClock;
|
|
}
|
|
|
|
/* Routines for File Class */
|
|
void DOS_SetupFiles (void);
|
|
bool DOS_ReadFile(uint16_t entry,uint8_t * data,uint16_t * amount, bool fcb = false);
|
|
bool DOS_WriteFile(uint16_t entry,const uint8_t * data,uint16_t * amount,bool fcb = false);
|
|
bool DOS_SeekFile(uint16_t entry,uint32_t * pos,uint32_t type,bool fcb = false);
|
|
/* ert, 20100711: Locking extensions */
|
|
bool DOS_LockFile(uint16_t entry,uint8_t mode,uint32_t pos,uint32_t size);
|
|
bool DOS_CloseFile(uint16_t entry,bool fcb = false,uint8_t * refcnt = NULL);
|
|
bool DOS_FlushFile(uint16_t entry);
|
|
bool DOS_DuplicateEntry(uint16_t entry,uint16_t * newentry);
|
|
bool DOS_ForceDuplicateEntry(uint16_t entry,uint16_t newentry);
|
|
bool DOS_GetFileDate(uint16_t entry, uint16_t* otime, uint16_t* odate);
|
|
bool DOS_SetFileDate(uint16_t entry, uint16_t ntime, uint16_t ndate);
|
|
|
|
/* Routines for Drive Class */
|
|
bool DOS_OpenFile(char const * name,uint8_t flags,uint16_t * entry,bool fcb = false);
|
|
bool DOS_OpenFileExtended(char const * name, uint16_t flags, uint16_t createAttr, uint16_t action, uint16_t *entry, uint16_t* status);
|
|
bool DOS_CreateFile(char const * name,uint16_t attributes,uint16_t * entry, bool fcb = false);
|
|
bool DOS_UnlinkFile(char const * const name);
|
|
bool DOS_GetSFNPath(char const * const path, char *SFNpath, bool LFN);
|
|
bool DOS_FindFirst(const char *search,uint16_t attr,bool fcb_findfirst=false);
|
|
bool DOS_FindNext(void);
|
|
bool DOS_Canonicalize(char const * const name,char * const big);
|
|
bool DOS_CreateTempFile(char * const name,uint16_t * entry);
|
|
bool DOS_FileExists(char const * const name);
|
|
|
|
/* Helper Functions */
|
|
bool DOS_MakeName(char const * const name,char * const fullname,uint8_t * drive,bool isVolume = false);
|
|
/* Drive Handing Routines */
|
|
uint8_t DOS_GetDefaultDrive(void);
|
|
void DOS_SetDefaultDrive(uint8_t drive);
|
|
bool DOS_SetDrive(uint8_t drive);
|
|
bool DOS_GetCurrentDir(uint8_t drive,char * const buffer, bool LFN);
|
|
bool DOS_ChangeDir(char const * const dir);
|
|
bool DOS_MakeDir(char const * const dir);
|
|
bool DOS_RemoveDir(char const * const dir);
|
|
bool DOS_Rename(char const * const oldname,char const * const newname);
|
|
bool DOS_GetFreeDiskSpace(uint8_t drive,uint16_t * bytes,uint8_t * sectors,uint16_t * clusters,uint16_t * free);
|
|
bool DOS_GetFreeDiskSpace32(uint8_t drive,uint32_t * bytes,uint32_t * sectors,uint32_t * clusters,uint32_t * free);
|
|
bool DOS_GetFileAttr(char const * const name,uint16_t * attr);
|
|
bool DOS_SetFileAttr(char const * const name,uint16_t attr);
|
|
bool DOS_GetFileAttrEx(char const* const name, struct stat *status, uint8_t hdrive=-1);
|
|
unsigned long DOS_GetCompressedFileSize(char const* const name);
|
|
#if defined (WIN32)
|
|
HANDLE DOS_CreateOpenFile(char const* const name);
|
|
#endif
|
|
|
|
/* IOCTL Stuff */
|
|
bool DOS_IOCTL(void);
|
|
bool DOS_GetSTDINStatus();
|
|
uint8_t DOS_FindDevice(char const * name);
|
|
void DOS_SetupDevices(void);
|
|
void DOS_ClearKeyMap(void);
|
|
void DOS_SetConKey(uint16_t src, uint16_t dst);
|
|
uint32_t DOS_CheckExtDevice(const char *name, bool already_flag);
|
|
|
|
/* Execute and new process creation */
|
|
bool DOS_NewPSP(uint16_t segment,uint16_t size);
|
|
bool DOS_ChildPSP(uint16_t segment,uint16_t size);
|
|
bool DOS_Execute(const char* name, PhysPt block_pt, uint8_t flags);
|
|
void DOS_Terminate(uint16_t pspseg,bool tsr,uint8_t exitcode);
|
|
|
|
/* Memory Handling Routines */
|
|
void DOS_SetupMemory(void);
|
|
uint16_t DOS_GetMaximumFreeSize(uint16_t minBlocks);
|
|
bool DOS_AllocateMemory(uint16_t * segment,uint16_t * blocks);
|
|
bool DOS_ResizeMemory(uint16_t segment,uint16_t * blocks);
|
|
bool DOS_FreeMemory(uint16_t segment);
|
|
void DOS_FreeProcessMemory(uint16_t pspseg);
|
|
uint16_t DOS_GetMemory(uint16_t pages,const char *who=NULL);
|
|
void DOS_Private_UMB_Lock(const bool lock);
|
|
void DOS_FreeTableMemory();
|
|
bool DOS_SetMemAllocStrategy(uint16_t strat);
|
|
uint16_t DOS_GetMemAllocStrategy(void);
|
|
void DOS_BuildUMBChain(bool umb_active,bool ems_active);
|
|
bool DOS_LinkUMBsToMemChain(uint16_t linkstate);
|
|
|
|
/* FCB stuff */
|
|
bool DOS_FCBOpen(uint16_t seg,uint16_t offset);
|
|
bool DOS_FCBCreate(uint16_t seg,uint16_t offset);
|
|
bool DOS_FCBClose(uint16_t seg,uint16_t offset);
|
|
bool DOS_FCBFindFirst(uint16_t seg,uint16_t offset);
|
|
bool DOS_FCBFindNext(uint16_t seg,uint16_t offset);
|
|
uint8_t DOS_FCBRead(uint16_t seg,uint16_t offset, uint16_t recno);
|
|
uint8_t DOS_FCBWrite(uint16_t seg,uint16_t offset,uint16_t recno);
|
|
uint8_t DOS_FCBRandomRead(uint16_t seg,uint16_t offset,uint16_t * numRec,bool restore);
|
|
uint8_t DOS_FCBRandomWrite(uint16_t seg,uint16_t offset,uint16_t * numRec,bool restore);
|
|
bool DOS_FCBGetFileSize(uint16_t seg,uint16_t offset);
|
|
bool DOS_FCBDeleteFile(uint16_t seg,uint16_t offset);
|
|
bool DOS_FCBRenameFile(uint16_t seg, uint16_t offset);
|
|
void DOS_FCBSetRandomRecord(uint16_t seg, uint16_t offset);
|
|
uint8_t FCB_Parsename(uint16_t seg,uint16_t offset,uint8_t parser ,char *string, uint8_t *change);
|
|
bool DOS_GetAllocationInfo(uint8_t drive,uint16_t * _bytes_sector,uint8_t * _sectors_cluster,uint16_t * _total_clusters);
|
|
|
|
/* Extra DOS Interrupts */
|
|
void DOS_SetupMisc(void);
|
|
|
|
/* The DOS Tables */
|
|
void DOS_SetupTables(void);
|
|
|
|
/* Internal DOS Setup Programs */
|
|
void DOS_SetupPrograms(void);
|
|
|
|
/* Initialize Keyboard Layout */
|
|
void DOS_KeyboardLayout_Init(Section* sec);
|
|
|
|
bool DOS_LayoutKey(Bitu key, uint8_t flags1, uint8_t flags2, uint8_t flags3);
|
|
|
|
enum {
|
|
KEYB_NOERROR=0,
|
|
KEYB_FILENOTFOUND,
|
|
KEYB_INVALIDFILE,
|
|
KEYB_LAYOUTNOTFOUND,
|
|
KEYB_INVALIDCPFILE
|
|
};
|
|
|
|
|
|
static INLINE uint16_t long2para(uint32_t size) {
|
|
if (size>0xFFFF0) return 0xffff;
|
|
if (size&0xf) return (uint16_t)((size>>4)+1);
|
|
else return (uint16_t)(size>>4);
|
|
}
|
|
|
|
|
|
static INLINE uint16_t DOS_PackTime(uint16_t hour,uint16_t min,uint16_t sec) {
|
|
return (hour&0x1f)<<11 | (min&0x3f) << 5 | ((sec/2)&0x1f);
|
|
}
|
|
|
|
static INLINE uint16_t DOS_PackDate(uint16_t year,uint16_t mon,uint16_t day) {
|
|
return ((year-1980)&0x7f)<<9 | (mon&0x3f) << 5 | (day&0x1f);
|
|
}
|
|
|
|
/* fopen64, ftello64, fseeko64 */
|
|
#if defined(__linux__)
|
|
#define fseek_ofs_t long
|
|
#elif defined (_MSC_VER)
|
|
#define fopen64 fopen
|
|
#if (_MSC_VER >= 1400)
|
|
#define ftello64 _ftelli64
|
|
#define fseeko64 _fseeki64
|
|
#define fseek_ofs_t __int64
|
|
#else
|
|
#define ftello64 ftell
|
|
#define fseeko64 fseek
|
|
#define fseek_ofs_t long
|
|
#endif
|
|
#elif defined (__MINGW64_VERSION_MAJOR)
|
|
#define fopen64 fopen
|
|
#define ftello64 _ftelli64
|
|
#define fseeko64 _fseeki64
|
|
#define fseek_ofs_t __int64
|
|
#else
|
|
#define fopen64 fopen
|
|
#define ftello64 ftell
|
|
#define fseeko64 fseek
|
|
#define fseek_ofs_t off_t
|
|
#endif
|
|
|
|
/* Dos Error Codes */
|
|
#define DOSERR_NONE 0
|
|
#define DOSERR_FUNCTION_NUMBER_INVALID 1
|
|
#define DOSERR_FILE_NOT_FOUND 2
|
|
#define DOSERR_PATH_NOT_FOUND 3
|
|
#define DOSERR_TOO_MANY_OPEN_FILES 4
|
|
#define DOSERR_ACCESS_DENIED 5
|
|
#define DOSERR_INVALID_HANDLE 6
|
|
#define DOSERR_MCB_DESTROYED 7
|
|
#define DOSERR_INSUFFICIENT_MEMORY 8
|
|
#define DOSERR_MB_ADDRESS_INVALID 9
|
|
#define DOSERR_ENVIRONMENT_INVALID 10
|
|
#define DOSERR_FORMAT_INVALID 11
|
|
#define DOSERR_ACCESS_CODE_INVALID 12
|
|
#define DOSERR_DATA_INVALID 13
|
|
#define DOSERR_RESERVED 14
|
|
#define DOSERR_FIXUP_OVERFLOW 14
|
|
#define DOSERR_INVALID_DRIVE 15
|
|
#define DOSERR_REMOVE_CURRENT_DIRECTORY 16
|
|
#define DOSERR_NOT_SAME_DEVICE 17
|
|
#define DOSERR_NO_MORE_FILES 18
|
|
#define DOSERR_WRITE_PROTECTED 19
|
|
#define DOSERR_DRIVE_NOT_READY 21
|
|
#define DOSERR_FILE_ALREADY_EXISTS 80
|
|
|
|
|
|
/* Remains some classes used to access certain things */
|
|
#define sOffset(s,m) offsetof(s,m)
|
|
#define sGet(s,m) GetIt(sizeof(((s *)&pt)->m),(PhysPt)sOffset(s,m))
|
|
#define sSave(s,m,val) SaveIt(sizeof(((s *)&pt)->m),(PhysPt)sOffset(s,m),val)
|
|
|
|
class MemStruct {
|
|
public:
|
|
inline uint32_t GetIt(const uint32_t size, const PhysPt addr) {
|
|
switch (size) {
|
|
case 1:return mem_readb(pt+addr);
|
|
case 2:return mem_readw(pt+addr);
|
|
case 4:return mem_readd(pt+addr);
|
|
}
|
|
return 0;
|
|
}
|
|
inline void SaveIt(const uint32_t size, const PhysPt addr, const uint32_t val) {
|
|
switch (size) {
|
|
case 1:mem_writeb(pt+addr,(uint8_t)val);break;
|
|
case 2:mem_writew(pt+addr,(uint16_t)val);break;
|
|
case 4:mem_writed(pt+addr,val);break;
|
|
}
|
|
}
|
|
inline void SetPt(const uint16_t seg) { pt=PhysMake(seg,0);}
|
|
inline void SetPt(const uint16_t seg, const uint16_t off) { pt=PhysMake(seg,off);}
|
|
inline void SetPt(const RealPt addr) { pt=Real2Phys(addr);}
|
|
inline PhysPt GetPtPhys(void) const { return pt; }
|
|
inline void SetPtPhys(const PhysPt _pt) { pt=_pt; }
|
|
protected:
|
|
PhysPt pt;
|
|
};
|
|
|
|
class DOS_PSP :public MemStruct {
|
|
public:
|
|
DOS_PSP (uint16_t segment):seg(segment) { SetPt(segment);};
|
|
void MakeNew (uint16_t mem_size);
|
|
void CopyFileTable (DOS_PSP* srcpsp,bool createchildpsp);
|
|
uint16_t FindFreeFileEntry (void);
|
|
void CloseFile (const char *name);
|
|
void CloseFiles (void);
|
|
|
|
void SaveVectors (void);
|
|
void RestoreVectors (void);
|
|
void SetSize (uint16_t size) { sSave(sPSP,next_seg,size); };
|
|
uint16_t GetSize (void) { return (uint16_t)sGet(sPSP,next_seg); };
|
|
void SetEnvironment (uint16_t envseg) { sSave(sPSP,environment,envseg); };
|
|
uint16_t GetEnvironment (void) { return (uint16_t)sGet(sPSP,environment); };
|
|
uint16_t GetSegment (void) { return seg; };
|
|
void SetFileHandle (uint16_t index, uint8_t handle);
|
|
uint8_t GetFileHandle (uint16_t index);
|
|
void SetParent (uint16_t parent) { sSave(sPSP,psp_parent,parent); };
|
|
uint16_t GetParent (void) { return (uint16_t)sGet(sPSP,psp_parent); };
|
|
void SetStack (RealPt stackpt) { sSave(sPSP,stack,stackpt); };
|
|
RealPt GetStack (void) { return sGet(sPSP,stack); };
|
|
void SetInt22 (RealPt int22pt) { sSave(sPSP,int_22,int22pt); };
|
|
RealPt GetInt22 (void) { return sGet(sPSP,int_22); };
|
|
void SetFCB1 (RealPt src);
|
|
void SetFCB2 (RealPt src);
|
|
void SetCommandTail (RealPt src);
|
|
void StoreCommandTail (void);
|
|
void RestoreCommandTail (void);
|
|
bool SetNumFiles (uint16_t fileNum);
|
|
uint16_t FindEntryByHandle (uint8_t handle);
|
|
|
|
private:
|
|
#ifdef _MSC_VER
|
|
#pragma pack(1)
|
|
#endif
|
|
struct sPSP {
|
|
uint8_t exit[2]; /* CP/M-like exit point */
|
|
uint16_t next_seg; /* Segment of first byte beyond memory allocated or program */
|
|
uint8_t fill_1; /* single char fill */
|
|
uint8_t far_call; /* far call opcode */
|
|
RealPt cpm_entry; /* CPM Service Request address*/
|
|
RealPt int_22; /* Terminate Address */
|
|
RealPt int_23; /* Break Address */
|
|
RealPt int_24; /* Critical Error Address */
|
|
uint16_t psp_parent; /* Parent PSP Segment */
|
|
uint8_t files[20]; /* File Table - 0xff is unused */
|
|
uint16_t environment; /* Segment of environment table */
|
|
RealPt stack; /* SS:SP Save point for int 0x21 calls */
|
|
uint16_t max_files; /* Maximum open files */
|
|
RealPt file_table; /* Pointer to File Table PSP:0x18 */
|
|
RealPt prev_psp; /* Pointer to previous PSP */
|
|
uint8_t interim_flag;
|
|
uint8_t truename_flag;
|
|
uint16_t nn_flags;
|
|
uint16_t dos_version;
|
|
uint8_t fill_2[14]; /* Lot's of unused stuff i can't care about */
|
|
uint8_t service[3]; /* INT 0x21 Service call int 0x21;retf; */
|
|
uint8_t fill_3[9]; /* This has some blocks with FCB info */
|
|
uint8_t fcb1[16]; /* first FCB */
|
|
uint8_t fcb2[16]; /* second FCB */
|
|
uint8_t fill_4[4]; /* unused */
|
|
CommandTail cmdtail;
|
|
} GCC_ATTRIBUTE(packed);
|
|
#ifdef _MSC_VER
|
|
#pragma pack()
|
|
#endif
|
|
uint16_t seg;
|
|
public:
|
|
static uint16_t rootpsp;
|
|
};
|
|
|
|
class DOS_ParamBlock:public MemStruct {
|
|
public:
|
|
DOS_ParamBlock(PhysPt addr) {pt=addr;}
|
|
void Clear(void);
|
|
void LoadData(void);
|
|
void SaveData(void); /* Save it as an exec block */
|
|
#ifdef _MSC_VER
|
|
#pragma pack (1)
|
|
#endif
|
|
struct sOverlay {
|
|
uint16_t loadseg;
|
|
uint16_t relocation;
|
|
} GCC_ATTRIBUTE(packed);
|
|
struct sExec {
|
|
uint16_t envseg;
|
|
RealPt cmdtail;
|
|
RealPt fcb1;
|
|
RealPt fcb2;
|
|
RealPt initsssp;
|
|
RealPt initcsip;
|
|
}GCC_ATTRIBUTE(packed);
|
|
#ifdef _MSC_VER
|
|
#pragma pack()
|
|
#endif
|
|
sExec exec = {};
|
|
sOverlay overlay = {};
|
|
};
|
|
|
|
class DOS_InfoBlock:public MemStruct {
|
|
public:
|
|
DOS_InfoBlock() {};
|
|
void SetLocation(uint16_t segment);
|
|
void SetFirstDPB(uint32_t _first_dpb);
|
|
void SetFirstMCB(uint16_t _firstmcb);
|
|
void SetBuffers(uint16_t x,uint16_t y);
|
|
void SetCurDirStruct(uint32_t _curdirstruct);
|
|
void SetFCBTable(uint32_t _fcbtable);
|
|
void SetDeviceChainStart(uint32_t _devchain);
|
|
void SetDiskBufferHeadPt(uint32_t _dbheadpt);
|
|
void SetStartOfUMBChain(uint16_t _umbstartseg);
|
|
void SetUMBChainState(uint8_t _umbchaining);
|
|
void SetBlockDevices(uint8_t _count);
|
|
uint16_t GetStartOfUMBChain(void);
|
|
uint8_t GetUMBChainState(void);
|
|
RealPt GetPointer(void);
|
|
uint32_t GetDeviceChain(void);
|
|
|
|
void SetBootDrive(uint8_t drv) { sSave(sDIB,bootDrive,drv); }
|
|
uint8_t GetBootDrive(void) { return sGet(sDIB,bootDrive); }
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma pack(1)
|
|
#endif
|
|
struct sDIB {
|
|
uint8_t unknown1[4];
|
|
uint16_t magicWord; // -0x22 needs to be 1
|
|
uint8_t unknown2[8];
|
|
uint16_t regCXfrom5e; // -0x18 CX from last int21/ah=5e
|
|
uint16_t countLRUcache; // -0x16 LRU counter for FCB caching
|
|
uint16_t countLRUopens; // -0x14 LRU counter for FCB openings
|
|
uint8_t stuff[6]; // -0x12 some stuff, hopefully never used....
|
|
uint16_t sharingCount; // -0x0c sharing retry count
|
|
uint16_t sharingDelay; // -0x0a sharing retry delay
|
|
RealPt diskBufPtr; // -0x08 pointer to disk buffer
|
|
uint16_t ptrCONinput; // -0x04 pointer to con input
|
|
uint16_t firstMCB; // -0x02 first memory control block
|
|
RealPt firstDPB; // 0x00 first drive parameter block
|
|
RealPt firstFileTable; // 0x04 first system file table
|
|
RealPt activeClock; // 0x08 active clock device header
|
|
RealPt activeCon; // 0x0c active console device header
|
|
uint16_t maxSectorLength; // 0x10 maximum bytes per sector of any block device;
|
|
RealPt diskInfoBuffer; // 0x12 pointer to disk info buffer
|
|
RealPt curDirStructure; // 0x16 pointer to current array of directory structure
|
|
RealPt fcbTable; // 0x1a pointer to system FCB table
|
|
uint16_t protFCBs; // 0x1e protected fcbs
|
|
uint8_t blockDevices; // 0x20 installed block devices
|
|
uint8_t lastdrive; // 0x21 lastdrive
|
|
uint32_t nulNextDriver; // 0x22 NUL driver next pointer
|
|
uint16_t nulAttributes; // 0x26 NUL driver aattributes
|
|
uint16_t nulStrategy; // 0x28 NUL driver strategy routine
|
|
uint16_t nulInterrupt; // 0x2A NUL driver interrupt routine
|
|
uint8_t nulString[8]; // 0x2c NUL driver name string
|
|
uint8_t joindedDrives; // 0x34 joined drives
|
|
uint16_t specialCodeSeg; // 0x35 special code segment
|
|
RealPt setverPtr; // 0x37 pointer to setver
|
|
uint16_t a20FixOfs; // 0x3b a20 fix routine offset
|
|
uint16_t pspLastIfHMA; // 0x3d psp of last program (if dos in hma)
|
|
uint16_t buffers_x; // 0x3f x in BUFFERS x,y
|
|
uint16_t buffers_y; // 0x41 y in BUFFERS x,y
|
|
uint8_t bootDrive; // 0x43 boot drive
|
|
uint8_t useDwordMov; // 0x44 use dword moves
|
|
uint16_t extendedSize; // 0x45 size of extended memory
|
|
uint32_t diskBufferHeadPt; // 0x47 pointer to least-recently used buffer header
|
|
uint16_t dirtyDiskBuffers; // 0x4b number of dirty disk buffers
|
|
uint32_t lookaheadBufPt; // 0x4d pointer to lookahead buffer
|
|
uint16_t lookaheadBufNumber; // 0x51 number of lookahead buffers
|
|
uint8_t bufferLocation; // 0x53 workspace buffer location
|
|
uint32_t workspaceBuffer; // 0x54 pointer to workspace buffer
|
|
uint8_t unknown3[11]; // 0x58
|
|
uint8_t chainingUMB; // 0x63 bit0: UMB chain linked to MCB chain
|
|
uint16_t minMemForExec; // 0x64 minimum paragraphs needed for current program
|
|
uint16_t startOfUMBChain; // 0x66 segment of first UMB-MCB
|
|
uint16_t memAllocScanStart; // 0x68 start paragraph for memory allocation
|
|
} GCC_ATTRIBUTE(packed);
|
|
#ifdef _MSC_VER
|
|
#pragma pack ()
|
|
#endif
|
|
uint16_t seg = 0;
|
|
};
|
|
|
|
class DOS_DTA:public MemStruct{
|
|
public:
|
|
DOS_DTA(RealPt addr) { SetPt(addr); }
|
|
|
|
int GetFindData(int fmt,char * finddata,int *c);
|
|
|
|
void SetupSearch(uint8_t _sdrive,uint8_t _sattr,char * pattern);
|
|
void SetResult(const char * _name,const char * _lname,uint32_t _size,uint32_t _hsize,uint16_t _date,uint16_t _time,uint8_t _attr);
|
|
|
|
uint8_t GetSearchDrive(void);
|
|
void GetSearchParams(uint8_t & _sattr,char * _spattern,bool lfn);
|
|
void GetResult(char * _name,char * _lname,uint32_t & _size,uint32_t & _hsize,uint16_t & _date,uint16_t & _time,uint8_t & _attr);
|
|
|
|
void SetDirID(uint16_t entry) { sSave(sDTA,dirID,entry); };
|
|
void SetDirIDCluster(uint32_t entry) { sSave(sDTA,dirCluster,entry); };
|
|
uint16_t GetDirID(void) { return (uint16_t)sGet(sDTA,dirID); };
|
|
uint32_t GetDirIDCluster(void) { return sGet(sDTA,dirCluster); };
|
|
uint8_t GetAttr(void) { return (uint8_t)sGet(sDTA,sattr); }
|
|
private:
|
|
#ifdef _MSC_VER
|
|
#pragma pack(1)
|
|
#endif
|
|
struct sDTA {
|
|
uint8_t sdrive; /* The Drive the search is taking place */
|
|
uint8_t spname[8]; /* The Search pattern for the filename */
|
|
uint8_t spext[3]; /* The Search pattern for the extension */
|
|
uint8_t sattr; /* The Attributes that need to be found */
|
|
uint16_t dirID; /* custom: dir-search ID for multiple searches at the same time */
|
|
uint32_t dirCluster; /* custom (drive_fat only): cluster number for multiple searches at the same time. 32-bit wide on FAT32 aware MS-DOS 7.1 or higher. */
|
|
uint8_t fill[2];
|
|
uint8_t attr;
|
|
uint16_t time;
|
|
uint16_t date;
|
|
uint32_t size;
|
|
char name[DOS_NAMELENGTH_ASCII];
|
|
} GCC_ATTRIBUTE(packed);
|
|
static_assert(offsetof(sDTA,dirID) == 0x0D,"oops");
|
|
static_assert(offsetof(sDTA,dirCluster) == 0x0F,"oops");
|
|
static_assert(offsetof(sDTA,fill) == 0x13,"oops");
|
|
static_assert(offsetof(sDTA,attr) == 0x15,"oops");
|
|
#ifdef _MSC_VER
|
|
#pragma pack()
|
|
#endif
|
|
};
|
|
|
|
class DOS_FCB: public MemStruct {
|
|
public:
|
|
DOS_FCB(uint16_t seg,uint16_t off,bool allow_extended=true);
|
|
void Create(bool _extended);
|
|
void SetName(uint8_t _drive, const char* _fname, const char* _ext);
|
|
void SetSizeDateTime(uint32_t _size,uint16_t _date,uint16_t _time);
|
|
void GetSizeDateTime(uint32_t & _size,uint16_t & _date,uint16_t & _time);
|
|
void GetVolumeName(char * fillname);
|
|
void GetName(char * fillname);
|
|
void FileOpen(uint8_t _fhandle);
|
|
void FileClose(uint8_t & _fhandle);
|
|
void GetRecord(uint16_t & _cur_block,uint8_t & _cur_rec);
|
|
void SetRecord(uint16_t _cur_block,uint8_t _cur_rec);
|
|
void GetSeqData(uint8_t & _fhandle,uint16_t & _rec_size);
|
|
void SetSeqData(uint8_t _fhandle,uint16_t _rec_size);
|
|
void GetRandom(uint32_t & _random);
|
|
void SetRandom(uint32_t _random);
|
|
uint8_t GetDrive(void);
|
|
bool Extended(void);
|
|
void GetAttr(uint8_t & attr);
|
|
void SetAttr(uint8_t attr);
|
|
void SetResult(uint32_t size,uint16_t date,uint16_t time,uint8_t attr);
|
|
bool Valid(void);
|
|
void ClearBlockRecsize(void);
|
|
private:
|
|
bool extended = false;
|
|
PhysPt real_pt;
|
|
#ifdef _MSC_VER
|
|
#pragma pack (1)
|
|
#endif
|
|
struct sFCB {
|
|
uint8_t drive; /* Drive number 0=default, 1=A, etc */
|
|
uint8_t filename[8]; /* Space padded name */
|
|
uint8_t ext[3]; /* Space padded extension */
|
|
uint16_t cur_block; /* Current Block */
|
|
uint16_t rec_size; /* Logical record size */
|
|
uint32_t filesize; /* File Size */
|
|
uint16_t date;
|
|
uint16_t time;
|
|
/* Reserved Block should be 8 bytes */
|
|
uint8_t sft_entries;
|
|
uint8_t share_attributes;
|
|
uint8_t extra_info;
|
|
/* Maybe swap file_handle and sft_entries now that fcbs
|
|
* aren't stored in the psp filetable anymore */
|
|
uint8_t file_handle;
|
|
uint8_t reserved[4];
|
|
/* end */
|
|
uint8_t cur_rec; /* Current record in current block */
|
|
uint32_t rndm; /* Current relative record number */
|
|
} GCC_ATTRIBUTE(packed);
|
|
#ifdef _MSC_VER
|
|
#pragma pack ()
|
|
#endif
|
|
};
|
|
|
|
class DOS_MCB : public MemStruct{
|
|
public:
|
|
DOS_MCB(uint16_t seg) { SetPt(seg); }
|
|
void SetFileName(const char * const _name) { MEM_BlockWrite(pt+offsetof(sMCB,filename),_name,8); }
|
|
void GetFileName(char * const _name) { MEM_BlockRead(pt+offsetof(sMCB,filename),_name,8);_name[8]=0;}
|
|
void SetType(uint8_t _type) { sSave(sMCB,type,_type);}
|
|
void SetSize(uint16_t _size) { sSave(sMCB,size,_size);}
|
|
void SetPSPSeg(uint16_t _pspseg) { sSave(sMCB,psp_segment,_pspseg);}
|
|
uint8_t GetType(void) { return (uint8_t)sGet(sMCB,type);}
|
|
uint16_t GetSize(void) { return (uint16_t)sGet(sMCB,size);}
|
|
uint16_t GetPSPSeg(void) { return (uint16_t)sGet(sMCB,psp_segment);}
|
|
enum class MCBType : uint8_t
|
|
{
|
|
ValidBlock = 'M',
|
|
LastBlock = 'Z'
|
|
};
|
|
private:
|
|
#ifdef _MSC_VER
|
|
#pragma pack (1)
|
|
#endif
|
|
struct sMCB {
|
|
uint8_t type;
|
|
uint16_t psp_segment;
|
|
uint16_t size;
|
|
uint8_t unused[3];
|
|
uint8_t filename[8];
|
|
} GCC_ATTRIBUTE(packed);
|
|
#ifdef _MSC_VER
|
|
#pragma pack ()
|
|
#endif
|
|
};
|
|
|
|
class DOS_SDA : public MemStruct {
|
|
public:
|
|
DOS_SDA(uint16_t _seg,uint16_t _offs) { SetPt(_seg,_offs); }
|
|
void Init();
|
|
void SetDrive(uint8_t _drive) { sSave(sSDA,current_drive, _drive); }
|
|
void SetDTA(uint32_t _dta) { sSave(sSDA,current_dta, _dta); }
|
|
void SetPSP(uint16_t _psp) { sSave(sSDA,current_psp, _psp); }
|
|
uint8_t GetDrive(void) { return (uint8_t)sGet(sSDA,current_drive); }
|
|
uint16_t GetPSP(void) { return (uint16_t)sGet(sSDA,current_psp); }
|
|
uint32_t GetDTA(void) { return sGet(sSDA,current_dta); }
|
|
|
|
|
|
private:
|
|
#ifdef _MSC_VER
|
|
#pragma pack (1)
|
|
#endif
|
|
struct sSDA {
|
|
uint8_t crit_error_flag; /* 0x00 Critical Error Flag */
|
|
uint8_t inDOS_flag; /* 0x01 InDOS flag (count of active INT 21 calls) */
|
|
uint8_t drive_crit_error; /* 0x02 Drive on which current critical error occurred or FFh */
|
|
uint8_t locus_of_last_error; /* 0x03 locus of last error */
|
|
uint16_t extended_error_code; /* 0x04 extended error code of last error */
|
|
uint8_t suggested_action; /* 0x06 suggested action for last error */
|
|
uint8_t error_class; /* 0x07 class of last error*/
|
|
uint32_t last_error_pointer; /* 0x08 ES:DI pointer for last error */
|
|
uint32_t current_dta; /* 0x0C current DTA (Disk Transfer Address) */
|
|
uint16_t current_psp; /* 0x10 current PSP */
|
|
uint16_t sp_int_23; /* 0x12 stores SP across an INT 23 */
|
|
uint16_t return_code; /* 0x14 return code from last process termination (zerod after reading with AH=4Dh) */
|
|
uint8_t current_drive; /* 0x16 current drive */
|
|
uint8_t extended_break_flag; /* 0x17 extended break flag */
|
|
uint8_t fill[2]; /* 0x18 flag: code page switching || flag: copy of previous byte in case of INT 24 Abort*/
|
|
} GCC_ATTRIBUTE(packed);
|
|
#ifdef _MSC_VER
|
|
#pragma pack()
|
|
#endif
|
|
};
|
|
extern DOS_InfoBlock dos_infoblock;
|
|
|
|
struct DOS_Block {
|
|
DOS_Date date = {};
|
|
DOS_Version version = {};
|
|
uint16_t firstMCB = 0;
|
|
uint16_t errorcode = 0;
|
|
uint16_t psp() const;//{return DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).GetPSP();};
|
|
void psp(uint16_t _seg) const;//{ DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).SetPSP(_seg);};
|
|
RealPt dta() const;//{return DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).GetDTA();};
|
|
void dta(RealPt _dta) const;//{DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).SetDTA(_dta);};
|
|
uint8_t return_code = 0, return_mode = 0;
|
|
|
|
uint8_t current_drive = 0;
|
|
bool verify = false;
|
|
bool breakcheck = false;
|
|
bool echo = false; // if set to true dev_con::read will echo input
|
|
bool direct_output = false;
|
|
bool internal_output = false;
|
|
struct {
|
|
RealPt mediaid = 0;
|
|
RealPt tempdta = 0;
|
|
RealPt tempdta_fcbdelete = 0;
|
|
RealPt dbcs = 0;
|
|
RealPt filenamechar = 0;
|
|
RealPt collatingseq = 0;
|
|
RealPt upcase = 0;
|
|
uint8_t* country = NULL;//Will be copied to dos memory. resides in real mem
|
|
uint16_t dpb = 0; //Fake Disk parameter system using only the first entry so the drive letter matches
|
|
uint16_t dpb_size = 0x21; // bytes per DPB entry (MS-DOS 4.x-6.x size)
|
|
uint16_t mediaid_offset = 0x17; // media ID offset in DPB (MS-DOS 4.x-6.x case)
|
|
} tables;
|
|
uint16_t loaded_codepage = 0;
|
|
bool set_jdosv_enabled = false;
|
|
bool set_kdosv_enabled = false;
|
|
bool set_pdosv_enabled = false;
|
|
bool set_tdosv_enabled = false;
|
|
bool set_j3100_enabled = false;
|
|
bool im_enable_flag;
|
|
uint16_t dcp; // Device command packet
|
|
};
|
|
|
|
extern DOS_Block dos;
|
|
|
|
static INLINE uint8_t RealHandle(uint16_t handle) {
|
|
DOS_PSP psp(dos.psp());
|
|
return psp.GetFileHandle(handle);
|
|
}
|
|
|
|
struct DOS_GetMemLog_Entry {
|
|
uint16_t segbase = 0;
|
|
uint16_t pages = 0;
|
|
std::string who;
|
|
};
|
|
|
|
extern std::list<DOS_GetMemLog_Entry> DOS_GetMemLog;
|
|
|
|
extern int customcp, altcp;
|
|
bool isSupportedCP(int cp);
|
|
void SetupDBCSTable(void);
|
|
const char* DOS_GetLoadedLayout(void);
|
|
|
|
enum COUNTRYNO {
|
|
United_States = 1,
|
|
Candian_French = 2,
|
|
Latin_America = 3,
|
|
Russia = 7,
|
|
Greece = 30,
|
|
Netherlands = 31,
|
|
Belgium = 32,
|
|
France = 33,
|
|
Spain = 34,
|
|
Hungary = 36,
|
|
Yugoslavia = 38,
|
|
Italy = 39,
|
|
Romania = 40,
|
|
Switzerland = 41,
|
|
Czech_Slovak = 42,
|
|
Austria = 43,
|
|
United_Kingdom = 44,
|
|
Denmark = 45,
|
|
Sweden = 46,
|
|
Norway = 47,
|
|
Poland = 48,
|
|
Germany = 49,
|
|
Argentina = 54,
|
|
Brazil = 55,
|
|
Malaysia = 60,
|
|
Australia = 61,
|
|
Philippines = 63,
|
|
Singapore = 65,
|
|
Kazakhstan = 77,
|
|
Japan = 81,
|
|
South_Korea = 82,
|
|
Vietnam = 84,
|
|
China = 86,
|
|
Turkey = 90,
|
|
India = 91,
|
|
Niger = 227,
|
|
Benin = 229,
|
|
Nigeria = 234,
|
|
Faeroe_Islands = 298,
|
|
Portugal = 351,
|
|
Iceland = 354,
|
|
Albania = 355,
|
|
Malta = 356,
|
|
Finland = 358,
|
|
Bulgaria = 359,
|
|
Lithuania = 370,
|
|
Latvia = 371,
|
|
Estonia = 372,
|
|
Armenia = 374,
|
|
Belarus = 375,
|
|
Ukraine = 380,
|
|
Serbia = 381,
|
|
Montenegro = 382,
|
|
Croatia = 384,
|
|
Slovenia = 386,
|
|
Bosnia = 387,
|
|
Macedonia = 389,
|
|
Taiwan = 886,
|
|
Arabic = 785,
|
|
Israel = 972,
|
|
Mongolia = 976,
|
|
Tadjikistan = 992,
|
|
Turkmenistan = 993,
|
|
Azerbaijan = 994,
|
|
Georgia = 995,
|
|
Kyrgyzstan = 996,
|
|
Uzbekistan = 998,
|
|
};
|
|
|
|
const std::map<std::string, int> country_code_map {
|
|
// reference: https://gitlab.com/FreeDOS/base/keyb_lay/-/blob/master/DOC/KEYB/LAYOUTS/LAYOUTS.TXT
|
|
{"ar462", COUNTRYNO::Arabic },
|
|
{"ar470", COUNTRYNO::Arabic },
|
|
{"az", COUNTRYNO::Azerbaijan },
|
|
{"ba", COUNTRYNO::Bosnia },
|
|
{"be", COUNTRYNO::Belgium },
|
|
{"bg", COUNTRYNO::Bulgaria }, // 101-key
|
|
{"bg103", COUNTRYNO::Bulgaria }, // 101-key, Phonetic
|
|
{"bg241", COUNTRYNO::Bulgaria }, // 102-key
|
|
{"bl", COUNTRYNO::Belarus },
|
|
{"bn", COUNTRYNO::Benin },
|
|
{"br", COUNTRYNO::Brazil }, // ABNT layout
|
|
{"br274", COUNTRYNO::Brazil }, // US layout
|
|
{"bx", COUNTRYNO::Belgium }, // International
|
|
{"by", COUNTRYNO::Belarus },
|
|
{"ca", COUNTRYNO::Candian_French }, // Standard
|
|
{"ce", COUNTRYNO::Russia }, // Chechnya Standard
|
|
{"ce443", COUNTRYNO::Russia }, // Chechnya Typewriter
|
|
{"cg", COUNTRYNO::Montenegro },
|
|
{"cf", COUNTRYNO::Candian_French }, // Standard
|
|
{"cf445", COUNTRYNO::Candian_French }, // Dual-layer
|
|
{"co", COUNTRYNO::United_States }, // Colemak
|
|
{"cz", COUNTRYNO::Czech_Slovak }, // Czechia, QWERTY
|
|
{"cz243", COUNTRYNO::Czech_Slovak }, // Czechia, Standard
|
|
{"cz489", COUNTRYNO::Czech_Slovak }, // Czechia, Programmers
|
|
{"de", COUNTRYNO::Germany }, // Standard
|
|
{"dk", COUNTRYNO::Denmark },
|
|
{"dv", COUNTRYNO::United_States }, // Dvorak
|
|
{"ee", COUNTRYNO::Estonia },
|
|
{"el", COUNTRYNO::Greece }, // 319
|
|
{"es", COUNTRYNO::Spain },
|
|
{"et", COUNTRYNO::Estonia },
|
|
{"fi", COUNTRYNO::Finland },
|
|
{"fo", COUNTRYNO::Faeroe_Islands },
|
|
{"fr", COUNTRYNO::France }, // Standard
|
|
{"fx", COUNTRYNO::France }, // International
|
|
{"gk", COUNTRYNO::Greece }, // 319
|
|
{"gk220", COUNTRYNO::Greece }, // 220
|
|
{"gk459", COUNTRYNO::Greece }, // 101-key
|
|
{"gr", COUNTRYNO::Germany }, // Standard
|
|
{"gr453", COUNTRYNO::Germany }, // Dual-layer
|
|
{"hr", COUNTRYNO::Croatia },
|
|
{"hu", COUNTRYNO::Hungary }, // 101-key
|
|
{"hu208", COUNTRYNO::Hungary }, // 102-key
|
|
{"hy", COUNTRYNO::Armenia },
|
|
{"il", COUNTRYNO::Israel },
|
|
{"is", COUNTRYNO::Iceland }, // 101-key
|
|
{"is161", COUNTRYNO::Iceland }, // 102-key
|
|
{"it", COUNTRYNO::Italy }, // Standard
|
|
{"it142", COUNTRYNO::Italy }, // Comma on Numeric Pad
|
|
{"ix", COUNTRYNO::Italy }, // International
|
|
{"jp", COUNTRYNO::Japan },
|
|
{"ka", COUNTRYNO::Georgia },
|
|
{"kk", COUNTRYNO::Kazakhstan },
|
|
{"kk476", COUNTRYNO::Kazakhstan },
|
|
{"kx", COUNTRYNO::United_Kingdom }, // International
|
|
{"ky", COUNTRYNO::Kyrgyzstan },
|
|
{"la", COUNTRYNO::Latin_America },
|
|
{"lh", COUNTRYNO::United_States }, // Left-Hand Dvorak
|
|
{"lt", COUNTRYNO::Lithuania }, // Baltic
|
|
{"lt210", COUNTRYNO::Lithuania }, // 101-key, Programmers
|
|
{"lt211", COUNTRYNO::Lithuania }, // AZERTY
|
|
{"lt221", COUNTRYNO::Lithuania }, // Standard
|
|
{"lt456", COUNTRYNO::Lithuania }, // Dual-layout
|
|
{"lv", COUNTRYNO::Latvia }, // Standard
|
|
{"lv455", COUNTRYNO::Latvia }, // Dual-layout
|
|
{"ml", COUNTRYNO::Malta }, // UK-based
|
|
{"mk", COUNTRYNO::Macedonia },
|
|
{"mn", COUNTRYNO::Mongolia },
|
|
{"mo", COUNTRYNO::Mongolia },
|
|
{"mt", COUNTRYNO::Malta }, // UK-based
|
|
{"mt103", COUNTRYNO::Malta }, // US-based
|
|
{"ne", COUNTRYNO::Niger },
|
|
{"ng", COUNTRYNO::Nigeria },
|
|
{"nl", COUNTRYNO::Netherlands }, // 102-key
|
|
{"no", COUNTRYNO::Norway },
|
|
{"ph", COUNTRYNO::Philippines },
|
|
{"pl", COUNTRYNO::Poland }, // 101-key, Programmers
|
|
{"pl214", COUNTRYNO::Poland }, // 102-key
|
|
{"po", COUNTRYNO::Portugal },
|
|
{"px", COUNTRYNO::Portugal }, // International
|
|
{"ro", COUNTRYNO::Romania }, // Standard
|
|
{"ro446", COUNTRYNO::Romania }, // QWERTY
|
|
{"rh", COUNTRYNO::United_States }, // Right-Hand Dvorak
|
|
{"ru", COUNTRYNO::Russia }, // Standard
|
|
{"ru443", COUNTRYNO::Russia }, // Typewriter
|
|
{"rx", COUNTRYNO::Russia }, // Extended Standard
|
|
{"rx443", COUNTRYNO::Russia }, // Extended Typewriter
|
|
{"sd", COUNTRYNO::Switzerland }, // German
|
|
{"sf", COUNTRYNO::Switzerland }, // French
|
|
{"sg", COUNTRYNO::Switzerland }, // German
|
|
{"si", COUNTRYNO::Slovenia },
|
|
{"sk", COUNTRYNO::Czech_Slovak }, // Slovakia
|
|
{"sp", COUNTRYNO::Spain },
|
|
{"sq", COUNTRYNO::Albania }, // No-deadkeys
|
|
{"sq448", COUNTRYNO::Albania }, // Deadkeys
|
|
{"sr", COUNTRYNO::Serbia }, // Deadkey
|
|
{"su", COUNTRYNO::Finland },
|
|
{"sv", COUNTRYNO::Sweden },
|
|
{"sx", COUNTRYNO::Spain }, // International
|
|
{"tj", COUNTRYNO::Tadjikistan },
|
|
{"tm", COUNTRYNO::Turkmenistan },
|
|
{"tr", COUNTRYNO::Turkey }, // QWERTY
|
|
{"tr440", COUNTRYNO::Turkey }, // Non-standard
|
|
{"tt", COUNTRYNO::Russia }, // Tatarstan Standard
|
|
{"tt443", COUNTRYNO::Russia }, // Tatarstan Typewriter
|
|
{"ua", COUNTRYNO::Ukraine }, // 101-key
|
|
{"uk", COUNTRYNO::United_Kingdom }, // Standard
|
|
{"uk168", COUNTRYNO::United_Kingdom }, // Alternate
|
|
{"ur", COUNTRYNO::Ukraine }, // 101-key
|
|
{"ur465", COUNTRYNO::Ukraine }, // 101-key
|
|
{"ur1996", COUNTRYNO::Ukraine }, // 101-key
|
|
{"ur2001", COUNTRYNO::Ukraine }, // 102-key
|
|
{"ur2007", COUNTRYNO::Ukraine }, // 102-key
|
|
{"us", COUNTRYNO::United_States }, // Standard
|
|
{"ux", COUNTRYNO::United_States }, // International
|
|
{"uz", COUNTRYNO::Uzbekistan },
|
|
{"vi", COUNTRYNO::Vietnam },
|
|
{"yc", COUNTRYNO::Serbia }, // Deadkey
|
|
{"yc450", COUNTRYNO::Serbia }, // No-deadkey
|
|
{"yu", COUNTRYNO::Yugoslavia },
|
|
};
|
|
|
|
void DOS_FlushSTDIN(void);
|
|
|
|
#endif
|