Video mode switching when entering pice shell.
authorEugene Ingerman <geneing@myrealbox.com>
Sun, 30 Jun 2002 02:45:44 +0000 (02:45 +0000)
committerEugene Ingerman <geneing@myrealbox.com>
Sun, 30 Jun 2002 02:45:44 +0000 (02:45 +0000)
svn path=/trunk/; revision=3165

reactos/apps/utils/pice/module/makefile
reactos/apps/utils/pice/module/vga.c
reactos/apps/utils/pice/module/vga_utils.asm [new file with mode: 0644]

index 13f3e67..85ff43f 100644 (file)
@@ -27,6 +27,7 @@ TARGET_OBJECTS = \
   syscall.o \
   trace.o \
   vga.o \
+  vga_utils.o \
   utils.o
 
 include $(PATH_TO_TOP)/rules.mak
index 62101db..4e2e8c0 100644 (file)
@@ -17,6 +17,7 @@ Environment:
 Author:
 
     Klaus P. Gerlicher
+       Reactos Port by Eugene Ingerman
 
 Revision History:
 
@@ -42,41 +43,70 @@ Copyright notice:
 ////////////////////////////////////////////////////
 // PROTOTYPES
 ////
+extern void pice_save_current_registers(void);
+extern void pice_restore_current_registers(void);
+extern void pice_set_mode_3_80x50(void);
+extern void pice_set_mode_3_80x25(void);
+
+extern UCHAR cGraphTable[8*256];
+
+// storage for original VGA font
+UCHAR cGraphTable2[16*256];
 
 ////////////////////////////////////////////////////
 // DEFINES
 ////
-#define LOCAL_CONSOLE // undefine this to get text only hercules version
+#define VGA_EXTENDED  // define this for 80x50 console mode
+
+#ifndef VGA_EXTENDED
+#define SCREEN_BUFFER_SIZE (80*25*2)
+#else
+#define SCREEN_BUFFER_SIZE (80*50*2)
+#endif
+
+/* Port addresses of control regs */
+#define MISCOUTPUT  0x3c2
+#define FEATURECONTROL 0x3da
+#define SEQUENCER 0x3c4
+#define CRTC 0x03d4
+#define GRAPHICS 0x3ce
+#define ATTRIBS 0x03c0
+#define PELADDRESSWRITE 0x3c8
+#define PELDATAREG 0x3c9
+
+/* Number of regs on the various controllers */
+
+#define MAXSEQ 5
+#define MAXCRTC 0x19
+#define MAXGRAPH 0x9
+#define MAXATTRIB 0x015
 
 ////////////////////////////////////////////////////
 // GLOBALS
 ////
-// used for HERCUELS text and VGA text mode
-/*
+// used for HERCULES text and VGA text mode
 WINDOW wWindowVga[4]=
+#ifndef VGA_EXTENDED
 {
        {1,3,1,0,FALSE},
        {5,4,1,0,FALSE},
        {10,9,1,0,FALSE},
        {20,4,1,0,FALSE}
 };
-*/
-
-WINDOW wWindowVga[4]=
+#else // VGA_EXTENDED
 {
        {1,3,1,0,FALSE},
-       {5,7,1,0,FALSE},
-       {14,15,1,0,FALSE},
-       {30,14,1,0,FALSE}
+       {5,4,1,0,FALSE},
+       {10,24,1,0,FALSE},
+       {35,14,1,0,FALSE}
 };
-
-// 25 line text mode
-UCHAR MGATable25[]={97,80,82,15,25, 6,25,25, 2,13,11,12, 0, 0, 0, 0};
+#endif // VGA_EXTENDED
 
 PUCHAR pScreenBufferVga;
 PUCHAR pScreenBufferSaveVga = NULL;
 PUCHAR pScreenBufferTempVga;
 PUCHAR pScreenBufferHardwareVga;
+PUCHAR pFontBufferVga = NULL;
 
 UCHAR offset_a = 0;
 UCHAR offset_c = 0,offset_d = 0;
@@ -97,6 +127,115 @@ struct _attr
     }u;
 }attr;
 
