File:  [MS-DOS Player] / msdos-player / source / msdos.h
Revision 1.1.1.50 (vendor branch): download - view: text, annotated - select for diffs
Sun Mar 8 05:38:47 2020 UTC (6 years, 4 months ago) by root
Branches: t-takeda, MAIN
CVS tags: HEAD, D12/18/2018, D10/22/2019
MS-DOS Player

/*
	MS-DOS Player for Win32 console

	Author : Takeda.Toshiya
	Date   : 2009.11.09-
*/

#ifndef _MSDOS_H_
#define _MSDOS_H_

#ifndef _WIN32_WINNT
//#define _WIN32_WINNT 0x400	// Windows NT 4.0
#define _WIN32_WINNT 0x500	// Windows 2000
//#define _WIN32_WINNT 0x501	// Windows XP
#endif
#include <windows.h>
#include <winioctl.h>
#ifdef _MBCS
#include <mbstring.h>
#endif
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <conio.h>
#include <locale.h>
#include <math.h>
#include <dos.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>
#include <sys/locking.h>
#include <mbctype.h>
#include <direct.h>
#include <errno.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <setupapi.h>
#include <winsock.h>
#include <intrin.h>

#ifdef _DEBUG
// _malloca is defined in both intrin.h and crtdbg.h
#ifdef _malloca
#undef _malloca
#endif
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define calloc(c, s) _calloc_dbg(c, s, _NORMAL_BLOCK, __FILE__, __LINE__)
#define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif

// variable scope of 'for' loop for Microsoft Visual C++ 6.0
#if defined(_MSC_VER) && (_MSC_VER == 1200)
#define for if(0);else for
#endif

// disable warnings for Microsoft Visual C++ 2005 or later
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#pragma warning( disable : 4819 )
#pragma warning( disable : 4995 )
#pragma warning( disable : 4996 )
// for MAME i86/i386
#pragma warning( disable : 4018 )
#pragma warning( disable : 4065 )
#pragma warning( disable : 4146 )
#pragma warning( disable : 4244 )
#pragma warning( disable : 4267 )
#endif

// endian
#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
	#if defined(__BYTE_ORDER) && (defined(__LITTLE_ENDIAN) || defined(__BIG_ENDIAN))
		#if __BYTE_ORDER == __LITTLE_ENDIAN
			#define __LITTLE_ENDIAN__
		#elif __BYTE_ORDER == __BIG_ENDIAN
			#define __BIG_ENDIAN__
		#endif
	#elif defined(WORDS_LITTLEENDIAN)
		#define __LITTLE_ENDIAN__
	#elif defined(WORDS_BIGENDIAN)
		#define __BIG_ENDIAN__
	#endif
#endif
#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
	// Microsoft Visual C++
	#define __LITTLE_ENDIAN__
#endif

// compat for mingw32 headers
#ifndef COMMON_LVB_UNDERSCORE
#define COMMON_LVB_UNDERSCORE 0x8000
#endif

// type definition
#ifndef UINT8
typedef unsigned char UINT8;
#endif
#ifndef UINT16
typedef unsigned short UINT16;
#endif
#ifndef UINT32
typedef unsigned int UINT32;
#endif
#ifndef UINT64
typedef unsigned long long UINT64;
#endif
#ifndef INT8
typedef signed char INT8;
#endif
#ifndef INT16
typedef signed short INT16;
#endif
#ifndef INT32
typedef signed int INT32;
#endif
#ifndef INT64
typedef signed long long INT64;
#endif

#pragma pack(1)
typedef union {
	UINT32 dw;
	struct {
#ifdef __BIG_ENDIAN__
		UINT16 h, l;
#else
		UINT16 l, h;
#endif
	} w;
} PAIR32;
#pragma pack()

// MAME i86/i386

// src/emu/devcpu.h
// offsets and addresses are 32-bit (for now...)
typedef UINT32	offs_t;

/* ----------------------------------------------------------------------------
	FIFO buffer
---------------------------------------------------------------------------- */

class FIFO
{
private:
	int size;
	int *buf;
	int cnt, rpt, wpt;
public:
	FIFO(int s) {
		size = s;
		buf = (int *)malloc(size * sizeof(int));
		cnt = rpt = wpt = 0;
	}
	void release()
	{
		if(buf != NULL) {
			free(buf);
			buf = NULL;
		}
	}
	void clear()
	{
		cnt = rpt = wpt = 0;
	}
	void write(int val) {
		if(cnt < size) {
			buf[wpt++] = val;
			if(wpt >= size) {
				wpt = 0;
			}
			cnt++;
		}
	}
	int read() {
		int val = 0;
		if(cnt) {
			val = buf[rpt++];
			if(rpt >= size) {
				rpt = 0;
			}
			cnt--;
		}
		return(val);
	}
	int count() {
		return(cnt);
	}
	int remain() {
		return(size - cnt);
	}
	bool full()
	{
		return(cnt == size);
	}
	bool empty()
	{
		return(cnt == 0);
	}
};

/* ----------------------------------------------------------------------------
	MAME i86/i386
---------------------------------------------------------------------------- */

#if defined(HAS_I86)
	#define CPU_MODEL i8086
