Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members | Related Pages

SID_Amiga.i

Go to the documentation of this file.
00001 /*
00002  *  SID_Amiga.i - 6581 emulation, Amiga specific stuff
00003  *
00004  *  Frodo (C) 1994-1997 Christian Bauer
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 // Library bases
00016 struct Library *AHIBase;
00017 
00018 // CIA-A base
00019 extern struct CIA ciaa;
00020 
00021 
00022 /*
00023  *  Initialization, create sub-process
00024  */
00025 
00026 void DigitalRenderer::init_sound(void)
00027 {
00028         // Find our (main) task
00029         main_task = FindTask(NULL);
00030 
00031         // Create signal for communication
00032         main_sig = AllocSignal(-1);
00033 
00034         // Create sub-process and wait until it is ready
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,       // Easiest way to supply sub_invoc with this pointer
00040                 TAG_DONE)) != NULL)
00041                 Wait(1 << main_sig);
00042 }
00043 
00044 
00045 /*
00046  *  Destructor, delete sub-process
00047  */
00048 
00049 DigitalRenderer::~DigitalRenderer()
00050 {
00051         // Tell sub-process to quit and wait for completion
00052         if (sound_process != NULL) {
00053                 Signal(&(sound_process->pr_Task), 1 << quit_sig);
00054                 Wait(1 << main_sig);
00055         }
00056 
00057         // Free signal
00058         FreeSignal(main_sig);
00059 }
00060 
00061 
00062 /*
00063  *  Sample volume (for sampled voice)
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  *  Pause sound output
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  *  Resume sound output
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  *  Sound sub-process
00097  */
00098 
00099 void DigitalRenderer::sub_invoc(void)
00100 {
00101         // Get pointer to the DigitalRenderer object and call sub_func()
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         // Create signals for communication
00115         quit_sig = AllocSignal(-1);
00116         pause_sig = AllocSignal(-1);
00117         resume_sig = AllocSignal(-1);
00118         ahi_sig = AllocSignal(-1);
00119 
00120         // Open AHI
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         // Initialize callback hook
00131         sf_hook.h_Entry = sound_func;
00132 
00133         // Open audio control structure
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         // Prepare SampleInfos and load sounds (two sounds for double buffering)
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         // Set parameters
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         // Start audio output
00163         AHI_ControlAudio(ahi_ctrl, AHIC_Play, TRUE, TAG_DONE);
00164 
00165         // We are now ready for commands
00166         ready = TRUE;
00167         Signal(main_task, 1 << main_sig);
00168 
00169         // Accept and execute commands
00170         for (;;) {
00171                 ULONG sigs = Wait((1 << quit_sig) | (1 << pause_sig) | (1 << resume_sig) | (1 << ahi_sig));
00172 
00173                 // Quit sub-process
00174                 if (sigs & (1 << quit_sig))
00175                         goto quit;
00176 
00177                 // Pause sound output
00178                 if (sigs & (1 << pause_sig))
00179                         AHI_ControlAudio(ahi_ctrl, AHIC_Play, FALSE, TAG_DONE);
00180 
00181                 // Resume sound output
00182                 if (sigs & (1 << resume_sig))
00183                         AHI_ControlAudio(ahi_ctrl, AHIC_Play, TRUE, TAG_DONE);
00184 
00185                 // Calculate next buffer
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         // Initialization failed, wait for quit signal
00192         Wait(1 << quit_sig);
00193 
00194 quit:
00195         // Free everything
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         // Quit (synchronized with main task)
00217         Forbid();
00218         Signal(main_task, 1 << main_sig);
00219 }
00220 
00221 
00222 /*
00223  *  AHI sound callback, play next buffer and signal sub-process
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  *  Renderer for SID card
00239  */
00240 
00241 // Renderer class
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;        // SID card base pointer
00256 };
00257 
00258 // Constructor: Reset SID
00259 SIDCardRenderer::SIDCardRenderer()
00260 {
00261         sid_base = (UBYTE *)0xa00001;
00262         Reset();
00263 }
00264 
00265 // Destructor: Reset SID
00266 SIDCardRenderer::~SIDCardRenderer()
00267 {
00268         Reset();
00269 }
00270 
00271 // Reset SID
00272 void SIDCardRenderer::Reset(void)
00273 {
00274         WaitTOF();
00275         ciaa.ciapra |= CIAF_LED;
00276         WaitTOF();
00277         ciaa.ciapra &= ~CIAF_LED;
00278 }
00279 
00280 // Write to register
00281 void SIDCardRenderer::WriteRegister(uint16 adr, uint8 byte)
00282 {
00283         sid_base[adr << 1] = byte;
00284 }

Generated on Tue Feb 8 04:08:10 2005 for E32frodo by doxygen 1.3.3