--- /dev/null
+#Makefiledev
+/.cproject
+/.project
+/.settings
+/.tup
+/build-debug
+/doc
+/joe
+/scratch
+
--- /dev/null
+[submodule "libopencm3"]
+ path = libopencm3
+ url = https://github.com/libopencm3/libopencm3
--- /dev/null
+.gitignore
+TOP = $(TUP_CWD)
+
--- /dev/null
+include_rules
+
+PROG = stamp-test
+SRC = main.c
+SRC += cli.c cli_readline.c command.c command_tbl.c
+SRC += cmd_help.c cmd_echo.c cmd_mem.c cmd_boot.c
+SRC += env.c xmalloc.c
+SRC += timer.c con-utils.c serial.c
+SRC += background.c z180-serv.c z80-if.c
+
+SRC_Z = ../z180/hdrom.c
+
+#TARGETS = $(PROG).elf
+
+MCU_TARGET = atmega1281
+F_CPU = 18432000UL
+DEFS = -DF_CPU=$(F_CPU) -DBAUD=115200UL
+
+#INCLUDES += ../z180
+
+###############################################################################
+
+TOOLCHAINDIR =
+TOOLCHAIN = avr
+
+CC = $(TOOLCHAIN)-gcc
+LD = $(TOOLCHAIN)-gcc
+AR = $(TOOLCHAIN)-ar
+AS = $(TOOLCHAIN)-as
+OBJCOPY = $(TOOLCHAIN)-objcopy
+OBJDUMP = $(TOOLCHAIN)-objdump
+SIZE = $(TOOLCHAIN)-size
+GDB = $(TOOLCHAIN)-gdb
+
+###############################################################################
+
+ifdef DEBUG
+SRC += debug.c
+DEFS += -DDEBUG=2
+endif
+
+CFLAGS = -g -Os
+CFLAGS += -mmcu=$(MCU_TARGET)
+CFLAGS += -std=gnu99
+CFLAGS += -Wall -Wextra
+CFLAGS += -Wredundant-decls
+#CFLAGS += -fno-common -ffunction-sections -fdata-sections
+#CFLAGS += -I $(INCLUDES)
+
+CPPFLAGS += $(DEFS)
+
+# Linker flags
+LDFLAGS += -Wl,--gc-sections
+LDFLAGS += -Wl,--cref
+
+
+!cc = |> ^ CC %f^ $(CC) $(CFLAGS) $(CPPFLAGS) -c %f -o %o |> %B.o
+!LINK = |> ^ LINK %o^ $(LD) $(CFLAGS) $(LDFLAGS) -Wl,-Map=%O.map %f $(LDLIBS) -o %o |> | %O.map
+!OBJCOPY= |> ^ OBJCOPY %o^ $(OBJCOPY) -Oihex %f %o |>
+!OBJDUMP= |> ^ OBJDUMP %o^ $(OBJDUMP) -h -S %f > %o |> %O.lss
+!SIZE = |> ^ SIZE^ $(SIZE) %f |>
+
+: foreach $(SRC) | ../z180/hdrom.h |> !cc |> {objs}
+: $(SRC_Z) |> !cc -D'const=const __flash' |> {objs}
+
+: {objs} |> !LINK |> $(PROG).elf
+: $(PROG).elf |> !OBJCOPY |> %B.hex
+: $(PROG).elf |> !OBJDUMP |> %B.lss
+: $(PROG).elf |> !SIZE |>
+
--- /dev/null
+#include "common.h"
+#include "background.h"
+
+
+#define BG_FUNC_MAX 5
+
+static bg_func func_tab[BG_FUNC_MAX];
+static int_fast8_t fcount;
+
+int bg_register(bg_func f)
+{
+ if (fcount < BG_FUNC_MAX) {
+ func_tab[fcount++] = f;
+ return 1;
+ }
+ return 0;
+}
+
+
+void bg_shed(void)
+{
+ static int_fast8_t current;
+
+ if (func_tab[current]) {
+ func_tab[current](0);
+ }
+ if (++current >= fcount)
+ current = 0;
+}
+
+
--- /dev/null
+#ifndef BACKGROUND_H
+#define BACKGROUND_H
+
+typedef int (*bg_func)(int);
+
+int bg_register(bg_func f);
+void bg_shed(void);
+
+#endif /* BACKGROUND_H */
+
--- /dev/null
+#include "common.h"
+
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "config.h"
+#include "command.h"
+#include "xmalloc.h"
+#include "debug.h"
+#include "env.h"
+#include "cli_readline.h"
+#include "con-utils.h"
+#include "cli.h"
+
+#define DEBUG_PARSER 0 /* set to 1 to debug */
+
+#define debug_parser(fmt, args...) \
+ debug_cond(DEBUG_PARSER, fmt, ##args)
+
+static int cli_parse_line(char *line, char *argv[])
+{
+ static const FLASH char delim[] = {" \t"};
+
+ char *ptr;
+ uint_fast8_t nargs = 0;
+
+ debug_parser("parse_line: \"%s\"\n", line);
+
+ ptr = strtok_P(line, delim);
+ while(nargs < CONFIG_SYS_MAXARGS && ptr != NULL) {
+ argv[nargs++] = ptr;
+ ptr = strtok_P(NULL, delim);
+ }
+
+ if (ptr != NULL)
+ printf_P(PSTR("** Too many args (max. %d) **\n"), CONFIG_SYS_MAXARGS);
+
+ argv[nargs] = NULL;
+ debug_parser("parse_line: nargs=%d\n", nargs);
+
+ return nargs;
+}
+
+static void process_macros(const char *input, char *output)
+{
+ char c, prev;
+ const char *varname_start = NULL;
+#if 0 && (CONFIG_SYS_CBSIZE < __UINT_FAST8_MAX__)
+ uint_fast8_t inputcnt = strlen(input);
+ uint_fast8_t outputcnt = CONFIG_SYS_CBSIZE;
+#else
+ int inputcnt = strlen(input);
+ int outputcnt = CONFIG_SYS_CBSIZE;
+#endif
+ uint_fast8_t state = 0; /* 0 = waiting for '$' */
+
+ /* 1 = waiting for '(' or '{' */
+ /* 2 = waiting for ')' or '}' */
+ /* 3 = waiting for ''' */
+ char *output_start = output;
+
+ debug_parser("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen(input),
+ input);
+
+ prev = '\0'; /* previous character */
+
+ while (inputcnt && outputcnt) {
+ c = *input++;
+ inputcnt--;
+
+ if (state != 3) {
+ /* remove one level of escape characters */
+ if ((c == '\\') && (prev != '\\')) {
+ if (inputcnt-- == 0)
+ break;
+ prev = c;
+ c = *input++;
+ }
+ }
+
+ switch (state) {
+ case 0: /* Waiting for (unescaped) $ */
+ if ((c == '\'') && (prev != '\\')) {
+ state = 3;
+ break;
+ }
+ if ((c == '$') && (prev != '\\')) {
+ state++;
+ } else {
+ *(output++) = c;
+ outputcnt--;
+ }
+ break;
+ case 1: /* Waiting for ( */
+ if (c == '(' || c == '{') {
+ state++;
+ varname_start = input;
+ } else {
+ state = 0;
+ *(output++) = '$';
+ outputcnt--;
+
+ if (outputcnt) {
+ *(output++) = c;
+ outputcnt--;
+ }
+ }
+ break;
+ case 2: /* Waiting for ) */
+ if (c == ')' || c == '}') {
+ char envname[CONFIG_SYS_ENV_NAMELEN+1], *envval;
+ /* Varname # of chars */
+ uint_fast8_t envcnt = input - varname_start - 1;
+ if (envcnt > CONFIG_SYS_ENV_NAMELEN)
+ envcnt = CONFIG_SYS_ENV_NAMELEN;
+
+ memcpy(envname, varname_start, envcnt);
+ envname[envcnt] = '\0';
+
+ /* Get its value */
+ envval = getenv(envname);
+
+ /* Copy into the line if it exists */
+ if (envval != NULL)
+ while ((*envval) && outputcnt) {
+ *(output++) = *(envval++);
+ outputcnt--;
+ }
+ /* Look for another '$' */
+ state = 0;
+ }
+ break;
+ case 3: /* Waiting for ' */
+ if ((c == '\'') && (prev != '\\')) {
+ state = 0;
+ } else {
+ *(output++) = c;
+ outputcnt--;
+ }
+ break;
+ }
+ prev = c;
+ }
+
+ if (outputcnt)
+ *output = 0;
+ else
+ *(output - 1) = 0;
+
+ debug_parser("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n",
+ strlen(output_start), output_start);
+}
+
+ /*
+ * WARNING:
+ *
+ * We must create a temporary copy of the command since the command we get
+ * may be the result from getenv(), which returns a pointer directly to
+ * the environment data, which may change magicly when the command we run
+ * creates or modifies environment variables (like "bootp" does).
+ */
+static int cli_run_command(const char *cmd, int flag)
+{
+ char *cmdbuf; /* working copy of cmd */
+ char *token; /* start of token in cmdbuf */
+ char *sep; /* end of token (separator) in cmdbuf */
+ char *finaltoken;
+ char *str;
+ char *argv[CONFIG_SYS_MAXARGS + 1]; /* NULL terminated */
+ int argc;
+ uint_fast8_t inquotes, repeatable = 1;
+ int rc = 0;
+
+ debug_parser("[RUN_COMMAND] cmd[%p]=\"%s\"\n",
+ cmd, cmd ? cmd : "NULL");
+
+ clear_ctrlc(); /* forget any previous Control C */
+
+ if (!cmd || !*cmd)
+ return -1; /* empty command */
+
+
+ cmdbuf = xmalloc(strlen(cmd) + 1);
+ finaltoken = xmalloc(CONFIG_SYS_CBSIZE);
+
+ strcpy(cmdbuf, cmd);
+ str = cmdbuf;
+
+ /* Process separators and check for invalid
+ * repeatable commands
+ */
+
+ debug_parser("[PROCESS_SEPARATORS] %s\n", cmd);
+ while (*str) {
+ /*
+ * Find separator, or string end
+ * Allow simple escape of ';' by writing "\;"
+ */
+ for (inquotes = 0, sep = str; *sep; sep++) {
+ if ((*sep == '\'') &&
+ (*(sep - 1) != '\\'))
+ inquotes = !inquotes;
+
+ if (!inquotes &&
+ (*sep == ';' || *sep == '\n') && /* separator */
+ (sep != str) && /* past string start */
+ (*(sep - 1) != '\\')) /* and NOT escaped */
+ break;
+ }
+
+ /*
+ * Limit the token to data between separators
+ */
+ token = str;
+ if (*sep) {
+ str = sep + 1; /* start of command for next pass */
+ *sep = '\0';
+ } else {
+ str = sep; /* no more commands for next pass */
+ }
+ debug_parser("token: \"%s\"\n", token);
+
+ /* find macros in this token and replace them */
+ process_macros(token, finaltoken);
+
+ /* Extract arguments */
+ argc = cli_parse_line(finaltoken, argv);
+ if (argc == 0) {
+ rc = -1; /* no command at all */
+ continue;
+ }
+
+ if (cmd_process(flag, argc, argv, &repeatable))
+ rc = -1;
+
+ /* Did the user stop this? */
+ if (had_ctrlc()) {
+ rc = -1; /* if stopped then not repeatable */
+ break;
+ }
+ }
+
+ free(cmdbuf);
+ free(finaltoken);
+
+ return rc ? rc : repeatable;
+}
+
+static int cli_run_command_list(const char *cmd)
+{
+ return (cli_run_command(cmd, 0) < 0);
+}
+
+/******************************************************************************/
+
+
+/*
+ * Run a command using the selected parser.
+ *
+ * @param cmd Command to run
+ * @param flag Execution flags (CMD_FLAG_...)
+ * @return 0 on success, or != 0 on error.
+ */
+int run_command(const char *cmd, int flag)
+{
+ /*
+ * cli_run_command can return 0 or 1 for success, so clean up
+ * its result.
+ */
+ if (cli_run_command(cmd, flag) == -1)
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Run a command using the selected parser, and check if it is repeatable.
+ *
+ * @param cmd Command to run
+ * @param flag Execution flags (CMD_FLAG_...)
+ * @return 0 (not repeatable) or 1 (repeatable) on success, -1 on error.
+ */
+static int run_command_repeatable(const char *cmd, int flag)
+{
+ return cli_run_command(cmd, flag);
+}
+
+int run_command_list(const char *cmd, int len)
+{
+ (void) len;
+
+ return cli_run_command_list(cmd);
+}
+
+/****************************************************************************/
+
+
+void cli_loop(void)
+{
+ char *lastcommand = NULL;
+ int len;
+ int flag;
+ int rc = 1;
+
+ for (;;) {
+ len = cli_readline(PSTR(CONFIG_SYS_PROMPT));
+
+ flag = 0; /* assume no special flags for now */
+ if (len > 0) {
+ lastcommand = (char *) xrealloc(lastcommand, len+1);
+ if (lastcommand != NULL) {
+ strncpy(lastcommand, console_buffer, len+1);
+ lastcommand[len] = '\0';
+ }
+ } else if (len == 0)
+ flag |= CMD_FLAG_REPEAT;
+
+ if (len == -1)
+ my_puts_P(PSTR("<INTERRUPT>\n"));
+ else
+ rc = run_command_repeatable(lastcommand, flag);
+
+ if (rc <= 0) {
+ /* invalid command or not repeatable, forget it */
+ free(lastcommand);
+ lastcommand = NULL;
+ }
+ }
+}
+
+
+int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int i;
+ (void) cmdtp;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ for (i = 1; i < argc; ++i) {
+ char *arg;
+
+ arg = getenv(argv[i]);
+ if (arg == NULL) {
+ printf_P(PSTR("## Error: \"%s\" not defined\n"), argv[i]);
+ return 1;
+ }
+
+ if (run_command(arg, flag) != 0)
+ return 1;
+ }
+ return 0;
+}
+
--- /dev/null
+#ifndef CLI_H
+#define CLI_H
+
+/**
+ * Go into the command loop
+ *
+ * This will return if we get a timeout waiting for a command, but only for
+ * the simple parser (not hush). See CONFIG_BOOT_RETRY_TIME.
+ */
+void cli_loop(void);
+
+/**
+ * cli_simple_run_command() - Execute a command with the simple CLI
+ *
+ * @cmd: String containing the command to execute
+ * @flag Flag value - see CMD_FLAG_...
+ * @return 1 - command executed, repeatable
+ * 0 - command executed but not repeatable, interrupted commands are
+ * always considered not repeatable
+ * -1 - not executed (unrecognized, bootd recursion or too many args)
+ * (If cmd is NULL or "" or longer than CONFIG_SYS_CBSIZE-1 it is
+ * considered unrecognized)
+ */
+//int cli_simple_run_command(const char *cmd, int flag);
+
+/**
+ * cli_simple_run_command_list() - Execute a list of command
+ *
+ * The commands should be separated by ; or \n and will be executed
+ * by the built-in parser.
+ *
+ * This function cannot take a const char * for the command, since if it
+ * finds newlines in the string, it replaces them with \0.
+ *
+ * @param cmd String containing list of commands
+ * @param flag Execution flags (CMD_FLAG_...)
+ * @return 0 on success, or != 0 on error.
+ */
+//int cli_simple_run_command_list(char *cmd, int flag);
+
+/**
+ * parse_line() - split a command line down into separate arguments
+ *
+ * The argv[] array is filled with pointers into @line, and each argument
+ * is terminated by \0 (i.e. @line is changed in the process unless there
+ * is only one argument).
+ *
+ * #argv is terminated by a NULL after the last argument pointer.
+ *
+ * At most CONFIG_SYS_MAXARGS arguments are permited - if there are more
+ * than that then an error is printed, and this function returns
+ * CONFIG_SYS_MAXARGS, with argv[] set up to that point.
+ *
+ * @line: Command line to parse
+ * @args: Array to hold arguments
+ * @return number of arguments
+ */
+//int cli_simple_parse_line(char *line, char *argv[]);
+
+int run_command_list(const char *cmd, int len);
+
+
+#endif /* CLI_H */
+
--- /dev/null
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Add to readline cmdline-editing by
+ * (C) Copyright 2005
+ * JinHua Luo, GuangDong Linux Center, <luo.jinhua@gd-linux.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "common.h"
+
+#include <avr/pgmspace.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "config.h"
+#include "con-utils.h"
+#include "command.h"
+#include "cli_readline.h"
+
+char console_buffer[CONFIG_SYS_CBSIZE + 1]; /* console I/O buffer */
+
+static const FLASH char erase_seq[] = "\b \b"; /* erase sequence */
+static const FLASH char tab_seq[] = " "; /* used to expand TABs */
+
+#ifndef CONFIG_CMDLINE_EDITING
+static char *delete_char (char *buffer, char *p, int *colp, int *np, int plen)
+{
+ char *s;
+
+ if (*np == 0)
+ return p;
+
+ if (*(--p) == '\t') { /* will retype the whole line */
+ while (*colp > plen) {
+ my_puts_P(erase_seq);
+ (*colp)--;
+ }
+ for (s = buffer; s < p; ++s) {
+ if (*s == '\t') {
+ my_puts_P(tab_seq + ((*colp) & 07));
+ *colp += 8 - ((*colp) & 07);
+ } else {
+ ++(*colp);
+ putchar(*s);
+ }
+ }
+ } else {
+ my_puts_P(erase_seq);
+ (*colp)--;
+ }
+ (*np)--;
+
+ return p;
+}
+#endif /* CONFIG_CMDLINE_EDITING */
+
+
+#ifdef CONFIG_CMDLINE_EDITING
+
+/*
+ * cmdline-editing related codes from vivi.
+ * Author: Janghoon Lyu <nandy@mizi.com>
+ */
+
+#define putnstr(str, n) printf_P(PSTR("%.*s"), (int)n, str)
+
+#define CTL_CH(c) ((c) - 'a' + 1)
+#define CTL_BACKSPACE ('\b')
+#define DEL ((char)255)
+#define DEL7 ((char)127)
+#define CREAD_HIST_CHAR ('!')
+
+#define getcmd_putch(ch) putchar(ch)
+#define getcmd_getch() my_getchar()
+#define getcmd_cbeep() getcmd_putch('\a')
+
+#define HIST_MAX 5
+#define HIST_SIZE CONFIG_SYS_CBSIZE
+
+static int hist_max;
+static int hist_add_idx;
+static int hist_cur = -1;
+static unsigned hist_num;
+
+static char *hist_list[HIST_MAX];
+static char hist_lines[HIST_MAX][HIST_SIZE + 1]; /* Save room for NULL */
+
+#define add_idx_minus_one() ((hist_add_idx == 0) ? hist_max : hist_add_idx-1)
+
+static void hist_init(void)
+{
+ int i;
+
+ hist_max = 0;
+ hist_add_idx = 0;
+ hist_cur = -1;
+ hist_num = 0;
+
+ for (i = 0; i < HIST_MAX; i++) {
+ hist_list[i] = hist_lines[i];
+ hist_list[i][0] = '\0';
+ }
+}
+
+static void cread_add_to_hist(char *line)
+{
+ strcpy(hist_list[hist_add_idx], line);
+
+ if (++hist_add_idx >= HIST_MAX)
+ hist_add_idx = 0;
+
+ if (hist_add_idx > hist_max)
+ hist_max = hist_add_idx;
+
+ hist_num++;
+}
+
+static char *hist_prev(void)
+{
+ char *ret;
+ int old_cur;
+
+ if (hist_cur < 0)
+ return NULL;
+
+ old_cur = hist_cur;
+ if (--hist_cur < 0)
+ hist_cur = hist_max;
+
+ if (hist_cur == hist_add_idx) {
+ hist_cur = old_cur;
+ ret = NULL;
+ } else {
+ ret = hist_list[hist_cur];
+ }
+
+ return ret;
+}
+
+static char *hist_next(void)
+{
+ char *ret;
+
+ if (hist_cur < 0)
+ return NULL;
+
+ if (hist_cur == hist_add_idx)
+ return NULL;
+
+ if (++hist_cur > hist_max)
+ hist_cur = 0;
+
+ if (hist_cur == hist_add_idx)
+ ret = "";
+ else
+ ret = hist_list[hist_cur];
+
+ return ret;
+}
+
+#ifndef CONFIG_CMDLINE_EDITING
+static void cread_print_hist_list(void)
+{
+ int i;
+ unsigned n;
+
+ n = hist_num - hist_max;
+
+ i = hist_add_idx + 1;
+ while (1) {
+ if (i > hist_max)
+ i = 0;
+ if (i == hist_add_idx)
+ break;
+ printf_P(PSTR("%s\n"), hist_list[i]);
+ n++;
+ i++;
+ }
+}
+#endif /* CONFIG_CMDLINE_EDITING */
+
+#define BEGINNING_OF_LINE() { \
+ while (num) { \
+ getcmd_putch(CTL_BACKSPACE); \
+ num--; \
+ } \
+}
+
+#define ERASE_TO_EOL() { \
+ if (num < eol_num) { \
+ printf_P(PSTR("%*S"), (int)(eol_num - num), PSTR("")); \
+ do { \
+ getcmd_putch(CTL_BACKSPACE); \
+ } while (--eol_num > num); \
+ } \
+}
+
+#define REFRESH_TO_EOL() { \
+ if (num < eol_num) { \
+ wlen = eol_num - num; \
+ putnstr(buf + num, wlen); \
+ num = eol_num; \
+ } \
+}
+
+static void cread_add_char(char ichar, int insert, unsigned long *num,
+ unsigned long *eol_num, char *buf, unsigned long len)
+{
+ unsigned long wlen;
+
+ /* room ??? */
+ if (insert || *num == *eol_num) {
+ if (*eol_num > len - 1) {
+ getcmd_cbeep();
+ return;
+ }
+ (*eol_num)++;
+ }
+
+ if (insert) {
+ wlen = *eol_num - *num;
+ if (wlen > 1)
+ memmove(&buf[*num+1], &buf[*num], wlen-1);
+
+ buf[*num] = ichar;
+ putnstr(buf + *num, wlen);
+ (*num)++;
+ while (--wlen)
+ getcmd_putch(CTL_BACKSPACE);
+ } else {
+ /* echo the character */
+ wlen = 1;
+ buf[*num] = ichar;
+ putnstr(buf + *num, wlen);
+ (*num)++;
+ }
+}
+
+static void cread_add_str(char *str, int strsize, int insert,
+ unsigned long *num, unsigned long *eol_num,
+ char *buf, unsigned long len)
+{
+ while (strsize--) {
+ cread_add_char(*str, insert, num, eol_num, buf, len);
+ str++;
+ }
+}
+
+static int cread_line(const FLASH char *const prompt, char *buf, unsigned int *len)
+{
+ unsigned long num = 0;
+ unsigned long eol_num = 0;
+ unsigned long wlen;
+ char ichar;
+ int insert = 1;
+ int esc_len = 0;
+ char esc_save[8];
+ int init_len = strlen(buf);
+
+ (void) prompt;
+
+ if (init_len)
+ cread_add_str(buf, init_len, 1, &num, &eol_num, buf, *len);
+
+ while (1) {
+ ichar = getcmd_getch();
+
+ if ((ichar == '\n') || (ichar == '\r')) {
+ putchar('\n');
+ break;
+ }
+
+ /*
+ * handle standard linux xterm esc sequences for arrow key, etc.
+ */
+ if (esc_len != 0) {
+ if (esc_len == 1) {
+ if (ichar == '[') {
+ esc_save[esc_len] = ichar;
+ esc_len = 2;
+ } else {
+ cread_add_str(esc_save, esc_len,
+ insert, &num, &eol_num,
+ buf, *len);
+ esc_len = 0;
+ }
+ continue;
+ }
+
+ switch (ichar) {
+ case 'D': /* <- key */
+ ichar = CTL_CH('b');
+ esc_len = 0;
+ break;
+ case 'C': /* -> key */
+ ichar = CTL_CH('f');
+ esc_len = 0;
+ break; /* pass off to ^F handler */
+ case 'H': /* Home key */
+ ichar = CTL_CH('a');
+ esc_len = 0;
+ break; /* pass off to ^A handler */
+ case 'A': /* up arrow */
+ ichar = CTL_CH('p');
+ esc_len = 0;
+ break; /* pass off to ^P handler */
+ case 'B': /* down arrow */
+ ichar = CTL_CH('n');
+ esc_len = 0;
+ break; /* pass off to ^N handler */
+ default:
+ esc_save[esc_len++] = ichar;
+ cread_add_str(esc_save, esc_len, insert,
+ &num, &eol_num, buf, *len);
+ esc_len = 0;
+ continue;
+ }
+ }
+
+ switch (ichar) {
+ case 0x1b:
+ if (esc_len == 0) {
+ esc_save[esc_len] = ichar;
+ esc_len = 1;
+ } else {
+ my_puts_P(PSTR("impossible condition #876\n"));
+ esc_len = 0;
+ }
+ break;
+
+ case CTL_CH('a'):
+ BEGINNING_OF_LINE();
+ break;
+ case CTL_CH('c'): /* ^C - break */
+ *buf = '\0'; /* discard input */
+ return -1;
+ case CTL_CH('f'):
+ if (num < eol_num) {
+ getcmd_putch(buf[num]);
+ num++;
+ }
+ break;
+ case CTL_CH('b'):
+ if (num) {
+ getcmd_putch(CTL_BACKSPACE);
+ num--;
+ }
+ break;
+ case CTL_CH('d'):
+ if (num < eol_num) {
+ wlen = eol_num - num - 1;
+ if (wlen) {
+ memmove(&buf[num], &buf[num+1], wlen);
+ putnstr(buf + num, wlen);
+ }
+
+ getcmd_putch(' ');
+ do {
+ getcmd_putch(CTL_BACKSPACE);
+ } while (wlen--);
+ eol_num--;
+ }
+ break;
+ case CTL_CH('k'):
+ ERASE_TO_EOL();
+ break;
+ case CTL_CH('e'):
+ REFRESH_TO_EOL();
+ break;
+ case CTL_CH('o'):
+ insert = !insert;
+ break;
+ case CTL_CH('x'):
+ case CTL_CH('u'):
+ BEGINNING_OF_LINE();
+ ERASE_TO_EOL();
+ break;
+ case DEL:
+ case DEL7:
+ case 8:
+ if (num) {
+ wlen = eol_num - num;
+ num--;
+ memmove(&buf[num], &buf[num+1], wlen);
+ getcmd_putch(CTL_BACKSPACE);
+ putnstr(buf + num, wlen);
+ getcmd_putch(' ');
+ do {
+ getcmd_putch(CTL_BACKSPACE);
+ } while (wlen--);
+ eol_num--;
+ }
+ break;
+ case CTL_CH('p'):
+ case CTL_CH('n'):
+ {
+ char *hline;
+
+ esc_len = 0;
+
+ if (ichar == CTL_CH('p'))
+ hline = hist_prev();
+ else
+ hline = hist_next();
+
+ if (!hline) {
+ getcmd_cbeep();
+ continue;
+ }
+
+ /* nuke the current line */
+ /* first, go home */
+ BEGINNING_OF_LINE();
+
+ /* erase to end of line */
+ ERASE_TO_EOL();
+
+ /* copy new line into place and display */
+ strcpy(buf, hline);
+ eol_num = strlen(buf);
+ REFRESH_TO_EOL();
+ continue;
+ }
+#ifdef CONFIG_AUTO_COMPLETE
+ case '\t': {
+ int num2, col;
+
+ /* do not autocomplete when in the middle */
+ if (num < eol_num) {
+ getcmd_cbeep();
+ break;
+ }
+
+ buf[num] = '\0';
+ col = strlen_P(prompt) + eol_num;
+ num2 = num;
+ if (cmd_auto_complete(prompt, buf, &num2, &col)) {
+ col = num2 - num;
+ num += col;
+ eol_num += col;
+ }
+ break;
+ }
+#endif
+ default:
+ cread_add_char(ichar, insert, &num, &eol_num, buf,
+ *len);
+ break;
+ }
+ }
+ *len = eol_num;
+ buf[eol_num] = '\0'; /* lose the newline */
+
+ if (buf[0] && buf[0] != CREAD_HIST_CHAR)
+ cread_add_to_hist(buf);
+ hist_cur = hist_add_idx;
+
+ return 0;
+}
+
+#endif /* CONFIG_CMDLINE_EDITING */
+
+/****************************************************************************/
+
+static int cli_readline_into_buffer(const FLASH char *const prompt, char *buffer)
+{
+ char *p = buffer;
+#ifdef CONFIG_CMDLINE_EDITING
+ unsigned int len = CONFIG_SYS_CBSIZE;
+ int rc;
+ static int initted;
+
+ if (!initted) {
+ hist_init();
+ initted = 1;
+ }
+
+ if (prompt)
+ my_puts_P(prompt);
+
+ rc = cread_line(prompt, p, &len);
+ return rc < 0 ? rc : (int) len;
+
+#else /* CONFIG_CMDLINE_EDITING */
+ char *p_buf = p;
+ int n = 0; /* buffer index */
+ int plen = 0; /* prompt length */
+ int col; /* output column cnt */
+ char c;
+
+ /* print prompt */
+ if (prompt) {
+ plen = strlen_P(prompt);
+ my_puts_P(prompt);
+ }
+ col = plen;
+
+ for (;;) {
+
+ c = my_getchar();
+
+ /*
+ * Special character handling
+ */
+ switch (c) {
+ case '\r': /* Enter */
+ case '\n':
+ *p = '\0';
+ my_puts_P(PSTR("\r\n"));
+ return p - p_buf;
+
+ case '\0': /* nul */
+ continue;
+
+ case 0x03: /* ^C - break */
+ p_buf[0] = '\0'; /* discard input */
+ return -1;
+
+ case 0x15: /* ^U - erase line */
+ while (col > plen) {
+ my_puts_P(erase_seq);
+ --col;
+ }
+ p = p_buf;
+ n = 0;
+ continue;
+
+ case 0x17: /* ^W - erase word */
+ p = delete_char(p_buf, p, &col, &n, plen);
+ while ((n > 0) && (*p != ' '))
+ p = delete_char(p_buf, p, &col, &n, plen);
+ continue;
+
+ case 0x08: /* ^H - backspace */
+ case 0x7F: /* DEL - backspace */
+ p = delete_char(p_buf, p, &col, &n, plen);
+ continue;
+
+ default:
+ /*
+ * Must be a normal character then
+ */
+ if (n < CONFIG_SYS_CBSIZE-2) {
+ if (c == '\t') { /* expand TABs */
+#ifdef CONFIG_AUTO_COMPLETE
+ /*
+ * if auto completion triggered just
+ * continue
+ */
+ *p = '\0';
+ if (cmd_auto_complete(prompt,
+ console_buffer,
+ &n, &col)) {
+ p = p_buf + n; /* reset */
+ continue;
+ }
+#endif
+ my_puts_P(tab_seq + (col & 07));
+ col += 8 - (col & 07);
+ } else {
+ char buf[2];
+
+ /*
+ * Echo input using puts() to force an
+ * LCD flush if we are using an LCD
+ */
+ ++col;
+ buf[0] = c;
+ buf[1] = '\0';
+ my_puts(buf);
+ }
+ *p++ = c;
+ ++n;
+ } else { /* Buffer full */
+ putchar('\a');
+ }
+ }
+ }
+#endif /* CONFIG_CMDLINE_EDITING */
+}
+
+int cli_readline(const FLASH char *const prompt)
+{
+ /*
+ * If console_buffer isn't 0-length the user will be prompted to modify
+ * it instead of entering it from scratch as desired.
+ */
+ console_buffer[0] = '\0';
+
+ return cli_readline_into_buffer(prompt, console_buffer);
+}
+
--- /dev/null
+/*
+ * (C) Copyright 2014 Google, Inc
+ * Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef CLI_READLINE_H
+#define CLI_READLINE_H
+
+extern char console_buffer[]; /* console I/O buffer */
+
+/**
+ * cli_readline() - read a line into the console_buffer
+ *
+ * This is a convenience function which calls cli_readline_into_buffer().
+ *
+ * @prompt: Prompt to display
+ * @return command line length excluding terminator, or -ve on error
+ */
+int cli_readline(const FLASH char *const prompt);
+
+/**
+ * readline_into_buffer() - read a line into a buffer
+ *
+ * Display the prompt, then read a command line into @buffer. The
+ * maximum line length is CONFIG_SYS_CBSIZE including a \0 terminator, which
+ * will always be added.
+ *
+ * The command is echoed as it is typed. Command editing is supported if
+ * CONFIG_CMDLINE_EDITING is defined. Tab auto-complete is supported if
+ * CONFIG_AUTO_COMPLETE is defined. If CONFIG_BOOT_RETRY_TIME is defined,
+ * then a timeout will be applied.
+ *
+ * If CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0,
+ * time out when time goes past endtime (timebase time in ticks).
+ *
+ * @prompt: Prompt to display
+ * @buffer: Place to put the line that is entered
+ * @timeout: Timeout in milliseconds, 0 if none
+ * @return command line length excluding terminator, or -ve on error: of the
+ * timeout is exceeded (either CONFIG_BOOT_RETRY_TIME or the timeout
+ * parameter), then -2 is returned. If a break is detected (Ctrl-C) then
+ * -1 is returned.
+ */
+//int cli_readline_into_buffer(const char *const prompt, char *buffer, int timeout);
+
+
+#endif /* CLI_READLINE_H */
+
--- /dev/null
+
+/*
+ * Misc boot support
+ */
+#include "common.h"
+#include <stdlib.h>
+#include <util/delay.h>
+#include <avr/pgmspace.h>
+
+#include "command.h"
+#include "z80-if.h"
+
+/* ugly hack to get Z180 loadfile into flash memory */
+#define const const FLASH
+#include "../z180/hdrom.h"
+#undef const
+
+
+
+static void z80_load_mem(void)
+{
+ unsigned sec = 0;
+ uint32_t sec_base = hdrom_start;
+
+ printf_P(PSTR("Loading Z180 memory... \n"));
+
+ while (sec < hdrom_sections) {
+ printf_P(PSTR(" From: 0x%.5lX to: 0x%.5lX (%5li bytes)\n"),
+ hdrom_address[sec],
+ hdrom_address[sec]+hdrom_length_of_sections[sec] - 1,
+ hdrom_length_of_sections[sec]);
+
+ z80_bus_cmd(Request);
+ z80_write_block((const FLASH unsigned char *) &hdrom[sec_base], /* src */
+ hdrom_address[sec], /* dest */
+ hdrom_length_of_sections[sec]); /* len */
+ z80_bus_cmd(Release);
+ sec_base+=hdrom_length_of_sections[sec];
+ sec++;
+ }
+}
+
+int do_loadf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ (void) cmdtp; (void) flag; (void) argc; (void) argv;
+
+ if (z80_bus_state() & ZST_RUNNING) {
+ printf_P(PSTR("## Can't load while CPU is running!\n"));
+ return 1;
+ }
+
+ z80_load_mem();
+
+ return 0;
+}
+
+
+int do_busreq_pulse(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ uint16_t count=1;
+
+ (void) cmdtp; (void) flag;
+
+ if (!(z80_bus_state() & ZST_RUNNING)) {
+ printf_P(PSTR("## CPU is not running!\n"));
+ return 1;
+ }
+
+ if (argc > 1)
+ count = (uint16_t) strtoul(argv[2], NULL, 16);
+
+ z80_bus_cmd(Request);
+ while (count--)
+ z80_bus_cmd(M_Cycle);
+
+ return 0;
+}
+
+
+int do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ uint32_t addr;
+
+ (void) cmdtp; (void) flag;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+ addr = strtoul(argv[1], NULL, 16);
+ if (addr >= (1UL<<16)) {
+ printf_P(PSTR("## Startaddress 0x%05lx too high.\n"
+ " (Out of logical address space (0x00000-0x0ffff))\n"),
+ addr);
+ return 1;
+ }
+
+ if (z80_bus_state() & ZST_RUNNING) {
+ printf_P(PSTR("## CPU allready running!\n"));
+ return 1;
+ }
+
+ printf_P(PSTR("## Starting application at 0x%04lx ...\n"), addr);
+
+ if (addr != 0) {
+ uint8_t tmp[3];
+ uint_fast8_t i;
+
+ z80_bus_cmd(Request);
+ for (i = 0; i < 3; i++)
+ tmp[i] = z80_read(i);
+ z80_write(0, 0xc3);
+ z80_write(1, addr);
+ z80_write(2, (addr >> 8));
+
+ z80_bus_cmd(Run);
+ z80_bus_cmd(M_Cycle);
+ z80_bus_cmd(M_Cycle);
+ for (i = 0; i < 3; i++)
+ z80_write(i, tmp[i]);
+ } else
+ z80_bus_cmd(Run);
+
+ z80_bus_cmd(Release);
+
+ return 0;
+}
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ (void) cmdtp; (void) flag; (void) argc; (void) argv;
+
+ printf_P(PSTR("## CPU now in reset state.\n"));
+
+ z80_bus_cmd(Reset);
+ return 0;
+}
+
+int do_restart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ (void) cmdtp; (void) flag; (void) argc; (void) argv;
+
+ z80_bus_cmd(Restart);
+
+ return 0;
+}
+
--- /dev/null
+/*
+ * Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "common.h"
+#include "command.h"
+
+
+int do_echo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ uint_fast8_t putnl = 1;
+
+ (void) cmdtp; (void) flag;
+
+ for (uint_fast8_t i = 1; i < argc; i++) {
+
+ uint_fast8_t backslash = 0;
+ char *p = argv[i];
+ char c;
+
+ if (i != 1)
+ putchar(' ');
+ while ((c = *p++) != '\0') {
+
+ if(backslash) {
+ backslash = 0;
+ if (c == 'c') {
+ putnl = 0;
+ continue;
+ } else
+ putchar('\\');
+ } else {
+ if (c == '\\') {
+ backslash = 1;
+ continue;
+ }
+ }
+ putchar(c);
+ }
+ }
+
+ if (putnl)
+ putchar('\n');
+
+ return 0;
+}
+
+#if 0
+U_BOOT_CMD(
+ echo, CONFIG_SYS_MAXARGS, 1, do_echo,
+ "echo args to console",
+ "[args..]\n"
+ " - echo args to console; \\c suppresses newline"
+);
+#endif
--- /dev/null
+
+#include "common.h"
+#include "command.h"
+
+int do_help(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ const int len = cmd_tbl_item_count();
+ return _do_help(cmd_tbl, len, cmdtp, flag, argc, argv);
+}
+
+
+#if 0
+
+U_BOOT_CMD(
+ help, CONFIG_SYS_MAXARGS, 1, do_help,
+ "print command description/usage",
+ "\n"
+ " - print brief description of all commands\n"
+ "help command ...\n"
+ " - print detailed usage of 'command'"
+);
+
+/* This does not use the U_BOOT_CMD macro as ? can't be used in symbol names */
+ll_entry_declare(cmd_tbl_t, question_mark, cmd) = {
+ "?", CONFIG_SYS_MAXARGS, 1, do_help,
+ "alias for 'help'",
+#ifdef CONFIG_SYS_LONGHELP
+ ""
+#endif /* CONFIG_SYS_LONGHELP */
+};
+
+#endif
--- /dev/null
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * Memory Functions
+ *
+ * Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
+ */
+
+#include "common.h"
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "config.h"
+#include "debug.h"
+#include "command.h"
+#include "cli_readline.h"
+#include "con-utils.h"
+#include "z80-if.h"
+
+/*
+ * TODO: printf() --> printf_P()
+ */
+
+#ifndef CONFIG_SYS_MEMTEST_SCRATCH
+#define CONFIG_SYS_MEMTEST_SCRATCH 0
+#endif
+
+static int mod_mem(cmd_tbl_t *, int, int, int, char * const []);
+
+/* Display values from last command.
+ * Memory modify remembered values are different from display memory.
+ */
+static uint32_t dp_last_addr;
+static uint32_t dp_last_length = 0x100;
+static uint32_t mm_last_addr;
+
+static uint32_t base_address = 0;
+
+/*--------------------------------------------------------------------------*/
+
+static void print_blanks(uint_fast8_t count)
+{
+ while(count--)
+ putchar(' ');
+}
+
+int z180_dump_mem(uint32_t startaddr, uint32_t len, const char *title)
+{
+ uint8_t buf[16];
+ uint8_t llen = 16;
+ uint8_t pre = startaddr % 16;
+ uint32_t addr = startaddr & ~0x0f;
+ len += pre;
+ uint8_t i;
+
+ if (title && *title)
+ printf_P(PSTR("%s\n"),title);
+
+ while (len) {
+ if (len < 16)
+ llen = len;
+
+ z80_bus_cmd(Request);
+ for (i = pre; i < llen; i++)
+ buf[i] = z80_read(addr + i);
+ z80_bus_cmd(Release);
+
+ printf_P(PSTR("%.5lx:"), addr);
+#if 0
+ print_blanks(3 * pre);
+
+ /* Print hex values */
+ for (i = pre; i < llen; i++)
+ printf_P(PSTR(" %.2x"), buf[i]);
+#else
+ for (i = 0; i < llen; i++) {
+ if ((i % 8) == 0)
+ putchar(' ');
+ if (i < pre)
+ printf_P(PSTR(".. "));
+ else
+ printf_P(PSTR("%.2x "), buf[i]);
+ }
+#endif
+ /* fill line with whitespace for nice ASCII print */
+#if 1
+ print_blanks(3 * (16u - i) + (16u-i)/8 + 1 + pre);
+#else
+
+#endif
+ /* Print data in ASCII characters */
+ for (i = pre; i < llen; i++)
+ printf_P(PSTR("%c"), isprint(buf[i]) ? buf[i] : '.');
+ putchar('\n');
+
+ pre = 0;
+ addr += 16;
+ len -= llen;
+
+ if (ctrlc())
+ return -1;
+ }
+ return 0;
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+/* Memory Display
+ *
+ * Syntax:
+ * md {addr} {len}
+ */
+int do_mem_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ uint32_t addr, length;
+
+ (void) cmdtp;
+
+#if 0
+ printf_P(PSTR("flag: %d, argc: %d"), flag, argc);
+ for (int i = 0; i < argc; i++) {
+ printf_P(PSTR(", argv[%d]: %s"), i, argv[i] ? argv[i] : "<NULL>");
+ }
+ putchar('\n');
+#endif
+
+ /* We use the last specified parameters, unless new ones are
+ * entered.
+ */
+ addr = dp_last_addr;
+ length = dp_last_length;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if ((flag & CMD_FLAG_REPEAT) == 0) {
+ /* Address is specified since argc > 1 */
+ addr = strtoul(argv[1], NULL, 16);
+ addr += base_address;
+
+ /* If another parameter, it is the length to display. */
+ if (argc > 2)
+ length = strtoul(argv[2], NULL, 16);
+ }
+
+ /* Print the lines. */
+ z180_dump_mem(addr, length, NULL);
+
+ dp_last_addr = addr + length;
+ dp_last_length = length;
+ return 0;
+}
+
+int do_mem_mm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ return mod_mem (cmdtp, 1, flag, argc, argv);
+}
+int do_mem_nm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ return mod_mem (cmdtp, 0, flag, argc, argv);
+}
+
+int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ uint8_t writeval;
+ uint32_t addr, count;
+
+ (void) cmdtp;
+ (void) flag;
+
+ if ((argc < 3) || (argc > 4))
+ return CMD_RET_USAGE;
+
+ /* Address is specified since argc > 1
+ */
+ addr = strtoul(argv[1], NULL, 16);
+ addr += base_address;
+
+ /* Get the value to write.
+ */
+ writeval = (uint8_t) strtoul(argv[2], NULL, 16);
+
+ /* Count ? */
+ if (argc == 4) {
+ count = strtoul(argv[3], NULL, 16);
+ } else {
+ count = 1;
+ }
+
+ z80_bus_cmd(Request);
+ while (count-- > 0) {
+ z80_write(addr, writeval);
+ ++addr;
+ }
+ z80_bus_cmd(Release);
+
+ return 0;
+}
+
+#ifdef CONFIG_MX_CYCLIC
+int do_mem_mdc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int i;
+ uint32_t count;
+
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ count = strtoul(argv[3], NULL, 10);
+
+ for (;;) {
+ do_mem_md (NULL, 0, 3, argv);
+
+ /* delay for <count> ms... */
+/* TODO: use timer */
+ for (i=0; i<count; i++)
+ udelay (1000);
+
+ /* check for ctrl-c to abort... */
+ if (ctrlc()) {
+ my_puts("Abort\n");
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+int do_mem_mwc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int i;
+ uint32_t count;
+
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ count = strtoul(argv[3], NULL, 10);
+
+ for (;;) {
+ do_mem_mw (NULL, 0, 3, argv);
+
+ /* delay for <count> ms... */
+/* TODO: use timer */
+ for (i=0; i<count; i++)
+ udelay (1000);
+
+ /* check for ctrl-c to abort... */
+ if (ctrlc()) {
+ my_puts("Abort\n");
+ return 0;
+ }
+ }
+
+ return 0;
+}
+#endif /* CONFIG_MX_CYCLIC */
+
+int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ uint32_t addr1, addr2, count, ngood;
+ int rcode = 0;
+ uint8_t byte1, byte2;
+
+ (void) cmdtp;
+ (void) flag;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+
+ addr1 = strtoul(argv[1], NULL, 16);
+ addr1 += base_address;
+ addr2 = strtoul(argv[2], NULL, 16);
+ addr2 += base_address;
+ count = strtoul(argv[3], NULL, 16);
+
+ for (ngood = 0; ngood < count; ++ngood) {
+ z80_bus_cmd(Request);
+ byte1 = z80_read(addr1);
+ byte2 = z80_read(addr2);
+ z80_bus_cmd(Release);
+ if (byte1 != byte2) {
+ printf( "byte at 0x%05lx (%#02x) != "
+ "byte at 0x%05lx (%#02x)\n",
+ addr1, byte1, addr2, byte2);
+ rcode = 1;
+ break;
+ }
+ addr1++;
+ addr2++;
+
+ /* check for ctrl-c to abort... */
+ if (ctrlc()) {
+ my_puts("Abort\n");
+ return 0;
+ }
+ }
+
+ printf("Total of %ld byte(s) (0x%lx) were the same\n", ngood, ngood);
+ return rcode;
+}
+
+int do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ uint32_t src, dest, count;
+ int_fast8_t step;
+
+ (void) cmdtp;
+ (void) flag;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+ src = strtoul(argv[1], NULL, 16);
+ src += base_address;
+ dest = strtoul(argv[2], NULL, 16);
+ dest += base_address;
+ count = strtoul(argv[3], NULL, 16);
+
+ if (count == 0) {
+ my_puts ("Zero length ???\n");
+ return 1;
+ }
+
+ if (dest > src) {
+ src += count - 1;
+ dest += count - 1;
+ step = -1;
+ } else
+ step = 1;
+
+ while (count-- > 0) {
+ uint8_t data;
+ z80_bus_cmd(Request);
+ data = z80_read(src);
+ z80_write(dest, data);
+ z80_bus_cmd(Release);
+ src += step;
+ dest += step;
+
+ /* check for ctrl-c to abort... */
+ if (ctrlc()) {
+ my_puts("Abort\n");
+ return 0;
+ }
+ }
+ return 0;
+}
+
+int do_mem_base(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ (void) cmdtp;
+ (void) flag;
+
+ if (argc > 1) {
+ /* Set new base address. */
+ base_address = strtoul(argv[1], NULL, 16);
+ }
+ /* Print the current base address. */
+ printf("Base Address: 0x%05lx\n", base_address);
+ return 0;
+}
+
+int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ uint32_t addr, length;
+
+ (void) cmdtp;
+ (void) flag;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ /* Address is always specified. */
+ addr = strtoul(argv[1], NULL, 16);
+
+ /* Length is the number of bytes. */
+ length = strtoul(argv[2], NULL, 16);
+
+
+ /* We want to optimize the loops to run as fast as possible.
+ * If we have only one object, just run infinite loops.
+ */
+ if (length == 1) {
+ z80_bus_cmd(Request);
+ for (;;)
+ z80_read(addr);
+ z80_bus_cmd(Release);
+ }
+
+ z80_bus_cmd(Request);
+ for (;;) {
+ uint32_t i = length;
+ uint32_t p = addr;
+ while (i-- > 0)
+ z80_read(p++);
+ }
+ z80_bus_cmd(Release);
+
+ return 0;
+}
+
+#ifdef CONFIG_LOOPW
+int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ uint32_t addr, length;
+ uint8_t data;
+
+ (void) cmdtp;
+ (void) flag;
+
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ /* Address is always specified. */
+ addr = strtoul(argv[1], NULL, 16);
+
+ /* Length is the number of bytes. */
+ length = strtoul(argv[2], NULL, 16);
+
+ data = strtoul(argv[3], NULL, 16);
+
+ /* We want to optimize the loops to run as fast as possible.
+ * If we have only one object, just run infinite loops.
+ */
+ if (length == 1) {
+ z80_bus_cmd(Request);
+ for (;;)
+ z80_write(addr, data);
+ }
+
+ for (;;) {
+ uint32_t i = length;
+ uint32_t p = addr;
+ while (i-- > 0)
+ z80_write(p++, data);
+ }
+}
+#endif /* CONFIG_LOOPW */
+
+#ifdef CONFIG_CMD_MEMTEST
+static uint32_t mem_test_alt(vu_long *buf, uint32_t start_addr, uint32_t end_addr,
+ vu_long *dummy)
+{
+ vu_long *addr;
+ uint32_t errs = 0;
+ uint32_t val, readback;
+ int j;
+ vu_long offset;
+ vu_long test_offset;
+ vu_long pattern;
+ vu_long temp;
+ vu_long anti_pattern;
+ vu_long num_words;
+ static const FLASH uint32_t bitpattern[] = {
+ 0x00000001, /* single bit */
+ 0x00000003, /* two adjacent bits */
+ 0x00000007, /* three adjacent bits */
+ 0x0000000F, /* four adjacent bits */
+ 0x00000005, /* two non-adjacent bits */
+ 0x00000015, /* three non-adjacent bits */
+ 0x00000055, /* four non-adjacent bits */
+ 0xaaaaaaaa, /* alternating 1/0 */
+ };
+
+ num_words = (end_addr - start_addr) / sizeof(vu_long);
+
+ /*
+ * Data line test: write a pattern to the first
+ * location, write the 1's complement to a 'parking'
+ * address (changes the state of the data bus so a
+ * floating bus doesn't give a false OK), and then
+ * read the value back. Note that we read it back
+ * into a variable because the next time we read it,
+ * it might be right (been there, tough to explain to
+ * the quality guys why it prints a failure when the
+ * "is" and "should be" are obviously the same in the
+ * error message).
+ *
+ * Rather than exhaustively testing, we test some
+ * patterns by shifting '1' bits through a field of
+ * '0's and '0' bits through a field of '1's (i.e.
+ * pattern and ~pattern).
+ */
+ addr = buf;
+ for (j = 0; j < sizeof(bitpattern) / sizeof(bitpattern[0]); j++) {
+ val = bitpattern[j];
+ for (; val != 0; val <<= 1) {
+ *addr = val;
+ *dummy = ~val; /* clear the test data off the bus */
+ readback = *addr;
+ if (readback != val) {
+ printf("FAILURE (data line): "
+ "expected %05lx, actual %05lx\n",
+ val, readback);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+ *addr = ~val;
+ *dummy = val;
+ readback = *addr;
+ if (readback != ~val) {
+ printf("FAILURE (data line): "
+ "Is %05lx, should be %05lx\n",
+ readback, ~val);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+ }
+ }
+
+ /*
+ * Based on code whose Original Author and Copyright
+ * information follows: Copyright (c) 1998 by Michael
+ * Barr. This software is placed into the public
+ * domain and may be used for any purpose. However,
+ * this notice must not be changed or removed and no
+ * warranty is either expressed or implied by its
+ * publication or distribution.
+ */
+
+ /*
+ * Address line test
+
+ * Description: Test the address bus wiring in a
+ * memory region by performing a walking
+ * 1's test on the relevant bits of the
+ * address and checking for aliasing.
+ * This test will find single-bit
+ * address failures such as stuck-high,
+ * stuck-low, and shorted pins. The base
+ * address and size of the region are
+ * selected by the caller.
+
+ * Notes: For best results, the selected base
+ * address should have enough LSB 0's to
+ * guarantee single address bit changes.
+ * For example, to test a 64-Kbyte
+ * region, select a base address on a
+ * 64-Kbyte boundary. Also, select the
+ * region size as a power-of-two if at
+ * all possible.
+ *
+ * Returns: 0 if the test succeeds, 1 if the test fails.
+ */
+ pattern = (vu_long) 0xaaaaaaaa;
+ anti_pattern = (vu_long) 0x55555555;
+
+ debug("%s:%d: length = 0x%.5lx\n", __func__, __LINE__, num_words);
+ /*
+ * Write the default pattern at each of the
+ * power-of-two offsets.
+ */
+ for (offset = 1; offset < num_words; offset <<= 1)
+ addr[offset] = pattern;
+
+ /*
+ * Check for address bits stuck high.
+ */
+ test_offset = 0;
+ addr[test_offset] = anti_pattern;
+
+ for (offset = 1; offset < num_words; offset <<= 1) {
+ temp = addr[offset];
+ if (temp != pattern) {
+ printf("\nFAILURE: Address bit stuck high @ 0x%.5lx:"
+ " expected 0x%.5lx, actual 0x%.5lx\n",
+ start_addr + offset*sizeof(vu_long),
+ pattern, temp);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+ }
+ addr[test_offset] = pattern;
+
+ /*
+ * Check for addr bits stuck low or shorted.
+ */
+ for (test_offset = 1; test_offset < num_words; test_offset <<= 1) {
+ addr[test_offset] = anti_pattern;
+
+ for (offset = 1; offset < num_words; offset <<= 1) {
+ temp = addr[offset];
+ if ((temp != pattern) && (offset != test_offset)) {
+ printf("\nFAILURE: Address bit stuck low or"
+ " shorted @ 0x%.5lx: expected 0x%.5lx,"
+ " actual 0x%.5lx\n",
+ start_addr + offset*sizeof(vu_long),
+ pattern, temp);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+ }
+ addr[test_offset] = pattern;
+ }
+
+ /*
+ * Description: Test the integrity of a physical
+ * memory device by performing an
+ * increment/decrement test over the
+ * entire region. In the process every
+ * storage bit in the device is tested
+ * as a zero and a one. The base address
+ * and the size of the region are
+ * selected by the caller.
+ *
+ * Returns: 0 if the test succeeds, 1 if the test fails.
+ */
+ num_words++;
+
+ /*
+ * Fill memory with a known pattern.
+ */
+ for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
+ addr[offset] = pattern;
+ }
+
+ /*
+ * Check each location and invert it for the second pass.
+ */
+ for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
+ temp = addr[offset];
+ if (temp != pattern) {
+ printf("\nFAILURE (read/write) @ 0x%.5lx:"
+ " expected 0x%.5lx, actual 0x%.5lx)\n",
+ start_addr + offset*sizeof(vu_long),
+ pattern, temp);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+
+ anti_pattern = ~pattern;
+ addr[offset] = anti_pattern;
+ }
+
+ /*
+ * Check each location for the inverted pattern and zero it.
+ */
+ for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
+ WATCHDOG_RESET();
+ anti_pattern = ~pattern;
+ temp = addr[offset];
+ if (temp != anti_pattern) {
+ printf("\nFAILURE (read/write): @ 0x%.5lx:"
+ " expected 0x%.5lx, actual 0x%.5lx)\n",
+ start_addr + offset*sizeof(vu_long),
+ anti_pattern, temp);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+ addr[offset] = 0;
+ }
+
+ return 0;
+}
+
+static uint32_t mem_test_quick(vu_long *buf, uint32_t start_addr, uint32_t end_addr,
+ vu_long pattern, int iteration)
+{
+ vu_long *end;
+ vu_long *addr;
+ uint32_t errs = 0;
+ uint32_t incr, length;
+ uint32_t val, readback;
+
+ /* Alternate the pattern */
+ incr = 1;
+ if (iteration & 1) {
+ incr = -incr;
+ /*
+ * Flip the pattern each time to make lots of zeros and
+ * then, the next time, lots of ones. We decrement
+ * the "negative" patterns and increment the "positive"
+ * patterns to preserve this feature.
+ */
+ if (pattern & 0x80000000)
+ pattern = -pattern; /* complement & increment */
+ else
+ pattern = ~pattern;
+ }
+ length = (end_addr - start_addr) / sizeof(uint32_t);
+ end = buf + length;
+ printf("\rPattern %08lX Writing..."
+ "%12s"
+ "\b\b\b\b\b\b\b\b\b\b",
+ pattern, "");
+
+ for (addr = buf, val = pattern; addr < end; addr++) {
+ *addr = val;
+ val += incr;
+ }
+
+ my_puts("Reading...");
+
+ for (addr = buf, val = pattern; addr < end; addr++) {
+ readback = *addr;
+ if (readback != val) {
+ uint32_t offset = addr - buf;
+
+ printf("\nMem error @ 0x%08X: "
+ "found %08lX, expected %08lX\n",
+ (unsigned int)(uintptr_t)(start_addr + offset*sizeof(vu_long)),
+ readback, val);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+ val += incr;
+ }
+
+ return 0;
+}
+
+/*
+ * Perform a memory test. A more complete alternative test can be
+ * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until
+ * interrupted by ctrl-c or by a failure of one of the sub-tests.
+ */
+int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ uint32_t start, end;
+ vu_long *buf, *dummy;
+ int iteration_limit;
+ int ret;
+ uint32_t errs = 0; /* number of errors, or -1 if interrupted */
+ uint32_t pattern;
+ int iteration;
+#if defined(CONFIG_SYS_ALT_MEMTEST)
+ const int alt_test = 1;
+#else
+ const int alt_test = 0;
+#endif
+
+ if (argc > 1)
+ start = strtoul(argv[1], NULL, 16);
+ else
+ start = CONFIG_SYS_MEMTEST_START;
+
+ if (argc > 2)
+ end = strtoul(argv[2], NULL, 16);
+ else
+ end = CONFIG_SYS_MEMTEST_END;
+
+ if (argc > 3)
+ pattern = (uint32_t)strtoul(argv[3], NULL, 16);
+ else
+ pattern = 0;
+
+ if (argc > 4)
+ iteration_limit = (uint32_t)strtoul(argv[4], NULL, 16);
+ else
+ iteration_limit = 0;
+
+ printf("Testing %08x ... %08x:\n", (unsigned int)start, (unsigned int)end);
+ debug("%s:%d: start %#05lx end %#05lx\n", __func__, __LINE__,
+ start, end);
+
+/* TODO: */
+// buf = map_sysmem(start, end - start);
+// dummy = map_sysmem(CONFIG_SYS_MEMTEST_SCRATCH, sizeof(vu_long));
+ for (iteration = 0;
+ !iteration_limit || iteration < iteration_limit;
+ iteration++) {
+ if (ctrlc()) {
+ errs = -1UL;
+ break;
+ }
+
+ printf("Iteration: %6d\r", iteration + 1);
+ debug("\n");
+ if (alt_test) {
+ errs = mem_test_alt(buf, start, end, dummy);
+ } else {
+ errs = mem_test_quick(buf, start, end, pattern,
+ iteration);
+ }
+ if (errs == -1UL)
+ break;
+ }
+
+ if (errs == -1UL) {
+ /* Memory test was aborted - write a newline to finish off */
+ putc('\n');
+ ret = 1;
+ } else {
+ printf("Tested %d iteration(s) with %lu errors.\n",
+ iteration, errs);
+ ret = errs != 0;
+ }
+
+ return ret; /* not reached */
+}
+#endif /* CONFIG_CMD_MEMTEST */
+
+/* Modify memory.
+ *
+ * Syntax:
+ * mm {addr}
+ * nm {addr}
+ */
+static int
+mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
+{
+ uint32_t addr;
+ uint8_t data;
+ int nbytes;
+
+ (void) cmdtp;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ /* We use the last specified parameters, unless new ones are
+ * entered.
+ */
+ addr = mm_last_addr;
+
+ if ((flag & CMD_FLAG_REPEAT) == 0) {
+ /* New command specified.
+ */
+
+ /* Address is specified since argc > 1
+ */
+ addr = strtoul(argv[1], NULL, 16);
+ addr += base_address;
+ }
+
+ /* Print the address, followed by value. Then accept input for
+ * the next value. A non-converted value exits.
+ */
+ do {
+ z80_bus_cmd(Request);
+ data = z80_read(addr);
+ printf("%05lx: %02x", addr, data);
+ z80_bus_cmd(Release);
+
+ nbytes = cli_readline(PSTR(" ? "));
+ if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
+ /* <CR> pressed as only input, don't modify current
+ * location and move to next. "-" pressed will go back.
+ */
+ if (incrflag)
+ addr += nbytes ? -1 : 1;
+ nbytes = 1;
+ }
+ else {
+ char *endp;
+ data = strtoul(console_buffer, &endp, 16);
+ nbytes = endp - console_buffer;
+ if (nbytes) {
+ z80_bus_cmd(Request);
+ z80_write(addr, data);
+ z80_bus_cmd(Release);
+ if (incrflag)
+ addr++;
+ }
+ }
+ } while (nbytes);
+
+ mm_last_addr = addr;
+ return 0;
+}
+
--- /dev/null
+#ifndef CMD_MEM_H
+#define CMD_MEM_H
+
+//#include "common.h"
+
+#include "command.h"
+#include "cmd_mem.h"
+
+
+extern int do_mem_md(cmd_tbl_t *, int, int, char * const []);
+extern int do_mem_mm(cmd_tbl_t *, int, int, char * const []);
+extern int do_mem_nm(cmd_tbl_t *, int, int, char * const []);
+extern int do_mem_mw(cmd_tbl_t *, int, int, char * const []);
+extern int do_mem_cp(cmd_tbl_t *, int, int, char * const []);
+extern int do_mem_cmp(cmd_tbl_t *, int, int, char * const []);
+extern int do_mem_base(cmd_tbl_t *, int, int, char * const []);
+extern int do_mem_loop(cmd_tbl_t *, int, int, char * const []);
+#ifdef CONFIG_LOOPW
+extern int do_mem_loopw(cmd_tbl_t *, int, int, char * const []);
+#endif
+#ifdef CONFIG_CMD_MEMTEST
+extern int do_mem_mtest(cmd_tbl_t *, int, int, char * const []);
+#endif
+#ifdef CONFIG_MX_CYCLIC
+extern int do_mem_mdc(cmd_tbl_t *, int, int, char * const []);
+extern int do_mem_mwc(cmd_tbl_t *, int, int, char * const []);
+#endif /* CONFIG_MX_CYCLIC */
+
+#endif /* CMD_MEM_H */
+
--- /dev/null
+
+/*
+ * Command Processor Table
+ */
+
+#include "common.h"
+
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "config.h"
+#include "debug.h"
+#include "con-utils.h"
+#include "env.h"
+#include "timer.h"
+#include "command.h"
+
+
+static void print_blanks(int_fast8_t count)
+{
+ while(count--)
+ my_puts_P(PSTR(" "));
+}
+
+static void print_usage_line(const FLASH char *name, const FLASH char *usage)
+{
+ my_puts_P(name);
+ print_blanks(CONFIG_SYS_MAXARGS - strlen_P(name));
+ my_puts_P(PSTR(" - "));
+ my_puts_P(usage);
+ my_puts_P(PSTR("\n"));
+}
+
+int strcmp_PP(const FLASH char *s1, const FLASH char *s2)
+{
+ unsigned char c1, c2;
+
+ while ((c1 = *(const FLASH unsigned char *)s1++)
+ == (c2 = *(const FLASH unsigned char *)s2++))
+ if (c1 == 0)
+ return 0;
+
+ return c1 - c2;
+}
+
+int cmpstringp(const void *p1, const void *p2)
+{
+ return strcmp_PP((*(const FLASH cmd_tbl_t **) p1)->name,
+ (*(const FLASH cmd_tbl_t **) p2)->name);
+}
+
+int cmd_tbl_item_count(void)
+{
+ cmd_tbl_t * p = cmd_tbl;
+ int count = 0;
+
+ while (p->name != NULL) {
+ p++; count++;
+ }
+ return count;
+}
+
+/*
+ * Use puts() instead of printf() to avoid printf buffer overflow
+ * for long help messages
+ */
+
+int _do_help(cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t * cmdtp,
+ int flag, int argc, char * const argv[])
+{
+ uint_fast8_t i;
+ int rcode = 0;
+
+ (void) flag;
+
+ if (argc == 1) { /*show list of commands */
+ cmd_tbl_t *cmd_array[cmd_items];
+ int i;
+
+ /* Make array of commands from .uboot_cmd section */
+ cmdtp = cmd_start;
+ for (i = 0; i < cmd_items; i++) {
+ cmd_array[i] = cmdtp++;
+ }
+
+ /* Sort command list */
+ qsort(cmd_array, cmd_items, sizeof (cmd_tbl_t *), cmpstringp);
+
+ /* print short help (usage) */
+ for (i = 0; i < cmd_items; i++) {
+ const FLASH char *usage = cmd_array[i]->usage;
+
+ /* allow user abort */
+ if (ctrlc ())
+ return 1;
+ if (usage == NULL)
+ continue;
+#ifdef GCC_BUG_61443
+ print_usage_line(cmd_array[i]->name, usage);
+#else
+ printf_P(PSTR("%-" stringify(CONFIG_SYS_MAXARGS) "S - %S\n"),
+ cmd_array[i]->name, usage);
+#endif
+ }
+ return 0;
+ }
+ /*
+ * command help (long version)
+ */
+ for (i = 1; i < argc; ++i) {
+ if ((cmdtp = find_cmd_tbl (argv[i], cmd_start, cmd_items )) != NULL) {
+ rcode |= cmd_usage(cmdtp);
+ } else {
+ printf_P(PSTR("Unknown command '%s' - try 'help'"
+ " without arguments.\n\n"), argv[i]
+ );
+ rcode = 1;
+ }
+ }
+ return rcode;
+}
+
+/***************************************************************************
+ * find command table entry for a command
+ */
+cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len)
+{
+ cmd_tbl_t *cmdtp;
+ cmd_tbl_t *cmdtp_temp = table; /*Init value */
+ size_t len;
+ uint_fast8_t n_found = 0;
+
+ if (!cmd)
+ return NULL;
+
+ len = strlen(cmd);
+
+ for (cmdtp = table;
+ cmdtp != table + table_len;
+ cmdtp++) {
+ if (strncmp_P (cmd, cmdtp->name, len) == 0) {
+ if (len == strlen (cmdtp->name))
+ return cmdtp; /* full match */
+
+ cmdtp_temp = cmdtp; /* abbreviated command ? */
+ n_found++;
+ }
+ }
+ if (n_found == 1) { /* exactly one match */
+ return cmdtp_temp;
+ }
+
+ return NULL; /* not found or ambiguous command */
+}
+
+
+cmd_tbl_t *find_cmd (const char *cmd)
+{
+ return find_cmd_tbl(cmd, cmd_tbl, cmd_tbl_item_count());
+}
+
+
+int cmd_usage(const FLASH cmd_tbl_t *cmdtp)
+{
+// printf("%s - %s\n\n", cmdtp->name, cmdtp->usage);
+ print_usage_line(cmdtp->name, cmdtp->usage);
+#if 0
+ my_puts_P(cmdtp->name);
+ print_blanks(CONFIG_SYS_MAXARGS - strlen_P(cmdtp->name));
+ my_puts_P(PSTR(" - "));
+ my_puts_P(cmdtp->usage);
+ my_puts_P(PSTR("\n\n"));
+#endif
+#ifdef CONFIG_SYS_LONGHELP
+// printf("Usage:\n%s ", cmdtp->name);
+ my_puts_P(PSTR("Usage:\n"));
+ my_puts_P(cmdtp->name);
+ my_puts_P(PSTR(" "));
+
+ if (!cmdtp->help) {
+ my_puts_P(PSTR(" - No additional help available.\n"));
+ return 1;
+ }
+
+ my_puts_P(cmdtp->help);
+ my_puts_P(PSTR("\n"));
+#endif /* CONFIG_SYS_LONGHELP */
+ return 1;
+}
+
+#ifdef CONFIG_AUTO_COMPLETE
+
+int var_complete(int argc, char * const argv[], char last_char, int maxv, char *cmdv[])
+{
+ static char tmp_buf[512];
+ int space;
+
+ space = last_char == '\0' || isblank(last_char);
+
+ if (space && argc == 1)
+ return env_complete("", maxv, cmdv, sizeof(tmp_buf), tmp_buf);
+
+ if (!space && argc == 2)
+ return env_complete(argv[1], maxv, cmdv, sizeof(tmp_buf), tmp_buf);
+
+ return 0;
+}
+
+/*************************************************************************************/
+
+static int complete_cmdv(int argc, char * const argv[], char last_char, int maxv, char *cmdv[])
+{
+ cmd_tbl_t *cmdtp = cmd_tbl;
+// const int count = ARRAY_SIZE(cmd_tbl);
+// const cmd_tbl_t *cmdend = cmdtp + count;
+// const char *p;
+ int len, clen;
+ int n_found = 0;
+ const char *cmd;
+
+ /* sanity? */
+ if (maxv < 2)
+ return -2;
+
+ cmdv[0] = NULL;
+
+ if (argc == 0) {
+ /* output full list of commands */
+ for (; cmdtp->name[0] != '\0'; cmdtp++) {
+ if (n_found >= maxv - 2) {
+ cmdv[n_found++] = "...";
+ break;
+ }
+ cmdv[n_found++] = cmdtp->name;
+ }
+ cmdv[n_found] = NULL;
+ return n_found;
+ }
+
+ /* more than one arg or one but the start of the next */
+ if (argc > 1 || (last_char == '\0' || isblank(last_char))) {
+ cmdtp = find_cmd(argv[0]);
+ if (cmdtp == NULL || cmdtp->complete == NULL) {
+ cmdv[0] = NULL;
+ return 0;
+ }
+ return (*cmdtp->complete)(argc, argv, last_char, maxv, cmdv);
+ }
+
+ cmd = argv[0];
+
+ len = strlen(cmd);
+
+ /* return the partial matches */
+ for (; cmdtp->name[0] != '\0'; cmdtp++) {
+
+ clen = strlen(cmdtp->name);
+ if (clen < len)
+ continue;
+
+ if (memcmp(cmd, cmdtp->name, len) != 0)
+ continue;
+
+ /* too many! */
+ if (n_found >= maxv - 2) {
+ cmdv[n_found++] = "...";
+ break;
+ }
+
+ cmdv[n_found++] = cmdtp->name;
+ }
+
+ cmdv[n_found] = NULL;
+ return n_found;
+}
+
+static int make_argv(char *s, int argvsz, char *argv[])
+{
+ int argc = 0;
+
+ /* split into argv */
+ while (argc < argvsz - 1) {
+
+ /* skip any white space */
+ while (isblank(*s))
+ ++s;
+
+ if (*s == '\0') /* end of s, no more args */
+ break;
+
+ argv[argc++] = s; /* begin of argument string */
+
+ /* find end of string */
+ while (*s && !isblank(*s))
+ ++s;
+
+ if (*s == '\0') /* end of s, no more args */
+ break;
+
+ *s++ = '\0'; /* terminate current arg */
+ }
+ argv[argc] = NULL;
+
+ return argc;
+}
+
+static void print_argv(const char *banner, const char *leader, const char *sep, int linemax, char * const argv[])
+{
+ int ll = leader != NULL ? strlen(leader) : 0;
+ int sl = sep != NULL ? strlen(sep) : 0;
+ int len, i;
+
+ if (banner) {
+ my_puts_P(PSTR("\n"));
+ my_puts(banner);
+ }
+
+ i = linemax; /* force leader and newline */
+ while (*argv != NULL) {
+ len = strlen(*argv) + sl;
+ if (i + len >= linemax) {
+ my_puts_P(PSTR("\n"));
+ if (leader)
+ my_puts(leader);
+ i = ll - sl;
+ } else if (sep)
+ my_puts(sep);
+ my_puts(*argv++);
+ i += len;
+ }
+ my_puts_P(PSTR("\n"));
+}
+
+static int find_common_prefix(char * const argv[])
+{
+ int i, len;
+ char *anchor, *s, *t;
+
+ if (*argv == NULL)
+ return 0;
+
+ /* begin with max */
+ anchor = *argv++;
+ len = strlen(anchor);
+ while ((t = *argv++) != NULL) {
+ s = anchor;
+ for (i = 0; i < len; i++, t++, s++) {
+ if (*t != *s)
+ break;
+ }
+ len = s - anchor;
+ }
+ return len;
+}
+
+static char tmp_buf[CONFIG_SYS_CBSIZE]; /* copy of console I/O buffer */
+
+int cmd_auto_complete(const FLASH char *const prompt, char *buf, int *np, int *colp)
+{
+ int n = *np, col = *colp;
+ char *argv[CONFIG_SYS_MAXARGS + 1]; /* NULL terminated */
+ char *cmdv[20];
+ char *s, *t;
+ const char *sep;
+ int i, j, k, len, seplen, argc;
+ int cnt;
+ char last_char;
+
+ if (strcmp_PP(prompt, CONFIG_SYS_PROMPT) != 0)
+ return 0; /* not in normal console */
+
+ cnt = strlen(buf);
+ if (cnt >= 1)
+ last_char = buf[cnt - 1];
+ else
+ last_char = '\0';
+
+ /* copy to secondary buffer which will be affected */
+ strcpy(tmp_buf, buf);
+
+ /* separate into argv */
+ argc = make_argv(tmp_buf, sizeof(argv)/sizeof(argv[0]), argv);
+
+ /* do the completion and return the possible completions */
+ i = complete_cmdv(argc, argv, last_char, sizeof(cmdv)/sizeof(cmdv[0]), cmdv);
+
+ /* no match; bell and out */
+ if (i == 0) {
+ if (argc > 1) /* allow tab for non command */
+ return 0;
+ putchar('\a');
+ return 1;
+ }
+
+ s = NULL;
+ len = 0;
+ sep = NULL;
+ seplen = 0;
+ if (i == 1) { /* one match; perfect */
+ k = strlen(argv[argc - 1]);
+ s = cmdv[0] + k;
+ len = strlen(s);
+ sep = " ";
+ seplen = 1;
+ } else if (i > 1 && (j = find_common_prefix(cmdv)) != 0) { /* more */
+ k = strlen(argv[argc - 1]);
+ j -= k;
+ if (j > 0) {
+ s = cmdv[0] + k;
+ len = j;
+ }
+ }
+
+ if (s != NULL) {
+ k = len + seplen;
+ /* make sure it fits */
+ if (n + k >= CONFIG_SYS_CBSIZE - 2) {
+ putchar('\a');
+ return 1;
+ }
+
+ t = buf + cnt;
+ for (i = 0; i < len; i++)
+ *t++ = *s++;
+ if (sep != NULL)
+ for (i = 0; i < seplen; i++)
+ *t++ = sep[i];
+ *t = '\0';
+ n += k;
+ col += k;
+ my_puts(t - k);
+ if (sep == NULL)
+ putchar('\a');
+ *np = n;
+ *colp = col;
+ } else {
+ print_argv(NULL, " ", " ", 78, cmdv);
+
+ my_puts_P(prompt);
+ my_puts(buf);
+ }
+ return 1;
+}
+
+#endif /* CONFIG_AUTO_COMPLETE */
+
+
+
+/**
+ * Call a command function. This should be the only route in U-Boot to call
+ * a command, so that we can track whether we are waiting for input or
+ * executing a command.
+ *
+ * @param cmdtp Pointer to the command to execute
+ * @param flag Some flags normally 0 (see CMD_FLAG_.. above)
+ * @param argc Number of arguments (arg 0 must be the command text)
+ * @param argv Arguments
+ * @return 0 if command succeeded, else non-zero (CMD_RET_...)
+ */
+static int cmd_call(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int result;
+
+ result = (cmdtp->cmd)(cmdtp, flag, argc, argv);
+ if (result)
+ debug("Command failed, result=%d\n", result);
+ return result;
+}
+
+enum command_ret_t cmd_process(int flag, int argc, char * const argv[],
+ uint_fast8_t *repeatable)
+{
+ enum command_ret_t rc = CMD_RET_SUCCESS;
+ cmd_tbl_t *cmdtp;
+
+ /* Look up command in command table */
+ cmdtp = find_cmd(argv[0]);
+ if (cmdtp == NULL) {
+ printf_P(PSTR("Unknown command '%s' - try 'help'\n"), argv[0]);
+ return 1;
+ }
+ if (!cmdtp->cmd) {
+ debug("### Command '%s' found, but ->cmd == NULL \n", argv[0]);
+ return 1;
+ }
+
+ /* found - check max args */
+ if (argc > cmdtp->maxargs)
+ rc = CMD_RET_USAGE;
+
+#if defined(CONFIG_CMD_BOOTD)
+ /* avoid "bootd" recursion */
+ else if (cmdtp->cmd == do_bootd) {
+ if (flag & CMD_FLAG_BOOTD) {
+ my_puts_P(PSTR("'bootd' recursion detected\n"));
+ rc = CMD_RET_FAILURE;
+ } else {
+ flag |= CMD_FLAG_BOOTD;
+ }
+ }
+#endif
+
+ /* If OK so far, then do the command */
+ if (!rc) {
+ rc = cmd_call(cmdtp, flag, argc, argv);
+ *repeatable &= cmdtp->repeatable;
+ }
+ if (rc == CMD_RET_USAGE)
+ rc = cmd_usage(cmdtp);
+ return rc;
+}
+
+int cmd_process_error(cmd_tbl_t *cmdtp, int err)
+{
+ char buf[strlen_P(cmdtp->name) + 1];
+ strcpy_P(buf, cmdtp->name);
+
+ if (err) {
+ printf_P(PSTR("Command '%s' failed: Error %d\n"), buf, err);
+ return 1;
+ }
+
+ return 0;
+}
--- /dev/null
+
+/*
+ * Definitions for Command Processor
+ */
+#ifndef __COMMAND_H
+#define __COMMAND_H
+
+#include "common.h"
+#include "config.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* Default to a width of 8 characters for help message command width */
+#ifndef CONFIG_SYS_HELP_CMD_WIDTH
+#define CONFIG_SYS_HELP_CMD_WIDTH 8
+#endif
+
+/*
+ * Monitor Command Table
+ */
+
+struct cmd_tbl_s {
+ const FLASH char *name; /* Command Name */
+ int maxargs; /* maximum number of arguments */
+ int repeatable; /* autorepeat allowed? */
+ /* Implementation function */
+ int (*cmd)(const FLASH struct cmd_tbl_s *, int, int, char * const []);
+ const FLASH char *usage; /* Usage message (short) */
+#ifdef CONFIG_SYS_LONGHELP
+ const FLASH char *help; /* Help message (long) */
+#endif
+#ifdef CONFIG_AUTO_COMPLETE
+ /* do auto completion on the arguments */
+ int (*complete)(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]);
+#endif
+};
+
+typedef const FLASH struct cmd_tbl_s cmd_tbl_t;
+
+extern int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+
+/* command.c */
+int _do_help (cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t * cmdtp, int
+ flag, int argc, char * const argv[]);
+cmd_tbl_t *find_cmd(const char *cmd);
+cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len);
+
+int cmd_tbl_item_count(void);
+int cmd_usage(cmd_tbl_t *cmdtp);
+
+#ifdef CONFIG_AUTO_COMPLETE
+extern int var_complete(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]);
+extern int cmd_auto_complete(const char *const prompt, char *buf, int *np, int *colp);
+#endif
+
+/**
+ * cmd_process_error() - report and process a possible error
+ *
+ * @cmdtp: Command which caused the error
+ * @err: Error code (0 if none, -ve for error, like -EIO)
+ * @return 0 if there is not error, 1 (CMD_RET_FAILURE) if an error is found
+ */
+int cmd_process_error(cmd_tbl_t *cmdtp, int err);
+
+/*
+ * Monitor Command
+ *
+ * All commands use a common argument format:
+ *
+ * void function (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+ */
+
+
+#ifdef CONFIG_CMD_BOOTD
+extern int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+#endif
+#ifdef CONFIG_CMD_BOOTM
+extern int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+extern int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd);
+#else
+static inline int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
+{
+ (void) cmdtp; (void) cmd;
+
+ return 0;
+}
+#endif
+
+extern int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc,
+ char *const argv[]);
+
+extern int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+
+/*
+ * Error codes that commands return to cmd_process(). We use the standard 0
+ * and 1 for success and failure, but add one more case - failure with a
+ * request to call cmd_usage(). But the cmd_process() function handles
+ * CMD_RET_USAGE itself and after calling cmd_usage() it will return 1.
+ * This is just a convenience for commands to avoid them having to call
+ * cmd_usage() all over the place.
+ */
+enum command_ret_t {
+ CMD_RET_SUCCESS, /* 0 = Success */
+ CMD_RET_FAILURE, /* 1 = Failure */
+ CMD_RET_USAGE = -1, /* Failure, please report 'usage' error */
+};
+
+/**
+ * Process a command with arguments. We look up the command and execute it
+ * if valid. Otherwise we print a usage message.
+ *
+ * @param flag Some flags normally 0 (see CMD_FLAG_.. above)
+ * @param argc Number of arguments (arg 0 must be the command text)
+ * @param argv Arguments
+ * @param repeatable This function sets this to 0 if the command is not
+ * repeatable. If the command is repeatable, the value
+ * is left unchanged.
+ * @return 0 if the command succeeded, 1 if it failed
+ */
+int cmd_process(int flag, int argc, char * const argv[], uint_fast8_t *repeatable);
+
+
+/*
+ * Command Flags:
+ */
+#define CMD_FLAG_REPEAT 0x0001 /* repeat last command */
+#define CMD_FLAG_BOOTD 0x0002 /* command is from bootd */
+
+#ifdef CONFIG_AUTO_COMPLETE
+# define _CMD_COMPLETE(x) x,
+#else
+# define _CMD_COMPLETE(x)
+#endif
+#ifdef CONFIG_SYS_LONGHELP
+# define _CMD_HELP(x) x,
+#else
+# define _CMD_HELP(x)
+#endif
+
+
+#define CMD_TBL_ITEM_COMPLETE(_name, _maxargs, _rep, _cmd, \
+ _usage, _help, _comp) \
+ { FSTR(#_name), _maxargs, _rep, _cmd, FSTR(_usage), \
+ _CMD_HELP(FSTR(_help)) _CMD_COMPLETE(_comp) }
+
+#define CMD_TBL_ITEM(_name, _maxargs, _rep, _cmd, _usage, _help) \
+ CMD_TBL_ITEM_COMPLETE(_name, _maxargs, _rep, _cmd, \
+ _usage, _help, NULL)
+
+typedef int (*do_cmd_t)(cmd_tbl_t *, int, int, char * const []);
+
+extern cmd_tbl_t cmd_tbl[];
+
+
+#endif /* __COMMAND_H */
--- /dev/null
+
+#include "common.h"
+
+#include "command.h"
+#include "cmd_mem.h"
+
+
+extern int do_help(cmd_tbl_t *, int, int, char * const []);
+extern int do_echo(cmd_tbl_t *, int, int, char * const []);
+extern int do_env_print(cmd_tbl_t *, int, int, char * const []);
+extern int do_env_set(cmd_tbl_t *, int, int, char * const []);
+extern int do_env_save(cmd_tbl_t *, int, int, char * const []);
+extern int do_loadf(cmd_tbl_t *, int, int, char * const []);
+extern int do_go(cmd_tbl_t *, int, int, char * const []);
+extern int do_restart(cmd_tbl_t *, int, int, char * const []);
+extern int do_dump_mem(cmd_tbl_t *, int, int, char * const []);
+extern int do_eep_cp(cmd_tbl_t *, int, int, char * const []);
+extern int do_busreq_pulse(cmd_tbl_t *, int, int, char * const []);
+
+
+cmd_tbl_t cmd_tbl[] = {
+
+#ifdef DEBUG
+CMD_TBL_ITEM(
+ !mdr, 3, 1, do_dump_mem,
+ "RAM dump",
+ "address [count]"
+),
+CMD_TBL_ITEM(
+ !mde, 3, 1, do_dump_mem,
+ "EEPROM dump",
+ "address [count]"
+),
+CMD_TBL_ITEM(
+ !cpe, 4, 0, do_eep_cp,
+ "EEPROM copy",
+ "source target count"
+),
+#endif
+CMD_TBL_ITEM(
+ mstep, 2, 1, do_busreq_pulse,
+ "execute one M cycle",
+ "[count]\n"
+ " - repeat count times"
+),
+CMD_TBL_ITEM(
+ echo, CONFIG_SYS_MAXARGS, 1, do_echo,
+ "echo args to console",
+ "[args..]\n"
+ " - echo args to console; \\c suppresses newline"
+),
+CMD_TBL_ITEM_COMPLETE(
+ run, CONFIG_SYS_MAXARGS, 1, do_run,
+ "run commands in an environment variable",
+ "var [...]\n"
+ " - run the commands in the environment variable(s) 'var'",
+ var_complete
+),
+CMD_TBL_ITEM_COMPLETE(
+ printenv, CONFIG_SYS_MAXARGS, 1, do_env_print,
+ "print environment variables",
+ "\n"
+ " - print values of all environment variables\n"
+ "printenv name ...\n"
+ " - print value of environment variable 'name'",
+ var_complete
+),
+CMD_TBL_ITEM_COMPLETE(
+ setenv, CONFIG_SYS_MAXARGS, 0, do_env_set,
+ "set environment variables",
+ "name value ...\n"
+ " - set environment variable 'name' to 'value ...'\n"
+ "setenv name\n"
+ " - delete environment variable 'name'",
+ var_complete
+),
+CMD_TBL_ITEM(
+ saveenv, 1, 0, do_env_save,
+ "save environment variables to persistent storage",
+ ""
+),
+
+CMD_TBL_ITEM(
+ loadf, 1, 0, do_loadf,
+ "load srec_cat prepared image from controller flash",
+ ""
+),
+CMD_TBL_ITEM(
+ go, 2, 0, do_go,
+ "start application at address 'addr'",
+ "addr\n"
+ " - start application at address 'addr'"
+// "\n"
+// " passing 'arg' as arguments"
+),
+CMD_TBL_ITEM(
+ reset, 1, 0, do_reset,
+ "Keep CPU in RESET state",
+ ""
+),
+CMD_TBL_ITEM(
+ restart, 1, 0, do_restart,
+ "Perform RESET of the CPU",
+ ""
+),
+
+CMD_TBL_ITEM(
+ md, 3, 1, do_mem_md,
+ "memory display",
+ "address [# of objects]"
+),
+CMD_TBL_ITEM(
+ mm, 2, 1, do_mem_mm,
+ "memory modify (auto-incrementing address)",
+ "address"
+),
+CMD_TBL_ITEM(
+ nm, 2, 1, do_mem_nm,
+ "memory modify (constant address)",
+ "address"
+),
+CMD_TBL_ITEM(
+ mw, 4, 1, do_mem_mw,
+ "memory write (fill)",
+ "address value [count]"
+),
+CMD_TBL_ITEM(
+ cp, 4, 1, do_mem_cp,
+ "memory copy",
+ "source target count"
+),
+CMD_TBL_ITEM(
+ cmp, 4, 1, do_mem_cmp,
+ "memory compare",
+ "addr1 addr2 count"
+),
+CMD_TBL_ITEM(
+ base, 2, 1, do_mem_base,
+ "print or set address offset",
+ "\n"
+ " - print address offset for memory commands\n"
+ "base offset\n"
+ " - set address offset for memory commands to 'offset'"
+),
+CMD_TBL_ITEM(
+ loop, 3, 1, do_mem_loop,
+ "infinite loop on address range",
+ "address number_of_bytes"
+),
+#ifdef CONFIG_LOOPW
+CMD_TBL_ITEM(
+ loopw, 4, 1, do_mem_loopw,
+ "infinite write loop on address range",
+ "address number_of_bytes data_to_write"
+),
+#endif /* CONFIG_LOOPW */
+
+#ifdef CONFIG_CMD_MEMTEST
+CMD_TBL_ITEM(
+ mtest, 5, 1, do_mem_mtest,
+ "simple RAM read/write test",
+ "[start [end [pattern [iterations]]]]"
+),
+#endif /* CONFIG_CMD_MEMTEST */
+
+#ifdef CONFIG_MX_CYCLIC
+CMD_TBL_ITEM(
+ mdc, 4, 1, do_mem_mdc,
+ "memory display cyclic",
+ "address count delay(ms)"
+),
+CMD_TBL_ITEM(
+ mwc, 4, 1, do_mem_mwc,
+ "memory write cyclic",
+ "address value delay(ms)"
+),
+#endif /* CONFIG_MX_CYCLIC */
+
+
+CMD_TBL_ITEM(
+ help, CONFIG_SYS_MAXARGS, 1, do_help,
+ "print command description/usage",
+ "\n"
+ " - print brief description of all commands\n"
+ "help command ...\n"
+ " - print detailed usage of 'command'"
+),
+
+/* This does not use the CMD_TBL_ITEM macro as ? can't be used in symbol names */
+ {FSTR("?"), CONFIG_SYS_MAXARGS, 1, do_help,
+ FSTR("alias for 'help'"),
+#ifdef CONFIG_SYS_LONGHELP
+ FSTR(""),
+#endif /* CONFIG_SYS_LONGHELP */
+#ifdef CONFIG_AUTO_COMPLETE
+ 0,
+#endif
+},
+/* Mark end of table */
+{ 0 },
+};
--- /dev/null
+#ifndef COMMON_H
+#define COMMON_H
+
+#ifdef __AVR__
+#include <avr/io.h>
+
+//TODO:
+// Known to work: 4.8.4, 4.9.1
+// Known to fail: 4.8.3, 4.9.0
+#define GCC_BUG_61443 1
+
+#else
+// TODO: stm32
+#endif /* __AVR__ */
+
+#include <stdio.h>
+
+#ifdef __FLASH
+#define FLASH __flash
+#else
+#define FLASH
+#endif
+
+#define stringify(s) tostring(s)
+#define tostring(s) #s
+
+#define FSTR(X) ((const FLASH char[]) { X } )
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+
+#ifdef __AVR__
+#define Stat GPIOR0
+#else
+extern volatile uint_least8_t Stat;
+#endif /* __AVR__ */
+
+#define S_10MS_TO (1<<0)
+#define S_Z180_RUNNING (2<<0)
+
+static inline
+void my_puts(const char *s)
+{
+ fputs(s, stdout);
+}
+
+#ifdef __AVR__
+static inline
+void my_puts_P(const char *s)
+{
+ fputs_P(s, stdout);
+}
+
+#else
+static inline
+void my_puts_P(const char *s)
+{
+ fputs(s, stdout);
+}
+#endif /* __AVR__ */
+#endif /* COMMON_H */
+
--- /dev/null
+
+#include <string.h>
+#include "common.h"
+
+#include "serial.h"
+#include "background.h"
+#include "con-utils.h"
+
+uint_fast8_t tstc(void)
+{
+ bg_shed();
+ return serial_tstc();
+}
+
+int my_getchar(void)
+{
+ int c;
+
+ do {
+ bg_shed();
+ c = serial_getc();
+ } while (c < 0);
+
+ return c;
+}
+
+
+/* test if ctrl-c was pressed */
+
+static uint_fast8_t ctrlc_disabled; /* see disable_ctrl() */
+static uint_fast8_t ctrlc_was_pressed;
+
+uint_fast8_t ctrlc(void)
+{
+ if (!ctrlc_disabled) {
+ switch (serial_getc()) {
+ case 0x03: /* ^C - Control C */
+ ctrlc_was_pressed = 1;
+ return 1;
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+/* Reads user's confirmation.
+ Returns 1 if user's input is "y", "Y", "yes" or "YES"
+*/
+uint_fast8_t confirm_yesno(void)
+{
+ unsigned int i;
+ char str_input[5];
+
+ /* Flush input */
+ while (serial_getc())
+ ;
+ i = 0;
+ while (i < sizeof(str_input)) {
+ str_input[i] = my_getchar();
+ putchar(str_input[i]);
+ if (str_input[i] == '\r')
+ break;
+ i++;
+ }
+ putchar('\n');
+ if (strncmp(str_input, "y\r", 2) == 0 ||
+ strncmp(str_input, "Y\r", 2) == 0 ||
+ strncmp(str_input, "yes\r", 4) == 0 ||
+ strncmp(str_input, "YES\r", 4) == 0)
+ return 1;
+ return 0;
+}
+
+/* pass 1 to disable ctrlc() checking, 0 to enable.
+ * returns previous state
+ */
+uint_fast8_t disable_ctrlc(uint_fast8_t disable)
+{
+ uint_fast8_t prev = ctrlc_disabled; /* save previous state */
+
+ ctrlc_disabled = disable;
+ return prev;
+}
+
+uint_fast8_t had_ctrlc (void)
+{
+ return ctrlc_was_pressed;
+}
+
+void clear_ctrlc(void)
+{
+ ctrlc_was_pressed = 0;
+}
+
--- /dev/null
+#ifndef CON_UTILS_H
+#define CON_UTILS_H
+
+uint_fast8_t tstc(void);
+
+int my_getchar(void);
+
+/* test if ctrl-c was pressed */
+uint_fast8_t ctrlc(void);
+
+
+/* pass 1 to disable ctrlc() checking, 0 to enable.
+ * returns previous state
+ */
+uint_fast8_t disable_ctrlc(uint_fast8_t disable);
+
+uint_fast8_t had_ctrlc (void);
+void clear_ctrlc(void);
+
+#endif /* CON_UTILS_H */
+
+
--- /dev/null
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#define CONFIG_ENV_SIZE 1600
+#define CONFIG_ENV_OFFSET 0
+#define CONFIG_ENVVAR_MAX 20
+
+#define CONFIG_BOOTDELAY 4
+//#define CONFIG_ZERO_BOOTDELAY_CHECK 1
+
+//#define CONFIG_LOOPW
+//#define CONFIG_CMD_MEMTEST
+//#define CONFIG_MX_CYCLIC
+
+#define CONFIG_SYS_CBSIZE 250
+#define CONFIG_SYS_ENV_NAMELEN 16
+#define CONFIG_SYS_MAXARGS 8
+
+#define CONFIG_SYS_PROMPT "=> "
+
+
+//#define CONFIG_CMDLINE_EDITING 1
+//#define CONFIG_AUTO_COMPLETE 1
+
+#define CONFIG_SYS_LONGHELP 1
+
+#endif /* CONFIG_H */
+
--- /dev/null
+#ifndef CRC_H
+#define CRC_H
+
+#include <util/crc16.h>
+
+static inline
+uint16_t crc16(uint16_t crc, uint8_t data)
+{
+ return _crc_ccitt_update(crc, data);
+}
+
+#endif /* CRC_H */
--- /dev/null
+#include "common.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <avr/eeprom.h>
+
+#include "command.h"
+#include "debug.h"
+
+/*
+ * Debugging
+ */
+#ifdef DEBUG
+
+//uint8_t eeprom_read_byte (const uint8_t *__p)
+
+static void print_blanks(uint_fast8_t count)
+{
+ while(count--)
+ putchar(' ');
+}
+
+static uint8_t ram_read_byte(const uint8_t *p)
+{
+ return *p;
+}
+
+void dump_mem(const uint8_t *startaddr, int len,
+ uint8_t (*readfkt)(const uint8_t *), char *title)
+{
+ uint8_t buf[16];
+ uint8_t llen = 16;
+ uint8_t pre = (size_t) startaddr % 16;
+ const uint8_t *addr = (uint8_t *) ((size_t) startaddr & ~0x0f);
+ len += pre;
+ uint8_t i;
+
+ if (title && *title)
+ printf_P(PSTR("%s\n"),title);
+
+ while (len) {
+ if (len < 16)
+ llen = len;
+
+ for (i = pre; i < llen; i++)
+ buf[i] = readfkt(addr + i);
+
+ printf_P(PSTR("%04x:"), addr);
+ for (i = 0; i < llen; i++) {
+ if ((i % 8) == 0)
+ putchar(' ');
+ if (i < pre)
+ printf_P(PSTR(".. "));
+ else
+ printf_P(PSTR("%.2x "), buf[i]);
+ }
+ /* fill line with whitespace for nice ASCII print */
+ print_blanks(3 * (16u - i) + (16u-i)/8 + 1 + pre);
+ /* Print data in ASCII characters */
+ for (i = pre; i < llen; i++)
+ printf_P(PSTR("%c"), isprint(buf[i]) ? buf[i] : '.');
+ putchar('\n');
+
+ pre = 0;
+ addr += 16;
+ len -= llen;
+ }
+}
+
+#if 0
+void dump_ram(const uint8_t *startaddr, int len, char *title)
+{
+ uint8_t llen = 16;
+ uint8_t pre = (size_t) startaddr % 16;
+ const uint8_t *addr = (uint8_t *) ((size_t) startaddr & ~0x0f);
+ len += pre;
+ uint8_t i;
+
+ if (title && *title)
+ printf_P(PSTR("%s\n"),title);
+
+ while (len) {
+ if (len < 16)
+ llen = len;
+
+ printf_P(PSTR(" %.4x:"), (size_t) addr);
+ print_blanks(3 * pre);
+ for (i = pre; i < llen; i++)
+ printf_P(PSTR(" %.2x"), addr[i]);
+ print_blanks(3 * (16 - i + 1) + pre);
+ for (i = pre; i < llen; i++)
+ printf_P(PSTR("%c"), isprint(addr[i]) ? addr[i] : '.');
+ putchar('\n');
+
+ pre = 0;
+ addr += 16;
+ len -= llen;
+ }
+}
+#endif
+#if 0
+void dump_heap(void)
+{
+ extern unsigned int __brkval;
+
+ dump_ram((uint8_t *) __malloc_heap_start,
+ __brkval - (unsigned int) __malloc_heap_start,
+ "=== Heap:");
+}
+#endif
+
+#if 0
+/* TODO: combine with dump_ram() */
+void dump_eep(const uint8_t *addr, unsigned int len,
+ uint8_t (*readfkt)(const uint8_t *))
+{
+ uint_fast8_t i;
+ uint8_t buf[16];
+
+ printf_P(PSTR("eeprom dump:"));
+ while (len) {
+ printf_P(PSTR("\n 0x%.4x:"), (unsigned int) addr);
+ for (i = 0; i<16; i++)
+ buf[i] = readfkt(addr + i);
+ for (i = 0; i<16; i++)
+ printf_P(PSTR(" %.2x"), buf[i]);
+ printf_P(PSTR(" "));
+ for (i = 0; i<16; i++)
+ printf_P(PSTR("%c"), isprint(buf[i]) ? buf[i] : '.');
+
+ addr += 16;
+ len -= len > 16 ? 16 : len;
+ }
+ putchar('\n');
+}
+#endif
+
+
+/*
+ * EEPROM Display
+ * md addr {len}
+ */
+int do_dump_mem(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+// static const uint8_t *addr;
+// static uint16_t length = 128;
+ uint8_t (*readhow)(const uint8_t *);
+
+ (void) cmdtp; (void) flag;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ const uint8_t *addr;
+ uint16_t length = 128;
+
+ if (strchr(argv[0],'r') != NULL)
+ readhow = ram_read_byte;
+ else if (strchr(argv[0],'e') != NULL)
+ readhow = eeprom_read_byte;
+ else
+ return CMD_RET_USAGE;
+
+ /* Address is specified since argc > 1 */
+ addr = (const uint8_t *) (size_t) strtoul(argv[1], NULL, 16);
+
+ /* If another parameter, it is the length to display. */
+ if (argc > 2)
+ length = (uint16_t) strtoul(argv[2], NULL, 16);
+
+ /* Print the lines. */
+ dump_mem(addr, length, readhow, NULL);
+
+ return 0;
+}
+
+int do_eep_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ uint16_t src, dest, count;
+ int_fast8_t step;
+
+ (void) cmdtp;
+ (void) flag;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+ src = (size_t) strtoul(argv[1], NULL, 16);
+ dest = (size_t) strtoul(argv[2], NULL, 16);
+ count = (size_t) strtoul(argv[3], NULL, 16);
+
+ if (src > E2END) {
+ debug("src > EEPROM size: 0x%04x\n", src);
+ return 1;
+ }
+ if (dest > E2END) {
+ debug("dest > EEPROM size: 0x%04x\n", dest);
+ return 1;
+ }
+ if (count > E2END+1) {
+ debug("count > EEPROM size: 0x%04x\n", count);
+ return 1;
+ }
+ if (count == 0) {
+ debug("Zero length ???\n");
+ return 1;
+ }
+
+ if (dest > src) {
+ src += count - 1;
+ dest += count - 1;
+ step = -1;
+ } else
+ step = 1;
+
+ while (count-- > 0) {
+ uint8_t data;
+ data = eeprom_read_byte((uint8_t *) src);
+ eeprom_write_byte((uint8_t *) dest, data);
+ src += step;
+ dest += step;
+
+ }
+ return 0;
+}
+#endif /* DEBUG */
+
--- /dev/null
+
+#ifndef DEBUG_H_
+#define DEBUG_H_
+
+#include "common.h"
+#include <avr/pgmspace.h>
+
+#ifdef DEBUG
+#define _DEBUG 1
+#else
+#define _DEBUG 0
+#endif
+
+#define debug_cond(cond, fmt, args...) \
+ do { \
+ if (cond) \
+ printf_P(PSTR(fmt), ##args); \
+ } while (0)
+
+#define debug(fmt, args...) \
+ debug_cond(_DEBUG, fmt, ##args)
+
+
+#if 1
+#ifdef DEBUG
+#define DBG_P(lvl, format, ...) if (DEBUG>=lvl) \
+ fprintf_P( stdout, PSTR(format), ##__VA_ARGS__ )
+#else
+#define DBG_P(lvl, ...)
+#endif
+#endif /* 0 */
+
+#endif /* DEBUG_H_ */
+
--- /dev/null
+#include "common.h"
+#include <string.h>
+#include <stdlib.h>
+
+#include <avr/eeprom.h>
+
+#include "config.h"
+#include "debug.h"
+#include "xmalloc.h"
+#include "crc.h"
+#include "command.h"
+
+#include "env.h"
+
+
+#define ENV_SIZE (CONFIG_ENV_SIZE - sizeof(uint16_t) -1)
+#define ACTIVE_FLAG 1
+#define OBSOLETE_FLAG 0
+#define ENV_GET_VAL (1<<0)
+
+
+/*
+ * Default Environment
+ */
+
+#define DELIM "\0"
+
+const FLASH char default_env[] = {
+ "bootdelay=" "3" DELIM
+ "bootcmd=" "reset; loadf; go $(startaddr)" DELIM
+ "baudrate=" "115200" DELIM
+ "startaddr=" "0" DELIM
+ DELIM
+};
+
+/* EEPROM storage */
+typedef struct environment_s {
+ uint16_t crc; /* CRC16 over data bytes */
+ uint8_t flags; /* active/obsolete flags */
+ char data[ENV_SIZE]; /* Environment data */
+} env_t;
+
+
+/* */
+typedef struct env_item_s {
+#define EF_N_EEP (1<<7) /* Variable name is in EEPROM */
+#define EF_V_EEP (1<<6) /* Variable value is in EEPROM */
+#define EF_DIRTY (1<<0) /* Variable is new or value changed */
+ uint8_t flags;
+ union {
+ uint16_t eep;
+ char *ram;
+ } name;
+ union {
+ uint16_t eep;
+ char *ram;
+ } val;
+} env_item_t;
+
+
+static uint8_t env_valid;
+static env_item_t env_list[CONFIG_ENVVAR_MAX];
+static int entrycount;
+
+
+static
+char env_get_char(uint16_t index)
+{
+ unsigned int off = CONFIG_ENV_OFFSET;
+
+ if (env_valid == 2)
+ off = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE;
+
+ return (char) eeprom_read_byte((const uint8_t *)off + index +
+ offsetof(env_t, data));
+}
+
+
+static
+uint16_t varname_get(char *buf, env_item_t *ep)
+{
+ int i = 0;
+ char c;
+
+ if (ep->flags & EF_N_EEP) {
+
+ while ((c = env_get_char(ep->name.eep + i)) != '=' &&
+ c != '\0' && i < CONFIG_SYS_ENV_NAMELEN) {
+
+ buf[i] = c;
+ i++;
+ }
+ if (i > 0 && c != '=') {
+ debug("** ee_name: '%s' not '=' terminated!\n", buf);
+ }
+ } else {
+ strncpy(buf, ep->name.ram, CONFIG_SYS_ENV_NAMELEN);
+ i = strnlen(buf, CONFIG_SYS_ENV_NAMELEN);
+ }
+ buf[i] = '\0';
+ return i;
+}
+
+
+static
+uint16_t varval_get(char *buf, uint16_t index, int len)
+{
+ int i = 0;
+ char c;
+
+ while ((c = env_get_char (index + i)) != '\0' && i < len) {
+ buf[i] = c;
+ i++;
+ };
+
+ buf[i] = '\0';
+
+ /* TODO: len check */
+
+ return i;
+}
+
+static
+int comp_env_key_item(const void *key, const void *item)
+{
+ char buf[CONFIG_SYS_ENV_NAMELEN+1];
+ env_item_t *ep = (env_item_t *) item;
+
+ varname_get(buf, ep);
+
+ return strcmp((char *) key, buf);
+}
+
+static
+int comp_env_items(const void *m1, const void *m2)
+{
+ char b1[CONFIG_SYS_ENV_NAMELEN+1];
+ char b2[CONFIG_SYS_ENV_NAMELEN+1];
+
+ env_item_t *ep1 = (env_item_t *) m1;
+ env_item_t *ep2 = (env_item_t *) m2;
+
+ varname_get(b1, ep1);
+ varname_get(b2, ep2);
+
+ return strcmp(b1, b2);
+}
+
+
+static
+int envlist_import(void)
+{
+ char name[CONFIG_SYS_ENV_NAMELEN+1];
+ uint16_t idx = 0;
+ int nlen;
+ env_item_t e;
+
+ e.flags = EF_N_EEP | EF_V_EEP;
+ e.name.eep = idx;
+ while ((nlen = varname_get(name, &e)) != 0 && idx < ENV_SIZE) {
+
+ if (entrycount <= CONFIG_ENVVAR_MAX) {
+ e.val.eep = idx + nlen + 1;
+
+ env_list[entrycount++] = e;
+
+ idx += nlen + 1;
+ while (env_get_char(idx++) != 0 && idx < ENV_SIZE)
+ ;
+ e.name.eep = idx;
+ } else {
+ debug("** Too many environment variables!\n");
+ break;
+ }
+ }
+ qsort(env_list, entrycount, sizeof(env_item_t), comp_env_items);
+
+ return 0;
+}
+
+
+static
+int set_default_env(void)
+{
+ char buf[56];
+ uint16_t eep = CONFIG_ENV_OFFSET + offsetof(env_t, data);
+ unsigned int len = ENV_SIZE;
+ unsigned int i, src = 0;
+ char c = 0xff, c0 = c;
+
+ if (env_valid == 1) {
+ eep = CONFIG_ENV_OFFSET + offsetof(env_t, data) + CONFIG_ENV_SIZE;
+ }
+
+ while (len) {
+ memcpy_P(buf, default_env+src, sizeof(buf));
+ for (i=0; i < (len < sizeof(buf) ? len : sizeof(buf)) &&
+ !(c == 0 && c0 == 0);
+ i++) {
+ c0 = c; c = buf[i];
+ }
+ eeprom_update_block(buf, (char *) eep, i);
+ if (c == 0 && c0 == 0)
+ len = 0;
+ if (len > sizeof(buf))
+ len -= sizeof(buf);
+ src += sizeof(buf);
+ eep += sizeof(buf);
+ }
+
+ return 0;
+}
+
+
+static
+uint16_t env_crc(uint16_t data_offset)
+{
+ uint16_t crc;
+ uint16_t i;
+ char c, c0;
+
+ crc = 0xffff;
+ c = 0xff;
+ for (i = 0; !(c == 0 && c0 == 0) && i < ENV_SIZE; i++)
+ {
+ c0 = c;
+ c = eeprom_read_byte((const uint8_t *) data_offset + i);
+ crc = crc16(crc, c);
+ }
+ return crc ;
+}
+
+
+/**
+ * return valid env
+ */
+static
+int env_check_valid(void)
+{
+ const uint16_t offset[2] = {CONFIG_ENV_OFFSET,
+ CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE};
+ uint_fast8_t flags[2], crc_ok[2];
+ int rc;
+
+ /* read FLAGS */
+ flags[0] = eeprom_read_byte ((uint8_t *) offset[0] +
+ offsetof(env_t, flags));
+ flags[1] = eeprom_read_byte ((uint8_t *) offset[1] +
+ offsetof(env_t, flags));
+
+ /* check CRC */
+ crc_ok[0] = (
+ eeprom_read_word((uint16_t *) offset[0] +
+ offsetof(env_t, crc))
+ == env_crc(offset[0] + offsetof(env_t, data))
+ );
+ crc_ok[1] = (
+ eeprom_read_word((uint16_t *) offset[1] +
+ offsetof(env_t, crc))
+ == env_crc(offset[1] + offsetof(env_t, data))
+ );
+
+ if (!crc_ok[0] && !crc_ok[1]) {
+ rc = 0;
+
+ } else if (crc_ok[0] && !crc_ok[1]) {
+ rc = 1;
+ } else if (!crc_ok[0] && crc_ok[1]) {
+ rc = 2;
+ } else {
+ /* both ok - check serial */
+#if 1
+ if (flags[1] == ACTIVE_FLAG && flags[0] != ACTIVE_FLAG)
+ rc = 2;
+ else if (flags[1] == OBSOLETE_FLAG && flags[0] == 0xFF)
+ rc = 2;
+ else
+ rc = 1;
+#else
+ if (flags[0] == ACTIVE_FLAG && flags[1] == OBSOLETE_FLAG)
+ rc = 1;
+ else if (flags[0] == OBSOLETE_FLAG && flags[1] == ACTIVE_FLAG)
+ rc = 2;
+ else if (flags[0] == 0xFF && flags[1] == 0)
+ rc = 2;
+ else if (flags[1] == 0xFF && flags[0] == 0)
+ rc = 1;
+ else /* flags are equal - almost impossible */
+ rc = 1;
+#endif
+ }
+
+ return rc;
+}
+
+
+int env_init(void)
+{
+ env_valid = env_check_valid();
+ if (env_valid == 0) {
+ printf_P(PSTR("*** Warning - bad CRC, "
+ "using default environment\n\n"));
+ set_default_env();
+ }
+ entrycount = 0;
+ envlist_import();
+ return 0;
+}
+
+
+static
+env_item_t *envlist_search(const char *name)
+{
+ return bsearch(name, env_list, entrycount,
+ sizeof(env_item_t), comp_env_key_item);
+}
+
+
+static
+env_item_t *envlist_enter(env_item_t *e)
+{
+ char *key = e->name.ram;
+ const size_t size = sizeof(env_item_t);
+ env_item_t *ep;
+
+ ep = bsearch(key, env_list, entrycount,
+ size, comp_env_key_item);
+
+ if (ep == NULL) {
+ if (entrycount < CONFIG_ENVVAR_MAX) {
+
+ env_list[entrycount++] = *e;
+ qsort(env_list, entrycount, size, comp_env_items);
+ ep = bsearch(key, env_list, entrycount,
+ size, comp_env_key_item);
+ }
+ } else {
+ if ((ep->flags & EF_V_EEP) == 0) {
+ free(ep->val.ram);
+ }
+ ep->val.ram = e->val.ram;
+ }
+
+ if (ep != NULL) {
+ ep->flags |= EF_DIRTY;
+ ep->flags &= ~EF_V_EEP;
+
+ if ((ep->flags & EF_N_EEP) == 0) {
+ int nlen = strnlen(key, CONFIG_SYS_ENV_NAMELEN);
+ char *name = xmalloc(nlen + 1);
+ if (name == NULL) {
+ printf_P(PSTR("## Can't malloc %d bytes\n"),
+ nlen + 1);
+ return NULL;
+ }
+ strcpy(name, key);
+ name[nlen] = '\0';
+ ep->name.ram = name;
+ }
+ }
+
+ return ep;
+}
+
+
+static
+int env_item_delete(env_item_t *ep)
+{
+ if (entrycount == 0)
+ return -1;
+ if ((ep->flags & EF_V_EEP) == 0)
+ free(ep->val.ram);
+ if ((ep->flags & EF_N_EEP) == 0)
+ free(ep->name.ram);
+
+ entrycount--;
+ size_t size = sizeof(env_item_t);
+ memmove(ep, ep + 1, (env_list - ep)*size + entrycount*size);
+
+ return 0;
+}
+
+static
+int envlist_delete(const char *name)
+{
+ env_item_t *ep = bsearch(name, env_list, entrycount,
+ sizeof(env_item_t), comp_env_key_item);
+
+ if (ep != NULL)
+ return env_item_delete(ep);
+
+ return 1;
+}
+
+
+static
+env_item_t *envlist_get(const char *name, uint_fast8_t flag)
+{
+ env_item_t *ep;
+
+ ep = envlist_search(name);
+
+ if (ep != NULL && (flag & ENV_GET_VAL)) {
+ if (ep->flags & EF_V_EEP) {
+ char *vp;
+ uint_fast8_t len;
+ /* TODO: function that gets len of val,
+ to get rid of xrealloc */
+ vp = xmalloc(CONFIG_SYS_CBSIZE);
+ len = varval_get(vp, ep->val.eep, CONFIG_SYS_CBSIZE);
+ ep->val.ram = xrealloc(vp, len + 1);
+ ep->flags &= ~EF_V_EEP;
+ }
+ }
+
+ return ep;
+}
+
+
+char *getenv(const char *name)
+{
+ env_item_t *ep;
+ char *ret = NULL;
+
+ ep = envlist_get(name, ENV_GET_VAL);
+ if (ep != NULL)
+ ret = ep->val.ram;
+ return ret;
+}
+
+static
+int env_item_save(env_item_t *ep, uint16_t offset, int space_left)
+{
+ char buf[CONFIG_SYS_ENV_NAMELEN+1];
+ int len;
+ env_item_t e = *ep;
+
+ len = varname_get(buf, ep);
+ if (len == 0)
+ return 0;
+ buf[len++] = '=';
+ space_left -= len;
+
+ if (space_left <= 0)
+ return 0;
+
+ eeprom_update_block(buf, (uint8_t *) offset, len);
+ offset += len;
+
+ if (e.val.ram != NULL) {
+ char c;
+ do {
+ if (e.flags & EF_V_EEP)
+ c = env_get_char(e.val.eep++);
+ else
+ c = *e.val.ram++;
+
+ eeprom_update_byte((uint8_t *) offset, c);
+ offset++;
+ space_left--;
+ len++;
+ } while ((c != '\0') && space_left );
+ }
+ return len;
+}
+
+
+static
+int saveenv(void)
+{
+ unsigned int off = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE;
+ unsigned int off_red = CONFIG_ENV_OFFSET;
+ unsigned int pos;
+ int len, left;
+ uint16_t crc;
+ int rc = 0;
+
+ if (env_valid == 2) {
+ off = CONFIG_ENV_OFFSET;
+ off_red = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE;
+ }
+
+ eeprom_update_byte((uint8_t *) off + offsetof(env_t, flags), 0xff);
+
+ pos = off + offsetof(env_t, data);
+ left = ENV_SIZE - 1;
+ for (int i = 0 ; i < entrycount; i++) {
+ len = env_item_save(&env_list[i], pos, left);
+ if (len == 0) {
+ return 1;
+ }
+ pos += len;
+ left -= len;
+ }
+ /* terminate list */
+ eeprom_update_byte((uint8_t *) pos, 0);
+ crc = env_crc(off + offsetof(env_t, data));
+ eeprom_update_word((uint16_t *) off + offsetof(env_t, crc), crc);
+ eeprom_update_byte((uint8_t *) off + offsetof(env_t, flags),
+ ACTIVE_FLAG);
+
+ if (rc == 0) {
+ while (entrycount != 0) {
+ env_item_delete(&env_list[entrycount-1]);
+ }
+ eeprom_update_byte((uint8_t *) off_red + offsetof(env_t, flags),
+ OBSOLETE_FLAG);
+ env_valid = (env_valid == 2) ? 1 : 2;
+
+ envlist_import();
+ }
+
+ return rc;
+}
+
+
+static
+int env_item_print(env_item_t *ep)
+{
+ char buf[CONFIG_SYS_ENV_NAMELEN+1];
+ int len;
+ env_item_t e = *ep;
+
+ varname_get(buf, ep);
+ len = printf_P(PSTR("%s="), buf);
+
+ if (e.val.ram != NULL) {
+ while (1) {
+ char c;
+ if (e.flags & EF_V_EEP)
+ c = env_get_char(e.val.eep++);
+ else
+ c = *e.val.ram++;
+
+ if (c != '\0') {
+ putchar(c);
+ len++;
+ } else
+ break;
+ }
+ }
+ putchar('\n');
+ len ++;
+
+ return len;
+}
+
+
+/*
+ * Command interface: print one or all environment variables
+ *
+ * Returns -1 in case of error, or length of printed string
+ */
+static
+int env_print(char *name)
+{
+ int len = -1;
+
+ if (name) { /* print a single name */
+
+ env_item_t *ep = envlist_search(name);
+ if (ep != NULL)
+ len = env_item_print(ep);
+
+ } else { /* print whole list */
+ len = 0;
+ for (int i = 0 ; i < entrycount; i++) {
+ len += env_item_print(&env_list[i]);
+ }
+ }
+ return len;
+}
+
+static
+int env_print_ramsize(void)
+{
+ int size = 0;
+ uint8_t name_cnt = 0;
+ uint8_t val_cnt = 0;
+
+ for (int i = 0 ; i < entrycount; i++) {
+ if ((env_list[i].flags & EF_N_EEP) == 0 &&
+ (env_list[i].name.ram != NULL)) {
+ name_cnt++;
+ size += strlen(env_list[i].name.ram) + 3;
+ }
+ if ((env_list[i].flags & EF_V_EEP) == 0 &&
+ (env_list[i].val.ram != NULL)) {
+ val_cnt++;
+ size += strlen(env_list[i].val.ram) + 3;
+ }
+ }
+ printf_P(PSTR("%d bytes RAM used for %u names and %u values\n"),
+ size, name_cnt, val_cnt);
+ return size;
+}
+
+
+int do_env_print(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int i;
+ int rcode = 0;
+
+ (void) cmdtp; (void) flag;
+
+ if (argc == 1) {
+ /* print all env vars */
+ rcode = env_print(NULL);
+ if (rcode < 0)
+ return 1;
+ printf_P(PSTR("\nEnvironment size: %d/%d bytes\n"),
+ rcode, ENV_SIZE);
+ env_print_ramsize();
+ return 0;
+ }
+
+ /* print selected env vars */
+ for (i = 1; i < argc; ++i) {
+ int rc = env_print(argv[i]);
+ if (rc < 0) {
+ printf_P(PSTR("## Error: \"%s\" not defined\n"), argv[i]);
+ ++rcode;
+ }
+ }
+
+ return rcode;
+}
+
+
+/**
+ * Set or delete environment variable
+ *
+ * Set a new environment variable,
+ * or replace or delete an existing one.
+ *
+ * @param flag (not used)
+ * @param argc
+ * @param argv[1] Environment variable to set or delete
+ * if no more args
+ * @param argv[2] ... Value to set it to
+ *
+ * @return 0 if ok, 1 on error
+ */
+static
+int _do_env_set(int flag, int argc, char * const argv[])
+{
+ int i, len;
+ char *name, *value, *s;
+ env_item_t e, *ep;
+
+ (void) flag;
+ debug("Initial value for argc=%d\n", argc);
+
+ name = argv[1];
+ value = argv[2];
+
+ if (strchr(name, '=')) {
+ printf_P(PSTR("## Error: illegal character '='"
+ "in variable name \"%s\"\n"), name);
+ return 1;
+ }
+ if (strlen(name) > CONFIG_SYS_ENV_NAMELEN) {
+ printf_P(PSTR("## Error: Variable name \"%s\" too long. "
+ "(max %d characters)\n"), name, CONFIG_SYS_ENV_NAMELEN);
+ return 1;
+ }
+/*
+ env_id++;
+*/
+ /* Delete only ? */
+ if (argc < 3 || argv[2] == NULL) {
+ int rc = envlist_delete(name);
+ return rc != 0;
+ }
+
+ /*
+ * Insert / replace new value
+ */
+ for (i = 2, len = 0; i < argc; ++i)
+ len += strlen(argv[i]) + 1;
+
+ value = xmalloc(len);
+ if (value == NULL) {
+ printf_P(PSTR("## Can't malloc %d bytes\n"), len);
+ return 1;
+ }
+ for (i = 2, s = value; i < argc; ++i) {
+ char *v = argv[i];
+
+ while ((*s++ = *v++) != '\0')
+ ;
+ *(s - 1) = ' ';
+ }
+ if (s != value)
+ *--s = '\0';
+
+ e.flags = EF_DIRTY;
+ e.name.ram = name;
+ e.val.ram = value;
+ ep = envlist_enter(&e);
+ if (!ep) {
+ printf_P(PSTR("## Error inserting \"%s\" variable.\n"),
+ name);
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Set an environment variable
+ *
+ * @param varname Environment variable to set
+ * @param varvalue Value to set it to
+ * @return 0 if ok, 1 on error
+ */
+static
+int setenv(const char *varname, const char *varvalue)
+{
+ const char * const argv[3] = { NULL, varname, varvalue };
+ int argc = 3;
+
+ if (varvalue == NULL || varvalue[0] == '\0')
+ --argc;
+
+ return _do_env_set(0, argc, (char * const *)argv);
+}
+
+#if 0
+/**
+ * Set an environment variable to an integer value
+ *
+ * @param varname Environment variable to set
+ * @param value Value to set it to
+ * @return 0 if ok, 1 on error
+ */
+int setenv_ulong(const char *varname, unsigned long value)
+{
+ /* TODO: this should be unsigned */
+ char *str = simple_itoa(value);
+
+ return setenv(varname, str);
+}
+#endif
+
+
+/**
+ * Set an environment variable to an value in hex
+ *
+ * @param varname Environment variable to set
+ * @param value Value to set it to
+ * @return 0 if ok, 1 on error
+ */
+int setenv_hex(const char *varname, unsigned long value)
+{
+ char str[sizeof(unsigned long) *2 + 1];
+
+ sprintf_P(str, PSTR("%lx"), value);
+ return setenv(varname, str);
+}
+
+/**
+ * Get an environment variable as a hex value
+ *
+ * @param varname Environment variable to get
+ * @param default_val Return this, if variable does not exist
+ * @return hex value of variable or default_val
+ */
+unsigned long getenv_hex(const char *varname, unsigned long default_val)
+{
+ const char *s;
+ unsigned long value;
+ char *endp;
+
+ s = getenv(varname);
+ if (s)
+ value = strtoul(s, &endp, 16);
+ if (!s || endp == s)
+ return default_val;
+
+ return value;
+}
+
+int do_env_set(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ (void) cmdtp;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ return _do_env_set(flag, argc, argv);
+}
+
+
+int do_env_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ (void) cmdtp; (void) flag; (void) argc; (void) argv;
+
+ printf_P(PSTR("Saving Environment ...\n"));
+ return saveenv() ? 1 : 0;
+}
+
+#if defined(CONFIG_AUTO_COMPLETE)
+int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf)
+{
+ ENTRY *match;
+ int found, idx;
+
+ idx = 0;
+ found = 0;
+ cmdv[0] = NULL;
+
+ while ((idx = hmatch_r(var, idx, &match, &env_htab))) {
+ int vallen = strlen(match->key) + 1;
+
+ if (found >= maxv - 2 || bufsz < vallen)
+ break;
+
+ cmdv[found++] = buf;
+ memcpy(buf, match->key, vallen);
+ buf += vallen;
+ bufsz -= vallen;
+ }
+
+ qsort(cmdv, found, sizeof(cmdv[0]), strcmp_compar);
+
+ if (idx)
+ cmdv[found++] = "...";
+
+ cmdv[found] = NULL;
+ return found;
+}
+#endif
--- /dev/null
+#ifndef ENV_H
+#define ENV_H
+
+int env_init(void);
+
+char *getenv(const char *name);
+int env_complete(char *var, int maxv, char *cmdv[], int maxsz, char *buf);
+
+#endif /* ENV_H */
+
--- /dev/null
+/*
+ */
+
+
+#include "common.h"
+
+#include <util/delay.h>
+//#include <avr/power.h>
+//#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+//#include <util/atomic.h>
+//#include <avr/sleep.h>
+//#include <string.h>
+
+#include <util/delay.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+
+#include "config.h"
+#include "debug.h"
+#include "z80-if.h"
+#include "con-utils.h"
+#include "serial.h"
+#include "timer.h"
+#include "cli.h"
+#include "env.h"
+
+/*--------------------------------------------------------------------------*/
+
+static uint8_t mcusr;
+
+static
+void setup_avr(void)
+{
+ /* save and clear reset reason(s) */
+ mcusr = MCUSR;
+ MCUSR = 0;
+
+ /* WD */
+
+ /* CPU */
+
+ /* Disable JTAG Interface regardless of the JTAGEN fuse setting. */
+ MCUCR = _BV(JTD);
+ MCUCR = _BV(JTD);
+
+ /* disable unused periphels */
+ PRR0 = _BV(PRTIM2) | _BV(PRTIM0) | _BV(PRADC);
+ PRR1 = _BV(PRTIM5) | _BV(PRTIM4) | _BV(PRTIM3) |
+ _BV(PRUSART3) | _BV(PRUSART2) | _BV(PRUSART1);
+
+ /* disable analog comparator */
+ ACSR = _BV(ACD);
+ /* Ports */
+
+ /* Clock */
+ CLKPR = _BV(CLKPCE);
+ CLKPR = 0;
+
+ /* Timer */
+
+ OCR1A = F_CPU / 8 / 1000 - 1; // Timer1: 1000Hz interval (OC1A)
+ TCCR1B = 0b00001010;
+ TIMSK1 = _BV(OCIE1A); // Enable TC1.oca interrupt
+}
+
+static const FLASH char * const FLASH rreasons[] = {
+ FSTR("Power on"),
+ FSTR("External"),
+ FSTR("Brown out"),
+ FSTR("Watchdog"),
+ FSTR("JTAG"),
+ };
+
+static
+void print_reset_reason(void)
+{
+ uint8_t r = mcusr & 0x1f;
+ const FLASH char * const FLASH *p = rreasons;
+
+ printf_P(PSTR("Reset reason(s): "));
+ for ( ; r; p++, r >>= 1) {
+ if (r & 1) {
+ my_puts_P(*p);
+ if (r & ~1)
+ printf_P(PSTR(", "));
+ }
+ }
+ printf_P(PSTR(".\n"));
+}
+
+
+/*******************************************************************************/
+/*******************************************************************************/
+
+#define udelay(n) _delay_us(n)
+
+
+/* Stored value of bootdelay, used by autoboot_command() */
+static int stored_bootdelay;
+
+
+/***************************************************************************
+ * Watch for 'delay' seconds for autoboot stop.
+ * returns: 0 - no key, allow autoboot
+ * 1 - got key, abort
+ */
+
+static int abortboot(int bootdelay)
+{
+ int abort = 0;
+ uint32_t ts;
+
+ if (bootdelay >= 0)
+ printf_P(PSTR("Hit any key to stop autoboot: %2d "), bootdelay);
+
+#if defined CONFIG_ZERO_BOOTDELAY_CHECK
+ /*
+ * Check if key already pressed
+ * Don't check if bootdelay < 0
+ */
+ if (bootdelay >= 0) {
+ if (tstc()) { /* we got a key press */
+ (void) my_getchar(); /* consume input */
+ my_puts_P(PSTR("\b\b\b 0"));
+ abort = 1; /* don't auto boot */
+ }
+ }
+#endif
+
+ while ((bootdelay > 0) && (!abort)) {
+ --bootdelay;
+ /* delay 1000 ms */
+ ts = get_timer(0);
+ do {
+ if (tstc()) { /* we got a key press */
+ abort = 1; /* don't auto boot */
+ bootdelay = 0; /* no more delay */
+ break;
+ }
+ udelay(10000);
+ } while (!abort && get_timer(ts) < 1000);
+
+ printf_P(PSTR("\b\b\b%2d "), bootdelay);
+ }
+
+ putchar('\n');
+
+ return abort;
+}
+
+static
+const char *bootdelay_process(void)
+{
+ char *s;
+ int bootdelay;
+
+ s = getenv("bootdelay");
+ bootdelay = s ? atoi(s) : CONFIG_BOOTDELAY;
+
+
+ debug("### main_loop entered: bootdelay=%d\n\n", bootdelay);
+ _delay_ms(20);
+
+ s = getenv("bootcmd");
+ stored_bootdelay = bootdelay;
+ return s;
+}
+
+static
+void autoboot_command(const char *s)
+{
+ debug("### main_loop: bootcmd=\"%s\"\n", s ? s : PSTR("<UNDEFINED>"));
+ _delay_ms(20);
+
+ if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) {
+ run_command_list(s, -1);
+ }
+}
+
+
+static
+void main_loop(void)
+{
+ const char *s;
+
+ s = bootdelay_process();
+ autoboot_command(s);
+ cli_loop();
+}
+
+int main(void)
+{
+ setup_avr();
+ z80_setup_bus();
+
+ serial_setup();
+ sei();
+
+ debug("\n=========================< (RE)START DEBUG >=========================\n");
+#if DEBUG
+ print_reset_reason();
+#endif
+
+ env_init();
+
+ printf_P(PSTR("\n(ATMEGA1281+HD64180)_stamp Tester\n"));
+
+ main_loop();
+}
--- /dev/null
+#ifndef RING_H
+#define RING_H
+
+struct ring {
+ uint8_t *data;
+ uint_fast8_t mask;
+ volatile uint_fast8_t begin;
+ volatile uint_fast8_t end;
+};
+
+
+static inline
+void ring_init(struct ring *ring, uint8_t *buf, int size)
+{
+ ring->data = buf;
+ ring->mask = (size-1) & 0xff;
+ ring->begin = 0;
+ ring->end = 0;
+}
+
+static inline
+int ring_write_ch(struct ring *ring, uint8_t ch)
+{
+ uint_fast8_t ep = ring->end;
+
+ ring->data[ep] = ch;
+ ep = (ep + 1) & ring->mask;
+
+ if ((ep) != ring->begin) {
+ ring->end = ep;
+ return 1;
+ }
+
+ return -1;
+}
+
+#if 0
+static inline
+int ring_write(struct ring *ring, uint8_t *data, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ if (ring_write_ch(ring, data[i]) < 0)
+ return -i;
+ }
+
+ return i;
+}
+#endif
+
+static inline
+int ring_read_ch(struct ring *ring)
+{
+ int ret = -1;
+ uint_fast8_t bp = ring->begin;
+
+ if (bp != ring->end) {
+ ret = ring->data[bp];
+ ring->begin = (bp + 1) & ring->mask;
+ }
+
+ return ret;
+}
+
+
+static inline
+int_fast8_t ring_is_empty(struct ring *ring)
+{
+ return ring->begin == ring->end;
+}
+
+#endif /* RING_H */
+
--- /dev/null
+/*
+ */
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/atomic.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "ring.h"
+#include "serial.h"
+
+
+static int _write(char c, FILE *stream);
+static FILE mystdout = FDEV_SETUP_STREAM(_write,
+ NULL, _FDEV_SETUP_WRITE);
+
+
+
+#define BUFFER_SIZE 64
+
+#if ((BUFFER_SIZE-1) & BUFFER_SIZE)
+# error: BUFFER_SIZE not power of 2
+#endif
+
+#if ((BUFFER_SIZE) > 256)
+# error: BUFFER_SIZE
+#endif
+
+struct ring rx_ring;
+struct ring tx_ring;
+uint8_t rx_ring_buffer[BUFFER_SIZE];
+uint8_t tx_ring_buffer[BUFFER_SIZE];
+
+
+
+/* Initialize UART */
+
+void usart0_setup(void) {
+
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+
+ PRR0 &= ~_BV(PRUSART0);
+ UCSR0B = 0;
+
+ /* Initialize ring buffers. */
+ ring_init(&rx_ring, rx_ring_buffer, BUFFER_SIZE);
+ ring_init(&tx_ring, tx_ring_buffer, BUFFER_SIZE);
+
+ UCSR0A = 0;
+ UBRR0 = F_CPU / BAUD / 16 - 1;
+ UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0);
+ UCSR0C = 3 << UCSZ00;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* UART RXC interrupt */
+
+ISR(USART0_RX_vect)
+{
+ uint8_t d;
+
+ d = UDR0;
+ ring_write_ch(&rx_ring, d);
+}
+
+/* UART UDRE interrupt */
+
+ISR(USART0_UDRE_vect)
+{
+ int d = ring_read_ch(&tx_ring);
+
+ if (d < 0) {
+ /* Disable TX empty interrupt. */
+ UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0);
+ } else {
+ UDR0 = d;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void serial_setup(void)
+{
+ stdout = &mystdout;
+ usart0_setup();
+}
+
+/*--------------------------------------------------------------------------*/
+
+int _write(char c, FILE *stream)
+{
+ (void) stream;
+
+ if (c == '\n')
+ serial_putc('\r');
+ serial_putc(c);
+
+ return 0;
+}
+
+int serial_getc(void)
+{
+ return ring_read_ch(&rx_ring);
+}
+
+void serial_putc(char data)
+{
+ while (ring_write_ch(&tx_ring, data) < 0)
+ ;
+
+ /* Enable the TXE interrupt. */
+ UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0) | _BV(UDRIE0);
+}
+
+uint_fast8_t serial_tstc(void)
+{
+ return !ring_is_empty(&rx_ring);
+}
+
+
--- /dev/null
+#ifndef SERIAL_H
+#define SERIAL_H
+
+void serial_setup(void);
+void serial_putc(char);
+int serial_getc(void);
+uint_fast8_t serial_tstc(void);
+
+#endif /* SERIAL_H */
--- /dev/null
+/*
+ */
+
+
+#include "common.h"
+
+//#include <avr/power.h>
+//#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+#include <util/atomic.h>
+
+//#include <stdio.h>
+
+
+#include "timer.h"
+
+/* timer interrupt/overflow counter */
+static volatile uint32_t timestamp;
+
+
+/*---------------------------------------------------------*/
+/* 1000Hz timer interrupt generated by OC1A */
+/*---------------------------------------------------------*/
+
+ISR(TIMER1_COMPA_vect)
+{
+ static int_fast8_t tick_10ms;
+ int_fast8_t i;
+
+
+ timestamp++;
+
+ i = tick_10ms + 1;
+ if (i == 10) {
+ i = 0;
+ Stat |= S_10MS_TO;
+
+ /* Drive timer procedure of low level disk I/O module */
+ //disk_timerproc();
+ }
+ tick_10ms = i;
+
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+
+#if 0
+
+void do_10ms(void)
+{
+ if (to_counter)
+ to_counter--;
+}
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+
+void timer_setup(void)
+{
+
+ /* Clock */
+ CLKPR = _BV(CLKPCE);
+ CLKPR = 0;
+
+ /* Timer */
+
+ OCR1A = F_CPU / 1000 - 1; // Timer1: 1000Hz interval (OC1A)
+ TCCR1B = 0b00001001;
+ TIMSK1 = _BV(OCIE1A); // Enable TC1.oca interrupt
+}
+
+
+uint32_t get_timer(uint32_t base)
+{
+ uint32_t ret;
+
+ ATOMIC_BLOCK(ATOMIC_FORCEON)
+ {
+ ret = timestamp;
+ }
+ return ret - base;
+}
+
--- /dev/null
+#ifndef TIMER_H
+#define TIMER_H
+
+uint32_t get_timer(uint32_t);
+
+#endif /* TIMER_H */
+
--- /dev/null
+#include <stdlib.h>
+
+#include "debug.h"
+#include "xmalloc.h"
+
+void* xmalloc(size_t size)
+{
+ void *p;
+
+ p = malloc(size);
+
+ if (p == NULL)
+ debug("*** Out of memory!\n");
+
+ return p;
+}
+
+
+void* xrealloc(void *p, size_t size)
+{
+ p = realloc(p, size);
+
+ if (p == NULL)
+ debug("*** Out of memory!\n");
+
+ return p;
+}
--- /dev/null
+
+#ifndef XMALLOC_H
+#define XMALLOC_H
+
+void* xmalloc(size_t size);
+void* xrealloc(void *p, size_t size);
+
+#endif /* XMALLOC_H */
--- /dev/null
+/*
+ */
+
+#include "common.h"
+//#include <avr/power.h>
+//#include <avr/pgmspace.h>
+//#include <util/atomic.h>
+//#include <avr/sleep.h>
+//#include <string.h>
+
+
+#include "debug.h"
+#include "serial.h"
+#include "z80-if.h"
+
+
+
+/*--------------------------------------------------------------------------*/
+
+uint32_t z80_sram_cmp(uint32_t addr, uint32_t length, uint8_t wval, int inc)
+{
+ uint8_t rval;
+ int_fast8_t errors = 0;
+
+ DBG_P(1, "SRAM: Check 0x%.5lx byte... ", length);
+ while (length--) {
+ if ((rval = z80_read(addr)) != wval) {
+ if (errors == 0) {
+ DBG_P(1, "\nSRAM: Address W R\n" \
+ " ------------------\n");
+ }
+ errors++;
+ if (errors > 20) {
+ DBG_P(1, " ...\n");
+ break;
+ }
+ DBG_P(1, " 0x%.5lx 0x%.2x 0x%.2x\n", addr, wval, rval);
+ }
+ addr++;
+ wval += inc;
+ }
+ DBG_P(1, "Done.\n");
+
+ return addr;
+}
+
+void z80_sram_fill(uint32_t addr, uint32_t length, uint8_t startval, int inc)
+{
+ printf("SRAM: Write 0x%.5lx byte... ", length);
+ while (length--) {
+ z80_write(addr, startval);
+ ++addr;
+ startval += inc;
+ }
+ printf("Done.\n");
+}
+
+
+#if 0
+void z80_sram_fill_string(uint32_t addr, int length, const char *text)
+{
+ char c;
+ const char *p = text;
+
+ while (length--) {
+ z80_write(addr++, c = *p++);
+ if (c == 0)
+ p = text;
+ }
+}
+
+
+uint32_t z80_sram_cmp_string(uint32_t addr, int length, const char *text)
+{
+ char c;
+ const char *p = text;
+
+ while (length--) {
+ c = *p++;
+ if (z80_read(addr) != c)
+ break;
+ ++addr;
+ if (c == 0)
+ p = text;
+ }
+ return addr;
+}
+
+const char * const qbfox = "Zhe quick brown fox jumps over the lazy dog!";
+const char * const qbcat = "Zhe quick brown fox jumps over the lazy cat!";
+
+#endif
+
+uint8_t z80_get_byte(uint32_t adr)
+{
+ uint8_t data;
+
+ z80_bus_cmd(Request);
+ data = z80_read(adr),
+ z80_bus_cmd(Release);
+
+ return data;
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+struct msg_item {
+ uint8_t fct;
+ uint8_t sub_min, sub_max;
+ void (*func)(uint8_t, int, uint8_t *);
+};
+
+uint32_t msg_to_addr(uint8_t *msg)
+{
+ union {
+ uint32_t as32;
+ uint8_t as8[4];
+ } addr;
+
+ addr.as8[0] = msg[0];
+ addr.as8[1] = msg[1];
+ addr.as8[2] = msg[2];
+ addr.as8[3] = 0;
+
+ return addr.as32;
+}
+
+void do_msg_ini_msgfifo(uint8_t subf, int len, uint8_t * msg)
+{
+ (void)subf; (void)len;
+
+ z80_init_msg_fifo(msg_to_addr(msg));
+}
+
+
+void do_msg_ini_memfifo(uint8_t subf, int len, uint8_t * msg)
+{
+ (void)len;
+
+ z80_memfifo_init(subf - 1, msg_to_addr(msg));
+}
+
+
+void do_msg_char_out(uint8_t subf, int len, uint8_t * msg)
+{
+ (void)subf;
+
+ while (len--)
+ putchar(*msg++);
+}
+
+
+const FLASH struct msg_item z80_messages[] =
+{
+ { 0, /* fct nr. */
+ 0, 0, /* sub fct nr. from, to */
+ do_msg_ini_msgfifo},
+ { 0,
+ 1, 2,
+ do_msg_ini_memfifo},
+ { 1,
+ 1, 1,
+ do_msg_char_out},
+ { 0xff, /* end mark */
+ 0, 0,
+ 0},
+
+};
+
+
+
+
+void do_message(int len, uint8_t *msg)
+{
+ uint8_t fct, sub_fct;
+ int_fast8_t i = 0;
+
+ if (len >= 2) {
+ fct = *msg++;
+ sub_fct = *msg++;
+ len -= 2;
+
+ while (fct != z80_messages[i].fct)
+ ++i;
+
+ if (z80_messages[i].fct == 0xff) {
+ DBG_P(1, "do_message: Unknown function: %i, %i\n",
+ fct, sub_fct);
+ return; /* TODO: unknown message # */
+ }
+
+ while (fct == z80_messages[i].fct) {
+ if (sub_fct >= z80_messages[i].sub_min && sub_fct <= z80_messages[i].sub_max )
+ break;
+ ++i;
+ }
+
+ if (z80_messages[i].fct != fct) {
+ DBG_P(1, "do_message: Unknown sub function: %i, %i\n",
+ fct, sub_fct);
+ return; /* TODO: unknown message sub# */
+ }
+
+ (z80_messages[i].func)(sub_fct, len, msg);
+
+
+ } else {
+ /* TODO: error */
+ DBG_P(1, "do_message: to few arguments (%i); this shouldn't happen!\n", len);
+ }
+}
+
+
+
+#define CTRBUF_LEN 256
+
+void check_msg_fifo(void)
+{
+ int ch;
+ static int_fast8_t state;
+ static int msglen,idx;
+ static uint8_t buffer[CTRBUF_LEN];
+
+ while (state != 3 && (ch = z80_msg_fifo_getc()) >= 0) {
+ switch (state) {
+ case 0: /* wait for start of message */
+ if (ch == 0x81) {
+ msglen = 0;
+ idx = 0;
+ state = 1;
+ }
+ break;
+ case 1: /* get msg len */
+ if (ch > 0 && ch <= CTRBUF_LEN) {
+ msglen = ch;
+ state = 2;
+ } else
+ state = 0;
+ break;
+ case 2: /* get message */
+ buffer[idx++] = ch;
+ if (idx == msglen)
+ state = 3;
+ break;
+ }
+ }
+
+ if (state == 3) {
+ do_message(msglen, buffer);
+ state = 0;
+ }
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+#if 0
+void dump_mem(const FLASH uint8_t *addr, uint32_t len)
+{
+ DBG_P(1, "hdrom dump:");
+ while (len) {
+ DBG_P(1, "\n %.5x:", addr);
+ for (unsigned i = 0; i<16; i++)
+ DBG_P(1, " %.2x", *addr++);
+ len -= len > 16 ? 16 : len;
+ }
+ DBG_P(1, "\n");
+}
+#endif
+/*--------------------------------------------------------------------------*/
+
+
+const FLASH uint8_t iniprog[] = {
+ 0xAF, // xor a
+ 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh
+ 0x3E, 0x30, // ld a,030h
+ 0xED, 0x39, 0x32 //out0 (dcntl),a ;0 mem, max i/0 wait states
+};
+
+const FLASH uint8_t sertest[] = {
+ 0xAF, // xor a
+ 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh
+ 0x3E, 0x30, // ld a,030h
+ 0xED, 0x39, 0x32, // out0 (dcntl),a ;0 mem, max i/0 wait states
+ 0x3E, 0x80, // ld a,M_MPBT ;no MP, PS=10, DR=16, SS=0
+ 0xED, 0x39, 0x03, // out0 (cntlb1),a
+ 0x3E, 0x64, // ld a,M_RE + M_TE + M_MOD2 ;
+ 0xED, 0x39, 0x01, // out0 (cntla1),a
+ 0x3E, 0x00, // ld a,0
+ 0xED, 0x39, 0x05, // out0 (stat1),a ;Enable rx interrupts
+ 0xED, 0x38, 0x05, //l0:in0 a,(stat1)
+ 0xE6, 0x80, // and 80h
+ 0x28, 0xF9, // jr z,l0
+ 0xED, 0x00, 0x09, // in0 b,(rdr1)
+ 0xED, 0x38, 0x05, //l1:in0 a,(stat1)
+ 0xE6, 0x02, // and 02h
+ 0x28, 0xF9, // jr z,l1
+ 0xED, 0x01, 0x07, // out0 (tdr1),b
+ 0x18, 0xEA, // jr l0
+};
+
+const FLASH uint8_t test1[] = {
+ 0xAF, // xor a
+ 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh
+ 0x3E, 0x30, // ld a,030h
+ 0xED, 0x39, 0x32, // out0 (dcntl),a ;0 mem, max i/0 wait states
+ 0x21, 0x1E, 0x00, // ld hl,dmclrt ;load DMA registers
+ 0x06, 0x08, // ld b,dmct_e-dmclrt
+ 0x0E, 0x20, // ld c,sar0l
+ 0xED, 0x93, // otimr
+ 0x3E, 0xC3, // ld a,0c3h ;dst +1, src +1, burst
+ 0xED, 0x39, 0x31, // out0 (dmode),a ;
+ 0x3E, 0x62, // ld a,062h ;enable dma0,
+ 0xED, 0x39, 0x30, //cl_1: out0 (dstat),a ;copy 64k
+ 0x18, 0xFB, // jr cl_1 ;
+ 0x00, 0x00, //dmclrt: dw 0 ;src (inc)
+ 0x00, // db 0 ;src
+ 0x00, 0x00, // dw 0 ;dst (inc),
+ 0x00, // db 0 ;dst
+ 0x00, 0x00, // dw 0 ;count (64k)
+};
+
+
+
+// check_msg_fifo();
+
--- /dev/null
+/*
+ */
+
+
+#include <avr/io.h>
+//#include <avr/power.h>
+//#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+//#include <util/atomic.h>
+//#include <avr/sleep.h>
+//#include <string.h>
+
+#include <stdio.h>
+
+
+#include "debug.h"
+#include "serial.h"
+#include "z80-if.h"
+
+#define const const __flash
+#include "../z180/hdrom.h"
+#undef const
+
+#define FLASH __flash
+//#define FLASH
+
+#define ESCCHAR ('^'-0x40)
+
+#define S_10MS_TO (1<<0)
+
+
+volatile int_fast8_t timeout_1s;
+//volatile uint_least8_t Stat;
+#define Stat GPIOR0
+
+unsigned int to_counter;
+
+/****************************************************************/
+
+#define P_ADL PORTA
+#define P_ADH PORTC
+#define P_ADB PORTE
+#define PIN_ADB PINE
+
+#define ADB_WIDTH 3
+#define ADB_SHIFT 2
+//#define ADB_PORT GPIOE
+
+#define MASK(n) ((1<<(n))-1)
+#define SMASK(w,s) (MASK(w) << (s))
+
+typedef union {
+ uint32_t l;
+ uint16_t w[2];
+ uint8_t b[4];
+} addr_t;
+
+
+
+/*--------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------*/
+/* 1000Hz timer interrupt generated by OC1A */
+/*---------------------------------------------------------*/
+
+ISR(TIMER1_COMPA_vect)
+{
+ static int_fast8_t tick_10ms;
+// static int_fast16_t count_ms;
+
+ int_fast8_t i;
+
+
+ i = tick_10ms + 1;
+ if (i == 10) {
+ i = 0;
+ Stat |= S_10MS_TO;
+
+ /* Drive timer procedure of low level disk I/O module */
+ //disk_timerproc();
+ }
+ tick_10ms = i;
+
+#if 0
+ count_ms++;
+ if (count_ms == 1000) {
+ count_ms = 0;
+
+ i = timeout_1s;
+ if (i)
+ timeout_1s = i - 1;
+ }
+#endif
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+static uint32_t z80_sram_cmp(uint32_t addr, uint32_t length, uint8_t wval, int inc)
+{
+ uint8_t rval;
+ int_fast8_t errors = 0;
+
+ DBG_P(1, "SRAM: Check 0x%.5lx byte... ", length);
+ while (length--) {
+ if ((rval = z80_read(addr)) != wval) {
+ if (errors == 0) {
+ DBG_P(1, "\nSRAM: Address W R\n" \
+ " ------------------\n");
+ }
+ errors++;
+ if (errors > 20) {
+ DBG_P(1, " ...\n");
+ break;
+ }
+ DBG_P(1, " 0x%.5lx 0x%.2x 0x%.2x\n", addr, wval, rval);
+ }
+ addr++;
+ wval += inc;
+ }
+ DBG_P(1, "Done.\n");
+
+ return addr;
+}
+
+static void z80_sram_fill(uint32_t addr, uint32_t length, uint8_t startval, int inc)
+{
+ printf("SRAM: Write 0x%.5lx byte... ", length);
+ while (length--) {
+ z80_write(addr, startval);
+ ++addr;
+ startval += inc;
+ }
+ printf("Done.\n");
+}
+
+
+#if 0
+void z80_sram_fill_string(uint32_t addr, int length, const char *text)
+{
+ char c;
+ const char *p = text;
+
+ while (length--) {
+ z80_write(addr++, c = *p++);
+ if (c == 0)
+ p = text;
+ }
+}
+
+
+uint32_t z80_sram_cmp_string(uint32_t addr, int length, const char *text)
+{
+ char c;
+ const char *p = text;
+
+ while (length--) {
+ c = *p++;
+ if (z80_read(addr) != c)
+ break;
+ ++addr;
+ if (c == 0)
+ p = text;
+ }
+ return addr;
+}
+
+const char * const qbfox = "Zhe quick brown fox jumps over the lazy dog!";
+const char * const qbcat = "Zhe quick brown fox jumps over the lazy cat!";
+
+#endif
+
+uint8_t z80_get_byte(uint32_t adr)
+{
+ uint8_t data;
+
+ z80_request_bus();
+ data = z80_read(adr),
+ z80_release_bus();
+
+ return data;
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+static void do_10ms(void)
+{
+ if (to_counter)
+ to_counter--;
+}
+
+/*--------------------------------------------------------------------------*/
+
+struct msg_item {
+ uint8_t fct;
+ uint8_t sub_min, sub_max;
+ void (*func)(uint8_t, int, uint8_t *);
+};
+
+uint32_t msg_to_addr(uint8_t *msg)
+{
+ union {
+ uint32_t as32;
+ uint8_t as8[4];
+ } addr;
+
+ addr.as8[0] = msg[0];
+ addr.as8[1] = msg[1];
+ addr.as8[2] = msg[2];
+ addr.as8[3] = 0;
+
+ return addr.as32;
+}
+
+void do_msg_ini_msgfifo(uint8_t subf, int len, uint8_t * msg)
+{
+ (void)subf; (void)len;
+
+ z80_init_msg_fifo(msg_to_addr(msg));
+}
+
+
+void do_msg_ini_memfifo(uint8_t subf, int len, uint8_t * msg)
+{
+ (void)len;
+
+ z80_memfifo_init(subf - 1, msg_to_addr(msg));
+}
+
+
+void do_msg_char_out(uint8_t subf, int len, uint8_t * msg)
+{
+ (void)subf;
+
+ while (len--)
+ putchar(*msg++);
+}
+
+
+const FLASH struct msg_item z80_messages[] =
+{
+ { 0, /* fct nr. */
+ 0, 0, /* sub fct nr. from, to */
+ do_msg_ini_msgfifo},
+ { 0,
+ 1, 2,
+ do_msg_ini_memfifo},
+ { 1,
+ 1, 1,
+ do_msg_char_out},
+ { 0xff, /* end mark */
+ 0, 0,
+ 0},
+
+};
+
+
+
+
+void do_message(int len, uint8_t *msg)
+{
+ uint8_t fct, sub_fct;
+ int_fast8_t i = 0;
+
+ if (len >= 2) {
+ fct = *msg++;
+ sub_fct = *msg++;
+ len -= 2;
+
+ while (fct != z80_messages[i].fct)
+ ++i;
+
+ if (z80_messages[i].fct == 0xff) {
+ DBG_P(1, "do_message: Unknown function: %i, %i\n",
+ fct, sub_fct);
+ return; /* TODO: unknown message # */
+ }
+
+ while (fct == z80_messages[i].fct) {
+ if (sub_fct >= z80_messages[i].sub_min && sub_fct <= z80_messages[i].sub_max )
+ break;
+ ++i;
+ }
+
+ if (z80_messages[i].fct != fct) {
+ DBG_P(1, "do_message: Unknown sub function: %i, %i\n",
+ fct, sub_fct);
+ return; /* TODO: unknown message sub# */
+ }
+
+ (z80_messages[i].func)(sub_fct, len, msg);
+
+
+ } else {
+ /* TODO: error */
+ DBG_P(1, "do_message: to few arguments (%i); this shouldn't happen!\n", len);
+ }
+}
+
+
+
+#define CTRBUF_LEN 256
+
+void check_msg_fifo(void)
+{
+ int ch;
+ static int_fast8_t state;
+ static int msglen,idx;
+ static uint8_t buffer[CTRBUF_LEN];
+
+ while (state != 3 && (ch = z80_msg_fifo_getc()) >= 0) {
+ switch (state) {
+ case 0: /* wait for start of message */
+ if (ch == 0x81) {
+ msglen = 0;
+ idx = 0;
+ state = 1;
+ }
+ break;
+ case 1: /* get msg len */
+ if (ch > 0 && ch <= CTRBUF_LEN) {
+ msglen = ch;
+ state = 2;
+ } else
+ state = 0;
+ break;
+ case 2: /* get message */
+ buffer[idx++] = ch;
+ if (idx == msglen)
+ state = 3;
+ break;
+ }
+ }
+
+ if (state == 3) {
+ do_message(msglen, buffer);
+ state = 0;
+ }
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+void dump_mem(const __flash uint8_t *addr, uint32_t len)
+{
+ DBG_P(1, "hdrom dump:");
+ while (len) {
+ DBG_P(1, "\n %.5x:", addr);
+ for (unsigned i = 0; i<16; i++)
+ DBG_P(1, " %.2x", *addr++);
+ len -= len > 16 ? 16 : len;
+ }
+ DBG_P(1, "\n");
+}
+
+/*--------------------------------------------------------------------------*/
+
+void z80_load_mem(void)
+{
+ unsigned sec = 0;
+ uint32_t sec_base = hdrom_start;
+
+ DBG_P(1, "Loading z80 memory... \n");
+
+ while (sec < hdrom_sections) {
+ DBG_P(2, " From: 0x%.5lX to: 0x%.5lX (%5li bytes)\n",
+ hdrom_address[sec],
+ hdrom_address[sec]+hdrom_length_of_sections[sec] - 1,
+ hdrom_length_of_sections[sec]);
+
+ z80_write_block((const __flash unsigned char *) &hdrom[sec_base], /* src */
+ hdrom_address[sec], /* dest */
+ hdrom_length_of_sections[sec]); /* len */
+ sec_base+=hdrom_length_of_sections[sec];
+ sec++;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void z80_dump_mem(uint32_t addr, uint32_t len)
+{
+ DBG_P(1, "Memory dump:");
+ while (len) {
+ DBG_P(1, "\n %.5lx:", addr);
+ for (unsigned i = 0; i<16; i++)
+ DBG_P(1, " %.2x", z80_read(addr++));
+ len -= len > 16 ? 16 : len;
+ }
+ DBG_P(1, "\n");
+}
+
+/*--------------------------------------------------------------------------*/
+
+void setup_rtc(void)
+{
+ /* TODO: */
+}
+
+void setup_avr(void)
+{
+ /* WD */
+
+ /* CPU */
+
+ /* Disable JTAG Interface regardless of the JTAGEN fuse setting. */
+ MCUCR = _BV(JTD);
+ MCUCR = _BV(JTD);
+
+ /* disable unused periphels */
+ PRR0 = _BV(PRTIM2) | _BV(PRTIM0) | _BV(PRADC);
+ PRR1 = _BV(PRTIM5) | _BV(PRTIM4) | _BV(PRTIM3) |
+ _BV(PRUSART3) | _BV(PRUSART2) | _BV(PRUSART1);
+
+ /* disable analog comparator */
+ ACSR = _BV(ACD);
+ /* Ports */
+
+ /* Clock */
+ CLKPR = _BV(CLKPCE);
+ CLKPR = 0;
+
+ /* Timer */
+
+ OCR1A = F_CPU / 8 / 1000 - 1; // Timer1: 1000Hz interval (OC1A)
+ TCCR1B = 0b00001010;
+ TIMSK1 = _BV(OCIE1A); // Enable TC1.oca interrupt
+}
+
+const __flash uint8_t iniprog[] = {
+ 0xAF, // xor a
+ 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh
+ 0x3E, 0x30, // ld a,030h
+ 0xED, 0x39, 0x32 //out0 (dcntl),a ;0 mem, max i/0 wait states
+};
+
+const __flash uint8_t sertest[] = {
+ 0xAF, // xor a
+ 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh
+ 0x3E, 0x30, // ld a,030h
+ 0xED, 0x39, 0x32, // out0 (dcntl),a ;0 mem, max i/0 wait states
+ 0x3E, 0x80, // ld a,M_MPBT ;no MP, PS=10, DR=16, SS=0
+ 0xED, 0x39, 0x03, // out0 (cntlb1),a
+ 0x3E, 0x64, // ld a,M_RE + M_TE + M_MOD2 ;
+ 0xED, 0x39, 0x01, // out0 (cntla1),a
+ 0x3E, 0x00, // ld a,0
+ 0xED, 0x39, 0x05, // out0 (stat1),a ;Enable rx interrupts
+ 0xED, 0x38, 0x05, //l0:in0 a,(stat1)
+ 0xE6, 0x80, // and 80h
+ 0x28, 0xF9, // jr z,l0
+ 0xED, 0x00, 0x09, // in0 b,(rdr1)
+ 0xED, 0x38, 0x05, //l1:in0 a,(stat1)
+ 0xE6, 0x02, // and 02h
+ 0x28, 0xF9, // jr z,l1
+ 0xED, 0x01, 0x07, // out0 (tdr1),b
+ 0x18, 0xEA, // jr l0
+};
+
+const __flash uint8_t test1[] = {
+ 0xAF, // xor a
+ 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh
+ 0x3E, 0x30, // ld a,030h
+ 0xED, 0x39, 0x32, // out0 (dcntl),a ;0 mem, max i/0 wait states
+ 0x21, 0x1E, 0x00, // ld hl,dmclrt ;load DMA registers
+ 0x06, 0x08, // ld b,dmct_e-dmclrt
+ 0x0E, 0x20, // ld c,sar0l
+ 0xED, 0x93, // otimr
+ 0x3E, 0xC3, // ld a,0c3h ;dst +1, src +1, burst
+ 0xED, 0x39, 0x31, // out0 (dmode),a ;
+ 0x3E, 0x62, // ld a,062h ;enable dma0,
+ 0xED, 0x39, 0x30, //cl_1: out0 (dstat),a ;copy 64k
+ 0x18, 0xFB, // jr cl_1 ;
+ 0x00, 0x00, //dmclrt: dw 0 ;src (inc)
+ 0x00, // db 0 ;src
+ 0x00, 0x00, // dw 0 ;dst (inc),
+ 0x00, // db 0 ;dst
+ 0x00, 0x00, // dw 0 ;count (64k)
+};
+
+
+int main(void)
+{
+ int_fast8_t state = 0;
+ int ch;
+
+ setup_avr();
+ serial_setup();
+ setup_rtc();
+ sei();
+
+ printf_P(PSTR("\n(ATMEGA1281+HD64180)_stamp Tester\n"));
+
+ DBG_P(1, "z80_setup_bus... ");
+ z80_setup_msg_fifo();
+ z80_setup_bus();
+ DBG_P(1, "done.\n");
+
+ DBG_P(1, "Get bus... ");
+/* Now done via S_Z180_RUNNING
+ z80_busreq(LOW);
+ z80_reset(HIGH);
+*/
+ z80_request_bus();
+ DBG_P(1, "got it!\n");
+
+// z80_sram_fill(0, (uint32_t)512 * 1024, 0x00, 3);
+// z80_sram_cmp(0, (uint32_t)512 * 1024, 0x00, 3);
+// z80_dump_mem(0, 0x400);
+
+ z80_memset(0, 0x76, 0x80000);
+// z80_memset(0, 0x00, 0x80000);
+// z80_write_block(test1, 0, sizeof(test1));
+
+// z80_dump_mem(0, 0x100);
+
+// z80_sram_cmp(0, (uint32_t)512 * 1024, 0x76, 0);
+
+ z80_load_mem();
+// z80_write(0, 0x76);
+// z80_dump_mem(0, 0x200);
+
+
+/* Now done via S_Z180_RUNNING
+ z80_reset(LOW);
+*/
+ z80_release_bus();
+ DBG_P(1, "Bus released!\n");
+ z80_reset(HIGH);
+ DBG_P(1, "Reset released!\n");
+
+ to_counter = 200;
+
+ while (1) {
+
+ if (Stat & S_10MS_TO) {
+ Stat &= ~S_10MS_TO;
+ do_10ms();
+ }
+
+
+ if ((ch = serial_getc()) >= 0) {
+ switch (state) {
+ case 0:
+ if (ch == ESCCHAR) {
+ state = 1;
+ /* TODO: Timer starten */
+ } else {
+// z80_memfifo_putc(fifo_out, ch);
+ serial_putc(ch);
+ if (ch == '\r')
+ serial_putc('\n');
+ }
+ break;
+ case 1:
+ switch (ch) {
+
+ case 'r':
+ z80_reset_pulse();
+ break;
+
+ case 'b':
+ z80_request_bus();
+ z80_dump_mem(0, 0x2d20);
+ z80_release_bus();
+ break;
+
+ case 'e':
+ z80_request_bus();
+ z80_dump_mem(0x80000-0x4000, 0x800);
+ z80_dump_mem(0x80000-0x200, 0x200);
+ z80_release_bus();
+ break;
+
+ case ESCCHAR:
+ default:
+// z80_memfifo_putc(fifo_out, ch);
+ serial_putc(ch);
+ if (ch == '\r')
+ serial_putc('\n');
+ }
+ state = 0;
+ break;
+ }
+ }
+
+// check_msg_fifo();
+ }
+
+ return 0;
+}
--- /dev/null
+/**
+ *
+ * Pin assignments
+ *
+ * | Z180-Sig | AVR-Port | Dir | Special Function |
+ * +------------+---------------+-------+-----------------------+
+ * | A0 | PA 0 | O | |
+ * | A1 | PA 1 | O | |
+ * | A2 | PA 2 | O | |
+ * | A3 | PA 3 | O | |
+ * | A4 | PA 4 | O | |
+ * | A5 | PA 5 | O | |
+ * | A6 | PA 6 | O | |
+ * | A7 | PA 7 | O | |
+ * | A8 | PC 0 | O | |
+ * | A9 | PC 1 | O | |
+ * | A10 | PC 2 | O | |
+ * | A11 | PC 3 | O | |
+ * | A12 | PC 4 | O | |
+ * | A13 | PC 5 | O | |
+ * | A14 | PC 6 | O | |
+ * | A15 | PC 7 | O | |
+ * | A16 | PE 2 | O | |
+ * | A17 | PE 3 | O | |
+ * | A18 | PE 4 | O | |
+ * | D0 | PF 0 | I/O | |
+ * | D1 | PF 1 | I/O | |
+ * | D2 | PF 2 | I/O | |
+ * | D3 | PF 3 | I/O | |
+ * | D4 | PF 4 | I/O | |
+ * | D5 | PF 5 | I/O | |
+ * | D6 | PF 6 | I/O | |
+ * | D7 | PF 7 | I/O | |
+ * | RD | PD 3 | O | |
+ * | WR | PD 2 | O | |
+ * | MREQ | PD 4 | O | |
+ * | RST | PD 5 | O | |
+ * | BUSREQ | PD 7 | O | |
+ * | BUSACK | PD 6 | I | |
+ * | IOCS1 | PE 5 | I | |
+ * |* HALT | P | | |
+ * |* NMI | P | | |
+ * | | P | | |
+ * | | P | | af1 USART1_TX |
+ * | | P | | af1 USART1_RX |
+ * | | P |JTDI | remap SPI1_NSS' |
+ * | | P |JTDO | remap SPI1_SCK' |
+ * | | P |JTRST | remap SPI1_MISO' |
+ * | | P | | remap SPI1_MOSI' |
+ * | | P | | af1 OSC32 |
+ * | | P | | af1 OSC32 |
+
+
+ */
+
+#include <avr/io.h>
+#include <util/delay.h>
+#include <util/atomic.h>
+#include <stdio.h>
+#include "debug.h"
+#include "z80-if.h"
+
+
+/* Number of array elements */
+#define NELEMS(x) (sizeof x/sizeof *x)
+
+
+#define CONCAT(x,y) x ## y
+#define EVALUATOR(x,y) CONCAT(x,y)
+
+#define GPIO_(X) CONCAT(GPIO, X)
+
+struct bits {
+ uint8_t b0:1;
+ uint8_t b1:1;
+ uint8_t b2:1;
+ uint8_t b3:1;
+ uint8_t b4:1;
+ uint8_t b5:1;
+ uint8_t b6:1;
+ uint8_t b7:1;
+} __attribute__((__packed__));
+
+#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)
+
+
+
+#define P_MREQ PORTD
+#define MREQ 4
+#define DDR_MREQ DDRD
+#define P_RD PORTD
+#define RD 3
+#define P_WR PORTD
+#define WR 2
+#define P_BUSREQ PORTD
+#define BUSREQ 7
+#define DDR_BUSREQ DDRD
+#define P_BUSACK PORTD
+#define PIN_BUSACK PIND
+#define BUSACK 6
+#define DDR_BUSACK DDRD
+//#define P_HALT PORTA
+//#define HALT 12
+#define P_IOCS1 PORTE
+#define IOCS1 5
+#define DDR_IOCS1 DDRE
+//#define P_NMI PORTB
+//#define NMI 7
+#define P_RST PORTD
+#define DDR_RST DDRD
+#define RST 5
+
+
+#define P_DB PORTF
+#define PIN_DB PINF
+#define DDR_DB DDRF
+
+#define P_ADL PORTA
+#define P_ADH PORTC
+#define P_ADB PORTE
+#define PIN_ADB PINE
+#define DDR_ADL DDRA
+#define DDR_ADH DDRC
+#define DDR_ADB DDRE
+
+#define ADB_WIDTH 3
+#define ADB_SHIFT 2
+//#define ADB_PORT PORTE
+
+
+#define Z80_O_MREQ SBIT(P_MREQ, 4)
+#define Z80_O_RD SBIT(P_RD, 3)
+#define Z80_O_WR SBIT(P_WR, 2)
+#define Z80_O_BUSREQ SBIT(P_BUSREQ, 7)
+//#define Z80_O_NMI SBIT(P_NMI, )
+#define Z80_O_RST SBIT(P_RST, 5)
+#define Z80_I_BUSACK SBIT(PIN_BUSACK, 6)
+//#define Z80_I_HALT SBIT(P_HALT, )
+
+
+#define MASK(n) ((1<<(n))-1)
+#define SMASK(w,s) (MASK(w) << (s))
+
+
+
+typedef union {
+ uint32_t l;
+ uint16_t w[2];
+ uint8_t b[4];
+} addr_t;
+
+
+static zstate_t zstate;
+
+/*--------------------------------------------------------------------------*/
+
+
+static void z80_setup_addrbus_tristate(void)
+{
+ /* /MREQ, /RD, /WR: Input, no pullup */
+ DDR_MREQ &= ~(_BV(MREQ) | _BV(RD) | _BV(WR));
+ Z80_O_MREQ = 0;
+ Z80_O_RD = 0;
+ Z80_O_WR = 0;
+
+ P_ADL = 0;
+ DDR_ADL = 0;
+ P_ADH = 0;
+ DDR_ADH = 0;
+ PIN_ADB = P_ADB & ~(MASK(ADB_WIDTH) << ADB_SHIFT);
+ DDR_ADB = DDR_ADB & ~(MASK(ADB_WIDTH) << ADB_SHIFT);
+}
+
+
+static void z80_setup_addrbus_active(void)
+{
+ /* /MREQ, /RD, /WR: Output and high */
+ Z80_O_MREQ = 1;
+ Z80_O_RD = 1;
+ Z80_O_WR = 1;
+ DDR_MREQ |= _BV(MREQ) | _BV(RD) | _BV(WR);
+
+ DDR_ADL = 0xff;
+ DDR_ADH = 0xff;
+ DDR_ADB = DDR_ADB | (MASK(ADB_WIDTH) << ADB_SHIFT);
+}
+
+
+static void z80_setup_dbus_in(void)
+{
+ DDR_DB = 0;
+ P_DB = 0;
+}
+
+
+static void z80_setup_dbus_out(void)
+{
+ DDR_DB = 0xff;
+}
+
+
+static void z80_reset_pulse(void)
+{
+ Z80_O_RST = 0;
+ _delay_us(10);
+ Z80_O_RST = 1;
+}
+
+
+void z80_setup_bus(void)
+{
+ /* /ZRESET: Output and low */
+ Z80_O_RST = 0;
+ DDR_RST |= _BV(RST);
+
+ /* /BUSREQ: Output and high */
+ Z80_O_BUSREQ = 1;
+ DDR_BUSREQ |= _BV(BUSREQ);
+
+ /* /BUSACK: Input, no pullup */
+ DDR_BUSACK &= ~_BV(BUSACK);
+ P_BUSACK &= ~_BV(BUSACK);
+
+ /* /IOCS1: Input, no pullup */
+ DDR_IOCS1 &= ~_BV(IOCS1);
+ P_IOCS1 &= ~_BV(IOCS1);
+
+ z80_setup_addrbus_tristate();
+ z80_setup_dbus_in();
+
+ zstate = RESET;
+}
+
+
+zstate_t z80_bus_state(void)
+{
+ return zstate;
+}
+
+
+static void z80_busreq_hpulse(void)
+{
+ z80_setup_dbus_in();
+ z80_setup_addrbus_tristate();
+
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ Z80_O_BUSREQ = 1;
+ Z80_O_BUSREQ = 1; /* 2 AVR clock cycles */
+ Z80_O_BUSREQ = 0; /* 2 AVR clock cycles */
+ }
+
+ if (zstate & ZST_ACQUIRED) {
+ while(Z80_I_BUSACK == 1)
+ ;
+ z80_setup_addrbus_active();
+ }
+}
+
+
+/*
+
+ + | | | | |
+ + State | RESET | RESET_AQRD | RUNNING | RUNNING_AQRD |
+ + | | | | |
+ + | 0 | 1 | 2 | 3 |
+Event + | | | | |
+----------------+---------------+---------------+---------------+---------------+
+ | | | | |
+Reset | 0 | 0 | 0 | 0 |
+ | | | | |
+ | | | | |
+Request | 1 | | 3 | |
+ | | | | |
+ | | | | |
+Release | | 0 | | 2 |
+ | | | | |
+ | | | | |
+Run | 2 | 3 | | |
+ | | | | |
+ | | | | |
+Restart | | | 2 | 3 |
+ | | | | |
+ | | | | |
+M_Cycle | | | | 3 |
+ | | | | |
+ | | | | |
+*/
+
+zstate_t z80_bus_cmd(bus_cmd_t cmd)
+{
+ switch (cmd) {
+
+ case Reset:
+ z80_setup_dbus_in();
+ z80_setup_addrbus_tristate();
+ Z80_O_RST = 0;
+ Z80_O_BUSREQ = 1;
+ zstate = RESET;
+ break;
+
+ case Request:
+ switch (zstate) {
+ case RESET:
+ Z80_O_BUSREQ = 0;
+ Z80_O_RST = 1;
+ while(Z80_I_BUSACK == 1)
+ ;
+ z80_setup_addrbus_active();
+ zstate = RESET_AQRD;
+ break;
+
+ case RUNNING:
+ Z80_O_BUSREQ = 0;
+ while(Z80_I_BUSACK == 1)
+ ;
+ z80_setup_addrbus_active();
+ zstate = RUNNING_AQRD;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case Release:
+ switch (zstate) {
+ case RESET_AQRD:
+ z80_setup_dbus_in();
+ z80_setup_addrbus_tristate();
+ Z80_O_RST = 0;
+ Z80_O_BUSREQ = 1;
+ zstate = RESET;
+ break;
+ case RUNNING_AQRD:
+ z80_setup_dbus_in();
+ z80_setup_addrbus_tristate();
+ Z80_O_BUSREQ = 1;
+ zstate = RUNNING;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case Run:
+ switch (zstate) {
+ case RESET:
+ Z80_O_RST = 1;
+ zstate = RUNNING;
+ break;
+
+ case RESET_AQRD:
+ z80_setup_dbus_in();
+ z80_setup_addrbus_tristate();
+ z80_reset_pulse();
+ z80_setup_addrbus_active();
+ zstate = RUNNING_AQRD;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case Restart:
+ switch (zstate) {
+ case RUNNING:
+ case RUNNING_AQRD:
+ z80_reset_pulse();
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case M_Cycle:
+ switch (zstate) {
+ case RUNNING_AQRD:
+ z80_busreq_hpulse();
+ break;
+ default:
+ break;
+ }
+ }
+ return zstate;
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+static
+//inline __attribute__ ((always_inline))
+void z80_setaddress(uint32_t addr)
+{
+ addr_t x; x.l = addr;
+
+ P_ADL = x.b[0];
+ P_ADH = x.b[1];
+ PIN_ADB = ((x.b[2] << ADB_SHIFT) ^ P_ADB) & MASK(ADB_WIDTH) << ADB_SHIFT ;
+}
+
+void z80_write(uint32_t addr, uint8_t data)
+{
+ z80_setaddress(addr);
+ Z80_O_MREQ = 0;
+ z80_setup_dbus_out();
+ P_DB = data;
+ P_DB = data;
+ Z80_O_WR = 0;
+ Z80_O_WR = 0;
+ Z80_O_WR = 1;
+ Z80_O_MREQ = 1;
+}
+
+uint8_t z80_read(uint32_t addr)
+{
+ uint8_t data;
+
+ z80_setaddress(addr);
+ Z80_O_MREQ = 0;
+ z80_setup_dbus_in();
+ Z80_O_RD = 0;
+ Z80_O_RD = 0;
+ Z80_O_RD = 0;
+ data = PIN_DB;
+ Z80_O_RD = 1;
+ Z80_O_MREQ = 1;
+
+ return data;
+}
+
+
+void z80_memset(uint32_t addr, uint8_t data, uint32_t length)
+{
+ z80_setup_dbus_out();
+ Z80_O_MREQ = 0;
+ while(length--) {
+ z80_setaddress(addr++);
+ P_DB = data;
+ P_DB = data;
+ Z80_O_WR = 0;
+ Z80_O_WR = 0;
+ Z80_O_WR = 1;
+ }
+ Z80_O_MREQ = 1;
+}
+
+void z80_write_block(const __flash uint8_t *src, uint32_t dest, uint32_t length)
+{
+ uint8_t data;
+
+ z80_setup_dbus_out();
+ Z80_O_MREQ = 0;
+ while(length--) {
+ z80_setaddress(dest++);
+ data = *src++;
+ P_DB = data;
+ P_DB = data;
+ Z80_O_WR = 0;
+ Z80_O_WR = 0;
+ Z80_O_WR = 1;
+ }
+ Z80_O_MREQ = 1;
+}
+
+/*
+ 0179' rx.bs_mask: ds 1 ; (buf_len - 1)
+ 017A' rx.in_idx: ds 1 ;
+ 017B' rx.out_idx: ds 1 ;
+ 017C' rx.buf: ds rx.buf_len ;
+ 018B' rx.buf_end equ $-1 ; last byte (start+len-1)
+
+ 018C' tx.bs_mask: ds 1 ; (buf_len - 1)
+ 018D' tx.in_idx: ds 1 ;
+ 018E' tx.out_idx: ds 1 ;
+ 018F' tx.buf: ds tx.buf_len ;
+ 019E' tx.buf_end equ $-1 ; last byte
+*/
+
+
+typedef struct __attribute__((packed)) {
+ uint8_t mask;
+ uint8_t in_idx;
+ uint8_t out_idx;
+ uint8_t buf[];
+} zfifo_t;
+
+
+
+#define FIFO_BUFSIZE_MASK -3
+#define FIFO_INDEX_IN -2
+#define FIFO_INDEX_OUT -1
+
+
+static struct {
+ uint32_t base;
+ uint8_t idx_out,
+ idx_in,
+ mask;
+ } fifo_dsc[NUM_FIFOS];
+
+
+void z80_memfifo_init(const fifo_t f, uint32_t adr)
+{
+
+DBG_P(2, "z80_memfifo_init: %i, %lx\n", f, adr);
+
+ fifo_dsc[f].base = adr;
+
+ z80_bus_cmd(Request);
+
+ fifo_dsc[f].mask = z80_read(adr + FIFO_BUFSIZE_MASK);
+ fifo_dsc[f].idx_in = z80_read(adr + FIFO_INDEX_IN);
+ fifo_dsc[f].idx_out = z80_read(adr + FIFO_INDEX_OUT);
+
+ z80_bus_cmd(Release);
+}
+
+
+int z80_memfifo_is_empty(const fifo_t f)
+{
+ int rc = 1;
+
+ if (fifo_dsc[f].base != 0) {
+
+ uint32_t adr = fifo_dsc[f].base + FIFO_INDEX_IN;
+ uint8_t idx;
+
+ z80_bus_cmd(Request);
+ idx = z80_read(adr);
+ z80_bus_cmd(Release);
+ rc = idx == fifo_dsc[f].idx_out;
+ }
+
+ return rc;
+}
+
+int z80_memfifo_is_full(const fifo_t f)
+{
+ int rc = 1;
+
+ if (fifo_dsc[f].base != 0) {
+ z80_bus_cmd(Request);
+ rc = ((fifo_dsc[f].idx_in + 1) & fifo_dsc[f].mask)
+ == z80_read(fifo_dsc[f].base+FIFO_INDEX_OUT);
+ z80_bus_cmd(Release);
+ }
+ return rc;
+}
+
+uint8_t z80_memfifo_getc(const fifo_t f)
+{
+ uint8_t rc, idx;
+
+ while (z80_memfifo_is_empty(f))
+ ;
+
+ z80_bus_cmd(Request);
+ idx = fifo_dsc[f].idx_out;
+ rc = z80_read(fifo_dsc[f].base+idx);
+ fifo_dsc[f].idx_out = ++idx & fifo_dsc[f].mask;
+ z80_write(fifo_dsc[f].base+FIFO_INDEX_OUT, fifo_dsc[f].idx_out);
+ z80_bus_cmd(Release);
+
+ return rc;
+}
+
+
+void z80_memfifo_putc(fifo_t f, uint8_t val)
+{
+ int idx;
+
+ while (z80_memfifo_is_full(f))
+ ;
+
+ z80_bus_cmd(Request);
+ idx = fifo_dsc[f].idx_in;
+ z80_write(fifo_dsc[f].base+idx, val);
+ fifo_dsc[f].idx_in = ++idx & fifo_dsc[f].mask;
+ z80_write(fifo_dsc[f].base+FIFO_INDEX_IN, fifo_dsc[f].idx_in);
+ z80_bus_cmd(Release);
+}
+
+/*--------------------------------------------------------------------------*/
+/*
+ TODO: Rewrite msg_fifo routines for AVR
+*/
+
+static struct {
+ uint32_t base;
+ //uint8_t idx_out, idx_in;
+ uint16_t count;
+ uint8_t buf[256];
+ } msg_fifo;
+
+/*--------------------------------------------------------------------------*/
+
+#if 0
+
+static void tim1_setup(void)
+{
+ RCC_APB2RSTR |= RCC_APB2RSTR_TIM1RST;
+ RCC_APB2RSTR &= ~RCC_APB2RSTR_TIM1RST;
+
+ TIM1_CR1 = 0;
+
+ TIM1_SMCR = 0
+ /* | TIM_SMCR_ETP */
+ /* | TIM_SMCR_ETF_CK_INT_N_2 */
+ | TIM_SMCR_TS_ETRF
+ | TIM_SMCR_SMS_OFF
+ ;
+
+ TIM1_DIER = TIM_DIER_TDE;
+
+
+ TIM1_CCMR1 = 0
+ | TIM_CCMR1_OC1M_FORCE_LOW
+ | TIM_CCMR1_CC1S_OUT;
+
+ TIM1_SMCR |= TIM_SMCR_SMS_TM;
+}
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+void z80_setup_msg_fifo(void)
+{
+// gpio_set_mode(P_BUSACK, GPIO_MODE_INPUT,
+// GPIO_CNF_INPUT_FLOAT, GPIO_BUSACK | GPIO_IOCS1);
+
+//...
+
+// msg_fifo.count = NELEMS(msg_fifo.buf);
+ msg_fifo.count = 0;
+ msg_fifo.base = 0;
+
+}
+
+
+void z80_init_msg_fifo(uint32_t addr)
+{
+
+DBG_P(1, "z80_init_msg_fifo: %lx\n", addr);
+
+ z80_bus_cmd(Request);
+ z80_write(addr+FIFO_INDEX_OUT, z80_read(addr+FIFO_INDEX_IN));
+ z80_bus_cmd(Release);
+ msg_fifo.base = addr;
+}
+
+
+int z80_msg_fifo_getc(void)
+{
+ int c = -1;
+
+#if 0
+ if (msg_fifo.count != (NELEMS(msg_fifo.buf) /*- DMA1_CNDTR4 */ )) {
+ c = msg_fifo.buf[msg_fifo.count];
+ if (++msg_fifo.count == NELEMS(msg_fifo.buf))
+ msg_fifo.count = 0;
+
+ if (msg_fifo.base != 0) {
+ z80_bus_cmd(Request);
+ z80_write(msg_fifo.base+FIFO_INDEX_OUT, msg_fifo.count);
+ z80_bus_cmd(Release);
+ }
+ }
+#endif
+
+ return c;
+}
--- /dev/null
+
+#define ZST_ACQUIRED 0x01
+#define ZST_RUNNING 0x02
+
+typedef enum {
+ RESET = 0x00,
+ RESET_AQRD = ZST_ACQUIRED,
+ RUNNING = ZST_RUNNING,
+ RUNNING_AQRD = ZST_RUNNING | ZST_ACQUIRED,
+} zstate_t;
+
+typedef enum {
+ Reset,
+ Request,
+ Release,
+ Run,
+ Restart,
+ M_Cycle
+} bus_cmd_t;
+
+typedef enum {LOW, HIGH} level_t;
+
+zstate_t z80_bus_state(void);
+zstate_t z80_bus_cmd(bus_cmd_t cmd);
+void z80_setup_bus(void);
+int z80_stat_reset(void);
+//void z80_busreq(level_t level);
+int z80_stat_halt(void);
+
+void z80_write(uint32_t addr, uint8_t data);
+uint8_t z80_read(uint32_t addr);
+void z80_memset(uint32_t addr, uint8_t data, uint32_t length);
+void z80_write_block(const FLASH uint8_t *src, uint32_t dest, uint32_t length);
+
+
+typedef enum fifo_t {fifo_in, fifo_out, NUM_FIFOS} fifo_t;
+
+void z80_memfifo_init(const fifo_t f, uint32_t adr);
+int z80_memfifo_is_empty(const fifo_t f);
+int z80_memfifo_is_full(const fifo_t f);
+uint8_t z80_memfifo_getc(const fifo_t f);
+void z80_memfifo_putc(fifo_t f, uint8_t val);
+
+void z80_setup_msg_fifo(void);
+void z80_init_msg_fifo(uint32_t addr);
+int z80_msg_fifo_getc(void);
--- /dev/null
+CONFIG_DEBUG=0
--- /dev/null
+CC = $(TOOLCHAIN)-gcc
+LD = $(TOOLCHAIN)-gcc
+AR = $(TOOLCHAIN)-ar
+AS = $(TOOLCHAIN)-as
+OBJCOPY = $(TOOLCHAIN)-objcopy
+OBJDUMP = $(TOOLCHAIN)-objdump
+SIZE = $(TOOLCHAIN)-size
+GDB = $(TOOLCHAIN)-gdb
+
+
+CFLAGS += -g -Os
+CFLAGS += -std=gnu99
+CFLAGS += -Wall -Wextra
+CFLAGS += -Wredundant-decls
+#CFLAGS += -fno-common -ffunction-sections -fdata-sections
+
+
+LDFLAGS += -Wl,--gc-sections
+LDFLAGS += -Wl,--cref
+
+ifneq ($(LDSCRIPT),)
+LDFLAGS += -T$(LDSCRIPT)
+endif
+
+
+!cc = |> ^ CC %f^ $(CC) $(CFLAGS) $(CPPFLAGS) -c %f -o %o |> %B.o
+!LINK = |> ^ LINK %o^ $(LD) $(CFLAGS) $(LDFLAGS) -Wl,-Map=%O.map %f $(LDLIBS) -o %o |> | %O.map
+!OBJCOPY= |> ^ OBJCOPY %o^ $(OBJCOPY) -Oihex %f %o |>
+!OBJDUMP= |> ^ OBJDUMP %o^ $(OBJDUMP) -h -S %f > %o |> %O.lss
+!SIZE = |> ^ SIZE %f^ $(SIZE) %f |>
+
+
+: foreach $(SRC) | $(PREDEP) |> !cc |> {objs}
+: $(SRC_Z) |> !cc $(CPPFLAGS_Z) |> {objs}
+
+: {objs} |> !LINK |> $(PROG).elf {elf}
+: {elf} |> !OBJCOPY |> %B.hex {aux}
+: {elf} |> !OBJDUMP |> %B.lss {aux}
+: {elf} | {aux} |> !SIZE |>
+
--- /dev/null
+Subproject commit 69726cd1a5baf455d247d3e2469e53cd26856c28
--- /dev/null
+include_rules
+
+PROG = z180-stamp-stm32
+SRC = z180-stamp-stm32.c serial.c z80-if.c
+SRC_Z = ../z180/hdrom.c
+#TARGETS = $(PROG).elf
+
+FP_FLAGS = -msoft-float
+DEFS = -DSTM32F1 -DBAUD=115200
+
+LIBNAME = opencm3_stm32f1
+OPENCM3_DIR = $(TOP)/libopencm3
+LDSCRIPT = stm32vl-discovery.ld
+
+###############################################################################
+# Executables
+
+TOOLCHAINDIR = /usr/local/gcc-arm-none-eabi-4_8-2014q2/bin
+TOOLCHAIN = $(TOOLCHAINDIR)/arm-none-eabi
+
+CC = $(TOOLCHAIN)-gcc
+LD = $(TOOLCHAIN)-gcc
+AR = $(TOOLCHAIN)-ar
+AS = $(TOOLCHAIN)-as
+OBJCOPY = $(TOOLCHAIN)-objcopy
+OBJDUMP = $(TOOLCHAIN)-objdump
+SIZE = $(TOOLCHAIN)-size
+GDB = $(TOOLCHAIN)-gdb
+
+###############################################################################
+
+INCLUDES += $(OPENCM3_DIR)/include
+LIBDIRS += $(OPENCM3_DIR)/lib
+
+SCRIPT_DIR = $(OPENCM3_DIR)/scripts
+
+
+ifdef DEBUG
+DEFS += -DDEBUG=2
+endif
+
+CFLAGS += -g -Os
+CFLAGS += -mthumb -mcpu=cortex-m3 $(FP_FLAGS) -mfix-cortex-m3-ldrd
+CFLAGS += -std=gnu99
+CFLAGS += -Wall -Wextra -Wimplicit-function-declaration
+CFLAGS += -Wredundant-decls
+#CFLAGS += -fno-common -ffunction-sections -fdata-sections
+CFLAGS += -I $(INCLUDES)
+
+CPPFLAGS += $(DEFS)
+
+# Linker flags
+LDFLAGS += --static -nostartfiles
+LDFLAGS += -T$(LDSCRIPT)
+LDFLAGS += -Wl,--gc-sections
+LDFLAGS += -Wl,--cref
+
+LDLIBS += -L$(LIBDIRS) -l$(LIBNAME)
+LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group
+
+
+!cc = |> ^ CC %f^ $(CC) $(CFLAGS) $(CPPFLAGS) -c %f -o %o |> %B.o
+!LINK = |> ^ LINK %o^ $(LD) $(CFLAGS) $(LDFLAGS) -Wl,-Map=%O.map %f $(LDLIBS) -o %o |> | %O.map
+!OBJCOPY= |> ^ OBJCOPY %o^ $(OBJCOPY) -Oihex %f %o |>
+!OBJDUMP= |> ^ OBJDUMP %o^ $(OBJDUMP) -h -S %f > %o |> %O.lss
+!SIZE = |> ^ SIZE^ $(SIZE) %f |>
+
+: foreach $(SRC) $(SRC_Z) | ../z180/hdrom.h |> !cc |> {objs}
+
+: {objs} |> !LINK |> $(PROG).elf
+: $(PROG).elf |> !OBJCOPY |> %B.hex
+: $(PROG).elf |> !OBJDUMP |> %B.lss
+: $(PROG).elf |> !SIZE |>
+
--- /dev/null
+
+#ifndef DEBUG_H_
+#define DEBUG_H_
+
+#ifdef DEBUG
+#define DBG_P(lvl, ...) if (DEBUG>=lvl) fprintf( stderr, __VA_ARGS__ )
+#else
+#define DBG_P(lvl, ...)
+#endif
+
+#endif /* DEBUG_H_ */
--- /dev/null
+/*
+ * serial.c
+ *
+ * Created on: 04.05.2014
+ * Author: leo
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/usart.h>
+#include <libopencm3/cm3/nvic.h>
+#include "serial.h"
+
+
+#define USART_CONSOLE USART1
+
+int _write(int fd, char *ptr, int len) __attribute__((used));
+
+
+struct ring {
+ uint8_t *data;
+ int size;
+ volatile int begin;
+ volatile int end;
+};
+
+
+#define BUFFER_SIZE 256
+
+struct ring rx_ring;
+struct ring tx_ring;
+uint8_t rx_ring_buffer[BUFFER_SIZE];
+uint8_t tx_ring_buffer[BUFFER_SIZE];
+
+
+static void ring_init(struct ring *ring, uint8_t *buf, int size)
+{
+ ring->data = buf;
+ ring->size = size;
+ ring->begin = 0;
+ ring->end = 0;
+}
+
+static int ring_write_ch(struct ring *ring, uint8_t ch)
+{
+ int ep = (ring->end + 1) % ring->size;
+
+ if ((ep) != ring->begin) {
+ ring->data[ring->end] = ch;
+ ring->end = ep;
+ return 1;
+ }
+
+ return -1;
+}
+
+static int ring_write(struct ring *ring, uint8_t *data, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ if (ring_write_ch(ring, data[i]) < 0)
+ return -i;
+ }
+
+ return i;
+}
+
+static int ring_read_ch(struct ring *ring)
+{
+ int ret = -1;
+
+ if (ring->begin != ring->end) {
+ ret = ring->data[ring->begin];
+ ring->begin = (ring->begin +1) % ring->size;
+ }
+
+ return ret;
+}
+
+void usart_setup(void)
+{
+ /* Initialize output ring buffer. */
+ ring_init(&rx_ring, rx_ring_buffer, BUFFER_SIZE);
+ ring_init(&tx_ring, tx_ring_buffer, BUFFER_SIZE);
+
+ /* Enable the USART1 interrupt. */
+ nvic_enable_irq(NVIC_USART1_IRQ);
+
+ /* Setup GPIO pin GPIO_USART1_TX/LED_GREEN_PIN on GPIO port A for transmit. */
+ /* TODO: USART1 --> USART_CONSOLE */
+
+ gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
+ GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX);
+
+ /* Setup GPIO pin GPIO_USART1_RE_RX on GPIO port B for receive. */
+ gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
+ GPIO_CNF_INPUT_FLOAT, GPIO_USART1_RX);
+
+ /* Setup UART parameters. */
+// usart_set_baudrate(USART_CONSOLE, 38400);
+ usart_set_baudrate(USART_CONSOLE, 115200);
+ usart_set_databits(USART_CONSOLE, 8);
+ usart_set_stopbits(USART_CONSOLE, USART_STOPBITS_1);
+ usart_set_parity(USART_CONSOLE, USART_PARITY_NONE);
+ usart_set_flow_control(USART_CONSOLE, USART_FLOWCONTROL_NONE);
+ usart_set_mode(USART_CONSOLE, USART_MODE_TX_RX);
+
+ /* Enable USART1 Receive interrupt. */
+ USART_CR1(USART1) |= USART_CR1_RXNEIE;
+
+ /* Finally enable the USART. */
+ usart_enable(USART_CONSOLE);
+}
+
+void usart1_isr(void)
+{
+ /* Check if we were called because of RXNE. */
+ if (((USART_CR1(USART1) & USART_CR1_RXNEIE) != 0) &&
+ ((USART_SR(USART1) & USART_SR_RXNE) != 0)) {
+
+ /* Retrieve the data from the peripheral. */
+ ring_write_ch(&rx_ring, usart_recv(USART1));
+
+ }
+
+ /* Check if we were called because of TXE. */
+ if (((USART_CR1(USART1) & USART_CR1_TXEIE) != 0) &&
+ ((USART_SR(USART1) & USART_SR_TXE) != 0)) {
+
+ int data;
+
+ data = ring_read_ch(&tx_ring);
+
+ if (data == -1) {
+ /* Disable the TXE interrupt, it's no longer needed. */
+ USART_CR1(USART1) &= ~USART_CR1_TXEIE;
+ } else {
+ /* Put data into the transmit register. */
+ usart_send(USART1, data);
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void serial_setup(void)
+{
+ usart_setup();
+}
+
+/*--------------------------------------------------------------------------*/
+
+/**
+ * Use USART_CONSOLE as a console.
+ * This is a syscall for newlib
+ * @param fd
+ * @param ptr
+ * @param len
+ * @return
+ */
+int _write(int fd, char *ptr, int len)
+{
+ int i;
+
+ if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
+ for (i = 0; i < len; i++) {
+ if (ptr[i] == '\n') {
+ serial_putc('\r');
+ }
+ serial_putc(ptr[i]);
+ }
+ return i;
+ }
+ errno = EIO;
+ return -1;
+}
+
+int serial_getc(void)
+{
+ return ring_read_ch(&rx_ring);
+}
+
+void serial_putc(uint8_t data)
+{
+ while (ring_write_ch(&tx_ring, data) < 0)
+ ;
+
+ /* Enable the TXE interrupt. */
+ USART_CR1(USART1) |= USART_CR1_TXEIE;
+}
--- /dev/null
+#ifndef SERIAL_H
+#define SERIAL_H
+
+void serial_setup(void);
+void serial_putc(uint8_t);
+int serial_getc(void);
+
+#endif /* SERIAL_H */
--- /dev/null
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Linker script for ST STM32VLDISCOVERY (STM32F100RB, 128K flash, 8K RAM). */
+
+/* Define memory regions. */
+MEMORY
+{
+ rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
+}
+
+/* Include the common ld script. */
+INCLUDE libopencm3_stm32f1.ld
+
--- /dev/null
+/*
+ */
+
+#include <stdio.h>
+
+#include <libopencmsis/core_cm3.h>
+#include <libopencm3/cm3/nvic.h>
+#include <libopencm3/cm3/systick.h>
+#include <libopencm3/stm32/rtc.h>
+#include <libopencm3/stm32/rcc.h>
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/timer.h>
+
+#define ODR 0x0c
+#define IDR 0x08
+
+
+#include "debug.h"
+#include "serial.h"
+#include "z80-if.h"
+#include "../z180/hdrom.h"
+
+#define ESCCHAR ('^'-0x40)
+
+#define S_10MS_TO (1<<0)
+
+/*
+ * LED Connections
+ */
+
+#define LED_PORT GPIOC
+#define LED_BLUE_PIN GPIO8
+#define BLUE 8
+#define LED_GREEN_PIN GPIO9
+#define GREEN 9
+
+
+#define LED_BLUE_ON() BBIO_PERIPH(LED_PORT+ODR, BLUE) = 1
+#define LED_BLUE_OFF() BBIO_PERIPH(LED_PORT+ODR, BLUE) = 0
+#define LED_BLUE_TOGGLE() BBIO_PERIPH(LED_PORT+ODR, BLUE) = !BBIO_PERIPH(LED_PORT+ODR, BLUE)
+
+#define LED_GREEN_ON() BBIO_PERIPH(LED_PORT+ODR, GREEN) = 1
+#define LED_GREEN_OFF() BBIO_PERIPH(LED_PORT+ODR, GREEN) = 0
+#define LED_GREEN_TOGGLE() BBIO_PERIPH(LED_PORT+ODR, GREEN) = !BBIO_PERIPH(LED_PORT+ODR, GREEN)
+
+
+/*
+ * Button connections
+ */
+
+//BBIO_PERIPH(GPIOA+IDR, 0);
+
+#define KEY_PORT GPIOA_IDR
+#define KEY0 GPIO0
+//#define KEY1 GPIO1
+//#define KEY2 GPIO2
+
+#define REPEAT_MASK KEY0 // repeat: key0
+#define REPEAT_START 100 // after 1s
+#define REPEAT_NEXT 20 // every 200ms
+
+
+typedef enum {
+ NOTHING, PULSE, BLINK1, BLINK2
+} LED_MODE;
+
+typedef struct {
+ uint8_t mode;
+ uint8_t ontime, offtime;
+} led_stat_t;
+
+volatile uint8_t led_timer[2];
+led_stat_t led_stat[2];
+
+volatile int timeout_1s;
+volatile uint32_t Stat;
+
+
+/*--------------------------------------------------------------------------*/
+
+
+static void clock_setup(void)
+{
+ //rcc_clock_setup_in_hse_8mhz_out_24mhz();
+ rcc_clock_setup_in_hsi_out_24mhz();
+
+ /* Enable clocks for:
+ GPIO port A (for GPIO_USART1_TX and Button)
+ GPIO port C (LEDs)
+ USART1
+ TIM16 (RST-Pin)
+ TIM1 (IOCS1)
+ */
+ rcc_peripheral_enable_clock(&RCC_APB2ENR,
+ RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN
+ | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN
+ | RCC_APB2ENR_USART1EN | RCC_APB2ENR_AFIOEN
+ | RCC_APB2ENR_TIM1EN | RCC_APB2ENR_TIM16EN);
+ /* Enable clocks for:
+ TIM3
+ */
+ rcc_peripheral_enable_clock(&RCC_APB1ENR,
+ RCC_APB1ENR_TIM3EN);
+
+ /* Enable clocks for:
+ DMA1
+ */
+ rcc_peripheral_enable_clock(&RCC_AHBENR,
+ RCC_AHBENR_DMA1EN);
+}
+
+static void systick_setup(void)
+{
+ /* SysTick interrupt every N clock pulses: set reload to N-1 */
+ STK_RVR = 24000000/1000 - 1;
+
+ /* Set source to core clock, enable int and start counting. */
+ STK_CSR = STK_CSR_CLKSOURCE_AHB | STK_CSR_TICKINT | STK_CSR_ENABLE;
+}
+
+#if 0
+static void nvic_setup(void)
+{
+// nvic_enable_irq(NVIC_RTC_IRQ);
+// nvic_set_priority(NVIC_RTC_IRQ, 1);
+}
+#endif
+
+static void tim3_setup(void)
+{
+ TIM3_CR1 = TIM_CR1_CMS_EDGE | TIM_CR1_DIR_UP;
+
+ TIM3_CCMR2 = 0
+ | TIM_CCMR2_OC4M_FORCE_LOW
+ /* | TIM_CCMR2_OC4M_FORCE_HIGH */
+ /* | TIM_CCMR2_OC4M_PWM2 */
+
+ /* | TIM_CCMR2_OC4PE */
+ /* | TIM_CCMR2_OC4FE */
+ | TIM_CCMR2_CC4S_OUT;
+
+ TIM3_CCER = TIM_CCER_CC4E
+ | TIM_CCER_CC4P;
+
+ TIM3_ARR = 48; /* default */
+ TIM3_CCR4 = 1; /* */
+}
+
+static void gpio_setup(void)
+{
+
+ /* Disable JTAG-DP, but leave SW-DP Enabled. (free PA15, PB3, PB4)
+ Remap SPI1 to PB3, PB4, PB5 and PA15.
+ Remap TIM3 (CH1/PC6, CH2/PC7, CH3/PC8, CH4/PC9)
+ Port D0/Port D1 mapping on OSC_IN/OSC_OUT
+ */
+ gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON,
+ AFIO_MAPR_SPI1_REMAP
+ | AFIO_MAPR_TIM3_REMAP_FULL_REMAP
+ | AFIO_MAPR_PD01_REMAP);
+
+ /* LEDs and User Button. */
+ gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ,
+ GPIO_CNF_OUTPUT_PUSHPULL, LED_BLUE_PIN);
+ gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_10_MHZ,
+ GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, LED_GREEN_PIN);
+ gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
+ GPIO_CNF_INPUT_FLOAT, GPIO0);
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+void delay_systicks(int ticks)
+{
+ int start, stop, now;
+
+ start = STK_CVR;
+ stop = start - ticks;
+ if (stop < 0) {
+ stop += STK_RVR;
+ do {
+ now = STK_CVR;
+ } while ((now > stop) || (now <= start));
+ } else {
+ do {
+ now = STK_CVR;
+ } while ((now > stop) && (now <= start));
+ }
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+static void led_toggle(uint8_t lednr) {
+ if (lednr == 0)
+ LED_BLUE_TOGGLE();
+ else if (lednr == 1)
+ LED_GREEN_TOGGLE();
+}
+
+static void led_on(uint8_t lednr) {
+ if (lednr == 0)
+ LED_BLUE_ON();
+ else if (lednr == 1)
+ LED_GREEN_ON();
+}
+
+static void led_off(uint8_t lednr) {
+ if (lednr == 0)
+ LED_BLUE_OFF();
+ else if (lednr == 1)
+ LED_GREEN_OFF();
+}
+
+static uint8_t led_is_on(uint8_t lednr) {
+ if (lednr == 0)
+ return BBIO_PERIPH(LED_PORT+ODR, BLUE);
+ else if (lednr == 1)
+ return BBIO_PERIPH(LED_PORT+ODR, GREEN);
+ else
+ return 0;
+}
+
+static void ledset(uint8_t lednr, uint8_t what, uint8_t len) {
+
+ led_stat[lednr].mode = what;
+ switch (what) {
+ case PULSE:
+ led_stat[lednr].ontime = len;
+ led_stat[lednr].offtime = 0;
+ led_timer[lednr] = len;
+ led_on(lednr);
+ break;
+ case BLINK1:
+ case BLINK2:
+ if (what == BLINK1)
+ led_stat[lednr].offtime = 100 - len;
+ else
+ led_stat[lednr].offtime = 200 - len;
+ led_stat[lednr].ontime = len;
+ led_timer[lednr] = len;
+ led_on(lednr);
+ break;
+ default:
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+static volatile uint16_t key_state,
+ key_press, // key press detect
+ key_rpt; // key long press and repeat
+
+
+static uint16_t get_key_press(uint16_t key_mask) {
+ __disable_irq();
+ // read and clear atomic !
+ key_mask &= key_press; // read key(s)
+ key_press ^= key_mask; // clear key(s)
+ __enable_irq();
+ return key_mask;
+}
+
+/*
+static uint16_t get_key_rpt(uint16_t key_mask) {
+ __disable_irq();
+ // read and clear atomic !
+ key_mask &= key_rpt; // read key(s)
+ key_rpt ^= key_mask; // clear key(s)
+ __enable_irq();
+ return key_mask;
+}
+*/
+
+static uint16_t get_key_short(uint16_t key_mask) {
+ __disable_irq();
+ // read key state and key press atomic !
+ return get_key_press(key_state & key_mask);
+}
+
+/*
+static uint16_t get_key_long(uint16_t key_mask) {
+ return get_key_press(get_key_rpt(key_mask));
+}
+*/
+
+static void key_timerproc() {
+ static uint16_t key_in_last, rpt;
+ uint16_t key_in, c;
+
+ key_in = KEY_PORT;
+
+ c = key_in_last & key_in & ~key_state;
+
+// key_state = key_state & key_in_last | (key_state | key_in_last) & key_in;
+// key_state = key_state & key_in | (key_state | key_in) & key_in_last;
+
+ key_state = c | ((key_in_last | key_in) & key_state);
+
+// key_state = (key_state&key_in_last) | (key_state&key_in) | (key_in_last&key_in);
+
+ key_press |= c;
+
+ key_in_last = key_in;
+
+
+ if ((key_state & REPEAT_MASK) == 0) // check repeat function
+ rpt = REPEAT_START;
+ if (--rpt == 0) {
+ rpt = REPEAT_NEXT; // repeat delay
+ key_rpt |= key_state & REPEAT_MASK;
+ }
+
+}
+
+/*--------------------------------------------------------------------------*/
+
+void sys_tick_handler(void)
+{
+ static int_fast8_t tick_10ms = 0;
+ static int_fast16_t count_ms = 0;
+
+ int_fast8_t i;
+
+ ++tick_10ms;
+ if (tick_10ms == 10)
+ {
+ Stat |= S_10MS_TO;
+
+ tick_10ms = 0;
+
+ i = led_timer[0];
+ if (i)
+ led_timer[0] = i - 1;
+ i = led_timer[1];
+ if (i)
+ led_timer[1] = i - 1;
+
+ key_timerproc();
+
+ /* Drive timer procedure of low level disk I/O module */
+ //disk_timerproc();
+ }
+
+ count_ms++;
+ if (count_ms == 1000) {
+ count_ms = 0;
+
+ i = timeout_1s;
+ if (i)
+ timeout_1s = i - 1;
+ }
+}
+
+void rtc_isr(void)
+{
+ /* The interrupt flag isn't cleared by hardware, we have to do it. */
+ rtc_clear_flag(RTC_SEC);
+
+}
+
+/*--------------------------------------------------------------------------*/
+
+void tim3_set(int mode)
+{
+ uint16_t cc_mode;
+
+ cc_mode = TIM_CCMR2_CC4S_OUT;
+
+ TIM3_CR1 = TIM_CR1_CMS_EDGE | TIM_CR1_DIR_UP /*| TIM_CR1_OPM */ ;
+
+ if (mode < 0)
+ cc_mode |= TIM_CCMR2_OC4M_FORCE_LOW;
+ else if (mode == 0)
+ cc_mode |= TIM_CCMR2_OC4M_FORCE_HIGH;
+ else {
+ TIM3_ARR = mode;
+ TIM3_CCR4 = mode/2;
+ cc_mode |= TIM_CCMR2_OC4M_PWM2;
+ }
+
+ TIM3_CCMR2 = cc_mode;
+
+ if (mode > 0)
+ TIM3_CR1 |= TIM_CR1_CEN;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static uint32_t z80_sram_cmp(uint32_t addr, uint32_t length, uint8_t wval, int inc)
+{
+ uint8_t rval;
+ int_fast8_t errors = 0;
+
+ DBG_P(1, "SRAM: Check %#.5x byte... ", length);
+ while (length--) {
+ if ((rval = z80_read(addr)) != wval) {
+ if (errors == 0) {
+ printf("\nSRAM: Address W R\n" \
+ " -------------\n");
+// 12345 00 11
+ }
+ printf(" %.5lx %.2x %.2x\n", addr, wval, rval);
+
+ if (++errors > 16 )
+ break;
+ }
+ addr++;
+ wval += inc;
+ }
+ DBG_P(1, "Done.\n");
+
+ return addr;
+}
+
+#if 0
+static void z80_sram_fill(uint32_t addr, int length, uint8_t startval, int inc)
+{
+ printf("SRAM: Write %#.5x byte... ", length); //fflush(stdout);
+ while (length--) {
+ z80_write(addr, startval);
+ ++addr;
+ startval += inc;
+ }
+ printf("Done.\n");
+}
+
+
+void z80_sram_fill_string(uint32_t addr, int length, const char *text)
+{
+ char c;
+ const char *p = text;
+
+ while (length--) {
+ z80_write(addr++, c = *p++);
+ if (c == 0)
+ p = text;
+ }
+}
+
+
+uint32_t z80_sram_cmp_string(uint32_t addr, int length, const char *text)
+{
+ char c;
+ const char *p = text;
+
+ while (length--) {
+ c = *p++;
+ if (z80_read(addr) != c)
+ break;
+ ++addr;
+ if (c == 0)
+ p = text;
+ }
+ return addr;
+}
+
+const char * const qbfox = "Zhe quick brown fox jumps over the lazy dog!";
+const char * const qbcat = "Zhe quick brown fox jumps over the lazy cat!";
+
+#endif
+
+uint8_t z80_get_byte(uint32_t adr)
+{
+ uint8_t data;
+
+ z80_request_bus();
+ data = z80_read(adr),
+ z80_release_bus();
+
+ return data;
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+static void do_10ms(void)
+{
+ for (uint_fast8_t i = 0; i < 2; i++) {
+ switch (led_stat[i].mode) {
+ case PULSE:
+ if (led_timer[i] == 0) {
+ led_off(i);
+ led_stat[i].mode = NOTHING;
+ }
+ break;
+ case BLINK1:
+ case BLINK2:
+ if (led_timer[i] == 0) {
+ if (led_is_on(i))
+ led_timer[i] = led_stat[i].offtime;
+ else
+ led_timer[i] = led_stat[i].ontime;
+ led_toggle(i);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+struct msg_item {
+ uint8_t fct;
+ uint8_t sub_min, sub_max;
+ void (*func)(uint8_t, int, uint8_t *);
+};
+
+uint32_t msg_to_addr(uint8_t *msg)
+{
+ uint32_t addr = msg[0] | (msg[1] << 8) | ((uint32_t)msg[2] << 16);
+
+ return addr;
+
+}
+
+void do_msg_ini_msgfifo(uint8_t subf, int len, uint8_t * msg)
+{
+ (void)subf; (void)len;
+
+ z80_init_msg_fifo(msg_to_addr(msg));
+}
+
+
+void do_msg_ini_memfifo(uint8_t subf, int len, uint8_t * msg)
+{
+ (void)len;
+
+ z80_memfifo_init(subf - 1, msg_to_addr(msg));
+}
+
+
+void do_msg_char_out(uint8_t subf, int len, uint8_t * msg)
+{
+ (void)subf;
+
+ while (len--)
+ putchar(*msg++);
+}
+
+
+const struct msg_item z80_messages[] =
+{
+ { 0, /* fct nr. */
+ 0, 0, /* sub fct nr. from, to */
+ &do_msg_ini_msgfifo},
+ { 0,
+ 1, 2,
+ &do_msg_ini_memfifo},
+ { 1,
+ 1, 1,
+ &do_msg_char_out},
+ { 0xff, /* end mark */
+ 0, 0,
+ 0},
+
+};
+
+
+
+
+void do_message(int len, uint8_t *msg)
+{
+ uint8_t fct, sub_fct;
+ int_fast8_t i = 0;
+
+ if (len >= 2) {
+ fct = *msg++;
+ sub_fct = *msg++;
+ len -= 2;
+
+ while (fct != z80_messages[i].fct)
+ ++i;
+
+ if (z80_messages[i].fct == 0xff) {
+ DBG_P(1, "do_message: Unknown function: %i, %i\n",
+ fct, sub_fct);
+ return; /* TODO: unknown message # */
+ }
+
+ while (fct == z80_messages[i].fct) {
+ if (sub_fct >= z80_messages[i].sub_min && sub_fct <= z80_messages[i].sub_max )
+ break;
+ ++i;
+ }
+
+ if (z80_messages[i].fct != fct) {
+ DBG_P(1, "do_message: Unknown sub function: %i, %i\n",
+ fct, sub_fct);
+ return; /* TODO: unknown message sub# */
+ }
+
+ (z80_messages[i].func)(sub_fct, len, msg);
+
+
+ } else {
+ /* TODO: error */
+ DBG_P(1, "do_message: to few arguments (%i); this shouldn't happen!\n", len);
+ }
+}
+
+
+
+#define CTRBUF_LEN 256
+
+void check_msg_fifo(void)
+{
+ int ch;
+ static int_fast8_t state;
+ static int msglen,idx;
+ static uint8_t buffer[CTRBUF_LEN];
+
+ while (state != 3 && (ch = z80_msg_fifo_getc()) >= 0) {
+ switch (state) {
+ case 0: /* wait for start of message */
+ if (ch == 0x81) {
+ msglen = 0;
+ idx = 0;
+ state = 1;
+ }
+ break;
+ case 1: /* get msg len */
+ if (ch > 0 && ch <= CTRBUF_LEN) {
+ msglen = ch;
+ state = 2;
+ } else
+ state = 0;
+ break;
+ case 2: /* get message */
+ buffer[idx++] = ch;
+ if (idx == msglen)
+ state = 3;
+ break;
+ }
+ }
+
+ if (state == 3) {
+ do_message(msglen, buffer);
+ state = 0;
+ }
+}
+
+
+void z80_load_mem(void)
+{
+ unsigned sec = 0;
+ uint32_t sec_base = hdrom_start;
+
+ DBG_P(1, "Loading z80 memory... \n");
+
+ while (sec < hdrom_sections) {
+ DBG_P(2, " From: 0x%.5lX to: 0x%.5lX (%5li bytes)\n",
+ hdrom_address[sec],
+ hdrom_address[sec]+hdrom_length_of_sections[sec] - 1,
+ hdrom_length_of_sections[sec]);
+
+ z80_write_block((unsigned char *) &hdrom[sec_base], /* src */
+ hdrom_address[sec], /* dest */
+ hdrom_length_of_sections[sec]); /* len */
+ sec_base+=hdrom_length_of_sections[sec];
+ sec++;
+ }
+}
+/*--------------------------------------------------------------------------*/
+
+int main(void)
+{
+ int_fast8_t state = 0;
+ int ch;
+
+ clock_setup();
+ gpio_setup();
+ tim3_setup();
+ setvbuf(stdout, NULL, _IONBF, 0);
+ serial_setup();
+ printf("\n(STM32F100+HD64180)_stamp Tester\n");
+
+ DBG_P(1, "z80_setup_bus... ");
+ z80_setup_msg_fifo();
+ z80_setup_bus();
+ DBG_P(1, "done.\n");
+
+ /*
+ * If the RTC is pre-configured just allow access, don't reconfigure.
+ * Otherwise enable it with the LSE as clock source and 0x7fff as
+ * prescale value.
+ */
+ rtc_auto_awake(LSE, 0x7fff);
+
+ systick_setup();
+
+ DBG_P(1, "Get bus... ");
+ z80_busreq(LOW);
+ z80_reset(HIGH);
+ z80_request_bus();
+ DBG_P(1, "got it!\n");
+
+ z80_memset(0, 0x76, 0x80000);
+ //z80_sram_fill(0, 512 * 1024, 0x76, 0);
+ z80_sram_cmp(0, (uint32_t)512 * 1024, 0x76, 0);
+
+ z80_load_mem();
+ z80_reset(LOW);
+ DBG_P(1, "Bus released!\n");
+ z80_release_bus();
+ z80_reset(HIGH);
+ DBG_P(1, "Reset released!\n");
+
+
+ ledset(0, BLINK1, 50);
+
+ while (1) {
+
+ if (Stat & S_10MS_TO) {
+ Stat &= ~S_10MS_TO;
+ do_10ms();
+ }
+
+ if (get_key_short(KEY0)) {
+ z80_reset_pulse();
+ }
+
+ if ((ch = serial_getc()) >= 0) {
+ switch (state) {
+ case 0:
+ if (ch == ESCCHAR) {
+ state = 1;
+ /* TODO: Timer starten */
+ } else
+ z80_memfifo_putc(fifo_out, ch);
+ break;
+ case 1:
+ switch (ch) {
+
+ case 'h': /* test: green led on */
+ tim3_set(-1);
+ break;
+ case 'l': /* test: green led off */
+ tim3_set(0);
+ break;
+ case 'p': /* test: pulse on led pin */
+ tim3_set(24000000 / 1000000 * 5); /* 5 us */
+ break;
+ case 'r':
+ z80_reset_pulse();
+ break;
+
+ case ESCCHAR:
+ default:
+ z80_memfifo_putc(fifo_out, ch);
+ }
+ state = 0;
+ break;
+ }
+ }
+
+ check_msg_fifo();
+ }
+
+ return 0;
+}
--- /dev/null
+/**
+ *
+ * Pin assignments
+ *
+ * | Z180-Sig | STM32-Port |Buffer | Dir | Special Function |
+ * +------------+---------------+-------+-------+-----------------------+
+ * | A0 | A 1 | P | O | |
+ * | A1 | A 2 | P | O | |
+ * | A2 | A 3 | P | O | |
+ * | A3 | A 4 | P | O | |
+ * | A4 | A 5 | P | O | |
+ * | A5 | A 6 | P | O | |
+ * | A6 | A 7 | P | O | |
+ * | A7 | A 8 | | O | |
+ * | A8 | C 0 | P | O | |
+ * | A9 | C 1 | P | O | |
+ * | A10 | C 2 | P | O | |
+ * | A11 | C 3 | P | O | |
+ * | A12 | C 4 | P | O | |
+ * | A13 | C 5 | P | O | |
+ * | A14 | C 6 | | O | |
+ * | A15 | C 7 | | O | |
+ * | A16 | C 10 | | O | |
+ * | A17 | C 11 | | O | |
+ * | A18 | C 12 | | O | |
+ * | D0 | B 8 | | I/O | |
+ * | D1 | B 9 | | I/O | |
+ * | D2 | B 10 | | I/O | |
+ * | D3 | B 11 | | I/O | |
+ * | D4 | B 12 | | I/O | |
+ * | D5 | B 13 | | I/O | |
+ * | D6 | B 14 | | I/O | |
+ * | D7 | B 15 | | I/O | |
+ * | ME | C 13 | P | O | |
+ * | RD | B 0 | P | O | |
+ * | WR | B 1 | P | O | |
+ * | BUSREQ | D 2 | | O | |
+ * | IOCS1 | A 11 | | I | TIM1_CH4 |
+ * | BUSACK | A 12 | | I | |
+ * | HALT | A 12 | | I | |
+ * | NMI | B 7 | | O | |
+ * | RST | B 6 | | O | TIM16_CH1N |
+ * | | | | | |
+ * | | A 9 | | | af1 USART1_TX |
+ * | | A 10 | | | af1 USART1_RX |
+ * | | A 15 | | JTDI | remap SPI1_NSS' |
+ * | | B 3 | | JTDO | remap SPI1_SCK' |
+ * | | B 4 | |NJTRST | remap SPI1_MISO' |
+ * | | B 5 | | | remap SPI1_MOSI' |
+ * | | C 14 | | | af1 OSC32 |
+ * | | C 15 | | | af1 OSC32 |
+
+
+AFIO_MAPR2 =
+AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON (frees
+AFIO_MAPR_SPI1_REMAP
+
+ */
+
+/**
+ *
+ * Pin assignments
+ *
+ * | Z180-Sig | STM32-Port | Buffer | Dir |Special Function |
+ * | -------- | ---------- | ------ | --- | --------------- |
+ * | A0 |A 1 |P |O | |
+ * | A1 |A 2 |P |O | |
+ * | A2 |A 3 |P |O | |
+ * | A3 |A 4 |P |O | |
+ * | A4 |A 5 |P |O | |
+ * | A5 |A 6 |P |O | |
+ * | A6 |A 7 |P |O | |
+ * | A7 |A 8 | |O | |
+ * | A8 |C 0 |P |O | |
+ * | A9 |C 1 |P |O | |
+ * | A10 |C 2 |P |O | |
+ * | A11 |C 3 |P |O | |
+ * | A12 |C 4 |P |O | |
+ * | A13 |C 5 |P |O | |
+ * | A14 |C 6 | |O | |
+ * | A15 |C 7 | |O | |
+ * | A16 |C 10 | |O | |
+ * | A17 |C 11 | |O | |
+ * | A18 |C 12 | |O | |
+ * | D0 |B 8 | |I/O | |
+ * | D1 |B 9 | |I/O | |
+ * | D2 |B 10 | |I/O | |
+ * | D3 |B 11 | |I/O | |
+ * | D4 |B 12 | |I/O | |
+ * | D5 |B 13 | |I/O | |
+ * | D6 |B 14 | |I/O | |
+ * | D7 |B 15 | |I/O | |
+ * | ME |C 13 |P |O | |
+ * | RD |B 0 |P |O | |
+ * | WR |B 1 |P |O | |
+ * | BUSREQ |D 2 | |O | |
+ * | IOCS1 |A 11 | |I |TIM1_CH4 |
+ * | BUSACK |A 12 | |I | |
+ * | HALT |A 12 | |I | |
+ * | NMI |B 7 | |O | |
+ * | RST |B 6 | |O |TIM16_CH1N |
+ * | | | | | |
+ * | |A 9 | | |af1 USART1_TX |
+ * | |A 10 | | |af1 USART1_RX |
+ * | |A 15 | |JTDI | remap SPI1_NSS' |
+ * | |B 3 | |JTDO |remap SPI1_SCK' |
+ * | |B 4 | |NJTRST |remap SPI1_MISO' |
+ * | |B 5 | | |remap SPI1_MOSI' |
+ * | |C 14 | | |af1 OSC32 |
+ * | |C 15 | | |af1 OSC32 |
+
+
+AFIO_MAPR2 =
+AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON (frees
+AFIO_MAPR_SPI1_REMAP
+
+ */
+
+#include <stdio.h>
+
+
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/rcc.h>
+#include <libopencm3/stm32/timer.h>
+#include <libopencm3/stm32/dma.h>
+#include "debug.h"
+#include "z80-if.h"
+
+
+/* Number of array elements */
+#define NELEMS(x) (sizeof x/sizeof *x)
+
+#define ODR 0x0c
+#define IDR 0x08
+
+#define CONCAT(x,y) x ## y
+#define EVALUATOR(x,y) CONCAT(x,y)
+
+#define GPIO_(X) CONCAT(GPIO, X)
+
+
+
+
+#define P_ME GPIOC
+#define ME 13
+#define P_RD GPIOB
+#define RD 0
+#define P_WR GPIOB
+#define WR 1
+#define P_BUSREQ GPIOD
+#define BUSREQ 2
+#define P_BUSACK GPIOA
+#define BUSACK 12
+//#define P_HALT GPIOA
+//#define HALT 12
+#define P_IOCS1 GPIOA
+#define IOCS1 11
+#define P_NMI GPIOB
+#define NMI 7
+#define P_RST GPIOB
+#define RST 6
+
+#define ADp1_OFS 0
+#define ADp1_WIDTH 8
+#define ADp1_SHIFT 1
+#define ADp1_PORT GPIOA
+
+#define ADp2_OFS ADp1_WIDTH
+#define ADp2_WIDTH 8
+#define ADp2_SHIFT 0
+#define ADp2_PORT GPIOC
+
+#define ADp3_OFS (ADp2_OFS+ADp2_WIDTH)
+#define ADp3_WIDTH 3
+#define ADp3_SHIFT 10
+#define ADp3_PORT GPIOC
+
+#define ADunbuff1_WIDTH 1
+#define ADunbuff1_SHIFT 8
+#define ADunbuff1_PORT GPIOA
+
+#define ADunbuff2_WIDTH 2
+#define ADunbuff2_SHIFT 6
+#define ADunbuff2_PORT GPIOC
+
+#define ADunbuff3_WIDTH 3
+#define ADunbuff3_SHIFT 10
+#define ADunbuff3_PORT GPIOC
+
+#define DB_OFS 0
+#define DB_WIDTH 8
+#define DB_SHIFT 8
+#define DB_PORT GPIOB
+
+#define GPIO_ME GPIO_(ME)
+#define GPIO_RD GPIO_(RD)
+#define GPIO_WR GPIO_(WR)
+#define GPIO_BUSREQ GPIO_(BUSREQ)
+#define GPIO_BUSACK GPIO_(BUSACK)
+//#define GPIO_HALT GPIO_(HALT)
+#define GPIO_IOCS1 GPIO_(IOCS1)
+#define GPIO_NMI GPIO_(NMI)
+#define GPIO_RST GPIO_(RST)
+
+#define Z80_O_ME BBIO_PERIPH(P_ME+ODR, ME)
+#define Z80_O_RD BBIO_PERIPH(P_RD+ODR, RD)
+#define Z80_O_WR BBIO_PERIPH(P_WR+ODR, WR)
+#define Z80_O_BUSREQ BBIO_PERIPH(P_BUSREQ+ODR, BUSREQ)
+#define Z80_O_NMI BBIO_PERIPH(P_NMI+ODR, NMI)
+#define Z80_O_RST BBIO_PERIPH(P_RST+ODR, RST)
+
+#define Z80_I_BUSACK BBIO_PERIPH(P_BUSACK+IDR, BUSACK)
+//#define Z80_I_HALT BBIO_PERIPH(P_HALT+IDR, HALT)
+
+
+#define MASK(n) ((1<<n)-1)
+
+#define IOFIELD_SET(src, ofs, width, shift) \
+ ((((src>>ofs) & MASK(width)) << shift) | ((((~src>>ofs) & MASK(width)) << shift) << 16))
+
+#define IOFIELD_GET(src, width, shift) \
+ ((src>>shift) & MASK(width))
+
+#define CNF_MODE_I_F (GPIO_CNF_INPUT_FLOAT<<2 |GPIO_MODE_INPUT)
+#define CNF_MODE_O_PP (GPIO_CNF_OUTPUT_PUSHPULL<<2 | GPIO_MODE_OUTPUT_10_MHZ)
+
+#define DB_MODE_INPUT ( (CNF_MODE_I_F << (4 * 0)) \
+ | (CNF_MODE_I_F << (4 * 1)) \
+ | (CNF_MODE_I_F << (4 * 2)) \
+ | (CNF_MODE_I_F << (4 * 3)) \
+ | (CNF_MODE_I_F << (4 * 4)) \
+ | (CNF_MODE_I_F << (4 * 5)) \
+ | (CNF_MODE_I_F << (4 * 6)) \
+ | (CNF_MODE_I_F << (4 * 7)))
+
+#define DB_MODE_OUTPUT ( (CNF_MODE_O_PP << (4 * 0)) \
+ | (CNF_MODE_O_PP << (4 * 1)) \
+ | (CNF_MODE_O_PP << (4 * 2)) \
+ | (CNF_MODE_O_PP << (4 * 3)) \
+ | (CNF_MODE_O_PP << (4 * 4)) \
+ | (CNF_MODE_O_PP << (4 * 5)) \
+ | (CNF_MODE_O_PP << (4 * 6)) \
+ | (CNF_MODE_O_PP << (4 * 7)))
+
+
+/*--------------------------------------------------------------------------*/
+
+static void tim16_setup(void)
+{
+ RCC_APB2RSTR |= RCC_APB2RSTR_TIM16RST;
+ RCC_APB2RSTR &= ~RCC_APB2RSTR_TIM16RST;
+
+ TIM16_BDTR = TIM_BDTR_MOE;
+
+ TIM16_CCMR1 = 0
+ | TIM_CCMR1_OC1M_FORCE_LOW
+ | TIM_CCMR1_CC1S_OUT;
+
+ TIM16_CCER = TIM_CCER_CC1NE
+ | TIM_CCER_CC1NP;
+
+ TIM16_ARR = 48; /* default */
+ TIM16_CCR1 = 1; /* */
+}
+
+/*--------------------------------------------------------------------------*/
+
+static void tim16_set(int mode)
+{
+ uint16_t cc_mode;
+
+ cc_mode = TIM_CCMR1_CC1S_OUT;
+
+ TIM16_CR1 = TIM_CR1_OPM;
+
+ if (mode < 0)
+ cc_mode |= TIM_CCMR1_OC1M_FORCE_LOW;
+ else if (mode == 0)
+ cc_mode |= TIM_CCMR1_OC1M_FORCE_HIGH;
+ else {
+ TIM16_ARR = mode;
+ cc_mode |= TIM_CCMR1_OC1M_PWM2;
+ }
+
+ TIM16_CCMR1 = cc_mode;
+
+ if (mode > 0)
+ TIM16_CR1 |= TIM_CR1_CEN;
+}
+
+/*--------------------------------------------------------------------------*/
+
+
+
+/*
+ * A0..A6, A8..A13 are buffered. No need to disable.
+ * A7, A14..A18: set to input.
+ */
+
+static void z80_setup_adrbus_tristate(void)
+{
+#if 0
+ gpio_set_mode(ADunbuff1_PORT, GPIO_MODE_INPUT,
+ GPIO_CNF_INPUT_FLOAT, MASK(ADunbuff1_WIDTH) << ADunbuff1_SHIFT);
+ gpio_set_mode(ADunbuff2_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT,
+ (MASK(ADunbuff2_WIDTH) << ADunbuff2_SHIFT) | (MASK(ADunbuff3_WIDTH) << ADunbuff3_SHIFT));
+#else
+ GPIO_CRH(GPIOA) = (GPIO_CRH(GPIOA) & ~(0x0f << (4 * 0)))
+ | (CNF_MODE_I_F << (4 * 0));
+ GPIO_CRL(GPIOC) = (GPIO_CRL(GPIOC) & ~((0x0f << (4 * 6)) | (0x0f << (4 * 7))))
+ | ((CNF_MODE_I_F << (4 * 6)) | (CNF_MODE_I_F << (4 * 7)));
+ GPIO_CRH(GPIOC) = (GPIO_CRH(GPIOC) & ~((0x0f << (4*2)) | (0x0f << (4*3)) | (0x0f << (4*4))))
+ | ((CNF_MODE_I_F << (4*2)) | (CNF_MODE_I_F << (4*3)) | (CNF_MODE_I_F << (4*4)));
+#endif
+}
+
+
+static void z80_setup_adrbus_active(void)
+{
+#if 0
+ gpio_set_mode(ADunbuff1_PORT, GPIO_MODE_OUTPUT_10_MHZ,
+ GPIO_CNF_OUTPUT_PUSHPULL, MASK(ADunbuff1_WIDTH) << ADunbuff1_SHIFT);
+ gpio_set_mode(ADunbuff2_PORT, GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSHPULL,
+ (MASK(ADunbuff2_WIDTH) << ADunbuff2_SHIFT) | (MASK(ADunbuff3_WIDTH) << ADunbuff3_SHIFT));
+#else
+ GPIO_CRH(GPIOA) = (GPIO_CRH(GPIOA) & ~(0x0f << (4 * 0)))
+ | (CNF_MODE_O_PP << (4 * 0));
+ GPIO_CRL(GPIOC) = (GPIO_CRL(GPIOC) & ~((0x0f << (4 * 6)) | (0x0f << (4 * 7))))
+ | ((CNF_MODE_O_PP << (4 * 6)) | (CNF_MODE_O_PP << (4 * 7)));
+ GPIO_CRH(GPIOC) = (GPIO_CRH(GPIOC) & ~((0x0f << (4*2)) | (0x0f << (4*3)) | (0x0f << (4*4))))
+ | ((CNF_MODE_O_PP << (4*2)) | (CNF_MODE_O_PP << (4*3)) | (CNF_MODE_O_PP << (4*4)));
+#endif
+}
+
+
+static void z80_setup_dbus_in(void)
+{
+ GPIO_CRH(DB_PORT) = DB_MODE_INPUT;
+}
+
+static void z80_setup_dbus_out(void)
+{
+ GPIO_CRH(DB_PORT) = DB_MODE_OUTPUT;
+}
+
+
+static void z80_setaddress(uint32_t addr)
+{
+ GPIO_BSRR(ADp1_PORT) = IOFIELD_SET(addr, ADp1_OFS, ADp1_WIDTH, ADp1_SHIFT);
+ GPIO_BSRR(ADp2_PORT) = IOFIELD_SET(addr, ADp2_OFS, ADp2_WIDTH, ADp2_SHIFT);
+ GPIO_BSRR(ADp3_PORT) = IOFIELD_SET(addr, ADp3_OFS, ADp3_WIDTH, ADp3_SHIFT);
+}
+
+void z80_setup_bus(void)
+{
+ tim16_setup();
+
+ gpio_set_mode(P_RST, GPIO_MODE_OUTPUT_10_MHZ,
+ GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_RST);
+ Z80_O_BUSREQ = 1;
+ gpio_set_mode(P_BUSREQ, GPIO_MODE_OUTPUT_10_MHZ,
+ GPIO_CNF_OUTPUT_PUSHPULL, GPIO_BUSREQ);
+ Z80_O_NMI = 1;
+ gpio_set_mode(P_NMI, GPIO_MODE_OUTPUT_10_MHZ,
+ GPIO_CNF_OUTPUT_PUSHPULL, GPIO_NMI);
+ Z80_O_ME = 1;
+ Z80_O_RD = 1;
+ Z80_O_WR = 1;
+ gpio_set_mode(P_ME, GPIO_MODE_OUTPUT_2_MHZ,
+ GPIO_CNF_OUTPUT_PUSHPULL, GPIO_ME);
+ gpio_set_mode(P_RD, GPIO_MODE_OUTPUT_10_MHZ,
+ GPIO_CNF_OUTPUT_PUSHPULL, GPIO_RD | GPIO_WR);
+
+ //Z80_O_BUSREQ = 0;
+ //while(Z80_I_BUSACK == 1);
+
+ gpio_set_mode(ADp1_PORT, GPIO_MODE_OUTPUT_10_MHZ,
+ GPIO_CNF_OUTPUT_PUSHPULL, MASK(ADp1_WIDTH) << ADp1_SHIFT);
+ gpio_set_mode(ADp2_PORT, GPIO_MODE_OUTPUT_10_MHZ,
+ GPIO_CNF_OUTPUT_PUSHPULL, MASK(ADp2_WIDTH) << ADp2_SHIFT);
+ gpio_set_mode(ADp3_PORT, GPIO_MODE_OUTPUT_10_MHZ,
+ GPIO_CNF_OUTPUT_PUSHPULL, MASK(ADp3_WIDTH) << ADp3_SHIFT);
+
+ z80_setup_dbus_in();
+}
+
+void z80_request_bus(void)
+{
+ Z80_O_BUSREQ = 0;
+ while(Z80_I_BUSACK == 1);
+ z80_setup_adrbus_active();
+}
+
+void z80_release_bus(void)
+{
+ z80_setup_dbus_in();
+ z80_setup_adrbus_tristate();
+ Z80_O_BUSREQ = 1;
+ while(Z80_I_BUSACK == 0);
+}
+
+void z80_reset(level_t level)
+{
+ int x = level ? -1 : 0;
+
+ tim16_set(x);
+
+// Z80_O_RST = level;
+}
+
+void z80_reset_pulse(void)
+{
+ tim16_set(48);
+}
+
+void z80_busreq(level_t level)
+{
+ Z80_O_BUSREQ = level;
+}
+
+#if 0
+int z80_stat_halt(void)
+{
+ return Z80_I_HALT;
+}
+#endif
+
+void z80_write(uint32_t addr, uint8_t data)
+{
+ z80_setaddress(addr);
+ Z80_O_ME = 0;
+ GPIO_BSRR(DB_PORT) = IOFIELD_SET(data, DB_OFS, DB_WIDTH, DB_SHIFT);
+ z80_setup_dbus_out();
+ Z80_O_WR = 0;
+ Z80_O_WR = 1;
+ Z80_O_ME = 1;
+}
+
+uint8_t z80_read(uint32_t addr)
+{
+ uint8_t data;
+
+ z80_setaddress(addr);
+ Z80_O_ME = 0;
+ z80_setup_dbus_in();
+ Z80_O_RD = 0;
+ Z80_O_RD = 0;
+ data = IOFIELD_GET(GPIO_IDR(DB_PORT),DB_WIDTH, DB_SHIFT);
+ Z80_O_RD = 1;
+ Z80_O_ME = 1;
+
+ return data;
+}
+
+
+void z80_memset(uint32_t addr, uint8_t data, int length)
+{
+ z80_setup_dbus_out();
+ Z80_O_ME = 0;
+ while(length--) {
+ z80_setaddress(addr++);
+ GPIO_BSRR(DB_PORT) = IOFIELD_SET(data, DB_OFS, DB_WIDTH, DB_SHIFT);
+ Z80_O_WR = 0;
+ Z80_O_WR = 1;
+ }
+ Z80_O_ME = 1;
+}
+
+void z80_write_block(uint8_t *src, uint32_t dest, uint32_t length)
+{
+ uint8_t data;
+
+ z80_setup_dbus_out();
+ Z80_O_ME = 0;
+ while(length--) {
+ z80_setaddress(dest++);
+ data = *src++;
+ GPIO_BSRR(DB_PORT) = IOFIELD_SET(data, DB_OFS, DB_WIDTH, DB_SHIFT);
+ Z80_O_WR = 0;
+ Z80_O_WR = 1;
+ }
+ Z80_O_ME = 1;
+}
+
+/*
+ 0179' rx.bs_mask: ds 1 ; (buf_len - 1)
+ 017A' rx.in_idx: ds 1 ;
+ 017B' rx.out_idx: ds 1 ;
+ 017C' rx.buf: ds rx.buf_len ;
+ 018B' rx.buf_end equ $-1 ; last byte (start+len-1)
+
+ 018C' tx.bs_mask: ds 1 ; (buf_len - 1)
+ 018D' tx.in_idx: ds 1 ;
+ 018E' tx.out_idx: ds 1 ;
+ 018F' tx.buf: ds tx.buf_len ;
+ 019E' tx.buf_end equ $-1 ; last byte
+*/
+
+
+typedef struct __attribute__((packed)) {
+ uint8_t mask;
+ uint8_t in_idx;
+ uint8_t out_idx;
+ uint8_t buf[];
+} zfifo_t;
+
+
+
+#define FIFO_BUFSIZE_MASK -3
+#define FIFO_INDEX_IN -2
+#define FIFO_INDEX_OUT -1
+
+
+static struct {
+ uint32_t base;
+ uint8_t idx_out,
+ idx_in,
+ mask;
+ } fifo_dsc[NUM_FIFOS];
+
+
+void z80_memfifo_init(const fifo_t f, uint32_t adr)
+{
+
+DBG_P(2, "z80_memfifo_init: %i, %lx\n", f, adr);
+
+ fifo_dsc[f].base = adr;
+
+ z80_request_bus();
+
+ fifo_dsc[f].mask = z80_read(adr + FIFO_BUFSIZE_MASK);
+ fifo_dsc[f].idx_in = z80_read(adr + FIFO_INDEX_IN);
+ fifo_dsc[f].idx_out = z80_read(adr + FIFO_INDEX_OUT);
+
+ z80_release_bus();
+}
+
+
+int z80_memfifo_is_empty(const fifo_t f)
+{
+ int rc = 1;
+
+ if (fifo_dsc[f].base != 0) {
+
+ uint32_t adr = fifo_dsc[f].base + FIFO_INDEX_IN;
+ uint8_t idx;
+
+ z80_request_bus();
+ idx = z80_read(adr);
+ z80_release_bus();
+ rc = idx == fifo_dsc[f].idx_out;
+ }
+
+ return rc;
+}
+
+int z80_memfifo_is_full(const fifo_t f)
+{
+ int rc = 1;
+
+ if (fifo_dsc[f].base != 0) {
+ z80_request_bus();
+ rc = ((fifo_dsc[f].idx_in + 1) & fifo_dsc[f].mask)
+ == z80_read(fifo_dsc[f].base+FIFO_INDEX_OUT);
+ z80_release_bus();
+ }
+ return rc;
+}
+
+uint8_t z80_memfifo_getc(const fifo_t f)
+{
+ uint8_t rc, idx;
+
+ while (z80_memfifo_is_empty(f))
+ ;
+
+ z80_request_bus();
+ idx = fifo_dsc[f].idx_out;
+ rc = z80_read(fifo_dsc[f].base+idx);
+ fifo_dsc[f].idx_out = ++idx & fifo_dsc[f].mask;
+ z80_write(fifo_dsc[f].base+FIFO_INDEX_OUT, fifo_dsc[f].idx_out);
+ z80_release_bus();
+
+ return rc;
+}
+
+
+void z80_memfifo_putc(fifo_t f, uint8_t val)
+{
+ int idx;
+
+ while (z80_memfifo_is_full(f))
+ ;
+
+ z80_request_bus();
+ idx = fifo_dsc[f].idx_in;
+ z80_write(fifo_dsc[f].base+idx, val);
+ fifo_dsc[f].idx_in = ++idx & fifo_dsc[f].mask;
+ z80_write(fifo_dsc[f].base+FIFO_INDEX_IN, fifo_dsc[f].idx_in);
+ z80_release_bus();
+}
+
+/*--------------------------------------------------------------------------*/
+
+static struct {
+ uint32_t base;
+ //uint8_t idx_out, idx_in;
+ uint16_t count;
+ uint8_t buf[256];
+ } msg_fifo;
+
+/*--------------------------------------------------------------------------*/
+
+#if 0
+
+static void tim1_setup(void)
+{
+ RCC_APB2RSTR |= RCC_APB2RSTR_TIM1RST;
+ RCC_APB2RSTR &= ~RCC_APB2RSTR_TIM1RST;
+
+ TIM1_CR1 = 0;
+
+ TIM1_SMCR = 0
+ /* | TIM_SMCR_ETP */
+ /* | TIM_SMCR_ETF_CK_INT_N_2 */
+ | TIM_SMCR_TS_ETRF
+ | TIM_SMCR_SMS_OFF
+ ;
+
+ TIM1_DIER = TIM_DIER_TDE;
+
+
+ TIM1_CCMR1 = 0
+ | TIM_CCMR1_OC1M_FORCE_LOW
+ | TIM_CCMR1_CC1S_OUT;
+
+ TIM1_SMCR |= TIM_SMCR_SMS_TM;
+}
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+static void tim1_ch4_setup(void)
+{
+ /* Reset Timer 1 */
+ RCC_APB2RSTR |= RCC_APB2RSTR_TIM1RST;
+ RCC_APB2RSTR &= ~RCC_APB2RSTR_TIM1RST;
+
+ TIM1_CCMR2 = 0
+ | TIM_CCMR2_CC4S_IN_TI2
+ | TIM_CCMR2_IC4F_OFF
+ | TIM_CCMR2_IC4PSC_OFF;
+
+ TIM1_CCER = 0
+ /* | TIM_CCER_CC4P */
+ | TIM_CCER_CC4E;
+
+ /* Enable DMA for channel 4 */
+ TIM1_DIER = TIM_DIER_CC4DE;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static void dma1_ch4_setup(void)
+{
+ DMA1_CCR4 =
+ DMA_CCR_PL_VERY_HIGH
+ | DMA_CCR_MSIZE_8BIT
+ | DMA_CCR_PSIZE_8BIT
+ | DMA_CCR_MINC
+ | DMA_CCR_CIRC;
+
+ DMA1_CMAR4 = (uint32_t) msg_fifo.buf;
+
+#if (DB_SHIFT == 0) || (DB_SHIFT == 8)
+ DMA1_CPAR4 = DB_PORT + IDR + DB_SHIFT/8;
+#else
+ #error "Databus not byte aligned!"
+#endif
+
+ DMA1_CNDTR4 = NELEMS(msg_fifo.buf);
+// msg_fifo.count = NELEMS(msg_fifo.buf);
+ msg_fifo.count = 0;
+ msg_fifo.base = 0;
+
+ DMA1_CCR4 |= DMA_CCR_EN;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void z80_setup_msg_fifo(void)
+{
+ gpio_set_mode(P_BUSACK, GPIO_MODE_INPUT,
+ GPIO_CNF_INPUT_FLOAT, GPIO_BUSACK | GPIO_IOCS1);
+
+ tim1_ch4_setup();
+ dma1_ch4_setup();
+}
+
+
+void z80_init_msg_fifo(uint32_t addr)
+{
+
+DBG_P(1, "z80_init_msg_fifo: %lx\n", addr);
+
+ z80_request_bus();
+ z80_write(addr+FIFO_INDEX_OUT, z80_read(addr+FIFO_INDEX_IN));
+ z80_release_bus();
+ msg_fifo.base = addr;
+}
+
+
+int z80_msg_fifo_getc(void)
+{
+ int c = -1;
+
+ if (msg_fifo.count != (NELEMS(msg_fifo.buf) - DMA1_CNDTR4)) {
+ c = msg_fifo.buf[msg_fifo.count];
+ if (++msg_fifo.count == NELEMS(msg_fifo.buf))
+ msg_fifo.count = 0;
+
+ if (msg_fifo.base != 0) {
+ z80_request_bus();
+ z80_write(msg_fifo.base+FIFO_INDEX_OUT, msg_fifo.count);
+ z80_release_bus();
+ }
+ }
+
+ return c;
+}
--- /dev/null
+
+typedef enum {LOW, HIGH} level_t;
+
+//static void z80_setup_adrbus_tristate(void);
+//static void z80_setup_adrbus_active(void);
+//static void z80_setup_dbus_in(void);
+//static void z80_setup_dbus_out(void);
+//static void z80_setaddress(uint32_t addr);
+void z80_setup_bus(void);
+void z80_write(uint32_t addr, uint8_t data);
+uint8_t z80_read(uint32_t addr);
+void z80_request_bus(void);
+void z80_release_bus(void);
+void z80_memset(uint32_t addr, uint8_t data, int length);
+void z80_reset(level_t level);
+void z80_reset_pulse(void);
+void z80_busreq(level_t level);
+void z80_write_block(uint8_t *src, uint32_t dest, uint32_t length);
+int z80_stat_halt(void);
+
+
+typedef enum fifo_t {fifo_in, fifo_out, NUM_FIFOS} fifo_t;
+
+void z80_memfifo_init(const fifo_t f, uint32_t adr);
+int z80_memfifo_is_empty(const fifo_t f);
+int z80_memfifo_is_full(const fifo_t f);
+uint8_t z80_memfifo_getc(const fifo_t f);
+void z80_memfifo_putc(fifo_t f, uint8_t val);
+
+void z80_setup_msg_fifo(void);
+void z80_init_msg_fifo(uint32_t addr);
+int z80_msg_fifo_getc(void);
--- /dev/null
+
+
+SRC := r3init.180 ddtz.180
+SRC += fifoio.180 msgbuf.180 ser1-i.180 console.180
+SRC += romend.180
+
+INC := config.inc z180reg.inc z180.lib
+
+OBJ := $(SRC:.180=.rel)
+
+#CP/M emulator
+CPMEMU = zxcc
+
+#Location of CP/M binaries
+CPMBIN = /usr/local/lib/cpm/bin80
+
+#AS = $(CPMEMU) $(CPMBIN)/m80.com
+AS = $(CPMEMU) slr180.com
+LN = $(CPMEMU) slrnk+.com
+#LN = $(CPMEMU) ccpline.com
+
+AS_OPT := MFS
+
+AS_QUIET = 1
+LN_QUIET = 1
+
+#LNKCMD =
+LN_VERB = /V
+LN_PROG = 0
+LN_DATA = C000
+
+
+.suffixes:
+#.suffixes: .180 .rel
+
+.phony: all
+all: hdrom.c hdrom.h
+
+$(OBJ): $(INC)
+
+hdrom.h: hdrom.c
+
+comma:= ,
+empty:=
+space:= $(empty) $(empty)
+
+ccpline = $(CPMEMU) $(1) -$(subst $(space),$(comma),$(strip $(2)))
+
+define cpm-asm =
+COMMAND="$(AS) -$(basename $<)/$(AS_OPT)"; \
+OUTPUT=$$(mktemp); echo $${COMMAND}; \
+$${COMMAND} > $${OUTPUT}; \
+grep -q '^ 0 Error(s) Detected' $${OUTPUT}; ERROR=$$? ; \
+if [ "$${ERROR}" != "0" ]; then cat $${OUTPUT}; rm -f $@; fi ; \
+exit $${ERROR}
+endef
+
+define cpm-link =
+ COMMAND="$(call ccpline, slrnk+, $(basename $@)/H/M /V \
+ /P:$(LN_PROG) /D:$(LN_DATA) $(basename $^) /E /Q)";\
+ OUTPUT=$$(mktemp); echo $${COMMAND};\
+ $${COMMAND} > $${OUTPUT};\
+ ERROR=0;\
+ cat $${OUTPUT};\
+ grep -q ' Duplicate Symbol ' $${OUTPUT} && ERROR=2; \
+ grep -q '\- Previously Defined' $${OUTPUT} && ERROR=2; \
+ [ "$${ERROR}" = "0" ] && grep -q '^ ** ' $${OUTPUT} && ERROR=1 ; \
+ [ "$${ERROR}" != "0" ] && rm -f $@; \
+ exit $${ERROR}
+endef
+
+#Use: MAKESYM Filename[.ext][/PXXXX][/DXXXX][/CXXXX]
+#egrep '^[[:xdigit:]]{4}[[:space:]]+[[:xdigit:]]{4}[[:space:]]+D.*r3init\.rel' hdrom.map
+define cpm-mksym =
+COMMAND="$(CPMEMU) makesym -$^ -/P -D"; \
+OUTPUT=$$(mktemp); echo $${COMMAND}; \
+$${COMMAND} > $${OUTPUT}; \
+grep -q '^ 0 Error(s) Detected' $${OUTPUT}; ERROR=$$? ; \
+if [ "$${ERROR}" != "0" ]; then cat $${OUTPUT}; rm -f $@; fi ; \
+exit $${ERROR}
+endef
+
+hdrom.c: hdrom.hex
+ srec_cat -o $@ -c_array $(basename $<) -C_COMpressed -include $< -Intel
+
+hdrom.hex : $(OBJ)
+ @#$(cpm-link)
+ ld80 -o $@ -ms $(@:.hex=.map) -P $(LN_PROG) -D $(LN_DATA) $^
+
+%.rel %lst: %.180
+ @$(cpm-asm)
+
+hdrom.map: hdrom.hex
+
+%.sym: hdrom.map %.lst
+ @$(cpm-mksym)
+
+.phony: clean realclean
+clean:
+ rm -f $(OBJ) $(OBJ:.rel=.lst) $(OBJ:.rel=.sym) hdrom.hex
+
+realclean: clean
+ rm -f *.prn *~ hdrom.map
+
+
+#==================================================================
+
+%.REL: %.MAC
+ @COMMAND="$(AS) =$<"; \
+ OUTPUT=$$(mktemp); echo $${COMMAND}; \
+ $${COMMAND} > $${OUTPUT}; \
+ grep -q 'No Fatal error(s).$$' $${OUTPUT}; ERROR=$$? ; \
+ if [ "$${ERROR}" != "0" ]; then cat $${OUTPUT}; rm $@; fi ; \
+ rm $${OUTPUT}; \
+ exit $${ERROR}
+
+
+%.PRN: %.MAC
+ @COMMAND="$(AS) ,$@=$<"; \
+ OUTPUT=$$(mktemp); echo $${COMMAND}; \
+ $${COMMAND} > $${OUTPUT}; \
+ grep -q 'No Fatal error(s).$$' $${OUTPUT}; ERROR=$$? ; \
+ if [ "$${ERROR}" != "0" ]; then cat $${OUTPUT}; fi ; \
+ rm $${OUTPUT}; \
+ exit $${ERROR}
+
--- /dev/null
+include_rules
+
+PROG = hdrom
+
+SRC = r3init.180
+SRC += ddtz.180
+#SRC += fifoio.180 msgbuf.180 ser1-i.180 console.180
+SRC += ser1-i.180 console.180
+SRC += romend.180
+
+
+AS_OPT = MFS
+
+LN_PROG = 0
+LN_DATA = C000
+
+
+###############################################################################
+# Executables
+
+CPMEMU = zxcc
+
+#AS = $(CPMEMU) ccpline.com
+AS = $(CPMEMU) slr180.com
+
+
+###############################################################################
+
+!AS-plain = |> $(AS) -%B/$(AS_OPT) |> %B.rel | %B.lst
+
+!AS = |> ^ $(AS) -%B/$(AS_OPT)^ set +e; OUTPUT=\$(mktemp);\
+$(AS) -%B/$(AS_OPT) > ${OUTPUT};\
+grep -q '^ 0 Error(s) Detected' ${OUTPUT}; ERROR=$?;\
+[ "${ERROR}" != "0" ] && cat ${OUTPUT};\
+[ "${ERROR}" != "0" ] && rm -f %B.rel;\
+rm -f ${OUTPUT}; exit ${ERROR} \
+|> %B.rel | %B.lst
+
+!LINK = |> ld80 -o %o -ms %O.map -P $(LN_PROG) -D $(LN_DATA) %f |> | %O.map
+
+#ifndef DEBUG
+
+: foreach $(SRC) |> !AS |> {objs}
+: {objs} |> !LINK |> $(PROG).hex
+: $(PROG).hex |> srec_cat -o %o -c_array %B -C_COMpressed -include %f -Intel |> $(PROG).c | $(PROG).h
+
+
+#COMMAND="$(AS) -%B/$(AS_OPT)"; \
+
+
+#endif
+
--- /dev/null
+\r
+\r
+FOSC equ 18432 ;Oscillator frequency [KHz]\r
+PHI equ FOSC/2 ;CPU frequency \r
+\r
+;-----------------------------------------------------\r
+; Programmable Reload Timer (PRT)\r
+\r
+PRT_PRE equ 20 ;PRT prescaler\r
+\r
+; Reload value for 10 ms Int. (0.1KHz):\r
+; tc10ms = phi/prescale/0.1KHz = phi / (prescale/10)\r
+\r
+PRT_TC10MS equ PHI / (PRT_PRE/10)\r
+\r
+;-----------------------------------------------------\r
+; MMU\r
+\r
+SYS$CBAR equ 0C8h\r
+USR$CBAR equ 0F0h\r
+\r
+\r
+BANKS equ 18 ;max nr. of banks\r
+\r
+;-----------------------------------------------------\r
+\r
+CREFSH equ 0 ;Refresh rate register (disable refresh)\r
+CWAITIO equ 3 shl IWI0 ;Max I/O Wait States, 0 Memory Wait States\r
+\r
+\r
+ROMSYS equ 0\r
+\r
+ if ROMSYS\r
+c$rom equ 0a5h\r
+ROM_EN equ 0C0h\r
+ROM_DIS equ ROMEN+1\r
+CWAITROM equ 2 shl MWI0\r
+ endif\r
+\r
+\r
+DRSTNUM equ 30h ;DDTZ Restart vector (breakpoints)\r
+\r
+\r
+msg_fb_len equ 256\r
+rx.buf_len equ 20h\r
+tx.buf_len equ 80h\r
+rx.buf_len equ 20h\r
+tx.buf_len equ 80h\r
+\r
+\r
+s1.rx_len equ 256 ;Serial 1 (ASCI1) buffers\r
+s1.tx_len equ 256 ;\r
+\r
+PMSG equ 80h\r
+\r
+;-----------------------------------------------------\r
+; Definition of (locical) top 2 memory pages \r
+\r
+sysram_start equ 0FE00h\r
+stacksize equ 80\r
+\r
+isvsw_loc equ 0FEE0h\r
+\r
+ivtab equ 0ffc0h ;int vector table\r
+iv2tab equ ivtab + 2*9\r
+\r
+\r
+\r
+;-----------------------------------------------------\r
+\r
+\r
+o.mask equ -3\r
+o.in_idx equ -2\r
+o.out_idx equ -1\r
+ \r
+ .lall\r
+\r
+mkbuf macro name,size\r
+ if ((size & (size-1)) ne 0) or (size gt 256)\r
+ .printx Error: buffer ^size must be power of 2 and in range 0..256!\r
+ name&.mask equ ;wrong size error\r
+ else\r
+ ds 3 \r
+ name:: ds size\r
+ name&.mask equ low (size-1)\r
+ if size ne 0\r
+ name&.end equ $-1\r
+ name&.len equ size\r
+ endif\r
+ endif\r
+endm\r
+\r
+;-----------------------------------------------------\r
+\r
+inidat macro \r
+ cseg\r
+??ps.a defl $ \r
+ endm\r
+\r
+inidate macro\r
+??ps.len defl $ - ??ps.a\r
+ dseg\r
+ ds ??ps.len\r
+ endm\r
+\r
--- /dev/null
+ ;page 255\r
+ .z80\r
+ \r
+\r
+ global $coninit\r
+ global $cists,$ci\r
+ global $co\r
+\r
+\r
+ extrn ser.init,ser.instat,ser.in,ser.out\r
+; extrn f.init,f.in,f.out,f.i.st\r
+; extrn msg.co\r
+ \r
+\r
+ include config.inc\r
+ include z180reg.inc\r
+\r
+ cseg\r
+;\r
+;\r
+\r
+$coninit:\r
+; call f.init\r
+ call ser.init\r
+ ret\r
+ \r
+$cists:\r
+; call f.i.st\r
+; ret nz\r
+ call ser.instat\r
+ ret\r
+ \r
+$ci:\r
+; call f.i.st\r
+; jp nz,f.in\r
+ call ser.instat\r
+ jp nz,ser.in\r
+ jr $ci\r
+ \r
+;$costs:\r
+; jp f.o.st\r
+ \r
+$co:\r
+; call msg.co\r
+ jp ser.out\r
+ \r
+ end\r
+\r
--- /dev/null
+ page 255\r
+ .z80\r
+\r
+ external $ci, $co, $cists\r
+\r
+ global ddtz,bpent\r
+ global $stack\r
+\r
+\r
+ include config.inc\r
+ include z180reg.inc\r
+ include z180.lib\r
+\r
+BS equ 08h\r
+TAB equ 09h\r
+CR equ 0dh\r
+LF equ 0ah\r
+DEL equ 7fh\r
+CNTRX equ 'X'-'@'\r
+\r
+TPA equ 100h\r
+TOPRAM equ 0f000h\r
+\r
+\r
+MEMDUMP_CNT equ 16 ;mem dump bytes per line\r
+BP_CNT equ 12 ;number of breakbpoints\r
+\r
+\r
+;--------------------------------------------------\r
+; \r
+\r
+; copy code to common memory and execute it there\r
+comst macro\r
+ call ?excom\r
+ ds 1\r
+?lcs defl $\r
+ endm\r
+\r
+; mark end of common code snippet\r
+comend macro\r
+?lce defl $\r
+?lclen defl ?lce-?lcs\r
+ org ?lcs-1\r
+ db ?lclen\r
+ org ?lce\r
+ ifndef ?lcmax\r
+?lcmax defl 0\r
+ endif\r
+ if ?lclen gt ?lcmax\r
+?lcmax defl ?lclen\r
+ endif\r
+ endm\r
+\r
+; repeat execution of last common code snippet\r
+comrep macro\r
+ call ?exclst\r
+ endm\r
+\r
+\r
+\r
+ cseg\r
+\r
+;----------------------------------------------------------\r
+\r
+MSG:\r
+ DB 'DDT/Z - HD64180 (ROM)'\r
+ DB CR,LF,0\r
+\r
+HLPMSG:\r
+ DB 'DDT/Z180 (ROM) Commands:',CR,LF\r
+ DB '> @ examine/substitute the displacement register @',CR,LF\r
+ DB '> A [address] Assemble',CR,LF\r
+ DB '> B[X] display [or clear] all Breakpoints',CR,LF\r
+ DB ' B breakp [:count] [breakp..] set Breakpoints',CR,LF\r
+ DB ' BX address [address..] clear Breakpoints',CR,LF\r
+ DB '>>C[N][J] [count] trace over Calls [No list] [Jumps only]',CR,LF\r
+ DB ' C[N][J] W|U expression trace over Calls While|Until ...',CR,LF\r
+ DB '>>D [startadr] [endadr] Display memory in hex and ascii',CR,LF\r
+ DB '> G [startadr] [;breakp..] Go [to start] [temporary breakpoints]',CR,LF\r
+ DB '> H [expression [expression]] compute expressions / show High/max load adr.',CR,LF\r
+ DB '>>I [port] Input a byte from port',CR,LF\r
+ DB '>>L [startadr] [endadr] List disassembled code',CR,LF\r
+ DB '> M[V] startadr endadr destadr Move memory [and verify]',CR,LF\r
+ DB '>>O [byte] [port] Output a byte to port',CR,LF\r
+ DB '> Q[J] startadr endadr bytes Qery memory for byte string [Justified]',CR,LF\r
+ DB '> R [displacement] Read intel hex from console [add displacemt]',CR,LF\r
+ DB '> S address Substitute memory',CR,LF\r
+ DB '>>T[N][J] [count] Trace [No list] [Jumps only] [count steps]',CR,LF\r
+ DB ' T[N][J] W|U expression Trace While|Until expression',CR,LF\r
+ DB '> V startadr endadr destadr Verify (compare) two memory areas',CR,LF\r
+ DB '> X[register] eXamine [and substitute] registers',CR,LF\r
+ DB '> Y[0..9] eXamine [and substitute] Y variables',CR,LF\r
+ DB '> Z startadr endadr bytes Zap (fill) memory with a byte string',CR,LF\r
+ DB 0\r
+\r
+ddtz:\r
+ ld sp,$stack\r
+ ld a,(wstrtflg) ;check warm start flag\r
+ or a\r
+ jr nz,ddtz_w\r
+\r
+ exx\r
+ ld hl,sysramc\r
+ ld de,topcodbeg\r
+ ld bc,topcodend-topcodbeg\r
+ ldir \r
+ \r
+ ld hl,vartab\r
+ ld de,ddtram\r
+ ld bc,vartabe-vartab\r
+ ldir \r
+ exx\r
+\r
+ ld a,e\r
+ ld (ubbr),a\r
+ \r
+ddtz_w:\r
+ ld hl,MSG ;073c\r
+ call PSTR ;073f\r
+ call ddtei ;0742\r
+\r
+; DDTZ main loop\r
+\r
+DDTZML:\r
+ ld sp,$stack ;0761\r
+ ld hl,l07eah ;0764\r
+ ld (CMD_ERR),hl ;0767\r
+ ld hl,(REG.PC) ;076a\r
+ ld (OFFS.pc),hl ;076d\r
+ call sub_0e68h ;0770\r
+ ld hl,(CMD_RPT) ;0773\r
+ ld de,DDTZML ;0776\r
+ call CP.HL.DE ;0779\r
+ ld a,'>' ;077c\r
+ call OUTCHAR ;077e\r
+ call nz,OUTCHAR ;0781\r
+ call z,OUTBL ;0784\r
+ call INLINE ;0787\r
+ call SKIPBL ;078a\r
+ jr z,exe_hl ;078d\r
+ ld hl,DDTZML ;078f\r
+ ld (CMD_RPT),hl ;0792\r
+ inc de ;0795\r
+ sub '?' ;0796\r
+ jr c,ERROR ;0798\r
+ cp 'Z'+1-'?' ;079a\r
+ jr nc,ERROR ;079c\r
+ add a,a ;079e\r
+ ld hl,CMDTAB ;079f\r
+ call ADD_HL_A ;07a2\r
+ ld a,(hl) ;07a5\r
+ inc hl ;07a6\r
+ ld h,(hl) ;07a7\r
+ ld l,a ;07a8\r
+ jr exe_hl ;07a9\r
+ERROR:\r
+ ld hl,(CMD_ERR) ;07ab\r
+exe_hl:\r
+ call CALL.HL ;07ae\r
+ jr DDTZML ;07b1\r
+\r
+CALL.HL:\r
+ jp (hl) ;07b3\r
+\r
+\r
+CMDTAB:\r
+ defw CMD.?\r
+ defw CMD.@ ;07b4\r
+ defw CMD.A ;07b6\r
+ defw CMD.B ;07b8\r
+ defw CMD.C ;07ba\r
+ defw CMD.D ;07bc\r
+ defw ERROR ;07be\r
+ defw ERROR ;07c0\r
+ defw CMD.G ;07c2\r
+ defw CMD.H ;07c4\r
+ defw CMD.I ;07c6\r
+ defw ERROR ;07c8\r
+ defw ERROR ;07ca\r
+ defw CMD.L ;07cc\r
+ defw CMD.M ;07ce\r
+ defw ERROR ;07d0\r
+ defw CMD.O ;07d2\r
+ defw ERROR ;07d4\r
+ defw CMD.Q ;07d6\r
+ defw CMD.R ;07d8\r
+ defw CMD.S ;07da\r
+ defw CMD.T ;07dc\r
+ defw ERROR ;07de\r
+ defw CMD.V ;07e0\r
+ defw ERROR ;07e2\r
+ defw CMD.X ;07e4\r
+ defw CMD.Y ;07e6\r
+ defw CMD.Z ;07e8\r
+l07eah:\r
+ ld a,'?' ;07ea\r
+ call OUTCHAR ;07ec\r
+ jp CRLF ;07ef\r
+\r
+CMD.?:\r
+ call assert_eol\r
+ ld hl,HLPMSG\r
+ call PSTR\r
+ ret\r
+\r
+DELC:\r
+ ld a,b ;07f2\r
+ or a ;07f3\r
+ ret z ;07f4\r
+ ld a,BS ;07f5\r
+ call $co ;07f7\r
+ ld a,' ' ;07fa\r
+ call $co ;07fc\r
+ ld a,BS ;07ff\r
+ call $co ;0801\r
+ dec hl ;0804\r
+ dec b ;0805\r
+ inc c ;0806\r
+ ld a,(hl) ;0807\r
+ cp ' ' ;0808\r
+ ret nc ;080a\r
+ ld a,BS ;080b\r
+ call $co ;080d\r
+ ld a,' ' ;0810\r
+ call $co ;0812\r
+ ld a,BS ;0815\r
+ call $co ;0817\r
+ ret ;081a\r
+DELL:\r
+ ld a,b ;081b\r
+ or a ;081c\r
+ ret z ;081d\r
+ call DELC ;081e\r
+ jr DELL ;0821\r
+\r
+INLINE:\r
+ push hl ;0823\r
+ ld hl,CI.BUF ;0824\r
+ ld c,(hl) ;0827\r
+ inc hl ;0828\r
+ ld b,000h ;0829\r
+ inc hl ;082b\r
+inlnxtch:\r
+ ld a,c ;082c\r
+ or a ;082d\r
+ jr z,inl_e ;082e\r
+ call $ci ;0830\r
+ cp CR ;0833\r
+ jr z,inl_e ;0835\r
+ cp LF ;0837\r
+ jr z,inl_e ;0839\r
+ cp BS ;083b\r
+ jr nz,l0844h ;083d\r
+ call DELC ;083f\r
+ jr inlnxtch ;0842\r
+l0844h:\r
+ cp DEL ;0844\r
+ jr nz,l084dh ;0846\r
+ call DELC ;0848\r
+ jr inlnxtch ;084b\r
+l084dh:\r
+ cp CNTRX ;084d\r
+ jr nz,l0856h ;084f\r
+ call DELL ;0851\r
+ jr inlnxtch ;0854\r
+l0856h:\r
+ cp TAB ;0856\r
+ jr nz,l085ch ;0858\r
+ ld a,' ' ;085a\r
+l085ch:\r
+ ld (hl),a ;085c\r
+ cp ' ' ;085d\r
+ jr nc,l0869h ;085f\r
+ ld a,'^' ;0861\r
+ call $co ;0863\r
+ ld a,(hl) ;0866\r
+ add a,'@' ;0867\r
+l0869h:\r
+ call $co ;0869\r
+ inc hl ;086c\r
+ inc b ;086d\r
+ dec c ;086e\r
+ jr inlnxtch ;086f\r
+\r
+inl_e:\r
+ ld hl,ci.buf+1 ;0871\r
+ ld (hl),b ;0874\r
+ call CRLF ;0875\r
+ ld de,ci.buf+1 ;0878\r
+ ld a,(de) ;087b\r
+ ld b,a ;087c\r
+ ld c,000h ;087d\r
+ inc b ;087f\r
+l0880h:\r
+ inc de ;0880\r
+ dec b ;0881\r
+ jr z,l08b2h ;0882\r
+ ld a,(de) ;0884\r
+ bit 0,c ;0885\r
+ call z,UPCASE ;0887\r
+ ld (de),a ;088a\r
+ cp '''' ;088b\r
+ jr nz,l0880h ;088d\r
+ push de ;088f\r
+ dec de ;0890\r
+ ld a,(de) ;0891\r
+ cp '''' ;0892\r
+ jr z,l08aeh ;0894\r
+ dec de ;0896\r
+ ld a,(de) ;0897\r
+ cp '^' ;0898\r
+ jr z,l08a2h ;089a\r
+ dec de ;089c\r
+ ld a,(de) ;089d\r
+ cp '^' ;089e\r
+ jr nz,l08aeh ;08a0\r
+l08a2h:\r
+ inc de ;08a2\r
+ push bc ;08a3\r
+ call sub_0a0eh ;08a4\r
+ pop bc ;08a7\r
+ dec de ;08a8\r
+ ld a,(de) ;08a9\r
+ cp '''' ;08aa\r
+ jr z,l08afh ;08ac\r
+l08aeh:\r
+ inc c ;08ae\r
+l08afh:\r
+ pop de ;08af\r
+ jr l0880h ;08b0\r
+l08b2h:\r
+ xor a ;08b2\r
+ ld (de),a ;08b3\r
+ ld de,ci.buf+2 ;08b4\r
+ pop hl ;08b7\r
+ ret ;08b8\r
+\r
+UPCASE:\r
+ cp 'a' ;08b9\r
+ ret c ;08bb\r
+ cp 'z'+1 ;08bc\r
+ ret nc ;08be\r
+ and 05fh ;08bf\r
+ ret ;08c1\r
+\r
+out.hl.@:\r
+ call out.hl ;08c2\r
+ push de ;08c5\r
+ push hl ;08c6\r
+ ld de,(offs.@) ;08c7\r
+ ld a,d ;08cb\r
+ or e ;08cc\r
+ jr z,l08ddh ;08cd\r
+ call OUTBL ;08cf\r
+ ld a,'@' ;08d2\r
+ call OUTCHAR ;08d4\r
+ and a ;08d7\r
+ sbc hl,de ;08d8\r
+ call out.hl ;08da\r
+l08ddh:\r
+ pop hl ;08dd\r
+ pop de ;08de\r
+ ret ;08df\r
+\r
+out.bin.w:\r
+ ld a,h ;08e0\r
+ call out.bin.b ;08e1\r
+ ld a,l ;08e4\r
+out.bin.b:\r
+ ld b,008h ;08e5\r
+l08e7h:\r
+ add a,a ;08e7\r
+ push af ;08e8\r
+ ld a,0 ;08e9\r
+ adc a,a ;08eb\r
+ call out.digit ;08ec\r
+ pop af ;08ef\r
+ djnz l08e7h ;08f0\r
+ ld a,'"' ;08f2\r
+ jp OUTCHAR ;08f4\r
+\r
+sub_08f7h:\r
+ ld a,'-' ;08f7\r
+ call OUTCHAR ;08f9\r
+ dec hl ;08fc\r
+ jp cpl.hl ;08fd\r
+\r
+out.hl.decm:\r
+ push hl ;0900\r
+ call sub_08f7h ;0901\r
+ db 3eh ;0904 ld a,0E5h\r
+out.hl.dec:\r
+ push hl\r
+ ld b,6 ;0906\r
+ call sub_0917h ;0908\r
+ pop hl ;090b\r
+ ld a,'.' ;090c\r
+ call OUTCHAR ;090e\r
+l0911h:\r
+ call OUTBL ;0911\r
+ djnz l0911h ;0914\r
+ ret ;0916\r
+\r
+\r
+sub_0917h:\r
+ dec b ;0917\r
+ push de ;0918\r
+ ld de,10 ;0919\r
+ call DIV_HL_DE ;091c\r
+ ld a,h ;091f\r
+ or l ;0920\r
+ call nz,sub_0917h ;0921\r
+ ld a,e ;0924\r
+ pop de ;0925\r
+ jr out.digit ;0926\r
+\r
+sub_0928h:\r
+ push hl ;0928\r
+ call sub_08f7h ;0929\r
+ call out.hl ;092c\r
+ pop hl ;092f\r
+ ret ;0930\r
+out.hl:\r
+ ld a,h ;0931\r
+ call out.hex ;0932\r
+ ld a,l ;0935\r
+out.hex:\r
+ push af ;0936\r
+ rra ;0937\r
+ rra ;0938\r
+ rra ;0939\r
+ rra ;093a\r
+ call out.digit ;093b\r
+ pop af ;093e\r
+out.digit:\r
+ and 00fh ;093f\r
+ cp 10 ;0941\r
+ jr c,l0947h ;0943\r
+ add a,007h ;0945\r
+l0947h:\r
+ add a,'0' ;0947\r
+ jr OUTCHAR ;0949\r
+l094bh:\r
+ ld a,'-' ;094b\r
+ call OUTCHAR ;094d\r
+ ld a,040h ;0950\r
+out.ascii:\r
+ ex af,af' ;0952\r
+ call outquote ;0953\r
+ ex af,af' ;0956\r
+ push af ;0957\r
+ res 7,a ;0958\r
+ cp ' ' ;095a\r
+ jr nc,l0960h ;095c\r
+ sub 0c0h ;095e\r
+l0960h:\r
+ call OUTCHAR ;0960\r
+ push af ;0963\r
+ cp '''' ;0964\r
+ call z,OUTCHAR ;0966\r
+ pop af ;0969\r
+ ex af,af' ;096a\r
+ call outquote ;096b\r
+ pop af ;096e\r
+ or a ;096f\r
+ ld a,'.' ;0970\r
+ call m,OUTCHAR ;0972\r
+ ex af,af' ;0975\r
+ jr c,l094bh ;0976\r
+ ret ;0978\r
+\r
+outquote:\r
+ ld a,'''' ;0979\r
+OUTCHAR:\r
+ push hl ;097b\r
+ push af ;097c\r
+ and 07fh ;097d\r
+ call $co ;097f\r
+ ld hl,CON.COL ;0982\r
+ inc (hl) ;0985\r
+ pop af ;0986\r
+ pop hl ;0987\r
+ ret ;0988\r
+\r
+inchar:\r
+ call $cists ;0989\r
+ and a ;098c\r
+ ret z ;098d\r
+ call $ci ;098e\r
+ scf ;0991\r
+ ret ;0992\r
+\r
+PSTR:\r
+ ld c,000h ;0993\r
+l0995h:\r
+ ld a,(hl) ;0995\r
+ and a ;0996\r
+ ret z ;0997\r
+ call OUTCHAR ;0998\r
+ inc c ;099b\r
+ inc hl ;099c\r
+ and a ;099d\r
+ ret m ;099e\r
+ jr l0995h ;099f\r
+\r
+outbl6:\r
+ call outbl2 ;09a1\r
+outbl4:\r
+ call outbl2 ;09a4\r
+outbl2:\r
+ call OUTBL ;09a7\r
+OUTBL:\r
+ ld a,' ' ;09aa\r
+ jr OUTCHAR ;09ac\r
+CRLF:\r
+ call inchar ;09ae\r
+ ld a,CR ;09b1\r
+ call OUTCHAR ;09b3\r
+ ld a,LF ;09b6\r
+ call OUTCHAR ;09b8\r
+ ld a,000h ;09bb\r
+ ld (CON.COL),a ;09bd\r
+ jp c,DDTZML ;09c0\r
+ ret ;09c3\r
+\r
+ADD_HL_A:\r
+ add a,l ;09c4\r
+ ld l,a ;09c5\r
+ ret nc ;09c6\r
+ inc h ;09c7\r
+ ret ;09c8\r
+\r
+SKIPBL0:\r
+ inc de ;09c9\r
+SKIPBL:\r
+ ld a,(de) ;09ca\r
+ cp ' ' ;09cb\r
+ jr z,SKIPBL0 ;09cd\r
+ cp 009h ;09cf\r
+ jr z,SKIPBL0 ;09d1\r
+ or a ;09d3\r
+ ret ;09d4\r
+\r
+skip_to_nextarg:\r
+ call SKIPBL ;09d5\r
+ cp ',' ;09d8\r
+ ret nz ;09da\r
+ inc de ;09db\r
+ call SKIPBL ;09dc\r
+ cp a ;09df\r
+ ret ;09e0\r
+\r
+assert_eol:\r
+ call SKIPBL ;09e1\r
+ ret z ;09e4\r
+l09e5h:\r
+ jp ERROR ;09e5\r
+\r
+chk.sp:\r
+ push hl ;09e8\r
+ push de ;09e9\r
+ ld hl,0 ;09ea\r
+ add hl,sp ;09ed\r
+ ld de,$stack-50 ;09ee\r
+ call CP.HL.DE ;09f1\r
+ pop de ;09f4\r
+ pop hl ;09f5\r
+ jr c,l09e5h ;09f6\r
+ ret ;09f8\r
+\r
+CP.HL.DE:\r
+ and a ;09f9\r
+ sbc hl,de ;09fa\r
+ add hl,de ;09fc\r
+ ret ;09fd\r
+\r
+lookupch:\r
+ ld b,000h ;09fe\r
+l0a00h:\r
+ ld a,(hl) ;0a00\r
+ and a ;0a01\r
+ ret z ;0a02\r
+ ld a,(de) ;0a03\r
+ cp (hl) ;0a04\r
+ jr z,l0a0bh ;0a05\r
+ inc hl ;0a07\r
+ inc b ;0a08\r
+ jr l0a00h ;0a09\r
+l0a0bh:\r
+ scf ;0a0b\r
+ inc de ;0a0c\r
+ ret ;0a0d\r
+\r
+sub_0a0eh:\r
+ ld hl,b_0x132A_start ;0a0e\r
+ ld b,07fh ;0a11\r
+ jr l0a17h ;0a13\r
+\r
+sub_0a15h:\r
+ ld b,0ffh ;0a15\r
+l0a17h:\r
+ inc b ;0a17\r
+ ld a,(hl) ;0a18\r
+ and a ;0a19\r
+ ret z ;0a1a\r
+ call l0a27 ;0a1b\r
+ jr nc,l0a17h ;0a1e\r
+ res 7,b ;0a20\r
+ ret ;0a22\r
+\r
+sub_0a23h:\r
+ push bc ;0a23\r
+ res 7,b ;0a24\r
+ db 3eh ;0a26 ld a,0c5h\r
+l0a27:\r
+ push bc ;0a27\r
+ push de ;0a28\r
+l0a29h:\r
+ ld a,(de) ;0a29\r
+ xor (hl) ;0a2a\r
+ and 07fh ;0a2b\r
+ jr nz,l0a41h ;0a2d\r
+ bit 7,(hl) ;0a2f\r
+ inc hl ;0a31\r
+ inc de ;0a32\r
+ jr z,l0a29h ;0a33\r
+ scf ;0a35\r
+ bit 7,b ;0a36\r
+ call z,sub_0d20h ;0a38\r
+ jr nc,l0a44h ;0a3b\r
+ pop af ;0a3d\r
+ scf ;0a3e\r
+ pop bc ;0a3f\r
+ ret ;0a40\r
+\r
+l0a41h:\r
+ call sub_0a50h ;0a41\r
+l0a44h:\r
+ pop de ;0a44\r
+ and a ;0a45\r
+ pop bc ;0a46\r
+ ret ;0a47\r
+\r
+sub_0a48h:\r
+ inc b ;0a48\r
+l0a49h:\r
+ dec b ;0a49\r
+ ret z ;0a4a\r
+ call sub_0a50h ;0a4b\r
+ jr l0a49h ;0a4e\r
+sub_0a50h:\r
+ ld a,(hl) ;0a50\r
+ and a ;0a51\r
+ ret z ;0a52\r
+l0a53h:\r
+ ld a,(hl) ;0a53\r
+ inc hl ;0a54\r
+ and a ;0a55\r
+ ret m ;0a56\r
+ jr l0a53h ;0a57\r
+\r
+get_arg3:\r
+ call get_arg_range ;0a59\r
+ push hl ;0a5c\r
+ push bc ;0a5d\r
+ call skip_to_nextarg ;0a5e\r
+ call get_arg ;0a61\r
+ ex de,hl ;0a64\r
+ pop bc ;0a65\r
+ pop hl ;0a66\r
+ ret ;0a67\r
+\r
+sub_0a68h:\r
+ call EXPR ;0a68\r
+ jr c,error0 ;0a6b\r
+ ret ;0a6d\r
+\r
+get_arg:\r
+ call sub_0a68h ;0a6e\r
+l0a71h:\r
+ jp assert_eol ;0a71\r
+\r
+get_lastarg_def:\r
+ call get_arg_def ;0a74\r
+ jr l0a71h ;0a77\r
+\r
+get_arg_def:\r
+ push hl ;0a79\r
+ call EXPR ;0a7a\r
+ jr c,l0a80h ;0a7d\r
+ ex (sp),hl ;0a7f\r
+l0a80h:\r
+ pop hl ;0a80\r
+ ret ;0a81\r
+\r
+sub_0a82h:\r
+ call sub_0a87h ;0a82\r
+ jr l0a71h ;0a85\r
+\r
+sub_0a87h:\r
+ db 0e6h ;0a87 and 037h (clear carry)\r
+get_arg_range:\r
+ scf\r
+ ex af,af' ;0a89\r
+ push bc ;0a8a\r
+ push hl ;0a8b\r
+ call EXPR ;0a8c\r
+ jr nc,l0a97h ;0a8f\r
+ ex af,af' ;0a91\r
+ jr c,error0 ;0a92\r
+ ex af,af' ;0a94\r
+ pop hl ;0a95\r
+\r
+ defb 03eh ;0a96\r
+l0a97h:\r
+ pop af ;0a97\r
+ call sub_0aa5h ;0a98\r
+ jr nc,l0aa3h ;0a9b\r
+ ex af,af' ;0a9d\r
+ pop bc ;0a9e\r
+ ret nc ;0a9f\r
+error0:\r
+ jp ERROR ;0aa0\r
+\r
+l0aa3h:\r
+ pop af ;0aa3\r
+ ret ;0aa4\r
+\r
+sub_0aa5h:\r
+ call skip_to_nextarg ;0aa5\r
+ cp 'S' ;0aa8\r
+ jr nz,l0aadh ;0aaa\r
+ inc de ;0aac\r
+l0aadh:\r
+ push hl ;0aad\r
+ push af ;0aae\r
+ call EXPR ;0aaf\r
+ jr c,l0ac3h ;0ab2\r
+ ld b,h ;0ab4\r
+ ld c,l ;0ab5\r
+ pop af ;0ab6\r
+ pop hl ;0ab7\r
+ jr z,l0ac1h ;0ab8\r
+ ld a,c ;0aba\r
+ sub l ;0abb\r
+ ld c,a ;0abc\r
+ ld a,b ;0abd\r
+ sbc a,h ;0abe\r
+ ld b,a ;0abf\r
+ inc bc ;0ac0\r
+l0ac1h:\r
+ and a ;0ac1\r
+ ret ;0ac2\r
+\r
+l0ac3h:\r
+ pop af ;0ac3\r
+ pop hl ;0ac4\r
+ jr z,error0 ;0ac5\r
+ scf ;0ac7\r
+ ret ;0ac8\r
+\r
+EXPR:\r
+ call SKIPBL ;0ac9\r
+EXPR1:\r
+ call do_subexpr ;0acc\r
+ ret c ;0acf\r
+ call do_rel_op ;0ad0\r
+ ret nc ;0ad3\r
+ push bc ;0ad4\r
+ push hl ;0ad5\r
+ call do_subexpr ;0ad6\r
+ jr c,error0 ;0ad9\r
+ ex de,hl ;0adb\r
+ ex (sp),hl ;0adc\r
+ and a ;0add\r
+ sbc hl,de ;0ade\r
+ ld hl,0ffffh ;0ae0\r
+ pop de ;0ae3\r
+ ret ;0ae4\r
+\r
+do_op_eq:\r
+ jr z,l0af8h ;0ae5\r
+ jr l0af7h ;0ae7\r
+do_op_ne:\r
+ jr nz,l0af8h ;0ae9\r
+ jr l0af7h ;0aeb\r
+do_op_le:\r
+ jr z,l0af8h ;0aed\r
+do_op_lt:\r
+ jr c,l0af8h ;0aef\r
+ jr l0af7h ;0af1\r
+do_op_gt:\r
+ jr z,l0af7h ;0af3\r
+do_op_ge:\r
+ jr nc,l0af8h ;0af5\r
+l0af7h:\r
+ inc hl ;0af7\r
+l0af8h:\r
+ and a ;0af8\r
+ ret ;0af9\r
+\r
+do_rel_op:\r
+ push hl ;0afa\r
+ ld hl,tab_eq_le_ge ;0afb\r
+ call lookupch ;0afe\r
+ jr nc,l0b28h ;0b01\r
+ ld a,b ;0b03\r
+ or a ;0b04\r
+ jr z,l0b1ch ;0b05\r
+ ld a,(de) ;0b07\r
+ cp '=' ;0b08\r
+ jr nz,l0b11h ;0b0a\r
+ inc de ;0b0c\r
+ inc b ;0b0d\r
+ inc b ;0b0e\r
+ jr l0b1ch ;0b0f\r
+\r
+l0b11h:\r
+ bit 0,b ;0b11\r
+ jr z,l0b1ch ;0b13\r
+ cp '>' ;0b15\r
+ jr nz,l0b1ch ;0b17\r
+ inc de ;0b19\r
+ ld b,005h ;0b1a\r
+l0b1ch:\r
+ ld hl,tab_func_eqlege ;0b1c\r
+ ld a,b ;0b1f\r
+ add a,a ;0b20\r
+ call ADD_HL_A ;0b21\r
+ ld c,(hl) ;0b24\r
+ inc hl ;0b25\r
+ ld b,(hl) ;0b26\r
+ scf ;0b27\r
+l0b28h:\r
+ pop hl ;0b28\r
+ ret ;0b29\r
+\r
+tab_eq_le_ge:\r
+ db '=<>',0\r
+\r
+tab_func_eqlege:\r
+ defw do_op_eq ;0b2e\r
+ defw do_op_lt ;0b30\r
+ defw do_op_gt ;0b32\r
+ defw do_op_le ;0b34\r
+ defw do_op_ge ;0b36\r
+ defw do_op_ne ;0b38\r
+\r
+do_subexpr:\r
+ call do_factor ;0b3a\r
+ ret c ;0b3d\r
+l0b3eh:\r
+ call do_binary_op ;0b3e\r
+ push hl ;0b41\r
+ push bc ;0b42\r
+ call do_factor ;0b43\r
+ pop bc ;0b46\r
+ ex de,hl ;0b47\r
+ ex (sp),hl ;0b48\r
+ jr nc,l0b52h ;0b49\r
+ pop de ;0b4b\r
+ ld a,b ;0b4c\r
+ or c ;0b4d\r
+ ret z ;0b4e\r
+ jp ERROR ;0b4f\r
+\r
+l0b52h:\r
+ ld a,b ;0b52\r
+ or c ;0b53\r
+ push bc ;0b54\r
+ ret nz ;0b55\r
+ pop bc ;0b56\r
+do_op_add:\r
+ add hl,de ;0b57\r
+l0b58h:\r
+ pop de ;0b58\r
+ jr l0b3eh ;0b59\r
+\r
+do_op_sub:\r
+ and a ;0b5b\r
+ sbc hl,de ;0b5c\r
+ jr l0b58h ;0b5e\r
+\r
+do_op_mlt:\r
+ push bc ;0b60\r
+ ld b,h\r
+ ld c,e\r
+ ld h,e\r
+ ld e,l\r
+ mlt bc\r
+ mlt de\r
+ mlt hl\r
+ ld a,h\r
+ add a,c\r
+ add a,e\r
+ ld h,a\r
+ pop bc ;0b72\r
+ jr l0b58h ;0b73\r
+\r
+do_op_div:\r
+ call DIV_HL_DE ;0b75\r
+ jr l0b58h ;0b78\r
+\r
+do_op_mod:\r
+ call DIV_HL_DE ;0b7a\r
+ ex de,hl ;0b7d\r
+ jr l0b58h ;0b7e\r
+\r
+DIV_HL_DE:\r
+ push bc ;0b80\r
+ ex de,hl ;0b81\r
+ ld b,h ;0b82\r
+ ld c,l ;0b83\r
+ ld hl,0 ;0b84\r
+ ld a,16 ;0b87\r
+l0b89h:\r
+ push af ;0b89\r
+ add hl,hl ;0b8a\r
+ ex de,hl ;0b8b\r
+ xor a ;0b8c\r
+ add hl,hl ;0b8d\r
+ ex de,hl ;0b8e\r
+ adc a,l ;0b8f\r
+ sub c ;0b90\r
+ ld l,a ;0b91\r
+ ld a,h ;0b92\r
+ sbc a,b ;0b93\r
+ ld h,a ;0b94\r
+ inc de ;0b95\r
+ jr nc,l0b9ah ;0b96\r
+ add hl,bc ;0b98\r
+ dec de ;0b99\r
+l0b9ah:\r
+ pop af ;0b9a\r
+ dec a ;0b9b\r
+ jr nz,l0b89h ;0b9c\r
+ ex de,hl ;0b9e\r
+ pop bc ;0b9f\r
+ ret ;0ba0\r
+\r
+do_op_and:\r
+ ld a,h ;0ba1\r
+ and d ;0ba2\r
+ ld h,a ;0ba3\r
+ ld a,l ;0ba4\r
+ and e ;0ba5\r
+ ld l,a ;0ba6\r
+ jr l0b58h ;0ba7\r
+\r
+do_op_or:\r
+ ld a,h ;0ba9\r
+ or d ;0baa\r
+ ld h,a ;0bab\r
+ ld a,l ;0bac\r
+ or e ;0bad\r
+ ld l,a ;0bae\r
+ jr l0b58h ;0baf\r
+\r
+do_op_xor:\r
+ ld a,h ;0bb1\r
+ xor d ;0bb2\r
+ ld h,a ;0bb3\r
+ ld a,l ;0bb4\r
+ xor e ;0bb5\r
+ ld l,a ;0bb6\r
+ jr l0b58h ;0bb7\r
+\r
+do_binary_op:\r
+ push hl ;0bb9\r
+ ld hl,tab_op_a ;0bba\r
+ call lookupch ;0bbd\r
+ ld a,b ;0bc0\r
+ ld hl,tab_func_opa ;0bc1\r
+ add a,a ;0bc4\r
+ call ADD_HL_A ;0bc5\r
+ ld c,(hl) ;0bc8\r
+ inc hl ;0bc9\r
+ ld b,(hl) ;0bca\r
+ pop hl ;0bcb\r
+ ret ;0bcc\r
+\r
+tab_op_a:\r
+ DB '+-*/%&!#',0\r
+tab_func_opa:\r
+ defw do_op_add ;0bd6\r
+ defw do_op_sub ;0bd8\r
+ defw do_op_mlt ;0bda\r
+ defw do_op_div ;0bdc\r
+ defw do_op_mod ;0bde\r
+ defw do_op_and ;0be0\r
+ defw do_op_or ;0be2\r
+ defw do_op_xor ;0be4\r
+ defw 0 ;0be6\r
+\r
+fact_factor:\r
+ call do_factor ;0be8\r
+ ret nc ;0beb\r
+ jp ERROR ;0bec\r
+\r
+do_factor:\r
+ call chk.sp ;0bef\r
+ call get.number ;0bf2\r
+ ret nc ;0bf5\r
+ inc de ;0bf6\r
+ ld hl,TOPRAM ;0bf7\r
+ cp 'T' ;0bfa\r
+ ret z ;0bfc\r
+ ld hl,(HILOD) ;0bfd\r
+ cp 'H' ;0c00\r
+ ret z ;0c02\r
+ ld hl,(MAXLOD) ;0c03\r
+ cp 'M' ;0c06\r
+ ret z ;0c08\r
+ ld hl,TPA ;0c09\r
+ cp 'L' ;0c0c\r
+ ret z ;0c0e\r
+ ld hl,(offs.@) ;0c0f\r
+ cp '@' ;0c12\r
+ ret z ;0c14\r
+ ld hl,(OFFS.pc) ;0c15\r
+ cp '$' ;0c18\r
+ ret z ;0c1a\r
+ cp '-' ;0c1b\r
+ jr z,fact_factneg ;0c1d\r
+ cp '~' ;0c1f\r
+ jr z,fact_factinv ;0c21\r
+ cp '+' ;0c23\r
+ jr z,fact_factor ;0c25\r
+ cp '^' ;0c27\r
+ jr z,fact_reg.CPU ;0c29\r
+ cp 'Y' ;0c2b\r
+ jr z,fact_reg.Y ;0c2d\r
+ cp '(' ;0c2f\r
+ jr z,fact_mem ;0c31\r
+ cp '[' ;0c33\r
+ jp z,EXPR_BRCKT ;0c35 [ expression ]\r
+ cp '''' ;0c38\r
+ jr z,fact_factstring ;0c3a\r
+ dec de ;0c3c\r
+ scf ;0c3d\r
+ ret ;0c3e\r
+\r
+fact_reg.Y:\r
+ call get.decdigit ;0c3f\r
+ jp c,ERROR ;0c42\r
+ inc de ;0c45\r
+ add a,a ;0c46\r
+ ld hl,reg.Y ;0c47\r
+ call ADD_HL_A ;0c4a\r
+ ld a,(hl) ;0c4d\r
+ inc hl ;0c4e\r
+ ld h,(hl) ;0c4f\r
+ ld l,a ;0c50\r
+ and a ;0c51\r
+ ret ;0c52\r
+fact_factstring:\r
+ ld hl,0 ;0c53\r
+l0c56h:\r
+ ld a,(de) ;0c56\r
+ cp '''' ;0c57\r
+ jr z,l0c62h ;0c59\r
+ and a ;0c5b\r
+ ret z ;0c5c\r
+l0c5dh:\r
+ ld h,l ;0c5d\r
+ ld l,a ;0c5e\r
+ inc de ;0c5f\r
+ jr l0c56h ;0c60\r
+\r
+l0c62h:\r
+ inc de ;0c62\r
+ ld a,(de) ;0c63\r
+ cp '''' ;0c64\r
+ jr z,l0c5dh ;0c66\r
+ sub '.' ;0c68\r
+ or a ;0c6a\r
+ ret nz ;0c6b\r
+ inc de ;0c6c\r
+ set 7,l ;0c6d\r
+ ret ;0c6f\r
+\r
+fact_reg.CPU:\r
+ call sub_1315h ;0c70\r
+ jr nc,l0cbbh ;0c73\r
+ ld a,(hl) ;0c75\r
+ inc hl ;0c76\r
+ ld h,(hl) ;0c77\r
+ ld l,a ;0c78\r
+ and a ;0c79\r
+ bit 0,c ;0c7a\r
+ ret nz ;0c7c\r
+ ld h,000h ;0c7d\r
+ ret ;0c7f\r
+\r
+fact_factneg:\r
+ call fact_factor ;0c80\r
+ dec hl ;0c83\r
+cpl.hl:\r
+ ld a,h ;0c84\r
+ cpl ;0c85\r
+ ld h,a ;0c86\r
+ ld a,l ;0c87\r
+ cpl ;0c88\r
+ ld l,a ;0c89\r
+ ret ;0c8a\r
+fact_factinv:\r
+ call fact_factor ;0c8b\r
+ jr cpl.hl ;0c8e\r
+\r
+fact_mem:\r
+ call EXPR1 ;0c90\r
+ jr c,l0cbbh ;0c93\r
+ ld a,(de) ;0c95\r
+ cp ')' ;0c96\r
+ jr nz,l0cbbh ;0c98\r
+ inc de ;0c9a\r
+ comst\r
+ ld a,(hl) ;0c9f\r
+ inc hl ;\r
+ ld h,(hl) ;\r
+ comend\r
+ ld l,a ;0ca7\r
+ ld a,(de) ;0ca8\r
+ inc de ;0ca9\r
+ cp '.' ;0caa\r
+ ret z ;0cac\r
+ dec de ;0cad\r
+ xor a ;0cae\r
+ ld h,a ;0caf\r
+ ret ;0cb0\r
+\r
+EXPR_BRCKT:\r
+ call EXPR1 ;0cb1\r
+ jr c,l0cbbh ;0cb4\r
+ ld a,(de) ;0cb6\r
+ cp ']' ;0cb7\r
+ inc de ;0cb9\r
+ ret z ;0cba\r
+l0cbbh:\r
+ jp ERROR ;0cbb\r
+\r
+get.number:\r
+ call get.hexdigit ;0cbe\r
+ ret c ;0cc1\r
+ push de ;0cc2\r
+l0cc3h:\r
+ inc de ;0cc3\r
+ call get.hexdigit ;0cc4\r
+ jr nc,l0cc3h ;0cc7\r
+ pop de ;0cc9\r
+ cp '.' ;0cca\r
+ jr z,l0d04h ;0ccc\r
+ cp '"' ;0cce\r
+ jr z,l0ce9h ;0cd0\r
+ ld hl,0 ;0cd2\r
+l0cd5h:\r
+ call get.hexdigit ;0cd5\r
+ jr c,l0ce4h ;0cd8\r
+ add hl,hl ;0cda\r
+ add hl,hl ;0cdb\r
+ add hl,hl ;0cdc\r
+ add hl,hl ;0cdd\r
+ call ADD_HL_A ;0cde\r
+ inc de ;0ce1\r
+ jr l0cd5h ;0ce2\r
+l0ce4h:\r
+ xor 'H' ;0ce4\r
+ ret nz ;0ce6\r
+ inc de ;0ce7\r
+ ret ;0ce8\r
+\r
+l0ce9h:\r
+ ld hl,0 ;0ce9\r
+l0cech:\r
+ call get.decdigit ;0cec\r
+l0cefh:\r
+ inc de ;0cef\r
+ jr c,l0cf8h ;0cf0\r
+ add hl,hl ;0cf2\r
+ call ADD_HL_A ;0cf3\r
+ jr l0cech ;0cf6\r
+l0cf8h:\r
+ cp '"' ;0cf8\r
+ jp nz,ERROR ;0cfa\r
+ call get.decdigit ;0cfd\r
+ jr nc,l0cefh ;0d00\r
+ or a ;0d02\r
+ ret ;0d03\r
+l0d04h:\r
+ ld hl,0 ;0d04\r
+l0d07h:\r
+ call get.decdigit ;0d07\r
+ inc de ;0d0a\r
+ jr c,l0d1ah ;0d0b\r
+ push bc ;0d0d\r
+ add hl,hl ;0d0e hl *= 10\r
+ ld b,h ;0d0f\r
+ ld c,l ;0d10\r
+ add hl,hl ;0d11\r
+ add hl,hl ;0d12\r
+ add hl,bc ;0d13\r
+ pop bc ;0d14\r
+ call ADD_HL_A ;0d15\r
+ jr l0d07h ;0d18\r
+l0d1ah:\r
+ cp '.' ;0d1a\r
+ ret z ;0d1c\r
+ jp ERROR ;0d1d\r
+\r
+sub_0d20h:\r
+ ld a,(de) ;0d20\r
+ cp 05bh ;0d21\r
+ jr l0d28h ;0d23\r
+\r
+get.hexdigit:\r
+ ld a,(de) ;0d25\r
+sub_0d26h:\r
+ cp 'F'+1 ;0d26\r
+l0d28h:\r
+ ccf ;0d28\r
+ ret c ;0d29\r
+ cp 'A' ;0d2a\r
+ jr c,l0d32h ;0d2c\r
+ sub 'A'-10 ;0d2e\r
+ ret ;0d30\r
+\r
+get.decdigit:\r
+ ld a,(de) ;0d31\r
+l0d32h:\r
+ cp '9'+1 ;0d32\r
+ jr l0d39h ;0d34\r
+get.bindigit:\r
+ ld a,(de) ;0d36\r
+ cp '1'+1 ;0d37\r
+l0d39h:\r
+ ccf ;0d39\r
+ ret c ;0d3a\r
+ cp '0' ;0d3b\r
+ ret c ;0d3d\r
+ sub '0' ;0d3e\r
+ ret ;0d40\r
+\r
+l0d41h:\r
+ call assert_eol ;0d41\r
+\r
+prnt_cpustat:\r
+ call prnt_f ;0d44\r
+ call outbl2 ;0d47\r
+ ld hl,b_0x0DFD_start ;0d4a\r
+ ld de,b_0x0E1D_start ;0d4d\r
+ ld b,006h ;0d50\r
+l0d52h:\r
+ call prnt_regs ;0d52\r
+ djnz l0d52h ;0d55\r
+ push hl ;0d57\r
+ push de ;0d58\r
+ ld iy,(REG.PC) ;0d59\r
+ call sub_1f77h ;0d5d\r
+ exx ;0d60\r
+ ex af,af' ;0d61\r
+ call CRLF ;0d62\r
+ call prnt_f2 ;0d65\r
+ call outbl2 ;0d68\r
+ pop de ;0d6b\r
+ pop hl ;0d6c\r
+ ld b,007h ;0d6d\r
+l0d6fh:\r
+ call prnt_regs ;0d6f\r
+ djnz l0d6fh ;0d72\r
+ exx ;0d74\r
+ ex af,af' ;0d75\r
+ and a ;0d76\r
+ jr z,l0d7fh ;0d77\r
+ call outbl6 ;0d79\r
+ call sub_1f5bh ;0d7c\r
+l0d7fh:\r
+ jp crlf ;0d7f\r
+\r
+prnt_f:\r
+ ld a,(reg.f) ;0d82\r
+ call prnt_flags ;0d85\r
+ ld a,(reg.iff) ;0d88\r
+ cp 0f3h ;0d8b\r
+ jp z,outbl ;0d8d\r
+ ld a,'E' ;0d90\r
+ jp outchar ;0d92\r
+\r
+prnt_f2:\r
+ ld a,(reg.f2) ;0d95\r
+ call prnt_flags ;0d98\r
+ jp outbl ;0d9b\r
+\r
+prnt_flags:\r
+ ld b,a ;0d9e\r
+ ld a,'S' ;0d9f\r
+ call sub_0dbeh ;0da1\r
+ ld a,'Z' ;0da4\r
+ call sub_0dbeh ;0da6\r
+ rl b ;0da9\r
+ ld a,'H' ;0dab\r
+ call sub_0dbeh ;0dad\r
+ rl b ;0db0\r
+ ld a,'V' ;0db2\r
+ call sub_0dbeh ;0db4\r
+ ld a,'N' ;0db7\r
+ call sub_0dbeh ;0db9\r
+ ld a,'C' ;0dbc\r
+sub_0dbeh:\r
+ rl b ;0dbe\r
+ jp c,OUTCHAR ;0dc0\r
+ jp OUTBL ;0dc3\r
+\r
+prnt_regs:\r
+ push bc ;0dc6\r
+ push de ;0dc7\r
+ call PSTR ;0dc8\r
+ ld a,'=' ;0dcb\r
+ call OUTCHAR ;0dcd\r
+ ex (sp),hl ;0dd0\r
+ ld e,(hl) ;0dd1\r
+ inc hl ;0dd2\r
+ ld d,(hl) ;0dd3\r
+ inc hl ;0dd4\r
+ ld a,(hl) ;0dd5\r
+ inc hl ;0dd6\r
+ push hl ;0dd7\r
+ and a ;0dd8\r
+ jr z,l0df2h ;0dd9\r
+ push af ;0ddb\r
+ ld a,(de) ;0ddc\r
+ ld l,a ;0ddd\r
+ inc de ;0dde\r
+ ld a,(de) ;0ddf\r
+ ld h,a ;0de0\r
+ pop af ;0de1\r
+ dec a ;0de2\r
+ jr z,l0dedh ;0de3\r
+ call out.hl.@ ;0de5\r
+ call z,outbl6 ;0de8\r
+ jr l0df6h ;0deb\r
+l0dedh:\r
+ call out.hl ;0ded\r
+ jr l0df6h ;0df0\r
+l0df2h:\r
+ ld a,(de) ;0df2\r
+ call out.hex ;0df3\r
+l0df6h:\r
+ call OUTBL ;0df6\r
+ pop de ;0df9\r
+ pop hl ;0dfa\r
+ pop bc ;0dfb\r
+ ret ;0dfc\r
+\r
+b_0x0DFD_start:\r
+ DC 'A '\r
+ DC 'BC '\r
+ DC 'DE '\r
+ DC 'HL '\r
+ DC 'SP'\r
+ DC 'PC'\r
+ DC 'A'''\r
+ DC 'BC'''\r
+ DC 'DE'''\r
+ DC 'HL'''\r
+ DC 'IX'\r
+ DC 'IY'\r
+ DC 'I'\r
+ DB 0\r
+\r
+b_0x0E1D_start:\r
+ defw reg.a ;0e1d\r
+ defb 000h ;0e1f\r
+ defw reg.c ;0e20\r
+ defb 001h ;0e22\r
+ defw reg.e ;0e23\r
+ defb 001h ;0e25\r
+ defw reg.l ;0e26\r
+ defb 001h ;0e28\r
+ defw reg.sp ;0e29\r
+ defb 001h ;0e2b\r
+ defw reg.pc ;0e2c\r
+ defb 002h ;0e2e\r
+ defw reg.a2 ;0e2f\r
+ defb 000h ;0e31\r
+ defw reg.c2 ;0e32\r
+ defb 001h ;0e34\r
+ defw reg.e2 ;0e35\r
+ defb 001h ;0e37\r
+ defw reg.l2 ;0e38\r
+ defb 001h ;0e3a\r
+ defw reg.ix ;0e3b\r
+ defb 001h ;0e3d\r
+ defw reg.iy ;0e3e\r
+ defb 001h ;0e40\r
+ defw reg.i ;0e41\r
+ dw 0 ;0e43\r
+\r
+CMD.G:\r
+ sub a ;0e45\r
+ ld (TCFLG),a ;0e46\r
+ ld (XA747),a ;0e49\r
+ call EXPR ;0e4c\r
+ jr c,l0e54h ;0e4f\r
+ ld (REG.PC),hl ;0e51\r
+l0e54h:\r
+ call SKIPBL ;0e54\r
+ jp z,l1183h ;0e57\r
+ cp ';' ;0e5a\r
+ jp nz,ERROR ;0e5c\r
+ inc de ;0e5f\r
+ ld a,002h ;0e60\r
+ call sub_0f24h ;0e62\r
+ jp l1183h ;0e65\r
+\r
+sub_0e68h:\r
+ ld b,BP_CNT ;0e68\r
+ ld ix,bp_tab ;0e6a\r
+l0e6eh:\r
+ ld a,(ix+000h) ;0e6e\r
+ and 0f1h ;0e71\r
+ ld (ix+000h),a ;0e73\r
+ call sub_11c5h ;0e76\r
+ ld de,BP_SIZE ;0e79\r
+ add ix,de ;0e7c\r
+ djnz l0e6eh ;0e7e\r
+ ret ;0e80\r
+\r
+CMD.B:\r
+ call SKIPBL ;0e81\r
+ jr z,l0ecbh ;0e84\r
+ inc de ;0e86\r
+ cp 'X' ;0e87\r
+ jr z,l0e91h ;0e89\r
+ dec de ;0e8b\r
+ ld a,001h ;0e8c\r
+ jp sub_0f24h ;0e8e\r
+l0e91h:\r
+ call SKIPBL ;0e91\r
+ jr z,l0ea6h ;0e94\r
+l0e96h:\r
+ call EXPR ;0e96\r
+ jp c,assert_eol ;0e99\r
+ push de ;0e9c\r
+ call sub_0ea7h ;0e9d\r
+ pop de ;0ea0\r
+ call skip_to_nextarg ;0ea1\r
+ jr l0e96h ;0ea4\r
+l0ea6h:\r
+ scf ;0ea6\r
+sub_0ea7h:\r
+ ld b,BP_CNT ;0ea7\r
+ ld ix,bp_tab ;0ea9\r
+l0eadh:\r
+ push af ;0ead\r
+ jr c,l0ebbh ;0eae\r
+ ld e,(ix+002h) ;0eb0\r
+ ld d,(ix+003h) ;0eb3\r
+ call CP.HL.DE ;0eb6\r
+ jr nz,l0ec2h ;0eb9\r
+l0ebbh:\r
+ ld (ix+000h),000h ;0ebb\r
+ call sub_11c5h ;0ebf\r
+l0ec2h:\r
+ ld de,BP_SIZE ;0ec2\r
+ add ix,de ;0ec5\r
+ pop af ;0ec7\r
+ djnz l0eadh ;0ec8\r
+ ret ;0eca\r
+l0ecbh:\r
+ ld b,BP_CNT ;0ecb\r
+ ld ix,bp_tab ;0ecd\r
+l0ed1h:\r
+ bit 0,(ix+000h) ;0ed1\r
+ jr z,l0f1ch ;0ed5\r
+ ld a,'R' ;0ed7\r
+ bit 4,(ix+000h) ;0ed9\r
+ jr nz,l0ee1h ;0edd\r
+ ld a,' ' ;0edf\r
+l0ee1h:\r
+ call OUTCHAR ;0ee1\r
+ call OUTBL ;0ee4\r
+ ld l,(ix+002h) ;0ee7\r
+ ld h,(ix+003h) ;0eea\r
+ call out.hl.@ ;0eed\r
+ call outbl2 ;0ef0\r
+ ld a,':' ;0ef3\r
+ call OUTCHAR ;0ef5\r
+ ld l,(ix+004h) ;0ef8\r
+ ld h,(ix+005h) ;0efb\r
+ call out.hl ;0efe\r
+ ld l,(ix+006h) ;0f01\r
+ ld h,(ix+007h) ;0f04\r
+ ld a,h ;0f07\r
+ or l ;0f08\r
+ jr z,l0f19h ;0f09\r
+ call outbl4 ;0f0b\r
+ ld a,'I' ;0f0e\r
+ call OUTCHAR ;0f10\r
+ call outbl2 ;0f13\r
+ call PSTR ;0f16\r
+l0f19h:\r
+ call CRLF ;0f19\r
+l0f1ch:\r
+ ld de,BP_SIZE ;0f1c\r
+ add ix,de ;0f1f\r
+ djnz l0ed1h ;0f21\r
+ ret ;0f23\r
+\r
+sub_0f24h:\r
+ ld b,a ;0f24\r
+ call SKIPBL ;0f25\r
+ ret z ;0f28\r
+ cp 'R' ;0f29\r
+ jr nz,l0f30h ;0f2b\r
+ inc de ;0f2d\r
+ set 4,b ;0f2e\r
+l0f30h:\r
+ push bc ;0f30\r
+ call EXPR ;0f31\r
+ jp c,ERROR ;0f34\r
+ pop bc ;0f37\r
+ bit 0,b ;0f38\r
+ push bc ;0f3a\r
+ push de ;0f3b\r
+ push hl ;0f3c\r
+ call nz,sub_0ea7h ;0f3d\r
+ pop hl ;0f40\r
+ call sub_0f68h ;0f41\r
+ pop de ;0f44\r
+ ld (ix+002h),l ;0f45\r
+ ld (ix+003h),h ;0f48\r
+ call sub_0f80h ;0f4b\r
+ ld (ix+004h),l ;0f4e\r
+ ld (ix+005h),h ;0f51\r
+ call sub_0f91h ;0f54\r
+ ld (ix+006h),l ;0f57\r
+ ld (ix+007h),h ;0f5a\r
+ call skip_to_nextarg ;0f5d\r
+ pop af ;0f60\r
+ ld (ix+000h),a ;0f61\r
+ and 00fh ;0f64\r
+ jr sub_0f24h ;0f66\r
+sub_0f68h:\r
+ ld b,BP_CNT ;0f68\r
+ ld ix,bp_tab ;0f6a\r
+l0f6eh:\r
+ ld a,(ix+000h) ;0f6e\r
+ and 00fh ;0f71\r
+ ret z ;0f73\r
+ push bc ;0f74\r
+ ld bc,BP_SIZE ;0f75\r
+ add ix,bc ;0f78\r
+ pop bc ;0f7a\r
+ djnz l0f6eh ;0f7b\r
+ jp ERROR ;0f7d\r
+\r
+sub_0f80h:\r
+ call SKIPBL ;0f80\r
+ ld hl,1 ;0f83\r
+ cp 03ah ;0f86\r
+ ret nz ;0f88\r
+ inc de ;0f89\r
+ call EXPR ;0f8a\r
+ jp c,ERROR ;0f8d\r
+ ret ;0f90\r
+sub_0f91h:\r
+ call SKIPBL ;0f91\r
+ cp 049h ;0f94\r
+ ld hl,0 ;0f96\r
+ ret nz ;0f99\r
+ inc de ;0f9a\r
+ call SKIPBL ;0f9b\r
+ push de ;0f9e\r
+ call EXPR ;0f9f\r
+ jp c,ERROR ;0fa2\r
+ ex de,hl ;0fa5\r
+ pop de ;0fa6\r
+ push de ;0fa7\r
+ sbc hl,de ;0fa8\r
+ ld b,h ;0faa\r
+ ld c,l ;0fab\r
+ ld hl,(sexp1) ;0fac\r
+ push hl ;0faf\r
+ add hl,bc ;0fb0\r
+ ld de,sexpbufe ;0fb1\r
+ call CP.HL.DE ;0fb4\r
+ jp nc,ERROR ;0fb7\r
+ pop hl ;0fba\r
+ ld (sexp2),hl ;0fbb\r
+ pop de ;0fbe\r
+ ex de,hl ;0fbf\r
+ ldir ;0fc0\r
+ xor a ;0fc2\r
+ ld (de),a ;0fc3\r
+ inc de ;0fc4\r
+ ex de,hl ;0fc5\r
+ ld (sexp1),hl ;0fc6\r
+ ld hl,(sexp2) ;0fc9\r
+ ret ;0fcc\r
+\r
+bpddtz:\r
+ if ROMSYS\r
+ ld h,ROMEN ;0fcd\r
+ jr z,l0fd2h ;0fcf\r
+ inc h ;0fd1\r
+l0fd2h:\r
+ push hl ;0fd2 save rom enable stat\r
+ endif\r
+ push bc ;0fd3\r
+ push de ;0fd4\r
+ push ix ;0fd5\r
+ push iy ;0fd7\r
+ ld a,i ;0fd9\r
+ ld h,a ;0fdb\r
+ ld l,000h ;0fdc\r
+ push hl ;0fde\r
+ ld a,0f3h ;0fdf DI\r
+ jp po,l0fe6h ;0fe1\r
+ ld a,0fbh ;0fe4 EI\r
+l0fe6h:\r
+ ld (reg.iff),a ;0fe6\r
+ ld hl,ivtab ;0fe9\r
+ ld a,h ;0fec\r
+ ld i,a ;0fed\r
+ call ddtei ;0fef\r
+ ex af,af' ;0ff2\r
+ push af ;0ff3\r
+ exx ;0ff4\r
+ push bc ;0ff5\r
+ push de ;0ff6\r
+ push hl ;0ff7\r
+ call bp.unset ;0ff8\r
+ in0 a,(itc) ;0ffb\r
+ jp p,l1017h ;0ffe\r
+ res TRAP,a ;1001\r
+ out0 (itc),a ;1003\r
+ bit UFO,a ;1006\r
+ jr z,l1011h ;1008\r
+ ld hl,(REG.PC) ;100a\r
+ dec hl ;100d\r
+ ld (REG.PC),hl ;100e\r
+l1011h:\r
+ ld hl,MSG_trap ;1011\r
+ call PSTR ;1014\r
+l1017h:\r
+ ld a,(XBFE8) ;1017\r
+ dec a ;101a\r
+ jr z,l1051h ;101b\r
+ call inchar ;101d\r
+ jr c,l102eh ;1020\r
+ call sub_1059h ;1022\r
+ and a ;1025\r
+ jp z,l1183h ;1026\r
+ and 083h ;1029\r
+ jp z,l284ah ;102b\r
+l102eh:\r
+ call sub_0e68h ;102e\r
+ call prnt_cpustat ;1031\r
+ jp DDTZML ;1034\r
+\r
+MSG_trap:\r
+ DB CR,LF,'Undefined opcode trap'\r
+ DB CR,LF,0\r
+\r
+l1051h:\r
+ ld (XBFE8),a ;1051\r
+ ld c,007h ;1054\r
+ jp l119fh ;1056\r
+sub_1059h:\r
+ ld a,080h ;1059\r
+ ex af,af' ;105b\r
+ sub a ;105c\r
+ ld (XA747),a ;105d\r
+ ld b,BP_CNT ;1060\r
+ ld ix,bp_tab ;1062\r
+l1066h:\r
+ ld a,(ix+000h) ;1066\r
+ and 007h ;1069\r
+ jr z,l107eh ;106b\r
+ ld e,(ix+002h) ;106d\r
+ ld d,(ix+003h) ;1070\r
+ ld hl,(REG.PC) ;1073\r
+ call CP.HL.DE ;1076\r
+ push bc ;1079\r
+ call z,sub_1087h ;107a\r
+ pop bc ;107d\r
+l107eh:\r
+ ld de,BP_SIZE ;107e\r
+ add ix,de ;1081\r
+ djnz l1066h ;1083\r
+ ex af,af' ;1085\r
+ ret ;1086\r
+sub_1087h:\r
+ ex af,af' ;1087\r
+ res 7,a ;1088\r
+ ex af,af' ;108a\r
+ ld e,(ix+006h) ;108b\r
+ ld d,(ix+007h) ;108e\r
+ ld a,d ;1091\r
+ or e ;1092\r
+ ld hl,0ffffh ;1093\r
+ call nz,EXPR ;1096\r
+ ld a,h ;1099\r
+ or l ;109a\r
+ jr z,l10aeh ;109b\r
+ ld e,(ix+004h) ;109d\r
+ ld d,(ix+005h) ;10a0\r
+ dec de ;10a3\r
+ ld a,d ;10a4\r
+ or e ;10a5\r
+ jr z,l10b9h ;10a6\r
+ ld (ix+004h),e ;10a8\r
+ ld (ix+005h),d ;10ab\r
+l10aeh:\r
+ bit 4,(ix+000h) ;10ae\r
+ ret z ;10b2\r
+ ld a,001h ;10b3\r
+ ld (XA747),a ;10b5\r
+ ret ;10b8\r
+l10b9h:\r
+ ex af,af' ;10b9\r
+ or (ix+000h) ;10ba\r
+ ex af,af' ;10bd\r
+ ret\r
+\r
+bp.unset:\r
+ ld b,BP_CNT ;10bf\r
+ ld ix,bp_tab ;10c1\r
+l10c5h:\r
+ bit 5,(ix+000h) ;10c5\r
+ res 5,(ix+000h) ;10c9\r
+ jr z,l10e7h ;10cd\r
+ ld l,(ix+002h) ;10cf\r
+ ld h,(ix+003h) ;10d2\r
+ ld a,(ddtrst) ;10d5\r
+ comst ;10e2\r
+ cp (hl) ;10dc\r
+ comend\r
+ jr nz,l10e7h ;10dd\r
+ ld a,(ix+001h) ;10df\r
+ comst ;10e2\r
+ ld (hl),a ;10e6\r
+ comend\r
+l10e7h:\r
+ res 3,(ix+000h) ;10e7\r
+ ld de,BP_SIZE ;10eb\r
+ add ix,de ;10ee\r
+ djnz l10c5h ;10f0\r
+ ret ;10f2\r
+sub_10f3h:\r
+ ld b,BP_CNT ;10f3\r
+ ld ix,bp_tab ;10f5\r
+l10f9h:\r
+ ld a,(ix+000h) ;10f9\r
+ and 003h ;10fc\r
+ jr z,l110dh ;10fe\r
+ ld e,(ix+002h) ;1100\r
+ ld d,(ix+003h) ;1103\r
+ ld hl,(REG.PC) ;1106\r
+ call CP.HL.DE ;1109\r
+ ret z ;110c\r
+l110dh:\r
+ ld de,BP_SIZE ;110d\r
+ add ix,de ;1110\r
+ djnz l10f9h ;1112\r
+ sub a ;1114\r
+ inc a ;1115\r
+ ret ;1116\r
+sub_1117h:\r
+ call sub_0f68h ;1117\r
+ ld (ix+004h),001h ;111a\r
+ ld (ix+005h),000h ;111e\r
+ ld (ix+002h),l ;1122\r
+ ld (ix+003h),h ;1125\r
+ ld (ix+006h),000h ;1128\r
+ ld (ix+007h),000h ;112c\r
+ ld a,(XBFE8) ;1130\r
+ and a ;1133\r
+ ld a,008h ;1134\r
+ jr nz,l113ah ;1136\r
+ ld a,004h ;1138\r
+l113ah:\r
+ ld (ix+000h),a ;113a\r
+ ret ;113d\r
+\r
+bp.set:\r
+ ld b,BP_CNT ;113e\r
+ ld ix,bp_tab ;1140\r
+l1144h:\r
+ ld a,(ix+000h) ;1144\r
+ and c ;1147\r
+ jr z,l117bh ;1148\r
+ set 5,(ix+000h) ;114a\r
+ ld l,(ix+002h) ;114e\r
+ ld h,(ix+003h) ;1151\r
+\r
+ if 0\r
+\r
+ comst ;1154\r
+ ld a,(hl) ;1158\r
+ comend\r
+ ld (ix+001h),a ;1159\r
+ ld a,(ddtrst) ;115c\r
+ comst ;115f\r
+ ld (hl),a ;1163\r
+ comend\r
+ and 038h ;1164\r
+ ld h,000h ;1166\r
+ ld l,a ;1168\r
+ ld a,0c3h ;1169\r
+ comrep ;116b\r
+ inc hl ;116e\r
+ ld de,bpent ;116f\r
+ ld a,e ;1172\r
+ comrep ;1173\r
+ inc hl ;1176\r
+ ld a,d ;1177\r
+ comrep ;1178\r
+ \r
+ else\r
+\r
+ ld a,(ddtrst) ;115c\r
+ comst ;115f\r
+ ld e,(hl) ;1158\r
+ ld (hl),a ;1163\r
+ comend\r
+ ld (ix+001h),e ;1159\r
+ and 038h ;1164\r
+ ld h,0 ;1166\r
+ ld l,a ;1168\r
+ ld de,bpent ;116f\r
+ comst ;\r
+ ld (hl),0c3h ;1169\r
+ inc hl ;116e\r
+ ld (hl),e ;1172\r
+ inc hl ;1176\r
+ ld (hl),d ;1177\r
+ comend\r
+\r
+ endif\r
+ \r
+l117bh:\r
+ ld de,BP_SIZE ;117b\r
+ add ix,de ;117e\r
+ djnz l1144h ;1180\r
+ ret\r
+ ;1182\r
+l1183h:\r
+ sub a ;1183\r
+ ld (XBFE8),a ;1184\r
+ ld a,(XA747) ;1187\r
+ and a ;118a\r
+ call nz,prnt_cpustat ;118b\r
+ call sub_10f3h ;118e\r
+ ld c,007h ;1191\r
+ jr nz,l119fh ;1193\r
+ ld a,001h ;1195\r
+ ld (XBFE8),a ;1197\r
+ call sub_26e7h ;119a\r
+ ld c,008h ;119d\r
+l119fh:\r
+ call bp.set ;119f\r
+ ld sp,$stack ;11a2 set/restore user cpu state\r
+ pop hl ;11a5\r
+ pop de ;11a6\r
+ pop bc ;11a7\r
+ pop af ;11a8\r
+ exx ;11a9\r
+ ex af,af' ;11aa\r
+ pop af ;11ab\r
+ ld i,a ;11ac\r
+ pop iy ;11ae\r
+ pop ix ;11b0\r
+ pop de ;11b2\r
+ pop bc ;11b3\r
+ if ROMSYS\r
+ pop hl ;11b4\r
+ ld a,l ;11b5\r
+ and M_MWI ;11b6\r
+ ld l,a ;11b8\r
+ di ;11b9\r
+ in0 a,(dcntl) ;11ba\r
+ and ~M_MWI ;11bd\r
+ or l ;11bf\r
+ ld l,a ;11c0\r
+ ld a,h ;11c1\r
+ else\r
+ pop hl\r
+ di\r
+ endif\r
+ jp $go ;11c2 common ram, switch banks and go to user prog\r
+\r
+sub_11c5h:\r
+ ld a,(ix+000h) ;11c5\r
+ and 003h ;11c8\r
+ ret nz ;11ca\r
+ ld e,(ix+006h) ;11cb\r
+ ld d,(ix+007h) ;11ce\r
+ ld a,d ;11d1\r
+ or e ;11d2\r
+ ret z ;11d3\r
+ push bc ;11d4\r
+ ld h,d ;11d5\r
+ ld l,e ;11d6\r
+ sub a ;11d7\r
+ ld (ix+006h),a ;11d8\r
+ ld (ix+007h),a ;11db\r
+ ld bc,0ffffh ;11de\r
+ cpir ;11e1\r
+l11e3h:\r
+ push de ;11e3\r
+ ld de,(sexp1) ;11e4\r
+ call CP.HL.DE ;11e8\r
+ pop de ;11eb\r
+ jr nc,l11f9h ;11ec\r
+ call sub_11ffh ;11ee\r
+l11f1h:\r
+ ld a,(hl) ;11f1\r
+ ldi ;11f2\r
+ and a ;11f4\r
+ jr nz,l11f1h ;11f5\r
+ jr l11e3h ;11f7\r
+l11f9h:\r
+ ld (sexp1),de ;11f9\r
+ pop bc ;11fd\r
+ ret ;11fe\r
+sub_11ffh:\r
+ ld iy,bp_tab ;11ff\r
+ push de ;1203\r
+l1204h:\r
+ ld e,(iy+006h) ;1204\r
+ ld d,(iy+007h) ;1207\r
+ call CP.HL.DE ;120a\r
+ jr z,l1216h ;120d\r
+ ld de,BP_SIZE ;120f\r
+ add iy,de ;1212\r
+ jr l1204h ;1214\r
+l1216h:\r
+ pop de ;1216\r
+ ld (iy+006h),e ;1217\r
+ ld (iy+007h),d ;121a\r
+ ret ;121d\r
+\r
+CMD.Y:\r
+ call get.decdigit ;121e\r
+ jr c,l122fh ;1221\r
+ inc de ;1223\r
+ push af ;1224\r
+ call assert_eol ;1225\r
+ pop af ;1228\r
+ call sub_1248h ;1229\r
+ jp l127ch ;122c\r
+l122fh:\r
+ call assert_eol ;122f\r
+ xor a ;1232\r
+l1233h:\r
+ push af ;1233\r
+ call sub_1248h ;1234\r
+ call outbl4 ;1237\r
+ pop af ;123a\r
+ inc a ;123b\r
+ bit 0,a ;123c\r
+ push af ;123e\r
+ call z,CRLF ;123f\r
+ pop af ;1242\r
+ cp LF ;1243\r
+ jr c,l1233h ;1245\r
+ ret ;1247\r
+\r
+sub_1248h:\r
+ ld c,a ;1248\r
+ ld b,0 ;1249\r
+ add a,'0'+080h ;124b\r
+ ld de,msg.Y+1 ;124d\r
+ ld (de),a ;1250\r
+ dec de ;1251\r
+ ld hl,reg.Y ;1252\r
+ add hl,bc ;1255\r
+ add hl,bc ;1256\r
+ ex de,hl ;1257\r
+ ld c,003h ;1258\r
+ jp l129ah ;125a\r
+\r
+CMD.X:\r
+ call SKIPBL ;125d\r
+ call sub_1315h ;1260\r
+ jp nc,l0d41h ;1263\r
+ call assert_eol ;1266\r
+ ld a,b ;1269\r
+ cp 01fh ;126a\r
+ jr z,l12c6h ;126c\r
+ cp 020h ;126e\r
+ jr z,l12b6h ;1270\r
+ ex de,hl ;1272\r
+ ld hl,b_0x132A_start ;1273\r
+ call sub_0a48h ;1276\r
+l1279h:\r
+ call l129ah ;1279\r
+l127ch:\r
+ call OUTBL ;127c\r
+ push de ;127f\r
+ push bc ;1280\r
+ call INLINE ;1281\r
+ call SKIPBL ;1284\r
+ jr z,l1297h ;1287\r
+ call get_arg ;1289\r
+ ld b,h ;128c\r
+ ld c,l ;128d\r
+ pop af ;128e\r
+ pop hl ;128f\r
+ ld (hl),c ;1290\r
+ bit 0,a ;1291\r
+ ret z ;1293\r
+ inc hl ;1294\r
+ ld (hl),b ;1295\r
+ ret ;1296\r
+l1297h:\r
+ pop af ;1297\r
+ pop hl ;1298\r
+ ret ;1299\r
+l129ah:\r
+ ld b,c ;129a\r
+ call PSTR ;129b\r
+ ld a,'=' ;129e\r
+ call OUTCHAR ;12a0\r
+ ld a,(de) ;12a3\r
+ bit 0,b ;12a4\r
+ jp z,out.hex ;12a6\r
+ ld l,a ;12a9\r
+ inc de ;12aa\r
+ ld a,(de) ;12ab\r
+ dec de ;12ac\r
+ ld h,a ;12ad\r
+ bit 1,b ;12ae\r
+ jp z,out.hl ;12b0\r
+ jp out.hl.@ ;12b3\r
+\r
+l12b6h:\r
+ call prnt_f ;12b6\r
+ ld a,0f3h ;12b9\r
+ ld (reg.iff),a ;12bb\r
+ scf ;12be\r
+ call sub_12d1h ;12bf\r
+ ld (reg.f),a ;12c2\r
+ ret ;12c5\r
+\r
+l12c6h:\r
+ call prnt_f2 ;12c6\r
+ and a ;12c9\r
+ call sub_12d1h ;12ca\r
+ ld (reg.f2),a ;12cd\r
+ ret ;12d0\r
+\r
+sub_12d1h:\r
+ ex af,af' ;12d1\r
+ ld b,000h ;12d2\r
+ call outbl ;12d4\r
+ call assert_eol ;12d7\r
+ call inline ;12da\r
+l12ddh:\r
+ call skipbl ;12dd\r
+ ld a,b ;12e0\r
+ ret z ;12e1\r
+ push bc ;12e2\r
+ ld hl,tab_pr_flags ;12e3\r
+ call lookupch ;12e6\r
+ jp nc,error ;12e9\r
+ ld a,b ;12ec\r
+ cp 008h ;12ed\r
+ jr z,l12feh ;12ef\r
+ inc b ;12f1\r
+ ld a,001h ;12f2\r
+ jr l12f7h ;12f4\r
+l12f6h:\r
+ rlca ;12f6\r
+l12f7h:\r
+ djnz l12f6h ;12f7\r
+ pop bc ;12f9\r
+ or b ;12fa\r
+ ld b,a ;12fb\r
+ jr l12ddh ;12fc\r
+l12feh:\r
+ ex af,af' ;12fe\r
+ jp nc,ERROR ;12ff\r
+ ex af,af' ;1302\r
+ ld a,0FBh ;1303\r
+ ld (reg.iff),a ;1305\r
+ pop bc ;1308\r
+ jr l12ddh ;1309\r
+\r
+tab_pr_flags:\r
+ db 'CNV H ZSE'\r
+ db 0\r
+\r
+sub_1315h:\r
+ call sub_0a0eh ;1315\r
+ ret nc ;1318\r
+ ld a,b ;1319\r
+ add a,b ;131a\r
+ add a,b ;131b\r
+ ld hl,b_0x136C_start ;131c\r
+ call ADD_HL_A ;131f\r
+ ld c,(hl) ;1322\r
+ inc hl ;1323\r
+ ld a,(hl) ;1324\r
+ inc hl ;1325\r
+ ld h,(hl) ;1326\r
+ ld l,a ;1327\r
+ scf ;1328\r
+ ret ;1329\r
+\r
+b_0x132A_start:\r
+ DC 'CBAR'\r
+ DC 'BBR'\r
+ DC 'BC'''\r
+ DC 'DE'''\r
+ DC 'HL'''\r
+ DC 'BC'\r
+ DC 'DE'\r
+ DC 'HL'\r
+ DC 'A'''\r
+ DC 'B'''\r
+ DC 'C'''\r
+ DC 'D'''\r
+ DC 'E'''\r
+ DC 'H'''\r
+ DC 'L'''\r
+ DC 'A'\r
+ DC 'B'\r
+ DC 'C'\r
+ DC 'D'\r
+ DC 'E'\r
+ DC 'H'\r
+ DC 'L'\r
+ DC 'IX'\r
+ DC 'IY'\r
+ DC 'SP'\r
+ DC 'PC'\r
+ DC 'X'\r
+ DC 'Y'\r
+ DC 'S'\r
+ DC 'P'\r
+ DC 'I'\r
+ DC 'F'''\r
+ DC 'F'\r
+ if ROMSYS\r
+ DC 'ROMSEL'\r
+ endif\r
+ DB 0\r
+b_0x136C_start:\r
+ defb 000h ;136c\r
+ defw ucbar ;136d\r
+ defb 000h ;136f\r
+ defw ubbr ;1370\r
+ defb 003h ;1372\r
+ defw reg.c2 ;1373\r
+ defb 003h ;1375\r
+ defw reg.e2 ;1376\r
+ defb 003h ;1378\r
+ defw reg.l2 ;1379\r
+ defb 003h ;137b\r
+ defw reg.c ;137c\r
+ defb 003h ;137e\r
+ defw reg.e ;137f\r
+ defb 003h ;1381\r
+ defw reg.l ;1382\r
+ defb 000h ;1384\r
+ defw reg.a2 ;1385\r
+ defb 000h ;1387\r
+ defw reg.b2 ;1388\r
+ defb 000h ;138a\r
+ defw reg.c2 ;138b\r
+ defb 000h ;138d\r
+ defw reg.d2 ;138e\r
+ defb 000h ;1390\r
+ defw reg.e2 ;1391\r
+ defb 000h ;1393\r
+ defw reg.h2 ;1394\r
+ defb 000h ;1396\r
+ defw reg.l2 ;1397\r
+ defb 000h ;1399\r
+ defw reg.a ;139a\r
+ defb 000h ;139c\r
+ defw reg.b ;139d\r
+ defb 000h ;139f\r
+ defw reg.c ;13a0\r
+ defb 000h ;13a2\r
+ defw reg.d ;13a3\r
+ defb 000h ;13a5\r
+ defw reg.e ;13a6\r
+ defb 000h ;13a8\r
+ defw reg.h ;13a9\r
+ defb 000h ;13ab\r
+ defw reg.l ;13ac\r
+ defb 003h ;13ae\r
+ defw reg.ix ;13af\r
+ defb 003h ;13b1\r
+ defw reg.iy ;13b2\r
+ defb 003h ;13b4\r
+ defw reg.sp ;13b5\r
+ defb 003h ;13b7\r
+ defw reg.pc ;13b8\r
+ defb 003h ;13ba\r
+ defw reg.ix ;13bb\r
+ defb 003h ;13bd\r
+ defw reg.iy ;13be\r
+ defb 003h ;13c0\r
+ defw reg.sp ;13c1\r
+ defb 003h ;13c3\r
+ defw reg.pc ;13c4\r
+ defb 000h ;13c6\r
+ defw reg.i ;13c7\r
+ defb 000h ;13c9\r
+ defw reg.f2 ;13ca\r
+ defb 000h ;13cc\r
+ defw reg.f ;13cd\r
+ if ROMSYS\r
+ defb 000h ;13cf\r
+ defw uromen ;13d0\r
+ endif\r
+CMD.S:\r
+ ld hl,(lst.S) ;13d2\r
+ call get_lastarg_def ;13d5\r
+l13d8h:\r
+ ld (lst.S),hl ;13d8\r
+ call out.hl.@ ;13db\r
+ call OUTBL ;13de\r
+ comst ;13e1\r
+ ld a,(hl) ;13e5\r
+ comend\r
+ call out.hex ;13e6\r
+ call outbl2 ;13e9\r
+ call INLINE ;13ec\r
+ call SKIPBL ;13ef\r
+ inc hl ;13f2\r
+ jr z,l13d8h ;13f3\r
+ dec hl ;13f5\r
+ inc de ;13f6\r
+ cp '.' ;13f7\r
+ jp z,assert_eol ;13f9\r
+ cp '-' ;13fc\r
+ jr nz,l1406h ;13fe\r
+ ld a,(de) ;1400\r
+ or a ;1401\r
+ dec hl ;1402\r
+ jr z,l13d8h ;1403\r
+ inc hl ;1405\r
+l1406h:\r
+ dec de ;1406\r
+ call get_bytes_m ;1407\r
+ jr l13d8h ;140a\r
+\r
+CMD.@:\r
+ call assert_eol ;140c\r
+ ld hl,MSG_at ;140f\r
+ ld de,offs.@ ;1412\r
+ ld c,001h ;1415\r
+ jp l1279h ;1417\r
+MSG_at:\r
+ dc '@'\r
+\r
+CMD.I:\r
+ ld hl,CMD.I ;141b\r
+ ld (CMD_RPT),hl ;141e\r
+ ld hl,(lst.IP) ;1421\r
+ call get_lastarg_def ;1424\r
+ ld (lst.IP),hl ;1427\r
+ ld b,h ;142a\r
+ ld c,l ;142b\r
+ ld a,b ;142c\r
+ or a ;142d\r
+ jr nz,l1442h ;142e\r
+ ld a,c ;1430\r
+ ld hl,ucbar ;1431\r
+ cp cbar ;1434\r
+ jr z,l143fh ;1436\r
+ ld hl,ubbr ;1438\r
+ cp bbr ;143b\r
+ jr nz,l1442h ;143d\r
+l143fh:\r
+ ld a,(hl) ;143f\r
+ jr l1444h ;1440\r
+l1442h:\r
+ in a,(c) ;1442\r
+l1444h:\r
+ push af ;1444\r
+ call out.hex ;1445\r
+ call outbl4 ;1448\r
+ pop af ;144b\r
+ call out.bin.b ;144c\r
+ jp CRLF ;144f\r
+CMD.O:\r
+ ld hl,CMD.O ;1452\r
+ ld (CMD_RPT),hl ;1455\r
+ ld hl,(lst.OD) ;1458\r
+ call get_arg_def ;145b\r
+ ld a,l ;145e\r
+ ld (lst.OD),a ;145f\r
+ push af ;1462\r
+ call skip_to_nextarg ;1463\r
+ ld hl,(lst.OP) ;1466\r
+ call get_lastarg_def ;1469\r
+ ld (lst.OP),hl ;146c\r
+ ld b,h ;146f\r
+ ld c,l ;1470\r
+ ld a,b ;1471\r
+ or a ;1472\r
+ jr nz,l1489h ;1473\r
+ ld a,c ;1475\r
+ ld hl,ucbar ;1476\r
+ cp cbar ;1479\r
+ jr z,l148dh ;147b\r
+ ld hl,ubbr ;147d\r
+ cp bbr ;1480\r
+ jr z,l148dh ;1482\r
+ cp cbr ;1484\r
+ jp z,ERROR ;1486\r
+l1489h:\r
+ pop af ;1489\r
+ out (c),a ;148a\r
+ ret ;148c\r
+l148dh:\r
+ pop af ;148d\r
+ ld (hl),a ;148e\r
+ ret ;148f\r
+\r
+CMD.V:\r
+ call get_arg3 ;1490 get from, size, to\r
+cmp_mem:\r
+ push bc ;1493\r
+ comst ;1494\r
+ ld a,(de) ;1498\r
+ ld b,(hl) ;1499\r
+ comend\r
+ cp b ;149a\r
+ jr z,l14bah ;149b\r
+ ld c,a ;149d\r
+ call out.hl.@ ;149e\r
+ call OUTBL ;14a1\r
+ ld a,b ;14a4\r
+ call out.hex ;14a5\r
+ call outbl2 ;14a8\r
+ ld a,c ;14ab\r
+ call out.hex ;14ac\r
+ call OUTBL ;14af\r
+ ex de,hl ;14b2\r
+ call out.hl.@ ;14b3\r
+ ex de,hl ;14b6\r
+ call CRLF ;14b7\r
+l14bah:\r
+ pop bc ;14ba\r
+ inc hl ;14bb\r
+ inc de ;14bc\r
+ dec bc ;14bd\r
+ ld a,b ;14be\r
+ or c ;14bf\r
+ jr nz,cmp_mem ;14c0\r
+ ret ;14c2\r
+\r
+CMD.M:\r
+ ld a,(de) ;14c3\r
+ cp 'V' ;14c4\r
+ jr nz,bm_nv ;14c6\r
+ inc de ;14c8\r
+bm_nv:\r
+ push af ;14c9 save 'V' flag\r
+ call get_arg3 ;14ca\r
+ push hl ;14cd\r
+ push de ;14ce\r
+ push bc ;14cf\r
+ call CP.HL.DE ;14d0\r
+ jr nc,bm_mvdown ;14d3\r
+ add hl,bc ;14d5\r
+ ex de,hl ;14d6\r
+ add hl,bc ;14d7\r
+ ex de,hl ;14d8\r
+ dec hl ;14d9\r
+ dec de ;14da\r
+ comst ;14db\r
+ lddr ;14df\r
+ comend\r
+ jr bm_done ;14e1\r
+bm_mvdown:\r
+ comst ;14e3\r
+ ldir ;14e7\r
+ comend\r
+bm_done:\r
+ pop bc ;14e9\r
+ pop de ;14ea\r
+ pop hl ;14eb\r
+ pop af ;14ec\r
+ jr z,cmp_mem ;14ed validate?\r
+ ret ;14ef\r
+CMD.H:\r
+ call EXPR ;14f0\r
+ jp c,l173ch ;14f3\r
+ call skip_to_nextarg ;14f6\r
+ push hl ;14f9\r
+ call EXPR ;14fa\r
+ push af ;14fd\r
+ call assert_eol ;14fe\r
+ pop af ;1501\r
+ ex de,hl ;1502\r
+ pop hl ;1503\r
+ jr c,l1511h ;1504\r
+ push hl ;1506\r
+ push de ;1507\r
+ add hl,de ;1508\r
+ call l1511h ;1509\r
+ pop de ;150c\r
+ pop hl ;150d\r
+ and a ;150e\r
+ sbc hl,de ;150f\r
+l1511h:\r
+ call out.hl ;1511 val\r
+ call outbl2 ;1514\r
+ call sub_0928h ;1517 -val\r
+ call outbl4 ;151a\r
+ call out.hl.dec ;151d dec\r
+ call outbl2 ;1520\r
+ call out.hl.decm ;1523 -dec\r
+ call outbl4 ;1526\r
+ call out.bin.w ;1529 bin\r
+ call outbl2 ;152c\r
+ ld a,l ;152f\r
+ call out.ascii ;1530\r
+ jp CRLF ;1533\r
+\r
+CMD.Q:\r
+ ld a,(de) ;1536\r
+ sub 'J' ;1537\r
+ ld (lst.Qj),a ;1539\r
+ jr nz,l153fh ;153c\r
+ inc de ;153e\r
+l153fh:\r
+ call get_arg_range ;153f\r
+ push bc ;1542\r
+ push hl ;1543\r
+ call sub_15a7h ;1544\r
+ pop hl ;1547\r
+l1548h:\r
+ call sub_1594h ;1548\r
+ jr nz,l1562h ;154b\r
+ push bc ;154d\r
+ push hl ;154e\r
+ ld a,(lst.Qj) ;154f\r
+ or a ;1552\r
+ jr nz,l1559h ;1553\r
+ ld bc,-8 ;1555\r
+ add hl,bc ;1558\r
+l1559h:\r
+ ld bc,MEMDUMP_CNT ;1559\r
+ and a ;155c\r
+ call memdump ;155d\r
+ pop hl ;1560\r
+ pop bc ;1561\r
+l1562h:\r
+ inc hl ;1562\r
+ ex (sp),hl ;1563\r
+ dec hl ;1564\r
+ ld a,h ;1565\r
+ or l ;1566\r
+ ex (sp),hl ;1567\r
+ jr nz,l1548h ;1568\r
+ pop bc ;156a\r
+ ret ;156b\r
+\r
+CMD.Z:\r
+ call get_arg_range ;156c\r
+ push bc ;156f\r
+ push hl ;1570\r
+ call sub_15a7h ;1571\r
+ ld a,b ;1574\r
+ pop hl ;1575\r
+ pop bc ;1576\r
+ push hl ;1577\r
+ ex de,hl ;1578\r
+l1579h:\r
+ push af ;1579\r
+ ld a,(hl) ;157a\r
+ comst ;157b\r
+ ld (de),a ;157f\r
+ comend\r
+ pop af ;1580\r
+ inc de ;1581\r
+ cpi ;1582\r
+ jp po,l1592h ;1584\r
+ dec a ;1587\r
+ jr nz,l1579h ;1588\r
+ pop hl ;158a\r
+ comst ;158b\r
+ ldir ;158f\r
+ comend\r
+ ret ;1591\r
+l1592h:\r
+ pop hl ;1592\r
+ ret ;1593\r
+\r
+sub_1594h:\r
+ push hl ;1594\r
+ push de ;1595\r
+ push bc ;1596\r
+l1597h:\r
+ ld a,(de) ;1597\r
+ comst ;1598\r
+ cp (hl) ;159c\r
+ comend\r
+ jr nz,l15a3h ;159d\r
+ inc de ;159f\r
+ inc hl ;15a0\r
+ djnz l1597h ;15a1\r
+l15a3h:\r
+ pop bc ;15a3\r
+ pop de ;15a4\r
+ pop hl ;15a5\r
+ ret ;15a6\r
+\r
+sub_15a7h:\r
+ ld hl,ci.buf+1 ;15a7\r
+ call get_bytes ;15aa\r
+ ld de,ci.buf+1 ;15ad\r
+ and a ;15b0\r
+ sbc hl,de ;15b1\r
+ ld b,l ;15b3\r
+ ret nz ;15b4\r
+ jp ERROR ;15b5\r
+\r
+get_bytes:\r
+ db 0e6h ;15b8 and 037h (clear carry, skip next opc)\r
+get_bytes_m:\r
+ scf\r
+l15bah:\r
+ push af ;15ba\r
+ call skip_to_nextarg ;15bb\r
+ cp 'W' ;15be\r
+ jr nz,l15d9h ;15c0\r
+ inc de ;15c2\r
+ push hl ;15c3\r
+ call sub_0a68h ;15c4\r
+ ex de,hl ;15c7\r
+ pop bc ;15c8\r
+ pop af ;15c9\r
+ push af ;15ca\r
+ push bc ;15cb\r
+ ex (sp),hl ;15cc\r
+ jr nc,l15d3h ;15cd\r
+ comst ;15cf\r
+l15d3h:\r
+ ld (hl),e ;15d3\r
+ comend\r
+ inc hl ;15d4\r
+ ld c,d ;15d5\r
+ pop de ;15d6\r
+ jr l15e5h ;15d7\r
+l15d9h:\r
+ cp '''' ;15d9\r
+ jr z,l15f1h ;15db\r
+ push hl ;15dd\r
+ call EXPR ;15de\r
+ ld c,l ;15e1\r
+ pop hl ;15e2\r
+ jr c,l1626h ;15e3\r
+l15e5h:\r
+ pop af ;15e5\r
+ push af ;15e6\r
+ jr nc,l15edh ;15e7\r
+ comst ;15e9\r
+l15edh:\r
+ ld (hl),c ;15ed\r
+ comend\r
+ inc hl ;15ee\r
+ jr l161eh ;15ef\r
+l15f1h:\r
+ inc de ;15f1\r
+ ld a,(de) ;15f2\r
+ cp '''' ;15f3\r
+ jr z,l1607h ;15f5\r
+ or a ;15f7\r
+ jr z,l1626h ;15f8\r
+l15fah:\r
+ ld c,a ;15fa\r
+ pop af ;15fb\r
+ push af ;15fc\r
+ jr nc,l1603h ;15fd\r
+ comst ;15ff\r
+l1603h:\r
+ ld (hl),c ;1603\r
+ comend\r
+ inc hl ;1604\r
+ jr l15f1h ;1605\r
+l1607h:\r
+ inc de ;1607\r
+ ld a,(de) ;1608\r
+ cp '''' ;1609\r
+ jr z,l15fah ;160b\r
+ cp '.' ;160d\r
+ jr nz,l161eh ;160f\r
+ inc de ;1611\r
+ dec hl ;1612\r
+ pop af ;1613\r
+ push af ;1614\r
+ jr nc,l161bh ;1615\r
+ comst ;1617\r
+l161bh:\r
+ set 7,(hl) ;161b\r
+ comend\r
+ inc hl ;161d\r
+l161eh:\r
+ pop af ;161e\r
+ jr nc,l15bah ;161f\r
+ ld (lst.S),hl ;1621\r
+ jr l15bah ;1624\r
+\r
+l1626h:\r
+ pop af ;1626\r
+ ret nc ;1627\r
+ ld (lst.S),hl ;1628\r
+ ret ;162b\r
+\r
+CMD.D:\r
+ ld hl,CMD.D ;162c\r
+ ld (CMD_RPT),hl ;162f\r
+ ld hl,(lst.D) ;1632\r
+ ld bc,00080h ;1635\r
+ call sub_0a82h ;1638\r
+ scf ;163b\r
+memdump:\r
+ push bc ;163c\r
+ push de ;163d\r
+ push hl ;163e\r
+ ex af,af' ;163f\r
+l1640h:\r
+ call out.hl.@ ;1640\r
+ call z,outbl2 ;1643\r
+ call OUTBL ;1646\r
+ ld de,0 ;1649\r
+l164ch:\r
+ comst ;164c\r
+ ld a,(hl) ;1650\r
+ comend\r
+ inc hl ;1651\r
+ call out.hex ;1652\r
+ call OUTBL ;1655\r
+ dec bc ;1658\r
+ inc e ;1659\r
+ ld a,e ;165a\r
+ cp 010h ;165b\r
+ jr z,l1668h ;165d\r
+ and 003h ;165f\r
+ call z,OUTBL ;1661\r
+ ld a,b ;1664\r
+ or c ;1665\r
+ jr nz,l164ch ;1666\r
+l1668h:\r
+ call OUTBL ;1668\r
+ and a ;166b\r
+ sbc hl,de ;166c\r
+l166eh:\r
+ comst ;166e\r
+ ld a,(hl) ;1672\r
+ comend\r
+ call sub_168fh ;1673\r
+ call OUTCHAR ;1676\r
+ inc hl ;1679\r
+ dec e ;167a\r
+ jr nz,l166eh ;167b\r
+ ex af,af' ;167d\r
+ jr nc,l1683h ;167e\r
+ ld (lst.D),hl ;1680\r
+l1683h:\r
+ ex af,af' ;1683\r
+ call CRLF ;1684\r
+ ld a,b ;1687\r
+ or c ;1688\r
+ jr nz,l1640h ;1689\r
+ pop hl ;168b\r
+ pop de ;168c\r
+ pop bc ;168d\r
+ ret ;168e\r
+sub_168fh:\r
+ and 07fh ;168f\r
+ cp 07fh ;1691\r
+ jr z,l1698h ;1693\r
+ cp 020h ;1695\r
+ ret nc ;1697\r
+l1698h:\r
+ ld a,02eh ;1698\r
+ ret ;169a\r
+\r
+; Read Intel Hex File from console.\r
+\r
+CMD.R:\r
+ ld hl,0 ;169b\r
+ call get_lastarg_def ;169e\r
+ push hl ;16a1\r
+ ld hl,0 ;16a2\r
+ ld (HILOD),hl ;16a5\r
+w_recstart:\r
+ call i.getchar ;16a8\r
+ jr z,l16deh ;16ab\r
+ cp ':' ;16ad\r
+ jr nz,w_recstart ;16af\r
+ ld c,0 ;16b1 init checksum\r
+ call i.gethexbyte ;16b3 record len\r
+ ld b,a ;16b6\r
+ call i.gethexbyte ;16b7 address high\r
+ ld h,a ;16ba\r
+ call i.gethexbyte ;16bb address low\r
+ ld l,a ;16be\r
+ call i.gethexbyte ;16bf record type (ignored)\r
+ ld a,b ;16c2\r
+ and a ;16c3 record len == 0?\r
+ jr z,l16deh ;16c4\r
+l16c6h:\r
+ call i.gethexbyte ;16c6\r
+ pop de ;16c9\r
+ push de ;16ca\r
+ push hl ;16cb\r
+ add hl,de ;16cc\r
+ call i.storebyte ;16cd\r
+ pop hl ;16d0\r
+ inc hl ;16d1\r
+ djnz l16c6h ;16d2\r
+ call i.gethexbyte ;16d4\r
+ ld a,c ;16d7\r
+ and a ;16d8\r
+ jp nz,ERROR ;16d9 exit if checksum error\r
+ jr w_recstart ;16dc next record\r
+l16deh:\r
+ pop hl ;16de\r
+ call i.gethexbyte ;16df\r
+ jp l173fh ;16e2\r
+\r
+i.gethexbyte:\r
+ call sub_16f6h ;16e5\r
+ rlca ;16e8\r
+ rlca ;16e9\r
+ rlca ;16ea\r
+ rlca ;16eb\r
+ ld d,a ;16ec\r
+ call sub_16f6h ;16ed\r
+ add a,d ;16f0\r
+ ld d,a ;16f1\r
+ add a,c ;16f2\r
+ ld c,a ;16f3\r
+ ld a,d ;16f4\r
+ ret ;16f5\r
+\r
+sub_16f6h:\r
+ call i.getchar ;16f6\r
+ jr z,l16ffh ;16f9\r
+ call sub_0d26h ;16fb\r
+ ret nc ;16fe\r
+l16ffh:\r
+ jp ERROR ;16ff\r
+\r
+i.getchar:\r
+ call $ci ;1702\r
+ cp 01ah ;1705\r
+ ret ;1707\r
+\r
+i.storebyte:\r
+ push af ;1708\r
+ push de ;1709\r
+ ld de,TPA ;170a\r
+ call CP.HL.DE ;170d\r
+ jp c,ERROR ;1710\r
+ ld de,$stcka ;1713\r
+ call CP.HL.DE ;1716\r
+ jp nc,ERROR ;1719\r
+ ld de,(HILOD) ;171c\r
+ call CP.HL.DE ;1720\r
+ jr c,l1728h ;1723\r
+ ld (HILOD),hl ;1725\r
+l1728h:\r
+ ld de,(MAXLOD) ;1728\r
+ call CP.HL.DE ;172c\r
+ jr c,l1734h ;172f\r
+ ld (MAXLOD),hl ;1731\r
+l1734h:\r
+ pop de ;1734\r
+ pop af ;1735\r
+ comst ;1736\r
+ ld (hl),a ;173a\r
+ comend\r
+ ret ;173b\r
+\r
+l173ch:\r
+ call assert_eol ;173c\r
+l173fh:\r
+ ld hl,MSG_high ;173f\r
+ call PSTR ;1742\r
+ ld hl,(HILOD) ;1745\r
+ call out.hl ;1748\r
+ ld hl,MSG_max ;174b\r
+ call PSTR ;174e\r
+ ld hl,(MAXLOD) ;1751\r
+ call out.hl ;1754\r
+ jp CRLF ;1757\r
+\r
+MSG_high:\r
+ DC 'High = '\r
+MSG_max:\r
+ DC ' Max = '\r
+\r
+CMD.A:\r
+ ld hl,(lst.A) ;1769\r
+ call get_lastarg_def ;176c\r
+ push hl ;176f\r
+ pop iy ;1770\r
+ ld hl,l17c4h ;1772\r
+ ld (CMD_ERR),hl ;1775\r
+ ld (XB068),sp ;1778\r
+l177ch:\r
+ push iy ;177c\r
+ pop hl ;177e\r
+ ld (lst.A),hl ;177f\r
+ ld (OFFS.pc),hl ;1782\r
+ push hl ;1785\r
+ call sub_1f3fh ;1786\r
+ pop iy ;1789\r
+ ld c,b ;178b\r
+ ld de,(offs.@) ;178c\r
+ ld a,d ;1790\r
+ or e ;1791\r
+ ld b,011h ;1792\r
+ jr z,l1798h ;1794\r
+ ld b,019h ;1796\r
+l1798h:\r
+ call OUTBL ;1798\r
+ ld a,(CON.COL) ;179b\r
+ cp b ;179e\r
+ jr c,l1798h ;179f\r
+ push bc ;17a1\r
+ call INLINE ;17a2\r
+ pop bc ;17a5\r
+ call SKIPBL ;17a6\r
+ cp '.' ;17a9\r
+ ret z ;17ab\r
+ cp '-' ;17ac\r
+ jr nz,l17b6h ;17ae\r
+ ld iy,(XB06C) ;17b0\r
+ jr l177ch ;17b4\r
+l17b6h:\r
+ and a ;17b6\r
+ call nz,sub_17cdh ;17b7\r
+ ld (XB06C),iy ;17ba\r
+ ld b,0 ;17be\r
+ add iy,bc ;17c0\r
+ jr l177ch ;17c2\r
+l17c4h:\r
+ call l07eah ;17c4\r
+ ld sp,(XB068) ;17c7\r
+ jr l177ch ;17cb\r
+\r
+sub_17cdh:\r
+ call SKIPBL ;17cd\r
+ ld hl,t_MNEMONICS ;17d0\r
+ call sub_0a15h ;17d3\r
+ jp nc,ERROR ;17d6\r
+ call SKIPBL ;17d9\r
+ push de ;17dc\r
+ ld a,b ;17dd\r
+ add a,b ;17de\r
+ add a,b ;17df\r
+ ld hl,b_0x17EE_start ;17e0\r
+ call ADD_HL_A ;17e3\r
+ ld e,(hl) ;17e6\r
+ inc hl ;17e7\r
+ ld d,(hl) ;17e8\r
+ inc hl ;17e9\r
+ ld b,(hl) ;17ea\r
+ ex de,hl ;17eb\r
+ pop de ;17ec\r
+ jp (hl) ;17ed\r
+\r
+b_0x17EE_start:\r
+ defw l1b54h ;17ee\r
+\r
+b_0x17F0_start:\r
+ defb 088h ;17f0\r
+\r
+b_0x17F1_start:\r
+ defw l1b74h ;17f1\r
+\r
+b_0x17F3_start:\r
+ defb 080h ;17f3\r
+\r
+b_0x17F4_start:\r
+ defw l1babh ;17f4\r
+\r
+b_0x17F6_start:\r
+ defb 0a0h ;17f6\r
+\r
+b_0x17F7_start:\r
+ defw l1c14h ;17f7\r
+\r
+b_0x17F9_start:\r
+ defb 040h ;17f9\r
+\r
+b_0x17FA_start:\r
+ defw l1c38h ;17fa\r
+\r
+b_0x17FC_start:\r
+ defb 0c4h ;17fc\r
+\r
+b_0x17FD_start:\r
+ defw l1b36h ;17fd\r
+\r
+b_0x17FF_start:\r
+ defb 03fh ;17ff\r
+\r
+b_0x1800_start:\r
+ defw l1babh ;1800\r
+\r
+b_0x1802_start:\r
+ defb 0b8h ;1802\r
+\r
+b_0x1803_start:\r
+ defw gen.opc.ED2 ;1803\r
+\r
+b_0x1805_start:\r
+ defb 0a9h ;1805\r
+\r
+b_0x1806_start:\r
+ defw gen.opc.ED2 ;1806\r
+\r
+b_0x1808_start:\r
+ defb 0b9h ;1808\r
+\r
+b_0x1809_start:\r
+ defw gen.opc.ED2 ;1809\r
+\r
+b_0x180B_start:\r
+ defb 0a1h ;180b\r
+\r
+b_0x180C_start:\r
+ defw gen.opc.ED2 ;180c\r
+\r
+b_0x180E_start:\r
+ defb 0b1h ;180e\r
+\r
+b_0x180F_start:\r
+ defw l1b36h ;180f\r
+\r
+b_0x1811_start:\r
+ defb 02fh ;1811\r
+\r
+b_0x1812_start:\r
+ defw l1b36h ;1812\r
+\r
+b_0x1814_start:\r
+ defb 027h ;1814\r
+\r
+b_0x1815_start:\r
+ defw l1dabh ;1815\r
+\r
+b_0x1817_start:\r
+ defb 005h ;1817\r
+\r
+b_0x1818_start:\r
+ defw l1b36h ;1818\r
+\r
+b_0x181A_start:\r
+ defb 0f3h ;181a\r
+\r
+b_0x181B_start:\r
+ defw l1ca4h ;181b\r
+\r
+b_0x181D_start:\r
+ defb 010h ;181d\r
+\r
+b_0x181E_start:\r
+ defw l1b36h ;181e\r
+\r
+b_0x1820_start:\r
+ defb 0fbh ;1820\r
+\r
+b_0x1821_start:\r
+ defw l1d54h ;1821\r
+\r
+b_0x1823_start:\r
+ defb 0e3h ;1823\r
+\r
+b_0x1824_start:\r
+ defw l1b36h ;1824\r
+\r
+b_0x1826_start:\r
+ defb 0d9h ;1826\r
+\r
+b_0x1827_start:\r
+ defw l1b36h ;1827\r
+\r
+b_0x1829_start:\r
+ defb 076h ;1829\r
+\r
+b_0x182A_start:\r
+ defw l1cbfh ;182a\r
+\r
+b_0x182C_start:\r
+ defb 046h ;182c\r
+\r
+b_0x182D_start:\r
+ defw l1cf8h ;182d\r
+\r
+b_0x182F_start:\r
+ defb 040h ;182f\r
+\r
+b_0x1830_start:\r
+ defw l1dabh ;1830\r
+\r
+b_0x1832_start:\r
+ defb 004h ;1832\r
+\r
+b_0x1833_start:\r
+ defw gen.opc.ED2 ;1833\r
+\r
+b_0x1835_start:\r
+ defb 0aah ;1835\r
+\r
+b_0x1836_start:\r
+ defw gen.opc.ED2 ;1836\r
+\r
+b_0x1838_start:\r
+ defb 0bah ;1838\r
+\r
+b_0x1839_start:\r
+ defw gen.opc.ED2 ;1839\r
+\r
+b_0x183B_start:\r
+ defb 0a2h ;183b\r
+\r
+b_0x183C_start:\r
+ defw gen.opc.ED2 ;183c\r
+\r
+b_0x183E_start:\r
+ defb 0b2h ;183e\r
+\r
+b_0x183F_start:\r
+ defw l1c5eh ;183f\r
+\r
+b_0x1841_start:\r
+ defb 0c2h ;1841\r
+\r
+b_0x1842_start:\r
+ defw l1cabh ;1842\r
+\r
+b_0x1844_start:\r
+ defb 020h ;1844\r
+\r
+b_0x1845_start:\r
+ defw l1934h ;1845\r
+\r
+b_0x1847_start:\r
+ defb 040h ;1847\r
+\r
+b_0x1848_start:\r
+ defw gen.opc.ED2 ;1848\r
+\r
+b_0x184A_start:\r
+ defb 0a8h ;184a\r
+\r
+b_0x184B_start:\r
+ defw gen.opc.ED2 ;184b\r
+\r
+b_0x184D_start:\r
+ defb 0b8h ;184d\r
+\r
+b_0x184E_start:\r
+ defw gen.opc.ED2 ;184e\r
+\r
+b_0x1850_start:\r
+ defb 0a0h ;1850\r
+\r
+b_0x1851_start:\r
+ defw gen.opc.ED2 ;1851\r
+\r
+b_0x1853_start:\r
+ defb 0b0h ;1853\r
+\r
+b_0x1854_start:\r
+ defw gen.opc.ED2 ;1854\r
+\r
+b_0x1856_start:\r
+ defb 044h ;1856\r
+\r
+b_0x1857_start:\r
+ defw l1b36h ;1857\r
+\r
+b_0x1859_start:\r
+ defb 000h ;1859\r
+\r
+b_0x185A_start:\r
+ defw l1babh ;185a\r
+\r
+b_0x185C_start:\r
+ defb 0b0h ;185c\r
+\r
+b_0x185D_start:\r
+ defw gen.opc.ED2 ;185d\r
+\r
+b_0x185F_start:\r
+ defb 0bbh ;185f\r
+\r
+b_0x1860_start:\r
+ defw gen.opc.ED2 ;1860\r
+\r
+b_0x1862_start:\r
+ defb 0b3h ;1862\r
+\r
+b_0x1863_start:\r
+ defw l1d2ch ;1863\r
+\r
+b_0x1865_start:\r
+ defb 041h ;1865\r
+\r
+b_0x1866_start:\r
+ defw gen.opc.ED2 ;1866\r
+\r
+b_0x1868_start:\r
+ defb 0abh ;1868\r
+\r
+b_0x1869_start:\r
+ defw gen.opc.ED2 ;1869\r
+\r
+b_0x186B_start:\r
+ defb 0a3h ;186b\r
+\r
+b_0x186C_start:\r
+ defw l1ce4h ;186c\r
+\r
+b_0x186E_start:\r
+ defb 0c1h ;186e\r
+\r
+b_0x186F_start:\r
+ defw l1ce4h ;186f\r
+\r
+b_0x1871_start:\r
+ defb 0c5h ;1871\r
+\r
+b_0x1872_start:\r
+ defw l1c14h ;1872\r
+\r
+b_0x1874_start:\r
+ defb 080h ;1874\r
+\r
+b_0x1875_start:\r
+ defw l1c50h ;1875\r
+\r
+b_0x1877_start:\r
+ defb 0c0h ;1877\r
+\r
+b_0x1878_start:\r
+ defw gen.opc.ED2 ;1878\r
+\r
+b_0x187A_start:\r
+ defb 04dh ;187a\r
+\r
+b_0x187B_start:\r
+ defw gen.opc.ED2 ;187b\r
+\r
+b_0x187D_start:\r
+ defb 045h ;187d\r
+\r
+b_0x187E_start:\r
+ defw l1bd8h ;187e\r
+\r
+b_0x1880_start:\r
+ defb 010h ;1880\r
+\r
+b_0x1881_start:\r
+ defw l1b36h ;1881\r
+\r
+b_0x1883_start:\r
+ defb 017h ;1883\r
+\r
+b_0x1884_start:\r
+ defw l1bd8h ;1884\r
+\r
+b_0x1886_start:\r
+ defb 000h ;1886\r
+\r
+b_0x1887_start:\r
+ defw l1b36h ;1887\r
+\r
+b_0x1889_start:\r
+ defb 007h ;1889\r
+\r
+b_0x188A_start:\r
+ defw gen.opc.ED2 ;188a\r
+\r
+b_0x188C_start:\r
+ defb 06fh ;188c\r
+\r
+b_0x188D_start:\r
+ defw l1bd8h ;188d\r
+\r
+b_0x188F_start:\r
+ defb 018h ;188f\r
+\r
+b_0x1890_start:\r
+ defw l1b36h ;1890\r
+\r
+b_0x1892_start:\r
+ defb 01fh ;1892\r
+\r
+b_0x1893_start:\r
+ defw l1bd8h ;1893\r
+\r
+b_0x1895_start:\r
+ defb 008h ;1895\r
+\r
+b_0x1896_start:\r
+ defw l1b36h ;1896\r
+\r
+b_0x1898_start:\r
+ defb 00fh ;1898\r
+\r
+b_0x1899_start:\r
+ defw gen.opc.ED2 ;1899\r
+\r
+b_0x189B_start:\r
+ defb 067h ;189b\r
+\r
+b_0x189C_start:\r
+ defw l1cd5h ;189c\r
+\r
+b_0x189E_start:\r
+ defb 0c7h ;189e\r
+\r
+b_0x189F_start:\r
+ defw l1b54h ;189f\r
+\r
+b_0x18A1_start:\r
+ defb 098h ;18a1\r
+\r
+b_0x18A2_start:\r
+ defw l1b36h ;18a2\r
+\r
+b_0x18A4_start:\r
+ defb 037h ;18a4\r
+\r
+b_0x18A5_start:\r
+ defw l1c14h ;18a5\r
+\r
+b_0x18A7_start:\r
+ defb 0c0h ;18a7\r
+\r
+b_0x18A8_start:\r
+ defw l1bd8h ;18a8\r
+\r
+b_0x18AA_start:\r
+ defb 020h ;18aa\r
+\r
+b_0x18AB_start:\r
+ defw l1bd8h ;18ab\r
+\r
+b_0x18AD_start:\r
+ defb 028h ;18ad\r
+\r
+b_0x18AE_start:\r
+ defw l1bd8h ;18ae\r
+\r
+b_0x18B0_start:\r
+ defb 038h ;18b0\r
+\r
+b_0x18B1_start:\r
+ defw l1babh ;18b1\r
+\r
+b_0x18B3_start:\r
+ defb 090h ;18b3\r
+\r
+b_0x18B4_start:\r
+ defw l1babh ;18b4\r
+\r
+b_0x18B6_start:\r
+ defb 0a8h ;18b6\r
+\r
+b_0x18B7_start:\r
+ defw A.IN0 ;18b7\r
+\r
+b_0x18B9_start:\r
+ defb 000h ;18b9\r
+\r
+b_0x18BA_start:\r
+ defw A.MLT ;18ba\r
+\r
+b_0x18BC_start:\r
+ defb 04ch ;18bc\r
+ ld b,e ;18bd\r
+ dec de ;18be\r
+\r
+b_0x18BF_start:\r
+ defb 08bh ;18bf\r
+\r
+b_0x18C0_start:\r
+ defw gen.opc.ED2 ;18c0\r
+\r
+b_0x18C2_start:\r
+ defb 09bh ;18c2\r
+\r
+b_0x18C3_start:\r
+ defw gen.opc.ED2 ;18c3\r
+\r
+b_0x18C5_start:\r
+ defb 083h ;18c5\r
+\r
+b_0x18C6_start:\r
+ defw gen.opc.ED2 ;18c6\r
+\r
+b_0x18C8_start:\r
+ defb 093h ;18c8\r
+\r
+b_0x18C9_start:\r
+ defw l18fdh ;18c9\r
+\r
+b_0x18CB_start:\r
+ defb 001h ;18cb\r
+\r
+b_0x18CC_start:\r
+ defw gen.opc.ED2 ;18cc\r
+\r
+b_0x18CE_start:\r
+ defb 076h ;18ce\r
+\r
+b_0x18CF_start:\r
+ defw l191dh ;18cf\r
+\r
+b_0x18D1_start:\r
+ defb 004h ;18d1\r
+\r
+b_0x18D2_start:\r
+ defw l192ch ;18d2\r
+\r
+b_0x18D4_start:\r
+ defb 074h ;18d4\r
+A.IN0:\r
+ call sub_1e41h ;18d5\r
+ jr nc,l1931h ;18d8\r
+ cp 006h ;18da\r
+ jr z,l1931h ;18dc\r
+ rlca ;18de\r
+ rlca ;18df\r
+ rlca ;18e0\r
+ add a,b ;18e1\r
+ ld b,a ;18e2\r
+ call sub_1ed1h ;18e3\r
+ call sub_1e06h ;18e6\r
+l18e9h:\r
+ call assert_eol ;18e9\r
+ comst ;18ec\r
+ ld (iy+000h),0edh ;18f0\r
+ ld (iy+001h),b ;18f4\r
+ ld (iy+002h),l ;18f7\r
+ comend\r
+ ld c,003h ;18fa\r
+ ret ;18fc\r
+l18fdh:\r
+ call sub_1e06h ;18fd\r
+ call sub_1ed1h ;1900\r
+ call sub_1e41h ;1903\r
+ jr nc,l1931h ;1906\r
+ cp 006h ;1908\r
+ jr z,l1931h ;190a\r
+ rlca ;190c\r
+ rlca ;190d\r
+ rlca ;190e\r
+ add a,b ;190f\r
+ ld b,a ;1910\r
+ jr l18e9h ;1911\r
+A.MLT:\r
+ call sub_1e2eh ;1913\r
+ jr nc,l1931h ;1916\r
+ add a,b ;1918\r
+ ld b,a ;1919\r
+ jp gen.opc.ED2 ;191a\r
+l191dh:\r
+ call sub_1e41h ;191d\r
+ jr nc,l192ah ;1920\r
+ rlca ;1922\r
+ rlca ;1923\r
+ rlca ;1924\r
+ add a,b ;1925\r
+ ld b,a ;1926\r
+ jp gen.opc.ED2 ;1927\r
+l192ah:\r
+ ld b,064h ;192a\r
+l192ch:\r
+ call sub_1e12h ;192c\r
+ jr l18e9h ;192f\r
+l1931h:\r
+ jp ERROR ;1931\r
+l1934h:\r
+ call sub_1e41h ;1934\r
+ jp c,l19bfh ;1937\r
+ call sub_1e68h ;193a\r
+ jp c,l1a64h ;193d\r
+ call sub_1e2eh ;1940\r
+ jp c,l1a93h ;1943\r
+ call sub_1e50h ;1946\r
+ jp c,l1af0h ;1949\r
+ ld a,(de) ;194c\r
+ cp 049h ;194d\r
+ jp z,l1b0ch ;194f\r
+ cp 052h ;1952\r
+ jp z,l1b14h ;1954\r
+ cp 028h ;1957\r
+ jp nz,ERROR ;1959\r
+ inc de ;195c\r
+ call sub_1e2eh ;195d\r
+ jp c,l1b23h ;1960\r
+ call tst_EXPR ;1963\r
+ call sub_1ed8h ;1966\r
+ call sub_1ed1h ;1969\r
+ call sub_1e2eh ;196c\r
+ jr c,l19adh ;196f\r
+ call sub_1e50h ;1971\r
+ jr nc,l1991h ;1974\r
+ ld b,022h ;1976\r
+l1978h:\r
+ call assert_eol ;1978\r
+ ld a,(pfx.IXY) ;197b\r
+l197eh:\r
+ comst ;197e\r
+ ld (iy+000h),a ;1982\r
+ ld (iy+001h),b ;1985\r
+ ld (iy+002h),l ;1988\r
+ ld (iy+003h),h ;198b\r
+ comend\r
+ ld c,004h ;198e\r
+ ret ;1990\r
+l1991h:\r
+ ld a,(de) ;1991\r
+ cp 041h ;1992\r
+ jp nz,ERROR ;1994\r
+ inc de ;1997\r
+ ld b,032h ;1998\r
+l199ah:\r
+ call assert_eol ;199a\r
+ comst ;199d\r
+ ld (iy+000h),b ;19a1\r
+ ld (iy+001h),l ;19a4\r
+ ld (iy+002h),h ;19a7\r
+ comend\r
+ ld c,003h ;19aa\r
+ ret ;19ac\r
+l19adh:\r
+ cp 020h ;19ad\r
+ jr z,l19bbh ;19af\r
+ add a,043h ;19b1\r
+ ld b,a ;19b3\r
+l19b4h:\r
+ call assert_eol ;19b4\r
+ ld a,0edh ;19b7\r
+ jr l197eh ;19b9\r
+l19bbh:\r
+ ld b,022h ;19bb\r
+ jr l199ah ;19bd\r
+l19bfh:\r
+ ld b,a ;19bf\r
+ call sub_1ed1h ;19c0\r
+ call sub_1e41h ;19c3\r
+ jr nc,l19dbh ;19c6\r
+ push af ;19c8\r
+ ld a,b ;19c9\r
+ rlca ;19ca\r
+ rlca ;19cb\r
+ rlca ;19cc\r
+ ld b,a ;19cd\r
+ pop af ;19ce\r
+ add a,b ;19cf\r
+ add a,040h ;19d0\r
+ cp 076h ;19d2\r
+ jp z,ERROR ;19d4\r
+l19d7h:\r
+ ld b,a ;19d7\r
+ jp l1b36h ;19d8\r
+l19dbh:\r
+ call sub_1e68h ;19db\r
+ jr nc,l1a02h ;19de\r
+ ld a,b ;19e0\r
+ rlca ;19e1\r
+ rlca ;19e2\r
+ rlca ;19e3\r
+ add a,046h ;19e4\r
+ cp 076h ;19e6\r
+ jp z,ERROR ;19e8\r
+l19ebh:\r
+ ld b,a ;19eb\r
+ call assert_eol ;19ec\r
+ ld a,(pfx.IXY) ;19ef\r
+ comst ;19f2\r
+ ld (iy+000h),a ;19f6\r
+ ld (iy+001h),b ;19f9\r
+ ld (iy+002h),c ;19fc\r
+ comend\r
+ ld c,003h ;19ff\r
+ ret ;1a01\r
+l1a02h:\r
+ ld a,(de) ;1a02\r
+ cp 'I' ;1a03\r
+ jr z,l1a15h ;1a05\r
+ cp 'R' ;1a07\r
+ jr nz,l1a21h ;1a09\r
+ ld a,b ;1a0b\r
+ cp 007h ;1a0c\r
+ jp nz,ERROR ;1a0e\r
+ ld b,05fh ;1a11\r
+ jr l1a1dh ;1a13\r
+l1a15h:\r
+ ld a,b ;1a15\r
+ cp 007h ;1a16\r
+ jp nz,ERROR ;1a18\r
+ ld b,057h ;1a1b\r
+l1a1dh:\r
+ inc de ;1a1d\r
+ jp gen.opc.ED2 ;1a1e\r
+l1a21h:\r
+ cp '(' ;1a21\r
+ jr z,l1a3fh ;1a23\r
+ call sub_1e12h ;1a25\r
+ ld a,b ;1a28 ld r,nn\r
+ rlca ;1a29\r
+ rlca ;1a2a\r
+ rlca ;1a2b\r
+ add a,006h ;1a2c\r
+l1a2eh:\r
+ ld b,a ;1a2e\r
+l1a2fh:\r
+ call assert_eol ;1a2f\r
+ comst ;1a32\r
+ ld (iy+000h),b ;1a36\r
+ ld (iy+001h),l ;1a39\r
+ comend\r
+ ld c,002h ;1a3c\r
+ ret ;1a3e\r
+l1a3fh:\r
+ inc de ;1a3f\r
+ ld a,b ;1a40\r
+ cp 007h ;1a41\r
+ jp nz,ERROR ;1a43\r
+ call sub_1e2eh ;1a46\r
+ jr nc,l1a59h ;1a49\r
+ cp 030h ;1a4b\r
+ jp nc,ERROR ;1a4d\r
+ add a,00ah ;1a50\r
+ ld b,a ;1a52\r
+ call sub_1ed8h ;1a53\r
+ jp l1b36h ;1a56\r
+l1a59h:\r
+ call tst_EXPR ;1a59\r
+ call sub_1ed8h ;1a5c\r
+ ld b,03ah ;1a5f\r
+ jp l199ah ;1a61\r
+l1a64h:\r
+ call sub_1ed1h ;1a64\r
+ call sub_1e41h ;1a67\r
+ jr nc,l1a76h ;1a6a\r
+ cp 006h ;1a6c\r
+ jp z,ERROR ;1a6e\r
+ add a,070h ;1a71\r
+ jp l19ebh ;1a73\r
+l1a76h:\r
+ call sub_1e12h ;1a76\r
+ call assert_eol ;1a79\r
+ ld a,(pfx.IXY) ;1a7c\r
+ comst ;1a7f\r
+ ld (iy+000h),a ;1a83 dd/fd\r
+ ld (iy+001h),036h ;1a86\r
+ ld (iy+002h),c ;1a8a displacement\r
+ ld (iy+003h),l ;1a8d nn\r
+ comend\r
+ ld c,4 ;1a90\r
+ ret ;1a92\r
+l1a93h:\r
+ ld b,a ;1a93\r
+ call sub_1ed1h ;1a94\r
+ ld hl,t_HL.AF ;1a97\r
+ call sub_0a23h ;1a9a\r
+ jr c,l1abeh ;1a9d\r
+ call sub_1e50h ;1a9f\r
+ jr nc,l1ac7h ;1aa2\r
+ ld a,b ;1aa4\r
+ cp 030h ;1aa5\r
+ jr nz,l1b20h ;1aa7\r
+ ld b,0f9h ;1aa9\r
+l1aabh:\r
+ call assert_eol ;1aab\r
+ ld a,(pfx.IXY) ;1aae\r
+ comst ;1ab1\r
+ ld (iy+000h),a ;1ab5\r
+ ld (iy+001h),b ;1ab8\r
+ comend\r
+ ld c,002h ;1abb\r
+ ret ;1abd\r
+l1abeh:\r
+ ld a,b ;1abe\r
+ cp 030h ;1abf\r
+ jr nz,l1b20h ;1ac1\r
+ ld b,0f9h ;1ac3\r
+ jr l1b36h ;1ac5\r
+l1ac7h:\r
+ ld a,(de) ;1ac7\r
+ cp 028h ;1ac8\r
+ jr nz,l1ae3h ;1aca\r
+ inc de ;1acc\r
+ call tst_EXPR ;1acd\r
+ call sub_1ed8h ;1ad0\r
+ ld a,b ;1ad3\r
+ cp 020h ;1ad4\r
+ jr z,l1adeh ;1ad6\r
+ add a,04bh ;1ad8\r
+ ld b,a ;1ada\r
+ jp l19b4h ;1adb\r
+l1adeh:\r
+ ld b,02ah ;1ade\r
+ jp l199ah ;1ae0\r
+l1ae3h:\r
+ call tst_EXPR ;1ae3\r
+ call assert_eol ;1ae6\r
+ ld a,001h ;1ae9\r
+ add a,b ;1aeb\r
+ ld b,a ;1aec\r
+ jp l199ah ;1aed\r
+l1af0h:\r
+ call sub_1ed1h ;1af0\r
+ ld a,(de) ;1af3\r
+ cp 028h ;1af4\r
+ jr nz,l1b04h ;1af6\r
+ inc de ;1af8\r
+ call tst_EXPR ;1af9\r
+ call sub_1ed8h ;1afc\r
+ ld b,02ah ;1aff\r
+ jp l1978h ;1b01\r
+l1b04h:\r
+ call tst_EXPR ;1b04\r
+ ld b,021h ;1b07\r
+ jp l1978h ;1b09\r
+l1b0ch:\r
+ inc de ;1b0c\r
+ call sub_1ed1h ;1b0d\r
+ ld b,047h ;1b10\r
+ jr l1b1ah ;1b12\r
+l1b14h:\r
+ inc de ;1b14\r
+ call sub_1ed1h ;1b15\r
+ ld b,04fh ;1b18\r
+l1b1ah:\r
+ ld a,(de) ;1b1a\r
+ inc de ;1b1b\r
+ cp 041h ;1b1c\r
+ jr z,gen.opc.ED2 ;1b1e\r
+l1b20h:\r
+ jp ERROR ;1b20\r
+l1b23h:\r
+ cp 020h ;1b23\r
+ jr nc,l1b20h ;1b25\r
+ add a,002h ;1b27\r
+ ld b,a ;1b29\r
+ call sub_1ed8h ;1b2a\r
+ call sub_1ed1h ;1b2d\r
+ ld a,(de) ;1b30\r
+ cp 041h ;1b31\r
+ jr nz,l1b20h ;1b33\r
+ inc de ;1b35\r
+l1b36h:\r
+ call assert_eol ;1b36\r
+ comst ;1b39\r
+ ld (iy+000h),b ;1b3d\r
+ comend\r
+ ld c,001h ;1b40\r
+ ret ;1b42\r
+gen.opc.ED2:\r
+ call assert_eol ;1b43\r
+ comst ;1b46\r
+ ld (iy+000h),0edh ;1b4a\r
+ ld (iy+001h),b ;1b4e\r
+ comend\r
+ ld c,002h ;1b51\r
+ ret ;1b53\r
+l1b54h:\r
+ ld hl,t_HL.AF ;1b54\r
+ call sub_0a23h ;1b57\r
+ jr nc,l1babh ;1b5a\r
+ call sub_1ed1h ;1b5c\r
+ call sub_1e2eh ;1b5f\r
+ jp nc,ERROR ;1b62\r
+ push af ;1b65\r
+ ld a,b ;1b66\r
+ cp 088h ;1b67\r
+ ld b,04ah ;1b69\r
+ jr z,l1b6fh ;1b6b\r
+ ld b,042h ;1b6d\r
+l1b6fh:\r
+ pop af ;1b6f\r
+ add a,b ;1b70\r
+l1b71h:\r
+ ld b,a ;1b71\r
+ jr gen.opc.ED2 ;1b72\r
+l1b74h:\r
+ ld hl,t_HL.AF ;1b74\r
+ call sub_0a23h ;1b77\r
+ jr c,l1b9dh ;1b7a\r
+ call sub_1e50h ;1b7c\r
+ jr nc,l1babh ;1b7f\r
+ call sub_1ed1h ;1b81\r
+ ld hl,t_BC.DE.IX.SP ;1b84\r
+ ld a,(pfx.IXY) ;1b87\r
+ cp 0fdh ;1b8a\r
+ jr nz,l1b91h ;1b8c\r
+ ld hl,t_BC.DE.IY.SP ;1b8e\r
+l1b91h:\r
+ call sub_1e2bh ;1b91\r
+ jp nc,ERROR ;1b94\r
+ add a,009h ;1b97\r
+l1b99h:\r
+ ld b,a ;1b99\r
+ jp l1aabh ;1b9a\r
+l1b9dh:\r
+ call sub_1ed1h ;1b9d\r
+ call sub_1e2eh ;1ba0\r
+ jp nc,ERROR ;1ba3\r
+ add a,009h ;1ba6\r
+ jp l19d7h ;1ba8\r
+l1babh:\r
+ ld a,(de) ;1bab\r
+ cp 041h ;1bac\r
+ jr nz,l1bbbh ;1bae\r
+ push de ;1bb0\r
+ inc de ;1bb1\r
+ call skip_to_nextarg ;1bb2\r
+ jr z,l1bbah ;1bb5\r
+ pop de ;1bb7\r
+ jr l1bbbh ;1bb8\r
+l1bbah:\r
+ pop af ;1bba\r
+l1bbbh:\r
+ call sub_1e41h ;1bbb\r
+ jr c,l1bceh ;1bbe\r
+ call sub_1e68h ;1bc0\r
+ jr c,l1bd2h ;1bc3\r
+ call sub_1e12h ;1bc5\r
+ ld a,b ;1bc8\r
+ add a,046h ;1bc9\r
+ jp l1a2eh ;1bcb\r
+l1bceh:\r
+ add a,b ;1bce\r
+ jp l19d7h ;1bcf\r
+l1bd2h:\r
+ ld a,b ;1bd2\r
+ add a,006h ;1bd3\r
+ jp l19ebh ;1bd5\r
+l1bd8h:\r
+ call sub_1e41h ;1bd8\r
+ jr c,l1c01h ;1bdb\r
+ call sub_1e68h ;1bdd\r
+ jp nc,ERROR ;1be0\r
+ ld a,b ;1be3\r
+ add a,006h ;1be4\r
+ ld b,a ;1be6\r
+l1be7h:\r
+ call assert_eol ;1be7\r
+ ld a,(pfx.IXY) ;1bea\r
+ comst ;1bed\r
+ ld (iy+000h),a ;1bf1\r
+ ld (iy+001h),0cbh ;1bf4\r
+ ld (iy+002h),c ;1bf8\r
+ ld (iy+003h),b ;1bfb\r
+ comend\r
+ ld c,004h ;1bfe\r
+ ret ;1c00\r
+l1c01h:\r
+ add a,b ;1c01\r
+l1c02h:\r
+ ld b,a ;1c02\r
+ call assert_eol ;1c03\r
+ comst ;1c06\r
+ ld (iy+000h),0cbh ;1c0a\r
+ ld (iy+001h),b ;1c0e\r
+ comend\r
+ ld c,002h ;1c11\r
+ ret ;1c13\r
+l1c14h:\r
+ call sub_1de6h ;1c14\r
+ call sub_1ed1h ;1c17\r
+ call sub_1e41h ;1c1a\r
+ jr c,l1c2fh ;1c1d\r
+ call sub_1e68h ;1c1f\r
+ jp nc,ERROR ;1c22\r
+ ld a,l ;1c25\r
+ rlca ;1c26\r
+ rlca ;1c27\r
+ rlca ;1c28\r
+ add a,006h ;1c29\r
+ add a,b ;1c2b\r
+ ld b,a ;1c2c\r
+ jr l1be7h ;1c2d\r
+l1c2fh:\r
+ add a,b ;1c2f\r
+ ld b,a ;1c30\r
+ ld a,l ;1c31\r
+ rlca ;1c32\r
+ rlca ;1c33\r
+ rlca ;1c34\r
+ add a,b ;1c35\r
+ jr l1c02h ;1c36\r
+l1c38h:\r
+ push de ;1c38\r
+ call sub_1eb8h ;1c39\r
+ jr nc,l1c47h ;1c3c\r
+ add a,b ;1c3e\r
+ ld b,a ;1c3f\r
+ call skip_to_nextarg ;1c40\r
+ jr z,l1c49h ;1c43\r
+ pop de ;1c45\r
+ push de ;1c46\r
+l1c47h:\r
+ ld b,0cdh ;1c47\r
+l1c49h:\r
+ pop af ;1c49\r
+ call tst_EXPR ;1c4a\r
+ jp l199ah ;1c4d\r
+l1c50h:\r
+ call sub_1eb8h ;1c50\r
+ jr nc,l1c59h ;1c53\r
+ add a,b ;1c55\r
+ ld b,a ;1c56\r
+ jr l1c5bh ;1c57\r
+l1c59h:\r
+ ld b,0c9h ;1c59\r
+l1c5bh:\r
+ jp l1b36h ;1c5b\r
+l1c5eh:\r
+ push de ;1c5e\r
+ call sub_1eb8h ;1c5f\r
+ jr c,l1c71h ;1c62\r
+l1c64h:\r
+ pop de ;1c64\r
+ ld hl,b_0x1C97_start ;1c65\r
+ call sub_0a15h ;1c68\r
+ jr c,l1c7fh ;1c6b\r
+ ld b,0c3h ;1c6d\r
+ jr l1c79h ;1c6f\r
+l1c71h:\r
+ add a,b ;1c71\r
+ ld b,a ;1c72\r
+ call skip_to_nextarg ;1c73\r
+ jr nz,l1c64h ;1c76\r
+ pop af ;1c78\r
+l1c79h:\r
+ call tst_EXPR ;1c79\r
+ jp l199ah ;1c7c\r
+l1c7fh:\r
+ call assert_eol ;1c7f\r
+ ld a,b ;1c82\r
+ and a ;1c83\r
+ jr nz,l1c8bh ;1c84\r
+ ld b,0e9h ;1c86\r
+ jp l1b36h ;1c88\r
+l1c8bh:\r
+ ld b,0ddh ;1c8b\r
+ dec a ;1c8d\r
+ jr z,l1c92h ;1c8e\r
+ ld b,0fdh ;1c90\r
+l1c92h:\r
+ ld l,0e9h ;1c92\r
+ jp l1a2fh ;1c94\r
+\r
+b_0x1C97_start:\r
+ DC '(HL)'\r
+ DC '(IX)'\r
+ DC '(IY)'\r
+ DB 0\r
+\r
+l1ca4h:\r
+ call skip_to_nextarg ;1ca4\r
+ ld b,010h ;1ca7\r
+ jr l1cb9h ;1ca9\r
+l1cabh:\r
+ call sub_1ebfh ;1cab\r
+ jr c,l1cb4h ;1cae\r
+ ld b,018h ;1cb0\r
+ jr l1cb9h ;1cb2\r
+l1cb4h:\r
+ add a,b ;1cb4\r
+ ld b,a ;1cb5\r
+ call sub_1ed1h ;1cb6\r
+l1cb9h:\r
+ call sub_1defh ;1cb9\r
+ jp l1a2fh ;1cbc\r
+l1cbfh:\r
+ call sub_1e12h ;1cbf\r
+ ld a,l ;1cc2\r
+ cp 003h ;1cc3\r
+ jr nc,l1d23h ;1cc5\r
+ and a ;1cc7\r
+ jr z,l1cd2h ;1cc8\r
+ ld b,056h ;1cca\r
+ cp 001h ;1ccc\r
+ jr z,l1cd2h ;1cce\r
+ ld b,05eh ;1cd0\r
+l1cd2h:\r
+ jp gen.opc.ED2 ;1cd2\r
+l1cd5h:\r
+ call sub_1e12h ;1cd5\r
+ ld a,l ;1cd8\r
+ push af ;1cd9\r
+ add a,b ;1cda\r
+ ld b,a ;1cdb\r
+ pop af ;1cdc\r
+ and 0c7h ;1cdd\r
+ jr nz,l1d23h ;1cdf\r
+ jp l1b36h ;1ce1\r
+l1ce4h:\r
+ call sub_1e50h ;1ce4\r
+ jr c,l1cf2h ;1ce7\r
+ call sub_1e25h ;1ce9\r
+ jr nc,l1d23h ;1cec\r
+ add a,b ;1cee\r
+ jp l19d7h ;1cef\r
+l1cf2h:\r
+ ld a,b ;1cf2\r
+ add a,020h ;1cf3\r
+ jp l1b99h ;1cf5\r
+l1cf8h:\r
+ call sub_1e41h ;1cf8\r
+ jr nc,l1d23h ;1cfb\r
+ cp 006h ;1cfd\r
+ jr z,l1d23h ;1cff\r
+ rlca ;1d01\r
+ rlca ;1d02\r
+ rlca ;1d03\r
+ add a,b ;1d04\r
+ ld b,a ;1d05\r
+ cp 078h ;1d06\r
+ jr nz,l1d1ah ;1d08\r
+ call sub_1ed1h ;1d0a\r
+ call sub_1d26h ;1d0d\r
+ jr c,l1d20h ;1d10\r
+ call sub_1e06h ;1d12\r
+ ld b,0dbh ;1d15\r
+ jp l1a2fh ;1d17\r
+l1d1ah:\r
+ call sub_1ed1h ;1d1a\r
+ call sub_1d26h ;1d1d\r
+l1d20h:\r
+ jp c,gen.opc.ED2 ;1d20\r
+l1d23h:\r
+ jp ERROR ;1d23\r
+sub_1d26h:\r
+ ld hl,t__C_ ;1d26\r
+ jp sub_0a23h ;1d29\r
+l1d2ch:\r
+ call sub_1d26h ;1d2c\r
+ jr nc,l1d44h ;1d2f\r
+ call sub_1ed1h ;1d31\r
+ call sub_1e41h ;1d34\r
+ jr nc,l1d23h ;1d37\r
+ cp 006h ;1d39\r
+ jr z,l1d23h ;1d3b\r
+ rlca ;1d3d\r
+ rlca ;1d3e\r
+ rlca ;1d3f\r
+ add a,b ;1d40\r
+ jp l1b71h ;1d41\r
+l1d44h:\r
+ call sub_1e06h ;1d44\r
+ call sub_1ed1h ;1d47\r
+ cp 041h ;1d4a\r
+ jr nz,l1d23h ;1d4c\r
+ inc de ;1d4e\r
+ ld b,0d3h ;1d4f\r
+ jp l1a2fh ;1d51\r
+l1d54h:\r
+ ld hl,b_0x1D80_start ;1d54\r
+ call sub_0a15h ;1d57\r
+ jp nc,ERROR ;1d5a\r
+ ld c,b ;1d5d\r
+ call assert_eol ;1d5e\r
+ ld b,000h ;1d61\r
+ ld hl,b_0x1DA1_start ;1d63\r
+ add hl,bc ;1d66\r
+ add hl,bc ;1d67\r
+ ld a,(hl) ;1d68\r
+ comst ;1d69\r
+ ld (iy+000h),a ;1d6d\r
+ comend\r
+ ld c,001h ;1d70\r
+ inc hl ;1d72\r
+ ld a,(hl) ;1d73\r
+ and a ;1d74\r
+ ret z ;1d75\r
+ comst ;1d76\r
+ ld (iy+001h),a ;1d7a\r
+ comend\r
+ ld c,002h ;1d7d\r
+ ret ;1d7f\r
+\r
+b_0x1D80_start:\r
+ DC 'AF,AF'''\r
+l1d86h:\r
+ DC 'DE,HL'\r
+ DC '(SP),HL'\r
+ DC '(SP),IX'\r
+ DC '(SP),IY'\r
+ db 000h ;1da0\r
+\r
+b_0x1DA1_start:\r
+ db 008h ;1da1\r
+ db 000h ;1da2\r
+ db 0ebh ;1da3\r
+ db 000h ;1da4\r
+ db 0e3h ;1da5\r
+ db 000h ;1da6\r
+ db 0ddh ;1da7\r
+ db 0e3h ;1da8\r
+ db 0fdh ;1da9\r
+ db 0e3h ;1daa\r
+l1dabh:\r
+ call sub_1e50h ;1dab\r
+ jr c,l1dc6h ;1dae\r
+ call sub_1e2eh ;1db0\r
+ jr c,l1dd2h ;1db3\r
+ call sub_1e41h ;1db5\r
+ jr c,l1ddfh ;1db8\r
+ call sub_1e68h ;1dba\r
+ jp nc,ERROR ;1dbd\r
+ ld a,b ;1dc0\r
+ add a,030h ;1dc1\r
+ jp l19ebh ;1dc3\r
+l1dc6h:\r
+ ld a,b ;1dc6\r
+ ld b,023h ;1dc7\r
+ cp 004h ;1dc9\r
+ jr z,l1dcfh ;1dcb\r
+ ld b,02bh ;1dcd\r
+l1dcfh:\r
+ jp l1aabh ;1dcf\r
+l1dd2h:\r
+ push af ;1dd2\r
+ ld a,b ;1dd3\r
+ ld b,003h ;1dd4\r
+ cp 004h ;1dd6\r
+ jr z,l1ddch ;1dd8\r
+ ld b,00bh ;1dda\r
+l1ddch:\r
+ pop af ;1ddc\r
+ jr l1de2h ;1ddd\r
+l1ddfh:\r
+ rlca ;1ddf\r
+ rlca ;1de0\r
+ rlca ;1de1\r
+l1de2h:\r
+ add a,b ;1de2\r
+ jp l19d7h ;1de3\r
+sub_1de6h:\r
+ call sub_1e12h ;1de6\r
+ ld a,l ;1de9\r
+ cp 008h ;1dea\r
+ jr nc,error1 ;1dec\r
+ ret ;1dee\r
+sub_1defh:\r
+ call tst_EXPR ;1def\r
+ push bc ;1df2\r
+ push iy ;1df3\r
+ pop bc ;1df5\r
+ and a ;1df6\r
+ sbc hl,bc ;1df7\r
+ dec hl ;1df9\r
+ dec hl ;1dfa\r
+ pop bc ;1dfb\r
+ call sub_1e15h ;1dfc\r
+ ld a,h ;1dff\r
+ xor l ;1e00\r
+ bit 7,a ;1e01\r
+ jr nz,error1 ;1e03\r
+ ret ;1e05\r
+sub_1e06h:\r
+ ld a,(de) ;1e06\r
+ cp 028h ;1e07\r
+ jr nz,sub_1e12h ;1e09\r
+ inc de ;1e0b\r
+ call sub_1e12h ;1e0c\r
+ jp sub_1ed8h ;1e0f\r
+\r
+sub_1e12h:\r
+ call tst_EXPR ;1e12\r
+sub_1e15h:\r
+ ld a,h ;1e15\r
+ and a ;1e16\r
+ ret z ;1e17\r
+ inc a ;1e18\r
+ ret z ;1e19\r
+ jr error1 ;1e1a\r
+\r
+tst_EXPR:\r
+ push bc ;1e1c\r
+ call EXPR ;1e1d\r
+ pop bc ;1e20\r
+ ret nc ;1e21\r
+error1:\r
+ jp ERROR ;1e22\r
+sub_1e25h:\r
+ push hl ;1e25\r
+ ld hl,t_BC.DE.HL.AF ;1e26\r
+ jr l1e32h ;1e29\r
+sub_1e2bh:\r
+ push hl ;1e2b\r
+ jr l1e32h ;1e2c\r
+sub_1e2eh:\r
+ push hl ;1e2e\r
+ ld hl,t_BC.DE.HL.SP ;1e2f\r
+l1e32h:\r
+ push bc ;1e32\r
+ call sub_0a15h ;1e33\r
+ jr nc,l1e3eh ;1e36\r
+ ld a,b ;1e38\r
+ rlca ;1e39\r
+ rlca ;1e3a\r
+ rlca ;1e3b\r
+ rlca ;1e3c\r
+ scf ;1e3d\r
+l1e3eh:\r
+ pop bc ;1e3e\r
+ pop hl ;1e3f\r
+ ret ;1e40\r
+sub_1e41h:\r
+ call SKIPBL ;1e41\r
+ push bc ;1e44\r
+ push hl ;1e45\r
+ ld hl,t_BCDEHL_HL_A ;1e46\r
+ call sub_0a15h ;1e49\r
+ ld a,b ;1e4c\r
+ pop hl ;1e4d\r
+ pop bc ;1e4e\r
+ ret ;1e4f\r
+sub_1e50h:\r
+ push hl ;1e50\r
+ push bc ;1e51\r
+ ld hl,t_IX.IY ;1e52\r
+ call sub_0a15h ;1e55\r
+ jr nc,l1e65h ;1e58\r
+ ld a,0ddh ;1e5a\r
+ dec b ;1e5c\r
+ jr nz,l1e61h ;1e5d\r
+ ld a,0fdh ;1e5f\r
+l1e61h:\r
+ ld (pfx.IXY),a ;1e61\r
+ scf ;1e64\r
+l1e65h:\r
+ pop bc ;1e65\r
+ pop hl ;1e66\r
+ ret ;1e67\r
+sub_1e68h:\r
+ push hl ;1e68\r
+ push bc ;1e69\r
+ ld a,(de) ;1e6a\r
+ cp '(' ;1e6b\r
+ jr nz,l1eb4h ;1e6d\r
+ push de ;1e6f\r
+ inc de ;1e70\r
+ ld hl,t_IX.IY ;1e71\r
+ call sub_0a15h ;1e74\r
+ jr nc,l1eb3h ;1e77\r
+ pop af ;1e79\r
+ ld a,0ddh ;1e7a\r
+ dec b ;1e7c\r
+ jr nz,l1e81h ;1e7d\r
+ ld a,0fdh ;1e7f\r
+l1e81h:\r
+ ld (pfx.IXY),a ;1e81\r
+ ld a,(de) ;1e84\r
+ cp '+' ;1e85\r
+ jr z,l1e95h ;1e87\r
+ cp ')' ;1e89\r
+ ld hl,0 ;1e8b\r
+ jr z,l1eadh ;1e8e\r
+ cp '-' ;1e90\r
+ jp nz,ERROR ;1e92\r
+l1e95h:\r
+ push af ;1e95\r
+ inc de ;1e96\r
+ call sub_1e12h ;1e97 get displacement\r
+ pop af ;1e9a\r
+ cp '+' ;1e9b\r
+ jr z,l1ea7h ;1e9d\r
+ ld b,h ;1e9f\r
+ ld c,l ;1ea0\r
+ ld hl,0 ;1ea1\r
+ and a ;1ea4\r
+ sbc hl,bc ;1ea5\r
+l1ea7h:\r
+ ld a,(de) ;1ea7\r
+ cp ')' ;1ea8\r
+ jp nz,ERROR ;1eaa\r
+l1eadh:\r
+ inc de ;1ead\r
+ pop bc ;1eae\r
+ ld c,l ;1eaf\r
+ pop hl ;1eb0\r
+ scf ;1eb1\r
+ ret ;1eb2\r
+l1eb3h:\r
+ pop de ;1eb3\r
+l1eb4h:\r
+ pop bc ;1eb4\r
+ pop hl ;1eb5\r
+ and a ;1eb6\r
+ ret ;1eb7\r
+sub_1eb8h:\r
+ ld hl,t_tstfl_ZCPS ;1eb8\r
+ ld c,007h ;1ebb\r
+ jr l1ec4h ;1ebd\r
+sub_1ebfh:\r
+ ld hl,t_tstfl_ZC ;1ebf\r
+ ld c,003h ;1ec2\r
+l1ec4h:\r
+ push bc ;1ec4\r
+ call sub_0a15h ;1ec5\r
+ ld a,b ;1ec8\r
+ pop bc ;1ec9\r
+ ret nc ;1eca\r
+ and c ;1ecb\r
+ rlca ;1ecc\r
+ rlca ;1ecd\r
+ rlca ;1ece\r
+ scf ;1ecf\r
+ ret ;1ed0\r
+sub_1ed1h:\r
+ call skip_to_nextarg ;1ed1\r
+ ret z ;1ed4\r
+l1ed5h:\r
+ jp ERROR ;1ed5\r
+sub_1ed8h:\r
+ ld a,(de) ;1ed8\r
+ cp 029h ;1ed9\r
+ jr nz,l1ed5h ;1edb\r
+ inc de ;1edd\r
+ ret ;1ede\r
+CMD.L:\r
+ ld hl,CMD.L ;1edf\r
+ ld (CMD_RPT),hl ;1ee2\r
+ call EXPR ;1ee5\r
+ jr nc,l1eedh ;1ee8\r
+ ld hl,(lst.L) ;1eea\r
+l1eedh:\r
+ push hl ;1eed\r
+ pop iy ;1eee\r
+ call skip_to_nextarg ;1ef0\r
+ call sub_0aa5h ;1ef3\r
+ jr nc,l1f17h ;1ef6\r
+ call assert_eol ;1ef8\r
+ ld b,010h ;1efb\r
+l1efdh:\r
+ push bc ;1efd\r
+ push iy ;1efe\r
+ pop hl ;1f00\r
+ push hl ;1f01\r
+ call sub_1f3fh ;1f02\r
+ call CRLF ;1f05\r
+ pop iy ;1f08\r
+ ld c,b ;1f0a\r
+ ld b,000h ;1f0b\r
+ add iy,bc ;1f0d\r
+ ld (lst.L),iy ;1f0f\r
+ pop bc ;1f13\r
+ djnz l1efdh ;1f14\r
+ ret ;1f16\r
+l1f17h:\r
+ call assert_eol ;1f17\r
+ ld h,b ;1f1a\r
+ ld l,c ;1f1b\r
+ ld a,b ;1f1c\r
+ or c ;1f1d\r
+ jr nz,l1f21h ;1f1e\r
+ dec hl ;1f20\r
+l1f21h:\r
+ push hl ;1f21\r
+ push iy ;1f22\r
+ pop hl ;1f24\r
+ push hl ;1f25\r
+ call sub_1f3fh ;1f26\r
+ call CRLF ;1f29\r
+ pop iy ;1f2c\r
+ ld e,b ;1f2e\r
+ ld d,000h ;1f2f\r
+ add iy,de ;1f31\r
+ ld (lst.L),iy ;1f33\r
+ pop hl ;1f37\r
+ and a ;1f38\r
+ sbc hl,de ;1f39\r
+ ret z ;1f3b\r
+ ret c ;1f3c\r
+ jr l1f21h ;1f3d\r
+sub_1f3fh:\r
+ call out.hl.@ ;1f3f\r
+ call z,OUTBL ;1f42\r
+ call OUTBL ;1f45\r
+ sub a ;1f48\r
+ ld (CON.COL),a ;1f49\r
+ call sub_1f77h ;1f4c\r
+ and a ;1f4f\r
+ ret z ;1f50\r
+l1f51h:\r
+ call OUTBL ;1f51\r
+ ld a,(CON.COL) ;1f54\r
+ cp 010h ;1f57\r
+ jr c,l1f51h ;1f59\r
+sub_1f5bh:\r
+ ld de,(offs.@) ;1f5b\r
+ ld a,d ;1f5f\r
+ or e ;1f60\r
+ ret z ;1f61\r
+ ld a,'(' ;1f62\r
+ call OUTCHAR ;1f64\r
+ ld a,'@' ;1f67\r
+ call OUTCHAR ;1f69\r
+ and a ;1f6c\r
+ sbc hl,de ;1f6d\r
+ call out.hl ;1f6f\r
+ ld a,')' ;1f72\r
+ jp OUTCHAR ;1f74\r
+sub_1f77h:\r
+ sub a ;1f77\r
+ ld (XBE03),a ;1f78\r
+ call sub_1f9eh ;1f7b\r
+ jr nc,l1f91h ;1f7e\r
+ push bc ;1f80\r
+ call sub_2581h ;1f81\r
+ ex de,hl ;1f84\r
+ call sub_1fdbh ;1f85\r
+ pop bc ;1f88\r
+ ld a,(XBE03) ;1f89\r
+ ld hl,(XBE01) ;1f8c\r
+ scf ;1f8f\r
+ ret ;1f90\r
+l1f91h:\r
+ ld hl,b_0x1F9B_start ;1f91\r
+ call PSTR ;1f94\r
+ ld b,001h ;1f97\r
+ sub a ;1f99\r
+ ret ;1f9a\r
+\r
+b_0x1F9B_start:\r
+ DC '???'\r
+ \r
+sub_1f9eh:\r
+ sub a ;1f9e\r
+ ld (is.pfx.IXY),a ;1f9f\r
+ comst ;1fa2\r
+ ld a,(iy+000h) ;1fa6\r
+ comend\r
+ cp 0edh ;1fa9\r
+ jp z,disas_pfx.ED ;1fab\r
+ cp 0ddh ;1fae\r
+ jr z,l1fc5h ;1fb0\r
+ cp 0fdh ;1fb2\r
+ jr z,l1fc9h ;1fb4\r
+sub_1fb6h:\r
+ comst ;1fb6\r
+ ld a,(iy+000h) ;1fba\r
+ comend\r
+ cp 0cbh ;1fbd\r
+ jp z,l2061h ;1fbf\r
+ jp l2078h ;1fc2\r
+l1fc5h:\r
+ ld a,001h ;1fc5\r
+ jr l1fcbh ;1fc7\r
+l1fc9h:\r
+ ld a,002h ;1fc9\r
+l1fcbh:\r
+ ld (is.pfx.IXY),a ;1fcb\r
+ call sub_1fdch ;1fce\r
+ ret nc ;1fd1\r
+ push bc ;1fd2\r
+ call sub_1fb6h ;1fd3\r
+ pop af ;1fd6\r
+ add a,b ;1fd7\r
+ ld b,a ;1fd8\r
+ scf ;1fd9\r
+ ret ;1fda\r
+\r
+sub_1fdbh:\r
+ jp (hl) ;1fdb\r
+\r
+sub_1fdch:\r
+ inc iy ;1fdc\r
+ ld hl,b_0x2011_start ;1fde\r
+ call sub_20bbh ;1fe1\r
+ ld b,002h ;1fe4\r
+ ret c ;1fe6\r
+ ld hl,l202ch ;1fe7\r
+ call sub_20bbh ;1fea\r
+ ld b,001h ;1fed\r
+ ret c ;1fef\r
+ comst ;1ff0\r
+ ld a,(iy+000h) ;1ff4\r
+ comend\r
+ cp 0cbh ;1ff7\r
+ jr nz,l200fh ;1ff9\r
+ comst ;1ffb\r
+ ld a,(iy+002h) ;1fff\r
+ comend\r
+ cp 036h ;2002\r
+ ret z ;2004\r
+ and 007h ;2005\r
+ cp 006h ;2007\r
+ jr nz,l200fh ;2009\r
+ ld b,002h ;200b\r
+ scf ;200d\r
+ ret ;200e\r
+l200fh:\r
+ and a ;200f\r
+ ret ;2010\r
+\r
+b_0x2011_start:\r
+ db 034h ;2011\r
+ db 035h ;2012\r
+ db 036h ;2013\r
+ db 046h ;2014\r
+ db 04eh ;2015\r
+ db 056h ;2016\r
+ db 05eh ;2017\r
+ db 066h ;2018\r
+ db 06eh ;2019\r
+ db 070h ;201a\r
+ db 071h ;201b\r
+ db 072h ;201c\r
+ db 073h ;201d\r
+ db 074h ;201e\r
+ db 075h ;201f\r
+ db 076h ;2020\r
+ db 077h ;2021\r
+ db 07eh ;2022\r
+ db 086h ;2023\r
+ db 08eh ;2024\r
+ db 096h ;2025\r
+ db 09eh ;2026\r
+ db 0a6h ;2027\r
+ db 0aeh ;2028\r
+ db 0b6h ;2029\r
+ db 0beh ;202a\r
+ db 000h ;202b\r
+l202ch:\r
+ db 009h ;202c\r
+ db 019h ;202d\r
+ db 021h ;202e\r
+ db 022h ;202f\r
+ db 023h ;2030\r
+ db 029h ;2031\r
+ db 02ah ;2032\r
+ db 02bh ;2033\r
+ db 039h ;2034\r
+ db 0e1h ;2035\r
+ db 0e3h ;2036\r
+ db 0e5h ;2037\r
+ db 0e9h ;2038\r
+ db 0f9h ;2039\r
+ db 000h ;203a\r
+\r
+disas_pfx.ED:\r
+ inc iy ;203b\r
+ ld hl,b_0x2200_start ;203d\r
+ call sub_209dh ;2040\r
+ ld b,002h ;2043\r
+ ret c ;2045\r
+ ld hl,l2235h ;2046\r
+ call lookup_opc ;2049\r
+ ld b,002h ;204c\r
+ ret c ;204e\r
+ ld hl,l228bh ;204f\r
+ call lookup_opc ;2052\r
+ ld b,003h ;2055\r
+ ret c ;2057\r
+ ld hl,l22b4h ;2058\r
+ call lookup_opc ;205b\r
+ ld b,004h ;205e\r
+ ret ;2060\r
+l2061h:\r
+ push iy ;2061\r
+ inc iy ;2063\r
+ ld a,(is.pfx.IXY) ;2065\r
+ and a ;2068\r
+ jr z,l206dh ;2069\r
+ inc iy ;206b\r
+l206dh:\r
+ ld hl,l22c9h ;206d\r
+ call lookup_opc ;2070\r
+ pop iy ;2073\r
+ ld b,002h ;2075\r
+ ret ;2077\r
+l2078h:\r
+ ld hl,b_0x218B_start ;2078\r
+ call lookup_opc ;207b\r
+ ld b,002h ;207e\r
+ ret c ;2080\r
+ ld hl,b_0x20ED_start ;2081\r
+ call sub_209dh ;2084\r
+ ld b,001h ;2087\r
+ ret c ;2089\r
+ ld hl,b_0x2108_start ;208a\r
+ call lookup_opc ;208d\r
+ ld b,001h ;2090\r
+ ret c ;2092\r
+ ld hl,b_0x21D2_start ;2093\r
+ call lookup_opc ;2096\r
+ ret nc ;2099\r
+ ld b,003h ;209a\r
+ ret ;209c\r
+\r
+sub_209dh:\r
+ ld a,(hl) ;209d\r
+ cp 0ffh ;209e\r
+ ret z ;20a0\r
+ comst ;20a1\r
+ cp (iy+000h) ;20a5\r
+ comend\r
+ jr z,l20aeh ;20a8\r
+ inc hl ;20aa\r
+ inc hl ;20ab\r
+ jr sub_209dh ;20ac\r
+l20aeh:\r
+ inc hl ;20ae\r
+ ld c,(hl) ;20af\r
+ ld hl,t_MNEMONICS ;20b0\r
+ ld b,000h ;20b3\r
+ add hl,bc ;20b5\r
+ ld de,l230bh ;20b6\r
+ scf ;20b9\r
+ ret ;20ba\r
+sub_20bbh:\r
+ ld a,(hl) ;20bb\r
+ and a ;20bc\r
+ ret z ;20bd\r
+ inc hl ;20be\r
+ comst ;20bf\r
+ cp (iy+000h) ;20c3\r
+ comend\r
+ jr nz,sub_20bbh ;20c6\r
+ scf ;20c8\r
+ ret ;20c9\r
+\r
+lookup_opc:\r
+ comst ;20ca\r
+ ld a,(iy+000h) ;20ce\r
+ comend\r
+ and (hl) ;20d1\r
+ inc hl ;20d2\r
+ cp (hl) ;20d3\r
+ jr z,l20dfh ;20d4\r
+ inc hl ;20d6\r
+ inc hl ;20d7\r
+ inc hl ;20d8\r
+ inc hl ;20d9\r
+ ld a,(hl) ;20da\r
+ and a ;20db\r
+ jr nz,lookup_opc ;20dc\r
+ ret ;20de\r
+l20dfh:\r
+ inc hl ;20df\r
+ ld c,(hl) ;20e0\r
+ inc hl ;20e1\r
+ ld e,(hl) ;20e2\r
+ inc hl ;20e3\r
+ ld d,(hl) ;20e4\r
+ ld hl,t_MNEMONICS ;20e5\r
+ ld b,000h ;20e8\r
+ add hl,bc ;20ea\r
+ scf ;20eb\r
+ ret ;20ec\r
+\r
+b_0x20ED_start: ; 1 byte opcodes (no parameters)\r
+ db 076h ;20ed halt\r
+ db 039h ;20ee \r
+ db 0d9h ;20ef exx\r
+ db 036h ;20f0\r
+ db 0f3h ;20f1 di\r
+ db 02ch ;20f2\r
+ db 0fbh ;20f3 ei\r
+ db 032h ;20f4\r
+ db 000h ;20f5 nop\r
+ db 069h ;20f6\r
+ db 007h ;20f7 rlca\r
+ db 09eh ;20f8\r
+ db 00fh ;20f9 rrca\r
+ db 0adh ;20fa\r
+ db 017h ;20fb rla\r
+ db 098h ;20fc\r
+ db 01fh ;20fd rra\r
+ db 0a7h ;20fe\r
+ db 027h ;20ff daa\r
+ db 026h ;2100\r
+ db 02fh ;2101 cpl\r
+ db 023h ;2102\r
+ db 037h ;2103 scf\r
+ db 0bah ;2104\r
+ db 03fh ;2105 ccf\r
+ db 010h ;2106\r
+ db 0ffh ;2107 EOT\r
+\r
+b_0x2108_start: ; 1 byte opcodes\r
+ defb 0c0h ;2108 ld r,r\r
+ defb 040h ;2109\r
+ defb 056h ;210a\r
+ defw l22fch ;210b\r
+\r
+ defb 0f8h ;210d add a,r\r
+ defb 080h ;210e\r
+ defb 003h ;210f\r
+ defw l2305h ;2110\r
+\r
+ defb 0f8h ;2112 adc a,r\r
+ defb 088h ;2113\r
+ defb 000h ;2114\r
+ defw l2305h ;2115\r
+\r
+ defb 0f8h ;2117\r
+ defb 090h ;2118\r
+ defb 0c9h ;2119\r
+ defw l24ebh ;211a\r
+\r
+ defb 0f8h ;211c\r
+ defb 098h ;211d\r
+ defb 0b7h ;211e\r
+ defw l2305h ;211f\r
+\r
+ defb 0f8h ;2121\r
+ defb 0a0h ;2122\r
+ defb 006h ;2123\r
+ defw l24ebh ;2124\r
+\r
+ defb 0f8h ;2126\r
+ defb 0a8h ;2127\r
+ defb 0cch ;2128\r
+ defw l24ebh ;2129\r
+\r
+ defb 0f8h ;212b\r
+ defb 0b0h ;212c\r
+ defb 06ch ;212d\r
+ defw l24ebh ;212e\r
+\r
+ defb 0f8h ;2130\r
+ defb 0b8h ;2131\r
+ defb 013h ;2132\r
+ defw l24ebh ;2133\r
+\r
+ defb 0c7h ;2135\r
+ defb 0c0h ;2136 ret cc\r
+ defb 08bh ;2137\r
+ defw l2561h ;2138\r
+\r
+ defb 0c7h ;213a rst \r
+ defb 0c7h ;213b\r
+ defb 0b4h ;213c\r
+ defw l231eh ;213d\r
+\r
+ defb 0ffh ;213f ret\r
+ defb 0c9h ;2140\r
+ defb 08bh ;2141\r
+ defw l230bh ;2142\r
+\r
+ defb 0cfh ;2144 pop rr\r
+ defb 0c1h ;2145\r
+ defb 081h ;2146\r
+ defw l2546h ;2147\r
+\r
+ defb 0cfh ;2149 push rr\r
+ defb 0c5h ;214a\r
+ defb 084h ;214b\r
+ defw l2546h ;214c\r
+\r
+ defb 0ffh ;214e ex (sp),hl\r
+ defb 0e3h ;214f\r
+ defb 034h ;2150\r
+ defw l232ah ;2151\r
+\r
+ defb 0ffh ;2153 jp (hl)\r
+ defb 0e9h ;2154\r
+ defb 052h ;2155\r
+ defw l2338h ;2156\r
+\r
+ defb 0ffh ;2158 ex de,hl\r
+ defb 0ebh ;2159\r
+ defb 034h ;215a\r
+ defw l2345h ;215b\r
+\r
+ defb 0ffh ;215d ld sp,hl\r
+ defb 0f9h ;215e\r
+ defb 056h ;215f\r
+ defw l234bh ;2160\r
+\r
+ defb 0cfh ;2162 inc rr\r
+ defb 003h ;2163\r
+ defb 041h ;2164\r
+ defw l254bh ;2165\r
+\r
+ defb 0cfh ;2167 dec rr\r
+ defb 00bh ;2168\r
+ defb 029h ;2169\r
+ defw l254bh ;216a\r
+\r
+ defb 0c7h ;216c inc r\r
+ defb 004h ;216d\r
+ defb 041h ;216e\r
+ defw l24dfh ;216f\r
+\r
+ defb 0c7h ;2171 dec r\r
+ defb 005h ;2172\r
+ defb 029h ;2173\r
+ defw l24dfh ;2174\r
+\r
+ defb 0ffh ;2176 ex af,af'\r
+ defb 008h ;2177\r
+ defb 034h ;2178\r
+ defw l2357h ;2179\r
+\r
+ defb 0cfh ;217b add hl,rr\r
+ defb 009h ;217c\r
+ defb 003h ;217d\r
+ defw l235dh ;217e\r
+\r
+ defb 0efh ;2180 ld (rr),a ;rr=bc,de\r
+ defb 002h ;2181\r
+ defb 056h ;2182\r
+ defw l2366h ;2183\r
+\r
+ defb 0efh ;2185 ld a,(rr) ;rr=bc,de\r
+ defb 00ah ;2186\r
+ defb 056h ;2187\r
+ defw l236fh ;2188\r
+\r
+ defb 000h ;218a EOT\r
+\r
+b_0x218B_start: ; 2 byte opdodes\r
+ defb 0c7h ;218b ld r,nn\r
+ defb 006h ;218c\r
+ defb 056h ;218d\r
+ defw l2384h ;218e\r
+\r
+ defb 0ffh ;2190 add a,nn\r
+ defb 0c6h ;2191\r
+ defb 003h ;2192\r
+ defw l237fh ;2193\r
+\r
+ defb 0ffh ;2195 adc a,nn\r
+ defb 0ceh ;2196\r
+ defb 000h ;2197\r
+ defw l237fh ;2198\r
+\r
+ defb 0ffh ;219a sub a,nn\r
+ defb 0d6h ;219b\r
+ defb 0c9h ;219c\r
+ defw l2397h ;219d\r
+\r
+ defb 0ffh ;219f\r
+ defb 0deh ;21a0\r
+ defb 0b7h ;21a1\r
+ defw l237fh ;21a2\r
+\r
+ defb 0ffh ;21a4 and a,nn\r
+ defb 0e6h ;21a5\r
+ defb 006h ;21a6\r
+ defw l2397h ;21a7\r
+\r
+ defb 0ffh ;21a9\r
+ defb 0eeh ;21aa\r
+ defb 0cch ;21ab\r
+ defw l2397h ;21ac\r
+\r
+ defb 0ffh ;21ae\r
+ defb 0f6h ;21af\r
+ defb 06ch ;21b0\r
+ defw l2397h ;21b1\r
+\r
+ defb 0ffh ;21b3 cp a,nn\r
+ defb 0feh ;21b4\r
+ defb 013h ;21b5\r
+ defw l2397h ;21b6\r
+\r
+ defb 0ffh ;21b8 djnz\r
+ defb 010h ;21b9\r
+ defb 02eh ;21ba\r
+ defw l23b0h ;21bb\r
+\r
+ defb 0ffh ;21bd jr\r
+ defb 018h ;21be\r
+ defb 054h ;21bf\r
+ defw l23b0h ;21c0\r
+\r
+ defb 0e7h ;21c2 jr,cc\r
+ defb 020h ;21c3\r
+ defb 054h ;21c4\r
+ defw l23a1h ;21c5\r
+\r
+ defb 0ffh ;21c7\r
+ defb 0d3h ;21c8 out (nn),a\r
+ defb 076h ;21c9\r
+ defw l23d5h ;21ca\r
+\r
+ defb 0ffh ;21cc in a,(nn)\r
+ defb 0dbh ;21cd\r
+ defb 03fh ;21ce\r
+ defw l23c3h ;21cf\r
+\r
+ defb 000h ;21d1 EOT\r
+\r
+b_0x21D2_start: ; 3 byte opcodes\r
+ defb 0c7h ;21d2\r
+ defb 0c2h ;21d3\r
+ defb 052h ;21d4\r
+ defw l23e0h ;21d5\r
+\r
+ defb 0c7h ;21d7\r
+ defb 0c4h ;21d8\r
+ defb 00ch ;21d9\r
+ defw l23e0h ;21da\r
+\r
+ defb 0cfh ;21dc\r
+ defb 001h ;21dd\r
+ defb 056h ;21de\r
+ defw l23fch ;21df\r
+\r
+ defb 0ffh ;21e1\r
+ defb 0c3h ;21e2\r
+ defb 052h ;21e3\r
+ defw l23e6h ;21e4\r
+\r
+ defb 0ffh ;21e6\r
+ defb 0cdh ;21e7\r
+ defb 00ch ;21e8\r
+ defw l23e6h ;21e9\r
+\r
+ defb 0ffh ;21eb\r
+ defb 022h ;21ec\r
+ defb 056h ;21ed\r
+ defw l2404h ;21ee\r
+\r
+ defb 0ffh ;21f0\r
+ defb 02ah ;21f1\r
+ defb 056h ;21f2\r
+ defw l240dh ;21f3\r
+\r
+ defb 0ffh ;21f5\r
+ defb 032h ;21f6\r
+ defb 056h ;21f7\r
+ defw l2416h ;21f8\r
+\r
+ defb 0ffh ;21fa\r
+ defb 03ah ;21fb\r
+ defb 056h ;21fc\r
+ defw l2421h ;21fd\r
+\r
+ defb 000h ;21ff\r
+\r
+b_0x2200_start: ; prefix ED + 1 byte opcode\r
+ defb 044h ;2200 neg\r
+ defb 066h ;2201\r
+ defb 045h ;2202 retn\r
+ defb 092h ;2203\r
+ defb 04dh ;2204 reti\r
+ defb 08eh ;2205\r
+ defb 067h ;2206 rrd\r
+ defb 0b1h ;2207\r
+ defb 06fh ;2208 rld\r
+ defb 0a2h ;2209\r
+ defb 0a0h ;220a ldi\r
+ defb 05fh ;220b\r
+ defb 0a1h ;220c\r
+ defb 01ch ;220d\r
+ defb 0a2h ;220e\r
+ defb 04bh ;220f\r
+ defb 0a3h ;2210\r
+ defb 07dh ;2211\r
+ defb 0a8h ;2212 ldd\r
+ defb 058h ;2213\r
+ defb 0a9h ;2214\r
+ defb 015h ;2215\r
+ defb 0aah ;2216\r
+ defb 044h ;2217\r
+ defb 0abh ;2218\r
+ defb 079h ;2219\r
+ defb 0b0h ;221a ldir\r
+ defb 062h ;221b\r
+ defb 0b1h ;221c\r
+ defb 01fh ;221d\r
+ defb 0b2h ;221e\r
+ defb 04eh ;221f\r
+ defb 0b3h ;2220\r
+ defb 072h ;2221\r
+ defb 0b8h ;2222 lddr\r
+ defb 05bh ;2223\r
+ defb 0b9h ;2224\r
+ defb 018h ;2225\r
+ defb 0bah ;2226\r
+ defb 047h ;2227\r
+ defb 0bbh ;2228\r
+ defb 06eh ;2229\r
+ defb 08bh ;222a otdm\r
+ defb 0d5h ;222b\r
+ defb 09bh ;222c otdmr\r
+ defb 0d9h ;222d\r
+ defb 083h ;222e otim\r
+ defb 0deh ;222f\r
+ defb 093h ;2230 otimr\r
+ defb 0e2h ;2231\r
+ defb 076h ;2232 slp\r
+ defb 0ebh ;2233\r
+ defb 0ffh ;2234 EOT\r
+ \r
+l2235h:\r
+ defb 0e7h ;2235 in r,(c) ;r=bcde\r
+ defb 040h ;2236\r
+ defb 03fh ;2237\r
+ defw l2455h ;2238\r
+\r
+ defb 0f7h ;223a in r,(c) ;r=hl\r
+ defb 060h ;223b\r
+ defb 03fh ;223c\r
+ defw l2455h ;223d\r
+\r
+ defb 0ffh ;223f in r,(c) ;r=a\r
+ defb 078h ;2240\r
+ defb 03fh ;2241\r
+ defw l2455h ;2242\r
+\r
+ defb 0e7h ;2244\r
+ defb 041h ;2245\r
+ defb 076h ;2246\r
+ defw l2461h ;2247\r
+\r
+ defb 0f7h ;2249\r
+ defb 061h ;224a\r
+ defb 076h ;224b\r
+ defw l2461h ;224c\r
+\r
+ defb 0ffh ;224e out (c),r ;r=a\r
+ defb 079h ;224f\r
+ defb 076h ;2250\r
+ defw l2461h ;2251\r
+\r
+ defb 0cfh ;2253 sbc hl,rr\r
+ defb 042h ;2254\r
+ defb 0b7h ;2255\r
+ defw l246dh ;2256\r
+\r
+ defb 0cfh ;2258 adc hl,rr\r
+ defb 04ah ;2259\r
+ defb 000h ;225a\r
+ defw l246dh ;225b\r
+\r
+ defb 0ffh ;225d im 0\r
+ defb 046h ;225e\r
+ defb 03dh ;225f\r
+ defw l2427h ;2260\r
+\r
+ defb 0ffh ;2262 im 1\r
+ defb 056h ;2263\r
+ defb 03dh ;2264\r
+ defw l242bh ;2265\r
+\r
+ defb 0ffh ;2267 im 2\r
+ defb 05eh ;2268\r
+ defb 03dh ;2269\r
+ defw l242fh ;226a\r
+\r
+ defb 0ffh ;226c ld i,a\r
+ defb 047h ;226d\r
+ defb 056h ;226e\r
+ defw l2434h ;226f\r
+\r
+ defb 0ffh ;2271\r
+ defb 057h ;2272\r
+ defb 056h ;2273\r
+ defw l2439h ;2274\r
+\r
+ defb 0ffh ;2276\r
+ defb 04fh ;2277\r
+ defb 056h ;2278\r
+ defw l243eh ;2279\r
+\r
+ defb 0ffh ;227b\r
+ defb 05fh ;227c\r
+ defb 056h ;227d\r
+ defw l2443h ;227e\r
+\r
+ defb 0cfh ;2280 mlt rr\r
+ defb 04ch ;2281\r
+ defb 0d2h ;2282\r
+ defw l254bh ;2283\r
+\r
+ defb 0c7h ;2285 tst r\r
+ defb 004h ;2286\r
+ defb 0eeh ;2287\r
+ defw l24dfh ;2288\r
+\r
+ defb 000h ;228a\r
+\r
+l228bh:\r
+ defb 0e7h ;228b\r
+ defb 000h ;228c\r
+ defb 0cfh ;228d\r
+\r
+b_0x228E_start:\r
+ defw l230ch ;228e\r
+\r
+b_0x2290_start:\r
+ defb 0f7h ;2290\r
+ defb 020h ;2291\r
+ defb 0cfh ;2292\r
+\r
+b_0x2293_start:\r
+ defw l230ch ;2293\r
+\r
+b_0x2295_start:\r
+ defb 0ffh ;2295\r
+ defb 038h ;2296\r
+ defb 0cfh ;2297\r
+\r
+b_0x2298_start:\r
+ defw l230ch ;2298\r
+\r
+b_0x229A_start:\r
+ defb 0e7h ;229a\r
+ defb 001h ;229b\r
+ defb 0e7h ;229c\r
+\r
+b_0x229D_start:\r
+ defw l2315h ;229d\r
+\r
+b_0x229F_start:\r
+ defb 0f7h ;229f\r
+ defb 021h ;22a0\r
+ defb 0e7h ;22a1\r
+\r
+b_0x22A2_start:\r
+ defw l2315h ;22a2\r
+\r
+b_0x22A4_start:\r
+ defb 0ffh ;22a4\r
+ defb 039h ;22a5\r
+ defb 0e7h ;22a6\r
+\r
+b_0x22A7_start:\r
+ defw l2315h ;22a7\r
+\r
+b_0x22A9_start:\r
+ defb 0ffh ;22a9\r
+ defb 064h ;22aa\r
+ defb 0eeh ;22ab\r
+\r
+b_0x22AC_start:\r
+ defw l2397h ;22ac\r
+\r
+b_0x22AE_start:\r
+ defb 0ffh ;22ae\r
+ defb 074h ;22af\r
+ defb 0f1h ;22b0\r
+\r
+b_0x22B1_start:\r
+ defw l2397h ;22b1\r
+\r
+b_0x22B3_start:\r
+ defb 000h ;22b3\r
+l22b4h:\r
+ defb 0efh ;22b4\r
+ defb 043h ;22b5\r
+ defb 056h ;22b6\r
+\r
+b_0x22B7_start:\r
+ defw l2476h ;22b7\r
+\r
+b_0x22B9_start:\r
+ defb 0ffh ;22b9\r
+ defb 073h ;22ba\r
+ defb 056h ;22bb\r
+\r
+b_0x22BC_start:\r
+ defw l2476h ;22bc\r
+\r
+b_0x22BE_start:\r
+ defb 0efh ;22be\r
+ defb 04bh ;22bf\r
+ defb 056h ;22c0\r
+\r
+b_0x22C1_start:\r
+ defw l247fh ;22c1\r
+\r
+b_0x22C3_start:\r
+ defb 0ffh ;22c3\r
+ defb 07bh ;22c4\r
+ defb 056h ;22c5\r
+\r
+b_0x22C6_start:\r
+ defw l247fh ;22c6\r
+\r
+b_0x22C8_start:\r
+ defb 000h ;22c8\r
+l22c9h:\r
+ defb 0f8h ;22c9\r
+ defb 000h ;22ca\r
+ defb 09bh ;22cb\r
+\r
+b_0x22CC_start:\r
+ defw l24aeh ;22cc\r
+\r
+b_0x22CE_start:\r
+ defb 0f8h ;22ce\r
+ defb 008h ;22cf\r
+ defb 0aah ;22d0\r
+\r
+b_0x22D1_start:\r
+ defw l24aeh ;22d1\r
+\r
+b_0x22D3_start:\r
+ defb 0f8h ;22d3\r
+ defb 010h ;22d4\r
+ defb 096h ;22d5\r
+\r
+b_0x22D6_start:\r
+ defw l24aeh ;22d6\r
+\r
+b_0x22D8_start:\r
+ defb 0f8h ;22d8\r
+ defb 018h ;22d9\r
+ defb 0a5h ;22da\r
+\r
+b_0x22DB_start:\r
+ defw l24aeh ;22db\r
+\r
+b_0x22DD_start:\r
+ defb 0f8h ;22dd\r
+ defb 020h ;22de\r
+ defb 0c0h ;22df\r
+\r
+b_0x22E0_start:\r
+ defw l24aeh ;22e0\r
+\r
+b_0x22E2_start:\r
+ defb 0f8h ;22e2\r
+ defb 028h ;22e3\r
+ defb 0c3h ;22e4\r
+\r
+b_0x22E5_start:\r
+ defw l24aeh ;22e5\r
+\r
+b_0x22E7_start:\r
+ defb 0f8h ;22e7\r
+ defb 038h ;22e8\r
+ defb 0c6h ;22e9\r
+\r
+b_0x22EA_start:\r
+ defw l24aeh ;22ea\r
+\r
+b_0x22EC_start:\r
+ defb 0c0h ;22ec\r
+ defb 040h ;22ed\r
+ defb 009h ;22ee\r
+\r
+b_0x22EF_start:\r
+ defw l2487h ;22ef\r
+\r
+b_0x22F1_start:\r
+ defb 0c0h ;22f1\r
+ defb 080h ;22f2\r
+ defb 088h ;22f3\r
+\r
+b_0x22F4_start:\r
+ defw l2487h ;22f4\r
+\r
+b_0x22F6_start:\r
+ defb 0c0h ;22f6\r
+ defb 0c0h ;22f7\r
+ defb 0bdh ;22f8\r
+\r
+b_0x22F9_start:\r
+ defw l2487h ;22f9\r
+\r
+b_0x22FB_start:\r
+ defb 000h ;22fb\r
+l22fch:\r
+ call l24dfh ;22fc\r
+ call sub_257ch ;22ff\r
+ jp l24ebh ;2302\r
+l2305h:\r
+ call sub_2579h ;2305\r
+ jp l24ebh ;2308\r
+l230bh:\r
+ ret ;230b\r
+l230ch:\r
+ call l24dfh ;230c\r
+ call sub_257ch ;230f\r
+ jp l23c6h ;2312\r
+l2315h:\r
+ call l23c6h ;2315\r
+ call sub_257ch ;2318\r
+ jp l24dfh ;231b\r
+l231eh:\r
+ comst ;231e\r
+ ld a,(iy+000h) ;2322\r
+ comend\r
+ and 038h ;2325\r
+ jp out.hex ;2327\r
+l232ah:\r
+ ld hl,b_0x2333_start ;232a\r
+ call PSTR ;232d\r
+ jp l253eh ;2330\r
+\r
+b_0x2333_start:\r
+ DC '(SP),'\r
+\r
+l2338h:\r
+ ld a,'(' ;2338\r
+ call OUTCHAR ;233a\r
+ call l253eh ;233d\r
+ ld a,')' ;2340\r
+ jp OUTCHAR ;2342\r
+l2345h:\r
+ ld hl,l1d86h ;2345\r
+ jp PSTR ;2348\r
+l234bh:\r
+ ld hl,b_0x2354_start ;234b\r
+ call PSTR ;234e\r
+ jp l253eh ;2351\r
+\r
+b_0x2354_start:\r
+ DC 'SP,'\r
+\r
+l2357h:\r
+ ld hl,b_0x1D80_start ;2357\r
+ jp PSTR ;235a\r
+l235dh:\r
+ call l253eh ;235d\r
+ call sub_257ch ;2360\r
+ jp l254bh ;2363\r
+l2366h:\r
+ call sub_2372h ;2366\r
+ call sub_257ch ;2369\r
+ jp l23dbh ;236c\r
+l236fh:\r
+ call sub_2579h ;236f\r
+sub_2372h:\r
+ ld a,'(' ;2372\r
+ call OUTCHAR ;2374\r
+ call l254bh ;2377\r
+ ld a,')' ;237a\r
+ jp OUTCHAR ;237c\r
+l237fh:\r
+ call sub_2579h ;237f\r
+ jr l2397h ;2382\r
+l2384h:\r
+ call l24dfh ;2384\r
+ call sub_257ch ;2387\r
+ ld a,(is.pfx.IXY) ;238a\r
+ and a ;238d\r
+ comst ;238e\r
+ ld a,(iy+002h) ;2392\r
+ comend\r
+ jr nz,l239eh ;2395\r
+l2397h:\r
+ comst ;2397\r
+ ld a,(iy+001h) ;239b\r
+ comend\r
+l239eh:\r
+ jp out.hex ;239e\r
+l23a1h:\r
+ comst ;23a1\r
+ ld a,(iy+000h) ;23a5\r
+ comend\r
+ and 018h ;23a8\r
+ call sub_2568h ;23aa\r
+ call sub_257ch ;23ad\r
+l23b0h:\r
+ comst ;23b0\r
+ ld c,(iy+001h) ;23b4\r
+ comend\r
+ ld a,c ;23b7\r
+ rla ;23b8\r
+ sbc a,a ;23b9\r
+ ld b,a ;23ba\r
+ push iy ;23bb\r
+ pop hl ;23bd\r
+ add hl,bc ;23be\r
+ inc hl ;23bf\r
+ inc hl ;23c0\r
+ jr l23f0h ;23c1\r
+l23c3h:\r
+ call sub_2579h ;23c3\r
+l23c6h:\r
+ ld a,028h ;23c6\r
+ call OUTCHAR ;23c8\r
+ comst ;23cb\r
+ ld a,(iy+001h) ;23cf\r
+ comend\r
+ jp l252bh ;23d2\r
+l23d5h:\r
+ call l23c6h ;23d5\r
+ call sub_257ch ;23d8\r
+l23dbh:\r
+ ld a,041h ;23db\r
+ jp OUTCHAR ;23dd\r
+l23e0h:\r
+ call l2561h ;23e0\r
+ call sub_257ch ;23e3\r
+l23e6h:\r
+ comst ;23e6\r
+ ld l,(iy+001h) ;23ea\r
+ ld h,(iy+002h) ;23ed\r
+ comend\r
+l23f0h:\r
+ ld a,002h ;23f0\r
+sub_23f2h:\r
+ ld (XBE03),a ;23f2\r
+ ld (XBE01),hl ;23f5\r
+ call out.hl ;23f8\r
+ ret ;23fb\r
+l23fch:\r
+ call l254bh ;23fc\r
+ call sub_257ch ;23ff\r
+ jr l23e6h ;2402\r
+l2404h:\r
+ call sub_24c6h ;2404\r
+ call sub_257ch ;2407\r
+ jp l253eh ;240a\r
+l240dh:\r
+ call l253eh ;240d\r
+ call sub_257ch ;2410\r
+ jp sub_24c6h ;2413\r
+l2416h:\r
+ call sub_24c6h ;2416\r
+ call sub_257ch ;2419\r
+ ld a,041h ;241c\r
+ jp OUTCHAR ;241e\r
+l2421h:\r
+ call sub_2579h ;2421\r
+ jp sub_24c6h ;2424\r
+l2427h:\r
+ ld a,030h ;2427\r
+ jr l2431h ;2429\r
+l242bh:\r
+ ld a,031h ;242b\r
+ jr l2431h ;242d\r
+l242fh:\r
+ ld a,032h ;242f\r
+l2431h:\r
+ jp OUTCHAR ;2431\r
+l2434h:\r
+ ld hl,b_0x2449_start ;2434\r
+ jr l2446h ;2437\r
+l2439h:\r
+ ld hl,l244ch ;2439\r
+ jr l2446h ;243c\r
+l243eh:\r
+ ld hl,l244fh ;243e\r
+ jr l2446h ;2441\r
+l2443h:\r
+ ld hl,l2452h ;2443\r
+l2446h:\r
+ jp PSTR ;2446\r
+\r
+b_0x2449_start:\r
+ DC 'I,A'\r
+l244ch:\r
+ DC 'A,I'\r
+l244fh:\r
+ DC 'R,A'\r
+l2452h:\r
+ DC 'A,R'\r
+\r
+l2455h:\r
+ call l24dfh ;2455\r
+ call sub_257ch ;2458\r
+ ld hl,t__C_ ;245b\r
+ jp PSTR ;245e\r
+l2461h:\r
+ ld hl,t__C_ ;2461\r
+ call PSTR ;2464\r
+ call sub_257ch ;2467\r
+ jp l24dfh ;246a\r
+l246dh:\r
+ call l253eh ;246d\r
+ call sub_257ch ;2470\r
+ jp l254bh ;2473\r
+l2476h:\r
+ call sub_24c6h ;2476\r
+ call sub_257ch ;2479\r
+ jp l254bh ;247c\r
+l247fh:\r
+ call l254bh ;247f\r
+ call sub_257ch ;2482\r
+ jr sub_24c6h ;2485\r
+l2487h:\r
+ ld a,(is.pfx.IXY) ;2487\r
+ and a ;248a\r
+ jr nz,l2496h ;248b\r
+ comst ;248d\r
+ ld a,(iy+001h) ;2491\r
+ comend\r
+ jr l249dh ;2494\r
+l2496h:\r
+ comst ;2496\r
+ ld a,(iy+002h) ;249a\r
+ comend\r
+l249dh:\r
+ push af ;249d\r
+ rra ;249e\r
+ rra ;249f\r
+ rra ;24a0\r
+ and 007h ;24a1\r
+ add a,'0' ;24a3\r
+ call OUTCHAR ;24a5\r
+ call sub_257ch ;24a8\r
+ pop af ;24ab\r
+ jr l24f2h ;24ac\r
+l24aeh:\r
+ ld a,(is.pfx.IXY) ;24ae\r
+ and a ;24b1\r
+ jr nz,l24bdh ;24b2\r
+ comst ;24b4\r
+ ld a,(iy+001h) ;24b8\r
+ comend\r
+ jr l24c4h ;24bb\r
+l24bdh:\r
+ comst ;24bd\r
+ ld a,(iy+002h) ;24c1\r
+ comend\r
+l24c4h:\r
+ jr l24f2h ;24c4\r
+sub_24c6h:\r
+ ld a,'(' ;24c6\r
+ call OUTCHAR ;24c8\r
+ comst ;24cb\r
+ ld l,(iy+001h) ;24cf\r
+ ld h,(iy+002h) ;24d2\r
+ comend\r
+ ld a,001h ;24d5\r
+ call sub_23f2h ;24d7\r
+ ld a,')' ;24da\r
+ jp OUTCHAR ;24dc\r
+l24dfh:\r
+ comst ;24df\r
+ ld a,(iy+000h) ;24e3\r
+ comend\r
+ rra ;24e6\r
+ rra ;24e7\r
+ rra ;24e8\r
+ jr l24f2h ;24e9\r
+l24ebh:\r
+ comst ;24eb\r
+ ld a,(iy+000h) ;24ef\r
+ comend\r
+l24f2h:\r
+ and 007h ;24f2\r
+ cp 006h ;24f4\r
+ jr nz,l2533h ;24f6\r
+ ld a,(is.pfx.IXY) ;24f8\r
+ and a ;24fb\r
+ ld a,006h ;24fc\r
+ jr z,l2533h ;24fe\r
+ ld hl,b_0x2538_start ;2500\r
+ ld a,(is.pfx.IXY) ;2503\r
+ dec a ;2506\r
+ jr z,l250ch ;2507\r
+ ld hl,b_0x253B_start ;2509\r
+l250ch:\r
+ call PSTR ;250c\r
+ comst ;250f\r
+ ld a,(iy+001h) ;2513\r
+ comend\r
+ and a ;2516\r
+ push af ;2517\r
+ jp m,l2523h ;2518\r
+ ld a,'+' ;251b\r
+ call OUTCHAR ;251d\r
+ pop af ;2520\r
+ jr l252bh ;2521\r
+l2523h:\r
+ ld a,'-' ;2523\r
+ call OUTCHAR ;2525\r
+ pop af ;2528\r
+ neg ;2529\r
+l252bh:\r
+ call out.hex ;252b\r
+ ld a,')' ;252e\r
+ jp OUTCHAR ;2530\r
+l2533h:\r
+ ld hl,t_BCDEHL_HL_A ;2533\r
+ jr l2572h ;2536\r
+\r
+b_0x2538_start:\r
+ DC '(IX'\r
+b_0x253B_start:\r
+ DC '(IY'\r
+\r
+l253eh:\r
+ ld a,(is.pfx.IXY) ;253e\r
+ ld hl,t_HL.IX.IY ;2541\r
+ jr l2572h ;2544\r
+l2546h:\r
+ ld hl,t_BC.DE.HL.AF ;2546\r
+ jr l254eh ;2549\r
+l254bh:\r
+ ld hl,t_BC.DE.HL.SP ;254b\r
+l254eh:\r
+ comst ;254e\r
+ ld a,(iy+000h) ;2552\r
+ comend\r
+ rra ;2555\r
+ rra ;2556\r
+ rra ;2557\r
+ rra ;2558\r
+ and 003h ;2559\r
+ cp 002h ;255b\r
+ jr z,l253eh ;255d\r
+ jr l2572h ;255f\r
+l2561h:\r
+ comst ;2561\r
+ ld a,(iy+000h) ;2565\r
+ comend\r
+sub_2568h:\r
+ rra ;2568\r
+ rra ;2569\r
+ rra ;256a\r
+ and 007h ;256b\r
+ ld hl,t_tstfl_ZCPS ;256d\r
+ jr l2572h ;2570\r
+l2572h:\r
+ ld b,a ;2572\r
+ call sub_0a48h ;2573\r
+ jp PSTR ;2576\r
+sub_2579h:\r
+ call l23dbh ;2579\r
+sub_257ch:\r
+ ld a,',' ;257c\r
+ jp OUTCHAR ;257e\r
+sub_2581h:\r
+ call PSTR ;2581\r
+l2584h:\r
+ call OUTBL ;2584\r
+ inc c ;2587\r
+ ld a,c ;2588\r
+ cp 006h ;2589\r
+ jr nz,l2584h ;258b\r
+ ret ;258d\r
+\r
+t_MNEMONICS:\r
+ DC 'ADC'\r
+ DC 'ADD'\r
+ DC 'AND'\r
+ DC 'BIT'\r
+ DC 'CALL'\r
+ DC 'CCF'\r
+ DC 'CP'\r
+ DC 'CPD'\r
+ DC 'CPDR'\r
+ DC 'CPI'\r
+ DC 'CPIR'\r
+ DC 'CPL'\r
+ DC 'DAA'\r
+ DC 'DEC'\r
+ DC 'DI'\r
+ DC 'DJNZ'\r
+ DC 'EI'\r
+ DC 'EX'\r
+ DC 'EXX'\r
+ DC 'HALT'\r
+ DC 'IM'\r
+ DC 'IN'\r
+ DC 'INC'\r
+ DC 'IND'\r
+ DC 'INDR'\r
+ DC 'INI'\r
+ DC 'INIR'\r
+ DC 'JP'\r
+ DC 'JR'\r
+ DC 'LD'\r
+ DC 'LDD'\r
+ DC 'LDDR'\r
+ DC 'LDI'\r
+ DC 'LDIR'\r
+ DC 'NEG'\r
+ DC 'NOP'\r
+ DC 'OR'\r
+ DC 'OTDR'\r
+ DC 'OTIR'\r
+ DC 'OUT'\r
+ DC 'OUTD'\r
+ DC 'OUTI'\r
+ DC 'POP'\r
+ DC 'PUSH'\r
+ DC 'RES'\r
+ DC 'RET'\r
+ DC 'RETI'\r
+ DC 'RETN'\r
+ DC 'RL'\r
+ DC 'RLA'\r
+ DC 'RLC'\r
+ DC 'RLCA'\r
+ DC 'RLD'\r
+ DC 'RR'\r
+ DC 'RRA'\r
+ DC 'RRC'\r
+ DC 'RRCA'\r
+ DC 'RRD'\r
+ DC 'RST'\r
+ DC 'SBC'\r
+ DC 'SCF'\r
+ DC 'SET'\r
+ DC 'SLA'\r
+ DC 'SRA'\r
+ DC 'SRL'\r
+ DC 'SUB'\r
+ DC 'XOR'\r
+ DC 'IN0'\r
+ DC 'MLT'\r
+ DC 'OTDM'\r
+ DC 'OTDMR'\r
+ DC 'OTIM'\r
+ DC 'OTIMR'\r
+ DC 'OUT0'\r
+ DC 'SLP'\r
+ DC 'TST'\r
+ DC 'TSTIO'\r
+ DB 0\r
+ \r
+t_BCDEHL_HL_A:\r
+ DC 'B'\r
+ DC 'C'\r
+ DC 'D'\r
+ DC 'E'\r
+ DC 'H'\r
+ DC 'L'\r
+ DC '(HL)'\r
+ DC 'A'\r
+ DB 0\r
+t_BC.DE.HL.SP:\r
+ DC 'BC'\r
+ DC 'DE'\r
+ DC 'HL'\r
+ DC 'SP'\r
+ DB 0\r
+t_BC.DE.HL.AF:\r
+ DC 'BC'\r
+ DC 'DE'\r
+t_HL.AF:\r
+ DC 'HL'\r
+ DC 'AF'\r
+ DB 0\r
+t_BC.DE.IY.SP:\r
+ DC 'BC'\r
+ DC 'DE'\r
+ DC 'IY'\r
+ DC 'SP'\r
+ DB 0\r
+t_BC.DE.IX.SP:\r
+ DC 'BC'\r
+ DC 'DE'\r
+ DC 'IX'\r
+ DC 'SP'\r
+ DB 0\r
+t_HL.IX.IY:\r
+ DC 'HL'\r
+t_IX.IY:\r
+ DC 'IX'\r
+ DC 'IY'\r
+ DB 0\r
+t_tstfl_ZC:\r
+ DC 'NZ'\r
+ DC 'Z'\r
+ DC 'NC'\r
+ DC 'C'\r
+ DC 'NE'\r
+ DC 'EQ'\r
+ DC 'GE'\r
+ DC 'LT'\r
+ DB 0\r
+t_tstfl_ZCPS:\r
+ DC 'NZ'\r
+ DC 'Z'\r
+ DC 'NC'\r
+ DC 'C'\r
+ DC 'PO'\r
+ DC 'PE'\r
+ DC 'P'\r
+ DC 'M'\r
+ DC 'NE'\r
+ DC 'EQ'\r
+ DC 'GE'\r
+ DC 'LT'\r
+ DC 'NV'\r
+ DC 'V'\r
+ DB 0\r
+t__C_:\r
+ DC '(C)'\r
+ DB 0\r
+\r
+sub_26e7h:\r
+ ld hl,(REG.PC) ;26e7\r
+ ld a,h ;26ea\r
+ or l ;26eb\r
+ jr z,l2715h ;26ec\r
+ ld iy,(REG.PC) ;26ee\r
+ call sub_1f9eh ;26f2\r
+ jp nc,ERROR ;26f5\r
+ ld c,b ;26f8\r
+ ld b,000h ;26f9\r
+ ld hl,(REG.PC) ;26fb\r
+ add hl,bc ;26fe\r
+ call sub_1117h ;26ff\r
+ ld iy,(REG.PC) ;2702\r
+ ld hl,b_0x2717_start ;2706\r
+ call lookup_opc ;2709\r
+ ccf ;270c\r
+ ret c ;270d\r
+ ex de,hl ;270e\r
+ call CALL.HL ;270f\r
+ call c,sub_1117h ;2712\r
+l2715h:\r
+ scf ;2715\r
+ ret ;2716\r
+\r
+b_0x2717_start:\r
+ db 0ffh ;2717\r
+ db 0ddh ;2718\r
+ db 000h ;2719\r
+ dw x278d\r
+\r
+ db 0ffh ;271c\r
+ db 0fdh ;271d\r
+ db 000h ;271e\r
+ dw x2792\r
+\r
+ db 0ffh ;2721\r
+ db 0edh ;2722\r
+ db 000h ;2723\r
+ dw x27a2\r
+\r
+l2726h:\r
+ db 0ffh ;2726\r
+ db 0cdh ;2727\r
+ db 000h ;2728\r
+ dw x275e\r
+\r
+ db 0ffh ;272b\r
+ db 0c3h ;272c\r
+ db 000h ;272d\r
+ dw x2769\r
+\r
+ db 0ffh ;2730\r
+ db 0e9h ;2731\r
+ db 000h ;2732\r
+ dw x2788\r
+\r
+ db 0ffh ;2735\r
+ db 0c9h ;2736\r
+ db 000h ;2737\r
+ dw x27c9\r
+\r
+ db 0ffh ;273a\r
+ db 0cfh ;273b\r
+ db 000h ;273c\r
+ dw x280e\r
+\r
+ db 0c7h ;273f\r
+ db 0c7h ;2740\r
+ db 000h ;2741\r
+ dw x27ea\r
+\r
+ db 0c7h ;2744\r
+ db 0c4h ;2745\r
+ db 000h ;2746\r
+ dw x275e\r
+\r
+ db 0f7h ;2749\r
+ db 010h ;274a\r
+ db 000h ;274b\r
+ dw x2775\r
+\r
+ db 0e7h ;274e\r
+ db 020h ;274f\r
+ db 000h ;2750\r
+ dw x2775\r
+\r
+ db 0c7h ;2753\r
+ db 0c2h ;2754\r
+ db 000h ;2755\r
+ dw x2769\r
+\r
+ db 0c7h ;2758\r
+ db 0c0h ;2759\r
+ db 000h ;275a\r
+ dw x27b3\r
+\r
+ db 000h ;275d\r
+\r
+x275e:\r
+ ld a,(XBFE8) ;275e\r
+ and a ;2761\r
+ jr nz,x2769 ;2762\r
+ ld a,(TCFLG) ;2764\r
+ and a ;2767\r
+ ret nz ;2768\r
+\r
+x2769:\r
+ comst ;2769\r
+ ld l,(iy+001h) ;276d\r
+ ld h,(iy+002h) ;2770\r
+ comend\r
+ scf ;2773\r
+ ret ;2774\r
+\r
+x2775:\r
+ comst ;2775\r
+ ld c,(iy+001h) ;2779\r
+ comend\r
+ ld a,c ;277c\r
+ rla ;277d\r
+ sbc a,a ;277e\r
+ ld b,a ;277f\r
+ ld hl,(REG.PC) ;2780\r
+ add hl,bc ;2783\r
+ inc hl ;2784\r
+ inc hl ;2785\r
+ scf ;2786\r
+ ret ;2787\r
+\r
+x2788:\r
+ ld hl,(REG.L) ;2788\r
+ scf ;278b\r
+ ret ;278c\r
+\r
+x278d:\r
+ ld hl,(reg.ix) ;278d\r
+ jr l2795h ;2790\r
+\r
+x2792:\r
+ ld hl,(reg.iy) ;2792\r
+l2795h:\r
+ comst ;2795\r
+ ld a,(iy+001h) ;2799\r
+ comend\r
+ cp 0e9h ;279c\r
+ scf ;279e\r
+ ret z ;279f\r
+ and a ;27a0\r
+ ret ;27a1\r
+\r
+x27a2:\r
+ comst ;27a2\r
+ ld a,(iy+001h) ;27a6\r
+ comend\r
+ cp 04dh ;27a9\r
+ jr z,x27c9 ;27ab\r
+ cp 045h ;27ad\r
+ jr z,x27c9 ;27af\r
+ and a ;27b1\r
+ ret ;27b2\r
+\r
+x27b3:\r
+ comst ;27b3\r
+ ld a,(iy+000h) ;27b7\r
+ comend\r
+ ld (XBEDD),a ;27ba\r
+ ld hl,(REG.F) ;27bd\r
+ push hl ;27c0\r
+ pop af ;27c1\r
+ call XBEDD ;27c2\r
+ scf ;27c5\r
+ jr c,x27c9 ;27c6\r
+ ret ;27c8\r
+\r
+x27c9:\r
+ ld a,(XBFE8) ;27c9\r
+ and a ;27cc\r
+ jr nz,l27dah ;27cd\r
+ ld a,(TCFLG) ;27cf\r
+ and a ;27d2\r
+ jr z,l27dah ;27d3\r
+ call l27dah ;27d5\r
+ pop hl ;27d8\r
+ ret ;27d9\r
+l27dah:\r
+ ld hl,(REG.SP) ;27da\r
+ comst ;27dd\r
+ ld e,(hl) ;27e1\r
+ inc hl ;27e2\r
+ ld d,(hl) ;27e3\r
+ comend\r
+ ex de,hl ;27e4\r
+ call sub_1117h ;27e5\r
+ and a ;27e8\r
+ ret ;27e9\r
+\r
+x27ea:\r
+ ld a,(ddtrst) ;27ea\r
+ comst ;27ed\r
+ cp (iy+000h) ;27f1\r
+ comend\r
+ ret z ;27f4\r
+ comst ;27f5\r
+ ld a,(iy+000h) ;27f9\r
+ comend\r
+ and 038h ;27fc\r
+ ld l,a ;27fe\r
+ ld h,000h ;27ff\r
+ ld a,(XBFE8) ;2801\r
+ and a ;2804\r
+ jr nz,l280ch ;2805\r
+ ld a,(TCFLG) ;2807\r
+ and a ;280a\r
+ ret nz ;280b\r
+l280ch:\r
+ scf ;280c\r
+ ret ;280d\r
+\r
+x280e:\r
+ and a ;280e\r
+ ret ;280f\r
+\r
+CMD.C:\r
+ ld hl,CMD.C ;2810\r
+ ld a,001h ;2813\r
+ jr l281bh ;2815\r
+\r
+CMD.T:\r
+ xor a ;2817\r
+ ld hl,CMD.T ;2818\r
+l281bh:\r
+ ld (CMD_RPT),hl ;281b\r
+ ld (TCFLG),a ;281e\r
+ ld a,(de) ;2821\r
+ sub 'N' ;2822\r
+ jr nz,l2827h ;2824\r
+ inc de ;2826\r
+l2827h:\r
+ ld (TCNFLG),a ;2827\r
+ ld a,(de) ;282a\r
+ sub 'J' ;282b\r
+ jr nz,l2830h ;282d\r
+ inc de ;282f\r
+l2830h:\r
+ ld (TRJFLG),a ;2830\r
+ call sub_289fh ;2833\r
+ jr z,l283eh ;2836\r
+ ld hl,1 ;2838\r
+ call get_lastarg_def ;283b\r
+l283eh:\r
+ ld (TCCSTR),hl ;283e\r
+ sub a ;2841\r
+ ld (XA747),a ;2842\r
+l2845h:\r
+ call sub_26e7h ;2845\r
+ jr l289ch ;2848\r
+l284ah:\r
+ call sub_0e68h ;284a\r
+ ld a,(TRJFLG) ;284d\r
+ and a ;2850\r
+ jr nz,l2864h ;2851\r
+ ld iy,(REG.PC) ;2853\r
+ call sub_28c1h ;2857\r
+ jr z,l2864h ;285a\r
+ ld hl,l2726h ;285c\r
+ call lookup_opc ;285f\r
+ jr nc,l2845h ;2862\r
+l2864h:\r
+ ld a,(XBFEA) ;2864\r
+ and a ;2867\r
+ jr z,l2881h ;2868\r
+ ld de,(TCCSTR) ;286a\r
+ call EXPR ;286e\r
+ ld a,h ;2871\r
+ or l ;2872\r
+ add a,0ffh ;2873\r
+ sbc a,a ;2875\r
+ ld hl,XBFEA ;2876\r
+ xor (hl) ;2879\r
+ bit 1,a ;287a\r
+ jr z,l288ch ;287c\r
+l287eh:\r
+ jp l102eh ;287e\r
+l2881h:\r
+ ld hl,(TCCSTR) ;2881\r
+ dec hl ;2884\r
+ ld (TCCSTR),hl ;2885\r
+ ld a,h ;2888\r
+ or l ;2889\r
+ jr z,l287eh ;288a\r
+l288ch:\r
+ call sub_26e7h ;288c\r
+ jr nc,l287eh ;288f\r
+ ld a,(TCNFLG) ;2891\r
+ ld b,a ;2894\r
+ ld a,(XA747) ;2895\r
+ or b ;2898\r
+ ld (XA747),a ;2899\r
+l289ch:\r
+ jp l1183h ;289c\r
+\r
+sub_289fh:\r
+ call SKIPBL ;289f\r
+ xor a ;28a2\r
+ ld (XBFEA),a ;28a3\r
+ ld a,(de) ;28a6\r
+ cp 'U' ;28a7\r
+ jr z,l28aeh ;28a9\r
+ cp 'W' ;28ab\r
+ ret nz ;28ad\r
+\r
+l28aeh:\r
+ inc de ;28ae\r
+ push af ;28af\r
+ push de ;28b0\r
+ call EXPR ;28b1\r
+ jp c,ERROR ;28b4\r
+ call assert_eol ;28b7\r
+ pop hl ;28ba\r
+ pop af ;28bb\r
+ ld (XBFEA),a ;28bc\r
+ sub a ;28bf\r
+ ret ;28c0\r
+\r
+sub_28c1h:\r
+ comst \r
+ ld a,(iy+000h) \r
+ ld b,(iy+0001)\r
+ comend\r
+ cp 0edh \r
+ jr z,l28dbh \r
+ and 0dfh \r
+ cp 0ddh \r
+ ret nz \r
+ ld a,b\r
+ cp 0e9h \r
+ ret \r
+l28dbh:\r
+ ld a,b\r
+ and 0f7h \r
+ cp 045h \r
+ ret \r
+\r
+?excom:\r
+ ex (sp),hl ;28e7\r
+ push af ;28e8\r
+ push bc ;28e9\r
+ push de ;28ea\r
+ ld c,(hl) ;28eb\r
+ ld b,000h ;28ec\r
+ inc hl ;28ee\r
+ ld a,?lcmax\r
+ sub c\r
+ ld de,?exeit ;28ef\r
+ ldir\r
+ ex de,hl\r
+ ld (hl),018h\r
+ inc hl\r
+ ld (hl),a\r
+ ex de,hl\r
+ pop de ;28f7\r
+ pop bc ;28f8\r
+ pop af ;28f9\r
+ ex (sp),hl ;28fa\r
+?exclst:\r
+ push hl ;28fb\r
+ ld hl,(ubbr) ;2900\r
+\r
+ if ROMSYS\r
+ push af ;28fc\r
+ ld a,(uromen) ;28fd\r
+ endif\r
+ jp ?comcod ;2903\r
+ \r
+;------------------------------------------\r
+; ddtram\r
+;------------------------------------------\r
+\r
+vartab:\r
+ dseg\r
+ddtram: \r
+;todo:\r
+; The following 2 params are changeable by user.\r
+; Should these moved to top ram?\r
+;\r
+ddtrst: inidat ;\r
+ rst DRSTNUM ;rst used by ddtz\r
+ inidate ;\r
+ddtei: inidat ;\r
+ ei ;ints enabled/disabled while ddtz is running\r
+ ret ;\r
+ inidate ;\r
+offs.pc:\r
+ inidat \r
+ dw TPA \r
+ inidate\r
+offs.@:\r
+ inidat\r
+ dw 0 \r
+ inidate\r
+CMD_ERR:\r
+ inidat\r
+ dw 0 \r
+ inidate\r
+CMD_RPT:\r
+ inidat\r
+ dw DDTZML \r
+ inidate\r
+ci.buf:\r
+ inidat\r
+ db 80 \r
+ rept 83\r
+ db 0\r
+ endm\r
+ inidate\r
+CON.COL:\r
+ inidat\r
+ db 0 \r
+ inidate\r
+XA747:\r
+ inidat\r
+ db 0 \r
+ inidate\r
+bp_tab:\r
+ inidat\r
+ rept BP_CNT \r
+ db 0,0\r
+ dw 0,0,0\r
+ endm\r
+BP_SIZE equ 8\r
+ inidate\r
+sexp1:\r
+ inidat\r
+ dw sexpbuf \r
+ inidate\r
+sexp2:\r
+ inidat\r
+ dw sexpbuf \r
+ inidate\r
+sexpbuf:\r
+ inidat\r
+ rept 128 \r
+ db 0\r
+ endm\r
+ inidate\r
+sexpbufe:\r
+\r
+msg.Y:\r
+ inidat\r
+ dc 'Y0' \r
+ inidate\r
+reg.Y:\r
+ inidat\r
+ rept 10 \r
+ dw 0\r
+ endm\r
+ inidate\r
+lst.S:\r
+ inidat\r
+ dw 0 \r
+ inidate\r
+lst.IP:\r
+ inidat\r
+ dw 0 \r
+ inidate\r
+lst.OP:\r
+ inidat\r
+ dw 0 \r
+ inidate\r
+lst.OD:\r
+ inidat\r
+ db 0\r
+ inidate\r
+lst.Qj:\r
+ inidat\r
+ db 0\r
+ inidate\r
+lst.D:\r
+ inidat\r
+ dw 0 \r
+ inidate\r
+HILOD:\r
+ inidat\r
+ dw 0 \r
+ inidate\r
+MAXLOD:\r
+ inidat\r
+ dw 0 \r
+ inidate\r
+XB068:\r
+ inidat\r
+ dw 0 \r
+ inidate\r
+lst.A:\r
+ inidat\r
+ dw 0 \r
+ inidate\r
+XB06C:\r
+ inidat\r
+ dw 0 \r
+ inidate\r
+pfx.IXY:\r
+ inidat\r
+ db 000h \r
+ inidate\r
+is.pfx.IXY:\r
+ inidat\r
+ db 000h \r
+ inidate\r
+lst.L:\r
+ inidat\r
+ dw 0 \r
+ inidate\r
+XBE01:\r
+ inidat\r
+ dw 0 \r
+ inidate\r
+XBE03:\r
+ inidat\r
+ db 000h \r
+ inidate\r
+XBEDD:\r
+ inidat\r
+ ret ;ret cc\r
+ and a \r
+ pop hl \r
+ inc hl \r
+ jp (hl) \r
+ inidate\r
+XBFE8:\r
+ inidat\r
+ db 0 \r
+ inidate\r
+TCFLG:\r
+ inidat\r
+ db 0 \r
+ inidate\r
+XBFEA:\r
+ inidat\r
+ db 0 \r
+ inidate\r
+TCCSTR:\r
+ inidat\r
+ dw 0 \r
+ inidate\r
+TCNFLG:\r
+ inidat\r
+ db 0 \r
+ inidate\r
+TRJFLG:\r
+ inidat\r
+ db 0 \r
+ inidate\r
+wstrtflg:\r
+ inidat\r
+ db 1\r
+ inidate\r
+\r
+ cseg\r
+vartabe:\r
+\r
+;------------------------------------------\r
+\r
+ .phase sysram_start+stacksize\r
+$stack:\r
+$stcka equ $ - stacksize\r
+\r
+curphse defl $\r
+ .dephase\r
+sysramc:\r
+ .phase curphse\r
+topcodbeg:\r
+\r
+reg.l2: db 0 ; 0fe50h\r
+reg.h2: db 0 ; 0fe51h\r
+reg.e2: db 0 ; 0fe52h\r
+reg.d2: db 0 ; 0fe53h\r
+reg.c2: db 0 ; 0fe54h\r
+reg.b2: db 0 ; 0fe55h\r
+reg.f2: db 0 ; 0fe56h\r
+reg.a2: db 0 ; 0fe57h\r
+ db 0\r
+reg.i: db high ivtab\r
+reg.iy: dw 0 ; 0fe5ah\r
+reg.ix: dw 0 ; 0fe5ch\r
+reg.e: db 0 ; 0fe5eh\r
+reg.d: db 0 ; 0fe5fh\r
+reg.c: db 0 ; 0fe60h\r
+reg.b: db 0 ; 0fe61h\r
+ if ROMSYS\r
+udcntl: db CWAITIO ; 0fe62h (mem-, io- wait)\r
+uromen: db ROM_DIS ; 0fe63h\r
+ endif\r
+ubbr: db 0 ; 0fe64h\r
+ucbar: db USR$CBAR ; 0fe65h\r
+reg.f: db 0 ; 0fe66h\r
+reg.a: db 0 ; 0fe67h\r
+reg.l: db 0 ; 0fe68h\r
+reg.h: db 0 ; 0fe69h\r
+reg.sp: dw TOPRAM ; 0fe6ah\r
+\r
+$go:\r
+ if ROMSYS\r
+ out (000h),a ;064c fe6c\r
+ out0 (dcntl),l ;064e\r
+ pop hl ;0651\r
+ endif\r
+ out0 (cbar),h ;0652\r
+ out0 (bbr),l ;0655\r
+ pop af ;0658\r
+ pop hl ;0659\r
+ ld sp,(reg.sp) ;065a\r
+reg.iff:\r
+ ei ;065e\r
+ db 0C3h ;jp TPA ;065f feff ($+1): reg.pc\r
+reg.pc:\r
+ dw TPA\r
+ \r
+bpent:\r
+ ld (reg.l),hl ;0662 fe82: bpent:\r
+ pop hl ;0665\r
+ dec hl ;0666\r
+ ld (reg.pc),hl ;0667\r
+ ld (reg.sp),sp ;066a\r
+ ld sp,reg.l ;066e\r
+ push af ;0671\r
+ in0 h,(cbar) ;0672\r
+ in0 l,(bbr) ;0675\r
+ push hl ;0678\r
+ ld a,SYS$CBAR ;0679\r
+ out0 (cbar),a ;067b\r
+\r
+ if ROMSYS\r
+ in0 l,(dcntl) ;067e\r
+ ld a,CWAITROM+CWAITIO ;0681\r
+ out0 (dcntl),a ;0683\r
+ ld a,($crom) ;0686\r
+ cp c$rom ;0689\r
+ ld a,ROM_EN ;068b\r
+ out (000h),a ;068d\r
+ endif\r
+\r
+ jp bpddtz ;068f\r
+\r
+?comcod:\r
+ if ROMSYS\r
+ out (000h),a ;0692 feb2\r
+ pop af ;069a\r
+ endif\r
+\r
+ out0 (cbar),h ;0694\r
+ out0 (bbr),l ;0697\r
+ pop hl ;069b\r
+?exeit:\r
+ ds ?lcmax+2\r
+ push af ;069f\r
+ ld a,SYS$CBAR ;06a0\r
+ out0 (cbar),a ;06a2\r
+\r
+ if ROMSYS\r
+ ld a,ROM_EN ;06a5\r
+ out (000h),a ;06a7\r
+ endif\r
+ \r
+ pop af ;06a9\r
+ ret ;06aa\r
+\r
+topcodend:\r
+curph defl $\r
+ .dephase\r
+sysrame:\r
+\r
+ end\r
+\r
--- /dev/null
+ page 255\r
+ .z80\r
+ \r
+ global f.init,f.in,f.out,f.i.st\r
+\r
+ extrn buf.init\r
+\r
+ include config.inc\r
+ include z180reg.inc\r
+\r
+\r
+;--------------------------------------------------------------\r
+\r
+ dseg\r
+ \r
+\r
+ mkbuf rx.buf,rx.buf_len\r
+ mkbuf tx.buf,tx.buf_len\r
+\r
+\r
+;--------------------------------------------------------------\r
+\r
+ cseg\r
+;\r
+; FIFO channels for communication with stm32\r
+;\r
+; Init Serial I/O for console input and output\r
+;\r
+ \r
+f.init:\r
+ ld ix,rx.buf\r
+ ld a,rx.buf.mask\r
+ call buf.init\r
+ ld ix,tx.buf\r
+ ld a,tx.buf.mask\r
+ jp buf.init\r
+\r
+\r
+f.i.st:\r
+ push ix\r
+ ld ix,rx.buf ;\r
+\r
+buf.empty:\r
+ ld a,(ix+o.in_idx) ;\r
+ sub (ix+o.out_idx) ;\r
+ pop ix\r
+ ret z\r
+ or 0ffh\r
+ ret\r
+ \r
+\r
+f.in:\r
+ push ix\r
+ ld ix,rx.buf ;\r
+\r
+buf.get:\r
+ ld a,(ix+o.out_idx) ;\r
+bg.wait:\r
+ cp (ix+o.in_idx) ;\r
+ jr z,bg.wait\r
+\r
+ push hl ;\r
+ push ix\r
+ pop hl\r
+ add a,l\r
+ ld l,a\r
+ jr nc,bg.nc\r
+ inc h\r
+bg.nc:\r
+ ld l,(hl)\r
+ \r
+ ld a,(ix+o.out_idx) ;\r
+ inc a\r
+ and (ix+o.mask)\r
+ ld (ix+o.out_idx),a\r
+ \r
+ ld a,l\r
+ pop hl\r
+ pop ix\r
+ ret\r
+\r
+\r
+f.o.st:\r
+ push ix\r
+ ld ix,tx.buf ;\r
+\r
+buf.full:\r
+ ld a,(ix+o.in_idx) ;\r
+ inc a\r
+ and (ix+o.mask)\r
+ sub (ix+o.out_idx) ;\r
+ pop ix\r
+ ret z\r
+ or 0ffh\r
+ ret\r
+\r
+\r
+f.out:\r
+ push ix\r
+ ld ix,tx.buf ;\r
+\r
+buf.put:\r
+ push hl ;\r
+ push bc\r
+ push ix\r
+ pop hl\r
+ ld c,(ix+o.in_idx) ;\r
+ ld b,0\r
+ add hl,bc\r
+ ld b,a\r
+\r
+ ld a,c ;\r
+ inc a\r
+ and (ix+o.mask)\r
+bp.wait:\r
+ cp (ix+o.out_idx) ;\r
+ jr z,bp.wait\r
+ ld (hl),b\r
+ ld (ix+o.in_idx),a\r
+ \r
+ ld a,b\r
+ pop bc\r
+ pop hl\r
+ pop ix\r
+ ret\r
+\r
+ end\r
+\r
--- /dev/null
+ page 255\r
+ .z80\r
+ \r
+ global msg_fifo\r
+ global msginit\r
+ global msg.out,msg.sout,msg.co\r
+ \r
+ extrn buf.init\r
+\r
+ include config.inc\r
+ include z180reg.inc\r
+\r
+;--------------------------------------------------------------\r
+\r
+ dseg\r
+\r
+ mkbuf msg_fifo, 0\r
+\r
+\r
+;--------------------------------------------------------------\r
+\r
+ cseg\r
+\r
+;\r
+; Init buffer\r
+;\r
+ \r
+msginit:\r
+ ld ix,msg_fifo\r
+ ld a,msg_fb_len-1\r
+ jp buf.init\r
+\r
+\r
+;--------------------------------------------------------------\r
+\r
+msg.sts:\r
+ push ix\r
+ ld ix,msg_fifo ;\r
+\r
+ ld a,(ix+o.in_idx) ;\r
+ inc a\r
+ and (ix+o.mask)\r
+ sub (ix+o.out_idx) ;\r
+ pop ix\r
+ ret z\r
+ or 0ffh\r
+ ret\r
+\r
+;--------------------------------------------------------------\r
+\r
+msg.out:\r
+ push ix\r
+ ld ix,msg_fifo ;\r
+\r
+ push bc\r
+ ld b,a ;save char\r
+ ld a,(ix+o.in_idx) ;\r
+ inc a\r
+ and (ix+o.mask)\r
+bp.wait:\r
+ cp (ix+o.out_idx) ;\r
+ jr z,bp.wait\r
+ ld c,a\r
+ ld a,b\r
+ out (PMSG),a\r
+ ld (ix+o.in_idx),c\r
+ \r
+ pop bc\r
+ pop ix\r
+ ret\r
+\r
+;--------------------------------------------------------------\r
+;\r
+; (hl): data\r
+ \r
+msg.sout:\r
+ push ix\r
+ ld ix,msg_fifo ;\r
+ push bc\r
+\r
+ ld b,(hl) ;count\r
+ inc hl\r
+obs_1:\r
+ ld a,(ix+o.out_idx) ;\r
+ sub (ix+o.in_idx) ;\r
+ dec a\r
+ and (ix+o.mask)\r
+ cp b\r
+ jr c,obs_1\r
+\r
+ ld c,(hl) ;port address\r
+ inc hl\r
+ ld a,b\r
+ otir\r
+ add (ix+o.in_idx)\r
+ and (ix+o.mask)\r
+ ld (ix+o.in_idx),a\r
+ pop bc\r
+ pop ix\r
+ ret\r
+\r
+;----------------------------------------------------------------------\r
+\r
+msg.co:\r
+ push af\r
+ push hl\r
+ ld (buf_char),a\r
+ ld hl,buf\r
+ call msg.sout\r
+ pop hl\r
+ pop af\r
+ ret\r
+ \r
+ \r
+buf:\r
+ db buf_end - $ - 2 ;output string length\r
+ db PMSG ;output port\r
+ db 081h ; message start token\r
+ db buf_end - $ - 1 ; message length\r
+ db 1 ; command\r
+ db 1 ; subcommand\r
+buf_char:\r
+ db 0 ; pay load\r
+buf_end:\r
+\r
+;----------------------------------------------------------------------\r
+\r
+ end\r
+\r
--- /dev/null
+ page 255\r
+ .z80\r
+\r
+ extrn ddtz,bpent\r
+ extrn $stack\r
+ extrn $coninit,$cists,$ci\r
+\r
+ extrn romend\r
+\r
+\r
+ global isv_sw\r
+\r
+ include config.inc\r
+ include z180reg.inc\r
+ include z180.lib\r
+ \r
+;CR equ 0dh\r
+\r
+\r
+\r
+;----------------------------------------------------------------------\r
+\r
+ cseg\r
+\r
+ jp start \r
+\r
+; restart vectors\r
+\r
+rsti defl 1\r
+ rept 7\r
+ db 0, 0, 0, 0, 0\r
+ jp bpent\r
+rsti defl rsti+1\r
+ endm\r
+\r
+;----------------------------------------------------------------------\r
+\r
+ if ROMSYS\r
+$crom: defb c$rom ;\r
+ else\r
+ db 0 ;\r
+ endif\r
+\r
+dmclrt: ;clear ram per dma\r
+ db dmct_e-dmclrt-2 ;\r
+ db sar0l ;first port\r
+ dw nullbyte ;src (fixed) \r
+nullbyte:\r
+ db 000h ;src\r
+ dw romend ;dst (inc), start after "rom" code\r
+ db 00h ;dst\r
+ dw 0-romend ;count (64k)\r
+dmct_e:\r
+\r
+INIWAITS defl CWAITIO\r
+ if ROMSYS\r
+INIWAITS defl INIWAITS+CWAITROM\r
+ endif\r
+\r
+hwini0:\r
+ db 3 ;count\r
+ db rcr,CREFSH ;configure DRAM refresh\r
+ db dcntl,INIWAITS ;wait states\r
+ db cbar,SYS$CBAR\r
+\r
+;----------------------------------------------------------------------\r
+\r
+start:\r
+ push af ;003c\r
+ in0 a,(itc) ;003d Illegal opcode trap?\r
+ jp p,??st01 ;0040\r
+ pop af ;0043\r
+ jp bpent ;0044 yes, handle\r
+\r
+??st01:\r
+ ld a,i ;0047 I register == 0 ? \r
+ jr z,??st02 ;004b yes, harware reset\r
+ pop af ;004d \r
+ jp bpent ;004e no, allready set up\r
+\r
+??st02:\r
+ di ;0058\r
+ ld a,CREFSH\r
+ out0 (rcr),a ; configure DRAM refresh\r
+ ld a,CWAITIO\r
+ out0 (dcntl),a ; wait states\r
+\r
+; search warm start mark\r
+\r
+ ld ix,mark_55AA ;00b8 ; top of common area\r
+ ld a,SYS$CBAR ;\r
+ out0 (cbar),a ;\r
+ ld a,071h ;00bc\r
+ ex af,af' ;00be ;for cbr = 0x70 downto 0x40\r
+swsm_l:\r
+ ex af,af' ;00bf \r
+ dec a ;00c0\r
+ cp 03fh ;00c1\r
+ jr z,kstart ;00c3 ; break (mark not found)\r
+ out0 (cbr),a ;00c5\r
+ ex af,af' ;00c8\r
+ ld a,0aah ;00c9\r
+ cp (ix+000h) ;00cb\r
+ jr nz,swsm_l ;00ce\r
+ cp (ix+002h) ;00d0\r
+ jr nz,swsm_l ;00d3\r
+ cpl ;00d5\r
+ cp (ix+001h) ;00d6\r
+ jr nz,swsm_l ;00d9\r
+ cp (ix+003h) ;00db\r
+ jr nz,swsm_l ;00de\r
+ ld sp,$stack ;00e0 mark found, check\r
+ call checkcrc_alv ;00e3\r
+ jp z,wstart ;00e6 check ok,\r
+\r
+;\r
+; ram not ok, initialize -- kstart --\r
+\r
+kstart:\r
+\r
+ ld a,088h ;00e9 0000-7fff: common 0\r
+ out0 (cbar),a ;00eb 8000-ffff: common 1\r
+ ld ix,08000h ;00f3\r
+ ld a,0 ;00f1 start at 008000 (2. phys. 32k block)\r
+??f_0:\r
+ out0 (cbr),a ;00f9\r
+\r
+ ld (ix+0),a ;0103 \r
+ cpl\r
+ ld (ix+1),a ;0103 \r
+ cpl\r
+ add a,8 ;010a next 'bank'\r
+ cp 078h ;010c stop at 078000\r
+ jr nz,??f_0 ;010e\r
+\r
+ ld de,8000h ;0114 first block not tested, but mark as ok\r
+ ld a,0 ;00f1 start at 008000 (2. phys. 32k block)\r
+??cp_0:\r
+ out0 (cbr),a ;011c\r
+ ld c,a\r
+ xor (ix+0)\r
+ ld b,a\r
+ ld a,c\r
+ cpl\r
+ xor (ix+1)\r
+ or b\r
+ jr nz,??cp_1\r
+ scf\r
+??cp_1:\r
+ rr d\r
+ rr e\r
+ ld a,c\r
+ add a,8\r
+ cp 078h ; stop at 078000\r
+ jr nz,??cp_0\r
+ \r
+;\r
+; ram test found 1 or more error free blocks (32k)\r
+;\r
+\r
+ramok:\r
+ ld a,SYS$CBAR ;01c8\r
+ out0 (cbar),a ;01ca\r
+ ld h,d\r
+ ld l,e\r
+ ld c,070h ;01ce highest block\r
+ ld b,15 ;01d0\r
+??sr_1:\r
+ add hl,hl\r
+ jr c,alloc ;01d4 highest "error free" block\r
+ ld a,c ;01d6\r
+ sub 008h ;01d7\r
+ ld c,a ;01d9\r
+ djnz ??sr_1 ;01da\r
+\r
+ slp ;01dc should never be reached\r
+\r
+alloc:\r
+ out0 (cbr),c ;01de\r
+ ld sp,$stack ;01e1\r
+ \r
+; Clear RAM using DMA0\r
+\r
+ ld hl,dmclrt ;load DMA registers\r
+ call io.ini.m\r
+ ld a,0cbh ;01ef dst +1, src fixed, burst\r
+ out0 (dmode),a ;01f1\r
+\r
+ ld b,512/64\r
+ ld a,062h ;01f4 enable dma0, \r
+??cl_1:\r
+ out0 (dstat),a ;01f9 clear (up to) 64k\r
+ djnz ??cl_1 ; end of RAM?\r
+ \r
+; Init bank manager\r
+ \r
+ ld hl,banktabsys ;020f\r
+ ld (hl),c ; Common area\r
+ inc hl ;0213\r
+ ld (hl),c ; System work area\r
+ inc hl ;0215 Point to bank 0 entry\r
+ ld b,BANKS ;0216\r
+l0218h:\r
+ ld (hl),0ffh ;0218 Mark all banks as unassigned\r
+ inc hl ;021a\r
+ djnz l0218h ;021b\r
+\r
+ ld hl,memalv ;\r
+ ld b,8 ; 8*4k ie. first 32k\r
+??a_0:\r
+ ld (hl),0e0h ; mark as sys ("rom"/monitor)\r
+ inc hl\r
+ djnz ??a_0\r
+ \r
+ rr d ; shift out bit for block 0\r
+ rr e ;\r
+ ld c,15 ;022c 15*32k remaining blocks\r
+l022eh:\r
+ ld a,0feh ; 0xfe == block with error(s)\r
+ rr d ;\r
+ rr e\r
+ adc a,0 ; ==> 0xff : block ok\r
+ ld b,32/4 ; 32k == 8 * 4k \r
+l0236h:\r
+ ld (hl),a ;\r
+ inc hl ;\r
+ djnz l0236h ;\r
+ dec c ;\r
+ jr nz,l022eh ;next 32k block\r
+ \r
+ ld hl,memalv+0ch ;memalv+0ch\r
+ ld a,(banktabsys) ;\r
+ call add_hl_a\r
+ ld b,3 ;\r
+l024ah:\r
+ ld (hl),0ech ;alloc system ram\r
+ inc hl ;\r
+ djnz l024ah ;\r
+ ld (hl),0efh ;alloc common\r
+ call gencrc_alv\r
+\r
+ ld hl,0000h ;bank # \r
+ ld bc,0f0fh ; size (?) (4k blocks)\r
+ xor a ;\r
+ call sub_0420h ;alloc mem for bank 0\r
+ ld c,l ;\r
+ or a ;\r
+ call z,sub_04b5h ;\r
+\r
+ ld hl,0101h ;\r
+ ld bc,0f0fh ;\r
+ xor a ;\r
+ call sub_0420h ;\r
+ ld c,l ;\r
+ or a ;\r
+ call z,sub_04b5h ;\r
+\r
+ ld hl,055AAh ;set warm start mark\r
+ ld (mark_55AA),hl ;\r
+ ld (mark_55AA+2),hl;\r
+\r
+;\r
+; crc ok -- wstart --\r
+;\r
+wstart:\r
+ call sysram_init ;027f\r
+ call ivtab_init\r
+\r
+ call prt0_init\r
+\r
+\r
+;;; call bufferinit\r
+\r
+\r
+ call $coninit\r
+\r
+\r
+\r
+\r
+ im 2 ;?030e\r
+ ei ;0282\r
+\r
+ call $cists ;0284\r
+ call $cists ;0287\r
+ or a ;028a\r
+ call nz,$ci ;028d\r
+ \r
+ ld a,(banktab) ; \r
+ ld e,a ; \r
+ jp ddtz ;0290\r
+ \r
+\r
+;\r
+;----------------------------------------------------------------------\r
+;\r
+\r
+;TODO: Make a ringbuffer module.\r
+\r
+ global buf.init\r
+ \r
+buf.init:\r
+ ld (ix+o.in_idx),0\r
+ ld (ix+o.out_idx),0\r
+ ld (ix+o.mask),a\r
+ ret\r
+\r
+;----------------------------------------------------------------------\r
+\r
+.comment *\r
+\r
+ extrn msginit,msg.sout,msg_fifo\r
+ extrn tx.buf,rx.buf\r
+\r
+\r
+bufferinit:\r
+ call msginit\r
+ \r
+ ld hl,buffers\r
+ ld bc,0300h\r
+bfi_1:\r
+ ld e,(hl)\r
+ inc hl\r
+ ld d,(hl)\r
+ inc hl\r
+ push hl\r
+ in0 a,cbr\r
+ call log2phys\r
+ ld (bufdat+1),hl\r
+ ld (bufdat+3),a\r
+ ld a,c\r
+ ld (bufdat+0),a\r
+ ld hl,inimsg\r
+ call msg.sout\r
+ pop hl\r
+ inc c\r
+ djnz bfi_1\r
+ ret\r
+\r
+ rept 20\r
+ db 0\r
+ endm\r
+ \r
+buffers:\r
+ dw msg_fifo\r
+ dw tx.buf\r
+ dw rx.buf\r
+ \r
+inimsg: \r
+ db inimsg_e - $ -2\r
+ db PMSG\r
+ db 81h\r
+ db inimsg_e - $ -1\r
+ db 0\r
+bufdat:\r
+ db 0\r
+ dw 0\r
+ db 0\r
+inimsg_e:\r
+\r
+ *\r
+\r
+;\r
+;----------------------------------------------------------------------\r
+;\r
+\r
+sysram_init:\r
+ ld hl,sysramw\r
+ ld de,topcodsys\r
+ ld bc,sysrame-sysramw\r
+ ldir\r
+\r
+ ret\r
+\r
+;----------------------------------------------------------------------\r
+\r
+ivtab_init:\r
+ ld hl,ivtab ;\r
+ ld a,h ;\r
+ ld i,a ;\r
+ out0 (il),l ;\r
+\r
+; Let all vectors point to spurious int routines.\r
+\r
+ ld d,high sp.int0\r
+ ld a,low sp.int0\r
+ ld b,9\r
+ivt_i1: \r
+ ld (hl),a\r
+ inc l\r
+ ld (hl),d\r
+ inc l\r
+ add a,sp.int.len\r
+ djnz ivt_i1\r
+ ret\r
+\r
+;----------------------------------------------------------------------\r
+\r
+prt0_init:\r
+ ld a,i\r
+ ld h,a\r
+ in0 a,(il)\r
+ and 0E0h\r
+ or IV$PRT0\r
+ ld l,a\r
+ ld (hl),low iprt0\r
+ inc hl\r
+ ld (hl),high iprt0\r
+ ld hl,prt0itab\r
+ call io.ini.m\r
+ ret\r
+ \r
+prt0itab:\r
+ db prt0it_e-prt0itab-2\r
+ db tmdr0l\r
+ dw PRT_TC10MS\r
+ dw PRT_TC10MS\r
+ db M_TIE0+M_TDE0 ;enable timer 0 interrupt and down count.\r
+prt0it_e:\r
+\r
+\r
+;\r
+;----------------------------------------------------------------------\r
+;\r
+\r
+io.ini:\r
+ push bc\r
+ ld b,0 ;high byte port adress\r
+ ld a,(hl) ;count\r
+ inc hl\r
+ioi_1:\r
+ ld c,(hl) ;port address\r
+ inc hl\r
+ outi\r
+ inc b ;outi decrements b\r
+ dec a\r
+ jr nz,ioi_1\r
+ pop bc\r
+ ret\r
+\r
+io.ini.m:\r
+ push bc\r
+ ld b,(hl)\r
+ inc hl\r
+ ld c,(hl)\r
+ inc hl\r
+ otimr \r
+ pop bc \r
+ ret\r
+ \r
+io.ini.l:\r
+;\r
+\r
+;----------------------------------------------------------------------\r
+;\r
+\r
+; compute crc\r
+; hl: start adr\r
+; bc: len\r
+; bc returns crc val\r
+\r
+do_crc16:\r
+ ld de,0FFFFh\r
+crc1:\r
+ ld a,(hl)\r
+ xor e\r
+ ld e,a\r
+ rrca\r
+ rrca\r
+ rrca\r
+ rrca\r
+ and 0Fh\r
+ xor e\r
+ ld e,a\r
+ rrca\r
+ rrca\r
+ rrca\r
+ push af\r
+ and 1Fh\r
+ xor d\r
+ ld d,a\r
+ pop af\r
+ push af\r
+ rrca\r
+ and 0F0h\r
+ xor d\r
+ ld d,a\r
+ pop af\r
+ and 0E0h\r
+ xor e\r
+ ld e,d\r
+ ld d,a\r
+ cpi\r
+ jp pe,crc1\r
+ or e ;z-flag\r
+ ret\r
+\r
+\r
+gencrc_alv:\r
+ push hl ;03f6\r
+ push de ;03f7\r
+ push bc\r
+ push af ;03f8\r
+ ld hl,banktabsys ;03f9\r
+ ld bc,crc_len ;03fc\r
+ call do_crc16 ;03ff\r
+ ld (hl),e\r
+ inc hl\r
+ ld (hl),d\r
+ pop af ;0406\r
+ pop bc\r
+ pop de ;0407\r
+ pop hl ;0408\r
+ ret ;0409\r
+\r
+checkcrc_alv:\r
+ push hl ;040a\r
+ push de\r
+ push bc ;040b\r
+ ld hl,banktabsys ;040d\r
+ ld bc,crc_len+2 ;0410\r
+ call do_crc16 ;0413\r
+ pop bc ;041d\r
+ pop de\r
+ pop hl ;041e\r
+ ret ;041f\r
+\r
+;----------------------------------------------------------------------\r
+\r
+;\r
+; alloc\r
+;\r
+; h: max bank #\r
+; l: min bank #\r
+; b: max size\r
+; c: min size\r
+;\r
+; ret:\r
+; a: 0 == ok\r
+; 1 == \r
+; 2 == no bank # in requested range\r
+; ff == crc error\r
+;\r
+\r
+sub_0420h:\r
+ call checkcrc_alv ;0420\r
+ jr nz,l049ch ;0424 crc error, tables corrupt\r
+ \r
+ call sub_049dh ;0427 bank # in req. range available?\r
+ jr c,l0499h ;042a\r
+ push ix ;042c\r
+ push iy ;042e\r
+ push de ;0430\r
+ push hl ;0431\r
+ push bc ;0432\r
+ ld c,b ;0433\r
+ ld b,alv_len+1 ;0434\r
+ ld d,0 ;0436\r
+ ld hl,memalv-1 ;0438\r
+ jr l0441h ;043b\r
+\r
+; find free blocks\r
+\r
+l043dh:\r
+ ld a,(hl) ;043d\r
+ inc a ;043e free blocks are marked 0ffh\r
+ jr z,l0446h ;043f\r
+l0441h:\r
+ inc hl ;0441\r
+ djnz l043dh ;0442\r
+ jr l0464h ;0444\r
+l0446h:\r
+ push hl ;0446 \r
+ pop ix ;0447 free blocks start here\r
+ ld e,000h ;0449\r
+ jr l0451h ;044b\r
+l044dh: ; count free blocks\r
+ ld a,(hl) ;044d\r
+ inc a ;044e\r
+ jr nz,l0457h ;044f\r
+l0451h:\r
+ inc e ;0451\r
+ inc hl ;0452\r
+ djnz l044dh ;0453\r
+ jr l0464h ;0455\r
+\r
+; end of free blocks run. \r
+\r
+l0457h:\r
+ ld a,d ;0457\r
+ cp e ;0458 nr of blocks >= requested ?\r
+ jr nc,l0441h ;0459 \r
+\r
+ ld d,e ;045b\r
+ push ix ;045c\r
+ pop iy ;045e\r
+ ld a,d ;0460\r
+ cp c ;0461\r
+ jr c,l0441h ;0462\r
+l0464h:\r
+ pop bc ;0464\r
+ ld a,d ;0465\r
+ cp b ;0466\r
+ jr c,l046ch ;0467\r
+ ld d,b ;0469\r
+ jr l0471h ;046a\r
+l046ch:\r
+ cp c ;046c\r
+ jr nc,l0471h ;046d\r
+ ld d,000h ;046f\r
+l0471h:\r
+ ld a,d ;0471\r
+ push iy ;0472\r
+ pop hl ;0474\r
+ ld de,memalv ;0475\r
+ or a ;0478\r
+ sbc hl,de ;0479\r
+ ld b,l ;047b\r
+ ld c,a ;047c\r
+ pop hl ;047d\r
+l047eh:\r
+ or a ;047e\r
+ jr z,l0489h ;047f\r
+ ld (iy+0),l ;0481\r
+ inc iy ;0484\r
+ dec a ;0486\r
+ jr l047eh ;0487\r
+l0489h:\r
+ pop de ;0489\r
+ pop iy ;048a\r
+ pop ix ;048c\r
+ call gencrc_alv ;048e\r
+ ld a,c ;0491\r
+ or a ;0492\r
+ ld a,000h ;0493\r
+ ret nz ;0495\r
+ or 001h ;0496\r
+ ret ;0498\r
+\r
+l0499h:\r
+ ld a,2 ;0499\r
+l049ch:\r
+ or a\r
+ ret ;049c\r
+\r
+\r
+; search a free bank number in range\r
+; h: max #\r
+; l: min #\r
+; ret:\r
+; l: bank number available\r
+; nc, if found, bank nr. in l\r
+; cy, if none found\r
+\r
+sub_049dh:\r
+ push de ;049d\r
+ push bc ;049e\r
+ ex de,hl ;049f\r
+ dec e ;04a0\r
+l04a1h:\r
+ inc e ;04a1 test next #\r
+ ld a,d ;04a2\r
+ cp e ;04a3\r
+ jr c,l04b1h ;04a4 \r
+ ld a,e ;04a6\r
+ ld hl,memalv ;04a7\r
+ ld bc,alv_len ;04aa\r
+ cpir ;04ad bank# allready allocated?\r
+ jr z,l04a1h ;04af if yes, search for next\r
+l04b1h:\r
+ ex de,hl ;04b1\r
+ pop bc ;04b2\r
+ pop de ;04b3\r
+ ret ;04b4\r
+\r
+\r
+sub_04b5h:\r
+ ld a,l ;04b5\r
+ cp 012h ;04b6\r
+ ccf ;04b8\r
+ ret c ;04b9\r
+ push hl ;04ba\r
+ ld hl,banktab ;04bb\r
+ call add_hl_a\r
+ ld (hl),b ;04c3\r
+ call gencrc_alv ;04c4\r
+ pop hl ;04c7\r
+ or a ;04c8 clear carry\r
+ ret ;04c9\r
+\r
+\r
+;--------------------------------------------------------------\r
+;\r
+; de: Log. Address\r
+; a: Bank number\r
+;\r
+;out ahl: Phys. (linear) Address\r
+\r
+\r
+bnk2phys:\r
+ push hl\r
+ ld hl,banktab\r
+ call add_hl_a\r
+ ld a,(hl)\r
+ pop hl\r
+\r
+ ; fall thru\r
+;--------------------------------------------------------------\r
+;\r
+; de: Log. Address\r
+; a: Bank (bbr)\r
+;\r
+; OP: ahl = (a<<12) + (d<<8) + e\r
+;\r
+;out ahl: Phys. (linear) Address\r
+\r
+\r
+log2phys:\r
+ push bc ;\r
+ ld c,a ;\r
+ ld b,16 ;\r
+ mlt bc ;bc = a<<4\r
+ ld l,d ;\r
+ ld h,0 ;\r
+ add hl,bc ;bc + d == a<<4 + d \r
+ ld a,h ;\r
+ ld h,l ;\r
+ ld l,e ;\r
+ pop bc ;\r
+ ret ;\r
+\r
+\r
+;--------------------------------------------------------------\r
+;\r
+;return:\r
+; hl = hl + a\r
+; Flags undefined\r
+;\r
+\r
+add_hl_a:\r
+ add a,l \r
+ ld l,a \r
+ ret nc \r
+ inc h \r
+ ret \r
+\r
+; ---------------------------------------------------------\r
+\r
+sysramw:\r
+\r
+ .phase isvsw_loc\r
+topcodsys:\r
+\r
+; Trampoline for interrupt routines in banked ram.\r
+; Switch stack pointer to "system" stack in top ram\r
+; Save cbar\r
+ \r
+isv_sw: ;\r
+ ex (sp),hl ; save hl, return adr in hl\r
+ push de ;\r
+ push af ;\r
+ ex de,hl ;\r
+ ld hl,0 ;\r
+ add hl,sp ;\r
+ ld a,h ;\r
+ cp 0f8h ;\r
+ jr nc,isw_1 ;\r
+ ld sp,$stack ;\r
+isw_1:\r
+ push hl ;\r
+ in0 h,(cbar) ;\r
+ push hl ;\r
+ ld a,SYS$CBAR ;\r
+ out0 (cbar),a ;\r
+ ex de,hl ;\r
+ ld e,(hl) ;\r
+ inc hl ;\r
+ ld d,(hl) ;\r
+ ex de,hl ;\r
+ push bc ;\r
+ call jphl ;\r
+\r
+ pop bc ;\r
+ pop hl ;\r
+ out0 (cbar),h ;\r
+ pop hl ;\r
+ ld sp,hl ;\r
+ pop af ;\r
+ pop de ;\r
+ pop hl ;\r
+ ei ;\r
+ ret ;\r
+jphl:\r
+ jp (hl) ;\r
+\r
+; ---------------------------------------------------------\r
+\r
+\r
+iprt0:\r
+ push af\r
+ push hl\r
+ in0 a,(tcr)\r
+ in0 a,(tmdr0l)\r
+ in0 a,(tmdr0h)\r
+ ld a,(tim_ms)\r
+ inc a\r
+ cp 100\r
+ jr nz,iprt_1\r
+ xor a\r
+ ld hl,(tim_s)\r
+ inc hl\r
+ ld (tim_s),hl\r
+iprt_1:\r
+ ld (tim_ms),a\r
+ pop hl\r
+ pop af\r
+ ei\r
+ ret\r
+\r
+; ---------------------------------------------------------\r
+\r
+sp.int0:\r
+ ld a,0d0h\r
+ jr sp.i.1\r
+sp.int.len equ $-sp.int0\r
+ ld a,0d1h\r
+ jr sp.i.1\r
+ ld a,0d2h\r
+ jr sp.i.1\r
+ ld a,0d3h\r
+ jr sp.i.1\r
+ ld a,0d4h\r
+ jr sp.i.1\r
+ ld a,0d5h\r
+ jr sp.i.1\r
+ ld a,0d6h\r
+ jr sp.i.1\r
+ ld a,0d7h\r
+ jr sp.i.1\r
+ ld a,0d8h\r
+sp.i.1:\r
+; out (80h),a\r
+ halt\r
+\r
+curph defl $\r
+ .dephase\r
+sysrame:\r
+ .phase curph\r
+tim_ms: db 0\r
+tim_s: dw 0\r
+ .dephase\r
+ \r
+;-----------------------------------------------------\r
+\r
+ dseg\r
+\r
+ ds 1\r
+banktabsys:\r
+ ds 1 ;0c001h\r
+ ds 1 ;0c002h\r
+banktab:\r
+ ds BANKS ;0c003h\r
+memalv:\r
+ ds 512/4 ;Number of 4k blocks\r
+alv_len equ $-memalv\r
+crc_len equ $-banktabsys\r
+\r
+crc_memalv: \r
+ ds 2 ;\r
+\r
+ cseg\r
+\r
+ ;.phase 0ffc0h\r
+;ivtab equ 0ffc0h ; 0ffc0h ;int vector table\r
+ ;.dephase\r
+\r
+ ;.phase 0fffch\r
+mark_55AA equ 0fffch\r
+ ;ds 4 ; 0fffch\r
+ ;.dephase\r
+\r
+\r
+ end\r
+\r
--- /dev/null
+\r
+ global romend\r
+\r
+ cseg\r
+\r
+romend equ $\r
+ \r
+ end\r
+\r
--- /dev/null
+ page 200\r
+\r
+\r
+ extrn buf.init\r
+ extrn isv_sw\r
+\r
+ \r
+ global ser.init\r
+ global ser.instat,ser.in\r
+ global ser.out\r
+\r
+;TODO: define a trampoline area somewhere in top ram. \r
+rtxisvjmp equ 0FF60h ;momentan frei...\r
+\r
+ include config.inc\r
+ include z180reg.inc\r
+\r
+\r
+;-----------------------------------------------------\r
+\r
+ dseg\r
+ \r
+buf_start:\r
+ mkbuf ser1.inbuf,s1.rx_len\r
+ mkbuf ser1.outbuf,s1.tx_len\r
+buf_end:\r
+\r
+\r
+\r
+;-----------------------------------------------------\r
+\r
+ cseg\r
+;\r
+; Init Serial I/O for console input and output (ASCI1)\r
+;\r
+ \r
+\r
+ser.init:\r
+; ld a,i\r
+; push af ;save IFF\r
+; di\r
+\r
+ xor a ;\r
+ out0 (stat1),a ;Disable rx/tx interrupts\r
+ \r
+ ld hl,rxtx_src ;move rx and tx isv to common ram\r
+ ld de,rxtx_dst ;\r
+ ld bc,rxtx_src_e-rxtx_src ; \r
+ ldir ;\r
+\r
+ ld hl,rtxisvjmp ;rx/tx int vector\r
+ ld (ivtab + IV$ASCI1),hl;\r
+ ld a,0cdh ;\r
+ ld (rtxisvjmp),a ;\r
+ ld hl,isv_sw ;\r
+ ld (rtxisvjmp + 1),hl ;\r
+ ld hl,rxtxisv ;\r
+ ld (rtxisvjmp + 3),hl ;\r
+\r
+; ASCI1: 8N1, highest baudrate (56700), CTS disabled\r
+\r
+ ld a,M_MPBT \r
+ out0 (cntlb1),a\r
+ ld a,M_RE + M_TE + M_MOD2\r
+ out0 (cntla1),a\r
+ ld a,M_RIE\r
+ out0 (stat1),a ;Enable rx interrupts\r
+\r
+ ld ix,ser1.inbuf\r
+ ld a,ser1.inbuf.mask\r
+ call buf.init\r
+ ld ix,ser1.outbuf\r
+ ld a,ser1.outbuf.mask\r
+ call buf.init\r
+\r
+; pop af\r
+; ret po\r
+; ei\r
+ ret ;\r
+\r
+ser.instat:\r
+ push ix\r
+ ld ix,ser1.inbuf ;\r
+\r
+buf.empty:\r
+ ld a,(ix+o.in_idx) ;\r
+ sub (ix+o.out_idx) ;\r
+ pop ix\r
+ ret z\r
+ or 0ffh\r
+ ret\r
+ \r
+ser.in:\r
+ push hl ;11 \r
+ push de ;11\r
+ ld hl,ser1.inbuf-1 ; 9 hl = &rx.out_idx \r
+ ld a,(hl) ; 6 a = rx.out_idx\r
+ dec hl ; 4 hl = &rx.in_idx\r
+ jr bg.w1\r
+bg.wait:\r
+ halt\r
+bg.w1:\r
+ cp (hl) ; 6 while (out_idx==in_idx) \r
+ jr z,bg.wait ; 6 (/8) ;\r
+\r
+ ld e,a ; 4 \r
+ ld d,0 ; 6\r
+ inc de\r
+ inc de\r
+\r
+ ex de,hl ; 3\r
+ add hl,de ;10\r
+ ld l,(hl) ; 6\r
+ ex de,hl ; 3 \r
+\r
+ inc a ; 4\r
+ dec hl ; 4\r
+ and (hl) ; 6 \r
+ inc hl ; 4\r
+ inc hl ; 4\r
+ ld (hl),a ; 7\r
+ \r
+ ld a,e ; 4\r
+ pop de ; 9\r
+ pop hl ; 9\r
+ ret ; 9\r
+ ; 153 \r
+\r
+ser.outstat:\r
+ push ix\r
+ ld ix,ser1.outbuf ;\r
+buf.full:\r
+ ld a,(ix+o.in_idx) ;\r
+ inc a\r
+ and (ix+o.mask)\r
+ sub (ix+o.out_idx) ;\r
+ pop ix\r
+ ret z\r
+ or 0ffh\r
+ ret\r
+\r
+\r
+ser.out:\r
+ push ix\r
+ ld ix,ser1.outbuf ;\r
+buf.put:\r
+ push hl ;\r
+ push bc\r
+ push ix\r
+ pop hl\r
+ ld c,(ix+o.in_idx) ;\r
+ ld b,0\r
+ add hl,bc\r
+ ld (hl),a\r
+\r
+ ld a,c ;\r
+ inc a\r
+ and (ix+o.mask)\r
+bp.wait:\r
+ cp (ix+o.out_idx) ;\r
+ jr z,bp.wait\r
+ ld (ix+o.in_idx),a\r
+\r
+ di ;036f\r
+ in0 a,(stat1) ;0374\r
+ set TIE,a ;0377\r
+ out0 (stat1),a ;0379\r
+ ei ;037c\r
+\r
+ ld a,b\r
+ pop bc\r
+ pop hl\r
+ pop ix\r
+ ret\r
+\r
+\r
+;------------------------------------------\r
+; ASCI 1 Transmit/Receive interupt routines\r
+; moved to common ram\r
+\r
+rxtx_src:\r
+ dseg\r
+rxtx_dst: ; (0c097h) old\r
+\r
+rxtxisv:\r
+ inidat\r
+ in0 a,(stat1) ;receive flag set?\r
+ jp p,txisv ;\r
+\r
+ in0 d,(rdr1) ;todo: break detection\r
+ bit FE,a ;framing error?\r
+ jr nz,??ri_1\r
+ \r
+ push ix\r
+ ld ix,ser1.inbuf ;\r
+ ld hl,ser1.inbuf ;\r
+ ld c,(ix+o.in_idx) ;\r
+ ld b,0\r
+ add hl,bc\r
+\r
+ ld a,c ;\r
+ inc a\r
+ and (ix+o.mask)\r
+ cp (ix+o.out_idx) ;\r
+ jr z,??ri_0\r
+ ld (hl),d\r
+ ld (ix+o.in_idx),a\r
+??ri_0:\r
+ pop ix\r
+??ri_1:\r
+ in0 a,(cntla1) ;0705 c0c0\r
+ res EFR,a ;0708\r
+ out0 (cntla1),a ;070a\r
+ ret\r
+\r
+ inidate\r
+\r
+txisv:\r
+ inidat\r
+ push ix\r
+ ld ix,ser1.outbuf ;\r
+\r
+ ld a,(ix+o.out_idx) ;\r
+ cp (ix+o.in_idx) ;\r
+ jr z,??ti_2\r
+\r
+ ld hl,ser1.outbuf ;\r
+ add a,l\r
+ ld l,a\r
+ jr nc,??ti_1\r
+ inc h\r
+??ti_1:\r
+ ld l,(hl)\r
+ out0 (tdr1),l ;071b\r
+ \r
+ ld a,(ix+o.out_idx) ;\r
+ inc a\r
+ and (ix+o.mask)\r
+ ld (ix+o.out_idx),a\r
+ jr ??ti_3\r
+??ti_2:\r
+ in0 a,(stat1) ;0730 disable tx-int\r
+ res TIE,a ;0733\r
+ out0 (stat1),a ;0735\r
+??ti_3:\r
+ pop ix\r
+ ret\r
+\r
+ inidate\r
+\r
+ cseg\r
+rxtx_src_e:\r
+\r
+\r
+ end\r
+\r
+\r
--- /dev/null
+ .xlist\r
+;;\r
+;; Z180 / HD64180 MACRO LIBRARY\r
+;;\r
+\r
+IFNDEF SLP\r
+\r
+;;\r
+;;\r
+;; HD64180 instructions:\r
+;;\r
+;; SLP ; Enter SLEEP mode\r
+;; MLT RR ; 8 bit multiply with 16 bit result\r
+;; IN0 R,P ; Input from internal port\r
+;; OUT0 P,R ; Output to internal port\r
+;; OTIM ; Block output, increment\r
+;; OTIMR ; Block output, increment and repeat\r
+;; OTDM ; Block output, decrement\r
+;; OTDMR ; Block output, decrement and repeat\r
+;; TSTIO P ; Non destructive AND, I/O port and A\r
+;; TST R ; Non destructive AND, reg and A\r
+;; TST ID ; Non destructive AND, immediate data and A\r
+;; TST (HL) ; Non destructive AND, (HL) and A\r
+;;\r
+;;\r
+\r
+??BC EQU 0 ; Double-register definitions\r
+??DE EQU 1\r
+??HL EQU 2\r
+??SP EQU 3\r
+\r
+??A EQU 7 ; Single-register defintions\r
+??B EQU 0\r
+??C EQU 1\r
+??D EQU 2\r
+??E EQU 3\r
+??H EQU 4\r
+??L EQU 5\r
+\r
+SLP MACRO\r
+ DEFB 0EDH,76H\r
+ ENDM\r
+\r
+MLT MACRO ?R\r
+ DB 0EDH,4CH+(??&?R AND 3) SHL 4\r
+ ENDM\r
+\r
+IN0 MACRO ?R,?P\r
+ DB 0EDH,(??&?R AND 7) SHL 3, ?P\r
+ ENDM\r
+\r
+OUT0 MACRO ?P,?R\r
+ DB 0EDH,1+(??&?R AND 7) SHL 3,?P\r
+ ENDM\r
+\r
+OTIM MACRO\r
+ DB 0EDH,83H\r
+ ENDM\r
+\r
+OTIMR MACRO\r
+ DB 0EDH,93H\r
+ ENDM\r
+\r
+OTDM MACRO\r
+ DB 0EDH,8BH\r
+ ENDM\r
+\r
+OTDMR MACRO\r
+ DB 0EDH,9BH\r
+ ENDM\r
+\r
+TSTIO MACRO ?P\r
+ DB 0EDH,74H,?P\r
+ ENDM\r
+\r
+TSTR MACRO ?R\r
+ DB 0EDH,4+(??&?R AND 7) SHL 3\r
+ ENDM\r
+\r
+TSTD MACRO ?P\r
+ DB 0EDH,64H,?P\r
+ ENDM\r
+\r
+TSTP MACRO\r
+ DB 0EDH,34H\r
+ ENDM\r
+\r
+TST MACRO ?R\r
+ ?D: SET 0\r
+ IRPC ?X,?R\r
+ ?D: SET ?D+1 ; Count # chars in "?R"\r
+ ENDM\r
+ IF ?D EQ 1 ; IF # chars = 1\r
+ IRPC ?X,ABCDEHL ; Look up the character\r
+ IF ??&?X EQ ??&?R\r
+ DB 0EDH,4+(??&?R AND 7) SHL 3\r
+ EXITM\r
+ ENDIF\r
+ ENDM\r
+ DB 0EDh,64h,?R\r
+ EXITM\r
+ ENDIF\r
+ IF (?R = 2) & (?D = 4)\r
+ ?D: SET 0\r
+ IRPC ?X,?R\r
+ IFIDN <?X>,<(>\r
+ DB 0EDh,34h\r
+ EXITM\r
+ ENDIF\r
+ ?D: SET ?D + 1\r
+ ENDM\r
+ ENDIF\r
+ IF ?D NE 0\r
+ DB 0EDH,64H,?R\r
+ ENDIF\r
+ ENDM\r
+\r
+ENDIF ;/* IFNDEF SLP /\r
+ .list\r
+\r
--- /dev/null
+ .xlist\r
+\r
+;;\r
+;; HD64180/Z180 Register Definitions\r
+;;\r
+\r
+\r
+b2m macro name,nr\r
+name equ nr\r
+M_&name equ 1 shl nr\r
+ endm\r
+\r
+; ifndef IOBASE\r
+IOBASE equ 0\r
+; endif\r
+\r
+cntla0 equ IOBASE+00h ;ASCI Control Register A Channel 0\r
+cntla1 equ IOBASE+01h ;ASCI Control Register A Channel 1\r
+ b2m MPE, 7 ;Multi-Processor Mode Enable\r
+ b2m RE, 6 ;Receiver Enable\r
+ b2m TE, 5 ;Transmitter Enable\r
+ b2m RTS0, 4 ;Request to Send Channel 0\r
+ b2m CKA1D, 4 ;\r
+ b2m MPBR, 3 ;Multiprocessor Bit Receive (Read)\r
+ b2m EFR, 3 ;Error Flag Reset (Write)\r
+ b2m MOD2, 2 ;Data Format Mode 1 = 8-Bit data\r
+ b2m NOD1, 1 ;1 = Parity enabled\r
+ b2m MOD0, 0 ;1 = 2 stop bits\r
+\r
+cntlb0 equ IOBASE+02h ;ASCI Control Register B Channel 0\r
+cntlb1 equ IOBASE+03h ;ASCI Control Register B Channel 1\r
+ b2m MPBT,7 ;Multiprocessor Bit Transmit\r
+ b2m MP,6 ;Multiprocessor Mode\r
+ b2m CTS,5 ;Clear to Send\r
+ b2m PS,5 ;Prescale\r
+ b2m PEO,4 ;Parity Even Odd\r
+ b2m DR,3 ;Divede Ratio\r
+ b2m SS2,2 ;Source/Speed Select 2,1,0\r
+ b2m SS1,1 ;\r
+ b2m SS0,0 ;\r
+\r
+stat0 equ IOBASE+04h ;ASCI Status Channel 0\r
+stat1 equ IOBASE+05h ;ASCI Status Channel 1\r
+ b2m RDRF,7 ;Receive Data Register Full\r
+ b2m OVRN,6 ;Overrun Error\r
+ b2m PERR,5 ;Parity Error (M80: PE conflicts with JP/CALL cc)\r
+ b2m FE,4 ;Framing Error\r
+ b2m RIE,3 ;Receive Interrupt Enable\r
+ b2m DCD0,2 ;Data Carrier Detect (Ch 0)\r
+ b2m CTS1E,2 ;Clear To Send (Ch 1)\r
+ b2m TDRE,1 ;Transmit Data Register Empty\r
+ b2m TIE,0 ;Transmit Interrupt Enable\r
+\r
+tdr0 equ IOBASE+06h ;ASCI Transmit Data \r
+tdr1 equ IOBASE+07h ;ASCI Transmit Data \r
+rdr0 equ IOBASE+08h ;ASCI Receive Data \r
+rdr1 equ IOBASE+09h ;ASCI Receive Data \r
+\r
+cntr equ IOBASE+0Ah ;CSI/O Control Register\r
+trdr equ IOBASE+0Bh ;CSI/O Transmit/Receive Data Register\r
+\r
+tmdr0l equ IOBASE+0Ch ;Timer Data Register Channel 0\r
+tmdr0h equ IOBASE+0Dh ;\r
+rldr0l equ IOBASE+0Eh ;Timer Reload Register Channel 0\r
+rldr0h equ IOBASE+0Fh ;\r
+tcr equ IOBASE+10h ;Timer Control Register\r
+ b2m TIF1,7 ;Timer Interrupt Flag\r
+ b2m TIF0,6 ;\r
+ b2m TIE1,5 ;Timer Interrupt Enable\r
+ b2m TIE0,4 ;\r
+ b2m TOC1,3 ;Timer Output Control\r
+ b2m TOC0,2 ;\r
+ b2m TDE1,1 ;Timer Down Count Enable\r
+ b2m TDE0,0 ;\r
+\r
+\r
+asext0 equ IOBASE+12h ;ASCI Extension Control Register\r
+asext1 equ IOBASE+13h ;ASCI Extension Control Register\r
+\r
+tmdr1l equ IOBASE+14h ;Timer Data Register Channel 1\r
+tmdr1h equ IOBASE+15h ;\r
+rldr1l equ IOBASE+16h ;Timer Reload Register Channel 1\r
+rldr1h equ IOBASE+17h ;\r
+\r
+frc equ IOBASE+18h ;Free Running Counter\r
+\r
+astc0l equ IOBASE+1Ah ;ASCI Time Constant Register 0\r
+astc0h equ IOBASE+1Bh ;\r
+astc1l equ IOBASE+1Ch ;ASCI Time Constant Register 1\r
+astc1h equ IOBASE+1Dh ;\r
+\r
+cmr equ IOBASE+1Eh ;Clock Mutiplier Register\r
+ b2m X2CM,7 ;X2 Clock Multiplier\r
+ b2m LNC,6 ;Low Noise Crystal\r
+\r
+ccr equ IOBASE+1Fh ;CPU Control Register\r
+\r
+sar0l equ IOBASE+20h ;DMA Src Adr Register Channel 0\r
+sar0h equ IOBASE+21h ;\r
+sar0b equ IOBASE+22h ;\r
+dar0l equ IOBASE+23h ;DMA Dst Adr Register Channel 0\r
+dar0h equ IOBASE+24h ;\r
+dar0b equ IOBASE+25h ;\r
+bcr0l equ IOBASE+26h ;DMA Byte Count Register Channel 0\r
+bcr0h equ IOBASE+27h ;\r
+\r
+mar1l equ IOBASE+28h ;DMA Memory Address Register Channel 1\r
+mar1h equ IOBASE+29h ;\r
+mar1b equ IOBASE+2Ah ;\r
+iar1l equ IOBASE+2Bh ;DMA I/O Address Register Channel 1\r
+iar1h equ IOBASE+2Ch ;\r
+iar1b equ IOBASE+2Dh ;\r
+ b2m ALTE,7 ;Alternating Chnnels\r
+ b2m ALTC,6 ;Currently selected DMA Channel when Bit7=1\r
+ b2m REQ1SEL2,2 ;\r
+ b2m REQ1SEL1,1 ;\r
+ b2m REQ1SEL0,0 ;\r
+\r
+bcr1l equ IOBASE+2Eh ;DMA Byte Count Register Channel 1\r
+bcr1h equ IOBASE+2Fh ;\r
+\r
+dstat equ IOBASE+30h ;DMA Status Register\r
+ b2m DE1,7 ;DMA enable ch 1,0\r
+ b2m DE0,6 ;\r
+ b2m DWE1,5 ;DMA Enable Bit Write Enable 1,0\r
+ b2m DWE0,4 ;\r
+ b2m DIE1,3 ;DMA Interrupt Enable 1,0\r
+ b2m DIE0,2 ;\r
+ b2m DME,0 ;DMA Master enable\r
+\r
+dmode equ IOBASE+31h ;DMA Mode Register\r
+ b2m DM1,5 ;Ch 0 Destination Mode 1,0\r
+ b2m DM0,4 ;\r
+ b2m SM1,3 ;Ch 0 Source Mode 1,0\r
+ b2m SM0,2 ;\r
+ b2m MMOD,1 ;Memory MODE select (0=cycle steel/1=burst)\r
+\r
+dcntl equ IOBASE+32h ;DMA/WAIT Control\r
+ b2m MWI1,7 ;Memory Wait Insertion\r
+ b2m MWI0,6 ;\r
+ b2m IWI1,5 ;I/O Wait Insertion\r
+ b2m IWI0,4 ;\r
+ b2m DMS1,3 ;DREQi Select (Edge/Level)\r
+ b2m DMS0,2 ;\r
+ b2m DIMA1,1 ;DMA Ch1 I/O Memory Mode Select\r
+ b2m DIMA0,0\r
+M_MWI equ M_MWI1 + M_MWI0\r
+M_IWI equ M_IWI1 + M_IWI0\r
+\r
+il equ IOBASE+33h ;Interrupt Vector Low Register\r
+itc equ IOBASE+34h ;INT/TRAP Control Register\r
+ b2m TRAP,7 ;Trap\r
+ b2m UFO,6 ;Unidentified Fetch Object\r
+ b2m ITE2,2 ;/INT Enable 2,1,0\r
+ b2m ITE1,1 ;\r
+ b2m ITE0,0 ;\r
+\r
+rcr equ IOBASE+36h ;Refresh Control Register\r
+ b2m REFE,7 ;Refresh Enable\r
+ b2m REFW,6 ;Refresh Wait State\r
+ b2m CYC1,1 ;Cycle select\r
+ b2m CYC0,0 ;\r
+\r
+cbr equ IOBASE+38h ;MMU Common Base Register\r
+bbr equ IOBASE+39h ;MMU Bank Base Register\r
+cbar equ IOBASE+3Ah ;MMU Common/Bank Register\r
+\r
+omcr equ IOBASE+3Eh ;Operation Mode Control Register\r
+ b2m M1E,7 ;M1 Enable\r
+ b2m M1TE,6 ;M1 Temporary Enable\r
+ b2m IOC,5 ;I/O Compatibility\r
+\r
+icr equ IOBASE+3Fh ;I/O Control Register\r
+ b2m IOSTP,5 ;I/O Stop\r
+;\r
+; Interrupt Vectors\r
+;\r
+\r
+IV$INT1 equ 0 ;/INT1 (highest priority)\r
+IV$INT2 equ 2 ;/INT2\r
+IV$PRT0 equ 4 ;PRT channel 0\r
+IV$PRT1 equ 6 ;PRT channel 1\r
+IV$DMA0 equ 8 ;DMA channel 0\r
+IV$DMA1 equ 10 ;DMA channel 1\r
+IV$CSIO equ 12 ;CSI/O\r
+IV$ASCI0 equ 14 ;ASCI channel 0\r
+IV$ASCI1 equ 16 ;ASCI channel 1 (lowest priority)\r
+\r
+ .list\r
+\r