#elif defined(HAS_I186)
	#define CPU_MODEL i80186
#elif defined(HAS_V30)
	#define CPU_MODEL v30
#elif defined(HAS_I286)
	#define CPU_MODEL i80286
#elif defined(HAS_I386)
	#define CPU_MODEL i386
#else
//	#if defined(HAS_I386SX)
//		#define CPU_MODEL i386SX
//	#else
		#if defined(HAS_I486)
			#define CPU_MODEL i486
		#else
			#if defined(HAS_PENTIUM)
				#define CPU_MODEL pentium
			#elif defined(HAS_MEDIAGX)
				#define CPU_MODEL mediagx
			#elif defined(HAS_PENTIUM_PRO)
				#define CPU_MODEL pentium_pro
			#elif defined(HAS_PENTIUM_MMX)
				#define CPU_MODEL pentium_mmx
			#elif defined(HAS_PENTIUM2)
				#define CPU_MODEL pentium2
			#elif defined(HAS_PENTIUM3)
				#define CPU_MODEL pentium3
			#elif defined(HAS_PENTIUM4)
				#define CPU_MODEL pentium4
			#endif
			#define SUPPORT_RDTSC
		#endif
		#define SUPPORT_FPU
//	#endif
	#define HAS_I386
#endif

/* ----------------------------------------------------------------------------
	debugger
---------------------------------------------------------------------------- */

//#define USE_DEBUGGER

#ifdef USE_DEBUGGER
#define MAX_BREAK_POINTS	8

bool now_debugging = false;
bool now_going = false;
bool now_suspended = false;
bool force_suspend = false;

typedef struct {
	struct {
		UINT32 addr;
		UINT32 seg;
		UINT32 ofs;
		int status;	// 0 = none, 1 = enabled, other = disabled
	} table[MAX_BREAK_POINTS];
	int hit;
} break_point_t;

break_point_t break_point = {0};
break_point_t rd_break_point = {0};
break_point_t wr_break_point = {0};
break_point_t in_break_point = {0};
break_point_t out_break_point = {0};

typedef struct {
	struct {
		int int_num;
		UINT8 ah, ah_registered;
		UINT8 al, al_registered;
		int status;	// 0 = none, 1 = enabled, other = disabled
	} table[MAX_BREAK_POINTS];
	int hit;
} int_break_point_t;

int_break_point_t int_break_point = {0};

FILE *fp_debugger = NULL;
FILE *fi_debugger = NULL;

// these read/write interfaces do not check break points,
// debugger should use them not to hit any break point mistakely
UINT8 debugger_read_byte(offs_t byteaddress);
UINT16 debugger_read_word(offs_t byteaddress);
UINT32 debugger_read_dword(offs_t byteaddress);
void debugger_write_byte(offs_t byteaddress, UINT8 data);
void debugger_write_word(offs_t byteaddress, UINT16 data);
void debugger_write_dword(offs_t byteaddress, UINT32 data);
UINT8 debugger_read_io_byte(offs_t addr);
UINT16 debugger_read_io_word(offs_t addr);
UINT32 debugger_read_io_dword(offs_t addr);
void debugger_write_io_byte(offs_t addr, UINT8 val);
void debugger_write_io_word(offs_t addr, UINT16 val);
void debugger_write_io_dword(offs_t addr, UINT32 val);
#endif

/* ----------------------------------------------------------------------------
	service thread
---------------------------------------------------------------------------- */

#define USE_SERVICE_THREAD

#ifdef USE_SERVICE_THREAD
CRITICAL_SECTION input_crit_sect;
CRITICAL_SECTION key_buf_crit_sect;
CRITICAL_SECTION putch_crit_sect;
bool in_service = false;
bool service_exit = false;
DWORD main_thread_id;

void start_service_loop(LPTHREAD_START_ROUTINE lpStartAddress);
void finish_service_loop();
#endif

bool in_service_29h = false;

/* ----------------------------------------------------------------------------
	PC/AT hardware emulation
---------------------------------------------------------------------------- */

//#define SUPPORT_GRAPHIC_SCREEN

void hardware_init();
void hardware_finish();
void hardware_release();
void hardware_run();
void hardware_run_cpu();
void hardware_update();

// drive

typedef struct {
	int initialized;
	int valid;
	DISK_GEOMETRY geometry;
	
	int is_fdd()
	{
		if(initialized && valid) {
			switch(geometry.MediaType) {
			case F5_1Pt2_512:
			case F3_1Pt44_512:
			case F3_2Pt88_512:
			case F3_20Pt8_512:
			case F3_720_512:
			case F5_360_512:
			case F5_320_512:
			case F5_320_1024:
			case F5_180_512:
			case F5_160_512:
			case F3_120M_512:
			case F3_640_512:
			case F5_640_512:
			case F5_720_512:
			case F3_1Pt2_512:
			case F3_1Pt23_1024:
			case F5_1Pt23_1024:
			case F3_128Mb_512:
			case F3_230Mb_512:
			case F8_256_128:
			case F3_200Mb_512:
			case F3_240M_512:
			case F3_32M_512:
				return(1);
			}
		}
		return(0);
	}
	int head_num()
	{
		if(initialized && valid) {
			switch(geometry.MediaType) {
			case F5_1Pt2_512:
			case F3_1Pt44_512:
			case F3_2Pt88_512:
			case F3_20Pt8_512:
			case F3_720_512:
			case F5_360_512:
			case F5_320_512:
			case F5_320_1024:
//			case F5_180_512:
//			case F5_160_512:
			case F3_120M_512:
			case F3_640_512:
			case F5_640_512:
			case F5_720_512:
			case F3_1Pt2_512:
			case F3_1Pt23_1024:
			case F5_1Pt23_1024:
			case F3_128Mb_512:
			case F3_230Mb_512:
//			case F8_256_128:
			case F3_200Mb_512:
			case F3_240M_512:
			case F3_32M_512:
				return(2);
			default:
				return(1);
			}
		}
		return(0);
	}
} drive_param_t;

