+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++;
+ }
+}