/*
 * DOS type definitions, MCB functions, Exec
 *
 * Copyright 1994 Michael Beck
 */
#ifndef __DOSTYPE_H
#define __DOSTYPE_H

#define MEM(type, seg, ofs)	( type( ( ((int)(seg)) << 4) + (int)(ofs) ) )

#define PTR(seg, ofs)		MEM((char *), seg, ofs)
#define MCB(seg)		MEM((mcb_t *), seg, 0)
#define PSP(seg)		MEM((psp_t *), seg, 0)

#define NEXT_MCB(mcb)		(mcb + MCB(mcb)->size + 1)
#define FREE_MCB(mcb)		(MCB(mcb)->owner == 0)
#define FIRST_MCB		mem_head

#define DTA			PTR(dta_seg, dta_ofs)
#define SET_DTA(seg, ofs)	dta_seg = seg, dta_ofs = ofs
#define GET_DTA(seg, ofs)	seg = dta_seg, ofs = dta_ofs

#define USPTR(far)		MEM((us *), far.segment, far.offset)

/* some define for exec */

#define TYPE_COM		1
#define TYPE_EXE		2

/* first some usefull abbrev */

typedef unsigned short us;
typedef unsigned int ui;
typedef unsigned char uc;

/* the segmented FAR-Pointer */

typedef struct far_pointer {
	us offset;
	us segment;
} far_t;

/* structure of a Memory-Control-Block */

typedef struct mcb_type {
	uc magic;
	us owner;
	us size;
	uc unused[3];
	uc name[8];
} mcb_t;

/* the Program-Segment-Praefix */

typedef struct psp_type {
	uc int_20[2];			/*  0 */
	us mem_size;			/*  2 */
	uc reserved;			/*  4 */
	uc dos_call[5];			/*  5 */
	far_t old22;			/*  A */
	far_t old23;			/*  E */
	far_t old24;			/* 12 */
	us parent;			/* 16 */
	uc jft[20];			/* 18 */
	us environ;			/* 2c */
	far_t saved_stack;		/* 2e */
	us jft_size;			/* 32 */
	far_t jft_ptr;			/* 34 */
	far_t prev_psp;			/* 38 */
	uc unused1[4];			/* 3c */
	uc unused2[2];			/* 40 */
	uc unused3[6];			/* 42 */
	uc unused4;			/* 48 */
	uc unused5[7];			/* 49 */
	uc int21_req[3];		/* 50 */
	uc unused6[9];			/* 53 */
	uc fcb1[16];			/* 5c */
	uc fcb2[16];			/* 6c */
	uc unused7[4];			/* 7c */
	uc cmd_length;			/* 80 */
	uc cmd_line[0x79];		/* 81 */
} psp_t;

typedef struct {	/* for ExecLoad: SS:ESP und CS:EIP of the loaded module */
	unsigned rESP;
	us       rSS;	/* SS:ESP */
	unsigned rEIP;
	us       rCS;	/* CS:EIP */
} ssip_t;

typedef struct {	/* the famous EXE-header */
	uc	magic[2];	/* MZ */
	us	partpag;	/* length of partial page at end */
	us	pagecnt;	/* length of image in 512-byte pages, including the header */
	us	relocnt;	/* number of items in relocation table */
	us	hdrsize;	/* size of header in 16-byte paragraphs */
	us	minmem;		/* minimum memory needed above end of program (in paragraphs) */
	us	maxmem;		/*  maximum memory needed above end of program */
	us	reloSS;		/* segment offset of stack segment (for setting SS) */
	us	exeSP;		/* value for SP register (stack pointer) when started */
	us	chksum;		/* file checksum (negative sum of all words in file)*/
	us	exeIP;		/* value for IP register when started */
	us	reloCS;		/* segment offset of code */
	us	tabloff;	/* file-offset of first relocation item (often 001cH) */
	us	overlay;	/* overlay number (0 for base module) */
} exehead_t;

/* needed data */

extern us current_psp;
extern us dta_seg, dta_ofs;

/* mcb functions */

extern void list_mcb(void);
extern void mcb_init(us start);
extern int dos_split_block(us seg, us size);
extern int dos_alloc_mem(us size, long *max, int split);
extern int dos_resize_block(us seg, us size);
extern int dos_dealloc_mem(us seg);
extern int dos_allocation_strat(us ax, us bx);

/* exec functions */

extern void dos_set_active_psp(us psp);
extern us dos_get_active_psp(void);
extern void dos_copy_psp(us psp);
extern void dos_create_new_psp(us psp, us endadr);
extern int dos_exec_load(char *path, char *cmdline, ssip_t *ssip);
extern int dos_exec(char *path, char *cmdline);

/* ioctl */

int dos_ioctl(us ax, us bx, us dx);
#endif
