diff --git a/src/ints/Makefile.am b/src/ints/Makefile.am
index 7330a855..6b6621df 100644
--- a/src/ints/Makefile.am
+++ b/src/ints/Makefile.am
@@ -3,5 +3,5 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
noinst_LIBRARIES = libints.a
libints_a_SOURCES = mouse.cpp xms.cpp xms.h ems.cpp \
int10.cpp int10.h int10_char.cpp int10_memory.cpp int10_misc.cpp int10_modes.cpp \
- int10_vesa.cpp int10_pal.cpp int10_put_pixel.cpp \
- bios.cpp bios_disk.cpp bios_keyboard.cpp
+ int10_vesa.cpp int10_pal.cpp int10_put_pixel.cpp int10_video_state.cpp \
+ bios.cpp bios_disk.cpp bios_keyboard.cpp
diff --git a/src/ints/int10.cpp b/src/ints/int10.cpp
index 33f4dd39..5d653dba 100644
--- a/src/ints/int10.cpp
+++ b/src/ints/int10.cpp
@@ -424,9 +424,29 @@ graphics_chars:
}
break;
case 0x1C: /* Video Save Area */
- if (IS_VGA_ARCH) break;
- if (reg_al==0) reg_bx = 0;
- reg_al = 0x1C;
+ if (!IS_VGA_ARCH) break;
+ switch (reg_al) {
+ case 0: {
+ Bitu ret=INT10_VideoState_GetSize(reg_cx);
+ if (ret) {
+ reg_al=0x1c;
+ reg_bx=ret;
+ } else reg_al=0;
+ }
+ break;
+ case 1:
+ if (INT10_VideoState_Save(reg_cx,RealMake(SegValue(es),reg_bx))) reg_al=0x1c;
+ else reg_al=0;
+ break;
+ case 2:
+ if (INT10_VideoState_Restore(reg_cx,RealMake(SegValue(es),reg_bx))) reg_al=0x1c;
+ else reg_al=0;
+ break;
+ default:
+ if (svgaCard==SVGA_TsengET4K) reg_ax=0;
+ else reg_al=0;
+ break;
+ }
break;
case 0x4f: /* VESA Calls */
if ((!IS_VGA_ARCH) || (svgaCard==SVGA_None)) break;
@@ -447,6 +467,30 @@ graphics_chars:
reg_al=0x4f;
reg_ah=VESA_GetSVGAMode(reg_bx);
break;
+ case 0x04: /* Save/restore state */
+ reg_al=0x4f;
+ switch (reg_dl) {
+ case 0: {
+ Bitu ret=INT10_VideoState_GetSize(reg_cx);
+ if (ret) {
+ reg_ah=0;
+ reg_bx=ret;
+ } else reg_ah=1;
+ }
+ break;
+ case 1:
+ if (INT10_VideoState_Save(reg_cx,RealMake(SegValue(es),reg_bx))) reg_ah=0;
+ else reg_ah=1;
+ break;
+ case 2:
+ if (INT10_VideoState_Restore(reg_cx,RealMake(SegValue(es),reg_bx))) reg_ah=0;
+ else reg_ah=1;
+ break;
+ default:
+ reg_ah=1;
+ break;
+ }
+ break;
case 0x05:
if (reg_bh==0) { /* Set CPU Window */
reg_ah=VESA_SetCPUWindow(reg_bl,reg_dl);
diff --git a/src/ints/int10.h b/src/ints/int10.h
index 7c9671d3..ab461176 100644
--- a/src/ints/int10.h
+++ b/src/ints/int10.h
@@ -212,3 +212,8 @@ void INT10_EGA_RIL_ReadRegisterRange(Bit8u & bl, Bit8u ch, Bit8u cl, Bit16u dx,
void INT10_EGA_RIL_WriteRegisterRange(Bit8u & bl, Bit8u ch, Bit8u cl, Bit16u dx, PhysPt dst);
void INT10_EGA_RIL_ReadRegisterSet(Bit16u cx, PhysPt tbl);
void INT10_EGA_RIL_WriteRegisterSet(Bit16u cx, PhysPt tbl);
+
+/* Video State */
+Bitu INT10_VideoState_GetSize(Bitu state);
+bool INT10_VideoState_Save(Bitu state,RealPt buffer);
+bool INT10_VideoState_Restore(Bitu state,RealPt buffer);
diff --git a/src/ints/int10_video_state.cpp b/src/ints/int10_video_state.cpp
new file mode 100644
index 00000000..0d83a902
--- /dev/null
+++ b/src/ints/int10_video_state.cpp
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2002-2007 The DOSBox Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* $Id: */
+
+#include "dosbox.h"
+#include "mem.h"
+#include "inout.h"
+#include "int10.h"
+
+Bitu INT10_VideoState_GetSize(Bitu state) {
+ // state: bit0=hardware, bit1=bios data, bit2=color regs/dac state
+ if ((state&7)==0) return 0;
+
+ Bitu size=0x20;
+ if (state&1) size+=0x46;
+ if (state&2) size+=0x3a;
+ if (state&4) size+=0x303;
+ if ((svgaCard==SVGA_S3Trio) && (state&8)) size+=0x43;
+ if (size!=0) size=(size-1)/64+1;
+ return size;
+}
+
+bool INT10_VideoState_Save(Bitu state,RealPt buffer) {
+ Bitu ct;
+ if ((state&7)==0) return false;
+
+ Bitu base_seg=RealSeg(buffer);
+ Bitu base_dest=RealOff(buffer)+0x20;
+
+ if (state&1) {
+ real_writew(base_seg,RealOff(buffer),base_dest);
+
+ Bit16u crt_reg=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
+ real_writew(base_seg,base_dest+0x40,crt_reg);
+
+ real_writeb(base_seg,base_dest+0x00,IO_ReadB(0x3c4));
+ real_writeb(base_seg,base_dest+0x01,IO_ReadB(0x3d4));
+ real_writeb(base_seg,base_dest+0x02,IO_ReadB(0x3ce));
+ IO_ReadB(crt_reg+6);
+ real_writeb(base_seg,base_dest+0x03,IO_ReadB(0x3c0));
+ real_writeb(base_seg,base_dest+0x04,IO_ReadB(0x3ca));
+
+ // sequencer
+ for (ct=1; ct<5; ct++) {
+ IO_WriteB(0x3c4,ct);
+ real_writeb(base_seg,base_dest+0x04+ct,IO_ReadB(0x3c5));
+ }
+
+ real_writeb(base_seg,base_dest+0x09,IO_ReadB(0x3cc));
+
+ // crt controller
+ for (ct=0; ct<0x19; ct++) {
+ IO_WriteB(crt_reg,ct);
+ real_writeb(base_seg,base_dest+0x0a+ct,IO_ReadB(crt_reg+1));
+ }
+
+ // attr registers
+ for (ct=0; ct<4; ct++) {
+ IO_ReadB(crt_reg+6);
+ IO_WriteB(0x3c0,0x10+ct);
+ real_writeb(base_seg,base_dest+0x33+ct,IO_ReadB(0x3c1));
+ }
+
+ // graphics registers
+ for (ct=0; ct<9; ct++) {
+ IO_WriteB(0x3ce,ct);
+ real_writeb(base_seg,base_dest+0x37+ct,IO_ReadB(0x3cf));
+ }
+
+ // save some registers
+ IO_WriteB(0x3c4,2);
+ Bit8u crtc_2=IO_ReadB(0x3c5);
+ IO_WriteB(0x3c4,4);
+ Bit8u crtc_4=IO_ReadB(0x3c5);
+ IO_WriteB(0x3ce,6);
+ Bit8u gfx_6=IO_ReadB(0x3cf);
+ IO_WriteB(0x3ce,5);
+ Bit8u gfx_5=IO_ReadB(0x3cf);
+ IO_WriteB(0x3ce,4);
+ Bit8u gfx_4=IO_ReadB(0x3cf);
+
+ // reprogram for full access to plane latches
+ IO_WriteW(0x3c4,0x0f02);
+ IO_WriteW(0x3c4,0x0704);
+ IO_WriteW(0x3ce,0x0406);
+ IO_WriteW(0x3ce,0x0105);
+ mem_writeb(0xaffff,0);
+
+ for (ct=0; ct<4; ct++) {
+ IO_WriteW(0x3ce,0x0004+ct*0x100);
+ real_writeb(base_seg,base_dest+0x42+ct,mem_readb(0xaffff));
+ }
+
+ // restore registers
+ IO_WriteW(0x3ce,0x0004|(gfx_4<<8));
+ IO_WriteW(0x3ce,0x0005|(gfx_5<<8));
+ IO_WriteW(0x3ce,0x0006|(gfx_6<<8));
+ IO_WriteW(0x3c4,0x0004|(crtc_4<<8));
+ IO_WriteW(0x3c4,0x0002|(crtc_2<<8));
+
+ for (ct=0; ct<0x10; ct++) {
+ IO_ReadB(crt_reg+6);
+ IO_WriteB(0x3c0,ct);
+ real_writeb(base_seg,base_dest+0x23+ct,IO_ReadB(0x3c1));
+ }
+ IO_WriteB(0x3c0,0x20);
+
+ base_dest+=0x46;
+ }
+
+ if (state&2) {
+ real_writew(base_seg,RealOff(buffer)+2,base_dest);
+
+ real_writeb(base_seg,base_dest+0x00,mem_readb(0x410)&0x30);
+ for (ct=0; ct<0x1e; ct++) {
+ real_writeb(base_seg,base_dest+0x01+ct,mem_readb(0x449+ct));
+ }
+ for (ct=0; ct<0x07; ct++) {
+ real_writeb(base_seg,base_dest+0x1f+ct,mem_readb(0x484+ct));
+ }
+ real_writed(base_seg,base_dest+0x26,mem_readd(0x48a));
+ real_writed(base_seg,base_dest+0x2a,mem_readd(0x14)); // int 5
+ real_writed(base_seg,base_dest+0x2e,mem_readd(0x74)); // int 1d
+ real_writed(base_seg,base_dest+0x32,mem_readd(0x7c)); // int 1f
+ real_writed(base_seg,base_dest+0x36,mem_readd(0x10c)); // int 43
+
+ base_dest+=0x3a;
+ }
+
+ if (state&4) {
+ real_writew(base_seg,RealOff(buffer)+4,base_dest);
+
+ Bit16u crt_reg=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
+
+ IO_ReadB(crt_reg+6);
+ IO_WriteB(0x3c0,0x14);
+ real_writeb(base_seg,base_dest+0x303,IO_ReadB(0x3c1));
+
+ Bitu dac_state=IO_ReadB(0x3c7)&1;
+ Bitu dac_windex=IO_ReadB(0x3c8);
+ if (dac_state!=0) dac_windex--;
+ real_writeb(base_seg,base_dest+0x000,dac_state);
+ real_writeb(base_seg,base_dest+0x001,dac_windex);
+ real_writeb(base_seg,base_dest+0x002,IO_ReadB(0x3c6));
+
+ for (ct=0; ct<0x100; ct++) {
+ IO_WriteB(0x3c7,ct);
+ real_writeb(base_seg,base_dest+0x003+ct*3+0,IO_ReadB(0x3c9));
+ real_writeb(base_seg,base_dest+0x003+ct*3+1,IO_ReadB(0x3c9));
+ real_writeb(base_seg,base_dest+0x003+ct*3+2,IO_ReadB(0x3c9));
+ }
+
+ IO_ReadB(crt_reg+6);
+ IO_WriteB(0x3c0,0x20);
+
+ base_dest+=0x303;
+ }
+
+ if ((svgaCard==SVGA_S3Trio) && (state&8)) {
+ real_writew(base_seg,RealOff(buffer)+6,base_dest);
+
+ Bit16u crt_reg=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
+
+ IO_WriteB(0x3c4,0x08);
+ Bitu seq_8=IO_ReadB(0x3c5);
+// real_writeb(base_seg,base_dest+0x00,IO_ReadB(0x3c5));
+ IO_WriteB(0x3c5,0x06); // unlock s3-specific registers
+
+ // sequencer
+ for (ct=0; ct<0x13; ct++) {
+ IO_WriteB(0x3c4,0x09+ct);
+ real_writeb(base_seg,base_dest+0x00+ct,IO_ReadB(0x3c5));
+ }
+
+ // unlock s3-specific registers
+ IO_WriteW(crt_reg,0x4838);
+ IO_WriteW(crt_reg,0xa539);
+
+ // crt controller
+ Bitu ct_dest=0x13;
+ for (ct=0; ct<0x40; ct++) {
+ if ((ct==0x4a-0x30) || (ct==0x4b-0x30)) {
+ IO_WriteB(crt_reg,0x45);
+ IO_ReadB(crt_reg+1);
+ IO_WriteB(crt_reg,0x30+ct);
+ real_writeb(base_seg,base_dest+(ct_dest++),IO_ReadB(crt_reg+1));
+ real_writeb(base_seg,base_dest+(ct_dest++),IO_ReadB(crt_reg+1));
+ real_writeb(base_seg,base_dest+(ct_dest++),IO_ReadB(crt_reg+1));
+ } else {
+ IO_WriteB(crt_reg,0x30+ct);
+ real_writeb(base_seg,base_dest+(ct_dest++),IO_ReadB(crt_reg+1));
+ }
+ }
+ }
+ return true;
+}
+
+bool INT10_VideoState_Restore(Bitu state,RealPt buffer) {
+ Bitu ct;
+ if ((state&7)==0) return false;
+
+ Bit16u base_seg=RealSeg(buffer);
+ Bit16u base_dest;
+
+ if (state&1) {
+ base_dest=real_readw(base_seg,RealOff(buffer));
+ Bit16u crt_reg=real_readw(base_seg,base_dest+0x40);
+
+ // reprogram for full access to plane latches
+ IO_WriteW(0x3c4,0x0704);
+ IO_WriteW(0x3ce,0x0406);
+ IO_WriteW(0x3ce,0x0005);
+
+ IO_WriteW(0x3c4,0x0002);
+ mem_writeb(0xaffff,real_readb(base_seg,base_dest+0x42));
+ IO_WriteW(0x3c4,0x0102);
+ mem_writeb(0xaffff,real_readb(base_seg,base_dest+0x43));
+ IO_WriteW(0x3c4,0x0202);
+ mem_writeb(0xaffff,real_readb(base_seg,base_dest+0x44));
+ IO_WriteW(0x3c4,0x0402);
+ mem_writeb(0xaffff,real_readb(base_seg,base_dest+0x45));
+ IO_WriteW(0x3c4,0x0f02);
+ mem_readb(0xaffff);
+
+ IO_WriteW(0x3c4,0x0100);
+
+ // sequencer
+ for (ct=1; ct<5; ct++) {
+ IO_WriteW(0x3c4,ct+(real_readb(base_seg,base_dest+0x04+ct)<<8));
+ }
+
+ IO_WriteB(0x3c2,real_readb(base_seg,base_dest+0x09));
+ IO_WriteW(0x3c4,0x0300);
+ IO_WriteW(crt_reg,0x0011);
+
+ // crt controller
+ for (ct=0; ct<0x19; ct++) {
+ IO_WriteW(crt_reg,ct+(real_readb(base_seg,base_dest+0x0a+ct)<<8));
+ }
+
+ IO_ReadB(crt_reg+6);
+ // attr registers
+ for (ct=0; ct<4; ct++) {
+ IO_WriteB(0x3c0,0x10+ct);
+ IO_WriteB(0x3c0,real_readb(base_seg,base_dest+0x33+ct));
+ }
+
+ // graphics registers
+ for (ct=0; ct<9; ct++) {
+ IO_WriteW(0x3ce,ct+(real_readb(base_seg,base_dest+0x37+ct)<<8));
+ }
+
+ IO_WriteB(crt_reg+6,real_readb(base_seg,base_dest+0x04));
+ IO_ReadB(crt_reg+6);
+
+ // attr registers
+ for (ct=0; ct<0x10; ct++) {
+ IO_WriteB(0x3c0,ct);
+ IO_WriteB(0x3c0,real_readb(base_seg,base_dest+0x23+ct));
+ }
+
+ IO_WriteB(0x3c4,real_readb(base_seg,base_dest+0x00));
+ IO_WriteB(0x3d4,real_readb(base_seg,base_dest+0x01));
+ IO_WriteB(0x3ce,real_readb(base_seg,base_dest+0x02));
+ IO_ReadB(crt_reg+6);
+ IO_WriteB(0x3c0,real_readb(base_seg,base_dest+0x03));
+ }
+
+ if (state&2) {
+ base_dest=real_readw(base_seg,RealOff(buffer)+2);
+
+ mem_writeb(0x410,(mem_readb(0x410)&0xcf) | real_readb(base_seg,base_dest+0x00));
+ for (ct=0; ct<0x1e; ct++) {
+ mem_writeb(0x449+ct,real_readb(base_seg,base_dest+0x01+ct));
+ }
+ for (ct=0; ct<0x07; ct++) {
+ mem_writeb(0x484+ct,real_readb(base_seg,base_dest+0x1f+ct));
+ }
+ mem_writed(0x48a,real_readd(base_seg,base_dest+0x26));
+ mem_writed(0x14,real_readd(base_seg,base_dest+0x2a)); // int 5
+ mem_writed(0x74,real_readd(base_seg,base_dest+0x2e)); // int 1d
+ mem_writed(0x7c,real_readd(base_seg,base_dest+0x32)); // int 1f
+ mem_writed(0x10c,real_readd(base_seg,base_dest+0x36)); // int 43
+ }
+
+ if (state&4) {
+ base_dest=real_readw(base_seg,RealOff(buffer)+4);
+
+ Bit16u crt_reg=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
+
+ IO_WriteB(0x3c6,real_readb(base_seg,base_dest+0x002));
+
+ for (ct=0; ct<0x100; ct++) {
+ IO_WriteB(0x3c8,ct);
+ IO_WriteB(0x3c9,real_readb(base_seg,base_dest+0x003+ct*3+0));
+ IO_WriteB(0x3c9,real_readb(base_seg,base_dest+0x003+ct*3+1));
+ IO_WriteB(0x3c9,real_readb(base_seg,base_dest+0x003+ct*3+2));
+ }
+
+ IO_ReadB(crt_reg+6);
+ IO_WriteB(0x3c0,0x14);
+ IO_WriteB(0x3c0,real_readb(base_seg,base_dest+0x303));
+
+ Bitu dac_state=real_readb(base_seg,base_dest+0x000);
+ if (dac_state==0) {
+ IO_WriteB(0x3c8,real_readb(base_seg,base_dest+0x001));
+ } else {
+ IO_WriteB(0x3c7,real_readb(base_seg,base_dest+0x001));
+ }
+ }
+
+ if ((svgaCard==SVGA_S3Trio) && (state&8)) {
+ base_dest=real_readw(base_seg,RealOff(buffer)+6);
+
+ Bit16u crt_reg=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
+
+ Bitu seq_idx=IO_ReadB(0x3c4);
+ IO_WriteB(0x3c4,0x08);
+ Bitu seq_8=IO_ReadB(0x3c5);
+// real_writeb(base_seg,base_dest+0x00,IO_ReadB(0x3c5));
+ IO_WriteB(0x3c5,0x06); // unlock s3-specific registers
+
+ // sequencer
+ for (ct=0; ct<0x13; ct++) {
+ IO_WriteW(0x3c4,(0x09+ct)+(real_readb(base_seg,base_dest+0x00+ct)<<8));
+ }
+ IO_WriteB(0x3c4,seq_idx);
+
+ Bitu crtc_idx=IO_ReadB(0x3d4);
+
+ // unlock s3-specific registers
+ IO_WriteW(crt_reg,0x4838);
+ IO_WriteW(crt_reg,0xa539);
+
+ // crt controller
+ Bitu ct_dest=0x13;
+ for (ct=0; ct<0x40; ct++) {
+ if ((ct==0x4a-0x30) || (ct==0x4b-0x30)) {
+ IO_WriteB(crt_reg,0x45);
+ IO_ReadB(crt_reg+1);
+ IO_WriteB(crt_reg,0x30+ct);
+ IO_WriteB(crt_reg,real_readb(base_seg,base_dest+(ct_dest++)));
+ } else {
+ IO_WriteW(crt_reg,(0x30+ct)+(real_readb(base_seg,base_dest+(ct_dest++))<<8));
+ }
+ }
+
+ // mmio
+/* IO_WriteB(crt_reg,0x40);
+ Bitu sysval1=IO_ReadB(crt_reg+1);
+ IO_WriteB(crt_reg+1,sysval|1);
+ IO_WriteB(crt_reg,0x53);
+ Bitu sysva2=IO_ReadB(crt_reg+1);
+ IO_WriteB(crt_reg+1,sysval2|0x10);
+
+ real_writew(0xa000,0x8128,0xffff);
+
+ IO_WriteB(crt_reg,0x40);
+ IO_WriteB(crt_reg,sysval1);
+ IO_WriteB(crt_reg,0x53);
+ IO_WriteB(crt_reg,sysval2);
+ IO_WriteB(crt_reg,crtc_idx); */
+ }
+
+ return true;
+}
diff --git a/visualc_net/dosbox.vcproj b/visualc_net/dosbox.vcproj
index 11a108f4..b2eb0668 100644
--- a/visualc_net/dosbox.vcproj
+++ b/visualc_net/dosbox.vcproj
@@ -689,6 +689,9 @@
+
+