├── .gitignore ├── YM2608J_Translated.PDF ├── fmgen ├── rhythmdata.c ├── Makefile ├── e_expf.c ├── psg.h ├── opna.h ├── op.h └── psg.c ├── libaout ├── Makefile ├── audio_out.h ├── oss_audio_open.c ├── audio_out.c ├── alsa_audio_open.c ├── w64crt1.c ├── win32waveout.c ├── alsa_pcm_api.c ├── alsa_pcm_api.h ├── ntapi.h └── nt_wdmks.c ├── Makefile ├── md5.c ├── pmd_play.c ├── pmdwin.h └── efftbl.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.a 3 | 4 | -------------------------------------------------------------------------------- /YM2608J_Translated.PDF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pbarfuss/PMDWinS036/HEAD/YM2608J_Translated.PDF -------------------------------------------------------------------------------- /fmgen/rhythmdata.c: -------------------------------------------------------------------------------- 1 | #include "rhythmdata.h" 2 | 3 | const unsigned char* rhythmdata[6] = { 4 | BD_2608, SD_2608, TOP_2608, HH_2608, TOM_2608, RIM_2608 5 | }; 6 | 7 | -------------------------------------------------------------------------------- /fmgen/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS += -Wall -pipe -O2 -fno-math-errno -fno-trapping-math -fno-omit-frame-pointer -fno-asynchronous-unwind-tables -fwrapv 3 | 4 | all: libfmgen.a 5 | %.o: %.c 6 | $(CC) $(CFLAGS) -c $< 7 | 8 | clean: 9 | rm *.o libfmgen.a 10 | 11 | libfmgen.a: e_expf.o opna.o psg.o rhythmdata.o 12 | $(AR) rc $@ $^ 13 | 14 | -------------------------------------------------------------------------------- /libaout/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS += -Wall -pipe -O2 -fno-math-errno -fno-trapping-math -fno-omit-frame-pointer -fno-asynchronous-unwind-tables -fwrapv 3 | 4 | all: libaout.a 5 | %.o: %.c 6 | $(CC) $(CFLAGS) -c $< 7 | 8 | clean: 9 | rm *.o libaout.a 10 | 11 | libaout.a: audio_out.o oss_audio_open.o alsa_audio_open.o alsa_pcm_api.o 12 | $(AR) rc $@ $^ 13 | ranlib $@ $^ 14 | 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS += -Ifmgen -Wall -pipe -O2 -fno-math-errno -fno-trapping-math -fno-omit-frame-pointer -fno-asynchronous-unwind-tables -fwrapv -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 3 | 4 | all: pmdwin 5 | %.o: %.c 6 | $(CC) $(CFLAGS) -c $< 7 | 8 | clean: 9 | rm *.o fmgen/*.o libfmgen.a pmdwin 10 | 11 | pmdwin: pmd_play.o pmdwin.o md5.o fmgen/libfmgen.a libaout/libaout.a 12 | $(CC) -o $@ $^ 13 | 14 | fmgen/libfmgen.a: 15 | make -C fmgen 16 | 17 | libaout/libaout.a: 18 | make -C libaout 19 | 20 | -------------------------------------------------------------------------------- /fmgen/e_expf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | typedef union _f32 { 5 | float f; 6 | uint32_t i; 7 | } _f32; 8 | 9 | /* Constants for expf(x) -- single-precision exponential function evaluated at x (i.e. e^x). */ 10 | static const float 11 | halF[2] = {0.5,-0.5,}, 12 | ln2 = 0.69314718246, 13 | invln2 = 1.4426950216, /* 0x3fb8aa3b */ 14 | T_P3 = 1.66662832359450473e-01, 15 | T_P4 = 4.16979462133574885e-02, 16 | T_P5 = 8.2031098e-03; 17 | 18 | float expf(float x) /* default IEEE double exp */ 19 | { 20 | _f32 tmp, hy; 21 | int32_t k = 0; 22 | 23 | /* filter out non-finite argument */ 24 | if (x != x) return x; 25 | tmp.f = x; 26 | tmp.i &= 0x7fffffff; /* high word of |x| */ 27 | if(tmp.i >= 0x42b17218) { /* if |x|>=88.721... */ 28 | if(tmp.i==0x7f800000) 29 | return (x < 0.0f)? x:0.0f; /* exp(+-inf)={inf,0} */ 30 | return x; 31 | } 32 | 33 | /* argument reduction */ 34 | if(tmp.i > 0x3eb17218) { /* if |x| > 0.5 ln2 */ 35 | k = lrintf(invln2*x); 36 | x = (x - k*ln2); 37 | } 38 | 39 | /* x is now in primary range */ 40 | hy.f = 1.0f+x*(1.0f+x*(0.5f+x*(T_P3+x*(T_P4+x*T_P5)))); 41 | hy.i += (k << 23); /* add k to y\s exponent */ 42 | return hy.f; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /fmgen/psg.h: -------------------------------------------------------------------------------- 1 | #ifndef __PSG_H__ 2 | #define __PSG_H__ 3 | 4 | #include 5 | #define PSG_SAMPLETYPE int32_t // any of int16_t, int32_t or float will work here. 6 | 7 | // Constants for the shift amounts used in the counters. 8 | // 9 | enum { 10 | toneshift = 24, 11 | envshift = 22 12 | }; 13 | 14 | typedef struct _PSG { 15 | uint8_t reg[16]; 16 | 17 | const uint32_t *envelop; 18 | uint32_t rng; 19 | uint32_t olevel[3]; 20 | uint32_t scount[3], speriod[3]; 21 | uint32_t ecount, eperiod; 22 | uint32_t ncount, nperiod; 23 | uint32_t tperiodbase; 24 | uint32_t eperiodbase; 25 | int volume; 26 | int mask; 27 | } PSG; 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | // Mostly self-explanatory. 34 | // Actual descriptions of each function can be found in psg.c 35 | // Also, PSGGetReg() is basically useless. 36 | // (More info on that can *also* be found in psg.c). 37 | void PSGInit(PSG *psg); 38 | void PSGReset(PSG *psg); 39 | void PSGSetClock(PSG *psg, uint32_t clock, uint32_t rate); 40 | void PSGSetChannelMask(PSG *psg, int c); 41 | void PSGSetReg(PSG *psg, uint8_t regnum, uint8_t data); 42 | void PSGMix(PSG *psg, int32_t *dest, uint32_t nsamples); 43 | 44 | static inline uint32_t PSGGetReg(PSG *psg, uint8_t regnum) { 45 | return psg->reg[regnum & 0x0f]; 46 | } 47 | 48 | #ifdef __cplusplus 49 | }; 50 | #endif 51 | 52 | #endif // PSG_H 53 | -------------------------------------------------------------------------------- /libaout/audio_out.h: -------------------------------------------------------------------------------- 1 | #ifndef __AUDIO_OUT_H__ 2 | #define __AUDIO_OUT_H__ 3 | 4 | #include 5 | #if defined(_WIN32) || defined(_WIN64) 6 | #include "ntapi.h" 7 | #endif 8 | 9 | #if defined(_WIN32) || defined(_WIN64) 10 | typedef UNICODE_STRING devpath_t; 11 | #else 12 | typedef const char devpath_t; 13 | #endif 14 | 15 | extern void (*audio_write_flt)(void *snd_fd, float *buf, uint32_t bufsize); 16 | extern void (*audio_write_s16)(void *snd_fd, int16_t *buf, uint32_t bufsize); 17 | extern void (*audio_close)(void *snd_fd); 18 | 19 | void *audio_open(uint8_t devtype, devpath_t *devpath, uint32_t *samplerate); 20 | 21 | void *oss_audio_open(const char *devpath, uint32_t *oss_audio_rate); 22 | void oss_audio_write_flt(void *snd_fd, float *buf, uint32_t bufsize); 23 | void oss_audio_write_s16(void *snd_fd, int16_t *buf, uint32_t bufsize); 24 | void oss_audio_close(void *snd_fd); 25 | void *alsa_audio_open(const char *devpath, uint32_t *samplerate, uint32_t *_ver); 26 | void alsa_audio_write_flt(void *snd_fd, float *buf, uint32_t bufsize); 27 | void alsa_audio_write_s16(void *snd_fd, int16_t *buf, uint32_t bufsize); 28 | void alsa_audio_close(void *snd_fd); 29 | 30 | void *CoreAudioOpen(uint32_t rate); 31 | void CoreAudioWriteFlt(void *_ao, float *output_samples, uint32_t num_bytes); 32 | void CoreAudioWriteS16(void *_ao, int16_t *output_samples, uint32_t num_bytes); 33 | void CoreAudioClose(void *_ao); 34 | 35 | #if defined(_WIN32) || defined(_WIN64) 36 | void *audio_wdmks_open(UNICODE_STRING *AudioDevicePath, uint32_t *samplerate, uint32_t bufsize); 37 | void audio_wdmks_close(void *wdmks); 38 | void *audio_winmm_open(unsigned int *sfreq); 39 | void audio_winmm_write_flt(void *waveout, float *buf, uint32_t bufsize); 40 | void audio_winmm_write_s16(void *waveout, int16_t *buf, uint32_t bufsize); 41 | void audio_winmm_close(void *waveout); 42 | #if 0 43 | typedef struct _devlist_t { 44 | void *next; 45 | ULONG idx; 46 | UNICODE_STRING devpath; 47 | } devlist_t; 48 | devlist_t *NtWdmKSEnumerateAudioDevices(UNICODE_STRING *KeyName); 49 | #endif 50 | #endif 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /libaout/oss_audio_open.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | void *oss_audio_open(const char *devpath, uint32_t *oss_audio_rate) 9 | { 10 | int afd = -1, tmp = 0; 11 | 12 | /* open the sound device */ 13 | if (!devpath) { 14 | devpath = "/dev/dsp"; 15 | } 16 | 17 | if ((afd = open(devpath, O_WRONLY, 0)) < 0) 18 | { /* Opening device failed */ 19 | return NULL; 20 | } 21 | 22 | tmp = AFMT_S16_NE; 23 | /* set the sound driver audio format for playback */ 24 | if (ioctl(afd, SNDCTL_DSP_SETFMT, &tmp) < 0) 25 | { /* Fatal error */ 26 | goto err; 27 | } 28 | 29 | /* set the sound driver number of channels for playback */ 30 | tmp = 0; 31 | if (ioctl(afd, SNDCTL_DSP_STEREO, &tmp) < 0) 32 | { /* Fatal error */ 33 | goto err; 34 | } 35 | 36 | /* set the sound driver number playback rate */ 37 | tmp = *oss_audio_rate; 38 | if (ioctl(afd, SNDCTL_DSP_SPEED, &tmp) < 0) 39 | { /* Fatal error */ 40 | goto err; 41 | } 42 | *oss_audio_rate = tmp; 43 | 44 | return (void*)((size_t)afd); 45 | err: 46 | close(afd); 47 | return NULL; 48 | } 49 | 50 | #define WORD2INT(x) ((x) < -32766.5f ? -32767 : ((x) > 32766.5f ? 32767 : lrintf(x))) 51 | void oss_audio_write_flt(void *ao, float *floatbuf, uint32_t floatbufsize) 52 | { 53 | int snd_fd = (int)((size_t)ao); 54 | uint32_t i; 55 | short outbuf[8192]; 56 | for(i=0; i 5 | #include "op.h" 6 | #include "psg.h" 7 | 8 | // YM2608 (OPNA) ------------------------------------------------------ 9 | typedef struct _OPNA 10 | { 11 | int fmvolume; 12 | uint32_t clock; 13 | uint32_t rate; 14 | uint32_t psgrate; 15 | uint32_t status; 16 | Channel4 ch[6]; 17 | Channel4* csmch; 18 | 19 | int32_t mixdelta; 20 | int mpratio; 21 | uint8_t interpolation; 22 | 23 | uint8_t timer_status; 24 | uint8_t regtc; 25 | uint8_t regta[2]; 26 | 27 | int32_t timera, timera_count; 28 | int32_t timerb, timerb_count; 29 | int32_t timer_step; 30 | uint8_t prescale; 31 | uint8_t devmask; 32 | 33 | PSG psg; 34 | 35 | Rhythm rhythm[6]; 36 | int8_t rhythmtl; 37 | int rhythmtvol; 38 | uint8_t rhythmkey; 39 | 40 | int32_t mixl, mixl1; 41 | uint8_t fnum2[9]; 42 | 43 | uint8_t reg22; 44 | uint32_t reg29; 45 | uint32_t statusnext; 46 | 47 | uint32_t lfocount; 48 | uint32_t lfodcount; 49 | 50 | uint32_t fnum[6]; 51 | uint32_t fnum3[3]; 52 | } OPNA; 53 | 54 | #ifdef __cplusplus 55 | extern "C" { 56 | #endif 57 | 58 | // --------------------------------------------------------------------------- 59 | uint8_t OPNAInit(OPNA *opna, uint32_t c, uint32_t r, uint8_t ipflag); 60 | void OPNAReset(OPNA *opna); 61 | void OPNASetVolumeRhythm(OPNA *opna, int index, int db); 62 | uint8_t OPNASetRate(OPNA *opna, uint32_t r, uint8_t ipflag); 63 | void OPNASetChannelMask(OPNA *opna, uint32_t mask); 64 | void OPNASetReg(OPNA *opna, uint32_t addr, uint32_t data); 65 | uint8_t OPNATimerCount(OPNA *opna, int32_t us); 66 | void OPNAMix(OPNA *opna, int16_t *buffer, uint32_t nsamples); 67 | 68 | // --------------------------------------------------------------------------- 69 | static inline uint32_t OPNAReadStatus(OPNA *opna) { return opna->status & 0x03; } 70 | 71 | static inline int32_t OPNAGetNextEvent(OPNA *opna) 72 | { 73 | uint32_t ta = ((opna->timera_count + 0xffff) >> 16) - 1; 74 | uint32_t tb = ((opna->timerb_count + 0xfff) >> 12) - 1; 75 | return (ta < tb ? ta : tb) + 1; 76 | } 77 | 78 | #ifdef __cplusplus 79 | }; 80 | #endif 81 | 82 | #endif // FM_OPNA_H 83 | -------------------------------------------------------------------------------- /libaout/audio_out.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "audio_out.h" 6 | 7 | void (*audio_write_flt)(void *snd_fd, float *buf, uint32_t bufsize); 8 | void (*audio_write_s16)(void *snd_fd, int16_t *buf, uint32_t bufsize); 9 | void (*audio_close)(void *snd_fd); 10 | 11 | void *audio_open(uint8_t devtype, devpath_t *devpath, uint32_t *samplerate) 12 | { 13 | void *ao = NULL; 14 | #ifdef __linux__ 15 | if (devtype == 'a') goto try_alsa; 16 | #endif 17 | #if !defined(_WIN32) && !defined(_WIN64) 18 | if (devtype == 'o') goto try_oss; 19 | #endif 20 | #if (defined(_WIN32) || defined(_WIN64)) 21 | if ((devtype == 's') || (devtype == 'S')) goto try_nt_wdmks; 22 | #ifdef ENABLE_WINMM 23 | if (devtype == 'm') goto try_winmm; 24 | #endif 25 | #endif 26 | #ifdef __linux__ 27 | if (!ao) { 28 | try_alsa: 29 | ao = alsa_audio_open(devpath, samplerate, NULL); 30 | if (ao) { 31 | audio_write_flt = alsa_audio_write_flt; 32 | audio_write_s16 = alsa_audio_write_s16; 33 | audio_close = alsa_audio_close; 34 | return ao; 35 | } 36 | } 37 | #endif 38 | #if !defined(_WIN32) && !defined(_WIN64) 39 | if (!ao) { 40 | try_oss: 41 | ao = oss_audio_open(devpath, samplerate); 42 | if (ao) { 43 | audio_write_flt = oss_audio_write_flt; 44 | audio_write_s16 = oss_audio_write_s16; 45 | audio_close = oss_audio_close; 46 | return ao; 47 | } 48 | } 49 | #endif 50 | #if (defined(_WIN32) || defined(_WIN64)) 51 | if (!ao) { 52 | try_nt_wdmks: 53 | ao = audio_wdmks_open(devpath, samplerate); 54 | if (ao) { 55 | audio_close = audio_wdmks_close; // audio_wdmks_open will already have initialized audio_write for us. 56 | return ao; 57 | } 58 | #ifdef ENABLE_WINMM 59 | } 60 | if (!ao) { 61 | try_winmm: 62 | ao = audio_winmm_open(samplerate); 63 | if (ao) { 64 | audio_write_flt = audio_winmm_write_flt; 65 | audio_write_s16 = audio_winmm_write_s16; 66 | audio_close = audio_winmm_close; 67 | return ao; 68 | } 69 | } 70 | #endif 71 | #endif 72 | if (!ao) { 73 | //audio_wrerr("Tried all sound devices, none were successfully opened. Exiting...\n"); 74 | return NULL; 75 | } 76 | return ao; 77 | } 78 | 79 | -------------------------------------------------------------------------------- /libaout/alsa_audio_open.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "alsa_pcm_api.h" 11 | #define WORD2INT(x) ((x) < -32766.5f ? -32767 : ((x) > 32766.5f ? 32767 : lrintf(x))) 12 | void alsa_init_hwparams(int snd_fd, snd_pcm_access_t access, uint32_t *samplerate, uint32_t frame_size, uint8_t channels); 13 | 14 | void alsa_audio_close(void *ao) 15 | { 16 | int snd_fd = (int)((size_t)ao); 17 | ioctl(snd_fd, SNDRV_PCM_IOCTL_HW_FREE); 18 | close(snd_fd); 19 | } 20 | 21 | void *alsa_audio_open(const char *devpath, uint32_t *samplerate, uint32_t *_ver) 22 | { 23 | int ver, snd_fd = -1; 24 | 25 | if (!devpath) { 26 | devpath = "/dev/snd/pcmC0D0p"; 27 | } 28 | 29 | snd_fd = open(devpath, O_WRONLY); 30 | if (snd_fd < 0) 31 | return NULL; 32 | 33 | if (ioctl(snd_fd, SNDRV_PCM_IOCTL_PVERSION, &ver) < 0) { 34 | if (snd_fd >= 0) 35 | close(snd_fd); 36 | return NULL; 37 | } 38 | if(_ver) *_ver = ver; 39 | 40 | // Initialize hwparams structure. 41 | alsa_init_hwparams(snd_fd, SND_PCM_ACCESS_RW_INTERLEAVED, samplerate, 1024, 1); 42 | return (void*)((size_t)snd_fd); 43 | } 44 | 45 | void alsa_audio_write_flt(void *ao, float *buf, uint32_t bufsize) 46 | { 47 | struct snd_xferi xferi; 48 | int snd_fd = (int)((size_t)ao); 49 | unsigned int i, j; 50 | short outbuf[16384]; 51 | for(i=0; i= 0) { 60 | j = xferi.result; 61 | } 62 | if(j == -32) { //-EPIPE 63 | ioctl(snd_fd, SNDRV_PCM_IOCTL_PREPARE); 64 | } 65 | } 66 | 67 | void alsa_audio_write_s16(void *ao, int16_t *buf, uint32_t bufsize) 68 | { 69 | struct snd_xferi xferi; 70 | int snd_fd = (int)((size_t)ao); 71 | unsigned int i, j; 72 | short outbuf[16384]; 73 | for(i=0; i= 0) { 82 | j = xferi.result; 83 | } 84 | if(j == -32) { //-EPIPE 85 | ioctl(snd_fd, SNDRV_PCM_IOCTL_PREPARE); 86 | } 87 | } 88 | 89 | -------------------------------------------------------------------------------- /libaout/w64crt1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file has no copyright assigned and is placed in the Public Domain. 3 | * This file is part of the w64 mingw-runtime package. 4 | * No warranty is given; refer to the file DISCLAIMER.PD within this package. 5 | */ 6 | 7 | #ifdef NULL 8 | #undef NULL 9 | #endif 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "ntapi.h" 17 | 18 | #ifndef NULL 19 | #ifdef __cplusplus 20 | #define NULL 0 21 | #else 22 | #define NULL ((void *)0) 23 | #endif 24 | #endif 25 | 26 | int main(int _Argc, char **_Argv, char **_Env); 27 | int wmain(int _Argc, wchar_t **_Argv, wchar_t **_Env); 28 | 29 | #ifdef _WIN64 30 | #define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll 31 | #else 32 | #define DEFAULT_SECURITY_COOKIE 0xBB40E64E 33 | #endif 34 | DECLSPEC_SELECTANY UINT_PTR __security_cookie = DEFAULT_SECURITY_COOKIE; 35 | DECLSPEC_SELECTANY UINT_PTR __security_cookie_complement = ~(DEFAULT_SECURITY_COOKIE); 36 | 37 | static void __security_init_cookie (void) 38 | { 39 | UINT_PTR cookie; 40 | LARGE_INTEGER perfctr, perffreq; 41 | 42 | if (__security_cookie != DEFAULT_SECURITY_COOKIE) { 43 | __security_cookie_complement = ~__security_cookie; 44 | return; 45 | } 46 | 47 | NtQueryPerformanceCounter(&perfctr, &perffreq); 48 | #ifdef _WIN64 49 | cookie = perfctr.QuadPart; 50 | #else 51 | cookie = perfctr.LowPart; 52 | cookie ^= perfctr.HighPart; 53 | #endif 54 | 55 | if (cookie == DEFAULT_SECURITY_COOKIE) 56 | cookie = DEFAULT_SECURITY_COOKIE + 1; 57 | __security_cookie = cookie; 58 | __security_cookie_complement = ~cookie; 59 | } 60 | 61 | static int wargc; 62 | static wchar_t **wargv; 63 | 64 | static WCHAR** _CommandLineToArgvW(UNICODE_STRING *CmdLine, int* _argc) 65 | { 66 | WCHAR **argv; 67 | WCHAR *_argv, *argv_alloc = NULL; 68 | WCHAR a; 69 | ULONG len, argc, i = 0, j = 0; 70 | SIZE_T k; 71 | BOOLEAN in_QM = FALSE, in_TEXT = FALSE, in_SPACE = TRUE; 72 | 73 | len = CmdLine->Length; 74 | i = ((len+2)/2)*sizeof(VOID*) + sizeof(VOID*); 75 | k = (i + (len+2)*sizeof(WCHAR)); 76 | NtAllocateVirtualMemory((HANDLE)-1, (void**)&argv_alloc, 0, &k, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); 77 | argv = (WCHAR**)argv_alloc; 78 | _argv = (WCHAR*)(((UCHAR*)argv)+i); 79 | 80 | argc = 0; 81 | argv[argc] = _argv; 82 | i = 0; 83 | 84 | while((a = CmdLine->Buffer[i])) { 85 | if(in_QM) { 86 | if(a == L'\"') { 87 | in_QM = FALSE; 88 | } else { 89 | _argv[j] = a; 90 | j++; 91 | } 92 | } else { 93 | switch(a) { 94 | case L'\"': 95 | in_QM = TRUE; 96 | in_TEXT = TRUE; 97 | if(in_SPACE) { 98 | argv[argc] = _argv+j; 99 | argc++; 100 | } 101 | in_SPACE = FALSE; 102 | break; 103 | case L' ': 104 | case L'\t': 105 | case L'\n': 106 | case L'\r': 107 | if(in_TEXT) { 108 | _argv[j] = '\0'; 109 | j++; 110 | } 111 | in_TEXT = FALSE; 112 | in_SPACE = TRUE; 113 | break; 114 | default: 115 | in_TEXT = TRUE; 116 | if(in_SPACE) { 117 | argv[argc] = _argv+j; 118 | argc++; 119 | } 120 | _argv[j] = a; 121 | j++; 122 | in_SPACE = FALSE; 123 | break; 124 | } 125 | } 126 | i++; 127 | } 128 | _argv[j] = L'\0'; 129 | argv[argc] = NULL; 130 | 131 | (*_argc) = argc; 132 | return argv; 133 | } 134 | 135 | #ifdef COMPILE_NATIVE_BINARY 136 | int NtProcessStartup(void) { 137 | #else 138 | int mainCRTStartup (void) 139 | #endif 140 | { 141 | int ret = 255; 142 | UNICODE_STRING wcmdln; 143 | RtlGetCommandLine(&wcmdln); 144 | 145 | #if defined(__i386__) && !defined(__x86_64__) 146 | /* 147 | * Initialize floating point unit. 148 | */ 149 | __cpu_features_init (); /* Do we have SSE, etc.*/ 150 | _fpreset (); /* Supplied by the runtime library. */ 151 | #endif 152 | __security_init_cookie (); 153 | wargv = _CommandLineToArgvW(&wcmdln, &wargc); 154 | #if defined(__i386__) && !defined(__x86_64__) 155 | /* Align the stack to 16 bytes for the sake of SSE ops in main 156 | * or in functions inlined into main. 157 | */ 158 | __asm__ __volatile__ ("andl $-16, %%esp" ::: "%esp"); 159 | #endif 160 | ret = wmain(wargc, wargv, NULL); 161 | NtTerminateProcess(NtCurrentProcess(), ret); 162 | return ret; 163 | } 164 | 165 | -------------------------------------------------------------------------------- /fmgen/op.h: -------------------------------------------------------------------------------- 1 | #ifndef FM_OP_H 2 | #define FM_OP_H 3 | 4 | #include 5 | #define false 0 6 | #define true 1 7 | #define Max(a,b) ((a>b)?a:b) 8 | #define Min(a,b) ((a max ? max : (v < min ? min : v); 34 | } 35 | 36 | static inline int16_t Limit16(int a) 37 | { 38 | if ((a+0x8000) & ~0xFFFF) return (a>>31) ^ 0x7FFF; 39 | else return a; 40 | } 41 | 42 | // Operator ---------------------------------------------------------------- 43 | typedef struct _FMOperator 44 | { 45 | int32_t out, out2; 46 | 47 | // Phase Generator ----------------------------------------------------- 48 | uint32_t dp; // Octave (used to define note in conjunction with bn, below). 49 | uint8_t detune; // Detune 50 | uint8_t multiple; // Multiple 51 | uint32_t pgcount; // Phase generator sweep value. Only the top 9 bits are relevant/used. 52 | uint32_t pgdcount; // Phase generator increment-per-clock value. Hopefully self-explanatory. 53 | uint32_t pgdcountl; // Phase generator detune increment value. Used in the implementation of vibrato. 54 | // Equal to pgdcount >> 11. 55 | 56 | // Envelope Generator -------------------------------------------------- 57 | uint32_t bn; // Block/Note 58 | uint32_t egout; 59 | int eglevel; // EG ¤Î½ÐÎÏÃÍ 60 | int eglvnext; // ¼¡¤Î phase ¤Ë°Ü¤ëÃÍ 61 | int32_t egstep; // EG ¤Î¼¡¤ÎÊѰܤޤǤλþ´Ö 62 | int32_t egstepd; // egstep ¤Î»þ´Öº¹Ê¬ 63 | uint8_t egtransa; // EG ÊѲ½¤Î³ä¹ç (for attack) 64 | uint8_t egtransd; // EG ÊѲ½¤Î³ä¹ç (for decay) 65 | 66 | uint32_t ksr; // key scale rate 67 | EGPhase phase; 68 | uint8_t ams; 69 | uint8_t ms; 70 | 71 | uint8_t keyon; // current key state 72 | 73 | uint8_t tl; // Total Level (0-127) 74 | uint8_t tll; // Total Level Latch (for CSM mode) 75 | uint8_t ar; // Attack Rate (0-63) 76 | uint8_t dr; // Decay Rate (0-63) 77 | uint8_t sr; // Sustain Rate (0-63) 78 | uint8_t sl; // Sustain Level (0-127) 79 | uint8_t rr; // Release Rate (0-63) 80 | uint8_t ks; // Keyscale (0-3) 81 | uint8_t ssgtype; // SSG-Type Envelope Control 82 | 83 | uint8_t amon; // enable Amplitude Modulation 84 | uint8_t paramchanged; // Set whenever f-number or any ADSR constants 85 | // are set in OPNASetReg(), as well as upon 86 | // chip reset and chip "DAC" samplerate change. 87 | // Causes the envelope generator to reset its 88 | // internal state, also sets correct increments 89 | // for the phase generator. 90 | uint8_t mute; 91 | } FMOperator; 92 | 93 | // 4-op Channel ------------------------------------------------------------ 94 | typedef struct Channel4 95 | { 96 | uint32_t fb; 97 | int buf[4]; 98 | uint8_t idx[6]; 99 | int *pms; 100 | FMOperator op[4]; 101 | } Channel4; 102 | 103 | // OPNA Rhythm Generator --------------------------------------------------- 104 | typedef struct Rhythm { 105 | uint8_t pan; 106 | int8_t level; 107 | int8_t volume; 108 | int8_t* sample; // Rhythm sample data 109 | uint32_t size; // Rhythm sample data size 110 | uint32_t pos; // Current index into rhytm sample data array 111 | uint32_t step; // Amount to increment the above by every time 112 | // RhythmMix() gets called. 113 | uint32_t rate; // Samplerate of rhythm sample data 114 | // (44100Hz in this implementation). 115 | } Rhythm; 116 | 117 | #ifdef __cplusplus 118 | extern "C" { 119 | #endif 120 | 121 | // -------------------------------------------------------------------------- 122 | // Miscellaneous and probably irrelevant function prototypes. 123 | void MakeTable(void); 124 | void OperatorInit(FMOperator *op); 125 | void OperatorReset(FMOperator *op); 126 | void OperatorPrepare(FMOperator *op); 127 | 128 | static inline uint32_t IsOn(FMOperator *op) { 129 | return (op->phase - off); 130 | } 131 | 132 | #ifdef __cplusplus 133 | }; 134 | #endif 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /libaout/win32waveout.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "ntapi.h" 7 | 8 | /* 9 | * some good values for block size and count 10 | */ 11 | #define BLOCK_SIZE 8192 12 | #define BLOCK_COUNT 16 13 | 14 | /* 15 | * module level variables 16 | */ 17 | static WAVEHDR* waveBlocks; 18 | volatile LONG waveFreeBlockCount; 19 | static int waveCurrentBlock; 20 | static HWAVEOUT hWaveOut; 21 | 22 | void CALLBACK waveOutProc(HWAVEOUT hWaveOut, UINT uMsg, DWORD dwInstance, DWORD dwParam1,DWORD dwParam2){ 23 | /* 24 | * pointer to free block counter 25 | */ 26 | LONG* freeBlockCounter = (LONG*)dwInstance; 27 | /* 28 | * ignore calls that occur due to openining and closing the 29 | * device. 30 | */ 31 | if(uMsg != WOM_DONE) 32 | return; 33 | InterlockedIncrement(freeBlockCounter); 34 | } 35 | 36 | static WAVEHDR* allocateBlocks(unsigned int size, unsigned int count){ 37 | unsigned char* buffer = NULL; 38 | int i; 39 | WAVEHDR* blocks; 40 | SIZE_T totalBufferSize = (size + sizeof(WAVEHDR)) * count; 41 | /* 42 | * allocate memory for the entire set in one go 43 | */ 44 | NtAllocateVirtualMemory(((HANDLE)-1), (void**)&buffer, 0, &totalBufferSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); 45 | 46 | /* 47 | * and set up the pointers to each bit 48 | */ 49 | blocks = (WAVEHDR*)buffer; 50 | buffer += sizeof(WAVEHDR) * count; 51 | for(i = 0; i < count; i++) { 52 | blocks[i].dwBufferLength = size; 53 | blocks[i].lpData = (char*)buffer; 54 | buffer += size; 55 | } 56 | return blocks; 57 | } 58 | 59 | #define WORD2INT(x) ((x) < -32766.5f ? -32767 : ((x) > 32766.5f ? 32767 : lrintf(x))) 60 | void audio_winmm_write_flt(void *_ao, float *data, unsigned int size){ 61 | HWAVEOUT hWaveOut = (HWAVEOUT)_ao; 62 | WAVEHDR* current; 63 | current = &waveBlocks[waveCurrentBlock]; 64 | unsigned int i, k = 0, remain; 65 | int16_t *outbuf; 66 | while(size > 0) { 67 | /* 68 | * first make sure the header we're going to use is unprepared 69 | */ 70 | if(current->dwFlags & WHDR_PREPARED) 71 | waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR)); 72 | if(size < (size_t)((BLOCK_SIZE - current->dwUser) >> 1)) { 73 | //memcpy(current->lpData + current->dwUser, data, size); 74 | outbuf = (int16_t*)(current->lpData + current->dwUser); 75 | for (i = 0; i < size; i++) { 76 | outbuf[i] = WORD2INT(data[i+k]*32768.0f); 77 | } 78 | current->dwUser += (size * sizeof(int16_t)); 79 | break; 80 | } 81 | remain = ((BLOCK_SIZE - current->dwUser) >> 1); 82 | outbuf = (int16_t*)(current->lpData + current->dwUser); 83 | //memcpy(current->lpData + current->dwUser, data, remain); 84 | for (i = 0; i < remain; i++) { 85 | outbuf[i] = WORD2INT(data[i+k]*32768.0f); 86 | } 87 | size -= (remain >> 1); 88 | k += (remain >> 1); 89 | current->dwBufferLength = BLOCK_SIZE; 90 | waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR)); 91 | waveOutWrite(hWaveOut, current, sizeof(WAVEHDR)); 92 | InterlockedExchangeAdd(&waveFreeBlockCount, -1); 93 | 94 | while(!waveFreeBlockCount) { 95 | LARGE_INTEGER TimeOut; 96 | TimeOut.QuadPart = -1000000; 97 | NtDelayExecution(FALSE, &TimeOut); 98 | } 99 | 100 | waveCurrentBlock++; 101 | waveCurrentBlock %= BLOCK_COUNT; 102 | current = &waveBlocks[waveCurrentBlock]; 103 | current->dwUser = 0; 104 | } 105 | } 106 | 107 | void audio_winmm_write_s16(void *_ao, int16_t *data, unsigned int size){ 108 | HWAVEOUT hWaveOut = (HWAVEOUT)_ao; 109 | WAVEHDR* current; 110 | current = &waveBlocks[waveCurrentBlock]; 111 | unsigned int i, k = 0, remain; 112 | int16_t *outbuf; 113 | while(size > 0) { 114 | /* 115 | * first make sure the header we're going to use is unprepared 116 | */ 117 | if(current->dwFlags & WHDR_PREPARED) 118 | waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR)); 119 | if(size < (size_t)((BLOCK_SIZE - current->dwUser) >> 1)) { 120 | //memcpy(current->lpData + current->dwUser, data, size); 121 | outbuf = (int16_t*)(current->lpData + current->dwUser); 122 | for (i = 0; i < size; i++) { 123 | outbuf[i] = data[i+k]; 124 | } 125 | current->dwUser += (size * sizeof(int16_t)); 126 | break; 127 | } 128 | remain = ((BLOCK_SIZE - current->dwUser) >> 1); 129 | outbuf = (int16_t*)(current->lpData + current->dwUser); 130 | //memcpy(current->lpData + current->dwUser, data, remain); 131 | for (i = 0; i < remain; i++) { 132 | outbuf[i] = data[i+k]; 133 | } 134 | size -= (remain >> 1); 135 | k += (remain >> 1); 136 | current->dwBufferLength = BLOCK_SIZE; 137 | waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR)); 138 | waveOutWrite(hWaveOut, current, sizeof(WAVEHDR)); 139 | InterlockedExchangeAdd(&waveFreeBlockCount, -1); 140 | 141 | while(!waveFreeBlockCount) { 142 | LARGE_INTEGER TimeOut; 143 | TimeOut.QuadPart = -1000000; 144 | NtDelayExecution(FALSE, &TimeOut); 145 | } 146 | 147 | waveCurrentBlock++; 148 | waveCurrentBlock %= BLOCK_COUNT; 149 | current = &waveBlocks[waveCurrentBlock]; 150 | current->dwUser = 0; 151 | } 152 | } 153 | 154 | void *audio_winmm_open(unsigned int *sfreq) { 155 | DWORD r = MMSYSERR_NOERROR; 156 | WAVEFORMATEX wfx; 157 | waveBlocks = allocateBlocks(BLOCK_SIZE, BLOCK_COUNT); 158 | waveFreeBlockCount = BLOCK_COUNT; 159 | waveCurrentBlock= 0; 160 | if(waveBlocks == NULL) { 161 | return NULL; 162 | } 163 | wfx.nSamplesPerSec = *sfreq; 164 | wfx.wBitsPerSample = 16; 165 | wfx.nChannels = 1; 166 | wfx.cbSize = 0; 167 | wfx.wFormatTag = WAVE_FORMAT_PCM; 168 | wfx.nBlockAlign = (wfx.wBitsPerSample * wfx.nChannels) >> 3; 169 | wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec; 170 | if ((r = waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, (DWORD_PTR)waveOutProc, (DWORD_PTR)&waveFreeBlockCount, CALLBACK_FUNCTION)) == MMSYSERR_NOERROR) { 171 | return &hWaveOut; 172 | } 173 | return NULL; 174 | } 175 | 176 | void audio_winmm_close(HWAVEOUT hWaveOut) { 177 | int i; 178 | while(waveFreeBlockCount < BLOCK_COUNT) { 179 | LARGE_INTEGER TimeOut; 180 | TimeOut.QuadPart = -1000000; 181 | NtDelayExecution(FALSE, &TimeOut); 182 | } 183 | 184 | for(i = 0; i < waveFreeBlockCount; i++) 185 | if(waveBlocks[i].dwFlags & WHDR_PREPARED) 186 | waveOutUnprepareHeader(hWaveOut, &waveBlocks[i], sizeof(WAVEHDR)); 187 | NtFreeVirtualMemory(((HANDLE)-1), (void**)&waveBlocks, 0, MEM_RELEASE); 188 | waveOutClose(hWaveOut); 189 | } 190 | 191 | -------------------------------------------------------------------------------- /md5.c: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * This code implements the MD5 message-digest algorithm. 3 | * The algorithm is due to Ron Rivest. This code was 4 | * written by Colin Plumb in 1993, no copyright is claimed. 5 | * This code is in the public domain; do with it what you wish. 6 | * 7 | * Equivalent code is available from RSA Data Security, Inc. 8 | * This code has been tested against that, and is equivalent, 9 | * except that you don't need to include two pages of legalese 10 | * with every copy. 11 | * 12 | * To compute the message digest of a chunk of bytes, declare an 13 | * MD5Context structure, pass it to MD5Init, call MD5Update as 14 | * needed on buffers full of bytes, and then call MD5Final, which 15 | * will fill a supplied 16-byte array with the digest. 16 | */ 17 | #include 18 | #include 19 | 20 | typedef struct { 21 | uint32_t buf[4]; 22 | uint32_t bytes[2]; 23 | uint32_t in[16]; 24 | } MD5_CTX; 25 | #define ROTATE(a,n) ({ register unsigned int ret; \ 26 | __asm__ volatile("roll %%cl,%0" \ 27 | : "=r"(ret) \ 28 | : "c"(n), "0"((unsigned int)(a)) \ 29 | : "cc"); ret; }) 30 | 31 | /*! 32 | * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious 33 | * initialization constants. 34 | */ 35 | void 36 | MD5Init(MD5_CTX *ctx) { 37 | ctx->buf[0] = 0x67452301; 38 | ctx->buf[1] = 0xefcdab89; 39 | ctx->buf[2] = 0x98badcfe; 40 | ctx->buf[3] = 0x10325476; 41 | 42 | ctx->bytes[0] = 0; 43 | ctx->bytes[1] = 0; 44 | } 45 | 46 | /*@{*/ 47 | /*! The four core functions - F1 is optimized somewhat */ 48 | 49 | /* #define F1(x, y, z) (x & y | ~x & z) */ 50 | #define F1(x, y, z) (z ^ (x & (y ^ z))) 51 | #define F2(x, y, z) F1(z, x, y) 52 | #define F3(x, y, z) (x ^ y ^ z) 53 | #define F4(x, y, z) (y ^ (x | ~z)) 54 | /*@}*/ 55 | 56 | /*! This is the central step in the MD5 algorithm. */ 57 | #define MD5STEP(f,w,x,y,z,in,s) \ 58 | (w += f(x,y,z) + in, w = (w<>(32-s)) + x) 59 | 60 | /*! 61 | * The core of the MD5 algorithm, this alters an existing MD5 hash to 62 | * reflect the addition of 16 longwords of new data. MD5Update blocks 63 | * the data and converts bytes into longwords for this routine. 64 | */ 65 | static void 66 | transform(uint32_t buf[4], uint32_t const in[16]) { 67 | register uint32_t a, b, c, d; 68 | 69 | a = buf[0]; 70 | b = buf[1]; 71 | c = buf[2]; 72 | d = buf[3]; 73 | 74 | MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); 75 | MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); 76 | MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); 77 | MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); 78 | MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); 79 | MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); 80 | MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); 81 | MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); 82 | MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); 83 | MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); 84 | MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); 85 | MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); 86 | MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); 87 | MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); 88 | MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); 89 | MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); 90 | 91 | MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); 92 | MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); 93 | MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); 94 | MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); 95 | MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); 96 | MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); 97 | MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); 98 | MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); 99 | MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); 100 | MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); 101 | MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); 102 | MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); 103 | MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); 104 | MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); 105 | MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); 106 | MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); 107 | 108 | MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); 109 | MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); 110 | MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); 111 | MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); 112 | MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); 113 | MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); 114 | MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); 115 | MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); 116 | MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); 117 | MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); 118 | MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); 119 | MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); 120 | MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); 121 | MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); 122 | MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); 123 | MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); 124 | 125 | MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); 126 | MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); 127 | MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); 128 | MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); 129 | MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); 130 | MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); 131 | MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); 132 | MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); 133 | MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); 134 | MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); 135 | MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); 136 | MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); 137 | MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); 138 | MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); 139 | MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); 140 | MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); 141 | 142 | buf[0] += a; 143 | buf[1] += b; 144 | buf[2] += c; 145 | buf[3] += d; 146 | } 147 | 148 | /*! 149 | * Update context to reflect the concatenation of another buffer full 150 | * of bytes. 151 | */ 152 | void 153 | MD5Update(MD5_CTX *ctx, const unsigned char *buf, unsigned int len) { 154 | uint32_t t; 155 | 156 | /* Update byte count */ 157 | 158 | t = ctx->bytes[0]; 159 | if ((ctx->bytes[0] = t + len) < t) 160 | ctx->bytes[1]++; /* Carry from low to high */ 161 | 162 | t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */ 163 | if (t > len) { 164 | memcpy((unsigned char *)ctx->in + 64 - t, buf, len); 165 | return; 166 | } 167 | /* First chunk is an odd size */ 168 | memcpy((unsigned char *)ctx->in + 64 - t, buf, t); 169 | transform(ctx->buf, ctx->in); 170 | buf += t; 171 | len -= t; 172 | 173 | /* Process data in 64-byte chunks */ 174 | while (len >= 64) { 175 | memcpy(ctx->in, buf, 64); 176 | transform(ctx->buf, ctx->in); 177 | buf += 64; 178 | len -= 64; 179 | } 180 | 181 | /* Handle any remaining bytes of data. */ 182 | memcpy(ctx->in, buf, len); 183 | } 184 | 185 | static inline void small_memset(void *addr, int c, size_t size) { 186 | unsigned int i; 187 | unsigned char *ptr = (unsigned char*)addr; 188 | for (i=0; ibytes[0] & 0x3f; /* Number of bytes in ctx->in */ 200 | unsigned char *p = (unsigned char *)ctx->in + count; 201 | 202 | /* Set the first char of padding to 0x80. There is always room. */ 203 | *p++ = 0x80; 204 | 205 | /* Bytes of padding needed to make 56 bytes (-8..55) */ 206 | count = 56 - 1 - count; 207 | 208 | if (count < 0) { /* Padding forces an extra block */ 209 | small_memset(p, 0, count + 8); 210 | transform(ctx->buf, ctx->in); 211 | p = (unsigned char *)ctx->in; 212 | count = 56; 213 | } 214 | small_memset(p, 0, count); 215 | 216 | /* Append length in bits and transform */ 217 | ctx->in[14] = ctx->bytes[0] << 3; 218 | ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29; 219 | transform(ctx->buf, ctx->in); 220 | memcpy(digest, ctx->buf, 16); 221 | } 222 | 223 | void MD5(unsigned char *dst, const unsigned char *src, unsigned int len) 224 | { 225 | MD5_CTX ctx; 226 | 227 | MD5Init(&ctx); 228 | MD5Update(&ctx, src, len); 229 | MD5Final(&ctx, dst); 230 | } 231 | 232 | -------------------------------------------------------------------------------- /pmd_play.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #if defined(WIN32) || defined(WIN64) 9 | #include 10 | #endif 11 | #include "pmdwin.h" 12 | #include "libaout/audio_out.h" 13 | 14 | #ifndef O_BINARY 15 | #define O_BINARY 0 16 | #endif 17 | 18 | static uint32_t atoui(const uint8_t *str) { 19 | uint32_t c, num = 0; 20 | while(1) { 21 | c = *str++ - 0x30; 22 | if(c > 9) break; 23 | num = (num << 1) + (num << 3) + c; 24 | } 25 | return num; 26 | } 27 | 28 | static inline unsigned int gethex(unsigned int c) { 29 | if ((c - 0x30) < 10) return c - 0x30; 30 | else return (c|0x20) - 'a' + 10; 31 | } 32 | 33 | static uint32_t atoui16(const uint8_t *str) { 34 | uint32_t c, num = 0; 35 | if (str[0] == '0' && ((str[1]|0x20) == 'x')) str += 2; 36 | while(1) { 37 | c = gethex(*str++); 38 | if(c > 15) break; 39 | num = (num << 4) + c; 40 | } 41 | return num; 42 | } 43 | 44 | static const unsigned char static_hdr_portion[20] = { 45 | 0x52, 0x49, 0x46, 0x46, 0xFF, 0xFF, 0xFF, 0x7F, 46 | 0x57, 0x41, 0x56, 0x45, 0x66, 0x6D, 0x74, 0x20, 47 | 0x10, 0x00, 0x00, 0x00 48 | }; 49 | 50 | typedef struct _WAVHeader { 51 | uint16_t wav_id; 52 | uint16_t channels; 53 | uint32_t samplerate; 54 | uint32_t bitrate; 55 | uint32_t block_align; 56 | uint32_t pad0; 57 | uint32_t pad1; 58 | } __attribute__((packed)) WAVHeader; 59 | 60 | static void write_wav_header(int fd, uint32_t rate) 61 | { 62 | WAVHeader w; 63 | write(fd, &static_hdr_portion, 20); 64 | 65 | w.wav_id = 1; 66 | w.channels = 1; 67 | w.samplerate = rate; 68 | w.bitrate = rate*2; 69 | w.block_align = 0x00100010; 70 | w.pad0 = 0x61746164; 71 | w.pad1 = 0x7fffffff; 72 | write(fd, &w, sizeof(WAVHeader)); 73 | } 74 | 75 | //============================================================================= 76 | // Load PMD data from file into memory. Uses mmap() on both Windows and *nix. 77 | // Originally in pmdwin.cpp, moved here to minimize platform-specific code 78 | // in pmdwin.cpp 79 | //============================================================================= 80 | #if defined(WIN32) || defined(WIN64) 81 | static NTSTATUS map_file(const wchar_t *filename, VOID **addr, SIZE_T *sz_ret) 82 | { 83 | OBJECT_ATTRIBUTES oa; 84 | UNICODE_STRING name; 85 | NTSTATUS r; 86 | HANDLE file, section; 87 | IO_STATUS_BLOCK iosb; 88 | LARGE_INTEGER ofs; 89 | SIZE_T sz; 90 | 91 | RtlDosPathNameToNtPathName_U(filename, &name, NULL, NULL); 92 | memset(&oa, 0, sizeof(oa)); 93 | oa.Length = sizeof(oa); 94 | oa.RootDirectory = NULL; 95 | oa.ObjectName = &name; 96 | oa.Attributes = OBJ_CASE_INSENSITIVE; 97 | 98 | r = NtOpenFile(&file, FILE_GENERIC_READ | 0x8F | SYNCHRONIZE, &oa, &iosb, 99 | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0); 100 | if (r != STATUS_SUCCESS) { 101 | return r; 102 | } 103 | 104 | memset(&oa, 0, sizeof(oa)); 105 | oa.Length = sizeof(oa); 106 | oa.RootDirectory = NULL; 107 | oa.ObjectName = NULL; 108 | oa.Attributes = OBJ_CASE_INSENSITIVE; 109 | 110 | section = NULL; 111 | r = NtCreateSection(§ion, SECTION_MAP_READ, &oa, 0, PAGE_READWRITE, SEC_COMMIT, file); 112 | if (r != STATUS_SUCCESS) { 113 | return r; 114 | } 115 | 116 | sz = 0; 117 | ofs.QuadPart = 0; 118 | r = NtMapViewOfSection(section, (HANDLE)-1, addr, 0, 0, &ofs, &sz, 1, 0, PAGE_READONLY); 119 | if (r != STATUS_SUCCESS) { 120 | return r; 121 | } 122 | 123 | if (sz_ret != NULL) { 124 | FILE_STANDARD_INFORMATION st; 125 | NtQueryInformationFile(file, &iosb, &st, sizeof(st), 5); // FileStandardInformation == 5 126 | *sz_ret = st.EndOfFile.QuadPart-1; 127 | } 128 | RtlFreeUnicodeString(&name); 129 | NtClose(section); 130 | NtClose(file); 131 | return r; 132 | } 133 | 134 | static int music_load(PMDWIN *pmd, wchar_t *filename) 135 | { 136 | int result; 137 | size_t size; 138 | uint8_t *musbuf; 139 | 140 | if (map_file(filename, (void**)&musbuf, &size) != NTSTATUS_SUCCESS) { 141 | return ERR_OPEN_MUSIC_FILE; 142 | } 143 | result = music_load3(pmd, musbuf, size); 144 | return result; 145 | } 146 | #else 147 | static int music_load(PMDWIN *pmd, char *filename) 148 | { 149 | struct stat st; 150 | int fd = -1; 151 | int result; 152 | size_t size; 153 | uint8_t musbuf[mdata_def*1024]; 154 | 155 | if((fd = open(filename, O_RDONLY)) < 0) { 156 | return ERR_OPEN_MUSIC_FILE; 157 | } 158 | 159 | fstat(fd, &st); 160 | size = st.st_size; 161 | read(fd, musbuf, size); 162 | close(fd); 163 | result = music_load3(pmd, musbuf, size); 164 | return result; 165 | } 166 | #endif 167 | 168 | #if defined(WIN32) || defined(WIN64) 169 | #define WriteToConsole(str, len) WriteFile(errh, (str), (len), &done, NULL) 170 | #else 171 | #define WriteToConsole(str, len) write(2, (str), (len)) 172 | #endif 173 | 174 | static void usage(void) { 175 | #if defined(WIN32) || defined(WIN64) 176 | DWORD done; 177 | HANDLE errh = GetStdHandle(STD_ERROR_HANDLE); 178 | #endif 179 | const char *usage_str = 180 | "pmdwin -f -l -m -c -t