bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,const char* descr) {
	if (callback>=CB_MAX) return false;
	switch (type) {
	case CB_RETF:
		phys_writeb(CB_BASE+(callback<<4)+0,(Bit8u)0xFE);	//GRP 4
		phys_writeb(CB_BASE+(callback<<4)+1,(Bit8u)0x38);	//Extra Callback instruction
		phys_writew(CB_BASE+(callback<<4)+2,callback);		//The immediate word
		phys_writeb(CB_BASE+(callback<<4)+4,(Bit8u)0xCB);	//A RETF Instruction
		break;
	case CB_IRET:
		phys_writeb(CB_BASE+(callback<<4)+0,(Bit8u)0xFE);	//GRP 4
		phys_writeb(CB_BASE+(callback<<4)+1,(Bit8u)0x38);	//Extra Callback instruction
		phys_writew(CB_BASE+(callback<<4)+2,callback);		//The immediate word
		phys_writeb(CB_BASE+(callback<<4)+4,(Bit8u)0xCF);	//An IRET Instruction
		break;
	case CB_IRET_STI:
		phys_writeb(CB_BASE+(callback<<4)+0,(Bit8u)0xFB);	//STI
		phys_writeb(CB_BASE+(callback<<4)+1,(Bit8u)0xFE);	//GRP 4
		phys_writeb(CB_BASE+(callback<<4)+2,(Bit8u)0x38);	//Extra Callback instruction
		phys_writew(CB_BASE+(callback<<4)+3,callback);		//The immediate word
		phys_writeb(CB_BASE+(callback<<4)+5,(Bit8u)0xCF);	//An IRET Instruction
		break;
	default:
		E_Exit("CALLBACK:Setup:Illegal type %d",type);
	}
	CallBack_Handlers[callback]=handler;
	CALLBACK_SetDescription(callback,descr);
	return true;
}
Esempio n. 2
0
void updateDPT(void) {
	Bit32u tmpheads, tmpcyl, tmpsect, tmpsize;
	if(imageDiskList[2] != NULL) {
		PhysPt dp0physaddr=CALLBACK_PhysPointer(diskparm0);
		imageDiskList[2]->Get_Geometry(&tmpheads, &tmpcyl, &tmpsect, &tmpsize);
		phys_writew(dp0physaddr,(Bit16u)tmpcyl);
		phys_writeb(dp0physaddr+0x2,(Bit8u)tmpheads);
		phys_writew(dp0physaddr+0x3,0);
		phys_writew(dp0physaddr+0x5,(Bit16u)-1);
		phys_writeb(dp0physaddr+0x7,0);
		phys_writeb(dp0physaddr+0x8,(0xc0 | (((imageDiskList[2]->heads) > 8) << 3)));
		phys_writeb(dp0physaddr+0x9,0);
		phys_writeb(dp0physaddr+0xa,0);
		phys_writeb(dp0physaddr+0xb,0);
		phys_writew(dp0physaddr+0xc,(Bit16u)tmpcyl);
		phys_writeb(dp0physaddr+0xe,(Bit8u)tmpsect);
	}
	if(imageDiskList[3] != NULL) {
		PhysPt dp1physaddr=CALLBACK_PhysPointer(diskparm1);
		imageDiskList[3]->Get_Geometry(&tmpheads, &tmpcyl, &tmpsect, &tmpsize);
		phys_writew(dp1physaddr,(Bit16u)tmpcyl);
		phys_writeb(dp1physaddr+0x2,(Bit8u)tmpheads);
		phys_writeb(dp1physaddr+0xe,(Bit8u)tmpsect);
	}
}
Esempio n. 3
0
Bit16u INT10_SetupVideoParameterTable(PhysPt basepos) {
	if (IS_VGA_ARCH) {
		for (Bitu i=0;i<0x40*0x1d;i++) {
			phys_writeb(basepos+i,video_parameter_table_vga[i]);
		}
		return 0x40*0x1d;
	} else {
		for (Bitu i=0;i<0x40*0x17;i++) {
			phys_writeb(basepos+i,video_parameter_table_ega[i]);
		}
		return 0x40*0x17;
	}
}
Esempio n. 4
0
void CreateMouseCallback(void)
{
	// Create callback
	call_int33=CALLBACK_Allocate();
	CALLBACK_Setup(call_int33,&INT33_Handler,CB_IRET,"Mouse");

	// Create a mouse vector with weird address 
	// for strange mouse detection routines in Sim City & Wasteland
	Bit16u ofs = call_int33<<4;
	phys_writeb(CB_BASE+ofs+0,(Bit8u)0x90);	//NOP
	phys_writeb(CB_BASE+ofs+1,(Bit8u)0xFE);	//GRP 4
	phys_writeb(CB_BASE+ofs+2,(Bit8u)0x38);	//Extra Callback instruction
	phys_writew(CB_BASE+ofs+3,call_int33);	//The immediate word
	phys_writeb(CB_BASE+ofs+5,(Bit8u)0xCF);	//An IRET Instruction
	// Write weird vector
	WriteMouseIntVector();
};
Esempio n. 5
0
void INT10_SetupVESA(void) {
	/* Put the mode list somewhere in memory */
	Bitu i;
	i=0;
	int10.rom.vesa_modes=RealMake(0xc000,int10.rom.used);
//TODO Maybe add normal vga modes too, but only seems to complicate things
	while (ModeList_VGA[i].mode!=0xffff) {
		bool canuse_mode=false;
		if (!svga.accepts_mode) canuse_mode=true;
		else {
			if (svga.accepts_mode(ModeList_VGA[i].mode)) canuse_mode=true;
		}
		if (ModeList_VGA[i].mode>=0x100 && canuse_mode) {
			if ((!int10.vesa_oldvbe) || (ModeList_VGA[i].mode<0x120)) {
				phys_writew(PhysMake(0xc000,int10.rom.used),ModeList_VGA[i].mode);
				int10.rom.used+=2;
			}
		}
		i++;
	}
	phys_writew(PhysMake(0xc000,int10.rom.used),0xffff);
	int10.rom.used+=2;
	int10.rom.oemstring=RealMake(0xc000,int10.rom.used);
	Bitu len=(Bitu)(strlen(string_oem)+1);
	for (i=0;i<len;i++) {
		phys_writeb(0xc0000+int10.rom.used++,string_oem[i]);
	}
	switch (svgaCard) {
	case SVGA_S3Trio:
		break;
	}
	callback.setwindow=CALLBACK_Allocate();
	callback.pmPalette=CALLBACK_Allocate();
	callback.pmStart=CALLBACK_Allocate();
	CALLBACK_Setup(callback.setwindow,VESA_SetWindow,CB_RETF, "VESA Real Set Window");
	/* Prepare the pmode interface */
	int10.rom.pmode_interface=RealMake(0xc000,int10.rom.used);
	int10.rom.used += 8;		//Skip the byte later used for offsets
	/* PM Set Window call */
	int10.rom.pmode_interface_window = int10.rom.used - RealOff( int10.rom.pmode_interface );
	phys_writew( Real2Phys(int10.rom.pmode_interface) + 0, int10.rom.pmode_interface_window );
	callback.pmWindow=CALLBACK_Allocate();
	int10.rom.used += (Bit16u)CALLBACK_Setup(callback.pmWindow, VESA_PMSetWindow, CB_RETN, PhysMake(0xc000,int10.rom.used), "VESA PM Set Window");
	/* PM Set start call */
	int10.rom.pmode_interface_start = int10.rom.used - RealOff( int10.rom.pmode_interface );
	phys_writew( Real2Phys(int10.rom.pmode_interface) + 2, int10.rom.pmode_interface_start);
	callback.pmStart=CALLBACK_Allocate();
	int10.rom.used += (Bit16u)CALLBACK_Setup(callback.pmStart, VESA_PMSetStart, CB_RETN, PhysMake(0xc000,int10.rom.used), "VESA PM Set Start");
	/* PM Set Palette call */
	int10.rom.pmode_interface_palette = int10.rom.used - RealOff( int10.rom.pmode_interface );
	phys_writew( Real2Phys(int10.rom.pmode_interface) + 4, int10.rom.pmode_interface_palette);
	callback.pmPalette=CALLBACK_Allocate();
	int10.rom.used += (Bit16u)CALLBACK_Setup(callback.pmPalette, VESA_PMSetPalette, CB_RETN, PhysMake(0xc000,int10.rom.used), "VESA PM Set Palette");
	/* Finalize the size and clear the required ports pointer */
	phys_writew( Real2Phys(int10.rom.pmode_interface) + 6, 0);
	int10.rom.pmode_interface_size=int10.rom.used - RealOff( int10.rom.pmode_interface );
}
Esempio n. 6
0
/* write a block into physical memory */
static void DMA_BlockWrite(PhysPt pt,void * data,Bitu size) {
	Bit8u * read=(Bit8u *) data;
	for ( ; size ; size--, pt++) {
		Bitu page = pt >> 12;
		/* care for EMS pageframe etc. */
		if (page < EMM_PAGEFRAME4K) page = paging.firstmb[page];
		else if (page < EMM_PAGEFRAME4K+0x10) page = ems_board_mapping[page];
		else if (page < LINK_START) page = paging.firstmb[page];
		phys_writeb(page*4096 + (pt & 4095), *read++);
	}
}
Esempio n. 7
0
void INT10_SetupBasicVideoParameterTable(void) {
	/* video parameter table at F000:F0A4 */
	RealSetVec(0x1d,RealMake(0xF000, 0xF0A4));
	switch (machine) {
	case MCH_TANDY:
		for (Bit16u i = 0; i < sizeof(vparams_tandy); i++) {
			phys_writeb(0xFF0A4+i,vparams_tandy[i]);
		}
		break;
	case MCH_PCJR:
		for (Bit16u i = 0; i < sizeof(vparams_pcjr); i++) {
			phys_writeb(0xFF0A4+i,vparams_pcjr[i]);
		}
		break;
	default:
		for (Bit16u i = 0; i < sizeof(vparams); i++) {
			phys_writeb(0xFF0A4+i,vparams[i]);
		}
		break;
	}
}
Esempio n. 8
0
void SVGA_Setup_ParadisePVGA1A(void) {
	svga.write_p3cf = &write_p3cf_pvga1a;
	svga.read_p3cf = &read_p3cf_pvga1a;

	svga.set_video_mode = &FinishSetMode_PVGA1A;
	svga.determine_mode = &DetermineMode_PVGA1A;
	svga.set_clock = &SetClock_PVGA1A;
	svga.get_clock = &GetClock_PVGA1A;
	svga.accepts_mode = &AcceptsMode_PVGA1A;

	VGA_SetClock(0,CLK_25);
	VGA_SetClock(1,CLK_28);
	VGA_SetClock(2,32400); // could not find documentation
	VGA_SetClock(3,35900);

	// Adjust memory, default to 512K
	if (vga.vmemsize == 0)
		vga.vmemsize = 512*1024;

	if (vga.vmemsize < 512*1024)	{
		vga.vmemsize = 256*1024;
		pvga1a.PR1 = 1<<6;
	} else if (vga.vmemsize > 512*1024) {
		vga.vmemsize = 1024*1024;
		pvga1a.PR1 = 3<<6;
	} else {
		pvga1a.PR1 = 2<<6;
	}

	// Paradise ROM signature
	PhysPt rom_base=PhysMake(0xc000,0);
	phys_writeb(rom_base+0x007d,'V');
	phys_writeb(rom_base+0x007e,'G');
	phys_writeb(rom_base+0x007f,'A');
	phys_writeb(rom_base+0x0080,'=');

	IO_Write(0x3cf, 0x05); // Enable!
}
Esempio n. 9
0
void INT10_SetupBasicVideoParameterTable(void) {
	const unsigned char *copy = NULL;
	size_t copy_sz = 0;
	Bitu ofs;

	switch (machine) {
		case MCH_TANDY:
			copy = vparams_tandy;
			copy_sz = sizeof(vparams_tandy);
			break;
		case MCH_PCJR:
			copy = vparams_pcjr;
			copy_sz = sizeof(vparams_pcjr);
			break;
		default:
			copy = vparams;
			copy_sz = sizeof(vparams);
			break;
	}

	if (BIOS_VIDEO_TABLE_LOCATION == ~0 || BIOS_VIDEO_TABLE_SIZE != (Bitu)copy_sz) {
		if (rom_bios_vptable_enable) {
			/* TODO: Free previous block */

			BIOS_VIDEO_TABLE_SIZE = copy_sz;
			if (mainline_compatible_bios_mapping)
				BIOS_VIDEO_TABLE_LOCATION = RealMake(0xf000,0xf0a4);
			else
				BIOS_VIDEO_TABLE_LOCATION = PhysToReal416(ROMBIOS_GetMemory(copy_sz,"BIOS video table (INT 1Dh)")); /* TODO: make option */

			/* NTS: Failure to allocate means BIOS_VIDEO_TABLE_LOCATION == 0 */
		}
		else {
			BIOS_VIDEO_TABLE_LOCATION = 0;
		}
	}

	RealSetVec(0x1d,BIOS_VIDEO_TABLE_LOCATION);
	ofs = RealToPhys(BIOS_VIDEO_TABLE_LOCATION);
	if (ofs != 0) {
		if (copy && copy_sz <= BIOS_VIDEO_TABLE_SIZE) {
			for (size_t i=0;i < copy_sz;i++)
				phys_writeb(ofs+i,copy[i]);
		}
		else {
			E_Exit("Somehow, INT 10 video param table too large");
		}
	}
}
Esempio n. 10
0
void CALLBACK_Init(Section* /*sec*/) {
	Bitu i;
	for (i=0;i<CB_MAX;i++) {
		CallBack_Handlers[i]=&illegal_handler;
	}

	/* Setup the Stop Handler */
	call_stop=CALLBACK_Allocate();
	CallBack_Handlers[call_stop]=stop_handler;
	CALLBACK_SetDescription(call_stop,"stop");
	phys_writeb(CALLBACK_PhysPointer(call_stop)+0,0xFE);
	phys_writeb(CALLBACK_PhysPointer(call_stop)+1,0x38);
	phys_writew(CALLBACK_PhysPointer(call_stop)+2,(Bit16u)call_stop);

	/* Setup the idle handler */
	call_idle=CALLBACK_Allocate();
	CallBack_Handlers[call_idle]=stop_handler;
	CALLBACK_SetDescription(call_idle,"idle");
	for (i=0;i<=11;i++) phys_writeb(CALLBACK_PhysPointer(call_idle)+i,0x90);
	phys_writeb(CALLBACK_PhysPointer(call_idle)+12,0xFE);
	phys_writeb(CALLBACK_PhysPointer(call_idle)+13,0x38);
	phys_writew(CALLBACK_PhysPointer(call_idle)+14,(Bit16u)call_idle);

	/* Default handlers for unhandled interrupts that have to be non-null */
	call_default=CALLBACK_Allocate();
	CALLBACK_Setup(call_default,&default_handler,CB_IRET,"default");
	call_default2=CALLBACK_Allocate();
	CALLBACK_Setup(call_default2,&default_handler,CB_IRET,"default");

	/* Only setup default handler for first part of interrupt table */
	for (Bit16u ct=0;ct<0x60;ct++) {
		real_writed(0,ct*4,CALLBACK_RealPointer(call_default));
	}
	for (Bit16u ct=0x68;ct<0x70;ct++) {
		real_writed(0,ct*4,CALLBACK_RealPointer(call_default));
	}
	/* Setup block of 0xCD 0xxx instructions */
	PhysPt rint_base=CALLBACK_GetBase()+CB_MAX*CB_SIZE;
	for (i=0;i<=0xff;i++) {
		phys_writeb(rint_base,0xCD);
		phys_writeb(rint_base+1,(Bit8u)i);
		phys_writeb(rint_base+2,0xFE);
		phys_writeb(rint_base+3,0x38);
		phys_writew(rint_base+4,(Bit16u)call_stop);
		rint_base+=6;

	}
	// setup a few interrupt handlers that point to bios IRETs by default
	real_writed(0,0x0e*4,CALLBACK_RealPointer(call_default2));	//design your own railroad
	real_writed(0,0x66*4,CALLBACK_RealPointer(call_default));	//war2d
	real_writed(0,0x67*4,CALLBACK_RealPointer(call_default));
	real_writed(0,0x68*4,CALLBACK_RealPointer(call_default));
	real_writed(0,0x5c*4,CALLBACK_RealPointer(call_default));	//Network stuff
	//real_writed(0,0xf*4,0); some games don't like it

	call_priv_io=CALLBACK_Allocate();

	// virtualizable in-out opcodes
	phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x00,(Bit8u)0xec);	// in al, dx
	phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x01,(Bit8u)0xcb);	// retf
	phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x02,(Bit8u)0xed);	// in ax, dx
	phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x03,(Bit8u)0xcb);	// retf
	phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x04,(Bit8u)0x66);	// in eax, dx
	phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x05,(Bit8u)0xed);
	phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x06,(Bit8u)0xcb);	// retf

	phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x08,(Bit8u)0xee);	// out dx, al
	phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x09,(Bit8u)0xcb);	// retf
	phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0a,(Bit8u)0xef);	// out dx, ax
	phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0b,(Bit8u)0xcb);	// retf
	phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0c,(Bit8u)0x66);	// out dx, eax
	phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0d,(Bit8u)0xef);
	phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0e,(Bit8u)0xcb);	// retf
}
Esempio n. 11
0
void CALLBACK_RemoveSetup(Bitu callback) {
	for (Bitu i = 0;i < CB_SIZE;i++) {
		phys_writeb(CALLBACK_PhysPointer(callback)+i ,(Bit8u) 0x00);
	}
}
Esempio n. 12
0
Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_cb=true) {
	if (callback>=CB_MAX)
		return 0;
	switch (type) {
	case CB_RETN:
		if (use_cb) {
			phys_writeb(physAddress+0x00,(Bit8u)0xFE);	//GRP 4
			phys_writeb(physAddress+0x01,(Bit8u)0x38);	//Extra Callback instruction
			phys_writew(physAddress+0x02,(Bit16u)callback);	//The immediate word
			physAddress+=4;
		}
		phys_writeb(physAddress+0x00,(Bit8u)0xC3);		//A RETN Instruction
		return (use_cb?5:1);
	case CB_RETF:
		if (use_cb) {
			phys_writeb(physAddress+0x00,(Bit8u)0xFE);	//GRP 4
			phys_writeb(physAddress+0x01,(Bit8u)0x38);	//Extra Callback instruction
			phys_writew(physAddress+0x02,(Bit16u)callback);	//The immediate word
			physAddress+=4;
		}
		phys_writeb(physAddress+0x00,(Bit8u)0xCB);		//A RETF Instruction
		return (use_cb?5:1);
	case CB_RETF8:
		if (use_cb) {
			phys_writeb(physAddress+0x00,(Bit8u)0xFE);	//GRP 4
			phys_writeb(physAddress+0x01,(Bit8u)0x38);	//Extra Callback instruction
			phys_writew(physAddress+0x02,(Bit16u)callback);	//The immediate word
			physAddress+=4;
		}
		phys_writeb(physAddress+0x00,(Bit8u)0xCA);		//A RETF 8 Instruction
		phys_writew(physAddress+0x01,(Bit16u)0x0008);
		return (use_cb?7:3);
	case CB_IRET:
		if (use_cb) {
			phys_writeb(physAddress+0x00,(Bit8u)0xFE);	//GRP 4
			phys_writeb(physAddress+0x01,(Bit8u)0x38);	//Extra Callback instruction
			phys_writew(physAddress+0x02,(Bit16u)callback);		//The immediate word
			physAddress+=4;
		}
		phys_writeb(physAddress+0x00,(Bit8u)0xCF);		//An IRET Instruction
		return (use_cb?5:1);
	case CB_IRETD:
		if (use_cb) {
			phys_writeb(physAddress+0x00,(Bit8u)0xFE);	//GRP 4
			phys_writeb(physAddress+0x01,(Bit8u)0x38);	//Extra Callback instruction
			phys_writew(physAddress+0x02,(Bit16u)callback);		//The immediate word
			physAddress+=4;
		}
		phys_writeb(physAddress+0x00,(Bit8u)0x66);		//An IRETD Instruction
		phys_writeb(physAddress+0x01,(Bit8u)0xCF);
		return (use_cb?6:2);
	case CB_IRET_STI:
		phys_writeb(physAddress+0x00,(Bit8u)0xFB);		//STI
		if (use_cb) {
			phys_writeb(physAddress+0x01,(Bit8u)0xFE);	//GRP 4
			phys_writeb(physAddress+0x02,(Bit8u)0x38);	//Extra Callback instruction
			phys_writew(physAddress+0x03,(Bit16u)callback);	//The immediate word
			physAddress+=4;
		}
		phys_writeb(physAddress+0x01,(Bit8u)0xCF);		//An IRET Instruction
		return (use_cb?6:2);
	case CB_IRET_EOI_PIC1:
		if (use_cb) {
			phys_writeb(physAddress+0x00,(Bit8u)0xFE);	//GRP 4
			phys_writeb(physAddress+0x01,(Bit8u)0x38);	//Extra Callback instruction
			phys_writew(physAddress+0x02,(Bit16u)callback);		//The immediate word
			physAddress+=4;
		}
		phys_writeb(physAddress+0x00,(Bit8u)0x50);		// push ax
		phys_writeb(physAddress+0x01,(Bit8u)0xb0);		// mov al, 0x20
		phys_writeb(physAddress+0x02,(Bit8u)0x20);
		phys_writeb(physAddress+0x03,(Bit8u)0xe6);		// out 0x20, al
		phys_writeb(physAddress+0x04,(Bit8u)0x20);
		phys_writeb(physAddress+0x05,(Bit8u)0x58);		// pop ax
		phys_writeb(physAddress+0x06,(Bit8u)0xcf);		//An IRET Instruction
		return (use_cb?0x0b:0x07);
	case CB_IRQ0:	// timer int8
		phys_writeb(physAddress+0x00,(Bit8u)0xFB);		//STI
		if (use_cb) {
			phys_writeb(physAddress+0x01,(Bit8u)0xFE);	//GRP 4
			phys_writeb(physAddress+0x02,(Bit8u)0x38);	//Extra Callback instruction
			phys_writew(physAddress+0x03,(Bit16u)callback);		//The immediate word
			physAddress+=4;
		}
		phys_writeb(physAddress+0x01,(Bit8u)0x1e);		// push ds
		phys_writeb(physAddress+0x02,(Bit8u)0x50);		// push ax
		phys_writeb(physAddress+0x03,(Bit8u)0x52);		// push dx
		phys_writew(physAddress+0x04,(Bit16u)0x1ccd);	// int 1c
		phys_writeb(physAddress+0x06,(Bit8u)0xfa);		// cli
		phys_writew(physAddress+0x07,(Bit16u)0x20b0);	// mov al, 0x20
		phys_writew(physAddress+0x09,(Bit16u)0x20e6);	// out 0x20, al
		phys_writeb(physAddress+0x0b,(Bit8u)0x5a);		// pop dx
		phys_writeb(physAddress+0x0c,(Bit8u)0x58);		// pop ax
		phys_writeb(physAddress+0x0d,(Bit8u)0x1f);		// pop ds
		phys_writeb(physAddress+0x0e,(Bit8u)0xcf);		//An IRET Instruction
		return (use_cb?0x13:0x0f);
	case CB_IRQ1:	// keyboard int9
		phys_writeb(physAddress+0x00,(Bit8u)0x50);			// push ax
		phys_writew(physAddress+0x01,(Bit16u)0x60e4);		// in al, 0x60
		phys_writew(physAddress+0x03,(Bit16u)0x4fb4);		// mov ah, 0x4f
		phys_writeb(physAddress+0x05,(Bit8u)0xf9);			// stc
		phys_writew(physAddress+0x06,(Bit16u)0x15cd);		// int 15
		if (use_cb) {
			phys_writew(physAddress+0x08,(Bit16u)0x0473);	// jc skip
			phys_writeb(physAddress+0x0a,(Bit8u)0xFE);		//GRP 4
			phys_writeb(physAddress+0x0b,(Bit8u)0x38);		//Extra Callback instruction
			phys_writew(physAddress+0x0c,(Bit16u)callback);			//The immediate word
			// jump here to (skip):
			physAddress+=6;
		}
		phys_writeb(physAddress+0x08,(Bit8u)0xfa);			// cli
		phys_writew(physAddress+0x09,(Bit16u)0x20b0);		// mov al, 0x20
		phys_writew(physAddress+0x0b,(Bit16u)0x20e6);		// out 0x20, al
		phys_writeb(physAddress+0x0d,(Bit8u)0x58);			// pop ax
		phys_writeb(physAddress+0x0e,(Bit8u)0xcf);			//An IRET Instruction
		return (use_cb?0x15:0x0f);
	case CB_IRQ9:	// pic cascade interrupt
		if (use_cb) {
			phys_writeb(physAddress+0x00,(Bit8u)0xFE);	//GRP 4
			phys_writeb(physAddress+0x01,(Bit8u)0x38);	//Extra Callback instruction
			phys_writew(physAddress+0x02,(Bit16u)callback);		//The immediate word
			physAddress+=4;
		}
		phys_writeb(physAddress+0x00,(Bit8u)0x50);		// push ax
		phys_writew(physAddress+0x01,(Bit16u)0x61b0);	// mov al, 0x61
		phys_writew(physAddress+0x03,(Bit16u)0xa0e6);	// out 0xa0, al
		phys_writew(physAddress+0x05,(Bit16u)0x0acd);	// int a
		phys_writeb(physAddress+0x07,(Bit8u)0xfa);		// cli
		phys_writeb(physAddress+0x08,(Bit8u)0x58);		// pop ax
		phys_writeb(physAddress+0x09,(Bit8u)0xcf);		//An IRET Instruction
		return (use_cb?0x0e:0x0a);
	case CB_IRQ12:	// ps2 mouse int74
		if (!use_cb) E_Exit("int74 callback must implement a callback handler!");
		phys_writeb(physAddress+0x00,(Bit8u)0x1e);		// push ds
		phys_writeb(physAddress+0x01,(Bit8u)0x06);		// push es
		phys_writew(physAddress+0x02,(Bit16u)0x6066);	// pushad
		phys_writeb(physAddress+0x04,(Bit8u)0xfc);		// cld
		phys_writeb(physAddress+0x05,(Bit8u)0xfb);		// sti
		phys_writeb(physAddress+0x06,(Bit8u)0xFE);		//GRP 4
		phys_writeb(physAddress+0x07,(Bit8u)0x38);		//Extra Callback instruction
		phys_writew(physAddress+0x08,(Bit16u)callback);			//The immediate word
		return 0x0a;
	case CB_IRQ12_RET:	// ps2 mouse int74 return
		if (use_cb) {
			phys_writeb(physAddress+0x00,(Bit8u)0xFE);	//GRP 4
			phys_writeb(physAddress+0x01,(Bit8u)0x38);	//Extra Callback instruction
			phys_writew(physAddress+0x02,(Bit16u)callback);		//The immediate word
			physAddress+=4;
		}
		phys_writeb(physAddress+0x00,(Bit8u)0xfa);		// cli
		phys_writew(physAddress+0x01,(Bit16u)0x20b0);	// mov al, 0x20
		phys_writew(physAddress+0x03,(Bit16u)0xa0e6);	// out 0xa0, al
		phys_writew(physAddress+0x05,(Bit16u)0x20e6);	// out 0x20, al
		phys_writew(physAddress+0x07,(Bit16u)0x6166);	// popad
		phys_writeb(physAddress+0x09,(Bit8u)0x07);		// pop es
		phys_writeb(physAddress+0x0a,(Bit8u)0x1f);		// pop ds
		phys_writeb(physAddress+0x0b,(Bit8u)0xcf);		//An IRET Instruction
		return (use_cb?0x10:0x0c);
	case CB_IRQ6_PCJR:	// pcjr keyboard interrupt
		phys_writeb(physAddress+0x00,(Bit8u)0x50);			// push ax
		phys_writew(physAddress+0x01,(Bit16u)0x60e4);		// in al, 0x60
		phys_writew(physAddress+0x03,(Bit16u)0xe03c);		// cmp al, 0xe0
		if (use_cb) {
			phys_writew(physAddress+0x05,(Bit16u)0x0674);	// je skip
			phys_writeb(physAddress+0x07,(Bit8u)0xFE);		//GRP 4
			phys_writeb(physAddress+0x08,(Bit8u)0x38);		//Extra Callback instruction
			phys_writew(physAddress+0x09,(Bit16u)callback);			//The immediate word
			physAddress+=4;
		} else {
			phys_writew(physAddress+0x05,(Bit16u)0x0274);	// je skip
		}
		phys_writew(physAddress+0x07,(Bit16u)0x09cd);		// int 9
		// jump here to (skip):
		phys_writeb(physAddress+0x09,(Bit8u)0xfa);			// cli
		phys_writew(physAddress+0x0a,(Bit16u)0x20b0);		// mov al, 0x20
		phys_writew(physAddress+0x0c,(Bit16u)0x20e6);		// out 0x20, al
		phys_writeb(physAddress+0x0e,(Bit8u)0x58);			// pop ax
		phys_writeb(physAddress+0x0f,(Bit8u)0xcf);			//An IRET Instruction
		return (use_cb?0x14:0x10);
	case CB_MOUSE:
		phys_writew(physAddress+0x00,(Bit16u)0x07eb);		// jmp i33hd
		physAddress+=9;
		// jump here to (i33hd):
		if (use_cb) {
			phys_writeb(physAddress+0x00,(Bit8u)0xFE);	//GRP 4
			phys_writeb(physAddress+0x01,(Bit8u)0x38);	//Extra Callback instruction
			phys_writew(physAddress+0x02,(Bit16u)callback);		//The immediate word
			physAddress+=4;
		}
		phys_writeb(physAddress+0x00,(Bit8u)0xCF);		//An IRET Instruction
		return (use_cb?0x0e:0x0a);
	case CB_INT16:
		phys_writeb(physAddress+0x00,(Bit8u)0xFB);		//STI
		if (use_cb) {
			phys_writeb(physAddress+0x01,(Bit8u)0xFE);	//GRP 4
			phys_writeb(physAddress+0x02,(Bit8u)0x38);	//Extra Callback instruction
			phys_writew(physAddress+0x03,(Bit16u)callback);	//The immediate word
			physAddress+=4;
		}
		phys_writeb(physAddress+0x01,(Bit8u)0xCF);		//An IRET Instruction
		for (Bitu i=0;i<=0x0b;i++) phys_writeb(physAddress+0x02+i,0x90);
		phys_writew(physAddress+0x0e,(Bit16u)0xedeb);	//jmp callback
		return (use_cb?0x10:0x0c);
	case CB_INT29:	// fast console output
		if (use_cb) {
			phys_writeb(physAddress+0x00,(Bit8u)0xFE);	//GRP 4
			phys_writeb(physAddress+0x01,(Bit8u)0x38);	//Extra Callback instruction
			phys_writew(physAddress+0x02,(Bit16u)callback);		//The immediate word
			physAddress+=4;
		}
		phys_writeb(physAddress+0x00,(Bit8u)0x50);	// push ax
		phys_writeb(physAddress+0x01,(Bit8u)0x53);	// push bx
		phys_writew(physAddress+0x02,(Bit16u)0x0eb4);	// mov ah, 0x0e
		phys_writeb(physAddress+0x04,(Bit8u)0xbb);	// mov bx,
		phys_writew(physAddress+0x05,(Bit16u)0x0007);	// 0x0007
		phys_writew(physAddress+0x07,(Bit16u)0x10cd);	// int 10
		phys_writeb(physAddress+0x09,(Bit8u)0x5b);	// pop bx
		phys_writeb(physAddress+0x0a,(Bit8u)0x58);	// pop ax
		phys_writeb(physAddress+0x0b,(Bit8u)0xcf);	//An IRET Instruction
		return (use_cb?0x10:0x0c);
	case CB_HOOKABLE:
		phys_writeb(physAddress+0x00,(Bit8u)0xEB);		//jump near
		phys_writeb(physAddress+0x01,(Bit8u)0x03);		//offset
		phys_writeb(physAddress+0x02,(Bit8u)0x90);		//NOP
		phys_writeb(physAddress+0x03,(Bit8u)0x90);		//NOP
		phys_writeb(physAddress+0x04,(Bit8u)0x90);		//NOP
		if (use_cb) {
			phys_writeb(physAddress+0x05,(Bit8u)0xFE);	//GRP 4
			phys_writeb(physAddress+0x06,(Bit8u)0x38);	//Extra Callback instruction
			phys_writew(physAddress+0x07,(Bit16u)callback);		//The immediate word
			physAddress+=4;
		}
		phys_writeb(physAddress+0x05,(Bit8u)0xCB);		//A RETF Instruction
		return (use_cb?0x0a:0x06);
	case CB_TDE_IRET:	// TandyDAC end transfer
		if (use_cb) {
			phys_writeb(physAddress+0x00,(Bit8u)0xFE);	//GRP 4
			phys_writeb(physAddress+0x01,(Bit8u)0x38);	//Extra Callback instruction
			phys_writew(physAddress+0x02,(Bit16u)callback);		//The immediate word
			physAddress+=4;
		}
		phys_writeb(physAddress+0x00,(Bit8u)0x50);		// push ax
		phys_writeb(physAddress+0x01,(Bit8u)0xb8);		// mov ax, 0x91fb
		phys_writew(physAddress+0x02,(Bit16u)0x91fb);
		phys_writew(physAddress+0x04,(Bit16u)0x15cd);	// int 15
		phys_writeb(physAddress+0x06,(Bit8u)0xfa);		// cli
		phys_writew(physAddress+0x07,(Bit16u)0x20b0);	// mov al, 0x20
		phys_writew(physAddress+0x09,(Bit16u)0x20e6);	// out 0x20, al
		phys_writeb(physAddress+0x0b,(Bit8u)0x58);		// pop ax
		phys_writeb(physAddress+0x0c,(Bit8u)0xcf);		//An IRET Instruction
		return (use_cb?0x11:0x0d);
/*	case CB_IPXESR:		// IPX ESR
		if (!use_cb) E_Exit("ipx esr must implement a callback handler!");
		phys_writeb(physAddress+0x00,(Bit8u)0x1e);		// push ds
		phys_writeb(physAddress+0x01,(Bit8u)0x06);		// push es
		phys_writew(physAddress+0x02,(Bit16u)0xa00f);	// push fs
		phys_writew(physAddress+0x04,(Bit16u)0xa80f);	// push gs
		phys_writeb(physAddress+0x06,(Bit8u)0x60);		// pusha
		phys_writeb(physAddress+0x07,(Bit8u)0xFE);		//GRP 4
		phys_writeb(physAddress+0x08,(Bit8u)0x38);		//Extra Callback instruction
		phys_writew(physAddress+0x09,(Bit16u)callback);	//The immediate word
		phys_writeb(physAddress+0x0b,(Bit8u)0xCB);		//A RETF Instruction
		return 0x0c;
	case CB_IPXESR_RET:		// IPX ESR return
		if (use_cb) E_Exit("ipx esr return must not implement a callback handler!");
		phys_writeb(physAddress+0x00,(Bit8u)0xfa);		// cli
		phys_writew(physAddress+0x01,(Bit16u)0x20b0);	// mov al, 0x20
		phys_writew(physAddress+0x03,(Bit16u)0xa0e6);	// out 0xa0, al
		phys_writew(physAddress+0x05,(Bit16u)0x20e6);	// out 0x20, al
		phys_writeb(physAddress+0x07,(Bit8u)0x61);		// popa
		phys_writew(physAddress+0x08,(Bit16u)0xA90F);	// pop gs
		phys_writew(physAddress+0x0a,(Bit16u)0xA10F);	// pop fs
		phys_writeb(physAddress+0x0c,(Bit8u)0x07);		// pop es
		phys_writeb(physAddress+0x0d,(Bit8u)0x1f);		// pop ds
		phys_writeb(physAddress+0x0e,(Bit8u)0xcf);		//An IRET Instruction
		return 0x0f; */
	case CB_INT21:
		phys_writeb(physAddress+0x00,(Bit8u)0xFB);		//STI
		if (use_cb) {
			phys_writeb(physAddress+0x01,(Bit8u)0xFE);	//GRP 4
			phys_writeb(physAddress+0x02,(Bit8u)0x38);	//Extra Callback instruction
			phys_writew(physAddress+0x03,(Bit16u)callback);	//The immediate word
			physAddress+=4;
		}
		phys_writeb(physAddress+0x01,(Bit8u)0xCF);		//An IRET Instruction
		phys_writeb(physAddress+0x02,(Bit8u)0xCB);		//A RETF Instruction
		phys_writeb(physAddress+0x03,(Bit8u)0x51);		// push cx
		phys_writeb(physAddress+0x04,(Bit8u)0xB9);		// mov cx,
		phys_writew(physAddress+0x05,(Bit16u)0x0140);		// 0x140
		phys_writew(physAddress+0x07,(Bit16u)0xFEE2);		// loop $-2
		phys_writeb(physAddress+0x09,(Bit8u)0x59);		// pop cx
		phys_writeb(physAddress+0x0A,(Bit8u)0xCF);		//An IRET Instruction
		return (use_cb?15:11);
	case CB_INT13:
		phys_writeb(physAddress+0x00,(Bit8u)0xFB);		//STI
		if (use_cb) {
			phys_writeb(physAddress+0x01,(Bit8u)0xFE);	//GRP 4
			phys_writeb(physAddress+0x02,(Bit8u)0x38);	//Extra Callback instruction
			phys_writew(physAddress+0x03,(Bit16u)callback);	//The immediate word
			physAddress+=4;
		}
		phys_writeb(physAddress+0x01,(Bit8u)0xCF);		//An IRET Instruction
		phys_writew(physAddress+0x02,(Bit16u)0x0ECD);		// int 0e
		phys_writeb(physAddress+0x04,(Bit8u)0xCF);		//An IRET Instruction
		return (use_cb?9:5);
	default:
		E_Exit("CALLBACK:Setup:Illegal type %d",type);
	}
	return 0;
}
void CALLBACK_Init(Section* sec) {
	Bitu i;
	for (i=0;i<CB_MAX;i++) {
		CallBack_Handlers[i]=&illegal_handler;
	}
	/* Setup the Stop Handler */
	call_stop=CALLBACK_Allocate();
	CallBack_Handlers[call_stop]=stop_handler;
	CALLBACK_SetDescription(call_stop,"stop");
	phys_writeb(CB_BASE+(call_stop<<4)+0,0xFE);
	phys_writeb(CB_BASE+(call_stop<<4)+1,0x38);
	phys_writew(CB_BASE+(call_stop<<4)+2,call_stop);
	/* Setup the idle handler */
	call_idle=CALLBACK_Allocate();
	CallBack_Handlers[call_idle]=stop_handler;
	CALLBACK_SetDescription(call_idle,"idle");
	for (i=0;i<=11;i++) phys_writeb(CB_BASE+(call_idle<<4)+i,0x90);
	phys_writeb(CB_BASE+(call_idle<<4)+12,0xFE);
	phys_writeb(CB_BASE+(call_idle<<4)+13,0x38);
	phys_writew(CB_BASE+(call_idle<<4)+14,call_idle);

	/* Setup all Interrupt to point to the default handler */
	call_default=CALLBACK_Allocate();
	CALLBACK_Setup(call_default,&default_handler,CB_IRET,"default");
   
	/* Only setup default handler for first half of interrupt table */
	for (i=0;i<0x40;i++) {
		real_writed(0,i*4,CALLBACK_RealPointer(call_default));
	}
	/* Setup block of 0xCD 0xxx instructions */
	PhysPt rint_base=CB_BASE+CB_MAX*16;
	for (i=0;i<=0xff;i++) {
		phys_writeb(rint_base,0xCD);
		phys_writeb(rint_base+1,i);
		phys_writeb(rint_base+2,0xFE);
		phys_writeb(rint_base+3,0x38);
		phys_writew(rint_base+4,call_stop);
		rint_base+=6;

	}
	real_writed(0,0x67*4,CALLBACK_RealPointer(call_default));
	real_writed(0,0x5c*4,CALLBACK_RealPointer(call_default)); //Network stuff
	//real_writed(0,0xf*4,0); some games don't like it

	call_priv_io=CALLBACK_Allocate();

	phys_writeb(CB_BASE+(call_priv_io<<4)+0x00,(Bit8u)0xec);	// in al, dx
	phys_writeb(CB_BASE+(call_priv_io<<4)+0x01,(Bit8u)0xcb);	// retf
	phys_writeb(CB_BASE+(call_priv_io<<4)+0x02,(Bit8u)0xed);	// in ax, dx
	phys_writeb(CB_BASE+(call_priv_io<<4)+0x03,(Bit8u)0xcb);	// retf
	phys_writeb(CB_BASE+(call_priv_io<<4)+0x04,(Bit8u)0x66);	// in eax, dx
	phys_writeb(CB_BASE+(call_priv_io<<4)+0x05,(Bit8u)0xed);
	phys_writeb(CB_BASE+(call_priv_io<<4)+0x06,(Bit8u)0xcb);	// retf

	phys_writeb(CB_BASE+(call_priv_io<<4)+0x08,(Bit8u)0xee);	// out dx, al
	phys_writeb(CB_BASE+(call_priv_io<<4)+0x09,(Bit8u)0xcb);	// retf
	phys_writeb(CB_BASE+(call_priv_io<<4)+0x0a,(Bit8u)0xef);	// out dx, ax
	phys_writeb(CB_BASE+(call_priv_io<<4)+0x0b,(Bit8u)0xcb);	// retf
	phys_writeb(CB_BASE+(call_priv_io<<4)+0x0c,(Bit8u)0x66);	// out dx, eax
	phys_writeb(CB_BASE+(call_priv_io<<4)+0x0d,(Bit8u)0xef);
	phys_writeb(CB_BASE+(call_priv_io<<4)+0x0e,(Bit8u)0xcb);	// retf
}
Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress) {
	if (callback>=CB_MAX) 
		return 0;
	switch (type) {
	case CB_RETN:
		phys_writeb(physAddress+0,(Bit8u)0xFE);	//GRP 4
		phys_writeb(physAddress+1,(Bit8u)0x38);	//Extra Callback instruction
		phys_writew(physAddress+2, callback);	//The immediate word
		phys_writeb(physAddress+4,(Bit8u)0xC3);	//A RETN Instruction
		return 5;
	case CB_RETF:
		phys_writeb(physAddress+0,(Bit8u)0xFE);	//GRP 4
		phys_writeb(physAddress+1,(Bit8u)0x38);	//Extra Callback instruction
		phys_writew(physAddress+2, callback);	//The immediate word
		phys_writeb(physAddress+4,(Bit8u)0xCB);	//A RETF Instruction
		return 5;
	case CB_IRET:
		phys_writeb(physAddress+0,(Bit8u)0xFE);	//GRP 4
		phys_writeb(physAddress+1,(Bit8u)0x38);	//Extra Callback instruction
		phys_writew(physAddress+2,callback);	//The immediate word
		phys_writeb(physAddress+4,(Bit8u)0xCF);	//An IRET Instruction
		return 5;
	case CB_IRET_STI:
		phys_writeb(physAddress+0,(Bit8u)0xFB);	//STI
		phys_writeb(physAddress+1,(Bit8u)0xFE);	//GRP 4
		phys_writeb(physAddress+2,(Bit8u)0x38);	//Extra Callback instruction
		phys_writew(physAddress+3, callback);	//The immediate word
		phys_writeb(physAddress+5,(Bit8u)0xCF);	//An IRET Instruction
		return 6;
	default:
		E_Exit("CALLBACK:Setup:Illegal type %d",type);
	}
	return 0;
}
void CALLBACK_RemoveSetup(Bitu callback) {
	for (Bitu i = 0;i < 16;i++) {
		phys_writeb(CB_BASE+(callback<<4)+i ,(Bit8u) 0x00);
	}
}