00001
00002
00003
00004
00005
00006
00007 #include <dos/dostags.h>
00008 #include <hardware/cia.h>
00009 #include <proto/exec.h>
00010 #include <proto/dos.h>
00011 #include <proto/ahi.h>
00012 #include <proto/graphics.h>
00013
00014
00015
00016 struct Library *AHIBase;
00017
00018
00019 extern struct CIA ciaa;
00020
00021
00022
00023
00024
00025
00026 void DigitalRenderer::init_sound(void)
00027 {
00028
00029 main_task = FindTask(NULL);
00030
00031
00032 main_sig = AllocSignal(-1);
00033
00034
00035 if ((sound_process = CreateNewProcTags(
00036 NP_Entry, (ULONG)&sub_invoc,
00037 NP_Name, (ULONG)"Frodo Sound Process",
00038 NP_Priority, 1,
00039 NP_ExitData, (ULONG)this,
00040 TAG_DONE)) != NULL)
00041 Wait(1 << main_sig);
00042 }
00043
00044
00045
00046
00047
00048
00049 DigitalRenderer::~DigitalRenderer()
00050 {
00051
00052 if (sound_process != NULL) {
00053 Signal(&(sound_process->pr_Task), 1 << quit_sig);
00054 Wait(1 << main_sig);
00055 }
00056
00057
00058 FreeSignal(main_sig);
00059 }
00060
00061
00062
00063
00064
00065
00066 void DigitalRenderer::EmulateLine(void)
00067 {
00068 sample_buf[sample_in_ptr] = volume;
00069 sample_in_ptr = (sample_in_ptr + 1) % SAMPLE_BUF_SIZE;
00070 }
00071
00072
00073
00074
00075
00076
00077 void DigitalRenderer::Pause(void)
00078 {
00079 if (sound_process != NULL)
00080 Signal(&(sound_process->pr_Task), 1 << pause_sig);
00081 }
00082
00083
00084
00085
00086
00087
00088 void DigitalRenderer::Resume(void)
00089 {
00090 if (sound_process != NULL)
00091 Signal(&(sound_process->pr_Task), 1 << resume_sig);
00092 }
00093
00094
00095
00096
00097
00098
00099 void DigitalRenderer::sub_invoc(void)
00100 {
00101
00102 DigitalRenderer *r = (DigitalRenderer *)((struct Process *)FindTask(NULL))->pr_ExitData;
00103 r->sub_func();
00104 }
00105
00106 void DigitalRenderer::sub_func(void)
00107 {
00108 ahi_port = NULL;
00109 ahi_io = NULL;
00110 ahi_ctrl = NULL;
00111 sample[0].ahisi_Address = sample[1].ahisi_Address = NULL;
00112 ready = FALSE;
00113
00114
00115 quit_sig = AllocSignal(-1);
00116 pause_sig = AllocSignal(-1);
00117 resume_sig = AllocSignal(-1);
00118 ahi_sig = AllocSignal(-1);
00119
00120
00121 if ((ahi_port = CreateMsgPort()) == NULL)
00122 goto wait_for_quit;
00123 if ((ahi_io = (struct AHIRequest *)CreateIORequest(ahi_port, sizeof(struct AHIRequest))) == NULL)
00124 goto wait_for_quit;
00125 ahi_io->ahir_Version = 2;
00126 if (OpenDevice(AHINAME, AHI_NO_UNIT, (struct IORequest *)ahi_io, NULL))
00127 goto wait_for_quit;
00128 AHIBase = (struct Library *)ahi_io->ahir_Std.io_Device;
00129
00130
00131 sf_hook.h_Entry = sound_func;
00132
00133
00134 if ((ahi_ctrl = AHI_AllocAudio(
00135 AHIA_AudioID, 0x0002000b,
00136 AHIA_MixFreq, SAMPLE_FREQ,
00137 AHIA_Channels, 1,
00138 AHIA_Sounds, 2,
00139 AHIA_SoundFunc, (ULONG)&sf_hook,
00140 AHIA_UserData, (ULONG)this,
00141 TAG_DONE)) == NULL)
00142 goto wait_for_quit;
00143
00144
00145 sample[0].ahisi_Type = AHIST_M16S;
00146 sample[0].ahisi_Length = SAMPLE_FREQ / CALC_FREQ;
00147 sample[0].ahisi_Address = AllocVec(SAMPLE_FREQ / CALC_FREQ * 2, MEMF_PUBLIC | MEMF_CLEAR);
00148 sample[1].ahisi_Type = AHIST_M16S;
00149 sample[1].ahisi_Length = SAMPLE_FREQ / CALC_FREQ;
00150 sample[1].ahisi_Address = AllocVec(SAMPLE_FREQ / CALC_FREQ * 2, MEMF_PUBLIC | MEMF_CLEAR);
00151 if (sample[0].ahisi_Address == NULL || sample[1].ahisi_Address == NULL)
00152 goto wait_for_quit;
00153 AHI_LoadSound(0, AHIST_DYNAMICSAMPLE, &sample[0], ahi_ctrl);
00154 AHI_LoadSound(1, AHIST_DYNAMICSAMPLE, &sample[1], ahi_ctrl);
00155
00156
00157 play_buf = 0;
00158 AHI_SetVol(0, 0x10000, 0x8000, ahi_ctrl, AHISF_IMM);
00159 AHI_SetFreq(0, SAMPLE_FREQ, ahi_ctrl, AHISF_IMM);
00160 AHI_SetSound(0, play_buf, 0, 0, ahi_ctrl, AHISF_IMM);
00161
00162
00163 AHI_ControlAudio(ahi_ctrl, AHIC_Play, TRUE, TAG_DONE);
00164
00165
00166 ready = TRUE;
00167 Signal(main_task, 1 << main_sig);
00168
00169
00170 for (;;) {
00171 ULONG sigs = Wait((1 << quit_sig) | (1 << pause_sig) | (1 << resume_sig) | (1 << ahi_sig));
00172
00173
00174 if (sigs & (1 << quit_sig))
00175 goto quit;
00176
00177
00178 if (sigs & (1 << pause_sig))
00179 AHI_ControlAudio(ahi_ctrl, AHIC_Play, FALSE, TAG_DONE);
00180
00181
00182 if (sigs & (1 << resume_sig))
00183 AHI_ControlAudio(ahi_ctrl, AHIC_Play, TRUE, TAG_DONE);
00184
00185
00186 if (sigs & (1 << ahi_sig))
00187 calc_buffer((int16 *)(sample[play_buf].ahisi_Address), sample[play_buf].ahisi_Length * 2);
00188 }
00189
00190 wait_for_quit:
00191
00192 Wait(1 << quit_sig);
00193
00194 quit:
00195
00196 if (ahi_ctrl != NULL) {
00197 AHI_ControlAudio(ahi_ctrl, AHIC_Play, FALSE, TAG_DONE);
00198 AHI_FreeAudio(ahi_ctrl);
00199 CloseDevice((struct IORequest *)ahi_io);
00200 }
00201
00202 FreeVec(sample[0].ahisi_Address);
00203 FreeVec(sample[1].ahisi_Address);
00204
00205 if (ahi_io != NULL)
00206 DeleteIORequest((struct IORequest *)ahi_io);
00207
00208 if (ahi_port != NULL)
00209 DeleteMsgPort(ahi_port);
00210
00211 FreeSignal(quit_sig);
00212 FreeSignal(pause_sig);
00213 FreeSignal(resume_sig);
00214 FreeSignal(ahi_sig);
00215
00216
00217 Forbid();
00218 Signal(main_task, 1 << main_sig);
00219 }
00220
00221
00222
00223
00224
00225
00226 ULONG DigitalRenderer::sound_func(void)
00227 {
00228 register struct AHIAudioCtrl *ahi_ctrl asm ("a2");
00229 DigitalRenderer *r = (DigitalRenderer *)ahi_ctrl->ahiac_UserData;
00230 r->play_buf ^= 1;
00231 AHI_SetSound(0, r->play_buf, 0, 0, ahi_ctrl, 0);
00232 Signal(&(r->sound_process->pr_Task), 1 << (r->ahi_sig));
00233 return 0;
00234 }
00235
00236
00237
00238
00239
00240
00241
00242 class SIDCardRenderer : public SIDRenderer {
00243 public:
00244 SIDCardRenderer();
00245 virtual ~SIDCardRenderer();
00246
00247 virtual void Reset(void);
00248 virtual void EmulateLine(void) {}
00249 virtual void WriteRegister(uint16 adr, uint8 byte);
00250 virtual void NewPrefs(Prefs *prefs) {}
00251 virtual void Pause(void) {}
00252 virtual void Resume(void) {}
00253
00254 private:
00255 UBYTE *sid_base;
00256 };
00257
00258
00259 SIDCardRenderer::SIDCardRenderer()
00260 {
00261 sid_base = (UBYTE *)0xa00001;
00262 Reset();
00263 }
00264
00265
00266 SIDCardRenderer::~SIDCardRenderer()
00267 {
00268 Reset();
00269 }
00270
00271
00272 void SIDCardRenderer::Reset(void)
00273 {
00274 WaitTOF();
00275 ciaa.ciapra |= CIAF_LED;
00276 WaitTOF();
00277 ciaa.ciapra &= ~CIAF_LED;
00278 }
00279
00280
00281 void SIDCardRenderer::WriteRegister(uint16 adr, uint8 byte)
00282 {
00283 sid_base[adr << 1] = byte;
00284 }