OSDN Git Service

b1d5666608cc365bde1c4a28b11e11afb69b5c5b
[csp-qt/common_source_project-fm7.git] / source / src / vm / tk80bs / tk80bs.cpp
1 /*\r
2         NEC TK-80BS (COMPO BS/80) Emulator 'eTK-80BS'\r
3 \r
4         Author : Takeda.Toshiya\r
5         Date   : 2008.08.26 -\r
6 \r
7         [ virtual machine ]\r
8 */\r
9 \r
10 #include "tk80bs.h"\r
11 #include "../../emu.h"\r
12 #include "../device.h"\r
13 #include "../event.h"\r
14 \r
15 #include "../i8080.h"\r
16 #include "../i8251.h"\r
17 #include "../i8255.h"\r
18 #include "../io.h"\r
19 #include "../memory.h"\r
20 #include "../pcm1bit.h"\r
21 \r
22 #ifdef USE_DEBUGGER\r
23 #include "../debugger.h"\r
24 #endif\r
25 \r
26 #include "cmt.h"\r
27 #include "display.h"\r
28 #include "keyboard.h"\r
29 \r
30 // ----------------------------------------------------------------------------\r
31 // initialize\r
32 // ----------------------------------------------------------------------------\r
33 \r
34 VM::VM(EMU* parent_emu) : emu(parent_emu)\r
35 {\r
36         // check configs\r
37 //      boot_mode = config.boot_mode;\r
38         boot_mode = -1;\r
39         \r
40         // create devices\r
41         first_device = last_device = NULL;\r
42         dummy = new DEVICE(this, emu);  // must be 1st device\r
43         event = new EVENT(this, emu);   // must be 2nd device\r
44         \r
45         sio_b = new I8251(this, emu);   // on TK-80BS\r
46         pio_b = new I8255(this, emu);\r
47         pio_t = new I8255(this, emu);   // on TK-80\r
48         memio = new IO(this, emu);\r
49         memory = new MEMORY(this, emu);\r
50         pcm0 = new PCM1BIT(this, emu);\r
51         pcm1 = new PCM1BIT(this, emu);\r
52         cpu = new I8080(this, emu);\r
53         \r
54         cmt = new CMT(this, emu);\r
55         display = new DISPLAY(this, emu);\r
56         keyboard = new KEYBOARD(this, emu);\r
57         \r
58         // set contexts\r
59         event->set_context_cpu(cpu);\r
60         event->set_context_sound(pcm0);\r
61         event->set_context_sound(pcm1);\r
62         \r
63 /*      8255 on TK-80\r
64         \r
65         PA      key matrix\r
66         PB0     serial in\r
67         PC0     serial out\r
68         PC1     sound #1\r
69         PC2     sound #2\r
70         PC4-6   key column\r
71         PC7     dma disable\r
72 */\r
73         sio_b->set_context_out(cmt, SIG_CMT_OUT);\r
74         pio_b->set_context_port_c(display, SIG_DISPLAY_MODE, 3, 0);\r
75         pio_t->set_context_port_c(pcm0, SIG_PCM1BIT_SIGNAL, 2, 0);\r
76         pio_t->set_context_port_c(pcm1, SIG_PCM1BIT_SIGNAL, 4, 0);\r
77         pio_t->set_context_port_c(keyboard, SIG_KEYBOARD_COLUMN, 0x70, 0);\r
78         pio_t->set_context_port_c(display, SIG_DISPLAY_DMA, 0x80, 0);\r
79         \r
80         cmt->set_context_sio(sio_b);\r
81         display->set_context_key(keyboard);\r
82         display->set_vram_ptr(vram);\r
83         display->set_led_ptr(ram + 0x3f8);\r
84         keyboard->set_context_pio_b(pio_b);\r
85         keyboard->set_context_pio_t(pio_t);\r
86         keyboard->set_context_cpu(cpu);\r
87         \r
88         // cpu bus\r
89         cpu->set_context_mem(memory);\r
90         cpu->set_context_io(pio_t);\r
91         cpu->set_context_intr(keyboard);\r
92 #ifdef USE_DEBUGGER\r
93         cpu->set_context_debugger(new DEBUGGER(this, emu));\r
94 #endif\r
95         \r
96         // memory bus\r
97         memset(mon, 0xff, sizeof(mon));\r
98         memset(bsmon, 0xff, sizeof(bsmon));\r
99         memset(ext, 0xff, sizeof(ext));\r
100         \r
101         static const uint8 top[3] = {0xc3, 0x00, 0xf0};\r
102         static const uint8 rst[3] = {0xc3, 0xdd, 0x83};\r
103         \r
104         if(!memory->read_bios(_T("TK80.ROM"), mon, sizeof(mon))) {\r
105                 // default\r
106                 memcpy(mon, top, sizeof(top));\r
107                 memcpy(mon + 0x38, rst, sizeof(rst));\r
108         }\r
109         if(memory->read_bios(_T("BSMON.ROM"), bsmon, sizeof(bsmon))) {\r
110                 // patch\r
111                 memcpy(mon + 0x38, rst, sizeof(rst));\r
112         }\r
113         memory->read_bios(_T("EXT.ROM"), ext, sizeof(ext));\r
114         \r
115         memory->set_memory_r(0x0000, 0x07ff, mon);\r
116         memory->set_memory_r(0x0c00, 0x7bff, ext);\r
117         memory->set_memory_mapped_io_rw(0x7c00, 0x7dff, memio);\r
118         memory->set_memory_rw(0x7e00, 0x7fff, vram);\r
119         memory->set_memory_rw(0x8000, 0xcfff, ram);\r
120         memory->set_memory_r(0xd000, 0xefff, basic);\r
121         memory->set_memory_r(0xf000, 0xffff, bsmon);\r
122         \r
123         // memory mapped i/o\r
124         memio->set_iomap_alias_rw(0x7df8, sio_b, 0);\r
125         memio->set_iomap_alias_rw(0x7df9, sio_b, 1);\r
126         memio->set_iomap_alias_rw(0x7dfc, pio_b, 0);\r
127         memio->set_iomap_alias_rw(0x7dfd, pio_b, 1);\r
128         memio->set_iomap_alias_rw(0x7dfe, pio_b, 2);\r
129         memio->set_iomap_alias_w(0x7dff, pio_b, 3);\r
130         \r
131         // initialize all devices\r
132         for(DEVICE* device = first_device; device; device = device->next_device) {\r
133                 device->initialize();\r
134         }\r
135 }\r
136 \r
137 VM::~VM()\r
138 {\r
139         // delete all devices\r
140         for(DEVICE* device = first_device; device;) {\r
141                 DEVICE *next_device = device->next_device;\r
142                 device->release();\r
143                 delete device;\r
144                 device = next_device;\r
145         }\r
146 }\r
147 \r
148 DEVICE* VM::get_device(int id)\r
149 {\r
150         for(DEVICE* device = first_device; device; device = device->next_device) {\r
151                 if(device->this_device_id == id) {\r
152                         return device;\r
153                 }\r
154         }\r
155         return NULL;\r
156 }\r
157 \r
158 // ----------------------------------------------------------------------------\r
159 // drive virtual machine\r
160 // ----------------------------------------------------------------------------\r
161 \r
162 void VM::reset()\r
163 {\r
164         // load basic rom\r
165         if(boot_mode != config.boot_mode) {\r
166                 memset(basic, 0xff, sizeof(basic));\r
167                 if(config.boot_mode == 0) {\r
168                         memory->read_bios(_T("LV1BASIC.ROM"), basic + 0x1000, 0x1000);\r
169                 } else {\r
170                         memory->read_bios(_T("LV2BASIC.ROM"), basic, sizeof(basic));\r
171                 }\r
172                 boot_mode = config.boot_mode;\r
173                 \r
174                 memset(ram, 0, sizeof(ram));\r
175                 memset(vram, 0x20, sizeof(vram));\r
176         }\r
177         \r
178         // reset all devices\r
179         for(DEVICE* device = first_device; device; device = device->next_device) {\r
180                 device->reset();\r
181         }\r
182         \r
183         // init 8255 on TK-80\r
184         pio_t->write_io8(0xfb, 0x92);\r
185         pio_t->write_signal(SIG_I8255_PORT_A, 0xff, 0xff);\r
186 }\r
187 \r
188 void VM::run()\r
189 {\r
190         event->drive();\r
191 }\r
192 \r
193 // ----------------------------------------------------------------------------\r
194 // debugger\r
195 // ----------------------------------------------------------------------------\r
196 \r
197 #ifdef USE_DEBUGGER\r
198 DEVICE *VM::get_cpu(int index)\r
199 {\r
200         if(index == 0) {\r
201                 return cpu;\r
202         }\r
203         return NULL;\r
204 }\r
205 #endif\r
206 \r
207 // ----------------------------------------------------------------------------\r
208 // draw screen\r
209 // ----------------------------------------------------------------------------\r
210 \r
211 void VM::draw_screen()\r
212 {\r
213         display->draw_screen();\r
214 }\r
215 \r
216 // ----------------------------------------------------------------------------\r
217 // soud manager\r
218 // ----------------------------------------------------------------------------\r
219 \r
220 void VM::initialize_sound(int rate, int samples)\r
221 {\r
222         // init sound manager\r
223         event->initialize_sound(rate, samples);\r
224         \r
225         // init sound gen\r
226         pcm0->init(rate, 8000);\r
227         pcm1->init(rate, 8000);\r
228 }\r
229 \r
230 uint16* VM::create_sound(int* extra_frames)\r
231 {\r
232         return event->create_sound(extra_frames);\r
233 }\r
234 \r
235 int VM::sound_buffer_ptr()\r
236 {\r
237         return event->sound_buffer_ptr();\r
238 }\r
239 \r
240 // ----------------------------------------------------------------------------\r
241 // notify key\r
242 // ----------------------------------------------------------------------------\r
243 \r
244 void VM::key_down(int code, bool repeat)\r
245 {\r
246         keyboard->key_down(code);\r
247 }\r
248 \r
249 void VM::key_up(int code)\r
250 {\r
251         keyboard->key_up(code);\r
252 }\r
253 \r
254 // ----------------------------------------------------------------------------\r
255 // user interface\r
256 // ----------------------------------------------------------------------------\r
257 \r
258 void VM::load_binary(int drv, _TCHAR* file_path)\r
259 {\r
260         if(drv == 0) {\r
261                 memory->read_image(file_path, ram, sizeof(ram));\r
262         }\r
263 }\r
264 \r
265 void VM::save_binary(int drv, _TCHAR* file_path)\r
266 {\r
267         if(drv == 0) {\r
268                 memory->write_image(file_path, ram, sizeof(ram));\r
269         }\r
270 }\r
271 \r
272 void VM::play_tape(_TCHAR* file_path)\r
273 {\r
274         cmt->play_tape(file_path);\r
275 }\r
276 \r
277 void VM::rec_tape(_TCHAR* file_path)\r
278 {\r
279         cmt->rec_tape(file_path);\r
280 }\r
281 \r
282 void VM::close_tape()\r
283 {\r
284         cmt->close_tape();\r
285 }\r
286 \r
287 bool VM::tape_inserted()\r
288 {\r
289         return cmt->tape_inserted();\r
290 }\r
291 \r
292 bool VM::now_skip()\r
293 {\r
294         return event->now_skip();\r
295 }\r
296 \r
297 void VM::update_config()\r
298 {\r
299         if(boot_mode != config.boot_mode) {\r
300                 // boot mode is changed !!!\r
301 //              boot_mode = config.boot_mode;\r
302                 reset();\r
303         } else {\r
304                 for(DEVICE* device = first_device; device; device = device->next_device) {\r
305                         device->update_config();\r
306                 }\r
307         }\r
308 }\r
309 \r