dosbox-wii/src/ints/int10_modes.cpp

597 lines
24 KiB
C++
Raw Normal View History

2009-05-02 23:43:00 +02:00
#include <string.h>
2009-05-02 23:03:37 +02:00
#include "dosbox.h"
#include "mem.h"
#include "inout.h"
#include "int10.h"
2009-05-02 23:27:47 +02:00
#include "mouse.h"
2009-05-02 23:03:37 +02:00
2009-05-02 23:53:27 +02:00
#define _EGA_HALF_CLOCK 0x0001
#define _EGA_LINE_DOUBLE 0x0002
2009-05-02 23:43:00 +02:00
#define SEQ_REGS 0x05
#define GFX_REGS 0x09
#define ATT_REGS 0x15
VideoModeBlock ModeList[]={
2009-05-02 23:53:27 +02:00
/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde ,rate,special flags */
{ 0x000 ,M_TEXT16 ,320 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,70 ,_EGA_HALF_CLOCK },
{ 0x001 ,M_TEXT16 ,320 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,70 ,_EGA_HALF_CLOCK },
{ 0x002 ,M_TEXT16 ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,70 ,0 },
{ 0x003 ,M_TEXT16 ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,70 ,0 },
{ 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,100 ,449 ,80 ,400 ,60 ,0 },
{ 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,100 ,449 ,80 ,400 ,60 ,0},
{ 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,100 ,449 ,80 ,400 ,60 ,0 },
{ 0x007 ,M_TEXT2 ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,70 ,0 },
2009-05-02 23:43:00 +02:00
/* 8,9,0xa are tandy modes */
2009-05-02 23:53:27 +02:00
{ 0x009 ,M_TANDY16,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,100 ,449 ,80 ,400 ,60 ,0},
2009-05-02 23:12:18 +02:00
2009-05-02 23:53:27 +02:00
{ 0x00D ,M_EGA16 ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,70 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE },
{ 0x00E ,M_EGA16 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,70 ,_EGA_LINE_DOUBLE },
{ 0x00F ,M_EGA2 ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,400 ,70 ,0 },
{ 0x010 ,M_EGA16 ,640 ,350 ,80 ,25 ,8 ,14 ,1 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,70 ,0 },
{ 0x011 ,M_EGA2 ,640 ,480 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,449 ,80 ,480 ,70 ,0 },
{ 0x012 ,M_EGA16 ,640 ,480 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,70 ,0 },
{ 0x013 ,M_VGA ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x0000 ,100 ,449 ,80 ,400 ,70 ,0 },
2009-05-02 23:03:37 +02:00
2009-05-02 23:53:27 +02:00
{ 0x100 ,M_LIN8 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,70 ,0 },
{ 0x101 ,M_LIN8 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,70 ,0 },
{ 0x103 ,M_LIN8 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 ,70 ,0 },
2009-05-02 23:03:37 +02:00
2009-05-02 23:53:27 +02:00
{ 0x150 ,M_LIN8 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,70 , 0},
{ 0x151 ,M_LIN8 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,70 , 0},
{ 0x152 ,M_LIN8 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,70 , 0 },
{ 0x153 ,M_LIN8 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,70 , 0 },
{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 ,0 },
2009-05-02 23:03:37 +02:00
};
2009-05-02 23:43:00 +02:00
static Bit8u text_palette[64][3]=
2009-05-02 23:03:37 +02:00
{
2009-05-02 23:43:00 +02:00
{0x00,0x00,0x00},{0x00,0x00,0x2a},{0x00,0x2a,0x00},{0x00,0x2a,0x2a},{0x2a,0x00,0x00},{0x2a,0x00,0x2a},{0x2a,0x2a,0x00},{0x2a,0x2a,0x2a},
{0x00,0x00,0x15},{0x00,0x00,0x3f},{0x00,0x2a,0x15},{0x00,0x2a,0x3f},{0x2a,0x00,0x15},{0x2a,0x00,0x3f},{0x2a,0x2a,0x15},{0x2a,0x2a,0x3f},
{0x00,0x15,0x00},{0x00,0x15,0x2a},{0x00,0x3f,0x00},{0x00,0x3f,0x2a},{0x2a,0x15,0x00},{0x2a,0x15,0x2a},{0x2a,0x3f,0x00},{0x2a,0x3f,0x2a},
{0x00,0x15,0x15},{0x00,0x15,0x3f},{0x00,0x3f,0x15},{0x00,0x3f,0x3f},{0x2a,0x15,0x15},{0x2a,0x15,0x3f},{0x2a,0x3f,0x15},{0x2a,0x3f,0x3f},
{0x15,0x00,0x00},{0x15,0x00,0x2a},{0x15,0x2a,0x00},{0x15,0x2a,0x2a},{0x3f,0x00,0x00},{0x3f,0x00,0x2a},{0x3f,0x2a,0x00},{0x3f,0x2a,0x2a},
{0x15,0x00,0x15},{0x15,0x00,0x3f},{0x15,0x2a,0x15},{0x15,0x2a,0x3f},{0x3f,0x00,0x15},{0x3f,0x00,0x3f},{0x3f,0x2a,0x15},{0x3f,0x2a,0x3f},
{0x15,0x15,0x00},{0x15,0x15,0x2a},{0x15,0x3f,0x00},{0x15,0x3f,0x2a},{0x3f,0x15,0x00},{0x3f,0x15,0x2a},{0x3f,0x3f,0x00},{0x3f,0x3f,0x2a},
{0x15,0x15,0x15},{0x15,0x15,0x3f},{0x15,0x3f,0x15},{0x15,0x3f,0x3f},{0x3f,0x15,0x15},{0x3f,0x15,0x3f},{0x3f,0x3f,0x15},{0x3f,0x3f,0x3f}
2009-05-02 23:03:37 +02:00
};
2009-05-02 23:43:00 +02:00
static Bit8u ega_palette[64][3]=
2009-05-02 23:03:37 +02:00
{
2009-05-02 23:43:00 +02:00
{0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
{0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
{0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
{0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
{0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
{0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
{0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
{0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}
2009-05-02 23:03:37 +02:00
};
2009-05-02 23:53:27 +02:00
#if 0
static Bit8u cga_palette[64][3]= {
{0x00,0x00,0x00}, {0x00,0x00,0x1f}, {0x00,0x1f,0x00}, {0x00,0x1f,0x1f}, {0x1f,0x00,0x00}, {0x1f,0x00,0x1f}, {0x1f,0x1f,0x00}, {0x1f,0x1f,0x1f},
{0x0f,0x0f,0x0f}, {0x00,0x00,0x3f}, {0x00,0x3f,0x00}, {0x00,0x3f,0x3f}, {0x3f,0x00,0x00}, {0x3f,0x00,0x3f}, {0x3f,0x3f,0x00}, {0x3f,0x3f,0x3f},
};
#else
static Bit8u cga_palette[16][3]= {
{0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
{0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
};
#endif
2009-05-02 23:03:37 +02:00
2009-05-02 23:43:00 +02:00
static Bit8u vga_palette[256][3]=
2009-05-02 23:03:37 +02:00
{
2009-05-02 23:43:00 +02:00
{0x00,0x00,0x00},{0x00,0x00,0x2a},{0x00,0x2a,0x00},{0x00,0x2a,0x2a},{0x2a,0x00,0x00},{0x2a,0x00,0x2a},{0x2a,0x15,0x00},{0x2a,0x2a,0x2a},
{0x15,0x15,0x15},{0x15,0x15,0x3f},{0x15,0x3f,0x15},{0x15,0x3f,0x3f},{0x3f,0x15,0x15},{0x3f,0x15,0x3f},{0x3f,0x3f,0x15},{0x3f,0x3f,0x3f},
{0x00,0x00,0x00},{0x05,0x05,0x05},{0x08,0x08,0x08},{0x0b,0x0b,0x0b},{0x0e,0x0e,0x0e},{0x11,0x11,0x11},{0x14,0x14,0x14},{0x18,0x18,0x18},
{0x1c,0x1c,0x1c},{0x20,0x20,0x20},{0x24,0x24,0x24},{0x28,0x28,0x28},{0x2d,0x2d,0x2d},{0x32,0x32,0x32},{0x38,0x38,0x38},{0x3f,0x3f,0x3f},
{0x00,0x00,0x3f},{0x10,0x00,0x3f},{0x1f,0x00,0x3f},{0x2f,0x00,0x3f},{0x3f,0x00,0x3f},{0x3f,0x00,0x2f},{0x3f,0x00,0x1f},{0x3f,0x00,0x10},
{0x3f,0x00,0x00},{0x3f,0x10,0x00},{0x3f,0x1f,0x00},{0x3f,0x2f,0x00},{0x3f,0x3f,0x00},{0x2f,0x3f,0x00},{0x1f,0x3f,0x00},{0x10,0x3f,0x00},
{0x00,0x3f,0x00},{0x00,0x3f,0x10},{0x00,0x3f,0x1f},{0x00,0x3f,0x2f},{0x00,0x3f,0x3f},{0x00,0x2f,0x3f},{0x00,0x1f,0x3f},{0x00,0x10,0x3f},
{0x1f,0x1f,0x3f},{0x27,0x1f,0x3f},{0x2f,0x1f,0x3f},{0x37,0x1f,0x3f},{0x3f,0x1f,0x3f},{0x3f,0x1f,0x37},{0x3f,0x1f,0x2f},{0x3f,0x1f,0x27},
{0x3f,0x1f,0x1f},{0x3f,0x27,0x1f},{0x3f,0x2f,0x1f},{0x3f,0x37,0x1f},{0x3f,0x3f,0x1f},{0x37,0x3f,0x1f},{0x2f,0x3f,0x1f},{0x27,0x3f,0x1f},
{0x1f,0x3f,0x1f},{0x1f,0x3f,0x27},{0x1f,0x3f,0x2f},{0x1f,0x3f,0x37},{0x1f,0x3f,0x3f},{0x1f,0x37,0x3f},{0x1f,0x2f,0x3f},{0x1f,0x27,0x3f},
{0x2d,0x2d,0x3f},{0x31,0x2d,0x3f},{0x36,0x2d,0x3f},{0x3a,0x2d,0x3f},{0x3f,0x2d,0x3f},{0x3f,0x2d,0x3a},{0x3f,0x2d,0x36},{0x3f,0x2d,0x31},
{0x3f,0x2d,0x2d},{0x3f,0x31,0x2d},{0x3f,0x36,0x2d},{0x3f,0x3a,0x2d},{0x3f,0x3f,0x2d},{0x3a,0x3f,0x2d},{0x36,0x3f,0x2d},{0x31,0x3f,0x2d},
{0x2d,0x3f,0x2d},{0x2d,0x3f,0x31},{0x2d,0x3f,0x36},{0x2d,0x3f,0x3a},{0x2d,0x3f,0x3f},{0x2d,0x3a,0x3f},{0x2d,0x36,0x3f},{0x2d,0x31,0x3f},
{0x00,0x00,0x1c},{0x07,0x00,0x1c},{0x0e,0x00,0x1c},{0x15,0x00,0x1c},{0x1c,0x00,0x1c},{0x1c,0x00,0x15},{0x1c,0x00,0x0e},{0x1c,0x00,0x07},
{0x1c,0x00,0x00},{0x1c,0x07,0x00},{0x1c,0x0e,0x00},{0x1c,0x15,0x00},{0x1c,0x1c,0x00},{0x15,0x1c,0x00},{0x0e,0x1c,0x00},{0x07,0x1c,0x00},
{0x00,0x1c,0x00},{0x00,0x1c,0x07},{0x00,0x1c,0x0e},{0x00,0x1c,0x15},{0x00,0x1c,0x1c},{0x00,0x15,0x1c},{0x00,0x0e,0x1c},{0x00,0x07,0x1c},
{0x0e,0x0e,0x1c},{0x11,0x0e,0x1c},{0x15,0x0e,0x1c},{0x18,0x0e,0x1c},{0x1c,0x0e,0x1c},{0x1c,0x0e,0x18},{0x1c,0x0e,0x15},{0x1c,0x0e,0x11},
{0x1c,0x0e,0x0e},{0x1c,0x11,0x0e},{0x1c,0x15,0x0e},{0x1c,0x18,0x0e},{0x1c,0x1c,0x0e},{0x18,0x1c,0x0e},{0x15,0x1c,0x0e},{0x11,0x1c,0x0e},
{0x0e,0x1c,0x0e},{0x0e,0x1c,0x11},{0x0e,0x1c,0x15},{0x0e,0x1c,0x18},{0x0e,0x1c,0x1c},{0x0e,0x18,0x1c},{0x0e,0x15,0x1c},{0x0e,0x11,0x1c},
{0x14,0x14,0x1c},{0x16,0x14,0x1c},{0x18,0x14,0x1c},{0x1a,0x14,0x1c},{0x1c,0x14,0x1c},{0x1c,0x14,0x1a},{0x1c,0x14,0x18},{0x1c,0x14,0x16},
{0x1c,0x14,0x14},{0x1c,0x16,0x14},{0x1c,0x18,0x14},{0x1c,0x1a,0x14},{0x1c,0x1c,0x14},{0x1a,0x1c,0x14},{0x18,0x1c,0x14},{0x16,0x1c,0x14},
{0x14,0x1c,0x14},{0x14,0x1c,0x16},{0x14,0x1c,0x18},{0x14,0x1c,0x1a},{0x14,0x1c,0x1c},{0x14,0x1a,0x1c},{0x14,0x18,0x1c},{0x14,0x16,0x1c},
{0x00,0x00,0x10},{0x04,0x00,0x10},{0x08,0x00,0x10},{0x0c,0x00,0x10},{0x10,0x00,0x10},{0x10,0x00,0x0c},{0x10,0x00,0x08},{0x10,0x00,0x04},
{0x10,0x00,0x00},{0x10,0x04,0x00},{0x10,0x08,0x00},{0x10,0x0c,0x00},{0x10,0x10,0x00},{0x0c,0x10,0x00},{0x08,0x10,0x00},{0x04,0x10,0x00},
{0x00,0x10,0x00},{0x00,0x10,0x04},{0x00,0x10,0x08},{0x00,0x10,0x0c},{0x00,0x10,0x10},{0x00,0x0c,0x10},{0x00,0x08,0x10},{0x00,0x04,0x10},
{0x08,0x08,0x10},{0x0a,0x08,0x10},{0x0c,0x08,0x10},{0x0e,0x08,0x10},{0x10,0x08,0x10},{0x10,0x08,0x0e},{0x10,0x08,0x0c},{0x10,0x08,0x0a},
{0x10,0x08,0x08},{0x10,0x0a,0x08},{0x10,0x0c,0x08},{0x10,0x0e,0x08},{0x10,0x10,0x08},{0x0e,0x10,0x08},{0x0c,0x10,0x08},{0x0a,0x10,0x08},
{0x08,0x10,0x08},{0x08,0x10,0x0a},{0x08,0x10,0x0c},{0x08,0x10,0x0e},{0x08,0x10,0x10},{0x08,0x0e,0x10},{0x08,0x0c,0x10},{0x08,0x0a,0x10},
{0x0b,0x0b,0x10},{0x0c,0x0b,0x10},{0x0d,0x0b,0x10},{0x0f,0x0b,0x10},{0x10,0x0b,0x10},{0x10,0x0b,0x0f},{0x10,0x0b,0x0d},{0x10,0x0b,0x0c},
{0x10,0x0b,0x0b},{0x10,0x0c,0x0b},{0x10,0x0d,0x0b},{0x10,0x0f,0x0b},{0x10,0x10,0x0b},{0x0f,0x10,0x0b},{0x0d,0x10,0x0b},{0x0c,0x10,0x0b},
{0x0b,0x10,0x0b},{0x0b,0x10,0x0c},{0x0b,0x10,0x0d},{0x0b,0x10,0x0f},{0x0b,0x10,0x10},{0x0b,0x0f,0x10},{0x0b,0x0d,0x10},{0x0b,0x0c,0x10},
{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00}
2009-05-02 23:03:37 +02:00
};
2009-05-02 23:43:00 +02:00
VideoModeBlock * CurMode;
2009-05-02 23:03:37 +02:00
2009-05-02 23:43:00 +02:00
bool INT10_SetVideoMode(Bitu mode) {
2009-05-02 23:03:37 +02:00
2009-05-02 23:43:00 +02:00
bool clearmem=true;
2009-05-02 23:03:37 +02:00
Bit8u modeset_ctl,video_ctl,vga_switches;
2009-05-02 23:43:00 +02:00
if (mode<256) {
if (mode & 128) {
clearmem=false;
mode-=128;
}
} else {
/* Check for special vesa mode bits */
mode&=0xfff;
2009-05-02 23:03:37 +02:00
}
2009-05-02 23:43:00 +02:00
LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode);
Bitu i=0;
while (ModeList[i].mode!=0xffff) {
if (ModeList[i].mode==mode) goto foundmode;
i++;
}
LOG(LOG_INT10,LOG_ERROR)("Trying to set illegal mode %X",mode);
return false;
foundmode:
CurMode=&ModeList[i];
2009-05-02 23:03:37 +02:00
2009-05-02 23:43:00 +02:00
/* First read mode setup settings from bios area */
video_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
2009-05-02 23:03:37 +02:00
vga_switches=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES);
modeset_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2009-05-02 23:43:00 +02:00
/* Setup the VGA to the correct mode */
VGA_SetMode(CurMode->type);
2009-05-02 23:53:27 +02:00
Bit16u crtc_base;
bool mono_mode=CurMode->type == M_TEXT2;
if (mono_mode) {
crtc_base=0x3b4;
} else {
crtc_base=0x3d4;
}
2009-05-02 23:43:00 +02:00
/* Setup MISC Output Register */
2009-05-02 23:53:27 +02:00
Bit8u misc_output=0x2 | (mono_mode ? 0x0 : 0x1);
IO_Write(0x3c2,misc_output); //Setup for 3b4 or 3d4
2009-05-02 23:43:00 +02:00
/* Program Sequencer */
Bit8u seq_data[SEQ_REGS];
memset(seq_data,0,SEQ_REGS);
seq_data[1]|=1; //8 dot fonts by default
seq_data[1]|= //Check for half clock
2009-05-02 23:53:27 +02:00
(CurMode->special & _EGA_HALF_CLOCK) ? 0x08 : 0x00;
2009-05-02 23:43:00 +02:00
seq_data[4]|=0x02; //More than 64kb
switch (CurMode->type) {
2009-05-02 23:53:27 +02:00
case M_TEXT2:
2009-05-02 23:43:00 +02:00
case M_TEXT16:
seq_data[2]|=0x3; //Enable plane 0 and 1
seq_data[4]|=0x05; //Alpanumeric and odd/even enabled
break;
case M_EGA16:
seq_data[2]|=0xf; //Enable all planes for writing
break;
case M_LIN8: //Seems to have the same reg layout from testing
case M_VGA:
seq_data[2]|=0xf; //Enable all planes for writing
seq_data[4]|=0xc; //Graphics - odd/even - Chained
break;
2009-05-02 23:20:05 +02:00
}
2009-05-02 23:43:00 +02:00
for (i=0;i<SEQ_REGS;i++) {
IO_Write(0x3c4,i);
IO_Write(0x3c5,seq_data[i]);
2009-05-02 23:20:05 +02:00
}
2009-05-02 23:43:00 +02:00
/* Program CRTC */
/* First disable write protection */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x11);
IO_Write(crtc_base+1,IO_Read(crtc_base+1)&0x7f);
2009-05-02 23:43:00 +02:00
/* Clear all the regs */
for (i=0x0;i<=0x18;i++) {
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,i);IO_Write(crtc_base+1,0);
2009-05-02 23:43:00 +02:00
}
Bit8u overflow=0;Bit8u max_scanline=0;
Bit8u ver_overflow=0;Bit8u hor_overflow=0;
/* Horizontal Total */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x00);IO_Write(crtc_base+1,CurMode->htotal-5);
2009-05-02 23:43:00 +02:00
hor_overflow|=((CurMode->htotal-5) & 0x100) >> 8;
/* Horizontal Display End */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x01);IO_Write(crtc_base+1,CurMode->hdispend-1);
2009-05-02 23:43:00 +02:00
hor_overflow|=((CurMode->hdispend-1) & 0x100) >> 7;
/* Start horizontal Blanking */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x02);IO_Write(crtc_base+1,CurMode->hdispend);
2009-05-02 23:43:00 +02:00
hor_overflow|=((CurMode->hdispend) & 0x100) >> 6;
/* End horizontal Blanking */
Bitu blank_end;
2009-05-02 23:53:27 +02:00
if (CurMode->special & _EGA_HALF_CLOCK) {
2009-05-02 23:43:00 +02:00
blank_end = (CurMode->htotal-1) & 0x7f;
} else {
blank_end = (CurMode->htotal-2) & 0x7f;
2009-05-02 23:20:05 +02:00
}
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x03);IO_Write(crtc_base+1,0x80|(blank_end & 0x1f));
2009-05-02 23:43:00 +02:00
// hor_overflow|=(blank_end & 0x40) >> 3;
/* Start Horizontal Retrace */
Bitu ret_start;
2009-05-02 23:53:27 +02:00
if (CurMode->special & _EGA_HALF_CLOCK) {
2009-05-02 23:43:00 +02:00
ret_start = (CurMode->hdispend+2);
} else {
ret_start = (CurMode->hdispend+4);
}
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x04);IO_Write(crtc_base+1,ret_start);
2009-05-02 23:43:00 +02:00
hor_overflow|=(ret_start & 0x100) >> 4;
/* End Horizontal Retrace */
Bitu ret_end;
2009-05-02 23:53:27 +02:00
if (CurMode->special & _EGA_HALF_CLOCK) {
2009-05-02 23:43:00 +02:00
ret_end = (CurMode->htotal-2) & 0x3f;
} else {
ret_end = (CurMode->htotal-4) & 0x3f;
}
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x05);IO_Write(crtc_base+1,(ret_end & 0x1f) | (blank_end & 0x20) << 2);
2009-05-02 23:43:00 +02:00
// hor_overflow|=(ret_end & 0x20);
//TODO Be sure about these ending values in extended overflow of s3
/* Vertical Total */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x06);IO_Write(crtc_base+1,(CurMode->vtotal-2));
2009-05-02 23:43:00 +02:00
overflow|=((CurMode->vtotal-2) & 0x100) >> 8;
overflow|=((CurMode->vtotal-2) & 0x200) >> 4;
ver_overflow|=((CurMode->vtotal-2) & 0x400) >> 10;
/*
These aren't exactly accurate i think,
Should be more like a certain percentage based on vertical total
So you get same sized borders, but okay :)
*/
/* Vertical Retrace Start */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x10);IO_Write(crtc_base+1,(CurMode->vdispend+12));
2009-05-02 23:43:00 +02:00
overflow|=((CurMode->vdispend+12) & 0x100) >> 6;
overflow|=((CurMode->vdispend+12) & 0x200) >> 2;
ver_overflow|=((CurMode->vdispend+12) & 0x400) >> 6;
/* Vertical Retrace End */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x11);IO_Write(crtc_base+1,(CurMode->vdispend+14) & 0xF);
2009-05-02 23:43:00 +02:00
/* Vertical Display End */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x12);IO_Write(crtc_base+1,(CurMode->vdispend-1));
2009-05-02 23:43:00 +02:00
overflow|=((CurMode->vdispend-1) & 0x100) >> 7;
overflow|=((CurMode->vdispend-1) & 0x200) >> 3;
ver_overflow|=((CurMode->vdispend-1) & 0x400) >> 9;
/* Vertical Blank Start */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x15);IO_Write(crtc_base+1,(CurMode->vdispend+8));
2009-05-02 23:43:00 +02:00
overflow|=((CurMode->vdispend+8) & 0x100) >> 5;
2009-05-02 23:53:27 +02:00
max_scanline|=((CurMode->vdispend+8) & 0x200) >> 4;
2009-05-02 23:43:00 +02:00
ver_overflow|=((CurMode->vdispend+8) & 0x400) >> 8;
/* Vertical Retrace End */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x16);IO_Write(crtc_base+1,(CurMode->vtotal-8));
2009-05-02 23:43:00 +02:00
/* Line Compare */
2009-05-02 23:53:27 +02:00
Bitu line_compare=(mode>=256) ? 2047 : 1023;
IO_Write(crtc_base,0x18);IO_Write(crtc_base+1,line_compare&0xff);
2009-05-02 23:43:00 +02:00
overflow|=(line_compare & 0x100) >> 4;
max_scanline|=(line_compare & 0x200) >> 3;
ver_overflow|=(line_compare & 0x400) >> 4;
Bit8u underline=0;
/* Maximum scanline / Underline Location */
2009-05-02 23:53:27 +02:00
if (CurMode->special & _EGA_LINE_DOUBLE) max_scanline|=0x80;
2009-05-02 23:43:00 +02:00
switch (CurMode->type) {
2009-05-02 23:53:27 +02:00
case M_TEXT2:
2009-05-02 23:43:00 +02:00
case M_TEXT16:
2009-05-02 23:53:27 +02:00
max_scanline|=CurMode->cheight-1;
2009-05-02 23:43:00 +02:00
underline=0x1f;
break;
case M_VGA:
underline=0x40;
max_scanline|=1; //Vga doesn't use double line but this
break;
case M_LIN8:
underline=0x60; //Seems to enable the every 4th clock on my s3
2009-05-02 23:53:27 +02:00
// if (CurMode->special & _VGA_LINE_DOUBLE) max_scanline|=1;
2009-05-02 23:43:00 +02:00
break;
}
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x09);IO_Write(crtc_base+1,max_scanline);
IO_Write(crtc_base,0x14);IO_Write(crtc_base+1,underline);
2009-05-02 23:43:00 +02:00
/* OverFlow */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x07);IO_Write(crtc_base+1,overflow);
2009-05-02 23:43:00 +02:00
/* Extended Horizontal Overflow */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x5d);IO_Write(crtc_base+1,hor_overflow);
2009-05-02 23:43:00 +02:00
/* Extended Vertical Overflow */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x5e);IO_Write(crtc_base+1,ver_overflow);
2009-05-02 23:43:00 +02:00
/* Offset Register */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x13);
2009-05-02 23:43:00 +02:00
switch (CurMode->type) {
case M_LIN8:
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base+1,CurMode->swidth/8);
2009-05-02 23:43:00 +02:00
break;
default:
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base+1,CurMode->hdispend/2);
2009-05-02 23:43:00 +02:00
}
/* Mode Control */
Bit8u mode_control=0;
switch (CurMode->type) {
case M_CGA4:
case M_CGA2:
mode_control=0xa2;
break;
case M_EGA16:
mode_control=0xe3;
break;
2009-05-02 23:53:27 +02:00
case M_TEXT2:
2009-05-02 23:43:00 +02:00
case M_TEXT16:
case M_VGA:
mode_control=0xa3;
break;
case M_LIN8:
mode_control=0xab;
break;
}
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x17);IO_Write(crtc_base+1,mode_control);
2009-05-02 23:43:00 +02:00
/* Renable write protection */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x11);
IO_Write(crtc_base+1,IO_Read(crtc_base+1)|0x80);
2009-05-02 23:43:00 +02:00
/* Setup the correct clock */
2009-05-02 23:53:27 +02:00
switch (CurMode->type) {
case M_VGA:
case M_TEXT2:
case M_TEXT16:
case M_EGA16:
2009-05-02 23:43:00 +02:00
//Stick to 25mhz clock for now
2009-05-02 23:53:27 +02:00
break;
default:
2009-05-02 23:43:00 +02:00
misc_output|=0xef; //Select clock 3
2009-05-02 23:53:27 +02:00
Bitu clock=CurMode->vtotal*8*CurMode->htotal*CurMode->rate;
2009-05-02 23:43:00 +02:00
VGA_SetClock(3,clock/1000);
}
/* Write Misc Output */
IO_Write(0x3c2,misc_output);
/* Program Graphics controller */
Bit8u gfx_data[GFX_REGS];
memset(gfx_data,0,GFX_REGS);
gfx_data[0x7]=0xf; /* Color don't care */
gfx_data[0x8]=0xff; /* BitMask */
switch (CurMode->type) {
2009-05-02 23:53:27 +02:00
case M_TEXT2:
gfx_data[0x5]|=0x10; //Odd-Even Mode
gfx_data[0x6]|=0x0a; //alphanumeric mode at 0xb000=0x7fff
break;
2009-05-02 23:43:00 +02:00
case M_TEXT16:
gfx_data[0x5]|=0x10; //Odd-Even Mode
gfx_data[0x6]|=0x0e; //alphanumeric mode at 0xb800=0xbfff
break;
case M_LIN8:
case M_VGA:
gfx_data[0x5]|=0x40; //256 color mode
gfx_data[0x6]|=0x05; //graphics mode at 0xa000-affff
break;
case M_EGA16:
gfx_data[0x6]|=0x05; //graphics mode at 0xa000-affff
break;
case M_CGA2:
case M_CGA4:
case M_TANDY16:
gfx_data[0x5]|=0x20; //CGA mode
gfx_data[0x6]|=0x0f; //graphics mode at at 0xb800=0xbfff
break;
}
for (i=0;i<GFX_REGS;i++) {
IO_Write(0x3ce,i);
IO_Write(0x3cf,gfx_data[i]);
}
Bit8u att_data[ATT_REGS];
memset(att_data,0,ATT_REGS);
att_data[0x12]=0xf; //Always have all color planes enabled
/* Porgram Attribute Controller */
switch (CurMode->type) {
case M_EGA16:
if (CurMode->mode>0xe) goto att_text16;
2009-05-02 23:53:27 +02:00
for (i=0;i<8;i++) {
att_data[i]=i;
att_data[i+8]=i+0x10;
}
break;
2009-05-02 23:43:00 +02:00
case M_TANDY16:
att_data[0x10]=0x01; //Color Graphics
2009-05-02 23:53:27 +02:00
for (i=0;i<16;i++) {
2009-05-02 23:43:00 +02:00
att_data[i]=i;
}
break;
2009-05-02 23:53:27 +02:00
case M_TEXT2:
2009-05-02 23:43:00 +02:00
case M_TEXT16:
att_data[0x13]=0x08; //Pel panning on 8, although we don't have 9 dot text mode
att_data[0x10]=0x0C; //Color Text with blinking
att_text16:
for (i=0;i<8;i++) {
att_data[i]=i;
att_data[i+8]=i+0x38;
}
break;
case M_CGA2:
2009-05-02 23:53:27 +02:00
IO_Write(0x3d9,0x7); //Setup using CGA color select register
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x7);
goto skipatt;
2009-05-02 23:43:00 +02:00
case M_CGA4:
2009-05-02 23:53:27 +02:00
IO_Write(0x3d9,0x30); //Setup using CGA color select register
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x30);
2009-05-02 23:43:00 +02:00
goto skipatt;
case M_VGA:
case M_LIN8:
for (i=0;i<16;i++) {
att_data[i]=i;
}
att_data[0x10]=0x41; //Color Graphics 8-bit
break;
2009-05-02 23:20:05 +02:00
}
2009-05-02 23:53:27 +02:00
IO_Read(mono_mode ? 0x3ba : 0x3da);
2009-05-02 23:43:00 +02:00
for (i=0;i<ATT_REGS;i++) {
IO_Write(0x3c0,i);
IO_Write(0x3c0,att_data[i]);
}
skipatt:
/* Setup the DAC */
IO_Write(0x3c8,0);
switch (CurMode->type) {
case M_EGA16:
if (CurMode->mode>0xe) goto dac_text16;
for (i=0;i<64;i++) {
IO_Write(0x3c9,ega_palette[i][0]);
IO_Write(0x3c9,ega_palette[i][1]);
IO_Write(0x3c9,ega_palette[i][2]);
2009-05-02 23:03:37 +02:00
}
2009-05-02 23:43:00 +02:00
break;
2009-05-02 23:53:27 +02:00
case M_CGA2:
case M_CGA4:
case M_TANDY16:
for (i=0;i<16;i++) {
IO_Write(0x3c9,cga_palette[i][0]);
IO_Write(0x3c9,cga_palette[i][1]);
IO_Write(0x3c9,cga_palette[i][2]);
}
break;
case M_TEXT2:
2009-05-02 23:43:00 +02:00
case M_TEXT16:
dac_text16:
for (i=0;i<64;i++) {
IO_Write(0x3c9,text_palette[i][0]);
IO_Write(0x3c9,text_palette[i][1]);
IO_Write(0x3c9,text_palette[i][2]);
}
break;
case M_VGA:
case M_LIN8:
2009-05-02 23:03:37 +02:00
for (i=0;i<256;i++) {
2009-05-02 23:43:00 +02:00
IO_Write(0x3c9,vga_palette[i][0]);
IO_Write(0x3c9,vga_palette[i][1]);
IO_Write(0x3c9,vga_palette[i][2]);
2009-05-02 23:03:37 +02:00
}
2009-05-02 23:43:00 +02:00
break;
2009-05-02 23:03:37 +02:00
}
2009-05-02 23:53:27 +02:00
/* Setup some special stuff for different modes */
Bit8u feature=real_readb(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE);
2009-05-02 23:43:00 +02:00
switch (CurMode->type) {
2009-05-02 23:53:27 +02:00
case M_CGA2:
feature=(feature&~0x30)|0x20;
IO_Write(0x3d8,0x12); //Setup using CGA color select register
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x12);
break;
case M_CGA4:
feature=(feature&~0x30)|0x20;
IO_Write(0x3d8,0x2); //Setup using CGA color select register
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2);
break;
2009-05-02 23:43:00 +02:00
case M_TANDY16:
2009-05-02 23:53:27 +02:00
feature=(feature&~0x30)|0x20;
2009-05-02 23:43:00 +02:00
IO_Write(0x3df,0x80); //Enter 32k mode and banks on 0
break;
2009-05-02 23:53:27 +02:00
case M_TEXT2:
feature=(feature&~0x30)|0x30;
break;
case M_TEXT16:
feature=(feature&~0x30)|0x20;
break;
case M_EGA16:
case M_VGA:
feature=(feature&~0x30);
break;
2009-05-02 23:03:37 +02:00
}
2009-05-02 23:53:27 +02:00
real_writeb(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE,feature);
2009-05-02 23:43:00 +02:00
/* Setup the CPU Window */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x6a);
IO_Write(crtc_base+1,0);
2009-05-02 23:43:00 +02:00
/* Setup the linear frame buffer */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x59);
IO_Write(crtc_base+1,(Bit8u)(S3_LFB_BASE >> 24));
IO_Write(crtc_base,0x5a);
IO_Write(crtc_base+1,(Bit8u)(S3_LFB_BASE >> 16));
2009-05-02 23:43:00 +02:00
/* Setup some remaining S3 registers */
2009-05-02 23:53:27 +02:00
IO_Write(crtc_base,0x31);IO_Write(crtc_base+1,0x9); //Enable banked memory and 256k+ access
IO_Write(crtc_base,0x58);IO_Write(crtc_base+1,0x3); //Enable 8 mb of linear addressing
IO_Write(crtc_base,0x38);IO_Write(crtc_base+1,0x48); //Register lock 1
IO_Write(crtc_base,0x39);IO_Write(crtc_base+1,0xa5); //Register lock 2
2009-05-02 23:20:05 +02:00
2009-05-02 23:43:00 +02:00
/* Load text mode font */
2009-05-02 23:53:27 +02:00
if (CurMode->type<=M_TEXT16) {
2009-05-02 23:43:00 +02:00
INT10_LoadFont(Real2Phys(int10.rom.font_16),true,256,0,0,16);
}
/* Clear video memory if needs be */
if (clearmem) {
switch (CurMode->type) {
case M_CGA4:
case M_CGA2:
for (i=0;i<16*1024;i++) {
real_writew(0xb800,i*2,0x0000);
2009-05-02 23:03:37 +02:00
}
2009-05-02 23:43:00 +02:00
break;
2009-05-02 23:53:27 +02:00
case M_TEXT2:
for (i=0;i<16*1024;i++) {
real_writew(0xb000,i*2,0x0120);
}
break;
2009-05-02 23:43:00 +02:00
case M_TEXT16:
for (i=0;i<16*1024;i++) {
2009-05-02 23:53:27 +02:00
real_writew(0xb800,i*2,0x0720);
2009-05-02 23:03:37 +02:00
}
2009-05-02 23:43:00 +02:00
break;
case M_EGA16:
case M_VGA:
case M_LIN8:
/* Just clear the whole 2 mb of memory */
for (i=0;i<2*1024*1024/4;i++) {
mem_writed(S3_LFB_BASE+i*4,0);
2009-05-02 23:03:37 +02:00
}
}
}
2009-05-02 23:43:00 +02:00
/* Setup the BIOS */
if (mode<128) real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
else real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode-0x98); //Looks like the s3 bios
real_writew(BIOSMEM_SEG,BIOSMEM_NB_COLS,CurMode->twidth);
real_writew(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,CurMode->plength);
2009-05-02 23:53:27 +02:00
real_writew(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_base);
2009-05-02 23:43:00 +02:00
real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,CurMode->theight-1);
real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,CurMode->cheight);
2009-05-02 23:03:37 +02:00
real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|(clearmem << 7)));
2009-05-02 23:27:47 +02:00
real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0x09);
2009-05-02 23:03:37 +02:00
real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
// FIXME We nearly have the good tables. to be reworked
real_writeb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
real_writew(BIOSMEM_SEG,BIOSMEM_VS_POINTER,0x00);
real_writew(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00);
// Set cursor shape
2009-05-02 23:53:27 +02:00
if(CurMode->type<=M_TEXT16) {
2009-05-02 23:43:00 +02:00
INT10_SetCursorShape(0x06,07);
2009-05-02 23:03:37 +02:00
}
// Set cursor pos for page 0..7
for(i=0;i<8;i++) INT10_SetCursorPos(0,0,(Bit8u)i);
// Set active page 0
INT10_SetActivePage(0);
/* Set some interrupt vectors */
2009-05-02 23:43:00 +02:00
switch (CurMode->cheight) {
case 8:RealSetVec(0x43,int10.rom.font_8_first);break;
case 14:RealSetVec(0x43,int10.rom.font_14);break;
case 16:RealSetVec(0x43,int10.rom.font_16);break;
}
2009-05-02 23:27:47 +02:00
/* Tell mouse resolution change */
2009-05-02 23:43:00 +02:00
Mouse_NewVideoMode();
return true;
}
2009-05-02 23:27:47 +02:00