#include #include #include int get1(FILE *fp) { return fgetc(fp); } int get2(FILE *fp) { int c1,c2; c1 = get1(fp); c2 = get1(fp); return ((c1<<8) | c2); } int get4(FILE *fp) { int c1,c2; c1 = get2(fp); c2 = get2(fp); return ((c1<<16) | c2); } int getn(FILE *fp, int n, char *p) { int i,c; for(i = 0; i < n; i++) { c = get1(fp); if (c == EOF) break; p[i] = (char)c; } for(c = i; c < n; c++) { p[c] = '\0'; } return i; } void skipn(FILE *fp, int n) { int c; int s = 3; if (n <= 0) return; //printf(" (%d)",n); while((c = get1(fp)) != EOF) { if (s > 0) { //printf(" %02X",c); s--; if (s == 0 && n > 1) { //printf(" ..."); } } n--; if (n <= 0) break; } //printf("\n"); } char *int_name(int id) { static char buf[256] = ""; int i; int c; for(i = 0; i < 4; i++) { c = (id >> (i*8)) & 0xFF; if (!isprint(c)) c = '?'; buf[3-i] = c; } buf[4] = '\0'; return buf; } void str_printable(char *str, int len) { int i; for(i = 0; i < len; i++) { if (str[i] == '\0') break; if (!isprint(str[i])) str[i] = '?'; } if (i == len) str[len] = '\0'; } void dump_head(FILE *fp, int left) { unsigned char buf[256]; int i; getn(fp,9,buf); left -= 9; printf(" Version ="); for(i = 0; i < 8; i++) { printf(" %02X",buf[i]); } printf("\n"); getn(fp,129,buf); left -= 129; str_printable(buf,128); printf(" Copyright = %s\n",buf); skipn(fp,left); } void dump_glob(FILE *fp, int left) { unsigned char buf[256]; int c; c = get1(fp); left--; printf(" PlayMode = %d\n",c); c = get1(fp); left--; printf(" Loop = %d\n",c); c = get4(fp); left -= 4; printf(" Tempo = %d.%03d\n",c/1000,c%1000); c = get4(fp); left -= 4; printf(" LoopStart = %d.%03d\n",c/768,c%768); c = get4(fp); left -= 4; printf(" LoopEnd = %d.%03d\n",c/768,c%768); c = get1(fp); left--; printf(" ShuffleAmount = %d\n",c); getn(fp,65,buf); left -= 65; str_printable(buf,64); printf(" Name_Mod = %s\n",buf); getn(fp,201,buf); left -= 201; str_printable(buf,200); printf(" FTP_Mod = %s\n",buf); getn(fp,201,buf); left -= 201; str_printable(buf,200); printf(" WWW_Mod = %s\n",buf); c = get1(fp); left--; printf(" VintageMode = %d\n",c); skipn(fp,left); } void dump_usri(FILE *fp, int left) { unsigned char buf[256]; int c; getn(fp,41,buf); left -= 41; str_printable(buf,40); printf(" WindowTitle = %s\n",buf); getn(fp,201,buf); left -= 201; str_printable(buf,200); printf(" SongInfo = %s\n",buf); getn(fp,101,buf); left -= 101; str_printable(buf,100); printf(" WebPage = %s\n",buf); c = get1(fp); left--; printf(" ShowInfoOnOpen = %d\n",c); skipn(fp,left); } char *pattern_name(int id) { static char buf[256] = ""; if (id >= 0 && id <= 31) { sprintf(buf,"%c%d", ('A'+id/8), (1+id%8)); }else{ sprintf(buf,"%d",id); } return buf; } char *compdev_name(int id) { static char buf[256] = ""; switch(id) { case 0: strcpy(buf,"none"); break; case 1: strcpy(buf,"master"); break; case 2: strcpy(buf,"303#1"); break; case 3: strcpy(buf,"303#2"); break; case 4: strcpy(buf,"808"); break; case 5: strcpy(buf,"909"); break; default: sprintf(buf,"%d",id); break; } return buf; } char *pcfdev_name(int id) { static char buf[256] = ""; switch(id) { case 0: strcpy(buf,"off"); break; case 1: strcpy(buf,"303#1"); break; case 2: strcpy(buf,"303#2"); break; case 3: strcpy(buf,"808"); break; case 4: strcpy(buf,"909"); break; default: sprintf(buf,"%d",id); break; } return buf; } char *delayunit_name(int id) { static char buf[256] = ""; switch(id) { case 0: strcpy(buf,"triplet"); break; case 1: strcpy(buf,"straight"); break; default: sprintf(buf,"%d",id); break; } return buf; } char *waveform_name(int id) { static char buf[256] = ""; switch(id) { case 0: strcpy(buf,"triangle"); break; case 1: strcpy(buf,"square"); break; default: sprintf(buf,"%d",id); break; } return buf; } char *value_name(int t, int id, int v) { static char buf[256] = ""; switch(t*100+id) { case 201: case 301: case 401: case 501: strcpy(buf,pattern_name(v)); break; case 101: strcpy(buf,compdev_name(v)); break; case 102: case 807: strcpy(buf,pcfdev_name(v)); break; case 208: case 308: strcpy(buf,waveform_name(v)); break; case 602: strcpy(buf,delayunit_name(v)); break; default: sprintf(buf,"%d",v); break; } return buf; } char *mix_name(int id) { static char buf[256] = ""; switch(id) { case 0: strcpy(buf,"mst-level"); break; case 1: strcpy(buf,"comp-dev"); break; case 2: strcpy(buf,"pcf-dev"); break; case 5: strcpy(buf,"303#1-mix"); break; case 6: strcpy(buf,"303#1-level"); break; case 7: strcpy(buf,"303#1-pan"); break; case 8: strcpy(buf,"303#1-delay"); break; case 9: strcpy(buf,"303#1-dist"); break; case 11: strcpy(buf,"303#2-mix"); break; case 12: strcpy(buf,"303#2-level"); break; case 13: strcpy(buf,"303#2-pan"); break; case 14: strcpy(buf,"303#2-delay"); break; case 15: strcpy(buf,"303#2-dist"); break; case 17: strcpy(buf,"808-mix"); break; case 18: strcpy(buf,"808-level"); break; case 19: strcpy(buf,"808-pan"); break; case 20: strcpy(buf,"808-delay"); break; case 21: strcpy(buf,"808-dist"); break; case 23: strcpy(buf,"909-mix"); break; case 24: strcpy(buf,"909-level"); break; case 25: strcpy(buf,"909-pan"); break; case 26: strcpy(buf,"909-delay"); break; case 27: strcpy(buf,"909-dist"); break; default: sprintf(buf,"(%d)",id); break; } return buf; } char *delay_name(int id) { static char buf[256] = ""; switch(id) { case 0: strcpy(buf,"enable"); break; case 1: strcpy(buf,"steps"); break; case 2: strcpy(buf,"unit"); break; case 3: strcpy(buf,"feedback"); break; case 4: strcpy(buf,"pan"); break; default: sprintf(buf,"(%d)",id); break; } return buf; } char *pcf_name(int id) { static char buf[256] = ""; switch(id) { case 0: strcpy(buf,"enable"); break; case 1: strcpy(buf,"freq"); break; case 2: strcpy(buf,"Q"); break; case 3: strcpy(buf,"amt"); break; case 4: strcpy(buf,"pattern"); break; case 5: strcpy(buf,"dec"); break; case 6: strcpy(buf,"BP/LP"); break; case 7: strcpy(buf,"pcf-dev"); break; default: sprintf(buf,"(%d)",id); break; } return buf; } char *dist_name(int id) { static char buf[256] = ""; switch(id) { case 0: strcpy(buf,"enable"); break; case 1: strcpy(buf,"amount"); break; case 2: strcpy(buf,"shape"); break; default: sprintf(buf,"(%d)",id); break; } return buf; } char *comp_name(int id) { static char buf[256] = ""; switch(id) { case 0: strcpy(buf,"enable"); break; case 1: strcpy(buf,"ratio"); break; case 2: strcpy(buf,"thres"); break; default: sprintf(buf,"(%d)",id); break; } return buf; } char *i303_name(int id) { static char buf[256] = ""; switch(id) { case 0: strcpy(buf,"enable"); break; case 1: strcpy(buf,"pattern"); break; case 2: strcpy(buf,"tune"); break; case 3: strcpy(buf,"cutoff"); break; case 4: strcpy(buf,"reso"); break; case 5: strcpy(buf,"envmod"); break; case 6: strcpy(buf,"decay"); break; case 7: strcpy(buf,"accent"); break; case 8: strcpy(buf,"waveform"); break; default: sprintf(buf,"(%d)",id); break; } return buf; } char *i808_name(int id) { static char buf[256] = ""; switch(id) { case 0: strcpy(buf,"enable"); break; case 1: strcpy(buf,"pattern"); break; case 2: strcpy(buf,"AC-level"); break; case 3: strcpy(buf,"BD-level"); break; case 4: strcpy(buf,"BD-tone"); break; case 5: strcpy(buf,"BD-decay"); break; case 6: strcpy(buf,"SD-level"); break; case 7: strcpy(buf,"SD-tune"); break; case 8: strcpy(buf,"SD-snapy"); break; case 9: strcpy(buf,"LT-level"); break; case 10: strcpy(buf,"LT-tune"); break; case 11: strcpy(buf,"LC/LT"); break; case 12: strcpy(buf,"MT-level"); break; case 13: strcpy(buf,"MT-tune"); break; case 14: strcpy(buf,"MC/MT"); break; case 15: strcpy(buf,"HT-level"); break; case 16: strcpy(buf,"HT-tune"); break; case 17: strcpy(buf,"HC/HT"); break; case 18: strcpy(buf,"RS-level"); break; case 19: strcpy(buf,"CL/RS"); break; case 20: strcpy(buf,"CP-level"); break; case 21: strcpy(buf,"MA/CP"); break; case 22: strcpy(buf,"CB-level"); break; case 23: strcpy(buf,"CY-level"); break; case 24: strcpy(buf,"CY-tone"); break; case 25: strcpy(buf,"CY-decay"); break; case 26: strcpy(buf,"OH-level"); break; case 27: strcpy(buf,"OH-decay"); break; case 28: strcpy(buf,"CH-level"); break; case 29: strcpy(buf,"(CY-tone)"); break; default: sprintf(buf,"(%d)",id); break; } return buf; } char *i909_name(int id) { static char buf[256] = ""; switch(id) { case 0: strcpy(buf,"enable"); break; case 1: strcpy(buf,"pattern"); break; case 2: strcpy(buf,"AC-level"); break; case 3: strcpy(buf,"BD-level"); break; case 4: strcpy(buf,"BD-tune"); break; case 5: strcpy(buf,"BD-attack"); break; case 6: strcpy(buf,"BD-decay"); break; case 7: strcpy(buf,"SD-level"); break; case 8: strcpy(buf,"SD-tune"); break; case 9: strcpy(buf,"SD-tone"); break; case 10: strcpy(buf,"SD-snapy"); break; case 11: strcpy(buf,"LT-level"); break; case 12: strcpy(buf,"LT-tune"); break; case 13: strcpy(buf,"LT-decay"); break; case 14: strcpy(buf,"MT-level"); break; case 15: strcpy(buf,"MT-tune"); break; case 16: strcpy(buf,"MT-decay"); break; case 17: strcpy(buf,"HT-level"); break; case 18: strcpy(buf,"HT-tune"); break; case 19: strcpy(buf,"HT-decay"); break; case 20: strcpy(buf,"RS-level"); break; case 21: strcpy(buf,"CP-level"); break; case 22: strcpy(buf,"HH-level"); break; case 23: strcpy(buf,"CH-decay"); break; case 24: strcpy(buf,"OH-decay"); break; case 25: strcpy(buf,"CC-level"); break; case 26: strcpy(buf,"CC-tune"); break; case 27: strcpy(buf,"RC-level"); break; case 28: strcpy(buf,"RC-tune"); break; case 29: strcpy(buf,"flam"); break; case 30: strcpy(buf,"(CC-level)"); break; default: sprintf(buf,"(%d)",id); break; } return buf; } char *tid_name(int tcount, int id) { static char buf[256] = ""; switch(tcount) { case 1: strcpy(buf,"mix."); strcat(buf,mix_name(id)); break; case 2: strcpy(buf,"303#1."); strcat(buf,i303_name(id)); break; case 3: strcpy(buf,"303#2."); strcat(buf,i303_name(id)); break; case 4: strcpy(buf,"808."); strcat(buf,i808_name(id)); break; case 5: strcpy(buf,"909."); strcat(buf,i909_name(id)); break; case 6: strcpy(buf,"delay."); strcat(buf,delay_name(id)); break; case 7: strcpy(buf,"dist."); strcat(buf,dist_name(id)); break; case 8: strcpy(buf,"pcf."); strcat(buf,pcf_name(id)); break; case 9: strcpy(buf,"comp."); strcat(buf,comp_name(id)); break; default: sprintf(buf,"(%d).(%d)",tcount,id); break; } return buf; } void dump_mixr(FILE *fp, int left) { int c,i; for(i = 0; i <= 2; i++) { c = get1(fp); left--; printf(" %s = %s\n",mix_name(i),value_name(1,i,c)); } skipn(fp,13); left -= 13; for(i = 5; i <= 9; i++) { c = get1(fp); left--; printf(" %s = %s\n",mix_name(i),value_name(1,i,c)); } skipn(fp,7); left -= 7; for(i = 11; i <= 15; i++) { c = get1(fp); left--; printf(" %s = %s\n",mix_name(i),value_name(1,i,c)); } skipn(fp,7); left -= 7; for(i = 17; i <= 21; i++) { c = get1(fp); left--; printf(" %s = %s\n",mix_name(i),value_name(1,i,c)); } skipn(fp,7); left -= 7; for(i = 23; i <= 27; i++) { c = get1(fp); left--; printf(" %s = %s\n",mix_name(i),value_name(1,i,c)); } skipn(fp,7); left -= 7; skipn(fp,left); } void dump_dely(FILE *fp, int left) { int c,i; for(i = 0; i < 5; i++) { c = get1(fp); left--; printf(" %s = %s\n",delay_name(i),value_name(6,i,c)); } skipn(fp,left); } void dump_pcf(FILE *fp, int left) { int c,i; for(i = 0; i < 8; i++) { c = get1(fp); left--; printf(" %s = %s\n",pcf_name(i),value_name(8,i,c)); } skipn(fp,left); } void dump_dist(FILE *fp, int left) { int c,i; for(i = 0; i < 3; i++) { c = get1(fp); left--; printf(" %s = %s\n",dist_name(i),value_name(7,i,c)); } skipn(fp,left); } void dump_comp(FILE *fp, int left) { int c,i; for(i = 0; i < 3; i++) { c = get1(fp); left--; printf(" %s = %s\n",comp_name(i),value_name(9,i,c)); } skipn(fp,left); } void dump_303(FILE *fp, int left) { int c,i,j,k; for(i = 0; i < 9; i++) { c = get1(fp); left--; printf(" %s = %s\n",i303_name(i),value_name(2,i,c)); } for(i = 0; i < 32; i++) { printf(" %s {\n",pattern_name(i)); c = get1(fp); left--; printf(" shuffle = %d\n",c); c = get1(fp); left--; printf(" length = %d\n",c); printf(" C_D_EF_G_A_BC_D_EF_G_A_BC_D_EF_G_A_BC\n"); for(j = 0; j < 16; j++) { c = get2(fp); left -= 2; printf(" [%02d] %04X ",j,c); k = (c>>8) & 0xFF; if ((c&0x04) != 0) c += (12<<8); if ((c&0x08) == 0) c += (12<<8); for(k = 0; k <= 36> 0; k++) { if (k == ((c>>8)&0xFF)) { switch(c&0x13) { case 0x00: putchar('o'); break; case 0x02: putchar('O'); break; case 0x01: putchar('s'); break; case 0x03: putchar('S'); break; case 0x11: putchar('='); break; default: putchar('.'); break; } }else if (k%12 == 0) { putchar('|'); }else{ putchar(' '); } } printf("\n"); } printf(" }\n"); } skipn(fp,left); } void dump_808(FILE *fp, int left) { int c,i,j,k; for(i = 0; i < 30; i++) { c = get1(fp); left--; printf(" %s = %s\n",i808_name(i),value_name(4,i,c)); } for(i = 0; i < 32; i++) { printf(" %s {\n",pattern_name(i)); c = get1(fp); left--; printf(" shuffle = %d\n",c); c = get1(fp); left--; printf(" length = %d\n",c); printf(" A B S L-M-H R P B Y O-C\n"); for(j = 0; j < 16; j++) { printf(" [%2d]",j); for(k = 0; k < 12; k++) { c = get1(fp); left--; switch(c) { case 0: printf(" ."); break; case 1: printf(" O"); break; default: printf(" %d",c); break; } } printf("\n"); } printf(" }\n"); } skipn(fp,left); } void dump_909(FILE *fp, int left) { int c,i,j,k; for(i = 0; i < 31; i++) { c = get1(fp); left--; printf(" %s = %s\n",i909_name(i),value_name(5,i,c)); } for(i = 0; i < 32; i++) { printf(" %s {\n",pattern_name(i)); c = get1(fp); left--; printf(" shuffle = %d\n",c); c = get1(fp); left--; printf(" length = %d\n",c); printf(" A B S L-M-H R P C-O c r\n"); for(j = 0; j < 16; j++) { printf(" [%2d]",j); for(k = 0; k < 12; k++) { c = get1(fp); left--; switch(c) { case 0: printf(" ."); break; case 1: printf(" o"); break; case 2: printf(" O"); break; case 3: printf(" F"); break; default: printf(" %d",c); break; } } printf("\n"); } printf(" }\n"); } skipn(fp,left); } void dump_trak(FILE *fp, int left, int tcount) { int i,n,c; int tm=0; int id,v; n = get4(fp); left -= 4; printf(" n = %d\n",n); if (left <= 0) return; for(i = 0; i < n; i++) { v = 0; do { c = get1(fp); left--; v <<= 7; v |= (c&0x7F); if (left <= 2) break; } while((c&0x80) != 0); tm += v; id = get1(fp); left--; v = get1(fp); left--; printf(" [%d] (%d.%d) %s = %s\n", i, tm/32, tm%32, tid_name(tcount,id), value_name(tcount,id,v)); if (left <= 0) break; } skipn(fp,left); } #define ID_CAT (('C'<<24)|('A'<<16)|('T'<<8)|' ') #define IC_RB40 (('R'<<24)|('B'<<16)|('4'<<8)|'0') #define ID_HEAD (('H'<<24)|('E'<<16)|('A'<<8)|'D') #define ID_GLOB (('G'<<24)|('L'<<16)|('O'<<8)|'B') #define ID_USRI (('U'<<24)|('S'<<16)|('R'<<8)|'I') #define ID_MIXR (('M'<<24)|('I'<<16)|('X'<<8)|'R') #define ID_DELY (('D'<<24)|('E'<<16)|('L'<<8)|'Y') #define ID_PCF (('P'<<24)|('C'<<16)|('F'<<8)|' ') #define ID_DIST (('D'<<24)|('I'<<16)|('S'<<8)|'T') #define ID_COMP (('C'<<24)|('O'<<16)|('M'<<8)|'P') #define ID_303 (('3'<<24)|('0'<<16)|('3'<<8)|' ') #define ID_808 (('8'<<24)|('0'<<16)|('8'<<8)|' ') #define ID_909 (('9'<<24)|('0'<<16)|('9'<<8)|' ') #define IC_TRKL (('T'<<24)|('R'<<16)|('K'<<8)|'L') #define ID_TRAK (('T'<<24)|('R'<<16)|('A'<<8)|'K') void sub(FILE *fp, int left) { int id; int size; int ctype; int i; int bcount = 0; int tcount = 0; while(left > 0) { id = get4(fp); left -= 4; if (left <= 0 || feof(fp)) break; size = get4(fp); left -= 4; if (left <= 0 || feof(fp)) break; if (size < 0 || size > left) { printf(" error!\n"); break; } switch(id) { case ID_CAT: ctype = get4(fp); printf(" [%d] {\n",int_name(ctype),size); sub(fp,size-4); printf("}\n"); break; case ID_HEAD: printf("<%s> [%d]\n",int_name(id),size); dump_head(fp,size); break; case ID_GLOB: printf("<%s> [%d]\n",int_name(id),size); dump_glob(fp,size); break; case ID_USRI: printf("<%s> [%d]\n",int_name(id),size); dump_usri(fp,size); break; case ID_MIXR: printf("<%s> [%d]\n",int_name(id),size); dump_mixr(fp,size); break; case ID_DELY: printf("<%s> [%d]\n",int_name(id),size); dump_dely(fp,size); break; case ID_PCF: printf("<%s> [%d]\n",int_name(id),size); dump_pcf(fp,size); break; case ID_DIST: printf("<%s> [%d]\n",int_name(id),size); dump_dist(fp,size); break; case ID_COMP: printf("<%s> [%d]\n",int_name(id),size); dump_comp(fp,size); break; case ID_303: bcount++; printf("<%s #%d> [%d]\n",int_name(id),bcount,size); dump_303(fp,size); break; case ID_808: printf("<%s> [%d]\n",int_name(id),size); dump_808(fp,size); break; case ID_909: printf("<%s> [%d]\n",int_name(id),size); dump_909(fp,size); break; case ID_TRAK: tcount++; printf("<%s #%d> [%d]\n",int_name(id),tcount,size); dump_trak(fp,size,tcount); break; default: printf("<%s> [%d]\n",int_name(id),size); for(i = 0; i < size; i++) { printf(" %02X",get1(fp)); } printf("\n"); break; } if (size%2 != 0) { fgetc(fp); left--; } left -= size; } } int main(int argc, char *argv[]) { FILE *fp = NULL; int size = 0; int i; if (argc < 2) { printf("rbsdump 1.0.0 by nshdot\n"); return 1; } for(i = 1; i < argc; i++) { fp = fopen(argv[i],"rb"); if (fp == NULL) { printf("file open error: %s\n",argv[i]); continue; } fseek(fp,0L,SEEK_END); size = ftell(fp); rewind(fp); printf("%s:\n",argv[i]); sub(fp,size); fclose(fp); fp = NULL; } return 0; }