From 505cc59d0eb8835d3cb3f8c9f4f6cc9281c05fd2 Mon Sep 17 00:00:00 2001 From: mothcompute Date: Thu, 28 Jul 2022 21:01:51 -0700 Subject: [PATCH] stuff --- getmod | 101 +++++++++++++++++++++++++++++++++++++++++++++ s3mstrip.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 220 insertions(+) create mode 100755 getmod create mode 100644 s3mstrip.c diff --git a/getmod b/getmod new file mode 100755 index 0000000..acbffe1 --- /dev/null +++ b/getmod @@ -0,0 +1,101 @@ +#!/bin/sh + +# _ _ +# | | | | +# _____ _____ _| |_ ____ ____ _____ ___| | +# / _ \/ ____|_ _| _ V _ | _ | _ | +# | |_| | ___ | | | | | | | | |_| | |_| | +# \___ |\_____| |_| |_| |_| |_|_____|_____| +# __| | _________________________________ +# |___/ --------------------------------- +# _ _ _ _ +# | |_| | | | | | _ +# | |-| |___ ____ ____ _____ ___| |_____ ___________| |___|-| _ _ _____ +# | | | _ | _ V _ | _ | _ | _ | ___| ___| _ | |\ \/ / ____| +# | | | |_| | | | | | | |_| | |_| | |_| | | | |___| | | | | \ / ___ +# |_|_|_____|_| |_| |_|_____|_____|____/\_| |_____|_| |_|_| \/ \_____| + +# a simple program (and somewhat of a library) to download modules from the +# mod archive. provide a filename as the first argument, and a search method +# (if you want) as the second (see getmodid() for details). by mothcompute. +# public domain as always. part of https://github.com/mothcompute/stuff + +# on bsds you may need to make this `gsed` +SED=sed + +# `penc` takes a single string on argv[1] and outputs +# its percent-encoded version, followed by a newline, +# unless argv[1] is '-p', in which case ' ' is encoded +# as '+'. here is my implementation: +# int main(int a,char**v){if(a<2)exit(1);int i=0,c;if((a>2)&&!(i=(*((short*)v[1])==28717)))exit(1);while(c=*(v[1+i]++)){if(i&&c==32){c=43;goto p;}if((!((c^32)>>4)&&c!=34&&c!=45&&c!=46)||(c==58||c==59||c==61||c==63||c==64||c==91||c==93))printf("%%%02X",c);else p:putchar(c);}putchar(10);} +PENC=penc + +PLAYER() { + which xmp > /dev/null || exit + xmp -l $@ +} + +which $SED > /dev/null || exit +which $PENC > /dev/null || exit + +# lma_getid(): returns module id +# $1 : song or filename +# $2 OPTIONAL : search type +# possible values for $2: +true DEFAULT: 'filename_or_songtitle' \ + 'filename' \ + 'module_instruments' \ + 'filename_and_songtitle' \ + 'songtitle' \ + 'module_comments' +lma_getid() { + SEARCHTYPE='filename_or_songtitle' + [ ! -z "$2" ] && SEARCHTYPE=$2 + + curl -s "https://modarchive.org/index.php?request=search&submit=Find&search_type=$SEARCHTYPE&query=$($PENC -p "$1")" | $SED 's/?/ /g;s/ /\n/g' | grep moduleid= | $SED 's/#.*//;s/moduleid=//g' | xargs | awk '{print $1}' +} + +# lma_getname(): returns filename of module +# $1 : module id +lma_getname() { + curl -s "https://modarchive.org/index.php?request=view_by_moduleid&query=$1" | $SED 's/span/\n/g' | grep module-sub-header | $SED 's/).*//;s/.*(//' +} + +lma_int_gmi() { + curl -s "https://modarchive.org/index.php?request=view_by_moduleid&query=$1" | grep -A 8 Info | grep li | grep -v 'ul class=' | $SED "s/
  • //g;s/<\/li>//g;s//$(printf '\033')[1m/g;s/<\/b>/$(printf '\033')[0m/g" | grep -v , | $SED 's/ //g;s/times//g;s/:/ /g;s/ModArchive//g' +} + +# lma_getinfo(): gets various information on module +# $1 : module id +# $2 OPTIONAL : search term. if not specified, prints all in 'key value' format +# possible values for $2: +true 'ID' \ + 'Downloads' \ + 'Favourited' \ + 'MD5' \ + 'Format' \ + 'Channels' \ + 'UncompressedSize' +lma_getinfo() { + exp() { + cat + } + [ ! -z "$2" ] && exp() { + grep $1 | awk '{print $2}' + } + lma_int_gmi "$1" | exp $2 +} + +# lma_getlink(): returns download link to module file +# $1 : module id +lma_getlink() { + echo "https://api.modarchive.org/downloads.php?moduleid=$1" +} + +# this serves as a fairly good example of using it as a library +fetchid=$(lma_getid "$1" "$2") +fetchname=$(lma_getname $fetchid) +echo $fetchname +lma_getinfo $fetchid +wget -q "$(lma_getlink $fetchid)" -nv -O "$fetchname" +PLAYER "$fetchname" diff --git a/s3mstrip.c b/s3mstrip.c new file mode 100644 index 0000000..09ed72e --- /dev/null +++ b/s3mstrip.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include + +#define mem16 ((uint16_t*)mem) +#define memhdr ((mhdr*)mem) + +typedef struct { + char title[28]; + uint16_t sig; // 0x101A + uint16_t rsv0; + uint16_t num_orders; + uint16_t num_inst; + uint16_t num_pat; + uint16_t flags; + uint16_t tracker; + uint16_t sampletype; + uint32_t SCRM; + uint8_t global_volume; + uint8_t init_speed; + uint8_t init_tempo; + uint8_t master_volume; + uint8_t gus_click; + uint8_t pan; + uint8_t rsv1[8]; + uint16_t ext; + uint8_t chn_settings[32]; +} __attribute__((packed)) mhdr; + +typedef struct { + uint8_t type; + uint8_t name[12]; +} __attribute__((packed)) inst_stub; + +typedef struct { + uint8_t type; + uint8_t name[12]; + uint8_t ptr_h; + uint16_t ptr_l; + uint32_t len; + uint32_t lpstart; + uint32_t lpend; + uint8_t volume; + uint8_t rsv0; + uint8_t pack; + uint8_t flags; + uint32_t c2spd; + uint8_t rsv1[12]; + uint8_t title[28]; + uint32_t SCRS; +} __attribute__((packed)) inst_pcm; + +typedef struct { + uint8_t type; + uint8_t name[12]; + uint8_t rsv0[3]; + uint8_t opl[12]; + uint8_t volume; + uint8_t unknown_i_fuckin_guess; + uint16_t rsv1; + uint32_t c2spd; + uint8_t rsv2[12]; + uint8_t title[28]; + uint32_t SCRI; +} __attribute__((packed)) inst_adl; + +int main(int argc, char** argv) { + if(argc ^ 3) return printf("need [in] [out]\n"); + int ifd, ofd; + if( + ((ifd = open(argv[1], O_RDWR)) < 0) | + ((ofd = open(argv[2], O_RDWR|O_CREAT, 0644)) < 0) + ) { + f: return printf("error opening files (%i %i)\n", ifd, ofd); + } + unsigned long hdat = 0; + struct stat s; + fstat(ifd, &s); + uint8_t* mem; + if((mem = mmap(0, s.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0)) == MAP_FAILED) goto f; + + if(memhdr->flags & 0x80) hdat = ((int)memhdr->ext) << 4; + uint16_t* t = (uint16_t*)(mem + sizeof(mhdr) + memhdr->num_orders); + + for(int i = 0; i < memhdr->num_inst; i++) { + uint32_t a = ((int)*(t++)) << 4; + printf("sample at offset %X\n", a); + inst_stub* ca = mem + a; + if(!(ca->type & (~7))) { + if(!ca->type && a+sizeof(inst_stub) > hdat) hdat = a+sizeof(inst_stub); + else if(!(ca->type^1)) { + inst_pcm* p = ca; + if(a+sizeof(inst_pcm) > hdat) hdat = a+sizeof(inst_pcm); + long conptr = p->ptr_h; + conptr = (((conptr << 16) | p->ptr_l) << 4); + printf("calculated conptr: %lX\n", conptr); + conptr += ((p->len << ((p->flags & 2) >> 1)) << ((p->flags & 4) >> 2)); + printf("calculated sz: %lX\n", ((p->len << ((p->flags & 2) >> 1)) << ((p->flags & 4) >> 2))); + if(conptr > hdat) hdat = conptr; + } else if(a+sizeof(inst_adl) > hdat) hdat = a+sizeof(inst_adl); + } + } + + for(int i = 0; i < memhdr->num_pat; i++) { + uint32_t a = ((int)*(t++)) << 4; + printf("pat at %X\n", a); + if(*((uint16_t*)(mem + a)) + a > hdat) hdat = *((uint16_t*)(mem + a)) + a; + printf("pat sz %hX\n", *((uint16_t*)(mem + a))); + } + + write(ofd, mem, hdat); + ftruncate(ofd, hdat); + munmap(mem, s.st_size); + close(ifd); + close(ofd); +}