Browse Source

renamed project because it is to cool for stupid name

feature/2015
tixiv 16 years ago
commit
fe14b29d15
  1. 173
      Makefile
  2. 32
      Makefile-old
  3. 2
      README
  4. 5
      README.txt
  5. 21
      animations/Makefile
  6. 312
      animations/gameoflife.c
  7. 14
      animations/gameoflife.h
  8. 98
      animations/matrix.c
  9. 14
      animations/matrix.h
  10. 227
      animations/programm.c
  11. 22
      animations/programm.h
  12. 249
      animations/snake.c
  13. 8
      animations/snake.h
  14. 31
      borg_hw/Makefile
  15. 15
      borg_hw/borg_hw.h
  16. 168
      borg_hw/borg_hw_andreborg.c
  17. 207
      borg_hw/borg_hw_borg16.c
  18. 127
      borg_hw/borg_hw_borg_ls.c
  19. 165
      borg_hw/borg_hw_borg_mini.c
  20. 50
      borg_hw/config.in
  21. 71
      borg_hw/config_andreborg.in
  22. 77
      borg_hw/config_borg16.in
  23. 55
      borg_hw/config_borg_ls.in
  24. 50
      borg_hw/config_borg_mini.in
  25. 134
      can/borg_can.c
  26. 11
      can/borg_can.h
  27. 496
      can/can.c
  28. 139
      can/can.h
  29. 55
      can/spi.c
  30. 28
      can/spi.h
  31. 57
      config.h
  32. 58
      config.in
  33. 70
      defaults.mk
  34. 32
      depend.mk
  35. 14
      eeprom_reserve.c
  36. 115
      games/invader_draw.c
  37. 153
      games/invader_init.c
  38. 304
      games/invader_proc.c
  39. 134
      games/invaders2.c
  40. 182
      games/invaders2.h
  41. 19
      games/tetris/COPYING
  42. 19
      games/tetris/LICENSE
  43. 25
      games/tetris/Makefile
  44. 400
      games/tetris/input.c
  45. 129
      games/tetris/input.h
  46. 467
      games/tetris/logic.c
  47. 143
      games/tetris/logic.h
  48. 119
      games/tetris/piece.c
  49. 97
      games/tetris/piece.h
  50. 595
      games/tetris/playfield.c
  51. 213
      games/tetris/playfield.h
  52. 421
      games/tetris/view.c
  53. 95
      games/tetris/view.h
  54. 13
      joystick.c
  55. 21
      joystick.h
  56. 149
      main.c
  57. 2
      makros.h
  58. 76
      mcuf/mcuf.c
  59. 3
      mcuf/mcuf.h
  60. 272
      menu/menu.c
  61. 34
      menu/menu.h
  62. 127
      pixel.c
  63. 41
      pixel.h
  64. 68
      random/memxor.S
  65. 7
      random/memxor.h
  66. 76
      random/noekeon.h
  67. 641
      random/noekeon_asm.S
  68. 111
      random/persistentCounter.c
  69. 23
      random/persistentCounter.h
  70. 49
      random/prng.c
  71. 22
      random/prng.h
  72. 21
      rules.mk
  73. 1697
      scripts/Menuconfig
  74. 4
      scripts/lxdialog/BIG.FAT.WARNING
  75. 46
      scripts/lxdialog/Makefile
  76. 369
      scripts/lxdialog/checklist.c
  77. 161
      scripts/lxdialog/colors.h
  78. 184
      scripts/lxdialog/dialog.h
  79. 240
      scripts/lxdialog/inputbox.c
  80. 226
      scripts/lxdialog/lxdialog.c
  81. 443
      scripts/lxdialog/menubox.c
  82. 85
      scripts/lxdialog/msgbox.c
  83. 556
      scripts/lxdialog/textbox.c
  84. 359
      scripts/lxdialog/util.c
  85. 118
      scripts/lxdialog/yesno.c
  86. 13
      scripts/size
  87. 10
      scrolltext/Makefile
  88. 20
      scrolltext/config.in
  89. 21
      scrolltext/font.h
  90. 544
      scrolltext/font_arial8.c
  91. 8
      scrolltext/font_arial8.h
  92. 439
      scrolltext/font_small6.c
  93. 7
      scrolltext/font_small6.h
  94. 503
      scrolltext/font_uni53.c
  95. 8
      scrolltext/font_uni53.h
  96. 6
      scrolltext/scrolltext.h
  97. 578
      scrolltext/scrolltext3.c
  98. 111
      simulator/Makefile
  99. 102
      simulator/Makefile.osx
  100. 309
      simulator/main.c

173
Makefile

@ -0,0 +1,173 @@
TARGET := image
TOPDIR = .
SRC = \
main.c \
eeprom_reserve.c \
pixel.c \
util.c \
LAUNCH_BOOTLOADER = launch-bootloader
SERIAL = /dev/ttyUSB0
export TOPDIR
##############################################################################
all: compile-$(TARGET)
@echo "==============================="
@echo "$(TARGET) compiled for: $(MCU)"
@echo "size is: "
@${TOPDIR}/scripts/size $(TARGET)
@echo "==============================="
##############################################################################
# generic fluff
include defaults.mk
#include $(TOPDIR)/rules.mk
##############################################################################
# generate SUBDIRS variable
#
.subdirs: autoconf.h
$(RM) -f $@
echo "SUBDIRS += borg_hw" >> $@
echo "SUBDIRS += animations" >> $@
(for subdir in `grep -e "^#define .*_SUPPORT" autoconf.h \
| sed -e "s/^#define //" -e "s/_SUPPORT.*//" \
| tr "[A-Z]\\n" "[a-z] " `; do \
test -d $$subdir && echo "SUBDIRS += $$subdir" ; \
done) | sort -u >> $@
ifneq ($(no_deps),t)
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),mrproper)
ifneq ($(MAKECMDGOALS),menuconfig)
include $(TOPDIR)/.subdirs
include $(TOPDIR)/.config
endif # MAKECMDGOALS!=menuconfig
endif # MAKECMDGOALS!=mrproper
endif # MAKECMDGOALS!=clean
endif # no_deps!=t
##############################################################################
.PHONY: compile-subdirs
compile-subdirs:
for dir in $(SUBDIRS); do make -C $$dir lib$$dir.a || exit 5; done
.PHONY: compile-$(TARGET)
compile-$(TARGET): compile-subdirs $(TARGET).hex $(TARGET).bin $(TARGET).lst
OBJECTS += $(patsubst %.c,%.o,${SRC})
LINKLIBS = $(foreach subdir,$(SUBDIRS),$(subdir)/lib$(subdir).a)
# FIXME how can we omit specifying every file to be linked twice?
# This is currently necessary because of interdependencies between
# the libraries, which aren't denoted in these however.
$(TARGET): $(OBJECTS) $(LINKLIBS)
$(CC) $(LDFLAGS) -o $@ $(OBJECTS) \
$(foreach subdir,$(SUBDIRS),-L$(subdir) -l$(subdir)) \
$(foreach subdir,$(SUBDIRS),-l$(subdir)) \
$(foreach subdir,$(SUBDIRS),-l$(subdir))
##############################################################################
%.hex: %
$(OBJCOPY) -O ihex -R .eeprom $< $@
ifeq ($(HTTPD_INLINE_FILES_SUPPORT),y)
INLINE_FILES := $(wildcard httpd/embed/*)
else
INLINE_FILES :=
endif
%.bin: % $(INLINE_FILES)
$(OBJCOPY) -O binary -R .eeprom $< $@
ifeq ($(HTTPD_INLINE_FILES_SUPPORT),y)
$(MAKE) -C httpd httpd-concat
httpd/do-embed $(INLINE_FILES)
$(OBJCOPY) -O ihex -I binary $(TARGET).bin $(TARGET).hex
endif
%.eep.hex: %
$(OBJCOPY) --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex -j .eeprom $< $@
%.lst: %
$(OBJDUMP) -h -S $< > $@
%-size: %.hex
$(SIZE) $<
##############################################################################
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
else if [ -x /bin/bash ]; then echo /bin/bash; \
else echo sh; fi ; fi)
menuconfig:
$(MAKE) -C scripts/lxdialog all
$(CONFIG_SHELL) scripts/Menuconfig config.in
test -e .config
@$(MAKE) no_deps=t what-now-msg
what-now-msg:
@echo ""
@echo "Next, you can: "
@echo " * 'make' to compile your borgware"
@for subdir in $(SUBDIRS); do \
test -e "$$subdir/configure" -a -e "$$subdir/cfgpp" \
&& echo " * 'make $$subdir/menuconfig' to" \
"further configure $$subdir"; done || true
@echo ""
.PHONY: what-now-msg
%/menuconfig:
$(SH) "$(@D)/configure"
@$(MAKE) what-now-msg
##############################################################################
clean:
$(MAKE) -f rules.mk no_deps=t clean-common
$(RM) $(TARGET) $(TARGET).bin $(TARGET).hex .subdirs
for subdir in `find . -type d`; do \
test "x$$subdir" != "x." \
&& test -e $$subdir/Makefile \
&& make no_deps=t -C $$subdir clean; done
mrproper:
$(MAKE) clean
$(RM) -f autoconf.h .config config.mk .menuconfig.log .config.old
sflash: $(TARGET).hex
$(LAUNCH_BOOTLOADER) $(SERIAL) 115200
avrdude -p m32 -b 115200 -u -c avr109 -P $(SERIAL) -U f:w:$< -F
echo X > $(SERIAL)
.PHONY: clean mrproper sflash
##############################################################################
# configure ethersex
#
show-config: autoconf.h
@echo
@echo "These modules are currently enabled: "
@echo "======================================"
@grep -e "^#define .*_SUPPORT" autoconf.h | sed -e "s/^#define / * /" -e "s/_SUPPORT.*//"
.PHONY: show-config
autoconf.h .config:
@echo make\'s goal: $(MAKECMDGOALS)
ifneq ($(MAKECMDGOALS),menuconfig)
# make sure menuconfig isn't called twice, on `make menuconfig'
test -s autoconf.h -a -s .config || $(MAKE) no_deps=t menuconfig
# test the target file, test fails if it doesn't exist
# and will keep make from looping menuconfig.
test -s autoconf.h -a -s .config
endif
include depend.mk

32
Makefile-old

@ -0,0 +1,32 @@
OBJ = borg_hw.o main.o util.o pixel.o programm.o borg_can.o can.o \
spi.o scrolltext3.o font_arial8.o joystick.o snake.o \
eeprom_reserve.o persistentCounter.o prng.o matrix.o \
invader_draw.o invader_init.o invader_proc.o invaders2.o \
tetris/tetris.o menu.o gameoflife.o memxor.o noekeon_asm.o \
mcuf.o uart.o
CANADDR = 0x43
SERIAL = /dev/ttyUSB0
include ../../make/avr.mk
.PHONY: tetris/tetris.o
tetris/tetris.o:
$(MAKE) "MCU_CC=$(MCU_CC)" "MCU_LD=$(MCU_LD)" "LDFLAGS=$(LDFLAGS)" \
"CFLAGS=$(CFLAGS) -DNDEBUG -pedantic -std=c99" --directory=tetris
LAUNCH_BOOTLOADER = launch-bootloader
sflash: $(OUT).hex
$(LAUNCH_BOOTLOADER) $(SERIAL) 115200
avrdude -p m32 -b 115200 -u -c avr109 -P $(SERIAL) -U f:w:$(OUT).hex -F
echo X > $(SERIAL)
urflash: image_with_bootloader.hex
avrdude -p m32 -c bsd -P /dev/parport0 -U hfuse:w:0xdc:m
avrdude -p m32 -c bsd -P /dev/parport0 -U lfuse:w:0xef:m
avrdude -p m32 -c bsd -P /dev/parport0 -U f:w:image_with_bootloader.hex
avrdude -p m32 -c bsd -P /dev/parport0 -U e:w:image_eeprom.hex
avrdude -p m32 -c bsd -P /dev/parport0 -U lock:w:0x2f:m

2
README

@ -0,0 +1,2 @@
Source für Borg16 Controller

5
README.txt

@ -0,0 +1,5 @@
Hier liegt der Versuch, eine universelle Codebasis für 2d-borgs zu bauen, die
durch 'make menuconfig' konfigurierbar ist. Das ganze ist grade nochnicht
besonders weit, und funktioniert noch garnicht. Work is in progress...

21
animations/Makefile

@ -0,0 +1,21 @@
TARGET = libanimations.a
TOPDIR = ..
include $(TOPDIR)/defaults.mk
SRC = programm.c
ifeq ($(ANIMATION_SNAKE),y)
SRC += snake.c
endif
ifeq ($(ANIMATION_MATRIX),y)
SRC += matrix.c
endif
ifeq ($(ANIMATION_GAMEOFLIFE),y)
SRC += gameoflife.c
endif
include $(TOPDIR)/rules.mk

312
animations/gameoflife.c

@ -0,0 +1,312 @@
/**
* Conways Game of life
* Author: Daniel Otte
* License: GPLv3
*
*
*/
#include <stdint.h>
#include <util/delay.h>
#include <avr/sfr_defs.h> /* for debugging */
#include "../config.h"
#include "../random/prng.h"
#include "../pixel.h"
#include "../util.h"
/******************************************************************************/
#undef DEBUG
#define XSIZE NUM_COLS
#define YSIZE NUM_ROWS
/*
* last line is for debug information
*/
#ifdef DEBUG
#undef YSIZE
#define YSIZE (NUM_ROWS-1)
#define DEBUG_ROW (NUM_ROWS-1)
#define DEBUG_BIT(pos, val) \
setpixel((pixel){(pos)%XSIZE,DEBUG_ROW+(pos)/XSIZE},(val)?3:0)
#define DEBUG_BYTE(s,v) \
DEBUG_BIT((s)*8+0, (v)&(1<<0)); \
DEBUG_BIT((s)*8+1, (v)&(1<<1)); \
DEBUG_BIT((s)*8+2, (v)&(1<<2)); \
DEBUG_BIT((s)*8+3, (v)&(1<<3)); \
DEBUG_BIT((s)*8+4, (v)&(1<<4)); \
DEBUG_BIT((s)*8+5, (v)&(1<<5)); \
DEBUG_BIT((s)*8+6, (v)&(1<<6)); \
DEBUG_BIT((s)*8+7, (v)&(1<<7))
#else
#define DEBUG_BIT(s,v)
#define DEBUG_BYTE(s,v)
#endif
//#define GLIDER_TEST
#define BITSTUFFED
#define LOOP_DETECT_BUFFER_SIZE 8
#ifndef GOL_DELAY
#define GOL_DELAY 1 /* milliseconds */
#endif
#ifndef GOL_CYCLES
#define GOL_CYCLES (2*60*3)
#endif
/******************************************************************************/
/******************************************************************************/
typedef enum{dead=0, alive=1} cell_t;
#ifndef BITSTUFFED
#define FIELD_XSIZE XSIZE
#define FIELD_YSIZE YSIZE
typedef cell_t field_t[FIELD_XSIZE][FIELD_YSIZE];
/******************************************************************************/
void setcell(field_t pf, int x, int y, cell_t value){
pf[(x+FIELD_XSIZE)%FIELD_XSIZE][(y+FIELD_YSIZE)%FIELD_YSIZE] = value;
}
/******************************************************************************/
cell_t getcell(field_t pf, int x, int y){
return pf[(x+FIELD_XSIZE)%FIELD_XSIZE][(y+FIELD_YSIZE)%FIELD_YSIZE];
}
#else /* BITSTUFFED */
#define FIELD_XSIZE ((XSIZE+7)/8)
#define FIELD_YSIZE YSIZE
typedef uint8_t field_t[FIELD_XSIZE][FIELD_YSIZE];
/******************************************************************************/
void setcell(field_t pf, int x, int y, cell_t value){
uint8_t t;
x = (x+XSIZE) % XSIZE;
y = (y+YSIZE) % YSIZE;
t = pf[x/8][y];
if(value==alive){
t |= 1<<(x&7);
} else {
t &= ~(1<<(x&7));
}
pf[x/8][y] = t;
}
/******************************************************************************/
cell_t getcell(field_t pf, int x, int y){
x = (x+XSIZE) % XSIZE;
y = (y+YSIZE) % YSIZE;
return ((pf[x/8][y])&(1<<(x&7)))?alive:dead;
}
#endif
/******************************************************************************/
uint8_t countsurroundingalive(field_t pf, int x, int y){
uint8_t ret=0;
ret += (getcell(pf, x-1, y-1)==alive)?1:0;
ret += (getcell(pf, x , y-1)==alive)?1:0;
ret += (getcell(pf, x+1, y-1)==alive)?1:0;
ret += (getcell(pf, x-1, y )==alive)?1:0;
ret += (getcell(pf, x+1, y )==alive)?1:0;
ret += (getcell(pf, x-1, y+1)==alive)?1:0;
ret += (getcell(pf, x , y+1)==alive)?1:0;
ret += (getcell(pf, x+1, y+1)==alive)?1:0;
return ret;
}
/******************************************************************************/
void nextiteration(field_t dest, field_t src){
int x,y;
uint8_t tc;
for(y=0; y<YSIZE; ++y){
for(x=0; x<XSIZE; ++x){
tc=countsurroundingalive(src,x,y);
switch(tc){
// case 0:
// case 1:
// /* dead */
// setcell(dest, x,y, dead);
case 2:
/* keep */
setcell(dest, x,y, getcell(src,x,y));
break;
case 3:
/* alive */
setcell(dest, x,y, alive);
break;
default:
/* dead */
setcell(dest, x,y, dead);
break;
}
}
}
}
/******************************************************************************/
void printpf(field_t pf){
int x,y;
for(y=0; y<YSIZE; ++y){
for(x=0; x<XSIZE; ++x){
setpixel((pixel){x,y},(getcell(pf,x,y)==alive)?3:0);
}
}
}
/******************************************************************************/
void pfcopy(field_t dest, field_t src){
int x,y;
for(y=0; y<YSIZE; ++y){
for(x=0; x<XSIZE; ++x){
setcell(dest,x,y,getcell(src,x,y));
}
}
}
/******************************************************************************/
#ifndef BITSTUFFED
uint8_t pfcmp(field_t dest, field_t src){
int x,y;
for(y=0; y<YSIZE; ++y){
for(x=0; x<XSIZE; ++x){
if (getcell(src,x,y) != getcell(dest,x,y))
return 1;
}
}
return 0;
}
/******************************************************************************/
uint8 pfempty(field_t src){ int x,y;
for(y=0; y<YSIZE; ++y){
for(x=0; x<XSIZE; ++x){
if (getcell(src,x,y)==alive)
return 0;
}
}
return 1;
}
#else
uint8_t pfcmp(field_t dest, field_t src){
int x,y;
for(y=0; y<FIELD_YSIZE; ++y){
for(x=0; x<FIELD_XSIZE; ++x){
if (src[x][y] != dest[x][y])
return 1;
}
}
return 0;
}
/******************************************************************************/
uint8_t pfempty(field_t src){
int x,y;
for(y=0; y<FIELD_YSIZE; ++y){
for(x=0; x<FIELD_XSIZE; ++x){
if (src[x][y]!=0)
return 0;
}
}
return 1;
}
#endif
/******************************************************************************/
void insertglider(field_t pf){
/*
* #
* #
* ###
*/
setcell(pf, 1, 0, alive);
setcell(pf, 2, 1, alive);
setcell(pf, 0, 2, alive); setcell(pf, 1, 2, alive); setcell(pf, 2, 2, alive);
}
/******************************************************************************/
int gameoflife(){
DEBUG_BYTE(0,0); // set debug bytes to zero
DEBUG_BYTE(1,0);
field_t pf1,pf2;
field_t ldbuf[LOOP_DETECT_BUFFER_SIZE]={{{0}}}; // loop detect buffer
uint8_t ldbuf_idx=0;
int x,y;
uint16_t cycle;
//start:
/* initalise the field with random */
for(y=0;y<YSIZE;++y){
for(x=0;x<XSIZE; ++x){
setcell(pf1,x,y,(random8()&1)?alive:dead);
}
}
#ifdef GLIDER_TEST
/* initialise with glider */
for(y=0;y<YSIZE;++y){
for(x=0;x<XSIZE; ++x){
setcell(pf1,x,y,dead);
}
}
insertglider(pf1);
#endif
/* the main part */
printpf(pf1);
for(cycle=1; cycle<GOL_CYCLES; ++cycle){
DEBUG_BYTE(0,(uint8_t)(GOL_CYCLES-cycle)&0xff);
DEBUG_BYTE(1, SREG);
wait(GOL_DELAY);
pfcopy(pf2,pf1);
nextiteration(pf1,pf2);
printpf(pf1);
/* loop detection */
if(!pfcmp(pf1, pf2)){
insertglider(pf1);
cycle=1;
}
if(pfempty(pf1)){
/* kill game */
return 0;
}
/* */
uint8_t i;
for(i=0; i<LOOP_DETECT_BUFFER_SIZE; ++i){
if(!pfcmp(pf1, ldbuf[i])){
insertglider(pf1);
cycle=1;
}
}
pfcopy(ldbuf[ldbuf_idx], pf1);
ldbuf_idx = (ldbuf_idx+1)%LOOP_DETECT_BUFFER_SIZE;
}
return 0;
}

14
animations/gameoflife.h

@ -0,0 +1,14 @@
/**
*
*
*
*
*
*/
#ifndef GAMEOFLIFE_H_
#define GAMEOFLIFE_H_
void gameoflife();
#endif /* GAMEOFLIFE_H_ */

98
animations/matrix.c

@ -0,0 +1,98 @@
#include "../config.h"
#include <stdint.h>
#include "../random/prng.h"
#include "../pixel.h"
#include "../util.h"
typedef struct{
pixel start;
unsigned char len;
unsigned char decay;
unsigned char index;
unsigned char speed;
} streamer;
typedef uint8_t pixel_matrix_t[NUM_COLS][NUM_ROWS/4];
inline static uint8_t get_bright(pixel_matrix_t *matrix, uint8_t x, uint8_t y){
uint8_t ret;
ret = (*matrix)[x][y/4];
return 0x3&(ret>>(2*(y%4)));
}
inline static void set_bright(pixel_matrix_t *matrix, uint8_t x, uint8_t y, uint8_t value){
uint8_t t;
t = (*matrix)[x][y/4];
t &= ~(0x3<<(2*(y%4)));
t |= value<<(2*(y%4));
(*matrix)[x][y/4] = t;
}
void matrix() {
unsigned int counter = 500; /* run 500 cycles */
streamer streamers[STREAMER_NUM];
pixel_matrix_t matrix_bright;
unsigned char x, y;
unsigned char index = 0;
unsigned char draw;
unsigned char streamer_num = 0;
while(counter--){
unsigned char i, j;
/* initialise matrix-buffer */
for(x=0;x<NUM_COLS;x++)
for(y=0;y<NUM_ROWS/4;y++)
matrix_bright[x][y]=0;
for(i=0;i<streamer_num;i++){
streamer str = streamers[i];
unsigned char bright = 0xFF; draw = 0;
for(j=(str.len/8);j!=0xFF;j--){ /* Draw streamer */
if(j+str.start.y<NUM_ROWS){
if(bright>>6) /* bright>>6 */
draw = 1;
if(bright > (get_bright(&matrix_bright, str.start.x, str.start.y+j)<<6) ){
set_bright(&matrix_bright, str.start.x, str.start.y+j, bright>>6);
}
}
bright-=((bright>>5)*str.decay);
}
str.len+=str.speed/2;
streamers[i] = str;
if(!draw){
for(j=i;j<streamer_num-1;j++){
streamers[j] = streamers[j+1];
}
streamer_num--;
i--;
}
}
for(y=0;y<NUM_ROWS;y++)
for(x=0;x<NUM_COLS;x++){
setpixel((pixel){x,y}, get_bright(&matrix_bright,x,y));
}
unsigned char nsc;
for(nsc=0;nsc<6;nsc++){
if(streamer_num<STREAMER_NUM){
unsigned char sy = random8()%(2*NUM_ROWS);
if (sy>NUM_ROWS-1) sy=0;
streamers[streamer_num] = (streamer){{random8()%NUM_COLS, sy}, 0, (random8()%8)+12, index++,(random8()%16)+3};
streamer_num++;
}
}
wait(60);
}
}

14
animations/matrix.h

@ -0,0 +1,14 @@
/**
*
*
*
*
*
*/
#ifndef MATRIX_H_
#define MATRIX_H_
void matrix();
#endif /* MATRIX_H_ */

227
animations/programm.c

@ -0,0 +1,227 @@
#include "../config.h"
#include "../random/prng.h"
#include "../pixel.h"
#include "../util.h"
#ifdef AVR
#include <avr/io.h>
#endif
#define RANDOM8() (random8())
#ifdef ANIMATION_TESTS
void test1(){
unsigned char x,y;
for (y=0;y<NUM_ROWS;y++){
for (x=0;x<NUM_COLS;x++){
setpixel((pixel){x,y}, 3);
wait(100);
}
}
}
void test_level1(){
unsigned char x,y;
for (y=0;y<NUM_ROWS;y++){
for (x=0;x<NUM_COLS;x++){
setpixel((pixel){x,y}, 1);
wait(5);
}
}
for(;;) wait(100);
}
void test_level2(){
unsigned char x,y;
for (y=0;y<NUM_ROWS;y++){
for (x=0;x<NUM_COLS;x++){
setpixel((pixel){x,y}, 2);
wait(5);
}
}
for(;;) wait(100);
}
void test_level3(){
unsigned char x,y;
for (y=0;y<NUM_ROWS;y++){
for (x=0;x<NUM_COLS;x++){
setpixel((pixel){x,y}, 3);
wait(5);
}
}
for(;;) wait(100);
}
void test_levels(){
unsigned char x,y,b;
for(b=1;b<4;b++){
for (y=0;y<NUM_ROWS;y++){
for (x=0;x<NUM_COLS;x++){
setpixel((pixel){x,y}, b);
wait(5);
}
}
}
}
void test_palette(){
unsigned char x,y,b;
for (y=0;y<NUM_ROWS;y++){
b=y%4;
for (x=0;x<NUM_COLS;x++){
setpixel((pixel){x,y}, b);
wait(1);
}
}
for(;;) wait(100);
}
#endif
#ifdef ANIMATION_OFF
void off()
{
clear_screen(0);
while(1)
wait(100);
}
#endif
#ifdef ANIMATION_SPIRALE
void spirale(unsigned int delay){
clear_screen(0);
cursor cur;
cur.dir = right;
cur.mode = set;
set_cursor (&cur, (pixel){NUM_COLS-1,0});
unsigned char clearbit=0;
while(clearbit == 0){
clearbit = 1;
while (!get_next_pixel(cur.pos, cur.dir)){
clearbit = 0;
walk(&cur, 1, delay);
}
cur.dir = direction_r(cur.dir);
}
cur.mode = clear;
set_cursor(&cur, (pixel){(NUM_COLS/2)-1,(NUM_ROWS/2)-1});
for(clearbit=0;clearbit==0;){
if( get_next_pixel(cur.pos, direction_r(cur.dir)) ){
cur.dir = direction_r(cur.dir);
}
if( get_next_pixel(cur.pos, cur.dir) == 1 ){
walk(&cur , 1, delay);
}else{
clearbit = 1;
}
}
}
#endif
#ifdef ANIMATION_JOERN1
void joern1(){
unsigned char i, j, x;
unsigned char rolr=0x01 , rol;
clear_screen(3);
for(i = 0; i< 80;i++){
rol = rolr;
for(j = 0 ;j < NUM_ROWS; j++){
for(x=0;x<LINEBYTES;x++)
pixmap[2][j][x] = rol;
if((rol<<=1)==0)rol = 0x01;
}
if((rolr<<=1) == 0) rolr = 1;
wait(100);
}
}
#endif
#ifdef ANIMATION_SCHACHBRETT
void schachbrett(unsigned char times){
clear_screen(0);
unsigned char j;
for(j=0;j<times;j++){
unsigned char i, x;
for(i = 0; i<NUM_ROWS; i++){
for(x=0;x<LINEBYTES;x++)
pixmap[2][i][x] = 0x55<<(i&0x01);
}
wait(200);
for(i = 0; i<NUM_ROWS; i++){
for(x=0;x<LINEBYTES;x++)
pixmap[2][i][x] = 0xAA>>(i&0x01);
}
wait(200);
}
}
#endif
#ifdef ANIMATION_FEUER
#define FEUER_Y (NUM_ROWS + 3)
void feuer()
{
unsigned char y, x;
unsigned int t;
unsigned char world[NUM_COLS][FEUER_Y]; // double buffer
for(t=0; t<800; t++) {
// diffuse
for(y=1; y<FEUER_Y; y++) {
for(x=1; x<NUM_COLS-1; x++) {
world[x][y-1] = (FEUER_N*world[x-1][y] + FEUER_S*world[x][y] + FEUER_N*world[x+1][y]) / FEUER_DIV;
};
world[0][y-1] = (FEUER_N*world[NUM_COLS-1][y] + FEUER_S*world[0][y] + FEUER_N*world[1][y]) / FEUER_DIV;
world[NUM_COLS-1][y-1] = (FEUER_N*world[0][y] + FEUER_S*world[NUM_COLS-1][y] + FEUER_N*world[NUM_COLS-2][y]) / FEUER_DIV;
};
// update lowest line
for(x=0; x<NUM_COLS; x++) {
world[x][FEUER_Y-1] = RANDOM8();
};
// copy to screen
for(y=0; y<NUM_ROWS; y++) {
for(x=0; x<NUM_COLS; x++) {
setpixel( (pixel){x,y}, (world[x][y] >> 5) );
}
};
wait(FEUER_DELAY);
}
}
#endif
#ifdef ANIMATION_RANDOM_BRIGHT
/**
* void random_bright(void)
* by Daniel Otte
*
*
*/
void random_bright(unsigned cycles){
uint8_t t,x,y;
while(cycles--){
for(y=0; y<NUM_ROWS; ++y)
for(x=0; x<NUM_COLS/4; ++x){
t=random8();
setpixel((pixel){x*4+0, y}, 0x3&(t>>0));
setpixel((pixel){x*4+1, y}, 0x3&(t>>2));
setpixel((pixel){x*4+2, y}, 0x3&(t>>4));
setpixel((pixel){x*4+3, y}, 0x3&(t>>6));
}
wait(200);
}
}
#endif

22
animations/programm.h

@ -0,0 +1,22 @@
#ifndef PROGRAMM_H_
#define PROGRAMM_H_
void off();
void spirale(unsigned int delay);
void joern1();
void joern2();
void draw_line( unsigned char yabs, signed char delta);
void schachbrett(unsigned char times);
void test1();
void test_level1();
void test_level2();
void test_level3();
void test_levels();
void test_palette();
void snake();
void matrix();
void fadein();
void feuer();
void random_bright(unsigned cycles);
#endif /* PROGRAMM_H_ */

249
animations/snake.c

@ -0,0 +1,249 @@
#include "../config.h"
#include "../pixel.h"
#include "../util.h"
#include "../random/prng.h"
#include "snake.h"
#include "../joystick.h"
#define RANDOM8() (random8())
void snake(){
pixel pixels[64];
pixels[0] = (pixel){NUM_COLS/2, NUM_ROWS/2};
pixels[1] = (pixel){NUM_COLS/2, (NUM_ROWS/2)-1};
pixel * head = &pixels[1];
pixel * tail = &pixels[0];
pixel old_head;
pixel apples[10];
unsigned char apple_num = 0;
direction dir = up;
clear_screen(0);
unsigned char x=0, dead=0;
while(1){
x++;
old_head = *head;
if(++head == pixels + 64) head = pixels;
unsigned char dead_cnt=0;
unsigned char apple_found = 0, j;
for(j=0;j<apple_num;j++){
unsigned char i;
for(i=0;i<4;i++){
if ( (next_pixel(old_head, i).x == apples[j].x) && (next_pixel(old_head, i).y == apples[j].y) ){
apple_found = 1;
dir = i;
for(;j<apple_num-1;j++){
apples[j]=apples[j+1];
}
apple_num--;
goto apple_se;
}
}
}
apple_se:
if(apple_found){
}else{
while(get_next_pixel(old_head, dir)){
if((dead_cnt++)==4){
dead = 1;
break;
}
dir = direction_r(dir);
}
}
if(!dead){
*head = next_pixel(old_head, dir);
setpixel(*head, 3);
if((RANDOM8()&0xff)<80){
unsigned char j;
unsigned char nextapple=0, distx, disty, shortdist=255, xy=0;
if(!apple_num){
dir = RANDOM8()%4;
}else{
for(j=0;j<apple_num;j++){
if(head->x > apples[j].x){
distx = head->x - apples[j].x;
}else{
distx = apples[j].x - head->x;
}
if(head->y > apples[j].y){
disty = head->y - apples[j].y;
}else{
disty = apples[j].y - head->y;
}
if ((distx + disty) < shortdist){
shortdist = distx + disty;
nextapple = j;
xy = (distx > disty)?1:0;
}
}
if(xy){
dir = (apples[nextapple].x > head->x)?left:right;
}else{
dir = (apples[nextapple].y > head->y)?down:up;
}
}
}
if( (apple_num<9) && ((RANDOM8()&0xff)<10) ){
pixel new_apple = (pixel){RANDOM8()%NUM_COLS,RANDOM8()%NUM_ROWS};
if(!get_pixel(new_apple)){
apples[apple_num++]=new_apple;
}
}
if(!apple_found){
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]);
}
}
wait (SNAKE_DELAY);
}
}
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);
}
}
}

8
animations/snake.h

@ -0,0 +1,8 @@
#ifndef SNAKE_H_
#define SNAKE_H_
void snake();
void snake_game();
#endif /* SNAKE_H_ */

31
borg_hw/Makefile

@ -0,0 +1,31 @@
TARGET = libborg_hw.a
TOPDIR = ..
include $(TOPDIR)/defaults.mk
ifeq ($(BORG_HW),HW_BORG_16)
SRC = borg_hw_borg16.c
endif
ifeq ($(BORG_HW),HW_BORG_ANDRE)
SRC = borg_hw_andreborg.c
endif
ifeq ($(BORG_HW),HW_BORG_LS)
SRC = borg_hw_borg_ls.c
endif
ifeq ($(BORG_HW),HW_BORG_LS)
SRC = borg_hw_borg_ls.c
endif
ifeq ($(BORG_HW),HW_BORG_MINI)
SRC = borg_hw_borg_mini.c
endif
ifeq ($(SRC),'')
$(error no valid hardware driver selected )
endif
include $(TOPDIR)/rules.mk

15
borg_hw/borg_hw.h

@ -0,0 +1,15 @@
#ifndef BORG_HW_H
#define BORG_HW_H
//Linebytes gibt die Zahl der Bytes pro Zeile in der
//Pixmap an, also Spaltenzahl/8 aufgerundet
#define LINEBYTES (((NUM_COLS-1)/8)+1)
extern unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
void watchdog_enable();
void borg_hw_init();
void timer0_off();
#endif

168
borg_hw/borg_hw_andreborg.c

@ -0,0 +1,168 @@
#include "../config.h"
#include "../makros.h"
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include "borg_hw.h"
/*
// Diese #defines werden nun durch menuconfig gesetzt
// 16 Spalten insgesamt direkt gesteuert, dafür 2 Ports
#define COLPORT1 PORTA
#define COLDDR1 DDRA
#define COLPORT2 PORTC
#define COLDDR2 DDRC
// Der andere Port übernimmt die Steuerung der Schieberegister
#define ROWPORT PORTD
#define ROWDDR DDRD
// Clock und reset gehen gemeinsam an beide Schieberegister
// der reset pin ist negiert
#define PIN_MCLR PD4
#define PIN_CLK PD5
//das dier sind die individuellen Dateneingänge für die Schieberegister
#define PIN_DATA1 PD6
#define PIN_DATA2 PD7
*/
#define COLDDR1 DDR(COLPORT1)
#define COLDDR2 DDR(COLPORT2)
#define ROWDDR DDR(ROWPORT)
//Der Puffer, in dem das aktuelle Bild gespeichert wird
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
//Eine Zeile anzeigen
inline void rowshow(unsigned char row, unsigned char plane){
//Die Zustände von der vorherigen Zeile löschen
COLPORT1 = 0;
COLPORT2 = 0;
//kurze Warteschleife, damit die Treiber auch wirklich ausschalten
unsigned char i;
for(i=0;i<20;i++){
asm volatile("nop");
}
if (row == 0){
//Zeile 0: Das erste Schieberegister initialisieren
ROWPORT&= ~(1<<PIN_MCLR);
ROWPORT|= (1<<PIN_MCLR);
ROWPORT|= (1<<PIN_DATA1);
ROWPORT|= (1<<PIN_CLK);
ROWPORT&= ~(1<<PIN_CLK);
ROWPORT&= ~(1<<PIN_DATA1);
//Je nachdem, welche der Ebenen wir Zeichnen, die Zeile verschieden lange Anzeigen
switch (plane){
case 0:
OCR0 = 5;
break;
case 1:
OCR0 = 8;
break;
case 2:
OCR0 = 20;
}
}else if(row == 8){
//Zeile 8: Das Zweite Schieberegister initialisieren
ROWPORT&= ~(1<<PIN_MCLR);
ROWPORT|= (1<<PIN_MCLR);
ROWPORT|= (1<<PIN_DATA2);
ROWPORT|= (1<<PIN_CLK);
ROWPORT&= ~(1<<PIN_CLK);
ROWPORT&= ~(1<<PIN_DATA2);
}else{
//In jeder anderen Zeile einfach nur einen weiter schieben
ROWPORT|= (1<<PIN_CLK);
ROWPORT&= ~(1<<PIN_CLK);
}
//ncoh eine Warteschleife, damit die Zeilentreiber bereit sind
for(i=0;i<20;i++){
asm volatile("nop");
}
//die Daten für die aktuelle Zeile auf die Spaltentreiber ausgeben
COLPORT1 = pixmap[plane][row][0];
COLPORT2 = pixmap[plane][row][1];
}
//Dieser Interrupt wird je nach Ebene mit 50kHz 31,25kHz oder 12,5kHz ausgeführt
SIGNAL(SIG_OUTPUT_COMPARE0)
{
static unsigned char plane = 0;
static unsigned char row = 0;
//Watchdog zurücksetzen
wdt_reset();
//Die aktuelle Zeile in der aktuellen Ebene ausgeben
rowshow(row, plane);
//Zeile und Ebene inkrementieren
if(++row == NUM_ROWS){
row = 0;
if(++plane==NUMPLANE) plane=0;
}
}
void timer0_off(){
cli();
COLPORT1 = 0;
COLPORT2 = 0;
ROWPORT = 0;
TCCR0 = 0x00;
sei();
}
// Den Timer, der denn Interrupt auslöst, initialisieren
void timer0_on(){
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00
CS02 CS01 CS00
0 0 0 stop
0 0 1 clk
0 1 0 clk/8
0 1 1 clk/64
1 0 0 clk/256
1 0 1 clk/1024
*/
TCCR0 = 0x0B; // CTC Mode, clk/64
TCNT0 = 0; // reset timer
OCR0 = 20; // Compare with this value
TIMSK = 0x02; // Compare match Interrupt on
}
void borg_hw_init(){
//Spalten Ports auf Ausgang
COLDDR1 = 0xFF;
COLDDR2 = 0xFF;
//Pins am Zeilenport auf Ausgang
ROWDDR = (1<<PIN_MCLR) | (1<<PIN_CLK) | (1<< PIN_DATA1) | (1<<PIN_DATA2);
//Alle Spalten erstmal aus
COLPORT1 = 0;
COLPORT2 = 0;
//Schieberegister für Zeilen zurücksetzen
ROWPORT = 0;
timer0_on();
//Watchdog Timer aktivieren
wdt_reset();
wdt_enable(0x00); // 17ms Watchdog
}

207
borg_hw/borg_hw_borg16.c

@ -0,0 +1,207 @@
#include "../config.h"
#include "../makros.h"
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include "borg_hw.h"
/*
// Diese #defines werden nun durch menuconfig gesetzt
// 16 Spalten insgesamt direkt gesteuert, dafür 2 Ports
#define COLPORT1 PORTC
#define COLDDR1 DDRC
#define COLPORT2 PORTA
#define COLDDR2 DDRA
// Der andere Port übernimmt die Steuerung der Schieberegister
#define ROWPORT PORTD
#define ROWDDR DDRD
// Clock und reset gehen gemeinsam an beide Schieberegister
// der reset pin ist negiert
#define PIN_MCLR PD4
#define PIN_CLK PD6
//das dier sind die individuellen Dateneingänge für die Schieberegister
#define PIN_DATA PD7
*/
#define COLDDR1 DDR(COLPORT1)
#define COLDDR2 DDR(COLPORT2)
#define ROWDDR DDR(ROWPORT)
//Der Puffer, in dem das aktuelle Bild gespeichert wird
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
//zur nächsten Zeile weiterschalten
inline void nextrow(uint8_t row){
//Die Zustände von der vorherigen Zeile löschen
COLPORT1 = 0;
COLPORT2 = 0;
//kurze Warteschleife, damit die Treiber auch wirklich ausschalten
unsigned char i;
for(i=0;i<10;i++){
asm volatile("nop");
}
if (row == 0){
//Zeile 0: Das erste Schieberegister initialisieren
#ifndef INVERSE_ROWS
ROWPORT&= ~(1<<PIN_MCLR);
ROWPORT|= (1<<PIN_MCLR);
ROWPORT|= (1<<PIN_DATA);
ROWPORT|= (1<<PIN_CLK);
ROWPORT&= ~(1<<PIN_CLK);
ROWPORT&= ~(1<<PIN_DATA);
#else
ROWPORT&= ~(1<<PIN_DATA);
ROWPORT|= (1<<PIN_CLK);
ROWPORT&= ~(1<<PIN_CLK);
ROWPORT|= (1<<PIN_DATA);
#endif
}else{
//In jeder anderen Zeile einfach nur einen weiter schieben
ROWPORT|= (1<<PIN_CLK);
ROWPORT&= ~(1<<PIN_CLK);
}
//noch eine Warteschleife, damit die Zeilentreiber bereit sind
for(i=0;i<20;i++){
asm volatile("nop");
}
}
//Eine Zeile anzeigen
inline void rowshow(unsigned char row, unsigned char plane){
//Je nachdem, welche der Ebenen wir Zeichnen, die Zeile verschieden lange Anzeigen
switch (plane){
case 0:
OCR0 = 3;
break;
case 1:
OCR0 = 4;
break;
case 2:
OCR0 = 22;
}
uint8_t tmp, tmp1;
//die Daten für die aktuelle Zeile auf die Spaltentreiber ausgeben
#ifndef INTERLACED_ROWS
tmp = pixmap[plane][row][0];
tmp1 = pixmap[plane][row][1];
#else
row = (row>>1) + ((row & 0x01)?8:0 );
tmp = pixmap[plane][row][0];
tmp1 = pixmap[plane][row][1];
#endif
#ifdef REVERSED_HARDWARE
tmp = (tmp >> 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
COLPORT2 = tmp;
tmp = tmp1;
tmp = (tmp >> 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
COLPORT1 = tmp;
#else
#ifdef INTERLACED_COLS
static uint8_t interlace_table[16] = {
0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15, 0x40, 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55
};
COLPORT1 = interlace_table[tmp&0x0f] | (interlace_table[tmp1&0x0f]<<1);
tmp>>=4; tmp1>>=4;
COLPORT2 = interlace_table[tmp] | (interlace_table[tmp1]<<1);
#else
COLPORT1 = tmp;
COLPORT2 = tmp1;
#endif
#endif
}
//Dieser Interrupt wird je nach Ebene mit 50kHz 31,25kHz oder 12,5kHz ausgeführt
SIGNAL(SIG_OUTPUT_COMPARE0)
{
static unsigned char plane = 0;
static unsigned char row = 0;
//Watchdog zurücksetzen
wdt_reset();
//Zeile und Ebene inkrementieren
if(++plane==NUMPLANE){
plane=0;
if(++row == NUM_ROWS){
row = 0;
}
nextrow(row);
}
//Die aktuelle Zeile in der aktuellen Ebene ausgeben
rowshow(row, plane);
}
void timer0_off(){
cli();
COLPORT1 = 0;
COLPORT2 = 0;
ROWPORT = 0;
TCCR0 = 0x00;
sei();
}
// Den Timer, der denn Interrupt auslöst, initialisieren
void timer0_on(){
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00
CS02 CS01 CS00
0 0 0 stop
0 0 1 clk
0 1 0 clk/8
0 1 1 clk/64
1 0 0 clk/256
1 0 1 clk/1024
*/
TCCR0 = 0x0C; // CTC Mode, clk/64
TCNT0 = 0; // reset timer
OCR0 = 20; // Compare with this value
TIMSK = 0x02; // Compare match Interrupt on
}
void borg_hw_init(){
//Spalten Ports auf Ausgang
COLDDR1 = 0xFF;
COLDDR2 = 0xFF;
//Pins am Zeilenport auf Ausgang
ROWDDR = (1<<PIN_MCLR) | (1<<PIN_CLK) | (1<< PIN_DATA);
//Alle Spalten erstmal aus
COLPORT1 = 0;
COLPORT2 = 0;
//Schieberegister für Zeilen zurücksetzen
ROWPORT = 0;
timer0_on();
//Watchdog Timer aktivieren
wdt_reset();
wdt_enable(0x00); // 17ms Watchdog
}

127
borg_hw/borg_hw_borg_ls.c

@ -0,0 +1,127 @@
#include "../config.h"
#include "../makros.h"
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include "borg_hw.h"
/*
// Diese #defines werden nun durch menuconfig gesetzt
#define ROWPORT PORTB
#define ROWDDR DDRB
#define COLPORT PORTD
#define COLDDR DDRD
#define PIN_DATA PC4
#define PIN_CLK PC6 //active low
#define PIN_LINE_EN PC5 //active low
*/
#define COLDDR DDR(COLPORT)
#define ROWDDR DDR(ROWPORT)
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
inline void rowshow(unsigned char row, unsigned char plane){
COLPORT |= (1<<PIN_LINE_EN);//blank display
ROWPORT = (ROWPORT & 0xF8) | row;
unsigned char b, d, x;
for(b=0;b<LINEBYTES;b++){
d = pixmap[plane][row][b];
for(x=0;x<8;x++){
if(d & 0x01){
COLPORT |= (1<<PIN_DATA);
}else{
COLPORT &= ~(1<<PIN_DATA);
}
d>>=1;
COLPORT &= ~(1<<PIN_CLK);
COLPORT |= (1<<PIN_CLK);
}
}
COLPORT &= ~(1<<PIN_LINE_EN);//unblank display
}
SIGNAL(SIG_OUTPUT_COMPARE0)
{
static unsigned char plane = 0;
static unsigned char row = 0;
if (row == 0){
switch (plane){
case 0:
OCR0 = 7;
break;
case 1:
OCR0 = 20;
break;
case 2:
OCR0 = 40;
}
}
rowshow(row, plane);
if(++row == NUM_ROWS){
row = 0;
if(++plane==NUMPLANE) plane=0;
}
wdt_reset();
}
void timer0_on(){
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00
CS02 CS01 CS00
0 0 0 stop
0 0 1 clk
0 1 0 clk/8
0 1 1 clk/64
1 0 0 clk/256
1 0 1 clk/1024
*/
TCCR0 = 0x08 |0x04; // CTC Mode, clk/256
TCNT0 = 0; // reset timer
OCR0 = 0x30; // Compare with this value
TIMSK = 0x02; // Compare match Interrupt on
}
void timer0_off(){
cli();
COLPORT |= (1<<PIN_LINE_EN);//blank display
TCCR0 = 0x00;
sei();
}
void watchdog_enable()
{
wdt_reset();
wdt_enable(0x00); // 17ms
}
void borg_hw_init(){
COLPORT |= (1<<PIN_CLK) | (1<<PIN_LINE_EN);
COLDDR |= (1<<PIN_CLK) | (1<<PIN_LINE_EN) | (1<<PIN_DATA);
ROWDDR |= 0x07;
watchdog_enable();
timer0_on();
}

165
borg_hw/borg_hw_borg_mini.c

@ -0,0 +1,165 @@
#include "../config.h"
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include "borg_hw.h"
/*
// Diese #defines werden nun durch menuconfig gesetzt
//An diesen Pins ist das Schieberegister
//für die Spalten angeschlossen.
#define COLPORT PORTC
#define COLDDR DDRC
#define BIT_DAT 4 //Daten-Eingang
#define BIT_CLK 5 //Takt-Eingang
//An diesem Port sind die Zeilentreiber angeschlossen.
//Ein Null-Pegel schaltet den jeweiligen Transistor an.
#define ROWPORT1 PORTD
#define ROWDDR1 DDRD
#define ROWPORT2 PORTC
#define ROWDDR2 DDRC
*/
#define COLDDR DDR(COLPORT)
#define ROWDDR1 DDR(ROWPORT1)
#define ROWDDR2 DDR(ROWPORT2)
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
inline void rowshow(unsigned char row, unsigned char plane){
static uint8_t rowmask = 0xFF;
uint8_t x, tmp;
//alle Zeilentreiber aus
ROWPORT1 |= 0xF3;
ROWPORT2 |= 0x0C;
for(x=0;x<10;x++){
asm volatile ("nop");
}
if (row == 0){
rowmask = 0x7F; //0111 1111
}else{
rowmask >>= 1;
rowmask |= 0x80;
}
switch (plane){
case 0:
TCNT0 = 0x100-12;
break;
case 1:
TCNT0 = 0x100-20;
break;
case 2:
TCNT0 = 0x100-50;
}
//Die fünf bits für das 2. Display in das
//Schieberegister takten
tmp = pixmap[plane][row][0];
for(x=0;x<3;x++){
if(tmp & 0x20){
COLPORT &= ~(1<<BIT_DAT);
}else{
COLPORT |= (1<<BIT_DAT);
}
tmp>>=1;
COLPORT |= (1<<BIT_CLK);
COLPORT &= ~(1<<BIT_CLK);
}
tmp = pixmap[plane][row][1];
for(x=0;x<2;x++){
if(tmp & 0x01){
COLPORT &= ~(1<<BIT_DAT);
}else{
COLPORT |= (1<<BIT_DAT);
}
tmp>>=1;
COLPORT |= (1<<BIT_CLK);
COLPORT &= ~(1<<BIT_CLK);
}
//Die restlichen 5 bit auch ins Schieberegister
tmp = pixmap[plane][row][0];
for(x=0;x<5;x++){
if(tmp & 0x01){
COLPORT &= ~(1<<BIT_DAT);
}else{
COLPORT |= (1<<BIT_DAT);
}
tmp>>=1;
COLPORT |= (1<<BIT_CLK);
COLPORT &= ~(1<<BIT_CLK);
}
//nächste Zeile anschalten
ROWPORT1 &= rowmask | 0x0C;
ROWPORT2 &= rowmask | 0xF3;
}
extern uint8_t schmuh;
ISR(SIG_OVERFLOW0)
{
static unsigned char plane = 0;
static unsigned char row = 0;
rowshow(row, plane);
if(++row == NUM_ROWS){
row = 0;
if(++plane==NUMPLANE) plane=0;
}
schmuh = 1;
}
void timer0_on(){
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00
CS02 CS01 CS00
0 0 0 stop
0 0 1 clk
0 1 0 clk/8
0 1 1 clk/64
1 0 0 clk/256
1 0 1 clk/1024
*/
TCCR0 = 0x03; // clk/64
TCNT0 = 0xFF-20;// reset timer
TIMSK |= (1<<TOIE0);
}
void borg_hw_init(){
// Alle Zeilentransistoren aus.
ROWPORT1 |= 0xF3;
// Port für Zeilentransistoren auf Ausgang
ROWDDR1 |= 0xF3;
ROWPORT2 |=0x0C;
ROWDDR2 |=0x0C;
//Signale für Schieberegister auf Ausgang
COLDDR |= (1<<BIT_CLK) | (1<<BIT_DAT);
COLPORT &= ~(1<<BIT_CLK);
timer0_on();
}

50
borg_hw/config.in

@ -0,0 +1,50 @@
###################### Borg Hardware Menu #####################################
mainmenu_option next_comment
comment "Borg Hardware"
int "Number of rows " NUM_ROWS 16
int "Number of columns" NUM_COLS 16
int "Number of brightnes-levels" NUMPLANE 3
choice 'Hardware Driver' \
"Borg-16 HW_BORG_16 \
Andre-borg HW_BORG_ANDRE \
Laufschrift-borg HW_BORG_LS \
Borg-mini HW_BORG_MINI" \
'Borg-16' BORG_HW
if [ "$BORG_HW" == "HW_BORG_16" ] ; then
source borg_hw/config_borg16.in
fi
if [ "$BORG_HW" == "HW_BORG_ANDRE" ] ; then
source borg_hw/config_andreborg.in
fi
if [ "$BORG_HW" == "HW_BORG_LS" ] ; then
source borg_hw/config_borg_ls.in
fi
if [ "$BORG_HW" == "HW_BORG_MINI" ] ; then
source borg_hw/config_borg_mini.in
fi
# case $x in
# y) flag="*" ;;
# m) flag="M" ;;
# *) flag=" " ;;
# esac
endmenu
###############################################################################

71
borg_hw/config_andreborg.in

@ -0,0 +1,71 @@
mainmenu_option next_comment
comment "Andreborg port setup"
choice 'Column Port 1 (right)' \
"PORTA PORTA \
PORTB PORTB \
PORTC PORTC \
PORTD PORTD" \
'PORTA' COLPORT1
choice 'Column Port 2 (left)' \
"PORTA PORTA \
PORTB PORTB \
PORTC PORTC \
PORTD PORTD" \
'PORTC' COLPORT2
choice 'port for row shiftregisters' \
"PORTA PORTA \
PORTB PORTB \
PORTC PORTC \
PORTD PORTD" \
'PORTD' ROWPORT
comment "pin numbers on shiftregister port"
choice '/MCLR Pin' \
"Pin0 0 \
Pin1 1 \
Pin2 2 \
Pin3 3 \
Pin4 4 \
Pin5 5 \
Pin6 6 \
Pin7 7" \
'Pin4' PIN_MCLR
choice 'CLK Pin' \
"Pin0 0 \
Pin1 1 \
Pin2 2 \
Pin3 3 \
Pin4 4 \
Pin5 5 \
Pin6 6 \
Pin7 7" \
'Pin5' PIN_CLK
choice 'DATA1 Pin' \
"Pin0 0 \
Pin1 1 \
Pin2 2 \
Pin3 3 \
Pin4 4 \
Pin5 5 \
Pin6 6 \
Pin7 7" \
'Pin6' PIN_DATA1
choice 'DATA2 Pin' \
"Pin0 0 \
Pin1 1 \
Pin2 2 \
Pin3 3 \
Pin4 4 \
Pin5 5 \
Pin6 6 \
Pin7 7" \
'Pin7' PIN_DATA2
endmenu

77
borg_hw/config_borg16.in

@ -0,0 +1,77 @@
mainmenu_option next_comment
comment "Borg16 port setup"
#define COLPORT1 PORTC
#define COLDDR1 DDRC
#define COLPORT2 PORTA
#define COLDDR2 DDRA
#// Der andere Port übernimmt die Steuerung der Schieberegister
#define ROWPORT PORTD
#define ROWDDR DDRD
#// Clock und reset gehen gemeinsam an beide Schieberegister
#// der reset pin ist negiert
#define PIN_RST PD4
#define PIN_CLK PD6
#//das dier sind die individuellen Dateneingänge für die Schieberegister
#define PIN_SHFT1 PD7
choice 'Column Port 1 (right)' \
"PORTA PORTA \
PORTB PORTB \
PORTC PORTC \
PORTD PORTD" \
'PORTC' COLPORT1
choice 'Column Port 2 (left)' \
"PORTA PORTA \
PORTB PORTB \
PORTC PORTC \
PORTD PORTD" \
'PORTA' COLPORT2
choice 'port for row shiftregisters' \
"PORTA PORTA \
PORTB PORTB \
PORTC PORTC \
PORTD PORTD" \
'PORTD' ROWPORT
comment "pin numbers on shiftregister port"
choice '/MCLR Pin' \
"Pin0 0 \
Pin1 1 \
Pin2 2 \
Pin3 3 \
Pin4 4 \
Pin5 5 \
Pin6 6 \
Pin7 7" \
'Pin4' PIN_MCLR
choice 'CLK Pin' \
"Pin0 0 \
Pin1 1 \
Pin2 2 \
Pin3 3 \
Pin4 4 \
Pin5 5 \
Pin6 6 \
Pin7 7" \
'Pin6' PIN_CLK
choice 'DATA Pin' \
"Pin0 0 \
Pin1 1 \
Pin2 2 \
Pin3 3 \
Pin4 4 \
Pin5 5 \
Pin6 6 \
Pin7 7" \
'Pin7' PIN_DATA
endmenu

55
borg_hw/config_borg_ls.in

@ -0,0 +1,55 @@
mainmenu_option next_comment
comment "Laufschrift-Borg port setup"
choice 'port for row select' \
"PORTA PORTA \
PORTB PORTB \
PORTC PORTC \
PORTD PORTD" \
'PORTB' ROWPORT
choice 'Column shiftregister Port' \
"PORTA PORTA \
PORTB PORTB \
PORTC PORTC \
PORTD PORTD" \
'PORTD' COLPORT
comment "pin numbers on shiftregister port"
choice 'CLK Pin' \
"Pin0 0 \
Pin1 1 \
Pin2 2 \
Pin3 3 \
Pin4 4 \
Pin5 5 \
Pin6 6 \
Pin7 7" \
'Pin6' PIN_CLK
choice 'DATA Pin' \
"Pin0 0 \
Pin1 1 \
Pin2 2 \
Pin3 3 \
Pin4 4 \
Pin5 5 \
Pin6 6 \
Pin7 7" \
'Pin4' PIN_DATA
choice 'LINE_EN Pin' \
"Pin0 0 \
Pin1 1 \
Pin2 2 \
Pin3 3 \
Pin4 4 \
Pin5 5 \
Pin6 6 \
Pin7 7" \
'Pin5' PIN_LINE_EN
endmenu

50
borg_hw/config_borg_mini.in

@ -0,0 +1,50 @@
mainmenu_option next_comment
comment "Borg-mini port setup"
choice 'Row Port 1' \
"PORTA PORTA \
PORTB PORTB \
PORTC PORTC \
PORTD PORTD" \
'PORTD' ROWPORT1
choice 'Row Port 2' \
"PORTA PORTA \
PORTB PORTB \
PORTC PORTC \
PORTD PORTD" \
'PORTC' ROWPORT2
choice 'Column shiftregister Port' \
"PORTA PORTA \
PORTB PORTB \
PORTC PORTC \
PORTD PORTD" \
'PORTC' COLPORT
comment "pin numbers on shiftregister port"
choice 'CLK Pin' \
"Pin0 0 \
Pin1 1 \
Pin2 2 \
Pin3 3 \
Pin4 4 \
Pin5 5 \
Pin6 6 \
Pin7 7" \
'Pin5' PIN_CLK
choice 'DATA Pin' \
"Pin0 0 \
Pin1 1 \
Pin2 2 \
Pin3 3 \
Pin4 4 \
Pin5 5 \
Pin6 6 \
Pin7 7" \
'Pin4' PIN_DATA
endmenu

134
can/borg_can.c

@ -0,0 +1,134 @@
#include "can.h"
#include "lap.h"
#include "borg_can.h"
#include "spi.h"
#include "blinken.h"
#include <avr/pgmspace.h>
#include <setjmp.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <string.h>
can_addr myaddr;
extern jmp_buf newmode_jmpbuf;
void bcan_init()
{
spi_init();
can_init();
myaddr = eeprom_read_byte(0x00);
pdo_message *msg = (pdo_message *)can_buffer_get();
msg->addr_src = myaddr;
msg->addr_dst = 0xff;
msg->port_src = PORT_BORG;
msg->port_dst = PORT_BORG;
msg->dlc = 4;
msg->cmd = FKT_BORG_INFO;
msg->data[0] = NUM_ROWS;
msg->data[1] = NUM_COLS;
msg->data[2] = NUM_PLANES;
can_transmit((can_message *)msg);
}
void process_mgt_msg(pdo_message *msg)
{
pdo_message *rmsg;
switch(msg->cmd) {
case FKT_MGT_RESET:
timer0_off();
cli();
while(1);
break;
case FKT_MGT_PING:
rmsg = (pdo_message *)can_buffer_get();
rmsg->addr_dst = msg->addr_src;
rmsg->addr_src = myaddr;
rmsg->port_dst = msg->port_src;
rmsg->port_src = msg->port_dst;
rmsg->cmd = FKT_MGT_PONG;
rmsg->dlc = 1;
can_transmit((can_message *)rmsg);
break;
}
}
void process_borg_msg(pdo_message *msg)
{
unsigned char i, j;
switch(msg->cmd) {
case FKT_BORG_MODE:
longjmp(newmode_jmpbuf, msg->data[0]);
break;
case FKT_BORG_SCROLLTEXT_RESET:
for(i=0; i < msg->dlc-1; i++) {
scrolltext_text[i] = msg->data[i];
}
scrolltext_text[i] = 0;
break;
case FKT_BORG_SCROLLTEXT_APPEND:
j=0;
while(scrolltext_text[j]) j++;
for(i=0; i < msg->dlc-1; i++) {
scrolltext_text[i+j] = msg->data[i];
}
scrolltext_text[i+j] = 0;
break;
#ifdef Hansi_hat_gelernt_Werte_vorher_zu_definieren
//========== blinkenstuff
//clear the blinkenbackbuffer to color
case FKT_BLINK_CLEARBUF:
blink_clearbuf(msg->data[0]);
break;
//set auto position increment flag
case FKT_BLINK_SETAUTOPOS:
blink_setautopos(msg->data[0]);
break;
//set the current blinkenbuffer offset position
case FKT_BLINK_SETPOS:
blink_setpos(msg->data[0]);
break;
//puts the current blinkenbuffer to the frontbuffer
case FKT_BLINK_SHOW:
blink_show();
break;
//puts data into the blinkenbuffer
case FKT_BLINK_DATA:
blink_data(msg->data, msg->dlc - 1);
break;
#endif
}
}
void bcan_process_messages()
{
pdo_message *msg = (pdo_message*) can_get_nb();
while(msg) {
if (!msg)
return;
if(msg->addr_dst == myaddr && msg->port_dst == PORT_MGT)
process_mgt_msg(msg);
if(msg->addr_dst == myaddr && msg->port_dst == PORT_BORG)
process_borg_msg(msg);
msg = (pdo_message*) can_get_nb();
};
}

11
can/borg_can.h

@ -0,0 +1,11 @@
#ifndef BORG_CAN_H_
#define BORG_CAN_H_
extern unsigned char borg_mode;
extern char scrolltext_text[];
void bcan_init();
unsigned char bcan_mode();
void bcan_process_messages();
#endif /* BORG_CAN_H */

496
can/can.c

@ -0,0 +1,496 @@
#ifndef __C64__
#include <avr/io.h>
#include <avr/interrupt.h>
#define asm asm volatile
#endif
#include "can.h"
#include "spi.h"
#define spi_clear_ss() SPI_PORT |= (1<<SPI_PIN_SS)
#define spi_set_ss() SPI_PORT &= ~(1<<SPI_PIN_SS)
//Registers
#define RXF0SIDH 0x00
#define RXF0SIDL 0x01
#define RXF0EID8 0x02
#define RXF0EID0 0x03
#define RXF1SIDH 0x04
#define RXF1SIDL 0x05
#define RXF1EID8 0x06
#define RXF1EID0 0x07
#define RXF2SIDH 0x08
#define RXF2SIDL 0x09
#define RXF2EID8 0x0A
#define RXF2EID0 0x0B
#define BFPCTRL 0x0C
#define TXRTSCTRL 0x0D
#define CANSTAT 0x0E
#define CANCTRL 0x0F
#define RXF3SIDH 0x10
#define RXF3SIDL 0x11
#define RXF3EID8 0x12
#define RXF3EID0 0x13
#define RXF4SIDH 0x14
#define RXF4SIDL 0x15
#define RXF4EID8 0x16
#define RXF4EID0 0x17
#define RXF5SIDH 0x18
#define RXF5SIDL 0x19
#define RXF5EID8 0x1A
#define RXF5EID0 0x1B
#define TEC 0x1C
#define REC 0x1D
#define RXM0SIDH 0x20
#define RXM0SIDL 0x21
#define RXM0EID8 0x22
#define RXM0EID0 0x23
#define RXM1SIDH 0x24
#define RXM1SIDL 0x25
#define RXM1EID8 0x26
#define RXM1EID0 0x27
#define CNF3 0x28
#define CNF2 0x29
#define CNF1 0x2A
#define CANINTE 0x2B
#define MERRE 7
#define WAKIE 6
#define ERRIE 5
#define TX2IE 4
#define TX1IE 3
#define TX0IE 2
#define RX1IE 1
#define RX0IE 0
#define CANINTF 0x2C
#define MERRF 7
#define WAKIF 6
#define ERRIF 5
#define TX2IF 4
#define TX1IF 3
#define TX0IF 2
#define RX1IF 1
#define RX0IF 0
#define EFLG 0x2D
#define TXB0CTRL 0x30
#define TXREQ 3
#define TXB0SIDH 0x31
#define TXB0SIDL 0x32
#define EXIDE 3
#define TXB0EID8 0x33
#define TXB0EID0 0x34
#define TXB0DLC 0x35
#define TXB0D0 0x36
#define RXB0CTRL 0x60
#define RXM1 6
#define RXM0 5
#define RXRTR 3
// Bits 2:0 FILHIT2:0
#define RXB0SIDH 0x61
#define RXB0SIDL 0x62
#define RXB0EID8 0x63
#define RXB0EID0 0x64
#define RXB0DLC 0x65
#define RXB0D0 0x66
//Command Bytes
#define RESET 0xC0
#define READ 0x03
#define READ_RX_BUFFER 0x90
#define WRITE 0x02
#define LOAD_TX_BUFFER 0x40
#define RTS 0x80
#define READ_STATUS 0xA0
#define RX_STATUS 0xB0
#define BIT_MODIFY 0x05
typedef struct{
can_message msg;
volatile unsigned char flags;
}can_message_x;
/* MCP */
void mcp_reset();
void mcp_write(unsigned char reg, unsigned char data);
//void mcp_write_b(unsigned char reg, unsigned char *buf, unsigned char len);
unsigned char mcp_read(unsigned char reg);
//void mcp_read_b(unsigned char reg, unsigned char *buf, unsigned char len);
void mcp_bitmod(unsigned char reg, unsigned char mask, unsigned char val);
unsigned char mcp_status();
//unsigned char mcp_rx_status();
// Functions
/*
unsigned char mcp_rx_status(){
unsigned char d;
spi_set_ss();
spi_data(RX_STATUS);
d = spi_data(0);
spi_clear_ss();
return d;
}
*/
unsigned char mcp_status(){
unsigned char d;
spi_set_ss();
spi_data(READ_STATUS);
d = spi_data(0);
spi_clear_ss();
return d;
}
void mcp_bitmod(unsigned char reg, unsigned char mask, unsigned char val){
spi_set_ss();
spi_data(BIT_MODIFY);
spi_data(reg);
spi_data(mask);
spi_data(val);
spi_clear_ss();
}
//load a message to mcp2515 and start transmission
void message_load(can_message_x * msg){
unsigned char x;
spi_set_ss();
spi_data(WRITE);
spi_data(TXB0SIDH);
spi_data( ((unsigned char)(msg->msg.port_src << 2)) | (msg->msg.port_dst >> 4 ) );
spi_data( (unsigned char)((msg->msg.port_dst & 0x0C) << 3) | (1<<EXIDE) | (msg->msg.port_dst & 0x03) );
spi_data(msg->msg.addr_src);
spi_data(msg->msg.addr_dst);
spi_data(msg->msg.dlc);
for(x=0;x<msg->msg.dlc;x++){
spi_data(msg->msg.data[x]);
}
spi_clear_ss();
spi_set_ss();
spi_data(WRITE);
spi_data(TXB0CTRL);
spi_data( (1<<TXREQ) );
spi_clear_ss();
}
//get a message from mcp2515 and disable RX interrupt Condition
void message_fetch(can_message_x * msg){
unsigned char tmp1, tmp2, tmp3;
unsigned char x;
spi_set_ss();
spi_data(READ);
spi_data(RXB0SIDH);
tmp1 = spi_data(0);
msg->msg.port_src = tmp1 >> 2;
tmp2 = spi_data(0);
tmp3 = (unsigned char)((unsigned char)(tmp2 >> 3) & 0x0C);
msg->msg.port_dst = ((unsigned char)(tmp1 <<4 ) & 0x30) | tmp3 | (unsigned char)(tmp2 & 0x03);
msg->msg.addr_src = spi_data(0);
msg->msg.addr_dst = spi_data(0);
msg->msg.dlc = spi_data(0) & 0x0F;
for(x=0;x<msg->msg.dlc;x++){
msg->msg.data[x] = spi_data(0);
}
spi_clear_ss();
mcp_bitmod(CANINTF, (1<<RX0IF), 0x00);
}
#ifdef CAN_INTERRUPT
static can_message_x RX_BUFFER[CAN_RX_BUFFER_SIZE], TX_BUFFER[CAN_TX_BUFFER_SIZE];
unsigned char RX_HEAD=0;volatile unsigned char RX_TAIL=0;
unsigned char TX_HEAD= 0;volatile unsigned char TX_TAIL=0;
static volatile unsigned char TX_INT;
SIGNAL(SIG_INTERRUPT0) {
unsigned char status = mcp_status();
if ( status & 0x01 ) { // Message in RX0
if ( !(((can_message_x*)&RX_BUFFER[RX_HEAD])->flags & 0x01) ) {
message_fetch(&RX_BUFFER[RX_HEAD]);
RX_BUFFER[RX_HEAD].flags |= 0x01;//mark buffer as used
if( ++RX_HEAD == CAN_RX_BUFFER_SIZE) RX_HEAD = 0;
}else{
//buffer overflow
//just clear the Interrupt condition, and lose the message
mcp_bitmod(CANINTF, (1<<RX0IF), 0x00);
}
} else if ( status & 0x08 ) { // TX1 empty
if(((can_message_x*)&TX_BUFFER[TX_TAIL])->flags & 0x01) {
((can_message_x*)&TX_BUFFER[TX_TAIL])->flags &= ~0x01;
TX_INT = 1;
message_load(&TX_BUFFER[TX_TAIL]);
if(++TX_TAIL == CAN_TX_BUFFER_SIZE) TX_TAIL = 0;
}else{
TX_INT = 0;
}
mcp_bitmod(CANINTF, (1<<TX0IF), 0x00);
} else {
#ifdef CAN_HANDLEERROR
status = mcp_read(EFLG);
if(status) { // we've got a error condition
can_error = status;
mcp_write(EFLG, 0);
}
#endif // CAN_HANDLEERROR
}
}
#endif
void mcp_reset(){
spi_set_ss();
spi_data(RESET);
spi_clear_ss();
}
void mcp_write(unsigned char reg, unsigned char data){
spi_set_ss();
spi_data(WRITE);
spi_data(reg);
spi_data(data);
spi_clear_ss();
}
/*
void mcp_write_b(unsigned char reg, unsigned char *buf, unsigned char len){
unsigned char x;
spi_set_ss();
spi_data(WRITE);
spi_data(reg);
for(x=0;x<len;x++){
spi_data(buf[x]);
}
spi_clear_ss();
}
*/
unsigned char mcp_read(unsigned char reg){
unsigned char d;
spi_set_ss();
spi_data(READ);
spi_data(reg);
d = spi_data(0);
spi_clear_ss();
return d;
}
/*
void mcp_read_b(unsigned char reg, unsigned char *buf, unsigned char len){
unsigned char x;
spi_set_ss();
spi_data(READ);
spi_data(reg);
for(x=0;x<len;x++){
buf[x] = spi_data(0);
}
spi_clear_ss();
}
*/
/* Management */
void can_setmode( can_mode_t mode ) {
unsigned char val = mode << 5;
val |= 0x04; // CLKEN
mcp_write( CANCTRL, val );
}
void can_setfilter() {
//RXM1 RXM0
// 0 0 receive matching filter
// 0 1 " only 11bit Identifier
// 1 0 " only 29bit Identifier
// 1 1 any
mcp_write(RXB0CTRL, (1<<RXM1) | (1<<RXM0));
}
void can_setled(unsigned char led, unsigned char state){
mcp_bitmod(BFPCTRL, 0x10<<led, state?0xff:0);
}
/*******************************************************************/
void delayloop(){
unsigned char x;
for(x=0;x<255;x++){
asm ("nop");
}
}
void can_init(){
//set Slave select high
SPI_PORT |= (1<<SPI_PIN_SS);
#ifdef CAN_INTERRUPT
unsigned char x;
for(x=0;x<CAN_RX_BUFFER_SIZE;x++){
RX_BUFFER[x].flags = 0;
}
for(x=0;x<CAN_TX_BUFFER_SIZE;x++){
TX_BUFFER[x].flags = 0;
}
#endif
#ifdef CAN_HANDLEERROR
can_error = 0;
#endif
mcp_reset();
delayloop();
mcp_write(BFPCTRL,0x0C);//RXBF Pins to Output
// 0x01 : 125kbit/8MHz
// 0x03 : 125kbit/16MHz
// 0x04 : 125kbit/20MHz
#if F_MCP == 16000000
#define CNF1_T 0x03
#elif F_MCP == 8000000
#define CNF1_T 0x01
#elif F_MCP == 20000000
#define CNF1_T 0x04
#else
#error Can Baudrate is only defined for 8, 16 and 20 MHz
#endif
mcp_write( CNF1, 0x40 | CNF1_T );
mcp_write( CNF2, 0xf1 );
mcp_write( CNF3, 0x05 );
// configure IRQ
// this only configures the INT Output of the mcp2515, not the int on the Atmel
mcp_write( CANINTE, (1<<RX0IE) | (1<<TX0IE) );
can_setfilter();
can_setmode(normal);
#ifdef CAN_INTERRUPT
// configure IRQ
// this only configures the INT Output of the mcp2515, not the int on the Atmel
mcp_write( CANINTE, (1<<RX0IE) | (1<<TX0IE) );
#ifdef __C64__
#error not implemented yet
#elif ATMEGA
//this turns on INT0 on the Atmega
GICR |= (1<<INT0);
#else
//this turns on INT0 on the Atmel
MCUCR |= (1<<ISC01);
GIMSK |= (1<<INT0);
#endif //ATMEGA
#else //CAN_INTERRUPT
// configure IRQ
// this only configures the INT Output of the mcp2515, not the int on the Atmel
mcp_write( CANINTE, (1<<RX0IE) ); //only turn RX int on
#endif //CAN_INTERRUPT
}
#ifdef CAN_INTERRUPT
//returns next can message in buffer, or 0 Pointer if buffer is empty
can_message * can_get_nb(){
can_message_x *p;
if(RX_HEAD == RX_TAIL){
return 0;
}else{
p = &RX_BUFFER[RX_TAIL];
if(++RX_TAIL == CAN_RX_BUFFER_SIZE) RX_TAIL = 0;
return &(p->msg);
}
}
can_message * can_get(){
can_message_x *p;
while(RX_HEAD == RX_TAIL) { };
p = &RX_BUFFER[RX_TAIL];
if(++RX_TAIL == CAN_RX_BUFFER_SIZE) RX_TAIL = 0;
return &(p->msg);
}
//marks a receive buffer as unused again so it can be overwritten in Interrupt
void can_free(can_message * msg){
can_message_x * msg_x = (can_message_x *) msg;
msg_x->flags = 0;
}
//returns pointer to the next can TX buffer
can_message * can_buffer_get(){
can_message_x *p;
p = &TX_BUFFER[TX_HEAD];
while (p->flags&0x01); //wait until buffer is free
if(++TX_HEAD == CAN_TX_BUFFER_SIZE) TX_HEAD = 0;
return &(p->msg);
}
//start transmitting can messages, and mark message msg as transmittable
void can_transmit(can_message* msg2){
can_message_x* msg=(can_message_x*) msg2;
if(msg){
msg->flags |= 0x01;
}
if(!TX_INT){
if(((can_message_x*)&TX_BUFFER[TX_TAIL])->flags & 0x01){
((can_message_x*)&TX_BUFFER[TX_TAIL])->flags &= ~0x01;
TX_INT = 1;
message_load(&TX_BUFFER[TX_TAIL]);
if(++TX_TAIL == CAN_TX_BUFFER_SIZE) TX_TAIL = 0;
}
}
}
#else // NON INTERRUPT VERSION
can_message_x RX_MESSAGE, TX_MESSAGE;
can_message * can_get_nb(){
//check the pin, that the MCP's Interrup output connects to
if(SPI_REG_PIN_MCP_INT & (1<<SPI_PIN_MCP_INT)){
return 0;
}else{
//So the MCP Generates an RX Interrupt
message_fetch(&RX_MESSAGE);
return &(RX_MESSAGE.msg);
}
}
can_message * can_get(){
//wait while the MCP doesn't generate an RX Interrupt
while(SPI_REG_PIN_MCP_INT & (1<<SPI_PIN_MCP_INT)) { };
message_fetch(&RX_MESSAGE);
return &(RX_MESSAGE.msg);
}
//only for compatibility with Interrupt driven Version
can_message * can_buffer_get(){
return &(TX_MESSAGE.msg);
}
void can_transmit(can_message * msg){
message_load((can_message_x*)msg);
}
void can_free(can_message * msg){
}
#endif

139
can/can.h

@ -0,0 +1,139 @@
#ifndef CAN_H
#define CAN_H
/*****************************************************************************
* Simple CAN Library
*
* #define CAN_INTERRUPT 1 //set this to enable interrupt driven
* and buffering version
* #define CAN_RX_BUFFER_SIZE 2 //only used for Interrupt
* #define CAN_TX_BUFFER_SIZE 2 //only used for Interrupt
*/
/*****************************************************************************
* Types
*/
#include <stdint.h>
typedef unsigned char can_addr;
typedef unsigned char can_port;
typedef uint16_t can_channel_t;
typedef uint8_t can_subchannel_t;
typedef struct
{
uint32_t id;
uint8_t dlc;
uint8_t data[8];
} can_message_raw;
typedef struct{
can_addr addr_src;
can_addr addr_dst;
can_port port_src;
can_port port_dst;
unsigned char dlc;
unsigned char data[8];
}can_message;
typedef struct
{
can_channel_t channel;
can_subchannel_t subchannel;
can_addr addr_src;
can_addr addr_dst;
uint8_t dlc;
uint8_t data[8];
} can_message_v2;
typedef enum { normal, mode_sleep, loopback, listenonly, config } can_mode_t ;
/*****************************************************************************
* Global variables
*/
#ifdef CAN_HANDLEERROR
extern unsigned char can_error;
#endif
/*****************************************************************************
* Management
*/
void can_init();
void can_setfilter();
void can_setmode(can_mode_t);
void can_setled(unsigned char led, unsigned char state);
/*****************************************************************************
* Sending
*/
can_message * can_buffer_get();
void can_transmit( can_message *msg );
/*****************************************************************************
* Receiving
*/
can_message *can_get();
can_message *can_get_nb();
// this is only needed for Interrupt driven Version
#ifndef CAN_INTERRUPT
// # define can_free(m)
void can_free(can_message * msg);
#else
void can_free(can_message * msg);
#endif
/*****************************************************************************
* Sending
*/
can_message_raw * can_buffer_get_raw();
void can_transmit_raw( can_message_raw *msg );
/*****************************************************************************
* Receiving
*/
can_message_raw *can_get_raw();
can_message_raw *can_get_raw_nb();
// this is only needed for Interrupt driven Version
#ifndef CAN_INTERRUPT
// # define can_free(m)
void can_free_raw(can_message_raw * msg);
#else
void can_free_raw(can_message_raw * msg);
#endif
/*****************************************************************************
* Sending
*/
void can_transmit_v2( can_message_v2 *msg );
/*****************************************************************************
* Receiving
*/
can_message_v2 *can_get_v2_nb();
void can_free_v2(can_message_v2 *msg);
#endif

55
can/spi.c

@ -0,0 +1,55 @@
#include <avr/io.h>
#include "spi.h"
void spi_init(){
//set output SPI pins to output
SPI_DDR |= (1<<SPI_PIN_MOSI) | (1<<SPI_PIN_SCK) | (1<<SPI_PIN_SS);
#ifdef SPI_HARDWARE
// 0 1
//DORD msb first lsb first
//CPOL low idle high idle
//CPHA rising edge fallling edge
//SPR0 SPR1
// 0 0 ck/4
// 0 1 ck/16
// 1 0 ck/64
// 1 1 ck/128
//Interrupt disable, SPI enable, MSB first, master, clk low idle, data valid on rising edge, ck/4
SPCR = (0<<SPIE) | (1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);
//Double speed on
SPSR = (1<<SPI2X);
#endif
}
#ifndef SPI_HARDWARE
unsigned char spi_data(unsigned char c){
unsigned char x, d=d;
for(x=0;x<8;x++){
if(c & 0x80){
SPI_PORT |= (1<<SPI_PIN_MOSI);
}else{
SPI_PORT &= ~(1<<SPI_PIN_MOSI);
}
SPI_PORT |= (1<<SPI_PIN_SCK);
d<<=1;
if(SPI_PIN & (1<<SPI_PIN_MISO)){
d|=1;
}
SPI_PORT &= ~(1<<SPI_PIN_SCK);
c<<=1;
}
return d;
}
#else
unsigned char spi_data(unsigned char c) {
SPDR = c;
while(!(SPSR & (1<<SPIF)));
c = SPDR;
return (c);
}
#endif

28
can/spi.h

@ -0,0 +1,28 @@
#ifndef SPI_H
#define SPI_H
#include "config.h"
/**
* this enables the use of Hardware SPI on ATMEGA
*
* #define SPI_HARDWARE 1
* #define SPI_PORT PORTB
* #define SPI_PIN PINB
* #define SPI_DDR DDRB
*
* #define SPI_PIN_MOSI PB5
* #define SPI_PIN_MISO PB6
* #define SPI_PIN_SCK PB7
* #define SPI_PIN_SS PB4
*
*/
void spi_init();
unsigned char spi_data(unsigned char c);
#endif

57
config.h

@ -0,0 +1,57 @@
#ifndef CONFIG_H_
#define CONFIG_H_
#include "autoconf.h"
#define STREAMER_NUM 30
#define FEUER_N 5
#define FEUER_S 30
#define FEUER_DIV 44
#define FEUER_DELAY 50
#define SNAKE_DELAY 100
//#define SCROLLTEXT_STRING_SIZE 128
//#define SCROLLTEXT_FONT font_arial8
//#define SCROLLTEXT_DEFAULT "</#www.das-labor.org"
//#define SCROLL_X_SPEED 20
//#define SCROLL_Y_SPEED 20
#define BORG_CAN
// spi.[ch] defines
#define SPI_HARDWARE
#define SPI_PORT PORTB //for slave select
#define SPI_PIN PINB //for slave select
#define SPI_DDR DDRB
#define SPI_PIN_MOSI PB5
#define SPI_PIN_MISO PB6
#define SPI_PIN_SCK PB7
#define SPI_PIN_SS PB4 // for slave select
//interrupt pin of MCP2515 for non interrupt driven can
#define SPI_REG_PIN_MCP_INT PIND
#define SPI_PIN_MCP_INT PD2
// can.[ch] defines
#undef CAN_INTERRUPT //set this to enable interrupt driven and buffering version
#define CAN_RX_BUFFER_SIZE 2 //only used for Interrupt
#define CAN_TX_BUFFER_SIZE 2 //only used for Interrupt
#define F_MCP F_CPU
#define INIT_EEPROM
//#define UART_BAUD_RATE 115200L
#define REVERSED_HARDWARE
//#define INVERSE_ROWS
//#define INTERLACED_ROWS
//#define INTERLACED_COLS
#endif /* CONFIG_H_ */

58
config.in

@ -0,0 +1,58 @@
mainmenu_name "Borg Configuration"
###################### General Setup Menu #####################################
mainmenu_option next_comment
comment "General Setup"
#bool 'Prompt for experimental code' CONFIG_EXPERIMENTAL
choice 'Target MCU' \
"ATmega8 atmega8 \
ATmega32 atmega32 \
ATmega644 atmega644 \
ATmega644p atmega644p" \
'ATmega32' MCU
int "MCU frequency" FREQ 16000000
endmenu
###############################################################################
###################### Borg Hardware Menu #####################################
source borg_hw/config.in
###############################################################################
mainmenu_option next_comment
comment "Features"
bool "prng random number generator" RANDOM_SUPPORT y
endmenu
########################## Scrolltext Menu ####################################
source scrolltext/config.in
###############################################################################
######################### Animations Menu #####################################
mainmenu_option next_comment
comment "Animations"
comment "selects which animations are displayed in main loop"
dep_bool "Scrolltext" ANIMATION_SCROLLTEXT $SCROLLTEXT_SUPPORT
bool "Spirale" ANIMATION_SPIRALE
bool "Joern1" ANIMATION_JOERN1
bool "Snake" ANIMATION_SNAKE
bool "Schachbrett" ANIMATION_SCHACHBRETT
bool "Feuer" ANIMATION_FEUER
bool "Matrix" ANIMATION_MATRIX
bool "Random bright" ANIMATION_RANDOM_BRIGHT
bool "Game of Life" ANIMATION_GAMEOFLIFE
comment "Special Animations"
bool "Test Animations" ANIMATION_TESTS
bool "Display off mode" ANIMATION_OFF
endmenu
###############################################################################

70
defaults.mk

@ -0,0 +1,70 @@
# ethersex project specific defaults, each can be overridden in config.mk
F_CPU = 20000000UL
MCU = atmega644
CC=avr-gcc
AR=avr-ar
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
AS = avr-as
CP = cp
RM = rm -f
AVRDUDE = avrdude
AVRDUDE_BAUDRATE = 115200
SIZE = avr-size
STRIP = avr-strip
HOSTCC := gcc
export HOSTCC
# flags for the compiler
CPPFLAGS += -mmcu=$(MCU)
CFLAGS ?= -Wall -W -Wno-unused-parameter -Wno-sign-compare
CFLAGS += -g -Os -std=gnu99 -fgnu89-inline
# flags for the linker
LDFLAGS += -mmcu=$(MCU)
##############################################################################
# the default target
$(TARGET):
##############################################################################
# include user's config.mk file
$(TOPDIR)/config.mk:
@echo "# Put your own config here!" > $@
@echo "#F_CPU = $(F_CPU)" >> $@
@echo "#MCU = $(MCU)" >> $@
@echo "created default config.mk, tune your settings there!"
-include $(TOPDIR)/config.mk
##############################################################################
# configure load address for bootloader, if enabled
#
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),mrproper)
ifneq ($(MAKECMDGOALS),menuconfig)
include $(TOPDIR)/.config
CPPFLAGS += -DF_CPU=$(FREQ)UL -mmcu=$(MCU)
endif # MAKECMDGOALS!=menuconfig
endif # MAKECMDGOALS!=mrproper
endif # MAKECMDGOALS!=clean
ifeq ($(BOOTLOADER_SUPPORT),y)
LDFLAGS += -Wl,--section-start=.text=0xE000
CFLAGS += -mcall-prologues
endif
%.s: %.c
$(CC) -o $@ -O0 $(CPPFLAGS) -S $<
%.E: %.c
$(CC) -o $@ -O0 $(CPPFLAGS) -C -E -dD $<

32
depend.mk

@ -0,0 +1,32 @@
# How to build automatic dependencies
# Don't include dependencies if $(no_deps) is set; the master makefile
# does this for clean and other such targets that don't need
# dependencies. That then avoids rebuilding dependencies.
ifneq ($(no_deps),t)
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),mrproper)
ifneq ($(MAKECMDGOALS),menuconfig)
# For each .o file we need a .d file.
-include $(subst .o,.d,$(filter %.o,$(OBJECTS))) /dev/null
endif
endif
endif
endif
# Here is how to build those dependency files
define make-deps
set -e; $(CC) $(CFLAGS) $(CPPFLAGS) -M -MM $< | \
sed > $@.new -e 's;$(*F)\.o:;$@ $*.o $*.E $*.s:;' \
-e 's% [^ ]*/gcc-lib/[^ ]*\.h%%g'
if test -s $@.new; then mv -f $@.new $@; else rm -f $@.new; fi
endef
# Here is how to make .d files from .c files
%.d: %.c $(TOPDIR)/pinning.c; $(make-deps)
%.d: %.S ; $(make-deps)

14
eeprom_reserve.c

@ -0,0 +1,14 @@
/*
*
*
*
*
*
*/
#include <avr/eeprom.h>
#include <stdint.h>
uint8_t EEMEM do_not_use;

115
games/invader_draw.c

@ -0,0 +1,115 @@
#include "invaders2.h"
/*----------------------getter/setter----------------------------*/
unsigned char getInvaderPixel(Invaders * iv, unsigned char x, unsigned char y)
{
if (((x - iv->pos.x) < MAX_INVADER_WIDTH) && ((x - iv->pos.x) >= 0) && ((y
- iv->pos.y) < MAX_INVADER_HEIGHT) && ((y - iv->pos.y) >= 0))
{
return iv->map[x - iv->pos.x][y - iv->pos.y];
}
return 0;
}
void setInvaderPixel(Invaders * iv, unsigned char x, unsigned char y,
unsigned char val)
{
if (((x - iv->pos.x) < MAX_INVADER_WIDTH) && ((x - iv->pos.x) >= 0) && ((y
- iv->pos.y) < MAX_INVADER_HEIGHT) && ((y - iv->pos.y) >= 0))
{
iv->map[x - iv->pos.x][y - iv->pos.y] = val;
}
}
unsigned char getGuardPixel(unsigned char guards[BORG_WIDTH], unsigned char x,
unsigned char y)
{
if (x < BORG_WIDTH && y == GUARD_LINE)
return guards[x];
return 0;
}
void setGuardPixel(unsigned char guards[BORG_WIDTH], unsigned char x,
unsigned char y, unsigned char val)
{
if (x < BORG_WIDTH && y == GUARD_LINE && val <= 3)
guards[x] = val;
}
/*----------------------drawing Method---------------------------*/
void draw(Invaders * iv, Spaceship * sc, Player * pl, Cannon * cn,
unsigned char guards[BORG_WIDTH], uPixel st[MAX_SHOTS], uPixel * shot)
{
clearScreen ();
int x, y;
/*---SPACESHIP---*/
if (sc->pos < RIGHT_BORDER)
{
setPixel (sc->pos, SPACESHIP_LINE, sc->lives);
}
if (sc->pos - 1 < RIGHT_BORDER)
{
setPixel (sc->pos + 1, SPACESHIP_LINE, sc->lives);
}
/*---INVADERS--*/
for (y = 0; y < MAX_INVADER_HEIGHT; y++)
{
for (x = 0; x < MAX_INVADER_WIDTH; x++)
{
//mal in oder statement umwandeln ;-)
if (iv->map[x][y] == 0)
continue;
if (x + iv->pos.x > RIGHT_BORDER)
continue;
if (x + iv->pos.x < 0)
continue;
setPixel (x + iv->pos.x, y + iv->pos.y, iv->map[x][y]);
}
}
/*---GUARDS---*/
for (x = 0; x < BORG_WIDTH; ++x)
{
if (guards[x] != 0)
{
setPixel (x, GUARD_LINE, guards[x]);
}
}
/*---SHOTS--*/
int i;
for (i = 0; i < MAX_SHOTS; ++i)
{
if (st[i].x < BORG_WIDTH && st[i].y < BORG_HEIGHT)
{
setPixel (st[i].x, st[i].y, 3);
}
}
/*draw player shot */
if (!(cn->ready))
{
setPixel (shot->x, shot->y, 3);
}
/*-- CANNON --*/
if (cn->pos >= LEFT_BORDER + 1)
{
setPixel (cn->pos - 1, 15, pl->lives);
}
if (cn->pos < BORG_WIDTH)
{
setPixel (cn->pos, 15, pl->lives);
setPixel (cn->pos, 14, pl->lives);
}
if (cn->pos < RIGHT_BORDER)
{
setPixel (cn->pos + 1, 15, pl->lives);
}
}

153
games/invader_init.c

@ -0,0 +1,153 @@
#include "invaders2.h"
unsigned char peter[8][11] =
{
{ 0, 0, P, 0, 0, 0, 0, 0, P, 0, 0 },
{ 0, 0, 0, P, 0, 0, 0, P, 0, 0, 0 },
{ 0, 0, P, P, P, P, P, P, P, 0, 0 },
{ 0, P, P, 0, P, P, P, 0, P, P, 0 },
{ P, P, P, P, P, P, P, P, P, P, P },
{ P, 0, P, P, P, P, P, P, P, 0, P },
{ P, 0, P, 0, 0, 0, 0, 0, P, 0, P },
{ 0, 0, 0, P, P, 0, P, P, 0, 0, 0 } };
unsigned char hans[8][11] =
{
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 2, 1, 1, 2, 2, 2, 1, 2, 2, 1 },
{ 1, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2 },
{ 1, 2, 1, 1, 2, 2, 2, 1, 2, 2, 1 },
{ 1, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2 },
{ 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 2 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
void initGuards(unsigned char guards[BORG_WIDTH])
{
int x;
for (x = 0; x < BORG_WIDTH; ++x)
{
guards[x] = 0;
}
guards[3] = 3;
guards[6] = 3;
guards[10] = 3;
guards[13] = 3;
}
void initInvaders(Invaders * iv, unsigned char lv)
{
unsigned char x, y;
// first zero out map!
for (x = 0; x < MAX_INVADER_WIDTH; ++x)
{
for (y = 0; y < MAX_INVADER_HEIGHT; ++y)
{
iv->map[x][y] = 0;
}
}
iv->speedinc = 0;
iv->isEdged = 0;
switch (lv)
{
case 0:
for (x = 0; x < 8; ++x)
{
iv->map[x][0] = 2;
iv->map[x][1] = 2;
iv->map[x][2] = 2;
iv->map[x][3] = 1;
// iv->map[x][4] = 1;
}
iv->pos.x = 4;
iv->pos.y = SPACESHIP_LINE + 1;
iv->speed = MIN_SPEED - 3;
iv->direction = 1;
break;
case 1:
for (x = 0; x < 8; ++x)
{
//for(y = 0; y < MAX_INVADER_HEIGHT; ++y) {
iv->map[x][0] = 3;
iv->map[x][1] = 3;
iv->map[x][2] = 2;
iv->map[x][3] = 2;
// iv->map[x][4] = 1;
//}
}
iv->pos.x = 4;
iv->pos.y = SPACESHIP_LINE + 1;
iv->speed = MIN_SPEED - 2;
iv->direction = 1;
break;
case 2:
for (x = 0; x < 8; ++x)
{
//for(y = 0; y < MAX_INVADER_HEIGHT; ++y) {
iv->map[x][0] = 3;
iv->map[x][1] = 3;
iv->map[x][2] = 2;
iv->map[x][3] = 2;
iv->map[x][4] = 1;
//}
}
iv->pos.x = 4;
iv->pos.y = SPACESHIP_LINE + 1;
iv->speed = MIN_SPEED - 1;
iv->direction = 1;
break;
case 3:
for (x = 0; x < 11; ++x)
{
for (y = 0; y < 8; ++y)
{
if (hans[y][x] != 0)
{
iv->map[x][y] = 2;
}
}
}
iv->pos.x = 3;
iv->pos.y = SPACESHIP_LINE + 1;
iv->speed = MIN_SPEED + 2;
iv->direction = 1;
break;
case 4:
for (x = 0; x < 11; ++x)
{
for (y = 0; y < 8; ++y)
{
if (peter[y][x] != 0)
{
iv->map[x][y] = 2;
}
}
}
iv->pos.x = 3;
iv->pos.y = SPACESHIP_LINE + 1;
iv->speed = MIN_SPEED + 3;
iv->direction = 1;
break;
}
}

304
games/invader_proc.c

@ -0,0 +1,304 @@
#include <stdlib.h>
#include "prng.h"
#include "invaders2.h"
void procCannon(Cannon * cn, uPixel * shot)
{
static unsigned char mv = 0;
if (mv >= CANNON_SPEED)
{
mv = 0;
if (JOYISLEFT)
{
if (cn->pos != RIGHT_BORDER)
{
cn->pos++;
}
}
else if (JOYISRIGHT)
{
if (cn->pos != LEFT_BORDER)
{
cn->pos--;
}
}
else if (JOYISFIRE)
{
if (cn->ready)
{
shot->x = cn->pos;
shot->y = 14;
cn->ready = 0;
}
}
}
else
{
mv++;
}
}
unsigned char areAtBorder(Invaders * iv)
{
int y;
for (y = SPACESHIP_LINE + 1; y <= GUARD_LINE; ++y)
{
if (getInvaderPixel(iv, LEFT_BORDER, y) || getInvaderPixel(iv,
RIGHT_BORDER, y))
{
return 1;
}
}
return 0;
}
void procInvaders(Invaders * iv, uPixel st[MAX_SHOTS])
{
static unsigned char mv = 0;
if (mv >= iv->speed)
{
mv = 0;
if (areAtBorder(iv) && !(iv->isEdged))
{
iv->pos.y++;
iv->direction = -iv->direction;
iv->isEdged = 1;
}
else
{
iv->pos.x += iv->direction;
iv->isEdged = 0;
}
}
mv++;
unsigned char i, y;
unsigned char spos = random8() % 16;
if (spos >= BORG_WIDTH)
return;
unsigned char shoot = random8();
if (shoot < SHOOTING_RATE)
{
for (i = 0; i < MAX_SHOTS; ++i)
{
if (st[i].x > BORG_WIDTH || st[i].y > BORG_HEIGHT)
{
for (y = GUARD_LINE; y > SPACESHIP_LINE; --y)
{
if (getInvaderPixel(iv, spos, y) != 0)
{
st[i].x = spos;
st[i].y = y + 1;
return;
}
}
}
} //for SHOTS
}
}
void procShots(Invaders * iv, Player * pl, Cannon * cn, Spaceship * sc,
unsigned char guards[BORG_WIDTH], uPixel st[MAX_SHOTS], uPixel * shot)
{
int i;
static unsigned char cmv = 0, imv = 0;
// shuß mit einen struct mit dem shuß!!
if (cmv >= CANNON_SHOOTING_SPEED)
{
cmv = 0;
if (!(cn->ready))
{
shot->y--;
}
if (shot->y > BORG_HEIGHT)
{
cn->ready = 1;
}
}
if (imv >= INVADER_SHOOTING_SPEED)
{
imv = 0;
for (i = 0; i < MAX_SHOTS; ++i)
{
if ( /*st[i].x < BORG_WIDTH && */st[i].y < BORG_HEIGHT)
{
st[i].y++;
}
}
}
cmv++;
imv++;
/****************************************************************/
/* TESTE OB GETROFFEN */
/****************************************************************/
// USER CANNON
unsigned char tmp;
if (!(cn->ready))
{
for (i = 0; i < MAX_SHOTS; ++i)
{
if (shot->x == st[i].x && shot->y == st[i].y)
{
st[i].x = 255;
st[i].y = 255;
cn->ready = 1;
}
}
//GUARDS
if ((tmp = getGuardPixel(guards, shot->x, shot->y)))
{
--tmp;
setGuardPixel(guards, shot->x, shot->y, tmp);
cn->ready = 1;
goto invader_shots;
}
//INVADER
if ((tmp = getInvaderPixel(iv, shot->x, shot->y)))
{
--tmp;
setInvaderPixel(iv, shot->x, shot->y, tmp);
if (tmp == 0)
{
iv->speedinc++;
if (iv->speedinc == SPEED_INC_RATE)
{
iv->speedinc = 0;
iv->speed -= SPEED_INC_VALUE;
}
pl->points += POINTS_FOR_KILL;
}
else
{
pl->points += POINTS_FOR_HIT;
}
cn->ready = 1;
goto invader_shots;
}
//SPACESHIP
if (shot->y == SPACESHIP_LINE)
{
if (shot->x == sc->pos || shot->x == sc->pos + 1)
{
sc->pos = 255;
pl->points += POINTS_FOR_SPACESHIP;
cn->ready = 1;
goto invader_shots;
}
}
} // !(cn->ready)
invader_shots: for (i = 0; i < MAX_SHOTS; ++i)
{
if ((tmp = getGuardPixel(guards, st[i].x, st[i].y)))
{
--tmp;
setGuardPixel(guards, st[i].x, st[i].y, tmp);
st[i].x = 255;
st[i].y = 255;
}
if (st[i].y == BORG_HEIGHT - 1)
{
if (st[i].x == cn->pos)
{
pl->lives--;
st[i].x = 255;
st[i].y = 255;
}
}
}
}
void procSpaceship(Spaceship * sc)
{
unsigned char rnd1 = random8();
unsigned char rnd2 = random8();
static unsigned char sct = 0;
if (sc->pos > RIGHT_BORDER)
{
if (rnd1 == 73)
{
if (rnd2 >= 200)
{
sc->pos = RIGHT_BORDER;
sct = 0;
}
}
}
else
{
if (sct == SPACESHIP_SPEED)
{
sct = 0;
if (sc->pos == 0)
{
sc->pos = 255;
}
else
{
sc->pos--;
}
}
}
sct++;
}
unsigned char getStatus(Invaders * iv)
{
//count Invader!
unsigned char x, y, inv = 0;
for (x = 0; x < MAX_INVADER_WIDTH; ++x)
{
for (y = 0; y < MAX_INVADER_HEIGHT; ++y)
{
if (iv->map[x][y] != 0)
inv++;
}
}
//LEVEL BEREINIGT
if (inv == 0)
return 1;
//INVADERS REACHED EARTH
for (x = 0; x < BORG_WIDTH; ++x)
{
if (getInvaderPixel(iv, x, GUARD_LINE + 1))
return 2;
}
return 0;
}

134
games/invaders2.c

@ -0,0 +1,134 @@
#include <stdio.h>
#include "util.h"
#include "invaders2.h"
//#include <stdio.h>
#ifndef __AVR__
#define wait(_X) myWait(_X)
#endif
void borg_invaders()
{
// waitForFire = 0;
/****************************************************************/
/* INITIALIZE */
/****************************************************************/
Invaders iv;
Cannon cn;
Player pl;
Spaceship sc;
unsigned char guards[BORG_WIDTH];
unsigned char level = 0;
unsigned char ivStatus = 0;
uPixel st[MAX_SHOTS] =
{
{ 255, 255},
{ 255, 255},
{ 255, 255},
{ 255, 255},
{ 255, 255}
};
uPixel shot;
// = {0,0};
pl.points = 0;
pl.lives = 3;
//--------Init Cannon-------//
//cn.pos = 4;
//cn.ready = 1;
/****************************************************************/
/* INTRO */
/****************************************************************/
//drawIntroScreen(2000);
/****************************************************************/
/* GAME LOOP */
/****************************************************************/
do
{
//----- INITIALIZE LEVEL-----//
initGuards(guards);
initInvaders(&iv, level);
//Spaceship
sc.lives = 1;
sc.pos = 255;
//Cannon
cn.pos = 7;
cn.ready = 1;
draw(&iv, &sc, &pl, &cn, guards, st, &shot);
while (1)
{
procInvaders(&iv, st);
procSpaceship(&sc);
procShots(&iv, &pl, &cn, &sc, guards, st, &shot);
procCannon(&cn, &shot);
draw(&iv, &sc, &pl, &cn, guards, st, &shot);
ivStatus = getStatus(&iv);
if (ivStatus == 2) //LOST
{
//pl.lives--;
pl.lives = 0;
break;
}
else if (ivStatus == 1) //WON
{
unsigned int bonus= POINTS_FOR_LEVEL * (level + 1) * (12 - iv.pos.y);
pl.points += bonus;
//printf("cleared l: %d , y: %d bonus: %d \n",
// level, iv.pos.y, bonus);
if (level == MAX_LEVEL - 1)
{
level = 0;
}
else
{
level = (level + 1);
}
break;
}
if (pl.lives <= 0)
{
//scrolltext("GAME OVER",0,80);
break;
}
wait (WAIT_MS);
} //IN LEVEL LOOP
} while (pl.lives > 0); //GAME LOOP
clearScreen ();
//wait(5000);
char text[64];
snprintf(text, 64, "</#points: %u", pl.points);
scrolltext(text);
//printf("scores: %d\n", pl.points);
/****************************************************************/
/* PLAYER STAT */
/* HIGH SCORES */
/****************************************************************/
// waitForFire = 1;
}

182
games/invaders2.h

@ -0,0 +1,182 @@
/* Space INVADERS V0.2
*
* by: Fabian Bremerich
* Thanx to: Peter F.
*
* date: Mi, 08.03.2006
*
*/
#ifndef INVADERS2_H
#define INVADERS2_H
#define USE_ORIGINAL_PIXEL_API
/*CONNECTION TO SIMULATOR*/
//extern char fkey;
/* TEST PARTS NEW API */
typedef struct
{
signed char x;
signed char y;
} sPixel;
typedef struct
{
unsigned char x;
unsigned char y;
} uPixel;
//for compatibility to pisel.h api!
#ifdef USE_ORIGINAL_PIXEL_API
#include "pixel.h"
#include "scrolltext.h"
#include "joystick.h"
//typedef uPixel pixel;
#define uPixel pixel
//#define getPixel(_X, _Y) get_pixel( (pixel){_X, _Y})
#define clearScreen() clear_screen(0)
//#define
//#ifdef SIMULATOR
#define setPixel(_X, _Y, _V) setpixel( (pixel){_X, _Y}, _V)
//#else //if defined (AVR)
//#define setPixel(_X, _Y, _V) reverseSetPixel( (pixel){_X, _Y}, _V)
//#endif
#endif
/****************************************************************/
/* GLOBALE VAR */
/****************************************************************/
#define P 3
extern unsigned char peter[8][11];
extern unsigned char hans[8][11];
/****************************************************************/
/* DEFINES */
/****************************************************************/
#define START_LIVES 3
#define SPACESHIP_LINE 1
//#define SPACESHIP_TRIGGER_POINTS 250
//#define SPACESHIP_TRIGGER_RATE 333
#define GUARD_LINE 13
#define BORG_WIDTH 16
#define BORG_HEIGHT 16
#ifdef SWITCHED_SIDE
#define RIGHT_BORDER 0
#define LEFT_BORDER (BORG_WIDTH -1 )
#else
#define RIGHT_BORDER (BORG_WIDTH -1 )
#define LEFT_BORDER 0
#endif
#define MAX_INVADER_HEIGHT 8
#define MAX_INVADER_WIDTH 12
#define MAX_INVADER_LIVES 3
#define POINTS_FOR_HIT 5
#define POINTS_FOR_KILL 25
#define POINTS_FOR_SPACESHIP 75
#define POINTS_FOR_LEVEL 100
#define MAX_SHOTS 7
#define MIN_SPEED 70
#define SPEED_INC_RATE 2
#define SPEED_INC_VALUE 3
#define MAX_LEVEL 5
#define SHOOTING_RATE 6
#define INVADER_SHOOTING_SPEED 10
#define CANNON_SHOOTING_SPEED 4
#define SPACESHIP_SPEED 30
#define CANNON_SPEED 2
#define WAIT_MS 15
//#define WAIT_MS 20
typedef struct
{
unsigned char map[MAX_INVADER_WIDTH][MAX_INVADER_HEIGHT];
sPixel pos;
unsigned char speed;
unsigned char speedinc;
signed char direction;
unsigned char isEdged;
} Invaders;
typedef struct
{
unsigned char pos;
unsigned char lives;
} Spaceship;
typedef struct
{
unsigned char pos;
unsigned char ready;
} Cannon;
//typedef struct {
// unsigned char guards[numGards];
//}
typedef struct
{
signed char lives;
unsigned int points;
} Player;
/****************************************************************/
/* FUNCTIONS */
/****************************************************************/
void borg_invaders();
/*----------------------main_level_funcs-------------------------*/
void procSpaceship(Spaceship * sp);
void procCannon(Cannon * cn, uPixel * shot);
void procInvaders(Invaders * iv, uPixel st[MAX_SHOTS]);
void procShots(Invaders * iv, Player * pl, Cannon * cn, Spaceship * sc,
unsigned char guards[BORG_WIDTH], uPixel st[MAX_SHOTS], uPixel * shot);
unsigned char getStatus(Invaders * iv);
/*----------------------Initialization---------------------------*/
void initGuards(unsigned char guards[BORG_WIDTH]);
void initInvaders(Invaders * iv, unsigned char lv);
//void initSpaceship(Spaceship* sc);
//void initPlayer(Player* pl);
/*----------------------getter/setter----------------------------*/
unsigned char getInvaderPixel(Invaders * iv, unsigned char x, unsigned char y);
void setInvaderPixel(Invaders * iv, unsigned char x, unsigned char y,
unsigned char val);
unsigned char getGuardPixel(unsigned char guards[BORG_WIDTH], unsigned char x,
unsigned char y);
void setGuardPixel(unsigned char guards[BORG_WIDTH], unsigned char x,
unsigned char y, unsigned char val);
/*----------------------drawing Method---------------------------*/
void draw(Invaders * iv, Spaceship * sc, Player * pl, Cannon * cn,
unsigned char guards[BORG_WIDTH], uPixel ishots[MAX_SHOTS],
uPixel * shot);
#endif

19
games/tetris/COPYING

@ -0,0 +1,19 @@
Copyright (c) 2007 Christian Kroll
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.

19
games/tetris/LICENSE

@ -0,0 +1,19 @@
Copyright (c) 2007 Christian Kroll
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.

25
games/tetris/Makefile

@ -0,0 +1,25 @@
LD = avr-ld
all: tetris.o
tetris.o: piece.o playfield.o view.o logic.o input.o
$(LD) -r piece.o playfield.o view.o logic.o input.o -o tetris.o
piece.o: piece.c piece.h
$(MCU_CC) $(CFLAGS) -c piece.c -o piece.o
playfield.o: playfield.c playfield.h piece.h
$(MCU_CC) $(CFLAGS) -c playfield.c -o playfield.o
view.o: view.c view.h logic.h piece.h playfield.h ../config.h ../pixel.h \
../util.h ../scrolltext.h
$(MCU_CC) $(CFLAGS) -c view.c -o view.o
logic.o: logic.c logic.h piece.h playfield.h input.h view.h
$(MCU_CC) $(CFLAGS) -c logic.c -o logic.o
input.o: input.c input.h ../joystick.h ../util.h
$(MCU_CC) $(CFLAGS) -c input.c -o input.o
clean:
rm -rf *.o *.d

400
games/tetris/input.c

@ -0,0 +1,400 @@
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <assert.h>
#include "../joystick.h"
#include "../util.h"
#include "input.h"
/* - the API simulator and the real API have different named wait functions
* - the macro PM helps in reading values from PROGMEM on the AVR arch
*/
#ifdef __AVR__
#include <avr/pgmspace.h>
#define WAIT(ms) wait(ms)
#define PM(value) pgm_read_word(&value)
#else
#define PROGMEM
#define WAIT(ms) myWait(ms)
#define PM(value) (value)
#endif
/***********
* defines *
***********/
// amount of milliseconds that each loop cycle waits
#define TETRIS_INPUT_TICKS 5
// amount of milliseconds the input is ignored after the pause combo has been
// pressed, since it is difficult to release all buttons simultaneously
#define TETRIS_INPUT_PAUSE_TICKS 100
// amount of allowed loop cycles while in pause mode so that the game
// automatically continues after five minutes
#define TETRIS_INPUT_PAUSE_CYCLES 60000
// minimum of cycles in gliding mode
#define TETRIS_INPUT_GLIDE_CYCLES 75
// here you can adjust the delays (in loop cycles) for key repeat
#define TETRIS_INPUT_REPEAT_INITIALDELAY 40
#define TETRIS_INPUT_REPEAT_DELAY 10
// Here you can adjust the amount of loop cycles a command is ignored after
// its button has been released (to reduce joystick chatter)
#define TETRIS_INPUT_CHATTER_TICKS_ROT_CW 24
#define TETRIS_INPUT_CHATTER_TICKS_ROT_CCW 24
#define TETRIS_INPUT_CHATTER_TICKS_LEFT 12
#define TETRIS_INPUT_CHATTER_TICKS_RIGHT 12
#define TETRIS_INPUT_CHATTER_TICKS_DOWN 12
#define TETRIS_INPUT_CHATTER_TICKS_DROP 24
/***************************
* non-interface functions *
***************************/
/* Function: tetris_input_chatterProtect;
* Description: sets an ignore counter to a command specific value if it is 0
* Argument pIn: pointer to an input object
* Argument cmd: the command whose counter should be set
* Return value: void
*/
void tetris_input_chatterProtect (tetris_input_t *pIn,
tetris_input_command_t cmd)
{
// never exceed the index
assert(cmd < TETRIS_INCMD_NONE);
// amount of loop cycles a command is ignored after its button has been
// released (every command has its own counter)
const static uint8_t nInitialIgnoreValue[TETRIS_INCMD_NONE] PROGMEM =
{
TETRIS_INPUT_CHATTER_TICKS_ROT_CW,
TETRIS_INPUT_CHATTER_TICKS_ROT_CCW,
TETRIS_INPUT_CHATTER_TICKS_LEFT,
TETRIS_INPUT_CHATTER_TICKS_RIGHT,
TETRIS_INPUT_CHATTER_TICKS_DOWN,
TETRIS_INPUT_CHATTER_TICKS_DROP,
0, // TETRIS_INCMD_GRAVITY (irrelevant because it doesn't have a button)
0 // TETRIS_INCMD_PAUSE (is a combination of ROT_CW and DOWN)
};
// setting ignore counter according to the predefined array
if (pIn->nIgnoreCmdCounter[cmd] == 0)
{
// if the command isn't TETRIS_INCMD_PAUSE, setting the ignore counter
// is straight forward
if (cmd != TETRIS_INCMD_PAUSE)
{
pIn->nIgnoreCmdCounter[cmd] = PM(nInitialIgnoreValue[cmd]);
}
// TETRIS_INCMD_PAUSE is issued via a combination of the buttons for
// TETRIS_INCMD_ROT_CW and TETRIS_INCMD_DOWN, so we must set their
// ignore counters
else
{
pIn->nIgnoreCmdCounter[TETRIS_INCMD_ROT_CW] =
TETRIS_INPUT_CHATTER_TICKS_ROT_CW;
pIn->nIgnoreCmdCounter[TETRIS_INCMD_DOWN] =
TETRIS_INPUT_CHATTER_TICKS_DOWN;
}
}
// The ignore counter of TETRIS_INCMD_PAUSE is either set to the counter
// value of TETRIS_INCMD_ROT_CW or TETRIS_INCMD_DOWN (whichever is higher).
if ((cmd == TETRIS_INCMD_ROT_CW) || (cmd == TETRIS_INCMD_DOWN))
{
// helper variables (which the compiler hopefully optimizes away)
uint8_t nRotCw = pIn->nIgnoreCmdCounter[TETRIS_INCMD_ROT_CW];
uint8_t nDown = pIn->nIgnoreCmdCounter[TETRIS_INCMD_DOWN];
pIn->nIgnoreCmdCounter[TETRIS_INCMD_PAUSE] =
(nRotCw > nDown ? nRotCw : nDown);
}
}
/* Function: tetris_input_queryJoystick
* Description: translates joystick movements into tetris_input_command_t
* Argument pIn: pointer to an input object
* Return value: see definition of tetris_input_command_t
*/
tetris_input_command_t tetris_input_queryJoystick()
{
tetris_input_command_t cmdReturn;
if (JOYISFIRE)
{
cmdReturn = TETRIS_INCMD_DROP;
}
else if (JOYISLEFT)
{
cmdReturn = TETRIS_INCMD_LEFT;
}
else if (JOYISRIGHT)
{
cmdReturn = TETRIS_INCMD_RIGHT;
}
else if (JOYISUP && JOYISDOWN)
{
cmdReturn = TETRIS_INCMD_PAUSE;
WAIT(TETRIS_INPUT_PAUSE_TICKS);
}
else if (JOYISDOWN)
{
cmdReturn = TETRIS_INCMD_DOWN;
}
else if (JOYISUP)
{
cmdReturn = TETRIS_INCMD_ROT_CW;
}
else
{
cmdReturn = TETRIS_INCMD_NONE;
}
return cmdReturn;
}
/*****************************
* construction/destruction *
*****************************/
/* Function: tetris_input_construct
* Description: constructs an input object for André's borg
* Return value: pointer to a newly created input object
*/
tetris_input_t *tetris_input_construct()
{
tetris_input_t *pIn = (tetris_input_t *)malloc(sizeof(tetris_input_t));
assert(pIn != NULL);
pIn->cmdLast = TETRIS_INCMD_NONE;
pIn->nLevel = 0xFF;
tetris_input_setLevel(pIn, 0);
pIn->nLoopCycles = 0;
pIn->nRepeatCount = -TETRIS_INPUT_REPEAT_INITIALDELAY;
pIn->nPauseCount = 0;
memset(pIn->nIgnoreCmdCounter, 0, TETRIS_INCMD_NONE);
return pIn;
}
/* Function: tetris_input_destruct
* Description: destructs an input structure
* Argument pIn: pointer to the input object which should to be destructed
* Return value: void
*/
void tetris_input_destruct(tetris_input_t *pIn)
{
assert(pIn != NULL);
free(pIn);
}
/***************************
* input related functions *
***************************/
/* Function: retris_input_getCommand
* Description: retrieves commands from joystick or loop interval
* Argument pIn: pointer to an input object
* Argument nPace: falling pace (see definition of tetris_input_pace_t)
* Return value: see definition of tetris_input_command_t
*/
tetris_input_command_t tetris_input_getCommand(tetris_input_t *pIn,
tetris_input_pace_t nPace)
{
assert (pIn != NULL);
// holds the translated command value of the joystick
tetris_input_command_t cmdJoystick = TETRIS_INCMD_NONE;
// this variable both serves as the return value and as a flag for not
// leaving the function as long as its value is TETRIS_INCMD_NONE
tetris_input_command_t cmdReturn = TETRIS_INCMD_NONE;
uint8_t nMaxCycles;
// if the piece is gliding we grant the player a reasonable amount of time
// to make the game more controllable at higher falling speeds
if ((nPace == TETRIS_INPACE_GLIDING) &&
(pIn->nMaxCycles < TETRIS_INPUT_GLIDE_CYCLES))
{
nMaxCycles = TETRIS_INPUT_GLIDE_CYCLES;
}
else
{
nMaxCycles = pIn->nMaxCycles;
}
while (pIn->nLoopCycles < nMaxCycles)
{
cmdJoystick = tetris_input_queryJoystick();
// only obey current command if it is not considered as chattering
if (((cmdJoystick < TETRIS_INCMD_NONE) ?
pIn->nIgnoreCmdCounter[cmdJoystick] : 0) == 0)
{
switch (cmdJoystick)
{
case TETRIS_INCMD_LEFT:
case TETRIS_INCMD_RIGHT:
case TETRIS_INCMD_DOWN:
// only react if either the current command differs from the
// last one or enough loop cycles have been run on the same
// command (for key repeat)
if ((pIn->cmdLast != cmdJoystick)
|| ((pIn->cmdLast == cmdJoystick)
&& (pIn->nRepeatCount >= TETRIS_INPUT_REPEAT_DELAY)))
{
// reset repeat counter
if (pIn->cmdLast != cmdJoystick)
{
// different command: we set an extra initial delay
pIn->nRepeatCount = -TETRIS_INPUT_REPEAT_INITIALDELAY;
}
else
{
// same command: there's no extra initial delay
pIn->nRepeatCount = 0;
}
// update cmdLast and return value
pIn->cmdLast = cmdReturn = cmdJoystick;
}
else
{
// if not enough loop cycles have been run we increment the
// repeat counter, ensure that we continue the loop and
// keep the key repeat functioning
++pIn->nRepeatCount;
cmdReturn = TETRIS_INCMD_NONE;
}
break;
case TETRIS_INCMD_DROP:
case TETRIS_INCMD_ROT_CW:
case TETRIS_INCMD_ROT_CCW:
// no key repeat here
if (pIn->cmdLast != cmdJoystick)
{
pIn->cmdLast = cmdReturn = cmdJoystick;
}
else
{
// if we reach here the command is ignored
cmdReturn = TETRIS_INCMD_NONE;
}
break;
case TETRIS_INCMD_PAUSE:
// if this is an initial pause command, make sure that the logic
// module is informed about it
if (pIn->cmdLast != TETRIS_INCMD_PAUSE)
{
pIn->cmdLast = cmdReturn = cmdJoystick;
pIn->nPauseCount = 0;
}
// consecutive pause commands should not cause the loop to leave
else
{
cmdReturn = TETRIS_INCMD_NONE;
}
break;
case TETRIS_INCMD_NONE:
// chatter protection
if (pIn->cmdLast != TETRIS_INCMD_NONE)
{
tetris_input_chatterProtect(pIn, pIn->cmdLast);
}
// If the game is paused (last command was TETRIS_INCMD_PAUSE)
// we ensure that the variable which holds that last command
// isn't touched. We use this as a flag so that the loop cycle
// counter doesn't get incremented.
// We count the number of pause cycles, though. If enough pause
// cycles have been run, we enforce the continuation of the game.
if ((pIn->cmdLast != TETRIS_INCMD_PAUSE) ||
(++pIn->nPauseCount > TETRIS_INPUT_PAUSE_CYCLES))
{
pIn->cmdLast = TETRIS_INCMD_NONE;
}
// reset repeat counter
pIn->nRepeatCount = -TETRIS_INPUT_REPEAT_INITIALDELAY;
// using cmdReturn as a flag for not leaving the loop
cmdReturn = TETRIS_INCMD_NONE;
break;
default:
break;
}
}
// current command is considered as chattering
else
{
pIn->cmdLast = cmdReturn = TETRIS_INCMD_NONE;
}
// decrement all ignore counters
for (int nIgnoreIndex = 0; nIgnoreIndex < TETRIS_INCMD_NONE; ++nIgnoreIndex)
{
if (pIn->nIgnoreCmdCounter[nIgnoreIndex] != 0)
{
--pIn->nIgnoreCmdCounter[nIgnoreIndex];
}
}
// reset automatic falling if the player has dropped a piece
if ((cmdReturn == TETRIS_INCMD_DOWN)
|| (cmdReturn == TETRIS_INCMD_DROP))
{
pIn->nLoopCycles = 0;
}
// otherwise ensure automatic falling (unless the game is running)
else if ((cmdReturn != TETRIS_INCMD_PAUSE) &&
!((cmdReturn == TETRIS_INCMD_NONE) &&
(pIn->cmdLast == TETRIS_INCMD_PAUSE)))
{
++pIn->nLoopCycles;
}
WAIT(TETRIS_INPUT_TICKS);
if (cmdReturn != TETRIS_INCMD_NONE)
{
return cmdReturn;
}
}
// since we have left the loop we reset the cycle counter
pIn->nLoopCycles = 0;
return TETRIS_INCMD_GRAVITY;
}
/* Function: tetris_input_setLevel
* Description: modifies time interval of input events
* Argument pIn: pointer to an input object
* Argument nLvl: desired level (0 <= nLvl <= TETRIS_INPUT_LEVELS - 1)
* Return value: void
*/
void tetris_input_setLevel(tetris_input_t *pIn,
uint8_t nLvl)
{
assert(pIn != NULL);
assert(nLvl <= TETRIS_INPUT_LEVELS - 1);
if (pIn->nLevel != nLvl)
{
pIn->nLevel = nLvl;
pIn->nMaxCycles = 400 / (nLvl + 2);
}
}

129
games/tetris/input.h

@ -0,0 +1,129 @@
#ifndef INPUT_H_
#define INPUT_H_
#include <inttypes.h>
/***********
* defines *
***********/
// number of levels
#define TETRIS_INPUT_LEVELS 20
/*********
* types *
*********/
typedef enum tetris_input_command_t
{
TETRIS_INCMD_ROT_CW, // rotate clockwise
TETRIS_INCMD_ROT_CCW, // rotate counter clockwise
TETRIS_INCMD_LEFT, // move piece left
TETRIS_INCMD_RIGHT, // move piece right
TETRIS_INCMD_DOWN, // lower piece by one row
TETRIS_INCMD_DROP, // move piece to the ground immediately
TETRIS_INCMD_GRAVITY, // piece gets pulled by gravity
TETRIS_INCMD_PAUSE, // pause the game
TETRIS_INCMD_NONE // idle (must alway be the last one)
}
tetris_input_command_t;
typedef enum tetris_input_pace_t
{
TETRIS_INPACE_HOVERING, // normal falling pace
TETRIS_INPACE_GLIDING /* guarantees a minimum docking time to avoid that
pieces are docked immediately if they hit something
in higher levels */
}
tetris_input_pace_t;
typedef struct tetris_input_t
{
// current level (determines falling speed)
uint8_t nLevel;
// Amount of loop cycles between forced piece movements. This value gets
// set via the tetris_input_setLevel() function.
uint8_t nMaxCycles;
// This counter keeps track of the number of loop cycles whoch have been
// done since the last forced piece movement. It gets reset if it either
// reaches a well defined value (causing a gravity command to be issued)
// or the player has moved down the piece herself/himself.
uint8_t nLoopCycles;
// Amount of loop cycles in which the same command has been issued
// consecutively. It gets reset if either the current command differs from
// the last one or a well-defined value has been reached (thereby
// regulating the pace of the key repeat as commands are only processed
// if that value is reached).
int8_t nRepeatCount;
// Keeps track of the number loop cycles which have been run while in
// pause mode. As soon as a well defined value is reached, the game
// continues (in case someone paused the game and forgot to resume it).
uint16_t nPauseCount;
// last command (important for key repeat)
tetris_input_command_t cmdLast;
// Every command has its own counter. A command is ignored as long as its
// counter is unequal to 0. A counter gets set to a specific value (or 0)
// if the button of the corresponding command has been released by the
// player. All counters get decremented by one every loop cycle until they
// are zero. This is used to work against joystick chatter. Look at the
// TETRIS_INPUT_CHATTER_TICKS_... constants in input.c for the initial
// values of these counters.
uint8_t nIgnoreCmdCounter[TETRIS_INCMD_NONE];
}
tetris_input_t;
/****************************
* construction/destruction *
****************************/
/* Function: tetris_input_construct
* Description: constructs an input object for André's borg
* Return value: pointer to a newly created input object
*/
tetris_input_t *tetris_input_construct();
/* Function: tetris_input_destruct
* Description: destructs an input object
* Argument pIn: pointer to the input object which should be destructed
* Return value: void
*/
void tetris_input_destruct(tetris_input_t *pIn);
/***************************
* input related functions *
***************************/
/* Function: retris_input_getCommand
* Description: retrieves commands from joystick or loop interval
* Argument pIn: pointer to an input object
* Argument nPace: falling pace (see definition of tetris_input_pace_t)
* Return value: see definition of tetris_input_command_t
*/
tetris_input_command_t tetris_input_getCommand(tetris_input_t *pIn,
tetris_input_pace_t nPace);
/* Function: tetris_input_setLevel
* Description: modifies time interval of input events
* Argument pIn: pointer to an input object
* Argument nLvl: desired level (0 <= nLvl <= TETRIS_INPUT_LEVELS - 1)
* Return value: void
*/
void tetris_input_setLevel(tetris_input_t *pIn,
uint8_t nLvl);
#endif /*INPUT_H_*/

467
games/tetris/logic.c

@ -0,0 +1,467 @@
/* Borgtris
* by: Christian Kroll
* date: Tuesday, 2007/09/16
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <inttypes.h>
#ifdef __AVR__
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#endif
#include "logic.h"
#include "piece.h"
#include "playfield.h"
#include "view.h"
#include "input.h"
#include "../prng.h"
#ifdef EEMEM
/***********************
* Highscore in EEPROM *
***********************/
uint16_t tetris_logic_nHighscore EEMEM;
#endif
/***************************
* non-interface functions *
***************************/
/* Function: tetris_logic_calculateLines
* Description: calculates number of lines for the given row mask
* Argument nRowMask: row mask from which the no. of lines will be calculated
* Return value: number of lines of the row mask
*/
uint8_t tetris_logic_calculateLines(uint8_t nRowMask)
{
uint8_t nMask = 0x0001;
uint8_t nLines = 0;
for (uint8_t i = 0; i < 4; ++i)
{
if ((nMask & nRowMask) != 0)
{
++nLines;
}
nMask <<= 1;
}
return nLines;
}
uint16_t tetris_logic_retrieveHighscore(void)
{
#ifdef EEMEM
uint16_t nHighscore = 0;
nHighscore = eeprom_read_word(&tetris_logic_nHighscore);
// a score of 65535 is most likely caused by uninitialized EEPROM addresses
if (nHighscore == 65535)
{
nHighscore = 0;
}
return nHighscore;
#else
return 0;
#endif
}
void tetris_logic_saveHighscore(uint16_t nHighscore)
{
#ifdef EEMEM
if (nHighscore > tetris_logic_retrieveHighscore())
{
eeprom_write_word(&tetris_logic_nHighscore, nHighscore);
}
#endif
}
/****************************
* construction/destruction *
****************************/
/* Function: tetris_logic_construct
* Description: constructs a logic object
* Return value: pointer to a newly created logic object
*/
tetris_logic_t *tetris_logic_construct()
{
tetris_logic_t *pLogic = (tetris_logic_t *)malloc(sizeof(tetris_logic_t));
assert(pLogic != NULL);
memset(pLogic, 0, sizeof(tetris_logic_t));
return pLogic;
}
/* Function: tetris_logic_destruct
* Description: destructs a logic object
* Argument pIn: pointer to the logic object to be destructed
* Return value: void
*/
void tetris_logic_destruct(tetris_logic_t *pLogic)
{
assert(pLogic != 0);
free(pLogic);
}
/***************************
* logic related functions *
***************************/
/* Function: tetris
* Description: runs the tetris game
* Return value: void
*/
void tetris ()
{
// get view dependent dimensions of the playfield
int8_t nWidth;
int8_t nHeight;
tetris_view_getDimensions(&nWidth, &nHeight);
// holds the current user command which should be processed
tetris_input_command_t inCmd;
// prepare data structures that drive the game...
tetris_logic_t *pLogic = tetris_logic_construct();
tetris_playfield_t *pPl = tetris_playfield_construct(nWidth, nHeight);
tetris_input_t *pIn = tetris_input_construct();
tetris_view_t *pView = tetris_view_construct(pLogic, pPl);
// runtime variable
int8_t nPieceRow;
// retrieve highscore
static uint16_t nHighscore = 0;
if (nHighscore == 0)
{
nHighscore = tetris_logic_retrieveHighscore();
}
// initialize current and next piece
tetris_piece_t *pPiece = NULL;
tetris_piece_t *pNextPiece = pPiece =
tetris_piece_construct(random8() % 7, TETRIS_PC_ANGLE_0);
// the view only monitors the logic and the playfield object for the game
// status so we must put information like the next piece or the current
// highscore to a place where the view can find it
tetris_logic_setHighscore(pLogic, nHighscore);
tetris_logic_setPreviewPiece(pLogic, pNextPiece);
// pace flag
tetris_input_pace_t inPace;
// game loop, runs as long as the game is not over
while (tetris_playfield_getStatus(pPl) != TETRIS_PFS_GAMEOVER)
{
// what we do strongly depends on the status of the playfield
switch (tetris_playfield_getStatus(pPl))
{
// the playfield awaits a new piece
case TETRIS_PFS_READY:
// make preview piece the current piece and create new preview piece
pPiece = pNextPiece;
pNextPiece =
tetris_piece_construct(random8() % 7, TETRIS_PC_ANGLE_0);
tetris_logic_setPreviewPiece(pLogic, pNextPiece);
// insert new piece into playfield
tetris_piece_t *pOldPiece;
tetris_playfield_insertPiece(pPl, pPiece, &pOldPiece);
// destruct old piece (if it exists) since we don't need it anymore
if (pOldPiece != NULL)
{
tetris_piece_destruct(pOldPiece);
pOldPiece = NULL;
}
break;
// a piece is hovering and can be controlled by the player
case TETRIS_PFS_HOVERING:
case TETRIS_PFS_GLIDING:
// if the piece is gliding the input module has to grant us
// a minimum amount of time to move it
if (tetris_playfield_getStatus(pPl) == TETRIS_PFS_GLIDING)
{
inPace = TETRIS_INPACE_GLIDING;
}
else
{
inPace = TETRIS_INPACE_HOVERING;
}
// ensure correct view mode if the game isn't paused
if ((inCmd = tetris_input_getCommand(pIn, inPace))
!= TETRIS_INCMD_PAUSE)
{
tetris_view_setViewMode(pView, TETRIS_VIMO_RUNNING);
}
// what we do depends on what the input module tells us
switch (inCmd)
{
// game paused?
case TETRIS_INCMD_PAUSE:
// tell the view it should display the pause screen
tetris_view_setViewMode(pView, TETRIS_VIMO_PAUSED);
break;
// the piece was pulled down by the almighty gravity
case TETRIS_INCMD_GRAVITY:
tetris_playfield_advancePiece(pPl);
break;
// the player has pulled down the piece herself/himself
case TETRIS_INCMD_DOWN:
tetris_playfield_advancePiece(pPl);
// if the game still runs, reward the player with extra points
if (tetris_playfield_getStatus(pPl) != TETRIS_PFS_GAMEOVER)
{
tetris_logic_singleDrop(pLogic, 1);
}
break;
// player shifted the piece to the left
case TETRIS_INCMD_LEFT:
tetris_playfield_movePiece(pPl, TETRIS_PFD_LEFT);
break;
// player shifted the piece to the right
case TETRIS_INCMD_RIGHT:
tetris_playfield_movePiece(pPl, TETRIS_PFD_RIGHT);
break;
// player rotated the piece clockwise
case TETRIS_INCMD_ROT_CW:
tetris_playfield_rotatePiece(pPl, TETRIS_PC_ROT_CW);
break;
// player rotated the piece counter clockwise
case TETRIS_INCMD_ROT_CCW:
tetris_playfield_rotatePiece(pPl, TETRIS_PC_ROT_CCW);
break;
// the player decided to make an immediate drop
case TETRIS_INCMD_DROP:
nPieceRow = tetris_playfield_getRow(pPl);
// emulate immediate drop
while((tetris_playfield_getStatus(pPl) == TETRIS_PFS_GLIDING) ||
(tetris_playfield_getStatus(pPl) == TETRIS_PFS_HOVERING))
{
tetris_playfield_advancePiece(pPl);
}
// if the game still runs, reward the player with extra points
if (tetris_playfield_getStatus(pPl) != TETRIS_PFS_GAMEOVER)
{
tetris_logic_completeDrop(pLogic,
tetris_playfield_getRow(pPl) - nPieceRow);
}
break;
// avoid compiler warnings
default:
break;
}
break;
// the piece has irrevocably hit the ground
case TETRIS_PFS_DOCKED:
// remove complete lines (if any)
tetris_playfield_removeCompleteLines(pPl);
// let the logic object decide how many points the player gets
// and whether the level gets changed
tetris_logic_removedLines(pLogic, tetris_playfield_getRowMask(pPl));
tetris_input_setLevel(pIn, tetris_logic_getLevel(pLogic));
break;
// avoid compiler warnings
default:
break;
}
// the view updates it state every loop cycle to make changes visible
tetris_view_update(pView);
}
// game is over and we provide the player with her/his results
tetris_view_showResults(pView);
// update highscore if it has been beaten
uint16_t nScore = tetris_logic_getScore(pLogic);
if (nScore > nHighscore)
{
nHighscore = nScore;
tetris_logic_saveHighscore(nHighscore);
}
// clean up
tetris_view_destruct(pView);
tetris_input_destruct(pIn);
tetris_playfield_destruct(pPl);
tetris_logic_destruct(pLogic);
tetris_piece_destruct(pPiece);
tetris_piece_destruct(pNextPiece);
}
/* Function: tetris_logic_singleDrop
* Description: add points which result from single step dropping
* Argument pLogic: the logic object we want to modify
* Argument nLines: the number of rows involved
* Return value: void
*/
void tetris_logic_singleDrop(tetris_logic_t *pLogic,
uint8_t nLines)
{
assert(pLogic != 0);
pLogic->nScore += nLines;
}
/* Function: tetris_logic_completeDrop
* Description: add points which result from a complete drop
* Argument pLogic: the logic object we want to modify
* Argument nLines: the number of rows involved
* Return value: void
*/
void tetris_logic_completeDrop(tetris_logic_t *pLogic,
uint8_t nLines)
{
assert(pLogic != 0);
pLogic->nScore += nLines * 2;
}
/* Function: tetris_logic_removedLines
* Description: add points which result from removed rows
* Argument pLogic: the logic object we want to modify
* Argument nRowMask: see tetris_playfield_completeLines
* Return value: void
*/
void tetris_logic_removedLines(tetris_logic_t *pLogic,
uint8_t nRowMask)
{
assert(pLogic != 0);
uint8_t nLines = tetris_logic_calculateLines(nRowMask);
pLogic->nLines += nLines;
pLogic->nLevel = ((pLogic->nLines / 10) < TETRIS_INPUT_LEVELS) ?
(pLogic->nLines / 10) : (TETRIS_INPUT_LEVELS - 1);
switch (nLines)
{
case 1:
pLogic->nScore += 50;
break;
case 2:
pLogic->nScore += 150;
break;
case 3:
pLogic->nScore += 250;
break;
case 4:
pLogic->nScore += 400;
break;
}
}
/*****************
* get functions *
*****************/
/* Function: tetris_logic_getScore
* Description: returns the current score
* Argument pLogic: the logic object we want information from
* Return value: the score as uint16_t
*/
uint16_t tetris_logic_getScore(tetris_logic_t *pLogic)
{
assert(pLogic != NULL);
return pLogic->nScore;
}
/* Function: tetris_logic_getHighscore
* Description: returns the current highscore
* Argument pLogic: the logic object we want information from
* Return value: the highscore as uint16_t
*/
uint16_t tetris_logic_getHighscore(tetris_logic_t *pLogic)
{
assert(pLogic != NULL);
return pLogic->nHighscore;
}
/* Function: tetris_logic_setHighscore
* Description: set highscore
* Argument pLogic: the logic object we want to modify
* Argmument nHighscore: highscore
*/
void tetris_logic_setHighscore(tetris_logic_t *pLogic,
uint16_t nHighscore)
{
assert(pLogic != NULL);
pLogic->nHighscore = nHighscore;
}
/* Function: tetris_logic_getLevel
* Description: returns the current level
* Argument pLogic: the logic object we want information from
* Return value: the level as uint8_t
*/
uint8_t tetris_logic_getLevel(tetris_logic_t *pLogic)
{
assert(pLogic != NULL);
return pLogic->nLevel;
}
/* Function: tetris_logic_getLines
* Description: returns the number of completed lines
* Argument pLogic: the logic object we want information from
* Return value: number of completed lines as uint16_t
*/
uint16_t tetris_logic_getLines(tetris_logic_t *pLogic)
{
assert(pLogic != NULL);
return pLogic->nLines;
}
/* Function: tetris_logic_setPreviewPiece
* Description: help for the view to determine the preview piece
* Argument pLogic: the logic object we want to modify
* Argument pPiece: pointer to piece intended to be the next one (may be NULL)
* Return value: void
*/
void tetris_logic_setPreviewPiece(tetris_logic_t *pLogic,
tetris_piece_t *pPiece)
{
assert(pLogic != NULL);
pLogic->pPreviewPiece = pPiece;
}
/* Function: tetris_logic_getPreviewPiece
* Description: returns piece which was set via tetris_logic_setPreviewPiece
* Argument pLogic: the logic object we want information from
* Return value: the piece intended to be the next one (may be NULL)
*/
tetris_piece_t* tetris_logic_getPreviewPiece(tetris_logic_t *pLogic)
{
assert(pLogic != NULL);
return pLogic->pPreviewPiece;
}

143
games/tetris/logic.h

@ -0,0 +1,143 @@
#ifndef TETRIS_LOGIC_H_
#define TETRIS_LOGIC_H_
#include <inttypes.h>
#include "piece.h"
/*********
* types *
*********/
typedef struct tetris_logic_t
{
uint16_t nScore; // score of the player
uint16_t nHighscore; // highscore
uint8_t nLevel; // current level
uint16_t nLines; // number of completed lines
tetris_piece_t *pPreviewPiece; // the piece intended to be the next one
}
tetris_logic_t;
/****************************
* construction/destruction *
****************************/
/* Function: tetris_logic_construct
* Description: constructs a logic object
* Return value: pointer to a newly created logic object
*/
tetris_logic_t *tetris_logic_construct();
/* Function: tetris_logic_destruct
* Description: destructs a logic object
* Argument pIn: pointer to the logic object to be destructed
* Return value: void
*/
void tetris_logic_destruct(tetris_logic_t *pLogic);
/***************************
* logic related functions *
***************************/
/* Function: tetris
* Description: runs the tetris game
* Return value: void
*/
void tetris();
/* Function: tetris_logic_singleDrop
* Description: add points which result from single step dropping
* Argument pLogic: the logic object we want to modify
* Argument nLines: the number of rows involved
* Return value: void
*/
void tetris_logic_singleDrop(tetris_logic_t *pLogic,
uint8_t nLines);
/* Function: tetris_logic_completeDrop
* Description: add points which result from a complete drop
* Argument pLogic: the logic object we want to modify
* Argument nLines: the number of rows involved
* Return value: void
*/
void tetris_logic_completeDrop(tetris_logic_t *pLogic,
uint8_t nLines);
/* Function: tetris_logic_removedLines
* Description: add points which result from removed rows
* Argument pLogic: the logic object we want to modify
* Argument nRowMask: see tetris_playfield_completeLines
* Return value: void
*/
void tetris_logic_removedLines(tetris_logic_t *pLogic,
uint8_t nRowMask);
/*********************
* get/set functions *
*********************/
/* Function: tetris_logic_getScore
* Description: returns the current score
* Argument pLogic: the logic object we want information from
* Return value: the score as uint16_t
*/
uint16_t tetris_logic_getScore(tetris_logic_t *pLogic);
/* Function: tetris_logic_getHighscore
* Description: returns the current highscore
* Argument pLogic: the logic object we want information from
* Return value: the highscore as uint16_t
*/
uint16_t tetris_logic_getHighscore(tetris_logic_t *pLogic);
/* Function: tetris_logic_setHighscore
* Description: set highscore
* Argument pLogic: the logic object we want to modify
* Argmument nHighscore: highscore
*/
void tetris_logic_setHighscore(tetris_logic_t *pLogic,
uint16_t nHighscore);
/* Function: tetris_logic_getLevel
* Description: returns the current level
* Argument pLogic: the logic object we want information from
* Return value: the level as uint8_t
*/
uint8_t tetris_logic_getLevel(tetris_logic_t *pLogic);
/* Function: tetris_logic_getLines
* Description: returns the number of completed lines
* Argument pLogic: the logic object we want information from
* Return value: number of completed lines as uint16_t
*/
uint16_t tetris_logic_getLines(tetris_logic_t *pLogic);
/* Function: tetris_logic_setPreviewPiece
* Description: help for the view to determine the preview piece
* Argument pLogic: the logic object we want to modify
* Argument pPiece: pointer to piece intended to be the next one
* Return value: void
*/
void tetris_logic_setPreviewPiece(tetris_logic_t *pLogic,
tetris_piece_t *pPiece);
/* Function: tetris_logic_getPreviewPiece
* Description: returns piece which was set via tetris_logic_setPreviewPiece
* Argument pLogic: the logic object we want information from
* Return value: the piece intended to be the next one
*/
tetris_piece_t* tetris_logic_getPreviewPiece(tetris_logic_t *pLogic);
#endif /*TETRIS_LOGIC_H_*/

119
games/tetris/piece.c

@ -0,0 +1,119 @@
#include <stdlib.h>
#include <assert.h>
#include <inttypes.h>
#include "piece.h"
#ifdef __AVR__
#include <avr/pgmspace.h>
#else
#define PROGMEM
#endif
/*****************************
* construction/destruction *
*****************************/
/* Function: tetris_piece_construct
* Description: constructs a piece with the given attributes
* Argument s: shape of the piece (see tetris_piece_shape_t)
* Argument a: its angle (see tetris_piece_angel_t)
* Return value: pointer to a newly created piece
*/
tetris_piece_t *tetris_piece_construct(tetris_piece_shape_t s,
tetris_piece_angle_t a)
{
tetris_piece_t *p_piece = (tetris_piece_t*) malloc (sizeof(tetris_piece_t));
assert(p_piece != NULL);
p_piece->shape = s;
p_piece->angle = a;
return p_piece;
}
/* Function: tetris_piece_destruct
* Description: destructs a piece
* Argument pPc: pointer to the piece to be destructed
* Return value: void
*/
void tetris_piece_destruct(tetris_piece_t *pPc)
{
assert(pPc != NULL);
free(pPc);
}
/****************************
* piece related functions *
****************************/
/* Function: tetris_piece_getBitmap
* Description: returns bitfield representation of the piece
* Argument pPc: piece from which the bitfield shuld be retrieved
* Return value: bitfield representation of the piece
* - nth nibble is nth row of the piece (from upper left)
* - the LSB of a nibble represents the left side of a row
*/
uint16_t tetris_piece_getBitmap(tetris_piece_t *pPc)
{
assert(pPc != NULL);
// Lookup table:
// A value in an array represents a piece in a specific angle (rotating
// clockwise from index 0).
const static uint16_t piece[][4] PROGMEM =
{{0x0F00, 0x2222, 0x0F00, 0x2222}, // LINE
{0x4E00, 0x4640, 0x0E40, 0x4C40}, // T
{0x0660, 0x0660, 0x0660, 0x0660}, // SQUARE
{0x2E00, 0x88C0, 0x0E80, 0xC440}, // L
{0x8E00, 0x6440, 0x0E20, 0x44C0}, // LBACK
{0x6C00, 0x4620, 0x6C00, 0x4620}, // S
{0xC600, 0x4C80, 0xC600, 0x4C80}}; // Z
#ifdef __AVR__
return pgm_read_word(&piece[pPc->shape][pPc->angle]);
#else
return piece[pPc->shape][pPc->angle];
#endif
}
/* Function: tetris_piece_rotate
* Description: rotates a piece
* Argument pPc: piece to rotate
* Argument r: type of rotation (see tetris_piece_rotation_t)
* Return value: void
*/
void tetris_piece_rotate(tetris_piece_t *pPc,
tetris_piece_rotation_t r)
{
assert(pPc != NULL);
// we just rotate through the available angles in the given direction and
// make wrap arounds where appropriate
switch (r)
{
case TETRIS_PC_ROT_CW:
if (pPc->angle == TETRIS_PC_ANGLE_270)
{
pPc->angle = TETRIS_PC_ANGLE_0;
}
else
{
++pPc->angle;
}
break;
case TETRIS_PC_ROT_CCW:
if (pPc->angle == TETRIS_PC_ANGLE_0)
{
pPc->angle = TETRIS_PC_ANGLE_270;
}
else
{
--pPc->angle;
}
break;
}
}

97
games/tetris/piece.h

@ -0,0 +1,97 @@
#ifndef TETRIS_PIECE_H_
#define TETRIS_PIECE_H_
#include <inttypes.h>
/*********
* types *
*********/
typedef enum tetris_piece_shape_t
{
TETRIS_PC_LINE,
TETRIS_PC_T,
TETRIS_PC_SQUARE,
TETRIS_PC_L,
TETRIS_PC_LBACK,
TETRIS_PC_S,
TETRIS_PC_Z
}
tetris_piece_shape_t;
typedef enum tetris_piece_angle_t
{
TETRIS_PC_ANGLE_0,
TETRIS_PC_ANGLE_90,
TETRIS_PC_ANGLE_180,
TETRIS_PC_ANGLE_270
}
tetris_piece_angle_t;
typedef enum tetris_piece_rotation_t
{
TETRIS_PC_ROT_CW, // clockwise rotation
TETRIS_PC_ROT_CCW // counter clockwise rotation
}
tetris_piece_rotation_t;
typedef struct tetris_piece_t
{
tetris_piece_shape_t shape; // specifies the shape of the piece
tetris_piece_angle_t angle; // specifies one of 4 angels
}
tetris_piece_t;
/*****************************
* construction/destruction *
*****************************/
/* Function: tetris_piece_construct
* Description: constructs a piece with the given attributes
* Argument s: shape of the piece (see tetris_piece_shape_t)
* Argument a: its angle (see tetris_piece_angel_t)
* Return value: pointer to a newly created piece
*/
tetris_piece_t *tetris_piece_construct(tetris_piece_shape_t s,
tetris_piece_angle_t a);
/* Function: tetris_piece_destruct
* Description: destructs a piece
* Argument pPc: pointer to the piece to be destructed
* Return value: void
*/
void tetris_piece_destruct(tetris_piece_t *pPc);
/****************************
* piece related functions *
****************************/
/* Function: tetris_piece_getBitmap
* Description: returns bitfield representation of the piece
* Argument pPc: piece from which the bitfield shuld be retrieved
* Return value: bitfield representation of the piece
* - nth nibble is nth row of the piece (from upper left)
* - the LSB of a nibble represents the left side of a row
*/
uint16_t tetris_piece_getBitmap(tetris_piece_t *pPc);
/* Function: tetris_piece_rotate
* Description: rotates a piece
* Argument pPc: piece to rotate
* Argument r: type of rotation (see tetris_piece_rotation_t)
* Return value: void
*/
void tetris_piece_rotate(tetris_piece_t *pPc,
tetris_piece_rotation_t r);
#endif /*TETRIS_PIECE_H_*/

595
games/tetris/playfield.c

@ -0,0 +1,595 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <inttypes.h>
#include "playfield.h"
#include "piece.h"
/***************************
* non-interface functions *
***************************/
/* Function: tetris_playfield_hoverStatus;
* Description: determines if piece is either hovering or gliding
* Argument pPl: playfield perform action on
* Return value: TETRIS_PFS_HOVERING or TETRIS_PFS_GLIDING
*/
tetris_playfield_status_t tetris_playfield_hoverStatus(tetris_playfield_t* pPl)
{
// if the piece touches the dump we ensure that the status is "gliding"
if (tetris_playfield_collision(pPl, pPl->nColumn, pPl->nRow + 1))
{
return TETRIS_PFS_GLIDING;
}
// otherwise the status must be "hovering"
else
{
return TETRIS_PFS_HOVERING;
}
}
/****************************
* construction/destruction *
****************************/
/* Function: tetris_playfield_construct
* Description: constructs a playfield with the given diemensions
* Argument nWidth: width of playfield (4 <= n <= 16)
* Argument nHeight: height of playfield (4 <= n <= 124)
* Return value: pointer to a newly created playfield
*/
tetris_playfield_t *tetris_playfield_construct(int8_t nWidth,
int8_t nHeight)
{
assert((nWidth >= 4) && (nWidth <= 16));
assert((nHeight >= 4) && (nHeight <= 124));
tetris_playfield_t *pPlayfield =
(tetris_playfield_t*) malloc(sizeof(tetris_playfield_t));
if (pPlayfield != NULL)
{
// allocating mem for dump array
pPlayfield->dump = (uint16_t*) calloc(nHeight, sizeof(uint16_t));
if (pPlayfield->dump != NULL)
{
// setting desired attributes
pPlayfield->nWidth = nWidth;
pPlayfield->nHeight = nHeight;
tetris_playfield_reset(pPlayfield);
return pPlayfield;
}
else
{
free(pPlayfield);
pPlayfield = NULL;
}
}
return NULL;
}
/* Function: tetris_playfield_destruct
* Description: destructs a playfield
* Argument pPl: pointer to the playfield to be destructed
* Return value: void
*/
void tetris_playfield_destruct(tetris_playfield_t *pPl)
{
assert(pPl != NULL);
// if memory for the dump array has been allocated, free it
if (pPl->dump != NULL)
{
free(pPl->dump);
}
free(pPl);
}
/*******************************
* playfield related functions *
*******************************/
/* Function: tetris_playfield_reset
* Description: resets playfield to begin a new game
* Argument pPl: playfield to perform action on
* Return value: void
*/
void tetris_playfield_reset(tetris_playfield_t *pPl)
{
assert(pPl != NULL);
pPl->pPiece = NULL;
pPl->nColumn = 0;
pPl->nRow = 0;
pPl->nRowMask = 0;
// clear dump if it has been allocated in memory
if (pPl->dump != NULL)
{
memset(pPl->dump, 0, pPl->nHeight);
}
pPl->status = TETRIS_PFS_READY;
}
/* Function: tetris_playfield_insertPiece
* Description: inserts a new piece
* Argument pPl: playfield to perform action on
* Argument pPiece: piece to be inserted
* Argument ppOldPiece: [out] indirect pointer to former piece for deallocation
* Return value: void
*/
void tetris_playfield_insertPiece(tetris_playfield_t *pPl,
tetris_piece_t *pPiece,
tetris_piece_t** ppOldPiece)
{
assert((pPl != NULL) && (pPiece != NULL) && (ppOldPiece != NULL));
// a piece can only be inserted in state TETRIS_PFS_READY
assert(pPl->status == TETRIS_PFS_READY);
// row mask is now meaningless
pPl->nRowMask = 0;
// replace old piece
*ppOldPiece = pPl->pPiece;
pPl->pPiece = pPiece;
// set horizontal start position (in the middle of the top line)
pPl->nColumn = (pPl->nWidth - 2) / 2;
// set vertical start position (first piece row with matter at pos. 1)
uint16_t nPieceMap = tetris_piece_getBitmap(pPl->pPiece);
uint16_t nElementMask = 0xF000;
pPl->nRow = -3;
while ((nPieceMap & nElementMask) == 0)
{
++pPl->nRow;
nElementMask >>= 4;
}
if (pPl->nRow < 0)
{
++pPl->nRow;
}
// did we already collide with something?
if (tetris_playfield_collision(pPl, pPl->nColumn, pPl->nRow) == 1)
{
// game over man, game over!!
pPl->status = TETRIS_PFS_GAMEOVER;
}
else
{
// bring it on!
pPl->status = tetris_playfield_hoverStatus(pPl);
}
}
/* Function: tetris_playfield_collision
* Description: detects if piece collides with s.th. at a given position
* Argument pPl: playfield to perform action on
* Argument nColumn: column where the piece should be moved
* Argument nRow: row where the piece should be moved
* Return value: 1 for collision, 0 otherwise
*/
uint8_t tetris_playfield_collision(tetris_playfield_t *pPl,
int8_t nColumn,
int8_t nRow)
{
assert(pPl != NULL);
// only allow coordinates which are within sane ranges
assert((nColumn >= -4) && (nColumn < pPl->nWidth));
assert((nRow >= -4) && (nRow < pPl->nHeight));
// The rows of a piece get compared with the background one by one
// until either a collision occures or all rows are compared. Both the
// piece row and the part of the playfield it covers are represented in
// 4 bits which were singled out from their corresponding uint16_t
// values and are aligned to LSB. In case where a piece overlaps with
// either the left or the right border we "enhance" the playfield part
// via bit shifting and set all bits representing the border to 1.
//
// NOTE: LSB represents the left most position.
uint16_t nPieceMap = tetris_piece_getBitmap(pPl->pPiece);
uint16_t nPlayfieldPart;
uint16_t nPieceRowMap;
// negative nRow values indicate that the piece hasn't fully entered the
// playfield yet which requires special treatment if the piece overlaps
// with either the left or the right border
if (nRow < 0)
{
uint16_t nBorderMask = 0x0000;
// piece overlaps with left border
if (nColumn < 0)
{
nBorderMask = 0x1111 << (-nColumn - 1);
}
// piece overlaps with right border
else if ((nColumn + 3) >= pPl->nWidth)
{
nBorderMask = 0x8888 >> ((nColumn + 3) - pPl->nWidth);
}
// return if piece collides with border
if ((nPieceMap & nBorderMask) != 0)
{
return 1;
}
}
// here we check the part which has already entered the playfield
for (int8_t y = (nRow < 0) ? -nRow : 0; y < 4; ++y)
{
// current piece row overlaps with lower border
if ((y + nRow) >= pPl->nHeight)
{
// all 4 bits represent the lower border
nPlayfieldPart = 0x000F;
}
// piece overlaps with left border
else if (nColumn < 0)
{
// clear all bits we are not interested in
nPlayfieldPart = (pPl->dump[y + nRow] & (0x000F >> -nColumn));
// add zeros to the left (the bits "behind" the left border)
nPlayfieldPart <<= -nColumn;
// set bits beyond left border to 1
nPlayfieldPart |= 0x000F >> (4 + nColumn);
}
// piece overlaps with right border
else if ((nColumn + 3) >= pPl->nWidth)
{
// align the bits we are interested in to LSB
// (thereby clearing the rest)
nPlayfieldPart = pPl->dump[y + nRow] >> nColumn;
// set bits beyond right border to 1
nPlayfieldPart |= 0xFFF8 >> (nColumn + 3 - pPl->nWidth);
}
// current row neither overlaps with left, right nor lower border
else
{
// clear all bits we are not interested in and align the
// remaing row to LSB
nPlayfieldPart =
(pPl->dump[y + nRow] & (0x000F << nColumn)) >> nColumn;
}
// clear all bits of the piece we are not interested in and
// align the remaing row to LSB
nPieceRowMap = (nPieceMap & (0x000F << (y << 2))) >> (y << 2);
// finally check for a collision
if ((nPlayfieldPart & nPieceRowMap) != 0)
{
return 1;
}
}
// if we reach here, no collision was detected
return 0;
}
/* Function: tetris_playfield_advancePiece
* Description: lowers piece by one row or finally docks it
* Argument pPl: playfield to perform action on
* Return value: void
*/
void tetris_playfield_advancePiece(tetris_playfield_t *pPl)
{
assert(pPl != NULL);
// a piece can only be lowered if it is hovering or gliding
assert ((pPl->status == TETRIS_PFS_HOVERING) ||
(pPl->status == TETRIS_PFS_GLIDING));
if (tetris_playfield_collision(pPl, pPl->nColumn, pPl->nRow + 1))
{
uint16_t nPiece = tetris_piece_getBitmap(pPl->pPiece);
// Is the playfield filled up?
if ((pPl->nRow < 0) && (nPiece & (0x0FFF >> ((3 + pPl->nRow) << 2))) != 0)
{
pPl->status = TETRIS_PFS_GAMEOVER;
}
else
{
// determine valid start point for dump index
int8_t nStartRow = ((pPl->nRow + 3) < pPl->nHeight) ?
(pPl->nRow + 3) : pPl->nHeight - 1;
for (int8_t i = nStartRow; i >= pPl->nRow; --i)
{
int8_t y = i - pPl->nRow;
// clear all bits of the piece we are not interested in and
// align the rest to LSB
uint16_t nPieceMap = (nPiece & (0x000F << (y << 2))) >> (y << 2);
// shift the remaining content to the current column
if (pPl->nColumn >= 0)
{
nPieceMap <<= pPl->nColumn;
}
else
{
nPieceMap >>= -pPl->nColumn;
}
// embed piece in playfield
pPl->dump[i] |= nPieceMap;
}
// the piece has finally been docked
pPl->status = TETRIS_PFS_DOCKED;
}
}
else
{
// since there is no collision the piece may continue its travel
// to the ground...
pPl->nRow++;
// are we gliding?
pPl->status = tetris_playfield_hoverStatus(pPl);
}
}
/* Function: tetris_playfield_movePiece
* Description: moves piece to the given direction
* Argument pPl: playfield to perform action on
* Argument direction: direction (see tetris_playfield_direction_t)
* Return value: 1 if piece could be moved, 0 otherwise
*/
uint8_t tetris_playfield_movePiece(tetris_playfield_t *pPl,
tetris_playfield_direction_t direction)
{
assert(pPl != NULL);
// a piece can only be moved if it is still hovering or gliding
assert((pPl->status == TETRIS_PFS_HOVERING) ||
(pPl->status == TETRIS_PFS_GLIDING));
int8_t nOffset = (direction == TETRIS_PFD_LEFT) ? -1 : 1;
if (tetris_playfield_collision(pPl, pPl->nColumn + nOffset, pPl->nRow) == 0)
{
pPl->nColumn += nOffset;
// are we gliding?
pPl->status = tetris_playfield_hoverStatus(pPl);
return 1;
}
return 0;
}
/* Function: tetris_playfield_rotatePiece
* Description: rotates piece to the given direction
* Argument pPl: playfield to perform action on
* Argument r: type of rotation (see tetris_piece_rotation_t)
* Return value: 1 if piece could be rotated, 0 otherwise
*/
uint8_t tetris_playfield_rotatePiece(tetris_playfield_t *pPl,
tetris_piece_rotation_t rotation)
{
assert(pPl != NULL);
// a piece can only be rotation if it is still hovering or gliding
assert((pPl->status == TETRIS_PFS_HOVERING) ||
(pPl->status == TETRIS_PFS_GLIDING));
tetris_piece_rotate(pPl->pPiece, rotation);
// does the rotated piece cause a collision?
if (tetris_playfield_collision(pPl, pPl->nColumn, pPl->nRow) != 0)
{
// in that case we revert the rotation
if (rotation == TETRIS_PC_ROT_CW)
{
tetris_piece_rotate(pPl->pPiece, TETRIS_PC_ROT_CCW);
}
else
{
tetris_piece_rotate(pPl->pPiece, TETRIS_PC_ROT_CW);
}
return 0;
}
// are we gliding?
pPl->status = tetris_playfield_hoverStatus(pPl);
return 1;
}
/* Function: tetris_playfield_removeCompletedLines
* Description: removes completed lines (if any) and lowers the dump
* Argument pPl: playfield to perform action on
* Return value: void
*/
void tetris_playfield_removeCompleteLines(tetris_playfield_t *pPl)
{
assert(pPl != NULL);
// rows can only be removed if we are in state TETRIS_PFS_DOCKED
assert(pPl->status == TETRIS_PFS_DOCKED);
// bit mask of a full row
uint16_t nFullRow = 0xFFFF >> (16 - pPl->nWidth);
// bit mask (only 4 bits) that tells us if the n-th row after the
// current nRow is complete (n-th bit set to 1, LSB represents nRow itself)
uint8_t nRowMask = 0;
// determine sane start and stop values for the dump' index
int8_t nStartRow =
((pPl->nRow + 3) >= pPl->nHeight) ? pPl->nHeight - 1 : pPl->nRow + 3;
int8_t nStopRow = (pPl->nRow < 0) ? 0 : pPl->nRow;
// dump index variables
// for incomplete rows, both variables will be decremented
// for complete rows, only i gets decremented
int8_t nLowestRow = nStartRow;
// this loop only considers rows which are affected by the piece
for (int8_t i = nStartRow; i >= nStopRow; --i)
{
// is current row a full row?
if ((nFullRow & pPl->dump[i]) == nFullRow)
{
// set corresponding bit for the row mask
// nRowMask |= 0x08 >> (nStartRow - i);
nRowMask |= 0x01 << (i - pPl->nRow);
}
else
{
// if nLowestRow and i differ, the dump has to be shifted
if (i < nLowestRow)
{
pPl->dump[nLowestRow] = pPl->dump[i];
}
--nLowestRow;
}
}
// if rows have been removed, this loop shifts the rest of the dump
uint8_t nComplete = nLowestRow - nStopRow + 1;
if (nComplete > 0)
{
for (int8_t i = nStopRow - 1; nLowestRow >= 0; --i)
{
// is the row we are copying from below the upper border?
if (i >= 0)
{
// just copy from that row
pPl->dump[nLowestRow] = pPl->dump[i];
}
else
{
// rows above the upper border are always empty
pPl->dump[nLowestRow] = 0;
}
--nLowestRow;
}
}
// ready to get the next piece
pPl->status = TETRIS_PFS_READY;
pPl->nRowMask = nRowMask;
}
/*****************
* get functions *
*****************/
/* Function: tetris_playfield_getWidth
* Description: returns the width of the playfield
* Argument pPl: the playfield we want information from
* Return value: width of the playfield
*/
int8_t tetris_playfield_getWidth(tetris_playfield_t *pPl)
{
assert(pPl != NULL);
return pPl->nWidth;
}
/* Function: tetris_playfield_getHeight
* Description: returns the height of the playfield
* Argument pPl: the playfield we want information from
* Return value: height of the playfield
*/
int8_t tetris_playfield_getHeight(tetris_playfield_t *pPl)
{
assert(pPl != NULL);
return pPl->nHeight;
}
/* Function: tetris_playfield_getPiece
* Description: returns the currently falling piece
* Argument pPl: the playfield we want information from
* Return value: pointer to the currently falling piece
*/
tetris_piece_t *tetris_playfield_getPiece(tetris_playfield_t *pPl)
{
assert(pPl != NULL);
return pPl->pPiece;
}
/* Function: tetris_playfield_getColumn
* Description: returns the column of the currently falling piece
* Argument pPl: the playfield we want information from
* Return value: column of the currently falling piece
*/
int8_t tetris_playfield_getColumn(tetris_playfield_t *pPl)
{
assert(pPl != NULL);
return pPl->nColumn;
}
/* Function: tetris_playfield_getRow
* Description: returns the row of the currently falling piece
* Argument pPl: the playfield we want information from
* Return value: row of the currently falling piece
*/
int8_t tetris_playfield_getRow(tetris_playfield_t *pPl)
{
assert(pPl != NULL);
return pPl->nRow;
}
/* Function: tetris_playfield_getRowMask
* Description: returns the row mask relative to nRow
* Argument pPl: the playfield we want information from
* Return value: the first 4 bits indicate which lines (relative to nRow)
* have been removed if we are in status TETRIS_PFS_READY
* LSB is the highest line
*/
uint8_t tetris_playfield_getRowMask(tetris_playfield_t *pPl)
{
assert(pPl != NULL);
return pPl->nRowMask;
}
/* Function: tetris_playfield_getStatus
* Description: returns the status of the playfield
* Argument pPl: the playfield we want information from
* Return value: status of the playfield (see tetris_playfield_status_t)
*/
tetris_playfield_status_t tetris_playfield_getStatus(tetris_playfield_t *pPl)
{
assert(pPl != NULL);
return pPl->status;
}
/* Function: tetris_playfield_getDumpRow
* Description: returns the given row of the dump (as bitmap)
* Argument pPl: the playfield we want information from
* Argument nRow: the number of the row (0 <= nRow < height of playfield)
* Return value: bitmap of the requested row (LSB is leftmost column)
*/
uint16_t tetris_playfield_getDumpRow(tetris_playfield_t *pPl,
int8_t nRow)
{
assert(pPl != NULL);
assert((0 <= nRow) && (nRow < pPl->nHeight));
return pPl->dump[nRow];
}

213
games/tetris/playfield.h

@ -0,0 +1,213 @@
#ifndef TETRIS_PLAYFIELD_H_
#define TETRIS_PLAYFIELD_H_
#include <inttypes.h>
#include "piece.h"
/*********
* types *
*********/
// directions to which a piece can be moved
typedef enum tetris_playfield_direction_t
{
TETRIS_PFD_LEFT,
TETRIS_PFD_RIGHT
}
tetris_playfield_direction_t;
// status of the playfield
typedef enum tetris_playfield_status_t
{
TETRIS_PFS_READY, // ready to get next piece
TETRIS_PFS_HOVERING, // piece is still hovering
TETRIS_PFS_GLIDING, // piece is gliding on the dump
TETRIS_PFS_DOCKED, // piece has been docked
TETRIS_PFS_GAMEOVER // playfield is filled up
}
tetris_playfield_status_t;
// tetris_playfield_t
typedef struct tetris_playfield_t
{
int8_t nWidth; // width of playfield
int8_t nHeight; // height of playfield
tetris_piece_t *pPiece; // currently falling piece
int8_t nColumn; // horz. piece pos. (0 is left)
int8_t nRow; // vert. piece pos. (0 is top)
uint8_t nRowMask; // removed lines relative to nRow (bitmap)
tetris_playfield_status_t status; // status
uint16_t *dump; // playfield itself
}
tetris_playfield_t;
/****************************
* construction/destruction *
****************************/
/* Function: tetris_playfield_construct
* Description: constructs a playfield with the given diemensions
* Argument nWidth: width of playfield (4 <= n <= 16)
* Argument nHeight: height of playfield (4 <= n <= 124)
* Return value: pointer to a newly created playfield
*/
tetris_playfield_t *tetris_playfield_construct(int8_t nWidth, int8_t nHeight);
/* Function: tetris_playfield_destruct
* Description: destructs a playfield
* Argument pPl: pointer to the playfield to be destructed
* Return value: void
*/
void tetris_playfield_destruct(tetris_playfield_t *pPl);
/*******************************
* playfield related functions *
*******************************/
/* Function: tetris_playfield_reset
* Description: resets playfield to begin a new game
* Argument pPl: playfield to perform action on
* Return value: void
*/
void tetris_playfield_reset(tetris_playfield_t *pPl);
/* Function: tetris_playfield_insertPiece
* Description: inserts a new piece
* Argument pPl: playfield to perform action on
* Argument pPiece: piece to be inserted
* Argument ppOldPiece: [out] indirect pointer to former piece for deallocation
* Return value: void
*/
void tetris_playfield_insertPiece(tetris_playfield_t *pPl,
tetris_piece_t *pPiece,
tetris_piece_t** ppOldPiece);
/* Function: tetris_playfield_collision
* Description: detects if piece collides with s.th. at a given position
* Argument pPl: playfield to perform action on
* Argument nColumn: column where the piece should be moved
* Argument nRow: row where the piece should be moved
* Return value: 1 for collision, 0 otherwise
*/
uint8_t tetris_playfield_collision(tetris_playfield_t *pPl,
int8_t nColumn,
int8_t nRow);
/* Function: tetris_playfield_advancePiece
* Description: lowers piece by one row or finally docks it
* Argument pPl: playfield to perform action on
* Return value: void
*/
void tetris_playfield_advancePiece(tetris_playfield_t *pPl);
/* Function: tetris_playfield_movePiece
* Description: moves piece to the given direction
* Argument pPl: playfield to perform action on
* Argument direction: direction (see tetris_playfield_direction_t)
* Return value: 1 if piece could be moved, 0 otherwise
*/
uint8_t tetris_playfield_movePiece(tetris_playfield_t *pPl,
tetris_playfield_direction_t direction);
/* Function: tetris_playfield_rotatePiece
* Description: rotates piece to the given direction
* Argument pPl: playfield to perform action on
* Argument r: type of rotation (see tetris_piece_rotation_t)
* Return value: 1 if piece could be rotated, 0 otherwise
*/
uint8_t tetris_playfield_rotatePiece(tetris_playfield_t *pPl,
tetris_piece_rotation_t rotation);
/* Function: tetris_playfield_removeCompletedLines
* Description: removes completed lines (if any) and lowers the dump
* Argument pPl: playfield to perform action on
* Return value: void
*/
void tetris_playfield_removeCompleteLines(tetris_playfield_t *pPl);
/*****************
* get functions *
*****************/
/* Function: tetris_playfield_getWidth
* Description: returns the width of the playfield
* Argument pPl: the playfield we want information from
* Return value: width of the playfield
*/
int8_t tetris_playfield_getWidth(tetris_playfield_t *pPl);
/* Function: tetris_playfield_getHeight
* Description: returns the height of the playfield
* Argument pPl: the playfield we want information from
* Return value: height of the playfield
*/
int8_t tetris_playfield_getHeight(tetris_playfield_t *pPl);
/* Function: tetris_playfield_getPiece
* Description: returns the currently falling piece
* Argument pPl: the playfield we want information from
* Return value: pointer to the currently falling piece
*/
tetris_piece_t *tetris_playfield_getPiece(tetris_playfield_t *pPl);
/* Function: tetris_playfield_getColumn
* Description: returns the column of the currently falling piece
* Argument pPl: the playfield we want information from
* Return value: column of the currently falling piece
*/
int8_t tetris_playfield_getColumn(tetris_playfield_t *pPl);
/* Function: tetris_playfield_getRow
* Description: returns the row of the currently falling piece
* Argument pPl: the playfield we want information from
* Return value: row of the currently falling piece
*/
int8_t tetris_playfield_getRow(tetris_playfield_t *pPl);
/* Function: tetris_playfield_getRowMask
* Description: returns the row mask relative to nRow
* Argument pPl: the playfield we want information from
* Return value: the first 4 bits indicate which lines (relative to nRow)
* have been removed if we are in status TETRIS_PFS_READY
*/
uint8_t tetris_playfield_getRowMask(tetris_playfield_t *pPl);
/* Function: tetris_playfield_getStatus
* Description: returns the status of the playfield
* Argument pPl: the playfield we want information from
* Return value: status of the playfield (see tetris_playfield_status_t)
*/
tetris_playfield_status_t tetris_playfield_getStatus(tetris_playfield_t *pPl);
/* Function: tetris_playfield_getDumpRow
* Description: returns the given row of the dump (as bitmap)
* Argument pPl: the playfield we want information from
* Argument nRow: the number of the row (0 <= nRow <= 124)
* Return value: bitmap of the requested row (LSB is leftmost column)
*/
uint16_t tetris_playfield_getDumpRow(tetris_playfield_t *pPl,
int8_t nRow);
#endif /*TETRIS_PLAYFIELD_H_*/

421
games/tetris/view.c

@ -0,0 +1,421 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <inttypes.h>
#include "../config.h"
#include "../pixel.h"
#include "../util.h"
#include "../scrolltext.h"
#include "logic.h"
#include "piece.h"
#include "playfield.h"
#include "view.h"
/* the API simulator and the real API have different named wait functions */
#ifdef __AVR__
#define WAIT(ms) wait(ms)
#else
#define WAIT(ms) myWait(ms)
#endif
/***********
* defines *
***********/
// how often should the border blink (to indicate level up)
#define TETRIS_VIEW_BORDER_BLINK_COUNT 2
// amount of time (in ms) between border color changes
#define TETRIS_VIEW_BORDER_BLINK_DELAY 100
// how often should the lines blink when they get removed
#define TETRIS_VIEW_LINE_BLINK_COUNT 3
// amount of time (in ms) between line color changes
#define TETRIS_VIEW_LINE_BLINK_DELAY 75
// colors of game elements
#define TETRIS_VIEW_COLORSPACE 0
#define TETRIS_VIEW_COLORBORDER 1
#define TETRIS_VIEW_COLORFADE 2
#define TETRIS_VIEW_COLORPIECE 3
/***************************
* non-interface functions *
***************************/
/* Function: tetris_view_getPieceColor
* Description: helper function to dim the piece color if game is paused
* Argument pV: pointer to the view whose pause status is of interest
* Return value: void
*/
uint8_t tetris_view_getPieceColor (tetris_view_t *pV)
{
if (pV->modeCurrent == TETRIS_VIMO_RUNNING)
{
return TETRIS_VIEW_COLORPIECE;
}
else
{
return TETRIS_VIEW_COLORBORDER;
}
}
/* Function: tetris_view_drawDump
* Description: redraws the dump and the falling piece (if necessary)
* Argument pV: pointer to the view on which the dump should be drawn
* Return value: void
*/
void tetris_view_drawDump(tetris_view_t *pV)
{
assert(pV->pPl != NULL);
if (tetris_playfield_getRow(pV->pPl) <= -4)
{
return;
}
int8_t nPieceRow = tetris_playfield_getRow(pV->pPl);
// only redraw dump completely if the view mode has been changed
int8_t nStartRow;
if (pV->modeCurrent == pV->modeOld)
{
nStartRow = ((nPieceRow + 3) < 16) ? (nPieceRow + 3) : 15;
}
else
{
nStartRow = 15;
}
uint16_t nRowMap;
uint16_t nElementMask;
tetris_playfield_status_t status = tetris_playfield_getStatus(pV->pPl);
for (int8_t nRow = nStartRow; nRow >= 0; --nRow)
{
nRowMap = tetris_playfield_getDumpRow(pV->pPl, nRow);
// if a piece is hovering or gliding it needs to be drawn
if ((status == TETRIS_PFS_HOVERING) || (status == TETRIS_PFS_GLIDING) ||
(status == TETRIS_PFS_GAMEOVER))
{
if ((nRow >= nPieceRow) && (nRow <= nPieceRow + 3))
{
int8_t y = nRow - nPieceRow;
int8_t nColumn = tetris_playfield_getColumn(pV->pPl);
uint16_t nPieceMap =
tetris_piece_getBitmap(tetris_playfield_getPiece(pV->pPl));
// clear all bits of the piece we are not interested in and
// align the remaining row to LSB
nPieceMap = (nPieceMap & (0x000F << (y << 2))) >> (y << 2);
// shift remaining part to current column
if (nColumn >= 0)
{
nPieceMap <<= nColumn;
}
else
{
nPieceMap >>= -nColumn;
}
// cut off unwanted stuff
nPieceMap &= 0x03ff;
// finally embed piece into the view
nRowMap |= nPieceMap;
}
}
nElementMask = 0x0001;
for (int8_t x = 0; x < 10; ++x)
{
unsigned char nColor;
if ((nRowMap & nElementMask) != 0)
{
nColor = tetris_view_getPieceColor(pV);
}
else
{
nColor = TETRIS_VIEW_COLORSPACE;
}
setpixel((pixel){14-x,nRow}, nColor);
nElementMask <<= 1;
}
}
}
/* Function: tetris_view_drawPreviewPiece
* Description: redraws the preview window
* Argument pV: pointer to the view on which the piece should be drawn
* Argmument pPc: pointer to the piece for the preview window (may be NULL)
* Return value: void
*/
void tetris_view_drawPreviewPiece(tetris_view_t *pV, tetris_piece_t *pPc)
{
if (pPc != NULL)
{
uint8_t nColor;
uint16_t nElementMask = 0x0001;
uint16_t nPieceMap;
if (pV->modeCurrent == TETRIS_VIMO_RUNNING)
{
nPieceMap = tetris_piece_getBitmap(pPc);
}
else
{
nPieceMap = 0x26a6;
}
for (uint8_t y = 0; y < 4; ++y)
{
for (uint8_t x = 0; x < 4; ++x)
{
if ((nPieceMap & nElementMask) != 0)
{
nColor = TETRIS_VIEW_COLORPIECE;
}
else
{
nColor = TETRIS_VIEW_COLORSPACE;
}
setpixel((pixel) {3 - x, y + 6}, nColor);
nElementMask <<= 1;
}
}
}
else
{
for (uint8_t y = 0; y < 4; ++y)
{
for (uint8_t x = 0; x < 4; ++x)
{
setpixel((pixel) {3 - x, y + 6}, TETRIS_VIEW_COLORSPACE);
}
}
}
}
/* Function: tetris_view_drawBorders
* Description: draws borders in the given color
* Argument nColor: the color for the border
* Return value: void
*/
void tetris_view_drawBorders(uint8_t nColor)
{
// drawing playfield
uint8_t x, y;
for (y = 0; y < 16; ++y)
{
setpixel((pixel){4, y}, nColor);
setpixel((pixel){15, y}, nColor);
}
for (y = 0; y < 5; ++y)
{
for (x = 0; x <= 3; ++x){
setpixel((pixel){x, y}, nColor);
setpixel((pixel){x, y + 11}, nColor);
}
}
}
/* Function: tetris_view_blinkBorders
* Description: lets the borders blink to notify player of a level change
* Return value: void
*/
void tetris_view_blinkBorders()
{
for (uint8_t i = 0; i < TETRIS_VIEW_BORDER_BLINK_COUNT; ++i)
{
tetris_view_drawBorders(TETRIS_VIEW_COLORPIECE);
WAIT(TETRIS_VIEW_BORDER_BLINK_DELAY);
tetris_view_drawBorders(TETRIS_VIEW_COLORBORDER);
WAIT(TETRIS_VIEW_BORDER_BLINK_DELAY);
}
}
/* Function: tetris_view_blinkLines
* Description: lets complete lines blink to emphasize their removal
* Argmument pPl: pointer to the playfield whose complete lines should blink
* Return value: void
*/
void tetris_view_blinkLines(tetris_playfield_t *pPl)
{
// reduce necessity of pointer arithmetic
int8_t nRow = tetris_playfield_getRow(pPl);
uint8_t nRowMask = tetris_playfield_getRowMask(pPl);
// don't try to draw below the border
int8_t nDeepestRowOffset = ((nRow + 3) < tetris_playfield_getHeight(pPl) ?
3 : tetris_playfield_getHeight(pPl) - (nRow + 1));
// this loop controls how often the lines should blink
for (uint8_t i = 0; i < TETRIS_VIEW_LINE_BLINK_COUNT; ++i)
{
// this loop determines the color of the line to be drawn
for (uint8_t nColIdx = 0; nColIdx < 2; ++nColIdx)
{
// iterate through the possibly complete lines
for (uint8_t j = 0; j <= nDeepestRowOffset; ++j)
{
// is current line a complete line?
if ((nRowMask & (0x01 << j)) != 0)
{
// draw line in current color
uint8_t y = nRow + j;
for (uint8_t x = 0; x < 10; ++x)
{
uint8_t nColor = (nColIdx == 0 ? TETRIS_VIEW_COLORFADE
: TETRIS_VIEW_COLORPIECE);
setpixel((pixel){14 - x, y}, nColor);
}
}
}
// wait a few ms to make the blink effect visible
WAIT(TETRIS_VIEW_LINE_BLINK_DELAY);
}
}
}
/****************************
* construction/destruction *
****************************/
/* Function: tetris_view_construct
* Description: constructs a view for André's borg
* Argument pPl: pointer to logic object which should be observed
* Argument pPl: pointer to playfield which should be observed
* Return value: pointer to a newly created view
*/
tetris_view_t *tetris_view_construct(tetris_logic_t *pLogic,
tetris_playfield_t *pPl)
{
// memory allocation
assert((pLogic != NULL) && (pPl != NULL));
tetris_view_t *pView =
(tetris_view_t *) malloc(sizeof(tetris_view_t));
assert(pView != NULL);
// init
memset(pView, 0, sizeof(tetris_view_t));
pView->pLogic = pLogic;
pView->pPl = pPl;
pView->modeCurrent = TETRIS_VIMO_RUNNING;
pView->modeOld = TETRIS_VIMO_RUNNING;
// drawing some first stuff
clear_screen(0);
tetris_view_drawBorders(TETRIS_VIEW_COLORBORDER);
return pView;
}
/* Function: tetris_view_destruct
* Description: destructs a view
* Argument pView: pointer to the view which should be destructed
* Return value: void
*/
void tetris_view_destruct(tetris_view_t *pView)
{
assert(pView != NULL);
free(pView);
}
/***************************
* view related functions *
***************************/
/* Function: tetris_view_getDimensions
* Description: destructs a view
* Argument w: [out] pointer to an int8_t to store the playfield width
* Argument h: [out] pointer to an int8_t to store the playfield height
* Return value: void
*/
void tetris_view_getDimensions(int8_t *w,
int8_t *h)
{
assert((w != NULL) && (h != NULL));
*w = 10;
*h = 16;
}
/* Function: tetris_view_setViewMode
* Description: sets the view mode (pause or running)
* Argument pV: pointer to the view whose mode should be set
* Argument vm: see definition of tetris_view_mode_t
* Return value: void
*/
void tetris_view_setViewMode(tetris_view_t *pV, tetris_view_mode_t vm)
{
pV->modeOld = pV->modeCurrent;
pV->modeCurrent = vm;
}
/* Function: tetris_view_update
* Description: informs a view about changes in the game
* Argument pV: pointer to the view which should be updated
* Return value: void
*/
void tetris_view_update(tetris_view_t *pV)
{
assert(pV != NULL);
// let complete lines blink (if there are any)
if (tetris_playfield_getRowMask(pV->pPl) != 0)
{
tetris_view_blinkLines(pV->pPl);
}
// draw preview piece
tetris_view_drawPreviewPiece(pV, tetris_logic_getPreviewPiece(pV->pLogic));
// draw dump
tetris_view_drawDump(pV);
// visual feedback to inform about a level change
uint8_t nLevel = tetris_logic_getLevel(pV->pLogic);
if (nLevel != pV->nOldLevel)
{
tetris_view_blinkBorders();
pV->nOldLevel = nLevel;
}
}
/* Function: tetris_view_showResults
* Description: shows results after game
* Argument pV: pointer to the view which should show the reults
* Return value: void
*/
void tetris_view_showResults(tetris_view_t *pV)
{
char pszResults[48];
uint16_t nScore = tetris_logic_getScore(pV->pLogic);
uint16_t nHighscore = tetris_logic_getHighscore(pV->pLogic);
uint16_t nLines = tetris_logic_getLines(pV->pLogic);
if (nScore <= nHighscore)
{
snprintf(pszResults, 48 * sizeof(char),
"</#Lines %u Score %u Highscore %u",
nLines, nScore, nHighscore);
}
else
{
snprintf(pszResults, 48 * sizeof(char),
"</#Lines %u New Highscore %u", nLines, nScore);
}
scrolltext(pszResults);
}

95
games/tetris/view.h

@ -0,0 +1,95 @@
#ifndef TETRIS_VIEW_H_
#define TETRIS_VIEW_H_
#include <inttypes.h>
#include "logic.h"
#include "piece.h"
#include "playfield.h"
/*********
* types *
*********/
// presentation modes
typedef enum tetris_view_mode_t
{
TETRIS_VIMO_PAUSED,
TETRIS_VIMO_RUNNING
}
tetris_view_mode_t;
typedef struct tetris_view_t
{
tetris_logic_t *pLogic; // associated logic object
tetris_playfield_t *pPl; // associated playfield
tetris_view_mode_t modeCurrent; // current presentation mode
tetris_view_mode_t modeOld; // old presentation mode
uint8_t nOldLevel; // helper variable to recognize level changes
}
tetris_view_t;
/*****************************
* construction/destruction *
*****************************/
/* Function: tetris_view_construct
* Description: constructs a view for André's borg
* Argument pPl: pointer to logic object which should be observed
* Argument pPl: pointer to playfield which should be observed
* Return value: pointer to a newly created view
*/
tetris_view_t *tetris_view_construct(tetris_logic_t *pLogic,
tetris_playfield_t *pPl);
/* Function: tetris_view_destruct
* Description: destructs a view
* Argument pView: pointer to the view to be destructed
* Return value: void
*/
void tetris_view_destruct(tetris_view_t *pView);
/***************************
* view related functions *
***************************/
/* Function: tetris_view_getDimensions
* Description: destructs a view
* Argument w: [out] pointer to an int8_t to store the playfield width
* Argument h: [out] pointer to an int8_t to store the playfield height
* Return value: void
*/
void tetris_view_getDimensions(int8_t *w,
int8_t *h);
/* Function: tetris_view_setViewMode
* Description: sets the view mode (pause or running)
* Argument pV: pointer to the view whose mode should be set
* Argument vm: see definition of tetris_view_mode_t
* Return value: void
*/
void tetris_view_setViewMode(tetris_view_t *pV, tetris_view_mode_t vm);
/* Function: tetris_view_update
* Description: informs a view about changes in the game
* Argument pV: pointer to the view which should be updated
* Return value: void
*/
void tetris_view_update(tetris_view_t *pV);
/* Function: tetris_view_showResults
* Description: shows results after game
* Argument pV: pointer to the view which should show the reults
* Return value: void
*/
void tetris_view_showResults(tetris_view_t *pV);
#endif /*TETRIS_VIEW_H_*/

13
joystick.c

@ -0,0 +1,13 @@
#include "joystick.h"
#include <avr/io.h>
unsigned char waitForFire;
inline void joy_init(){
DDRB &= ~((1<<BITUP)|(1<<BITDOWN)|(1<<BITLEFT)|(1<<BITRIGHT));
PORTB |= (1<<BITUP)|(1<<BITDOWN)|(1<<BITLEFT)|(1<<BITRIGHT);
DDRD &= ~(1<<BITFIRE);
PORTD |= (1<<BITFIRE);
}

21
joystick.h

@ -0,0 +1,21 @@
#ifndef JOYSTICK_H
#define JOYSTICK_H
#include <avr/io.h>
unsigned char waitForFire;
void joy_init();
#define BITFIRE PD3
#define BITRIGHT PB3
#define BITLEFT PB2
#define BITDOWN PB1
#define BITUP PB0
#define JOYISFIRE (!(PIND & (1<<BITFIRE)))
#define JOYISLEFT (!(PINB & (1<<BITLEFT)))
#define JOYISRIGHT (!(PINB & (1<<BITRIGHT)))
#define JOYISDOWN (!(PINB & (1<<BITDOWN)))
#define JOYISUP (!(PINB & (1<<BITUP)))
#endif // JOYSTICK_H

149
main.c

@ -0,0 +1,149 @@
#include <setjmp.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include "autoconf.h"
//#include "config.h"
#include "scrolltext/scrolltext.h"
#include "animations/programm.h"
#include "animations/matrix.h"
#include "animations/gameoflife.h"
#include "borg_hw/borg_hw.h"
#include "can/borg_can.h"
#include "random/prng.h"
#include "random/persistentCounter.h"
#include "mcuf/mcuf.h"
#include "menu/menu.h"
#include "pixel.h"
#include "joystick.h"
volatile unsigned char oldMode, oldOldmode, mode;
jmp_buf newmode_jmpbuf;
int main (void){
clear_screen(0);
borg_hw_init();
#ifdef RANDOM_SUPPORT
srandom32(percnt_get());
percnt_inc();
#endif
#ifdef CAN_SUPPORT
bcan_init();
#endif
#ifdef JOYSTICK_SUPPORT
joy_init();
#endif
#ifdef UART_SUPPORT
uart_init();
#endif
sei();
// mcuf_serial_mode();
mode = setjmp(newmode_jmpbuf);
oldOldmode = oldMode;
waitForFire = 1;
for(;;){
oldMode = mode;
switch(mode++) {
#ifdef ANIMATION_SCROLLTEXT
case 1:
scrolltext(scrolltext_text);
{ char a[14];
sprintf(a,"</# counter == %lu ", percnt_get());
scrolltext(a);
}
break;
#endif
#ifdef ANIMATION_SPIRALE
case 2:
spirale(5);
break;
#endif
#ifdef ANIMATION_JOERN1
case 3:
joern1();
break;
#endif
#ifdef ANIMATION_SNAKE
case 4:
snake();
break;
#endif
#ifdef ANIMATION_SCHACHBRETT
case 5:
schachbrett(20);
break;
#endif
#ifdef ANIMATION_FEUER
case 6:
feuer();
break;
#endif
#ifdef ANIMATION_MATRIX
case 7:
matrix();
break;
#endif
#ifdef ANIMATION_RANDOM_BRIGHT
case 8:
random_bright(200);
break;
#endif
#ifdef ANIMATION_GAMEOFLIFE
case 9:
gameoflife();
break;
#endif
case 29:
mode = 1;
break;
#ifdef ANIMATION_TESTS
case 31:
test_level1();
break;
case 32:
test_level2();
break;
case 33:
test_level3();
break;
case 35:
test1();
while(1);
break;
#endif
#ifdef ANIMATION_OFF
case 0xFF:
off();
break;
#endif
#ifdef MENU_SUPPORT
case 43:
menu();
mode = oldOldmode;
#endif
}
}
}

2
makros.h

@ -0,0 +1,2 @@
#define DDR(port) (*(volatile uint8_t*)((&port)-1))

76
mcuf/mcuf.c

@ -0,0 +1,76 @@
#include "uart.h"
#include "pixel.h"
#define my_uart_getc uart_getc
typedef struct
{
uint32_t magic;
uint8_t height_h;
uint8_t height_l;
uint8_t width_h;
uint8_t width_l;
uint16_t channels;
uint16_t maxval;
uint8_t pixels[256];
} mcuf_t;
static void parse_mcuf(mcuf_t * mcuf){
if(mcuf->height_l == 8 && mcuf->width_l == 18){
uint8_t x,y;
for(y=0;y<8;y++){
for(x=0;x<16;x++){
setpixel((pixel){15-x, y+4}, mcuf->pixels[y*18 + x + 1] >> 6 );
}
}
}else if(mcuf->height_l == 16 && mcuf->width_l == 16){
uint8_t x,y;
for(y=0;y<16;y++){
for(x=0;x<16;x++){
setpixel((pixel){15-x, y}, mcuf->pixels[y*16 + x] >> 6 );
}
}
}
}
static uint8_t mcuf_magic[4] = {0x23, 0x54, 0x26, 0x66};
void mcuf_serial_mode(){
mcuf_t mcuf_packet;
uint8_t c;
while(1){
uint16_t count = 0;
uint8_t x;
uint16_t num_pixels;
do{
c = my_uart_getc();
((uint8_t*)&mcuf_packet)[count] = c;
if(c == mcuf_magic[count] ){
count ++;
}else{
count = 0;
}
}while(count != 4);
for(x=0; x<4; x++){
c = my_uart_getc();
((uint8_t*)&mcuf_packet)[count++] = c;
}
num_pixels = (uint16_t)mcuf_packet.width_l * mcuf_packet.height_l;
if(num_pixels <= 256){
num_pixels += 4;
while(num_pixels--){
c = my_uart_getc();
((uint8_t*)&mcuf_packet)[count++] = c;
}
parse_mcuf(&mcuf_packet);
}
}
}

3
mcuf/mcuf.h

@ -0,0 +1,3 @@
void mcuf_serial_mode();

272
menu/menu.c

@ -0,0 +1,272 @@
/* A game chooser for borgs
* by: Christian Kroll
* date: Thursday, 2008/03/16
*/
#include <stdlib.h>
#include <assert.h>
#include <inttypes.h>
// architecture dependent stuff
#ifdef __AVR__
#include <avr/pgmspace.h>
#define WAIT(ms) wait(ms)
#else
#define PROGMEM
#define WAIT(ms) myWait(ms)
#endif
#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"
// defines
#define MENU_WIDTH_ICON 8
#define MENU_HEIGHT_ICON 8
#define MENU_WIDTH_DELIMITER 2
#define MENU_POLL_INTERVAL 10
#define MENU_TIMEOUT_ITERATIONS 2000
#define MENU_WAIT_CHATTER 60
#define MENU_WAIT_INITIAL 40
#define MENU_WAIT_INCREMENT 0
#define MENU_NEXTITEM(item) ((item + 1) % MENU_ITEM_MAX)
#define MENU_PREVITEM(item) ((item + MENU_ITEM_MAX - 1) % MENU_ITEM_MAX)
void menu()
{
// don't let WAIT() query fire button to prevent endless circular jumps
waitForFire = 0;
clear_screen(0);
// wait as long the fire button is pressed to prevent unwanted selections
while (JOYISFIRE)
{
WAIT(MENU_POLL_INTERVAL);
}
// set initial menu item
static menu_item_t miSelection = MENU_ITEM_TETRIS;
// scroll in currently selected menu item
menu_animate(MENU_PREVITEM(miSelection), MENU_DIRECTION_LEFT);
uint16_t nMenuIterations= MENU_TIMEOUT_ITERATIONS;
while (1)
{
// the user has made her/his choice
if (JOYISFIRE)
{
// prevent unwanted selections
while (JOYISFIRE)
{
WAIT(MENU_POLL_INTERVAL);
}
// work against the chatter effects of dump joysticks
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;
}
break;
}
// change selected item and do some scrolling
else if (JOYISRIGHT)
{
menu_animate(miSelection, MENU_DIRECTION_LEFT);
miSelection = MENU_NEXTITEM(miSelection);
nMenuIterations = MENU_TIMEOUT_ITERATIONS;
}
else if (JOYISLEFT)
{
menu_animate(miSelection, MENU_DIRECTION_RIGHT);
miSelection = MENU_PREVITEM(miSelection);
nMenuIterations = MENU_TIMEOUT_ITERATIONS;
}
// exit menu
else if (JOYISUP)
{
break;
}
// return if timeout is reached
else
{
WAIT(MENU_POLL_INTERVAL);
if (--nMenuIterations == 0)
break;
}
}
waitForFire = 1;
return;
}
uint8_t menu_getIconPixel(menu_item_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
}
else
{
// delimiter
return 0;
}
}
void menu_animate(menu_item_t miInitial, menu_direction_t direction)
{
int16_t nWait= MENU_WAIT_INITIAL;
// space between left border and the icon in the middle
int8_t nWidthSide = (NUM_COLS - MENU_WIDTH_ICON) / 2;
// determine the icon at the leftmost position
menu_item_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)
{
++nBack;
}
mi = (mi + MENU_ITEM_MAX - (nBack % MENU_ITEM_MAX)) % MENU_ITEM_MAX;
// start and stop offsets for the scrolling icons (both are 0 for stills)
int8_t nStart, nStop;
if (direction == MENU_DIRECTION_STILL)
{
nStart = 0;
nStop = 0;
}
else
{
nStart = 1;
nStop = MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER;
}
// draw menu screen for each offset within the nStart/nStop range
int8_t i;
for (i = nStart; i <= nStop; ++i)
{
int8_t nOffset;
if (direction == MENU_DIRECTION_LEFT)
nOffset = i;
else
nOffset = -i;
// offset of the left most icon if it is cut by the left border
int8_t nInitialSideOffset = (((MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER)
- (nWidthSide % (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER)))
+ nOffset + (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER))
% (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER);
// an initial side offset of 0 means the leftmost icon was changed
// if we are scrolling to the left, increment value for leftmost item
if (direction == MENU_DIRECTION_LEFT)
{
if (nInitialSideOffset == 0)
{
mi = MENU_NEXTITEM(mi);
}
}
// draw the icons from the leftmost position (line by line)
int8_t y;
for (y = 0; y < MENU_HEIGHT_ICON; ++y)
{
menu_item_t miCurrent = mi;
int8_t nIconOffset = nInitialSideOffset;
int8_t x;
for (x = 0; x < NUM_COLS; ++x)
{
int8_t nPixel = menu_getIconPixel(miCurrent, nIconOffset, y);
menu_setpixel(x, ((NUM_ROWS - MENU_HEIGHT_ICON) / 2) + y,
nPixel);
if (++nIconOffset >= (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER))
{
nIconOffset = 0;
miCurrent = MENU_NEXTITEM(miCurrent);
}
}
}
// an initial side offset of 0 means the leftmost icon was changed
// if we are scrolling to the right, decrement value for leftmost item
if (direction == MENU_DIRECTION_RIGHT)
{
if (nInitialSideOffset == 0)
{
mi = MENU_PREVITEM(mi);
}
}
// wait between the frames so that the animation can be seen
WAIT(nWait);
// animation speed can be throtteled
nWait += MENU_WAIT_INCREMENT;
}
}
void menu_setpixel(int8_t x, int8_t y, int8_t isSet)
{
uint8_t nColor;
// mirror mirror on the wall, what's the quirkiest API of them all...
x = NUM_COLS - 1 - x;
uint8_t nMiddle = (NUM_COLS - MENU_WIDTH_ICON) / 2;
if (isSet != 0)
{
if ((x >= nMiddle - MENU_WIDTH_DELIMITER) && (x < (nMiddle
+ MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER)))
{
nColor = 3;
}
else if ((x == (nMiddle - MENU_WIDTH_DELIMITER - 1)) || (x == (nMiddle
+ MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER)))
{
nColor = 2;
}
else
{
nColor = 1;
}
}
else
{
nColor = 0;
}
setpixel((pixel){x, y}, nColor);
}

34
menu/menu.h

@ -0,0 +1,34 @@
/* A game chooser for borgs
* by: Christian Kroll
* date: Tuesday, 2008/03/16
*/
#ifndef MENU_H_
#define MENU_H_
#include <inttypes.h>
typedef enum menu_item_t
{
MENU_ITEM_SNAKE,
MENU_ITEM_SPACEINVADERS,
MENU_ITEM_TETRIS,
MENU_ITEM_MAX // fake entry to mark the end
}
menu_item_t;
typedef enum menu_direction_t
{
MENU_DIRECTION_LEFT,
MENU_DIRECTION_RIGHT,
MENU_DIRECTION_STILL
}
menu_direction_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_setpixel(int8_t x, int8_t y, int8_t isSet);
#endif /*MENU_H_*/

127
pixel.c

@ -0,0 +1,127 @@
#define PIXEL_C
#include "config.h"
#include "pixel.h"
#include "borg_hw/borg_hw.h"
unsigned char shl_table[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
void clear_screen(unsigned char value){
unsigned char p,*pix,v=0xff;
unsigned int i;
for(p=0;p<NUMPLANE;p++){
pix=&pixmap[p][0][0];
if(p==value)
v=0;
for(i=0;i<NUM_ROWS*LINEBYTES;i++)
pix[i]=v;
}
}
void setpixel(pixel p, unsigned char value ){
p.x %= NUM_COLS;
if(value>NUMPLANE)
value=NUMPLANE;
unsigned char pos = (p.y%NUM_ROWS)*LINEBYTES + (p.x/8);
unsigned char mask = shl_table[p.x%8];
unsigned char plane;
for(plane=0;plane<value;plane++)
pixmap[plane][0][pos]|=mask;
mask ^=0xff;
for(;plane<NUMPLANE;plane++)
pixmap[plane][0][pos]&=mask;
}
//shifts pixmap left. It is really shifted right, but because col0 is left in the Display it's left.
void shift_pixmap_l(){
unsigned char plane, row, byte;
for(plane=0; plane<NUMPLANE; plane++){
for(row=0;row<NUM_ROWS; row++){
for(byte=0;byte<(LINEBYTES-1);byte++){
pixmap[plane][row][byte] >>= 1;
pixmap[plane][row][byte] |= (pixmap[plane][row][byte+1] & 0x01) * 0x80;;
}
pixmap[plane][row][LINEBYTES-1] >>= 1;
}
}
}
unsigned char get_pixel(pixel p){
if( (p.x >= NUM_COLS) || (p.y >= NUM_ROWS) ){
return 0xff;
}else{
return 0!= (pixmap[0][p.y][p.x/8] & shl_table[p.x%8]);
}
}
unsigned char get_next_pixel(pixel p, direction dir){
pixel tmp;
switch (dir){
case right:
tmp = (pixel){p.x-1, p.y};
break;
case left:
tmp = (pixel){p.x+1, p.y};
break;
case down:
tmp = (pixel){p.x, p.y+1};
break;
case up:
tmp = (pixel){p.x, p.y-1};
break;
default:
tmp = p;
break;
}
return get_pixel(tmp);
}
direction direction_r(direction dir){
switch (dir){
case right:
return(down);
case down:
return(left);
case left:
return(up);
case up:
return (right);
}
return(0);
}
void set_cursor(cursor* cur, pixel p){
cur->pos = p;
switch (cur->mode){
case clear:
clearpixel(p);
break;
case set:
setpixel(p,3);
break;
}
}
pixel next_pixel(pixel pix, direction dir){
switch (dir){
case right:
return((pixel){pix.x-1, pix.y});
break;
case left:
return((pixel){pix.x+1, pix.y});
break;
case down:
return((pixel){pix.x, pix.y+1});
break;
case up:
return((pixel){pix.x, pix.y-1});
break;
}
return (pixel){0,0};
}

41
pixel.h

@ -0,0 +1,41 @@
#ifndef PIXEL_H
#define PIXEL_H
#define LINEBYTES (((NUM_COLS-1)/8)+1)
extern unsigned char shl_table[];
extern unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
typedef struct {
unsigned char x;
unsigned char y;
} pixel;
typedef enum {right,left,up,down} direction;
typedef struct {
pixel pos;
direction dir;
enum{clear=0, set=1} mode;
} cursor;
/****************************************************************************
* Pixel routines
*/
void clear_screen(unsigned char value);
void setpixel(pixel p, unsigned char value);
#define clearpixel(p) setpixel(p, 0);
unsigned char get_pixel(pixel p);
unsigned char get_next_pixel(pixel p, direction dir);
pixel next_pixel(pixel pix, direction dir);
direction direction_r(direction dir);
void shift_pixmap_l();
void set_cursor(cursor* cur, pixel p);
#endif // PIXEL_H

68
random/memxor.S

@ -0,0 +1,68 @@
/* memxor.S */
/*
This file is part of the Crypto-avr-lib/microcrypt-lib.
Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* File: memxor.S
* Author: Daniel Otte
* Date: 2008-08-07
* License: GPLv3 or later
* Description: memxor, XORing one block into another
*
*/
/*
* void memxor(void* dest, const void* src, uint16_t n);
*/
/*
* param dest is passed in r24:r25
* param src is passed in r22:r23
* param n is passed in r20:r21
*/
.global memxor
memxor:
movw r30, r24
movw r26, r22
movw r24, r20
tst r24
brne 1f
tst r25
breq 2f
1:
ld r20, X+
ld r21, Z
eor r20, r21
st Z+, r20
sbiw r24, 1
brne 1b
2:
ret

7
random/memxor.h

@ -0,0 +1,7 @@
#ifndef MEMXOR_H_
#define MEMXOR_H_
#include <stdint.h>
void memxor(void* dest, const void* src, uint16_t n);
#endif

76
random/noekeon.h

@ -0,0 +1,76 @@
/* noekeon.h */
/*
This file is part of the Crypto-avr-lib/microcrypt-lib.
Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NOEKEON_H_
#define NOEKEON_H_
/**
* \author Daniel Otte
* \email daniel.otte@rub.de
* \date 2008-04-11
* \license GPLv3
* \brief
*
*
*/
#include <stdint.h>
typedef uint8_t noekeon_ctx_t[16];
/** \fn void noekeon_enc(void* buffer, void* key)
* \brief noekeon encrytion funtion
*
* This function encrypts a block (64 bit = 8 byte) with the noekeon encrytion
* algorithm. Due to the two modes of noekeon (direct mode and indirect mode)
* the second parameter either points directly to the key (direct mode) or to a
* context generated by the noekeon_init() function (indirect mode)
* \param buffer pointer to the 64 bit (8 byte) block to encrypt
* \param key pointer to either the key (128 bit = 16 byte; direct mode) or
* to the context (indirect mode)
*/
void noekeon_enc(void* buffer, const void* key);
/** \fn void noekeon_enc(void* buffer, void* key)
* \brief noekeon encrytion funtion
*
* This function decrypts a block (64 bit = 8 byte) encrypted with the noekeon
* encrytion algorithm. Due to the two modes of noekeon (direct mode and
* indirect mode) the second parameter either points directly to the key
* (direct mode) or to a context generated by the noekeon_init() function
* (indirect mode)
* \param buffer pointer to the 64 bit (8 byte) block to decrypt
* \param key pointer to either the key (128 bit = 16 byte; direct mode) or
* to the context (indirect mode)
*/
void noekeon_dec(void* buffer, const void* key);
/** \fn void noekeon_init(void* key, noekeon_ctx_t* ctx)
* \brief noekeon context generation function for indirect mode
*
* This function generates a context from the supplied key for using
* noekeon in indirect mode. For using noekeon in direct mode supply the key
* direct to the noekeon_enc() and noekeon_dec() functions
* \param key pointer to the key (128 bit = 16 byte)
* \param ctx pointer to the context to fill with key material
* to the context (indirect mode)
*/
void noekeon_init(const void* key, noekeon_ctx_t* ctx);
#endif /*NOEKEON_H_*/

641
random/noekeon_asm.S

@ -0,0 +1,641 @@
/* noekeon_asm.S */
/*
This file is part of the Crypto-avr-lib/microcrypt-lib.
Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* noekeon assembler implementation for avr
* author: Daniel Otte
* email: daniel.otte@rub.de
* license: GPLv3
*/
#include <avr/io.h>
.macro push_all
push r2
push r3
push r4
push r5
push r6
push r7
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
push r16
push r17
push r28
push r29
.endm
.macro pop_all
pop r29
pop r28
pop r17
pop r16
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop r7
pop r6
pop r5
pop r4
pop r3
pop r2
clr r1
.endm
push_all_func:
pop r31
pop r30
push_all
ijmp
pop_all_func:
pop r31
pop r30
pop_all
ijmp
.macro xchg a b
eor \a, \b
eor \b, \a
eor \a, \b
.endm
.macro op32 op a b
\op \a\()_0, \b\()_0
\op \a\()_1, \b\()_1
\op \a\()_2, \b\()_2
\op \a\()_3, \b\()_3
.endm
.macro op32_4t op a b c d w x y z
\op \a, \w
\op \b, \x
\op \c, \y
\op \d, \z
.endm
.macro op32_prefix op p q a b c d w x y z
\op \p\()\a, \q\()\w
\op \p\()\b, \q\()\x
\op \p\()\c, \q\()\y
\op \p\()\d, \q\()\z
.endm
; === bigendian_rotl32 ===
; this function rotates a 32bit bigendian word n bits to the left
; param1: the 32-bit value
; given in r25,r24,r23,r22 (r22 is most significant)
; param2: the 8-bit parameter giving the number of bits to rotate
; given in r20
; return: the rotatet 32-bit word
; given in r25,r24,r23,r22
bigendian_rotl32:
/* copy high bit of r22 to carry */
mov r1, r22
2:
rol r1
rol r25
rol r24
rol r23
rol r22
dec r20
brne 2b
bigendian_rotl32_exit:
clr r1
ret
/******************************************************************************/
; === bigendian_rotl32 ===
; this function rotates a 32bit bigendian word n bits to the right
; param1: the 32-bit value
; given in r25,r24,r23,r22 (r22 is most significant)
; param2: the 8-bit parameter giving the number of bits to rotate
; given in r20
; return: the rotatet 32-bit word
; given in r25,r24,r23,r22
bigendian_rotr32:
/* copy high bit of r25 to carry */
mov r1, r25
2:
ror r1
ror r22
ror r23
ror r24
ror r25
dec r20
brne 2b
bigendian_rotr32_exit:
clr r1
ret
/******************************************************************************/
/*
void theta(uint32_t* k, uint32_t* a){
uint32_t temp;
temp = a[0] ^ a[2]; temp ^= ROTR32(temp, 8) ^ ROTL32(temp, 8);
a[1] ^= temp;
a[3] ^= temp;
a[0] ^= k[0];
a[1] ^= k[1];
a[2] ^= k[2];
a[3] ^= k[3];
temp = a[1] ^ a[3]; temp ^= ROTR32(temp, 8) ^ ROTL32(temp, 8);
a[0] ^= temp;
a[2] ^= temp;
}
*/
round_const: .byte 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A, \
0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A, \
0xD4
;-- a[0]
state0_0 = 2
state0_1 = 3
state0_2 = 4
state0_3 = 5
;-- a[1]
state1_0 = 6
state1_1 = 7
state1_2 = 8
state1_3 = 9
;-- a[2]
state2_0 = 10
state2_1 = 11
state2_2 = 12
state2_3 = 13
;-- a[3]
state3_0 = 14
state3_1 = 15
state3_2 = 16
state3_3 = 17
; === theta ===
;
; param1: the state in r2-r17
; param2: pointer to k in X (r26,r27)
;
temp_a = 18
temp_b = 19
temp_c = 20
temp_d = 21
theta:
/* temp = a[0] ^ a[2]; temp ^= temp>>>8 ^ temp<<<8 */
op32_prefix mov, temp_, state0_, a,b,c,d, 0,1,2,3
op32_prefix eor, temp_, state2_, a,b,c,d, 0,1,2,3
mov r1, temp_a
eor r1, temp_b
eor r1, temp_c
eor r1, temp_d
op32_prefix eor, temp_, r, a,b,c,d, 1,1,1,1
/* temp is know a little bit mixed c,d,a,b (if abcd is normal order) */
/* a[1] ^= temp */
eor state1_0, temp_c
eor state1_1, temp_d
eor state1_2, temp_a
eor state1_3, temp_b
/* a[3] ^= temp */
eor state3_0, temp_c
eor state3_1, temp_d
eor state3_2, temp_a
eor state3_3, temp_b
/* state ^ k (X points to K) */
ldi r28, 2
clr r29 /* Y points to r2 aka state0_0 */
ldi temp_a, 16
1:
ld r1, X+
ld r0, Y
eor r1, r0
st Y+, r1
dec temp_a
brne 1b
sbiw r26, 16 /* set X back to key */
mov temp_a, state1_0
mov temp_b, state1_1
mov temp_c, state1_2
mov temp_d, state1_3
eor temp_a, state3_0
eor temp_b, state3_1
eor temp_c, state3_2
eor temp_d, state3_3
mov r1, temp_a
eor r1, temp_b
eor r1, temp_c
eor r1, temp_d
eor temp_a, r1
eor temp_b, r1
eor temp_c, r1
eor temp_d, r1
/* temp is know a little bit mixed c,d,a,b (if abcd is normal order) */
/* a[0] ^= temp */
eor state0_0, temp_c
eor state0_1, temp_d
eor state0_2, temp_a
eor state0_3, temp_b
/* a[2] ^= temp */
eor state2_0, temp_c
eor state2_1, temp_d
eor state2_2, temp_a
eor state2_3, temp_b
clr r1
ret
/******************************************************************************/
#ifndef NOEKEON_NO_ENC
; === noekeon_enc ===
;
; param1: pointer to buffer (r24,r25)
; param2: pointer to k (r22,r23)
;
.global noekeon_enc
noekeon_enc:
rcall push_all_func
/* load state */
movw r26, r22
ldi r28, 2
clr r29 /* Y points at r2 aka state0_0 */
movw r30, r24 /* Z points at state */
push r30
push r31
ldi r22, 16
push r22 /* 16 is also the number of rounds and gets pushed here */
1:
ld r0, Z+
st Y+, r0
dec r22
brne 1b
/* state loaded */
push r1 /* push round constan2 (0x00) */
ldi r20, 0x80
push r20 /* push round constan2 (0x00) */
rjmp 3f
2:
ldi r30, lo8(round_const+15)
ldi r31, hi8(round_const+15)
sub r30, r22
sbci r31, 0
clr r1
push r1
lpm r0, Z
push r0
3:
rcall round /* pops rc2 & rc1 */
pop r22
dec r22
push r22
brne 2b
pop r22
ldi r22, 0xD4
eor state0_3, r22
rcall theta
pop r31
pop r30
clr r29
ldi r28, 2
ldi r22, 16
1:
ld r0, Y+
st Z+, r0
dec r22
brne 1b
rcall pop_all_func
ret
#endif
/******************************************************************************/
/******************************************************************************/
#ifndef NOEKEON_NO_DEC
; === noekeon_dec ===
;
; param1: pointer to buffer/state (r24,r25)
; param2: pointer to k (r22,r23)
;
.global noekeon_dec
noekeon_dec:
rcall push_all_func
/* allocate 16 bytes on the stack */
in r30, _SFR_IO_ADDR(SPL)
in r31, _SFR_IO_ADDR(SPH)
sbiw r30, 16
out _SFR_IO_ADDR(SPH), r31
out _SFR_IO_ADDR(SPL), r30
adiw r30, 1
/* push state pointer */
push r24
push r25
movw r26, r22 /* move key ptr to X */
/* set stackkey to zero */
ldi r22, 16
1: st Z+, r1
dec r22
brne 1b
/* copy key to state */
clr r29
ldi r28, 2
ldi r22, 16
1: ld r0, X+
st Y+, r0
dec r22
brne 1b
movw r26, r30
sbiw r26, 16 /* set X back to begining of stack key */
rcall theta
/* mov state to stackkey */
clr r29
ldi r28, 2
ldi r22, 16
1: ld r0, Y+
st X+, r0
dec r22
brne 1b
sbiw r26, 16 /* set X back to begining of stack key */
/* move data from stateptr to state */
pop r31
pop r30
push r30
push r31
clr r29
ldi r28, 2
ldi r22, 16
push r22
1: ld r0, Z+
st Y+, r0
dec r22
brne 1b
;--- snip 8< ----
ldi r20, 0xD4
push r20 /* push round constant2 (0xD4) */
push r22 /* push round constan1 (0x00) */
rjmp 3f
2:
ldi r30, lo8(round_const-1)
ldi r31, hi8(round_const-1)
clr r1
add r30, r22
adc r31, r1
lpm r0, Z
push r0
push r1
3:
rcall round /* pops rc2 & rc1 */
pop r22
dec r22
push r22
brne 2b
;----
pop r22
rcall theta
ldi r22, 0x80
eor state0_3, r22
write_state_back:
/* write state back */
pop r31 /* pop state pointer */
pop r30
clr r29
ldi r28, 2
ldi r22, 16
1:
ld r0, Y+
st Z+, r0
dec r22
brne 1b
/* remove key from stack */
in r30, _SFR_IO_ADDR(SPL)
in r31, _SFR_IO_ADDR(SPH)
adiw r30, 16
out _SFR_IO_ADDR(SPH), r31
out _SFR_IO_ADDR(SPL), r30
rcall pop_all_func
ret
#endif
/******************************************************************************/
round:
pop r24
pop r25
pop r1
eor state0_3, r1
rcall theta
pop r1
eor state0_3, r1
push r25
push r24
pi_gamma_pi:
ldi r30, pm_lo8(bigendian_rotl32)
ldi r31, pm_hi8(bigendian_rotl32)
rcall pi
/* pi1 done; now gamma */
rcall gamma_1
/* a[0] <-> a[3] */
xchg state0_0, state3_0
xchg state0_1, state3_1
xchg state0_2, state3_2
xchg state0_3, state3_3
/* a[2] ^= a[0] ^ a[1] ^ a[3] */
op32 eor, state2, state0
op32 eor, state2, state1
op32 eor, state2, state3
rcall gamma_1
ldi r30, pm_lo8(bigendian_rotr32)
ldi r31, pm_hi8(bigendian_rotr32)
rcall pi
ret
gamma_1:
/* a[1] ^= ~(a[3]|a[2])*/
mov r1, state3_0
or r1, state2_0
com r1
eor state1_0, r1
mov r1, state3_1
or r1, state2_1
com r1
eor state1_1, r1
mov r1, state3_2
or r1, state2_2
com r1
eor state1_2, r1
mov r1, state3_3
or r1, state2_3
com r1
eor state1_3, r1
/* a[0] ^= a[2]&a[1] */
mov r1, state2_0
and r1, state1_0
eor state0_0, r1
mov r1, state2_1
and r1, state1_1
eor state0_1, r1
mov r1, state2_2
and r1, state1_2
eor state0_2, r1
mov r1, state2_3
and r1, state1_3
eor state0_3, r1
ret
pi:
/* a[1] <<<= 1*/
mov r22, state1_0
mov r23, state1_1
mov r24, state1_2
mov r25, state1_3
ldi r20, 1
icall
mov state1_0, r22
mov state1_1, r23
mov state1_2, r24
mov state1_3, r25
/* a[2] <<<= 5*/
mov r22, state2_0
mov r23, state2_1
mov r24, state2_2
mov r25, state2_3
ldi r20, 5
icall
mov state2_0, r22
mov state2_1, r23
mov state2_2, r24
mov state2_3, r25
/* a[3] <<<= 2*/
mov r22, state3_0
mov r23, state3_1
mov r24, state3_2
mov r25, state3_3
ldi r20, 2
icall
mov state3_0, r22
mov state3_1, r23
mov state3_2, r24
mov state3_3, r25
ret
/******************************************************************************/
/*
void noekeon_init(void* key, noekeon_ctx_t* ctx){
uint8_t nullv[16];
memset(nullv, 0, 16);
memcpy(ctx, key, 16);
noekeon_enc(ctx, nullv);
}
*/
#ifndef NOEKEON_NO_INIT
.global noekeon_init
noekeon_init:
; === noekeon_init ===
;
; param1: pointer to key (r24,r25)
; param2: pointer to context (r22,r23)
;
in r30, _SFR_IO_ADDR(SPL)
in r31, _SFR_IO_ADDR(SPH)
sbiw r30, 16
out _SFR_IO_ADDR(SPH), r31
out _SFR_IO_ADDR(SPL), r30
movw r26, r22
adiw r30, 1
movw r22, r30
/* set nullv(stack) to zero */
ldi r20, 16
1: st Z+, r1
dec r20
brne 1b
/* copy key data to ctx */
movw r30, r24
ldi r20, 16
1: ld r1, Z+
st X+, r1
dec r20
brne 1b
clr r1
sbiw r26, 16
movw r24, r26
rcall noekeon_enc
in r30, _SFR_IO_ADDR(SPL)
in r31, _SFR_IO_ADDR(SPH)
adiw r30, 16
out _SFR_IO_ADDR(SPH), r31
out _SFR_IO_ADDR(SPL), r30
ret
#endif

111
random/persistentCounter.c

@ -0,0 +1,111 @@
/**
* \file persistentCounter.c
* \author Daniel Otte
* \brief a persistent 24-bit counter in EEPROM for ATmega µC
*
*/
#include <stdint.h>
#include <avr/interrupt.h> /* cli() & sei() */
#include <avr/eeprom.h>
#include "../config.h"
#ifdef ERROR_HANDLING
#include "error-handling.h"
#define PERSISTENT_COUNTER_OVERFLOW (void*)0, 2,4,1
#define PERSISTENT_COUNTER_WRITER_ERROR (void*)0, 2,4,2
#endif
#define RING_SIZE 168
uint8_t ring_idx = 0xff;
uint16_t EEMEM B08_23;
uint8_t EEMEM B0_7[RING_SIZE];
#ifdef INIT_EEPROM
void init_buffer(void){
uint8_t i;
eeprom_busy_wait();
eeprom_write_word(&B08_23, 0x0000);
for(i=0; i<RING_SIZE; ++i){
eeprom_busy_wait();
eeprom_write_byte(&(B0_7[i]), 0x00);
}
}
#endif
void percnt_init(void){
uint8_t i;
uint8_t maxidx=0;
uint8_t t,max=eeprom_read_byte(&(B0_7[0]));
#ifdef INIT_EEPROM
if (eeprom_read_word(&B08_23)==0xFFFF){ /* test if the 2 MSB == 0xFFFF*/
if (eeprom_read_word((uint16_t*)&(B0_7[0]))==0xFFFF) /* test the first to bytes of ringbuffer*/
init_buffer();
}
#endif
for(i=0; i<RING_SIZE; ++i){ /* this might be speed up, but such optimisation could lead to timing attacks */
eeprom_busy_wait();
t=eeprom_read_byte(&(B0_7[i]));
if(t==max+1){
max=t;
maxidx=i;
}
}
ring_idx = (maxidx==RING_SIZE)?0:maxidx;
}
uint32_t percnt_get(void){
uint32_t ret=0;
if(ring_idx==0xff)
percnt_init();
cli();
eeprom_busy_wait();
ret=eeprom_read_word(&B08_23)<<8;
eeprom_busy_wait();
ret |= eeprom_read_byte(&(B0_7[ring_idx]));
sei();
return ret;
}
void percnt_inc(void){
/* we must make this resistant agaist power off while this is running ... */
uint32_t u;
if(ring_idx==0xff)
percnt_init();
u = percnt_get();
cli();
/* it's important to write msb first! */
if((u&0x000000ff) == 0xff){
if((u&0x0000ffff) == 0xffff){
if((u&0x00ffffff) == 0xffffff){
/* we can turn the lights off now. it's time to die */
#ifdef ERROR_HANDLING
error(PERSISTENT_COUNTER_OVERFLOW);
#endif
}
eeprom_busy_wait();
eeprom_write_byte(&(((uint8_t*)&B08_23)[1]),((u+1)>>16)&0xff);
}
eeprom_busy_wait();
eeprom_write_byte(&(((uint8_t*)&B08_23)[0]),((u+1)>>8)&0xff);
}
/* set least significant byte (in ringbuffer) */
ring_idx = (ring_idx+1)%RING_SIZE;
eeprom_busy_wait();
eeprom_write_byte(&(B0_7[ring_idx]),(u+1)&0xff);
eeprom_busy_wait();
if(u+1 != percnt_get()){
#ifdef ERROR_HANDLING
error(PERSISTENT_COUNTER_WRITER_ERROR);
#endif
}
sei();
}

23
random/persistentCounter.h

@ -0,0 +1,23 @@
/**
* \file persistentCounter.h
* \author Daniel Otte
* \brief a persistent 24-bit vounter in EEPROM for ATmega µC
*
*
*/
#ifndef PERSISTENTCOUNTER_H_
#define PERSISTENTCOUNTER_H_
#include <stdint.h>
#define PERSISTENT_COUNTER_BITS 24
void percnt_init(void);
uint32_t percnt_get(void);
void percnt_inc(void);
#endif /*PERSISTENTCOUNTER_H_*/

49
random/prng.c

@ -0,0 +1,49 @@
/**
* \author Daniel Otte
* \date 2008-08-24
* \license GPLv3 or later
* \brief random number generator based on noekeon running in CFB-mode
*
*/
#include "noekeon.h"
#include "memxor.h"
#include <stdint.h>
#include <string.h>
uint8_t random_state[16];
uint8_t random_key[16];
uint8_t random8(void){
static uint8_t sr[16];
static uint8_t i=0;
if(i==0){
noekeon_enc(random_state, random_key);
memcpy(sr, random_state, 16);
i=15;
return sr[15];
}
--i;
return sr[i];
}
void random_block(void* dest){
noekeon_enc(random_state, random_key);
memcpy(dest, random_state, 16);
}
void srandom32(uint32_t seed){
memcpy(random_key, &seed, 4);
}
void random_seed(const void* buffer){
memcpy(random_key, buffer, 16);
}
void random_add(const void* buffer){
memxor(random_key, buffer, 16);
}

22
random/prng.h

@ -0,0 +1,22 @@
/**
* \author Daniel Otte
* \date 2008-08-24
* \license GPLv3 or later
* \brief random number generator based on noekeon running in CFB-mode
*
*/
#ifndef PRNG_H_
#define PRNG_H_
#include <stdint.h>
uint8_t random8(void);
void random_block(void* dest);
void srandom32(uint32_t seed);
void random_seed(const void* buffer);
void random_add(const void* buffer);
#endif /* PRNG_H_*/

21
rules.mk

@ -0,0 +1,21 @@
OBJECTS += $(patsubst %.c,%.o,${SRC})
OBJECTS += $(patsubst %.S,%.o,${ASRC})
%.a: $(OBJECTS)
$(RM) $@
$(AR) qcv $@ $^
# $(STRIP) --strip-unneeded $@
%.o: %.S
$(CC) -o $@ $(CPPFLAGS) $(ASFLAGS) -c $<
clean-common:
$(RM) $(TARGET) *.[odasE] *.d.new *~
clean: clean-common
all:
make -C $(TOPDIR) all
include $(TOPDIR)/depend.mk

1697
scripts/Menuconfig

File diff suppressed because it is too large

4
scripts/lxdialog/BIG.FAT.WARNING

@ -0,0 +1,4 @@
This is NOT the official version of dialog. This version has been
significantly modified from the original. It is for use by the Linux
kernel configuration script. Please do not bother Savio Lam with
questions about this program.

46
scripts/lxdialog/Makefile

@ -0,0 +1,46 @@
HOSTCFLAGS += -DLOCALE
LIBS = -lncurses
ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h))
HOSTCFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"
else
ifeq (/usr/include/ncurses/curses.h, $(wildcard /usr/include/ncurses/curses.h))
HOSTCFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"
else
ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h))
HOSTCFLAGS += -DCURSES_LOC="<ncurses.h>"
else
HOSTCFLAGS += -DCURSES_LOC="<curses.h>"
endif
endif
endif
OBJS = checklist.o menubox.o textbox.o yesno.o inputbox.o \
util.o lxdialog.o msgbox.o
%.o: %.c
$(HOSTCC) $(HOSTCFLAGS) -c -o $@ $<
all: ncurses lxdialog
lxdialog: $(OBJS)
$(HOSTCC) -o lxdialog $(OBJS) $(LIBS)
ncurses:
@echo "main() {}" > lxtemp.c
@if $(HOSTCC) -lncurses lxtemp.c ; then \
rm -f lxtemp.c a.out; \
else \
rm -f lxtemp.c; \
echo -e "\007" ;\
echo ">> Unable to find the Ncurses libraries." ;\
echo ">>" ;\
echo ">> You must have Ncurses installed in order" ;\
echo ">> to use 'make menuconfig'" ;\
echo ;\
exit 1 ;\
fi
clean:
rm -f core *.o *~ lxdialog

369
scripts/lxdialog/checklist.c

@ -0,0 +1,369 @@
/*
* checklist.c -- implements the checklist box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
* Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
static int list_width, check_x, item_x, checkflag;
/*
* Print list item
*/
static void
print_item (WINDOW * win, const char *item, int status,
int choice, int selected)
{
int i;
/* Clear 'residue' of last item */
wattrset (win, menubox_attr);
wmove (win, choice, 0);
for (i = 0; i < list_width; i++)
waddch (win, ' ');
wmove (win, choice, check_x);
wattrset (win, selected ? check_selected_attr : check_attr);
if (checkflag == FLAG_CHECK)
wprintw (win, "[%c]", status ? 'X' : ' ');
else
wprintw (win, "(%c)", status ? 'X' : ' ');
wattrset (win, selected ? tag_selected_attr : tag_attr);
mvwaddch(win, choice, item_x, item[0]);
wattrset (win, selected ? item_selected_attr : item_attr);
waddstr (win, (char *)item+1);
if (selected) {
wmove (win, choice, check_x+1);
wrefresh (win);
}
}
/*
* Print the scroll indicators.
*/
static void
print_arrows (WINDOW * win, int choice, int item_no, int scroll,
int y, int x, int height)
{
wmove(win, y, x);
if (scroll > 0) {
wattrset (win, uarrow_attr);
waddch (win, ACS_UARROW);
waddstr (win, "(-)");
}
else {
wattrset (win, menubox_attr);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
}
y = y + height + 1;
wmove(win, y, x);
if ((height < item_no) && (scroll + choice < item_no - 1)) {
wattrset (win, darrow_attr);
waddch (win, ACS_DARROW);
waddstr (win, "(+)");
}
else {
wattrset (win, menubox_border_attr);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
}
}
/*
* Display the termination buttons
*/
static void
print_buttons( WINDOW *dialog, int height, int width, int selected)
{
int x = width / 2 - 11;
int y = height - 2;
print_button (dialog, "Select", y, x, selected == 0);
print_button (dialog, " Help ", y, x + 14, selected == 1);
wmove(dialog, y, x+1 + 14*selected);
wrefresh (dialog);
}
/*
* Display a dialog box with a list of options that can be turned on or off
* The `flag' parameter is used to select between radiolist and checklist.
*/
int
dialog_checklist (const char *title, const char *prompt, int height, int width,
int list_height, int item_no, const char * const * items, int flag)
{
int i, x, y, box_x, box_y;
int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status;
WINDOW *dialog, *list;
checkflag = flag;
/* Allocate space for storing item on/off status */
if ((status = malloc (sizeof (int) * item_no)) == NULL) {
endwin ();
fprintf (stderr,
"\nCan't allocate memory in dialog_checklist().\n");
exit (-1);
}
/* Initializes status */
for (i = 0; i < item_no; i++) {
status[i] = !strcasecmp (items[i * 3 + 2], "on");
if (!choice && status[i])
choice = i;
}
max_choice = MIN (list_height, item_no);
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
draw_shadow (stdscr, y, x, height, width);
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
wattrset (dialog, border_attr);
mvwaddch (dialog, height-3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
waddch (dialog, ACS_RTEE);
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
wattrset (dialog, dialog_attr);
print_autowrap (dialog, prompt, width - 2, 1, 3);
list_width = width - 6;
box_y = height - list_height - 5;
box_x = (width - list_width) / 2 - 1;
/* create new window for the list */
list = subwin (dialog, list_height, list_width, y+box_y+1, x+box_x+1);
keypad (list, TRUE);
/* draw a box around the list items */
draw_box (dialog, box_y, box_x, list_height + 2, list_width + 2,
menubox_border_attr, menubox_attr);
/* Find length of longest item in order to center checklist */
check_x = 0;
for (i = 0; i < item_no; i++)
check_x = MAX (check_x, + strlen (items[i * 3 + 1]) + 4);
check_x = (list_width - check_x) / 2;
item_x = check_x + 4;
if (choice >= list_height) {
scroll = choice - list_height + 1;
choice -= scroll;
}
/* Print the list */
for (i = 0; i < max_choice; i++) {
print_item (list, items[(scroll+i) * 3 + 1],
status[i+scroll], i, i == choice);
}
print_arrows(dialog, choice, item_no, scroll,
box_y, box_x + check_x + 5, list_height);
print_buttons(dialog, height, width, 0);
wnoutrefresh (list);
wnoutrefresh (dialog);
doupdate ();
while (key != ESC) {
key = wgetch (dialog);
for (i = 0; i < max_choice; i++)
if (toupper(key) == toupper(items[(scroll+i)*3+1][0]))
break;
if ( i < max_choice || key == KEY_UP || key == KEY_DOWN ||
key == '+' || key == '-' ) {
if (key == KEY_UP || key == '-') {
if (!choice) {
if (!scroll)
continue;
/* Scroll list down */
if (list_height > 1) {
/* De-highlight current first item */
print_item (list, items[scroll * 3 + 1],
status[scroll], 0, FALSE);
scrollok (list, TRUE);
wscrl (list, -1);
scrollok (list, FALSE);
}
scroll--;
print_item (list, items[scroll * 3 + 1],
status[scroll], 0, TRUE);
wnoutrefresh (list);
print_arrows(dialog, choice, item_no, scroll,
box_y, box_x + check_x + 5, list_height);
wrefresh (dialog);
continue; /* wait for another key press */
} else
i = choice - 1;
} else if (key == KEY_DOWN || key == '+') {
if (choice == max_choice - 1) {
if (scroll + choice >= item_no - 1)
continue;
/* Scroll list up */
if (list_height > 1) {
/* De-highlight current last item before scrolling up */
print_item (list, items[(scroll + max_choice - 1) * 3 + 1],
status[scroll + max_choice - 1],
max_choice - 1, FALSE);
scrollok (list, TRUE);
scroll (list);
scrollok (list, FALSE);
}
scroll++;
print_item (list, items[(scroll + max_choice - 1) * 3 + 1],
status[scroll + max_choice - 1],
max_choice - 1, TRUE);
wnoutrefresh (list);
print_arrows(dialog, choice, item_no, scroll,
box_y, box_x + check_x + 5, list_height);
wrefresh (dialog);
continue; /* wait for another key press */
} else
i = choice + 1;
}
if (i != choice) {
/* De-highlight current item */
print_item (list, items[(scroll + choice) * 3 + 1],
status[scroll + choice], choice, FALSE);
/* Highlight new item */
choice = i;
print_item (list, items[(scroll + choice) * 3 + 1],
status[scroll + choice], choice, TRUE);
wnoutrefresh (list);
wrefresh (dialog);
}
continue; /* wait for another key press */
}
switch (key) {
case 'H':
case 'h':
case '?':
delwin (dialog);
free (status);
return 1;
case TAB:
case KEY_LEFT:
case KEY_RIGHT:
button = ((key == KEY_LEFT ? --button : ++button) < 0)
? 1 : (button > 1 ? 0 : button);
print_buttons(dialog, height, width, button);
wrefresh (dialog);
break;
case 'S':
case 's':
case ' ':
case '\n':
if (!button) {
if (flag == FLAG_CHECK) {
status[scroll + choice] = !status[scroll + choice];
wmove (list, choice, check_x);
wattrset (list, check_selected_attr);
wprintw (list, "[%c]", status[scroll + choice] ? 'X' : ' ');
} else {
if (!status[scroll + choice]) {
for (i = 0; i < item_no; i++)
status[i] = 0;
status[scroll + choice] = 1;
for (i = 0; i < max_choice; i++)
print_item (list, items[(scroll + i) * 3 + 1],
status[scroll + i], i, i == choice);
}
}
wnoutrefresh (list);
wrefresh (dialog);
for (i = 0; i < item_no; i++) {
if (status[i]) {
if (flag == FLAG_CHECK) {
fprintf (stderr, "\"%s\" ", items[i * 3]);
} else {
fprintf (stderr, "%s", items[i * 3]);
}
}
}
}
delwin (dialog);
free (status);
return button;
case 'X':
case 'x':
key = ESC;
case ESC:
break;
}
/* Now, update everything... */
doupdate ();
}
delwin (dialog);
free (status);
return -1; /* ESC pressed */
}

161
scripts/lxdialog/colors.h

@ -0,0 +1,161 @@
/*
* colors.h -- color attribute definitions
*
* AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Default color definitions
*
* *_FG = foreground
* *_BG = background
* *_HL = highlight?
*/
#define SCREEN_FG COLOR_CYAN
#define SCREEN_BG COLOR_BLUE
#define SCREEN_HL TRUE
#define SHADOW_FG COLOR_BLACK
#define SHADOW_BG COLOR_BLACK
#define SHADOW_HL TRUE
#define DIALOG_FG COLOR_BLACK
#define DIALOG_BG COLOR_WHITE
#define DIALOG_HL FALSE
#define TITLE_FG COLOR_YELLOW
#define TITLE_BG COLOR_WHITE
#define TITLE_HL TRUE
#define BORDER_FG COLOR_WHITE
#define BORDER_BG COLOR_WHITE
#define BORDER_HL TRUE
#define BUTTON_ACTIVE_FG COLOR_WHITE
#define BUTTON_ACTIVE_BG COLOR_BLUE
#define BUTTON_ACTIVE_HL TRUE
#define BUTTON_INACTIVE_FG COLOR_BLACK
#define BUTTON_INACTIVE_BG COLOR_WHITE
#define BUTTON_INACTIVE_HL FALSE
#define BUTTON_KEY_ACTIVE_FG COLOR_WHITE
#define BUTTON_KEY_ACTIVE_BG COLOR_BLUE
#define BUTTON_KEY_ACTIVE_HL TRUE
#define BUTTON_KEY_INACTIVE_FG COLOR_RED
#define BUTTON_KEY_INACTIVE_BG COLOR_WHITE
#define BUTTON_KEY_INACTIVE_HL FALSE
#define BUTTON_LABEL_ACTIVE_FG COLOR_YELLOW
#define BUTTON_LABEL_ACTIVE_BG COLOR_BLUE
#define BUTTON_LABEL_ACTIVE_HL TRUE
#define BUTTON_LABEL_INACTIVE_FG COLOR_BLACK
#define BUTTON_LABEL_INACTIVE_BG COLOR_WHITE
#define BUTTON_LABEL_INACTIVE_HL TRUE
#define INPUTBOX_FG COLOR_BLACK
#define INPUTBOX_BG COLOR_WHITE
#define INPUTBOX_HL FALSE
#define INPUTBOX_BORDER_FG COLOR_BLACK
#define INPUTBOX_BORDER_BG COLOR_WHITE
#define INPUTBOX_BORDER_HL FALSE
#define SEARCHBOX_FG COLOR_BLACK
#define SEARCHBOX_BG COLOR_WHITE
#define SEARCHBOX_HL FALSE
#define SEARCHBOX_TITLE_FG COLOR_YELLOW
#define SEARCHBOX_TITLE_BG COLOR_WHITE
#define SEARCHBOX_TITLE_HL TRUE
#define SEARCHBOX_BORDER_FG COLOR_WHITE
#define SEARCHBOX_BORDER_BG COLOR_WHITE
#define SEARCHBOX_BORDER_HL TRUE
#define POSITION_INDICATOR_FG COLOR_YELLOW
#define POSITION_INDICATOR_BG COLOR_WHITE
#define POSITION_INDICATOR_HL TRUE
#define MENUBOX_FG COLOR_BLACK
#define MENUBOX_BG COLOR_WHITE
#define MENUBOX_HL FALSE
#define MENUBOX_BORDER_FG COLOR_WHITE
#define MENUBOX_BORDER_BG COLOR_WHITE
#define MENUBOX_BORDER_HL TRUE
#define ITEM_FG COLOR_BLACK
#define ITEM_BG COLOR_WHITE
#define ITEM_HL FALSE
#define ITEM_SELECTED_FG COLOR_WHITE
#define ITEM_SELECTED_BG COLOR_BLUE
#define ITEM_SELECTED_HL TRUE
#define TAG_FG COLOR_YELLOW
#define TAG_BG COLOR_WHITE
#define TAG_HL TRUE
#define TAG_SELECTED_FG COLOR_YELLOW
#define TAG_SELECTED_BG COLOR_BLUE
#define TAG_SELECTED_HL TRUE
#define TAG_KEY_FG COLOR_YELLOW
#define TAG_KEY_BG COLOR_WHITE
#define TAG_KEY_HL TRUE
#define TAG_KEY_SELECTED_FG COLOR_YELLOW
#define TAG_KEY_SELECTED_BG COLOR_BLUE
#define TAG_KEY_SELECTED_HL TRUE
#define CHECK_FG COLOR_BLACK
#define CHECK_BG COLOR_WHITE
#define CHECK_HL FALSE
#define CHECK_SELECTED_FG COLOR_WHITE
#define CHECK_SELECTED_BG COLOR_BLUE
#define CHECK_SELECTED_HL TRUE
#define UARROW_FG COLOR_GREEN
#define UARROW_BG COLOR_WHITE
#define UARROW_HL TRUE
#define DARROW_FG COLOR_GREEN
#define DARROW_BG COLOR_WHITE
#define DARROW_HL TRUE
/* End of default color definitions */
#define C_ATTR(x,y) ((x ? A_BOLD : 0) | COLOR_PAIR((y)))
#define COLOR_NAME_LEN 10
#define COLOR_COUNT 8
/*
* Global variables
*/
typedef struct {
char name[COLOR_NAME_LEN];
int value;
} color_names_st;
extern color_names_st color_names[];
extern int color_table[][3];

184
scripts/lxdialog/dialog.h

@ -0,0 +1,184 @@
/*
* dialog.h -- common declarations for all dialog modules
*
* AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include CURSES_LOC
/*
* Colors in ncurses 1.9.9e do not work properly since foreground and
* background colors are OR'd rather than separately masked. This version
* of dialog was hacked to work with ncurses 1.9.9e, making it incompatible
* with standard curses. The simplest fix (to make this work with standard
* curses) uses the wbkgdset() function, not used in the original hack.
* Turn it off if we're building with 1.9.9e, since it just confuses things.
*/
#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
#define OLD_NCURSES 1
#undef wbkgdset
#define wbkgdset(w,p) /*nothing*/
#else
#define OLD_NCURSES 0
#endif
#define TR(params) _tracef params
#define ESC 27
#define TAB 9
#define MAX_LEN 2048
#define BUF_SIZE (10*1024)
#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
#ifndef ACS_ULCORNER
#define ACS_ULCORNER '+'
#endif
#ifndef ACS_LLCORNER
#define ACS_LLCORNER '+'
#endif
#ifndef ACS_URCORNER
#define ACS_URCORNER '+'
#endif
#ifndef ACS_LRCORNER
#define ACS_LRCORNER '+'
#endif
#ifndef ACS_HLINE
#define ACS_HLINE '-'
#endif
#ifndef ACS_VLINE
#define ACS_VLINE '|'
#endif
#ifndef ACS_LTEE
#define ACS_LTEE '+'
#endif
#ifndef ACS_RTEE
#define ACS_RTEE '+'
#endif
#ifndef ACS_UARROW
#define ACS_UARROW '^'
#endif
#ifndef ACS_DARROW
#define ACS_DARROW 'v'
#endif
/*
* Attribute names
*/
#define screen_attr attributes[0]
#define shadow_attr attributes[1]
#define dialog_attr attributes[2]
#define title_attr attributes[3]
#define border_attr attributes[4]
#define button_active_attr attributes[5]
#define button_inactive_attr attributes[6]
#define button_key_active_attr attributes[7]
#define button_key_inactive_attr attributes[8]
#define button_label_active_attr attributes[9]
#define button_label_inactive_attr attributes[10]
#define inputbox_attr attributes[11]
#define inputbox_border_attr attributes[12]
#define searchbox_attr attributes[13]
#define searchbox_title_attr attributes[14]
#define searchbox_border_attr attributes[15]
#define position_indicator_attr attributes[16]
#define menubox_attr attributes[17]
#define menubox_border_attr attributes[18]
#define item_attr attributes[19]
#define item_selected_attr attributes[20]
#define tag_attr attributes[21]
#define tag_selected_attr attributes[22]
#define tag_key_attr attributes[23]
#define tag_key_selected_attr attributes[24]
#define check_attr attributes[25]
#define check_selected_attr attributes[26]
#define uarrow_attr attributes[27]
#define darrow_attr attributes[28]
/* number of attributes */
#define ATTRIBUTE_COUNT 29
/*
* Global variables
*/
extern bool use_colors;
extern bool use_shadow;
extern chtype attributes[];
extern const char *backtitle;
/*
* Function prototypes
*/
extern void create_rc (const char *filename);
extern int parse_rc (void);
void init_dialog (void);
void end_dialog (void);
void attr_clear (WINDOW * win, int height, int width, chtype attr);
void dialog_clear (void);
void color_setup (void);
void print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x);
void print_button (WINDOW * win, const char *label, int y, int x, int selected);
void draw_box (WINDOW * win, int y, int x, int height, int width, chtype box,
chtype border);
void draw_shadow (WINDOW * win, int y, int x, int height, int width);
int first_alpha (const char *string, const char *exempt);
int dialog_yesno (const char *title, const char *prompt, int height, int width);
int dialog_msgbox (const char *title, const char *prompt, int height,
int width, int pause);
int dialog_textbox (const char *title, const char *file, int height, int width);
int dialog_menu (const char *title, const char *prompt, int height, int width,
int menu_height, const char *choice, int item_no,
const char * const * items);
int dialog_checklist (const char *title, const char *prompt, int height,
int width, int list_height, int item_no,
const char * const * items, int flag);
extern unsigned char dialog_input_result[];
int dialog_inputbox (const char *title, const char *prompt, int height,
int width, const char *init);
/*
* This is the base for fictitious keys, which activate
* the buttons.
*
* Mouse-generated keys are the following:
* -- the first 32 are used as numbers, in addition to '0'-'9'
* -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
* -- uppercase chars are used to invoke the button (M_EVENT + 'O')
*/
#define M_EVENT (KEY_MAX+1)
/*
* The `flag' parameter in checklist is used to select between
* radiolist and checklist
*/
#define FLAG_CHECK 1
#define FLAG_RADIO 0

240
scripts/lxdialog/inputbox.c

@ -0,0 +1,240 @@
/*
* inputbox.c -- implements the input box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
unsigned char dialog_input_result[MAX_LEN + 1];
/*
* Print the termination buttons
*/
static void
print_buttons(WINDOW *dialog, int height, int width, int selected)
{
int x = width / 2 - 11;
int y = height - 2;
print_button (dialog, " Ok ", y, x, selected==0);
print_button (dialog, " Help ", y, x + 14, selected==1);
wmove(dialog, y, x+1+14*selected);
wrefresh(dialog);
}
/*
* Display a dialog box for inputing a string
*/
int
dialog_inputbox (const char *title, const char *prompt, int height, int width,
const char *init)
{
int i, x, y, box_y, box_x, box_width;
int input_x = 0, scroll = 0, key = 0, button = -1;
unsigned char *instr = dialog_input_result;
WINDOW *dialog;
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
draw_shadow (stdscr, y, x, height, width);
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
wattrset (dialog, border_attr);
mvwaddch (dialog, height-3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
waddch (dialog, ACS_RTEE);
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
wattrset (dialog, dialog_attr);
print_autowrap (dialog, prompt, width - 2, 1, 3);
/* Draw the input field box */
box_width = width - 6;
getyx (dialog, y, x);
box_y = y + 2;
box_x = (width - box_width) / 2;
draw_box (dialog, y + 1, box_x - 1, 3, box_width + 2,
border_attr, dialog_attr);
print_buttons(dialog, height, width, 0);
/* Set up the initial value */
wmove (dialog, box_y, box_x);
wattrset (dialog, inputbox_attr);
if (!init)
instr[0] = '\0';
else
strcpy (instr, init);
input_x = strlen (instr);
if (input_x >= box_width) {
scroll = input_x - box_width + 1;
input_x = box_width - 1;
for (i = 0; i < box_width - 1; i++)
waddch (dialog, instr[scroll + i]);
} else
waddstr (dialog, instr);
wmove (dialog, box_y, box_x + input_x);
wrefresh (dialog);
while (key != ESC) {
key = wgetch (dialog);
if (button == -1) { /* Input box selected */
switch (key) {
case TAB:
case KEY_UP:
case KEY_DOWN:
break;
case KEY_LEFT:
continue;
case KEY_RIGHT:
continue;
case KEY_BACKSPACE:
case 127:
if (input_x || scroll) {
wattrset (dialog, inputbox_attr);
if (!input_x) {
scroll = scroll < box_width - 1 ?
0 : scroll - (box_width - 1);
wmove (dialog, box_y, box_x);
for (i = 0; i < box_width; i++)
waddch (dialog, instr[scroll + input_x + i] ?
instr[scroll + input_x + i] : ' ');
input_x = strlen (instr) - scroll;
} else
input_x--;
instr[scroll + input_x] = '\0';
mvwaddch (dialog, box_y, input_x + box_x, ' ');
wmove (dialog, box_y, input_x + box_x);
wrefresh (dialog);
}
continue;
default:
if (key < 0x100 && isprint (key)) {
if (scroll + input_x < MAX_LEN) {
wattrset (dialog, inputbox_attr);
instr[scroll + input_x] = key;
instr[scroll + input_x + 1] = '\0';
if (input_x == box_width - 1) {
scroll++;
wmove (dialog, box_y, box_x);
for (i = 0; i < box_width - 1; i++)
waddch (dialog, instr[scroll + i]);
} else {
wmove (dialog, box_y, input_x++ + box_x);
waddch (dialog, key);
}
wrefresh (dialog);
} else
flash (); /* Alarm user about overflow */
continue;
}
}
}
switch (key) {
case 'O':
case 'o':
delwin (dialog);
return 0;
case 'H':
case 'h':
delwin (dialog);
return 1;
case KEY_UP:
case KEY_LEFT:
switch (button) {
case -1:
button = 1; /* Indicates "Cancel" button is selected */
print_buttons(dialog, height, width, 1);
break;
case 0:
button = -1; /* Indicates input box is selected */
print_buttons(dialog, height, width, 0);
wmove (dialog, box_y, box_x + input_x);
wrefresh (dialog);
break;
case 1:
button = 0; /* Indicates "OK" button is selected */
print_buttons(dialog, height, width, 0);
break;
}
break;
case TAB:
case KEY_DOWN:
case KEY_RIGHT:
switch (button) {
case -1:
button = 0; /* Indicates "OK" button is selected */
print_buttons(dialog, height, width, 0);
break;
case 0:
button = 1; /* Indicates "Cancel" button is selected */
print_buttons(dialog, height, width, 1);
break;
case 1:
button = -1; /* Indicates input box is selected */
print_buttons(dialog, height, width, 0);
wmove (dialog, box_y, box_x + input_x);
wrefresh (dialog);
break;
}
break;
case ' ':
case '\n':
delwin (dialog);
return (button == -1 ? 0 : button);
case 'X':
case 'x':
key = ESC;
case ESC:
break;
}
}
delwin (dialog);
return -1; /* ESC pressed */
}

226
scripts/lxdialog/lxdialog.c

@ -0,0 +1,226 @@
/*
* dialog - Display simple dialog boxes from shell scripts
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
static void Usage (const char *name);
typedef int (jumperFn) (const char *title, int argc, const char * const * argv);
struct Mode {
char *name;
int argmin, argmax, argmod;
jumperFn *jumper;
};
jumperFn j_menu, j_checklist, j_radiolist, j_yesno, j_textbox, j_inputbox;
jumperFn j_msgbox, j_infobox;
static struct Mode modes[] =
{
{"--menu", 9, 0, 3, j_menu},
{"--checklist", 9, 0, 3, j_checklist},
{"--radiolist", 9, 0, 3, j_radiolist},
{"--yesno", 5,5,1, j_yesno},
{"--textbox", 5,5,1, j_textbox},
{"--inputbox", 5, 6, 1, j_inputbox},
{"--msgbox", 5, 5, 1, j_msgbox},
{"--infobox", 5, 5, 1, j_infobox},
{NULL, 0, 0, 0, NULL}
};
static struct Mode *modePtr;
#ifdef LOCALE
#include <locale.h>
#endif
int
main (int argc, const char * const * argv)
{
int offset = 0, clear_screen = 0, end_common_opts = 0, retval;
const char *title = NULL;
#ifdef LOCALE
(void) setlocale (LC_ALL, "");
#endif
#ifdef TRACE
trace(TRACE_CALLS|TRACE_UPDATE);
#endif
if (argc < 2) {
Usage (argv[0]);
exit (-1);
}
while (offset < argc - 1 && !end_common_opts) { /* Common options */
if (!strcmp (argv[offset + 1], "--title")) {
if (argc - offset < 3 || title != NULL) {
Usage (argv[0]);
exit (-1);
} else {
title = argv[offset + 2];
offset += 2;
}
} else if (!strcmp (argv[offset + 1], "--backtitle")) {
if (backtitle != NULL) {
Usage (argv[0]);
exit (-1);
} else {
backtitle = argv[offset + 2];
offset += 2;
}
} else if (!strcmp (argv[offset + 1], "--clear")) {
if (clear_screen) { /* Hey, "--clear" can't appear twice! */
Usage (argv[0]);
exit (-1);
} else if (argc == 2) { /* we only want to clear the screen */
init_dialog ();
refresh (); /* init_dialog() will clear the screen for us */
end_dialog ();
return 0;
} else {
clear_screen = 1;
offset++;
}
} else /* no more common options */
end_common_opts = 1;
}
if (argc - 1 == offset) { /* no more options */
Usage (argv[0]);
exit (-1);
}
/* use a table to look for the requested mode, to avoid code duplication */
for (modePtr = modes; modePtr->name; modePtr++) /* look for the mode */
if (!strcmp (argv[offset + 1], modePtr->name))
break;
if (!modePtr->name)
Usage (argv[0]);
if (argc - offset < modePtr->argmin)
Usage (argv[0]);
if (modePtr->argmax && argc - offset > modePtr->argmax)
Usage (argv[0]);
init_dialog ();
retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset);
if (clear_screen) { /* clear screen before exit */
attr_clear (stdscr, LINES, COLS, screen_attr);
refresh ();
}
end_dialog();
exit (retval);
}
/*
* Print program usage
*/
static void
Usage (const char *name)
{
fprintf (stderr, "\
\ndialog, by Savio Lam (lam836@cs.cuhk.hk).\
\n patched by Stuart Herbert (S.Herbert@shef.ac.uk)\
\n modified/gutted for use as a Linux kernel config tool by \
\n William Roadcap (roadcapw@cfw.com)\
\n\
\n* Display dialog boxes from shell scripts *\
\n\
\nUsage: %s --clear\
\n %s [--title <title>] [--backtitle <backtitle>] --clear <Box options>\
\n\
\nBox options:\
\n\
\n --menu <text> <height> <width> <menu height> <tag1> <item1>...\
\n --checklist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
\n --radiolist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
\n --textbox <file> <height> <width>\
\n --inputbox <text> <height> <width> [<init>]\
\n --yesno <text> <height> <width>\
\n", name, name);
exit (-1);
}
/*
* These are the program jumpers
*/
int
j_menu (const char *t, int ac, const char * const * av)
{
return dialog_menu (t, av[2], atoi (av[3]), atoi (av[4]),
atoi (av[5]), av[6], (ac - 6) / 2, av + 7);
}
int
j_checklist (const char *t, int ac, const char * const * av)
{
return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]),
atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_CHECK);
}
int
j_radiolist (const char *t, int ac, const char * const * av)
{
return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]),
atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_RADIO);
}
int
j_textbox (const char *t, int ac, const char * const * av)
{
return dialog_textbox (t, av[2], atoi (av[3]), atoi (av[4]));
}
int
j_yesno (const char *t, int ac, const char * const * av)
{
return dialog_yesno (t, av[2], atoi (av[3]), atoi (av[4]));
}
int
j_inputbox (const char *t, int ac, const char * const * av)
{
int ret = dialog_inputbox (t, av[2], atoi (av[3]), atoi (av[4]),
ac == 6 ? av[5] : (char *) NULL);
if (ret == 0)
fprintf(stderr, dialog_input_result);
return ret;
}
int
j_msgbox (const char *t, int ac, const char * const * av)
{
return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 1);
}
int
j_infobox (const char *t, int ac, const char * const * av)
{
return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 0);
}

443
scripts/lxdialog/menubox.c

@ -0,0 +1,443 @@
/*
* menubox.c -- implements the menu box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Changes by Clifford Wolf (god@clifford.at)
*
* [ 1998-06-13 ]
*
* *) A bugfix for the Page-Down problem
*
* *) Formerly when I used Page Down and Page Up, the cursor would be set
* to the first position in the menu box. Now lxdialog is a bit
* smarter and works more like other menu systems (just have a look at
* it).
*
* *) Formerly if I selected something my scrolling would be broken because
* lxdialog is re-invoked by the Menuconfig shell script, can't
* remember the last scrolling position, and just sets it so that the
* cursor is at the bottom of the box. Now it writes the temporary file
* lxdialog.scrltmp which contains this information. The file is
* deleted by lxdialog if the user leaves a submenu or enters a new
* one, but it would be nice if Menuconfig could make another "rm -f"
* just to be sure. Just try it out - you will recognise a difference!
*
* [ 1998-06-14 ]
*
* *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
* and menus change their size on the fly.
*
* *) If for some reason the last scrolling position is not saved by
* lxdialog, it sets the scrolling so that the selected item is in the
* middle of the menu box, not at the bottom.
*
* 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
* Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
* This fixes a bug in Menuconfig where using ' ' to descend into menus
* would leave mis-synchronized lxdialog.scrltmp files lying around,
* fscanf would read in 'scroll', and eventually that value would get used.
*/
#include "dialog.h"
static int menu_width, item_x;
/*
* Print menu item
*/
static void
print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey)
{
int j;
char menu_item[menu_width+1];
strncpy(menu_item, item, menu_width);
menu_item[menu_width] = 0;
j = first_alpha(menu_item, "YyNnMm");
/* Clear 'residue' of last item */
wattrset (win, menubox_attr);
wmove (win, choice, 0);
#if OLD_NCURSES
{
int i;
for (i = 0; i < menu_width; i++)
waddch (win, ' ');
}
#else
wclrtoeol(win);
#endif
wattrset (win, selected ? item_selected_attr : item_attr);
mvwaddstr (win, choice, item_x, menu_item);
if (hotkey) {
wattrset (win, selected ? tag_key_selected_attr : tag_key_attr);
mvwaddch(win, choice, item_x+j, menu_item[j]);
}
if (selected) {
wmove (win, choice, item_x+1);
wrefresh (win);
}
}
/*
* Print the scroll indicators.
*/
static void
print_arrows (WINDOW * win, int item_no, int scroll,
int y, int x, int height)
{
int cur_y, cur_x;
getyx(win, cur_y, cur_x);
wmove(win, y, x);
if (scroll > 0) {
wattrset (win, uarrow_attr);
waddch (win, ACS_UARROW);
waddstr (win, "(-)");
}
else {
wattrset (win, menubox_attr);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
}
y = y + height + 1;
wmove(win, y, x);
if ((height < item_no) && (scroll + height < item_no)) {
wattrset (win, darrow_attr);
waddch (win, ACS_DARROW);
waddstr (win, "(+)");
}
else {
wattrset (win, menubox_border_attr);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
}
wmove(win, cur_y, cur_x);
}
/*
* Display the termination buttons.
*/
static void
print_buttons (WINDOW *win, int height, int width, int selected)
{
int x = width / 2 - 16;
int y = height - 2;
print_button (win, "Select", y, x, selected == 0);
print_button (win, " Exit ", y, x + 12, selected == 1);
print_button (win, " Help ", y, x + 24, selected == 2);
wmove(win, y, x+1+12*selected);
wrefresh (win);
}
/*
* Display a menu for choosing among a number of options
*/
int
dialog_menu (const char *title, const char *prompt, int height, int width,
int menu_height, const char *current, int item_no,
const char * const * items)
{
int i, j, x, y, box_x, box_y;
int key = 0, button = 0, scroll = 0, choice = 0, first_item = 0, max_choice;
WINDOW *dialog, *menu;
FILE *f;
max_choice = MIN (menu_height, item_no);
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
draw_shadow (stdscr, y, x, height, width);
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
wattrset (dialog, border_attr);
mvwaddch (dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
wbkgdset (dialog, dialog_attr & A_COLOR);
waddch (dialog, ACS_RTEE);
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
wattrset (dialog, dialog_attr);
print_autowrap (dialog, prompt, width - 2, 1, 3);
menu_width = width - 6;
box_y = height - menu_height - 5;
box_x = (width - menu_width) / 2 - 1;
/* create new window for the menu */
menu = subwin (dialog, menu_height, menu_width,
y + box_y + 1, x + box_x + 1);
keypad (menu, TRUE);
/* draw a box around the menu items */
draw_box (dialog, box_y, box_x, menu_height + 2, menu_width + 2,
menubox_border_attr, menubox_attr);
/*
* Find length of longest item in order to center menu.
* Set 'choice' to default item.
*/
item_x = 0;
for (i = 0; i < item_no; i++) {
item_x = MAX (item_x, MIN(menu_width, strlen (items[i * 2 + 1]) + 2));
if (strcmp(current, items[i*2]) == 0) choice = i;
}
item_x = (menu_width - item_x) / 2;
/* get the scroll info from the temp file */
if ( (f=fopen("lxdialog.scrltmp","r")) != NULL ) {
if ( (fscanf(f,"%d\n",&scroll) == 1) && (scroll <= choice) &&
(scroll+max_choice > choice) && (scroll >= 0) &&
(scroll+max_choice <= item_no) ) {
first_item = scroll;
choice = choice - scroll;
fclose(f);
} else {
scroll=0;
remove("lxdialog.scrltmp");
fclose(f);
f=NULL;
}
}
if ( (choice >= max_choice) || (f==NULL && choice >= max_choice/2) ) {
if (choice >= item_no-max_choice/2)
scroll = first_item = item_no-max_choice;
else
scroll = first_item = choice - max_choice/2;
choice = choice - scroll;
}
/* Print the menu */
for (i=0; i < max_choice; i++) {
print_item (menu, items[(first_item + i) * 2 + 1], i, i == choice,
(items[(first_item + i)*2][0] != ':'));
}
wnoutrefresh (menu);
print_arrows(dialog, item_no, scroll,
box_y, box_x+item_x+1, menu_height);
print_buttons (dialog, height, width, 0);
wmove (menu, choice, item_x+1);
wrefresh (menu);
while (key != ESC) {
key = wgetch(menu);
if (key < 256 && isalpha(key)) key = tolower(key);
if (strchr("ynm", key))
i = max_choice;
else {
for (i = choice+1; i < max_choice; i++) {
j = first_alpha(items[(scroll+i)*2+1], "YyNnMm");
if (key == tolower(items[(scroll+i)*2+1][j]))
break;
}
if (i == max_choice)
for (i = 0; i < max_choice; i++) {
j = first_alpha(items[(scroll+i)*2+1], "YyNnMm");
if (key == tolower(items[(scroll+i)*2+1][j]))
break;
}
}
if (i < max_choice ||
key == KEY_UP || key == KEY_DOWN ||
key == '-' || key == '+' ||
key == KEY_PPAGE || key == KEY_NPAGE) {
print_item (menu, items[(scroll+choice)*2+1], choice, FALSE,
(items[(scroll+choice)*2][0] != ':'));
if (key == KEY_UP || key == '-') {
if (choice < 2 && scroll) {
/* Scroll menu down */
scrollok (menu, TRUE);
wscrl (menu, -1);
scrollok (menu, FALSE);
scroll--;
print_item (menu, items[scroll * 2 + 1], 0, FALSE,
(items[scroll*2][0] != ':'));
} else
choice = MAX(choice - 1, 0);
} else if (key == KEY_DOWN || key == '+') {
print_item (menu, items[(scroll+choice)*2+1], choice, FALSE,
(items[(scroll+choice)*2][0] != ':'));
if ((choice > max_choice-3) &&
(scroll + max_choice < item_no)
) {
/* Scroll menu up */
scrollok (menu, TRUE);
scroll (menu);
scrollok (menu, FALSE);
scroll++;
print_item (menu, items[(scroll+max_choice-1)*2+1],
max_choice-1, FALSE,
(items[(scroll+max_choice-1)*2][0] != ':'));
} else
choice = MIN(choice+1, max_choice-1);
} else if (key == KEY_PPAGE) {
scrollok (menu, TRUE);
for (i=0; (i < max_choice); i++) {
if (scroll > 0) {
wscrl (menu, -1);
scroll--;
print_item (menu, items[scroll * 2 + 1], 0, FALSE,
(items[scroll*2][0] != ':'));
} else {
if (choice > 0)
choice--;
}
}
scrollok (menu, FALSE);
} else if (key == KEY_NPAGE) {
for (i=0; (i < max_choice); i++) {
if (scroll+max_choice < item_no) {
scrollok (menu, TRUE);
scroll(menu);
scrollok (menu, FALSE);
scroll++;
print_item (menu, items[(scroll+max_choice-1)*2+1],
max_choice-1, FALSE,
(items[(scroll+max_choice-1)*2][0] != ':'));
} else {
if (choice+1 < max_choice)
choice++;
}
}
} else
choice = i;
print_item (menu, items[(scroll+choice)*2+1], choice, TRUE,
(items[(scroll+choice)*2][0] != ':'));
print_arrows(dialog, item_no, scroll,
box_y, box_x+item_x+1, menu_height);
wnoutrefresh (dialog);
wrefresh (menu);
continue; /* wait for another key press */
}
switch (key) {
case KEY_LEFT:
case TAB:
case KEY_RIGHT:
button = ((key == KEY_LEFT ? --button : ++button) < 0)
? 2 : (button > 2 ? 0 : button);
print_buttons(dialog, height, width, button);
wrefresh (menu);
break;
case ' ':
case 's':
case 'y':
case 'n':
case 'm':
/* save scroll info */
if ( (f=fopen("lxdialog.scrltmp","w")) != NULL ) {
fprintf(f,"%d\n",scroll);
fclose(f);
}
delwin (dialog);
fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
switch (key) {
case 's': return 3;
case 'y': return 3;
case 'n': return 4;
case 'm': return 5;
case ' ': return 6;
}
return 0;
case 'h':
case '?':
button = 2;
case '\n':
delwin (dialog);
if (button == 2)
fprintf(stderr, "%s \"%s\"\n",
items[(scroll + choice) * 2],
items[(scroll + choice) * 2 + 1] +
first_alpha(items[(scroll + choice) * 2 + 1],""));
else
fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
remove("lxdialog.scrltmp");
return button;
case 'e':
case 'x':
key = ESC;
case ESC:
break;
}
}
delwin (dialog);
remove("lxdialog.scrltmp");
return -1; /* ESC pressed */
}

85
scripts/lxdialog/msgbox.c

@ -0,0 +1,85 @@
/*
* msgbox.c -- implements the message box and info box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
/*
* Display a message box. Program will pause and display an "OK" button
* if the parameter 'pause' is non-zero.
*/
int
dialog_msgbox (const char *title, const char *prompt, int height, int width,
int pause)
{
int i, x, y, key = 0;
WINDOW *dialog;
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
draw_shadow (stdscr, y, x, height, width);
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
wattrset (dialog, dialog_attr);
print_autowrap (dialog, prompt, width - 2, 1, 2);
if (pause) {
wattrset (dialog, border_attr);
mvwaddch (dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
waddch (dialog, ACS_RTEE);
print_button (dialog, " Ok ",
height - 2, width / 2 - 4, TRUE);
wrefresh (dialog);
while (key != ESC && key != '\n' && key != ' ' &&
key != 'O' && key != 'o' && key != 'X' && key != 'x')
key = wgetch (dialog);
} else {
key = '\n';
wrefresh (dialog);
}
delwin (dialog);
return key == ESC ? -1 : 0;
}

556
scripts/lxdialog/textbox.c

@ -0,0 +1,556 @@
/*
* textbox.c -- implements the text box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
static void back_lines (int n);
static void print_page (WINDOW * win, int height, int width);
static void print_line (WINDOW * win, int row, int width);
static char *get_line (void);
static void print_position (WINDOW * win, int height, int width);
static int hscroll = 0, fd, file_size, bytes_read;
static int begin_reached = 1, end_reached = 0, page_length;
static char *buf, *page;
/*
* Display text from a file in a dialog box.
*/
int
dialog_textbox (const char *title, const char *file, int height, int width)
{
int i, x, y, cur_x, cur_y, fpos, key = 0;
int passed_end;
char search_term[MAX_LEN + 1];
WINDOW *dialog, *text;
search_term[0] = '\0'; /* no search term entered yet */
/* Open input file for reading */
if ((fd = open (file, O_RDONLY)) == -1) {
endwin ();
fprintf (stderr,
"\nCan't open input file in dialog_textbox().\n");
exit (-1);
}
/* Get file size. Actually, 'file_size' is the real file size - 1,
since it's only the last byte offset from the beginning */
if ((file_size = lseek (fd, 0, SEEK_END)) == -1) {
endwin ();
fprintf (stderr, "\nError getting file size in dialog_textbox().\n");
exit (-1);
}
/* Restore file pointer to beginning of file after getting file size */
if (lseek (fd, 0, SEEK_SET) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in dialog_textbox().\n");
exit (-1);
}
/* Allocate space for read buffer */
if ((buf = malloc (BUF_SIZE + 1)) == NULL) {
endwin ();
fprintf (stderr, "\nCan't allocate memory in dialog_textbox().\n");
exit (-1);
}
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr, "\nError reading file in dialog_textbox().\n");
exit (-1);
}
buf[bytes_read] = '\0'; /* mark end of valid data */
page = buf; /* page is pointer to start of page to be displayed */
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
draw_shadow (stdscr, y, x, height, width);
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
/* Create window for text region, used for scrolling text */
text = subwin (dialog, height - 4, width - 2, y + 1, x + 1);
wattrset (text, dialog_attr);
wbkgdset (text, dialog_attr & A_COLOR);
keypad (text, TRUE);
/* register the new window, along with its borders */
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
wattrset (dialog, border_attr);
mvwaddch (dialog, height-3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
wbkgdset (dialog, dialog_attr & A_COLOR);
waddch (dialog, ACS_RTEE);
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
print_button (dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
wnoutrefresh (dialog);
getyx (dialog, cur_y, cur_x); /* Save cursor position */
/* Print first page of text */
attr_clear (text, height - 4, width - 2, dialog_attr);
print_page (text, height - 4, width - 2);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh (dialog);
while ((key != ESC) && (key != '\n')) {
key = wgetch (dialog);
switch (key) {
case 'E': /* Exit */
case 'e':
case 'X':
case 'x':
delwin (dialog);
free (buf);
close (fd);
return 0;
case 'g': /* First page */
case KEY_HOME:
if (!begin_reached) {
begin_reached = 1;
/* First page not in buffer? */
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr,
"\nError moving file pointer in dialog_textbox().\n");
exit (-1);
}
if (fpos > bytes_read) { /* Yes, we have to read it in */
if (lseek (fd, 0, SEEK_SET) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in "
"dialog_textbox().\n");
exit (-1);
}
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr,
"\nError reading file in dialog_textbox().\n");
exit (-1);
}
buf[bytes_read] = '\0';
}
page = buf;
print_page (text, height - 4, width - 2);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh (dialog);
}
break;
case 'G': /* Last page */
case KEY_END:
end_reached = 1;
/* Last page not in buffer? */
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr,
"\nError moving file pointer in dialog_textbox().\n");
exit (-1);
}
if (fpos < file_size) { /* Yes, we have to read it in */
if (lseek (fd, -BUF_SIZE, SEEK_END) == -1) {
endwin ();
fprintf (stderr,
"\nError moving file pointer in dialog_textbox().\n");
exit (-1);
}
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr,
"\nError reading file in dialog_textbox().\n");
exit (-1);
}
buf[bytes_read] = '\0';
}
page = buf + bytes_read;
back_lines (height - 4);
print_page (text, height - 4, width - 2);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh (dialog);
break;
case 'K': /* Previous line */
case 'k':
case KEY_UP:
if (!begin_reached) {
back_lines (page_length + 1);
/* We don't call print_page() here but use scrolling to ensure
faster screen update. However, 'end_reached' and
'page_length' should still be updated, and 'page' should
point to start of next page. This is done by calling
get_line() in the following 'for' loop. */
scrollok (text, TRUE);
wscrl (text, -1); /* Scroll text region down one line */
scrollok (text, FALSE);
page_length = 0;
passed_end = 0;
for (i = 0; i < height - 4; i++) {
if (!i) {
/* print first line of page */
print_line (text, 0, width - 2);
wnoutrefresh (text);
} else
/* Called to update 'end_reached' and 'page' */
get_line ();
if (!passed_end)
page_length++;
if (end_reached && !passed_end)
passed_end = 1;
}
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh (dialog);
}
break;
case 'B': /* Previous page */
case 'b':
case KEY_PPAGE:
if (begin_reached)
break;
back_lines (page_length + height - 4);
print_page (text, height - 4, width - 2);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x);
wrefresh (dialog);
break;
case 'J': /* Next line */
case 'j':
case KEY_DOWN:
if (!end_reached) {
begin_reached = 0;
scrollok (text, TRUE);
scroll (text); /* Scroll text region up one line */
scrollok (text, FALSE);
print_line (text, height - 5, width - 2);
wnoutrefresh (text);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh (dialog);
}
break;
case KEY_NPAGE: /* Next page */
case ' ':
if (end_reached)
break;
begin_reached = 0;
print_page (text, height - 4, width - 2);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x);
wrefresh (dialog);
break;
case '0': /* Beginning of line */
case 'H': /* Scroll left */
case 'h':
case KEY_LEFT:
if (hscroll <= 0)
break;
if (key == '0')
hscroll = 0;
else
hscroll--;
/* Reprint current page to scroll horizontally */
back_lines (page_length);
print_page (text, height - 4, width - 2);
wmove (dialog, cur_y, cur_x);
wrefresh (dialog);
break;
case 'L': /* Scroll right */
case 'l':
case KEY_RIGHT:
if (hscroll >= MAX_LEN)
break;
hscroll++;
/* Reprint current page to scroll horizontally */
back_lines (page_length);
print_page (text, height - 4, width - 2);
wmove (dialog, cur_y, cur_x);
wrefresh (dialog);
break;
case ESC:
break;
}
}
delwin (dialog);
free (buf);
close (fd);
return -1; /* ESC pressed */
}
/*
* Go back 'n' lines in text file. Called by dialog_textbox().
* 'page' will be updated to point to the desired line in 'buf'.
*/
static void
back_lines (int n)
{
int i, fpos;
begin_reached = 0;
/* We have to distinguish between end_reached and !end_reached
since at end of file, the line is not ended by a '\n'.
The code inside 'if' basically does a '--page' to move one
character backward so as to skip '\n' of the previous line */
if (!end_reached) {
/* Either beginning of buffer or beginning of file reached? */
if (page == buf) {
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in "
"back_lines().\n");
exit (-1);
}
if (fpos > bytes_read) { /* Not beginning of file yet */
/* We've reached beginning of buffer, but not beginning of
file yet, so read previous part of file into buffer.
Note that we only move backward for BUF_SIZE/2 bytes,
but not BUF_SIZE bytes to avoid re-reading again in
print_page() later */
/* Really possible to move backward BUF_SIZE/2 bytes? */
if (fpos < BUF_SIZE / 2 + bytes_read) {
/* No, move less then */
if (lseek (fd, 0, SEEK_SET) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in "
"back_lines().\n");
exit (-1);
}
page = buf + fpos - bytes_read;
} else { /* Move backward BUF_SIZE/2 bytes */
if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR)
== -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer "
"in back_lines().\n");
exit (-1);
}
page = buf + BUF_SIZE / 2;
}
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr, "\nError reading file in back_lines().\n");
exit (-1);
}
buf[bytes_read] = '\0';
} else { /* Beginning of file reached */
begin_reached = 1;
return;
}
}
if (*(--page) != '\n') { /* '--page' here */
/* Something's wrong... */
endwin ();
fprintf (stderr, "\nInternal error in back_lines().\n");
exit (-1);
}
}
/* Go back 'n' lines */
for (i = 0; i < n; i++)
do {
if (page == buf) {
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr,
"\nError moving file pointer in back_lines().\n");
exit (-1);
}
if (fpos > bytes_read) {
/* Really possible to move backward BUF_SIZE/2 bytes? */
if (fpos < BUF_SIZE / 2 + bytes_read) {
/* No, move less then */
if (lseek (fd, 0, SEEK_SET) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer "
"in back_lines().\n");
exit (-1);
}
page = buf + fpos - bytes_read;
} else { /* Move backward BUF_SIZE/2 bytes */
if (lseek (fd, -(BUF_SIZE / 2 + bytes_read),
SEEK_CUR) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer"
" in back_lines().\n");
exit (-1);
}
page = buf + BUF_SIZE / 2;
}
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr, "\nError reading file in "
"back_lines().\n");
exit (-1);
}
buf[bytes_read] = '\0';
} else { /* Beginning of file reached */
begin_reached = 1;
return;
}
}
} while (*(--page) != '\n');
page++;
}
/*
* Print a new page of text. Called by dialog_textbox().
*/
static void
print_page (WINDOW * win, int height, int width)
{
int i, passed_end = 0;
page_length = 0;
for (i = 0; i < height; i++) {
print_line (win, i, width);
if (!passed_end)
page_length++;
if (end_reached && !passed_end)
passed_end = 1;
}
wnoutrefresh (win);
}
/*
* Print a new line of text. Called by dialog_textbox() and print_page().
*/
static void
print_line (WINDOW * win, int row, int width)
{
int y, x;
char *line;
line = get_line ();
line += MIN (strlen (line), hscroll); /* Scroll horizontally */
wmove (win, row, 0); /* move cursor to correct line */
waddch (win, ' ');
waddnstr (win, line, MIN (strlen (line), width - 2));
getyx (win, y, x);
/* Clear 'residue' of previous line */
#if OLD_NCURSES
{
int i;
for (i = 0; i < width - x; i++)
waddch (win, ' ');
}
#else
wclrtoeol(win);
#endif
}
/*
* Return current line of text. Called by dialog_textbox() and print_line().
* 'page' should point to start of current line before calling, and will be
* updated to point to start of next line.
*/
static char *
get_line (void)
{
int i = 0, fpos;
static char line[MAX_LEN + 1];
end_reached = 0;
while (*page != '\n') {
if (*page == '\0') {
/* Either end of file or end of buffer reached */
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in "
"get_line().\n");
exit (-1);
}
if (fpos < file_size) { /* Not end of file yet */
/* We've reached end of buffer, but not end of file yet,
so read next part of file into buffer */
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr, "\nError reading file in get_line().\n");
exit (-1);
}
buf[bytes_read] = '\0';
page = buf;
} else {
if (!end_reached)
end_reached = 1;
break;
}
} else if (i < MAX_LEN)
line[i++] = *(page++);
else {
/* Truncate lines longer than MAX_LEN characters */
if (i == MAX_LEN)
line[i++] = '\0';
page++;
}
}
if (i <= MAX_LEN)
line[i] = '\0';
if (!end_reached)
page++; /* move pass '\n' */
return line;
}
/*
* Print current position
*/
static void
print_position (WINDOW * win, int height, int width)
{
int fpos, percent;
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in print_position().\n");
exit (-1);
}
wattrset (win, position_indicator_attr);
wbkgdset (win, position_indicator_attr & A_COLOR);
percent = !file_size ?
100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
wmove (win, height - 3, width - 9);
wprintw (win, "(%3d%%)", percent);
}

359
scripts/lxdialog/util.c

@ -0,0 +1,359 @@
/*
* util.c
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
/* use colors by default? */
bool use_colors = 1;
const char *backtitle = NULL;
const char *dialog_result;
/*
* Attribute values, default is for mono display
*/
chtype attributes[] =
{
A_NORMAL, /* screen_attr */
A_NORMAL, /* shadow_attr */
A_NORMAL, /* dialog_attr */
A_BOLD, /* title_attr */
A_NORMAL, /* border_attr */
A_REVERSE, /* button_active_attr */
A_DIM, /* button_inactive_attr */
A_REVERSE, /* button_key_active_attr */
A_BOLD, /* button_key_inactive_attr */
A_REVERSE, /* button_label_active_attr */
A_NORMAL, /* button_label_inactive_attr */
A_NORMAL, /* inputbox_attr */
A_NORMAL, /* inputbox_border_attr */
A_NORMAL, /* searchbox_attr */
A_BOLD, /* searchbox_title_attr */
A_NORMAL, /* searchbox_border_attr */
A_BOLD, /* position_indicator_attr */
A_NORMAL, /* menubox_attr */
A_NORMAL, /* menubox_border_attr */
A_NORMAL, /* item_attr */
A_REVERSE, /* item_selected_attr */
A_BOLD, /* tag_attr */
A_REVERSE, /* tag_selected_attr */
A_BOLD, /* tag_key_attr */
A_REVERSE, /* tag_key_selected_attr */
A_BOLD, /* check_attr */
A_REVERSE, /* check_selected_attr */
A_BOLD, /* uarrow_attr */
A_BOLD /* darrow_attr */
};
#include "colors.h"
/*
* Table of color values
*/
int color_table[][3] =
{
{SCREEN_FG, SCREEN_BG, SCREEN_HL},
{SHADOW_FG, SHADOW_BG, SHADOW_HL},
{DIALOG_FG, DIALOG_BG, DIALOG_HL},
{TITLE_FG, TITLE_BG, TITLE_HL},
{BORDER_FG, BORDER_BG, BORDER_HL},
{BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL},
{BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL},
{BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL},
{BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL},
{BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, BUTTON_LABEL_ACTIVE_HL},
{BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG,
BUTTON_LABEL_INACTIVE_HL},
{INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL},
{INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL},
{SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL},
{SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL},
{SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL},
{POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL},
{MENUBOX_FG, MENUBOX_BG, MENUBOX_HL},
{MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL},
{ITEM_FG, ITEM_BG, ITEM_HL},
{ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL},
{TAG_FG, TAG_BG, TAG_HL},
{TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL},
{TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL},
{TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL},
{CHECK_FG, CHECK_BG, CHECK_HL},
{CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL},
{UARROW_FG, UARROW_BG, UARROW_HL},
{DARROW_FG, DARROW_BG, DARROW_HL},
}; /* color_table */
/*
* Set window to attribute 'attr'
*/
void
attr_clear (WINDOW * win, int height, int width, chtype attr)
{
int i, j;
wattrset (win, attr);
for (i = 0; i < height; i++) {
wmove (win, i, 0);
for (j = 0; j < width; j++)
waddch (win, ' ');
}
touchwin (win);
}
void dialog_clear (void)
{
attr_clear (stdscr, LINES, COLS, screen_attr);
/* Display background title if it exists ... - SLH */
if (backtitle != NULL) {
int i;
wattrset (stdscr, screen_attr);
mvwaddstr (stdscr, 0, 1, (char *)backtitle);
wmove (stdscr, 1, 1);
for (i = 1; i < COLS - 1; i++)
waddch (stdscr, ACS_HLINE);
}
wnoutrefresh (stdscr);
}
/*
* Do some initialization for dialog
*/
void
init_dialog (void)
{
initscr (); /* Init curses */
keypad (stdscr, TRUE);
cbreak ();
noecho ();
if (use_colors) /* Set up colors */
color_setup ();
dialog_clear ();
}
/*
* Setup for color display
*/
void
color_setup (void)
{
int i;
if (has_colors ()) { /* Terminal supports color? */
start_color ();
/* Initialize color pairs */
for (i = 0; i < ATTRIBUTE_COUNT; i++)
init_pair (i + 1, color_table[i][0], color_table[i][1]);
/* Setup color attributes */
for (i = 0; i < ATTRIBUTE_COUNT; i++)
attributes[i] = C_ATTR (color_table[i][2], i + 1);
}
}
/*
* End using dialog functions.
*/
void
end_dialog (void)
{
endwin ();
}
/*
* Print a string of text in a window, automatically wrap around to the
* next line if the string is too long to fit on one line. Newline
* characters '\n' are replaced by spaces. We start on a new line
* if there is no room for at least 4 nonblanks following a double-space.
*/
void
print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x)
{
int newl, cur_x, cur_y;
int i, prompt_len, room, wlen;
char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
strcpy (tempstr, prompt);
prompt_len = strlen(tempstr);
/*
* Remove newlines
*/
for(i=0; i<prompt_len; i++) {
if(tempstr[i] == '\n') tempstr[i] = ' ';
}
if (prompt_len <= width - x * 2) { /* If prompt is short */
wmove (win, y, (width - prompt_len) / 2);
waddstr (win, tempstr);
} else {
cur_x = x;
cur_y = y;
newl = 1;
word = tempstr;
while (word && *word) {
sp = index(word, ' ');
if (sp)
*sp++ = 0;
/* Wrap to next line if either the word does not fit,
or it is the first word of a new sentence, and it is
short, and the next word does not fit. */
room = width - cur_x;
wlen = strlen(word);
if (wlen > room ||
(newl && wlen < 4 && sp && wlen+1+strlen(sp) > room
&& (!(sp2 = index(sp, ' ')) || wlen+1+(sp2-sp) > room))) {
cur_y++;
cur_x = x;
}
wmove (win, cur_y, cur_x);
waddstr (win, word);
getyx (win, cur_y, cur_x);
cur_x++;
if (sp && *sp == ' ') {
cur_x++; /* double space */
while (*++sp == ' ');
newl = 1;
} else
newl = 0;
word = sp;
}
}
}
/*
* Print a button
*/
void
print_button (WINDOW * win, const char *label, int y, int x, int selected)
{
int i, temp;
wmove (win, y, x);
wattrset (win, selected ? button_active_attr : button_inactive_attr);
waddstr (win, "<");
temp = strspn (label, " ");
label += temp;
wattrset (win, selected ? button_label_active_attr
: button_label_inactive_attr);
for (i = 0; i < temp; i++)
waddch (win, ' ');
wattrset (win, selected ? button_key_active_attr
: button_key_inactive_attr);
waddch (win, label[0]);
wattrset (win, selected ? button_label_active_attr
: button_label_inactive_attr);
waddstr (win, (char *)label + 1);
wattrset (win, selected ? button_active_attr : button_inactive_attr);
waddstr (win, ">");
wmove (win, y, x + temp + 1);
}
/*
* Draw a rectangular box with line drawing characters
*/
void
draw_box (WINDOW * win, int y, int x, int height, int width,
chtype box, chtype border)
{
int i, j;
wattrset (win, 0);
for (i = 0; i < height; i++) {
wmove (win, y + i, x);
for (j = 0; j < width; j++)
if (!i && !j)
waddch (win, border | ACS_ULCORNER);
else if (i == height - 1 && !j)
waddch (win, border | ACS_LLCORNER);
else if (!i && j == width - 1)
waddch (win, box | ACS_URCORNER);
else if (i == height - 1 && j == width - 1)
waddch (win, box | ACS_LRCORNER);
else if (!i)
waddch (win, border | ACS_HLINE);
else if (i == height - 1)
waddch (win, box | ACS_HLINE);
else if (!j)
waddch (win, border | ACS_VLINE);
else if (j == width - 1)
waddch (win, box | ACS_VLINE);
else
waddch (win, box | ' ');
}
}
/*
* Draw shadows along the right and bottom edge to give a more 3D look
* to the boxes
*/
void
draw_shadow (WINDOW * win, int y, int x, int height, int width)
{
int i;
if (has_colors ()) { /* Whether terminal supports color? */
wattrset (win, shadow_attr);
wmove (win, y + height, x + 2);
for (i = 0; i < width; i++)
waddch (win, winch (win) & A_CHARTEXT);
for (i = y + 1; i < y + height + 1; i++) {
wmove (win, i, x + width);
waddch (win, winch (win) & A_CHARTEXT);
waddch (win, winch (win) & A_CHARTEXT);
}
wnoutrefresh (win);
}
}
/*
* Return the position of the first alphabetic character in a string.
*/
int
first_alpha(const char *string, const char *exempt)
{
int i, in_paren=0, c;
for (i = 0; i < strlen(string); i++) {
c = tolower(string[i]);
if (strchr("<[(", c)) ++in_paren;
if (strchr(">])", c)) --in_paren;
if ((! in_paren) && isalpha(c) &&
strchr(exempt, c) == 0)
return i;
}
return 0;
}

118
scripts/lxdialog/yesno.c

@ -0,0 +1,118 @@
/*
* yesno.c -- implements the yes/no box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
/*
* Display termination buttons
*/
static void
print_buttons(WINDOW *dialog, int height, int width, int selected)
{
int x = width / 2 - 10;
int y = height - 2;
print_button (dialog, " Yes ", y, x, selected == 0);
print_button (dialog, " No ", y, x + 13, selected == 1);
wmove(dialog, y, x+1 + 13*selected );
wrefresh (dialog);
}
/*
* Display a dialog box with two buttons - Yes and No
*/
int
dialog_yesno (const char *title, const char *prompt, int height, int width)
{
int i, x, y, key = 0, button = 0;
WINDOW *dialog;
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
draw_shadow (stdscr, y, x, height, width);
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
wattrset (dialog, border_attr);
mvwaddch (dialog, height-3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
waddch (dialog, ACS_RTEE);
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
wattrset (dialog, dialog_attr);
print_autowrap (dialog, prompt, width - 2, 1, 3);
print_buttons(dialog, height, width, 0);
while (key != ESC) {
key = wgetch (dialog);
switch (key) {
case 'Y':
case 'y':
delwin (dialog);
return 0;
case 'N':
case 'n':
delwin (dialog);
return 1;
case TAB:
case KEY_LEFT:
case KEY_RIGHT:
button = ((key == KEY_LEFT ? --button : ++button) < 0)
? 1 : (button > 1 ? 0 : button);
print_buttons(dialog, height, width, button);
wrefresh (dialog);
break;
case ' ':
case '\n':
delwin (dialog);
return button;
case ESC:
break;
}
}
delwin (dialog);
return -1; /* ESC pressed */
}

13
scripts/size

@ -0,0 +1,13 @@
#!/bin/bash
j=0
for i in ".text" ".data" ".bss"
do
val[$j]=$(avr-size -A $1 | grep $i | sed -e "s/^$i *//g" | cut -d " " -f1)
let j=$j+1
done
echo ""
echo "Program: $(echo ${val[0]}+${val[1]}|bc) bytes"
echo "(.text + .data)"
echo ""
echo "Data: $(echo ${val[2]}+${val[1]}|bc) bytes"
echo "(.data + .bss)"

10
scrolltext/Makefile

@ -0,0 +1,10 @@
TARGET = libscrolltext.a
TOPDIR = ..
include $(TOPDIR)/defaults.mk
SRC = scrolltext3.c
SRC += $(SCROLLTEXT_FONT).c
include $(TOPDIR)/rules.mk

20
scrolltext/config.in

@ -0,0 +1,20 @@
dep_bool_menu "Scrolltext Support" SCROLLTEXT_SUPPORT y
choice 'Scrolltext Font' \
'Arial_8 font_arial8 \
Small_6 font_small6 \
Uni_53 font_uni53' \
'Arial_8' SCROLLTEXT_FONT
int "Scrolltest buffer size" SCROLLTEXT_BUFFER_SIZE 128
int "Scrolltext default delay" SCROLLTEXT_DELAY 60
int "Default x speed" SCROLL_X_SPEED 20
int "Default y speed" SCROLL_Y_SPEED 20
string "Default text" SCROLLTEXT_TEXT "</#www.das-labor.org"
endmenu

21
scrolltext/font.h

@ -0,0 +1,21 @@
#ifndef FONT_H
#define FONT_H
#ifdef AVR
# include <avr/pgmspace.h>
#else
# define PROGMEM
# define pgm_read_byte(B) *(B)
# define pgm_read_word(B) *(B)
#endif
typedef struct{
unsigned char fontHeight;
const unsigned int* fontIndex;
const unsigned char* fontData;
unsigned char glyph_beg;
unsigned char glyph_end;
unsigned char glyph_def;
unsigned char storebytes;
} font;
#endif //FONT_H

544
scrolltext/font_arial8.c

@ -0,0 +1,544 @@
#include "font.h"
unsigned int PROGMEM fontIndex_arial8[] = {
0, /* */
2, /* ! */
4, /* " */
10, /* # */
20, /* $ */
30, /* % */
48, /* & */
60, /* ' */
62, /* ( */
68, /* ) */
74, /* * */
80, /* + */
90, /* , */
94, /* - */
100, /* . */
104, /* / */
110, /* 0 */
120, /* 1 */
126, /* 2 */
136, /* 3 */
146, /* 4 */
156, /* 5 */
166, /* 6 */
176, /* 7 */
186, /* 8 */
196, /* 9 */
206, /* : */
208, /* ; */
210, /* < */
220, /* = */
230, /* > */
240, /* ? */
250, /* @ */
270, /* A */
284, /* B */
296, /* C */
308, /* D */
320, /* E */
330, /* F */
340, /* G */
354, /* H */
366, /* I */
368, /* J */
376, /* K */
388, /* L */
398, /* M */
412, /* N */
424, /* O */
438, /* P */
448, /* Q */
462, /* R */
474, /* S */
486, /* T */
496, /* U */
508, /* V */
522, /* W */
542, /* X */
554, /* Y */
568, /* Z */
580, /* [ */
584, /* \ */
590, /* ] */
594, /* ^ */
604, /* _ */
616, /* ` */
620, /* a */
630, /* b */
640, /* c */
650, /* d */
660, /* e */
670, /* f */
676, /* g */
686, /* h */
696, /* i */
698, /* j */
700, /* k */
708, /* l */
710, /* m */
724, /* n */
734, /* o */
744, /* p */
754, /* q */
764, /* r */
770, /* s */
780, /* t */
784, /* u */
794, /* v */
804, /* w */
822, /* x */
832, /* y */
842, /* z */
852, /* { */
858, /* | */
860, /* } */
868, /* ~ */
878
};
unsigned char PROGMEM fontData_arial8[] = {
0x00, 0x00, /* */
0xfc, 0x02, /* # ###### */
0x1c, 0x00, /* ### */
0x00, 0x00, /* */
0x1c, 0x00, /* ### */
0x90, 0x03, /* ### # */
0xf0, 0x00, /* #### */
0x9c, 0x03, /* ### ### */
0xf0, 0x00, /* #### */
0x9c, 0x00, /* # ### */
0x18, 0x01, /* # ## */
0x24, 0x02, /* # # # */
0xfc, 0x07, /* ######### */
0x24, 0x02, /* # # # */
0xc8, 0x01, /* ### # */
0x18, 0x00, /* ## */
0x24, 0x00, /* # # */
0x24, 0x02, /* # # # */
0x98, 0x01, /* ## ## */
0x60, 0x00, /* ## */
0x98, 0x01, /* ## ## */
0x44, 0x02, /* # # # */
0x40, 0x02, /* # # */
0x80, 0x01, /* ## */
0x80, 0x01, /* ## */
0x58, 0x02, /* # # ## */
0x24, 0x02, /* # # # */
0x64, 0x02, /* # ## # */
0x98, 0x01, /* ## ## */
0x80, 0x02, /* # # */
0x1c, 0x00, /* ### */
0xf0, 0x03, /* ###### */
0x08, 0x04, /* # # */
0x04, 0x08, /* # # */
0x04, 0x08, /* # # */
0x08, 0x04, /* # # */
0xf0, 0x03, /* ###### */
0x28, 0x00, /* # # */
0x1c, 0x00, /* ### */
0x28, 0x00, /* # # */
0x40, 0x00, /* # */
0x40, 0x00, /* # */
0xf0, 0x01, /* ##### */
0x40, 0x00, /* # */
0x40, 0x00, /* # */
0x00, 0x00, /* */
0x00, 0x0e, /* ### */
0x80, 0x00, /* # */
0x80, 0x00, /* # */
0x80, 0x00, /* # */
0x00, 0x00, /* */
0x00, 0x02, /* # */
0x00, 0x03, /* ## */
0xf0, 0x00, /* #### */
0x0c, 0x00, /* ## */
0xf8, 0x01, /* ###### */
0x04, 0x02, /* # # */
0x04, 0x02, /* # # */
0x04, 0x02, /* # # */
0xf8, 0x01, /* ###### */
0x10, 0x00, /* # */
0x08, 0x00, /* # */
0xfc, 0x03, /* ######## */
0x08, 0x02, /* # # */
0x04, 0x03, /* ## # */
0x84, 0x02, /* # # # */
0x44, 0x02, /* # # # */
0x38, 0x02, /* # ### */
0x08, 0x01, /* # # */
0x04, 0x02, /* # # */
0x24, 0x02, /* # # # */
0x24, 0x02, /* # # # */
0xd8, 0x01, /* ### ## */
0xc0, 0x00, /* ## */
0xb0, 0x00, /* # ## */
0x88, 0x00, /* # # */
0xfc, 0x03, /* ######## */
0x80, 0x00, /* # */
0x30, 0x01, /* # ## */
0x2c, 0x02, /* # # ## */
0x24, 0x02, /* # # # */
0x24, 0x02, /* # # # */
0xc4, 0x01, /* ### # */
0xf8, 0x01, /* ###### */
0x24, 0x02, /* # # # */
0x24, 0x02, /* # # # */
0x24, 0x02, /* # # # */
0xc8, 0x01, /* ### # */
0x04, 0x00, /* # */
0x84, 0x03, /* ### # */
0x64, 0x00, /* ## # */
0x1c, 0x00, /* ### */
0x04, 0x00, /* # */
0xd8, 0x01, /* ### ## */
0x24, 0x02, /* # # # */
0x24, 0x02, /* # # # */
0x24, 0x02, /* # # # */
0xd8, 0x01, /* ### ## */
0x38, 0x01, /* # ### */
0x44, 0x02, /* # # # */
0x44, 0x02, /* # # # */
0x44, 0x02, /* # # # */
0xf8, 0x01, /* ###### */
0x10, 0x02, /* # # */
0x10, 0x0e, /* ### # */
0x40, 0x00, /* # */
0xa0, 0x00, /* # # */
0xa0, 0x00, /* # # */
0xa0, 0x00, /* # # */
0x10, 0x01, /* # # */
0xa0, 0x00, /* # # */
0xa0, 0x00, /* # # */
0xa0, 0x00, /* # # */
0xa0, 0x00, /* # # */
0xa0, 0x00, /* # # */
0x10, 0x01, /* # # */
0xa0, 0x00, /* # # */
0xa0, 0x00, /* # # */
0xa0, 0x00, /* # # */
0x40, 0x00, /* # */
0x08, 0x00, /* # */
0x04, 0x00, /* # */
0xc4, 0x02, /* # ## # */
0x24, 0x00, /* # # */
0x18, 0x00, /* ## */
0xe0, 0x03, /* ##### */
0x18, 0x04, /* # ## */
0xc8, 0x09, /* # ### # */
0x24, 0x0a, /* # # # # */
0x14, 0x0a, /* # # # # */
0x14, 0x09, /* # # # # */
0xe4, 0x0b, /* # ##### # */
0x34, 0x0a, /* # # ## # */
0x08, 0x05, /* # # # */
0xf0, 0x04, /* # #### */
0x00, 0x03, /* ## */
0xc0, 0x00, /* ## */
0xb8, 0x00, /* # ### */
0x84, 0x00, /* # # */
0xb8, 0x00, /* # ### */
0xc0, 0x00, /* ## */
0x00, 0x03, /* ## */
0xfc, 0x03, /* ######## */
0x24, 0x02, /* # # # */
0x24, 0x02, /* # # # */
0x24, 0x02, /* # # # */
0x24, 0x02, /* # # # */
0xf8, 0x01, /* ###### */
0xf0, 0x00, /* #### */
0x08, 0x01, /* # # */
0x04, 0x02, /* # # */
0x04, 0x02, /* # # */
0x04, 0x02, /* # # */
0x08, 0x01, /* # # */
0xfc, 0x03, /* ######## */
0x04, 0x02, /* # # */
0x04, 0x02, /* # # */
0x04, 0x02, /* # # */
0x08, 0x01, /* # # */
0xf0, 0x00, /* #### */
0xfc, 0x03, /* ######## */
0x24, 0x02, /* # # # */
0x24, 0x02, /* # # # */
0x24, 0x02, /* # # # */
0x24, 0x02, /* # # # */
0xfc, 0x03, /* ######## */
0x24, 0x00, /* # # */
0x24, 0x00, /* # # */
0x24, 0x00, /* # # */
0x04, 0x00, /* # */
0xf0, 0x00, /* #### */
0x08, 0x01, /* # # */
0x04, 0x02, /* # # */
0x04, 0x02, /* # # */
0x44, 0x02, /* # # # */
0x48, 0x01, /* # # # */
0xc0, 0x00, /* ## */
0xfc, 0x03, /* ######## */
0x20, 0x00, /* # */
0x20, 0x00, /* # */
0x20, 0x00, /* # */
0x20, 0x00, /* # */
0xfc, 0x03, /* ######## */
0xfc, 0x03, /* ######## */
0x80, 0x01, /* ## */
0x00, 0x02, /* # */
0x00, 0x02, /* # */
0xfc, 0x01, /* ####### */
0xfc, 0x03, /* ######## */
0x40, 0x00, /* # */
0x20, 0x00, /* # */
0x70, 0x00, /* ### */
0x88, 0x01, /* ## # */
0x04, 0x02, /* # # */
0xfc, 0x03, /* ######## */
0x00, 0x02, /* # */
0x00, 0x02, /* # */
0x00, 0x02, /* # */
0x00, 0x02, /* # */
0xfc, 0x03, /* ######## */
0x18, 0x00, /* ## */
0xe0, 0x00, /* ### */
0x00, 0x03, /* ## */
0xe0, 0x00, /* ### */
0x18, 0x00, /* ## */
0xfc, 0x03, /* ######## */
0xfc, 0x03, /* ######## */
0x08, 0x00, /* # */
0x30, 0x00, /* ## */
0xc0, 0x00, /* ## */
0x00, 0x01, /* # */
0xfc, 0x03, /* ######## */
0xf0, 0x00, /* #### */
0x08, 0x01, /* # # */
0x04, 0x02, /* # # */
0x04, 0x02, /* # # */
0x04, 0x02, /* # # */
0x08, 0x01, /* # # */
0xf0, 0x00, /* #### */
0xfc, 0x03, /* ######## */
0x44, 0x00, /* # # */
0x44, 0x00, /* # # */
0x44, 0x00, /* # # */
0x38, 0x00, /* ### */
0xf0, 0x00, /* #### */
0x08, 0x01, /* # # */
0x04, 0x02, /* # # */
0x84, 0x02, /* # # # */
0x84, 0x02, /* # # # */
0x08, 0x01, /* # # */
0xf0, 0x02, /* # #### */
0xfc, 0x03, /* ######## */
0x24, 0x00, /* # # */
0x24, 0x00, /* # # */
0x64, 0x00, /* ## # */
0xa4, 0x01, /* ## # # */
0x18, 0x02, /* # ## */
0x18, 0x01, /* # ## */
0x24, 0x02, /* # # # */
0x24, 0x02, /* # # # */
0x44, 0x02, /* # # # */
0x44, 0x02, /* # # # */
0x88, 0x01, /* ## # */
0x04, 0x00, /* # */
0x04, 0x00, /* # */
0xfc, 0x03, /* ######## */
0x04, 0x00, /* # */
0x04, 0x00, /* # */
0xfc, 0x01, /* ####### */
0x00, 0x02, /* # */
0x00, 0x02, /* # */
0x00, 0x02, /* # */
0x00, 0x02, /* # */
0xfc, 0x01, /* ####### */
0x0c, 0x00, /* ## */
0x30, 0x00, /* ## */
0xc0, 0x00, /* ## */
0x00, 0x03, /* ## */
0xc0, 0x00, /* ## */
0x30, 0x00, /* ## */
0x0c, 0x00, /* ## */
0xf0, 0x00, /* #### */
0x00, 0x03, /* ## */
0xc0, 0x00, /* ## */
0x38, 0x00, /* ### */
0x04, 0x00, /* # */
0x38, 0x00, /* ### */
0xc0, 0x00, /* ## */
0x00, 0x03, /* ## */
0xf0, 0x00, /* #### */
0x0c, 0x00, /* ## */
0x04, 0x02, /* # # */
0x98, 0x01, /* ## ## */
0x60, 0x00, /* ## */
0x60, 0x00, /* ## */
0x98, 0x01, /* ## ## */
0x04, 0x02, /* # # */
0x04, 0x00, /* # */
0x18, 0x00, /* ## */
0x20, 0x00, /* # */
0xc0, 0x03, /* #### */
0x20, 0x00, /* # */
0x18, 0x00, /* ## */
0x04, 0x00, /* # */
0x00, 0x02, /* # */
0x04, 0x03, /* ## # */
0xc4, 0x02, /* # ## # */
0x34, 0x02, /* # ## # */
0x0c, 0x02, /* # ## */
0x04, 0x02, /* # # */
0xfc, 0x0f, /* ########## */
0x04, 0x08, /* # # */
0x0c, 0x00, /* ## */
0xf0, 0x00, /* #### */
0x00, 0x03, /* ## */
0x04, 0x08, /* # # */
0xfc, 0x0f, /* ########## */
0x20, 0x00, /* # */
0x18, 0x00, /* ## */
0x04, 0x00, /* # */
0x18, 0x00, /* ## */
0x20, 0x00, /* # */
0x00, 0x08, /* # */
0x00, 0x08, /* # */
0x00, 0x08, /* # */
0x00, 0x08, /* # */
0x00, 0x08, /* # */
0x00, 0x08, /* # */
0x04, 0x00, /* # */
0x08, 0x00, /* # */
0xa0, 0x01, /* ## # */
0x50, 0x02, /* # # # */
0x50, 0x02, /* # # # */
0x50, 0x01, /* # # # */
0xe0, 0x03, /* ##### */
0xfc, 0x03, /* ######## */
0x20, 0x01, /* # # */
0x10, 0x02, /* # # */
0x10, 0x02, /* # # */
0xe0, 0x01, /* #### */
0xe0, 0x01, /* #### */
0x10, 0x02, /* # # */
0x10, 0x02, /* # # */
0x10, 0x02, /* # # */
0x20, 0x01, /* # # */
0xe0, 0x01, /* #### */
0x10, 0x02, /* # # */
0x10, 0x02, /* # # */
0x20, 0x01, /* # # */
0xfc, 0x03, /* ######## */
0xe0, 0x01, /* #### */
0x50, 0x02, /* # # # */
0x50, 0x02, /* # # # */
0x50, 0x02, /* # # # */
0x60, 0x01, /* # ## */
0x10, 0x00, /* # */
0xf8, 0x03, /* ####### */
0x14, 0x00, /* # # */
0xe0, 0x09, /* # #### */
0x10, 0x0a, /* # # # */
0x10, 0x0a, /* # # # */
0x20, 0x09, /* # # # */
0xf0, 0x07, /* ####### */
0xfc, 0x03, /* ######## */
0x20, 0x00, /* # */
0x10, 0x00, /* # */
0x10, 0x00, /* # */
0xe0, 0x03, /* ##### */
0xf4, 0x03, /* ###### # */
0xf4, 0x07, /* ####### # */
0xfc, 0x03, /* ######## */
0x40, 0x00, /* # */
0xa0, 0x01, /* ## # */
0x10, 0x02, /* # # */
0xfc, 0x03, /* ######## */
0xf0, 0x03, /* ###### */
0x20, 0x00, /* # */
0x10, 0x00, /* # */
0xf0, 0x03, /* ###### */
0x20, 0x00, /* # */
0x10, 0x00, /* # */
0xe0, 0x03, /* ##### */
0xf0, 0x03, /* ###### */
0x10, 0x00, /* # */
0x10, 0x00, /* # */
0x10, 0x00, /* # */
0xe0, 0x03, /* ##### */
0xe0, 0x01, /* #### */
0x10, 0x02, /* # # */
0x10, 0x02, /* # # */
0x10, 0x02, /* # # */
0xe0, 0x01, /* #### */
0xf0, 0x0f, /* ######## */
0x20, 0x01, /* # # */
0x10, 0x02, /* # # */
0x10, 0x02, /* # # */
0xe0, 0x01, /* #### */
0xe0, 0x01, /* #### */
0x10, 0x02, /* # # */
0x10, 0x02, /* # # */
0x20, 0x01, /* # # */
0xf0, 0x0f, /* ######## */
0xf0, 0x03, /* ###### */
0x20, 0x00, /* # */
0x10, 0x00, /* # */
0x20, 0x01, /* # # */
0x50, 0x02, /* # # # */
0x50, 0x02, /* # # # */
0x90, 0x02, /* # # # */
0x20, 0x01, /* # # */
0xfc, 0x03, /* ######## */
0x10, 0x02, /* # # */
0xf0, 0x01, /* ##### */
0x00, 0x02, /* # */
0x00, 0x02, /* # */
0x00, 0x01, /* # */
0xf0, 0x03, /* ###### */
0x30, 0x00, /* ## */
0xc0, 0x00, /* ## */
0x00, 0x03, /* ## */
0xc0, 0x00, /* ## */
0x30, 0x00, /* ## */
0x30, 0x00, /* ## */
0xc0, 0x00, /* ## */
0x00, 0x03, /* ## */
0xe0, 0x00, /* ### */
0x10, 0x00, /* # */
0xe0, 0x00, /* ### */
0x00, 0x03, /* ## */
0xc0, 0x00, /* ## */
0x30, 0x00, /* ## */
0x10, 0x02, /* # # */
0x20, 0x01, /* # # */
0xc0, 0x00, /* ## */
0x20, 0x01, /* # # */
0x10, 0x02, /* # # */
0x10, 0x00, /* # */
0xe0, 0x09, /* # #### */
0x00, 0x07, /* ### */
0xc0, 0x00, /* ## */
0x30, 0x00, /* ## */
0x10, 0x02, /* # # */
0x10, 0x03, /* ## # */
0x90, 0x02, /* # # # */
0x70, 0x02, /* # ### */
0x10, 0x02, /* # # */
0x40, 0x00, /* # */
0xb8, 0x07, /* #### ### */
0x04, 0x08, /* # # */
0xfc, 0x0f, /* ########## */
0x00, 0x00, /* */
0x04, 0x08, /* # # */
0xb8, 0x07, /* #### ### */
0x40, 0x00, /* # */
0x60, 0x00, /* ## */
0x20, 0x00, /* # */
0x60, 0x00, /* ## */
0x40, 0x00, /* # */
0x20, 0x00, /* # */
};
font font_arial8 = {13, fontIndex_arial8, fontData_arial8, ' ', '~', '.', 2};

8
scrolltext/font_arial8.h

@ -0,0 +1,8 @@
#ifndef FONT_ARIAL8_H
#define FONT_ARIAL8_H
#include "font.h"
extern font font_arial8;
#endif /* FONT_ARIAL8_H */

439
scrolltext/font_small6.c

@ -0,0 +1,439 @@
#include "font.h"
unsigned int PROGMEM fontIndex_small6[] = {
0, /* */
1, /* ! */
2, /* " */
5, /* # */
10, /* $ */
13, /* % */
17, /* & */
21, /* ' */
22, /* ( */
24, /* ) */
26, /* * */
28, /* + */
31, /* , */
32, /* - */
34, /* . */
35, /* / */
37, /* 0 */
41, /* 1 */
43, /* 2 */
47, /* 3 */
51, /* 4 */
55, /* 5 */
58, /* 6 */
62, /* 7 */
65, /* 8 */
69, /* 9 */
73, /* : */
74, /* ; */
75, /* < */
78, /* = */
81, /* > */
84, /* ? */
88, /* @ */
95, /* A */
100, /* B */
105, /* C */
110, /* D */
115, /* E */
119, /* F */
123, /* G */
128, /* H */
132, /* I */
133, /* J */
136, /* K */
140, /* L */
143, /* M */
150, /* N */
155, /* O */
160, /* P */
164, /* Q */
169, /* R */
174, /* S */
178, /* T */
182, /* U */
187, /* V */
192, /* W */
199, /* X */
204, /* Y */
209, /* Z */
213, /* [ */
215, /* \ */
217, /* ] */
219, /* ^ */
222, /* _ */
226, /* ` */
228, /* a */
231, /* b */
235, /* c */
238, /* d */
242, /* e */
245, /* f */
247, /* g */
251, /* h */
254, /* i */
255, /* j */
256, /* k */
259, /* l */
260, /* m */
265, /* n */
268, /* o */
272, /* p */
276, /* q */
280, /* r */
282, /* s */
285, /* t */
287, /* u */
290, /* v */
293, /* w */
298, /* x */
301, /* y */
304, /* z */
307, /* { */
309, /* | */
310, /* } */
312, /* ~ */
316, /* ß */
321, /* ä */
324, /* ö */
328, /* ü */
331
};
unsigned char PROGMEM fontData_small6[] = {
0x00, /* */
0x2f, /* # #### */
0x03, /* ## */
0x00, /* */
0x03, /* ## */
0x12, /* # # */
0x3f, /* ###### */
0x12, /* # # */
0x3f, /* ###### */
0x12, /* # # */
0x26, /* # ## */
0x7f, /* ####### */
0x32, /* ## # */
0x13, /* # ## */
0x0b, /* # ## */
0x34, /* ## # */
0x32, /* ## # */
0x1a, /* ## # */
0x25, /* # # # */
0x1a, /* ## # */
0x28, /* # # */
0x03, /* ## */
0x7e, /* ###### */
0x81, /* # # */
0x81, /* # # */
0x7e, /* ###### */
0x03, /* ## */
0x03, /* ## */
0x08, /* # */
0x1c, /* ### */
0x08, /* # */
0x60, /* ## */
0x08, /* # */
0x08, /* # */
0x20, /* # */
0x38, /* ### */
0x07, /* ### */
0x1e, /* #### */
0x21, /* # # */
0x21, /* # # */
0x1e, /* #### */
0x02, /* # */
0x3f, /* ###### */
0x32, /* ## # */
0x29, /* # # # */
0x29, /* # # # */
0x26, /* # ## */
0x12, /* # # */
0x21, /* # # */
0x25, /* # # # */
0x1a, /* ## # */
0x18, /* ## */
0x16, /* # ## */
0x3f, /* ###### */
0x10, /* # */
0x27, /* # ### */
0x25, /* # # # */
0x19, /* ## # */
0x1e, /* #### */
0x25, /* # # # */
0x25, /* # # # */
0x18, /* ## */
0x01, /* # */
0x3d, /* #### # */
0x03, /* ## */
0x1a, /* ## # */
0x25, /* # # # */
0x25, /* # # # */
0x1a, /* ## # */
0x12, /* # # */
0x25, /* # # # */
0x25, /* # # # */
0x1e, /* #### */
0x24, /* # # */
0x64, /* ## # */
0x08, /* # */
0x14, /* # # */
0x22, /* # # */
0x14, /* # # */
0x14, /* # # */
0x14, /* # # */
0x22, /* # # */
0x14, /* # # */
0x08, /* # */
0x02, /* # */
0x29, /* # # # */
0x05, /* # # */
0x02, /* # */
0x1c, /* ### */
0x22, /* # # */
0x49, /* # # # */
0x55, /* # # # # */
0x59, /* # ## # */
0x12, /* # # */
0x0c, /* ## */
0x30, /* ## */
0x0c, /* ## */
0x0b, /* # ## */
0x0c, /* ## */
0x30, /* ## */
0x3f, /* ###### */
0x25, /* # # # */
0x25, /* # # # */
0x25, /* # # # */
0x1a, /* ## # */
0x1e, /* #### */
0x21, /* # # */
0x21, /* # # */
0x21, /* # # */
0x12, /* # # */
0x3f, /* ###### */
0x21, /* # # */
0x21, /* # # */
0x21, /* # # */
0x1e, /* #### */
0x3f, /* ###### */
0x25, /* # # # */
0x25, /* # # # */
0x21, /* # # */
0x3f, /* ###### */
0x05, /* # # */
0x05, /* # # */
0x01, /* # */
0x1e, /* #### */
0x21, /* # # */
0x21, /* # # */
0x29, /* # # # */
0x3a, /* ### # */
0x3f, /* ###### */
0x04, /* # */
0x04, /* # */
0x3f, /* ###### */
0x3f, /* ###### */
0x30, /* ## */
0x20, /* # */
0x1f, /* ##### */
0x3f, /* ###### */
0x0c, /* ## */
0x12, /* # # */
0x21, /* # # */
0x3f, /* ###### */
0x20, /* # */
0x20, /* # */
0x3f, /* ###### */
0x03, /* ## */
0x0c, /* ## */
0x30, /* ## */
0x0c, /* ## */
0x03, /* ## */
0x3f, /* ###### */
0x3f, /* ###### */
0x03, /* ## */
0x0c, /* ## */
0x30, /* ## */
0x3f, /* ###### */
0x1e, /* #### */
0x21, /* # # */
0x21, /* # # */
0x21, /* # # */
0x1e, /* #### */
0x3f, /* ###### */
0x09, /* # # */
0x09, /* # # */
0x06, /* ## */
0x1e, /* #### */
0x21, /* # # */
0x29, /* # # # */
0x11, /* # # */
0x2e, /* # ### */
0x3f, /* ###### */
0x09, /* # # */
0x09, /* # # */
0x09, /* # # */
0x36, /* ## ## */
0x12, /* # # */
0x25, /* # # # */
0x29, /* # # # */
0x12, /* # # */
0x01, /* # */
0x3f, /* ###### */
0x01, /* # */
0x01, /* # */
0x1f, /* ##### */
0x20, /* # */
0x20, /* # */
0x20, /* # */
0x1f, /* ##### */
0x03, /* ## */
0x0c, /* ## */
0x30, /* ## */
0x0c, /* ## */
0x03, /* ## */
0x03, /* ## */
0x0c, /* ## */
0x30, /* ## */
0x0c, /* ## */
0x30, /* ## */
0x0c, /* ## */
0x03, /* ## */
0x21, /* # # */
0x12, /* # # */
0x0c, /* ## */
0x12, /* # # */
0x21, /* # # */
0x01, /* # */
0x02, /* # */
0x3c, /* #### */
0x02, /* # */
0x01, /* # */
0x31, /* ## # */
0x29, /* # # # */
0x25, /* # # # */
0x23, /* # ## */
0x7f, /* ####### */
0x41, /* # # */
0x07, /* ### */
0x38, /* ### */
0x41, /* # # */
0x7f, /* ####### */
0x02, /* # */
0x01, /* # */
0x02, /* # */
0x40, /* # */
0x40, /* # */
0x40, /* # */
0x40, /* # */
0x00, /* */
0x01, /* # */
0x14, /* # # */
0x24, /* # # */
0x38, /* ### */
0x3f, /* ###### */
0x24, /* # # */
0x24, /* # # */
0x18, /* ## */
0x18, /* ## */
0x24, /* # # */
0x24, /* # # */
0x18, /* ## */
0x24, /* # # */
0x24, /* # # */
0x3f, /* ###### */
0x18, /* ## */
0x24, /* # # */
0x28, /* # # */
0x3e, /* ##### */
0x05, /* # # */
0x18, /* ## */
0xa4, /* # # # */
0xa4, /* # # # */
0x7c, /* ##### */
0x3f, /* ###### */
0x04, /* # */
0x38, /* ### */
0x3d, /* #### # */
0xfd, /* ###### # */
0x3f, /* ###### */
0x08, /* # */
0x34, /* ## # */
0x3f, /* ###### */
0x3c, /* #### */
0x04, /* # */
0x3c, /* #### */
0x04, /* # */
0x38, /* ### */
0x3c, /* #### */
0x04, /* # */
0x38, /* ### */
0x18, /* ## */
0x24, /* # # */
0x24, /* # # */
0x18, /* ## */
0xfc, /* ###### */
0x24, /* # # */
0x24, /* # # */
0x18, /* ## */
0x18, /* ## */
0x24, /* # # */
0x24, /* # # */
0xfc, /* ###### */
0x3c, /* #### */
0x04, /* # */
0x28, /* # # */
0x24, /* # # */
0x14, /* # # */
0x1e, /* #### */
0x24, /* # # */
0x1c, /* ### */
0x20, /* # */
0x3c, /* #### */
0x0c, /* ## */
0x30, /* ## */
0x0c, /* ## */
0x0c, /* ## */
0x30, /* ## */
0x0c, /* ## */
0x30, /* ## */
0x0c, /* ## */
0x24, /* # # */
0x18, /* ## */
0x24, /* # # */
0x9c, /* # ### */
0x60, /* ## */
0x1c, /* ### */
0x34, /* ## # */
0x24, /* # # */
0x2c, /* # ## */
0x08, /* # */
0x77, /* ### ### */
0x7f, /* ####### */
0x77, /* ### ### */
0x08, /* # */
0x01, /* # */
0x02, /* # */
0x01, /* # */
0x02, /* # */
0x3e, /* ##### */
0x05, /* # # */
0x26, /* # ## */
0x18, /* ## */
0x19, /* ## # */
0x24, /* # # */
0x29, /* # # # */
0x19, /* ## # */
0x24, /* # # */
0x24, /* # # */
0x19, /* ## # */
0x1d, /* ### # */
0x20, /* # */
0x3d, /* #### # */
};
font font_small6 = {8, fontIndex_small6, fontData_small6, ' ', '~', '.', 1};

7
scrolltext/font_small6.h

@ -0,0 +1,7 @@
#ifndef FONT_SMALL6_H
#define FONT_SMALL6_H
#include "font.h"
extern font font_small6;
#endif /* FONT_SMALL6_H_ */

503
scrolltext/font_uni53.c

@ -0,0 +1,503 @@
#include "font.h"
static unsigned int PROGMEM fontIndex_uni53[] = { 0, /* */
1, /* ! */
3, /* " */
6, /* # */
11, /* $ */
16, /* % */
21, /* & */
27, /* ' */
28, /* ( */
30, /* ) */
32, /* * */
37, /* + */
42, /* , */
44, /* - */
48, /* . */
49, /* / */
54, /* 0 */
59, /* 1 */
61, /* 2 */
66, /* 3 */
71, /* 4 */
76, /* 5 */
81, /* 6 */
86, /* 7 */
90, /* 8 */
95, /* 9 */
100, /* : */
102, /* ; */
104, /* < */
107, /* = */
112, /* > */
115, /* ? */
119, /* @ */
124, /* A */
129, /* B */
134, /* C */
139, /* D */
144, /* E */
149, /* F */
154, /* G */
159, /* H */
164, /* I */
165, /* J */
169, /* K */
174, /* L */
178, /* M */
183, /* N */
188, /* O */
193, /* P */
198, /* Q */
203, /* R */
208, /* S */
213, /* T */
218, /* U */
223, /* V */
228, /* W */
235, /* X */
240, /* Y */
245, /* Z */
250, /* [ */
252, /* \ */
257, /* ] */
259, /* ^ */
262, /* _ */
267, /* ` */
269, /* a */
273, /* b */
277, /* c */
281, /* d */
285, /* e */
289, /* f */
291, /* g */
295, /* h */
299, /* i */
300, /* j */
302, /* k */
306, /* l */
307, /* m */
314, /* n */
318, /* o */
322, /* p */
326, /* q */
330, /* r */
333, /* s */
337, /* t */
340, /* u */
344, /* v */
348, /* w */
355, /* x */
359, /* y */
363, /* z */
367, /* { */
370, /* | */
372, /* } */
375, /* ~ */
379, /* ß */
383, /* ä */
387, /* ö */
391, /* ü */
395
};
static unsigned char PROGMEM fontData_uni53[] = {
0x00, /* */
0x00, /* */
0x2e, /* # ### */
0x06, /* ## */
0x00, /* */
0x06, /* ## */
0x14, /* # # */
0x3e, /* ##### */
0x14, /* # # */
0x3e, /* ##### */
0x14, /* # # */
0x24, /* # # */
0x2a, /* # # # */
0x6b, /* ## # ## */
0x2a, /* # # # */
0x12, /* # # */
0x22, /* # # */
0x10, /* # */
0x08, /* # */
0x04, /* # */
0x22, /* # # */
0x14, /* # # */
0x2a, /* # # # */
0x2a, /* # # # */
0x2a, /* # # # */
0x24, /* # # */
0x10, /* # */
0x06, /* ## */
0x3e, /* ##### */
0x41, /* # # */
0x41, /* # # */
0x3e, /* ##### */
0x08, /* # */
0x2a, /* # # # */
0x1c, /* ### */
0x2a, /* # # # */
0x08, /* # */
0x08, /* # */
0x08, /* # */
0x3e, /* ##### */
0x08, /* # */
0x08, /* # */
0x80, /* # */
0x60, /* ## */
0x08, /* # */
0x08, /* # */
0x08, /* # */
0x08, /* # */
0x20, /* # */
0x20, /* # */
0x10, /* # */
0x08, /* # */
0x04, /* # */
0x02, /* # */
0x1c, /* ### */
0x22, /* # # */
0x22, /* # # */
0x22, /* # # */
0x1c, /* ### */
0x02, /* # */
0x3e, /* ##### */
0x32, /* ## # */
0x2a, /* # # # */
0x2a, /* # # # */
0x2a, /* # # # */
0x2c, /* # ## */
0x22, /* # # */
0x2a, /* # # # */
0x2a, /* # # # */
0x2a, /* # # # */
0x14, /* # # */
0x0e, /* ### */
0x08, /* # */
0x08, /* # */
0x08, /* # */
0x3e, /* ##### */
0x2e, /* # ### */
0x2a, /* # # # */
0x2a, /* # # # */
0x2a, /* # # # */
0x12, /* # # */
0x1c, /* ### */
0x2a, /* # # # */
0x2a, /* # # # */
0x2a, /* # # # */
0x10, /* # */
0x02, /* # */
0x02, /* # */
0x32, /* ## # */
0x0e, /* ### */
0x14, /* # # */
0x2a, /* # # # */
0x2a, /* # # # */
0x2a, /* # # # */
0x14, /* # # */
0x04, /* # */
0x2a, /* # # # */
0x2a, /* # # # */
0x2a, /* # # # */
0x1c, /* ### */
0x00, /* */
0x14, /* # # */
0x80, /* # */
0x64, /* ## # */
0x08, /* # */
0x14, /* # # */
0x22, /* # # */
0x14, /* # # */
0x14, /* # # */
0x14, /* # # */
0x14, /* # # */
0x14, /* # # */
0x22, /* # # */
0x14, /* # # */
0x08, /* # */
0x02, /* # */
0x2a, /* # # # */
0x0a, /* # # */
0x04, /* # */
0x1c, /* ### */
0x22, /* # # */
0x2a, /* # # # */
0x2a, /* # # # */
0x0c, /* ## */
0x3c, /* #### */
0x0a, /* # # */
0x0a, /* # # */
0x0a, /* # # */
0x3c, /* #### */
0x3e, /* ##### */
0x2a, /* # # # */
0x2a, /* # # # */
0x2a, /* # # # */
0x14, /* # # */
0x1c, /* ### */
0x22, /* # # */
0x22, /* # # */
0x22, /* # # */
0x14, /* # # */
0x3e, /* ##### */
0x22, /* # # */
0x22, /* # # */
0x22, /* # # */
0x1c, /* ### */
0x3e, /* ##### */
0x2a, /* # # # */
0x2a, /* # # # */
0x2a, /* # # # */
0x22, /* # # */
0x3e, /* ##### */
0x0a, /* # # */
0x0a, /* # # */
0x0a, /* # # */
0x02, /* # */
0x1c, /* ### */
0x22, /* # # */
0x2a, /* # # # */
0x2a, /* # # # */
0x3a, /* ### # */
0x3e, /* ##### */
0x08, /* # */
0x08, /* # */
0x08, /* # */
0x3e, /* ##### */
0x3e, /* ##### */
0x10, /* # */
0x20, /* # */
0x20, /* # */
0x1e, /* #### */
0x3e, /* ##### */
0x08, /* # */
0x08, /* # */
0x14, /* # # */
0x22, /* # # */
0x3e, /* ##### */
0x20, /* # */
0x20, /* # */
0x20, /* # */
0x3e, /* ##### */
0x04, /* # */
0x08, /* # */
0x04, /* # */
0x3e, /* ##### */
0x3e, /* ##### */
0x04, /* # */
0x08, /* # */
0x10, /* # */
0x3e, /* ##### */
0x1c, /* ### */
0x22, /* # # */
0x22, /* # # */
0x22, /* # # */
0x1c, /* ### */
0x3e, /* ##### */
0x0a, /* # # */
0x0a, /* # # */
0x0a, /* # # */
0x04, /* # */
0x1c, /* ### */
0x22, /* # # */
0x22, /* # # */
0x22, /* # # */
0x5c, /* # ### */
0x3e, /* ##### */
0x0a, /* # # */
0x0a, /* # # */
0x1a, /* ## # */
0x24, /* # # */
0x24, /* # # */
0x2a, /* # # # */
0x2a, /* # # # */
0x2a, /* # # # */
0x12, /* # # */
0x02, /* # */
0x02, /* # */
0x3e, /* ##### */
0x02, /* # */
0x02, /* # */
0x1e, /* #### */
0x20, /* # */
0x20, /* # */
0x20, /* # */
0x1e, /* #### */
0x0e, /* ### */
0x10, /* # */
0x20, /* # */
0x10, /* # */
0x0e, /* ### */
0x1e, /* #### */
0x20, /* # */
0x20, /* # */
0x1e, /* #### */
0x20, /* # */
0x20, /* # */
0x1e, /* #### */
0x22, /* # # */
0x14, /* # # */
0x08, /* # */
0x14, /* # # */
0x22, /* # # */
0x02, /* # */
0x04, /* # */
0x38, /* ### */
0x04, /* # */
0x02, /* # */
0x22, /* # # */
0x32, /* ## # */
0x2a, /* # # # */
0x26, /* # ## */
0x22, /* # # */
0x7f, /* ####### */
0x41, /* # # */
0x02, /* # */
0x04, /* # */
0x08, /* # */
0x10, /* # */
0x20, /* # */
0x41, /* # # */
0x7f, /* ####### */
0x04, /* # */
0x02, /* # */
0x04, /* # */
0x40, /* # */
0x40, /* # */
0x40, /* # */
0x40, /* # */
0x40, /* # */
0x02, /* # */
0x04, /* # */
0x18, /* ## */
0x24, /* # # */
0x24, /* # # */
0x38, /* ### */
0x3e, /* ##### */
0x24, /* # # */
0x24, /* # # */
0x18, /* ## */
0x18, /* ## */
0x24, /* # # */
0x24, /* # # */
0x24, /* # # */
0x18, /* ## */
0x24, /* # # */
0x24, /* # # */
0x3e, /* ##### */
0x18, /* ## */
0x24, /* # # */
0x34, /* ## # */
0x2c, /* # ## */
0x3c, /* #### */
0x0a, /* # # */
0x18, /* ## */
0xa4, /* # # # */
0xa4, /* # # # */
0x78, /* #### */
0x3e, /* ##### */
0x04, /* # */
0x04, /* # */
0x38, /* ### */
0x3a, /* ### # */
0x80, /* # */
0x7a, /* #### # */
0x3e, /* ##### */
0x10, /* # */
0x08, /* # */
0x34, /* ## # */
0x3e, /* ##### */
0x3c, /* #### */
0x04, /* # */
0x04, /* # */
0x38, /* ### */
0x04, /* # */
0x04, /* # */
0x38, /* ### */
0x3c, /* #### */
0x04, /* # */
0x04, /* # */
0x38, /* ### */
0x18, /* ## */
0x24, /* # # */
0x24, /* # # */
0x18, /* ## */
0xfc, /* ###### */
0x24, /* # # */
0x24, /* # # */
0x18, /* ## */
0x18, /* ## */
0x24, /* # # */
0x24, /* # # */
0xfc, /* ###### */
0x3c, /* #### */
0x08, /* # */
0x04, /* # */
0x28, /* # # */
0x2c, /* # ## */
0x34, /* ## # */
0x14, /* # # */
0x04, /* # */
0x3e, /* ##### */
0x04, /* # */
0x1c, /* ### */
0x20, /* # */
0x20, /* # */
0x3c, /* #### */
0x1c, /* ### */
0x20, /* # */
0x20, /* # */
0x1c, /* ### */
0x1c, /* ### */
0x20, /* # */
0x20, /* # */
0x1c, /* ### */
0x20, /* # */
0x20, /* # */
0x1c, /* ### */
0x24, /* # # */
0x18, /* ## */
0x18, /* ## */
0x24, /* # # */
0x1c, /* ### */
0xa0, /* # # */
0xa0, /* # # */
0x7c, /* ##### */
0x24, /* # # */
0x34, /* ## # */
0x2c, /* # ## */
0x24, /* # # */
0x08, /* # */
0x36, /* ## ## */
0x41, /* # # */
0x00, /* */
0x7f, /* ####### */
0x41, /* # # */
0x36, /* ## ## */
0x08, /* # */
0x08, /* # */
0x04, /* # */
0x08, /* # */
0x04, /* # */
0x3c, /* #### */
0x02, /* # */
0x2a, /* # # # */
0x14, /* # # */
0x19, /* ## # */
0x24, /* # # */
0x24, /* # # */
0x39, /* ### # */
0x19, /* ## # */
0x24, /* # # */
0x24, /* # # */
0x19, /* ## # */
0x1d, /* ### # */
0x20, /* # */
0x20, /* # */
0x3d, /* #### # */
};
font font_uni53 = {8, fontIndex_uni53, fontData_uni53, ' ', '~', '.', 1};

8
scrolltext/font_uni53.h

@ -0,0 +1,8 @@
#ifndef FONT_UNI53_H_
#define FONT_UNI53_H_
#include "font.h"
extern font font_uni53;
#endif /* FONT_UNI53_H_ */

6
scrolltext/scrolltext.h

@ -0,0 +1,6 @@
#ifndef SCROLLTEXT_H_
#define SCROLLTEXT_H_
void scrolltext(char *str);
#endif /* SCROLLTEXT_H_ */

578
scrolltext/scrolltext3.c

@ -0,0 +1,578 @@
#define SCROLLTEXT_C
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include "../config.h"
#include "scrolltext.h"
#ifdef AVR
# include "../borg_hw/borg_hw.h"
#endif
#include "../pixel.h"
#include "../util.h"
#include "font_arial8.h"
#include "font_small6.h"
#include "font_uni53.h"
#define MAX_FONTS 1
font fonts[MAX_FONTS];
#define MAX_SPECIALCOLORS 3
unsigned char PROGMEM colorTable[MAX_SPECIALCOLORS*NUM_ROWS] = {1, 1, 2, 3, 3, 2, 1, 1,
3, 3, 2, 1, 1, 2, 3, 3,
3, 3, 2, 2, 3, 3, 2, 2
};
char default_text[] PROGMEM = SCROLLTEXT_TEXT;
char scrolltext_text[SCROLLTEXT_BUFFER_SIZE];
/* Konzept
=======
Text wird in Token unterteilt, jeder Token bekommt einen Command-String.
z.B.
#b</#LABOR
Es werden die Zeiger aus dem Eingabestring direkt übernommen, mit Stringlen.
Wenn der Command abgearbeitet ist wird automatisch das nächste Token eingelesen.
*/
unsigned char (*text_pixmap)[NUM_ROWS][LINEBYTES];
void text_setpixel(pixel p, unsigned char value ){
if(value){
(*text_pixmap)[p.y%NUM_ROWS][p.x/8] |= shl_table[p.x%8];
}
}
void clear_text_pixmap(unsigned char value){
unsigned char y, z;
for(y=0;y<NUM_ROWS;y++){
for(z=0;z<LINEBYTES;z++){
(*text_pixmap)[y][z] = 0;
}
}
}
void update_pixmap(){
unsigned char x, y, z;
for(x=0;x<NUMPLANE;x++){
for(y=0;y<NUM_ROWS;y++){
for(z=0;z<LINEBYTES;z++){
pixmap[x][y][z] = (*text_pixmap)[y][z];
}
}
}
}
enum waitfor_e{
wait_new,
wait_posy,
wait_posx,
wait_out,
wait_timer,
wait_col_l,
wait_col_r
};
#define DIRECTION_RIGHT 0x01
#define DIRECTION_DOWN 0x02
struct blob_t_struct;
typedef struct blob_t_struct{
struct blob_t_struct * next, * last;
char *str;
char *commands;
enum waitfor_e waitfor;
int sizex;
char sizey;
int posx;
char posy;
int tox;
char toy;
unsigned char delayx, delayx_rld;
unsigned char delayy, delayy_rld;
unsigned char delayb, delayb_rld;
unsigned char visible;
unsigned char direction;
unsigned int timer;
const unsigned int* fontIndex;
const unsigned char* fontData;
unsigned char font_storebytes;/*bytes per char*/
unsigned char space;
}blob_t;
/*
void showBlob(blob_t * blob){
unsigned char * str = blob->str;
unsigned char tmp[200], x=0;
while(*str){
tmp[x++] = (*str++) + ' ' -1;
}
tmp[x] = 0;
printf("this:\t%x\n",blob);
printf("last:\t%x\n",blob->last);
printf("next:\t%x\n",blob->next);
printf("str:\t%s\n",tmp);
printf("cmd:\t%s\n",blob->commands);
printf("sizex\t%d\n",blob->sizex);
printf("posx\t%d\n",blob->posx);
printf("posy\t%d\n",blob->posy);
printf("tox\t%d\n",blob->tox);
printf("toy\t%d\n",blob->toy);
printf("delayy_rld\t%d\n",blob->delayx_rld);
printf("delayx_rld\t%d\n",blob->delayy_rld);
printf("timer\t%d\n",blob->timer);
printf("\n");
}
*/
#define PW(a) pgm_read_word(&(a))
#define PB(a) pgm_read_byte(&(a))
unsigned int getLen(blob_t *blob) {
unsigned char glyph;
unsigned int strLen = 0;
unsigned char * str = (unsigned char*)blob->str;
uint8_t space = blob->space * blob->font_storebytes;
while ((glyph = *str++)) {
glyph -= 1;
strLen += PW(blob->fontIndex[glyph+1]) - PW(blob->fontIndex[glyph]);
strLen += space;
}
return strLen/blob->font_storebytes;
}
unsigned int getnum(blob_t * blob){
unsigned int num=0;
unsigned char gotnum = 0;
while( (*blob->commands >= '0') && (*blob->commands <='9') ){
gotnum = 1;
num *= 10;
num += *blob->commands - '0';
blob->commands++;
}
if(gotnum){
return num;
}else{
return 0xffff;
}
}
unsigned char blobNextCommand(blob_t * blob){
unsigned int tmp;
unsigned char retval = 0;
while(*blob->commands != 0){
switch (*blob->commands++){
case '<':
blob->direction &= ~DIRECTION_RIGHT;
if((tmp = getnum(blob)) != 0xFFFF){
blob->delayx_rld = tmp;
}else{
blob->delayx_rld = SCROLL_X_SPEED;
}
blob->delayx = blob->delayx_rld;
break;
case '>':
blob->direction |= DIRECTION_RIGHT;
if((tmp = getnum(blob)) != 0xFFFF){
blob->delayx_rld = tmp;
}else{
blob->delayx_rld = SCROLL_X_SPEED;
}
blob->delayx = blob->delayx_rld;
break;
case 'd':
blob->direction |= DIRECTION_DOWN;
if((tmp = getnum(blob)) != 0xFFFF){
blob->delayy_rld = tmp;
}else{
blob->delayy_rld = SCROLL_Y_SPEED;
}
blob->delayy = blob->delayy_rld;
break;
case 'u':
blob->direction &= ~DIRECTION_DOWN;
if((tmp = getnum(blob)) != 0xFFFF){
blob->delayy_rld = tmp;
}else{
blob->delayy_rld = SCROLL_Y_SPEED;
}
blob->delayy = blob->delayy_rld;
break;
case 'x'://Place string at this x Position
if((tmp = getnum(blob)) != 0xFFFF){
blob->posx = tmp;
}else{
blob->posx = NUM_COLS/2 + blob->sizex/2;
}
break;
case 'y'://Place string at this y Position
if((tmp = getnum(blob)) != 0xFFFF){
blob->posy = tmp - blob->sizey;
}
break;
case 'b'://blink blob
if((tmp = getnum(blob)) != 0xFFFF){
blob->delayb_rld = tmp;
}else{
blob->delayb_rld = 50;
}
blob->delayb = blob->delayb_rld;
break;
case '|':
if((tmp = getnum(blob)) != 0xFFFF){
blob->tox = tmp;
}else{
blob->tox = (NUM_COLS - 2 + blob->sizex)/2;
}
blob->waitfor = wait_posx;
return retval;
break;
case '-':
if((tmp = getnum(blob)) != 0xFFFF){
blob->toy = tmp;
}else{
blob->toy = (NUM_ROWS-blob->sizey) / 2;
}
blob->waitfor = wait_posy;
return retval;
break;
case 'p':
blob->delayx_rld = 0;
blob->delayy_rld = 0;
if((tmp = getnum(blob)) != 0xFFFF){
blob->timer = tmp*64;
}else{
blob->timer = 30*64;
}
blob->waitfor = wait_timer;
return retval;
break;
case '/':
blob->waitfor = wait_out;
return retval;
break;
case ';':
blob->waitfor = wait_col_l;
return (retval);
break;
case ':':
blob->waitfor = wait_col_r;
return (retval);
break;
case '+':
retval = 2;
break;
}
}
return 1;//this blob is finished, and can be deleted.
}
blob_t * setupBlob(char * str){
/*char * strtok_r ( char * string, const char * delim, char ** last)*/
static unsigned char chop_cnt;
static char *last; static char delim[] = "#";
static char *lastcommands;
unsigned int tmp;
if(str){
chop_cnt = 0;
}
blob_t *blob = malloc(sizeof (blob_t));
if(!chop_cnt){
blob->commands = strtok_r (str, delim, &last);
if( blob->commands == 0) goto fail;
if((tmp = getnum(blob)) != 0xFFFF){
chop_cnt = tmp;
lastcommands = blob->commands;
}
}
if(chop_cnt){
chop_cnt--;
blob->commands = lastcommands;
}
blob->str = strtok_r (0, delim, &last);
if ( blob->str == 0) goto fail;
blob->fontIndex = fonts[0].fontIndex;
blob->fontData = fonts[0].fontData;
blob->font_storebytes = fonts[0].storebytes;
unsigned char tmp1, *strg = (unsigned char*)blob->str;
unsigned char glyph_beg = fonts[0].glyph_beg;
unsigned char glyph_end = fonts[0].glyph_end;
//translate the string: subtract 1 to get offset in Table
while((tmp1 = *strg)){
if((tmp1>=glyph_beg) && (tmp1<glyph_end)){
*strg = 1 + tmp1 - glyph_beg;
}else{
*strg = 1;
}
strg++;
}
blob->space = 1;
blob->sizey = fonts[0].fontHeight;
blob->sizex = getLen(blob);
if(*blob->commands == '<'){
blob->posx = 0;
blob->posy = (NUM_ROWS-blob->sizey)/2;
}else if(*blob->commands == '>'){
blob->posx = NUM_COLS+blob->sizex;
blob->posy = (NUM_ROWS-blob->sizey)/2;
}else if(*blob->commands == 'd'){
blob->posy = -blob->sizey;
blob->posx = (NUM_COLS - 2 + blob->sizex)/2;
}else if(*blob->commands == 'u'){
blob->posy = blob->sizey;
blob->posx = (NUM_COLS - 2 + blob->sizex)/2;
}
blob->delayx_rld = 0;
blob->delayy_rld = 0;
blob->delayb_rld = 0;
blob->waitfor = wait_new;
return blob;
fail:
free(blob);
return 0;//no more blobs to parse
}
unsigned char updateBlob(blob_t * blob){
if(blob->delayx_rld && (!(blob->delayx--))){
blob->delayx = blob->delayx_rld;
(blob->direction & DIRECTION_RIGHT)?blob->posx--:blob->posx++;
}
if(blob->delayy_rld && (!(blob->delayy--))){
blob->delayy = blob->delayy_rld;
(blob->direction & DIRECTION_DOWN)?blob->posy++:blob->posy--;
}
if(blob->delayb_rld){
if(!(blob->delayb--)){
blob->delayb = blob->delayb_rld;
blob->visible ^= 1;
}
}else{
blob->visible = 1;
}
unsigned char done=0;
switch (blob->waitfor){
case wait_posy:
if (blob->posy == blob->toy)done = 1;
break;
case wait_posx:
if (blob->posx == blob->tox)done = 1;
break;
case wait_out:
if((blob->posx - blob->sizex) > NUM_COLS || blob->posx < 0) done = 1;
if((blob->posy) > NUM_ROWS || (blob->posy + blob->sizey) <0 ) done = 1;
break;
case wait_timer:
if(0 == blob->timer--){
done = 1;
}
break;
case wait_col_l:
if(blob->last){
if((blob->last->posx - blob->last->sizex) == blob->posx){
done=1;
}
}else{
done = 1;
}
break;
case wait_col_r:
if(blob->next){
if(blob->next->posx == (blob->posx - blob->sizex)){
done=1;
}
}else{
done = 1;
}
break;
default:
done = 1;
break;
}
if(done){
return (blobNextCommand(blob));
}
return 0;
}
void drawBlob(blob_t *blob) {
char x, y;
unsigned char byte=0, glyph, storebytes;
unsigned int charPos, charEnd;
unsigned int posx; unsigned char posy, toy;
if(!blob->visible) return;
unsigned char * str = (unsigned char*)blob->str;
posx = blob->posx;
posy = blob->posy;
toy = posy + blob->sizey;
storebytes = blob->font_storebytes;
glyph = (*blob->str)-1;
charPos = PW(blob->fontIndex[glyph]);
charEnd = PW(blob->fontIndex[glyph+1]);
while (posx >= NUM_COLS) {
charPos += storebytes;
if (charPos < charEnd) {
posx--;
}else{
posx -= blob->space + 1;
if (!(glyph = *++str)) return;
glyph -= 1;
charPos = PW(blob->fontIndex[glyph]);
charEnd = PW(blob->fontIndex[glyph+1]);
}
}
for (x = posx; x >= 0; x-- ) {
unsigned char mask = 0;
unsigned int datpos;
datpos = charPos;
for (y = posy; (y < NUM_ROWS) && (y < toy); y++) {
if((mask<<=1) == 0){
mask = 0x01;
byte = PB(blob->fontData[datpos++]);
}
if ((byte & mask) && y >= 0 ) {
text_setpixel((pixel){x, y},1);
}
}
charPos += storebytes;
if (charPos < charEnd) {
}else{
x -= blob->space;
if (!(glyph = *++str)) return;
glyph -= 1;
charPos = PW(blob->fontIndex[glyph]);
charEnd = PW(blob->fontIndex[glyph+1]);
}
}
}
extern jmp_buf newmode_jmpbuf;
void scrolltext(char *str) {
jmp_buf tmp_jmpbuf;
char tmp_str[SCROLLTEXT_BUFFER_SIZE];
int ljmp_retval;
fonts[0] = SCROLLTEXT_FONT;
text_pixmap = malloc(NUM_ROWS * LINEBYTES);
if(scrolltext_text[0] == 0){
strcpy_P(scrolltext_text, default_text);
}
memcpy(tmp_str, str, SCROLLTEXT_BUFFER_SIZE);
blob_t *startblob=0, *aktblob, *nextblob=0;
memcpy (tmp_jmpbuf, newmode_jmpbuf, sizeof(jmp_buf));
if((ljmp_retval = setjmp(newmode_jmpbuf))){
while(startblob){
aktblob = startblob;
startblob = aktblob->next;
free(aktblob);
}
free(text_pixmap);
memcpy (newmode_jmpbuf, tmp_jmpbuf, sizeof(jmp_buf));
longjmp(newmode_jmpbuf, ljmp_retval);
}
if (!(startblob = setupBlob(tmp_str))){
goto exit;
}
unsigned char retval;
do{
startblob->next = 0;
startblob->last = 0;
while(startblob){
aktblob = startblob;
while(aktblob){
retval = updateBlob(aktblob);
if(!retval){
nextblob = aktblob->next;
}else if(retval == 1){
if(aktblob == startblob){
startblob = aktblob->next;
}else{
aktblob->last->next = aktblob->next;
}
if(aktblob->next){
aktblob->next->last = aktblob->last;
}
nextblob = aktblob->next;
free(aktblob);
}else if(retval == 2){
blob_t * newblob = setupBlob(0);
if (newblob){
newblob->last = aktblob;
newblob->next = aktblob->next;
if(aktblob->next){
aktblob->next->last = newblob;
}
aktblob->next = newblob;
}
nextblob = aktblob->next;
}
aktblob = nextblob;
}
aktblob = startblob;
clear_text_pixmap(0);
while(aktblob){
drawBlob(aktblob);
aktblob = aktblob->next;
}
update_pixmap();
wait(2);
};
startblob = setupBlob(0);
//showBlob(startblob);
}while(startblob);
exit:
free(text_pixmap);
memcpy (newmode_jmpbuf, tmp_jmpbuf, sizeof(jmp_buf));
}

111
simulator/Makefile

@ -0,0 +1,111 @@
PRG = borgSim
OPTIMIZE = -O0
LIBS = -lglut -lpthread -lGL -lGLU
CC = gcc
LD = ld
override CFLAGS = -g -Wall -pedantic -std=c99 $(OPTIMIZE)
$(DEFS)
override LDFLAGS = -Wl,-Map,$(PRG).map
OBJ = breakpoint.o font_arial8.o font_small6.o font_uni53.o invader_draw.o \
invader_init.o invader_proc.o invaders2.o joystick.o main.o menu.o pixel.o \
programm.o scrolltext3.o snake.o trackball.o util.o tetris/input.o \
tetris/logic.o tetris/piece.o tetris/playfield.o tetris/view.o prng.o \
memxor_c.o noekeon.o stonefly.o
all: $(PRG)
$(PRG): $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(OBJ) -o $@
clean:
rm -rf $(OBJ) $(PRG) $(PRG).map
breakpoint.o: breakpoint.c pixel.h util.h config.h
$(CC) $(CFLAGS) -c -o breakpoint.o breakpoint.c
font_arial8.o: font_arial8.c font.h
$(CC) $(CFLAGS) -c -o font_arial8.o font_arial8.c
font_small6.o: font_small6.c font.h
$(CC) $(CFLAGS) -c -o font_small6.o font_small6.c
font_uni53.o: font_uni53.c font.h
$(CC) $(CFLAGS) -c -o font_uni53.o font_uni53.c
invader_draw.o: invader_draw.c invaders2.h pixel.h util.h config.h \
scrolltext.h joystick.h
$(CC) $(CFLAGS) -c -o invader_draw.o invader_draw.c
invader_init.o: invader_init.c invaders2.h pixel.h util.h config.h \
scrolltext.h joystick.h
$(CC) $(CFLAGS) -c -o invader_init.o invader_init.c
invader_proc.o: invader_proc.c invaders2.h pixel.h util.h config.h \
scrolltext.h joystick.h
$(CC) $(CFLAGS) -c -o invader_proc.o invader_proc.c
invaders2.o: invaders2.c util.h invaders2.h pixel.h config.h scrolltext.h \
joystick.h
$(CC) $(CFLAGS) -c -o invaders2.o invaders2.c
joystick.o: joystick.c joystick.h
$(CC) $(CFLAGS) -c -o joystick.o joystick.c
main.o: main.c config.h pixel.h util.h programm.h menu.h tetris/logic.h \
tetris/piece.h trackball.h snake.h scrolltext.h
$(CC) $(CFLAGS) -c -o main.o main.c
menu.o: menu.c menu.h config.h util.h pixel.h joystick.h snake.h \
tetris/logic.h tetris/piece.h invaders2.h scrolltext.h
$(CC) $(CFLAGS) -c -o menu.o menu.c
pixel.o: pixel.c pixel.h util.h config.h
$(CC) $(CFLAGS) -c -o pixel.o pixel.c
programm.o: programm.c pixel.h util.h config.h programm.h joystick.h
$(CC) $(CFLAGS) -c -o programm.o programm.c
scrolltext3.o: scrolltext3.c config.h scrolltext.h pixel.h util.h \
font_arial8.h font.h font_small6.h font_uni53.h
$(CC) $(CFLAGS) -c -o scrolltext3.o scrolltext3.c
snake.o: snake.c pixel.h util.h config.h joystick.h
$(CC) $(CFLAGS) -c -o snake.o snake.c
trackball.o: trackball.c trackball.h
$(CC) $(CFLAGS) -c -o trackball.o trackball.c
util.o: util.c joystick.h
$(CC) $(CFLAGS) -c -o util.o util.c
noekeon.o: noekeon.c noekeon.h memxor.h
$(CC) $(CFLAGS) -c -o $@ $<
memxor_c.o: memxor_c.c memxor.h
$(CC) $(CFLAGS) -c -o $@ $<
prng.o: prng.c prng.h noekeon.h memxor.h
$(CC) $(CFLAGS) -c -o $@ $<
tetris/input.o: tetris/input.c joystick.h util.h tetris/input.h
$(CC) $(CFLAGS) -c -o tetris/input.o tetris/input.c
logic.o: tetris/logic.c tetris/logic.h tetris/piece.h tetris/playfield.h \
tetris/view.h tetris/input.h prng.h ../borg-base/prng.h
$(CC) $(CFLAGS) -c -o tetris/logic.o tetris/logic.c
tetris/piece.o: tetris/piece.c tetris/piece.h
$(CC) $(CFLAGS) -c -o tetris/piece.o tetris/piece.c
tetris/playfield.o: tetris/playfield.c tetris/playfield.h tetris/piece.h
$(CC) $(CFLAGS) -c -o tetris/playfield.o tetris/playfield.c
tetris/view.o: tetris/view.c config.h pixel.h util.h scrolltext.h \
tetris/logic.h tetris/piece.h tetris/playfield.h tetris/view.h
$(CC) $(CFLAGS) -c -o tetris/view.o tetris/view.c
stonefly.o: stonefly.h stonefly.c pixel.h util.h config.h prng.h \
../borg-base/prng.h tetris/piece.h
$(CC) $(CFLAGS) -c -o stonefly.o stonefly.c

102
simulator/Makefile.osx

@ -0,0 +1,102 @@
PRG = borgSim
APP = $(PRG).app/Contents/MacOS/$(PRG)
OPTIMIZE = -O2
LIBS = -lpthread -framework Carbon -framework GLUT -framework OpenGL -framework Foundation -framework AppKit
CC = gcc
LD = ld
override CFLAGS = -g -Wall -pedantic -std=c99 $(OPTIMIZE) -DOSX_
$(DEFS)
override LDFLAGS = -Wl --prebind
OBJ = breakpoint.o font_arial8.o font_small6.o font_uni53.o invader_draw.o \
invader_init.o invader_proc.o invaders2.o joystick.o main.o menu.o pixel.o \
programm.o scrolltext3.o snake.o trackball.o util.o tetris/input.o \
tetris/logic.o tetris/piece.o tetris/playfield.o tetris/view.o
all: Makefile.osx $(APP)
$(APP): $(OBJ)
test -d $(PRG).app/Contents/MacOS/ || mkdir -p $(PRG).app/Contents/MacOS/
test -d $(PRG).app/Contents/Resources/ || mkdir -p $(PRG).app/Resources/
test $(PRG).app/Contents/Rescources/borg3d.icns || cp -f borg3d.icns $(PRG).app/Contents/Rescources/
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(OBJ) -o $@
clean:
rm -rf $(OBJ) $(PRG) $(PRG).app/
breakpoint.o: breakpoint.c pixel.h util.h config.h
$(CC) $(CFLAGS) -c -o breakpoint.o breakpoint.c
font_arial8.o: font_arial8.c font.h
$(CC) $(CFLAGS) -c -o font_arial8.o font_arial8.c
font_small6.o: font_small6.c font.h
$(CC) $(CFLAGS) -c -o font_small6.o font_small6.c
font_uni53.o: font_uni53.c font.h
$(CC) $(CFLAGS) -c -o font_uni53.o font_uni53.c
invader_draw.o: invader_draw.c invaders2.h pixel.h util.h config.h \
scrolltext.h joystick.h
$(CC) $(CFLAGS) -c -o invader_draw.o invader_draw.c
invader_init.o: invader_init.c invaders2.h pixel.h util.h config.h \
scrolltext.h joystick.h
$(CC) $(CFLAGS) -c -o invader_init.o invader_init.c
invader_proc.o: invader_proc.c invaders2.h pixel.h util.h config.h \
scrolltext.h joystick.h
$(CC) $(CFLAGS) -c -o invader_proc.o invader_proc.c
invaders2.o: invaders2.c util.h invaders2.h pixel.h config.h scrolltext.h \
joystick.h
$(CC) $(CFLAGS) -c -o invaders2.o invaders2.c
joystick.o: joystick.c joystick.h
$(CC) $(CFLAGS) -c -o joystick.o joystick.c
main.o: main.c config.h pixel.h util.h programm.h menu.h tetris/logic.h \
tetris/piece.h trackball.h snake.h scrolltext.h
$(CC) $(CFLAGS) -c -o main.o main.c
menu.o: menu.c menu.h config.h util.h pixel.h joystick.h snake.h \
tetris/logic.h tetris/piece.h invaders2.h scrolltext.h
$(CC) $(CFLAGS) -c -o menu.o menu.c
pixel.o: pixel.c pixel.h util.h config.h
$(CC) $(CFLAGS) -c -o pixel.o pixel.c
programm.o: programm.c pixel.h util.h config.h programm.h joystick.h
$(CC) $(CFLAGS) -c -o programm.o programm.c
scrolltext3.o: scrolltext3.c config.h scrolltext.h pixel.h util.h \
font_arial8.h font.h font_small6.h font_uni53.h
$(CC) $(CFLAGS) -c -o scrolltext3.o scrolltext3.c
snake.o: snake.c pixel.h util.h config.h joystick.h
$(CC) $(CFLAGS) -c -o snake.o snake.c
trackball.o: trackball.c trackball.h
$(CC) $(CFLAGS) -c -o trackball.o trackball.c
util.o: util.c joystick.h
$(CC) $(CFLAGS) -c -o util.o util.c
tetris/input.o: tetris/input.c joystick.h util.h tetris/input.h
$(CC) $(CFLAGS) -c -o tetris/input.o tetris/input.c
tetris/logic.o: tetris/logic.c tetris/logic.h tetris/piece.h \
tetris/playfield.h tetris/view.h tetris/input.h
$(CC) $(CFLAGS) -c -o tetris/logic.o tetris/logic.c
tetris/piece.o: tetris/piece.c tetris/piece.h
$(CC) $(CFLAGS) -c -o tetris/piece.o tetris/piece.c
tetris/playfield.o: tetris/playfield.c tetris/playfield.h tetris/piece.h
$(CC) $(CFLAGS) -c -o tetris/playfield.o tetris/playfield.c
tetris/view.o: tetris/view.c config.h pixel.h util.h scrolltext.h \
tetris/logic.h tetris/piece.h tetris/playfield.h tetris/view.h
$(CC) $(CFLAGS) -c -o tetris/view.o tetris/view.c

309
simulator/main.c

@ -0,0 +1,309 @@
#ifdef _WIN32
# include <GL/glut.h>
# include <windows.h>
# include <process.h>
# define pthread_t int
#else
# ifdef OSX_
# include <GLUT/glut.h>
# else
# include <GL/glut.h>
# endif
# include <pthread.h> // for threads in linux
# include <stdlib.h>
# include <sys/time.h>
# include <sys/types.h>
# include <unistd.h>
#endif
#include <stdio.h>
#include <setjmp.h>
#include "config.h"
#include "pixel.h"
#include "programm.h"
#include "menu.h"
#include "tetris/logic.h"
#include "trackball.h"
#include "snake.h"
#include "stonefly.h"
#include "scrolltext.h"
unsigned char fakeport;
jmp_buf newmode_jmpbuf;
volatile unsigned char oldMode, oldOldmode, mode;
extern unsigned char waitForFire;
int WindWidth, WindHeight;
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
unsigned char joystick;
float view_rotx = 0, view_roty = 0, view_rotz = 0;
int win;
pthread_t simthread;
GLUquadric* quad;
void drawLED(int color, float pos_x, float pos_y, float pos_z) {
glPushMatrix();
glTranslatef(pos_x, pos_y, pos_z);
glCallList(color);
glPopMatrix();
}
void display(void){
int x, y, z, level, color;
tbReshape(WindWidth, WindHeight);
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glTranslatef(NUM_COLS*2., 0., NUM_ROWS*2.);
tbMatrix();
glRotatef(view_rotx, 1.0, 0.0, 0.0);
glRotatef(view_roty, 0.0, 1.0, 0.0);
glRotatef(view_rotz, 0.0, 0.0, 1.0);
glTranslatef(-NUM_COLS*2, 0., -NUM_ROWS*2.);
for (x = 0; x < 1; x++) {
for (y = 0; y < NUM_COLS; y++) {
for (z = 0; z < NUM_ROWS; z++) {
color = 0;
for (level = 0; level < NUMPLANE; level++) {
if (pixmap[level][z%NUM_ROWS][y/8] & (1 << y % 8)) {
color = level+1;
}
}
drawLED(color, (float)y*4.0,
(float)x*4.0,
(float)(NUM_ROWS-1-z)*4.0);
}
}
}
glPopMatrix();
glutSwapBuffers();
#ifdef _WIN32
Sleep(10);
#else
usleep(20000);
#endif
joystick = 255;
}
void keyboard(unsigned char key, int x, int y){
switch (key) {
case 'q': printf("Quit\n");
glutDestroyWindow(win);
exit(0);
break;
case ' ':
fakeport |= 0x01;
break;
case 'a':
fakeport |= 0x02;
break;
case 'd':
fakeport |= 0x04;
break;
case 's':
fakeport |= 0x08;
break;
case 'w':
fakeport |= 0x10;
break;
}
}
void keyboardup(unsigned char key, int x, int y){
switch (key) {
case ' ':
fakeport &= ~0x01;
break;
case 'a':
fakeport &= ~0x02;
break;
case 'd':
fakeport &= ~0x04;
break;
case 's':
fakeport &= ~0x08;
break;
case 'w':
fakeport &= ~0x10;
break;
}
}
void mouse(int button, int state, int x, int y)
{
tbMouse(button, state, x, y);
}
void motion(int x, int y)
{
tbMotion(x, y);
}
void reshape(int width, int height)
{
tbReshape(width, height);
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (float)WindWidth/(float)WindWidth, 5., 1000.);
gluLookAt(NUM_ROWS*2., NUM_ROWS*2.+50., NUM_COLS*2.,
NUM_ROWS*2., NUM_ROWS*2., NUM_COLS*2.,
0.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
WindWidth = width;
WindHeight = height;
}
/* change view angle */
static void special(int k, int x, int y) {
switch (k) {
case GLUT_KEY_UP:
view_rotx += 5.0;
break;
case GLUT_KEY_DOWN:
view_rotx -= 5.0;
break;
case GLUT_KEY_LEFT:
view_rotz += 5.0;
break;
case GLUT_KEY_RIGHT:
view_rotz -= 5.0;
break;
default:
return;
}
glutPostRedisplay();
}
/*
void timf(int value) {
glutPostRedisplay();
glutTimerFunc(1, timf, 0);
}*/
void *display_loop(void * unused) {
unsigned char mode;;;
mode = setjmp(newmode_jmpbuf);
oldOldmode = oldMode;
waitForFire = 1;
scrolltext("</#Scrolltext3 Test");
for(;;){
oldMode = mode;
switch(mode++) {
case 1:
stonefly();
break;
case 2:
breakpoint();
break;
case 3:
schwarzesLoch();
break;
case 4:
scrolltext("</#Scrolltext3 Test");
break;
case 5:
spirale(20);
break;
case 6:
joern1();
break;
case 7:
snake();
break;
case 8:
schachbrett(20);
break;
case 9:
feuer();
break;
case 10:
matrix();
break;
case 31:
fadein();
break;
case 32:
test1();
break;
case 43:
menu();
mode = oldOldmode;
default:
break;
}
}
}
int main(int argc, char **argv){
WindHeight = 700;
WindWidth = 700;
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(WindHeight, WindWidth);
win = glutCreateWindow("16x16 Borg Simulator");
// callback
//glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutIdleFunc(display);
glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF);
glutKeyboardFunc(keyboard);
glutKeyboardUpFunc(keyboardup);
glutSpecialFunc(special);
glutMouseFunc(mouse);
glutMotionFunc(motion);
// clearcolor & main loop
glClearColor(0,0,0,1.0);
gluPerspective(60.0, (float)WindWidth/(float)WindWidth, 5., 1000.);
gluLookAt(NUM_COLS*2., NUM_COLS*2.+50., NUM_ROWS*2.,
NUM_COLS*2., NUM_COLS*2., NUM_ROWS*2.,
0.0, 0.0, 1.0);
// init Call List for LED
quad = gluNewQuadric();
glNewList(0, GL_COMPILE);
glColor4f(0.8, 0.0, 0.0, 1.);
gluSphere(quad, 1.0, 12, 12);
glEndList();
glNewList(1, GL_COMPILE);
glColor4f(0.5, 0.0, 0.0, 1.);
gluSphere(quad, 1.4, 12, 12);
glEndList();
glNewList(2, GL_COMPILE);
glColor4f(0.7, 0.0, 0.0, 1.);
gluSphere(quad, 1.55, 12, 12);
glEndList();
glNewList(3, GL_COMPILE);
glColor4f(1.00, 0.0, 0.0, 1.);
gluSphere(quad, 1.7, 12, 12);
glEndList();
tbInit(GLUT_LEFT_BUTTON);
tbAnimate(GL_FALSE);
// start display_loop thread
#ifdef _WIN32
_beginthread((void (*)(void*))display_loop, 0, NULL);
#else
pthread_create(&simthread, NULL, display_loop, NULL);
#endif
//glutTimerFunc(40, timf, 0); // Set up timer for 40ms, about 25 fps
glutMainLoop();
return 0;
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save