]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
x86 bridgeboard updates.
authorToni Wilen <twilen@winuae.net>
Fri, 4 Sep 2015 16:51:39 +0000 (19:51 +0300)
committerToni Wilen <twilen@winuae.net>
Fri, 4 Sep 2015 16:51:39 +0000 (19:51 +0300)
dosbox/cpu.cpp
dosbox/db_memory.cpp
dosbox/dosbox.h
dosbox/mem.h
dosbox/paging.h
dosbox/pic.cpp
dosbox/timer.cpp [new file with mode: 0644]
dosbox/timer.h [new file with mode: 0644]
include/x86.h
x86.cpp

index ea037e3f7195a8d0d8c6164c341d73b8eb2e9fbd..97049a0f05557dec9d5c4182cc868f6fa17e41da 100644 (file)
@@ -2170,7 +2170,7 @@ class CPU: public Module_base {
 private:
        static bool inited;
 public:
-       CPU(Section* configuration):Module_base(configuration) {
+       CPU(Section* configuration, int cpumode, int cpuarch):Module_base(configuration) {
 //             if(inited) {
 //                     Change_Config(configuration);
 //                     return;
@@ -2226,10 +2226,10 @@ public:
 #endif
                MAPPER_AddHandler(CPU_CycleDecrease,MK_f11,MMOD1,"cycledown","Dec Cycles");
                MAPPER_AddHandler(CPU_CycleIncrease,MK_f12,MMOD1,"cycleup"  ,"Inc Cycles");
-               Change_Config(configuration);   
+               Change_Config(configuration, cpumode, cpuarch); 
                CPU_JMP(false,0,0,0);                                   //Setup the first cpu core
        }
-       bool Change_Config(Section* newconfig){
+       bool Change_Config(Section* newconfig, int cpumode, int cpuarch){
                Section_prop * section=static_cast<Section_prop *>(newconfig);
                CPU_AutoDetermineMode=CPU_AUTODETERMINE_NONE;
                //CPU_CycleLeft=0;//needed ?
@@ -2320,7 +2320,15 @@ public:
                CPU_CycleUp=section->Get_int("cycleup");
                CPU_CycleDown=section->Get_int("cycledown");
                //std::string core(section->Get_string("core"));
+
                std::string core = "simple";
+               if (cpumode == 2)
+                       core = "normal";
+               else if (cpumode == 3)
+                       core = "full";
+               else if (cpumode == 4)
+                       core = "auto";
+
                cpudecoder=&CPU_Core_Normal_Run;
                if (core == "normal") {
                        cpudecoder=&CPU_Core_Normal_Run;
@@ -2357,7 +2365,21 @@ public:
 
                CPU_ArchitectureType = CPU_ARCHTYPE_MIXED;
                //std::string cputype(section->Get_string("cputype"));
+
                std::string cputype = "auto";
+               if (cpuarch == 1)
+                       cputype = "386";
+               else if (cpuarch == 2)
+                       cputype = "386_prefetch";
+               else if (cpuarch == 3)
+                       cputype = "386_slow";
+               else if (cpuarch == 4)
+                       cputype = "486_slow";
+               else if (cpuarch == 5)
+                       cputype = "486_prefetch";
+               else if (cpuarch == 6)
+                       cputype = "pentium_slow";
+
                if (cputype == "auto") {
                        CPU_ArchitectureType = CPU_ARCHTYPE_MIXED;
                } else if (cputype == "386") {
@@ -2420,8 +2442,8 @@ void CPU_ShutDown(Section* sec) {
        test = NULL;
 }
 
-void CPU_Init(Section* sec) {
-       test = new CPU(sec);
+void CPU_Init(Section* sec, int cpumode, int cpuarch) {
+       test = new CPU(sec, cpumode, cpuarch);
        sec->AddDestroyFunction(&CPU_ShutDown,true);
 }
 //initialize static members
index d5d2575024b55277aa9d770fc8f18979902bcf08..cad040803e6e37433ca01b8a129504350ad4b51a 100644 (file)
@@ -196,13 +196,21 @@ void MEM_SetPageHandler(Bitu phys_page,Bitu pages,PageHandler * handler) {
        }
 }
 
-void MEM_ResetPageHandler(Bitu phys_page, Bitu pages) {
+void MEM_ResetPageHandlerRAM(Bitu phys_page, Bitu pages) {
        for (;pages>0;pages--) {
                memory.phandlers[phys_page]=&ram_page_handler;
                phys_page++;
        }
 }
 
+void MEM_ResetPageHandlerROM(Bitu phys_page, Bitu pages)
+{
+       for (; pages>0; pages--) {
+               memory.phandlers[phys_page] = &rom_page_handler;
+               phys_page++;
+       }
+}
+
 Bitu mem_strlen(PhysPt pt) {
        Bitu x=0;
        while (x<1024) {
index e76e0c9eec99989b01da540ab11b1ab990d4ccca..a0c20b11eb383efdd8338307c02c5f281474f57e 100644 (file)
@@ -30,6 +30,8 @@ typedef Bit32u Bitu;
 typedef Bit32s Bits;
 typedef double Real64;
 
+#define C_UNALIGNED_MEMORY
+
 #define LONGTYPE(a) a##LL
 
 #define INLINE __inline
index c02262681399322acf64e18571b5f29f789bd767..885cee61fc104369c898952b3f9f64c32f39d5af 100644 (file)
@@ -57,8 +57,6 @@ MemHandle MEM_NextHandleAt(MemHandle handle,Bitu where);
        Working on big or little endian machines 
 */
 
-#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY)
-
 void bridge_mono_hit(void);
 void bridge_color_hit(void);
 extern HostPt mono_start, mono_end, color_start, color_end;
@@ -70,6 +68,8 @@ static INLINE void bridge_special_addr_check(HostPt off)
                bridge_color_hit();
 }
 
+#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY)
+
 static INLINE Bit8u host_readb(HostPt off) {
        return off[0];
 }
@@ -108,12 +108,15 @@ static INLINE Bit32u host_readd(HostPt off) {
        return *(Bit32u *)off;
 }
 static INLINE void host_writeb(HostPt off,Bit8u val) {
+       bridge_special_addr_check(off);
        *(Bit8u *)(off)=val;
 }
 static INLINE void host_writew(HostPt off,Bit16u val) {
+       bridge_special_addr_check(off);
        *(Bit16u *)(off)=val;
 }
 static INLINE void host_writed(HostPt off,Bit32u val) {
+       bridge_special_addr_check(off);
        *(Bit32u *)(off)=val;
 }
 
index f7198f8fafd2a91c04bf5d0acfb6c0c381555ba4..805e92998fb3fb3934f366f1b9e36141b524c038 100644 (file)
@@ -97,7 +97,8 @@ bool PAGING_ForcePageInit(Bitu lin_addr);
 
 void MEM_SetLFB(Bitu page, Bitu pages, PageHandler *handler, PageHandler *mmiohandler);
 void MEM_SetPageHandler(Bitu phys_page, Bitu pages, PageHandler * handler);
-void MEM_ResetPageHandler(Bitu phys_page, Bitu pages);
+void MEM_ResetPageHandlerRAM(Bitu phys_page, Bitu pages);
+void MEM_ResetPageHandlerROM(Bitu phys_page, Bitu pages);
 
 
 #ifdef _MSC_VER
index f6c1801a14edad18a261fddaefc8cf0ec90fc776..3a68d0629875d25c582f0d83168627de9f895baf 100644 (file)
@@ -25,7 +25,7 @@
 #include "cpu.h"
 #include "callback.h"
 #include "pic.h"
-//#include "timer.h"
+#include "timer.h"
 #include "setup.h"
 
 #define PIC_QUEUESIZE 512
@@ -498,7 +498,6 @@ bool PIC_RunQueue(void) {
        return true;
 }
 
-#if 0
 /* The TIMER Part */
 struct TickerBlock {
        TIMER_TickHandler handler;
@@ -548,7 +547,6 @@ void TIMER_AddTick(void) {
                ticker=nextticker;
        }
 }
-#endif
 
 void x86_pic_write(Bitu port, Bitu val)
 {
@@ -580,7 +578,7 @@ Bitu x86_pic_read(Bitu port)
 }
 
 class PIC:public Module_base{
-private:
+//private:
 //     IO_ReadHandleObject ReadHandler[4];
 //     IO_WriteHandleObject WriteHandler[4];
 public:
diff --git a/dosbox/timer.cpp b/dosbox/timer.cpp
new file mode 100644 (file)
index 0000000..9a43194
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+ *  Copyright (C) 2002-2010  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: timer.cpp,v 1.49 2009-04-10 09:53:04 c2woody Exp $ */
+
+#include <math.h>
+#include "dosbox.h"
+#include "inout.h"
+#include "pic.h"
+#include "mem.h"
+//#include "mixer.h"
+#include "timer.h"
+#include "setup.h"
+
+static INLINE void BIN2BCD(Bit16u& val) {
+       Bit16u temp=val%10 + (((val/10)%10)<<4)+ (((val/100)%10)<<8) + (((val/1000)%10)<<12);
+       val=temp;
+}
+
+static INLINE void BCD2BIN(Bit16u& val) {
+       Bit16u temp= (val&0x0f) +((val>>4)&0x0f) *10 +((val>>8)&0x0f) *100 +((val>>12)&0x0f) *1000;
+       val=temp;
+}
+
+struct PIT_Block {
+       Bitu cntr;
+       float delay;
+       double start;
+
+       Bit16u read_latch;
+       Bit16u write_latch;
+
+       Bit8u mode;
+       Bit8u latch_mode;
+       Bit8u read_state;
+       Bit8u write_state;
+
+       bool bcd;
+       bool go_read_latch;
+       bool new_mode;
+       bool counterstatus_set;
+       bool counting;
+       bool update_count;
+};
+
+static PIT_Block pit[3];
+static bool gate2;
+
+static Bit8u latched_timerstatus;
+// the timer status can not be overwritten until it is read or the timer was 
+// reprogrammed.
+static bool latched_timerstatus_locked;
+
+static void PIT0_Event(Bitu /*val*/) {
+       PIC_ActivateIRQ(0);
+       if (pit[0].mode != 0) {
+               pit[0].start += pit[0].delay;
+
+               if (GCC_UNLIKELY(pit[0].update_count)) {
+                       pit[0].delay=(1000.0f/((float)PIT_TICK_RATE/(float)pit[0].cntr));
+                       pit[0].update_count=false;
+               }
+               PIC_AddEvent(PIT0_Event,pit[0].delay);
+       }
+}
+
+static bool counter_output(Bitu counter) {
+       PIT_Block * p=&pit[counter];
+       double index=PIC_FullIndex()-p->start;
+       switch (p->mode) {
+       case 0:
+               if (p->new_mode) return false;
+               if (index>p->delay) return true;
+               else return false;
+               break;
+       case 2:
+               if (p->new_mode) return true;
+               index=fmod(index,(double)p->delay);
+               return index>0;
+       case 3:
+               if (p->new_mode) return true;
+               index=fmod(index,(double)p->delay);
+               return index*2<p->delay;
+       case 4:
+               //Only low on terminal count
+               // if(fmod(index,(double)p->delay) == 0) return false; //Maybe take one rate tick in consideration
+               //Easiest solution is to report always high (Space marines uses this mode)
+               return true;
+       default:
+               LOG(LOG_PIT,LOG_ERROR)("Illegal Mode %d for reading output",p->mode);
+               return true;
+       }
+}
+static void status_latch(Bitu counter) {
+       // the timer status can not be overwritten until it is read or the timer was 
+       // reprogrammed.
+       if(!latched_timerstatus_locked) {
+               PIT_Block * p=&pit[counter];
+               latched_timerstatus=0;
+               // Timer Status Word
+               // 0: BCD 
+               // 1-3: Timer mode
+               // 4-5: read/load mode
+               // 6: "NULL" - this is 0 if "the counter value is in the counter" ;)
+               // should rarely be 1 (i.e. on exotic modes)
+               // 7: OUT - the logic level on the Timer output pin
+               if(p->bcd)latched_timerstatus|=0x1;
+               latched_timerstatus|=((p->mode&7)<<1);
+               if((p->read_state==0)||(p->read_state==3)) latched_timerstatus|=0x30;
+               else if(p->read_state==1) latched_timerstatus|=0x10;
+               else if(p->read_state==2) latched_timerstatus|=0x20;
+               if(counter_output(counter)) latched_timerstatus|=0x80;
+               if(p->new_mode) latched_timerstatus|=0x40;
+               // The first thing that is being read from this counter now is the
+               // counter status.
+               p->counterstatus_set=true;
+               latched_timerstatus_locked=true;
+       }
+}
+static void counter_latch(Bitu counter) {
+       /* Fill the read_latch of the selected counter with current count */
+       PIT_Block * p=&pit[counter];
+       p->go_read_latch=false;
+
+       //If gate2 is disabled don't update the read_latch
+       if(counter == 2 && !gate2 && p->mode !=1) return;
+
+       double index=PIC_FullIndex()-p->start;
+       switch (p->mode) {
+       case 4:         /* Software Triggered Strobe */
+       case 0:         /* Interrupt on Terminal Count */
+               /* Counter keeps on counting after passing terminal count */
+               if (index>p->delay) {
+                       index-=p->delay;
+                       if(p->bcd) {
+                               index = fmod(index,(1000.0/PIT_TICK_RATE)*10000.0);
+                               p->read_latch = (Bit16u)(9999-index*(PIT_TICK_RATE/1000.0));
+                       } else {
+                               index = fmod(index,(1000.0/PIT_TICK_RATE)*(double)0x10000);
+                               p->read_latch = (Bit16u)(0xffff-index*(PIT_TICK_RATE/1000.0));
+                       }
+               } else {
+                       p->read_latch=(Bit16u)(p->cntr-index*(PIT_TICK_RATE/1000.0));
+               }
+               break;
+       case 1: // countdown
+               if(p->counting) {
+                       if (index>p->delay) { // has timed out
+                               p->read_latch = 0xffff; //unconfirmed
+                       } else {
+                               p->read_latch=(Bit16u)(p->cntr-index*(PIT_TICK_RATE/1000.0));
+                       }
+               }
+               break;
+       case 2:         /* Rate Generator */
+               index=fmod(index,(double)p->delay);
+               p->read_latch=(Bit16u)(p->cntr - (index/p->delay)*p->cntr);
+               break;
+       case 3:         /* Square Wave Rate Generator */
+               index=fmod(index,(double)p->delay);
+               index*=2;
+               if (index>p->delay) index-=p->delay;
+               p->read_latch=(Bit16u)(p->cntr - (index/p->delay)*p->cntr);
+               // In mode 3 it never returns odd numbers LSB (if odd number is written 1 will be
+               // subtracted on first clock and then always 2)
+               // fixes "Corncob 3D"
+               p->read_latch&=0xfffe;
+               break;
+       default:
+               LOG(LOG_PIT,LOG_ERROR)("Illegal Mode %d for reading counter %d",p->mode,counter);
+               p->read_latch=0xffff;
+               break;
+       }
+}
+
+
+static void write_latch(Bitu port,Bitu val,Bitu /*iolen*/) {
+//LOG(LOG_PIT,LOG_ERROR)("port %X write:%X state:%X",port,val,pit[port-0x40].write_state);
+       Bitu counter=port-0x40;
+       PIT_Block * p=&pit[counter];
+       if(p->bcd == true) BIN2BCD(p->write_latch);
+   
+       switch (p->write_state) {
+               case 0:
+                       p->write_latch = p->write_latch | ((val & 0xff) << 8);
+                       p->write_state = 3;
+                       break;
+               case 3:
+                       p->write_latch = val & 0xff;
+                       p->write_state = 0;
+                       break;
+               case 1:
+                       p->write_latch = val & 0xff;
+                       break;
+               case 2:
+                       p->write_latch = (val & 0xff) << 8;
+               break;
+       }
+       if (p->bcd==true) BCD2BIN(p->write_latch);
+       if (p->write_state != 0) {
+               if (p->write_latch == 0) {
+                       if (p->bcd == false) p->cntr = 0x10000;
+                       else p->cntr=9999;
+               } else p->cntr = p->write_latch;
+
+               if ((!p->new_mode) && (p->mode == 2) && (counter == 0)) {
+                       // In mode 2 writing another value has no direct effect on the count
+                       // until the old one has run out. This might apply to other modes too.
+                       // This is not fixed for PIT2 yet!!
+                       p->update_count=true;
+                       return;
+               }
+               p->start=PIC_FullIndex();
+               p->delay=(1000.0f/((float)PIT_TICK_RATE/(float)p->cntr));
+
+               switch (counter) {
+               case 0x00:                      /* Timer hooked to IRQ 0 */
+                       if (p->new_mode || p->mode == 0 ) {
+                               if(p->mode==0) PIC_RemoveEvents(PIT0_Event); // DoWhackaDo demo
+                               PIC_AddEvent(PIT0_Event,p->delay);
+                       } else LOG(LOG_PIT,LOG_NORMAL)("PIT 0 Timer set without new control word");
+                       LOG(LOG_PIT,LOG_NORMAL)("PIT 0 Timer at %.4f Hz mode %d",1000.0/p->delay,p->mode);
+                       break;
+               case 0x02:                      /* Timer hooked to PC-Speaker */
+//                     LOG(LOG_PIT,"PIT 2 Timer at %.3g Hz mode %d",PIT_TICK_RATE/(double)p->cntr,p->mode);
+//                     PCSPEAKER_SetCounter(p->cntr,p->mode);
+                       break;
+               default:
+                       LOG(LOG_PIT,LOG_ERROR)("PIT:Illegal timer selected for writing");
+               }
+               p->new_mode=false;
+    }
+}
+
+static Bitu read_latch(Bitu port,Bitu /*iolen*/) {
+//LOG(LOG_PIT,LOG_ERROR)("port read %X",port);
+       Bit32u counter=port-0x40;
+       Bit8u ret=0;
+       if(GCC_UNLIKELY(pit[counter].counterstatus_set)){
+               pit[counter].counterstatus_set = false;
+               latched_timerstatus_locked = false;
+               ret = latched_timerstatus;
+       } else {
+               if (pit[counter].go_read_latch == true) 
+                       counter_latch(counter);
+
+               if( pit[counter].bcd == true) BIN2BCD(pit[counter].read_latch);
+
+               switch (pit[counter].read_state) {
+               case 0: /* read MSB & return to state 3 */
+                       ret=(pit[counter].read_latch >> 8) & 0xff;
+                       pit[counter].read_state = 3;
+                       pit[counter].go_read_latch = true;
+                       break;
+               case 3: /* read LSB followed by MSB */
+                       ret = pit[counter].read_latch & 0xff;
+                       pit[counter].read_state = 0;
+                       break;
+               case 1: /* read LSB */
+                       ret = pit[counter].read_latch & 0xff;
+                       pit[counter].go_read_latch = true;
+                       break;
+               case 2: /* read MSB */
+                       ret = (pit[counter].read_latch >> 8) & 0xff;
+                       pit[counter].go_read_latch = true;
+                       break;
+               default:
+                       E_Exit("Timer.cpp: error in readlatch");
+                       break;
+               }
+               if( pit[counter].bcd == true) BCD2BIN(pit[counter].read_latch);
+       }
+       return ret;
+}
+
+static void write_p43(Bitu /*port*/,Bitu val,Bitu /*iolen*/) {
+//LOG(LOG_PIT,LOG_ERROR)("port 43 %X",val);
+       Bitu latch=(val >> 6) & 0x03;
+       switch (latch) {
+       case 0:
+       case 1:
+       case 2:
+               if ((val & 0x30) == 0) {
+                       /* Counter latch command */
+                       counter_latch(latch);
+               } else {
+                       pit[latch].bcd = (val&1)>0;   
+                       if (val & 1) {
+                               if(pit[latch].cntr>=9999) pit[latch].cntr=9999;
+                       }
+
+                       // Timer is being reprogrammed, unlock the status
+                       if(pit[latch].counterstatus_set) {
+                               pit[latch].counterstatus_set=false;
+                               latched_timerstatus_locked=false;
+                       }
+                       pit[latch].update_count = false;
+                       pit[latch].counting = false;
+                       pit[latch].read_state  = (val >> 4) & 0x03;
+                       pit[latch].write_state = (val >> 4) & 0x03;
+                       Bit8u mode             = (val >> 1) & 0x07;
+                       if (mode > 5)
+                               mode -= 4; //6,7 become 2 and 3
+
+                       /* Don't set it directly so counter_output uses the old mode */
+                       /* That's theory. It breaks panic. So set it here again */
+                       if(!pit[latch].mode) pit[latch].mode     = mode;
+
+                       /* If the line goes from low to up => generate irq. 
+                        *      ( BUT needs to stay up until acknowlegded by the cpu!!! therefore: )
+                        * If the line goes to low => disable irq.
+                        * Mode 0 starts with a low line. (so always disable irq)
+                        * Mode 2,3 start with a high line.
+                        * counter_output tells if the current counter is high or low 
+                        * So actually a mode 2 timer enables and disables irq al the time. (not handled) */
+
+                       if (latch == 0) {
+                               PIC_RemoveEvents(PIT0_Event);
+                               if (!counter_output(0) && mode) {
+                                       PIC_ActivateIRQ(0);
+                                       //Don't raise instantaniously. (Origamo)
+                                       if(CPU_Cycles < 25) CPU_Cycles = 25;
+                               }
+                               if(!mode)
+                                       PIC_DeActivateIRQ(0);
+                       }
+                       pit[latch].new_mode = true;
+                       pit[latch].mode     = mode; //Set the correct mode (here)
+               }
+               break;
+    case 3:
+               if ((val & 0x20)==0) {  /* Latch multiple pit counters */
+                       if (val & 0x02) counter_latch(0);
+                       if (val & 0x04) counter_latch(1);
+                       if (val & 0x08) counter_latch(2);
+               }
+               // status and values can be latched simultaneously
+               if ((val & 0x10)==0) {  /* Latch status words */
+                       // but only 1 status can be latched simultaneously
+                       if (val & 0x02) status_latch(0);
+                       else if (val & 0x04) status_latch(1);
+                       else if (val & 0x08) status_latch(2);
+               }
+               break;
+       }
+}
+
+void TIMER_SetGate2(bool in) {
+       //No changes if gate doesn't change
+       if(gate2 == in) return;
+       Bit8u & mode=pit[2].mode;
+       switch(mode) {
+       case 0:
+               if(in) pit[2].start = PIC_FullIndex();
+               else {
+                       //Fill readlatch and store it.
+                       counter_latch(2);
+                       pit[2].cntr = pit[2].read_latch;
+               }
+               break;
+       case 1:
+               // gate 1 on: reload counter; off: nothing
+               if(in) {
+                       pit[2].counting = true;
+                       pit[2].start = PIC_FullIndex();
+               }
+               break;
+       case 2:
+       case 3:
+               //If gate is enabled restart counting. If disable store the current read_latch
+               if(in) pit[2].start = PIC_FullIndex();
+               else counter_latch(2);
+               break;
+       case 4:
+       case 5:
+               LOG(LOG_MISC,LOG_WARN)("unsupported gate 2 mode %x",mode);
+               break;
+       }
+       gate2 = in; //Set it here so the counter_latch above works
+}
+
+void x86_timer_write(Bitu port, Bitu val)
+{
+       switch (port)
+       {
+               case 0x40:
+               case 0x41:
+               case 0x42:
+               write_latch(port, val, 1);
+               break;
+               case 0x43:
+               write_p43(port, val, 1);
+               break;
+       }
+}
+Bitu x86_timer_read(Bitu port)
+{
+       switch (port)
+       {
+               case 0x40:
+               case 0x41:
+               case 0x42:
+               return read_latch(port, 1);
+               break;
+       }
+       return 0;
+}
+
+class TIMER:public Module_base{
+//private:
+//     IO_ReadHandleObject ReadHandler[4];
+//     IO_WriteHandleObject WriteHandler[4];
+public:
+       TIMER(Section* configuration):Module_base(configuration){
+#if 0
+               WriteHandler[0].Install(0x40,write_latch,IO_MB);
+       //      WriteHandler[1].Install(0x41,write_latch,IO_MB);
+               WriteHandler[2].Install(0x42,write_latch,IO_MB);
+               WriteHandler[3].Install(0x43,write_p43,IO_MB);
+               ReadHandler[0].Install(0x40,read_latch,IO_MB);
+               ReadHandler[1].Install(0x41,read_latch,IO_MB);
+               ReadHandler[2].Install(0x42,read_latch,IO_MB);
+#endif
+               /* Setup Timer 0 */
+               pit[0].cntr=0x10000;
+               pit[0].write_state = 3;
+               pit[0].read_state = 3;
+               pit[0].read_latch=0;
+               pit[0].write_latch=0;
+               pit[0].mode=3;
+               pit[0].bcd = false;
+               pit[0].go_read_latch = true;
+               pit[0].counterstatus_set = false;
+               pit[0].update_count = false;
+       
+               pit[1].bcd = false;
+               pit[1].write_state = 1;
+               pit[1].read_state = 1;
+               pit[1].go_read_latch = true;
+               pit[1].cntr = 18;
+               pit[1].mode = 2;
+               pit[1].write_state = 3;
+               pit[1].counterstatus_set = false;
+       
+               pit[2].read_latch=1320; /* MadTv1 */
+               pit[2].write_state = 3; /* Chuck Yeager */
+               pit[2].read_state = 3;
+               pit[2].mode=3;
+               pit[2].bcd=false;   
+               pit[2].cntr=1320;
+               pit[2].go_read_latch=true;
+               pit[2].counterstatus_set = false;
+               pit[2].counting = false;
+       
+               pit[0].delay=(1000.0f/((float)PIT_TICK_RATE/(float)pit[0].cntr));
+               pit[1].delay=(1000.0f/((float)PIT_TICK_RATE/(float)pit[1].cntr));
+               pit[2].delay=(1000.0f/((float)PIT_TICK_RATE/(float)pit[2].cntr));
+
+               latched_timerstatus_locked=false;
+               gate2 = false;
+               PIC_AddEvent(PIT0_Event,pit[0].delay);
+       }
+       ~TIMER(){
+               PIC_RemoveEvents(PIT0_Event);
+       }
+};
+static TIMER* test;
+
+void TIMER_Destroy(Section*){
+       delete test;
+}
+void TIMER_Init(Section* sec) {
+       test = new TIMER(sec);
+       sec->AddDestroyFunction(&TIMER_Destroy);
+}
diff --git a/dosbox/timer.h b/dosbox/timer.h
new file mode 100644 (file)
index 0000000..2826809
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  Copyright (C) 2002-2010  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.
+ */
+
+#ifndef DOSBOX_TIMER_H
+#define DOSBOX_TIMER_H
+
+/* underlying clock rate in HZ */
+//#include <SDL.h>
+
+#define PIT_TICK_RATE 1193182
+
+//#define GetTicks() SDL_GetTicks()
+
+typedef void (*TIMER_TickHandler)(void);
+
+/* Register a function that gets called everytime if 1 or more ticks pass */
+void TIMER_AddTickHandler(TIMER_TickHandler handler);
+void TIMER_DelTickHandler(TIMER_TickHandler handler);
+
+/* This will add 1 milliscond to all timers */
+void TIMER_AddTick(void);
+
+#endif
index 0669a50718a15ee26539b857225eeca19e41af9c..8ec53ac835ac8d4de37619fa8ce49e0bc168752b 100644 (file)
@@ -8,6 +8,7 @@ void x86_bridge_hsync(void);
 void x86_bridge_reset(void);
 void x86_bridge_free(void);
 void x86_bridge_rethink(void);
+void x86_bridge_sync_change(void);
 
 #define X86_STATE_INACTIVE 0
 #define X86_STATE_STOP 1
diff --git a/x86.cpp b/x86.cpp
index 5616e1b473460fe5a9519c7aacc87930a5e59025..320f7158f6df3b2962926ff8b9563ef1aca15593 100644 (file)
--- a/x86.cpp
+++ b/x86.cpp
@@ -42,6 +42,8 @@
 #include "dosbox/paging.h"
 #include "dosbox/setup.h"
 #include "dosbox/cpu.h"
+#include "dosbox/pic.h"
+#include "dosbox/timer.h"
 typedef Bits(CPU_Decoder)(void);
 extern CPU_Decoder *cpudecoder;
 extern Bit32s CPU_Cycles;
@@ -62,14 +64,14 @@ void intcall86(uint8_t intnum);
 void x86_doirq(uint8_t irqnum);
 
 static frame_time_t last_cycles;
-#define DEFAULT_X86_INSTRUCTION_COUNT 40
+#define DEFAULT_X86_INSTRUCTION_COUNT 120
 static int x86_instruction_count;
 static bool x86_turbo_allowed;
 static bool x86_turbo_enabled;
 bool x86_turbo_on;
 bool x86_cpu_active;
 
-void CPU_Init(Section*);
+void CPU_Init(Section*, int, int);
 void CPU_ShutDown(Section*);
 void CPU_JMP(bool use32, Bitu selector, Bitu offset, Bitu oldeip);
 void PAGING_Init(Section * sec);
@@ -79,6 +81,8 @@ void CMOS_Init(Section* sec, int);
 void CMOS_Destroy(Section* sec);
 void PIC_Init(Section* sec);
 void PIC_Destroy(Section* sec);
+void TIMER_Destroy(Section*);
+void TIMER_Init(Section* sec);
 static Section_prop *dosbox_sec;
 Bitu x86_in_keyboard(Bitu port);
 void x86_out_keyboard(Bitu port, Bitu val);
@@ -87,6 +91,8 @@ void cmos_writereg(Bitu port, Bitu val, Bitu iolen);
 Bitu cmos_readreg(Bitu port, Bitu iolen);
 void x86_pic_write(Bitu port, Bitu val);
 Bitu x86_pic_read(Bitu port);
+void x86_timer_write(Bitu port, Bitu val);
+Bitu x86_timer_read(Bitu port);
 void PIC_ActivateIRQ(Bitu irq);
 void PIC_DeActivateIRQ(Bitu irq);
 void PIC_runIRQs(void);
@@ -94,6 +100,8 @@ void KEYBOARD_AddBuffer(Bit8u data);
 void FPU_Init(Section*);
 Bit8u *x86_cmos_regs(Bit8u *regs);
 void MEM_SetVGAHandler(void);
+Bit32s ticksDone;
+Bit32u ticksScheduled;
 HostPt mono_start, mono_end, color_start, color_end;
 int x86_memsize;
 int x86_biosstart;
@@ -112,6 +120,7 @@ struct x86_bridge
        uaecptr baseaddress;
        int pc_maxram;
        uae_u8 *pc_ram;
+       uae_u8 *pc_rom;
        uae_u8 *io_ports;
        uae_u8 *amiga_io;
        bool x86_reset;
@@ -123,11 +132,17 @@ struct x86_bridge
        int bios_size;
        int settings;
        int dosbox_cpu;
+       int dosbox_cpu_arch;
        bool x86_reset_requested;
        struct zfile *cmosfile;
        uae_u8 cmosregs[3 * 0x40];
+       uae_u8 vlsi_regs[0x100];
+       int a2386_default_video;
        int cmossize;
        int scamp_idx1, scamp_idx2;
+       uae_u8 rombank[1024 * 1024 / 4096];
+       float dosbox_vpos_tick;
+       float dosbox_tick_vpos_cnt;
        struct romconfig *rc;
 };
 static int x86_found;
@@ -170,8 +185,10 @@ void x86_init_reset(void)
 
 static void reset_dosbox_cpu(void)
 {
+       struct x86_bridge *xb = bridges[0];
+
        CPU_ShutDown(dosbox_sec);
-       CPU_Init(dosbox_sec);
+       CPU_Init(dosbox_sec, xb->dosbox_cpu, xb->dosbox_cpu_arch);
        CPU_JMP(false, 0xffff, 0, 0);
 }
 
@@ -193,10 +210,27 @@ uint8_t x86_get_jumpers(void)
        struct x86_bridge *xb = bridges[0];
        uint8_t v = 0;
 
-       if (!(xb->settings & (1 << 14)))
-               v |= 0x40;
-       if (!(xb->settings & (1 << 15)))
-               v |= 0x80; // key lock off
+       if (xb->type >= TYPE_2286) {
+               if (xb->pc_maxbaseram > 512 * 1024)
+                       v |= 0x20;
+       }
+
+       if (xb->type == TYPE_2386) {
+               // A2386 = software controlled
+               if (xb->a2386_default_video)
+                       v |= 0x40;
+       } else {
+               // Others have default video jumper
+               if (!(xb->settings & (1 << 14))) {
+                       // default video mde, 0 = cga, 1 = mda
+                       v |= 0x40;
+               }
+       }
+
+       if (!(xb->settings & (1 << 15))) {
+               // key lock state: 0 = on, 1 = off
+               v |= 0x80;
+       }
        return v;
 }
 
@@ -300,6 +334,10 @@ static uae_u8 x86_bridge_put_io(struct x86_bridge *xb, uaecptr addr, uae_u8 v)
                break;
                case IO_A2386_CONFIG:
                write_log(_T("A2386 CONFIG BYTE %02x\n"), v);
+               if (v == 8 || v == 9) {
+                       xb->a2386_default_video = v & 1;
+                       write_log(_T("A2386 Default mode = %s\n"), xb->a2386_default_video ? _T("MDA") : _T("CGA"));
+               }
                break;
 
                default:
@@ -1050,6 +1088,11 @@ static int floppy_selected(void)
 
 static bool floppy_valid_rate(struct floppy_reserved *fr)
 {
+       struct x86_bridge *xb = bridges[0];
+       // A2386 BIOS sets 720k data rate for both 720k and 1.4M drives
+       // probably because it thinks Amiga half-speed drive is connected?
+       if (xb->type == TYPE_2386 && fr->rate == 0 && floppy_rate == 2)
+               return true;
        return fr->rate == floppy_rate || floppy_rate < 0;
 }
 
@@ -1384,7 +1427,7 @@ static void outfloppy(struct x86_bridge *xb, int portnum, uae_u8 v)
                        floppy_delay_hsync = 20;
                }
 #if FLOPPY_IO_DEBUG
-               write_log(_T("DPC: Motormask %02x sel=%d dmaen=%d reset=%d\n"), (v >> 4) & 15, v & 3, (v & 8) ? 1 : 0, (v & 4) ? 0 : 1);
+               write_log(_T("DPC=%02x: Motormask %02x sel=%d dmaen=%d reset=%d\n"), v, (v >> 4) & 15, v & 3, (v & 8) ? 1 : 0, (v & 4) ? 0 : 1);
 #endif
 #ifdef DRIVESOUND
                for (int i = 0; i < 2; i++) {
@@ -1454,11 +1497,15 @@ static void outfloppy(struct x86_bridge *xb, int portnum, uae_u8 v)
                        floppy_rate = -1;
                }
                break;
+               default:
+               write_log(_T("Unknown FDC %04x write %02x\n"), portnum, v);
+               break;
        }
 #if FLOPPY_IO_DEBUG
        write_log(_T("out floppy port %04x %02x\n"), portnum, v);
 #endif
 }
+
 static uae_u8 infloppy(struct x86_bridge *xb, int portnum)
 {
        uae_u8 v = 0;
@@ -1501,6 +1548,9 @@ static uae_u8 infloppy(struct x86_bridge *xb, int portnum)
                                v = 0x80;
                }
                break;
+               default:
+               write_log(_T("Unknown FDC %04x read\n"), portnum);
+               break;
        }
 #if FLOPPY_IO_DEBUG
        write_log(_T("in  floppy port %04x %02x\n"), portnum, v);
@@ -1538,13 +1588,14 @@ static void set_pc_address_access(struct x86_bridge *xb, uaecptr addr)
 
 static void set_pc_io_access(struct x86_bridge *xb, uaecptr portnum, bool write)
 {
+       uae_u8 mode_register = xb->amiga_io[IO_MODE_REGISTER];
        if (write && portnum >= 0x3b0 && portnum < 0x3bf) {
                // mono crt
-               if (xb->amiga_io[IO_MODE_REGISTER] & 8)
+               if (mode_register & 8)
                        set_interrupt(xb, 2);
        } else if (write && portnum >= 0x3d0 && portnum < 0x3df) {
                // color crt
-               if (xb->amiga_io[IO_MODE_REGISTER] & 16)
+               if (mode_register & 16)
                        set_interrupt(xb, 3);
        } else if (portnum >= 0x37a && portnum < 0x37b) {
                // LPT1
@@ -1573,6 +1624,76 @@ static bool is_port_enabled(struct x86_bridge *xb, uint16_t portnum)
        return true;
 }
 
+static uae_u8 vlsi_in(struct x86_bridge *xb, int portnum)
+{
+       uae_u8 v = 0;
+       switch(portnum)
+       {
+               case 0xed:
+               v = xb->vlsi_regs[xb->scamp_idx2];
+               break;
+       }
+       //write_log(_T("VLSI_IN %02x = %02x\n"), portnum, v);
+       return v;
+}
+
+static void vlsi_reg_out(struct x86_bridge *xb, int reg, uae_u8 v)
+{
+       uae_u32 shadow_start = 0;
+       uae_u32 shadow_size = 0;
+
+       switch(reg)
+       {
+               case 0x1d:
+               x86_cmos_bank = (v & 0x20) ? 1 : 0;
+               break;
+               case 0x0e: // ABAX
+               shadow_size = 0x8000;
+               shadow_start = 0xa0000;
+               break;
+               case 0x0f: // CAXS
+               shadow_size = 0x4000;
+               shadow_start = 0xc0000;
+               break;
+               case 0x10: // DAXS
+               shadow_size = 0x4000;
+               shadow_start = 0xd0000;
+               break;
+               case 0x11: // FEAXS
+               shadow_size = 0x4000;
+               shadow_start = 0xe0000;
+               break;
+       }
+       if (shadow_size) {
+               for (int i = 0; i < 4; i++) {
+                       int state = (v >> (i * 2)) & 3;
+                       write_log(_T("%06x - %06x : shadow status=%d\n"), shadow_start, shadow_start + shadow_size - 1, state);
+                       shadow_start += shadow_size;
+               }
+
+       }
+}
+
+
+static void vlsi_out(struct x86_bridge *xb, int portnum, uae_u8 v)
+{
+       switch (portnum)
+       {
+               case 0xe8:
+               xb->scamp_idx1 = v;
+               break;
+               case 0xec:
+               xb->scamp_idx2 = v;
+               break;
+               case 0xed:
+               xb->vlsi_regs[xb->scamp_idx2] = v;
+               vlsi_reg_out(xb, xb->scamp_idx2, v);
+               break;
+       }
+       //write_log(_T("VLSI_OUT %02x = %02x\n"), portnum, v);
+}
+
+
 void portout(uint16_t portnum, uint8_t v)
 {
        struct x86_bridge *xb = bridges[0];
@@ -1605,7 +1726,10 @@ void portout(uint16_t portnum, uint8_t v)
                case 0x41:
                case 0x42:
                case 0x43:
-               out8253(portnum, v);
+               if (xb->dosbox_cpu)
+                       x86_timer_write(portnum, v);
+               else
+                       out8253(portnum, v);
                break;
                case 0x80:
                case 0x81:
@@ -1902,16 +2026,25 @@ void portout(uint16_t portnum, uint8_t v)
 
                // A2386SX only
                case 0xe8:
-               xb->scamp_idx1 = v;
-               break;
+               case 0xe9:
+               case 0xea:
+               case 0xeb:
                case 0xec:
-               xb->scamp_idx2 = v;
-               break;
                case 0xed:
-               write_log(_T("VL82C107 %02x = %02x\n"), xb->scamp_idx2, v);
-               if (xb->scamp_idx2 == 0x1d) {
-                       x86_cmos_bank = (v & 0x20) ? 1 : 0;
-               }
+               case 0xee:
+               case 0xef:
+               case 0xf0:
+               case 0xf1:
+               case 0xf4:
+               case 0xf5:
+               case 0xf8:
+               case 0xf9:
+               case 0xfa:
+               case 0xfb:
+               case 0xfc:
+               case 0xfe:
+               if (xb->type >= TYPE_2386)
+                       vlsi_out(xb, portnum, v);
                break;
 
                // floppy
@@ -1921,7 +2054,6 @@ void portout(uint16_t portnum, uint8_t v)
                case 0x3f3:
                case 0x3f4:
                case 0x3f5:
-               case 0x3f6:
                case 0x3f7:
                outfloppy(xb, portnum, v);
                break;
@@ -1935,6 +2067,7 @@ void portout(uint16_t portnum, uint8_t v)
                case 0x175:
                case 0x176:
                case 0x177:
+               case 0x376:
                x86_ide_hd_put(portnum, v, 0);
                break;
                // at ide 0
@@ -1946,6 +2079,7 @@ void portout(uint16_t portnum, uint8_t v)
                case 0x1f5:
                case 0x1f6:
                case 0x1f7:
+               case 0x3f6:
                x86_ide_hd_put(portnum, v, 0);
                break;
 
@@ -2020,8 +2154,8 @@ static void portout32(uint16_t portnum, uint32_t value)
                case 0x170:
                case 0x1f0:
                case 0x300:
-               x86_ide_hd_put(portnum, value >> 16, 1);
                x86_ide_hd_put(portnum, value, 1);
+               x86_ide_hd_put(portnum, value >> 16, 1);
                break;
                default:
                write_log(_T("portout32 %08x %08x\n"), portnum, value);
@@ -2062,7 +2196,10 @@ uint8_t portin(uint16_t portnum)
                case 0x41:
                case 0x42:
                case 0x43:
-               v = in8253(portnum);
+               if (xb->dosbox_cpu)
+                       v = x86_timer_read(portnum);
+               else
+                       v = in8253(portnum);
                break;
 
                case 0x80:
@@ -2317,6 +2454,29 @@ uint8_t portin(uint16_t portnum)
                }
                break;
 
+               // A2386SX only
+               case 0xe8:
+               case 0xe9:
+               case 0xea:
+               case 0xeb:
+               case 0xec:
+               case 0xed:
+               case 0xee:
+               case 0xef:
+               case 0xf0:
+               case 0xf1:
+               case 0xf4:
+               case 0xf5:
+               case 0xf8:
+               case 0xf9:
+               case 0xfa:
+               case 0xfb:
+               case 0xfc:
+               case 0xfe:
+               if (xb->type >= TYPE_2386)
+                       v = vlsi_in(xb, portnum);
+               break;
+
                // floppy
                case 0x3f0:
                case 0x3f1:
@@ -2324,15 +2484,14 @@ uint8_t portin(uint16_t portnum)
                case 0x3f3:
                case 0x3f4:
                case 0x3f5:
-               case 0x3f6:
                case 0x3f7:
                v = infloppy(xb, portnum);
                break;
 
                case 0x60:
-               //write_log(_T("PC read keycode %02x\n"), v);
                if (xb->type >= TYPE_2286) {
                        v = x86_in_keyboard(0x60);
+                       //write_log(_T("PC read keycode %02x\n"), v);
                }
                break;
                case 0x61:
@@ -2386,12 +2545,6 @@ uint8_t portin(uint16_t portnum)
                }
                break;
 
-               case 0xed:
-               if (xb->scamp_idx2 == 0x1d) {
-                       v = x86_cmos_bank ? 0x20 : 0x00;
-               }
-               break;
-
                // at ide 1
                case 0x170:
                case 0x171:
@@ -2401,6 +2554,7 @@ uint8_t portin(uint16_t portnum)
                case 0x175:
                case 0x176:
                case 0x177:
+               case 0x376:
                v = x86_ide_hd_get(portnum, 0);
                break;
                // at ide 0
@@ -2412,6 +2566,7 @@ uint8_t portin(uint16_t portnum)
                case 0x1f5:
                case 0x1f6:
                case 0x1f7:
+               case 0x3f6:
                v = x86_ide_hd_get(portnum, 0);
                break;
 
@@ -2481,8 +2636,8 @@ static uint32_t portin32(uint16_t portnum)
                case 0x170:
                case 0x1f0:
                case 0x300:
-               v = x86_ide_hd_get(portnum, 1) << 16;
-               v |= x86_ide_hd_get(portnum, 1);
+               v = x86_ide_hd_get(portnum, 1) << 0;
+               v |= x86_ide_hd_get(portnum, 1) << 16;
                break;
                default:
                write_log(_T("portin32 %08x\n"), portnum);
@@ -2538,6 +2693,10 @@ uint16_t readw86(uint32_t addr32)
 static uaecptr get_x86_address(struct x86_bridge *xb, uaecptr addr, int *mode)
 {
        addr -= xb->baseaddress;
+       if (!xb->baseaddress || addr >= 0x80000) {
+               *mode = -1;
+               return 0;
+       }
        *mode = addr >> 17;
        addr &= 0x1ffff;
        if (addr < 0x10000) {
@@ -2660,7 +2819,9 @@ static void REGPARAM2 x86_bridge_wput(uaecptr addr, uae_u32 b)
        write_log(_T("pci_bridge_wput %08x (%08x,%d) %04x PC=%08x\n"), addr - xb->baseaddress, a, mode, b & 0xffff, M68K_GETPC);
 #endif
 
-       if (a >= 0x100000 - xb->bios_size || mode < 0)
+       if (a >= 0x100000 || mode < 0)
+               return;
+       if (xb->rombank[a / 4096])
                return;
 
        if (mode == ACCESS_MODE_IO) {
@@ -2710,7 +2871,9 @@ static void REGPARAM2 x86_bridge_bput(uaecptr addr, uae_u32 b)
        int mode;
        uaecptr a = get_x86_address(xb, addr, &mode);
 
-       if (a >= 0x100000 - xb->bios_size || mode < 0)
+       if (a >= 0x100000 || mode < 0)
+               return;
+       if (xb->rombank[a / 4096])
                return;
 
 #if X86_DEBUG_BRIDGE > 1
@@ -2769,6 +2932,7 @@ void x86_bridge_reset(void)
                        }
                        CPU_ShutDown(dosbox_sec);
                        CMOS_Destroy(dosbox_sec);
+                       TIMER_Destroy(dosbox_sec);
                        PIC_Destroy(dosbox_sec);
                        MEM_ShutDown(dosbox_sec);
                        delete dosbox_sec;
@@ -2776,6 +2940,7 @@ void x86_bridge_reset(void)
                xfree(xb->amiga_io);
                xfree(xb->io_ports);
                xfree(xb->pc_ram);
+               xfree(xb->pc_rom);
                zfile_fclose(xb->cmosfile);
                bridges[i] = NULL;
        }
@@ -2804,7 +2969,6 @@ static void check_floppy_delay(void)
        }
 }
 
-
 static void x86_cpu_execute(int cnt)
 {
        struct x86_bridge *xb = bridges[0];
@@ -2814,8 +2978,15 @@ static void x86_cpu_execute(int cnt)
                                xb->x86_reset_requested = false;
                                reset_x86_cpu(xb);
                        }
-                       CPU_Cycles = cnt;
-                       (*cpudecoder)();
+                       Bit32s old_cpu_cycles = CPU_Cycles;
+                       if (CPU_Cycles > cnt)
+                               CPU_Cycles = cnt;
+                       if (PIC_RunQueue()) {
+                               (*cpudecoder)();
+                       }
+                       CPU_Cycles = old_cpu_cycles -= cnt;
+                       if (CPU_Cycles < 0)
+                               CPU_Cycles = 0;
                        check_x86_irq();
                } else {
                        exec86(cnt);
@@ -2843,6 +3014,17 @@ void x86_bridge_execute_until(int until)
        }
 }
 
