#include #include #include #include "Z80.h" #include "machine.h" #include "memmap.h" #include "roms.h" #include "romdecod.h" #include "osdepend.h" #include "sndhrdw.h" #define AY8910_CLOCK (1536000000) /* 1.536000000 MHZ */ #include "psg.c" unsigned char samples[0x4000]; /* 16k for samples */ #define UPDATES_PER_SECOND 60 #define emulation_rate (200*UPDATES_PER_SECOND) #define buffer_len (emulation_rate/UPDATES_PER_SECOND) int porta; byte porthandler(AY8910 *chip, int port, int iswrite, byte val) { if (iswrite) porta = val; return 0; } /*************************************************************************** Initialize the sound hardware. Returns 0 if successful. ***************************************************************************/ int sh_init(const char *gamename) { char *tmpstorage; int i; if ((tmpstorage = malloc(0x2000)) == 0) return 1; i = 0; while (gamesndinfo[i].name && stricmp(gamename,gamesndinfo[i].name) != 0) i++; if (readroms(tmpstorage,gamesndinfo[i].sndrom,gamename) != 0) { free(tmpstorage); return 1; } decodesound(samples,tmpstorage); decodesound(samples + 0x2000,tmpstorage + 0x1000); free(tmpstorage); return 0; } int sh_start(void) { if (AYInit(1,emulation_rate,buffer_len,0) == 0) { AYSetPortHandler(0,AY_PORTA,porthandler); return 0; } else return 1; } void sh_stop(void) { AYShutdown(); } /*************************************************************************** Handle a write to memory. This function is called when the emulated code writes to RAM. Arguments: dword A - Memory address to write to. byte V - Value to write into memory. If the address given concerns the sound hardware, the write is performed (together with additional operations which might be required by the sound hardware) and the function returns non zero. Otherwise, it returns 0. ***************************************************************************/ int sh_wrmem(dword A,byte V) { if (A == DIGSND_TRIGGER) { // fprintf(stderr,"sample\n"); if (V && play_sound != 0) /* play digital sound */ { int start,end; int freq,volume; // fprintf(stderr,"ins\n"); /* calculate the sampling frequency */ freq = 768000 / (256 - RAM[DIGSND_FREQ]); start = 64 * porta; end = start; /* find end of sample */ // while (end < 0x4000 && (samples[end] != 0x77 || samples[end+1] != 0x00)) while (end < 0x4000 && (samples[end] != 0xf7 || samples[end+1] != 0x80)) end += 2; volume = RAM[DIGSND_VOLUME] & 0x1f; volume = (volume << 3) | (volume >> 2); volume = 200; osd_play_sample(1,samples + start,end - start,freq,volume,0); } return 1; } else return 0; } /*************************************************************************** Execute an OUT instruction. If the port given concerns the sound hardware, the sound hardware processes it and the function returns non zero. Otherwise, it returns 0. ***************************************************************************/ int lastreg; /* AY-3-8910 register currently selected */ int sh_doout(byte A,byte V) { if (A == SNDCTRL_PORT) { lastreg = V; return 1; } else if (A == SNDWRITE_PORT) { AYWriteReg(0,lastreg,V); return 1; } else return 0; } /*************************************************************************** Read a data port IN. The processor needs to be able to read data from the Sound Chip. When turning voices on and off it must be able to read the status of other voices so it can OR or AND the appropriate bits without affecting the others. The CC software doesn't keep its own record of the status of the sound chip voices. (Lionel T.) ***************************************************************************/ int sh_doin(byte A,byte *V) { if (A == SNDREAD_PORT) { *V = AYReadReg(0,lastreg); return 1; } else return 0; } #define BUFFERS 2 void sh_update(void) { static int c; static unsigned char buffer[BUFFERS * buffer_len]; static int playing; static int vol = 200; if (play_sound == 0) return; AYSetBuffer(0,&buffer[c * buffer_len]); AYUpdate(); osd_play_streamed_sample(0,&buffer[c * buffer_len],buffer_len,emulation_rate,vol); if (!playing) { osd_play_streamed_sample(0,&buffer[c * buffer_len],buffer_len,emulation_rate,vol); osd_play_streamed_sample(0,&buffer[c * buffer_len],buffer_len,emulation_rate,vol); playing = 1; } c ^= 1; osd_update_audio(); }