Most patches are temporary and there just to let the code to build. It will not work in the current state. Also now force the use of paged memory. It was not working properly because of the way the old GPU code is working.
1257 lines
30 KiB
C
1257 lines
30 KiB
C
/*******************************************************************************
|
|
* NewOswan
|
|
* audio.c:
|
|
* Based on the original Oswan-unix
|
|
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
|
|
*
|
|
******************************************************************************/
|
|
|
|
// alternate the commenting of the following defines to get audio port tracing
|
|
#define dbgprintf(...)
|
|
//#define dbgprintf(...) printf(...)
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
#include <log.h>
|
|
#include <rom.h>
|
|
#include "nec.h"
|
|
#include <memory.h>
|
|
#include <io.h>
|
|
#include <audio.h>
|
|
|
|
#define SNDP ws_ioRam[0x80]
|
|
#define SNDV ws_ioRam[0x88]
|
|
#define SNDSWP ws_ioRam[0x8C]
|
|
#define SWPSTP ws_ioRam[0x8D]
|
|
#define NSCTL ws_ioRam[0x8E]
|
|
#define WAVDTP ws_ioRam[0x8F]
|
|
#define SNDMOD ws_ioRam[0x90]
|
|
#define SNDOUT ws_ioRam[0x91]
|
|
#define PCSRL ws_ioRam[0x92]
|
|
#define PCSRH ws_ioRam[0x93]
|
|
#define DMASL ws_ioRam[0x40]
|
|
#define DMASH ws_ioRam[0x41]
|
|
#define DMASB ws_ioRam[0x42]
|
|
#define DMADB ws_ioRam[0x43]
|
|
#define DMADL ws_ioRam[0x44]
|
|
#define DMADH ws_ioRam[0x45]
|
|
#define DMACL ws_ioRam[0x46]
|
|
#define DMACH ws_ioRam[0x47]
|
|
#define DMACTL ws_ioRam[0x48]
|
|
#define SDMASL ws_ioRam[0x4A]
|
|
#define SDMASH ws_ioRam[0x4B]
|
|
#define SDMASB ws_ioRam[0x4C]
|
|
#define SDMACL ws_ioRam[0x4E]
|
|
#define SDMACH ws_ioRam[0x4F]
|
|
#define SDMACTL ws_ioRam[0x52]
|
|
|
|
#define BPS 44100
|
|
#define BPSMAX AUDIO_MAX_FREQUENCY
|
|
#define BPSMIN AUDIO_MIN_FREQUENCY
|
|
#define BUFSIZE 1024
|
|
#define BUFSIZEN 0x10000
|
|
#define BUFSIZEP 159
|
|
#define PCMNUM 100
|
|
#define POFF 128
|
|
#define PDIV 3
|
|
#define PH POFF+PDIV*8
|
|
#define PL POFF-PDIV*7
|
|
|
|
int WaveMap;
|
|
int ChPerInit;
|
|
int SwpTime;
|
|
int SwpStep;
|
|
unsigned int SwpCurPeriod;
|
|
|
|
int MainVol = 15;
|
|
int HardVol = 3;
|
|
|
|
int ChCurVol[6] = {-1, -1, -1, -1, -1, -1};
|
|
int ChCurPer[6] = {-1, -1, -1, -1, -1, -1};
|
|
long ChCurPan[6] = {-1, -1, -1, -1, -1, -1};
|
|
|
|
unsigned char PData[4][BUFSIZE];
|
|
unsigned char PDataP[BUFSIZEP << 4];
|
|
unsigned char PDataN[8][BUFSIZEN];
|
|
|
|
int RandData[BUFSIZEN];
|
|
|
|
int CntSwp = 0;
|
|
int PcmWrPos = 0;
|
|
|
|
/*
|
|
const long TblChVol[16]= // n/15 n=0~15
|
|
{
|
|
-10000,-2352,-1750,-1398,-1148,-954,-796,-662,
|
|
-546,-444,-352,-269,-194,-124,-60,0
|
|
};
|
|
|
|
const long TblMainVol[4]= // 1,1/2,1/4,1/8
|
|
{
|
|
0,-602,-1204,-1806
|
|
};
|
|
*/
|
|
|
|
//HAC ws_audio_pcm_voice[4];
|
|
//HAC ws_audio_noise_voice;
|
|
//HAC ws_audio_sweep_voice;
|
|
|
|
//AUDIOWAVE ws_audio_pcm_wave[4];
|
|
//AUDIOWAVE ws_audio_noise_wave;
|
|
//AUDIOWAVE ws_audio_sweep_wave;
|
|
|
|
uint32_t ws_audio_channel_isPlaying[6];
|
|
|
|
static unsigned int ws_audio_log;
|
|
|
|
// TODO: Temporary to let build for now
|
|
static uint8_t ws_ioRam[0x100];
|
|
|
|
void ws_audio_init(void)
|
|
{
|
|
Log(TLOG_NORMAL, "audio", "audio init");
|
|
ws_audio_log = 0;
|
|
//ws_audio_seal_init();
|
|
ws_audio_reset();
|
|
}
|
|
|
|
void ws_audio_reset(void)
|
|
{
|
|
WaveMap = -1;
|
|
|
|
for (int i = 0 ; i < 6 ; i++)
|
|
{
|
|
ws_audio_stop_channel(i);
|
|
ws_audio_play_channel(i);
|
|
ws_audio_set_channel_frequency(i, 0);
|
|
|
|
if (i != 4)
|
|
{
|
|
ws_audio_set_channel_pan(i, 0, 0);
|
|
}
|
|
|
|
ws_audio_clear_channel(i);
|
|
}
|
|
|
|
ws_audio_set_channel_frequency(4, 0);
|
|
ws_audio_set_channel_frequency(4, 1792);
|
|
}
|
|
|
|
void ws_audio_port_write(uint32_t port, uint8_t value)
|
|
{
|
|
uint32_t n, i, j, k, b;
|
|
|
|
ws_ioRam[port] = value;
|
|
|
|
switch (port)
|
|
{
|
|
case 0x48:
|
|
if (value & 0x80)
|
|
{
|
|
n = (DMACH << 8) | DMACL;
|
|
i = (DMASB << 16) | (DMASH << 8) | DMASL;
|
|
j = (DMADH << 8) | DMADL;
|
|
|
|
for (k = 0 ; k < n ; k++)
|
|
{
|
|
b = mem_readmem20(i);
|
|
mem_writemem20(j, b);
|
|
i++;
|
|
j++;
|
|
}
|
|
|
|
n = 0;
|
|
DMASB = (uint8_t)((i >> 16) & 0xFF);
|
|
DMASH = (uint8_t)((i >> 8) & 0xFF);
|
|
DMASL = (uint8_t)(i & 0xFF);
|
|
DMADB = (uint8_t)((j >> 16) & 0xFF);
|
|
DMADH = (uint8_t)((j >> 8) & 0xFF);
|
|
DMADL = (uint8_t)(j & 0xFF);
|
|
DMACH = (uint8_t)((n >> 8) & 0xFF);
|
|
DMACL = (uint8_t)(n & 0xFF);
|
|
value &= 0x7F;
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x80:
|
|
case 0x81:
|
|
i = (((unsigned int)ws_ioRam[0x81]) << 8) + ((unsigned int)ws_ioRam[0x80]);
|
|
ws_audio_set_channel_frequency(0, i);
|
|
break;
|
|
|
|
case 0x82:
|
|
case 0x83:
|
|
i = (((unsigned int)ws_ioRam[0x83]) << 8) + ((unsigned int)ws_ioRam[0x82]);
|
|
ws_audio_set_channel_frequency(1, i);
|
|
break;
|
|
|
|
case 0x84:
|
|
case 0x85:
|
|
i = (((unsigned int)ws_ioRam[0x85]) << 8) + ((unsigned int)ws_ioRam[0x84]);
|
|
ws_audio_set_channel_frequency(2, i);
|
|
break;
|
|
|
|
case 0x86:
|
|
case 0x87:
|
|
i = (((unsigned int)(ws_ioRam[0x87] & 0x07)) << 8) + ((unsigned int)ws_ioRam[0x86]);
|
|
ws_audio_set_channel_frequency(5, i);
|
|
ws_audio_set_channel_frequency(3, i);
|
|
break;
|
|
|
|
case 0x88:
|
|
ws_audio_set_channel_pan(0, (value & 0xF0) >> 4, value & 0x0F);
|
|
break;
|
|
|
|
case 0x89:
|
|
ws_audio_set_channel_pan(1, (value & 0xF0) >> 4, value & 0x0F);
|
|
break;
|
|
|
|
case 0x8A:
|
|
ws_audio_set_channel_pan(2, (value & 0xF0) >> 4, value & 0x0F);
|
|
break;
|
|
|
|
case 0x8B:
|
|
ws_audio_set_channel_pan(5, (value & 0xF0) >> 4, value & 0x0F);
|
|
ws_audio_set_channel_pan(3, (value & 0xF0) >> 4, value & 0x0F);
|
|
break;
|
|
|
|
case 0x8C:
|
|
SwpStep = (signed char)value;
|
|
break;
|
|
|
|
case 0x8D:
|
|
SwpTime = (((unsigned int)value) + 1) << 5;
|
|
break;
|
|
|
|
case 0x8E:
|
|
if (value & 0x10)
|
|
{
|
|
ws_audio_set_channel_pdata(5, value & 0x07);
|
|
}
|
|
else
|
|
{
|
|
// hmmm.. shut up!
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x8F:
|
|
WaveMap = ((unsigned int)value) << 6;
|
|
break;
|
|
|
|
case 0x90:
|
|
if (value & 0x01)
|
|
{
|
|
ws_audio_play_channel(0);
|
|
}
|
|
else
|
|
{
|
|
ws_audio_stop_channel(0);
|
|
}
|
|
|
|
if ((value & 0x22) == 0x02)
|
|
{
|
|
ws_audio_play_channel(1);
|
|
}
|
|
else
|
|
{
|
|
ws_audio_stop_channel(1);
|
|
}
|
|
|
|
if (value & 0x04)
|
|
{
|
|
ws_audio_play_channel(2);
|
|
}
|
|
else
|
|
{
|
|
ws_audio_stop_channel(2);
|
|
}
|
|
|
|
if ((value & 0x88) == 0x08)
|
|
{
|
|
ws_audio_play_channel(3);
|
|
}
|
|
else
|
|
{
|
|
ws_audio_stop_channel(3);
|
|
}
|
|
|
|
if ((value & 0x88) == 0x88)
|
|
{
|
|
ws_audio_play_channel(5);
|
|
}
|
|
else
|
|
{
|
|
ws_audio_stop_channel(5);
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x91:
|
|
value |= 0x80;
|
|
HardVol = (value >> 1) & 0x3;
|
|
|
|
ws_ioRam[port] = value; // Always have external speaker
|
|
|
|
value = ws_ioRam[0x88];
|
|
|
|
ws_audio_set_channel_pan(0, (value & 0xF0) >> 4, value & 0x0F);
|
|
|
|
value = ws_ioRam[0x89];
|
|
|
|
ws_audio_set_channel_pan(1, (value & 0xF0) >> 4, value & 0x0F);
|
|
|
|
value = ws_ioRam[0x8A];
|
|
|
|
ws_audio_set_channel_pan(2, (value & 0xF0) >> 4, value & 0x0F);
|
|
|
|
value = ws_ioRam[0x8B];
|
|
|
|
ws_audio_set_channel_pan(3, (value & 0xF0) >> 4, value & 0x0F);
|
|
|
|
ws_audio_set_channel_pan(5, (value & 0xF0) >> 4, value & 0x0F);
|
|
|
|
break;
|
|
|
|
case 0x92:
|
|
dbgprintf("0x92 <- 0x%2x\n", value);
|
|
fflush(stdout);
|
|
break;
|
|
|
|
case 0x93:
|
|
dbgprintf("0x93 <- 0x%2x\n", value);
|
|
fflush(stdout);
|
|
break;
|
|
|
|
case 0x94:
|
|
dbgprintf("0x94 <- 0x%2x\n", value);
|
|
fflush(stdout);
|
|
MainVol = (value & 0x0f) >> 2;
|
|
value = ws_ioRam[0x88];
|
|
|
|
ws_audio_set_channel_pan(0, (value & 0xF0) >> 4, value & 0x0F);
|
|
|
|
value = ws_ioRam[0x89];
|
|
|
|
ws_audio_set_channel_pan(1, (value & 0xF0) >> 4, value & 0x0F);
|
|
|
|
value = ws_ioRam[0x8A];
|
|
|
|
ws_audio_set_channel_pan(2, (value & 0xF0) >> 4, value & 0x0F);
|
|
|
|
value = ws_ioRam[0x8B];
|
|
|
|
ws_audio_set_channel_pan(3, (value & 0xF0) >> 4, value & 0x0F);
|
|
|
|
ws_audio_set_channel_pan(5, (value & 0xF0) >> 4, value & 0x0F);
|
|
|
|
break;
|
|
|
|
case 0x9A:
|
|
break;
|
|
}
|
|
}
|
|
|
|
uint8_t ws_audio_port_read(uint8_t port)
|
|
{
|
|
return (ws_ioRam[port]);
|
|
}
|
|
|
|
void ws_audio_done(void)
|
|
{
|
|
ws_audio_seal_done();
|
|
}
|
|
|
|
unsigned int ws_audio_mrand(unsigned int Degree)
|
|
{
|
|
#define BIT(n) (1<<n)
|
|
typedef struct
|
|
{
|
|
unsigned int N;
|
|
int InputBit;
|
|
int Mask;
|
|
} POLYNOMIAL;
|
|
|
|
static POLYNOMIAL TblMask[] = {{2, BIT(2), BIT(0) | BIT(1)},
|
|
{3, BIT(3), BIT(0) | BIT(1)},
|
|
{4, BIT(4), BIT(0) | BIT(1)},
|
|
{5, BIT(5), BIT(0) | BIT(2)},
|
|
{6, BIT(6), BIT(0) | BIT(1)},
|
|
{7, BIT(7), BIT(0) | BIT(1)},
|
|
{8, BIT(8), BIT(0) | BIT(2) | BIT(3) | BIT(4)},
|
|
{9, BIT(9), BIT(0) | BIT(4)},
|
|
{10, BIT(10), BIT(0) | BIT(3)},
|
|
{11, BIT(11), BIT(0) | BIT(2)},
|
|
{12, BIT(12), BIT(0) | BIT(1) | BIT(4) | BIT(6)},
|
|
{13, BIT(13), BIT(0) | BIT(1) | BIT(3) | BIT(4)},
|
|
{14, BIT(14), BIT(0) | BIT(1) | BIT(4) | BIT(5)},
|
|
{15, BIT(15), BIT(0) | BIT(1)},
|
|
{0, 0, 0},
|
|
};
|
|
|
|
static POLYNOMIAL *pTbl = TblMask;
|
|
static int ShiftReg = 1;
|
|
int XorReg = 0;
|
|
int Masked;
|
|
|
|
if (pTbl->N != Degree)
|
|
{
|
|
pTbl = TblMask;
|
|
|
|
while (pTbl->N)
|
|
{
|
|
if (pTbl->N == Degree)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pTbl++;
|
|
}
|
|
|
|
if (!pTbl->N)
|
|
{
|
|
pTbl--;
|
|
}
|
|
|
|
ShiftReg &= pTbl->InputBit - 1;
|
|
|
|
if (!ShiftReg)
|
|
{
|
|
ShiftReg = pTbl->InputBit - 1;
|
|
}
|
|
}
|
|
|
|
Masked = ShiftReg & pTbl->Mask;
|
|
|
|
while (Masked)
|
|
{
|
|
XorReg ^= Masked & 0x01;
|
|
Masked >>= 1;
|
|
}
|
|
|
|
if (XorReg)
|
|
{
|
|
ShiftReg |= pTbl->InputBit;
|
|
}
|
|
else
|
|
{
|
|
ShiftReg &= ~pTbl->InputBit;
|
|
}
|
|
|
|
ShiftReg >>= 1;
|
|
|
|
return ShiftReg;
|
|
}
|
|
|
|
int ws_audio_seal_init(void)
|
|
{
|
|
#if 0
|
|
int i, j;
|
|
AUDIOINFO info;
|
|
AUDIOCAPS caps;
|
|
uint32_t rc;
|
|
uint32_t nDevId;
|
|
|
|
fprintf(log_get(),"audio: using seal audio library\n");
|
|
/* initialize audio library */
|
|
AInitialize();
|
|
|
|
/* show registered device drivers */
|
|
fprintf(log_get(),"audio: registered sound devices:\n");
|
|
|
|
for (nDevId = 0; nDevId < AGetAudioNumDevs(); nDevId++)
|
|
{
|
|
AGetAudioDevCaps(nDevId, &caps);
|
|
fprintf(log_get(),"audio: %2d. %s\n", nDevId, caps.szProductName);
|
|
}
|
|
|
|
/* open audio device */
|
|
info.nDeviceId = 0;
|
|
info.wFormat = AUDIO_FORMAT_16BITS | AUDIO_FORMAT_STEREO; // | AUDIO_MIXER_BASS;
|
|
info.nSampleRate = 44100;
|
|
|
|
if ((rc = AOpenAudio(&info)) != AUDIO_ERROR_NONE)
|
|
{
|
|
CHAR szText[80];
|
|
AGetErrorText(rc, szText, sizeof(szText) - 1);
|
|
fprintf(log_get(),"audio: error: %s\n", szText);
|
|
fflush(log_get());
|
|
return(0);
|
|
}
|
|
|
|
// open 6 voices ( 4 pcm, one noise, and one sweep)
|
|
AOpenVoices(6);
|
|
|
|
// create the 4 pcm channels
|
|
for (i=0; i<4; i++)
|
|
{
|
|
// create the channel
|
|
ACreateAudioVoice(&ws_audio_pcm_voice[i]);
|
|
ASetVoiceVolume ( ws_audio_pcm_voice[i], AUDIO_MAX_VOLUME);
|
|
ASetVoicePanning ( ws_audio_pcm_voice[i], AUDIO_MIN_PANNING);
|
|
|
|
|
|
// create a looped sound buffer
|
|
ws_audio_pcm_wave[i].nSampleRate = info.nSampleRate;
|
|
ws_audio_pcm_wave[i].dwLength = BUFSIZE;
|
|
ws_audio_pcm_wave[i].dwLoopStart = 0;
|
|
ws_audio_pcm_wave[i].dwLoopEnd = ws_audio_pcm_wave[i].dwLength;
|
|
ws_audio_pcm_wave[i].wFormat = AUDIO_FORMAT_8BITS | AUDIO_FORMAT_MONO | AUDIO_FORMAT_LOOP;
|
|
|
|
ACreateAudioData(&ws_audio_pcm_wave[i]);
|
|
|
|
// channel is not playing yet
|
|
ws_audio_channel_isPlaying[i]=0;
|
|
|
|
// clear the channel
|
|
ws_audio_clear_channel(i);
|
|
}
|
|
|
|
// create the noise channel
|
|
{
|
|
// create the channel
|
|
ACreateAudioVoice(&ws_audio_noise_voice);
|
|
ASetVoiceVolume ( ws_audio_noise_voice, AUDIO_MAX_VOLUME);
|
|
ASetVoicePanning ( ws_audio_noise_voice, AUDIO_MAX_PANNING>>1);
|
|
|
|
|
|
// create a looped sound buffer
|
|
ws_audio_noise_wave.nSampleRate = info.nSampleRate;
|
|
ws_audio_noise_wave.dwLength = (BUFSIZEP<<4);
|
|
ws_audio_noise_wave.dwLoopStart = 0;
|
|
ws_audio_noise_wave.dwLoopEnd = ws_audio_noise_wave.dwLength;
|
|
ws_audio_noise_wave.wFormat = AUDIO_FORMAT_8BITS | AUDIO_FORMAT_MONO | AUDIO_FORMAT_LOOP;
|
|
|
|
ACreateAudioData(&ws_audio_noise_wave);
|
|
|
|
// channel is not playing yet
|
|
ws_audio_channel_isPlaying[4]=0;
|
|
|
|
// clear the channel
|
|
ws_audio_clear_channel(4);
|
|
}
|
|
|
|
// create the sweep channel
|
|
{
|
|
// create the channel
|
|
ACreateAudioVoice(&ws_audio_sweep_voice);
|
|
ASetVoiceVolume ( ws_audio_sweep_voice, AUDIO_MAX_VOLUME);
|
|
ASetVoicePanning ( ws_audio_sweep_voice, AUDIO_MAX_PANNING);
|
|
|
|
|
|
// create a looped sound buffer
|
|
ws_audio_sweep_wave.nSampleRate = info.nSampleRate;
|
|
ws_audio_sweep_wave.dwLength = BUFSIZEN;
|
|
ws_audio_sweep_wave.dwLoopStart = 0;
|
|
ws_audio_sweep_wave.dwLoopEnd = ws_audio_sweep_wave.dwLength;
|
|
ws_audio_sweep_wave.wFormat = AUDIO_FORMAT_8BITS | AUDIO_FORMAT_MONO | AUDIO_FORMAT_LOOP;
|
|
|
|
ACreateAudioData(&ws_audio_sweep_wave);
|
|
|
|
// channel is not playing yet
|
|
ws_audio_channel_isPlaying[5]=0;
|
|
|
|
// clear the channel
|
|
ws_audio_clear_channel(5);
|
|
}
|
|
|
|
// initialize the noise channel data
|
|
int rand;
|
|
|
|
for(i=0; i<8; i++)
|
|
{
|
|
for(j=0; j<BUFSIZEN; j++)
|
|
{
|
|
rand=ws_audio_mrand(15-i)&1;
|
|
|
|
if(rand)
|
|
{
|
|
PDataN[i][j]=PH;
|
|
}
|
|
else
|
|
{
|
|
PDataN[i][j]=PL;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(j=0; j<BUFSIZEN; j++)
|
|
{
|
|
RandData[j]=ws_audio_mrand(15);
|
|
}
|
|
|
|
ASetAudioMixerValue(AUDIO_MIXER_MASTER_VOLUME, AUDIO_MAX_VOLUME);
|
|
|
|
|
|
fflush(log_get());
|
|
|
|
#endif
|
|
return 1;
|
|
}
|
|
|
|
void ws_audio_seal_done(void)
|
|
{
|
|
#if 0
|
|
int i;
|
|
|
|
// stop channels
|
|
for (i=0; i<6; i++)
|
|
{
|
|
ws_audio_stop_channel(i);
|
|
}
|
|
|
|
// destroy pcm wave data
|
|
for (i=0; i<4; i++)
|
|
{
|
|
ADestroyAudioData(&ws_audio_pcm_wave[i]);
|
|
}
|
|
|
|
// destroy noise wave data
|
|
ADestroyAudioData(&ws_audio_noise_wave);
|
|
|
|
// destroy sweep wave data
|
|
ADestroyAudioData(&ws_audio_sweep_wave);
|
|
|
|
// release pcm channels
|
|
for (i=0; i<4; i++)
|
|
{
|
|
ADestroyAudioVoice(ws_audio_pcm_voice[i]);
|
|
}
|
|
|
|
// release noise channel
|
|
ADestroyAudioVoice(ws_audio_noise_voice);
|
|
|
|
// release sweep channel
|
|
ADestroyAudioVoice(ws_audio_sweep_voice);
|
|
|
|
// close A channels
|
|
ACloseVoices();
|
|
|
|
// close audio
|
|
ACloseAudio();
|
|
#endif
|
|
|
|
}
|
|
|
|
void ws_audio_clear_channel(int Channel)
|
|
{
|
|
#if 0
|
|
ChCurVol[Channel]=-1;
|
|
ChCurPer[Channel]=-1;
|
|
ChCurPan[Channel]=-1;
|
|
|
|
if(Channel==5)
|
|
{
|
|
memset(ws_audio_sweep_wave.lpData, 0, ws_audio_sweep_wave.dwLength);
|
|
AWriteAudioData(&ws_audio_sweep_wave, 0, ws_audio_sweep_wave.dwLength);
|
|
}
|
|
else if(Channel==4)
|
|
{
|
|
memset(ws_audio_noise_wave.lpData, 0, ws_audio_noise_wave.dwLength);
|
|
AWriteAudioData(&ws_audio_noise_wave, 0, ws_audio_noise_wave.dwLength);
|
|
}
|
|
else
|
|
{
|
|
memset(ws_audio_pcm_wave[Channel].lpData, 0, ws_audio_pcm_wave[Channel].dwLength);
|
|
AWriteAudioData(&ws_audio_pcm_wave[Channel], 0, ws_audio_pcm_wave[Channel].dwLength);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
int ws_audio_play_channel(int Channel)
|
|
{
|
|
#if 0
|
|
if (ws_audio_channel_isPlaying[Channel])
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
ws_audio_channel_isPlaying[Channel]=1;
|
|
|
|
if (Channel==5)
|
|
{
|
|
APlayVoice(ws_audio_sweep_voice, &ws_audio_sweep_wave);
|
|
}
|
|
else if (Channel==4)
|
|
{
|
|
APlayVoice(ws_audio_noise_voice, &ws_audio_noise_wave);
|
|
}
|
|
else
|
|
{
|
|
// ASetVoiceFrequency(ws_audio_pcm_voice[Channel],3072000/(2048-ChCurPer[Channel]));
|
|
APlayVoice(ws_audio_pcm_voice[Channel], &ws_audio_pcm_wave[Channel]);
|
|
ASetVoiceFrequency(ws_audio_pcm_voice[Channel],3072000/(2048-ChCurPer[Channel]));
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
int ws_audio_stop_channel(int Channel)
|
|
{
|
|
#if 0
|
|
if (!ws_audio_channel_isPlaying[Channel])
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
ws_audio_channel_isPlaying[Channel]=0;
|
|
|
|
if (Channel==5)
|
|
{
|
|
AStopVoice(ws_audio_sweep_voice);
|
|
}
|
|
else if (Channel==4)
|
|
{
|
|
AStopVoice(ws_audio_noise_voice);
|
|
}
|
|
else
|
|
{
|
|
AStopVoice(ws_audio_pcm_voice[Channel]);
|
|
}
|
|
#endif
|
|
return (0);
|
|
}
|
|
|
|
void ws_audio_set_channel_frequency(int Channel, int Period)
|
|
{
|
|
#if 0
|
|
uint32_t Freq;
|
|
|
|
if(ChCurPer[Channel]==Period)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ChCurPer[Channel]=Period;
|
|
|
|
Freq=3072000/(2048-Period);
|
|
|
|
if(Channel==2)
|
|
{
|
|
ChPerInit=Period;
|
|
SwpCurPeriod=Period;
|
|
}
|
|
|
|
if(Freq>BPSMAX)
|
|
{
|
|
Freq=BPSMAX;
|
|
}
|
|
|
|
else if(Freq<BPSMIN)
|
|
{
|
|
Freq=BPSMIN;
|
|
}
|
|
|
|
if (Channel==5)
|
|
{
|
|
ASetVoiceFrequency(ws_audio_sweep_voice,Freq);
|
|
}
|
|
else if (Channel==4)
|
|
{
|
|
ASetVoiceFrequency(ws_audio_noise_voice,Freq);
|
|
}
|
|
else
|
|
{
|
|
ASetVoiceFrequency(ws_audio_pcm_voice[Channel],Freq);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void ws_audio_set_channel_volume(int Channel, int Vol)
|
|
{
|
|
#if 0
|
|
long volume;
|
|
|
|
if(ChCurVol[Channel]==Vol)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ChCurVol[Channel]=Vol;
|
|
|
|
volume=(Vol+1)*(MainVol+1)*(HardVol+1)/16-1;
|
|
|
|
if (Channel==5)
|
|
{
|
|
ASetVoiceVolume(ws_audio_sweep_voice,volume);
|
|
}
|
|
else if (Channel==4)
|
|
{
|
|
ASetVoiceVolume(ws_audio_noise_voice,volume);
|
|
}
|
|
else
|
|
{
|
|
ASetVoiceVolume(ws_audio_pcm_voice[Channel],volume);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void ws_audio_set_channel_pan(int Channel, int Left, int Right)
|
|
{
|
|
#if 0
|
|
long pan;
|
|
|
|
const long TblPan[16][16]=
|
|
{
|
|
{ 0, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000},
|
|
{-10000, 0, 602, 954, 1204, 1398, 1556, 1690, 1806, 1908, 2000, 2082, 2158, 2228, 2292, 2352},
|
|
{-10000, -602, 0, 352, 602, 796, 954, 1088, 1204, 1306, 1398, 1481, 1556, 1626, 1690, 1750},
|
|
{-10000, -954, -352, 0, 250, 444, 602, 736, 852, 954, 1046, 1129, 1204, 1274, 1338, 1398},
|
|
{-10000, -1204, -602, -250, 0, 194, 352, 486, 602, 704, 796, 879, 954, 1024, 1088, 1148},
|
|
{-10000, -1398, -796, -444, -194, 0, 158, 292, 408, 511, 602, 685, 760, 830, 894, 954},
|
|
{-10000, -1556, -954, -602, -352, -158, 0, 134, 250, 352, 444, 526, 602, 672, 736, 796},
|
|
{-10000, -1690, -1088, -736, -486, -292, -134, 0, 116, 218, 310, 393, 468, 538, 602, 662},
|
|
{-10000, -1806, -1204, -852, -602, -408, -250, -116, 0, 102, 194, 277, 352, 422, 486, 546},
|
|
{-10000, -1908, -1306, -954, -704, -511, -352, -218, -102, 0, 92, 174, 250, 319, 384, 444},
|
|
{-10000, -2000, -1398, -1046, -796, -602, -444, -310, -194, -92, 0, 83, 158, 228, 292, 352},
|
|
{-10000, -2082, -1481, -1129, -879, -685, -526, -393, -277, -174, -83, 0, 76, 145, 209, 269},
|
|
{-10000, -2158, -1556, -1204, -954, -760, -602, -468, -352, -250, -158, -76, 0, 70, 134, 194},
|
|
{-10000, -2228, -1626, -1274, -1024, -830, -672, -538, -422, -319, -228, -145, -70, 0, 64, 124},
|
|
{-10000, -2292, -1690, -1338, -1088, -894, -736, -602, -486, -384, -292, -209, -134, -64, 0, 60},
|
|
{-10000, -2352, -1750, -1398, -1148, -954, -796, -662, -546, -444, -352, -269, -194, -124, -60, 0},
|
|
};
|
|
|
|
if(Left>Right)
|
|
{
|
|
ws_audio_set_channel_volume(Channel,Left);
|
|
}
|
|
else
|
|
{
|
|
ws_audio_set_channel_volume(Channel,Right);
|
|
}
|
|
|
|
pan=TblPan[Left][Right];
|
|
|
|
if(ChCurPan[Channel]==pan)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ChCurPan[Channel]=pan;
|
|
|
|
if (pan>10000)
|
|
{
|
|
pan=10000;
|
|
}
|
|
|
|
pan=((pan+10000)*AUDIO_MAX_PANNING)/20000;
|
|
|
|
if (Channel==5)
|
|
{
|
|
ASetVoicePanning(ws_audio_sweep_voice,pan);
|
|
}
|
|
else if (Channel==4)
|
|
{
|
|
ASetVoicePanning(ws_audio_noise_voice,pan);
|
|
}
|
|
else
|
|
{
|
|
ASetVoicePanning(ws_audio_pcm_voice[Channel],pan);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void ws_audio_set_channel_pdata(int Channel, int Index)
|
|
{
|
|
#if 0
|
|
unsigned char *pData;
|
|
|
|
if(Channel==5)
|
|
{
|
|
pData=PDataN[Index];
|
|
|
|
memcpy(ws_audio_sweep_wave.lpData, pData, ws_audio_sweep_wave.dwLength);
|
|
AWriteAudioData(&ws_audio_sweep_wave, 0, ws_audio_sweep_wave.dwLength);
|
|
}
|
|
else if(Channel==4)
|
|
{
|
|
pData=PDataP;
|
|
memcpy(ws_audio_noise_wave.lpData, pData, ws_audio_noise_wave.dwLength);
|
|
AWriteAudioData(&ws_audio_noise_wave, 0, ws_audio_noise_wave.dwLength);
|
|
}
|
|
else
|
|
{
|
|
pData=PData[Channel];
|
|
memcpy(ws_audio_pcm_wave[Channel].lpData, pData, ws_audio_pcm_wave[Channel].dwLength);
|
|
AWriteAudioData(&ws_audio_pcm_wave[Channel], 0, ws_audio_pcm_wave[Channel].dwLength);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void ws_audio_set_channels_pbuf(int Addr, int Data)
|
|
{
|
|
#if 0
|
|
int i,j;
|
|
|
|
i=(Addr&0x30)>>4;
|
|
|
|
for(j=(Addr&0x0F)<<1; j<BUFSIZE; j+=32)
|
|
{
|
|
PData[i][j] = (Data&0x0f)*17-128;
|
|
PData[i][j+1] = ((Data>>4)&0x0f)*17-128;
|
|
}
|
|
|
|
if((Addr&0x0F)==0x0F)
|
|
{
|
|
ws_audio_set_channel_pdata(i,0);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void ws_audio_rst_channel(int Channel)
|
|
{
|
|
#if 0
|
|
if(Channel==2)
|
|
{
|
|
ws_audio_set_channel_frequency(2,ChPerInit);
|
|
SwpCurPeriod=ChPerInit;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
int ws_audio_int(void)
|
|
{
|
|
#if 0
|
|
unsigned int value;
|
|
static int i;
|
|
|
|
if((SwpStep)&&(SNDMOD&0x40))
|
|
{
|
|
if(CntSwp<0)
|
|
{
|
|
CntSwp=SwpTime;
|
|
SwpCurPeriod+=SwpStep;
|
|
SwpCurPeriod&=0x7FF;
|
|
value=3072000/(2048-SwpCurPeriod);
|
|
|
|
if(value>100000)
|
|
{
|
|
value=100000;
|
|
ws_audio_set_channel_volume(2,0);
|
|
}
|
|
|
|
if(value<100)
|
|
{
|
|
value=100;
|
|
}
|
|
|
|
ASetVoiceFrequency(ws_audio_pcm_voice[2],value);
|
|
}
|
|
|
|
CntSwp--;
|
|
}
|
|
|
|
i++;
|
|
|
|
if(i>=BUFSIZEN)
|
|
{
|
|
i=0;
|
|
}
|
|
|
|
return RandData[i];
|
|
#endif
|
|
return 1;
|
|
}
|
|
|
|
#if 0
|
|
static uint32_t PCMPos=0;
|
|
uint32_t TickZ=0,PcmCount;
|
|
#endif
|
|
|
|
void ws_audio_set_pcm(int Data)
|
|
{
|
|
#if 0
|
|
uint32_t tick;
|
|
PDataP[PCMPos++]=(unsigned char)(Data+128);
|
|
tick=SDL_GetTicks();
|
|
PcmCount++;
|
|
|
|
if(tick>=TickZ)
|
|
{
|
|
TickZ=tick+125;
|
|
PcmCount<<=3;
|
|
|
|
if(PcmCount>=10000)
|
|
{
|
|
PcmCount=12000;
|
|
}
|
|
|
|
ASetVoiceFrequency(ws_audio_noise_voice,PcmCount);
|
|
PcmCount=0;
|
|
}
|
|
|
|
if(PCMPos>=BUFSIZEP)
|
|
{
|
|
ws_audio_flash_pcm();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void ws_audio_flash_pcm(void)
|
|
{
|
|
#if 0
|
|
uint32_t len1;
|
|
|
|
const uint32_t WrPos[16]=
|
|
{
|
|
BUFSIZEP*0,BUFSIZEP*1,BUFSIZEP*2,BUFSIZEP*3,
|
|
BUFSIZEP*4,BUFSIZEP*5,BUFSIZEP*6,BUFSIZEP*7,
|
|
BUFSIZEP*8,BUFSIZEP*9,BUFSIZEP*10,BUFSIZEP*11,
|
|
BUFSIZEP*12,BUFSIZEP*13,BUFSIZEP*14,BUFSIZEP*15,
|
|
};
|
|
|
|
len1=BUFSIZEP;
|
|
|
|
if (ws_audio_noise_wave.lpData == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
memcpy(&ws_audio_noise_wave.lpData[WrPos[PcmWrPos]], PDataP, len1);
|
|
AWriteAudioData(&ws_audio_noise_wave, 0, ws_audio_noise_wave.dwLength);
|
|
|
|
|
|
PcmWrPos++;
|
|
PcmWrPos&=0xF;
|
|
memset(PDataP,PL,sizeof(PDataP));
|
|
PCMPos=0;
|
|
#endif
|
|
}
|
|
|
|
void ws_audio_write_byte(uint32_t offset, uint8_t value)
|
|
{
|
|
if (!((offset - WaveMap) & 0xFFC0))
|
|
{
|
|
ws_audio_set_channels_pbuf(offset & 0x003F, value);
|
|
internalRam[offset] = value;
|
|
}
|
|
}
|
|
|
|
void ws_audio_process(void)
|
|
{
|
|
uint32_t i, j, b;
|
|
i = ws_audio_int();
|
|
PCSRL = (uint8_t)(i & 0xFF);
|
|
PCSRH = (uint8_t)((i >> 8) & 0xFF);
|
|
|
|
if ((SDMACTL & 0x88) == 0x80)
|
|
{
|
|
i = (SDMACH << 8) | SDMACL;
|
|
j = (SDMASB << 16) | (SDMASH << 8) | SDMASL;
|
|
b = mem_readmem20(j);
|
|
|
|
if (!ws_audio_channel_isPlaying[5])
|
|
{
|
|
b = 0x80;
|
|
}
|
|
|
|
ws_ioRam[0x89] = b;
|
|
i--;
|
|
j++;
|
|
|
|
if (i < 32)
|
|
{
|
|
i = 0;
|
|
SDMACTL &= 0x7F;
|
|
}
|
|
|
|
SDMASB = (uint8_t)((j >> 16) & 0xFF);
|
|
SDMASH = (uint8_t)((j >> 8) & 0xFF);
|
|
SDMASL = (uint8_t)(j & 0xFF);
|
|
SDMACH = (uint8_t)((i >> 8) & 0xFF);
|
|
SDMACL = (uint8_t)(i & 0xFF);
|
|
}
|
|
else if ((SNDMOD & 0x22) == 0x22)
|
|
{
|
|
b = ws_ioRam[0x89];
|
|
|
|
if (!ws_audio_channel_isPlaying[4])
|
|
{
|
|
b = 0x80;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
b = 0x80;
|
|
}
|
|
|
|
b >>= 1;
|
|
b += 0x40;
|
|
|
|
if (b > 0xAA)
|
|
{
|
|
b = 0xAA;
|
|
}
|
|
else if (b < 0x55)
|
|
{
|
|
b = 0x55;
|
|
}
|
|
|
|
ws_audio_set_pcm(b);
|
|
}
|
|
|
|
void ws_audio_readState(int fp)
|
|
{
|
|
#if 0
|
|
long lpdwPosition;
|
|
long lpdwFrequency;
|
|
unsigned int lpnVolume;
|
|
unsigned int lpnPanning;
|
|
int lpnStatus;
|
|
unsigned char *pData;
|
|
|
|
read(fp,&PCMPos,sizeof(uint32_t));
|
|
read(fp,&TickZ,sizeof(uint32_t));
|
|
read(fp,&PcmCount,sizeof(uint32_t));
|
|
read(fp,&WaveMap,sizeof(int));
|
|
read(fp,&ChPerInit,sizeof(int));
|
|
read(fp,&SwpTime,sizeof(int));
|
|
read(fp,&SwpStep,sizeof(int));
|
|
read(fp,&SwpCurPeriod,sizeof(int));
|
|
read(fp,&MainVol,sizeof(int));
|
|
read(fp,&CntSwp,sizeof(int));
|
|
read(fp,&PcmWrPos,sizeof(int));
|
|
|
|
read(fp,ws_audio_channel_isPlaying,sizeof(uint32_t)*6);
|
|
|
|
read(fp,PData,sizeof(unsigned char)*4*BUFSIZE);
|
|
read(fp,PDataP,sizeof(unsigned char)*(BUFSIZEP<<4));
|
|
read(fp,PDataN,sizeof(unsigned char)*8*BUFSIZEN);
|
|
read(fp,PDataN,sizeof(int)*BUFSIZEN);
|
|
|
|
for (int i=0; i<4; i++)
|
|
{
|
|
read(fp,&lpdwPosition,sizeof(long));
|
|
read(fp,&lpdwFrequency,sizeof(long));
|
|
read(fp,&lpnVolume,sizeof(unsigned int));
|
|
read(fp,&lpnPanning,sizeof(unsigned int));
|
|
read(fp,&lpnStatus,sizeof(int));
|
|
ASetVoicePosition(ws_audio_pcm_voice[i],lpdwPosition);
|
|
ASetVoiceFrequency(ws_audio_pcm_voice[i], lpdwFrequency);
|
|
ASetVoiceVolume(ws_audio_pcm_voice[i], lpnVolume);
|
|
ASetVoicePanning(ws_audio_pcm_voice[i], lpnPanning);
|
|
pData=PData[i];
|
|
memcpy(ws_audio_pcm_wave[i].lpData, pData, ws_audio_pcm_wave[i].dwLength);
|
|
AWriteAudioData(&ws_audio_pcm_wave[i], 0, ws_audio_pcm_wave[i].dwLength);
|
|
|
|
if (ws_audio_channel_isPlaying[i])
|
|
{
|
|
APlayVoice(ws_audio_pcm_voice[i], &ws_audio_pcm_wave[i]);
|
|
}
|
|
}
|
|
|
|
ASetVoicePosition(ws_audio_noise_voice,lpdwPosition);
|
|
ASetVoiceFrequency(ws_audio_noise_voice, lpdwFrequency);
|
|
ASetVoiceVolume(ws_audio_noise_voice, lpnVolume);
|
|
ASetVoicePanning(ws_audio_noise_voice, lpnPanning);
|
|
pData=PDataP;
|
|
memcpy(ws_audio_noise_wave.lpData, pData, ws_audio_noise_wave.dwLength);
|
|
AWriteAudioData(&ws_audio_noise_wave, 0, ws_audio_noise_wave.dwLength);
|
|
|
|
if (ws_audio_channel_isPlaying[4])
|
|
{
|
|
APlayVoice(ws_audio_noise_voice, &ws_audio_noise_wave);
|
|
}
|
|
|
|
read(fp,&lpdwPosition,sizeof(long));
|
|
read(fp,&lpdwFrequency,sizeof(long));
|
|
read(fp,&lpnVolume,sizeof(unsigned int));
|
|
read(fp,&lpnPanning,sizeof(unsigned int));
|
|
read(fp,&lpnStatus,sizeof(int));
|
|
|
|
ASetVoicePosition(ws_audio_sweep_voice,lpdwPosition);
|
|
ASetVoiceFrequency(ws_audio_sweep_voice, lpdwFrequency);
|
|
ASetVoiceVolume(ws_audio_sweep_voice, lpnVolume);
|
|
ASetVoicePanning(ws_audio_sweep_voice, lpnPanning);
|
|
pData=PDataN[0];
|
|
memcpy(ws_audio_sweep_wave.lpData, pData, ws_audio_sweep_wave.dwLength);
|
|
AWriteAudioData(&ws_audio_sweep_wave, 0, ws_audio_sweep_wave.dwLength);
|
|
|
|
if (ws_audio_channel_isPlaying[5])
|
|
{
|
|
APlayVoice(ws_audio_sweep_voice, &ws_audio_sweep_wave);
|
|
}
|
|
|
|
read(fp,&lpdwPosition,sizeof(long));
|
|
read(fp,&lpdwFrequency,sizeof(long));
|
|
read(fp,&lpnVolume,sizeof(unsigned int));
|
|
read(fp,&lpnPanning,sizeof(unsigned int));
|
|
read(fp,&lpnStatus,sizeof(int));
|
|
#endif
|
|
}
|
|
|
|
void ws_audio_writeState(int fp)
|
|
{
|
|
#if 0
|
|
int32_t lpdwPosition;
|
|
int32_t lpdwFrequency;
|
|
uint16_t lpnVolume;
|
|
uint16_t lpnPanning;
|
|
int8_t lpnStatus;
|
|
|
|
write(fp,&PCMPos,sizeof(uint32_t));
|
|
write(fp,&TickZ,sizeof(uint32_t));
|
|
write(fp,&PcmCount,sizeof(uint32_t));
|
|
write(fp,&WaveMap,sizeof(int));
|
|
write(fp,&ChPerInit,sizeof(int));
|
|
write(fp,&SwpTime,sizeof(int));
|
|
write(fp,&SwpStep,sizeof(int));
|
|
write(fp,&SwpCurPeriod,sizeof(int));
|
|
write(fp,&MainVol,sizeof(int));
|
|
write(fp,&CntSwp,sizeof(int));
|
|
write(fp,&PcmWrPos,sizeof(int));
|
|
|
|
write(fp,ws_audio_channel_isPlaying,sizeof(uint32_t)*6);
|
|
|
|
write(fp,PData,sizeof(unsigned char)*4*BUFSIZE);
|
|
write(fp,PDataP,sizeof(unsigned char)*(BUFSIZEP<<4));
|
|
write(fp,PDataN,sizeof(unsigned char)*8*BUFSIZEN);
|
|
write(fp,PDataN,sizeof(int)*BUFSIZEN);
|
|
|
|
for (int i=0; i<4; i++)
|
|
{
|
|
AGetVoicePosition(ws_audio_pcm_voice[i],&lpdwPosition);
|
|
AGetVoiceFrequency(ws_audio_pcm_voice[i], &lpdwFrequency);
|
|
AGetVoiceVolume(ws_audio_pcm_voice[i], &lpnVolume);
|
|
AGetVoicePanning(ws_audio_pcm_voice[i], &lpnPanning);
|
|
AGetVoiceStatus(ws_audio_pcm_voice[i], &lpnStatus);
|
|
|
|
write(fp,&lpdwPosition,sizeof(long));
|
|
write(fp,&lpdwFrequency,sizeof(long));
|
|
write(fp,&lpnVolume,sizeof(unsigned int));
|
|
write(fp,&lpnPanning,sizeof(unsigned int));
|
|
write(fp,&lpnStatus,sizeof(int));
|
|
}
|
|
|
|
AGetVoicePosition(ws_audio_noise_voice,&lpdwPosition);
|
|
AGetVoiceFrequency(ws_audio_noise_voice, &lpdwFrequency);
|
|
AGetVoiceVolume(ws_audio_noise_voice, &lpnVolume);
|
|
AGetVoicePanning(ws_audio_noise_voice, &lpnPanning);
|
|
AGetVoiceStatus(ws_audio_noise_voice, &lpnStatus);
|
|
|
|
write(fp,&lpdwPosition,sizeof(long));
|
|
write(fp,&lpdwFrequency,sizeof(long));
|
|
write(fp,&lpnVolume,sizeof(unsigned int));
|
|
write(fp,&lpnPanning,sizeof(unsigned int));
|
|
write(fp,&lpnStatus,sizeof(int));
|
|
|
|
AGetVoicePosition(ws_audio_sweep_voice,&lpdwPosition);
|
|
AGetVoiceFrequency(ws_audio_sweep_voice, &lpdwFrequency);
|
|
AGetVoiceVolume(ws_audio_sweep_voice, &lpnVolume);
|
|
AGetVoicePanning(ws_audio_sweep_voice, &lpnPanning);
|
|
AGetVoiceStatus(ws_audio_sweep_voice, &lpnStatus);
|
|
|
|
write(fp,&lpdwPosition,sizeof(long));
|
|
write(fp,&lpdwFrequency,sizeof(long));
|
|
write(fp,&lpnVolume,sizeof(unsigned int));
|
|
write(fp,&lpnPanning,sizeof(unsigned int));
|
|
write(fp,&lpnStatus,sizeof(int));
|
|
#endif
|
|
}
|