OSDN Git Service

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