2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
20 #define MAX_LINES 1024
24 class EVENT : public DEVICE
31 uint32_t update_clocks;
32 uint32_t accum_clocks;
37 int vclocks[MAX_LINES];
40 int cpu_remain, cpu_accum, cpu_done;
41 uint64_t event_clocks;
43 typedef struct event_t {
46 uint64_t expired_clock;
48 uint64_t accum_clocks;
54 event_t event[MAX_EVENT];
55 event_t *first_free_event;
56 event_t *first_fire_event;
58 DEVICE* frame_event[MAX_EVENT];
59 DEVICE* vline_event[MAX_EVENT];
60 int frame_event_count, vline_event_count;
62 double frames_per_sec, next_frames_per_sec;
63 int lines_per_frame, next_lines_per_frame;
65 void update_event(int clock);
66 void insert_event(event_t *event_handle);
69 DEVICE* d_sound[MAX_SOUND];
72 uint16_t* sound_buffer;
76 int sound_tmp_samples;
79 bool prev_skip, next_skip;
82 void mix_sound(int samples);
83 void* get_event(int index);
93 EVENT(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
95 dcount_cpu = dcount_sound = 0;
96 frame_event_count = vline_event_count = 0;
99 memset(event, 0, sizeof(event));
100 for(int i = 0; i < MAX_EVENT; i++) {
101 event[i].active = false;
103 event[i].next = (i + 1 < MAX_EVENT) ? &event[i + 1] : NULL;
105 first_free_event = &event[0];
106 first_fire_event = NULL;
110 // force update timing in the first frame
111 frames_per_sec = 0.0;
113 next_frames_per_sec = FRAMES_PER_SEC;
114 next_lines_per_frame = LINES_PER_FRAME;
117 initialize_done = false;
119 set_device_name(_T("EVENT"));
128 void event_callback(int event_id, int err);
129 void update_config();
130 void save_state(FILEIO* state_fio);
131 bool load_state(FILEIO* state_fio);
133 // common event functions
134 int get_event_manager_id()
136 return this_device_id;
138 void set_frames_per_sec(double new_frames_per_sec)
140 next_frames_per_sec = new_frames_per_sec;
142 void set_lines_per_frame(int new_lines_per_frame)
144 next_lines_per_frame = new_lines_per_frame;
146 void register_event(DEVICE* device, int event_id, double usec, bool loop, int* register_id);
147 void register_event_by_clock(DEVICE* device, int event_id, uint64_t clock, bool loop, int* register_id);
148 void cancel_event(DEVICE* device, int register_id);
149 void register_frame_event(DEVICE* device);
150 void register_vline_event(DEVICE* device);
151 uint32_t get_event_remaining_clock(int register_id);
152 double get_event_remaining_usec(int register_id);
153 uint32_t get_current_clock();
154 uint32_t get_passed_clock(uint32_t prev);
155 double get_passed_usec(uint32_t prev);
156 uint32_t get_cpu_pc(int index);
157 void request_skip_frames();
160 double get_frame_rate()
162 return next_frames_per_sec;
166 void initialize_sound(int rate, int samples);
167 uint16_t* create_sound(int* extra_frames);
168 int get_sound_buffer_ptr();
170 void set_context_cpu(DEVICE* device, uint32_t clocks)
172 int index = dcount_cpu++;
173 d_cpu[index].device = device;
174 d_cpu[index].cpu_clocks = clocks;
175 d_cpu[index].accum_clocks = 0;
177 void set_secondary_cpu_clock(DEVICE* device, uint32_t clocks)
179 // XXX: primary cpu clock should not be changed
180 for(int index = 1; index < dcount_cpu; index++) {
181 if(d_cpu[index].device == device) {
182 d_cpu[index].accum_clocks = 0;
183 d_cpu[index].cpu_clocks = clocks;
184 d_cpu[index].update_clocks = (int)(1024.0 * (double)d_cpu[index].cpu_clocks / (double)d_cpu[0].cpu_clocks + 0.5);
189 void set_context_cpu(DEVICE* device)
191 set_context_cpu(device, CPU_CLOCKS);
193 void set_context_sound(DEVICE* device)
195 if(dcount_sound < MAX_SOUND) {
196 d_sound[dcount_sound++] = device;
199 void touch_sound(void)
201 if((need_mix <= 0) && !sound_touched) {
202 int t_s = mix_counter;
203 // Do need mix_sound(remain_samples) before?
204 if(t_s >= (sound_tmp_samples - buffer_ptr)) t_s = sound_tmp_samples - buffer_ptr - 1;
207 mix_counter = mix_counter - t_s;
209 if(mix_counter < 1) mix_counter = 1;
210 sound_touched = true;
213 void set_realtime_render(bool flag)
217 if(need_mix >= (0x7fff - 1)) need_mix = 0x7fff - 1;
220 if(need_mix < 0) need_mix = 0;
223 bool is_frame_skippable();