2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
11 #include "../fileio.h"
13 #ifndef EVENT_CONTINUOUS_SOUND
14 //#ifdef PCM1BIT_HIGH_QUALITY
15 #define EVENT_CONTINUOUS_SOUND
19 void EVENT::initialize()
22 if(!(0 <= config.cpu_power && config.cpu_power <= 4)) {
25 power = config.cpu_power;
27 // initialize sound buffer
32 prev_skip = next_skip = false;
33 sound_changed = false;
36 void EVENT::initialize_sound(int rate, int samples)
40 sound_samples = samples;
41 #ifdef EVENT_CONTINUOUS_SOUND
42 sound_tmp_samples = samples * 2;
44 sound_tmp_samples = samples;
46 sound_buffer = (uint16*)malloc(sound_samples * sizeof(uint16) * 2);
47 memset(sound_buffer, 0, sound_samples * sizeof(uint16) * 2);
48 sound_tmp = (int32*)malloc(sound_tmp_samples * sizeof(int32) * 2);
49 memset(sound_tmp, 0, sound_tmp_samples * sizeof(int32) * 2);
50 buffer_ptr = accum_samples = 0;
66 // clear events except loop event
67 for(int i = 0; i < MAX_EVENT; i++) {
68 if(event[i].active && event[i].loop_clock == 0) {
69 cancel_event(NULL, i);
74 cpu_remain = cpu_accum = cpu_done = 0;
78 memset(sound_buffer, 0, sound_samples * sizeof(uint16) * 2);
81 memset(sound_tmp, 0, sound_tmp_samples * sizeof(int32) * 2);
86 initialize_done = true;
92 // raise pre frame events to update timing settings
93 for(int i = 0; i < frame_event_count; i++) {
94 frame_event[i]->event_pre_frame();
97 // generate clocks per line
98 if(frames_per_sec != next_frames_per_sec || lines_per_frame != next_lines_per_frame) {
99 frames_per_sec = next_frames_per_sec;
100 lines_per_frame = next_lines_per_frame;
102 int sum = (int)((double)d_cpu[0].cpu_clocks / frames_per_sec + 0.5);
105 for(int i = 0; i < lines_per_frame; i++) {
106 vclocks[i] = (int)(sum / lines_per_frame);
107 remain -= vclocks[i];
109 for(int i = 0; i < remain; i++) {
110 int index = (int)((double)lines_per_frame * (double)i / (double)remain);
113 for(int i = 1; i < dcount_cpu; i++) {
114 d_cpu[i].update_clocks = (int)(1024.0 * (double)d_cpu[i].cpu_clocks / (double)d_cpu[0].cpu_clocks + 0.5);
116 for(DEVICE* device = vm->first_device; device; device = device->next_device) {
117 if(device->event_manager_id() == this_device_id) {
118 device->update_timing(d_cpu[0].cpu_clocks, frames_per_sec, lines_per_frame);
121 update_samples = (int)(1024.0 * (double)sound_rate / frames_per_sec / (double)lines_per_frame + 0.5);
124 // run virtual machine for 1 frame period
125 for(int i = 0; i < frame_event_count; i++) {
126 frame_event[i]->event_frame();
128 for(int v = 0; v < lines_per_frame; v++) {
129 // run virtual machine per line
130 for(int i = 0; i < vline_event_count; i++) {
131 vline_event[i]->event_vline(v, vclocks[v]);
134 if(event_remain < 0) {
135 if(-event_remain > vclocks[v]) {
136 update_event(vclocks[v]);
138 update_event(-event_remain);
141 event_remain += vclocks[v];
142 cpu_remain += vclocks[v] << power;
144 while(event_remain > 0) {
145 int event_done = event_remain;
147 // run one opecode on primary cpu
149 if(dcount_cpu == 1) {
150 cpu_done_tmp = d_cpu[0].device->run(-1);
154 cpu_done = d_cpu[0].device->run(-1);
156 cpu_done_tmp = (cpu_done < 4) ? cpu_done : 4;
157 cpu_done -= cpu_done_tmp;
159 for(int i = 1; i < dcount_cpu; i++) {
161 d_cpu[i].accum_clocks += d_cpu[i].update_clocks * cpu_done_tmp;
162 int sub_clock = d_cpu[i].accum_clocks >> 10;
164 d_cpu[i].accum_clocks -= sub_clock << 10;
165 d_cpu[i].device->run(sub_clock);
169 cpu_remain -= cpu_done_tmp;
170 cpu_accum += cpu_done_tmp;
171 event_done = cpu_accum >> power;
172 cpu_accum -= event_done << power;
175 if(event_done > event_remain) {
176 update_event(event_remain);
178 update_event(event_done);
180 event_remain -= event_done;
187 void EVENT::update_event(int clock)
189 uint64 event_clocks_tmp = event_clocks + clock;
191 while(first_fire_event != NULL && first_fire_event->expired_clock <= event_clocks_tmp) {
192 event_t *event_handle = first_fire_event;
193 uint64 expired_clock = event_handle->expired_clock;
195 first_fire_event = event_handle->next;
196 if(first_fire_event != NULL) {
197 first_fire_event->prev = NULL;
199 if(event_handle->loop_clock != 0) {
200 event_handle->expired_clock += event_handle->loop_clock;
201 insert_event(event_handle);
203 event_handle->active = false;
204 event_handle->next = first_free_event;
205 first_free_event = event_handle;
207 event_clocks = expired_clock;
208 event_handle->device->event_callback(event_handle->event_id, 0);
210 event_clocks = event_clocks_tmp;
213 uint32 EVENT::current_clock()
215 return (uint32)(event_clocks & 0xffffffff);
218 uint32 EVENT::passed_clock(uint32 prev)
220 uint32 current = current_clock();
221 return (current > prev) ? current - prev : current + (0xffffffff - prev) + 1;
224 double EVENT::passed_usec(uint32 prev)
226 return 1000000.0 * passed_clock(prev) / d_cpu[0].cpu_clocks;
229 uint32 EVENT::get_cpu_pc(int index)
231 return d_cpu[index].device->get_pc();
234 void EVENT::register_event(DEVICE* device, int event_id, double usec, bool loop, int* register_id)
236 int clock = (int)((double)d_cpu[0].cpu_clocks / 1000000.0 * usec + 0.5);
237 register_event_by_clock(device, event_id, clock, loop, register_id);
240 void EVENT::register_event_by_clock(DEVICE* device, int event_id, int clock, bool loop, int* register_id)
243 if(!initialize_done && !loop) {
244 emu->out_debug_log(_T("EVENT: non-loop event is registered before initialize is done\n"));
249 if(first_free_event == NULL) {
251 emu->out_debug_log(_T("EVENT: too many events !!!\n"));
253 if(register_id != NULL) {
258 event_t *event_handle = first_free_event;
259 first_free_event = first_free_event->next;
261 if(register_id != NULL) {
262 *register_id = event_handle->index;
264 event_handle->active = true;
265 event_handle->device = device;
266 event_handle->event_id = event_id;
267 event_handle->expired_clock = event_clocks + clock;
268 event_handle->loop_clock = loop ? clock : 0;
270 insert_event(event_handle);
273 void EVENT::insert_event(event_t *event_handle)
275 if(first_fire_event == NULL) {
276 first_fire_event = event_handle;
277 event_handle->prev = event_handle->next = NULL;
279 for(event_t *insert_pos = first_fire_event; insert_pos != NULL; insert_pos = insert_pos->next) {
280 if(insert_pos->expired_clock > event_handle->expired_clock) {
281 if(insert_pos->prev != NULL) {
283 insert_pos->prev->next = event_handle;
284 event_handle->prev = insert_pos->prev;
285 event_handle->next = insert_pos;
286 insert_pos->prev = event_handle;
290 first_fire_event = event_handle;
291 event_handle->prev = NULL;
292 event_handle->next = insert_pos;
293 insert_pos->prev = event_handle;
296 } else if(insert_pos->next == NULL) {
298 insert_pos->next = event_handle;
299 event_handle->prev = insert_pos;
300 event_handle->next = NULL;
307 void EVENT::cancel_event(DEVICE* device, int register_id)
309 // cancel registered event
310 if(0 <= register_id && register_id < MAX_EVENT) {
311 event_t *event_handle = &event[register_id];
312 if(device != NULL && device != event_handle->device) {
313 emu->out_debug_log("EVENT: event cannot be canceled by non ownew device (id=%d) !!!\n", device->this_device_id);
316 if(event_handle->active) {
317 if(event_handle->prev != NULL) {
318 event_handle->prev->next = event_handle->next;
320 first_fire_event = event_handle->next;
322 if(event_handle->next != NULL) {
323 event_handle->next->prev = event_handle->prev;
325 event_handle->active = false;
326 event_handle->next = first_free_event;
327 first_free_event = event_handle;
332 void EVENT::register_frame_event(DEVICE* dev)
334 if(frame_event_count < MAX_EVENT) {
335 frame_event[frame_event_count++] = dev;
338 emu->out_debug_log(_T("EVENT: too many frame events !!!\n"));
343 void EVENT::register_vline_event(DEVICE* dev)
345 if(vline_event_count < MAX_EVENT) {
346 vline_event[vline_event_count++] = dev;
349 emu->out_debug_log(_T("EVENT: too many vline events !!!\n"));
354 void EVENT::mix_sound(int samples)
357 int32* buffer = sound_tmp + buffer_ptr * 2;
358 memset(buffer, 0, samples * sizeof(int32) * 2);
359 for(int i = 0; i < dcount_sound; i++) {
360 d_sound[i]->mix(buffer, samples);
363 for(int i = 0; i < samples * 2; i += 2) {
364 if(buffer[i] != sound_tmp[0] || buffer[i + 1] != sound_tmp[1]) {
365 sound_changed = true;
370 buffer_ptr += samples;
372 // notify to sound devices
373 for(int i = 0; i < dcount_sound; i++) {
374 d_sound[i]->mix(sound_tmp + buffer_ptr * 2, 0);
379 void EVENT::update_sound()
381 accum_samples += update_samples;
382 int samples = accum_samples >> 10;
383 accum_samples -= samples << 10;
386 if(prev_skip && dont_skip_frames == 0 && !sound_changed) {
389 if(samples > sound_tmp_samples - buffer_ptr) {
390 samples = sound_tmp_samples - buffer_ptr;
395 uint16* EVENT::create_sound(int* extra_frames)
397 if(prev_skip && dont_skip_frames == 0 && !sound_changed) {
398 memset(sound_buffer, 0, sound_samples * sizeof(uint16) * 2);
404 #ifdef EVENT_CONTINUOUS_SOUND
405 // drive extra frames to fill the sound buffer
406 while(sound_samples > buffer_ptr) {
412 int samples = sound_samples - buffer_ptr;
415 #ifdef LOW_PASS_FILTER
417 for(int i = 0; i < sound_samples - 1; i++) {
418 sound_tmp[i * 2 ] = (sound_tmp[i * 2 ] + sound_tmp[i * 2 + 2]) / 2; // L
419 sound_tmp[i * 2 + 1] = (sound_tmp[i * 2 + 1] + sound_tmp[i * 2 + 3]) / 2; // R
423 for(int i = 0; i < sound_samples * 2; i++) {
424 int dat = sound_tmp[i];
425 uint16 highlow = (uint16)(dat & 0x0000ffff);
427 if((dat > 0) && (highlow >= 0x8000)) {
428 sound_buffer[i] = 0x7fff;
431 if((dat < 0) && (highlow < 0x8000)) {
432 sound_buffer[i] = 0x8000;
435 sound_buffer[i] = highlow;
437 if(buffer_ptr > sound_samples) {
438 buffer_ptr -= sound_samples;
439 memcpy(sound_tmp, sound_tmp + sound_samples * 2, buffer_ptr * sizeof(int32) * 2);
443 *extra_frames = frames;
447 int EVENT::sound_buffer_ptr()
452 void EVENT::request_skip_frames()
457 bool EVENT::now_skip()
459 bool value = next_skip;
461 if(sound_changed || (prev_skip && !next_skip)) {
462 dont_skip_frames = (int)frames_per_sec;
464 if(dont_skip_frames > 0) {
468 prev_skip = next_skip;
470 sound_changed = false;
475 void EVENT::update_config()
477 if(power != config.cpu_power) {
478 power = config.cpu_power;
483 #define STATE_VERSION 1
485 void EVENT::save_state(FILEIO* state_fio)
487 state_fio->FputUint32(STATE_VERSION);
488 state_fio->FputInt32(this_device_id);
490 state_fio->FputInt32(dcount_cpu);
491 for(int i = 0; i < dcount_cpu; i++) {
492 state_fio->FputInt32(d_cpu[i].cpu_clocks);
493 state_fio->FputInt32(d_cpu[i].update_clocks);
494 state_fio->FputInt32(d_cpu[i].accum_clocks);
496 state_fio->Fwrite(vclocks, sizeof(vclocks), 1);
497 state_fio->FputInt32(event_remain);
498 state_fio->FputInt32(cpu_remain);
499 state_fio->FputInt32(cpu_accum);
500 state_fio->FputInt32(cpu_done);
501 state_fio->FputUint64(event_clocks);
502 for(int i = 0; i < MAX_EVENT; i++) {
503 state_fio->FputInt32(event[i].device != NULL ? event[i].device->this_device_id : -1);
504 state_fio->FputInt32(event[i].event_id);
505 state_fio->FputUint64(event[i].expired_clock);
506 state_fio->FputUint32(event[i].loop_clock);
507 state_fio->FputBool(event[i].active);
508 state_fio->FputInt32(event[i].next != NULL ? event[i].next->index : -1);
509 state_fio->FputInt32(event[i].prev != NULL ? event[i].prev->index : -1);
511 state_fio->FputInt32(first_free_event != NULL ? first_free_event->index : -1);
512 state_fio->FputInt32(first_fire_event != NULL ? first_fire_event->index : -1);
513 state_fio->FputDouble(frames_per_sec);
514 state_fio->FputDouble(next_frames_per_sec);
515 state_fio->FputInt32(lines_per_frame);
516 state_fio->FputInt32(next_lines_per_frame);
519 bool EVENT::load_state(FILEIO* state_fio)
521 if(state_fio->FgetUint32() != STATE_VERSION) {
524 if(state_fio->FgetInt32() != this_device_id) {
527 if(state_fio->FgetInt32() != dcount_cpu) {
530 for(int i = 0; i < dcount_cpu; i++) {
531 d_cpu[i].cpu_clocks = state_fio->FgetInt32();
532 d_cpu[i].update_clocks = state_fio->FgetInt32();
533 d_cpu[i].accum_clocks = state_fio->FgetInt32();
535 state_fio->Fread(vclocks, sizeof(vclocks), 1);
536 event_remain = state_fio->FgetInt32();
537 cpu_remain = state_fio->FgetInt32();
538 cpu_accum = state_fio->FgetInt32();
539 cpu_done = state_fio->FgetInt32();
540 event_clocks = state_fio->FgetUint64();
541 for(int i = 0; i < MAX_EVENT; i++) {
542 event[i].device = vm->get_device(state_fio->FgetInt32());
543 event[i].event_id = state_fio->FgetInt32();
544 event[i].expired_clock = state_fio->FgetUint64();
545 event[i].loop_clock = state_fio->FgetUint32();
546 event[i].active = state_fio->FgetBool();
547 event[i].next = (event_t *)get_event(state_fio->FgetInt32());
548 event[i].prev = (event_t *)get_event(state_fio->FgetInt32());
550 first_free_event = (event_t *)get_event(state_fio->FgetInt32());
551 first_fire_event = (event_t *)get_event(state_fio->FgetInt32());
552 frames_per_sec = state_fio->FgetDouble();
553 next_frames_per_sec = state_fio->FgetDouble();
554 lines_per_frame = state_fio->FgetInt32();
555 next_lines_per_frame = state_fio->FgetInt32();
559 memset(sound_buffer, 0, sound_samples * sizeof(uint16) * 2);
562 memset(sound_tmp, 0, sound_tmp_samples * sizeof(int32) * 2);
564 buffer_ptr = accum_samples = 0;
565 update_samples = (int)(1024.0 * (double)sound_rate / frames_per_sec / (double)lines_per_frame + 0.5);
569 void* EVENT::get_event(int index)
571 if(index >= 0 && index < MAX_EVENT) {
572 return &event[index];