drive_param_t drive_params[26] = {0};

// memory

#if defined(HAS_I386)
	#define ADDR_MASK 0xffffffff
	#define MAX_MEM 0x2000000	/* 32MB */
#elif defined(HAS_I286)
	#define ADDR_MASK 0xffffff
	#define MAX_MEM 0x1000000	/* 16MB */
#else
	#define ADDR_MASK 0xfffff
	#define MAX_MEM 0x100000	/* 1MB */
#endif
UINT8 mem[MAX_MEM + 15];

// ems

#define MAX_EMS_HANDLES 16
#define MAX_EMS_PAGES 2048	/* 32MB */

typedef struct {
	char name[8];
	UINT8* buffer;
	int pages;
	bool allocated;
} ems_handle_t;

typedef struct {
	UINT16 handle;
	UINT16 page;
	bool mapped;
} ems_page_t;

ems_handle_t ems_handles[MAX_EMS_HANDLES + 1] = {0};
ems_page_t ems_pages[4];
int free_ems_pages;

void ems_init();
void ems_finish();
void ems_release();
void ems_allocate_pages(int handle, int pages);
void ems_reallocate_pages(int handle, int pages);
void ems_release_pages(int handle);
void ems_map_page(int physical, int handle, int logical);
void ems_unmap_page(int physical);

// dma

typedef struct {
	struct {
		union {
			UINT16 w;
			struct {
#ifdef __BIG_ENDIAN__
				UINT8 h, l;
#else
				UINT8 l, h;
#endif
			} b;
		} areg, creg, bareg, bcreg;
		UINT8 mode;
		UINT8 pagereg;
		UINT32 port;
	} ch[4];
	
	bool low_high;
	UINT8 cmd;
	UINT8 req;
	UINT8 mask;
	UINT8 tc;
	UINT16 tmp;
} dma_t;

dma_t dma[2];

void dma_init();
void dma_reset(int c);
void dma_write(int c, UINT32 addr, UINT8 data);
UINT8 dma_read(int c, UINT32 addr);
void dma_page_write(int c, int ch, UINT8 data);
UINT8 dma_page_read(int c, int ch);
void dma_run(int c, int ch);

// pic

typedef struct {
	UINT8 imr, isr, irr, prio;
	UINT8 icw1, icw2, icw3, icw4;
	UINT8 ocw3;
	UINT8 icw2_r, icw3_r, icw4_r;
} pic_t;

pic_t pic[2];
int pic_req_chip, pic_req_level;
UINT8 pic_req_bit;

void pic_init();
void pic_write(int c, UINT32 addr, UINT8 data);
UINT8 pic_read(int c, UINT32 addr);
void pic_req(int c, int level, int signal);
int pic_ack();
void pic_update();

// pio

typedef struct {
	UINT8 data, stat, ctrl;
	// code conversion
	bool conv_mode;
	bool jis_mode;
	UINT8 sjis_hi;
	UINT8 esc_buf[8];
	UINT32 esc_len;
	// printer to file
	char path[MAX_PATH];
	FILE *fp;
	SYSTEMTIME time;
} pio_t;

pio_t pio[2];

void pio_init();
void pio_finish();
void pio_release();
void pio_write(int c, UINT32 addr, UINT8 data);
UINT8 pio_read(int c, UINT32 addr);
void printer_out(int c, UINT8 data);
void pcbios_printer_out(int c, UINT8 data);

// pit

#define PIT_ALWAYS_RUNNING

typedef struct {
	INT32 count;
	UINT16 latch;
	UINT16 prev_latch, next_latch;
	UINT16 count_reg;
	UINT8 ctrl_reg;
	int count_latched;
	int low_read, high_read;
	int low_write, high_write;
	int mode;
	int status_latched;
	UINT8 status;
	// constant clock
	UINT32 expired_time;
	UINT32 prev_time;
	UINT64 accum;
} pit_t;

pit_t pit[3];
#ifndef PIT_ALWAYS_RUNNING
int pit_active;
#endif

void pit_init();
void pit_write(int ch, UINT8 val);
UINT8 pit_read(int ch);
int pit_run(int ch, UINT32 cur_time);
void pit_latch_count(int ch);
int pit_get_expired_time(int ch);

UINT8 system_port = 0;

// sio

