BBC Basic in Z80 emulation on the mbed, USB serial terminal output only. LOAD and SAVE work on the local file system but there is no error signalling.

Dependencies:   mbed

Committer:
gertk
Date:
Wed Jun 29 14:25:56 2011 +0000
Revision:
0:806c2f2a7d47
preliminary version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gertk 0:806c2f2a7d47 1 /* BBC Basic emulator on NXP mbed by Gert van der Knokke
gertk 0:806c2f2a7d47 2 * Emulation of the Z80 CPU
gertk 0:806c2f2a7d47 3 * The z80 emulator is heavily modified by me (Gert)
gertk 0:806c2f2a7d47 4 * original Copyright (C) 1994 Ian Collier.
gertk 0:806c2f2a7d47 5 *
gertk 0:806c2f2a7d47 6 * This program is free software; you can redistribute it and/or modify
gertk 0:806c2f2a7d47 7 * it under the terms of the GNU General Public License as published by
gertk 0:806c2f2a7d47 8 * the Free Software Foundation; either version 2 of the License, or
gertk 0:806c2f2a7d47 9 * (at your option) any later version.
gertk 0:806c2f2a7d47 10 *
gertk 0:806c2f2a7d47 11 * This program is distributed in the hope that it will be useful,
gertk 0:806c2f2a7d47 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
gertk 0:806c2f2a7d47 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
gertk 0:806c2f2a7d47 14 * GNU General Public License for more details.
gertk 0:806c2f2a7d47 15 *
gertk 0:806c2f2a7d47 16 * You should have received a copy of the GNU General Public License
gertk 0:806c2f2a7d47 17 * along with this program; if not, write to the Free Software
gertk 0:806c2f2a7d47 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
gertk 0:806c2f2a7d47 19 */
gertk 0:806c2f2a7d47 20
gertk 0:806c2f2a7d47 21 #include "mbed.h"
gertk 0:806c2f2a7d47 22 #include "module.h"
gertk 0:806c2f2a7d47 23 #include "z80.h"
gertk 0:806c2f2a7d47 24
gertk 0:806c2f2a7d47 25 #define DEBUG false
gertk 0:806c2f2a7d47 26
gertk 0:806c2f2a7d47 27 // define serial port for debug
gertk 0:806c2f2a7d47 28 Serial linktopc(USBTX,USBRX);
gertk 0:806c2f2a7d47 29
gertk 0:806c2f2a7d47 30
gertk 0:806c2f2a7d47 31 // VDU queue
gertk 0:806c2f2a7d47 32 unsigned char vdu_queue[256]; // a somewhat large queue
gertk 0:806c2f2a7d47 33 unsigned char queue_bytes=0; // vdu queue pointer
gertk 0:806c2f2a7d47 34 unsigned char oldchar; // which VDU function needs the queue
gertk 0:806c2f2a7d47 35
gertk 0:806c2f2a7d47 36 volatile unsigned char flag,oldy=0;
gertk 0:806c2f2a7d47 37
gertk 0:806c2f2a7d47 38
gertk 0:806c2f2a7d47 39 int background_color; // for clear screen
gertk 0:806c2f2a7d47 40 int cursor_xpos;
gertk 0:806c2f2a7d47 41 int cursor_ypos;
gertk 0:806c2f2a7d47 42 int last_line_processed;
gertk 0:806c2f2a7d47 43 int previous_line_found;
gertk 0:806c2f2a7d47 44
gertk 0:806c2f2a7d47 45 int current_background_color;
gertk 0:806c2f2a7d47 46 int current_text_color;
gertk 0:806c2f2a7d47 47
gertk 0:806c2f2a7d47 48
gertk 0:806c2f2a7d47 49 // prepare mbed storage for local use
gertk 0:806c2f2a7d47 50 LocalFileSystem local("local"); // Create the local filesystem under the name "local"
gertk 0:806c2f2a7d47 51
gertk 0:806c2f2a7d47 52 // clear the screen
gertk 0:806c2f2a7d47 53 void cls() {
gertk 0:806c2f2a7d47 54 putchar(0x0c);
gertk 0:806c2f2a7d47 55 }
gertk 0:806c2f2a7d47 56
gertk 0:806c2f2a7d47 57 // dummy function
gertk 0:806c2f2a7d47 58 void set_cursor_position() {
gertk 0:806c2f2a7d47 59 }
gertk 0:806c2f2a7d47 60
gertk 0:806c2f2a7d47 61 // home cursor
gertk 0:806c2f2a7d47 62 void home_cursor() {
gertk 0:806c2f2a7d47 63 cursor_xpos=0x00; // ypos
gertk 0:806c2f2a7d47 64 cursor_ypos=0x00; // xpos
gertk 0:806c2f2a7d47 65 set_cursor_position();
gertk 0:806c2f2a7d47 66 }
gertk 0:806c2f2a7d47 67
gertk 0:806c2f2a7d47 68 // prepare the screen
gertk 0:806c2f2a7d47 69 void init_screen() {
gertk 0:806c2f2a7d47 70 current_background_color=0; // set initial background color
gertk 0:806c2f2a7d47 71 current_text_color=7; // initial text color attributes
gertk 0:806c2f2a7d47 72 cls();
gertk 0:806c2f2a7d47 73 home_cursor();
gertk 0:806c2f2a7d47 74 }
gertk 0:806c2f2a7d47 75
gertk 0:806c2f2a7d47 76 // handle VDU calls after all bytes are in queue
gertk 0:806c2f2a7d47 77 // Note! queue is working front to back (255 is first, 0 is last)
gertk 0:806c2f2a7d47 78 void do_handle_queue(unsigned char code) {
gertk 0:806c2f2a7d47 79 switch (code) {
gertk 0:806c2f2a7d47 80 case 0x11: // select text color
gertk 0:806c2f2a7d47 81 current_text_color=vdu_queue[255];
gertk 0:806c2f2a7d47 82 break;
gertk 0:806c2f2a7d47 83 case 0x16: // Mode
gertk 0:806c2f2a7d47 84 current_text_color=7;
gertk 0:806c2f2a7d47 85 current_background_color=0;
gertk 0:806c2f2a7d47 86 init_screen();
gertk 0:806c2f2a7d47 87 home_cursor();
gertk 0:806c2f2a7d47 88 break;
gertk 0:806c2f2a7d47 89 case 0x17: // define character n
gertk 0:806c2f2a7d47 90 break;
gertk 0:806c2f2a7d47 91 case 0x1f: // move cursor to x,y
gertk 0:806c2f2a7d47 92 cursor_xpos=vdu_queue[254];
gertk 0:806c2f2a7d47 93 cursor_ypos=vdu_queue[255];
gertk 0:806c2f2a7d47 94 set_cursor_position();
gertk 0:806c2f2a7d47 95 break;
gertk 0:806c2f2a7d47 96 }
gertk 0:806c2f2a7d47 97 }
gertk 0:806c2f2a7d47 98
gertk 0:806c2f2a7d47 99 // VDU OSWRCHR
gertk 0:806c2f2a7d47 100 // this routine evaluates the stream characters
gertk 0:806c2f2a7d47 101 // and prepares the queue if needed
gertk 0:806c2f2a7d47 102 void printchar(unsigned char ch) {
gertk 0:806c2f2a7d47 103
gertk 0:806c2f2a7d47 104 // do we need more queue bytes ?
gertk 0:806c2f2a7d47 105 if (queue_bytes) {
gertk 0:806c2f2a7d47 106 vdu_queue[queue_bytes++]=ch;
gertk 0:806c2f2a7d47 107 // all bytes in queue, now handle the call
gertk 0:806c2f2a7d47 108 if (queue_bytes==0)
gertk 0:806c2f2a7d47 109 do_handle_queue(oldchar);
gertk 0:806c2f2a7d47 110
gertk 0:806c2f2a7d47 111 } else {
gertk 0:806c2f2a7d47 112
gertk 0:806c2f2a7d47 113 switch (ch) {
gertk 0:806c2f2a7d47 114 case 0x00: // NULL
gertk 0:806c2f2a7d47 115 break;
gertk 0:806c2f2a7d47 116 case 0x08: // CURSOR LEFT
gertk 0:806c2f2a7d47 117 putchar(0x08);
gertk 0:806c2f2a7d47 118 if (cursor_xpos>0) {
gertk 0:806c2f2a7d47 119 cursor_xpos--;
gertk 0:806c2f2a7d47 120 set_cursor_position();
gertk 0:806c2f2a7d47 121 }
gertk 0:806c2f2a7d47 122 break;
gertk 0:806c2f2a7d47 123 case 0x09: // CURSOR RIGHT
gertk 0:806c2f2a7d47 124 if (cursor_xpos<39) {
gertk 0:806c2f2a7d47 125 cursor_xpos++;
gertk 0:806c2f2a7d47 126 set_cursor_position();
gertk 0:806c2f2a7d47 127 }
gertk 0:806c2f2a7d47 128 break;
gertk 0:806c2f2a7d47 129 case 0x0a: // CURSOR DOWN
gertk 0:806c2f2a7d47 130 if (cursor_ypos<23) {
gertk 0:806c2f2a7d47 131 cursor_ypos++;
gertk 0:806c2f2a7d47 132 set_cursor_position();
gertk 0:806c2f2a7d47 133 } else {
gertk 0:806c2f2a7d47 134 cursor_ypos=23;
gertk 0:806c2f2a7d47 135 }
gertk 0:806c2f2a7d47 136 break;
gertk 0:806c2f2a7d47 137 case 0x0b: // CURSOR UP
gertk 0:806c2f2a7d47 138 cursor_ypos++;
gertk 0:806c2f2a7d47 139 if (cursor_ypos>0) {
gertk 0:806c2f2a7d47 140 cursor_ypos--;
gertk 0:806c2f2a7d47 141 set_cursor_position();
gertk 0:806c2f2a7d47 142 } else {
gertk 0:806c2f2a7d47 143 cursor_ypos=0;
gertk 0:806c2f2a7d47 144 }
gertk 0:806c2f2a7d47 145 break;
gertk 0:806c2f2a7d47 146 case 0x0d: // Carriage Return
gertk 0:806c2f2a7d47 147 cursor_xpos=0;
gertk 0:806c2f2a7d47 148 putchar(0x0d);
gertk 0:806c2f2a7d47 149 putchar(0x0a);
gertk 0:806c2f2a7d47 150 set_cursor_position();
gertk 0:806c2f2a7d47 151 break;
gertk 0:806c2f2a7d47 152 case 0x0c: // CLEAR TEXT WINDOW
gertk 0:806c2f2a7d47 153 case 0x10: // CLEAR GRAPHIC WINDOW
gertk 0:806c2f2a7d47 154 cls();
gertk 0:806c2f2a7d47 155 cursor_xpos=0;
gertk 0:806c2f2a7d47 156 cursor_ypos=0;
gertk 0:806c2f2a7d47 157 set_cursor_position();
gertk 0:806c2f2a7d47 158 break;
gertk 0:806c2f2a7d47 159 case 0x11: // set TEXT color
gertk 0:806c2f2a7d47 160 oldchar=ch; // this was the code of the initial call
gertk 0:806c2f2a7d47 161 queue_bytes=256-1; // for this call we need one more byte
gertk 0:806c2f2a7d47 162 break;
gertk 0:806c2f2a7d47 163 case 0x14: // reset colors
gertk 0:806c2f2a7d47 164 current_text_color=7;
gertk 0:806c2f2a7d47 165 current_background_color=0;
gertk 0:806c2f2a7d47 166 break;
gertk 0:806c2f2a7d47 167 case 0x16: // MODE select
gertk 0:806c2f2a7d47 168 oldchar=ch;
gertk 0:806c2f2a7d47 169 queue_bytes=256-1;
gertk 0:806c2f2a7d47 170 break;
gertk 0:806c2f2a7d47 171 case 0x17: // define character n
gertk 0:806c2f2a7d47 172 break;
gertk 0:806c2f2a7d47 173 case 0x1e:
gertk 0:806c2f2a7d47 174 cursor_xpos=0;
gertk 0:806c2f2a7d47 175 cursor_ypos=0;
gertk 0:806c2f2a7d47 176 set_cursor_position();
gertk 0:806c2f2a7d47 177 break;
gertk 0:806c2f2a7d47 178 case 0x1f: // set cursor to position X,Y
gertk 0:806c2f2a7d47 179 oldchar=ch; // this was the code of the initial call
gertk 0:806c2f2a7d47 180 queue_bytes=256-2; // for this call we need two more bytes
gertk 0:806c2f2a7d47 181 break;
gertk 0:806c2f2a7d47 182 // all else is put on screen literally
gertk 0:806c2f2a7d47 183 default:
gertk 0:806c2f2a7d47 184 putchar(ch);
gertk 0:806c2f2a7d47 185 break;
gertk 0:806c2f2a7d47 186 }
gertk 0:806c2f2a7d47 187 }
gertk 0:806c2f2a7d47 188 }
gertk 0:806c2f2a7d47 189
gertk 0:806c2f2a7d47 190
gertk 0:806c2f2a7d47 191 void init_ramtop() {
gertk 0:806c2f2a7d47 192
gertk 0:806c2f2a7d47 193
gertk 0:806c2f2a7d47 194 // set all MOS calls to illegal opcode 0xed55
gertk 0:806c2f2a7d47 195 // that code is trapped by a mbed routine
gertk 0:806c2f2a7d47 196 wrmem(OSWRCH,0xed);
gertk 0:806c2f2a7d47 197 wrmem(OSWRCH+1,0x55);
gertk 0:806c2f2a7d47 198
gertk 0:806c2f2a7d47 199 wrmem(OSWORD,0xed);
gertk 0:806c2f2a7d47 200 wrmem(OSWORD+1,0x55);
gertk 0:806c2f2a7d47 201
gertk 0:806c2f2a7d47 202 wrmem(OSBYTE,0xed);
gertk 0:806c2f2a7d47 203 wrmem(OSBYTE+1,0x55);
gertk 0:806c2f2a7d47 204
gertk 0:806c2f2a7d47 205 wrmem(OSRDCH,0xed);
gertk 0:806c2f2a7d47 206 wrmem(OSRDCH+1,0x55);
gertk 0:806c2f2a7d47 207
gertk 0:806c2f2a7d47 208 wrmem(OSNEWL,0xed);
gertk 0:806c2f2a7d47 209 wrmem(OSNEWL+1,0x55);
gertk 0:806c2f2a7d47 210
gertk 0:806c2f2a7d47 211 wrmem(OSASCI,0xed);
gertk 0:806c2f2a7d47 212 wrmem(OSASCI+1,0x55);
gertk 0:806c2f2a7d47 213
gertk 0:806c2f2a7d47 214 wrmem(OSRDCH,0xed);
gertk 0:806c2f2a7d47 215 wrmem(OSRDCH+1,0x55);
gertk 0:806c2f2a7d47 216
gertk 0:806c2f2a7d47 217 wrmem(MAINVDU,0xed);
gertk 0:806c2f2a7d47 218 wrmem(MAINVDU+1,0x55);
gertk 0:806c2f2a7d47 219
gertk 0:806c2f2a7d47 220 wrmem(GSINIT,0xed);
gertk 0:806c2f2a7d47 221 wrmem(GSINIT+1,0x55);
gertk 0:806c2f2a7d47 222
gertk 0:806c2f2a7d47 223 wrmem(GSREAD,0xed);
gertk 0:806c2f2a7d47 224 wrmem(GSREAD+1,0x55);
gertk 0:806c2f2a7d47 225
gertk 0:806c2f2a7d47 226 wrmem(OSRDRM,0xed);
gertk 0:806c2f2a7d47 227 wrmem(OSRDRM+1,0x55);
gertk 0:806c2f2a7d47 228
gertk 0:806c2f2a7d47 229 wrmem(OSEVEN,0xed);
gertk 0:806c2f2a7d47 230 wrmem(OSEVEN+1,0x55);
gertk 0:806c2f2a7d47 231
gertk 0:806c2f2a7d47 232 wrmem(OSCLI,0xed);
gertk 0:806c2f2a7d47 233 wrmem(OSCLI+1,0x55);
gertk 0:806c2f2a7d47 234
gertk 0:806c2f2a7d47 235 wrmem(OSFILE,0xed);
gertk 0:806c2f2a7d47 236 wrmem(OSFILE+1,0x55);
gertk 0:806c2f2a7d47 237
gertk 0:806c2f2a7d47 238 wrmem(CMDPTR,0xf0); // pointer to CR terminated string (auto start filename)
gertk 0:806c2f2a7d47 239 wrmem(CMDPTR+1,0x00); // it is set here to 0x00f0
gertk 0:806c2f2a7d47 240
gertk 0:806c2f2a7d47 241 wrmem(BRKV,0x00); // break vector
gertk 0:806c2f2a7d47 242 wrmem(BRKV+1,0x00);
gertk 0:806c2f2a7d47 243
gertk 0:806c2f2a7d47 244 wrmem(FAULT,0x38); // fault vector
gertk 0:806c2f2a7d47 245 wrmem(FAULT+1,0x00);
gertk 0:806c2f2a7d47 246 }
gertk 0:806c2f2a7d47 247
gertk 0:806c2f2a7d47 248 unsigned char getkey() {
gertk 0:806c2f2a7d47 249 unsigned char key=0x00;
gertk 0:806c2f2a7d47 250 if (linktopc.readable()) // get USB status
gertk 0:806c2f2a7d47 251 key=linktopc.getc(); // get ASCII key
gertk 0:806c2f2a7d47 252 return key;
gertk 0:806c2f2a7d47 253 }
gertk 0:806c2f2a7d47 254
gertk 0:806c2f2a7d47 255 // crude getline routine
gertk 0:806c2f2a7d47 256 void mygets(int ad,int max,unsigned char minasc,unsigned char maxasc) {
gertk 0:806c2f2a7d47 257 int n=0;
gertk 0:806c2f2a7d47 258 int key=0;
gertk 0:806c2f2a7d47 259
gertk 0:806c2f2a7d47 260 bool eflag=1;
gertk 0:806c2f2a7d47 261
gertk 0:806c2f2a7d47 262 // show cursor
gertk 0:806c2f2a7d47 263 set_cursor_position();
gertk 0:806c2f2a7d47 264
gertk 0:806c2f2a7d47 265 while (eflag) {
gertk 0:806c2f2a7d47 266 // key=getkey();
gertk 0:806c2f2a7d47 267 #if !DEBUG
gertk 0:806c2f2a7d47 268 // USB serial data ? then override key (only when NOT in debug mode)
gertk 0:806c2f2a7d47 269 if (linktopc.readable()) // get USB status
gertk 0:806c2f2a7d47 270 key=linktopc.getc(); // get ASCII key code
gertk 0:806c2f2a7d47 271 else key=0;
gertk 0:806c2f2a7d47 272 // key=getchar(); // BLOCKING MODE
gertk 0:806c2f2a7d47 273 #endif
gertk 0:806c2f2a7d47 274
gertk 0:806c2f2a7d47 275 if (key) // printf("got key code: %02x\n\r",key);
gertk 0:806c2f2a7d47 276
gertk 0:806c2f2a7d47 277 // only ASCII should arrive here
gertk 0:806c2f2a7d47 278 switch (key) {
gertk 0:806c2f2a7d47 279 case 0x00: // no key
gertk 0:806c2f2a7d47 280 break;
gertk 0:806c2f2a7d47 281 case 0x0d: // Enter or Return
gertk 0:806c2f2a7d47 282 wrmem(ad+n,key);
gertk 0:806c2f2a7d47 283 h=n;
gertk 0:806c2f2a7d47 284 // clear carry flag
gertk 0:806c2f2a7d47 285 anda(a); // z80 way of clearing carry...
gertk 0:806c2f2a7d47 286 eflag=0; // terminate the loop
gertk 0:806c2f2a7d47 287 printchar(key);
gertk 0:806c2f2a7d47 288 printchar(0x0a);
gertk 0:806c2f2a7d47 289 break;
gertk 0:806c2f2a7d47 290 case 0x1b: // Escape
gertk 0:806c2f2a7d47 291 wrmem(ad+n,key);
gertk 0:806c2f2a7d47 292 // set carry flag
gertk 0:806c2f2a7d47 293 f=(f&0xc4)|1|(a&0x28);
gertk 0:806c2f2a7d47 294 eflag=0;
gertk 0:806c2f2a7d47 295 h=n;
gertk 0:806c2f2a7d47 296 break;
gertk 0:806c2f2a7d47 297 case 0x15: // CTRL-U (clear input)
gertk 0:806c2f2a7d47 298 while (n) {
gertk 0:806c2f2a7d47 299
gertk 0:806c2f2a7d47 300 printchar(0x08);
gertk 0:806c2f2a7d47 301 printchar(0x20);
gertk 0:806c2f2a7d47 302 printchar(0x08);
gertk 0:806c2f2a7d47 303 n--;
gertk 0:806c2f2a7d47 304 }
gertk 0:806c2f2a7d47 305 wrmem(ad,0x0d);
gertk 0:806c2f2a7d47 306 break;
gertk 0:806c2f2a7d47 307 case 0x7f: // DELETE
gertk 0:806c2f2a7d47 308 if (n) {
gertk 0:806c2f2a7d47 309 n--;
gertk 0:806c2f2a7d47 310 printchar(0x08); // cursor left
gertk 0:806c2f2a7d47 311 printchar(0x20); // delete character by printing a space
gertk 0:806c2f2a7d47 312 printchar(0x08); // cursor left
gertk 0:806c2f2a7d47 313 wrmem(ad+n,0x20); // overwrite with space
gertk 0:806c2f2a7d47 314 }
gertk 0:806c2f2a7d47 315 break;
gertk 0:806c2f2a7d47 316 default: // all else
gertk 0:806c2f2a7d47 317 // keep within maximum lenght and given ascii limits
gertk 0:806c2f2a7d47 318 if ((key>=minasc) && (key<=maxasc) && n<max) {
gertk 0:806c2f2a7d47 319 wrmem(ad+n,key);
gertk 0:806c2f2a7d47 320 n++;
gertk 0:806c2f2a7d47 321 printchar(key);
gertk 0:806c2f2a7d47 322 }
gertk 0:806c2f2a7d47 323 break;
gertk 0:806c2f2a7d47 324 }
gertk 0:806c2f2a7d47 325 }
gertk 0:806c2f2a7d47 326 }
gertk 0:806c2f2a7d47 327
gertk 0:806c2f2a7d47 328
gertk 0:806c2f2a7d47 329 // OSWORD
gertk 0:806c2f2a7d47 330 void do_osword() {
gertk 0:806c2f2a7d47 331 int ad,n;
gertk 0:806c2f2a7d47 332 char buf[40];
gertk 0:806c2f2a7d47 333 time_t seconds;
gertk 0:806c2f2a7d47 334
gertk 0:806c2f2a7d47 335 // printf("OSWORD called with PC=%04x A=%02x HL=%02x%02x\n\r",pc,a,h,l);
gertk 0:806c2f2a7d47 336 switch (a) {
gertk 0:806c2f2a7d47 337
gertk 0:806c2f2a7d47 338 case 0x00: // get a line from the keyboard/input channel
gertk 0:806c2f2a7d47 339 ad=(h<<8)+l;
gertk 0:806c2f2a7d47 340 // printf("Control block:\n\r");
gertk 0:806c2f2a7d47 341 // printf("buffer address %02x%02x\n\r",rdmem(ad+1),rdmem(ad));
gertk 0:806c2f2a7d47 342 // printf("maximum length: %d\n\r",rdmem(ad+2));
gertk 0:806c2f2a7d47 343 // printf("minimum ASCII value %d\n\r",rdmem(ad+3));
gertk 0:806c2f2a7d47 344 // printf("maximum ASCII value %d\n\r",rdmem(ad+4));
gertk 0:806c2f2a7d47 345
gertk 0:806c2f2a7d47 346 mygets((rdmem(ad+1)<<8)+rdmem(ad),rdmem(ad+2),rdmem(ad+3),rdmem(ad+4));
gertk 0:806c2f2a7d47 347
gertk 0:806c2f2a7d47 348 break;
gertk 0:806c2f2a7d47 349 case 0x01: // read systemclock (long integer)
gertk 0:806c2f2a7d47 350 break;
gertk 0:806c2f2a7d47 351 case 0x02: // write systemclock (long integer)
gertk 0:806c2f2a7d47 352 break;
gertk 0:806c2f2a7d47 353 case 0x07: // emit a sound from the sound library (0-7)
gertk 0:806c2f2a7d47 354 break;
gertk 0:806c2f2a7d47 355 case 0x0e: // read TIME$ (not present in original BBC Basic)
gertk 0:806c2f2a7d47 356 ad=hl; // get pointer to function number
gertk 0:806c2f2a7d47 357 switch (rdmem(hl)) { // select function number
gertk 0:806c2f2a7d47 358 case 0: // return time string
gertk 0:806c2f2a7d47 359 seconds = time(NULL); // get current time from mbed RTC
gertk 0:806c2f2a7d47 360 strftime(buf,40, "%a,%d %m %Y.%H:%M:%S\r", localtime(&seconds)); // write to temporary buffer
gertk 0:806c2f2a7d47 361 n=0;
gertk 0:806c2f2a7d47 362 while (buf[n]) wrmem(ad++,buf[n++]); // copy to pointer from HL
gertk 0:806c2f2a7d47 363 break;
gertk 0:806c2f2a7d47 364 case 1: // return BCD values of clock
gertk 0:806c2f2a7d47 365 // On exit:
gertk 0:806c2f2a7d47 366 // XY?0=year (&00-&99)
gertk 0:806c2f2a7d47 367 // XY?1=month (&01-&12)
gertk 0:806c2f2a7d47 368 // XY?2=date (&01-&31)
gertk 0:806c2f2a7d47 369 // XY?3=day of week (&01-&07, Sun-Sat)
gertk 0:806c2f2a7d47 370 // XY?4=hours (&00-&23)
gertk 0:806c2f2a7d47 371 // XY?5=minutes (&00-&59)
gertk 0:806c2f2a7d47 372 // XY?6=seconds (&00-&59).
gertk 0:806c2f2a7d47 373 //
gertk 0:806c2f2a7d47 374 // A year value of &80-&99 represents 1980-1999, a value of
gertk 0:806c2f2a7d47 375 // &00-&79 represents 2000-2079.
gertk 0:806c2f2a7d47 376 //
gertk 0:806c2f2a7d47 377 break;
gertk 0:806c2f2a7d47 378 case 2: // Convert BCD to string.
gertk 0:806c2f2a7d47 379 // On entry:
gertk 0:806c2f2a7d47 380 // XY+1..7=BCD value
gertk 0:806c2f2a7d47 381 // On exit:
gertk 0:806c2f2a7d47 382 // XY+1..25=CR-terminated string
gertk 0:806c2f2a7d47 383 break;
gertk 0:806c2f2a7d47 384 }
gertk 0:806c2f2a7d47 385 break;
gertk 0:806c2f2a7d47 386 case 0x0f: // write TIME$ (not present in original BBC Basic)
gertk 0:806c2f2a7d47 387 // On entry:
gertk 0:806c2f2a7d47 388 // XY?0=function code
gertk 0:806c2f2a7d47 389 // XY+1.. value to use.
gertk 0:806c2f2a7d47 390 // Functions are:
gertk 0:806c2f2a7d47 391 // 8 - Set time to value in format "HH:MM:SS"
gertk 0:806c2f2a7d47 392 // 16 - Set date to value in format "Day,DD Mon Year"
gertk 0:806c2f2a7d47 393 // 24 - Set time and date to value in format
gertk 0:806c2f2a7d47 394 // "Day,DD Mon Year.HH:MM:SS"
gertk 0:806c2f2a7d47 395 n=0;
gertk 0:806c2f2a7d47 396 ad=hl;
gertk 0:806c2f2a7d47 397 // printf(" write time$ function %d\n\r",rdmem(ad));
gertk 0:806c2f2a7d47 398 ad++;
gertk 0:806c2f2a7d47 399 while (rdmem(ad)!=0x0d) buf[n++]=rdmem(ad++); // copy timestring to buffer
gertk 0:806c2f2a7d47 400 buf[n]=0;
gertk 0:806c2f2a7d47 401 // printf("trying to set time from %s\n\r",buf);
gertk 0:806c2f2a7d47 402 break;
gertk 0:806c2f2a7d47 403 }
gertk 0:806c2f2a7d47 404 }
gertk 0:806c2f2a7d47 405
gertk 0:806c2f2a7d47 406 // OSBYTE
gertk 0:806c2f2a7d47 407 // on 6502 A register and X,Y are used for Low,High parameters
gertk 0:806c2f2a7d47 408 // Z80 uses L and H (so X=L and H=Y <-> L=X and Y=H)
gertk 0:806c2f2a7d47 409 void do_osbyte() {
gertk 0:806c2f2a7d47 410 unsigned char temp;
gertk 0:806c2f2a7d47 411
gertk 0:806c2f2a7d47 412 // printf("OSBYTE called with PC=%04x A=%02x H=%02x L=%02x\n\r",pc,a,h,l);
gertk 0:806c2f2a7d47 413 switch (a) {
gertk 0:806c2f2a7d47 414 case 0x00: // NULL
gertk 0:806c2f2a7d47 415 l=0xff;
gertk 0:806c2f2a7d47 416 break;
gertk 0:806c2f2a7d47 417 case 0x13: // ASCII 19
gertk 0:806c2f2a7d47 418 break;
gertk 0:806c2f2a7d47 419 case 0x7c: // clear ESCAPE state
gertk 0:806c2f2a7d47 420 wrmem(0xff80,rdmem(0xff80)&0x7f);
gertk 0:806c2f2a7d47 421 break;
gertk 0:806c2f2a7d47 422 case 0x7d: // set ESCAPE state
gertk 0:806c2f2a7d47 423 wrmem(0xff80,rdmem(0xff80)|0x80);
gertk 0:806c2f2a7d47 424 break;
gertk 0:806c2f2a7d47 425 case 0x7e: // acknowledge ESCAPE state ? (CLOSE ALL!)
gertk 0:806c2f2a7d47 426 wrmem(0xff80,rdmem(0xff80)&0x7f);
gertk 0:806c2f2a7d47 427 break;
gertk 0:806c2f2a7d47 428 case 0x7f: // read EOF on channel
gertk 0:806c2f2a7d47 429 l=0x01;
gertk 0:806c2f2a7d47 430 break;
gertk 0:806c2f2a7d47 431 case 0x80: // read ADVAL(hl)
gertk 0:806c2f2a7d47 432 h=0;
gertk 0:806c2f2a7d47 433 l=0;
gertk 0:806c2f2a7d47 434 break;
gertk 0:806c2f2a7d47 435 case 0x81: // read key within time limit 'hl' centiseconds
gertk 0:806c2f2a7d47 436 temp=hl; // get timeout value (100th seconds)
gertk 0:806c2f2a7d47 437 do {
gertk 0:806c2f2a7d47 438 l=getkey();
gertk 0:806c2f2a7d47 439 wait(0.01);
gertk 0:806c2f2a7d47 440 } while ((temp--) && (!l));
gertk 0:806c2f2a7d47 441
gertk 0:806c2f2a7d47 442 if (l) { // we got a key
gertk 0:806c2f2a7d47 443 if (l==0x1b) { // Escape ?
gertk 0:806c2f2a7d47 444 f=(f&0xc4)|1|(a&0x28); // set carry
gertk 0:806c2f2a7d47 445 h=0x1b;
gertk 0:806c2f2a7d47 446 } else {
gertk 0:806c2f2a7d47 447 anda(a); // clear carry
gertk 0:806c2f2a7d47 448 h=0x00; // clear h
gertk 0:806c2f2a7d47 449 }
gertk 0:806c2f2a7d47 450 } else { // timeout
gertk 0:806c2f2a7d47 451 f=(f&0xc4)|1|(a&0x28); // set carry
gertk 0:806c2f2a7d47 452 h=0xff; // signal no key
gertk 0:806c2f2a7d47 453 }
gertk 0:806c2f2a7d47 454 break; // scan keyboard etc
gertk 0:806c2f2a7d47 455 case 0x82:
gertk 0:806c2f2a7d47 456 h=l=0;
gertk 0:806c2f2a7d47 457 break; // Machine high order address
gertk 0:806c2f2a7d47 458 case 0x83:
gertk 0:806c2f2a7d47 459 h=PAGE>>8;
gertk 0:806c2f2a7d47 460 l=(PAGE & 0xff);
gertk 0:806c2f2a7d47 461 break; // lowest available memory address (PAGE)
gertk 0:806c2f2a7d47 462 case 0x84: // highest available memory address (HIMEM)
gertk 0:806c2f2a7d47 463 h=RAMEND>>8;
gertk 0:806c2f2a7d47 464 l=RAMEND & 0xff;
gertk 0:806c2f2a7d47 465 break;
gertk 0:806c2f2a7d47 466 case 0x85: // read bottom of display RAM for a specific mode
gertk 0:806c2f2a7d47 467 h=0x80;
gertk 0:806c2f2a7d47 468 l=0x00;
gertk 0:806c2f2a7d47 469 break;
gertk 0:806c2f2a7d47 470 case 0x86: // return H=VPOS, L=POS
gertk 0:806c2f2a7d47 471 h=cursor_ypos;
gertk 0:806c2f2a7d47 472 l=cursor_xpos;
gertk 0:806c2f2a7d47 473 break;
gertk 0:806c2f2a7d47 474 case 0x87: // L=character on screen at cursor position
gertk 0:806c2f2a7d47 475 h=7;
gertk 0:806c2f2a7d47 476 l=0;
gertk 0:806c2f2a7d47 477 break;
gertk 0:806c2f2a7d47 478 case 0xda: // read/write the number of items in the VDU queue
gertk 0:806c2f2a7d47 479 // on return H contains the new value, L the old
gertk 0:806c2f2a7d47 480 temp=queue_bytes;
gertk 0:806c2f2a7d47 481 queue_bytes=(queue_bytes & h)^l;
gertk 0:806c2f2a7d47 482 h=queue_bytes;
gertk 0:806c2f2a7d47 483 l=temp;
gertk 0:806c2f2a7d47 484 break; // read/write the number of items in the VDU queue
gertk 0:806c2f2a7d47 485 }
gertk 0:806c2f2a7d47 486 // show_registers();
gertk 0:806c2f2a7d47 487 // wait(0.1);
gertk 0:806c2f2a7d47 488 }
gertk 0:806c2f2a7d47 489
gertk 0:806c2f2a7d47 490 void do_osreadchar() {
gertk 0:806c2f2a7d47 491 a=getchar();
gertk 0:806c2f2a7d47 492 // test for ESCAPE
gertk 0:806c2f2a7d47 493 if (a==27) {
gertk 0:806c2f2a7d47 494 f=(f&0xc4)|1|(a&0x28);
gertk 0:806c2f2a7d47 495 wrmem(0xff80,rdmem(0xff80)|0x80);
gertk 0:806c2f2a7d47 496 }
gertk 0:806c2f2a7d47 497 }
gertk 0:806c2f2a7d47 498
gertk 0:806c2f2a7d47 499 void do_osnewline() {
gertk 0:806c2f2a7d47 500 printchar(0x0a);
gertk 0:806c2f2a7d47 501 printchar(0x0d);
gertk 0:806c2f2a7d47 502 a=0x0d;
gertk 0:806c2f2a7d47 503 }
gertk 0:806c2f2a7d47 504
gertk 0:806c2f2a7d47 505 void do_osasci() {
gertk 0:806c2f2a7d47 506 if (a==0x0d) do_osnewline();
gertk 0:806c2f2a7d47 507 else printchar(a);
gertk 0:806c2f2a7d47 508 }
gertk 0:806c2f2a7d47 509
gertk 0:806c2f2a7d47 510 void do_mainvdu() {
gertk 0:806c2f2a7d47 511 printchar(a);
gertk 0:806c2f2a7d47 512 }
gertk 0:806c2f2a7d47 513
gertk 0:806c2f2a7d47 514 void do_gsinit() {
gertk 0:806c2f2a7d47 515 printf("GSINIT called with PC=%04x A=%02x\n\r",pc,a);
gertk 0:806c2f2a7d47 516 }
gertk 0:806c2f2a7d47 517
gertk 0:806c2f2a7d47 518 void do_gsread() {
gertk 0:806c2f2a7d47 519 }
gertk 0:806c2f2a7d47 520
gertk 0:806c2f2a7d47 521 void do_osrdrm() {
gertk 0:806c2f2a7d47 522 printf("OSRDRM called with PC=%04x A=%02x H=%02x L=%02x\n\r",pc,a,h,l);
gertk 0:806c2f2a7d47 523 }
gertk 0:806c2f2a7d47 524
gertk 0:806c2f2a7d47 525 void do_oseven() {
gertk 0:806c2f2a7d47 526 printf("OSEVEN called with PC=%04x A=%02x H=%02x L=%02x\n\r",pc,a,h,l);
gertk 0:806c2f2a7d47 527 }
gertk 0:806c2f2a7d47 528
gertk 0:806c2f2a7d47 529 void do_oscli() {
gertk 0:806c2f2a7d47 530 printf("OSCLI called with PC=%04x A=%02x H=%02x L=%02x\n\r",pc,a,h,l);
gertk 0:806c2f2a7d47 531 do {
gertk 0:806c2f2a7d47 532 a=rdmem((h<<8)+l);
gertk 0:806c2f2a7d47 533 if (!++l)h++;
gertk 0:806c2f2a7d47 534 putchar(a);
gertk 0:806c2f2a7d47 535 } while (a!=0x0d);
gertk 0:806c2f2a7d47 536 }
gertk 0:806c2f2a7d47 537
gertk 0:806c2f2a7d47 538 void do_osfile() {
gertk 0:806c2f2a7d47 539 char buffer[200];
gertk 0:806c2f2a7d47 540 int n=0;
gertk 0:806c2f2a7d47 541 FILE *fp;
gertk 0:806c2f2a7d47 542 // get address of control block
gertk 0:806c2f2a7d47 543 int controlblock=hl;
gertk 0:806c2f2a7d47 544 int offset=rdmem(controlblock)+(rdmem(controlblock+1)<<8);
gertk 0:806c2f2a7d47 545 // create a kludgy pointer from this offset to the filename
gertk 0:806c2f2a7d47 546 char *filename=(char *)(ram+offset-RAMSTART);
gertk 0:806c2f2a7d47 547 long load_address=rdmem(controlblock+2)+(rdmem(controlblock+3)<<8)+(rdmem(controlblock+4)<<16)+(rdmem(controlblock+5)<<24);
gertk 0:806c2f2a7d47 548 long execution_address=rdmem(controlblock+6)+(rdmem(controlblock+7)<<8)+(rdmem(controlblock+8)<<16)+(rdmem(controlblock+9)<<24);
gertk 0:806c2f2a7d47 549 long start_or_length=rdmem(controlblock+10)+(rdmem(controlblock+11)<<8)+(rdmem(controlblock+12)<<16)+(rdmem(controlblock+13)<<24);
gertk 0:806c2f2a7d47 550 long end_address_or_attributes=rdmem(controlblock+14)+(rdmem(controlblock+15)<<8)+(rdmem(controlblock+16)<<16)+(rdmem(controlblock+17)<<24);
gertk 0:806c2f2a7d47 551
gertk 0:806c2f2a7d47 552
gertk 0:806c2f2a7d47 553 // printf("OSFILE called with PC=%04x A=%02x H=%02x L=%02x\n\r",pc,a,h,l);
gertk 0:806c2f2a7d47 554
gertk 0:806c2f2a7d47 555 // for (n=0; n<=0x11; n++) printf("offset %02x value %02x\n\r",n,rdmem(controlblock+n));
gertk 0:806c2f2a7d47 556
gertk 0:806c2f2a7d47 557 n=0;
gertk 0:806c2f2a7d47 558 while (filename[n]!=0x0d) n++;
gertk 0:806c2f2a7d47 559 // overwrite 0x0d with end of string
gertk 0:806c2f2a7d47 560 filename[n]=0x00;
gertk 0:806c2f2a7d47 561
gertk 0:806c2f2a7d47 562 // now determine what to do
gertk 0:806c2f2a7d47 563 switch (a) {
gertk 0:806c2f2a7d47 564 case 0x00: // save a section of memory as a named file
gertk 0:806c2f2a7d47 565 sprintf(buffer,"/local/%s",filename);
gertk 0:806c2f2a7d47 566 // printf("Saving file %s load adr:%08lx exec adr:%08lx start/length%08lx end/attr:%08lx\n\r",filename,load_address,execution_address,start_or_length,end_address_or_attributes);
gertk 0:806c2f2a7d47 567 fp=fopen(buffer, "w");
gertk 0:806c2f2a7d47 568 if (fp) {
gertk 0:806c2f2a7d47 569 n=start_or_length;
gertk 0:806c2f2a7d47 570 while (n!=end_address_or_attributes) fputc(rdmem(n++),fp);
gertk 0:806c2f2a7d47 571 fclose(fp);
gertk 0:806c2f2a7d47 572 a=1;
gertk 0:806c2f2a7d47 573 } else {
gertk 0:806c2f2a7d47 574 // printf("could not write %s\n\r",buffer);
gertk 0:806c2f2a7d47 575 a=0;
gertk 0:806c2f2a7d47 576 pc=rdmem(0xfffa)+(rdmem(0xfffb)<<8); // do BRK
gertk 0:806c2f2a7d47 577 }
gertk 0:806c2f2a7d47 578 break;
gertk 0:806c2f2a7d47 579 case 0x01: // write the catalogue information (only) for the named file (disc only)
gertk 0:806c2f2a7d47 580 break;
gertk 0:806c2f2a7d47 581 case 0x02: // write the load address (only) for the named file (disc only)
gertk 0:806c2f2a7d47 582 break;
gertk 0:806c2f2a7d47 583 case 0x03: // write the execution address (only) for the named file (disc only)
gertk 0:806c2f2a7d47 584 break;
gertk 0:806c2f2a7d47 585 case 0x04: // write the attributes (only) for the named file (disc only)
gertk 0:806c2f2a7d47 586 break;
gertk 0:806c2f2a7d47 587 case 0x05: // read the named file's catalogue information, place file type in A (disc only)
gertk 0:806c2f2a7d47 588 break;
gertk 0:806c2f2a7d47 589 case 0x06: // delete the named file (disc only)
gertk 0:806c2f2a7d47 590 break;
gertk 0:806c2f2a7d47 591 case 0xff: // load the named file and read the named file's catalogue information
gertk 0:806c2f2a7d47 592 sprintf(buffer,"/local/%s",filename);
gertk 0:806c2f2a7d47 593 // printf("Loading file %s load adr:%08lx exec adr:%08lx start/length%08lx end/attr:%08lx\n\r",buffer,load_address,execution_address,start_or_length,end_address_or_attributes);
gertk 0:806c2f2a7d47 594 fp = fopen(buffer, "r");
gertk 0:806c2f2a7d47 595 if (fp) {
gertk 0:806c2f2a7d47 596 n=load_address;
gertk 0:806c2f2a7d47 597 while (!feof(fp)) wrmem(n++,fgetc(fp));
gertk 0:806c2f2a7d47 598 fclose(fp);
gertk 0:806c2f2a7d47 599 a=1; // file found
gertk 0:806c2f2a7d47 600 } else {
gertk 0:806c2f2a7d47 601 // printf("Could not open %s\n",buffer);
gertk 0:806c2f2a7d47 602 a=0;
gertk 0:806c2f2a7d47 603 pc=rdmem(0xfffa)+(rdmem(0xfffb)<<8); // do BRK
gertk 0:806c2f2a7d47 604 }
gertk 0:806c2f2a7d47 605 break;
gertk 0:806c2f2a7d47 606 }
gertk 0:806c2f2a7d47 607 }
gertk 0:806c2f2a7d47 608
gertk 0:806c2f2a7d47 609 void terminalgets(char *buffer) {
gertk 0:806c2f2a7d47 610 int n=0;
gertk 0:806c2f2a7d47 611 int key=0;
gertk 0:806c2f2a7d47 612 do {
gertk 0:806c2f2a7d47 613 key=getchar();
gertk 0:806c2f2a7d47 614 buffer[n]=key;
gertk 0:806c2f2a7d47 615 putchar(key);
gertk 0:806c2f2a7d47 616 if (n<16) n++;
gertk 0:806c2f2a7d47 617 } while (key != 0x0d);
gertk 0:806c2f2a7d47 618 buffer[n]=0;
gertk 0:806c2f2a7d47 619 }
gertk 0:806c2f2a7d47 620
gertk 0:806c2f2a7d47 621
gertk 0:806c2f2a7d47 622 // here the OS calls are recognized and
gertk 0:806c2f2a7d47 623 // diverted to the mbed routines.
gertk 0:806c2f2a7d47 624 // this needs to be replaced by native Z80 code
gertk 0:806c2f2a7d47 625 void do_mos() {
gertk 0:806c2f2a7d47 626 // printf("Entering MOS emulation with PC %04x\n\r",pc);
gertk 0:806c2f2a7d47 627
gertk 0:806c2f2a7d47 628 // compensate pc for length of ED55 opcode
gertk 0:806c2f2a7d47 629 switch (pc-2) {
gertk 0:806c2f2a7d47 630 case OSBYTE:
gertk 0:806c2f2a7d47 631 do_osbyte();
gertk 0:806c2f2a7d47 632 break;
gertk 0:806c2f2a7d47 633 case OSWORD:
gertk 0:806c2f2a7d47 634 do_osword();
gertk 0:806c2f2a7d47 635 break;
gertk 0:806c2f2a7d47 636 case OSWRCH:
gertk 0:806c2f2a7d47 637 printchar(a);
gertk 0:806c2f2a7d47 638 break;
gertk 0:806c2f2a7d47 639 case OSRDCH:
gertk 0:806c2f2a7d47 640 do_osreadchar();
gertk 0:806c2f2a7d47 641 break;
gertk 0:806c2f2a7d47 642 case OSNEWL:
gertk 0:806c2f2a7d47 643 do_osnewline();
gertk 0:806c2f2a7d47 644 break;
gertk 0:806c2f2a7d47 645 case OSASCI:
gertk 0:806c2f2a7d47 646 do_osasci();
gertk 0:806c2f2a7d47 647 break;
gertk 0:806c2f2a7d47 648 case MAINVDU:
gertk 0:806c2f2a7d47 649 do_mainvdu();
gertk 0:806c2f2a7d47 650 break;
gertk 0:806c2f2a7d47 651 case GSINIT:
gertk 0:806c2f2a7d47 652 do_gsinit();
gertk 0:806c2f2a7d47 653 break;
gertk 0:806c2f2a7d47 654 case GSREAD:
gertk 0:806c2f2a7d47 655 do_gsread();
gertk 0:806c2f2a7d47 656 break;
gertk 0:806c2f2a7d47 657 case OSRDRM:
gertk 0:806c2f2a7d47 658 do_osrdrm();
gertk 0:806c2f2a7d47 659 break;
gertk 0:806c2f2a7d47 660 case OSEVEN:
gertk 0:806c2f2a7d47 661 do_oseven();
gertk 0:806c2f2a7d47 662 break;
gertk 0:806c2f2a7d47 663 case OSCLI:
gertk 0:806c2f2a7d47 664 do_oscli();
gertk 0:806c2f2a7d47 665 break;
gertk 0:806c2f2a7d47 666 case OSFILE:
gertk 0:806c2f2a7d47 667 do_osfile();
gertk 0:806c2f2a7d47 668 break;
gertk 0:806c2f2a7d47 669 }
gertk 0:806c2f2a7d47 670 }
gertk 0:806c2f2a7d47 671
gertk 0:806c2f2a7d47 672 void listdir(void) {
gertk 0:806c2f2a7d47 673 DIR *d;
gertk 0:806c2f2a7d47 674 struct dirent *p;
gertk 0:806c2f2a7d47 675
gertk 0:806c2f2a7d47 676 d = opendir("/sd");
gertk 0:806c2f2a7d47 677 if (d != NULL) {
gertk 0:806c2f2a7d47 678 while ((p = readdir(d)) != NULL) {
gertk 0:806c2f2a7d47 679 printf(" - %s\r\n", p->d_name);
gertk 0:806c2f2a7d47 680 }
gertk 0:806c2f2a7d47 681 } else {
gertk 0:806c2f2a7d47 682 printf("Could not open directory!\n");
gertk 0:806c2f2a7d47 683 }
gertk 0:806c2f2a7d47 684 closedir(d);
gertk 0:806c2f2a7d47 685 }
gertk 0:806c2f2a7d47 686
gertk 0:806c2f2a7d47 687
gertk 0:806c2f2a7d47 688
gertk 0:806c2f2a7d47 689
gertk 0:806c2f2a7d47 690
gertk 0:806c2f2a7d47 691 // ================================================================
gertk 0:806c2f2a7d47 692 // main loop
gertk 0:806c2f2a7d47 693 // ================================================================
gertk 0:806c2f2a7d47 694 int main() {
gertk 0:806c2f2a7d47 695
gertk 0:806c2f2a7d47 696 // serial port on at 115200 baud
gertk 0:806c2f2a7d47 697 linktopc.baud(115200);
gertk 0:806c2f2a7d47 698 setbuf(stdout, NULL); // no buffering for this filehandle
gertk 0:806c2f2a7d47 699
gertk 0:806c2f2a7d47 700 // reset all Z80 registers to some initial values
gertk 0:806c2f2a7d47 701 a=f=b=c=d=e=h=l=a1=f1=b1=c1=d1=e1=h1=l1=i=iff1=iff2=im=r=0;
gertk 0:806c2f2a7d47 702 ixoriy=new_ixoriy=0;
gertk 0:806c2f2a7d47 703 ix=iy=sp=pc=0;
gertk 0:806c2f2a7d47 704
gertk 0:806c2f2a7d47 705 queue_bytes=0;
gertk 0:806c2f2a7d47 706
gertk 0:806c2f2a7d47 707 // init MOS vectors
gertk 0:806c2f2a7d47 708 init_ramtop();
gertk 0:806c2f2a7d47 709
gertk 0:806c2f2a7d47 710 init_screen();
gertk 0:806c2f2a7d47 711 home_cursor();
gertk 0:806c2f2a7d47 712
gertk 0:806c2f2a7d47 713 // endless loop
gertk 0:806c2f2a7d47 714 while (1) {
gertk 0:806c2f2a7d47 715 // wait(0.01);
gertk 0:806c2f2a7d47 716 r++;
gertk 0:806c2f2a7d47 717 // this is some optimization for the IX and IY opcodes (DD/FD)
gertk 0:806c2f2a7d47 718 ixoriy=new_ixoriy;
gertk 0:806c2f2a7d47 719 new_ixoriy=0;
gertk 0:806c2f2a7d47 720
gertk 0:806c2f2a7d47 721 // fetch opcode and execute, the include does all the heavy decoding
gertk 0:806c2f2a7d47 722 switch (fetch(pc++)) {
gertk 0:806c2f2a7d47 723 #include "z80ops.h"
gertk 0:806c2f2a7d47 724 }
gertk 0:806c2f2a7d47 725
gertk 0:806c2f2a7d47 726 // next is the interrupt emulator (only IM1 mode)
gertk 0:806c2f2a7d47 727 // interrupt pending? if new_ixoriy is set or iff1==0 don't do interrupt yet (continue DD/FD opcode)
gertk 0:806c2f2a7d47 728 // if (intpend && !new_ixoriy && iff1) {
gertk 0:806c2f2a7d47 729 // are we HALT-ed ? then resume
gertk 0:806c2f2a7d47 730 // if (fetch(pc)==0x76) pc++;
gertk 0:806c2f2a7d47 731
gertk 0:806c2f2a7d47 732 // block further interrupts for now
gertk 0:806c2f2a7d47 733 // iff1=0;
gertk 0:806c2f2a7d47 734
gertk 0:806c2f2a7d47 735 // do the call to 00x38
gertk 0:806c2f2a7d47 736 // push2(pc); // save old pc
gertk 0:806c2f2a7d47 737 // pc=0x0038; // setup new pc
gertk 0:806c2f2a7d47 738 // intpend=0; // release interrupt pending flag;
gertk 0:806c2f2a7d47 739 // } // if intpend
gertk 0:806c2f2a7d47 740 } // while
gertk 0:806c2f2a7d47 741 }