-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
555 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
outputwaves/ | ||
*.exe |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
#include "LSDJ2DMW.h" | ||
|
||
/* | ||
instrument names (1e7a-1fb9) | ||
names are 5 bytes long | ||
pay attention to wave instrument param length!!! | ||
indexed from 0 | ||
*/ | ||
|
||
|
||
|
||
int main(int argc, char* argv[]){ | ||
if(argc <= 1){ | ||
printf(HELPSTRING); | ||
exit(0); | ||
} | ||
if(strcmp("-h",argv[1]) == 0){ | ||
printf(HELPSTRING); | ||
exit(0); | ||
} | ||
if(strcmp(argv[1],"") == 0){ | ||
printf("ERROR: input filename not entered\n"); | ||
printf(HELPSTRING); | ||
exit(1); | ||
} | ||
if(access(argv[1], F_OK ) == -1){ | ||
printf("ERROR: file '%s' does not exist\n",argv[1]); | ||
printf(HELPSTRING); | ||
exit(1); | ||
} | ||
strcpy(GLOBALINFILE,argv[1]); | ||
int runcode = 0; | ||
for(int i = 2; i < argc; i++){ | ||
if(strcmp("-p",argv[i]) == 0){//print ripped waves and all songs | ||
GLOBALWAVEPRINTFLAG = 1; | ||
GLOBALFILEPRINTFLAG = 1; | ||
} | ||
else if(strcmp("-pw",argv[i]) == 0){//print ripped waves | ||
GLOBALWAVEPRINTFLAG = 1; | ||
} | ||
else if(strcmp("-pf",argv[i]) == 0){//print all songs | ||
GLOBALFILEPRINTFLAG = 1; | ||
} | ||
|
||
else if(strcmp("-l",argv[i]) == 0){//rip all wavetables in loaded song | ||
runcode = 5; | ||
} | ||
else if(strcmp("-lw",argv[i]) == 0){//rip single wave in loaded song | ||
GLOBALRIPWAVENUM = atoi(argv[++i]); | ||
runcode = 6; | ||
} | ||
else if(strcmp("-lwr",argv[i]) == 0){//rip range of wavetables from loaded song | ||
GLOBALRIPWAVENUM = atoi(argv[++i]); | ||
GLOBALENDWAVENUM = atoi(argv[++i]); | ||
if (GLOBALRIPWAVENUM>GLOBALENDWAVENUM){ | ||
printf("ERROR: first value in range cannot be larger than the second value in range\n"); | ||
exit(1); | ||
} | ||
runcode = 7; | ||
} | ||
|
||
else if(strcmp("-a",argv[i]) == 0){//rip all waves in all songs | ||
runcode = 4; | ||
} | ||
else if(strcmp("-s",argv[i]) == 0){//rip single song | ||
strcpy(GLOBALSONGNAME,argv[++i]); | ||
runcode = 1; | ||
} | ||
else if(strcmp("-sw",argv[i]) == 0){//rip single wave in song | ||
strcpy(GLOBALSONGNAME,argv[++i]); | ||
GLOBALRIPWAVENUM = atoi(argv[++i]); | ||
//GLOBALRIPWAVENUM = argv[++i]; | ||
runcode = 2; | ||
} | ||
else if(strcmp("-swr",argv[i]) == 0){//rip range of waves in song | ||
strcpy(GLOBALSONGNAME,argv[++i]); | ||
GLOBALRIPWAVENUM = atoi(argv[++i]); | ||
GLOBALENDWAVENUM = atoi(argv[++i]); | ||
if (GLOBALRIPWAVENUM>GLOBALENDWAVENUM){ | ||
printf("ERROR: first value in range cannot be larger than the second value in range\n"); | ||
exit(1); | ||
} | ||
//GLOBALRIPWAVENUM = argv[++i]; | ||
//GLOBALENDWAVENUM = argv[++i]; | ||
runcode = 3; | ||
} | ||
else if(strcmp("-x",argv[i]) == 0){ | ||
GLOBALOUTPUTINDEXMODE = 1; | ||
} | ||
else if(strcmp("-nw",argv[i]) == 0){ | ||
runcode = 10; | ||
} | ||
else if(strcmp("-h",argv[i]) == 0){ | ||
printf(HELPSTRING); | ||
exit(0); | ||
} | ||
else if(strcmp("-d",argv[i]) == 0){ | ||
test(); | ||
exit(0); | ||
} | ||
} | ||
switch (runcode){ | ||
case 0:// rip all wavetables in loaded song(default) | ||
ripWaveRangeFromLoaded(GLOBALINFILE,0,255); | ||
break; | ||
case 1://single file | ||
ripSingleSong(GLOBALINFILE,GLOBALSONGNAME); | ||
break; | ||
case 2://single wavetable in single song | ||
ripWavetableRangeFromSong(GLOBALINFILE,GLOBALSONGNAME,GLOBALRIPWAVENUM,GLOBALRIPWAVENUM); | ||
break; | ||
case 3://rip range of wavetables in single song | ||
ripWavetableRangeFromSong(GLOBALINFILE,GLOBALSONGNAME,GLOBALRIPWAVENUM,GLOBALENDWAVENUM); | ||
break; | ||
case 4://rip all in all songs | ||
ripAllWavetables(GLOBALINFILE); | ||
break; | ||
case 5://rip all wavetables in loaded song | ||
ripWaveRangeFromLoaded(GLOBALINFILE,0,255); | ||
break; | ||
case 6://rip single wavetable in loaded song | ||
ripWaveRangeFromLoaded(GLOBALINFILE,GLOBALRIPWAVENUM,GLOBALRIPWAVENUM); | ||
break; | ||
case 7://rip wavetables in given range of song | ||
ripWaveRangeFromLoaded(GLOBALINFILE,GLOBALRIPWAVENUM,GLOBALENDWAVENUM); | ||
break; | ||
case 10://do nothing -nw | ||
break; | ||
default://something went wrong | ||
break; | ||
} | ||
if(GLOBALFILEPRINTFLAG){ | ||
printAllFilenames("test1.sav"); | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <stdint.h> | ||
#include <string.h> | ||
#include <unistd.h> | ||
|
||
#ifndef SYSTEMOS | ||
#define SYSTEMOS 0//windows | ||
#endif | ||
int GLOBALWAVEPRINTFLAG = 0;//print waves | ||
int GLOBALFILEPRINTFLAG = 0;//print scanned files | ||
int GLOBALOUTFILEFLAG = 1;//output .dmw's | ||
|
||
#if SYSTEMOS == 0//windows | ||
char* GLOBALFILEDIRECTORY = ".\\outputwaves\\";//directory to dump files into (windows) | ||
#endif | ||
#if SYSTEMOS == 1//linux | ||
char* GLOBALFILEDIRECTORY = "./outputwaves/";//directory to dump files into (linux) | ||
#endif | ||
char GLOBALINFILE[50] = ""; | ||
char GLOBALSONGNAME[50] = ""; | ||
int GLOBALRIPWAVENUM = 0;//lazy solution | ||
int GLOBALENDWAVENUM = 0; | ||
int GLOBALOUTPUTINDEXMODE = 0;//1 = dec, 2 = hex | ||
#define GBWAVESIZE 32 | ||
#define GBBITDEPTH 4 | ||
#define LSDJWAVESTARTADDRESS 0x6000 | ||
#define LSDJWAVEENDADDRESS 0x6FFF | ||
#define LSDJVERSIONADDRESS 0x7FFF | ||
#define FILENAMES_BASEADDRESS 0x8000 | ||
#define FILENAME_LENGTH 8 | ||
|
||
char* HELPSTRING = \ | ||
"==LSDJ2DMW 1.0==\n\ | ||
by Pegmode (Dan Chu)\n\n\ | ||
Rips wavetables from LSDJ into .dmw for use in Deflemask\n\ | ||
USAGE: LSDJ2SDMW <inputSavFilename> [options]\n\ | ||
OPTIONS: \n\ | ||
-l: rip all wavetables in loaded module (default)\n\ | ||
-lw <wavenumber>: rips a single wavetable from the loaded module\n\ | ||
-lwr <startWaveNumber>: rip a range of wavetables from the loaded module\n\ | ||
-a: rips all wavetables from all saved songs\n\ | ||
-s: <songname>: rip all wavetables from a single song\n\ | ||
-sw: <songname> <wavenumber>: rips a specific wavetable from a given song (0-255)\n\ | ||
-swr: <songname> <startWaveNumber> <endWaveNumber>: rips wavetables in a given range in a specific song (0-255)\n\ | ||
-p: print ripped waves and files\n\ | ||
-pw: print ripped waves\n\ | ||
-pf: print songs\n\ | ||
-x: format outputted wavetable indices as hex\n\ | ||
-nw: don't write files or parse files. Useful in combination with -p/-pf for reading songnames\n\ | ||
\n\ | ||
Example usage: LSDJ2SFMW test.sav -p -lwr 0 5\n\ | ||
default behavior rips all wavetables in loaded song \n\ | ||
for all behavior involving the 'loaded song', the 'loaded song' means what you have loaded in LSDj before saving\n\ | ||
by default waves are dumped into directory ./outputwaves/\n\ | ||
LSDJ versions less than 6.7.0 are not guaranteed to function properly with this program\n\ | ||
"; | ||
|
||
#include "LSDJDecompress.c" | ||
#include "utils.c" | ||
#include "ripTools.c" | ||
#include "debug.c" | ||
|
||
|
||
|
||
/* | ||
Version Codes | ||
* 0: < 3.6.0 | ||
* 1: 3.6.0 | ||
* 2: 3.6.1 | ||
* 3: 4.4.0 | ||
* 4: 5.7.0 | ||
* 5: 6.3.0 | ||
* 6: 6.7.0 | ||
* 7: 6.8.0 | ||
* 8: 7.1.0 | ||
* 9: 7.5.0 | ||
* 10: 7.9.8 | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#include "LSDJDecompress.h" | ||
|
||
//info https://littlesounddj.fandom.com/wiki/File_Management_Structure | ||
//https://littlesounddj.fandom.com/wiki/.sav_structure | ||
//WARNING: If comparing outputted binaries to .sav, timers may be different | ||
uint8_t defaultInstrument[] = {0xa8,0x0,0x0,0xff,0x0,0x0,0x3,0x0,0x0,0xd0,0x0,0x0,0x0,0xf3,0x0,0x0};//length 16 | ||
uint8_t defaultWave[] = {0x8e,0xcd,0xcc,0xbb,0xaa,0xa9,0x99,0x88,0x87,0x76,0x66,0x55,0x54,0x43,0x32,0x31};//length 16 | ||
|
||
|
||
int calculateBlockBase(int blockNumber){//base address in .sav memory map | ||
return (0x8000 + 0x200 * blockNumber); | ||
} | ||
|
||
int findFirstBlockFromFileIndex(int fileIndex ,char* filePath){ | ||
FILE* f = fopen(filePath,"rb"); | ||
uint8_t fileAllocationTable[FILE_ALLOC_SIZE] = {0xff}; | ||
fseek(f,FILE_ALLOC_ADDRESSBASE,SEEK_SET); | ||
fread(fileAllocationTable,FILE_ALLOC_SIZE,1,f); | ||
fclose(f); | ||
|
||
for(int i = 0; i < FILE_ALLOC_SIZE; i++){//search filealloc table for file index | ||
//block indexed from 1 | ||
//printf("%i\n",fileAllocationTable[i]); | ||
if(fileAllocationTable[i] == fileIndex){ | ||
return i+1; | ||
} | ||
} | ||
return -1; | ||
} | ||
|
||
int calculateRealAddress(int cPos){ | ||
return 0x8200 + cPos; | ||
} | ||
|
||
void createFileBlocksBuffer(char* filePath, uint8_t* blockBuffer){ | ||
FILE* f = fopen(filePath,"rb"); | ||
fseek(f,BLOCK_BASE_ADDRESS,SEEK_SET); | ||
fread(blockBuffer,FILE_BLOCKS_SIZE,1,f); | ||
fclose(f); | ||
|
||
FILE* fz = fopen("debugout2.bin","wb"); | ||
fwrite(blockBuffer,1,FILE_BLOCKS_SIZE,fz); | ||
fclose(fz); | ||
} | ||
int uncompressDefault(uint8_t* uncompressedFile,uint8_t* defaultContent,int uPos, int cPos, uint8_t* compressedFile){ | ||
int loopLength = compressedFile[cPos]; | ||
for(int i = 0; i < loopLength; i++){ | ||
memcpy(&uncompressedFile[uPos],defaultContent,DEFAULT_DECOMPRESS_LENGTH); | ||
uPos += 16; | ||
} | ||
return uPos; | ||
} | ||
|
||
int calculateBlockOffsetFromBlockIndex(int blockIndex){//base offset | ||
return (blockIndex-1) * 0x200; | ||
} | ||
|
||
|
||
void decompressBlocks(int startBlockIndex,char* filePath,uint8_t* uncompressedFile){ | ||
uint8_t compressedFile[FILE_BLOCKS_SIZE] = {0}; | ||
createFileBlocksBuffer(filePath,compressedFile); | ||
int uPos = 0;//uncompressed position | ||
int cPos = calculateBlockOffsetFromBlockIndex(startBlockIndex);//compressed positon | ||
for(;uPos < 0x8000;){ | ||
//printf("%d\n",uPos ); | ||
switch(compressedFile[cPos]){ | ||
case 0xC0://RLE?s | ||
cPos++; | ||
if(compressedFile[cPos] != 0xC0){//IS RLE | ||
uint8_t byteValue = compressedFile[cPos++]; | ||
uint8_t rleLength = compressedFile[cPos++]; | ||
for(int j = 0; j < (int)rleLength; j++){ | ||
//compressedFile[uPos++] = byteValue; | ||
uncompressedFile[uPos++] = byteValue; | ||
} | ||
//printf("RLE val: %X len: %d c adr: %X u adr: %X\n",byteValue,rleLength,calculateRealAddress(cPos - 3),uPos); | ||
} | ||
else{//IS NOT RLE | ||
uncompressedFile[uPos++] = 0xC0; | ||
cPos++; | ||
} | ||
break; | ||
case 0xE0://command | ||
cPos++; | ||
switch (compressedFile[cPos]){ | ||
case 0xE0://not a command | ||
uncompressedFile[uPos++] = 0xE0; | ||
cPos++; | ||
break; | ||
case 0xF1://default instrument | ||
//printf("\nPasting Default instrument c adr:%X u adr:%X\n",calculateRealAddress(cPos),uPos); | ||
cPos++; | ||
uPos = uncompressDefault(uncompressedFile,defaultInstrument,uPos,cPos,compressedFile); | ||
cPos++; | ||
break; | ||
case 0xF0://default wavetable | ||
//printf("\nPasting Default WT c adr:%X u adr:%X\n",calculateRealAddress(cPos),uPos); | ||
cPos++; | ||
uPos = uncompressDefault(uncompressedFile,defaultWave,uPos,cPos,compressedFile); | ||
cPos++; | ||
break; | ||
case 0xFF://end of file | ||
//printf("\nFinished Decompression c adr:%X u adr:%X\n",calculateRealAddress(cPos),uPos); | ||
return; | ||
break; | ||
default://block Switch | ||
//printf("\nSwitching Blocks c adr:%X u adr:%X\n",calculateRealAddress(cPos),uPos); | ||
cPos = calculateBlockOffsetFromBlockIndex(compressedFile[cPos]); | ||
//printf(" new c adr:%X\n",calculateRealAddress(cPos)); | ||
//printf("next: %X\n",compressedFile[cPos]); | ||
break; | ||
} | ||
|
||
break; | ||
default://write byte | ||
uncompressedFile[uPos++] = compressedFile[cPos++]; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
void decompressLSDJFile(int fileIndex,char* fileName, uint8_t* uncompressedFile){ | ||
int blockIndex = findFirstBlockFromFileIndex(fileIndex,fileName); | ||
//printf("BLOCK INDEX: %i\n",blockIndex); | ||
if(blockIndex == -1){ | ||
//BLOCK INDEX NOT FOUND | ||
printf("Block Index not found\n"); | ||
} | ||
else decompressBlocks(blockIndex,fileName,uncompressedFile); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#include <stdio.h> | ||
#include <stdint.h> | ||
#include <string.h> | ||
|
||
#define FILE_ALLOC_ADDRESSBASE 0x8141 | ||
#define FILE_ALLOC_SIZE 191 | ||
#define FILE_BLOCK_LENGTH 0x200 | ||
#define DEFAULT_DECOMPRESS_LENGTH 16 | ||
#define MAX_FILE_NUMBER 0x20 | ||
#define BLOCK_BASE_ADDRESS 0x8200 | ||
#define FILE_BLOCKS_SIZE 0x17DFF | ||
|
||
|
||
/* | ||
* 0: < 3.6.0 | ||
* 1: 3.6.0 | ||
* 2: 3.6.1 | ||
* 3: 4.4.0 | ||
* 4: 5.7.0 | ||
* 5: 6.3.0 | ||
* 6: 6.7.0 | ||
* 7: 6.8.0 | ||
* 8: 7.1.0 | ||
* 9: 7.5.0 | ||
* 10: 7.9.8 | ||
* C: 8.7.7? | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
C = gcc | ||
outname = LSDJ2DMW | ||
dependencies = LSDJ2DMW.c LSDJ2DMW.h utils.c utils.h ripTools.c ripTools.h LSDJDecompress.c LSDJDecompress.h debug.c debug.h | ||
windows: $(dependencies) | ||
$(C) LSDJ2DMW.c -o $(outname).exe | ||
linux: $(dependencies) #untested | ||
$(C) LSDJ2DMW.c -o $(outname) -D SYSTEMOS = 1 |
Oops, something went wrong.