#define SIO_BUFFER_SIZE 1024

typedef struct {
	int channel;
	
	FIFO *send_buffer;
	FIFO *recv_buffer;
	
	union {
		UINT16 w;
		struct {
#ifdef __BIG_ENDIAN__
			UINT8 h, l;
#else
			UINT8 l, h;
#endif
		} b;
	} divisor;
	UINT16 prev_divisor;
	UINT8 line_ctrl, prev_line_ctrl;
	UINT8 selector;
	
	UINT8 modem_ctrl;
	bool set_brk, set_rts, set_dtr;
	bool prev_set_brk;
//	bool prev_set_rts, prev_set_dtr;
	
	UINT8 line_stat_buf, line_stat_err;
	UINT8 modem_stat, prev_modem_stat;
	
	UINT8 irq_enable;
	UINT8 irq_identify;
	
	UINT8 scratch;
} sio_t;

typedef struct {
	HANDLE hThread;
	CRITICAL_SECTION csSendData;
	CRITICAL_SECTION csRecvData;
	CRITICAL_SECTION csLineCtrl;
	CRITICAL_SECTION csLineStat;
	CRITICAL_SECTION csModemCtrl;
	CRITICAL_SECTION csModemStat;
} sio_mt_t;

sio_t sio[4] = {0};
sio_mt_t sio_mt[4];

void sio_init();
void sio_finish();
void sio_release();
void sio_write(int c, UINT32 addr, UINT8 data);
UINT8 sio_read(int c, UINT32 addr);
void sio_update(int c);
void sio_update_irq(int c);
DWORD WINAPI sio_thread(void *lpx);

// cmos

UINT8 cmos[128];
UINT8 cmos_addr;

void cmos_init();
void cmos_write(int addr, UINT8 val);
UINT8 cmos_read(int addr);

// kbd (a20)

UINT8 kbd_data;
UINT8 kbd_status;
UINT8 kbd_command;

void kbd_init();
UINT8 kbd_read_data();
void kbd_write_data(UINT8 val);
UINT8 kbd_read_status();
void kbd_write_command(UINT8 val);

// crtc

UINT8 crtc_addr = 0;
UINT8 crtc_regs[16] = {0};
UINT8 crtc_changed[16] = {0};

/* ----------------------------------------------------------------------------
	MS-DOS virtual machine
---------------------------------------------------------------------------- */

#if defined(HAS_I386)
#define SUPPORT_VCPI
#endif
#if defined(HAS_I286) || defined(HAS_I386)
#define SUPPORT_XMS
//#define SUPPORT_HMA
#endif
//#define SUPPORT_MSCDEX

#define VECTOR_TOP	0
#define VECTOR_SIZE	0x400
#define BIOS_TOP	(VECTOR_TOP + VECTOR_SIZE)
#define BIOS_SIZE	0x100
#define WORK_TOP	(BIOS_TOP + BIOS_SIZE)
#define WORK_SIZE	0x200
// IO.SYS 0070:0000
#define DEVICE_TOP	(WORK_TOP + WORK_SIZE)
#define DEVICE_SIZE	0x100	/* 22 + 18 * 12 + 7 */
#define DOS_INFO_TOP	(DEVICE_TOP + DEVICE_SIZE)
#define DOS_INFO_SIZE	0x100
//#define EXT_BIOS_TOP	(DOS_INFO_TOP + DOS_INFO_SIZE)
//#define EXT_BIOS_SIZE	0x400
#ifdef EXT_BIOS_TOP
#define DPB_TOP		(EXT_BIOS_TOP + EXT_BIOS_SIZE)
#else
#define DPB_TOP		(DOS_INFO_TOP + DOS_INFO_SIZE)
#endif
#define DPB_SIZE	0x600
#define SFT_TOP		(DPB_TOP + DPB_SIZE)
#define SFT_SIZE	0x4b0	/* 6 + 0x3b * 20 */
#define DISK_BUF_TOP	(SFT_TOP + SFT_SIZE)
#define DISK_BUF_SIZE	0x20
#define CDS_TOP		(DISK_BUF_TOP + DISK_BUF_SIZE)
#define CDS_SIZE	0x8F0	/* 88 * 26 */
#define FCB_TABLE_TOP	(CDS_TOP + CDS_SIZE)
#define FCB_TABLE_SIZE	0x10
#define SDA_TOP		(FCB_TABLE_TOP + FCB_TABLE_SIZE)
#define SDA_SIZE	0xb0
// nls tables
#define UPPERTABLE_TOP	(SDA_TOP + SDA_SIZE)
#define UPPERTABLE_SIZE	0x82
#define LOWERTABLE_TOP	(UPPERTABLE_TOP + UPPERTABLE_SIZE)
#define LOWERTABLE_SIZE	0x82
#define FILENAME_UPPERTABLE_TOP (LOWERTABLE_TOP + LOWERTABLE_SIZE)
#define FILENAME_UPPERTABLE_SIZE 0x82
#define FILENAME_TERMINATOR_TOP (FILENAME_UPPERTABLE_TOP + FILENAME_UPPERTABLE_SIZE)
#define FILENAME_TERMINATOR_SIZE 0x20	/* requirement: 10 + 14(terminate chars) */
#define COLLATING_TABLE_TOP (FILENAME_TERMINATOR_TOP + FILENAME_TERMINATOR_SIZE)
#define COLLATING_TABLE_SIZE 0x102
#define DBCS_TOP	(COLLATING_TABLE_TOP + COLLATING_TABLE_SIZE)
#define DBCS_TABLE	(DBCS_TOP + 2)
#define DBCS_SIZE	0x10
#define MSDOS_SYSTEM_DATA_END (DBCS_TOP + DBCS_SIZE)
#define MEMORY_TOP	((MSDOS_SYSTEM_DATA_END + 15) & ~15U)
#ifdef SUPPORT_GRAPHIC_SCREEN
#define MEMORY_END	0xa0000
#define VGA_VRAM_TOP	0xa0000
#else
#define MEMORY_END	0xb8000
#endif
#define TEXT_VRAM_TOP	0xb8000
#define EMS_TOP		0xc0000
#define EMS_SIZE	0x10000
UINT32 UMB_TOP = EMS_TOP; // EMS is disabled
#define UMB_END		0xf8000
#define SHADOW_BUF_TOP	0xf8000
// text vram size: 80x25x2 = 4000 = 0fa0h
// fffa0h-fffefh can be used for dummy routines
#define DUMMY_TOP	0xfffc0
//#define EMB_TOP	0x10fff0
#define EMB_TOP		0x110000 // align to 4KB
#define EMB_END		MAX_MEM

