| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785 |
- #define HL_NAME(n) fmt_##n
- #include <png.h>
- #include <hl.h>
- #if defined(HL_CONSOLE) && !defined(HL_XBO)
- extern bool sys_jpg_decode( vbyte *data, int dataLen, vbyte *out, int width, int height, int stride, int format, int flags );
- #else
- # include <turbojpeg.h>
- #endif
- #include <zlib.h>
- #include <vorbis/vorbisfile.h>
- #define MINIMP3_IMPLEMENTATION
- #define MINIMP3_FLOAT_OUTPUT
- #include <minimp3.h>
- /* ------------------------------------------------- IMG --------------------------------------------------- */
- typedef struct {
- unsigned char a,r,g,b;
- } pixel;
- HL_PRIM bool HL_NAME(jpg_decode)( vbyte *data, int dataLen, vbyte *out, int width, int height, int stride, int format, int flags ) {
- #if defined(HL_CONSOLE) && !defined(HL_XBO)
- hl_blocking(true);
- bool b = sys_jpg_decode(data, dataLen, out, width, height, stride, format, flags);
- hl_blocking(false);
- return b;
- #else
- hl_blocking(true);
- tjhandle h = tjInitDecompress();
- int result;
- result = tjDecompress2(h,data,dataLen,out,width,stride,height,format,(flags & 1 ? TJFLAG_BOTTOMUP : 0));
- tjDestroy(h);
- hl_blocking(false);
- return result == 0;
- #endif
- }
- HL_PRIM bool HL_NAME(png_decode)( vbyte *data, int dataLen, vbyte *out, int width, int height, int stride, int format, int flags ) {
- # ifdef PNG_IMAGE_VERSION
- png_image img;
- hl_blocking(true);
- memset(&img, 0, sizeof(img));
- img.version = PNG_IMAGE_VERSION;
- if( png_image_begin_read_from_memory(&img,data,dataLen) == 0 ) {
- hl_blocking(false);
- png_image_free(&img);
- return false;
- }
- switch( format ) {
- case 0:
- img.format = PNG_FORMAT_RGB;
- break;
- case 1:
- img.format = PNG_FORMAT_BGR;
- break;
- case 7:
- img.format = PNG_FORMAT_RGBA;
- break;
- case 8:
- img.format = PNG_FORMAT_BGRA;
- break;
- case 9:
- img.format = PNG_FORMAT_ABGR;
- break;
- case 10:
- img.format = PNG_FORMAT_ARGB;
- break;
- case 12:
- img.format = PNG_FORMAT_LINEAR_Y;
- break;
- case 13:
- img.format = PNG_FORMAT_LINEAR_RGB;
- break;
- case 14:
- img.format = PNG_FORMAT_LINEAR_RGB_ALPHA;
- break;
- default:
- hl_blocking(false);
- png_image_free(&img);
- hl_error("Unsupported format");
- break;
- }
- if( img.width != width || img.height != height ) {
- hl_blocking(false);
- png_image_free(&img);
- return false;
- }
- if( png_image_finish_read(&img,NULL,out,stride * (flags & 1 ? -1 : 1),NULL) == 0 ) {
- hl_blocking(false);
- png_image_free(&img);
- return false;
- }
- hl_blocking(false);
- png_image_free(&img);
- # else
- hl_error("PNG support is missing for this libPNG version");
- # endif
- return true;
- }
- HL_PRIM void HL_NAME(img_scale)( vbyte *out, int outPos, int outStride, int outWidth, int outHeight, vbyte *in, int inPos, int inStride, int inWidth, int inHeight, int flags ) {
- int x, y;
- float scaleX = outWidth <= 1 ? 0.0f : (float)((inWidth - 1.001f) / (outWidth - 1));
- float scaleY = outHeight <= 1 ? 0.0f : (float)((inHeight - 1.001f) / (outHeight - 1));
- out += outPos;
- in += inPos;
- hl_blocking(true);
- for(y=0;y<outHeight;y++) {
- for(x=0;x<outWidth;x++) {
- float fx = x * scaleX;
- float fy = y * scaleY;
- int ix = (int)fx;
- int iy = (int)fy;
- if( (flags & 1) == 0 ) {
- // nearest
- vbyte *rin = in + iy * inStride;
- *(pixel*)out = *(pixel*)(rin + (ix<<2));
- out += 4;
- } else {
- // bilinear
- float rx = fx - ix;
- float ry = fy - iy;
- float rx1 = 1.0f - rx;
- float ry1 = 1.0f - ry;
- int w1 = (int)(rx1 * ry1 * 256.0f);
- int w2 = (int)(rx * ry1 * 256.0f);
- int w3 = (int)(rx1 * ry * 256.0f);
- int w4 = (int)(rx * ry * 256.0f);
- vbyte *rin = in + iy * inStride;
- pixel p1 = *(pixel*)(rin + (ix<<2));
- pixel p2 = *(pixel*)(rin + ((ix + 1)<<2));
- pixel p3 = *(pixel*)(rin + inStride + (ix<<2));
- pixel p4 = *(pixel*)(rin + inStride + ((ix + 1)<<2));
- *out++ = (unsigned char)((p1.a * w1 + p2.a * w2 + p3.a * w3 + p4.a * w4 + 128)>>8);
- *out++ = (unsigned char)((p1.r * w1 + p2.r * w2 + p3.r * w3 + p4.r * w4 + 128)>>8);
- *out++ = (unsigned char)((p1.g * w1 + p2.g * w2 + p3.g * w3 + p4.g * w4 + 128)>>8);
- *out++ = (unsigned char)((p1.b * w1 + p2.b * w2 + p3.b * w3 + p4.b * w4 + 128)>>8);
- }
- }
- out += outStride - (outWidth << 2);
- }
- hl_blocking(false);
- }
- DEFINE_PRIM(_BOOL, jpg_decode, _BYTES _I32 _BYTES _I32 _I32 _I32 _I32 _I32);
- DEFINE_PRIM(_BOOL, png_decode, _BYTES _I32 _BYTES _I32 _I32 _I32 _I32 _I32);
- DEFINE_PRIM(_VOID, img_scale, _BYTES _I32 _I32 _I32 _I32 _BYTES _I32 _I32 _I32 _I32 _I32);
- /* ------------------------------------------------- ZLIB --------------------------------------------------- */
- typedef struct _fmt_zip fmt_zip;
- struct _fmt_zip {
- void (*finalize)( fmt_zip * );
- z_stream *z;
- int flush;
- bool inflate;
- };
- static void free_stream_inf( fmt_zip *v ) {
- if( v->inflate )
- inflateEnd(v->z); // no error
- else
- deflateEnd(v->z);
- free(v->z);
- v->z = NULL;
- v->finalize = NULL;
- }
- static void zlib_error( z_stream *z, int err ) {
- hl_buffer *b = hl_alloc_buffer();
- vdynamic *d;
- hl_buffer_cstr(b, "ZLib Error : ");
- if( z && z->msg ) {
- hl_buffer_cstr(b,z->msg);
- hl_buffer_cstr(b," (");
- }
- d = hl_alloc_dynamic(&hlt_i32);
- d->v.i = err;
- hl_buffer_val(b,d);
- if( z && z->msg )
- hl_buffer_char(b,')');
- d = hl_alloc_dynamic(&hlt_bytes);
- d->v.ptr = hl_buffer_content(b,NULL);
- hl_throw(d);
- }
- HL_PRIM fmt_zip *HL_NAME(inflate_init)( int wbits ) {
- z_stream *z;
- int err;
- fmt_zip *s;
- if( wbits == 0 )
- wbits = MAX_WBITS;
- z = (z_stream*)malloc(sizeof(z_stream));
- memset(z,0,sizeof(z_stream));
- if( (err = inflateInit2(z,wbits)) != Z_OK ) {
- free(z);
- zlib_error(NULL,err);
- }
- s = (fmt_zip*)hl_gc_alloc_finalizer(sizeof(fmt_zip));
- s->finalize = free_stream_inf;
- s->flush = Z_NO_FLUSH;
- s->z = z;
- s->inflate = true;
- return s;
- }
- HL_PRIM fmt_zip *HL_NAME(deflate_init)( int level ) {
- z_stream *z;
- int err;
- fmt_zip *s;
- z = (z_stream*)malloc(sizeof(z_stream));
- memset(z,0,sizeof(z_stream));
- if( (err = deflateInit(z,level)) != Z_OK ) {
- free(z);
- zlib_error(NULL,err);
- }
- s = (fmt_zip*)hl_gc_alloc_finalizer(sizeof(fmt_zip));
- s->finalize = free_stream_inf;
- s->flush = Z_NO_FLUSH;
- s->z = z;
- s->inflate = false;
- return s;
- }
- HL_PRIM void HL_NAME(zip_end)( fmt_zip *z ) {
- free_stream_inf(z);
- }
- HL_PRIM void HL_NAME(zip_flush_mode)( fmt_zip *z, int flush ) {
- switch( flush ) {
- case 0:
- z->flush = Z_NO_FLUSH;
- break;
- case 1:
- z->flush = Z_SYNC_FLUSH;
- break;
- case 2:
- z->flush = Z_FULL_FLUSH;
- break;
- case 3:
- z->flush = Z_FINISH;
- break;
- case 4:
- z->flush = Z_BLOCK;
- break;
- default:
- hl_error("Invalid flush mode %d",flush);
- break;
- }
- }
- HL_PRIM bool HL_NAME(inflate_buffer)( fmt_zip *zip, vbyte *src, int srcpos, int srclen, vbyte *dst, int dstpos, int dstlen, int *read, int *write ) {
- int slen, dlen, err;
- z_stream *z = zip->z;
- slen = srclen - srcpos;
- dlen = dstlen - dstpos;
- if( srcpos < 0 || dstpos < 0 || slen < 0 || dlen < 0 )
- hl_error("Out of range");
- hl_blocking(true);
- z->next_in = (Bytef*)(src + srcpos);
- z->next_out = (Bytef*)(dst + dstpos);
- z->avail_in = slen;
- z->avail_out = dlen;
- if( (err = inflate(z,zip->flush)) < 0 ) {
- hl_blocking(false);
- zlib_error(z,err);
- }
- z->next_in = NULL;
- z->next_out = NULL;
- *read = slen - z->avail_in;
- *write = dlen - z->avail_out;
- hl_blocking(false);
- return err == Z_STREAM_END;
- }
- HL_PRIM bool HL_NAME(deflate_buffer)( fmt_zip *zip, vbyte *src, int srcpos, int srclen, vbyte *dst, int dstpos, int dstlen, int *read, int *write ) {
- int slen, dlen, err;
- z_stream *z = zip->z;
- slen = srclen - srcpos;
- dlen = dstlen - dstpos;
- if( srcpos < 0 || dstpos < 0 || slen < 0 || dlen < 0 )
- hl_error("Out of range");
- hl_blocking(true);
- z->next_in = (Bytef*)(src + srcpos);
- z->next_out = (Bytef*)(dst + dstpos);
- z->avail_in = slen;
- z->avail_out = dlen;
- if( (err = deflate(z,zip->flush)) < 0 ) {
- hl_blocking(false);
- zlib_error(z,err);
- }
- z->next_in = NULL;
- z->next_out = NULL;
- *read = slen - z->avail_in;
- *write = dlen - z->avail_out;
- hl_blocking(false);
- return err == Z_STREAM_END;
- }
- HL_PRIM int HL_NAME(deflate_bound)( fmt_zip *zip, int size ) {
- return deflateBound(zip->z,size);
- }
- #define _ZIP _ABSTRACT(fmt_zip)
- DEFINE_PRIM(_ZIP, inflate_init, _I32);
- DEFINE_PRIM(_ZIP, deflate_init, _I32);
- DEFINE_PRIM(_I32, deflate_bound, _ZIP _I32);
- DEFINE_PRIM(_VOID, zip_end, _ZIP);
- DEFINE_PRIM(_VOID, zip_flush_mode, _ZIP _I32);
- DEFINE_PRIM(_BOOL, inflate_buffer, _ZIP _BYTES _I32 _I32 _BYTES _I32 _I32 _REF(_I32) _REF(_I32));
- DEFINE_PRIM(_BOOL, deflate_buffer, _ZIP _BYTES _I32 _I32 _BYTES _I32 _I32 _REF(_I32) _REF(_I32));
- /* ----------------------------------------------- SOUND : OGG ------------------------------------------------ */
- typedef struct _fmt_ogg fmt_ogg;
- struct _fmt_ogg {
- void (*finalize)( fmt_ogg * );
- OggVorbis_File f;
- char *bytes;
- int pos;
- int size;
- int section;
- };
- static void ogg_finalize( fmt_ogg *o ) {
- ov_clear(&o->f);
- }
- static size_t ogg_memread( void *ptr, int size, int count, fmt_ogg *o ) {
- int len = size * count;
- if( o->pos + len > o->size )
- len = o->size - o->pos;
- memcpy(ptr, o->bytes + o->pos, len);
- o->pos += len;
- return len;
- }
- static int ogg_memseek( fmt_ogg *o, ogg_int64_t _offset, int mode ) {
- int offset = (int)_offset;
- switch( mode ) {
- case SEEK_SET:
- if( offset < 0 || offset > o->size ) return 1;
- o->pos = offset;
- break;
- case SEEK_CUR:
- if( o->pos + offset < 0 || o->pos + offset > o->size ) return 1;
- o->pos += offset;
- break;
- case SEEK_END:
- if( offset < 0 || offset > o->size ) return 1;
- o->pos = o->size - offset;
- break;
- }
- return 0;
- }
- static long ogg_memtell( fmt_ogg *o ) {
- return o->pos;
- }
- static ov_callbacks OV_CALLBACKS_MEMORY = {
- (size_t (*)(void *, size_t, size_t, void *)) ogg_memread,
- (int (*)(void *, ogg_int64_t, int)) ogg_memseek,
- (int (*)(void *)) NULL,
- (long (*)(void *)) ogg_memtell
- };
- HL_PRIM fmt_ogg *HL_NAME(ogg_open)( char *bytes, int size ) {
- fmt_ogg *o = (fmt_ogg*)hl_gc_alloc_finalizer(sizeof(fmt_ogg));
- o->finalize = NULL;
- o->bytes = bytes;
- o->size = size;
- o->pos = 0;
- if( ov_open_callbacks(o,&o->f,NULL,0,OV_CALLBACKS_MEMORY) != 0 )
- return NULL;
- o->finalize = ogg_finalize;
- return o;
- }
- HL_PRIM void HL_NAME(ogg_info)( fmt_ogg *o, int *bitrate, int *freq, int *samples, int *channels ) {
- vorbis_info *i = ov_info(&o->f,-1);
- *bitrate = i->bitrate_nominal;
- *freq = i->rate;
- *channels = i->channels;
- *samples = (int)ov_pcm_total(&o->f, -1);
- }
- HL_PRIM int HL_NAME(ogg_tell)( fmt_ogg *o ) {
- return (int)ov_pcm_tell(&o->f); // overflow at 12 hours @48 Khz
- }
- HL_PRIM bool HL_NAME(ogg_seek)( fmt_ogg *o, int sample ) {
- return ov_pcm_seek(&o->f,sample) == 0;
- }
- #define OGGFMT_I8 1
- #define OGGFMT_I16 2
- //#define OGGFMT_F32 3
- #define OGGFMT_BIGENDIAN 128
- #define OGGFMT_UNSIGNED 256
- HL_PRIM int HL_NAME(ogg_read)( fmt_ogg *o, char *output, int size, int format ) {
- int ret = -1;
- hl_blocking(true);
- switch( format&127 ) {
- case OGGFMT_I8:
- case OGGFMT_I16:
- ret = ov_read(&o->f, output, size, (format & OGGFMT_BIGENDIAN) != 0, format&3, (format & OGGFMT_UNSIGNED) == 0, &o->section);
- break;
- // case OGGFMT_F32:
- // -- this decodes separates channels instead of mixed single buffer one
- // return ov_read_float(&o->f, output, size, (format & OGGFMT_BIGENDIAN) != 0, format&3, (format & OGGFMT_UNSIGNED) == 0, &o->section);
- default:
- break;
- }
- hl_blocking(false);
- return ret;
- }
- #define _OGG _ABSTRACT(fmt_ogg)
- DEFINE_PRIM(_OGG, ogg_open, _BYTES _I32);
- DEFINE_PRIM(_VOID, ogg_info, _OGG _REF(_I32) _REF(_I32) _REF(_I32) _REF(_I32));
- DEFINE_PRIM(_I32, ogg_tell, _OGG);
- DEFINE_PRIM(_BOOL, ogg_seek, _OGG _I32);
- DEFINE_PRIM(_I32, ogg_read, _OGG _BYTES _I32 _I32);
- /* ----------------------------------------------- SOUND : MP3 ------------------------------------------------ */
- typedef struct _fmt_mp3 fmt_mp3;
- struct _fmt_mp3 {
- mp3dec_t dec;
- mp3dec_frame_info_t info;
- mp3d_sample_t pcm[MINIMP3_MAX_SAMPLES_PER_FRAME];
- };
- // Allocate MP3 reader.
- HL_PRIM fmt_mp3 *HL_NAME(mp3_open)() {
- fmt_mp3 *o = (fmt_mp3*)hl_gc_alloc_noptr(sizeof(fmt_mp3));
- mp3dec_init(&o->dec);
- return o;
- }
- /**
- Retreive last decoded frame information.
- @param bitrate_kbps Bitrate of the frame
- @param channels Total amount of channels in the frame.
- @param frame_bytes The size of the frame in the input stream,
- @param hz
- @param layer Mpeg Layer index (usually 3).
- **/
- HL_PRIM void HL_NAME(mp3_frame_info)(fmt_mp3 *o, int *bitrate_kbps, int *channels, int *frame_bytes, int *hz, int *layer) {
- *bitrate_kbps = o->info.bitrate_kbps;
- *channels = o->info.channels;
- *frame_bytes = o->info.frame_bytes;
- *hz = o->info.hz;
- *layer = o->info.layer;
- }
- /**
- Decodes a single frame from input stream and writes result to output.
- Decoded samples are in Float32 format. Output bytes should contain enough space to fit entire frame in.
- To calculate required output size, follow next formula: `samples * channels * 4`.
- For Layer 1, amount of frames is 384, MPEG 2 Layer 2 is 576 and 1152 otherwise. Using 1152 samples is the safest.
- @param o Allocated MP3 reader.
- @param bytes Input stream.
- @param size Input stream size.
- @param position Input stream offset.
- @param output Output stream.
- @param outputSize Output stream size.
- @param offset Output stream write offset.
- @returns 0 if no MP3 data was found (end of stream/invalid data), -1 if either input buffer position invalid or output size is insufficent.
- Amount of decoded samples otherwise.
- **/
- HL_PRIM int HL_NAME(mp3_decode_frame)( fmt_mp3 *o, char *bytes, int size, int position, char *output, int outputSize, int offset ) {
- // Out of mp3 file bounds.
- if ( position < 0 || size <= position )
- return -1;
- int samples = 0;
- hl_blocking(true);
- do {
- samples = mp3dec_decode_frame(&o->dec, (unsigned char*)bytes + position, size - position, o->pcm, &o->info);
- // Try to read until found mp3 data or EOF.
- if ( samples != 0 || o->info.frame_bytes == 0 )
- break;
- position += o->info.frame_bytes;
- } while ( size > position );
- // No or invalid MP3 data.
- if ( samples == 0 || o->info.frame_bytes == 0 ) {
- hl_blocking(false);
- return 0;
- }
- int decodedSize = samples * o->info.channels * sizeof(mp3d_sample_t);
- // Insufficent output buffer size.
- if ( outputSize - offset < decodedSize ) {
- hl_blocking(false);
- return -1;
- }
- memcpy( (void *)(output + offset), (void *)o->pcm, decodedSize );
- hl_blocking(false);
- return samples;
- }
- #define _MP3 _ABSTRACT(fmt_mp3)
- DEFINE_PRIM(_MP3, mp3_open, _BYTES _I32);
- DEFINE_PRIM(_VOID, mp3_frame_info, _MP3 _REF(_I32) _REF(_I32) _REF(_I32) _REF(_I32) _REF(_I32))
- DEFINE_PRIM(_I32, mp3_decode_frame, _MP3 _BYTES _I32 _I32 _BYTES _I32 _I32);
- /* ------------------------------------------------- CRYPTO --------------------------------------------------- */
- typedef unsigned int uint32;
- typedef unsigned char uint8;
- typedef struct {
- uint32 total[2];
- uint32 state[4];
- uint8 buffer[64];
- } md5_context;
- #define GET_UINT32(n,b,i) \
- { \
- (n) = ( (uint32) (b)[(i) ] ) \
- | ( (uint32) (b)[(i) + 1] << 8 ) \
- | ( (uint32) (b)[(i) + 2] << 16 ) \
- | ( (uint32) (b)[(i) + 3] << 24 ); \
- }
- #define PUT_UINT32(n,b,i) \
- { \
- (b)[(i) ] = (uint8) ( (n) ); \
- (b)[(i) + 1] = (uint8) ( (n) >> 8 ); \
- (b)[(i) + 2] = (uint8) ( (n) >> 16 ); \
- (b)[(i) + 3] = (uint8) ( (n) >> 24 ); \
- }
- static void md5_starts( md5_context *ctx ) {
- ctx->total[0] = 0;
- ctx->total[1] = 0;
- ctx->state[0] = 0x67452301;
- ctx->state[1] = 0xEFCDAB89;
- ctx->state[2] = 0x98BADCFE;
- ctx->state[3] = 0x10325476;
- }
- static void md5_process( md5_context *ctx, uint8 data[64] ) {
- uint32 X[16], A, B, C, D;
- GET_UINT32( X[0], data, 0 );
- GET_UINT32( X[1], data, 4 );
- GET_UINT32( X[2], data, 8 );
- GET_UINT32( X[3], data, 12 );
- GET_UINT32( X[4], data, 16 );
- GET_UINT32( X[5], data, 20 );
- GET_UINT32( X[6], data, 24 );
- GET_UINT32( X[7], data, 28 );
- GET_UINT32( X[8], data, 32 );
- GET_UINT32( X[9], data, 36 );
- GET_UINT32( X[10], data, 40 );
- GET_UINT32( X[11], data, 44 );
- GET_UINT32( X[12], data, 48 );
- GET_UINT32( X[13], data, 52 );
- GET_UINT32( X[14], data, 56 );
- GET_UINT32( X[15], data, 60 );
- #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
- #define P(a,b,c,d,k,s,t) \
- { \
- a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
- }
- A = ctx->state[0];
- B = ctx->state[1];
- C = ctx->state[2];
- D = ctx->state[3];
- #define F(x,y,z) (z ^ (x & (y ^ z)))
- P( A, B, C, D, 0, 7, 0xD76AA478 );
- P( D, A, B, C, 1, 12, 0xE8C7B756 );
- P( C, D, A, B, 2, 17, 0x242070DB );
- P( B, C, D, A, 3, 22, 0xC1BDCEEE );
- P( A, B, C, D, 4, 7, 0xF57C0FAF );
- P( D, A, B, C, 5, 12, 0x4787C62A );
- P( C, D, A, B, 6, 17, 0xA8304613 );
- P( B, C, D, A, 7, 22, 0xFD469501 );
- P( A, B, C, D, 8, 7, 0x698098D8 );
- P( D, A, B, C, 9, 12, 0x8B44F7AF );
- P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
- P( B, C, D, A, 11, 22, 0x895CD7BE );
- P( A, B, C, D, 12, 7, 0x6B901122 );
- P( D, A, B, C, 13, 12, 0xFD987193 );
- P( C, D, A, B, 14, 17, 0xA679438E );
- P( B, C, D, A, 15, 22, 0x49B40821 );
- #undef F
- #define F(x,y,z) (y ^ (z & (x ^ y)))
- P( A, B, C, D, 1, 5, 0xF61E2562 );
- P( D, A, B, C, 6, 9, 0xC040B340 );
- P( C, D, A, B, 11, 14, 0x265E5A51 );
- P( B, C, D, A, 0, 20, 0xE9B6C7AA );
- P( A, B, C, D, 5, 5, 0xD62F105D );
- P( D, A, B, C, 10, 9, 0x02441453 );
- P( C, D, A, B, 15, 14, 0xD8A1E681 );
- P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
- P( A, B, C, D, 9, 5, 0x21E1CDE6 );
- P( D, A, B, C, 14, 9, 0xC33707D6 );
- P( C, D, A, B, 3, 14, 0xF4D50D87 );
- P( B, C, D, A, 8, 20, 0x455A14ED );
- P( A, B, C, D, 13, 5, 0xA9E3E905 );
- P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
- P( C, D, A, B, 7, 14, 0x676F02D9 );
- P( B, C, D, A, 12, 20, 0x8D2A4C8A );
- #undef F
-
- #define F(x,y,z) (x ^ y ^ z)
- P( A, B, C, D, 5, 4, 0xFFFA3942 );
- P( D, A, B, C, 8, 11, 0x8771F681 );
- P( C, D, A, B, 11, 16, 0x6D9D6122 );
- P( B, C, D, A, 14, 23, 0xFDE5380C );
- P( A, B, C, D, 1, 4, 0xA4BEEA44 );
- P( D, A, B, C, 4, 11, 0x4BDECFA9 );
- P( C, D, A, B, 7, 16, 0xF6BB4B60 );
- P( B, C, D, A, 10, 23, 0xBEBFBC70 );
- P( A, B, C, D, 13, 4, 0x289B7EC6 );
- P( D, A, B, C, 0, 11, 0xEAA127FA );
- P( C, D, A, B, 3, 16, 0xD4EF3085 );
- P( B, C, D, A, 6, 23, 0x04881D05 );
- P( A, B, C, D, 9, 4, 0xD9D4D039 );
- P( D, A, B, C, 12, 11, 0xE6DB99E5 );
- P( C, D, A, B, 15, 16, 0x1FA27CF8 );
- P( B, C, D, A, 2, 23, 0xC4AC5665 );
- #undef F
- #define F(x,y,z) (y ^ (x | ~z))
- P( A, B, C, D, 0, 6, 0xF4292244 );
- P( D, A, B, C, 7, 10, 0x432AFF97 );
- P( C, D, A, B, 14, 15, 0xAB9423A7 );
- P( B, C, D, A, 5, 21, 0xFC93A039 );
- P( A, B, C, D, 12, 6, 0x655B59C3 );
- P( D, A, B, C, 3, 10, 0x8F0CCC92 );
- P( C, D, A, B, 10, 15, 0xFFEFF47D );
- P( B, C, D, A, 1, 21, 0x85845DD1 );
- P( A, B, C, D, 8, 6, 0x6FA87E4F );
- P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
- P( C, D, A, B, 6, 15, 0xA3014314 );
- P( B, C, D, A, 13, 21, 0x4E0811A1 );
- P( A, B, C, D, 4, 6, 0xF7537E82 );
- P( D, A, B, C, 11, 10, 0xBD3AF235 );
- P( C, D, A, B, 2, 15, 0x2AD7D2BB );
- P( B, C, D, A, 9, 21, 0xEB86D391 );
- #undef F
- ctx->state[0] += A;
- ctx->state[1] += B;
- ctx->state[2] += C;
- ctx->state[3] += D;
- }
- static void md5_update( md5_context *ctx, uint8 *input, uint32 length ) {
- uint32 left, fill;
- if( !length )
- return;
- left = ctx->total[0] & 0x3F;
- fill = 64 - left;
- ctx->total[0] += length;
- ctx->total[0] &= 0xFFFFFFFF;
- if( ctx->total[0] < length )
- ctx->total[1]++;
- if( left && length >= fill ) {
- memcpy( (void *) (ctx->buffer + left),
- (void *) input, fill );
- md5_process( ctx, ctx->buffer );
- length -= fill;
- input += fill;
- left = 0;
- }
- while( length >= 64 ) {
- md5_process( ctx, input );
- length -= 64;
- input += 64;
- }
- if( length ) {
- memcpy( (void *) (ctx->buffer + left),
- (void *) input, length );
- }
- }
- static uint8 md5_padding[64] =
- {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- static void md5_finish( md5_context *ctx, uint8 digest[16] ) {
- uint32 last, padn;
- uint32 high, low;
- uint8 msglen[8];
- high = ( ctx->total[0] >> 29 )
- | ( ctx->total[1] << 3 );
- low = ( ctx->total[0] << 3 );
- PUT_UINT32( low, msglen, 0 );
- PUT_UINT32( high, msglen, 4 );
- last = ctx->total[0] & 0x3F;
- padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
- md5_update( ctx, md5_padding, padn );
- md5_update( ctx, msglen, 8 );
- PUT_UINT32( ctx->state[0], digest, 0 );
- PUT_UINT32( ctx->state[1], digest, 4 );
- PUT_UINT32( ctx->state[2], digest, 8 );
- PUT_UINT32( ctx->state[3], digest, 12 );
- }
- #include "sha1.h"
- HL_PRIM void HL_NAME(digest)( vbyte *out, vbyte *in, int length, int format ) {
- if( format & 256 ) {
- in = (vbyte*)hl_to_utf8((uchar*)in);
- length = (int)strlen((char*)in);
- }
- hl_blocking(true);
- switch( format & 0xFF ) {
- case 0:
- {
- md5_context ctx;
- md5_starts(&ctx);
- md5_update(&ctx,in,(uint32)length);
- md5_finish(&ctx,out);
- }
- break;
- case 1:
- {
- SHA1_CTX ctx;
- sha1_init(&ctx);
- sha1_update(&ctx,in,length);
- sha1_final(&ctx,out);
- }
- break;
- case 2:
- *((int*)out) = crc32(*(int*)out, in, length);
- break;
- case 3:
- *((int*)out) = adler32(*(int*)out, in, length);
- break;
- default:
- hl_blocking(false);
- hl_error("Unknown digest format %d",format&0xFF);
- break;
- }
- hl_blocking(false);
- }
- DEFINE_PRIM(_VOID, digest, _BYTES _BYTES _I32 _I32);
|