From c7398d66cba7dda9498317708233ebf816dabbea Mon Sep 17 00:00:00 2001 From: yenatch Date: Fri, 6 Jan 2017 23:12:47 -0500 Subject: Dump the cries and rewrite aif2pcm. (#156) --- tools/aif2pcm/main.c | 846 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 555 insertions(+), 291 deletions(-) (limited to 'tools') diff --git a/tools/aif2pcm/main.c b/tools/aif2pcm/main.c index dd2d368a5..41b413d4b 100644 --- a/tools/aif2pcm/main.c +++ b/tools/aif2pcm/main.c @@ -52,43 +52,94 @@ typedef struct { unsigned long num_samples; uint8_t *samples; uint8_t midi_note; + bool has_loop; unsigned long loop_offset; double sample_rate; } AifData; +struct Bytes { + unsigned long length; + uint8_t *data; +}; -char * get_file_extension(char *filename) +struct Bytes *read_bytearray(const char *filename) { - char *dot = strrchr(filename, '.'); - if (!dot || dot == filename) + struct Bytes *bytes = malloc(sizeof(struct Bytes)); + FILE *f = fopen(filename, "rb"); + if (!f) { - FATAL_ERROR("Input file has no file extension.\n"); + FATAL_ERROR("Failed to open '%s' for reading!\n", filename); } + fseek(f, 0, SEEK_END); + bytes->length = ftell(f); + fseek(f, 0, SEEK_SET); + bytes->data = malloc(bytes->length); + unsigned long read = fread(bytes->data, bytes->length, 1, f); + fclose(f); + if (read <= 0) + { + FATAL_ERROR("Failed to read data from '%s'!\n", filename); + } + return bytes; +} + +void write_bytearray(const char *filename, struct Bytes *bytes) +{ + FILE *f = fopen(filename, "wb"); + if (!f) + { + FATAL_ERROR("Failed to open '%s' for writing!\n", filename); + } + fwrite(bytes->data, bytes->length, 1, f); + fclose(f); +} - return dot + 1; +void free_bytearray(struct Bytes *bytes) +{ + free(bytes->data); + free(bytes); } -void change_file_extension(char *filename, const char *new_extension) +char *get_file_extension(char *filename) { - char *dot = strrchr(filename, '.'); - if (!dot || dot == filename) + char *index = strrchr(filename, '.'); + if (!index || index == filename) { - FATAL_ERROR("Input file has no file extension.\n"); + return NULL; } + return index + 1; +} - memcpy(dot + 1, new_extension, 3); +char *new_file_extension(char *filename, char *ext) +{ + char *index = strrchr(filename, '.'); + if (!index || index == filename) + { + index = filename + strlen(filename); + } + int length = index - filename; + char *new_filename = malloc(length + 1 + strlen(ext) + 1); + if (new_filename) + { + strcpy(new_filename, filename); + new_filename[length] = '.'; + strcpy(new_filename + length + 1, ext); + } + return new_filename; } -AifData *read_aif(uint8_t * aif_file_data, unsigned long aif_file_data_size) +AifData *read_aif(struct Bytes *aif) { AifData *aif_data = (AifData *)malloc(sizeof(AifData)); + aif_data->has_loop = false; + aif_data->num_samples = 0; unsigned long pos = 0; char chunk_name[5]; chunk_name[4] = '\0'; char chunk_type[5]; chunk_type[4] = '\0'; // Check for FORM Chunk - memcpy(chunk_name, aif_file_data + pos, 4); + memcpy(chunk_name, &aif->data[pos], 4); pos += 4; if (strcmp(chunk_name, "FORM") != 0) { @@ -96,19 +147,19 @@ AifData *read_aif(uint8_t * aif_file_data, unsigned long aif_file_data_size) } // Read size of whole file. - unsigned long whole_chunk_size = aif_file_data[pos++] << 24; - whole_chunk_size |= (aif_file_data[pos++] << 16); - whole_chunk_size |= (aif_file_data[pos++] << 8); - whole_chunk_size |= (uint8_t)aif_file_data[pos++]; + unsigned long whole_chunk_size = aif->data[pos++] << 24; + whole_chunk_size |= (aif->data[pos++] << 16); + whole_chunk_size |= (aif->data[pos++] << 8); + whole_chunk_size |= (uint8_t)aif->data[pos++]; - unsigned long expected_whole_chunk_size = aif_file_data_size - 8; + unsigned long expected_whole_chunk_size = aif->length - 8; if (whole_chunk_size != expected_whole_chunk_size) { FATAL_ERROR("FORM Chunk ckSize '%lu' doesn't match actual size '%lu'!\n", whole_chunk_size, expected_whole_chunk_size); } // Check for AIFF Form Type - memcpy(chunk_type, aif_file_data + pos, 4); + memcpy(chunk_type, &aif->data[pos], 4); pos += 4; if (strcmp(chunk_type, "AIFF") != 0) { @@ -118,44 +169,44 @@ AifData *read_aif(uint8_t * aif_file_data, unsigned long aif_file_data_size) unsigned long num_sample_frames = 0; // Read all the Chunks to populate the AifData struct. - while ((pos + 8) < aif_file_data_size) + while ((pos + 8) < aif->length) { // Read Chunk id - memcpy(chunk_name, aif_file_data + pos, 4); + memcpy(chunk_name, &aif->data[pos], 4); pos += 4; - unsigned long chunk_size = (aif_file_data[pos++] << 24); - chunk_size |= (aif_file_data[pos++] << 16); - chunk_size |= (aif_file_data[pos++] << 8); - chunk_size |= aif_file_data[pos++]; + unsigned long chunk_size = (aif->data[pos++] << 24); + chunk_size |= (aif->data[pos++] << 16); + chunk_size |= (aif->data[pos++] << 8); + chunk_size |= aif->data[pos++]; - if ((pos + chunk_size) > aif_file_data_size) + if ((pos + chunk_size) > aif->length) { FATAL_ERROR("%s chunk at 0x%lx reached end of file before finishing\n", chunk_name, pos); } if (strcmp(chunk_name, "COMM") == 0) { - short num_channels = (aif_file_data[pos++] << 8); - num_channels |= (uint8_t)aif_file_data[pos++]; + short num_channels = (aif->data[pos++] << 8); + num_channels |= (uint8_t)aif->data[pos++]; if (num_channels != 1) { FATAL_ERROR("numChannels (%d) in the COMM Chunk must be 1!\n", num_channels); } - num_sample_frames = (aif_file_data[pos++] << 24); - num_sample_frames |= (aif_file_data[pos++] << 16); - num_sample_frames |= (aif_file_data[pos++] << 8); - num_sample_frames |= (uint8_t)aif_file_data[pos++]; + num_sample_frames = (aif->data[pos++] << 24); + num_sample_frames |= (aif->data[pos++] << 16); + num_sample_frames |= (aif->data[pos++] << 8); + num_sample_frames |= (uint8_t)aif->data[pos++]; - short sample_size = (aif_file_data[pos++] << 8); - sample_size |= (uint8_t)aif_file_data[pos++]; + short sample_size = (aif->data[pos++] << 8); + sample_size |= (uint8_t)aif->data[pos++]; if (sample_size != 8) { FATAL_ERROR("sampleSize (%d) in the COMM Chunk must be 8!\n", sample_size); } - double sample_rate = ieee754_read_extended((uint8_t*)(aif_file_data + pos)); + double sample_rate = ieee754_read_extended((uint8_t*)(aif->data + pos)); pos += 10; aif_data->sample_rate = sample_rate; @@ -167,32 +218,31 @@ AifData *read_aif(uint8_t * aif_file_data, unsigned long aif_file_data_size) } else if (strcmp(chunk_name, "MARK") == 0) { - unsigned short num_markers = (aif_file_data[pos++] << 8); - num_markers |= (uint8_t)aif_file_data[pos++]; - - unsigned long loop_start = 0; + unsigned short num_markers = (aif->data[pos++] << 8); + num_markers |= (uint8_t)aif->data[pos++]; // Read each marker and look for the "START" marker. for (int i = 0; i < num_markers; i++) { - unsigned short marker_id = (aif_file_data[pos++] << 8); - marker_id |= (uint8_t)aif_file_data[pos++]; + unsigned short marker_id = (aif->data[pos++] << 8); + marker_id |= (uint8_t)aif->data[pos++]; - unsigned long marker_position = (aif_file_data[pos++] << 24); - marker_position |= (aif_file_data[pos++] << 16); - marker_position |= (aif_file_data[pos++] << 8); - marker_position |= (uint8_t)aif_file_data[pos++]; + unsigned long marker_position = (aif->data[pos++] << 24); + marker_position |= (aif->data[pos++] << 16); + marker_position |= (aif->data[pos++] << 8); + marker_position |= (uint8_t)aif->data[pos++]; // Marker id is a pascal-style string. - uint8_t marker_name_size = aif_file_data[pos++]; + uint8_t marker_name_size = aif->data[pos++]; char *marker_name = (char *)malloc((marker_name_size + 1) * sizeof(char)); - memcpy(marker_name, aif_file_data + pos, marker_name_size); + memcpy(marker_name, &aif->data[pos], marker_name_size); marker_name[marker_name_size] = '\0'; pos += marker_name_size; if (strcmp(marker_name, "START") == 0) { - loop_start = marker_position; + aif_data->loop_offset = marker_position; + aif_data->has_loop = true; } else if (strcmp(marker_name, "END") == 0) { @@ -201,12 +251,10 @@ AifData *read_aif(uint8_t * aif_file_data, unsigned long aif_file_data_size) free(marker_name); } - - aif_data->loop_offset = loop_start; } else if (strcmp(chunk_name, "INST") == 0) { - uint8_t midi_note = (uint8_t)aif_file_data[pos++]; + uint8_t midi_note = (uint8_t)aif->data[pos++]; aif_data->midi_note = midi_note; @@ -218,15 +266,16 @@ AifData *read_aif(uint8_t * aif_file_data, unsigned long aif_file_data_size) // SKip offset and blockSize pos += 8; - uint8_t *sample_data = (uint8_t *)malloc(num_sample_frames * sizeof(uint8_t)); - memcpy(sample_data, aif_file_data + pos, num_sample_frames); + unsigned long num_samples = chunk_size - 8; + uint8_t *sample_data = (uint8_t *)malloc(num_samples * sizeof(uint8_t)); + memcpy(sample_data, &aif->data[pos], num_samples); aif_data->samples = sample_data; - pos += num_sample_frames; + pos += chunk_size - 8; } else { - // Skip over stuff we unsupported chunks. + // Skip over unsupported chunks. pos += chunk_size; } } @@ -234,368 +283,583 @@ AifData *read_aif(uint8_t * aif_file_data, unsigned long aif_file_data_size) return aif_data; } -// Reads an .aif file and produces a .pcm file containing an array of 8-bit samples. -void aif2pcm(const char *aif_filename) -{ - // Get .pcm filename. - char *pcm_filename = malloc(strlen(aif_filename) + 1); +// This is a table of deltas between sample values in compressed PCM data. +const int8_t gDeltaEncodingTable[] = { + 0, 1, 4, 9, 16, 25, 36, 49, + -64, -49, -36, -25, -16, -9, -4, -1, +}; - if (!pcm_filename) +struct Bytes *delta_decompress(struct Bytes *delta, unsigned int expected_length) +{ + struct Bytes *pcm = malloc(sizeof(struct Bytes)); + pcm->length = expected_length; + pcm->data = malloc(pcm->length + 0x40); + + uint8_t hi, lo; + unsigned int i = 0; + unsigned int j = 0; + int k; + int8_t base; + while (i < delta->length) { - FATAL_ERROR("Failed to allocate space for pcm filename.\n"); + base = (int8_t)delta->data[i++]; + pcm->data[j++] = (uint8_t)base; + if (i >= delta->length) + { + break; + } + if (j >= pcm->length) + { + break; + } + lo = delta->data[i] & 0xf; + base += gDeltaEncodingTable[lo]; + pcm->data[j++] = base; + i++; + if (i >= delta->length) + { + break; + } + if (j >= pcm->length) + { + break; + } + for (k = 0; k < 31; k++) + { + hi = (delta->data[i] >> 4) & 0xf; + base += gDeltaEncodingTable[hi]; + pcm->data[j++] = base; + if (j >= pcm->length) + { + break; + } + lo = delta->data[i] & 0xf; + base += gDeltaEncodingTable[lo]; + pcm->data[j++] = base; + i++; + if (i >= delta->length) + { + break; + } + if (j >= pcm->length) + { + break; + } + } + if (j >= pcm->length) + { + break; + } } - strcpy(pcm_filename, aif_filename); - change_file_extension(pcm_filename, "pcm"); + pcm->length = j; + return pcm; +} - // Get .metadata filename. - char *metadata_filename = malloc(strlen(aif_filename) + 1); +struct Bytes *delta_compress(struct Bytes *pcm) +{ + struct Bytes *delta = malloc(sizeof(struct Bytes)); + // estimate the length so we can malloc + int num_blocks = pcm->length / 64; + delta->length = num_blocks * 33; - if (!metadata_filename) + int extra = pcm->length % 64; + if (extra) + { + delta->length += 1; + extra -= 1; + } + if (extra) { - FATAL_ERROR("Failed to allocate space for metadata filename.\n"); + delta->length += 1; + extra -= 1; + } + if (extra) + { + delta->length += (extra + 1) / 2; } - strcpy(metadata_filename, aif_filename); - change_file_extension(metadata_filename, "bin"); + delta->data = malloc(delta->length + 33); - // Open the given .aif file so we can read its contents. - FILE *aif_file; - aif_file = fopen(aif_filename, "rb"); - if (!aif_file) + uint8_t hi, lo; + unsigned int i = 0; + unsigned int j = 0; + int k; + int l; + int8_t base; + int8_t diff; + while (i < pcm->length) { - FATAL_ERROR("Failed to open '%s' for reading!\n", aif_filename); + base = (int8_t)pcm->data[i++]; + delta->data[j++] = (uint8_t)base; + if (i >= pcm->length) + { + break; + } + hi = 0; + diff = pcm->data[i++] - base; + if (diff > 49) + { + diff = -diff; + } + if (diff < 0) + { + for (l = 8; l < 16; l++) + { + lo = l & 0xf; + if (diff <= gDeltaEncodingTable[l]) break; + } + } + else + { + for (l = 0; l < 8; l++) + { + lo = l & 0xf; + if (diff <= gDeltaEncodingTable[l]) break; + } + } + base += diff; + delta->data[j++] = (hi << 4) | lo; + if (i >= pcm->length) + { + break; + } + for (k = 0; k < 31; k++) + { + diff = pcm->data[i++] - base; + if (diff > 49) diff = -diff; + if (diff < 0) + { + for (l = 8; l < 16; l++) + { + hi = l & 0xf; + if (diff <= gDeltaEncodingTable[l]) break; + } + } + else + { + for (l = 0; l < 8; l++) + { + hi = l & 0xf; + if (diff <= gDeltaEncodingTable[l]) break; + } + } + base += diff; + delta->data[j] = (hi << 4); + if (i >= pcm->length) + { + break; + } + diff = pcm->data[i++] - base; + if (diff > 49) diff = -diff; + if (diff < 0) + { + for (l = 8; l < 16; l++) + { + lo = l & 0xf; + if (diff <= gDeltaEncodingTable[l]) break; + } + } + else + { + for (l = 0; l < 8; l++) + { + lo = l & 0xf; + if (diff <= gDeltaEncodingTable[l]) break; + } + } + base += diff; + delta->data[j++] = (hi << 4) | lo; + if (i >= pcm->length) + { + break; + } + } + if (i >= pcm->length) + { + break; + } } - // Get file length. - fseek(aif_file, 0, SEEK_END); - unsigned long aif_file_length = ftell(aif_file); - fseek(aif_file, 0, SEEK_SET); + delta->length = j; + + return delta; +} - // Create buffer for samples. - uint8_t *aif_file_data = (uint8_t *)malloc(aif_file_length * sizeof(uint8_t)); - if (!aif_file_data) +#define STORE_U32_LE(dest, value) \ +do { \ + *(dest) = (value) & 0xff; \ + *((dest) + 1) = ((value) >> 8) & 0xff; \ + *((dest) + 2) = ((value) >> 16) & 0xff; \ + *((dest) + 3) = ((value) >> 24) & 0xff; \ +} while (0) + +#define LOAD_U32_LE(var, src) \ +do { \ + (var) = *(src); \ + (var) |= (*((src) + 1) << 8); \ + (var) |= (*((src) + 2) << 16); \ + (var) |= (*((src) + 3) << 24); \ +} while (0) + +// Reads an .aif file and produces a .pcm file containing an array of 8-bit samples. +void aif2pcm(const char *aif_filename, const char *pcm_filename, bool compress) +{ + struct Bytes *aif = read_bytearray(aif_filename); + AifData *aif_data = read_aif(aif); + + int header_size = 0x10; + struct Bytes *pcm; + struct Bytes output = {0}; + + if (compress) { - FATAL_ERROR("Failed to allocate buffer for aif file data!\n"); + struct Bytes *input = malloc(sizeof(struct Bytes)); + input->data = aif_data->samples; + input->length = aif_data->num_samples; + pcm = delta_compress(input); + free(input); } - - // Populate buffer from file. - unsigned long read = fread(aif_file_data, aif_file_length, 1, aif_file); - fclose(aif_file); - if (read <= 0) + else { - FATAL_ERROR("Failed to read data from '%s'!\n", aif_filename); + pcm = malloc(sizeof(struct Bytes)); + pcm->data = aif_data->samples; + pcm->length = aif_data->num_samples; } + output.length = header_size + pcm->length; + output.data = malloc(output.length); - AifData *aif_data = read_aif(aif_file_data, aif_file_length); - - // Write the output .pcm file - FILE *pcm_file; - pcm_file = fopen(pcm_filename, "wb"); - fwrite(aif_data->samples, aif_data->num_samples, 1, pcm_file); - fclose(pcm_file); - - // Write the output .bin file containing .aif metadata. - FILE *metadata_file; - metadata_file = fopen(metadata_filename, "wb"); uint32_t pitch_adjust = (uint32_t)(aif_data->sample_rate * 1024); - fwrite(&pitch_adjust, sizeof(uint32_t), 1, metadata_file); - fwrite(&(aif_data->loop_offset), sizeof(uint32_t), 1, metadata_file); + uint32_t loop_offset = (uint32_t)(aif_data->loop_offset); uint32_t adjusted_num_samples = (uint32_t)(aif_data->num_samples - 1); - fwrite(&adjusted_num_samples, sizeof(uint32_t), 1, metadata_file); - fclose(metadata_file); - + uint32_t flags = 0; + if (aif_data->has_loop) flags |= 0x40000000; + if (compress) flags |= 1; + STORE_U32_LE(output.data + 0, flags); + STORE_U32_LE(output.data + 4, pitch_adjust); + STORE_U32_LE(output.data + 8, loop_offset); + STORE_U32_LE(output.data + 12, adjusted_num_samples); + memcpy(&output.data[header_size], pcm->data, pcm->length); + write_bytearray(pcm_filename, &output); + + free(aif->data); + free(aif); + free(pcm); + free(output.data); free(aif_data->samples); free(aif_data); - free(aif_file_data); - free(metadata_filename); - free(pcm_filename); } // Reads a .pcm file containing an array of 8-bit samples and produces an .aif file. // See http://www-mmsp.ece.mcgill.ca/documents/audioformats/aiff/Docs/AIFF-1.3.pdf for .aif file specification. -void pcm2aif(const char *pcm_filename, char base_note, long pitch_adjust, long loop_start) +void pcm2aif(const char *pcm_filename, const char *aif_filename, uint32_t base_note) { - // Get .aif filename. - char *aif_filename = malloc(strlen(pcm_filename) + 1); + struct Bytes *pcm = read_bytearray(pcm_filename); - if (!aif_filename) - { - FATAL_ERROR("Failed to allocate space for aif filename.\n"); - } + AifData *aif_data = malloc(sizeof(AifData)); - strcpy(aif_filename, pcm_filename); - change_file_extension(aif_filename, "aif"); + uint32_t flags; + LOAD_U32_LE(flags, pcm->data + 0); + aif_data->has_loop = flags & 0x40000000; + bool compressed = flags & 1; - // Open the given .pcm file so we can read its 8-bit samples. - FILE *pcm_file; - pcm_file = fopen(pcm_filename, "rb"); - if (!pcm_file) - { - FATAL_ERROR("Failed to open '%s' for reading!\n", pcm_filename); - } + uint32_t pitch_adjust; + LOAD_U32_LE(pitch_adjust, pcm->data + 4); + aif_data->sample_rate = pitch_adjust / 1024.0; - // Get file length. - fseek(pcm_file, 0, SEEK_END); - unsigned long num_samples = ftell(pcm_file); - fseek(pcm_file, 0, SEEK_SET); + LOAD_U32_LE(aif_data->loop_offset, pcm->data + 8); + LOAD_U32_LE(aif_data->num_samples, pcm->data + 12); + aif_data->num_samples += 1; - unsigned long num_samples_extended = num_samples * 1; - - // Create buffer for samples. - signed char *pcm_samples = (signed char *)malloc(num_samples_extended * sizeof(signed char)); - if (!pcm_samples) + if (compressed) { - FATAL_ERROR("Failed to allocate buffer for pcm samples!\n"); + struct Bytes *delta = pcm; + uint8_t *pcm_data = pcm->data; + delta->length -= 0x10; + delta->data += 0x10; + pcm = delta_decompress(delta, aif_data->num_samples); + free(pcm_data); + free(delta); } - - // Populate buffer from file. - unsigned long read = fread(pcm_samples, num_samples, 1, pcm_file); - fclose(pcm_file); - if (read <= 0) + else { - FATAL_ERROR("Failed to read data from '%s'!\n", pcm_filename); + pcm->length -= 0x10; + pcm->data += 0x10; } - // Allocate buffer for output .aif file. - unsigned long aif_file_size = 54 + 60 + num_samples_extended; - char *aif_buffer = (char *)malloc(aif_file_size * sizeof(char)); - if (!aif_buffer) - { - FATAL_ERROR("Failed to allocate buffer for aif file!\n"); - } + aif_data->samples = malloc(pcm->length); + memcpy(aif_data->samples, pcm->data, pcm->length); + + struct Bytes *aif = malloc(sizeof(struct Bytes)); + aif->length = 54 + 60 + aif_data->num_samples; + aif->data = malloc(aif->length); long pos = 0; // First, write the FORM header chunk. // FORM Chunk ckID - aif_buffer[pos++] = 'F'; - aif_buffer[pos++] = 'O'; - aif_buffer[pos++] = 'R'; - aif_buffer[pos++] = 'M'; + aif->data[pos++] = 'F'; + aif->data[pos++] = 'O'; + aif->data[pos++] = 'R'; + aif->data[pos++] = 'M'; // FORM Chunk ckSize - unsigned long data_size = aif_file_size - 8; - aif_buffer[pos++] = ((data_size >> 24) & 0xFF); - aif_buffer[pos++] = ((data_size >> 16) & 0xFF); - aif_buffer[pos++] = ((data_size >> 8) & 0xFF); - aif_buffer[pos++] = (data_size & 0xFF); + unsigned long form_size = pos; + unsigned long data_size = aif->length - 8; + aif->data[pos++] = ((data_size >> 24) & 0xFF); + aif->data[pos++] = ((data_size >> 16) & 0xFF); + aif->data[pos++] = ((data_size >> 8) & 0xFF); + aif->data[pos++] = (data_size & 0xFF); // FORM Chunk formType - aif_buffer[pos++] = 'A'; - aif_buffer[pos++] = 'I'; - aif_buffer[pos++] = 'F'; - aif_buffer[pos++] = 'F'; + aif->data[pos++] = 'A'; + aif->data[pos++] = 'I'; + aif->data[pos++] = 'F'; + aif->data[pos++] = 'F'; // Next, write the Common Chunk // Common Chunk ckID - aif_buffer[pos++] = 'C'; - aif_buffer[pos++] = 'O'; - aif_buffer[pos++] = 'M'; - aif_buffer[pos++] = 'M'; + aif->data[pos++] = 'C'; + aif->data[pos++] = 'O'; + aif->data[pos++] = 'M'; + aif->data[pos++] = 'M'; // Common Chunk ckSize - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 18; + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 18; // Common Chunk numChannels - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 1; // 1 channel + aif->data[pos++] = 0; + aif->data[pos++] = 1; // 1 channel // Common Chunk numSampleFrames - aif_buffer[pos++] = ((num_samples_extended >> 24) & 0xFF); - aif_buffer[pos++] = ((num_samples_extended >> 16) & 0xFF); - aif_buffer[pos++] = ((num_samples_extended >> 8) & 0xFF); - aif_buffer[pos++] = (num_samples_extended & 0xFF); + aif->data[pos++] = ((pcm->length >> 24) & 0xFF); + aif->data[pos++] = ((pcm->length >> 16) & 0xFF); + aif->data[pos++] = ((pcm->length >> 8) & 0xFF); + aif->data[pos++] = (pcm->length & 0xFF); // Common Chunk sampleSize - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 8; // 8 bits per sample + aif->data[pos++] = 0; + aif->data[pos++] = 8; // 8 bits per sample // Common Chunk sampleRate - double sample_rate = pitch_adjust / 1024.0; + //double sample_rate = pitch_adjust / 1024.0; uint8_t sample_rate_buffer[10]; - ieee754_write_extended(sample_rate, sample_rate_buffer); + ieee754_write_extended(aif_data->sample_rate, sample_rate_buffer); for (int i = 0; i < 10; i++) { - aif_buffer[pos++] = sample_rate_buffer[i]; + aif->data[pos++] = sample_rate_buffer[i]; } // Marker Chunk ckID - aif_buffer[pos++] = 'M'; - aif_buffer[pos++] = 'A'; - aif_buffer[pos++] = 'R'; - aif_buffer[pos++] = 'K'; + aif->data[pos++] = 'M'; + aif->data[pos++] = 'A'; + aif->data[pos++] = 'R'; + aif->data[pos++] = 'K'; // Marker Chunk ckSize - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 24; + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 12 + (aif_data->has_loop ? 12 : 0); // Marker Chunk numMarkers - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 2; - - // Marker loop start - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 1; // id = 1 - - aif_buffer[pos++] = ((loop_start >> 24) & 0xFF); - aif_buffer[pos++] = ((loop_start >> 16) & 0xFF); - aif_buffer[pos++] = ((loop_start >> 8) & 0xFF); - aif_buffer[pos++] = (loop_start & 0xFF); // position + aif->data[pos++] = 0; + aif->data[pos++] = (aif_data->has_loop ? 2 : 1); - aif_buffer[pos++] = 5; // pascal-style string length - aif_buffer[pos++] = 'S'; - aif_buffer[pos++] = 'T'; - aif_buffer[pos++] = 'A'; - aif_buffer[pos++] = 'R'; - aif_buffer[pos++] = 'T'; // markerName + if (aif_data->has_loop) + { + // Marker loop start + aif->data[pos++] = 0; + aif->data[pos++] = 1; // id = 1 + + long loop_start = aif_data->loop_offset; + aif->data[pos++] = ((loop_start >> 24) & 0xFF); + aif->data[pos++] = ((loop_start >> 16) & 0xFF); + aif->data[pos++] = ((loop_start >> 8) & 0xFF); + aif->data[pos++] = (loop_start & 0xFF); // position + + aif->data[pos++] = 5; // pascal-style string length + aif->data[pos++] = 'S'; + aif->data[pos++] = 'T'; + aif->data[pos++] = 'A'; + aif->data[pos++] = 'R'; + aif->data[pos++] = 'T'; // markerName + } // Marker loop end - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 2; // id = 2 + aif->data[pos++] = 0; + aif->data[pos++] = (aif_data->has_loop ? 2 : 1); // id = 2 - long loop_end = num_samples; - aif_buffer[pos++] = ((loop_end >> 24) & 0xFF); - aif_buffer[pos++] = ((loop_end >> 16) & 0xFF); - aif_buffer[pos++] = ((loop_end >> 8) & 0xFF); - aif_buffer[pos++] = (loop_end & 0xFF); // position - - aif_buffer[pos++] = 3; // pascal-style string length - aif_buffer[pos++] = 'E'; - aif_buffer[pos++] = 'N'; - aif_buffer[pos++] = 'D'; + long loop_end = aif_data->num_samples; + aif->data[pos++] = ((loop_end >> 24) & 0xFF); + aif->data[pos++] = ((loop_end >> 16) & 0xFF); + aif->data[pos++] = ((loop_end >> 8) & 0xFF); + aif->data[pos++] = (loop_end & 0xFF); // position + aif->data[pos++] = 3; // pascal-style string length + aif->data[pos++] = 'E'; + aif->data[pos++] = 'N'; + aif->data[pos++] = 'D'; // Instrument Chunk ckID - aif_buffer[pos++] = 'I'; - aif_buffer[pos++] = 'N'; - aif_buffer[pos++] = 'S'; - aif_buffer[pos++] = 'T'; + aif->data[pos++] = 'I'; + aif->data[pos++] = 'N'; + aif->data[pos++] = 'S'; + aif->data[pos++] = 'T'; // Instrument Chunk ckSize - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 20; - - aif_buffer[pos++] = base_note; // baseNote - aif_buffer[pos++] = 0; // detune - aif_buffer[pos++] = 0; // lowNote - aif_buffer[pos++] = 127; // highNote - aif_buffer[pos++] = 1; // lowVelocity - aif_buffer[pos++] = 127; // highVelocity - aif_buffer[pos++] = 0; // gain (hi) - aif_buffer[pos++] = 0; // gain (lo) + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 20; + + aif->data[pos++] = base_note; // baseNote + aif->data[pos++] = 0; // detune + aif->data[pos++] = 0; // lowNote + aif->data[pos++] = 127; // highNote + aif->data[pos++] = 1; // lowVelocity + aif->data[pos++] = 127; // highVelocity + aif->data[pos++] = 0; // gain (hi) + aif->data[pos++] = 0; // gain (lo) // Instrument Chunk sustainLoop - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 1; // playMode = ForwardLooping + aif->data[pos++] = 0; + aif->data[pos++] = 1; // playMode = ForwardLooping - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 1; // beginLoop marker id + aif->data[pos++] = 0; + aif->data[pos++] = 1; // beginLoop marker id - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 2; // endLoop marker id + aif->data[pos++] = 0; + aif->data[pos++] = 2; // endLoop marker id // Instrument Chunk releaseLoop - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 1; // playMode = ForwardLooping + aif->data[pos++] = 0; + aif->data[pos++] = 1; // playMode = ForwardLooping - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 1; // beginLoop marker id + aif->data[pos++] = 0; + aif->data[pos++] = 1; // beginLoop marker id - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 2; // endLoop marker id + aif->data[pos++] = 0; + aif->data[pos++] = 2; // endLoop marker id // Finally, write the Sound Data Chunk // Sound Data Chunk ckID - aif_buffer[pos++] = 'S'; - aif_buffer[pos++] = 'S'; - aif_buffer[pos++] = 'N'; - aif_buffer[pos++] = 'D'; + aif->data[pos++] = 'S'; + aif->data[pos++] = 'S'; + aif->data[pos++] = 'N'; + aif->data[pos++] = 'D'; // Sound Data Chunk ckSize - unsigned long sound_data_size = num_samples_extended + 8; - aif_buffer[pos++] = ((sound_data_size >> 24) & 0xFF); - aif_buffer[pos++] = ((sound_data_size >> 16) & 0xFF); - aif_buffer[pos++] = ((sound_data_size >> 8) & 0xFF); - aif_buffer[pos++] = (sound_data_size & 0xFF); + unsigned long sound_data_size = pcm->length + 8; + aif->data[pos++] = ((sound_data_size >> 24) & 0xFF); + aif->data[pos++] = ((sound_data_size >> 16) & 0xFF); + aif->data[pos++] = ((sound_data_size >> 8) & 0xFF); + aif->data[pos++] = (sound_data_size & 0xFF); // Sound Data Chunk offset - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 0; // Sound Data Chunk blockSize - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 0; - aif_buffer[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 0; // Sound Data Chunk soundData - for (int i = 0; i < loop_start; i++) + for (unsigned int i = 0; i < aif_data->loop_offset; i++) { - aif_buffer[pos++] = pcm_samples[i]; + aif->data[pos++] = aif_data->samples[i]; } int j = 0; - for (unsigned int i = loop_start; i < num_samples_extended; i++) + for (unsigned int i = aif_data->loop_offset; i < pcm->length; i++) { - int pcm_index = loop_start + (j++ % (num_samples - loop_start - 1)); - aif_buffer[pos++] = pcm_samples[pcm_index]; + int pcm_index = aif_data->loop_offset + (j++ % (pcm->length - aif_data->loop_offset)); + aif->data[pos++] = aif_data->samples[pcm_index]; } - // Write the .aif file contents. - FILE *aif_file; - aif_file = fopen(aif_filename, "wb"); - if (!aif_file) - { - FATAL_ERROR("Failed to open '%s' for writing!\n", aif_filename); - } + aif->length = pos; + + // Go back and rewrite ckSize + data_size = aif->length - 8; + aif->data[form_size + 0] = ((data_size >> 24) & 0xFF); + aif->data[form_size + 1] = ((data_size >> 16) & 0xFF); + aif->data[form_size + 2] = ((data_size >> 8) & 0xFF); + aif->data[form_size + 3] = (data_size & 0xFF); - fwrite(aif_buffer, 1, aif_file_size, aif_file); - fclose(aif_file); + write_bytearray(aif_filename, aif); + + free(aif->data); + free(aif); +} - free(aif_buffer); - free(pcm_samples); - free(aif_filename); +void usage(void) +{ + fprintf(stderr, "Usage: aif2pcm bin_file [aif_file]\n"); + fprintf(stderr, " aif2pcm aif_file [bin_file] [--compress]\n"); } int main(int argc, char **argv) { if (argc < 2) { - FATAL_ERROR("Usage: aif2pcm \n"); + usage(); + exit(1); } - char *input_filename = argv[1]; - char *extension = get_file_extension(input_filename); + char *input_file = argv[1]; + char *extension = get_file_extension(input_file); + char *output_file; + bool compressed = false; + + if (argc > 3) + { + for (int i = 3; i < argc; i++) + { + if (strcmp(argv[i], "--compress") == 0) + { + compressed = true; + } + } + } if (strcmp(extension, "aif") == 0) { - aif2pcm(input_filename); + if (argc >= 3) + { + output_file = argv[2]; + aif2pcm(input_file, output_file, compressed); + } + else + { + output_file = new_file_extension(input_file, "bin"); + aif2pcm(input_file, output_file, compressed); + free(output_file); + } } - else if (strcmp(extension, "pcm") == 0) + else if (strcmp(extension, "bin") == 0) { - if (argc < 5) + if (argc >= 3) { - FATAL_ERROR("Usage: aif2pcm \n"); + output_file = argv[2]; + pcm2aif(input_file, output_file, 60); + } + else + { + output_file = new_file_extension(input_file, "aif"); + pcm2aif(input_file, output_file, 60); + free(output_file); } - - char base_note = atoi(argv[2]); - long pitch_adjust = atol(argv[3]); - long loop_start = atol(argv[4]); - pcm2aif(input_filename, base_note, pitch_adjust, loop_start); } else { - FATAL_ERROR("Input file must be .aif or .pcm: '%s'\n", input_filename); + FATAL_ERROR("Input file must be .aif or .bin: '%s'\n", input_file); } return 0; -- cgit v1.2.3 From 8c4b69e1d0978eccd554edd4a5538398543dda59 Mon Sep 17 00:00:00 2001 From: YamaArashi Date: Fri, 6 Jan 2017 21:01:49 -0800 Subject: make ROM match --- tools/aif2pcm/main.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) (limited to 'tools') diff --git a/tools/aif2pcm/main.c b/tools/aif2pcm/main.c index 41b413d4b..be83554a2 100644 --- a/tools/aif2pcm/main.c +++ b/tools/aif2pcm/main.c @@ -128,9 +128,8 @@ char *new_file_extension(char *filename, char *ext) return new_filename; } -AifData *read_aif(struct Bytes *aif) +void read_aif(struct Bytes *aif, AifData *aif_data) { - AifData *aif_data = (AifData *)malloc(sizeof(AifData)); aif_data->has_loop = false; aif_data->num_samples = 0; @@ -279,8 +278,6 @@ AifData *read_aif(struct Bytes *aif) pos += chunk_size; } } - - return aif_data; } // This is a table of deltas between sample values in compressed PCM data. @@ -506,7 +503,8 @@ do { \ void aif2pcm(const char *aif_filename, const char *pcm_filename, bool compress) { struct Bytes *aif = read_bytearray(aif_filename); - AifData *aif_data = read_aif(aif); + AifData aif_data = {0}; + read_aif(aif, &aif_data); int header_size = 0x10; struct Bytes *pcm; @@ -515,25 +513,25 @@ void aif2pcm(const char *aif_filename, const char *pcm_filename, bool compress) if (compress) { struct Bytes *input = malloc(sizeof(struct Bytes)); - input->data = aif_data->samples; - input->length = aif_data->num_samples; + input->data = aif_data.samples; + input->length = aif_data.num_samples; pcm = delta_compress(input); free(input); } else { pcm = malloc(sizeof(struct Bytes)); - pcm->data = aif_data->samples; - pcm->length = aif_data->num_samples; + pcm->data = aif_data.samples; + pcm->length = aif_data.num_samples; } output.length = header_size + pcm->length; output.data = malloc(output.length); - uint32_t pitch_adjust = (uint32_t)(aif_data->sample_rate * 1024); - uint32_t loop_offset = (uint32_t)(aif_data->loop_offset); - uint32_t adjusted_num_samples = (uint32_t)(aif_data->num_samples - 1); + uint32_t pitch_adjust = (uint32_t)(aif_data.sample_rate * 1024); + uint32_t loop_offset = (uint32_t)(aif_data.loop_offset); + uint32_t adjusted_num_samples = (uint32_t)(aif_data.num_samples - 1); uint32_t flags = 0; - if (aif_data->has_loop) flags |= 0x40000000; + if (aif_data.has_loop) flags |= 0x40000000; if (compress) flags |= 1; STORE_U32_LE(output.data + 0, flags); STORE_U32_LE(output.data + 4, pitch_adjust); @@ -546,8 +544,7 @@ void aif2pcm(const char *aif_filename, const char *pcm_filename, bool compress) free(aif); free(pcm); free(output.data); - free(aif_data->samples); - free(aif_data); + free(aif_data.samples); } // Reads a .pcm file containing an array of 8-bit samples and produces an .aif file. -- cgit v1.2.3 From 10e5474a65d2ff356e1a6280568c078fee1c9b52 Mon Sep 17 00:00:00 2001 From: yenatch Date: Sun, 8 Jan 2017 16:06:19 -0500 Subject: aif2pcm: Fix length reporting. Don't use a MARK chunk if no loop. The reported sample length in the aif header can differ from the actual length of the SSND chunk. The END marker was being misused to contain the reported length, but this still counts as a loop in aif2agb, even if the START marker is omitted (it defaults to the END value). Now the reported length is in the COMM chunk, which is more correct. --- tools/aif2pcm/main.c | 81 ++++++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 37 deletions(-) (limited to 'tools') diff --git a/tools/aif2pcm/main.c b/tools/aif2pcm/main.c index be83554a2..a2c3bcd5c 100644 --- a/tools/aif2pcm/main.c +++ b/tools/aif2pcm/main.c @@ -55,6 +55,7 @@ typedef struct { bool has_loop; unsigned long loop_offset; double sample_rate; + unsigned long real_num_samples; } AifData; struct Bytes { @@ -245,6 +246,10 @@ void read_aif(struct Bytes *aif, AifData *aif_data) } else if (strcmp(marker_name, "END") == 0) { + if (!aif_data->has_loop) { + aif_data->loop_offset = marker_position; + aif_data->has_loop = true; + } aif_data->num_samples = marker_position; } @@ -270,6 +275,7 @@ void read_aif(struct Bytes *aif, AifData *aif_data) memcpy(sample_data, &aif->data[pos], num_samples); aif_data->samples = sample_data; + aif_data->real_num_samples = num_samples; pos += chunk_size - 8; } else @@ -514,7 +520,7 @@ void aif2pcm(const char *aif_filename, const char *pcm_filename, bool compress) { struct Bytes *input = malloc(sizeof(struct Bytes)); input->data = aif_data.samples; - input->length = aif_data.num_samples; + input->length = aif_data.real_num_samples; pcm = delta_compress(input); free(input); } @@ -522,7 +528,7 @@ void aif2pcm(const char *aif_filename, const char *pcm_filename, bool compress) { pcm = malloc(sizeof(struct Bytes)); pcm->data = aif_data.samples; - pcm->length = aif_data.num_samples; + pcm->length = aif_data.real_num_samples; } output.length = header_size + pcm->length; output.data = malloc(output.length); @@ -588,7 +594,7 @@ void pcm2aif(const char *pcm_filename, const char *aif_filename, uint32_t base_n memcpy(aif_data->samples, pcm->data, pcm->length); struct Bytes *aif = malloc(sizeof(struct Bytes)); - aif->length = 54 + 60 + aif_data->num_samples; + aif->length = 54 + 60 + pcm->length; aif->data = malloc(aif->length); long pos = 0; @@ -632,10 +638,10 @@ void pcm2aif(const char *pcm_filename, const char *aif_filename, uint32_t base_n aif->data[pos++] = 1; // 1 channel // Common Chunk numSampleFrames - aif->data[pos++] = ((pcm->length >> 24) & 0xFF); - aif->data[pos++] = ((pcm->length >> 16) & 0xFF); - aif->data[pos++] = ((pcm->length >> 8) & 0xFF); - aif->data[pos++] = (pcm->length & 0xFF); + aif->data[pos++] = ((aif_data->num_samples >> 24) & 0xFF); + aif->data[pos++] = ((aif_data->num_samples >> 16) & 0xFF); + aif->data[pos++] = ((aif_data->num_samples >> 8) & 0xFF); + aif->data[pos++] = (aif_data->num_samples & 0xFF); // Common Chunk sampleSize aif->data[pos++] = 0; @@ -650,24 +656,25 @@ void pcm2aif(const char *pcm_filename, const char *aif_filename, uint32_t base_n aif->data[pos++] = sample_rate_buffer[i]; } - // Marker Chunk ckID - aif->data[pos++] = 'M'; - aif->data[pos++] = 'A'; - aif->data[pos++] = 'R'; - aif->data[pos++] = 'K'; + if (aif_data->has_loop) + { - // Marker Chunk ckSize - aif->data[pos++] = 0; - aif->data[pos++] = 0; - aif->data[pos++] = 0; - aif->data[pos++] = 12 + (aif_data->has_loop ? 12 : 0); + // Marker Chunk ckID + aif->data[pos++] = 'M'; + aif->data[pos++] = 'A'; + aif->data[pos++] = 'R'; + aif->data[pos++] = 'K'; - // Marker Chunk numMarkers - aif->data[pos++] = 0; - aif->data[pos++] = (aif_data->has_loop ? 2 : 1); + // Marker Chunk ckSize + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 12 + (aif_data->has_loop ? 12 : 0); + + // Marker Chunk numMarkers + aif->data[pos++] = 0; + aif->data[pos++] = (aif_data->has_loop ? 2 : 1); - if (aif_data->has_loop) - { // Marker loop start aif->data[pos++] = 0; aif->data[pos++] = 1; // id = 1 @@ -684,22 +691,22 @@ void pcm2aif(const char *pcm_filename, const char *aif_filename, uint32_t base_n aif->data[pos++] = 'A'; aif->data[pos++] = 'R'; aif->data[pos++] = 'T'; // markerName - } - // Marker loop end - aif->data[pos++] = 0; - aif->data[pos++] = (aif_data->has_loop ? 2 : 1); // id = 2 - - long loop_end = aif_data->num_samples; - aif->data[pos++] = ((loop_end >> 24) & 0xFF); - aif->data[pos++] = ((loop_end >> 16) & 0xFF); - aif->data[pos++] = ((loop_end >> 8) & 0xFF); - aif->data[pos++] = (loop_end & 0xFF); // position - - aif->data[pos++] = 3; // pascal-style string length - aif->data[pos++] = 'E'; - aif->data[pos++] = 'N'; - aif->data[pos++] = 'D'; + // Marker loop end + aif->data[pos++] = 0; + aif->data[pos++] = (aif_data->has_loop ? 2 : 1); // id = 2 + + long loop_end = aif_data->num_samples; + aif->data[pos++] = ((loop_end >> 24) & 0xFF); + aif->data[pos++] = ((loop_end >> 16) & 0xFF); + aif->data[pos++] = ((loop_end >> 8) & 0xFF); + aif->data[pos++] = (loop_end & 0xFF); // position + + aif->data[pos++] = 3; // pascal-style string length + aif->data[pos++] = 'E'; + aif->data[pos++] = 'N'; + aif->data[pos++] = 'D'; + } // Instrument Chunk ckID aif->data[pos++] = 'I'; -- cgit v1.2.3 From de69de433b922502b6fe4ce966b7b636dcf53a71 Mon Sep 17 00:00:00 2001 From: yenatch Date: Sun, 8 Jan 2017 18:00:49 -0500 Subject: aif2pcm: Fix delta compression for foreign audio. The direction should not be reversed if the delta is too large. The new code is redundant, but the intent is more obvious. --- tools/aif2pcm/main.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'tools') diff --git a/tools/aif2pcm/main.c b/tools/aif2pcm/main.c index a2c3bcd5c..b7058f0c8 100644 --- a/tools/aif2pcm/main.c +++ b/tools/aif2pcm/main.c @@ -400,11 +400,9 @@ struct Bytes *delta_compress(struct Bytes *pcm) break; } hi = 0; - diff = pcm->data[i++] - base; - if (diff > 49) - { - diff = -diff; - } + diff = ((int8_t)pcm->data[i++]) - base; + if (diff > 49) diff = 49; + if (diff < -64) diff = -64; if (diff < 0) { for (l = 8; l < 16; l++) @@ -429,8 +427,9 @@ struct Bytes *delta_compress(struct Bytes *pcm) } for (k = 0; k < 31; k++) { - diff = pcm->data[i++] - base; - if (diff > 49) diff = -diff; + diff = ((int8_t)pcm->data[i++]) - base; + if (diff > 49) diff = 49; + if (diff < -64) diff = -64; if (diff < 0) { for (l = 8; l < 16; l++) @@ -453,8 +452,9 @@ struct Bytes *delta_compress(struct Bytes *pcm) { break; } - diff = pcm->data[i++] - base; - if (diff > 49) diff = -diff; + diff = ((int8_t)pcm->data[i++]) - base; + if (diff > 49) diff = 49; + if (diff < -64) diff = -64; if (diff < 0) { for (l = 8; l < 16; l++) -- cgit v1.2.3 From c1330157ee38703e79821fe3f485680b0157352c Mon Sep 17 00:00:00 2001 From: yenatch Date: Sun, 8 Jan 2017 18:08:25 -0500 Subject: aif2pcm: Accept .aiff files too. --- tools/aif2pcm/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/aif2pcm/main.c b/tools/aif2pcm/main.c index b7058f0c8..6eb47ade1 100644 --- a/tools/aif2pcm/main.c +++ b/tools/aif2pcm/main.c @@ -833,7 +833,7 @@ int main(int argc, char **argv) } } - if (strcmp(extension, "aif") == 0) + if (strcmp(extension, "aif") == 0 || strcmp(extension, "aiff") == 0) { if (argc >= 3) { -- cgit v1.2.3 From 42e277b2983ead33a0a9042bbff428f911bd23f3 Mon Sep 17 00:00:00 2001 From: YamaArashi Date: Sun, 8 Jan 2017 16:54:21 -0800 Subject: simplify delta compression algorithm --- tools/aif2pcm/main.c | 118 +++++++++++++++++---------------------------------- 1 file changed, 39 insertions(+), 79 deletions(-) (limited to 'tools') diff --git a/tools/aif2pcm/main.c b/tools/aif2pcm/main.c index 6eb47ade1..fbb024a1d 100644 --- a/tools/aif2pcm/main.c +++ b/tools/aif2pcm/main.c @@ -23,6 +23,7 @@ #include #include #include +#include /* extended.c */ void ieee754_write_extended (double, uint8_t*); @@ -287,7 +288,7 @@ void read_aif(struct Bytes *aif, AifData *aif_data) } // This is a table of deltas between sample values in compressed PCM data. -const int8_t gDeltaEncodingTable[] = { +const int gDeltaEncodingTable[] = { 0, 1, 4, 9, 16, 25, 36, 49, -64, -49, -36, -25, -16, -9, -4, -1, }; @@ -359,6 +360,26 @@ struct Bytes *delta_decompress(struct Bytes *delta, unsigned int expected_length return pcm; } +int get_delta_index(uint8_t sample, uint8_t prev_sample) +{ + int best_error = INT_MAX; + int best_index = -1; + + for (int i = 0; i < 16; i++) + { + uint8_t new_sample = prev_sample + gDeltaEncodingTable[i]; + int error = sample > new_sample ? sample - new_sample : new_sample - sample; + + if (error < best_error) + { + best_error = error; + best_index = i; + } + } + + return best_index; +} + struct Bytes *delta_compress(struct Bytes *pcm) { struct Bytes *delta = malloc(sizeof(struct Bytes)); @@ -384,103 +405,42 @@ struct Bytes *delta_compress(struct Bytes *pcm) delta->data = malloc(delta->length + 33); - uint8_t hi, lo; unsigned int i = 0; unsigned int j = 0; int k; - int l; - int8_t base; - int8_t diff; + uint8_t base; + int delta_index; + while (i < pcm->length) { - base = (int8_t)pcm->data[i++]; - delta->data[j++] = (uint8_t)base; - if (i >= pcm->length) - { - break; - } - hi = 0; - diff = ((int8_t)pcm->data[i++]) - base; - if (diff > 49) diff = 49; - if (diff < -64) diff = -64; - if (diff < 0) - { - for (l = 8; l < 16; l++) - { - lo = l & 0xf; - if (diff <= gDeltaEncodingTable[l]) break; - } - } - else - { - for (l = 0; l < 8; l++) - { - lo = l & 0xf; - if (diff <= gDeltaEncodingTable[l]) break; - } - } - base += diff; - delta->data[j++] = (hi << 4) | lo; + base = pcm->data[i++]; + delta->data[j++] = base; + if (i >= pcm->length) { break; } + delta_index = get_delta_index(pcm->data[i++], base); + base += gDeltaEncodingTable[delta_index]; + delta->data[j++] = delta_index; + for (k = 0; k < 31; k++) { - diff = ((int8_t)pcm->data[i++]) - base; - if (diff > 49) diff = 49; - if (diff < -64) diff = -64; - if (diff < 0) - { - for (l = 8; l < 16; l++) - { - hi = l & 0xf; - if (diff <= gDeltaEncodingTable[l]) break; - } - } - else - { - for (l = 0; l < 8; l++) - { - hi = l & 0xf; - if (diff <= gDeltaEncodingTable[l]) break; - } - } - base += diff; - delta->data[j] = (hi << 4); if (i >= pcm->length) { break; } - diff = ((int8_t)pcm->data[i++]) - base; - if (diff > 49) diff = 49; - if (diff < -64) diff = -64; - if (diff < 0) - { - for (l = 8; l < 16; l++) - { - lo = l & 0xf; - if (diff <= gDeltaEncodingTable[l]) break; - } - } - else - { - for (l = 0; l < 8; l++) - { - lo = l & 0xf; - if (diff <= gDeltaEncodingTable[l]) break; - } - } - base += diff; - delta->data[j++] = (hi << 4) | lo; + delta_index = get_delta_index(pcm->data[i++], base); + base += gDeltaEncodingTable[delta_index]; + delta->data[j] = (delta_index << 4); + if (i >= pcm->length) { break; } - } - if (i >= pcm->length) - { - break; + delta_index = get_delta_index(pcm->data[i++], base); + base += gDeltaEncodingTable[delta_index]; + delta->data[j++] |= delta_index; } } -- cgit v1.2.3 From 535ed69d33072543b543829b86409758cc7f6318 Mon Sep 17 00:00:00 2001 From: YamaArashi Date: Sun, 22 Jan 2017 21:55:01 -0800 Subject: change preproc syntax for C strings --- tools/preproc/c_file.cpp | 183 ++++++++++++++++++++++++++++++---------------- tools/preproc/c_file.h | 4 + tools/preproc/char_util.h | 4 +- 3 files changed, 124 insertions(+), 67 deletions(-) (limited to 'tools') diff --git a/tools/preproc/c_file.cpp b/tools/preproc/c_file.cpp index aed53d44b..4e6035214 100644 --- a/tools/preproc/c_file.cpp +++ b/tools/preproc/c_file.cpp @@ -72,8 +72,6 @@ CFile::~CFile() void CFile::Preproc() { - bool inConcatMode = false; - bool noTerminator = false; char stringChar = 0; while (m_pos < m_size) @@ -94,85 +92,140 @@ void CFile::Preproc() } else { + if (m_buffer[m_pos] == '\n') + m_lineNum++; std::putchar(m_buffer[m_pos]); m_pos++; } } else { - if (inConcatMode ? m_buffer[m_pos] == '"' - : (m_buffer[m_pos] == '_' || m_buffer[m_pos] == '@') && m_buffer[m_pos + 1] == '"') - { - if (!inConcatMode) - { - noTerminator = (m_buffer[m_pos] == '@'); - m_pos++; // skip past underscore or at-sign - } - - unsigned char s[kMaxStringLength]; - int length; - StringParser stringParser(m_buffer, m_size); - - try - { - m_pos += stringParser.ParseString(m_pos, s, length); - } - catch (std::runtime_error e) - { - RaiseError(e.what()); - } - - if (!inConcatMode) - { - std::printf("{ "); - } - - inConcatMode = true; - - for (int i = 0; i < length; i++) - printf("0x%02X, ", s[i]); - } - else - { - char c = m_buffer[m_pos++]; + TryConvertString(); - if (c == '\r') - { - if (m_buffer[m_pos] == '\n') - { - m_pos++; - } + char c = m_buffer[m_pos++]; - c = '\n'; - } + std::putchar(c); - if ((c != ' ' && c != '\t' && c != '\n') && inConcatMode) - { - if (noTerminator) - std::printf(" }"); - else - std::printf("0xFF }"); + if (c == '\n') + m_lineNum++; + else if (c == '"') + stringChar = '"'; + else if (m_buffer[m_pos] == '\'') + stringChar = '\''; + } + } +} - inConcatMode = false; - } +bool CFile::ConsumeHorizontalWhitespace() +{ + if (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ') + { + m_pos++; + return true; + } - std::putchar(c); + return false; +} - if (c == '\n') - m_lineNum++; - else if (c == '"') - stringChar = '"'; - else if (m_buffer[m_pos] == '\'') - stringChar = '\''; - } - } +bool CFile::ConsumeNewline() +{ + if (m_buffer[m_pos] == '\r' && m_buffer[m_pos + 1] == '\n') + { + m_pos += 2; + m_lineNum++; + return true; } - if (inConcatMode) + if (m_buffer[m_pos] == '\n') { - printf("0xFF }"); - RaiseWarning("string at end of file"); + m_pos++; + m_lineNum++; + return true; } + + return false; +} + +void CFile::SkipWhitespace() +{ + while (ConsumeHorizontalWhitespace() || ConsumeNewline()) + ; +} + +void CFile::TryConvertString() +{ + long oldPos = m_pos; + long oldLineNum = m_lineNum; + bool noTerminator = false; + + if (m_buffer[m_pos] != '_' || (m_pos > 0 && IsIdentifierChar(m_buffer[m_pos - 1]))) + return; + + m_pos++; + + if (m_buffer[m_pos] == '_') + { + noTerminator = true; + m_pos++; + } + + SkipWhitespace(); + + if (m_buffer[m_pos] != '(') + { + m_pos = oldPos; + m_lineNum = oldLineNum; + return; + } + + m_pos++; + + SkipWhitespace(); + + std::printf("{ "); + + while (1) + { + SkipWhitespace(); + + if (m_buffer[m_pos] == '"') + { + unsigned char s[kMaxStringLength]; + int length; + StringParser stringParser(m_buffer, m_size); + + try + { + m_pos += stringParser.ParseString(m_pos, s, length); + } + catch (std::runtime_error e) + { + RaiseError(e.what()); + } + + for (int i = 0; i < length; i++) + printf("0x%02X, ", s[i]); + } + else if (m_buffer[m_pos] == ')') + { + m_pos++; + break; + } + else + { + if (m_pos >= m_size) + RaiseError("unexpected EOF"); + if (IsAsciiPrintable(m_buffer[m_pos])) + RaiseError("unexpected character '%c'", m_buffer[m_pos]); + else + RaiseError("unexpected character '\\x%02X'", m_buffer[m_pos]); + } + } + + if (noTerminator) + std::printf(" }"); + else + std::printf("0xFF }"); } // Reports a diagnostic message. diff --git a/tools/preproc/c_file.h b/tools/preproc/c_file.h index b6041cc00..1a2573839 100644 --- a/tools/preproc/c_file.h +++ b/tools/preproc/c_file.h @@ -42,6 +42,10 @@ private: long m_lineNum; std::string m_filename; + bool ConsumeHorizontalWhitespace(); + bool ConsumeNewline(); + void SkipWhitespace(); + void TryConvertString(); void ReportDiagnostic(const char* type, const char* format, std::va_list args); void RaiseError(const char* format, ...); void RaiseWarning(const char* format, ...); diff --git a/tools/preproc/char_util.h b/tools/preproc/char_util.h index ab20dbc53..02a6e1ceb 100644 --- a/tools/preproc/char_util.h +++ b/tools/preproc/char_util.h @@ -56,13 +56,13 @@ inline bool IsAsciiPrintable(unsigned char c) return (c >= ' ' && c <= '~'); } -// Returns whether the character can start the identifier of a "{FOO}" constant in strings. +// Returns whether the character can start a C identifier or the identifier of a "{FOO}" constant in strings. inline bool IsIdentifierStartingChar(unsigned char c) { return IsAsciiAlpha(c) || c == '_'; } -// Returns whether the character can be used in the identifier of a "{FOO}" constant in strings. +// Returns whether the character can be used in a C identifier or the identifier of a "{FOO}" constant in strings. inline bool IsIdentifierChar(unsigned char c) { return IsAsciiAlphanum(c) || c == '_'; -- cgit v1.2.3 From c8542506580c0fa247bbb44c169a2cb1244577e4 Mon Sep 17 00:00:00 2001 From: YamaArashi Date: Mon, 23 Jan 2017 16:34:20 -0800 Subject: preproc incbins --- tools/preproc/asm_file.cpp | 37 +---- tools/preproc/c_file.cpp | 161 ++++++++++++++++++- tools/preproc/c_file.h | 4 + tools/scaninc/Makefile | 6 +- tools/scaninc/asm_file.cpp | 191 +++++++++++++++++++++++ tools/scaninc/asm_file.h | 119 ++++++++++++++ tools/scaninc/c_file.cpp | 329 ++++++++++++++++++++++++++++++++++++++ tools/scaninc/c_file.h | 54 +++++++ tools/scaninc/scaninc.cpp | 382 ++++++++++----------------------------------- tools/scaninc/scaninc.h | 59 +++++++ 10 files changed, 1008 insertions(+), 334 deletions(-) create mode 100644 tools/scaninc/asm_file.cpp create mode 100644 tools/scaninc/asm_file.h create mode 100644 tools/scaninc/c_file.cpp create mode 100644 tools/scaninc/c_file.h create mode 100644 tools/scaninc/scaninc.h (limited to 'tools') diff --git a/tools/preproc/asm_file.cpp b/tools/preproc/asm_file.cpp index 7deaccc8a..49c9e3c66 100644 --- a/tools/preproc/asm_file.cpp +++ b/tools/preproc/asm_file.cpp @@ -111,45 +111,22 @@ void AsmFile::RemoveComments() m_buffer[pos++] = ' '; m_buffer[pos++] = ' '; - char commentStringChar = 0; - for (;;) { if (m_buffer[pos] == 0) return; - if (commentStringChar != 0) + if (m_buffer[pos] == '*' && m_buffer[pos + 1] == '/') { - if (m_buffer[pos] == '\\' && m_buffer[pos + 1] == commentStringChar) - { - m_buffer[pos++] = ' '; - m_buffer[pos++] = ' '; - } - else - { - if (m_buffer[pos] == commentStringChar) - commentStringChar = 0; - if (m_buffer[pos] != '\n') - m_buffer[pos] = ' '; - pos++; - } + m_buffer[pos++] = ' '; + m_buffer[pos++] = ' '; + break; } else { - if (m_buffer[pos] == '*' && m_buffer[pos + 1] == '/') - { - m_buffer[pos++] = ' '; - m_buffer[pos++] = ' '; - break; - } - else - { - if (m_buffer[pos] == '"' || m_buffer[pos] == '\'') - commentStringChar = m_buffer[pos]; - if (m_buffer[pos] != '\n') - m_buffer[pos] = ' '; - pos++; - } + if (m_buffer[pos] != '\n') + m_buffer[pos] = ' '; + pos++; } } } diff --git a/tools/preproc/c_file.cpp b/tools/preproc/c_file.cpp index 4e6035214..cd11c8f6d 100644 --- a/tools/preproc/c_file.cpp +++ b/tools/preproc/c_file.cpp @@ -20,6 +20,8 @@ #include #include +#include +#include #include "preproc.h" #include "c_file.h" #include "char_util.h" @@ -101,6 +103,10 @@ void CFile::Preproc() else { TryConvertString(); + TryConvertIncbin(); + + if (m_pos >= m_size) + break; char c = m_buffer[m_pos++]; @@ -110,7 +116,7 @@ void CFile::Preproc() m_lineNum++; else if (c == '"') stringChar = '"'; - else if (m_buffer[m_pos] == '\'') + else if (c == '\'') stringChar = '\''; } } @@ -228,6 +234,159 @@ void CFile::TryConvertString() std::printf("0xFF }"); } +bool CFile::CheckIdentifier(const std::string& ident) +{ + int i; + + for (i = 0; (unsigned)i < ident.length() && m_pos + i < m_size; i++) + if (ident[i] != m_buffer[m_pos + i]) + return false; + + return (i == ident.length()); +} + +std::unique_ptr CFile::ReadWholeFile(const std::string& path, int& size) +{ + FILE* fp = fopen(path.c_str(), "rb"); + + if (fp == nullptr) + RaiseError("Failed to open \"%s\" for reading.\n", path.c_str()); + + fseek(fp, 0, SEEK_END); + + size = ftell(fp); + + std::unique_ptr buffer = std::make_unique(size); + + rewind(fp); + + if (fread(buffer.get(), size, 1, fp) != 1) + RaiseError("Failed to read \"%s\".\n", path.c_str()); + + fclose(fp); + + return buffer; +} + +int ExtractData(const std::unique_ptr& buffer, int offset, int size) +{ + switch (size) + { + case 1: + return buffer[offset]; + case 2: + return (buffer[offset + 1] << 8) + | buffer[offset]; + case 4: + return (buffer[offset + 3] << 24) + | (buffer[offset + 2] << 16) + | (buffer[offset + 1] << 8) + | buffer[offset]; + default: + FATAL_ERROR("Invalid size passed to ExtractData.\n"); + } +} + +void CFile::TryConvertIncbin() +{ + std::string idents[6] = { "INCBIN_S8", "INCBIN_U8", "INCBIN_S16", "INCBIN_U16", "INCBIN_S32", "INCBIN_U32" }; + int incbinType = -1; + + for (int i = 0; i < 6; i++) + { + if (CheckIdentifier(idents[i])) + { + incbinType = i; + break; + } + } + + if (incbinType == -1) + return; + + int size = 1 << (incbinType / 2); + bool isSigned = ((incbinType % 2) == 0); + + long oldPos = m_pos; + long oldLineNum = m_lineNum; + + m_pos += idents[incbinType].length(); + + SkipWhitespace(); + + if (m_buffer[m_pos] != '(') + { + m_pos = oldPos; + m_lineNum = oldLineNum; + return; + } + + m_pos++; + + SkipWhitespace(); + + if (m_buffer[m_pos] != '"') + RaiseError("expected double quote"); + + m_pos++; + + int startPos = m_pos; + + while (m_buffer[m_pos] != '"') + { + if (m_buffer[m_pos] == 0) + { + if (m_pos >= m_size) + RaiseError("unexpected EOF in path string"); + else + RaiseError("unexpected null character in path string"); + } + + if (m_buffer[m_pos] == '\r' || m_buffer[m_pos] == '\n') + RaiseError("unexpected end of line character in path string"); + + if (m_buffer[m_pos] == '\\') + RaiseError("unexpected escape in path string"); + + m_pos++; + } + + std::string path(&m_buffer[startPos], m_pos - startPos); + + m_pos++; + + SkipWhitespace(); + + if (m_buffer[m_pos] != ')') + RaiseError("expected ')'"); + + m_pos++; + + std::printf("{"); + + int fileSize; + std::unique_ptr buffer = ReadWholeFile(path, fileSize); + + if ((fileSize % size) != 0) + RaiseError("Size %d doesn't evenly divide file size %d.\n", size, fileSize); + + int count = fileSize / size; + int offset = 0; + + for (int i = 0; i < count; i++) + { + int data = ExtractData(buffer, offset, size); + offset += size; + + if (isSigned) + printf("%d,", data); + else + printf("%uu,", data); + } + + std::printf("}"); +} + // Reports a diagnostic message. void CFile::ReportDiagnostic(const char* type, const char* format, std::va_list args) { diff --git a/tools/preproc/c_file.h b/tools/preproc/c_file.h index 1a2573839..ddd57fd84 100644 --- a/tools/preproc/c_file.h +++ b/tools/preproc/c_file.h @@ -24,6 +24,7 @@ #include #include #include +#include #include "preproc.h" class CFile @@ -46,6 +47,9 @@ private: bool ConsumeNewline(); void SkipWhitespace(); void TryConvertString(); + std::unique_ptr CFile::ReadWholeFile(const std::string& path, int& size); + bool CheckIdentifier(const std::string& ident); + void TryConvertIncbin(); void ReportDiagnostic(const char* type, const char* format, std::va_list args); void RaiseError(const char* format, ...); void RaiseWarning(const char* format, ...); diff --git a/tools/scaninc/Makefile b/tools/scaninc/Makefile index 0efe283f1..71c4389ef 100644 --- a/tools/scaninc/Makefile +++ b/tools/scaninc/Makefile @@ -2,11 +2,13 @@ CXX = g++ CXXFLAGS = -Wall -std=c++11 -O2 -SRCS = scaninc.cpp +SRCS = scaninc.cpp c_file.cpp asm_file.cpp + +HEADERS := scaninc.h asm_file.h c_file.h .PHONY: clean -scaninc: $(SRCS) +scaninc: $(SRCS) $(HEADERS) $(CXX) $(CXXFLAGS) $(SRCS) -o $@ clean: diff --git a/tools/scaninc/asm_file.cpp b/tools/scaninc/asm_file.cpp new file mode 100644 index 000000000..143c70242 --- /dev/null +++ b/tools/scaninc/asm_file.cpp @@ -0,0 +1,191 @@ +// Copyright(c) 2015-2017 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include +#include +#include "scaninc.h" +#include "asm_file.h" + +AsmFile::AsmFile(std::string path) +{ + m_path = path; + + FILE *fp = fopen(path.c_str(), "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for reading.\n", path.c_str()); + + fseek(fp, 0, SEEK_END); + + m_size = ftell(fp); + + m_buffer = new char[m_size]; + + rewind(fp); + + if (fread(m_buffer, m_size, 1, fp) != 1) + FATAL_ERROR("Failed to read \"%s\".\n", path.c_str()); + + fclose(fp); + + m_pos = 0; + m_lineNum = 1; +} + +AsmFile::~AsmFile() +{ + delete[] m_buffer; +} + +IncDirectiveType AsmFile::ReadUntilIncDirective(std::string &path) +{ + // At the beginning of each loop iteration, the current file position + // should be at the start of a line or at the end of the file. + for (;;) + { + SkipTabsAndSpaces(); + + IncDirectiveType incDirectiveType = IncDirectiveType::None; + + if (PeekChar() == '.') + { + m_pos++; + + if (MatchIncDirective("incbin", path)) + incDirectiveType = IncDirectiveType::Incbin; + else if (MatchIncDirective("include", path)) + incDirectiveType = IncDirectiveType::Include; + } + + for (;;) + { + int c = GetChar(); + + if (c == -1) + return incDirectiveType; + + if (c == ';') + { + SkipEndOfLineComment(); + break; + } + else if (c == '/' && PeekChar() == '*') + { + m_pos++; + SkipMultiLineComment(); + } + else if (c == '"') + { + SkipString(); + } + else if (c == '\n') + { + break; + } + } + + if (incDirectiveType != IncDirectiveType::None) + return incDirectiveType; + } +} + +std::string AsmFile::ReadPath() +{ + int length = 0; + int startPos = m_pos; + + for (;;) + { + int c = GetChar(); + + if (c == '"') + break; + + if (c == -1) + FATAL_INPUT_ERROR("unexpected EOF in include string\n"); + + if (c == 0) + FATAL_INPUT_ERROR("unexpected NUL character in include string\n"); + + if (c == '\n') + FATAL_INPUT_ERROR("unexpected end of line character in include string\n"); + + // Don't bother allowing any escape sequences. + if (c == '\\') + FATAL_INPUT_ERROR("unexpected escape in include string\n"); + + length++; + + if (length > SCANINC_MAX_PATH) + FATAL_INPUT_ERROR("path is too long"); + } + + return std::string(m_buffer, startPos, length); +} + +void AsmFile::SkipEndOfLineComment() +{ + int c; + + do + { + c = GetChar(); + } while (c != -1 && c != '\n'); +} + +void AsmFile::SkipMultiLineComment() +{ + for (;;) + { + int c = GetChar(); + + if (c == '*') + { + if (PeekChar() == '/') + { + m_pos++; + return; + } + } + else if (c == -1) + { + return; + } + } +} + +void AsmFile::SkipString() +{ + for (;;) + { + int c = GetChar(); + + if (c == '"') + break; + + if (c == -1) + FATAL_INPUT_ERROR("unexpected EOF in string\n"); + + if (c == '\\') + { + c = GetChar(); + } + } +} diff --git a/tools/scaninc/asm_file.h b/tools/scaninc/asm_file.h new file mode 100644 index 000000000..ad99b757e --- /dev/null +++ b/tools/scaninc/asm_file.h @@ -0,0 +1,119 @@ +// Copyright(c) 2015-2017 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASM_FILE_H +#define ASM_FILE_H + +#include +#include "scaninc.h" + +enum class IncDirectiveType +{ + None, + Include, + Incbin +}; + +class AsmFile +{ +public: + AsmFile(std::string path); + ~AsmFile(); + IncDirectiveType ReadUntilIncDirective(std::string& path); + +private: + char *m_buffer; + int m_pos; + int m_size; + int m_lineNum; + std::string m_path; + + int GetChar() + { + if (m_pos >= m_size) + return -1; + + int c = m_buffer[m_pos++]; + + if (c == '\r') + { + if (m_pos < m_size && m_buffer[m_pos++] == '\n') + { + m_lineNum++; + return '\n'; + } + else + { + FATAL_INPUT_ERROR("CR line endings are not supported\n"); + } + } + + if (c == '\n') + m_lineNum++; + + return c; + } + + // No newline translation because it's not needed for any use of this function. + int PeekChar() + { + if (m_pos >= m_size) + return -1; + + return m_buffer[m_pos]; + } + + void SkipTabsAndSpaces() + { + while (m_pos < m_size && (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ')) + m_pos++; + } + + bool MatchIncDirective(std::string directiveName, std::string& path) + { + int length = directiveName.length(); + int i; + + for (i = 0; i < length && m_pos + i < m_size; i++) + if (directiveName[i] != m_buffer[m_pos + i]) + return false; + + if (i < length) + return false; + + m_pos += length; + + SkipTabsAndSpaces(); + + if (GetChar() != '"') + FATAL_INPUT_ERROR("no path after \".%s\" directive\n", directiveName.c_str()); + + path = ReadPath(); + + return true; + } + + std::string ReadPath(); + void SkipEndOfLineComment(); + void SkipMultiLineComment(); + void SkipString(); +}; + +#endif // ASM_FILE_H diff --git a/tools/scaninc/c_file.cpp b/tools/scaninc/c_file.cpp new file mode 100644 index 000000000..4af741f6e --- /dev/null +++ b/tools/scaninc/c_file.cpp @@ -0,0 +1,329 @@ +// Copyright(c) 2017 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "c_file.h" + +CFile::CFile(std::string path) +{ + m_path = path; + + FILE *fp = fopen(path.c_str(), "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for reading.\n", path.c_str()); + + fseek(fp, 0, SEEK_END); + + m_size = ftell(fp); + + m_buffer = new char[m_size + 1]; + m_buffer[m_size] = 0; + + rewind(fp); + + if (fread(m_buffer, m_size, 1, fp) != 1) + FATAL_ERROR("Failed to read \"%s\".\n", path.c_str()); + + fclose(fp); + + m_pos = 0; + m_lineNum = 1; + + RemoveComments(); +} + +CFile::~CFile() +{ + delete[] m_buffer; +} + +// Removes comments to simplify further processing. +// It stops upon encountering a null character, +// which may or may not be the end of file marker. +// If it's not, the error will be caught later. +void CFile::RemoveComments() +{ + long pos = 0; + char stringChar = 0; + + for (;;) + { + if (m_buffer[pos] == 0) + return; + + if (stringChar != 0) + { + if (m_buffer[pos] == '\\' && m_buffer[pos + 1] == stringChar) + { + pos += 2; + } + else + { + if (m_buffer[pos] == stringChar) + stringChar = 0; + pos++; + } + } + else if (m_buffer[pos] == '/' && m_buffer[pos + 1] == '/') + { + while (m_buffer[pos] != '\n' && m_buffer[pos] != 0) + m_buffer[pos++] = ' '; + } + else if (m_buffer[pos] == '/' && m_buffer[pos + 1] == '*') + { + m_buffer[pos++] = ' '; + m_buffer[pos++] = ' '; + + for (;;) + { + if (m_buffer[pos] == 0) + return; + + if (m_buffer[pos] == '*' && m_buffer[pos + 1] == '/') + { + m_buffer[pos++] = ' '; + m_buffer[pos++] = ' '; + break; + } + else + { + if (m_buffer[pos] != '\n') + m_buffer[pos] = ' '; + pos++; + } + } + } + else + { + if (m_buffer[pos] == '"' || m_buffer[pos] == '\'') + stringChar = m_buffer[pos]; + pos++; + } + } +} + +void CFile::FindIncbins() +{ + char stringChar = 0; + + while (m_pos < m_size) + { + if (stringChar) + { + if (m_buffer[m_pos] == stringChar) + { + m_pos++; + stringChar = 0; + } + else if (m_buffer[m_pos] == '\\' && m_buffer[m_pos + 1] == stringChar) + { + m_pos += 2; + } + else + { + if (m_buffer[m_pos] == '\n') + m_lineNum++; + m_pos++; + } + } + else + { + CheckIncbin(); + + if (m_pos >= m_size) + break; + + char c = m_buffer[m_pos++]; + + if (c == '\n') + m_lineNum++; + else if (c == '"') + stringChar = '"'; + else if (c == '\'') + stringChar = '\''; + else if (c == 0) + FATAL_INPUT_ERROR("unexpected null character"); + } + } +} + +bool CFile::ConsumeHorizontalWhitespace() +{ + if (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ') + { + m_pos++; + return true; + } + + return false; +} + +bool CFile::ConsumeNewline() +{ + if (m_buffer[m_pos] == '\r' && m_buffer[m_pos + 1] == '\n') + { + m_pos += 2; + m_lineNum++; + return true; + } + + if (m_buffer[m_pos] == '\n') + { + m_pos++; + m_lineNum++; + return true; + } + + return false; +} + +void CFile::SkipWhitespace() +{ + while (ConsumeHorizontalWhitespace() || ConsumeNewline()) + ; +} + +bool CFile::CheckIdentifier(const std::string& ident) +{ + int i; + + for (i = 0; (unsigned)i < ident.length() && m_pos + i < m_size; i++) + if (ident[i] != m_buffer[m_pos + i]) + return false; + + return (i == ident.length()); +} + +std::unique_ptr CFile::ReadWholeFile(const std::string& path, int& size) +{ + FILE* fp = fopen(path.c_str(), "rb"); + + if (fp == nullptr) + FATAL_INPUT_ERROR("Failed to open \"%s\" for reading.\n", path.c_str()); + + fseek(fp, 0, SEEK_END); + + size = ftell(fp); + + std::unique_ptr buffer = std::make_unique(size); + + rewind(fp); + + if (fread(buffer.get(), size, 1, fp) != 1) + FATAL_INPUT_ERROR("Failed to read \"%s\".\n", path.c_str()); + + fclose(fp); + + return buffer; +} + +int ExtractData(const std::unique_ptr& buffer, int offset, int size) +{ + switch (size) + { + case 1: + return buffer[offset]; + case 2: + return (buffer[offset + 1] << 8) + | buffer[offset]; + case 4: + return (buffer[offset + 3] << 24) + | (buffer[offset + 2] << 16) + | (buffer[offset + 1] << 8) + | buffer[offset]; + default: + FATAL_ERROR("Invalid size passed to ExtractData.\n"); + } +} + +void CFile::CheckIncbin() +{ + std::string idents[6] = { "INCBIN_S8", "INCBIN_U8", "INCBIN_S16", "INCBIN_U16", "INCBIN_S32", "INCBIN_U32" }; + int incbinType = -1; + + for (int i = 0; i < 6; i++) + { + if (CheckIdentifier(idents[i])) + { + incbinType = i; + break; + } + } + + if (incbinType == -1) + return; + + long oldPos = m_pos; + long oldLineNum = m_lineNum; + + m_pos += idents[incbinType].length(); + + SkipWhitespace(); + + if (m_buffer[m_pos] != '(') + { + m_pos = oldPos; + m_lineNum = oldLineNum; + return; + } + + m_pos++; + + SkipWhitespace(); + + if (m_buffer[m_pos] != '"') + FATAL_INPUT_ERROR("expected double quote"); + + m_pos++; + + int startPos = m_pos; + + while (m_buffer[m_pos] != '"') + { + if (m_buffer[m_pos] == 0) + { + if (m_pos >= m_size) + FATAL_INPUT_ERROR("unexpected EOF in path string"); + else + FATAL_INPUT_ERROR("unexpected null character in path string"); + } + + if (m_buffer[m_pos] == '\r' || m_buffer[m_pos] == '\n') + FATAL_INPUT_ERROR("unexpected end of line character in path string"); + + if (m_buffer[m_pos] == '\\') + FATAL_INPUT_ERROR("unexpected escape in path string"); + + m_pos++; + } + + std::string path(&m_buffer[startPos], m_pos - startPos); + + m_pos++; + + SkipWhitespace(); + + if (m_buffer[m_pos] != ')') + FATAL_INPUT_ERROR("expected ')'"); + + m_pos++; + + m_incbins.emplace(path); +} diff --git a/tools/scaninc/c_file.h b/tools/scaninc/c_file.h new file mode 100644 index 000000000..fcd327d28 --- /dev/null +++ b/tools/scaninc/c_file.h @@ -0,0 +1,54 @@ +// Copyright(c) 2017 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef C_FILE_H +#define C_FILE_H + +#include +#include +#include +#include "scaninc.h" + +class CFile +{ +public: + CFile(std::string path); + ~CFile(); + void FindIncbins(); + const std::set& GetIncbins() { return m_incbins; } + +private: + char *m_buffer; + int m_pos; + int m_size; + int m_lineNum; + std::string m_path; + std::set m_incbins; + + void CFile::RemoveComments(); + bool ConsumeHorizontalWhitespace(); + bool ConsumeNewline(); + void SkipWhitespace(); + std::unique_ptr CFile::ReadWholeFile(const std::string& path, int& size); + bool CheckIdentifier(const std::string& ident); + void CheckIncbin(); +}; + +#endif // C_FILE_H diff --git a/tools/scaninc/scaninc.cpp b/tools/scaninc/scaninc.cpp index 3bd6b81a5..2f9ed81e9 100644 --- a/tools/scaninc/scaninc.cpp +++ b/tools/scaninc/scaninc.cpp @@ -1,317 +1,97 @@ -// Copyright (c) 2015 YamaArashi +// Copyright(c) 2015-2017 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. #include #include #include #include #include - -#ifdef _MSC_VER - -#define FATAL_INPUT_ERROR(format, ...) \ -do { \ - fprintf(stderr, "%s:%d " format, m_path.c_str(), m_lineNum, __VA_ARGS__); \ - exit(1); \ -} while (0) - -#define FATAL_ERROR(format, ...) \ -do { \ - fprintf(stderr, format, __VA_ARGS__); \ - exit(1); \ -} while (0) - -#else - -#define FATAL_INPUT_ERROR(format, ...) \ -do { \ - fprintf(stderr, "%s:%d " format, m_path.c_str(), m_lineNum, ##__VA_ARGS__); \ - exit(1); \ -} while (0) - -#define FATAL_ERROR(format, ...) \ -do { \ - fprintf(stderr, format, ##__VA_ARGS__); \ - exit(1); \ -} while (0) - -#endif // _MSC_VER - -#define SCANINC_MAX_PATH 255 - -enum class IncDirectiveType { - None, - Include, - Incbin -}; - -class AsmFile -{ -public: - AsmFile(std::string path); - ~AsmFile(); - IncDirectiveType ReadUntilIncDirective(std::string &path); - -private: - char *m_buffer; - int m_pos; - int m_size; - int m_lineNum; - std::string m_path; - - int GetChar() - { - if (m_pos >= m_size) - return -1; - - int c = m_buffer[m_pos++]; - - if (c == '\r') { - if (m_pos < m_size && m_buffer[m_pos++] == '\n') { - m_lineNum++; - return '\n'; - } else { - FATAL_INPUT_ERROR("CR line endings are not supported\n"); - } - } - - if (c == '\n') - m_lineNum++; - - return c; - } - - // No newline translation because it's not needed for any use of this function. - int PeekChar() - { - if (m_pos >= m_size) - return -1; - - return m_buffer[m_pos]; - } - - void SkipTabsAndSpaces() - { - while (m_pos < m_size && (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ')) - m_pos++; - } - - bool MatchIncDirective(std::string directiveName, std::string &path) - { - int length = directiveName.length(); - int i; - - for (i = 0; i < length && m_pos + i < m_size; i++) - if (directiveName[i] != m_buffer[m_pos + i]) - return false; - - if (i < length) - return false; - - m_pos += length; - - SkipTabsAndSpaces(); - - if (GetChar() != '"') - FATAL_INPUT_ERROR("no path after \".%s\" directive\n", directiveName.c_str()); - - path = ReadPath(); - - return true; - } - - std::string ReadPath(); - void SkipEndOfLineComment(); - void SkipMultiLineComment(); - void SkipString(); -}; - -AsmFile::AsmFile(std::string path) -{ - m_path = path; - - FILE *fp = fopen(path.c_str(), "rb"); - - if (fp == NULL) - FATAL_ERROR("Failed to open \"%s\" for reading.\n", path.c_str()); - - fseek(fp, 0, SEEK_END); - - m_size = ftell(fp); - - m_buffer = new char[m_size]; - - rewind(fp); - - if (fread(m_buffer, m_size, 1, fp) != 1) - FATAL_ERROR("Failed to read \"%s\".\n", path.c_str()); - - fclose(fp); - - m_pos = 0; - m_lineNum = 1; -} - -AsmFile::~AsmFile() -{ - delete[] m_buffer; -} - -IncDirectiveType AsmFile::ReadUntilIncDirective(std::string &path) -{ - // At the beginning of each loop iteration, the current file position - // should be at the start of a line or at the end of the file. - for (;;) { - SkipTabsAndSpaces(); - - IncDirectiveType incDirectiveType = IncDirectiveType::None; - - if (PeekChar() == '.') { - m_pos++; - - if (MatchIncDirective("incbin", path)) - incDirectiveType = IncDirectiveType::Incbin; - else if (MatchIncDirective("include", path)) - incDirectiveType = IncDirectiveType::Include; - } - - for (;;) { - int c = GetChar(); - - if (c == -1) - return incDirectiveType; - - if (c == ';') { - SkipEndOfLineComment(); - break; - } else if (c == '/' && PeekChar() == '*') { - m_pos++; - SkipMultiLineComment(); - } else if (c == '"') { - SkipString(); - } else if (c == '\n') { - break; - } - } - - if (incDirectiveType != IncDirectiveType::None) - return incDirectiveType; - } -} - -std::string AsmFile::ReadPath() -{ - int length = 0; - int startPos = m_pos; - - for (;;) { - int c = GetChar(); - - if (c == '"') - break; - - if (c == -1) - FATAL_INPUT_ERROR("unexpected EOF in include string\n"); - - if (c == 0) - FATAL_INPUT_ERROR("unexpected NUL character in include string\n"); - - if (c == '\n') - FATAL_INPUT_ERROR("unexpected end of line character in include string\n"); - - // Don't bother allowing any escape sequences. - if (c == '\\') - FATAL_INPUT_ERROR("unexpected escape '\\%c' in include string\n", c); - - length++; - - if (length > SCANINC_MAX_PATH) - FATAL_INPUT_ERROR("path is too long"); - } - - return std::string(m_buffer, startPos, length); -} - -void AsmFile::SkipEndOfLineComment() -{ - int c; - - do { - c = GetChar(); - } while (c != -1 && c != '\n'); -} - -void AsmFile::SkipMultiLineComment() -{ - for (;;) { - int c = GetChar(); - - if (c == '*') { - if (PeekChar() == '/') { - m_pos++; - return; - } - } else if (c == -1) { - return; - } - } -} - -void AsmFile::SkipString() -{ - for (;;) { - int c = GetChar(); - - if (c == '"') - break; - - if (c == -1) - FATAL_INPUT_ERROR("unexpected EOF in string\n"); - - if (c == '\\') { - c = GetChar(); - } - } -} +#include "scaninc.h" +#include "asm_file.h" +#include "c_file.h" bool CanOpenFile(std::string path) { - FILE *fp = fopen(path.c_str(), "rb"); + FILE *fp = fopen(path.c_str(), "rb"); - if (fp == NULL) - return false; + if (fp == NULL) + return false; - fclose(fp); - return true; + fclose(fp); + return true; } int main(int argc, char **argv) { - if (argc < 2) - FATAL_ERROR("Usage: scaninc ASM_FILE_PATH\n"); - - std::stack filesToProcess; - std::set dependencies; - - filesToProcess.push(std::string(argv[1])); - - while (!filesToProcess.empty()) { - AsmFile file(filesToProcess.top()); - - filesToProcess.pop(); - - IncDirectiveType incDirectiveType; - std::string path; - - while ((incDirectiveType = file.ReadUntilIncDirective(path)) != IncDirectiveType::None) { - bool inserted = dependencies.insert(path).second; - if (inserted - && incDirectiveType == IncDirectiveType::Include - && CanOpenFile(path)) - filesToProcess.push(path); - } - } - - for (const std::string &path : dependencies) { - printf("%s\n", path.c_str()); - } + if (argc < 2) + FATAL_ERROR("Usage: scaninc FILE_PATH\n"); + + std::stack filesToProcess; + std::set dependencies; + + std::string initialPath(argv[1]); + + std::size_t pos = initialPath.find_last_of('.'); + + if (pos == std::string::npos) + FATAL_ERROR("no file extension in path \"%s\"\n", initialPath.c_str()); + + std::string extension = initialPath.substr(pos + 1); + + if (extension == "c") + { + CFile file(initialPath); + + file.FindIncbins(); + dependencies = file.GetIncbins(); + } + else if (extension == "s") + { + filesToProcess.push(std::string(argv[1])); + + while (!filesToProcess.empty()) + { + AsmFile file(filesToProcess.top()); + + filesToProcess.pop(); + + IncDirectiveType incDirectiveType; + std::string path; + + while ((incDirectiveType = file.ReadUntilIncDirective(path)) != IncDirectiveType::None) + { + bool inserted = dependencies.insert(path).second; + if (inserted + && incDirectiveType == IncDirectiveType::Include + && CanOpenFile(path)) + filesToProcess.push(path); + } + } + } + else + { + FATAL_ERROR("unknown extension \"%s\"\n", extension.c_str()); + } + + for (const std::string &path : dependencies) + { + printf("%s\n", path.c_str()); + } } diff --git a/tools/scaninc/scaninc.h b/tools/scaninc/scaninc.h new file mode 100644 index 000000000..30cc9611c --- /dev/null +++ b/tools/scaninc/scaninc.h @@ -0,0 +1,59 @@ +// Copyright(c) 2015-2017 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef SCANINC_H +#define SCANINC_H + +#include +#include + +#ifdef _MSC_VER + +#define FATAL_INPUT_ERROR(format, ...) \ +do { \ + fprintf(stderr, "%s:%d " format, m_path.c_str(), m_lineNum, __VA_ARGS__); \ + exit(1); \ +} while (0) + +#define FATAL_ERROR(format, ...) \ +do { \ + fprintf(stderr, format, __VA_ARGS__); \ + exit(1); \ +} while (0) + +#else + +#define FATAL_INPUT_ERROR(format, ...) \ +do { \ + fprintf(stderr, "%s:%d " format, m_path.c_str(), m_lineNum, ##__VA_ARGS__); \ + exit(1); \ +} while (0) + +#define FATAL_ERROR(format, ...) \ +do { \ + fprintf(stderr, format, ##__VA_ARGS__); \ + exit(1); \ +} while (0) + +#endif // _MSC_VER + +#define SCANINC_MAX_PATH 255 + +#endif // SCANINC_H -- cgit v1.2.3 From 3f2ea6a1f076575d0c61ca0b71917704e38f6dd7 Mon Sep 17 00:00:00 2001 From: Cameron Hall Date: Tue, 24 Jan 2017 19:50:28 -0600 Subject: make preproc build under GCC (#215) --- tools/preproc/Makefile | 2 +- tools/preproc/c_file.cpp | 4 ++-- tools/preproc/c_file.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/preproc/Makefile b/tools/preproc/Makefile index 2d577c79f..24f60e3f6 100644 --- a/tools/preproc/Makefile +++ b/tools/preproc/Makefile @@ -1,6 +1,6 @@ CXX := g++ -CXXFLAGS := -std=c++11 -O2 -Wall -Wno-switch +CXXFLAGS := -std=c++14 -O2 -Wall -Wno-switch SRCS := asm_file.cpp c_file.cpp charmap.cpp preproc.cpp string_parser.cpp \ utf8.cpp diff --git a/tools/preproc/c_file.cpp b/tools/preproc/c_file.cpp index cd11c8f6d..3b4024efe 100644 --- a/tools/preproc/c_file.cpp +++ b/tools/preproc/c_file.cpp @@ -236,9 +236,9 @@ void CFile::TryConvertString() bool CFile::CheckIdentifier(const std::string& ident) { - int i; + unsigned int i; - for (i = 0; (unsigned)i < ident.length() && m_pos + i < m_size; i++) + for (i = 0; i < ident.length() && m_pos + i < (unsigned)m_size; i++) if (ident[i] != m_buffer[m_pos + i]) return false; diff --git a/tools/preproc/c_file.h b/tools/preproc/c_file.h index ddd57fd84..7369aba85 100644 --- a/tools/preproc/c_file.h +++ b/tools/preproc/c_file.h @@ -47,7 +47,7 @@ private: bool ConsumeNewline(); void SkipWhitespace(); void TryConvertString(); - std::unique_ptr CFile::ReadWholeFile(const std::string& path, int& size); + std::unique_ptr ReadWholeFile(const std::string& path, int& size); bool CheckIdentifier(const std::string& ident); void TryConvertIncbin(); void ReportDiagnostic(const char* type, const char* format, std::va_list args); -- cgit v1.2.3 From 72bc8f23d37c6efd68ad4a0f86ba87b6cd3db4d2 Mon Sep 17 00:00:00 2001 From: Cameron Hall Date: Thu, 26 Jan 2017 01:15:49 -0500 Subject: make scaninc build under GCC (#218) --- tools/scaninc/Makefile | 2 +- tools/scaninc/c_file.cpp | 4 ++-- tools/scaninc/c_file.h | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/scaninc/Makefile b/tools/scaninc/Makefile index 71c4389ef..c408e4a6e 100644 --- a/tools/scaninc/Makefile +++ b/tools/scaninc/Makefile @@ -1,6 +1,6 @@ CXX = g++ -CXXFLAGS = -Wall -std=c++11 -O2 +CXXFLAGS = -Wall -std=c++14 -O2 SRCS = scaninc.cpp c_file.cpp asm_file.cpp diff --git a/tools/scaninc/c_file.cpp b/tools/scaninc/c_file.cpp index 4af741f6e..970fbe135 100644 --- a/tools/scaninc/c_file.cpp +++ b/tools/scaninc/c_file.cpp @@ -202,9 +202,9 @@ void CFile::SkipWhitespace() bool CFile::CheckIdentifier(const std::string& ident) { - int i; + unsigned int i; - for (i = 0; (unsigned)i < ident.length() && m_pos + i < m_size; i++) + for (i = 0; i < ident.length() && m_pos + i < (unsigned)m_size; i++) if (ident[i] != m_buffer[m_pos + i]) return false; diff --git a/tools/scaninc/c_file.h b/tools/scaninc/c_file.h index fcd327d28..2503acac1 100644 --- a/tools/scaninc/c_file.h +++ b/tools/scaninc/c_file.h @@ -42,11 +42,11 @@ private: std::string m_path; std::set m_incbins; - void CFile::RemoveComments(); + void RemoveComments(); bool ConsumeHorizontalWhitespace(); bool ConsumeNewline(); void SkipWhitespace(); - std::unique_ptr CFile::ReadWholeFile(const std::string& path, int& size); + std::unique_ptr ReadWholeFile(const std::string& path, int& size); bool CheckIdentifier(const std::string& ident); void CheckIncbin(); }; -- cgit v1.2.3 From 18e21f8b090a49934a80d56b1796e0c1d469a22c Mon Sep 17 00:00:00 2001 From: YamaArashi Date: Fri, 3 Feb 2017 20:34:51 -0800 Subject: remove C++14 feature from tools --- tools/preproc/Makefile | 2 +- tools/preproc/c_file.cpp | 2 +- tools/scaninc/Makefile | 2 +- tools/scaninc/c_file.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/preproc/Makefile b/tools/preproc/Makefile index 24f60e3f6..2d577c79f 100644 --- a/tools/preproc/Makefile +++ b/tools/preproc/Makefile @@ -1,6 +1,6 @@ CXX := g++ -CXXFLAGS := -std=c++14 -O2 -Wall -Wno-switch +CXXFLAGS := -std=c++11 -O2 -Wall -Wno-switch SRCS := asm_file.cpp c_file.cpp charmap.cpp preproc.cpp string_parser.cpp \ utf8.cpp diff --git a/tools/preproc/c_file.cpp b/tools/preproc/c_file.cpp index 3b4024efe..a2f178623 100644 --- a/tools/preproc/c_file.cpp +++ b/tools/preproc/c_file.cpp @@ -256,7 +256,7 @@ std::unique_ptr CFile::ReadWholeFile(const std::string& path, i size = ftell(fp); - std::unique_ptr buffer = std::make_unique(size); + std::unique_ptr buffer = std::unique_ptr(new unsigned char[size]); rewind(fp); diff --git a/tools/scaninc/Makefile b/tools/scaninc/Makefile index c408e4a6e..71c4389ef 100644 --- a/tools/scaninc/Makefile +++ b/tools/scaninc/Makefile @@ -1,6 +1,6 @@ CXX = g++ -CXXFLAGS = -Wall -std=c++14 -O2 +CXXFLAGS = -Wall -std=c++11 -O2 SRCS = scaninc.cpp c_file.cpp asm_file.cpp diff --git a/tools/scaninc/c_file.cpp b/tools/scaninc/c_file.cpp index 970fbe135..bb84fedbe 100644 --- a/tools/scaninc/c_file.cpp +++ b/tools/scaninc/c_file.cpp @@ -222,7 +222,7 @@ std::unique_ptr CFile::ReadWholeFile(const std::string& path, i size = ftell(fp); - std::unique_ptr buffer = std::make_unique(size); + std::unique_ptr buffer = std::unique_ptr(new unsigned char[size]); rewind(fp); -- cgit v1.2.3 From 7c96b16179792a044ded6ade1b74cdb1c0b870a5 Mon Sep 17 00:00:00 2001 From: camthesaxman Date: Fri, 3 Feb 2017 23:16:28 -0600 Subject: use std:: prefix and remove some unused functions --- tools/preproc/asm_file.cpp | 2 +- tools/preproc/c_file.cpp | 16 +++++++------- tools/preproc/preproc.cpp | 14 ++++++------ tools/scaninc/asm_file.cpp | 12 +++++------ tools/scaninc/c_file.cpp | 54 ++++++---------------------------------------- tools/scaninc/c_file.h | 1 - tools/scaninc/scaninc.cpp | 6 +++--- 7 files changed, 31 insertions(+), 74 deletions(-) (limited to 'tools') diff --git a/tools/preproc/asm_file.cpp b/tools/preproc/asm_file.cpp index 49c9e3c66..bb296b78b 100644 --- a/tools/preproc/asm_file.cpp +++ b/tools/preproc/asm_file.cpp @@ -494,7 +494,7 @@ bool AsmFile::IsAtEnd() // Output the current location to set gas's logical file and line numbers. void AsmFile::OutputLocation() { - printf("# %ld \"%s\"\n", m_lineNum, m_filename.c_str()); + std::printf("# %ld \"%s\"\n", m_lineNum, m_filename.c_str()); } // Reports a diagnostic message. diff --git a/tools/preproc/c_file.cpp b/tools/preproc/c_file.cpp index a2f178623..5bfdee086 100644 --- a/tools/preproc/c_file.cpp +++ b/tools/preproc/c_file.cpp @@ -247,23 +247,23 @@ bool CFile::CheckIdentifier(const std::string& ident) std::unique_ptr CFile::ReadWholeFile(const std::string& path, int& size) { - FILE* fp = fopen(path.c_str(), "rb"); + FILE* fp = std::fopen(path.c_str(), "rb"); if (fp == nullptr) RaiseError("Failed to open \"%s\" for reading.\n", path.c_str()); - fseek(fp, 0, SEEK_END); + std::fseek(fp, 0, SEEK_END); - size = ftell(fp); + size = std::ftell(fp); std::unique_ptr buffer = std::unique_ptr(new unsigned char[size]); - rewind(fp); + std::rewind(fp); - if (fread(buffer.get(), size, 1, fp) != 1) + if (std::fread(buffer.get(), size, 1, fp) != 1) RaiseError("Failed to read \"%s\".\n", path.c_str()); - fclose(fp); + std::fclose(fp); return buffer; } @@ -379,9 +379,9 @@ void CFile::TryConvertIncbin() offset += size; if (isSigned) - printf("%d,", data); + std::printf("%d,", data); else - printf("%uu,", data); + std::printf("%uu,", data); } std::printf("}"); diff --git a/tools/preproc/preproc.cpp b/tools/preproc/preproc.cpp index b51861580..8320a2d27 100644 --- a/tools/preproc/preproc.cpp +++ b/tools/preproc/preproc.cpp @@ -31,15 +31,15 @@ void PrintAsmBytes(unsigned char *s, int length) { if (length > 0) { - printf("\t.byte "); + std::printf("\t.byte "); for (int i = 0; i < length; i++) { - printf("0x%02X", s[i]); + std::printf("0x%02X", s[i]); if (i < length - 1) - printf(", "); + std::printf(", "); } - putchar('\n'); + std::putchar('\n'); } } @@ -89,8 +89,8 @@ void PreprocAsmFile(std::string filename) if (globalLabel.length() != 0) { - printf("\t.global %s\n", globalLabel.c_str()); - printf("%s:\n", globalLabel.c_str()); + std::printf("\t.global %s\n", globalLabel.c_str()); + std::printf("%s:\n", globalLabel.c_str()); } else { @@ -134,7 +134,7 @@ int main(int argc, char **argv) { if (argc != 3) { - fprintf(stderr, "Usage: %s SRC_FILE CHARMAP_FILE", argv[0]); + std::fprintf(stderr, "Usage: %s SRC_FILE CHARMAP_FILE", argv[0]); return 1; } diff --git a/tools/scaninc/asm_file.cpp b/tools/scaninc/asm_file.cpp index 143c70242..c3d140bb1 100644 --- a/tools/scaninc/asm_file.cpp +++ b/tools/scaninc/asm_file.cpp @@ -27,23 +27,23 @@ AsmFile::AsmFile(std::string path) { m_path = path; - FILE *fp = fopen(path.c_str(), "rb"); + FILE *fp = std::fopen(path.c_str(), "rb"); if (fp == NULL) FATAL_ERROR("Failed to open \"%s\" for reading.\n", path.c_str()); - fseek(fp, 0, SEEK_END); + std::fseek(fp, 0, SEEK_END); - m_size = ftell(fp); + m_size = std::ftell(fp); m_buffer = new char[m_size]; - rewind(fp); + std::rewind(fp); - if (fread(m_buffer, m_size, 1, fp) != 1) + if (std::fread(m_buffer, m_size, 1, fp) != 1) FATAL_ERROR("Failed to read \"%s\".\n", path.c_str()); - fclose(fp); + std::fclose(fp); m_pos = 0; m_lineNum = 1; diff --git a/tools/scaninc/c_file.cpp b/tools/scaninc/c_file.cpp index bb84fedbe..b82276dd6 100644 --- a/tools/scaninc/c_file.cpp +++ b/tools/scaninc/c_file.cpp @@ -24,24 +24,24 @@ CFile::CFile(std::string path) { m_path = path; - FILE *fp = fopen(path.c_str(), "rb"); + FILE *fp = std::fopen(path.c_str(), "rb"); if (fp == NULL) FATAL_ERROR("Failed to open \"%s\" for reading.\n", path.c_str()); - fseek(fp, 0, SEEK_END); + std::fseek(fp, 0, SEEK_END); - m_size = ftell(fp); + m_size = std::ftell(fp); m_buffer = new char[m_size + 1]; m_buffer[m_size] = 0; - rewind(fp); + std::rewind(fp); - if (fread(m_buffer, m_size, 1, fp) != 1) + if (std::fread(m_buffer, m_size, 1, fp) != 1) FATAL_ERROR("Failed to read \"%s\".\n", path.c_str()); - fclose(fp); + std::fclose(fp); m_pos = 0; m_lineNum = 1; @@ -211,48 +211,6 @@ bool CFile::CheckIdentifier(const std::string& ident) return (i == ident.length()); } -std::unique_ptr CFile::ReadWholeFile(const std::string& path, int& size) -{ - FILE* fp = fopen(path.c_str(), "rb"); - - if (fp == nullptr) - FATAL_INPUT_ERROR("Failed to open \"%s\" for reading.\n", path.c_str()); - - fseek(fp, 0, SEEK_END); - - size = ftell(fp); - - std::unique_ptr buffer = std::unique_ptr(new unsigned char[size]); - - rewind(fp); - - if (fread(buffer.get(), size, 1, fp) != 1) - FATAL_INPUT_ERROR("Failed to read \"%s\".\n", path.c_str()); - - fclose(fp); - - return buffer; -} - -int ExtractData(const std::unique_ptr& buffer, int offset, int size) -{ - switch (size) - { - case 1: - return buffer[offset]; - case 2: - return (buffer[offset + 1] << 8) - | buffer[offset]; - case 4: - return (buffer[offset + 3] << 24) - | (buffer[offset + 2] << 16) - | (buffer[offset + 1] << 8) - | buffer[offset]; - default: - FATAL_ERROR("Invalid size passed to ExtractData.\n"); - } -} - void CFile::CheckIncbin() { std::string idents[6] = { "INCBIN_S8", "INCBIN_U8", "INCBIN_S16", "INCBIN_U16", "INCBIN_S32", "INCBIN_U32" }; diff --git a/tools/scaninc/c_file.h b/tools/scaninc/c_file.h index 2503acac1..922cb4639 100644 --- a/tools/scaninc/c_file.h +++ b/tools/scaninc/c_file.h @@ -46,7 +46,6 @@ private: bool ConsumeHorizontalWhitespace(); bool ConsumeNewline(); void SkipWhitespace(); - std::unique_ptr ReadWholeFile(const std::string& path, int& size); bool CheckIdentifier(const std::string& ident); void CheckIncbin(); }; diff --git a/tools/scaninc/scaninc.cpp b/tools/scaninc/scaninc.cpp index 2f9ed81e9..b6f7ba767 100644 --- a/tools/scaninc/scaninc.cpp +++ b/tools/scaninc/scaninc.cpp @@ -29,12 +29,12 @@ bool CanOpenFile(std::string path) { - FILE *fp = fopen(path.c_str(), "rb"); + FILE *fp = std::fopen(path.c_str(), "rb"); if (fp == NULL) return false; - fclose(fp); + std::fclose(fp); return true; } @@ -92,6 +92,6 @@ int main(int argc, char **argv) for (const std::string &path : dependencies) { - printf("%s\n", path.c_str()); + std::printf("%s\n", path.c_str()); } } -- cgit v1.2.3 From 08725a4773d8530fe3a58824b647f6c2e90b2771 Mon Sep 17 00:00:00 2001 From: YamaArashi Date: Fri, 5 May 2017 20:02:16 -0700 Subject: German ProcessRecvCmds --- tools/ramscrgen/main.cpp | 26 +++++++++-------- tools/ramscrgen/sym_file.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++++ tools/ramscrgen/sym_file.h | 3 ++ 3 files changed, 85 insertions(+), 11 deletions(-) (limited to 'tools') diff --git a/tools/ramscrgen/main.cpp b/tools/ramscrgen/main.cpp index 5c803c31f..6c4f4bbd7 100644 --- a/tools/ramscrgen/main.cpp +++ b/tools/ramscrgen/main.cpp @@ -25,7 +25,7 @@ #include "sym_file.h" #include "elf.h" -void HandleCommonInclude(std::string filename, std::string sourcePath, std::string symOrderPath) +void HandleCommonInclude(std::string filename, std::string sourcePath, std::string symOrderPath, std::string lang) { auto commonSymbols = GetCommonSymbols(sourcePath + "/" + filename); @@ -40,6 +40,8 @@ void HandleCommonInclude(std::string filename, std::string sourcePath, std::stri while (!symFile.IsAtEnd()) { + symFile.HandleLangConditional(lang); + std::string label = symFile.GetLabel(false); if (label.length() == 0) @@ -71,12 +73,14 @@ void HandleCommonInclude(std::string filename, std::string sourcePath, std::stri } } -void ConvertSymFile(std::string filename, std::string sectionName, bool common, std::string sourcePath, std::string commonSymPath) +void ConvertSymFile(std::string filename, std::string sectionName, std::string lang, bool common, std::string sourcePath, std::string commonSymPath) { SymFile symFile(filename); while (!symFile.IsAtEnd()) { + symFile.HandleLangConditional(lang); + Directive directive = symFile.GetDirective(); switch (directive) @@ -87,10 +91,9 @@ void ConvertSymFile(std::string filename, std::string sectionName, bool common, symFile.ExpectEmptyRestOfLine(); printf(". = ALIGN(4);\n"); if (common) - HandleCommonInclude(incFilename, sourcePath, commonSymPath); + HandleCommonInclude(incFilename, sourcePath, commonSymPath, lang); else printf("%s(%s);\n", incFilename.c_str(), sectionName.c_str()); - printf(". = ALIGN(4);\n"); break; } case Directive::Space: @@ -133,28 +136,29 @@ void ConvertSymFile(std::string filename, std::string sectionName, bool common, int main(int argc, char **argv) { - if (argc < 3) + if (argc < 4) { - fprintf(stderr, "Usage: %s SECTION_NAME SYM_FILE [-c SRC_PATH,COMMON_SYM_PATH]", argv[0]); + fprintf(stderr, "Usage: %s SECTION_NAME SYM_FILE LANG [-c SRC_PATH,COMMON_SYM_PATH]", argv[0]); return 1; } bool common = false; std::string sectionName = std::string(argv[1]); std::string symFileName = std::string(argv[2]); + std::string lang = std::string(argv[3]); std::string sourcePath; std::string commonSymPath; - if (argc > 3) + if (argc > 4) { - if (std::strcmp(argv[3], "-c") != 0) + if (std::strcmp(argv[4], "-c") != 0) FATAL_ERROR("error: unrecognized argument \"%s\"\n", argv[4]); - if (argc < 5) + if (argc < 6) FATAL_ERROR("error: missing SRC_PATH,COMMON_SYM_PATH after \"-c\"\n"); common = true; - std::string paths = std::string(argv[4]); + std::string paths = std::string(argv[5]); std::size_t commaPos = paths.find(','); if (commaPos == std::string::npos) @@ -164,6 +168,6 @@ int main(int argc, char **argv) commonSymPath = paths.substr(commaPos + 1); } - ConvertSymFile(symFileName, sectionName, common, sourcePath, commonSymPath); + ConvertSymFile(symFileName, sectionName, lang, common, sourcePath, commonSymPath); return 0; } diff --git a/tools/ramscrgen/sym_file.cpp b/tools/ramscrgen/sym_file.cpp index 9d9e4a064..5379bd93f 100644 --- a/tools/ramscrgen/sym_file.cpp +++ b/tools/ramscrgen/sym_file.cpp @@ -53,6 +53,7 @@ SymFile::SymFile(std::string filename) : m_filename(filename) m_pos = 0; m_lineNum = 1; m_lineStart = 0; + m_inLangConditional = false; RemoveComments(); } @@ -387,12 +388,78 @@ void SymFile::ExpectEmptyRestOfLine() } } + +void SymFile::SkipLine() +{ + while (m_buffer[m_pos] != 0 && m_buffer[m_pos] != '\n') + m_pos++; + + if (m_buffer[m_pos] == '\n') + m_pos++; +} + // Checks if we're at the end of the file. bool SymFile::IsAtEnd() { return (m_pos >= m_size); } +void SymFile::HandleLangConditional(std::string lang) +{ + if (m_buffer[m_pos] != '#') + return; + + m_pos++; + + if (CheckForDirective("begin")) + { + if (m_inLangConditional) + RaiseError("already inside language conditional"); + + SkipWhitespace(); + + std::string label = GetLabel(false); + + if (label.length() == 0) + RaiseError("no language name after #begin"); + + ExpectEmptyRestOfLine(); + + if (lang == label) + { + m_inLangConditional = true; + } + else + { + while (!IsAtEnd() && m_buffer[m_pos] != '#') + SkipLine(); + + if (m_buffer[m_pos] != '#') + RaiseError("unterminated language conditional"); + + m_pos++; + + if (!CheckForDirective("end")) + RaiseError("expected #end"); + + ExpectEmptyRestOfLine(); + } + } + else if (CheckForDirective("end")) + { + if (!m_inLangConditional) + RaiseError("not inside language conditional"); + + m_inLangConditional = false; + + ExpectEmptyRestOfLine(); + } + else + { + RaiseError("unknown # directive"); + } +} + // Reports a diagnostic message. void SymFile::ReportDiagnostic(const char* type, const char* format, std::va_list args) { diff --git a/tools/ramscrgen/sym_file.h b/tools/ramscrgen/sym_file.h index 5b3cedb3b..bb0c8038d 100644 --- a/tools/ramscrgen/sym_file.h +++ b/tools/ramscrgen/sym_file.h @@ -46,7 +46,9 @@ public: std::string ReadPath(); bool ReadInteger(unsigned long& value); void ExpectEmptyRestOfLine(); + void SkipLine(); bool IsAtEnd(); + void HandleLangConditional(std::string lang); void RaiseError(const char* format, ...); void RaiseWarning(const char* format, ...); @@ -57,6 +59,7 @@ private: long m_lineNum; long m_lineStart; std::string m_filename; + bool m_inLangConditional; bool ConsumeComma(); void RemoveComments(); -- cgit v1.2.3 From 46048394acb7f6441a362c41cc16b7d7d31ba210 Mon Sep 17 00:00:00 2001 From: Cameron Date: Thu, 11 May 2017 21:51:54 -0500 Subject: add LDFLAGS variable to tools makefiles --- tools/aif2pcm/Makefile | 2 +- tools/bin2c/Makefile | 2 +- tools/gbagfx/Makefile | 2 +- tools/mid2agb/Makefile | 2 +- tools/preproc/Makefile | 2 +- tools/ramscrgen/Makefile | 2 +- tools/rsfont/Makefile | 2 +- tools/scaninc/Makefile | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) (limited to 'tools') diff --git a/tools/aif2pcm/Makefile b/tools/aif2pcm/Makefile index ec6343b12..7e7e116b2 100644 --- a/tools/aif2pcm/Makefile +++ b/tools/aif2pcm/Makefile @@ -9,7 +9,7 @@ SRCS = main.c extended.c .PHONY: clean aif2pcm: $(SRCS) - $(CC) $(CFLAGS) $(SRCS) -o $@ $(LIBS) + $(CC) $(CFLAGS) $(SRCS) -o $@ $(LDFLAGS) $(LIBS) clean: $(RM) aif2pcm aif2pcm.exe diff --git a/tools/bin2c/Makefile b/tools/bin2c/Makefile index eee19af22..715668eba 100644 --- a/tools/bin2c/Makefile +++ b/tools/bin2c/Makefile @@ -7,7 +7,7 @@ CFLAGS = -Wall -Wextra -std=c11 -O2 SRCS = bin2c.c bin2c: $(SRCS) - $(CC) $(CFLAGS) $(SRCS) -o $@ + $(CC) $(CFLAGS) $(SRCS) -o $@ $(LDFLAGS) clean: $(RM) bin2c bin2c.exe diff --git a/tools/gbagfx/Makefile b/tools/gbagfx/Makefile index de4ea5c42..8ab033403 100644 --- a/tools/gbagfx/Makefile +++ b/tools/gbagfx/Makefile @@ -9,7 +9,7 @@ SRCS = main.c convert_png.c gfx.c jasc_pal.c lz.c rl.c util.c font.c .PHONY: clean gbagfx: $(SRCS) convert_png.h gfx.h global.h jasc_pal.h lz.h rl.h util.h font.h - $(CC) $(CFLAGS) $(SRCS) -o $@ $(LIBS) + $(CC) $(CFLAGS) $(SRCS) -o $@ $(LDFLAGS) $(LIBS) clean: $(RM) gbagfx gbagfx.exe diff --git a/tools/mid2agb/Makefile b/tools/mid2agb/Makefile index 3215169d3..029432022 100644 --- a/tools/mid2agb/Makefile +++ b/tools/mid2agb/Makefile @@ -9,7 +9,7 @@ HEADERS := agb.h error.h main.h midi.h tables.h .PHONY: clean mid2agb: $(SRCS) $(HEADERS) - $(CXX) $(CXXFLAGS) $(SRCS) -o $@ + $(CXX) $(CXXFLAGS) $(SRCS) -o $@ $(LDFLAGS) clean: $(RM) mid2agb mid2agb.exe diff --git a/tools/preproc/Makefile b/tools/preproc/Makefile index 2d577c79f..e5321afbd 100644 --- a/tools/preproc/Makefile +++ b/tools/preproc/Makefile @@ -11,7 +11,7 @@ HEADERS := asm_file.h c_file.h char_util.h charmap.h preproc.h string_parser.h \ .PHONY: clean preproc: $(SRCS) $(HEADERS) - $(CXX) $(CXXFLAGS) $(SRCS) -o $@ + $(CXX) $(CXXFLAGS) $(SRCS) -o $@ $(LDFLAGS) clean: $(RM) preproc preproc.exe diff --git a/tools/ramscrgen/Makefile b/tools/ramscrgen/Makefile index e18ae99f2..ef05a2d76 100644 --- a/tools/ramscrgen/Makefile +++ b/tools/ramscrgen/Makefile @@ -9,7 +9,7 @@ HEADERS := ramscrgen.h sym_file.h elf.h char_util.h .PHONY: clean ramscrgen: $(SRCS) $(HEADERS) - $(CXX) $(CXXFLAGS) $(SRCS) -o $@ + $(CXX) $(CXXFLAGS) $(SRCS) -o $@ $(LDFLAGS) clean: $(RM) ramscrgen ramscrgen.exe diff --git a/tools/rsfont/Makefile b/tools/rsfont/Makefile index d2a88c46d..2bb57da97 100644 --- a/tools/rsfont/Makefile +++ b/tools/rsfont/Makefile @@ -9,7 +9,7 @@ SRCS = main.c convert_png.c util.c font.c .PHONY: clean rsfont: $(SRCS) convert_png.h gfx.h global.h util.h font.h - $(CC) $(CFLAGS) $(SRCS) -o $@ $(LIBS) + $(CC) $(CFLAGS) $(SRCS) -o $@ $(LDFLAGS) $(LIBS) clean: $(RM) rsfont rsfont.exe diff --git a/tools/scaninc/Makefile b/tools/scaninc/Makefile index 71c4389ef..093b06032 100644 --- a/tools/scaninc/Makefile +++ b/tools/scaninc/Makefile @@ -9,7 +9,7 @@ HEADERS := scaninc.h asm_file.h c_file.h .PHONY: clean scaninc: $(SRCS) $(HEADERS) - $(CXX) $(CXXFLAGS) $(SRCS) -o $@ + $(CXX) $(CXXFLAGS) $(SRCS) -o $@ $(LDFLAGS) clean: $(RM) scaninc scaninc.exe -- cgit v1.2.3 From 543820c7264ad7f2cc206602e88f2172735bbcd3 Mon Sep 17 00:00:00 2001 From: camthesaxman Date: Thu, 11 May 2017 21:57:48 -0500 Subject: strip debugging symbols from tools --- tools/aif2pcm/Makefile | 2 +- tools/bin2c/Makefile | 2 +- tools/gbagfx/Makefile | 2 +- tools/mid2agb/Makefile | 2 +- tools/preproc/Makefile | 2 +- tools/ramscrgen/Makefile | 2 +- tools/rsfont/Makefile | 2 +- tools/scaninc/Makefile | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) (limited to 'tools') diff --git a/tools/aif2pcm/Makefile b/tools/aif2pcm/Makefile index 7e7e116b2..611c0e2df 100644 --- a/tools/aif2pcm/Makefile +++ b/tools/aif2pcm/Makefile @@ -1,6 +1,6 @@ CC = gcc -CFLAGS = -Wall -Wextra -Wno-switch -std=c11 -O2 +CFLAGS = -Wall -Wextra -Wno-switch -std=c11 -O2 -s LIBS = -lm diff --git a/tools/bin2c/Makefile b/tools/bin2c/Makefile index 715668eba..bd5f60490 100644 --- a/tools/bin2c/Makefile +++ b/tools/bin2c/Makefile @@ -1,6 +1,6 @@ CC = gcc -CFLAGS = -Wall -Wextra -std=c11 -O2 +CFLAGS = -Wall -Wextra -std=c11 -O2 -s .PHONY: clean diff --git a/tools/gbagfx/Makefile b/tools/gbagfx/Makefile index 8ab033403..9a5dee1cc 100644 --- a/tools/gbagfx/Makefile +++ b/tools/gbagfx/Makefile @@ -1,6 +1,6 @@ CC = gcc -CFLAGS = -Wall -Wextra -std=c11 -O2 -DPNG_SKIP_SETJMP_CHECK +CFLAGS = -Wall -Wextra -std=c11 -O2 -s -DPNG_SKIP_SETJMP_CHECK LIBS = -lpng -lz diff --git a/tools/mid2agb/Makefile b/tools/mid2agb/Makefile index 029432022..accd81882 100644 --- a/tools/mid2agb/Makefile +++ b/tools/mid2agb/Makefile @@ -1,6 +1,6 @@ CXX := g++ -CXXFLAGS := -std=c++11 -O2 -Wall -Wno-switch +CXXFLAGS := -std=c++11 -O2 -s -Wall -Wno-switch SRCS := agb.cpp error.cpp main.cpp midi.cpp tables.cpp diff --git a/tools/preproc/Makefile b/tools/preproc/Makefile index e5321afbd..1f4c58e21 100644 --- a/tools/preproc/Makefile +++ b/tools/preproc/Makefile @@ -1,6 +1,6 @@ CXX := g++ -CXXFLAGS := -std=c++11 -O2 -Wall -Wno-switch +CXXFLAGS := -std=c++11 -O2 -s -Wall -Wno-switch SRCS := asm_file.cpp c_file.cpp charmap.cpp preproc.cpp string_parser.cpp \ utf8.cpp diff --git a/tools/ramscrgen/Makefile b/tools/ramscrgen/Makefile index ef05a2d76..6c4ca28b6 100644 --- a/tools/ramscrgen/Makefile +++ b/tools/ramscrgen/Makefile @@ -1,6 +1,6 @@ CXX := g++ -CXXFLAGS := -std=c++11 -O2 -Wall -Wno-switch +CXXFLAGS := -std=c++11 -O2 -s -Wall -Wno-switch SRCS := main.cpp sym_file.cpp elf.cpp diff --git a/tools/rsfont/Makefile b/tools/rsfont/Makefile index 2bb57da97..544954bfc 100644 --- a/tools/rsfont/Makefile +++ b/tools/rsfont/Makefile @@ -1,6 +1,6 @@ CC = gcc -CFLAGS = -Wall -Wextra -std=c11 -O2 -DPNG_SKIP_SETJMP_CHECK +CFLAGS = -Wall -Wextra -std=c11 -O2 -s -DPNG_SKIP_SETJMP_CHECK LIBS = -lpng -lz diff --git a/tools/scaninc/Makefile b/tools/scaninc/Makefile index 093b06032..d33dee6d2 100644 --- a/tools/scaninc/Makefile +++ b/tools/scaninc/Makefile @@ -1,6 +1,6 @@ CXX = g++ -CXXFLAGS = -Wall -std=c++11 -O2 +CXXFLAGS = -Wall -std=c++11 -O2 -s SRCS = scaninc.cpp c_file.cpp asm_file.cpp -- cgit v1.2.3