UINT32 IRET_TOP = 0;
#define IRET_SIZE	0x100
UINT32 XMS_TOP = 0;
// XMS_TOP + 0x000	EMMXXXX0 driver
// XMS_TOP + 0x012	EMS dummy routine
// XMS_TOP + 0x015	XMS dummy routine
// XMS_TOP + 0x018	EMMXXXX0 ioctrl recv buffer
// XMS_TOP + 0x1b9	EMMXXXX0 driver dummy routine (at XMS_TOP + XMS_SIZE - 7)
#define XMS_SIZE	0x1c0	/* 18 + 6 + 413 + 7 */

//#define ENV_SIZE	0x800
#define ENV_SIZE	0x2000
#define PSP_SIZE	0x100
#define PSP_SYSTEM	0x0008

#define MAX_FILES	128
#define MAX_PROCESS	16
#define MAX_DTAINFO	128
#define LFN_DTA_LADDR	0x10FFF0
#define FIND_MAGIC	0x46696e64

#define DUP_STDIN	27
#define DUP_STDOUT	28
#define DUP_STDERR	29
#define DUP_STDAUX	30
#define DUP_STDPRN	31

//#define MAP_AUX_DEVICE_TO_FILE

#pragma pack(1)
typedef struct {
	UINT8 mz;
	UINT16 psp;
	UINT16 paragraphs;
	UINT8 reserved[3];
	char prog_name[8];
} mcb_t;
#pragma pack()

#ifdef SUPPORT_HMA
#pragma pack(1)
typedef struct {
	UINT8 ms[2];
	UINT16 owner;
	UINT16 size;
	UINT16 next;
} hma_mcb_t;
#pragma pack()
#endif

#pragma pack(1)
typedef struct {
	UINT16 env_seg;
	PAIR32 cmd_line;
	PAIR32 fcb1;
	PAIR32 fcb2;
	UINT16 sp;
	UINT16 ss;
	UINT16 ip;
	UINT16 cs;
} param_block_t;
#pragma pack()

#pragma pack(1)
typedef struct {
	UINT8 len;
	char cmd[127];
} cmd_line_t;
#pragma pack()

#pragma pack(1)
typedef struct {
	UINT8 exit[2];
	UINT16 first_mcb;
	UINT8 reserved_1;
//	UINT8 far_call;
//	PAIR32 cpm_entry;
	UINT8 call5[5];
	PAIR32 int_22h;
	PAIR32 int_23h;
	PAIR32 int_24h;
	UINT16 parent_psp;
	UINT8 file_table[20];
	UINT16 env_seg;
	PAIR32 stack;
	UINT16 file_table_size;
	PAIR32 file_table_ptr;
	UINT8 reserved_2[24];
	UINT8 service[3];
	UINT8 reserved_3[2];
	UINT8 ex_fcb[7];
	UINT8 fcb1[16];
	UINT8 fcb2[20];
	UINT8 buffer[128];
} psp_t;
#pragma pack()

#pragma pack(1)
typedef struct {
	UINT16 mz;
	UINT16 extra_bytes;
	UINT16 pages;
	UINT16 relocations;
	UINT16 header_size;
	UINT16 min_alloc;
	UINT16 max_alloc;
	UINT16 init_ss;
	UINT16 init_sp;
	UINT16 check_sum;
	UINT16 init_ip;
	UINT16 init_cs;
	UINT16 relocation_table;
	UINT16 overlay;
} exe_header_t;
#pragma pack()

#pragma pack(1)
typedef struct {
	UINT8 flag;
	UINT8 reserved[5];
	UINT8 attribute;
} ext_fcb_t;
#pragma pack()

