From ce5ac2ef9a7c4476aaff9474c2a23df79a56f484 Mon Sep 17 00:00:00 2001 From: tixiv Date: Thu, 1 Jan 2009 17:06:38 +0000 Subject: [PATCH] adding menu and game support --- Makefile | 7 +- animations/snake.c | 119 -------------------- avr5.x | 231 +++++++++++++++++++++++++++++++++++++++ borg_hw/borg_hw_borg16.c | 4 +- borg_hw/config_borg16.in | 11 ++ config.h | 19 +--- defaults.mk | 2 +- depend.mk | 2 +- display_loop.c | 4 + games/Makefile | 12 ++ games/snake_game.c | 138 +++++++++++++++++++++++ joystick.h | 16 ++- menu/Makefile | 9 ++ menu/menu.c | 74 ++++++------- menu/menu.h | 12 +- simulator/i386pe.x | 5 +- simulator/joystick.c | 3 + simulator/joystick.h | 2 +- 18 files changed, 480 insertions(+), 190 deletions(-) create mode 100644 avr5.x create mode 100644 games/Makefile create mode 100644 games/snake_game.c create mode 100644 menu/Makefile diff --git a/Makefile b/Makefile index ac0a38a..1b51379 100644 --- a/Makefile +++ b/Makefile @@ -15,8 +15,8 @@ SRC_SIM = \ LAUNCH_BOOTLOADER = launch-bootloader -SERIAL = /dev/ttyUSB0 - +#SERIAL = /dev/ttyUSB0 +SERIAL = COM5 export TOPDIR ############################################################################## @@ -40,6 +40,7 @@ include defaults.mk @ echo "checking in which subdirs to build" @ $(RM) -f $@ @ echo "SUBDIRS += animations" >> $@ +# @ echo "SUBDIRS += animations games menu" >> $@ @ (for subdir in `grep -e "^#define .*_SUPPORT" autoconf.h \ | sed -e "s/^#define //" -e "s/_SUPPORT.*//" \ | tr "[A-Z]\\n" "[a-z] " `; do \ @@ -159,7 +160,7 @@ mrproper: $(RM) -f autoconf.h .config config.mk .menuconfig.log .config.old sflash: $(TARGET).hex - $(LAUNCH_BOOTLOADER) $(SERIAL) 115200 +# $(LAUNCH_BOOTLOADER) $(SERIAL) 115200 avrdude -p m32 -b 115200 -u -c avr109 -P $(SERIAL) -U f:w:$< -F echo X > $(SERIAL) diff --git a/animations/snake.c b/animations/snake.c index b1470a7..a43a21b 100644 --- a/animations/snake.c +++ b/animations/snake.c @@ -128,122 +128,3 @@ void snake(){ } } -void snake_game() { - pixel pixels[64] = {{4, 14},{4, 13}}; - pixel * head = &pixels[1]; - pixel * tail = &pixels[0]; - pixel old_head; - pixel apples[10]; - uint8_t joy, joy_old=0xff, joy_cmd=0xff; - - unsigned char x, y, dead = 0; - unsigned char apple_num = 0; - direction dir = up; - - unsigned char apple_found = 0; - unsigned char j; - - clear_screen(0); - - // zeichne Rahmen - for (x = 0; x < NUM_COLS; x++) { - for (y = 0; y < NUM_ROWS; y++) { - if (((x == 0) || (x == NUM_COLS-1)) || - ((y == 0) || (y == NUM_ROWS-1))) { - setpixel((pixel) {x, y}, 3); - } - } - } - - x = 0; - while (1) { - - x++; - old_head = *head; - ++head; - if (head == pixels + 64) - head = pixels; - - if (joy_cmd == right) { - dir = direction_r(dir); - joy_cmd = 0xff; - } else if (joy_cmd == left) { - dir = direction_r(dir); - dir = direction_r(dir); - dir = direction_r(dir); - joy_cmd = 0xff; - } - - // kopf einen weiter bewegen - *head = next_pixel(old_head, dir); - - apple_found = 0; - - // prŸfen ob man auf nen Apfel drauf ist - for (j = 0; j < apple_num; j++) { - if ( ( head->x == apples[j].x) && - (head->y == apples[j].y) ){ - apple_found = 1; - for(; j < apple_num - 1; j++) { - apples[j] = apples[j+1]; - } - apple_num--; - goto apple_se; - } - } - if (get_pixel(*head)) { - dead = 1; - } - apple_se: - - if (!dead) { - setpixel(*head, 3); - - // setze neue €pfel - if ( (apple_num < 9) && (random8() < 10) ) { - pixel new_apple = (pixel) {(random8() % (NUM_COLS-2))+1, - (random8() % (NUM_ROWS-2))+1}; - if (!get_pixel(new_apple)){ - apples[apple_num++] = new_apple; - } - } - // lšsche Ende - if (!apple_found && !dead) { - clearpixel(*tail); - if (++tail == pixels + 64) - tail = pixels; - } - } else { - while (tail != head) { - clearpixel(*tail); - if ((++tail) > pixels + 64) - tail = pixels; - wait (60); - } - break; - } - - for (j = 0; j < apple_num; j++) { - if (x % 2) { - setpixel(apples[j], 3); - } else { - clearpixel(apples[j]); - } - } - for(j=0;j<20;j++){ - if(JOYISLEFT){ - joy = left; - }else if(JOYISRIGHT){ - joy = right; - }else{ - joy = 0xff; - } - if(joy != joy_old){ - joy_cmd = joy; - } - joy_old = joy; - wait (5); - } - } -} - diff --git a/avr5.x b/avr5.x new file mode 100644 index 0000000..3e08033 --- /dev/null +++ b/avr5.x @@ -0,0 +1,231 @@ +/* Default linker script, for normal executables */ +OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr") +OUTPUT_ARCH(avr:5) +MEMORY +{ + text (rx) : ORIGIN = 0, LENGTH = 128K + data (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0 + eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K + fuse (rw!x) : ORIGIN = 0x820000, LENGTH = 1K + lock (rw!x) : ORIGIN = 0x830000, LENGTH = 1K + signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K +} +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.text : + { + *(.rel.text) + *(.rel.text.*) + *(.rel.gnu.linkonce.t*) + } + .rela.text : + { + *(.rela.text) + *(.rela.text.*) + *(.rela.gnu.linkonce.t*) + } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.rodata : + { + *(.rel.rodata) + *(.rel.rodata.*) + *(.rel.gnu.linkonce.r*) + } + .rela.rodata : + { + *(.rela.rodata) + *(.rela.rodata.*) + *(.rela.gnu.linkonce.r*) + } + .rel.data : + { + *(.rel.data) + *(.rel.data.*) + *(.rel.gnu.linkonce.d*) + } + .rela.data : + { + *(.rela.data) + *(.rela.data.*) + *(.rela.gnu.linkonce.d*) + } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + /* Internal text space or external memory. */ + .text : + { + *(.vectors) + KEEP(*(.vectors)) + /* For data that needs to reside in the lower 64k of progmem. */ + *(.progmem.gcc*) + *(.progmem*) + . = ALIGN(2); + __trampolines_start = . ; + /* The jump trampolines for the 16-bit limited relocs will reside here. */ + *(.trampolines) + *(.trampolines*) + __trampolines_end = . ; + /* For future tablejump instruction arrays for 3 byte pc devices. + We don't relax jump/call instructions within these sections. */ + *(.jumptables) + *(.jumptables*) + /* For code that needs to reside in the lower 128k progmem. */ + *(.lowtext) + *(.lowtext*) + __ctors_start = . ; + *(.ctors) + __ctors_end = . ; + __dtors_start = . ; + *(.dtors) + __dtors_end = . ; + KEEP(SORT(*)(.ctors)) + KEEP(SORT(*)(.dtors)) + /* From this point on, we don't bother about wether the insns are + below or above the 16 bits boundary. */ + *(.init0) /* Start here after reset. */ + KEEP (*(.init0)) + *(.init1) + KEEP (*(.init1)) + *(.init2) /* Clear __zero_reg__, set up stack pointer. */ + KEEP (*(.init2)) + *(.init3) + KEEP (*(.init3)) + *(.init4) /* Initialize data and BSS. */ + KEEP (*(.init4)) + *(.init5) + KEEP (*(.init5)) + *(.init6) /* C++ constructors. */ + KEEP (*(.init6)) + *(.init7) + KEEP (*(.init7)) + *(.init8) + KEEP (*(.init8)) + *(.init9) /* Call main(). */ + KEEP (*(.init9)) + *(.text) + . = ALIGN(2); + *(.text.*) + . = ALIGN(2); + *(.fini9) /* _exit() starts here. */ + KEEP (*(.fini9)) + *(.fini8) + KEEP (*(.fini8)) + *(.fini7) + KEEP (*(.fini7)) + *(.fini6) /* C++ destructors. */ + KEEP (*(.fini6)) + *(.fini5) + KEEP (*(.fini5)) + *(.fini4) + KEEP (*(.fini4)) + *(.fini3) + KEEP (*(.fini3)) + *(.fini2) + KEEP (*(.fini2)) + *(.fini1) + KEEP (*(.fini1)) + *(.fini0) /* Infinite loop after program termination. */ + KEEP (*(.fini0)) + _etext = . ; + } > text + .data : AT (ADDR (.text) + SIZEOF (.text)) + { + PROVIDE (__data_start = .) ; + *(.data) + *(.data*) + *(.rodata) /* We need to include .rodata here if gcc is used */ + *(.rodata*) /* with -fdata-sections. */ + *(.gnu.linkonce.d*) + __game_descriptors_start__ = . ; + *(.game_descriptors) + __game_descriptors_end__ = . ; + . = ALIGN(2); + _edata = . ; + PROVIDE (__data_end = .) ; + } > data + .bss SIZEOF(.data) + ADDR(.data) : + { + PROVIDE (__bss_start = .) ; + *(.bss) + *(.bss*) + *(COMMON) + PROVIDE (__bss_end = .) ; + } > data + __data_load_start = LOADADDR(.data); + __data_load_end = __data_load_start + SIZEOF(.data); + /* Global data not cleared after reset. */ + .noinit SIZEOF(.bss) + ADDR(.bss) : + { + PROVIDE (__noinit_start = .) ; + *(.noinit*) + PROVIDE (__noinit_end = .) ; + _end = . ; + PROVIDE (__heap_start = .) ; + } > data + .eeprom : + { + *(.eeprom*) + __eeprom_end = . ; + } > eeprom + .fuse : + { + KEEP(*(.fuse)) + KEEP(*(.lfuse)) + KEEP(*(.hfuse)) + KEEP(*(.efuse)) + } > fuse + .lock : + { + KEEP(*(.lock*)) + } > lock + .signature : + { + KEEP(*(.signature*)) + } > signature + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } +} diff --git a/borg_hw/borg_hw_borg16.c b/borg_hw/borg_hw_borg16.c index e3b67af..639a788 100644 --- a/borg_hw/borg_hw_borg16.c +++ b/borg_hw/borg_hw_borg16.c @@ -51,7 +51,7 @@ inline void nextrow(uint8_t row){ if (row == 0){ //Zeile 0: Das erste Schieberegister initialisieren -#ifndef INVERSE_ROWS +#ifndef INVERT_ROWS ROWPORT&= ~(1<> 4) | (tmp << 4); tmp = ((tmp & 0xcc) >> 2) | ((tmp & 0x33)<< 2); //0xcc = 11001100, 0x33 = 00110011 tmp = ((tmp & 0xaa) >> 1) | ((tmp & 0x55)<< 1); //0xaa = 10101010, 0x55 = 1010101 diff --git a/borg_hw/config_borg16.in b/borg_hw/config_borg16.in index 5068fd4..5ae4ee0 100644 --- a/borg_hw/config_borg16.in +++ b/borg_hw/config_borg16.in @@ -74,4 +74,15 @@ choice 'DATA Pin' \ Pin7 7" \ 'Pin7' PIN_DATA +comment "fixing hardwareproblems in software" + + +bool "reverse cols" REVERSE_COLS n +bool "invert rows " INVERT_ROWS n + +comment "for borg jacket" + +bool "interlaced rows" INTERLACED_ROWS n +bool "interlaced cols" INTERLACED_COLS n + endmenu diff --git a/config.h b/config.h index f2253fc..7337829 100644 --- a/config.h +++ b/config.h @@ -12,13 +12,8 @@ #define SNAKE_DELAY 100 -//#define SCROLLTEXT_STRING_SIZE 128 -//#define SCROLLTEXT_FONT font_arial8 -//#define SCROLLTEXT_DEFAULT "x == apples[j].x) && + (head->y == apples[j].y) ){ + apple_found = 1; + for(; j < apple_num - 1; j++) { + apples[j] = apples[j+1]; + } + apple_num--; + goto apple_se; + } + } + if (get_pixel(*head)) { + dead = 1; + } + apple_se: + + if (!dead) { + setpixel(*head, 3); + + // setze neue ?pfel + if ( (apple_num < 9) && (random8() < 10) ) { + pixel new_apple = (pixel) {(random8() % (NUM_COLS-2))+1, + (random8() % (NUM_ROWS-2))+1}; + if (!get_pixel(new_apple)){ + apples[apple_num++] = new_apple; + } + } + // l?sche Ende + if (!apple_found && !dead) { + clearpixel(*tail); + if (++tail == pixels + 64) + tail = pixels; + } + } else { + while (tail != head) { + clearpixel(*tail); + if ((++tail) > pixels + 64) + tail = pixels; + wait (60); + } + break; + } + + for (j = 0; j < apple_num; j++) { + if (x % 2) { + setpixel(apples[j], 3); + } else { + clearpixel(apples[j]); + } + } + for(j=0;j<20;j++){ + if(JOYISLEFT){ + joy = left; + }else if(JOYISRIGHT){ + joy = right; + }else{ + joy = 0xff; + } + if(joy != joy_old){ + joy_cmd = joy; + } + joy_old = joy; + wait (5); + } + } +} diff --git a/joystick.h b/joystick.h index 2f1a11a..8828790 100644 --- a/joystick.h +++ b/joystick.h @@ -1,9 +1,11 @@ #ifndef JOYSTICK_H #define JOYSTICK_H -unsigned char waitForFire; +extern unsigned char waitForFire; void joy_init(); +#ifdef AVR + #define BITFIRE PD3 #define BITRIGHT PB3 #define BITLEFT PB2 @@ -16,4 +18,16 @@ void joy_init(); #define JOYISDOWN (!(PINB & (1< // architecture dependent stuff -#ifdef __AVR__ -#include -#define WAIT(ms) wait(ms) -#else -#define PROGMEM -#define WAIT(ms) myWait(ms) -#endif +#include "../compat/pgmspace.h" #include "menu.h" -#include "config.h" -#include "util.h" -#include "pixel.h" -#include "joystick.h" -#include "snake.h" -#include "tetris/logic.h" -#include "invaders2.h" +#include "../config.h" +#include "../util.h" +#include "../pixel.h" +#include "../joystick.h" + + +extern game_descriptor_t _game_descriptors_start__[]; +extern game_descriptor_t _game_descriptors_end__[]; // defines +#define MENU_ITEM_MAX (((int)_game_descriptors_end__ - (int)_game_descriptors_start__)/sizeof(game_descriptor_t)) + #define MENU_WIDTH_ICON 8 #define MENU_HEIGHT_ICON 8 #define MENU_WIDTH_DELIMITER 2 @@ -48,11 +45,11 @@ void menu() // wait as long the fire button is pressed to prevent unwanted selections while (JOYISFIRE) { - WAIT(MENU_POLL_INTERVAL); + wait(MENU_POLL_INTERVAL); } // set initial menu item - static menu_item_t miSelection = MENU_ITEM_TETRIS; + static uint8_t miSelection = 0; // scroll in currently selected menu item menu_animate(MENU_PREVITEM(miSelection), MENU_DIRECTION_LEFT); @@ -66,27 +63,17 @@ void menu() // prevent unwanted selections while (JOYISFIRE) { - WAIT(MENU_POLL_INTERVAL); + wait(MENU_POLL_INTERVAL); } // work against the chatter effects of dump joysticks - WAIT(MENU_WAIT_CHATTER); + wait(MENU_WAIT_CHATTER); // call corresponding function - switch (miSelection) - { - case MENU_ITEM_SNAKE: - snake_game(); - break; - case MENU_ITEM_SPACEINVADERS: - borg_invaders(); - break; - case MENU_ITEM_TETRIS: - tetris(); - break; - default: - break; - } + + _game_descriptors_start__[miSelection].run(); + break; + } // change selected item and do some scrolling else if (JOYISRIGHT) @@ -109,7 +96,7 @@ void menu() // return if timeout is reached else { - WAIT(MENU_POLL_INTERVAL); + wait(MENU_POLL_INTERVAL); if (--nMenuIterations == 0) break; } @@ -119,23 +106,24 @@ void menu() return; } -uint8_t menu_getIconPixel(menu_item_t item, int8_t x, int8_t y) + +uint8_t menu_getIconPixel(uint8_t item, int8_t x, int8_t y) { +/* + // MSB is leftmost pixel static uint8_t nIcon[][8] PROGMEM = {{0xff, 0x81, 0xbd, 0xa5, 0xa5, 0xad, 0xa1, 0xbf}, // Snake icon {0x66, 0x18, 0x3c, 0x5a, 0xff, 0xbd, 0xa5, 0x18}, // Invaders icon {0x0f, 0x0f, 0xc3, 0xdb, 0xdb, 0xc3, 0xf0, 0xf0}}; // Tetris icon +*/ + // is x within the icon or do we have reached the delimiter? if (x < MENU_WIDTH_ICON) { // return pixel -#ifdef __AVR__ - return (0x80 >> x) & pgm_read_word(&nIcon[item][y]); -#else - return (0x80 >> x) & nIcon[item][y]; -#endif + return (0x80 >> x) & pgm_read_word(&_game_descriptors_start__[item].icon[y]); } else { @@ -144,7 +132,7 @@ uint8_t menu_getIconPixel(menu_item_t item, int8_t x, int8_t y) } } -void menu_animate(menu_item_t miInitial, menu_direction_t direction) +void menu_animate(uint8_t miInitial, menu_direction_t direction) { int16_t nWait= MENU_WAIT_INITIAL; @@ -152,7 +140,7 @@ void menu_animate(menu_item_t miInitial, menu_direction_t direction) int8_t nWidthSide = (NUM_COLS - MENU_WIDTH_ICON) / 2; // determine the icon at the leftmost position - menu_item_t mi = miInitial + MENU_ITEM_MAX; + uint8_t mi = miInitial + MENU_ITEM_MAX; int8_t nBack = nWidthSide / (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER); if ((nWidthSide % (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER)) != 0) { @@ -203,7 +191,7 @@ void menu_animate(menu_item_t miInitial, menu_direction_t direction) int8_t y; for (y = 0; y < MENU_HEIGHT_ICON; ++y) { - menu_item_t miCurrent = mi; + uint8_t miCurrent = mi; int8_t nIconOffset = nInitialSideOffset; int8_t x; for (x = 0; x < NUM_COLS; ++x) @@ -231,7 +219,7 @@ void menu_animate(menu_item_t miInitial, menu_direction_t direction) } // wait between the frames so that the animation can be seen - WAIT(nWait); + wait(nWait); // animation speed can be throtteled nWait += MENU_WAIT_INCREMENT; } diff --git a/menu/menu.h b/menu/menu.h index d23ca35..b43ca94 100644 --- a/menu/menu.h +++ b/menu/menu.h @@ -8,6 +8,7 @@ #include +/* typedef enum menu_item_t { MENU_ITEM_SNAKE, @@ -16,6 +17,7 @@ typedef enum menu_item_t MENU_ITEM_MAX // fake entry to mark the end } menu_item_t; +*/ typedef enum menu_direction_t { @@ -25,9 +27,15 @@ typedef enum menu_direction_t } menu_direction_t; +typedef struct{ + void(*run)(void); + uint8_t * icon; +}game_descriptor_t; + + void menu(); -void menu_animate(menu_item_t currentItem, menu_direction_t direction); -uint8_t menu_getIconPixel(menu_item_t item, int8_t x, int8_t y); +void menu_animate(uint8_t currentItem, menu_direction_t direction); +uint8_t menu_getIconPixel(uint8_t item, int8_t x, int8_t y); void menu_setpixel(int8_t x, int8_t y, int8_t isSet); #endif /*MENU_H_*/ diff --git a/simulator/i386pe.x b/simulator/i386pe.x index cfbfcbf..6f250eb 100644 --- a/simulator/i386pe.x +++ b/simulator/i386pe.x @@ -38,7 +38,10 @@ SECTIONS *(.data2) *(SORT(.data$*)) *(.jcr) - __data_end__ = . ; + __game_descriptors_start__ = . ; + *(.game_descriptors) + __game_descriptors_end__ = . ; + __data_end__ = . ; *(.data_cygwin_nocopy) } .rdata BLOCK(__section_alignment__) : diff --git a/simulator/joystick.c b/simulator/joystick.c index 86d8d9c..8826f64 100644 --- a/simulator/joystick.c +++ b/simulator/joystick.c @@ -1,5 +1,8 @@ #include "joystick.h" +unsigned char fakeport; + + // fake function since our keybord doesn't need any initialisation void joy_init() { diff --git a/simulator/joystick.h b/simulator/joystick.h index 707ba4b..6bbb525 100644 --- a/simulator/joystick.h +++ b/simulator/joystick.h @@ -1,7 +1,7 @@ #ifndef JOYSTICK_H_ #define JOYSTICK_H_ -unsigned char fakeport; +extern unsigned char fakeport; #define JOYISFIRE (0x01 & fakeport) #define JOYISLEFT (0x02 & fakeport)