#ifdef _MSC_VER
#if (_MSC_VER >= 1900)
int INP(int dummy) { return 0; }
void OUTP(int dummy, int dummy2) { return; }
#else
# include <conio.h>
# define INP _inp
# define OUTP _outp
#endif #elif defined(__WATCOMC__)
# include <conio.h>
# define INP inp
# define OUTP outp
#elif defined(WIN32) && defined(__MSVCRT__) && defined(__MINGW32__)
# define INP inb
# define OUTP(reg, val) outb(val, reg)
#elif defined(DJGPP)
# include <pc.h>
# define INP inportb
# define OUTP outportb
#elif defined(linux) && defined(HAVE_SYS_IO_H)
# include <sys/io.h>
# define INP inb
# define OUTP(reg,val) outb(val,reg)
#else
# define INP(reg) 0
# define OUTP(reg, val)
#endif
#include "realopl.h"
#define SHORTDELAY 6
#define LONGDELAY 35
const unsigned char CRealopl::op_table[9] =
{0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12};
#if defined(WIN32) && defined(__MINGW32__)
static __inline unsigned char inb(unsigned short int port) {
unsigned char _v;
__asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (port));
return _v;
}
static __inline void outb(unsigned char value, unsigned short int port) {
__asm__ __volatile__ ("outb %b0,%w1": :"a" (value), "Nd" (port));
}
#endif
CRealopl::CRealopl(unsigned short initport)
: adlport(initport), hardvol(0), bequiet(false), nowrite(false) {
for (int i = 0; i < 22; i++) {
hardvols[0][i][0] = 0;
hardvols[0][i][1] = 0;
hardvols[1][i][0] = 0;
hardvols[1][i][1] = 0;
}
currType = TYPE_OPL3;
}
bool CRealopl::harddetect() {
unsigned char stat1, stat2, i;
unsigned short adp = (currChip == 0 ? adlport : adlport + 2);
hardwrite(4, 0x60); hardwrite(4, 0x80);
stat1 = INP(adp);
hardwrite(2, 0xff); hardwrite(4, 0x21);
for (i = 0; i < 80; i++) INP(adp);
stat2 = INP(adp);
hardwrite(4, 0x60); hardwrite(4, 0x80);
if (((stat1 & 0xe0) == 0) && ((stat2 & 0xe0) == 0xc0))
return true;
else
return false;
}
bool CRealopl::detect() {
unsigned char stat;
setchip(0);
if (harddetect()) {
currType = TYPE_OPL2;
stat = INP(adlport);
if (stat & 6) {
setchip(1);
if (harddetect())
currType = TYPE_DUAL_OPL2;
} else {
currType = TYPE_OPL3;
}
setchip(0);
return true;
} else {
return false;
}
}
void CRealopl::setvolume(int volume) {
int i, j;
hardvol = volume;
for (j = 0; j < 2; j++)
for (i = 0; i < 9; i++) {
hardwrite(0x43 + op_table[i], ((hardvols[j][op_table[i] + 3][0] & 63) + volume) > 63 ? 63 : hardvols[j][op_table[i] + 3][0] + volume);
if (hardvols[j][i][1] & 1) hardwrite(0x40 + op_table[i], ((hardvols[j][op_table[i]][0] & 63) + volume) > 63 ? 63 : hardvols[j][op_table[i]][0] + volume);
}
}
void CRealopl::setquiet(bool quiet) {
bequiet = quiet;
if (quiet) {
oldvol = hardvol;
setvolume(63);
} else
setvolume(oldvol);
}
void CRealopl::hardwrite(int reg, int val) {
int i;
unsigned short adp = (currChip == 0 ? adlport : adlport + 2);
if (nowrite)
return;
#if defined(linux) && defined(HAVE_SYS_IO_H)
if (!gotperms) {
if ((ioperm(adlport, 2, 1) != 0) || (ioperm(adlport + 2, 2, 1) != 0)) {
return;
}
gotperms = true;
}
#endif
OUTP(adp, reg);
for (i = 0; i < SHORTDELAY; i++) INP(adp);
OUTP(adp + 1, val);
for (i = 0; i < LONGDELAY; i++) INP(adp);
}
void CRealopl::write(int reg, int val) {
int i;
if (nowrite)
return;
if (currType == TYPE_OPL2 && currChip > 0)
return;
if (bequiet && (reg >= 0xb0 && reg <= 0xb8)) val &= ~32;
if (reg >= 0x40 && reg <= 0x55) hardvols[currChip][reg - 0x40][0] = val;
if (reg >= 0xc0 && reg <= 0xc8)
hardvols[currChip][reg - 0xc0][1] = val;
if (hardvol) for (i = 0; i < 9; i++) {
if (reg == 0x43 + op_table[i])
val = ((val & 63) + hardvol) > 63 ? 63 : val + hardvol;
else if ((reg == 0x40 + op_table[i]) && (hardvols[currChip][i][1] & 1))
val = ((val & 63) + hardvol) > 63 ? 63 : val + hardvol;
}
hardwrite(reg, val);
}
void CRealopl::init() {
int i, j;
for (j = 0; j < 2; j++) {
setchip(j);
for (i = 0; i < 256; i++) {
write(i, 0);
}
for (i = 0; i < 9; i++) {
hardwrite(0xb0 + i, 0); hardwrite(0x80 + op_table[i], 0xff); }
hardwrite(0xbd, 0); }
setchip(0);
}