OSDN Git Service

[VM][COMMON_VM] Include IO:: class to common_vm.
[csp-qt/common_source_project-fm7.git] / source / src / vm / event.h
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2006.11.29-
6
7         [ event manager ]
8 */
9
10 #ifndef _EVENT_H_
11 #define _EVENT_H_
12
13 #include "vm.h"
14 #include "../emu.h"
15 #include "device.h"
16
17 #include <typeinfo>
18
19 #define MAX_DEVICE      64
20 #define MAX_CPU         8
21 #define MAX_SOUND       32
22 #define MAX_LINES       1024
23 #define MAX_EVENT       64
24 #define NO_EVENT        -1
25 #if !defined(MAX_SOUND_IN_BUFFERS)
26         #define MAX_SOUND_IN_BUFFERS 8
27 #else
28         #if (MAX_SOUND_IN_BUFFERS <= 0)
29         #define MAX_SOUND_IN_BUFFERS 8
30         #endif
31 #endif
32
33 enum {
34         EVENT_CPUTYPE_GENERIC = 0,
35         EVENT_CPUTYPE_HD6301,
36         EVENT_CPUTYPE_HUC6280,
37         EVENT_CPUTYPE_I286,
38         EVENT_CPUTYPE_I386,
39         EVENT_CPUTYPE_I8080,
40         EVENT_CPUTYPE_M6502,
41         EVENT_CPUTYPE_N2A03,
42         EVENT_CPUTYPE_MB8861,
43         EVENT_CPUTYPE_MC6800,
44         EVENT_CPUTYPE_MC6801,
45         EVENT_CPUTYPE_MC6809,
46         EVENT_CPUTYPE_MCS48,
47         EVENT_CPUTYPE_TMS9995,
48         EVENT_CPUTYPE_UPD7801,
49         EVENT_CPUTYPE_Z80,
50         EVENT_CPUTYPE_I86,
51         EVENT_CPUTYPE_V30,
52         EVENT_CPUTYPE_UPD7810,
53         EVENT_CPUTYPE_UPD7907,
54 };
55
56
57 class EVENT : public DEVICE
58 {
59 private:
60         // event manager
61         typedef struct {
62                 DEVICE* device;
63                 uint32_t cpu_clocks;
64                 uint32_t update_clocks;
65                 uint32_t accum_clocks;
66         } cpu_t;
67         cpu_t d_cpu[MAX_CPU];
68
69         uint32_t cpu_update_clocks[MAX_CPU][6];
70         int dcount_cpu;
71         
72         int frame_clocks;
73         int vline_clocks[MAX_LINES];
74         int power;
75         int event_remain, event_extra;
76         int cpu_remain, cpu_accum, cpu_done;
77         uint64_t event_clocks;
78         
79         typedef struct event_t {
80                 DEVICE* device;
81                 int event_id;
82                 uint64_t expired_clock;
83                 uint64_t loop_clock;
84                 uint64_t accum_clocks;
85                 bool active;
86                 int index;
87                 event_t *next;
88                 event_t *prev;
89         } event_t;
90         event_t event[MAX_EVENT];
91         event_t *first_free_event;
92         event_t *first_fire_event;
93         // For State
94         DEVICE* frame_event[MAX_EVENT];
95         DEVICE* vline_event[MAX_EVENT];
96         int frame_event_count, vline_event_count;
97         
98         double frames_per_sec, next_frames_per_sec;
99         int lines_per_frame, next_lines_per_frame;
100         uint32_t vline_start_clock;
101         int cur_vline;
102         
103         void update_event(int clock);
104         void insert_event(event_t *event_handle);
105         
106         // sound manager
107         DEVICE* d_sound[MAX_SOUND];
108         int dcount_sound;
109         
110         uint16_t* sound_buffer;
111         int32_t* sound_tmp;
112         int buffer_ptr;
113         int sound_samples;
114         int sound_tmp_samples;
115
116         int16_t* sound_in_tmp_buffer[MAX_SOUND_IN_BUFFERS]; // This is buffer from recording devices.
117         int sound_in_rate[MAX_SOUND_IN_BUFFERS];
118         int sound_in_samples[MAX_SOUND_IN_BUFFERS];
119         int sound_in_channels[MAX_SOUND_IN_BUFFERS];
120         int sound_in_writeptr[MAX_SOUND_IN_BUFFERS];
121         int sound_in_readptr[MAX_SOUND_IN_BUFFERS];
122         int sound_in_write_size[MAX_SOUND_IN_BUFFERS];
123         int sound_in_read_size[MAX_SOUND_IN_BUFFERS];
124         int sound_in_read_mod[MAX_SOUND_IN_BUFFERS];
125         
126         int dont_skip_frames;
127         bool prev_skip, next_skip;
128         bool sound_changed;
129         
130         int mix_counter;
131         int mix_limit;
132         bool dev_need_mix[MAX_DEVICE];
133         int need_mix;
134         
135         void mix_sound(int samples);
136         void* get_event(int index);
137
138 #ifdef _DEBUG_LOG
139         bool initialize_done;
140 #endif
141 public:
142         EVENT(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
143         {
144                 dcount_cpu = dcount_sound = 0;
145                 frame_event_count = vline_event_count = 0;
146                 
147                 // initialize event
148                 memset(event, 0, sizeof(event));
149                 for(int i = 0; i < MAX_EVENT; i++) {
150                         event[i].active = false;
151                         event[i].index = i;
152                         event[i].next = (i + 1 < MAX_EVENT) ? &event[i + 1] : NULL;
153                 }
154                 first_free_event = &event[0];
155                 first_fire_event = NULL;
156                 
157                 event_clocks = 0;
158                 
159                 // force update timing in the first frame
160                 frames_per_sec = 0.0;
161                 lines_per_frame = 0;
162                 next_frames_per_sec = FRAMES_PER_SEC;
163                 next_lines_per_frame = LINES_PER_FRAME;
164                 // reset before other device may call set_realtime_render()
165                 memset(dev_need_mix, 0, sizeof(dev_need_mix));
166                 need_mix = 0;
167                 
168                 for(int i = 0; i < MAX_SOUND_IN_BUFFERS; i++) {
169                         sound_in_tmp_buffer[i] = NULL;
170                         sound_in_rate[i] = 0;
171                         sound_in_samples[i] = 0;
172                         sound_in_channels[i] = 0;
173                         sound_in_readptr[i] = 0;
174                         sound_in_writeptr[i] = 0;
175                         sound_in_read_size[i] = 0;
176                         sound_in_write_size[i] = 0;
177                         sound_in_read_mod[i] = 0;
178                 }
179 #ifdef _DEBUG_LOG
180                 initialize_done = false;
181 #endif
182                 set_device_name(_T("Event Manager"));
183         }
184         ~EVENT() {}
185         
186         // common functions
187         void initialize();
188         void release();
189         void reset();
190         void event_callback(int event_id, int err);
191         void update_config();
192         bool process_state(FILEIO* state_fio, bool loading);
193         
194         // common event functions
195         int get_event_manager_id()
196         {
197                 return this_device_id;
198         }
199         void set_frames_per_sec(double new_frames_per_sec)
200         {
201                 next_frames_per_sec = new_frames_per_sec;
202         }
203         void set_lines_per_frame(int new_lines_per_frame)
204         {
205                 if(new_lines_per_frame < MAX_LINES) {
206                         next_lines_per_frame = new_lines_per_frame;
207                 }
208         }
209         int get_lines_per_frame()
210         {
211                 return next_lines_per_frame;
212         }
213         bool is_primary_cpu(DEVICE* device)
214         {
215                 return (d_cpu[0].device == device);
216         }
217         void update_extra_event(int clock);
218         void register_event(DEVICE* device, int event_id, double usec, bool loop, int* register_id);
219         void register_event_by_clock(DEVICE* device, int event_id, uint64_t clock, bool loop, int* register_id);
220         void cancel_event(DEVICE* device, int register_id);
221         void register_frame_event(DEVICE* device);
222         void register_vline_event(DEVICE* device);
223         uint32_t get_event_remaining_clock(int register_id);
224         double get_event_remaining_usec(int register_id);
225         uint32_t get_current_clock();
226         uint32_t get_passed_clock(uint32_t prev);
227         double get_passed_usec(uint32_t prev);
228         uint32_t get_passed_clock_since_vline();
229         double get_passed_usec_since_vline();
230         int get_cur_vline()
231         {
232                 return cur_vline;
233         }
234         int get_cur_vline_clocks()
235         {
236                 return vline_clocks[cur_vline];
237         }
238         uint32_t get_cpu_pc(int index);
239         void request_skip_frames();
240         void touch_sound();
241         void set_realtime_render(DEVICE* device, bool flag);
242         uint64_t get_current_clock_uint64();
243         uint32_t get_cpu_clock(int index);
244         // unique functions
245         double get_frame_rate()
246         {
247                 return next_frames_per_sec;
248         }
249         void drive();
250         
251         void initialize_sound(int rate, int samples);
252         uint16_t* create_sound(int* extra_frames);
253         int get_sound_buffer_ptr();
254         // Sound input functions
255         void clear_sound_in_source(int bank);
256         int add_sound_in_source(int rate, int samples, int channels);
257         int release_sound_in_source(int bank);
258         
259         bool is_sound_in_source_exists(int bank);
260         int increment_sound_in_passed_data(int bank, double passed_usec);
261         int get_sound_in_buffers_count();
262         int get_sound_in_samples(int bank);
263         int get_sound_in_rate(int bank);
264         int get_sound_in_channels(int bank);
265         int16_t* get_sound_in_buf_ptr(int bank);
266         int write_sound_in_buffer(int bank, int32_t* src, int samples);
267         // Add sampled values to sample buffer;value may be -32768 to +32767.
268         int get_sound_in_latest_data(int bank, int32_t* dst, int expect_channels);
269         int get_sound_in_data(int bank, int32_t* dst, int expect_samples, int expect_rate, int expect_channels);
270         int rechannel_sound_in_data(int32_t*dst, int16_t* src, int dst_channels, int src_channels, int samples);
271         
272         int set_context_cpu(DEVICE* device, uint32_t clocks = CPU_CLOCKS)
273         {
274                 assert(dcount_cpu < MAX_CPU);
275                 int index = dcount_cpu++;
276                 d_cpu[index].device = (DEVICE *)device;
277                 d_cpu[index].cpu_clocks = clocks;
278                 d_cpu[index].accum_clocks = 0;
279                 for(int k = 0; k < 6; k++) cpu_update_clocks[index][k] = d_cpu[index].update_clocks * k;
280                 return index;
281         }
282         bool remove_context_cpu(DEVICE* device, int num)
283         {
284                 if(num <= 0) return false; // Number one must not be removed.
285                 if(num >= MAX_CPU) return false;
286                 if(num >= dcount_cpu) return false;
287                 if(dcount_cpu <= 1) return false;
288                 // Note: This function is dangerous.
289                 if(d_cpu[num].device != device) return false;
290                 if(d_cpu[num].device == NULL) return false;
291                 if(dcount_cpu == 2) {
292                         d_cpu[1].device = (DEVICE *)NULL;
293                         d_cpu[1].cpu_clocks = 0;
294                         d_cpu[1].accum_clocks = 0;
295                         dcount_cpu = 1;
296                         for(int k = 0; k < 6; k++)      cpu_update_clocks[1][k] = d_cpu[1].update_clocks * k;
297                 } else {
298                         for(int i = num; i < (dcount_cpu - 1); i++) {
299                                 d_cpu[i].device = d_cpu[i + 1].device;
300                                 d_cpu[i].cpu_clocks = d_cpu[i + 1].cpu_clocks;
301                                 d_cpu[i].accum_clocks = d_cpu[i + 1].accum_clocks;
302                         }
303                         int n = dcount_cpu - 1;
304                         d_cpu[n].device = (DEVICE *)NULL;
305                         d_cpu[n].cpu_clocks = 0;
306                         d_cpu[n].accum_clocks = 0;
307                         for(int i = 1; i < dcount_cpu; i++) {
308                                 for(int k = 0; k < 6; k++)      cpu_update_clocks[i][k] = d_cpu[i].update_clocks * k;
309                         }
310                         dcount_cpu = dcount_cpu - 1;
311                 }
312                 return true;
313         }
314         void set_secondary_cpu_clock(DEVICE* device, uint32_t clocks)
315         {
316                 // XXX: primary cpu clock should not be changed
317                 for(int index = 1; index < dcount_cpu; index++) {
318                         if(d_cpu[index].device == device) {
319                                 d_cpu[index].accum_clocks = 0;
320                                 d_cpu[index].cpu_clocks = clocks;
321                                 d_cpu[index].update_clocks = (int)(1024.0 * (double)d_cpu[index].cpu_clocks / (double)d_cpu[0].cpu_clocks + 0.5)
322 ;
323                                 for(int k = 0; k < 6; k++) cpu_update_clocks[index][k] = d_cpu[index].update_clocks * k;
324                                 break;
325                         }
326                 }
327         }
328         void set_context_sound(DEVICE* device)
329         {
330                 assert(dcount_sound < MAX_SOUND);
331                 d_sound[dcount_sound++] = device;
332         }
333         bool is_frame_skippable();
334 };
335
336 /*
337  * Faster runncing cpu.
338  * Expect to optimize switch(...) - case to jump table.
339  * You should include real header of CPU DEVICE begin of this file.
340  * -- 20180317 K.O.
341  */
342
343
344
345 #endif
346