OSDN Git Service

f07bb8cfbb622dd62501892e1b8aaf04aa594348
[csp-qt/common_source_project-fm7.git] / source / src / vm / z80tvgame / z80tvgame.cpp
1 /*
2         Homebrew Z80 TV GAME SYSTEM Emulator 'eZ80TVGAME'
3
4         Author : Takeda.Toshiya
5         Date   : 2015.04.28-
6
7         [ virtual machine ]
8 */
9
10 // http://w01.tp1.jp/~a571632211/z80tvgame/index.html
11
12 #include "z80tvgame.h"
13 #include "../../emu.h"
14 #include "../device.h"
15 #include "../event.h"
16
17 #ifdef _USE_I8255
18 #include "../i8255.h"
19 #else
20 #include "../z80pio.h"
21 #endif
22 #include "../pcm1bit.h"
23 #include "../z80.h"
24
25 #ifdef USE_DEBUGGER
26 #include "../debugger.h"
27 #endif
28
29 #include "joystick.h"
30 #include "memory.h"
31
32 // ----------------------------------------------------------------------------
33 // initialize
34 // ----------------------------------------------------------------------------
35
36 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
37 {
38         // create devices
39         first_device = last_device = NULL;
40         dummy = new DEVICE(this, emu);  // must be 1st device
41         event = new EVENT(this, emu);   // must be 2nd device
42         dummy->set_device_name(_T("1st Dummy"));
43         
44 #ifdef _USE_I8255
45         pio = new I8255(this, emu);
46 #else
47         pio = new Z80PIO(this, emu);
48 #endif
49         pcm = new PCM1BIT(this, emu);
50         cpu = new Z80(this, emu);
51         
52         joystick = new JOYSTICK(this, emu);
53         memory = new MEMORY(this, emu);
54         
55         // set contexts
56         event->set_context_cpu(cpu);
57         event->set_context_sound(pcm);
58
59         // Sound:: Force realtime rendering. This is temporally fix. 20161024 K.O
60         //pcm->set_realtime_render(true);
61
62 #ifdef _USE_I8255
63         pio->set_context_port_c(pcm, SIG_PCM1BIT_SIGNAL, 1, 0);
64 #else
65         pio->set_context_port_b(pcm, SIG_PCM1BIT_SIGNAL, 1, 0);
66 #endif
67         joystick->set_context_pio(pio);
68         
69         // cpu bus
70         cpu->set_context_mem(memory);
71         cpu->set_context_io(pio);
72         cpu->set_context_intr(dummy);
73 #ifdef USE_DEBUGGER
74         cpu->set_context_debugger(new DEBUGGER(this, emu));
75 #endif
76         
77         // initialize all devices
78         for(DEVICE* device = first_device; device; device = device->next_device) {
79                 device->initialize();
80         }
81         decl_state();
82 }
83
84 VM::~VM()
85 {
86         // delete all devices
87         for(DEVICE* device = first_device; device;) {
88                 DEVICE *next_device = device->next_device;
89                 device->release();
90                 delete device;
91                 device = next_device;
92         }
93 }
94
95 DEVICE* VM::get_device(int id)
96 {
97         for(DEVICE* device = first_device; device; device = device->next_device) {
98                 if(device->this_device_id == id) {
99                         return device;
100                 }
101         }
102         return NULL;
103 }
104
105 // ----------------------------------------------------------------------------
106 // debugger
107 // ----------------------------------------------------------------------------
108
109 #ifdef USE_DEBUGGER
110 DEVICE *VM::get_cpu(int index)
111 {
112         if(index == 0) {
113                 return cpu;
114         }
115         return NULL;
116 }
117 #endif
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 // draw screen
138 // ----------------------------------------------------------------------------
139
140 void VM::draw_screen()
141 {
142         memory->draw_screen();
143 }
144
145 // ----------------------------------------------------------------------------
146 // soud manager
147 // ----------------------------------------------------------------------------
148
149 void VM::initialize_sound(int rate, int samples)
150 {
151         // init sound manager
152         event->initialize_sound(rate, samples);
153         
154         // init sound gen
155         pcm->initialize_sound(rate, 8000);
156 }
157
158 uint16_t* VM::create_sound(int* extra_frames)
159 {
160         return event->create_sound(extra_frames);
161 }
162
163 int VM::get_sound_buffer_ptr()
164 {
165         return event->get_sound_buffer_ptr();
166 }
167
168 #ifdef USE_SOUND_VOLUME
169 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
170 {
171         if(ch == 0) {
172                 pcm->set_volume(0, decibel_l, decibel_r);
173         }
174 }
175 #endif
176
177 // ----------------------------------------------------------------------------
178 // user interface
179 // ----------------------------------------------------------------------------
180
181 void VM::open_cart(int drv, const _TCHAR* file_path)
182 {
183         if(drv == 0) {
184                 memory->open_cart(file_path);
185                 reset();
186         }
187 }
188
189 void VM::close_cart(int drv)
190 {
191         if(drv == 0) {
192                 memory->close_cart();
193                 reset();
194         }
195 }
196
197 bool VM::is_cart_inserted(int drv)
198 {
199         if(drv == 0) {
200                 return memory->is_cart_inserted();
201         } else {
202                 return false;
203         }
204 }
205
206 bool VM::is_frame_skippable()
207 {
208         return event->is_frame_skippable();
209 }
210
211 void VM::update_config()
212 {
213         for(DEVICE* device = first_device; device; device = device->next_device) {
214                 device->update_config();
215         }
216 }
217
218 #define STATE_VERSION   2
219
220 #include "../../statesub.h"
221 #include "../../qt/gui/csp_logger.h"
222 extern CSP_Logger DLL_PREFIX_I *csp_logger;
223
224 void VM::decl_state(void)
225 {
226 #if defined(_USE_I8255)
227         state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::Z80_TV_GAME_I8255_HEAD")), csp_logger);
228 #else
229         state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::Z80_TV_GAME_Z80PIO_HEAD")), csp_logger);
230 #endif
231         for(DEVICE* device = first_device; device; device = device->next_device) {
232                 device->decl_state();
233         }
234 }
235
236 void VM::save_state(FILEIO* state_fio)
237 {
238         //state_fio->FputUint32(STATE_VERSION);
239         
240         if(state_entry != NULL) {
241                 state_entry->save_state(state_fio);
242         }
243         for(DEVICE* device = first_device; device; device = device->next_device) {
244                 device->save_state(state_fio);
245         }
246 }
247
248 bool VM::load_state(FILEIO* state_fio)
249 {
250         //if(state_fio->FgetUint32() != STATE_VERSION) {
251         //      return false;
252         //}
253         bool mb = false;
254         if(state_entry != NULL) {
255                 mb = state_entry->load_state(state_fio);
256         }
257         if(!mb) {
258                 emu->out_debug_log("INFO: HEADER DATA ERROR");
259                 return false;
260         }
261         for(DEVICE* device = first_device; device; device = device->next_device) {
262                 if(!device->load_state(state_fio)) {
263                         return false;
264                 }
265         }
266         return true;
267 }
268