#pragma pack(1)
typedef struct {
	UINT8 drive;
	UINT8 file_name[8 + 3];
	UINT16 current_block;
	UINT16 record_size;
	UINT32 file_size;
	UINT16 date;
	UINT16 time;
	union {
		UINT8 reserved[8];
		HANDLE handle;
	};
	UINT8 cur_record;
	UINT32 rand_record;
} fcb_t;
#pragma pack()

#pragma pack(1)
typedef struct {
	UINT8 drive;
	UINT8 file_name[8 + 3];
	UINT8 attribute;
	UINT8 nt_res;
	UINT8 create_time_ms;
	UINT16 creation_time;
	UINT16 creation_date;
	UINT16 last_access_date;
	UINT16 cluster_hi;
	UINT16 last_write_time;
	UINT16 last_write_date;
	UINT16 cluster_lo;
	UINT32 file_size;
} find_fcb_t;
#pragma pack()

#pragma pack(1)
typedef struct {
	union {
		UINT8 reserved[21];
		struct {
			UINT32 find_magic;
			UINT32 dta_index;
		};
	};
	UINT8 attrib;
	UINT16 time;
	UINT16 date;
	UINT32 size;
	char name[13];
} find_t;
#pragma pack()

#pragma pack(1)
typedef struct {
	UINT32 attrib;
	PAIR32 ctime_lo;
	PAIR32 ctime_hi;
	PAIR32 atime_lo;
	PAIR32 atime_hi;
	PAIR32 mtime_lo;
	PAIR32 mtime_hi;
	UINT32 size_hi;
	UINT32 size_lo;
	UINT8 reserved[8];
	char full_name[260];
	char short_name[14];
} find_lfn_t;
#pragma pack()

#pragma pack(1)
typedef struct {
	UINT16 info_level;
	UINT32 serial_number;
	char volume_label[11];
	char file_system[8];
} drive_info_t;
#pragma pack()

#pragma pack(1)
typedef struct {
	UINT16 size_of_structure;
	UINT16 structure_version;
	UINT32 sectors_per_cluster;
	UINT32 bytes_per_sector;
	UINT32 available_clusters_on_drive;
	UINT32 total_clusters_on_drive;
	UINT32 available_sectors_on_drive;
	UINT32 total_sectors_on_drive;
	UINT32 available_allocation_units;
	UINT32 total_allocation_units;
	UINT8 reserved[8];
} ext_space_info_t;
#pragma pack()

#pragma pack(1)
typedef struct {
	UINT8 drive_num;
	UINT8 unit_num;
	UINT16 bytes_per_sector;
	UINT8 highest_sector_num;
	UINT8 shift_count;
	UINT16 reserved_sectors;
	UINT8 fat_num;
	UINT16 root_entries;
	UINT16 first_data_sector;
	UINT16 highest_cluster_num;
	UINT16 sectors_per_fat;
	UINT16 first_dir_sector;
	UINT32 device_driver_header;
	UINT8 media_type;
	UINT8 drive_accessed;
	UINT16 next_dpb_ofs;
	UINT16 next_dpb_seg;
	UINT16 first_free_cluster;
	UINT16 free_clusters;
	// extended
	UINT16 fat_mirroring;
	UINT16 info_sector;
	UINT16 backup_boot_sector;
	UINT32 first_cluster_sector;
	UINT32 maximum_cluster_num;
	UINT32 fat_sectors;
	UINT32 root_cluster;
	UINT32 free_search_cluster;
} dpb_t;
#pragma pack()

#pragma pack(1)
typedef struct {
	UINT16 bytes_per_sector;
	UINT8 sectors_per_cluster;
	UINT16 reserved_sectors;
	UINT8 fat_num;
	UINT16 root_entries;
	UINT16 total_sectors;
	UINT8 media_type;
	UINT16 sectors_per_fat;
	UINT16 sectors_per_track;
	UINT16 heads_num;
	UINT32 hidden_sectors;
	// extended
	UINT32 ext_total_sectors;
	UINT32 ext_sectors_per_fat;
} bpb_t;
#pragma pack()

#pragma pack(1)
typedef struct {
	char path_name[67];
	UINT16 drive_attrib;
	PAIR32 dpb_ptr;
	UINT16 word_1;
	UINT16 word_2;
	UINT16 word_3;
	UINT16 bs_offset;
} cds_t;
#pragma pack()

