OSDN Git Service

[VM][OSD] Add upstream devices/OSD updates.
[csp-qt/common_source_project-fm7.git] / source / src / vm / trnjr / trnjr.cpp
1 /*
2         EPS TRN Junior Emulator 'eTRNJunior'
3
4         Author : Takeda.Toshiya
5         Date   : 2022.07.02-
6
7         [ virtual machine ]
8 */
9
10 #include "trnjr.h"
11 #include "../../emu.h"
12 #include "../device.h"
13 #include "../event.h"
14
15 #include "../i8255.h"
16 #include "../io.h"
17 #include "../midi.h"
18 #include "../speaker.h"
19 #include "../tmpz84c015.h"
20 #include "../z80.h"
21 #include "../z80ctc.h"
22 #include "../z80sio.h"
23
24 #ifdef USE_DEBUGGER
25 #include "../debugger.h"
26 #endif
27
28 #include "display.h"
29 #include "membus.h"
30
31 // ----------------------------------------------------------------------------
32 // initialize
33 // ----------------------------------------------------------------------------
34
35 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
36 {
37         // create devices
38         first_device = last_device = NULL;
39         dummy = new DEVICE(this, emu);  // must be 1st device
40         event = new EVENT(this, emu);   // must be 2nd device
41         
42         pio1 = new I8255(this, emu);
43         pio1->set_device_name(_T("8255 PIO (7-Seg/Keyboard)"));
44         pio2 = new I8255(this, emu);
45         pio2->set_device_name(_T("8255 PIO (ROM Writer)"));
46         io = new IO(this, emu);
47         midi = new MIDI(this, emu);
48         speaker = new SPEAKER(this, emu);
49         // TMPZ84C013
50         cpudev = new TMPZ84C015(this, emu);
51         cpudev->set_context_ctc(new Z80CTC(this, emu));
52         cpudev->set_context_sio(new Z80SIO(this, emu));
53         cpu = new Z80(this, emu);
54         
55         display = new DISPLAY(this, emu);
56         memory = new MEMBUS(this, emu);
57         
58         // set contexts
59         event->set_context_cpu(cpu);
60         event->set_context_sound(speaker);
61         
62         cpudev->set_context_ctc_zc1(cpudev, SIG_TMPZ84C015_SIO_TX_CLK_CH0, 1);
63         cpudev->set_context_ctc_zc1(cpudev, SIG_TMPZ84C015_SIO_RX_CLK_CH0, 1);
64         cpudev->set_context_ctc_zc2(cpudev, SIG_TMPZ84C015_SIO_TX_CLK_CH1, 1);
65         cpudev->set_context_ctc_zc2(cpudev, SIG_TMPZ84C015_SIO_RX_CLK_CH1, 1);
66         cpudev->set_context_ctc_zc3(cpu, SIG_CPU_NMI, 1);
67         cpudev->set_context_sio_send(1, midi, SIG_MIDI_OUT);
68         pio1->set_context_port_a(display, SIG_DISPLAY_PORT_A, 0xff, 0);
69         pio1->set_context_port_b(speaker, SIG_SPEAKER_SAMPLE, 0xff, 0);
70         pio1->set_context_port_c(display, SIG_DISPLAY_PORT_C, 0xf0, 0);
71         midi->set_context_in(cpudev, SIG_TMPZ84C015_SIO_RECV_CH1, 0xff);
72         
73         display->set_context_pio(pio1);
74         memory->set_context_cpudev(cpudev);
75         
76         // cpu bus
77         cpu->set_context_mem(memory);
78         cpu->set_context_io(io);
79         cpu->set_context_intr(cpudev);
80 #ifdef USE_DEBUGGER
81         cpu->set_context_debugger(new DEBUGGER(this, emu));
82 #endif
83         
84         // z80 family daisy chain
85         cpudev->set_context_intr(cpu, 0);
86         
87         // memory bus
88         memset(ram, 0x00, sizeof(ram));
89         memset(rom, 0xff, sizeof(rom));
90         
91         memory->read_bios(_T("MON.ROM"), rom, sizeof(rom));
92         
93         memory->set_memory_r (0x0000, 0x7fff, rom);
94         memory->set_memory_rw(0x8000, 0xffff, ram);
95         
96         // i/o bus
97         cpudev->set_iomap(io);
98         io->set_iomap_range_rw(0x60, 0x63, pio1);
99         io->set_iomap_range_rw(0x64, 0x67, pio2);
100 //      io->set_iomap_range_rw(0x6c, 0x6f, fdc ); // uPD72605
101         
102         // initialize all devices
103         for(DEVICE* device = first_device; device; device = device->next_device) {
104                 device->initialize();
105         }
106 }
107
108 VM::~VM()
109 {
110         // delete all devices
111         for(DEVICE* device = first_device; device;) {
112                 DEVICE *next_device = device->next_device;
113                 device->release();
114                 delete device;
115                 device = next_device;
116         }
117 }
118
119 DEVICE* VM::get_device(int id)
120 {
121         for(DEVICE* device = first_device; device; device = device->next_device) {
122                 if(device->this_device_id == id) {
123                         return device;
124                 }
125         }
126         return NULL;
127 }
128
129 // ----------------------------------------------------------------------------
130 // drive virtual machine
131 // ----------------------------------------------------------------------------
132
133 void VM::reset()
134 {
135         // reset all devices
136         for(DEVICE* device = first_device; device; device = device->next_device) {
137                 device->reset();
138         }
139 }
140
141 void VM::run()
142 {
143         event->drive();
144 }
145
146 // ----------------------------------------------------------------------------
147 // debugger
148 // ----------------------------------------------------------------------------
149
150 #ifdef USE_DEBUGGER
151 DEVICE *VM::get_cpu(int index)
152 {
153         if(index == 0) {
154                 return cpu;
155         }
156         return NULL;
157 }
158 #endif
159
160 // ----------------------------------------------------------------------------
161 // draw screen
162 // ----------------------------------------------------------------------------
163
164 void VM::draw_screen()
165 {
166         display->draw_screen();
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         speaker->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                 speaker->set_volume(0, decibel_l, decibel_r);
197         }
198 }
199 #endif
200
201 // ----------------------------------------------------------------------------
202 // notify key
203 // ----------------------------------------------------------------------------
204
205 void VM::key_down(int code, bool repeat)
206 {
207 }
208
209 void VM::key_up(int code)
210 {
211 }
212
213 // ----------------------------------------------------------------------------
214 // user interface
215 // ----------------------------------------------------------------------------
216
217 void VM::load_binary(int drv, const _TCHAR* file_path)
218 {
219         if(drv == 0) {
220                 memory->read_image(file_path, ram, sizeof(ram));
221         }
222 }
223
224 void VM::save_binary(int drv, const _TCHAR* file_path)
225 {
226         if(drv == 0) {
227                 memory->write_image(file_path, ram, sizeof(ram));
228         }
229 }
230
231 bool VM::is_frame_skippable()
232 {
233         return event->is_frame_skippable();
234 }
235
236 void VM::update_config()
237 {
238         for(DEVICE* device = first_device; device; device = device->next_device) {
239                 device->update_config();
240         }
241 }
242
243 #define STATE_VERSION   1
244
245 bool VM::process_state(FILEIO* state_fio, bool loading)
246 {
247         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
248                 return false;
249         }
250         for(DEVICE* device = first_device; device; device = device->next_device) {
251                 const _TCHAR *name = char_to_tchar(typeid(*device).name() + 6); // skip "class "
252                 int len = (int)_tcslen(name);
253                 
254                 if(!state_fio->StateCheckInt32(len)) {
255                         return false;
256                 }
257                 if(!state_fio->StateCheckBuffer(name, len, 1)) {
258                         return false;
259                 }
260                 if(!device->process_state(state_fio, loading)) {
261                         return false;
262                 }
263         }
264         state_fio->StateArray(ram, sizeof(ram), 1);
265         return true;
266 }
267