# Note: this are my paths to cc65 as there is no gentoo ebuild, sorry for that.
# Please use the path below if you've installed cc65 system-wide
-CC=~/customSoftware/cc65-2.11.0/src/cc65/cc65 -I ~/customSoftware/cc65-2.11.0/include -O
+CC=~/customSoftware/cc65-2.11.0/src/cc65/cc65 -I ~/customSoftware/cc65-2.11.0/include
CA=~/customSoftware/cc65-2.11.0/src/ca65/ca65
CL=~/customSoftware/cc65-2.11.0/src/cl65/cl65
# CC=cc65
# CA=ca65
# CL=cl65
-%.o: %.c
- ${CC} -t c128 $<
- ${CA} -t c128 $$(basename $< .c).s
+src/%.o: src/%.c include/%.h
+ ${CC} -I include -t c128 $<
+ ${CA} -I include -t c128 src/$$(basename $< .c).s
-all: config.o kasse.o general.o credit_manager.o time.o
+all: src/config.o src/kasse.o src/general.o src/credit_manager.o src/time.o
# See above, please just kill the PATH-definition
cp /tmp/cc65/lib/c128* .
- PATH=${PATH}:~/customSoftware/cc65-2.11.0/src/ld65:/tmp/cc65/lib ${CL} -t c128 *.o -o kasse
+ PATH=${PATH}:~/customSoftware/cc65-2.11.0/src/ld65:/tmp/cc65/lib ${CL} -t c128 -O src/*.o -o kasse
package: all
c1541 -attach kasse.d64 -delete state || exit 0
c1541 -attach test.d64 -write items || exit 0
clean:
- rm -rf *.o *.s
+ rm -rf src/*.o src/*.s
dist-clean: clean
rm kasse test
-
+++ /dev/null
-#define _IS_CONFIG_C
-
-#include <stdlib.h>
-#include <conio.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include "general.h"
-#include "config.h"
-
-/* undocumented function which scratches files */
-unsigned char __fastcall__ _sysremove(const char *name);
-
-unsigned long int money = 0;
-unsigned long int items_sold = 0;
-BYTE printer_port = 4;
-static bool files_existing = false;
-struct status_array_t status;
-struct credits_array_t credits;
-
-/*
- * Checks if items/credits-files are existing to avoid having to recover
- * the error state of the drive (we'd have to if we would just access the
- * files directly)
- *
- */
-bool lookup_needed_files() {
- BYTE lfn = 8;
- BYTE files_existing = 0;
- struct cbm_dirent *dirent;
-
- if (cbm_opendir(lfn, (BYTE)8) != 0) {
- cprintf("could not open directory\r\n");
- return false;
- }
- while (cbm_readdir(lfn, dirent) == 0)
- if ( strcasecmp(dirent->name, "items") == 0 ||
- strcasecmp(dirent->name, "credits") == 0)
- files_existing++;
- cbm_closedir(lfn);
- return (files_existing >= 2);
-}
-
-void load_items() {
- if (files_existing)
- cbm_load("items", (BYTE)8, &status);
-}
-
-void load_credits() {
- if (files_existing)
- cbm_load("credits", (BYTE)8, &credits);
-}
-
-void save_items() {
- if (files_existing)
- _sysremove("items");
- cbm_save("items", (BYTE)8, &status, sizeof(struct status_array_t));
- files_existing = true;
-}
-
-void save_credits() {
- if (files_existing)
- _sysremove("credits");
- cbm_save("credits", (BYTE)8, &credits, sizeof(struct credits_array_t));
- files_existing = true;
-}
-
-void load_config() {
- files_existing = lookup_needed_files();
-}
+++ /dev/null
-#include "general.h"
-
-#ifndef CONFIG_H_
-#define CONFIG_H_
-
-#define MAX_ITEMS 15
-#define MAX_CREDIT_ITEMS 75
-
-/* Eingenommes Geld in Cent */
-extern unsigned long int money;
-extern unsigned long int items_sold;
-extern BYTE printer_port;
-
-
-/* Datenstruktur der verkauften Einträge */
-struct status_t {
- char item_name[10];
- /* Wieviel kostet der Eintrag (in Cent)? */
- unsigned int price;
- /* Wie oft wurde er verkauft */
- unsigned int times_sold;
-};
-
-struct status_array_t {
- BYTE num_items;
- struct status_t status[MAX_ITEMS];
-};
-
-/* Datenstruktur für die Guthaben */
-struct credits_t {
- char nickname[11];
- /* Guthaben (in Cent) */
- unsigned int credit;
-};
-
-struct credits_array_t {
- BYTE num_items;
- struct credits_t credits[MAX_CREDIT_ITEMS];
-};
-
-#ifndef _IS_CONFIG_C
-extern struct status_array_t status;
-extern struct credits_array_t credits;
-#endif
-
-/* Lädt Dinge wie die Druckeradresse */
-void load_config();
-void load_items();
-void load_credits();
-//void dump_state();
-
-void save_items();
-void save_credits();
-#endif /*CONFIG_H_*/
+++ /dev/null
-#include <conio.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "config.h"
-#include "general.h"
-
-static char *filter = NULL;
-static BYTE filter_len;
-
-static void print_credit_screen() {
- BYTE i = 0;
- clrscr();
- cprintf("C128-Kassenprogramm: Credit Manager\r\n\r\n");
- for (; i < credits.num_items; ++i)
- if (filter == NULL || strncmp(credits.credits[i].nickname, filter, filter_len) == 0)
- cprintf("Guthaben %s: %d Cents\r\n", credits.credits[i].nickname, credits.credits[i].credit);
- cprintf("\r\nBefehle: n) Neues Guthaben f) Filtern z) Zurueck\r\n");
-}
-
-/* Guthabenverwalter */
-void credit_manager() {
- int negative = 1;
- char *c, *nickname, *credits_input;
- /* credits_int is a stupid name, but overlaps with struct credits_t credits; else */
- int credits_int;
- while (1) {
- print_credit_screen();
- c = get_input();
- if (c == NULL || *c == '\0')
- continue;
- if (*c == 'n') {
- cprintf("\r\nGuthaben eingeben:\r\n");
- credits_input = get_input();
-
- if (credits_input == NULL || credits_input[0] == '\0')
- continue;
- else if (credits_input[0] == '-') {
- negative = -1;
- ++credits_input;
- }
- credits_int = atoi(credits_input) * negative;
- if (credits_int > 0) {
- cprintf("Nickname eingeben:\r\n");
- nickname = get_input();
- if (nickname == NULL || nickname[0] == '\0')
- continue;
- strncpy(credits.credits[credits.num_items].nickname, nickname, 9);
- credits.credits[credits.num_items].credit = credits_int;
- ++credits.num_items;
- }
- } else if (*c == 'f') {
- cprintf("Filter eingeben:\r\n");
- filter = get_input();
- if (filter == NULL || *filter == 32 || (filter_len = strlen(filter)) == 0)
- filter = NULL;
- } else if (*c == 'z' || *c == 'q')
- break;
- }
-}
+++ /dev/null
-#ifndef CREDIT_MANAGER_H_
-#define CREDIT_MANAGER_H_
-void credit_manager();
-#endif
+++ /dev/null
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <conio.h>
-
-#include "general.h"
-
-/*
- * Liest (maximal 31) Zeichen ein, bis Enter gedrückt wird.
- * Vorsicht: Es wird ein statischer Buffer benutzt, sodass man
- * das Ergebnis via strdup() retten muss, bevor man get_input()
- * erneut aufruft
- *
- */
-char *get_input() {
- BYTE i = 0;
- static char output[32];
- BYTE c;
- memset(output, '\0', 32);
- while (1) {
- if (i == 31)
- break;
- c = getchar();
- if (c == 13)
- break;
- else output[i++] = c;
- }
- return output;
-}
-
-char *format_euro(char *s, int maxlen, int cent){
- int tmp = cent;
- int len = strlen(",EUR");
- while ((tmp /= 10) > 0)
- ++len;
- if (len >= maxlen)
- return NULL;
- sprintf(s, "%d,%dEUR", cent / 100, cent % 100);
- return s;
-}
-
-void c128_perror(BYTE c, char *msg) {
- cprintf("\r\nError (Code %d) while: %s\r\nOS Error = %d\r\n", c, msg, _oserror);
-}
+++ /dev/null
-#ifndef GENERAL_H_
-#define GENERAL_H_
-typedef unsigned char BYTE;
-char *get_input();
-char * format_euro(char * s, int maxlen, int cent);
-void c128_perror(BYTE, char*);
-extern BYTE _oserror;
-#define POKE(addr,val) (*(unsigned char*) (addr) = (val))
-#define POKEW(addr,val) (*(unsigned*) (addr) = (val))
-#define PEEK(addr) (*(unsigned char*) (addr))
-#define PEEKW(addr) (*(unsigned*) (addr))
-#endif /*GENERAL_H_*/
--- /dev/null
+#include "general.h"
+
+#ifndef CONFIG_H_
+#define CONFIG_H_
+
+#define MAX_ITEMS 15
+#define MAX_CREDIT_ITEMS 75
+
+/* Eingenommes Geld in Cent */
+extern unsigned long int money;
+extern unsigned long int items_sold;
+extern BYTE printer_port;
+
+
+/* Datenstruktur der verkauften Einträge */
+struct status_t {
+ char item_name[10];
+ /* Wieviel kostet der Eintrag (in Cent)? */
+ unsigned int price;
+ /* Wie oft wurde er verkauft */
+ unsigned int times_sold;
+};
+
+struct status_array_t {
+ BYTE num_items;
+ struct status_t status[MAX_ITEMS];
+};
+
+/* Datenstruktur für die Guthaben */
+struct credits_t {
+ char nickname[11];
+ /* Guthaben (in Cent) */
+ unsigned int credit;
+};
+
+struct credits_array_t {
+ BYTE num_items;
+ struct credits_t credits[MAX_CREDIT_ITEMS];
+};
+
+#ifndef _IS_CONFIG_C
+extern struct status_array_t status;
+extern struct credits_array_t credits;
+#endif
+
+/* Lädt Dinge wie die Druckeradresse */
+void load_config();
+void load_items();
+void load_credits();
+//void dump_state();
+
+void save_items();
+void save_credits();
+#endif /*CONFIG_H_*/
--- /dev/null
+#ifndef CREDIT_MANAGER_H_
+#define CREDIT_MANAGER_H_
+void credit_manager();
+#endif
--- /dev/null
+#ifndef GENERAL_H_
+#define GENERAL_H_
+typedef unsigned char BYTE;
+char *get_input();
+char * format_euro(char * s, int maxlen, int cent);
+void c128_perror(BYTE, char*);
+extern BYTE _oserror;
+#define POKE(addr,val) (*(unsigned char*) (addr) = (val))
+#define POKEW(addr,val) (*(unsigned*) (addr) = (val))
+#define PEEK(addr) (*(unsigned char*) (addr))
+#define PEEKW(addr) (*(unsigned*) (addr))
+#endif /*GENERAL_H_*/
--- /dev/null
+BYTE printing = 1;
--- /dev/null
+#ifndef TIME_H_
+#define TIME_H_
+void set_time();
+char *get_time();
+#endif
+++ /dev/null
-#include <stdio.h>
-#include <conio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <cbm.h>
-
-#include "general.h"
-#include "config.h"
-#include "kasse.h"
-#include "credit_manager.h"
-#include "time.h"
-// drucker 4 oder 5
-// graphic 4,0,10
-
-char print_buffer[81];
-
-/* Hauptbildschirm ausgeben */
-static void print_screen() {
- BYTE i = 0;
- char *time = get_time();
- char profit[10];
- clrscr();
- if (format_euro(profit, 10, money) == NULL) {
- cprintf("Einname %ld konnte nicht umgerechnet werden\r\n", money);
- exit(1);
- }
- cprintf("C128-Kassenprogramm (phil_fry, sECuRE, sur5r)\r\
-\r\nUhrzeit: %s (wird nicht aktualisiert)\r\
-Eingenommen: %s, Verkauft: %ld Flaschen, Drucken: %s\r\n\r\n",
- time, profit, items_sold, (printing == 1 ? "ein" : "aus"));
- for (; i < status.num_items; ++i)
- cprintf("Eintrag %x: %s (%d Cents, %d mal verkauft)\r\n",
- i, status.status[i].item_name, status.status[i].price, status.status[i].times_sold);
- cprintf("\r\nBefehle: s) Daten sichern d) Drucken umschalten\r\
-g) Guthabenverwaltung z) Zeit setzen\r\
-n) Neues Getraenk\r\n");
-}
-
-static void log_file(const char *s) {
- BYTE c = cbm_open((BYTE)8, (BYTE)8, (BYTE)1, "log");
- if (c != 0) {
- c128_perror(c, "cbm_open(log)");
- save_items();
- save_credits();
- exit(1);
- }
- c = cbm_write((BYTE)8, s, strlen(s));
- if (c != strlen(s)) {
- cprintf("Could not save logfile, please make sure the floppy is not full!\n");
- save_items();
- save_credits();
- exit(1);
- }
- cbm_close((BYTE)8);
-}
-
-/* Druckt eine entsprechende Zeile aus */
-static void print_log(BYTE n, int einheiten, char *nickname) {
- BYTE c;
- char *time = get_time();
- char price[10];
- /* Format:
- Transaction-ID (Anzahl verkaufter Einträge, inklusive des zu druckenden!)
- Uhrzeit
- Eintragname (= Getränk)
- Preis (in Cents)
- Anzahl
- Nickname (falls es vom Guthaben abgezogen wird)
- */
- if (format_euro(price, 10, status.status[n].price) == NULL) {
- cprintf("Preis %d konnte nicht umgerechnet werden\r\n", status.status[n].price);
- exit(1);
- }
-
- sprintf(print_buffer, "[%lu] %s - %s - %s - %d - an %s\r\n",
- items_sold, time, status.status[n].item_name, price,
- einheiten, (nickname != NULL ? nickname : "Unbekannt"));
- c = cbm_open((BYTE)4, (BYTE)4, (BYTE)0, NULL);
- if (c != 0) {
- c128_perror(c, "cbm_open(printer)");
- save_items();
- save_credits();
- exit(1);
- }
- c = cbm_write((BYTE)4, print_buffer, strlen(print_buffer));
- if (c != strlen(print_buffer)) {
- c128_perror(c, "write(printer)");
- save_items();
- save_credits();
- exit(1);
- }
- cbm_close((BYTE)4);
- log_file(print_buffer);
-}
-
-/* Dialog, der einen durch's Abrechnen der Einträge führt */
-void buy(BYTE n) {
- int negative = 1;
- char entered[5] = {'1', 0, 0, 0, 0};
- BYTE i = 0, matches = 0;
- BYTE c, nickname_len;
- int einheiten;
- char *nickname;
-
- if (status.status[n].item_name == NULL) {
- cprintf("FEHLER: Diese Einheit existiert nicht.\r\n");
- return;
- }
- cprintf("Wieviel Einheiten \"%s\"? [1] \r\n", status.status[n].item_name);
- while (1) {
- c = getchar();
- if (c == 13)
- break;
- else if (c == 27) {
- cprintf("Kauf abgebrochen, druecke RETURN...\r\n");
- get_input();
- return;
- } else if (c == '-' && i == 0)
- negative = -1;
- else if (c > 47 && c < 58)
- entered[i++] = c;
- }
- einheiten = atoi(entered) * negative;
- cprintf("\r\nAuf ein Guthaben kaufen? Wenn ja, Nickname eingeben:\r\n");
- nickname = get_input();
- if (nickname != NULL && *nickname != '\0' && *nickname != 32) {
- nickname_len = strlen(nickname);
- /* go through credits and remove the amount of money or set nickname
- * to NULL if no such credit could be found */
- for (c = 0; c < credits.num_items; ++c)
- if (strncmp(nickname, credits.credits[c].nickname, nickname_len) == 0) {
- if (credits.credits[c].credit < (status.status[n].price * einheiten)) {
- cprintf("Sorry, %s hat nicht genug Geld :-(\r\n", nickname);
- return;
- }
- /* Geld abziehen */
- credits.credits[c].credit -= (status.status[n].price * einheiten);
- cprintf("\r\nVerbleibendes Guthaben fuer %s: %d Cents. Druecke RETURN...\r\n",
- nickname, credits.credits[c].credit);
- get_input();
- matches++;
- break;
- }
- if (matches == 0) {
- cprintf("\r\nNickname nicht gefunden in der Guthabenverwaltung! Abbruch, druecke RETURN...\r\n");
- get_input();
- return;
- }
- } else {
- /* Ensure that nickname is NULL if it's empty because it's used in print_log */
- nickname = NULL;
- }
- status.status[n].times_sold += einheiten;
- money += status.status[n].price * einheiten;
- items_sold += einheiten;
- if (printing == 1)
- print_log(n, einheiten, nickname);
-}
-
-void set_time_interactive() {
- BYTE part[3] = {'0', '0', '\0'};
- BYTE tp1, tp2, tp3;
- char *time_input, *time;
- cprintf("Gib die aktuelle Uhrzeit ein (Format HHMMSS):\r\n");
- time_input = get_input();
- part[0] = time_input[0];
- part[1] = time_input[1];
- tp1 = atoi(part);
- part[0] = time_input[2];
- part[1] = time_input[3];
- tp2 = atoi(part);
- part[0] = time_input[4];
- part[1] = time_input[5];
- tp3 = atoi(part);
- set_time(tp1, tp2, tp3);
-
- time = get_time();
- cprintf("Zeit gesetzt: %s\r\n", time);
-}
-
-int main() {
- char *c;
- toggle_videomode();
- /* Zeit erstmalig setzen */
- set_time_interactive();
- POKE(216, 255);
- /* Variablen zurechtbiegen */
- credits.num_items = 0;
- status.num_items = 0;
- /* Konfigurationsdatei laden */
- load_config();
- /* Einträge (=Getränke) und Zustand laden */
- load_items();
- /* Guthaben laden */
- load_credits();
- while (1) {
- /* Bildschirm anzeigen */
- print_screen();
- /* Tastatureingaben abfragen */
- c = get_input();
- /* und eventuell weitere Dialoge anzeigen */
- if (*c > 47 && *c < 58)
- buy((*c) - 48);
- else if (*c == 's') {
- /* Zustandsdatei schreiben */
- save_items();
- save_credits();
- cprintf("Statefile/Creditfile gesichert, druecke RETURN...\r\n");
- get_input();
- } else if (*c == 'd') {
- /* Drucken an- oder ausschalten */
- printing = (printing == 1 ? 0 : 1);
- cprintf("Drucken ist nun %s, druecke RETURN...\r\n",
- (printing == 1 ? "eingeschaltet" : "ausgeschaltet"));
- get_input();
- } else if (*c == 'g') {
- /* Guthabenverwalter aufrufen */
- credit_manager();
- } else if (*c == 'z') {
- /* Zeit setzen */
- set_time_interactive();
- } else if (*c == 'n') {
- strcpy(status.status[status.num_items].item_name, "mate");
- status.status[status.num_items].price = 23;
- status.status[status.num_items].times_sold = 5;
- status.num_items++;
- } else if (*c == 'q')
- break;
- }
- cprintf("BYEBYE\r\n");
-}
+++ /dev/null
-BYTE printing = 1;
--- /dev/null
+#define _IS_CONFIG_C
+
+#include <stdlib.h>
+#include <conio.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include "general.h"
+#include "config.h"
+
+/* undocumented function which scratches files */
+unsigned char __fastcall__ _sysremove(const char *name);
+
+unsigned long int money = 0;
+unsigned long int items_sold = 0;
+BYTE printer_port = 4;
+static bool files_existing = false;
+struct status_array_t status;
+struct credits_array_t credits;
+
+/*
+ * Checks if items/credits-files are existing to avoid having to recover
+ * the error state of the drive (we'd have to if we would just access the
+ * files directly)
+ *
+ */
+bool lookup_needed_files() {
+ BYTE lfn = 8;
+ BYTE files_existing = 0;
+ struct cbm_dirent *dirent;
+
+ if (cbm_opendir(lfn, (BYTE)8) != 0) {
+ cprintf("could not open directory\r\n");
+ return false;
+ }
+ while (cbm_readdir(lfn, dirent) == 0)
+ if ( strcasecmp(dirent->name, "items") == 0 ||
+ strcasecmp(dirent->name, "credits") == 0)
+ files_existing++;
+ cbm_closedir(lfn);
+ return (files_existing >= 2);
+}
+
+void load_items() {
+ if (files_existing)
+ cbm_load("items", (BYTE)8, &status);
+}
+
+void load_credits() {
+ if (files_existing)
+ cbm_load("credits", (BYTE)8, &credits);
+}
+
+void save_items() {
+ if (files_existing)
+ _sysremove("items");
+ cbm_save("items", (BYTE)8, &status, sizeof(struct status_array_t));
+ files_existing = true;
+}
+
+void save_credits() {
+ if (files_existing)
+ _sysremove("credits");
+ cbm_save("credits", (BYTE)8, &credits, sizeof(struct credits_array_t));
+ files_existing = true;
+}
+
+void load_config() {
+ files_existing = lookup_needed_files();
+}
--- /dev/null
+#include <conio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "general.h"
+
+static char *filter = NULL;
+static BYTE filter_len;
+
+static void print_credit_screen() {
+ BYTE i = 0;
+ clrscr();
+ cprintf("C128-Kassenprogramm: Credit Manager\r\n\r\n");
+ for (; i < credits.num_items; ++i)
+ if (filter == NULL || strncmp(credits.credits[i].nickname, filter, filter_len) == 0)
+ cprintf("Guthaben %s: %d Cents\r\n", credits.credits[i].nickname, credits.credits[i].credit);
+ cprintf("\r\nBefehle: n) Neues Guthaben f) Filtern z) Zurueck\r\n");
+}
+
+/* Guthabenverwalter */
+void credit_manager() {
+ int negative = 1;
+ char *c, *nickname, *credits_input;
+ /* credits_int is a stupid name, but overlaps with struct credits_t credits; else */
+ int credits_int;
+ while (1) {
+ print_credit_screen();
+ c = get_input();
+ if (c == NULL || *c == '\0')
+ continue;
+ if (*c == 'n') {
+ cprintf("\r\nGuthaben eingeben:\r\n");
+ credits_input = get_input();
+
+ if (credits_input == NULL || credits_input[0] == '\0')
+ continue;
+ else if (credits_input[0] == '-') {
+ negative = -1;
+ ++credits_input;
+ }
+ credits_int = atoi(credits_input) * negative;
+ if (credits_int > 0) {
+ cprintf("Nickname eingeben:\r\n");
+ nickname = get_input();
+ if (nickname == NULL || nickname[0] == '\0')
+ continue;
+ strncpy(credits.credits[credits.num_items].nickname, nickname, 9);
+ credits.credits[credits.num_items].credit = credits_int;
+ ++credits.num_items;
+ }
+ } else if (*c == 'f') {
+ cprintf("Filter eingeben:\r\n");
+ filter = get_input();
+ if (filter == NULL || *filter == 32 || (filter_len = strlen(filter)) == 0)
+ filter = NULL;
+ } else if (*c == 'z' || *c == 'q')
+ break;
+ }
+}
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <conio.h>
+
+#include "general.h"
+
+/*
+ * Liest (maximal 31) Zeichen ein, bis Enter gedrückt wird.
+ * Vorsicht: Es wird ein statischer Buffer benutzt, sodass man
+ * das Ergebnis via strdup() retten muss, bevor man get_input()
+ * erneut aufruft
+ *
+ */
+char *get_input() {
+ BYTE i = 0;
+ static char output[32];
+ BYTE c;
+ memset(output, '\0', 32);
+ while (1) {
+ if (i == 31)
+ break;
+ c = getchar();
+ if (c == 13)
+ break;
+ else output[i++] = c;
+ }
+ return output;
+}
+
+char *format_euro(char *s, int maxlen, int cent){
+ int tmp = cent;
+ int len = strlen(",EUR");
+ while ((tmp /= 10) > 0)
+ ++len;
+ if (len >= maxlen)
+ return NULL;
+ sprintf(s, "%d,%dEUR", cent / 100, cent % 100);
+ return s;
+}
+
+void c128_perror(BYTE c, char *msg) {
+ cprintf("\r\nError (Code %d) while: %s\r\nOS Error = %d\r\n", c, msg, _oserror);
+}
--- /dev/null
+#include <stdio.h>
+#include <conio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cbm.h>
+
+#include "general.h"
+#include "config.h"
+#include "kasse.h"
+#include "credit_manager.h"
+#include "time.h"
+// drucker 4 oder 5
+// graphic 4,0,10
+
+char print_buffer[81];
+
+/* Hauptbildschirm ausgeben */
+static void print_screen() {
+ BYTE i = 0;
+ char *time = get_time();
+ char profit[10];
+ clrscr();
+ if (format_euro(profit, 10, money) == NULL) {
+ cprintf("Einname %ld konnte nicht umgerechnet werden\r\n", money);
+ exit(1);
+ }
+ cprintf("C128-Kassenprogramm (phil_fry, sECuRE, sur5r)\r\
+\r\nUhrzeit: %s (wird nicht aktualisiert)\r\
+Eingenommen: %s, Verkauft: %ld Flaschen, Drucken: %s\r\n\r\n",
+ time, profit, items_sold, (printing == 1 ? "ein" : "aus"));
+ for (; i < status.num_items; ++i)
+ cprintf("Eintrag %x: %s (%d Cents, %d mal verkauft)\r\n",
+ i, status.status[i].item_name, status.status[i].price, status.status[i].times_sold);
+ cprintf("\r\nBefehle: s) Daten sichern d) Drucken umschalten\r\
+g) Guthabenverwaltung z) Zeit setzen\r\
+n) Neues Getraenk\r\n");
+}
+
+static void log_file(const char *s) {
+ BYTE c = cbm_open((BYTE)8, (BYTE)8, (BYTE)1, "log");
+ if (c != 0) {
+ c128_perror(c, "cbm_open(log)");
+ save_items();
+ save_credits();
+ exit(1);
+ }
+ c = cbm_write((BYTE)8, s, strlen(s));
+ if (c != strlen(s)) {
+ cprintf("Could not save logfile, please make sure the floppy is not full!\n");
+ save_items();
+ save_credits();
+ exit(1);
+ }
+ cbm_close((BYTE)8);
+}
+
+/* Druckt eine entsprechende Zeile aus */
+static void print_log(BYTE n, int einheiten, char *nickname) {
+ BYTE c;
+ char *time = get_time();
+ char price[10];
+ /* Format:
+ Transaction-ID (Anzahl verkaufter Einträge, inklusive des zu druckenden!)
+ Uhrzeit
+ Eintragname (= Getränk)
+ Preis (in Cents)
+ Anzahl
+ Nickname (falls es vom Guthaben abgezogen wird)
+ */
+ if (format_euro(price, 10, status.status[n].price) == NULL) {
+ cprintf("Preis %d konnte nicht umgerechnet werden\r\n", status.status[n].price);
+ exit(1);
+ }
+
+ sprintf(print_buffer, "[%lu] %s - %s - %s - %d - an %s\r\n",
+ items_sold, time, status.status[n].item_name, price,
+ einheiten, (nickname != NULL ? nickname : "Unbekannt"));
+ c = cbm_open((BYTE)4, (BYTE)4, (BYTE)0, NULL);
+ if (c != 0) {
+ c128_perror(c, "cbm_open(printer)");
+ save_items();
+ save_credits();
+ exit(1);
+ }
+ c = cbm_write((BYTE)4, print_buffer, strlen(print_buffer));
+ if (c != strlen(print_buffer)) {
+ c128_perror(c, "write(printer)");
+ save_items();
+ save_credits();
+ exit(1);
+ }
+ cbm_close((BYTE)4);
+ log_file(print_buffer);
+}
+
+/* Dialog, der einen durch's Abrechnen der Einträge führt */
+void buy(BYTE n) {
+ int negative = 1;
+ char entered[5] = {'1', 0, 0, 0, 0};
+ BYTE i = 0, matches = 0;
+ BYTE c, nickname_len;
+ int einheiten;
+ char *nickname;
+
+ if (status.status[n].item_name == NULL) {
+ cprintf("FEHLER: Diese Einheit existiert nicht.\r\n");
+ return;
+ }
+ cprintf("Wieviel Einheiten \"%s\"? [1] \r\n", status.status[n].item_name);
+ while (1) {
+ c = getchar();
+ if (c == 13)
+ break;
+ else if (c == 27) {
+ cprintf("Kauf abgebrochen, druecke RETURN...\r\n");
+ get_input();
+ return;
+ } else if (c == '-' && i == 0)
+ negative = -1;
+ else if (c > 47 && c < 58)
+ entered[i++] = c;
+ }
+ einheiten = atoi(entered) * negative;
+ cprintf("\r\nAuf ein Guthaben kaufen? Wenn ja, Nickname eingeben:\r\n");
+ nickname = get_input();
+ if (nickname != NULL && *nickname != '\0' && *nickname != 32) {
+ nickname_len = strlen(nickname);
+ /* go through credits and remove the amount of money or set nickname
+ * to NULL if no such credit could be found */
+ for (c = 0; c < credits.num_items; ++c)
+ if (strncmp(nickname, credits.credits[c].nickname, nickname_len) == 0) {
+ if (credits.credits[c].credit < (status.status[n].price * einheiten)) {
+ cprintf("Sorry, %s hat nicht genug Geld :-(\r\n", nickname);
+ return;
+ }
+ /* Geld abziehen */
+ credits.credits[c].credit -= (status.status[n].price * einheiten);
+ cprintf("\r\nVerbleibendes Guthaben fuer %s: %d Cents. Druecke RETURN...\r\n",
+ nickname, credits.credits[c].credit);
+ get_input();
+ matches++;
+ break;
+ }
+ if (matches == 0) {
+ cprintf("\r\nNickname nicht gefunden in der Guthabenverwaltung! Abbruch, druecke RETURN...\r\n");
+ get_input();
+ return;
+ }
+ } else {
+ /* Ensure that nickname is NULL if it's empty because it's used in print_log */
+ nickname = NULL;
+ }
+ status.status[n].times_sold += einheiten;
+ money += status.status[n].price * einheiten;
+ items_sold += einheiten;
+ if (printing == 1)
+ print_log(n, einheiten, nickname);
+}
+
+void set_time_interactive() {
+ BYTE part[3] = {'0', '0', '\0'};
+ BYTE tp1, tp2, tp3;
+ char *time_input, *time;
+ cprintf("Gib die aktuelle Uhrzeit ein (Format HHMMSS):\r\n");
+ time_input = get_input();
+ part[0] = time_input[0];
+ part[1] = time_input[1];
+ tp1 = atoi(part);
+ part[0] = time_input[2];
+ part[1] = time_input[3];
+ tp2 = atoi(part);
+ part[0] = time_input[4];
+ part[1] = time_input[5];
+ tp3 = atoi(part);
+ set_time(tp1, tp2, tp3);
+
+ time = get_time();
+ cprintf("Zeit gesetzt: %s\r\n", time);
+}
+
+int main() {
+ char *c;
+ toggle_videomode();
+ /* Zeit erstmalig setzen */
+ set_time_interactive();
+ POKE(216, 255);
+ /* Variablen zurechtbiegen */
+ credits.num_items = 0;
+ status.num_items = 0;
+ /* Konfigurationsdatei laden */
+ load_config();
+ /* Einträge (=Getränke) und Zustand laden */
+ load_items();
+ /* Guthaben laden */
+ load_credits();
+ while (1) {
+ /* Bildschirm anzeigen */
+ print_screen();
+ /* Tastatureingaben abfragen */
+ c = get_input();
+ /* und eventuell weitere Dialoge anzeigen */
+ if (*c > 47 && *c < 58)
+ buy((*c) - 48);
+ else if (*c == 's') {
+ /* Zustandsdatei schreiben */
+ save_items();
+ save_credits();
+ cprintf("Statefile/Creditfile gesichert, druecke RETURN...\r\n");
+ get_input();
+ } else if (*c == 'd') {
+ /* Drucken an- oder ausschalten */
+ printing = (printing == 1 ? 0 : 1);
+ cprintf("Drucken ist nun %s, druecke RETURN...\r\n",
+ (printing == 1 ? "eingeschaltet" : "ausgeschaltet"));
+ get_input();
+ } else if (*c == 'g') {
+ /* Guthabenverwalter aufrufen */
+ credit_manager();
+ } else if (*c == 'z') {
+ /* Zeit setzen */
+ set_time_interactive();
+ } else if (*c == 'n') {
+ strcpy(status.status[status.num_items].item_name, "mate");
+ status.status[status.num_items].price = 23;
+ status.status[status.num_items].times_sold = 5;
+ status.num_items++;
+ } else if (*c == 'q')
+ break;
+ }
+ cprintf("BYEBYE\r\n");
+}
--- /dev/null
+#include <peekpoke.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "general.h"
+
+char *get_time() {
+ long int h = PEEK(0x00A0) * 65536,
+ m = PEEK(0x00A1) * 256,
+ s = PEEK(0x00A2);
+ static char buffer[9];
+ BYTE hrs, min;
+ h = (h + m + s) / 60;
+ hrs = (h / 3600);
+ h -= (hrs * 3600);
+ min = (h / 60);
+ h -= (min * 60);
+ sprintf(buffer, "%02d:%02d:%02d", hrs, min, (int)h);
+ return buffer;
+}
+
+void set_time(BYTE hrs, min, sec) {
+ long int added = ((long int)sec + ((long int)min * (long int)60) + ((long int)hrs * (long int)3600)) * (long int)60;
+ POKE(0x00A0, (BYTE)(added / 65536));
+ POKE(0x00A1, (BYTE)(added / 256));
+ POKE(0x00A2, (BYTE)added);
+}
+++ /dev/null
-#include <stdio.h>
-#include <conio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "general.h"
-#include "config.h"
-#include "kasse.h"
-#include "credit_manager.h"
-
-int main(){
- BYTE i=0;
- char euro[10];
- load_items();
- load_state();
- for (i=0; i < num_items; ++i) {
- cprintf("%x: %s (%s, %d mal)\n", i, status[i].item_name, format_euro(euro, 9, status[i].price), status[i].times_sold);
- status[i].times_sold+=10;
- }
-
- save_state();
- load_items();
- load_state();
- for (i=0; i < num_items; ++i) {
- cprintf("%x: %s (%s, %d mal)\n", i, status[i].item_name, format_euro(euro, 9, status[i].price), status[i].times_sold);
- }
-
- cprintf("strlen(%s)==%d\n", status[1].item_name, strlen(status[1].item_name));
- cprintf("%d %d %d\n", status[1].item_name[0], '\r', '\n');
-}
--- /dev/null
+#include <stdio.h>
+#include <conio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "general.h"
+#include "config.h"
+#include "kasse.h"
+#include "credit_manager.h"
+
+int main(){
+ BYTE i=0;
+ char euro[10];
+ load_items();
+ load_state();
+ for (i=0; i < num_items; ++i) {
+ cprintf("%x: %s (%s, %d mal)\n", i, status[i].item_name, format_euro(euro, 9, status[i].price), status[i].times_sold);
+ status[i].times_sold+=10;
+ }
+
+ save_state();
+ load_items();
+ load_state();
+ for (i=0; i < num_items; ++i) {
+ cprintf("%x: %s (%s, %d mal)\n", i, status[i].item_name, format_euro(euro, 9, status[i].price), status[i].times_sold);
+ }
+
+ cprintf("strlen(%s)==%d\n", status[1].item_name, strlen(status[1].item_name));
+ cprintf("%d %d %d\n", status[1].item_name[0], '\r', '\n');
+}
+++ /dev/null
-#include <peekpoke.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include "general.h"
-
-char *get_time() {
- long int h = PEEK(0x00A0) * 65536,
- m = PEEK(0x00A1) * 256,
- s = PEEK(0x00A2);
- static char buffer[9];
- BYTE hrs, min;
- h = (h + m + s) / 60;
- hrs = (h / 3600);
- h -= (hrs * 3600);
- min = (h / 60);
- h -= (min * 60);
- sprintf(buffer, "%02d:%02d:%02d", hrs, min, (int)h);
- return buffer;
-}
-
-void set_time(BYTE hrs, min, sec) {
- long int added = ((long int)sec + ((long int)min * (long int)60) + ((long int)hrs * (long int)3600)) * (long int)60;
- POKE(0x00A0, (BYTE)(added / 65536));
- POKE(0x00A1, (BYTE)(added / 256));
- POKE(0x00A2, (BYTE)added);
-}
+++ /dev/null
-#ifndef TIME_H_
-#define TIME_H_
-void set_time();
-char *get_time();
-#endif