First Commit
This commit is contained in:
16
.hgignore
Normal file
16
.hgignore
Normal file
@@ -0,0 +1,16 @@
|
||||
syntax: glob
|
||||
|
||||
aee
|
||||
recursos/*
|
||||
bin/*
|
||||
obj/*
|
||||
Debug/*
|
||||
Release/*
|
||||
data/*
|
||||
*.suo
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.user
|
||||
*.dll
|
||||
.DS_Store
|
||||
trick.ini
|
||||
9
config.ini
Normal file
9
config.ini
Normal file
@@ -0,0 +1,9 @@
|
||||
tile_width = 16
|
||||
tile_height = 16
|
||||
map_width = 240
|
||||
map_height = 238
|
||||
screen_width = 320
|
||||
screen_height = 224
|
||||
zoom = 2
|
||||
tiles = tiles.png
|
||||
map = map.map
|
||||
47
font.h
Normal file
47
font.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
font.h (GIF).
|
||||
*/
|
||||
static unsigned char
|
||||
font[] =
|
||||
{
|
||||
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x60, 0x00, 0x24, 0x00, 0xF0, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
|
||||
0x2C, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x24, 0x00,
|
||||
0x00, 0x02, 0xFE, 0x84, 0x6F, 0x81, 0xAA, 0x09, 0x1D, 0x62, 0x7C, 0xF0,
|
||||
0x4C, 0x8B, 0x5E, 0x6E, 0x38, 0xFB, 0x0F, 0x2E, 0x21, 0xA7, 0x41, 0x12,
|
||||
0xA3, 0x25, 0xA8, 0x43, 0xB6, 0x1F, 0x27, 0x75, 0xE1, 0x2C, 0x8E, 0xF3,
|
||||
0x7A, 0xC2, 0x0B, 0xE9, 0xF1, 0x8E, 0x1C, 0x03, 0x05, 0x6D, 0xB4, 0xD1,
|
||||
0x09, 0x53, 0x99, 0xF8, 0x7A, 0x2F, 0xA4, 0xAC, 0x28, 0x2C, 0x2E, 0x9D,
|
||||
0x94, 0x98, 0x49, 0x75, 0x69, 0xD6, 0xA0, 0x3F, 0x62, 0x8A, 0x0B, 0x0E,
|
||||
0x8B, 0xB9, 0x53, 0xF2, 0xB1, 0x9B, 0xAB, 0x2A, 0x91, 0xC7, 0xB4, 0xBB,
|
||||
0x7D, 0x26, 0x7B, 0xD5, 0xAB, 0x54, 0x76, 0xCB, 0xA2, 0x3E, 0x37, 0xDF,
|
||||
0x7A, 0x99, 0x89, 0xC5, 0x87, 0x56, 0xD2, 0x67, 0x71, 0x06, 0x67, 0x85,
|
||||
0x78, 0x67, 0x62, 0x05, 0x24, 0xD8, 0x75, 0xB3, 0xE3, 0xE7, 0x18, 0x85,
|
||||
0x47, 0x38, 0x38, 0x98, 0x26, 0x17, 0x68, 0x29, 0x79, 0x11, 0xF4, 0x36,
|
||||
0xC4, 0xA2, 0xA8, 0x83, 0x75, 0x57, 0xD8, 0x59, 0xE6, 0xF3, 0x37, 0xD6,
|
||||
0xEA, 0xBA, 0xF7, 0x6A, 0x08, 0xF3, 0x39, 0x04, 0x6A, 0x9B, 0x88, 0xBB,
|
||||
0x36, 0x9A, 0x3B, 0xC9, 0xA3, 0xD4, 0xDB, 0xA6, 0x52, 0xA8, 0x43, 0xAC,
|
||||
0x07, 0xF9, 0x85, 0x89, 0xFC, 0x53, 0xA1, 0x8C, 0xC2, 0x90, 0x44, 0xA5,
|
||||
0x5B, 0x02, 0xFA, 0xF8, 0x4C, 0xFB, 0x59, 0x45, 0x07, 0xCB, 0xB8, 0x57,
|
||||
0xEC, 0x6C, 0xAC, 0x5D, 0x9C, 0x37, 0xDE, 0xAD, 0x57, 0x6A, 0xB7, 0x7C,
|
||||
0x2C, 0x2E, 0xCD, 0x3D, 0x5C, 0x7B, 0xCD, 0x28, 0x6D, 0x0A, 0x9C, 0x9B,
|
||||
0x19, 0x4C, 0x6E, 0x7D, 0x1A, 0xBB, 0xCF, 0xBF, 0x1F, 0xFA, 0xCB, 0x2B,
|
||||
0x9C, 0xB9, 0x61, 0x03, 0x35, 0x51, 0xDB, 0xB0, 0xC8, 0x4B, 0x2F, 0x70,
|
||||
0xC9, 0x16, 0xA6, 0x63, 0x86, 0xEC, 0xDC, 0xB1, 0x4C, 0x95, 0x2E, 0x59,
|
||||
0xCC, 0x77, 0x4E, 0xDC, 0xC5, 0xB1, 0x27, 0x75, 0x22, 0x02, 0xEA, 0x24,
|
||||
0xE4, 0x5E, 0xBC, 0x8F, 0x19, 0xC7, 0x7D, 0xB3, 0xE8, 0x11, 0xA4, 0xAF,
|
||||
0x4D, 0xB2, 0x36, 0x6A, 0xEA, 0x13, 0xC7, 0x05, 0xC4, 0x8C, 0x87, 0xF4,
|
||||
0xB5, 0xEB, 0x11, 0xA7, 0x9F, 0xCE, 0x9D, 0x62, 0x7C, 0xC1, 0x6B, 0xA9,
|
||||
0x66, 0x5E, 0xB8, 0x7B, 0xD3, 0x02, 0x6A, 0x14, 0xC6, 0x4E, 0x5B, 0x43,
|
||||
0x82, 0xF8, 0x9A, 0x3D, 0x5A, 0x2A, 0x88, 0xD9, 0x4A, 0x67, 0xD0, 0x26,
|
||||
0xBA, 0xC3, 0xB6, 0x25, 0x9F, 0xA9, 0x5D, 0x4A, 0x95, 0xD9, 0xC9, 0xB2,
|
||||
0x32, 0xCF, 0x49, 0xAF, 0x02, 0x9B, 0x1E, 0x75, 0xDA, 0x14, 0x93, 0x54,
|
||||
0x75, 0xD1, 0x26, 0x91, 0x0C, 0xCA, 0xA9, 0x66, 0x23, 0x4F, 0xF4, 0x00,
|
||||
0xCE, 0x2C, 0xEB, 0x32, 0x27, 0xCF, 0xBD, 0x7C, 0x71, 0x1A, 0x25, 0x85,
|
||||
0xD7, 0xA1, 0x4B, 0x36, 0xEF, 0xF0, 0x24, 0x9C, 0xA2, 0x51, 0x70, 0xD6,
|
||||
0x82, 0x1D, 0x70, 0x70, 0xB4, 0x14, 0x16, 0x65, 0x35, 0xA6, 0x45, 0xC1,
|
||||
0x3A, 0x4A, 0xFC, 0xD8, 0x85, 0xA1, 0xA7, 0x14, 0xCC, 0xCC, 0x1D, 0x39,
|
||||
0x59, 0x2D, 0x3A, 0xC7, 0x9A, 0x27, 0x46, 0xB6, 0x5A, 0x31, 0x50, 0x5D,
|
||||
0x9A, 0xB5, 0x44, 0xDC, 0x45, 0x13, 0xB3, 0x74, 0xE7, 0xBE, 0xB4, 0x6B,
|
||||
0x73, 0x29, 0x00, 0x00, 0x3B,
|
||||
};
|
||||
510
gif.c
Normal file
510
gif.c
Normal file
@@ -0,0 +1,510 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define EXTENSION_INTRODUCER 0x21
|
||||
#define IMAGE_DESCRIPTOR 0x2C
|
||||
#define TRAILER 0x3B
|
||||
|
||||
#define GRAPHIC_CONTROL 0xF9
|
||||
#define APPLICATION_EXTENSION 0xFF
|
||||
#define COMMENT_EXTENSION 0xFE
|
||||
#define PLAINTEXT_EXTENSION 0x01
|
||||
|
||||
#define READ(dst, size) memcpy(dst, buffer, size); buffer += size
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
unsigned char fields;
|
||||
unsigned char background_color_index;
|
||||
unsigned char pixel_aspect_ratio;
|
||||
}
|
||||
screen_descriptor_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char r;
|
||||
unsigned char g;
|
||||
unsigned char b;
|
||||
}
|
||||
rgb;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short image_left_position;
|
||||
unsigned short image_top_position;
|
||||
unsigned short image_width;
|
||||
unsigned short image_height;
|
||||
unsigned char fields;
|
||||
}
|
||||
image_descriptor_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char byte;
|
||||
int prev;
|
||||
int len;
|
||||
}
|
||||
dictionary_entry_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char extension_code;
|
||||
unsigned char block_size;
|
||||
}
|
||||
extension_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char fields;
|
||||
unsigned short delay_time;
|
||||
unsigned char transparent_color_index;
|
||||
}
|
||||
graphic_control_extension_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char application_id[ 8 ];
|
||||
unsigned char version[ 3 ];
|
||||
}
|
||||
application_extension_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short left;
|
||||
unsigned short top;
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
unsigned char cell_width;
|
||||
unsigned char cell_height;
|
||||
unsigned char foreground_color;
|
||||
unsigned char background_color;
|
||||
}
|
||||
plaintext_extension_t;
|
||||
|
||||
//static unsigned short width = 0;
|
||||
//static unsigned short height = 0;
|
||||
//static unsigned char* uncompressed_data = NULL;
|
||||
|
||||
void uncompress( int code_length,
|
||||
const unsigned char *input,
|
||||
int input_length,
|
||||
unsigned char *out )
|
||||
{
|
||||
//int maxbits;
|
||||
int i, bit;
|
||||
int code, prev = -1;
|
||||
dictionary_entry_t *dictionary;
|
||||
int dictionary_ind;
|
||||
unsigned int mask = 0x01;
|
||||
int reset_code_length;
|
||||
int clear_code; // This varies depending on code_length
|
||||
int stop_code; // one more than clear code
|
||||
int match_len;
|
||||
|
||||
clear_code = 1 << ( code_length );
|
||||
stop_code = clear_code + 1;
|
||||
// To handle clear codes
|
||||
reset_code_length = code_length;
|
||||
|
||||
// Create a dictionary large enough to hold "code_length" entries.
|
||||
// Once the dictionary overflows, code_length increases
|
||||
dictionary = ( dictionary_entry_t * )
|
||||
malloc( sizeof( dictionary_entry_t ) * ( 1 << ( code_length + 1 ) ) );
|
||||
|
||||
// Initialize the first 2^code_len entries of the dictionary with their
|
||||
// indices. The rest of the entries will be built up dynamically.
|
||||
|
||||
// Technically, it shouldn't be necessary to initialize the
|
||||
// dictionary. The spec says that the encoder "should output a
|
||||
// clear code as the first code in the image data stream". It doesn't
|
||||
// say must, though...
|
||||
for ( dictionary_ind = 0;
|
||||
dictionary_ind < ( 1 << code_length );
|
||||
dictionary_ind++ )
|
||||
{
|
||||
dictionary[ dictionary_ind ].byte = dictionary_ind;
|
||||
// XXX this only works because prev is a 32-bit int (> 12 bits)
|
||||
dictionary[ dictionary_ind ].prev = -1;
|
||||
dictionary[ dictionary_ind ].len = 1;
|
||||
}
|
||||
|
||||
// 2^code_len + 1 is the special "end" code; don't give it an entry here
|
||||
dictionary_ind++;
|
||||
dictionary_ind++;
|
||||
|
||||
// TODO verify that the very last byte is clear_code + 1
|
||||
while ( input_length )
|
||||
{
|
||||
code = 0x0;
|
||||
// Always read one more bit than the code length
|
||||
for ( i = 0; i < ( code_length + 1 ); i++ )
|
||||
{
|
||||
// This is different than in the file read example; that
|
||||
// was a call to "next_bit"
|
||||
bit = ( *input & mask ) ? 1 : 0;
|
||||
mask <<= 1;
|
||||
|
||||
if ( mask == 0x100 )
|
||||
{
|
||||
mask = 0x01;
|
||||
input++;
|
||||
input_length--;
|
||||
}
|
||||
|
||||
code = code | ( bit << i );
|
||||
}
|
||||
|
||||
if ( code == clear_code )
|
||||
{
|
||||
code_length = reset_code_length;
|
||||
dictionary = ( dictionary_entry_t * ) realloc( dictionary,
|
||||
sizeof( dictionary_entry_t ) * ( 1 << ( code_length + 1 ) ) );
|
||||
|
||||
for ( dictionary_ind = 0;
|
||||
dictionary_ind < ( 1 << code_length );
|
||||
dictionary_ind++ )
|
||||
{
|
||||
dictionary[ dictionary_ind ].byte = dictionary_ind;
|
||||
// XXX this only works because prev is a 32-bit int (> 12 bits)
|
||||
dictionary[ dictionary_ind ].prev = -1;
|
||||
dictionary[ dictionary_ind ].len = 1;
|
||||
}
|
||||
dictionary_ind++;
|
||||
dictionary_ind++;
|
||||
prev = -1;
|
||||
continue;
|
||||
}
|
||||
else if ( code == stop_code )
|
||||
{
|
||||
if ( input_length > 1 )
|
||||
{
|
||||
fprintf( stderr, "Malformed GIF (early stop code)\n" );
|
||||
exit( 0 );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Update the dictionary with this character plus the _entry_
|
||||
// (character or string) that came before it
|
||||
if ( ( prev > -1 ) && ( code_length < 12 ) )
|
||||
{
|
||||
if ( code > dictionary_ind )
|
||||
{
|
||||
fprintf( stderr, "code = %.02x, but dictionary_ind = %.02x\n",
|
||||
code, dictionary_ind );
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
// Special handling for KwKwK
|
||||
if ( code == dictionary_ind )
|
||||
{
|
||||
int ptr = prev;
|
||||
|
||||
while ( dictionary[ ptr ].prev != -1 )
|
||||
{
|
||||
ptr = dictionary[ ptr ].prev;
|
||||
}
|
||||
dictionary[ dictionary_ind ].byte = dictionary[ ptr ].byte;
|
||||
}
|
||||
else
|
||||
{
|
||||
int ptr = code;
|
||||
while ( dictionary[ ptr ].prev != -1 )
|
||||
{
|
||||
ptr = dictionary[ ptr ].prev;
|
||||
}
|
||||
dictionary[ dictionary_ind ].byte = dictionary[ ptr ].byte;
|
||||
}
|
||||
|
||||
dictionary[ dictionary_ind ].prev = prev;
|
||||
|
||||
dictionary[ dictionary_ind ].len = dictionary[ prev ].len + 1;
|
||||
|
||||
dictionary_ind++;
|
||||
|
||||
// GIF89a mandates that this stops at 12 bits
|
||||
if ( ( dictionary_ind == ( 1 << ( code_length + 1 ) ) ) &&
|
||||
( code_length < 11 ) )
|
||||
{
|
||||
code_length++;
|
||||
|
||||
dictionary = ( dictionary_entry_t * ) realloc( dictionary,
|
||||
sizeof( dictionary_entry_t ) * ( 1 << ( code_length + 1 ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
prev = code;
|
||||
|
||||
// Now copy the dictionary entry backwards into "out"
|
||||
match_len = dictionary[ code ].len;
|
||||
while ( code != -1 )
|
||||
{
|
||||
out[ dictionary[ code ].len - 1 ] = dictionary[ code ].byte;
|
||||
if ( dictionary[ code ].prev == code )
|
||||
{
|
||||
fprintf( stderr, "Internal error; self-reference." );
|
||||
exit( 0 );
|
||||
}
|
||||
code = dictionary[ code ].prev;
|
||||
}
|
||||
|
||||
out += match_len;
|
||||
}
|
||||
}
|
||||
|
||||
static int read_sub_blocks( unsigned char* buffer, unsigned char **data )
|
||||
{
|
||||
int data_length;
|
||||
int index;
|
||||
unsigned char block_size;
|
||||
|
||||
// Everything following are data sub-blocks, until a 0-sized block is
|
||||
// encountered.
|
||||
data_length = 0;
|
||||
*data = NULL;
|
||||
index = 0;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
READ(&block_size, 1);
|
||||
|
||||
if ( block_size == 0 ) // end of sub-blocks
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
data_length += block_size;
|
||||
*data = (unsigned char*)realloc( *data, data_length );
|
||||
|
||||
// TODO this could be split across block size boundaries
|
||||
READ(*data + index, block_size);
|
||||
|
||||
index += block_size;
|
||||
}
|
||||
|
||||
return data_length;
|
||||
}
|
||||
|
||||
unsigned char* process_image_descriptor( unsigned char* buffer,
|
||||
rgb *gct,
|
||||
int gct_size,
|
||||
int resolution_bits )
|
||||
{
|
||||
image_descriptor_t image_descriptor;
|
||||
int disposition;
|
||||
int compressed_data_length;
|
||||
unsigned char *compressed_data = NULL;
|
||||
unsigned char lzw_code_size;
|
||||
int uncompressed_data_length = 0;
|
||||
unsigned char *uncompressed_data = NULL;
|
||||
|
||||
// TODO there could actually be lots of these
|
||||
READ(&image_descriptor, 9);
|
||||
|
||||
// TODO if LCT = true, read the LCT
|
||||
|
||||
disposition = 1;
|
||||
|
||||
READ(&lzw_code_size, 1);
|
||||
|
||||
compressed_data_length = read_sub_blocks( buffer, &compressed_data );
|
||||
|
||||
// width = image_descriptor.image_width;
|
||||
// height = image_descriptor.image_height;
|
||||
uncompressed_data_length = image_descriptor.image_width *
|
||||
image_descriptor.image_height;
|
||||
uncompressed_data = (unsigned char*)malloc( uncompressed_data_length );
|
||||
|
||||
uncompress( lzw_code_size, compressed_data, compressed_data_length,
|
||||
uncompressed_data );
|
||||
|
||||
if ( compressed_data ) free( compressed_data );
|
||||
|
||||
//if ( uncompressed_data )
|
||||
// free( uncompressed_data );
|
||||
|
||||
return uncompressed_data;
|
||||
}
|
||||
|
||||
static int process_extension( unsigned char* buffer )
|
||||
{
|
||||
extension_t extension;
|
||||
graphic_control_extension_t gce;
|
||||
application_extension_t application;
|
||||
plaintext_extension_t plaintext;
|
||||
unsigned char *extension_data = NULL;
|
||||
int extension_data_length;
|
||||
|
||||
READ(&extension, 2);
|
||||
|
||||
switch ( extension.extension_code )
|
||||
{
|
||||
case GRAPHIC_CONTROL:
|
||||
READ(&gce, 4);
|
||||
|
||||
break;
|
||||
case APPLICATION_EXTENSION:
|
||||
READ(&application, 11);
|
||||
break;
|
||||
case 0xFE:
|
||||
// comment extension; do nothing - all the data is in the
|
||||
// sub-blocks that follow.
|
||||
break;
|
||||
case 0x01:
|
||||
READ(&plaintext, 12);
|
||||
break;
|
||||
default:
|
||||
fprintf( stderr, "Unrecognized extension code.\n" );
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
// All extensions are followed by data sub-blocks; even if it's
|
||||
// just a single data sub-block of length 0
|
||||
extension_data_length = read_sub_blocks( buffer, &extension_data );
|
||||
|
||||
if ( extension_data != NULL )
|
||||
free( extension_data );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param gif_file the file descriptor of a file containing a
|
||||
* GIF-encoded file. This should point to the first byte in
|
||||
* the file when invoked.
|
||||
*/
|
||||
|
||||
unsigned char* LoadPalette(unsigned char *buffer) {
|
||||
unsigned char header[7];
|
||||
screen_descriptor_t screen_descriptor;
|
||||
int color_resolution_bits;
|
||||
|
||||
int global_color_table_size = 0; // number of entries in global_color_table
|
||||
rgb *global_color_table = NULL;
|
||||
|
||||
READ(header, 6);
|
||||
READ(&screen_descriptor, 7);
|
||||
|
||||
color_resolution_bits = ((screen_descriptor.fields & 0x70) >> 4) + 1;
|
||||
global_color_table = (rgb *)calloc(1, 768);
|
||||
|
||||
if (screen_descriptor.fields & 0x80) {
|
||||
global_color_table_size = 1 << (((screen_descriptor.fields & 0x07) + 1));
|
||||
|
||||
//global_color_table = (rgb *)malloc(3 * global_color_table_size);
|
||||
READ(global_color_table, 3 * global_color_table_size);
|
||||
}
|
||||
return (unsigned char*)global_color_table;
|
||||
}
|
||||
|
||||
static unsigned char* process_gif_stream(unsigned char *buffer, unsigned short* w, unsigned short* h)
|
||||
{
|
||||
unsigned char header[ 7 ];
|
||||
screen_descriptor_t screen_descriptor;
|
||||
int color_resolution_bits;
|
||||
|
||||
int global_color_table_size =0; // number of entries in global_color_table
|
||||
rgb *global_color_table = NULL;
|
||||
|
||||
unsigned char block_type = 0x0;
|
||||
|
||||
// A GIF file starts with a Header (section 17)
|
||||
READ(header, 6);
|
||||
header[ 6 ] = 0x0;
|
||||
|
||||
// XXX there's another format, GIF87a, that you may still find
|
||||
// floating around.
|
||||
if ( strcmp( "GIF89a", (char*)header ) )
|
||||
{
|
||||
fprintf( stderr,
|
||||
"Invalid GIF file (header is '%s', should be 'GIF89a')\n",
|
||||
header );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Followed by a logical screen descriptor
|
||||
// Note that this works because GIFs specify little-endian order; on a
|
||||
// big-endian machine, the height & width would need to be reversed.
|
||||
|
||||
// Can't use sizeof here since GCC does byte alignment;
|
||||
// sizeof( screen_descriptor_t ) = 8!
|
||||
READ(&screen_descriptor, 7);
|
||||
|
||||
*w = screen_descriptor.width;
|
||||
*h = screen_descriptor.height;
|
||||
|
||||
color_resolution_bits = ( ( screen_descriptor.fields & 0x70 ) >> 4 ) + 1;
|
||||
|
||||
if ( screen_descriptor.fields & 0x80 )
|
||||
{
|
||||
//int i;
|
||||
// If bit 7 is set, the next block is a global color table; read it
|
||||
global_color_table_size = 1 <<
|
||||
( ( ( screen_descriptor.fields & 0x07 ) + 1 ) );
|
||||
|
||||
global_color_table = ( rgb * ) malloc( 3 * global_color_table_size );
|
||||
|
||||
// XXX this could conceivably return a short count...
|
||||
READ(global_color_table, 3 * global_color_table_size);
|
||||
}
|
||||
|
||||
while ( block_type != TRAILER )
|
||||
{
|
||||
READ(&block_type, 1);
|
||||
|
||||
switch ( block_type )
|
||||
{
|
||||
case IMAGE_DESCRIPTOR:
|
||||
return process_image_descriptor(buffer,
|
||||
global_color_table,
|
||||
global_color_table_size,
|
||||
color_resolution_bits);
|
||||
break;
|
||||
case EXTENSION_INTRODUCER:
|
||||
if ( !process_extension( buffer ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case TRAILER:
|
||||
break;
|
||||
default:
|
||||
fprintf( stderr, "Bailing on unrecognized block type %.02x\n",
|
||||
block_type );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
unsigned char* LoadGif(unsigned char *buffer, unsigned short* w, unsigned short* h) {
|
||||
return process_gif_stream(buffer, w, h);
|
||||
}
|
||||
|
||||
/*int main( int argc, char *argv[] )
|
||||
{
|
||||
FILE* gif_file;
|
||||
|
||||
if ( argc < 2 )
|
||||
{
|
||||
fprintf( stderr, "Usage: %s <path-to-gif-file>\n", argv[ 0 ] );
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
gif_file = fopen( argv[ 1 ], "rb" );
|
||||
|
||||
if ( gif_file == NULL )
|
||||
{
|
||||
fprintf( stderr, "Unable to open file '%s'", argv[ 1 ] );
|
||||
perror( ": " );
|
||||
}
|
||||
|
||||
process_gif_stream( gif_file );
|
||||
|
||||
fclose( gif_file );
|
||||
}*/
|
||||
234
main.cpp
Normal file
234
main.cpp
Normal file
@@ -0,0 +1,234 @@
|
||||
#include <SDL.h>
|
||||
#include <SDL_mixer.h>
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
#include "font.h"
|
||||
#include "gif.c"
|
||||
#include <stdio.h>
|
||||
|
||||
struct Mouse {
|
||||
int x, y;
|
||||
bool buttons[3];
|
||||
};
|
||||
|
||||
typedef bool(*LoopFun)(void);
|
||||
|
||||
SDL_Window* sdlWindow = NULL;
|
||||
SDL_Renderer* sdlRenderer = NULL;
|
||||
SDL_Texture* sdlFontTexture = NULL;
|
||||
SDL_Texture* sdlTilesTexture = NULL;
|
||||
SDL_Event sdlEvent;
|
||||
bool anyKey = false;
|
||||
LoopFun loop;
|
||||
Mouse mouse;
|
||||
int error = 0;
|
||||
|
||||
int tile_width = 16;
|
||||
int tile_height = 16;
|
||||
int map_width = 240;
|
||||
int map_height = 240;
|
||||
int screen_width = 256;
|
||||
int screen_height = 192;
|
||||
int zoom = 2;
|
||||
char tiles_filename[100] = { 0 };
|
||||
char map_filename[100] = { 0 };
|
||||
int tilemap_width = 0;
|
||||
int tilemap_height = 0;
|
||||
|
||||
int map_x = 0;
|
||||
int map_y = 0;
|
||||
|
||||
int StrToInt(const char* str) {
|
||||
int val = 0;
|
||||
int size = strlen(str);
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (str[i] < 48 || str[i] > 57) return 0;
|
||||
val = val * 10 + (str[i] - 48);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
void LoadConfig() {
|
||||
FILE* f = fopen("config.ini", "r");
|
||||
if (!f) { error = 1; return; }
|
||||
char key[50];
|
||||
char val[255];
|
||||
while (!feof(f)) {
|
||||
fscanf(f, "%s = %s", key, val);
|
||||
if (strcmp(key, "tile_width") == 0) { tile_width = StrToInt(val); }
|
||||
else if (strcmp(key, "tile_height") == 0) { tile_height = StrToInt(val); }
|
||||
else if (strcmp(key, "map_width") == 0) { map_width = StrToInt(val); }
|
||||
else if (strcmp(key, "map_height") == 0) { map_height = StrToInt(val); }
|
||||
else if (strcmp(key, "screen_width") == 0) { screen_width = StrToInt(val); }
|
||||
else if (strcmp(key, "screen_height") == 0) { screen_height = StrToInt(val); }
|
||||
else if (strcmp(key, "zoom") == 0) { zoom = StrToInt(val); }
|
||||
else if (strcmp(key, "tiles") == 0) { strcpy(tiles_filename, val); }
|
||||
else if (strcmp(key, "map") == 0) { strcpy(map_filename, val); }
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void Init() {
|
||||
LoadConfig();
|
||||
SDL_Init(SDL_INIT_EVERYTHING);
|
||||
sdlWindow = SDL_CreateWindow("Mappy v0.1", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_width*zoom, screen_height*zoom, SDL_WINDOW_SHOWN);
|
||||
sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_PRESENTVSYNC);
|
||||
//SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
|
||||
SDL_RenderSetLogicalSize(sdlRenderer, screen_width, screen_height);
|
||||
|
||||
unsigned short w, h;
|
||||
unsigned char* buffer = LoadGif(font, &w, &h);
|
||||
|
||||
sdlFontTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, w, h);
|
||||
Uint32* pixels = (Uint32*)malloc(w*h*sizeof(Uint32));
|
||||
for (int i = 0; i < w*h; i++) { pixels[i] = buffer[i] == 0 ? 0x00000000 : 0xffffffff; }
|
||||
SDL_UpdateTexture(sdlFontTexture, NULL, pixels, w * sizeof(Uint32));
|
||||
SDL_SetTextureBlendMode(sdlFontTexture, SDL_BLENDMODE_BLEND);
|
||||
free(buffer);
|
||||
free(pixels);
|
||||
|
||||
int c;
|
||||
FILE* f = fopen(tiles_filename, "rb");
|
||||
if (!f) {
|
||||
error = 2;
|
||||
} else {
|
||||
buffer = stbi_load_from_file(f, &tilemap_width, &tilemap_height, &c, 4);
|
||||
sdlTilesTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, tilemap_width, tilemap_height);
|
||||
SDL_UpdateTexture(sdlTilesTexture, NULL, buffer, tilemap_width * sizeof(Uint32));
|
||||
SDL_SetTextureBlendMode(sdlTilesTexture, SDL_BLENDMODE_BLEND);
|
||||
stbi_image_free(buffer);
|
||||
}
|
||||
|
||||
//SDL_Surface* bmp = SDL_LoadBMP("assets.bmp");
|
||||
//texture = SDL_CreateTextureFromSurface(renderer, bmp);
|
||||
//SDL_FreeSurface(bmp);
|
||||
}
|
||||
|
||||
void Quit() {
|
||||
SDL_DestroyTexture(sdlFontTexture);
|
||||
SDL_DestroyRenderer(sdlRenderer);
|
||||
SDL_DestroyWindow(sdlWindow);
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
void Flip() { SDL_RenderPresent(sdlRenderer); }
|
||||
void Clear() { SDL_SetRenderDrawColor(sdlRenderer, 0, 0, 0, 255); SDL_RenderClear(sdlRenderer); }
|
||||
|
||||
void Draw(SDL_Texture* texture, int x, int y, int sx, int sy, int w, int h) {
|
||||
SDL_Rect src, dst;
|
||||
src.x = sx; src.y = sy;
|
||||
dst.x = x; dst.y = y;
|
||||
src.w = dst.w = w;
|
||||
src.h = dst.h = h;
|
||||
SDL_RenderCopy(sdlRenderer, texture, &src, &dst);
|
||||
}
|
||||
|
||||
void FillRect(int x, int y, int w, int h, Uint8 r, Uint8 g, Uint8 b, Uint8 a = 255) {
|
||||
SDL_Rect src;
|
||||
src.x = x; src.y = y; src.w = w; src.h = h;
|
||||
SDL_SetRenderDrawColor(sdlRenderer, r, g, b, a);
|
||||
SDL_RenderFillRect(sdlRenderer, &src);
|
||||
}
|
||||
|
||||
void Print(int x, int y, const char* text) {
|
||||
int str_size = strlen(text);
|
||||
for (int i = 0; i < str_size; i++) {
|
||||
char chr = text[i] - 32;
|
||||
Draw(sdlFontTexture, x + (i * 6), y, (chr & 0x0f) * 6, (chr >> 4) * 6, 6, 6);
|
||||
}
|
||||
}
|
||||
|
||||
bool Button(int x, int y, char* text) {
|
||||
bool inside = (mouse.x >= x) && (mouse.y >= y) && (mouse.x < x + 51) && (mouse.y < y + 8);
|
||||
if (inside) {
|
||||
FillRect(x, y, 51, 9, 128, 64, 64, 255);
|
||||
} else {
|
||||
FillRect(x, y, 51, 9, 255, 64, 64, 255);
|
||||
}
|
||||
Print(x+2, y+2, text);
|
||||
return inside && mouse.buttons[0];
|
||||
}
|
||||
|
||||
bool Update() {
|
||||
anyKey = false;
|
||||
while (SDL_PollEvent(&sdlEvent)) {
|
||||
if (sdlEvent.type == SDL_QUIT) {return true; break; }
|
||||
else if (sdlEvent.type == SDL_KEYDOWN) {
|
||||
anyKey = true;
|
||||
if (sdlEvent.key.keysym.scancode == SDL_SCANCODE_ESCAPE) { return true; }
|
||||
}
|
||||
}
|
||||
Uint32 buttons = SDL_GetMouseState(&mouse.x, &mouse.y);
|
||||
mouse.x /= zoom;
|
||||
mouse.y /= zoom;
|
||||
mouse.buttons[0] = (buttons & 1) == 1;
|
||||
mouse.buttons[1] = (buttons & 2) == 2;
|
||||
mouse.buttons[2] = (buttons & 4) == 4;
|
||||
return false;
|
||||
}
|
||||
|
||||
void PrintFatalError(const char* errorMsg) {
|
||||
int size = strlen(errorMsg);
|
||||
Print((screen_width - (size*6)) / 2, (screen_height - 6) / 2, errorMsg);
|
||||
}
|
||||
void ShowError() {
|
||||
switch (error) {
|
||||
case 1: PrintFatalError("No s'ha trobat l'arxiu config.ini"); break;
|
||||
case 2: PrintFatalError("No s'ha trobat arxiu de tiles"); break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
Init();
|
||||
|
||||
while (!Update()) {
|
||||
Clear();
|
||||
|
||||
if (error == 0) {
|
||||
int x = 0, y = 0;
|
||||
if (tilemap_width <= screen_width) {
|
||||
x = (screen_width - tilemap_width) / 2;
|
||||
} else {
|
||||
const int max_offset = tilemap_width - screen_width;
|
||||
const float mouse_ratio = float(mouse.x) / float(screen_width);
|
||||
x = -(mouse_ratio * max_offset);
|
||||
}
|
||||
if (tilemap_height <= screen_height) {
|
||||
y = (screen_height - tilemap_height) / 2;
|
||||
}
|
||||
else {
|
||||
const int max_offset = tilemap_height - screen_height;
|
||||
const float mouse_ratio = float(mouse.y) / float(screen_height);
|
||||
y = -(mouse_ratio * max_offset);
|
||||
}
|
||||
Draw(sdlTilesTexture, x, y, 0, 0, tilemap_width, tilemap_height);
|
||||
/*char num[5];
|
||||
sprintf(num, "%d", mouse.x);
|
||||
Print(100, 100, num);
|
||||
sprintf(num, ",%d", mouse.y);
|
||||
Print(118, 100, num);
|
||||
|
||||
if (Button(2, 2, "New")) {
|
||||
strcpy(state, "New pressed");
|
||||
}
|
||||
if (Button(2, 12, "Open")) {
|
||||
strcpy(state, "open pressed");
|
||||
}
|
||||
if (Button(2, 22, "Save")) {
|
||||
strcpy(state, "save pressed");
|
||||
}
|
||||
if (Button(2, 32, "Save As")) {
|
||||
strcpy(state, "Save As pressed");
|
||||
}
|
||||
|
||||
FillRect(0, 183, 256, 9, 128, 128, 128, 255);
|
||||
Print(2, 185, state);*/
|
||||
} else {
|
||||
ShowError();
|
||||
}
|
||||
Flip();
|
||||
}
|
||||
|
||||
Quit();
|
||||
return 0;
|
||||
}
|
||||
22
mappy.sln
Normal file
22
mappy.sln
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mappy", "mappy.vcxproj", "{A54CF7AB-24D6-4778-9B8B-80F1ADEE3363}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A54CF7AB-24D6-4778-9B8B-80F1ADEE3363}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{A54CF7AB-24D6-4778-9B8B-80F1ADEE3363}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{A54CF7AB-24D6-4778-9B8B-80F1ADEE3363}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{A54CF7AB-24D6-4778-9B8B-80F1ADEE3363}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
92
mappy.vcxproj
Normal file
92
mappy.vcxproj
Normal file
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{A54CF7AB-24D6-4778-9B8B-80F1ADEE3363}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>mappy</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>C:\dev\lib\sdl2\include;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>C:\dev\lib\sdl2\lib\x86;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="gif.c" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="font.h" />
|
||||
<ClInclude Include="stb_image.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
33
mappy.vcxproj.filters
Normal file
33
mappy.vcxproj.filters
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gif.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="font.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="stb_image.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
6845
stb_image.h
Normal file
6845
stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user