2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
22 #define MAX_LINES 1024
27 EVENT_CPUTYPE_GENERIC = 0,
29 EVENT_CPUTYPE_HUC6280,
40 EVENT_CPUTYPE_TMS9995,
41 EVENT_CPUTYPE_UPD7801,
44 class EVENT : public DEVICE
51 uint32_t update_clocks;
52 uint32_t accum_clocks;
56 uint32_t cpu_update_clocks[MAX_CPU][6];
57 uint32_t cpu_type[MAX_CPU];
61 int vclocks[MAX_LINES];
64 int cpu_remain, cpu_accum, cpu_done;
65 uint64_t event_clocks;
67 typedef struct event_t {
70 uint64_t expired_clock;
72 uint64_t accum_clocks;
78 event_t event[MAX_EVENT];
79 event_t *first_free_event;
80 event_t *first_fire_event;
82 DEVICE* frame_event[MAX_EVENT];
83 DEVICE* vline_event[MAX_EVENT];
84 int frame_event_count, vline_event_count;
86 double frames_per_sec, next_frames_per_sec;
87 int lines_per_frame, next_lines_per_frame;
88 uint32_t vline_start_clock;
91 void update_event(int clock);
92 void insert_event(event_t *event_handle);
95 DEVICE* d_sound[MAX_SOUND];
98 uint16_t* sound_buffer;
102 int sound_tmp_samples;
104 int dont_skip_frames;
105 bool prev_skip, next_skip;
110 bool dev_need_mix[MAX_DEVICE];
113 void mix_sound(int samples);
114 void* get_event(int index);
115 int run_cpu(uint32_t num, int cycles);
118 bool initialize_done;
121 void set_cpu_type(T *p, int num)
123 if((num < 0) || (num >= MAX_CPU)) return;
124 #if defined(USE_CPU_HD6301)
125 if(typeid(T) == typeid(HD6301)) {
126 cpu_type[num] = EVENT_CPUTYPE_HD6301;
129 #if defined(USE_CPU_HUC6280)
130 if(typeid(T) == typeid(HUC6280)) {
131 cpu_type[num] = EVENT_CPUTYPE_HUC6280;
134 #if defined(USE_CPU_I86) || defined(USE_CPU_I286) || defined(USE_CPU_I186) || defined(USE_CPU_V30)
135 if(typeid(T) == typeid(I286)) {
136 cpu_type[num] = EVENT_CPUTYPE_I286;
139 #if defined(USE_CPU_I386) || defined(USE_CPU_I486) || defined(USE_CPU_PENTIUM)
140 if(typeid(T) == typeid(I386)) {
141 cpu_type[num] = EVENT_CPUTYPE_I386;
144 #if defined(USE_CPU_I8080)
145 if(typeid(T) == typeid(I8080)) {
146 cpu_type[num] = EVENT_CPUTYPE_I8080;
149 #if defined(USE_CPU_M6502)
150 if(typeid(T) == typeid(M6502)) {
151 cpu_type[num] = EVENT_CPUTYPE_M6502;
154 #if defined(USE_CPU_N2A03)
155 if(typeid(T) == typeid(N2A03)) {
156 cpu_type[num] = EVENT_CPUTYPE_N2A03;
159 #if defined(USE_CPU_MB8861)
160 if(typeid(T) == typeid(MB8861)) {
161 cpu_type[num] = EVENT_CPUTYPE_MB8861;
164 #if defined(USE_CPU_MC6800)
165 if(typeid(T) == typeid(MC6800)) {
166 cpu_type[num] = EVENT_CPUTYPE_MC6800;
169 #if defined(USE_CPU_MC6801)
170 if(typeid(T) == typeid(MC6801)) {
171 cpu_type[num] = EVENT_CPUTYPE_MC6801;
174 #if defined(USE_CPU_MC6809)
175 if(typeid(T) == typeid(MC6809)) {
176 cpu_type[num] = EVENT_CPUTYPE_MC6809;
179 #if defined(USE_CPU_MCS48)
180 if(typeid(T) == typeid(MCS48)) {
181 cpu_type[num] = EVENT_CPUTYPE_MCS48;
184 #if defined(USE_CPU_TMS9995)
185 if(typeid(T) == typeid(TMS9995)) {
186 cpu_type[num] = EVENT_CPUTYPE_TMS9995;
189 #if defined(USE_CPU_UPD7801)
190 if(typeid(T) == typeid(UPD7801)) {
191 cpu_type[num] = EVENT_CPUTYPE_UPD7801;
194 #if defined(USE_CPU_Z80)
195 if(typeid(T) == typeid(Z80)) {
196 cpu_type[num] = EVENT_CPUTYPE_Z80;
200 cpu_type[num] = EVENT_CPUTYPE_GENERIC;
204 EVENT(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
206 dcount_cpu = dcount_sound = 0;
207 frame_event_count = vline_event_count = 0;
210 memset(event, 0, sizeof(event));
211 for(int i = 0; i < MAX_EVENT; i++) {
212 event[i].active = false;
214 event[i].next = (i + 1 < MAX_EVENT) ? &event[i + 1] : NULL;
216 first_free_event = &event[0];
217 first_fire_event = NULL;
221 // force update timing in the first frame
222 frames_per_sec = 0.0;
224 next_frames_per_sec = FRAMES_PER_SEC;
225 next_lines_per_frame = LINES_PER_FRAME;
226 // reset before other device may call set_realtime_render()
227 memset(dev_need_mix, 0, sizeof(dev_need_mix));
231 initialize_done = false;
233 for(int i = 0; i < MAX_CPU; i++) {
234 cpu_type[i] = EVENT_CPUTYPE_GENERIC;
236 set_device_name(_T("Event Manager"));
244 void event_callback(int event_id, int err);
245 void update_config();
247 void save_state(FILEIO* state_fio);
248 bool load_state(FILEIO* state_fio);
250 // common event functions
251 int get_event_manager_id()
253 return this_device_id;
255 void set_frames_per_sec(double new_frames_per_sec)
257 next_frames_per_sec = new_frames_per_sec;
259 void set_lines_per_frame(int new_lines_per_frame)
261 if(new_lines_per_frame < MAX_LINES) {
262 next_lines_per_frame = new_lines_per_frame;
265 int get_lines_per_frame()
267 return next_lines_per_frame;
269 void register_event(DEVICE* device, int event_id, double usec, bool loop, int* register_id);
270 void register_event_by_clock(DEVICE* device, int event_id, uint64_t clock, bool loop, int* register_id);
271 void cancel_event(DEVICE* device, int register_id);
272 void register_frame_event(DEVICE* device);
273 void register_vline_event(DEVICE* device);
274 uint32_t get_event_remaining_clock(int register_id);
275 double get_event_remaining_usec(int register_id);
276 uint32_t get_current_clock();
277 uint32_t get_passed_clock(uint32_t prev);
278 double get_passed_usec(uint32_t prev);
279 uint32_t get_passed_clock_since_vline();
280 double get_passed_usec_since_vline();
285 int get_cur_vline_clocks()
287 return vclocks[cur_vline];
289 uint32_t get_cpu_pc(int index);
290 void request_skip_frames();
292 void set_realtime_render(DEVICE* device, bool flag);
295 double get_frame_rate()
297 return next_frames_per_sec;
301 void initialize_sound(int rate, int samples);
302 uint16_t* create_sound(int* extra_frames);
303 int get_sound_buffer_ptr();
305 void set_context_cpu(T* device, uint32_t clocks = CPU_CLOCKS)
307 assert(dcount_cpu < MAX_CPU);
308 int index = dcount_cpu++;
309 d_cpu[index].device = (DEVICE *)device;
310 d_cpu[index].cpu_clocks = clocks;
311 d_cpu[index].accum_clocks = 0;
312 set_cpu_type(device, index);
313 for(int k = 0; k < 6; k++) cpu_update_clocks[index][k] = d_cpu[index].update_clocks * k;
315 void set_secondary_cpu_clock(DEVICE* device, uint32_t clocks)
317 // XXX: primary cpu clock should not be changed
318 for(int index = 1; index < dcount_cpu; index++) {
319 if(d_cpu[index].device == device) {
320 d_cpu[index].accum_clocks = 0;
321 d_cpu[index].cpu_clocks = clocks;
322 d_cpu[index].update_clocks = (int)(1024.0 * (double)d_cpu[index].cpu_clocks / (double)d_cpu[0].cpu_clocks + 0.5)
324 for(int k = 0; k < 6; k++) cpu_update_clocks[index][k] = d_cpu[index].update_clocks * k;
329 void set_context_sound(DEVICE* device)
331 assert(dcount_sound < MAX_SOUND);
332 d_sound[dcount_sound++] = device;
334 bool is_frame_skippable();
338 * Faster runncing cpu.
339 * Expect to optimize switch(...) - case to jump table.
340 * You should include real header of CPU DEVICE begin of this file.