OSDN Git Service

[General] Add upstream 2022-06-08 .
[csp-qt/common_source_project-fm7.git] / source / src / vm / crc80 / crc80.cpp
1 /*
2         Computer Research CRC-80 Emulator 'eCRC-80'
3
4         Author : Takeda.Toshiya
5         Date   : 2022.06.05-
6
7         [ virtual machine ]
8 */
9
10 #include "./crc80.h"
11 #include "../../emu.h"
12 #include "../device.h"
13 #include "../event.h"
14
15 #include "../datarec.h"
16 #include "../io.h"
17 #include "../memory.h"
18 #include "../noise.h"
19 #include "../not.h"
20 #include "../z80.h"
21 #include "../z80pio.h"
22
23 #ifdef USE_DEBUGGER
24 #include "../debugger.h"
25 #endif
26
27 #include "./display.h"
28 #include "./membus.h"
29
30 using CRC80::DISPLAY;
31 using CRC80::MEMBUS;
32
33 // ----------------------------------------------------------------------------
34 // initialize
35 // ----------------------------------------------------------------------------
36
37 VM::VM(EMU_TEMPLATE* parent_emu) : VM_TEMPLATE(parent_emu)
38 {
39         // create devices
40         first_device = last_device = NULL;
41         dummy = new DEVICE(this, emu);  // must be 1st device
42         event = new EVENT(this, emu);   // must be 2nd device
43         
44         drec = new DATAREC(this, emu);
45         drec->set_context_noise_play(new NOISE(this, emu));
46         drec->set_context_noise_stop(new NOISE(this, emu));
47         drec->set_context_noise_fast(new NOISE(this, emu));
48         io = new IO(this, emu);
49         m_not = new NOT(this, emu);
50         cpu = new Z80(this, emu);
51         pio = new Z80PIO(this, emu);
52         
53         display = new DISPLAY(this, emu);
54         memory = new MEMBUS(this, emu);
55         
56         // set contexts
57         event->set_context_cpu(cpu);
58         event->set_context_sound(drec);
59         event->set_context_sound(drec->get_context_noise_play());
60         event->set_context_sound(drec->get_context_noise_stop());
61         event->set_context_sound(drec->get_context_noise_fast());
62         
63         drec->set_context_ear(m_not, SIG_NOT_INPUT, 1);
64         m_not->set_context_out(pio, SIG_Z80PIO_PORT_B, 0x80);
65         pio->set_context_port_b(drec, SIG_DATAREC_MIC, 0x40, 0);
66         pio->set_context_port_a(display, SIG_DISPLAY_PA, 0xff, 0);
67         pio->set_context_port_b(display, SIG_DISPLAY_PB, 0x0f, 0);
68         
69         display->set_context_pio(pio);
70         memory->set_context_cpu(cpu);
71         
72         // cpu bus
73         cpu->set_context_mem(memory);
74         cpu->set_context_io(io);
75         cpu->set_context_intr(pio);
76 #ifdef USE_DEBUGGER
77         cpu->set_context_debugger(new DEBUGGER(this, emu));
78 #endif
79         
80         // memory bus
81         memset(mon, 0xff, sizeof(mon));
82         memset(tty, 0xff, sizeof(tty));
83         memset(ext, 0xff, sizeof(ext));
84         memset(ram, 0x00, sizeof(ram));
85         
86         memory->read_bios(_T("MON.ROM"), mon, sizeof(mon));
87         memory->read_bios(_T("TTY.ROM"), tty, sizeof(tty));
88         memory->read_bios(_T("EXT.ROM"), ext, sizeof(ext));
89         
90         for(int i = 0; i < 0x8000; i += 0x1000) {
91                 memory->set_memory_r (i + 0x0000, i + 0x03ff, mon);
92                 memory->set_memory_r (i + 0x0400, i + 0x07ff, tty);
93                 memory->set_memory_r (i + 0x0800, i + 0x0bff, ext);
94                 memory->set_memory_rw(i + 0x8000, i + 0x8fff, ram);
95         }
96         
97         // i/o bus
98         for(int i = 0; i < 0x100; i += 4) {
99                 io->set_iomap_alias_rw(i + 0, pio, 0);
100                 io->set_iomap_alias_rw(i + 1, pio, 2);
101                 io->set_iomap_alias_rw(i + 2, pio, 1);
102                 io->set_iomap_alias_rw(i + 3, pio, 3);
103         }
104         
105         // initialize all devices
106         for(DEVICE* device = first_device; device; device = device->next_device) {
107                 device->initialize();
108         }
109         pio->write_signal(SIG_Z80PIO_PORT_B, (config.dipswitch & 2) ? 0 : 0xff, 0x10);
110 }
111
112 VM::~VM()
113 {
114         // delete all devices
115         for(DEVICE* device = first_device; device;) {
116                 DEVICE *next_device = device->next_device;
117                 device->release();
118                 delete device;
119                 device = next_device;
120         }
121 }
122
123 DEVICE* VM::get_device(int id)
124 {
125         for(DEVICE* device = first_device; device; device = device->next_device) {
126                 if(device->this_device_id == id) {
127                         return device;
128                 }
129         }
130         return NULL;
131 }
132
133 // ----------------------------------------------------------------------------
134 // drive virtual machine
135 // ----------------------------------------------------------------------------
136
137 void VM::reset()
138 {
139         // reset all devices
140         for(DEVICE* device = first_device; device; device = device->next_device) {
141                 device->reset();
142         }
143         pio->write_signal(SIG_Z80PIO_PORT_A, 0xff, 0xff);
144         pio->write_signal(SIG_Z80PIO_PORT_B, (config.dipswitch & 2) ? 0 : 0xff, 0x10);
145 }
146
147 void VM::run()
148 {
149         event->drive();
150 }
151
152 // ----------------------------------------------------------------------------
153 // debugger
154 // ----------------------------------------------------------------------------
155
156 #ifdef USE_DEBUGGER
157 DEVICE *VM::get_cpu(int index)
158 {
159         if(index == 0) {
160                 return cpu;
161         }
162         return NULL;
163 }
164 #endif
165
166 // ----------------------------------------------------------------------------
167 // draw screen
168 // ----------------------------------------------------------------------------
169
170 void VM::draw_screen()
171 {
172         display->draw_screen();
173 }
174
175 // ----------------------------------------------------------------------------
176 // soud manager
177 // ----------------------------------------------------------------------------
178
179 void VM::initialize_sound(int rate, int samples)
180 {
181         // init sound manager
182         event->initialize_sound(rate, samples);
183 }
184
185 uint16_t* VM::create_sound(int* extra_frames)
186 {
187         return event->create_sound(extra_frames);
188 }
189
190 int VM::get_sound_buffer_ptr()
191 {
192         return event->get_sound_buffer_ptr();
193 }
194
195 #ifdef USE_SOUND_VOLUME
196 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
197 {
198         if(ch == 0) {
199                 drec->set_volume(0, decibel_l, decibel_r);
200         } else if(ch == 1) {
201                 drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
202                 drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
203                 drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
204         }
205 }
206 #endif
207
208 // ----------------------------------------------------------------------------
209 // notify key
210 // ----------------------------------------------------------------------------
211
212 void VM::key_down(int code, bool repeat)
213 {
214 }
215
216 void VM::key_up(int code)
217 {
218 }
219
220 bool VM::get_caps_locked()
221 {
222         return false;
223 }
224
225 bool VM::get_kana_locked()
226 {
227         return false;
228 }
229
230 // ----------------------------------------------------------------------------
231 // user interface
232 // ----------------------------------------------------------------------------
233
234 void VM::load_binary(int drv, const _TCHAR* file_path)
235 {
236         memory->read_image(file_path, ram, sizeof(ram));
237 }
238
239 void VM::save_binary(int drv, const _TCHAR* file_path)
240 {
241         memory->write_image(file_path, ram, sizeof(ram));
242 }
243
244 void VM::play_tape(int drv, const _TCHAR* file_path)
245 {
246         if(drec->play_tape(file_path)) {
247                 push_play(drv);
248         }
249 }
250
251 void VM::rec_tape(int drv, const _TCHAR* file_path)
252 {
253         if(drec->rec_tape(file_path)) {
254                 push_play(drv);
255         }
256 }
257
258 void VM::close_tape(int drv)
259 {
260         emu->lock_vm();
261         push_stop(drv);
262         drec->close_tape();
263         emu->unlock_vm();
264 }
265
266 bool VM::is_tape_inserted(int drv)
267 {
268         return drec->is_tape_inserted();
269 }
270
271 bool VM::is_tape_playing(int drv)
272 {
273         return drec->is_tape_playing();
274 }
275
276 bool VM::is_tape_recording(int drv)
277 {
278         return drec->is_tape_recording();
279 }
280
281 int VM::get_tape_position(int drv)
282 {
283         return drec->get_tape_position();
284 }
285
286 const _TCHAR* VM::get_tape_message(int drv)
287 {
288         return drec->get_message();
289 }
290
291 void VM::push_play(int drv)
292 {
293         drec->set_remote(false);
294         drec->set_ff_rew(0);
295         drec->set_remote(true);
296 }
297
298 void VM::push_stop(int drv)
299 {
300         drec->set_remote(false);
301 }
302
303 void VM::push_fast_forward(int drv)
304 {
305         drec->set_remote(false);
306         drec->set_ff_rew(1);
307         drec->set_remote(true);
308 }
309
310 void VM::push_fast_rewind(int drv)
311 {
312         drec->set_remote(false);
313         drec->set_ff_rew(-1);
314         drec->set_remote(true);
315 }
316
317 bool VM::is_frame_skippable()
318 {
319         return event->is_frame_skippable();
320 }
321
322 void VM::update_config()
323 {
324         for(DEVICE* device = first_device; device; device = device->next_device) {
325                 device->update_config();
326         }
327 }
328
329 #define STATE_VERSION   1
330
331 bool VM::process_state(FILEIO* state_fio, bool loading)
332 {
333         if(!(VM_TEMPLATE::process_state_core(state_fio, loading, STATE_VERSION))) {
334                 return false;
335         }
336         // Machine specified.
337         state_fio->StateArray(ram, sizeof(ram), 1);
338         return true;
339 }
340