OSDN Git Service

87502e1b36c10ede738a1ee7e97ec436a4440639
[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 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         for(DEVICE* device = first_device; device; device = device->next_device) {
91                 device->initialize();
92         }
93         decl_state();
94 }
95
96 VM::~VM()
97 {
98         // delete all devices
99         for(DEVICE* device = first_device; device;) {
100                 DEVICE *next_device = device->next_device;
101                 device->release();
102                 delete device;
103                 device = next_device;
104         }
105 }
106
107 DEVICE* VM::get_device(int id)
108 {
109         for(DEVICE* device = first_device; device; device = device->next_device) {
110                 if(device->this_device_id == id) {
111                         return device;
112                 }
113         }
114         return NULL;
115 }
116
117 // ----------------------------------------------------------------------------
118 // drive virtual machine
119 // ----------------------------------------------------------------------------
120
121 void VM::reset()
122 {
123         // reset all devices
124         for(DEVICE* device = first_device; device; device = device->next_device) {
125                 device->reset();
126         }
127 }
128
129 void VM::run()
130 {
131         event->drive();
132 }
133
134 // ----------------------------------------------------------------------------
135 // debugger
136 // ----------------------------------------------------------------------------
137
138 #ifdef USE_DEBUGGER
139 DEVICE *VM::get_cpu(int index)
140 {
141         if(index == 0) {
142                 return cpu;
143         }
144         return NULL;
145 }
146 #endif
147
148 // ----------------------------------------------------------------------------
149 // draw screen
150 // ----------------------------------------------------------------------------
151
152 void VM::draw_screen()
153 {
154         display->draw_screen();
155 }
156
157 int VM::max_draw_ranges()
158 {
159         return (config.monitor_type == 0) ? 9 : 8;
160 }
161
162 // ----------------------------------------------------------------------------
163 // soud manager
164 // ----------------------------------------------------------------------------
165
166 void VM::initialize_sound(int rate, int samples)
167 {
168         // init sound manager
169         event->initialize_sound(rate, samples);
170         
171         // init sound gen
172         pcm->initialize_sound(rate, 8000);
173 }
174
175 uint16_t* VM::create_sound(int* extra_frames)
176 {
177         return event->create_sound(extra_frames);
178 }
179
180 int VM::get_sound_buffer_ptr()
181 {
182         return event->get_sound_buffer_ptr();
183 }
184
185 #ifdef USE_SOUND_VOLUME
186 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
187 {
188         if(ch == 0) {
189                 pcm->set_volume(0, decibel_l, decibel_r);
190         }
191 }
192 #endif
193
194 // ----------------------------------------------------------------------------
195 // user interface
196 // ----------------------------------------------------------------------------
197
198 void VM::load_binary(int drv, const _TCHAR* file_path)
199 {
200         if(drv == 0) {
201                 memory->load_binary(file_path);
202         }
203 }
204
205 void VM::save_binary(int drv, const _TCHAR* file_path)
206 {
207         if(drv == 0) {
208                 memory->save_binary(file_path);
209         }
210 }
211
212 void VM::play_tape(int drv, const _TCHAR* file_path)
213 {
214         cmt->play_tape(file_path);
215 }
216
217 void VM::rec_tape(int drv, const _TCHAR* file_path)
218 {
219         cmt->rec_tape(file_path);
220 }
221
222 void VM::close_tape(int drv)
223 {
224         cmt->close_tape();
225 }
226
227 bool VM::is_tape_inserted(int drv)
228 {
229         return cmt->is_tape_inserted();
230 }
231
232 bool VM::is_frame_skippable()
233 {
234         return event->is_frame_skippable();
235 }
236
237 void VM::update_config()
238 {
239         for(DEVICE* device = first_device; device; device = device->next_device) {
240                 device->update_config();
241         }
242 }
243
244 #define STATE_VERSION   2
245
246 #include "../../statesub.h"
247 #include "../../qt/gui/csp_logger.h"
248 extern CSP_Logger DLL_PREFIX_I *csp_logger;
249
250 void VM::decl_state(void)
251 {
252         state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::EX80_HEAD")), csp_logger);
253         for(DEVICE* device = first_device; device; device = device->next_device) {
254                 device->decl_state();
255         }
256 }
257
258 void VM::save_state(FILEIO* state_fio)
259 {
260         //state_fio->FputUint32(STATE_VERSION);
261         
262         if(state_entry != NULL) {
263                 state_entry->save_state(state_fio);
264         }
265         for(DEVICE* device = first_device; device; device = device->next_device) {
266                 device->save_state(state_fio);
267         }
268 }
269
270 bool VM::load_state(FILEIO* state_fio)
271 {
272         //if(state_fio->FgetUint32() != STATE_VERSION) {
273         //      return false;
274         //}
275         bool mb = false;
276         if(state_entry != NULL) {
277                 mb = state_entry->load_state(state_fio);
278         }
279         if(!mb) {
280                 emu->out_debug_log("INFO: HEADER DATA ERROR");
281                 return false;
282         }
283         for(DEVICE* device = first_device; device; device = device->next_device) {
284                 if(!device->load_state(state_fio)) {
285                         return false;
286                 }
287         }
288         return true;
289 }
290