From 5aabef4c9d22f34c27101970b4bdc812277e3b0c Mon Sep 17 00:00:00 2001 From: Tyrolyean Date: Fri, 27 Mar 2020 15:10:31 +0100 Subject: [PATCH] Added files Signed-off-by: Tyrolyean --- .gitignore | 53 +++++ Makefile | 70 +++++++ include/16550.h | 54 +++++ include/avr.h | 49 +++++ include/dac.h | 45 ++++ include/game.h | 51 +++++ include/interrupt.h | 22 ++ include/sound.h | 47 +++++ include/structures.h | 81 ++++++++ src/16550.c | 126 ++++++++++++ src/dac.c | 207 +++++++++++++++++++ src/game.c | 378 ++++++++++++++++++++++++++++++++++ src/interrupt.c | 36 ++++ src/main.c | 112 ++++++++++ src/sound.c | 261 +++++++++++++++++++++++ src/structures.c | 480 +++++++++++++++++++++++++++++++++++++++++++ 16 files changed, 2072 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 include/16550.h create mode 100644 include/avr.h create mode 100644 include/dac.h create mode 100644 include/game.h create mode 100644 include/interrupt.h create mode 100644 include/sound.h create mode 100644 include/structures.h create mode 100644 src/16550.c create mode 100644 src/dac.c create mode 100644 src/game.c create mode 100644 src/interrupt.c create mode 100644 src/main.c create mode 100644 src/sound.c create mode 100644 src/structures.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dab799c --- /dev/null +++ b/.gitignore @@ -0,0 +1,53 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cd51ad7 --- /dev/null +++ b/Makefile @@ -0,0 +1,70 @@ +MKDIR_P := mkdir -p +CP := cp +MV := mv +CC := avr-gcc +CCC := avr-g++ +RM_RF = rm -rf +OCPY := avr-objcopy +AVRDUDE := avrdude +PORT := /dev/ttyACM0 +#PORT := usb +#BOARD := atmega328p +BOARD := atmega2560 +#PROGRAMMER := arduino +PROGRAMMER := usbasp +#PROGBOARD := m328p +PROGBOARD := m2560 +BAUD_RATE_PROG := 115200 +FLASH_CMD := $(AVRDUDE) -b $(BAUD_RATE_PROG) -p $(PROGBOARD) -D -P $(PORT) -c $(PROGRAMMER) +AVRSIZE := avr-size +AVRSIZE_FLAGS := -C --mcu=$(PROGBOARD) + +# directories +CWD := $(realpath .) +BINDIR := $(CWD)/bin +BUILDDIR := $(CWD)/build +SRCDIR := $(CWD)/src +INCLUDEDIR := $(CWD)/include + +# flas +CFLAGS := -mmcu=$(BOARD) -Os -I$(INCLUDEDIR) -Wall -Wextra +LDFLAGS := -mmcu=$(BOARD) + +# target files +DIRS_TARGET := $(BINDIR) $(BUILDDIR) +TARGET := $(BINDIR)/mc.hex +TARGET_ELF := $(BINDIR)/mc.elf +SRCFILES := $(wildcard $(SRCDIR)/*.c) +OBJFILES := $(patsubst $(SRCDIR)/%.c,$(BUILDDIR)/%.o,$(SRCFILES)) + +# fancy targets +all: directories $(TARGET) + +directories: $(DIRS_TARGET) + +# less fancy targets + +$(DIRS_TARGET): + $(MKDIR_P) $@ + +$(TARGET) : $(TARGET_ELF) + $(OCPY) -O ihex -j .text -j .data $^ $@ + +$(TARGET_ELF): $(OBJFILES) + $(CC) $(LDFLAGS) -o $@ $^ + $(AVRSIZE) $(AVRSIZE_FLAGS) $@ + +$(BUILDDIR)/%.o: $(SRCDIR)/%.c + $(CC) $(CFLAGS) -c -o $@ $< + +flash: $(TARGET) + # For atmega 2560 + $(FLASH_CMD) -e -U hfuse:w:0xD9:m -U lfuse:w:0xDF:m -U efuse:w:0xFF:m -U flash:w:$^:i -U efuse:w:0xfa:m + # For atmega 328p: + #$(FLASH_CMD) -e -U hfuse:w:0xD9:m -U efuse:w:0xFF:m -U lfuse:w:0xDF:m -U flash:w:$^:i -U efuse:w:0xfd:m + # If unknown or no fuse bits available over programmer + #$(FLASH_CMD) -U flash:w:$^:i + $(FLASH_CMD) -U flash:v:$^:i + +clean: + $(RM_RF) $(DIRS_TARGET) diff --git a/include/16550.h b/include/16550.h new file mode 100644 index 0000000..acc6fe8 --- /dev/null +++ b/include/16550.h @@ -0,0 +1,54 @@ +/* Copyright © 2020 tyrolyean + * + * 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 . + */ + +#ifndef _16550_H +#define _16550_H + +#include +#include + +/* Registers in the 16550 UART */ + +#define UART_REG_DLLS 0 +#define UART_REG_DLMS 1 +#define UART_REG_TXRX 0 +#define UART_REG_IER 1 +#define UART_REG_IIR 2 +#define UART_REG_LCR 3 +#define UART_REG_MCR 4 +#define UART_REG_LSR 5 +#define UART_REG_MSR 6 +#define UART_REG_SCR 7 + +/* The printf function in the background performs automatic column wrapping by + * finding the first space character within 10 characters ofthe display columns + * and replacingit with a newline character + */ +#define DISPLAY_COLUMNS 80 + +void init_16550(); +void write_to_uart(uint8_t addr, uint8_t data); +uint8_t read_from_uart(uint8_t addr); + +void init_uart(); + +int println(const char* output,...); +int putchar_16550(char var, FILE *stream); +void writechar_16550(char var); + +void routine_uart(); + +#endif diff --git a/include/avr.h b/include/avr.h new file mode 100644 index 0000000..586d36f --- /dev/null +++ b/include/avr.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2020 tyrolyean + * + * 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 . + */ + +#ifndef _AVR_H_TEXT +#define _AVR_H_TEXT + + + +#define F_CPU 16000000UL +#include + +/* Shift values for the peripherials on the control bus PORTL */ + +#define MR_SHIFT 0 +#define WR_SHIFT 1 +#define RD_SHIFT 2 +#define CS_UART_SHIFT 3 +#define CS_DAC_SHIFT 4 + +#define ADDR_REG PORTK +#define DATA_REG PORTF +#define CTRL_REG PORTL + +#define ADDR_DDR_REG DDRK +#define DATA_DDR_REG DDRF +#define CTRL_DDR_REG DDRL + +/* Included here to prevent accidental redefinition of F_CPU */ +#include + +/* Time it takes for the bus lanes to become stable for read and write access */ +#define BUS_HOLD_US 1 + +void set_addr(uint8_t addr); + +#endif diff --git a/include/dac.h b/include/dac.h new file mode 100644 index 0000000..55631d5 --- /dev/null +++ b/include/dac.h @@ -0,0 +1,45 @@ +/* Copyright © 2020 tyrolyean + * + * 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 . + */ + +#ifndef _DAC_H +#define _DAC_H + +#include + +void write_to_dac(uint8_t addr, uint8_t data); +uint8_t read_from_dac(uint8_t addr); + +/* The operation modes of the dac used for generation of different tones */ +#define DAC_MODE_SILENT 0 +#define DAC_MODE_SINE 1 +#define DAC_MODE_SQUARE 2 +#define DAC_MODE_SAW 3 +#define DAC_MODE_NOISE 4 +#define DAC_MODE_TRIANGLE 5 + +extern uint8_t dac_mode; +/* This variable is used to deviate the frequency from the baseline frequency + * of around 1kHz. If this integer is positive it makes the produced waveform + * longer, if it is negative the produced waveform becomes less sharp, but the + * frequency goes up. 0 is the baseline */ +extern int16_t dac_frequency_deviation; + +void feed_dac(); +void routine_dac(); + +void update_sound(); + +#endif diff --git a/include/game.h b/include/game.h new file mode 100644 index 0000000..5715470 --- /dev/null +++ b/include/game.h @@ -0,0 +1,51 @@ +/* Copyright © 2020 tyrolyean + * + * 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 . + */ + +#ifndef _GAME_H +#define _GAME_H + +#include +#include + +extern char command_buffer[100]; +extern uint8_t command_buffer_pointer; + +#define COMPUTER_STATE_NOTHING 0 +#define COMPUTER_STATE_KEYBOARD 1 +#define COMPUTER_STATE_FLOPPY 2 +extern uint8_t computer_state; /* FSM for the computer */ + +extern bool bear_shot; + +extern uint8_t current_room; + +void routine_game(); +void prepare_command_buffer(); +void ingest_user_char(char in); +void perform_action(uint8_t action_id); +void move_direction(uint8_t direction); +void describe_room(uint8_t room, bool auto_desc); +void print_inventory(); +void print_room_item(); +void consume_room_item(const char* item_name); + +void use_item(const char* item_name); +void use_item_id(uint8_t item_id); + +bool perform_computer_action(uint8_t action_id); +void reset_game(bool fleshed); +void init_game(); +#endif diff --git a/include/interrupt.h b/include/interrupt.h new file mode 100644 index 0000000..ba1b002 --- /dev/null +++ b/include/interrupt.h @@ -0,0 +1,22 @@ +/* Copyright © 2020 tyrolyean + * + * 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 . + */ + +#ifndef _INTERRUPT_H +#define _INTERRUPT_H + +void init_interrupts(); + +#endif diff --git a/include/sound.h b/include/sound.h new file mode 100644 index 0000000..d93999b --- /dev/null +++ b/include/sound.h @@ -0,0 +1,47 @@ +/* Copyright © 2020 tyrolyean + * + * 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 . + */ + +#ifndef _SOUND_H +#define _SOUND_H + +#include +#include + +struct tone_t { + uint8_t waveform; + int16_t frequency_deviation; /* */ + uint16_t length; /* The tone length in milliseconds */ +}; + +/* The end marker tells the sound routines where the end of a track is. It + * is required to be present at the end of EVERY track, otherwise the + * routine runs into undefined behaviour */ +#define TRACK_END_MARKER {DAC_MODE_SILENT, 0, 0} + +extern const struct tone_t computer_room_track[] PROGMEM; +extern const struct tone_t lonely_road_track[] PROGMEM; + +#define INTRO_LEN 10350 +extern const struct tone_t intro_track[] PROGMEM; + +extern const struct tone_t * current_track; +extern int16_t global_frequency_offset; /* Added to every playing song */ + +void update_sound(); +void init_sound(); + + +#endif diff --git a/include/structures.h b/include/structures.h new file mode 100644 index 0000000..2229b2b --- /dev/null +++ b/include/structures.h @@ -0,0 +1,81 @@ +/* Copyright © 2020 tyrolyean + * + * 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 . + */ + +#ifndef _STRUCTURES_H +#define _STRUCTURES_H + +#include + +#include +#include +#include + +#define NUM_ACTIONS 0x0A +#define ACTION_HELP 0x00 +#define ACTION_NORTH 0x01 +#define ACTION_SOUTH 0x02 +#define ACTION_WEST 0x03 +#define ACTION_EAST 0x04 +#define ACTION_DESCRIBE 0x05 +#define ACTION_USE 0x06 +#define ACTION_INVENTORY 0x07 +#define ACTION_SEARCH 0x08 +#define ACTION_TAKE 0x09 + +/* The direction in the direction table is the action_id - 1 */ +#define DIRECTION_NORTH 0x00 +#define DIRECTION_SOUTH 0x01 +#define DIRECTION_WEST 0x02 +#define DIRECTION_EAST 0x03 + +#define NUM_ROOMS 0x0A +#define ROOM_NOTHING 0x00 +#define ROOM_LONELYROAD 0x01 +#define ROOM_SNDIRTROAD 0x02 +#define ROOM_FIREPLACE 0x03 +#define ROOM_EWSTREET 0x04 +#define ROOM_OLDHOUSE 0x05 +#define ROOM_LIVINGROOM 0x06 +#define ROOM_ATTIC 0x07 +#define ROOM_BASEMENT 0x08 +#define ROOM_COMPUTER 0x09 + +#define NUM_ITEMS 0x07 +#define ITEM_FLOPPY 0x00 +#define ITEM_SCREWDRIVER 0x01 +#define ITEM_KEYBOARD 0x02 +#define ITEM_SAUSAGE 0x03 +#define ITEM_FLESH 0x04 +#define ITEM_KEY 0x05 +#define ITEM_PISTOL 0x06 + +extern const uint8_t sine_table[256] PROGMEM; +extern const uint8_t noise_table[1024] PROGMEM; + +extern char* sndirtroad_msg[2]; +extern char* user_action_req_msgs[3]; + +extern const char* info_table[]; +extern const char* action_table[NUM_ACTIONS]; +extern const char* room_table[NUM_ROOMS]; +extern char* room_description_table[NUM_ROOMS]; +extern uint8_t room_map_table[NUM_ROOMS][4]; +extern bool room_visited_table[NUM_ROOMS]; +extern const char* item_table[NUM_ITEMS]; +extern bool inventory[NUM_ITEMS]; +extern int8_t item_room_map[NUM_ROOMS]; +extern const struct tone_t * room_track_map[NUM_ROOMS]; +#endif diff --git a/src/16550.c b/src/16550.c new file mode 100644 index 0000000..424ba0b --- /dev/null +++ b/src/16550.c @@ -0,0 +1,126 @@ +/* Copyright © 2020 tyrolyean + * + * 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 . + */ + +#include "avr.h" +#include "16550.h" +#include "structures.h" +#include "game.h" + +#include +static FILE stdout_16550 = FDEV_SETUP_STREAM(putchar_16550, NULL, + _FDEV_SETUP_WRITE); + + +void write_to_uart(uint8_t addr, uint8_t data){ + + set_addr(addr); + DATA_DDR_REG = 0xFF; + DATA_REG = data; + CTRL_REG &= ~(1< (DISPLAY_COLUMNS - 10)){ + putchar_16550('\n',NULL); + return 0; + } + if(var == '\n'){ + column_cnt = 0x00; + writechar_16550('\r'); + } + + writechar_16550(var); + return 0; +} +/* Writes a character to the 16550 uart for transmission without cr lf magic */ +void writechar_16550(char var){ + + for(uint32_t i = 0; i < 1000000; i++ ){ + uint8_t received = read_from_uart(UART_REG_LSR); + if((received & (1<<5))){ + break; + } + } + + write_to_uart(UART_REG_TXRX,var); + return; +} + +void routine_uart(){ + + uint8_t received = read_from_uart(UART_REG_LSR); + if(received & 0x01){ + received = read_from_uart(UART_REG_TXRX); + ingest_user_char(received); + if(received == '\r'){ + writechar_16550('\n'); + } + writechar_16550(received); /* Echo back */ + } + + return; +} + diff --git a/src/dac.c b/src/dac.c new file mode 100644 index 0000000..1310ff6 --- /dev/null +++ b/src/dac.c @@ -0,0 +1,207 @@ +/* Copyright © 2020 tyrolyean + * + * 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 . + */ + +#include "avr.h" +#include "dac.h" +#include "structures.h" + +#include + +uint8_t dac_mode = DAC_MODE_SINE; +int16_t dac_frequency_deviation = 0; + +void write_to_dac(uint8_t addr, uint8_t data){ + + + set_addr(addr); + DATA_DDR_REG = 0xFF; + DATA_REG = data; + CTRL_REG &= ~(1< the frequency made lower from baseline + */ + static int16_t freq_delay_cnt = 0x00; + switch(dac_mode){ + + default: + case DAC_MODE_SILENT: + for(uint8_t i = 0; i < 0xFF; i++){ + write_to_dac(i%2, 0); + } + + break; + + case DAC_MODE_SINE: + /* Generates a sine from a predetermined sine table in program + * space */ + for(uint8_t i = 0; i < (0xFF/2); i++){ + write_to_dac(1, + pgm_read_byte(&sine_table[threash])); + write_to_dac(0, + pgm_read_byte(&sine_table[threash])); + + if(dac_frequency_deviation >=0){ + freq_delay_cnt++; + if(freq_delay_cnt >= + dac_frequency_deviation){ + freq_delay_cnt = 0; + threash++; + + } + + }else{ + threash -= dac_frequency_deviation; + } + + } + break; + case DAC_MODE_SQUARE: + /* Generates a square wave tone */ + for(uint8_t i = 0; i < (0xFF/2); i++){ + if(threash > (0xFF/2)){ + write_to_dac(0, 0xFF); + write_to_dac(1, 0xFF); + }else{ + write_to_dac(0, 0); + write_to_dac(1, 0); + } + if(dac_frequency_deviation >=0){ + freq_delay_cnt++; + if(freq_delay_cnt >= + dac_frequency_deviation){ + freq_delay_cnt = 0; + threash++; + + } + + }else{ + threash -= dac_frequency_deviation; + } + } + break; + case DAC_MODE_SAW: + /* Generates a saw wave tone */ + for(uint8_t i = 0; i < (0xFF/2); i++){ + write_to_dac(0, threash); + write_to_dac(1, threash); + if(dac_frequency_deviation >=0){ + freq_delay_cnt++; + if(freq_delay_cnt >= + dac_frequency_deviation){ + freq_delay_cnt = 0; + threash++; + + } + + }else{ + threash -= dac_frequency_deviation; + } + } + break; + case DAC_MODE_NOISE: + /* Generates white noise from a predetermined LUT + */ + for(uint8_t i = 0; i < (0xFF/2); i++){ + static uint16_t noise_cnt = 0; + write_to_dac(1, + pgm_read_byte(&noise_table[noise_cnt])); + write_to_dac(0, + pgm_read_byte(&noise_table[noise_cnt])); + + noise_cnt++; /* Doesn't have frequency diversion + */ + if(noise_cnt >= 1024){ + noise_cnt = 0; + } + + } + break; + case DAC_MODE_TRIANGLE: + /* Generates a triangle wave tone */ + for(uint8_t i = 0; i < (0xFF/2); i++){ + static int8_t direction = 1; + if((threash == 0xFF) | !threash){ + direction = -direction; + } + write_to_dac(0, threash); + write_to_dac(1, threash); + if(dac_frequency_deviation >=0){ + freq_delay_cnt++; + if(freq_delay_cnt >= + dac_frequency_deviation){ + freq_delay_cnt = 0; + + threash += direction; + + } + + }else{ + if((dac_frequency_deviation * + direction) > + (0xFF - threash)){ + threash = 0xFF; + continue; + } + threash = (dac_frequency_deviation * + direction); + } + } + break; + } + + return; +} + +void routine_dac(){ + + uint8_t received = read_from_dac(0x00); + if(!(received & (0x01<<0))){ + feed_dac(); + } + return; +} diff --git a/src/game.c b/src/game.c new file mode 100644 index 0000000..66fa794 --- /dev/null +++ b/src/game.c @@ -0,0 +1,378 @@ +/* Copyright © 2020 tyrolyean + * + * 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 . + */ + +#include "game.h" +#include "structures.h" +#include "16550.h" + +#include +#include +#include + +char command_buffer[100]; +uint8_t command_buffer_pointer = 0x00; + +uint8_t current_room = ROOM_LONELYROAD; + +uint8_t computer_state = 0; +bool bear_shot = false; + +void routine_game(){ + + if(command_buffer_pointer >= sizeof(command_buffer)){ + + command_buffer_pointer = 0x00; + memset(command_buffer, 0, sizeof(command_buffer)); + + println("\nToo much input!"); + return; + } + + if(command_buffer[command_buffer_pointer-1] == '\n' || + command_buffer[command_buffer_pointer-1] == '\r'){ + /* A command from the user has been received, we are ready to + * do something!*/ + + int8_t action_id = -1; + for(size_t i = 0; i < sizeof(action_table)/sizeof(const char*); + i++){ + if(strncasecmp(action_table[i], command_buffer, + strlen(action_table[i])) == 0){ + action_id = i; + break; + } + + } + if(action_id < 0){ + println(info_table[1]); + }else{ + perform_action(action_id); + + } + + command_buffer_pointer = 0x00; + memset(command_buffer, 0, sizeof(command_buffer)); + } + + return; +} + +void ingest_user_char(char in){ + if(in == 0x7F /* DELETE CHAR */){ + command_buffer[command_buffer_pointer--] = 0x00; + + }else{ + command_buffer[command_buffer_pointer++] = in; + } + return; +} + +void perform_action(uint8_t action_id){ + putchar_16550('\n', NULL); + switch(action_id){ + default: + case ACTION_HELP: + println("You can:"); + for(size_t i = 0; i < NUM_ACTIONS; i++){ + println(" %s",action_table[i]); + } + break; + + case ACTION_DESCRIBE: + describe_room(current_room, false); + break; + + case ACTION_NORTH: + case ACTION_SOUTH: + case ACTION_WEST: + case ACTION_EAST: + move_direction(action_id -1); + break; + case ACTION_INVENTORY: + print_inventory(); + break; + case ACTION_SEARCH: + print_room_item(); + break; + case ACTION_TAKE: + consume_room_item(command_buffer+ + strlen(action_table[ACTION_TAKE])+1); + break; + case ACTION_USE: + use_item(command_buffer+ + strlen(action_table[ACTION_USE])+1); + break; + + }; + println(info_table[3]); + + return; +} + +void move_direction(uint8_t direction){ + if(!room_map_table[current_room][direction]){ + println(info_table[4]); + return; + } + println("Moving towards %s",action_table[direction+1]); + current_room = room_map_table[current_room][direction]; + describe_room(current_room,true); + current_track = room_track_map[current_room]; + return; +} + +void describe_room(uint8_t room, bool auto_desc){ + + println(room_table[room]); + if(room_visited_table[room] && auto_desc){ + room_visited_table[room] = true; + return; + } + room_visited_table[room] = true; + putchar_16550('\n', NULL); + println(room_description_table[room]); + + return; +} + +void print_inventory(){ + bool found_item = false; + for(size_t i = 0; i < NUM_ITEMS; i++){ + if(inventory[i]){ + found_item = true; + break; + } + } + if(found_item){ + println("You have:"); + for(size_t i = 0; i < NUM_ITEMS; i++){ + if(inventory[i]){ + println(" %s",item_table[i]); + } + } + + }else{ + println("Your inventory is empty"); + } + + return; +} + +void print_room_item(){ + if(item_room_map[current_room] < 0){ + println(info_table[6]); + }else{ + println("You found a %s", + item_table[item_room_map[current_room]]); + } + return; +} + +void consume_room_item(const char* item_name){ + if(item_room_map[current_room] < 0){ + println(info_table[6]); + }else{ + for(int8_t i = 0; i < NUM_ITEMS; i++){ + if(strncasecmp(item_table[i], item_name, + strlen(item_table[i])) == 0){ + + if(item_room_map[current_room] != i){ + break; + } + + println("You took the %s", + item_table[item_room_map[ + current_room]]); + + inventory[item_room_map[current_room]] = true; + item_room_map[current_room] = -1; + return; + } + + } + println("That's not here..."); + + } + return; +} +void use_item(const char* item_name){ + + for(size_t i = 0; i < NUM_ITEMS; i++){ + if(strncasecmp(item_table[i], item_name, + strlen(item_table[i])) == 0){ + use_item_id(i); + return; + } + + } + println(info_table[2]); + return; + +} + +void use_item_id(uint8_t item_id){ + if(!inventory[item_id]){ + println(info_table[2]); + return; + } + + + switch(item_id){ + case ITEM_SAUSAGE: + if(current_room == ROOM_SNDIRTROAD){ + inventory[ITEM_SAUSAGE] = false; + room_map_table[current_room][DIRECTION_NORTH] = + ROOM_FIREPLACE; + println(info_table[10]); + return; + } + break; + case ITEM_PISTOL: + if(current_room == ROOM_SNDIRTROAD){ + room_map_table[current_room][DIRECTION_NORTH] = + ROOM_FIREPLACE; + println(info_table[7]); + bear_shot = true; + return; + } else if(current_room == ROOM_NOTHING){ + /* The real end i guess. I won't put this in the + * info table as it *SHOULD* only be displayed + * once. + */ + println("You cry for help. It's no use. You " + "attempt to shoot yourself. It's no " + "use... You run out of bullets"); + inventory[ITEM_PISTOL] = false; + return; + } + break; + case ITEM_KEY: + if(current_room == ROOM_EWSTREET){ + inventory[ITEM_KEY] = false; + room_map_table[current_room][DIRECTION_NORTH] = + ROOM_OLDHOUSE; + println(info_table[13]); + return; + } + break; + case ITEM_FLOPPY: + case ITEM_FLESH: + case ITEM_SCREWDRIVER: + case ITEM_KEYBOARD: + if(current_room == ROOM_COMPUTER){ + if(perform_computer_action(item_id)){ + return; + } + + } + break; + }; + println(info_table[2]); + + return; +} + +bool perform_computer_action(uint8_t item_id){ + + static bool fleshed = false; + if(item_id == ITEM_KEYBOARD && + computer_state == COMPUTER_STATE_NOTHING){ + computer_state = COMPUTER_STATE_KEYBOARD; + inventory[item_id] = false; + println("You connected the keyboard"); + return true; + } + + if(item_id == ITEM_FLOPPY && + computer_state == COMPUTER_STATE_KEYBOARD){ + computer_state = COMPUTER_STATE_FLOPPY; + inventory[item_id] = false; + println("You inseted the floppy disk"); + return true; + } + if(item_id == ITEM_FLESH && + computer_state == COMPUTER_STATE_KEYBOARD){ + computer_state = COMPUTER_STATE_FLOPPY; + inventory[item_id] = false; + println("You inserted the flesh into the floppy drive"); + fleshed = true; + return true; + } + if(item_id == ITEM_SCREWDRIVER && + computer_state == COMPUTER_STATE_FLOPPY){ + computer_state = COMPUTER_STATE_FLOPPY; + inventory[item_id] = false; + /* Perform a reset of the game */ + println("You start the computer with the screwdriver, sit down" + " and watch it boot into a textadventure:"); + + reset_game(fleshed); + return true; + } + + return false; +} +/* Resets the game into "original" state or the bear dead state or the FLESH + * game state. FLESH is basically the end. You need to reset your computer + * afterwards. + */ +void reset_game(bool fleshed){ + + /* clear inventory */ + memset(inventory, 0, sizeof(inventory)); + /* Reset rooms visited */ + memset(room_visited_table, 0, sizeof(inventory)); + /* Reset items in rooms */ + for(size_t i = 0; i < NUM_ROOMS; i++){ + item_room_map[i] = -1; + } + + if(fleshed){ + current_room = ROOM_NOTHING; + inventory[ITEM_PISTOL] = true; + }else if(bear_shot){ + current_room = ROOM_LONELYROAD; + room_description_table[ROOM_SNDIRTROAD] = sndirtroad_msg[1]; + item_room_map[ROOM_SNDIRTROAD] = ITEM_FLESH; + + }else{ + current_room = ROOM_LONELYROAD; + room_map_table[ROOM_SNDIRTROAD][DIRECTION_NORTH] = 0x00; + item_room_map[ROOM_SNDIRTROAD] = ITEM_SAUSAGE; + item_room_map[ROOM_LONELYROAD] = ITEM_PISTOL; + item_room_map[ROOM_BASEMENT] = ITEM_FLOPPY; + } + + item_room_map[ROOM_EWSTREET] = ITEM_KEY; + item_room_map[ROOM_OLDHOUSE] = ITEM_SCREWDRIVER; + item_room_map[ROOM_ATTIC] = ITEM_KEYBOARD; + + computer_state = COMPUTER_STATE_NOTHING; + + room_map_table[ROOM_EWSTREET][DIRECTION_NORTH] = 0x00; + current_track = room_track_map[current_room]; + describe_room(current_room, false); + + + return; +} + +void init_game(){ + + room_description_table[ROOM_SNDIRTROAD] = sndirtroad_msg[0]; + info_table[3] = user_action_req_msgs[0]; + return; +} diff --git a/src/interrupt.c b/src/interrupt.c new file mode 100644 index 0000000..4737080 --- /dev/null +++ b/src/interrupt.c @@ -0,0 +1,36 @@ +/* Copyright © 2020 tyrolyean + * + * 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 . + */ + +#include "interrupt.h" +#include "dac.h" +#include + +void init_interrupts(){ + /* Initialize the timer interrupt */ + TCCR0A = (1 << COM0A1) | (1 << WGM11); + TCCR0B = (1 << CS02); + OCR0A = 64; /* Interrupt fires every Millisecond */ + TIMSK0 = (1 << OCIE0A); + +} + + +ISR(TIMER0_COMPA_vect) +{ + update_sound(); +} + + diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..fe18e37 --- /dev/null +++ b/src/main.c @@ -0,0 +1,112 @@ +/* Copyright © 2020 tyrolyean + * + * 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 . + */ + +#include "avr.h" +#include "structures.h" +#include "16550.h" +#include "dac.h" +#include "interrupt.h" +#include "sound.h" +#include "game.h" + +#include +#include +#include +#include +#include + + +/* Included early on the prevent the watchdog from killing the already killed + * microcontroller because of init delay + */ + +uint8_t mcusr_mirror __attribute__ ((section (".noinit"))); +void get_mcusr(void) \ + __attribute__((naked)) \ + __attribute__((section(".init3"))); + +void get_mcusr(void) +{ + mcusr_mirror = MCUSR; + MCUSR = 0; + wdt_disable(); +} + +/* Function used to be more complicated, still remains for readability reasons + */ + +void set_addr(uint8_t addr){ + + ADDR_REG = addr; + return; +} + +void reset_modules(){ + + /* Setup Data Direction Registers and populate with sane default + values */ + DATA_DDR_REG = 0xFF; /* Data Bus */ + ADDR_DDR_REG = 0xFF; /* Address Bus */ + CTRL_DDR_REG= 0xFF; /* Control Bus */ + ADDR_REG = 0x00; + DATA_REG = 0x00; + CTRL_REG = 0x00; + + /* Cleanly reset the dac and the uart */ + CTRL_REG |= (1<. + */ + + +#include "sound.h" +#include "sound.h" +#include "dac.h" + +#include +#include + +const struct tone_t computer_room_track[] PROGMEM = +{ + {DAC_MODE_SQUARE, 0,100}, + {DAC_MODE_SQUARE, 10,100}, + {DAC_MODE_SQUARE, 0,100}, + {DAC_MODE_SQUARE, 10,100}, + {DAC_MODE_SQUARE, 0,100}, + {DAC_MODE_NOISE, 0,200}, + {DAC_MODE_SINE, 10,50}, + {DAC_MODE_SINE, -10,50}, + {DAC_MODE_SINE, 10,50}, + {DAC_MODE_SINE, -10,50}, + + {DAC_MODE_SQUARE, 0,100}, + {DAC_MODE_SQUARE, 10,100}, + {DAC_MODE_SQUARE, 0,100}, + {DAC_MODE_SQUARE, 10,100}, + {DAC_MODE_SQUARE, 0,100}, + {DAC_MODE_NOISE, 0,200}, + {DAC_MODE_SINE, 10,50}, + {DAC_MODE_SINE, -10,50}, + {DAC_MODE_SINE, 10,50}, + {DAC_MODE_SINE, -10,50}, + + {DAC_MODE_SQUARE, 0,100}, + {DAC_MODE_SQUARE, 10,100}, + {DAC_MODE_SQUARE, 0,100}, + {DAC_MODE_SQUARE, 10,100}, + {DAC_MODE_SQUARE, 0,100}, + {DAC_MODE_NOISE, 0,200}, + {DAC_MODE_SINE, 10,50}, + {DAC_MODE_SINE, -10,50}, + {DAC_MODE_SINE, 10,50}, + {DAC_MODE_SINE, -10,50}, + + {DAC_MODE_SQUARE, 0,100}, + {DAC_MODE_SQUARE, 10,100}, + {DAC_MODE_SQUARE, 0,100}, + {DAC_MODE_SQUARE, 10,100}, + {DAC_MODE_SQUARE, 0,100}, + {DAC_MODE_NOISE, 0,200}, + {DAC_MODE_SINE, 10,50}, + {DAC_MODE_SINE, -10,50}, + {DAC_MODE_SINE, 10,50}, + {DAC_MODE_SINE, -10,50}, + + {DAC_MODE_SQUARE, 0,100}, + {DAC_MODE_SQUARE, 10,100}, + {DAC_MODE_SQUARE, 0,100}, + {DAC_MODE_SQUARE, 10,100}, + {DAC_MODE_SQUARE, 0,100}, + {DAC_MODE_NOISE, 0,200}, + {DAC_MODE_SINE, 10,50}, + {DAC_MODE_SINE, -10,50}, + {DAC_MODE_SINE, 10,50}, + {DAC_MODE_SINE, -10,50}, + + {DAC_MODE_SQUARE, -2,100}, + {DAC_MODE_SQUARE, 8,100}, + {DAC_MODE_SQUARE, -2,100}, + {DAC_MODE_SQUARE, 8,100}, + {DAC_MODE_SQUARE, -2,100}, + {DAC_MODE_NOISE, 0,200}, + {DAC_MODE_SINE, 12,50}, + {DAC_MODE_SINE, -8,50}, + {DAC_MODE_SINE, 12,50}, + {DAC_MODE_SINE, -8,50}, + + {DAC_MODE_SQUARE, -3,100}, + {DAC_MODE_SQUARE, 7,100}, + {DAC_MODE_SQUARE, -3,100}, + {DAC_MODE_SQUARE, 7,100}, + {DAC_MODE_SQUARE, -3,100}, + {DAC_MODE_NOISE, 0,200}, + {DAC_MODE_SINE, 13,50}, + {DAC_MODE_SINE, -7,50}, + {DAC_MODE_SINE, 13,50}, + {DAC_MODE_SINE, -7,50}, + + TRACK_END_MARKER +}; + +const struct tone_t lonely_road_track[] PROGMEM = +{ + + {DAC_MODE_SQUARE, -2,80}, + {DAC_MODE_SQUARE, -3,80}, + {DAC_MODE_SAW, -4,170}, + {DAC_MODE_SILENT, 0,30}, + {DAC_MODE_SAW, -6,170}, + {DAC_MODE_SILENT, 0,30}, + {DAC_MODE_SAW, -6,170}, + {DAC_MODE_SILENT, 0,30}, + + {DAC_MODE_SQUARE, -2,80}, + {DAC_MODE_SQUARE, -3,80}, + {DAC_MODE_SAW, -4,170}, + {DAC_MODE_SILENT, 0,30}, + {DAC_MODE_SAW, -6,170}, + {DAC_MODE_SILENT, 0,30}, + {DAC_MODE_SAW, -6,170}, + {DAC_MODE_SILENT, 0,30}, + + {DAC_MODE_SQUARE, -2,80}, + {DAC_MODE_SQUARE, -3,80}, + {DAC_MODE_SAW, -4,170}, + {DAC_MODE_SILENT, 0,30}, + {DAC_MODE_SAW, -6,170}, + {DAC_MODE_SILENT, 0,30}, + {DAC_MODE_SAW, -6,300}, + {DAC_MODE_SAW, -4,130}, + {DAC_MODE_SAW, -2,130}, + {DAC_MODE_SILENT, 0,80}, + + + {DAC_MODE_SQUARE, -1,80}, + {DAC_MODE_SQUARE, -2,80}, + {DAC_MODE_SAW, -3,170}, + {DAC_MODE_SILENT, 0,20}, + {DAC_MODE_SAW, -5,170}, + {DAC_MODE_SILENT, 0,20}, + {DAC_MODE_SAW, -5,170}, + {DAC_MODE_SILENT, 0,30}, + + {DAC_MODE_SQUARE, -1,80}, + {DAC_MODE_SQUARE, -2,80}, + {DAC_MODE_SAW, -3,170}, + {DAC_MODE_SILENT, 0,20}, + {DAC_MODE_SAW, -5,170}, + {DAC_MODE_SILENT, 0,20}, + {DAC_MODE_SAW, -5,170}, + {DAC_MODE_SILENT, 0,20}, + + {DAC_MODE_SQUARE, -1,80}, + {DAC_MODE_SQUARE, -2,80}, + {DAC_MODE_SAW, -3,170}, + {DAC_MODE_SILENT, 0,30}, + {DAC_MODE_SAW, -5,170}, + {DAC_MODE_SILENT, 0,30}, + {DAC_MODE_SAW, -5,300}, + {DAC_MODE_SAW, -3,130}, + {DAC_MODE_SAW, -1,130}, + {DAC_MODE_SILENT, 0,80}, + TRACK_END_MARKER +}; + +const struct tone_t intro_track[] PROGMEM = +{ + {DAC_MODE_SQUARE, -3,200}, + {DAC_MODE_SQUARE, -4,200}, + {DAC_MODE_SQUARE, -5,200}, + {DAC_MODE_SQUARE, -3,200}, + {DAC_MODE_SQUARE, -4,200}, + {DAC_MODE_SQUARE, -5,200}, + {DAC_MODE_SQUARE, -3,200}, + {DAC_MODE_SQUARE, -4,200}, + {DAC_MODE_SQUARE, -5,200}, + {DAC_MODE_SQUARE, -3,200}, + {DAC_MODE_SQUARE, -4,200}, + {DAC_MODE_SQUARE, -5,200}, + + + {DAC_MODE_SQUARE, -3,200}, + {DAC_MODE_SQUARE, -4,200}, + {DAC_MODE_SQUARE, -5,200}, + {DAC_MODE_SQUARE, -3,200}, + {DAC_MODE_SQUARE, -4,200}, + {DAC_MODE_SQUARE, -5,200}, + {DAC_MODE_SQUARE, -3,200}, + {DAC_MODE_SQUARE, -4,200}, + {DAC_MODE_SQUARE, -5,200}, + {DAC_MODE_SQUARE, -3,200}, + {DAC_MODE_SQUARE, -4,200}, + {DAC_MODE_SQUARE, -5,200}, + + {DAC_MODE_SQUARE, -3,400}, + {DAC_MODE_SQUARE, -4,400}, + {DAC_MODE_SQUARE, -5,400}, + {DAC_MODE_SQUARE, -3,500}, + {DAC_MODE_SQUARE, -4,550}, + {DAC_MODE_SQUARE, -5,600}, + + {DAC_MODE_SQUARE, -3,800}, + {DAC_MODE_SQUARE, -4,900}, + {DAC_MODE_SQUARE, -5,1000}, + + {DAC_MODE_SILENT, 0,1000}, + + TRACK_END_MARKER +}; + +const struct tone_t *current_track = NULL; +int16_t global_frequency_offset = 0x00; + +/* Loops a track indefinitely and changes voices according to predefined tables. + * A new track resets the internal state. A voice with a length of 0ms is used + * to mark the end of a track and continue at the beginning + */ +void update_sound(){ + + static uint16_t audio_time = 0; + static size_t tone_pointer = 0x00; + static struct tone_t current_tone = {DAC_MODE_SILENT, 0,0}; + if(current_track == NULL){ + /* ABORT */ + audio_time = 0x00; + return; + } + audio_time++; + static const struct tone_t * old_track = NULL; + + if(audio_time >= current_tone.length || + current_track != old_track){ + + if(old_track != current_track){ + tone_pointer = 0; + audio_time = 0x00; + old_track = current_track; + } + memcpy_P(¤t_tone,&(current_track[tone_pointer]), + sizeof(current_tone)); + + if(current_tone.length == 0){ + tone_pointer = 0; + memcpy_P(¤t_tone,&(current_track[tone_pointer]), + sizeof(current_tone)); + + } + + dac_mode = current_tone.waveform; + dac_frequency_deviation = current_tone.frequency_deviation + + global_frequency_offset; + audio_time = 0x00; + tone_pointer++; + } + return; +} diff --git a/src/structures.c b/src/structures.c new file mode 100644 index 0000000..e957dc7 --- /dev/null +++ b/src/structures.c @@ -0,0 +1,480 @@ +/* Copyright © 2020 tyrolyean + * + * 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 . + */ + +#include "structures.h" +#include + +const uint8_t sine_table[256] PROGMEM = { + 0x7f,0x82,0x85,0x88, + 0x8c,0x8f,0x92,0x95, + 0x98,0x9b,0x9e,0xa1, + 0xa4,0xa7,0xaa,0xad, + 0xb0,0xb3,0xb6,0xb9, + 0xbb,0xbe,0xc1,0xc3, + 0xc6,0xc9,0xcb,0xce, + 0xd0,0xd3,0xd5,0xd7, + 0xd9,0xdc,0xde,0xe0, + 0xe2,0xe4,0xe6,0xe8, + 0xe9,0xeb,0xed,0xee, + 0xf0,0xf1,0xf2,0xf4, + 0xf5,0xf6,0xf7,0xf8, + 0xf9,0xfa,0xfb,0xfc, + 0xfc,0xfd,0xfd,0xfe, + 0xfe,0xfe,0xfe,0xfe, + 0xfe,0xfe,0xfe,0xfe, + 0xfe,0xfd,0xfd,0xfc, + 0xfc,0xfb,0xfa,0xfa, + 0xf9,0xf8,0xf7,0xf6, + 0xf4,0xf3,0xf2,0xf0, + 0xef,0xed,0xec,0xea, + 0xe8,0xe7,0xe5,0xe3, + 0xe1,0xdf,0xdd,0xdb, + 0xd8,0xd6,0xd4,0xd1, + 0xcf,0xcc,0xca,0xc7, + 0xc5,0xc2,0xbf,0xbd, + 0xba,0xb7,0xb4,0xb1, + 0xaf,0xac,0xa9,0xa6, + 0xa3,0xa0,0x9d,0x9a, + 0x96,0x93,0x90,0x8d, + 0x8a,0x87,0x84,0x81, + 0x7d,0x7a,0x77,0x74, + 0x71,0x6e,0x6b,0x68, + 0x64,0x61,0x5e,0x5b, + 0x58,0x55,0x52,0x4f, + 0x4d,0x4a,0x47,0x44, + 0x41,0x3f,0x3c,0x39, + 0x37,0x34,0x32,0x2f, + 0x2d,0x2a,0x28,0x26, + 0x23,0x21,0x1f,0x1d, + 0x1b,0x19,0x17,0x16, + 0x14,0x12,0x11,0xf, + 0xe,0xc,0xb,0xa, + 0x8,0x7,0x6,0x5, + 0x4,0x4,0x3,0x2, + 0x2,0x1,0x1,0x0, + 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0, + 0x0,0x1,0x1,0x2, + 0x2,0x3,0x4,0x5, + 0x6,0x7,0x8,0x9, + 0xa,0xc,0xd,0xe, + 0x10,0x11,0x13,0x15, + 0x16,0x18,0x1a,0x1c, + 0x1e,0x20,0x22,0x25, + 0x27,0x29,0x2b,0x2e, + 0x30,0x33,0x35,0x38, + 0x3b,0x3d,0x40,0x43, + 0x45,0x48,0x4b,0x4e, + 0x51,0x54,0x57,0x5a, + 0x5d,0x60,0x63,0x66, + 0x69,0x6c,0x6f,0x72, + 0x76,0x79,0x7c,0x7f, +}; + +const uint8_t noise_table[1024] PROGMEM = { + 0x30, 0xc, 0x3, 0xdf, + 0x31, 0xfa, 0x2b, 0x78, + 0xd5, 0xd8, 0x6c, 0x29, + 0x45, 0xa1, 0x2, 0x69, + 0x69, 0x91, 0x8d, 0x65, + 0x71, 0xb8, 0x43, 0xde, + 0xf2, 0xf6, 0x78, 0x6e, + 0x1d, 0xbf, 0x34, 0x4e, + 0xcb, 0x38, 0x2e, 0xfd, + 0x32, 0x59, 0x75, 0x7, + 0x32, 0xe2, 0x31, 0x77, + 0x84, 0x33, 0xe1, 0xed, + 0xc5, 0x6e, 0x52, 0x36, + 0x27, 0x96, 0x15, 0x19, + 0x8d, 0x8d, 0x88, 0xab, + 0x4d, 0xbc, 0xf9, 0x18, + 0xf5, 0x27, 0x16, 0x27, + 0x81, 0x8c, 0x2f, 0xb4, + 0x6e, 0x60, 0x2b, 0xf2, + 0x94, 0xc, 0xe0, 0x59, + 0x7b, 0x33, 0x8f, 0xa3, + 0xc9, 0xa4, 0xbd, 0x57, + 0x32, 0x45, 0x2, 0x7f, + 0x2, 0xfb, 0x98, 0xf7, + 0x23, 0xae, 0x1e, 0xa5, + 0x3a, 0x4d, 0x59, 0xa9, + 0xae, 0x84, 0x9b, 0x42, + 0x91, 0x7c, 0x9b, 0xc, + 0xb0, 0x2b, 0xb0, 0x7a, + 0xcf, 0x6d, 0xd1, 0x2, + 0xb2, 0xd3, 0x81, 0xb4, + 0xce, 0x19, 0xac, 0xf2, + 0xc7, 0xcb, 0x97, 0x2, + 0x18, 0xf0, 0xab, 0xc7, + 0x74, 0x47, 0x9, 0x6, + 0xc4, 0xa5, 0x13, 0x74, + 0xd0, 0xc3, 0xee, 0xa0, + 0x30, 0xbf, 0xa2, 0xe2, + 0x92, 0x24, 0x97, 0x61, + 0x3d, 0x44, 0x53, 0x5, + 0xf, 0xea, 0x7, 0x28, + 0xda, 0xb3, 0xef, 0x4f, + 0xfa, 0xf9, 0x55, 0xbe, + 0x9f, 0x68, 0x33, 0x6f, + 0x2b, 0x21, 0x10, 0x5c, + 0xe0, 0xb2, 0x3f, 0x73, + 0xd6, 0xd7, 0xd4, 0x14, + 0x1b, 0x27, 0x1a, 0x2a, + 0x12, 0x21, 0x53, 0xec, + 0xd5, 0x42, 0x3c, 0xcf, + 0x3c, 0x91, 0x8e, 0xdb, + 0xfa, 0xc2, 0x4b, 0x26, + 0xe3, 0x5b, 0x82, 0xc4, + 0xe, 0xc1, 0x37, 0xe5, + 0x98, 0xb, 0xfa, 0xb4, + 0x33, 0x14, 0xde, 0x45, + 0x36, 0x31, 0x32, 0xb, + 0x74, 0x6e, 0xdb, 0xb1, + 0x0, 0x6a, 0x8c, 0xfa, + 0x2c, 0xd7, 0x21, 0xf, + 0x33, 0xa3, 0xd3, 0x42, + 0x65, 0xa, 0x27, 0xfe, + 0x16, 0x21, 0xb2, 0x49, + 0x35, 0x91, 0x8e, 0x6b, + 0xc3, 0xc0, 0x77, 0x38, + 0x2e, 0x52, 0xe9, 0x2f, + 0xbc, 0x76, 0x29, 0xe8, + 0x4d, 0x4b, 0xf7, 0x81, + 0xef, 0xcb, 0xc3, 0x54, + 0xd5, 0xeb, 0x53, 0xec, + 0xd, 0x6, 0x35, 0x43, + 0x98, 0xc3, 0xaf, 0x5b, + 0x84, 0x26, 0x94, 0xb3, + 0x78, 0x7d, 0xe2, 0x35, + 0xf3, 0xc, 0x1d, 0x41, + 0x57, 0x15, 0xc3, 0x46, + 0xe0, 0x87, 0x9b, 0xb6, + 0x72, 0xee, 0xa3, 0x7f, + 0xf5, 0xd8, 0xc2, 0x8d, + 0x9c, 0x72, 0xe9, 0x20, + 0x98, 0x7d, 0xd3, 0x11, + 0xfb, 0xb5, 0x46, 0xef, + 0xc1, 0x64, 0x31, 0x19, + 0x79, 0xf4, 0x5f, 0x5a, + 0x7b, 0xfa, 0x11, 0xee, + 0xe9, 0xb4, 0x6e, 0xde, + 0x8c, 0x31, 0x6c, 0x29, + 0xa3, 0x55, 0x49, 0x3b, + 0xd3, 0x1c, 0x4d, 0xce, + 0xd2, 0x93, 0xbe, 0x94, + 0xf7, 0xef, 0xad, 0x71, + 0xe4, 0xd, 0xcc, 0x60, + 0x8, 0xdd, 0x4e, 0xf1, + 0x92, 0xbc, 0xd0, 0x1f, + 0xed, 0x3c, 0x48, 0x90, + 0x92, 0x91, 0xcc, 0x65, + 0xae, 0x19, 0x34, 0x81, + 0xad, 0xf2, 0x15, 0xa5, + 0xe2, 0xc3, 0x17, 0xc6, + 0xd0, 0xe3, 0x27, 0xd8, + 0xc1, 0x75, 0xca, 0x53, + 0x32, 0x9b, 0x72, 0x1f, + 0xd8, 0xbb, 0xb0, 0x6a, + 0x4d, 0x7d, 0xd0, 0xfb, + 0x97, 0x4, 0x7d, 0x45, + 0xf7, 0x93, 0xea, 0xd9, + 0x56, 0x1, 0xa0, 0x27, + 0xe4, 0xc7, 0x0, 0xa5, + 0x3d, 0xcb, 0xf9, 0x6f, + 0x66, 0x6c, 0x8f, 0x3f, + 0x27, 0x40, 0xa9, 0x74, + 0xbe, 0x7a, 0x70, 0x55, + 0x7f, 0xee, 0x9a, 0x76, + 0x81, 0x85, 0x50, 0xd7, + 0x87, 0xf1, 0xff, 0x6b, + 0xb9, 0xff, 0x11, 0xf7, + 0xca, 0xb, 0x67, 0x31, + 0x77, 0xf7, 0x70, 0x9f, + 0x37, 0x1a, 0x14, 0xf6, + 0x94, 0x85, 0x4b, 0x13, + 0x73, 0xe6, 0x8a, 0xf4, + 0x6c, 0xdb, 0xcb, 0xf3, + 0xcc, 0xcb, 0x5f, 0x86, + 0xca, 0x71, 0x7d, 0x95, + 0x7c, 0xe4, 0xc6, 0xf4, + 0xdc, 0x36, 0x93, 0x13, + 0x50, 0xa7, 0xa, 0xe5, + 0x2d, 0x55, 0xf9, 0xa0, + 0x3c, 0x83, 0x94, 0xa9, + 0x5f, 0x60, 0x9c, 0x2b, + 0x2b, 0xfc, 0xb2, 0xf6, + 0x6d, 0x30, 0x8b, 0xe9, + 0x14, 0x51, 0xde, 0xf0, + 0x88, 0x71, 0x4, 0xd8, + 0x19, 0xe, 0xbe, 0x46, + 0x64, 0xb7, 0xe6, 0xa1, + 0x3b, 0x7b, 0x4a, 0x9a, + 0xdb, 0xe7, 0xc6, 0x7, + 0xe3, 0x78, 0xfd, 0x51, + 0xa8, 0x88, 0x3b, 0xbd, + 0xda, 0x19, 0xae, 0x62, + 0x8a, 0xb3, 0x3a, 0xa4, + 0xc2, 0xf9, 0xeb, 0x26, + 0xb0, 0xd2, 0xc8, 0xec, + 0x4d, 0x13, 0x86, 0x29, + 0xfa, 0x4d, 0x30, 0xde, + 0xc6, 0x2e, 0x2f, 0x6f, + 0xb6, 0x6a, 0x2d, 0x90, + 0x83, 0xdb, 0xf2, 0xe, + 0x8f, 0x2d, 0xb3, 0x51, + 0x27, 0x9e, 0x78, 0xd8, + 0x71, 0x40, 0xc4, 0xbe, + 0x54, 0x4b, 0xe8, 0x4e, + 0x98, 0x18, 0x2d, 0x5f, + 0x46, 0x5d, 0xce, 0xfd, + 0xc7, 0xfb, 0x8e, 0x4b, + 0xd7, 0x81, 0x5a, 0x66, + 0xaf, 0xe, 0xb7, 0xd6, + 0xac, 0x2f, 0xae, 0x1d, + 0x70, 0x72, 0xdc, 0xc4, + 0xbd, 0xc4, 0x13, 0x56, + 0xdd, 0x40, 0xb6, 0x24, + 0x9d, 0x84, 0x21, 0x65, + 0x80, 0xb0, 0xb1, 0x57, + 0x31, 0xb, 0xbd, 0xe0, + 0x19, 0x75, 0xb6, 0xc6, + 0xa5, 0x64, 0xe4, 0x15, + 0xd7, 0xc1, 0xda, 0x95, + 0x85, 0xed, 0xec, 0x63, + 0x2e, 0xa2, 0x87, 0xcc, + 0x26, 0xa9, 0x32, 0xa6, + 0x59, 0xe3, 0xfd, 0x8a, + 0xef, 0xbb, 0x6b, 0x9, + 0x30, 0x21, 0xcf, 0xd5, + 0x86, 0xb4, 0xeb, 0x5d, + 0x75, 0xc5, 0xf3, 0xfb, + 0xb3, 0xdf, 0x5e, 0xe2, + 0x81, 0xe6, 0xaf, 0xa7, + 0x8f, 0xe1, 0x4e, 0xe8, + 0xc5, 0x4c, 0x73, 0xb4, + 0x7, 0xdf, 0xbe, 0x38, + 0x1, 0x8e, 0xd, 0x87, + 0x42, 0xf8, 0xe5, 0xb8, + 0xbe, 0xd8, 0xb4, 0x72, + 0xb7, 0x12, 0x54, 0x39, + 0xf9, 0x4, 0xe0, 0x88, + 0xe6, 0x2f, 0x71, 0xab, + 0x7b, 0xe5, 0x60, 0x83, + 0xc4, 0x1e, 0xbb, 0xc5, + 0xac, 0xc9, 0x4d, 0xef, + 0xc2, 0x33, 0xa7, 0x80, + 0xc, 0x5b, 0xf3, 0xc3, + 0x6e, 0x48, 0xfc, 0x67, + 0x4c, 0xdd, 0xf0, 0x32, + 0xd, 0x61, 0xdd, 0x88, + 0x47, 0x3e, 0xb, 0xb, + 0x5c, 0xc7, 0xd1, 0x9, + 0x90, 0x1e, 0xf8, 0x52, + 0x52, 0x9f, 0xd2, 0x5e, + 0xfb, 0xc6, 0x22, 0x69, + 0xe, 0x1f, 0xd1, 0x5a, + 0xfd, 0xc2, 0x8c, 0xa, + 0x23, 0x6a, 0x92, 0x6a, + 0xa9, 0x9e, 0x76, 0x5, + 0x65, 0x47, 0xe, 0xf5, + 0x66, 0x6, 0x47, 0xb9, + 0xa6, 0x1a, 0x17, 0xa2, + 0xe0, 0x39, 0xc, 0xee, + 0x59, 0xdd, 0x49, 0x56, + 0x9f, 0xd6, 0x60, 0xc3, + 0x41, 0xf3, 0x2e, 0xea, + 0x91, 0xa4, 0xf0, 0xf7, + 0xec, 0xfe, 0xec, 0x53, + 0x5, 0x34, 0xc, 0xac, + 0x4f, 0x24, 0x4e, 0x2f, + 0x5d, 0x5a, 0x1e, 0xb7, + 0x38, 0x67, 0xd, 0xd8, + 0x3e, 0x6d, 0x9c, 0x7f, + 0x61, 0xca, 0x69, 0xf2, + 0x6f, 0x59, 0xe9, 0x5c, + 0x58, 0xd6, 0xb0, 0x5e, + 0xb, 0xbc, 0xa, 0x5a, + 0xe0, 0x59, 0x8a, 0x3e, + 0xb4, 0xa8, 0xf5, 0xec, + 0x10, 0x3, 0xc5, 0x4e, + 0x71, 0x61, 0xce, 0xd2, + 0x2c, 0x37, 0xc4, 0x9c, + 0x91, 0xae, 0xf8, 0xea, + 0x85, 0xa8, 0x48, 0x90, + 0x65, 0x52, 0xeb, 0x46, + 0xac, 0x75, 0x84, 0x60, + 0x1e, 0x7a, 0x4d, 0x2f, + 0x7d, 0x13, 0x7d, 0xee, + 0x74, 0x4c, 0xc0, 0xa1, + 0x83, 0x85, 0x3d, 0x15, + 0x34, 0x36, 0xff, 0xba, + 0xdf, 0x47, 0x4b, 0x44, + 0x9a, 0x36, 0x8a, 0x47, + 0xac, 0xf, 0xa7, 0xca, + 0x89, 0xf5, 0xf9, 0x7, + 0x8, 0x77, 0xf5, 0x7d, + 0xc3, 0xb6, 0x1f, 0x47, + 0x3c, 0x5c, 0x5c, 0x71, + 0x93, 0x5c, 0x2b, 0x72, + 0xa3, 0x76, 0xb7, 0x3e, + 0xac, 0x41, 0x85, 0x58, + 0x51, 0x2d, 0x23, 0xdb, + 0x22, 0x1c, 0xe2, 0x2b, + 0x93, 0xd8, 0xa8, 0x57, + 0x8f, 0xc7, 0x9e, 0xcb, + 0x24, 0xfb, 0x3c, 0xb7, + 0x57, 0x68, 0x2a, 0xfb, + 0xde, 0xe1, 0x39, 0x8b, + 0x23, 0xbf, 0xe4, 0x74, + 0xec, 0x7, 0x4f, 0xf, + 0x24, 0x32, 0x3a, 0xb8 +}; + +char* sndirtroad_msg[2] = { + "You travel a bit towards the moon, you think that's the way to go. You" + " find a bear in the middle of the road sleeping seemingly in peace. " + "The way to the north is blocked by the bear.", + "You atravel a bit towards the moon, you KNOW that's the way to go. You" + " smell something weired along the way, but you don't know where it is " + "coming from. Smells like flesh rotting away..." +}; + +char* user_action_req_msgs[3] = { + "What are you going to do?" +}; + +const char* info_table[] = { + "ERROR", // 0 + "Invalid command!", // 1 + "You can't use that!", // 2 + NULL, // 3 + "You can't go that way!", // 4 + "YOU MAY ACT NOW!", // 5 + "There is nothing here..", // 6 + "it died", // 7 + "it survived", // 8 + "a bear blocks the way", // 9 + "it ran away...", // 10 + "it won't start", // 11 + "you can't type", // 12 + "you unlocked the door" // 13 +}; + +const char* action_table[NUM_ACTIONS] = { + "help", + "north", + "south", + "west", + "east", + "describe", + "use", + "inventory", + "search", + "take", +}; + +const char* room_table[] = { + "NOTHING", + "LONELY ROAD", + "S/N DIRT ROAD", + "FIREPLACE", + "E/W Street", + "OLD HOUSE", + "LIVING ROOM", + "ATTIC", + "BASEMENT", + "COMPUTER ROOM" +}; + +char* room_description_table[sizeof(room_table)/sizeof(const char*)] = { + "You stare into a void of nothingness. You see noone, you hear noone," + "you feel someone. You look around, and see nothing, yet " + "you are no less scared.", + "You are on the dead end of a lonely road. You look right and left of " + "you, but you cannot remember why you are here... You are terrified.", + NULL, + "You find a fireplace in the middle of the woods. A street leads to it " + "from the west. The fire in the middle of the place is still burning as" + " if someone had left in a hurry...", + "You travel down the road. It has no lights, but the moon shines bright" + ". The road ends with a house to your left. The houses door mat is in " + "the road. Its door is locked.", + "You enter the long hallway of the old house. It has doors on all walls" + ". The doors look a little weired because they are flat and don't have " + "a handle to pull.", + "You enter a large room with a few chairs and a tube TV inside it. In " + "the center there is a tile table with a vase and flowers on it. The " + "flowers are blooming.", + "You enter the attic of the house. It has a few books and some filers " + "with documents inside it. The filers are glued together. The books too" + ". You can't stand up straight.", + "You enter the basement. You find some potatoes in a corner and a " + "skeleton atop it. ", + "You enter a room which looks like you've traveled from an old house " + "to the campus of a university. There is a large machine witha sign " + "DIGITAL on it. It looks like a computer, though you've never seen one " + "in person before..." +}; + +bool room_visited_table[sizeof(room_table)/sizeof(const char*)]; + +uint8_t room_map_table[sizeof(room_table)/sizeof(const char*)] + [4] = { + /* NORTH, SOUTH, WEST, EAST */ + {0,0,0,0}, /* 0 nothing */ + {2,0,0,0}, /* 1 LONELY ROAD */ + {0,1,0,0}, /* 2 S/N DIRT ROAD */ + {0,2,4,0}, /* 3 FIREPLACE */ + {0,0,0,3}, /* 4 E/W STREET */ + {7,4,9,6}, /* 5 OLD HOUSE */ + {8,0,5,0}, /* 6 LIVING ROOM */ + {0,5,0,0}, /* 7 ATTIC */ + {0,6,0,0}, /* 8 BASEMENT */ + {0,0,0,5} /* 9 COMPUTERROOM */ +}; + +const char* item_table[NUM_ITEMS] = { + "FLOPPY DISK", /* 0 */ + "SCREWDRIVER", /* 1 */ + "KEYBOARD", /* 2 */ + "SAUSAGE", /* 3 */ + "FLESH", /* 4 */ + "KEY", /* 5 */ + "PISTOL" /* 6 */ +}; + +bool inventory[sizeof(item_table)/sizeof(const char*)]; + + +int8_t item_room_map[NUM_ROOMS] = { + -1, /* 0 NOTHING */ + ITEM_PISTOL, /* 1 LONELY ROAD */ + ITEM_SAUSAGE, /* 2 S/N DIRT ROAD */ + -1, /* 3 FIREPLACE */ + ITEM_KEY, /* 4 E/W STREET*/ + ITEM_SCREWDRIVER, /* 5 OLD HOUSE */ + -1, /* 6 LIVING ROOM */ + ITEM_KEYBOARD, /* 7 ATTIC */ + ITEM_FLOPPY, /* 8 BASEMENT */ + -1 /* 9 COMPUTERROOM */ +}; +const struct tone_t * room_track_map[NUM_ROOMS] = { + intro_track, + lonely_road_track, + computer_room_track, + lonely_road_track, + computer_room_track +};