|
|
1.1 root 1: /*
2: Hatari - clocks_timings.c
3:
1.1.1.2 root 4: This file is distributed under the GNU General Public License, version 2
5: or at your option any later version. Read the file gpl.txt for details.
1.1 root 6:
7: Clocks Timings for the hardware components in each supported machine type,
8: as well as functions taking into account the exact length of a VBL to
9: precisely emulate video/audio parts (number of VBL per sec, number of
10: audio samples per VBL, ...)
11:
12: The video freq is not exactly 50 or 60 Hz because the number of cpu cycles
13: per second is not a multiple of the number of cpu cycles per VBL.
14: This can cause synchronisation errors between audio and video effects
15: when both components use different clocks (eg in STE where audio DMA clock
16: is not the same as the cpu clock).
17:
18: To get the best results, it's recommanded to set RoundVBLPerSec=false.
19:
20: Note that if you do so, the number of VBL won't be exactly 50 or 60 per sec
21: but 50.05 or 60.04 ; if this does not work with your display, set RoundVBLPerSec=true
22: to get an integer number of VBL per sec (but this should not be needed).
23:
24:
25:
26: ST :
27: MCLK = 32 MHz
28: SHIFTER IN = 32 MHz OUT = 16 MHz
29: MMU IN = 16 MHz OUT = 8 MHz, 4 MHz
30: GLUE IN = 8 MHz OUT = 2 MHz, 500 kHz
31: BUS = 8 MHz
32:
33: CPU 68000 IN = 8 MHz
34: DMA IN = 8 MHz
35: MFP 68901 IN = 4 MHz, 2.4576 MHz (external clock)
36: FDC WD1772 IN = 8 MHz
37: BLITTER IN = 8 MHz
38: YM2149 IN = 2 MHz
39: ACIA MC6850 IN = 500 kHz
40: IKBD HD6301 IN = 1 MHZ (local clock)
41:
42:
43: STE :
44: MCLK = 32 MHz
45: EXT OSC = 8 MHZ OUT = 8 MHz (SCLK), 2 MHz (CLK2)
46: GST SHIFTER IN = 32 MHz, 8 MHz (external clock SCLK) OUT = 16 MHz, 8 MHz (FCLK=SCLK)
47: GST MCU IN = 16 MHz OUT = 8 MHz (CLK8), 4 MHz (CLK4), 500 kHz (KHZ500)
48: BUS = 8 MHz
49:
50: CPU 68000 IN = 8 MHz (CLK8)
51: DMA IN = 8 MHz (CLK8)
52: DMA AUDIO IN = 8 MHz (SCLK)
53: MFP 68901 IN = 4 MHz (CLK4), 2.4576 MHz (external clock)
54: FDC WD1772 IN = 8 MHz (SCLK)
55: BLITTER IN = 8 MHz (CLK8)
56: YM2149 IN = 2 MHz (CLK2)
57: ACIA MC6850 IN = 500 kHz (KHZ500)
58: IKBD HD6301 IN = 1 MHZ (local clock)
59:
60:
61: MEGA STE :
62: MCLK = 32 MHz
63: SCLK = 8 MHz
64: GST SHIFTER IN = 32 MHz, 8 MHz (external clock SCLK) OUT = 16 MHz (CLK16), 8 MHz (FCLK=SCLK)
65: GST MCU IN = 16 MHz (CLK16) OUT = 8 MHz (CLK8), 4 MHz (CLK4), 500 kHz (KHZ500)
66: BUS = 8 MHz
67:
68: CPU 68000 IN = 16 MHz (CLK16)
69: FPU 68881 IN = 16 MHz (CLK16)
70: DMA IN = 8 MHz (CLK8)
71: DMA AUDIO IN = 8 MHz (SCLK)
72: MFP 68901 IN = 4 MHz (CLK4), 2.4576 MHz (external clock)
73: FDC WD1772 IN = 8 MHz (SCLK)
74: BLITTER IN = 8 MHz (CLK8)
75: YM2149 IN = 2 MHz (CLK2 = SCLK / 4)
76: ACIA MC6850 IN = 500 kHz (KHZ500)
77: IKBD HD6301 IN = 1 MHZ (local clock)
78:
79:
80: TT :
81: MCLK = 32 MHz (CLK32)
82: TT VIDEO IN = 32 MHz (CLK32) OUT = 16 MHz (CLK16), 4 MHz (CLK4), 2 MHz (CLK2)
83: GST MCU IN = 16 MHz (CLK16A), 2 MHz (CLK2) OUT = 8 MHz (CLK8), 8 MHz (FCCLK), 1 MHz (CLKE), 500 kHz (CLKX5)
84: BUS = 16 MHz
85:
86: CPU 68030 IN = 32 MHz (CLK32)
87: FPU 68882 IN = 32 MHz (CLK32)
88: DMA IN = 8 MHz (CLK8)
89: SND SHIFTER IN = 16 MHz (CLK16F), 2 MHz (CLK2) OUT = ? MHz (FCLK)
90: MFP 68901 IN = 4 MHz (CLK4), 2.4576 MHz (external clock) NOTE : TT has 2 MFPs 68901
91: FDC WD1772 IN = 8 MHz (FCCLK)
92: BLITTER NOT AVAILABLE
93: YM2149 IN = 2 MHz (CLK2)
94: ACIA MC6850 IN = 500 kHz (CLKX5)
95: IKBD HD6301 IN = 1 MHZ (local clock)
96:
97:
98: FALCON :
99: MCLK = 32 MHz (CLK32)
100: VIDEL IN = 32 MHz (VID32MHZ), 25 MHz (25K)
101: COMBEL IN = 32 MHz (CLK32) OUT = 4 MHz (CLK4), 500 kHz (KHZ500)
102: BUS = 16 MHz
103:
104: CPU 68030 IN = 16 MHz (CPUCLKB)
105: FPU 68882 IN = 16 MHz (CPUCLKA)
106: DMA IN = 8 MHz (CLK8)
107: CODEC IN = 25 MHz (25K)
108: MFP 68901 IN = 4 MHz (CLK4), 2.4576 MHz (external clock)
109: FDC AJAX IN = 16 MHz (FCCLK)
110: BLITTER IN = 16 MHz
111: YM3439 IN = 2 MHz (CLK2)
112: ACIA MC6850 IN = 500 kHz (KHZ500)
113: IKBD HD6301 IN = 1 MHZ (local clock)
114:
115: DSP 56001 IN = 32 MHz (DSP_32M)
116:
117: */
118:
119:
120: const char ClocksTimings_fileid[] = "Hatari clocks_timings.c : " __DATE__ " " __TIME__;
121:
122: #include <SDL.h>
123: #include <SDL_endian.h>
124:
125: #include "main.h"
126: #include "configuration.h"
127: #include "log.h"
128: #include "clocks_timings.h"
1.1.1.4 ! root 129: #include "m68000.h"
1.1 root 130:
131:
132:
133: /* The possible master frequencies used in the different machines */
134: /* depending on PAL/NTSC version. */
135:
136: #define ATARI_STF_PAL_MCLK 32084988 /* CPU_Freq = 8.021247 MHz */
137: #define ATARI_STF_NTSC_MCLK 32042400 /* CPU_Freq = 8.010600 MHz */
138: #define ATARI_STF_CYCLES_PER_VBL_PAL 160256 /* 512 cycles * 313 lines */
139: #define ATARI_STF_CYCLES_PER_VBL_NTSC 133604 /* 508 cycles * 263 lines */
140: #define ATARI_STF_CYCLES_PER_VBL_HI 112224 /* 224 cycles * 501 lines */
141:
142: #define ATARI_STE_PAL_MCLK 32084988 /* CPU_Freq = 8.021247 MHz */
143: #define ATARI_STE_NTSC_MCLK 32215905 /* CPU_Freq = 8.05397625 MHz */
144: #define ATARI_STE_EXT_OSC 8010613 /* OSC U303 */
145: #define ATARI_STE_CYCLES_PER_VBL_PAL 160256 /* 512 cycles * 313 lines */
146: #define ATARI_STE_CYCLES_PER_VBL_NTSC 133604 /* 508 cycles * 263 lines */
147: #define ATARI_STE_CYCLES_PER_VBL_HI 112224 /* 224 cycles * 501 lines */
148:
149: #define ATARI_MEGA_STE_PAL_MCLK 32084988 /* CPU_Freq = 16.042494 MHz */
150: #define ATARI_MEGA_STE_NTSC_MCLK 32215905 /* CPU_Freq = 16.1079525 MHz */
151: #define ATARI_MEGA_STE_EXT_OSC 16021226 /* OSC U408 */
152:
153: #define ATARI_TT_PAL_MCLK 32084988 /* CPU_Freq = 32.084988 MHz */
154: #define ATARI_TT_NTSC_MCLK 32215905 /* CPU_Freq = 32.215905 MHz */
155:
156: #define ATARI_FALCON_PAL_MCLK 32084988 /* CPU_Freq = 16.042494 MHz */
157: #define ATARI_FALCON_NTSC_MCLK 32215905 /* CPU_Freq = 16.1079525 MHz */
158: #define ATARI_FALCON_25M_CLK 25175000
159:
160: #define ATARI_MFP_XTAL 2457600 /* external clock for the MFP */
161: #define ATARI_IKBD_CLK 1000000 /* clock of the HD6301 ikbd cpu */
162:
163:
164:
165: CLOCKS_STRUCT MachineClocks;
166:
167:
168: bool RoundVBLPerSec = false; /* if false, don't round number of VBL to 50/60 Hz */
169: /* but compute the exact value based on cpu/video clocks */
170:
171:
172:
173:
174: /*--------------------------------------------------------------------------*/
175: /**
176: * Initialize all the clocks informations related to a specific machine type.
177: * We consider the machine is running with PAL clocks.
178: */
179:
180: void ClocksTimings_InitMachine ( MACHINETYPE MachineType )
181: {
1.1.1.4 ! root 182: //fprintf ( stderr , "clock init mach=%d shift=%d\n" , MachineType , nCpuFreqShift );
1.1 root 183: memset ( (void *)&MachineClocks , 0 , sizeof ( MachineClocks ) );
184:
1.1.1.3 root 185: if (MachineType == MACHINE_ST || MachineType == MACHINE_MEGA_ST)
1.1 root 186: {
187: int CLK16, CLK8, CLK4, CLK2, CLK500;
188:
189: MachineClocks.MCLK_Freq = ATARI_STF_PAL_MCLK; /* 32.084988 MHz */
190:
191: MachineClocks.SHIFTER_Freq = MachineClocks.MCLK_Freq; /* 32 MHz */
192: CLK16 = MachineClocks.SHIFTER_Freq / 2;
193:
194: MachineClocks.MMU_Freq = CLK16; /* 16 MHz */
195: CLK8 = MachineClocks.MMU_Freq / 2;
196: CLK4 = MachineClocks.MMU_Freq / 4;
197:
198: MachineClocks.GLUE_Freq = CLK8; /* 8 MHz */
199: CLK2 = MachineClocks.GLUE_Freq / 4;
200: CLK500 = MachineClocks.GLUE_Freq / 16;
201:
202: MachineClocks.BUS_Freq = CLK8; /* 8 MHz */
203:
204: MachineClocks.CPU_Freq = CLK8; /* 8 MHz */
205: MachineClocks.DMA_Freq = CLK8; /* 8 MHz */
206: MachineClocks.MFP_Freq = CLK4; /* 4 MHz */
207: MachineClocks.MFP_Timer_Freq = ATARI_MFP_XTAL; /* 2.4576 MHz (XTAL)*/
208: MachineClocks.FDC_Freq = CLK8; /* 8 MHz */
209: MachineClocks.BLITTER_Freq = CLK8; /* 8 MHz */
210: MachineClocks.YM_Freq = CLK2; /* 2 MHz */;
211: MachineClocks.ACIA_Freq = CLK500; /* 500 kHz */
212: MachineClocks.IKBD_Freq = ATARI_IKBD_CLK; /* 1 MHz */
213: }
214:
215: else if ( MachineType == MACHINE_STE )
216: {
217: int SCLK, CLK16, CLK8, CLK4, CLK2, KHZ500;
218: //int FCLK; /* not used (audio filters) */
219:
220: MachineClocks.MCLK_Freq = ATARI_STE_PAL_MCLK; /* 32.084988 MHz */
221: SCLK = ATARI_STE_EXT_OSC; /* 8.010613 MHz (SCLK) */
222: CLK2 = SCLK / 4;
223:
224: MachineClocks.SHIFTER_Freq = MachineClocks.MCLK_Freq; /* 32 MHz */
225: CLK16 = MachineClocks.SHIFTER_Freq / 2;
226: //FCLK = SCLK;
227:
228: MachineClocks.MCU_Freq = CLK16; /* 16 MHz */
229: CLK8 = MachineClocks.MCU_Freq / 2;
230: CLK4 = MachineClocks.MCU_Freq / 4;
231: KHZ500 = MachineClocks.MCU_Freq / 32;
232:
233: MachineClocks.BUS_Freq = CLK8; /* 8 MHz (CLK8) */
234:
235: MachineClocks.CPU_Freq = CLK8; /* 8 MHz (CLK8) */
236: MachineClocks.DMA_Freq = CLK8; /* 8 MHz (CLK8) */
237: MachineClocks.DMA_Audio_Freq = SCLK; /* 8 MHz (SCLK) */
238: MachineClocks.MFP_Freq = CLK4; /* 4 MHz (CLK4) */
239: MachineClocks.MFP_Timer_Freq = ATARI_MFP_XTAL; /* 2.4576 MHz (XTAL)*/
240: MachineClocks.FDC_Freq = SCLK; /* 8 MHz (SCLK) */
241: MachineClocks.BLITTER_Freq = CLK8; /* 8 MHz (CLK8) */
242: MachineClocks.YM_Freq = CLK2; /* 2 MHz (CLK2) */
243: MachineClocks.ACIA_Freq = KHZ500; /* 500 kHz (KHZ500) */
244: MachineClocks.IKBD_Freq = ATARI_IKBD_CLK; /* 1 MHz */
245: }
246:
247: else if ( MachineType == MACHINE_MEGA_STE )
248: {
249: int SCLK, CLK16, CLK8, CLK4, CLK2, KHZ500;
250: //int FCLK; /* not used (audio filters) */
251:
252: MachineClocks.MCLK_Freq = ATARI_MEGA_STE_PAL_MCLK; /* 32.084988 MHz */
253: SCLK = ATARI_MEGA_STE_EXT_OSC / 2; /* 16.021226 MHz / 2 = 8.010613 MHz */
254: CLK2 = SCLK / 4;
255:
256: MachineClocks.SHIFTER_Freq = MachineClocks.MCLK_Freq; /* 32 MHz */
257: CLK16 = MachineClocks.SHIFTER_Freq / 2;
258: //FCLK = SCLK;
259:
260: MachineClocks.MCU_Freq = CLK16; /* 16 MHz (CLK16) */
261: CLK8 = MachineClocks.MCU_Freq / 2;
262: CLK4 = MachineClocks.MCU_Freq / 4;
263: KHZ500 = MachineClocks.MCU_Freq / 32;
264:
265: MachineClocks.BUS_Freq = CLK8; /* 8 MHz (CLK8) */
266:
1.1.1.3 root 267: /* Special case : the Mega STE has an internal 16 MHz CPU clock */
268: /* but it can be set to 8 MHz for compatibility with STE using $FF8E21 */
1.1.1.4 ! root 269: MachineClocks.CPU_Freq = CLK16; /* 16 MHz (CLK16) */
1.1 root 270: MachineClocks.FPU_Freq = CLK16; /* 16 MHz (CLK16) */
271: MachineClocks.DMA_Freq = CLK8; /* 8 MHz (CLK8) */
272: MachineClocks.DMA_Audio_Freq = SCLK; /* 8 MHz (SCLK) */
273: MachineClocks.MFP_Freq = CLK4; /* 4 MHz (CLK4) */
274: MachineClocks.MFP_Timer_Freq = ATARI_MFP_XTAL; /* 2.4576 MHz (XTAL)*/
275: MachineClocks.FDC_Freq = SCLK; /* 8 MHz (SCLK) */
276: MachineClocks.BLITTER_Freq = CLK8; /* 8 MHz (CLK8) */
277: MachineClocks.YM_Freq = CLK2; /* 2 MHz (CLK2) */
278: MachineClocks.ACIA_Freq = KHZ500; /* 500 kHz (KHZ500) */
279: MachineClocks.IKBD_Freq = ATARI_IKBD_CLK; /* 1 MHz */
280: }
281:
282: else if ( MachineType == MACHINE_TT )
283: {
284: int CLK32, CLK16, CLK8, FCCLK, CLK4, CLK2, CLKX5;
285:
286: MachineClocks.MCLK_Freq = ATARI_TT_PAL_MCLK; /* 32.084988 MHz */
287: CLK32 = MachineClocks.MCLK_Freq;
288:
289: MachineClocks.TTVIDEO_Freq = MachineClocks.MCLK_Freq; /* 32 MHz */
290: CLK16 = MachineClocks.TTVIDEO_Freq / 2;
291: CLK4 = MachineClocks.TTVIDEO_Freq / 8;
292: CLK2 = MachineClocks.TTVIDEO_Freq / 16;
293:
294: MachineClocks.MCU_Freq = CLK16; /* 16 MHz (CLK16A) */
295: CLK8 = MachineClocks.MCU_Freq / 2;
296: FCCLK = MachineClocks.MCU_Freq / 2;
297: CLKX5 = MachineClocks.MCU_Freq / 32;
298:
299: MachineClocks.BUS_Freq = CLK16; /* 16 MHz (CLK16) */
300:
301: MachineClocks.CPU_Freq = CLK32; /* 32 MHz (CLK32) */
302: MachineClocks.FPU_Freq = CLK32; /* 32 MHz (CLK32) */
303: MachineClocks.DMA_Freq = CLK8; /* 8 MHz (CLK8) */
304: MachineClocks.DMA_Audio_Freq = CLK16; /* 16 MHz (CLK16) SND SHIFTER */
305: MachineClocks.MFP_Freq = CLK4; /* 4 MHz (CLK4) */
306: MachineClocks.MFP_Timer_Freq = ATARI_MFP_XTAL; /* 2.4576 MHz (XTAL)*/
307: MachineClocks.FDC_Freq = FCCLK; /* 8 MHz (FCCLK) */
308: MachineClocks.BLITTER_Freq = 0; /* No blitter in TT */
309: MachineClocks.YM_Freq = CLK2; /* 2 MHz (CLK2) */
310: MachineClocks.ACIA_Freq = CLKX5; /* 500 kHz (CLKX5) */
311: MachineClocks.IKBD_Freq = ATARI_IKBD_CLK; /* 1 MHz */
312: }
313:
314: else if ( MachineType == MACHINE_FALCON )
315: {
316: /* TODO : need more docs for Falcon's clocks */
317: int CLK32, CLK25, CLK16, FCCLK, CLK4, CLK2, KHZ500;
318:
319: MachineClocks.MCLK_Freq = ATARI_FALCON_PAL_MCLK; /* 32.084988 MHz */
320: CLK32 = MachineClocks.MCLK_Freq;
321: CLK25 = ATARI_FALCON_25M_CLK;
322: CLK16 = CLK32 / 2;
323: CLK2 = CLK32 / 16;
324: FCCLK = CLK16;
325:
326: MachineClocks.VIDEL_Freq = CLK32; /* 32 MHz */
327:
328: MachineClocks.COMBEL_Freq = CLK32; /* 16 MHz (CLK16A) */
329: CLK4 = MachineClocks.COMBEL_Freq / 8;
330: KHZ500 = MachineClocks.COMBEL_Freq / 64;
331:
332: MachineClocks.BUS_Freq = CLK16; /* 16 MHz (CPUCLK16A) */
333: MachineClocks.CPU_Freq = CLK16; /* 16 MHz (CPUCLK16B) */
334: MachineClocks.FPU_Freq = CLK16; /* 16 MHz (CLK32) */
335: MachineClocks.DSP_Freq = CLK32; /* 32 MHz */
336: MachineClocks.DMA_Freq = CLK16; /* 16 MHz (CLK16) ? */
337: MachineClocks.CODEC_Freq = CLK25; /* 25 MHz (CLK25) */
338: MachineClocks.MFP_Freq = CLK4; /* 4 MHz (CLK4) */
339: MachineClocks.MFP_Timer_Freq = ATARI_MFP_XTAL; /* 2.4576 MHz (XTAL)*/
340: MachineClocks.FDC_Freq = FCCLK; /* 16 MHz (FCCLK) ? */
341: MachineClocks.BLITTER_Freq = CLK16; /* 16 MHz */
342: MachineClocks.YM_Freq = CLK2; /* 2 MHz (CLK2) */
343: MachineClocks.ACIA_Freq = KHZ500; /* 500 kHz (KHZ500) */
344: MachineClocks.IKBD_Freq = ATARI_IKBD_CLK; /* 1 MHz */
345: }
346:
347:
1.1.1.4 ! root 348: /* Update some other variables depending on the current nCpuFreqShift */
! 349: ClocksTimings_UpdateCpuFreqEmul ( MachineType , nCpuFreqShift );
1.1 root 350: }
351:
352:
353:
354:
355: /*-----------------------------------------------------------------------------------------*/
356: /**
1.1.1.4 ! root 357: * Update the number of emulated cycles per second for the current CPU settings, depending on the
! 358: * base CPU freq in MachineClocks.CPU_Freq and nCpuFreqShift
! 359: *
! 360: * We use CPU_Freq as a base (instead of fixed values of 8, 16 or 32 MHz) to handle different CPU
! 361: * clocks in case the machine is a PAL or NTSC model for example (in which cases CPU_Freq
! 362: * values are slightly different)
1.1 root 363: */
1.1.1.4 ! root 364: void ClocksTimings_UpdateCpuFreqEmul ( MACHINETYPE MachineType , int nCpuFreqShift )
! 365: {
! 366: Uint32 Cpu_Freq_Emul;
! 367:
! 368: Cpu_Freq_Emul = MachineClocks.CPU_Freq;
! 369:
! 370: /* Machines where the base CPU is 8 MHz */
! 371: if (MachineType == MACHINE_ST || MachineType == MACHINE_MEGA_ST
! 372: || MachineType == MACHINE_STE)
! 373: {
! 374: Cpu_Freq_Emul <<= nCpuFreqShift; /* 8, 16 or 32 MHz */
! 375: }
! 376:
! 377: /* Machines where the base CPU is 16 MHz */
! 378: else if (MachineType == MACHINE_MEGA_STE || MachineType == MACHINE_FALCON )
! 379: {
! 380: if ( nCpuFreqShift == 0 ) Cpu_Freq_Emul >>= 1; /* 8 MHz */
! 381: else if ( nCpuFreqShift == 2 ) Cpu_Freq_Emul <<= 1; /* 32 MHz */
! 382: }
! 383:
! 384: /* Machines where the base CPU is 32 MHz */
! 385: else if (MachineType == MACHINE_TT )
! 386: {
! 387: if ( nCpuFreqShift == 0 ) Cpu_Freq_Emul >>= 2; /* 8 MHz */
! 388: else if ( nCpuFreqShift == 1 ) Cpu_Freq_Emul >>= 1; /* 16 MHz */
! 389: }
1.1 root 390:
1.1.1.4 ! root 391: MachineClocks.CPU_Freq_Emul = Cpu_Freq_Emul;
! 392: //fprintf ( stderr , "clock cpu freq mach=%d shift=%d base=%d -> %d\n" , MachineType , nCpuFreqShift , MachineClocks.CPU_Freq , MachineClocks.CPU_Freq_Emul );
! 393: }
! 394:
! 395:
! 396:
! 397:
! 398: /*-----------------------------------------------------------------------------------------*/
! 399: /**
! 400: * Return the number of cycles per VBL, depending on the video settings and the simulated cpu freq.
! 401: * This value is only precisely known for STF/STE running at 50, 60 or 71 Hz.
! 402: * For the other machines, we return CPU_Freq_Emul / ScreenRefreshRate
! 403: */
1.1 root 404: Uint32 ClocksTimings_GetCyclesPerVBL ( MACHINETYPE MachineType , int ScreenRefreshRate )
405: {
406: Uint32 CyclesPerVBL;
407:
1.1.1.4 ! root 408: /* STF and STE have the same numbers of cycles per VBL (numbers are for an 8 MHz CPU) */
1.1.1.3 root 409: if (MachineType == MACHINE_ST || MachineType == MACHINE_MEGA_ST
410: || MachineType == MACHINE_STE || MachineType == MACHINE_MEGA_STE)
1.1 root 411: {
412: if ( ScreenRefreshRate == 50 )
413: CyclesPerVBL = ATARI_STF_CYCLES_PER_VBL_PAL;
414: else if ( ScreenRefreshRate == 60 )
415: CyclesPerVBL = ATARI_STF_CYCLES_PER_VBL_NTSC;
416: else if ( ScreenRefreshRate == 71 )
417: CyclesPerVBL = ATARI_STF_CYCLES_PER_VBL_HI;
418: else
1.1.1.4 ! root 419: CyclesPerVBL = MachineClocks.CPU_Freq / ScreenRefreshRate; /* unknown refresh rate, should not happen */
1.1 root 420:
1.1.1.4 ! root 421: /* At this point CyclesPerVBL is the number of cycles per VBL for a 8 MHz CPU */
! 422: /* We need to apply nCpuFreqShift to get the number of cycles at the currently simulated CPU speed (8, 16 or 32 MHz) */
! 423: CyclesPerVBL <<= nCpuFreqShift;
! 424: }
1.1 root 425:
1.1.1.4 ! root 426: /* For machines where cpu freq can be changed, the number of cycles per VBL is not constant */
! 427: else /* MACHINE_TT or MACHINE_FALCON */
! 428: CyclesPerVBL = MachineClocks.CPU_Freq_Emul / ScreenRefreshRate;
1.1 root 429:
1.1.1.4 ! root 430: //fprintf ( stderr , "clock cycles per vbl %d %d -> %d\n" , MachineType , ScreenRefreshRate , CyclesPerVBL );
1.1 root 431: return CyclesPerVBL;
432: }
433:
434:
435:
436:
437: /*-----------------------------------------------------------------------------------------*/
438: /**
1.1.1.4 ! root 439: * Return the number of VBL per second, depending on the video settings and the simulated cpu freq.
1.1 root 440: * Since the cpu freq is not an exact multiple of the number of cycles per VBL, the real
441: * value slightly differs from the usual 50/60 Hz.
1.1.1.4 ! root 442: * Precise (not rounded) values are needed in STE mode to synchronize cpu and dma sound (as they both use
1.1 root 443: * 2 different clocks).
444: * example for STF/STE :
445: * PAL STF/STE video PAL : 50.053 VBL/sec
446: * PAL STF/STE video NTSC : 60.037 VBL/sec
447: * NTSC STF/STE video PAL : 49.986 VBL/sec
448: * NTSC STF/STE video NTSC : 59.958 VBL/sec
449: *
450: * The returned number of VBL per sec is << 24 (=CLOCKS_TIMINGS_SHIFT_VBL) to simulate floating point using Uint32.
451: */
452: Uint32 ClocksTimings_GetVBLPerSec ( MACHINETYPE MachineType , int ScreenRefreshRate )
453: {
454: Uint32 VBLPerSec; /* Upper 8 bits are for int part, 24 lower bits for float part */
455:
456:
1.1.1.4 ! root 457: if ( RoundVBLPerSec == true )
1.1 root 458: {
1.1.1.4 ! root 459: VBLPerSec = ScreenRefreshRate << CLOCKS_TIMINGS_SHIFT_VBL;
1.1 root 460: }
461:
1.1.1.4 ! root 462: else
! 463: {
! 464: VBLPerSec = ( (Sint64)MachineClocks.CPU_Freq_Emul << CLOCKS_TIMINGS_SHIFT_VBL ) / ClocksTimings_GetCyclesPerVBL ( MachineType , ScreenRefreshRate );
! 465: }
1.1 root 466:
1.1.1.4 ! root 467: //fprintf ( stderr , "clock vbl per sec %d %d %d -> %d\n" , MachineType , MachineClocks.CPU_Freq_Emul , ScreenRefreshRate , VBLPerSec );
1.1 root 468: return VBLPerSec;
469: }
470:
471:
472:
473:
474: /*-----------------------------------------------------------------------------------------*/
475: /**
476: * Return the length in microsec of a VBL (opposite function of ClocksTimings_GetVBLPerSec)
477: * We use precise values only in STF/STE mode, else we use 1000000 / ScreenRefreshRate.
478: * example for STF/STE :
479: * PAL STF/STE video PAL : 19979 micro sec (instead of 20000 for 50 Hz)
480: * PAL STF/STE video NTSC : 16656 micro sec (instead of 16667 for 60 Hz)
481: */
482: Uint32 ClocksTimings_GetVBLDuration_micro ( MACHINETYPE MachineType , int ScreenRefreshRate )
483: {
484: Uint32 VBLDuration_micro;
485:
1.1.1.4 ! root 486: if ( RoundVBLPerSec == true )
1.1 root 487: {
1.1.1.4 ! root 488: VBLDuration_micro = (Uint32) (1000000.0 / ScreenRefreshRate + 0.5);
1.1 root 489: }
490:
1.1.1.4 ! root 491: else
! 492: {
! 493: VBLDuration_micro = (Uint32) (1000000.0 * ClocksTimings_GetCyclesPerVBL ( MachineType , ScreenRefreshRate ) / MachineClocks.CPU_Freq_Emul + 0.5);
! 494: }
1.1 root 495:
1.1.1.4 ! root 496: //fprintf ( stderr , "clock vbl duration %d %d %d -> %d\n" , MachineType , MachineClocks.CPU_Freq_Emul , ScreenRefreshRate , VBLDuration_micro );
1.1 root 497: return VBLDuration_micro;
498: }
499:
500:
501:
502:
503: /*-----------------------------------------------------------------------------------------*/
504: /**
505: * Return the number of samples needed to emulate the sound that was produced during one VBL.
506: * This depends on the chosen audio output frequency, as well as the VBL's duration,
507: *
508: * We use precise values only in STF/STE mode, else we use AudioFreq/ScreenRefreshRate.
509: *
510: * The returned number of samples per VBL is << 28 to simulate maximum precision using
511: * 64 bits integers (lower 28 bits are for the floating point part).
512: * example for STF/STE with emulation's audio freq = 44100 :
513: * PAL STF/STE video PAL : 881.07 samples per VBL (instead of 882 for 50 Hz)
514: * 44053.56 samples for 50 VBLs (instead of 44100 for 1 sec at 50 Hz)
515: */
516: Sint64 ClocksTimings_GetSamplesPerVBL ( MACHINETYPE MachineType , int ScreenRefreshRate , int AudioFreq )
517: {
518: Sint64 SamplesPerVBL;
519:
1.1.1.4 ! root 520: if ( RoundVBLPerSec == true )
1.1 root 521: {
1.1.1.4 ! root 522: SamplesPerVBL = ( ((Sint64)AudioFreq) << 28 ) / ScreenRefreshRate;
1.1 root 523: }
524:
1.1.1.4 ! root 525: else
! 526: {
! 527: SamplesPerVBL = ( ((Sint64)AudioFreq * ClocksTimings_GetCyclesPerVBL ( MachineType , ScreenRefreshRate ) ) << 28 ) / MachineClocks.CPU_Freq_Emul;
! 528: }
1.1 root 529:
1.1.1.4 ! root 530: //fprintf ( stderr , "clock sample per vbl %d %d %d -> %ld\n" , MachineType , MachineClocks.CPU_Freq_Emul , AudioFreq , SamplesPerVBL );
1.1 root 531: return SamplesPerVBL;
532: }
533:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.