summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/cRSID/libcRSID.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/cRSID/libcRSID.c')
-rw-r--r--lib/rbcodec/codecs/cRSID/libcRSID.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/cRSID/libcRSID.c b/lib/rbcodec/codecs/cRSID/libcRSID.c
new file mode 100644
index 0000000000..f7ef713e12
--- /dev/null
+++ b/lib/rbcodec/codecs/cRSID/libcRSID.c
@@ -0,0 +1,134 @@
1// cRSID lightweight (integer-only) RealSID library (with API-calls) by Hermit (Mihaly Horvath), Year 2022
2// License: WTF - do what the fuck you want with the code, but please mention me as the original author
3
4#include <stdlib.h>
5//#include <stdint.h>
6#ifdef CRSID_PLATFORM_PC
7 #include <stdio.h>
8#endif
9
10#include "libcRSID.h"
11
12#include "C64/C64.c"
13#include "host/file.c"
14#include "host/audio.c"
15
16
17cRSID_C64instance* cRSID_init (unsigned short samplerate, unsigned short buflen) {
18 static cRSID_C64instance* C64 = &cRSID_C64;
19
20 C64 = cRSID_createC64 (C64, samplerate);
21#ifdef CRSID_PLATFORM_PC
22 if ( cRSID_initSound (C64, samplerate,buflen) == NULL) return NULL;
23#else
24 if (buflen) return C64; //this is here just to eliminate unused 'buflen' variable warning
25#endif
26
27 return C64;
28}
29
30
31void cRSID_initSIDtune (cRSID_C64instance* C64, cRSID_SIDheader* SIDheader, char subtune) { //subtune: 1..255
32 static const unsigned char PowersOf2[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
33 unsigned int InitTimeout=10000000; //allowed instructions, value should be selected to allow for long-running memory-copiers in init-routines (e.g. Synth Sample)
34
35 if (subtune==0) subtune = 1;
36 else if (subtune > SIDheader->SubtuneAmount) subtune = SIDheader->SubtuneAmount;
37 C64->SubTune = subtune;
38
39 cRSID_setC64(C64); cRSID_initC64(C64); //cRSID_writeMemC64(C64,0xD418,0xF); //set C64 hardware and init (reset) it
40
41 //determine init-address:
42 C64->InitAddress = ((SIDheader->InitAddressH)<<8) + (SIDheader->InitAddressL); //get info from BASIC-startupcode for some tunes
43 if (C64->RAMbank[1] == 0x37) { //are there SIDs with routine under IO area? some PSIDs don't set bank-registers themselves
44 if ( (0xA000 <= C64->InitAddress && C64->InitAddress < 0xC000)
45 || (C64->LoadAddress < 0xC000 && C64->EndAddress >= 0xA000) ) C64->RAMbank[1] = 0x36;
46 else if (C64->InitAddress >= 0xE000 || C64->EndAddress >=0xE000) C64->RAMbank[1] = 0x35;
47 }
48 cRSID_initCPU( &C64->CPU, C64->InitAddress ); //prepare init-routine call
49 C64->CPU.A = subtune - 1;
50
51 if (!C64->RealSIDmode) {
52 //call init-routine:
53 for (InitTimeout=10000000; InitTimeout>0; InitTimeout--) { if ( cRSID_emulateCPU()>=0xFE ) break; } //give error when timed out?
54 }
55
56 //determine timing-source, if CIA, replace FrameCycles previouisly set to VIC-timing
57 if (subtune>32) C64->TimerSource = C64->SIDheader->SubtuneTimeSources[0] & 0x80; //subtunes above 32 should use subtune32's timing
58 else C64->TimerSource = C64->SIDheader->SubtuneTimeSources[(32-subtune)>>3] & PowersOf2[(subtune-1)&7];
59 if (C64->TimerSource || C64->IObankWR[0xDC05]!=0x40 || C64->IObankWR[0xDC04]!=0x24) { //CIA1-timing (probably multispeed tune)
60 C64->FrameCycles = ( ( C64->IObankWR[0xDC04] + (C64->IObankWR[0xDC05]<<8) ) ); //<< 4) / C64->ClockRatio;
61 C64->TimerSource = 1; //if init-routine changed DC04 or DC05, assume CIA-timing
62 }
63
64 //determine playaddress:
65 C64->PlayAddress = (SIDheader->PlayAddressH<<8) + SIDheader->PlayAddressL;
66 if (C64->PlayAddress) { //normal play-address called with JSR
67 if (C64->RAMbank[1] == 0x37) { //are there SIDs with routine under IO area?
68 if (0xA000 <= C64->PlayAddress && C64->PlayAddress < 0xC000) C64->RAMbank[1] = 0x36;
69 }
70 else if (C64->PlayAddress >= 0xE000) C64->RAMbank[1] = 0x35; //player under KERNAL (e.g. Crystal Kingdom Dizzy)
71 }
72 else { //IRQ-playaddress for multispeed-tunes set by init-routine (some tunes turn off KERNAL ROM but doesn't set IRQ-vector!)
73 C64->PlayAddress = (C64->RAMbank[1] & 3) < 2 ? cRSID_readMemC64(C64,0xFFFE) + (cRSID_readMemC64(C64,0xFFFF)<<8) //for PSID
74 : cRSID_readMemC64(C64,0x314) + (cRSID_readMemC64(C64,0x315)<<8);
75 if (C64->PlayAddress==0) { //if 0, still try with RSID-mode fallback
76 cRSID_initCPU( &C64->CPU, C64->PlayAddress ); //point CPU to play-routine
77 C64->Finished=1; C64->Returned=1; return;
78 }
79 }
80
81 if (!C64->RealSIDmode) { //prepare (PSID) play-routine playback:
82 cRSID_initCPU( &C64->CPU, C64->PlayAddress ); //point CPU to play-routine
83 C64->FrameCycleCnt=0; C64->Finished=1; C64->SampleCycleCnt=0; //C64->CIAisSet=0;
84 }
85 else { C64->Finished=0; C64->Returned=0; }
86
87}
88
89
90#ifdef CRSID_PLATFORM_PC
91
92
93char cRSID_playSIDfile(cRSID_C64instance* C64, char* filename, char subtune) {
94 static cRSID_SIDheader* SIDheader;
95
96 SIDheader = cRSID_loadSIDtune(C64,filename);
97 if (SIDheader==NULL) return CRSID_ERROR_LOAD;
98
99 cRSID_initSIDtune (C64 , SIDheader , subtune);
100 cRSID_playSIDtune ();
101
102 return CRSID_STATUS_OK;
103}
104
105
106cRSID_SIDheader* cRSID_loadSIDtune(cRSID_C64instance* C64, char* filename) {
107 enum SIDspecs { CRSID_FILESIZE_MAX = 100000 };
108 int FileSize;
109 static unsigned char SIDfileData [CRSID_FILESIZE_MAX]; //use memset?
110
111 FileSize = cRSID_loadSIDfile( SIDfileData, filename, CRSID_FILESIZE_MAX);
112 if ( FileSize == CRSID_ERROR_LOAD ) return NULL;
113
114 return cRSID_processSIDfile ( C64, SIDfileData, FileSize );
115}
116
117
118void cRSID_close() {
119 cRSID_closeSound();
120}
121
122
123void cRSID_playSIDtune (void) {
124 cRSID_startSound();
125}
126
127
128void cRSID_pauseSIDtune (void) {
129 cRSID_stopSound();
130}
131
132
133#endif
134