+void x86_bridge_sync_change(void)
+{
+       struct x86_bridge *xb = bridges[0];
+       if (!xb)
+               return;
+
+       xb->dosbox_vpos_tick = maxvpos * vblank_hz / 1000;
+       if (xb->dosbox_vpos_tick >= xb->dosbox_vpos_tick)
+               xb->dosbox_tick_vpos_cnt -= xb->dosbox_vpos_tick;
+}
+
 void x86_bridge_hsync(void)
 {
        struct x86_bridge *xb = bridges[0];
@@ -2851,9 +3033,20 @@ void x86_bridge_hsync(void)
 
        check_floppy_delay();
 
-       for (int i = 0; i < 3; i++) {
-               x86_cpu_execute(x86_instruction_count);
-               timing(maxhpos / 3);
+       if (!xb->x86_reset) {
+               if (xb->dosbox_cpu) {
+                       xb->dosbox_tick_vpos_cnt++;
+                       if (xb->dosbox_tick_vpos_cnt >= xb->dosbox_vpos_tick) {
+                               TIMER_AddTick();
+                               xb->dosbox_tick_vpos_cnt -= xb->dosbox_vpos_tick;
+                       }
+                       x86_cpu_execute(x86_instruction_count);
+               } else {
+                       for (int i = 0; i < 3; i++) {
+                               x86_cpu_execute(x86_instruction_count / 3);
+                               timing(maxhpos / 3);
+                       }
+               }
        }
 
        if (currprefs.x86_speed_throttle != changed_prefs.x86_speed_throttle) {
@@ -2885,9 +3078,17 @@ static void ew(uae_u8 *acmemory, int addr, uae_u8 value)
        }
 }
 
+static void setrombank(struct x86_bridge *xb, int start, int len)
+{
+       while (len > 0) {
+               xb->rombank[start / 4096] = 1;
+               start += 4096;
+               len -= 4096;
+       }
+}
+
 static void bridge_reset(struct x86_bridge *xb)
 {
-       uae_u8 *temp[2];
        xb->x86_reset = true;
        xb->configured = 0;
        xb->amiga_forced_interrupts = false;
@@ -2898,26 +3099,25 @@ static void bridge_reset(struct x86_bridge *xb)
        x86_instruction_count = DEFAULT_X86_INSTRUCTION_COUNT;
        memset(xb->amiga_io, 0, 0x10000);
        memset(xb->io_ports, 0, 0x10000);
-       for (int i = 0; i < 2; i++) {
-               temp[i] = NULL;
-               if (x86_xrom_start[i]) {
-                       temp[i] = xmalloc(uae_u8, x86_xrom_end[i] - x86_xrom_start[i]);
-                       memcpy(temp[i], xb->pc_ram + x86_xrom_start[i], x86_xrom_end[i] - x86_xrom_start[i]);
-               }
-       }
        memset(xb->pc_ram, 0, 0x100000 - xb->bios_size);
+       memset(xb->rombank, 0, sizeof xb->rombank);
+
        for (int i = 0; i < 2; i++) {
-               if (temp[i]) {
-                       memcpy(xb->pc_ram + x86_xrom_start[i], temp[i], x86_xrom_end[i] - x86_xrom_start[i]);
-                       xfree(temp[i]);
+               if (x86_xrom_end[i] - x86_xrom_start[i] > 0) {
+                       memcpy(xb->pc_ram + x86_xrom_start[i], xb->pc_rom + x86_xrom_start[i], x86_xrom_end[i] - x86_xrom_start[i]);
+                       setrombank(xb, x86_xrom_start[i], x86_xrom_end[i] - x86_xrom_start[i]);
                }
        }
+       memcpy(xb->pc_ram + 0x100000 - xb->bios_size, xb->pc_rom + 0x100000 - xb->bios_size, xb->bios_size);
+       setrombank(xb, 0x100000 - xb->bios_size, xb->bios_size);
+
        xb->amiga_io[IO_CONTROL_REGISTER] =     0xfe;
        xb->amiga_io[IO_PC_INTERRUPT_CONTROL] = 0xff;
        xb->amiga_io[IO_INTERRUPT_MASK] = 0xff;
        xb->amiga_io[IO_MODE_REGISTER] = 0x00;
        xb->amiga_io[IO_PC_INTERRUPT_STATUS] = 0xfe;
        x86_cmos_bank = 0;
+       memset(xb->vlsi_regs, 0, sizeof xb->vlsi_regs);
 
        if (xb->type >= TYPE_2286) {
                int sel1 = (xb->settings >> 10) & 1;
@@ -2930,7 +3130,10 @@ static void bridge_reset(struct x86_bridge *xb)
                xb->amiga_io[IO_MODE_REGISTER] |= sel1 << 5;
                xb->amiga_io[IO_MODE_REGISTER] |= sel2 << 6;
        }
+       if (xb->type == TYPE_2386)
+               x86_turbo_allowed = true;
 
+       x86_bridge_sync_change();
        inittiming();
        floppy_hardreset();
 }
@@ -2970,10 +3173,12 @@ static void load_vga_bios(void)
        x86_xrom_start[1] = 0xc0000;
        x86_xrom_end[1] = x86_xrom_start[1];
        if (zf) {
-               x86_xrom_end[1] += zfile_fread(MemBase + 0xc0000, 1, 65536, zf);
+               x86_xrom_end[1] += zfile_fread(xb->pc_rom + x86_xrom_start[1], 1, 65536, zf);
                zfile_fclose(zf);
                x86_xrom_end[1] += 4095;
                x86_xrom_end[1] &= ~4095;
+               memcpy(xb->pc_ram + x86_xrom_start[1], xb->pc_rom + x86_xrom_start[1], x86_xrom_end[1] - x86_xrom_start[1]);
+               setrombank(xb, x86_xrom_start[1], x86_xrom_end[1] - x86_xrom_start[1]);
        }
        if (xb->dosbox_cpu) {
                MEM_ShutDown(dosbox_sec);
@@ -2982,14 +3187,30 @@ static void load_vga_bios(void)
        }
 }
 
-void x86_xt_ide_bios(struct zfile *z)
+void x86_xt_ide_bios(struct zfile *z, struct romconfig *rc)
 {
        struct x86_bridge *xb = bridges[0];
+       uae_u32 addr = 0;
        if (!xb || !z)
                return;
-       x86_xrom_start[0] = 0xec000;
+       switch (rc->device_settings)
+       {
+               case 0:
+               addr = 0xcc000;
+               break;
+               case 1:
+               addr = 0xdc000;
+               break;
+               case 2:
+               default:
+               addr = 0xec000;
+               break;
+       }
+       x86_xrom_start[0] = addr;
        x86_xrom_end[0] = x86_xrom_start[0] + 0x4000;
-       zfile_fread(xb->pc_ram + x86_xrom_start[0], 1, 32768, z);
+       zfile_fread(xb->pc_rom + x86_xrom_start[0], 1, 32768, z);
+       memcpy(xb->pc_ram + x86_xrom_start[0], xb->pc_rom + x86_xrom_start[0], x86_xrom_end[0] - x86_xrom_start[0]);
+       setrombank(xb, x86_xrom_start[0], x86_xrom_end[0] - x86_xrom_start[0]);
        if (xb->dosbox_cpu) {
                MEM_ShutDown(dosbox_sec);
                MEM_Init(dosbox_sec);
@@ -3002,7 +3223,7 @@ void x86_xt_ide_bios(struct zfile *z)
 static const uae_u8 a1060_autoconfig[16] = { 0xc4, 0x01, 0x80, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 static const uae_u8 a2386_autoconfig[16] = { 0xc4, 0x67, 0x80, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
-addrbank *x86_bridge_init(struct romconfig *rc, int type)
+addrbank *x86_bridge_init(struct romconfig *rc, uae_u32 romtype, int type)
 {
        struct x86_bridge *xb = x86_bridge_alloc();
        const uae_u8 *ac;
@@ -3021,18 +3242,21 @@ addrbank *x86_bridge_init(struct romconfig *rc, int type)
        xb->settings = rc->device_settings;
        if (xb->type >= TYPE_2286) {
                xb->dosbox_cpu = ((xb->settings >> 19) & 3) + 1;
+               xb->dosbox_cpu_arch = (xb->settings >> 23) & 7;
                xb->settings |= 0xff;
                ac = xb->type >= TYPE_2386 ? a2386_autoconfig : a1060_autoconfig;
                xb->pc_maxram = (1024 * 1024) << ((xb->settings >> 16) & 7);
                xb->bios_size = 65536;
        } else {
                xb->dosbox_cpu = (xb->settings >> 19) & 7;
+               xb->dosbox_cpu_arch = (xb->settings >> 23) & 7;
                ac = a1060_autoconfig;
                xb->pc_maxram = 1 * 1024 * 1024;
                xb->bios_size = 32768;
        }
 
        xb->pc_ram = xcalloc(uae_u8, xb->pc_maxram + 1 * 1024 * 1024);
+       xb->pc_rom = xcalloc(uae_u8, 0x100000);
        x86_memsize = xb->pc_maxram;
        mono_start =  xb->pc_ram + 0xb0000;
        mono_end =    xb->pc_ram + 0xb2000;
@@ -3042,12 +3266,15 @@ addrbank *x86_bridge_init(struct romconfig *rc, int type)
        MemBase = xb->pc_ram;
 
        if (xb->dosbox_cpu) {
+               ticksDone = 0;
+               ticksScheduled = 0;
                x86_fpu_enabled = (xb->settings >> 22) & 1;
                dosbox_sec = new Section_prop("dummy");
                MEM_Init(dosbox_sec);
                PAGING_Init(dosbox_sec);
                CMOS_Init(dosbox_sec, xb->type == TYPE_2386 ? 0x7f : 0x3f);
                PIC_Init(dosbox_sec);
+               TIMER_Init(dosbox_sec);
                FPU_Init(dosbox_sec);
                if (xb->type >= TYPE_2286) {
                        xb->cmossize = xb->type == TYPE_2386 ? 192 : 64;
@@ -3064,7 +3291,9 @@ addrbank *x86_bridge_init(struct romconfig *rc, int type)
                }
        }
        if (ISVGA()) {
-               MEM_SetVGAHandler();
+               if (xb->dosbox_cpu) {
+                       MEM_SetVGAHandler();
+               }
                load_vga_bios();
        }
 
@@ -3089,11 +3318,13 @@ addrbank *x86_bridge_init(struct romconfig *rc, int type)
        bridge_reset(xb);
 
        // load bios
-       if (!load_rom_rc(rc, NULL, xb->bios_size, 0, xb->pc_ram + 0x100000 - xb->bios_size, xb->bios_size, LOADROM_FILL)) {
+       if (!load_rom_rc(rc, romtype, xb->bios_size, 0, xb->pc_rom + 0x100000 - xb->bios_size, xb->bios_size, LOADROM_FILL)) {
                error_log(_T("Bridgeboard BIOS failed to load"));
                x86_bridge_free();
                return &expamem_null;
        }
+       memcpy(xb->pc_ram + 0x100000 - xb->bios_size, xb->pc_rom + 0x100000 - xb->bios_size, xb->bios_size);
+       setrombank(xb, 0x100000 - xb->bios_size, xb->bios_size);
 
        xb->bank = &x86_bridge_bank;
        for (int i = 0; i < 16; i++) {
@@ -3105,30 +3336,27 @@ addrbank *x86_bridge_init(struct romconfig *rc, int type)
 
 addrbank *a1060_init(struct romconfig *rc)
 {
-       return x86_bridge_init(rc, TYPE_SIDECAR);
+       return x86_bridge_init(rc, ROMTYPE_A1060, TYPE_SIDECAR);
 }
 addrbank *a2088xt_init(struct romconfig *rc)
 {
-       return x86_bridge_init(rc, TYPE_2088);
+       return x86_bridge_init(rc, ROMTYPE_A2088, TYPE_2088);
 }
 addrbank *a2088t_init(struct romconfig *rc)
 {
-       return x86_bridge_init(rc, TYPE_2088T);
+       return x86_bridge_init(rc, ROMTYPE_A2088T, TYPE_2088T);
 }
 addrbank *a2286_init(struct romconfig *rc)
 {
-       return x86_bridge_init(rc, TYPE_2286);
+       return x86_bridge_init(rc, ROMTYPE_A2286, TYPE_2286);
 }
 addrbank *a2386_init(struct romconfig *rc)
 {
-       return x86_bridge_init(rc, TYPE_2386);
+       return x86_bridge_init(rc, ROMTYPE_A2386, TYPE_2386);
 }
 
 /* dosbox cpu core support stuff */
 
-Bit32s ticksDone;
-Bit32u ticksScheduled;
-
 void IO_WriteB(Bitu port, Bitu val)
 {
        portout(port, val);
@@ -3154,11 +3382,6 @@ Bitu IO_ReadD(Bitu port)
        return portin32(port);
 }
 
-void TIMER_SetGate2(bool v)
-{
-       write_log(_T("void TIMER_SetGate2(%d)!\n"), v);
-}
-
 Bits CPU_Core_Prefetch_Run(void)
 {
        return 0;