2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
11 * BELOW INCLUDES ARE for run_cpu().
12 * ToDo: Minimum include.
16 #if defined(USE_CPU_HD6301)
20 #if defined(USE_CPU_HUC6280)
24 #if defined(USE_CPU_I86) || defined(USE_CPU_I286) || defined(USE_CPU_I186) || defined(USE_CPU_V30)
28 #if defined(USE_CPU_I386) || defined(USE_CPU_I486) || defined(USE_CPU_PENTIUM)
32 #if defined(USE_CPU_I8080)
36 #if defined(USE_CPU_M6502) || defined(USE_CPU_N2A03)
40 #if defined(USE_CPU_MB8861)
44 #if defined(USE_CPU_MC6800)
48 #if defined(USE_CPU_MC6801)
52 #if defined(USE_CPU_MC6809)
56 #if defined(USE_CPU_MCS48)
60 #if defined(USE_CPU_TMS9995)
64 #if defined(USE_CPU_UPD7801)
68 #if defined(USE_CPU_Z80)
77 void EVENT::initialize()
81 if(!(0 <= config.cpu_power && config.cpu_power <= 4)) {
84 power = config.cpu_power;
86 // initialize sound buffer
91 prev_skip = next_skip = false;
92 sound_changed = false;
95 frame_clocks = (int)((double)d_cpu[0].cpu_clocks / (double)FRAMES_PER_SEC + 0.5);
96 vline_start_clock = 0;
98 vline_clocks[0] = (int)((double)d_cpu[0].cpu_clocks / (double)FRAMES_PER_SEC / (double)LINES_PER_FRAME + 0.5);
101 void EVENT::initialize_sound(int rate, int samples)
104 sound_samples = samples;
105 sound_tmp_samples = samples * 2;
106 sound_buffer = (uint16_t*)malloc(sound_samples * sizeof(uint16_t) * 2);
107 memset(sound_buffer, 0, sound_samples * sizeof(uint16_t) * 2);
108 sound_tmp = (int32_t*)malloc(sound_tmp_samples * sizeof(int32_t) * 2);
109 memset(sound_tmp, 0, sound_tmp_samples * sizeof(int32_t) * 2);
112 mix_limit = (int)((double)(emu->get_sound_rate() / 2000.0)); // per 0.5ms.
114 for(int i = 0; i < MAX_SOUND_IN_BUFFERS; i++) {
115 if(sound_in_rate[i] != rate) {
116 release_sound_in_source(i);
117 sound_in_samples[i] = samples;
119 if((sound_in_samples[i] > 0) && (sound_in_channels[i] > 0)) {
120 if(sound_in_tmp_buffer[i] == NULL) {
121 sound_in_tmp_buffer[i] = (int16_t*)malloc(sound_in_samples[i] * sound_in_channels[i] * sizeof(int16_t));
122 if(sound_in_tmp_buffer[i] != NULL) {
123 clear_sound_in_source(i);
128 // ToDo: UnLock Mutex
130 this->register_event(this, EVENT_MIX, 1000000.0 / rate, true, NULL);
133 void EVENT::clear_sound_in_source(int bank)
136 if(bank >= MAX_SOUND_IN_BUFFERS) return;
138 if(sound_in_tmp_buffer[bank] == NULL) return;
139 if(sound_in_samples[bank] <= 0) return;
140 if(sound_in_channels[bank] <= 0) return;
141 memset(sound_in_tmp_buffer[bank], 0x00, sound_in_samples[bank] * sound_in_channels[bank] * sizeof(int16_t));
144 int EVENT::add_sound_in_source(int rate, int samples, int channels)
147 for(banknum = 0; banknum < MAX_SOUND_IN_BUFFERS; banknum++) {
148 if(sound_in_samples[banknum] == 0) break;
150 if(banknum < MAX_SOUND_IN_BUFFERS) {
152 if(sound_in_tmp_buffer[banknum] != NULL) free(sound_in_tmp_buffer[banknum]);
153 sound_in_tmp_buffer[banknum] = NULL;
154 if((rate > 0) && (samples > 0)) {
155 sound_in_rate[banknum] = rate;
156 sound_in_samples[banknum] = samples;
157 sound_in_channels[banknum] = channels;
158 sound_in_tmp_buffer[banknum] = (int16_t*)malloc(samples * sizeof(int16_t) * channels);
160 // ToDo: UnLock Mutex
161 sound_in_writeptr[banknum] = 0;
162 sound_in_readptr[banknum] = 0;
163 sound_in_write_size[banknum] = 0;
164 sound_in_read_size[banknum] = 0;
165 sound_in_read_mod[banknum] = 0;
171 int EVENT::release_sound_in_source(int bank)
173 if(bank < 0) return -1;
174 if(bank >= MAX_SOUND_IN_BUFFERS) return -1;
176 if(sound_in_tmp_buffer[bank] != NULL) {
177 free(sound_in_tmp_buffer[bank]);
178 sound_in_tmp_buffer[bank] = NULL;
180 sound_in_readptr[bank] = 0;
181 sound_in_writeptr[bank] = 0;
182 sound_in_read_size[bank] = 0;
183 sound_in_write_size[bank] = 0;
184 clear_sound_in_source(bank);
185 // ToDo: UnLock Mutex
189 void EVENT::release()
192 for(int i = 0; i < MAX_SOUND_IN_BUFFERS; i++) {
193 release_sound_in_source(i);
205 // clear events except loop event
206 for(int i = 0; i < MAX_EVENT; i++) {
207 if(event[i].active && event[i].loop_clock == 0) {
208 cancel_event(NULL, i);
212 event_remain = event_extra = 0;
213 cpu_remain = cpu_accum = cpu_done = 0;
217 memset(sound_buffer, 0, sound_samples * sizeof(uint16_t) * 2);
220 memset(sound_tmp, 0, sound_tmp_samples * sizeof(int32_t) * 2);
225 initialize_done = true;
229 #define RUN_CPU_N(num, _class, arg) \
230 return static_cast<_class *>(d_cpu[num].device)->run(arg)
232 #define RUN_CPU_GENERIC(num, arg) \
233 return d_cpu[num].device->run(arg)
236 int EVENT::run_cpu(uint32_t num, int cycles)
239 uint32_t dom_num = cpu_type[num];
241 #if defined(USE_CPU_HD6301)
242 case EVENT_CPUTYPE_HD6301:
243 RUN_CPU_N(num, HD6301, cycles);
246 #if defined(USE_CPU_HUC6280)
247 case EVENT_CPUTYPE_HUC6280:
248 RUN_CPU_N(num, HUC6280, cycles);
251 #if defined(USE_CPU_I286)
252 case EVENT_CPUTYPE_I286:
253 RUN_CPU_N(num, I286, cycles);
256 #if defined(USE_CPU_I386)
257 case EVENT_CPUTYPE_I386:
258 RUN_CPU_N(num, I386, cycles);
261 #if defined(USE_CPU_I8080)
262 case EVENT_CPUTYPE_I8080:
263 RUN_CPU_N(num, I8080, cycles);
266 #if defined(USE_CPU_M6502)
267 case EVENT_CPUTYPE_M6502:
268 RUN_CPU_N(num, M6502, cycles);
271 #if defined(USE_CPU_N2A03)
272 case EVENT_CPUTYPE_N2A03:
273 RUN_CPU_N(num, N2A03, cycles);
276 #if defined(USE_CPU_MB8861)
277 case EVENT_CPUTYPE_MB8861:
278 RUN_CPU_N(num, MB8861, cycles);
281 #if defined(USE_CPU_MC6800)
282 case EVENT_CPUTYPE_MC6800:
283 RUN_CPU_N(num, MC6800, cycles);
286 #if defined(USE_CPU_MC6801)
287 case EVENT_CPUTYPE_MC6801:
288 RUN_CPU_N(num, MC6801, cycles);
291 #if defined(USE_CPU_MC6809)
292 case EVENT_CPUTYPE_MC6809:
293 RUN_CPU_N(num, MC6809, cycles);
296 #if defined(USE_CPU_MCS48)
297 case EVENT_CPUTYPE_MCS48:
298 RUN_CPU_N(num, MCS48, cycles);
301 #if defined(USE_CPU_TMS9995)
302 case EVENT_CPUTYPE_TMS9995:
303 RUN_CPU_N(num, TMS9995, cycles);
306 #if defined(USE_CPU_UPD7801)
307 case EVENT_CPUTYPE_UPD7801:
308 RUN_CPU_N(num, UPD7801, cycles);
311 #if defined(USE_CPU_Z80)
312 case EVENT_CPUTYPE_Z80:
313 RUN_CPU_N(num, Z80, cycles);
316 case EVENT_CPUTYPE_GENERIC:
318 RUN_CPU_GENERIC(num, cycles);
329 //#define USE_SUPRESS_VTABLE
332 // raise pre frame events to update timing settings
333 for(int i = 0; i < frame_event_count; i++) {
334 frame_event[i]->event_pre_frame();
337 // generate clocks per line
338 if(frames_per_sec != next_frames_per_sec || lines_per_frame != next_lines_per_frame) {
339 frames_per_sec = next_frames_per_sec;
340 lines_per_frame = next_lines_per_frame;
342 frame_clocks = (int)((double)d_cpu[0].cpu_clocks / frames_per_sec + 0.5);
343 int remain = frame_clocks;
345 for(int i = 0; i < lines_per_frame; i++) {
346 assert(i < MAX_LINES);
347 vline_clocks[i] = (int)(frame_clocks / lines_per_frame);
348 remain -= vline_clocks[i];
350 for(int i = 0; i < remain; i++) {
351 int index = (int)((double)lines_per_frame * (double)i / (double)remain);
352 assert(index < MAX_LINES);
353 vline_clocks[index]++;
355 for(int i = 1; i < dcount_cpu; i++) {
356 d_cpu[i].update_clocks = (int)(1024.0 * (double)d_cpu[i].cpu_clocks / (double)d_cpu[0].cpu_clocks + 0.5);
358 for(DEVICE* device = vm->first_device; device; device = device->next_device) {
359 if(device->get_event_manager_id() == this_device_id) {
360 device->update_timing(d_cpu[0].cpu_clocks, frames_per_sec, lines_per_frame);
365 // run virtual machine for 1 frame period
366 for(int i = 0; i < frame_event_count; i++) {
367 frame_event[i]->event_frame();
371 vline_start_clock = get_current_clock();
373 for(int i = 0; i < vline_event_count; i++) {
374 vline_event[i]->event_vline(cur_vline, vline_clocks[cur_vline]);
376 this->register_event_by_clock(this, EVENT_VLINE, vline_clocks[cur_vline], false, NULL);
378 if(event_remain < 0) {
379 if(-event_remain > vline_clocks[cur_vline]) {
380 update_event(vline_clocks[cur_vline]);
382 update_event(-event_remain);
385 event_remain += frame_clocks;
386 cpu_remain += frame_clocks << power;
388 while(event_remain > 0) {
389 int event_done = event_remain;
393 if(dcount_cpu == 1) {
394 // run one opecode on primary cpu
395 cpu_done_tmp = d_cpu[0].device->run(-1);
399 // run one opecode on primary cpu
400 #if !defined(USE_SUPRESS_VTABLE)
401 cpu_done = d_cpu[0].device->run(-1);
403 cpu_done = run_cpu(0, -1);
407 // sub cpu runs continuously and no events will be fired while the given clocks,
408 // so I need to give small enough clocks...
409 cpu_done_tmp = (event_extra > 0 || cpu_done < 4) ? cpu_done : 4;
410 cpu_done -= cpu_done_tmp;
412 for(int i = 1; i < dcount_cpu; i++) {
414 d_cpu[i].accum_clocks += d_cpu[i].update_clocks * cpu_done_tmp;
415 int sub_clock = d_cpu[i].accum_clocks >> 10;
417 d_cpu[i].accum_clocks -= sub_clock << 10;
418 #if !defined(USE_SUPRESS_VTABLE)
419 d_cpu[i].device->run(sub_clock);
421 run_cpu(i, sub_clock);
426 cpu_remain -= cpu_done_tmp;
427 cpu_accum += cpu_done_tmp;
428 event_done = cpu_accum >> power;
429 cpu_accum -= event_done << power;
430 event_done -= event_extra;
433 if(event_remain > 0) {
434 if(event_done > event_remain) {
435 update_event(event_remain);
437 update_event(event_done);
440 event_remain -= event_done;
445 void EVENT::update_extra_event(int clock)
447 // this is called from primary cpu while running one opecode
448 int event_done = clock >> power;
451 if(event_remain > 0) {
452 if(event_done > event_remain) {
453 update_event(event_remain);
455 update_event(event_done);
458 event_remain -= event_done;
459 event_extra += event_done;
463 void EVENT::update_event(int clock)
465 uint64_t event_clocks_tmp = event_clocks + clock;
467 while(first_fire_event != NULL && first_fire_event->expired_clock <= event_clocks_tmp) {
468 event_t *event_handle = first_fire_event;
469 uint64_t expired_clock = event_handle->expired_clock;
471 first_fire_event = event_handle->next;
472 if(first_fire_event != NULL) {
473 first_fire_event->prev = NULL;
475 if(event_handle->loop_clock != 0) {
476 event_handle->accum_clocks += event_handle->loop_clock;
477 uint64_t clock_tmp = event_handle->accum_clocks >> 10;
478 event_handle->accum_clocks -= clock_tmp << 10;
479 event_handle->expired_clock += clock_tmp;
480 insert_event(event_handle);
482 event_handle->active = false;
483 event_handle->next = first_free_event;
484 first_free_event = event_handle;
486 event_clocks = expired_clock;
487 event_handle->device->event_callback(event_handle->event_id, 0);
489 event_clocks = event_clocks_tmp;
492 uint32_t EVENT::get_current_clock()
494 return (uint32_t)(event_clocks & 0xffffffff);
497 uint32_t EVENT::get_passed_clock(uint32_t prev)
499 uint32_t current = get_current_clock();
500 return (current > prev) ? current - prev : current + (0xffffffff - prev) + 1;
503 double EVENT::get_passed_usec(uint32_t prev)
505 return 1000000.0 * get_passed_clock(prev) / d_cpu[0].cpu_clocks;
508 uint32_t EVENT::get_passed_clock_since_vline()
510 return get_passed_clock(vline_start_clock);
513 double EVENT::get_passed_usec_since_vline()
515 return get_passed_usec(vline_start_clock);
518 uint32_t EVENT::get_cpu_pc(int index)
520 return d_cpu[index].device->get_pc();
523 void EVENT::register_event(DEVICE* device, int event_id, double usec, bool loop, int* register_id)
526 if(!initialize_done && !loop) {
527 this->out_debug_log(_T("EVENT: non-loop event is registered before initialize is done\n"));
532 if(first_free_event == NULL) {
534 this->out_debug_log(_T("EVENT: too many events !!!\n"));
536 if(register_id != NULL) {
541 event_t *event_handle = first_free_event;
542 first_free_event = first_free_event->next;
544 if(register_id != NULL) {
545 *register_id = event_handle->index;
547 event_handle->active = true;
548 event_handle->device = device;
549 event_handle->event_id = event_id;
552 event_handle->loop_clock = (uint64_t)(1024.0 * (double)d_cpu[0].cpu_clocks / 1000000.0 * usec + 0.5);
553 event_handle->accum_clocks = event_handle->loop_clock;
554 clock = event_handle->accum_clocks >> 10;
555 event_handle->accum_clocks -= clock << 10;
557 clock = (uint64_t)((double)d_cpu[0].cpu_clocks / 1000000.0 * usec + 0.5);
558 event_handle->loop_clock = 0;
559 event_handle->accum_clocks = 0;
561 event_handle->expired_clock = event_clocks + clock;
563 insert_event(event_handle);
566 void EVENT::register_event_by_clock(DEVICE* device, int event_id, uint64_t clock, bool loop, int* register_id)
569 if(!initialize_done && !loop) {
570 this->out_debug_log(_T("EVENT: device (name=%s, id=%d) registeres non-loop event before initialize is done\n"), device->this_device_name, device->this_device_id);
575 if(first_free_event == NULL) {
577 this->out_debug_log(_T("EVENT: too many events !!!\n"));
579 if(register_id != NULL) {
584 event_t *event_handle = first_free_event;
585 first_free_event = first_free_event->next;
587 if(register_id != NULL) {
588 *register_id = event_handle->index;
590 event_handle->active = true;
591 event_handle->device = device;
592 event_handle->event_id = event_id;
593 event_handle->expired_clock = event_clocks + clock;
594 event_handle->loop_clock = loop ? (clock << 10) : 0;
595 event_handle->accum_clocks = 0;
597 insert_event(event_handle);
600 void EVENT::insert_event(event_t *event_handle)
602 if(first_fire_event == NULL) {
603 first_fire_event = event_handle;
604 event_handle->prev = event_handle->next = NULL;
606 for(event_t *insert_pos = first_fire_event; insert_pos != NULL; insert_pos = insert_pos->next) {
607 if(insert_pos->expired_clock > event_handle->expired_clock) {
608 if(insert_pos->prev != NULL) {
610 insert_pos->prev->next = event_handle;
611 event_handle->prev = insert_pos->prev;
612 event_handle->next = insert_pos;
613 insert_pos->prev = event_handle;
617 first_fire_event = event_handle;
618 event_handle->prev = NULL;
619 event_handle->next = insert_pos;
620 insert_pos->prev = event_handle;
623 } else if(insert_pos->next == NULL) {
625 insert_pos->next = event_handle;
626 event_handle->prev = insert_pos;
627 event_handle->next = NULL;
634 void EVENT::cancel_event(DEVICE* device, int register_id)
636 // cancel registered event
637 if(0 <= register_id && register_id < MAX_EVENT) {
638 event_t *event_handle = &event[register_id];
639 if(device != NULL && device != event_handle->device) {
640 this->out_debug_log(_T("EVENT: device (name=%s, id=%d) tries to cancel event %d that is not its own (owned by (name=%s id=%d))!!!\n"), device->this_device_name, device->this_device_id,
642 event_handle->device->this_device_name,
643 event_handle->device->this_device_id);
646 if(event_handle->active) {
647 if(event_handle->prev != NULL) {
648 event_handle->prev->next = event_handle->next;
650 first_fire_event = event_handle->next;
652 if(event_handle->next != NULL) {
653 event_handle->next->prev = event_handle->prev;
655 event_handle->active = false;
656 event_handle->next = first_free_event;
657 first_free_event = event_handle;
662 void EVENT::register_frame_event(DEVICE* device)
664 if(frame_event_count < MAX_EVENT) {
665 for(int i = 0; i < frame_event_count; i++) {
666 if(frame_event[i] == device) {
668 this->out_debug_log(_T("EVENT: device (name=%s, id=%d) has already registered frame event !!!\n"), device->this_device_name, device->this_device_id);
673 frame_event[frame_event_count++] = device;
676 this->out_debug_log(_T("EVENT: too many frame events !!!\n"));
681 void EVENT::register_vline_event(DEVICE* device)
683 if(vline_event_count < MAX_EVENT) {
684 for(int i = 0; i < vline_event_count; i++) {
685 if(vline_event[i] == device) {
687 this->out_debug_log(_T("EVENT: device (name=%s, id=%d) has already registered vline event !!!\n"), device->this_device_name, device->this_device_id);
692 vline_event[vline_event_count++] = device;
695 this->out_debug_log(_T("EVENT: too many vline events !!!\n"));
700 uint32_t EVENT::get_event_remaining_clock(int register_id)
702 if(0 <= register_id && register_id < MAX_EVENT) {
703 event_t *event_handle = &event[register_id];
704 if(event_handle->active && event->expired_clock > event_clocks) {
705 return (uint32_t)(event->expired_clock - event_clocks);
711 double EVENT::get_event_remaining_usec(int register_id)
713 return 1000000.0 * get_event_remaining_clock(register_id) / d_cpu[0].cpu_clocks;
716 void EVENT::touch_sound()
718 if(!(config.sound_strict_rendering || (need_mix > 0))) {
719 int samples = mix_counter;
720 if(samples >= (sound_tmp_samples - buffer_ptr)) {
721 samples = sound_tmp_samples - buffer_ptr;
725 mix_counter -= samples;
730 void EVENT::set_realtime_render(DEVICE* device, bool flag)
732 assert(device != NULL && device->this_device_id < MAX_DEVICE);
733 if(dev_need_mix[device->this_device_id] != flag) {
737 assert(need_mix > 0);
739 if(need_mix < 0) need_mix = 0;
741 dev_need_mix[device->this_device_id] = flag;
745 void EVENT::event_callback(int event_id, int err)
747 if(event_id == EVENT_MIX) {
749 if(prev_skip && dont_skip_frames == 0 && !sound_changed) {
752 int remain = sound_tmp_samples - buffer_ptr;
755 int samples = mix_counter;
757 if(config.sound_strict_rendering || (need_mix > 0)) {
762 if(samples >= remain) {
765 if(config.sound_strict_rendering || (need_mix > 0)) {
771 if(samples > 0 && mix_counter >= mix_limit) {
773 mix_counter -= samples;
778 } else if(event_id == EVENT_VLINE) {
779 if(cur_vline + 1 < lines_per_frame) {
781 vline_start_clock = get_current_clock();
783 for(int i = 0; i < vline_event_count; i++) {
784 vline_event[i]->event_vline(cur_vline, vline_clocks[cur_vline]);
787 // do not register if next vline is the first vline of next frame
788 if(cur_vline + 1 < lines_per_frame) {
789 this->register_event_by_clock(this, EVENT_VLINE, vline_clocks[cur_vline], false, NULL);
795 void EVENT::mix_sound(int samples)
798 int32_t* buffer = sound_tmp + buffer_ptr * 2;
799 memset(buffer, 0, samples * sizeof(int32_t) * 2);
800 for(int i = 0; i < dcount_sound; i++) {
801 d_sound[i]->mix(buffer, samples);
804 for(int i = 0; i < samples * 2; i += 2) {
805 if(buffer[i] != sound_tmp[0] || buffer[i + 1] != sound_tmp[1]) {
806 sound_changed = true;
811 buffer_ptr += samples;
813 // notify to sound devices
814 for(int i = 0; i < dcount_sound; i++) {
815 d_sound[i]->mix(sound_tmp + buffer_ptr * 2, 0);
820 uint16_t* EVENT::create_sound(int* extra_frames)
822 if(prev_skip && dont_skip_frames == 0 && !sound_changed) {
823 memset(sound_buffer, 0, sound_samples * sizeof(uint16_t) * 2);
829 // drive extra frames to fill the sound buffer
830 while(sound_samples > buffer_ptr) {
834 #ifdef LOW_PASS_FILTER
836 for(int i = 0; i < sound_samples - 1; i++) {
837 sound_tmp[i * 2 ] = (sound_tmp[i * 2 ] + sound_tmp[i * 2 + 2]) / 2; // L
838 sound_tmp[i * 2 + 1] = (sound_tmp[i * 2 + 1] + sound_tmp[i * 2 + 3]) / 2; // R
842 for(int i = 0; i < sound_samples * 2; i++) {
843 int dat = sound_tmp[i];
844 uint16_t highlow = (uint16_t)(dat & 0x0000ffff);
846 if((dat > 0) && (highlow >= 0x8000)) {
847 sound_buffer[i] = 0x7fff;
850 if((dat < 0) && (highlow < 0x8000)) {
851 sound_buffer[i] = 0x8000;
854 sound_buffer[i] = highlow;
856 if(buffer_ptr > sound_samples) {
857 buffer_ptr -= sound_samples;
858 memcpy(sound_tmp, sound_tmp + sound_samples * 2, buffer_ptr * sizeof(int32_t) * 2);
862 *extra_frames = frames;
866 int EVENT::get_sound_buffer_ptr()
871 bool EVENT::is_sound_in_source_exists(int bank)
874 if(bank < 0) return false;
875 if(bank >= MAX_SOUND_IN_BUFFERS) return false;
878 if(sound_in_tmp_buffer[bank] == NULL) f = false;
879 // ToDo: UnLock Mutex
880 if(sound_in_samples[bank] <= 0) f = false;
881 if(sound_in_rate[bank] <= 0) f = false;
882 if(sound_in_channels[bank] <= 0) f = false;
886 int EVENT::get_sound_in_buffers_count()
889 for(int i = 0; i < MAX_SOUND_IN_BUFFERS; i++) {
890 if(sound_in_samples[i] == 0) break;
896 int EVENT::get_sound_in_samples(int bank)
898 if(bank < 0) return 0;
899 if(bank >= MAX_SOUND_IN_BUFFERS) return 0;
900 return sound_in_samples[bank];
903 int EVENT::get_sound_in_rate(int bank)
905 if(bank < 0) return 0;
906 if(bank >= MAX_SOUND_IN_BUFFERS) return 0;
907 return sound_in_rate[bank];
910 int EVENT::get_sound_in_channels(int bank)
912 if(bank < 0) return 0;
913 if(bank >= MAX_SOUND_IN_BUFFERS) return 0;
914 return sound_in_channels[bank];
917 int16_t* EVENT::get_sound_in_buf_ptr(int bank)
919 if(bank < 0) return NULL;
920 if(bank >= MAX_SOUND_IN_BUFFERS) return NULL;
921 return &(sound_in_tmp_buffer[bank][sound_in_writeptr[bank]]);
924 int EVENT::write_sound_in_buffer(int bank, int32_t* src, int samples)
926 if(bank < 0) return 0;
927 if(bank >= MAX_SOUND_IN_BUFFERS) return 0;
928 if(samples <= 0) return 0;
929 if(sound_in_tmp_buffer[bank] == NULL) return 0;
930 if(samples >= sound_in_samples[bank]) samples = sound_in_samples[bank];
932 int n_samples = samples;
933 int16_t* dst = &(sound_in_tmp_buffer[bank][sound_in_writeptr[bank] * sound_in_channels[bank]]);
935 if((sound_in_writeptr[bank] + samples) >= sound_in_samples[bank]) {
936 if((sound_in_samples[bank] - sound_in_writeptr[bank] - 1) > 0) {
937 memcpy(dst, src, (sound_in_samples[bank] - sound_in_writeptr[bank] - 1) * sound_in_channels[bank] * sizeof(int16_t));
938 src = src + (sound_in_samples[bank] - sound_in_writeptr[bank] - 1) * sound_in_channels[bank];
939 sound_in_writeptr[bank] = 0;
940 n_samples = n_samples - (sound_in_samples[bank] - sound_in_writeptr[bank] - 1);
942 sound_in_writeptr[bank] = 0;
944 dst = &(sound_in_tmp_buffer[bank][sound_in_writeptr[bank] * sound_in_channels[bank]]);
946 memcpy(dst, src, n_samples * sound_in_channels[bank] * sizeof(int16_t));
947 // ToDo: UnLock Mutex
948 sound_in_writeptr[bank] = sound_in_writeptr[bank] + n_samples;
949 if(sound_in_writeptr[bank] >= sound_in_samples[bank]) sound_in_writeptr[bank] = 0;
953 // Add sampled values to sample buffer;value may be -32768 to +32767.
954 int EVENT::get_sound_in_samples(int bank, int32_t* dst, int expect_samples, int expect_rate, int expect_channels)
956 if(bank < 0) return -1;
957 if(bank >= MAX_SOUND_IN_BUFFERS) return -1;
958 if(sound_in_tmp_buffer[bank] == NULL) return -1;
959 if(dst == NULL) return -1;
962 int32_t tmpbuf[expect_samples * expect_channels];
963 int gave_samples = 0;
966 if(sound_in_channels[bank] > expect_channels) {
967 sound_div = sound_in_channels[bank] / expect_channels;
968 sound_mod = sound_in_channels[bank] % expect_channels;
969 } else if(sound_in_channels[bank] < expect_channels) {
970 sound_div = expect_channels / sound_in_channels[bank];
971 sound_mod = expect_channels % sound_in_channels[bank];
974 if(sound_in_channels[bank] == expect_channels) {
976 for(int i = 0; i < expect_samples; i++) {
977 if(sound_in_write_size[bank] <= 0) break;
978 int16_t* q = &(sound_in_tmp_buffer[bank][sound_in_readptr[bank] * sound_in_channels[bank]]);
979 for(int j = 0; j < expect_channels; j++) {
983 sound_in_readptr[bank] = sound_in_readptr[bank] + 1;
984 if(sound_in_readptr[bank] >= sound_in_samples[bank]) sound_in_readptr[bank] = 0;
986 sound_in_write_size[bank] = sound_in_write_size[bank] - 1;
988 } else if(sound_in_channels[bank] > expect_channels) {
989 for(int i = 0; i < expect_samples; i++) {
992 int32_t* p = &(tmpbuf[i * expect_channels]);
993 int16_t* q = &(sound_in_tmp_buffer[bank][sound_in_readptr[bank] * sound_in_channels[bank]]);
994 if(sound_in_write_size[bank] <= 0) break;
996 for(int j = 0; j < sound_in_channels[bank]; j++) {
1000 if(chp >= sound_div) {
1006 if((chp >= sound_div) && (chq < (expect_channels - 1))){
1013 p = &(dst[i * expect_channels]);
1014 if(sound_mod != 0) {
1015 for(int j = 0; j < (expect_channels - 1); j++) {
1016 *p = *p / sound_div;
1019 *p = *p / (sound_div + sound_mod);
1021 for(int j = 0; j < expect_channels; j++) {
1022 *p = *p / sound_div;
1026 sound_in_readptr[bank] = sound_in_readptr[bank] + 1;
1027 if(sound_in_readptr[bank] >= sound_in_samples[bank]) sound_in_readptr[bank] = 0;
1029 sound_in_write_size[bank] = sound_in_write_size[bank] - 1;
1031 } else { // sound_in_channels[bank] < expect_channels
1032 int32_t* p = tmpbuf;
1033 for(int i = 0; i < expect_samples; i++) {
1034 if(sound_in_write_size[bank] <= 0) break;
1037 int16_t* q = &(sound_in_tmp_buffer[bank][sound_in_readptr[bank] * sound_in_channels[bank]]);
1038 for(int j = 0; j < sound_div; j++) {
1042 if(sound_mod == 0) {
1044 } else if(chp < (expect_channels - sound_mod - 1)) {
1047 for(int j = 0; j < sound_mod; j++) {
1052 sound_in_readptr[bank] = sound_in_readptr[bank] + 1;
1053 if(sound_in_readptr[bank] >= sound_in_samples[bank]) sound_in_readptr[bank] = 0;
1055 sound_in_write_size[bank] = sound_in_write_size[bank] - 1;
1059 // ToDo: UnLock Mutex
1060 // Got to TMP Buffer
1061 if(expect_rate == sound_in_rate[bank]) {
1062 int32_t* p = tmpbuf;
1065 for(int i = 0; i < n_samples; i++) {
1066 for(int j = 0; j < expect_channels; j++) {
1069 if(tval >= 32768) tval = 32767;
1070 if(tval < -32768) tval = -32768;
1077 } else if(expect_rate > sound_in_rate[bank]) {
1078 int32_t* p = tmpbuf;
1081 // ToDo: Interpollate
1083 for(int i = 0; i < n_samples;) {
1084 for(int j = 0; j < expect_channels; j++) {
1087 if(tval >= 32768) tval = 32767;
1088 if(tval < -32768) tval = -32768;
1092 sound_in_read_mod[bank] = sound_in_read_mod[bank] + sound_in_rate[bank];
1093 if(sound_in_read_mod[bank] >= expect_rate) {
1094 sound_in_read_mod[bank] = sound_in_read_mod[bank] - expect_rate;
1095 p = p + expect_channels;
1100 return gave_samples + 1;
1101 } else { // expect_rate < sound_in_rate[bank]
1102 int32_t* p = tmpbuf;
1105 // ToDo: Interpollate
1107 for(int i = 0; i < n_samples; i++) {
1109 for(int j = 0; j < expect_channels; j++) {
1112 if(tval >= 32768) tval = 32767;
1113 if(tval < -32768) tval = -32768;
1118 p = p + expect_channels;
1119 sound_in_read_mod[bank] = sound_in_read_mod[bank] + expect_rate;
1120 if(sound_in_read_mod[bank] >= sound_in_rate[bank]) {
1121 sound_in_read_mod[bank] = sound_in_read_mod[bank] - sound_in_rate[bank];
1122 for(int j = 0; j < expect_channels; j++) {
1125 if(tval >= 32768) tval = 32767;
1126 if(tval < -32768) tval = -32768;
1133 return gave_samples + 1;
1137 void EVENT::request_skip_frames()
1142 bool EVENT::is_frame_skippable()
1144 bool value = next_skip;
1146 if(sound_changed || (prev_skip && !next_skip)) {
1147 dont_skip_frames = (int)frames_per_sec;
1149 if(dont_skip_frames > 0) {
1153 prev_skip = next_skip;
1155 sound_changed = false;
1160 void EVENT::update_config()
1162 if(power != config.cpu_power) {
1163 power = config.cpu_power;
1168 #define STATE_VERSION 4
1170 bool EVENT::process_state(FILEIO* state_fio, bool loading)
1172 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
1175 if(!state_fio->StateCheckInt32(this_device_id)) {
1178 if(!state_fio->StateCheckInt32(dcount_cpu)) {
1181 for(int i = 0; i < dcount_cpu; i++) {
1182 state_fio->StateValue(d_cpu[i].cpu_clocks);
1183 state_fio->StateValue(d_cpu[i].update_clocks);
1184 state_fio->StateValue(d_cpu[i].accum_clocks);
1186 state_fio->StateValue(frame_clocks);
1187 state_fio->StateArray(vline_clocks, sizeof(vline_clocks), 1);
1188 state_fio->StateValue(event_remain);
1189 state_fio->StateValue(event_extra);
1190 state_fio->StateValue(cpu_remain);
1191 state_fio->StateValue(cpu_accum);
1192 state_fio->StateValue(cpu_done);
1193 state_fio->StateValue(event_clocks);
1194 for(int i = 0; i < MAX_EVENT; i++) {
1196 event[i].device = vm->get_device(state_fio->FgetInt32_LE());
1198 state_fio->FputInt32_LE(event[i].device != NULL ? event[i].device->this_device_id : -1);
1200 state_fio->StateValue(event[i].event_id);
1201 state_fio->StateValue(event[i].expired_clock);
1202 state_fio->StateValue(event[i].loop_clock);
1203 state_fio->StateValue(event[i].accum_clocks);
1204 state_fio->StateValue(event[i].active);
1206 event[i].next = (event_t *)get_event(state_fio->FgetInt32_LE());
1207 event[i].prev = (event_t *)get_event(state_fio->FgetInt32_LE());
1209 state_fio->FputInt32_LE(event[i].next != NULL ? event[i].next->index : -1);
1210 state_fio->FputInt32_LE(event[i].prev != NULL ? event[i].prev->index : -1);
1214 first_free_event = (event_t *)get_event(state_fio->FgetInt32_LE());
1215 first_fire_event = (event_t *)get_event(state_fio->FgetInt32_LE());
1217 state_fio->FputInt32_LE(first_free_event != NULL ? first_free_event->index : -1);
1218 state_fio->FputInt32_LE(first_fire_event != NULL ? first_fire_event->index : -1);
1220 state_fio->StateValue(frames_per_sec);
1221 state_fio->StateValue(next_frames_per_sec);
1222 state_fio->StateValue(lines_per_frame);
1223 state_fio->StateValue(next_lines_per_frame);
1224 state_fio->StateArray(dev_need_mix, sizeof(dev_need_mix), 1);
1225 state_fio->StateValue(need_mix);
1230 memset(sound_buffer, 0, sound_samples * sizeof(uint16_t) * 2);
1233 memset(sound_tmp, 0, sound_tmp_samples * sizeof(int32_t) * 2);
1237 mix_limit = (int)((double)(emu->get_sound_rate() / 2000.0)); // per 0.5ms.
1242 void* EVENT::get_event(int index)
1244 if(index >= 0 && index < MAX_EVENT) {
1245 return &event[index];