#pragma pack(1)
typedef struct {
//	UINT16 int21h_5d0ah_si;		// -38
//	UINT16 int21h_5d0ah_ds;		// -36
	// swappable data area
	UINT8 printer_cho_flag;		// -34
	UINT16 int21h_5d0ah_dx;		// -33
	UINT8 switchar;			// -31 current switch character
	UINT8 malloc_strategy;		// -30 current memory allocation strategy
	UINT8 int21h_5d0ah_cl;		// -29
	UINT8 int21h_5e01h_counter;	// -28
	UINT8 int21h_5e01h_name[16];	// -27
	UINT16 offset_lists[5];		// -11
	UINT8 int21h_5d0ah_called;	// -1
	// ----- from DOSBox -----
	UINT8 crit_error_flag;		// 0x00 Critical Error Flag
	UINT8 indos_flag;		// 0x01 InDOS flag (count of active INT 21 calls)
	UINT8 drive_crit_error;		// 0x02 Drive on which current critical error occurred or FFh
	UINT8 locus_of_last_error;	// 0x03 locus of last error
	UINT16 extended_error_code;	// 0x04 extended error code of last error
	UINT8 suggested_action;		// 0x06 suggested action for last error
	UINT8 error_class;		// 0x07 class of last error
	PAIR32 last_error_pointer; 	// 0x08 ES:DI pointer for last error
	PAIR32 current_dta;		// 0x0C current DTA (Disk Transfer Address)
	UINT16 current_psp; 		// 0x10 current PSP
	UINT16 sp_int_23;		// 0x12 stores SP across an INT 23
	UINT16 return_code;		// 0x14 return code from last process termination (zerod after reading with AH=4Dh)
	UINT8 current_drive;		// 0x16 current drive
	UINT8 extended_break_flag; 	// 0x17 extended break flag
	UINT8 fill[2];			// 0x18 flag: code page switching || flag: copy of previous byte in case of INT 24 Abort
} sda_t;
#pragma pack()

#pragma pack(1)
typedef struct {
	UINT8 reserved_0[4];	// -38
	UINT16 magic_word;	// -34 from DOSBox
	UINT8 reserved_1[30];	// -32
	UINT16 first_mcb;	// -2
	PAIR32 first_dpb;	// +0
	PAIR32 first_sft;	// +4
	PAIR32 clock_device;	// +8
	PAIR32 con_device;	// +12
	UINT16 max_sector_len;	// +16
	PAIR32 disk_buf_info;	// +18 from DOSBox
	PAIR32 cds;		// +22
	PAIR32 fcb_table;	// +26
	UINT8 reserved_2[3];	// +30
	UINT8 last_drive;	// +33
	struct {
		PAIR32 next_driver;	// +34
		UINT16 attributes;	// +38
		UINT16 strategy;	// +40
		UINT16 interrupt;	// +42
		char dev_name[8];	// +44
	} nul_device;
	UINT8 reserved_3[11];	// +52
	UINT16 buffers_x;	// +63
	UINT16 buffers_y;	// +65
	UINT8 boot_drive;	// +67
	UINT8 i386_or_later;	// +68
	UINT16 ext_mem_size;	// +69
	PAIR32 disk_buf_heads;	// +71 from DOSBox
	UINT8 reserved_4[21];	// +75
	UINT8 dos_flag;		// +96
	UINT8 reserved_5[2];	// +97
	UINT8 umb_linked;	// +99 from DOSBox
	UINT8 reserved_6[2];	// +100
	UINT16 first_umb_fcb;	// +102 from DOSBox
	UINT16 first_mcb_2;	// +104 from DOSBox
	UINT8 nul_device_routine[7];
} dos_info_t;
#pragma pack()

#pragma pack(1)
typedef struct {
	PAIR32 next_driver;
	UINT16 attributes;
	UINT16 strategy;
	UINT16 interrupt;
	char dev_name[8];
} device_t;
#pragma pack()

#pragma pack(1)
typedef struct {
	UINT16 date_format;
	char currency_symbol[5];
	char thou_sep[2];
	char dec_sep[2];
	char date_sep[2];
	char time_sep[2];
	char currency_format;
	char currency_dec_digits;
	char time_format;
	PAIR32 case_map;
	char list_sep[2];
	char reserved[10];
} country_info_t;
#pragma pack()

typedef struct {
	char path[MAX_PATH];
	int valid;
	int id;
	int atty;
	int mode;
	UINT16 info;
	UINT16 psp;
	int sio_port; // 1-4
	int lpt_port; // 1-3
} file_handler_t;

static const struct {
	int mode;
	int in;
	int out;
} file_mode[] = {
	{ _O_RDONLY | _O_BINARY, 1, 0 },
	{ _O_WRONLY | _O_BINARY, 0, 1 },
	{ _O_RDWR   | _O_BINARY, 1, 1 },
};

typedef struct {
	UINT16 psp;
	char module_dir[MAX_PATH];
#ifdef USE_DEBUGGER
	char module_path[MAX_PATH];
#endif
	PAIR32 dta;
	UINT8 switchar;
	UINT8 verify;
	int max_files;
	char volume_label[MAX_PATH];
	bool parent_int_10h_feh_called;
	bool parent_int_10h_ffh_called;
	UINT16 parent_ds;
	UINT16 parent_es;
	struct {
		UINT16 handle;
		UINT16 page;
		bool mapped;
	} ems_pages[4];
	bool ems_pages_stored;
	bool called_by_int2eh;
} process_t;

typedef struct {
	UINT16 psp;
	UINT32 dta;
	UINT8 allowable_mask;
	UINT8 required_mask;
	HANDLE find_handle;
} dtainfo_t;

UINT8 dos_major_version = 7;	// Windows 98 Second Edition
UINT8 dos_minor_version = 10;
UINT8 win_major_version = 4;
UINT8 win_minor_version = 10;

UINT16 first_mcb;
UINT16 current_psp;

int retval = 0;
UINT16 error_code = 0;

file_handler_t file_handler[MAX_FILES];
UINT8 file_buffer[0x100000];

process_t process[MAX_PROCESS];
dtainfo_t dtalist[MAX_DTAINFO];

UINT16 malloc_strategy = 0;

char comspec_path[MAX_PATH] = "C:\\COMMAND.COM";

void msdos_syscall(unsigned num);
int msdos_init(int argc, char *argv[], char *envp[], int standard_env);
void msdos_finish();

// console

#define SCR_BUF_WIDTH	256
#define SCR_BUF_HEIGHT	128

#define SET_RECT(rect, l, t, r, b) { \
	rect.Left = l; \
	rect.Top = t; \
	rect.Right = r; \
	rect.Bottom = b; \
}

DWORD dwConsoleMode = 0;

CONSOLE_CURSOR_INFO ci_old;
CONSOLE_CURSOR_INFO ci_new;
int font_width = 10;
int font_height = 18;

CHAR_INFO scr_buf[SCR_BUF_WIDTH * SCR_BUF_HEIGHT];
char scr_char[SCR_BUF_WIDTH * SCR_BUF_HEIGHT];
WORD scr_attr[SCR_BUF_WIDTH * SCR_BUF_HEIGHT];
COORD scr_buf_size;
COORD scr_buf_pos;
int scr_width, scr_height;
int scr_top;
bool restore_console_on_exit = false;
bool cursor_moved;
bool cursor_moved_by_crtc;

FIFO *key_buf_char = NULL;
FIFO *key_buf_scan = NULL;
FIFO *key_buf_data = NULL;
bool key_changed = false;
UINT32 key_code = 0;
UINT32 key_recv = 0;

bool pcbios_is_key_buffer_empty();
void pcbios_clear_key_buffer();
void pcbios_set_key_buffer(int key_char, int key_scan);
bool pcbios_get_key_buffer(int *key_char, int *key_scan);

UINT8 ctrl_break_checking = 0x00; // ???
bool ctrl_break_detected = false;
bool ctrl_break_pressed = false;
bool ctrl_c_pressed = false;
bool raise_int_1bh = false;

int active_code_page;
int system_code_page;
int console_code_page;

UINT32 text_vram_top_address;
UINT32 text_vram_end_address;
UINT32 shadow_buffer_top_address;
UINT32 shadow_buffer_end_address;
UINT32 cursor_position_address;
int vram_pages;
bool int_10h_feh_called = false;
bool int_10h_ffh_called = false;

#define MAX_MOUSE_BUTTONS	2

typedef struct {
	bool enabled;	// from DOSBox
	bool enabled_ps2;
	int hidden;
	int old_hidden;	// from DOSBox
	struct {
		int x, y;
	} position, prev_position, max_position, min_position, mickey;
	struct {
		bool status;
		int pressed_times;
		int released_times;
		struct {
			int x, y;
		} pressed_position;
		struct {
			int x, y;
		} released_position;
	} buttons[MAX_MOUSE_BUTTONS];
	int get_buttons()
	{
		int val = 0;
		for(int i = 0; i < MAX_MOUSE_BUTTONS; i++) {
			if(buttons[i].status) {
				val |= 1 << i;
			}
		}
		return(val);
	}
	UINT16 status, status_alt;
	UINT16 status_irq, status_irq_alt, status_irq_ps2;
	UINT16 call_mask;
	PAIR32 call_addr, call_addr_alt[8], call_addr_ps2;
	// dummy
	UINT16 sensitivity[3];
	UINT16 display_page;
	UINT16 language;
	UINT16 hot_spot[2];
	UINT16 screen_mask;
	UINT16 cursor_mask;
} mouse_t;

mouse_t mouse;

UINT16 mouse_push_ax;
UINT16 mouse_push_bx;
UINT16 mouse_push_cx;
UINT16 mouse_push_dx;
UINT16 mouse_push_si;
UINT16 mouse_push_di;

// hma

#ifdef SUPPORT_HMA
bool is_hma_used_by_xms = false;
bool is_hma_used_by_int_2fh = false;
#endif

// xms

#ifdef SUPPORT_XMS
typedef struct emb_handle_s {
	UINT32 handle; // 0=allocated
	offs_t address;
	int size_kb;
	int lock;
	struct emb_handle_s *prev;
	struct emb_handle_s *next;
} emb_handle_t;

emb_handle_t *emb_handle_top = NULL;
int xms_a20_local_enb_count;
UINT16 xms_dx_after_call_08h = 0;

void msdos_xms_init();
void msdos_xms_finish();
void msdos_xms_release();
emb_handle_t *msdos_xms_get_emb_handle(int handle);
int msdos_xms_get_unused_emb_handle_id();
int msdos_xms_get_unused_emb_handle_count();
void msdos_xms_split_emb_handle(emb_handle_t *emb_handle, int size_kb);
void msdos_xms_combine_emb_handles(emb_handle_t *emb_handle);
emb_handle_t *msdos_xms_alloc_emb_handle(int size_kb);
void msdos_xms_free_emb_handle(emb_handle_t *emb_handle);
#endif

#endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.