#include #include #include "../libmodplay/modplay.h" #include "adpcm.h" unsigned char *mod_data; ModMusic *mod; // Container format // Header // 8 bytes - "_mod4psx" // 4 bytes - Number of samples contained // Sample format // 4 bytes - Length of ADPCM sample // 8 bytes - Reserved // ... Data ... // All multi word numerical values are in little endian format // which is used by the processor of the PlayStation. // All data is aligned to 4 bytes. unsigned char adpcm_buffer[0x10000]; int main(int argc, char *argv[]) { FILE *f; int sz, x,y; if(argc < 3) { printf("mod4psx \n"); printf( "\nMOD4PSX gets the sound samples from a music module supported by libmodplay, " "and then converts them to PS1 ADPCM format and puts them all in a datafile, which will be able to be loaded " "by libmodplay. In this way the CPU time needed by the PlayStation processor to convert at runtime from PCM to ADPCM is saved.\n" ); return -1; } f = fopen(argv[1], "rb"); if(f == NULL) { printf("Could not open %s for reading. Aborting.\n", argv[1]); return -1; } fseek(f, 0, SEEK_END); sz = ftell(f); fseek(f, 0, SEEK_SET); mod_data = malloc(sz); if(mod_data == NULL) { printf("Could not allocate %d bytes of memory. Aborting.\n", sz); return -1; } fread(mod_data, sizeof(char), sz, f); fclose(f); mod = MODLoad(mod_data); printf("Title: %s\n", mod->title); f = fopen(argv[2], "wb"); // Write header // Magic string fprintf(f, "_mod4psx"); // Write number of samples fputc(mod->sample_num & 0xff, f); fputc((mod->sample_num >> 8) & 0xff, f); fputc(0, f); fputc(0, f); for(x = 0; x < mod->sample_num; x++) { //printf("%d: %s\n", x, mod->sample[x].name); printf("sample[%d].bits = %d, sample[%d].data_type = %d\n", x, mod->sample[x].bits, x, mod->sample[x].data_type); if(mod->sample[x].length >= 32) { if((mod->sample[x].data_type & 1) && mod->sample[x].bits == 8) { for(y = 0; y < mod->sample[x].length; y++) mod->sample[x].data[y]^=0x80; } if(//mod->fmt == MOD_FMT_MOD && mod->sample[x].repeat_len > 2) { sz = SsAdpcmPack(mod->sample[x].data, adpcm_buffer, // FIX THIS!!! mod->sample[x].length / (mod->sample[x].bits / 8), (mod->sample[x].bits==16)?FMT_S16:FMT_U8, sizeof(adpcm_buffer), 1, mod->sample[x].repeat_off); } else { sz = SsAdpcmPack(mod->sample[x].data, adpcm_buffer, mod->sample[x].length / (mod->sample[x].bits / 8), (mod->sample[x].bits==16)?FMT_S16:FMT_U8, sizeof(adpcm_buffer), 0, 0); } printf("%d) %s, %d -> %d, %d, %d, FIN=%d\n", x, mod->sample[x].name, mod->sample[x].length, sz, mod->sample[x].repeat_off, mod->sample[x].repeat_len, mod->sample[x].finetune); } else { printf("%d) %s, Not written\n", x, mod->sample[x].name); sz = 0; } // Write length of ADPCM sample fputc(sz & 0xff, f); fputc((sz>>8)&0xff, f); fputc((sz>>16)&0xff, f); fputc((sz>>24)&0xff, f); // Skip 8 reserved bytes - for future expansion... fseek(f, 8, SEEK_CUR); // Write ADPCM sample data // Manipulate the samples to do looping for Protracker MOD samples // The PCM to ADPCM conversion routines haven't been modified to do this yet. /*if(mod->sample[x].repeat_len > 2 && mod->fmt == MOD_FMT_MOD) { for(y = 0; y < ((sz / 16)-1); y++) { if((mod->sample[x].repeat_off / 28) == y) adpcm_buffer[(y<<4) + 1] = 6; else adpcm_buffer[(y<<4) + 1] = 2; } adpcm_buffer[(y<<4) + 1] = 3; }*/ fwrite(adpcm_buffer, sizeof(char), sz, f); } return 0; }