1
0
Fork 0

changes for improved timing event system

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1968
This commit is contained in:
Sjoerd van der Berg 2004-09-10 22:15:20 +00:00
parent 5c26302fc2
commit dfbb195418
13 changed files with 103 additions and 116 deletions

View file

@ -32,21 +32,20 @@ typedef void (* PIC_EventHandler)(Bitu val);
#define PIC_MAXIRQ 15
#define PIC_NOIRQ 0xFF
extern Bitu PIC_IRQCheck;
extern Bitu PIC_IRQActive;
extern Bitu PIC_Ticks;
INLINE Bitu PIC_Index(void) {
return ((CPU_CycleMax-CPU_CycleLeft-CPU_Cycles)*1000)/CPU_CycleMax;
INLINE float PIC_TickIndex(void) {
return (CPU_CycleMax-CPU_CycleLeft-CPU_Cycles)/(float)CPU_CycleMax;
}
INLINE Bits PIC_MakeCycles(Bitu amount) {
return (CPU_CycleMax*amount)/1000;
INLINE Bits PIC_MakeCycles(double amount) {
return (Bits)(CPU_CycleMax*amount);
}
INLINE Bit64u PIC_MicroCount(void) {
return PIC_Ticks*1000+PIC_Index();
INLINE double PIC_FullIndex(void) {
return PIC_Ticks+PIC_TickIndex();
}
void PIC_ActivateIRQ(Bitu irq);
@ -55,7 +54,8 @@ void PIC_DeActivateIRQ(Bitu irq);
void PIC_runIRQs(void);
bool PIC_RunQueue(void);
void PIC_AddEvent(PIC_EventHandler handler,Bitu delay,Bitu val=0);
//Delay in milliseconds
void PIC_AddEvent(PIC_EventHandler handler,float delay,Bitu val=0);
void PIC_RemoveEvents(PIC_EventHandler handler);
void PIC_SetIRQMask(Bitu irq, bool masked);

View file

@ -89,7 +89,6 @@ typedef struct {
typedef struct {
bool resizing;
bool drawing;
Bitu width;
Bitu height;
Bitu blocks;
@ -106,20 +105,21 @@ typedef struct {
Bitu parts_lines;
Bitu parts_left;
struct {
Bitu vtotal;
Bitu vstart;
Bitu vend;
Bitu htotal;
Bitu hstart;
Bitu hend;
Bitu parts;
} micro;
float vtotal;
float vstart;
float vend;
float htotal;
float hstart;
float hend;
float parts;
} delay;
bool double_scan;
bool doublewidth,doubleheight;
Bit8u font[64*1024];
Bit8u * font_tables[2];
Bitu blinking;
struct {
Bitu address;
Bit8u sline,eline;
Bit8u count,delay;
Bit8u enabled;

View file

@ -62,7 +62,7 @@ namespace OPL2 {
}
void TimerHandler(int channel,double interval_Sec) {
if (interval_Sec==0.0) return;
PIC_AddEvent(TimerOver,(Bitu)(1000000.0*interval_Sec),channel);
PIC_AddEvent(TimerOver,1000.0f*interval_Sec,channel);
}
}
#undef OSD_CPU_H
@ -75,7 +75,7 @@ namespace THEOPL3 {
}
void TimerHandler(int channel,double interval_Sec) {
if (interval_Sec==0.0) return;
PIC_AddEvent(TimerOver,(Bitu)(1000000.0*interval_Sec),channel);
PIC_AddEvent(TimerOver,1000.0f*interval_Sec,channel);
}
}
@ -125,7 +125,7 @@ static void OPL_CallBack(Bitu len) {
opl.chan->AddSamples_s16(len,(Bit16s*)MixTemp);
break;
}
if ((PIC_Ticks-opl.last_used)>5000) {
if ((PIC_Ticks-opl.last_used)>30000) {
opl.chan->Enable(false);
opl.active=false;
}

View file

@ -33,34 +33,28 @@ static struct {
struct {
bool enabled;
Bit8u div;
Bitu micro;
float delay;
} timer;
struct {
Bit64u timer;
Bit64u ended;
Bit64u alarm;
double timer;
double ended;
double alarm;
} last;
bool ack;
bool update_ended;
} cmos;
static void cmos_timerevent(Bitu val) {
PIC_ActivateIRQ(8);
if(cmos.timer.enabled) PIC_AddEvent(cmos_timerevent,cmos.timer.micro);
if (cmos.ack) {
PIC_AddEvent(cmos_timerevent,cmos.timer.micro);
cmos.regs[0x0c]|=0x0a0;
cmos.ack=false;
}
if (cmos.timer.enabled) PIC_AddEvent(cmos_timerevent,cmos.timer.delay);
}
static void cmos_checktimer(void) {
PIC_RemoveEvents(cmos_timerevent);
if (cmos.timer.div<=2) cmos.timer.div+=7;
cmos.timer.micro=(Bitu) (1000000.0/(32768.0 / (1 << (cmos.timer.div - 1))));
cmos.timer.delay=(1000.0f/(32768.0f / (1 << (cmos.timer.div - 1))));
if (!cmos.timer.div || !cmos.timer.enabled) return;
LOG(LOG_PIT,LOG_NORMAL)("RTC Timer at %f hz",1000000.0/cmos.timer.micro);
PIC_AddEvent(cmos_timerevent,cmos.timer.micro);
LOG(LOG_PIT,LOG_NORMAL)("RTC Timer at %.2f hz",1000.0/cmos.timer.delay);
PIC_AddEvent(cmos_timerevent,cmos.timer.delay);
}
void cmos_selreg(Bitu port,Bitu val,Bitu iolen) {
@ -146,7 +140,7 @@ static Bitu cmos_readreg(Bitu port,Bitu iolen) {
case 0x05: /* Hours Alarm */
return cmos.regs[cmos.reg];
case 0x0a: /* Status register C */
if (PIC_Index()<0x2) {
if (PIC_TickIndex()<0.002) {
return (cmos.regs[0x0a]&0x7f) | 0x80;
} else {
return (cmos.regs[0x0a]&0x7f);
@ -160,12 +154,12 @@ static Bitu cmos_readreg(Bitu port,Bitu iolen) {
} else {
/* Give correct values at certain times */
Bit8u val=0;
Bit64u index=PIC_MicroCount();
if (index>=(cmos.last.timer+cmos.timer.micro)) {
double index=PIC_FullIndex();
if (index>=(cmos.last.timer+cmos.timer.delay)) {
cmos.last.timer=index;
val|=0x40;
}
if (index>=(cmos.last.ended+1000000)) {
if (index>=(cmos.last.ended+1000)) {
cmos.last.ended=index;
val|=0x10;
}

View file

@ -79,7 +79,7 @@ struct GFGus {
bool raiseirq;
bool masked;
bool running;
Bit32u delay;
float delay;
} timers[2];
Bit32u rate;
Bit16u portbase;
@ -366,8 +366,8 @@ static void GUSReset(void) {
myGUS.timers[0].value = 0xff;
myGUS.timers[1].value = 0xff;
myGUS.timers[0].delay = 80;
myGUS.timers[1].delay = 320;
myGUS.timers[0].delay = 0.080f;
myGUS.timers[1].delay = 0.320f;
myGUS.ChangeIRQDMA = false;
// Stop all channels
int i;
@ -471,7 +471,8 @@ static void GUS_TimerEvent(Bitu val) {
myGUS.IRQStatus|=0x4 << val;
GUS_CheckIRQ();
}
if (myGUS.timers[val].running) PIC_AddEvent(GUS_TimerEvent,myGUS.timers[val].delay,val);
if (myGUS.timers[val].running)
PIC_AddEvent(GUS_TimerEvent,myGUS.timers[val].delay,val);
};
@ -588,11 +589,11 @@ static void ExecuteGlobRegister(void) {
break;
case 0x46: // Timer 1 control
myGUS.timers[0].value = (Bit8u)(myGUS.gRegData>>8);
myGUS.timers[0].delay = (0x100 - myGUS.timers[0].value) * 80;
myGUS.timers[0].delay = (0x100 - myGUS.timers[0].value) * 0.080f;
break;
case 0x47: // Timer 2 control
myGUS.timers[1].value = (Bit8u)(myGUS.gRegData>>8);
myGUS.timers[1].delay = (0x100 - myGUS.timers[1].value) * 320;
myGUS.timers[1].delay = (0x100 - myGUS.timers[1].value) * 0.320f;
break;
case 0x49: // DMA sampling control register
myGUS.SampControl = (Bit8u)(myGUS.gRegData>>8);

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: keyboard.cpp,v 1.27 2004-08-04 09:12:55 qbix79 Exp $ */
/* $Id: keyboard.cpp,v 1.28 2004-09-10 22:15:20 harekiet Exp $ */
#include <string.h>
#include <assert.h>
@ -30,7 +30,7 @@
#include "mixer.h"
#define KEYBUFSIZE 32
#define KEYDELAY 300 //Considering 20-30 khz serial clock and 11 bits/char
#define KEYDELAY 0.300f //Considering 20-30 khz serial clock and 11 bits/char
enum KeyCommands {
CMD_NONE,

View file

@ -250,12 +250,8 @@ void MixerChannel::FillUp(void) {
SDL_UnlockAudio();
return;
}
Bitu filled=(done-mixer.done)*1000/(mixer.needed-mixer.done);
Bitu index=PIC_Index();
if (filled<index) {
Bitu temp=mixer.done+((index*(mixer.needed-mixer.done))/1000);
Mix(temp);
}
float index=PIC_TickIndex();
Mix((Bitu)(index*mixer.needed));
SDL_UnlockAudio();
}

View file

@ -15,7 +15,7 @@ static void MPU401_Reset(void);
static void MPU401_EOIHandler(void);
#define MPU_QUEUE 32
#define TIMECONSTANT 60000000
#define TIMECONSTANT (60000000/1000.0f)
enum MpuMode { M_UART,M_INTELLIGENT } ;
enum MpuDataType {OVERFLOW,MARK,MIDI_SYS,MIDI_NORM,COMMAND};

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: pic.cpp,v 1.23 2004-08-04 09:12:55 qbix79 Exp $ */
/* $Id: pic.cpp,v 1.24 2004-09-10 22:15:20 harekiet Exp $ */
#include <list>
@ -57,7 +57,8 @@ static IRQ_Block irqs[16];
static PIC_Controller pics[2];
struct PICEntry {
Bitu index;Bitu value;
float index;
Bitu value;
PIC_EventHandler event;
PICEntry * next;
};
@ -294,21 +295,20 @@ static void AddEntry(PICEntry * entry) {
break;
}
}
Bits cycles=PIC_MakeCycles(pic.next_entry->index-PIC_Index());
Bits cycles=PIC_MakeCycles(pic.next_entry->index-PIC_TickIndex());
if (cycles<CPU_Cycles) {
CPU_CycleLeft+=CPU_Cycles;
CPU_Cycles=0;
}
}
void PIC_AddEvent(PIC_EventHandler handler,Bitu delay,Bitu val) {
void PIC_AddEvent(PIC_EventHandler handler,float delay,Bitu val) {
if (!pic.free_entry) {
LOG(LOG_PIC,LOG_ERROR)("Event queue full");
return;
}
PICEntry * entry=pic.free_entry;
Bitu index=delay+PIC_Index();
entry->index=index;
entry->index=delay+PIC_TickIndex();;
entry->event=handler;
entry->value=val;
pic.free_entry=pic.free_entry->next;
@ -350,7 +350,7 @@ bool PIC_RunQueue(void) {
return false;
}
/* Check the queue for an entry */
Bitu index=PIC_Index();
double index=PIC_TickIndex();
while (pic.next_entry && pic.next_entry->index<=index) {
PICEntry * entry=pic.next_entry;
pic.next_entry=entry->next;
@ -412,7 +412,7 @@ void TIMER_AddTick(void) {
/* Go through the list of scheduled events and lower their index with 1000 */
PICEntry * entry=pic.next_entry;
while (entry) {
if (entry->index>1000) entry->index-=1000;
if (entry->index>=1) entry->index-=1;
else entry->index=0;
entry=entry->next;
}

View file

@ -425,27 +425,27 @@ static void DMA_Silent_Event(Bitu val) {
}
if (sb.dma.left) {
Bitu bigger=(sb.dma.left > sb.dma.min) ? sb.dma.min : sb.dma.left;
Bitu index=(bigger*1000000)/sb.dma.rate;
PIC_AddEvent(DMA_Silent_Event,index,bigger);
float delay=(bigger*1000.0f)/sb.dma.rate;
PIC_AddEvent(DMA_Silent_Event,delay,bigger);
}
}
static void END_DMA_Event(Bitu val) {
GenerateDMASound(sb.dma.left);
GenerateDMASound(val);
}
static void CheckDMAEnd(void) {
if (!sb.dma.left) return;
if (!sb.speaker) {
Bitu bigger=(sb.dma.left > sb.dma.min) ? sb.dma.min : sb.dma.left;
Bitu index=(bigger*1000000)/sb.dma.rate;
PIC_AddEvent(DMA_Silent_Event,index,bigger);
LOG(LOG_SB,LOG_NORMAL)("Silent DMA Transfer scheduling IRQ in %d microseconds",index);
float delay=(bigger*1000.0f)/sb.dma.rate;
PIC_AddEvent(DMA_Silent_Event,delay,bigger);
LOG(LOG_SB,LOG_NORMAL)("Silent DMA Transfer scheduling IRQ in %.3f milliseconds",delay);
} else if (sb.dma.left<sb.dma.min) {
Bitu index=(sb.dma.left*1000000)/sb.dma.rate;
LOG(LOG_SB,LOG_NORMAL)("Sub millisecond transfer scheduling IRQ in %d microseconds",index);
PIC_AddEvent(END_DMA_Event,index);
float delay=(sb.dma.left*1000.0f)/sb.dma.rate;
LOG(LOG_SB,LOG_NORMAL)("Short transfer scheduling IRQ in %.3f milliseconds",delay);
PIC_AddEvent(END_DMA_Event,delay,sb.dma.left);
}
}
@ -663,7 +663,7 @@ static void DSP_DoCommand(void) {
break;
case 0x80: /* Silence DAC */
PIC_AddEvent(&DSP_RaiseIRQEvent,
(1000000*(1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8))/sb.freq));
(1000.0f*(1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8))/sb.freq));
break;
case 0xb0: case 0xb2: case 0xb4: case 0xb6:
case 0xc0: case 0xc2: case 0xc4: case 0xc6:

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: timer.cpp,v 1.28 2004-09-07 11:28:27 harekiet Exp $ */
/* $Id: timer.cpp,v 1.29 2004-09-10 22:15:20 harekiet Exp $ */
#include "dosbox.h"
#include "inout.h"
@ -26,6 +26,7 @@
#include "dosbox.h"
#include "mixer.h"
#include "timer.h"
#include "math.h"
static INLINE void BIN2BCD(Bit16u& val) {
Bit16u temp=val%10 + (((val/10)%10)<<4)+ (((val/100)%10)<<8) + (((val/1000)%10)<<12);
@ -38,17 +39,18 @@ static INLINE void BCD2BIN(Bit16u& val) {
}
struct PIT_Block {
Bit8u mode; /* Current Counter Mode */
Bitu cntr;
Bits micro;
Bit64u start;
float delay;
double start;
Bit16u read_latch;
Bit16u write_latch;
Bit8u mode;
Bit8u latch_mode;
Bit8u read_state;
Bit16u read_latch;
Bit8u write_state;
Bit16u write_latch;
bool bcd;
bool go_read_latch;
bool new_mode;
@ -58,26 +60,26 @@ static PIT_Block pit[3];
static void PIT0_Event(Bitu val) {
PIC_ActivateIRQ(0);
if (pit[0].mode!=0) PIC_AddEvent(PIT0_Event,pit[0].micro);
if (pit[0].mode!=0) PIC_AddEvent(PIT0_Event,pit[0].delay);
}
static bool counter_output(Bitu counter) {
PIT_Block * p=&pit[counter];
Bit64s micro=PIC_MicroCount()-p->start;
double index=PIC_FullIndex()-p->start;
switch (p->mode) {
case 0:
if (p->new_mode) return false;
if (micro>p->micro) return true;
if (index>p->delay) return true;
else return false;
break;
case 2:
if (p->new_mode) return true;
micro%=p->micro;
return micro>0;
index=fmod(index,(double)p->delay);
return index>0;
case 3:
if (p->new_mode) return true;
micro%=p->micro;
return micro*2<p->micro;
index=fmod(index,(double)p->delay);
return index*2<p->delay;
default:
LOG(LOG_PIT,LOG_ERROR)("Illegal Mode %d for reading output",p->mode);
return true;
@ -88,37 +90,32 @@ 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;
Bit64s micro=PIC_MicroCount()-p->start;
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 (micro>p->micro) {
micro-=p->micro;
micro%=(Bit64u)(1000000/((float)PIT_TICK_RATE/(float)0x10000));
p->read_latch=(Bit16u)(0x10000-(((double)micro/(double)p->micro)*(double)0x10000));
if (index>p->delay) {
index-=p->delay;
index=fmod(index,(1000.0/PIT_TICK_RATE)*0x1000);
p->read_latch=(Bit16u)(0xffff-index*0xffff);
} else {
p->read_latch=(Bit16u)(p->cntr-(((double)micro/(double)p->micro)*(double)p->cntr));
p->read_latch=(Bit16u)(p->cntr-index*(PIT_TICK_RATE/1000.0));
}
break;
case 2: /* Rate Generator */
micro%=p->micro;
p->read_latch=(Bit16u)(p->cntr-(((double)micro/(double)p->micro)*(double)p->cntr));
index=fmod(index,(double)p->delay);
p->read_latch=(Bit16u)(p->cntr - (index/p->delay)*p->cntr);
break;
case 3: /* Square Wave Rate Generator */
micro%=p->micro;
micro*=2;
if (micro>p->micro) micro-=p->micro;
p->read_latch=(Bit16u)(p->cntr-(((double)micro/(double)p->micro)*(double)p->cntr));
break;
case 4: /* Software Triggered Strobe */
if (micro>p->micro) p->read_latch=p->write_latch;
else p->read_latch=(Bit16u)(p->cntr-(((double)micro/(double)p->micro)*(double)p->cntr));
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);
break;
default:
LOG(LOG_PIT,LOG_ERROR)("Illegal Mode %d for reading counter %d",p->mode,counter);
micro%=p->micro;
p->read_latch=(Bit16u)(p->cntr-(((double)micro/(double)p->micro)*(double)p->cntr));
p->read_latch=0xffff;
break;
}
}
@ -151,16 +148,15 @@ static void write_latch(Bitu port,Bitu val,Bitu iolen) {
if (p->bcd == false) p->cntr = 0x10000;
else p->cntr=9999;
} else p->cntr = p->write_latch;
p->start=PIC_MicroCount();
p->micro=(Bits)(1000000/((float)PIT_TICK_RATE/(float)p->cntr));
if (!p->micro) p->micro=1;
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->new_mode=false;
PIC_AddEvent(PIT0_Event,p->micro);
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 %.3g Hz mode %d",PIT_TICK_RATE/(double)p->cntr,(Bit32u)p->mode);
LOG(LOG_PIT,LOG_NORMAL)("PIT 0 Timer at %.2f 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);
@ -283,10 +279,10 @@ void TIMER_Init(Section* sect) {
pit[2].cntr=1320;
pit[2].go_read_latch=true;
pit[0].micro=(Bits)(1000000/((float)PIT_TICK_RATE/(float)pit[0].cntr));
pit[1].micro=(Bits)(1000000/((float)PIT_TICK_RATE/(float)pit[1].cntr));
pit[2].micro=(Bits)(1000000/((float)PIT_TICK_RATE/(float)pit[2].cntr));
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));
PIC_AddEvent(PIT0_Event,pit[0].micro);
PIC_AddEvent(PIT0_Event,pit[0].delay);
}

View file

@ -71,7 +71,7 @@ void VGA_StartResize(void) {
if (!vga.draw.resizing) {
vga.draw.resizing=true;
/* Start a resize after 50 ms */
PIC_AddEvent(VGA_SetupDrawing,50000);
PIC_AddEvent(VGA_SetupDrawing,50);
}
}

View file

@ -419,7 +419,7 @@ static void VGA_DoUpdateLFB(Bitu val) {
void VGA_StartUpdateLFB(void) {
if (!lfb_update) {
lfb_update=true;
PIC_AddEvent(VGA_DoUpdateLFB,100); //100 microseconds later
PIC_AddEvent(VGA_DoUpdateLFB,0.100f); //100 microseconds later
}
}