OSDN Git Service

[VM][DEVICE] Add name to all of components.
[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
20 #ifdef USE_DEBUGGER
21 #include "../debugger.h"
22 #endif
23
24 #include "io.h"
25
26 // ----------------------------------------------------------------------------
27 // initialize
28 // ----------------------------------------------------------------------------
29
30 VM::VM(EMU* parent_emu) : emu(parent_emu)
31 {
32         config.tape_sound = false;
33         config.wave_shaper = false;
34         
35         // create devices
36         first_device = last_device = NULL;
37         dummy = new DEVICE(this, emu);  // must be 1st device
38         event = new EVENT(this, emu);   // must be 2nd device
39 #if defined(_USE_QT)
40         dummy->set_device_name(_T("1st Dummy"));
41 #endif  
42         
43         drec = new DATAREC(this, emu);
44         cpu = new I8080(this, emu);     // 8085
45         pio = new I8155(this, emu);     // 8156
46         memory = new MEMORY(this, emu);
47 #if defined(_USE_QT)
48         cpu->set_device_name(_T("CPU(i8080)"));
49 #endif  
50         
51         io = new IO(this, emu);
52 #if defined(_USE_QT)
53         io->set_device_name(_T("I/O"));
54 #endif  
55         
56         // set contexts
57         event->set_context_cpu(cpu);
58         event->set_context_sound(drec);
59         
60         drec->set_context_ear(io, SIG_IO_DREC_EAR, 1);
61         cpu->set_context_sod(drec, SIG_DATAREC_MIC, 1);
62         pio->set_context_port_b(io, SIG_IO_PORT_B, 0xff, 0);
63         pio->set_context_port_c(io, SIG_IO_PORT_C, 0xff, 0);
64         pio->set_context_timer(cpu, SIG_I8085_RST7, 1);
65         pio->set_constant_clock(CPU_CLOCKS);    // from 8085 CLOCK OUT
66         
67         io->set_context_drec(drec);
68         io->set_context_cpu(cpu);
69         io->set_context_pio(pio);
70         io->set_vram_ptr(vram);
71         
72         // cpu bus
73         cpu->set_context_mem(memory);
74         cpu->set_context_io(io);
75         cpu->set_context_intr(io);
76 #ifdef USE_DEBUGGER
77         cpu->set_context_debugger(new DEBUGGER(this, emu));
78 #endif
79         
80         // memory bus
81         memset(rom, 0xff, sizeof(rom));
82         
83         memory->read_bios(_T("BIOS.ROM"), rom, sizeof(rom));
84         
85         memory->set_memory_r(0x0000, 0x1fff, rom);
86         memory->set_memory_rw(0x4000, 0x43ff, vram);
87         memory->set_memory_rw(0x6000, 0x60ff, ram);     // 8156
88         
89         // initialize all devices
90         for(DEVICE* device = first_device; device; device = device->next_device) {
91                 device->initialize();
92         }
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         drec->set_volume(0, decibel_l, decibel_r);
188 }
189 #endif
190
191 // ----------------------------------------------------------------------------
192 // user interface
193 // ----------------------------------------------------------------------------
194
195 void VM::play_tape(const _TCHAR* file_path)
196 {
197         if(drec->play_tape(file_path)) {
198                 drec->set_remote(true);
199                 io->open_tape();
200         }
201 }
202
203 void VM::rec_tape(const _TCHAR* file_path)
204 {
205         if(drec->rec_tape(file_path)) {
206                 drec->set_remote(true);
207                 io->open_tape();
208         }
209 }
210
211 void VM::close_tape()
212 {
213         drec->close_tape();
214         drec->set_remote(false);
215 }
216
217 bool VM::is_tape_inserted()
218 {
219         return drec->is_tape_inserted();
220 }
221
222 bool VM::is_tape_playing()
223 {
224         return drec->is_tape_playing();
225 }
226
227 bool VM::is_tape_recording()
228 {
229         return drec->is_tape_recording();
230 }
231
232 int VM::get_tape_position()
233 {
234         return drec->get_tape_position();
235 }
236
237 void VM::push_play()
238 {
239         drec->set_ff_rew(0);
240         drec->set_remote(true);
241 }
242
243 void VM::push_stop()
244 {
245         drec->set_remote(false);
246 }
247
248 void VM::push_fast_forward()
249 {
250         drec->set_ff_rew(1);
251         drec->set_remote(true);
252 }
253
254 void VM::push_fast_rewind()
255 {
256         drec->set_ff_rew(-1);
257         drec->set_remote(true);
258 }
259
260 bool VM::is_frame_skippable()
261 {
262         return event->is_frame_skippable();
263 }
264
265 void VM::update_config()
266 {
267         for(DEVICE* device = first_device; device; device = device->next_device) {
268                 device->update_config();
269         }
270 }
271
272 #define STATE_VERSION   2
273
274 void VM::save_state(FILEIO* state_fio)
275 {
276         state_fio->FputUint32(STATE_VERSION);
277         
278         for(DEVICE* device = first_device; device; device = device->next_device) {
279                 device->save_state(state_fio);
280         }
281         state_fio->Fwrite(ram, sizeof(ram), 1);
282         state_fio->Fwrite(vram, sizeof(vram), 1);
283 }
284
285 bool VM::load_state(FILEIO* state_fio)
286 {
287         if(state_fio->FgetUint32() != STATE_VERSION) {
288                 return false;
289         }
290         for(DEVICE* device = first_device; device; device = device->next_device) {
291                 if(!device->load_state(state_fio)) {
292                         return false;
293                 }
294         }
295         state_fio->Fread(ram, sizeof(ram), 1);
296         state_fio->Fread(vram, sizeof(vram), 1);
297         return true;
298 }
299