+unsigned char oldgraphicsmode;
+unsigned char oldgraphicsmisc;
+unsigned char oldsqregmapmask;
+unsigned char oldsqregmemory;
+unsigned char oldgraphicssetresetenable;
+unsigned char oldgraphicsreadmapsel;
+
+unsigned char read_vga_reg(int port, int reg)
+{
+  outportb(port,reg);
+  return(inportb(port+1));
+}
+
+void write_vga_reg(int port, unsigned char reg, unsigned char value)
+{
+       outportb(port,reg);
+       outportb(port+1,value);
+}
+
+/* Registers within controllers */
+#define VREND 0x11
+#define GRREGSETRESET 0
+#define GRREGENABLESETRESET 1
+#define GRREGREADMAPSEL 4
+#define SQREGMAPMASK 2
+#define SQREGMEMORY 4
+#define GRREGWRMODE 5
+#define GRREGMISC 6
+
+void map_font_memory(void)
+{
+       oldgraphicssetresetenable = read_vga_reg(GRAPHICS, GRREGENABLESETRESET);
+       oldgraphicsmode = read_vga_reg(GRAPHICS, GRREGWRMODE);
+       oldgraphicsmisc = read_vga_reg(GRAPHICS, GRREGMISC);
+       oldgraphicsreadmapsel = read_vga_reg(GRAPHICS, GRREGREADMAPSEL);
+       oldsqregmapmask = read_vga_reg(SEQUENCER, SQREGMAPMASK);
+       oldsqregmemory = read_vga_reg(SEQUENCER, SQREGMEMORY);
+
+
+       /* Make sure set/reset enable is off */
+       write_vga_reg(GRAPHICS,GRREGENABLESETRESET,0);
+       /* Select read plane 2 */
+       write_vga_reg(GRAPHICS,GRREGREADMAPSEL,0x02);
+       /* Make sure write and read mode = 0 */
+       write_vga_reg(GRAPHICS,GRREGWRMODE,0x00);
+       /* Set mapping to 64K at a000:0 & turn off odd/even at the graphics reg */
+       write_vga_reg(GRAPHICS,GRREGMISC, 0x04);
+       /* Set sequencer plane to 2 */
+       write_vga_reg(SEQUENCER,SQREGMAPMASK, 0x04);
+       /* Turn off odd/even at the sequencer */
+       write_vga_reg(SEQUENCER,SQREGMEMORY, 0x07);
+}
+
+void unmap_font_memory(void)
+{
+       write_vga_reg(GRAPHICS,GRREGENABLESETRESET,oldgraphicssetresetenable);
+       write_vga_reg(GRAPHICS,GRREGWRMODE,oldgraphicsmode);
+       write_vga_reg(GRAPHICS,GRREGREADMAPSEL,oldgraphicsreadmapsel);
+       write_vga_reg(GRAPHICS,GRREGMISC, oldgraphicsmisc);
+       write_vga_reg(SEQUENCER,SQREGMAPMASK, oldsqregmapmask);
+       write_vga_reg(SEQUENCER,SQREGMEMORY, oldsqregmemory);
+}
+
+/* Font and palette constants */
+#define BYTESPERFONT 8
+#define FONTENTRIES 256
+#define FONTBUFFERSIZE 8192
+
+void save_font(UCHAR* graph_table)
+{
+       PUCHAR FontBase = pFontBufferVga;
+       int i,j;
+       map_font_memory();
+
+       for (i=0; i < FONTENTRIES; i++)
+               for (j=0; j < 16; j++)
+                               graph_table[i*16+j] = FontBase[i*32+j];
+
+       unmap_font_memory();
+}
+
+void load_font(UCHAR* graph_table,int bEnter)
+{
+       PUCHAR FontBase = pFontBufferVga;
+       int i,j;
+       map_font_memory();
+
+       if(bEnter)
+       {
+#ifdef VGA_EXTENDED
+               for (i=0; i < FONTENTRIES; i++)
+                       for (j=0; j < 8; j++)
+                                       FontBase[i*32+j] = graph_table[i*BYTESPERFONT+j];
+#else // VGA_EXTENDED
+               for (i=0; i < FONTENTRIES; i++)
+                       for (j=0; j < 16; j++)
+                                       FontBase[i*32+j] = graph_table[i*BYTESPERFONT+(j/2)] << (j&1);
+#endif // VGA_EXTENDED
+       }
+       else
+       {
+               for (i=0; i < FONTENTRIES; i++)
+                       for (j=0; j < 16; j++)
+                                       FontBase[i*32+j] = graph_table[i*16+j];
+       }
+
+       unmap_font_memory();
+}
+
 //*************************************************************************
 // SetForegroundColorVga()
 //
@@ -137,13 +276,8 @@ void ShowCursorVga(void)
 
     bCursorEnabled=TRUE;
 
-#ifdef LOCAL_CONSOLE
        outb_p(0x0a,0x3d4);
        outb_p(inb_p(0x3d5)&~0x20,0x3d5);
-#else
-       outb_p(0x0a,0x3b4);
-       outb_p(inb_p(0x3b5)&~0x20,0x3b5);
-#endif
 
     LEAVE_FUNC();
 }
@@ -158,13 +292,8 @@ void HideCursorVga(void)
     ENTER_FUNC();
        bCursorEnabled=FALSE;
 
-#ifdef LOCAL_CONSOLE
        outb_p(0x0a,0x3d4);
        outb_p(inb_p(0x3d5)|0x20,0x3d5);
-#else
-       outb_p(0x0a,0x3b4);
-       outb_p(inb_p(0x3b5)|0x20,0x3b5);
-#endif
 
     LEAVE_FUNC();
 }
@@ -176,13 +305,11 @@ void HideCursorVga(void)
 //*************************************************************************
 void CopyLineToVga(USHORT dest,USHORT src)
 {
-       USHORT i;
     PUSHORT p = (PUSHORT)pScreenBufferVga;
 
     ENTER_FUNC();
 
-       for(i=0;i<GLOBAL_SCREEN_WIDTH;i++)
-               p[dest*GLOBAL_SCREEN_WIDTH+i] = p[src*GLOBAL_SCREEN_WIDTH+i];
+       PICE_memcpy(&p[dest*GLOBAL_SCREEN_WIDTH],&p[src*GLOBAL_SCREEN_WIDTH],GLOBAL_SCREEN_WIDTH*sizeof(USHORT));
 
     LEAVE_FUNC();
 }
@@ -196,22 +323,15 @@ void InvertLineVga(ULONG line)
 {
     ULONG i;
     PUSHORT p = (PUSHORT)pScreenBufferVga;
-#ifdef LOCAL_CONSOLE
     USHORT attr;
-#endif
 
-    if(line<25)
+    if(line < GLOBAL_SCREEN_HEIGHT)
     {
-#ifdef LOCAL_CONSOLE
         attr = p[line*GLOBAL_SCREEN_WIDTH]>>8;
         attr = ((attr & 0x07)<<4) | ((attr & 0xF0)>>4);
         attr <<= 8;
         for(i=0;i<GLOBAL_SCREEN_WIDTH;i++)
             p[line*GLOBAL_SCREEN_WIDTH + i] = (p[line*GLOBAL_SCREEN_WIDTH + i] & 0x00FF) | attr;
-#else
-        for(i=0;i<GLOBAL_SCREEN_WIDTH;i++)
-            p[line*GLOBAL_SCREEN_WIDTH + i] = p[line*GLOBAL_SCREEN_WIDTH + i] ^ 0xFF00;
-#endif
     }
 }
 
