summaryrefslogtreecommitdiff
path: root/tools/mod4psx.c
blob: 1fc68ef77ec53d8eb95a58064d4b1ad4d3b38f01 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#include <stdio.h>
#include <stdlib.h>
#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 <mod_music> <adpcm_dat>\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;
}