Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,253 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_SOUND_ADPLUG_OPL_CLASS_H
#define NUVIE_SOUND_ADPLUG_OPL_CLASS_H
#include "ultima/nuvie/sound/adplug/opl.h"
namespace Ultima {
namespace Nuvie {
#define HAS_YM3812 1
#define HAS_YM3526 0
#define HAS_Y8950 0
/* --- select emulation chips --- */
#define BUILD_YM3812 (HAS_YM3812)
#define BUILD_YM3526 (HAS_YM3526)
#define BUILD_Y8950 (HAS_Y8950)
/* select output bits size of output : 8 or 16 */
#define OPL_SAMPLE_BITS 16
#if (OPL_SAMPLE_BITS==16)
typedef int16 OPLSAMPLE;
#endif
#if (OPL_SAMPLE_BITS==8)
typedef int8 OPLSAMPLE;
#endif
typedef void (*OPL_TIMERHANDLER)(int channel, double interval_Sec);
typedef void (*OPL_IRQHANDLER)(int param, int irq);
typedef void (*OPL_UPDATEHANDLER)(int param, int min_interval_us);
typedef void (*OPL_PORTHANDLER_W)(int param, unsigned char data);
typedef unsigned char (*OPL_PORTHANDLER_R)(int param);
/* Saving is necessary for member of the 'R' mark for suspend/resume */
typedef struct {
uint32 ar; /* attack rate: AR<<2 */
uint32 dr; /* decay rate: DR<<2 */
uint32 rr; /* release rate:RR<<2 */
uint8 KSR; /* key scale rate */
uint8 ksl; /* keyscale level */
uint8 ksr; /* key scale rate: kcode>>KSR */
uint8 mul; /* multiple: mul_tab[ML] */
/* Phase Generator */
uint32 Cnt; /* frequency counter */
uint32 Incr; /* frequency counter step */
uint8 FB; /* feedback shift value */
signed int *connect1; /* slot1 output pointer */
int32 op1_out[2]; /* slot1 output for feedback */
uint8 CON; /* connection (algorithm) type */
/* Envelope Generator */
uint8 eg_type; /* percussive/non-percussive mode */
uint8 state; /* phase type */
uint32 TL; /* total level: TL << 2 */
int32 TLL; /* adjusted now TL */
int32 volume; /* envelope counter */
uint32 sl; /* sustain level: sl_tab[SL] */
uint8 eg_sh_ar; /* (attack state) */
uint8 eg_sel_ar; /* (attack state) */
uint8 eg_sh_dr; /* (decay state) */
uint8 eg_sel_dr; /* (decay state) */
uint8 eg_sh_rr; /* (release state) */
uint8 eg_sel_rr; /* (release state) */
uint32 key; /* 0 = KEY OFF, >0 = KEY ON */
/* LFO */
uint32 AMmask; /* LFO Amplitude Modulation enable mask */
uint8 vib; /* LFO Phase Modulation enable flag (active high)*/
/* waveform select */
unsigned int wavetable;
} OPL_SLOT;
typedef struct {
OPL_SLOT SLOT[2];
/* phase generator state */
uint32 block_fnum; /* block+fnum */
uint32 fc; /* Freq. Increment base */
uint32 ksl_base; /* KeyScaleLevel Base step */
uint8 kcode; /* key code (for key scaling) */
} OPL_CH;
/* OPL state */
typedef struct fm_opl_f {
/* FM channel slots */
OPL_CH P_CH[9]; /* OPL/OPL2 chips have 9 channels*/
uint32 eg_cnt; /* global envelope generator counter */
uint32 eg_timer; /* global envelope generator counter works at frequency = chipclock/72 */
uint32 eg_timer_add; /* step of eg_timer */
uint32 eg_timer_overflow; /* envelope generator timer overlfows every 1 sample (on real chip) */
uint8 rhythm; /* Rhythm mode */
uint32 fn_tab[1024]; /* fnumber->increment counter */
/* LFO */
uint8 lfo_am_depth;
uint8 lfo_pm_depth_range;
uint32 lfo_am_cnt;
uint32 lfo_am_inc;
uint32 lfo_pm_cnt;
uint32 lfo_pm_inc;
uint32 noise_rng; /* 23 bit noise shift register */
uint32 noise_p; /* current noise 'phase' */
uint32 noise_f; /* current noise period */
uint8 wavesel; /* waveform select enable flag */
int T[2]; /* timer counters */
uint8 st[2]; /* timer enable */
/* external event callback handlers */
OPL_TIMERHANDLER TimerHandler; /* TIMER handler */
int TimerParam; /* TIMER parameter */
OPL_IRQHANDLER IRQHandler; /* IRQ handler */
int IRQParam; /* IRQ parameter */
OPL_UPDATEHANDLER UpdateHandler;/* stream update handler */
int UpdateParam; /* stream update parameter */
uint8 type; /* chip type */
uint8 address; /* address register */
uint8 status; /* status flag */
uint8 statusmask; /* status mask */
uint8 mode; /* Reg.08 : CSM,notesel,etc. */
int clock; /* master clock (Hz) */
int rate; /* sampling rate (Hz) */
double freqbase; /* frequency base */
double TimerBase; /* Timer base time (==sampling time)*/
} FM_OPL;
#define MAX_OPL_CHIPS 2
/* sinwave entries */
#define SIN_BITS 10
#define SIN_LEN (1<<SIN_BITS)
#define SIN_MASK (SIN_LEN-1)
#define TL_RES_LEN (256) /* 8 bits addressing (real chip) */
/* TL_TAB_LEN is calculated as:
* 12 - sinus amplitude bits (Y axis)
* 2 - sinus sign bit (Y axis)
* TL_RES_LEN - sinus resolution (X axis)
*/
#define TL_TAB_LEN (12*2*TL_RES_LEN)
class OplClass: public Copl {
private:
FM_OPL *OPL_YM3812[MAX_OPL_CHIPS]; /* array of pointers to the YM3812's */
int YM3812NumChips; /* number of chips */
signed int tl_tab[TL_TAB_LEN];
/* sin waveform table in 'decibel' scale */
/* four waveforms on OPL2 type chips */
unsigned int sin_tab[SIN_LEN * 4];
/* lock level of common table */
int num_lock;
/* work table */
void *cur_chip; /* current chip point */
OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
signed int phase_modulation; /* phase modulation input (SLOT 2) */
signed int output[1];
uint32 LFO_AM;
int32 LFO_PM;
bool use16bit, stereo;
int oplRate;
public:
OplClass(int rate, bool bit16, bool usestereo); // rate = sample rate
~OplClass() override {
YM3812Shutdown();
}
int getRate() {
return oplRate;
}
void update(short *buf, int samples); // fill buffer
// template methods
void write(int reg, int val) override;
void init() override;
private:
int YM3812Init(int num, int clock, int rate);
void YM3812Shutdown(void);
void YM3812ResetChip(int which);
int YM3812Write(int which, int a, int v);
unsigned char YM3812Read(int which, int a);
int YM3812TimerOver(int which, int c);
void YM3812UpdateOne(int which, int16 *buffer, int length);
void YM3812SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset);
void YM3812SetIRQHandler(int which, OPL_IRQHANDLER IRQHandler, int param);
void YM3812SetUpdateHandler(int which, OPL_UPDATEHANDLER UpdateHandler, int param);
int init_tables(void);
void OPLWriteReg(FM_OPL *OPL, int r, int v);
void OPLResetChip(FM_OPL *OPL);
int OPL_LockTable(void);
FM_OPL *OPLCreate(int type, int clock, int rate);
void OPL_UnLockTable(void);
void OPLDestroy(FM_OPL *OPL);
int OPLWrite(FM_OPL *OPL, int a, int v);
inline void advance_lfo(FM_OPL *OPL);
inline void advancex(FM_OPL *OPL);
inline signed int op_calc(uint32 phase, unsigned int env, signed int pm, unsigned int wave_tab);
inline signed int op_calc1(uint32 phase, unsigned int env, signed int pm, unsigned int wave_tab);
inline void OPL_CALC_CH(OPL_CH *CH);
inline void OPL_CALC_RH(OPL_CH *CH, unsigned int noise);
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif