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.
main.cpp
00001 /* BBC Basic emulator on NXP mbed by Gert van der Knokke 00002 * Emulation of the Z80 CPU 00003 * The z80 emulator is heavily modified by me (Gert) 00004 * original Copyright (C) 1994 Ian Collier. 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 */ 00020 00021 #include "mbed.h" 00022 #include "module.h" 00023 #include "z80.h" 00024 00025 #define DEBUG false 00026 00027 // define serial port for debug 00028 Serial linktopc(USBTX,USBRX); 00029 00030 00031 // VDU queue 00032 unsigned char vdu_queue[256]; // a somewhat large queue 00033 unsigned char queue_bytes=0; // vdu queue pointer 00034 unsigned char oldchar; // which VDU function needs the queue 00035 00036 volatile unsigned char flag,oldy=0; 00037 00038 00039 int background_color; // for clear screen 00040 int cursor_xpos; 00041 int cursor_ypos; 00042 int last_line_processed; 00043 int previous_line_found; 00044 00045 int current_background_color; 00046 int current_text_color; 00047 00048 00049 // prepare mbed storage for local use 00050 LocalFileSystem local("local"); // Create the local filesystem under the name "local" 00051 00052 // clear the screen 00053 void cls() { 00054 putchar(0x0c); 00055 } 00056 00057 // dummy function 00058 void set_cursor_position() { 00059 } 00060 00061 // home cursor 00062 void home_cursor() { 00063 cursor_xpos=0x00; // ypos 00064 cursor_ypos=0x00; // xpos 00065 set_cursor_position(); 00066 } 00067 00068 // prepare the screen 00069 void init_screen() { 00070 current_background_color=0; // set initial background color 00071 current_text_color=7; // initial text color attributes 00072 cls(); 00073 home_cursor(); 00074 } 00075 00076 // handle VDU calls after all bytes are in queue 00077 // Note! queue is working front to back (255 is first, 0 is last) 00078 void do_handle_queue(unsigned char code) { 00079 switch (code) { 00080 case 0x11: // select text color 00081 current_text_color=vdu_queue[255]; 00082 break; 00083 case 0x16: // Mode 00084 current_text_color=7; 00085 current_background_color=0; 00086 init_screen(); 00087 home_cursor(); 00088 break; 00089 case 0x17: // define character n 00090 break; 00091 case 0x1f: // move cursor to x,y 00092 cursor_xpos=vdu_queue[254]; 00093 cursor_ypos=vdu_queue[255]; 00094 set_cursor_position(); 00095 break; 00096 } 00097 } 00098 00099 // VDU OSWRCHR 00100 // this routine evaluates the stream characters 00101 // and prepares the queue if needed 00102 void printchar(unsigned char ch) { 00103 00104 // do we need more queue bytes ? 00105 if (queue_bytes) { 00106 vdu_queue[queue_bytes++]=ch; 00107 // all bytes in queue, now handle the call 00108 if (queue_bytes==0) 00109 do_handle_queue(oldchar); 00110 00111 } else { 00112 00113 switch (ch) { 00114 case 0x00: // NULL 00115 break; 00116 case 0x08: // CURSOR LEFT 00117 putchar(0x08); 00118 if (cursor_xpos>0) { 00119 cursor_xpos--; 00120 set_cursor_position(); 00121 } 00122 break; 00123 case 0x09: // CURSOR RIGHT 00124 if (cursor_xpos<39) { 00125 cursor_xpos++; 00126 set_cursor_position(); 00127 } 00128 break; 00129 case 0x0a: // CURSOR DOWN 00130 if (cursor_ypos<23) { 00131 cursor_ypos++; 00132 set_cursor_position(); 00133 } else { 00134 cursor_ypos=23; 00135 } 00136 break; 00137 case 0x0b: // CURSOR UP 00138 cursor_ypos++; 00139 if (cursor_ypos>0) { 00140 cursor_ypos--; 00141 set_cursor_position(); 00142 } else { 00143 cursor_ypos=0; 00144 } 00145 break; 00146 case 0x0d: // Carriage Return 00147 cursor_xpos=0; 00148 putchar(0x0d); 00149 putchar(0x0a); 00150 set_cursor_position(); 00151 break; 00152 case 0x0c: // CLEAR TEXT WINDOW 00153 case 0x10: // CLEAR GRAPHIC WINDOW 00154 cls(); 00155 cursor_xpos=0; 00156 cursor_ypos=0; 00157 set_cursor_position(); 00158 break; 00159 case 0x11: // set TEXT color 00160 oldchar=ch; // this was the code of the initial call 00161 queue_bytes=256-1; // for this call we need one more byte 00162 break; 00163 case 0x14: // reset colors 00164 current_text_color=7; 00165 current_background_color=0; 00166 break; 00167 case 0x16: // MODE select 00168 oldchar=ch; 00169 queue_bytes=256-1; 00170 break; 00171 case 0x17: // define character n 00172 break; 00173 case 0x1e: 00174 cursor_xpos=0; 00175 cursor_ypos=0; 00176 set_cursor_position(); 00177 break; 00178 case 0x1f: // set cursor to position X,Y 00179 oldchar=ch; // this was the code of the initial call 00180 queue_bytes=256-2; // for this call we need two more bytes 00181 break; 00182 // all else is put on screen literally 00183 default: 00184 putchar(ch); 00185 break; 00186 } 00187 } 00188 } 00189 00190 00191 void init_ramtop() { 00192 00193 00194 // set all MOS calls to illegal opcode 0xed55 00195 // that code is trapped by a mbed routine 00196 wrmem(OSWRCH,0xed); 00197 wrmem(OSWRCH+1,0x55); 00198 00199 wrmem(OSWORD,0xed); 00200 wrmem(OSWORD+1,0x55); 00201 00202 wrmem(OSBYTE,0xed); 00203 wrmem(OSBYTE+1,0x55); 00204 00205 wrmem(OSRDCH,0xed); 00206 wrmem(OSRDCH+1,0x55); 00207 00208 wrmem(OSNEWL,0xed); 00209 wrmem(OSNEWL+1,0x55); 00210 00211 wrmem(OSASCI,0xed); 00212 wrmem(OSASCI+1,0x55); 00213 00214 wrmem(OSRDCH,0xed); 00215 wrmem(OSRDCH+1,0x55); 00216 00217 wrmem(MAINVDU,0xed); 00218 wrmem(MAINVDU+1,0x55); 00219 00220 wrmem(GSINIT,0xed); 00221 wrmem(GSINIT+1,0x55); 00222 00223 wrmem(GSREAD,0xed); 00224 wrmem(GSREAD+1,0x55); 00225 00226 wrmem(OSRDRM,0xed); 00227 wrmem(OSRDRM+1,0x55); 00228 00229 wrmem(OSEVEN,0xed); 00230 wrmem(OSEVEN+1,0x55); 00231 00232 wrmem(OSCLI,0xed); 00233 wrmem(OSCLI+1,0x55); 00234 00235 wrmem(OSFILE,0xed); 00236 wrmem(OSFILE+1,0x55); 00237 00238 wrmem(CMDPTR,0xf0); // pointer to CR terminated string (auto start filename) 00239 wrmem(CMDPTR+1,0x00); // it is set here to 0x00f0 00240 00241 wrmem(BRKV,0x00); // break vector 00242 wrmem(BRKV+1,0x00); 00243 00244 wrmem(FAULT,0x38); // fault vector 00245 wrmem(FAULT+1,0x00); 00246 } 00247 00248 unsigned char getkey() { 00249 unsigned char key=0x00; 00250 if (linktopc.readable()) // get USB status 00251 key=linktopc.getc(); // get ASCII key 00252 return key; 00253 } 00254 00255 // crude getline routine 00256 void mygets(int ad,int max,unsigned char minasc,unsigned char maxasc) { 00257 int n=0; 00258 int key=0; 00259 00260 bool eflag=1; 00261 00262 // show cursor 00263 set_cursor_position(); 00264 00265 while (eflag) { 00266 // key=getkey(); 00267 #if !DEBUG 00268 // USB serial data ? then override key (only when NOT in debug mode) 00269 if (linktopc.readable()) // get USB status 00270 key=linktopc.getc(); // get ASCII key code 00271 else key=0; 00272 // key=getchar(); // BLOCKING MODE 00273 #endif 00274 00275 if (key) // printf("got key code: %02x\n\r",key); 00276 00277 // only ASCII should arrive here 00278 switch (key) { 00279 case 0x00: // no key 00280 break; 00281 case 0x0d: // Enter or Return 00282 wrmem(ad+n,key); 00283 h=n; 00284 // clear carry flag 00285 anda(a); // z80 way of clearing carry... 00286 eflag=0; // terminate the loop 00287 printchar(key); 00288 printchar(0x0a); 00289 break; 00290 case 0x1b: // Escape 00291 wrmem(ad+n,key); 00292 // set carry flag 00293 f=(f&0xc4)|1|(a&0x28); 00294 eflag=0; 00295 h=n; 00296 break; 00297 case 0x15: // CTRL-U (clear input) 00298 while (n) { 00299 00300 printchar(0x08); 00301 printchar(0x20); 00302 printchar(0x08); 00303 n--; 00304 } 00305 wrmem(ad,0x0d); 00306 break; 00307 case 0x7f: // DELETE 00308 if (n) { 00309 n--; 00310 printchar(0x08); // cursor left 00311 printchar(0x20); // delete character by printing a space 00312 printchar(0x08); // cursor left 00313 wrmem(ad+n,0x20); // overwrite with space 00314 } 00315 break; 00316 default: // all else 00317 // keep within maximum lenght and given ascii limits 00318 if ((key>=minasc) && (key<=maxasc) && n<max) { 00319 wrmem(ad+n,key); 00320 n++; 00321 printchar(key); 00322 } 00323 break; 00324 } 00325 } 00326 } 00327 00328 00329 // OSWORD 00330 void do_osword() { 00331 int ad,n; 00332 char buf[40]; 00333 time_t seconds; 00334 00335 // printf("OSWORD called with PC=%04x A=%02x HL=%02x%02x\n\r",pc,a,h,l); 00336 switch (a) { 00337 00338 case 0x00: // get a line from the keyboard/input channel 00339 ad=(h<<8)+l; 00340 // printf("Control block:\n\r"); 00341 // printf("buffer address %02x%02x\n\r",rdmem(ad+1),rdmem(ad)); 00342 // printf("maximum length: %d\n\r",rdmem(ad+2)); 00343 // printf("minimum ASCII value %d\n\r",rdmem(ad+3)); 00344 // printf("maximum ASCII value %d\n\r",rdmem(ad+4)); 00345 00346 mygets((rdmem(ad+1)<<8)+rdmem(ad),rdmem(ad+2),rdmem(ad+3),rdmem(ad+4)); 00347 00348 break; 00349 case 0x01: // read systemclock (long integer) 00350 break; 00351 case 0x02: // write systemclock (long integer) 00352 break; 00353 case 0x07: // emit a sound from the sound library (0-7) 00354 break; 00355 case 0x0e: // read TIME$ (not present in original BBC Basic) 00356 ad=hl; // get pointer to function number 00357 switch (rdmem(hl)) { // select function number 00358 case 0: // return time string 00359 seconds = time(NULL); // get current time from mbed RTC 00360 strftime(buf,40, "%a,%d %m %Y.%H:%M:%S\r", localtime(&seconds)); // write to temporary buffer 00361 n=0; 00362 while (buf[n]) wrmem(ad++,buf[n++]); // copy to pointer from HL 00363 break; 00364 case 1: // return BCD values of clock 00365 // On exit: 00366 // XY?0=year (&00-&99) 00367 // XY?1=month (&01-&12) 00368 // XY?2=date (&01-&31) 00369 // XY?3=day of week (&01-&07, Sun-Sat) 00370 // XY?4=hours (&00-&23) 00371 // XY?5=minutes (&00-&59) 00372 // XY?6=seconds (&00-&59). 00373 // 00374 // A year value of &80-&99 represents 1980-1999, a value of 00375 // &00-&79 represents 2000-2079. 00376 // 00377 break; 00378 case 2: // Convert BCD to string. 00379 // On entry: 00380 // XY+1..7=BCD value 00381 // On exit: 00382 // XY+1..25=CR-terminated string 00383 break; 00384 } 00385 break; 00386 case 0x0f: // write TIME$ (not present in original BBC Basic) 00387 // On entry: 00388 // XY?0=function code 00389 // XY+1.. value to use. 00390 // Functions are: 00391 // 8 - Set time to value in format "HH:MM:SS" 00392 // 16 - Set date to value in format "Day,DD Mon Year" 00393 // 24 - Set time and date to value in format 00394 // "Day,DD Mon Year.HH:MM:SS" 00395 n=0; 00396 ad=hl; 00397 // printf(" write time$ function %d\n\r",rdmem(ad)); 00398 ad++; 00399 while (rdmem(ad)!=0x0d) buf[n++]=rdmem(ad++); // copy timestring to buffer 00400 buf[n]=0; 00401 // printf("trying to set time from %s\n\r",buf); 00402 break; 00403 } 00404 } 00405 00406 // OSBYTE 00407 // on 6502 A register and X,Y are used for Low,High parameters 00408 // Z80 uses L and H (so X=L and H=Y <-> L=X and Y=H) 00409 void do_osbyte() { 00410 unsigned char temp; 00411 00412 // printf("OSBYTE called with PC=%04x A=%02x H=%02x L=%02x\n\r",pc,a,h,l); 00413 switch (a) { 00414 case 0x00: // NULL 00415 l=0xff; 00416 break; 00417 case 0x13: // ASCII 19 00418 break; 00419 case 0x7c: // clear ESCAPE state 00420 wrmem(0xff80,rdmem(0xff80)&0x7f); 00421 break; 00422 case 0x7d: // set ESCAPE state 00423 wrmem(0xff80,rdmem(0xff80)|0x80); 00424 break; 00425 case 0x7e: // acknowledge ESCAPE state ? (CLOSE ALL!) 00426 wrmem(0xff80,rdmem(0xff80)&0x7f); 00427 break; 00428 case 0x7f: // read EOF on channel 00429 l=0x01; 00430 break; 00431 case 0x80: // read ADVAL(hl) 00432 h=0; 00433 l=0; 00434 break; 00435 case 0x81: // read key within time limit 'hl' centiseconds 00436 temp=hl; // get timeout value (100th seconds) 00437 do { 00438 l=getkey(); 00439 wait(0.01); 00440 } while ((temp--) && (!l)); 00441 00442 if (l) { // we got a key 00443 if (l==0x1b) { // Escape ? 00444 f=(f&0xc4)|1|(a&0x28); // set carry 00445 h=0x1b; 00446 } else { 00447 anda(a); // clear carry 00448 h=0x00; // clear h 00449 } 00450 } else { // timeout 00451 f=(f&0xc4)|1|(a&0x28); // set carry 00452 h=0xff; // signal no key 00453 } 00454 break; // scan keyboard etc 00455 case 0x82: 00456 h=l=0; 00457 break; // Machine high order address 00458 case 0x83: 00459 h=PAGE>>8; 00460 l=(PAGE & 0xff); 00461 break; // lowest available memory address (PAGE) 00462 case 0x84: // highest available memory address (HIMEM) 00463 h=RAMEND>>8; 00464 l=RAMEND & 0xff; 00465 break; 00466 case 0x85: // read bottom of display RAM for a specific mode 00467 h=0x80; 00468 l=0x00; 00469 break; 00470 case 0x86: // return H=VPOS, L=POS 00471 h=cursor_ypos; 00472 l=cursor_xpos; 00473 break; 00474 case 0x87: // L=character on screen at cursor position 00475 h=7; 00476 l=0; 00477 break; 00478 case 0xda: // read/write the number of items in the VDU queue 00479 // on return H contains the new value, L the old 00480 temp=queue_bytes; 00481 queue_bytes=(queue_bytes & h)^l; 00482 h=queue_bytes; 00483 l=temp; 00484 break; // read/write the number of items in the VDU queue 00485 } 00486 // show_registers(); 00487 // wait(0.1); 00488 } 00489 00490 void do_osreadchar() { 00491 a=getchar(); 00492 // test for ESCAPE 00493 if (a==27) { 00494 f=(f&0xc4)|1|(a&0x28); 00495 wrmem(0xff80,rdmem(0xff80)|0x80); 00496 } 00497 } 00498 00499 void do_osnewline() { 00500 printchar(0x0a); 00501 printchar(0x0d); 00502 a=0x0d; 00503 } 00504 00505 void do_osasci() { 00506 if (a==0x0d) do_osnewline(); 00507 else printchar(a); 00508 } 00509 00510 void do_mainvdu() { 00511 printchar(a); 00512 } 00513 00514 void do_gsinit() { 00515 printf("GSINIT called with PC=%04x A=%02x\n\r",pc,a); 00516 } 00517 00518 void do_gsread() { 00519 } 00520 00521 void do_osrdrm() { 00522 printf("OSRDRM called with PC=%04x A=%02x H=%02x L=%02x\n\r",pc,a,h,l); 00523 } 00524 00525 void do_oseven() { 00526 printf("OSEVEN called with PC=%04x A=%02x H=%02x L=%02x\n\r",pc,a,h,l); 00527 } 00528 00529 void do_oscli() { 00530 printf("OSCLI called with PC=%04x A=%02x H=%02x L=%02x\n\r",pc,a,h,l); 00531 do { 00532 a=rdmem((h<<8)+l); 00533 if (!++l)h++; 00534 putchar(a); 00535 } while (a!=0x0d); 00536 } 00537 00538 void do_osfile() { 00539 char buffer[200]; 00540 int n=0; 00541 FILE *fp; 00542 // get address of control block 00543 int controlblock=hl; 00544 int offset=rdmem(controlblock)+(rdmem(controlblock+1)<<8); 00545 // create a kludgy pointer from this offset to the filename 00546 char *filename=(char *)(ram+offset-RAMSTART); 00547 long load_address=rdmem(controlblock+2)+(rdmem(controlblock+3)<<8)+(rdmem(controlblock+4)<<16)+(rdmem(controlblock+5)<<24); 00548 long execution_address=rdmem(controlblock+6)+(rdmem(controlblock+7)<<8)+(rdmem(controlblock+8)<<16)+(rdmem(controlblock+9)<<24); 00549 long start_or_length=rdmem(controlblock+10)+(rdmem(controlblock+11)<<8)+(rdmem(controlblock+12)<<16)+(rdmem(controlblock+13)<<24); 00550 long end_address_or_attributes=rdmem(controlblock+14)+(rdmem(controlblock+15)<<8)+(rdmem(controlblock+16)<<16)+(rdmem(controlblock+17)<<24); 00551 00552 00553 // printf("OSFILE called with PC=%04x A=%02x H=%02x L=%02x\n\r",pc,a,h,l); 00554 00555 // for (n=0; n<=0x11; n++) printf("offset %02x value %02x\n\r",n,rdmem(controlblock+n)); 00556 00557 n=0; 00558 while (filename[n]!=0x0d) n++; 00559 // overwrite 0x0d with end of string 00560 filename[n]=0x00; 00561 00562 // now determine what to do 00563 switch (a) { 00564 case 0x00: // save a section of memory as a named file 00565 sprintf(buffer,"/local/%s",filename); 00566 // 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); 00567 fp=fopen(buffer, "w"); 00568 if (fp) { 00569 n=start_or_length; 00570 while (n!=end_address_or_attributes) fputc(rdmem(n++),fp); 00571 fclose(fp); 00572 a=1; 00573 } else { 00574 // printf("could not write %s\n\r",buffer); 00575 a=0; 00576 pc=rdmem(0xfffa)+(rdmem(0xfffb)<<8); // do BRK 00577 } 00578 break; 00579 case 0x01: // write the catalogue information (only) for the named file (disc only) 00580 break; 00581 case 0x02: // write the load address (only) for the named file (disc only) 00582 break; 00583 case 0x03: // write the execution address (only) for the named file (disc only) 00584 break; 00585 case 0x04: // write the attributes (only) for the named file (disc only) 00586 break; 00587 case 0x05: // read the named file's catalogue information, place file type in A (disc only) 00588 break; 00589 case 0x06: // delete the named file (disc only) 00590 break; 00591 case 0xff: // load the named file and read the named file's catalogue information 00592 sprintf(buffer,"/local/%s",filename); 00593 // 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); 00594 fp = fopen(buffer, "r"); 00595 if (fp) { 00596 n=load_address; 00597 while (!feof(fp)) wrmem(n++,fgetc(fp)); 00598 fclose(fp); 00599 a=1; // file found 00600 } else { 00601 // printf("Could not open %s\n",buffer); 00602 a=0; 00603 pc=rdmem(0xfffa)+(rdmem(0xfffb)<<8); // do BRK 00604 } 00605 break; 00606 } 00607 } 00608 00609 void terminalgets(char *buffer) { 00610 int n=0; 00611 int key=0; 00612 do { 00613 key=getchar(); 00614 buffer[n]=key; 00615 putchar(key); 00616 if (n<16) n++; 00617 } while (key != 0x0d); 00618 buffer[n]=0; 00619 } 00620 00621 00622 // here the OS calls are recognized and 00623 // diverted to the mbed routines. 00624 // this needs to be replaced by native Z80 code 00625 void do_mos() { 00626 // printf("Entering MOS emulation with PC %04x\n\r",pc); 00627 00628 // compensate pc for length of ED55 opcode 00629 switch (pc-2) { 00630 case OSBYTE: 00631 do_osbyte(); 00632 break; 00633 case OSWORD: 00634 do_osword(); 00635 break; 00636 case OSWRCH: 00637 printchar(a); 00638 break; 00639 case OSRDCH: 00640 do_osreadchar(); 00641 break; 00642 case OSNEWL: 00643 do_osnewline(); 00644 break; 00645 case OSASCI: 00646 do_osasci(); 00647 break; 00648 case MAINVDU: 00649 do_mainvdu(); 00650 break; 00651 case GSINIT: 00652 do_gsinit(); 00653 break; 00654 case GSREAD: 00655 do_gsread(); 00656 break; 00657 case OSRDRM: 00658 do_osrdrm(); 00659 break; 00660 case OSEVEN: 00661 do_oseven(); 00662 break; 00663 case OSCLI: 00664 do_oscli(); 00665 break; 00666 case OSFILE: 00667 do_osfile(); 00668 break; 00669 } 00670 } 00671 00672 void listdir(void) { 00673 DIR *d; 00674 struct dirent *p; 00675 00676 d = opendir("/sd"); 00677 if (d != NULL) { 00678 while ((p = readdir(d)) != NULL) { 00679 printf(" - %s\r\n", p->d_name); 00680 } 00681 } else { 00682 printf("Could not open directory!\n"); 00683 } 00684 closedir(d); 00685 } 00686 00687 00688 00689 00690 00691 // ================================================================ 00692 // main loop 00693 // ================================================================ 00694 int main() { 00695 00696 // serial port on at 115200 baud 00697 linktopc.baud(115200); 00698 setbuf(stdout, NULL); // no buffering for this filehandle 00699 00700 // reset all Z80 registers to some initial values 00701 a=f=b=c=d=e=h=l=a1=f1=b1=c1=d1=e1=h1=l1=i=iff1=iff2=im=r=0; 00702 ixoriy=new_ixoriy=0; 00703 ix=iy=sp=pc=0; 00704 00705 queue_bytes=0; 00706 00707 // init MOS vectors 00708 init_ramtop(); 00709 00710 init_screen(); 00711 home_cursor(); 00712 00713 // endless loop 00714 while (1) { 00715 // wait(0.01); 00716 r++; 00717 // this is some optimization for the IX and IY opcodes (DD/FD) 00718 ixoriy=new_ixoriy; 00719 new_ixoriy=0; 00720 00721 // fetch opcode and execute, the include does all the heavy decoding 00722 switch (fetch(pc++)) { 00723 #include "z80ops.h" 00724 } 00725 00726 // next is the interrupt emulator (only IM1 mode) 00727 // interrupt pending? if new_ixoriy is set or iff1==0 don't do interrupt yet (continue DD/FD opcode) 00728 // if (intpend && !new_ixoriy && iff1) { 00729 // are we HALT-ed ? then resume 00730 // if (fetch(pc)==0x76) pc++; 00731 00732 // block further interrupts for now 00733 // iff1=0; 00734 00735 // do the call to 00x38 00736 // push2(pc); // save old pc 00737 // pc=0x0038; // setup new pc 00738 // intpend=0; // release interrupt pending flag; 00739 // } // if intpend 00740 } // while 00741 }
Generated on Wed Jul 13 2022 16:07:28 by 1.7.2