OSDN Git Service

[VM] TRY:Use namespace {VMNAME} to separate around VMs. This feature still apply...
[csp-qt/common_source_project-fm7.git] / source / src / vm / ex80 / ex80.cpp
1 /*
2         TOSHIBA EX-80 Emulator 'eEX-80'
3
4         Author : Takeda.Toshiya
5         Date   : 2015.12.10-
6
7         [ virtual machine ]
8 */
9
10 #include "ex80.h"
11 #include "../../emu.h"
12 #include "../device.h"
13 #include "../event.h"
14
15 #include "../i8080.h"
16 #include "../i8251.h"
17 #include "../i8255.h"
18 #include "../io.h"
19 #include "../pcm1bit.h"
20
21 #ifdef USE_DEBUGGER
22 #include "../debugger.h"
23 #endif
24
25 #include "./cmt.h"
26 #include "./display.h"
27 #include "./keyboard.h"
28 #include "./memory.h"
29
30 using EX80::CMT;
31 using EX80::DISPLAY;
32 using EX80::KEYBOARD;
33 using EX80::MEMORY;
34
35 // ----------------------------------------------------------------------------
36 // initialize
37 // ----------------------------------------------------------------------------
38
39 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
40 {
41         // create devices
42         first_device = last_device = NULL;
43         dummy = new DEVICE(this, emu);  // must be 1st device
44         event = new EVENT(this, emu);   // must be 2nd device
45         
46         sio = new I8251(this, emu);
47         pio = new I8255(this, emu);
48         io = new IO(this, emu);
49         pcm = new PCM1BIT(this, emu);
50         cpu = new I8080(this, emu);
51         
52         cmt = new CMT(this, emu);
53         display = new DISPLAY(this, emu);
54         keyboard = new KEYBOARD(this, emu);
55         memory = new MEMORY(this, emu);
56         // Set names
57 #if defined(_USE_QT)
58         dummy->set_device_name(_T("1st Dummy"));
59         
60         pio->set_device_name(_T("i8255(SOUND/KEY/DISPLAY)"));
61         sio->set_device_name(_T("i8251(CMT)"));
62         pcm->set_device_name(_T("SOUND OUT"));
63 #endif
64         
65         // set contexts
66         event->set_context_cpu(cpu);
67         event->set_context_sound(pcm);
68         
69         sio->set_context_out(cmt, SIG_CMT_OUT);
70         pio->set_context_port_c(pcm, SIG_PCM1BIT_SIGNAL, 0x08, 0);
71         pio->set_context_port_c(keyboard, SIG_KEYBOARD_COLUMN, 0x70, 0);
72         pio->set_context_port_c(display, SIG_DISPLAY_DMA, 0x80, 0);
73         // Sound:: Force realtime rendering. This is temporally fix. 20161024 K.O
74         //pcm->set_realtime_render(true);
75         
76         cmt->set_context_sio(sio);
77         display->set_context_cpu(cpu);
78         display->set_ram_ptr(memory->get_ram());
79         keyboard->set_context_pio(pio);
80         memory->set_context_cpu(cpu);
81         
82         // cpu bus
83         cpu->set_context_mem(memory);
84         cpu->set_context_io(io);
85         cpu->set_context_intr(dummy);
86 #ifdef USE_DEBUGGER
87         cpu->set_context_debugger(new DEBUGGER(this, emu));
88 #endif
89         
90         // io bus
91         io->set_iomap_range_rw(0xdc, 0xdd, sio);
92         io->set_iomap_range_rw(0xf8, 0xfb, pio);
93         
94         // initialize all devices
95 #if defined(__GIT_REPO_VERSION)
96         strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
97 #endif
98         for(DEVICE* device = first_device; device; device = device->next_device) {
99                 device->initialize();
100         }
101 }
102
103 VM::~VM()
104 {
105         // delete all devices
106         for(DEVICE* device = first_device; device;) {
107                 DEVICE *next_device = device->next_device;
108                 device->release();
109                 delete device;
110                 device = next_device;
111         }
112 }
113
114 DEVICE* VM::get_device(int id)
115 {
116         for(DEVICE* device = first_device; device; device = device->next_device) {
117                 if(device->this_device_id == id) {
118                         return device;
119                 }
120         }
121         return NULL;
122 }
123
124 // ----------------------------------------------------------------------------
125 // drive virtual machine
126 // ----------------------------------------------------------------------------
127
128 void VM::reset()
129 {
130         // reset all devices
131         for(DEVICE* device = first_device; device; device = device->next_device) {
132                 device->reset();
133         }
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         display->draw_screen();
162 }
163
164 int VM::max_draw_ranges()
165 {
166         return (config.monitor_type == 0) ? 9 : 8;
167 }
168
169 // ----------------------------------------------------------------------------
170 // soud manager
171 // ----------------------------------------------------------------------------
172
173 void VM::initialize_sound(int rate, int samples)
174 {
175         // init sound manager
176         event->initialize_sound(rate, samples);
177         
178         // init sound gen
179         pcm->initialize_sound(rate, 8000);
180 }
181
182 uint16_t* VM::create_sound(int* extra_frames)
183 {
184         return event->create_sound(extra_frames);
185 }
186
187 int VM::get_sound_buffer_ptr()
188 {
189         return event->get_sound_buffer_ptr();
190 }
191
192 #ifdef USE_SOUND_VOLUME
193 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
194 {
195         if(ch == 0) {
196                 pcm->set_volume(0, decibel_l, decibel_r);
197         }
198 }
199 #endif
200
201 // ----------------------------------------------------------------------------
202 // user interface
203 // ----------------------------------------------------------------------------
204
205 void VM::load_binary(int drv, const _TCHAR* file_path)
206 {
207         if(drv == 0) {
208                 memory->load_binary(file_path);
209         }
210 }
211
212 void VM::save_binary(int drv, const _TCHAR* file_path)
213 {
214         if(drv == 0) {
215                 memory->save_binary(file_path);
216         }
217 }
218
219 void VM::play_tape(int drv, const _TCHAR* file_path)
220 {
221         cmt->play_tape(file_path);
222 }
223
224 void VM::rec_tape(int drv, const _TCHAR* file_path)
225 {
226         cmt->rec_tape(file_path);
227 }
228
229 void VM::close_tape(int drv)
230 {
231         cmt->close_tape();
232 }
233
234 bool VM::is_tape_inserted(int drv)
235 {
236         return cmt->is_tape_inserted();
237 }
238
239 bool VM::is_frame_skippable()
240 {
241         return event->is_frame_skippable();
242 }
243
244 void VM::update_config()
245 {
246         for(DEVICE* device = first_device; device; device = device->next_device) {
247                 device->update_config();
248         }
249 }
250
251 #define STATE_VERSION   2
252
253 bool VM::process_state(FILEIO* state_fio, bool loading)
254 {
255         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
256                 return false;
257         }
258         for(DEVICE* device = first_device; device; device = device->next_device) {
259                 // Note: typeid(foo).name is fixed by recent ABI.Not dec 6.
260                 // const char *name = typeid(*device).name();
261                 //       But, using get_device_name() instead of typeid(foo).name() 20181008 K.O
262                 const char *name = device->get_device_name();
263                 int len = strlen(name);
264                 
265                 if(!state_fio->StateCheckInt32(len)) {
266                         if(loading) {
267                                 printf("Class name len Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
268                         }
269                         return false;
270                 }
271                 if(!state_fio->StateCheckBuffer(name, len, 1)) {
272                         if(loading) {
273                                 printf("Class name Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
274                         }
275                         return false;
276                 }
277                 if(!device->process_state(state_fio, loading)) {
278                         if(loading) {
279                                 printf("Data loading Error: DEVID=%d\n", device->this_device_id);
280                         }
281                         return false;
282                 }
283         }
284         // Machine specified.
285         return true;
286 }
287