1 // license:GPL-2.0+
2 // copyright-holders:Jarek Burczynski,Tatsuyuki Satoh
3 /*
4   File: fm.h -- header file for software emulation for FM sound generator
5 
6 */
7 
8 #ifndef MAME_SOUND_FM_H
9 #define MAME_SOUND_FM_H
10 
11 #pragma once
12 
13 /* --- select emulation chips --- */
14 #define BUILD_YM2203  (1)       /* build YM2203(OPN)   emulator */
15 #define BUILD_YM2608  (1)       /* build YM2608(OPNA)  emulator */
16 #define BUILD_YM2610  (1)       /* build YM2610(OPNB)  emulator */
17 #define BUILD_YM2610B (1)       /* build YM2610B(OPNB?)emulator */
18 #define BUILD_YM2612  (1)       /* build YM2612(OPN2)  emulator */
19 #define BUILD_YM3438  (1)       /* build YM3438(OPN) emulator */
20 
21 /* select bit size of output : 8 or 16 */
22 #define FM_SAMPLE_BITS 16
23 
24 /* select timer system internal or external */
25 #define FM_INTERNAL_TIMER 0
26 
27 /* --- speedup optimize --- */
28 /* busy flag emulation , The definition of FM_GET_TIME_NOW() is necessary. */
29 #define FM_BUSY_FLAG_SUPPORT 1
30 
31 /* --- external SSG(YM2149/AY-3-8910)emulator interface port */
32 /* used by YM2203,YM2608,and YM2610 */
33 struct ssg_callbacks
34 {
35 	void (*set_clock)(device_t *device, int clock);
36 	void (*write)(device_t *device, int address, int data);
37 	int (*read)(device_t *device);
38 	void (*reset)(device_t *device);
39 };
40 
41 /* --- external callback functions for realtime update --- */
42 
43 #if FM_BUSY_FLAG_SUPPORT
44 using TIME_TYPE = attotime;
45 #define UNDEFINED_TIME              attotime::zero
46 #define FM_GET_TIME_NOW(machine)    (machine)->time()
ADD_TIMES(TIME_TYPE const & t1,TIME_TYPE const & t2)47 inline TIME_TYPE ADD_TIMES(TIME_TYPE const &t1, TIME_TYPE const &t2) { return t1 + t2; }
COMPARE_TIMES(TIME_TYPE const & t1,TIME_TYPE const & t2)48 constexpr int COMPARE_TIMES(TIME_TYPE const &t1, TIME_TYPE const &t2) { return (t1 == t2) ? 0 : (t1 < t2) ? -1 : 1; }
MULTIPLY_TIME_BY_INT(TIME_TYPE const & t,X && i)49 template <typename X> constexpr TIME_TYPE MULTIPLY_TIME_BY_INT(TIME_TYPE const &t, X &&i) { return t * i; }
50 #endif
51 
52 
53 typedef s32 FMSAMPLE;
54 /*
55 #if (FM_SAMPLE_BITS==16)
56 typedef int16_t FMSAMPLE;
57 #endif
58 #if (FM_SAMPLE_BITS==8)
59 typedef unsigned char  FMSAMPLE;
60 #endif
61 */
62 
63 typedef uint8_t (*FM_READBYTE)(device_t *device, offs_t offset);
64 typedef void(*FM_WRITEBYTE)(device_t *device, offs_t offset, uint8_t data);
65 typedef void (*FM_TIMERHANDLER)(device_t *device,int c,int cnt,int clock);
66 typedef void (*FM_IRQHANDLER)(device_t *device,int irq);
67 /* FM_TIMERHANDLER : Stop or Start timer         */
68 /* int n          = chip number                  */
69 /* int c          = Channel 0=TimerA,1=TimerB    */
70 /* int count      = timer count (0=stop)         */
71 /* doube stepTime = step time of one count (sec.)*/
72 
73 /* FM_IRQHHANDLER : IRQ level changing sense     */
74 /* int n       = chip number                     */
75 /* int irq     = IRQ level 0=OFF,1=ON            */
76 
77 #if BUILD_YM2203
78 /* -------------------- YM2203(OPN) Interface -------------------- */
79 
80 /*
81 ** Initialize YM2203 emulator(s).
82 **
83 ** 'num'           is the number of virtual YM2203's to allocate
84 ** 'baseclock'
85 ** 'rate'          is sampling rate
86 ** 'TimerHandler'  timer callback handler when timer start and clear
87 ** 'IRQHandler'    IRQ callback handler when changed IRQ level
88 ** return      0 = success
89 */
90 void * ym2203_init(device_t *device, int baseclock, int rate,
91 				FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler, const ssg_callbacks *ssg);
92 
93 /*
94 ** YM2203 clock changed notifier
95 */
96 void ym2203_clock_changed(void *chip, int clock, int rate);
97 
98 /*
99 ** shutdown the YM2203 emulators
100 */
101 void ym2203_shutdown(void *chip);
102 
103 /*
104 ** reset all chip registers for YM2203 number 'num'
105 */
106 void ym2203_reset_chip(void *chip);
107 
108 /*
109 ** update one of chip
110 */
111 void ym2203_update_one(void *chip, write_stream_view &buffer);
112 
113 /*
114 ** Write
115 ** return : InterruptLevel
116 */
117 int ym2203_write(void *chip,int a,unsigned char v);
118 
119 /*
120 ** Read
121 ** return : InterruptLevel
122 */
123 unsigned char ym2203_read(void *chip,int a);
124 
125 /*
126 **  Timer OverFlow
127 */
128 int ym2203_timer_over(void *chip, int c);
129 
130 /*
131 **  State Save
132 */
133 void ym2203_postload(void *chip);
134 #endif /* BUILD_YM2203 */
135 
136 #if BUILD_YM2608
137 /* -------------------- YM2608(OPNA) Interface -------------------- */
138 void * ym2608_init(device_t *device, int baseclock, int rate,
139 	FM_READBYTE InternalReadByte,
140 	FM_READBYTE ExternalReadByte, FM_WRITEBYTE ExternalWriteByte,
141 	FM_TIMERHANDLER TimerHandler, FM_IRQHANDLER IRQHandler, const ssg_callbacks *ssg);
142 void ym2608_clock_changed(void *chip, int clock, int rate);
143 void ym2608_shutdown(void *chip);
144 void ym2608_reset_chip(void *chip);
145 void ym2608_update_one(void *chip, std::vector<write_stream_view> &buffer);
146 
147 int ym2608_write(void *chip, int a,unsigned char v);
148 unsigned char ym2608_read(void *chip,int a);
149 int ym2608_timer_over(void *chip, int c );
150 void ym2608_postload(void *chip);
151 #endif /* BUILD_YM2608 */
152 
153 #if (BUILD_YM2610||BUILD_YM2610B)
154 /* -------------------- YM2610(OPNB) Interface -------------------- */
155 void * ym2610_init(device_t *device, int baseclock, int rate,
156 	FM_READBYTE adpcm_a_read_byte, FM_READBYTE adpcm_b_read_byte,
157 	FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler, const ssg_callbacks *ssg);
158 void ym2610_clock_changed(void *chip, int clock, int rate);
159 void ym2610_shutdown(void *chip);
160 void ym2610_reset_chip(void *chip);
161 void ym2610_update_one(void *chip, std::vector<write_stream_view> &buffer);
162 
163 #if BUILD_YM2610B
164 void ym2610b_update_one(void *chip, std::vector<write_stream_view> &buffer);
165 #endif /* BUILD_YM2610B */
166 
167 int ym2610_write(void *chip, int a,unsigned char v);
168 unsigned char ym2610_read(void *chip,int a);
169 int ym2610_timer_over(void *chip, int c );
170 void ym2610_postload(void *chip);
171 #endif /* (BUILD_YM2610||BUILD_YM2610B) */
172 
173 #if (BUILD_YM2612||BUILD_YM3438)
174 void * ym2612_init(device_t *device, int baseclock, int rate,
175 				FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler);
176 void ym2612_clock_changed(void *chip, int clock, int rate);
177 void ym2612_shutdown(void *chip);
178 void ym2612_reset_chip(void *chip);
179 void ym2612_update_one(void *chip, std::vector<write_stream_view> &buffer, u8 output_bits);
180 
181 int ym2612_write(void *chip, int a,unsigned char v);
182 unsigned char ym2612_read(void *chip,int a);
183 int ym2612_timer_over(void *chip, int c );
184 void ym2612_postload(void *chip);
185 #endif /* (BUILD_YM2612||BUILD_YM3438) */
186 
187 
188 #endif // MAME_SOUND_FM_H
189