summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/modplug/load_okt.cpp
authorllornkcor <llornkcor>2002-07-20 22:07:31 (UTC)
committer llornkcor <llornkcor>2002-07-20 22:07:31 (UTC)
commit2342d48be31847e7ead9d1cc682452e8f0122351 (patch) (side-by-side diff)
tree8329bb94e9d429c905a0ef6b881cf1c0f775bf14 /core/multimedia/opieplayer/modplug/load_okt.cpp
parent0f24c1fb86d3bb58d8696358b824c0e01752b10d (diff)
downloadopie-2342d48be31847e7ead9d1cc682452e8f0122351.zip
opie-2342d48be31847e7ead9d1cc682452e8f0122351.tar.gz
opie-2342d48be31847e7ead9d1cc682452e8f0122351.tar.bz2
initial commit of modplugin
Diffstat (limited to 'core/multimedia/opieplayer/modplug/load_okt.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/modplug/load_okt.cpp200
1 files changed, 200 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/modplug/load_okt.cpp b/core/multimedia/opieplayer/modplug/load_okt.cpp
new file mode 100644
index 0000000..4030bbd
--- a/dev/null
+++ b/core/multimedia/opieplayer/modplug/load_okt.cpp
@@ -0,0 +1,200 @@
+/*
+ * This program is free software; you can redistribute it and modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the license or (at your
+ * option) any later version.
+ *
+ * Authors: Olivier Lapicque <olivierl@jps.net>,
+ * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
+*/
+
+//////////////////////////////////////////////
+// Oktalyzer (OKT) module loader //
+//////////////////////////////////////////////
+#include "stdafx.h"
+#include "sndfile.h"
+
+//#pragma warning(disable:4244)
+
+typedef struct OKTFILEHEADER
+{
+ DWORD okta; // "OKTA"
+ DWORD song; // "SONG"
+ DWORD cmod; // "CMOD"
+ DWORD fixed8;
+ BYTE chnsetup[8];
+ DWORD samp; // "SAMP"
+ DWORD samplen;
+} Q_PACKED OKTFILEHEADER;
+
+
+typedef struct OKTSAMPLE
+{
+ CHAR name[20];
+ DWORD length;
+ WORD loopstart;
+ WORD looplen;
+ BYTE pad1;
+ BYTE volume;
+ BYTE pad2;
+ BYTE pad3;
+} Q_PACKED OKTSAMPLE;
+
+
+BOOL CSoundFile::ReadOKT(const BYTE *lpStream, DWORD dwMemLength)
+//---------------------------------------------------------------
+{
+ OKTFILEHEADER *pfh = (OKTFILEHEADER *)lpStream;
+ DWORD dwMemPos = sizeof(OKTFILEHEADER);
+ UINT nsamples = 0, npatterns = 0, norders = 0;
+
+ if ((!lpStream) || (dwMemLength < 1024)) return FALSE;
+ if ((pfh->okta != 0x41544B4F) || (pfh->song != 0x474E4F53)
+ || (pfh->cmod != 0x444F4D43) || (pfh->chnsetup[0]) || (pfh->chnsetup[2])
+ || (pfh->chnsetup[4]) || (pfh->chnsetup[6]) || (pfh->fixed8 != 0x08000000)
+ || (pfh->samp != 0x504D4153)) return FALSE;
+ m_nType = MOD_TYPE_OKT;
+ m_nChannels = 4 + pfh->chnsetup[1] + pfh->chnsetup[3] + pfh->chnsetup[5] + pfh->chnsetup[7];
+ if (m_nChannels > MAX_CHANNELS) m_nChannels = MAX_CHANNELS;
+ nsamples = bswapBE32(pfh->samplen) >> 5;
+ m_nSamples = nsamples;
+ if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1;
+ // Reading samples
+ for (UINT smp=1; smp <= nsamples; smp++)
+ {
+ if (dwMemPos >= dwMemLength) return TRUE;
+ if (smp < MAX_SAMPLES)
+ {
+ OKTSAMPLE *psmp = (OKTSAMPLE *)(lpStream + dwMemPos);
+ MODINSTRUMENT *pins = &Ins[smp];
+
+ memcpy(m_szNames[smp], psmp->name, 20);
+ pins->uFlags = 0;
+ pins->nLength = bswapBE32(psmp->length) & ~1;
+ pins->nLoopStart = bswapBE16(psmp->loopstart);
+ pins->nLoopEnd = pins->nLoopStart + bswapBE16(psmp->looplen);
+ if (pins->nLoopStart + 2 < pins->nLoopEnd) pins->uFlags |= CHN_LOOP;
+ pins->nGlobalVol = 64;
+ pins->nVolume = psmp->volume << 2;
+ pins->nC4Speed = 8363;
+ }
+ dwMemPos += sizeof(OKTSAMPLE);
+ }
+ // SPEE
+ if (dwMemPos >= dwMemLength) return TRUE;
+ if (*((DWORD *)(lpStream + dwMemPos)) == 0x45455053)
+ {
+ m_nDefaultSpeed = lpStream[dwMemPos+9];
+ dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
+ }
+ // SLEN
+ if (dwMemPos >= dwMemLength) return TRUE;
+ if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C53)
+ {
+ npatterns = lpStream[dwMemPos+9];
+ dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
+ }
+ // PLEN
+ if (dwMemPos >= dwMemLength) return TRUE;
+ if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C50)
+ {
+ norders = lpStream[dwMemPos+9];
+ dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
+ }
+ // PATT
+ if (dwMemPos >= dwMemLength) return TRUE;
+ if (*((DWORD *)(lpStream + dwMemPos)) == 0x54544150)
+ {
+ UINT orderlen = norders;
+ if (orderlen >= MAX_ORDERS) orderlen = MAX_ORDERS-1;
+ for (UINT i=0; i<orderlen; i++) Order[i] = lpStream[dwMemPos+10+i];
+ for (UINT j=orderlen; j>1; j--) { if (Order[j-1]) break; Order[j-1] = 0xFF; }
+ dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
+ }
+ // PBOD
+ UINT npat = 0;
+ while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4250))
+ {
+ DWORD dwPos = dwMemPos + 10;
+ UINT rows = lpStream[dwMemPos+9];
+ if (!rows) rows = 64;
+ if (npat < MAX_PATTERNS)
+ {
+ if ((Patterns[npat] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE;
+ MODCOMMAND *m = Patterns[npat];
+ PatternSize[npat] = rows;
+ UINT imax = m_nChannels*rows;
+ for (UINT i=0; i<imax; i++, m++, dwPos+=4)
+ {
+ if (dwPos+4 > dwMemLength) break;
+ const BYTE *p = lpStream+dwPos;
+ UINT note = p[0];
+ if (note)
+ {
+ m->note = note + 48;
+ m->instr = p[1] + 1;
+ }
+ UINT command = p[2];
+ UINT param = p[3];
+ m->param = param;
+ switch(command)
+ {
+ // 0: no effect
+ case 0:
+ break;
+ // 1: Portamento Up
+ case 1:
+ case 17:
+ case 30:
+ if (param) m->command = CMD_PORTAMENTOUP;
+ break;
+ // 2: Portamento Down
+ case 2:
+ case 13:
+ case 21:
+ if (param) m->command = CMD_PORTAMENTODOWN;
+ break;
+ // 10: Arpeggio
+ case 10:
+ case 11:
+ case 12:
+ m->command = CMD_ARPEGGIO;
+ break;
+ // 15: Filter
+ case 15:
+ m->command = CMD_MODCMDEX;
+ m->param = param & 0x0F;
+ break;
+ // 25: Position Jump
+ case 25:
+ m->command = CMD_POSITIONJUMP;
+ break;
+ // 28: Set Speed
+ case 28:
+ m->command = CMD_SPEED;
+ break;
+ // 31: Volume Control
+ case 31:
+ if (param <= 0x40) m->command = CMD_VOLUME; else
+ if (param <= 0x50) { m->command = CMD_VOLUMESLIDE; m->param &= 0x0F; if (!m->param) m->param = 0x0F; } else
+ if (param <= 0x60) { m->command = CMD_VOLUMESLIDE; m->param = (param & 0x0F) << 4; if (!m->param) m->param = 0xF0; } else
+ if (param <= 0x70) { m->command = CMD_MODCMDEX; m->param = 0xB0 | (param & 0x0F); if (!(param & 0x0F)) m->param = 0xBF; } else
+ if (param <= 0x80) { m->command = CMD_MODCMDEX; m->param = 0xA0 | (param & 0x0F); if (!(param & 0x0F)) m->param = 0xAF; }
+ break;
+ }
+ }
+ }
+ npat++;
+ dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
+ }
+ // SBOD
+ UINT nsmp = 1;
+ while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4253))
+ {
+ if (nsmp < MAX_SAMPLES) ReadSample(&Ins[nsmp], RS_PCM8S, (LPSTR)(lpStream+dwMemPos+8), dwMemLength-dwMemPos-8);
+ dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
+ nsmp++;
+ }
+ return TRUE;
+}
+