From 9c45a245e8bde30ea7935a236464d8e0b49ca3d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Strohh=C3=A4cker?= Date: Tue, 25 Sep 2007 17:46:18 +0000 Subject: [PATCH] add video state functionality Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2996 --- src/ints/Makefile.am | 4 +- src/ints/int10.cpp | 50 ++++- src/ints/int10.h | 5 + src/ints/int10_video_state.cpp | 382 +++++++++++++++++++++++++++++++++ visualc_net/dosbox.vcproj | 3 + 5 files changed, 439 insertions(+), 5 deletions(-) create mode 100644 src/ints/int10_video_state.cpp 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 @@ + +