@@ -225,7 +345,7 @@ void HatchLineVga(ULONG line)
     ULONG i;
     PUSHORT p = (PUSHORT)pScreenBufferVga;
 
-    if(line<GLOBAL_SCREEN_HEIGHT)
+    if(line < GLOBAL_SCREEN_HEIGHT)
     {
         for(i=0;i<GLOBAL_SCREEN_WIDTH;i++)
             p[line*GLOBAL_SCREEN_WIDTH + i] = (p[line*GLOBAL_SCREEN_WIDTH + i] & 0xF0FF) | 0x0c00;
@@ -242,7 +362,7 @@ void ClrLineVga(ULONG line)
     ULONG i;
     PUSHORT p = (PUSHORT)pScreenBufferVga;
 
-    if(line<GLOBAL_SCREEN_HEIGHT)
+    if(line < GLOBAL_SCREEN_HEIGHT)
     {
         for(i=0;i<GLOBAL_SCREEN_WIDTH;i++)
             p[line*GLOBAL_SCREEN_WIDTH + i] = (USHORT)((attr.u.Asuchar<<8) | 0x20);
@@ -276,15 +396,6 @@ void PrintCursorVga(BOOLEAN bForce)
 
         charoffset = (y* GLOBAL_SCREEN_WIDTH + x);
 
-#ifndef LOCAL_CONSOLE
-               outb_p(0x0e,0x3b4);
-               data=(UCHAR)((charoffset>>8)&0xFF);
-               outb_p(data,0x3b5);
-
-               outb_p(0x0d,0x3b4);
-               data=(UCHAR)(charoffset & 0xFF);
-               outb_p(data,0x3b5);
-#else
                outb_p(0x0e,0x3d4);
                data=(UCHAR)((charoffset>>8)&0xFF);
                outb_p(data,0x3d5);
@@ -292,7 +403,6 @@ void PrintCursorVga(BOOLEAN bForce)
         outb_p(0x0f,0x3d4);
                data=(UCHAR)(charoffset & 0xFF);
                outb_p(data,0x3d5);
-#endif
     }
 }
 
@@ -302,33 +412,37 @@ void PrintCursorVga(BOOLEAN bForce)
 //*************************************************************************
 void SaveGraphicsStateVga(void)
 {
-#ifdef LOCAL_CONSOLE
-    // copy the screen content to temp area
-    PICE_memcpy(pScreenBufferTempVga,pScreenBufferHardwareVga,FRAMEBUFFER_SIZE);
+       UCHAR data;
+
+       // save current regs
+       pice_save_current_registers();
+
+       // unprotect crtc regs 0-7
+       outb_p(0x11,0x3d4);
+       data = inb_p(0x3d5);
+       outb_p(data & 0x7F,0x3d5);
+
+       // save current font
+       save_font(cGraphTable2);
+
+       // restore original regs
+#ifdef VGA_EXTENDED
+       pice_set_mode_3_80x50();
+#else
+       pice_set_mode_3_80x25();
+#endif
+
+       // load a font
+       load_font(cGraphTable,1);
+
+       // copy the screen content to temp area
+    PICE_memcpy(pScreenBufferTempVga,pScreenBufferHardwareVga,SCREEN_BUFFER_SIZE);
     // copy the console to the screen
-    PICE_memcpy(pScreenBufferHardwareVga,pScreenBufferVga,FRAMEBUFFER_SIZE);
+    PICE_memcpy(pScreenBufferHardwareVga,pScreenBufferVga,SCREEN_BUFFER_SIZE);
     // save original pointer
     pScreenBufferSaveVga = pScreenBufferVga;
     // pScreenBufferVga now points to screen
     pScreenBufferVga = pScreenBufferHardwareVga;
-
-    // save video RAM start address
-    outb_p(0xc,0x3d4);
-    offset_c = inb_p(0x3d5);
-    outb_p(0x0,0x3d5);
-    outb_p(0xd,0x3d4);
-    offset_d = inb_p(0x3d5);
-    outb_p(0x0,0x3d5);
-
-    // cursor state
-    outb_p(0x0a,0x3d4);
-       offset_a = inb_p(0x3d5);
-    // cursor position
-       outb_p(0x0e,0x3d4);
-       offset_e = inb_p(0x3d5);
-       outb_p(0x0f,0x3d4);
-       offset_f = inb_p(0x3d5);
-#endif
 }
 
 //*************************************************************************
@@ -337,28 +451,24 @@ void SaveGraphicsStateVga(void)
 //*************************************************************************
 void RestoreGraphicsStateVga(void)
 {
-#ifdef LOCAL_CONSOLE
+       UCHAR data;
+
+       // unprotect crtc regs 0-7
+       outb_p(0x11,0x3d4);
+       data = inb_p(0x3d5);
+       outb_p(data & 0x7F,0x3d5);
+
+       // restore original regs
+       pice_restore_current_registers();
+
+       // load a font
+       load_font(cGraphTable2,0);
+
     pScreenBufferVga = pScreenBufferSaveVga;
     // copy screen to the console
-    PICE_memcpy(pScreenBufferVga,pScreenBufferHardwareVga,FRAMEBUFFER_SIZE);
+    PICE_memcpy(pScreenBufferVga,pScreenBufferHardwareVga,SCREEN_BUFFER_SIZE);
     // copy the temp area to the screen
-    PICE_memcpy(pScreenBufferHardwareVga,pScreenBufferTempVga,FRAMEBUFFER_SIZE);
-
-    // restore video RAM start address
-    outb_p(0xc,0x3d4);
-    outb_p(offset_c,0x3d5);
-    outb_p(0xd,0x3d4);
-    outb_p(offset_d,0x3d5);
-
-    // cursor state
-    outb_p(0x0a,0x3d4);
-       outb_p(offset_a,0x3d5);
-    // cursor position
-       outb_p(0x0e,0x3d4);
-    outb_p(offset_e,0x3d5);
-       outb_p(0x0f,0x3d4);
-    outb_p(offset_f,0x3d5);
-#endif
+    PICE_memcpy(pScreenBufferHardwareVga,pScreenBufferTempVga,SCREEN_BUFFER_SIZE);
 }
 
 //*************************************************************************
