|
|
uae-0.6.8
/*
* UAE - The Un*x Amiga Emulator
*
* DOS VESA BIOS / VGA / Mode X graphics interface.
*
* (c) 1996 Gustavo Goedert
*
* Originaly based on svga.c -- (c) 1995 Bernd Schmidt
* Led routines by Michael Sontheimer
*
*/
#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 <conio.h>
#include <fcntl.h>
#include <crt0.h>
#include <signal.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 "gui.h"
#include "tui.h"
#include "uae.h"
#define PACKED __attribute__ ((packed))
#define ALIGN(x) ((((int)(x)>>12)<<12)+4096)
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 = 0, 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;
int Original_produce_sound;
void my_kbd_handler(void);
void my_mouse_handler(_go32_dpmi_registers *mouse_regs);
int SetupVBEMode(int mode);
void disalocate_memory(int level);
void HandleDisk(int num);
void SaveScreen(void);
void RestoreLEDStatus(void);
/* 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
#define ChangeOptions 0x200
#define SaveImage 0x400
/* 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 setup_brkhandler(void)
{
}
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;
static int get_color(int r, int g, int b, xcolnr *cnp)
{
_go32_dpmi_registers int_regs;
if ((BasicModeInfo.ModeType == T16) && (colors_allocated == 16))
return -1;
else 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 !fake_joystick ? AK_CTRL : AK_NP5;
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: return AK_HELP;
/* 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;
}
/* PAUSE Key */
if (is_escape > 1) {
is_escape++;
if (is_escape == 7) {
/* turn on/off sound */
if (produce_sound == 0)
produce_sound = Original_produce_sound;
else
produce_sound = 0;
is_escape = 0;
}
outportb(0x20, 0x20);
return;
}
if (scancode == 0xe1) {
is_escape = 2;
outportb(0x20, 0x20);
return;
}
/* PrintScreen Key */
if (is_escape && (scancode == 0x37)) {
CommandFlags |= SaveImage;
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) {
regs.spcflags |= 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 int_regs;
unsigned int dosmempos;
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 */
freopen("uae.log", "w", stderr);
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);
signal(SIGFPE, SIG_IGN);
/* save produce_sound state */
Original_produce_sound = produce_sound;
/* enable case on LFN systems (eg. win95) */
if (_USE_LFN)
_crt0_startup_flags = _CRT0_FLAG_PRESERVE_FILENAME_CASE;
/* 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 */
int_regs.x.ax=0;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x33, &int_regs);
if (int_regs.x.ax==0) {
fprintf (stderr, "Mouse driver not present.\n");
disalocate_memory(1);
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");
disalocate_memory(1);
return 0;
}
int_regs.x.ax=0xc;
int_regs.x.cx=0x7f;
int_regs.x.es=mouse_handler.rm_segment;
int_regs.x.dx=mouse_handler.rm_offset;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x33, &int_regs);
/* Save Old VGA Mode */
int_regs.x.ax = 0x1C;
int_regs.h.ah = 0x0F;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, &int_regs);
OldVGAMode = int_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");
disalocate_memory(2);
return 0;
}
if (correct_aspect)
CorrectLines = 1;
if (screen_res < 2)
correct_aspect = 0;
/* set up wanted video mode information */
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");
disalocate_memory(3);
return 0;
}
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");
disalocate_memory(3);
return 0;
}
FoundMode = 0;
/* check for vbe */
HasVbe = VBE_GetVbeInfoBlock();
if (HasVbe) {
dosmempos = (VBE_VbeInfoBlock.VideoModePtr >> 16) * 16 +
(VBE_VbeInfoBlock.VideoModePtr & 0xffff);
dosmemget(dosmempos, 256, VBE_ModeList);
VBE_ModeList[127] = -1;
for (i=0; i<28; i++) {
if ((WantedWidth == Old_VBE_Table[i].ModeWidth) &&
(WantedHeight == Old_VBE_Table[i].ModeHeight) &&
(WantedType == Old_VBE_Table[i].ModeType)) {
if (VBE_GetModeInfoBlock(0x100+i)) {
BasicModeInfo = Old_VBE_Table[i];
FoundMode = SetupVBEMode(0x100+i);
}
break;
}
}
for (i=0; (VBE_VbeInfoBlock.VbeVersion >= 0x0200) && (!FoundMode) && (VBE_ModeList[i] != -1) ; i++) {
if ((VBE_ModeList[i] != (short)0x81ff) && VBE_GetModeInfoBlock(VBE_ModeList[i])) {
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))
FoundMode = SetupVBEMode(VBE_ModeList[i]);
}
}
/* if we don't have VBE, see if Normal VGA can do the job... */
if (!FoundMode) {
if (screen_res==0) {
if (WantedType == T256) {
BasicModeInfo.ModeWidth=320;
BasicModeInfo.ModeHeight=200;
BasicModeInfo.ModeType=T256;
BasicModeInfo.BitsPerPixel=8;
BasicModeInfo.BitsPerColor=8;
if (!no_xhair) {
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;
DoFlushLine = DoFlushLineLinear;
} else
free(LinearBufferPtr);
}
}
if (!HasLinear) {
WinLength = 65536;
WinStart = 0xa0000;
FastWinCalc = 1;
WinMask1 = 16;
WinMask2 = WinLength-1;
DoFlushLine = DoFlushLineBuffered;
PutLine = PutLineBanked;
}
int_regs.h.ah = 0x00;
int_regs.h.al = 0x13;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, &int_regs);
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;
int_regs.h.ah = 0x00;
int_regs.h.al = 0xd;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, &int_regs);
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;
} else 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;
int_regs.h.ah = 0x00;
int_regs.h.al = 0x12;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, &int_regs);
ControlInfo.ControlType = TVGA;
ControlInfo.mode = 0x12;
LineLength = 80;
LogicalLineLength = 80;
FoundMode = 1;
}
}
if (!FoundMode) {
fprintf(stderr, "Sorry, this combination of color and video mode is not available.\n");
disalocate_memory(3);
return 0;
}
if (ControlInfo.ControlType == TVBE) {
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");
}
RestoreOldVGAMode = 1;
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;
/* initialize colors/palette */
init_colors();
dosmemput(PaletteData, 768, PaletteMem.rm_segment*16);
LoadPalette();
/* initialize mouse data */
buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
lastmx = lastmy = 0;
newmousecounters = 0;
/* initialize keyboard data */
for(i = 0; i < 256; i++)
keystate[i] = 0;
/* Lock Data Touched by Interrupt 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));
_go32_dpmi_lock_data(&Original_produce_sound, sizeof(Original_produce_sound));
_go32_dpmi_lock_data(&produce_sound, sizeof(produce_sound));
return 1;
}
int SetupVBEMode(int mode) {
int i;
_go32_dpmi_registers int_regs;
int VideoMemorySize, ExtraVideoMemorySize;
HasLinear = 0;
if ((VBE_ModeInfoBlock.ModeAttributes & (1<<7)) && !no_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) {
int_regs.x.ax = 0x4F02;
int_regs.x.bx = mode | (1<<14);
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, &int_regs);
ControlInfo.ControlType = TVBE;
ControlInfo.mode = mode | (1<<14);
DoFlushLine = DoFlushLineLinear;
}
}
if (!HasLinear) {
if (!(VBE_ModeInfoBlock.ModeAttributes & (1<<6))) {
int_regs.x.ax = 0x4F02;
int_regs.x.bx = mode;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, &int_regs);
ControlInfo.ControlType = TVBE;
ControlInfo.mode = mode;
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) || (!(VBE_ModeInfoBlock.WinBAttributes & 4))) {
WriteWindow = 0;
WinStart = VBE_ModeInfoBlock.WinASegment * 16;
} else {
WriteWindow = 1;
WinStart = VBE_ModeInfoBlock.WinBSegment * 16;
}
/* You never know... */
if (WinStart == 0)
WinStart = 0xa0000;
if (WinLength == 0)
WinLength = 65536;
for (i=1; i<32; i++) { // This was a bug!
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
return 0;
}
LineLength = (VBE_ModeInfoBlock.BitsPerPixel >> 3) * BasicModeInfo.ModeWidth;
LogicalLineLength = VBE_ModeInfoBlock.BytesPerScanLine;
return 1;
}
void graphics_leave(void)
{
_go32_dpmi_registers int_regs;
FILE *fp;
char inChar;
if (RestoreOldVGAMode) {
dumpcustom();
int_regs.x.ax = 0x1C;
int_regs.h.ah = 0x00;
int_regs.h.al = OldVGAMode;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, &int_regs);
disalocate_memory(3);
}
freopen("CON", "w", stderr);
fp = fopen("uae.log","r");
if(fp)
{
inChar = getc(fp);
while(inChar != EOF)
{
putchar(inChar);
inChar=getc(fp);
}
fclose(fp);
}
}
void disalocate_memory(int level) {
_go32_dpmi_registers int_regs;
if (level>=1) {
_go32_dpmi_set_protected_mode_interrupt_vector(9, &old_kbd_handler);
_go32_dpmi_free_iret_wrapper(&new_kbd_handler);
}
if (level>=2) {
int_regs.x.ax=0xc;
int_regs.x.cx=0x0;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x33, &int_regs);
_go32_dpmi_free_real_mode_callback(&mouse_handler);
}
if (level>=3)
_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;
}
if (CommandFlags & SaveImage) {
SaveScreen();
CommandFlags &= ~SaveImage;
}
}
}
int debuggable(void)
{
return 0;
}
int needmousehack(void)
{
return 0;
}
// ***MS Now the scroll-lock-led does the same as the amiga power-led
UBYTE ubSavedLED;
void RestoreLEDStatus(void)
{
_go32_dpmi_registers regs;
_farsetsel( _dos_ds );
_farnspokeb( (0x40<<4)+0x17, ubSavedLED );
regs.x.ax = 0x0100;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x16, ®s);
}
void LED(int on)
{
static int OldStat=-1;
_go32_dpmi_registers regs;
if( OldStat != on ) // Avoid more int's than necessary
{
_farsetsel( _dos_ds );
if( OldStat == -1 ) // Am I here the first time ?
{
ubSavedLED = _farnspeekb( (0x40<<4)+0x17 ); // Save LED-status
atexit( RestoreLEDStatus );
}
if( !on )
_farnspokeb( (0x40<<4)+0x17, _farnspeekb( (0x40<<4)+0x17 ) | 16 );
else
_farnspokeb( (0x40<<4)+0x17, _farnspeekb( (0x40<<4)+0x17 ) & ~16 );
regs.x.ax = 0x0100;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x16, ®s);
OldStat = on;
}
}
void target_specific_usage(void)
{
printf(" -S n : Sound emulation accuracy (n = 0, 1, 2 or 3)\n"
" For sound emulation, n = 2 is recommended\n");
printf(" -b n : Use n bits for sound output (8 or 16)\n");
printf(" -R n : Use n Hz to output sound. Common values are\n"
" 22050 Hz or 44100 Hz\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");
}
void HandleDisk(int num)
{
int i, memsize = 0;
char *ptr=NULL, buf[256], *save_mem = NULL;
_go32_dpmi_registers int_regs;
extern char *adfdefaultdir;
_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 */
int_regs.x.ax = 0x1C;
int_regs.h.ah = 0x00;
int_regs.h.al = 0x03;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, &int_regs);
tui_setup();
switch(num) {
case 0:
tui_gotoxy(5, 4);
tui_puts("DF0:");
ptr = tui_filereq("*.adf", df0);
break;
case 1:
tui_gotoxy(5, 4);
tui_puts("DF1:");
ptr = tui_filereq("*.adf", df1);
break;
case 2:
tui_gotoxy(5, 4);
tui_puts("DF2:");
ptr = tui_filereq("*.adf", df2);
break;
case 3:
tui_gotoxy(5, 4);
tui_puts("DF3:");
ptr = tui_filereq("*.adf", df3);
break;
}
tui_shutdown();
if (ptr != NULL) {
strcpy(buf, ptr);
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 SaveScreen(void) {
static int err=0, lastsave=0;
char filename[13];
FILE *imagefile;
char targaheader[18];
int i;
if (err)
return;
while(1) {
sprintf(filename, "uae%05d.tga", lastsave);
imagefile = fopen(filename, "rb");
if (imagefile == NULL) {
imagefile = fopen(filename, "wb");
if (imagefile == NULL) {
err = 1;
return;
}
break;
}
fclose(imagefile);
lastsave++;
if (lastsave == 100000) {
err = 1;
return;
}
}
memset(targaheader, 0, 18);
if (BasicModeInfo.BitsPerPixel == 8) {
targaheader[1] = 1;
targaheader[2] = 1;
*((unsigned short *)&(targaheader[5])) = 256;
targaheader[7] = 24;
} else
targaheader[2] = 2;
*((unsigned short *)&(targaheader[12])) = BasicModeInfo.ModeWidth;
*((unsigned short *)&(targaheader[14])) = gfxvidinfo.maxline;
targaheader[16] = BasicModeInfo.BitsPerPixel;
targaheader[17] = 0x20;
fwrite(targaheader, 18, 1, imagefile);
if (BasicModeInfo.BitsPerPixel == 8) {
for(i=0; i<256; i++) {
fputc(PaletteData[i*3+2]<<2, imagefile);
fputc(PaletteData[i*3+1]<<2, imagefile);
fputc(PaletteData[i*3+0]<<2, imagefile);
}
}
if (need_dither) {
for(i=0; i<gfxvidinfo.maxline; i++) {
DitherLine(dither_buf, (UWORD *)(gfxvidinfo.bufmem + i*gfxvidinfo.rowbytes), 0, i, BasicModeInfo.ModeWidth, BasicModeInfo.BitsPerPixel);
fwrite(dither_buf, BasicModeInfo.ModeWidth, 1, imagefile);
}
} else {
if (BasicModeInfo.BitsPerColor!=16)
fwrite(gfxvidinfo.bufmem, gfxvidinfo.rowbytes * gfxvidinfo.maxline, 1, imagefile);
else {
int r, g, b, c;
for(i=0; i<(gfxvidinfo.rowbytes * gfxvidinfo.maxline); i=i+2) {
r = (*((int *)&(gfxvidinfo.bufmem[i])) >> VBE_ModeInfoBlock.RedFieldPosition) & ((1<<VBE_ModeInfoBlock.RedMaskSize)-1);
g = (*((int *)&(gfxvidinfo.bufmem[i])) >> VBE_ModeInfoBlock.GreenFieldPosition) & ((1<<VBE_ModeInfoBlock.GreenMaskSize)-1);
b = (*((int *)&(gfxvidinfo.bufmem[i])) >> VBE_ModeInfoBlock.BlueFieldPosition) & ((1<<VBE_ModeInfoBlock.BlueMaskSize)-1);
if (VBE_ModeInfoBlock.RedMaskSize == 6)
r = r>>1;
if (VBE_ModeInfoBlock.GreenMaskSize == 6)
g = g>>1;
if (VBE_ModeInfoBlock.BlueMaskSize == 6)
b = b>>1;
c = b | (g<<5) | (r<<10);
fwrite(&c, 2, 1, imagefile);
}
}
}
fclose(imagefile);
}
void SetGraphicsMode(void) {
_go32_dpmi_registers int_regs;
switch(ControlInfo.ControlType) {
case TVBE:
VBE_GetModeInfoBlock(ControlInfo.mode);
int_regs.x.ax = 0x4F02;
int_regs.x.bx = ControlInfo.mode;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, &int_regs);
break;
case TVGA:
int_regs.h.ah = 0x00;
int_regs.h.al = ControlInfo.mode;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, &int_regs);
break;
case TModeX:
SetModeX(ControlInfo.mode);
break;
}
}
void SetModeX(int num) {
_go32_dpmi_registers int_regs;
int i;
char cleared[320];
int_regs.h.ah = 0x00;
int_regs.h.al = 0x13;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, &int_regs);
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 int_regs;
int i;
if (BasicModeInfo.ModeType == T16) {
for(i=0; i<16; i++) {
int_regs.h.ah = 0x10;
int_regs.h.al = 0x00;
int_regs.h.bh = i;
int_regs.h.bl = i;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, &int_regs);
}
}
int_regs.h.ah = 0x10;
int_regs.h.al = 0x12;
int_regs.x.bx = 0;
if (BasicModeInfo.ModeType == T16)
int_regs.x.cx = 16;
else
int_regs.x.cx = 256;
int_regs.x.es = PaletteMem.rm_segment;
int_regs.x.dx = 0x0000;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, &int_regs);
}
int VBE_GetVbeInfoBlock(void) {
_go32_dpmi_registers int_regs;
strncpy(VBE_VbeInfoBlock.VbeSignature, "VBE2", 4);
dosmemput(&VBE_VbeInfoBlock, sizeof(VBE_VbeInfoBlock), __tb);
int_regs.x.ax = 0x4F00;
int_regs.x.di = __tb & 0x0F;
int_regs.x.es = (__tb >> 4) & 0xFFFF;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, &int_regs);
dosmemget(__tb, sizeof(VBE_VbeInfoBlock), &VBE_VbeInfoBlock);
return((int_regs.x.ax == 0x004F) && (VBE_VbeInfoBlock.VbeVersion >= 0x0100));
}
int VBE_GetModeInfoBlock(short mode) {
_go32_dpmi_registers int_regs;
VBE_ModeInfoBlock.ReservedA = 1;
int_regs.x.ax = 0x4F01;
int_regs.x.cx = mode;
int_regs.x.di = __tb & 0x0F;
int_regs.x.es = (__tb >> 4) & 0xFFFF;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, &int_regs);
dosmemget(__tb, sizeof(VBE_ModeInfoBlock), &VBE_ModeInfoBlock);
return(int_regs.x.ax == 0x004F);
}
int VBE_GetProtectedModeInterface(void) {
_go32_dpmi_registers int_regs;
int_regs.x.ax = 0x4F0A;
int_regs.x.bx = 0x0000;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, &int_regs);
VBE_ProtectedModeInterface = (T_VBE_ProtectedModeInterface *) malloc(int_regs.x.cx);
if (VBE_ProtectedModeInterface == NULL)
return(0);
dosmemget(int_regs.x.es * 16 + int_regs.x.di, int_regs.x.cx, VBE_ProtectedModeInterface);
SetWindow = (unsigned int) VBE_ProtectedModeInterface + VBE_ProtectedModeInterface->SetWindowOffset;
PortsMemory = (short *) VBE_ProtectedModeInterface + VBE_ProtectedModeInterface->PortsMemoryOffset;
return(int_regs.x.ax == 0x004F);
}
void VBE_ChangeBankRealInterrupt(short BankNumber) {
_go32_dpmi_registers int_regs;
int_regs.x.ax = 0x4F05;
int_regs.x.bx = WriteWindow;
int_regs.x.dx = BankNumber;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_int(0x10, &int_regs);
CurrentBankNumber = BankNumber;
}
void VBE_ChangeBankRealMode(short BankNumber) {
_go32_dpmi_registers int_regs;
int_regs.x.ax = 0x4F05;
int_regs.x.bx = WriteWindow;
int_regs.x.dx = BankNumber;
int_regs.x.cs = WinFuncPtrSegment;
int_regs.x.ip = WinFuncPtrOffset;
int_regs.x.ss=int_regs.x.sp=int_regs.x.flags=0;
_go32_dpmi_simulate_fcall(&int_regs);
CurrentBankNumber = BankNumber;
}
void VBE_ChangeBankProtectMode(short BankNumber) {
asm __volatile__ ("
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", "cc"
);
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"
);
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"
);
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"
);
}
}
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, 0xf02);
for (i=0; i<BasicModeInfo.ModeWidth; i+=4, ptr++)
_farnspokeb(ptr, addr[i]);
ptr = start;
outportw(0x3c4, 0xe02);
for (i=1; i<BasicModeInfo.ModeWidth; i+=4, ptr++) {
if (addr[i] != addr[i-1])
_farnspokeb(ptr, addr[i]);
}
ptr = start;
outportw(0x3c4, 0xc02);
for (i=2; i<BasicModeInfo.ModeWidth; i+=4, ptr++) {
if (addr[i] != addr[i-1])
_farnspokeb(ptr, addr[i]);
}
ptr = start;
outportw(0x3c4, 0x802);
for (i=3; i<BasicModeInfo.ModeWidth; i+=4, ptr++) {
if (addr[i] != addr[i-1])
_farnspokeb(ptr, addr[i]);
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.