OSDN Git Service

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