Assets - Converting Menu Assets to Bitmaps
This time we'll turn our attention to the menu assets in the Traffic Department 2192 archive: The TD.MEN, TD.SSS, and the supporting palette TDMEN.PAL. Much of this will be a rehash of everything we've done and our code will look a lot like the SCR files except we'll fix the width derive the length.
Menu File Format
We can easily guess that menu elements will take the full width of the display since we do have to display the whole screen. However, a big difference between the MEN and SSS file is that one contains many assets including our popups while the other contains just one partial asset. In retrospect, the original developer could have probably combined these files, but there may have been a memory limitation or they were created out of order.
The TD.MEN file contains more than the the main menu screen. It's actually a full sprite sheet containing all of the menu items including popups. Some of the menu items are stored interlaced. The menu text elements contain unique colors that are swapped out using palette data at the bottom. We won't be using the palette data in our implementation, but we'll copy the asset as-is and ignore that section.
Conversion Process
Read in the menu palette from TDMEN.PAL. Scan through our input file assuming a width of 320. Use that width to calculate the number of lines based on the file size. Match each index to an RGB triple in the palette. Write the resulting set colors to the output container.
C Source Code
We'll rely on C as we've already done with all othr graphics assets.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
/* Menu to BMP file converter designed for use with Traffic Department 2192 Menu files * argv[1] points to Face data file * * Five issues: * 1) This program is a security nightmare - don't compile and store * 2) No trapping, feedback, instructions, or any output whatsoever * 3) SDL_Surface normally needs to be locked due to concurrency * 4) Free the SDL surface - in this case, the OS does it * 5) Void pointer implicit cast (not portable to C++) */ #include <stdio.h> /* Opening Files */ #include <string.h> /* Manipulating File Names */ #include <stdint.h> /* Fixed-width data types (C99) */ #include <SDL.H> /* Using SDL data structure */ int main(int argc, char* argv[]) { FILE *fin, *fpal; /* Input File and palette file pointers */ uint32_t FILE_SIZE; /* Get file size */ uint32_t IMAGE_WIDTH; /* Pixel width of a single frame*/ uint32_t IMAGE_HEIGHT; /* Pixel width of a single frame*/ SDL_Surface *surface; /* SDL Surface struct */ uint8_t *dst_byte; /* Pointer to surface struct Pixels */ uint32_t current_byte; /* Named iterator */ uint8_t palette[768]; /* Palette array: 3 x 8-bit*/ uint8_t src_byte; /* Single byte read from input */ uint8_t red_p, green_p, blue_p; /* Palette lookup bytes by color */ uint8_t FILENAME_LEN; /* File Name length*/ char fout[12]; /* New filename container */ /* Open Menu and PAL File and find file size*/ fin = fopen(argv[1],"rb"); fpal = fopen("TDMEN.PAL","rb"); /* Find File Size */ fseek(fin, 0, SEEK_END); FILE_SIZE = ftell(fin); rewind(fin); /* Calculate File Metrics */ IMAGE_WIDTH = 320; /* Pre-determined widths */ IMAGE_HEIGHT = FILE_SIZE / IMAGE_WIDTH; /* Make surface strip and pixel data pointer. Each Image is 160x100 */ surface = SDL_CreateRGBSurface(0, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0,0,0,0); dst_byte = surface->pixels; /* Extract image palette - guaranteed 768 bytes*/ for (current_byte=0; current_byte<768; current_byte++) palette[current_byte] = fgetc(fpal) << 2; /* Reranging values 63 -> 255 */ fclose(fpal); /* Extract 64kb of image data, match to palette, write to surface */ for (current_byte=0; current_byte < (IMAGE_WIDTH*IMAGE_HEIGHT); current_byte++) { src_byte = fgetc(fin); /* Read Byte From File */ red_p = palette[src_byte*3]; /* Palette Red Channel */ green_p = palette[src_byte*3+1]; /* Palette Green Channel */ blue_p = palette[src_byte*3+2]; /* Palette Blue Channel */ dst_byte[current_byte*4] = blue_p; /* Set Blue channel pixel */ dst_byte[current_byte*4+1] = green_p; /* Set Green channel pixel */ dst_byte[current_byte*4+2] = red_p; /* Set Red channel pixel */ dst_byte[current_byte*4+3] = 0xff; /* Set Alpha channel pixel */ } fclose(fin); /* New output filename with .BMP extension */ FILENAME_LEN = strlen(argv[1]); /* Length of input file name */ strncpy(fout,argv[1],FILENAME_LEN-3); /* Chop off PIC extension */ fout[FILENAME_LEN-3]='\0'; /* Nullterm it */ strncat(fout,"BMP",3); /* Attach BMP extension */ /* Save BMP*/ SDL_SaveBMP(surface, fout); return 0; } |