OSDN Git Service

[VM][Qt] Merge upstream 2016-04-17.
[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         
40         drec = new DATAREC(this, emu);
41         cpu = new I8080(this, emu);     // 8085
42         pio = new I8155(this, emu);     // 8156
43         memory = new MEMORY(this, emu);
44         
45         io = new IO(this, emu);
46         
47         // set contexts
48         event->set_context_cpu(cpu);
49         event->set_context_sound(drec);
50         
51         drec->set_context_ear(io, SIG_IO_DREC_EAR, 1);
52         cpu->set_context_sod(drec, SIG_DATAREC_MIC, 1);
53         pio->set_context_port_b(io, SIG_IO_PORT_B, 0xff, 0);
54         pio->set_context_port_c(io, SIG_IO_PORT_C, 0xff, 0);
55         pio->set_context_timer(cpu, SIG_I8085_RST7, 1);
56         pio->set_constant_clock(CPU_CLOCKS);    // from 8085 CLOCK OUT
57         
58         io->set_context_drec(drec);
59         io->set_context_cpu(cpu);
60         io->set_context_pio(pio);
61         io->set_vram_ptr(vram);
62         
63         // cpu bus
64         cpu->set_context_mem(memory);
65         cpu->set_context_io(io);
66         cpu->set_context_intr(io);
67 #ifdef USE_DEBUGGER
68         cpu->set_context_debugger(new DEBUGGER(this, emu));
69 #endif
70         
71         // memory bus
72         memset(rom, 0xff, sizeof(rom));
73         
74         memory->read_bios(_T("BIOS.ROM"), rom, sizeof(rom));
75         
76         memory->set_memory_r(0x0000, 0x1fff, rom);
77         memory->set_memory_rw(0x4000, 0x43ff, vram);
78         memory->set_memory_rw(0x6000, 0x60ff, ram);     // 8156
79         
80         // initialize all devices
81         for(DEVICE* device = first_device; device; device = device->next_device) {
82                 device->initialize();
83         }
84 }
85
86 VM::~VM()
87 {
88         // delete all devices
89         for(DEVICE* device = first_device; device;) {
90                 DEVICE *next_device = device->next_device;
91                 device->release();
92                 delete device;
93                 device = next_device;
94         }
95 }
96
97 DEVICE* VM::get_device(int id)
98 {
99         for(DEVICE* device = first_device; device; device = device->next_device) {
100                 if(device->this_device_id == id) {
101                         return device;
102                 }
103         }
104         return NULL;
105 }
106
107 // ----------------------------------------------------------------------------
108 // drive virtual machine
109 // ----------------------------------------------------------------------------
110
111 void VM::reset()
112 {
113         // reset all devices
114         for(DEVICE* device = first_device; device; device = device->next_device) {
115                 device->reset();
116         }
117         pio->write_signal(SIG_I8155_PORT_A, 0xff, 0x80); // PA7=1
118         memset(ram, 0, sizeof(ram));
119         memset(vram, 0, sizeof(vram));
120 }
121
122 void VM::special_reset()
123 {
124         cpu->reset();
125 }
126
127 void VM::run()
128 {
129         event->drive();
130 }
131
132 // ----------------------------------------------------------------------------
133 // debugger
134 // ----------------------------------------------------------------------------
135
136 #ifdef USE_DEBUGGER
137 DEVICE *VM::get_cpu(int index)
138 {
139         if(index == 0) {
140                 return cpu;
141         }
142         return NULL;
143 }
144 #endif
145
146 // ----------------------------------------------------------------------------
147 // draw screen
148 // ----------------------------------------------------------------------------
149
150 void VM::draw_screen()
151 {
152         io->draw_screen();
153 }
154
155 // ----------------------------------------------------------------------------
156 // soud manager
157 // ----------------------------------------------------------------------------
158
159 void VM::initialize_sound(int rate, int samples)
160 {
161         // init sound manager
162         event->initialize_sound(rate, samples);
163 }
164
165 uint16_t* VM::create_sound(int* extra_frames)
166 {
167         return event->create_sound(extra_frames);
168 }
169
170 int VM::get_sound_buffer_ptr()
171 {
172         return event->get_sound_buffer_ptr();
173 }
174
175 #ifdef USE_SOUND_VOLUME
176 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
177 {
178         drec->set_volume(0, decibel_l, decibel_r);
179 }
180 #endif
181
182 // ----------------------------------------------------------------------------
183 // user interface
184 // ----------------------------------------------------------------------------
185
186 void VM::play_tape(const _TCHAR* file_path)
187 {
188         if(drec->play_tape(file_path)) {
189                 drec->set_remote(true);
190                 io->open_tape();
191         }
192 }
193
194 void VM::rec_tape(const _TCHAR* file_path)
195 {
196         if(drec->rec_tape(file_path)) {
197                 drec->set_remote(true);
198                 io->open_tape();
199         }
200 }
201
202 void VM::close_tape()
203 {
204         drec->close_tape();
205         drec->set_remote(false);
206 }
207
208 bool VM::is_tape_inserted()
209 {
210         return drec->is_tape_inserted();
211 }
212
213 bool VM::is_tape_playing()
214 {
215         return drec->is_tape_playing();
216 }
217
218 bool VM::is_tape_recording()
219 {
220         return drec->is_tape_recording();
221 }
222
223 int VM::get_tape_position()
224 {
225         return drec->get_tape_position();
226 }
227
228 void VM::push_play()
229 {
230         drec->set_ff_rew(0);
231         drec->set_remote(true);
232 }
233
234 void VM::push_stop()
235 {
236         drec->set_remote(false);
237 }
238
239 void VM::push_fast_forward()
240 {
241         drec->set_ff_rew(1);
242         drec->set_remote(true);
243 }
244
245 void VM::push_fast_rewind()
246 {
247         drec->set_ff_rew(-1);
248         drec->set_remote(true);
249 }
250
251 bool VM::is_frame_skippable()
252 {
253         return event->is_frame_skippable();
254 }
255
256 void VM::update_config()
257 {
258         for(DEVICE* device = first_device; device; device = device->next_device) {
259                 device->update_config();
260         }
261 }
262
263 #define STATE_VERSION   2
264
265 void VM::save_state(FILEIO* state_fio)
266 {
267         state_fio->FputUint32(STATE_VERSION);
268         
269         for(DEVICE* device = first_device; device; device = device->next_device) {
270                 device->save_state(state_fio);
271         }
272         state_fio->Fwrite(ram, sizeof(ram), 1);
273         state_fio->Fwrite(vram, sizeof(vram), 1);
274 }
275
276 bool VM::load_state(FILEIO* state_fio)
277 {
278         if(state_fio->FgetUint32() != STATE_VERSION) {
279                 return false;
280         }
281         for(DEVICE* device = first_device; device; device = device->next_device) {
282                 if(!device->load_state(state_fio)) {
283                         return false;
284                 }
285         }
286         state_fio->Fread(ram, sizeof(ram), 1);
287         state_fio->Fread(vram, sizeof(vram), 1);
288         return true;
289 }
290