forked from hissorii/px68k
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfmg_wrap.cpp
364 lines (294 loc) · 6.3 KB
/
fmg_wrap.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
// ciscタンノエロガゾウキボンヌを強引にけろぴーに繋ぐための
// extern "C" の入れ方がきちゃなくてステキ(ぉ
// readme.txtに従って、改変点:
// - opna.cppにYMF288用のクラス追加してます。OPNAそのまんまだけどね(ほんとは正しくないがまあいいや)
// - 多分他は弄ってないはず……
extern "C" {
#include "common.h"
#include "winx68k.h"
#include "dswin.h"
#include "prop.h"
#include "juliet.h"
#include "mfp.h"
#include "adpcm.h"
#include "mercury.h"
#include "fdc.h"
#include "fmg_wrap.h"
#include "opm.h"
#include "opna.h"
#define RMBUFSIZE (256*1024)
typedef struct {
unsigned int time;
int reg;
BYTE data;
} RMDATA;
};
static RMDATA RMData[RMBUFSIZE];
static int RMPtrW;
static int RMPtrR;
class MyOPM : public FM::OPM
{
public:
MyOPM();
virtual ~MyOPM() {}
void WriteIO(DWORD adr, BYTE data);
void Count2(DWORD clock);
private:
virtual void Intr(bool);
int CurReg;
DWORD CurCount;
};
MyOPM::MyOPM()
{
CurReg = 0;
}
void MyOPM::WriteIO(DWORD adr, BYTE data)
{
if( adr&1 ) {
if ( CurReg==0x1b ) {
::ADPCM_SetClock((data>>5)&4);
::FDC_SetForceReady((data>>6)&1);
}
SetReg((int)CurReg, (int)data);
if ( (juliet_YM2151IsEnable())&&(Config.SoundROMEO) ) {
int newptr = (RMPtrW+1)%RMBUFSIZE;
if ( newptr!=RMPtrR ) {
#if 0
RMData[RMPtrW].time = timeGetTime();
RMData[RMPtrW].reg = CurReg;
if ( CurReg==0x14 ) data &= 0xf3; // Int Enableはマスクする
RMData[RMPtrW].data = data;
RMPtrW = newptr;
}
#else
OPM_RomeoOut(Config.BufferSize*5);
}
RMData[RMPtrW].time = timeGetTime();
RMData[RMPtrW].reg = CurReg;
if ( CurReg==0x14 ) data &= 0xf3; // Int Enableはマスクする
RMData[RMPtrW].data = data;
RMPtrW = newptr;
#endif
}
} else {
CurReg = (int)data;
}
}
void MyOPM::Intr(bool f)
{
if ( f ) ::MFP_Int(12);
}
void MyOPM::Count2(DWORD clock)
{
CurCount += clock;
Count(CurCount/10);
CurCount %= 10;
}
static MyOPM* opm = NULL;
int OPM_Init(int clock, int rate)
{
juliet_load();
juliet_prepare();
RMPtrW = RMPtrR = 0;
memset(RMData, 0, sizeof(RMData));
opm = new MyOPM();
if ( !opm ) return FALSE;
if ( !opm->Init(clock, rate, TRUE) ) {
delete opm;
opm = NULL;
return FALSE;
}
return TRUE;
}
void OPM_Cleanup(void)
{
juliet_YM2151Reset();
juliet_unload();
delete opm;
opm = NULL;
}
void OPM_SetRate(int clock, int rate)
{
if ( opm ) opm->SetRate(clock, rate, TRUE);
}
void OPM_Reset(void)
{
RMPtrW = RMPtrR = 0;
memset(RMData, 0, sizeof(RMData));
if ( opm ) opm->Reset();
juliet_YM2151Reset();
}
BYTE FASTCALL OPM_Read(WORD adr)
{
BYTE ret = 0;
(void)adr;
if ( opm ) ret = opm->ReadStatus();
if ( (juliet_YM2151IsEnable())&&(Config.SoundROMEO) ) {
int newptr = (RMPtrW+1)%RMBUFSIZE;
ret = (ret&0x7f)|((newptr==RMPtrR)?0x80:0x00);
}
return ret;
}
void FASTCALL OPM_Write(DWORD adr, BYTE data)
{
if ( opm ) opm->WriteIO(adr, data);
}
void OPM_Update(short *buffer, int length, int rate, BYTE *pbsp, BYTE *pbep)
{
if ( (!juliet_YM2151IsEnable())||(!Config.SoundROMEO) )
if ( opm ) opm->Mix((FM::Sample*)buffer, length, rate, pbsp, pbep);
}
void FASTCALL OPM_Timer(DWORD step)
{
if ( opm ) opm->Count2(step);
}
void OPM_SetVolume(BYTE vol)
{
int v = (vol)?((16-vol)*4):192; // このくらいかなぁ
if ( opm ) opm->SetVolume(-v);
}
void OPM_RomeoOut(unsigned int delay)
{
unsigned int t = timeGetTime();
if ( (juliet_YM2151IsEnable())&&(Config.SoundROMEO) ) {
while ( RMPtrW!=RMPtrR ) {
if ( (t-RMData[RMPtrR].time)>=delay ) {
juliet_YM2151W(RMData[RMPtrR].reg, RMData[RMPtrR].data);
RMPtrR = (RMPtrR+1)%RMBUFSIZE;
} else
break;
}
}
}
// ----------------------------------------------------------
// ---------------------------- YMF288 (満開版ま~きゅり~)
// ----------------------------------------------------------
// TODO : ROMEOの288を叩くの
class YMF288 : public FM::Y288
{
public:
YMF288();
virtual ~YMF288() {}
void WriteIO(DWORD adr, BYTE data);
BYTE ReadIO(DWORD adr);
void Count2(DWORD clock);
void SetInt(int f) { IntrFlag = f; };
private:
virtual void Intr(bool);
int CurReg[2];
DWORD CurCount;
int IntrFlag;
};
YMF288::YMF288()
{
CurReg[0] = 0;
CurReg[1] = 0;
IntrFlag = 0;
}
void YMF288::WriteIO(DWORD adr, BYTE data)
{
if( adr&1 ) {
SetReg(((adr&2)?(CurReg[1]+0x100):CurReg[0]), (int)data);
} else {
CurReg[(adr>>1)&1] = (int)data;
}
}
BYTE YMF288::ReadIO(DWORD adr)
{
BYTE ret = 0;
if ( adr&1 ) {
ret = GetReg(((adr&2)?(CurReg[1]+0x100):CurReg[0]));
} else {
ret = ((adr)?(ReadStatusEx()):(ReadStatus()));
}
return ret;
}
void YMF288::Intr(bool f)
{
if ( (f)&&(IntrFlag) ) ::Mcry_Int();
}
void YMF288::Count2(DWORD clock)
{
CurCount += clock;
Count(CurCount/10);
CurCount %= 10;
}
static YMF288* ymf288a = NULL;
static YMF288* ymf288b = NULL;
int M288_Init(int clock, int rate, const char* path)
{
ymf288a = new YMF288();
ymf288b = new YMF288();
if ( (!ymf288a)||(!ymf288b) ) {
M288_Cleanup();
return FALSE;
}
if ( (!ymf288a->Init(clock, rate, TRUE, path))||(!ymf288b->Init(clock, rate, TRUE, path)) ) {
M288_Cleanup();
return FALSE;
}
ymf288a->SetInt(1);
ymf288b->SetInt(0);
return TRUE;
}
void M288_Cleanup(void)
{
delete ymf288a;
delete ymf288b;
ymf288a = ymf288b = NULL;
}
void M288_SetRate(int clock, int rate)
{
if ( ymf288a ) ymf288a->SetRate(clock, rate, TRUE);
if ( ymf288b ) ymf288b->SetRate(clock, rate, TRUE);
}
void M288_Reset(void)
{
if ( ymf288a ) ymf288a->Reset();
if ( ymf288b ) ymf288b->Reset();
}
BYTE FASTCALL M288_Read(WORD adr)
{
if ( adr<=3 ) {
if ( ymf288a )
return ymf288a->ReadIO(adr);
else
return 0;
} else {
if ( ymf288b )
return ymf288b->ReadIO(adr&3);
else
return 0;
}
}
void FASTCALL M288_Write(DWORD adr, BYTE data)
{
if ( adr<=3 ) {
if ( ymf288a ) ymf288a->WriteIO(adr, data);
} else {
if ( ymf288b ) ymf288b->WriteIO(adr&3, data);
}
}
void M288_Update(short *buffer, int length)
{
if ( ymf288a ) ymf288a->Mix((FM::Sample*)buffer, length);
if ( ymf288b ) ymf288b->Mix((FM::Sample*)buffer, length);
}
void FASTCALL M288_Timer(DWORD step)
{
if ( ymf288a ) ymf288a->Count2(step);
if ( ymf288b ) ymf288b->Count2(step);
}
void M288_SetVolume(BYTE vol)
{
int v1 = (vol)?((16-vol)*4-24):192; // このくらいかなぁ
int v2 = (vol)?((16-vol)*4):192; // 少し小さめに
if ( ymf288a ) {
ymf288a->SetVolumeFM(-v1);
ymf288a->SetVolumePSG(-v2);
}
if ( ymf288b ) {
ymf288b->SetVolumeFM(-v1);
ymf288b->SetVolumePSG(-v2);
}
}