PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
sdsq.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#ifdef _IOP
12#include "irx_imports.h"
13#else
14#include <stdint.h>
15typedef int8_t s8;
16typedef int16_t s16;
17typedef int32_t s32;
18typedef uint8_t u8;
19typedef uint16_t u16;
20typedef uint32_t u32;
21#endif
22#include <sdsq.h>
23
24#ifdef _IOP
25IRX_ID("Sound_Data_SQ", 2, 1);
26#endif
27// Based on the module from SCE SDK 3.1.0.
28
30{
31 unsigned int Creator;
32 unsigned int Type;
33 unsigned int chunkSize;
34 u16 reserved;
35 u8 versionMajor;
36 u8 versionMinor;
37};
40
41typedef struct sceSeqHeaderChunk_
42{
43 unsigned int Creator;
44 unsigned int Type;
45 unsigned int chunkSize;
46 unsigned int fileSize;
47 unsigned int songChunkAddr;
48 unsigned int midiChunkAddr;
49 unsigned int seSequenceChunkAddr;
50 unsigned int seSongChunkAddr;
52
53typedef struct sceSeqMidiChunk_
54{
55 unsigned int Creator;
56 unsigned int Type;
57 unsigned int chunkSize;
58 unsigned int maxMidiNumber;
59 unsigned int midiOffsetAddr[];
61
62typedef struct sceSeqSongChunk_
63{
64 unsigned int Creator;
65 unsigned int Type;
66 unsigned int chunkSize;
67 unsigned int maxSongNumber;
68 unsigned int songOffsetAddr[];
70
72{
73 unsigned int Creator;
74 unsigned int Type;
75 unsigned int chunkSize;
76 unsigned int maxSeSequenceSetNumber;
77 unsigned int tableOffset;
78 u8 seSequenceMasterVolume;
79 char seSequenceMasterPanpot;
80 u16 seSequenceMasterTimeScale;
81 unsigned int dmy0;
82 unsigned int dmy1;
83 unsigned int seSequenceSetOffsetAddr[];
85
87{
88 sceSeqVersionChunk *m_vers;
89 sceSeqHeaderChunk *m_sequ;
90 sceSeqMidiChunk *m_midi;
91 sceSeqSongChunk *m_song;
92};
93
94#ifdef _IOP
95extern struct irx_export_table _exp_sdsq;
96#endif
97
98static unsigned int do_get_vers_sequ_chunk(sceSeqVersionChunk *indata, struct sdsq_info *dinfo)
99{
100 dinfo->m_vers = 0;
101 dinfo->m_sequ = 0;
102 dinfo->m_midi = 0;
103 dinfo->m_song = 0;
104 dinfo->m_vers = indata;
105 if ( indata->Creator != 0x53434549 || indata->Type != 0x56657273 )
106 {
107 dinfo->m_vers = 0;
108 return 0x8104000E;
109 }
110 if ( (indata->chunkSize & 0x80000000) )
111 {
112 dinfo->m_vers = 0;
113 return 0x8104002F;
114 }
115 dinfo->m_sequ = (sceSeqHeaderChunk *)((char *)indata + indata->chunkSize);
116 if ( dinfo->m_sequ->Creator != 0x53434549 || dinfo->m_sequ->Type != 0x53657175 )
117 {
118 dinfo->m_vers = 0;
119 dinfo->m_sequ = 0;
120 return 0x8104002F;
121 }
122 return 0;
123}
124
125static unsigned int do_get_midi_chunk(void *indata, struct sdsq_info *dinfo)
126{
127 if ( dinfo->m_sequ->midiChunkAddr == 0xFFFFFFFF )
128 return 0x81049024;
129 if ( (dinfo->m_sequ->midiChunkAddr & 0x80000000) )
130 return 0x8104002F;
131 dinfo->m_midi = (sceSeqMidiChunk *)((char *)indata + dinfo->m_sequ->midiChunkAddr);
132 if ( dinfo->m_midi->Creator != 0x53434549 || dinfo->m_midi->Type != 0x4D696469 )
133 {
134 dinfo->m_midi = 0;
135 return 0x8104002F;
136 }
137 return 0;
138}
139
140static unsigned int do_get_song_chunk(void *indata, struct sdsq_info *dinfo)
141{
142 if ( dinfo->m_sequ->songChunkAddr == 0xFFFFFFFF )
143 return 0x81049025;
144 if ( (dinfo->m_sequ->songChunkAddr & 0x80000000) )
145 return 0x8104002F;
146 dinfo->m_song = (sceSeqSongChunk *)((char *)indata + dinfo->m_sequ->songChunkAddr);
147 if ( dinfo->m_song->Creator != 0x53434549 || dinfo->m_song->Type != 0x536F6E67 )
148 {
149 dinfo->m_song = 0;
150 return 0x8104002F;
151 }
152 return 0;
153}
154
155static unsigned int do_get_midi_data_block(void *indata, unsigned int idx, sceSeqMidiDataBlock **datablk)
156{
157 unsigned int result;
158 struct sdsq_info dinfo;
159
160 result = do_get_vers_sequ_chunk((sceSeqVersionChunk *)indata, &dinfo);
161 if ( result )
162 return result;
163 result = do_get_midi_chunk(indata, &dinfo);
164 if ( result )
165 return result;
166 if ( dinfo.m_midi->maxMidiNumber < idx )
167 return 0x81049026;
168 if ( dinfo.m_midi->midiOffsetAddr[idx] == 0xFFFFFFFF )
169 return 0x81049026;
170 *datablk = (sceSeqMidiDataBlock *)((char *)dinfo.m_midi + dinfo.m_midi->midiOffsetAddr[idx]);
171 return 0;
172}
173
174int sceSdSqGetMaxMidiNumber(void *addr)
175{
176 int result;
177 struct sdsq_info dinfo;
178
179 result = (int)do_get_vers_sequ_chunk((sceSeqVersionChunk *)addr, &dinfo);
180 if ( result )
181 return result;
182 result = (int)do_get_midi_chunk(addr, &dinfo);
183 if ( result )
184 return result;
185 return (int)dinfo.m_midi->maxMidiNumber;
186}
187
188int sceSdSqGetMaxSongNumber(void *addr)
189{
190 int result;
191 struct sdsq_info dinfo;
192
193 result = (int)do_get_vers_sequ_chunk((sceSeqVersionChunk *)addr, &dinfo);
194 if ( result )
195 return result;
196 result = (int)do_get_song_chunk(addr, &dinfo);
197 if ( result )
198 return result;
199 return (int)dinfo.m_song->maxSongNumber;
200}
201
202int sceSdSqInitMidiData(void *addr, u32 midiNumber, SceSdSqMidiData *midiData)
203{
204 int result;
205 struct sdsq_info dinfo;
206
207 result = (int)do_get_vers_sequ_chunk((sceSeqVersionChunk *)addr, &dinfo);
208 if ( result )
209 return result;
210 result = (int)do_get_midi_chunk(addr, &dinfo);
211 if ( result )
212 return result;
213 if ( dinfo.m_midi->maxMidiNumber < midiNumber )
214 return (int)0x81049026;
215 if ( dinfo.m_midi->midiOffsetAddr[midiNumber] == 0xFFFFFFFF )
216 return (int)0x81049026;
217 midiData->readStatus = 0;
218 midiData->midiNumber = midiNumber;
219 midiData->midiData = (sceSeqMidiDataBlock *)((char *)dinfo.m_midi + dinfo.m_midi->midiOffsetAddr[midiNumber]);
220 midiData->offset = 0;
221 midiData->nextOffset = midiData->midiData->sequenceDataOffset;
222 midiData->division = midiData->midiData->Division;
223 midiData->compMode = (midiData->nextOffset == 6) ? 0 : 1;
224 midiData->compTableSize = (midiData->nextOffset == 6) ? 0 : midiData->midiData->compBlock[0].compTableSize;
225 midiData->deltaTime = 0;
226 midiData->lastStatus = 0;
227 midiData->reserve[0] = 0;
228 midiData->reserve[1] = 0;
229 midiData->reserve[2] = 0;
230 midiData->messageLength = 1;
231 midiData->message[0] = 0;
232 midiData->message[1] = 0;
233 midiData->message[2] = 0;
234 midiData->message[3] = 0;
235 midiData->message[4] = 0;
236 midiData->message[5] = 0;
237 midiData->message[6] = 0;
238 midiData->message[7] = 0;
239 midiData->originalMessageLength = 1;
240 midiData->originalMessage[0] = 0;
241 midiData->originalMessage[1] = 0;
242 midiData->originalMessage[2] = 0;
243 midiData->originalMessage[3] = 0;
244 midiData->originalMessage[4] = 0;
245 midiData->originalMessage[5] = 0;
246 midiData->originalMessage[6] = 0;
247 midiData->originalMessage[7] = 0;
248 midiData->originalMessage[8] = 0;
249 midiData->originalMessage[9] = 0;
250 midiData->originalMessage[10] = 0;
251 midiData->originalMessage[11] = 0;
252 return 0;
253}
254
255int sceSdSqReadMidiData(SceSdSqMidiData *midiData)
256{
257 char niceflag;
258 u8 cur_message;
259 sceSeqMidiDataBlock *midiData_1;
260 u32 nextOffset;
261 u8 lastStatus;
262 u8 *midiData_offs;
263 u32 midiData_curval1_1;
264 u8 midiData_curval2;
265 const u8 *midiData_offs_plusone;
266 u32 nextMessageLength;
267 u8 *currofssplusone;
268 u8 *someaddoffsone;
269 int endflg;
270
271 endflg = 3;
272 niceflag = 0;
273 if ( midiData->readStatus )
274 return (int)0x81048001;
275 if ( !midiData->originalMessageLength )
276 {
277 midiData->readStatus = 2;
278 return (int)0x8104002F;
279 }
280 cur_message = midiData->originalMessage[midiData->originalMessageLength - 1];
281 midiData_1 = midiData->midiData;
282 nextOffset = midiData->nextOffset;
283 lastStatus = midiData->lastStatus;
284 midiData->originalMessageLength = 0;
285 midiData->messageLength = 0;
286 midiData_offs = (u8 *)midiData_1 + nextOffset;
287 midiData->offset = nextOffset;
288 midiData_curval1_1 = 0;
289 if ( !(cur_message & 0x80) || lastStatus == 255 )
290 {
291 u8 midiData_curval1;
292
293 midiData_curval1 = *midiData_offs;
294 midiData->originalMessage[midiData->originalMessageLength] = *midiData_offs;
295 midiData->originalMessageLength += 1;
296 midiData_offs += 1;
297 midiData_curval1_1 = midiData_curval1 & 0x7F;
298 while ( midiData_curval1 & 0x80 )
299 {
300 midiData_curval1 = *midiData_offs;
301 midiData_offs += 1;
302 midiData->originalMessage[midiData->originalMessageLength] = midiData_curval1;
303 midiData->originalMessageLength += 1;
304 midiData_curval1_1 = (midiData_curval1_1 << 7) + (midiData_curval1 & 0x7F);
305 }
306 }
307 midiData->deltaTime = midiData_curval1_1;
308 midiData_curval2 = *midiData_offs;
309 midiData->originalMessage[midiData->originalMessageLength] = *midiData_offs;
310 if ( (midiData_curval2 & 0x80) )
311 {
312 midiData_offs += 1;
313 midiData->originalMessageLength += 1;
314 }
315 else
316 {
317 midiData_curval2 = lastStatus;
318 }
319 midiData->message[0] = midiData_curval2;
320 midiData->lastStatus = midiData_curval2;
321 midiData_offs_plusone = 0;
322 switch ( midiData_curval2 & 0xF0 )
323 {
324 case 0x90:
325 case 0xB0:
326 case 0xE0:
327 {
328 endflg = 4;
329 break;
330 }
331 case 0x80:
332 case 0xC0:
333 case 0xD0:
334 {
335 break;
336 }
337 case 0xA0:
338 {
339 if ( !midiData->compMode )
340 {
341 endflg = 4;
342 }
343 else
344 {
345 int someoffsx;
346
347 midiData->originalMessage[midiData->originalMessageLength] = *midiData_offs;
348 midiData->message[1] = midiData->originalMessage[midiData->originalMessageLength];
349 midiData->message[2] = 8 * (midiData->originalMessage[midiData->originalMessageLength] & 0xF);
350 midiData->originalMessageLength = midiData->originalMessageLength + 1;
351 someoffsx = 2 * ((midiData->message[0] & 0xF) | (midiData->message[1] & 0x70));
352 midiData->message[1] = midiData->message[1] & 0x7F;
353 midiData_offs_plusone = midiData_offs + 1;
354 midiData->message[0] = *((u8 *)&midiData->midiData->compBlock[1].compOption + someoffsx);
355 midiData->message[1] = *((u8 *)&midiData->midiData->compBlock[1].compOption + someoffsx + 1);
356 midiData->messageLength = 3;
357 endflg = 1;
358 }
359 break;
360 }
361 case 0xF0:
362 {
363 int i;
364 u8 midiData_curval7;
365 int msg2ew;
366
367 if ( midiData_curval2 != 255 )
368 {
369 midiData->readStatus = 2;
370 return (int)0x8104002F;
371 }
372 midiData->messageLength = 1;
373 midiData->originalMessage[midiData->originalMessageLength] = *midiData_offs;
374 midiData->message[1] = midiData->originalMessage[midiData->originalMessageLength];
375 midiData->messageLength = midiData->messageLength + 1;
376 midiData->originalMessageLength = midiData->originalMessageLength + 1;
377 someaddoffsone = midiData_offs + 1;
378 midiData_curval7 = *someaddoffsone;
379 midiData->originalMessage[midiData->originalMessageLength] = *someaddoffsone;
380 midiData->message[2] = midiData->originalMessage[midiData->originalMessageLength];
381 midiData->messageLength = midiData->messageLength + 1;
382 midiData_offs_plusone = someaddoffsone + 1;
383 midiData->originalMessageLength += 1;
384 msg2ew = midiData_curval7;
385 for ( i = 1; msg2ew >= i; i += 1 )
386 {
387 midiData->originalMessage[midiData->originalMessageLength] = *midiData_offs_plusone;
388 midiData_offs_plusone += 1;
389 midiData->message[i + 2] = midiData->originalMessage[midiData->originalMessageLength];
390 msg2ew = midiData->message[2];
391 midiData->messageLength += 1;
392 midiData->originalMessageLength += 1;
393 }
394 niceflag = 1;
395 if ( midiData->message[0] == 0xFF && midiData->message[1] == 0x2F && midiData->message[2] == 0x00 )
396 midiData->readStatus = 1;
397 endflg = 1;
398 break;
399 }
400 default:
401 {
402 midiData->readStatus = 2;
403 return (int)0x8104002F;
404 }
405 }
406 nextMessageLength = 0;
407 if ( endflg >= 4 )
408 {
409 midiData->originalMessage[midiData->originalMessageLength] = *midiData_offs;
410 midiData->message[1] = *midiData_offs;
411 midiData->originalMessageLength = midiData->originalMessageLength + 1;
412 currofssplusone = midiData_offs + 1;
413 midiData->originalMessage[midiData->originalMessageLength] = *currofssplusone;
414 midiData_offs_plusone = currofssplusone + 1;
415 midiData->message[2] = midiData->originalMessage[midiData->originalMessageLength];
416 nextMessageLength = 3;
417 endflg = 2;
418 }
419 if ( endflg >= 3 )
420 {
421 midiData->originalMessage[midiData->originalMessageLength] = *midiData_offs;
422 midiData_offs_plusone = midiData_offs + 1;
423 midiData->message[1] = midiData->originalMessage[midiData->originalMessageLength];
424 nextMessageLength = 2;
425 }
426 if ( endflg >= 2 )
427 {
428 midiData->messageLength = nextMessageLength;
429 midiData->originalMessageLength = midiData->originalMessageLength + 1;
430 }
431 if ( !niceflag )
432 midiData->message[midiData->messageLength - 1] &= ~0x80u;
433 midiData->nextOffset = (u32)(midiData_offs_plusone - (u8 *)midiData->midiData);
434 return 0;
435}
436
437int sceSdSqInitSongData(void *addr, u32 songNumber, SceSdSqSongData *songData)
438{
439 int result;
440 struct sdsq_info dinfo;
441
442 result = (int)do_get_vers_sequ_chunk((sceSeqVersionChunk *)addr, &dinfo);
443 if ( result )
444 return result;
445 result = (int)do_get_song_chunk(addr, &dinfo);
446 if ( result )
447 return result;
448 if ( dinfo.m_song->maxSongNumber < songNumber )
449 return (int)0x81049027;
450 if ( dinfo.m_song->songOffsetAddr[songNumber] == 0xFFFFFFFF )
451 return (int)0x81049027;
452 songData->readStatus = 0;
453 songData->songNumber = songNumber;
454 songData->topAddr = (char *)(dinfo.m_song) + dinfo.m_song->songOffsetAddr[songNumber];
455 songData->offset = 0;
456 songData->nextOffset = 0;
457 songData->message[0] = 0;
458 songData->message[1] = 0;
459 songData->message[2] = 0;
460 songData->reserve = 0;
461 return 0;
462}
463
464int sceSdSqReadSongData(SceSdSqSongData *songData)
465{
466 const u8 *curOffset;
467
468 if ( songData->readStatus )
469 return (int)0x81048001;
470 curOffset = (u8 *)songData->topAddr + songData->nextOffset;
471 if ( (*curOffset & 0xF0) != 160 || (curOffset[1] & 0x80u) )
472 {
473 songData->readStatus = 2;
474 return (int)0x8104002F;
475 }
476 songData->offset = songData->nextOffset;
477 songData->message[0] = *curOffset;
478 songData->message[1] = curOffset[1];
479 songData->message[2] = curOffset[2];
480 if ( songData->message[0] == 0xA0 && songData->message[1] == 0x7F && songData->message[2] == 0x7F )
481 songData->readStatus = 1;
482 else
483 songData->nextOffset += 3;
484 return 0;
485}
486
487int sceSdSqGetMaxCompTableIndex(void *addr, u32 midiNumber)
488{
489 int result;
491
492 result = (int)do_get_midi_data_block(addr, midiNumber, &dblk);
493 if ( result )
494 return result;
495 if ( dblk->sequenceDataOffset == 6 )
496 return (int)0x81049028;
497 return dblk->compBlock[0].compTableSize >> 1;
498}
499
500int sceSdSqGetCompTableOffset(void *addr, u32 midiNumber, u32 *offset)
501{
502 int result;
504
505 result = (int)do_get_midi_data_block(addr, midiNumber, &dblk);
506 if ( result )
507 return result;
508 if ( dblk->sequenceDataOffset == 6 )
509 return (int)0x81049028;
510 *offset = (u32)((char *)dblk - (char *)addr) - 10;
511 return 0;
512}
513
514int sceSdSqGetCompTableDataByIndex(void *addr, u32 midiNumber, u32 compTableIndex, SceSdSqCompTableData *data)
515{
516 int result;
518
519 result = (int)do_get_midi_data_block(addr, midiNumber, &dblk);
520 if ( result )
521 return result;
522 if ( dblk->sequenceDataOffset == 6 )
523 return (int)0x81049028;
524 if ( dblk->compBlock[0].compTableSize >> 1 < compTableIndex )
525 return (int)0x81049029;
526 data->status = *((u8 *)&dblk->compBlock[1].compOption + (compTableIndex << 1));
527 data->data = *((u8 *)&dblk->compBlock[1].compOption + (compTableIndex << 1) + 1);
528 return 0;
529}
530
531int sceSdSqGetNoteOnEventByPolyKeyPress(
532 void *addr, u32 midiNumber, const SceSdSqPolyKeyData *pData, SceSdSqCompTableNoteOnEvent *kData)
533{
534 u32 compTableIndex;
535 int result;
537
538 if ( (pData->status & 0xF0) != 160 )
539 return (int)0x8104902A;
540 compTableIndex = (pData->status & 0xF) + (pData->data & 0xF0);
541 if ( compTableIndex >= 0x80 )
542 return (int)0x8104902A;
543 result = sceSdSqGetCompTableDataByIndex(addr, midiNumber, compTableIndex, &data);
544 if ( result )
545 return result;
546 kData->status = data.status;
547 kData->note = data.data;
548 kData->velocity = 8 * (pData->data & 0xF);
549 return 0;
550}
551
552int sceSdSqCopyMidiData(SceSdSqMidiData *to, const SceSdSqMidiData *from)
553{
554 // The following structure copy was inlined
555 *to = *from;
556 return 0;
557}
558
559int sceSdSqCopySongData(SceSdSqSongData *to, const SceSdSqSongData *from)
560{
561 // The following structure copy was inlined
562 *to = *from;
563 return 0;
564}
565
566#ifdef _IOP
567int _start(int ac, char *av[], void *startaddr, ModuleInfo_t *mi)
568{
569 int regres;
570 int state;
571
572 (void)av;
573 (void)startaddr;
574 if ( ac < 0 )
575 {
576 CpuSuspendIntr(&state);
577 regres = ReleaseLibraryEntries(&_exp_sdsq);
578 CpuResumeIntr(state);
579 return (!regres) ? MODULE_NO_RESIDENT_END : MODULE_REMOVABLE_END;
580 }
581 CpuSuspendIntr(&state);
582 regres = RegisterLibraryEntries(&_exp_sdsq);
583 CpuResumeIntr(state);
584 if ( regres )
585 return MODULE_NO_RESIDENT_END;
586#if 0
587 return MODULE_REMOVABLE_END;
588#else
589 if ( mi && ((mi->newflags & 2) != 0) )
590 mi->newflags |= 0x10;
591 return MODULE_RESIDENT_END;
592#endif
593}
594#endif
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205
u16 newflags
Definition loadcore.h:36