OSDN Git Service

[VM][SN76489AN][YM2151][YM2203] Add write_debug_reg() and get_debug_regs().
[csp-qt/common_source_project-fm7.git] / source / src / vm / yis / yis.cpp
1 /*
2         YAMAHA YIS Emulator 'eYIS'
3
4         Author : Takeda.Toshiya
5         Date   : 2017.04.13-
6
7         [ virtual machine ]
8 */
9
10 #include "yis.h"
11 #include "../../emu.h"
12 #include "../device.h"
13 #include "../event.h"
14
15 #include "../m6502.h"
16 #include "../io.h"
17 #include "../memory.h"
18 #include "../am9511.h"
19 #include "../beep.h"
20 #include "../disk.h"
21 #include "../mb8877.h"
22 #include "../mc6820.h"
23 #include "../mc6844.h"
24 #include "../mc6850.h"
25 #include "../msm58321.h"
26 #include "../noise.h"
27
28 #ifdef USE_DEBUGGER
29 #include "../debugger.h"
30 #endif
31
32 #include "calendar.h"
33 #include "display.h"
34 #include "floppy.h"
35 #include "keyboard.h"
36 #include "mapper.h"
37 #include "sound.h"
38
39 using YIS::CALENDAR;
40 using YIS::DISPLAY;
41 using YIS::FLOPPY;
42 using YIS::KEYBOARD;
43 using YIS::MAPPER;
44 using YIS::SOUND;
45 // ----------------------------------------------------------------------------
46 // initialize
47 // ----------------------------------------------------------------------------
48
49 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
50 {
51         // create devices
52         first_device = last_device = NULL;
53         dummy = new DEVICE(this, emu);  // must be 1st device
54         event = new EVENT(this, emu);   // must be 2nd device
55         
56         cpu = new M6502(this, emu);     // YM-2002
57         io = new IO(this, emu);
58         memory = new MEMORY(this, emu);
59         apu = new AM9511(this, emu);
60         beep = new BEEP(this, emu);
61 #ifdef USE_DEBUGGER
62         beep->set_context_debugger(new DEBUGGER(this, emu));
63 #endif
64         fdc = new MB8877(this, emu);
65 #ifdef USE_DEBUGGER
66         fdc->set_context_debugger(new DEBUGGER(this, emu));
67 #endif
68         fdc->set_context_noise_seek(new NOISE(this, emu));
69         fdc->set_context_noise_head_down(new NOISE(this, emu));
70         fdc->set_context_noise_head_up(new NOISE(this, emu));
71         pia = new MC6820(this, emu);    // MB8874
72         dma = new MC6844(this, emu);    // HD46504
73         acia1 = new MC6850(this, emu);  // MB8863
74         acia2 = new MC6850(this, emu);
75         rtc = new MSM58321(this, emu);  // MSM5832RS
76         
77         calendar = new CALENDAR(this, emu);
78         display = new DISPLAY(this, emu);
79         floppy = new FLOPPY(this, emu);
80         keyboard = new KEYBOARD(this, emu);
81         mapper = new MAPPER(this, emu);
82         sound = new SOUND(this, emu);
83         
84         // set contexts
85         event->set_context_cpu(cpu);
86         event->set_context_sound(beep);
87         event->set_context_sound(fdc->get_context_noise_seek());
88         event->set_context_sound(fdc->get_context_noise_head_down());
89         event->set_context_sound(fdc->get_context_noise_head_up());
90         
91         fdc->set_context_drq(dma, SIG_MC6844_TX_RQ_0, 1);
92         dma->set_context_memory(memory);
93         dma->set_context_ch0(fdc);
94         
95         calendar->set_context_rtc(rtc);
96         floppy->set_context_fdc(fdc);
97         keyboard->set_context_cpu(cpu);
98         mapper->set_context_memory(memory);
99         sound->set_context_beep(beep);
100         
101         // cpu bus
102         cpu->set_context_mem(memory);
103         cpu->set_context_intr(dummy);
104 #ifdef USE_DEBUGGER
105         cpu->set_context_debugger(new DEBUGGER(this, emu));
106 #endif
107         
108         // memory bus
109         memory->read_bios(_T("BIOS.ROM"), rom, sizeof(rom));
110         // $0000-$efff will be mapped in mapper class
111         memory->set_memory_mapped_io_rw(0xf000, 0xf0ff, io);
112         memory->set_memory_r(0xf100, 0xffff, rom + 0x100);
113         
114         // io bus
115         io->set_iomap_range_rw(0xf000, 0xf016, dma);
116         io->set_iomap_range_rw(0xf020, 0xf023, fdc);
117         io->set_iomap_single_w(0xf024, floppy);
118         io->set_iomap_single_rw(0xf030, keyboard);
119         io->set_iomap_single_r(0xf031, keyboard);
120         io->set_iomap_range_w(0xf031, 0xf032, sound);
121         io->set_iomap_range_rw(0xf034, 0xf035, apu);
122         io->set_iomap_range_rw(0xf036, 0xf037, calendar);
123         io->set_iomap_range_rw(0xf038, 0xf03b, pia);
124         io->set_iomap_range_rw(0xf03c, 0xf03d, acia1);
125         io->set_iomap_range_rw(0xf03e, 0xf03f, acia2);
126         io->set_iomap_range_rw(0xf040, 0xf04b, display);
127         io->set_iomap_range_rw(0xf04f, 0xf05f, mapper);
128 //      io->set_iomap_range_rw(0xf060, 0xf06f, keyboard);
129         
130         // initialize all devices
131 #if defined(__GIT_REPO_VERSION)
132         strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
133 #endif
134         for(DEVICE* device = first_device; device; device = device->next_device) {
135                 device->initialize();
136         }
137         for(int i = 0; i < MAX_DRIVE; i++) {
138                 fdc->set_drive_type(i, DRIVE_TYPE_2DD); // 1DD
139                 fdc->set_track_size(i, 6238);
140         }
141 }
142
143 VM::~VM()
144 {
145         // delete all devices
146         for(DEVICE* device = first_device; device;) {
147                 DEVICE *next_device = device->next_device;
148                 device->release();
149                 delete device;
150                 device = next_device;
151         }
152 }
153
154 DEVICE* VM::get_device(int id)
155 {
156         for(DEVICE* device = first_device; device; device = device->next_device) {
157                 if(device->this_device_id == id) {
158                         return device;
159                 }
160         }
161         return NULL;
162 }
163
164 // ----------------------------------------------------------------------------
165 // drive virtual machine
166 // ----------------------------------------------------------------------------
167
168 void VM::reset()
169 {
170         // reset all devices
171         for(DEVICE* device = first_device; device; device = device->next_device) {
172                 device->reset();
173         }
174 }
175
176 void VM::run()
177 {
178         event->drive();
179 }
180
181 // ----------------------------------------------------------------------------
182 // debugger
183 // ----------------------------------------------------------------------------
184
185 #ifdef USE_DEBUGGER
186 DEVICE *VM::get_cpu(int index)
187 {
188         if(index == 0) {
189                 return cpu;
190         }
191         return NULL;
192 }
193 #endif
194
195 // ----------------------------------------------------------------------------
196 // draw screen
197 // ----------------------------------------------------------------------------
198
199 void VM::draw_screen()
200 {
201         display->draw_screen();
202 }
203
204 // ----------------------------------------------------------------------------
205 // soud manager
206 // ----------------------------------------------------------------------------
207
208 void VM::initialize_sound(int rate, int samples)
209 {
210         // init sound manager
211         event->initialize_sound(rate, samples);
212         
213         // init sound gen
214         beep->initialize_sound(rate, 49152 / 0x80, 8000);
215 }
216
217 uint16_t* VM::create_sound(int* extra_frames)
218 {
219         return event->create_sound(extra_frames);
220 }
221
222 int VM::get_sound_buffer_ptr()
223 {
224         return event->get_sound_buffer_ptr();
225 }
226
227 #ifdef USE_SOUND_VOLUME
228 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
229 {
230         if(ch == 0) {
231                 beep->set_volume(0, decibel_l, decibel_r);
232         } else if(ch == 1) {
233                 fdc->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
234                 fdc->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
235                 fdc->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
236         }
237 }
238 #endif
239
240 // ----------------------------------------------------------------------------
241 // notify key
242 // ----------------------------------------------------------------------------
243
244 void VM::key_down(int code, bool repeat)
245 {
246         if(!repeat) {
247                 keyboard->key_down(code);
248         }
249 }
250
251 void VM::key_up(int code)
252 {
253 }
254
255 bool VM::get_caps_locked()
256 {
257         return keyboard->get_caps_locked();
258 }
259
260 bool VM::get_kana_locked()
261 {
262         return keyboard->get_kana_locked();
263 }
264
265 // ----------------------------------------------------------------------------
266 // user interface
267 // ----------------------------------------------------------------------------
268
269 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
270 {
271         fdc->open_disk(drv, file_path, bank);
272 }
273
274 void VM::close_floppy_disk(int drv)
275 {
276         fdc->close_disk(drv);
277 }
278
279 bool VM::is_floppy_disk_inserted(int drv)
280 {
281         return fdc->is_disk_inserted(drv);
282 }
283
284 void VM::is_floppy_disk_protected(int drv, bool value)
285 {
286         fdc->is_disk_protected(drv, value);
287 }
288
289 bool VM::is_floppy_disk_protected(int drv)
290 {
291         return fdc->is_disk_protected(drv);
292 }
293
294 uint32_t VM::is_floppy_disk_accessed()
295 {
296         return fdc->read_signal(0);
297 }
298
299 bool VM::is_frame_skippable()
300 {
301         return event->is_frame_skippable();
302 }
303
304 void VM::update_config()
305 {
306         for(DEVICE* device = first_device; device; device = device->next_device) {
307                 device->update_config();
308         }
309 }
310
311 #define STATE_VERSION   2
312
313 bool VM::process_state(FILEIO* state_fio, bool loading)
314 {
315         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
316                 return false;
317         }
318         for(DEVICE* device = first_device; device; device = device->next_device) {
319                 // Note: typeid(foo).name is fixed by recent ABI.Not dec 6.
320                 // const char *name = typeid(*device).name();
321                 //       But, using get_device_name() instead of typeid(foo).name() 20181008 K.O
322                 const char *name = device->get_device_name();
323                 int len = strlen(name);
324                 
325                 if(!state_fio->StateCheckInt32(len)) {
326                         if(loading) {
327                                 printf("Class name len Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
328                         }
329                         return false;
330                 }
331                 if(!state_fio->StateCheckBuffer(name, len, 1)) {
332                         if(loading) {
333                                 printf("Class name Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
334                         }
335                         return false;
336                 }
337                 if(!device->process_state(state_fio, loading)) {
338                         if(loading) {
339                                 printf("Data loading Error: DEVID=%d\n", device->this_device_id);
340                         }
341                         return false;
342                 }
343         }
344         // Machine specified.
345         return true;
346 }