OSDN Git Service

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