OSDN Git Service

f25d5a6415768064f71e674b245811070d2f6f20
[csp-qt/common_source_project-fm7.git] / source / src / vm / yalky / yalky.cpp
1 /*
2         Yuasa Kyouiku System YALKY Emulator 'eYALKY'
3
4         Author : Takeda.Toshiya
5         Date   : 2016.03.28-
6
7         [ virtual machine ]
8 */
9
10 #include "yalky.h"
11 #include "../../emu.h"
12 #include "../device.h"
13 #include "../event.h"
14
15 #include "../datarec.h"
16 #include "../i8080.h"
17 #include "../i8155.h"
18 #include "../memory.h"
19 #include "../noise.h"
20
21 #ifdef USE_DEBUGGER
22 #include "../debugger.h"
23 #endif
24
25 #include "io.h"
26
27 // ----------------------------------------------------------------------------
28 // initialize
29 // ----------------------------------------------------------------------------
30
31 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
32 {
33         config.sound_play_tape = false;
34         config.wave_shaper[0] = false;
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 I8080(this, emu);     // 8085
47         pio = new I8155(this, emu);     // 8156
48         memory = new MEMORY(this, emu);
49         
50         io = new IO(this, emu);
51         
52         // set contexts
53         event->set_context_cpu(cpu);
54         event->set_context_sound(drec);
55         event->set_context_sound(drec->get_context_noise_play());
56         event->set_context_sound(drec->get_context_noise_stop());
57         event->set_context_sound(drec->get_context_noise_fast());
58         
59         drec->set_context_ear(io, SIG_IO_DREC_EAR, 1);
60         cpu->set_context_sod(drec, SIG_DATAREC_MIC, 1);
61         pio->set_context_port_b(io, SIG_IO_PORT_B, 0xff, 0);
62         pio->set_context_port_c(io, SIG_IO_PORT_C, 0xff, 0);
63         pio->set_context_timer(cpu, SIG_I8085_RST7, 1);
64         pio->set_constant_clock(CPU_CLOCKS);    // from 8085 CLOCK OUT
65         
66         io->set_context_drec(drec);
67         io->set_context_cpu(cpu);
68         io->set_context_pio(pio);
69         io->set_vram_ptr(vram);
70         
71         // cpu bus
72         cpu->set_context_mem(memory);
73         cpu->set_context_io(io);
74         cpu->set_context_intr(io);
75 #ifdef USE_DEBUGGER
76         cpu->set_context_debugger(new DEBUGGER(this, emu));
77 #endif
78         
79         // memory bus
80         memset(rom, 0xff, sizeof(rom));
81         
82         memory->read_bios(_T("BIOS.ROM"), rom, sizeof(rom));
83         
84         memory->set_memory_r(0x0000, 0x1fff, rom);
85         memory->set_memory_rw(0x4000, 0x43ff, vram);
86         memory->set_memory_rw(0x6000, 0x60ff, ram);     // 8156
87         
88         // initialize all devices
89         for(DEVICE* device = first_device; device; device = device->next_device) {
90                 device->initialize();
91         }
92         decl_state();
93 }
94
95 VM::~VM()
96 {
97         // delete all devices
98         for(DEVICE* device = first_device; device;) {
99                 DEVICE *next_device = device->next_device;
100                 device->release();
101                 delete device;
102                 device = next_device;
103         }
104 }
105
106 DEVICE* VM::get_device(int id)
107 {
108         for(DEVICE* device = first_device; device; device = device->next_device) {
109                 if(device->this_device_id == id) {
110                         return device;
111                 }
112         }
113         return NULL;
114 }
115
116 // ----------------------------------------------------------------------------
117 // drive virtual machine
118 // ----------------------------------------------------------------------------
119
120 void VM::reset()
121 {
122         // reset all devices
123         for(DEVICE* device = first_device; device; device = device->next_device) {
124                 device->reset();
125         }
126         pio->write_signal(SIG_I8155_PORT_A, 0xff, 0x80); // PA7=1
127         memset(ram, 0, sizeof(ram));
128         memset(vram, 0, sizeof(vram));
129 }
130
131 void VM::special_reset()
132 {
133         cpu->reset();
134 }
135
136 void VM::run()
137 {
138         event->drive();
139 }
140
141 // ----------------------------------------------------------------------------
142 // debugger
143 // ----------------------------------------------------------------------------
144
145 #ifdef USE_DEBUGGER
146 DEVICE *VM::get_cpu(int index)
147 {
148         if(index == 0) {
149                 return cpu;
150         }
151         return NULL;
152 }
153 #endif
154
155 // ----------------------------------------------------------------------------
156 // draw screen
157 // ----------------------------------------------------------------------------
158
159 void VM::draw_screen()
160 {
161         io->draw_screen();
162 }
163
164 // ----------------------------------------------------------------------------
165 // soud manager
166 // ----------------------------------------------------------------------------
167
168 void VM::initialize_sound(int rate, int samples)
169 {
170         // init sound manager
171         event->initialize_sound(rate, samples);
172 }
173
174 uint16_t* VM::create_sound(int* extra_frames)
175 {
176         return event->create_sound(extra_frames);
177 }
178
179 int VM::get_sound_buffer_ptr()
180 {
181         return event->get_sound_buffer_ptr();
182 }
183
184 #ifdef USE_SOUND_VOLUME
185 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
186 {
187         if(ch == 0) {
188                 drec->set_volume(0, decibel_l, decibel_r);
189         } else if(ch == 1) {
190                 drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
191                 drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
192                 drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
193         }
194 }
195 #endif
196
197 // ----------------------------------------------------------------------------
198 // user interface
199 // ----------------------------------------------------------------------------
200
201 void VM::play_tape(int drv, const _TCHAR* file_path)
202 {
203         if(drec->play_tape(file_path)) {
204                 drec->set_remote(true);
205                 io->open_tape();
206         }
207 }
208
209 void VM::rec_tape(int drv, const _TCHAR* file_path)
210 {
211         if(drec->rec_tape(file_path)) {
212                 drec->set_remote(true);
213                 io->open_tape();
214         }
215 }
216
217 void VM::close_tape(int drv)
218 {
219         emu->lock_vm();
220         drec->close_tape();
221         emu->unlock_vm();
222         drec->set_remote(false);
223 }
224
225 bool VM::is_tape_inserted(int drv)
226 {
227         return drec->is_tape_inserted();
228 }
229
230 bool VM::is_tape_playing(int drv)
231 {
232         return drec->is_tape_playing();
233 }
234
235 bool VM::is_tape_recording(int drv)
236 {
237         return drec->is_tape_recording();
238 }
239
240 int VM::get_tape_position(int drv)
241 {
242         return drec->get_tape_position();
243 }
244
245 const _TCHAR* VM::get_tape_message(int drv)
246 {
247         return drec->get_message();
248 }
249
250 void VM::push_play(int drv)
251 {
252         drec->set_ff_rew(0);
253         drec->set_remote(true);
254 }
255
256 void VM::push_stop(int drv)
257 {
258         drec->set_remote(false);
259 }
260
261 void VM::push_fast_forward(int drv)
262 {
263         drec->set_ff_rew(1);
264         drec->set_remote(true);
265 }
266
267 void VM::push_fast_rewind(int drv)
268 {
269         drec->set_ff_rew(-1);
270         drec->set_remote(true);
271 }
272
273 bool VM::is_frame_skippable()
274 {
275         return event->is_frame_skippable();
276 }
277
278 void VM::update_config()
279 {
280         for(DEVICE* device = first_device; device; device = device->next_device) {
281                 device->update_config();
282         }
283 }
284
285 #define STATE_VERSION   4
286
287 #include "../../statesub.h"
288 #include "../../qt/gui/csp_logger.h"
289 extern CSP_Logger DLL_PREFIX_I *csp_logger;
290
291 void VM::decl_state(void)
292 {
293
294         state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::YALKY_HEAD")), csp_logger);
295         DECL_STATE_ENTRY_1D_ARRAY(ram, sizeof(ram));
296         DECL_STATE_ENTRY_1D_ARRAY(vram, sizeof(vram));
297         for(DEVICE* device = first_device; device; device = device->next_device) {
298                 device->decl_state();
299         }
300 }
301
302 void VM::save_state(FILEIO* state_fio)
303 {
304         //state_fio->FputUint32(STATE_VERSION);
305         
306         if(state_entry != NULL) {
307                 state_entry->save_state(state_fio);
308         }
309         for(DEVICE* device = first_device; device; device = device->next_device) {
310                 device->save_state(state_fio);
311         }
312         //state_fio->Fwrite(ram, sizeof(ram), 1);
313         //state_fio->Fwrite(vram, sizeof(vram), 1);
314 }
315
316 bool VM::load_state(FILEIO* state_fio)
317 {
318         //if(state_fio->FgetUint32() != STATE_VERSION) {
319         //      return false;
320         //}
321         bool mb = false;
322         if(state_entry != NULL) {
323                 mb = state_entry->load_state(state_fio);
324         }
325         if(!mb) {
326                 emu->out_debug_log("INFO: HEADER DATA ERROR");
327                 return false;
328         }
329         for(DEVICE* device = first_device; device; device = device->next_device) {
330                 if(!device->load_state(state_fio)) {
331                         return false;
332                 }
333         }
334         //state_fio->Fread(ram, sizeof(ram), 1);
335         //state_fio->Fread(vram, sizeof(vram), 1);
336         return true;
337 }
338