00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00013 #include "stdafx.h"
00014 #include "sndfile.h"
00015
00016
00017
00018 #pragma pack(1)
00019
00020 typedef struct AMSFILEHEADER
00021 {
00022 char szHeader[7];
00023 BYTE verlo, verhi;
00024 BYTE chncfg;
00025 BYTE samples;
00026 WORD patterns;
00027 WORD orders;
00028 BYTE vmidi;
00029 WORD extra;
00030 } Q_PACKED AMSFILEHEADER;
00031
00032 typedef struct AMSSAMPLEHEADER
00033 {
00034 DWORD length;
00035 DWORD loopstart;
00036 DWORD loopend;
00037 BYTE finetune_and_pan;
00038 WORD samplerate;
00039 BYTE volume;
00040 BYTE infobyte;
00041 } Q_PACKED AMSSAMPLEHEADER;
00042
00043
00044 #pragma pack()
00045
00046
00047
00048 BOOL CSoundFile::ReadAMS(LPCBYTE lpStream, DWORD dwMemLength)
00049
00050 {
00051 BYTE pkinf[MAX_SAMPLES];
00052 AMSFILEHEADER *pfh = (AMSFILEHEADER *)lpStream;
00053 DWORD dwMemPos;
00054 UINT tmp, tmp2;
00055
00056 if ((!lpStream) || (dwMemLength < 1024)) return FALSE;
00057 if ((pfh->verhi != 0x01) || (strncmp(pfh->szHeader, "Extreme", 7))
00058 || (!pfh->patterns) || (!pfh->orders) || (!pfh->samples) || (pfh->samples > MAX_SAMPLES)
00059 || (pfh->patterns > MAX_PATTERNS) || (pfh->orders > MAX_ORDERS))
00060 {
00061 return ReadAMS2(lpStream, dwMemLength);
00062 }
00063 dwMemPos = sizeof(AMSFILEHEADER) + pfh->extra;
00064 if (dwMemPos + pfh->samples * sizeof(AMSSAMPLEHEADER) + 256 >= dwMemLength) return FALSE;
00065 m_nType = MOD_TYPE_AMS;
00066 m_nInstruments = 0;
00067 m_nChannels = (pfh->chncfg & 0x1F) + 1;
00068 m_nSamples = pfh->samples;
00069 for (UINT nSmp=1; nSmp<=m_nSamples; nSmp++, dwMemPos += sizeof(AMSSAMPLEHEADER))
00070 {
00071 AMSSAMPLEHEADER *psh = (AMSSAMPLEHEADER *)(lpStream + dwMemPos);
00072 MODINSTRUMENT *pins = &Ins[nSmp];
00073 pins->nLength = psh->length;
00074 pins->nLoopStart = psh->loopstart;
00075 pins->nLoopEnd = psh->loopend;
00076 pins->nGlobalVol = 64;
00077 pins->nVolume = psh->volume << 1;
00078 pins->nC4Speed = psh->samplerate;
00079 pins->nPan = (psh->finetune_and_pan & 0xF0);
00080 if (pins->nPan < 0x80) pins->nPan += 0x10;
00081 pins->nFineTune = MOD2XMFineTune(psh->finetune_and_pan & 0x0F);
00082 pins->uFlags = (psh->infobyte & 0x80) ? CHN_16BIT : 0;
00083 if ((pins->nLoopEnd <= pins->nLength) && (pins->nLoopStart+4 <= pins->nLoopEnd)) pins->uFlags |= CHN_LOOP;
00084 pkinf[nSmp] = psh->infobyte;
00085 }
00086
00087 tmp = lpStream[dwMemPos++];
00088 if (dwMemPos + tmp + 1 >= dwMemLength) return TRUE;
00089 tmp2 = (tmp < 32) ? tmp : 31;
00090 if (tmp2) memcpy(m_szNames[0], lpStream+dwMemPos, tmp2);
00091 m_szNames[0][tmp2] = 0;
00092 dwMemPos += tmp;
00093
00094 for (UINT sNam=1; sNam<=m_nSamples; sNam++)
00095 {
00096 if (dwMemPos + 32 >= dwMemLength) return TRUE;
00097 tmp = lpStream[dwMemPos++];
00098 tmp2 = (tmp < 32) ? tmp : 31;
00099 if (tmp2) memcpy(m_szNames[sNam], lpStream+dwMemPos, tmp2);
00100 dwMemPos += tmp;
00101 }
00102
00103 for (UINT cNam=0; cNam<m_nChannels; cNam++)
00104 {
00105 if (dwMemPos + 32 >= dwMemLength) return TRUE;
00106 tmp = lpStream[dwMemPos++];
00107 dwMemPos += tmp;
00108 }
00109
00110 m_lpszPatternNames = new char[pfh->patterns * 32];
00111 if (!m_lpszPatternNames) return TRUE;
00112 m_nPatternNames = pfh->patterns;
00113 memset(m_lpszPatternNames, 0, m_nPatternNames * 32);
00114 for (UINT pNam=0; pNam < m_nPatternNames; pNam++)
00115 {
00116 if (dwMemPos + 32 >= dwMemLength) return TRUE;
00117 tmp = lpStream[dwMemPos++];
00118 tmp2 = (tmp < 32) ? tmp : 31;
00119 if (tmp2) memcpy(m_lpszPatternNames+pNam*32, lpStream+dwMemPos, tmp2);
00120 dwMemPos += tmp;
00121 }
00122
00123 tmp = *((WORD *)(lpStream+dwMemPos));
00124 dwMemPos += 2;
00125 if (dwMemPos + tmp >= dwMemLength) return TRUE;
00126 if (tmp)
00127 {
00128 m_lpszSongComments = new char[tmp+1];
00129 if (!m_lpszSongComments) return TRUE;
00130 memset(m_lpszSongComments, 0, tmp+1);
00131 memcpy(m_lpszSongComments, lpStream + dwMemPos, tmp);
00132 dwMemPos += tmp;
00133 }
00134
00135 for (UINT iOrd=0; iOrd<pfh->orders; iOrd++, dwMemPos += 2)
00136 {
00137 UINT n = *((WORD *)(lpStream+dwMemPos));
00138 Order[iOrd] = (BYTE)n;
00139 }
00140
00141 for (UINT iPat=0; iPat<pfh->patterns; iPat++)
00142 {
00143 if (dwMemPos + 4 >= dwMemLength) return TRUE;
00144 UINT len = *((DWORD *)(lpStream + dwMemPos));
00145 dwMemPos += 4;
00146 if ((len >= dwMemLength) || (dwMemPos + len > dwMemLength)) return TRUE;
00147 PatternSize[iPat] = 64;
00148 MODCOMMAND *m = AllocatePattern(PatternSize[iPat], m_nChannels);
00149 if (!m) return TRUE;
00150 Patterns[iPat] = m;
00151 const BYTE *p = lpStream + dwMemPos;
00152 UINT row = 0, i = 0;
00153 while ((row < PatternSize[iPat]) && (i+2 < len))
00154 {
00155 BYTE b0 = p[i++];
00156 BYTE b1 = p[i++];
00157 BYTE b2 = 0;
00158 UINT ch = b0 & 0x3F;
00159
00160 if (!(b0 & 0x40))
00161 {
00162 b2 = p[i++];
00163 if (ch < m_nChannels)
00164 {
00165 if (b1 & 0x7F) m[ch].note = (b1 & 0x7F) + 25;
00166 m[ch].instr = b2;
00167 }
00168 if (b1 & 0x80)
00169 {
00170 b0 |= 0x40;
00171 b1 = p[i++];
00172 }
00173 }
00174
00175 if (b0 & 0x40)
00176 {
00177 anothercommand:
00178 if (b1 & 0x40)
00179 {
00180 if (ch < m_nChannels)
00181 {
00182 m[ch].volcmd = VOLCMD_VOLUME;
00183 m[ch].vol = b1 & 0x3F;
00184 }
00185 } else
00186 {
00187 b2 = p[i++];
00188 if (ch < m_nChannels)
00189 {
00190 UINT cmd = b1 & 0x3F;
00191 if (cmd == 0x0C)
00192 {
00193 m[ch].volcmd = VOLCMD_VOLUME;
00194 m[ch].vol = b2 >> 1;
00195 } else
00196 if (cmd == 0x0E)
00197 {
00198 if (!m[ch].command)
00199 {
00200 UINT command = CMD_S3MCMDEX;
00201 UINT param = b2;
00202 switch(param & 0xF0)
00203 {
00204 case 0x00: if (param & 0x08) { param &= 0x07; param |= 0x90; } else {command=param=0;} break;
00205 case 0x10: command = CMD_PORTAMENTOUP; param |= 0xF0; break;
00206 case 0x20: command = CMD_PORTAMENTODOWN; param |= 0xF0; break;
00207 case 0x30: param = (param & 0x0F) | 0x10; break;
00208 case 0x40: param = (param & 0x0F) | 0x30; break;
00209 case 0x50: param = (param & 0x0F) | 0x20; break;
00210 case 0x60: param = (param & 0x0F) | 0xB0; break;
00211 case 0x70: param = (param & 0x0F) | 0x40; break;
00212 case 0x90: command = CMD_RETRIG; param &= 0x0F; break;
00213 case 0xA0: if (param & 0x0F) { command = CMD_VOLUMESLIDE; param = (param << 4) | 0x0F; } else command=param=0; break;
00214 case 0xB0: if (param & 0x0F) { command = CMD_VOLUMESLIDE; param |= 0xF0; } else command=param=0; break;
00215 }
00216 m[ch].command = command;
00217 m[ch].param = param;
00218 }
00219 } else
00220 {
00221 m[ch].command = cmd;
00222 m[ch].param = b2;
00223 ConvertModCommand(&m[ch]);
00224 }
00225 }
00226 }
00227 if (b1 & 0x80)
00228 {
00229 b1 = p[i++];
00230 if (i <= len) goto anothercommand;
00231 }
00232 }
00233 if (b0 & 0x80)
00234 {
00235 row++;
00236 m += m_nChannels;
00237 }
00238 }
00239 dwMemPos += len;
00240 }
00241
00242 for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) if (Ins[iSmp].nLength)
00243 {
00244 if (dwMemPos >= dwMemLength - 9) return TRUE;
00245 UINT flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_AMS16 : RS_AMS8;
00246 dwMemPos += ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
00247 }
00248 return TRUE;
00249 }
00250
00251
00253
00254
00255 #pragma pack(1)
00256
00257 typedef struct AMS2FILEHEADER
00258 {
00259 DWORD dwHdr1;
00260 WORD wHdr2;
00261 BYTE b1A;
00262 BYTE titlelen;
00263 CHAR szTitle[30];
00264 } Q_PACKED AMS2FILEHEADER;
00265
00266 typedef struct AMS2SONGHEADER
00267 {
00268 WORD version;
00269 BYTE instruments;
00270 WORD patterns;
00271 WORD orders;
00272 WORD bpm;
00273 BYTE speed;
00274 BYTE channels;
00275 BYTE commands;
00276 BYTE rows;
00277 WORD flags;
00278 } Q_PACKED AMS2SONGHEADER;
00279
00280 typedef struct AMS2INSTRUMENT
00281 {
00282 BYTE samples;
00283 BYTE notemap[120];
00284 } Q_PACKED AMS2INSTRUMENT;
00285
00286 typedef struct AMS2ENVELOPE
00287 {
00288 BYTE speed;
00289 BYTE sustain;
00290 BYTE loopbegin;
00291 BYTE loopend;
00292 BYTE points;
00293 BYTE info[3];
00294 } Q_PACKED AMS2ENVELOPE;
00295
00296 typedef struct AMS2SAMPLE
00297 {
00298 DWORD length;
00299 DWORD loopstart;
00300 DWORD loopend;
00301 WORD frequency;
00302 BYTE finetune;
00303 WORD c4speed;
00304 CHAR transpose;
00305 BYTE volume;
00306 BYTE flags;
00307 } Q_PACKED AMS2SAMPLE;
00308
00309
00310 #pragma pack()
00311
00312
00313 BOOL CSoundFile::ReadAMS2(LPCBYTE lpStream, DWORD dwMemLength)
00314
00315 {
00316 AMS2FILEHEADER *pfh = (AMS2FILEHEADER *)lpStream;
00317 AMS2SONGHEADER *psh;
00318 DWORD dwMemPos;
00319 BYTE smpmap[16];
00320 BYTE packedsamples[MAX_SAMPLES];
00321
00322 if ((pfh->dwHdr1 != 0x68534D41) || (pfh->wHdr2 != 0x7264)
00323 || (pfh->b1A != 0x1A) || (pfh->titlelen > 30)) return FALSE;
00324 dwMemPos = pfh->titlelen + 8;
00325 psh = (AMS2SONGHEADER *)(lpStream + dwMemPos);
00326 if (((psh->version & 0xFF00) != 0x0200) || (!psh->instruments)
00327 || (psh->instruments > MAX_INSTRUMENTS) || (!psh->patterns) || (!psh->orders)) return FALSE;
00328 dwMemPos += sizeof(AMS2SONGHEADER);
00329 if (pfh->titlelen)
00330 {
00331 memcpy(m_szNames, pfh->szTitle, pfh->titlelen);
00332 m_szNames[0][pfh->titlelen] = 0;
00333 }
00334 m_nType = MOD_TYPE_AMS;
00335 m_nChannels = 32;
00336 m_nDefaultTempo = psh->bpm >> 8;
00337 m_nDefaultSpeed = psh->speed;
00338 m_nInstruments = psh->instruments;
00339 m_nSamples = 0;
00340 if (psh->flags & 0x40) m_dwSongFlags |= SONG_LINEARSLIDES;
00341 for (UINT nIns=1; nIns<=m_nInstruments; nIns++)
00342 {
00343 UINT insnamelen = lpStream[dwMemPos];
00344 CHAR *pinsname = (CHAR *)(lpStream+dwMemPos+1);
00345 dwMemPos += insnamelen + 1;
00346 AMS2INSTRUMENT *pins = (AMS2INSTRUMENT *)(lpStream + dwMemPos);
00347 dwMemPos += sizeof(AMS2INSTRUMENT);
00348 if (dwMemPos + 1024 >= dwMemLength) return TRUE;
00349 AMS2ENVELOPE *volenv, *panenv, *pitchenv;
00350 volenv = (AMS2ENVELOPE *)(lpStream+dwMemPos);
00351 dwMemPos += 5 + volenv->points*3;
00352 panenv = (AMS2ENVELOPE *)(lpStream+dwMemPos);
00353 dwMemPos += 5 + panenv->points*3;
00354 pitchenv = (AMS2ENVELOPE *)(lpStream+dwMemPos);
00355 dwMemPos += 5 + pitchenv->points*3;
00356 INSTRUMENTHEADER *penv = new INSTRUMENTHEADER;
00357 if (!penv) return TRUE;
00358 memset(smpmap, 0, sizeof(smpmap));
00359 memset(penv, 0, sizeof(INSTRUMENTHEADER));
00360 for (UINT ismpmap=0; ismpmap<pins->samples; ismpmap++)
00361 {
00362 if ((ismpmap >= 16) || (m_nSamples+1 >= MAX_SAMPLES)) break;
00363 m_nSamples++;
00364 smpmap[ismpmap] = m_nSamples;
00365 }
00366 penv->nGlobalVol = 64;
00367 penv->nPan = 128;
00368 penv->nPPC = 60;
00369 Headers[nIns] = penv;
00370 if (insnamelen)
00371 {
00372 if (insnamelen > 31) insnamelen = 31;
00373 memcpy(penv->name, pinsname, insnamelen);
00374 penv->name[insnamelen] = 0;
00375 }
00376 for (UINT inotemap=0; inotemap<120; inotemap++)
00377 {
00378 penv->NoteMap[inotemap] = inotemap+1;
00379 penv->Keyboard[inotemap] = smpmap[pins->notemap[inotemap] & 0x0F];
00380 }
00381
00382 {
00383 UINT pos = 0;
00384 penv->nVolEnv = (volenv->points > 16) ? 16 : volenv->points;
00385 penv->nVolSustainBegin = penv->nVolSustainEnd = volenv->sustain;
00386 penv->nVolLoopStart = volenv->loopbegin;
00387 penv->nVolLoopEnd = volenv->loopend;
00388 for (UINT i=0; i<penv->nVolEnv; i++)
00389 {
00390 penv->VolEnv[i] = (BYTE)((volenv->info[i*3+2] & 0x7F) >> 1);
00391 pos += volenv->info[i*3] + ((volenv->info[i*3+1] & 1) << 8);
00392 penv->VolPoints[i] = (WORD)pos;
00393 }
00394 }
00395 penv->nFadeOut = (((lpStream[dwMemPos+2] & 0x0F) << 8) | (lpStream[dwMemPos+1])) << 3;
00396 UINT envflags = lpStream[dwMemPos+3];
00397 if (envflags & 0x01) penv->dwFlags |= ENV_VOLLOOP;
00398 if (envflags & 0x02) penv->dwFlags |= ENV_VOLSUSTAIN;
00399 if (envflags & 0x04) penv->dwFlags |= ENV_VOLUME;
00400 dwMemPos += 5;
00401
00402 for (UINT ismp=0; ismp<pins->samples; ismp++)
00403 {
00404 MODINSTRUMENT *psmp = ((ismp < 16) && (smpmap[ismp])) ? &Ins[smpmap[ismp]] : NULL;
00405 UINT smpnamelen = lpStream[dwMemPos];
00406 if ((psmp) && (smpnamelen) && (smpnamelen <= 22))
00407 {
00408 memcpy(m_szNames[smpmap[ismp]], lpStream+dwMemPos+1, smpnamelen);
00409 }
00410 dwMemPos += smpnamelen + 1;
00411 if (psmp)
00412 {
00413 AMS2SAMPLE *pams = (AMS2SAMPLE *)(lpStream+dwMemPos);
00414 psmp->nGlobalVol = 64;
00415 psmp->nPan = 128;
00416 psmp->nLength = pams->length;
00417 psmp->nLoopStart = pams->loopstart;
00418 psmp->nLoopEnd = pams->loopend;
00419 psmp->nC4Speed = pams->c4speed;
00420 psmp->RelativeTone = pams->transpose;
00421 psmp->nVolume = pams->volume / 2;
00422 packedsamples[smpmap[ismp]] = pams->flags;
00423 if (pams->flags & 0x04) psmp->uFlags |= CHN_16BIT;
00424 if (pams->flags & 0x08) psmp->uFlags |= CHN_LOOP;
00425 if (pams->flags & 0x10) psmp->uFlags |= CHN_PINGPONGLOOP;
00426 }
00427 dwMemPos += sizeof(AMS2SAMPLE);
00428 }
00429 }
00430 if (dwMemPos + 256 >= dwMemLength) return TRUE;
00431
00432 {
00433 UINT composernamelen = lpStream[dwMemPos];
00434 if (composernamelen)
00435 {
00436 m_lpszSongComments = new char[composernamelen+1];
00437 if (m_lpszSongComments)
00438 {
00439 memcpy(m_lpszSongComments, lpStream+dwMemPos+1, composernamelen);
00440 m_lpszSongComments[composernamelen] = 0;
00441 }
00442 }
00443 dwMemPos += composernamelen + 1;
00444
00445 for (UINT i=0; i<32; i++)
00446 {
00447 UINT chnnamlen = lpStream[dwMemPos];
00448 if ((chnnamlen) && (chnnamlen < MAX_CHANNELNAME))
00449 {
00450 memcpy(ChnSettings[i].szName, lpStream+dwMemPos+1, chnnamlen);
00451 }
00452 dwMemPos += chnnamlen + 1;
00453 if (dwMemPos + chnnamlen + 256 >= dwMemLength) return TRUE;
00454 }
00455
00456 UINT songtextlen = *((LPDWORD)(lpStream+dwMemPos));
00457 dwMemPos += songtextlen;
00458 if (dwMemPos + 256 >= dwMemLength) return TRUE;
00459 }
00460
00461 {
00462 for (UINT i=0; i<MAX_ORDERS; i++)
00463 {
00464 Order[i] = 0xFF;
00465 if (dwMemPos + 2 >= dwMemLength) return TRUE;
00466 if (i < psh->orders)
00467 {
00468 Order[i] = lpStream[dwMemPos];
00469 dwMemPos += 2;
00470 }
00471 }
00472 }
00473
00474 for (UINT ipat=0; ipat<psh->patterns; ipat++)
00475 {
00476 if (dwMemPos+8 >= dwMemLength) return TRUE;
00477 UINT packedlen = *((LPDWORD)(lpStream+dwMemPos));
00478 UINT numrows = 1 + (UINT)(lpStream[dwMemPos+4]);
00479
00480
00481 UINT patnamlen = lpStream[dwMemPos+6];
00482 dwMemPos += 4;
00483 if ((ipat < MAX_PATTERNS) && (packedlen < dwMemLength-dwMemPos) && (numrows >= 8))
00484 {
00485 if ((patnamlen) && (patnamlen < MAX_PATTERNNAME))
00486 {
00487 char s[MAX_PATTERNNAME];
00488 memcpy(s, lpStream+dwMemPos+3, patnamlen);
00489 s[patnamlen] = 0;
00490 SetPatternName(ipat, s);
00491 }
00492 PatternSize[ipat] = numrows;
00493 Patterns[ipat] = AllocatePattern(numrows, m_nChannels);
00494 if (!Patterns[ipat]) return TRUE;
00495
00496 LPCBYTE psrc = lpStream + dwMemPos;
00497 UINT pos = 3 + patnamlen;
00498 UINT row = 0;
00499 while ((pos < packedlen) && (row < numrows))
00500 {
00501 MODCOMMAND *m = Patterns[ipat] + row * m_nChannels;
00502 UINT byte1 = psrc[pos++];
00503 UINT ch = byte1 & 0x1F;
00504
00505 if (!(byte1 & 0x40))
00506 {
00507 UINT byte2 = psrc[pos++];
00508 UINT note = byte2 & 0x7F;
00509 if (note) m[ch].note = (note > 1) ? (note-1) : 0xFF;
00510 m[ch].instr = psrc[pos++];
00511
00512 while (byte2 & 0x80)
00513 {
00514 byte2 = psrc[pos++];
00515 if (byte2 & 0x40)
00516 {
00517 m[ch].volcmd = VOLCMD_VOLUME;
00518 m[ch].vol = byte2 & 0x3F;
00519 } else
00520 {
00521 UINT command = byte2 & 0x3F;
00522 UINT param = psrc[pos++];
00523 if (command == 0x0C)
00524 {
00525 m[ch].volcmd = VOLCMD_VOLUME;
00526 m[ch].vol = param / 2;
00527 } else
00528 if (command < 0x10)
00529 {
00530 m[ch].command = command;
00531 m[ch].param = param;
00532 ConvertModCommand(&m[ch]);
00533 } else
00534 {
00535
00536 }
00537 }
00538 }
00539 }
00540 if (byte1 & 0x80) row++;
00541 }
00542 }
00543 dwMemPos += packedlen;
00544 }
00545
00546 for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) if (Ins[iSmp].nLength)
00547 {
00548 if (dwMemPos >= dwMemLength - 9) return TRUE;
00549 UINT flags;
00550 if (packedsamples[iSmp] & 0x03)
00551 {
00552 flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_AMS16 : RS_AMS8;
00553 } else
00554 {
00555 flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S;
00556 }
00557 dwMemPos += ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
00558 }
00559 return TRUE;
00560 }
00561
00562
00564
00565
00566 void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter)
00567 {
00568 UINT tmplen = dmax;
00569 signed char *amstmp = new signed char[tmplen];
00570
00571 if (!amstmp) return;
00572
00573 {
00574 signed char *p = amstmp;
00575 UINT i=0, j=0;
00576 while ((i < inputlen) && (j < tmplen))
00577 {
00578 signed char ch = psrc[i++];
00579 if (ch == packcharacter)
00580 {
00581 BYTE ch2 = psrc[i++];
00582 if (ch2)
00583 {
00584 ch = psrc[i++];
00585 while (ch2--)
00586 {
00587 p[j++] = ch;
00588 if (j >= tmplen) break;
00589 }
00590 } else p[j++] = packcharacter;
00591 } else p[j++] = ch;
00592 }
00593 }
00594
00595 {
00596 signed char *p = amstmp;
00597 UINT bitcount = 0x80, dh;
00598 UINT k=0;
00599 for (UINT i=0; i<dmax; i++)
00600 {
00601 BYTE al = *p++;
00602 dh = 0;
00603 for (UINT count=0; count<8; count++)
00604 {
00605 UINT bl = al & bitcount;
00606 bl = ((bl|(bl<<8)) >> ((dh+8-count) & 7)) & 0xFF;
00607 bitcount = ((bitcount|(bitcount<<8)) >> 1) & 0xFF;
00608 pdest[k++] |= bl;
00609 if (k >= dmax)
00610 {
00611 k = 0;
00612 dh++;
00613 }
00614 }
00615 bitcount = ((bitcount|(bitcount<<8)) >> dh) & 0xFF;
00616 }
00617 }
00618
00619 {
00620 signed char old = 0;
00621 for (UINT i=0; i<dmax; i++)
00622 {
00623 int pos = ((LPBYTE)pdest)[i];
00624 if ((pos != 128) && (pos & 0x80)) pos = -(pos & 0x7F);
00625 old -= (signed char)pos;
00626 pdest[i] = old;
00627 }
00628 }
00629 delete amstmp;
00630 }
00631