From 415d45749c26b6c51981ab2baef33579c55bf21a Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Wed, 7 Mar 2018 18:55:57 +0100 Subject: [PATCH] Remove circular dependencies between libs, use callback function pointers instead --- src/libcpu/execute.c | 35 +++-- src/libcpu/execute.h | 4 +- src/libdisk/disk.c | 8 + src/libdisk/disk.h | 3 +- src/libsdl/sdl.c | 7 +- src/libsdl/sdl.h | 4 +- src/mercenary/main.c | 420 ++++++++++++++++++++++++++------------------------- 7 files changed, 249 insertions(+), 232 deletions(-) diff --git a/src/libcpu/execute.c b/src/libcpu/execute.c index cb97845..0b53f23 100644 --- a/src/libcpu/execute.c +++ b/src/libcpu/execute.c @@ -32,23 +32,26 @@ static uint8_t *memory = NULL; static uint32_t memory_size = 0; static uint16_t *chipreg = NULL; +static uint16_t (*io_read)(uint32_t address) = NULL; +static void (*io_write)(uint32_t address, uint16_t value) = NULL; -static uint16_t read_io(unsigned int address) + +static uint16_t read_io_16(unsigned int address) { #ifdef DEBUG_CPU printf("Chip read from 0x%08x\n", address); #endif - return emulate_io_read(address); + return io_read(address); } -static void write_io(unsigned int address, uint16_t value) +static void write_io_16(unsigned int address, uint16_t value) { #ifdef DEBUG_CPU printf("Chip write to 0x%08x\n", address); #endif if ((address & IOMASK) == IOBASE) chipreg[address & ~IOMASK] = value; - emulate_io_write(address, value); + io_write(address, value); } unsigned int m68k_read_memory_8(unsigned int address) @@ -56,10 +59,10 @@ unsigned int m68k_read_memory_8(unsigned int address) if (address > memory_size - 1) { if ((address & 1)) { /* read lower (right) byte */ - return read_io(address & ~1); + return read_io_16(address & ~1); } else { /* read upper (left) byte */ - return read_io(address) >> 8; + return read_io_16(address) >> 8; } } return *((uint8_t *)(memory + address)); @@ -68,7 +71,7 @@ unsigned int m68k_read_memory_8(unsigned int address) unsigned int m68k_read_memory_16(unsigned int address) { if (address > memory_size - 2) { - return read_io(address); + return read_io_16(address); } return (memory[address] << 8) | memory[address + 1]; @@ -78,8 +81,8 @@ unsigned int m68k_read_memory_32(unsigned int address) { if (address > memory_size - 4) { int32_t value; - value = read_io(address) << 16; - value |= read_io(address + 2); + value = read_io_16(address) << 16; + value |= read_io_16(address + 2); return value; } return (memory[address] << 24)| @@ -93,10 +96,10 @@ void m68k_write_memory_8(unsigned int address, unsigned int value) if (address > memory_size - 1) { if ((address & 1)) { /* write lower (right) byte */ - write_io(address & ~1, 0xff00 | value); + write_io_16(address & ~1, 0xff00 | value); } else { /* write upper (left) byte */ - write_io(address, 0x00ff | (value << 8)); + write_io_16(address, 0x00ff | (value << 8)); } return; } @@ -106,7 +109,7 @@ void m68k_write_memory_8(unsigned int address, unsigned int value) void m68k_write_memory_16(unsigned int address, unsigned int value) { if (address > memory_size - 2) { - write_io(address, value); + write_io_16(address, value); return; } memory[address] = value >> 8; @@ -116,8 +119,8 @@ void m68k_write_memory_16(unsigned int address, unsigned int value) void m68k_write_memory_32(unsigned int address, unsigned int value) { if (address > memory_size - 4) { - write_io(address, value >> 16); - write_io(address + 2, value); + write_io_16(address, value >> 16); + write_io_16(address + 2, value); return; } memory[address] = value >> 24; @@ -126,11 +129,13 @@ void m68k_write_memory_32(unsigned int address, unsigned int value) memory[address + 3] = value; } -void execute_init(int32_t _memory_size, uint8_t *_memory, uint16_t *_chipreg) +void execute_init(int32_t _memory_size, uint8_t *_memory, uint16_t *_chipreg, uint16_t (*_io_read)(uint32_t address), void (*_io_write)(uint32_t address, uint16_t value)) { memory_size = _memory_size; memory = _memory; chipreg = _chipreg; + io_read = _io_read; + io_write = _io_write; /* init CPU */ m68k_init(); diff --git a/src/libcpu/execute.h b/src/libcpu/execute.h index 64ef160..2b84421 100644 --- a/src/libcpu/execute.h +++ b/src/libcpu/execute.h @@ -4,9 +4,7 @@ struct cpu_stop { int event; }; -void execute_init(int32_t _memory_size, uint8_t *_memory, uint16_t *_chipreg); +void execute_init(int32_t _memory_size, uint8_t *_memory, uint16_t *_chipreg, uint16_t (*io_read)(uint32_t address), void (*io_write)(uint32_t address, uint16_t value)); void reset_cpu(void); int execute_cpu(int irq, const struct cpu_stop stop_at[], int *event); -uint16_t emulate_io_read(uint32_t address); -void emulate_io_write(uint32_t address, uint16_t value); diff --git a/src/libdisk/disk.c b/src/libdisk/disk.c index e9126d4..ba34192 100644 --- a/src/libdisk/disk.c +++ b/src/libdisk/disk.c @@ -35,9 +35,17 @@ static uint16_t ciabprb = 0xffff; static int track = 0; static uint32_t dskptr = 0; static uint16_t dsklen = 0; +static void (*disk_read)(int track, int side, uint32_t data, uint16_t length) = NULL; +static void (*disk_write)(int track, int side, uint32_t data, uint16_t length) = NULL; /* NOTE: all CIA access is WORD access, so we use bits 8..15 for CIA-B */ +void disk_init(void (*_disk_read)(int track, int side, uint32_t data, uint16_t length), void (*_disk_write)(int track, int side, uint32_t data, uint16_t length)) +{ + disk_read = _disk_read; + disk_write = _disk_write; +} + uint16_t emulate_disk_read(uint32_t address) { uint16_t value = 0xffff; diff --git a/src/libdisk/disk.h b/src/libdisk/disk.h index 76361f2..0d517fe 100644 --- a/src/libdisk/disk.h +++ b/src/libdisk/disk.h @@ -1,7 +1,6 @@ +void disk_init(void (*disk_read)(int track, int side, uint32_t data, uint16_t length), void (*disk_write)(int track, int side, uint32_t data, uint16_t length)); uint16_t emulate_disk_read(uint32_t address); void emulate_disk_write(uint32_t address, uint16_t value); int get_disk_track(void); -void disk_read(int track, int side, uint32_t data, uint16_t length); -void disk_write(int track, int side, uint32_t data, uint16_t length); diff --git a/src/libsdl/sdl.c b/src/libsdl/sdl.c index ad57dad..99178db 100644 --- a/src/libsdl/sdl.c +++ b/src/libsdl/sdl.c @@ -30,6 +30,8 @@ static int sdl_initialized = 0; static int audio_initialized = 0; static SDL_Window *gl_window = NULL; static SDL_GLContext gl_context = NULL; +static void (*keyboard_sdl)(int down, SDL_Keycode sym) = NULL; +static void (*audio_sdl)(float *data, int len) = NULL; static void audio_cb(void __attribute__((unused)) *userdata, Uint8 *stream, int len) { @@ -40,10 +42,13 @@ static void audio_cb(void __attribute__((unused)) *userdata, Uint8 *stream, int SDL_MixAudio(stream, (Uint8 *)audio_data, len, SDL_MIX_MAXVOLUME); } -int init_sdl(const char *progname, int width, int height, int sound_samplerate, int sound_chunk) +int init_sdl(const char *progname, int width, int height, int sound_samplerate, int sound_chunk, void (*keyboard)(int down, SDL_Keycode sym), void (*audio)(float *data, int len)) { int rc; + keyboard_sdl = keyboard; + audio_sdl = audio; + /* init SDL library */ rc = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); if (rc < 0) { diff --git a/src/libsdl/sdl.h b/src/libsdl/sdl.h index dab62c2..08eb7fc 100644 --- a/src/libsdl/sdl.h +++ b/src/libsdl/sdl.h @@ -1,9 +1,7 @@ #include -int init_sdl(const char *progname, int width, int height, int sound_samplerate, int sound_chunk); +int init_sdl(const char *progname, int width, int height, int sound_samplerate, int sound_chunk, void (*keyboard)(int down, SDL_Keycode sym), void (*audio)(float *data, int len)); int event_sdl(void); void swap_sdl(void); void exit_sdl(void); -void audio_sdl(float *data, int len); -void keyboard_sdl(int down, SDL_Keycode sym); diff --git a/src/mercenary/main.c b/src/mercenary/main.c index c0d5150..4dce2fb 100644 --- a/src/mercenary/main.c +++ b/src/mercenary/main.c @@ -250,143 +250,121 @@ static void main_loop(void) } } -int main(int argc, char *argv[]) +static uint16_t io_read(uint32_t address) { - int rc; - int sdl_sound_chunk; - - home_dir = getenv("HOME"); - if (!home_dir) - home_dir = ""; - - rc = parse_args(argc, argv); - if (rc) - return 0; + uint16_t value = 0xffff; - /* allocate image */ - image = calloc(IMAGE_WIDTH * IMAGE_HEIGHT * ((double_size) ? 4 : 1), 3); - if (!image) { - fprintf(stderr, "Failed to allocate image buffer\n"); - goto done; - } + /* joystick and fire button */ + if (address == 0xbfe000 || address == 0xdff00c) + value &= emulate_joystick_read(address); + /* keyboard */ + if (address == 0xbfec00 || address == 0xbfed00 || address == 0xbfee00) + value &= emulate_keyboard_read(address); + /* diskette */ + if (address == 0xbfd100 || address == 0xbfe000 || address == 0xdff01a || address == 0xdff01e) + value &= emulate_disk_read(address); - if ((SOUND_SAMPLERATE % IRQ_RATE)) { - fprintf(stderr, "Sample rate must be a multiple of IRQ rate, please fix!\n"); - goto done; - } - if ((1000 % IRQ_RATE)) { - fprintf(stderr, "1000 (Ticks per second) rate must be a multiple of IRQ rate, please fix!\n"); - goto done; - } + return value; +} - /* calculate SDL chunk size for audio - * it must be a power of two, but not more than the chunk size for each IRQ! - */ - for (sdl_sound_chunk = 2; sdl_sound_chunk <= (SOUND_SAMPLERATE / IRQ_RATE); sdl_sound_chunk <<= 1) - ; - sdl_sound_chunk >>= 1; -// printf("samples per IRQ = %d, samples per SDL audio = %d\n", SOUND_SAMPLERATE / IRQ_RATE, sdl_sound_chunk); exit(0); +static void io_write(uint32_t address, uint16_t value) +{ + /* dmacon and sound registers */ + if (address == 0xdff096 || (address >= 0xdff0a0 && address <= 0xdff0df)) + emulate_sound_write(address, value, SOUND_SAMPLERATE); + if (address == 0xbfd100 || (address >= 0xdff020 && address <= 0xdff024)) + emulate_disk_write(address, value); +} - /* allocate sound buffers */ - sound_buffer_size = SOUND_SAMPLERATE / IRQ_RATE * SOUND_CHUNKS; - sound_buffer = calloc(sound_buffer_size, sizeof(*sound_buffer)); - if (!sound_buffer) { - fprintf(stderr, "Failed to allocate image buffer\n"); - goto done; - } +/* two tracks with 0x1820 words of length */ +static uint8_t game_save[2][0x1820 << 1]; +static int last_track = 0; - /* allocate memory */ - memory = calloc(MEMORY_SIZE, 1); - if (!memory) { - fprintf(stderr, "Failed to allocate cpu's memory\n"); - goto done; - } - chipreg = calloc(IOSIZE, 1); - if (!chipreg) { - fprintf(stderr, "Failed to allocate chip register\n"); - goto done; +/* game reads track with saved game */ +static void disk_read(int track, int __attribute__((unused)) side, uint32_t data, uint16_t length) +{ + if (length > sizeof(game_save[0])) { + fprintf(stderr, "loading game state failed, because length exceeds game save data size, please fix!\n"); + return; } - /* init cpu code */ - execute_init(MEMORY_SIZE, memory, chipreg); - - /* load binary */ - mercenary_load(); - - /* patch some stuff */ - mercenary_patch(); - - /* init SDL and OpenGL */ - rc = init_sdl(argv[0], SCREEN_WIDTH, SCREEN_HEIGHT, SOUND_SAMPLERATE, sdl_sound_chunk); - if (rc < 0) - goto done; - rc = init_opengl((double_size) ? IMAGE_WIDTH * 2 : IMAGE_WIDTH, (double_size) ? IMAGE_HEIGHT * 2 : IMAGE_HEIGHT); - if (rc < 0) - goto done; - resize_opengl(SCREEN_WIDTH, SCREEN_HEIGHT); - - /* init audio filter */ - sound_init_filter(SOUND_SAMPLERATE); + /* if even track is selected, load game */ + if (!(track & 1)) { + char filename[256]; + int gamesave_num = (track - 2) >> 1; + int got; + FILE *fp; - /* start cpu */ - reset_cpu(); + memset(game_save, 0, sizeof(game_save)); /* clear so make the game fail, if we fail */ + sprintf(filename, "%s/%s/%d.gamesave", home_dir, config_gamesave_dir, gamesave_num); + fp = fopen(filename, "r"); + if (!fp) { +fail: + fprintf(stderr, "failed to load game from '%s'\n", filename); + goto copy; + } + got = fread(game_save, sizeof(game_save[0]), 2, fp); + fclose(fp); + if (got != 2) + goto fail; + } - printf("**********************************\n"); - printf("* Welcome to Mercenary Reloaded! *\n"); - printf("**********************************\n\n"); - printf("Press CTRL + cursor keys to select inventory or pickup/drop item.\n"); - printf("Press CTRL + f to toggle full screen.\n"); - printf("Press CTRL + s to toggle rendering speed.\n"); - printf("Press CTRL + v to toggle video filter.\n"); - printf("Press CTRL + a to toggle audio filter.\n"); - printf("Press CTRL + c to exit game.\n\n"); - printf("Use '--help' as command line option for configuration settings.\n\n"); +copy: + /* copy track */ + memcpy(memory + data, game_save[track & 1], length /* sizeof(game_save[0])*/); +} - /* run game */ - main_loop(); +/* game writes track with saved game */ +static void disk_write(int track, int __attribute__((unused)) side, uint32_t data, uint16_t length) +{ + /* skip sync info that is provided by game and only relevant for a real disk track */ + data += 0x200; + length -= 0x200; -done: - exit_opengl(); - exit_sdl(); + if (length != sizeof(game_save[0])) { + fprintf(stderr, "saving game state failed, because length of data does not match, please fix!\n"); + return; + } - if (chipreg) - free(chipreg); - if (memory) - free(memory); - if (sound_buffer) - free(sound_buffer); - if (image) - free(image); + /* don't save if last track is the same, because disk is written on both sides with the same data */ + if (track == last_track) { + if (memcmp(memory + data, game_save[track & 1], length)) { + fprintf(stderr, "saving game data on other side of the disk is different, please fix!\n"); + } + return; + } + last_track = track; - return 0; -} + /* save game data */ + memcpy(game_save[track & 1], memory + data, length); -void audio_sdl(float *data, int length) -{ - int fill, s; + /* if done with saving */ + if ((track & 1)) { + char filename[256]; + int gamesave_num = (track - 2) >> 1; + int wrote; + FILE *fp; - /* read sound from sound buffer - * buffer pointer read and write is atomic, so no locking required! - */ - fill = (sound_buffer_writep - sound_buffer_readp + sound_buffer_size) % sound_buffer_size; - if (fill < length) { -#ifdef DEBUG_SOUND_BUFFERING - fprintf(stderr, "sound buffer underrun\n"); -#endif - /* correct read pointer as if the buffer would have 'length' of samples stored inside */ - sound_buffer_readp = (sound_buffer_readp + fill - length + sound_buffer_size) % sound_buffer_size; + sprintf(filename, "%s/%s", home_dir, config_gamesave_dir); + mkdir(filename, 0777); + sprintf(filename + strlen(filename), "/%d.gamesave", gamesave_num); + fp = fopen(filename, "w"); + if (!fp) { +fail: + fprintf(stderr, "failed to save game to '%s'\n", filename); + return; + } + printf("Game state saved to '%s'\n", filename); + wrote = fwrite(game_save, sizeof(game_save[0]), 2, fp); + fclose(fp); + if (wrote != 2) + goto fail; } - for (s = 0; s < length; s++) - *data++ = sound_buffer[(sound_buffer_readp + s) % sound_buffer_size]; -#ifdef DEBUG_SOUND_BUFFERING - printf("fill %d = %.4f\n", length, sound_buffer[sound_buffer_readp]); -#endif - sound_buffer_readp =(sound_buffer_readp + length) % sound_buffer_size; } static int shift = 0, ctrl = 0; -void keyboard_sdl(int down, SDL_Keycode sym) +static void keyboard_sdl(int down, SDL_Keycode sym) { switch (sym) { case SDLK_LCTRL: @@ -544,114 +522,140 @@ void keyboard_sdl(int down, SDL_Keycode sym) } } -uint16_t emulate_io_read(uint32_t address) +void audio_sdl(float *data, int length) { - uint16_t value = 0xffff; - - /* joystick and fire button */ - if (address == 0xbfe000 || address == 0xdff00c) - value &= emulate_joystick_read(address); - /* keyboard */ - if (address == 0xbfec00 || address == 0xbfed00 || address == 0xbfee00) - value &= emulate_keyboard_read(address); - /* diskette */ - if (address == 0xbfd100 || address == 0xbfe000 || address == 0xdff01a || address == 0xdff01e) - value &= emulate_disk_read(address); + int fill, s; - return value; + /* read sound from sound buffer + * buffer pointer read and write is atomic, so no locking required! + */ + fill = (sound_buffer_writep - sound_buffer_readp + sound_buffer_size) % sound_buffer_size; + if (fill < length) { +#ifdef DEBUG_SOUND_BUFFERING + fprintf(stderr, "sound buffer underrun\n"); +#endif + /* correct read pointer as if the buffer would have 'length' of samples stored inside */ + sound_buffer_readp = (sound_buffer_readp + fill - length + sound_buffer_size) % sound_buffer_size; + } + for (s = 0; s < length; s++) + *data++ = sound_buffer[(sound_buffer_readp + s) % sound_buffer_size]; +#ifdef DEBUG_SOUND_BUFFERING + printf("fill %d = %.4f\n", length, sound_buffer[sound_buffer_readp]); +#endif + sound_buffer_readp =(sound_buffer_readp + length) % sound_buffer_size; } -void emulate_io_write(uint32_t address, uint16_t value) +int main(int argc, char *argv[]) { - /* dmacon and sound registers */ - if (address == 0xdff096 || (address >= 0xdff0a0 && address <= 0xdff0df)) - emulate_sound_write(address, value, SOUND_SAMPLERATE); - if (address == 0xbfd100 || (address >= 0xdff020 && address <= 0xdff024)) - emulate_disk_write(address, value); -} - -/* two tracks with 0x1820 words of length */ -static uint8_t game_save[2][0x1820 << 1]; -static int last_track = 0; + int rc; + int sdl_sound_chunk; -/* game reads track with saved game */ -void disk_read(int track, int __attribute__((unused)) side, uint32_t data, uint16_t length) -{ - if (length > sizeof(game_save[0])) { - fprintf(stderr, "loading game state failed, because length exceeds game save data size, please fix!\n"); - return; - } + home_dir = getenv("HOME"); + if (!home_dir) + home_dir = ""; - /* if even track is selected, load game */ - if (!(track & 1)) { - char filename[256]; - int gamesave_num = (track - 2) >> 1; - int got; - FILE *fp; + rc = parse_args(argc, argv); + if (rc) + return 0; - memset(game_save, 0, sizeof(game_save)); /* clear so make the game fail, if we fail */ - sprintf(filename, "%s/%s/%d.gamesave", home_dir, config_gamesave_dir, gamesave_num); - fp = fopen(filename, "r"); - if (!fp) { -fail: - fprintf(stderr, "failed to load game from '%s'\n", filename); - goto copy; - } - got = fread(game_save, sizeof(game_save[0]), 2, fp); - fclose(fp); - if (got != 2) - goto fail; + /* allocate image */ + image = calloc(IMAGE_WIDTH * IMAGE_HEIGHT * ((double_size) ? 4 : 1), 3); + if (!image) { + fprintf(stderr, "Failed to allocate image buffer\n"); + goto done; } -copy: - /* copy track */ - memcpy(memory + data, game_save[track & 1], length /* sizeof(game_save[0])*/); -} + if ((SOUND_SAMPLERATE % IRQ_RATE)) { + fprintf(stderr, "Sample rate must be a multiple of IRQ rate, please fix!\n"); + goto done; + } + if ((1000 % IRQ_RATE)) { + fprintf(stderr, "1000 (Ticks per second) rate must be a multiple of IRQ rate, please fix!\n"); + goto done; + } -/* game writes track with saved game */ -void disk_write(int track, int __attribute__((unused)) side, uint32_t data, uint16_t length) -{ - /* skip sync info that is provided by game and only relevant for a real disk track */ - data += 0x200; - length -= 0x200; + /* calculate SDL chunk size for audio + * it must be a power of two, but not more than the chunk size for each IRQ! + */ + for (sdl_sound_chunk = 2; sdl_sound_chunk <= (SOUND_SAMPLERATE / IRQ_RATE); sdl_sound_chunk <<= 1) + ; + sdl_sound_chunk >>= 1; +// printf("samples per IRQ = %d, samples per SDL audio = %d\n", SOUND_SAMPLERATE / IRQ_RATE, sdl_sound_chunk); exit(0); - if (length != sizeof(game_save[0])) { - fprintf(stderr, "saving game state failed, because length of data does not match, please fix!\n"); - return; + /* allocate sound buffers */ + sound_buffer_size = SOUND_SAMPLERATE / IRQ_RATE * SOUND_CHUNKS; + sound_buffer = calloc(sound_buffer_size, sizeof(*sound_buffer)); + if (!sound_buffer) { + fprintf(stderr, "Failed to allocate image buffer\n"); + goto done; } - /* don't save if last track is the same, because disk is written on both sides with the same data */ - if (track == last_track) { - if (memcmp(memory + data, game_save[track & 1], length)) { - fprintf(stderr, "saving game data on other side of the disk is different, please fix!\n"); - } - return; + /* allocate memory */ + memory = calloc(MEMORY_SIZE, 1); + if (!memory) { + fprintf(stderr, "Failed to allocate cpu's memory\n"); + goto done; + } + chipreg = calloc(IOSIZE, 1); + if (!chipreg) { + fprintf(stderr, "Failed to allocate chip register\n"); + goto done; } - last_track = track; - /* save game data */ - memcpy(game_save[track & 1], memory + data, length); + /* init cpu code */ + execute_init(MEMORY_SIZE, memory, chipreg, io_read, io_write); - /* if done with saving */ - if ((track & 1)) { - char filename[256]; - int gamesave_num = (track - 2) >> 1; - int wrote; - FILE *fp; + /* init disk emulation */ + disk_init(disk_read, disk_write); - sprintf(filename, "%s/%s", home_dir, config_gamesave_dir); - mkdir(filename, 0777); - sprintf(filename + strlen(filename), "/%d.gamesave", gamesave_num); - fp = fopen(filename, "w"); - if (!fp) { -fail: - fprintf(stderr, "failed to save game to '%s'\n", filename); - return; - } - printf("Game state saved to '%s'\n", filename); - wrote = fwrite(game_save, sizeof(game_save[0]), 2, fp); - fclose(fp); - if (wrote != 2) - goto fail; - } + /* load binary */ + mercenary_load(); + + /* patch some stuff */ + mercenary_patch(); + + /* init SDL and OpenGL */ + rc = init_sdl(argv[0], SCREEN_WIDTH, SCREEN_HEIGHT, SOUND_SAMPLERATE, sdl_sound_chunk, keyboard_sdl, audio_sdl); + if (rc < 0) + goto done; + rc = init_opengl((double_size) ? IMAGE_WIDTH * 2 : IMAGE_WIDTH, (double_size) ? IMAGE_HEIGHT * 2 : IMAGE_HEIGHT); + if (rc < 0) + goto done; + resize_opengl(SCREEN_WIDTH, SCREEN_HEIGHT); + + /* init audio filter */ + sound_init_filter(SOUND_SAMPLERATE); + + /* start cpu */ + reset_cpu(); + + printf("**********************************\n"); + printf("* Welcome to Mercenary Reloaded! *\n"); + printf("**********************************\n\n"); + printf("Press CTRL + cursor keys to select inventory or pickup/drop item.\n"); + printf("Press CTRL + f to toggle full screen.\n"); + printf("Press CTRL + s to toggle rendering speed.\n"); + printf("Press CTRL + v to toggle video filter.\n"); + printf("Press CTRL + a to toggle audio filter.\n"); + printf("Press CTRL + c to exit game.\n\n"); + printf("Use '--help' as command line option for configuration settings.\n\n"); + + /* run game */ + main_loop(); + +done: + exit_opengl(); + exit_sdl(); + + if (chipreg) + free(chipreg); + if (memory) + free(memory); + if (sound_buffer) + free(sound_buffer); + if (image) + free(image); + + return 0; } + -- 2.13.6