OSDN Git Service

[SOUND][VM][PCM1BIT][AY_3_891X] Re-implement low pass filter and high pass filter...
[csp-qt/common_source_project-fm7.git] / source / src / vm / jr100 / jr100.cpp
1 /*
2         National JR-100 Emulator 'eJR-100'
3
4         Author : Takeda.Toshiya
5         Date   : 2015.08.27-
6
7         [ virtual machine ]
8 */
9
10 #include "jr100.h"
11 #include "../../emu.h"
12 #include "../device.h"
13 #include "../event.h"
14
15 #include "../datarec.h"
16 //#include "../mc6800.h"
17 #include "../mb8861.h"
18 #include "../noise.h"
19 #include "../not.h"
20 #include "../pcm1bit.h"
21 #include "../sy6522.h"
22
23 #ifdef USE_DEBUGGER
24 #include "../debugger.h"
25 #endif
26
27 #include "./memory.h"
28
29 using JR100::MEMORY;
30 // ----------------------------------------------------------------------------
31 // initialize
32 // ----------------------------------------------------------------------------
33
34 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
35 {
36         // create devices
37         first_device = last_device = NULL;
38         dummy = new DEVICE(this, emu);  // must be 1st device
39         event = new EVENT(this, emu);   // must be 2nd device
40         dummy->set_device_name(_T("1st Dummy"));
41         
42         drec = new DATAREC(this, emu);
43         drec->set_context_noise_play(new NOISE(this, emu));
44         drec->set_context_noise_stop(new NOISE(this, emu));
45         drec->set_context_noise_fast(new NOISE(this, emu));
46         //cpu = new MC6800(this, emu);  // MB8861N
47         cpu = new MB8861(this, emu);    // MB8861N
48         not_mic = new NOT(this, emu);
49         not_mic->set_device_name(_T("NOT Gate (Mic)"));
50         not_ear = new NOT(this, emu);
51         not_ear->set_device_name(_T("NOT Gate (Ear)"));
52         pcm = new PCM1BIT(this, emu);
53         via = new SY6522(this, emu);
54         
55         memory = new MEMORY(this, emu);
56         // set contexts
57         event->set_context_cpu(cpu);
58         event->set_context_sound(pcm);
59         event->set_context_sound(drec);
60         event->set_context_sound(drec->get_context_noise_play());
61         event->set_context_sound(drec->get_context_noise_stop());
62         event->set_context_sound(drec->get_context_noise_fast());
63         
64         via->set_context_port_a(memory, SIG_MEMORY_VIA_PORT_A, 0xff, 0);
65         via->set_context_port_b(memory, SIG_MEMORY_VIA_PORT_B, 0xff, 0);
66         via->set_context_port_b(pcm, SIG_PCM1BIT_SIGNAL, 0x80, 0);      // PB7 -> Speaker
67         via->set_context_port_b(via, SIG_MEMORY_VIA_PORT_B, 0x80, -1);  // PB7 -> PB6
68         via->set_context_cb2(not_mic, SIG_NOT_INPUT, 1);                // CB2 -> NOT -> MIC
69         via->set_constant_clock(CPU_CLOCKS >> 2);
70         not_mic->set_context_out(drec, SIG_DATAREC_MIC, 1);
71         drec->set_context_ear(not_ear, SIG_NOT_INPUT, 1);               // EAR -> NOT -> CA1,CB1
72         not_ear->set_context_out(via, SIG_SY6522_PORT_CA1, 1);
73         not_ear->set_context_out(via, SIG_SY6522_PORT_CB1, 1);
74         // Sound:: Force realtime rendering. This is temporally fix. 20161024 K.O
75         //pcm->set_realtime_render(true);
76         
77         memory->set_context_via(via);
78         
79         // cpu bus
80         cpu->set_context_mem(memory);
81 #ifdef USE_DEBUGGER
82         cpu->set_context_debugger(new DEBUGGER(this, emu));
83 #endif
84         
85         // initialize all devices
86 #if defined(__GIT_REPO_VERSION)
87         strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
88 #endif
89         for(DEVICE* device = first_device; device; device = device->next_device) {
90                 device->initialize();
91         }
92 }
93
94 VM::~VM()
95 {
96         // delete all devices
97         for(DEVICE* device = first_device; device;) {
98                 DEVICE *next_device = device->next_device;
99                 device->release();
100                 delete device;
101                 device = next_device;
102         }
103 }
104
105 DEVICE* VM::get_device(int id)
106 {
107         for(DEVICE* device = first_device; device; device = device->next_device) {
108                 if(device->this_device_id == id) {
109                         return device;
110                 }
111         }
112         return NULL;
113 }
114
115 // ----------------------------------------------------------------------------
116 // drive virtual machine
117 // ----------------------------------------------------------------------------
118
119 void VM::reset()
120 {
121         // reset all devices
122         for(DEVICE* device = first_device; device; device = device->next_device) {
123                 device->reset();
124         }
125 }
126
127 void VM::special_reset()
128 {
129         // reset all devices
130         for(DEVICE* device = first_device; device; device = device->next_device) {
131                 device->reset();
132         }
133 }
134
135 void VM::run()
136 {
137         event->drive();
138 }
139
140 double VM::get_frame_rate()
141 {
142         return event->get_frame_rate();
143 }
144
145 // ----------------------------------------------------------------------------
146 // debugger
147 // ----------------------------------------------------------------------------
148
149 #ifdef USE_DEBUGGER
150 DEVICE *VM::get_cpu(int index)
151 {
152         if(index == 0) {
153                 return cpu;
154         }
155         return NULL;
156 }
157 #endif
158
159 // ----------------------------------------------------------------------------
160 // draw screen
161 // ----------------------------------------------------------------------------
162
163 void VM::draw_screen()
164 {
165         memory->draw_screen();
166 }
167
168 // ----------------------------------------------------------------------------
169 // soud manager
170 // ----------------------------------------------------------------------------
171
172 void VM::initialize_sound(int rate, int samples)
173 {
174         // init sound manager
175         event->initialize_sound(rate, samples);
176         
177         // init sound gen
178         pcm->initialize_sound(rate, 5000);
179 }
180
181 uint16_t* VM::create_sound(int* extra_frames)
182 {
183         return event->create_sound(extra_frames);
184 }
185
186 int VM::get_sound_buffer_ptr()
187 {
188         return event->get_sound_buffer_ptr();
189 }
190
191 #ifdef USE_SOUND_VOLUME
192 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
193 {
194         if(ch == 0) {
195                 pcm->set_volume(0, decibel_l, decibel_r);
196         } else if(ch == 1) {
197                 drec->set_volume(0, decibel_l, decibel_r);
198         } else if(ch == 2) {
199                 drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
200                 drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
201                 drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
202         }
203 }
204 #endif
205
206 // ----------------------------------------------------------------------------
207 // user interface
208 // ----------------------------------------------------------------------------
209
210 void VM::play_tape(int drv, const _TCHAR* file_path)
211 {
212         bool remote = drec->get_remote();
213         
214         if(drec->play_tape(file_path) && remote) {
215                 // if machine already sets remote on, start playing now
216                 push_play(drv);
217         }
218 }
219
220 void VM::rec_tape(int drv, const _TCHAR* file_path)
221 {
222         bool remote = drec->get_remote();
223         
224         if(drec->rec_tape(file_path) && remote) {
225                 // if machine already sets remote on, start recording now
226                 push_play(drv);
227         }
228 }
229
230 void VM::close_tape(int drv)
231 {
232         emu->lock_vm();
233         drec->close_tape();
234         emu->unlock_vm();
235         drec->set_remote(false);
236 }
237
238 bool VM::is_tape_inserted(int drv)
239 {
240         return drec->is_tape_inserted();
241 }
242
243 bool VM::is_tape_playing(int drv)
244 {
245         return drec->is_tape_playing();
246 }
247
248 bool VM::is_tape_recording(int drv)
249 {
250         return drec->is_tape_recording();
251 }
252
253 int VM::get_tape_position(int drv)
254 {
255         return drec->get_tape_position();
256 }
257
258 const _TCHAR* VM::get_tape_message(int drv)
259 {
260         return drec->get_message();
261 }
262
263 void VM::push_play(int drv)
264 {
265         drec->set_remote(false);
266         drec->set_ff_rew(0);
267         drec->set_remote(true);
268 }
269
270 void VM::push_stop(int drv)
271 {
272         drec->set_remote(false);
273 }
274
275 void VM::push_fast_forward(int drv)
276 {
277         drec->set_remote(false);
278         drec->set_ff_rew(1);
279         drec->set_remote(true);
280 }
281
282 void VM::push_fast_rewind(int drv)
283 {
284         drec->set_remote(false);
285         drec->set_ff_rew(-1);
286         drec->set_remote(true);
287 }
288
289 bool VM::is_frame_skippable()
290 {
291         return event->is_frame_skippable();
292 }
293
294 void VM::update_config()
295 {
296         for(DEVICE* device = first_device; device; device = device->next_device) {
297                 device->update_config();
298         }
299 }
300
301 #define STATE_VERSION   3
302
303 bool VM::process_state(FILEIO* state_fio, bool loading)
304 {
305         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
306                 return false;
307         }
308         for(DEVICE* device = first_device; device; device = device->next_device) {
309                 // Note: typeid(foo).name is fixed by recent ABI.Not dec 6.
310                 // const char *name = typeid(*device).name();
311                 //       But, using get_device_name() instead of typeid(foo).name() 20181008 K.O
312                 const char *name = device->get_device_name();
313                 int len = strlen(name);
314                 
315                 if(!state_fio->StateCheckInt32(len)) {
316                         if(loading) {
317                                 printf("Class name len Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
318                         }
319                         return false;
320                 }
321                 if(!state_fio->StateCheckBuffer(name, len, 1)) {
322                         if(loading) {
323                                 printf("Class name Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
324                         }
325                         return false;
326                 }
327                 if(!device->process_state(state_fio, loading)) {
328                         if(loading) {
329                                 printf("Data loading Error: DEVID=%d\n", device->this_device_id);
330                         }
331                         return false;
332                 }
333         }
334         return true;
335 }