OSDN Git Service

[DOC] For release 2017-01-24.
[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 #define MAX_CPU         8
18 // 20161003 K.O
19 #define MAX_SOUND       32
20 #define MAX_LINES       1024
21 #define MAX_EVENT       64
22 #define NO_EVENT        -1
23
24 class EVENT : public DEVICE
25 {
26 private:
27         // event manager
28         typedef struct {
29                 DEVICE* device;
30                 uint32_t cpu_clocks;
31                 uint32_t update_clocks;
32                 uint32_t accum_clocks;
33         } cpu_t;
34         cpu_t d_cpu[MAX_CPU];
35         int dcount_cpu;
36         
37         int vclocks[MAX_LINES];
38         int power;
39         int event_remain;
40         int cpu_remain, cpu_accum, cpu_done;
41         uint64_t event_clocks;
42         
43         typedef struct event_t {
44                 DEVICE* device;
45                 int event_id;
46                 uint64_t expired_clock;
47                 uint64_t loop_clock;
48                 uint64_t accum_clocks;
49                 bool active;
50                 int index;
51                 event_t *next;
52                 event_t *prev;
53         } event_t;
54         event_t event[MAX_EVENT];
55         event_t *first_free_event;
56         event_t *first_fire_event;
57         
58         DEVICE* frame_event[MAX_EVENT];
59         DEVICE* vline_event[MAX_EVENT];
60         int frame_event_count, vline_event_count;
61         
62         double frames_per_sec, next_frames_per_sec;
63         int lines_per_frame, next_lines_per_frame;
64         
65         void update_event(int clock);
66         void insert_event(event_t *event_handle);
67         
68         // sound manager
69         DEVICE* d_sound[MAX_SOUND];
70         int dcount_sound;
71         
72         uint16_t* sound_buffer;
73         int32_t* sound_tmp;
74         int buffer_ptr;
75         int sound_samples;
76         int sound_tmp_samples;
77         
78         int dont_skip_frames;
79         bool prev_skip, next_skip;
80         bool sound_changed;
81         
82         void mix_sound(int samples);
83         void* get_event(int index);
84         
85 #ifdef _DEBUG_LOG
86         bool initialize_done;
87 #endif
88         int mix_counter;
89         int mix_limit;
90         int need_mix;
91         bool sound_touched;
92 public:
93         EVENT(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
94         {
95                 dcount_cpu = dcount_sound = 0;
96                 frame_event_count = vline_event_count = 0;
97                 
98                 // initialize event
99                 memset(event, 0, sizeof(event));
100                 for(int i = 0; i < MAX_EVENT; i++) {
101                         event[i].active = false;
102                         event[i].index = i;
103                         event[i].next = (i + 1 < MAX_EVENT) ? &event[i + 1] : NULL;
104                 }
105                 first_free_event = &event[0];
106                 first_fire_event = NULL;
107                 
108                 event_clocks = 0;
109                 
110                 // force update timing in the first frame
111                 frames_per_sec = 0.0;
112                 lines_per_frame = 0;
113                 next_frames_per_sec = FRAMES_PER_SEC;
114                 next_lines_per_frame = LINES_PER_FRAME;
115                 
116 #ifdef _DEBUG_LOG
117                 initialize_done = false;
118 #endif
119                 set_device_name(_T("EVENT"));
120                 need_mix = 0;
121         }
122         ~EVENT() {}
123         
124         // common functions
125         void initialize();
126         void release();
127         void reset();
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);
132         
133         // common event functions
134         int get_event_manager_id()
135         {
136                 return this_device_id;
137         }
138         void set_frames_per_sec(double new_frames_per_sec)
139         {
140                 next_frames_per_sec = new_frames_per_sec;
141         }
142         void set_lines_per_frame(int new_lines_per_frame)
143         {
144                 next_lines_per_frame = new_lines_per_frame;
145         }
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();
158         
159         // unique functions
160         double get_frame_rate()
161         {
162                 return next_frames_per_sec;
163         }
164         void drive();
165         
166         void initialize_sound(int rate, int samples);
167         uint16_t* create_sound(int* extra_frames);
168         int get_sound_buffer_ptr();
169         
170         void set_context_cpu(DEVICE* device, uint32_t clocks)
171         {
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;
176         }
177         void set_secondary_cpu_clock(DEVICE* device, uint32_t clocks)
178         {
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);
185                                 break;
186                         }
187                 }
188         }
189         void set_context_cpu(DEVICE* device)
190         {
191                 set_context_cpu(device, CPU_CLOCKS);
192         }
193         void set_context_sound(DEVICE* device)
194         {
195                 if(dcount_sound < MAX_SOUND) {
196                         d_sound[dcount_sound++] = device;
197                 }
198         }
199         void touch_sound(void)
200         {
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; 
205                         if(t_s > 0) {
206                                         mix_sound(t_s);
207                                         mix_counter = mix_counter - t_s;
208                         }
209                         if(mix_counter < 1) mix_counter = 1;
210                         sound_touched = true;
211                 }
212         }
213         void set_realtime_render(bool flag)
214         {
215                 if(flag) {
216                         need_mix++;
217                         if(need_mix >= (0x7fff - 1)) need_mix = 0x7fff - 1;
218                 } else {
219                         need_mix--;
220                         if(need_mix < 0) need_mix = 0;
221                 }
222         }
223         bool is_frame_skippable();
224 };
225
226 #endif
227