From: Toni Wilen Date: Fri, 4 Sep 2015 16:51:39 +0000 (+0300) Subject: x86 bridgeboard updates. X-Git-Tag: 3200~94 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=69bb097618b2d7d8ecf42dd16ba9a7d997bd9f0f;p=francis%2Fwinuae.git x86 bridgeboard updates. --- diff --git a/dosbox/cpu.cpp b/dosbox/cpu.cpp index ea037e3f..97049a0f 100644 --- a/dosbox/cpu.cpp +++ b/dosbox/cpu.cpp @@ -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(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 diff --git a/dosbox/db_memory.cpp b/dosbox/db_memory.cpp index d5d25750..cad04080 100644 --- a/dosbox/db_memory.cpp +++ b/dosbox/db_memory.cpp @@ -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) { diff --git a/dosbox/dosbox.h b/dosbox/dosbox.h index e76e0c9e..a0c20b11 100644 --- a/dosbox/dosbox.h +++ b/dosbox/dosbox.h @@ -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 diff --git a/dosbox/mem.h b/dosbox/mem.h index c0226268..885cee61 100644 --- a/dosbox/mem.h +++ b/dosbox/mem.h @@ -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; } diff --git a/dosbox/paging.h b/dosbox/paging.h index f7198f8f..805e9299 100644 --- a/dosbox/paging.h +++ b/dosbox/paging.h @@ -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 diff --git a/dosbox/pic.cpp b/dosbox/pic.cpp index f6c1801a..3a68d062 100644 --- a/dosbox/pic.cpp +++ b/dosbox/pic.cpp @@ -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 index 00000000..9a431945 --- /dev/null +++ b/dosbox/timer.cpp @@ -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 +#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*2delay; + 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 index 00000000..28268093 --- /dev/null +++ b/dosbox/timer.h @@ -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 + +#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 diff --git a/include/x86.h b/include/x86.h index 0669a507..8ec53ac8 100644 --- a/include/x86.h +++ b/include/x86.h @@ -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 5616e1b4..320f7158 100644 --- 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;