2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
12 #define EVENT_FM_TIMER 0
14 #ifdef SUPPORT_MAME_FM_DLL
15 // thanks PC8801MA
\89ΓΌ
16 #include "fmdll/fmdll.h"
17 static CFMDLL* fmdll = NULL;
18 static int chip_reference_counter = 0;
19 static bool dont_create_multiple_chips = false;
22 void YM2151::initialize()
26 #ifdef SUPPORT_MAME_FM_DLL
28 // fmdll = new CFMDLL(_T("mamefm.dll"));
29 fmdll = new CFMDLL(config.fmgen_dll_path);
33 register_vline_event(this);
35 clock_prev = clock_accum = clock_busy = 0;
38 void YM2151::release()
41 #ifdef SUPPORT_MAME_FM_DLL
43 fmdll->Release(dllchip);
45 chip_reference_counter--;
47 if(fmdll && !chip_reference_counter) {
58 #ifdef SUPPORT_MAME_FM_DLL
60 fmdll->Reset(dllchip);
62 memset(port_log, 0, sizeof(port_log));
65 irq_prev = busy = false;
68 void YM2151::write_io8(uint32_t addr, uint32_t data)
72 this->set_reg(ch, data);
77 clock_busy = get_current_clock();
84 uint32_t YM2151::read_io8(uint32_t addr)
89 uint32_t status = opm->ReadStatus() & ~0x80;
91 // FIXME: we need to investigate the correct busy period
92 if(get_passed_usec(clock_busy) < 8) {
102 void YM2151::write_signal(int id, uint32_t data, uint32_t mask)
104 if(id == SIG_YM2151_MUTE) {
105 mute = ((data & mask) != 0);
109 void YM2151::event_vline(int v, int clock)
115 void YM2151::event_callback(int event_id, int error)
123 void YM2151::update_count()
125 clock_accum += clock_const * get_passed_clock(clock_prev);
126 uint32_t count = clock_accum >> 20;
129 clock_accum -= count << 20;
131 clock_prev = get_current_clock();
134 void YM2151::update_event()
136 if(timer_event_id != -1) {
137 cancel_event(this, timer_event_id);
141 int count = opm->GetNextEvent();
143 register_event(this, EVENT_FM_TIMER, 1000000.0 / (double)chip_clock * (double)count, false, &timer_event_id);
147 void YM2151::update_interrupt()
149 bool irq = opm->ReadIRQ();
150 if(!irq_prev && irq) {
151 write_signals(&outputs_irq, 0xffffffff);
152 } else if(irq_prev && !irq) {
153 write_signals(&outputs_irq, 0);
158 void YM2151::mix(int32_t* buffer, int cnt)
160 if(cnt > 0 && !mute) {
161 opm->Mix(buffer, cnt);
162 #ifdef SUPPORT_MAME_FM_DLL
164 fmdll->Mix(dllchip, buffer, cnt);
170 void YM2151::set_volume(int ch, int decibel_l, int decibel_r)
172 opm->SetVolume(base_decibel + decibel_l, base_decibel + decibel_r);
173 #ifdef SUPPORT_MAME_FM_DLL
175 fmdll->SetVolumeFM(dllchip, base_decibel + decibel_l);
180 void YM2151::initialize_sound(int rate, int clock, int samples, int decibel)
182 opm->Init(clock, rate, false);
183 opm->SetVolume(decibel, decibel);
184 base_decibel = decibel;
186 #ifdef SUPPORT_MAME_FM_DLL
187 if(!dont_create_multiple_chips) {
188 fmdll->Create((LPVOID*)&dllchip, clock, rate);
190 chip_reference_counter++;
192 fmdll->SetVolumeFM(dllchip, decibel);
195 DWORD dwCaps = fmdll->GetCaps(dllchip);
196 if((dwCaps & SUPPORT_MULTIPLE) != SUPPORT_MULTIPLE) {
197 dont_create_multiple_chips = true;
199 if((dwCaps & SUPPORT_FM_A) == SUPPORT_FM_A) {
202 if((dwCaps & SUPPORT_FM_B) == SUPPORT_FM_B) {
205 if((dwCaps & SUPPORT_FM_C) == SUPPORT_FM_C) {
208 opm->SetChannelMask(mask);
209 fmdll->SetChannelMask(dllchip, ~mask);
217 void YM2151::set_reg(uint32_t addr, uint32_t data)
220 opm->SetReg(addr, data);
221 #ifdef SUPPORT_MAME_FM_DLL
223 fmdll->SetReg(dllchip, addr, data);
225 port_log[addr].written = true;
226 port_log[addr].data = data;
230 void YM2151::update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame)
232 clock_const = (uint32_t)((double)chip_clock * 1024.0 * 1024.0 / (double)new_clocks + 0.5);
235 #define STATE_VERSION 3
237 bool YM2151::process_state(FILEIO* state_fio, bool loading)
239 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
242 if(!state_fio->StateCheckInt32(this_device_id)) {
245 if(!opm->ProcessState((void *)state_fio, loading)) {
248 #ifdef SUPPORT_MAME_FM_DLL
249 state_fio->StateBuffer(port_log, sizeof(port_log), 1);
251 state_fio->StateInt32(chip_clock);
252 state_fio->StateUint8(ch);
253 state_fio->StateBool(irq_prev);
254 state_fio->StateBool(mute);
255 state_fio->StateUint32(clock_prev);
256 state_fio->StateUint32(clock_accum);
257 state_fio->StateUint32(clock_const);
258 state_fio->StateUint32(clock_busy);
259 state_fio->StateInt32(timer_event_id);
260 state_fio->StateBool(busy);
262 #ifdef SUPPORT_MAME_FM_DLL
264 if(loading && dllchip) {
265 fmdll->Reset(dllchip);
266 for(int i = 0; i < 0x100; i++) {
267 if(port_log[i].written) {
268 fmdll->SetReg(dllchip, i, port_log[i].data);