@@ -369,12 +479,9 @@ void RestoreGraphicsStateVga(void)
 BOOLEAN ConsoleInitVga(void)
 {
        BOOLEAN bResult = FALSE;
-#ifndef LOCAL_CONSOLE
-       PUCHAR pMGATable = MGATable25;
-       UCHAR i,reg,data;
-#endif
     PUSHORT p;
        PHYSICAL_ADDRESS FrameBuffer;
+       PHYSICAL_ADDRESS FontBuffer;
 
 
     ENTER_FUNC();
@@ -399,32 +506,27 @@ BOOLEAN ConsoleInitVga(void)
     SetWindowGeometry(wWindowVga);
 
     GLOBAL_SCREEN_WIDTH = 80;
-    GLOBAL_SCREEN_HEIGHT = 45;
+#ifndef VGA_EXTENDED
+    GLOBAL_SCREEN_HEIGHT = 25;
+#else // VGA_EXTENDED
+    GLOBAL_SCREEN_HEIGHT = 50;
+#endif // VGA_EXTENDED
 
     attr.u.Asuchar = 0x07;
 
-#ifdef LOCAL_CONSOLE
     // the real framebuffer
        FrameBuffer.u.LowPart = 0xB8000;
-       pScreenBufferHardwareVga = MmMapIoSpace(FrameBuffer,FRAMEBUFFER_SIZE,FALSE);
+       pScreenBufferHardwareVga = MmMapIoSpace(FrameBuffer,SCREEN_BUFFER_SIZE,FALSE);
+
+       //The real font buffer
+       FontBuffer.u.LowPart = 0xA0000;
+       pFontBufferVga = MmMapIoSpace(FontBuffer,FONTBUFFERSIZE,FALSE);
+
     // the console
-       pScreenBufferVga = PICE_malloc(FRAMEBUFFER_SIZE,NONPAGEDPOOL);
+       pScreenBufferVga = PICE_malloc(SCREEN_BUFFER_SIZE,NONPAGEDPOOL);
     // the save area
-       pScreenBufferTempVga = PICE_malloc(FRAMEBUFFER_SIZE,NONPAGEDPOOL);
-#else
-       outb_p(0,0x3b8);
-       outb_p(0,0x3bf);
-       for(i=0;i<sizeof(MGATable25);i++)
-       {
-               reg=i;
-               outb_p(reg,0x3b4);
-               data=pMGATable[i];
-               outb_p(data,0x3b5);
-       }
-       outb_p(0x08,0x3b8);
+       pScreenBufferTempVga = PICE_malloc(SCREEN_BUFFER_SIZE,NONPAGEDPOOL);
 
-       pScreenBufferVga=MmMapIoSpace(0xB0000,FRAMEBUFFER_SIZE,MmWriteCombined);
-#endif
        if(pScreenBufferVga)
        {
         DPRINT((0,"VGA memory phys. 0x000b0000 mapped to virt. 0x%x\n",pScreenBufferVga));
@@ -433,7 +535,7 @@ BOOLEAN ConsoleInitVga(void)
 
         p = (PUSHORT)pScreenBufferVga;
 
-               PICE_memset(pScreenBufferVga,0x0,FRAMEBUFFER_SIZE);
+               PICE_memset(pScreenBufferVga,0x0,SCREEN_BUFFER_SIZE);
 
         DPRINT((0,"VGA memory cleared!\n"));
 
@@ -456,21 +558,15 @@ void ConsoleShutdownVga(void)
 {
     ENTER_FUNC();
 
-#ifdef LOCAL_CONSOLE
        if(pScreenBufferVga)
     {
         PICE_free(pScreenBufferVga);
         PICE_free(pScreenBufferTempVga);
-               MmUnmapIoSpace(pScreenBufferHardwareVga,FRAMEBUFFER_SIZE);
+               MmUnmapIoSpace(pScreenBufferHardwareVga,SCREEN_BUFFER_SIZE);
+               MmUnmapIoSpace(pFontBufferVga,FONTBUFFERSIZE);
     }
-#else
-       // HERC video off
-       outb_p(0,0x3b8);
-       outb_p(0,0x3bf);
-
-       if(pScreenBufferVga)
-               MmUnmapIoSpace(pScreenBufferVga,FRAMEBUFFER_SIZE);
-#endif
 
     LEAVE_FUNC();
 }
+
+
diff --git a/reactos/apps/utils/pice/module/vga_utils.asm b/reactos/apps/utils/pice/module/vga_utils.asm
new file mode 100644 (file)
index 0000000..9602817
--- /dev/null
@@ -0,0 +1,729 @@
+;/*++
+;
+;Copyright (c) 1998-2001 Klaus P. Gerlicher
+;
+;Module Name:
+;
+;    vga_utils.asm
+;
+;Abstract:
+;
+;    assembler function for directly programming standard VGA
+;
+;Environment:
+;
+;    LINUX 2.2.X
+;    Kernel mode only
+;
+;Author:
+;
+;    Klaus P. Gerlicher
+;    Reactos Port by Eugene Ingerman
+;
+;Revision History:
+;
+;    30-Oct-2001:      created
+;
+;Copyright notice:
+;
+;  This file may be distributed under the terms of the GNU Public License.
+;
+;--*/
+
+global _pice_save_current_registers
+global _pice_restore_current_registers
+global _pice_set_mode_3_80x50
+global _pice_set_mode_3_80x25
+
+;****************************************************************************
+;* some assign's ************************************************************
+;****************************************************************************
+%assign VGA_CRT_REGISTERS              24
+%assign VGA_ATTRIBUTE_REGISTERS                21
+%assign VGA_GRAPHIC_REGISTERS          9
+%assign VGA_SEQUENCER_REGISTERS                5
+%assign VGA_MISC_REGISTERS             1
+
+%assign VGA_IO_BASE                    03c0h
+%assign VGA_IO_SIZE                    020h
+
+%assign VGA_ATTRIBUTE_INDEX            03c0h
+%assign VGA_ATTRIBUTE_DATA_WRITE       03c0h
+%assign VGA_ATTRIBUTE_DATA_READ                03c1h
+%assign VGA_MISC_DATA_WRITE            03c2h
+%assign VGA_SEQUENCER_INDEX            03c4h
+%assign VGA_SEQUENCER_DATA             03c5h
+%assign VGA_PEL_MASK                   03c6h
+%assign VGA_PEL_INDEX_READ             03c7h
+%assign VGA_PEL_INDEX_WRITE            03c8h
+%assign VGA_PEL_DATA                   03c9h
+%assign VGA_MISC_DATA_READ             03cch
+%assign VGA_GRAPHIC_INDEX              03ceh
+%assign VGA_GRAPHIC_DATA               03cfh
+%assign VGA_CRT_INDEX                  03d4h
+%assign VGA_CRT_DATA                   03d5h
+%assign VGA_INPUT_STATUS               03dah
+
+section .data
+pice_mode3_80x50_registers:
+;      offsets                 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18
+.crt:                  db      0x5f,0x4f,0x50,0x82,0x55,0x80,0xbf,0x1f,0x00,0x67,0x06,0x07,0x00,0x00,0x00,0x00,0x9c,0x8f,0x8f,0x28,0x1f,0x96,0xb9,0xa3,0xff
+.attribute             db      0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x08,0x00,0x0f,0x00,0x00
+.graphic:              db      0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0xff
+.sequencer:            db      0x03,0x00,0x03,0x00,0x02 ; 9 bits per char
+;.sequencer:           db      0x03,0x01,0x03,0x00,0x02 ; 8 bits per char
+.misc:                 db      0x67
+
+pice_mode3_80x25_registers:
+;      offsets                 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18
+.crt:                  db      0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,0x00,0x30,0xe8,0x9c,0x0e,0x8f,0x28,0x1f,0x96,0xb9,0xa3
+.attribute             db      0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x0c,0x00,0x0f,0x08,0x00
+.graphic:              db      0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0xff
+.sequencer:            db      0x03,0x00,0x03,0x00,0x02
+.misc:                 db      0x67
+
+
+
+section .bss
+pice_current_registers:
+.crt:                  resb    VGA_CRT_REGISTERS
+.attribute:            resb    VGA_ATTRIBUTE_REGISTERS
+.graphic:              resb    VGA_GRAPHIC_REGISTERS
+.sequencer:            resb    VGA_SEQUENCER_REGISTERS
+.misc:                 resb    VGA_MISC_REGISTERS
+                       align   4
+.colormap:             resd    256
+
+;****************************************************************************
+;* pice_save_current_charset ************************************************
+;****************************************************************************
+section .text
+pice_address dd 0xc00a0000
+pice_save_current_charset:
+                       xor     dword ebx, ebx
+                       call    pice_select_read_plane
+                       mov     dword ecx, 04000h
+                       mov     dword esi, [pice_address]
+                       mov     dword edi, pice_charset_saved
+                       cld
+                       rep movsd
+                       mov     dword ebx, 00100h
+                       call    pice_select_read_plane
+                       mov     dword ecx, 04000h
+                       mov     dword esi, [pice_address]
+                       mov     dword edi, (pice_charset_saved + 010000h)
+                       cld
+                       rep movsd
+                       mov     dword ebx, 00200h
+                       call    pice_select_read_plane
+                       mov     dword ecx, 04000h
+                       mov     dword esi, [pice_address]
+                       mov     dword edi, (pice_charset_saved + 020000h)
+                       cld
+                       rep movsd
+                       mov     dword ebx, 00300h
+                       call    pice_select_read_plane
+                       mov     dword ecx, 04000h
+                       mov     dword esi, [pice_address]
+                       mov     dword edi, (pice_charset_saved + 030000h)
+                       cld
+                       rep movsd
+.end:                  ret
+
+
+
+;****************************************************************************
+;* pice_restore_current_charset ****************************************************
+;****************************************************************************
+section .text
+pice_restore_current_charset:
+                       mov     dword ebx, 00100h
+                       call    pice_select_write_plane
+                       mov     dword ecx, 04000h
+                       mov     dword esi, pice_charset_saved
+                       mov     dword edi, [pice_address]
+                       cld
+                       rep movsd
+                       mov     dword ebx, 00200h
+                       call    pice_select_write_plane
+                       mov     dword ecx, 04000h
+                       mov     dword esi, (pice_charset_saved + 010000h)
+                       mov     dword edi, [pice_address]
+                       cld
+                       rep movsd
+                       mov     dword ebx, 00400h
+                       call    pice_select_write_plane
+                       mov     dword ecx, 04000h
+                       mov     dword esi, (pice_charset_saved + 020000h)
+                       mov     dword edi, [pice_address]
+                       cld
+                       rep movsd
+                       mov     dword ebx, 00800h
+                       call    pice_select_write_plane
+                       mov     dword ecx, 04000h
+                       mov     dword esi, (pice_charset_saved + 030000h)
+                       mov     dword edi, [pice_address]
+                       cld
+                       rep movsd
+.end:                  ret
+
+;****************************************************************************
+;* pice_get_crt_registers **************************************************
+;****************************************************************************
+;* ebx=>  pointer where to store crt registers
+;****************************************************************************
+section .text
+pice_get_crt_registers:
+                       xor     dword ecx, ecx
+.loop:                 mov     dword edx, VGA_CRT_INDEX
+                       mov     byte  al, cl
+                       out     word  dx, al
+                       mov     dword edx, VGA_CRT_DATA
+                       in      byte  al, dx
+                       mov     byte  [ebx + ecx], al
+                       inc     dword ecx
+                       cmp     dword ecx, VGA_CRT_REGISTERS
+                       jb      .loop
+                       ret
+
+
+
+;****************************************************************************
+;* pice_get_attribute_registers ********************************************
+;****************************************************************************
+;* ebx=>  pointer where to store attribute registers
+;****************************************************************************
+section .text
+pice_get_attribute_registers:
+                       xor     dword ecx, ecx
+.loop:                 mov     dword edx, VGA_INPUT_STATUS
+                       in      byte  al, dx
+                       mov     dword edx, VGA_ATTRIBUTE_INDEX
+                       mov     byte  al, cl
+                       out     word  dx, al
+                       mov     dword edx, VGA_ATTRIBUTE_DATA_READ
+                       in      byte  al, dx
+                       mov     byte  [ebx + ecx], al
+                       inc     dword ecx
+                       cmp     dword ecx, VGA_ATTRIBUTE_REGISTERS
+                       jb      .loop
+                       ret
+
+
+
+;****************************************************************************
+;* pice_get_graphic_registers **********************************************
+;****************************************************************************
+;* ebx=>  pointer where to store graphics registers
+;****************************************************************************
+section .text
+pice_get_graphic_registers:
+                       xor     dword ecx, ecx
+.loop:                 mov     dword edx, VGA_GRAPHIC_INDEX
+                       mov     byte  al, cl
+                       out     word  dx, al
+                       mov     dword edx, VGA_GRAPHIC_DATA
+                       in      byte  al, dx
+                       mov     byte  [ebx + ecx], al
+                       inc     dword ecx
+                       cmp     dword ecx, VGA_GRAPHIC_REGISTERS
+                       jb      .loop
+                       ret
+
+
+
+;****************************************************************************
+;* pice_get_sequencer_registers ********************************************
+;****************************************************************************
+;* ebx=>  pointer where to store sequencer registers
+;****************************************************************************
+section .text
+pice_get_sequencer_registers:
+                       xor     dword ecx, ecx
+.loop:                 mov     dword edx, VGA_SEQUENCER_INDEX
+                       mov     byte  al, cl
+                       out     word  dx, al
+                       mov     dword edx, VGA_SEQUENCER_DATA
+                       in      byte  al, dx
+                       mov     byte  [ebx + ecx], al
+                       inc     dword ecx
+                       cmp     dword ecx, VGA_SEQUENCER_REGISTERS
+                       jb      .loop
+                       ret
+
+
+
+;****************************************************************************
+;* pice_get_misc_registers *************************************************
+;****************************************************************************
+;* ebx=>  pointer where to store misc register
+;****************************************************************************
+section .text
+pice_get_misc_registers:
+                       mov     dword edx, VGA_MISC_DATA_READ
+                       in      byte  al, dx
+                       mov     byte  [ebx], al
+                       ret
+
+
+
+;****************************************************************************
+;* pice_get_colormap *******************************************************
+;****************************************************************************
+;* ebx=>  pointer where to store colormap
+;****************************************************************************
+section .text
+pice_get_colormap:
+                       xor     dword ecx, ecx
+                       xor     dword eax, eax
+                       mov     dword edx, VGA_PEL_INDEX_READ
+                       out     word  dx, al
+                       mov     dword edx, VGA_PEL_DATA
+.loop:                 in      byte  al, dx
+                       shl     dword eax, 8
+                       in      byte  al, dx
+                       shl     dword eax, 8
+                       in      byte  al, dx
+                       mov     dword [ebx + 4 * ecx], eax
+                       inc     dword ecx
+                       test    byte  cl, cl
+                       jnz     .loop
+                       ret
+
+
+
+;****************************************************************************
+;* pice_set_crt_registers **************************************************
+;****************************************************************************
+;* ebx=>  pointer to stored crt registers
+;****************************************************************************
+section .text
+pice_set_crt_registers:
+
+                       ;deprotect CRT registers 0 - 7
+
+                       mov     dword edx, VGA_CRT_INDEX
+                       mov     byte  al, 011h
+                       out     word  dx, al
+                       mov     dword edx, VGA_CRT_DATA
+                       in      byte  al, dx
+                       and     byte  al, 07fh
+                       out     word  dx, al
+
+                       ;write to the registers
+
+                       xor     dword ecx, ecx
+.loop:                 mov     dword edx, VGA_CRT_INDEX
+                       mov     byte  al, cl
+                       out     word  dx, al
+                       mov     dword edx, VGA_CRT_DATA
+                       mov     byte  al, [ebx + ecx]
+                       out     word  dx, al
+                       inc     dword ecx
+                       cmp     dword ecx, VGA_CRT_REGISTERS
+                       jb      .loop
+                       ret
+
+
+
+;****************************************************************************
+;* pice_set_attribute_registers ********************************************
+;****************************************************************************
+;* ebx=>  pointer to stored attibute registers
+;****************************************************************************
+section .text
+pice_set_attribute_registers:
+                       xor     dword ecx, ecx
+.loop:                 mov     dword edx, VGA_INPUT_STATUS
+                       in      byte  al, dx
+                       mov     dword edx, VGA_ATTRIBUTE_INDEX
+                       mov     byte  al, cl
+                       out     word  dx, al
+                       mov     dword edx, VGA_ATTRIBUTE_DATA_WRITE
+                       mov     byte  al, [ebx + ecx]
+                       out     word  dx, al
+                       inc     dword ecx
+                       cmp     dword ecx, VGA_ATTRIBUTE_REGISTERS
+                       jb      .loop
+                       ret
+
+
+
+;****************************************************************************
+;* pice_set_graphic_registers **********************************************
+;****************************************************************************
+;* ebx=>  pointer to stored graphic registers
+;****************************************************************************
+section .text
+pice_set_graphic_registers:
+                       xor     dword ecx, ecx
+.loop:                 mov     dword edx, VGA_GRAPHIC_INDEX
+                       mov     byte  al, cl
+                       out     word  dx, al
+                       mov     dword edx, VGA_GRAPHIC_DATA
+                       mov     byte  al, [ebx + ecx]
+                       out     word  dx, al
+                       inc     dword ecx
+                       cmp     dword ecx, VGA_GRAPHIC_REGISTERS
+                       jb      .loop
+                       ret
+
+
+
+;****************************************************************************
+;* pice_set_sequencer_registers ********************************************
+;****************************************************************************
+;* ebx=>  pointer to stored sequencer registers
+;****************************************************************************
+section .text
+pice_set_sequencer_registers:
+
+                       ;synchronous reset on
+
+                       mov     dword edx, VGA_SEQUENCER_INDEX
+                       xor     dword eax, eax
+                       out     word  dx, al
+                       mov     dword edx, VGA_SEQUENCER_DATA
+                       inc     dword eax
+                       out     word  dx, al
+
+                       ;write to the registers
+
+                       mov     dword edx, VGA_SEQUENCER_INDEX
+                       out     word  dx, al
+                       mov     dword edx, VGA_SEQUENCER_DATA
+                       mov     byte  al, [ebx + 1]
+                       or      byte  al, 020h
+                       out     word  dx, al
+                       mov     dword ecx, 2
+.loop:                 mov     dword edx, VGA_SEQUENCER_INDEX
+                       mov     byte  al, cl
+                       out     word  dx, al
+                       mov     dword edx, VGA_SEQUENCER_DATA
+                       mov     byte  al, [ebx + ecx]
+                       out     word  dx, al
+                       inc     dword ecx
+                       cmp     dword ecx, VGA_SEQUENCER_REGISTERS
+                       jb      .loop
+
+                       ;synchronous reset off
+
+                       mov     dword edx, VGA_SEQUENCER_INDEX
+                       xor     dword eax, eax
+                       out     word  dx, al
+                       mov     dword edx, VGA_SEQUENCER_DATA
+                       mov     byte  al, 3
+                       out     word  dx, al
+                       ret
+
+
+
+;****************************************************************************
+;* pice_set_misc_registers *************************************************
+;****************************************************************************
+;* ebx=>  pointer to stored misc register
+;****************************************************************************
+section .text
+pice_set_misc_registers:
+                       mov     dword edx, VGA_MISC_DATA_WRITE
+                       mov     byte  al, [ebx]
+                       out     word dx, al
+                       ret
+
+
+
+;****************************************************************************
+;* pice_set_colormap *******************************************************
+;****************************************************************************
+;* ebx=>  pointer to stored colormap
+;****************************************************************************
+section .text
+pice_set_colormap:
+                       xor     dword ecx, ecx
+                       xor     dword eax, eax
+                       mov     dword edx, VGA_PEL_INDEX_WRITE
+                       out     word  dx, al
+                       mov     dword edx, VGA_PEL_DATA
+.loop:                 mov     dword eax, [ebx + 4 * ecx]
+                       rol     dword eax, 16
+                       out     word  dx, al
+                       rol     dword eax, 8
+                       out     word  dx, al
+                       rol     dword eax, 8
+                       out     word  dx, al
+                       inc     dword ecx
+                       test    byte  cl, cl
+                       jnz     .loop
+                       ret
+
+
+
+;****************************************************************************
+;* pice_screen_on **********************************************************
+;****************************************************************************
+section .text
+pice_screen_on:
+
+                       ;turn on the screen
+
+                       mov     dword edx, VGA_SEQUENCER_INDEX
+                       mov     byte  al, 1
+                       out     word  dx, al
+                       mov     dword edx, VGA_SEQUENCER_DATA
+                       in      byte  al, dx
+                       and     byte  al, 0dfh
+                       out     word  dx, al
+
+                       ;enable video output
+
+                       mov     dword edx, VGA_INPUT_STATUS
+                       in      byte  al, dx
+                       mov     dword edx, VGA_ATTRIBUTE_DATA_WRITE
+                       mov     byte  al, 020h
+                       out     word  dx, al
+                       ret
+
+;****************************************************************************
+;* pice_select_write_plane *************************************************
+;****************************************************************************
+;* bl==>  write mode
+;* bh==>  write plane
+;****************************************************************************
+section .text
+pice_select_write_plane:
+                       and     dword ebx, 00f03h
+
+                       ;enable set/reset = 0
+
+                       mov     dword edx, VGA_GRAPHIC_INDEX
+                       mov     byte  al, 1
+                       out     word  dx, al
+                       mov     dword edx, VGA_GRAPHIC_DATA
+                       xor     dword eax, eax
+                       out     word  dx, al
+
+                       ;logical operation = none, rotate = 0
+
+                       mov     dword edx, VGA_GRAPHIC_INDEX
+                       mov     byte  al, 3
+                       out     word  dx, al
+                       mov     dword edx, VGA_GRAPHIC_DATA
+                       xor     dword eax, eax
+                       out     word  dx, al
+
+                       ;select write mode
+
+                       mov     dword edx, VGA_GRAPHIC_INDEX
+                       mov     byte  al, 5
+                       out     word  dx, al
+                       mov     dword edx, VGA_GRAPHIC_DATA
+                       in      byte  al, dx
+                       and     byte  al, 0fch
+                       or      byte  al, bl
+                       out     word  dx, al
+
+                       ;bitmask = 0ffh
+
+                       mov     dword edx, VGA_GRAPHIC_INDEX
+                       mov     byte  al, 8
+                       out     word  dx, al
+                       mov     dword edx, VGA_GRAPHIC_DATA
+                       mov     byte  al, 0ffh
+                       out     word  dx, al
+
+                       ;select write plane
+
+                       mov     dword edx, VGA_SEQUENCER_INDEX
+                       mov     byte  al, 2
+                       out     word  dx, al
+                       mov     dword edx, VGA_SEQUENCER_DATA
+                       mov     byte  al, bh
+                       out     word  dx, al
+                       ret
+
+
+
+;****************************************************************************
+;* pice_select_read_plane **************************************************
+;****************************************************************************
+;* bl==>  read mode
+;* bh==>  read plane
+;****************************************************************************
+section .text
+pice_select_read_plane:
+                       and     dword ebx, 00301h
+                       shl     byte  bl, 3
+
+                       ;select read mode
+
+                       mov     dword edx, VGA_GRAPHIC_INDEX
+                       mov     byte  al, 5
+                       out     word  dx, al
+                       mov     dword edx, VGA_GRAPHIC_DATA
+                       in      byte  al, dx
+                       and     byte  al, 0f7h
+                       or      byte  al, bl
+                       out     word  dx, al
+
+                       ;select read plane
+
+                       mov     dword edx, VGA_GRAPHIC_INDEX
+                       mov     byte  al, 4
+                       out     word  dx, al
+                       mov     dword edx, VGA_GRAPHIC_DATA
+                       mov     byte  al, bh
+                       out     word  dx, al
+                       ret
+
+
+
+;****************************************************************************
+;* pice_save_current_registers **********************************************
+;****************************************************************************
+section .text
+_pice_save_current_registers:
+                       push esi
+                       push edi
+                       push ebx
+
+;                      call    pice_save_current_charset
+
+.crt:          mov     dword ebx, pice_current_registers.crt
+                       call    pice_get_crt_registers
+
+.attribute:    mov     dword ebx, pice_current_registers.attribute
+                       call    pice_get_attribute_registers
+
+.graphic:      mov     dword ebx, pice_current_registers.graphic
+                       call    pice_get_graphic_registers
+
+.sequencer:    mov     dword ebx, pice_current_registers.sequencer
+                       call    pice_get_sequencer_registers
+
+.misc:         mov     dword ebx, pice_current_registers.misc
+                       call    pice_get_misc_registers
+
+.colormap:     mov     dword ebx, pice_current_registers.colormap
+                       call    pice_get_colormap
+
+                       pop ebx
+                       pop edi
+                       pop esi
+.end:          ret
+
+;****************************************************************************
+;* pice_restore_current_registers *******************************************
+;****************************************************************************
+section .text
+_pice_restore_current_registers:
+                       push esi
+                       push edi
+                       push ebx
+
+;                      call    pice_restore_current_charset
+
+.misc:         mov     dword ebx, pice_current_registers.misc
+                       call    pice_set_misc_registers
+
+.crt:          mov     dword ebx, pice_current_registers.crt
+                       call    pice_set_crt_registers
+
+.attribute:    mov     dword ebx, pice_current_registers.attribute
+                       call    pice_set_attribute_registers
+
+.graphic:      mov     dword ebx, pice_current_registers.graphic
+                       call    pice_set_graphic_registers
+
+.sequencer:    mov     dword ebx, pice_current_registers.sequencer
+                       call    pice_set_sequencer_registers
+
+.screen_on:    call    pice_screen_on
+
+.colormap:     mov     dword ebx, pice_current_registers.colormap
+                       call    pice_set_colormap
+
+                       pop ebx
+                       pop edi
+                       pop esi
+
+.end:          ret
+
+
+;****************************************************************************
+;* pice_set_mode_3_80x50*****************************************************
+;****************************************************************************
+section .text
+_pice_set_mode_3_80x50:
+                       push esi
+                       push edi
+                       push ebx
+
+.crt:          mov     dword ebx, pice_mode3_80x50_registers.crt
+                       call    pice_set_crt_registers
+
+.attribute:    mov     dword ebx, pice_mode3_80x50_registers.attribute
+                       call    pice_set_attribute_registers
+
+.graphic:      mov     dword ebx, pice_mode3_80x50_registers.graphic
+                       call    pice_set_graphic_registers
+
+.sequencer:    mov     dword ebx, pice_mode3_80x50_registers.sequencer
+                       call    pice_set_sequencer_registers
+
+.misc:         mov     dword ebx, pice_mode3_80x50_registers.misc
+                       call    pice_set_misc_registers
+
+.screen_on:    call    pice_screen_on
+
+;.colormap:    mov     dword ebx, pice_current_registers.colormap
+;                      call    pice_set_colormap
+
+                       pop ebx
+                       pop edi
+                       pop esi
+
+.end:          ret
+
+;****************************************************************************
+;* pice_set_mode_3_80x25*****************************************************
+;****************************************************************************
+section .text
+_pice_set_mode_3_80x25:
+                       push esi
+                       push edi
+                       push ebx
+
+.crt:          mov     dword ebx, pice_mode3_80x25_registers.crt
+                       call    pice_set_crt_registers
+
+.attribute:    mov     dword ebx, pice_mode3_80x25_registers.attribute
+                       call    pice_set_attribute_registers
+
+.graphic:      mov     dword ebx, pice_mode3_80x25_registers.graphic
+                       call    pice_set_graphic_registers
+
+.sequencer:    mov     dword ebx, pice_mode3_80x25_registers.sequencer
+                       call    pice_set_sequencer_registers
+
+.misc:         mov     dword ebx, pice_mode3_80x25_registers.misc
+                       call    pice_set_misc_registers
+
+.screen_on:    call    pice_screen_on
+
+;.colormap:    mov     dword ebx, pice_current_registers.colormap
+;                      call    pice_set_colormap
+
+                       pop ebx
+                       pop edi
+                       pop esi
+
+.end:          ret
+
+;****************************************************************************
+;* uninitialized data *******************************************************
+;****************************************************************************
+section .bss
+                       alignb  4
+pice_charset_saved:    resb    040000h
+
+