|
|
uae-0.6.4
/*
* UAE - The Un*x Amiga Emulator
*
* DOS VESA BIOS / VGA / Mode X graphics interface.
*
* (c) 1995 Bernd Schmidt
* (c) 1996 Gustavo Goedert
*/
#include "sysconfig.h"
#include "sysdeps.h"
#include <dos.h>
#include <go32.h>
#include <dpmi.h>
#include <sys/movedata.h>
#include <sys/exceptn.h>
#include <sys/farptr.h>
#include "config.h"
#include "options.h"
#include "memory.h"
#include "custom.h"
#include "newcpu.h"
#include "keyboard.h"
#include "xwin.h"
#include "keybuf.h"
#include "disk.h"
#include "dos-ui.h"
#define PACKED __attribute__ ((packed))
#define ALIGN(x) ((((int)(x)>>12)<<12)+4096)
static FILE *logfile;
enum VBE_MemoryModels { TextMode, CGA_Graphics, HerculesGraphics,
Planar, PackedPixel, ModeX, DirectColor, YUV } ;
typedef struct {
char VbeSignature[4] PACKED; // = VBE2
short VbeVersion PACKED;
char *OemStringPtr PACKED;
char Capabilities[4] PACKED;
unsigned int VideoModePtr PACKED;
short TotalMemory PACKED;
short OemSoftwareRev PACKED;
char *OemVendorNamePtr PACKED;
char *OemProductNamePtr PACKED;
char *OemProductRevPtr PACKED;
char Reserved[222] PACKED;
char OemData[256] PACKED;
} T_VBE_VbeInfoBlock;
typedef struct {
// Mandatory information for all VBE revisions
short ModeAttributes PACKED;
char WinAAttributes PACKED;
char WinBAttributes PACKED;
short WinGranularity PACKED;
unsigned short WinSize PACKED;
unsigned short WinASegment PACKED;
unsigned short WinBSegment PACKED;
unsigned int WinFuncPtr PACKED;
short BytesPerScanLine PACKED;
// Mandatory information for VBE 1.2 and above
short XResolution PACKED;
short YResolution PACKED;
char XCharSize PACKED;
char YCharSize PACKED;
char NumberOfPlanes PACKED;
char BitsPerPixel PACKED;
char NumberOfBanks PACKED;
char MemoryModel PACKED;
char BankSize PACKED;
char NumberOfImagePages PACKED;
char ReservedA PACKED; // = 1
// Direct Color fields (required for direct/6 and YUV/7 memory models)
char RedMaskSize PACKED;
char RedFieldPosition PACKED;
char GreenMaskSize PACKED;
char GreenFieldPosition PACKED;
char BlueMaskSize PACKED;
char BlueFieldPosition PACKED;
char RsvdMaskSize PACKED;
char RsvdFieldPosition PACKED;
char DirectColorModeInfo PACKED;
// Mandatory information for VBE 2.0 and above
unsigned int PhysBasePtr PACKED;
unsigned int OffScreenMemOffset PACKED;
short OffScreenMemSize PACKED;
char ReservedB[206] PACKED;
} T_VBE_ModeInfoBlock;
typedef struct {
short SetWindowOffset PACKED;
short SetDisplayStartOffset PACKED;
short SetPrimaryPaletteDataOffset PACKED;
short PortsMemoryOffset PACKED;
} T_VBE_ProtectedModeInterface;
typedef enum { TText, T16, T256, T256X, T32K, T64K, T16M, TNone } T_ModeType;
typedef struct {
int ModeWidth, ModeHeight;
T_ModeType ModeType;
int BitsPerPixel;
int BitsPerColor;
} T_BasicModeInfo;
typedef enum { TVBE, TVGA, TModeX } T_ControlType;
typedef struct {
T_ControlType ControlType;
int mode;
} T_ControlInfo;
void SetGraphicsMode(void);
void SetModeX(int num);
void LoadPalette(void);
int VBE_GetVbeInfoBlock(void);
int VBE_GetModeInfoBlock(short mode);
int VBE_GetProtectedModeInterface(void);
void VBE_ChangeBankRealInterrupt(short BankNumber);
void VBE_ChangeBankRealMode(short BankNumber);
void VBE_ChangeBankProtectMode(short BankNumber);
void DoFlushLineLinear(int y);
void DoFlushLineBuffered(int y);
void PutLineBanked(char *addr, int target_y);
void PutLineVGA16(char *addr, int target_y);
void PutLineVGAX(char *addr, int target_y);
void (*VBE_ChangeBank)(short BankNumber);
void (*DoFlushLine)(int y);
void (*PutLine)(char *addr, int y);
T_ControlInfo ControlInfo;
int RestoreOldVGAMode = 1, OldVGAMode;
short CurrentBankNumber = 0;
short WriteWindow;
unsigned short WinFuncPtrSegment, WinFuncPtrOffset;
unsigned int SetWindow;
short *PortsMemory;
T_VBE_VbeInfoBlock VBE_VbeInfoBlock;
T_VBE_ModeInfoBlock VBE_ModeInfoBlock;
T_VBE_ProtectedModeInterface *VBE_ProtectedModeInterface;
short VBE_ModeList[128];
unsigned int WinLength, WinStart;
int FastWinCalc = 0;
unsigned int WinMask1, WinMask2;
int HasVbe = 0, HasLinear = 0;
int LineLength, LogicalLineLength;
char *LinearBufferPtr;
char *AlignedLinearBufferPtr;
T_BasicModeInfo BasicModeInfo;
unsigned char PaletteData[768];
_go32_dpmi_seginfo PaletteMem;
T_BasicModeInfo Old_VBE_Table[28] = { { 640, 400, T256, 8, 8 },
{ 640, 480, T256, 8, 8 },
{ 800, 600, T16, 8, 4 },
{ 800, 600, T256, 8, 8 },
{ 1024, 768, T16, 8, 4 },
{ 1024, 768, T256, 8, 8 },
{ 1280, 1024, T16, 8, 4 },
{ 1280, 1024, T256, 8, 8 },
{ 80, 60, TText, 0, 0 },
{ 132, 25, TText, 0, 0 },
{ 132, 43, TText, 0, 0 },
{ 132, 50, TText, 0, 0 },
{ 132, 60, TText, 0, 0 },
{ 320, 200, T32K, 16, 15 },
{ 320, 200, T64K, 16, 16 },
{ 320, 200, T16M, 24, 24 },
{ 640, 480, T32K, 16, 15 },
{ 640, 480, T64K, 16, 16 },
{ 640, 480, T16M, 24, 24 },
{ 800, 600, T32K, 16, 15 },
{ 800, 600, T64K, 16, 16 },
{ 800, 600, T16M, 24, 24 },
{ 1024, 768, T32K, 16, 15 },
{ 1024, 768, T64K, 16, 16 },
{ 1024, 768, T16M, 24, 24 },
{ 1280, 1024, T32K, 16, 15 },
{ 1280, 1024, T64K, 16, 16 },
{ 1280, 1024, T16M, 24, 24 } };
_go32_dpmi_seginfo old_kbd_handler, new_kbd_handler, mouse_handler;
_go32_dpmi_registers mouse_callback_regs;
int CorrectLines = 0;
void my_kbd_handler(void);
void my_mouse_handler(_go32_dpmi_registers *mouse_regs);
void HandleDisk(int num);
/* dummie Amiga Keys */
#define AK_EjectDisk 0xfe
#define AK_ChangeDisk 0xff
/* Command Flags */
#define ResetCPU 0x001
#define EjectDisk0 0x002
#define EjectDisk1 0x004
#define EjectDisk2 0x008
#define EjectDisk3 0x010
#define ChangeDisk0 0x020
#define ChangeDisk1 0x040
#define ChangeDisk2 0x080
#define ChangeDisk3 0x100
/* PC Keys */
#define SCODE_CURSORBLOCKUP 103 /* Cursor key block. */
#define SCODE_CURSORBLOCKLEFT 105
#define SCODE_CURSORBLOCKRIGHT 106
#define SCODE_CURSORBLOCKDOWN 108
#define SCODE_INSERT 110
#define SCODE_HOME 102
#define SCODE_PGUP 104
#define SCODE_DELETE 111
#define SCODE_END 107
#define SCODE_PGDN 109
#define SCODE_KEYPAD0 82
#define SCODE_KEYPAD1 79
#define SCODE_KEYPAD2 80
#define SCODE_KEYPAD3 81
#define SCODE_KEYPAD4 75
#define SCODE_KEYPAD5 76
#define SCODE_KEYPAD6 77
#define SCODE_KEYPAD7 71
#define SCODE_KEYPAD8 72
#define SCODE_KEYPAD9 73
#define SCODE_KEYPADENTER 96
#define SCODE_KEYPADPLUS 78
#define SCODE_KEYPADMINUS 74
#define SCODE_Q 16
#define SCODE_W 17
#define SCODE_E 18
#define SCODE_R 19
#define SCODE_T 20
#define SCODE_Y 21
#define SCODE_U 22
#define SCODE_I 23
#define SCODE_O 24
#define SCODE_P 25
#define SCODE_A 30
#define SCODE_S 31
#define SCODE_D 32
#define SCODE_F 33
#define SCODE_G 34
#define SCODE_H 35
#define SCODE_J 36
#define SCODE_K 37
#define SCODE_L 38
#define SCODE_Z 44
#define SCODE_X 45
#define SCODE_C 46
#define SCODE_V 47
#define SCODE_B 48
#define SCODE_N 49
#define SCODE_M 50
#define SCODE_ESCAPE 1
#define SCODE_ENTER 28
#define SCODE_RIGHTCONTROL 97
#define SCODE_CONTROL 97
#define SCODE_RIGHTALT 100
#define SCODE_LEFTCONTROL 29
#define SCODE_LEFTALT 56
#define SCODE_SPACE 57
#define SCODE_F1 59
#define SCODE_F2 60
#define SCODE_F3 61
#define SCODE_F4 62
#define SCODE_F5 63
#define SCODE_F6 64
#define SCODE_F7 65
#define SCODE_F8 66
#define SCODE_F9 67
#define SCODE_F10 68
#define KEY_EVENTRELEASE 0
#define KEY_EVENTPRESS 1
#define SCODE_0 11
#define SCODE_1 2
#define SCODE_2 3
#define SCODE_3 4
#define SCODE_4 5
#define SCODE_5 6
#define SCODE_6 7
#define SCODE_7 8
#define SCODE_8 9
#define SCODE_9 10
#define SCODE_LEFTSHIFT 42
#define SCODE_RIGHTSHIFT 54
#define SCODE_TAB 15
#define SCODE_F11 87
#define SCODE_F12 88
#define SCODE_NEXT 81
#define SCODE_PRIOR 73
#define SCODE_BS 14
/*
#define SCODE_asciicircum 1
*/
#define SCODE_bracketleft 26
#define SCODE_bracketright 27
#define SCODE_comma 51
#define SCODE_period 52
#define SCODE_slash 53
#define SCODE_semicolon 39
#define SCODE_grave 40
#define SCODE_minus 12
#define SCODE_equal 13
#define SCODE_numbersign 41
#define SCODE_ltgt 43
#define SCODE_scrolllock 70
#define SCODE_LWIN95 125
#define SCODE_RWIN95 126
#define SCODE_MWIN95 127
#define SCODE_Caps_Lock 58
static unsigned char escape_keys[128] = {
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
SCODE_KEYPADENTER, SCODE_RIGHTCONTROL, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, SCODE_HOME,
SCODE_CURSORBLOCKUP, SCODE_PGUP, 0, SCODE_CURSORBLOCKLEFT,
0, SCODE_CURSORBLOCKRIGHT, 0, SCODE_END,
SCODE_CURSORBLOCKDOWN,SCODE_PGDN, SCODE_INSERT, SCODE_DELETE,
0, 0, 0, 0,
0, 0, 0, SCODE_LWIN95,
SCODE_RWIN95, SCODE_MWIN95, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
};
static int vsize;
static int CommandFlags = 0;
static int need_dither;
static UBYTE dither_buf[1000];
xcolnr xcolors[4096];
struct vidbuf_description gfxvidinfo;
void flush_line(int y)
{
DoFlushLine(y);
}
void flush_block(int a, int b)
{
abort();
}
void flush_screen(int a, int b)
{
}
void calc_adjustment(void)
{
switch (screen_res) {
case 0: case 1: case 2: /* LoRes, 320xfoo */
gfxvidinfo.x_adjust = prev_max_diwstop - 320;
break;
case 3: /* 640xbar */
gfxvidinfo.x_adjust = prev_max_diwstop - 640;
break;
default:
gfxvidinfo.x_adjust = 0;
break;
}
}
static int colors_allocated;
unsigned char PaletteData[768];
static int get_color(int r, int g, int b, xcolnr *cnp)
{
_go32_dpmi_registers regs;
if (colors_allocated == 256)
return -1;
*cnp = colors_allocated;
PaletteData[colors_allocated*3+0] = doMask(r, 6, 0);
PaletteData[colors_allocated*3+1] = doMask(g, 6, 0);
PaletteData[colors_allocated*3+2] = doMask(b, 6, 0);
colors_allocated++;
return 1;
}
static void init_colors(void)
{
if (need_dither) {
setup_dither(BasicModeInfo.BitsPerColor, get_color);
} else {
colors_allocated = 0;
if (gfxvidinfo.pixbytes == 1)
alloc_colors256(get_color);
else
alloc_colors64k(VBE_ModeInfoBlock.RedMaskSize,
VBE_ModeInfoBlock.GreenMaskSize,
VBE_ModeInfoBlock.BlueMaskSize,
VBE_ModeInfoBlock.RedFieldPosition,
VBE_ModeInfoBlock.GreenFieldPosition,
VBE_ModeInfoBlock.BlueFieldPosition);
}
}
int buttonstate[3] = { 0, 0, 0 };
int lastmx, lastmy;
int newmousecounters = 0;
static int keystate[256];
static int scancode2amiga(int scancode)
{
switch(scancode) {
case SCODE_A: return AK_A;
case SCODE_B: return AK_B;
case SCODE_C: return AK_C;
case SCODE_D: return AK_D;
case SCODE_E: return AK_E;
case SCODE_F: return AK_F;
case SCODE_G: return AK_G;
case SCODE_H: return AK_H;
case SCODE_I: return AK_I;
case SCODE_J: return AK_J;
case SCODE_K: return AK_K;
case SCODE_L: return AK_L;
case SCODE_M: return AK_M;
case SCODE_N: return AK_N;
case SCODE_O: return AK_O;
case SCODE_P: return AK_P;
case SCODE_Q: return AK_Q;
case SCODE_R: return AK_R;
case SCODE_S: return AK_S;
case SCODE_T: return AK_T;
case SCODE_U: return AK_U;
case SCODE_V: return AK_V;
case SCODE_W: return AK_W;
case SCODE_X: return AK_X;
case SCODE_Y: return AK_Y;
case SCODE_Z: return AK_Z;
case SCODE_0: return AK_0;
case SCODE_1: return AK_1;
case SCODE_2: return AK_2;
case SCODE_3: return AK_3;
case SCODE_4: return AK_4;
case SCODE_5: return AK_5;
case SCODE_6: return AK_6;
case SCODE_7: return AK_7;
case SCODE_8: return AK_8;
case SCODE_9: return AK_9;
case SCODE_KEYPAD0: return AK_NP0;
case SCODE_KEYPAD1: return AK_NP1;
case SCODE_KEYPAD2: return AK_NP2;
case SCODE_KEYPAD3: return AK_NP3;
case SCODE_KEYPAD4: return AK_NP4;
case SCODE_KEYPAD5: return AK_NP5;
case SCODE_KEYPAD6: return AK_NP6;
case SCODE_KEYPAD7: return AK_NP7;
case SCODE_KEYPAD8: return AK_NP8;
case SCODE_KEYPAD9: return AK_NP9;
case SCODE_F1: return AK_F1;
case SCODE_F2: return AK_F2;
case SCODE_F3: return AK_F3;
case SCODE_F4: return AK_F4;
case SCODE_F5: return AK_F5;
case SCODE_F6: return AK_F6;
case SCODE_F7: return AK_F7;
case SCODE_F8: return AK_F8;
case SCODE_F9: return AK_F9;
case SCODE_F10: return AK_F10;
case SCODE_BS: return AK_BS;
case SCODE_LEFTCONTROL: return AK_CTRL;
case SCODE_RIGHTCONTROL: return AK_CTRL;
case SCODE_TAB: return AK_TAB;
case SCODE_LEFTALT: return AK_LALT;
case SCODE_RIGHTALT: return AK_RALT;
case SCODE_ENTER: return AK_RET;
case SCODE_SPACE: return AK_SPC;
case SCODE_LEFTSHIFT: return AK_LSH;
case SCODE_RIGHTSHIFT: return AK_RSH;
case SCODE_ESCAPE: return AK_ESC;
case SCODE_INSERT: break;
/* case SCODE_END:
case SCODE_HOME: break;*/
case SCODE_DELETE: return AK_DEL;
case SCODE_CURSORBLOCKUP: return AK_UP;
case SCODE_CURSORBLOCKDOWN: return AK_DN;
case SCODE_CURSORBLOCKLEFT: return AK_LF;
case SCODE_CURSORBLOCKRIGHT: return AK_RT;
case SCODE_F11: return AK_BACKSLASH;
/*
case SCODE_asciicircum: return AK_00;
*/
case SCODE_bracketleft: return AK_LBRACKET;
case SCODE_bracketright: return AK_RBRACKET;
case SCODE_comma: return AK_COMMA;
case SCODE_period: return AK_PERIOD;
case SCODE_slash: return AK_SLASH;
case SCODE_semicolon: return AK_SEMICOLON;
case SCODE_grave: return AK_QUOTE;
case SCODE_minus: return AK_MINUS;
case SCODE_equal: return AK_EQUAL;
/* This one turns off screen updates. */
case SCODE_scrolllock: return AK_inhibit;
case SCODE_PGUP: case SCODE_RWIN95: return AK_RAMI;
case SCODE_PGDN: case SCODE_LWIN95: return AK_LAMI;
/*#ifdef KBD_LANG_DE*/
case SCODE_numbersign: return AK_NUMBERSIGN;
case SCODE_ltgt: return AK_LTGT;
/*#endif*/
case SCODE_END: return AK_EjectDisk;
case SCODE_HOME: return AK_ChangeDisk;
}
return -1;
}
void my_kbd_handler(void)
{
static int is_escape = 0;
int scancode, newstate, akey;
scancode = inportb(0x60);
if (scancode == 0xe0) {
is_escape = 1;
outportb(0x20, 0x20);
return;
}
newstate = !(scancode & 0x80);
scancode = scancode & 0x7f;
if (is_escape) {
scancode = escape_keys[scancode];
is_escape = 0;
}
outportb(0x20, 0x20);
akey = scancode2amiga(scancode);
if (scancode == SCODE_Caps_Lock) {
if (newstate == KEY_EVENTPRESS) {
akey = AK_CAPSLOCK;
newstate = !keystate[akey];
} else
return;
}
if (scancode == SCODE_F12) {
specialflags |= SPCFLAG_BRK;
quit_program = 1;
}
if (akey == -1)
return;
if (akey <= 0xFF) {
if (keystate[akey] == newstate)
return;
keystate[akey] = newstate;
}
if ((akey != AK_EjectDisk) && (akey != AK_ChangeDisk)) {
if (newstate == KEY_EVENTPRESS) {
if (akey == AK_inhibit)
inhibit_frame ^= 1;
else
record_key (akey << 1);
} else
record_key ((akey << 1) | 1);
}
/* "Affengriff" */
if (keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI])
CommandFlags |= ResetCPU;
if (keystate[AK_EjectDisk]) {
if (keystate[AK_F1])
CommandFlags |= EjectDisk0;
if (keystate[AK_F2])
CommandFlags |= EjectDisk1;
if (keystate[AK_F3])
CommandFlags |= EjectDisk2;
if (keystate[AK_F4])
CommandFlags |= EjectDisk3;
}
if (keystate[AK_ChangeDisk]) {
if (keystate[AK_F1])
CommandFlags |= ChangeDisk0;
if (keystate[AK_F2])
CommandFlags |= ChangeDisk1;
if (keystate[AK_F3])
CommandFlags |= ChangeDisk2;
if (keystate[AK_F4])
CommandFlags |= ChangeDisk3;
}
}
void my_mouse_handler(_go32_dpmi_registers *mouse_regs)
{
lastmx = (short)mouse_regs->x.si;
lastmy = (short)mouse_regs->x.di;
buttonstate[0] = mouse_regs->x.bx & 1;
buttonstate[1] = mouse_regs->x.bx & 4;
buttonstate[2] = mouse_regs->x.bx & 2;
}
int graphics_init(void)
{
int i;
_go32_dpmi_registers regs;
extern int kpb_first, kpb_last;
extern int keybuf[256];
int WantedWidth, WantedHeight;
T_ModeType WantedType;
int FoundMode;
int VideoMemorySize, ExtraVideoMemorySize;
/* small check and setup */
remove("uae.log");
if(ersatzkickfile && disk_empty(0)) {
fprintf (stderr, "No KickStart and no bootdisk, giving up.\n");
return 0;
}
_go32_want_ctrl_break(1);
__djgpp_set_ctrl_c(0);
/* set up keyboard handler */
_go32_dpmi_get_protected_mode_interrupt_vector(9, &old_kbd_handler);
new_kbd_handler.pm_offset = (int)my_kbd_handler;
if (_go32_dpmi_allocate_iret_wrapper(&new_kbd_handler) != 0) {
fprintf (stderr, "Can't allocate keyboard iret_wrapper.\n");
return 0;
}
if (_go32_dpmi_set_protected_mode_interrupt_vector(9, &new_kbd_handler) != 0) {
fprintf (stderr, "Can't set protected mode interrupt vector.\n");
return 0;
}
/* set up mouse handler */
regs.x.ax=0;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x33, ®s);
if (regs.x.ax==0) {
fprintf (stderr, "Mouse driver not present.\n");
return 0;
}
mouse_handler.pm_offset = (int)my_mouse_handler;
if (_go32_dpmi_allocate_real_mode_callback_retf(&mouse_handler, &mouse_callback_regs) != 0) {
fprintf (stderr, "Can't allocate mouse callback_retf.\n");
return 0;
}
regs.x.ax=0xc;
regs.x.cx=0x7f;
regs.x.es=mouse_handler.rm_segment;
regs.x.dx=mouse_handler.rm_offset;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x33, ®s);
/* Save Old VGA Mode */
regs.x.ax = 0x1C;
regs.h.ah = 0x0F;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, ®s);
OldVGAMode = regs.h.al;
/* Allocate Palette Memory */
PaletteMem.size = 48;
if (_go32_dpmi_allocate_dos_memory(&PaletteMem)) {
fprintf (stderr, "Can't allocate real mode memory for palette data.\n");
return 0;
}
if (correct_aspect)
CorrectLines = 1;
if (screen_res < 2)
correct_aspect = 0;
/* set up wanted video mode information */
switch (color_mode) {
case 0: WantedType=T256; need_dither=0; break;
case 1: WantedType=T32K; need_dither=0; break;
case 2: WantedType=T64K; need_dither=0; break;
case 3: WantedType=T256; need_dither=1; break;
case 4: WantedType=T16; need_dither=1; break;
case 5: WantedType=T16M; need_dither=0; break;
default:
fprintf(stderr, "Invalid color mode.\n");
return 0;
}
switch (screen_res) {
case 0: WantedWidth=320; WantedHeight=200; break;
case 1: WantedWidth=320; WantedHeight=240; break;
case 2: WantedWidth=320; WantedHeight=400; break;
case 3: WantedWidth=640; WantedHeight=480; break;
case 4: WantedWidth=800; WantedHeight=600; break;
default:
fprintf(stderr, "Invalid screen mode.\n");
return 0;
}
FoundMode = 0;
/* check for vbe */
HasVbe = VBE_GetVbeInfoBlock();
if (HasVbe) {
unsigned int dosmempos = (VBE_VbeInfoBlock.VideoModePtr >> 16) * 16 +
(VBE_VbeInfoBlock.VideoModePtr & 0xffff);
dosmemget(dosmempos, 256, VBE_ModeList);
VBE_ModeList[127] = -1;
for (i=0; (VBE_ModeList[i] != -1) && (!FoundMode) ; i++) {
if ((VBE_ModeList[i] != (short)0x81ff) && VBE_GetModeInfoBlock(VBE_ModeList[i])) {
if ((VBE_VbeInfoBlock.VbeVersion < 0x0200) && (VBE_ModeList[i] == 0x6a)) {
BasicModeInfo.ModeWidth = 800;
BasicModeInfo.ModeHeight = 600;
BasicModeInfo.ModeType = T16;
BasicModeInfo.BitsPerColor = 4;
BasicModeInfo.BitsPerPixel = 8;
VBE_ModeInfoBlock.BitsPerPixel = 8;
} else if ((VBE_VbeInfoBlock.VbeVersion < 0x0200) && ((VBE_ModeList[i] >= 0x100) && (VBE_ModeList[i] <= 0x11b)))
BasicModeInfo = Old_VBE_Table[VBE_ModeList[i] - 0x100];
else {
if (VBE_VbeInfoBlock.VbeVersion < 0x0102) {
if (VBE_ModeInfoBlock.MemoryModel == PackedPixel) {
if (VBE_ModeInfoBlock.BitsPerPixel == 16) {
VBE_ModeInfoBlock.MemoryModel = DirectColor;
VBE_ModeInfoBlock.RedMaskSize = 5;
VBE_ModeInfoBlock.RedFieldPosition = 10;
VBE_ModeInfoBlock.GreenMaskSize = 5;
VBE_ModeInfoBlock.GreenFieldPosition = 5;
VBE_ModeInfoBlock.BlueMaskSize = 5;
VBE_ModeInfoBlock.BlueFieldPosition = 0;
VBE_ModeInfoBlock.RsvdMaskSize = 1;
VBE_ModeInfoBlock.RsvdFieldPosition = 15;
} else if (VBE_ModeInfoBlock.BitsPerPixel == 24) {
VBE_ModeInfoBlock.MemoryModel = DirectColor;
VBE_ModeInfoBlock.RedMaskSize = 8;
VBE_ModeInfoBlock.RedFieldPosition = 16;
VBE_ModeInfoBlock.GreenMaskSize = 8;
VBE_ModeInfoBlock.GreenFieldPosition = 8;
VBE_ModeInfoBlock.BlueMaskSize = 8;
VBE_ModeInfoBlock.BlueFieldPosition = 0;
VBE_ModeInfoBlock.RsvdMaskSize = 0;
VBE_ModeInfoBlock.RsvdFieldPosition = 0;
} else if (VBE_ModeInfoBlock.BitsPerPixel == 32) {
VBE_ModeInfoBlock.MemoryModel = DirectColor;
VBE_ModeInfoBlock.RedMaskSize = 8;
VBE_ModeInfoBlock.RedFieldPosition = 16;
VBE_ModeInfoBlock.GreenMaskSize = 8;
VBE_ModeInfoBlock.GreenFieldPosition = 8;
VBE_ModeInfoBlock.BlueMaskSize = 8;
VBE_ModeInfoBlock.BlueFieldPosition = 0;
VBE_ModeInfoBlock.RsvdMaskSize = 8;
VBE_ModeInfoBlock.RsvdFieldPosition = 24;
}
}
}
BasicModeInfo.ModeWidth = VBE_ModeInfoBlock.XResolution;
BasicModeInfo.ModeHeight = VBE_ModeInfoBlock.YResolution;
if ((VBE_ModeInfoBlock.MemoryModel == PackedPixel) && (VBE_ModeInfoBlock.BitsPerPixel == 8)) {
BasicModeInfo.ModeType = T256;
BasicModeInfo.BitsPerColor = 8;
VBE_ModeInfoBlock.BitsPerPixel = 8;
} else if (VBE_ModeInfoBlock.MemoryModel == DirectColor) {
int BitsperColor = VBE_ModeInfoBlock.RedMaskSize+VBE_ModeInfoBlock.GreenMaskSize+VBE_ModeInfoBlock.BlueMaskSize;
if (BitsperColor == 15) {
BasicModeInfo.ModeType = T32K;
VBE_ModeInfoBlock.BitsPerPixel = 16;
} else if (BitsperColor == 16) {
BasicModeInfo.ModeType = T64K;
VBE_ModeInfoBlock.BitsPerPixel = 16;
} else if (BitsperColor == 24) {
BasicModeInfo.ModeType = T16M;
if (VBE_ModeInfoBlock.RsvdMaskSize == 8)
VBE_ModeInfoBlock.BitsPerPixel = 32;
else
VBE_ModeInfoBlock.BitsPerPixel = 24;
} else
BasicModeInfo.ModeType = TNone;
BasicModeInfo.BitsPerColor = BitsperColor;
} else if (VBE_ModeInfoBlock.MemoryModel == Planar) {
BasicModeInfo.ModeType = T16;
BasicModeInfo.BitsPerColor = 4;
VBE_ModeInfoBlock.BitsPerPixel = 8;
} else
BasicModeInfo.ModeType = TNone;
}
if ((BasicModeInfo.ModeType == T256) || (BasicModeInfo.ModeType == T16))
VBE_ModeInfoBlock.BitsPerPixel = 8;
BasicModeInfo.BitsPerPixel = VBE_ModeInfoBlock.BitsPerPixel;
if (WantedWidth == BasicModeInfo.ModeWidth &&
WantedHeight == BasicModeInfo.ModeHeight &&
WantedType == BasicModeInfo.ModeType) {
FoundMode = 1;
}
}
if (FoundMode && (VBE_ModeInfoBlock.ModeAttributes & 1)) {
HasLinear = 0;
if ((VBE_ModeInfoBlock.ModeAttributes & (1<<7)) && !use_xhair && (VBE_ModeInfoBlock.MemoryModel != Planar)) {
if (screen_res<4)
ExtraVideoMemorySize = VBE_ModeInfoBlock.BytesPerScanLine * 8;
else
ExtraVideoMemorySize = 0;
VideoMemorySize = ALIGN(VBE_ModeInfoBlock.BytesPerScanLine * VBE_ModeInfoBlock.YResolution);
LinearBufferPtr = malloc(VideoMemorySize + ExtraVideoMemorySize);
if (LinearBufferPtr != NULL) {
AlignedLinearBufferPtr = (char *) ALIGN(LinearBufferPtr + ExtraVideoMemorySize);
if (!__djgpp_map_physical_memory(AlignedLinearBufferPtr, VideoMemorySize, VBE_ModeInfoBlock.PhysBasePtr))
HasLinear = 1;
else
free(LinearBufferPtr);
}
if (HasLinear) {
regs.x.ax = 0x4F02;
regs.x.bx = VBE_ModeList[i] | (1<<14);
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, ®s);
ControlInfo.ControlType = TVBE;
ControlInfo.mode = VBE_ModeList[i] | (1<<14);
DoFlushLine = DoFlushLineLinear;
}
}
if (!HasLinear) {
if (!(VBE_ModeInfoBlock.ModeAttributes & (1<<6))) {
regs.x.ax = 0x4F02;
regs.x.bx = VBE_ModeList[i];
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, ®s);
ControlInfo.ControlType = TVBE;
ControlInfo.mode = VBE_ModeList[i];
if ((VBE_VbeInfoBlock.VbeVersion >= 0x0200) && VBE_GetProtectedModeInterface()) {
/* Test memory need for linear memory selector*/
VBE_ChangeBank = VBE_ChangeBankProtectMode;
} else if (VBE_ModeInfoBlock.WinFuncPtr != 0) {
WinFuncPtrSegment = VBE_ModeInfoBlock.WinFuncPtr >> 16;
WinFuncPtrOffset = VBE_ModeInfoBlock.WinFuncPtr & 0xffff;
VBE_ChangeBank = VBE_ChangeBankRealMode;
} else
VBE_ChangeBank = VBE_ChangeBankRealInterrupt;
WinLength = VBE_ModeInfoBlock.WinSize * 1024;
if (VBE_ModeInfoBlock.WinAAttributes & 4) {
WinStart = VBE_ModeInfoBlock.WinASegment * 16;
WriteWindow = 0;
} else {
WinStart = VBE_ModeInfoBlock.WinBSegment * 16;
WriteWindow = 1;
}
for (i=1; i<32; i++) {
if (((unsigned int) 1<<i) == WinLength) {
FastWinCalc = 1;
WinMask1 = i;
WinMask2 = WinLength-1;
break;
}
}
DoFlushLine = DoFlushLineBuffered;
if (VBE_ModeInfoBlock.MemoryModel != Planar)
PutLine = PutLineBanked;
else
PutLine = PutLineVGA16;
} else
FoundMode = 0;
}
LineLength = (VBE_ModeInfoBlock.BitsPerPixel >> 3) * BasicModeInfo.ModeWidth;
LogicalLineLength = VBE_ModeInfoBlock.BytesPerScanLine;
}
}
}
if (!FoundMode) {
if (screen_res==0) {
if (WantedType == T256) {
BasicModeInfo.ModeWidth=320;
BasicModeInfo.ModeHeight=200;
BasicModeInfo.ModeType=T256;
BasicModeInfo.BitsPerPixel=8;
BasicModeInfo.BitsPerColor=8;
ExtraVideoMemorySize = 2560;
VideoMemorySize = ALIGN(64000);
LinearBufferPtr = malloc(VideoMemorySize + ExtraVideoMemorySize);
if (LinearBufferPtr != NULL) {
AlignedLinearBufferPtr = (char *) ALIGN(LinearBufferPtr + ExtraVideoMemorySize);
if (!__djgpp_map_physical_memory(AlignedLinearBufferPtr, VideoMemorySize, 0xa0000))
HasLinear = 1;
else
free(LinearBufferPtr);
}
if (HasLinear)
DoFlushLine = DoFlushLineLinear;
else {
WinLength = 65536;
WinStart = 0xa0000;
FastWinCalc = 1;
WinMask1 = 16;
WinMask2 = WinLength-1;
DoFlushLine = DoFlushLineBuffered;
PutLine = PutLineBanked;
}
regs.h.ah = 0x00;
regs.h.al = 0x13;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, ®s);
ControlInfo.ControlType = TVGA;
ControlInfo.mode = 0x13;
LineLength = 320;
LogicalLineLength = 320;
FoundMode = 1;
} else if (WantedType == T16) {
BasicModeInfo.ModeWidth=320;
BasicModeInfo.ModeHeight=200;
BasicModeInfo.ModeType=T16;
BasicModeInfo.BitsPerPixel=8;
BasicModeInfo.BitsPerColor=4;
WinLength = 65536;
WinStart = 0xa0000;
DoFlushLine = DoFlushLineBuffered;
PutLine = PutLineVGA16;
regs.h.ah = 0x00;
regs.h.al = 0xd;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, ®s);
ControlInfo.ControlType = TVGA;
ControlInfo.mode = 0xd;
LineLength = 40;
LogicalLineLength = 40;
FoundMode = 1;
}
} else if ((screen_res==1) && (WantedType=T256)) {
BasicModeInfo.ModeWidth=320;
BasicModeInfo.ModeHeight=240;
BasicModeInfo.ModeType=T256X;
BasicModeInfo.BitsPerPixel=8;
BasicModeInfo.BitsPerColor=8;
WinLength = 65536;
WinStart = 0xa0000;
DoFlushLine = DoFlushLineBuffered;
PutLine = PutLineVGAX;
ControlInfo.ControlType = TModeX;
ControlInfo.mode = 1;
LineLength = 80;
LogicalLineLength = 80;
SetModeX(1);
FoundMode = 1;
} else if ((screen_res==2) && (WantedType=T256)) {
BasicModeInfo.ModeWidth=320;
BasicModeInfo.ModeHeight=400;
BasicModeInfo.ModeType=T256X;
BasicModeInfo.BitsPerPixel=8;
BasicModeInfo.BitsPerColor=8;
WinLength = 65536;
WinStart = 0xa0000;
DoFlushLine = DoFlushLineBuffered;
PutLine = PutLineVGAX;
ControlInfo.ControlType = TModeX;
ControlInfo.mode = 2;
LineLength = 80;
LogicalLineLength = 80;
SetModeX(2);
FoundMode = 1;
} if ((screen_res==3) && (WantedType == T16)) {
BasicModeInfo.ModeWidth=640;
BasicModeInfo.ModeHeight=480;
BasicModeInfo.ModeType=T16;
BasicModeInfo.BitsPerPixel=8;
BasicModeInfo.BitsPerColor=4;
WinLength = 65536;
WinStart = 0xa0000;
DoFlushLine = DoFlushLineBuffered;
PutLine = PutLineVGA16;
regs.h.ah = 0x00;
regs.h.al = 0x12;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, ®s);
ControlInfo.ControlType = TVGA;
ControlInfo.mode = 0x12;
LineLength = 80;
LogicalLineLength = 80;
FoundMode = 1;
}
}
if (!FoundMode) {
RestoreOldVGAMode = 0;
fprintf(stderr, "Sorry, this combination of color and video mode is not available.\n");
return 0;
}
logfile = freopen("UAE.LOG", "w", stderr);
if (HasVbe) {
fprintf (stderr, "VESA BIOS Extension version %d.%d found.\n", VBE_VbeInfoBlock.VbeVersion >> 8, VBE_VbeInfoBlock.VbeVersion & 0xFF);
if (HasLinear)
fprintf (stderr, "Using Linear FrameBuffer.\n");
if (VBE_ChangeBank == VBE_ChangeBankProtectMode)
fprintf (stderr, "Using Protected Mode Bank Switch Function.\n");
if (VBE_ChangeBank == VBE_ChangeBankRealMode)
fprintf (stderr, "Using Real Mode Bank Switch Function.\n");
if (VBE_ChangeBank == VBE_ChangeBankRealInterrupt)
fprintf (stderr, "Using Real Mode Bank Switch Interrupt Function.\n");
} else {
fprintf (stderr, "Using normal VGA hardware.\n");
if (HasLinear)
fprintf (stderr, "Using Linear FrameBuffer. (vga memory fits on a single segment)\n");
if (screen_res>0)
fprintf (stderr, "Using VGA Mode X.\n");
}
if (!need_dither)
gfxvidinfo.pixbytes = (BasicModeInfo.BitsPerPixel >> 3);
else
gfxvidinfo.pixbytes = 2;
vsize = correct_aspect ? 2*numscrlines : numscrlines;
gfxvidinfo.maxblocklines = 0;
if (HasLinear)
HasLinear = !need_dither;
if (HasLinear) {
gfxvidinfo.rowbytes = LogicalLineLength;
if (correct_aspect) {
if (screen_res == 4) {
gfxvidinfo.bufmem = AlignedLinearBufferPtr + (15 * LogicalLineLength);
gfxvidinfo.maxline = 585;
} else {
gfxvidinfo.bufmem = AlignedLinearBufferPtr - (8 * LogicalLineLength);
gfxvidinfo.maxline = BasicModeInfo.ModeHeight + 8;
}
} else {
if (screen_res == 4) {
gfxvidinfo.bufmem = AlignedLinearBufferPtr + (157 * LogicalLineLength);
gfxvidinfo.maxline = 443;
} else if (screen_res == 3) {
gfxvidinfo.bufmem = AlignedLinearBufferPtr + (97 * LogicalLineLength);
gfxvidinfo.maxline = 383;
} else if (screen_res == 2) {
gfxvidinfo.bufmem = AlignedLinearBufferPtr + (57 * LogicalLineLength);
gfxvidinfo.maxline = 343;
} else {
gfxvidinfo.bufmem = AlignedLinearBufferPtr - (8 * LogicalLineLength);
gfxvidinfo.maxline = BasicModeInfo.ModeHeight + 8;
}
}
} else {
gfxvidinfo.rowbytes = BasicModeInfo.ModeWidth * gfxvidinfo.pixbytes;
gfxvidinfo.bufmem = malloc(gfxvidinfo.rowbytes * vsize);
memset(gfxvidinfo.bufmem, 0, gfxvidinfo.rowbytes * vsize);
gfxvidinfo.maxline = vsize;
}
gfxvidinfo.maxlinetoscr = BasicModeInfo.ModeWidth < 800 ? BasicModeInfo.ModeWidth : 0;
gfxvidinfo.x_adjust = 0;
init_colors();
dosmemput(PaletteData, 768, PaletteMem.rm_segment*16);
LoadPalette();
buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
for(i = 0; i < 256; i++)
keystate[i] = 0;
lastmx = lastmy = 0;
newmousecounters = 0;
/* Lock Data Touched by Interrup Handlers */
_go32_dpmi_lock_code(scancode2amiga, (unsigned int)graphics_init-(unsigned int)scancode2amiga);
_go32_dpmi_lock_data(escape_keys, sizeof(escape_keys));
_go32_dpmi_lock_data(®s, sizeof(regs));
_go32_dpmi_lock_data(keystate, sizeof(keystate));
_go32_dpmi_lock_data(&CommandFlags, sizeof(CommandFlags));
_go32_dpmi_lock_data(&lastmx, sizeof(lastmx));
_go32_dpmi_lock_data(&lastmy, sizeof(lastmy));
_go32_dpmi_lock_data(buttonstate, sizeof(buttonstate));
_go32_dpmi_lock_data(&old_kbd_handler, sizeof(old_kbd_handler));
_go32_dpmi_lock_data(&new_kbd_handler, sizeof(new_kbd_handler));
_go32_dpmi_lock_data(&mouse_handler, sizeof(mouse_handler));
_go32_dpmi_lock_data(&mouse_callback_regs, sizeof(mouse_callback_regs));
_go32_dpmi_lock_code(record_key, (unsigned int)keybuf_init-(unsigned int)record_key);
_go32_dpmi_lock_data(&kpb_first, sizeof(kpb_first));
_go32_dpmi_lock_data(&kpb_last, sizeof(kpb_last));
_go32_dpmi_lock_data(keybuf, sizeof(keybuf));
return 1;
}
void graphics_leave(void)
{
_go32_dpmi_registers regs;
if (RestoreOldVGAMode) {
FILE *fp;
int inChar;
regs.x.ax = 0x1C;
regs.h.ah = 0x00;
regs.h.al = OldVGAMode;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, ®s);
fclose(logfile);
freopen("CON", "w", stderr);
fp = fopen("uae.log","r");
for (;;) {
inChar = getc(fp);
if (inChar == EOF)
break;
putchar(inChar);
}
fclose(fp);
}
_go32_dpmi_set_protected_mode_interrupt_vector(9, &old_kbd_handler);
_go32_dpmi_free_iret_wrapper(&new_kbd_handler);
regs.x.ax=0xc;
regs.x.cx=0x0;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x33, ®s);
_go32_dpmi_free_real_mode_callback(&mouse_handler);
_go32_dpmi_free_dos_memory(&PaletteMem);
}
void handle_events(void)
{
if (CommandFlags) {
if (CommandFlags & ResetCPU) {
m68k_reset();
CommandFlags &= ~ResetCPU;
}
if (CommandFlags & EjectDisk0) {
disk_eject(0);
CommandFlags &= ~EjectDisk0;
}
if (CommandFlags & EjectDisk1) {
disk_eject(1);
CommandFlags &= ~EjectDisk1;
}
if (CommandFlags & EjectDisk2) {
disk_eject(2);
CommandFlags &= ~EjectDisk2;
}
if (CommandFlags & EjectDisk3) {
disk_eject(3);
CommandFlags &= ~EjectDisk3;
}
if (CommandFlags & ChangeDisk0) {
HandleDisk(0);
keystate[AK_ChangeDisk] = 0;
keystate[AK_F1] = 0;
record_key ((AK_F1 << 1) | 1);
CommandFlags &= ~ChangeDisk0;
}
if (CommandFlags & ChangeDisk1) {
HandleDisk(1);
keystate[AK_ChangeDisk] = 0;
keystate[AK_F2] = 0;
record_key ((AK_F2 << 1) | 1);
CommandFlags &= ~ChangeDisk1;
}
if (CommandFlags & ChangeDisk2) {
HandleDisk(2);
keystate[AK_ChangeDisk] = 0;
keystate[AK_F3] = 0;
record_key ((AK_F3 << 1) | 1);
CommandFlags &= ~ChangeDisk2;
}
if (CommandFlags & ChangeDisk3) {
HandleDisk(3);
keystate[AK_ChangeDisk] = 0;
keystate[AK_F4] = 0;
record_key ((AK_F4 << 1) | 1);
CommandFlags &= ~ChangeDisk3;
}
}
}
int debuggable(void)
{
return 0;
}
int needmousehack(void)
{
return 0;
}
void LED(int on)
{
}
void target_specific_usage(void)
{
printf(" -S : Turn off sound support (if it is configured)\n");
printf(" -l lang : Set keyboard language to lang, where lang is\n"
" DE or US\n");
printf(" -x : Don't use linear framebuffer, even if available.\n");
printf(" -p filename : Use filename to save printer output (i.e. PRN)\n");
printf(" -I device : Name of the used serial device (i.e. AUX)\n");
printf(" -8 : Use 8 Bit Sound (default is 16 Bit Sound)\n");
printf(" -4 : Use 44100Hz Samplerate (default is 22050Hz)\n");
}
void HandleDisk(int num)
{
int i, memsize = 0;
char buf[256], *save_mem = NULL;
_go32_dpmi_registers regs;
_go32_dpmi_set_protected_mode_interrupt_vector(9, &old_kbd_handler);
if (HasLinear) {
memsize = LogicalLineLength * BasicModeInfo.ModeHeight;
save_mem = malloc(memsize);
if (save_mem != NULL)
memcpy(save_mem, AlignedLinearBufferPtr, memsize);
}
/* Set text mode */
regs.x.ax = 0x1C;
regs.h.ah = 0x00;
regs.h.al = 0x03;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, ®s);
strcpy(buf,dosfilereq("*.adf"));
disk_insert(num, buf);
_go32_dpmi_set_protected_mode_interrupt_vector(9, &new_kbd_handler);
/* Set graphics mode */
SetGraphicsMode();
/* Restore screen */
if ((gfxvidinfo.pixbytes == 1) || need_dither)
LoadPalette();
if (HasLinear) {
if (save_mem != NULL) {
memcpy(AlignedLinearBufferPtr, save_mem, memsize);
free(save_mem);
}
} else {
for(i=0; i<vsize; i++)
flush_line(i);
}
}
void SetGraphicsMode(void) {
_go32_dpmi_registers regs;
switch(ControlInfo.ControlType) {
case TVBE:
VBE_GetModeInfoBlock(ControlInfo.mode);
regs.x.ax = 0x4F02;
regs.x.bx = ControlInfo.mode;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, ®s);
break;
case TVGA:
regs.h.ah = 0x00;
regs.h.al = ControlInfo.mode;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, ®s);
break;
case TModeX:
SetModeX(ControlInfo.mode);
break;
}
}
void SetModeX(int num) {
_go32_dpmi_registers regs;
int i;
char cleared[320];
regs.h.ah = 0x00;
regs.h.al = 0x13;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, ®s);
for (i=0; i<320; i++)
cleared[i] = 0;
outportw(0x3c4, 0x604);
if (num==1) {
outportw(0x3c4, 0x0100);
outportb(0x3c2, 0x00e3);
outportw(0x3c4, 0x0300);
outportw(0x3d4, 0x2c11);
outportw(0x3d4, 0x5f00);
outportw(0x3d4, 0x4f01);
outportw(0x3d4, 0x5002);
outportw(0x3d4, 0x8203);
outportw(0x3d4, 0x5404);
outportw(0x3d4, 0x8005);
outportw(0x3d4, 0x0d06);
outportw(0x3d4, 0x3e07);
outportw(0x3d4, 0x0008);
outportw(0x3d4, 0x4109);
outportw(0x3d4, 0x000a);
outportw(0x3d4, 0x000b);
outportw(0x3d4, 0x000c);
outportw(0x3d4, 0x000d);
outportw(0x3d4, 0x000e);
outportw(0x3d4, 0x000f);
outportw(0x3d4, 0xea10);
outportw(0x3d4, 0xac11);
outportw(0x3d4, 0xdf12);
outportw(0x3d4, 0x2813);
outportw(0x3d4, 0x0014);
outportw(0x3d4, 0xe715);
outportw(0x3d4, 0x0616);
outportw(0x3d4, 0xe317);
for (i=0; i<240; i++)
PutLineVGAX(cleared, i);
} else {
outportw(0x3d4, 0x0e11);
outportw(0x3d4, 0x5f00);
outportw(0x3d4, 0x4f01);
outportw(0x3d4, 0x5002);
outportw(0x3d4, 0x8203);
outportw(0x3d4, 0x5404);
outportw(0x3d4, 0x8005);
outportw(0x3d4, 0xbf06);
outportw(0x3d4, 0x1f07);
outportw(0x3d4, 0x0008);
outportw(0x3d4, 0x4009);
outportw(0x3d4, 0x000a);
outportw(0x3d4, 0x000b);
outportw(0x3d4, 0x000c);
outportw(0x3d4, 0x000d);
outportw(0x3d4, 0x000e);
outportw(0x3d4, 0x000f);
outportw(0x3d4, 0x9c10);
outportw(0x3d4, 0x8e11);
outportw(0x3d4, 0x8f12);
outportw(0x3d4, 0x2813);
outportw(0x3d4, 0x0014);
outportw(0x3d4, 0x9615);
outportw(0x3d4, 0xb916);
outportw(0x3d4, 0xe317);
for (i=0; i<400; i++)
PutLineVGAX(cleared, i);
}
}
void LoadPalette(void) {
_go32_dpmi_registers regs;
regs.h.ah = 0x10;
regs.h.al = 0x12;
regs.x.bx = 0;
if (BasicModeInfo.ModeType == T16)
regs.x.cx = 16;
else
regs.x.cx = 256;
regs.x.es = PaletteMem.rm_segment;
regs.x.dx = 0x0000;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, ®s);
}
int VBE_GetVbeInfoBlock(void) {
_go32_dpmi_registers regs;
strncpy(VBE_VbeInfoBlock.VbeSignature, "VBE2", 4);
dosmemput(&VBE_VbeInfoBlock, sizeof(VBE_VbeInfoBlock), __tb);
regs.x.ax = 0x4F00;
regs.x.di = __tb & 0x0F;
regs.x.es = (__tb >> 4) & 0xFFFF;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, ®s);
dosmemget(__tb, sizeof(VBE_VbeInfoBlock), &VBE_VbeInfoBlock);
return((regs.x.ax == 0x004F) && (VBE_VbeInfoBlock.VbeVersion >= 0x0100));
}
int VBE_GetModeInfoBlock(short mode) {
_go32_dpmi_registers regs;
VBE_ModeInfoBlock.ReservedA = 1;
regs.x.ax = 0x4F01;
regs.x.cx = mode;
regs.x.di = __tb & 0x0F;
regs.x.es = (__tb >> 4) & 0xFFFF;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, ®s);
dosmemget(__tb, sizeof(VBE_ModeInfoBlock), &VBE_ModeInfoBlock);
return(regs.x.ax == 0x004F);
}
int VBE_GetProtectedModeInterface(void) {
_go32_dpmi_registers regs;
regs.x.ax = 0x4F0A;
regs.x.bx = 0x0000;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, ®s);
VBE_ProtectedModeInterface = (T_VBE_ProtectedModeInterface *) malloc(regs.x.cx);
if (VBE_ProtectedModeInterface == NULL)
return(0);
dosmemget(regs.x.es * 16 + regs.x.di, regs.x.cx, VBE_ProtectedModeInterface);
SetWindow = (unsigned int) VBE_ProtectedModeInterface + VBE_ProtectedModeInterface->SetWindowOffset;
PortsMemory = (short *) VBE_ProtectedModeInterface + VBE_ProtectedModeInterface->PortsMemoryOffset;
return(regs.x.ax == 0x004F);
}
void VBE_ChangeBankRealInterrupt(short BankNumber) {
_go32_dpmi_registers regs;
regs.x.ax = 0x4F05;
regs.x.bx = WriteWindow;
regs.x.dx = BankNumber;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, ®s);
CurrentBankNumber = BankNumber;
}
void VBE_ChangeBankRealMode(short BankNumber) {
_go32_dpmi_registers regs;
regs.x.ax = 0x4F05;
regs.x.bx = WriteWindow;
regs.x.dx = BankNumber;
regs.x.cs = WinFuncPtrSegment;
regs.x.ip = WinFuncPtrOffset;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_fcall(®s);
CurrentBankNumber = BankNumber;
}
void VBE_ChangeBankProtectMode(short BankNumber) {
asm ("
push %%es
movw %0, %%es
mov 0x4F05, %%ax
mov %1, %%bx
mov %2, %%dx
call %3
pop %%es
"
:
: "g" (_dos_ds), "g" (WriteWindow), "g" (BankNumber), "r" (SetWindow)
: "%ax", "%bx", "%dx"
);
CurrentBankNumber = BankNumber;
}
void DoFlushLineLinear(int y) {
int target_y;
char *addr;
if (need_dither) {
target_y = y;
switch (screen_res) {
case 0:
if (CorrectLines) {
if (target_y%3==0)
return;
target_y=(target_y<<1)/3+5;
} else
target_y -= 8;
break;
case 1:
if (CorrectLines) {
if (target_y%5==0)
return;
target_y=(target_y<<2)/5+6;
} else
target_y -= 8;
break;
case 2:
if (CorrectLines) {
if (target_y%3==0)
return;
target_y=(target_y<<1)/3+10;
} else
target_y += 57;
break;
case 3:
if (CorrectLines) {
if (target_y%5==0)
return;
target_y=(target_y<<2)/5+12;
} else
target_y += 97;
break;
case 4:
if (CorrectLines)
target_y += 15;
else
target_y += 157;
break;
}
if (target_y < BasicModeInfo.ModeHeight && target_y >= 0) {
addr = gfxvidinfo.bufmem + y*gfxvidinfo.rowbytes;
DitherLine(AlignedLinearBufferPtr + LogicalLineLength * target_y, (UWORD *)addr, 0, y, BasicModeInfo.ModeWidth, BasicModeInfo.BitsPerPixel);
}
}
}
void DoFlushLineBuffered(int y) {
int target_y = y;
char *addr;
switch (screen_res) {
case 0:
if (CorrectLines) {
if (target_y%3==0)
return;
target_y=(target_y<<1)/3+5;
} else
target_y -= 8;
break;
case 1:
if (CorrectLines) {
if (target_y%5==0)
return;
target_y=(target_y<<2)/5+6;
} else
target_y -= 8;
break;
case 2:
if (CorrectLines) {
if (target_y%3==0)
return;
target_y=(target_y<<1)/3+10;
} else
target_y += 57;
break;
case 3:
if (CorrectLines) {
if (target_y%5==0)
return;
target_y=(target_y<<2)/5+12;
} else
target_y += 97;
break;
case 4:
if (CorrectLines)
target_y += 15;
else
target_y += 157;
break;
}
if (target_y < BasicModeInfo.ModeHeight && target_y >= 0) {
addr = gfxvidinfo.bufmem + y*gfxvidinfo.rowbytes;
if (need_dither) {
DitherLine(dither_buf, (UWORD *)addr, 0, y, BasicModeInfo.ModeWidth, BasicModeInfo.BitsPerPixel);
addr = dither_buf;
}
PutLine(addr, target_y);
}
}
void PutLineBanked(char *addr, int target_y) {
unsigned int offs;
int page, pos, left;
char *ptr;
offs = target_y * LogicalLineLength;
if (FastWinCalc) {
page = offs >> WinMask1;
pos = offs & WinMask2;
} else {
page = offs / WinLength;
pos = offs % WinLength;
}
left = WinLength - pos;
ptr = (char *) WinStart + pos;
if (page != CurrentBankNumber)
VBE_ChangeBank(page);
if (left >= LineLength)
asm __volatile__ ("
push %%es
cld
movw %0, %%es
shrl $2, %%ecx
rep
movsl
pop %%es
"
:
: "g" (_dos_ds), "S" (addr), "D" (ptr), "c" (LineLength)
: "%esi", "%edi", "%ecx", "cc", "memory"
);
else {
asm __volatile__ ("
push %%es
cld
movw %0, %%es
shrl $2, %%ecx
rep
movsl
pop %%es
"
:
: "g" (_dos_ds), "S" (addr), "D" (ptr), "c" (left)
: "%esi", "%edi", "%ecx", "cc", "memory"
);
VBE_ChangeBank(page+1);
asm __volatile__ ("
push %%es
cld
movw %0, %%es
addl %1, %%esi
subl %1, %%ecx
shrl $2, %%ecx
rep
movsl
pop %%es
"
:
: "g" (_dos_ds), "g" (left), "S" (addr), "D" (WinStart), "c" (LineLength)
: "%esi", "%edi", "%ecx", "cc", "memory"
);
}
}
void PutLineVGA16(char *addr, int target_y) {
unsigned int start, ptr;
int i;
UBYTE c;
_farsetsel(_dos_ds);
#if 0
ptr = WinStart + target_y * LogicalLineLength;
outportw(0x3ce, 0x205);
outportw(0x3ce, 3);
for (i=0; i<BasicModeInfo.ModeWidth; i++) {
outportw(0x3ce, 1<<(((i&7)^7)+8)|8);
_farnspeekb(ptr+(i>>3));
_farnspokeb(ptr+(i>>3), addr[i]);
}
#else
start = WinStart + target_y * LogicalLineLength;
ptr = start;
outportw(0x3c4, 0x802);
for (i=0; i<BasicModeInfo.ModeWidth; i+=8, ptr++) {
c = ((addr[i ]<<4)&128)|((addr[i+1]<<3)&64)|((addr[i+2]<<2)&32)|((addr[i+3]<<1)&16)|
((addr[i+4] )&8 )|((addr[i+5]>>1)&4 )|((addr[i+6]>>2)&2 )|((addr[i+7]>>3)&1);
_farnspokeb(ptr, c);
}
ptr = start;
outportw(0x3c4, 0x402);
for (i=0; i<BasicModeInfo.ModeWidth; i+=8, ptr++) {
c = ((addr[i ]<<5)&128)|((addr[i+1]<<4)&64)|((addr[i+2]<<3)&32)|((addr[i+3]<<2)&16)|
((addr[i+4]<<1)&8 )|((addr[i+5] )&4 )|((addr[i+6]>>1)&2 )|((addr[i+7]>>2)&1 );
_farnspokeb(ptr, c);
}
ptr = start;
outportw(0x3c4, 0x202);
for (i=0; i<BasicModeInfo.ModeWidth; i+=8, ptr++) {
c = ((addr[i ]<<6)&128)|((addr[i+1]<<5)&64)|((addr[i+2]<<4)&32)|((addr[i+3]<<3)&16)|
((addr[i+4]<<2)&8 )|((addr[i+5]<<1)&4 )|((addr[i+6] )&2 )|((addr[i+7]>>1)&1 );
_farnspokeb(ptr, c);
}
ptr = start;
outportw(0x3c4, 0x102);
for (i=0; i<BasicModeInfo.ModeWidth; i+=8, ptr++) {
c = ((addr[i ]<<7)&128)|((addr[i+1]<<6)&64)|((addr[i+2]<<5)&32)|((addr[i+3]<<4)&16)|
((addr[i+4]<<3)&8 )|((addr[i+5]<<2)&4 )|((addr[i+6]<<1)&2 )|((addr[i+7] )&1 );
_farnspokeb(ptr, c);
}
#endif
}
void PutLineVGAX(char *addr, int target_y) {
unsigned int start, ptr;
int i;
UBYTE c;
_farsetsel(_dos_ds);
start = WinStart + target_y * LogicalLineLength;
ptr = start;
outportw(0x3c4, 0x102);
for (i=0; i<BasicModeInfo.ModeWidth; i+=4, ptr++)
_farnspokeb(ptr, addr[i]);
ptr = start;
outportw(0x3c4, 0x202);
for (i=1; i<BasicModeInfo.ModeWidth; i+=4, ptr++)
_farnspokeb(ptr, addr[i]);
ptr = start;
outportw(0x3c4, 0x402);
for (i=2; i<BasicModeInfo.ModeWidth; i+=4, ptr++)
_farnspokeb(ptr, addr[i]);
ptr = start;
outportw(0x3c4, 0x802);
for (i=3; i<BasicModeInfo.ModeWidth; i+=4, ptr++)
_farnspokeb(ptr, addr[i]);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.